Ceph-CSI 对接 K8s:RBD 动态持久化存储

概览

节点概览 → ceph 集群配置 → k8s 集群配置(ceph-csi)→ 挂载测试


节点 主机IP 系统 磁盘 配置 版本
k8s-master01 192.168.3.93 centos8s-mini 测试:16G 生产环境请酌情 2C4G 1.23.6(最新)
k8s-master02 192.168.3.91 centos8s-mini 测试:16G 生产环境请酌情 2C4G 1.23.6(最新)
K8s-master03 192.168.3.187 centos8s-mini 测试:16G 生产环境请酌情 2C4G 1.23.6(最新)
K8s-node01 192.168.3.95 centos8s-mini 测试:16G 生产环境请酌情 2C4G 1.23.6(最新)
ceph01 192.168.3.164 ubuntu18.4-mini 测试:16+100G 生产环境请酌情 2C4G 16.2.9
ceph02 192.168.3.167 ubuntu18.4-mini 测试:16+100G 生产环境请酌情 2C4G 16.2.9
ceph03 192.168.3.168 ubuntu18.4-mini 测试:16+100G 生产环境请酌情 2C4G 16.2.9

ceph集群配置

创建名为cephrbd01的pool

1
ceph osd pool create cephrbd01 32 32

初始化 pool(application 标记为 rbd)

1
rbd pool init cephrbd01

创建并打印账户auth,授予kubernetes01账号对应的权限

1
ceph auth get-or-create client.kubernetes01 mon 'profile rbd' osd 'profile rbd pool=cephrbd01' mgr 'profile rbd pool=cephrbd01'

image-20220730142906106

创建rbd的image块,大小为5G

1
rbd create -p cephrbd01 --image-feature layering kubernetes01-rbd-volume.img --size 5G

(这个 img 主要是手动验证 pool 可用;后面 CSI 动态供给时,卷是 provisioner 自动创建的,并不依赖它)

我们可以登录后台查看我们创建的img块(确认无误后,ceph集群配置完成)

image-20220730143038322

K8s集群配置

每个节点安装ceph-common

1
yum install ceph-common #此处ceph-common版本尽量和ceph集群保持一致

image-20220728223737545

会用到一些官方的yaml模版,我们需要去github下载对应的yaml

1
https://github.com/ceph/ceph-csi # 下载资源

image-20220728224003471

image-20220730143306605

我这会多出来部分的yaml,后面会说

此处我为了环境隔离,选择新建一个namespaces来做

1
vim cephrbd.namespaces.yaml
1
2
3
4
5
6
7
apiVersion: v1
#namespace固定写法
kind: Namespace
metadata:
name: cephrbd01
labels:
name: cephrbd01
1
kubectl apply -f cephrbd.namespaces.yaml #创建namespaces

查看刚才创建的namespace

1
kubectl get ns -A

image-20220730143608185

修改csi-config-map.yaml,把你的ceph集群信息写进去

1
vim csi-config-map.yaml #clusterID可以通过ceph -s 来查询,ceph的mon有多少个就写多少个,我这里有三个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
[
{
"clusterID": "0564e29a-de74-11ec-b648-000c2929a45f",
"monitors": [
"192.168.3.164:6789",
"192.168.3.167:6789",
"192.168.3.168:6789"
]
}
]
metadata:
name: ceph-csi-config
namespace: cephrbd01
1
kubectl apply -f csi-config-map.yaml #发布configmap,发布完我们可以查询一下

image-20220730143922254

配置密钥

1
#我们在ceph集群配置的时候已经把密钥打印出来了,也可以后续通过 ceph auth list 查询

image-20220730144035884

修改secret

1
vim csi-rbd-secret.yaml # 修改secret
1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: Secret
metadata:
name: csi-rbd-secret
namespace: cephrbd01
stringData:
userID: kubernetes01 # 对应前面创建的 client.kubernetes01(不带 client. 前缀)
userKey: AQCLz+Ri+s/ZIRAAiAc+MV4Y40uGQ1FsJr7bUQ==
encryptionPassphrase: test_passphrase
1
kubectl apply -f csi-rbd-secret.yaml #发布secret

image-20220730144456840

创建provisioner插件的rbac

1
kubectl apply -f csi-provisioner-rbac.yaml # 发布provisionerrbac,namespaces要修改成自己需要的

image-20220730144702331

image-20220730144622872

创建nodeplugin插件的rbac

1
kubectl apply -f csi-nodeplugin-rbac.yaml # 发布nodeplugin-rbac

image-20220730144827615

创建ceph-csi-encryption-kms-config

1
vim csi-kms-config-map.yaml
1
2
3
4
5
6
7
8
apiVersion: v1
kind: ConfigMap
data:
config.json: |-
{}
metadata:
name: ceph-csi-encryption-kms-config
namespace: cephrbd01
1
kubectl apply -f csi-kms-config-map.yaml

image-20220730150103712

创建ceph-config-map

1
vim ceph-config-map.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: ConfigMap
data:
ceph.conf: |
# minimal ceph.conf for 0564e29a-de74-11ec-b648-000c2929a45f
[global]
fsid = 0564e29a-de74-11ec-b648-000c2929a45f
mon_host = [v2:192.168.3.164:3300/0,v1:192.168.3.164:6789/0] [v2:192.168.3.167:3300/0,v1:192.168.3.167:6789/0] [v2:192.168.3.168:3300/0,v1:192.168.3.168:6789/0]
# keyring is a required key and its value should be empty
keyring: |
metadata:
name: ceph-config
namespace: cephrbd01
1
kubectl apply -f ceph-config-map.yaml

image-20220730151249411

有了上面两个之后再去创建csi-rbdplugin-provisioner

创建csi-rbdplugin-provisioner插件

此处注意⚠️⚠️⚠

csi-rbdplugin-provisioner插件是以pod形式存在集群里的,所以就会涉及image pull不下来的问题,建议挂代理后把需要的 image 都导入本地 Harbor

image-20220730145223398

image-20220730145258580

1
kubectl apply -f csi-rbdplugin-provisioner.yaml # 发布nodeplugin插件

image-20220730151648115

创建csi-rbdplugin插件

1
kubectl apply -f csi-rbdplugin.yaml #发布rbdplugin.插件

image-20220730152055886

挂载测试

创建StorageClass

1
vim storage.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
namespace: cephrbd01
provisioner: rbd.csi.ceph.com
parameters:
clusterID: 0564e29a-de74-11ec-b648-000c2929a45f
pool: cephrbd01 #之前创建pool的名称
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: cephrbd01
csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
csi.storage.k8s.io/controller-expand-secret-namespace: cephrbd01
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: cephrbd01
csi.storage.k8s.io/fstype: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard

注意:官方示例里 secret 的 namespace 写的都是 default;我的 csi-rbd-secret 建在 cephrbd01,这里必须改成一致,否则 provisioner 找不到密钥,PVC 会一直 Pending。

1
kubectl apply -f storage.yaml

image-20220730152508694

创建pvc

1
vim pvc.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
namespace: cephrbd01
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem #指定使用文件格式
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
1
2
kubectl apply -f pvc.yaml # 发布后查询,已经Bound
kubectl get pvc -n cephrbd01

image-20220730163837405

创建pod

1
vim pod.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Pod
metadata:
name: ceph-pod
namespace: cephrbd01
spec:
containers:
- name: test-pod
image: busybox:1.24
command: ["sleep", "60000"]
volumeMounts:
- name: pvc
mountPath: /usr/share/busybox
readOnly: false
volumes:
- name: pvc
persistentVolumeClaim:
claimName: rbd-pvc
1
2
kubectl apply -f pod.yaml # 发布
kubectl get pod -n cephrbd01 -o wide -w # 盯着起

image-20220730164212262

查看pod

1
kubectl exec -it ceph-pod  -n cephrbd01 /bin/sh # 进入pod

image-20220730164410329

image-20220730164526693