部署
Deployment 為 Pod 和 ReplicaSet 提供宣告式更新。
您在部署 (Deployment) 中描述期望狀態,而部署控制器會以受控速率將實際狀態變更為期望狀態。您可以定義部署以建立新的副本集 (ReplicaSet),或移除現有的部署並採用其所有資源到新的部署。
注意
請勿管理由部署擁有的副本集。如果您的使用案例未涵蓋在以下內容中,請考慮在主要的 Kubernetes 儲存庫中開啟 issue。使用案例
以下是部署的典型使用案例
- 建立部署以推出副本集。副本集會在背景中建立 Pod。檢查部署推出的狀態,以查看是否成功。
- 透過更新部署的 PodTemplateSpec 來宣告 Pod 的新狀態。系統會建立新的副本集,而部署會管理以受控速率將 Pod 從舊的副本集移至新的副本集。每個新的副本集都會更新部署的修訂版本。
- 如果部署的目前狀態不穩定,則回滾到較早的部署修訂版本。每次回滾都會更新部署的修訂版本。
- 擴展部署以容納更多負載.
- 暫停部署的推出,以將多個修正程式套用至其 PodTemplateSpec,然後恢復部署以開始新的推出。
- 使用部署的狀態作為部署推出停滯的指標。
- 清除您不再需要的舊副本集。
建立部署
以下是部署的範例。它建立一個副本集以啟動三個 nginx
Pod
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: nginx:1.14.2
ports:
- containerPort: 80
在此範例中
建立名為
nginx-deployment
的部署,由.metadata.name
欄位指示。此名稱將成為稍後建立的副本集和 Pod 的基礎。請參閱撰寫部署規格以取得更多詳細資訊。部署建立一個副本集,該副本集建立三個複寫的 Pod,由
.spec.replicas
欄位指示。.spec.selector
欄位定義建立的副本集如何找到要管理的 Pod。在此案例中,您選取在 Pod 範本中定義的標籤 (app: nginx
)。但是,更複雜的選取規則也是可能的,只要 Pod 範本本身符合規則即可。注意
.spec.selector.matchLabels
欄位是 {key,value} 配對的映射。matchLabels
映射中的單個 {key,value} 等效於matchExpressions
的一個元素,其key
欄位為 "key",operator
為 "In",而values
陣列僅包含 "value"。來自matchLabels
和matchExpressions
的所有需求都必須滿足才能比對。template
欄位包含以下子欄位- Pod 使用
.metadata.labels
欄位標記為app: nginx
。 - Pod 範本的規格,或
.template.spec
欄位,指示 Pod 執行一個容器,nginx
,它執行版本為 1.14.2 的nginx
Docker Hub 映像檔。 - 建立一個容器並使用
.spec.template.spec.containers[0].name
欄位將其命名為nginx
。
- Pod 使用
在開始之前,請確保您的 Kubernetes 叢集已啟動並執行。依照以下步驟建立上述部署
執行以下指令來建立部署
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
執行
kubectl get deployments
以檢查部署是否已建立。如果部署仍在建立中,則輸出類似於以下內容
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 0/3 0 0 1s
當您檢查叢集中的部署時,會顯示以下欄位
NAME
列出命名空間中部署的名稱。READY
顯示可供使用者使用的應用程式副本數。它遵循就緒/期望模式。UP-TO-DATE
顯示已更新以達到期望狀態的副本數。AVAILABLE
顯示可供使用者使用的應用程式副本數。AGE
顯示應用程式已執行的時間。
請注意,期望的副本數為 3,根據
.spec.replicas
欄位。若要查看部署的推出狀態,請執行
kubectl rollout status deployment/nginx-deployment
。輸出類似於
Waiting for rollout to finish: 2 out of 3 new replicas have been updated... deployment "nginx-deployment" successfully rolled out
幾秒鐘後再次執行
kubectl get deployments
。輸出類似於此NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 18s
請注意,部署已建立所有三個副本,並且所有副本都是最新的 (它們包含最新的 Pod 範本) 且可用。
若要查看部署建立的副本集 (
rs
),請執行kubectl get rs
。輸出類似於此NAME DESIRED CURRENT READY AGE nginx-deployment-75675f5897 3 3 3 18s
副本集輸出顯示以下欄位
NAME
列出命名空間中副本集的名稱。DESIRED
顯示應用程式的副本的期望數量,您在建立部署時定義。這是期望狀態。CURRENT
顯示目前正在執行的副本數。READY
顯示可供使用者使用的應用程式副本數。AGE
顯示應用程式已執行的時間。
請注意,副本集的名稱始終格式化為
[DEPLOYMENT-NAME]-[HASH]
。此名稱將成為建立的 Pod 的基礎。HASH
字串與副本集上的pod-template-hash
標籤相同。若要查看為每個 Pod 自動產生的標籤,請執行
kubectl get pods --show-labels
。輸出類似於NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897 nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897 nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=75675f5897
建立的副本集確保有三個
nginx
Pod。
注意
您必須在部署中指定適當的選取器和 Pod 範本標籤 (在此案例中為 app: nginx
)。
請勿將標籤或選取器與其他控制器 (包括其他部署和 StatefulSet) 重疊。Kubernetes 不會阻止您重疊,如果多個控制器具有重疊的選取器,這些控制器可能會衝突並表現異常。
Pod-template-hash 標籤
注意
請勿變更此標籤。pod-template-hash
標籤由部署控制器新增至部署建立或採用的每個副本集。
此標籤確保部署的子副本集不會重疊。它透過雜湊副本集的 PodTemplate
並使用產生的雜湊作為標籤值來產生,該標籤值會新增至副本集選取器、Pod 範本標籤,以及副本集可能擁有的任何現有 Pod 中。
更新部署
注意
只有在部署的 Pod 範本 (即.spec.template
) 變更時,才會觸發部署的推出,例如,如果範本的標籤或容器映像檔已更新。其他更新,例如擴展部署,不會觸發推出。依照以下步驟更新您的部署
讓我們更新 nginx Pod 以使用
nginx:1.16.1
映像檔,而不是nginx:1.14.2
映像檔。kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
或使用以下指令
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
其中
deployment/nginx-deployment
指示部署,nginx
指示將發生更新的容器,而nginx:1.16.1
指示新的映像檔及其標籤。輸出類似於
deployment.apps/nginx-deployment image updated
或者,您可以
edit
部署並將.spec.template.spec.containers[0].image
從nginx:1.14.2
變更為nginx:1.16.1
kubectl edit deployment/nginx-deployment
輸出類似於
deployment.apps/nginx-deployment edited
若要查看推出狀態,請執行
kubectl rollout status deployment/nginx-deployment
輸出類似於此
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
或
deployment "nginx-deployment" successfully rolled out
取得有關已更新部署的更多詳細資訊
在推出成功後,您可以執行
kubectl get deployments
來檢視部署。輸出類似於此NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 36s
執行
kubectl get rs
以查看部署如何透過建立新的副本集並將其擴展到 3 個副本,以及將舊的副本集縮減到 0 個副本來更新 Pod。kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE nginx-deployment-1564180365 3 3 3 6s nginx-deployment-2035384211 0 0 0 36s
執行
get pods
現在應該只顯示新的 Podkubectl get pods
輸出類似於此
NAME READY STATUS RESTARTS AGE nginx-deployment-1564180365-khku8 1/1 Running 0 14s nginx-deployment-1564180365-nacti 1/1 Running 0 14s nginx-deployment-1564180365-z9gth 1/1 Running 0 14s
下次您想要更新這些 Pod 時,您只需要再次更新部署的 Pod 範本即可。
部署確保在更新 Pod 時,只有一定數量的 Pod 處於關閉狀態。預設情況下,它確保至少 75% 的期望 Pod 數量處於啟動狀態 (最多 25% 不可用)。
部署也確保僅在期望 Pod 數量之上建立一定數量的 Pod。預設情況下,它確保最多 125% 的期望 Pod 數量處於啟動狀態 (最多 25% 突增)。
例如,如果您仔細查看上述部署,您會看到它首先建立一個新的 Pod,然後刪除一個舊的 Pod,然後再建立另一個新的 Pod。在足夠數量的新 Pod 啟動之前,它不會終止舊的 Pod,並且在足夠數量的舊 Pod 已終止之前,它不會建立新的 Pod。它確保至少有 3 個 Pod 可用,並且總共最多有 4 個 Pod 可用。在具有 4 個副本的部署案例中,Pod 數量將介於 3 到 5 之間。
取得部署的詳細資訊
kubectl describe deployments
輸出類似於此
Name: nginx-deployment Namespace: default CreationTimestamp: Thu, 30 Nov 2017 10:56:25 +0000 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=2 Selector: app=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.16.1 Port: 80/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-1564180365 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 2m deployment-controller Scaled up replica set nginx-deployment-2035384211 to 3 Normal ScalingReplicaSet 24s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 1 Normal ScalingReplicaSet 22s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 2 Normal ScalingReplicaSet 22s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 2 Normal ScalingReplicaSet 19s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 1 Normal ScalingReplicaSet 19s deployment-controller Scaled up replica set nginx-deployment-1564180365 to 3 Normal ScalingReplicaSet 14s deployment-controller Scaled down replica set nginx-deployment-2035384211 to 0
在這裡您可以看到,當您第一次建立部署時,它建立了一個副本集 (nginx-deployment-2035384211) 並直接將其擴展到 3 個副本。當您更新部署時,它建立了一個新的副本集 (nginx-deployment-1564180365) 並將其擴展到 1 個,並等待其啟動。然後,它將舊的副本集縮減到 2 個,並將新的副本集擴展到 2 個,以便始終至少有 3 個 Pod 可用,並且最多建立 4 個 Pod。然後,它繼續使用相同的滾動更新策略來擴展和縮減新的和舊的副本集。最後,您將在新的副本集中擁有 3 個可用的副本,而舊的副本集將縮減為 0。
注意
Kubernetes 在計算availableReplicas
的數量時不會計算終止中的 Pod,availableReplicas
的數量必須介於 replicas - maxUnavailable
和 replicas + maxSurge
之間。因此,您可能會注意到在部署推出期間,Pod 的數量超出預期,並且部署消耗的總資源超過 replicas + maxSurge
,直到終止中 Pod 的 terminationGracePeriodSeconds
過期。覆蓋 (又名多個進行中的更新)
每次部署控制器觀察到新的部署時,都會建立一個副本集以啟動期望的 Pod。如果部署已更新,則會縮減控制 Pod 的現有副本集,這些 Pod 的標籤符合 .spec.selector
,但其範本不符合 .spec.template
。最終,新的副本集會擴展到 .spec.replicas
,而所有舊的副本集都會縮減到 0。
如果您在現有部署推出正在進行時更新部署,則部署會根據更新建立新的副本集並開始擴展該副本集,並覆蓋先前正在擴展的副本集 -- 它會將其新增至舊副本集清單並開始縮減它。
例如,假設您建立一個部署以建立 5 個 nginx:1.14.2
的副本,但隨後在僅建立 3 個 nginx:1.14.2
副本時,將部署更新為建立 5 個 nginx:1.16.1
副本。在這種情況下,部署會立即開始終止已建立的 3 個 nginx:1.14.2
Pod,並開始建立 nginx:1.16.1
Pod。它不會等待建立 5 個 nginx:1.14.2
副本後再變更方向。
標籤選取器更新
通常不建議進行標籤選取器更新,建議預先規劃您的選取器。在任何情況下,如果您需要執行標籤選取器更新,請格外小心並確保您已掌握所有含義。
注意
在 API 版本apps/v1
中,部署的標籤選取器在建立後是不可變的。- 新增選取器需要使用新的標籤更新部署規格中的 Pod 範本標籤,否則會傳回驗證錯誤。此變更是非重疊的變更,表示新的選取器不會選取使用舊選取器建立的副本集和 Pod,導致孤立所有舊的副本集並建立新的副本集。
- 選取器更新會變更選取器金鑰中的現有值 -- 導致與新增相同的行為。
- 移除選取器會從部署選取器中移除現有的金鑰 -- 不需要變更 Pod 範本標籤。現有的副本集不會孤立,也不會建立新的副本集,但請注意,移除的標籤仍然存在於任何現有的 Pod 和副本集中。
回滾部署
有時,您可能想要回滾部署;例如,當部署不穩定時,例如崩潰迴圈。預設情況下,部署的所有部署歷史記錄都保留在系統中,以便您可以隨時回滾 (您可以透過修改修訂歷史記錄限制來變更此設定)。
注意
當觸發部署的推出時,會建立部署的修訂版本。這表示只有在部署的 Pod 範本 (.spec.template
) 變更時才會建立新的修訂版本,例如,如果您更新範本的標籤或容器映像檔。其他更新,例如擴展部署,不會建立部署修訂版本,因此您可以促進同時手動或自動擴展。這表示當您回滾到較早的修訂版本時,只會回滾部署的 Pod 範本部分。假設您在更新部署時輸入錯誤,將映像檔名稱輸入為
nginx:1.161
而不是nginx:1.16.1
kubectl set image deployment/nginx-deployment nginx=nginx:1.161
輸出類似於此
deployment.apps/nginx-deployment image updated
部署推出會停滯。您可以透過檢查推出狀態來驗證它
kubectl rollout status deployment/nginx-deployment
輸出類似於此
Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
按下 Ctrl-C 以停止上述推出狀態監看。如需有關停滯部署推出的更多資訊,請在此處閱讀更多內容。
您會看到舊副本的數量 (從
nginx-deployment-1564180365
和nginx-deployment-2035384211
新增副本計數) 為 3,而新副本的數量 (從nginx-deployment-3066724191
) 為 1。kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE nginx-deployment-1564180365 3 3 3 25s nginx-deployment-2035384211 0 0 0 36s nginx-deployment-3066724191 1 1 0 6s
查看建立的 Pod,您會看到由新副本集建立的 1 個 Pod 卡在映像檔提取迴圈中。
kubectl get pods
輸出類似於此
NAME READY STATUS RESTARTS AGE nginx-deployment-1564180365-70iae 1/1 Running 0 25s nginx-deployment-1564180365-jbqqo 1/1 Running 0 25s nginx-deployment-1564180365-hysrc 1/1 Running 0 25s nginx-deployment-3066724191-08mng 0/1 ImagePullBackOff 0 6s
注意
部署控制器會自動停止錯誤的推出,並停止擴展新的副本集。這取決於您指定的 rollingUpdate 參數 (特別是maxUnavailable
)。Kubernetes 預設將值設定為 25%。取得部署的描述
kubectl describe deployment
輸出類似於此
Name: nginx-deployment Namespace: default CreationTimestamp: Tue, 15 Mar 2016 14:48:04 -0700 Labels: app=nginx Selector: app=nginx Replicas: 3 desired | 1 updated | 4 total | 3 available | 1 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.161 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True ReplicaSetUpdated OldReplicaSets: nginx-deployment-1564180365 (3/3 replicas created) NewReplicaSet: nginx-deployment-3066724191 (1/1 replicas created) Events: FirstSeen LastSeen Count From SubObjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 1m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-2035384211 to 3 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 1 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 2 22s 22s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 2 21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 1 21s 21s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-1564180365 to 3 13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set nginx-deployment-2035384211 to 0 13s 13s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set nginx-deployment-3066724191 to 1
若要修正此問題,您需要回滾到先前的部署修訂版本,該版本是穩定的。
檢查部署的推出歷史記錄
依照以下步驟檢查部署的推出歷史記錄
首先,檢查此部署的修訂版本
kubectl rollout history deployment/nginx-deployment
輸出類似於此
deployments "nginx-deployment" REVISION CHANGE-CAUSE 1 kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml 2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 3 kubectl set image deployment/nginx-deployment nginx=nginx:1.161
CHANGE-CAUSE
會在建立時從部署註解kubernetes.io/change-cause
複製到其修訂版本。您可以透過以下方式指定CHANGE-CAUSE
訊息- 使用
kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1"
註解部署 - 手動編輯資源的 manifest。
- 使用
若要查看每個修訂版本的詳細資訊,請執行
kubectl rollout history deployment/nginx-deployment --revision=2
輸出類似於此
deployments "nginx-deployment" revision 2 Labels: app=nginx pod-template-hash=1159050644 Annotations: kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 Containers: nginx: Image: nginx:1.16.1 Port: 80/TCP QoS Tier: cpu: BestEffort memory: BestEffort Environment Variables: <none> No volumes.
回滾到先前的修訂版本
依照以下步驟將部署從目前版本回滾到先前的版本,即版本 2。
現在您已決定取消目前的部署推出並回滾到先前的修訂版本
kubectl rollout undo deployment/nginx-deployment
輸出類似於此
deployment.apps/nginx-deployment rolled back
或者,您可以透過使用
--to-revision
指定特定修訂版本來回滾kubectl rollout undo deployment/nginx-deployment --to-revision=2
輸出類似於此
deployment.apps/nginx-deployment rolled back
如需有關部署推出相關指令的更多詳細資訊,請閱讀
kubectl rollout
。部署現在已回滾到先前的穩定修訂版本。如您所見,從部署控制器產生了用於回滾到修訂版本 2 的
DeploymentRollback
事件。檢查回滾是否成功且部署是否如預期執行,請執行
kubectl get deployment nginx-deployment
輸出類似於此
NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 30m
取得部署的描述
kubectl describe deployment nginx-deployment
輸出類似於此
Name: nginx-deployment Namespace: default CreationTimestamp: Sun, 02 Sep 2018 18:17:55 -0500 Labels: app=nginx Annotations: deployment.kubernetes.io/revision=4 kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 Selector: app=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.16.1 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: nginx-deployment-c4747d96c (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deployment-75675f5897 to 3 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 2 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 1 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-c4747d96c to 3 Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deployment-75675f5897 to 0 Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deployment-595696685f to 1 Normal DeploymentRollback 15s deployment-controller Rolled back deployment "nginx-deployment" to revision 2 Normal ScalingReplicaSet 15s deployment-controller Scaled down replica set nginx-deployment-595696685f to 0
擴展部署
您可以使用以下指令來擴展部署
kubectl scale deployment/nginx-deployment --replicas=10
輸出類似於此
deployment.apps/nginx-deployment scaled
假設您的叢集中已啟用水平 Pod 自動擴展,您可以為您的部署設定自動擴展器,並根據現有 Pod 的 CPU 使用率選擇您想要執行的最小和最大 Pod 數量。
kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80
輸出類似於此
deployment.apps/nginx-deployment scaled
比例擴展
RollingUpdate 部署支援同時執行應用程式的多個版本。當您或自動擴展器擴展處於部署推出中間 (無論是進行中還是已暫停) 的 RollingUpdate 部署時,部署控制器會平衡現有作用中副本集 (具有 Pod 的副本集) 中的其他副本,以降低風險。這稱為比例擴展。
例如,您正在執行具有 10 個副本、maxSurge=3 和 maxUnavailable=2 的部署。
確保部署中的 10 個副本正在執行。
kubectl get deploy
輸出類似於此
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 10 10 10 10 50s
您更新到新的映像檔,該映像檔恰好無法從叢集內部解析。
kubectl set image deployment/nginx-deployment nginx=nginx:sometag
輸出類似於此
deployment.apps/nginx-deployment image updated
映像檔更新啟動了新的部署推出,副本集為 nginx-deployment-1989198191,但由於您在上面提及的
maxUnavailable
需求而被封鎖。檢查部署推出狀態kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE nginx-deployment-1989198191 5 5 0 9s nginx-deployment-618515232 8 8 8 1m
然後出現針對部署的新擴展請求。自動擴展器將部署副本數增加到 15。部署控制器需要決定將這 5 個新的副本新增到哪裡。如果您未使用比例擴展,則所有 5 個副本都將新增到新的副本集中。透過比例擴展,您可以將其他副本分散到所有副本集。較大的比例會分配給具有最多副本的副本集,而較小的比例會分配給具有較少副本的副本集。任何剩餘的副本都會新增到具有最多副本的副本集中。副本數為零的副本集不會擴展。
在我們上面的範例中,3 個副本新增到舊的副本集,2 個副本新增到新的副本集。部署推出程序最終應將所有副本移至新的副本集,前提是新的副本變得健全。若要確認這一點,請執行
kubectl get deploy
輸出類似於此
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
部署推出狀態確認了副本如何新增到每個副本集。
kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
暫停和恢復部署的部署推出
當您更新部署或計劃更新部署時,您可以在觸發一個或多個更新之前暫停該部署的部署推出。當您準備好套用這些變更時,您可以恢復部署的部署推出。這種方法可讓您在暫停和恢復之間套用多個修正程式,而不會觸發不必要的部署推出。
例如,對於已建立的部署
取得部署詳細資訊
kubectl get deploy
輸出類似於此
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 3 3 3 3 1m
取得部署推出狀態
kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE nginx-2142116321 3 3 3 1m
執行以下指令來暫停
kubectl rollout pause deployment/nginx-deployment
輸出類似於此
deployment.apps/nginx-deployment paused
然後更新部署的映像檔
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
輸出類似於此
deployment.apps/nginx-deployment image updated
請注意,沒有啟動新的部署推出
kubectl rollout history deployment/nginx-deployment
輸出類似於此
deployments "nginx" REVISION CHANGE-CAUSE 1 <none>
取得部署推出狀態以驗證現有的副本集是否未變更
kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE nginx-2142116321 3 3 3 2m
您可以進行任意數量的更新,例如,更新將使用的資源
kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
輸出類似於此
deployment.apps/nginx-deployment resource requirements updated
暫停部署推出之前的部署初始狀態將繼續其功能,但只要部署部署推出處於暫停狀態,對部署的新更新將不會產生任何影響。
最終,恢復部署部署推出並觀察新的副本集啟動並包含所有新更新
kubectl rollout resume deployment/nginx-deployment
輸出類似於此
deployment.apps/nginx-deployment resumed
監看部署推出的狀態,直到完成。
kubectl get rs --watch
輸出類似於此
NAME DESIRED CURRENT READY AGE nginx-2142116321 2 2 2 2m nginx-3926361531 2 2 0 6s nginx-3926361531 2 2 1 18s nginx-2142116321 1 2 2 2m nginx-2142116321 1 2 2 2m nginx-3926361531 3 2 1 18s nginx-3926361531 3 2 1 18s nginx-2142116321 1 1 1 2m nginx-3926361531 3 3 1 18s nginx-3926361531 3 3 2 19s nginx-2142116321 0 1 1 2m nginx-2142116321 0 1 1 2m nginx-2142116321 0 0 0 2m nginx-3926361531 3 3 3 20s
取得最新部署推出的狀態
kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE nginx-2142116321 0 0 0 2m nginx-3926361531 3 3 3 28s
注意
在您恢復已暫停的部署之前,您無法回滾它。部署狀態
部署在其生命週期中會進入各種狀態。它可以是進行中,同時推出新的副本集,它可以是完成,或者它可以無法進行。
進行中部署
當執行以下其中一項工作時,Kubernetes 會將部署標記為進行中
- 部署建立新的副本集。
- 部署正在擴展其最新的副本集。
- 部署正在縮減其較舊的副本集。
- 新的 Pod 變得就緒或可用 (就緒至少 MinReadySeconds)。
當部署推出變成「進行中」時,部署控制器會將具有以下屬性的條件新增至部署的 .status.conditions
type: Progressing
status: "True"
reason: NewReplicaSetCreated
|reason: FoundNewReplicaSet
|reason: ReplicaSetUpdated
您可以使用 kubectl rollout status
來監控部署的進度。
已完成部署
當 Kubernetes 部署具有以下特徵時,Kubernetes 會將其標記為已完成
- 與部署關聯的所有副本都已更新為您指定的最新版本,表示您要求的所有更新都已完成。
- 與部署關聯的所有副本都可用。
- 沒有部署的舊副本正在執行。
當部署推出變成「已完成」時,部署控制器會將具有以下屬性的條件設定為部署的 .status.conditions
type: Progressing
status: "True"
reason: NewReplicaSetAvailable
此 Progressing
條件將保留 "True"
的狀態值,直到啟動新的部署推出。即使副本的可用性發生變更 (這確實會影響 Available
條件),該條件仍然成立。
您可以使用 kubectl rollout status
來檢查部署是否已完成。如果部署推出成功完成,kubectl rollout status
會傳回零退出代碼。
kubectl rollout status deployment/nginx-deployment
輸出類似於此
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out
且來自 kubectl rollout
的退出狀態為 0 (成功)
echo $?
0
失敗的部署
您的部署可能會在嘗試部署其最新的副本集時停滯,而永遠無法完成。這可能是由於以下某些因素造成的
- 配額不足
- 就緒探測失敗
- 映像檔提取錯誤
- 權限不足
- 限制範圍
- 應用程式執行階段設定錯誤
您可以偵測到此狀況的一種方法是在部署規格中指定截止期限參數:(.spec.progressDeadlineSeconds
)。.spec.progressDeadlineSeconds
表示部署控制器等待的秒數,然後 (在部署狀態中) 指示部署進度已停滯。
以下 kubectl
指令將規格設定為 progressDeadlineSeconds
,以使控制器在 10 分鐘後報告部署的部署推出缺乏進度
kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
輸出類似於此
deployment.apps/nginx-deployment patched
一旦超過截止期限,部署控制器會將具有以下屬性的 DeploymentCondition 新增至部署的 .status.conditions
type: Progressing
status: "False"
reason: ProgressDeadlineExceeded
此條件也可能提前失敗,然後由於 ReplicaSetCreateError
等原因而設定為 "False"
的狀態值。此外,一旦部署部署推出完成,就不再考慮截止期限。
請參閱Kubernetes API 慣例以取得有關狀態條件的更多資訊。
注意
Kubernetes 對於停滯的部署不採取任何動作,除了報告具有reason: ProgressDeadlineExceeded
的狀態條件。更高等級的協調器可以利用它並採取相應的行動,例如,將部署回滾到其先前的版本。注意
如果您暫停部署部署推出,Kubernetes 不會根據您指定的截止期限檢查進度。您可以安全地在部署推出中間暫停部署推出並恢復,而不會觸發超過截止期限的條件。您的部署可能會遇到暫時性錯誤,可能是因為您設定的逾時時間過短,或是由於任何其他類型的可以視為暫時性的錯誤。例如,假設您的配額不足。如果您描述部署,您會注意到以下章節
kubectl describe deployment nginx-deployment
輸出類似於此
<...>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True ReplicaSetUpdated
ReplicaFailure True FailedCreate
<...>
如果您執行 kubectl get deployment nginx-deployment -o yaml
,部署狀態類似於此
status:
availableReplicas: 2
conditions:
- lastTransitionTime: 2016-10-04T12:25:39Z
lastUpdateTime: 2016-10-04T12:25:39Z
message: Replica set "nginx-deployment-4262182780" is progressing.
reason: ReplicaSetUpdated
status: "True"
type: Progressing
- lastTransitionTime: 2016-10-04T12:25:42Z
lastUpdateTime: 2016-10-04T12:25:42Z
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: 2016-10-04T12:25:39Z
lastUpdateTime: 2016-10-04T12:25:39Z
message: 'Error creating: pods "nginx-deployment-4262182780-" is forbidden: exceeded quota:
object-counts, requested: pods=1, used: pods=3, limited: pods=2'
reason: FailedCreate
status: "True"
type: ReplicaFailure
observedGeneration: 3
replicas: 2
unavailableReplicas: 2
最終,一旦超過部署進度截止期限,Kubernetes 會更新狀態和 Progressing 條件的原因
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
您可以透過縮減部署、縮減您可能正在執行的其他控制器或增加命名空間中的配額來解決配額不足的問題。如果您滿足配額條件,並且部署控制器隨後完成部署部署推出,您將看到部署的狀態更新為成功條件 (status: "True"
和 reason: NewReplicaSetAvailable
)。
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
type: Available
且 status: "True"
表示您的部署具有最低可用性。最低可用性由部署策略中指定的參數決定。type: Progressing
且 status: "True"
表示您的部署處於部署推出中間並且正在進行中,或者它已成功完成其進度並且最低要求的新副本可用 (請參閱條件的原因以了解詳細資訊 - 在我們的案例中,reason: NewReplicaSetAvailable
表示部署已完成)。
您可以使用 kubectl rollout status
來檢查部署是否未能進行。如果部署已超過進度期限,kubectl rollout status
會傳回非零退出代碼。
kubectl rollout status deployment/nginx-deployment
輸出類似於此
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
且來自 kubectl rollout
的退出狀態為 1 (表示錯誤)
echo $?
1
對失敗的部署進行操作
適用於已完成部署的所有動作也適用於失敗的部署。您可以將其擴展/縮減、回滾到先前的修訂版本,甚至在您需要在部署 Pod 範本中套用多個調整時暫停它。
清除策略
您可以在部署中設定 .spec.revisionHistoryLimit
欄位,以指定您要為此部署保留多少個舊的副本集。其餘的將在背景中進行垃圾收集。預設情況下,它是 10。
注意
將此欄位明確設定為 0 將導致清除部署的所有歷史記錄,因此該部署將無法回滾。金絲雀部署
如果您想要使用部署將版本發佈到使用者或伺服器的子集,您可以建立多個部署,每個版本一個部署,遵循管理資源中描述的金絲雀模式。
撰寫部署規格
與所有其他 Kubernetes 設定一樣,部署需要 .apiVersion
、.kind
和 .metadata
欄位。如需有關使用設定檔的一般資訊,請參閱部署應用程式、設定容器和使用 kubectl 管理資源文件。
當控制平面為部署建立新的 Pod 時,部署的 .metadata.name
是命名這些 Pod 的基礎的一部分。部署的名稱必須是有效的 DNS 子網域 值,但這可能會為 Pod 主機名稱產生非預期的結果。為了獲得最佳相容性,名稱應遵循更嚴格的 DNS 標籤 規則。
部署也需要 .spec
區段。
Pod 範本
.spec.template
和 .spec.selector
是 .spec
的唯一必要欄位。
.spec.template
是 Pod 範本。它與 Pod 具有完全相同的架構,只是它是巢狀的,並且沒有 apiVersion
或 kind
。
除了 Pod 的必要欄位外,部署中的 Pod 範本還必須指定適當的標籤和適當的重新啟動策略。對於標籤,請確保不要與其他控制器重疊。請參閱選取器。
僅允許 .spec.template.spec.restartPolicy
等於 Always
,如果未指定,則為預設值。
副本數
.spec.replicas
是一個選用欄位,用於指定期望的 Pod 數量。預設值為 1。
如果您手動擴展部署,例如透過 kubectl scale deployment deployment --replicas=X
,然後您根據 manifest 更新該部署 (例如:透過執行 kubectl apply -f deployment.yaml
),則套用該 manifest 會覆寫您先前執行的手動擴展。
如果 HorizontalPodAutoscaler (或任何類似的水平擴展 API) 正在管理部署的擴展,請勿設定 .spec.replicas
。
相反地,允許 Kubernetes 控制平面自動管理 .spec.replicas
欄位。
選取器
.spec.selector
是一個必要欄位,用於指定此部署目標 Pod 的標籤選取器。
.spec.selector
必須與 .spec.template.metadata.labels
相符,否則 API 將會拒絕它。
在 API 版本 apps/v1
中,如果未設定 .spec.selector
和 .metadata.labels
,則它們不會預設為 .spec.template.metadata.labels
。因此它們必須明確設定。另請注意,在 apps/v1
中建立部署後,.spec.selector
是不可變的。
如果 Pod 的範本與 .spec.template
不同,或者如果此類 Pod 的總數超過 .spec.replicas
,則部署可能會終止標籤與選取器相符的 Pod。如果 Pod 的數量少於期望的數量,它會啟動具有 .spec.template
的新 Pod。
注意
您不應建立其他標籤與此選取器相符的 Pod,無論是直接建立、透過建立另一個部署,還是透過建立另一個控制器 (例如副本集或 ReplicationController)。如果您這樣做,第一個部署會認為它建立了這些其他 Pod。Kubernetes 不會阻止您這樣做。如果您有多個控制器具有重疊的選取器,則控制器將會彼此衝突並且無法正常運作。
策略
.spec.strategy
指定用於將舊 Pod 替換為新 Pod 的策略。.spec.strategy.type
可以是 "Recreate" 或 "RollingUpdate"。"RollingUpdate" 是預設值。
重新建立部署
當 .spec.strategy.type==Recreate
時,所有現有的 Pod 都會在建立新的 Pod 之前終止。
注意
這僅能保證在升級之前終止 Pod。如果您升級部署,舊修訂版本的所有 Pod 都會立即終止。在建立新修訂版本的任何 Pod 之前,會等待成功移除。如果您手動刪除 Pod,則生命週期由副本集控制,並且會立即建立替換 (即使舊 Pod 仍處於 Terminating 狀態)。如果您需要 Pod 的「最多」保證,則應考慮使用 StatefulSet。滾動更新部署
當 .spec.strategy.type==RollingUpdate
時,部署會以滾動更新方式更新 Pod。您可以指定 maxUnavailable
和 maxSurge
來控制滾動更新程序。
最大不可用數
.spec.strategy.rollingUpdate.maxUnavailable
是一個選填欄位,用於指定在更新過程中,最多可以有多少個 Pod 無法使用。值可以是絕對數字(例如:5)或是期望 Pod 數量的百分比(例如:10%)。絕對數字是從百分比向下取整數計算而得。如果 .spec.strategy.rollingUpdate.maxSurge
為 0,則此值不能為 0。預設值為 25%。
例如,當此值設定為 30% 時,當滾動式更新開始時,舊的 ReplicaSet 可以立即縮減到期望 Pod 數量的 70%。一旦新的 Pod 準備就緒,舊的 ReplicaSet 可以進一步縮減,然後擴增新的 ReplicaSet,以確保在更新期間任何時間可用的 Pod 總數至少為期望 Pod 數量的 70%。
Max Surge(最大突增)
.spec.strategy.rollingUpdate.maxSurge
是一個選填欄位,用於指定可以超出期望 Pod 數量而建立的最大 Pod 數量。值可以是絕對數字(例如:5)或是期望 Pod 數量的百分比(例如:10%)。如果 MaxUnavailable
為 0,則此值不能為 0。絕對數字是從百分比向上取整數計算而得。預設值為 25%。
例如,當此值設定為 30% 時,當滾動式更新開始時,新的 ReplicaSet 可以立即擴增,使得新舊 Pod 的總數不超過期望 Pod 數量的 130%。一旦舊的 Pod 被終止,新的 ReplicaSet 可以進一步擴增,以確保在更新期間任何時間運行的 Pod 總數最多為期望 Pod 數量的 130%。
以下是一些使用 maxUnavailable
和 maxSurge
的滾動式更新 Deployment 範例:
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: nginx:1.14.2
ports:
- containerPort: 80
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
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: nginx:1.14.2
ports:
- containerPort: 80
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
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: nginx:1.14.2
ports:
- containerPort: 80
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
Progress Deadline Seconds(進度截止期限秒數)
.spec.progressDeadlineSeconds
是一個選填欄位,用於指定您希望等待 Deployment 進度的秒數,然後系統回報 Deployment 進度失敗 - 在資源狀態中以 type: Progressing
、status: "False"
和 reason: ProgressDeadlineExceeded
的條件呈現。Deployment 控制器將持續重試 Deployment。預設值為 600。未來,一旦實作自動回滾,Deployment 控制器將在觀察到此類條件時立即回滾 Deployment。
如果指定,則此欄位需要大於 .spec.minReadySeconds
。
Min Ready Seconds(最少就緒秒數)
.spec.minReadySeconds
是一個選填欄位,用於指定新建立的 Pod 應處於就緒狀態的最小秒數,且其任何容器皆未發生 crash,才會被視為可用。預設值為 0(Pod 一旦就緒就會被視為可用)。若要進一步瞭解 Pod 何時被視為就緒,請參閱容器探針。
Revision History Limit(修訂歷史限制)
Deployment 的修訂歷史記錄儲存在其控制的 ReplicaSet 中。
.spec.revisionHistoryLimit
是一個選填欄位,用於指定要保留多少舊的 ReplicaSet 以允許回滾。這些舊的 ReplicaSet 會消耗 etcd
中的資源,並使 kubectl get rs
的輸出變得雜亂。每個 Deployment 修訂版本的組態都儲存在其 ReplicaSet 中;因此,一旦刪除舊的 ReplicaSet,您將失去回滾到該 Deployment 修訂版本的能力。預設情況下,將保留 10 個舊的 ReplicaSet,但其理想值取決於新 Deployment 的頻率和穩定性。
更具體來說,將此欄位設定為零表示所有具有 0 個副本的舊 ReplicaSet 都將被清除。在這種情況下,新的 Deployment 推出將無法還原,因為其修訂歷史記錄已被清除。
已暫停
.spec.paused
是一個選填的布林值欄位,用於暫停和恢復 Deployment。暫停的 Deployment 與未暫停的 Deployment 之間唯一的區別在於,只要 Deployment 處於暫停狀態,對暫停的 Deployment 的 PodTemplateSpec 進行任何變更都不會觸發新的推出。Deployment 在建立時預設為未暫停。
接下來
- 進一步瞭解Pod。
- 使用 Deployment 執行無狀態應用程式.
- 閱讀 Deployment 以瞭解 Deployment API。
- 閱讀關於 PodDisruptionBudget 以及如何在干擾期間使用它來管理應用程式的可用性。
- 使用 kubectl 來建立 Deployment。