K8S-Statefulset控制器
  TEZNKK3IfmPf 2023年11月13日 62 0

一、statefulset简介

statefulset是用来管理有效状态应用的工作负载API对象,也是一种POD控制器,那为什么要放在PV/PVC之后再简介呢?这是因为statefulset是必须也有持久化数据,每个POD所对应的PV都是不一样的。相对于Deployment所创建的POD是无状态的,那statefulset是属于有状态的,即可以保留POD的状态信息。其特点有:

1、稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现

2、稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现

3、有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现

4、有序收缩,有序删除(即从N-1到0)

5、有序的滚动更新

在svc服务最后有个无头服务那就是headless service这东西有什么用?这是因为statefulset的特性所决定的:在statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。

 

二、statefulset实例

1、通过nfs创建共享存储

SQL

1、在一台服务器创建nfs共享存储

yum install -y nfs-common nfs-utils rpcbind

mkdir /data/nfs{0..3}

chmod 755 /data/nfs{0..3}

chown nfsnobody /data/nfs{0..3}

cat >/etc/exports <<EOF

/home/k8s/nfs  *(rw,sync,no_root_squash)

EOF

systemctl start rpcbind && systemctl enable rpcbind

systemctl start nfs && systemctl enable nfs

###查看共享服务器和路径

[root@k8s-master ~]# showmount -e 172.16.4.169

Export list for 172.16.4.169:

/home/k8s/nfs *

 

2、在其他服务器上进行挂载

[root@k8s-node1 ~]# mount -t nfs 172.16.4.169:/home/k8s/nfs /home/k8s/nfs/

[root@k8s-node1 ~]# df -h

172.16.4.169:/home/k8s/nfs  447G  7.6G  440G   2% /home/k8s/nfs

[root@k8s-node1 ~]# date > /home/k8s/nfs/index.html

[root@k8s-node1 ~]# cat /home/k8s/nfs/index.html

Thu May 12 19:26:48 CST 2022

[root@k8s-node1 ~]#

 

 

2、statefulset的yml

2.1、创建一个PV

 

 

YAML

[root@k8s-master statefulset]# cat pv.yml

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv-volume

spec:

  capacity:

    storage: 50Gi

  volumeMode: Filesystem

  accessModes:

    - ReadWriteOnce

  persistentVolumeReclaimPolicy: Recycle

  storageClassName: slow

  mountOptions:

    - hard

    - nfsvers=4.1

  nfs:

    path: /home/k8s/nfs

    server: 172.16.4.169

[root@k8s-master statefulset]# kubectl apply -f pv.yml

persistentvolume/pv-volume created

[root@k8s-master statefulset]# kubectl get pv

NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM               STORAGECLASS   REASON   AGE

pv-volume        50Gi       RWO            Recycle          Available                       slow                    7s

 

2.2、创建statefulset

 

 

YAML

[root@k8s-master 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: web

spec:

  selector:

    matchLabels:

      app: nginx

  serviceName: "nginx"

  replicas: 3

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.9.1

        ports:

        - containerPort: 80

          name: web

        volumeMounts:

        - name: www

          mountPath: /usr/share/nginx/html

 

  volumeClaimTemplates:

  - metadata:

      name: www

    spec:

      accessModes: [ "ReadWriteOnce" ]

      storageClassName: "slow"

      resources:

        requests:

          storage: 5Gi

[root@k8s-master statefulset]# kubectl apply -f statefulset.yaml

service/nginx created

statefulset.apps/web created

[root@k8s-master statefulset]# kubectl get statefulset

NAME   READY   AGE

web    0/3     10s

 

由于StatefulSet是2个副本,但是看到只创建了web-0。在创建web-1时出错了。这是由于没有可用的PV了。所以一个POD是绑定一个PVC的,每个POD所对应的存储空间是不一样的。

 

 

YAML

##在创建一个新的pv1

[root@k8s-master statefulset]# cat pv0.yml

apiVersion: v1

kind: PersistentVolume

metadata:

  name: pv-volume1

spec:

  capacity:

    storage: 8Gi

  volumeMode: Filesystem

  accessModes:

    - ReadWriteOnce

  persistentVolumeReclaimPolicy: Recycle

  storageClassName: slow

  mountOptions:

    - hard

    - nfsvers=4.1

  nfs:

    path: /home/k8s/nfs

    server: 172.16.4.169

[root@k8s-master statefulset]# kubectl apply -f pv0.yml

persistentvolume/pv-volume1 created

 

2.3、查看对应的服务

 

 

PowerShell

[root@k8s-master statefulset]# kubectl get pod,statefulset

NAME                                    READY   STATUS    RESTARTS   AGE

pod/myapp-deploy-786f88884c-89srx       1/1     Running   0          2d2h

pod/nginx-demo                          1/1     Running   0          24h

pod/nginx-deployment-644898db96-d7k77   1/1     Running   0          2d2h

pod/nginx-deployment-644898db96-rcxt5   1/1     Running   0          2d2h

pod/nginx-tcp-liveness-probe            0/1     Running   0          2d2h

pod/web-0                               1/1     Running   0          19m

pod/web-1                               1/1     Running   0          18m

 

NAME                   READY   AGE

statefulset.apps/web   2/2     19m

[root@k8s-master statefulset]# kubectl get pv,pvc

NAME                              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE

persistentvolume/pv-volume        50Gi       RWO            Recycle          Bound    default/www-web-0   slow                    23m

persistentvolume/pv-volume1       8Gi        RWO            Recycle          Bound    default/www-web-1   slow                    9m22s

persistentvolume/task-pv-volume   50Gi       RWO            Retain           Bound    default/pvc-claim   manual                  12d

 

NAME                              STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE

persistentvolumeclaim/pvc-claim   Bound    task-pv-volume   50Gi       RWO            manual         12d

persistentvolumeclaim/www-web-0   Bound    pv-volume        50Gi       RWO            slow           19m

persistentvolumeclaim/www-web-1   Bound    pv-volume1       8Gi        RWO            slow           18m

 

2.4、statefulset总结

匹配 Pod name ( 网络标识 ) 的模式为:$(statefulset名称)-$(序号),从零开始,比如上面的示例:web-0,web-1, web-2

StatefulSet 为每个 Pod 副本创建了一个 DNS 域名,这个域名的格式为: $(podname).(headless server name),也就意味着服务间是通过Pod域名来通信而非 Pod IP,因为当Pod所在Node发生故障时, Pod 会 被飘移到其它 Node 上,Pod IP 会发生变化,但是 Pod 域名不会有变化

StatefulSet 使用 Headless 服务来控制 Pod 的域名,这个域名的 FQDN 为:$(service name).$(namespace).svc.cluster.local

根据 volumeClaimTemplates,为每个 Pod 创建一个 pvc,pvc 的命名规则匹配模式: (volumeClaimTemplates.name)-(pod_name),比如上面的 volumeMounts.name=www, Pod name=web-[0-2],因此创建出来的 PVC 是 www-web-0、www-web-1、www-web-2

删除 Pod 不会删除其 pvc,手动删除 pvc 将自动释放 pv

 

Statefulset的启停顺序:

有序部署:部署StatefulSet时,如果有多个Pod副本,它们会被顺序地创建(从0到N-1),并且,在下一个 Pod运行之前所有之前的Pod必须都是Running和Ready状态。

有序删除:当Pod被删除时,它们被终止的顺序是从N-1到0。

有序扩展:当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态。

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2023年11月15日   31   0   0 k8s
  TEZNKK3IfmPf   2024年05月31日   26   0   0 nginxpasswd
  TEZNKK3IfmPf   2024年04月26日   37   0   0 linuxnginxcentos
  TEZNKK3IfmPf   2024年05月31日   28   0   0 nginxpasswd
  TEZNKK3IfmPf   2024年04月19日   24   0   0 nginxTCP
TEZNKK3IfmPf