在Kubernetes集群里,Pod运行状态看似正常却频繁重启,或者新副本一启动就被负载均衡转发请求然后报错,这类问题大多出在探针配置上。kubelet通过存活探针决定要不要重启容器,通过就绪探针决定要不要把Pod放进Service的可用端点列表。二者虽然都叫probe,但触发动作和适用阶段完全不同,混淆使用会直接引发业务中断。

探针底层工作机制与调度逻辑
kubelet是每个节点上的代理进程,它按照Pod spec里定义的周期,定期对容器执行探针检测。存活探针(livenessProbe)一旦连续失败次数达到failureThreshold,kubelet就会杀掉该容器,并依据restartPolicy决定是否重建。这意味着存活探针只应该检查“进程是否假死”,绝不能检查依赖服务是否可用,否则一个下游数据库抖动就会把上游容器全杀光。
就绪探针(readinessProbe)的失败则不会重启容器,而是将Pod的IP从Service的endpoint中移除。当探针恢复成功,kubelet会再次将其加回转发池。这个机制保证了流量只进到真正能处理的实例。在滚动更新时,新Pod若没配就绪探针,Service会立刻把流量切过去,而此时应用可能还在加载缓存,于是出现批量超时。
从调度视角看,就绪探针还影响Deployment的maxUnavailable和maxSurge计算。如果就绪探针迟迟不成功,新副本卡在NotReady,控制器就不会继续下线旧副本,导致发布停滞。因此initialDelaySeconds和periodSeconds的设置必须贴合应用的启动曲线,而不是拍脑袋写个10秒。
三类探针的配置方式与参数细节
Kubernetes支持exec、httpGet、tcpSocket三种探针模式。exec是在容器内执行命令,返回0为成功;httpGet是对容器指定端口发HTTP请求,2xx或3xx算通过;tcpSocket则是尝试建立TCP连接。对于Web服务,httpGet最直观,但要注意不能把探针路径写成需要鉴权的接口,否则永远401导致误判。
下面给出一个典型的Spring Boot服务配置,同时包含两种探针,且使用不同路径区分:
apiVersion: v1
kind: Pod
metadata:
name: demo-app
spec:
containers:
- name: app
image: ipipp.com/demo:latest
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 2
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
timeoutSeconds: 2
上面的YAML里,存活探针延迟30秒才开始,因为JVM冷启动加框架初始化可能要二十多秒;就绪探针延迟10秒,但业务线程池可能更晚就绪,所以实际中常把readiness路径背后逻辑做得更严格。timeoutSeconds设2秒,避免慢请求占用探针线程。failureThreshold为3,配合periodSeconds,意味着连续30秒或15秒不通才动作,能容忍短暂网络闪断。
tcpSocket适合无HTTP协议的服务,比如Redis客户端侧容器。但它只能证明端口开着,不能证明服务能响应命令,因此存活探针用tcp、就绪探针用exec去发ping更稳妥。exec示例:
readinessProbe:
exec:
command:
- sh
- -c
- redis-cli ping | grep PONG
initialDelaySeconds: 5
periodSeconds: 3
这段配置在容器内执行redis-cli ping,并过滤输出是否有PONG。如果Redis连不上,grep失败,命令返回非0,就绪探针失败,Pod不接流量。这种细粒度检查比单纯看端口更有意义。
常见误配场景与调优建议
最常见的错误是把同一个HTTP路径同时用于存活和就绪,并且把initialDelaySeconds设得极小。结果应用启动慢,探针在初始化完成前就失败,kubelet不断重启容器,容器永远起不来,形成CrashLoopBackOff。正确做法是利用Spring Boot Actuator之类的组件,暴露独立的liveness和readiness指标,前者只查内存死锁,后者查数据库连接池。
另一个坑是failureThreshold设成1。生产环境节点间偶发丢包很正常,一次探测超时就把容器干掉,会造成不必要的抖动。一般建议存活探针failureThreshold至少3,就绪探针可以稍敏感但也别为1。同时startupProbe在Kubernetes 1.16后可用来覆盖慢启动:在startupProbe成功前,存活和就绪都不生效,这样能把initialDelaySeconds从配置里解放出来。
还有人在就绪探针里调用外部API,比如检查第三方支付网关。一旦网关维护,所有Pod全部NotReady,Service endpoints清空,整个服务在集群内自我瘫痪。探针只能查自身依赖的本地健康度,跨系统链路健壮性应由熔断限流在代码层解决,而不是交给kubelet。理清边界,集群才稳。
最后提一个参数组合技巧:periodSeconds越小,故障发现越快,但API压力越大;对千实例规模的服务,periodSeconds设10比设2能省下数倍请求量。timeoutSeconds务必小于periodSeconds,否则一次慢探针会阻塞下一次调度,造成检测堆积。综合来看,存活探针偏保守、就绪探针偏灵敏,是大部分无状态服务的黄金准则。
Kubernetesliveness_probereadiness_probe修改时间:2026-08-17 21:56:31