Kubermetes对于有状态的容器应用或者对数据需要持久化的应用,不仅需要将容器内的目录挂载到宿主机的目录
或者emptyDir临时存储卷
,而且需要更加可靠的存储来保存应用产生的重要数据,以便容器应用在重建之后,仍然可以使用之前的数据。不过,存储资源和计算资源(CPU/内存)的管理方式完全不同。为了能够屏蔽底层存储实现的细节,让用户方便使用,同时能让管理员方便管理, Kubernetes从v1.0
版本就引入PersistentVolume
和PersistentVolumeClaim
两个资源对象来实现对存储的管理子系统。
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的PV
、PVC
、StorageClass
和动态资源供应
等共享存储管理机制进行详细说明。
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 Plugin | ReadWriteOnce | ReadOnlyMany | ReadWriteMany |
---|---|---|---|
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): 简单清除文件的操作(例如执行
rm -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的相互关系遵循下图所示的生命周期。
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使用的存储管理机制。
在动态资源供应模式下,通过StorageClass和PVC完成资源动态绑定(系统自动生成PV),并供Pod使用的存储管理机制。
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-serverserver deploy]$ catcat topology.json
{
"clusters": [
{
"nodes": [
{
"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
You can find it at
You can find it
You can find it at https://github.com/heketi/heketi/releases . Alternatively,
use it from within
use it from within
use it from within the heketi pod:
# /opt/k8s
use it from within
use it from within the heketi pod:
# /opt/k8s/bin/kubectl -n defaultt fromhe heketi/opt
use it from within the heketi pod:
# /opt/k8s/bin/kubectl -n default exec -i heketi-75dcfb7d44-vj9bk -- heketidcfb7d44-vj9bk -- heketi-cli -sdcfb7d44-vj9bk -- heketi-cli -s https://localhost:8080 --user admin --secret '<ADMIN_KEY>' cluster list
For dynamic provisioning, create this:
---
apiVersion: storage.k8s
For dynamic provisioning, create a StorageClass similarisioning, create
For dynamic provisioning, create a provisioning
For dynamic provisioning, create a StorageClass similar
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage
For dynamic provisioning
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storagedynamicisioning, createimilar to
For
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storageic provisioninging, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.iodynamicrageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: glusterfs dynamicreate a similar
For dynamic provisioning, create a
For
For dynamic provisioning, create aisioning, create a StorageClass similar to this provisioning, create a StorageClass similar to this:
---
apiVersion
For dynamic provisioningovisioning, create a StorageClass similar
For dynamic provisioning, create
For dynamic provisioning, create a
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kindprovisioning create a StorageClassFor dynamic provisioning, create a
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage dynamiconing, create StorageClass
For dynamic provisioningFor dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8sdynamicisioning, create
For dynamic provisioning, create a
For dynamic provisioning, create a StorageClass similar to thisor dynamicing, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning
For dynamic provisioning, create
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kind
For dynamic provisioning, create a
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8samic provisioningreate a
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create
For dynamic provisioning, create a
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kinddynamiconing, createageClass similar
For dynamic provisioning, create a StorageClass
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata
For dynamic provisioning, create
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: glusterfs-storage
provisioner: kubernetes
For dynamic provisioning, create a StorageClass
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: glusterfs-storage
provisionerdynamicsioning, createate ato
For dynamic provisioning, create a StorageClass similar
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name: glusterfsamic provisioningreate a
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io
For dynamic provisioning, create a StorageClass similar
For dynamic provisioning, create a StorageClass similar
For dynamic provisioning, create a StorageClass similar
For dynamic provisioning, create a StorageClass similar
For dynamic provisioning, create a StorageClass similar to this:
---
apiVersion: storage.k8s.io/v1beta1
kind: StorageClass
metadata:
name
For dynamicic provisioningoning, createrageClass 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上看看这个刚创建的存储卷:
通过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:
[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来进行管理。
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的共享存储,相对于静态模式至少有两大优势。
- 一个是管理员无须预先创建大量的PV作为存储资源
- 用户在申请PVC时也无法保证容量与预置PV的容量能够一致。因此,从
k8s v1.6
开始,建议用户优先考虑使用StorageClass
的动态存储供应模式进行存储管理。