1. 为什么需要存活探测机制
在Kubernetes集群中,Pod是最小的可部署单元。但现实情况是,任何运行中的进程都可能因为各种原因进入非健康状态——比如内存泄漏导致进程僵死、线程阻塞造成服务无响应,或者更常见的死锁情况。这时候容器本身可能还在运行,但已经无法正常提供服务了。
传统运维模式下,我们通常通过外部监控系统来检测服务状态,发现问题后手动重启服务。这种做法的响应延迟往往以分钟计,而且需要额外部署监控组件。Kubernetes的Liveness Probe机制则将这个能力内置到了平台层面,实现了秒级的问题检测和自动恢复。
我曾在生产环境遇到过典型的案例:一个Java应用因为GC配置不当导致周期性Full GC,每次停顿长达30秒。虽然进程没有崩溃,但在此期间所有请求都会超时。通过配置合理的Liveness Probe,我们让Kubernetes自动重启了问题实例,将故障影响从每次几分钟缩短到了几秒钟。
2. Liveness Probe的工作原理
2.1 探测机制的类型
Kubernetes提供了三种基本的探测方式:
HTTP GET:向容器内指定端口和路径发送HTTP请求,根据响应状态码判断(2xx/3xx表示健康)
livenessProbe: httpGet: path: /healthz port: 8080 httpHeaders: - name: Custom-Header value: AwesomeTCP Socket:尝试与指定端口建立TCP连接,能建立连接则认为健康
livenessProbe: tcpSocket: port: 8080Exec:在容器内执行指定命令,返回值为0表示健康
livenessProbe: exec: command: - cat - /tmp/healthy
2.2 探测过程的时间参数
每个探测行为都有一组关键时间参数控制:
livenessProbe: initialDelaySeconds: 30 # 容器启动后等待多长时间开始第一次探测 periodSeconds: 10 # 每次探测的间隔时间 timeoutSeconds: 5 # 探测请求的超时时间 successThreshold: 1 # 连续几次成功才算真的成功 failureThreshold: 3 # 连续几次失败才会重启容器这些参数的设置需要根据应用特性仔细调整。比如一个需要长时间初始化的应用,initialDelaySeconds就应该设置得比应用启动时间长。我曾经见过因为initialDelaySeconds设置过短,导致应用还没完成初始化就被不断重启的案例。
3. 生产环境配置实践
3.1 HTTP探测的最佳实践
对于HTTP服务,/healthz是最常用的健康检查端点。这个端点应该:
- 只做轻量级检查(避免数据库查询等耗时操作)
- 返回包含依赖服务状态的复合信息
- 设置适当的缓存控制头
一个Spring Boot应用的示例实现:
@RestController public class HealthController { @GetMapping("/healthz") public ResponseEntity<Map<String, String>> healthCheck() { Map<String, String> status = new HashMap<>(); status.put("status", "UP"); status.put("timestamp", Instant.now().toString()); return ResponseEntity.ok() .cacheControl(CacheControl.maxAge(Duration.ofSeconds(10))) .body(status); } }对应的Probe配置:
livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 45 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 23.2 有状态服务的特殊处理
对于数据库等有状态服务,直接重启可能导致数据不一致。这时可以采用更保守的策略:
livenessProbe: exec: command: - sh - -c - '[[ $(ps aux | grep "[m]ysqld") ]] && mysqladmin ping -uroot -p$MYSQL_ROOT_PASSWORD' initialDelaySeconds: 120 periodSeconds: 30 timeoutSeconds: 10 failureThreshold: 5这个配置:
- 检查mysqld进程是否存在
- 检查是否能正常执行ping命令
- 设置了较长的初始延迟和失败阈值
- 使用环境变量而非硬编码密码
4. 常见问题与排查技巧
4.1 探测导致的频繁重启
症状:Pod不断重启,kubectl describe pod显示"Liveness probe failed"
排查步骤:
- 检查容器日志是否有异常
kubectl logs <pod-name> --previous - 手动执行探测命令验证
kubectl exec <pod-name> -- curl http://localhost:8080/healthz - 检查资源限制是否过小
kubectl describe pod <pod-name> | grep -A 5 "Limits"
常见原因:
- initialDelaySeconds设置过短
- 健康检查端点响应慢导致超时
- 容器资源不足导致进程卡顿
4.2 与Readiness Probe的配合
Liveness Probe和Readiness Probe经常被混淆,它们的核心区别是:
| 特性 | Liveness Probe | Readiness Probe |
|---|---|---|
| 失败后的动作 | 重启容器 | 从Service摘除 |
| 典型检查频率 | 较低(10-30s) | 较高(1-5s) |
| 检查内容 | 深度健康检查 | 基本可用性检查 |
生产环境中通常同时配置两者:
ports: - name: http containerPort: 8080 readinessProbe: httpGet: path: /ready port: http periodSeconds: 5 livenessProbe: httpGet: path: /healthz port: http periodSeconds: 205. 高级场景与优化
5.1 渐进式健康检查
对于启动时间不固定的应用,可以使用动态initialDelaySeconds:
livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 30 periodSeconds: 5 timeoutSeconds: 1 failureThreshold: 3 successThreshold: 2 startupProbe: httpGet: path: /healthz port: 8080 failureThreshold: 30 periodSeconds: 5这种配置下:
- startupProbe允许应用有最多150秒(30×5)的启动时间
- 一旦startupProbe成功,就切换到常规的livenessProbe
- 避免了为所有Pod设置过长的initialDelaySeconds
5.2 基于gRPC的健康检查
对于gRPC服务,可以使用专门的grpc-health-probe:
livenessProbe: exec: command: - /bin/grpc_health_probe - -addr=:50051 - -tls - -tls-ca-cert=/etc/ssl/certs/ca.crt initialDelaySeconds: 10 periodSeconds: 5需要预先将grpc_health_probe二进制文件打包到容器镜像中,或者使用sidecar模式。
6. 监控与告警配置
合理的监控可以帮助发现探测机制本身的问题。建议监控以下指标:
Pod重启次数:
sum(kube_pod_container_status_restarts_total{namespace="production"}) by (pod)探测延迟分布:
histogram_quantile(0.95, sum(rate(kubelet_prober_probe_duration_seconds_bucket{probe_type="liveness"}[5m])) by (le))探测失败率:
sum(rate(kubelet_prober_probe_total{probe_type="liveness", result="failed"}[5m])) / sum(rate(kubelet_prober_probe_total{probe_type="liveness"}[5m]))
对应的告警规则示例:
- alert: HighPodRestartRate expr: increase(kube_pod_container_status_restarts_total[1h]) > 3 for: 15m labels: severity: warning annotations: summary: Pod {{ $labels.pod }} has restarted {{ $value }} times in the last hour在配置Liveness Probe时,一个常被忽视但非常重要的点是考虑应用本身的特性。比如对于批处理作业,可能根本不需要Liveness Probe;对于有状态服务,过于激进的探测配置可能导致数据损坏。每次调整探测参数后,都应该在预发布环境充分验证,观察至少一个完整的业务周期(比如24小时)的行为。