StatefulSet

StatefulSet有两个维度的抽象:

  • 拓扑状态:有时候多个实例之间并非对等关系,可能需要按顺序启动,又或者,某个Pod挂掉后,新创建的Pod必须和原先Pod的网络标识一样,这样,原先的访问者才可能使用访问原先Pod的方法,访问到新Pod。
  • 存储状态:即使Pod挂掉被重建,访问的存储应该是同一份。
  • 本质:StatefulSet是一种特殊的Deployment,只不过这个Deployment的Pod名称+编号固定,编号的顺序固定了Pod之间的拓扑关系;而编号对应的Persist Volume,绑定了Pod与持久化存储之间的关系。因此,Pod即使被重建,状态也不会改变。·

StatefulSet是用于管理有状态应用的工作负载API对象。StatefulSet在1.8中是beta版本。

管理Deployment以及一组 Pods 的伸缩,并为这些Pod的排序和唯一性提供保证。

Deployment 一样,StatefulSet管理基于相同容器spec的Pod。与Deployment不同,StatefulSet会为每个Pod保留粘性身份。这些Pod是从相同的spec创建的,但不可互换:每个Pod都有一个持久化的标识符,即使重新调度也仍然会使用该标识符。

StatefulSet与任何其他Controller的模式相同。您可在StatefulSet对象中定义期望状态,StatefulSet Controller会从当前状态进行必要的更新,从而达到期望状态。

Using StatefulSets(使用StatefulSet)

StatefulSet适用于以下场景:

  • 稳定、唯一的网络标识。
  • 稳定、持久化的存储。
  • 有序、优雅的部署和缩放(即:部署有顺序、扩展也有顺序)。
  • 有序、优雅的删除和终止。
  • 有序、自动的滚动更新。

在上文中,“稳定”是Pod调度(重新调度)持久化的代名词。如果应用程序不需要任何稳定的标识符或有序部署、删除或缩放,则应该使用提供无状态副本的Controller部署应用。 诸如 Deployment 或者 ReplicaSet 可能更适合您的无状态需求。

Limitations(限制)

  • StatefulSet是一个beta资源(处于Beta阶段的资源),在1.5之前的Kubernetes版本中不可用。
  • 与所有其他alpha/beta资源一样,可传给apiserver一个--runtime-config 选项来禁用StatefulSet。
  • 给定Pod的存储必须由 PersistentVolume Provisioner 根据请求的 storage class 提供,或由管理员预先设置。
  • 删除/缩容StatefulSet将不会删除与StatefulSet关联的Volume。这样做是为了确保数据安全性,这通常比自动清除StatefulSet所有相关资源更有价值。
  • StatefulSet目前需要一个 Headless Service 负责Pod的网络身份。您有责任创建此Service。

Components(组件)

下面的示例演示了StatefulSet的组件。

  • 名为nginx的Headless Service,用于控制网络域名。
  • 名为web的StatefulSet,它有一个Spec,表示有3个nginx副本。
  • volumeClaimTemplates将使用PersistentVolume Provisioner提供的 PersistentVolumes ,从而提供稳定的存储。
  1. kind: PersistentVolume
  2. apiVersion: v1
  3. metadata:
  4. name: pv-volume
  5. labels:
  6. type: local
  7. spec:
  8. storageClassName: manual
  9. capacity:
  10. storage: 10Gi
  11. accessModes:
  12. - ReadWriteOnce
  13. hostPath:
  14. path: "/mnt/data"
  15. ---
  16. kind: PersistentVolumeClaim
  17. apiVersion: v1
  18. metadata:
  19. name: pv-claim
  20. spec:
  21. storageClassName: manual
  22. accessModes:
  23. - ReadWriteOnce
  24. resources:
  25. requests:
  26. storage: 3Gi
  27. ---
  28. apiVersion: v1
  29. kind: Service
  30. metadata:
  31. name: nginx
  32. labels:
  33. app: nginx
  34. spec:
  35. ports:
  36. - port: 80
  37. name: web
  38. clusterIP: None
  39. selector:
  40. app: nginx
  41. ---
  42. apiVersion: apps/v1
  43. kind: StatefulSet
  44. metadata:
  45. name: web
  46. spec:
  47. selector:
  48. matchLabels:
  49. app: nginx # has to match .spec.template.metadata.labels
  50. serviceName: "nginx"
  51. replicas: 3 # by default is 1
  52. template:
  53. metadata:
  54. labels:
  55. app: nginx # has to match .spec.selector.matchLabels
  56. spec:
  57. terminationGracePeriodSeconds: 10
  58. containers:
  59. - name: nginx
  60. image: nginx
  61. ports:
  62. - containerPort: 80
  63. name: web
  64. volumeMounts:
  65. - name: task-pv-storage
  66. mountPath: /usr/share/nginx/html
  67. volumes:
  68. - name: task-pv-storage
  69. persistentVolumeClaim:
  70. claimName: task-pv-claim

Pod Selector(Pod选择器)

您必须设置StatefulSet的spec.selector 字段以匹配其.spec.template.metadata.labels 的Label。在Kubernetes 1.8之前, spec.selector 字段被默认为省略。 在1.8及更高版本中,如未指定匹配的Pod Selector将会导致在StatefulSet创建过程中验证错误。

Pod Identity(Pod身份)

StatefulSet Pod有唯一的身份,包括序数(ordinal)、稳定的网络标识和稳定的存储。 身份会绑定到Pod(具有粘性),不管Pod被调度到哪个Node上。

Ordinal Index(有序的索引)

对于一个有N个副本的StatefulSet,StatefulSet中的每个Pod将被分配一个整数序号,范围[0,N),并且唯一。

Stable Network ID(稳定的网络ID)

StatefulSet中的每个Pod,从StatefulSet的名称和Pod的序数派生其主机名。 构造的主机名的模式是 $(statefulset name)-$(ordinal) 。上面的例子中,将会创建名为web-0,web-1,web-2 的Pod。StatefulSet可以使用 Headless Service 来控制其Pod的域名。此Service管理的域名的格式为: $(service name).$(namespace).svc.cluster.local ,其中“cluster.local”是集群域名。在创建每个Pod时,它将会获得一个匹配的DNS子域,采用以下形式: $(podname).$(governing service domain) ,其中governing service由StatefulSet上的serviceName字段定义。

以下是Cluster Domain、Service名称、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}

请注意,除非 otherwise configured ,Cluster Domain将被设为cluster.local

Stable Storage(稳定的存储)

Kubernetes为每个VolumeClaimTemplate创建一个 PersistentVolume 。 在上面的nginx示例中,每个Pod将收到一个PersistentVolume,其中包含名为my-storage-class 的StorageClass和1 Gib的存储。如果未指定StorageClass,则将使用默认StorageClass。当一个Pod被重新调度到一个Node上时,它的volumeMounts 将挂载与其PersistentVolume Claims相关联的PersistentVolume。请注意,当Pod或StatefulSet被删除时,与Pod的PersistentVolume Claims相关联的PersistentVolumes不会被删除。这必须手动完成。

Deployment and Scaling Guarantees(部署和缩放保证)

  • 对于具有N个副本的StatefulSet,当部署Pod时,它们将按从{0..N-1}的顺序创建。
  • 当Pod被删除时,它们按从{N-1..0}的顺序终止。
  • 在将扩容操作应用于Pod之前,它的所有“前辈”必须Running and Ready。
  • 在Pod终止之前,所有的“后辈”必须完全关闭。

StatefulSet不应该将 pod.Spec.TerminationGracePeriodSeconds 设为0。这种做法是不安全,强烈不建议您这么做。 有关进一步说明,请参阅 force deleting StatefulSet Pods

当创建上述的nginx示例时,将以web-0、web-1、web-2的顺序部署三个Pod。在web-0正在 Running and Ready ,web-1将不被部署,而在web-1 Running and Ready之前web-2将不被部署。 如果web-0失败,在web-1 Running and Ready之后,但在启动web-2之前,web-2将不会启动,直到web-0成功重启并Running and Ready。

如果用户通过patch StatefulSet来scale部署的示例,例如设置replicas=1 ,则web-2将首先被终止。在web-2完全关闭和删除之前,web-1不会被终止。如果web-0失败发生在web-2终止并完全关闭之后、web-1终止之前,web-1将不会终止,除非web-0已经Running and Ready。

Pod Management Policies(Pod管理策略)

在Kubernetes 1.7及更高版本中,StatefulSet允许您放松其排序保证,同时通过.spec.podManagementPolicy 字段保留其唯一性和身份保证。

OrderedReady Pod Management(OrderedReady的Pod管理)

OrderedReady Pod管理是StatefulSet的默认值。 它实现了上述 行为。

Parallel Pod Management(并行 Pod管理)

Parallel Pod管理告诉StatefulSet Controller 并行启动或终止所有Pod,并且不要等待Pod在启动或终止另一个Pod之前变为“Running”和“Ready”或完全终止。

Update Strategies(更新策略)

在Kubernetes 1.7及更高版本中,StatefulSet的 .spec.updateStrategy 字段允许您配置和禁用StatefulSet中Pod的容器、标签、资源最小要求/最大限制、Annotation的滚动更新。

On Delete

OnDelete 更新策略实现了遗留(1.6和以前)的行为。 当 spec.updateStrategy 未指定时,这是默认策略。当StatefulSet的 .spec.updateStrategy.type 设置为OnDelete ,StatefulSet Controller将不会自动更新StatefulSet中的Pod。用户必须手动删除Pod以使Controller创建新的Pod,以反映对StatefulSet的.spec.template 进行的修改。

Rolling Updates

RollingUpdate更新策略为在StatefulSet中的Pod实现自动的滚动更新。当StatefulSet的.spec.updateStrategy.type设置为RollingUpdate 时,StatefulSet Controller将在StatefulSet中删除并重新创建每个Pod。它将按照Pod终止(从最大序号到最小)的顺序进行,每次更新一个Pod。 在更新其“前辈”之前,它将等待正在更新的Pod进入Running and Ready状态。

Partitions(分区)

可以通过指定 .spec.updateStrategy.rollingUpdate.partition 来对 RollingUpdate 更新策略进行分区。 如果指定了分区,则当StatefulSet的 .spec.template 更新时,具有大于或等于分区的序数的所有 .spec.template 被更新。具有小于分区的序数的所有Pods将不会更新,即使删除它们,也会使用以前的版本重新创建。 如果StatefulSet的 .spec.updateStrategy.rollingUpdate.partition 大于其 .spec.replicas ,则 .spec.replicas 更新将不会传播到其Pod。在大多数情况下,您不需要使用分区,但如果您想要进行阶段更新、金丝雀部署或执行分阶段发布,分区将非常有用。

What’s next(下一步)

原文

https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/

很赞的博客

在K8s中创建StatefulSet:http://www.cnblogs.com/puyangsky/p/6677308.html