# k8s StatefulSets
StatefulSets(有状态系统服务设计)在 k8s 1.7 中还是 beta 特性,同时 StatefulSets 是 1.4 版本中 PetSets 的替代品。PetSets 的用户参考 1.5 升级指南。
# 使用 StatefulSets
在具有以下特点时使用 StatefulSets:
- 稳定性,唯一的网络标识符。
- 稳定性,持久化存储。
- 有序的部署和扩展。
- 有序的删除和终止。
- 有序的自动滚动更新。
Pod 调度运行时,如果应用不需要任何稳定的标示、有序的部署、删除和扩展,则应该使用一组无状态副本的控制器来部署应用,例如 Deployment 或 ReplicaSet 更适合无状态服务需求。
# 限制
- StatefulSet 还是 beta 特性,在 k8s 1.5 版本之前任何版本都不可以使用。
- 与所有 alpha / beta 特性的资源一样,可以通过 apiserver 配置-runtime-config 来禁用 StatefulSet。
- Pod 的存储,必须基于请求 storage class 的 PersistentVolume Provisioner 或由管理员预先配置来提供。
- 基于数据安全性设计,删除或缩放 StatefulSet 将不会删除与 StatefulSet 关联的 Volume。
- StatefulSets 需要 Headless Service 负责 Pods 的网络的一致性(必须创建此服务)。
# 组件
示例:
- name 为 nginx 的 Headless Service 用于控制网络域。
- StatefulSet(name 为 web)有一个 Spec,在一个 Pod 中启动具有 3 个副本的 nginx 容器。
- volumeClaimTemplates 使用 PersistentVolumes 供应商的 PersistentVolume 来提供稳定的存储。
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: gcr.io/google_containers/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: my-storage-class
resources:
requests:
storage: 1Gi
# 部署和扩展
- 对于具有 N 个副本的 StatefulSet,当部署 Pod 时,将会顺序从{0..N-1}开始创建。
- Pods 被删除时,会从{N-1..0}的相反顺序终止。
- 在将缩放操作应用于 Pod 之前,它的所有前辈必须运行和就绪。
- 对 Pod 执行扩展操作时,前面的 Pod 必须都处于 Running 和 Ready 状态。
- 在 Pod 终止之前,所有 successors 都须完全关闭。
不要将 StatefulSet 的 pod.Spec.TerminationGracePeriodSeconds 值设置为 0,这样设置不安全,建议不要这么使用。更多说明,请参考 force deleting StatefulSet Pods.
在上面示例中,会按顺序部署三个 pod(name: web-0、web-1、web-2)。web-0 在 Running and Ready 状态后开始部署 web-1,web-1 在 Running and Ready 状态后部署 web-2,期间如果 web-0 运行失败,web-2 是不会被运行,直到 web-0 重新运行,web-1、web-2 才会按顺序进行运行。
如果用户通过 StatefulSet 来扩展修改部署 pod 副本数,比如修改 replicas=1,那么 web-2 首先被终止。在 web-2 完全关闭和删除之前,web-1 是不会被终止。如果在 web-2 被终止和完全关闭后,但 web-1 还没有被终止之前,此时 web-0 运行出错了,那么直到 web-0 再次变为 Running and Ready 状态之后,web-1 才会被终止。
# Pod 管理
在 k8s 1.7 及更高版本中,StatefulSet 放宽了排序规则,同时通过.spec.podManagementPolicy 字段保留其 uniqueness 和 identity guarantees
# OrderedReady Pod Management
OrderedReady Pod Management 是 StatefulSets 的默认行为。它实现了上述 “部署/扩展” 行为。
# Parallel Pod Management
Parallel Pod Management 告诉 StatefulSet 控制器同时启动或终止所有 Pod。
# Update Strategies
在 k8s 1.7 及更高版本中,StatefulSet 的.spec.updateStrategy 字段允许配置和禁用 StatefulSet 中 Pods 的 containers、labels、resource request/limits 和 annotations 的滚动更新。
# 删除
当 spec.updateStrategy 未指定时的默认策略,OnDelete 更新策略实现了传统(1.6 和以前)的行为。当 StatefulSet .spec.updateStrategy.type 设置为 OnDelete,StatefulSet 控制器将不会自动更新 StatefulSet 中的 Pod,用户必须手动删除 Pods 以使控制器创建新的 Pod。
# 滚动更新
RollingUpdate 更新策略实现了自动化,使 StatefulSet 中的 Pod 滚动更新。当 StatefulSet .spec.updateStrategy.type 设置为 RollingUpdate,StatefulSet 控制器将删除并重新创建 StatefulSet 中的每个 Pod。它将以与 Pod 终止相同的顺序进行(从最大的序数到最小的顺序)来更新每个 Pod。
# Partitions
通过指定 .spec.updateStrategy.rollingUpdate.partition 来分割 RollingUpdate 更新策略。如果指定了 partition,则当更新 StatefulSet 时,将更新具有大于或等于 partition 的序数的所有 Pods .spec.template,小于 partition 的序数的所有 Pod 将不会被更新。如果一个 StatefulSet 的.spec.updateStrategy.rollingUpdate.partition 大于它.spec.replicas,它的更新.spec.template 将不会被传 Pods。在通常数情况下,不需要使用 partition,但如果需要进行更新,推出金丝雀或执行分阶段推出,可以使用 partition。