从一开始,在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-statusPOOL 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计数-但无知的开销至少是有限且合理的。