4.3 容器原生存储的选择
在容器云中,Pod会经常被创建和销毁,也会在不同的主机之间快速迁移。为了保证容器在重启或者迁移以后能够使用原来的数据,容器必须使用持久化存储。因此,持久化存储的管理对于PaaS平台来说非常重要。
Kubernetes/OpenShift通过PV(PVC)管理持久化存储。PV分为动态PV和静态PV。如果使用静态PV,我们就需要手工创建PV或者预先创建大量的PV。在生产中,这种方式会给运维带来极大的困扰,因此我们推荐使用动态PV。接下来介绍如何基于Ceph实现容器原生存储,从而实现动态PV。
为了实现容器存储接口标准化,开源界提出容器存储接口(Container Storage Interface,CSI)。CSI旨在提供一种标准,让块存储和文件系统可以在符合这种标准的情况下,为Kubernetes上的容器提供持久化存储。随着CSI的应用,Kubernetes存储层变得真正可扩展。CSI使得第三方存储提供商可以编写和部署插件,发布支持Kubernetes的存储系统,而无须触及核心Kubernetes代码。CSI为Kubernetes用户提供了更多存储选项,使容器中的应用系统更加安全、可靠。
Ceph从v14开始支持CSI。也就是说,从Ceph v14开始,OpenShift访问Ceph时必须要通过CSI Driver。但是,在部署Ceph集群时,CSI Driver不会被自动部署到集群中,需要手工安装,步骤较为复杂,也不利于运维。出于方便Kubernetes纳管Ceph的目的,开源社区提出了Rook项目。
Rook(https://rook.io/)是一个开源项目,红帽是该项目的顶级代码贡献商之一。Rook由Operator提供,它可以实现Ceph的部署、配置、供应、扩展、升级、迁移、灾难恢复、监视和资源管理自动化。红帽OpenShift容器存储架构就是通过Rook纳管Ceph实现的。
4.3.1 OpenShift容器存储架构
基于Ceph和Rook,红帽构建了OpenShift容器存储架构(OpenShift Container Storage,OCS)。需要指出的是,新版本的OCS已经改名为Data Foundation。OCS是Rook和Ceph的企业级解决方案,其架构如图4-53所示。
图4-53 OCS架构图
从图4-53可以看出,OCS的组件都是以Pod形式运行在OpenShift中,Pod的具体作用会在后文展开说明。
OCS有两种工作模式,分析如下。
- 内置(Internal)模式:把OCS整体(OCS Operator和Ceph集群)部署在OpenShift集群中,把OpenShift的本地存储空间作为Ceph存储空间。这种模式的部署、使用都非常方便,适合开发测试和PoC环境。
- 外置(External)模式:在OpenShift上部署OCS Operator,对接在外部物理机上安装的Ceph;然后OpenShift以Rook的方式,管理外部物理机上的Ceph。外置模式的优势是实现了OpenShift和存储的解耦,而且存储性能较高,适合生产环境。
在介绍了OCS的架构后,接下来我们介绍OCS的部署步骤。
4.3.2 创建OCS存储
在OpenShift的Operator Hub中找到对应的Operator(图中显示名称仍为更名之前的称呼),如图4-54所示。
图4-54 选择OCS Operator
OCS Operator部署成功后会提供三个API:Storage Cluster、Backing Store、Bucket Class,如图4-55所示。
图4-55 OCS Operator提供的API
OCS Operator安装成功后,会在openshift-storage项目中部署三个Operator:
# oc get pods -n openshift-storage NAME READY STATUS RESTARTS AGE noobaa-operator-5c6dcb944b-8cds4 1/1 Running 0 42s ocs-operator-56d4d7ddc7-4qfxq 1/1 Running 0 45s rook-ceph-operator-7b46bff769-t9h8c 1/1 Running 0 45s
使用OCS Operator中的Storage Cluster API创建存储集群,如图4-56所示。
图4-56 创建存储集群
如前文所述,OCS有内置和外置两种模式。我们先选择内置模式,如图4-57所示。
图4-57 创建存储集群
选择内置模式后,OCS会列出OpenShift集群中可创建存储集群的节点。需要注意的是,OCS要求加入存储集群的OpenShift节点至少有16个CPU和64 GB内存,同时节点至少要选择三个,且不在一个故障域中。我们选择3个OpenShift节点,如图4-58所示。
图4-58 选择节点
存储空间选择2TiB,这代表三个存储节点,每个节点的内存是2TiB,做三副本,如图4-59所示。
图4-59 查看OCS相关Pod
存储集群创建后,会在openshift-storage项目中部署对应的Pod,以CSI开头的Pod为与CSI Driver相关的Pod,因此使用OCS时,我们不必单独安装CSI Driver;以rook开头的Pod为被Rook纳管的容器化Ceph组件,如图4-60所示。
图4-60 查看OCS相关Pod
所有Pod部署完毕后,在OpenShift中查看存储集群,显示已经部署成功:
# oc get storagecluster -n openshift-storage NAME AGE PHASE EXTERNAL CREATED AT VERSION ocs-storagecluster 39m Ready 2020-10-11T 14:20:27Z 4.5.0
查看storagecluster对象中的内容,看到集群有2TiB空间(每个存储节点大小为2TiB,有三个副本),如图4-61所示。
图4-61 查看存储集群
查看OCS新创建的三个存储类,分别为ceph-rbd、cephfs、ceph-rgw,如图4-62所示。
图4-62 查看新创建的存储类
接下来,我们查看ceph-rbd、cephfs这两个存储类的相关内容。
查看ceph-rbd,看到其相关的参数和该存储类对应的存储池,如图4-63所示。
图4-63 查看新创建的ceph-rbd的内容
查看cephfs,发现该存储类不对应pool,而是对应fs,且可以看到fsName,如图4-64所示。
图4-64 查看新创建的cephfs的内容
如果我们想要从Ceph集群角度查看集群的状态和资源,可以使用Rook-Ceph工具。Rook-Ceph工具需要手工部署:
#oc patch ocsInitialization ocsinit -n openshift-storage --type json --patch '[{ "op": "replace", "path": "/spec/enableCephTools", "value": true }]'
在rook-ceph-tools Pod运行之后,采用如下方法访问工具。首先设置变量:
#TOOLS_POD=$(oc get pods -n openshift-storage -l app=rook-ceph-tools -o name)
登录工具Pod:
#oc rsh -n openshift-storage $TOOLS_POD
登录后,就可以使用Ceph命令行来检查存储集群。我们可以看到集群的health、mon、mgr、mds的状态,如图4-65所示。
图4-65 查看新创建的集群状态
查看Ceph集群OSD状态,可以看到Ceph集群中一共有3个OSD节点,每个节点提供2TiB存储空间,如图4-66所示。
图4-66 查看Ceph集群存储节点
查看存储空间的使用情况,可以看到rbd和CephFS的使用情况,如图4-67所示。
图4-67 查看Ceph集群存储空间使用情况
查看Ceph版本,为14.2.8,如图4-68所示。
图4-68 查看Ceph版本
在成功部署了OCS以后,我们接下来介绍如何基于OCS的存储空间创建应用。在以下两节中,我们主要介绍如何使用OCS的rbd和CephFS来为OpenShift容器应用提供持久化存储。
4.3.3 使用rbd为应用提供持久化存储
接下来,我们在OpenShift中使用OCS-storagecluster-ceph-rbd存储类来创建RWO(ReadWriteOnce)持久性存储,供新建的应用使用。
我们使用rails-pgsql-persistent模板在OpenShift上部署应用(包含前端应用和一个数据库)。该模板包含一个参数STORAGE_CLASS,在部署应用时,我们通过这个参数指定pvc使用的STORAGE_CLASS。
首先创建项目:
oc new-project my-database-app
通过模板创建应用,指定使用名为ocs-storagecluster-ceph-rbd的存储类,所需空间大小为5GiB。
#oc new-app -f /opt/app-root/src/support/ocslab_rails-app.yaml -p STORAGE_CLASS= ocs-storagecluster-ceph-rbd -p VOLUME_CAPACITY=5Gi
查看应用的部署情况:前端应用和后端PostgreSQL数据库都已经部署成功,如图4-69所示。
图4-69 查看成功部署的应用
查看pvc,发现PostgreSQL已经和pvc自动绑定,如图4-70所示。这个pvc是OCS根据部署应用时指定的容量和读写模式最终在Ceph存储上自动创建的rbd卷,如图4-70所示。
图4-70 查看pvc
接下来,我们从Ceph存储集群角度,确认OCS自动创建的rbd卷。再次登录Ceph工具。
#TOOLS_POD=$(oc get pods -n openshift-storage -l app=rook-ceph-tools -o name) #oc rsh -n openshift-storage $TOOLS_POD
我们先获取rbd存储池的名称,如图4-71所示,为ocs-storagecluster-cephblockpool。
图4-71 查看rbd存储池
查看存储池中的卷,如图4-72所示。
图4-72 查看rbd卷
如果想确认我们刚部署的应用具体使用哪个卷,使用如下脚本:
#CSIVOL=$(oc get pv $(oc get pv | grep my-database-app | awk '{ print $1 }') -o jsonpath='{.spec.csi.volumeHandle}' | cut -d '-' -f 6- | awk '{print "csi- vol-"$1}') #echo $CSIVOL
从图4-73所示的输出中,我们可以看到,PostgreSQL数据库使用的pv对应的rbd卷为csi-vol-85766b1b-f719-11ea-b9a2-0a580a830405,即图4-72中的第一个卷。
图4-73 查看数据库使用的rbd卷
使用如下脚本查看rbd卷的具体信息,可以看到卷的大小,如图4-74所示。
图4-74 查看rbd卷的信息
TOOLS_POD=$(oc get pods -n openshift-storage -l app=rook-ceph-tools -o name) oc rsh -n openshift-storage $TOOLS_POD rbd -p ocs-storagecluster-cephblockpool info $CSIVOL
在介绍了如何通过rbd为容器应用提供持久化存储后,接下来我们介绍如何通过CephFS为容器应用提供持久化存储。
4.3.4 使用CephFS为应用提供持久化存储
使用rbd创建的pv,只能被一个Pod读写。但有些时候,我们需要提供可被多个Pod共享的持久化存储,这就需要使用RWX(ReadWriteMany)模式的pvc。接下来我们通过使用ocs-storagecluster-cephfs存储类,创建可同时由多个Pod使用的存储空间。
首先部署PHP应用程序示例,名为file-uploader:
#oc new-app openshift/php:7.2~https://github.com/christianh814/openshift-php- upload-demo --name=file-upload
应用部署成功后,如图4-75所示。此时的应用是没有持久化存储的。
图4-75 查看部署成功的Pod
为应用创建路由,并将应用的副本数增加到3:
#oc expose svc/file-uploader -n my-shared-storage #oc scale --replicas=3 dc/file-uploader
接下来,我们使用OCS-storagecluster-cephfs存储类创建一个PersistentVolumeClaim,并使用oc set volume命令将其附加到应用程序中,指定pvc需要的存储空间大小、读写模式:
#oc set volume dc/file-uploader --add --name=my-shared-storage \ -t pvc --claim-mode=ReadWriteMany --claim-size=1Gi \ --claim-name=my-shared-storage --claim-class=ocs-storagecluster-cephfs \ --mount-path=/opt/app-root/src/uploaded \
获取应用的路由:
#oc get route file-uploader -n my-shared-storage -o jsonpath --template="{.spec.host}"
通过浏览器访问应用,如图4-76所示,可以上传文件,将应用Pod重启后,发现上传的文件仍在,证明文件已经被存入持久化存储中。由于篇幅有限,具体步骤不再展开说明。
图4-76 浏览器访问应用
至此,我们介绍了如何使用OCS的rbd和CephFS为容器提供持久化存储。在以上环境中,我们使用了OCS的内置模式,将Ceph安装在OCP内部。但在生产环境中,如果客户对Ceph的容量和性能要求较高,就需要使用OCS的外置模式。接下来,我们介绍通过OCS纳管外部Ceph存储。
4.3.5 OCS Operator对接外部存储
在创建存储集群时,我们选择外部存储,会看到界面将提示下载一个Python脚本,如图4-77所示。
图4-77 Operator对接外部存储
我们在外置的Ceph的mon节点上执行这个脚本。首先查看脚本的使用帮助:
#python ceph-external-cluster-details-exporter.py --help
在下面的命令中,rbd-data-pool-name指定要创建的存储池的名称;rgw-endpoint指定Ceph集群对象网关地址:
#python ceph-external-cluster-details-exporter.py --rbd-data-pool-name abc --rgw- endpoint 192.168.18.203:8080
命令执行后,会以JSON格式返回一串输出结果,将结果粘贴到图4-77所示的空白处,即可完成添加。后续的操作步骤与内置模式类似,这里不再展开说明。
通过本节,相信你会对容器原生存储有一定的了解。通过Rook Operator,Kubernetes/OpenShift可以方便地使用持久化存储,解决了容器云在运维方面使用持久化存储的困扰。随着容器云的普及,相信Ceph的应用场景会越来越广。