zoukankan      html  css  js  c++  java
  • StatefulSet

    一、简介

    在Kubernetes系统中,Pod的管理对象RC、Deployment、DaemonSet和Job都面向无状态的服务。但是有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Kafka集群、zookeeper集群等,这些应用集群有4个共同点:

    • 每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现并通信

    • 集群的规模是比较固定的,集群规模不能随意变动

    • 集群中的每个节点都是有状态的,通常会持久化数据到永久存储中

    • 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损

     

    StatefulSet旨在与有状态的应用及分布式系统一起使用,它有如下特性:

    • StatefulSet里每个Pod都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。假设StatefulSet的名称为Kafka,那么第一个Pod叫Kafka-0,第二个叫Kafka-1,以此类推

    • StatefulSet控制的Pod副本启停顺序是受控的,操作第n个Pod时,前n-1个Pod已经是运行且准备好的状态

    • StatefulSet的Pod采用稳定的持久化存储卷,通过PV或者PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷

     

    StatefulSet除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service配合使用,即在每个StatefulSet定义中都要声明它属于哪个Headless Service。Headless Service于普通Service的关键区别在于,它没有Cluster IP,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表。StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod实例创建了一个DNS域名,这个域名格式为: $(podname).$(headless service name)

    二、使用StatefulSet搭建MongoDB集群

    为了完成MongoDB集群的搭建,需要创建如下三个资源对象

    • 一个StorageClass,用于StatefulSet自动为各个应用Pod申请PVC

    • 一个Headless Service,用于维护MongoDB的集群状态

    • 一个StatefulSet

    2.1创建一个StorageClass对象

    storageclass-fast.yaml

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: fast
    provisioner: kubernetes.io/glusterfs
    parameters:
      restful: http://192.168.10.106:18080

    执行kubectl create创建该storage class

    # kubectl create -f storageclass-fast.yaml 
    storageclass.storage.k8s.io/fast created

    2.2 授权ServiceAccount

    在2.4步骤需要使用mongo-sidecar的pod来配置管理mongo pod。

    由于默认的service account仅仅只能获取当前Pod自身的相关属性,无法观察到其他名称空间Pod的相关属性信息。如果想要扩展Pod,或者一个Pod需要用于管理其他Pod或者是其他资源对象,是无法通过自身的名称空间的serviceaccount进行获取其他Pod的相关属性信息的,因此需要进行手动创建一个serviceaccount,并在创建Pod时进行定义。或者直接将默认的serviceaccount进行授权。

    defaultaccount.yaml

    kind: ClusterRoleBinding
    metadata:
      name: default-view
    subjects:
      - kind: ServiceAccount
        name: default
        namespace: default
    roleRef:
      kind: ClusterRole
      name: view
      apiGroup: rbac.authorization.k8s.io

    2.3 创建Headless Service

    mongodb-sidecar作为MongoDB集群的管理者,将使用此Headless Service来维护各个MongoDB实例之间的集群关系,以及集群规模变化时的自动更新

    mongodb-headless-service.yaml

    apiVersion: v1
    kind: Service
    metadata:
      name: mongo
      labels:
        name: mongo
    spec:
      ports:
      - port: 27017
        targetPort: 27017
      clusterIP: None
      selector:
        role: mongo

    执行kubectl create命令创建该Headless Service

    # kubectl create -f mongodb-headless-service.yaml 
    service/mongo created

    2.4 MongoDB StatefulSet

    statefulset-mongo.yaml

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: mongo
    spec:
      serviceName: mongo  # 声明它属于哪个Headless Service
      replicas: 3
      selector:         # has to match .sepc.template.metadata.labels
        matchLabels:
          role: mongo
          environment: test
      template:
        metadata:
          labels:      # has to match .spec.selector.matchLabels
            role: mongo
            environment: test
        spec:
          terminationGracePeriodSeconds: 10
          containers:
          - name: mongo
            image: mongo:3.4
            command:
            - mongod
            - "--replSet"
            - rs0
            - "--bind_ip"
            - 0.0.0.0
            - "--smallfiles"
            - "--noprealloc"
            ports:
            - containerPort: 27017
            volumeMounts:
            - name: mongo-persistent-storage
              mountPath: /data/db
          - name: mongo-sidecar
            image: cvallance/mongo-k8s-sidecar
            env:
            - name: MONGO_SIDECAR_POD_LABELS
              value: "role=mongo,environment=test"
            - name: KUBERNETES_MONGO_SERVICE_NAME
              value: "mongo"
      volumeClaimTemplates:
      - metadata:
          name: mongo-persistent-storage
          annotations:
            volume.beta.kubernetes.io/storage-class: "fast"
        spec:
          accessModes: [ "ReadWriteOnce" ]
          resources:
            requests:
              storage: 2Gi

    其中主要配置说明如下:

    (1)在该statefulset定义中包含连个容器:mongo和mongo-sidecar。mongo是主服务程序,mongo-sidecar是将多个mongo实例进行集群设置的工具。mongo-sidecar中的环境变量如下:

    • MONGO_SIDECAR_POD_LABELS:设置为mongo容器的标签,用于sidecar查询它所要管理的MongoDB集群实例

    • KUBERNETES_MONGO_SERVICE_NAME: 它的值为mongo,表示sidecar将使用mongo这个服务名来完成MongoDB集群的设置

       

      (2)replicas=3 表示MongoDB集群由3个mongo实例组成

      (3)volumeClaimTemplates是 StatefulSet最重要的存储设置。在annotations段设置volume.beta.kubernetes.io/storage-class="fast" 表示使用名为fast的StorageClass自动为每个mongo Pod实例分配后端存储

      (4)resources.requests.storage=2Gi 表示为每个mongo实例都分配2G的磁盘空间

     

    2.5 验证MongoDB集群

    最终可以看到StatefulSet依次创建并启动了3个mongo Pod实例,它们的名字依次为mongo-0、mongo-1、mongo-2:

    # kubectl get pods -l role=mongo
    NAME      READY   STATUS    RESTARTS   AGE
    mongo-0   2/2     Running   0          72m
    mongo-1   2/2     Running   0          71m
    mongo-2   2/2     Running   0          64m

    StatefulSet会用volumeClaimTemplates中定义为每个Pod副本都创建一个PVC实例,每个PVC的名称由StatefulSet定义中volumeClaimTemplates的名称和Pod副本的名称组合而成:

    # kubectl get pvc -l role=mongo
    NAME                               STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    mongo-persistent-storage-mongo-0   Bound    pvc-63b576fc-1324-46db-b708-0c40f5896103   2Gi        RWO            fast           86m
    mongo-persistent-storage-mongo-1   Bound    pvc-6b2dfbc3-f57e-4e05-9cd7-dfabb3c5b00e   2Gi        RWO            fast           75m
    mongo-persistent-storage-mongo-2   Bound    pvc-24ed1a31-b9a8-4214-a189-137cf9eccc12   2Gi        RWO            fast           67m

    下面是mongo-0这个Pod中volume设置,可以看到系统自动为其挂载了对应的PVC:

    # kubectl get pod mongo-0 -o yaml | grep -A 3 volumes
      volumes:
      - name: mongo-persistent-storage
        persistentVolumeClaim:
          claimName: mongo-persistent-storage-mongo-0

    登入任意一个mongo Pod,在mongo命令行界面使用rs.status()命令查看MongoDB集群状态,该mongodb集群已由sidecar完成了创建。在集群中包含3个节点的名称都是StatefulSet设置的DNS域名格式的网络标识名称:

    mongo-0.mongo.default.svc.cluster.local
    mongo-1.mongo.default.svc.cluster.local
    mongo-2.mongo.default.svc.cluster.local

    同时,可以查看每个mongodb实例的各自角色(PRIMARY或SECONDARY)

    rs.status()
    ...
    ...
    ...
    "members" : [
            {
                "_id" : 0,
                "name" : "mongo-0.mongo.default.svc.cluster.local:27017",
                "health" : 1,
                "state" : 1,
                "stateStr" : "PRIMARY",
                "uptime" : 100,
                "optime" : {
                    "ts" : Timestamp(1592286258, 1),
                    "t" : NumberLong(1)
                },
                "optimeDate" : ISODate("2020-06-16T05:44:18Z"),
                "syncingTo" : "",
                "syncSourceHost" : "",
                "syncSourceId" : -1,
                "infoMessage" : "could not find member to sync from",
                "electionTime" : Timestamp(1592286196, 2),
                "electionDate" : ISODate("2020-06-16T05:43:16Z"),
                "configVersion" : 5,
                "self" : true,
                "lastHeartbeatMessage" : ""
            },
            {
                "_id" : 1,
                "name" : "mongo-1.mongo.default.svc.cluster.local:27017",
                "health" : 1,
                "state" : 2,
                "stateStr" : "SECONDARY",
                "uptime" : 45,
                "optime" : {
    ...
    ...
     
  • 相关阅读:
    正经学C#_循环[do while,while,for]:[c#入门经典]
    Vs 控件错位 右侧资源管理器文件夹点击也不管用,显示异常
    asp.net core 获取当前请求的url
    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be
    用orchard core和asp.net core 3.0 快速搭建博客,解决iis 部署https无法登录后台问题
    System.Data.Entity.Core.EntityCommandExecution The data reader is incompatible with the specified
    初探Java设计模式3:行为型模式(策略,观察者等)
    MySQL教程77-CROSS JOIN 交叉连接
    MySQL教程76-HAVING 过滤分组
    MySQL教程75-使用GROUP BY分组查询
  • 原文地址:https://www.cnblogs.com/bigberg/p/13494583.html
Copyright © 2011-2022 走看看