使用Rook在Kubernetes上部署Ceph集群

一、简介

rook

在本文中,我们将使用Rook在Kubernetes集群中设置Ceph存储。然后使用Ceph的块存储来持久存储MongoDB数据库的数据。

完成后,您将了解什么是Rook以及如何使用它来部署Ceph。您还将了解如何使用Rook在Kubernetes中部署其他一些存储后端。

二、环境准备

在开始之前,您需要满足以下条件:

  • 事先准备好一个具有4个节点的Kubernetes集群:1个Master节点和3个Node节点。每个节点都是具有至少4GB RAM 的Ubuntu 18.04服务器。在本教程中,主节点命名为master,工作节点命名为node-01node-02node-03
  • 配置为与上述集群通信的kubectl实用程序。
主机 系统 IP 配置
master ubuntu18.04 10.10.10.61 4C8G50G
node-01 ubuntu18.04 10.10.10.58 4C8G50G+50G
node-02 ubuntu18.04 10.10.10.59 4C8G50G+50G
node-03 ubuntu18.04 10.10.10.60 4C8G50G+50G
1kubectl get node
2NAME          STATUS   ROLES               AGE   VERSION
310.10.10.58   Ready    worker              81s   v1.18.6
410.10.10.59   Ready    worker              81s   v1.18.6
510.10.10.60   Ready    worker              81s   v1.18.6
610.10.10.61   Ready    controlplane,etcd   84s   v1.18.6

备注

如果你还没有Kubernetes集群,推荐使用RKE快速部署Kubernetes集群

工作节点的50G磁盘用于Ceph OSD使用。


三、安装部署

3.1 部署Rook Operator

Rook是[Cloud Native Computing Foundation(CNCF)](https://cncf.io)的一个孵化项目。它专用于存储编排,并允许在Kubernetes集群中直接部署多个存储解决方案。在本文中,我们将重点介绍Ceph存储,但是还可以使用其他存储解决方案。

备注:Ceph和EdgeFS当前是Rook处于Stable状态所支持的两个存储提供程序。其他存储提供程序(如Cassandra,Minio,NFS,CockroachDB,YugabyteDB)处于Alpha状态。

首先,我们从GitHub仓库release页面下载并使用Release 1.4.1(迄今为止的最新版本)

1wget https://github.com/rook/rook/archive/v1.4.1.tar.gz
2tar xf v1.4.1.tar.gz
3cd rook-1.4.1

对于Rook支持的每个存储解决方案,都有一个Kubernetes Operator。简而言之,Operator是一个运行在Pod中的包含管理复杂应用程序的所有逻辑的应用。Operator通常用于管理有状态的应用程序。

首先,我们将进入包含Ceph需要的所有资源的文件夹。

1cd cluster/examples/kubernetes/ceph

接下来,我们部署Rook的Ceph Operator所需的所有资源。

 1kubectl create -f common.yaml
 2namespace/rook-ceph created
 3customresourcedefinition.apiextensions.k8s.io/cephclusters.ceph.rook.io created
 4customresourcedefinition.apiextensions.k8s.io/cephclients.ceph.rook.io created
 5customresourcedefinition.apiextensions.k8s.io/cephrbdmirrors.ceph.rook.io created
 6customresourcedefinition.apiextensions.k8s.io/cephfilesystems.ceph.rook.io created
 7customresourcedefinition.apiextensions.k8s.io/cephnfses.ceph.rook.io created
 8customresourcedefinition.apiextensions.k8s.io/cephobjectstores.ceph.rook.io created
 9customresourcedefinition.apiextensions.k8s.io/cephobjectstoreusers.ceph.rook.io created
10customresourcedefinition.apiextensions.k8s.io/cephobjectrealms.ceph.rook.io created
11customresourcedefinition.apiextensions.k8s.io/cephobjectzonegroups.ceph.rook.io created
12customresourcedefinition.apiextensions.k8s.io/cephobjectzones.ceph.rook.io created
13customresourcedefinition.apiextensions.k8s.io/cephblockpools.ceph.rook.io created
14customresourcedefinition.apiextensions.k8s.io/volumes.rook.io created
15customresourcedefinition.apiextensions.k8s.io/objectbuckets.objectbucket.io created
16customresourcedefinition.apiextensions.k8s.io/objectbucketclaims.objectbucket.io created
17clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-object-bucket created
18serviceaccount/rook-ceph-admission-controller created
19clusterrole.rbac.authorization.k8s.io/rook-ceph-admission-controller-role created
20clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-admission-controller-rolebinding created
21clusterrole.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
22role.rbac.authorization.k8s.io/rook-ceph-system created
23clusterrole.rbac.authorization.k8s.io/rook-ceph-global created
24clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
25clusterrole.rbac.authorization.k8s.io/rook-ceph-object-bucket created
26serviceaccount/rook-ceph-system created
27rolebinding.rbac.authorization.k8s.io/rook-ceph-system created
28clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-global created
29serviceaccount/rook-ceph-osd created
30serviceaccount/rook-ceph-mgr created
31serviceaccount/rook-ceph-cmd-reporter created
32role.rbac.authorization.k8s.io/rook-ceph-osd created
33clusterrole.rbac.authorization.k8s.io/rook-ceph-osd created
34clusterrole.rbac.authorization.k8s.io/rook-ceph-mgr-system created
35role.rbac.authorization.k8s.io/rook-ceph-mgr created
36role.rbac.authorization.k8s.io/rook-ceph-cmd-reporter created
37rolebinding.rbac.authorization.k8s.io/rook-ceph-cluster-mgmt created
38rolebinding.rbac.authorization.k8s.io/rook-ceph-osd created
39rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr created
40rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-system created
41clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-cluster created
42clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-osd created
43rolebinding.rbac.authorization.k8s.io/rook-ceph-cmd-reporter created
44podsecuritypolicy.policy/00-rook-privileged created
45clusterrole.rbac.authorization.k8s.io/psp:rook created
46clusterrolebinding.rbac.authorization.k8s.io/rook-ceph-system-psp created
47rolebinding.rbac.authorization.k8s.io/rook-ceph-default-psp created
48rolebinding.rbac.authorization.k8s.io/rook-ceph-osd-psp created
49rolebinding.rbac.authorization.k8s.io/rook-ceph-mgr-psp created
50rolebinding.rbac.authorization.k8s.io/rook-ceph-cmd-reporter-psp created
51serviceaccount/rook-csi-cephfs-plugin-sa created
52serviceaccount/rook-csi-cephfs-provisioner-sa created
53role.rbac.authorization.k8s.io/cephfs-external-provisioner-cfg created
54rolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role-cfg created
55clusterrole.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
56clusterrole.rbac.authorization.k8s.io/cephfs-external-provisioner-runner created
57clusterrolebinding.rbac.authorization.k8s.io/rook-csi-cephfs-plugin-sa-psp created
58clusterrolebinding.rbac.authorization.k8s.io/rook-csi-cephfs-provisioner-sa-psp created
59clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-nodeplugin created
60clusterrolebinding.rbac.authorization.k8s.io/cephfs-csi-provisioner-role created
61serviceaccount/rook-csi-rbd-plugin-sa created
62serviceaccount/rook-csi-rbd-provisioner-sa created
63role.rbac.authorization.k8s.io/rbd-external-provisioner-cfg created
64rolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role-cfg created
65clusterrole.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
66clusterrole.rbac.authorization.k8s.io/rbd-external-provisioner-runner created
67clusterrolebinding.rbac.authorization.k8s.io/rook-csi-rbd-plugin-sa-psp created
68clusterrolebinding.rbac.authorization.k8s.io/rook-csi-rbd-provisioner-sa-psp created
69clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-nodeplugin created
70clusterrolebinding.rbac.authorization.k8s.io/rbd-csi-provisioner-role created

这些资源主要是CustomRessourceDefinitions,也称为CRD。它们用于定义将由Operator使用的新资源(Kubernetes中默认不存在的读取资源)。创建的其他资源主要与访问权限链接,因此Operator可以与集群的API Server进行通信:

  • ServiceAccount
  • Role
  • RoleBinding
  • ClusterRole
  • ClusterRoleBinding

接下来,我们部署Ceph Operator,该Operator将负责Ceph集群的设置和协调。

1kubectl create -f operator.yaml
2configmap/rook-ceph-operator-config created
3deployment.apps/rook-ceph-operator created

Operator需要几秒钟来启动并运行。可以使用以下命令验证其状态。

1kubectl get pod -n rook-ceph

一旦Operator准备就绪,它将触发创建**DaemonSet,**以负责在Kubernetes集群的每个Node节点上部署rook-discover代理。

最后,一切设置完成后,上述命令的结果类似于以下输出。

1NAME                                  READY   STATUS    RESTARTS   AGE
2rook-ceph-operator-58496b74f9-qppxc   1/1     Running   0          4m18s
3rook-discover-cmt2x                   1/1     Running   0          3m6s
4rook-discover-p92sh                   1/1     Running   0          3m6s
5rook-discover-q9k5z                   1/1     Running   0          3m6s

注意

Operator在您的环境中会有所不同

现在一切就绪,可以使用操作员部署Ceph集群了。


3.2 创建Ceph集群

现在,我们将在Kubernetes集群中创建一个Ceph集群。

下图显示了所有与Ceph相关的过程,这些过程将在集群中作为Pod运行。

rook-architecture

Rook架构

  • mgrManager守护程序,负责跟踪运行时指标和Ceph集群的当前状态。对于高可用性群集,至少需要2个Ceph管理器
  • mon是一个**Monitor,**负责维护Ceph守护程序相互协调所需的集群状态映射。对于高可用性群集,至少需要三个监视器
  • osd是一个对象存储守护程序,负责存储数据,处理数据复制,恢复,重新平衡。对于HA Ceph集群,至少需要3个Ceph OSD

首先,我们使用以下规范定义CephCluster资源。

 1---
 2apiVersion: ceph.rook.io/v1
 3kind: CephCluster
 4metadata:
 5  name: rook-ceph
 6  namespace: rook-ceph
 7spec:
 8  cephVersion:
 9    image: ceph/ceph:v14.2
10  allowUnsupported: false
11  dataDirHostPath: /var/lib/rook
12  skipUpgradeChecks: false
13  mon:
14    count: 3
15    allowMultiplePerNode: false
16  dashboard:
17    enabled: true
18    ssl: true
19  monitoring:
20    enabled: false
21    rulesNamespace: rook-ceph
22  network:
23    hostNetwork: false
24  rbdMirroring:
25    workers: 0
26  storage:
27    useAllNodes: true
28    useAllDevices: true

它基本上定义了集群的配置方式。属性useAllNodesuseAllDevices设置为**true,**这样Kubernetes集群的每个工作节点将用于部署Ceph的进程,并且附加到这些节点的所有设备将用于持久存储Ceph集群的数据。

然后我们创建集群:

1kubectl apply -f cluster.yaml

此新CephCluster资源的创建将通知Ceph Operator,并将向API Server发送请求,以创建所有与Ceph相关的Pod。

接下来,我们确保负责Ceph集群的所有Pod都已启动并正在运行。

1kubectl get pod -n rook-ceph

创建集群通常需要几分钟。完成此操作后,我们将获得类似于以下输出的列表。

 1NAME                                                    READY   STATUS      RESTARTS   AGE
 2csi-cephfsplugin-d9wct                                  3/3     Running     0          5m54s
 3csi-cephfsplugin-m2dgp                                  3/3     Running     0          5m54s
 4csi-cephfsplugin-provisioner-598854d87f-b5v79           6/6     Running     0          5m53s
 5csi-cephfsplugin-provisioner-598854d87f-jvbz2           6/6     Running     0          5m53s
 6csi-cephfsplugin-vrdz7                                  3/3     Running     0          5m54s
 7csi-rbdplugin-9d6cd                                     3/3     Running     0          5m54s
 8csi-rbdplugin-provisioner-dbc67ffdc-p522n               6/6     Running     0          5m54s
 9csi-rbdplugin-provisioner-dbc67ffdc-zm6kw               6/6     Running     0          5m54s
10csi-rbdplugin-s2f4f                                     3/3     Running     0          5m54s
11csi-rbdplugin-tkc66                                     3/3     Running     0          5m54s
12rook-ceph-crashcollector-10.10.10.58-df496b478-jrjl5    1/1     Running     0          49s
13rook-ceph-crashcollector-10.10.10.59-8487c88d5c-8w28n   1/1     Running     0          4m33s
14rook-ceph-crashcollector-10.10.10.60-7fcd8df78f-xw8j8   1/1     Running     0          2m39s
15rook-ceph-mgr-a-75b8c8b8f6-6c2wz                        1/1     Running     0          86s
16rook-ceph-mon-a-7b55d965b7-mr56c                        1/1     Running     0          4m33s
17rook-ceph-mon-b-bfdf4cd44-lh4bf                         1/1     Running     0          4m23s
18rook-ceph-mon-c-849775f65f-s5ngv                        1/1     Running     0          2m39s
19rook-ceph-operator-58496b74f9-qppxc                     1/1     Running     0          13m
20rook-ceph-osd-0-7ddf7cf545-4zk24                        1/1     Running     0          52s
21rook-ceph-osd-1-6fb7747465-jjdwr                        1/1     Running     0          49s
22rook-ceph-osd-2-767bf9d8cb-pgjn2                        1/1     Running     0          49s
23rook-ceph-osd-prepare-10.10.10.58-sgl2x                 0/1     Completed   0          86s
24rook-ceph-osd-prepare-10.10.10.59-trdgz                 0/1     Completed   0          85s
25rook-ceph-osd-prepare-10.10.10.60-mkr2r                 0/1     Completed   0          85s
26rook-discover-cmt2x                                     1/1     Running     0          11m
27rook-discover-p92sh                                     1/1     Running     0          11m
28rook-discover-q9k5z                                     1/1     Running     0          11m

备注:标识符在您的环境中会有所不同

Ceph可以提供几种存储方式:

  • 文件系统存储
  • 对象存储
  • 块存储

接下来,我们将创建使用块存储所需的资源。


3.3 从Ceph获取块存储

文件cluster/examples/kubernetes/ceph/csi/rbd/storageclass.yaml定义了ReplicaPoolStorageClass来自动创建由Ceph块存储备份的Kubernetes PersistentVolume

首先,我们创建这些资源:

1kubectl apply -f ./csi/rbd/storageclass.yaml
2cephblockpool.ceph.rook.io/replicapool created
3storageclass.storage.k8s.io/rook-ceph-block created

查看刚创建的存储类

1kubectl get sc
2NAME              PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
3rook-ceph-block   rook-ceph.rbd.csi.ceph.com   Delete          Immediate           true                   2m44s

接下来,我们定义PersistentVolumeClaim,一种用于请求存储的资源。由于它使用先前创建的rook-ceph-block StorageClass,它将自动从Ceph集群中调配块存储。

 1---
 2apiVersion: v1
 3kind: PersistentVolumeClaim
 4metadata:
 5  name: mongo-pvc
 6spec:
 7  storageClassName: rook-ceph-block
 8  accessModes:
 9  - ReadWriteOnce
10  resources:
11    requests:
12      storage: 5Gi

接下来,我们使用以下命令创建PersistentVolumeClaim

1kubectl apply -f pvc-rook-ceph-block.yaml

然后,我们验证PersistentVolumeClaim是否触发了PersistentVolume的创建。

1kubectl get pvc,pv
2NAME                              STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS      AGE
3persistentvolumeclaim/mongo-pvc   Bound    pvc-3e6c456a-8a3d-40bb-ab1b-16d8349f789d   5Gi        RWO            rook-ceph-block   9s
4
5NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS      REASON   AGE
6persistentvolume/pvc-3e6c456a-8a3d-40bb-ab1b-16d8349f789d   5Gi        RWO            Delete           Bound    default/mongo-pvc   rook-ceph-block            7s

我们应该得到一个列表,该列表显示PersistentVolumeClaim和自动设置的PersistentVolume之间的绑定。

引擎盖后面的PersistentVolume存储在附加到工作节点的卷上。

在接下来的步骤中,我们将使用此存储来持久存储MongoDB数据库的数据。


3.4 创建MongoDB数据库

现在,我们将部署数据库工作负载,并使用上一步中提供的存储来持久化Pod的数据。

首先,我们定义一个规范,其中包含:

  • 一个运行基于mongo:4.0 Docker映像的1个容器的Deployment。该容器使用上面创建的PersistentVolumeClaim mongo-pvc。关联的PersistentVolume安装在容器文件系统中的*/ data / db*上
  • 类型为NodePort 的服务,将mongo Pod 暴露在集群每个节点的端口31017
 1---
 2apiVersion: apps/v1
 3kind: Deployment
 4metadata:
 5  name: mongo
 6spec:
 7  selector:
 8    matchLabels:
 9      app: mongo
10  template:
11    metadata:
12      labels:
13        app: mongo
14    spec:
15      containers:
16      - image: mongo:4.0
17        name: mongo
18        ports:
19        - containerPort: 27017
20          name: mongo
21        volumeMounts:
22        - name: mongo-persistent-storage
23          mountPath: /data/db
24      volumes:
25      - name: mongo-persistent-storage
26        persistentVolumeClaim:
27          claimName: mongo-pvc
28---
29apiVersion: v1
30kind: Service
31metadata:
32  name: mongo
33  labels:
34    app: mongo
35spec:
36  selector:
37    app: mongo
38  type: NodePort
39  ports:
40    - port: 27017
41      nodePort: 31017

然后,我们创建那些资源。

1kubectl apply -f mongo.yaml
2deployment.apps/mongo created
3service/mongo created

接下来,我们可以验证PodService是否正确创建。

1kubectl get pods,svc
2NAME                        READY   STATUS    RESTARTS   AGE
3pod/mongo-dbcdddc5b-56gfm   1/1     Running   0          60s
4
5NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)           AGE
6service/kubernetes   ClusterIP   10.43.0.1      <none>        443/TCP           26m
7service/mongo        NodePort    10.43.120.20   <none>        27017:31017/TCP   60s

我们有一个数据库Pod将其数据持久存储在基础Ceph存储中。在接下来的步骤中,我们将使用MongoDB客户端并连接并确保一切正常。


3.5 连接数据库

现在,我们将使用MongoDB客户端并连接到上一步中部署的数据库。

这里直接使用mongo命令行工具,你也可以使用其他MongoDB的客户端工具。

1sudo apt -y install mongodb

由于数据库是通过NodePort类型的服务公开的,因此可以从群集的任何节点在特定端口(在本示例中为31017)上访问数据库。

首先,我们获得节点及其外部IP的列表

1kubectl get nodes -o wide
2NAME          STATUS   ROLES               AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
310.10.10.58   Ready    worker              27m   v1.18.6   10.10.10.58   <none>        Ubuntu 18.04.5 LTS   4.15.0-112-generic   docker://19.3.12
410.10.10.59   Ready    worker              27m   v1.18.6   10.10.10.59   <none>        Ubuntu 18.04.5 LTS   4.15.0-112-generic   docker://19.3.12
510.10.10.60   Ready    worker              27m   v1.18.6   10.10.10.60   <none>        Ubuntu 18.04.5 LTS   4.15.0-112-generic   docker://19.3.12
610.10.10.61   Ready    controlplane,etcd   27m   v1.18.6   10.10.10.61   <none>        Ubuntu 18.04.5 LTS   4.15.0-112-generic   docker://19.3.12

接下来,我们选择一个工作节点IP地址,并使用它与客户端连接。

 1mongo --host 10.10.10.58 --port 31017
 2MongoDB shell version v3.6.3
 3connecting to: mongodb://10.10.10.58:31017/
 4MongoDB server version: 4.0.20
 5WARNING: shell and server versions do not match
 6Server has startup warnings:
 72020-08-25T01:41:32.357+0000 I STORAGE  [initandlisten]
 82020-08-25T01:41:32.357+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
 92020-08-25T01:41:32.357+0000 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
102020-08-25T01:41:33.605+0000 I CONTROL  [initandlisten]
112020-08-25T01:41:33.605+0000 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
122020-08-25T01:41:33.605+0000 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
132020-08-25T01:41:33.605+0000 I CONTROL  [initandlisten]
14>

然后,我们可以访问数据库并添加一些数据。这些数据将保留在基础Ceph存储中,并跨块卷复制。

四、总结

在本文中,您使用了Rook Operator部署了在Kubernetes中运行Ceph集群所需的所有过程。现在,您可以使用Ceph提供的存储解决方案(对象存储,块存储,文件系统存储)以安全的方式持久保存工作负载的数据。

如果您想探索Rook并了解所有可用的所有存储后端,可以查看Rook GitHub仓库