本篇文章給大家分享的是有關(guān)怎樣淺析Kubernetes StatefulSet,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)專業(yè)IDC數(shù)據(jù)服務(wù)器托管提供商,專業(yè)提供成都服務(wù)器托管,服務(wù)器租用,內(nèi)蒙古服務(wù)器托管,內(nèi)蒙古服務(wù)器托管,成都多線服務(wù)器托管等服務(wù)器托管服務(wù)。
“Deployment用于部署無狀態(tài)服務(wù),StatefulSet用來部署有狀態(tài)服務(wù)”。
具體的,什么場(chǎng)景需要使用StatefulSet呢?官方給出的建議是,如果你部署的應(yīng)用滿足以下一個(gè)或多個(gè)部署需求,則建議使用StatefulSet。
穩(wěn)定的、唯一的網(wǎng)絡(luò)標(biāo)識(shí)。
穩(wěn)定的、持久的存儲(chǔ)。
有序的、優(yōu)雅的部署和伸縮。
有序的、優(yōu)雅的刪除和停止。
有序的、自動(dòng)的滾動(dòng)更新。
穩(wěn)定的主要是針對(duì)Pod發(fā)生re-schedule后仍然要保持之前的網(wǎng)絡(luò)標(biāo)識(shí)和持久化存儲(chǔ)。這里所說的網(wǎng)絡(luò)標(biāo)識(shí)包括hostname、集群內(nèi)DNS中該P(yáng)od對(duì)應(yīng)的A Record,并不能保證Pod re-schedule之后IP不變。要想保持Pod IP不變,我們可以借助穩(wěn)定的Pod hostname定制IPAM獲取固定的Pod IP。借助StatefulSet的
穩(wěn)定的唯一的網(wǎng)絡(luò)標(biāo)識(shí)
特性,我們能比較輕松的實(shí)現(xiàn)Pod的固定IP需求,然后如果使用Deployment,那么將會(huì)復(fù)雜的多,你需要考慮滾動(dòng)更新的過程中的參數(shù)控制(maxSurge、maxUnavailable)、每個(gè)應(yīng)用的IP池預(yù)留造成的IP浪費(fèi)等等問題。
因此,我想再加一個(gè)StatefulSet的使用場(chǎng)景:
實(shí)現(xiàn)固定的Pod IP方案, 可以優(yōu)先考慮基于StatefulSet;
StatefulSet對(duì)應(yīng)Pod的存儲(chǔ)最好通過StorageClass來動(dòng)態(tài)創(chuàng)建:每個(gè)Pod都會(huì)根據(jù)StatefulSet中定義的VolumeClaimTemplate來創(chuàng)建一個(gè)對(duì)應(yīng)的PVC,然后PVS通過StorageClass自動(dòng)創(chuàng)建對(duì)應(yīng)的PV,并掛載給Pod。所以這種方式,需要你事先創(chuàng)建好對(duì)應(yīng)的StorageClass。當(dāng)然,你也可以通過預(yù)先由管理員手動(dòng)創(chuàng)建好對(duì)應(yīng)的PV,只要能保證自動(dòng)創(chuàng)建的PVC能和這些PV匹配上。
為了數(shù)據(jù)安全,當(dāng)刪除StatefulSet中Pods或者對(duì)StatefulSet進(jìn)行縮容時(shí),Kubernetes并不會(huì)自動(dòng)刪除StatefulSet對(duì)應(yīng)的PV,而且這些PV默認(rèn)也不能被其他PVC Bound。當(dāng)你確認(rèn)數(shù)據(jù)無用之后再手動(dòng)去刪除PV的時(shí)候,數(shù)據(jù)是否刪除取決于PV的ReclaimPolicy配置。Reclaim Policy支持以下三種:
目前只有NFS和HostPath支持Recycle;
EBS,GCE PD, Azure Disk,Openstack Cinder支持Delete。
Retain,意味著需要你手動(dòng)清理;
Recycle,等同于rm -rf /thevolume/*
Delete,默認(rèn)值,依賴于后端的存儲(chǔ)系統(tǒng)自己實(shí)現(xiàn)。
注意:
請(qǐng)小心刪除StatefulSet對(duì)應(yīng)的PVC,首先確保Pods已經(jīng)完全Terminate,然后確定不需要Volume中的數(shù)據(jù)后,再考慮刪除PV。因?yàn)閯h除PVC可能觸發(fā)對(duì)應(yīng)PV的自動(dòng)刪除,并根據(jù)StorageClass中的recalimPolicy配置可能造成volume中的數(shù)據(jù)丟失。
因?yàn)椴渴鸬氖怯袪顟B(tài)應(yīng)用,我們需要自己創(chuàng)建對(duì)應(yīng)的Headless Service,注意Label要和StatefulSet中Pods的Label匹配。Kubernetes會(huì)為該Headless Service創(chuàng)建對(duì)應(yīng)SRV Records,包含所有的后端Pods,KubeDNS會(huì)通過Round Robin算法進(jìn)行選擇。
在Kubernetes 1.8+中,你必須保證StatefulSet的spec.selector能匹配.spec.template.metadata.labels,否則會(huì)導(dǎo)致StatefulSet創(chuàng)建失敗。在Kubernetes 1.8之前,StatefulSet的spec.selector如果沒指定則默認(rèn)會(huì)等同于.spec.template.metadata.labels。
對(duì)StatefulSet進(jìn)行縮容前,你需要確認(rèn)對(duì)應(yīng)的Pods都是Ready的,否則即使你觸發(fā)了縮容操作,Kubernetes也不會(huì)真的進(jìn)行縮容操作。
StatefulSet中反復(fù)強(qiáng)調(diào)的“穩(wěn)定的網(wǎng)絡(luò)標(biāo)識(shí)”,主要指Pods的hostname以及對(duì)應(yīng)的DNS Records。
HostName:StatefulSet的Pods的hostname按照這種格式生成:$(statefulset name)-$(ordinal), ordinal
從0 ~ N-1
(N為期望副本數(shù))。
StatefulSet Controller在創(chuàng)建pods時(shí),會(huì)給pod加上一個(gè)pod name label:statefulset.kubernetes.io/pod-name
, 然后設(shè)置到Pod的pod name和hostname中。
pod name label有啥用呢?我們可以創(chuàng)建獨(dú)立的Service匹配到這個(gè)指定的pod,然后方便我們單獨(dú)對(duì)這個(gè)pod進(jìn)行debug等處理。
DNS Records:
Headless Service的DNS解析:$(service name).$(namespace).svc.cluster.local
通過DNS RR解析到后端其中一個(gè)Pod。SRV Records只包含對(duì)應(yīng)的Running and Ready的Pods,不Ready的Pods不會(huì)在對(duì)應(yīng)的SRV Records中。
Pod的DNS解析:$(hostname).$(service name).$(namespace).svc.cluster.local
解析到對(duì)應(yīng)hostname的Pod。
每個(gè)Pod對(duì)應(yīng)一個(gè)PVC,PVC的名稱是這樣組成的:$(volumeClaimTemplates.name)-$(pod's hostname),跟對(duì)應(yīng)的Pod是一一對(duì)應(yīng)的。
當(dāng)Pod發(fā)生re-schedule(其實(shí)是recreate)后,它所對(duì)應(yīng)的PVC所Bound的PV仍然會(huì)自動(dòng)的掛載到新的Pod中。
Kubernetes會(huì)按照VolumeClaimTemplate創(chuàng)建N(N為期望副本數(shù))個(gè)PVC,由PVCs根據(jù)指定的StorageClass自動(dòng)創(chuàng)建PVs。
當(dāng)通過級(jí)聯(lián)刪除StatefulSet時(shí)并不會(huì)自動(dòng)刪除對(duì)應(yīng)的PVCs,所以PVC需要手動(dòng)刪除。
當(dāng)通過級(jí)聯(lián)刪除StatefulSet或者直接刪除對(duì)應(yīng)Pods時(shí),對(duì)應(yīng)的PVs并不會(huì)自動(dòng)刪除。需要你手動(dòng)的去刪除PV。
當(dāng)部署有N個(gè)副本的StatefulSet應(yīng)用時(shí),嚴(yán)格按照index從0到N-1的遞增順序創(chuàng)建,下一個(gè)Pod創(chuàng)建必須是前一個(gè)Pod Ready為前提。
當(dāng)刪除有N個(gè)副本的StatefulSet應(yīng)用時(shí),嚴(yán)格按照index從N-1到0的遞減順序刪除,下一個(gè)Pod刪除必須是前一個(gè)Pod shutdown并完全刪除為前提。
當(dāng)擴(kuò)容StatefulSet應(yīng)用時(shí),每新增一個(gè)Pod必須是前一個(gè)Pod Ready為前提。
當(dāng)縮容StatefulSet應(yīng)用時(shí),沒刪除一個(gè)Pod必須是前一個(gè)Pod shutdown并成功刪除為前提。
注意StatefulSet的pod.Spec.TerminationGracePeriodSeconds不要設(shè)置為0。
正常情況下,StatefulSet Controller會(huì)保證集群內(nèi)同一namespace下不會(huì)出現(xiàn)多個(gè)相同network identity的StatefulSet Pods。
如果集群內(nèi)出現(xiàn)以上情況,那么有可能導(dǎo)致該有狀態(tài)應(yīng)用不能正常工作、甚至出現(xiàn)數(shù)據(jù)丟失等致命問題。
那么什么情況下會(huì)導(dǎo)致出現(xiàn)同一namespace下會(huì)出現(xiàn)多個(gè)相同network identity的StatefulSet Pods呢?我們考慮下Node出現(xiàn)網(wǎng)絡(luò)Unreachable的情況:
如果你使用Kubernetes 1.5之前的版本,當(dāng)Node Condition是NetworkUnavailable時(shí),node controller會(huì)強(qiáng)制從apiserver中刪除這個(gè)Node上的這些pods對(duì)象,這時(shí)StatefulSet Controller就會(huì)自動(dòng)在其他Ready Nodes上recreate同identity的Pods。這樣做其實(shí)風(fēng)險(xiǎn)是很大的,可能會(huì)導(dǎo)致有一段時(shí)間有多個(gè)相同network identity的StatefulSet Pods,可能會(huì)導(dǎo)致該有狀態(tài)應(yīng)用不能正常工作。所以盡量不要在Kubernetes 1.5之前的版本中使用StatefulSet,或者你明確知道這個(gè)風(fēng)險(xiǎn)并且無視它。
如果你使用Kubernetes 1.5+的版本,當(dāng)Node Condition是NetworkUnavailable時(shí),node controller不會(huì)強(qiáng)制從apiserver中刪除這個(gè)Node上的這些pods對(duì)象,這些pods的state在apiserver中被標(biāo)記為Terminating
或者Unknown
,因此StatefulSet Controller并不會(huì)在其他Node上再recreate同identity的Pods。當(dāng)你確定了這個(gè)Node上的StatefulSet Pods shutdown或者無法和該StatefulSet的其他Pods網(wǎng)絡(luò)不同時(shí),接下來就需要強(qiáng)制刪除apiserver中這些unreachable pods object,然后StatefulSet Controller就能在其他Ready Nodes上recreate同identity的Pods,使得StatefulSet繼續(xù)健康工作。
那么在Kubernetes 1.5+中,如何強(qiáng)制從apiserver中刪除該StatefulSet pods呢?有如下三種方法:
如果Node永久的無法連接網(wǎng)絡(luò)或者關(guān)機(jī)了,意味著能確定這個(gè)Node上的Pods無法與其他Pods通信了,不會(huì)對(duì)StatefulSet應(yīng)用的可用性造成影響,那么建議手動(dòng)從apiserver中刪除該NetworkUnavailable的Node,Kubernetes會(huì)自動(dòng)從apiserver中刪除它上面的Pods object。
如果Node是因?yàn)榧壕W(wǎng)絡(luò)腦裂導(dǎo)致的,則建議去檢查網(wǎng)絡(luò)問題并成功恢復(fù),因?yàn)镻ods state已經(jīng)是Terminating
或者Unkown
,所以kubelet從apiserver中獲取到這個(gè)信息后就會(huì)自動(dòng)刪除這些Pods。
其他情況才考慮直接手動(dòng)從apiserver中刪除這些Pods,因?yàn)檫@時(shí)你無法確定對(duì)應(yīng)的Pods是否已經(jīng)shutdown或者對(duì)StatefulSet應(yīng)用無影響,強(qiáng)制刪除后就可能導(dǎo)致出現(xiàn)同一namespace下有多個(gè)相同network identity的StatefulSet Pods,所以盡量不要使用這種方法。
kubectl delete pods
小知識(shí):當(dāng)前Node Condition有以下6種:
Node Condition | Description |
---|---|
OutOfDisk | True if there is insufficient free space on the node for adding new pods, otherwise False |
Ready | True if the node is healthy and ready to accept pods, False if the node is not healthy and is not accepting pods, and Unknown if the node controller has not heard from the node in the last 40 seconds |
MemoryPressure | True if pressure exists on the node memory – that is, if the node memory is low; otherwise False |
DiskPressure | True if pressure exists on the disk size – that is, if the disk capacity is low; otherwise False |
NetworkUnavailable | True if the network for the node is not correctly configured, otherwise False |
ConfigOK | True if the kubelet is correctly configured, otherwise False |
Kubernetes 1.7+,StatefulSet開始支持Pod Management Policy配置,提供以下兩種配置:
OrderedReady,StatefulSet的Pod默認(rèn)管理策略,就是逐個(gè)的、順序的進(jìn)行部署、刪除、伸縮,也是默認(rèn)的策略。
Parallel,支持并行創(chuàng)建或者刪除同一個(gè)StatefulSet下面的所有Pods,并不會(huì)逐個(gè)的、順序的等待前一個(gè)操作確保成功后才進(jìn)行下一個(gè)Pod的處理。其實(shí)用這種管理策略的場(chǎng)景非常少。
StatefulSet的更新策略(由.spec.updateStrategy.type
指定)支持以下兩種:
OnDelete, 含義同Deployment的OnDelete策略,大家應(yīng)該很熟悉了,不多介紹。
RollingUpdate,滾動(dòng)更新過程也跟Deployment大致相同,區(qū)別在于:
所有ordinal大于等于partition指定的值的Pods將會(huì)進(jìn)行滾動(dòng)更新。
所有ordinal小于partition指定的值得Pods將保持不變。即使這些Pods被recreate,也會(huì)按照原來的pod template創(chuàng)建,并不會(huì)更新到最新的版本。
特殊地,如果partition的值大于StatefulSet的期望副本數(shù)N,那么將不會(huì)觸發(fā)任何Pods的滾動(dòng)更新。
相當(dāng)于Deployment的maxSurge=0,maxUnavailable=1(其實(shí)StatefulSet是不存在這兩個(gè)配置的)
滾動(dòng)更新的過程是有序的(逆序),index從N-1到0逐個(gè)依次進(jìn)行,并且下一個(gè)Pod創(chuàng)建必須是前一個(gè)Pod Ready為前提,下一個(gè)Pod刪除必須是前一個(gè)Pod shutdown并完全刪除為前提。
支持部分實(shí)例滾動(dòng)更新,部分不更新,通過.spec.updateStrategy.rollingUpdate.partition
來指定一個(gè)index分界點(diǎn)。
以上就是怎樣淺析Kubernetes StatefulSet,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。