當前位置: 妍妍網 > 碼農

使用 RBD 作為 Kubernetes 儲存解決方案的最佳實踐指南!

2024-06-28碼農

戳下方名片 ,關註並 星標

回復「 1024 」獲取 2TB 學習資源!


👉 體系化學習:

特色專欄

/ /

/ /

/ /

/ /

/ /

大家好,我是民工哥!

今天來聊一聊 k8s 使用 rbd 作為儲存的方案!

如果需要使用 rbd 作為後端儲存的話,需要先安裝 ceph-common。

ceph 集群建立 rbd

需要提前在 ceph 集群上建立 pool,然後建立 image

[root@ceph01 ~]# ceph osd pool create pool01
[root@ceph01 ~]# ceph osd pool application enable pool01 rbd
[root@ceph01 ~]# rbd pool init pool01
[root@ceph01 ~]# rbd create pool01/test --size 10G --image-format 2 --image-feature layerin
[root@ceph01 ~]# rbd info pool01/test

k8s 編寫 yaml 檔

apiVersion:apps/v1
kind:Deployment
metadata:
creationTimestamp:null
labels:
app:rbd
name:rbd
spec:
replicas:1
selector:
matchLabels:
app:rbd
strategy:{}
template:
metadata:
creationTimestamp:null
labels:
app:rbd
spec:
volumes:
-name:test
rbd:
fsType:xfs
keyring:/root/admin.keyring
monitors:
-192.168.200.230:6789
pool:pool01
image:test
user:admin
readOnly:false
containers:
-image:nginx
imagePullPolicy:IfNotPresent
volumeMounts:
-mountPath:/usr/share/nginx/html
name:test
name:nginx
resources:{}
status: {}

[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rbd-888b8b747-n56wr 1/1 Running 0 26m

這個時候 k8s 就使用了 rbd 作為儲存。

如果這個地方一直顯示 ContainerCreating 的話,可能是沒有安裝 ceph-common,也可能是你的 keyring 或者 ceph.conf 沒有發放到 node 節點,具體可以使用 describe 來看。

進入容器檢視掛載

[root@master euler]# kubectl exec -it rbd-5db4759c-nj2b4 -- bash
root@rbd-5db4759c-nj2b4:/# df -hT |grep /dev/rbd0
/dev/rbd0 xfs 10G 105M 9.9G 2% /usr/share/nginx/html

可以看到,/dev/rbd0 已經被格式化成 xfs 並且掛載到了/usr/share/nginx/html。

進入容器修改內容

root@rbd-5db4759c-nj2b4:/usr/share/nginx# cd html/
root@rbd-5db4759c-nj2b4:/usr/share/nginx/html# ls
root@rbd-5db4759c-nj2b4:/usr/share/nginx/html# echo 123 > index.html
root@rbd-5db4759c-nj2b4:/usr/share/nginx/html# chmod 644 index.html
root@rbd-5db4759c-nj2b4:/usr/share/nginx/html# exit
[root@master euler]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rbd-5db4759c-nj2b4 1/1 Running 0 8m5s 192.168.166.131 node1 <none> <none>

存取容器檢視內容

[root@master euler]# curl 192.168.166.131123

內容可以正常被存取到,我們將容器刪除,然後讓他自己重新啟動一個來看看檔是否還存在。

[root@master euler]# kubectl delete pods rbd-5db4759c-nj2b4
pod "rbd-5db4759c-nj2b4" deleted
[root@master euler]# kubectl get pods
NAME READY STATUS RESTARTS AGE
rbd-5db4759c-v9cgm 0/1ContainerCreating02s
[root@master euler]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
rbd-5db4759c-v9cgm 1/1Running040s192.168.166.132 node1 <none><none>
[root@master euler]# curl 192.168.166.132
123

可以看到,也是沒有問題的,這樣 k8s 就正常的使用了 rbd 儲存。

有一個問題,那就是開發人員他們並不是很了解 yaml 檔裏面改怎麽去寫掛載,每種型別的儲存都是不同的寫法,那有沒有一種方式遮蔽底層的寫法,直接告訴 k8s 集群我想要一個什麽樣的儲存呢?

有的,那就是 pv。

pv 使用 rbd

[root@mastereuler]# vim pvc.yaml 
apiVersion:v1
kind:PersistentVolumeClaim
metadata:
name:myclaim
spec:
accessModes:
-ReadWriteOnce
volumeMode:Block
resources:
requests:
storage:8Gi

這裏的 pvc 使用的是塊裝置,8 個 G,目前還沒有這個 pv 可以給到他。

具體的這裏不細說,CKA 裏面有寫。

註意,這裏是 pvc,並不是 pv,pvc 就是開發人員定義想要的儲存型別,大小,然後我可以根據你的 pvc 去給你建立 pv,或者提前建立好 pv 你直接申領。

[root@mastereuler]# vim pv.yaml 
apiVersion:v1
kind:PersistentVolume
metadata:
name:rbdpv
spec:
capacity:
storage:8Gi
volumeMode:Block
accessModes:
-ReadWriteOnce
persistentVolumeReclaimPolicy:Recycle
mountOptions:
-hard
-nfsvers=4.1
rbd:
fsType:xfs
image:test
keyring:/etc/ceph/ceph.client.admin.keyring
monitors:
-172.16.1.33
pool:rbd
readOnly:false
user:admin

檢視 pvc 狀態

[root@master euler]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGE class AGE
myclaim Bound rbdpv 8Gi RWO 11s

這個時候 pv 和就和 pvc 繫結上了,一個 pv 只能繫結一個 pvc,同樣,一個 pvc 也只能繫結一個 pv。

使用 pvc

[root@mastereuler]# vim pod-pvc.yaml 
apiVersion:v1
kind:Pod
metadata:
creationTimestamp:null
labels:
run:pvc-pod
name:pvc-pod
spec:
volumes:
-name:rbd
persistentVolumeClaim:
claimName:myclaim
readOnly:false
containers:
-image:nginx
imagePullPolicy:IfNotPresent
name:pvc-pod
volumeDevices:# 因為是使用的塊裝置,所以這裏是volumeDevices
-devicePath:/dev/rbd0
name:rbd
resources:{}
dnsPolicy:ClusterFirst
restartPolicy:Always
status:{}
~

[root@master euler]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pvc-pod 1/1 Running 0 2m5s
rbd-5db4759c-v9cgm 1/1 Running 0 39m

進入容器檢視塊裝置

root@pvc-pod:/# ls /dev/rbd0/dev/rbd0

可以看到,現在 rbd0 已經存在於容器內部了。

這樣做我們每次建立 pvc 都需要建立對應的 pv,我們可以使用動態制備。

動態制備

使用 storage class,但是目前歐拉使用的 k8s 太老了,所以需要下載歐拉 fork 的一個 storage class。

[root@master ~]# git clone https://gitee.com/yftyxa/ceph-csi.git
[root@master ~]# cd ceph-csi/deploy/
[root@master deploy]# ls
ceph-conf.yaml csi-config-map-sample.yaml rbd
cephcsi Makefile scc.yaml
cephfs nfs service-monitor.yaml

動態制備 rbd

這裏我們需要修改這個檔: /root/ceph-csi/deploy/rbd/kubernetes/csi-config-map.yaml

# 先建立一個csi名稱空間
[root@master ~]# kubectl create ns csi

修改檔內容

[root@master kubernetes]# vim csi-rbdplugin-provisioner.yaml
# 將第63行的內容改為false
63-"--extra-create-metadata=false"
# 修改第二個檔
[root@master kubernetes]# vim csi-config-map.yaml 
# 這裏盡量不要復制,因為測試過程中復制貼上到檔裏會導致k8s不辨識
apiVersion: v1
kind:ConfigMap
metadata:
name:"ceph-csi-config"
data:
config.json:|-
[
{
"clusterID":"c1f213ae-2de3-11ef-ae15-00163e179ce3",
"monitors":["172.16.1.33","172.16.1.32","172.16.1.31"]
}
]
[root@master kubernetes]# kubectl apply -f csi-config-map.yaml -n csi

  • • 這裏面的 clusterID 可以透過 ceph -s 去檢視

  • 修改第三個檔

    [root@master kubernetes]# vim csidriver.yaml 
    ---
    apiVersion: storage.k8s.io/v1
    kind:CSIDriver
    metadata:
    name:"rbd.csi.ceph.com"
    spec:
    attachRequired:true
    podInfoOnMount:false
    # seLinuxMount: true # 將這一行註釋
    fsGroupPolicy: File

    自行編寫一個檔

    [root@masterkubernetes]# vim csi-kms-config-map.yaml 
    ---
    apiVersion:v1
    kind:ConfigMap
    metadata:
    name:ceph-csi-encryption-kms-config
    data:
    config-json:|-
    {}

    獲取 admin 的 key

    [root@ceph001 ~]# cat /etc/ceph/ceph.client.admin.keyring 
    [client.admin]
    key = AQC4QnJmng4HIhAA42s27yOflqOBNtEWDgEmkg==
    caps mds = "allow *"
    caps mgr = "allow *"
    caps mon = "allow *"
    caps osd = "allow *"

  • • AQC4QnJmng4HIhAA42s27yOflqOBNtEWDgEmkg== 只要這部份。

  • 然後自行編寫一個 csi-secret.yaml 的檔

    [root@masterkubernetes]# vim csi-secret.yaml
    apiVersion:v1
    kind:Secret
    metadata:
    name:csi-secret
    stringData:
    userID:admin
    userKey:AQC4QnJmng4HIhAA42s27yOflqOBNtEWDgEmkg==
    adminID:admin
    adminKey:AQC4QnJmng4HIhAA42s27yOflqOBNtEWDgEmkg==
    [root@masterkubernetes]# kubectl apply -f csi-secret.yaml -n csi
    secret/csi-secretcreated
    [root@masterkubernetes]# cd ../../
    [root@masterdeploy]# kubectl apply -f ceph-conf.yaml -n csi
    configmap/ceph-configcreated
    [root@masterdeploy]# cd -
    /root/ceph-csi/deploy/rbd/kubernetes

    4替換所有的 namespace

    [root@master kubernetes]# sed -i "s/namespace: default/namespace: csi/g" 
    *.yaml

    部署

    [root@master kubernetes]# kubectl apply -f . -n csi

    註意 :如果你的 worker 節點數量少於 3 個的話,是需要將 csi-rbdplugin-provisioner.yaml 這個檔裏面的 replicas 改小一點的。

    [root@master kubernetes]# kubectl get pods -n csi
    NAME READY STATUS RESTARTS AGE
    csi-rbdplugin-cv455 3/3Running1(2m14s ago)2m46s
    csi-rbdplugin-pf5ld 3/3Running04m36s
    csi-rbdplugin-provisioner-6846c4df5f-dvqqk 7/7Running04m36s
    csi-rbdplugin-provisioner-6846c4df5f-nmcxf 7/7Running1(2m11s ago) 4m36s

    使用動態制備

    建立 storage class

    [root@master rbd]#/root/ceph-csi/examples/rbd
    [root@master rbd]# grep -Ev"\s*#|^$" storage class.yaml 
    ---
    apiVersion: storage.k8s.io/v1
    kind:Storage class
    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

    將這裏的內容復制出來

    ---
    apiVersion:storage.k8s.io/v1
    kind:Storage class
    metadata:
    name:csi-rbd-sc
    provisioner:rbd.csi.ceph.com
    parameters:
    clusterID:c1f213ae-2de3-11ef-ae15-00163e179ce3
    pool:rbd
    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:Retain
    allowVolumeExpansion:true
    mountOptions:
    -discard

    修改成這個樣子,這裏面的 clusterID 改成自己的,secret-name 自己查一下。

    建立 pvc

    [root@mastereuler]# cp pvc.yaml sc-pvc.yaml
    [root@mastereuler]# vim sc-pvc.yaml
    apiVersion:v1
    kind:PersistentVolumeClaim
    metadata:
    name:sc-pvc
    spec:
    accessModes:
    -ReadWriteOnce
    volumeMode:Block
    storage className:"csi-rbd-sc"
    resources:
    requests:
    storage:15Gi

  • • storage className 可以使用 kubectl get sc 檢視。

  • 現在我們只需要建立 pvc,他就自己可以建立 pv 了。

    [root@master euler]# kubectl apply -f sc-pvc.yaml 
    persistentvolumeclaim/sc-pvc created
    [root@master euler]# kubectl get pvc
    NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGE class AGE
    myclaim Bound rbdpv 8Gi RWO 111m
    sc-pvc Bound pvc-dfe3497f-9ed7-4961-9265-9e7242073c28 15Gi RWO csi-rbd-sc 2s

    回到 ceph 集群檢視 rbd

    [root@ceph001 ~]# rbd ls
    csi-vol-56e37046-b9d7-4ef1-a534-970a766744f3
    test
    [root@ceph001 ~]# rbd info csi-vol-56e37046-b9d7-4ef1-a534-970a766744f3
    rbd image 'csi-vol-56e37046-b9d7-4ef1-a534-970a766744f3':
    size 15GiBin3840 objects
    order 22(4MiB objects)
    snapshot_count:0
    id:38019ee708da
    block_name_prefix: rbd_data.38019ee708da
    format:2
    features: layering
    op_features:
    flags:
    create_timestamp:WedJun1904:55:352024
    access_timestamp:WedJun1904:55:352024
    modify_timestamp:WedJun1904:55:35 2024

    將 sc 設為預設

    如果不設定為預設的話,每次寫 yaml 檔都需要指定 sc,將 sc 設為預設的話就不用每次都指定了

    [root@master euler]# kubectl edit sc csi-rbd-sc
    # 在註釋裏面寫入這一行
    annotations:
    storage class.kubernetes.io/is-default- class: "true"

    測試預設 pvc

    [root@master euler]# kubectl get sc
    NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
    csi-rbd-sc (default) rbd.csi.ceph.com Retain Immediate true 29m

    再去檢視 sc 就會有一個 default 的顯示

    [root@master euler]# cp sc-pvc.yaml sc-pvc1.yaml 
    [root@master euler]# cat sc-pvc1.yaml 
    apiVersion: v1
    kind:PersistentVolumeClaim
    metadata:
    name: sc-pvc1
    spec:
    accessModes:
    -ReadWriteOnce
    volumeMode:Block
    resources:
    requests:
    storage: 20Gi

    這個檔裏面是沒有指定 storage className 的。

    [root@master euler]# kubectl apply -f sc-pvc1.yaml 
    persistentvolumeclaim/sc-pvc1 created
    [root@master euler]# kubectl get pvc
    NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGE class AGE
    myclaim Bound rbdpv 8Gi RWO 138m
    sc-pvc Bound pvc-dfe3497f-9ed7-4961-9265-9e7242073c28 15Gi RWO csi-rbd-sc 27m
    sc-pvc1 Bound pvc-167cf73b-4983-4c28-aa98-bb65bb966649 20Gi RWO csi-rbd-sc 6s

    這樣就好了

    作者:FuShudi 連結:

    https://cnblogs.com/fsdstudy/p/18254695

    👍 如果你喜歡這篇文章,請點贊並分享給你的朋友!

    公眾號讀者專屬技術群

    構建高品質的技術交流社群,歡迎從事後端開發、運維技術進群( 備註崗位,已在技術交流群的請勿重復添加微信好友 )。主要以技術交流、內推、行業探討為主,請文明發言。 廣告人士勿入,切勿輕信私聊,防止被騙。

    掃碼加我好友,拉你進群

    PS:因為公眾號平台更改了推播規則,如果不想錯過內容,記得讀完點一下 在看 ,加個 星標 ,這樣每次新文章推播才會第一時間出現在你的訂閱列表裏。 在看 支持我們吧!