當前位置:
首頁 > 知識 > Deployment和StatefulSet的使用理念和區別

Deployment和StatefulSet的使用理念和區別

2018上海KubeCon

理論上的區別

StatefulSet作為Kubernetes中部署應用的控制器之一,它被專門用於部署那些有狀態和有持久化需求的應用,同時,它也遵循一些指定的規則。另一方面,我們熟知的Deployment也是做相似的事情。除了Kubernetes 文檔中非常明確的指出:」如果應用不需要穩定的標識或者有序的部署,刪除和縮放,你應該使用無狀態的副本控制器部署你的應用,這些無狀態的副本控制器(例如:Deployment,ReplicaSet)或許更適合你應用的無狀態需求」。

If an application doesn』t require any stable identifiers or ordered deployment, deletion, or scaling, you should deploy your application with a controller that provides a set of stateless replicas. Controllers such as Deployment or Replica Set may be better suited to your stateless needs.

上面已經說明了StatefulSet和stateless replicas之間的區別,接下來,我們仔細看看:

從上面的表格可以非常有底氣的假設兩者之間最大的區別在於網路服務的要求和StatefulSet的持久化存的儲示例文檔。但是,眼睛看到的不一定就是全部。

StatefulSet在實踐中的總結

StatefulSets的要求是滿足Pod所需要的網路身份,為達到這個要求,一個標準的Kubernetes svc 需要根據selectorapp(用戶在標籤中定義的Key)來部署,以此來滿足StatefulSet的邏輯映射(邏輯映射指的是svc通過selector來選擇對應Label的Pod),接下來,我使用Postgres應用來作為示例。

以下Yaml文件定義了pgnet的Kubernetes svc,暴露的埠是:5432,定義的埠名字是:pgport,在這種情況下發布的類型是clusterIP,這意味著這個Postgres服務只能在Kubernetes集群內部訪問。但是這個ClusterIP的值是:None,這意味著不會預定義IP,如果需要讓外部也能訪問到Postgres服務,我們可以查看文檔了解如何在Kubernetes之外和外部網路上公開訪問它。這其中非常重要的部分是selector,它需要匹配被部署為StatefulSet的app的標籤。

StatefulSet的配置與Deployment非常相似,配置中的serviceName必須與上面創建的svc相匹配,容器也需要一致的埠,環境變數,volumeMounts等。

StatefulSet的配置與Deployment的配置相比,也有幾處獨特之處。

從使用kubectl命令看到StatefulSet所管控的Pod的名字似乎遵從特有的規則,這點我們放在後面討論.

掛載卷部分和Deployment中的容器相似,容器上定義的volumeMounts的名字和volumeClaimTemplates存在邏輯映射(之間的映射是根據name,在下面的配置中,我們可以著重看volumeMounts和volumeClaimTemplates部分).

鑒於Deployment可以使用StorageClass或者預定義好PersistentVolume,StatefulSet也可以預定義StorageClass實現動態掛載Volume,。我們可以在sc.yaml看到相關示例。

一旦部署了StatefulSet,它會依照名稱規則來顯示名字,在這個Pod示例中,名稱為pgdatabase的Pod會基於副本的數量有序排列(從小到大),而Deployment會以多個隨機字元來保證Pod名稱的唯一性,也就說Deployment控制的Pod名稱是隨機無序的,在名稱上另一個區別是:當刪除一個Pod後,Deployment會創建一個新Pod,且這個Pod的名字和之前的Pod名字是不一樣的,是一個隨機生成的新名字,相反,StatefulSet仍然沿用上一個Pod的名字和屬性創建新的Pod,它以這種方式來保證所管控Pod的名字具有唯一性、有序性和一致性。

另一個有趣的事情是刪除Pod的時候,在Deployment中,Pod可能會重新調度在集群中的其他節點,至於會調度到那個節點,這個由調度器說了算;而在StatefulSet中,他會在之前運行的、相同的節點上重新創建(有點像落地生根),這個是有StatefulSet的默認屬性決定的,這是因為StatefulSet認為沒有任何理由需要從Node上強行刪除Pod,Kubernetes假設以StatefulSet運行的應用程序需要穩定的網路標識和穩定的存儲,並且同一Pod有多個實例可能會導致數據損壞;如果某個節點/主機需要維護而關閉或者網路不可達,那麼Pod會進入 「Unknown」 或者 「Terminating」 狀態,但即使在這種情況下,Pod也不會重新調度到其他節點上(是不是很頭鐵),除非以手動的方式刪除Node對象或手動刪除Pod對象且此時原本的Node不可調度或不可用,與此同時,不響應節點上的kubelet進程開始殺死Pod並在apiServer中刪除對應的Pod條目,或者強行刪除Pod,當然,強行刪除會導致volume(掛載卷)未被正確卸載且重新調度Pod失敗。

他們之間的異同

當閱讀了StatefulSet的高可用性實踐後,Deployment似乎能更好的完成工作,那為什麼還推薦使用StatefulSet作為持久化應用的部署方法呢?是因為Kubernetes不希望Pod能夠在另外一個節點上立即重啟來增加腦裂(split-brain))情況的出現,如果存儲提供者有能力的話,pod.Spec.TerminationGracePeriodSeconds這個配置項可以配置在StatefulSet中,同時,Controller能夠在當前主機變為「Unknown」之前,在新的主機上自動重啟一個Pod,持久卷的volumeClaimTemplates用來確保跨組件重新啟動後仍然能夠保證正確的狀態,我們假設現在集群中正發生這樣的災難,因為Kubernetes支持本地存儲(host),如果存儲的數據未在節點間相互複製/同步或者集中於某一處,除非這個節點再次上線,否則你沒有其他方法安全的還原數據。

實驗論證

StatefulSet所管控的Pod的名字遵循何種規則?

StatefulSet所管控的Pod的名字遵循stsname-,同時保證唯一性,絕不重複,有序性,中間以-分割;名字中編號遵從如下規則:

另一方面,當你使用kubectl exec -it podname進入容器後,再執行echo $HOSTNAME命令 你會發現hostname的值與pod name是完全一致的。

為什麼說StatefulSet是有序,優雅的部署和擴展(縮放)?

StatefulSet在做任何操作的時候,都會遵循有序這個前提。

在部署的時候,他會遵從順序一個接一個的部署,如果中途有一個Pod沒有達到Running狀態,他也會hang在哪兒,直到當前Pod達到Running狀態,才會創建下一個Pod。

在擴容的時候,編號小的Pod沒有達到Running的狀態,它不會增加下一個Pod,也就說它會死等。

在縮容的時候,是編號值大的Pod會先被刪除,接下來才會刪除編號小的Pod,直到達到期望值才停止。

再次擴容到3個Pod會發現,相同Pod的名字仍然會綁定到相同的Node節點

通過以上實驗證明了StatefulSet是如何有序,優雅的進行部署和擴展。

Headless Service是如何工作的?StatefulSet是如何處理持久化存儲的?

在StatefulSet中我們有多種掛載數據捲來達到持久化存儲的目地,例如:

接下來,我們主要是對第二種方式進行探討:

在StatefulSet的配置模板中,有項關於volumeClaimTemplates的配置,這個配置是後續創建pvc的模板,在模板中,我們通常會聲明模板名字(例如:mysql),但是在PVC真正被創建時,被創建的pvc的名稱和pvc模板名字有所區別,真正創建pvc的名字遵循如下規則:

例如pvc模板名字是mysql,statefulset的名稱是master,那麼Statefulset所管控的pod名字是master-0,而生成的pvc名字是mysql-master-0。

另一方面值得注意的是:如果pod和pvc綁定在了一起,那麼他們編號往往是相同的(例如名為master-0的Pod綁定的pvc名字一定是mysql-master-0),且即使pod被刪除重建後,他們倆仍然會綁定在一起(頗有不離不棄,生死相依的感覺),出現這一情況的原因是:被創建的pod名字仍然是上一個被刪除Pod的名字,Pod的名字保持了不變,那麼該Pod選擇的pvc名字也就不會改變,也就是說名字,是名字的選擇讓他們在一起了,另外,他們看似生死相依,但是有一點例外,當Statefulset所管控的Pod被刪除後且還沒來及重建,在這段時間差里,剛好,有另外一個Pod綁定了這個名為:mysql-master-0的pvc,且這個pvc不支持多個Pod/host綁定,這會發生什麼呢?想想都刺激。對於pvc有哪幾種方式綁定pv的呢,我們可以留在後面再說。另外,值得推薦張磊的《深入剖析Kubernetes》,講的非常透徹,即使有什麼不懂的也可以在文後留言,回復速度也非常快速且有耐心。

參考文檔:

[1] Technical Dive into StatefulSets and Deployments in Kubernetes https://blog.thecodeteam.com/2017/08/16/technical-dive-statefulsets-deployments-kubernetes/

作者: yulibaozi


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 容器時代 的精彩文章:

TAG:容器時代 |