【本文目标】
-
StatefulSet
介绍 -
Deployment
和StatefulSet
组件的区别
【前置文章】
- 【k8s学习】Kubernetes学习——核心组件和架构
- 【k8s学习】minikube、kubectl、yaml配置文件的介绍
- 【k8s学习】在minikube上布署MongoDB和MongoExpress
- 【k8s学习】kubernetes namespace介绍
- 【k8s学习】Kubernetes Ingress介绍
- 【k8s学习】Kubernetes打包工具Helm介绍
- 【k8s学习】Kubernetes Volume介绍
1. StatefulSet介绍
官网:https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/statefulset/
StatefulSet
组件是用来管理stateful applications的(有状态的应用),如:MySQL,elasticsearch,mongoDB等。或者别的需要存储数据的应用。
对应的stateless applications即无状态的应用,比如普通的前端UI项目或是后台java项目(自身不存储数据)。
2. Deployment vs. StatefulSet
StatefulSet
组件和Deployment
组件都可以使用Storage
。
- 针对
无状态的服务
,Kubernetes使用Deployment
组件来管理。 - 针对
有状态的服务
,Kubernetes使用StatefulSet
组件来管理。
具体来说,假设我们需要部署my-app项目(目标3个Pod),以及数据库mysql(目标也是3个Pod)。
2.1 Deployment
对于my-app Pod,我们会写一个Deployment的yaml配置文件,在里面配上ReplicaSet=3,表示需要创建3个Pod,以及my-app Container的镜像,用来创建Pod时用。创建出来的my-app会是:
-
identical and interchangeable
:即创建的三个my-app Pod是相同的,以及如果一个挂了,很容易再新创建一个。 -
created in random order with random hashes
:三个my-app Pod启动也没有先后顺序,可以随意。 -
one Service that load balances to any Pod
:一个Service组件可以帮助做负载均衡。
2.2 StatefulSet
而对于mysql Pod,会使用StatefulSet
组件来创建:
-
can't be created/deleted at same time
:创建的时候是有顺序的 -
can't be randomly addressed
:并不是随机访问的 -
replica Pods are not identical
:主要原因是创建的Pod之间,并不是完全相同的,相反的,每个创建的Pod都有自己额外的标志(这个标志是唯一的)。
2.2.1 Pod Identity(Pod标志)
-
sticky identity for each pod
:即上述说的针对有状态的服务,Pod除了id外,还有额外的唯一标志,比如创建的3个mysql Pod,Pod标志可以是:mysql-0
,mysql-1
,mysql-2
,一般为${statefulset name}-${order}
。 -
created from same specification, but not interchangeable!
:虽然都是从同一个StatefulSet配置中创建的,但有状态的Pod并不像无状态的Pod一样是可交换的。 -
persistent identifier across any re-scheduling
:比如ID-2 down了,并不是会再生成一个ID-3或是别的,而是会新生成一个Pod来代替这个ID-2,即Identity不变。
听上去很绕,以及有状态的服务为啥需要额外的Pod Identity呢?
主要原因是如下的架构,会导致数据的不一致,多个Pod,都有读写,数据就会变的不同步。
通常情况下,只会有一台负责写,负责写的这台叫MASTER
,其余的叫WORKER
:
这也是为什么会就StatefulSet创建的Pod并不是完全相同的Pod,因为只有一台是Master。
-
They do not use the same physical storage!
,即上述的三个volume,并不是相同的地址,可以是:/data/vol/pv-0
,/data/vol/pv-1
,data/vol/pv-2
,相当于是有数据的备份。 -
Continuously synchronizing of the data
:这意味着Master和Worker节点间有数据的同步。Master是唯一有写权限的,所以Worker需要及时知道数据的改动,以及它自己的pv中的数据得到更新。 -
the first one is the Master
:最先启动的Pod为Master。 -
Next Pod is only created, if previous is up and running!
:即有状态的Pod是安顺序启动的,并且要等前面的Pod启动好了再启动新的Pod。 -
Deletion in reverse order, starting from the last one
:如果删除该StatefulSet,那么Pod的删除是启动顺序的倒序,即最先删除最后启动的那个Pod,删除成功后再接着删除倒数第2,以此类推。
【整个过程】
Master修改了数据
--> 所有的Worker感知到了数据的变动,开始修改自己的pv
--> 这时候要是新加入一个Pod,叫mysql-3,它会创建自己的Storage,然后会先从它顺序的前一个的Pod中clone数据。
--> mysql-3完成了clone数据后,也会开始监听数据的改动,以便及时更新到它自己的Storage中
Pod state
有状态的服务,它的Storage存放的不仅是Pod的数据,还会存Pod的状态
,如它所连的Pod是Master Pod还是Worker Pod等。当这个Storage所连的Pod挂了,如上述说的,并不是新起一个Pod,Pod标志什么的都变了,而是新起的这个Pod会替换掉原来的Pod,即Pod Identity都不会变,这时候之前的Storage会re-attached(重新连接)上这个Pod,这样就可以避免新起的Pod上来就先clone数据。--> 当然这里需要使用的是Remote storage!因为Local storage可能会跟随着旧的Node一起挂掉。
Pod endpoints
有服务状态的Service会有自己的DNS name,名字格式:${pod name}.${governing service domain}
,如mysql-0.svc2
,mysql-1.svc2
,mysql-2.svc2
。
这意味着如果Pod重启了,那么IP地址可以变了,但是name以及endpoint不会变。
3. 总结
关于有状态服务的部署,并没有像无状态服务部署来的容易。需要额外做很多事:
- 需要关心数据的sync同步问题。
- 需要Remote Storage(假使集群down了数据仍然在)
- 数据备份问题。
网友评论