有状态副本集 (SS, Stateful Set) 作为 Controller 为 Pod 提供唯一的标识。它可以保证部署和 scale 的顺序。

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-1
  • statefulSetName为 StatefulSet 的名字
  • namespace为服务所在的 namespace,Headless Servic 和 StatefulSet 必须在相同的 namespace
  • .cluster.local为 Cluster Domain

使用 Stateful Set

Stateful Set 适用于有以下某个或多个需求的应用:

  • 稳定,唯一的网络标志。
  • 稳定,持久化存储。
  • 有序,优雅地部署和 scale。
  • 有序,优雅地删除和终止。
  • 有序,自动的滚动升级。

在上文中,稳定是 Pod (重新)调度中持久性的代名词。 如果应用程序不需要任何稳定的标识符、有序部署、删除和 scale,则应该使用提供一组无状态副本的 controller 来部署应用程序,例如 DeploymentReplicaSet 可能更适合您的无状态需求。

yaml 示例

下面的示例中描述了 StatefulSet 中的组件。

  • 一个名为 nginx 的 headless service,用于控制网络域。
  • 一个名为 web 的 StatefulSet,它的 Spec 中指定在有 3 个运行 nginx 容器的 Pod。
  • volumeClaimTemplates 使用 PersistentVolume Provisioner 提供的 PersistentVolumes 作为稳定存储。
  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: nginx
  5. labels:
  6. app: nginx
  7. spec:
  8. ports:
  9. - port: 80
  10. name: web
  11. clusterIP: None
  12. selector:
  13. app: nginx
  14. ---
  15. apiVersion: apps/v1beta1
  16. kind: StatefulSet
  17. metadata:
  18. name: web
  19. spec:
  20. serviceName: "nginx"
  21. replicas: 3
  22. template:
  23. metadata:
  24. labels:
  25. app: nginx
  26. spec:
  27. terminationGracePeriodSeconds: 10
  28. containers:
  29. - name: nginx
  30. image: gcr.io/google_containers/nginx-slim:0.8
  31. ports:
  32. - containerPort: 80
  33. name: web
  34. volumeMounts:
  35. - name: www
  36. mountPath: /usr/share/nginx/html
  37. volumeClaimTemplates:
  38. - metadata:
  39. name: www
  40. annotations:
  41. volume.beta.kubernetes.io/storage-class: anything
  42. spec:
  43. accessModes: ["ReadWriteOnce"]
  44. resources:
  45. requests:
  46. storage: 1Gi