Deployment 是 Kubernetes 控制器的一種高階別實現,它構建於 ReplicaSet 控制器之上,它可用於為 Pod 和 ReplicaSet 資源提供宣告式更新,並能夠以自動方式實現跨多個 ReplicaSet 物件的捲動更新功能。相比較來說,Pod 和 ReplicaSet 是較低階別的資源,以至於很少被直接使用。
Deployment 控制器資源的主要職責同樣是為了保證 Pod 資源健康執行,其大部分功能通過呼叫 ReplicaSet 控制器實現,並增添了部分特性。
通過以上內容可以知道Deployment提供了很多核心功能,在本文主要關注Deployment多種升級策略功能。通過深入研究Deployment升級策略,我們將獲得更好的理解和掌握如何在Kubernetes環境中進行應用程式的升級。我們將學習如何選擇合適的升級策略,並瞭解如何正確設定和管理升級過程中的各種引數。最終,我們將能夠實現無縫、可控的應用程式升級,提高應用的穩定性和可用性。
在接下來的篇章中,讓我們一起深入探索Deployment升級策略的精髓,並學習如何在實際應用中應用這些策略,為應用程式的持續演進提供支援。
注意 1:Deployment只負責管理不同版本的ReplicaSet, 由ReplicaSet管理Pod副本數。每個ReplicaSet對應了Deployment template的一個版本,一個ReplicaSet下的Pod都是相同的版本。
Deployment控制器支援兩種更新策略: 捲動更新(RollingUpdate)和刪除式更新(Recreate)也稱為單批次更新,預設使用捲動更新策略。
Deployment 控制器的捲動更新操作並非在同一個 ReplicaSet 控制器物件下刪除並建立 Pod 資源,而是將它們分置於兩個不同的控制器之下,當前 ReplicaSet 物件的 Pod 副本數量不斷減少的同時,新 ReplicaSet 物件的 Pod 物件數量不斷增加,直到現有 ReplicaSet 物件的 Pod 副本數為 0,而新控制器的副本數量變得完全符合期望值,新舊版本之間區別彼此 Pod 物件的關鍵標籤為 pod-template-hash。
捲動更新(RollingUpdate)一次僅更新一批Pod,當更新的Pod就緒(可用)後,再更新另一批,直到全部更新完成為止,該策略實現了不間斷服務的目標,在更新過程中可能會出現不同的應用版本且並存,同時提供服務的情況,Rolling Update升級策略分為三個步驟:
注意 1:注意捲動升級步驟第2步,存在先增新後減舊、先減舊後增新、同時增減(少減多增)多種情況,具體與捲動升級策略屬性spec.strategy.rollingUpdate.maxSurge和spec.strategy.rollingUpdate.maxUnavailable設定相關,此部分會在下文進行詳細解釋。
注意 2:在Deployment的捲動升級期間,可以通過以下方式判斷Pod是否處於可用狀態:Pod設定就緒探針(Readiness Probe)的情況下:如果就緒探針的探測結果為成功,則表示容器已經準備好接收流量,該Pod被認為是就緒狀態。Pod沒有就緒探針的情況下:判斷Pod是否就緒的依據主要是基於Pod的執行狀態,一般Pod的狀態為Running則認為Pod是就緒狀態。
注意 3:修改 Deployment 控制器的 minReadySeconds、replicas 和 strategy 等欄位的值並不會觸發 Pod 資源的更新操作,因為它們不屬於 template 的內嵌欄位,對現存的 Pod 物件不產生任何影響。
(1)應用設定範例
# type欄位須設定為RollingUpdate # spec: # strategy: # type: RollingUpdate # 應用組態檔,現版本Nginx是1.16版本,要捲動到1.21.5; root@kubernetes-master01:~# cat nginx-deployment-test.yaml apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx-test namespace: deployment-test spec: strategy: type: RollingUpdate replicas: 2 selector: matchLabels: app: nginx-deployment template: metadata: labels: app: nginx-deployment spec: containers: - name: nginx image: nginx:1.16 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80
在叢集建立Deployment工作負載物件deployment-nginx-test。
[root@node1 deploy]# kubectl create ns deployment-test namespace/deployment-test created [root@node1 deploy]# kubectl apply -f nginx-deployment-test.yaml deployment.apps/deployment-nginx-test created
檢視Deployment工作負載物件deployment-nginx-test狀態,可以看到其捲動升級策略型別為RollingUpdate,這裡提前注意下捲動升級策略預設屬性值25% max unavailable, 25% max surge,此部分會在下文進行詳細解釋。
[root@node1 deploy]# kubectl describe deployments.apps -n=deployment-test deployment-nginx-test Name: deployment-nginx-test Namespace: deployment-test CreationTimestamp: Tue, 27 Jun 2023 09:29:42 +0800 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=nginx-deployment Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx-deployment Containers: nginx: Image: nginx:1.16 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: deployment-nginx-test-65b5c9746c (2/2 replicas created) Events: <none>
檢視Deployment工作負載物件deployment-nginx-test關聯Pod狀態。
[root@node1 deploy]# kubectl get pods -n=deployment-test NAME READY STATUS RESTARTS AGE deployment-nginx-test-65b5c9746c-nc875 1/1 Running 0 6m43s deployment-nginx-test-65b5c9746c-rbzsx 1/1 Running 0 6m43s
(2)測試卷動更新升級策略
修改Deployment工作負載物件deployment-nginx-test映象版本,測試卷動更新升級策略。
[root@node1 deploy]# kubectl set image -n=deployment-test deployment/deployment-nginx-test nginx=nginx:latest deployment.apps/deployment-nginx-test image updated
在測試卷動更新升級策略的同時,開一個新的shell視窗,監視Deployment工作負載物件deployment-nginx-test關聯Pod的實時狀態變化。
[root@node1 ~]# kubectl get pods -n=deployment-test --watch NAME READY STATUS RESTARTS AGE deployment-nginx-test-65b5c9746c-2f599 1/1 Running 0 23s deployment-nginx-test-65b5c9746c-m9lrs 1/1 Running 0 23s deployment-nginx-test-74859ff6d8-lhphh 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-lhphh 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-lhphh 0/1 ContainerCreating 0 0s deployment-nginx-test-74859ff6d8-lhphh 1/1 Running 0 2s deployment-nginx-test-65b5c9746c-2f599 1/1 Terminating 0 78s deployment-nginx-test-74859ff6d8-kjcgf 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-kjcgf 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-kjcgf 0/1 ContainerCreating 0 0s deployment-nginx-test-65b5c9746c-2f599 0/1 Terminating 0 79s deployment-nginx-test-74859ff6d8-kjcgf 1/1 Running 0 2s deployment-nginx-test-65b5c9746c-m9lrs 1/1 Terminating 0 80s deployment-nginx-test-65b5c9746c-m9lrs 0/1 Terminating 0 81s deployment-nginx-test-65b5c9746c-m9lrs 0/1 Terminating 0 88s deployment-nginx-test-65b5c9746c-m9lrs 0/1 Terminating 0 88s deployment-nginx-test-65b5c9746c-2f599 0/1 Terminating 0 88s deployment-nginx-test-65b5c9746c-2f599 0/1 Terminating 0 88s
通過監視Deployment工作負載物件deployment-nginx-test關聯Pod的實時狀態變化可知,當工作負載更新策略設定為Rolling Update,在更新映象時,它會啟動新的Pod,刪除舊的Pod,當新的Pod就緒後,繼續啟動新的Pod,刪除舊的Pod,周而復始,直到所有Pod都被更新成功。
注意 1:注意捲動升級步驟第2步,存在先增新後減舊、先減舊後增新、同時增減(少減多增)多種情況,具體與捲動升級策略屬性spec.strategy.rollingUpdate.maxSurge和spec.strategy.rollingUpdate.maxUnavailable設定相關,此部分會在下文進行詳細解釋。
捲動升級策略屬性:
可組合定義出 3 種不同的策略完成多批次的應用更新:
注意 1:maxSurge 和 maxUnavailable 屬性的值不可同時為 0,否則 Pod 物件的副本數量在符合使用者期望的數量後無法做出合理變動以進行卷動更新操作。
注意 2:有個特例,如果期望副本數被設定為 1,使用 Deployment 預設捲動升級策略,捲動升級策略屬性值也都是預設值(maxSurge: 25%、maxUnavailable: 25%),由於期望範例數 1*maxSurge 四捨五入=0,期望範例數 1*maxUnavailable 四捨五入=0,那麼在捲動升級期間,Pod 物件總數至多為1,至少有1個 Pod 處於正常提供服務的狀態,按照公式計算,則此工作負載無法做出合理變動以進行卷動更新操作。實際情況是先增新,後減舊。
範例,建立Deploymnet工作負載物件,其範例數為1,使用預設捲動升級策略,捲動升級策略屬性值也都是預設值(maxSurge: 25%、maxUnavailable: 25%),組態檔和2.1.2除了工作負載範例數外一致。
[root@node1 deploy]# kubectl apply -f nginx-deployment-test.yaml deployment.apps/deployment-nginx-test created [root@node1 deploy]# kubectl get pods -n=deployment-test NAME READY STATUS RESTARTS AGE deployment-nginx-test-65b5c9746c-cwbhr 0/1 ContainerCreating 0 5s [root@node1 deploy]# kubectl get pods -n=deployment-test NAME READY STATUS RESTARTS AGE deployment-nginx-test-65b5c9746c-cwbhr 1/1 Running 0 8s修改Deployment工作負載物件deployment-nginx-test映象版本,測試卷動更新升級策略。
[root@node1 deploy]# kubectl set image -n=deployment-test deployment/deployment-nginx-test nginx=nginx:latest deployment.apps/deployment-nginx-test image updated在測試卷動更新升級策略的同時,開一個新的shell視窗,監視Deployment工作負載物件deployment-nginx-test關聯Pod的實時狀態變化。
[root@node1 ~]# kubectl get pods -n=deployment-test --watch NAME READY STATUS RESTARTS AGE deployment-nginx-test-65b5c9746c-cwbhr 1/1 Running 0 4m12s deployment-nginx-test-74859ff6d8-kj2dw 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-kj2dw 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-kj2dw 0/1 ContainerCreating 0 0s deployment-nginx-test-74859ff6d8-kj2dw 1/1 Running 0 2s deployment-nginx-test-65b5c9746c-cwbhr 1/1 Terminating 0 4m26s deployment-nginx-test-65b5c9746c-cwbhr 0/1 Terminating 0 4m27s通過監視Deployment工作負載物件deployment-nginx-test關聯Pod的實時狀態變化可知,如果期望副本數被設定為 1,使用 Deployment 預設捲動升級策略,捲動升級策略屬性值也都是預設值(maxSurge: 25%、maxUnavailable: 25%),在更新映象時,它會啟動新的Pod,然後再刪除舊的Pod。
Deployment 還支援使用 spec.minReadySeconds 欄位來減慢捲動更新的速度,其預設值為 0,表示新建的 Pod 物件一旦「就緒」將立即被視作可用,隨後即可開始下一輪更新過程。而為該欄位指定一個正整數值能夠定義新建的 Pod 物件至少要成功執行多久才會被視作可用,即就緒之後還要等待 minReadySeconds 指定的時長才能開始下一批次的更新。在此期間,更新操作會被阻塞,因此,它可用用來讓kubernetes在每次建立出 Pod 資源後都要等上一部分時間再開始下一輪的替換;因此為minReadySeconds設定一個合理的值,不僅僅能夠減慢更新速度,還能夠讓Deployment發現一部分程式因為BUG而導致的升級故障。
minReadySeconds屬性配合就緒探針的設定,可以確保容器真正就緒後才會接收流量,避免將流量傳送到尚未完全啟動或初始化的容器上。這樣可以提高應用程式的可用性和穩定性。
Deployment控制器保留了一部分更新歷史中舊版本的ReplicaSet物件,當我們執行回滾操作時,就直接使用舊版本的ReplicaSet,在Deployment資源儲存歷史版本數量有spec.revisionHistoryLimit屬性進行定義,預設值為10。
捲動更新故障超時時長,預設為600秒,k8s在升級過程中有可能由於各種原因升級卡住(這個時候還沒有明確的升級失敗)比如在拉取被牆的映象,許可權不夠等錯誤,如果設定progressDeadlineSeconds當達到了時間如果還卡著,則會上報這個異常情況,這個時候Deployment的狀態就會被標記為false,並且註明原因,但是它不會阻止Deployment繼續進行卡住後面的升級操作。
Deployment的Rolling Update升級策略適用於以下場景:
捲動更新策略在實現應用的平滑升級、故障恢復、資源過渡和流量控制方面具有優勢,適用於大多數應用部署場景。它能夠減少對使用者的影響,提供可靠的應用更新和管理機制。
Recreate策略在更新映象時,它會先刪除現在正在執行的Pod,等徹底殺死後,重新建立新的RS(ReplicaSet),然後啟動對應的Pod,在整個更新過程中,會造成服務一段時間無法提供服務。也稱之為單批次更新。Recreate升級策略分為三個步驟:
(1)應用設定範例
# 必須在Spec欄位中明確定義strategy捲動更新策略和type型別 [root@node1 deploy]# cat nginx-deployment-test.yaml apiVersion: apps/v1 kind: Deployment metadata: name: deployment-nginx-test namespace: deployment-test spec: strategy: # 捲動更新策略 type: Recreate # Recreate表示的是刪除式更新,也稱為單批次更新; replicas: 2 selector: matchLabels: app: nginx-deployment template: metadata: labels: app: nginx-deployment spec: containers: - name: nginx image: nginx:1.16 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80
在叢集建立Deployment工作負載物件deployment-nginx-test。
[root@node1 deploy]# kubectl create ns deployment-test namespace/deployment-test created [root@node1 deploy]# kubectl apply -f nginx-deployment-test.yaml deployment.apps/deployment-nginx-test created
檢視Deployment工作負載物件deployment-nginx-test狀態,可以看到其捲動升級策略型別為Recreate。
[root@node1 deploy]# kubectl describe deployments.apps -n=deployment-test deployment-nginx-test Name: deployment-nginx-test Namespace: deployment-test CreationTimestamp: Tue, 27 Jun 2023 07:53:37 +0800 Labels: <none> Annotations: deployment.kubernetes.io/revision: 1 Selector: app=nginx-deployment Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable StrategyType: Recreate MinReadySeconds: 0 Pod Template: Labels: app=nginx-deployment Containers: nginx: Image: nginx:1.16 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: deployment-nginx-test-65b5c9746c (2/2 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 2m21s deployment-controller Scaled up replica set deployment-nginx-test-65b5c9746c to 2
檢視Deployment工作負載物件deployment-nginx-test關聯Pod狀態。
[root@node1 deploy]# kubectl get pods -n=deployment-test NAME READY STATUS RESTARTS AGE deployment-nginx-test-65b5c9746c-nc875 1/1 Running 0 6m43s deployment-nginx-test-65b5c9746c-rbzsx 1/1 Running 0 6m43s
(2)測試刪除式更新升級策略
修改Deployment工作負載物件deployment-nginx-test映象版本,測試刪除式更新升級策略。
[root@node1 deploy]# kubectl set image -n=deployment-test deployment/deployment-nginx-test nginx=nginx:latest deployment.apps/deployment-nginx-test image updated
在測試刪除式更新升級策略的同時,開一個新的shell視窗,監視Deployment工作負載物件deployment-nginx-test關聯Pod的實時狀態變化。
[root@node1 ~]# kubectl get pods -n=deployment-test --watch NAME READY STATUS RESTARTS AGE deployment-nginx-test-65b5c9746c-927r9 1/1 Running 0 73s deployment-nginx-test-65b5c9746c-vxztk 1/1 Running 0 73s deployment-nginx-test-65b5c9746c-vxztk 1/1 Terminating 0 80s deployment-nginx-test-65b5c9746c-927r9 1/1 Terminating 0 80s deployment-nginx-test-65b5c9746c-927r9 0/1 Terminating 0 83s deployment-nginx-test-65b5c9746c-vxztk 0/1 Terminating 0 84s deployment-nginx-test-65b5c9746c-vxztk 0/1 Terminating 0 92s deployment-nginx-test-65b5c9746c-vxztk 0/1 Terminating 0 92s deployment-nginx-test-65b5c9746c-927r9 0/1 Terminating 0 92s deployment-nginx-test-65b5c9746c-927r9 0/1 Terminating 0 92s deployment-nginx-test-74859ff6d8-zcmz4 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-zcmz4 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-h4889 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-h4889 0/1 Pending 0 0s deployment-nginx-test-74859ff6d8-h4889 0/1 ContainerCreating 0 0s deployment-nginx-test-74859ff6d8-zcmz4 0/1 ContainerCreating 0 0s deployment-nginx-test-74859ff6d8-zcmz4 1/1 Running 0 8s
通過監視Deployment工作負載物件deployment-nginx-test關聯Pod的實時狀態變化可知,當工作負載更新策略設定為Recreate,在更新映象時,它會先刪除現在正在執行的Pod,等徹底殺死後,重新建立新的RS(ReplicaSet),然後啟動對應的Pod,在整個更新過程中,會造成服務一段時間無法提供服務。也稱之為單批次更新。
Deployment的Recreate升級策略適用於以下場景:
快速回滾:當需要迅速回滾到先前的應用版本時,Recreate策略可以很方便地實現。通過將新版本的Pod全部替換為舊版本的Pod,可以快速恢復到先前穩定的應用狀態。
環境重建:當需要重新建立整個應用環境時,Recreate策略是一個合適的選擇。例如,在測試環境或開發環境中,需要定期清理和重新建立應用範例,以確保環境的一致性和穩定性。
應用初始化:在部署新的應用時,Recreate策略可以用來確保所有的Pod都從頭開始初始化。這對於一些需要重置狀態或執行初始設定的應用非常有用。
其他: 對於傳統企業大部分業務系統,升級前通常會發升級公告,一般是週五晚上12點左右進行新版本的升級,這個時候使用Recreate策略可以迅速的升級新版本;另外對於一些測試環境,或者說資源比較缺乏的一些環境,使用Recreate策略升級應用可以臨時節約叢集資源,使用預設Rolling Update升級策略時,如果不對Deployment升級策略做特殊設定,使用其預設捲動升級策略的話,在升級過程中會最多存在「期望範例數+maxSurge」個Pod範例數,尤其對於先增新,後減舊的情況,如果叢集資源很缺乏並且Pod資源需求很大,由於舊Pod還佔用著資源,叢集可能就會沒法排程新Pod,就會導致捲動升級失敗,現象是使用者端存取的還是舊的程式。
注意 1:使用Recreate策略進行卷動升級時,會在更新期間出現應用不可用的瞬間。因為在替換舊版本Pod之前,新版本Pod需要先全部啟動完成。因此,在選擇使用Recreate策略時,需要確保應用對短暫的停機時間或不可用性可以容忍。
Deployment升級策略是在Kubernetes中用於管理應用程式更新的重要機制。它允許在保證服務的可用性的同時,逐步將舊版本的Pod替換為新版本的Pod。Deployment提供了兩種主要的升級策略:Recreate(重建)和RollingUpdate(捲動更新)。
重建(Recreate)策略:
捲動更新(RollingUpdate)策略: