使用rook在k8s管理ceph集群
ceph是一种高度扩展的分布式存储方案,能够提供对象、文件和块存储,也可以为k8s提供持久化存储能力。然而,ceph的集群搭建相对还是计较复杂的,而且既然引入了k8s,何不让k8s为我们管理ceph集群呢?
Rook的出现为上面的问题提供了解决方案。Rook是一个自管理的分布式存储编排系统,可以为k8s提供便利的存储解决方案。Rook本身不提供春初,而是在k8s和存储系统之间提供了适配层,简化了存储系统的部署与维护。接下来我们就来使用Rook在k8s上搭建一套ceph集群。
环境准备
这里我准备了4台机器作为存储的设备。
配置信息:
系统类型 | IP | Hostname | 磁盘 |
centos-7.7 | 10.0.34.81 | storage-node1 | 系统盘:80G 存储盘:500G*2,不挂载 |
centos-7.7 | 10.0.34.82 | storage-node2 | |
centos-7.7 | 10.0.34.83 | storage-node3 | |
centos-7.7 | 10.0.34.84 | storage-node |
部署
首选,按照之前的教程,将4台机器加入k8s集群内(参考:部署worker节点和网络插件)
查看一下节点状态:
kubectl get node | grep storage-node
#storage-node1 Ready <none> 18m v1.19.3
#storage-node2 Ready <none> 18m v1.19.3
#storage-node3 Ready <none> 18m v1.19.3
#storage-node4 Ready <none> 18m v1.19.3
为这四个节点打上污点,因为我们希望这4个节点只提供存储服务,而不希望其他pod调度到这些节点上
kubectl taint node storage-node1 node-role.kubernetes.io/storage-node=:NoSchedule
kubectl taint node storage-node2 node-role.kubernetes.io/storage-node=:NoSchedule
kubectl taint node storage-node3 node-role.kubernetes.io/storage-node=:NoSchedule
kubectl taint node storage-node4 node-role.kubernetes.io/storage-node=:NoSchedule
再为这四个节点打上一个标签,后面会用到
kubectl label node storage-node1 role=storage
kubectl label node storage-node2 role=storage
kubectl label node storage-node3 role=storage
kubectl label node storage-node4 role=storage
然后我们到github上下载rook相关的配置文件,我这里使用的是release-1.5这个分支
github地址:https://github.com/rook/rook/tree/release-1.5/cluster/examples/kubernetes/ceph
我们需要的是common.yaml、operator.yaml、cluster.yaml这三个文件
common.yaml
这个文件定义了所有ceph相关的资源,不需要修改,直接执行接口
kubectl apply -f common.yaml
operator.yaml
这个文件顾名思义,定义了rook的operator,后续所有的对集群的操作,都由此控制。
此文件中使用了大量k8s.grc.io、quay.io的镜像,受网络限制可能无法下载,所以我把这些镜像都放在阿里云上了,可以按需求镜像替换
第48行:
#ROOK_CSI_CEPH_IMAGE: "quay.io/cephcsi/cephcsi:v3.1.1"
将注释去掉,替换为
ROOK_CSI_CEPH_IMAGE: "registry.cn-shanghai.aliyuncs.com/jieee/cephcsi:v3.1.1"
第49行:
#ROOK_CSI_REGISTRAR_IMAGE: "k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.0.1"
将注释去掉,替换为
ROOK_CSI_REGISTRAR_IMAGE: "registry.cn-shanghai.aliyuncs.com/jieee/csi-node-driver-registrar:v2.0.1"
第50行:
#ROOK_CSI_RESIZER_IMAGE: "k8s.gcr.io/sig-storage/csi-resizer:v1.0.0"
将注释去掉,替换为
ROOK_CSI_RESIZER_IMAGE: "registry.cn-shanghai.aliyuncs.com/jieee/csi-resizer:v1.0.0"
第51行:
#ROOK_CSI_PROVISIONER_IMAGE: "k8s.gcr.io/sig-storage/csi-provisioner:v2.0.0"
将注释去掉,替换为
ROOK_CSI_PROVISIONER_IMAGE: "registry.cn-shanghai.aliyuncs.com/jieee/csi-provisioner:v2.0.0"
第52行:
#ROOK_CSI_SNAPSHOTTER_IMAGE: "k8s.gcr.io/sig-storage/csi-snapshotter:v3.0.0"
将注释去掉,替换为
ROOK_CSI_SNAPSHOTTER_IMAGE: "registry.cn-shanghai.aliyuncs.com/jieee/csi-snapshotter:v3.0.0"
第53行:
#ROOK_CSI_ATTACHER_IMAGE: "k8s.gcr.io/sig-storage/csi-attacher:v3.0.0"
将注释去掉,替换为
ROOK_CSI_ATTACHER_IMAGE: "registry.cn-shanghai.aliyuncs.com/jieee/csi-attacher:v3.0.0"
设置节点情和性和污点,让pod运行到存储的节点上去
搜索:CSI_PROVISIONER_TOLERATIONS,把注释打开,替换成:
CSI_PROVISIONER_TOLERATIONS: |
- effect: NoSchedule
key: "node-role.kubernetes.io/storage-node"
operator: "Exists"
搜索:CSI_PLUGIN_TOLERATIONS,把注释打开,替换成:
CSI_PLUGIN_TOLERATIONS: |
- effect: NoSchedule
key: "node-role.kubernetes.io/storage-node"
operator: "Exists"
搜索:- name: AGENT_TOLERATIONS,把注释打开,替换成:
- name: AGENT_TOLERATIONS
value: |
- effect: NoSchedule
key: "node-role.kubernetes.io/storage-node"
operator: "Exists"
搜索:- name: AGENT_NODE_AFFINITY,把注释打开,替换成:
- name: AGENT_NODE_AFFINITY
value: "role=storage"
搜索:- name: DISCOVER_TOLERATIONS,把注释打开,替换成:
- name: AGENT_TOLERATIONS
value: |
- effect: NoSchedule
key: "node-role.kubernetes.io/storage-node"
operator: "Exists"
搜索:- name: DISCOVER_AGENT_NODE_AFFINITY,把注释打开,替换成:
- name: DISCOVER_AGENT_NODE_AFFINITY
value: "role=storage"
这样,operator.yaml中需要修改的地方就改完了。我们来执行以下
kubectl apply -f operator.yaml
到dashboard上看一下,发现多了一个operator pod和4个discover pod,rook-discover是一个daemonset,全部运行在storage-node上,这和我们的预期是一致的
随便找一个discover容器,看一下日志:
可以看到已经扫描到了机器上的sdb、sdc这两块盘,这两块盘就是我们给ceph准备的存储盘
cluster.yaml
这个文件将创建一个ceph集群,有几个地方需要修改:
首先,将镜像修改为阿里云的镜像:
image: ceph/ceph:v15.2.5
修改为
image: registry.cn-shanghai.aliyuncs.com/jieee/ceph:v15.2.5
修改一下dashboard的端口和协议(默认采用8433端口和自签证书的ssl,我们改为http协议)
dashboard:
enabled: true
port: 8080
ssl: false
然后修改一下节点亲和性和污点
placement:
all:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: role
operator: In
values:
- storage
podAffinity:
podAntiAffinity:
topologySpreadConstraints:
tolerations:
- key: "node-role.kubernetes.io/storage-node"
operator: Exists
cluster.yaml就修改完了,我们来执行以下
kubectl apply -f cluster.yaml
这次执行会慢以下,应为rook会创建大量的pod进行集群的初始化,过几分钟后,我们去dashboard上查看:
可以看到rook创建了两个csi的daemonset,还对ceph的mon、mgr组件分别创建了deployment,最关键的是rook-ceph-osd的deployment,rook为每一块磁盘都创建了一个pod进行管理,我们4台机器上共有8块磁盘,刚好对应这里8个deployment。
既然部署了dashboard,那么对应的肯定有管理页面,我们去service中看一下:
可以看到rook-ceph-mgr-dashboard这个service,我们直接访问IP看一下
需要登录,用户名是admin,密码存放在secret中
kubectl -n rook-ceph get secret rook-ceph-dashboard-password -o jsonpath="{['data']['password']}" | base64 --decode && echo
E7q@+O:f.$mHGe)Uk`S. # 拿到的密码
登录后就能看到熟悉的界面了
可以看到集群的健康状态、osd的数量,8个osd刚好对应我们8块磁盘。
使用Rook ceph块存储
首先下载配置文件:
wget https://github.com/rook/rook/raw/release-1.5/cluster/examples/kubernetes/ceph/csi/rbd/storageclass.yaml
storageclass.yaml
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool # ceph pool名称,与下面sc中的pool需保持一致
namespace: rook-ceph
spec:
failureDomain: host
replicated:
size: 3
requireSafeReplicaSize: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block # sc的名称,这个可以随意修改
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph
pool: replicapool
imageFormat: "2"
imageFeatures: layering
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
csi.storage.k8s.io/fstype: ext4
allowVolumeExpansion: true
reclaimPolicy: Delete
执行一下
kubectl apply -f storageclass.yaml
#查看结果
kubectl get cephblockpools -n rook-ceph
#NAME AGE
#replicapool 15s
可以看到sc已经创建成功。
接下来,试试创建一个pvc
rbd-test.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-test
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-ceph-block # sc名称需要保持一致
执行以下
kubectl apply -f rbd-test.yaml
可以看到,创建成功了。
使用Rook ceph共享文件存储
创建配置文件:
filesystem.yaml
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
name: myfs
namespace: rook-ceph
spec:
metadataPool:
replicated:
size: 3
dataPools:
- replicated:
size: 3
preserveFilesystemOnDelete: true
metadataServer:
activeCount: 1
activeStandby: true
storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-cephfs # sc名称
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
fsName: myfs # 文件系统名称
pool: myfs-data0 # 对应的存储池名称
csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
执行以下
kubectl apply -f filesystem.yaml
kubectl apply -f storageclass.yaml
#查看结果
kubectl get CephFilesystem -n rook-ceph
#NAME ACTIVEMDS AGE
#myfs 1 12s
kubectl -n rook-ceph get pod -l app=rook-ceph-mds
#NAME READY STATUS RESTARTS AGE
#rook-ceph-mds-myfs-a-6949ffb69d-p5mfs 1/1 Running 0 60s
#rook-ceph-mds-myfs-b-64874f59d-zvt9b 1/1 Running 0 58s
可以看到sc已经创建成功。
接下来,试试创建一个pvc
fs-test.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: fs-test
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
storageClassName: rook-cephfs # sc名称需要保持一致
执行以下
kubectl apply -f fs-test.yaml
可以看到,创建成功了。
本文配置文件地址,详见GITEE
文章转载或复制请以超链接形式并注明出处陌上小筑
发表评论
我这边创建pvc也是成功的,但是真正部署一个应用就会提示下面的信息
AttachVolume.Attach succeeded for volume "pvc-a69bef13-458f-4ffa-8c54-19c6b9e53e38"
Warning FailedMount 2m4s kubelet
Unable to attach or mount volumes: unmounted volumes=[wordpress-persistent-storage], unattached volumes=[wordpress-persistent-storage default-token-x2p58]: timed out waiting for the condition
Warning FailedMount 53s (x3 over 2m56s) kubelet
MountVolume.MountDevice failed for volume "pvc-a69bef13-458f-4ffa-8c54-19c6b9e53e38" : rpc error: code = Internal desc = rbd: map failed with error an error (exit status 110) and stdError (rbd: sysfs write failed
rbd: map failed: (110) Connection timed out) occurred while running rbd args: [--id csi-rbd-node -m 10.43.14.159:6789,10.43.162.252:6789,10.43.11.31:6789 --keyfile=stripped replicapool/csi-vol-2838c96a-3e70-11eb-ad8e-066905c1a6fe --device-type krbd], rbd error output: rbd: sysfs write failed
rbd: map failed: (110) Connection timed outmap
这个问题我没遇到过,找了一下,可能是系统内核版本太低引起的https://github.com/rook/rook/issues/4919#issuecomment-591224798
博主你好,请问你是如何获取csi-node-driver-registrar:v2.0.1等相关镜像到你个人阿里云镜像仓库的?
最近有好多人问我这个问题,我这边写了一篇文章,可以参考一下https://www.lingjie.tech/article/2020-11-24/25