zoukankan      html  css  js  c++  java
  • StatefulSet

    StatefulSet

     

    • 部署有状态应用 
      • 什么是无状态服务:

            deployment部署的pod属于无状态服务,控制器中的Pod因为物理节点,从一个Node漂移到另一个Node.或者在当前服务下直接拉起一个新的pod,这些操作都不影响服务的运行状态。即Pod的网络地址,存储与pod中的应用没有强依赖关系。比如:web的集群服务。

      •  什么是有状态服务:

              控制器中的每个Pod都有自己存储位置和存储内容,多个Pod之间的启动有严格的顺序,pod之间有独立的通讯要求。比如etcd数据库。

      • 有状态应用部署需要考虑: 
        1. 稳定的网络ID,实例之间通信地址要固定 
        2. 实例的独立存储
        3. 先后的启动顺序
        4. 应用场景:分布式应用(mysql,zk,etcd)
    • 解决pod独立生命周期,保持pod启动顺序和唯一性
      1. 稳定,唯一的网络标识符,持久存储
      2. 有序,优雅的部署和扩展、删除、终止
      3. 有序,流动更新

     

    稳定的网络ID

             实现方法:Headless Service

    • normal service 与 Headless Service区别

     

    Headless服务与正常的服务相比多了一个字段:ClusterIP: None. 在normal service中这个字段的地址是做VIP的,客户端访问后端服务时不需要知道后台服务器的真实地址,它只需要访问VIP,service的负载均衡器会把它的请求转发给其中一个服务器。而heardless service不需要这个VIP。例如,Client访问mysql的主从服务时,client的读写请求要么是访问主,要么是访问从,它不能把请求服务给VIP,让vip转发。

     

    1)用yaml文件生成一个headless service

         手动快速生成一个headless service的yaml文件

    [root@master ~]# kubectl create deploy web --image=nginx 
    deployment.apps/web created
    [root@master ~]# kubectl  expose deploy web --port=80 --target-port=80  --dry-run -o yaml > service-headless.yaml
    W0821 17:01:11.402969    2689 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client.
    [root@master ~]# 
    [root@master ~]#                                 #删除时间戳和状态字段,添加clusetrIP
    [root@master statefulset]# vim  service-headless.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: web
      name: web
    spec:
      clusterIP: None
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        app: web
    [root@master statefulset]# 
    
    
    [root@master statefulset]# kubectl apply -f service-headless.yaml 
    service/web created
    [root@master statefulset]# kubectl get svc
    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   279d
    web          ClusterIP   None         <none>        80/TCP    3s
    [root@master statefulset]# 

    1)用yaml文件生成一个statefulset

    快速复制一份statefulset文件

                                      #从任意地址拷贝一份deployment
                                      #复制后对部分字段进行修改,修改kind,replicas.  删除浅色部分
    [root@master statefulset]# cp ../../PV-PVC/deployment-web.yaml   statefulset-headless.yaml
    [root@master statefulset]#         
    [root@master statefulset]# cat statefulset-headless.yaml 
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: web
      name: web
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: web
      strategy: {}
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
          - image: nginx
            name: nginx
            resources: {}
            volumeMounts:
            - name: data
              mountPath: /usr/share/nginx/html
    
          volumes:
          - name: data
            nfs:
              server: 192.168.1.63
              path: /ifs/kubernetes
    
                                   # 添加 serviceName,注意这里serviceName 的值是service-headless.yaml中metadata.name                              
     [root@master statefulset]# vim statefulset-headless.yaml 
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      serviceName: "web"
      replicas: 3
      selector: 
        matchLabels:
          app: web
      template: 
        metadata:
          labels:
            app: web
        spec:
          containers:
          - image: nginx
            name: nginx
    [root@master statefulset]#          
    [root@master statefulset]# kubectl apply -f statefulset-headless.yaml 
    statefulset.apps/web created
    [root@master statefulset]#        #观察statefulset控制器生成的pod时的命名规律
    [root@master statefulset]# kubectl get pod
    NAME                   READY   STATUS    RESTARTS   AGE
    web-0                  1/1     Running   0          58s
    web-1                  1/1     Running   0          36s
    web-2                  1/1     Running   0          19s
    [root@master statefulset]# 

    3) 再用deployment生成副本为3的pod, 同时生成一个normal server与之关联,用于与statefulset做比较

    [root@master statefulset]# kubectl create deploy web2 --image=nginx
    deployment.apps/web2 created
    [root@master statefulset]# kubectl scale deploy web2 --replicas=3
    deployment.apps/web2 scaled
    [root@master statefulset]# kubectl expose deploy web2 --port=80 --target-port=80
    service/web2 exposed
    [root@master statefulset]#         #比较deploy,satefulset的pod的不同之处             
    [root@master statefulset]# kubectl get pod
    NAME                    READY   STATUS    RESTARTS   AGE
    web-0                   1/1     Running   0          23m
    web-1                   1/1     Running   0          22m
    web-2                   1/1     Running   0          22m
    web2-6448bfd7b7-5bv5q   1/1     Running   0          2m8s
    web2-6448bfd7b7-nht29   1/1     Running   0          2m37s
    web2-6448bfd7b7-wrh6t   1/1     Running   0          2m8s
    [root@master statefulset]# 
    [root@master statefulset]#         #比较normal server, headless service的不同之处
    [root@master statefulset]# kubectl get svc
    NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    web          ClusterIP   None            <none>        80/TCP    61m
    web2         ClusterIP   10.110.187.41   <none>        80/TCP    97s
    [root@master statefulset]# 
    
                                      #查看pod的IP
    [root@master ~]# kubectl get pod -o wide
    NAME                    READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
    sh                      1/1     Running   0          8m    10.244.2.31    node2   <none>           <none>
    web-0                   1/1     Running   0          43m   10.244.1.192   node1   <none>           <none>
    web-1                   1/1     Running   0          43m   10.244.2.27    node2   <none>           <none>
    web-2                   1/1     Running   0          43m   10.244.1.193   node1   <none>           <none>
    web2-6448bfd7b7-5bv5q   1/1     Running   0          22m   10.244.2.30    node2   <none>           <none>
    web2-6448bfd7b7-nht29   1/1     Running   0          23m   10.244.2.28    node2   <none>           <none>
    web2-6448bfd7b7-wrh6t   1/1     Running   0          22m   10.244.2.29    node2   <none>           <none>
    [root@master ~]# 

    4) 用busybox镜像启动一个临时的pod,在容器内用DNS做解析,比较headless service的不同之处

    # --rm 表示容器退出时,自动清除容器内的文件系统 [root@master statefulset]# kubectl run -it --rm --image=busybox:1.28.4 sh If you don't see a command prompt, try pressing enter. / # / # 在pod内分别对normal service, headless service做域名解析,比较不同之处。 DNS解析web2时返回的结果是clusterIP,与 <service-name>.<namespace-name>.svc.cluster.local的对应关系,clusterIP对应的是哪个pod 我们并不知道,但是解析web时返回的结果是pod的Ip与<statefulsetName-index>.<service-name> .<namespace-name>.svc.cluster.local 之间的对应关系,也即:每个pod的IP对应当前pod的主机名是唯一对应的。 / # nslookup web2.default Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: web2.default Address 1: 10.110.187.41 web2.default.svc.cluster.local / # / # nslookup web.default Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: web.default Address 1: 10.244.1.193 web-2.web.default.svc.cluster.local Address 2: 10.244.1.192 web-0.web.default.svc.cluster.local Address 3: 10.244.2.27 web-1.web.default.svc.cluster.local / # CoreDNS对headless的解析时,它解析的是pod的名字与pod的地址的对应关系 当使用headless service,且statefulset中serviceName字段又指定这个headless service时,这就已告诉statefulset它所管理的pod的身份是由headless来保证的。控制器的service不再为pod提供clusterIP,而是为每个pod提供一个固定的DNS名字,这个dns名字就是pod的name,即web-0,web-1,web-2. [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE sh 1/1 Running 0 8m14s web-0 1/1 Running 0 44m web-1 1/1 Running 0 43m web-2 1/1 Running 0 43m [root@master ~]# [root@master ~]# kubectl exec -it web-0 -- bash root@web-0:/# hostname web-0 root@web-0:/# root@web-0:/# cat /etc/hosts # Kubernetes-managed hosts file. 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet fe00::0 ip6-mcastprefix fe00::1 ip6-allnodes fe00::2 ip6-allrouters 10.244.1.192 web-0.web.default.svc.cluster.local web-0 root@web-0:/#

    5)service提供的稳定网络ID的格式

                        ClusterIP  ip地址   记录格式:

                                      <service-name>.<namespace-name>.svc.cluster.local

                         示例:   web2.default.svc.cluster.local

     

                        ClusterIP=None    记录格式:

                                       <statefulsetName-index>.<service-name> .<namespace-name>.svc.cluster.local

                         示例:    web-0.web.default.svc.cluster.local

    稳定的存储

    1) 用deploy创建三个pod运行web服务,三个web服务器共用一个PV, 使用动态PV来实现

      • 因为动态pvc使用的是nfs的存储类型,所以这里配置storageclass之外,还要安装让nfs支持动态pvc的插件。所以这里用了三个文件分别是

    class.yaml,deployment.yaml,rbac.yaml

    [root@master storage]# kubectl apply -f class.yaml 
    storageclass.storage.k8s.io/managed-nfs-storage created
    [root@master storage]# kubectl apply -f deployment.yaml 
    serviceaccount/nfs-client-provisioner created
    deployment.apps/nfs-client-provisioner created
    [root@master storage]# kubectl apply -f rbac.yaml 
    serviceaccount/nfs-client-provisioner unchanged
    clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
    clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
    role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
    rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
    [root@master storage]# 
      •  用deploy的yaml文件生成三个pod,并用yam文件生成pvc,注意观察这两个文件的关联方法
    [root@master storage]# cat  deploy-pvc.yaml 
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: web
      name: web
    spec:
      name: web
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: web
      template:
        metadata:
          labels:
            app: web
        spec:
          containers:
          - image: nginx
            name: nginx
            volumeMounts:
            - name: data
              mountPath: /usr/share/nginx/html
    
          volumes:
          - name: data
            persistentVolumeClaim:
              claimName: my-pvc2
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-pvc2
    spec:
      storageClassName: "managed-nfs-storage"     #这里的storageClassName的名字是上面class.yaml中SC的名字,用kubectl get sc查看
      accessModes:                                
        - ReadWriteMany
      resources:
        requests:
          storage: 9Gi    
    [root@master storage]# 
    [root@master storage]# kubectl apply -f deploy-pvc.yaml 
    deployment.apps/web created
    persistentvolumeclaim/my-pvc2 created
    [root@master storage]#
      • 查看创建的资源,虽然deploy创建了三个pod,但他们共用一个pvc,共用一个pv
    [root@master storage]# kubectl get pod
    NAME                                      READY   STATUS    RESTARTS   AGE
    nfs-client-provisioner-7676dc9cfc-c9z7s   1/1     Running   0          9m59s
    web-748845d84d-mgwzc                      1/1     Running   0          81s
    web-748845d84d-nskhl                      1/1     Running   0          81s
    web-748845d84d-p6xg7                      1/1     Running   0          81s
    [root@master storage]#
    [root@master storage]# kubectl get pvc
    NAME      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
    my-pvc2   Bound    pvc-cae4b9e0-3c10-4e14-b435-835c2ceea446   9Gi        RWX            managed-nfs-storage   88s
    [root@master storage]# 
    [root@master storage]# kubectl get pv
    NAME                                     CAPACITY ACCESS MODES  RECLAIM POLICY  STATUS  CLAIM           STORAGECLASS         AGE
    pvc-cae4b9e0-3c10-4e14-b435-835c2ceea446 9Gi      RWX           Delete          Bound   default/my-pvc2 managed-nfs-storage  103s
    [root@master storage]# 

    2)用statefulset创建三个pod运行web服务,三个web服务器分别用自己独立的pv, 使用动态PV

      • 注意deploy使用的是PVC,statefulset使用的是VCT,VCT是statefulset特有资源。在statefulset中不再需要volumes:字段
    [root@master storage]# cat statefulset-vct.yaml 
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      selector:
        matchLabels:
          app: nginx 
      serviceName: "headless-svc"
      replicas: 3 
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx 
            ports:
            - containerPort: 80
              name: web
            volumeMounts:
            - name: www                      #卷的name要与vct的name一致
              mountPath: /usr/share/nginx/html
      volumeClaimTemplates:
      - metadata:
          name: www
        spec:
          accessModes: [ "ReadWriteOnce" ]
          storageClassName: "managed-nfs-storage"
          resources:
            requests:
              storage: 2Gi
    [root@master storage]# 
    [root@master storage]# kubectl apply -f statefulset-vct.yaml 
    statefulset.apps/web created
    [root@master storage]#
      • 查看创建的资源,有三个pod分别是web-0,web-1,web-2 有三个PVC和三个PV
    [root@master storage]# kubectl get pod
    NAME                                      READY   STATUS    RESTARTS   AGE
    nfs-client-provisioner-7676dc9cfc-c9z7s   1/1     Running   0          36m
    web-0                                     1/1     Running   0          4m43s
    web-1                                     1/1     Running   0          4m15s
    web-2                                     1/1     Running   0          3m57s
    web-748845d84d-mgwzc                      1/1     Running   0          28m
    web-748845d84d-nskhl                      1/1     Running   0          28m
    web-748845d84d-p6xg7                      1/1     Running   0          28m
    [root@master storage]# 
    
    [root@master storage]# kubectl get pvc
    NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
    my-pvc2     Bound    pvc-cae4b9e0-3c10-4e14-b435-835c2ceea446   9Gi        RWX            managed-nfs-storage   29m
    www-web-0   Bound    pvc-c826db3b-8314-44c4-aa73-1b981c036c9e   2Gi        RWO            managed-nfs-storage   6m15s
    www-web-1   Bound    pvc-77d1d297-c463-40de-90f8-e5c44527f530   2Gi        RWO            managed-nfs-storage   5m47s
    www-web-2   Bound    pvc-052d0234-b350-434a-a7c0-8eed56f5eb55   2Gi        RWO            managed-nfs-storage   5m29s
    [root@master storage]# 
    
    [root@master storage]# kubectl get pv
    NAME                                      CAPACITY ACCESS MODES  RECLAIM POLICY STATUS CLAIM             STORAGECLASS         AGE
    pvc-052d0234-b350-434a-a7c0-8eed56f5eb55  2Gi      RWO           Delete         Bound  default/www-web-2 managed-nfs-storage  6m3s
    pvc-77d1d297-c463-40de-90f8-e5c44527f530  2Gi      RWO           Delete         Bound  default/www-web-1 managed-nfs-storage  6m21s
    pvc-c826db3b-8314-44c4-aa73-1b981c036c9e  2Gi      RWO           Delete         Bound  default/www-web-0 managed-nfs-storage  6m49s
    pvc-cae4b9e0-3c10-4e14-b435-835c2ceea446  9Gi      RWX           Delete         Bound  default/my-pvc2   managed-nfs-storage  30m
    [root@master storage]# 
      • 进入statefulset的不同pod写入不同数据,在nfs的物理目录中验证
    [root@master storage]# kubectl exec -it web-0 -- bash
    root@web-0:/# cd /usr/share/nginx/html/
    root@web-0:/usr/share/nginx/html# echo hello 0 > index.html
    root@web-0:/usr/share/nginx/html# ls 
    index.html
    root@web-0:/usr/share/nginx/html# exit
    exit
    [root@master storage]# kubectl exec -it web-1 -- bash
    root@web-1:/# cd /usr/share/nginx/html/
    root@web-1:/usr/share/nginx/html# echo hello 1 > index.html
    root@web-1:/usr/share/nginx/html# ls 
    index.html
    root@web-1:/usr/share/nginx/html# exit
    exit
    [root@master storage]# 
                      
    [root@node2 kubernetes]# pwd
    /ifs/kubernetes
    [root@node2 kubernetes]# ls
    default-my-pvc2-pvc-cae4b9e0-3c10-4e14-b435-835c2ceea446    default-www-web-1-pvc-77d1d297-c463-40de-90f8-e5c44527f530
    default-www-web-0-pvc-c826db3b-8314-44c4-aa73-1b981c036c9e  default-www-web-2-pvc-052d0234-b350-434a-a7c0-8eed56f5eb55
    [root@node2 kubernetes]# cat default-www-web-0-pvc-c826db3b-8314-44c4-aa73-1b981c036c9e/index.html 
    hello 0
    [root@node2 kubernetes]# cat default-www-web-1-pvc-77d1d297-c463-40de-90f8-e5c44527f530/index.html 
    hello 1
    [root@node2 kubernetes]#
  • 相关阅读:
    js设置滚动条定位到所属容器的最底部
    js如何获取前后连续n天的时间
    vue实现点击区域外部的区域,关闭该区域
    使用typed.js实现页面上的写字功能
    Python3基础 函数 多值参数 元组与字典形式(键值对分别指出)
    Python3基础 函数 返回值 利用元组返回多个值
    Python3基础 变量命名 区分大小写
    Python3基础 函数 参数为list可变类型时,使用append会影响到外部实参
    Python3基础 函数 多值参数 元组与字典形式(使用星号对列表与字典进行拆包)
    Python3基础 函数 参数 多个参数都有缺省值,需要指定参数进行赋值
  • 原文地址:https://www.cnblogs.com/sven-pro/p/15542496.html
Copyright © 2011-2022 走看看