從一開始,在Ceph中選擇和調整PG數量一直是管理Ceph集羣中最令人沮喪的部分之一。 選擇適當資源池的指南令人困惑,來源之間不一致,並且經常被警告和例外所包圍。 最重要的是,如果選擇了錯誤的值,獺並不總是可以進行糾正,並且性能和/或穩定性會受到影響。 Nautilus之前的Ceph版本中的關鍵限制是,如果pg_num值太小,則總是可以增加它,但是如果它太高,則不能減小它。
不再!。在Nautilus中,池的pg_num值可以降低。更重要的是,可以啓用pg autotuner,該組件允許系統自動進行任何適當的調整,以便用戶可以完全忽略pg_num調整的前期技巧。
PG是什麼?
RADOS(Ceph的底層存儲層)中存儲的數據對象被分組到邏輯池中。 池具有複製因子,糾刪碼方案之類的屬性,並且可能具有僅將數據放置在HDD或SSD上的規則。 在內部,根據存儲在池中對象名稱的哈希值將池分爲pg_num placement groups或PG。 因此,每個placement group都是整個池的僞隨機slice(切片),shard(分段)或fragment (片段),並且特定PG中的所有對象都被分組並一起存儲在同一組存儲設備(OSD)上。
對象很少的小池只需要幾個PG。大型池(例如,包含集羣中存儲的大部分數據的池)需要大量PG,以確保數據分佈在多個設備上,從而平衡所有OSD上的空間利用率,並在系統負載時提供良好的並行性。
PG太少會對少數存儲設備的性能造成瓶頸,而PG過多會使Cave的行爲效率低下-在極端情況下甚至不穩定-這是因爲管理每個PG需要進行內部跟蹤。
標準的經驗法則是,我們希望每個OSD大約有100個PG,但要計算出系統中每個池的PG數量-同時考慮複製和糾刪碼等因素-可能是一項挑戰。
PG分裂和合並
自2012年以來,Ceph就一直支持PG“分裂”,使現有PG可以將其內容“拆分”爲許多較小的PG,從而增加了池中PG的總數。 這使集羣開始時很小,然後隨時間增長而擴展。 從Nautilus開始,我們現在還可以將兩個現有PG“合併”到一個更大的PG中,從而減少PG的總數。 如果池中的相對數據量隨着時間的推移而減少,從而需要或適當地減少了PG,或者整個集羣都縮小了,或者所選的PG的初始數量太大,則這很有用。
傳統上,當PG數量增加時,PG分裂是一氣呵成的。例如,要將池的pg_num值從16調整爲64,只需
$ ceph osd pool set foo pg_num 64
集羣將16個PG中的每個PG一次性分割成4個片段。 以前,還需要第二步來調整這些新PG的位置,以便將它們存儲在新設備上:
$ ceph osd pool set foo pgp_num 64
這是移動實際數據的開銷最大的部分。從Nautilus開始,第二步不再是必需的:只要pgp_num和pg_num當前匹配,pgp_num就會自動跟蹤任何pg_num更改。更重要的是,根據新的target_max_misplace_rate配置選項(默認爲0.05或5%),逐步調整pgp_num以遷移數據並(最終)收斂到pg_num,以限制系統上的數據遷移負載。也就是說,默認情況下,Ceph會嘗試讓不超過5%的數據處於“錯位”狀態,並排隊等待遷移,從而限制對客戶端工作負載的影響。
PG合併的工作方式與分裂類似,不同之處在於內部pg_num值總是每次一次減少一個PG。 合併是一個更爲複雜和精細的過程,需要將PG的IO暫停幾秒鐘,並且一次合併一個PG可使系統將影響最小化並簡化整個過程。 當使用以下命令減少foo池的pg_num時,將設置一個內部pg_num_target值,該值指示pg_num的所需值,並且集羣會慢慢收斂於該值。 例如,要將pool foo的PG從64降低到4,
$ ceph osd pool set foo pg_num 4
$ ceph osd pool ls detail | grep foo
pool 1 'foo' replicated size 3 min_size 2 crush_rule 0 object_hash rjenkins pg_num 63 pgp_num 62 pg_num_target 4 pgp_num_target 4 autoscale_mode warn last_change 391 lfor 0/391/389 flags hashpspool stripe_width 0
PG auto-scaler
調整pg_num值的能力是向前邁出的關鍵一步,但它並未解決PG調整問題,對於大多數用戶而言,這似乎是不可思議的事情。 Nautilus包括一個稱爲pg_autoscaler的新管理器模塊,該模塊允許集羣考慮每個池中實際存儲(或預期要存儲)的數據量,並自動選擇適當的pg_num值。
由於爲pg_autoscaler是新的,因此需要在Nautilus中顯式啓用它:
$ ceph mgr module enable pg_autoscaler
autoscaler是按每個池配置的,可以在以下幾種模式下運行:
- **警告(warn)**模式:如果建議的pg_num值與當前值相差太大,則會發出健康警告。 這是新池和現有池的默認設置。
- **啓用(on)**模式:無需任何管理員交互即可自動調整池pg_num。
- **禁用(off)**模式:還可以爲任何給定池關閉autoscaler,讓管理員像以前一樣手動管理pg_num。
要爲特定池啓用autoscale,
$ ceph osd pool set foo pg_autoscale_mode on
啓用後,可以通過CLI查詢所有池的當前狀態和建議的調整。 例如,在我們的實驗集羣上,我們有:
$ ceph osd pool autoscale-status
POOL SIZE TARGET SIZE RATE RAW CAPACITY RATIO TARGET RATIO PG_NUM NEW PG_NUM AUTOSCALE
device_health_metrics 18331k 3.0 431.3T 0.0000 1 warn
default.rgw.buckets.non-ec 0 3.0 431.3T 0.0000 8 warn
default.rgw.meta 2410 3.0 431.3T 0.0000 8 warn
default.rgw.buckets.index 38637k 3.0 431.3T 0.0000 8 warn
default.rgw.control 0 3.0 431.3T 0.0000 8 warn
default.rgw.buckets.data 743.5G 3.0 431.3T 0.0050 32 on
.rgw.root 1113 3.0 431.3T 0.0000 8 warn
djf_tmp 1169G 3.0 431.3T 0.0079 4096 32 off
libvirt-pool 2048M 3.0 431.3T 0.0000 3000 4 off
data 66692G 3.0 431.3T 0.4529 4096 warn
default.rgw.log 8146k 3.0 431.3T 0.0000 8 warn
metadata 54050M 4.0 431.3T 0.0005
您會注意到,大部分數據位於存儲所有QA結果的CephFS的“元數據”和“數據”池中。大多數其他池是各種測試遺留下來的,(大部分)是空的。
讓我們看一下每一列:
- SIZE列僅報告存儲在池中的數據總量(以字節爲單位)。 這包括對象數據和omap鍵/值數據。
- TARGET SIZE報告有關池的預期大小的任何管理員輸入。如果池剛剛創建,則最初不會存儲任何數據,但管理員通常對最終將存儲多少數據有所瞭解。如果提供,則使用此值或實際大小中的較大者來計算池的理想PG數。
- RATE值是原始存儲佔用與存儲的用戶數據的比率,對於複本桶(bucket)來說,它只是一個複製因子,對於糾刪碼池來說,它是一個(通常)較小的比率。
- RAW CAPACITY是池由CRUSH映射到的存儲設備上的原始存儲容量。
- RATIO是池佔用的總存儲空間的比率。
- TARGET RATIO是管理員提供的值,類似於TARGET SIZE,它表示用戶預計池將佔用集羣總存儲的多大部分。
- 最後,PG_NUM是池的當前PG數量,而NEW PG_NUM(如果存在)是建議值。
- AUTOSCALE列指示池的模式,可以是禁用、警告或啓用。
建議的值考慮了幾個輸入,包括池佔用(或預期佔用)的整體羣集的比例、池分佈在哪些OSD上,以及每個OSD的目標PG數(由mon_target_pg_per_osd配置選項定義,默認爲100)。autoscaler將始終選擇一個2的冪的pg_num值,因爲這對於Ceph而言效率更高(這意味着同一池中的所有PG的大小都大致相同),並且只有當建議的值大於實際值的三倍時,autoscaler纔會建議更改pg_num。這意味着,在大多數情況下,不斷增長的池的pg_num值在每次更改時都會躍升4倍,並且除非其大小有非常顯著的變化,否則將傾向於保持相同的值。
首次設置集羣時,通常設置池的target ratio很有幫助,以便autoscaler可以做出良好的初始決策。 例如,如果集羣的主要用途是用於塊存儲,則可以將rbd池的target ratio設置爲.8並啓用PG auto-scaling:
$ ceph osd pool create foo 1
$ rbd pool init foo
$ ceph osd pool set foo target_size_ratio .8
$ ceph osd pool set foo pg_autoscale_mode on
此時,集羣將自行選擇一個pg_num並將其應用於後臺。
您可以使用以下命令控制將pg_autoscale_mode用於新創建的池
$ ceph config set global osd_pool_default_autoscale_mode <mode>
我可以完全放手嗎?
是。如果您爲新池啓用自動擴展,並在現有池上啓用它,則隨着數據存儲在集羣中,系統將向上擴展PG。
這種方法的唯一問題是在存儲數據後調整PG計數會在集羣中移動數據,這很昂貴。 根據經驗,如果創建了一個空池,然後將其填充以佔用集羣的所有可用空間,那麼寫入的所有數據將在寫入後大約移動一次。 這不是理想的選擇-最好在創建池時提供target ratio或target bytes值,以便選擇適當的初始PG計數-但無知的開銷至少是有限且合理的。