StatefulSet
StatefulSet
StatefulSet 作为 Controller 为 Pod 提供唯一的标识。它可以保证部署和 scale 的顺序。
使用案例参考:kubernetes contrib - statefulsets,其中包含zookeeper和kakfa的statefulset设置和使用说明。
StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:
稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
有序收缩,有序删除(即从N-1到0)
从上面的应用场景可以发现,StatefulSet由以下几个部分组成:
用于定义网络标志(DNS domain)的Headless Service
用于创建PersistentVolumes的volumeClaimTemplates
定义具体应用的StatefulSet
StatefulSet中每个Pod的DNS格式为statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local
,其中
serviceName
为Headless Service的名字0..N-1
为Pod所在的序号,从0开始到N-1statefulSetName
为StatefulSet的名字namespace
为服务所在的namespace,Headless Servic和StatefulSet必须在相同的namespace.cluster.local
为Cluster Domain
使用 StatefulSet
StatefulSet 适用于有以下某个或多个需求的应用:
稳定,唯一的网络标志。
稳定,持久化存储。
有序,优雅地部署和 scale。
有序,优雅地删除和终止。
有序,自动的滚动升级。
在上文中,稳定是 Pod (重新)调度中持久性的代名词。 如果应用程序不需要任何稳定的标识符、有序部署、删除和 scale,则应该使用提供一组无状态副本的 controller 来部署应用程序,例如 Deployment 或 ReplicaSet 可能更适合您的无状态需求
限制
StatefulSet 是 beta 资源,Kubernetes 1.5 以前版本不支持。
对于所有的 alpha/beta 的资源,您都可以通过在 apiserver 中设置
--runtime-config
选项来禁用。给定 Pod 的存储必须由 PersistentVolume Provisioner 根据请求的
storage class
进行配置,或由管理员预先配置。删除或 scale StatefulSet 将不会删除与 StatefulSet 相关联的 volume。 这样做是为了确保数据安全性,这通常比自动清除所有相关 StatefulSet 资源更有价值。
StatefulSets 目前要求 Headless Service 负责 Pod 的网络身份。 您有责任创建此服务。
组件
下面的示例中描述了 StatefulSet 中的组件。
一个名为 nginx 的 headless service,用于控制网络域。
一个名为 web 的 StatefulSet,它的 Spec 中指定在有 3 个运行 nginx 容器的 Pod。
volumeClaimTemplates 使用 PersistentVolume Provisioner 提供的 PersistentVolumes 作为稳定存储。
还可以进行其他的操作
Pod 身份
StatefulSet Pod 具有唯一的身份,包括序数,稳定的网络身份和稳定的存储。 身份绑定到 Pod 上,不管它(重新)调度到哪个节点上。
序数
对于一个有 N 个副本的 StatefulSet,每个副本都会被指定一个整数序数,在 [0,N)之间,且唯一。
稳定的网络 ID
StatefulSet 中的每个 Pod 从 StatefulSet 的名称和 Pod 的序数派生其主机名。构造的主机名的模式是$(statefulset名称)-$(序数)
。 上面的例子将创建三个名为web-0,web-1,web-2
的 Pod。
StatefulSet 可以使用 Headless Service 来控制其 Pod 的域。此服务管理的域的格式为:$(服务名称).$(namespace).svc.cluster.local
,其中 “cluster.local” 是集群域。
在创建每个Pod时,它将获取一个匹配的 DNS 子域,采用以下形式:$(pod 名称).$(管理服务域)
,其中管理服务由 StatefulSet 上的 serviceName
字段定义。
以下是 Cluster Domain,服务名称,StatefulSet 名称以及如何影响 StatefulSet 的 Pod 的 DNS 名称的一些示例。
Cluster Domain
Service (ns/name)
StatefulSet (ns/name)
StatefulSet Domain
Pod DNS
Pod Hostname
cluster.local
default/nginx
default/web
nginx.default.svc.cluster.local
web-{0..N-1}.nginx.default.svc.cluster.local
web-{0..N-1}
cluster.local
foo/nginx
foo/web
nginx.foo.svc.cluster.local
web-{0..N-1}.nginx.foo.svc.cluster.local
web-{0..N-1}
kube.local
foo/nginx
foo/web
nginx.foo.svc.kube.local
web-{0..N-1}.nginx.foo.svc.kube.local
web-{0..N-1}
注意 Cluster Domain 将被设置成 cluster.local
除非进行了其他配置。
稳定存储
Kubernetes 为每个 VolumeClaimTemplate 创建一个 PersistentVolume。上面的 nginx 的例子中,每个 Pod 将具有一个由 anything
存储类创建的 1 GB 存储的 PersistentVolume。当该 Pod (重新)调度到节点上,volumeMounts
将挂载与 PersistentVolume Claim 相关联的 PersistentVolume。请注意,与 PersistentVolume Claim 相关联的 PersistentVolume 在 产出 Pod 或 StatefulSet 的时候不会被删除。这必须手动完成。
部署和 Scale 保证
对于有 N 个副本的 StatefulSet,Pod 将按照 {0..N-1} 的顺序被创建和部署。
当 删除 Pod 的时候,将按照逆序来终结,从{N-1..0}
对 Pod 执行 scale 操作之前,它所有的前任必须处于 Running 和 Ready 状态。
在终止 Pod 前,它所有的继任者必须处于完全关闭状态。
不应该将 StatefulSet 的 pod.Spec.TerminationGracePeriodSeconds
设置为 0。这样是不安全的且强烈不建议您这样做。进一步解释,请参阅 强制删除 StatefulSet Pod。
上面的 nginx 示例创建后,3 个 Pod 将按照如下顺序创建 web-0,web-1,web-2。在 web-0 处于 运行并就绪 状态之前,web-1 将不会被部署,同样当 web-1 处于运行并就绪状态之前 web-2也不会被部署。如果在 web-1 运行并就绪后,web-2 启动之前, web-0 失败了,web-2 将不会启动,直到 web-0 成功重启并处于运行并就绪状态。
如果用户通过修补 StatefulSet 来 scale 部署的示例,以使 replicas=1
,则 web-2 将首先被终止。 在 web-2 完全关闭和删除之前,web-1 不会被终止。 如果 web-0 在 web-2 终止并且完全关闭之后,但是在 web-1 终止之前失败,则 web-1 将不会终止,除非 web-0 正在运行并准备就绪。
更新 StatefulSet
v1.7 + 支持 StatefulSet 的自动更新,通过 spec.updateStrategy
设置更新策略。目前支持两种策略
OnDelete:当
.spec.template
更新时,并不立即删除旧的 Pod,而是等待用户手动删除这些旧 Pod 后自动创建新 Pod。这是默认的更新策略,兼容 v1.6 版本的行为RollingUpdate:当
.spec.template
更新时,自动删除旧的 Pod 并创建新 Pod 替换。在更新时,这些 Pod 是按逆序的方式进行,依次删除、创建并等待 Pod 变成 Ready 状态才进行下一个 Pod 的更新。
Partitions
RollingUpdate 还支持 Partitions,通过 .spec.updateStrategy.rollingUpdate.partition
来设置。当 partition 设置后,只有序号大于或等于 partition 的 Pod 会在 .spec.template
更新的时候滚动更新,而其余的 Pod 则保持不变(即便是删除后也是用以前的版本重新创建)。
Pod 管理策略
v1.7 + 可以通过 .spec.podManagementPolicy
设置 Pod 管理策略,支持两种方式
OrderedReady:默认的策略,按照 Pod 的次序依次创建每个 Pod 并等待 Ready 之后才创建后面的 Pod
Parallel:并行创建或删除 Pod(不等待前面的 Pod Ready 就开始创建所有的 Pod)
Parallel 示例
可以看到,所有 Pod 是并行创建的
参考:
Last updated