1. 程式人生 > >初試 Kubernetes 叢集使用 CephFS 檔案儲存

初試 Kubernetes 叢集使用 CephFS 檔案儲存

目錄

  • Kubernetes PersistentVolumes 介紹
  • 環境、軟體準備
  • 單節點使用 CephFS
  • Kubernetes PV & PVC 方式使用 CephFS
  • 測試跨節點使用 CephFS

1、Kubernetes PersistentVolumes 介紹

Kubernetes PersistentVolumes 持久化儲存方案中,提供兩種 API 資源方式: PersistentVolume(簡稱PV) 和 PersistentVolumeClaim(簡稱PVC)。PV 可理解為叢集資源,PVC 可理解為對叢集資源的請求,Kubernetes 支援很多種持久化卷儲存型別。Ceph 是一個開源的分散式儲存系統,支援物件儲存、塊裝置、檔案系統,具有可靠性高、管理方便、伸縮性強等特點。在日常工作中,我們會遇到使用 k8s 時後端儲存需要持久化,這樣不管 Pod 排程到哪個節點,都能掛載同一個卷,從而很容易讀取或儲存持久化資料,我們可以使用 Kubernetes 結合 Ceph 完成。

2、環境、軟體準備

本次演示環境,我是在虛擬機器 Linux Centos7 上操作,通過虛擬機器完成 Ceph 儲存叢集搭建以及 Kubernetes 叢集的搭建,以下是安裝的軟體及版本:

  1. Centos:release 7.4.1708 (Core)
  2. Ceph:jewel-10.2.10
  3. Kubernetes:v1.6.2
  4. Docker:v1.12.6

注意:這裡我們著重描述一下 Kubernetes 叢集如何使用 CephFS 來實現持久化儲存,所以需要提前搭建好 Kubernetes 叢集和 Ceph 儲存叢集,具體搭建過程可參考之前文章 國內使用 kubeadm 在 Centos 7 搭建 Kubernetes 叢集

初試 Centos7 上 Ceph 儲存叢集搭建,這裡就不在詳細講解了。同時由於本機記憶體限制,共開啟了 3 個虛擬機器節點,每個節點既是 Ceph 叢集節點又是 Kubernetes 叢集節點,所以功能節點圖如下:

這裡寫圖片描述

3、單節點使用 CephFS

有上一篇 初試 Kubernetes 叢集使用 Ceph RBD 塊儲存 操作的基礎,這次就更加輕車熟路了!首先我們單節點使用 CephFS,先只使用 admin 和 node0,這樣就將所有的 Pod 都排程到 node0 上執行。

k8s 叢集單節點使用 CephFS,我們可以使用 Kubernetes Examples Github 官方示例程式碼,稍加修改即可。

$ cd /home/wanyang3/k8s
$ git clone https://github.com/kubernetes/examples.git
# tree examples/staging/volumes/cephfs
|-- cephfs-with-secret.yaml
|-- cephfs.yaml
|-- README.md
`-- secret
    `-- ceph-secret.yaml

跟之前使用 Ceph RBD 類似,也提供了兩種方式供 k8s 叢集使用 CephFS,在搭建 Ceph 叢集時,預設開啟了 cephx 安全認證的,所以在 k8s 叢集使用 CephFS 時,也是要配置認證資訊的,下邊分別演示一下吧!

3.1 建立 cephfs

在正式開始演示之前,我們先在 admin 節點建立一個 cephfs,測試下 cephfs 是否可用吧!詳細操作過程可參考文章 初試 Ceph 儲存之塊裝置、檔案系統、物件儲存 中檔案系統部分,貼下操作程式碼。

# 建立元資料伺服器 MDS
$ ceph-deploy mds create admin node0 node1
...
$ ceph mds stat
e5: 1/1/1 up {0=node0=up:active}, 1 up:standby

# 建立 cephfs
$ ceph osd pool create cephfs_data 128
pool 'cephfs_data' created
$ ceph osd pool create cephfs_metadata 128
pool 'cephfs_metadata' created
$ ceph fs new cephfs cephfs_metadata cephfs_data
new fs with metadata pool 2 and data pool 1
$ ceph fs ls
name: cephfs, metadata pool: cephfs_metadata, data pools: [cephfs_data ]

# 建立認證檔案 admin.secret
$ cat /etc/ceph/ceph.client.admin.keyring
[client.admin]
    key = AQD01VVaVvzzLRAAaTURyUZwI9Ad3uYYFRL+VA==
    caps mds = "allow *"
    caps mon = "allow *"
    caps osd = "allow *"
$ vim /etc/ceph/admin.secret
AQD01VVaVvzzLRAAaTURyUZwI9Ad3uYYFRL+VA==

$ mkdir /mnt/cephfs
$ mount -t ceph 10.222.78.12:6789:/ /mnt/cephfs -o name=admin,secretfile=/etc/ceph/admin.secret
$ df -h
...
10.222.78.12:6789:/   66G   32G   34G   49% /mnt/cephfs

從上邊看到在 admin 節點已經成功將 cephfs 掛載到 /mnt/cephfs 啦!說明整個儲存叢集是沒有問題的,接下來演示的時候,就不需要在各個節點再次建立 cephfs 了,pod 容器內部掛載即可。當然也建立不成功,因為目前 一個 Ceph 儲存叢集只支援建立一個 cephfs。

3.2 使用 cephfs.yaml

$ cat cephfs.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: cephfs1
spec:
  containers:
  - name: cephfs-rw
    image: kubernetes/pause
    volumeMounts:
    - mountPath: "/mnt/cephfs"
      name: cephfs
  volumes:
  - name: cephfs
    cephfs:
      monitors:
      - 10.222.78.12:6789
      user: admin
      secretFile: "/etc/ceph/admin.secret"
      readOnly: true

修改完的配置如上,這裡我們要掛載 /mnt/cephfs 目錄到 Pod 容器內。在建立之前,我們要去 node0 節點生成 admin.secret (因為現在是單節點測試,Pod 只會被排程到 node0,後續加入node1 時也需要生成 admin.secret),同時這裡 node0 既是 Ceph 叢集 osd 節點又是 k8s 節點,所以已存在該檔案,取出 Key 值即可。

$ cat /etc/ceph/ceph.client.admin.keyring
[client.admin]
    key = AQD01VVaVvzzLRAAaTURyUZwI9Ad3uYYFRL+VA==
    caps mds = "allow *"
    caps mon = "allow *"
    caps osd = "allow *"
$ vim /etc/ceph/admin.secret
AQD01VVaVvzzLRAAaTURyUZwI9Ad3uYYFRL+VA==

好了,現在可以建立使用 CephFS 作為後端儲存的 Pod 了。

$ kubectl create -f cephfs.yaml 
pod "cephfs1" created

$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
cephfs1   1/1       Running   0          12s

接下來我們去 node0 上驗證一下是否正確啟動並掛載該 CephFS 吧!

# node0 上操作
$ docker ps
CONTAINER ID        IMAGE                                                                                                COMMAND                  CREATED             STATUS              PORTS               NAMES
b9f2bac921d1        docker.io/kubernetes/[email protected]:2088df8eb02f10aae012e6d4bc212cabb0ada93cb05f09e504af0c9811e0ca14   "/pause"                 28 seconds ago      Up 27 seconds                           k8s_cephfs-rw_cephfs1_default_5cc74af6-f5ea-11e7-be96-080027ee5979_0

$ mount
...
10.222.78.12:6789:/ on /var/lib/kubelet/pods/5cc74af6-f5ea-11e7-be96-080027ee5979/volumes/kubernetes.io~cephfs/cephfs type ceph (ro,relatime,name=admin,secret=<hidden>,acl)


$ docker inspect b9f2bac921d1
...
"Mounts": [
            {
                "Source": "/var/lib/kubelet/pods/5cc74af6-f5ea-11e7-be96-080027ee5979/containers/cephfs-rw/80747a86",
                "Destination": "/dev/termination-log",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Source": "/var/lib/kubelet/pods/5cc74af6-f5ea-11e7-be96-080027ee5979/volumes/kubernetes.io~cephfs/cephfs",
                "Destination": "/mnt/cephfs",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Source": "/var/lib/kubelet/pods/5cc74af6-f5ea-11e7-be96-080027ee5979/volumes/kubernetes.io~secret/default-token-jg3f8",
                "Destination": "/var/run/secrets/kubernetes.io/serviceaccount",
                "Mode": "ro",
                "RW": false,
                "Propagation": "rprivate"
            },
            {
                "Source": "/var/lib/kubelet/pods/5cc74af6-f5ea-11e7-be96-080027ee5979/etc-hosts",
                "Destination": "/etc/hosts",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

3.3 使用 cephfs-with-secret & ceph-secret

接下來使用 cephfs-with-secret 和 ceph-secret 方式,這種方式跟上邊直接使 admin.secret 檔案認證最大的區別就是使用 k8s secret 物件,該 secret 物件用於 k8s volume 外掛通過 cephx 認證訪問 ceph 儲存叢集。不過要提一下的是,k8s secret 認證 key 需要使用 base64 編碼。

# 獲取 Ceph ceph.client.admin.keyring 並生成 secret key
$ ceph auth get-key client.admin |base64
QVFEMDFWVmFWdnp6TFJBQWFUVVJ5VVp3STlBZDN1WVlGUkwrVkE9PQ==

修改 ceph-secret.yaml 檔案中,key 欄位替換成上邊生成的字串。

$ cat ceph-secret.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: ceph-secret
data:
  key: QVFEMDFWVmFWdnp6TFJBQWFUVVJ5VVp3STlBZDN1WVlGUkwrVkE9PQ==

建立名稱為 ceph-secret 的 Secret。

$ kubectl create -f ceph-secret.yaml 
secret "ceph-secret" created
$ kubectl get secret
NAME                  TYPE                                  DATA      AGE
ceph-secret           Opaque                                1         11s
default-token-jg3f8   kubernetes.io/service-account-token   3         28m

接下來,需要修改一下 cephfs-with-secret.yaml 檔案,主要修改 cephfs 相關資訊,修改完成後如下。

# cat cephfs-with-secret.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: cephfs2
spec:
  containers:
  - name: cephfs-rw
    image: kubernetes/pause
    volumeMounts:
    - mountPath: "/mnt/cephfs"
      name: cephfs
  volumes:
  - name: cephfs
    cephfs:
      monitors:
      - 10.222.78.12:6789
      user: admin
      secretRef:
        name: ceph-secret
      readOnly: true

配置跟上邊類似,唯一區別就是 secretRef 換成剛建立的 ceph-secret 物件,接下來建立該 Pod 啦!

$ kubectl create -f cephfs-with-secret.yaml 
pod "cephfs2" created
$ kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
cephfs1   1/1       Running   0          11m
cephfs2   1/1       Running   0          25s

跟上邊示例一樣,妥妥沒問題,可以去 node0 上檢視 mount 資訊驗證一下,這裡就不在演示了。

4、Kubernetes PV & PVC 方式使用 CephFS

上一篇文章中指出,k8s 支援的 PV 型別有很多,其中就有我們熟悉的 Ceph RBD 和 CephFS,接下來就演示一下如何使用 PV & PVC 結合 CephFS 完成上邊演示操作。這裡使用上邊建立的同一個 cephfs,因為一個 Cephfs 儲存叢集只支援建立一個 cephfs。還有就是,這裡我們可以加入 node1 了,組成一個多節點的 k8s 叢集,測試跨節點使用 CephFS。

4.1 建立 PV

還記得上邊提過 Ceph 認證的 secret,這裡也是需要的,這次就不用再建立了,直接複用上邊的即可。新建 PV 檔案 rbd-pv.yaml 如下:

$ vim cephfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: cephfs-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  cephfs:
    monitors:
      - 10.222.78.12:6789
    user: admin
    secretRef:
      name: ceph-secret
    readOnly: false
  persistentVolumeReclaimPolicy: Recycle

注意,這裡我們使用的 accessModes 模型為 ReadWriteMany,kubernetes 官網 Persistent Volumes 文件中指出 CephFS 檔案儲存對三種 Mode 方式都支援,CephFS 支援讀寫多次,也是實際工作中需要的。接下來建立 PV。

$ kubectl create -f cephfs-pv.yaml 
persistentvolume "cephfs-pv" created
$ kubectl get pv
NAME        CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS      CLAIM     STORAGECLASS   REASON    AGE
cephfs-pv   1Gi        RWX           Recycle         Available     

4.2 建立 PVC

好了,上邊 PV 資源已經建立好了,接下來建立對資源的請求 PVC,新建 PVC 檔案 cephfs-pv-claim.yaml 如下:

$ cat cephfs-pv-claim.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: cephfs-pv-claim
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

這裡提一下的是,因為接下來驗證測試需要跨節點讀取和寫入檔案,所以使用 ReadWriteMany 模型,接下來建立 PVC。

$ kubectl create -f cephfs-pv-claim.yaml 
persistentvolumeclaim "cephfs-pv-claim" created
$ kubectl get pvc
NAME              STATUS    VOLUME      CAPACITY   ACCESSMODES   STORAGECLASS   AGE
cephfs-pv-claim   Bound     cephfs-pv   1Gi        RWX                          10s

4.3 建立掛載 CephFS 的 Pod

PV 和 PVC 都建立好了,接下來就需要建立掛載該 CephFS 的 Pod 了,這裡我使用官方示例中的 busybox 容器測試吧!新建 Pod 檔案 cephfs-pvc-pod1.yaml 如下:

# vim cephfs-pvc-pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: cephfs-pvc-pod
  name: cephfs-pv-pod1
spec:
  containers:
  - name: cephfs-pv-busybox1
    image: busybox
    command: ["sleep", "60000"]
    volumeMounts:
    - mountPath: "/mnt/cephfs"
      name: cephfs-vol1
      readOnly: false
  volumes:
  - name: cephfs-vol1
    persistentVolumeClaim:
      claimName: cephfs-pv-claim

從檔案可以看出,我們要將上邊建立的 cephfs-pv-claim 請求的資源掛載到容器的 /mnt/cephfs 目錄。接下來建立一下該 Pod,看是否能夠正常執行吧!建立之前,我們先造點資料到 /mnt/cephfs 目錄,方便後邊讀取測試。

# 提前寫入資料
$ vim /mnt/cephfs/test.txt 
This is cephfs test file.

# 建立 cephfs-pv-pod1
$ kubectl create -f cephfs-pvc-pod.yaml 
pod "cephfs-pv-pod1" created
$ kubectl get pod
NAME             READY     STATUS    RESTARTS   AGE
cephfs-pv-pod1   1/1       Running   0          47s
$ kubectl get pod --all-namespaces -o wide
NAMESPACE     NAME                            READY     STATUS    RESTARTS   AGE       IP              NODE
default       cephfs-pv-pod1                  1/1       Running   0          26s       10.96.2.2       node1
...

我們看到 Pod 能夠正常啟動,並且分配到了 node1,接下來我們去 node1 驗證一下吧!

# node1 上操作
$ docker ps
CONTAINER ID        IMAGE                                                                                       COMMAND                  CREATED             STATUS              PORTS               NAMES
3cc605bed890        docker.io/[email protected]:436bbf48aa1198ebca8eac0ad9a9c80c8929d9242e02608f76ce18334e0cfe6a   "sleep 60000"            12 seconds ago      Up 12 seconds                           k8s_cephfs-pv-busybox1_cephfs-pv-pod1_default_a2397f5d-f677-11e7-be96-080027ee5979_0

$ docker exec -it 3cc605bed890 /bin/sh
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
10.222.78.12:6789:/      65.4G     34.1G     31.3G  52% /mnt/cephfs
...

/ # ls  /mnt/cephfs
test.txt
/ # cat /mnt/cephfs/test.txt
This is cephfs test file.

# 建立一個新檔案,測試下邊跨節點看能否掛載的上,並且能夠讀取出來吧。
/ # vi /mnt/cephfs/cephfs-pv-pod1.txt
/ # cat /mnt/cephfs/cephfs-pv-pod1.txt
This message write by cephfs-pv-pod1 pod.

OK 我們看到 Pod 容器內能夠正確掛載 CephFS 併成功讀取到之前建立的檔案。

5、測試跨節點使用 CephFS

上一篇文中 K8s 叢集跨節點使用 Ceph RBD 存在 rbd: image ceph-rbd-pv-test is locked by other nodes 錯誤資訊,說明 Ceph RBD 僅能被 k8s 中的一個 node 掛載,也就是不支援跨節點掛載同一 Ceph RBD。那麼 CephFS 也會存在這個問題嗎?接下來我們驗證一下。

我們再在另外一個 node 上建立掛載同一個 CephFS 的 Pod,看是否可以跨節點掛載吧!

# 建立掛載 cephfs 的 pod2,配置同 pod1
$ vim cephfs-pvc-pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: cephfs-pvc-pod
  name: cephfs-pv-pod2
spec:
  containers:
  - name: cephfs-pv-busybox2
    image: busybox
    command: ["sleep", "60000"]
    volumeMounts:
    - mountPath: "/mnt/cephfs"
      name: cephfs-vol2
      readOnly: false
  volumes:
  - name: cephfs-vol2
    persistentVolumeClaim:
      claimName: cephfs-pv-claim

接下來建立一下該 Pod,看能夠建立成功吧!

$ kubectl create -f cephfs-pvc-pod2.yaml 
pod "cephfs-pv-pod2" created

$ kubectl get pods --all-namespaces -o wide
NAMESPACE     NAME                            READY     STATUS    RESTARTS   AGE       IP              NODE
default       cephfs-pv-pod1                  1/1       Running   0          9m        10.96.2.3       node1
default       cephfs-pv-pod2                  1/1       Running   0          16s       10.96.1.4       node0

OK 我們看到 cephfs-pv-pod2 被分配到了 node0 並且正常執行起來了。說明 K8s 支援 CephFS 跨節點掛載。接下來,我們去 node0 驗證一下是否正確掛載該 CephFS 吧!

# node0 上操作
$ docker ps
CONTAINER ID        IMAGE                                                                                       COMMAND                  CREATED              STATUS              PORTS               NAMES
f8e544e9f497        docker.io/[email protected]:436bbf48aa1198ebca8eac0ad9a9c80c8929d9242e02608f76ce18334e0cfe6a   "sleep 60000"            About a minute ago   Up About a minute                       k8s_cephfs-pv-busybox2_cephfs-pv-pod2_default_faf6f3fd-f678-11e7-be96-080027ee5979_0

$ docker exec -it f8e544e9f497 /bin/sh
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
10.222.78.12:6789:/      65.4G     34.1G     31.3G  52% /mnt/cephfs
...

/ # ls -l /mnt/cephfs
total 1
-rw-r--r--    1 root     root            42 Jan 11 02:36 cephfs-pv-pod1.txt
-rw-r--r--    1 root     root            26 Jan 10 09:39 test.txt

/ # cat /mnt/cephfs/cephfs-pv-pod1.txt
This message write by cephfs-pv-pod1 pod.

OK 一切正常,Pod 容器內能夠正確掛載同一 CephFS 併成功讀取到 pod1 建立的檔案。下邊我們在pod2 中寫入檔案,看下 pod1 中是否能夠讀取的到吧!

# node0 pod2 中寫入檔案
$ docker exec -it f8e544e9f497 /bin/sh
/ # vi /mnt/cephfs/cephfs-pv-pod2.txt 
/ # cat /mnt/cephfs/cephfs-pv-pod2.txt 
this message write by cephfs-pv-pod2 pod from node0.

# node1 pod1 讀取檔案
$ docker exec -it 3cc605bed890 /bin/sh
/ # ls /mnt/cephfs/
cephfs-pv-pod1.txt  cephfs-pv-pod2.txt  test.txt

依舊妥妥沒問題噠!再次說明,k8s 叢集支援跨節點掛載 CephFS 檔案儲存。同時 kubernetes 官網 Persistent Volumes 文件 中指出,當靜態 PV 都不匹配使用者的 PVC 請求時,k8s 叢集還支援 Dynamic 動態提供 Volume 給 PVC,不過這種方式需要配置 StorageClasses,檢視 Kubernetes 官網 Storage Classes 文件 Provisioner 部分指出支援 Ceph RBD,下一篇我們繼續研究 Kubernetes 叢集使用 RBD 作為 StorageClass PVC,來實現分散式儲存。

參考資料