k8s-statefulset

在当今的云原生计算环境中,Kubernetes已经成为容器编排的事实标准。随着微服务架构的普及,开发者们需要一种方法来管理有状态的服务,这些服务需要持久化存储、唯一网络标识和有序部署。这就是Kubernetes StatefulSet的用武之地。

StatefulSet是Kubernetes中的一种控制器,它专门设计用来管理有状态的应用。与传统的无状态应用不同,有状态应用需要跟踪它们的状态,这通常涉及到持久化存储和网络标识。StatefulSet提供了一种机制,确保每个Pod都有一个持久的标识符,并且可以以一种可预测的方式进行扩展和收缩。

以一个实验来展现一下statefulset控制器的一些特点

k8s-master    rockylinux9.4系统

192.168.8.128
k8s-node1     rockylinux9.4系统192.168.8.129
k8s-node2     rockylinux9.4系统192.168.8.130

 

文章中需要的一些镜像大家都可以找一个docker主机,配置好加速器之后

用docker pull 进行拉取

例如拉取1.24版本的nginx:   docker   pull  nginx:1.24

之后再docker save  -o  打包的文件名字.tar    nginx:1.24

打包完之后传到k8snode节点上面 ctr  -n k8s.io  image import  打包的文件名字.tar 进行导入镜像,或者直接将镜像打个harbor的ip标签传到harbor上面

一: 编写statefulset yaml文件

vim test.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-test
  namespace: sts  # 定义命名空间

spec:
  replicas: 3      # 定义StatefulSet中Pod副本的数量
  serviceName: statefulset-service    # 定义StatefulSet服务的名称
  selector:
    matchLabels: 
      app: nginx          # 定义选择器,用于匹配模板中定义的标签
  template:
    metadata:
      labels:
        app: nginx       # 定义模板标签对应上面的matchLabels
    spec:
      containers:
      - name: nginx
        image: nginx:1.24
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: /usr/share/nginx/html/      # 定义挂载路径
          name: nginx-volume                  # 定义挂载的卷名称
  volumeClaimTemplates:
  - metadata:
      name: nginx-volume          # 定义持久卷声明的名称对应上面的volumeMounts.name
    spec:
      storageClassName: "nfs"          # 定义存储类名称
      accessModes: ["ReadWriteOnce"]      # 定义卷的访问模式
      resources:
        requests:
          storage: 1Gi
  persistentVolumeClaimRetentionPolicy:
    whenDeleted: Delete
    # 当StatefulSet被删除时,对应的PVC也会被删除
    whenScaled: Retain
    # 当StatefulSet缩容时,保留对应的PVC

---
apiVersion: v1
kind: Service
metadata:
  name: statefulset-web
  labels:
    app: nginx
  namespace: sts      # 定义Service所在的命名空间
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None      # 定义Service的类型为Headless Service
  selector:
    app: nginx         # 定义Service选择器,用于匹配StatefulSet中Pod的标签

yaml文件中的volumeClaimTemplates这个字段就是卷模板的意思,后面创建的pod挂载的卷都是基于这个模板创建出来的卷进行挂载的,这个模板中定义的就是我们上个文章的nfs storageclass

kubectl  apply  -f   test.yaml               

kubectl  get  svc  -n sts        #查看sts命名空间下的service

kubectl   get  pod  -n sts       #查看sts命名空间下的pod

5a73120bf733461783d479a2dbe6f048.png

可以看到sts创建的pod都是具有序号的

二:测试

statefulset控制器和deployment控制器不同:

2.1 比如我们删除一个pod nginx-test-1

kubectl  -n sts delete pod nginx-test-1

  9a310341079b48be98376922f6ebdd25.png

重新创建出来的pod还是这个名字,这样就保持了一致性

2.2 pvc回收策略

yaml文件中定义的

d2dc55d285bd473986d8b0ae6a3e1b9f.png

测试一下

kubectl   get  pvc  -n sts

270e7b3fd4334ad19b30950fc046d3fb.png

可以看到在sts命名空间下有三个pvc,这三个pvc就是对应的sts命名空间中的那三个pod

d8ea1dc2f2004d169b16d112cf4bd05a.png

可以看到我们删除了sts命名空间下的nginx-test这个statefulset这个控制器的资源后,对应的pvc也会被删除。

现在我们重新把pod创建出来,再测试一下pod缩容的时候会不会删除对应的pvc

19b766831bdd46d785d890e66f667f4c.png

可以看到pvc和pod都已经创建出来了,现在将test.yaml中的副本数修改成1:replicas: 1

再来创建一下   kubectl    apply  -f test.yaml

2f91f56b430d427e84c8178bf68e4d80.png

可以看到pvc没有被删除,pod已经被成功缩容到1个

三: Headless Service

我们在yaml文件中定义了 service 其中的Cluster IP是none,这个就是表示没有ip 地址通过域名的方式来访问pod

ea02a8aab1364d8cb4a3d63fa28b71a8.png

我们先创建一个有一个nslookup命令的pod

vim  pod.yaml

apiVersion: v1
kind: Pod
metadata: 
  name: web
  labels:
    app: web
  namespace: sts
spec:
  containers:
  - name: caddy
    image: docker.io/library/caddy:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80

默认这个caddy镜像里面就有nslookup命令,镜像可以直接用docker  pull  caddy拉取

5e1c6326394a44789e796fddb88af0a3.png

可以看到通过域名解析的方式也是成功解析到了statefulset创建的三个pod的ip地址

默认的service的域名是 <servicename>.<namespace>.svc.<clusterdomain> 其中,servicename为service名称,namespace为service所处的命名空间,clusterdomain是k8s集群设计的域名后缀,默认为cluster.local。

四:更新策略

statefulset的更新策略是基于序号的方式进行更新的,就是pod后面跟着的数字

在yaml文件中加入这些内容

updateStrategy:
  rollingUpdate:   
    maxUnavailable: 0
    partition: 1

7ee0bde7e71c4872bb250630c422417d.png

在Kubernetes的StatefulSet资源中,updateStrategy定义了StatefulSet如何进行更新。StatefulSet支持两种更新策略:RollingUpdateOnDeleteOnDelete是默认策略,意味着StatefulSet仅在您手动删除Pod时才会更新Pod。而RollingUpdate则允许StatefulSet控制器自动更新Pod。

maxUnavailable:0  表示系统可以处于不可用状态的最大Pod数量。这里的值0意味着在更新过程中不允许有Pod不可用

partition:1 表示以序号为1的pod进行更新

将image换成nginx:1.26

fed761757fef44f79895806207332395.png

kubectl    apply   -f   test.yaml

kubectl   get  pod -n sts   -w    #-w表示动态查看pod

b0368701c32d4fdb97f1ad9d6b9fa247.png

可以看到pod的更新策略生效了,没有动nginx-test-0,只更新了序号大于等于的pod

并且是等待一个Pod更新并运行成功后,才会继续更新下一个Pod。

验证一下版本

kubectl -n sts exec -it  nginx-test-0  -- /bin/bash -c "nginx -v"

kubectl -n sts exec -it  nginx-test-1  -- /bin/bash -c "nginx -v"

kubectl -n sts exec -it  nginx-test-2  -- /bin/bash -c "nginx -v"

1246c3750130497fa78b2936b13a5b82.png

可以看到nginx-test-1和2都更新到了1.26版本,nginx-test-0没动还是nginx1.24版本。

再来测一下OnDelete这个更新策略

将test.yaml中updataStratrgy这里修改成这样

78934a52e63a4c2396592ae5ccc28797.png

修改镜像

de9dfb49b310433c9c4494ae518190f4.png

这个sjl-nginx:v1镜像里面封装的是nginx1.27版本

kubectl  apply  -f  test.yaml

再查看

392cc5109efc47e49defcbdfee94abea.png

可以看到还是没有改变,是因为ondelete这个策略是在删除pod之后再进行更新的

删除一下nginx-test-0再查看版本

864cb0c7c46048d3ab753f278f29a777.png

可以看到删除完重新创建出来的pod就会被更新成1.27版本

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Source、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值