Chapter 04

Deployment 与 ReplicaSet

掌握无状态应用的核心工作负载,理解滚动更新策略、版本回滚、HPA 水平自动伸缩,以及不同工作负载类型的选择。

Deployment、ReplicaSet 与 Pod 的关系

三层嵌套关系

┌────────────────────────────────────────────────────────┐
  Deployment  nginx-deployment (replicas: 3)            
                                                        
  管理 ──►  ┌──────────────────────────────────────┐  
              ReplicaSet  nginx-rs-abc123 (v1)      
                          nginx-rs-def456 (v2)      
            └──────────────────────────────────────┘  
  管理 ──►  ┌────────┐  ┌────────┐  ┌────────┐        
             Pod-1     Pod-2     Pod-3          
            └────────┘  └────────┘  └────────┘        
└────────────────────────────────────────────────────────┘

更新时:Deployment 创建新 ReplicaSet,逐步缩减旧 RS,扩充新 RS
Deployment
无状态应用的最高层抽象。管理 ReplicaSet,提供声明式更新、版本历史、滚动升级/回滚能力。是部署无状态服务的首选。
ReplicaSet
保证指定数量的 Pod 副本始终运行。通常不直接创建,由 Deployment 管理。滚动更新时,每个版本对应一个 ReplicaSet。

完整 Deployment YAML

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: production
  annotations:
    kubernetes.io/change-cause: "升级到 nginx 1.25,修复 CVE-2023-xxxx"  # 用于回滚历史记录
spec:
  replicas: 3
  revisionHistoryLimit: 5       # 保留最近 5 个 ReplicaSet(用于回滚),默认 10
  selector:
    matchLabels:
      app: nginx
  strategy:                      # 更新策略
    type: RollingUpdate          # RollingUpdate(默认)或 Recreate
    rollingUpdate:
      maxSurge: 1               # 更新期间最多多出几个 Pod(可用百分比)
      maxUnavailable: 0         # 更新期间最多有几个 Pod 不可用(0 = 零停机)
  template:
    metadata:
      labels:
        app: nginx
        version: v1.25
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 5

滚动更新策略详解

RollingUpdate 过程(maxSurge:1, maxUnavailable:0, replicas:3)

初始状态     [v1] [v1] [v1]        (3个运行)

第1步        [v1] [v1] [v1] [v2]  (创建1个新Pod,maxSurge=1)
             等待 v2 就绪...
第2步        [v1] [v1] [v2]       (删除1个旧Pod,始终>=3个就绪)

第3步        [v1] [v1] [v2] [v2]  (再创建1个 v2)
             等待就绪...
第4步        [v1] [v2] [v2]

第5步        [v1] [v2] [v2] [v2]
             等待就绪...
完成         [v2] [v2] [v2]        (全部更新完毕)
# 触发滚动更新(修改镜像)
kubectl set image deployment/nginx-deployment nginx=nginx:1.26

# 实时查看更新进度
kubectl rollout status deployment/nginx-deployment

# 暂停更新(金丝雀部署场景)
kubectl rollout pause deployment/nginx-deployment

# 恢复更新
kubectl rollout resume deployment/nginx-deployment

# 查看版本历史
kubectl rollout history deployment/nginx-deployment

# 回滚到上一版本
kubectl rollout undo deployment/nginx-deployment

# 回滚到指定版本(revision 编号来自 history)
kubectl rollout undo deployment/nginx-deployment --to-revision=2
更新策略选择

RollingUpdate(默认):适合无状态服务,实现零停机更新。
Recreate:先删除所有旧 Pod,再创建新 Pod,有短暂停机。适用于不能并存两个版本(如做了不兼容 DB 迁移)的场景。

HPA 水平自动伸缩

HPA(Horizontal Pod Autoscaler)根据观测到的指标自动调整 Deployment 的 replicas 数量。

apiVersion: autoscaling/v2    # v2 版本支持自定义指标
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:              # 要控制的目标工作负载
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 2               # 最小副本数
  maxReplicas: 10              # 最大副本数
  metrics:
  - type: Resource             # 基于资源指标(CPU/内存)
    resource:
      name: cpu
      target:
        type: Utilization       # 目标 CPU 利用率(相对于 requests)
        averageUtilization: 70 # 所有 Pod 平均 CPU 使用率目标 70%
  - type: Resource
    resource:
      name: memory
      target:
        type: AverageValue       # 目标内存绝对值
        averageValue: 200Mi
  behavior:                     # 伸缩行为控制(防止频繁波动)
    scaleDown:
      stabilizationWindowSeconds: 300   # 缩容冷却 5 分钟
      policies:
      - type: Pods
        value: 1                  # 每次最多缩减 1 个 Pod
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0     # 扩容无冷却,立即响应
      policies:
      - type: Percent
        value: 100                # 每次最多扩容当前数量的 100%(翻倍)
        periodSeconds: 15
HPA 需要 Metrics Server

HPA 依赖 metrics-server 提供 Pod CPU/内存指标。如果集群没有安装 metrics-server,HPA 无法工作,并显示 <unknown>/70%。安装命令:kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

PodDisruptionBudget

PDB(Pod 干扰预算)保证在节点维护、集群升级等自愿中断场景中,始终有足够数量的 Pod 保持可用,防止服务不可用。

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: nginx-pdb
spec:
  minAvailable: 2              # 最少保留 2 个 Pod 可用
  # 或者用 maxUnavailable: 1    # 最多允许 1 个 Pod 不可用
  selector:
    matchLabels:
      app: nginx

工作负载类型对比

类型适用场景特点
Deployment 无状态 Web 服务、API 服务 随机 Pod 名称、Pod 可任意替换、支持滚动更新
StatefulSet 数据库、消息队列、Zookeeper 稳定的 Pod 标识(pod-0/1/2)、有序启停、持久存储
DaemonSet 日志采集、监控 agent、网络插件 每个 Node 上运行且仅运行一个 Pod
Job 批处理任务、数据迁移 运行到完成(completion),支持并行
CronJob 定时任务、定期备份 基于 cron 表达式定期创建 Job

StatefulSet 示例

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql             # 必须指向一个 Headless Service
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:          # 每个 Pod 自动创建独立的 PVC
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi
# StatefulSet 创建的 Pod 名称固定为:mysql-0, mysql-1, mysql-2
# DNS 地址:mysql-0.mysql.default.svc.cluster.local
常见错误:在 StatefulSet 中误用 emptyDir

StatefulSet 的 Pod 重启后如果使用 emptyDir 存储,数据会丢失。必须使用 volumeClaimTemplates 创建 PVC,或挂载已有的 PVC,才能在 Pod 重启/重调度后保留数据。