zoukankan      html  css  js  c++  java
  • 20.Kubernetes共享存储

    Kubermetes对于有状态的容器应用或者对数据需要持久化的应用,不仅需要将容器内的目录挂载到宿主机的目录或者emptyDir临时存储卷,而且需要更加可靠的存储来保存应用产生的重要数据,以便容器应用在重建之后,仍然可以使用之前的数据。不过,存储资源和计算资源(CPU/内存)的管理方式完全不同。为了能够屏蔽底层存储实现的细节,让用户方便使用,同时能让管理员方便管理, Kubernetes从v1.0版本就引入PersistentVolumePersistentVolumeClaim两个资源对象来实现对存储的管理子系统。

    PersistentVolume (PV)是对底层网络共享存储的抽象,将共享存储定义为一种“资源”,比如节点(Node) 也是一种容 器应用可以“消费”的资源。PV由管理员进行创建和配置,它与共享存储的具体实现直接相关,例如GlusterFS、iSCSI、 RBD或GCB/AWS公有云提供的共享存储,通过插件式的机制完成与共享存储的对接,以供应用访问和使用。

    PersistentVolumeClaim (PVC)则是用户对于存储资源的一个“申请”。就像Pod“消费”Node的资源一-样, PVC会“消费”PV资源。PVC 可以申请特定的存储空间和访问模式。

    StorageClass,使用PVC“申请”到一定的存储空间仍然不足以满足应用对于存储设备的各种需求。通常应用程序都会对存储设备的特性和性能有不同的要求,包括读写速度、并发性能、数据冗余等更高的要求,Kubernetes 从v1.4版本开始引入了-一个新的资源对象StorageClass,用于标记存储资源的特性和性能。到v1.6版本时,StorageClass动态资源供应的机制得到了完善,实现了存储卷的按需创建,在共享存储的自动化管理进程中实现了重要的一步。

    通过StorageClass的定义,管理员可以将存储资源定义为某种类别(Class), 正如存储设备对于自身的配置描述(Profile),例如“快速存储”“慢速存储”“有数据冗余”“无数据冗余”等。用户根据StorageClas的描述就能够直观得知各种存储资源的特性,就可以根据应用对存储资源的需求去申请存储资源了。

    下面对Kubermetes的PVPVCStorageClass动态资源供应等共享存储管理机制进行详细说明。

    PV 详解

    PV作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略、后端存储类型等关键信息的设置。下面的例子声明的PV具有如下属性: 5Gi 存储空间,访问模式为“ReadWriteOnce”,存储类型为“slow" (要求系统中已存在名为slow的StorageClass),回收策略为“Recycle",并且后端存储类型为“nfs”(设置了NFS Server的IP地址和路径):

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: pv1
      spec:
        capacity:
          storage: 5Gi
        accessModes:
          - ReadWriteOnce
        persistentVolumeReclaimPolicy: Recycle
        storageClassName: slow
        nfs:
          path: /tmp
          server: 172.17.0.2
    

    Kubernetes支持的PV类型如下。

    • gcePersistentDisk: GCE公有云提供的PersistentDisk。
    • AWSElasticBlockStore: AWS公有云提供的ElasticBlockStore.
    • AzureFile: Azure公有云提供的File。
    • AzureDisk: Azure 公有云提供的Disk。
    • FC ( Fibre Channel)。
    • Flocker。
    • NFS:网络文件系统。
    • iSCSI。
    • RBD (Rados Block Device); Ceph块存储。
    • CephFS。
    • Cinder: OpenStack Cinder块存储。
    • GlusterFS。
    • VsphereVolume.
    • Quobyte Volumes。
    • VMware Photon。
    • Portworx Volumes。
    • ScaleIO Volumes。
    • HostPath:宿主机目录,仅用于单机测试。

    每种存储类型都有各自的特点,在使用时需要根据它们各自的参数进行设置。

    1、Capacity(容量)

    描述存储设备具备的能力,目前仅支持对存储空间的设置( storage= =xx),未来可能加入

    2、访问模式(Access Modes)

    • ReadWriteOnce (简写为 RWO): 读写权限,并且只能被单个Node挂载。
    • ReadOnlyMany (简写为 ROX): 只读权限,允许被多个Node挂载。
    • ReadWriteMany (简写为 RWX): 读写权限,允许被多个Node挂载。

    注意:即使volume支持很多种访问模式,但它同时只能使用一种访问模式。比如,GCEPersistentDisk可以被单个节点映射为ReadWriteOnce,或者多个节点映射为ReadOnlyMany,但不能同时使用这两种方式来映射。

    Volume PluginReadWriteOnceReadOnlyManyReadWriteMany
    AWSElasticBlockStore - -
    AzureFile
    AzureDisk - -
    CephFS
    Cinder - -
    FC -
    FlexVolume -
    Flocker - -
    GCEPersistentDisk -
    Glusterfs
    HostPath - -
    iSCSI -
    PhotonPersistentDisk - -
    Quobyte
    NFS
    RBD -
    VsphereVolume - -
    PortworxVolume -
    ScaleIO -

    3、存储类别(Class)

    PV可以设定其存储的类别(Class),通过storageClassName参数指定一个StorageClass资源对象的名称。具有特定“类别”的PV只能与请求该“类别”的PVC进行绑定。未设定“类别”的PV则只能与不请求任何“类别”的PVC进行绑定。

    4、回收策略(Reclaim Policy)

    目前支持如下三种回收策略。

    • 保留(Retain): 保留数据,需要手工处理。
    • 回收空间( Recycle):简单清除文件的操作(例如执行m -rf /thevolume/*命令)。
    • 删除(Delete):与PV相连的后端存储完成volume的删除操作(如AWS EBS、GCE PD、Azure Disk、OpenStack Cinder等设备的内部volume清理)。

    目前,只有NFS和HostPath两种类型的存储支持“Recycle”策略; AWS EBS、GCE PD、Azure Disk和Cinder volumes支持“Delete”策略。

    2. PV生命周期的各个阶段( Phase )

    某个PV在生命周期中,可能处于以下4个阶段之一。

    • Available: 可用状态,还未与某个PVC绑定。
    • Bound: 已与某个PVC绑定。
    • Released: 绑定的PVC已经删除,资源已释放,但没有被集群回收。
    • Failed: 自动资源回收失败。

    3. PV的挂载参数( Mount Options )

    在将PV挂载到一个Node上时,根据后端存储的特点,可能需要设置额外的挂载参数,目前可以通过在PV的定义中,设置一个名为“volume.beta.kubernetes.io/mount-options"的annotation来实现。下面的例子对一个类型为gcePersistentDisk的PV设置了挂载参数“discard":

    apiVersion: "v1"
    kind: "PersistentVolume"
    metadata :
      name: gce-disk-1
      annotations:
      volume.beta.kubernetes.io/mount-options: "discard"
    spec: 
      capacity:
        storage : "10Gi”
      accessModes :
        - ”ReadWriteOnce”
    gcePersistentDisk:
      fsType: "ext4"
      pdName : "gce-disk-1
    

    并非所有类型的存储都支持设置挂载参数。从Kubernetes v1.6版本开始,以下存储类型支持设置挂载参数。

    • gcePersistentDisk。
    • AWSElasticBlockStore.
    • AzureFile。
    • AzureDisk。
    • NFS。
    • iSCSI。
    • RBD
    • (Rados Block Device): Ceph 块存储。
    • CephFS。
    • Cinder: OpenStack 块存储。
    • GlusterFS。
    • VsphereVolume.
    • Quobyte Volumes.
    • VMware Photon。

    PVC详解

    PVC 作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别等信息的设置。下面的例子中声明的PVC具有如下属性:申请8Gi存储空间,访问模式为"ReadWriteOnce",PV选择条件为包含标签"release=stable"并且包含条件为"environment In [dev]"的标签,存储类别为"slow"(要求系统中已存在名为slow的StorageClass)。

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: myclaim
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 8Gi
      storageClassName: slow
      selector:
        matchLabels:
          release: "stable"
        matchExpressions:
         - {key: environment, operator: In, values: [dev]}
    

    PVC的关键配置参数说明如下:

    • 资源请求(Resources):描述对存储资源的请求,目前仅支持request.storage的设置,即存储空间大小。
    • 访问模式(Access Modes):PVC也可以设置访问模式,用于描述用户应用对存储资源的访问权限。可以设置的三种访问模式与PV相同。
    • PV选择条件(Selector):通过Label Selector的设置,可使PVC对于系统中已存在的各种PV进行筛选。系统将根据标签选择出合适的PV与该PVC进行绑定。选择条件可以使用matchLabels和matchExpressions进行设置。如果两个条件都设置了,则Selector的逻辑是两组条件同时满足才能完成匹配。
    • 存储类别(Class):PVC在定义时可以设定需要的后端存储的"类别"(通过storageClassName字段指定),以降低对后端存储特性的详细信息的依赖。只有设置了该Class的PV才能被系统选出,并与该PVC进行绑定。

    PVC也可以不设置Class需求。如果storageClassName字段的值被设置为空(storageClassName=""),则表示该PVC不要求特定的Class,系统将只选择未设定Class的PV与之匹配和绑定。PVC也可以完全不设置storageClassName字段,此时将根据系统是否启用了名为"DefaultStorageClass"的admission controller进行相应的操作。

    • 未启用DefaultStorageClass:等效于PVC设置storageClassName的值为空,即只能选择未设定Class的PV与之匹配和绑定。

    • 启用了DefaultStorageClass:要求集群管理员已定义默认的StorageClass。如果系统中不存在默认的StorageClass,则等效于不启用DefaultStorageClass的情况。如果存在默认的StorageClass,则系统将自动为PVC创建一个PV(使用默认StorageClass的后端存储),并将它们进行绑定。集群管理员设置默认StorageClass的方法为,在StorageClass的定义中加上一个annotation "storageclass.kubernetes.io/is-default-class=true"。如果管理员将多个StorageClass都定义为default,则由于不唯一,系统将无法为PVC创建相应的PV。

    注意,PVC和PV都受限于namespace,PVC在选择PV时受到namespace的限制,只有相同namespace中的PV才可能与PVC绑定。Pod在引用PVC时同样受namespace的限制,只有相同namespace中的PVC才能挂载到Pod内。

    当Selector和Class都进行了设置时,系统将选择两个条件同时满足的PV与之匹配。

    另外,如果资源供应使用的是动态模式,即管理员没有预先定义PV,仅通过StorageClass交给系统自动完成PV的动态创建,那么PVC再设定Selector时,系统将无法为其供应任何存储资源了。

    在启动动态供应模式的情况下,一旦用户删除了PVC,与之绑定的PV将根据其默认的回收策略"Delete"也会被删除。如果需要保留PV(用户数据),则在动态绑定成功后,用户需要将系统自动生成PV的回收策略从"Delete"改成"Retain"。

    PV和PVC的生命周期

    PV可以看作可用的存储资源,PVC则是对存储资源的需求,PV和PVC的相互关系遵循下图所示的生命周期。

    screenshot

    1 资源供应(Provisioning)

    k8s支持两种资源的供应模式:静态模式(Static)动态模式(Dynamic)。资源供应的结果就是创建好的PV。

    • 静态模式:集群管理员手工创建许多PV,在定义PV时需要将后端存储的特性进行设置。
    • 动态模式:集群管理员无须手工创建PV,而是通过StorageClass的设置对后端存储进行描述,标记为某种“类型(Class)”。此时要求PVC对存储类型进行声明,系统将自动完成PV的创建及与PVC的绑定。PVC可以声明Class为"",说明该PVC禁止使用动态模式。

    2 资源绑定(Binding)

    在用户定义好PVC之后,系统将根据PVC对存储资源的请求(存储空间和访问模式)在已存在的PV中选择一个满足PVC要求的PV,一旦找到,就将该PV与用户定义的PVC进行绑定,然后用户的应用就可以使用这个PVC了。如果系统中没有满足PVC要求的PV,PVC就会无限期处于Pending状态,直到等到系统管理员创建了一个符合其要求的PV。PV一旦绑定到某个PVC上,就被这个PVC独占,不能再与其他PVC进行绑定了。在这种情况下,当PVC申请的存储空间与PV的少时,整个PV的空间都会被PVC所用,可能会造成资源的浪费。如果资源供应使用的是动态模式,则系统在为PVC找到合适的StorageClass后,将自动创建一个PV并完成与PVC的绑定。

    3 资源使用(Using)

    Pod使用volume的定义,将PVC挂载到容器内的某个路径进行使用。volume的类型为"persistentVolumeClaim",在后面的示例中再进行详细说明。在容器应用挂载了一个PVC后,就能被持续独占使用。不过,多个Pod可以挂载同一个PVC,应用程序需要考虑多个实例共同访问同一块存储空间的问题。

    4 资源释放(Releasing)

    当用户对存储资源使用完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为“已释放”,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还留在存储设备上,只有在清除之后该PV才能再次使用。

    5 资源回收(Reclaimig)

    对于PV,管理员可以设定回收策略(Reclaim Policy),用于设置与之绑定的PVC释放资源之后,对于遗留数据如何处理。只有PV的存储空间完成回收,才能供新的PVC绑定和使用。

    下面通过两张图分别对在静态资源供应模式和动态资源供应模式下,PV、PVC、StorageClass及Pod使用PVC的原理进行说明。

    在静态资源供应模式下,通过PV和PVC完成绑定,并供Pod使用的存储管理机制。
    screenshot
    在动态资源供应模式下,通过StorageClass和PVC完成资源动态绑定(系统自动生成PV),并供Pod使用的存储管理机制。
    screenshot

    StorageClass详解

    StorageClass作为对存储资源的抽象定义,对用户设置的PVC申请屏蔽后端存储的细节。一方面减轻用户对于存储资源细节的关注,另一方面也减轻管理员手工管理PV的工作,由系统自动完成PV的创建和绑定,实现动态的资源供应。使用基于StorageClass的动态资源供应模式将逐步成为云平台的标准存储配置模式。

    StorageClass的定义主要包括名称、后端存储的提供者(Provisioner)和后端存储的相关参数配置。StorageClass一旦被创建出来,就将无法修改,只能删除原StorageClass的定义重建。下面的例子中定义了一个名为“standard"的StorageClass,提供者为aws-ebs,其参数设置了一个type=gp2。

    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: standard
    provisioner: kubernetes.io/aws-ebs
    parameters:
      type: gp2
    

    1 StorageClass的关键配置参数

    1)提供者(Provisioner)

    描述存储资源的提供者,也可以看作后端存储驱动。
    目前k8s支持的Provisioner都以"kubernetes.io/"为开头,用户也可以使用自定义的后端存储提供者。为了符合StorageClass的用法,自定义Provisioner需要符合存储卷的开发规范,详见该链接的说明:https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/volume-provisioning.md

    2)参数(Parameters)

    后端存储资源提供者的参数设置,不同的Provisioner包括不同的参数设置。某些参数可以不显示设定,Provisioner将使用其默认值。

    3)下面介绍几种常用的Provisioner对StorageClass的定义进行详细说明

    AWS EBS存储卷
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: slow
    provisioner: kubernetes.io/aws-ebs
    parameters:
      type: io1
      zone: us-east-id
      iopsPerGB: "10"
    

    参数说明如下:

    • type:可选项为io1, gp2, sc1, st1, 默认值为gp2
    • zone:AWS zone的名称
    • iopsPerGB:仅用于io1类型的volume,意为每秒每GiB的I/O操作数量
    • encrypted:是否加密
    • kmsKeyId:加密时的Amazon Resource Name
    GCE PD存储卷
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: slow
    provisioner: kubernetes.io/gce-pd
    parameters:
      type: pd-standard
      zone: us-centrall-a
    

    参数说明:

    • type:可选项为pd-standard, pd-ssd, 默认值为pd-standard
    • zone:GCE zone名称
    GlusterFS存储卷
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: slow
    provisioner: kubernetes.io/glusterfs
    parameters:
      resturl: "https://127.0.0.1:8081"
      clusterid: "sadfa2435hfghsrg462345"
      restauthenabled: "true"
      restuser: "admin"
      secretNamespace: "default"
      secretName: "heketi-secret"
      gidMin: "40000"
      gidMax: "50000"
      volumetype: "replicate:3"
    

    参数说明如下(详细说明请参考GlusterFS和Heketi的文档)。

    • resturl: Gluster REST服务(heketi)的URL地址,用于自动完成GlusterFSvolume的设置。
    • restauthenabled: 是否对Gluster REST服务启用安全机制。
    • restuser: 访问Gluster REST服务的用户名。
    • secretNamespace和secretName: 保存访问Gluster REST服务密码的Secret资源对象名。
    • clusterid: GlusterFS的Cluster ID
    • gidMin和gidMAX: StorageClass的GID范围,用于动态资源供应时为PV设置的GID。
    • volumetype: GlusterFS的volume类型设置,例如replicate:3(Replicate类型,3副本);disperse:4:2(Disperse类型,数据4份,冗余2份);none(Distribute类型)。
    OpenStack Cinder存储卷
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: gold
    provisioner: kubernetes.io/cinder
    parameters:
      type: fast
      availability: nova
    

    参数说明如下:

    • type: Cinder的VolumeType, 默认值为空。
    • availability: Availability Zone, 默认值为空。

    其他Provisioner的StorageClass相关参数设置请参考它们各自的配置手册。

    2 设置默认的StorageClass

    要在系统中设置一个默认的StorageClass,首先需要启动名为"DefaultStorageClass"admission controller, 即在kube-apiserver的命令行参数--admission-controll中增加:
    --admission-control=...,DefaultStorageClass

    然后,在StorageClass的定义中设置一个annotation:

    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: gold
      annotations:
        storageclass.beta.kubernetes.io/is-default-class="true"
    provisioner: kubernetes.io/cinder
    parameters:
      type: fast
      availability: nova
    

    通过kubectl create命令创建成功后,查看StorageClass列表,可以看到名为gold的StorageClass被标记为"default":

    # kubectl get sc
    gold (default)  kubernetes.io/cinder
    

    动态存储管理实战:GlusterFS

    本节以GlusterFS为例,从定义StorageClass、创建GlusterFS和Heketi服务、用户申请PVC到创建Pod使用存储资源,对StorageClass和动态资源分配进行详细说明,进一步剖析k8s的存储机制。

    1 准备工作

    首先在用于部署GlusterFS的三个节点上安装GlusterFS客户端:

    yum -y install glusterfs glusterfs-fuse
    

    GlusterFS管理服务容器需要以特权模式运行,中kube-apiserver的启动参数中确认已经打开了:

    --allow-privileged=true
    

    给要部署GlusterFS管理服务的节点打上"storagenode=glusterfs"的标签,这样可以将GlusterFS容器定向部署到安装了GlusterFS的Node上:

    [k8s@kube-server harbor]$ kubectl label node kube-node1 storagenode=glusterfs
    node "kube-node1" labeled
    [k8s@kube-server harbor]$ kubectl label node kube-node2 storagenode=glusterfs
    node "kube-node2" labeled
    [k8s@kube-server harbor]$ kubectl label node kube-node3 storagenode=glusterfs
    node "kube-node3" labeled
    

    2 创建GlusterFS服务容器集群

    GlusterFS服务容器以DaemonSet的方式进行部署,确保每台Node上都运行一个GlusterFS管理服务,glusterfs-daemonset.yaml内容如下。参照 https://github.com/gluster/gluster-kubernetes。

    1)在各个Node节点的启动参数中增加以下选项,因为GlusterFS需要使用容器的特权模式运行

    --allow-privileged
    

    生效:

    systemctl daemon-reload
    systemctl restart kubelet
    systemctl status kubelet
    

    2)给每个运行GlusterFS的Node节点增加一块数据磁盘

    注意数据盘挂载后,在系统中使用的设备描述符,需要在下一步配置中使用到。

    3)编辑topology.json拓朴文件

    获取一份安装资源:

    git clone https://github.com/gluster/gluster-kubernetes.git

    [k8s@kube-server deploy]$ pwd
    /home/k8s/gluster-kubernetes/deploy
    [k8s@kube-server deploy]$ ls
    gk-deploy  heketi.json.template  kube-templates  ocp-templates  topology.json
    

    至少需要3个节点,按下面格式对该文件进行更新:

    [k8s@kube-server deploy]$ cat topology.json
    {
      "clusters": [
        {
          "nodes": [
            {
              "node": {
                "hostnames": {
                  "manage": [
                    "kube-node1"
                  ],
                  "storage": [
                    "172.16.10.101"
                  ]
                },
                "zone": 1
              },
              "devices": [
                "/dev/sdb"
              ]
            },
            {
              "node": {
                "hostnames": {
                  "manage": [
                    "kube-node2"
                  ],
                  "storage": [
                    "172.16.10.102"
                  ]
                },
                "zone": 1
              },
              "devices": [
                "/dev/sdb"
              ]
            },
            {
              "node": {
                "hostnames": {
                  "manage": [
                    "kube-node3"
                  ],
                  "storage": [
                    "172.16.10.103"
                  ]
                },
                "zone": 1
              },
              "devices": [
                "/dev/sdb"
              ]
            }
          ]
        }
      ]
    }
    

    4)在k8s上部署 GlusterFS + heketi

    需要先检查下环境:

    • 至少需要3个节点
    • 每个节点上至少提供一个裸块存储设备;
    • 确保以下端口没有被占用:2222,24007, 24008, 49152~49251
    • 在系统中加载以下模块: modprobe dm_snapshot && modprobe dm_mirror && modprobe dm_thin_pool
    • 安装依赖包:yum -y install glusterfs-fuse

    执行部署命令:

    [k8s@kube-server deploy]$ ./gk-deploy -g
    

    注:-g参数表示要创建出一套glusterfs集群服务。

    如果一切顺利,在结束时会看到下面的输出:

    ....
    service "heketi" created
    deployment.extensions "heketi" created
    Waiting for heketi pod to start ... OK
    Flag --show-all has been deprecated, will be removed in an upcoming release
    
    heketi is now running and accessible via https://172.30.86.3:8080 . To run
    administrative commands you can install 'heketi-cli' and use it as follows:
    
      # heketi-cli -s https://172.30.86.3:8080 --user admin --secret '<ADMIN_KEY>' cluster list
    
    You can find it at https://github.com/heketi/heketi/releases . Alternatively,
    use it from within the heketi pod:
    
      # /opt/k8s/bin/kubectl -n default exec -i heketi-75dcfb7d44-vj9bk -- heketi-cli -s https://localhost:8080 --user admin --secret '<ADMIN_KEY>' cluster list
    
    For dynamic provisioning, create a StorageClass similar to this:
    
    ---
    apiVersion: storage.k8s.io/v1beta1
    kind: StorageClass
    metadata:
      name: glusterfs-storage
    provisioner: kubernetes.io/glusterfs
    parameters:
      resturl: "https://172.30.86.3:8080"
    
    Deployment complete!
    

    查看下都创建出了哪些服务实例:

    [k8s@kube-server deploy]$ kubectl get pods -o wide
    NAME                        READY     STATUS    RESTARTS   AGE       IP              NODE
    glusterfs-88469             1/1       Running   0          2h        172.16.10.102   kube-node2
    glusterfs-lwm4n             1/1       Running   0          2h        172.16.10.103   kube-node3
    glusterfs-pfgwb             1/1       Running   0          2h        172.16.10.101   kube-node1
    heketi-75dcfb7d44-vj9bk     1/1       Running   0          1h        172.30.86.3     kube-node2
    my-nginx-86555897f9-2kn92   1/1       Running   2          8h        172.30.49.2     kube-node1
    my-nginx-86555897f9-d95t9   1/1       Running   4          2d        172.30.48.2     kube-node3
    [k8s@kube-server deploy]$ kubectl get svc -o wide
    NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE       SELECTOR
    heketi                     ClusterIP   10.254.42.129    <none>        8080/TCP   1h        glusterfs=heketi-pod
    heketi-storage-endpoints   ClusterIP   10.254.4.122     <none>        1/TCP      1h        <none>
    kubernetes                 ClusterIP   10.254.0.1       <none>        443/TCP    7d        <none>
    my-nginx                   ClusterIP   10.254.191.237   <none>        80/TCP     5d        run=my-nginx
    [k8s@kube-server deploy]$ kubectl get deployment
    NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    heketi     1         1         1            1           1h
    my-nginx   2         2         2            2           5d
    
    [k8s@kube-server deploy]$ kubectl get secret
    NAME                                 TYPE                                  DATA      AGE
    default-token-p5wjd                  kubernetes.io/service-account-token   3         7d
    heketi-config-secret                 Opaque                                3         1h
    heketi-service-account-token-mrtsx   kubernetes.io/service-account-token   3         2h
    kubelet-api-test-token-gdj7g         kubernetes.io/service-account-token   3         6d
    [k8s@kube-server deploy]$
    

    5)使用示例

    在可以调用kubectl管理k8s集群的节点上,安装一个heketi客户端:

    yum -y install heketi-client
    

    创建个1GB的PV存储卷:

    [k8s@kube-server deploy]$ export HEKETI_CLI_SERVER=https://172.30.86.3:8080
    [k8s@kube-server deploy]$ heketi-cli volume create --size=1 --persistent-volume --persistent-volume-endpoint=heketi-storage-endpoints | kubectl create -f -
    persistentvolume "glusterfs-900fb349" created
    

    回到Dashboard上看看这个刚创建的存储卷:
    screenshot
    通过heketi服务查看和管理GlusterFS集群: 查看集群列表:

    [root@kube-node1 ~]# curl 10.254.42.129:8080/clusters
    {"clusters":["ada54ffbeac15a5c9a7521e0c7d2f636"]}
    

    查看集群详情:

    [root@kube-node1 ~]# curl 10.254.42.129:8080/clusters/ada54ffbeac15a5c9a7521e0c7d2f636
    {"id":"ada54ffbeac15a5c9a7521e0c7d2f636","nodes":["49ac6f56ef21408bcad7c7613cd40bd8","bdf51ae46025cd4fcf134f7be36c32de","fc21262379ec3636e3eadcae15efcc94"],"volumes":["42b01b9b08af23b751b2359fb161c004","900fb349e56af275f47d523d08fdfd6e"],"block":true,"file":true,"blockvolumes":[]}
    

    查看节点详情:

    [root@kube-node1 ~]# curl 10.254.42.129:8080/nodes/49ac6f56ef21408bcad7c7613cd40bd8
    {"zone":1,"hostnames":{"manage":["kube-node3"],"storage":["172.16.10.103"]},"cluster":"ada54ffbeac15a5c9a7521e0c7d2f636","id":"49ac6f56ef21408bcad7c7613cd40bd8","state":"online","devices":[{"name":"/dev/sdb","storage":{"total":8253440,"free":5087232,"used":3166208},"id":"2f6b2f6c289a2f6bf48fbec59c0c2009","state":"online","bricks":[{"id":"2ea90ebd791a4230e927d233d1c8a7d1","path":"/var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_2ea90ebd791a4230e927d233d1c8a7d1/brick","device":"2f6b2f6c289a2f6bf48fbec59c0c2009","node":"49ac6f56ef21408bcad7c7613cd40bd8","volume":"42b01b9b08af23b751b2359fb161c004","size":2097152},{"id":"4c98684d878ffe7dbfc1008336460eed","path":"/var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_4c98684d878ffe7dbfc1008336460eed/brick","device":"2f6b2f6c289a2f6bf48fbec59c0c2009","node":"49ac6f56ef21408bcad7c7613cd40bd8","volume":"900fb349e56af275f47d523d08fdfd6e","size":1048576}]}]}
    
    • state 为 online说明节点正常

    6)创建一个使用GlusterFS动态存储供应服务的nginx应用

    注:在本示例中的用户认证是未启用的,如果要启动用户认证服务,则可以创建一个secret,然后通过StorageClass配置参数传递给Gluster动态存储供应服务。
    下面是一个存储类的示例,它将请求2GB的按需存储,用于在我们的HelloWorld应用程序中使用。

    gluster-storage-class.yaml
    apiVersion: storage.k8s.io/v1beta1
    kind: StorageClass
    metadata:
      name: gluster-heketi  
    provisioner: kubernetes.io/glusterfs 
    parameters:
      resturl: "https://10.254.42.129:8080"
      restuser: "joe"  
      restuserkey: "My Secret Life"
    
    • name,StorageClass名称
    • provisioner,存储服务提供者
    • resturl,Heketi REST Url
    • restuser,因为未启用认证,所以这个参数无效
    • restuserkey,同上

    创建该存储类:

    [k8s@kube-server ~]$ kubectl create -f gluster-storage-class.yaml
    storageclass.storage.k8s.io "gluster-heketi" created
    
    [k8s@kube-server ~]$ kubectl get storageclass
    NAME             PROVISIONER               AGE
    gluster-heketi   kubernetes.io/glusterfs   43s
    

    创建PersistentVolumeClaim(PVC)以请求我们的HelloWorld应用程序的存储:
    我们将创建一个要求2GB存储空间的PVC,此时,Kubernetes Dynamic Provisioning Framework和Heketi将自动配置新的GlusterFS卷并生成Kubernetes PersistentVolume(PV)对象。

    gluster-pvc.yaml
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: gluster1
      annotations:
        volume.beta.kubernetes.io/storage-class: gluster-heketi
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 2Gi
    
    • annotations,Kubernetes存储类注释和存储类的名称

      [k8s@kube-server ~]$ kubectl create -f gluster-pvc.yaml
      persistentvolumeclaim "gluster1" created

    可以看到PVC是绑定到一个动态供给的存储卷上的:

    [k8s@kube-server ~]$ kubectl get pvc
    NAME       STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS     AGE
    gluster1   Bound     pvc-53e824cf-7eb7-11e8-bf5c-080027395360   2Gi        RWO            gluster-heketi   53s
    
    [k8s@kube-server ~]$ kubectl get pv
    NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM              STORAGECLASS     REASON    AGE
    glusterfs-900fb349                         1Gi        RWX            Retain           Available                                                 2h
    pvc-53e824cf-7eb7-11e8-bf5c-080027395360   2Gi        RWO            Delete           Bound       default/gluster1   gluster-heketi             1m
    

    创建一个使用该PVC的nginx实例:

    nginx-pod.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-pod1
      labels:
        name: nginx-pod1
    spec:
      containers:
      - name: nginx-pod1
        image: nginx:1.7.9
        ports:
        - name: web
          containerPort: 80
        volumeMounts:
        - name: gluster-vol1
          mountPath: /usr/share/nginx/html
      volumes:
      - name: gluster-vol1
        persistentVolumeClaim:
          claimName: gluster1
    

    claimName,要使用的PVC的名称

    [k8s@kube-server ~]$ kubectl create -f nginx-pod.yaml
    pod "nginx-pod1" created
    
    [k8s@kube-server ~]$ kubectl get pods -o wide|grep nginx-pod
    nginx-pod1                  1/1       Running   0          33s       172.30.86.3     kube-node2
    

    登录到该Pod中并创建一个网页文件:

    [k8s@kube-server ~]$ kubectl exec -it nginx-pod1  /bin/bash
    root@nginx-pod1:/# df -h
    Filesystem                                          Size  Used Avail Use% Mounted on
    rootfs                                               41G  7.1G   34G  18% /
    overlay                                              41G  7.1G   34G  18% /
    tmpfs                                                64M     0   64M   0% /dev
    tmpfs                                               496M     0  496M   0% /sys/fs/cgroup
    /dev/mapper/centos_bogon-root                        41G  7.1G   34G  18% /dev/termination-log
    shm                                                  64M     0   64M   0% /dev/shm
    /dev/mapper/centos_bogon-root                        41G  7.1G   34G  18% /etc/resolv.conf
    /dev/mapper/centos_bogon-root                        41G  7.1G   34G  18% /etc/hostname
    /dev/mapper/centos_bogon-root                        41G  7.1G   34G  18% /etc/hosts
    /dev/mapper/centos_bogon-root                        41G  7.1G   34G  18% /var/cache/nginx
    172.16.10.101:vol_1b6e32efd9b6f07e2b056bed2ce6cc73  2.0G   53M  2.0G   3% /usr/share/nginx/html
    tmpfs                                               496M   12K  496M   1% /run/secrets/kubernetes.io/serviceaccount
    tmpfs                                                64M     0   64M   0% /proc/kcore
    tmpfs                                                64M     0   64M   0% /proc/keys
    tmpfs                                                64M     0   64M   0% /proc/timer_list
    tmpfs                                                64M     0   64M   0% /proc/timer_stats
    tmpfs                                                64M     0   64M   0% /proc/sched_debug
    tmpfs                                               496M     0  496M   0% /proc/scsi
    tmpfs                                               496M     0  496M   0% /sys/firmware
    
    root@nginx-pod1:/# cd /usr/share/nginx/html
    dex.htmlnx-pod1:/usr/share/nginx/html# echo 'Hello World from GlusterFS!!!' > in
    root@nginx-pod1:/usr/share/nginx/html# ls
    index.html
    root@nginx-pod1:/usr/share/nginx/html# cat index.html
    Hello World from GlusterFS!!!
    root@nginx-pod1:/usr/share/nginx/html# exit
    exit
    

    访问一下我们的网页:

    [k8s@kube-server ~]$ curl https://172.30.86.3
    Hello World from GlusterFS!!!
    

    再检查一下gluster pod,找到我们刚写入的index.html文件,登录任一个gluster pod:

    screenshot

    [root@kube-node1 brick]# pwd
    /var/lib/heketi/mounts/vg_f8776d0d92102fc3e272f2ec899e5f18/brick_6e016b1ed8e16b6a28839f1670a56d00/brick
    [root@kube-node1 brick]# ls
    index.html
    [root@kube-node1 brick]# cat index.html
    Hello World from GlusterFS!!!
    

    7)删除 glusterfs 集群配置

    curl -X DELETE 10.254.42.129:8080/devices/46b2685901f56d6fe0cc85bf3d37bf75 # 使用的是device id,删除device
    curl -X DELETE 10.254.42.129:8080/nodes/8bd8497a8dcda0708508228f4ae8c2ae #使用的是node id, 删除node
    

    每个节点都要删除掉device才能再删除node

    cluster 列表下的所有节点都删除后 才能删除cluster:
    curl -X DELETE 10.254.42.129:8080/clusters/ada54ffbeac15a5c9a7521e0c7d2f636
    

    Heketi服务

    GlusterFS 是个开源的分布式文件系统,而 Heketi 在其上提供了 REST 形式的 API,二者协同为 Kubernetes 提供了存储卷的自动供给能力。Heketi还支持GlusterFS多集群管理。当一个集群中同时有多种规格、性能和容量特点的存储资源时,Heketi可以通过接入多个存储集群,在每个集群中又按资源特性划分出多个Zone来进行管理。

    screenshot

    1)在k8s中部署Heketi服务前需要为其创建一个ServiceAccount账号

    我们继续看一下前面例子中使用到的一些配置资源:

    [k8s@kube-server deploy]$ pwd
    /home/k8s/gluster-kubernetes/deploy
    [k8s@kube-server deploy]$ cat ./kube-templates/heketi-service-account.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: heketi-service-account
      labels:
        glusterfs: heketi-sa
        heketi: sa
    
    [k8s@kube-server deploy]$ kubectl get sa | grep heketi
    heketi-service-account   1         4h
    

    2)通过Deployment部署Heketi服务

    [k8s@kube-server deploy]$ kubectl get deployment
    NAME       DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    heketi     1         1         1            1           3h
    
    [k8s@kube-server kube-templates]$ pwd
    /home/k8s/gluster-kubernetes/deploy/kube-templates
    [k8s@kube-server kube-templates]$ cat heketi-deployment.yaml
    ---
    kind: Service
    apiVersion: v1
    metadata:
      name: heketi
      labels:
        glusterfs: heketi-service
        heketi: service
      annotations:
        description: Exposes Heketi Service
    spec:
      selector:
        glusterfs: heketi-pod
      ports:
      - name: heketi
        port: 8080
        targetPort: 8080
    ---
    kind: Deployment
    apiVersion: extensions/v1beta1
    metadata:
      name: heketi
      labels:
        glusterfs: heketi-deployment
        heketi: deployment
      annotations:
        description: Defines how to deploy Heketi
    spec:
      replicas: 1
      template:
        metadata:
          name: heketi
          labels:
            glusterfs: heketi-pod
            heketi: pod
        spec:
          serviceAccountName: heketi-service-account
          containers:
          - image: heketi/heketi:dev
            imagePullPolicy: IfNotPresent
            name: heketi
            env:
            - name: HEKETI_USER_KEY
              value: ${HEKETI_USER_KEY}
            - name: HEKETI_ADMIN_KEY
              value: ${HEKETI_ADMIN_KEY}
            - name: HEKETI_EXECUTOR
              value: ${HEKETI_EXECUTOR}
            - name: HEKETI_FSTAB
              value: ${HEKETI_FSTAB}
            - name: HEKETI_SNAPSHOT_LIMIT
              value: '14'
            - name: HEKETI_KUBE_GLUSTER_DAEMONSET
              value: "y"
            - name: HEKETI_IGNORE_STALE_OPERATIONS
              value: "true"
            ports:
            - containerPort: 8080
            volumeMounts:
            - name: db
              mountPath: "/var/lib/heketi"
            - name: config
              mountPath: /etc/heketi
            readinessProbe:
              timeoutSeconds: 3
              initialDelaySeconds: 3
              httpGet:
                path: "/hello"
                port: 8080
            livenessProbe:
              timeoutSeconds: 3
              initialDelaySeconds: 30
              httpGet:
                path: "/hello"
                port: 8080
          volumes:
          - name: db
            glusterfs:
              endpoints: heketi-storage-endpoints
              path: heketidbstorage
          - name: config
            secret:
              secretName: heketi-config-secret
    

    定义了两个volumes,其中"db"是使用的glusterfs提供的存储卷,而"config"的volume则是使用的"secret"

    查看一下被当作volume使用的secret的内容:

    [k8s@kube-server kube-templates]$ kubectl describe secret heketi-config-secret
    Name:         heketi-config-secret
    Namespace:    default
    Labels:       glusterfs=heketi-config-secret
                  heketi=config-secret
    Annotations:  <none>
    
    Type:  Opaque
    
    Data
    ====
    heketi.json:    909 bytes
    private_key:    0 bytes
    topology.json:  1029 bytes
    

    可以看到这个secret中是包含了三个配置文件

    这个secret是使用脚本创建的:

    [k8s@kube-server deploy]$ pwd
    /home/k8s/gluster-kubernetes/deploy
    [k8s@kube-server deploy]$ ls
    gk-deploy  heketi.json.template  kube-templates  ocp-templates  topology.json
    [k8s@kube-server deploy]$ grep heketi-config-secret gk-deploy
      eval_output "${CLI} create secret generic heketi-config-secret --from-file=private_key=${SSH_KEYFILE} --from-file=./heketi.json --from-file=topology.json=${TOPOLOGY}"
      eval_output "${CLI} label --overwrite secret heketi-config-secret glusterfs=heketi-config-secret heketi=config-secret"
    [k8s@kube-server deploy]$
    

    3)为Heketi设置GlusterFS集群

    使用一个topology.json的配置文件来完成各个GlusterFS节点和设备的定义。
    Heketi要求一个GlusterFS集群中至少有3个节点。在topology.json配置文件的hostnames字段中的manage中填写主机名,在storage上填写IP地址,devices要求是未创建文件系统的裸设备(支持多块磁盘)。这样Heketi就可以自动完成PV、VG和LV的创建。

    topology.json文件的内容在前面已经提供了,不再重复。

    当使用gluster-kubernetes项目提供的脚本工具和模板创建glusterfs和heketi服务时,不需要额外的手动干预。但如果是手动创建这些服务,则可以按下面的方法使用Heketi加载topology配置,完成GlusterFS服务集群的创建。
    可以登录进入Hekiti容器执行以下命令:

    # export HEKETI_CLI_SERVER=https://localhost:8080
    # heketi-cli topology load --json=topology.json
    

    这样Heketi就完成了GlusterFS集群的创建,同时在GlusterFS集群的各个节点的/dev/sdb盘上成功创建了PV和VG。
    此时,查看Heketi的topology信息,可以看到很详细的Node和Device信息:

    [k8s@kube-server deploy]$ heketi-cli topology info
    
    Cluster Id: ada54ffbeac15a5c9a7521e0c7d2f636
    
        Volumes:
    
        Name: vol_1b6e32efd9b6f07e2b056bed2ce6cc73
        Size: 2
        Id: 1b6e32efd9b6f07e2b056bed2ce6cc73
        Cluster Id: ada54ffbeac15a5c9a7521e0c7d2f636
        Mount: 172.16.10.103:vol_1b6e32efd9b6f07e2b056bed2ce6cc73
        Mount Options: backup-volfile-servers=172.16.10.102,172.16.10.101
        Durability Type: replicate
        Replica: 3
        Snapshot: Disabled
    
            Bricks:
                Id: 6e016b1ed8e16b6a28839f1670a56d00
                Path: /var/lib/heketi/mounts/vg_f8776d0d92102fc3e272f2ec899e5f18/brick_6e016b1ed8e16b6a28839f1670a56d00/brick
                Size (GiB): 2
                Node: fc21262379ec3636e3eadcae15efcc94
                Device: f8776d0d92102fc3e272f2ec899e5f18
    
                Id: c7acfcecaf85aada98b0c0208798440f
                Path: /var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_c7acfcecaf85aada98b0c0208798440f/brick
                Size (GiB): 2
                Node: 49ac6f56ef21408bcad7c7613cd40bd8
                Device: 2f6b2f6c289a2f6bf48fbec59c0c2009
    
                Id: e2acc8268f17f05e940ebe679dacfa3a
                Path: /var/lib/heketi/mounts/vg_e100120226d5d9567ed0f92b9810236c/brick_e2acc8268f17f05e940ebe679dacfa3a/brick
                Size (GiB): 2
                Node: bdf51ae46025cd4fcf134f7be36c32de
                Device: e100120226d5d9567ed0f92b9810236c
    
    
        Name: heketidbstorage
        Size: 2
        Id: 42b01b9b08af23b751b2359fb161c004
        Cluster Id: ada54ffbeac15a5c9a7521e0c7d2f636
        Mount: 172.16.10.103:heketidbstorage
        Mount Options: backup-volfile-servers=172.16.10.102,172.16.10.101
        Durability Type: replicate
        Replica: 3
        Snapshot: Disabled
    
            Bricks:
                Id: 2ea90ebd791a4230e927d233d1c8a7d1
                Path: /var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_2ea90ebd791a4230e927d233d1c8a7d1/brick
                Size (GiB): 2
                Node: 49ac6f56ef21408bcad7c7613cd40bd8
                Device: 2f6b2f6c289a2f6bf48fbec59c0c2009
    
                Id: 9dc7238db3240146f12189dd28320227
                Path: /var/lib/heketi/mounts/vg_f8776d0d92102fc3e272f2ec899e5f18/brick_9dc7238db3240146f12189dd28320227/brick
                Size (GiB): 2
                Node: fc21262379ec3636e3eadcae15efcc94
                Device: f8776d0d92102fc3e272f2ec899e5f18
    
                Id: cb68cbf4e992abffc86ab3b5db58ef56
                Path: /var/lib/heketi/mounts/vg_e100120226d5d9567ed0f92b9810236c/brick_cb68cbf4e992abffc86ab3b5db58ef56/brick
                Size (GiB): 2
                Node: bdf51ae46025cd4fcf134f7be36c32de
                Device: e100120226d5d9567ed0f92b9810236c
    
    
        Name: vol_900fb349e56af275f47d523d08fdfd6e
        Size: 1
        Id: 900fb349e56af275f47d523d08fdfd6e
        Cluster Id: ada54ffbeac15a5c9a7521e0c7d2f636
        Mount: 172.16.10.103:vol_900fb349e56af275f47d523d08fdfd6e
        Mount Options: backup-volfile-servers=172.16.10.102,172.16.10.101
        Durability Type: replicate
        Replica: 3
        Snapshot: Disabled
    
            Bricks:
                Id: 4c98684d878ffe7dbfc1008336460eed
                Path: /var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_4c98684d878ffe7dbfc1008336460eed/brick
                Size (GiB): 1
                Node: 49ac6f56ef21408bcad7c7613cd40bd8
                Device: 2f6b2f6c289a2f6bf48fbec59c0c2009
    
                Id: 7c82d03c88d73bb18d407a791a1053c2
                Path: /var/lib/heketi/mounts/vg_e100120226d5d9567ed0f92b9810236c/brick_7c82d03c88d73bb18d407a791a1053c2/brick
                Size (GiB): 1
                Node: bdf51ae46025cd4fcf134f7be36c32de
                Device: e100120226d5d9567ed0f92b9810236c
    
                Id: 822266f7ad3cf62b1e45686265cf7268
                Path: /var/lib/heketi/mounts/vg_f8776d0d92102fc3e272f2ec899e5f18/brick_822266f7ad3cf62b1e45686265cf7268/brick
                Size (GiB): 1
                Node: fc21262379ec3636e3eadcae15efcc94
                Device: f8776d0d92102fc3e272f2ec899e5f18
    
    
        Nodes:
    
        Node Id: 49ac6f56ef21408bcad7c7613cd40bd8
        State: online
        Cluster Id: ada54ffbeac15a5c9a7521e0c7d2f636
        Zone: 1
        Management Hostname: kube-node3
        Storage Hostname: 172.16.10.103
        Devices:
            Id:2f6b2f6c289a2f6bf48fbec59c0c2009   Name:/dev/sdb            State:online    Size (GiB):7       Used (GiB):5       Free (GiB):2       
                Bricks:
                    Id:2ea90ebd791a4230e927d233d1c8a7d1   Size (GiB):2       Path: /var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_2ea90ebd791a4230e927d233d1c8a7d1/brick
                    Id:4c98684d878ffe7dbfc1008336460eed   Size (GiB):1       Path: /var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_4c98684d878ffe7dbfc1008336460eed/brick
                    Id:c7acfcecaf85aada98b0c0208798440f   Size (GiB):2       Path: /var/lib/heketi/mounts/vg_2f6b2f6c289a2f6bf48fbec59c0c2009/brick_c7acfcecaf85aada98b0c0208798440f/brick
    
        Node Id: bdf51ae46025cd4fcf134f7be36c32de
        State: online
        Cluster Id: ada54ffbeac15a5c9a7521e0c7d2f636
        Zone: 1
        Management Hostname: kube-node2
        Storage Hostname: 172.16.10.102
        Devices:
            Id:e100120226d5d9567ed0f92b9810236c   Name:/dev/sdb            State:online    Size (GiB):7       Used (GiB):5       Free (GiB):2       
                Bricks:
                    Id:7c82d03c88d73bb18d407a791a1053c2   Size (GiB):1       Path: /var/lib/heketi/mounts/vg_e100120226d5d9567ed0f92b9810236c/brick_7c82d03c88d73bb18d407a791a1053c2/brick
                    Id:cb68cbf4e992abffc86ab3b5db58ef56   Size (GiB):2       Path: /var/lib/heketi/mounts/vg_e100120226d5d9567ed0f92b9810236c/brick_cb68cbf4e992abffc86ab3b5db58ef56/brick
                    Id:e2acc8268f17f05e940ebe679dacfa3a   Size (GiB):2       Path: /var/lib/heketi/mounts/vg_e100120226d5d9567ed0f92b9810236c/brick_e2acc8268f17f05e940ebe679dacfa3a/brick
    
        Node Id: fc21262379ec3636e3eadcae15efcc94
        State: online
        Cluster Id: ada54ffbeac15a5c9a7521e0c7d2f636
        Zone: 1
        Management Hostname: kube-node1
        Storage Hostname: 172.16.10.101
        Devices:
            Id:f8776d0d92102fc3e272f2ec899e5f18   Name:/dev/sdb            State:online    Size (GiB):7       Used (GiB):5       Free (GiB):2       
                Bricks:
                    Id:6e016b1ed8e16b6a28839f1670a56d00   Size (GiB):2       Path: /var/lib/heketi/mounts/vg_f8776d0d92102fc3e272f2ec899e5f18/brick_6e016b1ed8e16b6a28839f1670a56d00/brick
                    Id:822266f7ad3cf62b1e45686265cf7268   Size (GiB):1       Path: /var/lib/heketi/mounts/vg_f8776d0d92102fc3e272f2ec899e5f18/brick_822266f7ad3cf62b1e45686265cf7268/brick
                    Id:9dc7238db3240146f12189dd28320227   Size (GiB):2       Path: /var/lib/heketi/mounts/vg_f8776d0d92102fc3e272f2ec899e5f18/brick_9dc7238db3240146f12189dd28320227/brick
    

    总结:使用Kubernetes的动态存储供应模式,配置StorageClass和Heketi共同搭建基于GlusterFS的共享存储,相对于静态模式至少有两大优势。

    1. 一个是管理员无须预先创建大量的PV作为存储资源
    2. 用户在申请PVC时也无法保证容量与预置PV的容量能够一致。因此,从k8s v1.6开始,建议用户优先考虑使用StorageClass的动态存储供应模式进行存储管理。

    链接:https://www.orchome.com/1284
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
     
  • 相关阅读:
    MySQL-简述
    APP测试-Solo Pi工具-性能测试
    APP测试-弱网测试
    iOS 认识runtime 中的三个指针 isa , IMP , SEL
    iOS 什么是函数式编程
    iOS 根据农历日期 获取当前的农历年份 即 干支纪年法算农历年
    iOS 当公司有人向你提问,你该如何应对?
    Mac 环境 下使用Charles 抓包Http/Https请求
    iOS iPhone X 适配启动图片
    iOS11 仿大标题 导航栏
  • 原文地址:https://www.cnblogs.com/linux20190409/p/10976322.html
Copyright © 2011-2022 走看看