一.Rook简介
什么是Rook?
Rook 是一个开源的云原生存储编排器,为各种存储解决方案提供平台、框架和支持,以便与云原生环境进行原生集成。
Rook 将分布式存储系统转变为自管理、自扩展、自修复的存储服务。它使存储管理员的部署、引导、配置、配置、扩展、升级、迁移、灾难恢复、监控和资源管理等任务自动化。简而言之,Rook 就是一组 Kubernetes 的 Operator,它可以完全控制多种数据存储解决方案(例如 Ceph、EdgeFS、Minio、Cassandra)的部署,管理以及自动恢复。rook利用Kubernetes平台的强大功能,通过Kubernetes Operator为每个存储提供商提供服务。Rook目前支持Ceph、NFS、Minio Object Store和CockroachDB。
到目前为止,Rook 支持的最稳定的存储仍然是 Ceph,主要介绍如何使用 Rook 来创建维护 Ceph 集群,并作为 Kubernetes 的持久化存储。Rook 在 2018 年发布的 0.9 版本中,正式将 Ceph Operator 作为稳定支持的特性,迄今已经数年。使用 Rook 部署和管理生产级别的 Ceph 集群还是非常稳健的。
二.Rook与Ceph架构
2.1 Rook结构体系
Rook 的本意是为了降低部署管理 Ceph 集群的难度,Ceph 是一个高度可扩展的分布式存储解决方案,用于块存储、对象存储和共享文件系统。rook部署以及管理都在k8s中运行管理,rook用于编排ceph集群部署工具主要使用operator管理操作。而Rook存储运行则完全自动化。rook存储是通过第三方资源以kubernetes扩展形式运行。
Rook operator 是一个简单的容器,它拥有引导和监控存储集群所需的一切。操作员将启动和监控Ceph 监控 pod、提供 RADOS 存储的 Ceph OSD 守护进程,以及启动和管理其他 Ceph 守护进程。操作员通过初始化运行服务所需的 Pod 和其他资源来管理池、对象存储 (S3/Swift) 和文件系统的 CRD。
2.2 Rook包含组件
- Rook Operator
Rook Operater是rook的大脑,以deployment形式存在
- 其利用k8s的controller-runtime框架实现了CRD,并进而接受k8s创建资源的请求并创建相关资源(集群,pool,块存储服务,文件存储服务等)。
- Rook Operate监控存储守护进程,来确保存储集群的健康。
- 监听Rook Discovers收集到的存储磁盘设备,并创建相应服务(ceph的话就是osd了)。
注:可以通过修改operate.yaml中的replicas的副本数来保证Operate的高可用(默认为1)。
Rook Discover
Rook Discover是以daemonset形式部署在所有的存储机上的,其检测挂接到存储节点上的存储设备。把符合要求的存储设备记录下来,这样Rook Operate感知到以后就可以基于该存储设备创建相应服务了。Rook Agent
Rook Agent是以daemonset形式部署在所有的存储机上的,其处理所有的存储操作,例如挂卸载存储卷以及格式化文件系统等。
2.3 Rook与kubernetes结合的架构图如下
Rook负责初始化和管理ceph集群
monitor集群
mgr集群
osd集群
pool管理
对象存储
文件存储
Rook负责提供访问存储所需的驱动
csi驱动
flex驱动(旧驱动,不建议使用)
rbd块存储
cephfs文件存储
S3/swift风格对象存储
2.4 ceph特点
高性能
抛弃了传统的集中式存储运输局寻址的方案,采用 CRUSH 算法,数据分布均衡,并行度高;
考虑了容灾域的隔离,能够实现各类负载的副本设置规则,例如跨机房、机架感知等;
能够支持上千个存储节点的规模,支持 TB 到 PB 级的数据;
高可用性
副本数可以灵活控制;
支持故障域分离,数据强一致性;
多种故障场景自动进行修复自愈;
没有单点故障,自动管理;
高可扩展性
去中心化;
扩展灵活;
随着节点增加而线性增长;
特性丰富
支持三种存储接口:块存储、文件存储、对象存储;
支持自定义接口,支持多种语言驱动;
2.5 ceph架构
支持三种接口
- Object:有原生 API,而且也兼容 Swift 和 S3 的 API;
- Block:支持精简配置、快照、克隆;
- File:Posix 接口,支持快照
2.6 ceph组件
Monitor:一个 Ceph 集群需要多个 Monitor 组成的小集群,它们通过 Paxos 同步数据,用来保存 OSD 的元数据。
OSD:全称 Object Storage Device,也就是负责响应客户端请求返回具体数据的进程,一个 Ceph 集群一般都有很多个 OSD。主要功能用于数据的存储,当直接使用硬盘作为存储目标时,一块硬盘称之为 OSD,当使用一个目录作为存储目标的时候,这个目录也被称为 OSD。
MDS:全称 Ceph Metadata Server,是 CephFS 服务依赖的元数据服务,对象存储和块设备存储不需要该服务。
Object:Ceph 最底层的存储单元是 Object 对象,一条数据、一个配置都是一个对象,每个 Object 包含 ID、元数据和原始数据。
Pool:Pool 是一个存储对象的逻辑分区,它通常规定了数据冗余的类型与副本数,默认为3副本。对于不同类型的存储,需要单独的 Pool,如 RBD。
PG:全称 Placement Grouops,是一个逻辑概念,一个 OSD 包含多个 PG。引入 PG 这一层其实是为了更好的分配数据和定位数据。每个 Pool 内包含很多个 PG,它是一个对象的集合,服务端数据均衡和恢复的最小单位就是 PG。
FileStore与BlueStore:FileStore 是老版本默认使用的后端存储引擎,如果使用 FileStore,建议使用 xfs 文件系统。BlueStore 是一个新的后端存储引擎,可以直接管理裸硬盘,抛弃了 ext4 与 xfs 等本地文件系统。可以直接对物理硬盘进行操作,同时效率也高出很多。
RADOS:全称 Reliable Autonomic Distributed Object Store,是 Ceph 集群的精华,用于实现数据分配、Failover 等集群操作。
Librados:Librados 是 Rados 提供库,因为 RADOS 是协议很难直接访问,因此上层的 RBD、RGW 和 CephFS 都是通过 librados 访问的,目前提供 PHP、Ruby、Java、Python、C 和 C++ 支持。
CRUSH:CRUSH 是 Ceph 使用的数据分布算法,类似一致性哈希,让数据分配到预期的地方。 RBD:全称 RADOS Block Device,是 Ceph 对外提供的块设备服务,如虚拟机硬盘,支持快照功能。
RGW:全称是 RADOS Gateway,是 Ceph 对外提供的对象存储服务,接口与 S3 和 Swift 兼容。
CephFS:全称 Ceph File System,是 Ceph 对外提供的文件系统服务。
注:ceph相关组件概念及原理架构请阅读官方文档https://docs.ceph.com/
三.Rook部署Ceph集群
3.1 部署条件
- 已经部署好的kubernetes集群1.19版本或者更高
- osd节点需要有未格式化文件系统磁盘,至少需要3块硬盘
3.2 获取rook最新版本
[root@node1 opt]# git clone https://github.com/rook/rook.git
正克隆到 'rook'...
remote: Enumerating objects: 107711, done.
remote: Counting objects: 100% (107711/107711), done.
remote: Compressing objects: 100% (31142/31142), done.
remote: Total 107711 (delta 74734), reused 107391 (delta 74569), pack-reused 0
接收对象中: 100% (107711/107711), 52.11 MiB | 4.26 MiB/s, done.
处理 delta 中: 100% (74734/74734), done.
[root@node1 opt]#
注:rook版本1.10
3.3 rook资源文件目录结构
[root@node1 examples]# pwd
/opt/rook/deploy/examples
[root@node1 examples]# tree
.
├── bucket-notification-endpoint.yaml
├── bucket-notification.yaml
├── bucket-topic.yaml
├── ceph-client.yaml
├── cluster-external-management.yaml
├── cluster-external.yaml
├── cluster-multus-test.yaml
├── cluster-on-local-pvc.yaml
├── cluster-on-pvc.yaml
├── cluster-stretched-aws.yaml
├── cluster-stretched.yaml
├── cluster-test.yaml
├── cluster.yaml
├── common-external.yaml
├── common-second-cluster.yaml
├── common.yaml
├── crds.yaml
├── create-external-cluster-resources.py
├── create-external-cluster-resources-tests.py
├── csi
│ ├── cephfs
│ │ ├── kube-registry.yaml
│ │ ├── pod-ephemeral.yaml
│ │ ├── pod.yaml
│ │ ├── pvc-clone.yaml
│ │ ├── pvc-restore.yaml
│ │ ├── pvc.yaml
│ │ ├── snapshotclass.yaml
│ │ ├── snapshot.yaml
│ │ ├── storageclass-ec.yaml
│ │ └── storageclass.yaml
│ ├── nfs
│ │ ├── pod.yaml
│ │ ├── pvc-clone.yaml
│ │ ├── pvc-restore.yaml
│ │ ├── pvc.yaml
│ │ ├── rbac.yaml
│ │ ├── snapshotclass.yaml
│ │ ├── snapshot.yaml
│ │ └── storageclass.yaml
│ └── rbd
│ ├── pod-ephemeral.yaml
│ ├── pod.yaml
│ ├── pvc-clone.yaml
│ ├── pvc-restore.yaml
│ ├── pvc.yaml
│ ├── snapshotclass.yaml
│ ├── snapshot.yaml
│ ├── storageclass-ec.yaml
│ ├── storageclass-test.yaml
│ └── storageclass.yaml
├── csi-ceph-conf-override.yaml
├── dashboard-external-https.yaml
├── dashboard-external-http.yaml
├── dashboard-ingress-https.yaml
├── dashboard-loadbalancer.yaml
├── direct-mount.yaml
├── filesystem-ec.yaml
├── filesystem-mirror.yaml
├── filesystem-test.yaml
├── filesystem.yaml
├── images.txt
├── import-external-cluster.sh
├── monitoring
│ ├── csi-metrics-service-monitor.yaml
│ ├── externalrules.yaml
│ ├── keda-rgw.yaml
│ ├── localrules.yaml
│ ├── prometheus-service.yaml
│ ├── prometheus.yaml
│ ├── rbac.yaml
│ └── service-monitor.yaml
├── mysql.yaml
├── nfs-load-balancer.yaml
├── nfs-test.yaml
├── nfs.yaml
├── object-bucket-claim-delete.yaml
├── object-bucket-claim-notification.yaml
├── object-bucket-claim-retain.yaml
├── object-ec.yaml
├── object-external.yaml
├── object-multisite-pull-realm-test.yaml
├── object-multisite-pull-realm.yaml
├── object-multisite-test.yaml
├── object-multisite.yaml
├── object-openshift.yaml
├── object-test.yaml
├── object-user.yaml
├── object.yaml
├── operator-openshift.yaml
├── operator.yaml
├── osd-env-override.yaml
├── osd-purge.yaml
├── pool-builtin-mgr.yaml
├── pool-ec.yaml
├── pool-mirrored.yaml
├── pool-test.yaml
├── pool.yaml
├── psp.yaml
├── radosnamespace.yaml
├── rbdmirror.yaml
├── README.md
├── rgw-external.yaml
├── sqlitevfs-client.yaml
├── storageclass-bucket-delete.yaml
├── storageclass-bucket-retain.yaml
├── subvolumegroup.yaml
├── toolbox-job.yaml
├── toolbox.yaml
├── volume-replication-class.yaml
├── volume-replication.yaml
└── wordpress.yaml
5 directories, 107 files
[root@node1 examples]#
3.4 部署Rook/CRD/Ceph集群
[root@node1 examples]#
kubectl create -f crds.yaml -f common.yaml -f operator.yaml
[root@node1 examples]#
kubectl create -f cluster.yaml
crds和common资源文件用于创建RBAC相关secrets权限、rook的crd组件,主要用于管理控制ceph集群
operator资源文件可以修改Rook CSI 镜像地址,默认无法拉取镜像地址。可以通过制作内部镜像仓库,便于快速拉取CSI所需镜像。
Cluster.yaml资源文件,可以设置是否使用所有节点和所有节点上硬盘,生产环境应禁止使用发现功能,应通过标签或或者指定节点。
useAllNodes:用于表示是否使用集群中的所有节点进行存储,如果在 nodes 字段下指定了各个节点,则必须将useAllNodes设置为 false;
useAllDevices:表示 OSD 是否自动使用节点上的所有设备,一般设置为 false,这样可控性较高
osd存储节点指定主机名和硬盘方式示例
3.5 查看rook部署后pod状态
[root@node1 examples]# kubectl get pod -n rook-ceph
NAME READY STATUS RESTARTS AGE
csi-cephfsplugin-2bp2r 2/2 Running 0 23d
csi-cephfsplugin-6rf49 2/2 Running 0 23d
csi-cephfsplugin-dsjvj 2/2 Running 0 23d
csi-cephfsplugin-provisioner-776969d5f6-9px8h 5/5 Running 0 21d
csi-cephfsplugin-provisioner-776969d5f6-f9k9d 5/5 Running 0 21d
csi-rbdplugin-99759 2/2 Running 0 23d
csi-rbdplugin-hlspw 2/2 Running 0 23d
csi-rbdplugin-nsgcf 2/2 Running 0 23d
csi-rbdplugin-provisioner-755bcb589-8qgdk 5/5 Running 0 21d
csi-rbdplugin-provisioner-755bcb589-pf6jb 5/5 Running 0 21d
prometheus-rook-prometheus-0 3/3 Running 1 (8d ago) 8d
rook-ceph-crashcollector-10.255.82.25-7db9f5db45-vfx5z 1/1 Running 0 20d
rook-ceph-crashcollector-10.255.82.26-84d7d574b4-dz88c 1/1 Running 0 23d
rook-ceph-crashcollector-10.255.82.27-5bc77c979-j9drq 1/1 Running 0 20d
rook-ceph-mds-myfs-a-74566d999-rrpx7 1/1 Running 0 20d
rook-ceph-mds-myfs-b-6b4697cbf9-74wch 1/1 Running 0 20d
rook-ceph-mgr-a-7944fddb75-p4b9b 2/2 Running 0 8d
rook-ceph-mgr-b-7c9c8b8b6c-rkvgn 2/2 Running 0 8d
rook-ceph-mon-b-866cff855b-vbbcp 1/1 Running 0 23d
rook-ceph-mon-c-9fd694895-dzstp 1/1 Running 0 23d
rook-ceph-mon-d-77bd9f8dd6-cwf42 1/1 Running 0 17d
rook-ceph-operator-785cc8f794-z5zbc 1/1 Running 0 23d
rook-ceph-osd-0-8f499f9d-ntk7q 1/1 Running 0 23d
rook-ceph-osd-1-55f7dfcc4c-n9h45 1/1 Running 0 23d
rook-ceph-osd-2-574dcf8848-sxrtl 1/1 Running 0 23d
rook-ceph-osd-prepare-10.255.82.25-cdfch 0/1 Completed 0 3h25m
rook-ceph-osd-prepare-10.255.82.26-gzktz 0/1 Completed 0 3h25m
rook-ceph-osd-prepare-10.255.82.27-bpg6v 0/1 Completed 0 3h25m
rook-ceph-rgw-my-store-a-7fb9d556dd-59kkw 1/1 Running 0 20d
rook-ceph-rgw-my-store-a-7fb9d556dd-6ks48 1/1 Running 0 20d
[root@node1 examples]#
3.6 部署toolbox客户端
[root@node1 examples]# kubectl apply -f toolbox.yaml
[root@node1 ~]# kubectl get pod -n rook-ceph | grep tool
rook-ceph-tools-7c8ddb978b-2dzrx 1/1 Running 0 23d
[root@node1 ~]#
注:toolbox客户端用于操作ceph集群工具
3.7 使用toolbox客户端查看ceph集群状态
[root@node1 examples]# kubectl exec -it rook-ceph-tools-7c8ddb978b-2dzrx -n rook-ceph -- bash
bash-4.4$ ceph -s
cluster:
id: 592a3aca-f4c8-4a58-8023-7b1023555b0b
health: HEALTH_OK
services:
mon: 3 daemons, quorum b,c,d (age 2w)
mgr: a(active, since 8d), standbys: b
mds: 1/1 daemons up, 1 hot standby
osd: 3 osds: 3 up (since 3w), 3 in (since 3w)
rgw: 2 daemons active (2 hosts, 1 zones)
data:
volumes: 1/1 healthy
pools: 13 pools, 232 pgs
objects: 1.25k objects, 2.6 GiB
usage: 11 GiB used, 139 GiB / 150 GiB avail
pgs: 232 active+clean
io:
client: 852 B/s rd, 12 KiB/s wr, 1 op/s rd, 1 op/s wr
bash-4.4$
四.Rook部署云原生RBD块存储
前面通过rook部署ceph集群运行在kubernetes上,ceph集群支持rbd块存储。使用rook部署rbd块服务与kubernetes容器对接。ceph与kubernetes对接会涉及到pool池、ceph认证信息,配置文件,CSI驱动部署等。storageclass创建过程涉及配置较多,而Rook则将这些配置过程简化,以云原生的方式实现对接,默认已继承好相关驱动。通过kubernetes创建storageclass即可对接使用。
Storageclass:管理员可以将存储资源定义某种级别,正如存储设置对于自身的配置描述。用户根据storageclass的描述就能够直观得各种存储资源的特性,根据应用对存储资源的需求去申请存储资源了。
4.1部署storageclass资源
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool
namespace: rook-ceph
spec:
failureDomain: host
replicated:
size: 3
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block
# Change "rook-ceph" provisioner prefix to match the operator namespace if needed
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
# clusterID is the namespace where the rook cluster is running
clusterID: rook-ceph
# Ceph pool into which the RBD image shall be created
pool: replicapool
# (optional) mapOptions is a comma-separated list of map options.
# For krbd options refer
# https://docs.ceph.com/docs/master/man/8/rbd/#kernel-rbd-krbd-options
# For nbd options refer
# https://docs.ceph.com/docs/master/man/8/rbd-nbd/#options
# mapOptions: lock_on_read,queue_depth=1024
# (optional) unmapOptions is a comma-separated list of unmap options.
# For krbd options refer
# https://docs.ceph.com/docs/master/man/8/rbd/#kernel-rbd-krbd-options
# For nbd options refer
# https://docs.ceph.com/docs/master/man/8/rbd-nbd/#options
# unmapOptions: force
# RBD image format. Defaults to "2".
imageFormat: "2"
# RBD image features. Available for imageFormat: "2". CSI RBD currently supports only `layering` feature.
imageFeatures: layering
# The secrets contain Ceph admin credentials.
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
# Specify the filesystem type of the volume. If not specified, csi-provisioner
# will set default as `ext4`. Note that `xfs` is not recommended due to potential deadlock
# in hyperconverged settings where the volume is mounted on the same node as the osds.
csi.storage.k8s.io/fstype: ext4
# Delete the rbd volume when a PVC is deleted
reclaimPolicy: Delete
# Optional, if you want to add dynamic resize for PVC.
# For now only ext3, ext4, xfs resize support provided, like in Kubernetes itself.
allowVolumeExpansion: true
[root@node1 rbd]# kubectl create -f deploy/examples/csi/rbd/storageclass.yaml
查看storageclass资源
[root@node1 rbd]# kubectl get storageclasses.storage.k8s.io | grep rook-ceph-block
rook-ceph-block rook-ceph.rbd.csi.ceph.com Delete Immediate true 22d
[root@node1 rbd]#
4.2部署WordPress使用RBD
部署mysql和WordPress资源文件
# kubectl create -f mysql.yaml
# kubectl create -f wordpress.yaml
注:资源文件在deploy/examples文件夹下
查看mysql和WordPress pod状态
[root@node1 examples]# kubectl get pod | grep wordpress
wordpress-b98c66fff-nkctg 1/1 Running 0 21d
wordpress-mysql-79966d6c5b-4svxd 1/1 Running 0 21d
[root@node1 examples]#
4.3 WordPress访问
Wordpress svc更改为NodePort形式对外暴露服务访问
[root@node1 examples]# kubectl get svc | grep wordpress
wordpress NodePort 10.68.18.125 <none> 80:31372/TCP 21d
wordpress-mysql ClusterIP None <none> 3306/TCP 21d
[root@node1 examples]#
WordPress访问地址 http://node_ip:31372
注:第一次访问需要进行完善信息,完善后跟进自己使用情况进行后台修改或者默认直接使用即可
4.4查看mysql和WordPress使用PVC
[root@node1 examples]# kubectl get pvc | grep pv-claim
mysql-pv-claim Bound pvc-449482a9-3d01-4697-ba82-49fe44e911cc 4Gi RWO rook-ceph-block 21d
wp-pv-claim Bound pvc-a8d5053e-0d13-44a6-8ea4-1d9ac3221d34 2Gi RWO rook-ceph-block 21d
[root@node1 examples]#
这里以WordPress使用PVC示例,可以看到是存储类资源名称是rook-ceph-block。
[root@node1 examples]# kubectl describe pvc wp-pv-claim
Name: wp-pv-claim
Namespace: default
StorageClass: rook-ceph-block
Status: Bound
Volume: pvc-a8d5053e-0d13-44a6-8ea4-1d9ac3221d34
Labels: app=wordpress
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
volume.kubernetes.io/storage-provisioner: rook-ceph.rbd.csi.ceph.com
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 2Gi
Access Modes: RWO
VolumeMode: Filesystem
Used By: wordpress-b98c66fff-nkctg
Events: <none>
[root@node1 examples]#
五.Rook部署云原生RGW对象存储
rook能够在kubernetes中部署对象存储提供rgw服务。
5.1 部署objectstore资源
创建object资源文件
# kubectl create -f object.yaml
查看rgw pod状况
# kubectl -n rook-ceph get pod -l app=rook-ceph-rgw
查看rgw svc状况
[root@node1 examples]# kubectl -n rook-ceph get svc -l app=rook-ceph-rgw
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
rook-ceph-rgw-my-store ClusterIP 10.68.116.53 <none> 80/TCP 19d
5.2 pod访问rgw服务
root@csicephfs-demo-pod:/# curl 10.68.116.53
<?xml version="1.0" encoding="UTF-8"?><ListAllMyBucketsResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/"><Owner><ID>anonymous</ID><DisplayName></DisplayName></Owner><Buckets></Buckets></ListAllMyBucketsResult>root@csicephfs-demo-pod:/#
root@csicephfs-demo-pod:/#
5.3 创建rgw用户
[root@node1 examples]# cat object-user.yaml
#################################################################################################################
# Create an object store user for access to the s3 endpoint.
# kubectl create -f object-user.yaml
#################################################################################################################
apiVersion: ceph.rook.io/v1
kind: CephObjectStoreUser
metadata:
name: my-user
namespace: rook-ceph # namespace:cluster
spec:
store: my-store
displayName: "my display name"
# Quotas set on the user
# quotas:
# maxBuckets: 100
# maxSize: 10G
# maxObjects: 10000
# Additional permissions given to the user
# capabilities:
# user: "*"
# bucket: "*"
# metadata: "*"
# usage: "*"
# zone: "*"
[root@node1 examples]# kubectl create -f object-user.yaml
5.4 创建buckets桶
注:使用dashboard web界面管理操作查看即可,rgw对象存储操作使用参考文档:https://docs.ceph.com/en/quincy/radosgw/index.html