StatefulSet在Kubernetes中的应用

概述

Kubernetes中有很多的控制器,比如常用的ReplicaSet,Deployment,DaemonSet,StatefulSet等。以这四种为例,我们可以将它们分为两种,一种为有状态控制器,一种为无状态控制器,StatefulSet则为有状态控制器,通常用于管理有状态的服务,如:MySQL,Redis,MongoDB等。

有状态控制器通常有以下几个特点:

  • 稳定的,唯一的网络标识

  • 稳定的,持久的存储

  • 有序的,优雅的部署和伸缩

  • 有序的,优雅的删除和停止

  • 有序的,自动的滚更新

也就是说如果我们的应用如有以上的任何一个特点我们就可以使用statefulset控制器来完成应用的部署。


网络标识:

Pod名称:唯一且不会发生变化,由 $(statefulset name)-(0-N)组成,N为一个无限大的正整数,从0开始。

容器内计算机名:与Pod名称一至且不会发生变化。

DNS A记录:每一个副本都拥有唯一且不变的一条A记录指定自己,格式组成:$(pod name).$(service name).$(namespace name).svc。

唯一的Pod标签,通过StatefulSet创建的每个副本都拥有一个唯一的标签,格式为:statefulset.kubernetes.io/pod-name=$(pod name),通常可以将新的service单独关联到此标签,来解决某个Pod的问题等。

以上的标识只要配置不发生改变,发生重启,升级,删除后再创建这些标识都不会发生变化。

备注:Pod的IP地址会发生变化,但我们也可以使用另外的方案来结合StatefulSet实现固定IP的方案,通常不推荐这么做。


持久存储:

每个Pod都对应一个PVC,PVC的名称组成:$(volumeClaimTemplates name)-$(pod name)-(0-N),N为一个无限大的正整数,从0开始。

当Pod被删除的时候不会自动删除对应的PVC,需要手动删除。

每次Pod升级,重启,删除重新创建后都呆以保证使用的是首次使用的PVC,保证数据的唯一性与持久化。


有序:

当部署有N个副本的StatefulSet时候,严格按照从0到N的顺序创建,并且下一个Pod创建的前提是上一个Pod已经Running状态。

当删除有N个副本的StatefulSet时候,严格按照从N到0的顺序删除,并且下一个Pod删除的前提是上一个Pod已经完全Delete。

当扩容StatefulSet副本的时候,每增加一个pod前提是上一个Pod已经Running状态。

当减少StatefulSet副本的时候,每删除一个pod前提是上一个Pod已经完全Delete。

当升级StatefulSet的时候,严格按照从N到1的顺序升级,并且下一个Pod升级的前提是上一个Pod已经Running状态。


无头服务(headless service)

无头服务是Kubernetes中service类型的一种,为什么需要无头服务?通常我们在使用Deployment部署Pod的时候名称是随机的字符串,Pod也是无序的。但 StatefulSet是有序且名称唯一,每一个Pod不可以被取代,所以这时候就需要使用无头服务来实现。

无头服务特点:当使用Kubernetes内DNS解析去访问Service的时候,会将解析的IP指向Service后端的Pod。当无头服务与StatefulSet控制器使用的时候,因为每个Pod的数据可能是不一样的,所以在Service名前面再加了一个Pod名,这样我们的每个StatefulSet控制器的Pod就拥有了唯一的网络标识(A记录)。

无头服务案例:

apiVersion: v1
kind: Service
metadata:
  namespace: test
  name: mysql-test
spec:
  selector:
    app: mysql-test
  clusterIP: None
  ports:
  - port: 3306
    targetPort: 3306

ClusterIP:当此项的值为“None”的时候,此服务就为无头服务,Kubernetes不会给此服务分配IP地址。当使用type为NodePort的时候不可以使用无头服务。


volumeClaimTemplates:

此为Kubernetes中的一个对象,对象的路径为“statefulset.spec.volumeClaimTemplates”,用于给StatefulSet的Pod申请PVC,称为卷申请模板,它会为每个Pod生成不同的PVC,关绑定到PV,从而实现Pod的专有存储。

通常我们在使用Deployment中使用“deployment.spec.template.spec.volumes”与PVC建立关联的时候,所有的副本使用的是相同的PV与PVC,他们的数据是相同的。而StatefulSet为实现各Pod的专有存储,所以才有了“statefulset.spec.volumeClaimTemplates”此方法。


实际应用场景



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章