k8s之StatefulSet

StatefulSet(状态集)

1,什么是StatefulSet ?
StatefulSet又叫PetSet(之前的名称),它和RS,RC,Deployment等一样,都是pod控制器。
StatefulSet是为了解决有状态服务的问题(对应于deoloyment和RS,RC,ReplicaSet都是为无状态服务而设计的)。

什么是无状态服务?
在生产环境中,pod的名称是随机的,扩缩容的是时候没有规律,每一个pod都可以被新生成的pod代替。

2,StatefulSet的应用场景包括:

  • 稳定的持久化存储:即pod重新调度后还是能够访问到相同的持久化数据,基于PVC来实现。
  • 稳定的网络标志:即pod重新调度后其pod名称和host名称不变,基于Headless Service(即没有cluster ip的service)来实现。
  • 有序部署,有序扩展:即pod是由顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1, 在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现。
  • 有序收缩,有序删除:(即N-1到0)

从上面的引用场景可以发现,statefulset由以下几个部分组成:
1)headless Service:无头服务。用来定义pod的网络标识的(域名解析)。
2)statefulSet:定义具体的应用
3)volumeClaimTemplate:该模板自动为每一个pod创建pvc。

对比无状态服务,总结StatefulSet特点:pod的名称不变,每个副本启停有顺序,持久化存储,每个pod中的数据不同,根据定义的模板自动创建pvc。

3,接下来通过例子来实践statefulset资源的使用
部署nginx服务,通过storage class和statefulset实现有状态服务的数据持久化及其他操作。

操作流程如下:
1)通过nfs服务部署storage class(创建pv)
2)创建statefulset资源对象(创建pvc)
3)测试数据持久化
4)replicas扩容与缩容
5)分区更新

1)通过nfs部署storage class
以下直接进行部署,具体信息及参数解释请参考上章博文 k8s之StatefulSet
#开启nfs:

[[email protected] yaml]# yum -y install nfs-utils
[[email protected] yaml]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)
[[email protected] yaml]# mkdir /nfsdata
[[email protected] yaml]# systemctl start rpcbind
[[email protected] yaml]# systemctl start nfs-server
[[email protected] yaml]# systemctl enable nfs-server
[[email protected] yaml]# showmount -e
Export list for master:
/nfsdata *

#创建rbac权限:

[[email protected] yaml]# vim rbac-rolebind.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nfs-provisioner-runner
  namespace: default
rules:
   -  apiGroups: [""]
      resources: ["persistentvolumes"]
      verbs: ["get", "list", "watch", "create", "delete"]
   -  apiGroups: [""]
      resources: ["persistentvolumeclaims"]
      verbs: ["get", "list", "watch", "update"]
   -  apiGroups: ["storage.k8s.io"]
      resources: ["storageclasses"]
      verbs: ["get", "list", "watch"]
   -  apiGroups: [""]
      resources: ["events"]
      verbs: ["watch", "create", "update", "patch"]
   -  apiGroups: [""]
      resources: ["services", "endpoints"]
      verbs: ["get","create","list", "watch","update"]
   -  apiGroups: ["extensions"]
      resources: ["podsecuritypolicies"]
      resourceNames: ["nfs-provisioner"]
      verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: run-nfs-provisioner
subjects:
  - kind: ServiceAccount
    name: nfs-provisioner
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-provisioner-runner
  apiGroup: rbac.authorization.k8s.io

运行yaml文件。
#创建nfs-Deployment:

[[email protected] yaml]# vim nfs-deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: default
spec:
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-client-provisioner
          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner
          volumeMounts:
            - name: nfs-client-root
              mountPath:  /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: nfs-deploy    #供给方的名称(自定义)
            - name: NFS_SERVER
              value: 172.16.1.30     #nfs服务器的ip地址
            - name: NFS_PATH
              value: /nfsdata      #nfs共享的目录
      volumes:
        - name: nfs-client-root
          nfs:
            server: 172.16.1.30
            path: /nfsdata

#创建storage class:

[[email protected] yaml]# vim sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: statefu-nfs
  namespace: default
provisioner: nfs-deploy
reclaimPolicy: Retain
//运行yaml文件后,查看sc的信息:
[[email protected] yaml]# kubectl  get sc
NAME          PROVISIONER   AGE
statefu-nfs   nfs-deploy    48s

2)创建statefulset资源:

[[email protected] yaml]# vim statefulset.yaml
apiVersion: v1
kind: Service
metadata:
  name: headless-svc   #定义无头服务,需要定义标签
  labels:
    app: headless-svc
spec:
  ports:
  - name: testweb
    port: 80
  clusterIP: None    #需要将cluster ip定义为none
  selector:
    app: nginx  #此处指定的标签需要在后边进行定义
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sfs-web
spec:
  serviceName: headless-svc  #此处选择的服务名为上边定义的无头服务名
  replicas: 3
  selector:
    matchLabels:
      app: nginx    #选择标签
  template:
    metadata:
      labels:
        app: nginx   #定义标签
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
        volumeMounts:   #定义数据持久化
        - name: test-nginx
          mountPath: /usr/share/nginx/html  #挂载到容器内的路径
  volumeClaimTemplates:  #通过该字段(模板)为每个pod创建pvc
  - metadata:
      name: test-nginx
      annotations:
        volume.beta.kubernetes.io/storage-class: statefu-nfs #此处选择之前创建的storage class,名称要一致
    spec:
      accessModes:
        - ReadWriteOnce   #采用ReadWriteOnce的访问模式
      resources:
        requests:
          storage: 100Mi   #请求100M的空间
[[email protected] yaml]# kubectl apply -f statefulset.yaml
service/headless-svc unchanged
statefulset.apps/sfs-web created

//运行成功后,查看创建的headless service和statefulset的状态:


//查看svc的详细信息:

//查看创建的pod:(确保正常运行)

可以看到每个pod都是有序的,它们的名称(域名)会以0,1,2....依次排序。

#根据上面我们说到的,通过sc会创建pv,以及通过sts中的模板会自动创建pvc,我们进行查看集群中的pv和pvc:

我们可以看到pv和pvc创建成功,状态已经是Bound了,访问模式是RWO(在sc中定义的模式),回收策略Delete ,都是通过sc和sts动态创建的,而并不是我们手动创建。

3)测试数据持久化
#查看挂载到nfs服务器上是否会生成每个pvc的共享目录:

#进入某个pod目录下创建测试网页文件:

[[email protected] yaml]# cd /nfsdata/default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023/
[[email protected] default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023]# echo "<h1>hello world</h1>" > index.html
[[email protected] default-test-nginx-sfs-web-0-pvc-4ef5e77e-1198-4ccc-81a7-db48d8a75023]# ll
total 4
-rw-r--r-- 1 root root 21 Jan 12 17:13 index.html

#我们进入到pod中,查看文件是否挂载成功:

#接下来我们将该pod删除掉:

验证重新生成的pod是否被替换,数据是否丢失?

通过上面的测试结果,我们可以得知有状态的服务不同于无状态服务,重新生成的pod名称不会发生改变,即便删除后也不会被新生成的pod覆盖,且原有pod中的数据也一并会存在。

4)replicas的扩容与缩容:
(1)扩容操作:
[[email protected] yaml]# vim statefulset.yaml

//重新运行yaml文件,查看新生成的pod:

(2)缩容操作:(以倒序的方式依次缩减)

//重新运行服务,查看pod状态:

通过上面的扩缩容操作,我们可以得知statefulset资源在生产环境中能够实现有序部署,即有序扩展,有序收缩,且pod的启停都是有一定顺序的。

5)分区更新操作:
分区更新的主要目的是为pod进行一个分区,为了使我们对某个应用所有pod中的某一部分或者有选择性的pod进行更新操作。

#在更新之前,我们先来查看更新的参数:

[[email protected] yaml]#  kubectl  explain  sts.spec.updateStrategy.rollingUpdate
KIND:     StatefulSet
VERSION:  apps/v1

RESOURCE: rollingUpdate <Object>

DESCRIPTION:
     RollingUpdate is used to communicate parameters when Type is
     RollingUpdateStatefulSetStrategyType.

     RollingUpdateStatefulSetStrategy is used to communicate parameter for
     RollingUpdateStatefulSetStrategyType.

FIELDS:
   partition    <integer>
     Partition indicates the ordinal at which the StatefulSet should be
     partitioned. Default value is 0.

#根据以上参数,我们对pod进行分区,并且对指定分区的pod进行版本升级:

我们将replicas的数量设置为8个,且定义分区更新,表示从第四个pod(分区)开始(包括第四个分区)进行更新,之前的pod是不会进行更新操作的。
注意:如果不指定分区,则默认分区从0开始。

#版本升级就不进行测试了,只需将镜像更改为新的nginx版本,重新运行服务后,可以看到从第四个pod开始(包括第四个)之后的pod镜像版本将会进行升级,而之前分区的pod,版本不会发生改变。

4,StatefulSet限制

1)该资源对象还在beta(测试)状态,需要kubernetes v1.5版本以上才支持。
2)所有pod的volume必须使用pv或者是管理员事先创建好的。
3)为了保证数据安全,删除statefulset时不会删除volume。
4)statefulset需要一个Headless Service服务来定义DNS domin,需要在statefulset之前创建好。
5)目前statefulset功能还尚未完善,比如上面的更新操作还需要手动解决。

以上就是statefulset资源的理解与实践,如果应用程序不需要任何稳定的标识符,有序部署,删除和scale,则使用Deployment或RS等无状态控制器来部署。反之在生产中使用statefulset控制器为保证pod与volume的关系不会断开,即使pod挂了后还能使用之前挂载的磁盘

原文地址:https://blog.51cto.com/13972012/2466248

时间: 2024-10-08 04:19:56

k8s之StatefulSet的相关文章

k8s的StatefulSet(有状态服务)实现

StatefulSet介绍 遇到的问题: 使用Deployment创建的Pod是无状态的,当挂在Volume之后,如果该Pod挂了,Replication Controller会再run一个来保证可用性,但是由于是无状态的,Pod挂了的时候与之前的Volume的关系就已经断开了,新起来的Pod无法找到之前的Pod.但是对于用户而言,他们对底层的Pod挂了没有感知,但是当Pod挂了之后就无法再使用之前挂载的磁盘了. StatefulSet: 是一种给Pod提供唯一标志的控制器,它可以保证部署和扩展

K8S使用Statefulset管理集群pod模式(7)

上次我们说到了deployment来管理pod容器的副本数量,如果挂掉之后容器再次启动就可以了,但是如果要是启动的是mysql集群.zookeeper集群.etcd这种集群,里面都有id号,这种有关联的,如果一旦挂掉之后,在启动之后呢,集群id是否会变化呢?答案是肯定会变的.那有没有另外的一种控制器模式吗?当然k8s会给我吗提供的.[statefulset]那什么场景需要使用StatefulSet呢?官方给出的建议是,如果你部署的应用满足以下一个或多个部署需求,则建议使用StatefulSet

StatefulSet

StatefulSet StatefulSet:Pod控制器. ? RC,RS,Deployment,DS.---------->无状态的服务. ? template(模板):根据模板创建出来的Pod,他们的状态都是一模一样的(除了名称,IP,域名之外) ? 可以理解为:任何一个Pod,都可以被删除,然后用新生成的Pod进行替换. 有状态的服务:需要记录前一次或者多次通信中的相关事件,以作为一下通信的分类标准.比如:mysql等数据库服务.(Pod的名称,不能随意变化.数据持久化的目录也是不一样

阿里巴巴的 Kubernetes 应用管理实践经验与教训

作者 | 孙健波(天元)? 阿里巴巴技术专家 导读:本文整理自孙健波在 ArchSummit 大会 2019 北京站演讲稿记录.首先介绍了阿里巴巴基于 Kubernetes 项目进行大规模应用实践过程中遇到的问题:随后会逐一介绍解决这些问题的现有实践及其本身存在的局限性:最后会介绍阿里巴巴目前正在进行的尝试和社区在这一领域的发展方向. 如今,阿里巴巴内部维护了数十个大规模的 K8s 集群,其中最大的集群约 1 万个节点,每个集群会服务上万个应用:在阿里云的 Kubernetes 服务 ACK 上

(转)蘑菇街如何通过构建平台搞定数据标注难题?

在许多学术界和工业界人士努力下,先后在多个领域诞生了开放数据集,从入门的 MNIST,再到大名鼎鼎的 Image Net,涵盖了通用场景.但在实际的业务通常碰到某些细分领域没有开放数据集,比如服装的类型和风格,这就要求自己构建训练数据集,或自力更生,或临时雇用外包人员 (自己提供工具),甚至全权委托给专业标注公司 (无需提供标注工具,成本高).蘑菇街有大量数据标注的需求,综合成本.效率等因素考虑,我们建设了统一的标注平台,支撑众多的标注业务,部分样图请见如下 常见的标注场景 从领域角度,蘑菇街的

k8s实践18:statefulset学习配置记录

1.基础概念 statefulset,可以翻译成有状态的设定. 和deployment的对比 deployment部署创建的pod是无状态的,重新调度pod,pod名字hostname,启动pod顺序删除pod顺序都是随机的.deployment使用的是共享存储,所有pod共用一个存储卷. statefulset部署创建的pod是有状态的,重新调度pod,pod名字hostname保持固定不变,启动pod顺序删除pod顺序都可以根据定义的顺序有序执行操作,有序的动态更新,statefulset使

k8s中的pod控制器之Deployment、DaemonSet、StatefulSet

pod控制器分类:1.ReplicationController2.ReplicaSet3.Deployment4.StatefulSet5.DaemonSet6.Job,Cronjob7.HPApod控制器:一般包括3部分1.标签选择器2.期望的副本数(DaemonSet控制器不需要)3.pod模板deploy控制器构建于rs控制器之上,新特性包括:1.事件和状态查看2.回滚3.版本记录4.暂停和启动5.支持两种自动更新方案Recreate删除重建RollingUpdate回滚升级(默认方式)

k8s StatefulSet ingress 例子

k8s StatefulSet例子 apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: ports: - port: 80 name: web clusterIP: None selector: app: nginx --- apiVersion: apps/v1 kind: StatefulSet metadata: name: web spec: selector: matchLabels:

K8S statefulset 详解

概述 StatefulSet    RC.Deployment.DaemonSet都是面向无状态的服务,它们所管理的Pod的IP.名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所有有状态的服务,比如MySQL.MongoDB集群等.StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(ho