主题
第十一部分: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 信号
- 使用
tini或dumb-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:latest11.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 等级 | 条件 | 驱逐优先级 | 适用场景 |
|---|---|---|---|
| Guaranteed | requests = limits(CPU + Memory) | 最低 | 核心服务 |
| Burstable | requests < 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,决定驱逐优先级 |
练习
- 创建 Deployment,配置
maxUnavailable: 0+preStop sleep 5,观察滚动更新。 - 模拟 Liveness 探针依赖外部服务的错误配置,观察 Pod 雪崩重启。
- 创建三种 QoS 的 Pod,在节点资源不足时观察驱逐顺序。
- 使用 StatefulSet
partition实现金丝雀发布。