Skip to content

07 — 工作负载管理深度教材

工作负载是 K8s 中最常操作的对象。本章覆盖五种工作负载选型、滚动更新策略、PDB 保护、HPA 联动,全部以生产实战为导向。


1. 五种工作负载选型

类型场景关键特性
Deployment无状态应用(Web/API)滚动更新、回滚、HPA
StatefulSet有状态应用(DB/消息队列)稳定网络标识、有序部署、PVC 绑定
DaemonSet节点级守护进程每节点一个 Pod(监控/日志/CNI)
Job一次性任务执行成功即退出
CronJob定时任务按 cron 表达式调度 Job

1.1 Deployment 生产配置

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1           # 滚动更新时最多多 1 个 Pod
      maxUnavailable: 0     # 更新过程中不允许有不可用 Pod
  template:
    spec:
      terminationGracePeriodSeconds: 60  # 优雅终止等待时间
      containers:
      - name: app
        image: app:v1.2.3
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 10"]  # 等待 LB 摘除
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        startupProbe:
          httpGet:
            path: /health
            port: 8080
          failureThreshold: 30
          periodSeconds: 2

1.2 StatefulSet 要点

yaml
# StatefulSet 关键配置
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-headless   # 必须配合 Headless Service
  replicas: 3
  podManagementPolicy: OrderedReady  # 有序启动(默认)
  # podManagementPolicy: Parallel    # 并行启动(快但不保证顺序)
  volumeClaimTemplates:              # 每个 Pod 独立 PVC
  - metadata:
      name: data
    spec:
      accessModes: [ReadWriteOnce]
      storageClassName: ceph-rbd
      resources:
        requests:
          storage: 100Gi
bash
# StatefulSet Pod 命名规则
# mysql-0, mysql-1, mysql-2(按序创建,按序启动)
# DNS: mysql-0.mysql-headless.default.svc.cluster.local

# 缩容到 0 再扩容时,Pod 会使用之前的 PVC(数据保留)
kubectl scale statefulset mysql --replicas=0
kubectl scale statefulset mysql --replicas=3  # 数据仍在

2. 滚动更新与回滚

bash
# 查看更新状态
kubectl rollout status deployment/web-app

# 查看更新历史
kubectl rollout history deployment/web-app
kubectl rollout history deployment/web-app --revision=3

# 回滚
kubectl rollout undo deployment/web-app                    # 回滚到上一版本
kubectl rollout undo deployment/web-app --to-revision=2    # 回滚到指定版本

# 暂停/恢复更新(批量修改后一次性发布)
kubectl rollout pause deployment/web-app
kubectl set image deployment/web-app app=app:v2.0
kubectl set resources deployment/web-app --limits=cpu=2,memory=4Gi
kubectl rollout resume deployment/web-app  # 恢复后一次性更新

3. PodDisruptionBudget(PDB)

yaml
# PDB 保护应用可用性
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-app-pdb
spec:
  minAvailable: 2           # 至少 2 个 Pod 可用
  # maxUnavailable: 1       # 最多 1 个 Pod 不可用(二选一)
  selector:
    matchLabels:
      app: web-app
bash
# PDB 在以下场景生效:
# 1. 节点排空(kubectl drain)
# 2. 集群升级(RKE2 自动排空节点)
# 3. 节点缩容(Cluster Autoscaler)

# 查看 PDB 状态
kubectl get pdb
# NAME          MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS
# web-app-pdb   2               N/A               1

# 如果 ALLOWED DISRUPTIONS = 0,drain 会被阻塞

4. 面试高频问题

Q: Deployment 和 StatefulSet 怎么选?

Deployment:
  - Pod 无身份标识(可互换)
  - 共享存储或无状态
  - 适合:Web、API、微服务

StatefulSet:
  - Pod 有稳定身份(名称、DNS、存储)
  - 每个 Pod 独立 PVC
  - 有序启动/停止
  - 适合:MySQL、Redis Cluster、Kafka、ZooKeeper

Q: 如何实现零停机部署?

1. 滚动更新配置:maxUnavailable=0, maxSurge=1
2. Readiness Probe:确保新 Pod 就绪后才接入流量
3. preStop Hook:sleep 10 秒等待 LB 摘除旧 Pod
4. terminationGracePeriodSeconds:足够长的优雅终止时间
5. PDB:保护最低可用副本数
6. 应用层面:处理 SIGTERM 信号,完成当前请求后退出