使用Rook搭建Ceph集群

Rook

Posted by BlueFat on Tuesday, November 17, 2020

在容器世界中,无状态是一个核心原则,然而我们始终需要保存数据,并提供给他人进行访问。所以就需要一个方案用于保持数据,以备重启之需。

在 Kubernetes 中,PVC 是管理有状态应用的一个推荐方案。有了 PVC 的帮助,Pod 可以申请并连接到存储卷,这些存储卷在 Pod 生命周期结束之后,还能独立存在。

PVC 在存储方面让开发和运维的职责得以分离。运维人员负责供应存储,而开发人员则可以在不知后端细节的情况下,申请使用这些存储卷。

PVC 由一系列组件构成:

PVC:是 Pod 对存储的请求。PVC 会被 Pod 动态加载成为一个存储卷。

PV,可以由运维手工分配,也可以使用 StorageClass 动态分配。PV 受 Kubernetes 管理,但并不与特定的 Pod 直接绑定。

StorageClass:由管理员创建,可以用来动态的创建存储卷和 PV。

物理存储:实际连接和加载的存储卷。

分布式存储系统是一个有效的解决有状态工作负载高可用问题的方案。Ceph 就是一个分布式存储系统,近年来其影响主键扩大。Rook 是一个编排器,能够支持包括 Ceph 在内的多种存储方案。Rook 简化了 Ceph 在 Kubernetes 集群中的部署过程。

在生产环境中使用 Rook + Ceph 组合的用户正在日益增加,尤其是自建数据中心的用户,CENGN、Gini、GPR 等很多组织都在进行评估。

Ceph介绍

Ceph 是一个分布式存储系统,具备大规模、高性能、无单点失败的特点。Ceph 是一个软件定义的系统,也就是说他可以运行在任何符合其要求的硬件之上。

Ceph支持三种存储:

  • 块存储(RDB):可以直接作为磁盘挂载
  • 文件系统(CephFS):提供POSIX兼容的网络文件系统CephFS,专注于高性能、大容量存储
  • 对象存储(RADOSGW):提供RESTful接口,也提供多种编程语言绑定。兼容S3(是AWS里的对象存储)、Swift(是openstack里的对象存储)

核心组件

Ceph 包括多个组件:

Ceph Monitors(MON):负责生成集群票选机制。所有的集群节点都会向 Mon 进行汇报,并在每次状态变更时进行共享信息。

Ceph Object Store Devices(OSD):负责在本地文件系统保存对象,并通过网络提供访问。通常 OSD 守护进程会绑定在集群的一个物理盘上,Ceph 客户端直接和 OSD 打交道。

Ceph Manager(MGR):提供额外的监控和界面给外部的监管系统使用。

MDS (可选) 为 Ceph 文件系统提供元数据计算、缓存与同步。MDS 进程并不是必须的进程,只有需要使用 CephFS 时,才需要配置 MDS 节点。

Reliable Autonomic Distributed Object Stores:Ceph 存储集群的核心。这一层用于为存储数据提供一致性保障,执行数据复制、故障检测以及恢复等任务。

为了在 Ceph 上进行读写,客户端首先要联系 MON,获取最新的集群地图,其中包含了集群拓扑以及数据存储位置的信息。Ceph 客户端使用集群地图来获知需要交互的 OSD,从而和特定 OSD 建立联系。

Rook介绍

Rook https://rook.io 是一个自管理的分布式存储编排系统,可以为Kubernetes提供便利的存储解决方案。

Rook本身并不提供存储,而是在kubernetes和存储系统之间提供适配层,简化存储系统的部署与维护工作。

Rook 使用 CRD 一个控制器来对 Ceph 之类的资源进行部署和管理。

Rook 包含多个组件:

Rook Operator:Rook 的核心组件,Rook Operator 是一个简单的容器,自动启动存储集群,并监控存储守护进程,来确保存储集群的健康。

Rook Agent:在每个存储节点上运行,并配置一个 FlexVolume 插件,和 Kubernetes 的存储卷控制框架进行集成。Agent 处理所有的存储操作,例如挂接网络存储设备、在主机上加载存储卷以及格式化文件系统等。

Rook Discovers:检测挂接到存储节点上的存储设备。

Rook 还会用 Kubernetes Pod 的形式,部署 Ceph 的 MON、OSD 以及 MGR 守护进程。

Rook Operator 让用户可以通过 CRD 的是用来创建和管理存储集群。每种资源都定义了自己的 CRD.

Rook Cluster:提供了对存储机群的配置能力,用来提供块存储、对象存储以及共享文件系统。每个集群都有多个 Pool。

Pool:为块存储提供支持。Pool 也是给文件和对象存储提供内部支持。

Object Store:用 S3 兼容接口开放存储服务。

File System:为多个 Kubernetes Pod 提供共享存储。

目前,Rook支持的存储系统包括:Ceph、CockroachDB、Cassandra、EdgeFS、Minio、NFS。当然,Rook支持的最好的还是Ceph 和 NFS。

为什么要使用Rook?

使用Rook的其中一个主要好处在于它是通过原生的Kubernetes机制和数据存储交互。这就意味着你不再需要通过命令行手动配置Ceph。

安装Ceph集群

通过rook安装ceph集群需要满足以下两个前提条件:

  • 已部署好的Kubernetes集群
  • osd节点需要有未格式化⽂件系统的磁盘

注意:容器数据目录容量(生产应该是单独挂载磁盘),Node节点镜像+运行占用30G左右,小心引发disk-pressure:NoSchedule

开发环境使用,不建议在生产环境使用

前置准备

给所有需要安装ceph的worker节点安装lvm2

yum install lvm2 -y

# 检查是否安装成功
[root@node1 ~]# yum list installed | grep lvm2
lvm2.x86_64                        7:2.02.187-6.el7_9.5                @updates 
lvm2-libs.x86_64                   7:2.02.187-6.el7_9.5                @updates

下载rook

git clone --single-branch --branch v1.9.2 https://github.com/rook/rook.git

下载镜像

国内源:
gcr.m.daocloud.io
quay.m.daocloud.io

cat /root/rook/deploy/examples/images.txt

 k8s.gcr.io/sig-storage/csi-attacher:v3.4.0
 k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.5.0
 k8s.gcr.io/sig-storage/csi-provisioner:v3.1.0
 k8s.gcr.io/sig-storage/csi-resizer:v1.4.0
 k8s.gcr.io/sig-storage/csi-snapshotter:v5.0.1
 k8s.gcr.io/sig-storage/nfsplugin:v3.1.0
 # 下面这些没被墙,可以不用代理
 quay.io/ceph/ceph:v16.2.7
 quay.io/cephcsi/cephcsi:v3.6.1
 quay.io/csiaddons/k8s-sidecar:v0.2.1
 quay.io/csiaddons/volumereplication-operator:v0.3.0
 rook/ceph:v1.9.2

这里使用skopeo下载上传到harbor私有仓库

yum install -y skopeo

export https_proxy="192.168.10.250:7890"
for image in $(cat /root/rook/deploy/examples/images.txt); do skopeo copy docker://${image} docker://registry.sundayhk.com/k8s/${image#*/}; done

修改成harbor私有仓库地址

vim /root/rook/deploy/examples/operator.yaml

  ROOK_CSI_CEPH_IMAGE: "registry.sundayhk.com/k8s/cephcsi/cephcsi:v3.6.1"
  ROOK_CSI_REGISTRAR_IMAGE: "registry.sundayhk.com/k8s/sig-storage/csi-node-driver-registrar:v2.5.0"
  ROOK_CSI_RESIZER_IMAGE: "registry.sundayhk.com/k8s/sig-storage/csi-resizer:v1.4.0"
  ROOK_CSI_PROVISIONER_IMAGE: "registry.sundayhk.com/k8s/sig-storage/csi-provisioner:v3.1.0"
  ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.sundayhk.com/k8s/sig-storage/csi-snapshotter:v5.0.1"
  ROOK_CSI_ATTACHER_IMAGE: "registry.sundayhk.com/k8s/sig-storage/csi-attacher:v3.4.0"
  ROOK_CSI_NFS_IMAGE: "registry.sundayhk.com/k8s/sig-storage/nfsplugin:v3.1.0"
            image: registry.sundayhk.com/k8s/ceph:v1.9.2


vim /root/rook/deploy/examples/cluster.yaml

    image: registry.sundayhk.com/k8s/ceph/ceph:v16.2.7

先通过lsblk查看盘符,这里可以看到vdb2是预留给ceph的

[root@node1 ~]# lsblk
       NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
       sr0     11:0    1  478K  0 rom
       vda    253:0    0   50G  0 disk
       ├─vda1 253:1    0    1G  0 part /boot
       └─vda2 253:2    0   49G  0 part /
       vdb    253:16   0  500G  0 disk
       ├─vdb1 253:17   0  100G  0 part /var/lib/docker
       └─vdb2 253:18   0  400G  0 part

修改ceph集群配置

节点亲和性让其运行在指定节点上,同时手动指定节点及磁盘

给node节点打上标签,保证ceph只安装在这3台node节点上

kubectl label node node1 role=ceph-storage
kubectl label node node2 role=ceph-storage
kubectl label node node3 role=ceph-storage
vim /root/rook/deploy/examples/cluster.yaml
# 146行 第一处修改节点亲和性
  placement:
    all:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: role
              operator: In
              values:
              - ceph-storage ## 注意

# 223行 第二处修改
  storage: # cluster level storage configuration and selection
    useAllNodes: false
    useAllDevices: false
    config:
      journalSizeMB: "4096" 

# 236行 第三处修改
    nodes:
      - name: "node1"
        devices:
          - name: "vdb2" # 可以通过lsblk查看磁盘信息
            config:
              storeType: bluestore
      - name: "node2"
        devices:
          - name: "vdb2" # 可以通过lsblk查看磁盘信息
            config:
              storeType: bluestore
      - name: "vdb2"
        devices:
          - name: "sdb" # 可以通过lsblk查看磁盘信息

注意,name 不能够配置为IP,而应该是标签 kubernetes.io/hostname 的内容

修改operator.yaml,让CSI守护进程可以调度到主节点

默认情况下master节点是不允许调度的,但是ceph有些守护进程是需要调度到master去。这一步是为了解决后面出现的问题,如果此时不修改也可以在后面出现问题的时候再改。这些都是经验教训,网上的安装手册不会告诉你有这一步。

[root@haproxy rook]# kubectl describe node/master1 | grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule

修改rook operator的配置

 vim deploy/examples/operator.yaml 
 # 143行 去掉后#,再往前缩进一格,与上面#对齐
  CSI_PLUGIN_TOLERATIONS: |
    - effect: NoSchedule
      key: node-role.kubernetes.io/master
      operator: Exists

安装Ceph集群

创建ceph所需要的资源

cd rook/deploy/examples
kubectl apply -f crds.yaml -f common.yaml -f operator.yaml

执行完成后等待容器启动,只有完全启动后才能执行进行下一步操作。

[root@haproxy examples]#  kubectl -n rook-ceph get pod -w
NAME                                  READY   STATUS              RESTARTS   AGE
rook-ceph-operator-84985d69d4-z5bkq   0/1     ContainerCreating   0          7s
rook-ceph-operator-84985d69d4-z5bkq   1/1     Running             0          51s

# 此处注意是否启动成功,如果没有启动成功使用检查
# kubectl describe pod rook-ceph-operator-7c6784496d-dsdtc -n rook-ceph 

需要先修改一下集群osd的资源限制,否则osd的内存使用率会无限增长(同样是经验教训)

vim /root/rook/deploy/examples/cluster.yaml
# 196行
   osd:
     limits:
       cpu: "2" 
       memory: "8096Mi"
     requests:
       cpu: "2" 
       memory: "8096Mi"

修改保存后执行以下命令安装ceph集群

kubectl apply -f cluster.yaml

创建完成后,可以查看pod的状态:

[root@haproxy example] examples]# kubectl -n rook-ceph get pod
NAME                                                        READY   STATUS      RESTARTS   AGE
csi-cephfsplugin-gjmhv                                      3/3     Running     0          8m7s
csi-cephfsplugin-l2vz6                                      3/3     Running     0          8m7s
csi-cephfsplugin-provisioner-6f54f6c477-rnql9               6/6     Running     0          8m7s
csi-cephfsplugin-provisioner-6f54f6c477-vgvnj               6/6     Running     0          8m7s
csi-cephfsplugin-zplbg                                      3/3     Running     0          8m7s
csi-rbdplugin-54cgx                                         3/3     Running     0          8m7s
csi-rbdplugin-7795w                                         3/3     Running     0          8m7s
csi-rbdplugin-dtnqk                                         3/3     Running     0          8m7s
csi-rbdplugin-provisioner-6d765b47d5-g2lzc                  6/6     Running     0          8m7s
csi-rbdplugin-provisioner-6d765b47d5-klk9n                  6/6     Running     0          8m7s
rook-ceph-crashcollector-node1-7598585c9b-49czg   1/1     Running     0          5m23s
rook-ceph-crashcollector-node2-675d7c66f-lzw4n    1/1     Running     0          5m11s
rook-ceph-crashcollector-node3-656f47985d-k4h96   1/1     Running     0          5m35s
rook-ceph-mgr-a-c9bf8bb54-kvgbw                             1/1     Running     0          5m40s
rook-ceph-mon-a-55b778d66d-dl8h6                            1/1     Running     0          8m1s
rook-ceph-mon-b-65f6d54689-zxblk                            1/1     Running     0          7m26s
rook-ceph-mon-c-dc947478f-2jt2r                             1/1     Running     0          5m53s
rook-ceph-operator-84985d69d4-z5bkq                         1/1     Running     0          18h
rook-ceph-osd-0-d77bf645f-mk9j7                             1/1     Running     0          5m12s
rook-ceph-osd-1-b7d7c47d-2kz5p                              1/1     Running     0          5m11s
rook-ceph-osd-2-78fbd4bdc7-zbjsz                            1/1     Running     0          5m11s
rook-ceph-osd-prepare-node1-hzq7l                 0/1     Completed   0          5m19s
rook-ceph-osd-prepare-node2-8pqlk                 0/1     Completed   0          5m19s
rook-ceph-osd-prepare-node3-kb2q9                 0/1     Completed   0          5m19s 

rook-ceph-crashcollector (有几个 node 就有几个) rook-ceph-osd (有几个 disk,就会有几个 pod,排序从 0 开始)

以上是所有组件的 pod 完成后的状态,以rook-ceph-osd-prepare 开头的 pod 用于自动感知集群新挂载硬盘,只不过我们前面手动指定了节点,所以这个不起作用。osd-0、osd-1、osd-2容器必须是存在且正常的,如果上述pod均正常运行成功,则视为集群安装成功。

安装Ceph Dashboard

Ceph Dashboard 是一个内置的基于 Web 的管理和监视应用程序,它是开源 Ceph 发行版的一部分。通过 Dashboard 可以获取 Ceph 集群的各种基本状态信息。

默认的 ceph 已经安装的 ceph-dashboard,其 SVC 地址是 service clusterIP,并不能被外部访问,需要创建 service 服务

kubectl apply -f dashboard-external-https.yaml

创建NodePort类型就可以被外部访问了

[root@haproxy examples]# kubectl get svc -n rook-ceph  | grep rook-ceph-mgr-dashboard
rook-ceph-mgr-dashboard                  ClusterIP   10.233.7.175    <none>        8443/TCP            125m
rook-ceph-mgr-dashboard-external-https   NodePort    10.233.6.184    <none>        8443:32129/TCP      41s

浏览器访问(master1-ip换成自己的集群ip):https://master1-ip:32129/

用户名默认是admin,至于密码可以通过以下代码获取:

kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}"|base64 --decode && echo

安装Rook工具箱

Rook 工具箱是一个包含用于 Rook 调试和测试的常用工具的容器,安装很简单

cd /root/rook/deploy/examples
kubectl apply -f toolbox.yaml -n rook-ceph

待容器Running后,即可执行相关命令:

[root@haproxy example] ~]# kubectl get po -n rook-ceph | grep tools
rook-ceph-tools-775f4f4468-dcg4x                            1/1     Running     0          2m12s
[root@haproxy example] ~]# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') -- bash
[rook@rook-ceph-tools-775f4f4468-dcg4x /]$ ceph -s
 cluster:
   id:     cea16e6d-ef51-4cfd-aa15-3a0e13075071
   health: HEALTH_OK
 services:
   mon: 3 daemons, quorum a,b,c (age 28m)
   mgr: a(active, since 27m)
   osd: 3 osds: 3 up (since 28m), 3 in (since 28m)
 data:
   pools:   0 pools, 0 pgs
   objects: 0 objects, 0 B
   usage:   15 MiB used, 1.2 TiB / 1.2 TiB avail
   pgs:
[rook@rook-ceph-tools-775f4f4468-dcg4x /]$ ceph osd status
ID  HOST              USED  AVAIL  WR OPS  WR DATA  RD OPS  RD DATA  STATE
0  dev-node3  4976k   399G      0        0       0        0   exists,up
1  dev-node2  4976k   399G      0        0       0        0   exists,up
2  dev-node1  4976k   399G      0        0       0        0   exists,up

工具箱相关查询命令

ceph status
ceph osd status
ceph df
rados df

部署RBD块存储

rook ceph block 块存储部署文档

注意:RBD只支持ReadWriteOnce存储类型,即只允许单个pod挂载

Ceph 可以同时提供对象存储 RADOSGW、块存储 RBD、文件系统存储 Ceph FS。RBD 即 RADOS Block Device 的简称,RBD 块存储是最稳定且最常用的存储类型。RBD 块设备类似磁盘可以被挂载。RBD 块设备具有快照、多副本、克隆和一致性等特性,数据以条带化的方式存储在 Ceph 集群的多个 OSD 中。

1.创建 StorageClass

cd /root/rook/deploy/examples/csi/rbd
kubectl apply -f storageclass.yaml

2.校验replicapool pool安装情况

[root@haproxy rbd]# kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" \
	-o jsonpath='{.items[0].metadata.name}') -- ceph osd lspools

   1 device_health_metrics
   2 replicapool

3.查看StorageClass

[root@haproxy rbd]# kubectl get sc
NAME              PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block   rook-ceph.rbd.csi.ceph.com   Delete          Immediate           true                   43s

4.将Ceph设置为默认存储卷

kubectl patch storageclass rook-ceph-block -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

5.修改完成后再查看StorageClass状态(有个default标识

[root@haproxy example] rbd]# kubectl get sc
NAME                        PROVISIONER                  RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block (default)   rook-ceph.rbd.csi.ceph.com   Delete          Immediate           true                   108s

6.创建pvc及运行pod测试挂载

cd /root/rook/deploy/examples/csi/rbd
kubectl apply -f pvc.yaml
kubectl apply -f pod.yaml

部署CephFs文件存储系统

Rook Cephfs filesystem部署文档

注意:CephFs支持ReadWriteMany存储类型,即允许多个pod挂载

注意的是我们上面给集群安装的是基于RBD的块存储,只支持ReadWriteOnce存储类型,如果你要使用ReadWriteMany存储类型,还需要安装CephFs文件存储系统。

# 配置MDS元数据节点 标签
kubectl label node node1 app=rook-ceph-mds
kubectl label node node2 app=rook-ceph-mds
kubectl label node node3 app=rook-ceph-mds
cd /root/rook/deploy/examples/csi/cephfs
kubectl apply -f storageclass.yaml
kubectl apply -f pvc.yaml
kubectl apply -f pod.yaml

使用快照需要另外安装snapshot CRD and controller https://github.com/rook/rook/issues/6819#issuecomment-1112783548

Kuberntes云原生实战六 使用Rook搭建Ceph集群 [Rook & Ceph 简介]https://blog.fleeto.us/post/the-ultimate-rook-and-ceph-survival-guide/