LabHub
学习 学习路径 课程

CKAD — Kubernetes 应用开发者

探针设计与中断预算

在 LabHub 中继续学习

目标

能够创建三类探针,明确指定检查方式(httpGet/tcpSocket/exec)及时间字段,并能够设计 Deployment 的就绪状态、终止行为和 PodDisruptionBudget。

为什么重要

没有配置探针的 Deployment 等于禁用了滚动更新的所有安全保障。即使设置 maxUnavailable: 0,容器一启动便会被视为 Ready,流量会进入仍在初始化的 Pod。反过来,如果探针过于激进,正常 Pod 会不断重启,反而制造故障。因此,关键不只是“是否配置了探针”,而是“是否经过计算后配置了合理数值”。

混淆 liveness 和 readiness 会放大事故。当依赖服务(DB)短暂故障时,如果用 liveness 检查它,所有 Pod 会同时反复重启,即使 DB 恢复,整体恢复也会变慢。外部依赖应使用 readiness 检查——只需暂停接收流量,没有理由重启。

startup 探针可以化解两者之间的矛盾。如果给 liveness 设置 initialDelaySeconds: 300,运行期间的故障检测也会延迟 5 分钟;但若用 startup 单独提供 300 秒启动预算,则启动完成后仍可保持高频 liveness 检查。

步骤

  1. 创建命名空间 ckad-obs 和 Pod web-live。镜像 nginx:1.27livenessProbe 使用 httpGet,path /healthz、port 80initialDelaySeconds: 5periodSeconds: 10
  2. 创建 Pod db-ready。镜像 nginx:1.27readinessProbe 使用 tcpSocket,port 5432initialDelaySeconds: 10periodSeconds: 5failureThreshold: 3
  3. 创建 Pod file-check。镜像 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]livenessProbe 使用 execcommand: ["cat","/tmp/healthy"]periodSeconds: 5failureThreshold: 2
  4. 创建 Pod legacy-app。镜像 nginx:1.27startupProbe 使用 httpGet,path /startup、port 8080failureThreshold: 30periodSeconds: 10(= 300 秒预算)。在同一容器上再添加 livenessProbe,同样使用 httpGet,path /healthz、port 8080periodSeconds: 10
  5. 创建 Pod budget-app。镜像 nginx:1.27readinessProbe 使用 httpGet,path /ready、port 80initialDelaySeconds: 15。自行确定 periodSecondsfailureThreshold,使其在首次失败后的 20 秒内从 Endpoint 中移除。条件为 periodSeconds × failureThreshold ≤ 20failureThreshold ≥ 3periodSeconds ≥ 2
  6. 创建 Deployment api。副本数 3,标签 app=api,镜像 nginx:1.27。为容器添加 readinessProbe(httpGet /ready:8080)和 livenessProbe(httpGet /healthz:8080),并指定 terminationMessagePolicy: FallbackToLogsOnError
  7. 创建 PodDisruptionBudget api-pdbminAvailable: 2selectorapp=api
  8. 为 Deployment api 添加 startupProbe——httpGet path /startup、port 8080failureThreshold: 12periodSeconds: 5。再将 Pod 规范的 terminationGracePeriodSeconds 设为 60。保留原有 readiness/liveness 探针和 3 个副本。

参考

HTTP liveness 探针

创建命名空间 ckad-obs 和 Pod web-live。镜像 nginx:1.27livenessProbe 使用 httpGet,path /healthz、port 80initialDelaySeconds: 5periodSeconds: 10

livenessProbe.httpGet 中设置 pathport。探针位于容器下,不在 Pod 层级。响应码为 200~399 时视为成功。

TCP readiness 探针

创建 Pod db-ready。镜像 nginx:1.27readinessProbe 使用 tcpSocket,port 5432initialDelaySeconds: 10periodSeconds: 5failureThreshold: 3

tcpSocket 只需指定端口——连接成功即视为检查成功。readiness 失败不会触发重启,只会将 Pod 从 Endpoint 中移除。

exec 探针

创建 Pod file-check。镜像 busybox:1.36command: ["/bin/sh","-c","sleep 3600"]livenessProbe 使用 execcommand: ["cat","/tmp/healthy"]periodSeconds: 5failureThreshold: 2

exec.command 是字符串数组,不经过 Shell。退出代码为 0 即成功。只检查文件是否存在时,无需特意调用 Shell。

使用 startup 探针覆盖缓慢启动

创建 Pod legacy-app。镜像 nginx:1.27startupProbe 使用 httpGet,path /startup、port 8080failureThreshold: 30periodSeconds: 10(= 300 秒预算)。在同一容器上再添加 livenessProbe,同样使用 httpGet,path /healthz、port 8080periodSeconds: 10

startup 探针成功前,liveness/readiness 根本不会启动。启动预算按 periodSeconds × failureThreshold 计算。此 Pod 还必须同时配置 liveness。

计算检测延迟后确定数值

创建 Pod budget-app。镜像 nginx:1.27readinessProbe 使用 httpGet,path /ready、port 80initialDelaySeconds: 15。自行确定 periodSecondsfailureThreshold,使其在首次失败后的 20 秒内从 Endpoint 中移除。条件为 periodSeconds × failureThreshold ≤ 20failureThreshold ≥ 3periodSeconds ≥ 2

从首次失败到采取措施的时间约为 periodSeconds × failureThreshold。既要满足要求的上限,也要让 failureThreshold 足够大,避免因短暂故障而波动。答案不止一个。

为 Deployment 添加探针和终止消息策略

创建 Deployment api。副本数 3,标签 app=api,镜像 nginx:1.27。为容器添加 readinessProbe(httpGet /ready:8080)和 livenessProbe(httpGet /healthz:8080),并指定 terminationMessagePolicy: FallbackToLogsOnError

Deployment 的探针位于 spec.template.spec.containers[] 下。终止消息策略也是同一容器层级字段,且只有两个可用值,请用 kubectl explain 确认。

使用 PodDisruptionBudget 限制自愿中断

创建 PodDisruptionBudget api-pdbminAvailable: 2selectorapp=api

PDB 使用 policy/v1,且 minAvailablemaxUnavailable 只能选择一个。selector 必须指向Pod 标签,而不是 Deployment。

综合:同时配置启动预算与终止预算

为 Deployment api 添加 startupProbe——httpGet path /startup、port 8080failureThreshold: 12periodSeconds: 5。再将 Pod 规范的 terminationGracePeriodSeconds 设为 60。保留原有 readiness/liveness 探针和 3 个副本。

在之前创建的 Deployment 上添加 startup 探针,并延长终止宽限期。terminationGracePeriodSeconds 位于 Pod 规范(spec.template.spec)层级,而非容器层级。保留现有 liveness/readiness。