1. 程式人生 > 其它 >k8s叢集StatefulSets的Pod排程查詢丟失問題?

k8s叢集StatefulSets的Pod排程查詢丟失問題?

k8s叢集StatefulSets的Pod排程查詢丟失問題?

考點之簡單介紹下StatefulSets 和 Deployment 之間有什麼本質區別?特定場景該如何做出選擇呢?
考點之你能辯證的說說看StatefulSets 和 Deployment具體有哪些區別嘛?
考點之你瞭解k8s叢集StatefulSets的Pod排程查詢丟失問題嗎?k8s叢集中StatefulSet管理的Pod已經完成排程並啟動,為什麼還是無法查詢Pod 的 DNS 命名?

囧麼肥事-胡說八道

簡單介紹下StatefulSets 和 Deployment 之間有什麼本質區別?

首先、StatefulSet

Deployment 都是用來管理應用的工作負載 API 物件,都管理基於各自相同容器規約的一組 Pod,同時負責各自管理的Pod 集合的部署和擴縮、更新回滾等。

但和 Deployment 本質上不同的是,StatefulSets 用來管理有狀態應用,而Deployment 負責管理無狀態應用

如果應用程式不需要任何穩定的識別符號或有序的部署、刪除或伸縮,則應該使用 由一組無狀態的副本控制器提供的工作負載來部署應用程式,比如 Deployment或者ReplicaSet

如果希望使用儲存卷為工作負載提供持久儲存,可以使用 StatefulSet 作為解決方案的一部分。

儘管 StatefulSet 中的單個 Pod 仍可能出現故障, 但持久的 Pod 識別符號

可以更容易將現有卷與於重新排程的Pod進行繫結。

說道這裡,下面簡單介紹一下,應用分類:

應用通常可以分為兩大類:有狀態與無狀態

無狀態應用

簡單理解就是沒有特殊狀態的服務

服務和資料分離,本身不儲存資料

各個請求對於伺服器來說統一無差別處理

請求可以隨機發送到任意一臺server上

請求自身攜帶了所有服務端所需要的所有引數

服務自身不儲存跟請求相關的任何資料

有狀態應用

容器資料需要持久化保持

對於有資料儲存功能的服務

每個例項都需要有自己獨立的持久化儲存

或者指多執行緒型別的服務、佇列

mysql資料庫、kafka、zookeeper等

如果server是有狀態的,客戶端需要始終把請求發到同一臺server才行,

同時,這裡理解StatefulSets 兩個關鍵點:1、穩定的 2、有序的

“穩定的”意味著 Pod 排程或重排程的整個過程是有永續性的
“有序的”意味著 Pod 排程或重排程的整個過程是需要保持順序的

關於Deployment 的具體情況,可參考:【跟k8s工作負載Deployments的緣起緣滅】

你能辯證的說說看StatefulSets 和 Deployment具體有哪些區別嘛?

Deployment管理的Pod特點

Deployment被設計用來管理無狀態服務的pod,每個pod完全一致

  • 無序性:無狀態服務的多個Pod副本建立和銷燬是無序的,可以並行建立或銷燬,相互之間不必等待,除了需要遵守規約中定義的副本個數之外,沒有其他制約。
  • 隨機性:無狀態服務的多個Pod副本的名稱是隨機的,pod被重新啟動排程後,它的名稱與IP都會發生變化,替換為一個新的副本。
  • 共享性:無狀態服務的多個Pod副本共享儲存卷。Deployment中Pod基於template定義儲存卷,所有副本集共用一個儲存卷。

StatefulSets管理的Pod特點

StatefulSets 被設計用來管理有狀態的應用,StatefulSet 管理的 Pod 具有唯一的標識,該標識包括順序標識、穩定的網路標識和穩定的儲存。 並且該標識和 Pod 是繫結,不管它被排程在哪個節點上,最終都會被繫結這個唯一標識

  • 唯一性:對於具有 N 個副本的 StatefulSet,它管理的每個 Pod 將被分配一個整數序號,該序號在 StatefulSet 上是唯一的
  • 順序性:順序標識、Pod 排程過程,無論是啟動、銷燬、更新都需要嚴格遵守順序。有序優雅的部署和縮放,有序自動的滾動更新
  • 穩定的網路標識:Pod主機名、DNS地址不會隨著Pod被重新排程而發生變化。
  • 穩定的持久化儲存:Pod被重新排程後,不會刪除原有的PV,重新排程成功後,繼續掛載繫結原有的PV,從而保證了資料的完整性和一致性。

你瞭解過k8s叢集StatefulSets的Pod排程查詢丟失問題嗎?

k8s叢集中StatefulSet管理的Pod已經完成排程並啟動,為什麼還是無法查詢Pod 的 DNS 命名?如果需要在 Pod 排程完成之後及時發現,該怎麼做?

先看看StatefulSet是如何為每個Pod分配DNS的呢?

StatefulSet 中管理的每個 Pod 會根據 StatefulSet 的名稱和 以及為 Pod 的分配的有序索引(序號),派生出它的主機名。

組合主機名的格式為:

$(StatefulSet 名稱)-$(序號)

StatefulSet 使用 Headless Services 控制內部 Pod 的網路域。

通過Headless Service為Pod編號,在DNS伺服器中生成帶有編號的DNS記錄,從而可以達到通過Pod名字定位到相應的服務

管理域的服務的格式為:

$(服務名稱).$(名稱空間).svc.cluster.local

其中 cluster.local 是叢集域。 一旦每個 Pod 建立成功,就會得到一個匹配的 DNS 子域,格式為: $(pod 名稱).$(所屬服務的 DNS 域名),其中所屬服務由 StatefulSetserviceName 域來設定。

瞭解完分配和組成,接下來說一下為什麼會出現查詢失敗的情況呢?

第一種情況,Pod尚在建立過程中,這時候查詢,DNS命名還未分配成功

第二種情況,Pod已經建立成功,取決於叢集域內部 DNS 的配置,可能無法查詢一個剛剛啟動的 Pod 的 DNS 命名。原因是k8s有個負快取的概念。

負快取 (在 DNS 中較為常見)

之前失敗的查詢結果會被記錄和重用至少若干秒鐘

預設快取時長為 30s

查詢過程

第一次查詢結果是失敗
結果記錄到負快取中,標註失敗

在快取週期內查詢,直接從負快取中取,結果是失敗

如何及時發現建立的Pod的DNS命名?

如果需要在 Pod 被建立之後及時發現它們,有以下選項:

  • 直接查詢 Kubernetes API(比如,利用 watch 機制)而不是依賴於 DNS 查詢
  • 縮短 Kubernetes DNS 驅動的快取時長(修改 CoreDNSConfigMap,目前DNS快取時長為 30 秒)