如何在Kubernetes中管理有状态应用

在Kubernetes中,StatefulSet被用来管理有状态应用的API对象。StatefulSets在Kubernetes 1.9版本才稳定。StatefulSet管理Pod部署和扩容,并为这些Pod提供顺序和惟一性的保证。与Deployment类似的地方是,StatefulSet基于spec规格管理Pod;与Deployment不一样的地方是,StatefulSet须要维护每个Pod的惟一身份标识。这些Pod基于一样的spec建立,但互相之间不能替换,每个Pod都保留本身的持久化标识。html

输入图片说明

一、使用StatefulSet的场景

对于下面的应用场景,StatefulSets是有价值的:nginx

  • 稳定、惟一的网络标识web

  • 稳定、持久的存储api

  • 按照顺序、优雅的部署和扩容安全

  • 按照顺序、优雅的删除和终止网络

  • 按照顺序、自动滚动更新app

上述的稳定是持久的同义词,若是应用不须要稳定的标识或者顺序的部署、删除、扩容,则应该使用无状态的副本集。Deployment或者ReplicaSet的控制器更加适合无状态业务场景。less

二、StatefulSet的限制

  • 在Kubernetes 1.9版本以前是beta版本,在Kubernetes 1.5版本以前是不提供的。dom

  • Pod存储由PersistentVolume(storage类或者管理员预先建立)提供。spa

  • 删除或者缩容StatefulSet不会删除与StatefulSet关联的数据卷,这样可以保证数据的安全性。

  • 当前的StatefulSets须要一个Headless服务来为Pod提供网络标识,此Headless服务须要经过手工建立。

三、组件

下面是一个StatefuleSet组成的示例:

  • 一个名称为nginx的Headless服务,用来控制网络域。

  • 一个名称为web的statefulSet,它拥有nginx容器(在惟一的Pod启动)的3个副本集。

  • 使用PersistenVolumes(由PersistentVolume Provisioner提供)提供稳定存储的volumeClaimTemplates。

apiVersion:v1

kind:Service

metadata:

  name:nginx

  labels:

     app:nginx

spec:

  ports:

  -port:80

     name:web

  clusterIP:None //Headless服务

  selector:

     app:nginx

---

apiVersion:apps/v1

kind:StatefulSet

metadata:

  name:web

spec:

  selector:

     matchLabels:

       app:nginx# has to match .spec.template.metadata.labels

  serviceName:"nginx"

  replicas:3 # by default is 1

  template:

     metadata:

       labels:

         app:nginx # has to match .spec.selector.matchLabels

     spec:

       terminationGracePeriodSeconds:10

       containers:

       -name:nginx

         image:k8s.gcr.io/nginx-slim:0.8

         ports:

         -containerPort:80

           name:web

         volumeMounts: #挂接数据卷

         -name:www

           mountPath:/usr/share/nginx/html #挂接路径为容器的/usr/share/nginx/html

  volumeClaimTemplates: #数据卷生命模板

  -metadata:

       name:www

     spec:

       accessModes:["ReadWriteOnce"]

       storageClassName:my-storage-class

       resources:

         requests:

           storage:1Gi

四、Pod选择器

必须设置StatefulSet的sepc.selector,以匹配.spec.template.metadata.labels。在Kubernetes 1.8以前,spec.selector是能够忽略的,它被设置一个默认值。在1.8或者后续的版本,若是不设置sepc.selector,则会致使建立StatefulSet失败。

五、Pod身份标识

StatfuleSet Pod拥有一个惟一的身份标识,它由顺序、稳定的网络标识和稳定的存储所组成。此身份标识一直跟随着Pod,不过它被调度到那个Node上。

5.1 序数索引(Ordinal Index)

对于拥有N个副本集的StatefulSet,在StatefulSet中的每个Pod都会被指派一个整型的序数,此序数在0和N之间,在整个集合中是惟一的。

5.2 网络ID(Stable Network ID)

在StatefulSet中,每个Pod的主机名称都由StatefulSet的名称和序数所组成。Pod的主机名称的格式:$(statefulset name)-$(ordinal)。若是建立了三个Pod,这他们的主机名称为web-0,web-1,web-2。StatefulSet可以使用Headless服务来控制Pod的域。Service管理的域的格式为:$(service name).$(namespace).svc.cluster.local,cluster.local是集群域。对于每个被建立的Pod,它将获得一个DNS子域,格式为: $(podname).$(governing service domain),这里的管理服务在StatefulSet中,经过serviceName设置。

下面是StatefulSet中Pod在DNS中的名称:

输入图片说明

5.3 稳定的存储

kubernetes为每个VolumeClaimTemplate建立一个对应的PersistentVolume。在前面的nginx实例中,每个Pod将会my-storage-class存储类型的PersistenVolume单一实例和1Gib的存储空间。

若是没有指定存储类,则会使用默认的存储。但一个Pod被调度到Node上,它的volumeMounts将会挂接PersistentVolumes,并将其与PersistentVolumeClaims进行关联。须要注意的是,即便在Pod被删除,PersistentVolumes与PersistentVolumeClaims之间的关联关系也不会被删除。

5.4 Pod命名标签

当StatefulSet控制器建立了Pod,它将会添加一个标签,为此Pod名称的集合。此标签将可以管理服务到指定的Pod。

六、部署和扩容保证

  • 对于一个带有N个副本集的StatefulSet,当Pod被部署,它们将按0到N-1的顺序被建立。

  • 当一Pod被删除时,它们将按照N-1到0的倒序被终止。

  • 在进行Pod扩容前,全部依赖的Pod应该都已在运行和准备好。

  • 在Pod被终止前,全部的依赖它的Pod都必须彻底中止。

在前文建立的nginx例子中,将按照顺序部署web-0,web-1和web-2。web-1只能在web-0运行和准备好之后才可以被部署,web-2只能在web-1运行和准备好之后才可以被部署。若是web-0失败,就算web-1正在运行,web-2也是不能正常启动的,除非web-0被重启,并正常运行。

若是缩容上述例子,设置replicas=1,则web-2首先被终止,接着是web-1。若是在web-2被终止后,但在web-1被终止前,web-0失败了,web-1将不能被终止,除非web-0处于正常运行状态。

6.1 Pod管理策略

在Kubernetes 1.7之后,StatefulSet的惟一性标识能够经过.spec.podManagementPolicy的值进行保证。

6.1.1 OrderedReady Pod管理

OrderedReady pod管理是StatefulSets默认的管理模式,此模式安装顺序启动或者终止Pod。

6.1.2 并行Pod管理

并行Pod管理告诉StatefulSet控制器以并行的方式启动或者终止全部的Pod。

七、更新策略

在Kubernetes 1.7以后,运行经过配置StatefulSet的.spec.updateStrategy,实现Pod的容器、标签、资源请求/限制和注释自动更新。

7.1 On Delete策略

OnDelete更新策略是1.6以前版本的行为。当StatefulSet的.spec.updateStrategy.type被设置为OnDelete,则StatefulSet控制器将不会知道更新Pod。

7.2 Rolling Updates策略

RollingUpdate更新策略将实现StatefulSet中Pod的自动滚动更新,这是StatefulSet的默认更新模式。若是.spec.updateStrategy.type设置为 RollingUpdate,则StatefulSet控制器将会删除和重建StatefulSet中的每一Pod。它将会按照从最大到最小的序数终止Pod,并按照从小到大顺序重建Pod。

7.3 Partitions

RollingUpdate更新策略可以经过指定.spec.updateStrategy.rollingUpdate.partition进行分隔。当分隔被指定,全部序数大于或等于分隔的Pod将会被更新,其它的Pod将被不会进行更新。在大部分的状况下,不会使用分隔;当但愿进行金丝雀发布,或者执行阶段发布时,分隔是颇有用的。

做者简介:

季向远,北京神舟航天软件技术有限公司产品经理。本文版权归原做者全部。

相关文章
相关标签/搜索