Kubernetes 使用 ceph-csi 消費 RBD 做爲持久化存儲

本文詳細介紹瞭如何在 Kubernetes 集羣中部署 ceph-csi(v3.1.0),並使用 RBD 做爲持久化存儲。html

須要的環境參考下圖:node

v2-64748b8a9efa5ad9aa20853b00cd95d6_720w.png


本文使用的環境版本信息:git

Kubernetes 版本:github

$ 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 版本:json

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

如下是詳細部署過程:api

1. 新建 Ceph Poolbash

建立一個新的 ceph 存儲池(pool) 給 Kubernetes 使用:app

$ ceph osd pool create kubernetes
 
pool ' kubernetes' created

查看全部的 poolide

$ 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.yamlcsi-rbdplugin.yaml 中的 kms 部分配置註釋掉:

v2-99e1e397d8c78637187315641f549e6e_720w.png

v2-b1294cf085af289a144c24443df631be_720w.png

部署 csi-rbdplugin-provisioner

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

這裏麪包含了 6 個 Sidecar 容器,包括 external-provisionerexternal-attachercsi-resizercsi-rbdplugin

部署 RBD CSI driver

最後部署 RBD CSI Driver

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

Pod 中包含兩個容器:CSI node-driver-registrarCSI 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-csiexamples/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
相關文章
相關標籤/搜索