Spring Boot 应用在Kubernetes中的健康检查:Liveness与Readiness探针的实战配置与策略
1. 为什么需要健康检查在Kubernetes中部署Spring Boot应用时健康检查机制就像是给应用安装了一个生命体征监测仪。想象一下医院里的重症监护设备它能实时反映病人的心跳、血压等关键指标。Liveness和Readiness探针就是Kubernetes用来监测应用状态的生命体征仪。我去年负责的一个电商项目就吃过这个亏。当时没有配置Readiness探针结果应用还在加载数据库连接池时就收到了大量请求直接导致服务雪崩。后来我们给每个微服务都加上了健康检查类似的问题再没出现过。2. Liveness与Readiness探针的区别2.1 Liveness探针应用的心跳检测Liveness探针相当于应用的心跳检测。当它失败时Kubernetes会认为应用已经脑死亡需要立即重启。在实际项目中我发现这些场景特别适合用Liveness探针内存泄漏导致OOM死锁或线程池耗尽关键内部组件崩溃如消息队列消费者livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 30 # 给Spring Boot足够的启动时间 periodSeconds: 10 failureThreshold: 32.2 Readiness探针流量控制开关Readiness探针则是应用的服务可用性开关。当它返回失败时Kubernetes会从Service的Endpoint中移除该Pod但不会重启它。这几个场景你应该考虑Readiness探针数据库连接池初始化中缓存预热未完成依赖的下游服务不可用系统负载过高需要降级readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 15 periodSeconds: 5 successThreshold: 2 # 避免偶发性故障导致频繁状态切换3. Spring Boot中的实战配置3.1 基础环境搭建首先在pom.xml中添加必要依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-actuator/artifactId /dependency然后在application.properties中启用健康检查分组# 显示详细健康信息 management.endpoint.health.show-detailsalways # 启用Liveness/Readiness分组 management.endpoint.health.probes.enabledtrue # 自定义检查项分组 management.endpoint.health.group.readiness.includedb,redis management.endpoint.health.group.liveness.includediskSpace3.2 自定义健康指标假设我们需要检查第三方支付接口的可用性Component public class PaymentHealthIndicator implements HealthIndicator { private final PaymentClient paymentClient; Override public Health health() { try { boolean isHealthy paymentClient.checkHealth(); return isHealthy ? Health.up().build() : Health.down().withDetail(error, 支付服务响应超时).build(); } catch (Exception e) { return Health.down(e).build(); } } }然后在配置中将该指标加入Readiness组management.endpoint.health.group.readiness.includedb,redis,payment4. Kubernetes中的高级配置策略4.1 参数调优经验这些参数值是我在多个生产环境中验证过的黄金配置参数Liveness建议值Readiness建议值说明initialDelaySeconds30-60s15-30sSpring Boot启动时间periodSeconds10s5s检查频率timeoutSeconds3s2s超时阈值failureThreshold32失败重试次数successThreshold12成功确认次数4.2 优雅停机配合方案结合Graceful Shutdown实现零停机部署# application.properties server.shutdowngraceful spring.lifecycle.timeout-per-shutdown-phase30s对应的Kubernetes配置spec: terminationGracePeriodSeconds: 40 # 比Spring Boot超时略长 containers: - name: app lifecycle: preStop: exec: command: [sh, -c, sleep 10] # 给负载均衡器留出时间5. 常见问题排查指南5.1 探针配置错误症状Pod不断重启或无法接收流量 检查步骤查看Pod事件kubectl describe pod pod-name检查探针日志kubectl logs pod-name -c container-name手动测试端点kubectl exec -it pod-name -- curl http://localhost:8080/actuator/health/liveness5.2 启动顺序问题当应用依赖数据库等外部服务时建议使用initContainerinitContainers: - name: wait-for-db image: busybox command: [sh, -c, until nc -z mysql 3306; do echo 等待MySQL; sleep 2; done]5.3 资源不足处理在资源限制场景下的优化配置resources: limits: memory: 1Gi cpu: 1 requests: memory: 768Mi cpu: 0.5同时调整JVM参数避免OOM# application.properties spring.jvm.args-Xms512m -Xmx768m -XX:MaxRAMPercentage75.06. 生产环境最佳实践在金融级系统中我们采用分层检查策略Liveness只检查核心进程状态Readiness分三级检查基础级容器状态服务级数据库、缓存业务级下游依赖对应的健康指标实现Readiness Component public class TieredReadinessHealthIndicator implements HealthIndicator { private final ListHealthIndicator tier1Indicators; private final ListHealthIndicator tier2Indicators; Override public Health health() { Health.Builder builder Health.up(); // 第一层检查 for (HealthIndicator indicator : tier1Indicators) { Health health indicator.health(); if (health.getStatus() ! Status.UP) { return Health.down().withDetail(tier, 1).build(); } } // 第二层检查 for (HealthIndicator indicator : tier2Indicators) { Health health indicator.health(); builder.withDetail(indicator.getClass().getSimpleName(), health); if (health.getStatus() ! Status.UP) { builder.status(DEGRADED); } } return builder.build(); } }这种设计让我们在618大促期间即使部分非核心依赖出现故障也能保持基本服务能力。