Kubernetes 基础体系 · 第 20/83 篇。示例基于 Kubernetes 当前稳定 API;弃用、版本偏差、云厂商差异和生产风险会明确说明。
Kubernetes Probe:Startup、Readiness、Liveness、gRPC 和误配置风险
Kubernetes Probe 是 kubelet 对容器执行的健康检查。它不是一个抽象的“应用健康”标签,而是一组会直接影响容器重启、Pod 是否接收 Service 流量以及应用启动流程的控制机制。
Probe 主要解决三个不同问题:
- Startup Probe:应用是否已经完成启动?
- Readiness Probe:应用现在是否可以接收流量?
- Liveness Probe:应用是否仍然处于需要继续运行的状态?
此外,Kubernetes 还支持使用 HTTP、TCP、命令和 gRPC 作为探测方式。探测方式相同,并不意味着语义相同:一个 HTTP 探针可以用于启动检查、就绪检查或存活检查,而它们失败后的处理完全不同。
1. Probe 在 Kubernetes 中处于什么位置
Pod 中的每个容器由 kubelet 管理。kubelet 根据容器状态和 Probe 结果,更新本机保存的容器状态,并通过控制面反映出 Pod 的部分状态。
简化后的路径如下:
flowchart LR
K[kubelet] --> P[Probe worker]
P --> C[容器端点或进程]
C --> R[探测结果]
R --> K
K -->|Startup 失败达到阈值| X[停止并重启容器]
K -->|Liveness 失败达到阈值| X
K -->|Readiness 失败| CS[ContainerStatus.ready=false]
CS --> PC[Pod Ready Condition=false]
PC --> ES[EndpointSlice ready=false]
ES --> S[Service 流量选择]
这里有几个重要边界:
- Probe 由 kubelet 执行,不是由 API Server 执行。
- HTTP、TCP 和 gRPC 探针通常从 Pod 所在节点发起,不能把它们等同于“从集群外部访问应用”。
- Readiness 结果会影响 Service 的后端选择,但不会让 Pod 进入
FailedPhase。 - Liveness 或 Startup 失败会触发容器重启,但通常不会直接删除整个 Pod。
- Pod 的整体状态还受到
restartPolicy、调度、驱逐、终止流程等机制影响,不能仅凭 Probe 判断 Pod 的Phase。
1.1 容器就绪、Pod 就绪和 Service 后端不是同一个概念
容器状态中的:
status:
containerStatuses:
- name: app
ready: true
表示该容器最近一次 Readiness 判定为成功。
Pod 的 Ready Condition 通常要求 Pod 中所有需要就绪的容器都满足条件。若配置了额外的 Pod Readiness Gate,还需要这些条件也为 True。
Service 使用 EndpointSlice 选择后端时,通常依据端点的 ready 状态。于是存在这样的故障路径:
应用进程仍在运行
↓
Readiness Probe 失败
↓
containerStatuses[].ready=false
↓
Pod Ready Condition=false
↓
EndpointSlice.ready=false
↓
Service 不再把新连接发给该 Pod
这与下面的路径不同:
应用进程失去响应
↓
Liveness Probe 连续失败
↓
kubelet 停止容器
↓
按 restartPolicy 尝试重启容器
Readiness 是“暂时不要给我流量”,Liveness 是“这个进程需要被恢复”。
2. 三种 Probe 的完整语义
2.1 Startup Probe:启动阶段的保护门
Startup Probe 用来判断容器中的应用是否已经完成启动。只要配置了 Startup Probe,在它第一次成功之前,kubelet 不会执行该容器的 Liveness Probe 和 Readiness Probe。
状态过程可以表示为:
容器启动
↓
Startup Probe 执行
├─ 失败:累计失败次数,达到 failureThreshold 后重启容器
└─ 成功:Startup 阶段结束
↓
开始执行 Liveness 和 Readiness
因此,Startup Probe 并不是“又一种 Liveness Probe”。它的关键作用是把慢启动时间从 Liveness 的检测窗口中隔离出来。
没有 Startup Probe 时,慢启动应用可能在初始化期间被 Liveness 杀死:
容器启动
↓ 10 秒
第一次 Liveness 检查失败
↓
连续失败达到阈值
↓
容器被重启
↓
应用永远无法完成启动
配置 Startup Probe 后,Liveness Probe 在启动成功前不会干扰应用:
startupProbe:
httpGet:
path: /startup
port: 8080
periodSeconds: 5
failureThreshold: 24
livenessProbe:
httpGet:
path: /live
port: 8080
periodSeconds: 10
failureThreshold: 3
在名义配置下,Startup Probe 给应用约 24 × 5 = 120 秒的探测窗口。实际失败确认时间还受首次探测时机、探测耗时和 kubelet 调度影响,因此不能把这个乘积当作严格的墙上时钟保证。
Startup Probe 成功后,失败计数不会继续阻塞其他 Probe;之后如果 Liveness 失败,仍然会触发重启。
2.2 Readiness Probe:是否接收流量
Readiness Probe 表示容器是否具备处理业务请求的条件。Readiness 失败时,kubelet 不会重启容器,而是将容器标记为未就绪。
典型场景包括:
- 应用仍在加载模型或缓存;
- 依赖的数据库、配置中心或密钥服务暂时不可用;
- 应用正在排空连接,准备退出;
- 过载保护被触发;
- 实例仍然存活,但不应该接收新的业务请求。
例如:
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 2
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 2
successThreshold: 2
这里要求连续两次成功后才重新就绪,连续两次失败后才变为未就绪。successThreshold 对 Readiness 可以大于 1;对 Startup 和 Liveness 必须为 1。
Readiness 失败的结果不是“Pod 被删除”,也不是“容器被重启”。如果所有副本都因为错误的 Readiness Probe 失败,Service 可能暂时没有可用后端,但容器仍全部运行着。
这正是误配置很危险的原因:系统可能没有崩溃,却完全无法接收流量。
2.3 Liveness Probe:是否需要重启容器
Liveness Probe 用来发现进程仍然存在、但已经无法继续提供服务的情况,例如:
- 事件循环死锁;
- 内部线程池永久卡死;
- 应用陷入无法自行恢复的状态;
- 进程没有退出,但关键处理路径已经失效。
Liveness 失败达到 failureThreshold 后,kubelet 会停止容器,并根据 Pod 的 restartPolicy 处理后续重启。对于常见的 Deployment,Pod 通常使用 restartPolicy: Always,因此容器会被重新启动。
livenessProbe:
httpGet:
path: /live
port: 8080
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
Liveness 不应检查所有业务依赖。例如:
数据库暂时不可用
通常更适合让 Readiness 失败,因为应用进程本身可能仍然能够恢复,重启反而会:
- 让正在处理的请求中断;
- 增加数据库重连压力;
- 触发多个副本同时重启;
- 在依赖恢复前形成重启循环。
但如果应用明确设计为“没有数据库就无法恢复”,并且重启确实是恢复动作,才有理由把这类条件纳入 Liveness。这是应用恢复语义,而不是 Kubernetes 自动推导出的结论。
3. Probe 的执行模型和参数
Probe 的主要参数如下:
| 参数 | 含义 |
|---|---|
initialDelaySeconds |
容器启动后,首次探测前等待的秒数 |
periodSeconds |
两次探测之间的目标间隔 |
timeoutSeconds |
单次探测超时时间 |
successThreshold |
从失败恢复为成功所需的连续成功次数 |
failureThreshold |
从成功变为失败所需的连续失败次数 |
terminationGracePeriodSeconds |
该 Probe 触发容器终止时使用的终止宽限期,版本需确认 |
其中,failureThreshold 不是“失败一次就重启”的开关,而是连续失败判定所需的次数。名义上的失败确认时间可以近似理解为:
变量含义:
- :首次探测开始前的等待时间,通常受
initialDelaySeconds影响; - :
failureThreshold; - :
periodSeconds; - :最后一次探测耗时,最多接近
timeoutSeconds。
这个公式表达的是推导直觉,而不是严格实时保证。kubelet 还会受到探测执行时间、节点负载、容器运行时和调度时序影响。
例如:
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
如果首次检查立即开始,且每次失败都在 2 秒超时,那么大致会经历:
t=0:第 1 次失败
t≈10:第 2 次失败
t≈20:第 3 次失败
t≈22:完成第 3 次超时,确认失败
如果 initialDelaySeconds: 30,则整体时间大致再增加 30 秒。实际时序应通过 kubelet 事件和容器状态验证,而不能依赖手算值进行精确告警。
3.1 默认值会造成隐含行为
常见字段默认值包括:
periodSeconds默认 10 秒;timeoutSeconds默认 1 秒;failureThreshold默认 3;successThreshold默认 1;initialDelaySeconds默认 0。
timeoutSeconds: 1 对本地 HTTP 端点可能足够,但对于以下端点可能过短:
- JVM 第一次触发较长 Stop-The-World;
- 需要加锁的复杂健康检查;
- 节点 CPU 被严重限制;
- gRPC 服务端偶发排队;
- 探针访问路径包含不必要的外部依赖。
增加超时时间只能解决“合理的短暂延迟”,不能掩盖长期阻塞。否则探针本身会占用资源,且失败确认会变慢。
3.2 探针成功和失败如何定义
不同探测方式的成功条件不同:
- HTTP:通常返回 HTTP
200到399的状态码视为成功; - TCP:能够建立连接视为成功;
- Exec:在容器内执行命令,退出码为 0 视为成功;
- gRPC:调用标准 gRPC Health Checking Protocol,服务状态为
SERVING视为成功。
HTTP 响应体通常不会被用来判断业务内容是否正确。若接口返回 HTTP 200,但 JSON 中表示数据库已经不可用,Probe 仍可能被判断为成功。因此健康端点应明确设计返回码和检查范围。
4. HTTP Probe:最常用,但也最容易误配
一个完整的 HTTP Probe 示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: probe-demo
spec:
replicas: 1
selector:
matchLabels:
app: probe-demo
template:
metadata:
labels:
app: probe-demo
spec:
containers:
- name: app
image: nginx:1.27
ports:
- name: http
containerPort: 80
readinessProbe:
httpGet:
path: /
port: http
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 3
livenessProbe:
httpGet:
path: /
port: http
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
应用配置:
kubectl apply -f probe-demo.yaml
kubectl get pods -l app=probe-demo -w
预期可以看到 Pod 最终类似:
NAME READY STATUS RESTARTS AGE
probe-demo-xxxxxxxxxx-xxxxx 1/1 Running 0 30s
这里:
port: http使用容器端口的名称;- kubelet 从节点访问 Pod IP 的 80 端口;
/返回 2xx,因此两个 Probe 都成功;- 如果 Nginx 仍在运行但
/返回 500,Readiness 会失败,Liveness 也最终可能触发重启。
4.1 HTTP Probe 的地址和请求属性
HTTP 探针可以配置:
httpGet:
scheme: HTTP
host: 127.0.0.1
port: 8080
path: /ready
httpHeaders:
- name: X-Probe
value: kubernetes
需要区分:
port是容器网络命名空间中可访问的端口;host是目标主机名,通常不应随意填写 Service 名称;path必须与应用实际路由一致;scheme: HTTPS要求端点支持 TLS;- 自定义 Header 可用于区分探针请求,但不应把长期有效的敏感凭据直接写入 Pod YAML。
如果应用根据 Host Header 选择虚拟主机,必须确认 kubelet 发送的 Host 是否符合应用要求。不要为了绕过路由而把生产认证 Token 放在 Probe 配置中,因为它会出现在 Pod 对象及其审计、备份或调试输出中。
4.2 常见 HTTP 误配置
端口写成 Service 端口
假设 Service 是:
ports:
- port: 80
targetPort: 8080
容器实际监听 8080。Probe 应访问:
httpGet:
port: 8080
而不是根据 Service 的 port: 80 填 80。Probe 直接访问 Pod,不经过 Service 的端口转换。
服务只监听 127.0.0.1
如果进程只监听回环地址:
127.0.0.1:8080
而不是:
0.0.0.0:8080
节点通过 Pod IP 访问时可能无法建立连接。应用内部用 curl localhost:8080 成功,不代表 kubelet 的 HTTP Probe 成功。
依赖 Ingress 或外部 DNS
Probe 访问 Pod IP,不会自动经过 Ingress、外部负载均衡器或公网 DNS。把 /healthz 配置成必须经过网关鉴权、Host 路由或外部证书链的地址,容易导致“应用本身正常,但 Probe 路径不通”。
5. TCP Probe:只证明“端口能接受连接”
TCP Probe 的配置很简单:
readinessProbe:
tcpSocket:
port: 5432
periodSeconds: 5
timeoutSeconds: 1
它只做 TCP 连接建立检查。成功意味着:
从探测端能够连接到目标端口
它不证明:
- 数据库能执行查询;
- HTTP 服务路由正确;
- gRPC 服务状态为
SERVING; - 应用能够处理业务请求;
- 端口背后的服务没有死锁。
因此 TCP Probe 适合检查“端口是否已经监听”的早期条件,或者某些没有健康检查协议的简单服务。对数据库这类服务,TCP 成功而查询失败是完全可能的。
一个典型反例:
应用进程启动
↓
先 bind(8080)
↓
后台线程还未加载配置
↓
TCP Probe 成功
↓
Service 开始发送流量
↓
HTTP 请求全部返回 503
如果业务需要“已经可以服务”,HTTP、gRPC 或 Exec 检查通常更能表达真实条件。
6. Exec Probe:表达力强,但成本和安全边界更复杂
Exec Probe 在容器内执行命令:
readinessProbe:
exec:
command:
- /bin/sh
- -c
- test -f /tmp/application-ready
periodSeconds: 5
timeoutSeconds: 1
应用在完成初始化后创建文件:
touch /tmp/application-ready
命令退出码为 0 时,探针成功;非 0 时失败。
Exec 的优点是可以检查容器内部状态,例如:
- 本地 UNIX Socket;
- 本地文件;
- 进程内部生成的状态;
- 没有网络端点的应用。
但它有三个重要风险:
- 每次检查都要创建进程,频率高时会增加 CPU 和 PID 压力;
- 命令依赖镜像中的 Shell、工具和路径;
- 如果命令包含秘密、复杂替换或不安全输入,可能引入安全问题。
下面的配置在精简镜像中经常失败:
exec:
command: ["sh", "-c", "curl -f http://127.0.0.1:8080/ready"]
原因不是应用一定不健康,而是镜像可能没有 sh 或 curl。应在目标镜像中验证:
kubectl exec deploy/probe-demo -- sh -c 'command -v curl'
生产配置应尽量使用稳定、短小、无副作用的命令,避免在 Probe 中执行数据库迁移、缓存清理或其他会改变系统状态的操作。
7. gRPC Probe:检查标准健康服务,不是任意 RPC
Kubernetes 原生 gRPC Probe 使用 gRPC Health Checking Protocol。它不是向任意业务 RPC 发请求,也不是把 HTTP/2 端口当作“能连通就算成功”。
典型配置:
startupProbe:
grpc:
port: 9090
service: my.api.v1.Application
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 30
readinessProbe:
grpc:
port: 9090
service: my.api.v1.Application
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 2
livenessProbe:
grpc:
port: 9090
service: my.api.v1.Application
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
应用必须实现标准健康检查服务:
grpc.health.v1.Health/Check
调用时的 service 字符串由应用定义。若 service 省略,通常检查整体服务器状态;若填写,则检查指定逻辑服务。应用需要返回标准状态,例如:
SERVING:Probe 成功;NOT_SERVING:Probe 失败;SERVICE_UNKNOWN:通常表示指定服务没有健康状态;- RPC 错误或无法连接:Probe 失败。
7.1 gRPC Probe 的限制
原生 gRPC Probe 的配置能力比“用 grpcurl 自己执行命令”更有限:
port使用数字端口;- 不能像 HTTP Probe 那样指定 HTTP Header;
- 不能配置用户名、密码或 Bearer Token;
- 不能直接配置 TLS 证书、SNI 或客户端证书;
- 不适合依赖复杂鉴权流程的健康端点;
- 应用必须支持标准 gRPC Health Checking Protocol。
因此,下面这种理解是错误的:
gRPC 端口能建立 TCP 连接,所以 gRPC Probe 一定成功
实际过程至少是:
kubelet 建立 gRPC 连接
↓
调用标准 Health/Check RPC
↓
解析 gRPC 健康状态
↓
只有 SERVING 才判定成功
如果服务启用了 mTLS,而 Kubernetes 内置 gRPC Probe 无法提供客户端证书,就可能无法直接使用原生 gRPC Probe。此时可以考虑:
- 暴露一个适合节点探测的独立健康端点;
- 使用带有必要 TLS 配置的 Exec Probe;
- 调整应用的健康服务设计,但必须评估暴露面和认证边界。
Exec 方案示例:
readinessProbe:
exec:
command:
- /usr/local/bin/grpc-health-probe
- -addr=127.0.0.1:9090
- -service=my.api.v1.Application
periodSeconds: 5
timeoutSeconds: 3
这不是 Kubernetes 原生 gRPC Probe,而是容器内的外部工具。它的版本、参数、TLS 行为和退出码都必须由镜像维护者验证,不能把两者混为一谈。
7.2 gRPC 健康状态应由应用明确维护
gRPC 健康服务返回 SERVING 并不自动意味着所有业务依赖都正常。应用需要决定各服务名对应的状态。例如:
整体服务:SERVING
写入服务:NOT_SERVING
读取服务:SERVING
如果写入服务依赖的数据库不可用,那么 Readiness Probe 可以检查写入服务名;而只提供只读能力的实例仍可能对读取流量保持就绪。
这比简单检查“gRPC 端口是否开放”更精确,但也要求应用正确更新 Health 状态。健康服务本身实现错误,会把业务故障转化为错误的调度和流量结果。
8. Startup、Readiness、Liveness 的组合规则
推荐先明确三种状态,再决定是否复用端点:
| 状态 | 需要回答的问题 | 失败后的主要动作 |
|---|---|---|
| Startup | 初始化是否完成? | 达到失败阈值后重启容器 |
| Readiness | 现在是否应该接收流量? | 从可用后端中移除,不重启 |
| Liveness | 进程是否需要被恢复? | 达到失败阈值后重启容器 |
端点可以相同,但语义必须不同。最危险的复用方式是:
同一个端点检查数据库、缓存、配置中心和外部 API
同时用于 Readiness 和 Liveness
当外部依赖短暂故障时,可能发生:
外部依赖故障
↓
Readiness 失败:实例被摘流
↓
Liveness 也失败:实例被重启
↓
所有副本同时重连外部依赖
↓
外部依赖压力更大
↓
重启和故障互相放大
更稳妥的逻辑通常是:
Startup:确认进程初始化完成,允许较慢
Readiness:确认当前可以接收业务流量,可包含必要依赖
Liveness:只检查进程是否仍有合理的自我恢复能力
但这不是强制规范。实际划分取决于应用能否从依赖故障中自行恢复。
9. 终止、重启和 Probe 的关系
当 Liveness 或 Startup 失败达到阈值时,kubelet 会终止容器。容器终止可能经过:
- 发送终止信号;
- 等待终止宽限期;
- 超时后发送强制终止信号;
- 根据
restartPolicy启动新容器。
Pod 级别的 spec.terminationGracePeriodSeconds 控制默认终止宽限期。较新的 Kubernetes API 还支持在 Probe 级别设置 terminationGracePeriodSeconds,用于覆盖该容器因 Probe 失败而终止时的宽限期;使用前应确认集群版本和 API Server 是否支持该字段。
不要把 Probe 失败与优雅下线混为一谈。应用收到终止信号后,通常应:
- 停止接受新请求;
- 让现有请求完成或超时;
- 更新 Readiness,使实例尽快摘流;
- 关闭连接和资源。
如果只依赖 Liveness 失败触发重启,应用可能先被强制终止,导致请求丢失。发布或主动删除 Pod 时,Readiness、EndpointSlice 更新和终止宽限期共同决定排空效果。
10. 误配置风险:从 YAML 到故障的完整路径
10.1 把启动时间当成固定延迟
错误配置:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3
假设应用启动有时需要 30 秒。初始延迟只是“首次检查前等待”,不是“禁用检查直到应用一定完成”。如果应用在第 10 秒仍未监听端口,连续失败后可能在应用真正启动前就被重启。
改进方式是使用 Startup Probe:
startupProbe:
httpGet:
path: /startup
port: 8080
periodSeconds: 5
failureThreshold: 12
livenessProbe:
httpGet:
path: /live
port: 8080
periodSeconds: 10
failureThreshold: 3
Startup 允许启动阶段最多经历约 60 秒的名义失败窗口,成功后才开始执行 Liveness。
10.2 把业务依赖放进 Liveness
错误现象:
数据库出现短暂网络故障
↓
/health 返回 500
↓
Liveness 连续失败
↓
所有副本重启
↓
数据库恢复时收到大量重连
诊断时应比较:
kubectl describe pod <pod-name>
kubectl get pod <pod-name> -o wide
kubectl logs <pod-name> --previous
kubectl get endpointslice -l kubernetes.io/service-name=<service-name> -o yaml
重点观察:
- Events 中是否有
Liveness probe failed; RESTARTS是否持续增加;--previous中是否存在被终止前的日志;- EndpointSlice 中端点是否
ready: false; - 所有副本是否在相近时间重启。
如果应用只是暂时不能处理业务,优先让 Readiness 失败,而不是立即重启。
10.3 探针路径需要认证
应用把所有 HTTP 路由都置于认证中间件之后:
GET /ready → 401 Unauthorized
即使应用完全正常,HTTP Probe 也会失败。解决方式不是把认证失败视为健康,而是提供明确的内部健康路由,并通过网络策略、监听地址或专用端口限制访问。
同时,健康路由不能泄露:
- 数据库密码;
- 内部拓扑;
- 详细堆栈;
- 用户数据;
- 外部依赖的敏感错误信息。
10.4 Probe 自身消耗大量资源
如果 Probe 执行一次会:
- 扫描大量文件;
- 访问多个远程依赖;
- 执行复杂 SQL;
- 启动大型命令;
- 分配大量对象;
那么检查本身可能成为负载来源。尤其当每个 Pod 有多个 Probe,且副本数量较大时,节点上的探针开销会叠加。
健康检查应当短小、有限、幂等,并且对超时有明确处理。Readiness 可以比 Liveness 检查更多业务条件,但仍不应变成完整业务交易。
11. 如何验证 Probe,而不是只看 Pod 是否 Running
11.1 查看配置和事件
kubectl describe pod <pod-name>
重点查看:
Readiness probe failed: HTTP probe failed with statuscode: 503
Liveness probe failed: dial tcp ...: connect: connection refused
Startup probe failed: command timed out
这些信息可以区分:
- 端口未监听;
- 路径不存在;
- 返回码不在成功范围;
- 命令不存在;
- 命令超时;
- gRPC 服务状态不是
SERVING。
查看原始对象,确认实际生效字段:
kubectl get pod <pod-name> -o yaml
kubectl get deployment <deployment-name> -o yaml
不要只看本地文件,因为 Deployment 滚动更新期间,旧 Pod 和新 Pod 可能使用不同配置。
11.2 从容器内测试应用端点
HTTP:
kubectl exec <pod-name> -- sh -c \
'wget -S -O - http://127.0.0.1:8080/ready'
如果镜像没有 wget,可以使用临时调试容器或应用自带工具。测试 127.0.0.1 只能验证容器内部访问;还应确认 Pod IP 路径:
kubectl get pod <pod-name> -o wide
在具备网络工具的调试容器中访问 Pod IP,才能更接近 kubelet 的网络路径。
注意:kubectl exec 进入容器后测试成功,不一定说明 Probe 成功,因为两者可能有不同的:
- 网络源地址;
- DNS 配置;
- 用户权限;
- 环境变量;
- 文件系统;
- TLS 和 Host Header。
11.3 查看重启和历史日志
kubectl get pod <pod-name> \
-o jsonpath='{range .status.containerStatuses[*]}{.name}{" restart="}{.restartCount}{" ready="}{.ready}{" state="}{.state}{"\n"}{end}'
如果容器已经重启:
kubectl logs <pod-name> -c <container-name> --previous
--previous 对诊断 Probe 引起的重启尤其重要,因为当前容器日志可能只显示“重新启动后正常运行”的内容。
11.4 验证 Service 是否仍有可用端点
kubectl get endpointslice \
-l kubernetes.io/service-name=<service-name> -o yaml
检查端点的:
conditions:
ready: false
这可以证明 Readiness 失败已经影响到 Service 后端选择。但不同 Service 实现、代理模式和流量来源可能有额外行为,不能用单个客户端连接结果替代 EndpointSlice 状态验证。
12. 一个带错误场景的可运行演示
先部署一个故意会失败 Readiness 的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: probe-failure-demo
labels:
app: probe-failure-demo
spec:
containers:
- name: web
image: nginx:1.27
readinessProbe:
httpGet:
path: /does-not-exist
port: 80
periodSeconds: 3
timeoutSeconds: 1
failureThreshold: 2
执行:
kubectl apply -f probe-failure-demo.yaml
kubectl get pod probe-failure-demo -w
kubectl describe pod probe-failure-demo
预期现象类似:
NAME READY STATUS RESTARTS AGE
probe-failure-demo 0/1 Running 0 15s
这个结果说明:
- Nginx 进程仍在运行,所以
STATUS仍可能是Running; /does-not-exist返回 404;- Readiness 失败,因此
READY是0/1; - 因为没有 Liveness Probe,所以不会因为该失败自动重启;
- 若把它放入 Service,通常不会作为就绪后端接收新流量。
再检查事件:
kubectl describe pod probe-failure-demo
应能看到 HTTP Probe 失败相关事件。修正路径为 /:
kubectl patch pod probe-failure-demo --type='json' \
-p='[{"op":"replace","path":"/spec/containers/0/readinessProbe/httpGet/path","value":"/"}]'
对于生产工作负载,不建议直接修改由 Deployment 管理的 Pod;应修改 Deployment 清单后重新发布。这个演示的价值在于区分:
进程运行 ≠ 容器就绪 ≠ Service 可路由
13. 设计健康端点时必须先回答的边界问题
13.1 /live 应该检查什么
Liveness 端点应尽量检查进程本身是否仍能完成最基本的工作。例如:
- 主事件循环是否可响应;
- 核心线程是否仍在工作;
- 应用内部是否进入明确的不可恢复状态。
它不必验证每个下游服务,也不应执行大型业务请求。
13.2 /ready 应该检查什么
Readiness 端点应检查“接收流量后是否能够提供承诺的服务”。检查内容取决于流量类型:
- 读请求可能只需要缓存和只读数据库;
- 写请求可能需要主数据库;
- 消费者可能需要队列连接;
- 分片服务可能需要当前分片分配完成;
- 发布期间可能需要确认新版本已经加载配置。
如果同一 Pod 承担不同流量类型,可以使用不同的 gRPC service 名称或不同的 HTTP 路径表达不同就绪条件。
13.3 /startup 应该检查什么
Startup 端点应回答初始化是否完成,而不是要求所有运行时依赖永久正常。它可以检查:
- 配置是否加载;
- 必需的本地资源是否准备好;
- 模型是否加载完成;
- 监听服务是否启动;
- 应用是否已完成不可跳过的初始化。
Startup 成功后,运行时依赖的变化应主要由 Readiness 和应用自身恢复逻辑处理。
14. 版本和实现边界
Kubernetes Probe 的核心字段属于稳定 API,但具体能力仍需要结合集群版本确认。
- 原生 gRPC Probe 在较新的 Kubernetes 版本中已稳定;生产环境应确认控制面和节点版本,而不是只看客户端
kubectl版本。 - gRPC Probe 需要应用实现标准 gRPC Health Checking Protocol,不能由 Kubernetes 自动把任意 RPC 转换为健康检查。
- Probe 级别的
terminationGracePeriodSeconds属于较新的能力,旧集群可能拒绝该字段或不按预期处理;应通过目标集群的 API 校验和实际 Pod 行为验证。 - 云厂商的 Service、负载均衡器、健康检查和节点网络实现可能增加额外探测,但不能假设云负载均衡器的健康检查会替代 kubelet Probe。
kubectl是客户端工具,kubectl get pod显示的是 API Server 中的状态快照;探测的实际执行者仍是节点上的 kubelet。
检查集群版本:
kubectl version
kubectl api-resources
kubectl explain pod.spec.containers.readinessProbe
kubectl explain pod.spec.containers.livenessProbe
kubectl explain pod.spec.containers.startupProbe
kubectl explain 显示的是当前客户端或其 OpenAPI 信息可见的字段,最终能否被集群接受仍应以目标 API Server 验证为准。
15. 归纳:用失败后的动作反推 Probe 类型
可以用一个简单的决策过程避免把 Probe 配错:
应用正在启动,但启动时间不可预测?
→ Startup Probe
应用还活着,但现在不能接收请求?
→ Readiness Probe
应用已进入无法自行恢复的状态,重启是恢复手段?
→ Liveness Probe
只需要确认端口正在监听?
→ TCP Probe
需要检查容器内文件或进程状态?
→ Exec Probe
服务使用标准 gRPC Health Checking Protocol?
→ gRPC Probe
最终应验证的不是“YAML 能否通过校验”,而是故障路径是否符合预期:
启动变慢时:不会被过早重启
依赖短暂故障时:会摘流,而不是盲目重启
进程死锁时:最终会被恢复
发布终止时:会先停止接收新流量
端口可连接但业务不可用时:Probe 不会错误地报告成功
Probe 是 Kubernetes 工作负载稳定性控制面的一部分。它连接了应用内部状态、kubelet 的容器管理、Pod Ready Condition、EndpointSlice 和 Service 流量选择。只有明确区分 Startup、Readiness 和 Liveness 的因果语义,再选择与应用协议匹配的 HTTP、TCP、Exec 或 gRPC 检查方式,健康检查才不会从故障隔离工具变成故障放大器。
系列导航与关联阅读
- 系列入口:Kubernetes 完整学习路线:从 Pod 与控制面到安全、运维和 Operator
- 上一篇:Job 与 CronJob:并行、重试、补跑、时区、幂等和清理
- 下一篇:Kubernetes Resource 与 QoS:Request、Limit、CPU Throttle、OOM 和 Eviction
- 延伸:Pod 生命周期:Phase、Condition、RestartPolicy、终止和 Eviction
- 延伸:Kubernetes 生产就绪检查:架构、安全、容量、观测、发布和运行手册
官方资料
本文依据 Kubernetes、CNCF 与相关项目官方文档重新梳理;正文和生产清单由 WR BLOG 编写。

评论
0 条讨论