使用rook在k8s管理ceph集群

发布时间:2020-11-08 18:56:09阅读:(1300)

ceph是一种高度扩展的分布式存储方案,能够提供对象、文件和块存储,也可以为k8s提供持久化存储能力。然而,ceph的集群搭建相对还是计较复杂的,而且既然引入了k8s,何不让k8s为我们管理ceph集群呢?

Rook的出现为上面的问题提供了解决方案。Rook是一个自管理的分布式存储编排系统,可以为k8s提供便利的存储解决方案。Rook本身不提供春初,而是在k8s和存储系统之间提供了适配层,简化了存储系统的部署与维护。接下来我们就来使用Rook在k8s上搭建一套ceph集群。

环境准备

这里我准备了4台机器作为存储的设备。

配置信息:

系统类型IPHostname磁盘
centos-7.710.0.34.81storage-node1系统盘:80G
存储盘:500G*2,不挂载
centos-7.710.0.34.82storage-node2
centos-7.710.0.34.83storage-node3
centos-7.710.0.34.84storage-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

发表评论

评论列表(有4条评论1300人围观)
游客2020-12-15 09:22:36

我这边创建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

凌杰2020-12-15 11:11:55

这个问题我没遇到过,找了一下,可能是系统内核版本太低引起的https://github.com/rook/rook/issues/4919#issuecomment-591224798

游客2020-11-23 22:45:38

博主你好,请问你是如何获取csi-node-driver-registrar:v2.0.1等相关镜像到你个人阿里云镜像仓库的?

凌杰2020-11-24 11:05:55

最近有好多人问我这个问题,我这边写了一篇文章,可以参考一下https://www.lingjie.tech/article/2020-11-24/25