暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kubernetes应用部署——StatefulSet详解

IT运维大爆炸 2023-10-16
39

1、简介

StatefulSet是Kubernetes的一个资源类型,用于管理有状态应用,例如数据库或消息队列。它为每个Pod分配一个唯一的标识符,通常是数字索引,以确保每个Pod具有稳定的网络标识和存储卷。StatefulSet 是为了管理有状态服务的问题而设计的,给定 Pod 的存储必须由 PersistentVolume 驱动基于所请求的 storage class
来提供,或者由管理员预先提供。删除或者收缩 StatefulSet 并不会删除它关联的存储卷。这样做是为了保证数据安全。

2、两种服务状态

有状态服务?

StatefulSet 是有状态的集合,管理有状态的服务,它所管理的 Pod 的名称不能随意变化。数据 持久化的目录也是不一样,每一个 Pod 都有自己独有的数据持久化存储目录。比如 MySQL 主 从、redis 集群等。

无状态服务?

RC、Deployment、DaemonSet 都是管理无状态的服务,它们所管理的 Pod 的 IP、名字,启 停顺序等都是随机的。个体对整体无影响,所有 pod 都是共用一个数据卷的,部署的 tomcat 就 是无状态的服务,tomcat 被删除,在启动一个新的 tomcat,加入到集群即可,跟 tomcat 的名 字无关。

3、为什么需要 StatefulSet滚动更新

  • 维持稳定的标识符:有状态应用程序通常有稳定的网络标识符和存储标识符。StatefulSet 可以确保这些标识符在 Pod 更新过程中保持不变,以维护应用程序的稳定性。

  • 有序部署和缩放:StatefulSet 可以按照有序的方式部署和扩展应用程序,确保每个 Pod 都有唯一的标识符,并按照顺序进行扩展或缩小,有助于应用程序的可用性和可维护性。

  • 持久存储:有状态应用程序通常需要持久存储来保存数据。StatefulSet 可以管理 Pod 的 PVC(PersistentVolumeClaim),确保每个 Pod 有自己的持久存储。

  • 有序滚动更新:滚动更新是一种控制 Pod 更新的方式,以确保应用程序的平稳过渡。StatefulSet 允许您控制 Pod 的滚动更新,确保旧 Pod 在新 Pod 启动之前正确终止。

  • 数据迁移:StatefulSet 可以处理数据的迁移,例如在 Pod 更新期间将数据从旧 Pod 迁移到新 Pod。这对于有状态应用程序的数据迁移非常重要。

  • 自动 Pod 缩减:StatefulSet 可以在不需要的情况下自动删除多余的 Pod,从而节省资源。这对于动态扩展和缩减有状态应用程序非常有用。

4、StatefulSet的特点

  • Statefulset 管理的 pod,pod 名字是有序的,由 statefulset 的名字-0、1、2 这种格式组成。

  • 创建 statefulset 资源的时候,必须事先创建好一个 service,如果创建的 service 没有 ip,那 对这个 service 做 dns 解析,会找到它所关联的 pod ip,如果创建的 service 有 ip,那对这个 service 做 dns 解析,会解析到 service 本身 ip。版权声明,本文档全部内容及版权归韩先超所有,只可用于自己学习使用,禁止私自传阅,违者依法 追责。

  • statefulset 管理的 pod,删除 pod,新创建的 pod 名字跟删除的 pod 名字是一样的 。

  • statefulset 具有 volumeclaimtemplate 这个字段,这个是卷申请模板,会自动创建 pv, pvc 也会自动生成,跟 pv 进行绑定,那如果创建的 statefulset 使用了 volumeclaimtemplate 这个字段,那创建 pod,数据目录是独享的 。

  • ststefulset 创建的 pod,是域名的(域名组成:pod-name.svc-name.svcnamespace.svc.cluster.local),pod可以通过域名访问到。

[root@i-cd6217fb Statefulset]# cat statefulset.yaml
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: webs
spec:
selector:
  matchLabels:
    app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
  metadata:
    labels:
      app: nginx # has to match .spec.selector.matchLabels
  spec:
    terminationGracePeriodSeconds: 10
    containers:
     - name: nginx
      image: docker.io/library/nginx:latest
      ports:
       - containerPort: 80
        name: web

[root@i-cd6217fb Statefulset]# kubectl get pod
NAME     READY   STATUS   RESTARTS   AGE
webs-0   1/1     Running   0         7m35s
webs-1   1/1     Running   0         7m32s
webs-2   1/1     Running   0         7m29s

[root@i-cd6217fb Statefulset]# kubectl get sts
NAME   READY   AGE
webs   3/3     9m27s

[root@i-cd6217fb Statefulset]# kubectl edit sts webs
statefulset.apps/webs edited

#修改副本数为4个
[root@i-cd6217fb Statefulset]# kubectl get pod
NAME     READY   STATUS   RESTARTS   AGE
webs-0   1/1     Running   0         10m
webs-1   1/1     Running   0         10m
webs-2   1/1     Running   0         10m
webs-3   1/1     Running   0         7s

5、StatefulSet的两种更新策略

RollingUpdate(滚动更新)

  • 使用 RollingUpdate
    更新策略时,StatefulSet 会自动按顺序一个一个地创建新的 Pod 副本,并等待它们处于就绪状态。

  • 一旦新的 Pod 就绪,StatefulSet 会逐个删除旧的 Pod 副本,确保更新过程平滑。

  • 这意味着在更新期间,总是至少有一个旧 Pod 和一个新 Pod 同时存在,从而保持了应用程序的高可用性。

  • 使用 RollingUpdate
    策略时,您可以在 spec.updateStrategy.type
    中明确指定。

  • 这是推荐的更新策略,特别适用于大多数有状态应用程序,因为它保证了高可用性和平滑的过渡。

OnDelete(手动删除更新)

  • 使用 OnDelete
    更新策略时,StatefulSet 不会自动滚动更新 Pod。相反,它等待您手动删除旧的 Pod 副本,并创建新的 Pod 副本。

  • 这意味着您需要明确地删除每个 Pod 副本,以完成更新。您可以通过运行 kubectl delete pod <pod-name>
    来手动删除 Pod。

  • OnDelete
    策略通常用于特定需求,例如当应用程序需要特殊的维护过程或数据迁移时,可以在更新期间手动介入。

  • 使用 OnDelete
    策略时,您不需要在 spec.updateStrategy.type
    中指定任何内容,因为这是默认策略。

6、RollingUpdate更新

RollingUpdate更新策略对 StatefulSet 中的 Pod 执行自动的滚动更新。在没有声明.spec.updateStrategy时,RollingUpdate是默认配置。当 StatefulSet 的.spec.updateStrategy.type被设置为RollingUpdate时,StatefulSet 控制器会删除和重建 StatefulSet 中的每个 Pod。它将按照与 Pod 终止相同的顺序(从最大序号到最小序号)进行,每次更新一个 Pod。它会等到被更新的 Pod 进入 Running 和 Ready 状态,然后再更新其前身。

[root@i-cd6217fb Statefulset]# cat statefulset.yaml
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: webs
spec:
#滚动更新策略---起始
updateStrategy:
  rollingUpdate:
    partition: 2  
    maxUnavailable: 0
#滚动更新策略---结束    
selector:
  matchLabels:
    app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
  metadata:
    labels:
      app: nginx # has to match .spec.selector.matchLabels
  spec:
    terminationGracePeriodSeconds: 10
    containers:
     - name: nginx
      image: docker.io/library/nginx:latest
      ports:
       - containerPort: 80
        name: web

#我这里有3个pod,上面配置的为2,如果更新镜像,只会更新大于等于2的pod, webs-1、webs-2、webs-3三个pod。
[root@i-cd6217fb Statefulset]# kubectl get pod
NAME     READY   STATUS   RESTARTS   AGE
webs-0   1/1     Running   0         32m
webs-1   1/1     Running   0         32m
webs-2   1/1     Running   0         31m

7、OnDelete 更新

OnDelete 更新策略实现了 1.6 及以前版本的历史遗留行为。当 StatefulSet 的 .spec.updateStrategy.type 设置为 OnDelete 时,它的控制器将不会自动更新 StatefulSet 中的 Pod。用户必须手动删除 Pod 以便让控制器创建新的 Pod,以此来对 StatefulSet 的 .spec.template 的变动作出反应。

[root@i-cd6217fb Statefulset]# cat statefulset.yaml
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: webs
spec:
#滚动更新策略---起始
updateStrategy:
  type: OnDelete
#滚动更新策略---结束
selector:
  matchLabels:
    app: nginx # has to match .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # by default is 1
template:
  metadata:
    labels:
      app: nginx # has to match .spec.selector.matchLabels
  spec:
    terminationGracePeriodSeconds: 10
    containers:
     - name: nginx
      image: docker.io/library/nginx:latest
      ports:
       - containerPort: 80
        name: web
         
#我这里有3个pod,如果更新镜像,只能手动删除镜像才能更新,默认是这种策略。
[root@i-cd6217fb Statefulset]# kubectl get pod
NAME     READY   STATUS   RESTARTS   AGE
webs-0   1/1     Running   0         32m
webs-1   1/1     Running   0         32m
webs-2   1/1     Running   0         31m    

欢迎大家扫码关注:

本公众号只写原创,不接广告、不接广告、不接广告。下期小伙伴想学习什么技术,可以私信发我吆。

文章转载自IT运维大爆炸,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论