在 Kubernetes 里,Kubernetes 探针(Probe)是 kubelet 用来判断容器“是否健康、是否能接流量、是否启动完成”的健康检查机制。合理配置 liveness、readiness 与 startup 三类探针,能在进程假死、依赖未就绪、慢启动等场景下自动重启或摘流,是生产级工作负载的标配。本文用可复制的 YAML 讲清三类探针的区别、三种探测方式,以及最常见的配置误区。
一、三类探针到底管什么
很多人把三种探针混用,结果要么被反复重启,要么流量打到了还没准备好的 Pod。三者的职责完全不同:
| 探针 | 回答的问题 | 失败后果 | 典型用途 |
| livenessProbe | 容器还活着吗? | 杀死并重启容器 | 应对死锁、假死 |
| readinessProbe | 容器能接流量吗? | 从 Service 端点摘除 | 依赖就绪、预热完成 |
| startupProbe | 容器启动完了吗? | 失败则重启(在它成功前不跑 liveness) | 慢启动应用 |
一句话记忆:liveness 决定“要不要杀”,readiness 决定“要不要给流量”,startup 决定“启动期先别急着杀”。三者可以共存于同一个容器。
二、Liveness 探针:容器假死的最后一道保险
livenessProbe 失败会触发 kubelet 重启容器。它适合检测“进程还在但已经无法服务”的死锁场景。最常见的探测方式有三种。
exec:在容器内执行命令
livenessProbe:
exec:
command:
- /bin/sh
- -c
- test -f /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 10
当 /tmp/healthy 文件不存在时,命令返回非 0,探测失败。一个经典误用是把“应用是否就绪”也塞进 liveness:一旦依赖的数据库连不上,liveness 失败导致容器被无限重启,反而雪上加霜。
httpGet:发起 HTTP 请求
livenessProbe:
httpGet:
path: /healthz
port: 8080
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
HTTP 探测返回 200–399 视为成功,其它状态码(含 500)都算失败。注意:不要把需要鉴权或依赖下游的接口当作 liveness 端点,否则一个下游抖动就会引发级联重启。
tcpSocket:仅检查端口是否可连通
readinessProbe:
tcpSocket:
port: 6379
initialDelaySeconds: 5
periodSeconds: 5
tcpSocket 只验证“端口能连上”,不验证业务逻辑,适合 Redis、MySQL 这类纯端口服务,但无法区分“连上了但已无法响应命令”。
三、Readiness 探针:流量准入的闸门
readinessProbe 失败不会重启容器,而是把 Pod 从对应 Service 的 endpoints 里摘掉,直到探测恢复。它用来表达“我现在还不能接流量”。
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
一个典型场景:应用启动后需要先加载模型、预热缓存、连上消息队列。这些没完成前,readiness 返回失败,Service 不会把请求转发过来,避免了“启动即报错”的流量黑洞。它与 K8s ConfigMap/Secret 实战 配合时,配置热更新后也可通过 readiness 短暂摘流再恢复。
四、Startup 探针:慢启动应用的救星
如果应用冷启动要 2 分钟(如 JVM 大堆、AI 模型加载),而 liveness 的 periodSeconds×failureThreshold 只有 30 秒,启动期就会被反复杀掉,永远起不来。startupProbe 就是为此而生:在它成功之前,liveness 与 readiness 不会生效。
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30 # 每次 10s,最多等 300s
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3
这样 startup 给足 5 分钟启动窗口,启动成功后 liveness 才接管。Startup 探针与文件描述符耗尽排查这类资源类故障也常有关联:资源受限时启动明显变慢,正是 startup 阈值该放大的信号。
五、三种探测方式对照与选型
| 方式 | 优点 | 缺点 | 适用 |
| exec | 能验证任意内部状态 | 要写脚本,较重 | 复杂依赖检查 |
| httpGet | 语义清晰,零依赖 | 需暴露端点 | Web 服务首选 |
| tcpSocket | 最轻量 | 不验证业务逻辑 | 纯端口服务 |
六、生产级参数清单
以下五个参数决定了探针的行为节奏,务必按应用实际调优,而不是全用默认值:
# 推荐基线(Web 服务)
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
initialDelaySeconds: 15 # 启动后多久开始探
periodSeconds: 10 # 探测间隔
timeoutSeconds: 2 # 单次超时
successThreshold: 1 # 连续几次成功算恢复
failureThreshold: 3 # 连续几次失败算失败
| 参数 | 含义 | 经验值 |
| initialDelaySeconds | 首次探测前的等待 | 快应用 5–15s,慢应用配合 startup |
| periodSeconds | 探测周期 | 5–15s |
| timeoutSeconds | 单次超时 | 1–3s |
| failureThreshold | 失败容忍次数 | liveness 3,readiness 2–3 |
| successThreshold | 恢复所需连续成功 | 默认 1 |
七、一个真实事故:探针配错导致流量全挂
某次发布后,readiness 端点依赖了一个刚上线的内部鉴权服务。鉴权服务抖动时,所有 Pod 的 readiness 同时失败,Service endpoints 被清空,入口流量 100% 502。根因是把“强依赖外部服务”的逻辑放进了 readiness。修复方式是把 readiness 收敛为“仅检查本进程核心能力”,外部依赖交给RBAC 与重试与熔断处理。
八、与资源限制、优雅停机配合
探针不是孤立的。当容器因内存超限被 OOMKilled(见OOMKilled 排查实战)时,liveness 的重启会叠加在资源压力下,可能形成重启风暴。建议给容器设置合理的 resources.limits,并在应用里实现 SIGTERM 优雅停机:先让 readiness 失败摘流,再处理完在途请求后退出。同时配合 Pod 安全上下文 以非 root 运行,缩小爆炸半径。
九、常见误区排障表
| 现象 | 原因 | 修复 |
| Pod 一直重启 | liveness 阈值太短 / 端点依赖外部 | 拉长 failureThreshold,解耦外部依赖 |
| 新 Pod 启动即报错 | 未配 startup,启动慢被 liveness 杀 | 加 startupProbe 给足窗口 |
| 流量打到报错 Pod | 只配了 liveness 没配 readiness | 补 readiness 摘流 |
| 滚动更新卡住 | readiness 迟迟不成功 | 检查就绪条件是否可达 |
十、落地 Checklist
| 项 | 建议 |
| Web 服务 | httpGet + 独立 /healthz、/ready 端点 |
| 纯端口服务 | tcpSocket 或 exec |
| 慢启动 | 必配 startupProbe |
| liveness | 只验证“进程还活着”,不依赖下游 |
| readiness | 验证“能接流量”,依赖就绪前先摘流 |
| 参数 | 显式设置 5 个节奏参数,拒绝全默认 |
十一、小结
Kubernetes 探针是性价比极高的稳定性投资:用几行 YAML 就把“自动重启、自动摘流、慢启动保护”三件事安排明白。记住分工——liveness 管生死、readiness 管流量、startup 管启动,并让探针只反映本进程能力,外部依赖交给重试与熔断。把这套写进你的 CI/CD 流水线 与基础镜像,新应用开箱即稳。
十二、用 kubectl 验证探针状态
配置完探针,第一件事不是等事故,而是立刻用 kubectl 确认它们真的在工作。describe 能直接看到三类探针的实时结果与最近一次探测输出,restartCount 则能反映 liveness 是否在悄悄重启你的容器。
# 查看探针配置与最近探测结果
kubectl describe pod myapp-7d8f9 -n default | grep -A6 -i "Liveness\|Readiness\|Startup"
# 看 Pod 是否被 readiness 摘流
kubectl get endpoints myapp
# 看容器重启次数(持续增长说明 liveness 在杀)
kubectl get pod myapp-7d8f9 -o jsonpath="{.status.containerStatuses[0].restartCount}"
如果 endpoints 里没有 Pod IP,说明 readiness 处于失败状态;如果 restartCount 每分钟涨一次,基本锁定是 liveness 阈值过严或端点依赖了外部服务。把这些信息接入 Uptime Kuma 自建监控,还能在探针异常时第一时间收到告警。
十三、探针与滚动更新、HPA 的联动
探针还会悄悄影响发布与扩缩容。滚动更新时,新 Pod 只有在 readiness 成功后才会被加入 Service,旧 Pod 也只在自身 readiness 失败后(或被新版本替换)才退出,这天然实现了“零中断发布”。而 HPA 基于 CPU/内存扩缩容时,如果新扩容的 Pod 因 readiness 迟迟不就绪,Service 端点数量上去了、能接流量的却没上去,就会出现“扩容了却没扛住”的假象。
| 场景 | 探针的作用 |
| 滚动更新 | readiness 决定新旧 Pod 的流量切替时机 |
| 缩容 | terminating 状态先 readiness 失败再停,避免中断在途请求 |
| HPA 扩容 | 新 Pod readiness 就绪前不计入可用端点 |
| 节点驱逐 | 配合 PDB 与优雅停机平滑迁移 |
因此,探针不是“配了就行”的装饰,而是连接部署、伸缩与稳定性的中枢。上线前务必用上面的 kubectl 命令做一次真实验证,把 restartCount、endpoints 与 readiness 状态纳入你的发布检查单。




