部署

Deployment 管理一組 Pod,以執行應用程式工作負載,通常是不需要維護狀態的工作負載。

Deployment 為 PodReplicaSet 提供宣告式更新。

你在 Deployment 中描述一個**期望狀態**,Deployment 控制器 以受控速率將實際狀態更改為期望狀態。你可以定義 Deployment 以建立新的 ReplicaSet,或移除現有 Deployment 並使用新的 Deployment 採用所有其資源。

用例

以下是 Deployment 的典型用例:

建立 Deployment

下面是一個 Deployment 示例。它建立了一個 ReplicaSet 來啟動三個 `nginx` Pod。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

在此示例中:

  • 建立了一個名為 `nginx-deployment` 的 Deployment,由 `.metadata.name` 欄位指示。此名稱將成為稍後建立的 ReplicaSet 和 Pod 的基礎。有關更多詳細資訊,請參閱編寫 Deployment Spec

  • Deployment 建立了一個 ReplicaSet,該 ReplicaSet 建立三個複製的 Pod,由 `.spec.replicas` 欄位指示。

  • `.spec.selector` 欄位定義了建立的 ReplicaSet 如何找到要管理的 Pod。在本例中,你選擇 Pod 模板(`app: nginx`)中定義的標籤。但是,只要 Pod 模板本身滿足規則,就可以使用更復雜的選擇規則。

  • `.spec.template` 欄位包含以下子欄位:

    • 使用 `.metadata.labels` 欄位將 Pod 標記為 `app: nginx`。
    • Pod 模板的規約,即 `.spec` 欄位,指示 Pod 執行一個容器,名為 `nginx`,它執行 1.14.2 版本的 `nginx` Docker Hub 映象。
    • 使用 `.spec.containers[0].name` 欄位建立並命名一個容器為 `nginx`。

在開始之前,請確保你的 Kubernetes 叢集已啟動並正在執行。按照以下步驟建立上述 Deployment:

  1. 透過執行以下命令建立 Deployment:

    kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
    
  2. 執行 `kubectl get deployments` 以檢查 Deployment 是否已建立。

    如果 Deployment 仍在建立中,則輸出類似於以下內容:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   0/3     0            0           1s
    

    當你在叢集中檢查 Deployment 時,會顯示以下欄位:

    • `NAME` 列出了名稱空間中 Deployment 的名稱。
    • `READY` 顯示了應用程式有多少副本可供使用者使用。它遵循 ready/desired 模式。
    • `UP-TO-DATE` 顯示已更新到期望狀態的副本數量。
    • `AVAILABLE` 顯示了應用程式有多少副本可供使用者使用。
    • `AGE` 顯示應用程式已執行的時間。

    請注意,根據 `.spec.replicas` 欄位,期望的副本數量是 3。

  3. 要檢視 Deployment 的推出狀態,請執行 `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
    
  4. 幾秒鐘後再次執行 `kubectl get deployments`。輸出類似於:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           18s
    

    請注意,Deployment 已建立所有三個副本,並且所有副本都是最新的(它們包含最新的 Pod 模板)並且可用。

  5. 要檢視 Deployment 建立的 ReplicaSet (`rs`),請執行 `kubectl get rs`。輸出類似於:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-75675f5897   3         3         3       18s
    

    ReplicaSet 輸出顯示以下欄位:

    • `NAME` 列出名稱空間中 ReplicaSet 的名稱。
    • `DESIRED` 顯示應用程式期望的**副本**數量,這是你在建立 Deployment 時定義的。這是**期望狀態**。
    • `CURRENT` 顯示當前正在執行的副本數量。
    • `READY` 顯示應用程式有多少副本可供使用者使用。
    • `AGE` 顯示應用程式已執行的時間。

    請注意,ReplicaSet 的名稱總是格式化為 `[DEPLOYMENT-NAME]-[HASH]`。此名稱將成為建立 Pod 的基礎。

    `HASH` 字串與 ReplicaSet 上的 `pod-template-hash` 標籤相同。

  6. 要檢視為每個 Pod 自動生成的標籤,請執行 `kubectl get pods --show-labels`。輸出類似於:

    NAME                                READY     STATUS    RESTARTS   AGE       LABELS
    nginx-deployment-75675f5897-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    nginx-deployment-75675f5897-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    nginx-deployment-75675f5897-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    

    建立的 ReplicaSet 確保有三個 `nginx` Pod。

Pod 模板雜湊標籤

`pod-template-hash` 標籤由 Deployment 控制器新增到 Deployment 建立或採用的每個 ReplicaSet 中。

此標籤確保 Deployment 的子 ReplicaSet 不會重疊。它是透過對 ReplicaSet 的 `PodTemplate` 進行雜湊計算,並將生成的雜湊用作新增到 ReplicaSet 選擇器、Pod 模板標籤以及 ReplicaSet 可能具有的任何現有 Pod 中的標籤值來生成的。

更新 Deployment

按照以下步驟更新你的 Deployment:

  1. 讓我們將 nginx Pod 更新為使用 `nginx:1.16.1` 映象而不是 `nginx:1.14.2` 映象。

    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
    

    或者使用以下命令:

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

    其中 `deployment/nginx-deployment` 表示 Deployment,`nginx` 表示將進行更新的容器,`nginx:1.16.1` 表示新映象及其標籤。

    輸出類似於:

    deployment.apps/nginx-deployment image updated
    

    或者,你可以 `edit` Deployment 並將 `.spec.template.spec.containers[0].image` 從 `nginx:1.14.2` 更改為 `nginx:1.16.1`。

    kubectl edit deployment/nginx-deployment
    

    輸出類似於:

    deployment.apps/nginx-deployment edited
    
  2. 要檢視推出狀態,請執行:

    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
    

獲取關於更新後的 Deployment 的更多詳細資訊。

  • 推出成功後,你可以透過執行 `kubectl get deployments` 檢視 Deployment。輸出類似於:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           36s
    
  • 執行 `kubectl get rs` 檢視 Deployment 如何透過建立新的 ReplicaSet 並將其擴容到 3 個副本,以及將舊的 ReplicaSet 縮減到 0 個副本,來更新 Pod。

    kubectl get rs
    

    輸出類似於:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-1564180365   3         3         3       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 模板。

    Deployment 確保在更新期間只有一定數量的 Pod 下線。預設情況下,它確保至少 75% 的所需 Pod 處於活動狀態(最多 25% 不可用)。

    Deployment 還確保只建立一定數量的 Pod,超出所需 Pod 的數量。預設情況下,它確保最多 125% 的所需 Pod 處於活動狀態(最多 25% 突增)。

    例如,如果你仔細檢視上面的 Deployment,你會發現它首先建立一個新的 Pod,然後刪除一箇舊的 Pod,再建立另一個新的 Pod。它不會殺死舊的 Pod,直到足夠數量的新 Pod 出現,也不會建立新的 Pod,直到足夠數量的舊 Pod 被殺死。它確保至少 3 個 Pod 可用,並且總共有最多 4 個 Pod 可用。在具有 4 個副本的 Deployment 中,Pod 的數量將在 3 到 5 之間。

  • 獲取你的 Deployment 的詳細資訊。

    kubectl describe deployments
    

    輸出類似於:

    Name:                   nginx-deployment
    Namespace:              default
    CreationTimestamp:      Thu, 30 Nov 2017 10:56:25 +0000
    Labels:                 app=nginx
    Annotations:            deployment.kubernetes.io/revision=2
    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.16.1
          Port:         80/TCP
          Environment:  <none>
          Mounts:       <none>
        Volumes:        <none>
      Conditions:
        Type           Status  Reason
        ----           ------  ------
        Available      True    MinimumReplicasAvailable
        Progressing    True    NewReplicaSetAvailable
      OldReplicaSets:  <none>
      NewReplicaSet:   nginx-deployment-1564180365 (3/3 replicas created)
      Events:
        Type    Reason             Age   From                   Message
        ----    ------             ----  ----                   -------
        Normal  ScalingReplicaSet  2m    deployment-controller  Scaled up replica set nginx-deployment-2035384211 to 3
        Normal  ScalingReplicaSet  24s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 1
        Normal  ScalingReplicaSet  22s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 2
        Normal  ScalingReplicaSet  22s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 2
        Normal  ScalingReplicaSet  19s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 1
        Normal  ScalingReplicaSet  19s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 3
        Normal  ScalingReplicaSet  14s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 0
    

    在這裡,你看到當你第一次建立 Deployment 時,它建立了一個 ReplicaSet (nginx-deployment-2035384211) 並直接將其擴容到 3 個副本。當你更新 Deployment 時,它建立了一個新的 ReplicaSet (nginx-deployment-1564180365) 並將其擴容到 1 個,然後等待它啟動。然後它將舊的 ReplicaSet 縮減到 2,並將新的 ReplicaSet 擴容到 2,以便始終至少有 3 個 Pod 可用,並且最多建立 4 個 Pod。然後它繼續以相同的滾動更新策略對新舊 ReplicaSet 進行擴縮。最後,你將在新的 ReplicaSet 中擁有 3 個可用副本,並且舊的 ReplicaSet 將縮減到 0。

滾動(即飛行中的多次更新)

每當 Deployment 控制器觀察到新的 Deployment 時,就會建立一個 ReplicaSet 來啟動所需的 Pod。如果 Deployment 被更新,則控制 Pod 的現有 ReplicaSet(其標籤與 `.spec.selector` 匹配但其模板與 `.spec.template` 不匹配)將縮減。最終,新的 ReplicaSet 將擴容到 `.spec.replicas`,所有舊的 ReplicaSet 將縮減到 0。

如果你在現有推出正在進行時更新 Deployment,Deployment 會根據更新建立一個新的 ReplicaSet 並開始擴容,然後將之前正在擴容的 ReplicaSet 滾動更新——它會將其新增到舊 ReplicaSet 列表中並開始縮減。

例如,假設你建立了一個 Deployment 以建立 5 個 `nginx:1.14.2` 副本,但在只建立了 3 個 `nginx:1.14.2` 副本時更新了 Deployment 以建立 5 個 `nginx:1.16.1` 副本。在這種情況下,Deployment 立即開始殺死它已建立的 3 個 `nginx:1.14.2` Pod,並開始建立 `nginx:1.16.1` Pod。它不會等待 5 個 `nginx:1.14.2` 副本建立完畢再改變方向。

標籤選擇器更新

通常不鼓勵進行標籤選擇器更新,建議你預先規劃好選擇器。在任何情況下,如果你需要執行標籤選擇器更新,請務必謹慎並確保你已完全理解所有影響。

  • 選擇器新增需要 Deployment 規約中的 Pod 模板標籤也更新新標籤,否則將返回驗證錯誤。此更改是非重疊的,這意味著新選擇器不選擇使用舊選擇器建立的 ReplicaSet 和 Pod,導致所有舊 ReplicaSet 孤立並建立新的 ReplicaSet。
  • 選擇器更新更改選擇器鍵中的現有值——導致與新增相同的行為。
  • 選擇器刪除會從 Deployment 選擇器中移除現有鍵——不需要對 Pod 模板標籤進行任何更改。現有的 ReplicaSet 不會被孤立,也不會建立新的 ReplicaSet,但請注意,已移除的標籤仍然存在於任何現有 Pod 和 ReplicaSet 中。

回滾 Deployment

有時,你可能希望回滾 Deployment;例如,當 Deployment 不穩定(例如,崩潰迴圈)時。預設情況下,Deployment 的所有推出歷史記錄都保留在系統中,因此你可以隨時回滾(你可以透過修改修訂歷史限制來更改此設定)。

  • 假設你在更新 Deployment 時打錯了字,將映象名稱寫成 `nginx:1.161` 而不是 `nginx:1.16.1`。

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

    輸出類似於:

    deployment.apps/nginx-deployment image updated
    
  • 推出卡住了。你可以透過檢查推出狀態來驗證這一點:

    kubectl rollout status deployment/nginx-deployment
    

    輸出類似於:

    Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
    
  • 按 Ctrl-C 停止上述推出狀態監視。有關推出卡頓的更多資訊,請在此處閱讀

  • 你看到舊副本(`nginx-deployment-1564180365` 和 `nginx-deployment-2035384211` 的副本計數之和)的數量是 3,而新副本(來自 `nginx-deployment-3066724191`)的數量是 1。

    kubectl get rs
    

    輸出類似於:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-1564180365   3         3         3       25s
    nginx-deployment-2035384211   0         0         0       36s
    nginx-deployment-3066724191   1         1         0       6s
    
  • 檢視建立的 Pod,你看到由新的 ReplicaSet 建立的 1 個 Pod 停留在映象拉取迴圈中。

    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-1564180365-hysrc   1/1       Running            0          25s
    nginx-deployment-3066724191-08mng   0/1       ImagePullBackOff   0          6s
    
  • 獲取 Deployment 的描述。

    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 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.161
        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-1564180365 (3/3 replicas created)
    NewReplicaSet:      nginx-deployment-3066724191 (1/1 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 1
      21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
    

    要解決此問題,你需要回滾到穩定的 Deployment 的先前修訂版本。

檢查 Deployment 的推出歷史

按照以下步驟檢查推出歷史:

  1. 首先,檢查此 Deployment 的修訂版本:

    kubectl rollout history deployment/nginx-deployment
    

    輸出類似於:

    deployments "nginx-deployment"
    REVISION    CHANGE-CAUSE
    1           kubectl apply --filename=https://k8s.io/examples/controllers/nginx-deployment.yaml
    2           kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
    3           kubectl set image deployment/nginx-deployment nginx=nginx:1.161
    

    `CHANGE-CAUSE` 在建立時從 Deployment 註解 `kubernetes.io/change-cause` 複製到其修訂版本。你可以透過以下方式指定 `CHANGE-CAUSE` 訊息:

    • 使用 `kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1"` 為 Deployment 添加註解。
    • 手動編輯資源的清單。
  2. 要檢視每個修訂版本的詳細資訊,請執行:

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

回滾到先前修訂版本

按照以下步驟將 Deployment 從當前版本回滾到上一個版本,即版本 2。

  1. 現在你已決定撤銷當前的推出並回滾到上一個修訂版本。

    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
    

    有關推出相關命令的更多詳細資訊,請參閱 `kubectl rollout`

    Deployment 現在已回滾到以前的穩定修訂版本。如你所見,Deployment 控制器生成了一個 `DeploymentRollback` 事件,用於回滾到修訂版本 2。

  2. 檢查回滾是否成功以及 Deployment 是否按預期執行,執行:

    kubectl get deployment nginx-deployment
    

    輸出類似於:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           30m
    
  3. 獲取 Deployment 的描述。

    kubectl describe deployment nginx-deployment
    

    輸出類似於:

    Name:                   nginx-deployment
    Namespace:              default
    CreationTimestamp:      Sun, 02 Sep 2018 18:17:55 -0500
    Labels:                 app=nginx
    Annotations:            deployment.kubernetes.io/revision=4
                            kubernetes.io/change-cause=kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
    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.16.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-c4747d96c (3/3 replicas created)
    Events:
      Type    Reason              Age   From                   Message
      ----    ------              ----  ----                   -------
      Normal  ScalingReplicaSet   12m   deployment-controller  Scaled up replica set nginx-deployment-75675f5897 to 3
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 1
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 2
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 2
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 1
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 3
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 0
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-595696685f to 1
      Normal  DeploymentRollback  15s   deployment-controller  Rolled back deployment "nginx-deployment" to revision 2
      Normal  ScalingReplicaSet   15s   deployment-controller  Scaled down replica set nginx-deployment-595696685f to 0
    

擴充套件 Deployment

你可以使用以下命令擴充套件 Deployment:

kubectl scale deployment/nginx-deployment --replicas=10

輸出類似於:

deployment.apps/nginx-deployment scaled

假設你的叢集中啟用了水平 Pod 自動擴縮,你可以為你的 Deployment 設定一個自動擴縮器,並根據現有 Pod 的 CPU 利用率選擇你想要執行的最小和最大 Pod 數量。

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

輸出類似於:

deployment.apps/nginx-deployment scaled

按比例擴縮

滾動更新型 Deployment 支援同時執行應用程式的多個版本。當你或自動擴縮器擴縮一個處於推出中(正在進行或已暫停)的滾動更新型 Deployment 時,Deployment 控制器會在現有的活動 ReplicaSet(帶有 Pod 的 ReplicaSet)中平衡額外的副本,以減輕風險。這稱為**按比例擴縮**。

例如,你正在執行一個包含 10 個副本的 Deployment,maxSurge=3,maxUnavailable=2。

  • 確保你的 Deployment 中的 10 個副本正在執行。

    kubectl get deploy
    

    輸出類似於:

    NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment     10        10        10           10          50s
    
  • 你更新到新映象,但該映象無法從叢集內部解析。

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

    輸出類似於:

    deployment.apps/nginx-deployment image updated
    
  • 映象更新啟動了一個新的推出,ReplicaSet nginx-deployment-1989198191,但由於你上面提到的 `maxUnavailable` 要求,它被阻塞了。檢視推出狀態:

    kubectl get rs
    

    輸出類似於:

    NAME                          DESIRED   CURRENT   READY     AGE
    nginx-deployment-1989198191   5         5         0         9s
    nginx-deployment-618515232    8         8         8         1m
    
  • 然後,一個新的 Deployment 擴縮請求到來。自動擴縮器將 Deployment 副本增加到 15。Deployment 控制器需要決定將這 5 個新副本新增到哪裡。如果你不使用按比例擴縮,所有 5 個副本都將新增到新的 ReplicaSet 中。透過按比例擴縮,你將額外的副本分散到所有 ReplicaSet 中。較大比例分配給副本數量最多的 ReplicaSet,較小比例分配給副本數量較少的 ReplicaSet。任何剩餘的副本將新增到副本數量最多的 ReplicaSet 中。副本數量為零的 ReplicaSet 不會被擴容。

在上面的示例中,3 個副本被新增到舊的 ReplicaSet,2 個副本被新增到新的 ReplicaSet。推出過程最終應該將所有副本移動到新的 ReplicaSet,假設新的副本變得健康。要確認這一點,請執行:

kubectl get deploy

輸出類似於:

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     15        18        7            8           7m

推出狀態確認了副本是如何新增到每個 ReplicaSet 的。

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 的推出。當你準備好應用這些更改時,你將恢復 Deployment 的推出。這種方法允許你在暫停和恢復之間應用多個修復,而無需觸發不必要的推出。

  • 例如,對於已建立的 Deployment:

    獲取 Deployment 詳細資訊。

    kubectl get deploy
    

    輸出類似於:

    NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx     3         3         3            3           1m
    

    獲取推出狀態。

    kubectl get rs
    

    輸出類似於:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         1m
    
  • 透過執行以下命令暫停:

    kubectl rollout pause deployment/nginx-deployment
    

    輸出類似於:

    deployment.apps/nginx-deployment paused
    
  • 然後更新 Deployment 的映象:

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

    輸出類似於:

    deployment.apps/nginx-deployment image updated
    
  • 請注意,沒有新的推出啟動。

    kubectl rollout history deployment/nginx-deployment
    

    輸出類似於:

    deployments "nginx"
    REVISION  CHANGE-CAUSE
    1   <none>
    
  • 獲取推出狀態以驗證現有 ReplicaSet 未更改:

    kubectl get rs
    

    輸出類似於:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         2m
    
  • 你可以進行任意多次更新,例如,更新將使用的資源:

    kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
    

    輸出類似於:

    deployment.apps/nginx-deployment resource requirements updated
    

    Deployment 在暫停推出之前的初始狀態將繼續其功能,但只要 Deployment 推出處於暫停狀態,對 Deployment 的新更新將不會產生任何影響。

  • 最終,恢復 Deployment 推出並觀察到新的 ReplicaSet 出現,其中包含所有新更新。

    kubectl rollout resume deployment/nginx-deployment
    

    輸出類似於:

    deployment.apps/nginx-deployment resumed
    
  • 監視推出狀態,直到完成。

    kubectl get rs --watch
    

    輸出類似於:

    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
    
  • 獲取最新推出的狀態。

    kubectl get rs
    

    輸出類似於:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   0         0         0         2m
    nginx-3926361531   3         3         3         28s
    

Deployment 狀態

Deployment 在其生命週期中會進入各種狀態。它可能在推出新的 ReplicaSet 時處於進行中,可能處於完成狀態,也可能未能取得進展

正在進行的 Deployment

當執行以下任務之一時,Kubernetes 將 Deployment 標記為**進行中**:

  • Deployment 建立了一個新的 ReplicaSet。
  • Deployment 正在擴容其最新的 ReplicaSet。
  • Deployment 正在縮減其舊的 ReplicaSet。
  • 新的 Pod 變得就緒或可用(至少在 MinReadySeconds 期間就緒)。

當推出變為“進行中”時,Deployment 控制器會在 Deployment 的 `.status.conditions` 中新增一個具有以下屬性的條件:

  • type: Progressing
  • status: "True"
  • `reason: NewReplicaSetCreated` | `reason: FoundNewReplicaSet` | `reason: ReplicaSetUpdated`

你可以使用 `kubectl rollout status` 監視 Deployment 的進度。

完成的 Deployment

當 Deployment 具有以下特徵時,Kubernetes 會將其標記為**完成**:

  • 與 Deployment 相關聯的所有副本都已更新到你指定的最新版本,這意味著你請求的任何更新都已完成。
  • 與 Deployment 相關聯的所有副本都可用。
  • 沒有 Deployment 的舊副本正在執行。

當推出變為“完成”時,Deployment 控制器會在 Deployment 的 `.status.conditions` 中設定一個具有以下屬性的條件:

  • type: Progressing
  • status: "True"
  • reason: NewReplicaSetAvailable

此 `Progressing` 條件將保持 `“True”` 狀態值,直到啟動新的推出。即使副本的可用性發生變化(這會影響 `Available` 條件),該條件也保持不變。

你可以使用 `kubectl rollout status` 檢查 Deployment 是否已完成。如果推出成功完成,`kubectl rollout status` 將返回零退出程式碼。

kubectl rollout status deployment/nginx-deployment

輸出類似於:

Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out

並且來自 `kubectl rollout` 的退出狀態為 0(成功)

echo $?
0

失敗的 Deployment

你的 Deployment 可能會在嘗試部署其最新的 ReplicaSet 時卡住,而無法完成。這可能是由於以下一些因素造成的:

  • 配額不足
  • 就緒探針失敗
  • 映象拉取錯誤
  • 許可權不足
  • 限制範圍
  • 應用程式執行時配置錯誤

檢測此條件的一種方法是在 Deployment 規約中指定一個截止日期引數:(`.spec.progressDeadlineSeconds`)。`.spec.progressDeadlineSeconds` 表示 Deployment 控制器在指示(在 Deployment 狀態中)Deployment 進度已停滯之前等待的秒數。

以下 `kubectl` 命令將 spec 中的 `progressDeadlineSeconds` 設定為 10 分鐘,以便控制器在 10 分鐘後報告 Deployment 推出沒有進展:

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

輸出類似於:

deployment.apps/nginx-deployment patched

一旦超過截止日期,Deployment 控制器將在 Deployment 的 `.status.conditions` 中新增一個具有以下屬性的 DeploymentCondition:

  • type: Progressing
  • status: "False"
  • reason: ProgressDeadlineExceeded

此條件也可能提前失敗,然後由於 `ReplicaSetCreateError` 等原因而設定為 `“False”`。此外,一旦 Deployment 推出完成,截止日期將不再考慮。

有關狀態條件的更多資訊,請參閱 Kubernetes API 約定

你的 Deployment 可能會遇到瞬時錯誤,這可能是由於你設定的超時時間過短,或者由於任何其他可以視為瞬時錯誤的錯誤。例如,假設你的配額不足。如果你描述 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`,Deployment 狀態類似於:

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 進度截止日期,Kubernetes 會更新 `Progressing` 條件的狀態和原因:

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

你可以透過縮減 Deployment、縮減你可能正在執行的其他控制器或增加名稱空間中的配額來解決配額不足問題。如果你滿足配額條件,並且 Deployment 控制器隨後完成 Deployment 推出,你將看到 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 正在推出過程中並正在取得進展,或者它已成功完成其進展並且所需的新副本已可用(有關詳細資訊,請參閱條件的原因——在我們的示例中,`reason: NewReplicaSetAvailable` 表示 Deployment 已完成)。

你可以使用 `kubectl rollout status` 檢查 Deployment 是否未能取得進展。如果 Deployment 超出了進度截止日期,`kubectl rollout status` 將返回非零退出程式碼。

kubectl rollout status deployment/nginx-deployment

輸出類似於:

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline

並且來自 `kubectl rollout` 的退出狀態為 1(表示錯誤)

echo $?
1

對失敗的 Deployment 進行操作

適用於完整 Deployment 的所有操作也適用於失敗的 Deployment。你可以對其進行擴容/縮容,回滾到以前的修訂版本,甚至在需要對 Deployment Pod 模板進行多次調整時暫停它。

清理策略

你可以在 Deployment 中設定 `.spec.revisionHistoryLimit` 欄位,以指定要保留多少個此 Deployment 的舊 ReplicaSet。其餘的將在後臺進行垃圾回收。預設值為 10。

清理僅在 Deployment 達到完成狀態後才開始。如果你將 `.spec.revisionHistoryLimit` 設定為 0,任何推出仍然會在 Kubernetes 刪除舊的 ReplicaSet 之前觸發新的 ReplicaSet 的建立。

即使修訂歷史限制不為零,你也可以擁有比你配置的限制更多的 ReplicaSet。例如,如果 Pod 崩潰迴圈,並且隨著時間的推移觸發了多個滾動更新事件,你最終可能會擁有比 `.spec.revisionHistoryLimit` 更多的 ReplicaSet,因為 Deployment 從未達到完整狀態。

金絲雀部署

如果你希望使用 Deployment 向一部分使用者或伺服器推出版本,可以建立多個 Deployment,每個版本一個,遵循管理資源中描述的金絲雀模式。

編寫 Deployment 規約

與其他所有 Kubernetes 配置一樣,Deployment 需要 `.apiVersion`、`.kind` 和 `.metadata` 欄位。有關配置檔案的通用資訊,請參閱部署應用程式、配置容器和使用 kubectl 管理資源文件。

當控制平面為 Deployment 建立新的 Pod 時,Deployment 的 `.metadata.name` 是命名這些 Pod 的基礎。Deployment 的名稱必須是有效的DNS 子域名值,但這可能會導致 Pod 主機名出現意外結果。為了獲得最佳相容性,名稱應遵循更嚴格的DNS 標籤規則。

Deployment 還需要一個 `.spec` 節

Pod 模板

`.spec.template` 和 `.spec.selector` 是 `.spec` 唯一必填的欄位。

`.spec.template` 是一個Pod 模板。它與Pod 的模式完全相同,只是它是巢狀的,沒有 `apiVersion` 或 `kind`。

除了 Pod 的必需欄位外,Deployment 中的 Pod 模板必須指定適當的標籤和適當的重啟策略。對於標籤,請確保不要與其他控制器重疊。請參閱選擇器

只允許 `.spec.template.spec.restartPolicy` 等於 `Always`,這是未指定時的預設值。

副本

`.spec.replicas` 是一個可選欄位,用於指定所需 Pod 的數量。它預設為 1。

如果你手動擴縮 Deployment,例如透過 `kubectl scale deployment deployment --replicas=X`,然後你根據清單更新該 Deployment(例如:透過執行 `kubectl apply -f deployment.yaml`),那麼應用該清單會覆蓋你之前手動進行的擴縮。

如果 HorizontalPodAutoscaler(或任何類似的水平擴縮 API)正在管理 Deployment 的擴縮,請不要設定 `.spec.replicas`。

相反,允許 Kubernetes 控制平面 自動管理 `.spec.replicas` 欄位。

選擇器

`.spec.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 的標籤與選擇器匹配但其模板與 `.spec.template` 不同,或者此類 Pod 的總數超過 `.spec.replicas`,Deployment 可能會終止這些 Pod。如果 Pod 數量少於所需數量,它將使用 `.spec.template` 啟動新的 Pod。

如果多個控制器具有重疊的選擇器,它們將相互衝突,並且無法正常工作。

策略

`.spec.strategy` 指定用於替換舊 Pod 的新 Pod 的策略。`.spec.strategy.type` 可以是 "Recreate" 或 "RollingUpdate"。 "RollingUpdate" 是預設值。

重新建立 Deployment

當 `.`spec.strategy.type==Recreate` 時,所有現有 Pod 在建立新 Pod 之前都會被殺死。

滾動更新 Deployment

當 `.`spec.strategy.type==RollingUpdate` 時,Deployment 會以滾動更新的方式更新 Pod(逐步縮減舊 ReplicaSet 並擴容新的 ReplicaSet)。你可以指定 `maxUnavailable` 和 `maxSurge` 來控制滾動更新過程。

最大不可用數

`.spec.strategy.rollingUpdate.maxUnavailable` 是一個可選欄位,它指定在更新過程中可以不可用的 Pod 的最大數量。該值可以是絕對數字(例如 5)或所需 Pod 的百分比(例如 10%)。絕對數字透過向下取整從百分比計算。如果 `.spec.strategy.rollingUpdate.maxSurge` 為 0,則該值不能為 0。預設值為 25%。

例如,當此值設定為 30% 時,舊的 ReplicaSet 在滾動更新開始時可以立即縮減到所需 Pod 的 70%。一旦新的 Pod 就緒,舊的 ReplicaSet 可以進一步縮減,然後擴容新的 ReplicaSet,確保在更新期間任何時候可用的 Pod 總數至少為所需 Pod 的 70%。

最大激增數

`.spec.strategy.rollingUpdate.maxSurge` 是一個可選欄位,它指定可以建立超出所需 Pod 數量的最大 Pod 數量。該值可以是絕對數字(例如 5)或所需 Pod 的百分比(例如 10%)。如果 `maxUnavailable` 為 0,則該值不能為 0。絕對數字透過向上取整從百分比計算。預設值為 25%。

例如,當此值設定為 30% 時,新的 ReplicaSet 可以在滾動更新開始時立即擴容,從而使新舊 Pod 的總數不超過所需 Pod 的 130%。一旦舊 Pod 被殺死,新的 ReplicaSet 可以進一步擴容,確保在更新期間任何時候執行的 Pod 總數最多為所需 Pod 的 130%。

以下是一些使用 `maxUnavailable` 和 `maxSurge` 的滾動更新 Deployment 示例:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.14.2
       ports:
       - containerPort: 80
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxUnavailable: 1

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.14.2
       ports:
       - containerPort: 80
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 1

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.14.2
       ports:
       - containerPort: 80
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 1
     maxUnavailable: 1

進度截止秒數

`.spec.progressDeadlineSeconds` 是一個可選欄位,它指定 Deployment 在系統報告 Deployment 未能取得進展之前你希望等待的秒數——在資源狀態中顯示為 `type: Progressing`、`status: "False"` 和 `reason: ProgressDeadlineExceeded` 的條件。Deployment 控制器將繼續重試 Deployment。預設值為 600。將來,一旦實現了自動回滾,Deployment 控制器將在觀察到此類條件後立即回滾 Deployment。

如果指定,此欄位必須大於 `.spec.minReadySeconds`。

最小就緒秒數

`.spec.minReadySeconds` 是一個可選欄位,它指定新建立的 Pod 在其任何容器未崩潰的情況下應保持就緒的最短秒數,以便將其視為可用。預設值為 0(Pod 一旦就緒即被視為可用)。要了解有關 Pod 何時被視為就緒的更多資訊,請參閱容器探針

終止 Pods

特性狀態: `Kubernetes v1.33 [alpha]`(預設啟用:false)

你可以透過在API 伺服器kube-controller-manager 上設定 `DeploymentReplicaSetTerminatingReplicas` 特性門控來啟用此特性。

由於刪除或縮減而進入終止狀態的 Pod 可能需要很長時間才能終止,並且在此期間可能會消耗額外的資源。因此,所有 Pod 的總數可能會暫時超過 `.spec.replicas`。可以使用 Deployment 的 `.status.terminatingReplicas` 欄位跟蹤正在終止的 Pod。

修訂歷史限制

Deployment 的修訂歷史記錄儲存在其控制的 ReplicaSet 中。

`.spec.revisionHistoryLimit` 是一個可選欄位,它指定要保留的舊 ReplicaSet 的數量,以允許回滾。這些舊 ReplicaSet 會消耗 `etcd` 中的資源,並使 `kubectl get rs` 的輸出變得混亂。每個 Deployment 修訂的配置都儲存在其 ReplicaSet 中;因此,一旦舊 ReplicaSet 被刪除,你將失去回滾到該 Deployment 修訂的能力。預設情況下,將保留 10 箇舊 ReplicaSet,但其理想值取決於新 Deployment 的頻率和穩定性。

更具體地說,將此欄位設定為零意味著所有具有 0 個副本的舊 ReplicaSet 都將被清理。在這種情況下,新的 Deployment 推出無法撤消,因為其修訂歷史記錄已被清理。

暫停

`.spec.paused` 是一個可選的布林欄位,用於暫停和恢復 Deployment。暫停的 Deployment 與未暫停的 Deployment 之間的唯一區別是,只要它處於暫停狀態,對暫停的 Deployment 的 PodTemplateSpec 的任何更改都不會觸發新的推出。Deployment 在建立時預設不暫停。

下一步

最後修改於 2025 年 8 月 29 日下午 5:11 PST:澄清 Deployment 更新行為 (808824fa27)