3.4 探针接管:readiness与liveness的健康裁判


3.4 探针接管:readiness 与 liveness 的健康裁判

探针(Probe) 是 kubelet 对容器执行的周期性体检,分三种:startup 探针守护慢启动、liveness 探针决定要不要重启容器、readiness 探针决定要不要给容器分发流量。探针由你在 Pod 声明中配置,kubelet 执行,裁判规则一经声明即刻生效。

容器跑起来了,旅程还差最后一道工序:集群如何知道它能接活?没有这道工序,一个启动到一半、连不上数据库的容器会立刻被当成健康副本接进流量,用户请求成批超时。本节讲清三种探针的职权划分、参数调法与误杀事故的防范——这是声明从"能跑"到"可控"的分界线。

一、体检与裁判:三种探针的职权

三种探针用的是同一套检查手段(HTTP 请求、TCP 连接、执行命令),区别全在判负后的处置

探针 回答的问题 判负后的动作 典型误配后果
startup 启动完成了吗 通过前暂停另外两种探针 慢启动应用被 liveness 误杀
liveness 进程还活着吗 重启容器 检查项含外部依赖时引发重启风暴
readiness 现在能接活吗 摘出负载均衡,不重启 无探针时半死副本照样收流量

处置逻辑的差异用一张流程图固化下来,三条分支对应三种探针:

readiness 的摘除动作值得展开:Service 的流量分发名单(端点列表)以 READY 为准入条件,探针失败的副本会被移出名单、恢复后再加回。这给了集群一个精细的流量闸门——升级时新副本先过体检再接客,正是第4章滚动更新不中断服务的技术底座

二、为 orders-api 配齐三种探针

给 1.2 节的容器声明加上完整的体检条款:

containers: - name: orders-api image: orders-api:1.4.2 startupProbe: # 先问"起来了吗":最多等 60 秒 httpGet: path: /healthz # 轻量存活端点,只查进程不查依赖 port: 8080 periodSeconds: 2 # 每 2 秒查一次 failureThreshold: 30 # 连续失败 30 次才算启动失败(2x30=60 秒) livenessProbe: # 再问"还活着吗":判负即重启 httpGet: path: /healthz port: 8080 periodSeconds: 5 failureThreshold: 3 # 连续 3 次失败(约 15 秒)触发重启 readinessProbe: # 最后问"能接活吗":判负摘流量 httpGet: path: /ready # 就绪端点,可查关键依赖是否就位 port: 8080 initialDelaySeconds: 5 # 首查延迟,给应用初始化留时间 periodSeconds: 5

三个参数的乘积决定裁判的严厉程度:failureThreshold 乘 periodSeconds 是容忍窗口,窗口越短反应越快也越容易误杀。经验起点:liveness 容忍 15 秒左右,readiness 10 秒左右,startup 按应用最慢启动时间的两倍设置。检查端点的设计同样有讲究——下一小节的反例会看到,端点查错对象,参数再准也白搭。

判负的现场证据在事件流里,格式固定:

kubectl describe pod orders-api-6d9f7c8b5-2vxk7 -n production | grep -E "Liveness|Readiness" | tail -3 # Warning Unhealthy 4m kubelet Liveness probe failed: # HTTP probe failed with statuscode: 503 # Warning Unhealthy 4m kubelet Readiness probe failed: # dial tcp 10.244.1.5:8080: connect: connection refused

三、案例:一次 liveness 误杀引发的重启风暴

背景:同事把 liveness 探针的检查端点配成了 /deepcheck——这个端点会连数据库、连缓存、连下游风控服务,任何一家抖动都返回 503。某天风控服务慢了两分钟,orders-api 全体副本被 liveness 判死重启,重启后又因启动期依赖未就绪继续被判死,雪崩成形。

操作:事故中的关键观察与修复步骤——

# 第一步:确认现象:三副本齐刷刷重启 kubectl get pods -n production -l app=orders-api # NAME READY STATUS RESTARTS AGE # orders-api-6d9f7c8b5-2vxk7 1/1 Running 5 18m # orders-api-6d9f7c8b5-9mjq4 1/1 CrashLoopBackOff 6 18m # orders-api-6d9f7c8b5-x3p2q 1/1 Running 5 18m # 第二步:改声明——liveness 只查进程自身,依赖健康交给 readiness # /healthz 只做进程内存自检,/ready 才去 ping 数据库与风控 # 第三步:提交修复后的声明 kubectl apply -f orders-deploy.yaml # deployment.apps/orders-api configured

结果:滚动替换完成后风暴停止。风控服务恢复前,副本因 readiness 失败被摘出流量名单,用户请求由其余就绪副本承接;进程本身不再被重启。

解读:这次事故的教训是一条铁律——liveness 只回答"进程是否需要重启",因此只查进程自身;一切外部依赖的健康问题属于"暂时不能接活",归 readiness 管。重启解决不了外部依赖的故障,只会把局部抖动放大成全局重启风暴。

变式:慢启动的老旧单体应用(启动要 90 秒)不配 startup 探针就会被 liveness 在 30 秒处误杀,正确做法是补 startup 探针并把容忍窗口设到 180 秒;TCP 型探针适合没有 HTTP 端口的中间件容器;exec 型探针能执行自定义脚本,但开销最大,留给前两者覆盖不了的场合。

⚠️ 常见坑:给所有容器照抄同一套探针参数。不同应用的启动速度、依赖数量、恢复能力差异很大,探针参数应当按应用画像定制,抄来的参数迟早变成误杀清单。

💡 关键直觉:readiness 是流量闸门,liveness 是复活按钮。拿闸门当按钮用(或反之),是生产环境探针事故的几乎全部来源。

本节要点回顾

  • 三种探针职权分明:startup 守启动、liveness 管重启、readiness 控流量,判负动作完全不同;
  • 参数即严厉度:failureThreshold 乘 periodSeconds 等于容忍窗口,反应速度与误杀风险成正比;
  • 端点设计铁律:liveness 只查进程自身,依赖健康归 readiness,混用必致重启风暴;
  • 端点摘除是滚动更新的底座:新副本过体检才进名单,服务才能不中断地换版本;
  • 事件流留有判罚记录:Unhealthy 事件标注探针类型与失败原因,是排障第一手证据。

至此,orders-api 的 3 个副本全部通过体检、进入就绪名单,声明完成了从纸面到运行的全程。但集群不会静止:节点会宕、版本要升、副本数要调。下一章看控制器如何守住这份声明——调和循环、自愈与滚动更新的机制全景。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U