Kubernetes 探针(Probe)详解与生产环境配置实践

AI 总结

Kubernetes探针包括存活、就绪和启动三类,分别负责容器重启、流量摘除和慢启动保护。探测方式有exec、httpGet和tcpSocket,需按场景选择。配置需结合启动窗口、周期、阈值等参数,Java服务常用tcpSocket三探针并给足启动时间,Vue前端用httpGet就绪探测。典型组合包括Spring Boot、MySQL、Nginx等。常见坑有用存活代替就绪、慢启动不配启动探针、探测方式不当、参数过严、就绪依赖外部服务。监控可关注kube_pod_probe_success等指标,排障需查看Events、日志并手动复现。

``# 一、三大探针分别管什么?
K8s 的探针本质是"服务健康状态的三层校验机制",三种探针职责不同、失败后果也不同:

探针管什么失败后果典型场景
livenessProbe(存活探针)容器是否活着restartPolicy重启容器死锁、OOM、进程假死
readinessProbe(就绪探针)容器是否能用从 Service Endpoints 摘除,不再收流量依赖未就绪、初始化未完成
startupProbe(启动探针)慢启动保护重启容器Java/Tomcat 启动 3 分钟以上的服务

一句话区分:liveness 管"生死",readiness 管"流量",startup 管"启动保护"。liveness 和 readiness 的失败后果不同——一个重启、一个摘流量,这俩别搞混。

startupProbe 比较特殊:它探测成功之前,liveness 和 readiness 都不会生效,所以它是专门给慢启动服务兜底的。

二、三种探测方式

方式原理适用场景局限
exec容器内执行命令,退出码 0 为正常复杂校验(依赖检查、文件存在性)依赖容器内装好命令(如 curl)
httpGet请求 HTTP/HTTPS 端点,状态码 200-399 为正常Web 服务,能校验业务端口可用性仅支持 HTTP(S) 协议
tcpSocket建 TCP 连接,连得上即正常数据库、Redis 等非 HTTP 服务只能判断端口存活,无法校验内部状态

选择原则:Web 服务优先 httpGet;端口监听类服务用 tcpSocket;需要复杂逻辑校验用 exec

三、探针参数与黄金法则

所有探针共用同一套参数:

参数含义推荐值
initialDelaySeconds容器启动后延迟多久开始探测略短于实际启动时间(如 Java 实际 40s 设 30-35s)
periodSeconds探测间隔liveness 10-15s,readiness 5-8s
timeoutSeconds单次探测超时httpGet/tcpSocket 1-3s,exec 2-5s
successThreshold连续成功多少次算恢复默认 1(readiness 滚动更新时也建议 1)
failureThreshold连续失败多少次算故障liveness 3-5 次,readiness 2-3 次
terminationGracePeriodSeconds失败后的优雅终止时间30-60s

startupProbe 的启动窗口 = failureThreshold × periodSeconds,必须覆盖服务最慢一次的启动时间。

四、应该怎么配置

4.1 Java 服务标配:tcpSocket 三探针

测试和生产的大多数 Java 服务(如 szzx 的 qjksh、infostat、wmyc)配置完全一致,参数带注释的版本如下(测试环境写注释、生产环境没写,参数一个不差):

# argocd-apps/application/szzx/qjksh/values.yaml(测试,生产同参数)
probe:
  enabled: true
  startupProbe:
    enabled: true
    httpGet: null
    tcpSocket:
      port: http              # 使用容器端口名称,自动引用 appConfig.port
    initialDelaySeconds: 60    # 容器启动后 60s 开始检查
    periodSeconds: 10          # 每 10s 检查一次
    failureThreshold: 30       # 最多允许失败 30 次,总计 60s + (10s * 30) = 360s
  # 存活探针:启动探针成功后接手,判断应用是否由于死锁等原因挂掉
  livenessProbe:
    enabled: true
    tcpSocket:
      port: http              # 使用容器端口名称
    initialDelaySeconds: 10    # 启动探针成功后,只需 10s 即可开始
    periodSeconds: 30
    timeoutSeconds: 10
    failureThreshold: 3
  # 就绪探针:启动探针成功后接手,判断应用是否可对外提供服务
  readinessProbe:
    enabled: true
    tcpSocket:
      port: http              # 使用容器端口名称
    initialDelaySeconds: 10    # 启动探针成功后,只需 10s 即可开始
    periodSeconds: 20          # 就绪检查稍快一些,以便及时摘除故障节点
    timeoutSeconds: 10
    successThreshold: 1
    failureThreshold: 3

这套配置的思路:

  • startupProbe 给足 360 秒窗口(60s + 10s×30):东方通/Tomcat 启动慢,最坏情况要 6 分钟,保证启动期间不被误杀。
  • liveness 用 tcpSocket 而非 httpGet:Java 服务端口起来就算活,避免业务层偶发 5xx 触发重启(这点文章里也强调了,liveness 探测条件要"轻量无副作用")。
  • readiness 周期比 liveness 短(20s vs 30s):故障时能更快把实例从 Service 摘掉,滚动发布时新 pod 就绪判定也更及时。
  • port: http 用的是容器端口名称,由模板自动引用 appConfig.port,不用写死端口号,改端口不用动探针。

4.2 Vue 前端服务:httpGet 探针

前端服务(nginx 容器)用 httpGet,因为 nginx 是纯 HTTP 服务,直接请求页面最实在:

# argocd-apps/application/sccg/market-vue/values.yaml(节选)
probe:
  enabled: true
  readinessProbe:
    enabled: true
    httpGet:
      path: ''                # path 留空,模板自动补 SPA 首页路径
      port: http
    initialDelaySeconds: 5
    periodSeconds: 10
    successThreshold: 1
    failureThreshold: 3
    timeoutSeconds: 3
  livenessProbe:
    enabled: true
    tcpSocket:
      port: http
    initialDelaySeconds: 15
    periodSeconds: 20
    failureThreshold: 3
    timeoutSeconds: 3
  startupProbe:
    enabled: true
    httpGet:
      path: ''
      port: http
    failureThreshold: 30
    periodSeconds: 10
    timeoutSeconds: 3

注意这里 liveness 反而是 tcpSocket——nginx 挂不挂看端口就行,httpGet 留给 readiness 判断页面能不能访问,两边分工明确。生产环境的 gzsw-ui 等 vue 服务配置和测试完全一致。

五、组合场景与 5 个坑

文章总结的典型组合:

场景组合关键参数
Spring Boot 微服务startup + liveness + readinessstartup 24×10s=240s;liveness initialDelay 60s;readiness period 5s
MySQLliveness + readinessliveness tcpSocket 3306;readiness exec mysqladmin ping
Nginxliveness + readinessliveness exec pgrep nginx;readiness httpGet /
依赖 MQ 的服务readiness + livenessreadiness 校验内部健康端点(含 MQ 连接),failureThreshold 2

5 个坑(对应到我们环境):
1. 用 liveness 代替 readiness → 启动中的实例被塞流量,直接 5xx。我们的配置里两探针职责分明,没这个毛病。
2. 慢启动服务不配 startupProbe → 启动慢的 Java 服务被 liveness 反复重启,起不来的同时疯狂消耗资源。我们全配了,startup 窗口 360s。
3. 探测方式不当(tcpSocket 校验 Web 服务)→ 端口通但页面 500 也照样"健康"。我们 Java 用 tcpSocket 是刻意为之(liveness 轻量优先),但 readiness 其实可以更严格,后续可以评估给核心服务上 httpGet 健康端点。
4. 参数过严(如 periodSeconds=2s)→ 探测本身占资源,还可能把抖动当故障。我们的参数都按黄金法则来。
5. readiness 依赖外部不稳定服务(跨集群 DB)→ 上游一抖,实例被反复摘除,流量雪崩。这条要警惕:readiness 探针里的依赖校验别连跨集群的外部服务。

六、监控告警与排障

文章给出的探针监控指标(kube-state-metrics 提供):

指标告警建议
kube_pod_probe_success{probe="liveness"}5 分钟成功率 <90% 告警
kube_pod_probe_success{probe="readiness"}5 分钟成功率 <80% 告警
kube_pod_probe_success{probe="startup"}启动后 3 分钟未成功告警
kube_pod_container_status_waiting_reason(ProbeFailed)持续 5 分钟以上告警
kube_pod_status_ready(0)持续 10 分钟以上告警

Grafana 可以直接导入官方 Dashboard "Kubernetes Pod Health"(ID 13105)。
排障流程(遇到探针失败时):

# 1. 看 Events,确认失败原因
kubectl describe pod <pod-name> -n <namespace>
#    关注 "Liveness probe failed: ..." / "Readiness probe failed: ..." 事件

# 2. 看日志,排查崩溃或依赖连接问题
kubectl logs --tail=100 <pod-name> -n <namespace>

# 3. 手动执行探测命令,复现问题
kubectl exec -it <pod-name> -n <namespace> -- curl -v http://127.0.0.1:8080/actuator/health

# 4. 确认是参数问题还是业务问题,再决定调整探针还是修业务

七、注意事项

  • probe.enabled 是总开关:values.yaml 里三个探针都配了但总开关是 false,一样不生效(测试 kjds base-service 就是这个状态,光看 probe 段容易误判)。
  • httpGet.path 留空:vue chart 模板会自动补 SPA 路径;其他 chart 透传,path 留空会请求 /
  • tcpSocket 探针的边界:端口通不代表业务健康,核心服务建议上 httpGet + 业务健康端点(如 Spring Boot Actuator),端点必须轻量、耗时 <1s。
  • 探针不是越多越好:核心是"精准校验",在探测准确性和资源消耗之间取平衡。
  • 测试环境探针状态和生产不一致:kjds 测试环境 13 个服务探针全关是我拉长探针参数时一起处理的,这类差异会掩盖测试环境的问题表现——测试环境没探针意味着 pod 挂了不重启、流量照常打到坏实例,排障时看不到探针事件。

评论 (0)