StatefulSet是指带有状态的Pod集合,用于运行带有状态的应用集合,其使用与Deployment相同的方式扩展Pod的集群规模,运行在StatefulSet中的Pod具有固定的顺序以及固定的身份标识器,这些Pod的属性不会因为Pod资源的重新调度而发生变化。
StatefulSet简要描述
与Deployment相同的是StatefulSet使用相同的容器规范管理Pod,与Deployment不同的是StatefulSet对每个Pod维护一个严格的、唯一的身份标识(ID),也就是,它们创建Pod的规范或者方式相同,但是它们管理Pod的方式有区别。StatefulSet创建的Pod是不可变的,每个Pod都具备一个持久化的身份标识器,在任何情况下,控制器重新调度Pod资源的时候,该身份标识(ID)都不会发生变化。
在实际的应用场景中,如果用户的应用需求是依赖数据持久化存储空间,则可以使用StatefulSet编排资源。当集群系统发生异常,需要重新调度StatefulSet中Pod资源的时候,控制器会根据旧Pod的属性自动绑定旧Pod的存储空间到新创建的Pod中。
StatefulSet适用场景
StatefulSet适用于具有以下性质的应用:
即使控制器因为重新调度,而重新创建新的Pod,持久化层的存储空间或者网络空间也是固定不变的,新创建的Pod会自动绑定旧Pod的持久化层的资源。如果用户的应用不需要依赖于持久化层的资源以及有序的部署、删除、扩展,则可以使用无状态的Pod,无状态的Pod可以使用Deployment或者ReplicaSet实现。 |
StatefulSet使用限制
|
StatefulSet相关组件
如上图所示定义一个StatefulSet类型的Pod描述文件:
|
Pod选择器
域.spec.selector配置的标签,必须符合域.spec.template.metadata.labels配置的标签,例如,nginx。
定义存储空间模板
使用.spec.volumeClaimTemplates配置指定持久化存储空间提供商的存储空间类型。
最小化准备时间
配置域.spec.minReadySeconds用于创建完成一个新Pod时,还需要多长时间才认为Pod是可用的,单位:秒。当用户使用滚动更新策略时,控制器使用该配置值检查更新的进度,默认值是0,也就是,一旦Pod创建完,即被认为是可用的。
Pod的身份标识(ID)
StatefulSet中的Pod具备一个唯一性的身份标识,是由一个序数、固定的网络标识(ID)、固定的存储空间标识组成,该标识与Pod绑定,保持固定不变,在任何节点上调度都不会发生变化。
序数索引
对于一个给定的StatefulSet,其中包括N个副本,则序数从0到N-1赋予每个Pod,因此该序数在相同的StatefulSet内是唯一的。
固定的网络标识(ID)
在kubernetes集群中,每个Pod对应一个主机名称(hostname),同样,StatefulSet中每个Pod对应的主机名称是根据StatefulSet的名称而定,其命名规则是$(statefulset name)-$(ordinal),例如,上图定义Pod的名称分别是web-0、web-1、web-2。因为每个StatefulSet绑定headless服务,其服务域名的命名规则是$(service name).$(namespace).svc.cluster.local,其中,cluster.local是kubernetes集群的域名,每个Pod对应的子域名的命名规则是$(pondage).$(governing service domain):
在kubernetes集群中Pod提供的服务是以DNS的方式访问,而由于DNS的缓存问题以及DNS的生效时间延迟问题,刚创建的Pod需要等待一段时间(几十秒)才能使用域名正常访问到。用户可以使用如下的方式实现快速访问刚创建的Pod:
|
固定的存储空间标识
在StatefulSet的域VolumeClaimTemplate中定义存储空间,用户可以定义指定的存储空间类型。例如,在前面的例子中,定义存储空间类型是my-storage-class以及存储空间的容量大小是1Gib,如果用户没有指定存储空间类型,则系统默认的类型。在一个新的Pod在新的节点中创建,新创建的Pod会挂载旧的存储空间,当StatefulSet或者其中的Pod被删除,其绑定的存储空间不会被删除,需要用户手动删除。
Pod的名称标签
每个新创建Pod的名称标签的形式如:statefulset.kubernetes.io/pod-name,该标签可以用于为StatefulSet中的Pod绑定一个服务。
部署与扩缩容
StatefulSet控制器提供以下有关集群副本的部署与扩缩容的保证:
|
根据以上规则,Pod的启动顺序是web-0、web-1、web-2,web-1在web-0完成后启动,web-2在web-1完成后启动,如果web-1完成启动后,web-0发生故障,则web-2在web-0恢复之前不会启动。假如,用户修改集群副本数由3变化为1,web-2先被终止,web-1在web-2完成终止后终止,web-0在web-1完成终止后终止,如果web-2完成终止后,web-0先于web-1完成终止前发生故障,则web-1在web-0恢复之前不会终止。
Pod的管理策略
用户可以使用.spec.podManagementPolicy域设置更加宽松的扩缩容策略,如下所示:
OrderedReady 该配置值是严格按照指定顺序的扩缩容策略(如前面所述) |
Parallel 该配置值使用并行的、不按照指定顺序的扩缩容策略(不需要依赖于其他Pod的启动状态),该设置只对扩缩容的策略有效,而对更新策略无效 |
更新策略
用户可以使用.spec.updateStrategy域设置部署发布时的更新策略(Pod的更新内容包括容器镜像版本、标签属性、资源需求或者限制、注解),如下所示:
OnDelete 该设置值指定StatefulSet控制器不使用自动部署发布的更新方式,也就是,需要用户先手工删除旧的在运行的Pod实例,从而触发Pod新版本(模板更新)的创建与更新 |
RollingUpdate 该设置值指定StatefulSet控制器使用自动部署发布的更新方式,以滚动发布的方式更新Pod新版本 |
滚动更新
用户如果设置.spec.updateStrategy.type等于RollingUpdate,则StatefulSet控制器先删除已经存在的旧Pod,再重新创建新Pod替代旧Pod。其终止与更新的顺序是使用前面所述的序数索引的顺序,也就是,从序数索引大的Pod向序数索引小的Pod的方向操作,一次只更新一个Pod,控制器会等待当前的Pod更新完成后再更新下一个Pod,配置域.spec.minReadySeconds设置值是用于当前的Pod更新完成后再等待的持续时间才执行下一次的更新操作。
分区滚动更新
在RollingUpdate滚动更新的策略下,如果用户使用如下所示的设置域,指定序数索引的最小值,StatefulSet控制器只更新大于等于该序数索引的Pod:
.spec.updateStrategy.rollingUpdate.partition
小于该序数索引的Pod不会被更新,小于该序数索引的Pod即使被删除,控制器重新创建新Pod时也只使用旧版本的Pod。假如设置域的值大于副本数,则控制器不会执行任何更新的操作。该更新策略可以指定更新发布一部分的Pod,因此,适用于灰度发布、以及引流测试发布的使用场景。
最大不可用Pod数
在更新发布的过程中,用户可以使用如下所示的设置域,指定最大不可用的Pod数,该值支持整数值或者百分比,也就是,StatefulSet控制器在更新发布时,需要先终止已经运行的Pod,再创建新的Pod,这个数值对应的是最大终止Pod的数量,默认值是1:
.spec.updateStrategy.rollingUpdate.maxUnavailable
假设集群副本数是N,则该值的有效范围是从0到N-1,在StatefulSet中任何不可用的Pod都包括在该值中。
强制性回滚
在部署更新发布的过程中,如果出现异常的情况,则更新过程被终止,需要人工修复或者恢复对应的配置文件、配置域,其他已经涉及到不正确配置域的Pod也需要人工终止,人工修复完成,StatefulSet控制器继续执行更新发布的过程。
存储空间保持策略
PersistentVolumeClaim(PVC)配置域对应的规则如下所示:
.spec.persistentVolumeClaimRetentionPolicy 该配置域是可选项,用于设置在StatefulSet的生命周期内对应的存储空间(PVCs)的删除策略,在配置域StatefulSetAutoDeletePVC开启之后生效,该配置域一旦被开启,则用户可以同时指定如下两种删除规则 |
whenDeleted 当StatefulSet被删除,配置存储空间的处理规则 |
whenScaled 当StatefulSet中的Pod副本数降低,配置存储空间的处理规则 |
当以上设置生效,则设置如下存储空间的处理规则 |
Delete 当whenDeleted生效,则删除所有Pod对应的存储空间,当whenScaled生效,则删除被删除Pod副本的存储空间 |
Retain 这是默认值,当StatefulSet被删除或者Pod副本被删除,对应的存储空间不受影响,也就是,对应的存储空间不会被删除 |
以上的规则只对部署更新发布时,StatefulSet被删除或者StatefulSet中的集群副本规模收缩的时候才生效。如果因为集群节点发生异常,而引起Pod部署失败,则控制器不会删除Pod对应的存储空间,此时,控制器会在新的节点中挂载对应的存储空间,并且绑定到新建的Pod。
在whenDeleted设置域等于Delete值时,StatefulSet控制器创建Pod成功后,为Pod对应的存储空间设置属主的引用关系,当Pod被终止,则这些属主的引用关系也被删除,在存储空间被删除之前,控制器会卸载Pod中的存储空间。
在whenScaled设置域等于Delete值时,控制器只删除集群副本数收缩情况下被终止的Pod的存储空间,而不会删除其他异常情况下被终止的Pod的存储空间。在异常情况被修复之后,控制器会检测配置域中的集群副本数与实际环境kubernetes集群中的Pod实例数,任何Pod的ID大于集群副本数的都将被终止、与之对应的存储空间也最终被删除。
假如在以上属主关系设置成功之前,控制器发生异常而重启,则控制器不会处理这些Pod,在这种使用场景下,建议用户等待控制器的自动恢复处理或者手工检查Pod与存储空间的引用关系再手工恢复。
集群副本数
配置域.spec.replicas是可选项,指定集群副本数,默认值是1。用户可以使用命令行控制台执行以下命令行动态设置集群副本数:
kubectl scale statefulset
statefulset
--replicas=X
用户也可以使用配置文件执行如下命令行,覆盖旧的配置文件:
kubectl apply -f
statefulset.yaml
如果用户使用HorizontalPodAutoscaler水平扩展器,则不需要设置该值,由控制器自动化地管理集群副本数。
(未完待续)