高性能存儲Ceph:3個生產案例學習Ceph運維技巧
本文轉載自微信公眾號「新鈦云服」,作者祝祥 翻譯。轉載本文請聯系新鈦云服公眾號。
Ceph是一個統一的分布式存儲系統,設計初衷是提供較好的性能、可靠性和可擴展性。
Ceph項目最早起源于Sage就讀博士期間的工作(最早的成果于2004年發表),并隨后貢獻給開源社區。在經過了數年的發展之后,目前已得到眾多云計算廠商的支持并被廣泛應用。
RedHat及OpenStack都可與Ceph整合以支持虛擬機鏡像的后端存儲。同時Ceph也為Kubernetns提供塊,文件,對象存儲。
當在各種生產場景中使用Ceph作為網絡存儲時,我們可能會面臨著很多的生產場景。這里有一些案例:
- 在新集群中部分使用舊的服務器的情況下,將數據遷移到新的Ceph新的實例節點中;
- 解決Ceph中磁盤空間分配的問題。
為了處理這些問題,我們需要在保持數據完整的同時正確刪除OSD。在海量數據的情況下,這一點尤其重要。這就是我們將在本文中介紹的內容。
下述方法適用于各種版本的Ceph (除非特別說明)。另外,我們將考慮到大量數據可以存儲在Ceph中這一場景,因此我們將把某些步驟分解成較小的步驟——以防止數據丟失和其他問題。
關于OSD的幾句話
由于本文所涉及的三種場景中有兩種是與OSD(對象存儲守護程序)有關,因此在深入探討之前,我們先簡單討論一下OSD及其重要性。
首先,應該注意,整個Ceph集群由一組OSD組成。它們越多,Ceph中的可用數據量就越大。因此,OSD的主要目的是跨群集節點存儲對象數據,并提供對其的網絡訪問(用于讀取,寫入和其他查詢)。
通過在不同OSD之間復制對象,可以將復制參數設置為同一級別。這也是您可能會遇到問題的地方(我們將在本文后面提供解決方案)。
案例1:優雅地從Ceph集群中移除OSD
當需要從群集中移除OSD的時候,這很可能是集群硬件變更的需求(例如,將一臺服務器替換為另一臺服務器)。這也正是我們當前所遇到的場景,同時也是這一實際場景觸發我們寫了這篇文章。
因此,我們的最終目標是刪除服務器上的所有OSD和監視器,以便可以將服務器安全下架。
為了方便起見并避免在執行命令時選擇錯誤的OSD,讓我們定義一個單獨的變量,其中包含所需OSD的編號。我們將其稱為${ID}。從現在開始,此變量將替換我們正在使用的OSD的數量。
首先,讓我們看一下OSD映射關系:
- root@hv-1 ~ # ceph osd tree
- ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
- -1 0.46857 root default
- -3 0.15619 host hv-1
- -5 0.15619 host hv-2
- 1 ssd 0.15619 osd.1 up 1.00000 1.00000
- -7 0.15619 host hv-3
- 2 ssd 0.15619 osd.2 up 1.00000 1.00000
為了使OSD安全脫離群集,我們必須將reweight緩慢降低到零。這樣,我們就可以通過重新均衡的方式,將當前需要移除的OSD數據遷移到其他OSD中。
為此,請運行以下命令:
- ceph osd reweight osd.${ID} 0.98
- ceph osd reweight osd.${ID} 0.88
- ceph osd reweight osd.${ID} 0.78
…依此類推,直到權重為零。
但是,如果使用norebalance呢?
另外,還有一個解決方案是使用norebalance+backfill。首先,禁用重新均衡:
- ceph osd set norebalance
現在,您必須將新的OSD添加到CRUSH MAP中,并將舊OSD的權重設置為0。對于要刪除和添加的OSD,將主要親和力設置為0:
- ceph osd primary-affinity osd.$OLD 0
- ceph osd primary-affinity osd.$NEW 0
然后減小backfill到1并取消norebalance:
- ceph tell osd.* injectargs --osd_max_backfill=1
- ceph osd unset norebalance
之后,Ceph集群將開始數據遷移。
注意:這個解決方案是非常可行的,但是你必須考慮到具體的情況與需求。當我們不想在任何OSD Down時造成過多的網絡負載時,我們就可以使用norebalance。
`osd_max_backfill`允許您限制再均衡速度。因此,重新均衡將減慢速度從而降低網絡負載。
遵循的步驟
我們必須要逐步重新均衡從而避免數據丟失。如果OSD包含大量數據,則更要如此。如果要確保在運行reweight命令后是否一切正常,可以運行ceph -s查看集群當前的健康狀態。
此外,您可以在單獨的終端窗口中運行ceph -w以實時監視數據遷移的過程。
清空OSD之后,您可以開始按照標準操作來刪除它。為此,將選定的OSD設置為以下down狀態:
- ceph osd down osd.${ID}
現在是時將OSD移出群集了:
- ceph osd out osd.${ID}
停止OSD并卸載其卷:
- systemctl stop ceph-osd@${ID}
- umount /var/lib/ceph/osd/ceph-${ID}
從CRUSH MAP中刪除OSD:
- ceph osd crush remove osd.${ID}
刪除OSD身份驗證密鑰:
- ceph auth del osd.${ID}
最后,刪除OSD:
- ceph osd rm osd.${ID}
注意:對于Luminous(及更高版本)的Ceph版本,可以將上述步驟簡化為:
- ceph osd out osd.${ID}
- ceph osd purge osd.${ID}
現在,如果您運行ceph osd tree命令,您應該看到服務器的OSD已經被移除:
- root@hv-1 ~ # ceph osd tree
- ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF
- -1 0.46857 root default
- -3 0.15619 host hv-1
- -5 0.15619 host hv-2
- -7 0.15619 host hv-3
- 2 ssd 0.15619 osd.2 up 1.00000 1.00000
請注意,您的Ceph群集狀態將變為HEALTH_WARN,OSD的數量以及可用磁盤空間的數量將減少。
下面,我們將提供完全停止服務器并將其從Ceph中刪除所需的步驟。我們必須提醒您,在停止服務器之前,必須移除該服務器上的所有OSD。
從服務器中移除所有OSD之后,可以通過運行以下命令從CRUSH MAP中刪除服務器hv-2:
- ceph osd crush rm hv-2
通過在另一臺服務器(即 hv-1)上運行以下命令,從服務器hv-2上刪除監視器:
- ceph-deploy mon destroy hv-2
之后,您可以停止服務器并繼續執行其他操作(例如重新部署等)。
案例2:在現有的Ceph集群中分配磁盤空間
現在,讓我們從第二個案例開始,詳細講講放置組PG(https://docs.ceph.com/docs/mimic/rados/operations/placement-groups/)。PG(Placement Group)是 Ceph 中非常重要的概念,它可以看成是一致性哈希中的虛擬節點,維護了一部分數據并且是數據遷移和改變的最小單位。
它在 Ceph 中承擔著非常重要的角色,在一個 Pool 中存在一定數量的 PG (可動態增減),這些 PG 會被分布在多個 OSD ,分布規則可以通過 CRUSH RULE 來定義。
Monitor 維護了每個Pool中的所有 PG 信息,比如當副本數是3時,這個 PG 會分布在3個 OSD 中,其中有一個 OSD 角色會是 Primary ,另外兩個 OSD 的角色會是 Replicated。
Primary PG負責該 PG 的對象寫操作,讀操作可以從 Replicated PG獲得。而 OSD 則只是 PG 的載體,每個 OSD 都會有一部分 PG 角色是 Primary,另一部分是 Replicated,當 OSD 發生故障時(意外 crash 或者存儲設備損壞),Monitor 會將PG的角色為 Replicated的 OSD 提升為 Primary PG,而這個故障 OSD 上所有的 PG 都會處于 Degraded 狀態。
然后等待管理員的下一步操作, 如果原來所有Replicated的 OSD 無法啟動, OSD 會被踢出集群,這些 PG 會被 Monitor 根據 OSD 的情況分配到新的 OSD 上。
從上面可以看出,Ceph中的放置組主要聚合Ceph對象并在OSD中執行數據復制。Ceph文檔(https://docs.ceph.com/docs/mimic/rados/operations/placement-groups/#choosing-the-number-of-placement-groups)中提供了如何選擇PG數量的公式。
您還可以在其中找到有關如何計算所需PG數量的案例。
Ceph的存儲池之間的OSD和PG數量不一致是Ceph運行過程中最常見的問題之一。總體而言,正確數量的PG是Ceph集群健康運行的必要條件。下面,我們將看看不正確的PG數量配置會發生什么?
通常,PG的數量設置與以下兩個問題密切相關:
PG數量太少會導致均衡大數據塊的問題。
另一方面,數量過多的PG則會導致性能問題。
實際上,還有另一個更危險的問題:其中一個OSD中的數據溢出。其原因是,Ceph在估算可寫入池中的理論數據量時依賴于OSD中的可用數據量。您可以通過命令ceph df 查看每個存儲池的MAX AVAIL字段,從而獲知每個存儲池的最大可用量。如果出現一個OSD容量不足,則在所有OSD之間正確分配數據之前,您將無法寫入更多數據。
事實上在配置Ceph集群時可以解決以上問題。Ceph PGCalc(https://ceph.io/pgcalc/)是推薦使用的工具之一。它可以幫助您配置正確的PG。有一點需要特別注意,修復PG的常見場景之一是您很可能需要減少PG的數量。但是,較早的Ceph版本并不支持此功能(從Nautilus版本開始可用)。
好的,讓我們想象一下這種場景:由于某一個OSD空間不足(如HEALTH_WARN: 1 near full osd),集群處于HEALTH_WARN狀態。下面介紹了處理這種情況的方法。
首先,您需要在可用的OSD之間重新分配數據。當從集群中移除OSD時,在案例1中我們做了同樣的事情。唯一的區別是,現在我們需要稍微減少weight權重。例如,降至0.95:
- ceph osd reweight osd.${ID} 0.95
這樣,您可以釋放OSD中的磁盤空間并修復ceph運行狀況錯誤。但是,正如之前提到的,此問題主要是由于Ceph的初始配置不正確引起的。最佳的做法是重新配置群集,以防止以后再次發生此類錯誤。
在我們的場景中,所有這些都歸結為以下的兩種原因:
其中一個池的replication_count過高,
其中一個池中的PG數量過多,而另一個池中的PG數量不足。
下面,讓我們使用PGCalc計算器。它非常簡單,在指定了所有必需的參數之后,我們得到以下建議:
注意:PGCalc能夠生成一組命令,這些命令可以快速創建存儲池,這對那些從頭開始安裝與配置Ceph集群的人可能會是一個非常有用的功能。
最后一欄Suggested PG Count輸出推薦的PG數量值。在我們的場景中,您還應該注意第二列(Size),該列指定每個池的副本數(因為我們已經修改了副本數)。
因此,首先,我們需要更改存儲池的副本,我們可以通過減小replication_size參數來釋放磁盤空間。在命令處理過程中,您將看到可用磁盤空間會增加:
- ceph osd pool $pool_name set $replication_size
命令運行結束后,我們還必須修改pg_num和pgp_num參數,如下所示:
- ceph osd pool set $pool_name pg_num $pg_number
- ceph osd pool set $pool_name pgp_num $pg_number
注意:我們必須依次更改每個池中的PG數量,直到“n-number of pgs degraded”和“Degraded data redundancy”告警消失。
您可以使用ceph health detail和ceph -s命令檢查一切是否順利。
案例3:將VM從LVM遷移到Ceph RBD
Ceph的很多問題都是出現在虛擬化平臺的使用上。在這樣的存儲使用場景中有充足的空間也是非常必要的。另外一種常見的情況是服務器使用的是本地存儲的VM。您想擴展它的磁盤,但是也沒有足夠的可用空間。
有很多種方法可以解決此類問題。例如,您可以將虛擬機遷移到另外一臺物理服務器(如果有匹配條件的物理服務器節點),或在物理服務器上添加新的物理磁盤。但是,有時候,這些方法都不可行。在這種情況下,從LVM到Ceph的遷移可能是一個比較好的解決方案。通過這種方法,不需要將本地存儲從一個虛擬化節點遷移到另一個虛擬化節點,因此我們簡化了跨節點遷移。但是,有一個注意點:您必須停止VM,直到遷移完成。
我們的后續步驟是基于這個指南(http://blog.easter-eggs.org/index.php/post/2013/09/27/Libvirt-Migrating-from-on-disk-raw-images-to-RBD-storage)。我們已經成功測試了此處提供的解決方案。順便說一句,它還描述了無停機遷移的方式。但是,由于我們不要求使用此功能,因此我們尚未對其進行驗證。
那么實際步驟是什么?在我們的示例中,我們使用virsh命令。首先,確保目標Ceph池已連接到libvirt:
- virsh pool-dumpxml $ceph_pool
存儲池的描述必須包含所有必需的信息和憑據才能連接到Ceph。
下一步涉及將LVM鏡像轉換為Ceph RBD。轉換過程的持續時間主要取決于鏡像的大小:
- qemu-img convert -p -O rbd /dev/main/$vm_image_name
- rbd:$ceph_pool/$vm_image_name
轉換完成后,將仍然保留LVM鏡像。如果將VM遷移到RBD失敗,這將派上用場,而您必須回滾所做的更改。為了能夠快速回滾更改,讓我們備份VM的配置文件:
- virsh dumpxml $vm_name > $vm_name.xml
- cp $vm_name.xml $vm_name_backup.xml
編輯原始的vm_name.xml文件。查找磁盤的描述(以<disk type='file' device='disk'>開頭和以</disk>結尾),并按如下所示進行修改:
- <disk type='network' device='disk'>
- <driver name='qemu'/>
- <auth username='libvirt'>
- <secret type='ceph' uuid='sec-ret-uu-id'/>
- </auth>
- <source protocol='rbd' name='$ceph_pool/$vm_image_name>
- <host name='10.0.0.1' port='6789'/>
- <host name='10.0.0.2' port='6789'/>
- </source>
- <target dev='vda' bus='virtio'/>
- <alias name='virtio-disk0'/>
- <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
- </disk>
仔細查看細節:
- source協議字段中包含Ceph的RBD存儲池的路徑。
- secret字段包含ceph密碼的類型以及UUID。您可以使用以下virsh secret-list命令找出UUID 。
- host字段包含Ceph監視器的地址。
編輯完配置文件并將LVM成功轉換為RBD后,您可以應用修改后的xml文件并啟動虛擬機:
- virsh define $vm_name.xml
- virsh start $vm_name
現在該檢查虛擬機是否正常運行了。為此,您可以通過SSH或使用virsh直接連接到物理節點。
如果VM正常運行,并且沒有任何其他問題的提示,則可以刪除LVM鏡像,因為不再需要它:
- lvremove main/$vm_image_name
結論:在生產環境中,我們遇到了以上這些問題。我們希望我們的解決方式能夠幫助到您。當然,在Ceph的運維過程中所遇到的問題不僅僅是這些,還可能會更多,但只要遵循標準化操作,問題最終都能被圓滿解決。



























