Kubernetes筆記(六):瞭解控制器 —— Deployment

【雨歌】發表於2020-11-19

Pod(容器組)是 Kubernetes 中最小的排程單元,可以通過 yaml 定義檔案直接建立一個 Pod。但 Pod 本身並不具備自我恢復(self-healing)功能。如果一個 Pod 所在的節點出現故障,或者排程程式自身出現問題,以及節點資源不夠或節點進入維護而驅逐 Pod 時,Pod 將被刪除,且不能自我恢復。

因此,Kubernetes 中我們一般不直接建立 Pod, 而是通過 Controller(控制器)來管理 Pod。

Controller

Controller 能為 Pod 提供如下特性:

  • 水平擴充套件,控制 Pod 執行的副本數
  • rollout,即版本更新
  • self-healing,即自我恢復。當節點出現故障時,控制器可以自動地在另一個節點排程一個配置完全一樣的 Pod,以替換故障節點上的 Pod。

Kubernetes 中支援的控制器包括:

  • ReplicationController:用來維護一個數量穩定的 Pod 副本集合的控制器
  • ReplicaSet:是 ReplicationController 的升級版,比 ReplicationController 多一個特性:支援基於集合的選擇器。 不支援滾動更新(RollingUpdate)
  • Deployment:包含了 ReplicaSet,可通過宣告式、滾動更新的方式更新 ReplicaSet 及其 Pod。對於無狀態應用,推薦使用 Deployment 部署
  • StatefulSet:用於管理有狀態的應用程式
  • DaemonSet:在節點上以守護程式的方式執行一個指定的 Pod 副本,例如監控節點、收集節點上的日誌時,可使用 DaemonSet
  • CronJob:按照預定的時間計劃建立 Job,類似於 linux 的crontab
  • Job:使用 Job 執行任務,執行完後結束

ReplicaSet

Kubernetes 中,雖然一般使用 Deployment 來管理 Pod, 但 Deployment 中也是通過 ReplicaSet 來維護 Pod 的副本集合的,因此此處也對 ReplicaSet 進行簡單介紹。

在 ReplicaSet 的定義中,包含三部分:

  1. selector: 標籤選擇器,用於指定哪些 Pod 歸該 ReplicaSet 管理,通過 matchLabels 來與 Pod 的 label 匹配。
  2. replicas: 期望的 Pod 副本數,指定該 ReplicaSet 應該維持多少個 Pod 副本,預設為1。
  3. template: Pod 定義模板,ReplicaSet 使用該模板的定義來建立 Pod。

ReplicaSet 的示例定義文件如下所示,

apiVersion: apps/v1  # api版本
kind: ReplicaSet     # 資源型別
metadata:            # 後設資料定義
  name: nginx-ds     # ReplicaSet 名稱
spec:
  replicas: 2        # Pod 副本數量,預設1
  selector:          # 標籤選擇器
     matchLabels:
      app: nginx
  template:          # Pod 定義模板
    metadata:        # Pod 後設資料定義
      labels:
        app: nginx   # Pod 標籤
    spec:
      containers:    # 容器定義
      - name: nginx
        image: nginx

ReplicaSet 通過建立、刪除 Pod 容器組來確保符合 selector 選擇器的 Pod 數量等於 replicas 指定的數量。 ReplicaSet 建立的 Pod 中,都有一個欄位 metadata.ownerReferences 用於標識該 Pod 從屬於哪一個 ReplicaSet。可通過 kubectl get pod pod-name -o yaml 來檢視 Pod 的 ownerReference。

ReplicaSet 通過 selector 欄位的定義,識別哪些 Pod 應該由其管理, 不論該 Pod 是否由該 ReplicaSet 建立,即只要 selector 匹配, 通過外部定義建立的 Pod 也會被該 ReplicaSet 管理。因此需要注意 .spec.selector.matchLabels.spec.template.metadata.labels 的定義一致, 且避免與其他控制器的 selector 重合,造成混亂。

ReplicaSet 不支援滾動更新,所以對於無狀態應用,一般使用 Deployment來部署, 而不直接使用 ReplicaSet。ReplicaSet 主要是被用作 Deployment 中負責 Pod 建立、刪除、更新的一種手段。

Deployment

Deployment 物件包含 ReplicaSet 作為從屬物件,並且可通過宣告式、滾動更新的方式來更新 ReplicaSet 及其 Pod。ReplicaSet 現在主要是被用作 Deployment 中負責 Pod 建立、刪除、更新的一種手段。使用 Deployment 時,無需關心由 Deployment 建立的 ReplicaSet,Deployment 將處理所有與之相關的細節。同時,Deployment 還能以“宣告式”的方式管理 Pod 和 ReplicaSet (其本質是將一些特定場景的一系列運維步驟固化下來,以便快速準確無誤的執行),並提供版本(revision)回退功能。

Deployment 定義示例,

apiVersion: apps/v1
kind: Deployment        # 物件型別,固定為 Deployment
metadata:
  name: nginx-deploy    # Deployment 名稱
  namespace: default    # 名稱空間,預設為 default
  labels:
    app: nginx          # 標籤
spec:
  replicas: 4           # Pod 副本數,預設1
  strategy:  
    rollingUpdate:      # 升級策略為滾動升級,由於replicas為4,則整個升級過程pod個數在3-5個之間
      maxSurge: 1       # 滾動升級時超過 replicas 的最大 pod 數,也可以為百分比(replicas的百分比),預設為1
      maxUnavailable: 1 # 滾動升級時不可用的最大 pod 數,也可為百分比(replicas的百分比),預設為1
  selector:             # 標籤選擇器,通過標籤選擇該 Deployment 管理的 Pod
    matchLabels:
      app: nginx
  template:             # Pod 定義模板
    metadata:
      labels:
        app: nginx      # Pod 標籤
    spec:               # 定義容器模板,可以包含多個容器
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

可通過 kubectl explain xxx 來檢視支援哪些配置選項,

# 檢視 deployment 配置項
[root@kmaster ~]# kubectl explain deployment
...

# 檢視 deployment.spec 模組的配置項
[root@kmaster ~]# kubectl explain deployment.spec
KIND:     Deployment
VERSION:  apps/v1

RESOURCE: spec <Object>

DESCRIPTION:
     Specification of the desired behavior of the Deployment.

     DeploymentSpec is the specification of the desired behavior of the
     Deployment.

FIELDS:
   minReadySeconds	<integer>
     Minimum number of seconds for which a newly created pod should be ready
     without any of its container crashing, for it to be considered available.
     Defaults to 0 (pod will be considered available as soon as it is ready)

   paused	<boolean>
     Indicates that the deployment is paused.

   progressDeadlineSeconds	<integer>
     The maximum time in seconds for a deployment to make progress before it is
     considered to be failed. The deployment controller will continue to process
     failed deployments and a condition with a ProgressDeadlineExceeded reason
     will be surfaced in the deployment status. Note that progress will not be
     estimated during the time a deployment is paused. Defaults to 600s.

   replicas	<integer>
     Number of desired pods. This is a pointer to distinguish between explicit
     zero and not specified. Defaults to 1.

   revisionHistoryLimit	<integer>
     The number of old ReplicaSets to retain to allow rollback. This is a
     pointer to distinguish between explicit zero and not specified. Defaults to
     10.

   selector	<Object> -required-
     Label selector for pods. Existing ReplicaSets whose pods are selected by
     this will be the ones affected by this deployment. It must match the pod
     template's labels.

   strategy	<Object>
     The deployment strategy to use to replace existing pods with new ones.

   template	<Object> -required-

其它配置項說明:

  • .spec.minReadySeconds:用來控制應用升級的速度。升級過程中,新建立的 Pod 一旦成功響應了就緒探測即被認為是可用狀態,然後進行下一輪的替換。 .spec.minReadySeconds 定義了在新的 Pod 物件建立後至少需要等待多長的時間才能會被認為其就緒,在該段時間內,更新操作會被阻塞。
  • .spec.progressDeadlineSeconds:用來指定在系統報告 Deployment 失敗 —— 表現為狀態中的 type=Progressing、Status=False、 Reason=ProgressDeadlineExceeded 前可以等待的 Deployment 進行的秒數。Deployment controller 會繼續重試該 Deployment。如果設定該引數,該值必須大於 .spec.minReadySeconds
  • .spec.revisionHistoryLimit:用來指定可以保留的舊的 ReplicaSet 或 revision(版本) 的數量。預設所有舊的 Replicaset 都會被保留。如果刪除了一箇舊的 RepelicaSet,則 Deployment 將無法再回退到那個 revison。如果將該值設定為0,所有具有0個 Pod 副本的 ReplicaSet 都會被刪除,這時候 Deployment 將無法回退,因為 revision history 都被清理掉了。

1. 建立

[root@kmaster test]# kubectl apply -f nginx-deploy.yaml --record

--record 會將此次命令寫入 Deployment 的 kubernetes.io/change-cause 註解中。可在後面檢視某一個 Deployment 版本變化的原因。

2. 檢視

建立 Deployment 後,Deployment 控制器將立刻建立一個 ReplicaSet,並由 ReplicaSet 建立所需要的 Pod。

# 檢視 Deployment
[root@kmaster test]# kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   0/2     2            0           64s

# 檢視 ReplicaSet
[root@kmaster test]# kubectl get rs
NAME                     DESIRED   CURRENT   READY   AGE
nginx-deploy-59c9f8dff   2         2         1       2m16s

# 檢視 Pod,顯示排程的節點,及標籤
[root@kmaster test]# kubectl get pod -o wide --show-labels
NAME                           READY   STATUS      RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES   LABELS
nginx-deploy-59c9f8dff-47bgd   1/1     Running     0          5m14s   10.244.1.91   knode2   <none>           <none>            app=nginx,pod-template-hash=59c9f8dff
nginx-deploy-59c9f8dff-q4zb8   1/1     Running     0          5m14s   10.244.3.47   knode3   <none>           <none>            app=nginx,pod-template-hash=59c9f8dff

pod-template-hash 標籤是 Deployment 建立 ReplicaSet 時新增到 ReplicaSet 上的,ReplicaSet 進而將此標籤新增到 Pod 上。這個標籤用於區分 Deployment 中哪個 ReplicaSet 建立了哪些 Pod。該標籤的值是 .spec.template 的 hash 值,不要去修改這個標籤。由上可看出 ReplicaSet、 Pod 的命名分別遵循 <Deployment-name>-<Pod-template-hash><Deployment-name>-<Pod-template-hash>-xxx 的格式。

3. 釋出更新(rollout)

當且僅當 Deployment 的 Pod template(.spec.template)欄位中的內容發生變更時(例如標籤或容器的映象被改變),Deployment 的釋出更新(rollout)才會被觸發。Deployment 中其他欄位的變化(例如修改 .spec.replicas 欄位)將不會觸發 Deployment 的釋出更新。

更新 Deployment 中 Pod 的定義(例如,釋出新版本的容器映象)。此時 Deployment 控制器將為該 Deployment 建立一個新的 ReplicaSet,並且逐步在新的 ReplicaSet 中建立 Pod,在舊的 ReplicaSet 中刪除 Pod,以達到滾動更新的效果。

比如我們將上面 Deployment 的容器映象進行修改,

# 方式一:直接使用 kubectl 命令設定修改 
[root@kmaster ~]# kubectl set image deploy nginx-deploy nginx=nginx:1.16.1 --record
deployment.apps/nginx-deploy image updated

# 方式二:使用 kubectl edit 編輯yaml修改
[root@kmaster ~]# kubectl edit deploy nginx-deploy

檢視釋出更新(rollout)的狀態

[root@kmaster ~]# kubectl rollout status deploy nginx-deploy
Waiting for deployment "nginx-deploy" rollout to finish: 2 out of 4 new replicas have been updated...

檢視 ReplicaSet,

[root@kmaster ~]# kubectl get rs
NAME                     DESIRED   CURRENT   READY   AGE
nginx-deploy-59c9f8dff   1         1         1       3d6h
nginx-deploy-d47dbbb7c   4         4         2       3m41s

我們可以看到 Deployment 的更新是通過建立一個新的4個副本的 ReplicaSet,並同時將舊的 ReplicaSet 的副本數縮容到0個副本來達成的。

因為前面我們將 maxSurge, 與 maxUnavailable 都設定為了1, 因此在更新的過程中,任何時刻兩個 ReplicaSet 的 Pod 數至多為5個(4 replicas +1 maxSurge),且可用的 Pod 數至少為3個(4 replicas - 1 maxUnavailable)。

使用 kubectl describe 命令檢視 Deployment 的事件部分,如下所示

[root@kmaster ~]# kubectl describe deploy nginx-deploy
...

Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  12m    deployment-controller  Scaled up replica set nginx-deploy-d47dbbb7c to 1
  Normal  ScalingReplicaSet  12m    deployment-controller  Scaled down replica set nginx-deploy-59c9f8dff to 3
  Normal  ScalingReplicaSet  12m    deployment-controller  Scaled up replica set nginx-deploy-d47dbbb7c to 2
  Normal  ScalingReplicaSet  10m    deployment-controller  Scaled down replica set nginx-deploy-59c9f8dff to 2
  Normal  ScalingReplicaSet  10m    deployment-controller  Scaled up replica set nginx-deploy-d47dbbb7c to 3
  Normal  ScalingReplicaSet  8m56s  deployment-controller  Scaled down replica set nginx-deploy-59c9f8dff to 1
  Normal  ScalingReplicaSet  8m56s  deployment-controller  Scaled up replica set nginx-deploy-d47dbbb7c to 4
  Normal  ScalingReplicaSet  5m55s  deployment-controller  Scaled down replica set nginx-deploy-59c9f8dff to 0

當更新了 Deployment 的 Pod Template 時,Deployment Controller 會建立一個新的 ReplicaSet (nginx-deploy-d47dbbb7c) ,並將其 scale up 到 1 個副本,同時將舊的 ReplicaSet(nginx-deploy-59c9f8dff) scale down 到3個副本。接下來 Deployment Controller 繼續 scale up 新的 ReplicaSet 並 scale down 舊的 ReplicaSet,直到新的 ReplicaSet 擁有 replicas 個數的 Pod, 舊的 ReplicaSet Pod 數縮放到0。這個過程稱為 rollout(釋出更新)。

通過 .spec.strategy 欄位,可以指定更新策略,除了上述使用的 RollingUpdate(滾動更新),另一個可取的值為 Recreate(重新建立)。選擇重新建立,Deployment 將先刪除原有 ReplicaSet 中的所有 Pod,然後再建立新的 ReplicaSet 和新的 Pod,更新過程中將出現一段應用程式不可用的情況。因此,線上環境一般使用 RollingUpdate。

4. 回滾

預設情況下,kubernetes 將儲存 Deployment 的所有更新(rollout)歷史。可以通過設定 revision history limit(.spec.revisionHistoryLimit 配置項)來指定儲存的歷史版本數量。

當且僅當 Deployment 的 .spec.template 欄位被修改時(例如修改容器的映象),kubernetes 才為其建立一個 Deployment revision(版本)。Deployment 的其他更新(例如:修改 .spec.replicas 欄位)將不會建立新的 Deployment revision(版本)。

檢視 Deployment 的 revision,

[root@kmaster ~]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=nginx-deploy.yaml --record=true
2         kubectl set image deploy nginx-deploy nginx=nginx:1.16.1 --record=true

如果前面更新 Deployment 時沒有新增 --record=true,則此處 CHANGE-CAUSE 將為空。

我們通過將映象修改為一個不存在的版本來模擬一次失敗的更新,並回滾到前一個版本的場景,

# 1. 修改映象版本到一個不存在的值
[root@kmaster ~]# kubectl set image deploy nginx-deploy nginx=nginx:1.161 --record
deployment.apps/nginx-deploy image updated

# 2. 檢視 ReplicaSet
[root@kmaster ~]# kubectl  get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-58f69cfc57   2         2         0       2m7s
nginx-deploy-59c9f8dff    0         0         0       3d7h
nginx-deploy-d47dbbb7c    3         3         3       81m

# 3. 檢視 Pod 狀態
[root@kmaster ~]# kubect get pod
NAME                            READY   STATUS              RESTARTS   AGE
nginx-deploy-58f69cfc57-5968g   0/1     ContainerCreating   0          42s
nginx-deploy-58f69cfc57-tk7c5   0/1     ErrImagePull        0          42s
nginx-deploy-d47dbbb7c-2chgx    1/1     Running             0          77m
nginx-deploy-d47dbbb7c-8fcb9    1/1     Running             0          80m
nginx-deploy-d47dbbb7c-gnwjj    1/1     Running             0          78m

# 4. 檢視 Deployment 詳情
[root@kmaster ~]# kubectl describe deploy nginx-deploy
...
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  3m57s  deployment-controller  Scaled up replica set nginx-deploy-58f69cfc57 to 1
  Normal  ScalingReplicaSet  3m57s  deployment-controller  Scaled down replica set nginx-deploy-d47dbbb7c to 3
  Normal  ScalingReplicaSet  3m57s  deployment-controller  Scaled up replica set nginx-deploy-58f69cfc57 to 2

# 5. 檢視 Deployment 的歷史版本
[root@kmaster ~]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=nginx-deploy.yaml --record=true
2         kubectl set image deploy nginx-deploy nginx=nginx:1.16.1 --record=true
3         kubectl set image deploy nginx-deploy nginx=nginx:1.161 --record=true

# 6. 檢視某個版本的詳情
[root@kmaster ~]# kubectl rollout history deploy nginx-deploy --revision=3
deployment.apps/nginx-deploy with revision #3
Pod Template:
  Labels:	app=nginx
	pod-template-hash=58f69cfc57
  Annotations:	kubernetes.io/change-cause: kubectl set image deploy nginx-deploy nginx=nginx:1.161 --record=true
  Containers:
   nginx:
    Image:	nginx:1.161
    Port:	80/TCP
    Host Port:	0/TCP
    Environment:	<none>
    Mounts:	<none>
  Volumes:	<none>

# 7. 回滾到前一個版本
[root@kmaster ~]# kubectl rollout undo deploy nginx-deploy
deployment.apps/nginx-deploy rolled back

# 8. 回滾到指定的版本
[root@kmaster ~]# kubectl rollout undo deploy nginx-deploy --to-revision=1
deployment.apps/nginx-deploy rolled back

# 9. 檢視歷史版本資訊
[root@kmaster ~]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy 
REVISION  CHANGE-CAUSE
3         kubectl set image deploy nginx-deploy nginx=nginx:1.161 --record=true
4         kubectl set image deploy nginx-deploy nginx=nginx:1.16.1 --record=true
5         kubectl apply --filename=nginx-deploy.yaml --record=true

通過 kubectl rollout undo 命令可回滾到上一個版本或指定的版本,上述示例也可看出,回滾到歷史版本,會將歷史版本的序號設定為最新序號。如前所述,我們可以通過設定 Deployment 的 .spec.revisionHistoryLimit 來指定保留多少箇舊的 ReplicaSet(或 revision),超出該數字的將在後臺進行垃圾回收。如果該欄位被設為 0,Kubernetes 將清理掉該 Deployment 的所有歷史版本(revision),此時,將無法對該 Deployment 執行回滾操作了。

5. 伸縮

可以通過 kubectl scale 命令或 kubectl edit 修改定義的方式來對 Deployment 進行伸縮,增加或減少 Pod 的副本數,

# 將 Pod 數縮放到2個
[root@kmaster ~]# kubectl scale deploy nginx-deploy --replicas=2
deployment.apps/nginx-deploy scaled

# 檢視 Pod
[root@kmaster ~]# kubectl  get pod
NAME                           READY   STATUS        RESTARTS   AGE
nginx-deploy-59c9f8dff-7bpjp   1/1     Running       0          9m48s
nginx-deploy-59c9f8dff-tpxzf   0/1     Terminating   0          8m57s
nginx-deploy-59c9f8dff-v8fgz   0/1     Terminating   0          10m
nginx-deploy-59c9f8dff-w8s9z   1/1     Running       0          10m

# 檢視 ReplicaSet,DESIRED 變為2了
[root@kmaster ~]# kubectl get rs
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-58f69cfc57   0         0         0       22m
nginx-deploy-59c9f8dff    2         2         2       3d8h
nginx-deploy-d47dbbb7c    0         0         0       102m

6. 自動伸縮(HPA)

如果叢集啟用了自動伸縮(HPA —— Horizontal Pod Autoscaling),則可以基於 CPU、 記憶體的使用率在一個最大和最小的區間對 Deployment 實現自動伸縮,

# 建立一個 HPA
[root@kmaster ~]# kubectl autoscale deploy nginx-deploy --min=2 --max=4 --cpu-percent=80
horizontalpodautoscaler.autoscaling/nginx-deploy autoscaled

# 檢視 HPA
[root@kmaster ~]# kubectl get hpa
NAME           REFERENCE                 TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
nginx-deploy   Deployment/nginx-deploy   <unknown>/80%   2         4         2          16s

# 刪除 HPA
[root@kmaster ~]# kubectl delete hpa nginx-deploy
horizontalpodautoscaler.autoscaling "nginx-deploy" deleted

7. 暫停與恢復

我們可以將一個 Deployment 暫停(pause),然後在它上面做一個或多個更新,此時 Deployment 並不會觸發更新,只有再恢復(resume)該 Deployment,才會執行該時間段內的所有更新。這種做法可以在暫停和恢復中間對 Deployment 做多次更新,而不會觸發不必要的滾動更新。

# 1. 暫停 Deployment
[root@kmaster ~]# kubectl rollout pause deploy nginx-deploy
deployment.apps/nginx-deploy paused

# 2. 更新容器映象
[root@kmaster ~]# kubectl set image deploy nginx-deploy nginx=nginx:1.9.1 --record
deployment.apps/nginx-deploy image updated

# 3. 檢視版本歷史, 此時並沒有觸發更新
[root@kmaster ~]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy 
REVISION  CHANGE-CAUSE
3         kubectl set image deploy nginx-deploy nginx=nginx:1.161 --record=true
4         kubectl set image deploy nginx-deploy nginx=nginx:1.16.1 --record=true
5         kubectl apply --filename=nginx-deploy.yaml --record=true

# 4. 更新 Resource 限制,同樣並不會觸發更新
[root@kmaster ~]# kubectl set resources deploy nginx-deploy -c=nginx --limits=memory=512Mi,cpu=500m
deployment.apps/nginx-deploy resource requirements updated


# 5. 檢視修改,Pod 定義已被更新
[root@kmaster ~]# kubectl describe deploy nginx-deploy
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:      nginx:1.9.1
    Port:       80/TCP
    Host Port:  0/TCP
    Limits:
      cpu:        500m
      memory:     512Mi

# 6. 恢復 Deployment
[root@kmaster ~]# kubectl rollout resume deploy nginx-deploy
deployment.apps/nginx-deploy resumed


# 7. 檢視版本歷史,可見兩次修改只做了一次 rollout
[root@kmaster ~]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy
REVISION  CHANGE-CAUSE
3         kubectl set image deploy nginx-deploy nginx=nginx:1.161 --record=true
4         kubectl set image deploy nginx-deploy nginx=nginx:1.16.1 --record=true
5         kubectl apply --filename=nginx-deploy.yaml --record=true
6         kubectl set image deploy nginx-deploy nginx=nginx:1.9.1 --record=true

在更新容器映象時,因為 Deployment 處於暫停狀態,所以並不會生成新的版本(Revision),當 Deployment 恢復時,才將這段時間的更新生效,執行滾動更新,生成新的版本。在暫停中的 Deployment 上做的更新, 因為沒有生成版本,因此也不能回滾(rollback)。也不能對處於暫停狀態的 Deployment 執行回滾操作,只有在恢復(Resume)之後才能執行回滾操作。

8. 金絲雀釋出

金絲雀釋出也叫灰度釋出。當我們需要釋出新版本時,可以針對新版本新建一個 Deployment,與舊版本的 Deployment 同時掛在一個 Service 下(通過 label match), 通過 Service 的負載均衡將使用者請求流量分發到新版 Deployment 的 Pod 上,觀察新版執行情況,如果沒有問題再將舊版 Deployment 的版本更新到新版完成滾動更新,最後刪除新建的 Deployment。很明顯這種金絲雀釋出具有一定的侷限性,無法根據使用者或地域來分流,如果要更充分地實現金絲雀釋出,則可能需要引入 Istio 等。

金絲雀釋出名稱的由來: 以前,曠工在下礦洞時面臨的一個重要危險是礦井中的毒氣,他們想到一個辦法來辨別礦井中是否有毒氣,礦工們隨身攜帶一隻金絲雀下礦井,金絲雀對毒氣的抵抗能力比人類要弱,在毒氣環境下會先掛掉從而起到預警的作用。它背後的原理是:用較小的代價試錯,即使出現了嚴重的錯誤(出現了毒氣),系統總體的損失也是可承受的或者是非常小的(失去了一隻金絲雀)。

總結

Kubernetes 中最小的排程單元是 Pod, 負載建立 Pod 並控制其按一定的副本數執行的是 ReplicaSet, 而 Deployment 可以以“宣告式”的方式來管理 Pod 和 ReplicaSet,並提供滾動更新與版本(revision)回退功能。所以,一般使用 Deployment 來部署應用, 而不直接操作 ReplicaSet 或 Pod。


[轉載請註明出處]
作者:雨歌
歡迎關注作者公眾號:半路雨歌,檢視更多技術乾貨文章
qrcode

相關文章