摘要:基於 Pod 爲單位能更加合理進行容器編排,然而 Pod 只是個啓動了一個或一組容器的資源類型,在實際應用中,我們也需要 Pod 能實現動態擴展與收縮、滾動更新等,但 Pod 本身是沒有辦法做到的,它需要依賴上層的一種控制來達到這樣的效果,這就涉及到 Kubernetes 中的控制器(Controller)模型知識,本文將注意介紹 Deployment 這個最基本的控制器對象。Deployment 控制器根據修改後的 Pod 模板,創建新的 ReplicaSet( k8sdemo-deployment-68cb864ff6 ),Pod 數默認是 0,然後老的 ReplicaSet ( k8sdemo-deployment-84d777fb7 )Pod 數逐漸減少,新的 ReplicaSet 的 Pod 數逐漸增加,兩個過程交替進行,新的增加一個,老的減少一個,直到全部升級完成。

在上篇文章 .NET Core + Kubernetes:Pod 中,主要介紹了 Pod 的相關內容,

基於 Pod 爲單位能更加合理進行容器編排,然而 Pod 只是個啓動了一個或一組容器的資源類型,在實際應用中,我們也需要 Pod 能實現動態擴展與收縮、滾動更新等,但 Pod 本身是沒有辦法做到的,它需要依賴上層的一種控制來達到這樣的效果,這就涉及到 Kubernetes 中的控制器(Controller)模型知識,本文將注意介紹 Deployment 這個最基本的控制器對象。

我們繼續以 .NET Core + Kubernetes:快速體驗 文中配置爲例,將以下配置保存爲 k8sdemo-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8sdemo-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      name: k8sdemo
  template:
    metadata:
      labels:
        name: k8sdemo
    spec:
      containers:
      - name: k8sdemo
        image: beckjin/k8sdemo:1.0.0
        ports:
        - containerPort: 80
        imagePullPolicy: IfNotPresent

這個 Deployment 指定創建 2 個含 name=k8sdemo 標籤的 Pod,template 字段指定了 Pod 的模板。從表面上來看,Deployment 和 Pod 是直接關係,然而實際上在 Deployment 與 Pod 直接還有 ReplicaSet 一層。如下:

Deployment 實際上一個兩層控制器,Deployment 控制 ReplicaSet,ReplicaSet 控制 Pod。ReplicaSet 有版本區分,滾動更新的能力就是基於 ReplicaSet 的版本來實現,下文會介紹。

通過以下命令創建 k8sdemo-deployment

kubectl apply -f k8sdemo-deployment.yaml

查看 k8sdemo-deployment 的狀態信息:

kubectl get deployments

輸出結果中含3個狀態字段,含義如下:

  • READY:當前處於 Running 狀態的 Pod 的個數/用戶期望的 Pod 個數( 配置文件設置的 replicas );
  • UP-TO-DATE:當前處於最新版本的 Pod 個數( Pod 的 Spec 部分與 Deployment 裏 Pod 模板裏定義的完全一致 ),在滾動更新過程中會有不一致的階段;
  • AVAILABLE:當前可用的 Pod 個數。

查看 k8sdemo-deployment 所控制的 ReplicaSet 信息:

kubectl describe replicaset

如上圖,Deployment 創建後,Deployment 控制器就會立即創建一個 Pod 個數爲 2 的 ReplicaSet,ReplicaSet 的名字是由 Deployment 名字 + 隨機字符串 ,Pod 的名字是由 ReplicaSet 名字 + 隨機字符串

動態伸縮

要實現 Pod 的伸縮只需要調整配置文件中的 replicas 字段,如擴展爲 3 個,擴展完成後結果如下:

收縮則類似。

滾動更新

假設現在將鏡像 beckjin/k8sdemo:1.0.0 升級爲 beckjin/k8sdemo:1.1.0 ,重新 apply 後並查看 Deployment 的 Events 信息,輸出內容含 “滾動更新” 的整個流程。

kubectl describe deployment k8sdemo-deployment

Deployment 控制器根據修改後的 Pod 模板,創建新的 ReplicaSet( k8sdemo-deployment-68cb864ff6 ),Pod 數默認是 0,然後老的 ReplicaSet ( k8sdemo-deployment-84d777fb7 )Pod 數逐漸減少,新的 ReplicaSet 的 Pod 數逐漸增加,兩個過程交替進行,新的增加一個,老的減少一個,直到全部升級完成。

查看當前 ReplicaSet 的狀態:

可以看出原來的 ReplicaSet 的 Pod 已經縮減爲 0 個,新的 ReplicaSet 的 Pod 擴展爲 3 個,每次配置修改重新部署都可能創建一個新的 ReplicaSet,所以 Deployment、ReplicaSet 和 Pod 的關係圖可擴展如下:

回滾

通過上文的介紹,已經瞭解應用版本與 ReplicaSet 具有一一對應關係,所以如果要回滾版本其實就是使原來的 ReplicaSet 重新擴展 Pod,當前的 ReplicaSet 收縮至 0 個 Pod。

通過 kubectl rollout history 命令查看每次 Deployment 變更對應的版本。

kubectl rollout history deployment/k8sdemo-deployment

由於在創建 Deployment 沒有加 –record 參數,所以 CHANGE-CAUSE 都是 none

現在如果需要回滾到版本 1,執行以下命令:

kubectl rollout undo deployment/k8sdemo-deployment --to-revision=1

這時 Deployment 控制器還是按 “滾動更新” 的方式,完成對 k8sdemo-deployment 的回滾操作。

故障轉移

故障轉移主要是指當集羣中某個節點掛了,Pod 會自動轉移到其他健康的節點上。當前的 Pod 分佈情況如下:

可以看出 node1 上分配了 2 個 Pod,node2 分配了 1 個 Pod,接下來將 node1 強制關機,然後當 Kubernetes 檢測到 node1 不可用時,node1 上的 Pod 會變成 Terminating 狀態,並在 node2 上新建,維持可用 Pod 總數不變。

當 node1 恢復後,Terminating 狀態的 Pod 會被自動刪除,不過已經轉移到 node2 的 Pod 是不會被重新調度回 node1 的。

相關文章