k8s工作負載控制器--Deployment

misakivv發表於2024-07-29

目錄
  • 一、引入背景
  • 二、主要功能
  • 三、資源清單
  • 四、例項
    • 1、流程
    • 2、建立Deployment資源清單
    • 3、建立Deployment
    • 4、檢查Deployment是否建立成功(正在建立)
    • 5、檢視Deployment的上線狀態
    • 6、再次檢視Deployment狀態(建立完成)
    • 7、檢視Deployment 建立的ReplicaSet(rs)
    • 8、檢視被建立的Pod的標籤
    • 9、Pod-template-hash 標籤
  • 五、滾動更新Deployment
    • 1、更新容器所使用的映象
      • 1.1、kubectl set 手動設定
      • 1.2、edit線上更新
    • 2、檢視上線狀態
    • 3、上線後檢視Deployment
    • 4、檢視ReplicaSet(rs)
    • 5、檢視新建立的Pod
    • 6、檢視Deployment詳細資訊
    • 六、多 Deployment 動態更新
  • 七、回滾Deployment
    • 1、回滾場景
    • 2、檢查上線狀態來驗證
    • 3、檢視建立的Pod
    • 4、獲取Deployment詳細資訊
    • 5、檢查Deployment歷史上線
      • 5.1、檢查 Deployment 修訂歷史
      • 5.2、檢視修訂歷史的詳細資訊
    • 6、回滾到之前的版本
      • 6.1、撤消當前上線並回滾到以前的版本
      • 6.2、檢查回滾是否成功以及 Deployment 是否正在執行
      • 6.3、獲取Deployment詳細資訊
  • 八、縮放Deployment
    • 1、scale命令縮放
    • 2、自動縮放
    • 3、比例縮放
      • 3.1、修改資源清單
      • 3.2、應用資源清單
      • 3.3、確保 Deployment 的這 10 個副本都在執行
      • 3.4、更新 Deployment 使用新映象
      • 3.5、檢查上線狀態
      • 3.6、檢視Deployment狀態
      • 3.7、獲取上線狀態
  • 九、暫停、恢復 Deployment 的上線過程
    • 1、對於剛建立的Deployment
      • 1.1、獲取Deployment 資訊
      • 1.2、獲取上線狀態
    • 2、暫停上線
    • 3、更新映象
    • 4、檢視沒有觸發上線狀態
    • 5、獲取上線狀態驗證現有的 ReplicaSet 沒有被更改
    • 6、可以根據需要執行很多更新操作
    • 7、恢復 Deployment 上線
    • 8、觀察上線狀態
    • 9、獲取最新上線狀態
  • 十、Deployment狀態
    • 1、進行中的Deployment
    • 2、完成的Deployment
      • 2.1、示例
    • 3、失敗的 Deployment
      • 3.1、示例
        • 3.1.1、設定progressDeadlineSeconds
        • 3.1.2、設定配額
        • 3.1.3、應用配額
        • 3.1.4、觀察Deployment狀態
        • 3.1.5、檢視報錯message
        • 3.1.6、檢查Deployment進度
        • 3.1.7、超過 Deployment 進度限期,Kubernetes 將更新狀態和進度狀況的原因
        • 3.1.8、解決配額問題
        • 3.1.9、觀察Deployment恢復情況
        • 3.1.10、檢查 Deployment 是否未能取得進展
      • 3.2、對失敗的Deployment的操作
  • 十一、清理策略
  • 十二、金絲雀釋出
  • 十三、編寫Deployment規約
    • 1、Pod模版
      • 1.1、.spec.template
      • 1.2、.spec.selector
    • 2、副本
    • 3、指定算符
    • 4、策略
      • 4.1、重新建立Deployment
      • 4.2、滾動更新Deployment
        • 4.2.1、最大不可用
        • 4.2.2、最大峰值
        • 4.2.3、滾動更新示例
    • 5、進度期限秒數
    • 6、最短就緒時間
    • 7、修訂歷史限制
    • 8、paused(暫停的)

一、引入背景

在早期版本的K8s中,Pod的副本數量由Replication Controller(簡稱RC)進行管理。然而,隨著K8s的不斷髮展,RC的功能逐漸顯得捉襟見肘,無法滿足複雜的應用部署需求。為了解決這個問題,K8s從V1.2版本開始引入了Deployment控制器。

Deployment控制器並不直接管理Pod,而是透過管理ReplicaSet來間接管理Pod。簡單來說,Deployment管理ReplicaSet,而ReplicaSet管理Pod。這樣的設計使得DeploymentReplicaSet功能更加強大,能夠滿足更多樣化的應用部署需求。

image-20240618150136884

二、主要功能

  • 支援ReplicaSet的所有功能
  • 支援釋出的停止、繼續
  • 支援滾動升級和回滾版本

三、資源清單

apiVersion: apps/v1 # 版本號
kind: Deployment # 型別       
metadata: # 後設資料
  name: # Deploy名稱 
  namespace: # 所屬名稱空間 
  labels: #標籤
    controller: deploy
spec: # 詳情描述
  replicas: 3 # 副本數量
  revisionHistoryLimit: 3 # 保留歷史版本(rs,用於版本回退)
  paused: false # 暫停部署,預設是false
  progressDeadlineSeconds: 600 # 部署超時時間(s),預設是600
  strategy: # 策略
    type: RollingUpdate # 滾動更新策略
    rollingUpdate: # 滾動更新
      maxSurge: 30% # 最大額外可以存在的副本數,可以為百分比,也可以為整數
      maxUnavailable: 30% # 最大不可用狀態的 Pod 的最大值,可以為百分比,也可以為整數
  selector: # 選擇器,透過它指定該控制器管理哪些pod
    matchLabels: # Labels匹配規則
      app: nginx-pod
    matchExpressions: # Expressions匹配規則
      - { key: app, operator: In, values: [ nginx-pod ] }
  template: # 模板,當副本數量不足時,會根據下面的模板建立pod副本
    metadata:
      labels:
        app: nginx-pod
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
            - containerPort: 80

四、例項

1、流程

  • 建立 Deployment 以將 ReplicaSet 上線。ReplicaSet 在後臺建立 Pod。 檢查 ReplicaSet 的上線狀態,檢視其是否成功。
  • 透過更新 Deployment 的 PodTemplateSpec,宣告 Pod 的新狀態 。 新的 ReplicaSet 會被建立,Deployment 以受控速率將 Pod 從舊 ReplicaSet 遷移到新 ReplicaSet。 每個新的 ReplicaSet 都會更新 Deployment 的修訂版本。
  • 如果 Deployment 的當前狀態不穩定,回滾到較早的 Deployment 版本。 每次回滾都會更新 Deployment 的修訂版本。
  • 擴大 Deployment 規模以承擔更多負載
  • 暫停 Deployment 的上線 以應用對 PodTemplateSpec 所作的多項修改, 然後恢復其執行以啟動新的上線版本。
  • 使用 Deployment 狀態來判定上線過程是否出現停滯。
  • 清理較舊的不再需要的 ReplicaSet

2、建立Deployment資源清單

nginx-deployment.yaml

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:latest
        ports:
        - containerPort: 80
  • 建立名為 deploy-controller(由 .metadata.name 欄位標明)的 Deployment。 該名稱將成為後續建立 ReplicaSet 和 Pod 的命名基礎。 參閱編寫 Deployment 規約獲取更多詳細資訊。
  • 該 Deployment 建立一個 ReplicaSet,它建立三個(由 .spec.replicas 欄位標明)Pod 副本。
  • .spec.selector 欄位定義所建立的 ReplicaSet 如何查詢要管理的 Pod。 在這裡,你選擇在 Pod 模板中定義的標籤(app: nginx)。 不過,更復雜的選擇規則是也可能的,只要 Pod 模板本身滿足所給規則即可。
  • template 欄位包含以下子欄位:
    • Pod 被使用 .metadata.labels 欄位打上 app: nginx 標籤。
    • Pod 模板規約(即 .template.spec 欄位)指示 Pod 執行一個 nginx 容器,映象為nginx的最新版本。
    • 建立一個容器並使用 .spec.template.spec.containers[0].name 欄位將其命名為 nginx。

3、建立Deployment

kubectl apply -f nginx-deployment.yaml

image-20240728170949014

4、檢查Deployment是否建立成功(正在建立)

kubectl get deployments -n default 

image-20240728171633112

在檢查叢集中的 Deployment 時,所顯示的欄位有:

  • NAME 列出了名字空間中 Deployment 的名稱。
  • READY 顯示應用程式的可用的“副本”數。顯示的模式是“就緒個數/期望個數”。
  • UP-TO-DATE 顯示為了達到期望狀態已經更新的副本數。
  • AVAILABLE 顯示應用可供使用者使用的副本數。
  • AGE 顯示應用程式執行的時間。

請注意期望副本數是根據 .spec.replicas 欄位設定 3。

5、檢視Deployment的上線狀態

kubectl rollout status deployment/nginx-deployment

image-20240728172104454

6、再次檢視Deployment狀態(建立完成)

kubectl get deployments -n default 

image-20240728172555728

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

7、檢視Deployment 建立的ReplicaSet(rs)

kubectl get rs 

image-20240728172951869

ReplicaSet 輸出中包含以下欄位:

  • NAME 列出名字空間中 ReplicaSet 的名稱;
  • DESIRED 顯示應用的期望副本個數,即在建立 Deployment 時所定義的值。 此為期望狀態;
  • CURRENT 顯示當前執行狀態中的副本個數;
  • READY 顯示應用中有多少副本可以為使用者提供服務;
  • AGE 顯示應用已經執行的時間長度。

注意 ReplicaSet 的名稱格式始終為 [Deployment 名稱]-[雜湊]。 該名稱將成為所建立的 Pod 的命名基礎。 其中的雜湊字串與 ReplicaSet 上的 pod-template-hash 標籤一致。

image-20240728173415269

8、檢視被建立的Pod的標籤

kubectl get pods --show-labels 

image-20240728173731723

  • 所建立的 ReplicaSet 確保總是存在三個 nginx Pod。
  • 必須在 Deployment 中指定適當的Pod 模板標籤(在本例中為 app: nginx)。
  • 標籤最好不要與其他控制器(包括其他 Deployment 和 StatefulSet)重疊。

9、Pod-template-hash 標籤

不要更改此標籤

Deployment 控制器將 pod-template-hash 標籤新增到 Deployment 所建立或收留的每個 ReplicaSet 。

此標籤可確保 Deployment 的子 ReplicaSet 不重疊。 標籤是透過對 ReplicaSet 的 PodTemplate 進行雜湊處理。 所生成的雜湊值被新增到 ReplicaSet 選擇算符、Pod 模板標籤,並存在於在 ReplicaSet 可能擁有的任何現有 Pod 中。

五、滾動更新Deployment

僅當 Deployment Pod 模板(即 .spec.template)發生改變時,例如模板的標籤或容器映象被更新, 才會觸發 Deployment 上線。其他更新(如對 Deployment 執行擴縮容的操作)不會觸發上線動作。

1、更新容器所使用的映象

1.1、kubectl set 手動設定

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

image-20240728183010627

deployment/nginx-deployment 表明 Deployment 的名稱

nginx 表明需要進行更新的容器, 而 nginx:1.16.1 則表示映象的新版本以及它的標籤。

1.2、edit線上更新

kubectl edit deployment nginx-deployment

image-20240728183529742

2、檢視上線狀態

kubectl rollout status deployment/nginx-deployment

image-20240728184851400

3、上線後檢視Deployment

kubectl get deploy -o wide

image-20240728185629593

4、檢視ReplicaSet(rs)

kubectl get rs

image-20240728185951663

檢視Deployment 透過建立新的 ReplicaSet 並將其擴容到 3 個副本並將舊 ReplicaSet 縮容到 0 個副本完成了 Pod 的更新操作

5、檢視新建立的Pod

kubectl get pods

image-20240728190252272

應該僅顯示新的Pod資訊

下次要更新這些 Pod 時,只需再次更新 Deployment Pod 模板即可。

Deployment 可確保在更新時僅關閉一定數量的 Pod。預設情況下,它確保至少所需 Pod 的 75% 處於執行狀態(最大不可用比例為 25%)。

Deployment 還確保僅所建立 Pod 數量只可能比期望 Pod 數高一點點。 預設情況下,它可確保啟動的 Pod 個數比期望個數最多多出 125%(最大峰值 25%)。

例如,如果仔細檢視上述 Deployment ,將看到它首先建立了一個新的 Pod,然後刪除舊的 Pod, 並建立了新的 Pod。它不會殺死舊 Pod,直到有足夠數量的新 Pod 已經出現。 在足夠數量的舊 Pod 被殺死前並沒有建立新 Pod。它確保至少 3 個 Pod 可用, 同時最多總共 4 個 Pod 可用。 當 Deployment 設定為 4 個副本時,Pod 的個數會介於 3 和 5 之間。

6、檢視Deployment詳細資訊

kubectl describe deployments

image-20240728194803428

可以看到,當第一次建立 Deployment 時,它建立了一個 ReplicaSet(nginx-deployment-585449566) 並將其直接擴容至 3 個副本。更新 Deployment 時,它建立了一個新的 ReplicaSet (nginx-deployment-76f59d996),並將其擴容為 1,等待其就緒;然後將舊 ReplicaSet 縮容到 2, 將新的 ReplicaSet 擴容到 2 以便至少有 3 個 Pod 可用且最多建立 4 個 Pod。 然後,它使用相同的滾動更新策略繼續對新的 ReplicaSet 擴容並對舊的 ReplicaSet 縮容。 最後,你將有 3 個可用的副本在新的 ReplicaSet 中,舊 ReplicaSet 將縮容到 0。

Kubernetes 在計算 availableReplicas 數值時不考慮終止過程中的 Pod, availableReplicas 的值一定介於 replicas - maxUnavailable 和 replicas + maxSurge 之間。 因此,你可能在上線期間看到 Pod 個數比預期的多,Deployment 所消耗的總的資源也大於 replicas + maxSurge 個 Pod 所用的資源,直到被終止的 Pod 所設定的 terminationGracePeriodSeconds 到期為止。

六、多 Deployment 動態更新

Deployment 控制器每次注意到新的 Deployment 時,都會建立一個 ReplicaSet 以啟動所需的 Pod。 如果更新了 Deployment,則控制標籤匹配 .spec.selector 但模板不匹配 .spec.template 的 Pod 的現有 ReplicaSet 被縮容。 最終,新的 ReplicaSet 縮放為 .spec.replicas 個副本, 所有舊 ReplicaSet 縮放為 0 個副本。

當 Deployment 正在上線時被更新,Deployment 會針對更新建立一個新的 ReplicaSet 並開始對其擴容,之前正在被擴容的 ReplicaSet 會被翻轉,新增到舊 ReplicaSet 列表 並開始縮容。

例如,假定你在建立一個 Deployment 以生成 nginx:1.14.2 的 5 個副本,但接下來 更新 Deployment 以建立 5 個 nginx:1.16.1 的副本,而此時只有 3 個 nginx:1.14.2 副本已建立。在這種情況下,Deployment 會立即開始殺死 3 個 nginx:1.14.2 Pod, 並開始建立 nginx:1.16.1 Pod。它不會等待 nginx:1.14.2 的 5 個副本都建立完成後才開始執行變更動作。

七、回滾Deployment

Deployment 被觸發上線時,系統就會建立 Deployment 的新的修訂版本。 這意味著僅當 Deployment 的 Pod 模板(.spec.template)發生更改時,才會建立新修訂版本

例如,模板的標籤或容器映象發生變化。 其他更新,如 Deployment 的擴縮容操作不會建立 Deployment 修訂版本。 這是為了方便同時執行手動縮放或自動縮放。 換言之,當你回滾到較早的修訂版本時,只有 Deployment 的 Pod 模板部分會被回滾。

1、回滾場景

假設你在更新 Deployment 時犯了一個拼寫錯誤,將映象名稱命名設定為 nginx:1.161 而不是 nginx:1.16.1

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

image-20240728211025703

2、檢查上線狀態來驗證

kubectl rollout status deployment/nginx-deployment

image-20240728211226292

  • 按 Ctrl-C 停止上述上線狀態觀測。有關上線停滯的詳細資訊,參考這裡
  • 你可以看到舊的副本(算上來自 nginx-deployment-585449566nginx-deployment-76f59d996 的副本)有 3 個, 新的副本(來自 nginx-deployment-66d646f584)有 1 個:
kubectl get rs    

image-20240728211356814

3、檢視建立的Pod

新 ReplicaSet 所建立的 1 個 Pod 卡頓在映象拉取迴圈中。

kubectl get pods

image-20240728211823127

Deployment 控制器自動停止有問題的上線過程,並停止對新的 ReplicaSet 擴容。 這行為取決於所指定的 rollingUpdate 引數(具體為 maxUnavailable)。 預設情況下,Kubernetes 將此值設定為 25%。

4、獲取Deployment詳細資訊

kubectl describe deployments

image-20240728212141033

要解決此問題,需要回滾到以前穩定的 Deployment 版本。

5、檢查Deployment歷史上線

5.1、檢查 Deployment 修訂歷史

kubectl rollout history deployment/nginx-deployment

image-20240728212605765

5.2、檢視修訂歷史的詳細資訊

kubectl rollout history deployment/nginx-deployment --revision=2

6、回滾到之前的版本

6.1、撤消當前上線並回滾到以前的版本

kubectl rollout undo deployment/nginx-deployment --to-revision=2

與回滾相關的指令的更詳細資訊,請參考 kubectl rollout

現在,Deployment 正在回滾到以前的穩定版本。Deployment 控制器生成了回滾到修訂版本 2 的 DeploymentRollback 事件。

6.2、檢查回滾是否成功以及 Deployment 是否正在執行

kubectl get deployment nginx-deployment

image-20240728213450450

6.3、獲取Deployment詳細資訊

kubectl describe deploy nginx-deployment

image-20240728213640051

八、縮放Deployment

1、scale命令縮放

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

image-20240728215049761

2、自動縮放

假設叢集啟用了Pod 的水平自動縮放, 你可以為 Deployment 設定自動縮放器,並基於現有 Pod 的 CPU 利用率選擇要執行的 Pod 個數下限和上限。

kubectl autoscale deployment/nginx-deployment --min=6 --max=10 --cpu-percent=60

image-20240728215425931

3、比例縮放

RollingUpdate 的 Deployment 支援同時執行應用程式的多個版本。 當自動縮放器縮放處於上線程序(仍在進行中或暫停)中的 RollingUpdate Deployment 時, Deployment 控制器會平衡現有的活躍狀態的 ReplicaSet(含 Pod 的 ReplicaSet)中的額外副本, 以降低風險。這稱為 比例縮放(Proportional Scaling)

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

3.1、修改資源清單

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 10
  selector:
    matchLabels:
      app: nginx
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 3
      maxUnavailable: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
  • maxSurge 指定了在滾動更新期間可以比期望的副本數量多建立的最大 Pod 數量。它可以是一個絕對數字或者是相對於期望副本數量的百分比。這個欄位確保在建立新的 Pod 時不會超出資源限制,並且可以控制更新的速度。

    • 例如,在你的配置中,maxSurge: 3 意味著在滾動更新期間,最多可以比期望的副本數(在這個例子中是 10)多建立 3 個 Pod。
  • maxUnavailable 指定了在滾動更新期間可以比期望的副本數量少的 Pod 的最大數量。同樣,它可以是一個絕對數字或者是相對於期望副本數量的百分比。這個欄位確保在刪除舊的 Pod 時至少有一定數量的 Pod 可用,以保證服務的連續性。

    • 例如,在你的配置中,maxUnavailable: 2 意味著在滾動更新期間,最多可以比期望的副本數少 2 個 Pod 可用。

3.2、應用資源清單

kubectl apply -f nginx-deployment.yaml

image-20240728221827589

3.3、確保 Deployment 的這 10 個副本都在執行

kubectl get deploy

image-20240728222104349

3.4、更新 Deployment 使用新映象

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

image-20240728224308991

3.5、檢查上線狀態

映象更新使用 ReplicaSet nginx-deployment-56677b7d5d 啟動新的上線過程, 但由於上面提到的 maxUnavailable 要求,該程序被阻塞了。

kubectl get rs

image-20240728223909270

然後,出現了新的 Deployment 擴縮請求。自動縮放器將 Deployment 副本增加到 15。 Deployment 控制器需要決定在何處新增 5 個新副本。如果未使用比例縮放,所有 5 個副本 都將新增到新的 ReplicaSet 中。使用比例縮放時,可以將額外的副本分佈到所有 ReplicaSet。 較大比例的副本會被新增到擁有最多副本的 ReplicaSet,而較低比例的副本會進入到 副本較少的 ReplicaSet。所有剩下的副本都會新增到副本最多的 ReplicaSet。 具有零副本的 ReplicaSet 不會被擴容。

3.6、檢視Deployment狀態

image-20240728224637872

3.7、獲取上線狀態

kubectl get rs

image-20240728224748935

九、暫停、恢復 Deployment 的上線過程

在你更新一個 Deployment 的時候,或者計劃更新它的時候, 你可以在觸發一個或多個更新之前暫停 Deployment 的上線過程。 當你準備應用這些變更時,你可以重新恢復 Deployment 上線過程。 這樣做使得你能夠在暫停和恢復執行之間應用多個修補程式,而不會觸發不必要的上線操作。

1、對於剛建立的Deployment

1.1、獲取Deployment 資訊

kubectl get deploy

image-20240729110426671

1.2、獲取上線狀態

kubectl get rs -o wide

image-20240729110546747

2、暫停上線

kubectl rollout pause deployment/nginx-deployment

image-20240729110758042

3、更新映象

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

image-20240729110954044

4、檢視沒有觸發上線狀態

kubectl rollout history deployment nginx-deployment

image-20240729111137267

5、獲取上線狀態驗證現有的 ReplicaSet 沒有被更改

kubectl get rs -o wide

image-20240729111314701

6、可以根據需要執行很多更新操作

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

image-20240729112034750

暫停 Deployment 上線之前的初始狀態將繼續發揮作用,但新的更新在 Deployment 上線被暫停期間不會產生任何效果。

7、恢復 Deployment 上線

觀察新的 ReplicaSet 的建立過程,其中包含了所應用的所有更新

kubectl rollout resume deployment/nginx-deployment

image-20240729112303645

8、觀察上線狀態

 kubectl get rs -w

image-20240729112539662

9、獲取最新上線狀態

kubectl get rs -o wide

image-20240729112846521

不可以回滾處於暫停狀態的 Deployment,除非先恢復其執行狀態。

十、Deployment狀態

Deployment 的生命週期中會有許多狀態。上線新的 ReplicaSet 期間可能處於 Progressing(進行中),可能是 Complete(已完成),也可能是 Failed(失敗)以至於無法繼續進行。

1、進行中的Deployment

執行下面的任務期間,Kubernetes 標記 Deployment 為進行中(Progressing)

  • Deployment 建立新的 ReplicaSet
  • Deployment 正在為其最新的 ReplicaSet 擴容
  • Deployment 正在為其舊有的 ReplicaSet(s) 縮容
  • 新的 Pod 已經就緒或者可用(就緒至少持續了 MinReadySeconds 秒)。

當上線過程進入“Progressing”狀態時,Deployment 控制器會向 Deployment 的 .status.conditions 中新增包含下面屬性的狀況條目:

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

監視 Deployment 的進度:

kubectl rollout status deploy <deployment-name>

2、完成的Deployment

當 Deployment 具有以下特徵時,Kubernetes 將其標記為完成(Complete):

  • 與 Deployment 關聯的所有副本都已更新到指定的最新版本,這意味著之前請求的所有更新都已完成。
  • 與 Deployment 關聯的所有副本都可用。
  • 未執行 Deployment 的舊副本。

當上線過程進入“Complete”狀態時,Deployment 控制器會向 Deployment 的 .status.conditions 中新增包含下面屬性的狀況條目:

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

這一 Progressing 狀況的狀態值會持續為 "True",直至新的上線動作被觸發。 即使副本的可用狀態發生變化(進而影響 Available 狀況),Progressing 狀況的值也不會變化。

2.1、示例

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

kubectl rollout status deploy nginx-deployment

echo $?

image-20240729135409597

3、失敗的 Deployment

Deployment 可能會在嘗試部署其最新的 ReplicaSet ,一直處於未完成狀態。 造成此情況一些可能因素如下:

  • 配額(Quota)不足
  • 就緒探測(Readiness Probe)失敗
  • 映象拉取錯誤
  • 許可權不足
  • 限制範圍(Limit Ranges)問題
  • 應用程式執行時的配置錯誤

檢測此狀況的一種方法是在 Deployment 規約中指定截止時間引數: (.spec.progressDeadlineSeconds)。 .spec.progressDeadlineSeconds 給出的是一個秒數值,Deployment 控制器在(透過 Deployment 狀態) 標示 Deployment 進展停滯之前,需要等待所給的時長。

3.1、示例

3.1.1、設定progressDeadlineSeconds

以下 kubectl 命令設定規約中的 progressDeadlineSeconds,從而告知控制器 在 10 分鐘後報告 Deployment 的上線沒有進展:

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

image-20240729140008482

超過截止時間後,Deployment 控制器將新增具有以下屬性的 Deployment 狀況到 Deployment 的 .status.conditions 中:

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

這一狀況也可能會比較早地失敗,因而其狀態值被設定為 "False", 其原因為 ReplicaSetCreateError。 一旦 Deployment 上線完成,就不再考慮其期限。

參考 Kubernetes API Conventions 獲取更多狀態狀況相關的資訊。

Deployment 可能會出現瞬時性的錯誤,可能因為設定的超時時間過短, 也可能因為其他可認為是臨時性的問題。

3.1.2、設定配額

為了模擬配額不足的情況,我們需要為當前名稱空間設定一個配額限制。假設我們希望限制 Pod 的數量為 1 個,我們可以建立一個配額 YAML 檔案

quota.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: pod-quota
spec:
  hard:
    pods: 1

3.1.3、應用配額

kubectl apply -f quota.yaml

如果 Deployment 的建立時間早於 ResourceQuota 的應用時間,則 Deployment 不會受到配額限制的影響。

3.1.4、觀察Deployment狀態

kubectl describe deploy nginx-deployment

image-20240729143556979

3.1.5、檢視報錯message

kubectl get deploy nginx-deployment -o yaml

image-20240729144028258

3.1.6、檢查Deployment進度

kubectl rollout status deploy nginx-deployment

image-20240729144825554

如果 Deployment 超過了進度期限

命令將返回錯誤error: deployment "nginx-deployment" exceeded its progress deadline

3.1.7、超過 Deployment 進度限期,Kubernetes 將更新狀態和進度狀況的原因

image-20240729145254236

3.1.8、解決配額問題

增加配額限制,以便 Deployment 可以完成。我們可以透過修改 ResourceQuota 的硬限制來實現這一點:

kubectl patch resourcequota pod-quota -p '{"spec":{"hard":{"pods":"3"}}}'

image-20240729145941741

3.1.9、觀察Deployment恢復情況

kubectl describe deploy nginx-deployment

type: Available 加上 status: True 意味著 Deployment 具有最低可用性。 最低可用性由 Deployment 策略中的引數指定。

type: Progressing 加上 status: True 表示 Deployment 處於上線過程中,並且正在執行, 或者已成功完成進度,最小所需新副本處於可用。 在這個案例中 reason: NewReplicaSetAvailable 表示 Deployment 已完成。

3.1.10、檢查 Deployment 是否未能取得進展

kubectl rollout status deploy nginx-deployment

echo $?

image-20240729151823918

3.2、對失敗的Deployment的操作

可應用於已完成的 Deployment 的所有操作也適用於失敗的 Deployment。 你可以對其執行擴縮容、回滾到以前的修訂版本等操作,或者在需要對 Deployment 的 Pod 模板應用多項調整時,將 Deployment 暫停。

十一、清理策略

可以在 Deployment 中設定 .spec.revisionHistoryLimit 欄位以指定保留此 Deployment 的多少箇舊有 ReplicaSet。其餘的 ReplicaSet 將在後臺被垃圾回收。 預設情況下,此值為 10。

顯式將此欄位設定為 0 將導致 Deployment 的所有歷史記錄被清空,因此 Deployment 將無法回滾。

kubeectl get deploy nginx-deployment -o yaml

image-20240729152737859

十二、金絲雀釋出

如果要使用 Deployment 向使用者子集或伺服器子集上線版本, 則可以遵循資源管理所描述的金絲雀模式, 建立多個 Deployment,每個版本一個。

十三、編寫Deployment規約

同其他 Kubernetes 配置一樣, Deployment 需要 .apiVersion.kind.metadata 欄位。 有關配置檔案的其他資訊,請參考部署 Deployment、 配置容器和使用 kubectl 管理資源等相關文件。

當控制面為 Deployment 建立新的 Pod 時,Deployment 的 .metadata.name 是命名這些 Pod 的部分基礎。 Deployment 的名稱必須是一個合法的 DNS 子域值, 但這會對 Pod 的主機名產生意外的結果。為獲得最佳相容性,名稱應遵循更嚴格的 DNS 標籤規則。

Deployment 還需要 .spec 部分

1、Pod模版

.spec 中只有 .spec.template.spec.selector 是必需的欄位。

image-20240729153512705

1.1、.spec.template

  • 這個欄位定義了 Deployment 建立的 Pod 的模板,它告訴 Kubernetes 每個 Pod 應該是什麼樣子的。
  • 包含 .spec.template.metadata.labels,這些標籤用於標識由 Deployment 控制的 Pod。
  • 包含 .spec.template.spec,這描述了 Pod 的具體配置,比如容器、映象、埠等。

1.2、.spec.selector

  • 這個欄位指定了 Deployment 用來選擇 Pod 的標籤選擇器。
  • 它必須與 .spec.template.metadata.labels 中定義的標籤相匹配,這樣才能讓 Deployment 知道哪些 Pod 是它應該管理的。

.spec.template 是一個 Pod 模板。 它和 Pod 的語法規則完全相同。 只是這裡它是巢狀的,因此不需要 apiVersion 或 kind。

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

只有 .spec.template.spec.restartPolicy 等於 Always 才是被允許的,這也是在沒有指定時的預設設定。

2、副本

.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 欄位。

3、指定算符

.spec.selector 是指定本 Deployment 的 Pod 標籤選擇算符的必需欄位。

.spec.selector 必須匹配 .spec.template.metadata.labels,否則請求會被 API 拒絕。

image-20240729155413299

在 API apps/v1版本中,.spec.selector.metadata.labels 如果沒有設定的話, 不會被預設設定為 .spec.template.metadata.labels,所以需要明確進行設定。 同時在 apps/v1版本中,Deployment 建立後 .spec.selector 是不可變的。

當 Pod 的標籤和選擇算符匹配,但其模板和 .spec.template 不同時,或者此類 Pod 的總數超過 .spec.replicas 的設定時,Deployment 會終結之。 如果 Pod 總數未達到期望值,Deployment 會基於 .spec.template 建立新的 Pod。

如果有多個控制器的選擇算符發生重疊,則控制器之間會因衝突而無法正常工作。

4、策略

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

image-20240729155620602

4.1、重新建立Deployment

如果 .spec.strategy.type==Recreate,在建立新 Pod 之前,所有現有的 Pod 會被殺死。

這隻會確保為了升級而建立新 Pod 之前其他 Pod 都已終止。如果你升級一個 Deployment, 所有舊版本的 Pod 都會立即被終止。控制器等待這些 Pod 被成功移除之後, 才會建立新版本的 Pod。如果你手動刪除一個 Pod,其生命週期是由 ReplicaSet 來控制的, 後者會立即建立一個替換 Pod(即使舊的 Pod 仍然處於 Terminating 狀態)。 如果你需要一種“最多 n 個”的 Pod 個數保證,你需要考慮使用 StatefulSet

4.2、滾動更新Deployment

Deployment 會在 .spec.strategy.type==RollingUpdate時,採取 滾動更新的方式更新 Pod。你可以指定 maxUnavailablemaxSurge 來控制滾動更新過程。

4.2.1、最大不可用

.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%。

4.2.2、最大峰值

.spec.strategy.rollingUpdate.maxSurge 是一個可選欄位,用來指定可以建立的超出期望 Pod 個數的 Pod 數量。此值可以是絕對數(例如,5)或所需 Pod 的百分比(例如,10%)。 如果 MaxUnavailable 為 0,則此值不能為 0。百分比值會透過向上取整轉換為絕對數。 此欄位的預設值為 25%。

例如,當此值為 30% 時,啟動滾動更新後,會立即對新的 ReplicaSet 擴容,同時保證新舊 Pod 的總數不超過所需 Pod 總數的 130%。一旦舊 Pod 被殺死,新的 ReplicaSet 可以進一步擴容, 同時確保更新期間的任何時候執行中的 Pod 總數最多為所需 Pod 總數的 130%。

4.2.3、滾動更新示例

  • 最大不可用

    • 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
      

5、進度期限秒數

.spec.progressDeadlineSeconds 是一個可選欄位,用於指定系統在報告 Deployment 進展失敗之前等待 Deployment 取得進展的秒數。 這類報告會在資源狀態中體現為 type: Progressingstatus: Falsereason: ProgressDeadlineExceeded。Deployment 控制器將在預設 600 毫秒內持續重試 Deployment。 將來,一旦實現了自動回滾,Deployment 控制器將在探測到這樣的條件時立即回滾 Deployment。

如果指定,則此欄位值需要大於 .spec.minReadySeconds 取值。

6、最短就緒時間

.spec.minReadySeconds 是一個可選欄位,用於指定新建立的 Pod 在沒有任意容器崩潰情況下的最小就緒時間, 只有超出這個時間 Pod 才被視為可用。預設值為 0(Pod 在準備就緒後立即將被視為可用)。 要了解何時 Pod 被視為就緒, 可參考容器探針

7、修訂歷史限制

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

.spec.revisionHistoryLimit 是一個可選欄位,用來設定出於回滾目的所要保留的舊 ReplicaSet 數量。 這些舊 ReplicaSet 會消耗 etcd 中的資源,並佔用 kubectl get rs 的輸出。 每個 Deployment 修訂版本的配置都儲存在其 ReplicaSet 中;因此,一旦刪除了舊的 ReplicaSet, 將失去回滾到 Deployment 的對應修訂版本的能力。 預設情況下,系統保留 10 箇舊 ReplicaSet,但其理想值取決於新 Deployment 的頻率和穩定性。

image-20240729161828956

更具體地說,將此欄位設定為 0 意味著將清理所有具有 0 個副本的舊 ReplicaSet。 在這種情況下,無法撤消新的 Deployment 上線,因為它的修訂歷史被清除了。

8、paused(暫停的)

.spec.paused 是用於暫停和恢復 Deployment 的可選布林欄位。 暫停的 Deployment 和未暫停的 Deployment 的唯一區別是,Deployment 處於暫停狀態時, PodTemplateSpec 的任何修改都不會觸發新的上線。 Deployment 在建立時是預設不會處於暫停狀態。

相關文章