跟k8s工作負載Deployments的緣起緣滅

跟k8s工作負載Deployments的緣起緣滅

考點之簡單介紹一下什麼是Deployments吧?
考點之怎麼查看 Deployment 上線狀態?
考點之集群中能不能設置多個Deployments控制器具有重疊的標籤選擇器?
考點之可以自定義Pod-template-hash 標籤嘛?如果可以,有什麼好處?如果不可以,有什麼危害?
考點之什麼場景下會觸發Deployments上線動作?
考點之Deployments在更新時會關閉所有Pod嘛?如果不是,默認關閉最大比例是多少?
考點之你能不能簡單描述一下Deployments更新時RS和Pod是如何滾動更新的?
考點之如何判定Deployment上線過程是否出現停滯?有哪些原因會造成停滯?如何解決配額不足的問題?
考點之保存修訂歷史會消耗 etcd 中的資源,並佔用 `kubectl get rs` 的輸出,如果給修訂歷史限制值設置為0是不是就能有效解決這個問題?

囧么肥事-胡說八道

考點之簡單介紹一下什麼是Deployments吧?

Deployments是k8s內置的工作負載之一,主要作用是幫助我們管理無狀態Pod

一個 Deployment 為 Pods 和 ReplicaSets 提供了聲明式的更新能力,我們只需要負責描述 Deployment 中的RS和Pod需要達到的目標狀態,那麼DM就會以一種受控速率去幫助我們更改RS和Pod的實際狀態, 使其變為我們期望出現的狀態。

Deployment 很適合用來管理你的集群上的無狀態應用Deployment 認為所有的 Pod 都是相互等價的,在需要的時候都是可以替換的。

Deployment: "小Pod 們,都給我聽話"
DM: "你們都不是唯一的"
DM: "不聽話,鬧事的Pod"
DM: "隨時可以讓你走人"
DM: "大把的Pod可以替換你們"

Pods: "是是是,我們一定聽話"

Deployment 是一個實幹主義者,你如果好好工作,不鬧事,那麼一切OK,但是如果你有小心思,敢鬧事,那它隨時可以趕你走人,隨時隨地可以招新人。

考點之怎麼查看 Deployment 上線狀態?

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

利用kubectl rollout status 命令可以監視 Deployment 的進度。

假設創建了一個Nginx的DM,查看DM進度。

kubectl rollout status deployment/nginx-deployment

哪些場景會讓Deployment 進入這三種狀態呢?

為了方便,後續DM均代表Deployment

進行中(Progressing)

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

- DM創建新的 `ReplicaSet`
- DM正在為最新的 `ReplicaSet` 執行擴容操作
- DM 正在為舊的 `ReplicaSet`執行縮容操作
- 新的 Pods 已經就緒或者可用(就緒至少持續了 `MinReadySeconds` 秒)

完成(Complete)

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

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

失敗的(Failed)

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

- 配額(Quota)不足
- 就緒探測(Readiness Probe)失敗
- 鏡像拉取錯誤
- 權限不足
- 限制範圍(Limit Ranges)問題
- 應用程序運行時的配置錯誤

考點之集群中能不能設置多個Deployments控制器具有重疊的標籤選擇器?

首先答案肯定是不能的。

如果這樣做,後果是什麼呢?如果有多個控制器的標籤選擇器發生重疊,則控制器之間會因衝突而無法正常工作。

另一篇已經討論類似問題:線上預警k8s集群循環創建、刪除Pod副本,一直無法穩定指定目標副本數量?如果排除了是Pod內部發生了故障,從RS角度你猜測可能是什麼原因?

上一篇主要說明的是多個ReplicaSets 配置了相同的標籤選擇符,使用相同的標籤選擇器創建多個ReplicaSet,則多個RS無法識別哪個Pod是自己創建的,都會認為是歸屬於自己管理的Pod。這樣做的後果就是會造成Pod被競爭接管的情況,導致Pod副本數量一直無法穩定。

我們知道 DeploymentPodsReplicaSets 提供了聲明式的更新能力,主要管控的是RS和Pods。

Kubernetes 不會阻止你去給設置重疊的標籤選擇器,但是既然RS和Pods會出現因為競爭克制引發的管理衝突情況,那麼身為他們倆的管理者DM肯定是不能獨善其身,一定會受到影響的。

那麼為了不出現管理衝突,我們應該怎麼做呢?

必須在 Deployment 中指定適當的標籤選擇器和 Pod 模板標籤,同時標籤或者標籤選擇器不要與其他控制器(包括其他 DeploymentStatefulSet)重疊。

考點之可以自定義Pod-template-hash 標籤嘛?如果可以,有什麼好處?如果不可以,有什麼危害?

k8s官方說明: 不要更改此標籤

k8s官方直接明確的告訴我們,不要自定義Pod-template-hash 標籤,那麼為什麼呢?憑什麼就不能自定義?

Deployment 控制器會將自己創建或者管理的每一個ReplicaSet 身上都標註Pod-template-hash 標籤。

唯一的目的就是利用這個標籤確保 Deployment 的子 ReplicaSets 不重疊

注意DeploymentReplicaSet 的名稱始終被格式化[Deployment名稱]-[隨機字符串]

其中隨機字符串是使用 pod-template-hash 作為種子隨機生成的。

通過對 ReplicaSet 的 PodTemplate 進行哈希處理,所生成的哈希值被添加到 ReplicaSet 的標籤選擇器、Pod 模板標籤,以及RS中的每個Pod身上。

疑問來了,自定義有什麼危害呢?

上面說了,這個標籤主要是作為名稱隨機,確保不重疊,隨機到每一個Pod和RS上,可以避免出現多個Deployments控制器具有重疊的標籤選擇器。也就是上面說的那個競爭排斥問題。

考點之什麼場景下會觸發Deployments上線動作?

僅當 Deployment Pod 模板(即 .spec.template)發生改變時,例如模板的標籤或容器鏡像被更新, 才會觸發 Deployment 上線。

其他更新(如對 Deployment 執行擴縮容的操作)不會觸發上線動作。

考點之Deployments在更新時會關閉所有Pod嘛?如果不是,默認關閉最大比例是多少?

Deployment 可確保在更新時僅關閉一定數量的 Pod。

默認情況下,它確保至少所需 Pods 75% 處於運行狀態(maxUnavailable最大不可用比例為 25%)。

如果有100個Pod,在更新時,最多關閉25個Pod

DM 保證至少會有75個Pod能正常提供服務

Deployment 還確保所創建 Pod 數量只可能比期望 Pods 數高一點點。

默認情況下,它可確保啟動的 Pod 個數比期望個數最多多出 25%(最大峰值 25%)。

DM 更新會出現兩種操作
1、銷毀老版本Pod
2、創建新版本Pod

無論是銷毀還是創建
默認峰值都是25%

銷毀時,最多同時銷毀25%Pod
保證有75%的Pod可以繼續提供服務

創建時,最多運行比預期副本數多出25%

也就是說如果預期存活Pod副本是100個
那麼最多允許同時在運行125箇舊版副本+新版副本

考點之你能不能簡單描述一下Deployments更新時RS和Pod是如何滾動更新的?

如果不去更改默認的最大不可用比例和最大運行峰值比例,那麼DM更新時,會創建新版本RS,並將其進行擴容,控制到Pod副本數量滿足最大運行峰值比例

達到比例後,DM會停止新版RS擴容,不會再創建新版Pod,直到DM殺死足夠多的舊版Pod

接下來對舊版本RS進行縮容操作,控制去除Pod副本數量滿足最大不可用比例

同樣,達到比例後,DM會停止舊版RS刪除,不會再繼續刪除舊版Pod,直到DM創建到足夠多的新版Pod

此為一輪更新,DM不斷的進行滾動更新上述操作,直到舊版RS,舊版Pod副本數為0,新版副本數穩定,停止滾動更新。

考點之如何判定Deployment上線過程是否出現停滯?有哪些原因會造成停滯?如何解決配額不足的問題?

Deployment 可能會在嘗試部署最新的 ReplicaSet 時出現故障,一直處於未完成的停滯狀態。

造成此情況一些可能因素如下:

- 配額(Quota)不足
- 就緒探測(Readiness Probe)失敗
- 鏡像拉取錯誤
- 權限不足
- 限制範圍(Limit Ranges)問題
- 應用程序運行時的配置錯誤

如何判定Deployment上線過程是否出現停滯?

檢測此狀況的一種方法是在 Deployment 規約中指定截止時間參數.spec.progressDeadlineSeconds

一旦超過 Deployment 進度限期,Kubernetes 將更新DM狀態和進度狀況的原因:

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

通過 Deployment 狀態,就能知道是否出現停滯。你可以使用 kubectl rollout status 檢查 Deployment 是否未能取得進展。 如果 Deployment 已超過進度限期,kubectl rollout status 返回非零退出代碼。

判斷停滯,這時候我們可以在上線過程中間安全地暫停 Deployment ,對其進行上線修復

假設排查出停滯原因是配額不足,直接在命名空間中增加配額 來解決配額不足的問題。

配額條件滿足,Deployment 控制器完成了 Deployment 上線操作, Deployment 狀態會更新為成功狀況(Status=True and Reason=NewReplicaSetAvailable

考點之保存修訂歷史會消耗 etcd 中的資源,並佔用 kubectl get rs 的輸出,如果給修訂歷史限制值設置為0是不是就能有效解決這個問題?

.spec.revisionHistoryLimit 是一個可選字段,用來設定為回滾操作所備份保留的舊 ReplicaSet 數量。

這些舊 ReplicaSet 會消耗 etcd 中的資源,並佔用 kubectl get rs 的輸出。

每個 Deployment 修訂版本的配置都存儲在其 ReplicaSets 中;

因此,一旦刪除了舊的 ReplicaSet將失去回滾到 Deployment 的對應修訂版本的能力

默認情況下,系統保留 10 箇舊 ReplicaSet,但其理想值取決於新 Deployment 的頻率和穩定性。

如果給修訂歷史限制值設置為0,將導致 Deployment 的所有歷史記錄被清空。沒有了歷史備份,因此 Deployment 將無法回滾,無法撤消新的 Deployment 上線。

總結:雖然可以減少etcd的資源消耗,但是不利於k8s集群實現故障容錯、高可用。為了節約一些資源,而放棄容錯,高可用性質,只能說,非常非常非常,不值得。