Kubernetes 探针配置实战:从入门到生产级自愈方案
在生产环境中,容器化应用随时可能因内存泄漏、死锁或外部依赖故障而变得不可用。Kubernetes 探针(Probes)是解决这一问题的核心机制——它让集群能够自动检测并修复故障,无需人工介入。本文聚焦于 liveness、readiness 和 startup 三种探针的配置细节、常见陷阱以及调试方法,帮助你构建真正高可用的工作负载。
安装与快速上手
Kubernetes 探针是 Pod 规范的一部分,无需额外安装组件。要快速验证探针功能,可以直接应用官方示例:
BASHkubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
该命令会创建一个包含 liveness 探针的 Pod,探针通过执行 cat /tmp/healthy 命令来检查容器健康状态。如果文件不存在(模拟应用故障),kubelet 将重启容器。
查看探针状态:
BASHkubectl describe pod liveness-exec
在输出中,Events 部分会显示探针的检查结果和重启记录。
核心配置参数详解
探针的行为由一组参数精确控制。以下表格列出了所有关键参数及其作用:
| 参数 | 是否必需 | 默认值 | 描述 |
|---|---|---|---|
initialDelaySeconds | 否 | 0 | 容器启动后,kubelet 等待首次探测的秒数。对于启动慢的应用(如 Java 应用),应设置足够大的值 |
periodSeconds | 否 | 10 | 两次探测之间的间隔秒数。值越小,检测越快,但资源消耗越高 |
timeoutSeconds | 否 | 1 | 单次探测的超时秒数。超过此时间未响应视为失败 |
successThreshold | 否 | 1 | 探测失败后,连续成功多少次才认为容器恢复健康 |
failureThreshold | 否 | 3 | 连续失败多少次后,kubelet 执行相应操作(重启或移除端点) |
三种探测类型
Kubernetes 支持四种探测方式,每种适用于不同场景:
1. Exec 探针:在容器内执行命令,返回码 0 表示成功,非零表示失败。
YAMLlivenessProbe: exec: command: - cat - /tmp/healthy initialDelaySeconds: 5 periodSeconds: 5
2. HTTP Get 探针:向容器发送 HTTP GET 请求,状态码在 200-399 之间视为成功。
YAMLlivenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 10 periodSeconds: 10
3. TCP Socket 探针:尝试建立 TCP 连接,成功则视为健康。
YAMLlivenessProbe: tcpSocket: port: 3306 initialDelaySeconds: 15 periodSeconds: 20
4. gRPC 探针(Kubernetes 1.24+):调用 gRPC 健康检查协议,需要应用实现 grpc.health.v1.Health 服务。
三种探针的职责分工
理解 liveness、readiness 和 startup 探针的区别是正确配置的前提:
| 探针类型 | 失败后果 | 典型用途 |
|---|---|---|
| liveness | 重启容器 | 检测死锁、内存泄漏等不可恢复故障 |
| readiness | 从 Service 端点中移除 | 控制流量,如应用正在加载缓存或等待依赖 |
| startup | 禁用 liveness/readiness 探针 | 慢启动应用(如 JVM 初始化) |
配置建议:
- 对于启动时间超过 30 秒的应用,必须使用 startup 探针,否则 liveness 探针会在启动完成前误杀容器
- 有状态应用(如数据库)优先使用 readiness 探针,避免因重启导致数据丢失
- 无状态应用可以同时配置 liveness 和 readiness 探针
生产环境实践与注意事项
参数调优原则
- initialDelaySeconds:设置为应用启动时间的 1.5 倍。例如,应用需要 20 秒启动,则设为 30 秒
- periodSeconds:对于关键服务设为 5-10 秒,非关键服务可设为 15-30 秒
- failureThreshold:建议设为 3-5,避免因瞬时网络抖动导致误判
- timeoutSeconds:HTTP 探针建议设为 2-5 秒,exec 探针根据命令复杂度调整
常见陷阱
- 探测频率过高:
periodSeconds设为 1 秒可能导致 kubelet 资源耗尽,建议不低于 5 秒 - 探针路径暴露敏感信息:避免在
/healthz端点返回数据库密码等敏感数据 - 忽略网络策略:确保 kubelet 节点能访问 Pod 的探测端口,否则探针会持续失败
- 并发冲突:多个探针同时执行可能影响应用性能,建议错开探测时间
安全性考虑
- 对于 HTTP 探针,使用 HTTPS 时需配置证书,否则 kubelet 会拒绝连接
- exec 探针的命令应避免包含敏感参数,建议通过环境变量传递
- 确保 kubelet 有权限执行探测命令或访问端口(通常默认具备)
常见报错与排查
错误 1:Exec 探针文件不存在
Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
解决方案:
- 检查应用是否按预期创建了健康检查文件
- 调整探测命令路径,或改用 HTTP 探针
- 增加
initialDelaySeconds,确保应用完成初始化
错误 2:HTTP 探针返回 500
HTTP probe failed with status code 500
解决方案:
- 检查应用的健康检查端点逻辑,查看应用日志定位 500 原因
- 确认
httpGet.path和httpGet.port配置正确 - 临时使用
curl手动测试端点
错误 3:TCP 探针连接被拒绝
TCP probe failed: connection refused
解决方案:
- 确认应用是否在指定端口上监听:
kubectl exec <pod> -- netstat -tlnp - 检查端口映射和网络策略
- 增加
initialDelaySeconds等待应用启动
错误 4:gRPC 探针未实现
gRPC probe failed: health check not implemented
解决方案:
- 确保应用实现了 gRPC 健康检查协议(
grpc.health.v1.Health/Check) - 改用 HTTP 或 TCP 探针作为替代
- 检查 gRPC 服务版本兼容性
调试通用步骤
BASH# 查看探针事件和状态 kubectl describe pod <pod-name> # 查看应用日志 kubectl logs <pod-name> # 进入容器手动测试 kubectl exec -it <pod-name> -- /bin/sh # 在容器内执行探测命令 cat /tmp/healthy curl http://localhost:8080/healthz nc -zv localhost 3306
常见问题 FAQ
Q: 如何为有状态应用配置 liveness 探针以避免数据丢失?
A: 对于有状态应用(如数据库),建议使用 readiness 探针而非 liveness 探针,因为 liveness 探针失败会导致容器重启,可能丢失未持久化的数据。readiness 探针仅将 Pod 标记为不可用,不会重启容器。如果必须使用 liveness 探针,应确保应用在重启前能安全保存状态,或使用 preStop 钩子进行优雅关闭。例如:
YAMLlifecycle: preStop: exec: command: ["/bin/sh", "-c", "flock /var/lib/mysql/mysql.sock -c 'mysqladmin shutdown'"]
Q: liveness 和 readiness 探针有什么区别?何时使用 startup 探针?
A: liveness 探针用于检测容器是否存活,失败则重启容器;readiness 探针用于检测容器是否准备好接收流量,失败则从 Service 端点中移除。startup 探针用于慢启动应用,在启动期间禁用 liveness 和 readiness 探针,避免因启动慢而被误杀。建议:
- 对于启动时间长的应用(如 Java 应用),使用 startup 探针
- 对于需要流量控制的应用,使用 readiness 探针
- 对于需要自愈的应用,使用 liveness 探针
Q: 如何调试探针失败问题?
A: 1. 使用 kubectl describe pod <pod-name> 查看事件和探针状态。2. 检查应用日志:kubectl logs <pod-name>。3. 手动测试探针:对于 exec 探针,进入容器执行命令;对于 HTTP 探针,使用 curl 测试端点;对于 TCP 探针,使用 nc 测试端口。4. 调整探针参数:增加 initialDelaySeconds、failureThreshold 或 periodSeconds。5. 检查网络策略和防火墙是否阻止了 kubelet 的探测请求。
相关深度解决方案
在配置当前服务时,如果您需要实现更复杂的架构或多源数据整合,建议配合参考我们整理的 Node.js 堆内存溢出(OOM)实战排查与修复:从应急到根治。
在配置当前服务时,如果您需要实现更复杂的架构或多源数据整合,建议配合参考我们整理的 Redis Sentinel 故障转移实战:从配置到生产级高可用部署。