3.4.执子之手:Ceph RBD
死生契阔,与子成说。执子之手,与子偕老。——《诗经》
前边三个章节我们已经搭建好了K8S、Ceph、Harbor,基础环境已经有了,接下来这个章节就让K8S和Ceph联动起来,将Ceph作为K8S的底层存储引擎让二者协同工作,不论是之后的KubeSphere还是TiDB都可以直接使用本章配置的结果来访问底层存储。

K8S和Ceph集成有三种实现方式:
Volumes存储卷
PV/PVC持久化卷/持久化卷声明
StorageClass动态存储,动态创建PV、PVC
Ceph支持K8S存储有两种类型:
CephFS:文件系统
Ceph RBD:块存储
注意:一般写CephFS会将Ceph和FS连写,而RBD则中间加一空白来写!
1. ceph-csi
CSI全称Container Storage Interface,它是Ceph的一个插件,它的目的是定义行业标准“容器存储接口”,使存储供应商(SP)可以开发一个符合CSI标准的插件并使其能够在多个容器编排(CO)系统中工作。
本章K8S通过ceph-csi(csi plugin)来接入ceph存储(csi相关组件的分析以rbd为例进行分析),对csi系统结构、涉及的k8s对象和组件进行简单介绍,以及k8s对存储进行相关操作流程分析,存储相关操作包括存储创建、存储扩容、存储挂载、解除存储、存储删除操作。
1.1. 整体架构
图参考文档中内容重绘,PV/PVC/SC此处不解释其作用(烂大街的概念),下文主要围绕CSI部分。

VolumeAttachment组件
该组件记录了PV挂载的相关信息:挂载到哪个Node节点、由哪个Volume Plugin来挂载等。AD Controller会创建一个VolumeAttachment,而External-Attacher通过观察该VolumeAttachment,根据状态属性来执行存储的挂载、卸载操作。
CSINode
CSINode记录了csi plugin相关信息(NodeId、DriverName、拓扑),当Node Driver Register向kubelet注册一个csi plugin之后,会创建(更新)一个CSINode对象,记录csi plugin的相关信息。
Volume Plugin
该组件扩展各种存储类型的卷管理能力,实现第三方存储各种操作能力和K8S存储系统结合,并调用第三方存储的接口或命令,从而提供数据卷的创建/删除、attach/detach、mount/umount具体操作实现,可以认为是第三方存储代理人。
in-tree:在K8S源码内部实现,和K8S一起发布、管理,更新迭代慢、灵活性差。
out-of-tree:代码独立于K8S,由存储厂商实现,有
csi, flexvolume两种实现。
CSI Plugin
ceph-csi就属于csi plugin,它主要分为ControllerServer和NodeServer,负责不同的存储操作。
External Plugin
主要包含四个子组件(参考图),它辅助csi plugin组件共同完成存储相关的操作。
provisioner
Watch PVC对象,调用csi plugin创建存储,最终创建PV。
attacher
Watch VolumeAttachment对象,调用csi plugin做attach/dettach操作。
resizer
Watch PVC对象,调用csi plugin来做存储扩容。
snapshotter
创建快照。
Node-Driver-Registrar
该组件负责实现csi plugin(NodeServer)的注册,让kubelet感知csi plugin的存在。
AD/PV Controller
PV Controller负责PV、PVC绑定和生命周期管理(创建/删除底层存储、创建/删除PV对象、PV和PVC对象状态变更)。
AD Controller全称Attachment/Detachment控制器,主要负责创建、删除VolumeAttachment对象,并调用volume plugin来做存储设备的Attach/Detach操作(将数据卷挂载到特定node节点上/从特定node节点上解除挂载),以及更新node.Status.VolumesAttached等。
关于这部分内容参考引用博文第一章,这里就不再做过多介绍,本章节的基本介绍只是起一个抛砖引玉的作用。
1.2. CSI插件
ceph-csi的块设备功能要K8S v1.13以上或更高版本才可用,它动态提供了RBD映像以支持K8S卷并将这些RBD映像映射为工作节点上的块设备(可选地挂载映像中包含的文件系统)运行引用RBD支持卷的Pod。它的整体结构如下:

所以您可以通过kubernetes sidecar部署provisioner, attacher, resizer, driver-registrar, snapshotter组件以支持CSI功能。ceph-csi插件实现了支持CSI的Container Orchestrator(OC)和Ceph集群之间的接口,允许动态供应Ceph卷并将它们附加到工作负载中。默认情况下ceph-csi使用RBD内核模块,可能不支持所有的Ceph CRUSH可调参数或RBD映像等特性。
2. Ceph RBD部署
2.1.Ceph: Pool
默认情况下,Ceph块设备使用rbd池,使用下边命令为K8S创建一个池:

您可以登录Ceph集群管理界面等待任务执行完成(截图中可以看到Applications类型是
rbd):
为K8S创建新的Ceph账号


账号创建完成后,ceph-csi需要一个存储在K8S中的ConfigMap对象来定义Ceph集群的Ceph mon地址

2.2.K8S: ConfigMap
将部署配置放在
~/deploy/ceph中,clusterID需要和上边取得的id保持一致,并且需要修改mon地址,多个地址后面要使用逗号分隔。文件内容如下:

在K8S中创建该ConfigMap对象:

按照步骤4-5创建额外的几个ConfigMap(必须)
2.3.K8S: RBAC
ceph-csi需要创建ServiceAccount和RBAC用于访问集群内部信息,先下载yaml文件:
将下载的两个yaml文件内容配置到K8S中:

2.4.K8S: provisioner
下载两个yaml文件到本地:

查看第一个yaml文件中的镜像,手动拉取镜像(推荐)
将两个配置文件内容配置到K8S中:
查看csi插件是否已经启动,
FailedScheduling问题参考问题章节:
2.5.K8S: Secret
获取
ceph用户信息,找到client.admin用户,复制后边的Key,然后创建一个Secret对象:最终结果如下:

2.6.K8S: StorageClass
先获取集群ID
创建新的yaml文件(StorageClass)
将Yaml文件内容配置到K8S

注:上述
ceph-rbd-k8s如果并没有带(default)标记,证明它不是默认的SC,您需要执行如下命令将它设置成默认:
最后创建
PVC验证当前SC是否可用:
注意成功的标记是状态必须是Bound,如果状态不是这个值,证明有问题,可使用如下命令查看日志:
2.7. imageFeatures
上述SC中配置了一个imageFeatures的属性,对Ceph而言,该属性的值如下:
layering
image的克隆操作,可对image创建快照并保护,然后从快照克隆新的image,父子image之间使用COW技术,共享对象数据。
striping v2
条带化对象数据,类似raid 0,可改善顺序读写场景较多情况下的性能。
exclusive lock
保护image数据一致性,对image做修改时,需要持有此锁。这个可以看做是一个分布式锁,在开启的时候,确保只有一个客户端在访问image,否则锁的竞争会导致io急剧下降。 主要应用场景是qemu live-migration。
object map
此特性依赖于exclusive lock。因为image的对象分配是thin-provisioning,此特性开启的时候,会记录image所有对象的一个位图,用以标记对象是否真的存在,在一些场景下可以加速io。
fast diff
此特性依赖于object map和exlcusive lock。快速比较image的snapshot之间的差异。
deep-flatten
layering特性使得克隆image的时候,父子image之间采用COW,他们之间的对象文件存在依赖关系,flatten操作的目的是解除父子image的依赖关系,但是子image的快照并没有解除依赖,deep-flatten特性使得快照的依赖也解除。
journaling
依赖于exclusive lock。将image的所有修改操作进行日志化,并且复制到另外一个集群(mirror),可以做到块存储的异地灾备。这个特性在部署的时候需要新部署一个daemon进程,目前还在试验阶段,不过这个特性很重要,可以做跨集群/机房容灾。
Exclusive Lock
从上面可以看出,很多特性都依赖于exclusive lock,重点介绍一下。
exclusive lock
是分布式锁,实现的时候默认是客户端在第一次写的时候获取锁,并且在收到其他客户端的锁请求时自动释放锁。这个特性在jewel默认开启后,本身没什么问题, 客户端可以自动获取和释放锁,在客户端crash后也能够正确处理。
3. CephFS 部署
前文讲述了Ceph中Block存储块的部署教程,并且借用CSI架构在K8S中初始化了将要使用的SC(Storage Class),本章节基于CephFS搭建另一个SC,搭建之前先看搭建完成后的总体拓扑图(注意ConfigMap共享):

CephFS部署的文件地址从https://raw.githubusercontent.com/ceph/ceph-csi/master/deploy/cephfs/kubernetes/下载,将前边命令中的下载地址稍做修改即可,而前文中已经创建了CephFS:

所以跳过前边所有内容的apply,直接进入第二章节的第五步。

查看运行情况:

3.1. K8S: Secret
使用下边命令查看账号信息
admin和k8s:
根据两个密钥创建一个新的Secret

3.2.K8S: StorageClass
先获取集群ID
编辑配置文件创建SC
将Yaml文件内容配置到K8S

最后创建
PVC验证当前SC是否可用:
最后切换默认SC:

4. 问题
4.1. FailedScheduling

这个问题的主要原因是K8S的Master节点默认是不参与调度的,且在Master节点上有一个污点NoSchedule(表示K8S不会将Pod调度到具有污点的Node上),若想让master节点参与调度,则需要先删除污点,允许k8s将Pod调度到该节点Node上,再添加master为nodes角色。
先查看node以及污点

删除污点

再查看Pods运行情况:

Last updated