3. 健康检查基础:健康检查的目的、类型与探针机制
健康检查是弹性伸缩与发布流程中最重要的质量门禁之一。没有健康检查,系统无法判断实例是否真正就绪、是否存活、是否能够正常处理业务流量。Kubernetes 提供了三种探针(Probe)来覆盖不同阶段的应用状态检测:Liveness、Readiness 和 Startup。每种探针都有明确的职责边界,组合使用才能构建完整的健康门禁体系。
3.1 健康检查的核心目的
健康检查不是简单的“ping 通即健康”,而是从多个维度验证应用实例的实际运行质量。在弹性伸缩和发布场景中,健康检查需要解决以下关键问题:
- 检测实例是否存活:进程是否运行、是否陷入死锁或内存泄漏导致的假死状态。
- 检测实例是否就绪:应用是否已完成初始化、依赖服务是否可用、是否能够接收并处理请求。
- 检测实例是否启动完成:对于启动缓慢的应用(如 Java 应用、加载大量模型的服务),需要区分“正在启动”和“启动失败”。
- 避免流量损失:在滚动更新或弹性扩容时,确保只有健康的实例才被加入负载均衡池。
- 加速故障自愈:自动重启不健康的实例,减少人工介入时间。
3.2 三种探针类型与职责对比
Kubernetes 定义了三种探针,分别对应应用生命周期的不同阶段。下表清晰展示了它们的职责、触发动作和典型使用场景:
| 探针类型 | 检测目的 | 失败后动作 | 典型场景 |
|---|---|---|---|
| Liveness Probe | 检测容器是否存活(进程是否健康) | 重启容器(kubelet 执行 restart) | 检测死锁、内存泄漏、进程挂起 |
| Readiness Probe | 检测容器是否就绪(能否接收流量) | 从 Service Endpoints 中移除 | 滚动更新、扩容时等待应用就绪 |
| Startup Probe | 检测容器是否启动完成(慢启动保护) | 重启容器(启动阶段失败) | Java 应用、模型加载、冷启动耗时服务 |
3.3 探针机制:四种检测方式
Kubernetes 支持四种探针执行方式,每种方式适用于不同的应用协议和环境。选择哪种方式取决于应用暴露的端口、协议以及是否需要自定义检测逻辑。
3.3.1 HTTP GET 探针
最常用的探针方式。kubelet 向容器的指定端口和路径发起 HTTP GET 请求,返回 200-399 状态码视为成功,其他状态码或超时视为失败。
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: health-check
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
3.3.2 TCP Socket 探针
kubelet 尝试与容器的指定端口建立 TCP 连接。连接成功视为健康,失败则视为不健康。适用于只暴露 TCP 端口、没有 HTTP 服务的应用(如数据库、消息队列)。
readinessProbe:
tcpSocket:
port: 3306
initialDelaySeconds: 10
periodSeconds: 5
3.3.3 gRPC 探针
Kubernetes 1.24+ 原生支持 gRPC 探针。kubelet 通过 gRPC 健康检查协议(grpc.health.v1.Health/Check)检测应用状态。适用于微服务架构中大量使用 gRPC 通信的场景。
livenessProbe:
grpc:
port: 50051
service: "myapp.HealthService"
initialDelaySeconds: 5
periodSeconds: 10
3.3.4 Exec 命令探针
kubelet 在容器内执行一条命令,命令退出码为 0 视为健康,非零视为不健康。适用于无法通过网络端口检测的场景,或者需要执行自定义脚本验证内部状态。
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 10
- 优先使用 HTTP GET 探针,因为它能返回具体的业务状态码,便于调试。
- 如果应用只暴露 TCP 端口,使用 TCP Socket 探针。
- 如果应用使用 gRPC 通信,使用 gRPC 探针,避免额外的 HTTP 封装。
- 仅在无法通过网络检测时使用 Exec 探针,注意 Exec 探针会消耗容器内资源。
3.4 探针参数与调优原则
探针的行为由一组参数控制,错误的参数配置可能导致频繁重启或延迟发现故障。下表列出关键参数及其推荐配置思路:
| 参数 | 说明 | 推荐配置 |
|---|---|---|
initialDelaySeconds |
容器启动后等待多久开始第一次探测 | 根据应用启动时间设置,通常 5-30s |
periodSeconds |
每次探测的间隔时间 | 10-30s,避免过于频繁 |
timeoutSeconds |
单次探测的超时时间 | 1-5s,超时即视为失败 |
failureThreshold |
连续失败多少次后判定为不健康 | 3-5 次,避免瞬态波动导致误判 |
successThreshold |
连续成功多少次后判定为健康(仅 Readiness) | 1(默认),通常不需要修改 |
3.5 三种探针与四种机制的组合关系图
下图展示了三种探针在应用生命周期中的位置,以及四种检测方式如何与探针类型结合:
3.6 三种探针的协同工作流程
在实际发布和弹性伸缩过程中,三种探针需要协同工作才能实现平滑的流量切换和故障自愈。下图展示了从容器启动到稳定运行的完整探针协作流程:
3.7 最佳实践与常见陷阱
- 为每个容器配置 Readiness Probe:这是流量门禁的基础,确保只有就绪的实例接收流量。
- 为关键服务配置 Liveness Probe:避免死锁或内存泄漏导致的服务假死。
- 为慢启动应用配置 Startup Probe:防止启动阶段的正常耗时被 Liveness 误判为故障。
- 探针端点返回业务状态:HTTP 探针的
/healthz端点应返回应用的核心依赖状态,而不仅仅是进程存活。 - 设置合理的超时和阈值:避免因网络抖动或短暂负载导致频繁重启。
- 探针端点包含耗时操作:不要在健康检查端点中执行数据库查询或外部 API 调用,这会导致探针超时和级联故障。
- 所有探针使用相同的端点:Liveness 和 Readiness 应该使用不同的端点或不同的检测逻辑,因为它们的职责不同。
- 忽略 Startup Probe:对于启动时间超过
initialDelaySeconds + failureThreshold * periodSeconds的应用,不配置 Startup Probe 会导致容器被反复重启。 - Exec 探针执行复杂脚本:Exec 探针会消耗容器内的 CPU 和内存资源,复杂脚本可能影响应用性能。