Deployment 為 Pod 和 ReplicaSet 提供宣告式的更新。
您可以在 Deployment 中描述預期狀態 (desired state),Deployment 控制器會以受控的速率將實際狀態更改為預期狀態。您可以定義 Deployment 來建立新的 ReplicaSet,或者移除現有的 Deployment 並以新的 Deployment 接管其所有資源。
以下是 Deployment 的典型使用場景:
以下是 Deployment 的範例。它建立了一個 ReplicaSet 來啟動三個 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
在此範例中:
透過 .metadata.name 欄位建立名為 nginx-deployment 的 Deployment。此名稱將作為後續建立的 ReplicaSet 和 Pod 的基礎。詳情請參閱 撰寫 Deployment 規格。
Deployment 建立一個 ReplicaSet,該 ReplicaSet 建立三個副本 Pod,由 .spec.replicas 欄位指定。
.spec.selector 欄位定義了所建立的 ReplicaSet 如何找到要管理的 Pod。在本例中,選擇了 Pod 範本中定義的標籤(app: nginx)。只要 Pod 範本本身符合規則,也可以使用更複雜的選擇規則。
.spec.selector.matchLabels 欄位是一個 {key,value} 對映。matchLabels 中的單個 {key,value} 等同於 matchExpressions 的一個元素,其中 key 為 "key",operator 為 "In",且 values 陣列僅包含 "value"。若要符合匹配,必須同時滿足 matchLabels 和 matchExpressions 的所有要求。.spec.template 欄位包含以下子欄位:
.metadata.labels 欄位將 Pod 標記為 app: nginx。.spec 欄位) 指出 Pod 執行一個名為 nginx 的容器,該容器執行 1.14.2 版本的 Docker Hub nginx 映像檔。.spec.containers[0].name 欄位建立一個名為 nginx 的容器。開始之前,請確保您的 Kubernetes 叢集已啟動並運行。請遵循以下步驟建立上述 Deployment。
透過執行以下指令建立 Deployment:
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
執行 kubectl get deployments 以檢查 Deployment 是否已建立。
如果 Deployment 仍在建立中,輸出將類似於以下內容:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 0/3 0 0 1s
當您查看叢集中的 Deployment 時,會顯示以下欄位:
NAME:列出命名空間中的 Deployment 名稱。READY:顯示有多少副本應用程式可供使用者使用。遵循 ready/desired 的格式。UP-TO-DATE:顯示已更新以達到預期狀態的副本數量。AVAILABLE:顯示有多少副本應用程式可供使用者使用。AGE:顯示應用程式運行的時間長度。請注意,根據 .spec.replicas 欄位,預期副本數量為 3。
若要查看 Deployment 的發佈狀態,請執行 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
請注意,Deployment 已建立所有三個副本,並且所有副本皆為最新(包含最新的 Pod 範本)且可用。
若要查看由 Deployment 建立的 ReplicaSet (rs),請執行 kubectl get rs。輸出將類似於:
NAME DESIRED CURRENT READY AGE
nginx-deployment-75675f5897 3 3 3 18s
ReplicaSet 的輸出顯示以下欄位:
NAME:列出命名空間中的 ReplicaSet 名稱。DESIRED:顯示應用程式副本的預期數量(您在建立 Deployment 時定義的)。這是預期狀態。CURRENT:顯示目前正在運行的副本數量。READY:顯示有多少副本應用程式可供使用者使用。AGE:顯示應用程式運行的時間長度。請注意,ReplicaSet 的名稱格式始終為 [DEPLOYMENT-NAME]-[HASH]。此名稱將成為所建立 Pod 的基礎。
HASH 字串與 ReplicaSet 上的 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
所建立的 ReplicaSet 確保存在三個 nginx Pod。
您必須在 Deployment 中指定適當的選擇器和 Pod 範本標籤(本例中為 app: nginx)。
請勿與其他控制器(包括其他 Deployment 和 StatefulSet)重疊標籤或選擇器。Kubernetes 不會阻止這種重疊,如果多個控制器具有重疊的選擇器,這些控制器可能會發生衝突並產生非預期的行為。
pod-template-hash 標籤由 Deployment 控制器新增至 Deployment 所建立或接管的每個 ReplicaSet 中。
此標籤確保 Deployment 的子 ReplicaSet 不會重疊。它是透過對 ReplicaSet 的 PodTemplate 進行雜湊處理而產生的,並將產生的雜湊值作為標籤值新增至 ReplicaSet 選擇器、Pod 範本標籤以及 ReplicaSet 可能擁有的任何現有 Pod 中。
.spec.template)發生更改時才會觸發,例如更新範本的標籤或容器映像檔。其他更新(如擴縮容 Deployment)不會觸發發佈。請遵循以下步驟來更新您的 Deployment:
讓我們將 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 指的是 Deployment,nginx 是要進行更新的容器,nginx:1.16.1 是新的映像檔及其標籤。
輸出類似於
deployment.apps/nginx-deployment image updated
或者,您可以 edit Deployment 並將 .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
取得關於您已更新的 Deployment 的更多詳細資訊:
發佈成功後,您可以執行 kubectl get deployments 來查看 Deployment。輸出類似於:
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 36s
執行 kubectl get rs 以查看 Deployment 如何透過建立新的 ReplicaSet 並將其擴容至 3 個副本,同時將舊的 ReplicaSet 縮容至 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 現在應該只顯示新的 Pod。
kubectl 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 時,只需再次更新 Deployment 的 Pod 範本即可。
Deployment 確保在更新 Pod 時,只有特定數量的 Pod 會關閉。預設情況下,它確保至少有 75% 的預期 Pod 數量在運行(最多 25% 不可用)。
Deployment 也確保建立的 Pod 數量不會超過預期數量。預設情況下,它確保最多有 125% 的預期 Pod 數量在運行(最多 25% 溢出)。
例如,如果您仔細觀察上述 Deployment,會發現它先建立一個新 Pod,然後刪除一個舊 Pod,接著再建立一個新 Pod。在有足夠數量的新 Pod 啟動之前,它不會殺掉舊 Pod;在有足夠數量的舊 Pod 被殺掉之前,它不會建立新 Pod。它確保至少有 3 個 Pod 可用,且總共最多有 4 個 Pod 可用。對於具有 4 個副本的 Deployment,Pod 的數量會在 3 到 5 個之間。
取得 Deployment 的詳細資訊:
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
在這裡您可以看到,當您首次建立 Deployment 時,它建立了一個 ReplicaSet (nginx-deployment-2035384211) 並直接將其擴容至 3 個副本。當您更新 Deployment 時,它建立了一個新的 ReplicaSet (nginx-deployment-1564180365) 並將其擴容至 1,然後等待其啟動。接著,它將舊的 ReplicaSet 縮容至 2,並將新的 ReplicaSet 擴容至 2,以便隨時確保至少有 3 個 Pod 可用,且最多建立 4 個 Pod。然後,它繼續以相同的滾動更新策略對新舊 ReplicaSet 進行擴縮容。最後,您將在新的 ReplicaSet 中擁有 3 個可用的副本,而舊的 ReplicaSet 則縮容至 0。
availableReplicas 的數量時不會統計終止中的 Pod,該數量必須在 replicas - maxUnavailable 和 replicas + maxSurge 之間。因此,您可能會發現在發佈過程中 Pod 的數量比預期的多,且在終止中的 Pod 的 terminationGracePeriodSeconds 過期之前,Deployment 所消耗的總資源可能會超過 replicas + maxSurge。每當 Deployment 控制器觀察到一個新的 Deployment 時,就會建立一個 ReplicaSet 來啟動預期的 Pod。如果 Deployment 發生更新,則現有控制 Pod 的 ReplicaSet(其標籤符合 .spec.selector 但範本不符合 .spec.template)將會被縮容。最終,新的 ReplicaSet 將擴容至 .spec.replicas,而所有舊的 ReplicaSet 將縮容至 0。
如果您在現有的發佈過程中更新 Deployment,Deployment 會根據更新建立新的 ReplicaSet 並開始擴容,同時對之前正在擴容的 ReplicaSet 進行翻轉 (rollover)——它會將其新增至舊 ReplicaSet 的清單中並開始縮容。
例如,假設您建立了一個 Deployment 來建立 5 個 nginx:1.14.2 的副本,但隨後在僅建立了 3 個 nginx:1.14.2 副本時,將 Deployment 更新為建立 5 個 nginx:1.16.1 的副本。在這種情況下,Deployment 會立即開始殺掉它已建立的 3 個 nginx:1.14.2 Pod,並開始建立 nginx:1.16.1 Pod。它不會等待 5 個 nginx:1.14.2 副本全部建立完成才更改目標。
通常不鼓勵修改標籤選擇器,建議事先規劃好您的選擇器。Deployment 的標籤選擇器在建立後是不可變的;它不能透過 kubectl patch、kubectl edit、kubectl apply 或 helm upgrade 等工具進行更新。
如果您必須更改選擇器,則必須刪除並重新建立 Deployment。請格外小心,並確保您理解以下含義:
v1 到 v2)會導致與新增相同的行為(孤立與重建)。有時,您可能想要回滾 Deployment;例如,當 Deployment 不穩定(如崩潰重啟)時。預設情況下,系統會保留所有 Deployment 的發佈歷史,以便您隨時進行回滾(您可以透過修改版本歷史紀錄限制來變更此設定)。
.spec.template) 發生更改時(例如更新標籤或容器映像檔),才會建立新版本。其他更新(如縮擴容 Deployment)不會建立 Deployment 版本,這樣您就可以促進手動或自動的同時擴縮容。這意味著當您回滾到先前的版本時,只會回滾 Deployment 的 Pod 範本部分。假設您在更新 Deployment 時出現拼字錯誤,將映像檔名稱設定為 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,您會發現由新的 ReplicaSet 建立的 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
maxUnavailable)。Kubernetes 預設將此值設定為 25%。取得 Deployment 的描述:
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
要修復此問題,您需要回滾到先前穩定版本的 Deployment。
請遵循以下步驟檢查發佈歷史:
首先,檢查此 Deployment 的版本:
kubectl rollout history deployment/nginx-deployment
輸出類似於此
deployments "nginx-deployment"
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
CHANGE-CAUSE 是在建立時從 Deployment 註釋 kubernetes.io/change-cause 複製到其版本中的。您可以透過以下方式指定 CHANGE-CAUSE 訊息:
kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1" 註釋 Deployment。--record 旗標來自動填入 CHANGE-CAUSE 欄位。此旗標已被棄用,並將在未來的版本中移除。若要查看每個版本的詳細資訊,請執行:
kubectl rollout history deployment/nginx-deployment --revision=2
輸出類似於此
deployments "nginx-deployment" revision 2
Labels: app=nginx
pod-template-hash=1159050644
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
QoS Tier:
cpu: BestEffort
memory: BestEffort
Environment Variables: <none>
No volumes.
請遵循以下步驟將 Deployment 從當前版本回滾到先前版本(即第 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。
Deployment 現在已回滾到先前的穩定版本。如您所見,Deployment 控制器產生了一個用於回滾到版本 2 的 DeploymentRollback 事件。
若要檢查回滾是否成功且 Deployment 是否如預期運行,請執行:
kubectl get deployment nginx-deployment
輸出類似於此
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 30m
取得 Deployment 的描述:
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
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
您可以使用以下指令來擴縮容 Deployment:
kubectl scale deployment/nginx-deployment --replicas=10
輸出類似於此
deployment.apps/nginx-deployment scaled
假設您的叢集中啟用了 Horizontal Pod Autoscaling (HPA),您可以為您的 Deployment 設定自動擴縮容,並根據現有 Pod 的 CPU 利用率來選擇要運行的 Pod 最小和最大數量。
kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80%
輸出類似於此
deployment.apps/nginx-deployment scaled
RollingUpdate Deployment 支援同時運行應用程式的多個版本。當您或自動擴縮容工具對處於發佈中(進行中或暫停)的 RollingUpdate Deployment 進行擴縮容時,Deployment 控制器會平衡現有活動 ReplicaSet(具有 Pod 的 ReplicaSet)中的額外副本,以降低風險。這稱為比例縮放 (proportional scaling)。
例如,您正在運行一個具有 10 個副本的 Deployment,maxSurge=3,且 maxUnavailable=2。
確保您 Deployment 中的 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
映像檔更新啟動了一個使用 ReplicaSet 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
隨後,Deployment 的一個新的縮擴容請求到來。自動擴縮容工具將 Deployment 副本增加到 15。Deployment 控制器需要決定將這 5 個新副本新增到哪裡。如果您不使用比例縮放,它們將全部新增到新的 ReplicaSet 中。使用比例縮放,您可以將額外的副本分散到所有 ReplicaSet。最大的比例會分配給擁有最多副本的 ReplicaSet,較小的比例會分配給擁有較少副本的 ReplicaSet。任何剩餘部分都會新增到擁有最多副本的 ReplicaSet 中。副本數量為 0 的 ReplicaSet 不會被擴容。
在上述範例中,3 個副本被新增到舊的 ReplicaSet,2 個副本被新增到新的 ReplicaSet。假設新的副本變得健康,發佈過程最終應該會將所有副本移動到新的 ReplicaSet。若要確認這一點,請執行:
kubectl get deploy
輸出類似於此
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 15 18 7 8 7m
發佈狀態確認了副本是如何新增到每個 ReplicaSet 中的。
kubectl get rs
輸出類似於此
NAME DESIRED CURRENT READY AGE
nginx-deployment-1989198191 7 7 0 7m
nginx-deployment-618515232 11 11 11 7m
當您更新 Deployment 或計劃更新時,可以在觸發一項或多項更新之前暫停該 Deployment 的發佈。當您準備好套用這些變更時,請恢復 Deployment 的發佈。這種方法允許您在暫停和恢復之間套用多項修復,而不會觸發不必要的發佈。
例如,對於一個已建立的 Deployment:
取得 Deployment 詳細資訊:
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
然後更新 Deployment 的映像檔:
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>
取得發佈狀態以驗證現有的 ReplicaSet 未發生變化:
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
暫停發佈之前 Deployment 的初始狀態將繼續發揮作用,但只要 Deployment 的發佈處於暫停狀態,對 Deployment 的新更新將不會產生任何影響。
最後,恢復 Deployment 的發佈並觀察一個新的 ReplicaSet 帶著所有新更新啟動。
kubectl rollout resume deployment/nginx-deployment
輸出類似於此
deployment.apps/nginx-deployment resumed
監控 (Watch) 發佈狀態直到完成。
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
Deployment 在其生命週期中會進入各種狀態。它可以在發佈新的 ReplicaSet 時處於進行中 (progressing),可以是完成 (complete),或者可能無法進行 (fail to progress)。
當執行以下任務之一時,Kubernetes 會將 Deployment 標記為進行中:
當發佈變為「進行中」時,Deployment 控制器會將具有以下屬性的條件新增至 Deployment 的 .status.conditions:
type: Progressingstatus: "True"reason: NewReplicaSetCreated | reason: FoundNewReplicaSet | reason: ReplicaSetUpdated您可以使用 kubectl rollout status 監控 Deployment 的進度。
當 Deployment 具有以下特徵時,Kubernetes 會將其標記為完成:
當發佈變為「完成」時,Deployment 控制器會設定一個具有以下屬性的條件至 Deployment 的 .status.conditions:
type: Progressingstatus: "True"reason: NewReplicaSetAvailable此 Progressing 條件將保留 "True" 的狀態值,直到啟動新的發佈。即使副本的可用性發生變化(這會影響 Available 條件),該條件仍然保持。
您可以使用 kubectl rollout status 檢查 Deployment 是否已完成。如果發佈成功完成,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
您的 Deployment 可能會卡在部署最新的 ReplicaSet 而無法完成。這可能是由以下幾個因素導致的:
檢測此狀況的一種方法是在 Deployment 規格中指定截止參數:(.spec.progressDeadlineSeconds)。.spec.progressDeadlineSeconds 表示 Deployment 控制器在指示(在 Deployment 狀態中)Deployment 進度已停滯之前等待的秒數。
以下 kubectl 指令設定了 progressDeadlineSeconds,使控制器在 10 分鐘後報告 Deployment 發佈缺乏進度:
kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
輸出類似於此
deployment.apps/nginx-deployment patched
一旦超過截止日期,Deployment 控制器就會將具有以下屬性的 DeploymentCondition 新增至 Deployment 的 .status.conditions:
type: Progressingstatus: "False"reason: ProgressDeadlineExceeded此條件也可能提早失敗,隨後由於 ReplicaSetCreateError 等原因將狀態值設為 "False"。此外,一旦 Deployment 發佈完成,將不再考慮此截止日期。
有關狀態條件的更多資訊,請參閱 Kubernetes API 約定。
reason: ProgressDeadlineExceeded 的狀態條件外,Kubernetes 不會對停滯的 Deployment 採取任何行動。更高級別的編排器可以利用它並採取相應行動,例如將 Deployment 回滾到先前的版本。您可能會遇到 Deployment 的瞬時錯誤,原因可能是您設定的超時時間過低,或是任何其他可以視為瞬時的錯誤。例如,假設您的配額不足。如果您描述該 Deployment,會注意到以下區段:
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,Deployment 的狀態將類似於:
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
最終,一旦超過 Deployment 的進度截止日期,Kubernetes 就會更新 Progressing 條件的狀態和原因:
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing False ProgressDeadlineExceeded
ReplicaFailure True FailedCreate
您可以透過縮容 Deployment、縮容您可能正在運行的其他控制器,或增加命名空間中的配額來解決配額不足的問題。如果您滿足了配額條件,且 Deployment 控制器隨後完成了 Deployment 發佈,您將會看到 Deployment 的狀態更新為成功條件 (status: "True" 和 reason: NewReplicaSetAvailable)。
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
type: Available 且 status: "True" 意味著您的 Deployment 具有最低可用性。最低可用性由部署策略中指定的參數決定。type: Progressing 且 status: "True" 意味著您的 Deployment 處於發佈過程中並且正在進展,或者它已成功完成進度,並且所需的最低新副本可用(請參閱該條件的 Reason 以了解詳細資訊——在我們的例子中,reason: NewReplicaSetAvailable 意味著 Deployment 已完成)。
您可以使用 kubectl rollout status 檢查 Deployment 是否無法進展。如果 Deployment 超過了發佈截止日期,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
所有適用於已完成 Deployment 的操作同樣適用於失敗的 Deployment。您可以對其進行擴縮容、回滾到先前的版本,或者如果需要在 Deployment Pod 範本中套用多項微調,甚至可以暫停它。
您可以在 Deployment 中設定 .spec.revisionHistoryLimit 欄位,以指定您希望保留此 Deployment 的多少個舊 ReplicaSet。其餘的將在後台進行垃圾回收。預設值為 10。
清理工作僅在 Deployment 達到完成狀態後才會開始。如果您將 .spec.revisionHistoryLimit 設定為 0,任何發佈仍然會觸發新的 ReplicaSet 的建立,然後 Kubernetes 才會移除舊的。
即使設定了非零的版本歷史紀錄限制,您擁有的 ReplicaSet 數量也可能超過您配置的限制。例如,如果 Pod 處於崩潰迴圈中,並且隨著時間的推移觸發了多個滾動更新事件,您最終可能會得到比 .spec.revisionHistoryLimit 更多的 ReplicaSet,因為 Deployment 從未達到完成狀態。
如果您希望使用 Deployment 向一部分使用者或伺服器發佈版本,可以建立多個 Deployment,每個版本一個,並遵循管理資源中描述的金絲雀模式。
與所有其他 Kubernetes 設定一樣,Deployment 需要 .apiVersion、.kind 和 .metadata 欄位。有關使用設定檔的一般資訊,請參閱部署應用程式、設定容器,以及使用 kubectl 管理資源文件。
當控制平面為 Deployment 建立新 Pod 時,Deployment 的 .metadata.name 是這些 Pod 命名基礎的一部分。Deployment 的名稱必須是有效的 DNS 子域名值,但這可能會對 Pod 主機名稱產生非預期的結果。為了獲得最佳相容性,名稱應遵循 DNS 標籤的更嚴格規則。
Deployment 還需要一個 .spec 區段。
.spec.template 和 .spec.selector 是 .spec 中僅有的必填欄位。
.spec.template 是一個 Pod 範本。它與 Pod 具有完全相同的架構,只是它是巢狀的,並且沒有 apiVersion 或 kind。
除了 Pod 的必填欄位外,Deployment 中的 Pod 範本必須指定適當的標籤和適當的重啟策略。對於標籤,請確保不要與其他控制器重疊。請參閱選擇器。
僅允許 .spec.template.spec.restartPolicy 等於 Always,這也是預設值(如果未指定)。
.spec.replicas 是一個選填欄位,指定預期的 Pod 數量。預設值為 1。
如果您手動擴縮容 Deployment(例如透過 kubectl scale deployment deployment --replicas=X),然後根據清單更新該 Deployment(例如執行 kubectl apply -f deployment.yaml),那麼套用該清單會覆蓋您之前手動進行的縮擴容。
如果 HorizontalPodAutoscaler(或任何類似的水平擴縮容 API)正在管理 Deployment 的縮擴容,請勿設定 .spec.replicas。
相反地,應允許 Kubernetes 控制平面自動管理 .spec.replicas 欄位。
.spec.selector 是一個必填欄位,指定此 Deployment 目標 Pod 的 標籤選擇器。
.spec.selector 必須與 .spec.template.metadata.labels 匹配,否則將被 API 拒絕。
在 API 版本 apps/v1 中,如果未設定,.spec.selector 和 .metadata.labels 不會預設為 .spec.template.metadata.labels。因此它們必須明確設定。另請注意,在 apps/v1 中,.spec.selector 在 Deployment 建立後是不可變的。
如果標籤與選擇器匹配的 Pod 範本與 .spec.template 不同,或者該類 Pod 的總數超過 .spec.replicas,Deployment 可能會終止這些 Pod。如果 Pod 數量少於預期數量,它會使用 .spec.template 啟動新的 Pod。
如果您有多個具有重疊選擇器的控制器,這些控制器將會互相衝突且無法正確運作。
.spec.strategy 指定用於用新 Pod 替換舊 Pod 的策略。.spec.strategy.type 可以是 "Recreate" 或 "RollingUpdate"。預設值為 "RollingUpdate"。
當 .spec.strategy.type==Recreate 時,所有現有的 Pod 在建立新 Pod 之前都會被殺掉。
當 .spec.strategy.type==RollingUpdate 時,Deployment 以滾動更新的方式更新 Pod(逐步縮容舊 ReplicaSet 並擴容新 ReplicaSet)。您可以指定 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%。
.spec.strategy.rollingUpdate.maxSurge 是一個選填欄位,指定可以在預期 Pod 數量之外建立的最大 Pod 數量。該值可以是絕對數字(例如 5)或預期 Pod 數量的百分比(例如 10%)。如果 maxUnavailable 為 0,則此值不能為 0。絕對數字是透過百分比無條件進位計算得出的。預設值為 25%。
例如,當此值設定為 30% 時,新的 ReplicaSet 可以在滾動更新開始時立即擴容,使得舊 Pod 和新 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
.spec.progressDeadlineSeconds 是一個選填欄位,指定您希望等待 Deployment 進展的秒數,然後系統才會回報 Deployment 已無法進展——在資源狀態中顯示為具有 type: Progressing、status: "False" 和 reason: ProgressDeadlineExceeded 的條件。Deployment 控制器將繼續重試該 Deployment。預設值為 600。未來,一旦實作自動回滾,Deployment 控制器將在觀察到此條件時立即回滾 Deployment。
如果指定,此欄位的值必須大於 .spec.minReadySeconds。
.spec.minReadySeconds 是一個選填欄位,指定新建立的 Pod 在沒有任何容器崩潰的情況下,應該就緒的最少秒數,才能被視為可用。預設值為 0(Pod 一就緒就會被視為可用)。要了解何時 Pod 被視為就緒,請參閱 容器探針 (Container Probes)。
Kubernetes v1.35 [beta](預設啟用)只有在 API 伺服器和 kube-controller-manager 上啟用了 DeploymentReplicaSetTerminatingReplicas 特性閘道時,您才能看到終止中的 Pod。
由於刪除或縮容而變為終止中的 Pod 可能需要很長時間才能終止,並在此期間消耗額外資源。因此,所有 Pod 的總數可能會暫時超過 .spec.replicas。可以使用 Deployment 的 .status.terminatingReplicas 欄位來追蹤終止中的 Pod。
Deployment 的版本歷史紀錄儲存在其管理的 ReplicaSet 中。
.spec.revisionHistoryLimit 是一個選填欄位,指定要保留多少個舊的 ReplicaSet 以允許回滾。這些舊的 ReplicaSet 會消耗 etcd 中的資源並佔用 kubectl get rs 的輸出。每個 Deployment 版本的配置都儲存在其 ReplicaSet 中;因此,一旦刪除舊的 ReplicaSet,您就失去了回滾到該 Deployment 版本的權限。預設會保留 10 個舊的 ReplicaSet,但其理想值取決於新 Deployment 的頻率和穩定性。
更具體地說,將此欄位設定為 0 表示將清理所有副本數為 0 的舊 ReplicaSet。在這種情況下,新的 Deployment 發佈將無法撤銷,因為其版本歷史紀錄已被清理。
.spec.paused 是一個選填的布林欄位,用於暫停和恢復 Deployment。暫停的 Deployment 與未暫停的 Deployment 之間唯一的區別是,對暫停的 Deployment 的 PodTemplateSpec 進行的任何更改,只要處於暫停狀態,就不會觸發新的發佈。Deployment 在建立時預設不暫停。