• statefulset有状态应用管理


    statefulset介绍

    StatefulSet(有状态集,缩写为sts)常用于部署有状态的且需要有序启动的应用程序,比如在进行SpringCloud项目容器化时,Eureka的部署是比较适合用StatefulSet部署方式的,可以给每个Eureka实例创建一个唯一且固定的标识符,并且每个Eureka实例无需配置多余的Service,其余Spring Boot应用可以直接通过Eureka的Headless Service即可进行注册。
    Eureka的statefulset的资源名称是eureka,
    eureka-0 eureka-1 eureka-2
    Service:headless service,没有ClusterIP eureka-svc
    Eureka-0.eureka-svc.NAMESPACE_NAME eureka-1.eureka-svc

    StatefulSet的基本概念

        StatefulSet主要用于管理有状态应用程序的工作负载API对象。比如在生产环境中,可以部署ElasticSearch集群、MongoDB集群或者需要持久化的RabbitMQ集群、Redis集群、Kafka集群和ZooKeeper集群等。
        和Deployment类似,一个StatefulSet也同样管理着基于相同容器规范的Pod。不同的是,StatefulSet为每个Pod维护了一个粘性标识。这些Pod是根据相同的规范创建的,但是不可互换,每个Pod都有一个持久的标识符,在重新调度时也会保留,一般格式为StatefulSetName-Number。比如定义一个名字是Redis-Sentinel的StatefulSet,指定创建三个Pod,那么创建出来的Pod名字就为Redis-Sentinel-0、Redis-Sentinel-1、Redis-Sentinel-2。而StatefulSet创建的Pod一般使用Headless Service(无头服务)进行通信,和普通的Service的区别在于Headless Service没有ClusterIP,它使用的是Endpoint进行互相通信,Headless一般的格式为:
    
      statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster.local。
    
    说明:
    serviceName为Headless Service的名字,创建StatefulSet时,必须指定Headless Service名称;
    0..N-1为Pod所在的序号,从0开始到N-1;
    statefulSetName为StatefulSet的名字;
    namespace为服务所在的命名空间;
    .cluster.local为Cluster Domain(集群域)
    
    假如公司某个项目需要在Kubernetes中部署一个主从模式的Redis,此时使用StatefulSet部署就极为合适,因为StatefulSet启动时,只有当前一个容器完全启动时,后一个容器才会被调度,并且每个容器的标识符是固定的,那么就可以通过标识符来断定当前Pod的角色
    

    StatefulSet注意事项

    一般StatefulSet用于有以下一个或者多个需求的应用程序:
        需要稳定的独一无二的网络标识符。
        需要持久化数据。
        需要有序的、优雅的部署和扩展。
        需要有序的自动滚动更新。
    
        如果应用程序不需要任何稳定的标识符或者有序的部署、删除或者扩展,应该使用无状态的控制器部署应用程序,比如Deployment或者ReplicaSet。
    
        StatefulSet是Kubernetes 1.9版本之前的beta资源,在1.5版本之前的任何Kubernetes版本都没有。
        Pod所用的存储必须由PersistentVolume Provisioner(持久化卷配置器)根据请求配置StorageClass,或者由管理员预先配置,当然也可以不配置存储。
        为了确保数据安全,删除和缩放StatefulSet不会删除与StatefulSet关联的卷,可以手动选择性地删除PVC和PV(关于PV和PVC请参考2.2.12节)。    
        StatefulSet目前使用Headless Service(无头服务)负责Pod的网络身份和通信,需要提前创建此服务。
    删除一个StatefulSet时,不保证对Pod的终止,要在StatefulSet中实现Pod的有序和正常终止,可以在删除之前将StatefulSet的副本缩减为0 
    

    定义一个StatefulSet资源文件

    定义一个简单的StatefulSet的示例如下:
    Cat StatefulSet-1.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      ports:
      - port: 80
        name: web
      clusterIP: None  #这里可以有IP,也可以无IP,推荐无IP,也就是 无头service
      selector:
        app: nginx
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      serviceName: "nginx"
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.15.2
            ports:
            - containerPort: 80
              name: web
    

    此示例没有添加存储配置,后面的章节会单独讲解存储相关的知识点

    创建一个StatefulSet

    # 创建一个sts
    [root@k8s-m01 yaml-file]# kubectl create -f StatefulSet-1.yaml #-n namespace_name
    service/nginx created
    statefulset.apps/web created
    [root@k8s-m01 yaml-file]# kubectl get sts
    NAME   READY   AGE
    web    2/2     3s
    
    [root@k8s-m01 yaml-file]# kubectl get pod
    NAME                     READY   STATUS    RESTARTS   AGE
    web-0                    1/1     Running   0          73s
    web-1                    1/1     Running   0          72s
    
    
    [root@k8s-m01 yaml-file]# kubectl get svc
    NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   192.168.0.1   <none>        443/TCP   37d
    nginx        ClusterIP   None          <none>        80/TCP    2m59s 
    # <<--没有ClusterIP的service 简称 '无头service'
    

    无头service

    演示案例:

    cat sts-busybox.yaml
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: busybox
      namespace: default
    spec:
      containers:
      - name: busybox
        image: busybox:1.28
        command:
          - sleep
          - "3600"
        imagePullPolicy: IfNotPresent
      restartPolicy: Always
    
    #启动进入 busybox ping  StatefulSet的web节点,理解如何解析无头service
    
    [root@k8s-m01 yaml-file]# kubectl exec -it busybox -- sh
    
    #nslookup解析
    / # nslookup web-0.nginx
    Server:    192.168.0.10
    Address 1: 192.168.0.10 kube-dns.kube-system.svc.cluster.local
    
    Name:      web-0.nginx
    Address 1: 172.16.57.124 web-0.nginx.default.svc.cluster.local
    
    可以看到 可以直接ping通 service的名字
    

    缩容扩容StatefulSet

    [root@k8s-m01 yaml-file]# kubectl scale --replicas=3 sts web
    statefulset.apps/web scaled
    [root@k8s-m01 yaml-file]# kubectl get pod
    NAME                     READY   STATUS    RESTARTS   AGE
    nginx-55bbd66bbd-6n9jl   1/1     Running   0          9h
    nginx-55bbd66bbd-9gxhf   1/1     Running   0          9h
    web-0                    1/1     Running   0          6m54s
    web-1                    1/1     Running   0          6m53s
    web-2                    1/1     Running   0          4s
    
    [root@k8s-m01 yaml-file]# kubectl scale --replicas=2 sts web
    statefulset.apps/web scaled
    [root@k8s-m01 yaml-file]# kubectl get pod -o wide|grep web
    web-0                 1/1     Running   0        29m   172.16.57.124    k8s-n02
    web-1                 1/1     Running   0        29m   172.17.207.167   k8s-n01
    
    #查看sts标签
    [root@k8s-m01 yaml-file]# kubectl get pod --show-labels |grep web
    web-0    1/1     Running   0  30m   app=nginx,controller-revision-hash=web-6949d64dc8,statefulset.kubernetes.io/pod-name=web-0
    web-1    1/1     Running   0  30m   app=nginx,controller-revision-hash=web-6949d64dc8,statefulset.kubernetes.io/pod-name=web-1
    
    #过滤标签,找到属于某个标签下的pod
    [root@k8s-m01 yaml-file]# kubectl get pod -l controller-revision-hash=web-6949d64dc8
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          32m
    web-1   1/1     Running   0          32m
    
    
    #查看扩缩容过程:
     #执行命令监视pod变化动态
     kubectl get pod -l controller-revision-hash=web-6949d64dc8 -w
     
     #扩容sts
     [root@k8s-m01 ~]# kubectl scale --replicas=5 statefulset web
     statefulset.apps/web scaled
     
     #检查状态:
     [root@k8s-m01 yaml-file]# kubectl get pod -l controller-revision-hash=web-6949d64dc8 -w
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          42m
    web-1   1/1     Running   0          42m
    web-2   0/1     Pending   0          0s
    web-2   0/1     Pending   0          0s
    web-2   0/1     ContainerCreating   0          0s
    web-2   1/1     Running             0          2s
    web-3   0/1     Pending             0          0s
    web-3   0/1     Pending             0          0s
    web-3   0/1     ContainerCreating   0          0s
    web-3   1/1     Running             0          1s
    web-4   0/1     Pending             0          0s
    web-4   0/1     Pending             0          0s
    web-4   0/1     ContainerCreating   0          0s
    web-4   1/1     Running             0          1s
    可以看到扩容时,web序号呈现递增更新
    
    
    #缩容sts
    [root@k8s-m01 ~]# kubectl scale --replicas=3 statefulset web
     statefulset.apps/web scaled
     
    [root@k8s-m01 yaml-file]# kubectl get pod -l controller-revision-hash=web-6949d64dc8 -w
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          46m
    web-1   1/1     Running   0          46m
    web-2   1/1     Running   0          115s
    web-3   1/1     Running   0          113s
    web-4   1/1     Running   0          112s
    
    web-4   1/1     Terminating   0          2m1s
    web-4   0/1     Terminating   0          2m1s
    web-4   0/1     Terminating   0          2m2s
    web-4   0/1     Terminating   0          2m2s
    web-3   1/1     Terminating   0          2m3s
    web-3   0/1     Terminating   0          2m4s
    web-3   0/1     Terminating   0          2m4s
    web-3   0/1     Terminating   0          2m4s
    可以看到缩容时,web序号呈现倒序缩减
    
    
    #删除sts查看流程
    [root@k8s-m01 ~]# kubectl get pod
    NAME                     READY   STATUS    RESTARTS   AGE
    web-0                    1/1     Running   0          53m
    web-1                    1/1     Running   0          53m
    web-2                    1/1     Running   0          21s
    [root@k8s-m01 ~]# kubectl delete pod web-2
    pod "web-2" deleted
    
    [root@k8s-m01 yaml-file]# kubectl get pod -l controller-revision-hash=web-6949d64dc8 -w
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          53m
    web-1   1/1     Running   0          53m
    web-2   1/1     Running   0          13s
    
    web-2   1/1     Terminating   0          31s
    web-2   0/1     Terminating   0          31s
    web-2   0/1     Terminating   0          31s
    web-2   0/1     Terminating   0          31s
    web-2   0/1     Pending       0          0s
    web-2   0/1     Pending       0          0s
    web-2   0/1     ContainerCreating   0          0s
    web-2   1/1     Running             0          2s
    
    # sts 会保证副本数达到期望值,删除一个副本后会重新拉起一个新的副本
    [root@k8s-m01 ~]# kubectl get pod 
    NAME                     READY   STATUS    RESTARTS   AGE
    web-0                    1/1     Running   0          55m
    web-1                    1/1     Running   0          55m
    web-2                    1/1     Running   0          87s   #<=== 重新拉起的新副本
    

    注意:

    StatefulSet的pod也会被命名为 pod的name
    [root@k8s-m01 ~]# kubectl get pod 
    NAME                     READY   STATUS    RESTARTS   AGE
    web-0                    1/1     Running   0          55m
    web-1                    1/1     Running   0          55m
    web-2                    1/1     Running   0          87s 
    
    [root@k8s-m01 ~]# kubectl exec -it web-0 -- sh
    # hostname  
    web-0
    

    StatefulSet更新策略

    1. RollingUpdate 更新策略

    #监视 statefulset 
    kubectl get pod -l statefulset.kubernetes.io/pod-name
    
    #修改nginx版本让它进行滚动更新
    [root@k8s-m01 ~]# kubectl edit sts web
    
    #默认更新策略RollingUpdate
      updateStrategy:
        rollingUpdate:
          partition: 0       #不更新小于 N 的副本
        type: RollingUpdate
    
    
    #检查更新过程
    [root@k8s-m01 ~]# kubectl get pod -l statefulset.kubernetes.io/pod-name -w
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          8m44s
    web-1   1/1     Running   0          8m47s
    web-2   1/1     Running   0          8m50s
    
    web-2   1/1     Terminating   0          9m26s
    web-2   0/1     Terminating   0          9m27s
    web-2   0/1     Terminating   0          9m27s
    web-2   0/1     Terminating   0          9m27s
    web-2   0/1     Pending       0          0s
    web-2   0/1     Pending       0          0s
    web-2   0/1     ContainerCreating   0          0s
    web-2   1/1     Running             0          2s
    web-1   1/1     Terminating         0          9m26s
    web-1   0/1     Terminating         0          9m27s
    web-1   0/1     Terminating         0          9m27s
    web-1   0/1     Terminating         0          9m27s
    web-1   0/1     Pending             0          0s
    web-1   0/1     Pending             0          0s
    web-1   0/1     ContainerCreating   0          0s
    web-1   1/1     Running             0          1s
    web-0   1/1     Terminating         0          9m25s
    web-0   0/1     Terminating         0          9m26s
    web-0   0/1     Terminating         0          9m26s
    web-0   0/1     Terminating         0          9m26s
    web-0   0/1     Pending             0          0s
    web-0   0/1     Pending             0          0s
    web-0   0/1     ContainerCreating   0          0s
    web-0   1/1     Running             0          1s
    
    #可以看到更新过程会先从 web-2 更新,倒序更新
    

    2. Ondelete 更新策略 [适用于灰度发布]

     [root@k8s-m01 yaml-file]# kubectl edit sts web
     
     修改:
       updateStrategy:
        rollingUpdate:
          partition: 0
        type: RollingUpdate
     
     改为:
       updateStrategy:
        type: OnDelete   #修改为OnDelete更新模式并保存,该更新策略是,删除时才会进行更新
        
        
    
    #检查策略更新过程    
    开启一个窗口进行监视pod过程
    #  kubectl get pod -l statefulset.kubernetes.io/pod-name -w
    
    
    #此时修改一个镜像版本,看是否像之前一样会被更新
    - image: nginx:1.15.1 修改为 - image: nginx:1.15.3
    
    #这时候另一个窗口完全没有变化
    
    
    #删除pod查看窗口变化:
    [root@k8s-m01 yaml-file]# kubectl get pod -l statefulset.kubernetes.io/pod-name
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          8m31s
    web-1   1/1     Running   0          8m34s
    web-2   1/1     Running   0          8m37s
    
    [root@k8s-m01 yaml-file]# kubectl delete pod web-0
    pod "web-0" deleted
    
    #另一个窗口的变化:
    [root@k8s-m01 ~]# kubectl get pod -l statefulset.kubernetes.io/pod-name -w
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          11m
    web-1   1/1     Running   0          11m
    web-2   1/1     Running   0          12m
    
    
    web-0   1/1     Terminating   0          15m
    web-0   0/1     Terminating   0          15m
    web-0   0/1     Terminating   0          15m
    web-0   0/1     Terminating   0          15m
    web-0   0/1     Pending       0          0s
    web-0   0/1     Pending       0          0s
    web-0   0/1     ContainerCreating   0          0s
    web-0   1/1     Running             0          1s
    
    可以看到这时候web-0已经开始发生变化,这时候检查该pod版本是否被更新:
    
    [root@k8s-m01 yaml-file]# kubectl get pod -o wide
    NAME READY STATUS RESTARTS AGE IP            NODE  NOMINATED NODE READINESS GATES
    web-0 1/1  Running  0      64s 172.17.207.176 k8s-n01  <none>  <none>  #<--被更新
    web-1 1/1  Running  0      16m 172.17.207.174 k8s-n01  <none>  <none>
    web-2 1/1  Running  0      16m 172.16.57.68   k8s-n02  <none>  <none>
    
    #检查版本:
    kubectl get pod web-0 -o yaml|grep image #也可以用这个命令来看版本
    
    [root@k8s-m01 yaml-file]# kubectl exec -it web-0 -- sh
    # nginx -v
    nginx version: nginx/1.15.3
    
    [root@k8s-m01 yaml-file]# kubectl exec -it web-1 -- sh
    # nginx -v
    nginx version: nginx/1.15.2
    
    [root@k8s-m01 yaml-file]# kubectl exec -it web-2 -- sh
    # nginx -v
    nginx version: nginx/1.15.2
    
    结论:
    OnDelete策略只会在pod被删除时进行更新版本,该方法在进行灰度发布时效果较好
    

    yaml中参数 partition含义 #分段更新配置

    updateStrategy 
      rollingUpdate:
        partition: 2  #副本大于设置的值时进行更新,也就是分段更新,这里是大于2的副本更新
      type: RollingUpdate
    

    partition: 2 #不更新小于 N 的副本
     
    案例:
    修改当前statefulset配置添加更新参数:
    
    kubectl edit sts web
    
    找到: 
    updateStrategy:
      type: OnDelete
        
    修改为:   
    updateStrategy:
      type: RollingUpdate
      rollingUpdate:
        partition: 2
    
    顺便修改镜像版本:
    - image: nginx:1.15.3 修改为 - image: nginx:1.15.2
        
    新开窗口监视变化
    kubectl get pod -l statefulset.kubernetes.io/pod-name -w  
    
    修改镜像版本进行更新测试   partition: 2 参数
    
    #这里可以看到 保留2个副本后,只有web-2进行了自动更新,web-0 web-1都没有更新 
    [root@k8s-m01 ~]# kubectl get pod -l statefulset.kubernetes.io/pod-name -w
    NAME    READY   STATUS    RESTARTS   AGE
    web-0   1/1     Running   0          21m
    web-1   1/1     Running   0          22m
    web-2   1/1     Running   0          21m
    web-2   1/1     Terminating   0          22m
    web-2   0/1     Terminating   0          22m
    web-2   0/1     Terminating   0          22m
    web-2   0/1     Terminating   0          22m
    web-2   0/1     Pending       0          0s
    web-2   0/1     Pending       0          0s
    web-2   0/1     ContainerCreating   0          0s
    web-2   1/1     Running             0          1s  
    
    #检查更新结果:
    [root@k8s-m01 yaml-file]# kubectl get pod -l statefulset.kubernetes.io/pod-name -o yaml|grep image
        - image: nginx:1.15.3
          imagePullPolicy: IfNotPresent
          image: nginx:1.15.3
          imageID: docker-pullable://nginx@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
        - image: nginx:1.15.3
          imagePullPolicy: IfNotPresent
          image: nginx:1.15.3
          imageID: docker-pullable://nginx@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
        - image: nginx:1.15.2
          imagePullPolicy: IfNotPresent
          image: nginx:1.15.2
          imageID: docker-pullable://nginx@sha256:d85914d547a6c92faa39ce7058bd7529baacab7e0cd4255442b04577c4d1f424
     
     可以看到只有一个nginx进行了更新到了 1.15.2
     这就是 partition 参数的作用,在进行灰度发布时作用较大
    

    statefulset删除

    statefulset删除分为两种
    
    级联删除[默认]
    删除statefulset时删除pod
    
    
    非级联删除
    删除statefulset时不删除pod
    
    
    
    级联删除:
    默认级联删除时 会删除statefulset和pod
    
    [root@k8s-m01 yaml-file]# kubectl delete sts web
    statefulset.apps "web" deleted
    [root@k8s-m01 yaml-file]# kubectl delete svc nginx
    service "nginx" deleted
    [root@k8s-m01 yaml-file]# kubectl get pod -l statefulset.kubernetes.io/pod-name
    No resources found in default namespace.  #删除后 web这个sts pod 已经没了
    
    
    
    非级联删除:
    [root@k8s-m01 yaml-file]# kubectl create -f StatefulSet-1.yaml
    service/nginx created
    statefulset.apps/web created
    [root@k8s-m01 yaml-file]# kubectl get pod
    NAME                     READY   STATUS    RESTARTS      AGE
    web-0                    1/1     Running   0             7m
    web-1                    1/1     Running   0             5m
    
    非级联删除:
    [root@k8s-m01 yaml-file]# kubectl delete sts web --cascade=orphan
    statefulset.apps "web" deleted
    
    检查:
    [root@k8s-m01 yaml-file]# kubectl get sts
    No resources found in default namespace.
    
    #此时这些pod会变成 孤儿pod,可以删除并不会被重建
    [root@k8s-m01 yaml-file]# kubectl get pod
    NAME                     READY   STATUS    RESTARTS      AGE
    web-0                    1/1     Running   0             7m
    web-1                    1/1     Running   0             5m
    
    非级联删除时,删除了sts 但是pod并未被删除
    #kubernetes 1.24以前版本参数 --cascade=false
    #kubernetes 1.24以后版本参数 --cascade=orphan
    
  • 相关阅读:
    模拟伪造浏览器并获取json数据:
    Inno Setup命令行安装卸载参数
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——EmpDao层代码
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——hibernate的config文件(hibernate.cfg.xml)
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——hibernate的config文件(hibernate.cfg.xml)
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Dept实体类和对应的配置信息
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Dept实体类和对应的配置信息
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Emp实体类和对应的配置信息
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Emp实体类和对应的配置信息
    常用的字符串加密解密工具类
  • 原文地址:https://www.cnblogs.com/superlinux/p/16333832.html
Copyright © 2020-2023  润新知