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正在运行并准备就绪才会继续。