译文链接:https:///posts/kubernetes-storage-using-ceph-rbd/
本文详细介绍了如何在 Kubernetes 集群中部署ceph-csi (v3),并使用RBD 作为 1.0.0 存储。
需要的环境参考下图:
本文使用的环境版本信息:
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 池
创建一个新的 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==
后面的密钥需要通过下面的命令获取:
$ 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的最新发布分支(v3.1.0):
$ git clone --depth 1 --branch v3.1.0 https:///github.com/ceph/ceph-csi
修改配置地图
获取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
创建一个新的命名空间用于部署 ceph-csi:
$ kubectl create ns ceph-csi
将配置映射存储到 Kubernetes 集群中:
$ kubectl -n ceph-csi apply -f csi-config-map.yaml
新建秘密
使用创建的 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
部署秘密:
$ 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 边车
将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 驱动程序
最后部署RBD CSI Driver :
$ kubectl -n ceph-csi create -f csi-rbdplugin.yaml
Pod中包含两个容器:CSI node-driver-registrar 和CSI RBD driver 。
创建存储类
$ 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 确定创建的特征,如果不指定,就要使用 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://" > sealos.txt
root@csi-rbd-demo-pod:/var/lib/www# cat sealos.txt
https://
kubernetespool 中的rbd images :
$ rbd ls -p kubernetes
csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6
查看图片的特征:
$ 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
可以看到对图片的特征限制生效了,这里只有layering 。
设备image 会被挂到节点中,作为一个块设备,运行 Pod 的上可以通过rbd 命令载查看这个节点的信息:
$ rbd showmapped
id pool namespace image snap device
0 kubernetes csi-vol-d9d011f9-f669-11ea-a3fa-ee21730897e6 - /dev/rbd0
在节点上查看挂载信息:
$ 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 )功能,首先需要在的参数中,不过从Kubernetes 1.17 添加默认开启,不需要再手动设置了。apiserver --feature-gates VolumeSnapshotDataSource=true
卷的功能,不管是不是Kubernetes都需要来实现,它是通过实现同时一个卷的API,还是CRD 一个卷的语音(单卷)部署在某个特定的CSI和CRD 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
将卷部署清单中的命名空间改成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 的团体 ID ceph-csi :examples/rbd snapshotclass.yaml clusterID
---
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
然后创建快照类:
$ kubectl create -f snapshotclass.yaml
查看快照类是否创建成功:
$ 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
通过该配置清单创建PVCrbd-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 图像:
$ 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 上可以通过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
|