Rook部署ceph集群

Ceph介绍

Ceph是一个分布式存储系统,提供文件(file)、块(block)和对象存储(object storage),并在大规模生产集群中部署。

一个Ceph集群至少需要一个Ceph Monitor和一个Manager组件(建议每个Monitor都有一个Manager组件),Ceph Object Storage Daemons(OSDs)则是根据节点的多少而部署多少,必须每个节点都要部署,作为副本复制使用。

Ceph采用数据作为对象存储在逻辑存储池中。Ceph存储采用CRUSH算法来计算哪个Placement Group(PG)应该包含对象,以及哪个OSD应该存储到PG中。CRUSH算法使得Ceph存储具有动态可拓展、可平衡、以及恢复数据的能力。

  • Monitors:
    Ceph Monitor(ceph-mon)组件维持着Ceph集群的状态,包括monitor数据映射、manager数据映射、osd数据映射、MDS数据映射以及CRUSH映射。同时Monitor也负责管理Ceph守护进程和客户端之间的权限认证。集群部署需要至少3个Monitor来维持高可用状态。
  • Managers:
    Ceph Manager(ceph-mgr)负责保持运行时指标跟踪和集群状态跟踪,这里包括了存储使用率、当前集群性能指标和集群系统负载。Ceph-Manager作为守护进程,通过Python模块化的功能提供Ceph集群信息,方式为Ceph-Dashboard和REST-API。同时保障高可用需要至少两个Manager进程。
  • Ceph OSDs:
    Ceph Object Storage Daemon(Ceph OSD,ceph-osd)是Ceph集群的存储组件。负责处理数据复制(replication)、数据恢复(recovery)、数据均衡(rebalance),通过心跳机制提供一些监控数据给Monitor和Managers。高可用集群中需要至少3个OSD节点。
  • MDSs:
    Ceph Metadata Server(MDS,ceph-mds)负责存储Ceph文件系统的元数据。该组件允许CephFS用户执行一些不会给集群带来负担的基础命令(例如:ls,find等)。

以下是Ceph的架构图:

ceph-architecure.png

Rook介绍

Rook是一个开源的云原生存储编排组件,通过对Ceph提供平台、框架和支持,使得Ceph能更快速集成到云原生环境中。Rook也是云原生计算基金会(CNCF)的一个项目,从2018年成为孵化项目,并在2020年成为毕业项目。

使用Rook可以自动部署和管理Ceph,提供自我管理、自我扩展和自我修复的存储服务。Rook Operator通过Kubernetes Resources来部署(deploy)、配置(configure)、供应(provision)、扩展(scale)、升级(upgrade)和监控(monitor)Ceph。

rook-architecture.png

环境准备

Ceph集群部署支持多种方式,官方推荐Cephadm和Rook两种部署方式。Cephadm适合独立部署Ceph,可以在k8s外独立部署,而Rook则是直接将Ceph部署到K8s集群内,这样可以合理使用k8s工作节点资源。
其他的部署方式包括:Ceph-ansible、Ceph-deploy、ceph-salt等,当然Ceph也支持手动部署,但手动部署较为复杂。

本文采用Rook方式部署,环境如下:

  • 操作系统:Ceotos7.9
  • 系统内核:Linux os-60 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
  • Rook版本:v1.15.2
  • Ceph版本:v18.2.4
  • k8s集群:v1.28.0,containerd: 1.6.33
  • 准备4台k8s服务器,1台master,3台工作节点,3台k8s工作节点挂载一个磁盘(但不要挂载),本文采用虚拟机方式部署,需要在VirsualBox或者VM虚拟机上添加一块磁盘。
    virtualbox-adddisk.png

部署集群

本文采用离线部署,因此需要提前下载Rook仓库代码以及k8s所需要的镜像。

  • 挂载磁盘,在三台k8s工作节点上挂载一块20G的磁盘,在服务器上执行:lsblk,显示如下"sdb"就是刚才挂载的磁盘:

    #sdb盘就是刚刚挂载的,TYPE类型是disk,并且没有使用过
    NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
    sda               8:0    0  100G  0 disk
    ├─sda1            8:1    0    1G  0 part /boot
    └─sda2            8:2    0   99G  0 part
    ├─centos-root 253:0    0   50G  0 lvm  /
    ├─centos-swap 253:1    0  7.9G  0 lvm
    └─centos-home 253:2    0 41.1G  0 lvm  /home
    sdb               8:16   0   20G  0 disk
    sr0              11:0    1 1024M  0 rom
    
  • 准备lvm2环境和rbd模块

    #确认安装lvm2
    yum install lvm2 -y
    #启用rbd模块
    modprobe rbd
    cat > /etc/rc.sysinit << EOF
    #!/bin/bash
    for file in /etc/sysconfig/modules/*.modules
    do
    [ -x \$file ] && \$file
    done
    EOF
    
    cat > /etc/sysconfig/modules/rbd.modules << EOF
    modprobe rbd
    EOF
    
    chmod 755 /etc/sysconfig/modules/rbd.modules
    lsmod |grep rbd
    
    #显示如下表示成功加载模块
    rbd                    83733  2
    libceph               314775  2 rbd,ceph
    
  • rook安装包准备:提前下载rook仓库代码并切换到v1.15.2分支:

    git clone https://github.com/rook/rook.git
    git checkout v1.15.2
    
  • 镜像准备,提前下载如下镜像:

    docker.io/rook/ceph:v1.15.2
    quay.io/cephcsi/cephcsi:v3.12.2-amd64
    registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1
    registry.k8s.io/sig-storage/csi-resizer:v1.11.1
    registry.k8s.io/sig-storage/csi-provisioner:v5.0.1
    registry.k8s.io/sig-storage/csi-snapshotter:v8.0.1
    registry.k8s.io/sig-storage/csi-attacher:v4.6.1
    quay.io/ceph/ceph:v18.2.4
    
    #找一台可以下载镜像的服务器执行,并将镜像上传到k8s服务器:
    #rook
    docker pull --platform=linux/amd64 docker.io/rook/ceph:v1.15.2
    docker save -o rook-ceph-v1.15.2.tar.gz docker.io/rook/ceph:v1.15.2
    docker pull quay.io/cephcsi/cephcsi:v3.12.2-amd64
    docker save -o cephcsi-cephcsi-3.12.2.tar.gz quay.io/cephcsi/cephcsi:v3.12.2-amd64
    docker pull --platform=linux/amd64 registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1
    docker save -o csi-node-driver-registrar-v2.11.1.tar.gz registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.11.1
    docker pull --platform=linux/amd64 registry.k8s.io/sig-storage/csi-resizer:v1.11.1
    docker save -o csi-resizer-v1.11.1.tar.gz registry.k8s.io/sig-storage/csi-resizer:v1.11.1
    docker pull --platform=linux/amd64 registry.k8s.io/sig-storage/csi-provisioner:v5.0.1
    docker save -o csi-provisioner-v5.0.1.tar.gz registry.k8s.io/sig-storage/csi-provisioner:v5.0.1
    docker pull --platform=linux/amd64 registry.k8s.io/sig-storage/csi-snapshotter:v8.0.1
    docker save -o csi-snapshotter-v8.0.1.tar.gz registry.k8s.io/sig-storage/csi-snapshotter:v8.0.1
    docker pull --platform=linux/amd64 registry.k8s.io/sig-storage/csi-attacher:v4.6.1
    docker save -o csi-attacher-v4.6.1.tar.gz registry.k8s.io/sig-storage/csi-attacher:v4.6.1
    
    #ceph cluster
    docker pull --platform=linux/amd64 quay.io/ceph/ceph:v18.2.4
    docker save -o ceph-ceph-v18.2.4.tar.gz quay.io/ceph/ceph:v18.2.4
    
  • k8s服务器上导入镜像,需要在所有的k8s节点上执行:

    ctr -n k8s.io image import rook-ceph-v1.15.2.tar.gz && \
    ctr -n k8s.io image import ceph-ceph-v18.2.4.tar.gz && \
    ctr -n k8s.io image import cephcsi-cephcsi-3.12.2.tar.gz && \
    ctr -n k8s.io image import csi-node-driver-registrar-v2.11.1.tar.gz && \
    ctr -n k8s.io image import csi-resizer-v1.11.1.tar.gz && \
    ctr -n k8s.io image import csi-provisioner-v5.0.1.tar.gz && \
    ctr -n k8s.io image import csi-snapshotter-v8.0.1.tar.gz && \
    ctr -n k8s.io image import csi-attacher-v4.6.1.tar.gz
    

部署Rook Operator

安装部署Rook需要在k8s的master节点,首先将Rook仓库代码上传到k8s的master节点上。
进入Rook仓库目录,Rook部署所需要的yaml文件都位于仓库:deploy/examples下,部署Rook我们需要三个yaml,分别是:common.yamloperator.yamlcrds.yaml

  • 进入文件目录

    cd rook/deploy/examples
    
  • 部署Rook

    kubectl create -f crds.yaml -f common.yaml -f operator.yaml
    
  • 部署ceph集群,在执行部署前,需要修改cluster.yaml的部分配置,修改如下:

    #vim cluster.yaml
    #修改rook存储目录,存放rook相关配置
    dataDirHostPath: /home/data/rook
    #改为false,并非使用所有节点所有磁盘作为osd,devices的name修改为之前挂载的磁盘的名字“sdb”
    useAllNodes: true
    useAllDevices: false
    devices:
    - name: "sdb"
    
    #可选:自定义部署节点,只有useAllNodes为false时生效
    nodes:
    - name: "os-60"
      deviceFilter: "sdb"
    - name: "os-61"
      deviceFilter: "sdb"
    - name: "os-62"
      deviceFilter: "sdb"
    
    #执行安装Ceph集群
    kubectl create -f cluster.yaml
    
  • 查看集群部署情况,部署完毕会在k8s中创建rook-ceph命名空间,所有的rook以及ceph管理都在该空间下。

    kubectl -n rook-ceph get pods
    

    rook-status.png

  • 查看Ceph集群状态:

    kubectl get cephcluster -n rook-ceph
    
    #显示如下
    NAME        DATADIRHOSTPATH   MONCOUNT   AGE   PHASE   MESSAGE                        HEALTH        EXTERNAL   FSID
    rook-ceph   /home/data/rook   3          14d   Ready   Cluster created successfully   HEALTH_WARN              56ff0f1a-1099-4c7a-b3b9-c335ef307206
    

部署Ceph工具

rook镜像中提供一个ceph镜像工具,内部集成了ceph所有的命令,该工具的pod位于 rook/deploy/examples内,

cd rook/deploy/examples
kubectl create -f toolbox.yaml

#进入ceph工具内
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash

#查看ceph集群状态
ceph status

#结果如下:
bash-5.1$ ceph status
  cluster:
    id:     56ff0f1a-1099-4c7a-b3b9-c335ef307206
    health: HEALTH_WARN
            1 mgr modules have recently crashed

  services:
    mon: 3 daemons, quorum a,b,c (age 29h)
    mgr: b(active, since 29h), standbys: a
    mds: 1/1 daemons up, 1 hot standby
    osd: 3 osds: 3 up (since 29h), 3 in (since 2w)

  data:
    volumes: 1/1 healthy
    pools:   4 pools, 81 pgs
    objects: 626 objects, 2.1 GiB
    usage:   6.3 GiB used, 54 GiB / 60 GiB avail
    pgs:     81 active+clean

  io:
    client:   852 B/s rd, 1 op/s rd, 0 op/s wr

#查看磁盘使用情况
ceph df

#结果如下,可以看到集群磁盘总大小为60G,已使用6.3G。
bash-5.1$ ceph df
--- RAW STORAGE ---
CLASS    SIZE   AVAIL     USED  RAW USED  %RAW USED
hdd    60 GiB  54 GiB  6.3 GiB   6.3 GiB      10.57
TOTAL  60 GiB  54 GiB  6.3 GiB   6.3 GiB      10.57

--- POOLS ---
POOL             ID  PGS   STORED  OBJECTS     USED  %USED  MAX AVAIL
.mgr              1    1  577 KiB        2  1.7 MiB      0     17 GiB
replicapool       2   32  1.0 GiB      340  3.1 GiB   5.78     17 GiB
myfs-metadata     3   16  468 KiB       26  1.5 MiB      0     17 GiB
myfs-replicated   4   32  1.0 GiB      258  3.0 GiB   5.59     17 GiB

部署Dashboard

ceph提供一个对外的web管理页面,由ceph-Manager提供,但需要暴露service才可以使用,rook的目录下提供一个暴露service的yaml。

cd rook/deploy/examples
kubectl apply -f dashboard-external-https.yaml

#查看service对外端口
kubectl -n rook-ceph get svc
#显示如下,其中rook-ceph-mgr-dashboard-external-https对应的NodePort为31332,访问k8s集群+该端口即可访问管理页
NAME                                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
rook-ceph-exporter                       ClusterIP   10.103.229.154   <none>        9926/TCP            14d
rook-ceph-mgr                            ClusterIP   10.98.218.12     <none>        9283/TCP            14d
rook-ceph-mgr-dashboard                  ClusterIP   10.108.108.105   <none>        8443/TCP            14d
rook-ceph-mgr-dashboard-external-https   NodePort    10.102.158.148   <none>        8443:31332/TCP      14d
rook-ceph-mon-a                          ClusterIP   10.99.37.109     <none>        6789/TCP,3300/TCP   14d
rook-ceph-mon-b                          ClusterIP   10.98.151.62     <none>        6789/TCP,3300/TCP   14d
rook-ceph-mon-c                          ClusterIP   10.97.186.37     <none>        6789/TCP,3300/TCP   14d

本机的k8s集群master节点时10.0.0.60,因此访问地址:https://10.0.0.60:31332,即可访问dashboard页面:
ceph-dashboard.png

管理页面的账号是 admin,密码需要通过k8s-secret获取 kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 -d && echo,登陆即可在后台页面查看和操作ceph集群。
ceph-dashboard-1.png

部署CephRBD

k8s的卷访问模式有四种,其中核心的是 RWORWX两种,Ceph提供RBD块状存储,该存储在k8s主要用于访问模式是 ReadWriteOnce应用,在rook的部署例子中提供了rbd的动态卷的例子。
k8s-volume-accessmode.png

创建k8s动态卷,卷名称默认为:rook-ceph-block

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

#查看动态卷
kubectl get sc

#显示如下
NAME                PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
rook-ceph-block     rook-ceph.rbd.csi.ceph.com      Delete          Immediate           true                   14d

动态卷创建完毕以后,在ceph管理页面可以看到新增了一个名为 replicapool的pool存储池,这个就是动态卷 rook-ceph-block创建的pool池子。
ceph-pool.png
如果需要修改或者新增动态卷,我们可以通过查看 /csi/rbd/storageclass.yaml,可以看到meta.name的值就是动态卷的名称,parameters.pool的值就是ceph的pool池子的名称。
rbd-storageclass.png

部署应用,这里采用例子中的mysql和wordpress部署,首先修改mysql.yaml和wordpress.yaml中的数据库密码,然后执行部署:

kubectl apply -f mysql.yaml
kubectl apply -f wordpress.yaml

#访问wordpress,查看service,wordpress暴露的端口是30255
[root@os-60 ceph]# kubectl get svc
NAME              TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
kubernetes        ClusterIP      10.96.0.1       <none>        443/TCP           123d
wordpress         LoadBalancer   10.103.149.80   <pending>     80:30255/TCP      14d
wordpress-mysql   ClusterIP      None            <none>        3306/TCP          14d

访问10.0.0.60集群的30255端口:http://10.0.0.60:30255,即可访问workpress应用:
k8s-wordpress.png

如果要测试持久化存储能力,可以删除wordpress所有的pod,通过deployment拉起所有的pod,此时再次访问wordpress链接,仍然是之前的配置,表示持久化存储成功。

部署CephFS

Ceph提供FileSystem文件存储系统,该存储在k8s主要用于访问模式是 ReadWriteMany应用,可以达到多个k8s应用共享同一块存储,例如日志收集,简单文件存储等。
rook提供cephFS的例子,存放目录在 rook/deploy/examples

kubectl apply -f csi/cephfs/storageclass.yaml

#配置cephFS文件系统
kubectl apply -f filesystem.yaml

查看cephFS动态卷,cephFS的动态卷名称为 rook-cephfs

[root@os-60 ceph]# kubectl get sc
NAME                PROVISIONER                     RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-storage-class   iass.default/nfs                Delete          Immediate           false                  116d
rook-ceph-block     rook-ceph.rbd.csi.ceph.com      Delete          Immediate           true                   14d
rook-cephfs         rook-ceph.cephfs.csi.ceph.com   Delete          Immediate           true                   27h

#文件系统已配置完成,请等待mds Pod 启动,查看ceph-mds的状态
kubectl -n rook-ceph get pod -l app=rook-ceph-mds

#显示结果:
NAME                                    READY   STATUS    RESTARTS   AGE
rook-ceph-mds-myfs-a-676ffd56c7-t8cfl   2/2     Running   0          27h
rook-ceph-mds-myfs-b-6d84b7db9f-q8h8k   2/2     Running   0          27h

进入ceph工具内部,rook-ceph-tools,查看cephFs的状态:

kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash

#查看osd池子,确认myfs-metadata和myfs-replicated已经创建
bash-5.1$ ceph osd lspools
1 .mgr
2 replicapool
3 myfs-metadata
4 myfs-replicated

#查看fs状态:STATE为active
bash-5.1$ ceph fs status
myfs - 2 clients
====
RANK      STATE        MDS       ACTIVITY     DNS    INOS   DIRS   CAPS
 0        active      myfs-a  Reqs:    0 /s    40     29     23      6
0-s   standby-replay  myfs-b  Evts:    0 /s    35     20     14      0
      POOL         TYPE     USED  AVAIL
 myfs-metadata   metadata  1500k  16.8G
myfs-replicated    data    3072M  16.8G
MDS version: ceph version 18.2.4 (e7ad5345525c7aa95470c26863873b581076945d) reef (stable)

部署应用使用cephFS存储
首先创建pvc,pvc的配置如下,pvc的名称是 busybox-pvc,注意这里的accessModes的值是 ReadWriteMany

cat < ceph-pvc.yaml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: busybox-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  storageClassName: rook-cephfs
EOF

创建2个busybox应用,挂载的pvc都是 busybox-pvc

cat < busybox.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox
spec:
  replicas: 2
  selector:
    matchLabels:
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
      - name: busybox
        image: busybox:1.36
        command: ["sleep", "3600"]
        volumeMounts:
        - name: data-volume
          mountPath: /data
      volumes:
      - name: data-volume
        persistentVolumeClaim:
          claimName: busybox-pvc
EOF

cat < busybox-1.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: busybox-1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: busybox-1
  template:
    metadata:
      labels:
        app: busybox-1
    spec:
      containers:
      - name: busybox-1
        image: busybox:1.36
        command: ["sleep", "3600"]
        volumeMounts:
        - name: data-volume
          mountPath: /data
      volumes:
      - name: data-volume
        persistentVolumeClaim:
          claimName: busybox-pvc
EOF

创建两个busybox应用:

kubectl create -f busybox.yam -f busybox-1.yaml

#查看部署状态
[root@os-60 cephFS]# kubectl get pod -l app=busybox
NAME                       READY   STATUS    RESTARTS       AGE
busybox-6f95b45db6-c2rrf   1/1     Running   23 (47m ago)   23h
busybox-6f95b45db6-qrjw8   1/1     Running   23 (47m ago)   23h

#进入其中一个bosybox
kubectl exec -it deploy/busybox -- sh
#写入数据
echo "hello" >> /data/hello.txt
#进入另一个bosybox
kubectl exec -it deploy/busybox-1 -- sh
cat /data/hello.txt
#结果显示:
hello

结束

Ceph作为分布式存储系统,具有高度稳定性、高性能和高可拓展性,目前是主流的生产级别的存储系统。在云原生时代对于外部存储的要求越来越高,高性能可拓展的存储系统成为了必需品,因此也增强了Ceph的使用。
由于Ceph涉及组件较多,部署运维成本高,Rook的加入则简化了部署运维流程,大大节省了Ceph的运维成本。本文仅研究了Block和FileSystem两种,

第三种是对象存储,用于s3/swift等对外提供存储能力。

参考文献:
Ceph官网
Rook官网
CRUSH - Controlled, Scalable, Decentralized Placement of Replicated Data.