Kubernetes Deployment 控制器

一份内容详实、结构清晰的 Deployment 学习指南。

1.0 Deployment 控制器简介

在 Kubernetes 生态系统中,Deployment 是一种比 ReplicaSet (RS) 更高阶的控制器。虽然 ReplicaSet 能够确保指定数量的 Pod 副本持续运行,但在实际生产环境中,我们通常不直接操作它。我们更倾向于使用 Deployment,因为它提供了一个至关重要的功能:应用的滚动更新(Rolling Update)

1.1 核心定位

Deployment 的核心价值在于实现了 Pod 的无中断服务更新。当我们发布新版本的应用时,只需更新 Deployment 中 Pod 模板的容器镜像。Deployment 就会自动以滚动更新的方式,平滑地将线上服务从旧版本升级到新版本,确保业务的连续性。

1.2 与 ReplicaSet 的关系

Deployment 的强大功能是建立在 ReplicaSet 之上的。它们之间存在一个清晰的管理层级关系:

  • Deployment 管理 ReplicaSet 的版本。
  • ReplicaSet 管理 Pod 的副本数量。

简单来说,Deployment 通过创建和管理不同版本的 ReplicaSet 来实现应用的更新和回滚。每一个 Deployment 对象,都可以通俗地理解为集群中的一次“部署”活动。

关系图示:

Deployment → ReplicaSet → Pod

2.0 快速入门

2.1 基本 YAML 结构

Deployment 的资源对象格式与 ReplicaSet 非常相似。以下是一个标准的 `nginx-deploy.yaml` 示例:

# nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  namespace: default
spec:
  replicas: 3 # 期望的 Pod 副本数量,默认值为 1
  selector: # Label Selector,必须匹配 Pod 模板中的标签
    matchLabels:
      app: nginx
  template: # Pod 模板
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80

关键字段解析:

  • apiVersion: apps/v1: Deployment 对象的 API 版本。
  • kind: Deployment: 资源类型。
  • spec.replicas: 期望运行的 Pod 副本数量。
  • spec.selector: 标签选择器,用于识别此 Deployment 管理的 Pod。其 `matchLabels` 必须与 Pod 模板中的标签一致。
  • spec.template: Pod 模板,定义了要创建的 Pod 的具体规格,包括元数据、容器、镜像、端口等。

2.2 基本操作

创建 Deployment:

$ kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx-deploy created

查看 Deployment 状态:

$ kubectl get deployment
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   3/3     3            3           58s

查看由 Deployment 创建的 Pod:

$ kubectl get pods -l app=nginx
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-85ff79dd56-7r76h   1/1     Running   0          41s
nginx-deploy-85ff79dd56-d5gjs   1/1     Running   0          41s
nginx-deploy-85ff79dd56-txc4h   1/1     Running   0          41s

2.3 验证控制器层级

我们可以通过 `describe` 命令来验证控制器之间的层级关系。

第一层:Pod 受 ReplicaSet 控制

$ kubectl describe pod nginx-deploy-85ff79dd56-txc4h
...
Controlled By:  ReplicaSet/nginx-deploy-85ff79dd56
...

第二层:ReplicaSet 受 Deployment 控制

$ kubectl describe rs nginx-deploy-85ff79dd56
...
Controlled By:  Deployment/nginx-deploy
...

这清晰地展示了 `Deployment -> ReplicaSet -> Pod` 的控制链条。

3.0 水平伸缩 (Horizontal Scaling)

3.1 伸缩原理

水平伸缩是指动态地增加或减少 Pod 的副本数量。Deployment 通过修改其管理的 ReplicaSet 的 `spec.replicas` 字段来实现这一目标。当 Deployment 的 `replicas` 值改变时,该变更会传递给底层的 ReplicaSet,由 ReplicaSet 控制器负责创建或删除 Pod,以达到新的期望状态。

3.2 操作命令

使用 `kubectl scale` 命令可以方便地对 Deployment 进行动态伸缩。

# 将副本数扩展到 4
$ kubectl scale deployment nginx-deploy --replicas=4
deployment.apps/nginx-deploy scaled

3.3 事件观察

执行扩容后,可以通过查看 Deployment 的事件来观察伸缩过程。你会看到一个 `ScalingReplicaSet` 事件,表明 Deployment 控制器已成功将底层 ReplicaSet 的副本数调整到了新的期望值。

$ kubectl describe deployment nginx-deploy
...
Events:
  Type    Reason              Age    From                   Message
  ----    ------              ----   ----                   -------
  Normal  ScalingReplicaSet   2m20s  deployment-controller  Scaled up replica set nginx-deploy-85ff79dd56 to 3
  Normal  ScalingReplicaSet   30s    deployment-controller  Scaled up replica set nginx-deploy-85ff79dd56 to 4

4.0 滚动更新 (Rolling Update)

滚动更新是 Deployment 最核心的功能之一,它允许你在不中断服务的前提下升级应用。

4.1 更新策略配置

更新行为在 `spec.strategy` 字段中定义。以下是一个包含滚动更新策略的配置示例:

spec:
  replicas: 3
  minReadySeconds: 5 # Pod 就绪后等待 5 秒才视为可用,防止过快更新
  strategy:
    type: RollingUpdate # 策略类型,默认为 RollingUpdate
    rollingUpdate:
      maxSurge: 1       # 更新期间最多可以额外创建的 Pod 数量 (可以是绝对值或百分比)
      maxUnavailable: 1 # 更新期间最多允许不可用的 Pod 数量 (可以是绝对值或百分比)
  template:
    ...
    spec:
      containers:
      - name: nginx
        image: nginx:1.17.9 # 将镜像更新到新版本
        ...

策略类型 (`spec.strategy.type`):

  • RollingUpdate (默认): 逐步用新版本的 Pod 替换旧版本的 Pod,保证服务在更新期间始终可用。
  • Recreate: 先删除所有旧版本的 Pod,然后再创建所有新版本的 Pod。这种方式会导致服务短暂中断。

滚动更新参数:

  • maxSurge: 定义了更新过程中可以超过 `replicas` 数量的最大 Pod 数。例如,`replicas` 为 3,`maxSurge` 为 1,则更新时 Pod 总数最多为 4。
  • maxUnavailable: 定义了更新过程中允许处于不可用状态的最大 Pod 数。例如,`replicas` 为 3,`maxUnavailable` 为 1,则更新时必须至少有 2 个 Pod 处于可用状态。

4.2 滚动更新管理

当你修改了 Deployment 的 Pod 模板(例如更新了容器镜像)并执行 `kubectl apply` 后,滚动更新就会被触发。`kubectl rollout` 系列命令是管理和观察更新过程的利器。

命令 功能描述
kubectl rollout status deployment/<name> 实时监控滚动更新的状态,直到完成或失败。
kubectl rollout history deployment/<name> 查看部署历史记录,每一次更新都会生成一个新的版本 (revision)。
kubectl rollout pause deployment/<name> 暂停当前的滚动更新过程,常用于分步发布或问题排查。
kubectl rollout resume deployment/<name> 恢复已暂停的滚动更新。

5.0 版本回滚 (Rollback)

5.1 回滚原理

Deployment 的回滚能力得益于它保留了旧版本的 ReplicaSet。当你触发一次更新时,Deployment 会创建一个新的 ReplicaSet,并逐渐缩容旧的 ReplicaSet。如果新版本出现问题,你可以通过“回滚”操作,让 Deployment 重新扩容旧的 ReplicaSet,并缩容新的 ReplicaSet,从而恢复到上一个稳定版本。

5.2 回滚操作

回滚到上一个版本:

# 这条命令会将 Deployment 恢复到之前的版本
$ kubectl rollout undo deployment/nginx-deploy
deployment.apps/nginx-deploy rolled back

回滚到指定版本:

首先,查看历史版本号:

$ kubectl rollout history deployment/nginx-deploy
deployment.apps/nginx-deploy
REVISION  CHANGE-CAUSE
1         <none>
2         kubectl apply --filename=nginx-deploy.yaml --record=true

然后,执行回滚到指定版本(例如 revision 1):

$ kubectl rollout undo deployment/nginx-deploy --to-revision=1
deployment.apps/nginx-deploy rolled back

注:`CHANGE-CAUSE` 列的内容来自于执行 `kubectl` 命令时添加的 `--record` 标志,有助于追踪每次变更的原因。

6.0 历史版本管理

为了支持版本回滚,Deployment 会保留一定数量的旧 ReplicaSet 作为历史记录。

你可以通过 `spec.revisionHistoryLimit` 字段来设置保留的历史版本数量。默认值为 `10`。

spec:
  revisionHistoryLimit: 5 # 设置保留最近 5 个历史版本
  ...

将此值设置为一个合理的数字可以在需要回滚时提供足够的历史版本,同时避免过多的旧 ReplicaSet 对象占用系统资源。如果将其设置为 `0`,所有旧的 ReplicaSet 将被清理,你将无法执行回滚操作。