如何通過 Rook-Ceph 升級 NFS 服務
高瑞冬,中國移動磐基 PaaS 平臺中間件專業服務項目資深顧問,專注於雲原生等領域產品研發。
1.前言
nfs 是廣泛使用的網絡化存儲服務,用戶基礎大,技術成熟,具有操作知識的工程師很多。但是,在雲原生和分佈式存儲的角度看,原生的 nfs 存儲服務不能提供存儲高可用能力,然而存儲高可用能力是雲原生的普遍需求。
本文探索通過 ceph 爲 nfs 服務提供存儲的高可用的可行方案。ceph 存儲結合 nfs-ganesha 服務,爲 nfs 客戶端提供了基於 ceph 對象存儲的 nfs 協議輸出。ceph 提供的存儲類型豐富,包括 RBD,cephfs,RGW,能夠有效滿足不同業務場景的需求。本文給出了提供 cephfs 和 RGW 兩種後端存儲機制的 nfs 集成方案。期望 nfs 的衆多用戶可以在雲原生環境中繼續安心使用熟悉的 nfs 掛載提供存儲能力,而同時獲得了 ceph 存儲提供的多副本或者糾刪碼的高可用特性,滿足雲原生環境對業務運行的新需求。
本文嘗試通過 rook(1.10.11) 管理的 ceph(17.2.5) 創建 nfs 導出,爲 nfs 用戶提供一種新的選擇和參考。
2.準備 cephfs 後端存儲
2.1 cephfs 的一些準備性知識
- Volume
Volume 是 cephfs 文件系統的一個抽象。在這個層面可以指定存儲使用的 ceph 池,從而指定是使用多副本還是糾錯碼作爲數據高可用的提供者。每個 volume 會有獨立的 metadata server 爲其提供目錄等元數據服務。
- Subvolume
subvolume 是對 cephfs 文件系統目錄的抽象。cephfs 對外存儲是以 subvolume 爲單位供給。K8s 中爲容器申請一塊 cephfs 存儲空間就是一個 subvolume。
- Subvolumegroup
subvolumegroup 是比 subvolume 更高層面的目錄抽象。這個層面可以控制策略(如文件佈局等)。這裏設置的策略會在其下的 subvolume 中應用。
2.2 創建 cephfs volume
首先我們通過 rook 提供的如下 yaml 創建一個三副本的 cephfs(ceph 文件系統):
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
name: cephfs4nfs
namespace: rook-ceph
spec:
metadataPool:
replicated:
size: 3
requireSafeReplicaSize: true
parameters:
compression_mode:
none
dataPools:
- name: replicated
failureDomain: host
replicated:
size: 3
requireSafeReplicaSize: true
parameters:
compression_mode:
none
preserveFilesystemOnDelete: true
metadataServer:
activeCount: 1
activeStandby: true
placement:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- rook-ceph-mds
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- rook-ceph-mds
topologyKey: topology.kubernetes.io/zone
priorityClassName: system-cluster-critical
livenessProbe:
disabled: false
startupProbe:
disabled: false
使用 rook 提供的 krew 插件 rook-ceph 命令,可以 ceph 命令行的形式直接操作 k8s 中的 ceph 集羣,如同 ceph 的主機化部署一樣。如下命令用來查看上面新文件系統對應的 ceph 存儲池是否已經創建:
kubectl rook-ceph ceph osd pool ls | grep cephfs4nfs
cephfs4nfs-metadata
cephfs4nfs-replicated
可以看到爲新文件系統已經創建兩個存儲池:
-
用於存儲元數據:cephfs4nfs-metadata
-
用於存儲數據:cephfs4nfs-replicated
2.3 創建 cephfs 上的 nfs 導出目錄
目前需要使用 ceph 原生命令查看創建出來的 ceph 文件系統。工程上一般不會把整個 cephfs volume 做 nfs 導出,那麼在新創建的 cephfs volume 上創建一個 subvolumegroup 常常是很有必要的,subvolumegroup 對應的是 ceph 文件系統的目錄。以此便於控制 nfs 導出訪問權限,容量,專門用於 nfs 掛載。以下命令創建了空間配額爲 204800KB 的 subvolumegroup:
kubectl rook-ceph ceph fs subvolumegroup create cephfs4nfs nfsexport --size 204800
需要查看並記錄創建的這個 subvolumegroup 的絕對路徑,這個路徑在創建 nfs export 時候需要用到:
kubectl rook-ceph ceph fs subvolumegroup getpath cephfs4nfs nfsexport
/volumes/nfsexport
3.準備 RGW 後端存儲
爲了提供 nfs 導出的 RGW 後端存儲,我們需要在 ceph 中創建一個存儲對象桶(bucket),通過 nfs 讀寫的業務數據將存儲在這個桶的對象中。
創建對象桶可以通過 s3 客戶端完成,這裏我們使用 ceph 的儀表盤可視化的完成這個操作。通過瀏覽器打開儀表盤,在左側菜單欄中選擇 Object Gateway/Buckets,打開對象桶的管理頁面。
頁面上點擊 Create。在頁面中填入對象名稱 bkt4exp,選擇一個 owner,選擇合適的放置點,點擊 Create bucket 完成創建。
這個對象桶將在後面創建 nfs rgw 導出時使用。
4.創建 ganesha-nfs 服務提供 nfs 導出
然後我們通過 rook 提供的 cephnfs 模版創建一個 nfs 集羣。這一步將在 k8s 上啓動一個基於 ganesha-nfs 的服務。
apiVersion: ceph.rook.io/v1
kind: CephNFS
metadata:
name: nfs-cluster
namespace: rook-ceph
spec:
server:
active: 1
logLevel: NIV_INFO
稍後會有 pod 啓動,正是 pod 中運行的這個服務提供 nfs 導出到 ceph 存儲的轉換服務。
運行 kubectl rook-ceph ceph nfs cluster ls
nfs-cluster
nfs4cephfs
nfs4rgw
可以看到新的 nfs 集羣 nfs-cluster 已經創建出來了。
爲了掛載 nfs 導出,需要查看和記錄 nfs-ganesha 服務 nfs-cluster 所在的 ip。下面輸出的結果顯示 nfs 服務 ip 地址是 169.169.165.85。
kubectl get svc -n rook-ceph| grep nfs-cluster
rook-ceph-nfs-nfs-cluster-a ClusterIP 169.169.165.85 <none>
2049/TCP 9m29s
5.創建 nfs 導出
nfs-ganesha 服務已經就緒,需要的信息也已經蒐集和記錄。這樣我們就可以根據需要創建 nfs 導出了。目前 ceph 支持使用 cephfs 和 rgw 作爲存儲後端。
5.1 創建 cephfs 導出
下面是在 ceph 系統內部創建一個基於 cephfs 的 nfs 導出,掛載到 cephfs4nfs 文件系統的目錄 / volumes/nfsexport 下。這個目錄是在前面 2.3 節中準備好的。運行如下命令:
kubectl rook-ceph ceph nfs export create cephfs nfs-cluster /fsexport cephfs4nfs /volumes/nfsexport
{
"bind": "/fsexport",
"fs": "cephfs4nfs",
"path": "/volumes/nfsexport",
"cluster": "nfs-cluster",
"mode": "RW"
}
nfs 導出創建成功。在可以訪問此服務的主機環境下,運行如下命令掛載 nfs 存儲:
mount -t nfs -o port=2049,nfsvers=4.1,noauto,soft,sync,proto=tcp 169.169.165.85:/fsexport /mnt/mountpoint/cephfs
這樣掛載成功以後,就可以通過目錄 / mnt/mountpoint/cephfs 使用這個數據高可用的存儲了。
5.2 創建 rgw 導出
使用對象存儲提供 nfs 的底層支持有一定的優勢。首先是對象存儲具有比 cephfs 更加簡潔的技術堆棧,數據的讀寫效率比較高。其次對象存儲同樣的具有 ceph 的數據高可用特性。這無疑爲 nfs 的老鐵用戶帶來了無縫升級 nfs 卻又接口無憂的一個技術方案。
不過這部分功能目前還處於初期。其中存在一個 bug 導致 rgw 導出創建以後,ganesha-nfs 服務循環重啓。這個問題得到社區的反饋和關注,已經有一個 PR 正在提交解決中:
lhttps://github.com/rook/rook/pull/11598
在這個修復合併到 master 前,我們可以通過如下步驟繞過這個問題:
創建配置文件 rgw.conf,內容如下:
RGW
{
name = "client.nfs-ganesha.nfs-cluster.a";
}
運行如下命令,設置 nfs-cluster 服務的用戶定義配置:
ceph nfs cluster config set nfs-cluster -i ./rgw.conf
設置完成以後需要重啓 nfs-ganesha 服務。
爬過了這個坑,我們就可以開始創建 rgw nfs 導出了。
使用第 3 節中準備的 RGW 存儲桶,可以藉助 nfs-ganesha 服務在存儲桶 bkt4exp 上完成 nfs export 的創建。運行如下命令:
ceph nfs export create rgw --cluster-id nfs-cluster --pseudo-path /rgwexport --bucket bkt4exp
在可以訪問此服務的主機環境下,使用和 cephfs 導出相同的 nfs-ganesha 服務完成掛載:
mount -t nfs -o port=2049,nfsvers=4.1,noauto,soft,sync,proto=tcp 169.169.165.85:/rgwexport /mnt/mountpoint/rgw
這樣掛載成功以後,就可以通過目錄 / mnt/mountpoint/rgw 使用這個數據高可用的存儲了。
6.總結
目前存在的其他的類似方案一般是非雲原生環境的主機化部署,往往需要繁複的 ceph 命令行操作,對技術棧中各個組件需要單獨的修改配置文件。通過 rook 管理 ceph 集羣,同樣的 ceph nfs 導出配置過程得到很大的簡化。一方面體現了聲明式編程的強大力量。另一方面也能夠看到 operator sdk 爲複雜系統的運維知識的封裝提供了完美的支撐。
至此我們走了一遍基於 cephfs 和 rgw 的 nfs 導出和掛載過程。rook 這方面的相關資料比較少,本文給出了完整的實施步驟,相信對雲原生環境下小夥伴們深入使用 nfs 存儲能夠有所幫助。雖然目前 RGW 導出功能還處於試驗階段。不過通過 cephfs 的導出的 nfs 還是很值得在實際環境中考慮使用的。
另外的一個場景是 nfs 導出服務(nfs-ganesha)的高可用。目前社區還在討論和開發中,相信通過開源社區的協同努力,這方面的需求在不久的將來也能夠得到很好的滿足。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/lhUBPLmJRkIHGya4kd0Qcw