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 識別符號
說道這裡,下面簡單介紹一下,應用分類:
應用通常可以分為兩大類:有狀態與無狀態
無狀態應用
簡單理解就是沒有特殊狀態的服務
服務和資料分離,本身不儲存資料
各個請求對於伺服器來說統一無差別處理
請求可以隨機發送到任意一臺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 域名)
,其中所屬服務由 StatefulSet
的 serviceName
域來設定。
瞭解完分配和組成,接下來說一下為什麼會出現查詢失敗的情況呢?
第一種情況,Pod尚在建立過程中,這時候查詢,DNS命名還未分配成功
第二種情況,Pod已經建立成功,取決於叢集域內部 DNS 的配置,可能無法查詢一個剛剛啟動的 Pod 的 DNS 命名。原因是k8s有個負快取的概念。
負快取 (在 DNS 中較為常見)
之前失敗的查詢結果會被記錄和重用至少若干秒鐘
預設快取時長為 30s
查詢過程
第一次查詢結果是失敗
結果記錄到負快取中,標註失敗
在快取週期內查詢,直接從負快取中取,結果是失敗
如何及時發現建立的Pod的DNS命名?
如果需要在 Pod 被建立之後及時發現它們,有以下選項:
- 直接查詢
Kubernetes API
(比如,利用watch
機制)而不是依賴於 DNS 查詢 - 縮短
Kubernetes DNS
驅動的快取時長(修改CoreDNS
的ConfigMap
,目前DNS快取時長為 30 秒)