Kubernetes 探针完全指南:健康检查机制深度解析

Kubernetes 探针完全指南:健康检查机制深度解析

本文深入剖析 Kubernetes 三种探针(livenessProbe、readinessProbe、startupProbe)的核心技术,涵盖探针架构设计、配置方式详解、探测机制原理、YAML 字段说明,以及生产环境最佳实践。掌握探针是确保应用高可用的关键一步。


目录

  1. 为什么需要探针?
  2. 三种探针详解
  3. 探测方式详解
  4. 探针配置参数
  5. 探针与生命周期
  6. 实战:生产级探针配置
  7. 常用命令速查
  8. 最佳实践与避坑指南

一、为什么需要探针?

1.1 没有探针的问题

问题 说明 后果
假健康 容器运行但应用未就绪 流量发送到未就绪实例
死锁 进程存在但无法响应 请求超时、服务不可用
慢启动 应用启动需要时间 过早接收流量导致失败
资源泄漏 应用异常但进程不退出 内存耗尽、节点崩溃

1.2 探针的价值

#mermaid-svg-PNWTaJ0G3Q4pq1rs{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .error-icon{fill:#552222;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .marker.cross{stroke:#333333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs p{margin:0;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .cluster-label text{fill:#333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .cluster-label span{color:#333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .cluster-label span p{background-color:transparent;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .label text,#mermaid-svg-PNWTaJ0G3Q4pq1rs span{fill:#333;color:#333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .node rect,#mermaid-svg-PNWTaJ0G3Q4pq1rs .node circle,#mermaid-svg-PNWTaJ0G3Q4pq1rs .node ellipse,#mermaid-svg-PNWTaJ0G3Q4pq1rs .node polygon,#mermaid-svg-PNWTaJ0G3Q4pq1rs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .rough-node .label text,#mermaid-svg-PNWTaJ0G3Q4pq1rs .node .label text,#mermaid-svg-PNWTaJ0G3Q4pq1rs .image-shape .label,#mermaid-svg-PNWTaJ0G3Q4pq1rs .icon-shape .label{text-anchor:middle;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .rough-node .label,#mermaid-svg-PNWTaJ0G3Q4pq1rs .node .label,#mermaid-svg-PNWTaJ0G3Q4pq1rs .image-shape .label,#mermaid-svg-PNWTaJ0G3Q4pq1rs .icon-shape .label{text-align:center;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .node.clickable{cursor:pointer;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .arrowheadPath{fill:#333333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PNWTaJ0G3Q4pq1rs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PNWTaJ0G3Q4pq1rs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PNWTaJ0G3Q4pq1rs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .cluster text{fill:#333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .cluster span{color:#333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PNWTaJ0G3Q4pq1rs rect.text{fill:none;stroke-width:0;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .icon-shape,#mermaid-svg-PNWTaJ0G3Q4pq1rs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .icon-shape p,#mermaid-svg-PNWTaJ0G3Q4pq1rs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .icon-shape .label rect,#mermaid-svg-PNWTaJ0G3Q4pq1rs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PNWTaJ0G3Q4pq1rs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PNWTaJ0G3Q4pq1rs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PNWTaJ0G3Q4pq1rs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 探针
存活检测
就绪检测
启动检测
自动重启
流量控制
保护慢启动

核心能力

  1. 自动检测:无需人工干预
  2. 快速响应:及时发现问题
  3. 流量控制:确保流量只到健康实例
  4. 自愈能力:自动重启故障容器

1.3 探针对比

特性 livenessProbe readinessProbe startupProbe
目的 检测是否存活 检测是否就绪 检测是否启动完成
失败后果 重启容器 移除流量 重启容器
执行时机 容器启动后 容器启动后 容器启动时
适用场景 死锁检测 流量控制 慢启动保护
必要性 强烈推荐 强烈推荐 可选

二、三种探针详解

2.1 Liveness Probe(存活探针)

作用:检测容器是否存活,失败则重启容器。

yaml 复制代码
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3

适用场景

  • 应用死锁检测
  • 内存泄漏检测
  • 进程假死检测

注意事项

  • 不要检测外部依赖(数据库、缓存)
  • 探测逻辑要轻量
  • 避免误杀健康容器

2.2 Readiness Probe(就绪探针)

作用:检测容器是否就绪,失败则从 Service 移除。

yaml 复制代码
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5
  timeoutSeconds: 3
  successThreshold: 1
  failureThreshold: 3

适用场景

  • 应用启动完成检测
  • 依赖服务可用性检测
  • 流量控制

注意事项

  • 检测应用是否准备好接收流量
  • 可以检测外部依赖
  • 失败不会重启容器

2.3 Startup Probe(启动探针)

作用:检测容器是否启动完成,保护慢启动容器。

yaml 复制代码
startupProbe:
  httpGet:
    path: /startup
    port: 8080
  failureThreshold: 30
  periodSeconds: 10

适用场景

  • 应用启动时间较长(>60秒)
  • 需要初始化数据的应用
  • 避免被 livenessProbe 误杀

注意事项

  • 成功前其他探针不执行
  • 失败会重启容器
  • 成功后不再执行

三、探测方式详解

3.1 HTTP GET 探测

yaml 复制代码
httpGet:
  path: /healthz           # 探测路径
  port: 8080               # 端口
  host: localhost          # 主机(可选)
  scheme: HTTP             # HTTP/HTTPS
  httpHeaders:             # 自定义请求头
  - name: Authorization
    value: Bearer token123

成功条件:HTTP 状态码 200-399

适用场景:Web 应用、API 服务

3.2 TCP Socket 探测

yaml 复制代码
tcpSocket:
  port: 3306               # 探测端口
  host: localhost          # 主机(可选)

成功条件:TCP 连接建立成功

适用场景:数据库、缓存、非 HTTP 服务

3.3 Exec 命令探测

yaml 复制代码
exec:
  command:
  - /bin/sh
  - -c
  - |
    mysqladmin ping -h localhost -uroot -p$MYSQL_ROOT_PASSWORD

成功条件:命令退出码为 0

适用场景:复杂检测逻辑、特定应用检查

3.4 GRPC 探测(K8s 1.24+)

yaml 复制代码
grpc:
  port: 2379
  service: etcd.etcd.kube-system.svc.cluster.local

成功条件:gRPC 健康检查成功

适用场景:gRPC 服务

3.5 探测方式对比

方式 优点 缺点 适用场景
HTTP GET 简单直观 需要 HTTP 端点 Web 应用
TCP Socket 通用 无法检测应用层 数据库
Exec 灵活 需要脚本 复杂检查
GRPC 原生支持 版本要求 gRPC 服务

四、探针配置参数

4.1 通用参数

参数 默认值 说明
initialDelaySeconds 0 启动后等待时间
periodSeconds 10 探测间隔
timeoutSeconds 1 超时时间
successThreshold 1 成功阈值
failureThreshold 3 失败阈值

4.2 参数详解

yaml 复制代码
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  
  # 初始延迟:容器启动后等待 30 秒才开始探测
  initialDelaySeconds: 30
  
  # 探测间隔:每 10 秒探测一次
  periodSeconds: 10
  
  # 超时时间:探测请求超过 5 秒视为失败
  timeoutSeconds: 5
  
  # 成功阈值:连续成功 1 次视为成功
  successThreshold: 1
  
  # 失败阈值:连续失败 3 次视为失败
  failureThreshold: 3

4.3 参数配置建议

yaml 复制代码
# 快速失败(适合快速检测问题)
livenessProbe:
  periodSeconds: 5
  timeoutSeconds: 2
  failureThreshold: 3

# 慢速检测(适合避免误判)
livenessProbe:
  periodSeconds: 30
  timeoutSeconds: 10
  failureThreshold: 5

# 就绪检测(快速响应)
readinessProbe:
  periodSeconds: 5
  timeoutSeconds: 3
  failureThreshold: 2

# 启动检测(耐心等待)
startupProbe:
  periodSeconds: 10
  failureThreshold: 30  # 最长等待 300 秒

五、探针与生命周期

5.1 容器生命周期

#mermaid-svg-DTPz7yck6tLD1CE5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-DTPz7yck6tLD1CE5 .error-icon{fill:#552222;}#mermaid-svg-DTPz7yck6tLD1CE5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-DTPz7yck6tLD1CE5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-DTPz7yck6tLD1CE5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-DTPz7yck6tLD1CE5 .marker.cross{stroke:#333333;}#mermaid-svg-DTPz7yck6tLD1CE5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-DTPz7yck6tLD1CE5 p{margin:0;}#mermaid-svg-DTPz7yck6tLD1CE5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-DTPz7yck6tLD1CE5 .cluster-label text{fill:#333;}#mermaid-svg-DTPz7yck6tLD1CE5 .cluster-label span{color:#333;}#mermaid-svg-DTPz7yck6tLD1CE5 .cluster-label span p{background-color:transparent;}#mermaid-svg-DTPz7yck6tLD1CE5 .label text,#mermaid-svg-DTPz7yck6tLD1CE5 span{fill:#333;color:#333;}#mermaid-svg-DTPz7yck6tLD1CE5 .node rect,#mermaid-svg-DTPz7yck6tLD1CE5 .node circle,#mermaid-svg-DTPz7yck6tLD1CE5 .node ellipse,#mermaid-svg-DTPz7yck6tLD1CE5 .node polygon,#mermaid-svg-DTPz7yck6tLD1CE5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-DTPz7yck6tLD1CE5 .rough-node .label text,#mermaid-svg-DTPz7yck6tLD1CE5 .node .label text,#mermaid-svg-DTPz7yck6tLD1CE5 .image-shape .label,#mermaid-svg-DTPz7yck6tLD1CE5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-DTPz7yck6tLD1CE5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-DTPz7yck6tLD1CE5 .rough-node .label,#mermaid-svg-DTPz7yck6tLD1CE5 .node .label,#mermaid-svg-DTPz7yck6tLD1CE5 .image-shape .label,#mermaid-svg-DTPz7yck6tLD1CE5 .icon-shape .label{text-align:center;}#mermaid-svg-DTPz7yck6tLD1CE5 .node.clickable{cursor:pointer;}#mermaid-svg-DTPz7yck6tLD1CE5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-DTPz7yck6tLD1CE5 .arrowheadPath{fill:#333333;}#mermaid-svg-DTPz7yck6tLD1CE5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-DTPz7yck6tLD1CE5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-DTPz7yck6tLD1CE5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DTPz7yck6tLD1CE5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-DTPz7yck6tLD1CE5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DTPz7yck6tLD1CE5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-DTPz7yck6tLD1CE5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-DTPz7yck6tLD1CE5 .cluster text{fill:#333;}#mermaid-svg-DTPz7yck6tLD1CE5 .cluster span{color:#333;}#mermaid-svg-DTPz7yck6tLD1CE5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-DTPz7yck6tLD1CE5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-DTPz7yck6tLD1CE5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-DTPz7yck6tLD1CE5 .icon-shape,#mermaid-svg-DTPz7yck6tLD1CE5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-DTPz7yck6tLD1CE5 .icon-shape p,#mermaid-svg-DTPz7yck6tLD1CE5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-DTPz7yck6tLD1CE5 .icon-shape .label rect,#mermaid-svg-DTPz7yck6tLD1CE5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-DTPz7yck6tLD1CE5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-DTPz7yck6tLD1CE5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-DTPz7yck6tLD1CE5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 成功
失败
成功
失败
失败
容器创建
InitContainer 执行
主容器启动
startupProbe 执行
livenessProbe 开始
重启容器
readinessProbe 开始
加入 Service
从 Service 移除

5.2 探针执行时序

阶段 livenessProbe readinessProbe startupProbe
容器启动 等待 initialDelaySeconds 等待 initialDelaySeconds 立即开始
startupProbe 执行中 不执行 不执行 执行
startupProbe 成功 开始执行 开始执行 停止
startupProbe 失败 不执行 不执行 重启容器
livenessProbe 失败 重启容器 继续执行 -
readinessProbe 失败 继续执行 移除流量 -

5.3 与 Service 的关系

yaml 复制代码
# Service 只转发到就绪的 Pod
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

关键机制

  1. Pod 创建后,readinessProbe 开始执行
  2. 只有 readinessProbe 成功的 Pod 才会加入 Service 的 Endpoints
  3. readinessProbe 失败的 Pod 会被临时移除
  4. readinessProbe 恢复后,Pod 重新加入

六、实战:生产级探针配置

6.1 完整示例:Web 应用

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: web-server
        image: nginx:1.25.3
        
        ports:
        - name: http
          containerPort: 80
        
        # 启动探针:给应用足够时间启动
        startupProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 30    # 最多等待 10 + 30*5 = 160 秒
        
        # 存活探针:检测应用是否存活
        livenessProbe:
          httpGet:
            path: /healthz
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
          successThreshold: 1
        
        # 就绪探针:检测应用是否就绪
        readinessProbe:
          httpGet:
            path: /ready
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
          successThreshold: 1
        
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "256Mi"

6.2 数据库探针配置

yaml 复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: root-password
        
        # 启动探针:等待 MySQL 初始化完成
        startupProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - |
              mysqladmin ping -h localhost -uroot -p$MYSQL_ROOT_PASSWORD
          initialDelaySeconds: 20
          periodSeconds: 10
          failureThreshold: 30    # 最多等待 20 + 30*10 = 320 秒
        
        # 存活探针:检测 MySQL 是否存活
        livenessProbe:
          exec:
            command:
            - mysqladmin
            - ping
            - -h
            - localhost
            - -uroot
            - -p$MYSQL_ROOT_PASSWORD
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        
        # 就绪探针:检测 MySQL 是否就绪
        readinessProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - |
              mysql -h localhost -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT 1"
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3

6.3 Redis 探针配置

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis:7.0
    
    # 启动探针
    startupProbe:
      tcpSocket:
        port: 6379
      initialDelaySeconds: 5
      periodSeconds: 5
      failureThreshold: 30
    
    # 存活探针
    livenessProbe:
      exec:
        command:
        - redis-cli
        - ping
      initialDelaySeconds: 20
      periodSeconds: 10
      timeoutSeconds: 5
      failureThreshold: 3
    
    # 就绪探针
    readinessProbe:
      exec:
        command:
        - redis-cli
        - ping
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 3
      failureThreshold: 3

6.4 Java 应用探针配置

yaml 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: java-app
spec:
  containers:
  - name: app
    image: java-app:1.0
    
    # 使用 Spring Boot Actuator
    startupProbe:
      httpGet:
        path: /actuator/health/readiness
        port: 8080
      failureThreshold: 60
      periodSeconds: 10
    
    livenessProbe:
      httpGet:
        path: /actuator/health/liveness
        port: 8080
      initialDelaySeconds: 60
      periodSeconds: 15
      timeoutSeconds: 5
      failureThreshold: 5
    
    readinessProbe:
      httpGet:
        path: /actuator/health/readiness
        port: 8080
      initialDelaySeconds: 30
      periodSeconds: 10
      timeoutSeconds: 3
      failureThreshold: 3

七、常用命令速查

7.1 查看探针配置

bash 复制代码
# 查看 Pod 详情(包含探针配置)
kubectl describe pod <pod-name>

# 查看探针配置(JSON 格式)
kubectl get pod <pod-name> -o jsonpath='{.spec.containers[*].livenessProbe}'

# 查看探针状态
kubectl get pod <pod-name> -o jsonpath='{.status.containerStatuses[*].state}'

7.2 排查探针问题

bash 复制代码
# 1. 查看 Pod 事件
kubectl describe pod <pod-name> | grep -A10 Events

# 2. 查看容器日志
kubectl logs <pod-name> --previous  # 查看重启前的日志

# 3. 查看容器状态
kubectl get pod <pod-name> -o wide

# 4. 进入容器手动测试
kubectl exec -it <pod-name> -- /bin/bash
# 手动执行探针命令
curl localhost:8080/healthz
mysqladmin ping -h localhost
redis-cli ping

# 5. 实时监控探针状态
kubectl get pod <pod-name> -w

7.3 常见探针错误

错误 原因 解决方案
CrashLoopBackOff livenessProbe 失败 检查应用健康,调整探针
Readiness probe failed readinessProbe 失败 检查应用就绪状态
Startup probe failed startupProbe 失败 检查启动逻辑
Liveness probe failed livenessProbe 失败 应用可能死锁或崩溃

八、最佳实践与避坑指南

8.1 必须遵守的原则

原则 说明 示例
区分存活和就绪 不同探针不同用途 liveness ≠ readiness
探针要轻量 避免复杂计算 简单 HTTP GET
合理设置阈值 避免误判 failureThreshold: 3
使用启动探针 保护慢启动应用 startupProbe
避免外部依赖 liveness 不检测外部服务 只检测自身

8.2 常见错误

错误 1:livenessProbe 检测外部依赖
yaml 复制代码
# ❌ 错误:数据库不可用导致容器重启
livenessProbe:
  exec:
    command:
    - /bin/sh
    - -c
    - |
      mysql -h db-service -e "SELECT 1"

# ✅ 正确:只检测自身健康
livenessProbe:
  exec:
    command:
    - /bin/sh
    - -c
    - |
      # 检测进程是否存在
      ps aux | grep app
错误 2:探针过于频繁
yaml 复制代码
# ❌ 错误:过于频繁,增加系统负担
periodSeconds: 1
timeoutSeconds: 1

# ✅ 正确:合理频率
periodSeconds: 10
timeoutSeconds: 5
错误 3:没有启动探针
yaml 复制代码
# ❌ 错误:启动时间长,liveness 误杀
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 10  # 启动需要 60 秒
  failureThreshold: 3

# ✅ 正确:使用 startupProbe
startupProbe:
  httpGet:
    path: /healthz
    port: 8080
  failureThreshold: 60
  periodSeconds: 10

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  periodSeconds: 10

8.3 探针设计模式

模式 1:独立健康检查端点
python 复制代码
# 应用代码
from flask import Flask, jsonify
app = Flask(__name__)

@app.route('/healthz')  # 存活检查
def healthz():
    return jsonify({"status": "alive"}), 200

@app.route('/ready')    # 就绪检查
def ready():
    # 检查依赖服务
    if check_database() and check_cache():
        return jsonify({"status": "ready"}), 200
    else:
        return jsonify({"status": "not_ready"}), 503
模式 2:使用 Spring Boot Actuator
yaml 复制代码
# application.yaml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      probes:
        enabled: true
      group:
        liveness:
          include: livenessState
        readiness:
          include: readinessState,db
模式 3:自定义探针脚本
bash 复制代码
#!/bin/bash
# health-check.sh

# 检查进程
if ! pgrep -f "my-app" > /dev/null; then
  echo "Process not running"
  exit 1
fi

# 检查端口
if ! nc -z localhost 8080; then
  echo "Port not listening"
  exit 1
fi

# 检查日志
if grep -q "FATAL ERROR" /var/log/app.log; then
  echo "Fatal error in logs"
  exit 1
fi

echo "Healthy"
exit 0

8.4 性能优化建议

yaml 复制代码
# 1. 使用 TCP 探测代替 HTTP(性能更好)
readinessProbe:
  tcpSocket:
    port: 8080
  periodSeconds: 10

# 2. 合理设置超时
timeoutSeconds: 5  # 不要太小(网络波动)
# 也不要太大(响应慢)

# 3. 使用更长的间隔减少负载
periodSeconds: 30  # 对于稳定的应用

# 4. 利用 initialDelaySeconds 避免启动期探测
initialDelaySeconds: 60  # 给应用足够启动时间

九、总结

9.1 核心要点回顾

  1. 三种探针各司其职:liveness 保活、readiness 控流、startup 护启动
  2. 探测方式要合适:HTTP、TCP、Exec 根据场景选择
  3. 参数配置要合理:避免误判和过度探测
  4. 启动探针很重要:保护慢启动应用
  5. 探针与 Service 联动:确保流量只到健康实例

9.2 探针配置清单

yaml 复制代码
# 完整的探针配置模板
startupProbe:              # 启动探针(可选)
  httpGet:
    path: /startup
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5
  failureThreshold: 30

livenessProbe:             # 存活探针(必须)
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  failureThreshold: 3
  successThreshold: 1

readinessProbe:            # 就绪探针(必须)
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5
  timeoutSeconds: 3
  failureThreshold: 3
  successThreshold: 1

9.3 学习路线

复制代码
探针基础 → Deployment 滚动更新 → Service 流量管理
    ↓
PodDisruptionBudget → HPA 自动扩缩容 → 混沌工程

9.4 下一步学习

  1. PodDisruptionBudget:优雅处理节点维护
  2. HPA 深入:基于自定义指标的扩缩容
  3. Service Mesh:更高级的健康检查
  4. 混沌工程:Chaos Mesh 故障注入
  5. 可观测性:Prometheus 监控探针

附录:完整示例汇总

生产级探针完整配置

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: production-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: production-app
  template:
    metadata:
      labels:
        app: production-app
    spec:
      containers:
      - name: app
        image: myapp:1.0.0
        
        ports:
        - name: http
          containerPort: 8080
        
        # 启动探针
        startupProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 30
        
        # 存活探针
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        
        # 就绪探针
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        
        # 资源限制
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "256Mi"
        
        # 优雅终止
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 10"]

验证测试

bash 复制代码
# 1. 创建 Deployment
kubectl apply -f probe-demo.yaml

# 2. 查看 Pod 状态
kubectl get pods -n production -w

# 3. 查看探针配置
kubectl describe pod <pod-name> -n production | grep -A5 "Probe"

# 4. 测试探针
# 模拟探针失败
kubectl exec -it <pod-name> -n production -- /bin/bash
# 停止应用进程
kill 1  # 观察 livenessProbe 是否重启容器

# 5. 查看事件
kubectl get events -n production --sort-by='.lastTimestamp'

# 6. 查看重启次数
kubectl get pod <pod-name> -n production -o jsonpath='{.status.containerStatuses[*].restartCount}'

相关推荐
Kurisu_红莉栖2 小时前
关于docker的使用心得
运维·docker·容器
GGG7663 小时前
k8s-Pod Scheduler
云原生·容器·kubernetes
GGG7664 小时前
k8s-动态卷供应
云原生·容器·kubernetes
yunwei374 小时前
eBPF 教程:使用 fsession 追踪慢速 vfs_read 调用
linux·云原生
叶 落5 小时前
Docker-Compose 安装 Milvus
docker·容器·milvus
深念Y6 小时前
Windows → WSL2 全面迁移:工具链、Docker、OpenCode
linux·运维·windows·docker·容器·环境·wsl
heimeiyingwang17 小时前
【架构实战】Kubernetes存储实战:从EmptyDir到Ceph CSI的持久化存储选型指南
ceph·架构·kubernetes
QX_hao18 小时前
【Kubernetes】 的三个Probe
容器·kubernetes
Henry-SAP21 小时前
SAP S/4HANA引领物流ERP新生态
人工智能·云原生·sap·erp