上一篇文章我们详细拆解了 Spring Boot 3.4 Docker 镜像的分层构建技巧,把镜像从 200MB 优化到了 80MB。但容器化只是第一步——如何让应用在 Kubernetes 集群中稳定运行?如何配置探针让 K8s 帮你自动恢复故障?如何在流量洪峰时自动扩容、低谷时自动缩容? 本文从零开始,将同一个 Spring Boot 应用从 Docker 镜像演进到生产级 K8s 部署,涵盖 Deployment 编排、Liveness/Readiness 探针、ConfigMap/Secret 管理、HPA 自动伸缩、滚动更新与回滚,以及基于 Prometheus 指标的 KEDA 事件驱动伸缩。
一、为什么需要 Kubernetes?
Docker 解决了“一次构建,到处运行”的问题,但生产环境还需要解决更多问题:
| 能力 | Docker 单机 | Kubernetes 集群 |
|---|---|---|
| 容器调度 | 手动 docker run | 自动调度到最优节点 |
| 故障恢复 | 容器挂了就挂了 | 自动重启 + 自愈 |
| 负载均衡 | 需额外配置反向代理 | 内置 Service + Ingress |
| 弹性伸缩 | 手动改端口映射 | HPA/KEDA 自动伸缩 |
| 滚动更新 | 手动逐个替换 | 零停机滚动更新 + 一键回滚 |
Kubernetes 的核心价值在于将基础设施能力代码化——通过 YAML 声明期望状态,由 K8s 控制器负责将实际状态收敛到期望状态。
本文将从 Spring Boot 分层镜像出发,逐步构建完整的 K8s 部署体系。建议先阅读本站的 《Spring Boot 3.4 Docker 镜像最佳实践(含分层构建)》 作为前置准备。
二、从镜像到 Deployment:在 K8s 中运行 Spring Boot
2.1 前置条件
- Kubernetes 集群(本地可用 Minikube 或 Kind,生产推荐云厂商托管集群)
kubectl已配置好集群访问- 已构建好的 Spring Boot 镜像(推送到镜像仓库,如 Docker Hub、ACR、ECR 等)
2.2 编写 Deployment YAML
Deployment 是 K8s 中最核心的工作负载控制器,管理 Pod 的副本数、更新策略和生命周期。
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: production
labels:
app: order-service
version: v1
spec:
replicas: 3
selector:
matchLabels:
app: order-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 更新时最多超出期望副本数 1 个
maxUnavailable: 0 # 更新期间不允许 Pod 不可用(零停机)
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: your-registry/order-service:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
# 资源限制(HPA 依赖此项)
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
# === 探针配置(生产环境必备)===
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
failureThreshold: 3
# === 环境变量 ===
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: JAVA_OPTS
value: "-Xms512m -Xmx768m"
2.3 探针配置详解
Liveness Probe(存活探针) :检测容器是否“活着”。如果探针失败,K8s 会重启容器。
Readiness Probe(就绪探针) :检测容器是否“准备好接收流量”。如果探针失败,K8s 会从 Service 的负载均衡中摘除该 Pod。
Spring Boot Actuator 提供了两组专用端点:
# application-prod.yml
management:
endpoint:
health:
show-details: always
probes:
enabled: true # 启用 /actuator/health/liveness 和 /actuator/health/readiness
health:
livenessstate:
enabled: true
readinessstate:
enabled: true
为什么不能只用同一个 /actuator/health ?
| 端点 | 失败后果 | 包含检查项 |
|---|---|---|
/actuator/health/liveness | 重启 Pod | 仅 JVM 是否存活、OutOfMemory 等致命问题 |
/actuator/health/readiness | 摘除流量 | 数据库连接、消息队列、下游依赖是否就绪 |
如果 /actuator/health 因数据库暂时不可用而失败,Liveness Probe 会直接重启 Pod,可能让问题更糟。正确做法是:Liveness 只检查“是否还活着”,Readiness 检查“是否能干活” 。
2.4 资源限制(Requests & Limits)
resources:
requests: # 调度依据:K8s 保证至少分配这么多资源
memory: "512Mi"
cpu: "500m"
limits: # 运行时上限:Pod 不能超过这个值
memory: "1Gi"
cpu: "1000m"
核心原则:requests 是调度器决策的依据,limits 是运行时 Cgroups 的硬上限。建议 requests 设为 limits 的 50%-70%,既保证资源预留,又提高节点利用率。
三、Service:暴露服务与负载均衡
apiVersion: v1
kind: Service
metadata:
name: order-service
namespace: production
spec:
selector:
app: order-service
ports:
- port: 8080
targetPort: 8080
name: http
type: ClusterIP # 集群内部访问,外部通过 Ingress 暴露
部署命令:
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
# 查看部署状态
kubectl get pods -n production
kubectl get deployment -n production
kubectl get svc -n production
四、配置管理:ConfigMap 与 Secret
环境相关的配置不应硬编码在镜像中,而应通过 K8s 的 ConfigMap 和 Secret 注入。
4.1 ConfigMap(非敏感配置)
apiVersion: v1
kind: ConfigMap
metadata:
name: order-service-config
namespace: production
data:
application.yml: |
spring:
datasource:
url: jdbc:mysql://mysql-service:3306/order_db
hikari:
maximum-pool-size: 10
logging:
level:
com.example: INFO
挂载到 Pod 中:
spec:
containers:
- name: order-service
volumeMounts:
- name: config
mountPath: /config
volumes:
- name: config
configMap:
name: order-service-config
启动时通过 --spring.config.additional-location=/config/ 加载外部配置。
4.2 Secret(敏感配置,Base64 编码)
apiVersion: v1
kind: Secret
metadata:
name: order-service-secret
namespace: production
type: Opaque
data:
db-password: <base64-encoded-password>
api-key: <base64-encoded-api-key>
在 Deployment 中引用:
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: order-service-secret
key: db-password
⚠️ 重要:Secret 的 Base64 编码不是加密。生产环境应配合外部密钥管理服务(如 HashiCorp Vault、云厂商 KMS)使用。
五、滚动更新与回滚
5.1 触发滚动更新
更新镜像版本:
kubectl set image deployment/order-service order-service=your-registry/order-service:2.0.0 -n production
或修改 YAML 后重新 apply:
kubectl apply -f deployment.yaml
5.2 滚动更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 更新时最多超出期望副本数 1 个
maxUnavailable: 0 # 不允许有 Pod 不可用(保证零停机)
默认行为:maxSurge=25%,maxUnavailable=25%。对于生产环境的关键服务,建议 maxUnavailable: 0 + maxSurge: 1 确保零停机。
5.3 查看与回滚
# 查看滚动更新历史
kubectl rollout history deployment/order-service -n production
# 查看特定版本详情
kubectl rollout history deployment/order-service --revision=3 -n production
# 回滚到上一个版本
kubectl rollout undo deployment/order-service -n production
# 回滚到指定版本
kubectl rollout undo deployment/order-service --to-revision=2 -n production
# 暂停/恢复更新(用于金丝雀发布)
kubectl rollout pause deployment/order-service -n production
kubectl rollout resume deployment/order-service -n production
六、HPA 自动伸缩:基于 CPU/内存
Horizontal Pod Autoscaler(HPA)根据资源利用率自动调整 Pod 副本数。
6.1 前置条件:安装 Metrics Server
HPA 依赖 Metrics Server 提供 Pod 的资源指标:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
6.2 创建 HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-service-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 缩容冷静期 5 分钟
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0 # 扩容无延迟
policies:
- type: Percent
value: 100
periodSeconds: 60
- type: Pods
value: 4
periodSeconds: 60
selectPolicy: Max
关键参数解读:
| 参数 | 含义 | 推荐值 |
|---|---|---|
averageUtilization: 70 | CPU 平均使用率超过 70% 时扩容 | 60%-80% |
scaleDown.stabilizationWindowSeconds | 缩容前的观察窗口,防止抖动 | 300s(5分钟) |
scaleUp.stabilizationWindowSeconds | 扩容观察窗口,建议 0 快速响应 | 0 |
6.3 部署与验证
kubectl apply -f hpa.yaml
# 查看 HPA 状态
kubectl get hpa -n production
# 实时监控伸缩
kubectl get hpa order-service-hpa -n production --watch
⚠️ 常见陷阱:如果 Pod 没有设置 resources.requests,HPA 无法计算利用率,将无法工作。
七、KEDA:事件驱动的自动伸缩
HPA 只能基于 CPU/内存等基础指标,对于消息队列积压、自定义业务指标等场景无能为力。KEDA(Kubernetes Event-Driven Autoscaling)填补了这个空白。
7.1 KEDA vs HPA
| 维度 | HPA | KEDA |
|---|---|---|
| 指标来源 | CPU / Memory(Metrics Server) | Prometheus、Kafka、RabbitMQ、Redis 等 50+ 数据源 |
| 缩容到零 | ❌ 不支持 | ✅ 支持(Serverless 场景) |
| 伸缩粒度 | 基于平均值 | 基于具体事件数量(如队列深度、每秒请求数) |
| 适用场景 | 通用负载均衡 | 事件驱动型应用(消息消费、批处理任务) |
7.2 安装 KEDA
# Helm 安装
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm install keda kedacore/keda --namespace keda --create-namespace
7.3 基于 Prometheus 指标自动伸缩
延续本站 《Java 应用接入 Prometheus + Grafana 全记录》 的监控体系,我们可以让 KEDA 直接读取 Prometheus 中的业务指标进行伸缩。
Step 1:在 Spring Boot 中暴露自定义指标
@RestController
public class OrderMetricsController {
private final Counter orderCounter = Counter.builder("orders_total")
.description("Total number of orders")
.register(Metrics.globalRegistry);
private final Gauge pendingOrdersGauge = Gauge.builder("orders_pending",
() -> pendingOrderService.count()).register(Metrics.globalRegistry);
@PostMapping("/order")
public Order createOrder(@RequestBody OrderRequest request) {
orderCounter.increment();
// 业务逻辑...
}
}
Step 2:创建 KEDA ScaledObject
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-service-scaler
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-service
minReplicaCount: 1
maxReplicaCount: 20
fallback: # Prometheus 不可用时的保底策略
failureThreshold: 3
replicas: 3
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
metricName: orders_pending
threshold: "100" # 待处理订单超过 100 时扩容
query: |
sum(orders_pending{namespace="production"})
activationThreshold: "10" # 低于 10 时缩容
- type: prometheus
metadata:
serverAddress: http://prometheus.monitoring:9090
metricName: orders_per_second
threshold: "50"
query: |
rate(orders_total{namespace="production"}[1m])
Step 3:部署验证
kubectl apply -f scaledobject.yaml
# 查看 KEDA 伸缩状态
kubectl get scaledobject -n production
kubectl describe scaledobject order-service-scaler -n production
7.4 KEDA 适用场景
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 消息队列消费者(Kafka/RabbitMQ) | KEDA | 根据队列深度精准伸缩 |
| 批处理任务(按需启动) | KEDA + Job | 有任务时启动 Pod,完成后缩容到 0 |
| HTTP 服务(基于 QPS) | KEDA HTTP Add-on | 基于 HTTP 流量伸缩 |
| 通用 Web 服务(CPU/内存) | HPA | 简单直接,无需额外组件 |
八、完整架构总览

九、生产环境最佳实践清单
- 资源限制:所有 Pod 必须设置
requests和limits - 探针分离:Liveness 和 Readiness 使用不同端点,配置合理的
initialDelaySeconds - 滚动更新:生产环境设置
maxUnavailable: 0保证零停机 - 配置外置:使用 ConfigMap 和 Secret 管理配置,避免环境差异
- HPA 必备:所有生产 Deployment 都应配置 HPA,
minReplicas至少 2 保证高可用 - 监控联动:将 KEDA 与 Prometheus + Grafana 结合,实现指标驱动的精准伸缩
- 回滚预案:熟悉
kubectl rollout undo命令,故障时快速回滚 - 镜像拉取策略:生产环境使用
imagePullPolicy: IfNotPresent,避免每次都拉取
十、总结
从 Docker 到 Kubernetes 的演进路径清晰:
- 第一阶段:用 Docker 将应用容器化,通过分层构建优化镜像体积
- 第二阶段:编写 Deployment + Service YAML,将应用部署到 K8s 集群
- 第三阶段:配置 Liveness/Readiness 探针,让 K8s 具备自愈能力
- 第四阶段:接入 ConfigMap/Secret,实现配置与镜像分离
- 第五阶段:配置 HPA 实现 CPU/内存驱动的自动伸缩
- 第六阶段:引入 KEDA,实现基于业务指标的事件驱动伸缩
完成这六个阶段,你的 Spring Boot 应用就从“能在 K8s 上跑”进化到了“生产级云原生应用”——具备弹性伸缩、自动恢复、零停机发布的能力。
📌 系列拓展阅读:
- 《Spring Boot 3.4 Docker 镜像最佳实践(含分层构建)》——本文的容器化前置知识
- 《Java 应用接入 Prometheus + Grafana 全记录》——KEDA 指标来源的监控体系
- 《Java 日志最佳实践 2026:从 SLF4J 到 ELK 全链路日志追踪》——K8s 环境下的日志采集
- 《GitHub Actions 构建 Java 项目并推送 Docker 镜像》——CI/CD 镜像构建流水线
📚 参考文献:
- Kubernetes 官方文档. Deployments. https://kubernetes.io/docs/concepts/workloads/controllers/deployment/
- Kubernetes 官方文档. Horizontal Pod Autoscaling. https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
- Kubernetes 官方文档. Configure Liveness, Readiness and Startup Probes. https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
- Kubernetes 官方文档. Performing a Rolling Update. https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/
- KEDA 官方文档. Prometheus Scaler. https://keda.sh/docs/latest/scalers/prometheus/
- 华为云社区. Kubernetes 集群部署 Spring Boot 应用最佳实践. https://bbs.huaweicloud.com/blogs/443322
- CSDN. HPA 扩缩容总慢半拍?Spring Boot 指标选择的”精准制导”秘籍. https://blog.csdn.net/






