k8s 使用rbd存储
k8s使用rbd作为后端存储
-
主要介绍静态创建rbd,动态创建rbd
-
pv使用rbd存储
1、ceph集群创建rbd
- 因为是静态创建pv,有了这个rbd后,pv指定这个rbd即可
ceph osd pool create pool01
ceph osd pool application enable pool01 rbd
rbd pool init pool01
rbd create pool01/test --size 5Gi --image-format 2 --image-feature layering
[root@ceph01 ~]# rbd info pool01/test
rbd image 'test':
size 5 GiB in 1280 objects
order 22 (4 MiB objects)
snapshot_count: 0
id: 121b748877201
block_name_prefix: rbd_data.121b748877201
format: 2
features: layering
op_features:
flags:
create_timestamp: Tue Apr 7 20:57:32 2026
access_timestamp: Tue Apr 7 20:57:32 2026
modify_timestamp: Tue Apr 7 20:57:32 2026
2、k8s编写yaml文件
-
这个使用的是filesystem,就是将块设备格式化后,挂载到一个目录上面
-
也可以使用block,容器里面的参数就需要改成 volumeDevices 裸设备
[root@master01 pv]# cat b1-rbd.yml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: rbd-b1
name: rbd-b1
spec:
nodeName: master02 # 调度在02上
volumes:
- name: rbd
rbd: # 使用rbd作为后端存储
fsType: xfs # 格式化了这个块设备
keyring: /root/admin.keyring # 密钥文件
monitors: # 我是单节点的ceph
- 192.168.50.30:6789
pool: pool01 # rbd存储池
image: test # rbd存储池中创建的块
user: admin # 用户
readOnly: false # 读写都可以
containers:
- image: nginx:1.25
name: rbd-b1
resources: {}
volumeMounts: # rbd格式化后,作为目录挂载
- name: rbd
mountPath: /usr/share/nginx/html
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
1、rbd被挂载到容器内部(查看挂载)
- 发现rbd0直接挂载了,因为上面的配置写了格式化这个rbd0
[root@master01 pv]# kubectl exec -ti rbd-b1 -- /bin/bash
# rbd0挂载到容器这个目录下了
root@rbd-b1:/# df -hT | grep rbd
/dev/rbd0 xfs 5.0G 69M 5.0G 2% /usr/share/nginx/html
2、修改首页文件内容
root@rbd-b1:/# echo 123 > /usr/share/nginx/html/index.html
- 访问容器
[root@master01 pv]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rbd-b1 1/1 Running 0 6m14s 10.244.59.205 master02 <none> <none>
[root@master01 pv]# curl 10.244.59.205
123
- 将pod删除后,然后再次创建,看这个首页文件内容是否还存在
[root@master01 pv]# kubectl delete -f b1-rbd.yml --force
[root@master01 pv]# kubectl apply -f b1-rbd.yml
[root@master01 pv]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rbd-b1 1/1 Running 0 10s 10.244.59.206 master02 <none> <none>
[root@master01 pv]# curl 10.244.59.206
123
- 发现首页文件内容还是存在的,这个存储的数据的位置在rbd块中
3、pv使用rbd
上面这个写法,还需要了解这个ceph中一些配置,不同存储不同的写法,屏蔽掉底层的写法,直接使用pv进行绑定rbd,创建一个pvc绑定pv,pod直接使用pvc
1、创建pvc和pv
# pvc配置文件
[root@master01 pv]# cat rbd-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteOnce
volumeMode: Block # 默认是filesystem ,block的话就是不格式化,不挂载目录,就是将存储当成裸设备
resources:
requests:
storage: 2Gi
# pv配置文件
apiVersion: v1
kind: PersistentVolume
metadata:
name: rbdpv
spec:
capacity:
storage: 2Gi
volumeMode: Block # 裸设备挂载
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
mountOptions: # 这个是挂载的选项
- hard
- nfsvers=4.1
rbd:
fsType: xfs
image: test # rbd存储池中的test块
keyring: /etc/ceph/ceph.client.admin.keyring # 密钥文件
monitors:
- 192.168.50.30
pool: pool01 # 存储池
readOnly: false
user: admin # ceph用户为admin
# pv和pvc绑定在一起了
[root@master01 pv]# kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/rbdpv 2Gi RWO Recycle Bound default/myclaim 2m1s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/myclaim Bound rbdpv 2Gi RWO 4m47s
2、使用pvc
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pvc-pod
name: pvc-pod
spec:
nodeName: master02 # 指定调度的节点,我将ceph的一些文件传递到这个节点上了
volumes:
- name: rbd
persistentVolumeClaim:
claimName: myclaim
readOnly: false
containers:
- image: busybox
imagePullPolicy: IfNotPresent
name: pvc-pod
command:
- /bin/sh
- -c
- "sleep 3600"
volumeDevices: # 使用的是块设备,所以是这个字段,而不是目录挂载参数
- devicePath: /dev/rbd1 # 映射到容器里面块设备的名字是rbd1
name: rbd
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
-
创建好后,会有哪些操作呢?
-
我的ceph一些文件传递到master02上了,就可以使用ceph集群了
-
将rbd中的test这个块映射到容器里面了
-
3、进入容器查看块设备
# 说明rbd1已经在容器内部了
/ # fdisk /dev/rbd1
4、rbd原理和绑定pv
-
原理就是
-
rbd存储池中创建块设备
-
pv进行绑定,pvc绑定pv
-
pod绑定pvc,表现的形式是一个裸设备在容器内部,或者目录挂载也可以的
-
-
rbd和pv的绑定(volumeMode)
-
filesystem和block参数
-
支持文件系统,最开始的实验就是文件系统类型的,块设备被格式化,挂载到容器目录上面去了
-
下面的是裸设备挂载,直接映射到容器里面是一个裸设备
-
只是容器在配置挂载的时候选项不同而已
-
volumeDevices 块设备挂载
-
volumeMounts 目录挂载
-
-
4、动态制备(ceph-csi rbd)
| 组件 | 角色 | 作用 |
|---|---|---|
| PVC | 用户的租房申请 | 我要 10G 存储 |
| StorageClass(SC) | 租房中介 / 规则 | 找谁租、什么配置 |
| Ceph-CSI | 真正的房东 / 工人 | 真正去 Ceph 里创建磁盘 |
| PV | 真实的房子 / 磁盘 | 最终分配出来的存储 |
-
要创建哪些资源
-
创建一个ceph-csi的pod,配置rbac,secret等等,监控pvc的一些行为
-
创建一个storageClass,指向这个ceph-csi,是k8s和ceph集群之间的翻译器
-
里面定义了从ceph集群自动创建rbd
-
让pod动态的申请pvc,pv
-
非常的重要这个存储类
-
-

-
自动创建pv原理
-
创建了一个pvc,使用的大小为5G,先去找storageClass(存储类)
-
storageClass 找对应的驱动,ceph-csi
-
ceph-csi插件使用(clusterid,pool,secret)连接ceph集群
-
在存储池中创建块设备(image)
-
自动生成pv,绑定pvc
-
pod挂载pvc,实际后端使用的存储为rbd
-
1、下载ceph-csi项目
# 这个是比较老的版本的ceph-csi
[root@master01 pv]# git clone https://gitee.com/yftyxa/ceph-csi.git
# 里面有很多的文件,rbd,cephfs都可以实现的
[root@master01 deploy]# pwd
/root/pv/ceph-csi/deploy
[root@master01 deploy]# ls
ceph-conf.yaml cephfs Makefile rbd service-monitor.yaml
cephcsi csi-config-map-sample.yaml nfs scc.yaml
2、部署ceph-csi
- 创建一个csi的命名空间
[root@master01 deploy]# kubectl create ns csi
- 修改第一个文件csi-rbdplugin-provisioner.yaml
[root@master01 kubernetes]# vim csi-rbdplugin-provisioner.yaml
# 改成false 有2处需要改
- "--extra-create-metadata=false"
- 修改第二个文件csi-config-map.yaml,配置ceph-csi用于连接ceph monitor的配置文件
[root@master01 kubernetes]# cat csi-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: "ceph-csi-config"
data:
config.json: |-
[
{
"clusterID": "391a3056-24f0-11f1-abc4-000c2903217e",
"monitors": ["192.168.50.30"]
}
]
-
上面的clusterID 可以 通过 ceph -s 查询到id
-
修改第三个文件csidriver.yaml
[root@master01 kubernetes]# cat csidriver.yaml
#
# /!\ DO NOT MODIFY THIS FILE
#
# This file has been automatically generated by Ceph-CSI yamlgen.
# The source for the contents can be found in the api/deploy directory, make
# your modifications there.
#
---
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: "rbd.csi.ceph.com"
spec:
attachRequired: true
podInfoOnMount: false
#seLinuxMount: true # 注释这个字段,不识别这个字段
fsGroupPolicy: File
- 编写一个configmap,ceph-csi需要一个cm,定义一个空的即可
# 需要有这个才行,否则后面会不成功的
[root@master01 kubernetes]# cat csi-kms-config-map.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ceph-csi-encryption-kms-config
data:
config-json: |-
{}
3、为ceph-csi生成ceph认证文件
- ceph的管理员用户的keyring配置成secret
[root@ceph01 ceph]# cat ceph.client.admin.keyring
[client.admin]
key = AQBRPL5pKo68KhAAnvurJfOM19nOS5sOAPzO1g==
caps mds = "allow *"
caps mgr = "allow *"
caps mon = "allow *"
caps osd = "allow *"
# 只需要这个key部分即可
# 编写一个csi-secret.yml
[root@master01 kubernetes]# cat csi-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: csi-secret
stringData:
userID: admin
userKey: AQBRPL5pKo68KhAAnvurJfOM19nOS5sOAPzO1g==
adminID: admin
adminKey: AQBRPL5pKo68KhAAnvurJfOM19nOS5sOAPzO1g==
- ceph-csi还要一个ceph.conf文件,位于deploy目录下,ceph-conf.yaml,不需要修改,默认创建即可
4、替换所有的ns
[root@master01 kubernetes]# sed -i "s/namespace: default/namespace: csi/g" *.yaml
5、部署
# /root/pv/ceph-csi/deploy/rbd/kubernetes/下面的所有yaml文件部署
kubectl apply -f . -n csi
# 部署ceph-conf.yml文件,位于deploy下面
[root@master01 kubernetes]# kubectl get pod -n csi
[root@master01 kubernetes]# kubectl get pod -n csi
NAME READY STATUS RESTARTS AGE
csi-rbdplugin-66t6n 3/3 Running 0 19s
csi-rbdplugin-7wknj 3/3 Running 0 19s
csi-rbdplugin-provisioner-648469fc58-77vcb 7/7 Running 0 19s
csi-rbdplugin-provisioner-648469fc58-swvwz 7/7 Running 0 19s
# 如果你的worker节点数量少于3个的话,是需要将 csi-rbdplugin-provisioner.yaml这个文件里面的replicas改小一点的。我改成了2个
5、使用动态制备
1、创建storageClass
[root@master01 rbd]# pwd
/root/pv/ceph-csi/examples/rbd
[root@master01 rbd]# grep -Ev "\s*#|^$" storageclass.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
clusterID: <cluster-id>
pool: <rbd-pool-name>
imageFeatures: "layering"
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
csi.storage.k8s.io/controller-expand-secret-namespace: default
csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
csi.storage.k8s.io/node-stage-secret-namespace: default
csi.storage.k8s.io/fstype: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard
- 将这个里面的内容复制出来
vim q-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
provisioner: rbd.csi.ceph.com # 指向了ceph-csi,与ceph-csi进行了绑定
parameters:
clusterID: 391a3056-24f0-11f1-abc4-000c2903217e # 集群id
pool: pool01 # 存储池
imageFeatures: "layering"
csi.storage.k8s.io/provisioner-secret-name: csi-secret
csi.storage.k8s.io/provisioner-secret-namespace: csi
csi.storage.k8s.io/controller-expand-secret-name: csi-secret
csi.storage.k8s.io/controller-expand-secret-namespace: csi
csi.storage.k8s.io/node-stage-secret-name: csi-secret
csi.storage.k8s.io/node-stage-secret-namespace: csi
csi.storage.k8s.io/fstype: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
- discard
# apply这个storageClass
[root@master01 pv]# kubectl get storageclasses.storage.k8s.io
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-rbd-sc rbd.csi.ceph.com Delete Immediate true 15m
修改成这个样子,这里面的clusterID改成自己的,secret-name自己查一下
2、创建pvc
[root@master01 pv]# cat sc-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sc-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: "csi-rbd-sc"
resources:
requests:
storage: 3Gi
[root@master01 pv]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
sc-pvc Bound pvc-2d948bbe-dbe6-460b-a762-f0279d42437d 3Gi RWO csi-rbd-sc 16m
# 自动创建了一个pv出来了
[root@master01 pv]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-2d948bbe-dbe6-460b-a762-f0279d42437d 3Gi RWO Delete Bound default/sc-pvc csi-rbd-sc 16m
[root@master01 pv]#
- 查看rbd存储池
# pool01里面创建了一个块设备
[root@ceph01 ceph]# rbd ls -p pool01
csi-vol-5b0aa3cf-92aa-498e-84dd-b9ae19eae5d9
3、将sc设置为默认
- 不设置默认的话,每次pvc都需要指定storageClass,设置默认的话,就会自己去找
[root@master01 pv]# cat q-storageclass.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-rbd-sc
annotations:
storageclass.kubernetes.io/is-default-class: "true" # 添加这个为默认的
provisioner: rbd.csi.ceph.com
# 就会有一个default出来
[root@master01 pv]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-rbd-sc (default) rbd.csi.ceph.com Delete Immediate true 21m
- 创建pvc,不指定sc(存储类)
# 没有指定sc
[root@master01 pv]# cat sc-pvc1.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: sc-pvc1
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
[root@master01 pv]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
sc-pvc Bound pvc-2d948bbe-dbe6-460b-a762-f0279d42437d 3Gi RWO csi-rbd-sc 24m
sc-pvc1 Bound pvc-d60250cb-a74d-4131-a703-bc4b04583b72 3Gi RWO csi-rbd-sc 41s
# 自动创建了pv,
-
ceph-csi会自动的关联存储类吗
-
不会
-
需要这个clusterid
-
provisione
-
6、总结
1、动态制备的总结
-
需要一个存储类,ceph-csi
-
pvc创建,ceph-csi能够在ceph集群中创建rbd,pv绑定rbd,pvc绑定pv
2、静态制备
-
现在ceph集群中创建rbd
-
pv绑定rbd,pvc绑定pv

浙公网安备 33010602011771号