K8s中的StatefulSet

「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

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-1
  • statefulSetName为StatefulSet的名字
  • namespace为服务所在的namespace,Headless Servic和StatefulSet必须在相同的namespace
  • .cluster.local为Cluster Domain,
---
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: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      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
      annotations:
        volume.alpha.kubernetes.io/storage-class: anything
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi
复制代码
# 扩容
$ kubectl scale statefulset web --replicas=5

# 缩容
$ kubectl patch statefulset web -p '{"spec":{"replicas":3}}'

# 镜像更新(目前还不支持直接更新image,需要patch来间接实现)
$ kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.7"}]'

# 删除StatefulSet和Headless Service
$ kubectl delete statefulset web
$ kubectl delete service nginx

# StatefulSet删除后PVC还会保留着,数据不再使用的话也需要删除
$ kubectl delete pvc www-web-0 www-web-1
复制代码

StatefulSet注意事项

  1. 还在beta状态,需要kubernetes v1.5版本以上才支持
  2. 所有Pod的Volume必须使用PersistentVolume或者是管理员事先创建好
  3. 为了保证数据安全,删除StatefulSet时不会删除Volume
  4. StatefulSet需要一个Headless Service来定义DNS domain,需要在StatefulSet之前创建好
  5. 目前StatefulSet还没有feature complete,比如更新操作还需要手动patch。
  • Cluster : 集群是指由Kubernetes使用一系列的物理机、虚拟机和其他基础资源来运行你的应用程序。

  • Node : 一个node就是一个运行着Kubernetes的物理机或虚拟机,并且pod可以在其上面被调度。.

  • Pod一个pod对应一个由相关容器和卷组成的容器组

  • Label : 一个label是一个被附加到资源上的键/值对,譬如附加到一个Pod上,为它传递一个用户自定的并且可识别的属性.Label还可以被应用来组织和选择子网中的资源(了解Label详情)

  • selector是一个通过匹配labels来定义资源之间关系得表达式,例如为一个负载均衡的service指定所目标Pod.(了解selector详情)

  • Replication Controller: replication controller 是为了保证一定数量被指定的Pod的复制品在任何时间都能正常工作.它不仅允许复制的系统易于扩展,还会处理当pod在机器在重启或发生故障的时候再次创建一个

  • Service: 一个service定义了访问pod的方式,就像单个固定的IP地址和与其相对应的DNS名之间的关系。

  • Volume: 一个volume是一个目录,可能会被容器作为未见系统的一部分来访问。

  • Kubernetes volume 构建在Docker Volumes之上,并且支持添加和配置volume目录或者其他存储设备。

  • Secret : Secret 存储了敏感数据,例如能允许容器接收请求的权限令牌。

  • Name : 用户为Kubernetes中资源定义的名字

  • Namespace : Namespace 好比一个资源名字的前缀。它帮助不同的项目、团队或是客户可以共享cluster,例如防止相互独立的团队间出现命名冲突

  • Annotation : 相对于label来说可以容纳更大的键值对,它对我们来说可能是不可读的数据,只是为了存储不可识别的辅助数据,尤其是一些被工具或系统扩展用来操作的数据