一、为什么 Deployment 会成为无状态应用默认选择

Deployment 本身并不直接创建 Pod,它通过 ReplicaSet 去维护 Pod 副本。也正因为中间多了这一层,Deployment 才具备了滚动更新、版本保留和回滚能力。

理解 Deployment 时,有两个特别重要的规则:

  • 只有 .spec.template 发生变化,才会触发一次新的 rollout
  • 单纯修改副本数进行扩缩容,不会产生新的发布版本

这两个规则直接决定了你应该怎样理解“更新”和“扩容”。

二、创建一个最小可用的 Deployment

下面这个示例会创建 3 个 nginx 副本:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
        ports:
        - containerPort: 80

创建和查看状态:

kubectl create -f nginx-deploy.yaml
kubectl get deployment
kubectl rollout status deployment/nginx-deployment
kubectl get pods --show-labels

平时读状态时,最常看的字段有:

  • READY:当前就绪副本 / 期望副本
  • UP-TO-DATE:已更新到目标模板的副本数
  • AVAILABLE:对外可用的副本数

三、Deployment 更新时到底发生了什么

最典型的更新,就是更新镜像:

kubectl set image deployment nginx-deployment nginx=nginx:1.16.1
kubectl edit deployment nginx-deployment
kubectl get rs
kubectl describe deployment nginx-deployment

更新触发后,Deployment 会创建新的 ReplicaSet,并逐步把流量和副本从旧 ReplicaSet 迁移到新 ReplicaSet。也正因为旧 ReplicaSet 会被保留,你才能继续回滚。

四、回滚为什么这么好用

Deployment 默认会记录版本历史,因此回滚通常非常直接。

先看历史:

kubectl rollout history deployment nginx-deployment
kubectl rollout history deployment nginx-deployment --revision=5

回滚到上一版:

kubectl rollout undo deployment nginx-deployment

回滚到指定版本:

kubectl rollout undo deployment nginx-deployment --to-revision=5

如果你的上线流程里经常做镜像升级、参数切换和回退验证,那么 rollout historyrollout undo 几乎是必备命令。

五、扩缩容、暂停恢复和版本历史保留

扩容和缩容最直接的方法是:

kubectl scale deployment nginx-deployment --replicas=5
kubectl scale deployment nginx-deployment --replicas=3

如果要先改镜像,再改资源限制,又不想中间每改一次就触发一次 rollout,可以先暂停:

kubectl rollout pause deployment nginx-deployment
kubectl set image deployment nginx-deployment nginx=nginx:1.9.1
kubectl set resources deployment nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
kubectl rollout resume deployment nginx-deployment

另外还有一个非常实用的字段:

spec:
  revisionHistoryLimit: 10

它表示最多保留多少个历史 ReplicaSet。值越大,回滚窗口越充足;值越小,占用的 etcd 元数据越少。若直接设成 0,就意味着你几乎放弃了回滚历史。

对无状态服务来说,Deployment 之所以强大,不在于“能创建 Pod”,而在于它把创建、变更、观察、回退都放到了同一条稳定的工程化路径里。