Kubernetes的Deployment控制器使用

Kubernetes的Deployment控制器使用

Deployment簡述

Deployment 爲 Pod 和 ReplicaSet 提供了一個聲明式定義(declarative)方法,用來替代之前的ReplicationController 來方便的管理應用。典型的應用場景包括:html

  • 定義Deployment來建立Pod和ReplicaSet
  • 滾動升級和回滾應用
  • 擴容和縮容
  • 暫停和繼續Deployment

好比一個簡單的nginx應用能夠定義爲nginx

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

擴容:git

kubectl scale deployment nginx-deployment --replicas 10

若是集羣支持 horizontal pod autoscaling 的話,還能夠爲Deployment設置自動擴展:github

kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80

更新鏡像也比較簡單:api

kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

回滾:安全

kubectl rollout undo deployment/nginx-deployment

Deployment 結構示意圖

參考:https://kubernetes.io/docs/api-reference/v1.6/#deploymentspec-v1beta1-apps服務器

kubernetes deployment cheatsheet

圖片 - kubernetes deployment cheatsheetapp

Deployment 概念詳細解析

本文翻譯自kubernetes官方文檔:https://kubernetes.io/docs/concepts/workloads/controllers/deployment.mdless

根據2017年5月10日的Commit 8481c02 翻譯。ide

Deployment 是什麼?

Deployment爲Pod和Replica Set(下一代Replication Controller)提供聲明式更新。

您只須要在 Deployment 中描述您想要的目標狀態是什麼,Deployment controller 就會幫您將 Pod 和ReplicaSet 的實際狀態改變到您的目標狀態。您能夠定義一個全新的 Deployment 來建立 ReplicaSet 或者刪除已有的 Deployment 並建立一個新的來替換。

注意:您不應手動管理由 Deployment 建立的 ReplicaSet,不然您就篡越了 Deployment controller 的職責!下文羅列了 Deployment 對象中已經覆蓋了全部的用例。若是未有覆蓋您全部須要的用例,請直接在 Kubernetes 的代碼庫中提 issue。

典型的用例以下:

  • 使用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 來啓動3個 nginx pod。

下載示例文件並執行命令:

$ kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
deployment "nginx-deployment" created

將kubectl的 --record 的 flag 設置爲 true能夠在 annotation 中記錄當前命令建立或者升級了該資源。這在將來會頗有用,例如,查看在每一個 Deployment revision 中執行了哪些命令。

而後當即執行 get 將得到以下結果:

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         0         0            0           1s

輸出結果代表咱們但願的repalica數是3(根據deployment中的.spec.replicas配置)當前replica數( .status.replicas)是0, 最新的replica數(.status.updatedReplicas)是0,可用的replica數(.status.availableReplicas)是0。

過幾秒後再執行get命令,將得到以下輸出:

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           18s

咱們能夠看到Deployment已經建立了3個 replica,全部的 replica 都已是最新的了(包含最新的pod template),可用的(根據Deployment中的.spec.minReadySeconds聲明,處於已就緒狀態的pod的最少個數)。執行kubectl get rskubectl get pods會顯示Replica Set(RS)和Pod已建立。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-2035384211   3         3         0       18s

您可能會注意到 ReplicaSet 的名字老是<Deployment的名字>-<pod template的hash值>

$ kubectl get pods --show-labels
NAME                                READY     STATUS    RESTARTS   AGE       LABELS
nginx-deployment-2035384211-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=2035384211

剛建立的Replica Set將保證老是有3個 nginx 的 pod 存在。

注意: 您必須在 Deployment 中的 selector 指定正確的 pod template label(在該示例中是 app = nginx),不要跟其餘的 controller 的 selector 中指定的 pod template label 搞混了(包括 Deployment、Replica Set、Replication Controller 等)。Kubernetes 自己並不會阻止您任意指定 pod template label,可是若是您真的這麼作了,這些 controller 之間會相互打架,並可能致使不正確的行爲。

Pod-template-hash label

注意:這個 label 不是用戶指定的!

注意上面示例輸出中的 pod label 裏的 pod-template-hash label。當 Deployment 建立或者接管 ReplicaSet 時,Deployment controller 會自動爲 Pod 添加 pod-template-hash label。這樣作的目的是防止 Deployment 的子ReplicaSet 的 pod 名字重複。經過將 ReplicaSet 的 PodTemplate 進行哈希散列,使用生成的哈希值做爲 label 的值,並添加到 ReplicaSet selector 裏、 pod template label 和 ReplicaSet 管理中的 Pod 上。

更新Deployment

注意: Deployment 的 rollout 當且僅當 Deployment 的 pod template(例如.spec.template)中的label更新或者鏡像更改時被觸發。其餘更新,例如擴容Deployment不會觸發 rollout。

假如咱們如今想要讓 nginx pod 使用nginx:1.9.1的鏡像來代替原來的nginx:1.7.9的鏡像。

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

咱們可使用edit命令來編輯 Deployment,修改 .spec.template.spec.containers[0].image ,將nginx:1.7.9 改寫成 nginx:1.9.1

$ kubectl edit deployment/nginx-deployment
deployment "nginx-deployment" edited

查看 rollout 的狀態,只要執行:

$ 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

Rollout 成功後,get Deployment:

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           36s

UP-TO-DATE 的 replica 的數目已經達到了配置中要求的數目。

CURRENT 的 replica 數表示 Deployment 管理的 replica 數量,AVAILABLE 的 replica 數是當前可用的replica數量。

咱們經過執行kubectl get rs能夠看到 Deployment 更新了Pod,經過建立一個新的 ReplicaSet 並擴容了3個 replica,同時將原來的 ReplicaSet 縮容到了0個 replica。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1564180365   3         3         0       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 的 template 便可。

Deployment 能夠保證在升級時只有必定數量的 Pod 是 down 的。默認的,它會確保至少有比指望的Pod數量少一個是up狀態(最多一個不可用)。

Deployment 同時也能夠確保只建立出超過時望數量的必定數量的 Pod。默認的,它會確保最多比指望的Pod數量多一個的 Pod 是 up 的(最多1個 surge )。

在將來的 Kuberentes 版本中,將從1-1變成25%-25%。

例如,若是您本身看下上面的 Deployment,您會發現,開始建立一個新的 Pod,而後刪除一些舊的 Pod 再建立一個新的。當新的Pod建立出來以前不會殺掉舊的Pod。這樣可以確保可用的 Pod 數量至少有2個,Pod的總數最多4個。

$ kubectl describe deployments
Name:           nginx-deployment
Namespace:      default
CreationTimestamp:  Tue, 15 Mar 2016 12:01:06 -0700
Labels:         app=nginx
Selector:       app=nginx
Replicas:       3 updated | 3 total | 3 available | 0 unavailable
StrategyType:       RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
OldReplicaSets:     <none>
NewReplicaSet:      nginx-deployment-1564180365 (3/3 replicas created)
Events:
  FirstSeen LastSeen    Count   From                     SubobjectPath   Type        Reason              Message
  --------- --------    -----   ----                     -------------   --------    ------              -------
  36s       36s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
  23s       23s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
  23s       23s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
  23s       23s         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 0
  21s       21s         1       {deployment-controller }                 Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3

咱們能夠看到當咱們剛開始建立這個 Deployment 的時候,建立了一個 ReplicaSet(nginx-deployment-2035384211),並直接擴容到了3個 replica。

當咱們更新這個 Deployment 的時候,它會建立一個新的 ReplicaSet(nginx-deployment-1564180365),將它擴容到1個replica,而後縮容原先的 ReplicaSet 到2個 replica,此時知足至少2個 Pod 是可用狀態,同一時刻最多有4個 Pod 處於建立的狀態。

接着繼續使用相同的 rolling update 策略擴容新的 ReplicaSet 和縮容舊的 ReplicaSet。最終,將會在新的 ReplicaSet 中有3個可用的 replica,舊的 ReplicaSet 的 replica 數目變成0。

Rollover(多個rollout並行)

每當 Deployment controller 觀測到有新的 deployment 被建立時,若是沒有已存在的 ReplicaSet 來建立指望個數的 Pod 的話,就會建立出一個新的 ReplicaSet 來作這件事。已存在的 ReplicaSet 控制 label 與.spec.selector匹配可是 template 跟.spec.template不匹配的 Pod 縮容。最終,新的 ReplicaSet 將會擴容出.spec.replicas指定數目的 Pod,舊的 ReplicaSet 會縮容到0。

若是您更新了一個的已存在並正在進行中的 Deployment,每次更新 Deployment都會建立一個新的 ReplicaSet並擴容它,同時回滾以前擴容的 ReplicaSet ——將它添加到舊的 ReplicaSet 列表中,開始縮容。

例如,假如您建立了一個有5個niginx:1.7.9 replica的 Deployment,可是當還只有3個nginx:1.7.9的 replica 建立出來的時候您就開始更新含有5個nginx:1.9.1 replica 的 Deployment。在這種狀況下,Deployment 會當即殺掉已建立的3個nginx:1.7.9的 Pod,並開始建立nginx:1.9.1的 Pod。它不會等到全部的5個nginx:1.7.9的 Pod 都建立完成後纔開始改變航道。

Label selector 更新

咱們一般不鼓勵更新 label selector,咱們建議事先規劃好您的 selector。

任何狀況下,只要您想要執行 label selector 的更新,請必定要謹慎並確認您已經預料到全部可能所以致使的後果。

  • 增添 selector 須要同時在 Deployment 的 spec 中更新新的 label,不然將返回校驗錯誤。此更改是不可覆蓋的,這意味着新的 selector 不會選擇使用舊 selector 建立的 ReplicaSet 和 Pod,從而致使全部舊版本的 ReplicaSet 都被丟棄,並建立新的 ReplicaSet。
  • 更新 selector,即更改 selector key 的當前值,將致使跟增添 selector 一樣的後果。
  • 刪除 selector,即刪除 Deployment selector 中的已有的 key,不須要對 Pod template label 作任何更改,現有的 ReplicaSet 也不會成爲孤兒,可是請注意,刪除的 label 仍然存在於現有的 Pod 和 ReplicaSet 中。

回退Deployment

有時候您可能想回退一個 Deployment,例如,當 Deployment 不穩定時,好比一直 crash looping。

默認狀況下,kubernetes 會在系統中保存前兩次的 Deployment 的 rollout 歷史記錄,以便您能夠隨時回退(您能夠修改revision history limit來更改保存的revision數)。

注意: 只要 Deployment 的 rollout 被觸發就會建立一個 revision。也就是說當且僅當 Deployment 的 Pod template(如.spec.template)被更改,例如更新template 中的 label 和容器鏡像時,就會建立出一個新的 revision。

其餘的更新,好比擴容 Deployment 不會建立 revision——所以咱們能夠很方便的手動或者自動擴容。這意味着當您回退到歷史 revision 時,只有 Deployment 中的 Pod template 部分纔會回退。

假設咱們在更新 Deployment 的時候犯了一個拼寫錯誤,將鏡像的名字寫成了nginx:1.91,而正確的名字應該是nginx:1.9.1

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.91
deployment "nginx-deployment" image updated

Rollout 將會卡住。

$ kubectl rollout status deployments nginx-deployment
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...

按住 Ctrl-C 中止上面的 rollout 狀態監控。

您會看到舊的 replica(nginx-deployment-1564180365 和 nginx-deployment-2035384211)和新的 replica (nginx-deployment-3066724191)數目都是2個。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-1564180365   2         2         0       25s
nginx-deployment-2035384211   0         0         0       36s
nginx-deployment-3066724191   2         2         2       6s

看下建立 Pod,您會看到有兩個新的 ReplicaSet 建立的 Pod 處於 ImagePullBackOff 狀態,循環拉取鏡像。

$ 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-3066724191-08mng   0/1       ImagePullBackOff   0          6s
nginx-deployment-3066724191-eocby   0/1       ImagePullBackOff   0          6s

注意,Deployment controller會自動中止壞的 rollout,並中止擴容新的 ReplicaSet。

$ kubectl describe deployment
Name:           nginx-deployment
Namespace:      default
CreationTimestamp:  Tue, 15 Mar 2016 14:48:04 -0700
Labels:         app=nginx
Selector:       app=nginx
Replicas:       2 updated | 3 total | 2 available | 2 unavailable
StrategyType:       RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
OldReplicaSets:     nginx-deployment-1564180365 (2/2 replicas created)
NewReplicaSet:      nginx-deployment-3066724191 (2/2 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 0
  21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-1564180365 to 2
  13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 2

爲了修復這個問題,咱們須要回退到穩定的 Deployment revision。

檢查 Deployment 升級的歷史記錄

首先,檢查下 Deployment 的 revision:

$ kubectl rollout history deployment/nginx-deployment
deployments "nginx-deployment":
REVISION    CHANGE-CAUSE
1           kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml--record
2           kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
3           kubectl set image deployment/nginx-deployment nginx=nginx:1.91

由於咱們建立 Deployment 的時候使用了--record參數能夠記錄命令,咱們能夠很方便的查看每次 revision 的變化。

查看單個revision 的詳細信息:

$ 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.9.1
  Containers:
   nginx:
    Image:      nginx:1.9.1
    Port:       80/TCP
     QoS Tier:
        cpu:      BestEffort
        memory:   BestEffort
    Environment Variables:      <none>
  No volumes.

回退到歷史版本

如今,咱們能夠決定回退當前的 rollout 到以前的版本:

$ kubectl rollout undo deployment/nginx-deployment
deployment "nginx-deployment" rolled back

也可使用 --revision參數指定某個歷史版本:

$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment "nginx-deployment" rolled back

與 rollout 相關的命令詳細文檔見kubectl rollout

該 Deployment 如今已經回退到了先前的穩定版本。如您所見,Deployment controller產生了一個回退到revison 2的DeploymentRollback的 event。

$ kubectl get deployment
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3         3         3            3           30m

$ 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 updated | 3 total | 3 available | 0 unavailable
StrategyType:       RollingUpdate
MinReadySeconds:    0
RollingUpdateStrategy:  1 max unavailable, 1 max surge
OldReplicaSets:     <none>
NewReplicaSet:      nginx-deployment-1564180365 (3/3 replicas created)
Events:
  FirstSeen LastSeen    Count   From                    SubobjectPath   Type        Reason              Message
  --------- --------    -----   ----                    -------------   --------    ------              -------
  30m       30m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 2
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 2
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
  29m       29m         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-1564180365 to 2
  2m        2m          1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-3066724191 to 0
  2m        2m          1       {deployment-controller }                Normal      DeploymentRollback  Rolled back deployment "nginx-deployment" to revision 2
  29m       2m          2       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3

清理 Policy

您能夠經過設置.spec.revisonHistoryLimit項來指定 deployment 最多保留多少 revision 歷史記錄。默認的會保留全部的 revision;若是將該項設置爲0,Deployment就不容許回退了。

Deployment 擴容

您可使用如下命令擴容 Deployment:

$ kubectl scale deployment nginx-deployment --replicas 10
deployment "nginx-deployment" scaled

假設您的集羣中啓用了horizontal pod autoscaling,您能夠給 Deployment 設置一個 autoscaler,基於當前 Pod的 CPU 利用率選擇最少和最多的 Pod 數。

$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
deployment "nginx-deployment" autoscaled

比例擴容

RollingUpdate Deployment 支持同時運行一個應用的多個版本。或者 autoscaler 擴 容 RollingUpdate Deployment 的時候,正在中途的 rollout(進行中或者已經暫停的),爲了下降風險,Deployment controller 將會平衡已存在的活動中的 ReplicaSet(有 Pod 的 ReplicaSet)和新加入的 replica。這被稱爲比例擴容。

例如,您正在運行中含有10個 replica 的 Deployment。maxSurge=3,maxUnavailable=2。

$ kubectl get deploy
NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     10        10        10           10          50s

您更新了一個鏡像,而在集羣內部沒法解析。

$ kubectl set image deploy/nginx-deployment nginx=nginx:sometag
deployment "nginx-deployment" image updated

鏡像更新啓動了一個包含ReplicaSet nginx-deployment-1989198191的新的rollout,可是它被阻塞了,由於咱們上面提到的maxUnavailable。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-1989198191   5         5         0         9s
nginx-deployment-618515232    8         8         8         1m

而後發起了一個新的Deployment擴容請求。autoscaler將Deployment的repllica數目增長到了15個。Deployment controller須要判斷在哪裏增長這5個新的replica。若是咱們沒有誰用比例擴容,全部的5個replica都會加到一個新的ReplicaSet中。若是使用比例擴容,新添加的replica將傳播到全部的ReplicaSet中。大的部分加入replica數最多的ReplicaSet中,小的部分加入到replica數少的ReplciaSet中。0個replica的ReplicaSet不會被擴容。

在咱們上面的例子中,3個replica將添加到舊的ReplicaSet中,2個replica將添加到新的ReplicaSet中。rollout進程最終會將全部的replica移動到新的ReplicaSet中,假設新的replica成爲健康狀態。

$ 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

暫停和恢復Deployment

您能夠在發出一次或屢次更新前暫停一個 Deployment,而後再恢復它。這樣您就能屢次暫停和恢復 Deployment,在此期間進行一些修復工做,而不會發出沒必要要的 rollout。

例如使用剛剛建立 Deployment:

$ kubectl get deploy
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     3         3         3            3           1m
[mkargaki@dhcp129-211 kubernetes]$ kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   3         3         3         1m

使用如下命令暫停 Deployment:

$ kubectl rollout pause deployment/nginx-deployment
deployment "nginx-deployment" paused

而後更新 Deplyment中的鏡像:

$ kubectl set image deploy/nginx nginx=nginx:1.9.1
deployment "nginx-deployment" image updated

注意新的 rollout 啓動了:

$ kubectl rollout history deploy/nginx
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 -c=nginx --limits=cpu=200m,memory=512Mi
deployment "nginx" resource requirements updated

Deployment 暫停前的初始狀態將繼續它的功能,而不會對 Deployment 的更新產生任何影響,只要 Deployment是暫停的。

最後,恢復這個 Deployment,觀察完成更新的 ReplicaSet 已經建立出來了:

$ kubectl rollout resume deploy nginx
deployment "nginx" resumed
$ KUBECTL get rs -w
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
^C
$ KUBECTL get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-2142116321   0         0         0         2m
nginx-3926361531   3         3         3         28s

注意: 在恢復 Deployment 以前您沒法回退一個已經暫停的 Deployment。

Deployment 狀態

Deployment 在生命週期中有多種狀態。在建立一個新的 ReplicaSet 的時候它能夠是 progressing 狀態, complete 狀態,或者 fail to progress 狀態。

進行中的 Deployment

Kubernetes 將執行過下列任務之一的 Deployment 標記爲 progressing 狀態:

  • Deployment 正在建立新的ReplicaSet過程當中。
  • Deployment 正在擴容一個已有的 ReplicaSet。
  • Deployment 正在縮容一個已有的 ReplicaSet。
  • 有新的可用的 pod 出現。

您可使用kubectl rollout status命令監控 Deployment 的進度。

完成的 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
Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx" successfully rolled out
$ echo $?
0

失敗的 Deployment

您的 Deployment 在嘗試部署新的 ReplicaSet 的時候可能卡住,永遠也不會完成。這多是由於如下幾個因素引發的:

  • 無效的引用
  • 不可讀的 probe failure
  • 鏡像拉取錯誤
  • 權限不夠
  • 範圍限制
  • 程序運行時配置錯誤

探測這種狀況的一種方式是,在您的 Deployment spec 中指定spec.progressDeadlineSecondsspec.progressDeadlineSeconds 表示 Deployment controller 等待多少秒才能肯定(經過 Deployment status)Deployment進程是卡住的。

下面的kubectl命令設置progressDeadlineSeconds 使 controller 在 Deployment 在進度卡住10分鐘後報告:

$ kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'
"nginx-deployment" patched

當超過截止時間後,Deployment controller 會在 Deployment 的 status.conditions中增長一條DeploymentCondition,它包括以下屬性:

  • Type=Progressing
  • Status=False
  • Reason=ProgressDeadlineExceeded

瀏覽 Kubernetes API conventions 查看關於status conditions的更多信息。

注意: kubernetes除了報告Reason=ProgressDeadlineExceeded狀態信息外不會對卡住的 Deployment 作任何操做。更高層次的協調器能夠利用它並採起相應行動,例如,回滾 Deployment 到以前的版本。

注意: 若是您暫停了一個 Deployment,在暫停的這段時間內kubernetnes不會檢查您指定的 deadline。您能夠在 Deployment 的 rollout 途中安全的暫停它,而後再恢復它,這不會觸發超過deadline的狀態。

您可能在使用 Deployment 的時候遇到一些短暫的錯誤,這些多是因爲您設置了過短的 timeout,也有多是由於各類其餘錯誤致使的短暫錯誤。例如,假設您使用了無效的引用。當您 Describe 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,Deployement 的狀態可能看起來像這個樣子:

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 進程的 deadline,kuberentes 會更新狀態和致使 Progressing 狀態的緣由:

Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     False   ProgressDeadlineExceeded
  ReplicaFailure  True    FailedCreate

您能夠經過縮容 Deployment的方式解決配額不足的問題,或者增長您的 namespace 的配額。若是您知足了配額條件後,Deployment controller 就會完成您的 Deployment rollout,您將看到 Deployment 的狀態更新爲成功狀態(Status=True而且Reason=NewReplicaSetAvailable)。

Conditions:
  Type          Status  Reason
  ----          ------  ------
  Available     True    MinimumReplicasAvailable
  Progressing   True    NewReplicaSetAvailable

Type=Available、 Status=True 覺得這您的Deployment有最小可用性。 最小可用性是在Deployment策略中指定的參數。Type=Progressing 、 Status=True意味着您的Deployment 或者在部署過程當中,或者已經成功部署,達到了指望的最少的可用replica數量(查看特定狀態的Reason——在咱們的例子中Reason=NewReplicaSetAvailable 意味着Deployment已經完成)。

您可使用kubectl rollout status命令查看Deployment進程是否失敗。當Deployment過程超過了deadline,kubectl rollout status將返回非0的exit code。

$ kubectl rollout status deploy/nginx
Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline
$ echo $?
1

操做失敗的 Deployment

全部對完成的 Deployment 的操做都適用於失敗的 Deployment。您能夠對它擴/縮容,回退到歷史版本,您甚至能夠屢次暫停它來應用 Deployment pod template。

清理Policy

您能夠設置 Deployment 中的 .spec.revisionHistoryLimit 項來指定保留多少舊的 ReplicaSet。 餘下的將在後臺被看成垃圾收集。默認的,全部的 revision 歷史就都會被保留。在將來的版本中,將會更改成2。

注意: 將該值設置爲0,將致使全部的 Deployment 歷史記錄都會被清除,該 Deployment 就沒法再回退了。

用例

金絲雀 Deployment

若是您想要使用 Deployment 對部分用戶或服務器發佈 release,您能夠建立多個 Deployment,每一個 Deployment 對應一個 release,參照 managing resources 中對金絲雀模式的描述。

編寫 Deployment Spec

在全部的 Kubernetes 配置中,Deployment 也須要apiVersionkindmetadata這些配置項。配置文件的通用使用說明查看 部署應用,配置容器,和 使用 kubectl 管理資源 文檔。

Deployment也須要 .spec section.

Pod Template

.spec.template 是 .spec中惟一要求的字段。

.spec.template 是 pod template. 它跟 Pod有如出一轍的schema,除了它是嵌套的而且不須要apiVersion 和 kind字段。

另外爲了劃分Pod的範圍,Deployment中的pod template必須指定適當的label(不要跟其餘controller重複了,參考selector)和適當的重啓策略。

.spec.template.spec.restartPolicy 能夠設置爲 Always , 若是不指定的話這就是默認配置。

Replicas

.spec.replicas 是能夠選字段,指按期望的pod數量,默認是1。

Selector

.spec.selector是可選字段,用來指定 label selector ,圈定Deployment管理的pod範圍。

若是被指定, .spec.selector 必須匹配 .spec.template.metadata.labels,不然它將被API拒絕。若是 .spec.selector 沒有被指定, .spec.selector.matchLabels 默認是 .spec.template.metadata.labels

在Pod的template跟.spec.template不一樣或者數量超過了.spec.replicas規定的數量的狀況下,Deployment會殺掉label跟selector不一樣的Pod。

注意: 您不該該再建立其餘label跟這個selector匹配的pod,或者經過其餘Deployment,或者經過其餘Controller,例如ReplicaSet和ReplicationController。不然該Deployment會被把它們當成都是本身建立的。Kubernetes不會阻止您這麼作。

若是您有多個controller使用了重複的selector,controller們就會互相打架並致使不正確的行爲。

策略

.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=ProgressingStatus=False、 Reason=ProgressDeadlineExceeded前能夠等待的Deployment進行的秒數。Deployment controller會繼續重試該Deployment。將來,在實現了自動回滾後, deployment controller在觀察到這種狀態時就會自動回滾。

若是設置該參數,該值必須大於 .spec.minReadySeconds

Min Ready Seconds

.spec.minReadySeconds是一個可選配置項,用來指定沒有任何容器crash的Pod並被認爲是可用狀態的最小秒數。默認是0(Pod在ready後就會被認爲是可用狀態)。進一步瞭解什麼什麼後Pod會被認爲是ready狀態,參閱 Container Probes

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

Kubectl rolling update 雖然使用相似的方式更新Pod和ReplicationController。可是咱們推薦使用Deployment,由於它是聲明式的,客戶端側,具備附加特性,例如即便滾動升級結束後也能夠回滾到任何歷史版本。

相關文章
相關標籤/搜索