Kubernetes & StatefulSet
Kubernetes & StatefulSet
在Kubernetes系统中,Pod的管理对象RC
、Deployment
、DaemonSet
和Job
都面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Akka集群、ZooKeeper集群等,这些应用集群有4个共同点:
- 每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现并通信”
2.集群的规模是比较固定的,集群规模不能随意变动。
-
集群中的每个节点都是有状态的,通常会持久化数据到永久存储中。
-
如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。
如果通过RC
或Deployment
控制Pod
副本数量来实现上述有状态的集群,就会发现第1点是无法满足的,因为Pod的名称是随机产生的,Pod的IP地址也是在运行期才确定且可能有变动的,我们事先无法为每个Pod都确定唯一不变的ID。另外,为了能够在其他节点上恢复某个失败的节点,这种集群中的Pod需要挂接某种共享存储,为了解决这个问题,Kubernetes从1.4版本开始引入了PetSet这个新的资源对象,并且在1.5版本时更名为StatefulSet,StatefulSet从本质上来说,可以看作Deployment/RC的一个特殊变种,它有如下特性。
-
◎ StatefulSet里的每个Pod都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。假设StatefulSet的名称为kafka,那么第1个Pod叫kafka-0,第2个叫kafka-1,以此类推。
-
◎ StatefulSet控制的Pod副本的启停顺序是受控的,操作第n个Pod时,前n-1个Pod已经是运行且准备好的状态。
-
◎ StatefulSet里的Pod采用稳定的持久化存储卷,通过PV或PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)。
StatefulSet
除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service
配合使用,即在每个StatefulSet
定义中都要声明它属于哪个Headless Service
。
Headless Service
与普通Service的关键区别在于,它没有Cluster IP
,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表。StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod实例都创建了一个DNS域名。
比如一个3节点的Kafka的StatefulSet集群对应的Headless Service的名称为kafka,StatefulSet的名称为kafka,则StatefulSet里的3个Pod的DNS名称分别为kafka-0.kafka、kafka-1.kafka、kafka-3.kafka,这些DNS名称可以直接在集群的配置文件中固定下来。