Rook 1.12部署指南: 使用Rook 1.12部署和管理Ceph(Reef) 18.2.0
2023-09-02
Rook是一个开源的云原生存储编排器,为Ceph存储提供平台、框架和支持,使其能够与云原生环境进行本地集成。Ceph是一个分布式存储系统,提供文件(file)、块(block)和对象存储(object storage),并在大规模生产集群中部署。
使用Rook可以自动部署和管理Ceph,提供自我管理、自我扩展和自我修复的存储服务。Rook Operator通过Kubernetes Resources来部署(deploy)、配置(configure)、供应(provision)、扩展(scale)、升级(upgrade)和监控(monitor)Ceph。
Rook 1.12开始支持了Ceph(Reef) 18.2.0。
1.准备 #
1.1 K8S集群准备 #
Rook 1.12支持Kubernetes v1.22或更高版本。
本文使用的Kubernetes集群如下:
1kubectl get node
2NAME STATUS ROLES AGE VERSION
3node4 Ready control-plane 18d v1.28.0
4node5 Ready <none> 17d v1.28.0
5node6 Ready <none> 17d v1.28.0
关于容器运行时的配置,这里的Kubernetes集群的容器运行时是Containerd。
当前Containerd官方的systemd配置模板https://raw.githubusercontent.com/containerd/containerd/main/containerd.service中有LimitNOFILE=infinity
的配置,如果是使用这个containerd.service,后边在使用rook启动Ceph集群时,Mon组件会有问题,会出现ms_dispatch
进程的cpu一直是100%,Rook社区有两个ISSUES ISSUE 11253和ISSUE 10110讨论了这个问题,需要将LimitNOFILE
设置一个合适的值,我这里设置的是1048576
。
1.2 设置各个服务器节点的时间同步 #
注意设置各个服务器节点的时间同步,这个十分重要,否则如果各个服务器节点时间不同步时,rook ceph operator在操作时,ceph mon组件的可能会无法正常工作。
关于时间同步推荐使用chronyd。
1.3 本地存储准备(LVM逻辑卷) #
要配置Ceph存储集群,至少需要以下其中一种本地存储:
- 原始设备(Raw devices)(无分区或格式化文件系统)
- 原始分区(Raw partitions)(无格式化文件系统)
- LVM逻辑卷(无格式化文件系统)
- 以块模式(block mode)在存储类(storage class)中提供的持久卷。
本文将使用的本地存储是LVM逻辑卷
。
本文中node4, node5, node6三台主机上都有一个未分区的本地磁盘将用作Ceph集群的本地存储。
1fdisk -l | grep /dev/vdc
2Disk /dev/vdc: 50 GiB, 53687091200 bytes, 104857600 sectors
注意:在执行以下步骤之前,请确保磁盘上没有重要数据,因为这些步骤将擦除磁盘上的所有数据。
首先创建物理卷(Physical Volume),将磁盘/dev/vdc
标记为物理卷。运行以下命令:
1pvcreate /dev/vdc
2 Physical volume "/dev/vdc" successfully created.
查看创建的物理卷:
1pvdisplay
2 "/dev/vdc" is a new physical volume of "50.00 GiB"
3 --- NEW Physical volume ---
4 PV Name /dev/vdc
5 VG Name
6 PV Size 50.00 GiB
7 Allocatable NO
8 PE Size 0
9 Total PE 0
10 Free PE 0
11 Allocated PE 0
12 PV UUID AFIwMS-iAJZ-Od1w-dQ0a-1fdY-gg13-CcNo3a
接下来创建名称为ceph的卷组(Volume Group),并将物理卷/dev/vdc
添加到该卷组中:
1vgcreate ceph /dev/vdc
2 Volume group "ceph" successfully created
查看卷组:
1 vgdisplay
2 --- Volume group ---
3 VG Name ceph
4 System ID
5 Format lvm2
6 Metadata Areas 1
7 Metadata Sequence No 1
8 VG Access read/write
9 VG Status resizable
10 MAX LV 0
11 Cur LV 0
12 Open LV 0
13 Max PV 0
14 Cur PV 1
15 Act PV 1
16 VG Size <50.00 GiB
17 PE Size 4.00 MiB
18 Total PE 12799
19 Alloc PE / Size 0 / 0
20 Free PE / Size 12799 / <50.00 GiB
21 VG UUID lmU0uU-iI0q-zM9B-2wCQ-fWNs-eGF6-65oJLp
最后从卷组ceph创建逻辑卷, 使用lvcreate命令来创建逻辑卷。指定卷组的名称、逻辑卷的名称、大小等参数:
1lvcreate -n osd -l 100%FREE ceph
2 Logical volume "osd" created.
上面的命令使用卷组ceph的所有可用空间创建了名称为osd的逻辑卷,如果想指定逻辑卷的具体大小可以使用下面的命令:
1lvcreate -n osd -L 25G ceph
因为Ceph集群所需要的本地存储是未格式化为文件系统的LVM逻辑卷,所以注意一定不要使用mkfs.ext4
或mkfs.xfs
格式化逻辑卷。
最后查看一下逻辑卷:
1 --- Logical volume ---
2 LV Path /dev/ceph/osd
3 LV Name osd
4 VG Name ceph
5 LV UUID JkPcIu-ULqx-ajsF-iGQz-fe3S-qJ3m-mJOy4F
6 LV Write Access read/write
7 LV Status available
8 # open 0
9 LV Size <50.00 GiB
10 Current LE 12799
11 Segments 1
12 Allocation inherit
13 Read ahead sectors auto
14 - currently set to 256
15 Block device 253:0
2.部署Rook Operator #
本文使用的Kubernetes集群只有node4~node6这3个节点, Ceph集群的各个组件混部在这3个节点上,对于更多节点的生产级别配置,可以对label做更精细化的配置,例如node-role.kubernetes.io/ceph-mon=ceph-mon
等等。
这里将三个节点都打上role=ceph
的label:
1kubectl label nodes node4 role=ceph
2kubectl label nodes node5 role=ceph
3kubectl label nodes node6 role=ceph
我们将通过使用Rook Helm Chart来部署rook ceph operator。
Rook目前将Ceph Operator的构建版本发布到发布(release)和主要(master)通道。发布通道是Rook的最新稳定版。
1helm repo add rook-release https://charts.rook.io/release
2helm install --create-namespace --namespace rook-ceph rook-ceph rook-release/rook-ceph -f values.yaml
或者从https://charts.rook.io/release/rook-ceph-v1.12.3.tgz下载rook-ceph的helm chart,再使用下面的命令安装:
1helm install --create-namespace --namespace rook-ceph rook-ceph rook-ceph-v1.12.3.tgz -f values.yaml
关于values.yaml中配置的内容,可以根据文档https://github.com/rook/rook/blob/master/deploy/charts/rook-ceph-cluster/values.yaml中的内容按需定制。
以下是当前我所定制的内容,主要配置了在部署Rook Operator和Ceph时使用私有的镜像仓库地址,以及调度相关的配置。
1image:
2 pullPolicy: IfNotPresent
3 repository: harbor.frognew.com/library/rook/ceph
4 tag: v1.12.3
5imagePullSecrets:
6 - name: regsecret
7
8tolerations:
9 - key: "dedicated"
10 operator: "Equal"
11 value: "ceph"
12 effect: "NoSchedule"
13
14provisionerNodeAffinity:
15 requiredDuringSchedulingIgnoredDuringExecution:
16 nodeSelectorTerms:
17 - matchExpressions:
18 - key: role
19 operator: In
20 values:
21 - ceph
22provisionerTolerations:
23 - key: "dedicated"
24 operator: "Equal"
25 value: "ceph"
26 effect: "NoSchedule"
27pluginNodeAffinity:
28 requiredDuringSchedulingIgnoredDuringExecution:
29 nodeSelectorTerms:
30 - matchExpressions:
31 - key: role
32 operator: In
33 values:
34 - ceph
35pluginTolerations:
36 - key: "dedicated"
37 operator: "Equal"
38 value: "ceph"
39 effect: "NoSchedule"
40
41discover:
42 tolerations:
43 - key: "dedicated"
44 operator: "Equal"
45 value: "ceph"
46 effect: "NoSchedule"
47 nodeAffinity:
48 nodeSelectorTerms:
49 - matchExpressions:
50 - key: role
51 operator: In
52 values:
53 - ceph
54
55admissionController:
56 tolerations:
57 - key: "dedicated"
58 operator: "Equal"
59 value: "ceph"
60 effect: "NoSchedule"
61 - key: "node-role.kubernetes.io/master"
62 operator: "Exists"
63 effect: "PreferNoSchedule"
64 nodeAffinity:
65 nodeSelectorTerms:
66 - matchExpressions:
67 - key: role
68 operator: In
69 values:
70 - ceph
71
72csi:
73 kubeletDirPath: /var/lib/kubelet
74 cephcsi:
75 # -- Ceph CSI image
76 # @default -- `quay.io/cephcsi/cephcsi:v3.9.0``
77 image: harbor.frognew.com/gcr/quay.io/cephcsi/cephcsi:v3.9.0
78 registrar:
79 # -- Kubernetes CSI registrar image
80 # @default -- `registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0`
81 image: harbor.frognew.com/gcr/registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0
82 provisioner:
83 # -- Kubernetes CSI provisioner image
84 # @default -- `registry.k8s.io/sig-storage/csi-provisioner:v3.5.0`
85 image: harbor.frognew.com/gcr/registry.k8s.io/sig-storage/csi-provisioner:v3.5.0
86 snapshotter:
87 # -- Kubernetes CSI snapshotter image
88 # @default -- `registry.k8s.io/sig-storage/csi-snapshotter:v6.2.2`
89 image: harbor.frognew.com/gcr/registry.k8s.io/sig-storage/csi-snapshotter:v6.2.2
90 attacher:
91 # -- Kubernetes CSI Attacher image
92 # @default -- `registry.k8s.io/sig-storage/csi-attacher:v4.3.0`
93 image: harbor.frognew.com/gcr/registry.k8s.io/sig-storage/csi-attacher:v4.3.0
94 resizer:
95 # -- Kubernetes CSI resizer image
96 # @default -- `registry.k8s.io/sig-storage/csi-resizer:v1.8.0`
97 image: harbor.frognew.com/gcr/registry.k8s.io/sig-storage/csi-resizer:v1.8.0
https://github.com/rook/rook/blob/master/deploy/examples/images.txt这个地址里面有部署Rook Operator和Ceph所需的所有容器镜像,可以根据需要预先同步到我们的私有镜像仓库中。
本文中用到的镜像如下:
1rook/ceph:1.12.3
2quay.io/ceph/ceph:v18.2.0
3quay.io/cephcsi/cephcsi:v3.9.0
4quay.io/csiaddons/k8s-sidecar:v0.7.0
5registry.k8s.io/sig-storage/csi-attacher:v4.3.0
6registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.8.0
7registry.k8s.io/sig-storage/csi-provisioner:v3.5.0
8registry.k8s.io/sig-storage/csi-resizer:v1.8.0
9registry.k8s.io/sig-storage/csi-snapshotter:v6.2.2
部署完成后,确认rook-ceph-operator的正常启动:
1kubectl get pods -n rook-ceph -l "app=rook-ceph-operator"
2NAME READY STATUS RESTARTS AGE
3rook-ceph-operator-6b8f46d4b7-vck2b 1/1 Running 0 2m54s
3.创建Ceph集群 #
3.1 参考文档 #
Rook文档侧重于在各种环境中启动Rook。在创建Ceph集群时,可以考虑在以下的示例集群清单基础上做定制:
- cluster.yaml:用于在裸机上运行的生产集群的集群设置。需要至少三个工作节点。
- cluster-on-pvc.yaml:用于在动态云环境中运行的生产集群的集群设置。
- cluster-test.yaml:用于测试环境(如 minikube)的集群设置。
有关更多详细信息,可参考Ceph的示例配置。
Rook Ceph Operator已经部署完成并正常运行,我们可以创建Ceph集群了,这里选择的是cluster.yaml
。
3.2 创建集群 #
基于cluster.yaml定制我们自己的cluster.yaml,以下是只包含cluster.yaml的修改内容:
1...
2apiVersion: ceph.rook.io/v1
3kind: CephCluster
4metadata:
5 name: rook-ceph
6 namespace: rook-ceph
7spec:
8 cephVersion:
9 image: registry.frognew.com/gcr/quay.io/ceph/ceph:v18.2.0
10...
11 dashboard:
12 enabled: true
13 ssl: false
14...
15 storage:
16 useAllNodes: true
17 useAllDevices: true
18 devices:
19 - name: /dev/disk/by-id/dm-name-ceph-osd
20 config:
21 osdsPerDevice: "1"
22...
23 placement:
24 all:
25 nodeAffinity:
26 requiredDuringSchedulingIgnoredDuringExecution:
27 nodeSelectorTerms:
28 - matchExpressions:
29 - key: role
30 operator: In
31 values:
32 - ceph
33 podAffinity:
34 podAntiAffinity:
35 topologySpreadConstraints:
36 tolerations:
37 - key: "dedicated"
38 operator: "Equal"
39 value: "ceph"
40 effect: "NoSchedule"
41 - key: "node-role.kubernetes.io/master"
42 operator: "Exists"
43 effect: "PreferNoSchedule"
44...
因为Ceph集群的本地存储将使用前面创建的未格式化文件系统的LVM逻辑卷,我们创建的逻辑卷的名称为osd
,所属的卷组为ceph
,逻辑卷的路径为/dev/ceph/osd
。
Rook是从1.9开始支持使用LVM逻辑卷作为本地存储的,具体实现的代码是这个PR https://github.com/rook/rook/pull/7967。
文档CephCluster CRD中对如何使用逻辑卷作存储的说明不是特别详细。从PR的实现代码上看,当前是要在CephCluster的资源定义中的spec.storage.devices[].name
配置为/dev/disk/by-id/dm-name-<vgName>-<lvName>
。
所以我们的cluster.yaml配置的spec.storage
部分, devices[].name
的值是/dev/disk/by-id/dm-name-ceph-osd
。
创建Ceph集群:
1kubectl create -f cluster.yaml
2cephcluster.ceph.rook.io/rook-ceph created
通过查看rook-ceph
命名空间中的pod,验证集群是否正在运行。
1kubectl get po -n rook-ceph
2NAME READY STATUS RESTARTS AGE
3csi-cephfsplugin-6zbv4 2/2 Running 0 11m
4csi-cephfsplugin-b4blf 2/2 Running 0 11m
5csi-cephfsplugin-provisioner-54fd9db947-dn2nk 5/5 Running 0 11m
6csi-cephfsplugin-provisioner-54fd9db947-vxgv2 5/5 Running 0 11m
7csi-cephfsplugin-qcrt2 2/2 Running 0 11m
8csi-rbdplugin-dr99t 2/2 Running 0 11m
9csi-rbdplugin-ltlx4 2/2 Running 0 11m
10csi-rbdplugin-provisioner-6554f5797f-7lfkx 5/5 Running 0 11m
11csi-rbdplugin-provisioner-6554f5797f-898wn 5/5 Running 0 11m
12csi-rbdplugin-txfc9 2/2 Running 0 11m
13rook-ceph-crashcollector-node4-7ff7fff88c-qj5sz 1/1 Running 0 8m36s
14rook-ceph-crashcollector-node5-54cd6f7c8-5wvgb 1/1 Running 0 8m45s
15rook-ceph-crashcollector-node6-d6c6b7857-g6ltw 1/1 Running 0 9m33s
16rook-ceph-exporter-node4-7b56cc8477-z2h86 1/1 Running 0 8m36s
17rook-ceph-exporter-node5-7b79f46596-dh4qv 1/1 Running 0 8m45s
18rook-ceph-exporter-node6-f5fffb887-gtl46 1/1 Running 0 9m32s
19rook-ceph-mgr-a-6887574845-zwccw 3/3 Running 0 9m38s
20rook-ceph-mgr-b-7496547764-ln4nr 3/3 Running 0 9m37s
21rook-ceph-mon-a-65f6f6b579-256tv 2/2 Running 0 10m
22rook-ceph-mon-b-5455b5887-p27kj 2/2 Running 0 10m
23rook-ceph-mon-c-57b6d799d9-php65 2/2 Running 0 10m
24rook-ceph-operator-6b8f46d4b7-lg6dj 1/1 Running 0 13m
25rook-ceph-osd-0-7dc8d5f4dd-rn8lw 2/2 Running 0 8m47s
26rook-ceph-osd-1-7968944c57-bddwf 2/2 Running 0 8m36s
27rook-ceph-osd-2-5f6966f4bf-x7g96 2/2 Running 0 8m39s
28rook-ceph-osd-prepare-node4-m59zp 0/1 Completed 0 9m12s
29rook-ceph-osd-prepare-node5-pzswn 0/1 Completed 0 9m12s
30rook-ceph-osd-prepare-node6-7lvj8 0/1 Completed 0 9m11s
osd pod的数量取决于集群中的节点数量和配置的设备数量。对于上述默认的cluster.yaml,将为每个节点上找到的每个可用设备创建一个OSD。
创建过程如果遇到问题可以查看rook-ceph-operator
的Pod的日志。
如需重新运行rook-ceph-osd-prepare-<nodename>
Job,扫描可用本地存储添加OSD,可以执行以下命令:
1# 删除旧的job
2kubectl get job -n rook-ceph | awk '{system("kubectl delete job "$1" -n rook-ceph")}'
3# 重启operator
4kubectl rollout restart deploy rook-ceph-operator -n rook-ceph
每个节点上的osd能否添加成功,要注意查看rook-ceph-osd-prepare-<nodename>
Job对应Pod的日志。
4.验证集群状态 #
为了验证集群处于健康状态, 需要Rook工具箱。
1kubectl apply -f https://raw.githubusercontent.com/rook/rook/release-1.12/deploy/examples/toolbox.yaml
2
3kubectl get po -n rook-ceph | grep rook-ceph-tools
4rook-ceph-tools-68b98695bb-gh76t 1/1 Running 0 23s
注: 当前release-1.12/deploy/examples/toolbox.yaml中的Ceph镜像还是v17.2.6,可以手动修改成v18.2.0
连接到工具箱,并运行ceph status
命令:
1kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
以下是健康状态的验证要点:
- 所有的 monitor (mon) 节点应该处于 quorum(一致性)状态。
- 一个管理器 (mgr) 节点应该处于活动状态。
- 至少有三个 OSD 节点应该处于上线并可用状态。
如果健康状态不是 HEALTH_OK
,则应该调查警告或错误的原因。
1ceph status
2 cluster:
3 id: b4268a7c-6209-474f-937c-568d75d59b49
4 health: HEALTH_OK
5
6 services:
7 mon: 3 daemons, quorum a,b,c (age 29m)
8 mgr: b(active, since 27m), standbys: a
9 osd: 3 osds: 3 up (since 26m), 3 in (since 28m)
10
11 data:
12 pools: 1 pools, 1 pgs
13 objects: 2 objects, 449 KiB
14 usage: 81 MiB used, 150 GiB / 150 GiB avail
15 pgs: 1 active+clean
从输出可以看出集群状态一切正常,集群中部署了3个mon, 2个mgr, 3个osd。
查看一下当前集群中的存储池:
1ceph osd lspools
21 .mgr
可以看到当前集群中只有一个名称为.mgr
的存储池。这表示在这个Ceph集群中只创建了默认的管理池(mgr pool),这是一个特殊的池,用于存储管理和监控相关的数据。
4.使用存储 #
Ceph提供三种类型的存储接口: 块存储(Block)、共享文件系统(Shared Filesystem)、对象存储(Object)。
下面演示对于使用Rook部署和管理的Ceph集群,如何使用这三种存储。
通过Rook使用Ceph提供的三种存储类型以及它们的用途如下:
- 块存储(Block)适用于为单个 Pod 提供读写一致性(RWO)的存储
- CephFS 共享文件系统(Shared Filesystem)适用于多个Pod之间共享读写(RWX)的存储
- 对象存储(Object)提供了一个可通过内部或外部的Kubernetes集群的S3端点访问的存储
使用存储的详细内容这里略过,具体可查看之前编写的Rook 1.11部署指南中的"使用存储"。
5.Ceph Dashboard #
通过使用Ceph Dashboard可以查看集群的状态。使用Rook部署的Ceph集群已经默认启用了Ceph Dashboard。
rook-ceph-mgr-dashboard
是其在Kubernetes集群中的Service:
1kubectl get svc rook-ceph-mgr-dashboard -n rook-ceph
2NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
3rook-ceph-mgr-dashboard ClusterIP 10.98.187.210 <none> 7000/TCP 42m
可通过Ingress或创建一个NodePort的Service dashboard-external-http将其暴露的Kubernetes集群外部。
Ceph Dashboard admin用户的命名可以通过下面的命令查看:
1kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo