Skip to content

Java 应用 Kubernetes 资源配置详细方案

1. JVM 参数与容器内存配置

1.1 基础配置原则

yaml
# Kubernetes Deployment 配置
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: java-app
  template:
    metadata:
      labels:
        app: java-app
    spec:
      containers:
      - name: java-app
        image: openjdk:11-jre-slim
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 2000m
            memory: 2Gi
        env:
        - name: JAVA_OPTS
          value: >-
            -Xms512m 
            -Xmx1536m 
            -XX:MaxMetaspaceSize=256m 
            -XX:MaxDirectMemorySize=128m
            -XX:+UseContainerSupport
            -XX:MaxRAMPercentage=75.0
        - name: JVM_OPTS
          value: >-
            -XX:+UseG1GC 
            -XX:+UseStringDeduplication
            -XX:+PrintGCDetails
            -XX:+PrintGCTimeStamps
            -Xloggc:/var/log/gc.log

1.2 内存分配详细说明

bash
# 容器内存限制: 2Gi (2048Mi)
# 内存分配策略:
# - Heap Memory (-Xmx): 1536Mi (75%)
# - Metaspace: 256Mi (12.5%)
# - Direct Memory: 128Mi (6.25%)
# - 其他开销: 128Mi (6.25%) - GC、线程栈、JIT编译等

# 计算公式:
# Container Memory = Heap + Metaspace + Direct Memory + OS Cache + Other Overhead
# 2048Mi = 1536Mi + 256Mi + 128Mi + 128Mi

2. 不同规模应用的配置模板

2.1 小型 Spring Boot 应用

yaml
# 适用于: 微服务、简单 Web 应用
apiVersion: apps/v1
kind: Deployment
metadata:
  name: small-java-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-spring-boot-app:latest
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1Gi
        env:
        - name: JAVA_OPTS
          value: >-
            -Xms256m 
            -Xmx768m 
            -XX:MaxMetaspaceSize=128m
            -XX:MaxDirectMemorySize=64m
            -XX:+UseContainerSupport
            -XX:MaxRAMPercentage=75.0
        - name: SPRING_PROFILES_ACTIVE
          value: "production"
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 45
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 15

2.2 中型业务应用

yaml
# 适用于: 复杂业务逻辑、中等并发
apiVersion: apps/v1
kind: Deployment
metadata:
  name: medium-java-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-business-app:latest
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 2000m
            memory: 2Gi
        env:
        - name: JAVA_OPTS
          value: >-
            -Xms512m 
            -Xmx1536m 
            -XX:MaxMetaspaceSize=256m
            -XX:MaxDirectMemorySize=128m
            -XX:+UseContainerSupport
            -XX:+UseG1GC
            -XX:G1HeapRegionSize=16m
            -XX:G1MixedGCCountTarget=8
            -XX:InitiatingHeapOccupancyPercent=45
        - name: JVM_MONITORING
          value: >-
            -Dcom.sun.management.jmxremote
            -Dcom.sun.management.jmxremote.port=9999
            -Dcom.sun.management.jmxremote.authenticate=false
            -Dcom.sun.management.jmxremote.ssl=false
        ports:
        - containerPort: 8080
          name: http
        - containerPort: 9999
          name: jmx

2.3 大型高并发应用

yaml
# 适用于: 高并发、大数据处理
apiVersion: apps/v1
kind: Deployment
metadata:
  name: large-java-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-large-app:latest
        resources:
          requests:
            cpu: 1000m
            memory: 2Gi
          limits:
            cpu: 4000m
            memory: 4Gi
        env:
        - name: JAVA_OPTS
          value: >-
            -Xms1024m 
            -Xmx3072m 
            -XX:MaxMetaspaceSize=512m
            -XX:MaxDirectMemorySize=256m
            -XX:+UseContainerSupport
            -XX:+UseG1GC
            -XX:+UseStringDeduplication
            -XX:G1HeapRegionSize=32m
            -XX:MaxGCPauseMillis=200
            -XX:ParallelGCThreads=4
            -XX:ConcGCThreads=2
        - name: JVM_PERFORMANCE
          value: >-
            -XX:+UseLargePages
            -XX:+AlwaysPreTouch
            -XX:+DisableExplicitGC
            -XX:+OptimizeStringConcat

3. 容器感知配置详解

3.1 UseContainerSupport 详细说明

yaml
# 启用容器支持 (JDK 8u191+, JDK 11+)
env:
- name: JAVA_OPTS
  value: >-
    -XX:+UseContainerSupport
    -XX:MaxRAMPercentage=75.0
    -XX:InitialRAMPercentage=50.0
    -XX:MinRAMPercentage=25.0

# 或使用 JDK 11+ 的新参数
- name: JAVA_OPTS
  value: >-
    -XX:+UseContainerSupport
    -XX:MaxRAMPercentage=75.0
    -XX:ActiveProcessorCount=2

3.2 动态内存配置脚本

yaml
# 使用 init container 动态计算内存参数
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dynamic-java-app
spec:
  template:
    spec:
      initContainers:
      - name: memory-calculator
        image: busybox
        command:
        - sh
        - -c
        - |
          MEMORY_LIMIT=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
          MEMORY_GB=$((MEMORY_LIMIT / 1024 / 1024 / 1024))
          HEAP_SIZE=$((MEMORY_GB * 75 / 100))
          echo "-Xmx${HEAP_SIZE}g" > /shared/jvm-opts
        volumeMounts:
        - name: shared-data
          mountPath: /shared
      containers:
      - name: app
        image: my-app:latest
        command:
        - sh
        - -c
        - |
          JVM_OPTS=$(cat /shared/jvm-opts)
          java $JVM_OPTS -jar app.jar
        volumeMounts:
        - name: shared-data
          mountPath: /shared
      volumes:
      - name: shared-data
        emptyDir: {}

4. 监控和诊断配置

4.1 JVM 监控配置

yaml
# 添加 JVM 监控和调试功能
env:
- name: JAVA_OPTS
  value: >-
    -Xms512m 
    -Xmx1536m
    -XX:+UseContainerSupport
    -XX:+PrintGC
    -XX:+PrintGCDetails
    -XX:+PrintGCTimeStamps
    -XX:+PrintGCApplicationStoppedTime
    -XX:+PrintStringDeduplicationStatistics
    -Xloggc:/var/log/gc.log
    -XX:+UseGCLogFileRotation
    -XX:NumberOfGCLogFiles=5
    -XX:GCLogFileSize=10M
- name: JMX_OPTS
  value: >-
    -Dcom.sun.management.jmxremote
    -Dcom.sun.management.jmxremote.port=9999
    -Dcom.sun.management.jmxremote.authenticate=false
    -Dcom.sun.management.jmxremote.ssl=false
    -Djava.rmi.server.hostname=127.0.0.1

4.2 健康检查配置

yaml
# 配置合适的健康检查
readinessProbe:
  httpGet:
    path: /actuator/health
    port: 8080
  initialDelaySeconds: 60    # Java 应用启动时间较长
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

livenessProbe:
  httpGet:
    path: /actuator/health
    port: 8080
  initialDelaySeconds: 90    # 给足够时间让应用完全启动
  periodSeconds: 15
  timeoutSeconds: 10
  failureThreshold: 3

startupProbe:
  httpGet:
    path: /actuator/health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 5
  timeoutSeconds: 3
  failureThreshold: 20       # 最长等待 100 秒启动

5. 不同环境的配置差异

5.1 开发环境配置

yaml
# development 环境 - 便于调试
apiVersion: v1
kind: ConfigMap
metadata:
  name: java-app-dev-config
data:
  JAVA_OPTS: >-
    -Xms256m 
    -Xmx1024m
    -XX:+UseContainerSupport
    -XX:MaxRAMPercentage=80.0
    -XX:+PrintGCDetails
    -Xdebug
    -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005
    -Dspring.profiles.active=dev
    -Dlogging.level.root=DEBUG

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-app-dev
spec:
  template:
    spec:
      containers:
      - name: app
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
          limits:
            cpu: 2000m    # 开发环境给予更多 CPU 资源
            memory: 2Gi
        envFrom:
        - configMapRef:
            name: java-app-dev-config
        ports:
        - containerPort: 5005
          name: debug

5.2 生产环境配置

yaml
# production 环境 - 性能优化
apiVersion: v1
kind: ConfigMap
metadata:
  name: java-app-prod-config
data:
  JAVA_OPTS: >-
    -Xms1024m 
    -Xmx1536m
    -XX:MaxMetaspaceSize=256m
    -XX:MaxDirectMemorySize=128m
    -XX:+UseContainerSupport
    -XX:MaxRAMPercentage=75.0
    -XX:+UseG1GC
    -XX:+UseStringDeduplication
    -XX:+AlwaysPreTouch
    -XX:+DisableExplicitGC
    -XX:MaxGCPauseMillis=200
    -XX:+PrintGC
    -XX:+PrintGCTimeStamps
    -Xloggc:/var/log/gc.log
    -XX:+UseGCLogFileRotation
    -XX:NumberOfGCLogFiles=5
    -XX:GCLogFileSize=10M
    -Dspring.profiles.active=prod

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: java-app-prod
spec:
  template:
    spec:
      containers:
      - name: app
        resources:
          requests:
            cpu: 800m      # 基于监控数据的精确配置
            memory: 1536Mi
          limits:
            cpu: 2000m
            memory: 2Gi
        envFrom:
        - configMapRef:
            name: java-app-prod-config

6. 故障排查和优化脚本

6.1 内存使用情况检查脚本

bash
#!/bin/bash
# 检查 Java 应用内存使用情况

POD_NAME=$1
NAMESPACE=${2:-default}

echo "=== 检查 Pod 资源配置 ==="
kubectl get pod $POD_NAME -n $NAMESPACE -o yaml | grep -A 10 resources:

echo "=== 检查实际资源使用 ==="
kubectl top pod $POD_NAME -n $NAMESPACE

echo "=== 检查 JVM 内存使用 ==="
kubectl exec -n $NAMESPACE $POD_NAME -- jstat -gc 1 | head -2

echo "=== 检查 GC 日志 ==="
kubectl exec -n $NAMESPACE $POD_NAME -- tail -20 /var/log/gc.log

6.2 自动调优建议脚本

bash
#!/bin/bash
# 基于监控数据提供调优建议

POD_NAME=$1
NAMESPACE=${2:-default}

# 获取容器内存限制
MEMORY_LIMIT=$(kubectl get pod $POD_NAME -n $NAMESPACE -o jsonpath='{.spec.containers[0].resources.limits.memory}')

# 获取实际内存使用
MEMORY_USAGE=$(kubectl top pod $POD_NAME -n $NAMESPACE --no-headers | awk '{print $3}')

echo "当前内存限制: $MEMORY_LIMIT"
echo "实际内存使用: $MEMORY_USAGE"

# 提供优化建议
if [[ "$MEMORY_USAGE" =~ ([0-9]+)Mi ]]; then
    USAGE_MI=${BASH_REMATCH[1]}
    RECOMMENDED_HEAP=$((USAGE_MI * 75 / 100))
    
    echo "建议 JVM 配置:"
    echo "  -Xmx${RECOMMENDED_HEAP}m"
    echo "  -XX:MaxMetaspaceSize=$((USAGE_MI * 15 / 100))m"
    echo "  -XX:MaxDirectMemorySize=$((USAGE_MI * 10 / 100))m"
fi

7. 最佳实践总结

7.1 配置检查清单

  • [ ] 设置了 -Xmx 参数,且不超过容器内存限制的 75%
  • [ ] 启用了 -XX:+UseContainerSupport
  • [ ] 配置了 MaxMetaspaceSizeMaxDirectMemorySize
  • [ ] 设置了合适的 GC 算法(推荐 G1GC)
  • [ ] 配置了 GC 日志输出
  • [ ] 设置了合适的健康检查时间
  • [ ] 配置了 JMX 监控(生产环境)

7.2 常见问题避免

  • 避免让 JVM 使用容器全部内存
  • 避免在生产环境开启调试模式
  • 避免使用过小的 Metaspace 限制
  • 避免忽略 Direct Memory 的配置
  • 避免使用默认的 GC 算法(对于大堆内存)

通过以上配置方案,可以确保 Java 应用在 Kubernetes 环境中稳定高效运行。

核心要点说明:

1. 内存配置原则

  • 容器内存限制的 75% 用于 JVM 堆内存
  • 预留 25% 给 Metaspace、Direct Memory 和其他开销
  • 使用 -XX:+UseContainerSupport 让 JVM 感知容器限制

2. 不同规模应用的差异化配置

  • 小型应用:512Mi-1Gi 内存,适合微服务
  • 中型应用:1-2Gi 内存,适合复杂业务逻辑
  • 大型应用:2-4Gi 内存,适合高并发场景

3. 关键 JVM 参数

bash
-XX:+UseContainerSupport      # 容器感知
-XX:MaxRAMPercentage=75.0     # 最大内存使用比例
-XX:+UseG1GC                  # 推荐的 GC 算法
-XX:MaxMetaspaceSize=256m     # 元空间限制
-XX:MaxDirectMemorySize=128m  # 直接内存限制

4. 监控和诊断

  • 配置 GC 日志输出和轮转
  • 启用 JMX 监控
  • 设置合适的健康检查时间

5. 环境差异化

  • 开发环境:更宽松的资源限制,启用调试
  • 生产环境:精确的资源配置,性能优化

这个方案可以帮助您避免常见的 Java 应用在 Kubernetes 中的内存溢出、启动缓慢等问题,确保应用稳定运行。