ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Ceph crushtool 实战完全指南:CRUSH map 的编译、构建、测试与调优

Ceph crushtool 实战完全指南:CRUSH map 的编译、构建、测试与调优 存储分布式文件系统对象存储后端高可用【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址https://gitcode.com/gh_mirrors/ce/ceph点击查看免费下载crushtool是 Ceph 中专门用于创建、编译、反编译与测试 CRUSH map的命令行工具。CRUSHControlled Replication Under Scalable Hashing是 Ceph 的核心伪随机数据分布算法它将输入值在 Ceph 语境中对应 Placement Group即 PG高效地映射到异构、分层的设备树device map上。本文以仓库内手册 doc/man/8/crushtool.rst 为主线结合其实现源码 src/tools/crushtool.cc 与位于 src/test/cli/crushtool 的官方 CLI 测试套件系统讲解四种运行模式、--test全套报告选项、tunables 调优、--build分层建模以及 reclassify 迁移等实战能力。读完本文你将能够独立完成 CRUSH map 的生成、编辑、验证、性能评估与故障排查。crushtool 是什么CRUSH 映射的瑞士军刀从手册的 Synopsis 可以看到crushtool的核心用法如下crushtool ( -d map | -c map.txt | --build --num_osds numosds layer1 ... | --test ) [ -o outfile ]它一共有四种主要运行模式模式命令作用编译-c map.txt/--compile将纯文本map.txt编译为二进制 map 文件反编译-d map/--decompile将已编译的二进制 map 反编译为适合编辑的纯文本源文件构建--build --num_osds {num-osds} layer1 ...按给定分层结构创建全新 map测试--test对一段输入值默认[0,1023]可视为模拟的 PG执行 CRUSH 映射的干跑dry runCRUSH 算法最早由论文首次详细描述此后历经演化当前版本对 bucket 类型、tunables 等均有扩展而crushtool正是把该算法从理论落地为可操作工具的关键桥梁。需要特别注意的是与 Ceph 其他工具不同crushtool不接受命令行上的通用选项如--debug-crush。这些选项只能通过CEPH_ARGS环境变量传入。例如要静默 CRUSH 子系统的一切输出CEPH_ARGS--debug-crush 0 crushtool ...在实现层面这一点体现在 src/tools/crushtool.cccrushtool在global_init时仅从环境变量CEPH_ARGS解析参数并显式传入空参数向量从而避免与-ccompile等自带选项产生冲突。五阶段流水线crushtool 的执行模型阅读源码中的 usage() 输出 可以发现crushtool的处理流程并非简单的一命令一动作而是依次执行五个阶段输入/构建阶段input/build读取-i指定的二进制 map、用-d反编译、用-c编译或用--build新建 maptunables 调整阶段通过--set-choose-local-tries、--set-choose-total-tries等选项在内存中修改 map 的调优参数修改阶段modifications--add-item、--move、--reweight、--create-simple-rule等结构性修改显示/测试阶段display/test--dump、--tree、--test及各类--show-*报告输出阶段若 map 被修改modified true用-o outfile写回二进制文件若未指定输出文件则提示Use -o file to write it out。这一流水线结构对应 main() 函数 中输入 → 变更 → 显示 → 输出的代码顺序理解它能帮你合理组合多个选项完成复杂任务例如先-i读入、再--set-*调参、最后-o输出。编译与反编译文本与二进制的双向转换CRUSH map 的二进制文件与人类可读的纯文本源文件可以无损互转# 反编译把二进制 crushmap 转成可编辑的 map.txt crushtool -d crushmap -o map.txt # 编辑 vim map.txt # 重新编译 crushtool -c map.txt -o crushmap在源码中编译路径由 CrushCompiler 完成crushtool创建空的CrushWrapper读取文本文件后交给CrushCompiler::compile()解析若指定了--enable-unsafe-tunables还会允许编译使用不安全的 tunables。反编译则调用CrushCompiler::decompile()输出到-o指定的文件或直接输出到 stdoutsrc/tools/crushtool.cc#L1272-L1286。一个典型的文本 CRUSH map 结构如下摘录自测试样例 src/test/cli/crushtool/set-choose.crushmap.txt# begin crush map tunable choose_local_tries 1 tunable choose_local_fallback_tries 2 tunable choose_total_tries 35 tunable chooseleaf_descend_once 1 # devices device 0 device0 device 1 device1 # types type 0 device type 1 host type 2 rack type 3 root # buckets host host0 { id -1 # do not change unnecessarily # weight 3.00000 alg straw hash 0 # rjenkins1 item device0 weight 1.00000 item device1 weight 1.00000 item device2 weight 1.00000 } # rules rule choose { id 0 type replicated step take root0 step choose firstn 0 type host step choose firstn 1 type device step emit } # end crush map该文件覆盖了 CRUSH map 的全部要素tunable调优参数、device设备声明、type层级类型、bucket含id、alg、hash、item weight以及rule含step take / choose / chooseleaf / emit等步骤。这也是 compile-decompile-recompile.t 等测试反复验证的编译 → 反编译 → 再编译循环可以无差异往返的保证。使用 --build 构建分层 CRUSH map--build模式用于生成层级化的 CRUSH map其命令格式为crushtool -o crushmap --build --num_osds {num-osds} layer1 layer2 ...第一个参数--num_osds指定 CRUSH 层级中设备叶子的数量后续每个layer描述如何对前面的层进行分组。每层由三个组件构成bucket ( uniform | list | tree | straw | straw2 ) size组件含义bucket该层 bucket 的类型名如rack、row、node生成的 bucket 名由类型名追加唯一编号构成如rack0、rack1…第二个组件bucket 算法uniform、list、tree、straw、straw2日常使用推荐strawstraw2为更现代的改进版本第三个组件bucket 的最大容量含子项数0表示容量无限通常用于最顶层的root从源码看支持的 bucket 算法 与文档一一对应构建时每个 OSD 被赋予0x10000即 1.0的初始权重--num_osds通过crush.set_max_devices()设定设备上限并自动生成osd.0、osd.1…… 的名称src/tools/crushtool.cc#L955-L971。实战示例320 个 OSD 的经典机房拓扑手册给出了一个非常典型的例子假设有两个 row排每排两个 rack机柜每个 rack 20 个 node节点每个 node 4 块磁盘用于 Ceph OSD按 42U 机柜、2U 节点留 2U 给机柜交换机计算总共可部署 320 个 OSD。命令如下$ crushtool -o crushmap --build --num_osds 320 \ node straw 4 \ rack straw 20 \ row straw 2 \ root straw 0执行后会直接打印生成的层级树# id weight type name reweight -87 320 root root -85 160 row row0 -81 80 rack rack0 -1 4 node node0 0 1 osd.0 1 1 1 osd.1 1 2 1 osd.2 1 3 1 osd.3 1 -2 4 node node1 4 1 osd.4 1 5 1 osd.5 1 ...从输出可见每一层的权重等于其子项权重之和4 个 OSD × 1 node 权重 45 个 node × 4 rack 权重 20…… 最终 root 权重 320这正是后续 CRUSH 按权重比例分布的依据。值得注意的是当--num_osds无法被某层 size 整除、产生多个根时工具会给出提示并建议追加一层root straw 0将多个根归拢为单一 root。构建完成后工具还会调用OSDMap::build_simple_crush_rules()自动生成与新建 Ceph 集群默认创建相同的 CRUSH rules便于立即用--test验证src/tools/crushtool.cc#L1053-L1073。生成的规则可以用标准的 反编译→编辑→重编译 流程进一步定制# 反编译 crushtool -d crushmap -o map.txt # 编辑 emacs map.txt # 重新编译 crushtool -c map.txt -o crushmap使用 --test 进行映射干跑测试模式读取-i map指定的 CRUSH map对一段输入值执行 CRUSH 映射干跑若指定--simulate则改用随机数生成器模拟放置而非真实 CRUSH 算法用于对照。理解输入值x与 PG 的关系至关重要每个 Placement Group 都有整数 ID可通过ceph pg dump获取例如PG 2.2f表示 pool id 为 2、PG id 为 32。pool ID 与 PG ID 通过函数组合后得到一个值即x交给 CRUSH 映射到 OSD。而crushtool并不感知 PG/pool它只对[--min-x, --max-x]区间内的数值做模拟映射默认[0, 1023]。测试完成后可以生成两类报告--show-...系列选项在 stderr 上输出人类可读信息--output-csv生成由--help-output文档化的 CSV 文件。输入范围与副本数控制测试相关的可选参数来自 usage()参数说明--min-x x/--max-x x/--x x控制输入值范围或指定单个输入值--min-rule r/--max-rule r/--rule r控制测试的规则范围或指定单条规则--min-rep n/--max-rep n/--num-rep n控制副本数范围或指定精确副本数--pool-id n指定 pool id影响 x 的组合方式--batches b将 CRUSH 映射拆分为 b 1 轮进行--weight|-w devno weight临时设定设备权重0 到 1.0用于模拟权重调整--mark-down-ratio/--mark-down-bucket-ratio模拟按比例将设备/bucket 标记为 down评估故障场景--simulate用随机放置代替 CRUSH 算法其中--show-mappings使用时有前置约束必须满足 (a) 指定--num-rep或 (b) 同时指定--min-rep与--max-rep。--num-rep表示 pool 的精确副本数如--num-rep 5--min-rep与--max-rep配合表示一个副本数区间如--min-rep 1 --max-rep 10。这些参数在源码中分别对应CrushTester的set_min_x、set_max_x、set_num_rep、set_min_rep、set_max_rep等 settersrc/tools/crushtool.cc#L758-L817。--show-statistics分布统计摘要显示分布统计摘要例如rule 1 (metadata) num_rep 5 result size 5: 1024/1024含义名为metadata的规则 1在要求num_rep 5副本时成功将1024个输入值映射到result size 5台设备。当映射失败通常是因为tries需要调大时会显示失败明细rule 1 (metadata) num_rep 10 result size 8: 4/1024 rule 1 (metadata) num_rep 10 result size 9: 93/1024 rule 1 (metadata) num_rep 10 result size 10: 927/1024即虽然要求 10 个副本但 1024 个输入值中分别有 4 个只映射到 8 台设备、93 个映射到 9 台、927 个成功映射到 10 台。这是判断 map 是否够用的第一手证据。--show-mappings逐值映射明细显示区间[--min-x, --max-x]内每个值的映射结果CRUSH rule 1 x 24 [11,6]表示规则 1 将输入值 24 映射到设备 [11,6]。测试样例 src/test/cli/crushtool/set-choose.t 中就是先用-c编译set-choose.crushmap.txt再执行crushtool -i set-choose.crushmap --test --show-mappings --show-statistics \ --set-straw-calc-version 0 --min-rep 2 --max-rep 3输出形如rule 0 (choose), x 0..1023, numrep 2..3 CRUSH rule 0 x 0 [0,3] CRUSH rule 0 x 1 [0,8] CRUSH rule 0 x 2 [1,4] ...--show-bad-mappings定位失败映射显示未能映射到所需设备数量的输入值bad mapping rule 1 x 781 num_rep 7 result [8,10,2,11,6,9]含义规则 1 被要求映射 7 台设备但输入值 781 只映射到 6 台[8,10,2,11,6,9]。仓库测试 src/test/cli/crushtool/bad-mappings.t 演示了完整的复现链路$ crushtool -c bad-mappings.crushmap.txt -o bad-mappings.crushmap $ crushtool -i bad-mappings.crushmap --test --show-bad-mappings \ --rule 0 --x 1 --num-rep 10 bad mapping rule 0 x 1 num_rep 10 result [4,0,2,3,1]注意第二条规则测试时结果中出现2147483647这正是 CRUSH 内部用于表示未成功选择的哨兵值对应NONE设备直观展示了失败位置。--show-utilization 与 --show-utilization-all设备负载评估显示每台设备的实际与期望利用率对每个副本数分别统计device 0: stored : 951 expected : 853.333 device 1: stored : 963 expected : 853.333 ...表示设备 0 实际存储了 951 个值而按权重期望存储 853 个。--show-utilization-all输出相同内容但不抑制权重为 0 的设备。两者都隐含启用--show-statistics。源码中对应的开关是tester.set_output_utilization(true)/set_output_utilization_all(true)且两者都会强制set_output_statistics(true)src/tools/crushtool.cc#L1296-L1299。--show-choose-tries选择尝试次数直方图显示为找到设备映射所需的尝试次数分布tries 0: 95224 tries 1: 3745 tries 2: 2225 ..含义95224 个映射一次重试即成功3745 个经过 1 次尝试2225 个经过 2 次…… 行数与--set-choose-total-tries设定的值一致。测试样例 src/test/cli/crushtool/show-choose-tries.t 展示了 50 行tries 1 到 tries 50的典型输出直方图整体越靠左说明 map 选择效率越高。--show-retry-exhaustion重试耗尽检测检查是否有 PG 映射触达最大重试上限通常为 50 次并在检测到时输出告警。这在stretch cluster拉伸集群恰好 2 个数据中心、4 副本场景下尤其有价值由于 CRUSH 的伪随机选择可能反复选中同一个数据中心极少数 PG 会映射失败尽管概率极低仍值得显式检测。检测到耗尽时输出WARNING: Retry exhaustion detected! 5 PG(s) hit the maximum retry limit of 50 This indicates CRUSH failed to find optimal placement for some PGs.未检测到时输出成功信息No retry exhaustion detected (maximum tries needed: 7 / 50)该功能对应CrushTester的show_retry_exhaustion标志及其 setter/getter见 src/crush/CrushTester.h由--show-retry-exhaustion开启src/tools/crushtool.cc#L547-L549。--output-csv 与 --output-name导出离线分析数据--output-csv在当前目录生成 CSV 文件文件以测试所用规则命名。例如规则名为metadata时生成metadata-absolute_weights.csv metadata-device_utilization.csv ...文件首行简述列布局例如metadata-absolute_weights.csv Device ID, Absolute Weight 0,1 ...--output-name NAME可为文件名添加前缀例如--output-name FOO生成FOO-metadata-absolute_weights.csv等。源码中--output-name通过tester.set_output_data_file_name(name -)实现src/tools/crushtool.cc#L732-L740。--help-output可打印所有可导出数据的完整文档对应源码中的 data_analysis_usage()包括数据集含义数据布局absolute_weights每个 OSD 的十进制权重ROW MAJOROSD id (int), weight (int)batch_device_expected_utilization_all每轮放置中每个 OSD 应接收的对象数可为小数COLUMN MAJORround (int), 各 OSD 期望值 (float)batch_device_utilization_all每轮放置中每个 OSD 实际存储的对象数COLUMN MAJORround (int), 各 OSD 实际值 (int)device_utilization_all放置结束后每个 OSD 存储的对象数ROW MAJOROSD id, objects stored (int), objects expected (float)device_utilization放置结束后每个处于 up 状态 OSD 的对象数ROW MAJOROSD id, objects stored (int), objects expected (float)placement_information输入值 → OSD 的完整映射ROW MAJORinput (int), OSDs mapped (int)proportional_weights_allmap 中每个 OSD 的比例权重ROW MAJOROSD id, proportional weight (float)proportional_weights每个 up 状态 OSD 的比例权重ROW MAJOROSD id, proportional weight (float)注意absolute_weights与proportional_weights的区别前者是 CRUSH map 中显式记录的绝对权重后者是归一化到比例后的值。这些 CSV 导出能力对应测试 src/test/cli/crushtool/output-csv.t可用于把模拟结果交给外部工具做离线统计分析。调优参数tunables用 --set-* 修复分布问题--set-...系列选项可以在内存中修改输入 CRUSH map 的 tunables不影响磁盘上的原文件需配合-o写回选项含义--set-choose-local-tries N设置本地选择在重新下降前的重试次数--set-choose-local-fallback-tries N设置使用回退排列前的本地重试次数--set-choose-total-tries N设置总的选择下降尝试次数--set-chooseleaf-descend-once 0\|1设置 chooseleaf 是否只做一次递归下降--set-chooseleaf-vary-r 0\|1设置 chooseleaf 是否基于父级变化 r--set-chooseleaf-stable 0\|1设置 chooseleaf firstn 是否返回稳定结果--set-straw-calc-version N设置 straw bucket 的计算版本--set-allowed-bucket-algs N设置允许的 bucket 算法位掩码实战修复 bad mapping手册给出了一个完整的调优案例。假设当前测试报错$ crushtool -i mymap --test --show-bad-mappings bad mapping rule 1 x 781 num_rep 7 result [8,10,2,11,6,9]即规则 1 在要求 7 副本时对输入值 781 只成功映射了 6 台设备。修复方式是提高choose-total-tries$ crushtool -i mymap --test \ --show-bad-mappings \ --set-choose-total-tries 500调参后若不再输出 bad mapping说明问题正是尝试次数不足随后可通过-o将调整后的 map 写出。在源码中所有--set-*参数解析后统一进入tunables adjustments阶段通过crush.set_choose_total_tries()等 setter 应用到内存中的CrushWrappersrc/tools/crushtool.cc#L1077-L1108。注意这些选项既可用连字符也可用下划线形式--set_choose_total_tries源码中两者都接受。结构性修改增删改设备、bucket 与规则除编译、构建、测试外crushtool还支持对已有 map 做结构修改对应modifications阶段选项作用-i mapfn --add-item id weight name [--loc type name ...]将 item 按给定位置插入层级-i mapfn --update-item id weight name [--loc type name ...]插入或移动 item 到指定位置-i mapfn --remove-item name删除指定 item-i mapfn --reweight-item name weight调整 item 权重并同步调整祖先权重-i mapfn --add-bucket name type [--loc type name ...]在指定位置插入 bucket-i mapfn --move name --loc type name ...将 item 移动到指定位置-i mapfn --reweight重新计算所有 bucket 权重-i mapfn --rebuild-class-roots重建按设备类划分的影子树通常为空操作-i mapfn --create-simple-rule name root type mode创建规则从 root 开始、按 type 桶复制、mode 为firstn或indep-i mapfn --create-replicated-rule name root type创建复制规则等价于 modefirstn 的简化版--device-class class为新规则指定设备类-i mapfn --remove-rule name删除指定规则例如--add-bucket的实现do_add_bucket()会先检查名字是否已存在、bucket 类型是否合法get_type_id必须 0再通过crush.add_bucket()创建并可用--loc定位。这些修改配合-o输出即可实现脚本化的 CRUSH map 演进相关行为均有对应 CLI 测试如 src/test/cli/crushtool/add-item.t、add-bucket.t、reweight.t 等。Reclassify向设备类device class迁移reclassify功能允许用户从为不同 OSD 类型维护并行层级的旧式 CRUSH map平滑过渡到使用device class特性的现代 CRUSH map例如把ssd/hdd分别归入 class 专属 root。crushtool 的 reclassify 相关选项包括选项作用--reclassify对旧式 map 的 bucket 与规则做加类变换--reclassify-bucket bucket-match class default-parent指定匹配的 bucket 前缀/后缀模式、目标类与默认父级--reclassify-root bucket-name class为指定 root bucket 设定类--set-subtree-class bucket-name class为 bucket 之下的所有 item 设定类实现上--reclassify触发crush.reclassify()调用src/tools/crushtool.cc#L1223-L1234--set-subtree-class则调用crush.set_subtree_class()为整个子树批量打标。仓库内 src/test/cli/crushtool/reclassify.t 及 crush-classes 目录下的测试数据a、b、beesly等展示了从旧层级迁移到 class 化 map 的完整输入输出对照。显示与校验辅助选项除--test外展示与校验阶段还有以下常用选项-f/--format--dump以指定格式json、json-pretty、xml、xml-pretty、table、table-kv、html、html-pretty默认json-pretty完整导出 CRUSH map适合脚本解析src/tools/crushtool.cc#L1263-L1270--tree以树形摘要打印 map--bucket-tree--bucket-name仅打印指定 bucket 下的叶子OSD列表--check [max_id]检查是否有 item 引用了未知名称/类型check_name_maps-i mapfn --show-location id显示指定设备 id 的完整位置--compare otherfile使用--test的参数对两个 map 做对比。用官方 CLI 测试套件验证行为crushtool的每个选项行为几乎都有对应的自动化测试位于 src/test/cli/crushtool 目录命名规律为*.t测试脚本配合*.txt/*.crushmap/*.crushmap.txt输入数据。这些测试同时是绝佳的学习样例例如set-choose.t展示--show-mappings--show-statistics--set-straw-calc-version的完整调用与 1024 个输入值的逐行输出bad-mappings.t复现--show-bad-mappings及2147483647哨兵值的输出show-choose-tries.t展示--show-choose-tries的直方图输出output-csv.t验证--output-csv与--output-name的文件生成reclassify.t验证 device class 迁移以及 device-class.t、straw2.t、rules.t 等分别覆盖设备类、straw2 桶算法、规则管理。适用性与关联工具crushtool是 Ceph 发行版自带的工具随 Ceph 软件包一并提供适合在集群部署前离线设计并验证 CRUSH map、在上线后评估数据分布与副本放置质量、以及在调整层级或权重后做影响面预演。它通常与以下工具配合使用cephmon 管理命令可通过ceph osd crush ...在线调整 map也可用ceph pg dump获取 PG 分布用于对照osdmaptoolOSD map 操作工具可将 OSD map 与 CRUSH map 相互导出。需要重申的是crushtool只操作 CRUSH map 本身它不感知 pool/PG 语义只对数值区间做纯算法模拟——因此它是离线、安全、可重复的验证工具任何对线上 map 的改动都应先在--test中验证无误后再应用到集群。本文所依托的手册原文为 doc/man/8/crushtool.rst工具实现位于 src/tools/crushtool.cc测试样例位于 src/test/cli/crushtool读者可结合这些仓库资源进一步深入。手册作者为 John Wilkins、Sage Weil、Loic Dachary其中 Loic Dachary 也是 src/tools/crushtool.cc 的主要贡献者之一。赞分享存储分布式文件系统对象存储后端高可用【免费下载链接】cephCeph is a distributed object, block, and file storage platform项目地址https://gitcode.com/gh_mirrors/ce/ceph点击查看免费下载相关推荐Ceph osdmaptool 完全指南OSD Map 创建、CRUSH 操作、PG 映射分析与 upmap 平衡模拟Ceph osdmaptool 完全指南OSD Map 创建、CRUSH 操作、PG 映射分析与 upmap 平衡模拟 osdmaptool 是 Ceph 发存储分布式文件系统对象存储后端高可用Rook Ceph 高级配置实战指南命名空间、ceph.conf 覆盖、CRUSH 调优与 OSD 扩容Rook Ceph 高级配置实战指南命名空间、ceph.conf 覆盖、CRUSH 调优与 OSD 扩容 本文围绕 Rook 提供的 Ceph 存储集群高级配云原生存储容器编排运维Nuxt 调试完全指南Source Map、Node Inspector 与 IDE 断点调试实战Nuxt 调试完全指南Source Map、Node Inspector 与 IDE 断点调试实战 调试是开发全栈 Vue 应用Nuxt时最高频的技术环节前端后端Web框架SSR创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表