一、为什么 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 history 和 rollout 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”,而在于它把创建、变更、观察、回退都放到了同一条稳定的工程化路径里。