Skip to content

第十一部分:Pod 与工作负载深度解析

本章深入剖析 Pod 生命周期、探针机制、工作负载控制器的选型与生产实践,帮助你做出正确的架构决策。


11.1 Pod 生命周期全解

11.1.1 Pod 阶段与终止流程

Pod 终止流程(非常重要的生产知识):

1. Pod 标记为 Terminating
2. kubelet 执行 PreStop Hook(如果有)
3. 发送 SIGTERM 信号给容器进程(PID 1)
4. 等待 terminationGracePeriodSeconds(默认 30s)
5. 超时则发送 SIGKILL 强制终止
6. kubelet 通知 apiserver 删除 Pod
7. kube-proxy 移除 Service 端点(iptables/IPVS 规则)

生产要点:

  • PID 1 进程必须能处理 SIGTERM 信号
  • 使用 tinidumb-init 解决僵尸进程问题
  • terminationGracePeriodSeconds 应大于应用优雅关闭所需时间
yaml
spec:
  terminationGracePeriodSeconds: 60
  containers:
  - name: app
    lifecycle:
      preStop:
        exec:
          command: ["/bin/sh", "-c", "sleep 5"]
    # sleep 5 让 kube-proxy 有时间移除端点,避免终止期仍接收新流量

11.1.2 Init Container 与 Sidecar

yaml
initContainers:
- name: wait-for-db
  image: busybox
  command: ['sh', '-c', 'until nslookup mysql.default.svc; do sleep 2; done']

# K8s 1.28+ 原生 Sidecar 支持
containers:
- name: log-forwarder
  restartPolicy: Always    # 标记为 sidecar,Init 阶段启动,最后终止
  image: fluent-bit:latest

11.2 探针机制深度解析

11.2.1 三种探针对比

探针失败处理适用场景何时开始
Startup重启容器慢启动应用(Java)容器启动时
Liveness重启容器检测死锁/假死Startup 成功后
Readiness从 Service 移除临时不可用Startup 成功后

关键区别:Liveness 失败 → 重启容器;Readiness 失败 → 仅摘除流量

11.2.2 探针最佳实践

yaml
startupProbe:
  httpGet: { path: /healthz/startup, port: 8080 }
  periodSeconds: 5
  failureThreshold: 30    # 最多等 150s

livenessProbe:
  httpGet: { path: /healthz/live, port: 8080 }
  periodSeconds: 10
  failureThreshold: 3

readinessProbe:
  httpGet: { path: /healthz/ready, port: 8080 }
  periodSeconds: 5
  failureThreshold: 3

探针设计原则:

  • ✅ Liveness 只检测"进程死锁"级问题
  • ✅ Readiness 检测"临时不可用"
  • ❌ Liveness 不要依赖外部服务(外部挂了会导致全部 Pod 重启!)
  • ❌ Liveness 和 Readiness 不要指向同一端点

11.3 工作负载控制器选型

11.3.1 控制器对比

控制器特点适用场景
Deployment无状态,滚动更新Web/API 服务
StatefulSet有状态,固定标识,有序部署数据库、消息队列
DaemonSet每节点一个日志收集、监控 Agent
Job/CronJob一次性/定时批处理、数据迁移

11.3.2 零停机部署配置

yaml
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 25%
    maxUnavailable: 0      # 不可用 Pod 数为 0

# 配合 PodDisruptionBudget
apiVersion: policy/v1
kind: PodDisruptionBudget
spec:
  minAvailable: 80%
  selector:
    matchLabels: { app: my-app }

11.3.3 StatefulSet 关键特性

Pod 名:mysql-0, mysql-1, mysql-2(固定,重启不变)
DNS 名:mysql-0.mysql.default.svc.cluster.local
PVC 名:data-mysql-0, data-mysql-1(独立持久化)
缩容:按序号倒序删除(3→2→1→0)
删除 Pod 不会删除 PVC(数据安全)

金丝雀发布:

yaml
updateStrategy:
  rollingUpdate:
    partition: 2    # 只更新序号 >= 2 的 Pod,其余保持旧版本

11.4 QoS 等级与驱逐

QoS 等级条件驱逐优先级适用场景
Guaranteedrequests = limits(CPU + Memory)最低核心服务
Burstablerequests < limits中等一般应用
BestEffort未设置 requests/limits最高批处理任务

节点内存不足时,kubelet 按 BestEffort → Burstable → Guaranteed 顺序驱逐。


11.5 本章小结

核心概念关键要点
Pod 终止PreStop → SIGTERM → grace period → SIGKILL
三种探针Startup(慢启动)、Liveness(死锁重启)、Readiness(流量摘除)
工作负载选型Deployment(无状态)、StatefulSet(有状态)、DaemonSet(节点级)
QoS 等级Guaranteed > Burstable > BestEffort,决定驱逐优先级

练习

  1. 创建 Deployment,配置 maxUnavailable: 0 + preStop sleep 5,观察滚动更新。
  2. 模拟 Liveness 探针依赖外部服务的错误配置,观察 Pod 雪崩重启。
  3. 创建三种 QoS 的 Pod,在节点资源不足时观察驱逐顺序。
  4. 使用 StatefulSet partition 实现金丝雀发布。

上一章:第十部分:K8s 核心架构深度解析 下一章:第十二部分:K8s 网络模型与 CNI 深度解析