原文链接:https://fuckcloudnative.io/posts/kubernetes-storage-using-ceph-rbd/

本文详细介绍了如何在 Kubernetes 集群中部署 ceph-csi(v3.1.0),并使用 RBD 作为持久化存储。

需要的环境参考下图:

本文使用的环境版本信息:

Kubernetes 版本:

$ kubectl get node
NAME STATUS ROLES AGE VERSION
sealos01 Ready master 23d v1.18.8
sealos02 Ready master 23d v1.18.8
sealos03 Ready master 23d v1.18.8

Ceph 版本:

$ ceph version
ceph version 14.2.11 (f7fdb2f52131f54b891a2ec99d8205561242cdaf) nautilus (stable)

以下是详细部署过程:

1. 新建 Ceph Pool

创建一个新的 ceph 存储池(pool) 给 Kubernetes 使用:

$ ceph osd pool create kubernetes

pool ' kubernetes' created

查看所有的 pool:

$ ceph osd lspools

1 cephfs_data
2 cephfs_metadata
3 .rgw.root
4 default.rgw.control
5 default.rgw.meta
6 default.rgw.log
7 kubernetes

2. 新建用户

为 Kubernetes 和 ceph-csi 单独创建一个新用户:

$ ceph auth get-or-create client.kubernetes mon 'profile rbd' osd 'profile rbd pool=kubernetes' mgr 'profile rbd pool=kubernetes'

[client.kubernetes]
key = AQBnz11fclrxChAAf8TFw8ROzmr8ifftAHQbTw==

后面的配置需要用到这里的 key,如果忘了可以通过以下命令来获取:

$ ceph auth get client.kubernetes
exported keyring for client.kubernetes
[client.kubernetes]
key = AQBnz11fclrxChAAf8TFw8ROzmr8ifftAHQbTw==
caps mgr = "profile rbd pool=kubernetes"
caps mon = "profile rbd"
caps osd = "profile rbd pool=kubernetes"

3. 部署 ceph-csi

拉取 ceph-csi 的最新 release 分支(v3.1.0):

$ git clone --depth 1 --branch v3.1.0 https://gitclone.com/github.com/ceph/ceph-csi
  • 这里使用 gitclone 来加速拉取。

修改 Configmap

获取 Ceph 集群的信息:

$ ceph mon dump

dumped monmap epoch 1
epoch 1
fsid 154c3d17-a9af-4f52-b83e-0fddd5db6e1b
last_changed 2020-09-12 16:16:53.774567
created 2020-09-12 16:16:53.774567
min_mon_release 14 (nautilus)
0: [v2:172.16.1.21:3300/0,v1:172.16.1.21:6789/0] mon.sealos01
1: [v2:172.16.1.22:3300/0,v1:172.16.1.22:6789/0] mon.sealos02
2: [v2:172.16.1.23:3300/0,v1:172.16.1.23:6789/0] mon.sealos03

这里需要用到两个信息:

  • fsid : 这个是 Ceph 的集群 ID。
  • 监控节点信息。目前 ceph-csi 只支持 v1 版本的协议,所以监控节点那里我们只能用 v1 的那个 IP 和端口号(例如,172.16.1.21:6789)。

进入 ceph-csi 的 deploy/rbd/kubernetes 目录:

$ cd deploy/rbd/kubernetes

$ ls -l ./
total 36
-rw-r--r-- 1 root root 100 Sep 14 04:49 csi-config-map.yaml
-rw-r--r-- 1 root root 1686 Sep 14 04:49 csi-nodeplugin-psp.yaml
-rw-r--r-- 1 root root 858 Sep 14 04:49 csi-nodeplugin-rbac.yaml
-rw-r--r-- 1 root root 1312 Sep 14 04:49 csi-provisioner-psp.yaml
-rw-r--r-- 1 root root 3105 Sep 14 04:49 csi-provisioner-rbac.yaml
-rw-r--r-- 1 root root 5497 Sep 14 04:49 csi-rbdplugin-provisioner.yaml
-rw-r--r-- 1 root root 5852 Sep 14 04:49 csi-rbdplugin.yaml

将以上获取的信息写入 csi-config-map.yaml:

---
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[
{
"clusterID": "154c3d17-a9af-4f52-b83e-0fddd5db6e1b",
"monitors": [
"172.16.1.21:6789",
"172.15.1.22:6789",
"172.16.1.23:6789"
]
}
]
metadata:
name: ceph-csi-config

创建一个新的 namespace 专门用来部署 ceph-csi:

$ kubectl create ns ceph-csi

将此 Configmap 存储到 Kubernetes 集群中:

$ kubectl -n ceph-csi apply -f csi-config-map.yaml

新建 Secret

使用创建的 kubernetes 用户 ID 和 cephx 密钥生成 Secret:

cat <<EOF > csi-rbd-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: ceph-csi
stringData:
userID: kubernetes
userKey: AQBnz11fclrxChAAf8TFw8ROzmr8ifftAHQbTw==
EOF

部署 Secret:

$ kubectl apply -f csi-rbd-secret.yaml

RBAC 授权

将所有配置清单中的 namespace 改成 ceph-csi:

$ sed -i "s/namespace: default/namespace: ceph-csi/g" $(grep -rl "namespace: default" ./)
$ sed -i -e "/^kind: ServiceAccount/{N;N;a\ namespace: ceph-csi # 输入到这里的时候需要按一下回车键,在下一行继续输入
}" $(egrep -rl "^kind: ServiceAccount" ./)

创建必须的 ServiceAccount 和 RBAC ClusterRole/ClusterRoleBinding 资源对象:

$ kubectl create -f csi-provisioner-rbac.yaml
$ kubectl create -f csi-nodeplugin-rbac.yaml

创建 PodSecurityPolicy:

$ kubectl create -f csi-provisioner-psp.yaml
$ kubectl create -f csi-nodeplugin-psp.yaml

部署 CSI sidecar

将 csi-rbdplugin-provisioner.yaml 和 csi-rbdplugin.yaml 中的 kms 部分配置注释掉:

部署 csi-rbdplugin-provisioner:

$ kubectl -n ceph-csi create -f csi-rbdplugin-provisioner.yaml

这里面包含了 6 个 Sidecar 容器,包括 external-provisioner、external-attacher、csi-resizer 和 csi-rbdplugin。

部署 RBD CSI driver

最后部署 RBD CSI Driver:

$ kubectl -n ceph-csi create -f csi-rbdplugin.yaml

Pod 中包含两个容器:CSI node-driver-registrar 和 CSI RBD driver。

创建 Storageclass

$ cat <<EOF > storageclass.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: 154c3d17-a9af-4f52-b83e-0fddd5db6e1b
pool: kubernetes
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi
csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi
csi.storage.k8s.io/fstype: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard
EOF
  • 这里的 clusterID 对应之前步骤中的 fsid。
  • imageFeatures 用来确定创建的 image 特征,如果不指定,就会使用 RBD 内核中的特征列表,但 Linux 不一定支持所有特征,所以这里需要限制一下。

3. 试用 ceph-csi

Kubernetes 通过 PersistentVolume 子系统为用户和管理员提供了一组 API,将存储如何供应的细节从其如何被使用中抽象出来,其中 PV(PersistentVolume) 是实际的存储,PVC(PersistentVolumeClaim) 是用户对存储的请求。

下面通过官方仓库的示例来演示如何使用 ceph-csi。

先进入 ceph-csi 项目的 example/rbd 目录,然后直接创建 PVC:

$ kubectl apply -f pvc.yaml

查看 PVC 和申请成功的 PV:

$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
rbd-pvc Bound pvc-44b89f0e-4efd-4396-9316-10a04d289d7f 1Gi RWO csi-rbd-sc 8m21s $ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-44b89f0e-4efd-4396-9316-10a04d289d7f 1Gi RWO Delete Bound default/rbd-pvc csi-rbd-sc 8m18s

再创建示例 Pod:

$ kubectl apply -f pod.yaml

进入 Pod 里面测试读写数据:

$ kubectl exec -it csi-rbd-demo-pod bash
root@csi-rbd-demo-pod:/# cd /var/lib/www/
root@csi-rbd-demo-pod:/var/lib/www# ls -l
total 4
drwxrwxrwx 3 root root 4096 Sep 14 09:09 html
root@csi-rbd-demo-pod:/var/lib/www# echo "https://fuckcloudnative.io" > sealos.txt
root@csi-rbd-demo-pod:/var/lib/www# cat sealos.txt
https://fuckcloudnative.io

列出 kubernetes pool 中的 rbd images:

$ rbd ls -p kubernetes
csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6

查看该 image 的特征:

$ rbd info csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6 -p kubernetes
rbd image 'csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6':
size 1 GiB in 256 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 8da46585bb36
block_name_prefix: rbd_data.8da46585bb36
format: 2
features: layering
op_features:
flags:
create_timestamp: Mon Sep 14 09:08:27 2020
access_timestamp: Mon Sep 14 09:08:27 2020
modify_timestamp: Mon Sep 14 09:08:27 2020

可以看到对 image 的特征限制生效了,这里只有 layering。

实际上这个 image 会被挂载到 node 中作为一个块设备,到运行 Pod 的 Node 上可以通过 rbd 命令查看映射信息:

$ rbd showmapped
id pool namespace image snap device
0 kubernetes csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6 - /dev/rbd0

在 node 上查看挂载信息:

$ lsblk -l|grep rbd
rbd0 252:32 0 1G 0 disk /var/lib/kubelet/pods/15179e76-e06e-4c0e-91dc-e6ecf2119f4b/volumes/kubernetes.io~csi/pvc-44b89f0e-4efd-4396-9316-10a04d289d7f/mount

在 容器中查看挂载信息:

$ kubectl exec -it csi-rbd-demo-pod bash
root@csi-rbd-demo-pod:/# lsblk -l|grep rbd
rbd0 252:32 0 1G 0 disk /var/lib/www/html

一切正常!

4. 试用卷快照功能

要想使用卷快照(Volume Snapshot)功能,首先需要在 apiserver 的 --feature-gates 参数中加上 VolumeSnapshotDataSource=true,不过从 Kubernetes 1.17 开始这个特性已经默认开启了,不需要再手动添加。

卷快照功能不是 Kubernetes 的核心 API,它是通过 CRD 来实现的,同时还需要一个卷快照控制器(需要单独部署)。卷快照控制器和 CRD 独立于特定的 CSI 驱动,无论 Kubernetes 集群中部署了多少 CSI 驱动,每个集群都必须只运行一个卷快照控制器和一组卷快照 CRD。

卷快照 CRD 和控制器都在这个项目中:https://github.com/kubernetes-csi/external-snapshotter。

将 external-snapshotter 项目拉取到本地:

$ git clone --depth 1 https://github.com/kubernetes-csi/external-snapshotter

创建卷快照 CRD:

$ cd external-snapshotter
$ kubectl create -f client/config/crd

将卷快照部署清单中的 namespace 改成 kube-system:

$ sed -i "s/namespace: default/namespace: kube-system/g" $(grep -rl "namespace: default" deploy/kubernetes/snapshot-controller)

部署卷快照控制器:

$ kubectl create -f deploy/kubernetes/snapshot-controller

现在可以回到 ceph-csi 的 examples/rbd 目录试用卷快照功能了。先将 snapshotclass.yaml 中的 clusterID 改成 Ceph 的集群 ID:

---
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
name: csi-rbdplugin-snapclass
driver: rbd.csi.ceph.com
parameters:
# String representing a Ceph cluster to provision storage from.
# Should be unique across all Ceph clusters in use for provisioning,
# cannot be greater than 36 bytes in length, and should remain immutable for
# the lifetime of the StorageClass in use.
# Ensure to create an entry in the configmap named ceph-csi-config, based on
# csi-config-map-sample.yaml, to accompany the string chosen to
# represent the Ceph cluster in clusterID below
clusterID: 154c3d17-a9af-4f52-b83e-0fddd5db6e1b # Prefix to use for naming RBD snapshots.
# If omitted, defaults to "csi-snap-".
# snapshotNamePrefix: "foo-bar-" csi.storage.k8s.io/snapshotter-secret-name: csi-rbd-secret
csi.storage.k8s.io/snapshotter-secret-namespace: ceph-csi
deletionPolicy: Delete

然后创建 snapshot class:

$ kubectl create -f snapshotclass.yaml

查看 snapshot class 是否创建成功:

$ kubectl get volumesnapshotclass
NAME DRIVER DELETIONPOLICY AGE
csi-rbdplugin-snapclass rbd.csi.ceph.com Delete 2s

还记得上一节创建的 rbd-pvc 吗,现在我们可以直接创建该 PVC 的快照来进行备份了,卷快照的配置清单如下:

---
apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshot
metadata:
name: rbd-pvc-snapshot
spec:
volumeSnapshotClassName: csi-rbdplugin-snapclass
source:
persistentVolumeClaimName: rbd-pvc

通过该配置清单创建 PVC rbd-pvc 的快照:

$ kubectl create -f snapshot.yaml

验证快照是否创建成功:

$ kubectl get volumesnapshot
NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE
rbd-pvc-snapshot false rbd-pvc csi-rbdplugin-snapclass snapcontent-9011a05f-dc34-480d-854e-814b0b1b245d 16s

在 Ceph 集群中可以看到新创建快照的 image 名称:

$ rbd ls -p kubernetes
csi-snap-4da66c2e-f707-11ea-ba22-aaa4b0fc674d
csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6

查看新创建的快照信息:

$ rbd snap ls csi-snap-4da66c2e-f707-11ea-ba22-aaa4b0fc674d -p kubernetes
SNAPID NAME SIZE PROTECTED TIMESTAMP
9 csi-snap-4da66c2e-f707-11ea-ba22-aaa4b0fc674d 1 GiB Tue Sep 15 03:55:34 2020

快照也是 pool 中的一个 image,所以可以用常规的命令查看快照的详细信息:

$ rbd info csi-snap-4da66c2e-f707-11ea-ba22-aaa4b0fc674d -p kubernetes
rbd image 'csi-snap-4da66c2e-f707-11ea-ba22-aaa4b0fc674d':
size 1 GiB in 256 objects
order 22 (4 MiB objects)
snapshot_count: 1
id: 66cdcd259693
block_name_prefix: rbd_data.66cdcd259693
format: 2
features: layering, deep-flatten, operations
op_features: clone-child
flags:
create_timestamp: Tue Sep 15 03:55:33 2020
access_timestamp: Tue Sep 15 03:55:33 2020
modify_timestamp: Tue Sep 15 03:55:33 2020
parent: kubernetes/csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6@33d02b70-bc82-4def-afd3-b7a40567a8db
overlap: 1 GiB

如果想恢复快照,可以直接基于快照创建 PVC,配置清单内容如下:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc-restore
spec:
storageClassName: csi-rbd-sc
dataSource:
name: rbd-pvc-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi

创建 PVC:

$ kubectl apply -f pvc-restore.yaml

查看 PVC 和申请成功的 PV:

$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
rbd-pvc Bound pvc-44b89f0e-4efd-4396-9316-10a04d289d7f 1Gi RWO csi-rbd-sc 22h
rbd-pvc-restore Bound pvc-e0ef4f6a-03dc-4c3b-a9c2-db03baf35ab0 1Gi RWO csi-rbd-sc 2m45s $ kubectl get pv
pvc-44b89f0e-4efd-4396-9316-10a04d289d7f 1Gi RWO Delete Bound default/rbd-pvc csi-rbd-sc 22h
pvc-e0ef4f6a-03dc-4c3b-a9c2-db03baf35ab0 1Gi RWO Delete Bound default/rbd-pvc-restore csi-rbd-sc 2m14s

可以看到 PV 申请成功了,对应到 Ceph 里面就多了一个 RBD image:

$ rbd ls -p kubernetes
csi-snap-4da66c2e-f707-11ea-ba22-aaa4b0fc674d
csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6
csi-vol-e32d46bd-f722-11ea-a3fa-ee21730897e6

创建一个新 Pod,使用该 PV 作为持久化存储:

$ kubectl apply -f pod-restore.yaml

待 Pod 运行成功后,到运行 Pod 的 Node 上可以通过 rbd 命令查看映射信息:

$ rbd showmapped
id pool namespace image snap device
0 kubernetes csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6 - /dev/rbd0
1 kubernetes csi-vol-e32d46bd-f722-11ea-a3fa-ee21730897e6 - /dev/rbd1

5. 清理

结束对示例应用的体验后,就可以使用下面的命令来完成应用的删除和清理了:

$ kubectl delete -f pod-restore.yaml
$ kubectl delete -f pvc-restore.yaml
$ kubectl delete -f snapshot.yaml
$ kubectl delete -f snapshotclass.yaml
$ kubectl delete -f pod.yaml
$ kubectl delete -f pvc.yaml

Kubernetes 1.18.2 1.17.5 1.16.9 1.15.12离线安装包发布地址http://store.lameleg.com ,欢迎体验。 使用了最新的sealos v3.3.6版本。 作了主机名解析配置优化,lvscare 挂载/lib/module解决开机启动ipvs加载问题, 修复lvscare社区netlink与3.10内核不兼容问题,sealos生成百年证书等特性。更多特性 https://github.com/fanux/sealos 。欢迎扫描下方的二维码加入钉钉群 ,钉钉群已经集成sealos的机器人实时可以看到sealos的动态。

Kubernetes 使用 ceph-csi 消费 RBD 作为持久化存储的更多相关文章

  1. SUSE CaaS Platform 4 - 使用 Ceph RBD 作为持久存储 (静态)

    1.所有节点安装 # zypper -n in ceph-common 复制 ceph.conf 到 worker 节点上 # scp admin:/etc/ceph/ceph.conf /etc/c ...

  2. Kubernetes 持久化存储是个难题,解决方案有哪些?\n

    像Kubernetes 这样的容器编排工具正在彻底改变应用程序的开发和部署方式.随着微服务架构的兴起,以及基础架构与应用程序逻辑从开发人员的角度解耦,开发人员越来越关注构建软件和交付价值. Kuber ...

  3. 使用Ceph集群作为Kubernetes的动态分配持久化存储(转)

    使用Docker快速部署Ceph集群 , 然后使用这个Ceph集群作为Kubernetes的动态分配持久化存储. Kubernetes集群要使用Ceph集群需要在每个Kubernetes节点上安装ce ...

  4. Kubernetes配置Ceph RBD StorageClass

    1. 在Ceph上为Kubernetes创建一个存储池 # ceph osd pool create k8s 2. 创建k8s用户 # ceph auth get-or-create client.k ...

  5. [k8s] k8s基于csi使用rbd存储

    描述 ceph-csi扩展各种存储类型的卷的管理能力,实现第三方存储ceph的各种操作能力与k8s存储系统的结合.通过 ceph-csi 使用 ceph rbd块设备,它动态地提供rbd以支持 Kub ...

  6. kubernetes使用ceph

    一.有一个ceph cluster,假设已经准备好了,文档网上一大堆 二.开始集成ceph和kuberntes 2.1 禁用rbd features rbd image有4个 features,lay ...

  7. Kubernetes 学习(十)Kubernetes 容器持久化存储

    0. 前言 最近在学习张磊老师的 深入剖析Kubernetes 系列课程,最近学到了 Kubernetes 容器持久化存储部分 现对这一部分的相关学习和体会做一下整理,内容参考 深入剖析Kuberne ...

  8. 【原创】K8S使用ceph-csi持久化存储之RBD

    一.集群和组件版本 K8S集群:1.17.3+Ceph集群:Nautilus(stables)Ceph-CSI:release-v3.1snapshotter-controller:release-2 ...

  9. Kubernetes之持久化存储

    转载自 https://blog.csdn.net/dkfajsldfsdfsd/article/details/81319735 ConfigMap.Secret.emptyDir.hostPath ...

随机推荐

  1. [LeetCode]647. 回文子串(DP)

    ###题目 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串. 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串. 示例 1: 输入: "abc&q ...

  2. 常见重构技巧 - 5种方式去除多余的if else

    常见重构技巧 - 去除多余的if else 最为常见的是代码中使用很多的if/else,或者switch/case:如何重构呢?方法特别多,本文带你学习其中的技巧. 常见重构技巧 - 去除多余的if ...

  3. docker 部署 zabbix

    docker部署zabbix   我相信大家都已经会再物理机上跑zabbix并且监控了,那么有没有想过在docker中跑zabbix?下面咱们来看看如何在docker中搭建zabbix并且监控 部署环 ...

  4. Redis报错“ OOM command not allowed when used memory > 'maxmemory' ”

    生产环境上遇到这个问题,控制台不停打印 "OOM command not allowed when used memory > 'maxmemory' "; 起初不知道是什么 ...

  5. 听我的,看完这30道MySQL基础题再去面试

    可以微信搜索公众号「 后端技术学堂 」回复「1024」获取50本计算机电子书,回复「进群」拉你进读者技术交流群,文章每周持续更新,我们下期见! 一个典型的互联网产品架构包含接入层.逻辑处理层以及存储层 ...

  6. java进阶(19)--异常处理机制

    一.基本概念 1.异常的作用: java将异常信息打印至控制台,供程序修改,增加其健壮性. int c=1/0;    //将抛出 java.lang.ArithmeticException 2.异常 ...

  7. MySQL存储引擎入门介绍

    什么是MySQL? MySQL 是一种关系型数据库,在Java企业级开发中非常常用,因为 MySQL 是开源免费的,并且方便扩展.阿里巴巴数据库系统也大量用到了 MySQL,因此它的稳定性是有保障的. ...

  8. 最全总结 | 聊聊 Python 数据处理全家桶(Memcached篇)

    1. 前言 本篇文章继续继续另外一种比较常用的数据存储方式:Memcached Memcached:一款高性能分布式内存对象缓存系统,通过 内存缓存,以减少数据库的读取,从而分担数据库的压力,进而提高 ...

  9. 第一个随笔 Just For Test, Nothing Else

    第一个随笔 Just For Test, Nothing Else 注册了第一个博客,希望以后能添加点什么吧

  10. 025 01 Android 零基础入门 01 Java基础语法 03 Java运算符 05 if条件结构

    025 01 Android 零基础入门 01 Java基础语法 03 Java运算符 05 if条件结构 本文知识点:Java中的if条件结构语句 关系运算符回顾 生活中根据条件进行判断采取不同操作 ...