一、Deployment 简介

1.1 什么是 Deployment

Deployment 是 Kubernetes 提供的一种声明式控制器,用于管理 Pod 的部署和更新。它基于 ReplicaSet 实现,提供了应用版本的定义、回滚机制以及滚动更新策略。

plaintext

┌─────────────────────────────────────────────────────────────────────┐
│                         Deployment                                   │
│  ┌───────────────────┐     ┌───────────────────┐                     │
│  │    Deployment     │────▶│    ReplicaSet     │                    │
│  │  (声明式定义)      │     │  (副本管理)        │                    │
│  └───────────────────┘     └─────────┬─────────┘                     │
│                                      │                               │
│                          ┌───────────┼───────────┐                   │
│                          ▼           ▼           ▼                   │
│                      ┌───────┐   ┌───────┐   ┌───────┐               │
│                      │  Pod  │   │  Pod  │   │  Pod  │               │
│                      └───────┘   └───────┘   └───────┘               │
└─────────────────────────────────────────────────────────────────────┘

1.2 Deployment 的核心作用

功能 说明
副本管理 确保指定数量的 Pod 副本持续运行
滚动更新 自动化执行应用的零宕机更新
版本回滚 支持回退到历史的稳定版本
弹性伸缩 手动或自动调整副本数量
声明式配置 声明期望状态,控制器自动调谐

1.3 与其他控制器的对比

Kubernetes 提供了多种工作负载控制器,它们各有适用场景:

plaintext

┌──────────────────────────────────────────────────────────────────────┐
│                        Kubernetes Workload Controllers                │
├──────────────────────────────────────────────────────────────────────┤
│                                                                       │
│   ┌─────────────┐    ┌─────────────┐    ┌─────────────┐             │
│   │  Deployment │    │    ReplicaSet    │    StatefulSet    │       │
│   ├─────────────┤    ├─────────────┤    ├─────────────┤             │
│   │ • 无状态应用  │    │ • 底层副本管理 │    │ • 有状态应用  │             │
│   │ • Web 服务   │    │ • 很少直接使用 │    │ • 数据库      │             │
│   │ • API 服务   │    │ • Deployment   │    │ • 消息队列    │             │
│   │             │    │   的底层实现    │    │ • 持久化存储  │             │
│   └─────────────┘    └─────────────┘    └─────────────┘             │
│          │                  │                     │                  │
│          ▼                  ▼                     ▼                  │
│   ┌─────────────┐    ┌─────────────┐    ┌─────────────┐             │
│   │  DaemonSet  │    │    Job      │    │  CronJob    │             │
│   ├─────────────┤    ├─────────────┤    ├─────────────┤             │
│   │ • 守护进程    │    │ • 一次性任务  │    │ • 定时任务    │             │
│   │ • 日志收集   │    │ • 数据迁移   │    │ • 备份任务    │             │
│   │ • 监控代理   │    │ • 批处理作业  │    │ • 报表生成    │             │
│   └─────────────┘    └─────────────┘    └─────────────┘             │
│                                                                       │
└──────────────────────────────────────────────────────────────────────┘

核心区别:

控制器 Pod 标识 启动顺序 存储 典型场景
Deployment 无序、随机 并行 共享/无持久化 Web 服务、API
ReplicaSet 无序、随机 并行 共享/无持久化 很少直接使用
StatefulSet 固定标识 有序 独立持久化 MySQL、Kafka
DaemonSet 固定节点 每节点一个 本地/无持久化 日志、监控
Job 无标识 并行/有序 数据迁移、批处理

二、核心概念详解

2.1 Pod 模板(Pod Template)

Pod 模板是 Deployment 的核心组成部分,定义了 Pod 的规格:

yaml

spec:
  template:
    metadata:
      labels:
        app: my-app
        version: v1
    spec:
      containers:
      - name: my-container
        image: nginx:1.25
        ports:
        - containerPort: 80
        resources:
          limits:
            memory: "256Mi"
            cpu: "500m"
          requests:
            memory: "128Mi"
            cpu: "100m"
        livenessProbe:
          httpGet:
            path: /healthz
            port: 80
          initialDelaySeconds: 3
          periodSeconds: 10

重要:Deployment 下的 Pod 模板与 Pod 本身的 metadata 独立。Deployment 会为 ReplicaSet 生成标签以实现关联。

2.2 副本数(Replicas)

副本数定义了期望运行的 Pod 数量:

yaml

spec:
  replicas: 3    # 期望 3 个 Pod 副本

副本数的语义:

plaintext

                    ┌─────────────────────────────────────┐
                    │         Deployment (replicas: 3)      │
                    │                                        │
desired replicas ───▶│   [Pod-1]  [Pod-2]  [Pod-3]          │◀─── ready: 3
                    │                                        │
                    └─────────────────────────────────────┘
                                │
                                ▼
                    ┌─────────────────────────────────────┐
                    │           控制器调谐逻辑              │
                    │                                        │
                    │  期望数 (3) vs 实际数 (2)             │
                    │        ↓                              │
                    │  差距 = 1,创建新 Pod                 │
                    └─────────────────────────────────────┘

2.3 选择器(Selector)

Selector 是 Deployment 连接 ReplicaSet 和 Pod 的桥梁:

yaml

spec:
  selector:
    matchLabels:
      app: my-app

工作原理:

plaintext

┌─────────────────────────────────────────────────────────────────────┐
│                        Selector 匹配关系                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  Deployment.spec.selector        →    ReplicaSet.spec.selector      │
│  ┌─────────────────────┐              ┌─────────────────────┐        │
│  │  matchLabels:       │              │  matchLabels:       │        │
│  │    app: my-app      │────────────▶│    app: my-app      │        │
│  └─────────────────────┘              └──────────┬──────────┘      │
│                                                    │                  │
│                                                    ▼                  │
│                                        Pod.spec.metadata.labels      │
│                                        ┌─────────────────────┐       │
│                                        │  labels:            │       │
│                                        │    app: my-app      │       │
│                                        │    version: v1      │       │
│                                        └─────────────────────┘       │
│                                                                       │
│  ⚠️  注意:Pod 标签必须包含 selector 匹配的所有标签                    │
│     Pod 可以有额外的标签,但 selector 必须完全匹配                      │
└─────────────────────────────────────────────────────────────────────┘

⚠️ 注意事项:

  • Selector 是不可变的,创建后不能修改(除非使用 matchExpressions 且在特定版本支持)
  • Pod 模板中的标签必须匹配 Selector
  • 避免与同命名空间下其他 Deployment 的标签重叠

2.4 策略类型(strategy)

Deployment 支持两种更新策略:

2.4.1 RollingUpdate(滚动更新)

yaml

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1           # 最大超过副本数
      maxUnavailable: 0     # 最大不可用副本数

参数详解:

参数 类型 说明 示例值
maxSurge int/percentage 更新过程中最多超出期望副本数 125%
maxUnavailable int/percentage 更新过程中最多不可用副本数 025%

滚动更新示意图:

plaintext

初始状态: 3 个 Pod (v1)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Step 1: 启动 1 个新 Pod (v2)
      maxSurge=1
      ┌─────────────────────────────────────────────────────────────┐
      │  [Pod-v1] [Pod-v1] [Pod-v1]  →  [Pod-v2]                   │
      │                                     ↑                       │
      │                                     新启动                  │
      └─────────────────────────────────────────────────────────────┘

Step 2: 终止 1 个旧 Pod (v1)
      maxUnavailable=0, 所以先增后减
      ┌─────────────────────────────────────────────────────────────┐
      │  [Pod-v1] [Pod-v1] [Pod-v2]                                │
      │       ↓                                                   │
      │    终止 1 个                                               │
      └─────────────────────────────────────────────────────────────┘

Step 3-4: 重复 Step 1-2
      ┌─────────────────────────────────────────────────────────────┐
      │  [Pod-v1] [Pod-v2] [Pod-v2]  →  [Pod-v1] [Pod-v2] [Pod-v2]  │
      │       ↓                    替换        ↓                   │
      │    终止旧                    完成      终止旧                │
      └─────────────────────────────────────────────────────────────┘

最终状态: 3 个 Pod (v2)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

2.4.2 Recreate(重建)

yaml

spec:
  strategy:
    type: Recreate

重建策略示意图:

plaintext

┌─────────────────────────────────────────────────────────────────────┐
│                      Recreate 策略执行流程                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│   时间线 ──────────────────────────────────────────────────────▶    │
│                                                                      │
│   阶段1: 终止所有旧 Pod                                              │
│   ┌──────────────────────────────────────────────────────────────┐  │
│   │  [Pod-v1] [Pod-v1] [Pod-v1]  ──X──X──X──▶  (空)               │  │
│   │      ✗       ✗       ✗                                          │  │
│   └──────────────────────────────────────────────────────────────┘  │
│                              │                                       │
│                              │ (等待所有 Pod 真正终止)                │
│                              ▼                                       │
│   阶段2: 创建所有新 Pod                                              │
│   ┌──────────────────────────────────────────────────────────────┐  │
│   │  (空)  ──▶  [Pod-v2] [Pod-v2] [Pod-v2]                       │  │
│   │                     + + +                                    │  │
│   └──────────────────────────────────────────────────────────────┘  │
│                                                                      │
│   ⚠️ 注意: 存在服务中断窗口                                          │
└─────────────────────────────────────────────────────────────────────┘

策略选择建议:

策略 适用场景 优点 缺点
RollingUpdate 大多数生产环境 零宕机、平滑过渡 更新时间长、资源占用高
Recreate 无法容忍旧新版本共存 简单、资源占用低 有服务中断窗口

三、工作原理深度剖析

3.1 控制器架构

Deployment 控制器是 Kubernetes 控制平面的一部分:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                          Kubernetes Control Plane                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│    ┌────────────────────────────────────────────────────────────────────┐   │
│    │                        API Server (6443)                           │   │
│    │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐           │   │
│    │  │ REST API │  │  Auth N  │  │  Validat │  │  Mutate  │           │   │
│    │  └──────────┘  └──────────┘  └──────────┘  └──────────┘           │   │
│    └────────────────────────────────────────────────────────────────────┘   │
│                                    │                                         │
│                                    │ Watch/List                             │
│                                    ▼                                         │
│    ┌────────────────────────────────────────────────────────────────────┐   │
│    │                        etcd (数据存储)                              │   │
│    │  ┌──────────┐  ┌──────────┐  ┌──────────┐                         │   │
│    │  │Deployments│  │ReplicaSets│  │   Pods   │                         │   │
│    │  └──────────┘  └──────────┘  └──────────┘                         │   │
│    └────────────────────────────────────────────────────────────────────┘   │
│                                    ▲                                         │
│                                    │                                         │
│    ┌────────────────────────────────────────────────────────────────────┐   │
│    │                     Controller Manager                             │   │
│    │  ┌────────────────────┐  ┌────────────────────┐                   │   │
│    │  │ Deployment Controller│  │ ReplicaSet Controller│                 │   │
│    │  │  • 创建/更新 ReplicaSet│  │  • 管理 Pod 副本    │                   │   │
│    │  │  • 管理版本历史      │  │  • 处理 Pod 故障    │                   │   │
│    │  └────────────────────┘  └────────────────────┘                   │   │
│    │  ┌────────────────────┐  ┌────────────────────┐                   │   │
│    │  │    Node Controller │  │  Resource Controller│                  │   │
│    │  │  • 节点健康检测     │  │  • HPA 扩缩容       │                   │   │
│    │  └────────────────────┘  └────────────────────┘                   │   │
│    └────────────────────────────────────────────────────────────────────┘   │
│                                    │                                         │
└────────────────────────────────────│────────────────────────────────────────┘
                                     │
                                     │ 调度与通信
        ┌────────────────────────────┼────────────────────────────┐
        ▼                            ▼                            ▼
┌───────────────┐          ┌───────────────┐          ┌───────────────┐
│   Node 1      │          │   Node 2      │          │   Node 3      │
│ ┌───────────┐ │          │ ┌───────────┐ │          │ ┌───────────┐ │
│ │  kubelet  │ │          │ │  kubelet  │ │          │ │  kubelet  │ │
│ │    ↓      │ │          │ │    ↓      │ │          │ │    ↓      │ │
│ │  Pod 运行 │ │          │ │  Pod 运行 │ │          │ │  Pod 运行 │ │
│ └───────────┘ │          │ └───────────┘ │          │ └───────────┘ │
└───────────────┘          └───────────────┘          └───────────────┘

3.2 创建流程

Deployment 创建时的资源生成链:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                        Deployment 创建流程                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  用户操作                                                                    │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │  kubectl apply -f deployment.yaml                                   │    │
│  │  或: kubectl create deployment my-app --image=nginx:latest           │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    ▼                                         │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                         API Server                                    │    │
│  │  1. 认证 & 授权                                                       │    │
│  │  2. 验证 YAML 合法性                                                  │    │
│  │  3. 写入 etcd (Deployment 对象)                                       │    │
│  │  4. 返回 success 给客户端                                             │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    │ Deployment Controller 监听到新对象      │
│                                    ▼                                         │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                    Deployment Controller                              │    │
│  │                                                                        │    │
│  │  1. 创建 ReplicaSet (初始版本 revision=1)                            │    │
│  │  ┌──────────────────────────────────────────────────────────────┐     │    │
│  │  │  ReplicaSet Spec:                                             │     │    │
│  │  │    replicas: 3                                                │     │    │
│  │  │    selector: {app: my-app}                                   │     │    │
│  │  │    template: {Pod 模板内容}                                   │     │    │
│  │  └──────────────────────────────────────────────────────────────┘     │    │
│  │                                                                        │    │
│  │  2. 记录版本历史 (deployment.kubernetes.io/revision-history)          │    │
│  │  3. 设置注解 (deployment.kubernetes.io/revision: "1")                 │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    │ ReplicaSet Controller 监听到新对象      │
│                                    ▼                                         │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                      ReplicaSet Controller                            │    │
│  │                                                                        │    │
│  │  计算: desired(3) - current(0) = 需要创建 3 个 Pod                     │    │
│  │                                                                        │    │
│  │  调用 Scheduler                                                      │    │
│  │  ┌──────────────────────────────────────────────────────────────┐     │    │
│  │  │  调度决策:                                                     │     │    │
│  │  │    Pod-1 → Node-1 (资源充足)                                  │     │    │
│  │  │    Pod-2 → Node-2 (资源充足)                                  │     │    │
│  │  │    Pod-3 → Node-3 (资源充足)                                  │     │    │
│  │  └──────────────────────────────────────────────────────────────┘     │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    │ kubelet 在各节点上创建 Pod              │
│                                    ▼                                         │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                           kubelet                                     │    │
│  │                                                                        │    │
│  │  1. 从容器运行时拉取镜像                                              │    │
│  │  2. 创建容器 (Pause 容器 + 业务容器)                                   │    │
│  │  3. 配置网络 (CNI 插件)                                               │    │
│  │  4. 启动并监控容器                                                     │    │
│  │  5. 汇报状态给 API Server                                             │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    ▼                                         │
│                           Pod Running ✓                                     │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

3.3 更新流程(滚动更新机制)

Deployment 更新时的滚动升级流程:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                        滚动更新详细流程                                      │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  假设: replicas=3, maxSurge=1, maxUnavailable=0                              │
│  初始: 3 个 v1 Pod                                                          │
│  更新: 镜像从 nginx:1.21 → nginx:1.25                                       │
│                                                                              │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                       Deployment 更新                                 │    │
│  │                                                                        │    │
│  │  触发方式:                                                            │    │
│  │    • kubectl apply -f deployment.yaml                               │    │
│  │    • kubectl set image deployment/my-app nginx=nginx:1.25          │    │
│  │    • kubectl edit deployment my-app                                 │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    ▼                                         │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                  Deployment Controller 处理                            │    │
│  │                                                                        │    │
│  │  1. 创建新的 ReplicaSet (revision=2)                                  │    │
│  │     - 副本数: maxSurge (1)                                            │    │
│  │                                                                        │    │
│  │  2. 更新旧 ReplicaSet (revision=1)                                    │    │
│  │     - 副本数: 逐步减少                                                  │    │
│  │                                                                        │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
└────────────────────────────────────│────────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           滚动更新进度可视化                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  状态    │  Node-1       │  Node-2       │  Node-3       │ 说明             │
│  ────────┼───────────────┼───────────────┼───────────────┼────────────────  │
│          │               │               │               │                  │
│  初始    │  [Pod-v1]     │  [Pod-v1]     │  [Pod-v1]     │ 3 个 v1 Pod      │
│          │               │               │               │                  │
│  Step 1  │  [Pod-v1]     │  [Pod-v1]     │  [Pod-v1]     │ 新 RS 启动 1 个  │
│          │               │               │  [Pod-v2]  NEW│ v2 Pod (maxSurge)│
│          │               │               │               │                  │
│  Step 2  │  [Pod-v1]     │  [Pod-v1]     │  [Pod-v2]     │ 终止 1 个 v1     │
│          │      ✗        │               │               │ (maxUnavailable=0)│
│          │               │               │               │                  │
│  Step 3  │  [Pod-v1]     │  [Pod-v2] NEW │  [Pod-v2]     │ 新 RS 再启动 1 个│
│          │               │               │               │                  │
│  Step 4  │  [Pod-v1]     │  [Pod-v2]     │  [Pod-v2]     │ 再终止 1 个 v1   │
│          │      ✗        │               │               │                  │
│  Step 5  │  [Pod-v2] NEW │  [Pod-v2]     │  [Pod-v2]     │ 最后 1 个 v2     │
│          │               │               │               │                  │
│  Step 6  │  [Pod-v2]     │  [Pod-v2]     │  [Pod-v2]     │ 最后 1 个 v1 终止 │
│          │               │      ✗        │               │                  │
│          │               │               │               │                  │
│  完成    │  [Pod-v2]     │  [Pod-v2]     │  [Pod-v2]     │ 全 v2 ✓           │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

3.4 回滚机制

Deployment 自动保存历史版本,支持快速回退:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                           回滚机制原理                                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  回滚命令:                                                                  │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │  # 回滚到上一个版本                                                   │    │
│  │  kubectl rollout undo deployment/my-app                              │    │
│  │                                                                        │    │
│  │  # 回滚到指定版本                                                     │    │
│  │  kubectl rollout undo deployment/my-app --to-revision=2             │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    ▼                                         │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                    版本历史管理                                        │    │
│  │                                                                        │    │
│  │  Deployment 注解中的版本信息:                                          │    │
│  │  ┌──────────────────────────────────────────────────────────────┐     │    │
│  │  │  kubernetes.io/change-cause: "Update image nginx to 1.25"  │     │    │
│  │  │  deployment.kubernetes.io/revision: "3"                     │     │    │
│  │  └──────────────────────────────────────────────────────────────┘     │    │
│  │                                                                        │    │
│  │  保留的 ReplicaSet 历史 (通过 revisionHistoryLimit 控制):             │    │
│  │  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐                     │    │
│  │  │  RS (v1)    │ │  RS (v2)    │ │  RS (v3)    │  ← 当前活跃         │    │
│  │  │  revision=1 │ │  revision=2 │ │  revision=3 │                     │    │
│  │  │  replicas=0 │ │  replicas=0 │ │  replicas=3 │                     │    │
│  │  └─────────────┘ └─────────────┘ └─────────────┘                     │    │
│  │                                                                        │    │
│  │  revisionHistoryLimit=10 (默认保留 10 个历史版本)                     │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    ▼                                         │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │                    回滚执行过程                                        │    │
│  │                                                                        │    │
│  │  1. 将目标 ReplicaSet 的副本数调整为期望值                             │    │
│  │  2. 将当前 ReplicaSet 的副本数调整为 0                                 │    │
│  │  3. 更新 Deployment 的 revision 注解                                  │    │
│  │  4. 生成新的 rollout 历史记录                                         │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

四、YAML 配置详解

4.1 完整配置示例

yaml

apiVersion: apps/v1                    # API 版本
kind: Deployment                       # 资源类型
metadata:
  name: my-nginx                        # Deployment 名称
  namespace: default                    # 所属命名空间
  labels:                               # Deployment 标签
    app: my-nginx
    tier: frontend
  annotations:                          # 注解
    description: "Nginx web server deployment"
    kubernetes.io/change-cause: "Initialize deployment"
spec:
  replicas: 3                           # 副本数
  
  selector:                             # Pod 选择器(必须匹配 Pod 标签)
    matchLabels:
      app: my-nginx
  
  strategy:                             # 更新策略
    type: RollingUpdate                 # 滚动更新
    rollingUpdate:
      maxSurge: 1                       # 最多超出副本数
      maxUnavailable: 0                 # 最多不可用副本数
  
  minReadySeconds: 10                   # Pod 就绪后最少保持时间
  
  revisionHistoryLimit: 10              # 保留的历史版本数
  
  paused: false                         # 是否暂停更新
  
  progressDeadlineSeconds: 600         # 进度超时时间
  
  template:                             # Pod 模板
    metadata:
      labels:
        app: my-nginx                   # 必须包含 selector 匹配的所有标签
        version: v1
    spec:
      # 容器配置
      containers:
      - name: nginx
        image: nginx:1.25-alpine
        imagePullPolicy: IfNotPresent   # 镜像拉取策略
        ports:
        - name: http
          containerPort: 80
          protocol: TCP
        - name: https
          containerPort: 443
          protocol: TCP
        
        # 资源管理
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "500m"
        
        # 健康检查
        livenessProbe:
          httpGet:
            path: /healthz
            port: http
          initialDelaySeconds: 10
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        
        readinessProbe:
          httpGet:
            path: /ready
            port: http
          initialDelaySeconds: 5
          periodSeconds: 5
          successThreshold: 1
          failureThreshold: 3
        
        # 启动探针(K8s 1.16+)
        startupProbe:
          httpGet:
            path: /healthz
            port: http
          failureThreshold: 30
          periodSeconds: 10
        
        # 环境变量
        env:
        - name: APP_ENV
          value: "production"
        - name: LOG_LEVEL
          value: "info"
        
        # 配置挂载
        volumeMounts:
        - name: nginx-config
          mountPath: /etc/nginx/conf.d
          readOnly: true
        - name: nginx-cache
          mountPath: /var/cache/nginx
        - name: nginx-run
          mountPath: /var/run
      
      # 初始化容器(如需要)
      initContainers:
      - name: init-myservice
        image: busybox:1.36
        command: ['sh', '-c', 'echo Waiting for service; sleep 5']
      
      # 亲和性配置
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: my-nginx
              topologyKey: kubernetes.io/hostname
      
      # 容忍污点
      tolerations:
      - key: "node-role"
        operator: "Equal"
        value: "web"
        effect: "NoSchedule"
      
      # 安全上下文
      securityContext:
        runAsNonRoot: true
        runAsUser: 101
        fsGroup: 101
      
      # 镜像拉取凭证
      imagePullSecrets:
      - name: my-registry-secret
  
  # 共享存储卷
  volumes:
  - name: nginx-config
    configMap:
      name: nginx-config
      items:
      - key: default.conf
        path: default.conf
  - name: nginx-cache
    emptyDir:
      sizeLimit: "100Mi"
  - name: nginx-run
    emptyDir: {}

4.2 各字段含义说明

字段路径 类型 必填 说明
apiVersion string API 版本,固定为 apps/v1
kind string 资源类型,固定为 Deployment
metadata.name string Deployment 名称,命名空间内唯一
metadata.namespace string 所属命名空间,默认 default
metadata.labels map Deployment 的标签
metadata.annotations map 注解信息
spec.replicas integer 期望副本数,默认 1
spec.selector object Pod 选择器,定义如何识别管理的 Pod
spec.selector.matchLabels map 标签匹配规则
spec.selector.matchExpressions list 表达式匹配(可选)
spec.strategy.type string 更新策略:RollingUpdateRecreate
spec.strategy.rollingUpdate.maxSurge int/string 滚动更新时最多超出副本数
spec.strategy.rollingUpdate.maxUnavailable int/string 滚动更新时最多不可用副本数
spec.minReadySeconds integer Pod 就绪后最少保持时间
spec.revisionHistoryLimit integer 保留的历史版本数,默认 10
spec.paused boolean 是否暂停更新
spec.progressDeadlineSeconds integer 进度超时时间(秒)
spec.template object Pod 模板规格
spec.template.metadata object Pod 元数据
spec.template.spec object Pod 规格定义

4.3 常用配置模式

4.3.1 基础 Web 服务

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-service
  template:
    metadata:
      labels:
        app: web-service
    spec:
      containers:
      - name: web
        image: nginx:1.25-alpine
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "50m"
          limits:
            memory: "128Mi"
            cpu: "200m"

4.3.2 高可用多副本服务

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ha-service
spec:
  replicas: 5
  selector:
    matchLabels:
      app: ha-service
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 1
  template:
    metadata:
      labels:
        app: ha-service
    spec:
      affinity:
        # Pod 反亲和,确保副本分布在不同节点
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: ha-service
            topologyKey: kubernetes.io/hostname
      containers:
      - name: service
        image: myapp:v2.0
        ports:
        - containerPort: 8080

4.3.3 配置健康检查的服务

yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-with-probes
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app-with-probes
  template:
    metadata:
      labels:
        app: app-with-probes
    spec:
      containers:
      - name: app
        image: myapp:v1.0
        ports:
        - containerPort: 8080
        
        # 启动探针(容器启动期间使用)
        startupProbe:
          httpGet:
            path: /startup
            port: 8080
          failureThreshold: 30
          periodSeconds: 10
        
        # 存活探针(检测容器是否存活)
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 20
          timeoutSeconds: 3
          failureThreshold: 3
        
        # 就绪探针(检测是否可以接收流量)
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
          timeoutSeconds: 3
          failureThreshold: 3
          successThreshold: 1

五、常用操作指南

5.1 创建与删除

bash

# 创建 Deployment
kubectl apply -f deployment.yaml

# 或使用命令创建
kubectl create deployment my-app --image=nginx:latest --replicas=3

# 查看创建状态
kubectl get deployment my-app
kubectl rollout status deployment/my-app

# 删除 Deployment(会同时删除关联的 ReplicaSet 和 Pod)
kubectl delete deployment my-app

# 强制删除(如果卡住)
kubectl delete deployment my-app --grace-period=0 --force

# 删除并等待完成
kubectl delete deployment my-app --wait=true

5.2 扩缩容

5.2.1 手动扩缩容

bash

# 扩容到 5 个副本
kubectl scale deployment my-app --replicas=5

# 缩容到 1 个副本
kubectl scale deployment my-app --replicas=1

# 扩缩容多个 Deployment
kubectl scale deployment app1,app2,app3 --replicas=3

# 条件扩缩容(仅当副本数满足条件时才执行)
kubectl scale deployment my-app --current-replicas=3 --replicas=5

5.2.2 HPA 自动扩缩容

bash

# 创建 HPA
kubectl autoscale deployment my-app --min=2 --max=10 --cpu-percent=80

# 查看 HPA
kubectl get hpa

# 删除 HPA
kubectl delete hpa my-app

HPA 配合 Deployment 示例:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                           HPA + Deployment 联动                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│    ┌───────────────┐                                                         │
│    │     HPA       │                                                         │
│    │  min=2        │                                                         │
│    │  max=10       │                                                         │
│    │  target=80%   │                                                         │
│    └───────┬───────┘                                                         │
│            │                                                                  │
│            │ 动态调整 replicas                                                │
│            ▼                                                                  │
│    ┌────────────────────────────────────────────────────────────────────┐    │
│    │                      Deployment Controller                          │    │
│    │                                                                        │    │
│    │   CPU 使用率 ──▶ 高 ──────────▶ replicas: 2 → 3 → 5 → 8 → 10     │    │
│    │   CPU 使用率 ──▶ 低 ──────────▶ replicas: 10 → 8 → 5 → 3 → 2      │    │
│    │                                                                        │    │
│    └────────────────────────────────────────────────────────────────────┘    │
│                                                                              │
│   扩缩容触发条件:                                                            │
│   • 当前 CPU 使用率 > targetCPUUtilizationPercentage → 扩容                 │
│   • 当前 CPU 使用率 < targetCPUUtilizationPercentage → 缩容                 │
│   • 冷却时间: 5 分钟(扩容)、5 分钟(缩容)                                │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

5.3 更新策略配置

bash

# 查看当前更新策略
kubectl get deployment my-app -o jsonpath='{.spec.strategy}'

# 修改更新策略(立即生效)
kubectl patch deployment my-app -p '{"spec":{"strategy":{"type":"RollingUpdate","rollingUpdate":{"maxSurge":2,"maxUnavailable":1}}}}'

# 或使用 edit
kubectl edit deployment my-app

常见策略配置组合:

场景 maxSurge maxUnavailable 说明
保守更新 1 0 逐个替换,最安全
快速更新 2 1 平衡速度和安全性
激进更新 3 1 快速但资源占用高
最大效率 25% 25% 按百分比计算

5.4 版本回滚

bash

# 查看部署历史
kubectl rollout history deployment/my-app

# 查看特定版本的详细信息
kubectl rollout history deployment/my-app --revision=3

# 回滚到上一个版本
kubectl rollout undo deployment/my-app

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

# 查看回滚状态
kubectl rollout status deployment/my-app

5.5 暂停与恢复更新

bash

# 暂停更新(用于批量修改)
kubectl rollout pause deployment/my-app

# 执行多次修改(不会触发滚动更新)
kubectl set image deployment/my-app nginx=nginx:1.24
kubectl set resources deployment/my-app --limits=cpu=500m,memory=256Mi
kubectl label deployment/my-app version=v2

# 查看暂停状态
kubectl get deployment my-app -o jsonpath='{.spec.paused}' # true 表示暂停

# 恢复更新(触发滚动更新)
kubectl rollout resume deployment/my-app

# ⚠️ 注意事项:恢复时会一次性应用所有暂停期间的变更

暂停/恢复流程:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                      暂停与恢复更新流程                                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  Step 1: 暂停                                                               │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │  kubectl rollout pause deployment/my-app                             │    │
│  │                                                                       │    │
│  │  结果: spec.paused = true                                            │    │
│  │        Controller 停止监听 Deployment 变更                          │    │
│  │        ReplicaSet 保持不变                                           │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    ▼                                         │
│  Step 2: 多次修改(不触发滚动更新)                                          │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │  kubectl set image deployment/my-app nginx=nginx:1.24              │    │
│  │  kubectl set image deployment/my-app nginx=nginx:1.25              │    │
│  │  kubectl set image deployment/my-app nginx=nginx:1.26              │    │
│  │                                                                       │    │
│  │  Deployment spec 已更新,但 ReplicaSet 不受影响                      │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                    │                                         │
│                                    ▼                                         │
│  Step 3: 恢复(一次性应用所有变更)                                          │
│  ┌──────────────────────────────────────────────────────────────────────┐    │
│  │  kubectl rollout resume deployment/my-app                           │    │
│  │                                                                       │    │
│  │  Controller 检测到 paused=false                                     │    │
│  │  发现 spec 与当前 ReplicaSet 不同                                    │    │
│  │  创建新 ReplicaSet 并触发一次滚动更新                                │    │
│  │  (应用的是最后一次的镜像)                                           │    │
│  └──────────────────────────────────────────────────────────────────────┘    │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

5.6 其他常用命令

bash

# 获取 Deployment 详情
kubectl describe deployment my-app

# 查看 Pod 分布
kubectl get pods -l app=my-app -o wide

# 查看 Deployment 事件
kubectl get events --field-selector involvedObject.name=my-app

# 导出 YAML
kubectl get deployment my-app -o yaml > deployment-backup.yaml

# 应用部分更新(使用 patch)
kubectl patch deployment my-app -p '{"spec":{"replicas":5}}'

# 强制替换(删除后重建,用于不可修改字段)
kubectl replace --force -f deployment.yaml

六、高级特性

6.1 滚动更新参数详解

yaml

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      # maxSurge: 最大超出副本数
      # 形式: 整数 (如 1) 或 百分比 (如 25%)
      # 效果: 滚动更新期间,Pod 总数可以超过 replicas 数量
      maxSurge: 1                    # 或 "25%"
      
      # maxUnavailable: 最大不可用副本数
      # 形式: 整数 (如 1) 或 百分比 (如 25%)
      # 效果: 滚动更新期间,可以有最多这么多 Pod 不可用
      maxUnavailable: 0              # 或 "25%"
      
  # minReadySeconds: Pod 就绪后最少保持时间
  # Pod 必须持续运行这段时间才被认为可用
  minReadySeconds: 10
  
  # progressDeadlineSeconds: 进度超时时间
  # 如果在指定秒数内没有进度,Deployment 状态标记为 False
  progressDeadlineSeconds: 600

参数组合效果:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                    maxSurge 与 maxUnavailable 组合效果                       │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  replicas=3 时的 Pod 数量变化:                                               │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐     │
│  │  配置组合              │  最大 Pod 数 │  最小可用 Pod │  更新速度    │     │
│  ├────────────────────────┼──────────────┼───────────────┼────────────  │     │
│  │  maxSurge=0, maxUnav=0 │     ❌ 不可能(无意义)                       │     │
│  ├────────────────────────┼──────────────┼───────────────┼────────────  │     │
│  │  maxSurge=1, maxUnav=0 │   3+1=4       │     3         │   慢        │     │
│  ├────────────────────────┼──────────────┼───────────────┼────────────  │     │
│  │  maxSurge=0, maxUnav=1 │   3          │   3-1=2        │   慢        │     │
│  ├────────────────────────┼──────────────┼───────────────┼────────────  │     │
│  │  maxSurge=1, maxUnav=1 │   3+1=4       │   3-1=2        │   中等     │     │
│  ├────────────────────────┼──────────────┼───────────────┼────────────  │     │
│  │  maxSurge=25%, maxUnav=0│  ceil(3*1.25)=4│    3          │   慢        │     │
│  ├────────────────────────┼──────────────┼───────────────┼────────────  │     │
│  │  maxSurge=25%, maxUnav=25%│ ceil(3*1.25)=4│ ceil(3*0.75)=3│  中等      │     │
│  └─────────────────────────────────────────────────────────────────────┘     │
│                                                                              │
│  图示:                                                                       │
│  ┌─────────────────────────────────────────────────────────────────────┐     │
│  │  maxSurge=1, maxUnav=0  (最安全,资源消耗大)                         │     │
│  │  ┌────┬────┬────┬────┐                                              │     │
│  │  │ v1 │ v1 │ v1 │ v2 │ → ✗ → │ v2 │ v2 │ v2 │                       │     │
│  │  └────┴────┴────┴────┘        └────┴────┴────┘                      │     │
│  │  同时最多 4 个 Pod,v1 全部终止后 v2 才完全接管                       │     │
│  └─────────────────────────────────────────────────────────────────────┘     │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────┐     │
│  │  maxSurge=1, maxUnav=1  (平衡模式)                                   │     │
│  │  ┌────┬────┬────┬────┐                                              │     │
│  │  │ v1 │ v1 │ v1 │ v2 │ → ✗ → │ v1 │ v2 │ v2 │ → ✗ → │ v2 │ v2 │ v2 │    │
│  │  └────┴────┴────┴────┘      └────┴────┴────┘       └────┴────┴────┘   │
│  │  同时最多 4 个 Pod,最少 2 个可用                                    │     │
│  └─────────────────────────────────────────────────────────────────────┘     │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

6.2 金丝雀发布

金丝雀发布允许将新版本逐步推向小部分用户:

yaml

# 1. 主版本 Deployment(v1,承载 95% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-stable
  labels:
    app: my-app
    track: stable
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      track: stable
  template:
    metadata:
      labels:
        app: my-app
        track: stable
    spec:
      containers:
      - name: my-app
        image: myapp:v1
        ports:
        - containerPort: 8080

---
# 2. 金丝雀 Deployment(v2,承载 5% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-canary
  labels:
    app: my-app
    track: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
      track: canary
  template:
    metadata:
      labels:
        app: my-app
        track: canary
    spec:
      containers:
      - name: my-app
        image: myapp:v2
        ports:
        - containerPort: 8080

---
# 3. Service 选择器(同时覆盖两个版本)
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
spec:
  selector:
    app: my-app          # 匹配所有 track
  ports:
  - port: 80
    targetPort: 8080

金丝雀发布流量分配:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                         金丝雀发布架构                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│                           用户请求                                           │
│                               │                                               │
│                               ▼                                               │
│                    ┌────────────────────┐                                    │
│                    │      Service      │                                    │
│                    │   (selector: app)  │                                    │
│                    └─────────┬──────────┘                                    │
│                              │                                               │
│              ┌───────────────┴───────────────┐                               │
│              │                               │                               │
│              ▼                               ▼                               │
│    ┌─────────────────┐             ┌─────────────────┐                       │
│    │  Stable (v1)    │             │   Canary (v2)   │                       │
│    │  replicas: 3    │             │   replicas: 1    │                       │
│    │  track=stable   │             │   track=canary   │                       │
│    └────────┬────────┘             └────────┬────────┘                       │
│             │                               │                                │
│             ▼                               ▼                                │
│    ┌─────────────┐                 ┌─────────────┐                          │
│    │ Pod-1 v1 ✓  │                 │ Pod-4 v2 ✓  │                          │
│    │ Pod-2 v1 ✓  │                 └─────────────┘                          │
│    │ Pod-3 v1 ✓  │                                                     │
│    └─────────────┘                                                     │
│                                                                          │
│    流量比例: 75% ────────────→ Stable                                   │
│              25% ───→ Canary                                            │
│                                                                          │
│    提升金丝雀: replicas: 1 → 3 (50% 流量)                               │
│    完全发布: 合并配置,删除 canary deployment                           │
│    回滚: 删除 canary deployment                                         │
│                                                                          │
└─────────────────────────────────────────────────────────────────────────────┘

6.3 蓝绿部署

蓝绿部署通过两套完整环境实现即时切换:

yaml

# 蓝环境 Deployment(当前生产环境)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-blue
  labels:
    app: my-app
    env: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      env: blue
  template:
    metadata:
      labels:
        app: my-app
        env: blue
    spec:
      containers:
      - name: my-app
        image: myapp:v1
        ports:
        - containerPort: 8080

---
# 蓝环境 Service
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
spec:
  selector:
    app: my-app
    env: blue
  ports:
  - port: 80
    targetPort: 8080

蓝绿部署流程:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                         蓝绿部署流程                                         │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  阶段 1: 初始状态(蓝环境为生产)                                            │
│  ┌─────────────────────────────────────────────────────────────────────┐     │
│  │  ┌─────────────┐                          ┌─────────────┐         │     │
│  │  │   蓝 v1      │ ◀── active              │   绿 v2      │         │     │
│  │  │ (生产环境)   │                          │ (预发布环境)  │         │     │
│  │  │ replicas=3  │                          │ replicas=3   │         │     │
│  │  └─────────────┘                          └─────────────┘         │     │
│  │          │                                        │                 │     │
│  │          └──────────────┬──────────────────────────┘                 │     │
│  │                         │                                             │     │
│  │                         ▼                                             │     │
│  │                ┌─────────────────┐                                    │     │
│  │                │     Service     │                                    │     │
│  │                │ selector: env=blue  ← 流量全部进入蓝环境             │     │
│  │                └─────────────────┘                                    │     │
│  └─────────────────────────────────────────────────────────────────────┘     │
│                                                                              │
│  阶段 2: 部署绿环境                                                          │
│  ┌─────────────────────────────────────────────────────────────────────┐     │
│  │  # 更新绿环境 Deployment                                               │     │
│  │  kubectl apply -f my-app-green.yaml                                 │     │
│  │                                                                        │     │
│  │  测试绿环境(直接访问)                                                 │     │
│  │  kubectl run test --image=curlimages/curl --rm -it --restart=Never   │     │
│  │    -- curl http://<green-pod-ip>:8080/health                         │     │
│  └─────────────────────────────────────────────────────────────────────┘     │
│                                                                              │
│  阶段 3: 切换流量(蓝绿切换)                                                │
│  ┌─────────────────────────────────────────────────────────────────────┐     │
│  │  # 修改 Service selector 切换到绿环境                                 │     │
│  │  kubectl patch service my-app-svc -p '{"spec":{"selector":{"env":"green"}}}'  │
│  │                                                                        │     │
│  │  ┌──────────────────────────────────────────────────────────────┐     │     │
│  │  │                Service selector: env=green                   │     │     │
│  │  │                     ↓ 流量切换                                 │     │     │
│  │  │          ┌─────────────┐                                      │     │     │
│  │  │          │   绿 v2      │ ◀── 新生产环境 (active)              │     │     │
│  │  │          └─────────────┘                                      │     │     │
│  │  │                ✗                                               │     │     │
│  │  │          ┌─────────────┐                                      │     │     │
│  │  │          │   蓝 v1      │ ← 旧环境 (standby)                  │     │     │
│  │  │          └─────────────┘                                      │     │     │
│  │  └──────────────────────────────────────────────────────────────┘     │     │
│  └─────────────────────────────────────────────────────────────────────┘     │
│                                                                              │
│  阶段 4: 回滚(如需要)                                                      │
│  ┌─────────────────────────────────────────────────────────────────────┐     │
│  │  # 一键回滚到蓝环境                                                   │     │
│  │  kubectl patch service my-app-svc -p '{"spec":{"selector":{"env":"blue"}}}'  │
│  └─────────────────────────────────────────────────────────────────────┘     │
│                                                                              │
│  优点: 即时切换,零停机,支持快速回滚                                        │
│  缺点: 需要双倍资源                                                          │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

6.4 与 HPA/VPA 配合

6.4.1 HPA(水平自动扩缩容)

yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300    # 缩容冷却 5 分钟
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0      # 扩容立即执行
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
      selectPolicy: Max

6.4.2 VPA(垂直自动扩缩容)

yaml

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Auto"                   # Auto 或 Off
  resourcePolicy:
    containerPolicies:
    - containerName: my-app
      minAllowed:
        cpu: 50m
        memory: 64Mi
      maxAllowed:
        cpu: 2
        memory: 1Gi
      controlledResources: ["cpu", "memory"]

6.4.3 HPA + VPA 结合

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                      HPA 与 VPA 结合使用                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│                           ┌──────────────────────┐                          │
│                           │       HPA            │                          │
│                           │  水平扩缩容           │                          │
│                           │  控制 replicas        │                          │
│                           └──────────┬───────────┘                          │
│                                      │                                        │
│                                      │                                        │
│  ┌───────────────────────────────────┼───────────────────────────────────┐  │
│  │                                   ▼                                    │  │
│  │                        ┌──────────────────────┐                       │  │
│  │                        │     Deployment       │                       │  │
│  │                        │                      │                       │  │
│  │                        │   replicas: 3 → 6    │                       │  │
│  │                        │   (HPA 扩容)          │                       │  │
│  │                        └──────────┬───────────┘                       │  │
│  │                                   │                                    │  │
│  │                                   │                                    │  │
│  │                                   ▼                                    │  │
│  │                        ┌──────────────────────┐                       │  │
│  │                        │       VPA            │                       │  │
│  │                        │  垂直扩缩容           │                       │  │
│  │                        │  控制 resources       │                       │  │
│  │                        └──────────┬───────────┘                       │  │
│  │                                   │                                    │  │
│  └───────────────────────────────────┼───────────────────────────────────┘  │
│                                      │                                        │
│                                      ▼                                        │
│                           ┌──────────────────────┐                          │
│                           │        Pod           │                          │
│                           │  cpu: 100m → 200m     │                          │
│                           │  memory: 128Mi→ 256Mi │                          │
│                           │  (VPA 调整)           │                          │
│                           └──────────────────────┘                          │
│                                                                              │
│  典型场景:                                                                   │
│  • HPA: 根据 CPU/内存使用率调整副本数                                        │
│  • VPA: 根据历史资源使用自动调整容器规格                                      │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

七、状态与生命周期

7.1 状态字段含义

bash

kubectl get deployment my-app -o wide

输出示例与字段说明:

plaintext

NAME      READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES         SELECTOR
my-app    3/3     1            3           10m   my-app       nginx:1.25     app=my-app

字段 说明
READY 当前就绪 Pod 数 / 期望副本数 (如 3/3)
UP-TO-DATE 已更新到期望版本的 Pod 数
AVAILABLE 可用(就绪且非终止状态)的 Pod 数
AGE Deployment 创建至今的时间

完整状态查看:

bash

kubectl get deployment my-app -o jsonpath='{.status}'

json

{
  "conditions": [
    {
      "type": "Available",
      "status": "True",
      "reason": "MinimumReplicasAvailable",
      "message": "Deployment has minimum availability."
    },
    {
      "type": "Progressing",
      "status": "True",
      "reason": "NewReplicaSetAvailable",
      "message": "ReplicaSet \"my-app-7d9b65c8f5\" has successfully progressed."
    }
  ],
  "replicas": 3,
  "readyReplicas": 3,
  "availableReplicas": 3,
  "updatedReplicas": 1,
  "collisionCount": 0
}

7.2 条件类型判断

Deployment 通过 Conditions 表示当前状态:

Condition Type True 含义 False 含义
Available 至少最小可用副本数就绪 有 Pod 不可用
Progressing Deployment 正在推进(创建/更新中) Deployment 进度卡住
ReplicaFailure - 创建 Pod 失败

Progressing 条件的详细判断:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                      Progressing 条件判断逻辑                                │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│   Progressing = True (满足任一条件):                                         │
│   ┌─────────────────────────────────────────────────────────────────────┐    │
│   │  1. Deployment 正在执行创建或更新                                   │    │
│   │  2. 所有 Pod 都就绪(READY = replicas)                             │    │
│   │  3. 没有正在终止的 Pod                                               │    │
│   └─────────────────────────────────────────────────────────────────────┘    │
│                                                                              │
│   Progressing = False (原因):                                               │
│   ┌─────────────────────────────────────────────────────────────────────┐    │
│   │  reason: "ProgressDeadlineExceeded"                                 │    │
│   │  message: "ReplicaSet "xxx" has not progressed...                  │    │
│   │                                                                       │    │
│   │  可能原因:                                                            │    │
│   │  • 超过 progressDeadlineSeconds 未完成更新                           │    │
│   │  • 镜像拉取失败                                                       │    │
│   │  • 容器启动失败                                                       │    │
│   │  • 资源不足无法调度                                                   │    │
│   └─────────────────────────────────────────────────────────────────────┘    │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

7.3 事件查看与排查

bash

# 查看 Deployment 相关事件
kubectl get events --field-selector involvedObject.name=my-app --sort-by='.lastTimestamp'

# 查看更详细的事件
kubectl describe deployment my-app

# 查看 Pod 事件
kubectl get events --field-selector involvedObject.name=my-app-pod-xxx

# 查看命名空间级别所有事件
kubectl get events -n default --sort-by='.lastTimestamp'

# 过滤特定类型事件
kubectl get events --field-selector type=Warning
kubectl get events --field-selector reason=Failed

# 查看最新事件(实时)
kubectl get events --watch

八、常见问题与排查

8.1 更新卡住

症状: Deployment 长时间处于 Progressing 状态,Pod 数量不变化。

排查步骤:

bash

# 1. 检查 Deployment 状态
kubectl get deployment my-app
kubectl describe deployment my-app

# 2. 检查 ReplicaSet 状态
kubectl get rs -l app=my-app

# 3. 检查新 ReplicaSet 的 Pod
kubectl get pods -l app=my-app,pod-template-hash=xxx --show-labels

# 4. 检查 Pod 事件
kubectl describe pod <pod-name>

# 5. 检查 Pod 日志
kubectl logs <pod-name> --previous  # --previous 查看前一个容器的日志

常见原因及解决方案:

原因 诊断方法 解决方案
镜像拉取失败 kubectl describe pod 查看 Failed to pull image 配置正确的镜像仓库凭证
容器启动失败 kubectl logs 查看错误日志 修复应用代码或配置
存活探针失败 kubectl describe pod 查看探针信息 调整探针参数或修复应用
资源不足 kubectl describe node 查看资源 扩容节点或调整资源请求
节点不可用 kubectl get node 查看 NotReady 修复节点或驱逐 Pod

强制完成卡住的 Deployment:

bash

# 方法1: 增加 progressDeadlineSeconds
kubectl patch deployment my-app -p '{"spec":{"progressDeadlineSeconds":1200}}'

# 方法2: 标记为 Failed(可用于触发回滚)
kubectl annotate deployment my-app kubernetes.io/change-cause="Force complete"

# 方法3: 删除卡住的 ReplicaSet(慎用)
kubectl delete rs <stuck-replicaset-name>

# 方法4: 回滚
kubectl rollout undo deployment/my-app

8.2 Pod 启动失败

症状: Pod 处于 PendingImagePullBackOffCrashLoopBackOffError 等状态。

排查流程:

plaintext

┌─────────────────────────────────────────────────────────────────────────────┐
│                         Pod 启动失败排查流程                                 │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  kubectl get pods -l app=my-app                                              │
│                                                                              │
│  │                                                                           │
│  ├─→ ContainerCreating                                                        │
│  │       │                                                                   │
│  │       ├─→ 原因: 镜像拉取中                                                │
│  │       │       解决: 等待或检查镜像仓库                                     │
│  │       │                                                                   │
│  │       ├─→ 原因: CNI 网络插件问题                                          │
│  │       │       解决: 检查 CNI 配置和节点网络                                │
│  │       │                                                                   │
│  │       └─→ 原因: 资源不足无法调度                                          │
│  │               解决: 检查节点资源或调整资源请求                             │
│  │                                                                           │
│  ├─→ ImagePullBackOff                                                         │
│  │       │                                                                   │
│  │       ├─→ 原因: 镜像不存在                                                │
│  │       │       解决: 检查镜像名称和 tag                                    │
│  │       │                                                                   │
│  │       ├─→ 原因: 镜像仓库认证失败                                          │
│  │       │       解决: 配置 imagePullSecrets                                 │
│  │       │                                                                   │
│  │       └─→ 原因: 网络问题无法访问镜像仓库                                   │
│  │               解决: 检查节点网络配置                                      │
│  │                                                                           │
│  ├─→ CrashLoopBackOff                                                        │
│  │       │                                                                   │
│  │       ├─→ 原因: 应用启动失败                                               │
│  │       │       解决: kubectl logs <pod-name> 查看日志                      │
│  │       │                                                                   │
│  │       ├─→ 原因: 健康检查过于严格                                          │
│  │       │       解决: 调整 liveness/readinessProbe                          │
│  │       │                                                                   │
│  │       └─→ 原因: 依赖服务不可用                                             │
│  │               解决: 检查应用依赖配置                                       │
│  │                                                                           │
│  ├─→ Error                                                                   │
│  │       │                                                                   │
│  │       └─→ 原因: OOMKilled、资源限制、致命错误                              │
│  │               解决: kubectl describe pod 查看事件                        │
│  │                                                                           │
│  └─→ Pending                                                                  │
│          │                                                                   │
│          ├─→ 原因: 调度失败(无满足条件的节点)                               │
│          │       解决: 检查 affinity/taint/nodeSelector                      │
│          │                                                                   │
│          └─→ 原因: PVC 绑定等待                                              │
│                  解决: 检查 PersistentVolumeClaim 状态                      │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

详细排查命令:

bash

# 查看 Pod 详细状态
kubectl describe pod <pod-name>

# 查看 Pod 日志
kubectl logs <pod-name>
kubectl logs <pod-name> --previous        # 前一个容器的日志

# 进入 Pod 调试
kubectl exec -it <pod-name> -- /bin/sh

# 查看资源配额
kubectl describe resourcequota
kubectl describe limitrange

# 检查调度原因
kubectl get events --field-selector involvedObject.name=<pod-name>

8.3 回滚失败

症状: 回滚命令执行后没有效果或报错。

排查步骤:

bash

# 1. 确认回滚命令执行结果
kubectl rollout undo deployment/my-app --to-revision=2
kubectl rollout status deployment/my-app

# 2. 查看回滚历史
kubectl rollout history deployment/my-app

# 3. 检查 ReplicaSet 状态
kubectl get rs -l app=my-app -o wide

# 4. 检查新 Pod 状态
kubectl get pods -l app=my-app

常见回滚失败原因:

原因 现象 解决方案
指定版本不存在 error: unable to find revision 2 使用 kubectl rollout history 查看可用版本
Deployment 暂停 回滚不生效 kubectl rollout resume deployment/my-app
ReplicaSet 被删除 版本历史丢失 无法回滚,需手动重建
权限不足 权限错误 检查 RBAC 配置

手动回滚方法:

bash

# 如果自动回滚失败,可以手动执行:

# 1. 查看当前配置
kubectl get deployment my-app -o yaml > current.yaml

# 2. 找到历史版本的 ReplicaSet
kubectl get rs -l app=my-app

# 3. 从历史 ReplicaSet 获取配置
kubectl get rs <historical-replicaset> -o yaml > historical.yaml

# 4. 修改名称后应用
sed -i 's/name: my-app-xxx/name: my-app-rollback/' historical.yaml
kubectl apply -f historical.yaml

# 5. 修改 Deployment 指向新 ReplicaSet
kubectl scale deployment my-app --replicas=0
kubectl edit deployment my-app
# 修改 selector 中的 pod-template-hash 为新 ReplicaSet 的 hash
kubectl scale deployment my-app --replicas=3

8.4 其他常见问题

8.4.1 Selector 冲突

bash

# 错误: Deployment 与已有 ReplicaSet 冲突
# Error: Failed to create deployment: admission webhook "validationwebhook..." denied

解决方案: 使用唯一的 selector 标签

yaml

# 错误示例
spec:
  selector:
    matchLabels:
      app: my-app    # 可能与现有的 Deployment 冲突

# 正确示例
spec:
  selector:
    matchLabels:
      app: my-app
      version: v1     # 添加额外标签确保唯一

8.4.2 Pod 无法调度

bash

# 查看调度失败原因
kubectl describe pod <pod-name> | grep -A 5 "Events:"

# 常见原因
# - 资源不足: Insufficient memory/cpu
# - 污点不匹配: node(s) had taints that the pod didn't tolerate
# - 亲和性冲突: node(s) didn't match pod affinity/anti-affinity rules

8.4.3 版本历史丢失

bash

# 检查 revisionHistoryLimit 配置
kubectl get deployment my-app -o jsonpath='{.spec.revisionHistoryLimit}'

# 如果为 0,则不会保留历史版本
# 解决方案:设置合适的值
kubectl patch deployment my-app -p '{"spec":{"revisionHistoryLimit":10}}'

九、最佳实践

9.1 资源配置最佳实践

yaml

spec:
  template:
    spec:
      containers:
      - name: app
        # ✅ 必须设置资源请求(调度依据)
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          # ✅ 建议设置资源限制(防止异常)
          limits:
            memory: "512Mi"
            cpu: "500m"
        
        # ✅ 建议添加健康检查
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        
        # ✅ 生产环境建议使用 startupProbe
        startupProbe:
          httpGet:
            path: /healthz
            port: 8080
          failureThreshold: 30
          periodSeconds: 10

9.2 更新策略最佳实践

yaml

spec:
  # ✅ 生产环境推荐使用滚动更新
  strategy:
    type: RollingUpdate
    rollingUpdate:
      # 保守策略:确保服务稳定
      maxSurge: 1              # 最多超出 1 个 Pod
      maxUnavailable: 0        # 保持所有 Pod 可用
  
  # ✅ 设置合理的进度超时
  progressDeadlineSeconds: 600  # 10 分钟内必须完成
  
  # ✅ 设置就绪观察时间
  minReadySeconds: 10          # Pod 稳定运行 10 秒后才认为就绪
  
  # ✅ 保留历史版本用于回滚
  revisionHistoryLimit: 10

9.3 高可用部署策略

yaml

spec:
  # ✅ 生产环境至少 2 个副本
  replicas: 3
  
  # ✅ 使用 Pod 反亲和分散部署
  template:
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app: my-app
              topologyKey: kubernetes.io/hostname
  
  # ✅ 添加 Pod Disruption Budget
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 2    # 或使用 maxUnavailable: 1
  selector:
    matchLabels:
      app: my-app

9.4 版本管理最佳实践

bash

# ✅ 使用 labels 标记版本
kubectl label deployment my-app version=v1.2.3

# ✅ 使用 annotations 记录变更原因
kubectl annotate deployment my-app \
  kubernetes.io/change-cause="Update base image to nginx:1.25-alpine"

# ✅ 避免频繁小版本更新,攒批更新减少滚动次数

# ✅ 发布前在 staging 环境充分测试

# ✅ 使用 pause/resume 进行批量修改
kubectl rollout pause deployment/my-app
# 执行多次配置变更
kubectl rollout resume deployment/my-app

9.5 安全最佳实践

yaml

spec:
  template:
    spec:
      # ✅ 使用非 root 用户运行
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 1000
      
      containers:
      - name: app
        # ✅ 限制容器能力
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
        volumeMounts:
        - name: tmp
          mountPath: /tmp
      
      # ✅ 使用只读根文件系统 + tmp 目录
      volumes:
      - name: tmp
        emptyDir: {}
      
      # ✅ 分离应用和日志存储
      - name: app-storage
        emptyDir:
          sizeLimit: "100Mi"

9.6 监控与日志

bash

# ✅ 部署时添加监控标签
kubectl label deployment my-app \
  app=my-app \
  environment=production \
  team=backend

# ✅ 推荐配置
# - 使用 Prometheus + Grafana 监控 Deployment 状态
# - 配置 Pod 级别的 metrics 采集
# - 收集日志到集中式日志系统(ELK/Loki)
# - 配置告警规则监控 Deployment 状态异常

9.7 快速恢复脚本

bash

#!/bin/bash
# deployment-utils.sh

DEPLOYMENT=$1
NAMESPACE=${2:-default}

# 回滚 Deployment
rollback_deployment() {
    echo "Rolling back $DEPLOYMENT in $NAMESPACE..."
    kubectl rollout undo deployment/$DEPLOYMENT -n $NAMESPACE
    kubectl rollout status deployment/$DEPLOYMENT -n $NAMESPACE
}

# 查看部署状态
status_deployment() {
    echo "=== Deployment Status ==="
    kubectl get deployment $DEPLOYMENT -n $NAMESPACE
    
    echo -e "\n=== ReplicaSet Status ==="
    kubectl get rs -l app=$DEPLOYMENT -n $NAMESPACE
    
    echo -e "\n=== Pod Status ==="
    kubectl get pods -l app=$DEPLOYMENT -n $NAMESPACE
    
    echo -e "\n=== Recent Events ==="
    kubectl get events -n $NAMESPACE --field-selector involvedObject.name=$DEPLOYMENT --sort-by='.lastTimestamp'
}

# 扩容 Deployment
scale_deployment() {
    REPLICAS=$3
    echo "Scaling $DEPLOYMENT to $REPLICAS replicas..."
    kubectl scale deployment $DEPLOYMENT --replicas=$REPLICAS -n $NAMESPACE
}

# 强制重启
restart_deployment() {
    echo "Force restarting $DEPLOYMENT..."
    kubectl rollout restart deployment/$DEPLOYMENT -n $NAMESPACE
    kubectl rollout status deployment/$DEPLOYMENT -n $NAMESPACE
}

case "$1" in
    status)
        status_deployment
        ;;
    rollback)
        rollback_deployment
        ;;
    scale)
        scale_deployment "$@"
        ;;
    restart)
        restart_deployment
        ;;
    *)
        echo "Usage: $0 {status|rollback|scale|restart} <deployment> [namespace] [replicas]"
        ;;
esac

十、总结

Deployment 是 Kubernetes 中最核心的工作负载资源之一,它通过声明式的配置实现了应用的自动化部署、更新和扩缩容。掌握 Deployment 的原理和最佳实践,对于构建可靠的云原生应用至关重要。

核心要点回顾:

  1. 声明式管理:通过 YAML 声明期望状态,控制器自动调谐
  2. 滚动更新:支持零宕机部署,可配置 maxSurge/maxUnavailable
  3. 版本回滚:自动保存历史版本,支持快速回退
  4. 弹性伸缩:支持手动扩缩容和 HPA/VPA 自动扩缩容
  5. 健康检查:通过 liveness/readiness/startupProbe 保证应用质量
  6. 高级策略:支持金丝雀发布、蓝绿部署等复杂场景

推荐实践:

  • 生产环境使用 replicas ≥ 2 + Pod 反亲和
  • 保守的滚动更新策略:maxSurge=1, maxUnavailable=0
  • 始终配置资源请求和健康检查
  • 保留足够的 revisionHistoryLimit 用于回滚
  • 配合 PDB(PodDisruptionBudget) 保证高可用

更多推荐