1. 程式人生 > >3.深入k8s:Deployment控制器

3.深入k8s:Deployment控制器

![01d4985f180a37a8012066214a289c.png@1280w_1l_2o_100sh](https://img.luozhiyun.com/20200726183429.png) Deployment可以做到很便捷的管理Pod,只需要在Deployment中描述一下希望的Pod狀態時什麼,包括定義Pod副本數、滾動升級和回滾應用、擴容和縮容、暫停和繼續Deployment等,然後Deployment Controller就可以幫我們實現我們想要達到的狀態。 我們從一個例子入手: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 ``` 這個例子中: * 我們定義了一個Deployment,名字叫nginx-deployment; * 通過spec.replicas欄位定義了Pod的副本數是2; * 通過spec.selector欄位定義了被打上app: nginx的標籤的Pod才會被管理; * tmplate欄位定義了這個Deployment管理的Pod應該是怎樣的,具有怎樣的屬性; 總的來說一個Deploymet控制器可以由兩部分組成: ![img](https://img.luozhiyun.com/20200726182710.png) ### ReplicaSet ReplicaSet是一個副本控制器,ReplicaSet可以用selector來控制Pod的數量,而Deployments是一個更高層次的概念,它管理ReplicaSets,並提供對pod的宣告性更新以及許多其他的功能。 Deployment通過控制ReplicaSet的個數來和屬性,進而實現“水平擴充套件 / 收縮”和“滾動更新”這兩個編排動作。 ### 水平擴充套件與滾動更新 我們可以通過下面這個命令來建立Deployment: ``` kubectl create -f nginx-deployment.yaml --record ``` 這裡–record 引數作用是記錄下你每次操作所執行的命令,以方便後面檢視。 檢查一下Deployment狀態: ``` kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 2/2 2 2 33m ``` * NAME:列舉出Deployments 的名字; * READY:顯示了多少個應用的副本是可用的,目前副本數/期望副本數; * UP-TO-DATE:顯示了副本更新的次數,這裡顯示為2,說明已經做過2此更新; * AVAILABLE:顯示了多少個應用的副本是可用的; * AGE:顯示了應用執行的時間。 現在我們使用kubectl scale來做一個水平擴充套件: ``` kubectl scale deployment nginx-deployment --replicas=4 deployment.apps/nginx-deployment scaled ``` 然後我們可以使用rollout status來檢視滾動更新的狀態: ``` kubectl rollout status deployment/nginx-deployment Waiting for deployment "nginx-deployment" rollout to finish: 2 of 4 updated replicas are available... Waiting for deployment "nginx-deployment" rollout to finish: 3 of 4 updated replicas are available... deployment "nginx-deployment" successfully rolled out ``` 上面的3 of 4 updated replicas are available表示已經有3個Pod進入了UP-TO-DATE 狀態。 然後我們還可以檢視一下ReplicaSet狀態: ``` kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-9754ccbdf 4 4 4 44m ``` 在運行了一個Deployment修改後,Deployment Controller會建立一個副本為ReplicaSet,並會生成一串隨機字元,ReplicaSet 會把這個隨機字串加在它所控制的所有 Pod 的標籤裡,從而保證這些 Pod 不會與叢集裡的其他 Pod 混淆。 我們可以通過 kubectl get pods --show-labels來檢視: ``` NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-9754ccbdf-5pl2j 1/1 Running 0 5m4s app=nginx,pod-template-hash=9754ccbdf nginx-deployment-9754ccbdf-67d4g 1/1 Running 0 48m app=nginx,pod-template-hash=9754ccbdf nginx-deployment-9754ccbdf-9drgb 1/1 Running 0 48m app=nginx,pod-template-hash=9754ccbdf nginx-deployment-9754ccbdf-fdmrx 1/1 Running 0 5m4s app=nginx,pod-template-hash=9754ccbdf ``` 下面我們看看Deployment的滾動更新是如何做的: 我們使用set image 來修改deployment中的映象 ``` kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record deployment.apps/nginx-deployment image updated ``` 然後我們可以通過kubectl describe檢視滾動更新的過程: ``` $ kubectl describe deployment nginx-deployment ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- ... Normal ScalingReplicaSet 29s deployment-controller Scaled down replica set nginx-deployment-9754ccbdf to 3 Normal ScalingReplicaSet 29s deployment-controller Scaled up replica set nginx-deployment-dc46b5ffc to 2 Normal ScalingReplicaSet 12s (x2 over 11m) deployment-controller Scaled down replica set nginx-deployment-9754ccbdf to 2 Normal ScalingReplicaSet 12s deployment-controller Scaled up replica set nginx-deployment-dc46b5ffc to 3 Normal ScalingReplicaSet 11s deployment-controller Scaled down replica set nginx-deployment-9754ccbdf to 1 Normal ScalingReplicaSet 11s deployment-controller Scaled up replica set nginx-deployment-dc46b5ffc to 4 Normal ScalingReplicaSet 11s deployment-controller Scaled down replica set nginx-deployment-9754ccbdf to 0 ``` 可以看到Deployment Controller控制ReplicaSet將舊的Pod 副本數一個個減少,並建立一個新的ReplicaSet:nginx-deployment-dc46b5ffc,並將其控制的Pod副本數一個個增加。 在這個“滾動更新”過程完成之後,你可以檢視一下新、舊兩個 ReplicaSet 的最終狀態: ``` kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-9754ccbdf 0 0 0 57m nginx-deployment-dc46b5ffc 4 4 4 5m9s ``` 預設的情況下,Deployment 會保至少有75%的Pod還是可用的,所以我們的例子中,會保證至少有3個Pod是出於可用的狀態。 這個策略,是 Deployment 物件的一個欄位,名叫 RollingUpdateStrategy,如下所示: ``` kubectl describe deployment Name: nginx-deployment ... Selector: app=nginx Replicas: 4 desired | 4 updated | 4 total | 4 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge ... ``` 25% max unavailable表示最大25%不可用;25% max surge表示最多可以建立多少個新的Pod。 ### 版本控制與回滾 在上面的操作中,我們將nginx的版本設定成了1.16.1,現在我們可以通過rollout undo來進行版本的回滾: ``` kubectl rollout undo deployment/nginx-deployment deployment.apps/nginx-deployment rolled back ``` 當然除了這個命令以外由於我們使用了--record,所以我們可以通過kubectl rollout history 來檢視版本資訊: ``` kubectl rollout history deployment/nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true 3 kubectl apply --filename=nginx-deployment.yaml --record=true ``` 我們可以通過kubectl rollout history來看到相應版本的具體資訊: ``` kubectl rollout history deployment/nginx-deployment --revision=2 ``` 通過kubectl rollout undo命令來回滾到相應的版本: ``` kubectl rollout undo deployment/nginx-deployment --to-revision=2 ``` ### Pausing 和Resuming 一個Deployment 我們在上面的操作中,每進行一步操作都會進行一次滾動更新,如果我們想一次性執行多條命令然後再一次性滾動更新,那麼可以先pause Deployment然後操作完之後再resume 它。 如下: ``` kubectl rollout pause deployment/nginx-deployment deployment.apps/nginx-deployment paused ``` 然後就可以隨意的修改這個 Deployment 的內容了。由於此時 Deployment 正處於“暫停”狀態,所以我們對 Deployment 的所有修改,都不會觸發新的“滾動更新”,也不會建立新的 ReplicaSet。 操作完之後再執行: ``` kubectl rollout resume deployment/nginx-deployment deployment.apps/nginx-deployment resumed ``` 在 kubectl rollout pause 指令之後的這段時間裡,我們對 Deployment 進行的所有修改,最後只會觸發一次“滾動更