Kubernetes 資源對象


概述

我將它們簡單的分類為以下幾種資源對象:

類別 名稱
資源對象 Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaling、Node、Namespace、Service、Ingress、Label、CustomResourceDefinition
存儲對象 Volume、PersistentVolume、Secret、ConfigMap
策略對象 SecurityContext、ResourceQuota、LimitRange
身份對象 ServiceAccount、Role、ClusterRole

必需字段

在想要創建的 Kubernetes 對象對應的 .yaml 文件中,需要配置如下的字段:

  • apiVersion - 創建該對象所使用的 Kubernetes API 的版本
  • kind - 想要創建的對象的類型
  • metadata - 幫助識別對象唯一性的數據,包括一個 name 字符串、UID 和可選的 namespace

也需要提供對象的 spec 字段。對象 spec 的精確格式對每個 Kubernetes 對象來說是不同的,包含了特定於該對象的嵌套字段。Kubernetes API 參考能夠幫助我們找到任何我們想創建的對象的 spec 格式。

ReplicaSet

Kubernetes 中的 ReplicaSet 主要的作用是維持一組 Pod 副本的運行,它的主要作用就是保證一定數量的 Pod 能夠在集群中正常運行,它會持續監聽這些 Pod 的運行狀態,在 Pod 發生故障重啟數量減少時重新運行新的 Pod 副本。

這篇文章會介紹 ReplicaSet 的工作原理,其中包括在 Kubernetes 中是如何被創建的、如何創建並持有 Pod 並在出現問題時重啟它們。

在具體介紹 ReplicaSet 的實現原理之前,我們還是會先簡單介紹它的使用,與其他的 Kubernetes 對象一樣,我們會在 Kubernetes 集群中使用 YAML 文件創建新的 ReplicaSet 對象,一個常見的 ReplicaSet 的定義其實是這樣的:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3

這里的 YAML 文件除了常見的 apiVersionkindmetadata 屬性之外,規格中總共包含三部分重要內容,也就是 Pod 副本數目 replicas、選擇器 selector 和 Pod 模板 template,這三個部分共同定義了 ReplicaSet 的規格:

kubernetes-replicaset-spe

同一個 ReplicaSet 會使用選擇器 selector 中的定義查找集群中自己持有的 Pod 對象,它們會根據標簽的匹配獲取能夠獲得的 Pod,下面就是持有三個 Pod 對象的 Replica 拓撲圖:

被 ReplicaSet 持有的 Pod 有一個 metadata.ownerReferences 指針指向當前的 ReplicaSet,表示當前 Pod 的所有者,這個引用主要會被集群中的 垃圾收集器 使用以清理失去所有者的 Pod 對象。

實現原理

所有 ReplicaSet 對象的增刪改查都是由 ReplicaSetController 控制器完成的,該控制器會通過 Informer 監聽 ReplicaSet 和 Pod 的變更事件並將其加入持有的待處理隊列:

ReplicaSetController 中的 queue 其實就是一個存儲待處理 ReplicaSet 的『對象池』,它運行的幾個 Goroutine 會從隊列中取出最新的數據進行處理,上圖展示了事件從發生到被處理的流向,我們接下來將分別介紹 ReplicaSet 中常見的同步過程。

Deployment

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

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

比如一個簡單的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

擴容:

kubectl scale deployment nginx-deployment --replicas 10

如果集群支持 horizontal pod autoscaling 的話,還可以為Deployment設置自動擴展:

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

更新鏡像也比較簡單:

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

回滾:

kubectl rollout undo deployment/nginx-deployment

更新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。

回退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

該 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除了報告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,kubernetes 會更新狀態和導致 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=AvailableStatus=True 意味着您的Deployment有最小可用性。 最小可用性是在Deployment策略中指定的參數。Type=ProgressingStatus=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 就無法再回退了。

參考:

資源對象與基本概念解析

深入解析 kubernetes 資源管理,容器雲牛人有話說

Kubernetes學習之路(十)之資源清單定義

詳解 Kubernetes ReplicaSet 的實現原理

Deployment


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM