1. 程式人生 > 其它 >k8s叢集StatefulSets的Pod優雅排程問題思考?

k8s叢集StatefulSets的Pod優雅排程問題思考?

k8s叢集StatefulSets的Pod優雅排程問題思考

考點之你能解釋一下為什麼k8s的 StatefulSets 需要VolumeClaimTemplate嘛?
考點之簡單描述一下StatefulSets 對Pod的編排排程過程?
考點之針對線上StatefulSet 的Pod縮容故障無法正常縮容的情況,你能灰度分析一下嘛?
考點之聊聊什麼是StatefulSet的分割槽滾動更新吧?什麼場景需要使用分割槽更新?
考點之StatefulSet提供優雅穩定的儲存,但是線上告警StatefulSet Pod重新排程後資料丟失?

囧麼肥事-胡說八道

你能解釋一下為什麼k8s的 StatefulSets 需要VolumeClaimTemplate嘛?

對於k8s叢集來說有狀態的副本集都會用到持久儲存

Deployment中的Pod template裡定義的儲存卷,是基於模板配置排程所有副本集共用一個儲存卷,資料是相同的。

StatefulSet職責是管理有狀態應用,所以它管理的每個Pod都要自已的專有儲存卷,它的儲存卷就不能再用Pod模板來建立。

所以 StatefulSets 需要一種新方式來為管轄的Pod分配儲存卷。

就這樣VolumeClaimTemplate來了,k8sStatefulSets 設定了VolumeClaimTemplate,也就是卷申請模板

說了為什麼需要它,那麼VCT到底是什麼呢?

VolumeClaimTemplate

:基於靜態或動態地PV供給方式為Pod資源提供專有且固定的儲存,它會為每個Pod都生成不同的PVC,並且繫結PV,實現每個Pod都有自己獨立專用的儲存卷。

簡單描述一下StatefulSets 對Pod的編排排程過程?

StatefulSets 提供了有序且優雅的部署和擴縮保證

SS是如何優雅部署和擴縮的呢?

對於包含 N 個 副本的 StatefulSet

當部署 Pod 時,它們是依次建立的,順序為 `0..N-1`。

當刪除 Pod 時,它們是逆序終止的,順序為 `N-1..0`。

在將縮放操作應用到 Pod 之前,它前面的所有 Pod 必須是 Running 和 Ready 狀態。

在 Pod 終止之前,所有的繼任者必須完全關閉

建立或擴容過程,以Nginx舉例

定義副本數replicas=3

SS會建立3個Pod
分配有序序號
ng-0, ng-1, ng-2

SS嚴格執行部署或排程順序,按序部署
ng-0 開始部署...
ng-0 進入Running 和 Ready 狀態

SS 檢測 ng-0 部署狀態
確定ng-0,符合Running 和 Ready 狀態

ng-1 開始部署
ng-1 進入Running 和 Ready 狀態

SS 檢測 ng-0 和 ng-1 部署狀態
確定ng-0 和 ng-1 都符合Running 和 Ready 狀態
才會執行 ng-2 部署

假設此時 ng-0 發生故障
那麼ng-2 會阻塞,等待 ng-0 重新部署完成

ng-2 開始部署
ng-2 進入Running 和 Ready 狀態

類似,StatefulSet 進行縮容跟擴容整體規則是一樣的,只不過縮容時,終止順序和建立順序相反

按照 ng-2, ng-1, ng-0 的順序進行縮容操作。ng-2沒有完全停止和刪除前,ng-1不會進行終止操作。

注意:如果SS在縮容過程中,有些Pod發生了故障,那麼終止會進入阻塞,等待發生故障的Pod重新排程,進入Running和Ready狀態之後才會繼續執行SS縮容。

針對線上StatefulSet 的Pod縮容故障無法正常縮容的情況,你能灰度分析一下嘛?

為什麼縮容無法正常執行?

StatefulSet 執行縮容操作,需要保證管轄範圍內的Pod處於健康狀態。如果某些Pod發生故障,則縮容會陷入阻塞,無法繼續執行。

僅當 StatefulSet 等待到所有 Pod 都處於運Running和 Ready 狀態後才可繼續進行縮容操作。

瞭解完為什麼縮容無法執行,那麼再聊聊可能導致無法正常縮容原因都有哪些?

如果 spec.replicas 大於 1,Pod副本數量大於1 ,Kubernetes 無法直接判定 Pod 不健康的原因。

Pod 不健康可能是由於永久性故障造成也可能是瞬態故障

永久性故障

如果該 Pod 不健康是由於永久性故障導致,則在不糾正該故障的情況下進行縮容可能會導致 StatefulSet 成員 Pod 數量低於應正常執行的副本數。這種狀態也許會導致 StatefulSet 不可用。

瞬態故障

瞬態故障可能是節點升級或維護而引起的節點重啟造成的。

如果由於瞬態故障而導致 Pod 不健康,一般情況下,Pod 最終會再次變為可用,但是瞬態錯誤也可能會干擾 你對 StatefulSet 的擴容/縮容操作。

一些分散式資料庫在同時有節點加入和離開時會遇到問題。

在這些情況下,最好是在應用級別進行分析擴縮操作的狀態,並且只有在確保 Stateful 應用的叢集是完全健康時才執行擴縮操作。

聊聊什麼是StatefulSet的分割槽滾動更新吧?什麼場景可以使用分割槽更新?什麼情況分割槽更新會失效?

先說一下StatefulSet的更新策略

StatefulSet.spec.updateStrategy 欄位可以配置和禁用掉自動滾動更新 Pod 的容器、標籤、資源請求或限制、以及註解。

spec.updateStrategy 有兩個允許的值:RollingUpdateOnDelete

RollingUpdate 更新策略

對 StatefulSet 中的 Pod 執行自動的滾動更新。這是預設的更新策略

OnDelete更新策略

StatefulSet 將不會自動更新 StatefulSet 中的 Pod

當StatefulSet 的 .spec.template 設定出現變動
使用者必須手動刪除 Pod 以便讓控制器建立新的 Pod

滾動更新

StatefulSet.spec.updateStrategy.type 被設定為 RollingUpdate 時, 屬於預設滾動更新策略,這個時候如果template發生變化,StatefulSet 控制器會自動發起排程,進行刪除和重建 StatefulSet 中的每個 Pod。 它將按照與 Pod 終止相同的順序(從最大序號到最小序號)進行,每次更新一個 Pod。

Kubernetes 控制面會等到被更新的 Pod 進入 Running 和 Ready 狀態,然後再更新其前身Pod。

如果你設定了 .spec.minReadySeconds(最短就緒秒數),控制面在 Pod 就緒後會額外等待一定的時間再執行下一步。

接下來進入主題什麼是分割槽滾動更新?

分割槽滾動更新是滾動更新策略中的一個特殊場景,StatefulSet 控制一定範圍內的Pod進行滾動更新,排程為新版本Pod執行,而範圍外的Pod繼續維持老版本執行。

可以理解為,學校16個班級,校長通知說:"今天最後5個班級留下來打掃衛生"

通過宣告 .spec.updateStrategy.rollingUpdate.partition 的方式,RollingUpdate 更新策略可以實現分割槽。

如果聲明瞭一個分割槽,當 StatefulSet 的 .spec.template 被更新時

所有序號大於等於該分割槽序號的 Pod 都會被更新
所有序號小於該分割槽序號的 Pod 都不會被更新

分割槽更新,就是進行分段處理

假設原來有5個Pod
ng-0
ng-1
ng-2
ng-3
ng-4

SS滾動更新
ng-4 更新
ng-3 更新
ng-2 更新
ng-1 更新
ng-0 更新

如果指定 partition=2
那麼SS執行滾動更新時
ng-4 更新
ng-3 更新
ng-2 更新
ng-1 不更新
ng-0 不更新

需要注意的是,分割槽範圍外的Pod,即使他們被刪除或是重新排程,也會依據之前的舊版本進行重建,不會依賴當前最新版本重建。

此外,如果 StatefulSet 的 .spec.updateStrategy.rollingUpdate.partition 大於它的 .spec.replicas,對它的 .spec.template 的更新將不會傳遞到它的 Pod,此時所謂分割槽更新將失去意義。

分割槽更新應用場景?

在大多數情況下,你不需要使用分割槽,但如果你希望進行階段式更新、執行金絲雀或執行分階段上線,則分割槽更新會非常有用。

StatefulSet提供優雅穩定的儲存,但是線上告警StatefulSet Pod重新排程後資料丟失?

究竟是什麼情況呢?

我們都知道k8s中當 StatefulSet 或者它管理的 Pod 被刪除時並不會刪除關聯的卷,當重新排程完成後,新Pod應該會掛載原PV,繼續使用上一個Pod的資料。

壞事來了,本應該繼續使用原PV,皆大歡喜,可是線上告警發現PV 持久卷無法使用,導致資料丟失。咦,失聯了???

k8s刪除 StatefulSet 管理的 Pod 並不會刪除關聯的PV卷,這是為了確保你有機會重新排程Pod之後繼續使用原PV卷,或者在刪除卷之前從卷中複製資料,保證資料不會丟失。當一個 Pod 被排程(重新排程)到節點上時,它的 volumeMounts 會掛載與其 PVC相關聯的 PV。

刪除StatefulSet 和Pod雖然不會刪除關聯的PV卷,但是刪除PVC就不一定了,問題就出現在這裡,在 Pod 離開終止狀態後刪除 PVC ,可能會觸發刪除背後的 PV 持久卷,具體觸發策略要取決配置的儲存類和回收策略。

警告:⚠️ 永遠不要假定在 PVC 刪除後仍然能夠訪問卷

警告:⚠️ 刪除 PVC 時要謹慎,因為這可能會導致資料丟失

獲取更多幹貨(MySQL、K8S),歡迎關注微信公眾號:囧麼肥事