手把手教你搭建 Ceph+JuiceFS

JuiceFS發表於2023-12-08

Ceph 提供了物件儲存,可作為儲存引擎在 JuiceFS 中使用。這一組合非常適合雲端計算、大資料分析和機器學習等資料密集型應用場景。

在日常部署中可直接透過 Ceph RADOS 配合 JuiceFS 使用,無需部署 RGW。基於此方案實踐以及運維中的常見問題,結合Ceph 官方檔案整理了這篇部落格,旨在幫助那些不太熟悉 Ceph 的工程師順利部署和運維 Ceph,並與 JuiceFS 進行對接。

閱讀之前,簡單接下來操作中涉及到的 Ceph 基本概念:

  • cephadm 是 Ceph 叢集專門的運維管理工具,我們會用他初始化 Ceph 叢集

  • OSD(Object Storage Daemon)是 Ceph 叢集的儲存服務例項,分配給 Ceph 使用的每一塊盤,都由一個 OSD 來負責管理

  • 放置組(Placement Group,PG)可以簡單想象成是 Ceph 中的「虛擬目錄」,為 Ceph 中儲存的大量物件進行分組。同一目錄下的變更操作會加鎖執行,而不同的目錄之間可以進行併發操作。因此 PG 的數目如果太小,會由於衝突導致效能不佳,PG 數目過大,消耗的資源也會上升。在下方的教程裡會遵循官方推薦的經驗值計算方法進行設定

環境準備

檔案中以下方環境作為示範:

  • 作業系統:Ubuntu 22.04 LTS
  • 核心版本:5.15.0-72-generic
  • 資料盤:每臺節點 8 塊本地 NVME SSD
  • 記憶體:256G
  • Ceph 版本:quincy v17.2.6

共計 16 節點,每個節點 8 塊 SSD 盤(未格式化),在開始操作前,首先在 1 號節點配置好所有節點的免密登入,並且將節點資訊記錄在 /etc/hosts,類似:

10.38.0.1 ceph-node01
10.38.0.2 ceph-node02
10.32.0.3 ceph-node03
...
10.32.0.16 ceph-node16

準備完畢以後,接下來會把 ceph-node01 做為操作(兼 Ceph 主控)節點,接下來將會在這臺機上進行所有 Ceph 相關的安裝、運維操作,因此提前安裝 pssh,方便後續批次操作:

apt install pssh

pssh 也就是 Parallel SSH,可以方便地併發 SSH 到多個節點、批次執行命令,這個工具需要讀取主機列表,因此將所有節點(主控除外)的主機名記錄到文字檔案裡:

ceph-node02
ceph-node03
...

節點基礎設施

如果尚未搭建時鐘同步,需要手動安裝:

apt install chrony

# 檢視能連線到的 servers
# 如外網不通則需要改配置連內部伺服器,如果不清楚如何配置,聯絡雲服務商技術支援
chronyc sources

# 時鐘同步需要在所有節點設定,此處僅示範批次安裝 chrony 的命令
# 如果需要更多配置,需要自行操作
parallel-ssh -h hosts.txt -i apt install chrony

如果節點開啟了 swap(檢查 /etc/fstab 是否存在 swap 字樣),那麼首先需要對所有節點禁用 swap:

swapoff -a
# 將 fstab 中的專案進行註釋禁用
sed -i.bak "s/\/swap.img/# \/swap.img/" /etc/fstab

# 在主控節點上執行上方命令以後,還需要批次在所有其他節點執行
parallel-ssh -h hosts.txt -i swapoff -a
parallel-ssh -h hosts.txt -i 'sed -i.bak "s/\/swap.img/# \/swap.img/" /etc/fstab'

安裝 Ceph

Docker 和映象搬運

在所有節點上安裝 Docker:

apt install docker.io
parallel-ssh -h hosts.txt -i apt install docker.io

在後續的安裝過程中,ceph 和 node-exporter 這兩個映象是所有節點都需要的,因此推薦提前拉取下來、手動分發到所有節點。如果不做這一步,後續 cephadm 會從官方源拉,取決於當地網路環境,可能會非常慢。

docker image save quay.io/ceph/ceph quay.io/prometheus/node-exporter | gzip > images.tar.gz
parallel-scp -h hosts.txt ./images.tar.gz /tmp/
parallel-ssh -h hosts.txt -i 'docker load -i /tmp/images.tar.gz'

# 確認所有節點都載入成功後,清理映象
parallel-ssh -h hosts.txt -i rm /tmp/images.tar.gz

部署 Ceph 主控

Ubuntu 22 可以方便地從系統源安裝 cephadm,但對於其他 Ubuntu 版本或者其他系統,則可能需要手動安裝,詳見 Ceph 下載安裝

# 在主控節點安裝部署工具,需確認其版本為 quincy(17.2.6),這在 Ubuntu 22 已經是預設提供的版本
apt install cephadm

# 如果你的系統 apt 源提供的版本不滿足要求,則需額外手動從 Ceph 官方網站下載
# 比方說 Ubuntu 20(focal),就需要用下方命令手動安裝
# wget https://download.ceph.com/debian-17.2.6/pool/main/c/ceph/cephadm_17.2.6-1focal_amd64.deb
# dpkg -i ./cephadm_17.2.6-1focal_amd64.deb

# 手動安裝完 cephadm 後,還需要額外將 Ceph 相關的軟體源納入到包管理器的 repo 列表
# 該命令是為了下一步能夠安裝版本符合要求的 ceph-common
# cephadm add-repo --release quincy

# 安裝 Ceph 相關的各種工具
apt install ceph-common

初始化叢集,其中 mon-ip 為主控機的內網地址,多網路卡叢集可以額外指定內部網路,比如 --cluster-network 10.90.90.0/24

# 命令執行完畢以後,會列印 Ceph Dashboard 的賬號密碼,注意儲存
cephadm --image quay.io/ceph/ceph:v17.2.6-20230920 bootstrap --mon-ip 10.38.0.1 --log-to-file

Ceph 主控程式上線後,會生成自己的金鑰,需要將其安裝到所有節點:

# 列印公鑰,複製內容
cat /etc/ceph/ceph.pub

# 撰寫命令,批次執行
parallel-ssh -h hosts.txt -i 'echo ssh-rsa xxx ceph-xxx >> /root/.ssh/authorized_keys'

公鑰安裝完畢以後,主控節點就能登入所有 worker 節點進行運維操作了。進入 Ceph 管理容器,後續命令都在這個管理容器內執行。但考慮到主控節點已經在宿主機層面安裝了所有需要的工具,事實上不進入 cephadm shell 也是完全可以的。

# 執行該命令以後,會進入容器,但是 prompt 不會有任何變化
cephadm shell

# 可以列印程式,識別當前是在宿主機,還是容器內
ps -ef

確認叢集初始狀態,並進行一系列預調優:

# 檢視叢集狀態
ceph -s

# 禁用掉無用的 nfs 模組
ceph mgr module disable nfs

# 預設每個 OSD 記憶體上限 4G
# 在 Ceph 叢集中,一塊盤(塊裝置)會部署為一個 OSD
# 每節點 8 塊盤,記憶體 256G,因此給與 16G 更大的記憶體上限
# 調整過後,OSD 佔用的記憶體總上限為 128G,還有充足冗餘
ceph config set osd osd_memory_target 17179869184

組建 Ceph 叢集

將所有節點新增進 Ceph 叢集,前 5 臺節點(含主控)打上 _admin 標籤,後續的節點則不需要。考慮到節點眾多,將其撰寫為指令碼執行:

# 主控節點早已是叢整合員,不需要 add
# 因此為 ceph-node[02:04] 新增 _admin 標籤,其他節點則不需要
ceph orch host add ceph-node02 10.32.0.2 --labels _admin
...
ceph orch host add ceph-node16 10.32.0.16

至此,所有節點都已經加入 Ceph 叢集,會自動探測節點下的可用塊裝置,具體而言,未經格式化、無人使用的盤,均會探測到。不必擔心,在執行後續 add osd 前,這個過程不會對盤做任何修改。

# 檢視所有節點可用的盤,確認與現場實際情況匹配,也就是所有的空盤都探測到了、沒有壞盤
ceph orch device ls

# 非新盤需要先格式化
# ceph orch device zap host0 /dev/nvme0n1 --force

# 把所有節點的所有空閒 SSD 都新增為 Ceph OSD
# 執行完這個命令後,盤就歸 Ceph 管理了
# 注意按順序逐個新增以保證 ID 有序,這個過程耗時很長,建議做成指令碼執行
ceph orch daemon add osd ceph-node01:/dev/nvme0n1
ceph orch daemon add osd ceph-node01:/dev/nvme1n1
...
ceph orch daemon add osd ceph-node16:/dev/nvme7n1

# 部署 OSD 過程中,用這個命令檢視進度、狀態
ceph orch ps --daemon_type osd

建立儲存池

所有盤都順利部署為 OSD 後,就可以建立儲存池(pool),然後對接 JuiceFS 檔案系統開始使用了。建立儲存池之前,務必瞭解 Ceph 中支援的兩種儲存模式:

  • 副本模式(replication):預設每個物件儲存 3 份(size=3)。與之伴隨的另一個概念叫「最小可用副本數」,預設為 2(min_size=2),意為最少需要 2 個正常執行的副本,才能進行 I/O 操作。可想而知,在預設的 size=3,min_size=2 的配置下,最多允許 1 個副本損壞,這也是最適宜生產環境的設定。如果改為 size=2,min_size=1,那麼所有物件就只有 2 副本,如果任一出現故障,資料將只存一份,丟失的風險增加。副本模式下的故障域也和叢集的配置相關,在節點數 ≧ 3 的情況下,Ceph 會自動將副本分散到不同的節點上,因此對於預設的副本引數,允許任意一臺節點異常而不影響服務。

  • 糾刪碼模式(erasure code, EC):相比副本模式提供更好的儲存效率,但糾刪碼本身也帶來一定的計算資源損耗。如果希望優先節約磁碟空間,可以選取該模式;

# 兩個數字是放置組(placement group)個數,需要相同
# 取值公式:num_osd * 100 / 3 並向上取 2 的冪,num_osd 是 128,因此此處取 4096
ceph osd pool create jfsvol 4096 4096 replicated
ceph osd pool application enable jfsvol juicefs

糾刪碼模式的建立命令示範:

# EC 4+2 池(stripe unit 預設是 4K)
# ceph osd erasure-code-profile set jfs-ec k=4 m=2 stripe_unit=8192
# ceph osd pool create ec-pool 32 32 erasure jfs-ec

至此,Ceph 部署完可以投入使用,推薦先跳過下方的監控告警小節,直接對接 JuiceFS 檔案系統。對接完成後,再搭建監控也不遲。

對接 JuiceFS 檔案系統

建立 JuiceFS 檔案系統,Bucket 名稱對齊儲存池名稱,也就是上方建立好的 jfsvol。然後按照檔案操作掛載。

在 CSI 驅動中掛載對接了 Ceph 的 JuiceFS 檔案系統,為了讓 Ceph 配置檔案對 JuiceFS 客戶端可見,需要把他們上傳到 Kubernetes Secret:

# 上傳之前,確保配置檔案末尾有換行符,否則後續掛載可能引發異常
echo >> ceph.conf
echo >> ceph.client.admin.keyring

kubectl create secret generic ceph-secret --from-file=ceph.conf=ceph.conf --from-file=ceph.client.admin.keyring=ceph.client.admin.keyring

建立好 Secret 以後,還需要在檔案系統認證資訊裡新增 configs 欄位:

apiVersion: v1
kind: Secret
metadata:
  name: jfsvol-secret
type: Opaque
stringData:
  name: jfsvol
  token: xxx
  access-key: ceph
  secret-key: client.admin
  # 將上方建立的 ceph-secret 掛載到 /etc/ceph
  configs: '{"ceph-secret": "/etc/ceph/"}'

運維

Ceph 是很成熟的儲存方案,如果規劃和運維正確,能夠很穩定地執行。閱讀下方小節瞭解常見的運維要點。

部署監控

Cephadm 部署時,會預設安裝自己的 Grafana,並且預設與其 Dashboard 進行了整合。你可以直接使用這個 Dashboard 進行監控告警,也可以選擇對接已有的外部 Grafana。

如果希望複用環境中已有的外部 Grafana,那麼首先瀏覽器開啟這個 Grafana 的地址,點選左側邊欄 Administration,新增資料來源,把 Ceph 叢集的 Prometheus 地址填進去,預設是 http://<ceph-master-ip>:9095,如果你不確定具體埠號,也可以去主控節點 ss -lntp | grep prometheus 確認現場情況。測試並儲存資料來源。

Prometheus 新增成功後,匯入社群的 Ceph Grafana Dashboard,監控就搭建完畢了,這個 Dashboard 裡已經內建了告警規則,後續配置好告警傳送通道以後,就能直接開始執行。

容量監控和故障恢復

可以方便地用 ceph -s 檢視當前用量,在上一小節中匯入的皮膚裡,也已經包含了容量監控規則,對 Ceph 各個層面的容量佔用進行監控:

  • CephNodeRootFilesystemFull:節點根分割槽用量監控

  • CephOSDNearFull|CephOSDFull|CephOSDBackfillFull:OSD 相關容量監控

  • CephPoolNearFull|CephPoolFull|CephPoolBackfillFull:儲存池相關容量監控

上方報警項中,如果 Ceph 系統寫滿,那麼會觸發 CephOSDFull|CephPoolFull,同時 Ceph 不再允許寫入——這是很不妙的情況,因為對於 Ceph 而言,「刪」事實上也屬於寫請求,在 CephPoolFull 的情況下,即便是客戶端發起刪請求,Ceph 也會進行攔截,讓請求無法完成、直至超時。出現這種故障時,如果無法立刻加盤擴容,那麼處置步驟如下:

  1. 定位到問題檔案系統,接下來將會清理該檔案系統、釋放容量,因此需要:
  • 提前將回收站設定為 0,否則即便刪除了檔案,也會移入回收站進行儲存,無法釋放物件儲存容量

  • 推薦在業務側操作下線停寫(考慮到 Ceph 此時已經容量超限,所有的寫請求都會卡死),這並不是必要的,只是為了增加後續運維動作的容錯率

  1. 選取該檔案系統的一個可用客戶端,進入掛載點,清理檔案、釋放容量。

  2. 在 JuiceFS 掛載點刪除足量的檔案,如果 Ceph 一側沒有立即釋放容量,則說明遇到了上方提到的「容量超限時,無法執行刪除」的死鎖問題,這時需要登入 Ceph 主控節點,將閾值臨時提高,來允許刪除請求。操作前必須確保業務已經停寫,否則一旦放開閾值,就會迅速寫滿,再次引發故障。

# mon_osd_full_ratio 預設為 0.95,臨時調高以允許寫入
ceph osd set-full-ratio 0.96

# 放開閾值後,緊密觀察容量是否釋放

ceph -s
4. 確認容量釋放,準備回滾 full ratio 設定。這一步也需要謹慎操作:將 full ratio 回滾,必須保證操作不會再次讓叢集處於容量超限的狀態、中斷業務寫入。因此先執行 ceph df 核實已用空間佔比(%USED)。

如果 %USED 低於 90%,那麼可以執行下方命令回滾配置:

ceph osd set-full-ratio 0.95

為了改善容量超限的處置流程,JuiceFS 客戶端支援在 Ceph 叢集寫滿的情況下進行刪除操作(詳見社群版相關程式碼變更),因此對於新版客戶端,不再需要用 set-full-ratio 進行臨調。

擴容

由於是最為常見的擴容方法,本小節只介紹用增添新盤來擴大叢集容量的操作。

插盤已經在所有節點完成後,執行命令確認新盤:

# 輸出表格裡,AVAILABLE=Yes 的即為探測到的新盤
# 確認新盤引數符合預期
ceph orch device ls

在建立新的 OSD 之前,推薦先手動禁用資料均衡。這是由於盤數量可能比較多,OSD 建立需要格式化盤,整個操作耗時會比較長。如果在預設開啟資料遷移的狀態下加盤,每一個新盤都會伴隨著資料遷移。為了避免低效的資料反覆遷移,建議在所有新盤納入 Ceph 後,再統一開啟。

# 禁用資料均衡
ceph osd set nobackfill

# 確認生效
ceph -s | grep backfill

接下來執行命令新增新盤,操作和建立 Ceph 叢集中的相關步驟是完全一樣的,在對應的小節裡搜尋 ceph orch daemon add osd 命令,將所有新盤按順序新增,就可以了。如果待新增的盤數量眾多,建議提前撰寫指令碼執行。

所有盤新增完成後,執行下方命令進行收尾:

# 確認所有新盤均已加入叢集(AVAILABLE=No)
ceph orch device ls

# 重新開啟資料均衡
ceph osd unset nobackfill

相關文章