Java 应用上 K8s 全指南:从部署到治理的生产级实践
在云原生时代,Kubernetes(简称 K8s)已成为 Java 应用容器化部署的事实标准。但很多团队在实践中会陷入一个误区:"镜像能构建、Pod 能启动、服务能访问",就认为完成了生产级部署。
殊不知,生产环境的稳定性、可运维性、安全性,往往藏在那些被忽略的细节里。无数案例证明,Java 应用上 K8s 不是"一次性部署",而是"体系化治理"------从镜像构建到资源配置,从健康检查到故障兜底,每一步都需要符合生产级标准,才能避免上线后疲于救火。
一、基础架构层:镜像与运行时优化
多阶段构建 + 轻量级基础镜像
传统单阶段构建的 Java 镜像常超 500MB,而多阶段构建可压缩至 100MB 以内,显著降低拉取时间和存储成本。
生产配置:
bash
# 构建阶段
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
RUN ./mvnw clean package -DskipTests
# 运行阶段
FROM eclipse-temurin:21-jre-alpine
RUN apk add --no-cache tzdata && \
addgroup -S appgroup && adduser -S appuser -G appgroup
ENV TZ=Asia/Shanghai
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
避坑指南:
- 避免使用
openjdk:latest标签,锁定具体版本号 - Alpine 镜像需测试 musl libc 兼容性(部分 JNI 库可能异常)
JVM 容器感知参数调优
Java 8u131 之前版本无法识别 cgroup 限制,极易导致 OOM Killed。即使现代 JDK 已支持容器感知,仍需显式优化。
JVM 参数:
bash
-XX:+UseContainerSupport # 启用容器感知(JDK10+默认开启,通常可以删除) :contentReference[oaicite:0]{index=0}
-XX:MaxRAMPercentage=75.0 # 最大堆内存 = 容器内存的75%(Xmx替代) :contentReference[oaicite:1]{index=1}
-XX:InitialRAMPercentage=50.0 # 初始堆 = 50%(Xms替代) :contentReference[oaicite:3]{index=3}
-XX:MinRAMPercentage=25.0 # 小内存(<250MB)时才影响最大堆(几乎无用) :contentReference[oaicite:5]{index=5}
-XX:+UseG1GC # 使用G1垃圾回收器(低停顿,默认GC) 建议:✅ 保留(Java 11+ 默认,但写上更明确)
-XX:MaxGCPauseMillis=200 # 目标GC停顿时间200ms(软目标)
-XX:+UseStringDeduplication # G1字符串去重(减少重复字符串占用)建议:✅ 保留(JSON/日志-heavy系统收益明显)
推荐配置
bash
# 内存(容器自适应)
-XX:MaxRAMPercentage=70
-XX:InitialRAMPercentage=25
# GC
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
# 字符串优化
-XX:+UseStringDeduplication
# 稳定性
-XX:+DisableExplicitGC
# 容器CPU控制
-XX:ActiveProcessorCount=2
# OOM诊断
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/tmp
# GC日志
-Xlog:gc*:file=/tmp/gc.log:time,level,tags
非 Root 用户 + 安全上下文
生产配置:
yaml
securityContext:
runAsNonRoot: true # 禁止root运行
runAsUser: 1000 # 指定用户
runAsGroup: 1000 # 指定组
fsGroup: 1000 # 卷权限控制
allowPrivilegeEscalation: false # 禁止提权
readOnlyRootFilesystem: true # 根文件系统只读
privileged: false # 禁止特权模式
seccompProfile:
type: RuntimeDefault # 系统调用限制(强烈推荐)
capabilities:
drop:
- ALL # 最小权限原则
进阶加固:
- 使用 Distroless 或 Chainguard 镜像进一步减少攻击面
- 在 CI/CD 中集成 Trivy/Snyk 扫描,阻断高危漏洞镜像
二、资源管理层:调度与弹性
精细化资源请求与限制
Requests 决定调度,Limits 决定上限。生产环境务必设置两者,避免 "Noisy Neighbor" 问题。
配置示例:
yaml
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
QoS 策略:
- Guaranteed :关键服务设置
requests = limits,确保最高优先级 - Burstable:普通服务,允许临时突增
- BestEffort:仅用于开发/测试环境,生产禁用
HPA + VPA + Cluster Autoscaler 协同
三维弹性架构:
- HPA(横向):基于 CPU/内存/自定义指标(如 QPS、队列深度)扩缩 Pod
- VPA(纵向):调整 Pod 资源配置(建议仅用于 Recommender 模式,避免与 HPA 冲突)
- Cluster Autoscaler:节点级弹性,应对资源不足
HPA 生产配置:
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: java-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: java-app
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Pods # 自定义指标
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: "1000"
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 缩容冷却期,防止抖动
policies:
- type: Percent
value: 10
periodSeconds: 60
Pod 拓扑分布约束(高可用)
生产环境必须跨可用区(AZ)分布,避免单点故障。
yaml
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: java-app
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
三、生命周期管理:健康检查与优雅停机
探针分工:
- Startup Probe:保护慢启动应用(如 JVM 冷启动),成功后才启用其他探针
- Readiness Probe:决定流量是否打入,建议检查依赖服务(DB、Redis)
- Liveness Probe :故障自愈,严禁与 Readiness 共用端点
yaml
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 30 # 10 + 5*30 = 160s 启动时间
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
优雅停机(Graceful Shutdown)
Java 侧配置(Spring Boot):
yaml
server:
shutdown: graceful
spring:
lifecycle:
timeout-per-shutdown-phase: 30s
K8s 侧配置:
yaml
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 15"] # 等待负载均衡器移除 Endpoint
terminationGracePeriodSeconds: 60 # 必须大于 preStop + 应用停机时间
关键逻辑 :preStop → 停止接收新流量 → 处理完存量请求 → 退出
四、可观测性体系:监控、日志、追踪
Metrics 暴露与采集(Prometheus)
Micrometer + Prometheus 配置:
yaml
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
endpoint:
health:
show-details: always
probes:
enabled: true
prometheus:
enabled: true
metrics:
tags:
application: ${spring.application.name}
cluster: production
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 50ms,100ms,200ms,500ms,1s,5s
ServiceMonitor 配置:
yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: java-app-metrics
spec:
selector:
matchLabels:
app: java-app
endpoints:
- port: metrics
path: /actuator/prometheus
interval: 15s
scrapeTimeout: 10s
结构化日志与采集(EFK/Loki)
日志规范:
- 统一 JSON 格式输出
- 包含
trace_id、span_id用于链路追踪关联 - 敏感信息脱敏
Logback 配置示例:
xml
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeContext>true</includeContext>
<includeMdc>true</includeMdc>
<customFields>{"service":"${SERVICE_NAME}","cluster":"production"}</customFields>
</encoder>
</appender>
采集策略:DaemonSet 模式 Filebeat / Fluent Bit 采集 stdout,避免写本地文件
分布式追踪(OpenTelemetry)
全链路追踪架构:
- 接入 OpenTelemetry Agent(Java Agent 自动埋点)
- 支持 Trace → Metrics → Logs 关联
- 采样策略:生产环境建议 1-10% 概率采样,错误 100% 采样
五、配置与密钥管理
配置外化与热更新
分层配置策略:
- ConfigMap:非敏感配置(日志级别、线程池大小)
- Secret:敏感信息(密码、证书),使用 Sealed Secret 或 External Secrets Operator 加密
- 配置中心:Nacos、Apollo 或 Spring Cloud Config 实现动态刷新
环境变量注入:
yaml
env:
- name: SPRING_PROFILES_ACTIVE
value: "production"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
ConfigMap/Secret 变更自动重启
解决方案:
- 使用 Reloader/Stakater 控制器监听配置变更,自动滚动更新 Deployment
- 或应用层实现配置热刷新(Spring Cloud Kubernetes 的
@RefreshScope)
六、网络与流量治理
Service 与 Ingress 最佳实践
Service 类型选择:
- ClusterIP:内部微服务通信
- Headless Service:StatefulSet 场景(如 Kafka、Redis Cluster)
- ExternalName:外部服务代理
Ingress 生产配置:
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "10m"
nginx.ingress.kubernetes.io/rate-limit: "100"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: java-app
port:
number: 8080
服务网格(Service Mesh)接入
Istio/Linkerd 核心能力:
- mTLS 自动加密东西向流量
- 智能路由(金丝雀、蓝绿、A/B 测试)
- 熔断、重试、超时控制
- 全链路可观测性
熔断配置示例(Istio):
yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: java-app-circuit-breaker
spec:
host: java-app
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
maxRequestsPerConnection: 10
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
七、安全与合规
Pod Security Standards(PSS)
强制 Baseline/Restricted 级别:
yaml
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Network Policy 微隔离
零信任网络:默认拒绝所有流量,显式放行必要通信。
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: java-app-netpol
spec:
podSelector:
matchLabels:
app: java-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
镜像签名与供应链安全
关键措施:
- 使用 Cosign 签名镜像,验证后方可部署
- 启用 Kubernetes 镜像策略Webhook(ImagePolicyWebhook)
- 私有镜像仓库 + ImagePullSecret 管理
八、CI/CD 与 GitOps
GitOps 工作流(Argo CD/Flux)
核心原则:
- Git 为唯一可信源(Single Source of Truth)
- 自动同步与漂移检测
- 渐进式交付(Argo Rollouts 实现金丝雀/蓝绿发布)
目录结构建议:
k8s/
├── base/ # 基础资源
│ ├── deployment.yaml
│ ├── service.yaml
│ └── kustomization.yaml
├── overlays/
│ ├── development/ # 开发环境补丁
│ ├── staging/ # 预发环境补丁
│ └── production/ # 生产环境补丁(副本数、资源限制不同)
└── charts/ # Helm Chart(如使用 Helm)
混沌工程与容灾演练
故障注入场景:
- Pod 级:随机删除 Pod 测试自愈能力
- 网络级:模拟延迟、丢包、分区
- 节点级:宕机、磁盘压力、CPU 满载
工具链:Chaos Mesh、LitmusChaos、AWS Fault Injection Simulator
总结:生产级 Checklist 速查表
| 维度 | 关键检查项 | 风险等级 |
|---|---|---|
| 镜像 | 多阶段构建、非 Root、漏洞扫描 | 🔴 高 |
| 资源 | Requests/Limits、HPA、QoS | 🔴 高 |
| 健康 | 三类探针、优雅停机、拓扑分布 | 🔴 高 |
| 可观测 | Metrics、Logs、Traces 三支柱 | 🟡 中 |
| 安全 | PSS、NetworkPolicy、镜像签名 | 🔴 高 |
| 交付 | GitOps、灰度发布、混沌工程 | 🟡 中 |