kubernetes控制器之StatefulSets

StatefulSet是用于管理有状态应用程序的工作负载API对象,它是kubernetes从1.9版本中开始引入。它和其他Controller一样以相同的模式运行,具有Controller相同的特征。关于有状态和无状态服务区分,请参考链接。

与Deployment类似,StatefulSet管理基于相同容器规范的Pod组。不同的是,StatefulSet为其每个Pod维护一个粘性标识。这些pod是根据相同的规范创建的,但相互不可替代:每个pod都有一个持久的标识符(例如主机名),它在任何时候重新调度时都会保留,具有唯一性。

 

 

使用场景

当你的应用服务需要以下特征支持时,可适用StatefulSet部署:

  • 稳定且唯一的网络标识符。
  • 稳定且持久的存储。
  • 有序,平滑的部署和扩展。
  • 有序的自动滚动更新。

由上可知,Statefulset就是为有状态服务而生。例如你的缓存或数据库,他们需要固定的连接方式(hostname固定),持久化的存储(最好是共享存储),部署和更新时可以按你要求的顺序来进行。

 

 

使用要求

  • StatefulSet是1.9之前的beta资源,在1.5版本之前不支持。
  • 给定Pod的存储必须由PersistentVolume Provisioner根据请求的存储类(storage class)进行配置,或者由管理员预先配置。
  • 删除和/或伸缩StatefulSet将不会删除与StatefulSet关联的vloume卷。这样做是为了确保数据安全,防止误删数据。
  • StatefulSets目前要求使用Headless Service无头服务构建Pod的网络身份(hostname)。
  • 删除StatefulSet时,StatefulSets不提供对pod终止的任何保证。 要在StatefulSet中实现pod的有序和正常终止,可以在删除之前将StatefulSet缩小到0。
  • 使用具有默认Pod管理策略(OrderedReady)的Rolling Updates时,可能会进入需要手动干预进行修复的损坏状态。

 

重要组件

  • StatefulSet
  • Headless Service:无头服务
  • volumeClaimTemplates:使用PersistentVolume Provisioner配置的PersistentVolumes提供稳定的存储

 

示例:

nginx.yaml

apiVersion: v1
kind: Service   # 创建Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None   # 此处表明此Service类型为Headless Service
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet   # 创建StatefulSet
metadata:
  name: web
spec:
  selector:     # 必须指定selector选择器
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3   # 副本数
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:     # volume存储卷模板
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]  # 访问权限类型
      storageClassName: "my-storage-class"  # 存储类名
      resources:    # 资源申请详情
        requests:
          storage: 1Gi

 

Pod特征

StatefulSet Pod具有唯一的标识,由序号、稳定的网络标识和稳定的存储组成。 无论它(重新)安排在哪个节点上,这些特征保持不变

  • 序号

对于具有N个副本的StatefulSet,StatefulSet中的每个Pod将被分配一个整数序号,从0到N-1,在副本集上是唯一的。

  • 不变的网络ID

StatefulSet中的每个Pod都从StatefulSet的名称和Pod的序号中获取其主机名。 构造的主机名的模式是:

statefulset名-序号

上面的示例将创建三个名为web-0,web-1,web-2的Pod。 StatefulSet可以使用无头服务来控制其Pod的域名。 此服务管理的域采用以下形式:

Service_name.namesapce_name.svc.cluster.local

其中“cluster.local”是k8s集群默认的根域名。 在创建每个Pod时,它将获得匹配的如下形式的DNS子域名:

pod_name.Service_name
  • 不变的存储

Kubernetes为每个VolumeClaimTemplate创建一个PersistentVolume(简称pv)。 在上面的nginx示例中,每个Pod将接收一个PersistentVolume,其StorageClass为my-storage-class,1 Gib为预配置存储空间。 如果未指定StorageClass,则将使用默认的StorageClass。 当Pod(重新)调度到节点上时,volumeMounts将挂载与其PersistentVolume声明关联的PersistentVolumes。 请注意,删除Pods或StatefulSet时,不会删除与Pods的PersistentVolume声明关联的PersistentVolumes。 删除操作需要手动完成。

  • Pod标签

当StatefulSet控制器创建一个Pod时,它会为Pod添加一个标签:statefulset.kubernetes.io/pod-name,。此标签允许你将服务链接到StatefulSet的特定Pod上。

部署和伸缩

  • 对于具有N个副本的StatefulSet,当部署Pod时,将按顺序从{0…N-1}开始创建Pod。
  • 当删除Pod时,它们将以{N-1…0}的相反顺序终止。
  • 在将缩放操作应用于Pod之前,其所有前任必须是Running和Ready状态。
  • 在Pod终止之前,其所有后继者(序号比它大的)必须完全关闭。

StatefulSet的Pod默认管理策略(在.spec.podManagementPolicy中指定)为OrderedReady,即如上描述。也支持另一种管理策略Parallel,即不等前面的Pod是Running,并行启动Pod(谨慎使用)。

更新策略

在Kubernetes 1.7及更高版本中,StatefulSet的.spec.updateStrategy字段允许您为StatefulSet中的Pod配置和禁用容器、标签、资源请求/限制和注释的自动滚动更新。滚动更新策略有如下几种:

  • OnDelete:户必须手动删除Pod才能使控制器创建新的Pod
  • RollingUpdate:默认策略,StatefulSet控制器将删除并重新创建StatefulSet中的每个Pod。 它将以与Pod终止相同的顺序(从最大序号到最小序号)继续进行,一次更新每个Pod。 在更新其前任之前,它将等待更新的Pod正在运行并准备就绪才会继续。

 

发表评论