Pod 挂了没人管?Kubernetes 探针教它自己判断生死

举报
海是岛思念的泪 发表于 2026/09/15 11:23:21 2026/09/15
【摘要】 三种探针的区别与配置方法,配合 YAML 示例和常见坑位,让 Pod 自己管理生死。

Kubernetes 调度 Pod 的逻辑很积极——容器崩了就拉起来,节点挂了就迁移。但有些情况它判断不了:进程还活着但死锁了,端口还在监听但连不上数据库,启动太慢被误杀又重启又太慢又误杀……探针就是让 Pod 自己告诉 K8s “我什么状态”。

image.png

1. 三种探针各管什么

探针 作用 失败后果 适合场景
Liveness 容器是否活着 重启 Pod 检测死锁、内存泄漏
Readiness 是否准备好接流量 从 Endpoints 摘除 等待依赖就绪、预热缓存
Startup 是否启动完成 重启 Pod(但先不跑 Liveness) 慢启动应用保护

三者最容易搞混的是 Liveness 和 Readiness。一个简单的区分方式:Liveness 失败会重启,Readiness 失败只是摘流量不重启。你的服务连不上数据库,应该用 Readiness——服务本身没坏,等数据库恢复就好,重启反而浪费时间。

image.png

Startup Probe 是后来加的,专门解决慢启动应用被 Liveness 误杀的问题。Java 应用启动动辄 60 秒,如果 Liveness 设的 initialDelaySeconds: 30,30 秒时还没起来就被判定为不健康,重启后又得重来,永远起不来。

2. 配置实战:一个 HTTP 服务的完整探针

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api-server
  template:
    metadata:
      labels:
        app: api-server
    spec:
      containers:
      - name: api
        image: registry.example.com/api:v2.1
        ports:
        - containerPort: 8080
        startupProbe:
          httpGet:
            path: /healthz
            port: 8080
          failureThreshold: 30
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          periodSeconds: 10
          failureThreshold: 3
          timeoutSeconds: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          periodSeconds: 5
          failureThreshold: 2
          timeoutSeconds: 2
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi

逐字段拆解:

  • startupProbe:每 5 秒探一次 /healthz,允许失败 30 次,也就是最多等 150 秒启动。通过后这个探针就不再执行。
  • livenessProbe:每 10 秒探一次,连续 3 次失败才重启,单次超时 3 秒。给网络抖动留了缓冲。
  • readinessProbe:每 5 秒探一次,2 次失败就摘流量。比 Liveness 更敏感,因为摘流量代价低。

3. 健康检查端点怎么写

探针指向的 HTTP 端点需要自己在应用里实现。一个常见的写法:

func registerHealth(mux *http.ServeMux, db *sql.DB, redis *redis.Client) {
    mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("ok"))
    })

    mux.HandleFunc("/ready", func(w http.ResponseWriter, r *http.Request) {
        ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
        defer cancel()

        if err := db.PingContext(ctx); err != nil {
            w.WriteHeader(http.StatusServiceUnavailable)
            return
        }
        if err := redis.Ping(ctx).Err(); err != nil {
            w.WriteHeader(http.StatusServiceUnavailable)
            return
        }
        w.WriteHeader(http.StatusOK)
    })
}

/healthz 只检查进程本身——能响应就说明没死锁。/ready 检查依赖——数据库和 Redis 都通才算就绪。这样数据库挂了,Pod 不会被重启(Liveness 通过),但流量会切到其他 Pod(Readiness 失败)。

4. TCP 探针和 Exec 探针

不是所有服务都有 HTTP 端口。TCP 探针适合数据库、消息队列这类服务:

livenessProbe:
  tcpSocket:
    port: 3306
  periodSeconds: 10
  failureThreshold: 3

Exec 探针适合跑脚本检查,比如看某个文件是否存在:

livenessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  periodSeconds: 5

Exec 探针的退出码 0 表示成功,非 0 表示失败。注意 Exec 探针会增加容器开销,每期都要 fork 一个进程,高频检查不建议用。

5. 常见坑位

现象 解决方案
Liveness 检查依赖 依赖挂了 Pod 不断重启 用 Readiness 检查依赖
initialDelaySeconds 太短 慢启动应用被误杀 改用 Startup Probe
探针端点太重 每次检查跑全量逻辑 /healthz 只返回 ok
没设 timeoutSeconds 探针请求卡住占资源 设 2-3 秒超时
failureThreshold = 1 网络抖动就重启 至少设 3,给缓冲
探针和业务共用端口 探针请求被限流 用单独的端口或管理端口

最后一个坑值得展开。有些团队把 /healthz 挂在业务端口上,然后给业务端口加了限流中间件(比如前面文章里的令牌桶)。压测时限流把探针请求也拦了,K8s 判掉所有 Pod,服务直接没了。解法是开一个管理端口(比如 8081),探针走那个端口,不经过限流。

containers:
- name: api
  ports:
  - containerPort: 8080   # 业务端口
  - containerPort: 8081   # 管理端口
  livenessProbe:
    httpGet:
      path: /healthz
      port: 8081           # 走管理端口

跑起来之后

  • kubectl describe pod <name> 看 Events 里的探针失败记录
  • 监控 kube_pod_container_status_restarts_total,重启次数飙升说明探针配置有问题
  • 金丝雀发布时把 Readiness 的 failureThreshold 调低,让坏版本更快被摘除
  • 探针端点不要做鉴权,K8s 不带你的 token
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。