Files
wiki/存储/Ceph/知识库/03-RADOS-集群运维与配置.md
T
2026-09-18 13:49:11 +08:00

3232 lines
164 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
> 基于 Ceph 官方文档整理 | 文档版本:**Tentacle v20.2.4** | 抓取日期:2026-09-17 | 源文:ceph/ceph@v20.2.4 `doc/rados/`
> 官网入口:https://docs.ceph.com/en/tentacle/rados/
# 第 03 册 RADOS 核心篇(下):集群运维与配置参考
## 本册导读
本册覆盖 Ceph RADOS 的**日常运维动作**与**配置参考**两大部分,共 21 章 + 1 个"文档未明确项"清单。
| 板块 | 章节 | 回答的问题 |
|---|---|---|
| 集群生命周期 | 一 ~ 三 | 怎么启停集群、怎么加/删 MON、怎么加/删/换 OSD |
| 集群控制 | 四 | 有哪些开关(flag)、怎么用 `ceph` 命令操纵集群状态 |
| 可观测性 | 五 ~ 七 | 怎么看集群健康、怎么看 OSD/PG、每个告警码是什么意思 |
| 安全 | 八 | cephx 是什么、cap 怎么写、密钥怎么管 |
| 数据分布与特性 | 九 ~ 十三 | 均衡器、缓存分层、stretch mode、BlueStore 迁移、设备健康管理 |
| 配置参考 | 十四 ~ 二十一 | ceph.conf 与集中配置库、MON/OSD/网络/msgr2/mclock 全部配置项 |
阅读建议:
1. **排障优先看第七章**。第七章按 MON / Auth / MGR / OSD / BlueStore / 设备 / PG-Pool / Stretch / NVMeoF / Misc 分类,逐个列出官方 health-checks 页面中的告警码,给出「告警码 | 含义 | 触发原因 | 处理步骤」。
2. **改配置前先看第十四章**。Ceph 的配置来源有优先级(编译默认值 → MON 集中库 → 本地 ceph.conf → 环境变量 → 命令行 → 运行时覆盖),很多"改了没生效"的问题根源就在这里。
3. 配置项表中"类型/默认值"一栏若写「文档未明确」,表示**本册所依据的 rst 源文中未提供该值**(Ceph 官方文档页面上的类型/默认值由 Ceph 源码中的选项定义生成,不在 `doc/` 目录内)。此时请在实机上执行 `ceph config help <option>` 或 `ceph config show <daemon>` 查询,本册不做推测。
---
## 一、集群运维总览(Operating a Cluster)
Ceph 的一切服务都以**守护进程(daemon)**形式运行:`ceph-mon`、`ceph-mgr`、`ceph-osd`,部署 CephFS 时还有 `ceph-mds`,部署对象存储时还有 `radosgw`。
### 1.1 systemd 下启停集群
在所有运行 Ceph 守护进程的节点上,可以通过 `systemd` 统一操作。
```bash
# 启动本节点上所有 Ceph 守护进程
sudo systemctl start ceph.target
# 停止本节点上所有 Ceph 守护进程
sudo systemctl stop ceph.target
```
按**类型**启停(在本节点上):
```bash
sudo systemctl start ceph-osd.target
sudo systemctl start ceph-mon.target
sudo systemctl start ceph-mds.target
```
按**单个实例**启停:
```bash
# 按 OSD 编号
sudo systemctl start ceph-osd@{osd-id}
sudo systemctl stop ceph-osd@{osd-id}
sudo systemctl status ceph-osd@{osd-id}
# 示例
sudo systemctl restart ceph-osd@1
```
```bash
# 按 MON / MDS 主机名
sudo systemctl start ceph-mon@{hostname}
sudo systemctl start ceph-mds@{hostname}
```
```bash
# 按 MGR 实例名
sudo systemctl start ceph-mgr@{hostname}
```
> 💡 补充:Ceph 的 systemd unit 采用模板化命名,`@` 后面的实例名必须与 `/var/lib/ceph` 下的数据目录一致(OSD 用数字 ID,MON/MDS/MGR 用主机名或实例名),否则会出现 unit 启动失败但 `ceph -s` 看不到对应 daemon 的情况。
### 1.2 SysVinit 下的 `ceph` 命令
在没有 systemd 的环境(或用 `ceph` 统一脚本)中,语法为:
```bash
{commandline} [options] [commands] [daemons]
```
例如:
```bash
sudo /etc/init.d/ceph start
sudo /etc/init.d/ceph -a start # 作用于所有节点/全部实例
sudo /etc/init.d/ceph start osd # 只启动 osd 类型
sudo /etc/init.d/ceph start osd.0 # 只启动 osd.0
```
### 1.3 `ceph` 脚本选项
| 选项 | 含义 |
|---|---|
| `--verbose` / `-v` | 输出更详细信息 |
| `--valgrind` | 用 valgrind 启动守护进程(调试用) |
| `--allhosts` / `-a` | 在 `ceph.conf` 中配置的所有主机上执行(通常配合 ssh) |
| `--restart` | 核心转储后自动重启(把该选项放进 `ceph.conf` 可实现自动重启) |
| `--norestart` | 核心转储后不重启 |
| `--conf` / `-c` | 指定另一份配置文件,例如 `-c /etc/ceph/ceph2.conf` |
### 1.4 `ceph` 脚本命令
| 命令 | 含义 |
|---|---|
| `start` | 启动守护进程 |
| `stop` | 停止守护进程 |
| `forcestop` | 强制停止守护进程(相当于 `kill`) |
| `killall` | 杀掉某类型的所有守护进程 |
| `cleanlogs` | 清空日志目录 |
| `cleanalllogs` | 清空日志目录,并删除更多残留文件 |
### 1.5 守护进程类型(daemon type)
| 类型 | 说明 |
|---|---|
| `mon` | Ceph Monitor |
| `osd` | Ceph OSD Daemon |
| `mds` | Ceph Metadata Server |
> 引自:[Operating a Cluster](https://docs.ceph.com/en/tentacle/rados/operations/operating/)
---
## 二、增加 / 删除 Monitor
### 2.1 基本原则
- MON 之间用 **Paxos** 达成多数派(quorum)一致,所以 MON 数量应为**奇数**。
- 官方建议生产集群部署 **3 台**(小规模)或 **5 台**(大规模)MON:3 台容忍 1 台故障,5 台容忍 2 台故障。
- 一个集群只有 1 台 MON 也能跑,但它是**单点故障**。
### 2.2 手工添加 MON(推荐:让 cephadm/编排工具做,手工流程如下)
假设要新增的 MON ID 为 `{mon-id}`(如 `d`):
```bash
# 1) 在目标主机上创建数据目录
sudo mkdir /var/lib/ceph/mon/ceph-{mon-id}
# 2) 创建临时目录,用于放置组装 monmap 所需的材料
mkdir /tmp/{mon-id}
```
```bash
# 3) 导出 mon. 的密钥
sudo ceph auth get mon. -o /tmp/{mon-id}/keyring
# 4) 导出当前 monmap
sudo ceph mon getmap -o /tmp/{mon-id}/monmap
```
```bash
# 5) 用 monmap 与 keyring 初始化新 MON 的文件系统
sudo ceph-mon --mkfs -i {mon-id} --monmap /tmp/{mon-id}/monmap --keyring /tmp/{mon-id}/keyring
# 6) 启动新 MON(如需指定公网地址)
sudo ceph-mon -i {mon-id} --public-addr {ip:port}
```
启动后 `ceph -s` 应能看到新 MON 加入 quorum。
### 2.3 删除 MON(集群健康时)
```bash
# 1) 停止 MON 服务
sudo systemctl stop ceph-mon@{mon-id}
# 2) 从集群中移除
sudo ceph mon remove {mon-id}
# 3) 从 ceph.conf 中删除对应条目(mon_host / mon_initial_members 等)
```
### 2.4 删除 MON(集群不健康、无法形成 quorum 时)
当剩余 MON 无法形成多数派时,必须**离线改 monmap**:
```bash
# 1) 停止所有 MON
sudo systemctl stop ceph.target
# 2) 从某个 MON 的数据目录里提取 monmap
ceph-mon -i {mon-id} --extract-monmap /tmp/monmap
# 3) 查看并删除目标 MON
monmaptool /tmp/monmap --print
monmaptool /tmp/monmap --rm {mon-id-to-remove}
# 4) 把改过的 monmap 注入回存活的 MON
ceph-mon -i {surviving-mon-id} --inject-monmap /tmp/monmap
# 5) 启动存活的 MON
sudo systemctl start ceph-mon@{surviving-mon-id}
# 6) 验证
ceph -s
```
确认 quorum 恢复后,归档或删除被移除 MON 的数据目录 `/var/lib/ceph/mon/ceph-{mon-id}`。
> ⚠️ 注意:**不要在运行中的 MON 上 inject monmap**(即 MON 进程仍在运行时注入),这会导致不可预期行为。
### 2.5 修改 MON 的 IP 地址
**Preferred(推荐)方式:先加后删**
1. 用新 IP 添加一个新 MON;
2. 等待新 MON 加入 quorum、数据同步完成;
3. 用旧 IP 删除老 MON。
**Advanced(高级)方式:直接改 monmap**
```bash
# 提取 monmap
ceph-mon -i {mon-id} --extract-monmap /tmp/monmap
# 删除旧条目、添加新条目
monmaptool /tmp/monmap --rm {mon-id}
monmaptool /tmp/monmap --add {mon-id} {new-ip}:{port}
# 注入(必须在 MON 停止状态下执行)
ceph-mon -i {mon-id} --inject-monmap /tmp/monmap
```
### 2.6 用 cephadm 修改 MON 的 public network
下文以把 public network 从 `10.10.10.0/24` 改为 `192.168.160.0/24` 为例:
```bash
# 1) 为新网络添加 MON 地址(同时给出 v2 与 v1 端口)
ceph mon set-addrs {mon-id} --addv "[v2:192.168.160.10:3300,v1:192.168.160.10:6789]"
```
```bash
# 2) 让编排器知道主机新地址
ceph orch host set-addr {hostname} 192.168.160.10
# 3) 让 OSD 重新配置以使用新网络
ceph orch reconfig osd
```
> 💡 补充:改网络属于高风险变更,务必在变更窗口内逐台滚动执行,并在每步之后用 `ceph -s`、`ceph mon dump` 确认 quorum 与地址正确。
> 引自:[Add/Remove a Monitor](https://docs.ceph.com/en/tentacle/rados/operations/add-or-rm-mons/)
---
## 三、增加 / 删除 OSD
### 3.1 OSD 在 CRUSH 中的权重与位置
添加 OSD 后必须把它放进 **CRUSH 层级**(host/rack/row…)。如果只加到 `root`,OSD **收不到数据**。
### 3.2 添加 OSD(手工流程)
```bash
# 1) 创建 OSD(可指定 uuid,不推荐显式指定 id)
ceph osd create [{uuid} [{id}]]
```
```bash
# 2) 在新 OSD 主机上创建数据目录
sudo mkdir /var/lib/ceph/osd/ceph-{osd-number}
# 3) 若使用独立磁盘,格式化并挂载(需开启 user_xattr)
sudo mkfs -t {fstype} /dev/{disk}
sudo mount -o user_xattr /dev/{disk} /var/lib/ceph/osd/ceph-{osd-number}
```
```bash
# 4) 初始化 OSD 文件系统并生成密钥
sudo ceph-osd -i {osd-num} --mkfs --mkkey
```
```bash
# 5) 注册 OSD 的认证能力
sudo ceph auth add osd.{osd-num} osd 'allow *' mon 'allow rwx' -i /var/lib/ceph/osd/ceph-{osd-num}/keyring
```
```bash
# 6) 加入 CRUSH(务必指定 host 等 bucket,不要只写 root)
ceph osd crush add {id-or-name} {weight} [{bucket-type}={bucket-name} ...]
# 示例
ceph osd crush add osd.0 1.0 host=osd-host-a
```
```bash
# 7) 启动 OSD
sudo systemctl start ceph-osd@{osd-num}
```
启动后观察,直到它变成 `up` + `in`:
```bash
ceph -w
# 或
watch ceph status
```
### 3.3 替换(重建)OSD
```bash
# 1) 循环确认该 OSD 已无数据残留可安全销毁
while ! ceph osd safe-to-destroy osd.{id} ; do sleep 10 ; done
```
```bash
# 2) 销毁 OSD
ceph osd destroy {id} --yes-i-really-mean-it
```
```bash
# 3) 重新准备磁盘并激活(二选一)
ceph-volume lvm zap /dev/{disk}
ceph-volume lvm prepare --osd-id {id} --data /dev/{disk}
ceph-volume lvm activate {id} {fsid}
# 或者一步到位
ceph-volume lvm create --osd-id {id} --data /dev/{disk}
```
### 3.4 删除 OSD
```bash
# 1) 先标记为 out,让数据迁走
ceph osd out {osd-num}
# 观察数据迁移完成、集群回到 active+clean
ceph -w
```
```bash
# 2) 停止 OSD 进程
sudo systemctl stop ceph-osd@{osd-num}
# 3) 彻底清除(含 CRUSH、auth、osd 记录)
ceph osd purge {id} --yes-i-really-mean-it
# 4) 清理 ceph.conf 中残留条目
```
Luminous 之前的老版本没有 `purge`,需要手工三步:
```bash
ceph osd crush remove {name}
ceph auth del osd.{osd-num}
ceph osd rm {osd-num}
```
### 3.5 小集群的 active+remapped 处理
在 OSD 数量很少的集群里,直接 `out` 一个 OSD 可能长期停在 `active+remapped`。此时应改用 **CRUSH reweight 归零**,让 CRUSH 重新计算分布:
```bash
ceph osd crush reweight osd.N 0
```
> 引自:[Add/Remove OSDs](https://docs.ceph.com/en/tentacle/rados/operations/add-or-rm-osds/)
---
## 四、集群控制(Control)
`ceph` 命令是一个"总入口",通过子命令操纵集群。
### 4.1 Monitor 相关
```bash
ceph -s # 简版状态
ceph status # 完整状态
ceph -w # 持续观察(watch)
ceph health # 仅健康状态
ceph health detail # 健康状态 + 明细
ceph mon stat # MON 概要
ceph quorum_status # quorum 详情(JSON)
ceph mon dump # MON map 详情
ceph tell mon.[id] mon_status
```
### 4.2 Auth 相关
```bash
ceph auth list
ceph auth get {TYPE.ID}
ceph auth add {TYPE.ID} ...
ceph auth caps {TYPE.ID} ...
ceph auth del {TYPE.ID}
ceph auth rotate {entity}
```
### 4.3 PG 相关
```bash
ceph pg dump [--format {format}]
ceph pg dump_stuck {inactive|unclean|stale|undersized|degraded} [--threshold <seconds>]
ceph pg {pgid} mark_unfound_lost revert|delete
```
| 参数 | 说明 |
|---|---|
| `--threshold` | `dump_stuck` 判定"卡住"的秒数阈值,**默认 300** |
| `mark_unfound_lost revert` | 回滚到旧版本对象 |
| `mark_unfound_lost delete` | 直接删除 unfound 对象(会丢数据,谨慎) |
### 4.4 OSD 相关命令速查
```bash
ceph osd stat
ceph osd dump
ceph osd tree
ceph osd getmap -o om
ceph osd getcrushmap -o cm
ceph osd setcrushmap -i cm
ceph osd getmaxosd
ceph osd setmaxosd {num} # 默认 10000
ceph osd map {poolname} {object} # 定位对象
```
```bash
ceph osd crush set {id} {weight} {loc...}
ceph osd crush remove {name}
ceph osd crush move {name} {loc...}
ceph osd crush reweight {name} {weight}
```
```bash
ceph osd create [{uuid} [{id}]]
ceph osd rm {id...}
ceph osd down {id}
ceph osd out {id}
ceph osd in {id}
ceph osd lost {id} --yes-i-really-mean-it # 危险:可能丢数据
```
```bash
ceph osd pause # 停止 OSD 处理请求(内部维护用)
ceph osd unpause
ceph osd reweight {osd} {weight} # 0-1
ceph osd reweight-by-utilization [threshold] [max_change] [max_osds] [--no-increasing]
ceph osd test-reweight-by-utilization [threshold] [max_change] [max_osds] [--no-increasing]
```
| `reweight-by-utilization` 参数 | 默认值 | 说明 |
|---|---|---|
| `threshold` | 20(±20%) | 利用率偏离均值超过该百分比的 OSD 才参与调整 |
| `max_change` | 0.05 | 单次调整的最大幅度 |
| `max_osds` | 4 | 单次最多调整多少个 OSD |
| `--no-increasing` | — | 只允许降低权重,不允许提高 |
> ⚠️ `ceph osd reweight` 与 **balancer** 会互相干扰:若启用 balancer,`osd reweight` 应全部保持 `1.0000`,由 balancer 统一管理分布(见第九章)。
```bash
ceph osd blocklist add {addr} [{stamp}] # 默认封禁 1 小时
ceph osd blocklist rm {addr}
```
```bash
ceph osd pool mksnap {pool} {snap}
ceph osd pool rmsnap {pool} {snap}
ceph osd pool create {pool} {pg-num} [{pgp-num}] [replicated|erasure]
ceph osd pool delete {pool} {pool} --yes-i-really-really-mean-it
ceph osd pool rename {old} {new}
ceph osd pool set {pool} {key} {value} # size / pg_num / pgp_num / crush_rule ...
ceph osd pool get {pool} {key}
```
```bash
ceph osd scrub {osd}
ceph osd repair N # deep scrub + 修复
ceph tell osd.N bench [TOTAL_BYTES] [BYTES_PER_WRITE] # 默认 1GB / 4MB
ceph tell osd.N cache drop
ceph tell osd.N cache status
```
### 4.5 MDS 相关
```bash
ceph tell mds.{id} config set {key} {value}
ceph mds stat
ceph fs dump
ceph mds fail 0
```
### 4.6 集群 flag(重点)
flag 通过 `ceph osd set` / `ceph osd unset` 设置,会触发 `OSDMAP_FLAGS` 告警(说明集群当前被人工"压住"了)。
| flag | 作用 | 何时用 | 风险 |
|---|---|---|---|
| `noout` | 禁止 MON 把 down 的 OSD 标记 out | 计划内停机(换盘、重启整机、网络割接)后不希望触发数据迁移 | 忘记 unset 会让集群长期不恢复冗余;真正故障的 OSD 也得不到重建 |
| `noup` | 禁止 OSD 被标记为 up | 维护期间阻止 OSD 上线 | 新启动的 OSD 无法提供服务 |
| `nodown` | 禁止 OSD 被标记为 down | 网络抖动期间防止 OSD 被误判下线 | 真正挂掉的 OSD 不会被感知,PG 可能 hung |
| `noin` | 禁止 OSD 加入(in) | 部署阶段先让 OSD 起来但不承载数据 | OSD 无法上线承载数据 |
| `nobackfill` | 禁止 backfill | 想让集群只做 recovery、不做全量回填 | 数据分布迟迟不能恢复均衡 |
| `norecover` | 禁止 recovery | 极端场景:先保业务、暂缓恢复 | 冗余度长期不足,二次故障可能丢数据 |
| `norebalance` | 禁止 rebalance | 与 `nobackfill` 类似,抑制重平衡 | 同上 |
| `noscrub` | 禁止 light scrub | 业务高峰期临时抑制 scrub | 元数据不一致无法及时被发现 |
| `nodeep-scrub` | 禁止 deep scrub | 业务高峰期抑制深度校验(I/O 开销大) | 静默数据损坏(bit rot)无法被检出 |
| `notieragent` | 停止 cache tiering agent 的 flush/evict | 缓存分层维护/下线时 | 缓存层写满会阻塞写入 |
| `pauserd` | 暂停所有**读**请求 | 极短时间的内部维护 | 客户端读全挂 |
| `pausewr` | 暂停所有**写**请求 | 极短时间的内部维护 | 客户端写全挂 |
| `pause` | 同时暂停读与写(`pauserd`+`pausewr`) | 需要完全冻结 I/O | 业务完全中断 |
| `full` | 标记集群/OSD 已满,禁止写入 | 一般由 OSD 达到 full ratio 自动置位,也可人工置位保护 | 集群变为只读 |
| `sortbitwise` | 已在新版本中默认,历史遗留 flag | 文档未明确新增使用场景 | 文档未明确 |
```bash
# 设置 / 取消
ceph osd set noout
ceph osd unset noout
# 批量设置一组
ceph osd set-group {flags} # 例:ceph osd set-group noscrub,nodeep-scrub
ceph osd unset-group {flags}
```
可以对**特定目标**打 flag(OSD / host / device class):
```bash
ceph osd set-group noout osd.0
ceph osd set-group noout host-foo
ceph osd set-group nodeep-scrub class-hdd
```
> 引自:[Control](https://docs.ceph.com/en/tentacle/rados/operations/control/)
---
## 五、监控集群(Monitoring a Cluster)
### 5.1 交互模式
不带任何参数执行 `ceph` 会进入交互式 shell:
```bash
sudo ceph
ceph> health
ceph> status
ceph> quorum_status
ceph> quit
```
### 5.2 使用非默认路径
如果配置文件或 keyring 不在默认位置:
```bash
sudo ceph -c /path/to/conf -k /path/to/keyring health
```
### 5.3 `ceph status` 与容量计算
`ceph -s` / `ceph status` 的 `usage` 段展示集群容量。`ceph df` 给出更细的分级:
- **CLASS**:设备类(如 `hdd`、`ssd`)
- **SIZE**:该类的原始总容量
- **AVAIL**:可用容量
- **USED**:已用容量
- **RAW USED**:原始已用(含副本、开销)
- **%RAW USED**:原始使用率
`POOLS` 段字段:
| 字段 | 含义 |
|---|---|
| `STORED` | 用户数据实际大小(不含副本/EC 放大) |
| `DATA` | 计入副本/EC 后的数据占用 |
| `OMAP` | OMAP 键值数据占用 |
| `OBJECTS` | 对象数量 |
| `USED` | 该池总占用 |
| `MAX AVAIL` | 在 full ratio 约束下该池还能写入的量 |
| `QUOTA` | 配额(对象数/字节数) |
| `DIRTY` | 缓存层脏数据(cache tier 场景) |
| `USED COMPR` | 压缩后实际占用 |
| `UNDER COMPR` | 被压缩的数据量(压缩前) |
```bash
ceph df
ceph df detail
```
### 5.4 集群日志与 `ceph -w`
`ceph -w` 会持续打印集群日志(cluster log),等同于 tail `/var/log/ceph/ceph.log`:
```bash
ceph -w
ceph -w cephadm # 只看某个 channel
ceph log last [n] # 打印最近 n 条
```
健康检查触发/清除时都会记日志,典型形态:
```text
[WRN] OSD_DOWN: 1 osds down
[WRN] PG_DEGRADED: Degraded data redundancy: 183/75542 objects degraded (0.242%), 23 pgs degraded
[INF] Health check cleared: OSD_DOWN (was: 1 osds down)
```
### 5.5 慢心跳(Slow OSD heartbeats)
当 OSD 间心跳往返时间超过阈值(back 侧 >1s / 1000ms),集群报 `HEALTH_WARN` 的慢心跳告警,并可能生成 `OSD_SLOW_PING_TIME_BACK` 告警码。
查看网络指标:
```bash
ceph dump_osd_network 0
```
输出按 front / back 两个网络分别给出 **1min / 5min / 15min** 的 `average / min / max / last` 统计,用于判断是持续性问题还是瞬时抖动。
### 5.6 静默告警(health mute)
```bash
ceph health mute <code> # 永久静默
ceph health mute <code> <TTL> # 带 TTL,例如 1h / 8w
ceph health mute <code> --sticky # sticky:重启 MON 后依然保留
ceph health unmute <code>
```
被静默后状态行显示为:
```text
HEALTH_OK (muted: OSD_DOWN)
```
### 5.7 OSD / MON / MDS 状态命令
```bash
ceph osd stat # x osds: y up, z in; epoch: eNNNN
ceph osd tree # CRUSH 树 + 权重 + 利用率
ceph osd dump
ceph mon stat
ceph mon dump
ceph quorum_status # 返回 JSON,含 quorum 成员名与 epoch
ceph mds stat
ceph fs dump
```
### 5.8 Admin socket(与单个守护进程对话)
```bash
# 在守护进程所在主机上,按名字
ceph daemon {daemon-name} {command}
ceph daemon osd.0 config show
ceph daemon osd.0 help
# 或按 socket 路径
ceph daemon /var/run/ceph/ceph-osd.0.asok {command}
# 从任意主机,经 MON 转发
ceph tell osd.0 {command}
ceph tell osd.* {command}
```
admin socket 支持发送信号类操作(例如让守护进程重开日志):
```text
ceph daemon {name} {kill/...} # 具体支持项以 daemon 的 help 输出为准
```
> 💡 补充:文档中提到可以通过 admin socket 向守护进程发信号(如 `HUP` 触发日志重开、`-9` 触发自杀以复现崩溃转储),但具体命令形态需以 `ceph daemon {name} help` 的返回为准。
### 5.9 messenger dump(网络 messenger 信息)
```bash
ceph daemon {daemon-name} dump_messenger_state
```
可选的 messenger 包括:`client`、`cluster`、`hb_back_*`、`hb_front_*`、`ms_objecter`、`temp_mon_client`。加 `--tcp-info` 可附带 TCP 层信息。
### 5.10 数据可用性评分(availability status)
Ceph 可以为每个 pool 统计可用性指标:
```bash
ceph osd pool availability-status
```
| 字段 | 含义 |
|---|---|
| `UPTIME` | 累计可用时长 |
| `DOWNTIME` | 累计不可用时长 |
| `NUMFAILURES` | 失效次数 |
| `MTBF` | 平均故障间隔 |
| `MTTR` | 平均恢复时间 |
| `SCORE` | 可用性评分 |
| `AVAILABLE` | 当前是否可用 |
相关配置:
| 配置项 | 默认值 | 含义 |
|---|---|---|
| `enable_availability_tracking` | `false` | 是否启用可用性统计 |
| `pool_availability_update_interval` | 1(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 统计更新周期 |
清除历史统计:
```bash
ceph osd pool clear-availability-status
```
> 引自:[Monitoring a Cluster](https://docs.ceph.com/en/tentacle/rados/operations/monitoring/)
---
## 六、监控 OSD 与 PG
### 6.1 OSD 的四种状态组合
| 状态 | 含义 |
|---|---|
| `in` | OSD 在 CRUSH 中,承载数据 |
| `out` | OSD 不在 CRUSH 中(或权重为 0),不承载数据 |
| `up` | OSD 进程在跑,能响应 |
| `down` | OSD 进程不可达 |
组合含义:`up+in` 正常;`up+out` 正在把数据迁走;`down+in` 故障但数据仍在它上面(集群降级);`down+out` 已离线且不承载数据。
```bash
ceph osd stat
# 输出形如:
# x osds: y up, z in; epoch: eNNNN
```
### 6.2 PG 的两个集合
- **Acting Set**:负责该 PG 的 OSD 列表(权威副本所在)
- **Up Set**:当前实际提供服务的 OSD 列表
两者在正常情况下一致,恢复/迁移期间可能不同:
```bash
ceph pg map {pg-num}
# osdmap eNNN pg {raw-pg-num} ({pg-num}) -> up [0,1,2] acting [0,1,2]
```
### 6.3 Peering
Peering 是同一个 PG 内所有 OSD 就"对象状态达成一致"的过程。Peering 完成后 PG 才能变成 `active`。
### 6.4 PG 状态一览
| 状态 | 含义 |
|---|---|
| `creating` | PG 刚创建,还在选 OSD |
| `peering` | 正在同步 PG 内对象状态 |
| `active` | Peering 完成,可接受读写 |
| `clean` | 所有副本都就位且一致 |
| `degraded` | 副本数不足(有 OSD down) |
| `recovering` | 正在同步对象(通常是少量对象) |
| `backfill_wait` | 排队等待全量回填 |
| `backfilling` | 正在全量回填 |
| `backfill_toofull` | 目标 OSD 太满,无法回填 |
| `remapped` | 数据正在从旧 Acting Set 迁移到新 Acting Set |
| `stale` | PG 的 primary 长时间没向 MON 报告(通常是 MON 或 OSD 异常) |
### 6.5 OSD down → out 的判定
| 配置项 | 默认值 | 含义 |
|---|---|---|
| `mon_osd_down_out_interval` | 600(秒) | OSD down 多久后被自动标记 out |
设为 `0` 会触发 `OSD_NO_DOWN_OUT_INTERVAL` 告警(见第七章)。
### 6.6 Recovery 相关配置
| 配置项 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|
| `osd_recovery_delay_start` | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | OSD 起来后延迟多久开始 recovery | 大批量 OSD 同时重启时适当加大,避免"恢复风暴" |
| `osd_recovery_thread_timeout` | 文档未明确 | recovery 线程超时 | 文档未明确 |
| `osd_recovery_max_active` | 0(启用 mClock 时) | 每 OSD 并发 recovery 操作数 | 交给 mClock 管理,见第二十章 |
| `osd_recovery_max_chunk` | 8_M(= 8388608 字节 = 8 MiB)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | recovery 单次推送的数据块大小 | 大对象场景可适当调大 |
### 6.7 Backfill 相关配置
| 配置项 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|
| `osd_max_backfills` | 1 | 每 OSD 并发 backfill 数 | 扩容/缩容期可临时调大以加速 |
| `backfill_full_ratio` | 90% | 目标 OSD 使用率超过该值即拒绝回填 | 与 `mon_osd_backfillfull_ratio` 联动 |
| `osd_backfill_retry_interval` | 30(秒) | 回填失败后的重试间隔 | 文档未明确 |
| `osd_backfill_scan_min` | 64 | 单次 backfill 最少扫描对象数 | 大 PG 场景可调大 |
| `osd_backfill_scan_max` | 512 | 单次 backfill 最多扫描对象数 | 配合 min 调整 |
### 6.8 卡住的 PG(stuck PG)
三类 stuck:
| 类型 | 含义 |
|---|---|
| `unclean` | 长时间不是 clean |
| `inactive` | 长时间不能 peering/active |
| `stale` | 长时间没更新状态 |
```bash
ceph pg dump_stuck {inactive|unclean|stale|undersized|degraded} [--threshold <seconds>]
```
### 6.9 定位对象
```bash
ceph osd map {poolname} {object-name} [namespace]
```
> 引自:[Monitoring OSDs and PGs](https://docs.ceph.com/en/tentacle/rados/operations/monitoring-osd-pg/)
---
## 七、健康检查清单(Health Checks)— 本册重点
查看方式:
```bash
ceph health
ceph health detail
ceph health detail --format=json-pretty
```
所有告警码都可以通过 `ceph health mute <code> [TTL]` 静默(见 5.6)。
### 7.1 Monitor 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `DAEMON_OLD_VERSION` | 集群中存在版本较旧的守护进程 | 升级过程中部分 daemon 未升级;`mon_warn_older_version_delay` 默认给一周宽限期 | 完成升级;确认 `ceph versions` 中只有一个版本 |
| `MON_DOWN` | 有 Monitor 处于 down 状态 | MON 进程停止、主机宕机、网络中断 | 检查 MON 主机与进程;重启 `ceph-mon@{id}`;检查 quorum 是否仍为多数派 |
| `MON_CLOCK_SKEW` | MON 之间时钟偏移过大 | 未配置 NTP/PTP 或时间源质量差 | 在所有 MON 主机部署 NTP/PTP;调整 `mon_clock_drift_allowed`(与 `mon_lease` 相关) |
| `MON_MSGR2_NOT_ENABLED` | MON 未启用 msgr2(v2 协议,端口 3300) | 老集群沿用 v1(6789) | 执行 `ceph mon enable-msgr2`;随后更新 `mon_host` 写法(见第十八章) |
| `MON_DISK_LOW` | MON 数据盘可用空间低于告警线 | MON store(RocksDB)增长、分区太小 | 清理空间;调 `mon_data_avail_warn`(默认 30%);必要时 compact |
| `MON_DISK_CRIT` | MON 数据盘可用空间极低(严重) | 同上,更严重 | 立即扩容/清理;`mon_data_avail_crit` 默认 5% |
| `MON_DISK_BIG` | MON store 体积过大 | 长期未做 compaction | 对 MON 执行 compact;`mon_data_size_warn` 默认 15 GiB |
| `MON_NETSPLIT` | 检测到 MON 之间网络分裂(netsplit) | 网络分区;使用 connectivity 选举策略时更易暴露 | 修复网络;`mon_netsplit_grace_period` 默认 9 秒;可按 location-level 或 individual 维度上报 |
### 7.2 Auth / CephX 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `AUTH_INSECURE_GLOBAL_ID_RECLAIM` | 全局 ID 回收机制处于不安全模式 | 老版本遗留的行为 | 按官方升级流程收紧 reclaim 策略;具体方法文档未明确 |
| `AUTH_INSECURE_GLOBAL_ID_RECLAIM_ALLOWED` | 允许不安全的 global id reclaim | 配置允许旧行为 | 关闭该允许项(文档未给出具体命令) |
| `AUTH_INSECURE_KEYS_CREATABLE` | 当前允许创建不安全(旧 cipher)密钥 | `auth_allowed_ciphers` 含 `aes` 时,`mon_auth_allow_insecure_key` 运行时默认被改为 true | `ceph config set mon 'mon auth allow insecure key' false`;或在 `auth_allowed_ciphers` 中移除旧 cipher 后自动清除(默认 `mon_auth_allow_insecure_key` 为 false) |
| `AUTH_INSECURE_SERVICE_TICKETS` | 服务票据使用的 cipher 不安全 | `auth_service_cipher` 仍为 `aes` | `ceph mon set auth_service_cipher aes256k`,等待票据 TTL(默认 3600.000000 秒)到期自动刷新 |
| `AUTH_INSECURE_SERVICE_KEY_TYPE` | 服务守护进程(mon/mgr/osd/mds)密钥仍为旧 cipher | 未轮转密钥 | `ceph auth rotate --key-type=aes256k {TYPE}.{ID}`,重启/导入 keyring |
| `AUTH_INSECURE_ROTATING_SERVICE_KEY_TYPE` | 轮转中的服务密钥仍含旧 cipher | 轮转密钥数据库未刷新 | 等待默认 TTL 自然过期;或 `ceph auth wipe-rotating-service-keys`(不推荐,确认所有 daemon 已升级后再做);系统保留 3 把轮转 key |
| `AUTH_INSECURE_CLIENT_KEY_TYPE` | 客户端实体使用了不安全 cipher | 客户端密钥未轮转 | `ceph auth rotate --key-type=aes256k client.$ID` 并分发;短期内可用 `ceph health mute AUTH_INSECURE_CLIENT_KEY_TYPE 8w` 静默 |
| `AUTH_INSECURE_KEYS_ALLOWED` | 集群仍允许用不安全 cipher 认证 | `auth_allowed_ciphers` 仍包含 `aes` | `ceph mon set auth_allowed_ciphers aes256k`(**务必**先确认 `AUTH_INSECURE_CLIENT_KEY_TYPE` 与 `AUTH_INSECURE_SERVICE_KEY_TYPE` 已清除) |
| `AUTH_EMERGENCY_CIPHERS_SET` | 设置了应急 cipher(救援模式) | 密钥升级失败后用 `mon_auth_emergency_allowed_ciphers` 救急 | 完成密钥修复后清除该配置,仅临时使用 |
| `AUTH_BAD_CAPS` | 某个实体的 capability 配置不合法 | cap 语法错误或引用了不存在的 pool/profile | `ceph auth get {entity}` 检查并修正 cap |
### 7.3 Manager 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `MGR_DOWN` | 有 MGR 处于 down(或无 active MGR) | MGR 进程崩溃/未部署 | 检查 `ceph -s` 的 `mgr` 行;部署/重启 MGR;`ceph mgr fail` 可强制切主 |
| `MGR_MODULE_DEPENDENCY` | 某个 module 的依赖未满足(如缺少 python 包) | 模块启用但依赖缺失 | 按提示安装依赖或禁用该模块;`ceph mgr module ls` 查看 |
| `MGR_MODULE_ERROR` | 模块运行出错 | 模块异常/配置错误 | `ceph tell mgr mgr_status` 查看详情;`ceph mgr fail` 重启 MGR;必要时 `ceph mgr module disable {module}` |
> 💡 补充:文档中 `pending_modules` 用于表达 module 的待启用/待应用状态,用于 `MGR_MODULE_*` 类告警的排查上下文。
### 7.4 OSD 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `OSD_DOWN` | 有 OSD 处于 down 状态 | 进程停止、主机宕机、磁盘故障、网络问题 | 检查主机与进程;`systemctl start ceph-osd@{id}`;查 `/var/log/ceph/ceph-osd.{id}.log` |
| `OSD_<crush type>_DOWN` | 某个 CRUSH bucket 下的 OSD 大面积 down(如 `OSD_HOST_DOWN`) | 整机/机柜/机架故障 | 按故障域排查;配合 `mon_osd_min_in_ratio` 避免被自动 mark out |
| `OSD_ORPHAN` | CRUSH 中残留了已不存在的 OSD 条目 | OSD 已删除但 CRUSH 未清理 | `ceph osd crush rm {name}` |
| `OSD_OUT_OF_ORDER_FULL` | nearfull / backfillfull / full 的比例设置顺序不合法 | 手工设置比例时大小关系颠倒 | 用 `ceph osd set-nearfull-ratio` / `set-backfillfull-ratio` / `set-full-ratio` 按正确顺序重设 |
| `OSD_FULL` | 有 OSD 达到 full ratio,禁止写入 | 容量耗尽;也可能是 `rados bench` 残留数据占满 | 扩容或清理;调 `ceph osd set-full-ratio`;删除 bench 残留对象 |
| `OSD_BACKFILLFULL` | OSD 已达 backfillfull ratio,不再接受回填 | 容量接近 full | 扩容/均衡;调整 backfillfull 比例 |
| `OSD_NEARFULL` | OSD 接近 full | 容量水位较高 | 提前扩容;检查 CRUSH 权重是否合理 |
| `OSDMAP_FLAGS` | OSDMap 上被人设置了 flag | 人工 `ceph osd set <flag>` | 确认不再需要后 `ceph osd unset <flag>`(flag 详见第四章 4.6) |
| `OSD_FLAGS` | 针对具体目标的 flag(如 `osd.0`、`host-foo`、`class-hdd`) | `ceph osd set-group` | 用对应的 `unset-group` 清除 |
| `OLD_CRUSH_TUNABLES` | CRUSH tunables 过旧 | 老集群未升级 tunables | `ceph osd crush tunables optimal`(具体升级路径文档未明确) |
| `OLD_CRUSH_STRAW_CALC_VERSION` | straw 算法版本过旧 | 同上 | 升级 CRUSH tunables;相关配置 `mon_warn_on_crush_straw_calc_version_zero` |
| `CACHE_POOL_NO_HIT_SET` | 缓存池未配置 hit set | cache tier 缺 `hit_set_*` 配置 | 配置 `hit_set_type` / `hit_set_count` / `hit_set_period`(见第十章) |
| `OSD_NO_SORTBITWISE` | OSD 未启用 sortbitwise | 极老集群遗留 | 历史遗留告警;新版本默认开启(文档未给出处理步骤) |
| `OSD_FILESTORE` | 仍在使用 Filestore 后端 | 老 OSD 未迁移 | 迁移到 BlueStore(见第十二章)。注意:Reef 起不支持 Filestore;mClock 不支持 Filestore,会强制 `osd_op_queue=wpq` |
| `OSD_UNREACHABLE` | OSD 不可达 | 网络中断但 OSD 进程仍在 | 排查网络;检查 blocklist |
| `POOL_FULL` | 池达到配额/容量上限 | 配额写满或底层 OSD 满 | 调大配额或清理数据;`mon_pool_quota_crit_threshold` 相关 |
### 7.5 BlueStore / BlueFS 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `BLUEFS_SPILLOVER` | RocksDB 数据溢出到慢设备(spillover) | DB/WAL 分区容量不足 | 扩容 block.db(推荐),或调小 `bluestore_rocksdb_options` 中的 level 大小(文档未给出具体值) |
| `BLUEFS_AVAILABLE_SPACE` | 报告 BlueFS 可用空间 | 例行上报 | 关注 `BDEV_DB free` / `BDEV_SLOW free` / `available_from_bluestore` 三个数值 |
| `BLUEFS_LOW_SPACE` | BlueFS 可用空间低 | DB 设备将满 | 扩容 block.db 或迁移元数据 |
| `BLUESTORE_FRAGMENTATION` | 空闲空间碎片化 | 长期随机写后 allocator 碎片 | 关注 `[0-1]` 的分级(0.0-0.4 / 0.4-0.7 / 0.7-0.9 / 0.9-1.0);严重时需要重建 OSD |
| `BLUESTORE_LEGACY_STATFS` | 使用了老式 statfs 统计口径 | 老 OSD 遗留 | 文档未明确处理步骤(通常随重建 OSD 消除) |
| `BLUESTORE_NO_PER_POOL_OMAP` | 不支持 per-pool omap 统计 | OSD 版本/格式老 | 重建 OSD |
| `BLUESTORE_NO_PER_PG_OMAP` | 不支持 per-PG omap 统计 | 同上 | 重建 OSD |
| `BLUESTORE_DISK_SIZE_MISMATCH` | 磁盘实际大小与记录不一致 | 底层设备被更换/扩容但元数据未更新 | 核对设备与 OSD 元数据(文档未给出具体命令) |
| `BLUESTORE_NO_COMPRESSION` | 请求压缩但设备/配置不支持 | 压缩配置与设备不匹配 | 检查 `bluestore_compression_*` 配置与设备能力 |
| `BLUESTORE_SPURIOUS_READ_ERRORS` | 检测到偶发读错误 | 磁盘/固件问题 | 检查磁盘 SMART;考虑换盘 |
| `BLOCK_DEVICE_STALLED_READ_ALERT` | 主块设备出现读停滞 | 设备响应极慢 | 换盘;阈值由 `bdev_stalled_read_warn_lifetime` / `bdev_stalled_read_warn_threshold` 控制 |
| `WAL_DEVICE_STALLED_READ_ALERT` | WAL 设备读停滞 | 同上 | 同上 |
| `DB_DEVICE_STALLED_READ_ALERT` | DB 设备读停滞 | 同上 | 同上 |
| `BLUESTORE_SLOW_OP_ALERT` | BlueStore 层慢操作 | 设备延迟高 | `bluestore_slow_ops_warn_lifetime` 默认 300 秒、`bluestore_slow_ops_warn_threshold` 默认 5 |
### 7.6 设备健康类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `DEVICE_HEALTH` | 设备健康度低于阈值 | SMART 指标劣化 | 查看 `ceph device info {devid}`;必要时换盘;阈值 `mgr/devicehealth/warn_threshold` |
| `DEVICE_HEALTH_IN_USE` | 不健康设备正在被 OSD 使用 | 该设备上还有 OSD | 迁移/替换 OSD 后换盘 |
| `DEVICE_HEALTH_TOOMANY` | 不健康设备太多,自动 mark out 被抑制 | 同时坏的设备超过 `mon_osd_min_in_ratio` 允许范围 | 人工介入,逐个更换;`mon_osd_min_in_ratio` 默认 0.75 |
### 7.7 PG / Pool 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `PG_AVAILABILITY` | PG 可用性下降(有 PG 不可读/不可写) | OSD down 导致 PG 不可用 | 恢复 OSD;检查 `ceph pg dump_stuck inactive` |
| `PG_DEGRADED` | 副本数不足(降级) | OSD down / 正在恢复 | 等待 recovery;恢复 down 的 OSD;严重时用 `ceph pg {pgid} mark_unfound_lost` |
| `PG_RECOVERY_FULL` | recovery 因目标 OSD 满而受阻 | 容量不足 | 扩容或清理;调整 full ratio |
| `PG_BACKFILL_FULL` | backfill 因目标 OSD 满而受阻 | 容量不足 | 同上 |
| `PG_DAMAGED` | PG 数据损坏(scrub 发现不一致) | 磁盘/软件错误 | `ceph health detail` 查看;`ceph pg repair {pgid}`;必要时人工比对副本 |
| `OSD_SCRUB_ERRORS` | scrub 发现错误 | 数据不一致 | `ceph health detail` 定位 PG,然后 `ceph pg repair {pgid}` |
| `OSD_TOO_MANY_REPAIRS` | 单 OSD 修复次数过多 | 反复出现不一致 | `mon_osd_warn_num_repaired` 默认 10;排查硬件;用 `clear_shards_repaired` 清零计数 |
| `LARGE_OMAP_OBJECTS` | 存在超大 OMAP 对象 | RGW 索引分片过大等 | 调整应用侧分片;阈值 `osd_deep_scrub_large_omap_object_key_threshold` 与 `osd_deep_scrub_large_omap_object_value_sum_threshold` |
| `CACHE_POOL_NEAR_FULL` | 缓存层接近写满 | hit set / 目标容量配置不当 | 调整 `target_max_bytes` 等(见第十章) |
| `TOO_FEW_PGS` | 集群 PG 总数偏少 | 池的 `pg_num` 设置过小 | 增大 `pg_num`;`mon_pg_warn_min_per_osd` 控制告警阈值 |
| `POOL_PG_NUM_NOT_POWER_OF_TWO` | 池的 `pg_num` 不是 2 的幂 | 手工设置 | 调整为 2 的幂 |
| `POOL_TOO_FEW_PGS` | 单个池的 PG 太少 | `pg_num` 过小 | 增大 `pg_num` |
| `TOO_MANY_PGS` | 集群 PG 总数过多 | 池太多或 `pg_num` 过大 | 减少 PG;`mon_max_pg_per_osd` 控制阈值 |
| `POOL_TOO_MANY_PGS` | 单个池 PG 过多 | `pg_num` 过大 | 调小 `pg_num` |
| `POOL_TARGET_SIZE_BYTES_OVERCOMMITTED` | 池的 `target_size_bytes` 总量超出集群容量 | 多池目标容量之和超出 | 调整 `target_size_bytes` 或扩容 |
| `POOL_HAS_TARGET_SIZE_BYTES_AND_RATIO` | 同时设置了 `target_size_bytes` 与 `target_size_ratio` | 两种口径冲突 | 二选一 |
| `TOO_FEW_OSDS` | OSD 数量少于池副本数要求 | `osd_pool_default_size` 大于实际 OSD 数 | 增加 OSD 或降低副本数 |
| `SMALLER_PGP_NUM` | `pgp_num` 小于 `pg_num` | 扩容 PG 后未同步 `pgp_num` | `ceph osd pool set {pool} pgp_num {n}` |
| `MANY_OBJECTS_PER_PG` | 单个 PG 对象数过多(分布不均) | 数据倾斜 | 检查 pool/对象命名;`mon_pg_warn_max_object_skew` 控制阈值 |
| `POOL_APP_NOT_ENABLED` | 池未声明 application | 新建池未 enable app | `ceph osd pool application enable {pool} {rbd\|rgw\|cephfs}` |
| `POOL_FULL` | 池达到配额上限 | 配额用尽 | 调配额或清理;`mon_pool_quota_crit_threshold` |
| `POOL_NEAR_FULL` | 池接近配额上限 | 配额将满 | 提前扩容;`mon_pool_quota_warn_threshold` |
| `OBJECT_MISPLACED` | 有对象不在 CRUSH 计算出的目标位置 | 正在迁移/恢复 | 等待 balancer/recovery 完成 |
| `OBJECT_UNFOUND` | 有对象找不到任何副本 | 副本全丢 | `ceph pg {pgid} mark_unfound_lost revert` 或 `delete`(后者会丢数据) |
| `SLOW_OPS` | 存在慢请求 | 磁盘/网络/锁竞争 | `ceph daemon osd.N ops` 与 `dump_historic_ops` 查看;`ceph osd find N` 定位主机 |
| `PG_NOT_SCRUBBED` | PG 长时间未做 light scrub | scrub 被抑制或调度不均 | 检查 `osd_scrub_max_interval`;`mon_warn_pg_not_scrubbed_ratio` 控制告警比例 |
| `PG_NOT_DEEP_SCRUBBED` | PG 长时间未做 deep scrub | 同上 | 检查 `osd_deep_scrub_interval`(示例值 1209600 秒)。**两种改法**:① 在 `global` 段设置;② 在 `osd` + `mgr` 段同时设置 |
| `PG_SLOW_SNAP_TRIMMING` | 快照裁剪队列积压 | 快照过多/裁剪慢 | 查看 `snaptrimq_len`;`mon_osd_snap_trim_queue_warn_on` 默认 32768 |
### 7.8 Stretch mode 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `INCORRECT_NUM_BUCKETS_STRETCH_MODE` | stretch 模式下 bucket 数量不正确 | CRUSH 中该层级的 bucket 数不是 2 | 修正 CRUSH,使该层级恰好 2 个 bucket(见第十一章) |
| `STRETCH_MODE_BUCKET_WEIGHT_IMBALANCE` | 两个站点权重不均衡 | 站点容量/权重差异过大 | 调整权重;`mon_stretch_max_bucket_weight_delta` 默认 0.1 |
| `NONEXISTENT_MON_CRUSH_LOC_STRETCH_MODE` | MON 的 CRUSH location 不存在 | 未给 MON 设置 `set_location`,或 location 与 CRUSH 不符 | `ceph mon set_location {mon-id} datacenter={dc}` |
### 7.9 NVMeoF 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `NVMEOF_SINGLE_GATEWAY` | NVMeoF 只有单个 gateway(无冗余) | 只部署了一个 gateway | 部署多个 gateway 实现 HA |
| `NVMEOF_GATEWAY_DOWN` | NVMeoF gateway 处于 down | gateway 进程/主机故障 | 检查 gateway 服务与主机 |
| `NVMEOF_GATEWAY_DELETING` | gateway 正在被删除 | 删除流程进行中 | 等待删除完成;若卡住则需人工干预(文档未给出具体命令) |
### 7.10 Misc 类
| 告警码 | 含义 | 触发原因 | 处理步骤 |
|---|---|---|---|
| `RECENT_CRASH` | 近期有守护进程崩溃 | OSD/MON/MGR 等崩溃 | `ceph crash ls-new` / `crash info {id}` 查看;确认后 `ceph crash archive {id}` 或 `ceph crash archive-all` |
| `RECENT_MGR_MODULE_CRASH` | 近期有 MGR module 崩溃 | module 异常 | 同上,用 `ceph crash` 系列命令处理;`mgr/crash/warn_recent_interval` 默认两周 |
| `TELEMETRY_CHANGED` | telemetry 配置被改动 | 开启/关闭了 telemetry | `ceph telemetry show` 确认;用 `ceph telemetry on` / `off` 明确表态 |
| `OSD_NO_DOWN_OUT_INTERVAL` | `mon_osd_down_out_interval` 被设为 0 | 人为关闭自动 mark out | 设为合理值(默认 600);或确认有意为之并配置 `mon_warn_on_osd_down_out_interval_zero` |
| `DASHBOARD_DEBUG` | Dashboard 处于 debug 模式 | 开启了 dashboard debug | `ceph dashboard debug disable` |
> 引自:[Health checks](https://docs.ceph.com/en/tentacle/rados/operations/health-checks/)
---
## 八、用户与认证(User Management + CephX)
### 8.1 基本概念
Ceph 的"用户"既可以是人,也可以是系统角色(例如应用、守护进程)。启用认证后(默认启用),每个用户必须指定**用户名**与**密钥(keyring)**。
- 不指定用户名时,默认使用 `client.admin`;
- 不指定 keyring 时,Ceph 按 `keyring` 配置查找,默认 `/etc/ceph/ceph.client.admin.keyring`。
也就是说:
```bash
ceph health
```
等价于:
```bash
ceph -n client.admin --keyring=/etc/ceph/ceph.client.admin.keyring health
```
也可以用 `CEPH_ARGS` 环境变量避免每次重复输入。
### 8.2 用户标识 `TYPE.ID`
- 用户类型(type):用户管理场景下**永远是 `client`**;Cephx 协议本身也被 `mon`/`osd`/`mds` 等非客户端实体使用,因此需要区分类型。
- 完整形式:`client.admin`、`client.user1`、`osd.0`。
- 命令行差异:
- 用 `--user` / `--id` 时**可以省略类型**(写 `admin`);
- 用 `--name` / `-n` 时**必须带类型**(写 `client.admin`)。
- 官方建议:**始终写全类型和名字**。
> 注意:Ceph 存储集群用户 ≠ Ceph 对象存储(RGW)用户 ≠ CephFS 用户。RGW 与 CephFS 各有自己的用户体系。
### 8.3 Capability(caps)语法
通用形式:
```text
{daemon-type} '{cap-spec}[, {cap-spec} ...]'
```
**Monitor caps**
```text
mon 'allow {access-spec} [network {network/prefix}]'
mon 'profile {name}'
```
**OSD caps**
```text
osd 'allow {access-spec} [{match-spec}] [network {network/prefix}]'
osd 'profile {name} [pool={pool-name}] [namespace={namespace-name}] [network {network/prefix}]'
```
**Manager caps**
```text
mgr 'allow {access-spec} [network {network/prefix}]'
mgr 'profile {name} [{key1} {match-type} {value1} ...] [network {network/prefix}]'
mgr 'allow command "{command-prefix}" [with {key1} {match-type} {value1} ...] [network {network/prefix}]'
mgr 'allow service {service-name} {access-spec} [network {network/prefix}]'
mgr 'allow module {module-name} [with {key1} {match-type} {value1} ...] {access-spec} [network {network/prefix}]'
```
**Metadata Server caps**:管理员用 `allow *`;CephFS 客户端请参照 CephFS 的 client-auth 文档。
其中:
| 元素 | 取值 |
|---|---|
| `{access-spec}`(mon/mgr) | `*` \| `all` \| `[r][w][x]` |
| `{access-spec}`(osd) | `* \| all \| [r][w][x] [class-read] [class-write]` 或 `class {class name} [{method name}]` |
| `{match-spec}`(osd,四选一) | `pool={pool-name} [namespace={ns}] [object_prefix {prefix}]`;`[pool=...] namespace={ns} [object_prefix {prefix}]`;`[pool=...] [namespace=...] object_prefix {prefix}`;`[namespace=...] tag {application} {key}={value}` |
| `{service-name}` | `mgr` \| `osd` \| `pg` \| `py` |
| `{match-type}` | `=` \| `prefix` \| `regex` |
| `{network/prefix}` | CIDR,例如 `10.3.0.0/16`;带此限制时只有从该网段连入的客户端能用该 cap |
### 8.4 访问权限位(rwx)含义
| 权限 | 含义 |
|---|---|
| `allow` | 引导后续权限设置;**仅对 MDS 而言隐含 `rw`** |
| `r` | 读权限。对 MON 而言,要获取 CRUSH map 就必须有 `r` |
| `w` | 对对象的写权限 |
| `x` | 允许调用 class 方法(含读写),以及在 MON 上执行 `auth` 操作 |
| `class-read` | 允许调用 class 的读方法,是 `x` 的子集 |
| `class-write` | 允许调用 class 的写方法,是 `x` 的子集 |
| `*`、`all` | 对指定 daemon/pool 拥有 rwx,且可执行 admin 命令 |
### 8.5 预定义 profile
| profile | 适用 daemon | 含义 |
|---|---|---|
| `osd` | MON | 允许作为 OSD 连接其他 OSD/MON,处理复制心跳与状态上报 |
| `mds` | MON | 允许作为 MDS 连接其他 MDS/MON |
| `bootstrap-osd` | MON | 允许引导 OSD,供 `ceph-volume` / `cephadm` 使用 |
| `bootstrap-mds` | MON | 允许引导 MDS,供 `cephadm` 使用 |
| `bootstrap-rbd` | MON | 允许引导 RBD 用户 |
| `bootstrap-rbd-mirror` | MON | 允许引导 `rbd-mirror` 守护进程用户 |
| `rbd` | MGR、MON、OSD | 操作 RBD 镜像。作 MON cap 时提供 RBD 客户端所需最小权限(含 blocklist 其他 client 的能力);作 OSD cap 时提供指定池的读写。MGR cap 支持 `pool` / `namespace` 可选参数 |
| `rbd-mirror` | MON | 操作 RBD 镜像并读取 RBD mirroring 的 config-key secret |
| `rbd-read-only` | MGR、OSD | RBD 只读;MGR cap 支持 `pool` / `namespace` |
| `simple-rados-client` | MON | 对 mon/osd/pg 数据只读,供 librados 应用使用 |
| `simple-rados-client-with-blocklist` | MON | 同上,另含添加 blocklist 条目的权限,用于构建 HA 应用 |
| `fs-client` | MON | 对 mon/osd/pg/mds 数据只读,供 CephFS 客户端使用 |
| `role-definer` | MON、Auth | 对 auth 子系统拥有**全部**权限 + MON 只读。**除非非常清楚后果,否则不要分配** |
| `crash` | MON、MGR | MON 只读,配合 `crash` 模块上传崩溃转储 |
> ⚠️ 重要:如果执行 `ceph auth caps client.admin mgr 'allow*'`,会**去掉** `client.admin` 的必要能力。修复方式(在 `/var/lib/ceph/mon/<monitor_name>` 目录下执行):
```bash
ceph -n mon. --keyring keyring auth caps client.admin mds 'allow *' osd 'allow *' mon 'allow *'
```
### 8.6 Pool / Application Tag / Namespace
- **Pool**:数据的逻辑分区;用户权限常按池收敛。
- **Application Tag**:可按池的 application 元数据限定访问;`key`、`value` 均可用 `*`,`all` 等于 `*`。
- **Namespace**:池内的逻辑对象分组。**只对 librados 有效**。权限可用 `namespace=` 限定,支持有限通配:若指定值的最后一个字符是 `*`,则授予所有以该前缀开头的 namespace 的访问权。
> 为什么用 namespace:一个池通常每个 OSD 承载约 100 个 PG 副本;1000 OSD × 3 副本池 ⇒ 单池约 100,000 个 PG 副本 ⇒ 33,333 个 PG。相比为每个用户建池(计算代价高),把对象写进 namespace 只是给对象名加前缀,代价低得多。
### 8.7 用户管理命令
```bash
ceph auth ls # 列出所有用户
ceph auth ls -o {filename} # 输出到文件
ceph auth get {TYPE.ID} # 查看单个用户
ceph auth export {TYPE.ID} # 与 get 相同(给开发者用)
```
`ceph auth ls` 输出示例:
```text
installed auth entries:
osd.0
key: AQCvCbtToC6MDhAATtuT70Sl+DymPCfDSsyV4w==
caps: [mon] allow profile osd
caps: [osd] allow *
client.admin
key: AQBHCbtT6APDHhAA5W00cBchwkQjh3dkKsyPjw==
caps: [mds] allow
caps: [mon] allow *
caps: [osd] allow *
```
**三种创建方式**
| 命令 | 特点 |
|---|---|
| `ceph auth add` | 规范做法:创建用户 + 生成 key + 赋予指定 cap |
| `ceph auth get-or-create` | 最方便:返回带用户名(方括号)与 key 的 keyfile 格式;用户已存在则直接返回 |
| `ceph auth get-or-create-key` | 只返回 key(适合 libvirt 这类只需要 key 的客户端) |
```bash
ceph auth add client.john mon 'allow r' osd 'allow rw pool=liverpool'
ceph auth get-or-create client.paul mon 'allow r' osd 'allow rw pool=liverpool'
ceph auth get-or-create client.george mon 'allow r' osd 'allow rw pool=liverpool' -o george.keyring
ceph auth get-or-create-key client.ringo mon 'allow r' osd 'allow rw pool=liverpool' -o ringo.key
```
> ⚠️ **任何在 OSD 上有权限的用户,默认能访问集群里的所有池**,除非显式限定到池的子集。
**修改 caps**(注意:新 caps 会**覆盖**旧 caps,新增时要把原有 cap 一并写上)
```bash
ceph auth get client.john
ceph auth caps client.john mon 'allow r' osd 'allow rw pool=liverpool'
ceph auth caps client.paul mon 'allow rw' osd 'allow rwx pool=liverpool'
ceph auth caps client.brian-manager mon 'allow *' osd 'allow *'
```
**删除 / 打印 key / 导入**
```bash
ceph auth del {TYPE}.{ID}
ceph auth print-key {TYPE}.{ID}
ceph auth import -i /path/to/keyring
```
典型用法(libvirt 挂载时内联 key):
```bash
mount -t ceph serverhost:/ mountpoint -o name=client.user,secret=`ceph auth print-key client.user`
```
### 8.8 Keyring 管理
Ceph 预设了 4 个默认 keyring 搜索名(通常无需在 `ceph.conf` 里改):
```text
/etc/ceph/$cluster.$name.keyring
/etc/ceph/$cluster.keyring
/etc/ceph/keyring
/etc/ceph/keyring.bin
```
| 元变量 | 展开结果 | 示例 |
|---|---|---|
| `$cluster` | 集群名(默认 `ceph`) | `ceph.keyring` |
| `$name` | `$type.$id` | `ceph.client.admin.keyring` |
**创建空 keyring**
```bash
ceph-authtool --create-keyring /path/to/keyring # 或 -C
sudo ceph-authtool -C /etc/ceph/ceph.keyring
```
多用户 keyring 建议命名为 `$cluster.keyring` 放在 `/etc/ceph`;单用户 keyring 建议 `$cluster.$type.$id.keyring`(如 `ceph.client.admin.keyring`)。在 `/etc/ceph` 下创建需要 root,创建后记得用 `chown`/`chmod` 调整属主与权限。
**把用户加入 keyring**
```bash
sudo ceph auth get client.admin -o /etc/ceph/ceph.client.admin.keyring
sudo ceph-authtool /etc/ceph/ceph.keyring --import-keyring /etc/ceph/ceph.client.admin.keyring
```
**直接在客户端 keyring 上创建用户,再导入集群**
```bash
sudo ceph-authtool -n client.ringo --cap osd 'allow rwx' --cap mon 'allow rwx' /etc/ceph/ceph.keyring
# 一步到位:建 keyring + 加用户 + 生成 key
sudo ceph-authtool -C /etc/ceph/ceph.keyring -n client.ringo --cap osd 'allow rwx' --cap mon 'allow rwx' --gen-key
# 此时 client.ringo 只在本地 keyring,还需导入集群
sudo ceph auth add client.ringo -i /etc/ceph/ceph.keyring
```
**修改 keyring 中的用户并同步到集群**
```bash
sudo ceph-authtool /etc/ceph/ceph.keyring -n client.ringo --cap osd 'allow rwx' --cap mon 'allow rwx'
sudo ceph auth import -i /etc/ceph/ceph.keyring
```
### 8.9 密钥轮转
```bash
ceph auth rotate <entity>
```
好处:密钥泄露/丢失/定期轮换时,无需删除并重建实体。
### 8.10 命令行用法
| 选项 | 说明 |
|---|---|
| `--id` / `--user` | 只给 ID 部分,省略 type:`ceph --id foo --keyring /path/to/keyring health` |
| `--name` / `-n` | 完整用户名:`ceph -n client.foo --keyring /path/to/keyring health` |
| `--keyring` | keyring 路径。`--secret` 功能相同,但**不能用于 RADOS Gateway**(RGW 的 `--secret` 另有含义) |
### 8.11 cephx 的局限(官方明确)
- cephx 只做**客户端与服务器的互相认证**,不用于认证人类用户或其代理程序;需要的话要用前端层的额外机制。
- 密钥以**明文文件**形式存放在可信主机上,必须设置恰当的文件权限。
- **便携设备/用户机器不应直接访问 Ceph**,否则等于把明文密钥放在不安全设备上;应让用户先登录可信机器再访问。
- 目前 **cephx 不提供传输加密**(窃听者能读取全部数据,只是不能篡改);Ceph 也不提供对象存储加密。敏感数据应在写入前自行加密。
### 8.12 CephX 配置参考
**启用 / 禁用**
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `auth_cluster_required` | 文档未明确 | `cephx`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 集群内部(daemon↔daemon)认证方式 | 启用时设为 `cephx`,禁用时 `none` |
| `auth_service_required` | 文档未明确 | `cephx`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端↔服务认证方式 | 同上 |
| `auth_client_required` | 文档未明确 | `cephx, none`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端认证方式 | 同上 |
```ini
[global]
auth_cluster_required = cephx
auth_service_required = cephx
auth_client_required = cephx
```
> ⚠️ 官方警告:禁用认证通常是非常糟糕的选择——任何人、任何来源都能访问集群。仅为排障临时关闭,随后务必恢复。
**手动启用 CephX 的完整流程**(集群此前禁用了认证时)
```bash
# 1) 创建 client.admin key
ceph auth get-or-create client.admin mon 'allow *' mds 'allow *' mgr 'allow *' osd 'allow *' -o /etc/ceph/ceph.client.admin.keyring
```
```bash
# 2) 创建 monitor keyring
ceph-authtool --create-keyring /tmp/ceph.mon.keyring --gen-key -n mon. --cap mon 'allow *'
# 3) 分发到每个 MON 的数据目录
cp /tmp/ceph.mon.keyring /var/lib/ceph/mon/ceph-a/keyring
```
```bash
# 4) 为每个 MGR 生成密钥({$id} 为 MGR 字母)
ceph auth get-or-create mgr.{$id} mon 'allow profile mgr' mds 'allow *' osd 'allow *' -o /var/lib/ceph/mgr/ceph-{$id}/keyring
# 5) 为每个 OSD 生成密钥({$id} 为 OSD 编号)
ceph auth get-or-create osd.{$id} mon 'allow rwx' osd 'allow *' -o /var/lib/ceph/osd/ceph-{$id}/keyring
# 6) 为每个 MDS 生成密钥({$id} 为 MDS 字母)
ceph auth get-or-create mds.{$id} mon 'allow rwx' osd 'allow *' mds 'allow *' mgr 'allow profile mds' -o /var/lib/ceph/mds/ceph-{$id}/keyring
```
然后在 `[global]` 中开启三项 `cephx` 并重启集群。
**密钥存放**
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `keyring` | 文档未明确 | 文档未明确 | keyring 文件路径 | 不推荐覆盖默认搜索路径 |
| `keyfile` | 文档未明确 | 文档未明确 | 指向单密钥文件 | 不推荐 |
| `key` | 文档未明确 | 文档未明确 | 直接在配置里写密钥 | **不推荐** |
守护进程的 keyring 默认位于其数据目录:
```text
/var/lib/ceph/$type/$cluster-$id
# 例如 osd.12 → /var/lib/ceph/osd/ceph-12
```
**签名(Signatures)**
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `cephx_require_signatures` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 是否要求 Ceph 消息签名 | 需要中间人防篡改时开启;注意**签名不等于加密** |
| `cephx_cluster_require_signatures` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 集群内部消息签名 | 同上 |
| `cephx_service_require_signatures` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端↔服务消息签名 | 同上 |
| `cephx_sign_messages` | 文档未明确 | true(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 会话是否签名 | 同上 |
**票据有效期**
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `auth_mon_ticket_ttl` | 文档未明确 | 72_hr(= 259200 秒)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | MON 票据有效期 | 文档未明确 |
| `auth_service_ticket_ttl` | 文档未明确 | 3600.000000 | 服务票据有效期(秒) | 与 `AUTH_INSECURE_SERVICE_TICKETS` 轮转相关,改小可加速收敛、改大会增加开销 |
**2026 密钥 cipher 升级流程(官方给出的多步方案)**
1. 允许新 cipher:确认 `ceph --format=json mon dump | jq -r '.auth_allowed_ciphers | map(.name) | join (",")'` 输出含 `aes256k`;没有则 `ceph mon set auth_allowed_ciphers aes,aes256k`。
2. 设置新 key 的默认 cipher:检查 `auth_preferred_cipher`,升级用 `ceph mon set auth_preferred_cipher aes256k`。
3. 轮转所有服务 daemon(mon、mgr、osd、mds)的 key:
```bash
ceph auth rotate --key-type=aes256k mon. | tee mon.keyring
systemctl restart ceph-mon@$ID
```
其他 daemon:先 `systemctl stop ceph-$TYPE@$ID`(OSD 还要 `ceph osd down $ID`),再 `ceph auth rotate --key-type=aes256k $TYPE.$ID`,然后
`ceph-authtool --import-keyring $COPIED_KEYRING /var/lib/ceph/$TYPE/ceph-$ID/keyring`,最后重启。
- ⚠️ 改 key 会让现有 daemon 无法重新认证;MON 轮转期间不在 quorum 的 MON 拿不到新 key,需要用保存的 `mon.keyring` 救回。
4. 确认 `AUTH_INSECURE_SERVICE_KEY_TYPE` 已清除。
5. 升级轮转服务密钥的 cipher:`ceph mon set auth_service_cipher aes256k`。
6. (可选、不推荐)`ceph auth wipe-rotating-service-keys` 立即清掉旧的轮转 key;通常让它按 TTL 自然过期。
7. 禁止再创建不安全 key:`ceph config set mon 'mon auth allow insecure key' false`(`mon_auth_allow_insecure_key` 默认 `false`,但当 `auth_allowed_ciphers` 含不安全 cipher 时,MON 会在运行时把默认值改为 `true`)。
8. 轮转 `client.admin`(先建 `client.admin-backup` 应急密钥,验证后再 `ceph auth rm client.admin-backup`)。
9. 轮转其他 client key;暂时无法轮转的可 `ceph health mute AUTH_INSECURE_CLIENT_KEY_TYPE 8w` 静默。
10. 最后 `ceph mon set auth_allowed_ciphers aes256k`,彻底禁用不安全 cipher。
**应急 cipher**
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_auth_emergency_allowed_ciphers` | 文档未明确 | 文档未明确 | 本地启动时临时允许的 cipher 列表,用于 rescue | 仅在密钥升级失败救急时临时设置;设置后集群会报 `AUTH_EMERGENCY_CIPHERS_SET` |
| `mon_auth_allow_insecure_key` | 文档未明确 | `false`(当允许不安全 cipher 认证时运行时变为 `true`) | 是否允许创建不安全 cipher 的 key | 升级完成后保持关闭 |
**其他有用命令**
```bash
# 轮转单个实体(输出即新 key)
ceph auth rotate client.fs | tee ./client.fs.keyring
ceph-authtool --import-keyring ./client.fs.keyring /etc/ceph/client.fs.keyring
# 导出全部密钥元数据(仅支持 json / json-pretty)
ceph --format=json-pretty auth dump-keys
```
`auth dump-keys` 输出中每个 secret 含 `key.type_str`(如 `aes`)、`created`、`caps`;`rotating_secrets` 部分含 `max_ver`(示例中为 3,即保留 3 把轮转 key)与各自 `expiration`。这是用于审计"是否还有不安全 cipher"的**底层 API**,caps 字段为二进制格式,不适于直接分析。
> 引自:[User Management](https://docs.ceph.com/en/tentacle/rados/operations/user-management/) / [CephX Config Reference](https://docs.ceph.com/en/tentacle/rados/configuration/auth-config-ref/)
---
## 九、数据均衡(Balancer)
均衡器(`balancer`)是 `ceph-mgr` 的一个模块,负责把 PG 在 OSD 间摊平。
### 9.1 基本状态与开关
```bash
ceph balancer status # 查看当前模式、是否启用、上次执行结果
ceph balancer on
ceph balancer off
```
- **默认模式**:`upmap`
- `off` 表示关闭自动均衡
### 9.2 四种模式
| 模式 | 机制 | 要求 / 限制 |
|---|---|---|
| `crush-compat` | 通过 CRUSH 的 **compat weight-set** 调整权重 | 向后兼容性最好;**不能处理 OSD 在多个层级间共享**的复杂拓扑 |
| `upmap` | 使用 `pg-upmap` 显式重映射 PG | 需要 Luminous 及以上客户端 |
| `read` | 使用 `pg-upmap-primary` 调整 primary,均衡**读**流量 | 需要 Reef 及以上 |
| `upmap-read` | 同时做 `upmap` 与 read 均衡 | 组合模式 |
```bash
ceph balancer mode crush-compat
ceph balancer mode read
ceph balancer mode upmap-read
```
### 9.3 节流(throttle)
| 配置项 / 参数 | 默认值 | 含义 |
|---|---|---|
| `target_max_misplaced_ratio` | 0.05(5%,文档中示例写作 `.03`) | 允许同时被"错位"的数据比例;超过则不再调整 |
| `upmap_max_deviation` | 5(2025-06 起,建议设为 1) | 允许的偏差;设为 1 更激进、更均匀 |
| `sleep_interval` | 文档未明确 | 两次均衡之间的间隔 |
| `begin_time` / `end_time` | `0000` / `2359`(HHMM 格式) | 允许均衡的时间窗 |
| `begin_weekday` / `end_weekday` | 0 = 周日 | 允许均衡的星期窗口 |
| `pool_ids` | 文档未明确 | 限定参与均衡的池 |
- 集群处于**降级状态**(有 degraded PG)时,balancer **不会**做调整。
设置示例:
```bash
ceph config set mgr mgr/balancer/upmap_max_deviation 1
ceph config set mgr mgr/balancer/target_max_misplaced_ratio .03
```
### 9.4 监督式(Supervised)三阶段
```bash
# 1) 评估当前分布
ceph balancer eval
ceph balancer eval-verbose
ceph balancer eval <plan>
# 2) 生成优化计划
ceph balancer optimize <plan>
ceph balancer show <plan>
ceph balancer ls
ceph balancer rm <plan>
# 3) 执行计划(执行进度需开启 update_pg_upmap_activity)
ceph config set mgr mgr/balancer/update_pg_upmap_activity True
ceph balancer status detail
ceph balancer execute <plan>
```
### 9.5 读均衡(Read Balancer)
读均衡通过调整 primary 分布来均衡读压力,用 `read_balance_score` 衡量:
- 评分 **> 1**(如 `1.5`)说明 primary 分布不均衡;
- 越接近 1 越均衡。
```bash
ceph balancer on
ceph balancer mode read # 或 upmap-read
```
客户端要求:
```bash
ceph osd set-require-min-compat-client reef
ceph features
```
**离线优化**(不打扰线上集群):
```bash
ceph osd getmap -o om
osdmaptool om --read out.txt --read-pool <pool> [--vstart]
source out.txt
```
调试级别:`--debug-osd 10` / `--debug-osd 20`。
**排障**
```bash
ceph osd rm-pg-upmap-primary <pgid>
ceph osd rm-pg-upmap-primary-all
```
> ⚠️ 已知限制(截至 2025-09-08):**内核客户端不支持 `pg-upmap-primary`**。若内核客户端不支持,dmesg 中会出现 feature set mismatch 相关报错,此时读均衡无法对内核挂载生效。
> 引自:[Balancer](https://docs.ceph.com/en/tentacle/rados/operations/balancer/) / [Read Balancer](https://docs.ceph.com/en/tentacle/rados/operations/read-balancer/)
---
## 十、缓存分层(Cache Tiering)
> ⚠️ **Reef 起已弃用(deprecated)**。下文内容主要用于理解既有集群,新集群不应再部署缓存分层。
### 10.1 原理
- **cache tier**(高速层,通常是 SSD)+ **backing tier**(低速层,通常是 HDD/EC 池)。
- 由 **objecter** 与 **tiering agent** 在后台完成对象的提升(promote)与刷写(flush)/驱逐(evict),**对客户端完全透明**。
### 10.2 模式
| 模式 | 行为 |
|---|---|
| `writeback` | 写先落 cache tier,之后异步 flush 到 backing;读未命中时从 backing 提升对象 |
| `readproxy` | 写直接落 backing;读时 cache 中若无则从 backing 代理读(不提升) |
| `readonly` | 只读缓存;**实验性**,需要加 `--yes-i-really-mean-it` |
| `none` | 关闭分层(用于下线缓存层) |
### 10.3 官方告诫
- **大多数工作负载反而会性能下降**;
- 难以做基准测试;
- 使用 librados 枚举对象时**不保证一致性**;
- 整体复杂度高。
**Known Good(适合用)**:RGW 的 time-skewed 工作负载。
**Known Bad(不要用)**:RBD + EC base tier;RBD + replicated base tier。
### 10.4 建池与创建缓存层
```bash
# 两个池:冷(backing)与热(cache)
ceph osd pool create cold-storage ...
ceph osd pool create hot-storage ...
```
```bash
# 1) 把 hot-storage 作为 cold-storage 的 tier
ceph osd tier add cold-storage hot-storage
# 2) 设置缓存模式
ceph osd tier cache-mode hot-storage writeback
# 3) 把 hot-storage 设为 overlay(客户端流量全部走 cache)
ceph osd tier set-overlay cold-storage hot-storage
```
### 10.5 关键配置
```bash
# hit set:用于判断"最近是否被访问过"
ceph osd pool set hot-storage hit_set_type bloom
ceph osd pool set hot-storage hit_set_count 12
ceph osd pool set hot-storage hit_set_period 14400
# 提升(promote)阈值
ceph osd pool set hot-storage min_read_recency_for_promote 2
ceph osd pool set hot-storage min_write_recency_for_promote 2
# 容量目标(绝对容量)
ceph osd pool set hot-storage target_max_bytes 1000000000000
```
| 配置项 | 示例值 | 含义 |
|---|---|---|
| `target_max_bytes` | `1099511627776`(1 TiB) | 缓存层目标最大字节数 |
| `target_max_objects` | `1000000` | 缓存层目标最大对象数 |
| `cache_target_dirty_ratio` | `0.4` | 脏数据达到该比例开始 flush |
| `cache_target_dirty_high_ratio` | `0.6` | 脏数据达到该比例进入高速 flush |
| `cache_target_full_ratio` | `0.8` | 达到该比例开始 evict |
| `cache_min_flush_age` | `600`(秒) | 对象在 cache 中至少停留多久才允许 flush |
| `cache_min_evict_age` | `1800`(秒) | 对象至少多久才允许被 evict |
> 容量可以按**绝对值**(上面的 `target_max_bytes` / `target_max_objects`)设置,也可以按**相对比例**(`cache_target_*_ratio`)设置。
### 10.6 移除缓存层
**readonly 模式**
```bash
ceph osd tier cache-mode hot-storage none
ceph osd tier remove cold-storage hot-storage
```
**writeback 模式**(必须先确保数据都刷回 backing)
```bash
# 1) 切到 proxy,让新写入直接落 backing
ceph osd tier cache-mode hot-storage proxy
# 2) 把缓存中的对象全部 flush + evict
rados -p hot-storage cache-flush-evict-all
# 3) 移除 overlay
ceph osd tier remove-overlay cold-storage
# 4) 移除 tier
ceph osd tier remove cold-storage hot-storage
```
### 10.7 已知问题
- **unfound objects**:在特定场景下,缓存层可能出现 unfound 对象,与 `hit_set_archive` 相关,见官方 Tracker #44286;受影响版本包括 `14.2.8`、`14.2.16`、`15.2.15`、`16.2.5`、`17.2.7`。
- 缓存层未配置 hit set 时会触发 `CACHE_POOL_NO_HIT_SET` 告警;接近写满时触发 `CACHE_POOL_NEAR_FULL`。
> 引自:[Cache Tiering](https://docs.ceph.com/en/tentacle/rados/operations/cache-tiering/)
---
## 十一、Stretch 集群模式
### 11.1 拓扑与前提
- 标准形态:**两个站点**(各承载数据副本)+ **一个 tiebreaker MON**(可以是虚拟机,放在第三处)。
- 「stretch pool」与「stretch mode」不是一回事:
- *stretch pool* 只是让两个站点各有数据副本;
- *stretch mode* 是集群级的运行模式,含特殊的 peering 规则与降级/恢复行为。
- **限制**:
- stretch pool 在 netsplit(网络分裂)期间 I/O 不可用;
- 超过 25% 的 OSD down 时,`mon_osd_min_in_ratio`(默认 0.75)会阻止把 OSD mark out,从而避免误判。相关 Tracker #68338。
- stretch mode **要求 MON 选举策略为 `connectivity`**。
### 11.2 Peering 规则
stretch mode 下 Ceph 采用特殊的 **stretch peering rule**,防止某个 PG 在**单个站点内部**变成 active(那样会破坏跨站点的冗余语义)。
### 11.3 进入 stretch mode 的步骤
```bash
# 1) 为每个 MON 设置 location(先给站点 1 的 MON)
ceph mon set_location a datacenter=site1
```
```bash
# 2) 取出 CRUSH map,反编译后添加 stretch_rule
ceph osd getcrushmap -o cm
crushtool -d cm -o cm.txt
# 编辑 cm.txt,加入形如:
# step take site1
# step chooseleaf firstn 2 type host
# step emit
# step take site2
# step chooseleaf firstn 2 type host
# step emit
crushtool -c cm.txt -o cm.new
ceph osd setcrushmap -i cm.new
```
```bash
# 3) 设置选举策略
ceph mon set election_strategy connectivity
# 4) 给 tiebreaker MON 设置第三处 location 并启用 stretch mode
ceph mon set_location e datacenter=site3
ceph mon enable_stretch_mode e stretch_rule datacenter
```
> ⚠️ 已知问题:CRUSH rule 中若出现**多个 `take` 步骤**,会导致 `ceph df` 的 **MAX AVAIL 计算错误**。变通办法是使用 `step take default` + `step choose firstn 0 type datacenter`(见 Tracker #56650)。
### 11.4 启用后的变化
| 项目 | 变化 |
|---|---|
| `size` | 3 → **4**(每个站点 2 个副本) |
| `min_size` | → **1** |
| 单站点故障 | 进入 **degraded stretch mode** |
| 恢复阶段 | 进入 **recovery stretch mode** |
### 11.5 退出 stretch mode
```bash
ceph mon disable_stretch_mode [{crush_rule}] --yes-i-really-mean-it
```
> ⚠️ 集群处于 **recovery stretch mode** 时**不能**执行该命令。
### 11.6 硬性限制
- **恰好**两个站点(datacenter);
- 每个站点 2 个 MON + 1 个 tiebreaker,共 5 个 MON;
- **不支持**纠删码(EC)池;
- **不支持** device class;
- 建议使用 SSD。
### 11.7 其他相关命令
```bash
ceph mon set_new_tiebreaker {mon-id}
ceph mon enable_stretch_mode ... --set-crush-location
ceph mon force_recovery_stretch_mode --yes-i-really-mean-it
ceph mon force_healthy_stretch_mode --yes-i-really-mean-it
```
> 引自:[Stretch Clusters / stretch mode](https://docs.ceph.com/en/tentacle/rados/operations/stretch-mode/)
---
## 十二、BlueStore 迁移
Filestore 自 **Reef** 起已不被支持,所有 Filestore OSD 都应迁移到 BlueStore。官方给出三种策略。
### 12.1 策略一:mark-out 替换(逐 OSD 替换,最常用)
```bash
# 1) 找出还在用 filestore 的 OSD
ceph osd metadata 1 | grep osd_objectstore
ceph osd count-metadata osd_objectstore
```
```bash
# 2) 把该 OSD 标记 out,等数据迁走
ceph osd out osd.N
while ! ceph osd safe-to-destroy osd.N ; do sleep 10 ; done
```
```bash
# 3) 停进程、卸载、清盘、销毁、重建
systemctl kill ceph-osd@N
umount /var/lib/ceph/osd/ceph-N
ceph-volume lvm zap /dev/{disk}
ceph osd destroy N --yes-i-really-mean-it
ceph-volume lvm create --bluestore --osd-id N --data /dev/{disk}
```
- **优点**:粒度最小,一次只影响一个 OSD,集群冲击小。
- **缺点**:耗时长(每个 OSD 都要经历一次完整的数据迁移)。
### 12.2 策略二:整机替换(whole host)
```bash
# 1) 新主机加入 CRUSH
ceph osd crush add-bucket {newhost} host
# 2) 把新主机挂到目标位置,旧主机摘掉
ceph osd crush unlink {oldhost}
```
在新主机上批量创建 OSD:
```bash
ceph-volume lvm create --bluestore --data /dev/{disk} # 对每个盘执行
```
然后用 `crush swap-bucket` 交换新旧 bucket,并清理旧 OSD:
```bash
ceph osd crush swap-bucket {oldhost} {newhost}
while ! ceph osd safe-to-destroy $(ceph osd ls-tree $OLDHOST) ; do sleep 10 ; done
for id in $(ceph osd ls-tree $OLDHOST); do ceph osd purge $id --yes-i-really-mean-it; done
ceph-volume lvm zap ... # 旧盘
```
- **优点**:比逐盘快很多,适合大规模替换。
- **缺点**:需要额外的空闲主机(或先把旧主机腾空)。
### 12.3 策略三:per-OSD 设备拷贝(原地转换)
```bash
# 前提:目标设备空闲、先关闭自动恢复
ceph osd set noout
ceph osd set norecover
ceph osd set norebalance
# 用 ceph-objectstore-tool 把数据从旧设备拷贝到新设备
ceph-objectstore-tool --data-path /var/lib/ceph/osd/ceph-N --target-data-path /var/lib/ceph/osd/ceph-N-new copy
```
- **限制**:需要一个空闲设备;**不支持 dmcrypt**;需要**手工分区**。
- **优点**:不需要数据在网络上重平衡,理论上最快。
- **缺点**:步骤最复杂、出错代价高。
> 💡 补充:三种策略的共同前置条件是——备份好 OSD 的 `keyring` 与 `fsid`,并在操作前确认 `ceph -s` 处于 `active+clean`;迁移期间务必保持 `noout` 等 flag,避免二次数据移动。
> 引自:[BlueStore Migration](https://docs.ceph.com/en/tentacle/rados/operations/bluestore-migration/)
---
## 十三、设备管理(Devices)
`ceph device` 系列命令由 `ceph-mgr` 的 `devicehealth` 模块提供,用于查看与预测物理设备健康。
### 13.1 查看设备
```bash
ceph device ls # 所有设备
ceph device ls-by-host {host} # 按主机
ceph device ls-by-daemon {daemon} # 按守护进程
ceph device info {devid} # 单个设备详情
```
### 13.2 点亮磁盘 LED(定位故障盘)
```bash
ceph device light on {devid} [ident|fault] [--force]
ceph device light off {devid} [ident|fault] [--force]
```
- 需要 **cephadm 或 Rook** 编排器支持;
- 底层需要 `lsmcli`;
- 命令模板可通过 `mgr/cephadm/blink_device_light_cmd` 配置(Jinja2 模板),模板变量包括 `on`、`ident_fault`、`dev`、`path`。
### 13.3 健康监控开关与采集
```bash
ceph device monitoring on
ceph device monitoring off
```
| 配置项 | 默认值 | 含义 |
|---|---|---|
| `mgr/devicehealth/scrape_frequency` | 24 小时 | SMART 等指标采集周期 |
```bash
ceph device scrape-health-metrics {devid}
ceph device scrape-daemon-health-metrics {daemon}
ceph device get-health-metrics {devid}
```
### 13.4 故障预测
| 模式 | 说明 |
|---|---|
| `none` | 关闭预测 |
| `local` | 使用本地预测模型 |
```bash
ceph config set global device_failure_prediction_mode <mode>
ceph device predict-life-expectancy {devid}
ceph device set-life-expectancy {devid} {date}
```
### 13.5 健康告警与自动迁移
| 配置项 | 默认值 | 含义 |
|---|---|---|
| `mgr/devicehealth/warn_threshold` | 文档未明确 | 健康度告警阈值 |
| `mgr/devicehealth/self_heal` | 默认开启 | 是否自动把不健康设备上的 OSD 标记 out 以迁移数据 |
| `mgr/devicehealth/mark_out_threshold` | 文档未明确 | 触发自动 mark out 的阈值 |
```bash
ceph device check-health
```
> ⚠️ 与 `mon_osd_min_up_ratio` / `mon_osd_min_in_ratio` 的关系:当不健康设备过多时,自动 mark out 会被抑制并触发 `DEVICE_HEALTH_TOOMANY` 告警(见第七章 7.6)。
> 引自:[Device Management](https://docs.ceph.com/en/tentacle/rados/operations/devices/)
---
## 十四、配置文件参考(Configuring Ceph)
### 14.1 每个 Ceph 集群至少三类守护进程
`ceph-mon`、`ceph-mgr`、`ceph-osd`;部署 CephFS 时还有 `ceph-mds`,部署对象存储时还有 `radosgw`。每个守护进程都有大量配置项,每个配置项都有默认值。**修改默认值前务必理解后果**。默认值会在版本间变化,升级时要查阅对应版本的文档与 release notes。
### 14.2 选项名规则
- 选项名由小写字母 + 下划线组成;
- 命令行与持久化配置中,**下划线 `_` 与短横线 `-` 可互换**(`--mon-host` == `--mon_host`);
- 配置文件中还可以用**空格**代替下划线/短横线;
- 官方建议**统一使用下划线**。
### 14.3 配置来源与优先级(后面覆盖前面,"最后的值生效")
| 序号 | 来源 | 说明 |
|---|---|---|
| 1 | 编译进二进制的默认值 | 最低优先级 |
| 2 | MON 维护的集中配置数据库 | 推荐的主要配置方式 |
| 3 | 本地主机上的配置文件 | **本地文件优先级高于集中库**(不论 section) |
| 4 | 环境变量 | |
| 5 | 命令行参数 | |
| 6 | 运行时覆盖(admin socket / injectargs) | 最高优先级,且**不持久** |
进程启动时会先解析命令行、环境变量、本地配置文件,然后联系 MON 拉取集中配置,拿到完整配置集后才继续启动。
**Bootstrap 选项**(必须本地可用的那几个)
| 选项 | 作用 |
|---|---|
| `mon_host` | MON 地址(**最常需要修改的一个**) |
| `mon_host_override` | 覆盖 MON 地址 |
| `mon_dns_srv_name` | 通过 DNS SRV 查找 MON(见第十九章) |
| `mon_data` / `osd_data` / `mds_data` / `mgr_data` | 守护进程数据目录 |
| `keyring` / `keyfile` / `key` | 认证凭据(多数情况下默认就在上述数据目录里) |
```bash
# 完全跳过从 MON 拉取配置(配置全靠本地文件,或 quorum 已挂需要维护)
ceph --no-mon-config ...
```
### 14.4 配置段(Sections)
| 段 | 作用范围 | 示例 |
|---|---|---|
| `global` | 所有守护进程与客户端 | `log_file = /var/log/ceph/$cluster-$type.$id.log` |
| `mon` | 所有 `ceph-mon`,覆盖 `global` | `mon_cluster_log_to_syslog = true` |
| `mgr` | 所有 `ceph-mgr`,覆盖 `global` | `mgr_stats_period = 10` |
| `osd` | 所有 `ceph-osd`,覆盖 `global` | `osd_op_queue = wpq` |
| `mds` | 所有 `ceph-mds`,覆盖 `global` | `mds_cache_memory_limit = 10G` |
| `client` | 所有 Ceph 客户端(含挂载的 CephFS、RBD、RGW、NVMeoF Gateway) | `objecter_inflight_ops = 512` |
也可以指定具体实例:`mon.foo`、`osd.123`、`client.smith`。**官方不建议这么做**——集群扩容或编排器调整守护进程放置后,实例级配置容易失效;更好的是用 device class 掩码(见 14.6)。
优先级:`global` < 类型段(如 `mon`)< 实例段(如 `mon.foo`);同一段内同名选项**后写的生效**。
> ⚠️ **本地配置文件中的值,优先级永远高于 MON 集中配置库中的值**,与所在 section 无关。
### 14.5 元变量(Metavariables)
| 元变量 | 展开为 | 示例 |
|---|---|---|
| `$cluster` | 集群名,默认 `ceph` | `/etc/ceph/$cluster.keyring` |
| `$type` | 守护进程/进程类型(`mds`/`osd`/`mon`) | `/var/lib/ceph/$type` |
| `$id` | 守护进程/客户端 ID(`osd.0` → `0`;`mds.a` → `a`) | `/var/lib/ceph/$type/$cluster-$id` |
| `$host` | 进程所在主机名 | |
| `$name` | `$type.$id` | `/var/run/ceph/$cluster-$name.asok` |
| `$pid` | 守护进程 PID | `/var/run/ceph/$cluster-$name-$pid.asok` |
> ⚠️ 集群"花名"(vanity name,例如 `ceph2`)**已废弃**,未来版本可能移除。强烈建议新集群一律使用默认名 `ceph`。`--cluster` 选项仅为向后兼容保留。若确实需要在同一主机上运行多套集群,请用 cephadm(容器隔离)。
### 14.6 配置掩码(Masks,仅集中配置库支持)
| 形式 | 含义 | 示例 |
|---|---|---|
| `type:location` | CRUSH bucket 类型 + 值 | `host:foo`(只对主机 foo 上的 daemon 生效)、`rack:foo` |
| `class:device-class` | CRUSH device class | `class:ssd`(**只对 OSD 生效**) |
`who` 参数可以是段名、掩码,或二者用 `/` 组合:`osd/rack:foo` 表示 rack foo 下所有 OSD。
> 💡 官方提示:新版 Ceph 提供的 OSD device class、`osd_memory_target` 自动调优、`osd_recovery_sleep_ssd`、`osd_recovery_max_active_hdd` 等按介质区分的选项,已经能覆盖大多数"以前需要按主机写配置"的场景,应优先使用掩码而不是实例级配置。
### 14.7 ceph.conf 文件
**搜索顺序**(找到即用):
1. `$CEPH_CONF`(环境变量)
2. `-c path/path`(命令行)
3. `/etc/ceph/$cluster.conf`
4. `~/.ceph/$cluster.conf`
5. `./$cluster.conf`(当前工作目录)
6. 仅 FreeBSD:`/usr/local/etc/ceph/$cluster.conf`
**语法**:ini 风格;`#` 或 `;` 开始注释。
```ini
# <-- 井号(#)前导注释
; 注释可以是任何内容
# 注释总是跟随行内的分号(;)或井号(#)
# 行尾结束注释
```
段名用方括号:
```ini
[global]
debug_ms = 0
[osd]
debug_ms = 1
[osd.1]
debug_ms = 10
[osd.2]
debug_ms = 10
```
**续行**:行尾用 `\`,下一行内容会被拼接:
```ini
[global]
foo = long long ago\
long ago
```
上例中 `foo` 的值为 `long long ago long ago`。注意**最后一行末尾不要加反斜杠**。
带空格的值建议加引号:
```ini
[global]
line = "to be, or not to be"
```
四个元字符 `=`、`#`、`;`、`[` 若要做为值的一部分,必须用 `\` 转义:
```ini
[global]
secret = "I l0ve \# and \["
```
**值类型**
| 类型 | 说明 | 示例 |
|---|---|---|
| `int` | 64 位有符号整数,支持 `K`/`M`/`G`/`T`/`P`/`E`(10³/10⁶/10⁹…)与 `B` | `42`、`-1`、`1K`、`128B` |
| `uint` | 无符号整数 | `256`、`0` |
| `str` | UTF-8 字符串 | `"hello world"` |
| `boolean` | `true`/`false`;也接受整数(0 为假,非 0 为真) | `true`、`1` |
| `addr` | 单个地址,可带 `v1`/`v2`/`any` 前缀;**无前缀时默认 v2** | `v2:1.2.3.4:567`、`[::1]:6789` |
| `addrvec` | 逗号分隔的一组地址,可用 `[` `]` 包裹 | `[v1:1.2.3.4:567,v2:1.2.3.4:568]` |
| `uuid` | RFC4122 UUID | `f81d4fae-7dec-11d0-a765-00a0c91e6bf6` |
| `size` | 64 位无符号整数,支持 SI 与 IEC 前缀 | `1Ki`、`1K`、`1KiB`、`1B` |
| `secs` | 时长;支持 s/sec/second(s)、m/min/minute(s)、hs/hr/hour(s)、d/day(s)、w/wk/week(s)、mo/month(s)、y/yr/year(s) | `1 m`、`1 week` |
> 💡 补充:负数赋给"阈值/上限"类选项时通常表示"不限制",具体以各选项描述为准。
### 14.8 MON 集中配置数据库
自 **Mimic** 起,MON 维护一份全集群配置数据库。**绝大多数配置都应写在这里而不是各节点的 ceph.conf**。只有影响"能否连上 MON、能否认证、能否拉取配置"的少数选项(通常只有 `mon_host`)需要留在本地文件;若 DNS 基础设施足够健壮,还可用 DNS SRV 记录彻底免掉本地配置(第十九章)。
### 14.9 配置命令
| 命令 | 作用 |
|---|---|
| `ceph config dump` | 导出整个集中配置数据库 |
| `ceph config get <who>` | 查看某个 daemon/client 在集中库中的配置 |
| `ceph config get <who> <option>` | 查看某选项:集中库有就返回,否则返回编译默认值 |
| `ceph config set <who> <option> <value>` | 写入集中库(同选项已存在则覆盖) |
| `ceph config show <who>` | 查看**运行中** daemon 的实际值,含来源(可能来自本地文件/命令行/运行时覆盖) |
| `ceph config show-with-defaults <who>` | 同上,并列出所有默认值 |
| `ceph config generate-minimal-conf` | 生成仅够连上 MON 的最小 ceph.conf |
| `ceph config assimilate-conf -i <input> -o <output>` | 把旧配置文件吸入集中库;无法识别/不可由 MON 管理的项写回 output 文件 |
| `ceph config rm <who> <option>` | 从集中库删除某项 |
| `ceph-conf --show-config` | legacy 命令 |
```bash
ceph config dump
ceph config get osd.0
ceph config set global mon_allow_pool_delete false
ceph config show osd.0
ceph config rm osd osd_mclock_scheduler_client_res
```
> ⚠️ `ceph config get` 与 `ceph config show` **不保证返回相同值**:前者只反映编译默认值 + 集中库;要确认某选项是否在集中库中,请用 `ceph config dump`。
> ⚠️ `ceph config set` 的 `who` 粒度要小心:如果已存在 `osd` 级别的 `someoption`,再执行 `ceph config set global someoption somevalue`,集中库会**同时保留两条**,容易造成混淆,通常应避免。
```bash
# 从旧 ceph.conf 迁移到集中库
ceph config assimilate-conf -i /etc/ceph/ceph.conf -o /tmp/ceph.conf.leftover
```
### 14.10 查看选项帮助
```bash
ceph config help log_file
ceph config help log_file -f json-pretty
```
文本输出示例:
```text
log_file - path to log file
(std::string, basic)
Default (non-daemon):
Default (daemon): /var/log/ceph/$cluster-$name.log
Can update at runtime: false
See also: [log_to_stderr,err_to_stderr,log_to_syslog,err_to_syslog]
```
JSON 输出字段:`name`、`type`、`level`、`desc`、`long_desc`、`default`、`daemon_default`、`tags`、`services`、`see_also`、`enum_values`、`min`、`max`、`can_update_at_runtime`。
`level` 取值:`basic`、`advanced`、`dev`。**`dev` 级选项是给开发者测试用的,运维人员不要在没有专家支持的情况下修改**。
混合版本集群(如升级期间)可从具体 daemon 查 schema:
```bash
ceph daemon <name> config help [option]
ceph versions # 查看各 daemon 版本,非升级期应完全一致
```
### 14.11 运行时修改与临时覆盖
```bash
# 持久修改(大多数选项无需重启即生效)
ceph config set osd.1701 debug_ms 20
```
> ⚠️ 日志子系统级别范围 **0 ~ 20**。
> ⚠️ 若选项在本地 ceph.conf 中被定制过,集中配置的设置会被忽略(本地文件优先级更高)。
**临时覆盖(injection)**——只影响当前进程,重启即失效,适合谨慎地试参数:
```bash
# 方式一:从任意主机经 MON 转发(支持通配)
ceph tell osd.1701 config set debug_osd 20
ceph tell osd.* config set debug_osd 20
ceph tell osd.N injectargs '--osd_mclock_profile=high_recovery_ops'
# 方式二:在 daemon 所在主机连 admin socket
ceph daemon osd.4 config set debug_osd 20
```
在 `ceph config show` 的输出中,这些临时值的 source 显示为 `override`。
**查看运行时设置**
```bash
ceph config show osd.1701 # 非默认值
ceph config show osd.1701 debug_osd # 单选项
ceph config show-with-defaults osd.1701 # 含默认值
ceph daemon osd.1701 config show # 全部
ceph daemon osd.1701 config diff # 非默认值 + 每个值的来源
ceph daemon osd.1701 config get debug_osd # 单选项
```
> 若不知道 daemon 在哪台主机:`ceph osd find {id}` 或 `ceph orch ps`。
### 14.12 Octopus 起配置文件解析的变化
| 变化 | 说明 |
|---|---|
| 允许重复选项 | 不再告警,文件中**最后出现的值生效**(此前会报 `warning line 42: 'foo' in section 'bar' redefined`) |
| 非法 UTF-8 | 由"忽略 + 告警"改为**致命错误** |
| 续行 | 行尾 `\` 后可跟**空行**(此前要求下一行非空) |
| 非法配置行 | 视为无效配置并记录 `bad option ==== bad value` |
| 无 section 名的文件 | Octopus 之后只允许包含**一个**选项(此前视为 global) |
### 14.13 Common Settings(通用设置要点)
- 一个 Ceph 节点可以跑多个 daemon(例如一块盘一个 `ceph-osd`);理想情况是按进程类型分工。
- 最小配置示例:
```ini
[global]
mon_initial_members = ceph1
mon_host = 10.0.0.1
```
> ⚠️ `host` 设置的值是节点的**短名**(`hostname -s`),**不是 FQDN,更不是 IP 地址**。除手工部署的初始 MON 设置外,不要手工写 `host`;使用 `cephadm`、`chef` 等部署工具时**不要**在单个 daemon 下写 `host`。
**临时目录**
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `tmp_dir` | 文档未明确 | `/tmp`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 守护进程写临时文件的目录 | 可用 `$TMPDIR` 环境变量初始化,也可命令行覆盖 |
| `tmp_file_template` | 文档未明确 | 文档未明确 | 临时文件名模板 | 例如 `ceph tell --daemon-output-file=:tmp:` 会用到 |
**Monitors**
- 生产集群至少 3 个 MON(Paxos 需要多数派);
- MON 默认在 **3300**(v2)与 **6789**(v1)端口监听;
- 数据默认路径:`/var/lib/ceph/mon/$cluster-$id`,展开如 `/var/lib/ceph/mon/ceph-a`。
**OSDs**
- 数据默认路径:`/var/lib/ceph/osd/$cluster-$id`,展开如 `/var/lib/ceph/osd/ceph-0`;可用 `osd_data` 覆盖(**不建议**);
- `osd_data` 必须指向**不与操作系统共享**的设备;
```bash
ssh {new-osd-host}
sudo mkdir /var/lib/ceph/osd/ceph-{osd-number}
sudo mkfs -t {fstype} /dev/{disk}
sudo mount -o user_xattr /dev/{disk} /var/lib/ceph/osd/ceph-{osd-number}
```
> 文件系统推荐 **xfs**(`btrfs` 与 `ext4` 不推荐且已不再测试)。
**Heartbeats**:OSD 互相检查心跳并向 MON 上报;默认设置即可,有网络延迟问题时再调(见 mon-osd-interaction)。
**日志与调试**:日志轮转与调试参见 troubleshooting 的 log-and-debug 部分(不在本册范围)。
**示例 ceph.conf 的定位**:文档中的 demo-ceph.conf 只是参考样例。Mimic 之后应该"以集中配置为主 + 极简本地 ceph.conf(只写如何找到 MON)",本地文件因此很少需要改动。
> 引自:[Configuring Ceph](https://docs.ceph.com/en/tentacle/rados/configuration/ceph-conf/) / [Common Settings](https://docs.ceph.com/en/tentacle/rados/configuration/common/)
---
## 十五、MON 配置参考
MON 保存 Cluster Map 的"主副本",并提供**认证**与**日志**服务。所有变更都要经 **Paxos** 写入 KV store(RocksDB),因此具备强一致性。
> 一致性要点:MON **通过 monmap 而不是 ceph.conf 互相发现**。这样可避免配置笔误破坏集群。
上表之外的关键背景:
- **Quorum**:多数派(1;2/3;3/5;4/6…)才能形成 quorum。
- **同步角色**:Leader(首个达到最新 Paxos 版本者)、Provider(有最新版本但不是第一)、Requester(落后需同步者)。Leader 会把同步任务委派给 Provider,避免自己被压垮。同步完成后会做 trimming(要求 PG 为 `active+clean`)。
- **时钟**:MON 时钟必须同步(NTP/PTP),否则会出现消息被忽略、超时提前/延后等异常。
### 15.1 Quorum / 引导 / 最小配置
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_force_quorum_join` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 强制 MON 加入 quorum | 仅在确实需要时由专家操作 |
| `fsid` | 文档未明确 | 文档未明确 | 集群唯一标识 | 由部署工具(如 `cephadm` 调用 `uuidgen`)生成;通常存在 monmap 里,不写进配置文件 |
| `mon_initial_members` | 文档未明确 | 文档未明确 | 初始 MON 成员(如 `a,b,c`) | 写全可加快集群上线 |
```ini
[global]
mon_host = 10.0.0.2,10.0.0.3,10.0.0.4
[mon]
mon_initial_members = a,b,c
[mon.a]
host = hostname1
mon_addr = 10.0.0.10:6789
```
> ⚠️ 集群部署后**不应**再改 MON 的 IP;确有需要时按第二章 2.5 / 2.6 的流程操作。
### 15.2 数据(Data)
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_data` | 文档未明确 | `/var/lib/ceph/mon/$cluster-$id` | MON 数据目录 | 不建议改;要改就在 `[mon]` 段统一改 |
| `mon_data_size_warn` | 文档未明确 | 15 GiB | MON store 体积告警阈值(`MON_DISK_BIG`) | 触发后对 MON 做 compact |
| `mon_data_avail_warn` | 文档未明确 | 30% | MON 数据盘可用空间告警阈值(`MON_DISK_LOW`) | 提高到 40% 可更早预警 |
| `mon_data_avail_crit` | 文档未明确 | 5% | MON 数据盘可用空间严重阈值(`MON_DISK_CRIT`) | 触发后需立即处理 |
| `mon_warn_on_crush_straw_calc_version_zero` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | straw calc 版本为 0 时告警 | 配合 `OLD_CRUSH_STRAW_CALC_VERSION` |
| `mon_warn_on_legacy_crush_tunables` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 使用旧 CRUSH tunables 时告警 | 配合 `OLD_CRUSH_TUNABLES` |
| `mon_crush_min_required_version` | 文档未明确 | `hammer`(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 要求的最低 CRUSH 版本 | 升级 tunables 时使用 |
| `mon_warn_on_osd_down_out_interval_zero` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | `mon_osd_down_out_interval=0` 时告警 | 配合 `OSD_NO_DOWN_OUT_INTERVAL` |
| `mon_warn_on_slow_ping_ratio` | 文档未明确 | 0.05(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 慢心跳比例告警阈值 | 与慢心跳告警相关 |
| `mon_warn_on_slow_ping_time` | 文档未明确 | 0(= 禁用)(默认值取自 src/common/options/global.yaml.in @ v20.2.4;⚠️ 此前误写为「1 秒 / 1000ms」,已按权威默认值库更正) | 慢心跳时间阈值(毫秒);默认 0 表示禁用 | 网络质量差时可适度放大 |
| `mon_warn_on_pool_no_redundancy` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 池无冗余(size=1)时告警 | 文档未明确 |
| `mon_cache_target_full_warn_ratio` | 文档未明确 | 0.66(默认值取自 src/common/options/mgr.yaml.in @ v20.2.4) | MON cache 接近满时的告警比例 | 文档未明确 |
| `mon_health_to_clog` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 是否把健康状态变化写入 cluster log | 默认行为即可 |
| `mon_health_to_clog_tick_interval` | 文档未明确 | 1_min(= 60 秒)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 写 clog 的 tick 间隔 | 文档未明确 |
| `mon_health_to_clog_interval` | 文档未明确 | 10_min(= 600 秒)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 写 clog 的最小间隔 | 文档未明确 |
> ⚠️ 性能提示:RocksDB 用 `mmap()` 写数据、刷盘非常频繁,**MON 应与 OSD 分开部署在不同主机和不同磁盘上**。
### 15.3 存储容量(Storage Capacity)
集群接近 `mon_osd_full_ratio` 时,Ceph 会禁止读写以防数据丢失。**默认 full ratio 是 `.95`(95%)**,对小规模测试集群来说过于激进。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_osd_full_ratio` | Float | `0.95` | OSD 判定为 `full` 的已用比例 | 测试集群可降到 `.80`;生产建议留出足够余量 |
| `mon_osd_backfillfull_ratio` | Float | `0.90` | OSD 判定为 `backfillfull` 的比例 | 必须小于 full ratio |
| `mon_osd_nearfull_ratio` | Float | `0.85` | OSD 判定为 `nearfull` 的比例 | 必须小于 backfillfull ratio |
```ini
[global]
mon_osd_full_ratio = .80
mon_osd_backfillfull_ratio = .75
mon_osd_nearfull_ratio = .70
```
> ⚠️ **这三项只在集群创建时生效**,之后值被写入 OSDMap。正常运行期要修改,必须用 `ceph osd set-nearfull-ratio` / `ceph osd set-backfillfull-ratio` / `ceph osd set-full-ratio`。
> 💡 若部分 OSD nearfull 而另一些很空,可能是 nearfull 的 OSD 的 **CRUSH 权重设置不准确**。
**容量规划方法**(官方给出的算法):
1. 记下 OSD 数量与集群总容量,相除得到**单 OSD 平均容量**;
2. 乘以"预期同时故障的 OSD 数",得到需要预留的空间;
3. 用总容量 × full ratio 得到最大运行容量,再减去上一步的预留量,得到合理的 **full ratio**;
4. 用更大的故障规模(例如整个机柜)重复,得到合理的 **nearfull ratio**。
> 例:33 个 OSD × 3TB = 99TB 原始容量,full ratio 0.95 时剩 5TB 即禁止读写 ⇒ 实际可用 95TB,而不是 99TB。
### 15.4 同步(Sync / Paxos)
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_sync_timeout` | 文档未明确 | 1_min(= 60 秒)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 同步超时 | 大规模 monmap/store 时可能需要调大 |
| `mon_sync_max_payload_size` | 文档未明确 | 1_M(= 1048576 字节 = 1 MiB)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 同步时单个消息的最大载荷 | 文档未明确 |
| `paxos_max_join_drift` | 文档未明确 | 10(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 允许的最大落后版本数(超过则必须全量同步) | 文档未明确 |
| `paxos_stash_full_interval` | 文档未明确 | 25(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 多久做一次完整 stash | 文档未明确 |
| `paxos_propose_interval` | 文档未明确 | 1(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 提议间隔 | 文档未明确 |
| `paxos_min` | 文档未明确 | 500(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 保留的最小 Paxos 版本数 | 文档未明确 |
| `paxos_min_wait` | 文档未明确 | 0.05(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 最小等待 | 文档未明确 |
| `paxos_trim_min` | 文档未明确 | 250(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 每次 trim 的最小版本数 | 文档未明确 |
| `paxos_trim_max` | 文档未明确 | 500(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 每次 trim 的最大版本数 | 文档未明确 |
| `paxos_service_trim_min` | 文档未明确 | 250(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 服务级 trim 最小版本数 | 文档未明确 |
| `paxos_service_trim_max` | 文档未明确 | 500(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 服务级 trim 最大版本数 | 文档未明确 |
| `paxos_service_trim_max_multiplier` | 文档未明确 | 20(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 服务级 trim 上限倍数 | 文档未明确 |
| `mon_mds_force_trim_to` | 文档未明确 | 0(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 强制 MDS map trim 到指定 epoch | 排障用 |
| `mon_osd_force_trim_to` | 文档未明确 | 0(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 强制 OSD map trim 到指定 epoch | 排障用 |
| `mon_osd_cache_size` | 文档未明确 | 500(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | OSDMap 缓存的 epoch 数 | 文档未明确 |
| `mon_election_timeout` | 文档未明确 | 5(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 选举超时 | 网络差的集群可适当调大 |
| `mon_lease` | 文档未明确 | 5(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | Paxos lease 时长;与 `mon_clock_drift_allowed` 相关 | 文档未明确 |
| `mon_lease_renew_interval_factor` | 文档未明确 | 0.6(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | lease 续约间隔因子 | 文档未明确 |
| `mon_lease_ack_timeout_factor` | 文档未明确 | 2(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | lease ack 超时因子 | 文档未明确 |
| `mon_accept_timeout_factor` | 文档未明确 | 2(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | accept 超时因子 | 文档未明确 |
| `mon_min_osdmap_epochs` | 文档未明确 | 500(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 保留的最小 OSDMap epoch 数 | 文档未明确 |
| `mon_max_log_epochs` | 文档未明确 | 500(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 保留的最大日志 epoch 数 | 文档未明确 |
### 15.5 时钟(Clock)
> ⚠️ 必须在 MON 主机上配置 NTP/PTP;建议 MON 之间互相同步,同时对多个高质量上游时间源。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_tick_interval` | 文档未明确 | 5(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | MON tick 间隔 | 文档未明确 |
| `mon_clock_drift_allowed` | 文档未明确 | 0.05(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 允许的时钟漂移(`MON_CLOCK_SKEW`) | 与 `mon_lease` 一起考虑;NTP 已正常但仍有告警时可适度放宽 |
| `mon_clock_drift_warn_backoff` | 文档未明确 | 5(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 时钟漂移告警的退避系数 | 文档未明确 |
| `mon_timecheck_interval` | 文档未明确 | 5_min(= 300 秒)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 时钟检查间隔 | 文档未明确 |
| `mon_timecheck_skew_interval` | 文档未明确 | 30(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | skew 检查间隔 | 文档未明确 |
### 15.6 Client
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_client_hunt_interval` | 文档未明确 | 3(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端重新寻找 MON 的间隔 | 文档未明确 |
| `mon_client_ping_interval` | 文档未明确 | 10(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端 ping MON 的间隔 | 文档未明确 |
| `mon_client_max_log_entries_per_message` | 文档未明确 | 1000(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 单条消息携带的最大日志条目数 | 文档未明确 |
| `mon_client_bytes` | 文档未明确 | 100_M(= 104857600 字节 = 100 MiB)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端流量限制(字节) | 文档未明确 |
### 15.7 Pool settings
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_allow_pool_delete` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 是否允许删除池 | 默认应关闭以防止误删;确需删除时临时开启 |
| `osd_pool_default_ec_fast_read` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | EC 池是否启用 fast read | 读密集 EC 场景可开启(会消耗更多带宽) |
| `osd_pool_default_flag_hashpspool` | 文档未明确 | true(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 新建池是否默认启用 hashpspool | 新集群通常已默认开启 |
| `osd_pool_default_flag_nodelete` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 新建池默认禁止删除 | 建议开启(防误删) |
| `osd_pool_default_flag_nopgchange` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 新建池默认禁止改 pg_num | 防止误改导致大规模迁移 |
| `osd_pool_default_flag_nosizechange` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 新建池默认禁止改 size | 防止误改副本数 |
> 自 v0.94 起支持 pool flags,可限制对池的修改,甚至禁止删池。官方认为这点"不便"远小于它阻止的误删数据量。
### 15.8 Miscellaneous
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_max_osd` | 文档未明确 | 10000(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 集群允许的最大 OSD 数 | 文档未明确 |
| `mon_globalid_prealloc` | 文档未明确 | 10000(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | global id 预分配数量 | 大规模客户端场景可加大 |
| `mon_subscribe_interval` | 文档未明确 | 1_day(= 86400 秒)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 订阅间隔 | 文档未明确 |
| `mon_stat_smooth_intervals` | 文档未明确 | 6(默认值取自 src/common/options/mgr.yaml.in @ v20.2.4) | 统计平滑的区间数 | 文档未明确 |
| `mon_probe_timeout` | 文档未明确 | 2(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 探测超时 | 文档未明确 |
| `mon_daemon_bytes` | 文档未明确 | 400_M(= 419430400 字节 = 400 MiB)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | daemon 流量限制 | 文档未明确 |
| `mon_max_log_entries_per_event` | 文档未明确 | 4096(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 单个事件的最大日志条目 | 文档未明确 |
| `mon_osd_prime_pg_temp` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 是否为新 OSD 预置 pg_temp | 文档未明确 |
| `mon_osd_prime_pg_temp_max_time` | 文档未明确 | 0.5(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 预置 pg_temp 的最大耗时 | 文档未明确 |
| `mon_osd_prime_pg_temp_max_estimate` | 文档未明确 | 0.25(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 预置 pg_temp 的最大预估规模 | 文档未明确 |
| `mon_mds_skip_sanity` | 文档未明确 | false(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 跳过 MDS 健全性检查 | 排障用 |
| `mon_max_mdsmap_epochs` | 文档未明确 | 500(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 保留的 MDSMap epoch 数 | 文档未明确 |
| `mon_config_key_max_entry_size` | 文档未明确 | 64_K(= 65536 字节 = 64 KiB)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | config-key 单条最大大小 | 文档未明确 |
| `mon_scrub_interval` | 文档未明确 | 1_day(= 86400 秒)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | MON store scrub 间隔 | 文档未明确 |
| `mon_scrub_max_keys` | 文档未明确 | 100(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | MON store scrub 每次扫描的最大 key 数 | 文档未明确 |
| `mon_compact_on_start` | 文档未明确 | false(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 启动时是否 compact | 大 store 场景可考虑 |
| `mon_compact_on_bootstrap` | 文档未明确 | false(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | bootstrap 时是否 compact | 文档未明确 |
| `mon_compact_on_trim` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | trim 时是否 compact | 文档未明确 |
| `mon_cpu_threads` | 文档未明确 | 4(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | MON 使用的 CPU 线程数 | 文档未明确 |
| `mon_osd_mapping_pgs_per_chunk` | 文档未明确 | 4096(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 计算 PG 映射时每块多少 PG | 文档未明确 |
| `mon_session_timeout` | 文档未明确 | 5_min(= 300 秒)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 会话超时 | 文档未明确 |
| `mon_osd_cache_size_min` | 文档未明确 | 128_M(= 134217728 字节 = 128 MiB)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | OSDMap 缓存最小 epoch 数 | 文档未明确 |
| `mon_memory_target` | 文档未明确 | 2_G(= 2147483648 字节 = 2 GiB)(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | MON 内存目标(自动调优用) | 文档未明确 |
| `mon_memory_autotune` | 文档未明确 | true(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 是否开启 MON 内存自动调优 | 文档未明确 |
| `enable_availability_tracking` | 文档未明确 | `false` | 是否启用 pool 可用性统计 | 需要可用性指标时开启(见 5.10) |
| `pool_availability_update_interval` | 文档未明确 | 1(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 可用性统计更新周期 | 文档未明确 |
### 15.9 NVMe-oF Monitor Client
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `nvmeof_mon_client_disconnect_panic` | 文档未明确 | 100(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 断开连接时是否 panic | 仅调试用途 |
| `nvmeof_mon_client_connect_panic` | 文档未明确 | 30(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 建立连接时是否 panic | 仅调试用途 |
| `nvmeof_mon_client_tick_period` | 文档未明确 | 1(默认值取自 src/common/options/mon.yaml.in @ v20.2.4) | 客户端 tick 周期 | 文档未明确 |
> 引自:[Monitor Config Reference](https://docs.ceph.com/en/tentacle/rados/configuration/mon-config-ref/)
---
## 十六、OSD 配置参考
OSD 以数字递增标识:`osd.0`、`osd.1`、`osd.2`…… 在 `[osd]` 段配置所有 OSD,在 `[osd.0]` 段配置单个 OSD。
> ⚠️ **不要修改 data/journal 的默认路径**,否则后续排障会很麻烦。
### 16.1 常规设置(General)
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_uuid` | 文档未明确 | 文档未明确 | OSD 的 UUID | 由部署工具自动生成 |
| `osd_data` | 文档未明确 | `/var/lib/ceph/osd/$cluster-$id` | OSD 数据目录 | 不建议修改 |
| `osd_max_write_size` | 文档未明确 | 90(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 单次写入最大值 | 文档未明确 |
| `osd_max_object_size` | 文档未明确 | 128_M(= 134217728 字节 = 128 MiB)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 单个对象最大值 | 文档未明确 |
| `osd_client_message_size_cap` | 文档未明确 | 500_M(= 524288000 字节 = 500 MiB)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 客户端消息大小上限 | 文档未明确 |
| `osd_class_dir` | 文档未明确 | `$libdir/rados-classes` | rados class 插件目录 | 不建议修改 |
### 16.2 文件系统设置(File System)
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_mkfs_options_{fs-type}` | String | xfs:`-f -i 2048`;其他:空 | 创建 Filestore OSD 时的 mkfs 参数 | 示例:`osd_mkfs_options_xfs = -f -d agcount=24` |
| `osd_mount_options_{fs-type}` | String | xfs:`rw,noatime,inode64`;其他:`rw, noatime` | 挂载 Filestore OSD 的参数 | 示例:`osd_mount_options_xfs = rw, noatime, inode64, logbufs=8` |
### 16.3 Journal 设置(仅 Filestore)
> Filestore 自 Luminous 起已被 BlueStore 取代,并已废弃;本节仅供理解老集群。
默认 journal 路径:`/var/lib/ceph/osd/$cluster-$id/journal`(通常是指向某设备/分区的符号链接)。
- 单一介质(如全是机械盘)时,journal 应与 data **同设备共存(colocated)**;
- SSD/NVMe + 机械盘混布时,journal 放**快设备**,data 放**慢设备**。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_journal` | 文档未明确 | `/var/lib/ceph/osd/$cluster-$id/journal`(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | journal 路径 | 文档未明确 |
| `osd_journal_size` | 文档未明确 | 5120(5 GB) | journal 大小(MB) | 实践中常设 `10240`(10 GB);应 ≥ 盘速 × `filestore_max_sync_interval` × 2 |
### 16.4 Scrubbing
- **light scrub**:检查对象大小与属性,通常**每天**一次;
- **deep scrub**:读数据并用校验和验证完整性,通常**每周**一次。
Scrub 能保证数据完整性,但**会消耗 I/O**,可通过下列选项调节频率与深度。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_max_scrubs` | 文档未明确 | 3(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 单 OSD 并发 scrub 数 | 文档未明确 |
| `osd_scrub_begin_hour` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 允许 scrub 的起始小时 | 配合业务低峰设置 |
| `osd_scrub_end_hour` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 允许 scrub 的结束小时 | 同上 |
| `osd_scrub_begin_week_day` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 允许 scrub 的起始星期 | 同上 |
| `osd_scrub_end_week_day` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 允许 scrub 的结束星期 | 同上 |
| `osd_scrub_during_recovery` | 文档未明确 | false(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 恢复期间是否允许 scrub | 文档未明确 |
| `osd_scrub_load_threshold` | 文档未明确 | 10.0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 系统负载超过该值则不做 scrub | 文档未明确 |
| `osd_scrub_min_interval` | 文档未明确 | 1_day(= 86400 秒)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 最小 scrub 间隔 | 文档未明确 |
| `osd_scrub_max_interval` | 文档未明确 | 7_day(= 604800 秒)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 最大 scrub 间隔 | 与 `PG_NOT_SCRUBBED` 告警联动 |
| `osd_scrub_chunk_min` | 文档未明确 | 5(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 单次 scrub 最小对象数 | 文档未明确 |
| `osd_shallow_scrub_chunk_min` | 文档未明确 | 50(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 单次 shallow scrub 最小对象数 | 文档未明确 |
| `osd_scrub_chunk_max` | 文档未明确 | 15(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 单次 scrub 最大对象数 | 文档未明确 |
| `osd_shallow_scrub_chunk_max` | 文档未明确 | 100(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 单次 shallow scrub 最大对象数 | 文档未明确 |
| `osd_scrub_sleep` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | scrub chunk 之间的休眠 | 启用 mClock 时会被置 0 |
| `osd_deep_scrub_interval` | 文档未明确 | 7_day(= 604800 秒)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4;示例值 1209600 秒 = 2 周) | deep scrub 间隔 | 与 `PG_NOT_DEEP_SCRUBBED` 告警联动 |
| `osd_scrub_interval_randomize_ratio` | 文档未明确 | 0.5(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 对 scrub 间隔做随机化,避免同时触发 | 文档未明确 |
| `osd_deep_scrub_stride` | 文档未明确 | 512_K(= 524288 字节 = 512 KiB)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | deep scrub 读取的 stride 大小 | 文档未明确 |
| `osd_scrub_auto_repair` | 文档未明确 | false(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 发现不一致时自动修复 | 生产环境谨慎开启(可能掩盖真实错误来源) |
| `osd_scrub_auto_repair_num_errors` | 文档未明确 | 5(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 自动修复允许的错误数上限 | 文档未明确 |
### 16.5 Operations
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_op_num_shards` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | OSD op shard 数量(默认基准) | 见第二十章 mClock 建议 |
| `osd_op_num_shards_hdd` | 文档未明确 | 1(mClock 引入后的新默认,原为 5) | HDD OSD 的 shard 数 | 见 20.3 |
| `osd_op_num_shards_ssd` | 文档未明确 | 8(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD OSD 的 shard 数 | 文档未明确 |
| `osd_op_num_threads_per_shard` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 每 shard 的工作线程数 | 见 20.3 |
| `osd_op_num_threads_per_shard_hdd` | 文档未明确 | 5(原为 1) | HDD OSD 每 shard 线程数 | 见 20.3 |
| `osd_op_num_threads_per_shard_ssd` | 文档未明确 | 2(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD OSD 每 shard 线程数 | 文档未明确 |
| `osd_op_queue` | 文档未明确 | `mclock_scheduler`(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | op 队列调度器(`wpq` / `mclock_scheduler`) | EC 大集群在 mClock 下出现 slow ops 时,可改 `wpq`(见第二十章开头警告) |
| `osd_op_queue_cut_off` | 文档未明确 | `high`(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 队列切换阈值 | 文档未明确 |
| `osd_client_op_priority` | 文档未明确 | 63(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端 op 优先级 | 文档未明确 |
| `osd_recovery_op_priority` | 文档未明确 | 3(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | recovery op 优先级 | 文档未明确 |
| `osd_scrub_priority` | 文档未明确 | 5(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | scrub op 优先级 | 文档未明确 |
| `osd_requested_scrub_priority` | 文档未明确 | 5(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 手动发起 scrub 的优先级 | 文档未明确 |
| `osd_snap_trim_priority` | 文档未明确 | 5(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 快照裁剪优先级 | 文档未明确 |
| `osd_snap_trim_sleep` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 快照裁剪休眠 | mClock 启用时置 0 |
| `osd_snap_trim_sleep_hdd` | 文档未明确 | 5(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | HDD 上的快照裁剪休眠 | 同上 |
| `osd_snap_trim_sleep_ssd` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD 上的快照裁剪休眠 | 同上 |
| `osd_snap_trim_sleep_hybrid` | 文档未明确 | 2(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 混合介质上的快照裁剪休眠 | 同上 |
| `osd_op_thread_timeout` | 文档未明确 | 15(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | op 线程超时 | 文档未明确 |
| `osd_op_complaint_time` | 文档未明确 | 30(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 超过该时间未完成的 op 会被记入 slow request | 与 `SLOW_OPS` 告警联动 |
| `osd_op_history_size` | 文档未明确 | 20(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | op 历史保留条数 | 排障时可临时加大 |
| `osd_op_history_duration` | 文档未明确 | 600(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | op 历史保留时长 | 同上 |
| `osd_op_log_threshold` | 文档未明确 | 5(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 日志中记录 op 的阈值(每 N 个 op) | 文档未明确 |
| `osd_op_thread_suicide_timeout` | 文档未明确 | 150(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | op 线程自杀超时 | 文档未明确(可参考官方博客,但该文结论又指回本页) |
### 16.6 QoS(mClock 相关,详见第二十章)
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_async_recovery_min_cost` | 文档未明确 | 100(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 异步 recovery 的最小 cost | 文档未明确 |
| `osd_push_per_object_cost` | 文档未明确 | 1000(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 推送单个对象的 cost | 文档未明确 |
| `osd_mclock_scheduler_client_res` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | client 类 reservation | 内置 profile 下**被锁定**,无法修改 |
| `osd_mclock_scheduler_client_wgt` | 文档未明确 | 1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | client 类 weight | 同上 |
| `osd_mclock_scheduler_client_lim` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | client 类 limit | 同上 |
| `osd_mclock_scheduler_background_recovery_res` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | background recovery reservation | 同上 |
| `osd_mclock_scheduler_background_recovery_wgt` | 文档未明确 | 1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | background recovery weight | 同上 |
| `osd_mclock_scheduler_background_recovery_lim` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | background recovery limit | 同上 |
| `osd_mclock_scheduler_background_best_effort_res` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | background best-effort reservation | 同上 |
| `osd_mclock_scheduler_background_best_effort_wgt` | 文档未明确 | 1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | background best-effort weight | 同上 |
| `osd_mclock_scheduler_background_best_effort_lim` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | background best-effort limit | 同上 |
### 16.7 Backfilling
增删 OSD 时 CRUSH 会重新平衡,迁移 PG 与对象会明显影响性能。Ceph 用 **backfill** 机制,把迁移的优先级设得低于正常读写。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_max_backfills` | 文档未明确 | 1 | 单 OSD 并发 backfill 数 | mClock 启用时由 mClock 托管;见 20.6 |
| `osd_backfill_scan_min` | 文档未明确 | 64 | 单次 backfill 最少扫描对象数 | 文档未明确 |
| `osd_backfill_scan_max` | 文档未明确 | 512 | 单次 backfill 最多扫描对象数 | 文档未明确 |
| `osd_backfill_retry_interval` | 文档未明确 | 30(秒) | backfill 重试间隔 | 文档未明确 |
### 16.8 OSD Map
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_map_dedup` | 文档未明确 | true(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 是否对 OSDMap 做去重 | 文档未明确 |
| `osd_map_cache_size` | 文档未明确 | 50(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | OSDMap 缓存大小 | 文档未明确 |
| `osd_map_message_max` | 文档未明确 | 40(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 单条消息携带的最大 OSDMap 数 | 文档未明确 |
### 16.9 Recovery
OSD 崩溃重启后,数据可能落后于其他副本,需要进入 recovery 模式补齐。若整个故障域(如一个机柜)同时恢复,recovery 会非常耗时耗资源。Ceph 通过限制并发数、线程数与 chunk 大小来保证降级状态下的性能。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_recovery_delay_start` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 启动后延迟多久开始 recovery | 批量重启时调大可避免恢复风暴 |
| `osd_recovery_max_active` | 文档未明确 | 0(mClock 默认) | 单 OSD 并发 recovery 数 | 见 20.5 |
| `osd_recovery_max_active_hdd` | 文档未明确 | 3(mClock 默认) | HDD OSD 并发 recovery 数 | 同上 |
| `osd_recovery_max_active_ssd` | 文档未明确 | 10(mClock 默认) | SSD OSD 并发 recovery 数 | 同上 |
| `osd_recovery_max_chunk` | 文档未明确 | 8_M(= 8388608 字节 = 8 MiB)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | recovery 单次推送的数据块大小 | 大对象场景可调大 |
| `osd_recovery_max_single_start` | 文档未明确 | 1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 单次启动的 recovery 数上限 | 文档未明确 |
| `osd_recover_clone_overlap` | 文档未明确 | true(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 是否利用 clone overlap 减少恢复数据量 | 快照多的场景有价值 |
| `osd_recovery_sleep` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | recovery 之间的休眠 | mClock 启用时置 0 |
| `osd_recovery_sleep_hdd` | 文档未明确 | 0.1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | HDD recovery 休眠 | 同上 |
| `osd_recovery_sleep_ssd` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD recovery 休眠 | 同上 |
| `osd_recovery_sleep_hybrid` | 文档未明确 | 0.025(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 混合介质 recovery 休眠 | 同上 |
| `osd_recovery_sleep_degraded` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 降级状态下的 recovery 休眠 | 同上 |
| `osd_recovery_sleep_degraded_hdd` | 文档未明确 | 0.1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | HDD 降级 recovery 休眠 | 同上 |
| `osd_recovery_sleep_degraded_ssd` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD 降级 recovery 休眠 | 同上 |
| `osd_recovery_sleep_degraded_hybrid` | 文档未明确 | 0.025(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 混合介质降级 recovery 休眠 | 同上 |
| `osd_recovery_priority` | 文档未明确 | 5(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | recovery 优先级(非 mClock 调度器下) | 文档未明确 |
### 16.10 Tiering
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_agent_max_ops` | 文档未明确 | 4(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | tiering agent 最大并发操作数 | 缓存分层场景使用 |
| `osd_agent_max_low_ops` | 文档未明确 | 2(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | tiering agent 低优先级最大并发操作数 | 同上 |
> 与 `cache_target_dirty_high_ratio` 联动:脏数据达到该比例后,tiering agent 进入高速 flush 模式。
### 16.11 Miscellaneous
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_default_notify_timeout` | 文档未明确 | 30(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | notify 超时 | 文档未明确 |
| `osd_check_for_log_corruption` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 是否检查日志损坏 | 文档未明确 |
| `osd_delete_sleep` | 文档未明确 | 0(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 删除操作之间的休眠 | mClock 启用时置 0 |
| `osd_delete_sleep_hdd` | 文档未明确 | 5(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | HDD 删除休眠 | 同上 |
| `osd_delete_sleep_ssd` | 文档未明确 | 1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD 删除休眠 | 同上 |
| `osd_delete_sleep_hybrid` | 文档未明确 | 1(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 混合介质删除休眠 | 同上 |
| `osd_command_max_records` | 文档未明确 | 256(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 命令返回的最大记录数 | 文档未明确 |
| `osd_fast_fail_on_connection_refused` | 文档未明确 | true(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 连接被拒时快速失败 | 文档未明确 |
> 引自:[OSD Config Reference](https://docs.ceph.com/en/tentacle/rados/configuration/osd-config-ref/)
---
## 十七、网络配置参考
### 17.1 基本前提
- Ceph **不做请求路由或转发**:客户端直接向 OSD 发请求;OSD 之间自行复制,这会额外加重网络负担。
- 单 public 网络即可运行(尤其 25GE 及以上);客户端流量很大的集群,增加一条**私有的 cluster 网络**可显著提升韧性与性能。
- 若网络技术相对较慢(1GE,或高密度/SSD 节点上的 10GE),可考虑**绑定多条链路**或部署专用复制网络。
- 建议网卡做 **bonding(active/active)** 并接冗余交换机,或用 FRR 之类实现三层多路径。使用 LACP 时务必与网络团队确认 **transmit hash policy(通常是 2+3 或 3+4)**,选错会导致链路利用率严重不均。
- 观测工具推荐:`bmon`、`iftop`、`netstat`。
### 17.2 iptables / 防火墙
守护进程默认绑定 **6800:7568** 端口区间(可配置)。
```bash
sudo iptables -L
```
> 某些发行版默认规则形如 `REJECT all -- anywhere anywhere reject-with icmp-host-prohibited`,需要在 public 与 cluster 网络上都先删掉,之后再按需加固。
> 💡 Docker/Podman 容器在规则调整/reload 时可能受影响。建议逐台:置 maintenance → 停容器服务 → 改规则 → 起容器服务 → 退出 maintenance。
| 组件 | 端口 | 说明 |
|---|---|---|
| MON | **3300**(v2)、**6789**(v1) | 始终在 public 网络 |
| MDS / MGR | 从 **6800** 起的第一个可用端口 | 不具确定性;同主机多 daemon 或短时间重启会占用更高端口 ⇒ **应整段开放 6800-7568** |
| OSD | 从 **6800** 起,每个 OSD 最多 **4 个**端口 | 1 个用于客户端与 MON、1 个用于数据复制、2 个用于两个网络的心跳。daemon 崩溃重启未释放旧端口时会占新端口 ⇒ 应整段开放 |
```bash
# MON(public 网络)
sudo iptables -A INPUT -i {iface} -p tcp -s {ip-address}/{netmask} --dport 6789 -j ACCEPT
# MDS / MGR / OSD(整段)
sudo iptables -A INPUT -i {iface} -m multiport -p tcp -s {ip-address}/{netmask} --dports 6800:7568 -j ACCEPT
```
> 若 OSD 与 MDS 同机,public 网络的配置可以合并为一条。
### 17.3 Public Network 配置
```ini
[global]
public_network = {public-network/netmask}
```
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `public_network_interface` | 文档未明确 | 文档未明确 | public 网络使用的网卡名 | 文档未明确 |
| `public_network` | 文档未明确 | 文档未明确 | public 网络(CIDR) | 只能配置在 `[global]`;可配多个子网,但**子网间必须能互通** |
| `public_addr` | 文档未明确 | 文档未明确 | 为特定 daemon 指定静态 public IP | 覆盖 `public_network` |
### 17.4 Cluster Network 配置
声明 cluster network 后,OSD 的**心跳、对象复制与恢复流量**都会走这张网,可提升性能。
```ini
[global]
cluster_network = {cluster-network/netmask}
```
> 🔒 官方建议:cluster network **不应**能从 public 网络或 Internet 访问。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `cluster_network_interface` | 文档未明确 | 文档未明确 | cluster 网络使用的网卡名 | 文档未明确 |
| `cluster_network` | 文档未明确 | 文档未明确 | cluster 网络(CIDR) | 与 public 分开,且互不可达 |
| `cluster_addr` | 文档未明确 | 文档未明确 | 为特定 OSD 指定静态 cluster IP | 覆盖 `cluster_network` |
### 17.5 指定 daemon 地址
```ini
[osd.0]
public_addr = {host-public-ip-address}
cluster_addr = {host-cluster-ip-address}
```
> **单网卡 OSD 跑在双网络集群里**:官方**不推荐**这种部署。若必须如此,可在 `[osd.n]` 中只写 `public_addr` 让它走 public 网络,同时 public 与 cluster 网络必须能互相路由(出于安全考虑官方并不推荐这样做)。
### 17.6 MON 地址发现
```ini
[global]
mon_host = 10.0.0.2, 10.0.0.3, 10.0.0.4
```
- `mon_host` 可以是 IP 列表,也可以是 DNS 名;
- DNS 名若有多条 A/AAAA 记录,会**按顺序逐个探测**;
- 只要能连上**任意一个**在线 MON,就能发现其余所有 MON,因此 `mon_host` 只需保证"能触达一个在线 MON"即可。
- MGR / OSD / MDS 默认绑定任意可用地址,无需特殊配置。
### 17.7 Bind 设置
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `ms_bind_port_min` | 文档未明确 | 6800 | OSD/MDS 绑定的最小端口 | 与防火墙范围保持一致 |
| `ms_bind_port_max` | 文档未明确 | 7568 | OSD/MDS 绑定的最大端口 | 同上 |
| `ms_bind_ipv4` | 文档未明确 | `true` | 是否绑定 IPv4 | 文档未明确 |
| `ms_bind_ipv6` | 文档未明确 | `false` | 是否绑定 IPv6 | 纯 IPv6 环境需改为 true |
| `public_bind_addr` | 文档未明确 | 文档未明确 | public 网络绑定地址 | 文档未明确 |
### 17.8 TCP 设置
> Ceph **默认禁用 TCP buffering**(Nagle)。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `ms_tcp_nodelay` | 文档未明确 | true(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 是否禁用 Nagle | 默认即为禁用,通常不改 |
| `ms_tcp_rcvbuf` | 文档未明确 | 0(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | TCP 接收缓冲区大小 | 文档未明确 |
### 17.9 通用网络设置
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `ms_type` | 文档未明确 | `async+posix`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | messenger 实现类型(如 `async+posix`) | 文档未明确 |
| `ms_async_op_threads` | 文档未明确 | 3(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 异步 messenger 的 op 线程数 | CPU 富余时可适度增加 |
| `ms_initial_backoff` | 文档未明确 | 0.2(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 连接失败后的初始退避 | 文档未明确 |
| `ms_max_backoff` | 文档未明确 | 15(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 最大退避 | 文档未明确 |
| `ms_die_on_bad_msg` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 收到坏消息时是否自杀 | 仅调试 |
| `ms_dispatch_throttle_bytes` | 文档未明确 | 100_M(= 104857600 字节 = 100 MiB)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | dispatch 层限流字节数 | 文档未明确 |
| `ms_inject_socket_failures` | 文档未明确 | 0(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 注入 socket 故障(测试用) | 仅测试环境 |
> Ceph daemon 是**动态绑定**的,因此改网络配置后不需要一次性重启整个集群,可以逐个重启。
> 引自:[Network Configuration Reference](https://docs.ceph.com/en/tentacle/rados/configuration/network-config-ref/)
---
## 十八、msgr2(Messenger v2)协议
### 18.1 是什么
msgr2 是 Ceph 线上协议的第二个大版本,带来三项关键能力:
1. **secure 模式**:对网络上所有数据加密;
2. 改进的认证载荷封装,便于未来接入 Kerberos 等新认证方式;
3. 改进的特性提前通告与协商机制,便于后续协议演进。
守护进程可以同时绑定多个端口,因此**老 v1 客户端与新 v2 客户端可同时接入同一集群**。
- 默认 MON 绑定 IANA 分配的 **3300**(ce4h / 0xce4)用于 v2;
- 同时绑定旧的 **6789** 用于 v1。
### 18.2 地址格式
| 类型 | 形态 | 说明 |
|---|---|---|
| **v2** | `v2:1.2.3.4:578/89012` | 绑定 v2 协议的端口 |
| **v1** | `v1:1.2.3.4:578/89012` | 绑定旧 v1 协议;以前无前缀的地址现在都会显示为 `v1:` |
| **TYPE_ANY** | `any:1.2.3.4:578/89012` | 客户端可用任一版本;**显示时不带前缀** |
Nautilus 之前客户端显示为 `1.2.3.4:0/123456`(端口 0 表示客户端不接受入连接);Nautilus 起内部用 TYPE_ANY 表示。
因为一个 daemon 会绑定多个端口,所以用**地址向量**表示:
```text
epoch 1
fsid 50fcf227-be32-4bcb-8b41-34ca8370bd16
last_changed 2019-02-25 11:10:46.700821
created 2019-02-25 11:10:46.700821
min_mon_release 14 (nautilus)
0: [v2:10.0.0.10:3300/0,v1:10.0.0.10:6789/0] mon.foo
1: [v2:10.0.0.11:3300/0,v1:10.0.0.11:6789/0] mon.bar
2: [v2:10.0.0.12:3300/0,v1:10.0.0.12:6789/0] mon.baz
```
连接方**优先用 v2(列在第一个)**,不行再回退 v1。老客户端只"看得到" v1 地址。
### 18.3 Bind 配置
| 配置项 | 默认值 | 含义 |
|---|---|---|
| `ms_bind_msgr1` | `true` | 是否绑定 v1 端口 |
| `ms_bind_msgr2` | `true`(自 Nautilus 14.2.z 起) | 是否绑定 v2 端口 |
| `ms_bind_ipv4` | `true` | 是否绑定 IPv4 |
| `ms_bind_ipv6` | `false` | 是否绑定 IPv6 |
### 18.4 连接模式
| 模式 | 提供 | 不提供 |
|---|---|---|
| **crc** | 连接建立时的强认证(cephx 双向认证,防中间人与窃听);**crc32c 完整性校验**(防比特翻转) | **机密性**(窃听者能看到认证后的全部流量);**防恶意中间人**(攻击者可改流量并同步改 crc) |
| **secure** | 强认证 + **认证后全部流量加密**(含密码学校验) | — |
> secure 模式在 Nautilus 中使用 **AES-GCM** 流加密,在现代 CPU 上通常比 SHA-256 还快。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `ms_cluster_mode` | 文档未明确 | `crc secure`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 集群内部连接模式 | 可选 crc / secure / 组合 |
| `ms_service_mode` | 文档未明确 | `crc secure`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 服务连接模式 | 同上 |
| `ms_client_mode` | 文档未明确 | `crc secure`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端连接模式 | 同上 |
| `ms_mon_cluster_mode` | 文档未明确 | `secure crc`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | MON 集群内部连接模式 | 通常设置更严格 |
| `ms_mon_service_mode` | 文档未明确 | `secure crc`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | MON 服务连接模式 | 同上 |
| `ms_mon_client_mode` | 文档未明确 | `secure crc`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 客户端连 MON 的模式 | 同上 |
### 18.5 压缩模式
| 模式 | 说明 |
|---|---|
| `force` | 压缩 OSD 间复制消息:多 AZ 部署可降低延迟;公有云中跨 AZ 流量昂贵,压缩可省钱;AWS 实例存储(NVMe)场景下网络带宽相对设备带宽不足时,压缩能提升整体性能 |
| `none` | 不压缩 |
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `ms_compress_secure` | 文档未明确 | false(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | secure 模式下是否压缩 | 文档未明确 |
| `ms_osd_compress_mode` | 文档未明确 | `none`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | OSD 间消息的压缩模式 | 跨 AZ/广域网复制时可考虑 force |
| `ms_osd_compress_min_size` | 文档未明确 | 1_K(= 1024 字节 = 1 KiB)(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 触发压缩的最小消息大小 | 文档未明确 |
| `ms_osd_compression_algorithm` | 文档未明确 | `snappy`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 压缩算法 | 文档未明确 |
### 18.6 从 v1-only 迁移到 v2+v1
多数用户的 MON 仍绑在默认的 6789(v1),此时启用 v2 只需一句:
```bash
ceph mon enable-msgr2
```
若 MON 使用非标准端口(例如 `mon.a` 绑在 `1.2.3.4:1111`,想在 `1112` 上开 v2):
```bash
ceph mon set-addrs a [v2:1.2.3.4:1112,v1:1.2.3.4:1111]
```
MON 绑定 v2 后,每个 daemon 在**下次重启**时开始通告 v2 地址。
### 18.7 更新 ceph.conf 与 mon_host
旧的写法:
```text
mon_host = 10.0.0.1:6789,10.0.0.2:6789,10.0.0.3:6789
```
可改写成显式向量:
```text
mon_host = [v2:10.0.0.1:3300/0,v1:10.0.0.1:6789/0],[v2:10.0.0.2:3300/0,v1:10.0.0.2:6789/0],[v2:10.0.0.3:3300/0,v1:10.0.0.3:6789/0]
```
但使用默认端口(3300 / 6789)时**可以省略端口**:
```text
mon_host = 10.0.0.1,10.0.0.2,10.0.0.3
```
推荐流程(配合集中配置迁移):
```bash
ceph config assimilate-conf < /etc/ceph/ceph.conf
ceph config generate-minimal-config > /etc/ceph/ceph.conf.new
cat /etc/ceph/ceph.conf.new
# minimal ceph.conf for 0e5a806b-0ce5-4bc6-b949-aa6f68f5c2a3
# [global]
# fsid = 0e5a806b-0ce5-4bc6-b949-aa6f68f5c2a3
# mon_host = [v2:10.0.0.1:3300/0,v1:10.0.0.1:6789/0]
mv /etc/ceph/ceph.conf.new /etc/ceph/ceph.conf
```
> ⚠️ 方括号语法只有 Nautilus 及以上才认识,**不要**在尚未升级软件包的主机上先改。
> 引自:[Messenger v2](https://docs.ceph.com/en/tentacle/rados/configuration/msgr2/)
---
## 十九、通过 DNS 查找 Monitor
自 Ceph **11.0.0(Kraken)** 起,RADOS 支持通过 DNS 查找 MON。这样 daemon 与客户端的 `ceph.conf` 里就**不再需要 `mon host` 指令**,且 MON 拓扑变更只需改 DNS。
- 客户端与 daemon 通过 **`DNS SRV TCP` 记录**查找 MON;
- 默认查找名为 **ceph-mon** 的 TCP 服务,由 `mon_dns_srv_name` 配置。
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `mon_dns_srv_name` | 文档未明确 | `ceph-mon`(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 查找的 SRV 服务名 | 也可写成 `<service-name>_<upper-level-domain>`(如 `ceph-mon_example.com`),从而不使用 DNS search domain,直接查 `_ceph-mon._tcp.example.com` |
### 19.1 zone 文件示例(search domain = example.com)
先给 MON 建地址记录(IPv4 的 A 或 IPv6 的 AAAA):
```text
mon1.example.com. AAAA 2001:db8::100
mon2.example.com. AAAA 2001:db8::200
mon3.example.com. AAAA 2001:db8::300
```
```text
mon1.example.com. A 192.168.0.1
mon2.example.com. A 192.168.0.2
mon3.example.com. A 192.168.0.3
```
再建名为 `ceph-mon` 的 SRV TCP 记录:
```text
_ceph-mon._tcp.example.com. 60 IN SRV 10 20 6789 mon1.example.com.
_ceph-mon._tcp.example.com. 60 IN SRV 10 30 6789 mon2.example.com.
_ceph-mon._tcp.example.com. 60 IN SRV 20 50 6789 mon3.example.com.
```
### 19.2 负载均衡语义
- 三个 MON 都在端口 **6789**;
- priority 分别为 **10、10、20**;weight 分别为 **20、30、50**;
- **priority 相同的多条 SRV 记录,客户端按 weight 比例**分摊连接:本例中约 40% 连 mon1、60% 连 mon2;
- 若这两个都不可达,才会回退考虑 mon3。
> 参见第十八章(Messenger v2)中关于 v1/v2 端口与地址格式的说明。
> 引自:[Looking up Monitors through DNS](https://docs.ceph.com/en/tentacle/rados/configuration/mon-lookup-dns/)
---
## 二十、mClock QoS 配置参考
> ⚠️ **开篇警告(Tentacle 版新增关注点)**:在带 EC 池的大集群上,recovery/backfill 期间(例如把某个 OSD drain out)可能观察到 slow ops。原因是 mClock 下 EC 恢复产生的 sub-op 读会走 `immediate` 高优先级队列、**绕过 mClock 限流**;当很多 OSD 同时从一个源 OSD 读时,会打满该 OSD 的高优先级队列,饿死客户端与后台任务。**临时规避办法**是切换到 `WeightedPriorityQueue`(`wpq`),该改动需重启每个 OSD 后生效:
>
> ```bash
> ceph config set osd osd_op_queue wpq
> ```
### 20.1 mClock 客户端类型
| Client Type | 请求类型 |
|---|---|
| Client | 外部客户端发出的 I/O 请求 |
| Background recovery | 内部 recovery 请求 |
| Background best-effort | 内部 backfill、scrub、snap trim、PG deletion 请求 |
### 20.2 核心概念(dmClock)
- mClock 是 **dmClock** 的(非分布式)实现,通过 **reservation(预留,最小 IOPS)**、**limitation(上限,最大 IOPS)**、**weight(权重,超额时的比例份额)** 三个标签分配 I/O 资源。
- 在 Ceph 中,操作按 "**cost**" 计量。
示例:recovery `(r:1, l:5, w:1)` 与 client ops `(r:2, l:0, w:9)`:
- recovery **每秒最多 5 个请求**(当前实现会强制 limit,超限的 op 会留在队列中直到 limit 恢复);
- 只要还有 recovery 请求,每秒**至少有 1 个**会执行 ⇒ recovery 不会被饿死;
- 客户端权重 9 : 1,因此客户端能拿到更大份额;且客户端**没有 limit**,在没有 recovery 时可吃满资源。
**权重的微妙之处**:weight *W* 越大,下一个请求的权重标签增量 *1/W* 越小;当 *W* 过大时,计算出的标签可能永远小于当前时间,从而失去意义。**结论:weight 不要设得太大,应小于预期每秒能服务的请求数。**
### 20.3 内置 profile
> 说明:下表数值表示"分配给该服务类型的 OSD 总 IOPS 容量的比例"。
**balanced(默认)**:client 与 recovery 均分;best-effort 预留很低,竞争时完成得更慢。适用于常态运行。
| Service Type | Reservation | Weight | Limit |
|---|---|---|---|
| client | 50% | 1 | MAX |
| background recovery | 50% | 1 | MAX |
| background best-effort | 5% | 2 | 90% |
**high_client_ops**:优先保障客户端性能(例如 I/O 密集型应用持续运行),代价是恢复变慢。
| Service Type | Reservation | Weight | Limit |
|---|---|---|---|
| client | 60% | 2 | MAX |
| background recovery | 40% | 1 | MAX |
| background best-effort | 5% | 4 | 70% |
**high_recovery_ops**:优先保障恢复(例如运维人员在非高峰时段临时开启以加速恢复)。
| Service Type | Reservation | Weight | Limit |
|---|---|---|---|
| client | 30% | 1 | MAX |
| background recovery | 70% | 2 | MAX |
| background best-effort | 5% | 2 | MAX |
> 内置 profile 中,background best-effort 包含 backfill、scrub、snap trim、pg deletion 四类操作。
**custom**:完全手动控制所有 mClock 参数,供高级用户使用,需谨慎。
### 20.4 HDD 集群的 shard 配置(重要变更)
在 HDD 集群上,shard 数量决定 mClock 队列的作用力:**shard 越少,mClock 调度越精确**(前提是每 shard 有足够工作线程)。
官方在 192 OSD / 8 节点 / 1.5 亿对象的 HDD 集群上测试(对象大小 1 KiB - 256 KiB)发现:多 shard 下调度不理想——多节点故障测试时客户端吞吐在不同轮次间**不一致**,并伴随大量 slow request(见 Tracker #66289)。原因是 client 与 recovery 都被给了 MAX limit,两者直接竞争导致吞吐不可预测。改为**单 shard + 多线程**后,client 与 recovery 吞吐在多次测试中显著更稳定;大对象(1 MiB - 256 MiB)测试结果类似。
因此作为过渡措施,HDD 的默认值被调整:
| 配置项 | 旧默认值 | 新默认值 |
|---|---|---|
| `osd_op_num_shards_hdd` | 5 | **1** |
| `osd_op_num_threads_per_shard_hdd` | 1 | **5** |
### 20.5 内置 profile 会锁定的配置
> ⚠️ 这些默认值**无法通过任何配置子系统的命令修改**(`config set`、`config daemon`、`config tell`)。命令会报成功,但 mClock QoS 参数会被**还原为内置 profile 的默认值**。
被锁定的 mClock 参数(共 9 个):
```text
osd_mclock_scheduler_client_res / _wgt / _lim
osd_mclock_scheduler_background_recovery_res / _wgt / _lim
osd_mclock_scheduler_background_best_effort_res / _wgt / _lim
```
**Recovery/Backfill 被覆盖的选项**(官方建议不要改,内置 profile 是按这些默认值优化的):
| 配置项 | 原默认值 | mClock 默认值 |
|---|---|---|
| `osd_max_backfills` | 1 | 1 |
| `osd_recovery_max_active` | 0 | 0 |
| `osd_recovery_max_active_hdd` | 3 | 3 |
| `osd_recovery_max_active_ssd` | 10 | 10 |
**被禁用(置 0)的 sleep 选项**(任何 profile,含 custom,激活时都会置 0):
```text
osd_recovery_sleep / _hdd / _ssd / _hybrid
osd_recovery_sleep_degraded / _hdd / _ssd / _hybrid
osd_scrub_sleep
osd_delete_sleep / _hdd / _ssd / _hybrid
osd_snap_trim_sleep / _hdd / _ssd / _hybrid
```
> 目的:确保 mClock 调度器能自主决定何时从 op queue 取下一个 op 交给 operation sequencer,从而提供期望的 QoS。
### 20.6 启用与切换 profile
```bash
# 运行时切换(默认已是 balanced)
ceph config set osd.N osd_mclock_profile <value>
ceph config set osd.0 osd_mclock_profile high_recovery_ops
```
**切换到 custom**
```bash
ceph config set osd osd_mclock_profile custom
ceph config set osd.0 osd_mclock_scheduler_client_res 0.5
```
> ⚠️ 改某一项的 reservation 时,**必须同步调整其他服务**,确保各 reservation 之和**不超过 OSD IOPS 容量的 1.0**。
> 💡 reservation 与 limit 是**按 shard**分配的,依据 OSD 的 backing device 类型(HDD/SSD),参见 `osd_op_num_shards_hdd` 与 `osd_op_num_shards_ssd`。
**从 custom 切回内置 profile**(必须先清掉集中库里的 custom 设置)
```bash
ceph config set osd osd_mclock_profile high_client_ops
ceph config dump
ceph config rm osd osd_mclock_scheduler_client_res
ceph config show osd.0
```
**临时切换(ephemeral)**
```bash
ceph tell osd.0 injectargs '--osd_mclock_profile=high_recovery_ops'
ceph daemon osd.0 config set osd_mclock_profile high_recovery_ops
```
> ⚠️ 这是给高级用户/实验用的,**不建议在运行中的集群上做**。这些改动是临时的,重启即失效;且用 `ceph config set osd.N ...` 无法再覆盖它们(设计如此),除非重启 OSD。
### 20.7 修改 max backfills / recovery 上限
修改由 `osd_mclock_override_recovery_settings`(默认 `false`)把门。未先开启它而直接改,值会被**重置回 mClock 默认值**并在集群日志里留下警告(可能需要几秒才恢复,用 `config show` 验证)。
```bash
ceph config set osd osd_mclock_override_recovery_settings true
ceph config set osd osd_max_backfills 5
ceph config show osd.0 | grep osd_max_backfills
ceph config set osd osd_mclock_override_recovery_settings false
```
### 20.8 OSD 容量自动测定
OSD 初始化时会**自动运行 OSD bench**,并按设备类型覆盖 `osd_mclock_max_capacity_iops_[hdd, ssd]`,用户无需干预。
```bash
ceph config show osd.0 osd_mclock_max_capacity_iops_ssd
```
**不合理的 bench 结果会被抑制**:
| 配置项 | 默认值 |
|---|---|
| `osd_mclock_iops_capacity_threshold_hdd` | 500 |
| `osd_mclock_iops_capacity_threshold_ssd` | 80000 |
若 bench 结果超过阈值,则**回退到** `osd_mclock_max_capacity_iops_hdd` / `_ssd` 的默认值,并在集群日志记录警告,例如:
```text
2022-10-27T15:30:23.270+0000 7f9b5dbe95c0 0 log_channel(cluster) log [WRN]
: OSD bench result of 39546.479392 IOPS exceeded the threshold limit of
25000.000000 IOPS for osd.1. IOPS capacity is unchanged at 21500.000000
IOPS. The recommendation is to establish the osd's IOPS capacity using other
benchmark tools (e.g. Fio) and then override
osd_mclock_max_capacity_iops_[hdd|ssd].
```
若默认值仍不准确,建议用 **Fio** 等工具在盘上做自定义基准测试,再覆盖该选项。
### 20.9 手工基准测试(可选)
`ceph tell osd.N bench` 语法:
```bash
ceph tell osd.N bench [TOTAL_BYTES] [BYTES_PER_WRITE] [OBJ_SIZE] [NUM_OBJS]
```
| 参数 | 含义 |
|---|---|
| `TOTAL_BYTES` | 写入总字节数 |
| `BYTES_PER_WRITE` | 每次写入的块大小 |
| `OBJ_SIZE` | 每个对象的大小 |
| `NUM_OBJS` | 写入的对象数 |
步骤:
```bash
# 1) 先清缓存,保证测量准确
ceph tell osd.0 cache drop
# 2) 跑 4KiB 随机写
ceph tell osd.0 bench 12288000 4096 4194304 100
```
1. 记录基线吞吐(默认 bluestore throttle 下);
2. 若想测定适合本环境的 throttle 值,把 `bluestore_throttle_bytes` 与 `bluestore_throttle_deferred_bytes` 先都设为 **32 KiB(32768 字节)**;
3. 重跑同样的 4KiB 随机写;
4. 若吞吐与基线不符,把两个 throttle 值 **翻倍** 后重跑,直到吞吐接近基线。
> 参考值:NVMe SSD 机器上 `256 KiB` 能最大化 mClock 效果;HDD 上对应值为 `40 MiB`。一般而言 HDD 的 throttle 值应比 SSD 高。
设置/覆盖 OSD 容量:
```bash
ceph config set osd.0 osd_mclock_max_capacity_iops_hdd 350
```
也可以写在 ceph.conf 的 `[osd.N]` 段。
**全局覆盖多个 OSD 的容量**
```bash
# 1) 查看集中库中的 per-OSD 值
ceph config dump | grep osd_mclock_max_capacity_iops
# WHO MASK LEVEL OPTION VALUE
# osd.0 basic osd_mclock_max_capacity_iops_hdd 379.197568
# osd.1 basic osd_mclock_max_capacity_iops_hdd 400.903575
# 2) 逐个删除 per-OSD 值
ceph config rm osd.0 osd_mclock_max_capacity_iops_hdd
ceph config rm osd.1 osd_mclock_max_capacity_iops_hdd
# 3) 确认已清空后,设置全局值
ceph config set global osd_mclock_max_capacity_iops_hdd 111
# 4) 验证
ceph config dump | grep osd_mclock_max_capacity_iops
# global basic osd_mclock_max_capacity_iops_hdd 111.000000
ceph config show osd.0 | grep osd_mclock_max_capacity_iops_hdd
# osd_mclock_max_capacity_iops_hdd 111.000000 mon
```
> 注意:OSD 启动时的 bench 结果会覆盖全局值,因此 per-OSD 值存在时以 per-OSD 为准。
### 20.10 mClock 配置项清单
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `osd_mclock_profile` | 文档未明确 | `balanced` | 使用的 profile(`balanced` / `high_client_ops` / `high_recovery_ops` / `custom`) | 默认即可;非高峰加速恢复可临时切 `high_recovery_ops` |
| `osd_mclock_max_capacity_iops_hdd` | 文档未明确 | 315(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | HDD OSD 的 IOPS 容量 | 由启动时 bench 自动覆盖;偏差大时用 Fio 校准后手工设置 |
| `osd_mclock_max_capacity_iops_ssd` | 文档未明确 | 21500(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD OSD 的 IOPS 容量 | 同上 |
| `osd_mclock_max_sequential_bandwidth_hdd` | 文档未明确 | 150_M(= 157286400 字节 = 150 MiB)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | HDD OSD 的最大顺序带宽(MiB/s) | profile 的输入参数之一 |
| `osd_mclock_max_sequential_bandwidth_ssd` | 文档未明确 | 1200_M(= 1258291200 字节 = 1200 MiB)(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD OSD 的最大顺序带宽(MiB/s) | 同上 |
| `osd_mclock_force_run_benchmark_on_init` | 文档未明确 | false(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 初始化时强制运行 bench | 需要重新测定容量时可开启 |
| `osd_mclock_skip_benchmark` | 文档未明确 | false(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | 跳过 bench | 已手工设定容量时可开启 |
| `osd_mclock_override_recovery_settings` | 文档未明确 | `false` | 是否允许修改 mClock 的 recovery/backfill 默认值 | 仅在确有必要时临时开启,改完立即关回 |
| `osd_mclock_iops_capacity_threshold_hdd` | 文档未明确 | 500 | HDD bench 结果可信度上限 | bench 结果长期超阈值时可按实际盘型上调 |
| `osd_mclock_iops_capacity_low_threshold_hdd` | 文档未明确 | 50(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | HDD bench 结果下限阈值 | 文档未明确 |
| `osd_mclock_iops_capacity_threshold_ssd` | 文档未明确 | 80000 | SSD bench 结果可信度上限 | 同上 |
| `osd_mclock_iops_capacity_low_threshold_ssd` | 文档未明确 | 1000(默认值取自 src/common/options/osd.yaml.in @ v20.2.4) | SSD bench 结果下限阈值 | 文档未明确 |
> 引自:[mClock Config Reference](https://docs.ceph.com/en/tentacle/rados/configuration/mclock-config-ref/)
---
## 二十一、通用配置(General Config Reference)
| 配置项 | 类型 | 默认值 | 含义 | 调参建议 |
|---|---|---|---|---|
| `admin_socket` | 文档未明确 | `/var/run/ceph/$cluster-$name.asok` | admin socket 路径 | 一般不动;`ceph daemon` 依赖它 |
| `pid_file` | 文档未明确 | 文档未明确 | PID 文件路径 | 文档未明确 |
| `chdir` | 文档未明确 | 文档未明确 | 守护进程启动时切换到的目录 | 文档未明确 |
| `fatal_signal_handlers` | 文档未明确 | true(默认值取自 src/common/options/global.yaml.in @ v20.2.4) | 是否安装致命信号处理器(用于生成崩溃转储) | 排障时可开启 |
| `max_open_files` | 64-bit Integer | `0` | 进程启动时在 OS 层设置的最大文件描述符数 | `0` 表示不设置。OSD 数量多/对象多时设置一个足够大的值,可避免 daemon 耗尽 fd |
> 引自:[General Config Reference](https://docs.ceph.com/en/tentacle/rados/configuration/general-config-ref/)
---
## 二十二、修改 MON 选举策略(change-mon-elections)
MON 通过选举产生 leader。Ceph 提供三种 election strategy(选举策略),决定「哪些 monitor 可以被选为 leader、按什么规则选」。
**默认情况下 monitor 处于 `classic` 模式。** 官方明确建议:除非有非常具体的理由(unless you have a very specific reason),应保持在 `classic` 模式,因为它是最简单的模式;其余模式是为了提供 `classic` 没有的特定特性而存在的。
### 22.1 三种策略的语义与适用场景
| 策略 | 整数取值 | 语义 | 适用场景 |
|---|---|---|---|
| `classic` | `1` | 默认策略,参与 quorum 的 monitor 均可被选为 leader | 绝大多数集群;没有特殊诉求时的唯一推荐项 |
| `disallow` | `2` | 允许把某些 monitor 标记为 disallowed:它们**仍参与 quorum 并服务客户端,但不能被选为 leader** | 存在距离客户端很远(far away from clients)的 monitor 时 |
| `connectivity` | `3` | 各 monitor 为它的 peer 给出 connection score,选举**得分最高**的 monitor 为 leader | 集群跨多个数据中心(stretched across multiple data centers)、或网络拓扑不均匀/不平衡,可能发生网络分区(network partitioning,也称 *net-splits*)时 |
> 💡 补充:`connectivity` 模式同样支持 disallow 能力,且使用的是与 Disallow Mode **完全相同**的一组命令,因此"选谁当 leader"和"谁不许当 leader"可以叠加使用。
### 22.2 查看与修改
**在构造集群之前**切换模式,改的是 `mon election default strategy` 选项,它取整数值:
| 取值 | 对应策略 |
|---|---|
| `1` | `classic` |
| `2` | `disallow` |
| `3` | `connectivity` |
| 配置项 | 类型 | 默认值 | 取值范围 | 含义 |
|---|---|---|---|---|
| `mon election default strategy` | uint(整数) | `1`(默认值取自 src/common/options/*.yaml.in @ v20.2.4) | `1` ~ `3`(min: 1 / max: 3) | The election strategy to set when constructing the first monmap(构造第一个 monmap 时采用的选举策略) |
**集群已经开始运行之后**切换模式,用命令(无需重启、无需改配置):
```bash
ceph mon set election_strategy {classic|disallow|connectivity}
```
> 💡 补充:官方源文没有说明"如何查看当前生效的选举策略"。实机上可用 `ceph mon dump` 核对当前策略与 disallowed 列表——官方仅在 Disallow Mode 一节中说明用它查看 disallowed leader 列表。
### 22.3 Disallow Mode
`disallow` 模式允许把 monitor 标记为 disallowed。被标记的 monitor **仍然参与 quorum、仍然服务客户端,但不能被选为 leader**。官方给出的典型动机是:该 monitor 距离客户端很远。
```bash
# 禁止某个 monitor 被选为 leader
ceph mon add disallowed_leader {name}
# 从 disallowed 列表中移除,恢复其被选举为 leader 的资格
ceph mon rm disallowed_leader {name}
# 查看 disallowed leader 列表
ceph mon dump
```
### 22.4 Connectivity Mode
`connectivity` 模式会评估每个 monitor 为其 peer 提供的 connection score,并选举**分数最高**的 monitor。该模式专为处理网络分区(net-splits)而设计:当集群跨多个数据中心部署、或网络拓扑不均匀/不平衡时,就可能发生网络分区。
### 22.5 查看 connectivity scores
**即使 monitor 没有处于 `connectivity` 模式,它们也会维护 connection scores。**
```bash
ceph daemon mon.{name} connection scores dump
```
- 单条连接的分数范围是 `0` 到 `1`(含端点,inclusive);
- 分数中还会包含该连接是被判定为 alive 还是 dead——判定依据是它是否在超时前返回了最近一次 ping(whether it returned its latest ping before timeout)。
### 22.6 重置 connectivity scores
如果排障过程中确认这些分数因某种原因已经失效,可以丢弃历史并重置分数:
```bash
ceph daemon mon.{name} connection scores reset
```
官方对风险的描述:
- 重置分数**风险很小**(carries little risk):monitor 仍会快速判定一条连接是 alive 还是 dead,并且如果原分数是准确的,分数会重新趋回(trend back)到之前的水平;
- 但重置**本应是不必要的**(ought to be unnecessary);
- 除非支持团队或开发者建议(unless advised by your support team or by a developer),**不推荐**执行。
### 22.7 修改策略的注意事项与风险总结
| 事项 | 说明 |
|---|---|
| 默认即推荐 | `classic` 是最简单、也是官方唯一无条件推荐的模式,不要为"更高级"而切换 |
| 切换时机不同 | 建集群前改 `mon election default strategy`(整数 1/2/3);集群运行中改 `ceph mon set election_strategy`(字符串) |
| disallow 不影响可用性 | 被 disallow 的 monitor 仍参与 quorum、仍服务客户端,只是不担任 leader |
| connectivity 面向网络分区 | 仅在跨机房/拓扑不均匀时才有实际意义 |
| scores reset 需谨慎 | 风险低但默认不需要做,须经支持团队或开发者建议 |
> 引自:[Changing Monitor Elections](https://docs.ceph.com/en/tentacle/rados/operations/change-mon-elections/)
---
## 文档未明确项
本节汇总本册在整理过程中,**官方 rst 源文中确实没有给出、因此本册不做推测**的内容。在实机上可用右侧建议命令查询。
| 序号 | 位置 | 未明确的内容 | 建议的实机查询方式 |
|---|---|---|---|
| 1 | 第十四 ~ 二十一章大量配置项 | **多数配置项的「类型」与「默认值」**。Ceph 官网页面上这些值由 Ceph 源码中的选项定义(`src/common/options/*.yaml`)生成,**不在 `doc/` 目录内**,本册依据的 rst 源文只有 `.. confval:: <name>` 一行。**✅ 已补全(198 处)**:默认值已按 `src/common/options/*.yaml.in @ v20.2.4` 权威默认值库逐项回填并标注来源文件;「类型」列仍为「文档未明确」 | `ceph config help <option>`;`ceph config help <option> -f json-pretty`;`ceph config show <who>` |
| 2 | 4.6 flag 表 | `sortbitwise` flag 的新增使用场景与处置方式 | `ceph osd set-group --help`(文档未给出) |
| 3 | 5.8 | admin socket 发送信号(HUP / -9)的**确切命令形态** | `ceph daemon {name} help` |
| 4 | 5.10 | `pool_availability_update_interval` 默认值 —— **✅ 已补全**:`1`(`src/common/options/mon.yaml.in @ v20.2.4) | `ceph config help pool_availability_update_interval` |
| 5 | 7.2 | `AUTH_INSECURE_GLOBAL_ID_RECLAIM` 与 `AUTH_INSECURE_GLOBAL_ID_RECLAIM_ALLOWED` 的**具体收敛/关闭命令** | `ceph health detail`;`ceph config help auth_*` |
| 6 | 7.4 | `OLD_CRUSH_TUNABLES` / `OLD_CRUSH_STRAW_CALC_VERSION` 的**升级执行路径** | mon-osd-interaction 与 CRUSH 相关文档(不在本册范围) |
| 7 | 7.4 | `OSD_NO_SORTBITWISE` 的处理步骤 | 文档未明确 |
| 8 | 7.5 | `BLUESTORE_LEGACY_STATFS` / `BLUESTORE_DISK_SIZE_MISMATCH` 的具体处理命令 | `ceph health detail` |
| 9 | 7.9 | `NVMEOF_GATEWAY_DELETING` 卡住时的人工干预命令 | 文档未明确 |
| 10 | 9.3 | balancer 的 `sleep_interval`、`pool_ids` 默认值 —— **仍为「文档未明确」**:二者是 mgr balancer **模块参数**(`mgr/balancer/...`),不在 `src/common/options/*.yaml.in` 中,无法回填 | `ceph config help mgr/balancer/...`(文档未列出相关 help 名) |
| 11 | 13.5 | `mgr/devicehealth/warn_threshold`、`mark_out_threshold` 默认值 —— **仍为「文档未明确」**:二者是 mgr devicehealth **模块参数**(`mgr/devicehealth/...`),不在 `src/common/options/*.yaml.in` 中,无法回填 | `ceph config get mgr mgr/devicehealth/warn_threshold` |
| 12 | 15.2 / 15.4 / 15.5 / 15.8 | 大量 `mon_*` 与 `paxos_*` 选项的默认值 —— **✅ 已补全**:除 `fsid`、`mon_initial_members`、`tmp_file_template`、`mon_auth_emergency_allowed_ciphers`(在 yaml.in 中但无 `default:` 字段)外,其余均已按 `src/common/options/{mon,global,mgr}.yaml.in @ v20.2.4` 回填 | `ceph config help <option>` |
| 13 | 16.4 | `osd_deep_scrub_interval` 的默认值(文档只给了示例值 1209600)—— **✅ 已补全**:`7_day`(= 604800 秒 = 7 天),取自 `src/common/options/osd.yaml.in @ v20.2.4`(注意:与源文示例值 1209600 = 14 天不同,以权威默认值库为准) | `ceph config help osd_deep_scrub_interval` |
| 14 | 17.7 / 17.8 / 17.9 | 全部网络类配置项(`ms_*`、`public_*`、`cluster_*`)的默认值 —— **✅ 已补全**:`ms_*` 项已按 `src/common/options/global.yaml.in @ v20.2.4` 回填;`public_network`、`public_addr`、`public_bind_addr`、`cluster_network`、`cluster_addr`、`public_network_interface`、`cluster_network_interface` **在 yaml.in 中无 `default:` 字段**,保持「文档未明确」 | `ceph config help <option>` |
| 15 | 18.4 / 18.5 | `ms_cluster_mode` 等连接/压缩模式类选项的默认值与可选值枚举 —— **✅ 已补全**:`ms_cluster_mode` / `ms_service_mode` / `ms_client_mode` = `crc secure`,`ms_mon_*_mode` = `secure crc`,`ms_osd_compress_mode` = `none`,`ms_osd_compression_algorithm` = `snappy`,`ms_compress_secure` = `false`,取自 `src/common/options/global.yaml.in @ v20.2.4` | `ceph config help <option>`(`enum_values` 字段) |
| 16 | 19 | `mon_dns_srv_name` 的默认值 —— **✅ 已补全**:`ceph-mon`,取自 `src/common/options/global.yaml.in @ v20.2.4` | `ceph config help mon_dns_srv_name` |
| 17 | 20.10 | `osd_mclock_max_capacity_iops_[hdd\|ssd]`、带宽上限、`*_low_threshold_*` 的默认值 —— **✅ 已补全**:hdd/ssd IOPS 容量 `315` / `21500`,顺序带宽 `150_M` / `1200_M`,`*_low_threshold_*` `50` / `1000`,取自 `src/common/options/osd.yaml.in @ v20.2.4` | `ceph config help <option>` |
| 18 | 二十一 | `pid_file`、`chdir`、`fatal_signal_handlers` 的默认值 —— **部分已补全**:`fatal_signal_handlers` = `true`(`src/common/options/global.yaml.in @ v20.2.4`);`pid_file`、`chdir` 在 yaml.in 中**无 `default:` 字段**,保持「文档未明确」 | `ceph config help <option>` |
### 本册中由整理者补充(非官方文档原文)的内容清单
为便于审阅,以下条目均以「💡 补充」标注在正文中:
1. 1.1 — systemd 模板化 unit 命名与数据目录的对应关系;
2. 2.6 — 改网络属于高风险变更,应滚动执行并逐步验证;
3. 5.8 — admin socket 可用于发信号(以 daemon `help` 为准);
4. 7.3 — `pending_modules` 在 MGR 告警排查中的上下文含义;
5. 12(总结)— 三种 BlueStore 迁移策略的共同前置条件(备份 keyring/fsid、保持 noout);
6. 14.6 — 优先使用 device class 掩码而非实例级配置;
7. 14.7 — 负值赋给阈值类选项通常表示"不限制";
8. 17.2 — 容器环境下改 iptables 的推荐顺序(maintenance → 停容器 → 改规则 → 起容器)。
---
> 本册完。全册基于 Ceph Tentacle v20.2.4 `doc/rados/` 下 24 个官方 rst 源文整理,所有命令、参数名、配置项、告警码均保留英文原文;凡源文未给出的数值一律标注「文档未明确」,不做推测。