Deployment與控制器模型
Deployment可以幫我們做什么
- 定義一組Pod期望數(shù)量,Controller會維持Pod數(shù)量與期望數(shù)量一致
- 配置Pod的發(fā)布方式,controller會按照給定的策略更新Pod,保證更新過程中不可用Pod維持在限定數(shù)量范圍內(nèi)
- 如果發(fā)布有問題支持回滾
實例
apiVersion: v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
控制器模型
在Kubernetes架構(gòu)中,有一個叫做kube-controller-manager的組件。這個組件,是一系列控制器的集合。
其中每一個控制器,都以獨有的方式負責某種編排功能。而Deployment正是這些控制器中的一種。它們都遵循Kubernetes中一個通用的編排模式,即:控制循環(huán)
用一段go語言偽代碼,描述這個控制循環(huán)
for {
實際狀態(tài) := 獲取集群中對象X的實際狀態(tài)
期望狀態(tài) := 獲取集群中對象X的期望狀態(tài)
if 實際狀態(tài) == 期望狀態(tài) {
什么都不做
}else{
執(zhí)行編排動作,將實際狀態(tài)調(diào)整為期望狀態(tài)
}
}
在具體實現(xiàn)中,實際狀態(tài)往往來自于Kubernetes集群本身。比如Kubelet通過心跳匯報的容器狀態(tài)和節(jié)點狀態(tài),或者監(jiān)控系統(tǒng)中保存的應(yīng)用監(jiān)控數(shù)據(jù),或者控制器主動收集的它感興趣的信息,這些都是常見的實際狀態(tài)的來源;期望狀態(tài)一般來自用戶提交的YAML文件,這些信息都保存在Etcd中
對于Deployment,它的控制器簡單實現(xiàn)如下:
- Deployment Controller從Etcd中獲取到所有攜帶 “app:nginx”標簽的Pod,然后統(tǒng)計它們的數(shù)量,這就是實際狀態(tài)
- Deployment對象的replicas的值就是期望狀態(tài)
- Deployment Controller將兩個狀態(tài)做比較,然后根據(jù)比較結(jié)果,確定是創(chuàng)建Pod,還是刪除已有Pod
Deployment的滾動更新
Deployment滾動更新的實現(xiàn),依賴的是Kubernetes中的ReplicaSet
Deployment控制器實際操縱的,就是Replicas對象,而不是Pod對象。對于Deployment、ReplicaSet、Pod它們的關(guān)系如下圖:

ReplicaSet負責通過“控制器模式”,保證系統(tǒng)中Pod的個數(shù)永遠等于指定的個數(shù)。這也正是Deployment只允許容器的restartPolicy=Always的主要原因:只有容器能保證自己始終是running狀態(tài)的前提下,ReplicaSet調(diào)整Pod的個數(shù)才有意義。
Deployment同樣通過控制器模式,操作ReplicaSet的個數(shù)和屬性,進而實現(xiàn)“水平擴展/收縮”和“滾動更新”兩個編排動作
對于“水平擴展/收縮”的實現(xiàn),Deployment Controller只需要修改replicas的值即可。
用戶執(zhí)行這個操作的指令如下:
kubectl scale deployment nginx-deployment --replicas=4
滾動更新的過程
首先,創(chuàng)建上述Pod
[root@host1 deployment]# kubectl create -f nginx-deployment.yaml --record #record參數(shù)可以記錄每次操作所執(zhí)行的命令,方便日后查看
deployment.apps/nginx-deployment created
[root@host1 deployment]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 21s
[root@host1 deployment]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-76bf4969df 3 3 3 62s
[root@host1 deployment]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-76bf4969df-jq4tj 1/1 Running 0 70s
nginx-deployment-76bf4969df-jsln9 1/1 Running 0 70s
nginx-deployment-76bf4969df-nbl8j 1/1 Running 0 70s
test-projected-volume 1/1 Running 0 19h
[root@host1 deployment]# kubectl rollout status deployment/nginx-deployment #通過該指令可以實時查看對象的狀態(tài)變化
deployment "nginx-deployment" successfully rolled out
[root@host1 deployment]# kubectl edit deployment/nginx-deployment #修改etcd中的API對象
deployment.extensions/nginx-deployment edited
[root@host1 deployment]# kubectl rollout status deployment/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
[root@host1 deployment]# kubectl describe deployment/nginx-deployment
....
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 22m deployment-controller Scaled up replica set nginx-deployment-76bf4969df to 3
Normal ScalingReplicaSet 17m deployment-controller Scaled up replica set nginx-deployment-779fcd779f to 1
Normal ScalingReplicaSet 16m deployment-controller Scaled down replica set nginx-deployment-76bf4969df to 2
Normal ScalingReplicaSet 16m deployment-controller Scaled up replica set nginx-deployment-779fcd779f to 2
Normal ScalingReplicaSet 15m deployment-controller Scaled down replica set nginx-deployment-76bf4969df to 1
Normal ScalingReplicaSet 15m deployment-controller Scaled up replica set nginx-deployment-779fcd779f to 3
Normal ScalingReplicaSet 15m deployment-controller Scaled down replica set nginx-deployment-76bf4969df to 0
首先,當你修改了Deployment中的Pod定義之后,Deployment Controller會使用這個修改后的Pod模板,創(chuàng)建一個新的ReplicaSet,這個ReplicaSet的初始Pod副本數(shù)是:0
然后在17m的時候,Deployment Controller開始將這個新的ReplicaSet所控制的Pod副本數(shù)從0變?yōu)?,即水平擴展出與i個副本
接著,在16m的時候,Deployment Controller將舊的ReplicaSet所控制的舊Pod副本數(shù)減少一個
....
如此交替,就彎沉了一組Pod版本更新過程。
[root@host1 deployment]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-76bf4969df 0 0 0 26m
nginx-deployment-779fcd779f 3 3 3 21m
Deployment還會確保,在任何時間窗口內(nèi),只有指定比例的Pod處于離線狀態(tài),同時確保,在任何時間窗口內(nèi),只有指定比例的新Pod被創(chuàng)建出來,這兩個值都可以配置,默認是25%
這個策略,是Deployment對象的一個字段,叫做RollingUpdateStrategy,如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
...
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
maxSurge指定的是除了DESIRED數(shù)量之外,在一次滾動中,Deployment控制器還可以創(chuàng)建多少個新Pod;
maxUnavailable指的是,在一次滾動中,Deployment控制器可以刪除多少個舊Pod
回滾
首先我們使用kubeclt rollout history命令,查看每次Deployment變更對應(yīng)的版本
然后使用kubeclt rollout undo deployment/[deployment-name] --to-revision=[版本號]
參考:阿里云大學云原生技術(shù)公開課 極客時間深入剖析Kubernetes