• Kubernetes StatefulSet


    StatefulSet 简介

    在Kubernetes中,Pod的管理对象RC、Deployment、DaemonSet和Job都是面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Akka集群、ZooKeeper集群等

    以上集群有几个共同点: 1.每个节点都有固定的身份ID,通过这个ID,集群中的成员可以互相发现并且通信 2.集群的规模是比较固定的,集群规模不能随意变动。 3.集群里的每个节点都是有状态的,通常会持久化数据到永久存储中 4.如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。

    如果用RC/Deployment 控制Pod 副本数的方式来实现上述有状态的集群,则我们会发现第一点是无法满足的,因为Pod的名字是随机产生的,Pod的IP地址也是在运行期才确定且可能有变动的,我们事先无法为每个Pod确定唯一不变的ID。另外,为了能够在其他节点上恢复某个失败的节点,这种集群中的Pod 需要挂载某种共享存储,Kubernetes在1.4版本引入了PetSet这个新资源对象,在1.5更名为"StatefulSet"。StatefulSet 从本质来将,可以看作Deployment/RC 的一种特殊变种

    StatefulSet 特点

    StatefulSet特点:

    1.StatefulSet 里的每个Pod都有稳定、唯一的网络表示,可以用来发现集群内的其他成员。(假设StatefulSet 的名字叫kafka,那么第一个Pod叫kafka-0,第二个Pod叫kafka-1以此类推) 2.StatefulSet 控制的Pod副本的启动顺序是受控制的,操作第n个Pod,前n-1个Pod已经是运行且准备好的状态 3.StatefulSet 里的Pod采用稳定的持久化存储卷,通过PV/PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)

    StatefulSet是为了解决有状态服务的问题(对应DeploymentReplica Set是为无状态服务而设计),其应用场景包括

    • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
    • 稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
    • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
    • 有序收缩,有序删除(即从N-1到0

    从上面的应用场景可以发现,StatefulSet由以下几个部分组成:

    • 用于定义网络标志(DNS domain)的Headless Service
    • 用于创建PersistentVolumes的volumeClaimTemplates
    • 定义具体应用的StatefulSet

    StatefulSet 原理

    StatefulSet由Service和volumeClaimTemplates组成。Service中的多个Pod将会被分别编号,并挂载volumeClaimTemplates中声明的PV。

    注意: 官方提示StatefulSets在1.9中是稳定的

    案例:K8s企业实践使用storageclass实现动态存储

    StatefulSet 除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service配合使用,在每个StatfulSet的定义中要声明它属于哪个Headless Service.Headless Service 与普通Service的关键区别在于, Headless Service它没有Cluster IP,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表

    StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod实力创建了一个DNS域名,这个域名的格式为: ${podname}.${headless service name}

    比如一个3节点的Kafka的StatefulSet集群,对应的Headless Service的名字为kafka,StatefulSet的名字为kafka,则StatefulSet 里面的3个Pod的DNS分别为kafka-0.kafka、kafka-1.kafka、kafka-3.kafka,这些DNS名称可以直接在集群的配置文件中固定下来。

    简单点说:没有部署HeadlessService的话,PetSet/StatefulSet下的pod,无法通过域名进行访问。

    实例演示

    官方演示地址 首先使用以下示例创建StatefulSet以一个简单的nginx服务web.yaml为例

    StatefulSet注意事项

    • 还在beta状态,需要kubernetes v1.5版本以上才支持
    • 所有Pod的Volume必须使用PersistentVolume或者是管理员事先创建好
    • 为了保证数据安全,删除StatefulSet时不会删除Volume
    • StatefulSet需要一个Headless Service来定义DNS domain,需要在StatefulSet之前创建好
    • 目前StatefulSet还没有feature complete,比如更新操作还需要手动patch。

    案例开始

    application/web/web.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:
      serviceName: "nginx"
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: k8s.gcr.io/nginx-slim:0.8
            ports:
            - containerPort: 80
              name: web
            volumeMounts:
            - name: www
              mountPath: /usr/share/nginx/html
      volumeClaimTemplates:
      - metadata:
          name: www
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 1Gi
    
    $ kubectl create -f web.yaml
    service "nginx" created
    statefulset "web" created
    
    # 查看创建的headless service和statefulset
    $ kubectl get service nginx
    NAME      CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    nginx     None         <none>        80/TCP    1m
    $ kubectl get statefulset web
    NAME      DESIRED   CURRENT   AGE
    web       2         2         2m
    
    # 根据volumeClaimTemplates自动创建PVC(在GCE中会自动创建kubernetes.io/gce-pd类型的volume)
    $ kubectl get pvc
    NAME        STATUS    VOLUME                                     CAPACITY   ACCESSMODES   AGE
    www-web-0   Bound     pvc-d064a004-d8d4-11e6-b521-42010a800002   1Gi        RWO           16s
    www-web-1   Bound     pvc-d06a3946-d8d4-11e6-b521-42010a800002   1Gi        RWO           16s
    
    # 查看创建的Pod,他们都是有序的
    $ kubectl get pods -l app=nginx
    NAME      READY     STATUS    RESTARTS   AGE
    web-0     1/1       Running   0          5m
    web-1     1/1       Running   0          4m
    
    # 使用nslookup查看这些Pod的DNS
    $ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
    / # nslookup web-0.nginx
    Server:    10.0.0.10
    Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
    
    Name:      web-0.nginx
    Address 1: 10.244.2.10
    / # nslookup web-1.nginx
    Server:    10.0.0.10
    Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
    
    Name:      web-1.nginx
    Address 1: 10.244.3.12
    / # nslookup web-0.nginx.default.svc.cluster.local
    Server:    10.0.0.10
    Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
    
    Name:      web-0.nginx.default.svc.cluster.local
    Address 1: 10.244.2.10
    

    Statefulset 扩容与缩容

    # 扩容
    $ kubectl scale statefulset web --replicas=5
    
    # 缩容
    $ kubectl patch statefulset web -p '{"spec":{"replicas":3}}'
    
    # 镜像更新(目前还不支持直接更新image,需要patch来间接实现)
    $ kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.7"}]'
    
    # 删除StatefulSet和Headless Service
    $ kubectl delete statefulset web
    $ kubectl delete service nginx
    
    # StatefulSet删除后PVC还会保留着,数据不再使用的话也需要删除
    $ kubectl delete pvc www-web-0 www-web-1
  • 相关阅读:
    在Ubuntu 桌面版 12.04 LTS安装并运行SSH
    将Tp-link无线路由器桥接到Dlink无线路由器上
    如何解决Win7将任务栏程序自动分组的困扰
    安装Ubuntu 桌面版 12.04 LTS 过程之记录
    #lspci | grep Eth
    做技术不能人云亦云
    如何使用FF的Firebug组件中的net工具查看页面元素加载消耗时间
    在Fedora8上安装使用ActiveMQ5.8
    多态继承中的内存图解 && 多态中的对象变化的内存图解
    孔子装爹案例_帮助理解多态的成员访问特点及转型
  • 原文地址:https://www.cnblogs.com/weifeng1463/p/11624105.html
Copyright © 2020-2023  润新知