官方參考:https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
https://www.kubernetes.org.cn/deployment
Deployments
Deployment為Pod和ReplicaSet提供了一個聲明式定義(declarative)方法,用來替代以前的ReplicationController來方便的管理應用。典型的應用場景包括:
- 定義Deployment來創建Pod和ReplicaSet
- 滾動升級和回滾應用
- 擴容和縮容
- 暫停和繼續Deployment
你只需要在Deployment中描述你想要的目標狀態是什么,Deployment controller就會幫你將Pod和Replica Set的實際狀態改變到你的目標狀態。你可以定義一個全新的Deployment,也可以創建一個新的替換舊的Deployment。
一個典型的用例如下
- 使用Deployment來創建ReplicaSet。ReplicaSet在后台創建pod。檢查啟動狀態,看它是成功還是失敗。
- 然后,通過更新Deployment的PodTemplateSpec字段來聲明Pod的新狀態。這會創建一個新的ReplicaSet,Deployment會按照控制的速率將pod從舊的ReplicaSet移動到新的ReplicaSet中。
- 如果當前狀態不穩定,回滾到之前的Deployment revision。每次回滾都會更新Deployment的revision。
- 擴容Deployment以滿足更高的負載。
- 暫停Deployment來應用PodTemplateSpec的多個修復,然后恢復上線。
- 根據Deployment 的狀態判斷上線是否hang住了。
- 清除舊的不必要的ReplicaSet。
創建Deployment
下面是 Deployment 示例。創建一個 ReplicaSet 展開三個 nginx
Pods:
該示例為官方示例下載地址是
https://raw.githubusercontent.com/kubernetes/website/master/content/zh/examples/controllers/nginx-deployment.yaml
# cat nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:1.15.4 name: nginx ports: - containerPort: 80
也可以通過以下命令生成該yaml文檔然后修改
# kubectl create deployment nginx-deployment --image=nginx:1.15.4 --dry-run -o yaml apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: nginx-deployment name: nginx-deployment spec: replicas: 1 selector: matchLabels: app: nginx-deployment strategy: {} template: metadata: creationTimestamp: null labels: app: nginx-deployment spec: containers: - image: nginx:1.15.4 name: nginx resources: {} status: {}
在該例中
- 創建名為nginx-deployment的Deployment,由metadata.name字段指示
- Deployment創建3個復制的Pods,由spec.replicas字段指示,該字段可以沒有默認即為1
- selector字段定義Deployment如何查找要管理的Pods。在這種情況下只需要在Pod模板(app:nginx)中定義的標簽。
注意:`matchLabels` 字段是 {key,value} 的映射。單個 {key,value}在 `matchLabels` 映射中的值等效於 `matchExpressions` 的元素,其鍵字段是“key”,運算符為“In”,值數組僅包含“value”。所有要求,從 `matchLabels` 和 `matchExpressions`,必須滿足才能匹配。
- template字段包含以下子字段
- Pod使用labels字段標記為app:nginx
- template.spec字段指示Pod運行一個容器nginx
- 創建一個容器並使用name字段將其命名為nginx
通過運行以下命令創建Deployment
kubectl apply -f nginx-deployment.yaml
注意:將kubectl的 —record 的flag設置為 true可以在annotation中記錄當前命令創建或者升級了該資源。這在未來會很有用,例如,查看在每個Deployment revision中執行了哪些命令。
--record示例如下
運行kubectl get deployments
以檢查 Deployment 是否已創建。輸出以下內容:
# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 48s
顯示以下字段
`READY` 3/3左邊3是真正運行的副本數右邊3是期望的副本數即replicas定義的副本數。 `UP-TO-DATE`顯示已更新以實現期望狀態的副本數。 `AVAILABLE`顯示應用程序可供用戶使用的副本數。 `AGE` 顯示應用程序運行的時間量。
要查看Deployment創建的ReplicaSet(rs),運行kubectl get rs輸出
# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-67656986d9 3 3 3 108s
請注意, ReplicaSet 的名稱始終被格式化為`[DEPLOYMENT-NAME]-[RANDOM-STRING]`。隨機字符串是隨機生成並使用 pod-template-hash 作為種子
要查看每個Pod自動生成的標簽,運行kubectl get pods --show-labels輸出
# kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-67656986d9-996kk 1/1 Running 0 3m35s app=nginx,pod-template-hash=67656986d9 nginx-deployment-67656986d9-fgdwz 1/1 Running 0 3m35s app=nginx,pod-template-hash=67656986d9 nginx-deployment-67656986d9-j8jt8 1/1 Running 0 3m35s app=nginx,pod-template-hash=67656986d9
剛創建的Replica Set將保證總是有3個nginx的pod存在。並且創建的Pod名為[DEPLOYMENT-NAME]-[pod-template-hash]-[RANDOM-STRING]
注意: 你必須在Deployment中的selector指定正確pod template label(在該示例中是 app = nginx),不要跟其他的controller搞混了(包括Deployment、Replica Set、Replication Controller等)。Kubernetes本身不會阻止你這么做,如果你真的這么做了,這些controller之間會相互打架,並可能導致不正確的行為。
Pod-template-hash 標簽
注意:不要更改此標簽
Deployment 控制器將 pod-template-hash
標簽添加到 Deployment 創建或使用的每個 ReplicaSet 。
此標簽可確保 Deployment 的子 ReplicaSets 不重疊。它通過對 ReplicaSet 的 PodTemplate
進行哈希處理,並使用生成的哈希值添加到 ReplicaSet 選擇器、Pod 模板標簽,並在 ReplicaSet 可能具有的任何現有 Pod 中。
更新Deployment
注意: Deployment的rollout當且僅當Deployment的pod template(例如.spec.template)中的label更新或者鏡像更改時被觸發。其他更新,例如擴容Deployment不會觸發rollout。
安裝以下步驟更新Deployment
首先修改yaml把nginx版本修改成1.7.9
應用一下各項nginx Pods,使用nginx:1.9.1鏡像,而不是nginx:1.7.9
# kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1 deployment.apps/nginx-deployment image updated
說明:設置更新Deployment名為nginx-deployment鏡像的鏡像為nginx:1.9.1
也可以使用edit
命令來編輯Deployment,修改 .spec.template.spec.containers[0].image
,將nginx:1.7.9
改寫成nginx:1.9.1
。
kubectl edit deployment/nginx-deployment
修改完輸出
deployment.apps/nginx-deployment edited
查看rollout的狀態,只要執行:
# kubectl rollout status deployment/nginx-deployment deployment "nginx-deployment" successfully rolled out
rollout成功后查看deployment
# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 9m37s
UP-TO-DATE的replica的數目已經達到了配置中要求的數目。
CURRENT的replica數表示Deployment管理的replica數量,AVAILABLE的replica數是當前可用的replica數量。
我們通過執行kubectl get rs
可以看到Deployment更新了Pod,通過創建一個新的Replica Set並擴容了3個replica,同時將原來的Replica Set縮容到了0個replica。
# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-54f57cf6bf 0 0 0 12m nginx-deployment-56f8998dbc 3 3 3 9m6s
執行 get pods
只會看到當前的新的pod:
# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-56f8998dbc-8j49x 1/1 Running 0 5m25s nginx-deployment-56f8998dbc-fpzwt 1/1 Running 0 5m26s nginx-deployment-56f8998dbc-r2wvp 1/1 Running 0 5m28s
下次更新這些Pod的時候,只需要更新Deployment中pod的template即可
Deployment 可確保在更新時僅關閉一定數量的 Pods。默認情況下,它確保至少 75%所需 Pods 運行(25%最大不可用)。
Deployment 還確保僅創建一定數量的 Pods 高於期望的 Pods 數。默認情況下,它可確保最多增加 25% 期望 Pods 數(25%最大增量)。
例如,如果仔細查看上述 Deployment ,將看到它首先創建了一個新的 Pod,然后刪除了一些舊的 Pods,並創建了新的 Pods。它不會殺死老 Pods,直到有足夠的數量新的 Pods 已經出現,並沒有創造新的 Pods,直到足夠數量的舊 Pods 被殺死。它確保至少 2 個 Pods 可用,並且總共最多 4 個 Pods 可用。
獲取Deployment更多信息
# kubectl describe deployments nginx-deployment Name: nginx-deployment Namespace: default CreationTimestamp: Fri, 20 Mar 2020 16:01:54 +0800 Labels: app=nginx Annotations: deployment.kubernetes.io/revision: 2 kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-deployment","namespace":"d... 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.9.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-56f8998dbc (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 53s deployment-controller Scaled up replica set nginx-deployment-54f57cf6bf to 3 Normal ScalingReplicaSet 8s deployment-controller Scaled up replica set nginx-deployment-56f8998dbc to 1 Normal ScalingReplicaSet 6s deployment-controller Scaled down replica set nginx-deployment-54f57cf6bf to 2 Normal ScalingReplicaSet 6s deployment-controller Scaled up replica set nginx-deployment-56f8998dbc to 2 Normal ScalingReplicaSet 5s deployment-controller Scaled down replica set nginx-deployment-54f57cf6bf to 1 Normal ScalingReplicaSet 5s deployment-controller Scaled up replica set nginx-deployment-56f8998dbc to 3 Normal ScalingReplicaSet 3s deployment-controller Scaled down replica set nginx-deployment-54f57cf6bf to 0
可以看到,當第一次創建 Deployment 時,它創建了一個 ReplicaSet (nginx-deployment-54f57cf6bf)並將其直接擴展至 3 個副本。更新 Deployment 時,它創建了一個新的 ReplicaSet (nginx-deployment-56f8998dbc),並將其擴展為 1,然后將舊 ReplicaSet 縮小到 2,以便至少有 2 個 Pod 可用,並且最多創建 4 個 Pod。然后,它繼續向上和向下擴展新的和舊的 ReplicaSet ,具有相同的滾動更新策略。最后,將有 3 個可用的副本在新的 ReplicaSet 中,舊 ReplicaSet 將縮小到 0。
Rollover(多個rollout並行)
每當Deployment controller觀測到有新的Deployment被創建時,如果沒有已存在的ReplicaSet來創建期望個數的Pod的話,就會創建一個新的ReplicaSet來做這件事。如果更新了Deployment,則控制其標簽的Pods的現有ReplicaSet匹配.spec.selector但是template跟.spec.tmplate不匹配的Pod縮容。最終,新的ReplicaSet將會擴容出.spec.replicas
指定數目的Pod,舊的Replica Set會縮容到0。
如果你更新了一個的已存在並正在進行中的Deployment,每次更新Deployment都會創建一個新的Replica Set並擴容它,同時回滾之前擴容的Replica Set——將它添加到舊的Replica Set列表,開始縮容。
例如,假設創建一個 Deployment 以創建 nginx:1.7.9
的 5 個副本,然后更新 Deployment 以創建 5 個 nginx:1.9.1
的副本,而此時只有 3 個nginx:1.7.9
的副本已創建。在這種情況下, Deployment 會立即開始殺死3個 nginx:1.7.9
Pods,並開始創建 nginx:1.9.1
Pods。它不等待 nginx:1.7.9
的 5 個副本創建完畢再更新新的副本。
使用標簽選擇器進行更新
通常不鼓勵更新標簽選擇器,建議提前規划選擇器。在任何情況下,如果需要執行標簽選擇器更新,請格外小心,並確保已掌握所有的含義。
注意: 在 API 版本 apps/v1 中, Deployment 標簽選擇器在創建后是不可變的。
- 選擇器添加還需要使用新標簽更新 Deployment 規范中的 Pod 模板標簽,否則將返回驗證錯誤。此更改是非重疊的,這意味着新的選擇器不選擇使用舊選擇器創建的 ReplicaSets 和 Pod,從而導致棄用所有舊 ReplicaSets 和創建新的 ReplicaSet 。
- 選擇器更新更改選擇器鍵中的現有值 – 導致發生與添加相同的行為。
- 選擇器刪除從 Deployment 選擇器中刪除現有密鑰 – 不需要在Pod 模板標簽做任意更改。現有 ReplicaSets 不會孤立,並且不會創建新的 ReplicaSet ,但請注意,已刪除的標簽仍然存在於任何現有的 Pods 和 ReplicaSets 中。
回滾Deployment
有時,可能需要回滾 Deployment ;例如,當 Deployment 不穩定時,例如循環崩潰。
默認情況下,kubernetes會在系統中保存前兩次的Deployment的rollout歷史記錄,以便你可以隨時會退(你可以修改revision history limit
來更改保存的revision數)
注意: 只要Deployment的rollout被觸發就會創建一個revision。也就是說當且僅當Deployment的Pod template(如.spec.template)被更改,例如更新template中的label和容器鏡像時,就會創建出一個新的revision。
其他的更新,比如擴容Deployment不會創建revision——因此我們可以很方便的手動或者自動擴容。
例如修改副本數由3修改成5再查看revision是沒有新的revision的
# kubectl rollout history deployment/nginx-deployment --record deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 1 <none>
假設我們在更新Deployment的時候犯了一個拼寫錯誤,將鏡像的名字寫成了nginx:1.91
,而正確的名字應該是nginx:1.9.1
:
# kubectl set image deployment/nginx-deployment nginx=nginx:1.91 --record deployment.apps/nginx-deployment image updated
Rollout將會卡住
# kubectl rollout status deployment nginx-deployment Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated...
按住Ctrl-C停止上面的rollout狀態監控。
查看ReplicaSet
# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-54f57cf6bf 3 3 3 5m20s nginx-deployment-84fdd4f88c 1 1 0 2m
查看創建的 Pod,看到由新 ReplicaSet 創建的 1 個 Pod 卡在鏡像拉取循環中。
# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-54f57cf6bf-67bhs 1/1 Running 0 6m1s nginx-deployment-54f57cf6bf-dgrw7 1/1 Running 0 6m43s nginx-deployment-54f57cf6bf-n5mjc 1/1 Running 0 6m43s nginx-deployment-84fdd4f88c-cmzw6 0/1 ImagePullBackOff 0 3m23s
注意,Deployment controller會自動停止壞的rollout,並停止擴容新的Replica Set。
獲取deploym描述信息
# kubectl describe deployment nginx-deployment Name: nginx-deployment Namespace: default CreationTimestamp: Fri, 20 Mar 2020 16:51:44 +0800 Labels: app=nginx Annotations: deployment.kubernetes.io/revision: 2 kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"app":"nginx"},"name":"nginx-deployment","namespace":"d... 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.91 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-54f57cf6bf (3/3 replicas created) NewReplicaSet: nginx-deployment-84fdd4f88c (1/1 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 9m34s deployment-controller Scaled up replica set nginx-deployment-54f57cf6bf to 3 Normal ScalingReplicaSet 8m52s deployment-controller Scaled up replica set nginx-deployment-54f57cf6bf to 5 Normal ScalingReplicaSet 6m45s deployment-controller Scaled down replica set nginx-deployment-54f57cf6bf to 3 Normal ScalingReplicaSet 6m14s deployment-controller Scaled up replica set nginx-deployment-84fdd4f88c to 1
為了修復這個問題,我們需要回退到穩定的Deployment revision。
檢查升級歷史記錄
注意:檢查歷史記錄需要在創建的Deployment的時候加了參數--record否則歷史記錄只記錄version號,記錄歷史命令為none
# kubectl rollout history deployment/nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 1 kubectl apply --filename=nginx-deployment.yaml --record=true 2 kubectl set image deployment/nginx-deployment nginx=nginx:1.91 --record=true
查看修改歷史的詳細信息,查看version為2的詳細信息
# kubectl rollout history deployment/nginx-deployment --revision=2 deployment.apps/nginx-deployment with revision #2 Pod Template: Labels: app=nginx pod-template-hash=84fdd4f88c Annotations: kubernetes.io/change-cause: kubectl set image deployment/nginx-deployment nginx=nginx:1.91 --record=true Containers: nginx: Image: nginx:1.91 Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none>
回滾到上一次的修改
# 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
檢查回滾是否成功Deployment是否正常運行
# kubectl get deployment nginx-deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 8m19s
獲取Deployment描述信息
# kubectl describe deployment nginx-deployment Name: nginx-deployment Namespace: default CreationTimestamp: Fri, 20 Mar 2020 17:07:51 +0800 Labels: app=nginx Annotations: deployment.kubernetes.io/revision: 5 kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"kubernetes.io/change-cause":"kubectl apply --filename=nginx-deploy... kubernetes.io/change-cause: kubectl apply --filename=nginx-deployment.yaml --record=true 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.7.9 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-54f57cf6bf (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 9m25s deployment-controller Scaled up replica set nginx-deployment-54f57cf6bf to 3 Normal ScalingReplicaSet 3m49s (x2 over 9m17s) deployment-controller Scaled up replica set nginx-deployment-84fdd4f88c to 1 Normal ScalingReplicaSet 2m35s (x2 over 5m54s) deployment-controller Scaled down replica set nginx-deployment-84fdd4f88c to 0
你可以通過設置.spec.revisonHistoryLimit
項來指定deployment最多保留多少revison歷史記錄。默認的保留2次revision;如果將該項設置為0,Deployment就不允許回退了。
縮放Deployment
可以使用如下指令縮放 Deployment
# kubectl scale deployment/nginx-deployment --replicas=10 deployment.apps/nginx-deployment scaled
假設你的集群中啟用了horizontal pod autoscaling,你可以給Deployment設置一個autoscaler,基於當前Pod的CPU利用率選擇最少和最多的Pod數。
kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80
比例縮放
RollingUpdate Deployment支持同時運行一個應用的多個版本。當你活着autoscaler擴容RollingUpdate Deployment的時候,正在中途的rollout(進行中或者已經暫停的),為了降低風險,Deployment controller將會平衡已存在的活動中的ReplicaSets(有Pod的ReplicaSets)和新加入的replicas。這被稱為比例擴容。
例如,你真在運行的10個ReplicaSet的Deployment 。maxSurge=3,maxUnavailable=2即最多增加為3 最大不可用為2
maxSurge和maxUnavailable默認百分百為25% 可以編輯修改如此例副本數為10則maxSurge修改為30% maxUnavailable修改為20%
查看Deployment包含10個ReplicaSet修改參數以后maxSurge=3,maxUnavailable=2。
# kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 10/10 10 10 17m
更新了一個鏡像,而在集群內部無法解析
# kubectl set image deploy/nginx-deployment nginx=ngina:sametag deployment.apps/nginx-deployment image updated
鏡像更新啟動了一個包含ReplicaSet 名稱為nginx-deployment-55866c9bf7的rollout,但是它被阻塞了,因為前面提到的maxUnavailable最大不可用為2最大增加maxSurge為3所以新的ReplicaSet有5個Pod阻塞了
# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-54f57cf6bf 8 8 8 18m nginx-deployment-55866c9bf7 5 5 0 14m
查看Pod
然后發起了一個新的Deployment擴容請求。autoscaler將Deployment的repllica數目增加到了15個。Deployment controller需要判斷在哪里增加這5個新的replica。如果我們沒有用比例擴容,所有的5個replica都會加到一個新的ReplicaSet中。如果使用比例擴容,新添加的replica將傳播到所有的ReplicaSet中。大的部分加入replica數最多的ReplicaSet中,小的部分加入到replica數少的ReplciaSet中。0個replica的ReplicaSet不會被擴容。
# kubectl scale --replicas=15 deploy/nginx-deployment deployment.apps/nginx-deployment scaled
在該例中有4個replica加入到舊ReplicaSet中新的ReplicaSet有3個
# kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 12/15 8 12 29m [root@localhost deployment]# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-54f57cf6bf 12 12 12 29m nginx-deployment-55866c9bf7 8 8 0 25m
通過Pod的運行時間可以區分加入新舊ReplicaSet的副本數
暫停和恢復Deployment
可以在觸發一個或多個更新之前暫停 Deployment ,然后繼續它。這允許在暫停和恢復之間應用多個修補程序,而不會觸發不必要的rollout。
例如對於一個剛剛創建的Deployment獲取Deployment信息
# kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 3s
獲取rs
# kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-54f57cf6bf 3 3 3 35s
使用以下命令暫停Deployment
# kubectl rollout pause deploy/nginx-deployment deployment.apps/nginx-deployment paused
更新鏡像
# kubectl set image deploy/nginx-deployment nginx=nginx:1.9.1 deployment.apps/nginx-deployment image updated
查看rollout沒有記錄
# kubectl rollout history deploy/nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 1 <none>
恢復Deployment
# kubectl rollout resume deploy/nginx-deployment deployment.apps/nginx-deployment resumed
注意: 暫停的 Deployment 不可以回滾,除非恢復它以后。
暫停的Deployment管理的Pod功能正常運行
Deployment狀態
Deployment在生命周期中有多種狀態。在創建一個新的ReplicaSet的時候它可以是 progressing 狀態, complete 狀態,或者fail to progress狀態。
Progressing Deployment
Kubernetes將執行過下列任務之一的Deployment標記為progressing狀態:
- Deployment正在創建新的ReplicaSet過程中。
- Deployment正在擴容一個已有的ReplicaSet。
- Deployment正在縮容一個已有的ReplicaSet。
- 有新的可用的pod出現。
你可以使用kubectl roullout status
命令監控Deployment的進度。
Complete Deployment
Kubernetes將包括以下特性的Deployment標記為complete狀態:
- Deployment最小可用。最小可用意味着Deployment的可用replica個數等於或者超過Deployment策略中的期望個數。
- 所有與該Deployment相關的replica都被更新到了你指定版本,也就說更新完成。
- 該Deployment中沒有舊的Pod存在。
你可以用kubectl rollout status
命令查看Deployment是否完成。如果rollout成功完成,kubectl rollout status
將返回一個0值的Exit Code。
# kubectl rollout status deploy/nginx-deployment deployment "nginx-deployment" successfully rolled out [root@localhost deployment]# echo $? 0
Failed Deployment
- 無效的引用
- 不可讀的probe failure
- 鏡像拉取錯誤
- 權限不夠
- 范圍限制
- 程序運行時配置錯誤
探測這種情況的一種方式是,在你的Deployment spec中指定spec.progressDeadlineSeconds
。spec.progressDeadlineSeconds
表示Deployment controller等待多少秒才能確定(通過Deployment status)Deployment進程是卡住的。
下面的kubectl
命令設置progressDeadlineSeconds
使controller在Deployment在進度卡住10分鍾后報告:
# kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
PS:默認的參數值就是600秒,可以使用以下命令查看
kubectl edit deploy/nginx-deployment
超過截止時間后, Deployment 控制器將添加具有以下屬性到 Deployment 的 .status.conditions
:
- Type=Progressing
- Status=False
- Reason=ProgressDeadlineExceeded
注意: kubernetes除了報告Reason=ProgressDeadlineExceeded狀態信息外不會對卡住的Deployment做任何操作。更高層次的協調器可以利用它並采取相應行動,例如,回滾Deployment到之前的版本。 注意: 如果你暫停了一個Deployment,在暫停的這段時間內kubernetnes不會檢查你指定的deadline。你可以在Deployment的rollout途中安全的暫停它,然后再恢復它,這不會觸發超過deadline的狀態。
清理策略
可以在 Deployment 中設置 .spec.revisionHistoryLimit
,以指定保留多少此 Deployment 的 ReplicaSets。其余的將在后台進行垃圾回收。默認情況下,是10。
注意: 將該值設置為0,將導致所有的Deployment歷史記錄都會被清除,該Deploynent就無法再回退了。
編寫Deployment腳本
在所有的Kubernetes配置中,Deployment也需要apiVersion
,kind
和metadata
這些配置項。
Pod Template
.spec僅需要.spec.template和.spec.selector.
.spec.template是 pod template. 它跟 Pod有一模一樣的schema,除了它是嵌套的並且不需要apiVersion
和 kind
字段。
另外為了划分Pod的范圍,Deployment中的pod template必須指定適當的label(不要跟其他controller重復了)和適當的重啟策略。
.spec.template.spec.restartPolicy
可以設置為 Always
, 如果不指定的話這就是默認配置。
Replicas
.spec.replicas是可選字段,指定期望的副本即Pod數量,默認是1。
Selector
.spec.selector
是可選字段,用來指定 label selector ,圈定Deployment管理的pod范圍。
如果被指定, .spec.selector
必須匹配 .spec.template.metadata.labels
,否則它將被API拒絕。
在 API apps/v1
版本中,.spec.selector
和 .metadata.labels
不會被默認設置為 .spec.template.metadata.labels
,如果沒有設置的話。所以需要明確進行設置。同時在 apps/v1
版本中, Deployment 創建后 .spec.selector
是可變的
如下所示需要匹配
在Pod的template跟.spec.template
不同或者數量超過了.spec.replicas
規定的數量的情況下,Deployment會殺掉label跟selector不同的Pod。
注意: 不應創建其標簽與此選擇器匹配的 Pods,或者直接創建另一個 Deployment ,或通過創建其他控制器(如 ReplicaSet 或復制控制器)。如果這樣做,第一個 Deployment 認為它創建了這些其他 Pods。Kubernetes 不會阻止你這么做。
如果有多個具有重疊選擇器的控制器,則控制器之間會因沖突而故障。
策略
.spec.strategy
指定新的Pod替換舊的Pod的策略。 .spec.strategy.type
可以是”Recreate”或者是 “RollingUpdate”。”RollingUpdate”是默認值。
Recreate Deployment
.spec.strategy.type==Recreate
時,在創建出新的Pod之前會先殺掉所有已存在的Pod。
Rolling Update Deployment
.spec.strategy.type==RollingUpdate
時,Deployment使用rolling update 的方式更新Pod 。你可以指定maxUnavailable
和maxSurge
來控制 rolling update 進程。
Max Unavailable
.spec.strategy.rollingUpdate.maxUnavailable
是可選配置項,用來指定在升級過程中不可用Pod的最大數量。該值可以是一個絕對值(例如5),也可以是期望Pod數量的百分比(例如10%)。通過計算百分比的絕對值向下取整。如果.spec.strategy.rollingUpdate.maxSurge
為0時,這個值不可以為0。默認值是1。
例如,該值設置成30%,啟動rolling update后舊的ReplicatSet將會立即縮容到期望的Pod數量的70%。新的Pod ready后,隨着新的ReplicaSet的擴容,舊的ReplicaSet會進一步縮容,確保在升級的所有時刻可以用的Pod數量至少是期望Pod數量的70%。
Max Surge
.spec.strategy.rollingUpdate.maxSurge
是可選配置項,用來指定可以超過期望的Pod數量的最大個數。該值可以是一個絕對值(例如5)或者是期望的Pod數量的百分比(例如10%)。當MaxUnavailable
為0時該值不可以為0。通過百分比計算的絕對值向上取整。默認值是1。
例如,該值設置成30%,啟動rolling update后新的ReplicatSet將會立即擴容,新老Pod的總數不能超過期望的Pod數量的130%。舊的Pod被殺掉后,新的ReplicaSet將繼續擴容,舊的ReplicaSet會進一步縮容,確保在升級的所有時刻所有的Pod數量和不會超過期望Pod數量的130%。
Progress Deadline Seconds
.spec.progressDeadlineSeconds
是可選配置項,用來指定在系統報告Deployment的failed progressing ——表現為resource的狀態中type=Progressing
、Status=False
、 Reason=ProgressDeadlineExceeded
前可以等待的Deployment進行的秒數。Deployment controller會繼續重試該Deployment。未來,在實現了自動回滾后, deployment controller在觀察到這種狀態時就會自動回滾。
如果設置該參數,該值必須大於 .spec.minReadySeconds
。
Min Ready Seconds
.spec.minReadySeconds
是一個可選配置項,用來指定沒有任何容器crash的Pod並被認為是可用狀態的最小秒數。默認是0(Pod在ready后就會被認為是可用狀態)。進一步了解什么什么后Pod會被認為是ready狀態。
Rollback To
.spec.rollbackTo
是一個可以選配置項,用來配置Deployment回退的配置。設置該參數將觸發回退操作,每次回退完成后,該值就會被清除。
Revision
.spec.rollbackTo.revision
是一個可選配置項,用來指定回退到的revision。默認是0,意味着回退到歷史中最老的revision。
Revision History Limit
Deployment revision history存儲在它控制的ReplicaSets中。
.spec.revisionHistoryLimit
是一個可選配置項,用來指定可以保留的舊的ReplicaSet數量。該理想值取決於心Deployment的頻率和穩定性。如果該值沒有設置的話,默認所有舊的Replicaset或會被保留,將資源存儲在etcd中,是用kubectl get rs
查看輸出。每個Deployment的該配置都保存在ReplicaSet中,然而,一旦你刪除的舊的RepelicaSet,你的Deployment就無法再回退到那個revison了。
如果你將該值設置為0,所有具有0個replica的ReplicaSet都會被刪除。在這種情況下,新的Deployment rollout無法撤銷,因為revision history都被清理掉了。
Paused
.spec.paused
是可以可選配置項,boolean值。用來指定暫停和恢復Deployment。Paused和沒有paused的Deployment之間的唯一區別就是,所有對paused deployment中的PodTemplateSpec的修改都不會觸發新的rollout。Deployment被創建之后默認是非paused。
Deployment的替代方案
Kubectl rolling update 雖然使用類似的方式更新Pod和ReplicationController。但是我們推薦使用Deployment,因為它是聲明式的,客戶端側,具有附加特性,例如即使滾動升級結束后也可以回滾到任何歷史版本。