Files
wiki/存储/Ceph/知识库/06-ceph-volume-磁盘管理篇.md
2026-09-18 13:49:11 +08:00

1932 lines
97 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第 06 册 · ceph-volume 磁盘管理篇
> 基于 Ceph 官方文档整理 | 文档版本:**Tentacle v20.2.4** | 抓取日期:2026-09-17 | 源文:ceph/ceph@v20.2.4 `doc/ceph-volume/`
> 官网入口:https://docs.ceph.com/en/tentacle/ceph-volume/
---
## 本册导读
### 本册覆盖的官方页面(共 24 个 rst 源文)
| # | 源文路径 | 页面标题 | 本册章节 |
|---|---------|---------|---------|
| 1 | `ceph-volume/index.rst` | ceph-volume | 一、本册导读 |
| 2 | `ceph-volume/intro.rst` | Overview | 一 |
| 3 | `ceph-volume/systemd.rst` | systemd | 二 · systemd 集成 |
| 4 | `ceph-volume/inventory.rst` | inventory | 五 |
| 5 | `ceph-volume/drive-group.rst` | drive-group | 六 |
| 6 | `ceph-volume/lvm/index.rst` | lvm | 二 |
| 7 | `ceph-volume/lvm/prepare.rst` | prepare | 二 |
| 8 | `ceph-volume/lvm/activate.rst` | activate | 二 |
| 9 | `ceph-volume/lvm/create.rst` | create | 二 |
| 10 | `ceph-volume/lvm/batch.rst` | batch | 二 |
| 11 | `ceph-volume/lvm/list.rst` | list | 二 |
| 12 | `ceph-volume/lvm/scan.rst` | scan | 二 |
| 13 | `ceph-volume/lvm/zap.rst` | zap | 二 |
| 14 | `ceph-volume/lvm/migrate.rst` | migrate | 二 |
| 15 | `ceph-volume/lvm/newdb.rst` | new-db | 二 |
| 16 | `ceph-volume/lvm/newwal.rst` | new-wal | 二 |
| 17 | `ceph-volume/lvm/encryption.rst` | Encryption | 二 · 加密 |
| 18 | `ceph-volume/lvm/systemd.rst` | systemd(lvm) | 二 · systemd 集成 |
| 19 | `ceph-volume/simple/index.rst` | simple | 三 |
| 20 | `ceph-volume/simple/scan.rst` | scan(simple) | 三 |
| 21 | `ceph-volume/simple/activate.rst` | activate(simple) | 三 |
| 22 | `ceph-volume/simple/systemd.rst` | systemd(simple) | 三 |
| 23 | `ceph-volume/zfs/index.rst` | zfs | 四 |
| 24 | `ceph-volume/zfs/inventory.rst` | inventory(zfs) | 四 |
### 建议阅读顺序
| 阶段 | 读什么 | 目的 |
|------|--------|------|
| 1 | 本册第一章「ceph-volume 是什么」 | 建立定位:它替代谁、有哪些后端、处在 OSD 生命周期哪一段 |
| 2 | `inventory`(第五章) | 先学会「看清这台机器上有哪些盘、哪些能用」,这是所有操作的前提 |
| 3 | `lvm prepare` → `lvm activate` → `lvm create` | 理解 OSD 部署的两步模型与一步模型 |
| 4 | `lvm batch` + `drive-group`(第六章) | 学会多盘批量部署与预演 |
| 5 | `lvm list` / `scan` / `zap` | 日常巡检、发现与回收 |
| 6 | `lvm migrate` / `new-db` / `new-wal` | 运维期的 db/wal 迁移与扩容 |
| 7 | `encryption` + `systemd` | 加密原理与开机自启动机制 |
| 8 | `simple` / `zfs` | 历史兼容与边缘平台,按需了解 |
> 💡 补充:如果你只打算做「临时验证」或「单盘快速起一个 OSD」,最短路径是 `ceph-volume lvm inventory` → `ceph-volume lvm batch --report ...`(预演)→ 去掉 `--report` 实跑。
### ceph-volume 与 cephadm 的关系(重要)
- **日常部署由 cephadm 调用,你通常不需要直接敲 `ceph-volume`。** 现代 Ceph 集群(Octopus 之后)通过 `cephadm` / `orch` 管理 OSD,`cephadm` 在内部调用 `ceph-volume` 完成实际的设备准备与激活;`ceph-volume lvm activate` 页面明确写着「For information about OSDs deployed by cephadm, refer to :ref:`cephadm-osd-activate`」,即 cephadm 部署的 OSD 激活要看 cephadm 那一侧。
- **但理解底层很重要**,原因有三:
1. **排障需要**:OSD 起不来、设备被跳过、db/wal 没按预期分配,最终都要落到 `ceph-volume` 的日志与 LVM tag 上去判断。
2. **运维动作仍在 ceph-volume 层**:`zap`、`migrate`、`new-db`、`new-wal`、`list` 这些子命令,很多场景需要人工直接执行(例如换盘、迁移 db、擦除设备)。`newdb.rst` 中的 spillover 修复流程甚至混用了 `cephadm shell` + `ceph-bluestore-tool`。
3. **概念复用**:drive group 最终会被翻译成「一次 `ceph-volume lvm batch` 调用」(`drive-group.rst`、`batch.rst` 均如此表述),不理解 `batch` 就看不懂 drive group 实际做了什么。
- **边界提示**:由 cephadm 部署的 OSD,激活相关操作请优先使用 cephadm 提供的入口,不要混用 `ceph-volume lvm activate`。
> 引自:[ceph-volume](https://docs.ceph.com/en/tentacle/ceph-volume/)
---
## 一、ceph-volume 是什么
### 1.1 定位
`ceph-volume` 是一个**单一用途的命令行工具**,用来把逻辑卷(logical volume)部署成 OSD,并在 prepare / activate / create OSD 这些动作上尽量保持与老工具 `ceph-disk` 相似的 API。
它的设计目标:
- 用**可插拔的 tool/plugin** 来支持不同的设备技术(LVM、裸盘/GPT 分区、ZFS 等);`lvm` 本身就被当作一个 plugin 对待。
- 走一条**可预测、健壮**的 prepare → activate → start OSD 的路径。
- **刻意不依赖 udev 规则**:这一点与 `ceph-disk` 根本不同。`ceph-disk` 依赖随 Ceph 安装的 udev 规则来自动发现此前已配置好的设备并回喂给自身去激活。
### 1.2 它替代了什么:为什么 `ceph-disk` 被替换
`ceph-disk` 诞生于需要同时支持 upstart、sysvinit 等多种 init 系统、又要能发现设备的年代,因此它把全部重心压在了 **GPT 分区(尤其 GPT GUID)** 上,用 GUID 来回答:
- 这个设备是 Journal 吗?
- 是一个加密的数据分区吗?
- 这个设备是不是处于「部分 prepared」的半途状态?
它用 `UDEV` 规则匹配这些 GUID,规则回调 `ceph-disk`,而 `ceph-disk` 又与自己的 systemd unit 来回交互。官方对该机制的评价是:
> 这个过程非常不可靠、非常耗时(**每个 OSD** 不得不设置接近三小时的超时),并且会导致节点启动过程中 OSD 完全起不来。由于 UDEV 的异步行为,这些问题很难调试、甚至很难复现。
此外,因为 `ceph-disk` 的世界观只能是 GPT 分区,它**无法与 LVM 或其他 device mapper 设备协作**。最终社区决定做一个模块化的东西,从 LVM 起步,并保留扩展其他技术的能力。
### 1.3「GPT 分区很简单」其实是个误解
虽然「分区」本身容易理解,但 `ceph-disk` 的分区一点都不简单——它需要大量特殊标志配合设备发现流程。创建一个数据分区的实际调用长这样:
```bash
/sbin/sgdisk --largest-new=1 --change-name=1:ceph data \
--partition-guid=1:f0fc39fd-eeb2-49f1-b922-a11939cf8a0f \
--typecode=1:89c57f98-2fe5-4dc0-89c1-f3ad0ceff2be --mbrtogpt -- /dev/sdb
```
更难的是,这些分区要求设备被 Ceph **独占**。例如加密时还要额外建一个存放未加密密钥的特殊分区(lockbox):
```bash
/sbin/sgdisk --new=5:0:+10M --change-name=5:ceph lockbox \
--partition-guid=5:None --typecode=5:fb3aabf9-d25f-47cc-bf5e-721d181642be \
--mbrtogpt -- /dev/sdad
```
这些都属于 `ceph-disk` 的领域知识,无法被简化成「GPT 分区很简单」的理解。
### 1.4 模块化设计与支持的后端
`ceph-volume` 被设计成模块化工具,因为可以预见到「人们配置硬件设备的方式」会越来越多。官方点名的几种:
| 后端(plugin) | 子命令 | 适用场景 | 本册章节 |
|---------------|--------|---------|---------|
| `lvm` | `ceph-volume lvm` | **新部署的推荐后端**。可用任意 logical volume 作为 data OSD 输入,也可以从一块设备自动建一个 minimal/naive 的 logical volume | 二 |
| `simple` | `ceph-volume simple` | 接管此前由 `ceph-disk` 部署的、带 GPT 分区的遗留 OSD。扫描 data device 或 OSD 目录后彻底禁用 `ceph-disk`。**完全支持加密** | 三 |
| `zfs` | `ceph-volume zfs` | 用于运行 FreeBSD 集群(index.rst:「zfs support is available for running a FreeBSD cluster」) | 四 |
| SPDK | 文档未明确子命令 | 官方称「直接在用户态管理 NVMe 设备的 SPDK 已在近期地平线上」,因为完全不经过内核,LVM 在那里行不通 | 见「文档未明确项」 |
> 引自:[Overview](https://docs.ceph.com/en/tentacle/ceph-volume/intro/)
### 1.5 迁移路径(从 ceph-disk 到 ceph-volume)
从 Ceph **13.0.0** 起 `ceph-disk` 已废弃(deprecated),废弃警告会链接到 ceph-volume 文档页。官方强烈建议用户改用 `ceph-volume`。两条迁移路径:
| 路径 | 做法 | 说明 |
|------|------|------|
| 保留原 OSD | 用 `ceph-volume simple` 接管管理 | 接管的同时禁用 `ceph-disk` 的触发器(triggers) |
| 重新部署 | 用 `ceph-volume` 重新部署既有 OSD | 详见 `rados-replacing-an-osd`(本册范围外) |
### 1.6 新部署 / 既有 OSD 的官方建议
- **新部署**:推荐 `ceph-volume lvm`。
- **已有 OSD**(由 `ceph-disk` 配置):用 `ceph-volume simple` 接管,对 data device 或 OSD 目录做一次 scan,之后 `ceph-disk` 被完全禁用,加密也完全支持。
### 1.7 LVM tags:ceph-volume 的元数据基石
`ceph-volume lvm` 子命令通过 **LVM tags** 存储、并能在之后重新发现和查询与 OSD 关联的设备,从而完成激活。这是它与 `ceph-disk`(靠 GPT GUID + udev)最本质的技术分野。
### 1.8 LVM 的性能代价
官方的表述非常直接:
> 简而言之:我们没有发现任何与改用 LVM 相关的显著性能损失。并且由于能与 LVM 紧密协作,与其他 device mapper 技术协作的能力是顺理成章的——任何能位于 Logical Volume 之下的东西,在技术上都没有难度。
### 1.9 与 OSD 生命周期的关系
| 生命周期阶段 | 由谁负责 | 对应子命令 |
|-------------|---------|-----------|
| 设备发现 / 可用性判断 | `ceph-volume inventory` | 见第五章 |
| 规划与批量选择 | `ceph-volume lvm batch`(drive group 翻译而来) | `--report` 预演 |
| 准备(写元数据、建 LV、`ceph-osd --mkfs`) | `lvm prepare` | 写 LVM tags,**不改动卷的其他内容** |
| 激活(挂载、建 tmpfs、起 unit) | `lvm activate` | enable systemd unit |
| 一步到位 | `lvm create` = `prepare` + `activate` | |
| 运行期巡检 | `lvm list` | |
| 运行期调整 db/wal | `lvm migrate` / `lvm new-db` / `lvm new-wal` | |
| 退役 / 回收 | `lvm zap`(`--destroy`) | |
| 遗留接管 | `simple scan` → `simple activate` | |
> 引自:[ceph-volume](https://docs.ceph.com/en/tentacle/ceph-volume/)、[Overview](https://docs.ceph.com/en/tentacle/ceph-volume/intro/)
---
## 二、lvm 后端(重点)
`lvm` 子命令实现了从 LVM 部署 OSD 所需的全部功能:`ceph-volume lvm`。
官方列出的用户可见子命令:`prepare`、`activate`、`create`、`list`、`migrate`、`new-db`、`new-wal`。
(`scan` 在 `lvm/index.rst` 的 toctree 中被注释为 `not yet implemented`,见 2.9。)
> 引自:[lvm](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/)
### 2.1 四个核心动作:prepare / activate / create / batch 的区别与选择
| 子命令 | 干什么 | 是否立即 up/in | 是否联系 monitor 申请 OSD ID | 幂等 | 典型场景 |
|--------|--------|---------------|---------------------------|------|---------|
| `prepare` | 给 LV 打上 Ceph 元数据(LVM tags),创建 OSD 目录与符号链接,取 monmap,用 `ceph-osd --mkfs` 填充目录。**不改动卷的其他内容** | 否 | 是(除非显式给 `--osd-id`/`--osd-fsid`) | 文档未明确 | 想**逐步**把新 OSD 引入集群、避免一次性大量数据 rebalance |
| `activate` | 启用 systemd unit,把 OSD ID + UUID 持久化;挂载设备、确保设备就绪、启动 `ceph-osd@<id>` | 是 | 否(消费已有 ID/UUID) | **是(fully idempotent)** | 与 `prepare` 配合的两步流程第二步 |
| `create` | 把 `prepare` + `activate` 包成一次调用 | **是,命令结束即 up and in** | 同 `prepare` | 文档未明确 | 单盘/少量盘、不在意瞬时 rebalance 的场合 |
| `batch` | 基于 `create` 的同一套代码路径,额外负责**计算所有卷的合适大小**并**跳过已创建的卷**;一次部署多个 OSD | 是 | 同 `create` | **是(设计为幂等)** | 多盘批量部署;drive group 的实际执行者 |
**怎么选:**
- 想**平滑扩容**(一次只放一个 OSD 进集群,控制 rebalance 速率)→ `prepare` 然后 `activate`。
- 想**一条命令搞定**、且能接受 OSD 立刻 up/in → `create`。
- 有**一批盘**要一起上,或你其实在用 drive group → `batch`,并且**先用 `--report` 预演**。
- 关于 `create` 的官方提醒:`prepare` + `activate` 分开做的价值在于「逐步引入新 OSD,避免大量数据被 rebalance」。`create` 除了「OSD 会在完成后立刻 up and in」之外,过程与两步完全一致。
> 引自:[prepare](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/prepare/)、[activate](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/activate/)、[create](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/create/)、[batch](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/batch/)
---
### 2.2 `prepare`:参数逐项说明
`prepare` 会给 logical volume **添加元数据,但不会以任何其他方式改动它**。官方建议:先自行 provision 一个 logical volume,再在其上跑 `prepare`。
`prepare` 用 **LVM tags** 给 LV 打上若干元数据,被这样打标的卷更容易识别、也更容易被 Ceph 使用;tags 用来标识 LV 在集群中扮演的角色(例如:BlueStore data 或 BlueStore WAL+DB)。
#### 2.2.1 通用 / bluestore 参数表
| 参数 | 默认值 | 含义 | 示例 |
|------|--------|------|------|
| `--bluestore` | **默认后端**(文档称 BlueStore 是新 OSD 的默认后端) | 指定 OSD 后端为 bluestore。Ceph 允许改后端,可通过此 flag 显式指定 | `ceph-volume lvm prepare --bluestore --data vg/lv` |
| `--data` | 无(必填) | 指定 `block` 设备(即主数据设备)。可接受**物理块设备**、**物理设备上的分区**、或 **logical volume** 三种形态 | `--data vg/lv`、`--data /path/to/device` |
| `--block.db` | 无(bluestore 下可选) | 指定 `block.db` 设备。可为物理设备、分区或 logical volume | `--block.db /dev/sda1` |
| `--block.wal` | 无(bluestore 下可选) | 指定 `block.wal` 设备。可为物理设备、分区或 logical volume | `--block.wal /dev/ceph/osd-wal-0` |
| `--dmcrypt` | 关闭 | 启用 dmcrypt 加密。启用加密时**必须**带此 flag | `--dmcrypt --data vg/lv` |
| `--with-tpm` | 关闭 | **自 Ceph Squid 起可用**:为创建的 LUKS2 设备选择 TPM2 token enrollment。需与 `--dmcrypt` 同用 | `--dmcrypt --with-tpm --data vg/lv` |
| `--crush-device-class` | 文档未明确 | 设置该 OSD 的 CRUSH device class | `--crush-device-class foo` |
| `--osd-id` | 由 monitor 分配 | 指定 OSD ID。给定后命令行**不会**去联系 monitor 生成 OSD ID | `--osd-id 0` |
| `--osd-fsid` | 运行时生成 UUID | 指定 OSD FSID(UUID) | `--osd-fsid E3D291C1-E7BF-4984-9794-B60D9FA139CB` |
| `--filestore` | 非默认 | 指定 filestore 后端(**Reef 起已废弃且不再支持**) | `--filestore --data <dev>` |
| `--journal` | 无(filestore 下可选) | filestore 的 journal 设备。可为物理块设备、分区、logical volume | `--journal /dev/sdc1` |
#### 2.2.2 bluestore 支持的配置组合
| 组合 | 说明 |
|------|------|
| block + block.wal + block.db | 三者齐全 |
| block + block.wal | 有 WAL 无独立 DB |
| block + block.db | 有 DB 无独立 WAL |
| block(单设备) | 只有一个 block 设备 |
#### 2.2.3 关于设备形态的重要规则
- 对 `--data`:如果给的是**物理块设备**,会**自动创建 logical volume**。
- 如果提供的 volume group 名字以 `ceph` 开头:不存在则创建,已存在则**被 clobber 并复用**。这让 LVM 用法更简单,但代价是不灵活——**没有任何选项或配置可以改变 logical volume 的创建方式**。
- 对 `--block.db` / `--block.wal`:**分区可以原样使用**,因此不会被做成 logical volume。
- 命名约定(当传入设备、由 ceph-volume 自建 VG/LV 时):
- volume group 名:`ceph-{cluster fsid}`;若该 VG 已存在,则为 `ceph-{random uuid}`
- logical volume 名:`osd-block-{osd_fsid}`
#### 2.2.4 典型命令
```bash
# 最简:在已有 LV 上准备
ceph-volume lvm prepare --bluestore --data vg/lv
# 直接给裸设备(会自动创建 VG/LV)
ceph-volume lvm prepare --bluestore --data /path/to/device
# 启用 dmcrypt 加密
ceph-volume lvm prepare --bluestore --dmcrypt --data vg/lv
# 启用 dmcrypt + TPM2 token enrollment(Squid+)
ceph-volume lvm prepare --bluestore --dmcrypt --with-tpm --data vg/lv
# 指定 CRUSH device class
ceph-volume lvm prepare --bluestore --data vg/lv --crush-device-class foo
```
#### 2.2.5 OSD 目录与符号链接
创建 OSD 目录时,流程使用一个 **`tmpfs` 挂载**来存放 OSD 所需文件;这些文件由 `ceph-osd --mkfs` 创建,是**临时(ephemeral)**的。
`block` 设备会创建符号链接,`block.db` 与 `block.wal` 的符号链接是可选的。默认集群名 + OSD ID 为 0 时:
```bash
ls -l /var/lib/ceph/osd/ceph-0
```
```text
lrwxrwxrwx. 1 ceph ceph 93 Oct 20 13:05 block -> /dev/ceph-be2b6fbd-bcf2-4c51-b35d-a35a162a02f0/osd-block-25cf0a05-2bc6-44ef-9137-79d65bd7ad62
lrwxrwxrwx. 1 ceph ceph 93 Oct 20 13:05 block.db -> /dev/sda1
lrwxrwxrwx. 1 ceph ceph 93 Oct 20 13:05 block.wal -> /dev/ceph/osd-wal-0
-rw-------. 1 ceph ceph 37 Oct 20 13:05 ceph_fsid
-rw-------. 1 ceph ceph 37 Oct 20 13:05 fsid
-rw-------. 1 ceph ceph 55 Oct 20 13:05 keyring
-rw-------. 1 ceph ceph 6 Oct 20 13:05 ready
-rw-------. 1 ceph ceph 10 Oct 20 13:05 type
-rw-------. 1 ceph ceph 2 Oct 20 13:05 whoami
```
OSD 数据目录命名约定:
```text
/var/lib/ceph/osd/<cluster name>-<osd id>
```
#### 2.2.6 filestore(已废弃,仅供历史理解)
> ⚠️ 官方 warning:**Filestore 在 Reef 版本已废弃,不再被支持。**
- filestore 用一个 logical volume 存 OSD 数据,用物理设备/分区/logical volume 存 journal。
- 若用物理设备创建 filestore 后端,会在该设备上创建 logical volume。
- 若提供的 VG 名以 `ceph` 开头:不存在则建,已存在则 clobber 并复用。
- 对这些卷无需特殊准备,但要满足 OSD 数据与 journal 的**最小容量要求**(具体数值文档未明确)。
```bash
# 基本 filestore OSD
ceph-volume lvm prepare --filestore --data <data block device>
# 带外部 journal
ceph-volume lvm prepare --filestore --data <data block device> --journal <journal block device>
# 启用加密(--dmcrypt 必需)
ceph-volume lvm prepare --filestore --dmcrypt --data <data block device> --journal <journal block device>
```
**filestore 的形态约束:**
- 用 logical volume 部署时,传入值**必须**是 `volume_group/logical_volume_name` 格式。因为 LV 名不强制唯一,这个格式是防止选错卷(并 clobber 掉数据)的重要保障。
- 用分区部署时,分区**必须**含有一个能被 `blkid` 发现的 `PARTUUID`,以确保无论设备名/路径如何变化都能被正确识别。
```bash
# LV 存数据 + 分区做 journal
ceph-volume lvm prepare --filestore --data volume_group/logical_volume_name --journal /dev/sdc1
# 裸设备存数据 + LV 做 journal
ceph-volume lvm prepare --filestore --data /dev/sdc --journal volume_group/journal_lv
```
向集群申请新 OSD 时会使用一个**生成的 UUID**。OSD ID 与 OSD UUID 这两项信息是识别某个 OSD 的必要条件,并会在后续整个 activation 流程中使用。
filestore 手工流程(文档给出的完整步骤):
```bash
# 1. 把 journal 卷链接到已挂载的数据卷
ln -s /path/to/journal /var/lib/ceph/osd/<cluster_name>-<osd-id>/journal
# 2. 用 OSD 的 bootstrap key 抓取 monmap
/usr/bin/ceph --cluster ceph --name client.bootstrap-osd --keyring \
/var/lib/ceph/bootstrap-osd/ceph.keyring mon getmap -o \
/var/lib/ceph/osd/<cluster name>-<osd id>/activate.monmap
# 3. 填充已挂载的 OSD 目录
ceph-osd --cluster ceph --mkfs --mkkey -i <osd id> --monmap \
/var/lib/ceph/osd/<cluster name>-<osd id>/activate.monmap --osd-data \
/var/lib/ceph/osd/<cluster name>-<osd id> --osd-journal \
/var/lib/ceph/osd/<cluster name>-<osd id>/journal --osd-uuid <osd uuid> \
--keyring /var/lib/ceph/osd/<cluster name>-<osd id>/keyring --setuser ceph \
--setgroup ceph
```
#### 2.2.7 分区(Partitioning)
**`ceph-volume lvm` 目前不会从整块设备创建分区。** 如果你要用分区,唯一要求是它含有 `PARTUUID` 且能被 `blkid` 发现——`fdisk` 和 `parted` 新建分区时都会自动带上。
用 `parted` 在一块全新未格式化的盘(此处为 `/dev/sdd`)上建分区的完整过程:
```bash
# 1) 先看看设备信息
parted --script /dev/sdd print
```
```text
Model: VBOX HARDDISK (scsi)
Disk /dev/sdd: 11.5GB
Sector size (logical/physical): 512B/512B
Disk Flags:
```
```bash
# 2) 设备还没有 label,先建 gpt label 并复查
parted --script /dev/sdd mklabel gpt
parted --script /dev/sdd print
```
```text
Model: VBOX HARDDISK (scsi)
Disk /dev/sdd: 11.5GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:
```
```bash
# 3) 建一个分区,并确认 blkid 能找到 ceph-volume 需要的 PARTUUID
parted --script /dev/sdd mkpart primary 1 100%
blkid /dev/sdd1
```
```text
/dev/sdd1: PARTLABEL="primary" PARTUUID="16399d72-1e1f-467d-96ee-6fe371a7d0d4"
```
#### 2.2.8 对既有 OSD 使用 prepare
> ⚠️ 官方 warning:**该过程会强制格式化数据设备,销毁其上的既有数据(如果有的话)。**
需要注意:
- OSD 路径应遵循约定 `/var/lib/ceph/osd/<cluster name>-<osd id>`
- 最好不要存在其他挂载该卷的机制,已有的应移除(如 fstab 挂载点)
对 ID 为 0、集群名为 `ceph` 的既有 OSD,一次性过程如下(**会销毁该 OSD 中所有数据**):
```bash
ceph-volume lvm prepare --filestore --osd-id 0 --osd-fsid E3D291C1-E7BF-4984-9794-B60D9FA139CB
```
命令行工具此时**不会**联系 monitor 生成 OSD ID,并且除了格式化 LVM 设备外,还会把元数据存储其上,以便之后能启动。
#### 2.2.9 multipath 支持
`multipath` 设备在 `lvm` 配置正确的前提下是被支持的。
| 方式 | 说明 |
|------|------|
| **交给 LVM** | 大多数 Linux 发行版的 LVM2 包默认配置中带 `multipath_component_detection = 1`。有了这个设置,LVM 会忽略任何属于 multipath 组成部分的设备,`ceph-volume` 也就不会去碰这些设备。 |
| **使用 filters** | 如果该设置不可用,则必须在 `lvm.conf` 中提供正确的 `filter` 表达式。`ceph-volume` **绝不能**同时使用 multipath 设备及其成员设备。 |
#### 2.2.10 prepare 阶段写入的 LVM tags
无论卷类型(journal 或 data)或 OSD objectstore 是什么,准备过程都会打上以下 tags:
- `cluster_fsid`
- `encrypted`
- `osd_fsid`
- `osd_id`
- `crush_device_class`
对 **bluestore**,还会额外添加:
- `block_device`
- `block_uuid`
- `db_device`
- `db_uuid`
- `wal_device`
- `wal_uuid`
> 💡 补充:在 `lvm list --format=json` 的实际输出中,可以看到 tags 的真实书写形式为 `ceph.` 前缀,例如 `ceph.osd_id=0`、`ceph.cluster_fsid=...`、`ceph.data_device=...`、`ceph.data_uuid=...`、`ceph.journal_device=...`、`ceph.journal_uuid=...`、`ceph.osd_fsid=...`、`ceph.type=data`。即 `osd_id` 在可读报告里显示为 `osd id`,实际 tag 名是 `ceph.osd_id`。(依据:`lvm/list.rst` 的 json 输出样例与 note。)
#### 2.2.11 prepare 流程小结(bluestore)
1. 接受原始物理设备、物理设备上的分区或 logical volume 作为参数。
2. 在任何原始物理设备上创建 logical volume。
3. 为 OSD 生成一个 UUID。
4. 用生成的 UUID 向 monitor 申请一个 OSD ID。
5. 在 tmpfs 挂载上创建 OSD 数据目录。
6. `block`、`block.wal`、`block.db` 若已定义则建立符号链接。
7. 抓取 monmap 以备激活。
8. 由 `ceph-osd` 填充数据目录。
9. 用 lvm tags 给 Logical Volume 打上全部 Ceph 元数据。
> 引自:[prepare](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/prepare/)
---
### 2.3 `activate`:参数逐项说明
`prepare` 跑完后,卷就可以被激活了。激活包括启用一个 systemd unit,该 unit 会持久化 `OSD ID` 与其 `UUID`(也就是 Ceph CLI 工具里的 `fsid`)。这些信息持久化后,集群就能判断哪个 OSD 被启用、必须被挂载。
> ⚠️ 注意:该调用**完全幂等**(fully idempotent)——可以重复执行,不会改变首次成功执行的结果。
> ⚠️ 注意:由 cephadm 部署的 OSD,请参考 cephadm 的 OSD activate 文档,而不是直接用本子命令。
#### 2.3.1 参数表
| 参数 / 位置参数 | 默认值 | 含义 | 示例 |
|---------------|--------|------|------|
| `<osd id>`(位置参数) | 无 | 要激活的 OSD ID | `0` |
| `<osd uuid>`(位置参数) | 无 | 要激活的 OSD UUID(fsid) | `0263644D-0BF1-4D6D-BC34-28BD98AE3BC8` |
| `--all` | 关闭 | 一次性激活所有已存在(由 ceph-volume 创建但处于 inactive)的 OSD。已运行的会被报告出来并跳过,因此可安全重跑(幂等) | `ceph-volume lvm activate --all` |
| `--bluestore` | 文档未明确(示例中使用) | 指定后端为 bluestore | `ceph-volume lvm activate --bluestore 0 0263644D-...` |
| `--dmcrypt` | **不可用** | `activate` 子命令**没有**这个 flag。若 OSD 由 ceph-volume 以 dmcrypt 方式 prepare,激活时无需再次指定,加密 OSD 会被**自动检测** | — |
#### 2.3.2 命令示例
```bash
# 激活新准备的 OSD(需同时给出 OSD id 与 OSD uuid)
ceph-volume lvm activate --bluestore 0 0263644D-0BF1-4D6D-BC34-28BD98AE3BC8
# 激活全部
ceph-volume lvm activate --all
```
UUID 存放在 OSD 路径下的 `fsid` 文件中,该文件在 `prepare` 时生成。
#### 2.3.3 为什么必须提供 UUID
要求提供 **OSD uuid** 是一道额外的保险,用来确保激活的是正确的 OSD:完全有可能存在一个 ID 相同的旧 OSD,如果只按 ID 匹配就会激活到错误的那个。
#### 2.3.4 Discovery(发现)机制
对于此前由 `ceph-volume` 创建的 OSD,会借助 **LVM tags** 执行一个 discovery 过程来启用 systemd unit。systemd unit 会捕获 OSD id 与 OSD uuid 并持久化,内部会这样 enable:
```bash
systemctl enable ceph-volume@lvm-$id-$uuid
```
例如:
```bash
systemctl enable ceph-volume@lvm-0-8715BEB4-15C5-49DE-BA6F-401086EC7B41
```
该 unit 会寻找匹配的 OSD 设备,查看其 LVM tags,然后:
1. 把设备挂载到约定位置 `/var/lib/ceph/osd/<cluster name>-<osd id>/`
2. 确保该 OSD 所需的所有设备都就绪
3. 启动 `ceph-osd@0` systemd unit
> 注意:系统通过检查施加在 OSD 设备上的 LVM tags 来推断 objectstore 类型(无需显式指定)。
#### 2.3.5 既有 OSD
对于此前用 `ceph-disk` 部署的既有 OSD,需要用 `simple` 子命令做 scan 并 activate。如果当初用的是别的工具,那么移植到新机制的唯一办法就是**重新 prepare(会丢数据)**。
#### 2.3.6 activate 流程小结(bluestore)
1. 需要 OSD id 与 OSD uuid 两者。
2. 用匹配的 id 与 uuid 启用 systemd unit。
3. 在 `/var/lib/ceph/osd/$cluster-$id/` 创建 `tmpfs` 挂载。
4. 用 `ceph-bluestore-tool prime-osd-dir` 指向 OSD 的 `block` 设备,重建所有需要的文件。
5. systemd unit 确保所有设备就绪并已链接。
6. 启动对应的 `ceph-osd` systemd unit。
> 引自:[activate](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/activate/)
---
### 2.4 `create`
`create` 把「provision 一个新 OSD」的两步过程(先 `prepare` 再 `activate`)包装成**一步**。
- 与两步完全相同的流程,**唯一区别是 OSD 会在命令完成后立刻 up and in**。
- 支持的后端 flag:`--bluestore`。
- **所有命令行 flags 与 options 均与 `ceph-volume lvm prepare` 相同**,参数请参照 2.2 的 prepare 参数表(含 `--data`、`--block.db`、`--block.wal`、`--journal`、`--dmcrypt`、`--with-tpm`、`--osd-id`、`--osd-fsid`、`--crush-device-class`、`--filestore`)。
> 💡 补充:因为 `create` 与 `prepare` 参数完全一致,本册不再重复列一遍表格;实际使用时把 `ceph-volume lvm prepare` 换成 `ceph-volume lvm create` 即可,例如 `ceph-volume lvm create --bluestore --data /dev/sdb`。
> 引自:[create](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/create/)
---
### 2.5 `batch`:批量部署
`batch` 允许给定一组设备输入,**同时创建多个 OSD**。它与 drive-groups 紧密相关:**一个单独的 drive group 规格会翻译成一次 `batch` 调用**。
`batch` 基于 `ceph-volume lvm create`,走**完全相同的代码路径**。`batch` 额外做的只有两件事:
1. 计算所有卷的合适大小(sizing)
2. 跳过已经创建过的卷
`ceph-volume lvm create` 支持的**所有特性**,`batch` 都支持,包括:`dmcrypt`、避免 systemd unit 被启动、定义 bluestore。
#### 2.5.1 参数表
| 参数 | 默认值 | 含义 | 示例 |
|------|--------|------|------|
| `<devices...>`(位置参数) | 无 | 作为 data device 的设备列表 | `/dev/sdb /dev/sdc /dev/sdd` |
| `--db-devices` | 无 | 显式指定用于 `block.db` 的设备列表 | `--db-devices /dev/nvme0n1` |
| `--auto` | 见下方「自动排序」 | 显式启用设备的自动排序(按 rotational 属性) | `--auto` |
| `--no-auto` | 见下方「自动排序」 | 无论旋转盘还是固态盘,所有设备都用作独立 OSD | `--no-auto` |
| `--block-db-slots` | 文档未明确 | **隐式 sizing 提示**:告诉 ceph-volume 应有多少个 data device 的外部卷(db)落在给定的快速设备上 | `--block-db-slots 5` |
| `--block-wal-slots` | 文档未明确 | 同上,针对 wal | `--block-wal-slots 5` |
| `--journal-slots` | 文档未明确 | 同上,针对 journal(filestore) | `--journal-slots 5` |
| `--block-db-size` | 无 | **显式 sizing**:指定 db 卷大小 | `--block-db-size 60G`(格式文档未明确) |
| `--block-wal-size` | 无 | 显式 sizing:指定 wal 卷大小 | `--block-wal-size 10G`(格式文档未明确) |
| `--journal-size` | 无 | 显式 sizing:指定 journal 大小 | `--journal-size 10G`(格式文档未明确) |
| `--report` | 关闭 | 只打印计算出的 OSD 布局报告,然后**退出**,不实际部署。适合多次试跑 | `ceph-volume lvm batch --report /dev/sdb ...` |
| `--yes` | 关闭 | 覆盖默认行为(打印报告并等待用户确认),直接部署 | `--yes` |
| `--format` | 文档未明确(有 `pretty` 默认报告形态) | 报告格式,支持 `json` 与 `json-pretty` | `--format json-pretty` |
| `--dmcrypt` | 关闭 | 批量部署加密 OSD(`batch` 支持 `create` 的全部特性,含 dmcrypt) | `--dmcrypt` |
| `--bluestore` | 文档未明确是否可显式传 | 定义 bluestore(文档表述为「defining bluestore」被支持) | `--bluestore` |
> ⚠️ 关于 `--no-systemd`:`batch.rst` 只写了「avoiding ``systemd`` units from starting」这一**特性**被支持,**没有给出该 flag 的字面名称**。因此 `--no-systemd` 这个具体参数名在本册涵盖的 rst 源文中**未明确出现**。其存在性与拼写请以 `ceph-volume lvm batch --help` 为准。
> ⚠️ 关于 `--wal-devices` / `--journal-devices`:`batch.rst` 只出现了 `--db-devices`。是否存在同族的 `--wal-devices` 参数,**文档未明确**。
#### 2.5.2 自动排序规则(Automatic sorting of disks)
如果 `batch` 只收到一个 data device 列表而**没有其他相关选项**传入,`ceph-volume` 会按设备的 **rotational 属性**自动排序,并根据所用 objectstore,把非旋转盘(SSD/NVMe)用作 `block.db` 或 `journal`。
若要让所有设备都用作独立 OSD(无论旋转盘还是固态盘),传 `--no-auto`。
以 bluestore 且未传 `--no-auto` 为例,**已被废弃的旧行为**会根据传入设备产生如下部署:
| 传入设备情况 | 旧(deprecated)默认行为 |
|-------------|------------------------|
| 全是旋转 HDD | 每个设备创建 1 个 OSD |
| 全是 SSD | 每个设备创建 2 个 OSD |
| HDD 与 SSD 混合 | data 放在旋转设备上,`block.db` 建在 SSD 上,且**尽可能大** |
> ⚠️ 重要变更:这个默认的自动排序行为**现在已被 DEPRECATED,未来版本会改变**。取而代之的是:**除非显式传入 `--auto` 选项,否则设备不会被自动排序**。
>
> ✅ 官方建议:**使用显式的 `block.db`、`block.wal` 和 `journal` 设备列表**。
> ⚠️ 限制:虽然 `ceph-volume lvm create` 允许使用 `block.wal`,但 **`auto` 行为不支持 `block.wal`**。
#### 2.5.3 Reporting(报告 / 预演)
默认情况下 `batch` 会**打印计算出的 OSD 布局报告并要求用户确认**。可用 `--yes` 覆盖(跳过确认直接部署)。
如果想试跑多次而不被反复询问是否部署,可传 `--report`——`ceph-volume` 打印完报告就退出。
```bash
ceph-volume lvm batch --report /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
```
上例会在一块 NVMe 设备上部署三个带外部 `db` 与 `wal` 卷的 OSD。
**pretty 报告示例(默认格式):**
```text
$ ceph-volume lvm batch --report /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
--> passed data devices: 3 physical, 0 LVM
--> relative data size: 1.0
--> passed block_db devices: 1 physical, 0 LVM
Total OSDs: 3
Type Path LV Size % of device
----------------------------------------------------------------------------------------------------
data /dev/sdb 300.00 GB 100.00%
block_db /dev/nvme0n1 66.67 GB 33.33%
----------------------------------------------------------------------------------------------------
data /dev/sdc 300.00 GB 100.00%
block_db /dev/nvme0n1 66.67 GB 33.33%
----------------------------------------------------------------------------------------------------
data /dev/sdd 300.00 GB 100.00%
block_db /dev/nvme0n1 66.67 GB 33.33%
```
**报告字段解读:**
| 字段 | 含义 |
|------|------|
| `passed data devices: N physical, M LVM` | 传入的 data device 中,N 个是物理设备、M 个是 LVM 卷 |
| `relative data size` | 相对数据大小系数(示例为 `1.0`)。文档未给出进一步定义 |
| `passed block_db devices: N physical, M LVM` | 传入的 db device 中物理/LVM 各多少 |
| `Total OSDs` | 本次将创建的 OSD 总数 |
| `Type` | `data` / `block_db` / `block_wal` / `journal` |
| `Path` | 设备路径 |
| `LV Size` | 计算出的 logical volume 大小 |
| `% of device` | 占用该设备的百分比 |
**JSON 报告:**
```bash
ceph-volume lvm batch --report --format json-pretty /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
```
```text
--> passed data devices: 3 physical, 0 LVM
--> relative data size: 1.0
--> passed block_db devices: 1 physical, 0 LVM
[
{
"block_db": "/dev/nvme0n1",
"block_db_size": "66.67 GB",
"data": "/dev/sdb",
"data_size": "300.00 GB",
"encryption": "None"
},
{
"block_db": "/dev/nvme0n1",
"block_db_size": "66.67 GB",
"data": "/dev/sdc",
"data_size": "300.00 GB",
"encryption": "None"
},
{
"block_db": "/dev/nvme0n1",
"block_db_size": "66.67 GB",
"data": "/dev/sdd",
"data_size": "300.00 GB",
"encryption": "None"
}
]
```
#### 2.5.4 Sizing(容量规划)
不传任何 sizing 参数时,`ceph-volume` 会从传入的设备列表(或自动排序后的列表)**推导**出大小;`ceph-volume batch` 会尝试**充分利用设备的可用容量**。官方建议:**依赖自动 sizing**。
如果确实需要不同的 wal/db/journal 容量策略,`ceph-volume` 提供**隐式**与**显式**两类 sizing 规则。
| 类别 | 参数 | 用法 |
|------|------|------|
| 隐式 sizing | `--block-db-slots` / `--block-wal-slots` / `--journal-slots` | 在「设备未足额配置」或「部分 data device 暂不可用(如坏盘待换)」的场景下,给 ceph-volume 一个**提示**:应有多少个 data device 的外部卷落在这批快速设备上。省去手工计算显式大小。 |
| 显式 sizing | `--block-db-size` / `--block-wal-size` / `--journal-size` | 直接给定大小。`ceph-volume` 会尝试在给定磁盘前提下满足这些大小请求;**若无法满足,则不会部署任何 OSD**。 |
隐式 sizing 示例:一台 OSD 主机规划 5 块 data device + 1 块 wal/db 设备,但其中一块 data device 当前损坏待更换。此时不必计算 wal/db 的显式大小,只需:
```bash
ceph-volume lvm batch --report /dev/sdb /dev/sdc /dev/sdd /dev/sde --db-devices /dev/nvme0n1 --block-db-slots 5
```
#### 2.5.5 幂等性与换盘(Idempotency and disk replacements)
`ceph-volume lvm batch` **意图做到幂等**:重复调用同一条命令必须得到相同结果。
```bash
ceph-volume lvm batch --report /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
```
- 第一次调用(所有盘可用)会得到三个已部署的 OSD。
- 再次调用同一命令:**仍然只有三个 OSD**,`ceph-volume` 以返回码 0 退出。
**换盘场景:** 假设 `/dev/sdc` 坏了需要更换。销毁该 OSD 并更换硬件后,**再次调用同一条命令**,`ceph-volume` 会检测到三个期望 OSD 中只有两个已就位,于是**重新创建缺失的那个 OSD**。
> 💡 补充:这个幂等性与 drivegroups 紧密耦合、并被 drivegroups 大量使用——这正是「同一份 drive group spec 反复 apply 不会重复建 OSD、换盘后能自动补齐」的底层依据。
> 引自:[batch](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/batch/)
---
### 2.6 `list`:设备与 OSD 关联报告
`list` 会列出**任何可能与 Ceph 集群关联的设备(logical 与 physical)**,前提是它们带有足够的可发现元数据。
- 输出按设备关联的 **OSD ID** 分组。
- 与 `ceph-disk` 不同,它**不会**输出任何与 Ceph 无关的设备信息。
#### 2.6.1 参数表
| 参数 | 默认值 | 含义 | 示例 |
|------|--------|------|------|
| `--format` | `pretty` | 允许 `json` 或 `pretty`。`pretty` 以人类可读格式分组展示设备信息 | `ceph-volume lvm list --format=json` |
| `<device or vg/lv>`(位置参数) | 无(不给则为完整报告) | 单个报告:可为设备全路径,或 `vg/lv` 形式的 logical volume | `ceph-volume lvm list test_group/data-lv2`、`ceph-volume lvm list /dev/sdd1` |
#### 2.6.2 Full Reporting(完整报告)
不使用位置参数时给出完整报告,即展示系统中发现的**所有**设备和 logical volume。
两个 OSD(一个用 lv 作 journal,另一个用物理设备)的 `pretty` 完整报告示例:
```bash
ceph-volume lvm list
```
```text
====== osd.1 =======
[journal] /dev/journals/journal1
journal uuid C65n7d-B1gy-cqX3-vZKY-ZoE0-IEYM-HnIJzs
osd id 1
cluster fsid ce454d91-d748-4751-a318-ff7f7aa18ffd
type journal
osd fsid 661b24f8-e062-482b-8110-826ffe7f13fa
data uuid SlEgHe-jX1H-QBQk-Sce0-RUls-8KlY-g8HgcZ
journal device /dev/journals/journal1
data device /dev/test_group/data-lv2
devices /dev/sda
[data] /dev/test_group/data-lv2
journal uuid C65n7d-B1gy-cqX3-vZKY-ZoE0-IEYM-HnIJzs
osd id 1
cluster fsid ce454d91-d748-4751-a318-ff7f7aa18ffd
type data
osd fsid 661b24f8-e062-482b-8110-826ffe7f13fa
data uuid SlEgHe-jX1H-QBQk-Sce0-RUls-8KlY-g8HgcZ
journal device /dev/journals/journal1
data device /dev/test_group/data-lv2
devices /dev/sdb
====== osd.0 =======
[data] /dev/test_group/data-lv1
journal uuid cd72bd28-002a-48da-bdf6-d5b993e84f3f
osd id 0
cluster fsid ce454d91-d748-4751-a318-ff7f7aa18ffd
type data
osd fsid 943949f0-ce37-47ca-a33c-3413d46ee9ec
data uuid TUpfel-Q5ZT-eFph-bdGW-SiNW-l0ag-f5kh00
journal device /dev/sdd1
data device /dev/test_group/data-lv1
devices /dev/sdc
[journal] /dev/sdd1
PARTUUID cd72bd28-002a-48da-bdf6-d5b993e84f3f
```
#### 2.6.3 输出字段解读
| 字段 | 含义 |
|------|------|
| `====== osd.N =======` | 分组标题,按 OSD ID |
| `[journal]` / `[data]` | 该设备在此 OSD 中扮演的角色(type) |
| `journal uuid` | journal 卷/分区的 UUID(LV 为 lv_uuid,分区为 PARTUUID) |
| `osd id` | OSD ID(实际 tag 为 `ceph.osd_id`) |
| `cluster fsid` | 集群 FSID(tag `ceph.cluster_fsid`) |
| `type` | `data` / `journal` / `block` / `db` / `wal` 等(tag `ceph.type`) |
| `osd fsid` | OSD FSID(tag `ceph.osd_fsid`) |
| `data uuid` | 数据卷 UUID(tag `ceph.data_uuid`) |
| `journal device` | journal 设备路径(tag `ceph.journal_device`) |
| `data device` | 数据设备路径(tag `ceph.data_device`) |
| `devices` | 与该 logical volume 关联的**物理设备**。因为 LVM 允许多个物理设备组成一个 LV,`pretty` 下该值为**逗号分隔**,而 `json` 下是**数组** |
| `PARTUUID` | 当对象是物理分区时列出其 PARTUUID |
#### 2.6.4 Single Reporting(单个报告)
单个报告既能接受设备也能接受 logical volume 作为位置参数。**对 logical volume,必须同时使用卷组名和逻辑卷名**(即 `vg/lv`)。
```bash
ceph-volume lvm list test_group/data-lv2
```
```text
====== osd.1 =======
[data] /dev/test_group/data-lv2
journal uuid C65n7d-B1gy-cqX3-vZKY-ZoE0-IEYM-HnIJzs
osd id 1
cluster fsid ce454d91-d748-4751-a318-ff7f7aa18ffd
type data
osd fsid 661b24f8-e062-482b-8110-826ffe7f13fa
data uuid SlEgHe-jX1H-QBQk-Sce0-RUls-8KlY-g8HgcZ
journal device /dev/journals/journal1
data device /dev/test_group/data-lv2
devices /dev/sdc
```
对普通磁盘,需要设备完整路径:
```bash
ceph-volume lvm list /dev/sdd1
```
```text
====== osd.0 =======
[journal] /dev/sdd1
PARTUUID cd72bd28-002a-48da-bdf6-d5b993e84f3f
```
#### 2.6.5 json 输出
所有 `--format=json` 的输出会展示系统为这些设备存储的**全部**元数据,**包括 tags**。json 报告**不做任何可读性加工**,信息原样呈现。完整报告和单设备报告都支持。
```bash
ceph-volume lvm list --format=json test_group/data-lv1
```
```json
{
"0": [
{
"devices": ["/dev/sda"],
"lv_name": "data-lv1",
"lv_path": "/dev/test_group/data-lv1",
"lv_tags": "ceph.cluster_fsid=ce454d91-d748-4751-a318-ff7f7aa18ffd,ceph.data_device=/dev/test_group/data-lv1,ceph.data_uuid=TUpfel-Q5ZT-eFph-bdGW-SiNW-l0ag-f5kh00,ceph.journal_device=/dev/sdd1,ceph.journal_uuid=cd72bd28-002a-48da-bdf6-d5b993e84f3f,ceph.osd_fsid=943949f0-ce37-47ca-a33c-3413d46ee9ec,ceph.osd_id=0,ceph.type=data",
"lv_uuid": "TUpfel-Q5ZT-eFph-bdGW-SiNW-l0ag-f5kh00",
"name": "data-lv1",
"path": "/dev/test_group/data-lv1",
"tags": {
"ceph.cluster_fsid": "ce454d91-d748-4751-a318-ff7f7aa18ffd",
"ceph.data_device": "/dev/test_group/data-lv1",
"ceph.data_uuid": "TUpfel-Q5ZT-eFph-bdGW-SiNW-l0ag-f5kh00",
"ceph.journal_device": "/dev/sdd1",
"ceph.journal_uuid": "cd72bd28-002a-48da-bdf6-d5b993e84f3f",
"ceph.osd_fsid": "943949f0-ce37-47ca-a33c-3413d46ee9ec",
"ceph.osd_id": "0",
"ceph.type": "data"
},
"type": "data",
"vg_name": "test_group"
}
]
}
```
#### 2.6.6 Synchronized information(信息同步 / 设备改名自愈)
在任何 listing 之前,会先查询 lvm API,以确认在用的物理设备**没有发生改名**——像 `/dev/sda1` 这类非持久化命名完全可能变成 `/dev/sdb1`。
之所以能检测到,是因为 `PARTUUID` 作为元数据的一部分被存放在 data lv 中;**即使 journal 是物理设备,该信息也仍存放在与之关联的 data logical volume 上**。
若(用 `PARTUUID` 询问 `blkid` 得到的)名字已不再相同,tag 会被更新,报告会使用刷新后的新信息。
> 💡 补充:这条机制解释了为什么 `ceph-volume` 比 `ceph-disk` 更抗设备改名——元数据锚点是 PARTUUID / lv_uuid,而不是 `/dev/sdX` 这种不稳定的内核命名。
> 引自:[list](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/list/)
---
### 2.7 `zap`:擦除设备以复用
`zap` 用来擦除**已被 Ceph OSD 使用过的** lvs、分区或裸设备,使它们可以被重新使用。
- 如果给的是 logical volume 路径,**必须是 `vg/lv` 格式**。
- 给定 lv 或分区上存在的任何文件系统都会被移除,**所有数据都会被清除**。
- ⚠️ 注意:**lv 或分区本身会被保留完整(kept intact)**。
- ⚠️ 注意:如果该 logical volume、裸设备或分区正被任何 Ceph 相关的挂载点使用,它们会被**卸载**。
#### 2.7.1 参数表
| 参数 | 默认值 | 含义 | 示例 |
|------|--------|------|------|
| `<device / vg/lv>`(位置参数) | 无 | 要擦除的目标;可以是裸设备、分区,或 `vg/lv` 形式的 logical volume。**可同时接受多个设备** | `/dev/sdc`、`/dev/sdc1`、`osd-vg/data-lv` |
| `--destroy` | 关闭 | 在擦除的同时**完全移除**该设备(lv、vg 或 partition)。当你用整块裸设备部署过 OSD、之后想复用该设备再部署另一个 OSD 时,**必须**使用此 flag,否则 ceph-volume 在该裸设备上建的 vgs 与 lvs 不会被移除 | `--destroy` |
| `--osd-id` | 无 | 按 OSD ID 过滤要擦除的设备(可与 `--osd-fsid` 同时给) | `--osd-id 1` |
| `--osd-fsid` | 无 | 按 OSD FSID 过滤。文档特别指出:**用 FSID 过滤更严格**,可能不会匹配到那些(可能已无效的)与某 ID 关联的其他设备 | `--osd-fsid 2E8FBE58-0328-4E3B-BFB7-3CACE4E9A6CE` |
#### 2.7.2 示例
```bash
# 擦除一个 logical volume
ceph-volume lvm zap {vg name/lv name}
# 擦除一个分区
ceph-volume lvm zap /dev/sdc1
# 擦除裸设备并销毁其上的 vgs / lvs
ceph-volume lvm zap /dev/sdc --destroy
# --destroy 同样可用于分区与 logical volume
ceph-volume lvm zap /dev/sdc1 --destroy
ceph-volume lvm zap osd-vg/data-lv --destroy
# 按 OSD ID 过滤
ceph-volume lvm zap --destroy --osd-id 1
# 按 OSD FSID 过滤
ceph-volume lvm zap --destroy --osd-fsid 2E8FBE58-0328-4E3B-BFB7-3CACE4E9A6CE
# 两者同时使用
ceph-volume lvm zap --destroy --osd-fsid 2E8FBE58-0328-4E3B-BFB7-3CACE4E9A6CE --osd-id 1
```
> ⚠️ 官方 warning:**如果检测到待 zap 的 OSD ID 所对应的 systemd unit 正在运行,工具会拒绝执行 zap,直到该守护进程被停止。**
> 💡 补充:这条 warning 的实践含义是——zap 之前必须先停 OSD(例如 `systemctl stop ceph-osd@<id>`,cephadm 部署的则用 `cephadm unit --fsid $cid --name osd.<id> stop`),否则命令会被拒绝。
> 引自:[zap](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/zap/)
---
### 2.8 `migrate`:把 BlueFS 数据搬到目标卷
`migrate` 把 **BlueFS 数据**从源卷搬到目标卷;成功时**源卷(除主卷,即 data / block 卷之外)会被移除**。
- **Target 只允许 LVM 卷**,可以是已挂载的,也可以是新卷。
- 若是新卷,它会被挂到该 OSD 上,**替换掉某个源设备**。
#### 2.8.1 替换规则(按优先级顺序,命中即停)
| 优先级 | 条件 | 结果 |
|--------|------|------|
| 1 | 源列表中有 **DB volume** | target 设备替换它 |
| 2 | 源列表中有 **WAL volume** | target 设备替换它 |
| 3 | 源列表中**只有 slow volume** | **不允许该操作**,需要先用 `new-db` / `new-wal` 显式分配 |
#### 2.8.2 参数表
| 参数 | 默认值 | 含义 | 示例 |
|------|--------|------|------|
| `--osd-id` | 无 | 目标 OSD 的 ID | `--osd-id 1` |
| `--osd-fsid` | 无 | 目标 OSD 的 FSID(UUID) | `--osd-fsid <uuid>` |
| `--from` | 无 | 源卷列表,取值 `data` / `db` / `wal`,**可给多个**(空格分隔) | `--from data db wal` |
| `--target` | 无 | 目标 LVM 卷,格式 `vg/lv` | `--target vgname/new_db` |
#### 2.8.3 全部官方示例(逐条对照)
| # | 命令 | 效果 |
|---|------|------|
| 1 | `ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data --target vgname/db` | 把 BlueFS 数据从主设备搬到**已作为 DB 挂载的 LV** |
| 2 | `ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data --target vgname/new_db` | 把 BlueFS 数据从**共享的主设备**搬到一个将作为**新 DB** 挂载的 LV |
| 3 | `ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from db --target vgname/new_db` | 把 BlueFS 数据从 DB 设备搬到新 LV,**DB 被替换** |
| 4 | `ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data db --target vgname/new_db` | 把 BlueFS 数据从主设备与 DB 设备搬到新 LV,**DB 被替换** |
| 5 | `ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data db wal --target vgname/new_db` | 从主、DB、WAL 三个设备搬到新 LV,**WAL 被移除、DB 被替换** |
| 6 | `ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from db wal --target vgname/data` | 从主、DB、WAL 搬到**主设备**,**WAL 与 DB 都被移除** |
> 引自:[migrate](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/migrate/)
---
### 2.9 `new-db` / `new-wal`:挂载新的 DB / WAL 卷
| 子命令 | 作用 | 失败条件 |
|--------|------|---------|
| `new-db` | 把给定的 logical volume 作为 **DB** 挂到 OSD 上 | 若该 OSD **已挂载 DB** 则失败 |
| `new-wal` | 把给定的 logical volume 作为 **WAL** 挂到 OSD 上 | 若该 OSD **已挂载 DB** 则失败(源文原文如此) |
两者的 logical volume 名格式均为 **`vg/lv`**。
#### 2.9.1 参数表
| 参数 | 默认值 | 含义 | 示例 |
|------|--------|------|------|
| `--osd-id` | 无 | 目标 OSD 的 ID | `--osd-id 1` |
| `--osd-fsid` | 无 | 目标 OSD 的 FSID(UUID) | `--osd-fsid 55BD4219-16A7-4037-BC20-0F158EFCC83D` |
| `--target` | 无 | 要挂载的 logical volume,格式 `vg/lv` | `--target vgname/new_db` |
#### 2.9.2 示例
```bash
# 把 vgname/lvname 作为 DB 卷挂到 OSD 1
ceph-volume lvm new-db --osd-id 1 --osd-fsid 55BD4219-16A7-4037-BC20-0F158EFCC83D --target vgname/new_db
# 把 vgname/lvname 作为 WAL 卷挂到 OSD 1
ceph-volume lvm new-wal --osd-id 1 --osd-fsid 55BD4219-16A7-4037-BC20-0F158EFCC83D --target vgname/new_wal
```
#### 2.9.3 Reversing BlueFS Spillover to Slow Devices(回退 BlueFS 溢出)
在某些情形下,OSD 的 RocksDB 数据库会**溢出(spill over)到慢速存储**上,Ceph 集群会给出具体的 BlueFS spillover 警告,`ceph health detail` 会返回这些警告。示例:
```text
osd.76 spilled over 128 KiB metadata from 'db' device (56 GiB used of 60 GiB) to slow device
```
要把这部分 DB 元数据从慢设备搬回快设备,按以下步骤:
1. **扩容数据库的 logical volume(LV):**
```bash
lvextend -l ${size} ${lv}/${db} ${ssd_dev}
```
2. **停止该 OSD:**
```bash
cephadm unit --fsid $cid --name osd.${osd} stop
```
3. **执行 `bluefs-bdev-expand`:**
```bash
cephadm shell --fsid $cid --name osd.${osd} -- ceph-bluestore-tool bluefs-bdev-expand --path /var/lib/ceph/osd/ceph-${osd}
```
4. **执行 `bluefs-bdev-migrate`:**
```bash
cephadm shell --fsid $cid --name osd.${osd} -- ceph-bluestore-tool bluefs-bdev-migrate --path /var/lib/ceph/osd/ceph-${osd} --devs-source /var/lib/ceph/osd/ceph-${osd}/block --dev-target /var/lib/ceph/osd/ceph-${osd}/block.db
```
5. **重启该 OSD:**
```bash
cephadm unit --fsid $cid --name osd.${osd} start
```
> 📌 官方 note:以上流程由 **Chris Dunlop** 在 [ceph-users] 邮件列表上提出,原始出处为 `[ceph-users] Re: Fixing BlueFS spillover (pacific 16.2.14)`。
>
> 💡 补充:注意这套 spillover 修复流程用的是 `cephadm` + `ceph-bluestore-tool`,而不是 `ceph-volume lvm new-db`——它属于「就地扩容 db LV 后让 BlueFS 认识到新容量并搬回数据」的路径,与「给 OSD 新挂一个 DB 卷」的 `new-db` 是两回事。
> 引自:[new-db](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/newdb/)、[new-wal](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/newwal/)
---
### 2.10 `scan`(lvm):尚未实现
`lvm/scan.rst` 全文极短:该子命令本意是「通过查看系统的 logical volumes 及其 tags 来发现此前由本工具配置过的 Ceph 卷」。作为 `prepare` 过程的一部分,logical volume 会被打上若干带重要信息的 tags。
> ⚠️ **官方 note:This sub-command is not yet implemented(该子命令尚未实现)。**
在 `lvm/index.rst` 中,`scan` 也确实出现在被注释掉的 `.. not yet implemented` 列表里。
> 💡 补充:因此不要指望用 `ceph-volume lvm scan` 做发现;当前可用的「发现/查看」手段是 `ceph-volume lvm list`(2.6)与 `ceph-volume inventory`(第五章)。
> 引自:[scan](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/scan/)
---
### 2.11 加密(Encryption)
Logical volume 可以通过在创建 OSD 时指定 **`--dmcrypt`** flag 来使用 **dmcrypt** 加密。用 LVM 时,logical volume 有多种加密方式;`ceph-volume` 提供的选项没有 LVM 那么多,但它以一种**一致且健壮(consistent and robust)**的方式加密 logical volume。
`ceph-volume lvm` 遵循的约束:
- **非 LVM 设备(例如分区)使用与 OSD 相同的 key 加密。**
#### 2.11.1 LUKS 版本
LUKS 目前有两个版本,1 和 2。版本 2 实现起来稍容易一些,但**并非 Ceph 支持的所有 Linux 发行版都广泛提供**。
| 文档中的称呼 | 实际版本 |
|-------------|---------|
| "LUKS" | LUKS 版本 1 |
| "LUKS2" | LUKS 版本 2 |
#### 2.11.2 LUKS on LVM(在 LV 之上加密)
加密是在**已有 logical volume 之上**进行的(这与「加密物理设备」不是一回事)。任何单个 logical volume 都可以被加密,其他卷保持不加密。这种方式也允许灵活的 LV 布局,因为**加密发生在 LV 创建之后**。
#### 2.11.3 密钥管理与工作流
搭建 OSD 时会创建一个 secret key。该 secret key 以 **JSON 格式通过 `stdin` 传给 monitor**,以防止 key 被日志记录捕获。
JSON payload 形如:
```json
{
"cephx_secret": CEPHX_SECRET,
"dmcrypt_key": DMCRYPT_KEY,
"cephx_lockbox_secret": LOCKBOX_SECRET,
}
```
**三个 key 的命名约定是严格(strict)的**,之所以叫这些名字,是为了沿用 `ceph-disk` 使用的**硬编码(legacy)名称**:
| key 名 | 含义 |
|--------|------|
| `cephx_secret` | 用于认证的 cephx key |
| `dmcrypt_key` | 用于解锁加密设备的 secret(private)key |
| `cephx_lockbox_secret` | 用于取回 `dmcrypt_key` 的认证 key。之所以叫 *lockbox*,是因为 `ceph-disk` 过去有一个同名的**未加密分区**,用来存放公钥和其他 OSD 元数据 |
命名约定之所以严格,是因为 Monitor 支持 `ceph-disk` 的这套命名。为了保持兼容、避免破坏 `ceph-disk`,`ceph-volume` **沿用了同样的命名约定——尽管它对新加密工作流而言并没有意义**。
#### 2.11.4 加解密的时机
- 在 **prepare 阶段**(bluestore)完成 OSD 搭建的公共步骤之后,logical volume 就处于「随时可激活」的状态,**与设备当前是加密还是解密状态无关**。
- 到**激活时**,logical volume 才被解密。解密过程正确完成后 OSD 才启动。
#### 2.11.5 新建加密 OSD 的加密流程小结
1. OSD 被创建。**lockbox 与 dmcrypt 两个 key 都被创建**,并以 JSON 格式发送给 monitors,以此表明这是一个加密 OSD。
2. 所有配套设备(如 journal、db、wal)被创建,并**用同一个 OSD key 加密**。Key 存储在 OSD 的 **LVM 元数据**中。
3. 激活流程继续:确保设备被挂载、**从 monitors 取回 dmcrypt secret key**、在 OSD 启动前完成解密。
#### 2.11.6 加密相关命令回顾
```bash
# 准备时启用加密(--dmcrypt 必需)
ceph-volume lvm prepare --bluestore --dmcrypt --data vg/lv
# Squid 起:为 LUKS2 设备启用 TPM2 token enrollment
ceph-volume lvm prepare --bluestore --dmcrypt --with-tpm --data vg/lv
# filestore 场景(已废弃,仅作对照)
ceph-volume lvm prepare --filestore --dmcrypt --data <data block device> --journal <journal block device>
# 激活时无需再次指定 --dmcrypt:加密 OSD 会被自动检测
ceph-volume lvm activate --bluestore 0 0263644D-0BF1-4D6D-BC34-28BD98AE3BC8
```
> 引自:[Encryption](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/encryption/)
---
### 2.12 systemd 集成
#### 2.12.1 通用约定(`ceph-volume/systemd.rst`)
作为激活流程的一部分(无论是 `lvm activate` 还是 `simple activate`),会启用若干 **systemd unit**,这些 unit 的名字中带有 **OSD id 与 uuid**。这些 unit 会在系统启动时运行,并通过各自子命令的实现去激活对应的卷。
激活的 API 比较松散,只要求两部分:要用的**子命令**,以及用短横线分隔的**额外元信息**。约定使 unit 形如:
```text
ceph-volume@{command}-{extra metadata}
```
*extra metadata* 可以是实现处理的子命令所需的任何东西。对 `lvm` 与 `simple` 而言,两者都需要消费 **OSD id** 与 **OSD uuid**——但这不是硬性要求,只是这两个子命令的实现方式如此。
command 与 extra metadata 都会被 systemd 作为 unit 的**「instance name」**持久化。例如一个 ID 为 0 的 OSD,在 `lvm` 子命令下是:
```bash
systemctl enable ceph-volume@lvm-0-0A3E1ED2-DA8A-4F0E-AA95-61DEC71768D6
```
被启用的 unit 是一个 **systemd oneshot** 服务,设计为在**本地文件系统就绪之后**、随系统启动运行。
#### 2.12.2 unit 命名规则汇总
| 后端 | unit 命名 | 启用示例 |
|------|----------|---------|
| 通用形式 | `ceph-volume@{command}-{extra metadata}` | — |
| `lvm` | `ceph-volume@lvm-$id-$uuid` | `systemctl enable ceph-volume@lvm-0-8715BEB4-15C5-49DE-BA6F-401086EC7B41` |
| `simple` | `ceph-volume@simple-$id-$uuid` | `systemctl enable ceph-volume@simple-0-8715BEB4-15C5-49DE-BA6F-401086EC7B41` |
#### 2.12.3 失败与重试(Failure and Retries)
系统上线时失败很常见——设备有时尚未完全可用,这种不可预测的行为可能导致某个 OSD 没能就绪。
有两个可配置的环境变量用于设置重试行为:
| 环境变量 | 默认值 | 含义 |
|---------|-------|------|
| `CEPH_VOLUME_SYSTEMD_TRIES` | **30** | *"tries"*:unit 在放弃之前尝试激活某个 OSD 的**最大次数** |
| `CEPH_VOLUME_SYSTEMD_INTERVAL` | **5** | *"interval"*:发起下一次激活尝试前的**等待秒数** |
#### 2.12.4 lvm 侧的 systemd 流程(`lvm/systemd.rst`)
启动时,它会用 **LVM tags** 识别 logical volume,找到匹配的 ID,再用 **OSD uuid** 确认找对了。
识别到正确的卷之后,按 OSD 目标约定挂载:
```text
/var/lib/ceph/osd/<cluster name>-<osd id>
```
对我们的示例(OSD id 为 `0`),即挂载到:
```text
/var/lib/ceph/osd/ceph-0
```
该过程完成后,调用启动 OSD:
```bash
systemctl start ceph-osd@0
```
这一 systemd 部分由 **`ceph-volume lvm trigger`** 子命令处理,它只负责解析来自 systemd 与启动过程的元数据,然后分发给 `ceph-volume lvm activate` 去完成激活。
#### 2.12.5 启停操作速查
```bash
# 启用(开机自启)——lvm
systemctl enable ceph-volume@lvm-0-8715BEB4-15C5-49DE-BA6F-401086EC7B41
# 启用——simple
systemctl enable ceph-volume@simple-0-8715BEB4-15C5-49DE-BA6F-401086EC7B41
# 启动 OSD 本体
systemctl start ceph-osd@0
# 停止 OSD 本体(zap 前需要)
systemctl stop ceph-osd@0
```
> 💡 补充:文档只给出了 `enable` 与 `start` 的示例,没有给出 `disable`/`stop` `ceph-volume@` 这一 oneshot unit 的示例;`systemctl stop ceph-osd@0` 是根据 zap 前「必须停止守护进程」的要求推导出的常规做法。cephadm 部署的集群请用 `cephadm unit --fsid $cid --name osd.<id> stop/start`。
> 引自:[systemd](https://docs.ceph.com/en/tentacle/ceph-volume/systemd/)、[systemd(lvm)](https://docs.ceph.com/en/tentacle/ceph-volume/lvm/systemd/)
---
## 三、simple 后端(接管遗留 ceph-disk OSD)
`simple` 子命令实现了从 `simple` 子命令管理 OSD 所需的功能:`ceph-volume simple`。
**用户可见子命令:** `scan`、`activate`、`systemd`。
**「接管(taking over)」管理的含义:** 它禁用所有 `ceph-disk` 用来在启动时触发设备的 systemd unit,转而依赖**基础(可定制的)JSON 配置**与 systemd 来启动 OSD。
**两步流程:**
1. `scan` 运行中的 OSD 或 data device
2. `activate` 已被扫描的 OSD
扫描会推断出 `ceph-volume` 启动该 OSD 所需的**一切**信息,这样在需要激活时,OSD 可以正常启动,而不会受到 `ceph-disk` 的干扰。
作为激活流程的一部分,负责响应 udev 事件的 `ceph-disk` systemd unit 会被**链接到 `/dev/null`**,从而彻底失效。
### 3.1 `scan`(simple)
扫描可以捕获一个**已部署 OSD** 的重要细节,使 `ceph-volume` 能在**不需要任何其他启动工作流或工具(如 udev 或 ceph-disk)**的情况下管理它。**LUKS 或 PLAIN 格式的加密完全支持。**
该命令可以:
- 通过检查存放 OSD 数据的目录来检视一个运行中的 OSD;
- 或消费 data partition 来检视;
- 或者,如果不提供任何路径或设备,则**扫描所有运行中的 OSD**。
扫描后,信息(默认)会作为 JSON **持久化到 `/etc/ceph/osd` 下的一个文件中**。JSON 文件命名约定为 `{OSD ID}-{OSD FSID}.json`。例如 id 为 1、FSID 为 `86ebd829-1405-43d3-8fd6-4cbc9b6ecf96` 的 OSD,绝对路径为:
```text
/etc/ceph/osd/1-86ebd829-1405-43d3-8fd6-4cbc9b6ecf96.json
```
#### 3.1.1 参数表
| 参数 / 位置参数 | 默认值 | 含义 | 示例 |
|---------------|--------|------|------|
| `<path>`(位置参数) | 无(不给则扫描所有运行中的 OSD) | OSD 目录路径,或 OSD 的 data partition 设备(**必须是 data partition**) | `/var/lib/ceph/osd/ceph1`、`/dev/sda1` |
| `--force` | 关闭 | `scan` 子命令在该文件已存在时**拒绝写入**;如需覆盖内容,必须使用此 flag | `ceph-volume simple scan --force {path}` |
| `--stdout` | 关闭 | 无需持久化 JSON 元数据时,把内容发到 `stdout`(**不会写文件**) | `ceph-volume simple scan --stdout {path}` |
#### 3.1.2 Running OSDs scan(扫描运行中的 OSD)
不带 OSD 目录或设备参数使用该命令,会扫描**当前正在运行的** OSD 的目录。**如果某个运行中的 OSD 不是由 ceph-disk 创建的,它会被忽略、不被扫描。**
```bash
ceph-volume simple scan
```
#### 3.1.3 Directory scan(目录扫描)
目录扫描会从若干「有趣的文件」中捕获 OSD 文件内容。以下文件**必须存在**才能成功扫描:
- `ceph_fsid`
- `fsid`
- `keyring`
- `ready`
- `type`
- `whoami`
如果 OSD 是加密的,还会额外添加以下 key:
- `encrypted`
- `encryption_type`
- `lockbox_keyring`
对于任何其他文件,**只要不是二进制文件或目录**,也会被捕获并作为 JSON 对象的一部分持久化。
JSON 对象 key 的约定:**任何文件名就是一个 key,其内容就是它的值**。
- 若内容只有一行(如 `whoami`),内容会被 trim,换行被丢弃。例如 OSD id 为 1 时:`"whoami": "1",`
- 可能多行的文件内容保持原样,但 **keyring 会被特殊处理并解析以提取 keyring**。例如读到的 keyring 为:
```text
[osd.1]\n\tkey = AQBBJ/dZp57NIBAAtnuQS9WOS0hnLVe0rZnE6Q==\n
```
会被存为:
```text
"keyring": "AQBBJ/dZp57NIBAAtnuQS9WOS0hnLVe0rZnE6Q==",
```
对于 `/var/lib/ceph/osd/ceph-1` 这样的目录,命令形如:
```bash
ceph-volume simple scan /var/lib/ceph/osd/ceph1
```
#### 3.1.4 Device scan(设备扫描)
当 OSD 目录不可用时(OSD 未运行,或设备未挂载),`scan` 能够内省设备以捕获所需数据。与目录扫描一样,它仍然需要若干文件存在——这意味着**被扫描的设备必须是该 OSD 的 data partition**。
只要传入的是 OSD 的 data partition,该子命令就能扫描其内容。
- 若设备**已挂载**,工具能检测到这种情形,并从该目录捕获文件内容。
- 若设备**未挂载**,会创建一个临时目录,把设备临时挂载上仅用于扫描内容;内容扫描完成后设备会被卸载。
对于 `/dev/sda1`(**必须是 data partition**),命令形如:
```bash
ceph-volume simple scan /dev/sda1
```
#### 3.1.5 JSON 内容
JSON 对象的内容非常简单。扫描不仅会持久化来自特殊 OSD 文件及其内容的信息,还会**校验路径和设备 UUID**。
与 `ceph-disk` 把它们存放在 `{device type}_uuid` 文件里的做法不同,本工具会把它们作为 **device type key 的一部分**持久化。例如一个 `block.db` 设备:
```json
"block.db": {
"path": "/dev/disk/by-partuuid/6cc43680-4f6e-4feb-92ff-9c7ba204120e",
"uuid": "6cc43680-4f6e-4feb-92ff-9c7ba204120e"
},
```
但它**同时也会**持久化 `ceph-disk` 生成的特殊文件,如:
```json
"block.db_uuid": "6cc43680-4f6e-4feb-92ff-9c7ba204120e",
```
这种**重复(duplication)**的存在是为了确保三件事:
1. 支持那些可能没有 ceph-disk 特殊文件的 OSD
2. 通过查询 LVM 与 `blkid`,检查设备上**最新的**信息
3. 同时支持 logical volume 与 GPT 设备
一个使用 `bluestore` 的 OSD 的 JSON 元数据样例:
```json
{
"active": "ok",
"block": {
"path": "/dev/disk/by-partuuid/40fd0a64-caa5-43a3-9717-1836ac661a12",
"uuid": "40fd0a64-caa5-43a3-9717-1836ac661a12"
},
"block.db": {
"path": "/dev/disk/by-partuuid/6cc43680-4f6e-4feb-92ff-9c7ba204120e",
"uuid": "6cc43680-4f6e-4feb-92ff-9c7ba204120e"
},
"block.db_uuid": "6cc43680-4f6e-4feb-92ff-9c7ba204120e",
"block_uuid": "40fd0a64-caa5-43a3-9717-1836ac661a12",
"bluefs": "1",
"ceph_fsid": "c92fc9eb-0610-4363-aafc-81ddf70aaf1b",
"cluster_name": "ceph",
"data": {
"path": "/dev/sdr1",
"uuid": "86ebd829-1405-43d3-8fd6-4cbc9b6ecf96"
},
"fsid": "86ebd829-1405-43d3-8fd6-4cbc9b6ecf96",
"keyring": "AQBBJ/dZp57NIBAAtnuQS9WOS0hnLVe0rZnE6Q==",
"kv_backend": "rocksdb",
"magic": "ceph osd volume v026",
"mkfs_done": "yes",
"ready": "ready",
"systemd": "",
"type": "bluestore",
"whoami": "3"
}
```
### 3.2 `activate`(simple)
一旦 `scan` 完成、某个 OSD 的全部元数据都持久化到 `/etc/ceph/osd/{id}-{uuid}.json`,该 OSD 就可以被「激活」了。
**该激活过程会通过 masking 禁用所有 `ceph-disk` systemd unit**,以防止 UDEV / ceph-disk 交互在开机时尝试启动它们。
> ⚠️ 注意:禁用 `ceph-disk` unit **只在直接调用 `ceph-volume simple activate` 时发生**;当系统启动过程中由 systemd 调用时,**不会**执行禁用动作。
激活过程需要同时使用 **OSD id** 与 **OSD uuid**。
#### 3.2.1 参数表
| 参数 / 位置参数 | 默认值 | 含义 | 示例 |
|---------------|--------|------|------|
| `<osd id>`(位置参数) | 无 | 要激活的 OSD ID | `0` |
| `<osd uuid>`(位置参数) | 无 | 要激活的 OSD UUID | `6cc43680-4f6e-4feb-92ff-9c7ba204120e` |
| `--file` | 无 | 直接指定 JSON 文件路径,替代「id + uuid」的位置参数形式 | `--file /etc/ceph/osd/0-6cc43680-4f6e-4feb-92ff-9c7ba204120e.json` |
#### 3.2.2 示例
```bash
# 用 id + uuid(工具会去找 /etc/ceph/osd/0-6cc43680-4f6e-4feb-92ff-9c7ba204120e.json)
ceph-volume simple activate 0 6cc43680-4f6e-4feb-92ff-9c7ba204120e
# 直接给 JSON 文件
ceph-volume simple activate --file /etc/ceph/osd/0-6cc43680-4f6e-4feb-92ff-9c7ba204120e.json
```
**为何必须提供 uuid:** 这是一道额外的保险,确保激活的是正确的 OSD——完全可能存在一个 ID 相同的旧 OSD,只按 ID 匹配就会激活到错误的那个。
#### 3.2.3 Discovery(发现)机制
对于此前已被 `ceph-volume` 扫描过的 OSD,会借助 **`blkid` 与 `lvm`** 执行发现过程。目前**只支持**带 GPT 分区的设备和 LVM logical volume。
- GPT 分区会有一个可被 `blkid` 查询的 `PARTUUID`;
- logical volume 则会有一个可针对 `lvs`(LVM 的列出逻辑卷工具)查询的 `lv_uuid`。
该发现过程确保:即使设备被挪用到另一台系统、或其名称发生变化(如 `/dev/sda1` 这类非持久化命名),设备也能被正确检测出来。
用于映射「哪些设备属于哪个 OSD」的 JSON 配置文件,会在激活过程中协调挂载与符号链接操作。
为确保符号链接始终正确:**如果 OSD 目录中已存在符号链接,它们会被重新创建(re-done)。**
systemd unit 会捕获 OSD id 与 OSD uuid 并持久化,内部会这样 enable:
```bash
systemctl enable ceph-volume@simple-$id-$uuid
```
例如:
```bash
systemctl enable ceph-volume@simple-0-8715BEB4-15C5-49DE-BA6F-401086EC7B41
```
该 systemd 流程会调用 activate 并传入识别 OSD 及其设备所需的信息,然后:
1. 把设备挂载到约定位置 `/var/lib/ceph/osd/<cluster name>-<osd id>/`
2. 确保该 OSD 所需的所有设备就绪且正确链接。**符号链接总是会被重新创建**,以确保链接到正确的设备。
3. 启动 `ceph-osd@0` systemd unit
### 3.3 `systemd`(simple)
启动时,它会通过加载 `/etc/ceph/osd/{id}-{uuid}.json`(对应 systemd unit 的 instance name)来识别 logical volume。
识别到正确的卷之后,按 OSD 目标约定挂载:
```text
/var/lib/ceph/osd/{cluster name}-{osd id}
```
对示例(OSD id 为 `0`),即:
```text
/var/lib/ceph/osd/ceph-0
```
过程完成后调用启动 OSD:
```bash
systemctl start ceph-osd@0
```
这一 systemd 部分由 **`ceph-volume simple trigger`** 子命令处理,它只负责解析来自 systemd 与启动过程的元数据,然后分发给 `ceph-volume simple activate` 去完成激活。
> 引自:[simple](https://docs.ceph.com/en/tentacle/ceph-volume/simple/)、[scan(simple)](https://docs.ceph.com/en/tentacle/ceph-volume/simple/scan/)、[activate(simple)](https://docs.ceph.com/en/tentacle/ceph-volume/simple/activate/)、[systemd(simple)](https://docs.ceph.com/en/tentacle/ceph-volume/simple/systemd/)
---
## 四、zfs 后端(仅限 FreeBSD)
`zfs` 子命令实现了从 `zfs` 子命令部署 OSD 所需的功能:`ceph-volume zfs`。
> ⚠️ **现状(重要):当前实现只适用于 FreeBSD 上的 ZFS。**(`zfs/index.rst` 原文:"The current implementation only works for ZFS on FreeBSD")
### 4.1 用户可见子命令
| 子命令 | 状态 |
|--------|------|
| `inventory` | ✅ 可用(**仅 FreeBSD 平台**) |
| `prepare` | ❌ not yet implemented(源文中被注释掉) |
| `activate` | ❌ not yet implemented(源文中被注释掉) |
| `create` | ❌ not yet implemented(源文中被注释掉) |
| `list` | ❌ not yet implemented(源文中被注释掉) |
| `scan` | ❌ not yet implemented(源文中被注释掉) |
### 4.2 `inventory`(zfs)
`inventory` 子命令**通过 GEOM** 查询主机的磁盘清单,提供每个物理设备的硬件信息与元数据。
> ⚠️ **只在 FreeBSD 平台上工作。**
- 默认情况下,命令返回所有物理磁盘的**简短、人类可读**报告。
- 需要程序化消费该报告时,传 **`--format json`** 生成 JSON 格式报告。该报告包含物理驱动器的丰富信息,例如磁盘元数据(如 model 和 size)、logical volumes、它们是否被 ceph 使用,以及该盘是否能被 ceph 使用、不能用的原因。
- 可以指定一个设备路径,以 plain 或 json 两种格式获取该设备的详细信息。
#### 4.2.1 参数表
| 参数 / 位置参数 | 默认值 | 含义 | 示例 |
|---------------|--------|------|------|
| `<device path>`(位置参数) | 无(不给则报告所有物理磁盘) | 指定设备路径,获取该设备的详细信息 | 文档未给出具体示例 |
| `--format json` | 默认 plain(人类可读短报告) | 生成 JSON 格式报告,供程序化消费 | `ceph-volume zfs inventory --format json` |
### 4.3 限制小结
| 限制项 | 说明 |
|--------|------|
| 平台 | 仅 FreeBSD |
| 发现机制 | 通过 **GEOM**(与 Linux 侧的实现路径不同) |
| 可用能力 | 仅有 `inventory`,**不能部署 OSD**(prepare/activate/create/list/scan 均未实现) |
> 💡 补充:从源文看,`zfs` 后端目前只具备「看盘」能力,不具备「建 OSD」能力。因此在生产 Linux 环境中它没有任何实用价值;本册范围外的 Linux 部署请一律使用 `lvm` 后端。
> 引自:[zfs](https://docs.ceph.com/en/tentacle/ceph-volume/zfs/)、[inventory(zfs)](https://docs.ceph.com/en/tentacle/ceph-volume/zfs/inventory/)
---
## 五、`inventory`:设备清单报告
`inventory` 子命令查询主机的磁盘清单(disc inventory),并提供**每个物理设备的硬件信息与元数据**。
- 默认情况下,该命令返回**所有物理磁盘的简短、人类可读报告**。
- 需要程序化消费该报告时,传 **`--format json`** 生成 JSON 格式报告。该报告包含物理驱动器的丰富信息,例如:
- 磁盘元数据(如 **model** 和 **size**)
- **logical volumes**
- 它们**是否被 ceph 使用**
- 该盘**是否能被 ceph 使用**,以及**不能用的原因**
- 可以指定一个**设备路径**,以 plain 和 json 两种格式获取该设备的详细信息。
### 5.1 参数表
| 参数 / 位置参数 | 默认值 | 含义 | 示例 |
|---------------|--------|------|------|
| `<device path>`(位置参数) | 无(不给则报告所有物理磁盘) | 指定设备路径,报告该设备的详细信息(plain 与 json 均支持) | 文档未给出具体示例路径 |
| `--format json` | 默认 plain(简短人类可读报告) | 生成 JSON 格式报告,供程序化消费 | `ceph-volume inventory --format json` |
### 5.2 输出解读要点
| 关注点 | 说明 |
|--------|------|
| 设备是否被 Ceph 使用 | 报告会标明 logical volume 是否被 ceph 占用——这是判断「这块盘能不能动」的第一道依据 |
| 设备是否**可用**(usable) | 报告会给出该盘能否被 ceph 使用;如果不能用,会给出**原因**。这是排查「为什么我的盘没被 drive group / batch 选中」的关键字段 |
| model / size | 用于确认物理盘型号与容量,避免选错盘 |
| logical volumes | 列出盘上已有的 LV 及其与 Ceph 的关系 |
> 💡 补充:官方文档对 `inventory` 的描述很短,**没有给出实际的样例输出文本**,因此本册不臆造输出样例。实际字段请以 `ceph-volume inventory --format json` 的真实输出为准。它的典型用法是:在跑 `batch` / drive group 之前,先用它确认「哪些盘会被认为是 available」,避免部署时才发现设备被跳过。
> 💡 补充:`zfs` 后端也有同名的 `inventory` 子命令,但走 GEOM、仅限 FreeBSD(见第四章)。Linux 上使用的是顶层 `ceph-volume inventory`。
> 引自:[inventory](https://docs.ceph.com/en/tentacle/ceph-volume/inventory/)
---
## 六、`drive-group`:drive group spec 与 ceph-volume 的关系
`drive-group` 子命令允许把 **drivegroups 规格(specification)以 json 形式直接传给 ceph-volume**。之后 ceph-volume 会尝试**通过 `batch` 子命令**来部署这些 drive group。
### 6.1 核心关系(一句话)
> **一个 drive group 规格 → 一次 `ceph-volume lvm batch` 调用。**
`batch.rst` 中的对应表述:「The `batch` subcommand is closely related to drive-groups. One individual drive group specification translates to a single `batch` invocation.」
并且,`batch` 的幂等性设计与 drivegroups **紧密耦合、并被 drivegroups 大量使用**——这就是 drive group 可以反复 apply、且换盘后能自动补齐 OSD 的底层机制。
### 6.2 规格的传入方式
| 传入方式 | 说明 |
|---------|------|
| 文件 | 通过一个文件传入 spec |
| 字符串参数 | 作为 string argument 传入 |
| stdin | 从标准输入传入 |
### 6.3 用法
```bash
ceph-volume drive-group --help
```
> ⚠️ 注意:`drive-group.rst` 全文只有上述内容,**没有给出具体的 spec 字段定义、示例 JSON 或具体的命令行 flag 名称**,并明确写着「See the subcommand help for further details」,即让你去看 `ceph-volume drive-group --help`。
### 6.4 与 batch 的能力对应关系
| drive group 想做的事 | 落到 ceph-volume 的什么能力 |
|---------------------|---------------------------|
| 按设备属性(SSD/HDD)筛选 | `batch` 的自动排序(按 rotational 属性)/ `--no-auto`、`--auto` |
| 指定 db / wal 落在哪些盘 | `--db-devices` 等显式设备列表(官方推荐做法) |
| 控制 db/wal 大小 | `--block-db-size` / `--block-wal-size` / `--journal-size`,或 slots 类隐式提示 |
| 加密 | `--dmcrypt`(`batch` 支持 `create` 的全部特性) |
| 反复 apply、换盘补齐 | `batch` 的幂等性设计 |
> 💡 补充:drive group spec 本身的**字段语法**(如 `data_devices`、`db_devices`、`osds_per_device` 等)定义在 `doc/cephadm/drivegruops.rst`(属本册范围外),本册不展开;本册只覆盖它「如何落到 ceph-volume」这一层。
> 引自:[drive-group](https://docs.ceph.com/en/tentacle/ceph-volume/drive-group/)
---
## 七、常见工作流示例
> ⚠️ 以下流程中的命令均由本册覆盖的官方页面中的真实命令组合而成;凡官方文档未给出的具体取值(如路径、大小格式),均已在表格/说明中标注「文档未明确」。
### 7.1 新增 OSD(单盘,一步到位)
```bash
# 1) 先看清楚这台机器上有哪些盘、哪些可用
ceph-volume inventory
# 2) 一步创建并激活(OSD 会立刻 up and in)
ceph-volume lvm create --bluestore --data /dev/sdb
```
### 7.2 新增 OSD(单盘,两步、平滑引入)
```bash
# 1) 只做 prepare,此时 OSD 不会 up/in,便于控制 rebalance 节奏
ceph-volume lvm prepare --bluestore --data /dev/sdb --crush-device-class foo
# 2) 确认 fsid(prepare 时生成,存放在 OSD 路径下的 fsid 文件)
cat /var/lib/ceph/osd/ceph-0/fsid
# 3) 激活(需 id + uuid)
ceph-volume lvm activate --bluestore 0 0263644D-0BF1-4D6D-BC34-28BD98AE3BC8
```
### 7.3 批量新增 OSD(推荐:先预演)
```bash
# 1) 预演:只打印计算出的布局,不部署
ceph-volume lvm batch --report /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
# 2) 用 JSON 预演,便于脚本化校验
ceph-volume lvm batch --report --format json-pretty /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
# 3) 确认无误后实跑(--yes 跳过确认;不加则会打印报告并等待你确认)
ceph-volume lvm batch --yes /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
```
### 7.4 替换故障盘
```bash
# 1) 停止故障 OSD(cephadm 环境用 cephadm unit)
systemctl stop ceph-osd@1
# 2) 按 OSD ID(或 FSID)擦除;裸盘必须加 --destroy 才会移除 vgs/lvs
ceph-volume lvm zap --destroy --osd-id 1
# 更严格:同时给 FSID
ceph-volume lvm zap --destroy --osd-fsid 2E8FBE58-0328-4E3B-BFB7-3CACE4E9A6CE --osd-id 1
# 3) 更换硬件后,重跑与当初完全相同的 batch 命令
# ceph-volume 会发现期望的 3 个 OSD 只存在 2 个,从而重建缺失的那个
ceph-volume lvm batch --yes /dev/sdb /dev/sdc /dev/sdd --db-devices /dev/nvme0n1
```
> ⚠️ 注意:zap 时如果对应的 systemd unit 仍在运行,工具会**拒绝执行**,必须先停守护进程。
### 7.5 迁移 db / wal
```bash
# A) 把主设备上的 BlueFS 数据搬到已挂载的 DB LV
ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data --target vgname/db
# B) 把主设备上的 BlueFS 数据搬到一个将作为新 DB 挂载的 LV
ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data --target vgname/new_db
# C) 把 DB 设备上的数据搬到新 LV(DB 被替换)
ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from db --target vgname/new_db
# D) 从主 + DB 搬到新 LV(DB 被替换)
ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data db --target vgname/new_db
# E) 从主 + DB + WAL 搬到新 LV(WAL 被移除,DB 被替换)
ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from data db wal --target vgname/new_db
# F) 从 DB + WAL 搬回主设备(WAL 与 DB 都被移除)
ceph-volume lvm migrate --osd-id 1 --osd-fsid <uuid> --from db wal --target vgname/data
# G) 给还没有 DB 的 OSD 新挂一个 DB / WAL 卷(若已挂 DB 会失败)
ceph-volume lvm new-db --osd-id 1 --osd-fsid 55BD4219-16A7-4037-BC20-0F158EFCC83D --target vgname/new_db
ceph-volume lvm new-wal --osd-id 1 --osd-fsid 55BD4219-16A7-4037-BC20-0F158EFCC83D --target vgname/new_wal
```
### 7.6 修复 BlueFS spillover(db 溢出到慢设备)
```bash
# 1) 扩容 db LV
lvextend -l ${size} ${lv}/${db} ${ssd_dev}
# 2) 停 OSD
cephadm unit --fsid $cid --name osd.${osd} stop
# 3) bluefs-bdev-expand
cephadm shell --fsid $cid --name osd.${osd} -- ceph-bluestore-tool bluefs-bdev-expand --path /var/lib/ceph/osd/ceph-${osd}
# 4) bluefs-bdev-migrate
cephadm shell --fsid $cid --name osd.${osd} -- ceph-bluestore-tool bluefs-bdev-migrate --path /var/lib/ceph/osd/ceph-${osd} --devs-source /var/lib/ceph/osd/ceph-${osd}/block --dev-target /var/lib/ceph/osd/ceph-${osd}/block.db
# 5) 起 OSD
cephadm unit --fsid $cid --name osd.${osd} start
```
### 7.7 擦除设备(退役 / 复用)
```bash
# 只擦内容,保留 lv / 分区本身
ceph-volume lvm zap osd-vg/data-lv
ceph-volume lvm zap /dev/sdc1
# 完全移除(裸盘复用必须加 --destroy)
ceph-volume lvm zap /dev/sdc --destroy
ceph-volume lvm zap /dev/sdc1 --destroy
ceph-volume lvm zap osd-vg/data-lv --destroy
# 按 OSD 过滤(可一次擦多个设备)
ceph-volume lvm zap --destroy --osd-id 1
ceph-volume lvm zap --destroy --osd-fsid 2E8FBE58-0328-4E3B-BFB7-3CACE4E9A6CE
```
### 7.8 接管遗留 ceph-disk OSD
```bash
# 1) 扫描所有运行中的 ceph-disk OSD(非 ceph-disk 创建的会被忽略)
ceph-volume simple scan
# 或扫描指定目录 / data partition
ceph-volume simple scan /var/lib/ceph/osd/ceph1
ceph-volume simple scan /dev/sda1
# 需要覆盖已有 JSON 时
ceph-volume simple scan --force /dev/sda1
# 只想看看不落盘
ceph-volume simple scan --stdout /dev/sda1
# 2) 激活(会 mask 掉所有 ceph-disk systemd unit)
ceph-volume simple activate 0 6cc43680-4f6e-4feb-92ff-9c7ba204120e
# 或
ceph-volume simple activate --file /etc/ceph/osd/0-6cc43680-4f6e-4feb-92ff-9c7ba204120e.json
# 3) 开机自启
systemctl enable ceph-volume@simple-0-6cc43680-4f6e-4feb-92ff-9c7ba204120e
```
### 7.9 查看 / 巡检
```bash
# 全量 pretty 报告(按 OSD ID 分组)
ceph-volume lvm list
# 单个 LV(必须 vg/lv 形式)
ceph-volume lvm list test_group/data-lv2
# 单个分区
ceph-volume lvm list /dev/sdd1
# JSON 全量(含原始 tags,适合脚本)
ceph-volume lvm list --format=json
# 设备清单(Linux)
ceph-volume inventory
ceph-volume inventory --format json
```
### 7.10 创建加密 OSD
```bash
# 1) 准备(--dmcrypt 必需)
ceph-volume lvm prepare --bluestore --dmcrypt --data vg/lv
# 1') Squid 起可启用 TPM2 token enrollment
ceph-volume lvm prepare --bluestore --dmcrypt --with-tpm --data vg/lv
# 2) 激活时无需再指定 --dmcrypt(没有这个 flag,加密 OSD 自动检测)
ceph-volume lvm activate --bluestore 0 0263644D-0BF1-4D6D-BC34-28BD98AE3BC8
```
### 7.11 用分区部署(先建带 PARTUUID 的分区)
```bash
parted --script /dev/sdd print
parted --script /dev/sdd mklabel gpt
parted --script /dev/sdd print
parted --script /dev/sdd mkpart primary 1 100%
blkid /dev/sdd1
# 确认输出中带 PARTUUID,例如:
# /dev/sdd1: PARTLABEL="primary" PARTUUID="16399d72-1e1f-467d-96ee-6fe371a7d0d4"
# 然后即可把该分区用作设备参数
ceph-volume lvm prepare --bluestore --data /dev/sdd1
```
> 💡 补充:再次强调——`ceph-volume lvm` 本身**不会**从整块设备创建分区,分区需要你先用 `parted` / `fdisk` 建好(它们会自动写入 `PARTUUID`)。
---
## 八、命令速查表
### 8.1 顶层与通用
| 命令 | 用途 |
|------|------|
| `ceph-volume inventory` | 查询主机物理磁盘清单,输出简短人类可读报告 |
| `ceph-volume inventory --format json` | 输出 JSON 报告(含 model/size、LV、是否被 ceph 使用、是否可用及原因) |
| `ceph-volume inventory <device path>` | 报告单个设备的详细信息(plain / json 均可) |
| `ceph-volume drive-group --help` | 查看把 drive group spec 直接传给 ceph-volume 的用法(spec 可由文件 / 字符串 / stdin 传入) |
| `ceph-volume zfs inventory` | FreeBSD 上通过 GEOM 查询磁盘清单(仅 FreeBSD) |
| `ceph-volume zfs inventory --format json` | 同上,JSON 输出 |
### 8.2 lvm 后端
| 命令 | 用途 |
|------|------|
| `ceph-volume lvm prepare --bluestore --data vg/lv` | 在已有 LV 上打元数据(不激活、不改动卷内容) |
| `ceph-volume lvm prepare --bluestore --data /path/to/device` | 传裸设备,自动创建 VG/LV 后 prepare |
| `ceph-volume lvm prepare --bluestore --dmcrypt --data vg/lv` | 启用 dmcrypt 加密 |
| `ceph-volume lvm prepare --bluestore --dmcrypt --with-tpm --data vg/lv` | 加密 + TPM2 token enrollment(Squid 起) |
| `ceph-volume lvm prepare --bluestore --data vg/lv --crush-device-class foo` | 指定 CRUSH device class |
| `ceph-volume lvm prepare --filestore --data <dev> --journal <dev>` | filestore 后端(**Reef 起已废弃**) |
| `ceph-volume lvm prepare --filestore --osd-id 0 --osd-fsid <uuid>` | 对既有 OSD 用 prepare(**会销毁数据**) |
| `ceph-volume lvm activate --bluestore <id> <uuid>` | 激活单个已 prepare 的 OSD |
| `ceph-volume lvm activate --all` | 激活所有由 ceph-volume 创建但处于 inactive 的 OSD(幂等) |
| `ceph-volume lvm create --bluestore --data <dev>` | `prepare` + `activate` 一步到位,OSD 立即 up/in |
| `ceph-volume lvm batch --report <devices> --db-devices <dev>` | 预演批量部署布局,打印报告后退出 |
| `ceph-volume lvm batch --report --format json-pretty ...` | 以 JSON 形式预演 |
| `ceph-volume lvm batch --yes <devices> --db-devices <dev>` | 跳过确认直接批量部署 |
| `ceph-volume lvm batch ... --no-auto` | 所有设备都作独立 OSD,不做自动排序 |
| `ceph-volume lvm batch ... --auto` | 显式启用按 rotational 属性的自动排序 |
| `ceph-volume lvm batch ... --block-db-slots N` | 隐式 sizing:提示应有 N 个 data device 的 db 落在快速设备上 |
| `ceph-volume lvm batch ... --block-wal-slots N` | 同上,针对 wal |
| `ceph-volume lvm batch ... --journal-slots N` | 同上,针对 journal |
| `ceph-volume lvm batch ... --block-db-size <size>` | 显式指定 db 卷大小(无法满足则不部署任何 OSD) |
| `ceph-volume lvm batch ... --block-wal-size <size>` | 显式指定 wal 卷大小 |
| `ceph-volume lvm batch ... --journal-size <size>` | 显式指定 journal 大小 |
| `ceph-volume lvm list` | 列出所有与 Ceph 关联的设备/LV(按 OSD ID 分组) |
| `ceph-volume lvm list <vg>/<lv>` | 列出单个 logical volume(必须带卷组名) |
| `ceph-volume lvm list /dev/sdd1` | 列出单个分区 |
| `ceph-volume lvm list --format=json` | JSON 输出,含原始 LVM tags |
| `ceph-volume lvm zap <vg>/<lv>` | 擦除 LV 内容(保留 LV 本身) |
| `ceph-volume lvm zap /dev/sdc1` | 擦除分区 |
| `ceph-volume lvm zap /dev/sdc --destroy` | 擦除并移除裸设备上的 vgs/lvs |
| `ceph-volume lvm zap --destroy --osd-id 1` | 按 OSD ID 过滤擦除 |
| `ceph-volume lvm zap --destroy --osd-fsid <uuid>` | 按 OSD FSID 过滤擦除(更严格) |
| `ceph-volume lvm migrate --osd-id N --osd-fsid <uuid> --from data --target vg/lv` | 把 BlueFS 数据从主设备搬到目标 LV |
| `ceph-volume lvm migrate ... --from data db wal --target vg/lv` | 多源搬迁(WAL 移除、DB 替换) |
| `ceph-volume lvm migrate ... --from db wal --target vgname/data` | 搬回主设备,WAL 与 DB 均移除 |
| `ceph-volume lvm new-db --osd-id N --osd-fsid <uuid> --target vg/lv` | 给 OSD 新挂一个 DB 卷(已有 DB 则失败) |
| `ceph-volume lvm new-wal --osd-id N --osd-fsid <uuid> --target vg/lv` | 给 OSD 新挂一个 WAL 卷 |
| `ceph-volume lvm scan` | 发现此前由本工具配置的 Ceph 卷 —— **尚未实现(not yet implemented)** |
| `ceph-volume lvm trigger` | 内部子命令:解析 systemd 元数据并分发给 `ceph-volume lvm activate` |
### 8.3 simple 后端
| 命令 | 用途 |
|------|------|
| `ceph-volume simple scan` | 扫描所有运行中的 ceph-disk OSD(非 ceph-disk 创建的会被忽略) |
| `ceph-volume simple scan /var/lib/ceph/osd/ceph1` | 扫描 OSD 目录 |
| `ceph-volume simple scan /dev/sda1` | 扫描 OSD 的 data partition(**必须是 data partition**) |
| `ceph-volume simple scan --force <path>` | 覆盖已存在的 JSON 元数据文件 |
| `ceph-volume simple scan --stdout <path>` | 输出到 stdout,不写文件 |
| `ceph-volume simple activate <id> <uuid>` | 激活已扫描的 OSD(同时 mask 掉所有 ceph-disk systemd unit) |
| `ceph-volume simple activate --file /etc/ceph/osd/{id}-{uuid}.json` | 直接指定 JSON 文件激活 |
| `ceph-volume simple trigger` | 内部子命令:解析 systemd 元数据并分发给 `ceph-volume simple activate` |
### 8.4 systemd 相关
| 命令 | 用途 |
|------|------|
| `systemctl enable ceph-volume@lvm-<id>-<uuid>` | 启用 lvm 后端 OSD 的开机激活 unit(oneshot,本地文件系统就绪后运行) |
| `systemctl enable ceph-volume@simple-<id>-<uuid>` | 启用 simple 后端 OSD 的开机激活 unit |
| `systemctl start ceph-osd@<id>` | 启动该 OSD 的守护进程 |
| `systemctl stop ceph-osd@<id>` | 停止该 OSD 守护进程(zap 前需要) |
| `CEPH_VOLUME_SYSTEMD_TRIES`(环境变量) | 激活重试最大次数,默认 **30** |
| `CEPH_VOLUME_SYSTEMD_INTERVAL`(环境变量) | 重试间隔秒数,默认 **5** |
### 8.5 辅助命令(文档中出现的非 ceph-volume 命令)
| 命令 | 用途 |
|------|------|
| `ls -l /var/lib/ceph/osd/ceph-0` | 查看 OSD 目录与 block / block.db / block.wal 符号链接 |
| `parted --script /dev/sdd mklabel gpt` | 给设备建 GPT label |
| `parted --script /dev/sdd mkpart primary 1 100%` | 建分区(自动带 PARTUUID) |
| `blkid /dev/sdd1` | 确认分区含可被发现的 PARTUUID |
| `lvextend -l ${size} ${lv}/${db} ${ssd_dev}` | 扩容 db 用的 logical volume |
| `cephadm unit --fsid $cid --name osd.${osd} stop` | 停止 cephadm 管理的 OSD |
| `cephadm unit --fsid $cid --name osd.${osd} start` | 启动 cephadm 管理的 OSD |
| `cephadm shell --fsid $cid --name osd.${osd} -- ceph-bluestore-tool bluefs-bdev-expand --path /var/lib/ceph/osd/ceph-${osd}` | 让 BlueFS 认识到扩容后的新容量 |
| `cephadm shell --fsid $cid --name osd.${osd} -- ceph-bluestore-tool bluefs-bdev-migrate --path ... --devs-source .../block --dev-target .../block.db` | 把数据从 slow device 搬回 db device |
| `ceph health detail` | 查看 BlueFS spillover 等健康详情 |
| `ln -s /path/to/journal /var/lib/ceph/osd/<cluster>-<id>/journal` | 把 journal 卷链接到已挂载的数据卷(filestore) |
| `ceph --cluster ceph --name client.bootstrap-osd --keyring /var/lib/ceph/bootstrap-osd/ceph.keyring mon getmap -o <path>/activate.monmap` | 用 bootstrap key 抓取 monmap(filestore) |
| `ceph-osd --cluster ceph --mkfs --mkkey -i <id> --monmap ... --osd-data ... --osd-journal ... --osd-uuid <uuid> --keyring ... --setuser ceph --setgroup ceph` | 填充 OSD 目录(filestore) |
| `ceph-bluestore-tool prime-osd-dir`(在 activate 流程中调用) | 指向 OSD block 设备,重建 OSD 目录所需文件 |
---
## 文档未明确项
以下条目在本次覆盖的 24 个 rst 源文中**没有给出明确说明**,本册不做编造,需以 `--help` 或源码/其他分册为准:
| # | 未明确项 | 说明 |
|---|---------|------|
| 1 | `--no-systemd` 的实际参数名 | `batch.rst` 只描述了「avoiding `systemd` units from starting」这一**特性**,未给出 flag 字面名称。本册涵盖的源文中未出现 `--no-systemd` 字符串 |
| 2 | `ceph-volume lvm prepare` / `create` 的**完整**参数清单 | 官方文档只在叙述中逐个提到 `--bluestore`、`--data`、`--block.db`、`--block.wal`、`--journal`、`--dmcrypt`、`--with-tpm`、`--osd-id`、`--osd-fsid`、`--crush-device-class`、`--filestore`,**没有** `--help` 式全量列表;是否还有其他参数(如 `--block-db-size` 在 create 下是否可用)未明确 |
| 3 | `--block-db-size` / `--block-wal-size` / `--journal-size` 的取值格式 | 文档只说「provide explicit sizes」,未说明是 `60G`、`60GB` 还是字节数,也未给示例 |
| 4 | `--block-db-slots` / `--block-wal-slots` / `--journal-slots` 的默认值 | 文档未明确 |
| 5 | `--crush-device-class` 的默认值 | 文档只给了用法示例(`--crush-device-class foo`),未说明默认值(如是否自动识别 ssd/hdd) |
| 6 | `batch` 的 `--format` 默认值 | 文档只说明支持 `json` 与 `json-pretty`,并提到 `pretty` 是报告的默认「pretty report format」,未以参数默认值形式明确 |
| 7 | `--db-devices` 之外的同族参数 | 文档只出现 `--db-devices`;是否有 `--wal-devices`、`--journal-devices` 未明确 |
| 8 | `batch` 是否支持显式 `--bluestore` | 文档只说「defining bluestore」被支持,未给出该 flag 的实际拼写与默认值 |
| 9 | `ceph-volume lvm activate` 的 `--bluestore` 默认值 | 示例中使用了 `--bluestore`,但文档说 objectstore 类型由 LVM tags 推断,该 flag 是否必需未明确 |
| 10 | `inventory` 的实际输出样例与字段清单 | 文档只描述了「会包含哪些类型的信息」,**没有给任何样例输出** |
| 11 | `inventory <device path>` 的示例 | 文档只说「可以指定设备路径」,未给示例 |
| 12 | `zfs inventory` 的示例命令与输出 | 同上,且仅限 FreeBSD |
| 13 | `drive-group` 子命令的具体 flag 与 spec 字段 | `drive-group.rst` 明确要求去看 `ceph-volume drive-group --help`;spec 字段定义在本册范围外 |
| 14 | OSD data 与 journal 的**最小容量要求**数值 | `prepare.rst` 只说「be sure to meet the minimum size requirements」,未给数字 |
| 15 | `ceph-volume lvm create` 的幂等性 | 文档对 `activate` 与 `batch` 明确写了幂等,对 `create` / `prepare` 未明确 |
| 16 | `CEPH_VOLUME_SYSTEMD_TRIES` / `CEPH_VOLUME_SYSTEMD_INTERVAL` 的设置方式 | 文档只说明它们是「configurable environment variables」及默认值,未说明应在何处配置(systemd unit 的 `Environment=`、`/etc/environment` 等) |
| 17 | `migrate` 的 `--from` 是否支持 `block` 这个别名 | 文档示例只用 `data` / `db` / `wal` |
| 18 | `new-wal` 的失败条件 | `newwal.rst` 原文写「Fails if OSD has already got attached **DB**」,与直觉(应为已挂 WAL)不一致;源文如此,未作改动,是否笔误未明确 |
| 19 | SPDK 后端的子命令名与可用性 | `intro.rst` 只说「on the immediate horizon」,未给子命令名,也未见对应 rst 页面 |
| 20 | `ceph-volume lvm trigger` 的完整参数 | 文档只说明其职责,未给参数 |
| 21 | `lvm scan` 的实现计划 | 文档仅标注 `not yet implemented`,无时间表 |
| 22 | `zfs` 后端 prepare/activate/create/list/scan 的实现计划 | 源文中均被注释为 `not yet implemented`,无时间表 |
| 23 | `ceph-volume` 与 cephadm 的具体调用界面 | 文档仅在 `activate.rst` 提示「For OSDs deployed by cephadm, refer to cephadm-osd-activate」,未在本册展开 |
| 24 | `--with-tpm` 的前置条件(TPM2 硬件/软件栈要求、失败回退行为) | 文档只说自 Squid 起可选用,未展开 |
| 25 | LUKS2 在哪些发行版可用 | 文档只说「not widely available in all Linux distributions supported by Ceph」,未列具体发行版 |
| 26 | `zap` 对 `block.db` / `block.wal` 单独设备的处理 | 文档只说可按 `--osd-id` / `--osd-fsid` 过滤多个设备,未说明 db/wal 是否总被一并处理 |
---
> 本册完。全部内容均整理自 Ceph Tentacle v20.2.4 官方 `doc/ceph-volume/` 下 24 个 rst 源文;凡官方未写之处,均已标注「文档未明确」,由本册作者补充的推断与提示均以「💡 补充」标出。