【本文目標(biāo)】
-
StatefulSet介紹 -
Deployment和StatefulSet組件的區(qū)別
【前置文章】
- 【k8s學(xué)習(xí)】Kubernetes學(xué)習(xí)——核心組件和架構(gòu)
- 【k8s學(xué)習(xí)】minikube、kubectl、yaml配置文件的介紹
- 【k8s學(xué)習(xí)】在minikube上布署MongoDB和MongoExpress
- 【k8s學(xué)習(xí)】kubernetes namespace介紹
- 【k8s學(xué)習(xí)】Kubernetes Ingress介紹
- 【k8s學(xué)習(xí)】Kubernetes打包工具Helm介紹
- 【k8s學(xué)習(xí)】Kubernetes Volume介紹
1. StatefulSet介紹
官網(wǎng):https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/
StatefulSet組件是用來(lái)管理stateful applications的(有狀態(tài)的應(yīng)用),如:MySQL,elasticsearch,mongoDB等?;蛘邉e的需要存儲(chǔ)數(shù)據(jù)的應(yīng)用。
對(duì)應(yīng)的stateless applications即無(wú)狀態(tài)的應(yīng)用,比如普通的前端UI項(xiàng)目或是后臺(tái)java項(xiàng)目(自身不存儲(chǔ)數(shù)據(jù))。
2. Deployment vs. StatefulSet
StatefulSet組件和Deployment組件都可以使用Storage。
- 針對(duì)
無(wú)狀態(tài)的服務(wù),Kubernetes使用Deployment組件來(lái)管理。 - 針對(duì)
有狀態(tài)的服務(wù),Kubernetes使用StatefulSet組件來(lái)管理。
具體來(lái)說(shuō),假設(shè)我們需要部署my-app項(xiàng)目(目標(biāo)3個(gè)Pod),以及數(shù)據(jù)庫(kù)mysql(目標(biāo)也是3個(gè)Pod)。
2.1 Deployment
對(duì)于my-app Pod,我們會(huì)寫(xiě)一個(gè)Deployment的yaml配置文件,在里面配上ReplicaSet=3,表示需要?jiǎng)?chuàng)建3個(gè)Pod,以及my-app Container的鏡像,用來(lái)創(chuàng)建Pod時(shí)用。創(chuàng)建出來(lái)的my-app會(huì)是:
-
identical and interchangeable:即創(chuàng)建的三個(gè)my-app Pod是相同的,以及如果一個(gè)掛了,很容易再新創(chuàng)建一個(gè)。 -
created in random order with random hashes:三個(gè)my-app Pod啟動(dòng)也沒(méi)有先后順序,可以隨意。 -
one Service that load balances to any Pod:一個(gè)Service組件可以幫助做負(fù)載均衡。
2.2 StatefulSet
而對(duì)于mysql Pod,會(huì)使用StatefulSet組件來(lái)創(chuàng)建:
-
can't be created/deleted at same time:創(chuàng)建的時(shí)候是有順序的 -
can't be randomly addressed:并不是隨機(jī)訪問(wèn)的 -
replica Pods are not identical:主要原因是創(chuàng)建的Pod之間,并不是完全相同的,相反的,每個(gè)創(chuàng)建的Pod都有自己額外的標(biāo)志(這個(gè)標(biāo)志是唯一的)。
2.2.1 Pod Identity(Pod標(biāo)志)
-
sticky identity for each pod:即上述說(shuō)的針對(duì)有狀態(tài)的服務(wù),Pod除了id外,還有額外的唯一標(biāo)志,比如創(chuàng)建的3個(gè)mysql Pod,Pod標(biāo)志可以是:mysql-0,mysql-1,mysql-2,一般為${statefulset name}-${order}。 -
created from same specification, but not interchangeable!:雖然都是從同一個(gè)StatefulSet配置中創(chuàng)建的,但有狀態(tài)的Pod并不像無(wú)狀態(tài)的Pod一樣是可交換的。 -
persistent identifier across any re-scheduling:比如ID-2 down了,并不是會(huì)再生成一個(gè)ID-3或是別的,而是會(huì)新生成一個(gè)Pod來(lái)代替這個(gè)ID-2,即Identity不變。
聽(tīng)上去很繞,以及有狀態(tài)的服務(wù)為啥需要額外的Pod Identity呢?
主要原因是如下的架構(gòu),會(huì)導(dǎo)致數(shù)據(jù)的不一致,多個(gè)Pod,都有讀寫(xiě),數(shù)據(jù)就會(huì)變的不同步。

通常情況下,只會(huì)有一臺(tái)負(fù)責(zé)寫(xiě),負(fù)責(zé)寫(xiě)的這臺(tái)叫MASTER,其余的叫WORKER:

這也是為什么會(huì)就StatefulSet創(chuàng)建的Pod并不是完全相同的Pod,因?yàn)橹挥幸慌_(tái)是Master。
-
They do not use the same physical storage!,即上述的三個(gè)volume,并不是相同的地址,可以是:/data/vol/pv-0,/data/vol/pv-1,data/vol/pv-2,相當(dāng)于是有數(shù)據(jù)的備份。 -
Continuously synchronizing of the data:這意味著Master和Worker節(jié)點(diǎn)間有數(shù)據(jù)的同步。Master是唯一有寫(xiě)權(quán)限的,所以Worker需要及時(shí)知道數(shù)據(jù)的改動(dòng),以及它自己的pv中的數(shù)據(jù)得到更新。 -
the first one is the Master:最先啟動(dòng)的Pod為Master。 -
Next Pod is only created, if previous is up and running!:即有狀態(tài)的Pod是安順序啟動(dòng)的,并且要等前面的Pod啟動(dòng)好了再啟動(dòng)新的Pod。 -
Deletion in reverse order, starting from the last one:如果刪除該StatefulSet,那么Pod的刪除是啟動(dòng)順序的倒序,即最先刪除最后啟動(dòng)的那個(gè)Pod,刪除成功后再接著刪除倒數(shù)第2,以此類(lèi)推。
【整個(gè)過(guò)程】
Master修改了數(shù)據(jù) --> 所有的Worker感知到了數(shù)據(jù)的變動(dòng),開(kāi)始修改自己的pv --> 這時(shí)候要是新加入一個(gè)Pod,叫mysql-3,它會(huì)創(chuàng)建自己的Storage,然后會(huì)先從它順序的前一個(gè)的Pod中clone數(shù)據(jù)。 --> mysql-3完成了clone數(shù)據(jù)后,也會(huì)開(kāi)始監(jiān)聽(tīng)數(shù)據(jù)的改動(dòng),以便及時(shí)更新到它自己的Storage中
Pod state
有狀態(tài)的服務(wù),它的Storage存放的不僅是Pod的數(shù)據(jù),還會(huì)存Pod的狀態(tài),如它所連的Pod是Master Pod還是Worker Pod等。當(dāng)這個(gè)Storage所連的Pod掛了,如上述說(shuō)的,并不是新起一個(gè)Pod,Pod標(biāo)志什么的都變了,而是新起的這個(gè)Pod會(huì)替換掉原來(lái)的Pod,即Pod Identity都不會(huì)變,這時(shí)候之前的Storage會(huì)re-attached(重新連接)上這個(gè)Pod,這樣就可以避免新起的Pod上來(lái)就先clone數(shù)據(jù)。--> 當(dāng)然這里需要使用的是Remote storage!因?yàn)長(zhǎng)ocal storage可能會(huì)跟隨著舊的Node一起掛掉。
Pod endpoints
有服務(wù)狀態(tài)的Service會(huì)有自己的DNS name,名字格式:${pod name}.${governing service domain},如mysql-0.svc2,mysql-1.svc2,mysql-2.svc2。
這意味著如果Pod重啟了,那么IP地址可以變了,但是name以及endpoint不會(huì)變。
3. 總結(jié)
關(guān)于有狀態(tài)服務(wù)的部署,并沒(méi)有像無(wú)狀態(tài)服務(wù)部署來(lái)的容易。需要額外做很多事:
- 需要關(guān)心數(shù)據(jù)的sync同步問(wèn)題。
- 需要Remote Storage(假使集群down了數(shù)據(jù)仍然在)
- 數(shù)據(jù)備份問(wèn)題。