存储池&&PG及配置管理

11229 字
56 分钟
存储池&&PG及配置管理

存储池 && PG及配置管理#

[TOC]


命令拆解#

Ceph 命令是”层级式”命名的,拆开看每个词就不需要死记

Terminal window
ceph osd pool rm xixi xixi --yes-i-really-really-mean-it
└── "我真要这么干"池删除的最高级双重确认'两次 really'
└── 池名(要输两遍,防止手滑)
└── Remove 删除
└── 存储池(逻辑分区)
└── OSD 守护进程层
└── Ceph CLI 总入口
含义记忆方法
cephCeph 集群 CLI 总入口所有命令都从这个开始
osdObject Storage Daemon存储相关操作(PGCRUSH 都归这层管)
pool存储池,逻辑分区数据的”命名空间”,不同业务用不同池
pgPlacement Group 归置组数据分布的最小单位,一个 PG 里可放成千上万个对象
rmRemove 删除
create创建
get查单个属性精确==查询==某个参数值
set修改属性==修改==某个参数值
dump导出全部导出所有配置/规则,==常配合 grep 过滤==
show查看最终生效配置合并 Config DB + ceph.conf + 默认值
给出进程==实际==跑的配置
lsList 列出列出所有池 / 规则
config集中化配置数据库替代传统 ceph.conf,Monitor 集中存储
crushCRUSH 算法 / 拓扑表集群的”地图”——数据该往哪放
application池用途声明告诉集群这池是给 RBD / CephFS / RGW 用的
replicated副本池类型数据完整复制多份——==“一式三份”==
erasure纠删码池类型切块 + 校验块——“拼图 + 备用块”
pg_numPG 总数池里有多少个”调度组”
pgp_num参与数据放置的 PG 数多少个调度组实际在干活,≤ pg_num
size==副本数==数据一共存几份
min_size==最小副本数==I/O 服务需要的最少可用副本数
nodelete池级删除锁给某个池打上 true → 该池不可删除
mon_allow_pool_delete集群级删除开关Monitor 总闸,控制整个集群是否允许删池
pg_autoscale_modePG 自动伸缩Ceph 根据 OSD 数量和用量自动调整 PG 数
global==全局配置层==影响所有守护进程(mon/osd/mgr/mds/client)
mon / osd / mgr类型级配置 target只影响某一类守护进程
osd.0 / mon.Ceph-201==实例级==配置 target精确到某一个具体进程
--yes-i-really-really-mean-it”我真要这么干”(双重确认)删池的最高级确认,两个 really
--force跳过普通确认常规操作的安全确认

命令层级——越靠左越宏观,越靠右越具体:

Terminal window
ceph --> 集群层(管一切)
ceph osd --> OSD 层(管池、管 PG、管 CRUSH)
ceph osd pool --> 池层(管大小、管副本、管类型)
ceph config --> 配置层(管参数、管开关)
层面命令入口管的视角
OSD 数据层ceph osd ...CRUSH 地图、OSD 状态、池属性、PG 状态CRUSH 全局视角——“数据该往哪放”
配置管理层ceph config ...集中化配置数据库、参数读写Monitor 视角——“集群怎么跑”
Dashboard 层ceph dashboard ...Web 管理界面、用户权限图形化视角——“不想敲命令时用它”

存储池概述#

池(Pool)是个啥?#

🧱 池是 Ceph 里存储数据的逻辑分区,你可以把它理解成一个”命名空间”

  • 不同的业务(RBD 块存储、CephFS 文件系统、RGW 对象存储)各自用各自的池,井水不犯河水
池的核心作用大白话解释
逻辑分区给不同应用划地盘,互不干扰
数据保护指定==副本数==或==纠删码==,决定数据能坏几块盘还不丢
CRUSH 规则绑一条 CRUSH 规则控制数据分布
比如限定故障域或 OSD 的 class 标签(ssd/hdd/nvme)
访问控制权限按==池==粒度划分
Monitor 发证,OSD 验票,限定谁能读写这个池
快照管理对整个池做快照,出事了能回滚

数据存储流程对比#

我们最熟悉的是副本池的流程(参考之前的笔记📚),先用它过一遍,再对照看纠删码池

🔹 副本池流程(复习)—— 以 3 副本为例:

Terminal window
┌──────────────────────────────────────────┐
Step 1:文件 切成固定 4MB 对象
100MB 照片
┌──────┐┌──────┐┌──────┐ ┌──────┐
4MB ││ 4MB ││ 4MB ... 4MB
obj1 ││ obj2 ││ obj3 ×25 obj25│
└──────┘└──────┘└──────┘ └──────┘
'每个对象固定 4MB,不够就补齐'
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
Step 2:对象→Pool→命中某个 PG
"对象名" + CRUSH Map ──→ PG.7
'CRUSH①:决定对象归哪个 PG'
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
Step 3:PG CRUSH 再算 副本落盘
PG.7(size=3,要放 3 份)
'CRUSH②:决定副本落哪几块盘'
├─→ 副本① osd.1(host A)
├─→ 副本② osd.4(host B)
└─→ 副本③ osd.7(host C)
⚠️ (故障域 = host)
obj1 3 个副本,落在 3 台不同主机上
'读的时候随便找一个副本就能拿到完整数据'
└───────────────────────────────────────────┘

📌 副本池的本质:一份数据原样 copy 好几份,写的时候多写几遍,读的时候读最近的那份就行


🔹 纠删码池流程 —— 以 6+3 为例:

Terminal window
'前面两步一模一样,差异在第三步'
┌──────────────────────────────────────────────┐
Step 3:PG 编码切块 分散落盘
PG.7 收到 obj1(4MB 对象)
'不是直接 copy,而是先编码'
4MB 对象切成 6 个数据块
├─→ 数据块①
├─→ 数据块②
├─→ 数据块③ k = 6 个数据块
├─→ 数据块④
├─→ 数据块⑤
└─→ 数据块⑥
'根据 6 个数据块算出 3 个校验块'
├─→ 校验块⑦
├─→ 校验块⑧ m = 3 个校验块
└─→ 校验块⑨
'CRUSH②:9 个块分散到 9 块盘上'
├─→ 块① osd.1 ├─→ 块⑥ osd.6
├─→ 块② osd.2 ├─→ 块⑦ osd.7
├─→ 块③ osd.3 ├─→ 块⑧ osd.8
├─→ 块④ osd.4 ├─→ 块⑨ osd.9
└─→ 块⑤ osd.5
总共 k+m = 9 个块,散落在 9 块不同的盘上
⚠️ 如果故障域是 host 需要 9 台主机!
如果故障域是 osd 9 块盘可以都在同一台主机上
'只要任意 6 块还在,数据就能算回来'
└──────────────────────────────────────────────┘

📌 纠删码池的本质:数据不存整份,而是切成块 + 算出校验块,散开到更多盘上

  • 用 CPU + I/O 换空间
    • 具体差多少?往下看对比表格

🔹 读写路径对比 —— 关键差异一目了然:

Terminal window
🌰写路径:
副本池(3副本) 纠删码池(6+3)
obj1 ──→ copy 3 obj1 ──→ 切成6块+算3块
直接写 3 块盘 编码后写 9 块盘
'写 3 次,简单粗暴' 'CPU 编码开销 + 写 9 次 I/O'
写放大:3x 写放大:1.5x
'4MB 对象占 12MB 磁盘' '4MB 对象只占 6MB 磁盘'
=====================================================
🌰读路径:
副本池(3副本) 纠删码池(6+3)
需要数据 ──→ 读最近的 1 个副本 需要数据 ──→ 读任意 6
拿到完整数据 CPU 解码拼回数据
'读 1 次,秒返回' '读 6 次 I/O + CPU 解码'
延迟:低 延迟:高

存储池的两种类型#

类型英文名称原理类比
==副本池==replicated数据==完整复制==多份,每个副本放在不同 OSD 上RAID1(多副本)
==纠删码池==erasure数据切成 k 个==数据块== + 算出 m 个==校验块==
共 k+m 个块,散落在不同盘上
RAID5(校验码)

通俗解释

  • 副本池就是”一式三份”——同一份数据 copy 到三块盘上,简单粗暴,坏两块盘都不怕
    • 缺点是废空间,3 副本 = 实际可用只有 1/3 的容量
  • 纠删码池像*“拼图+备用块”*——把数据切成 6 个数据块,再算 3 个校验块,总共 9 个块散落在 9 块盘上
    • 只要任意 6 块还在就能恢复完整数据,比副本省空间多了
对比维度副本池纠删码池
存储利用率低(3 副本 = 1/3)高(6+3 = 2/3)
CPU 开销高(需要编码&解码运算)
I/O 延迟较高(要读多个块才能拼回数据)
典型场景RBD 块设备、高性能场景RGW 对象存储、冷数据归档
最多能坏几块盘size-1 块(3副本最多坏2块)任意 m 块(6+3 最多坏 3 块)
6是数据块(k), 3是校验块(m)

📌 生产环境推荐用副本池,除非你对容量极度敏感且能接受性能损耗


PG 概述#

什么是PG#

Ceph 存数据的过程:对象 → Pool → PG → OSD

💡 OSD 是什么? OSD 本质上是一个进程 + 一块盘

说 osd.0 就是指 /dev/sda 上的那个守护进程,说”数据写到 osd.3”就是写到 osd.3 背后的那块物理盘上

后面讲的 peering、backfill、磁盘 I/O,都是在说 OSD 进程在操作它背后的那块盘

Terminal window
Object(对象) --CRUSH①--> Pool 下的某个 PG --CRUSH②--> OSD 集合

📌 CRUSH 在数据落地过程中用了两次

  • 第一次负责逻辑分组(对象归哪个 PG)
  • 第二次负责数据落盘(PG 的副本落哪几块盘)

🧱 Pool 和 PG 的关系?

Pool 是 PG 的容器——一个 Pool 下挂着若干个 PG,PG 是 Pool 内部数据分布的最小单位

  • 对象先命中某个 Pool,再由 CRUSH 哈希到该 Pool 下的某个 PG,最终落盘到 OSD

📌 PG 的数量远小于对象的数量——这才是 PG 存在的意义

一个 PG 里可以存放成千上万个对象

Terminal window
PG.7(一个 PG)
├── obj1(4MB)
├── obj8(4MB)
├── obj15(4MB)
├── ...(成千上万个对象)
└── objN(4MB)
====================================
一个 Pool 里的数量对比:
对象:几百万个(甚至上亿) 海量
'CRUSH 哈希收敛'
PG:几百个(通常 32 ~ 1024) 少量
'CRUSH 再计算'
OSD:几十块盘 更少
  • PG 做的就是聚合收敛——把海量对象哈希到少量 PG 中,规模从百万级降到千级

  • 迁移时以 PG 为单位搬——一次搬”一筐对象”,而不是一个一个搬

    • 加减 OSD 时也只迁移受影响的 PG

PG 数量#

📌 ==官方公式==:

Terminal window
OSD 数量 × X
PG = ---------------
pool size(副本数)
X = 每块 OSD 期望承载的 PG 数量,官方推荐 100 左右

🧱 这个公式到底在算什么?

核心逻辑:先定每块 OSD 背多少个 PG 合理,再反推池里该建多少个 PG

Terminal window
# PG 均匀散落在 OSD 上:
PG 总数 × size
每块 OSD 背的 PG = ---------------
OSD 数量
# 反过来,已知每 OSD 期望背 X 个 PG,求 PG 总数:
OSD 数量 × X
PG 总数 = ---------------
size

PG 总数太多还是太少?

PG 总数后果
太少数据分布不均,个别 OSD 成为”热点”,忙的忙死闲的闲死
太多PG 元数据膨胀,peering(互相同步状态) / scrub (校验数据一致性)开销暴增,CPU 和内存吃紧
  • 公式里塞 X=100 就是为了让 PG 总数落在适中区间

  • Ceph 的 mon_max_pg_per_osd 默认上限是 250

  • 算是一种硬保护,防止 PG 总数失控

回到公式——代入算一下

Terminal window
示例①:9 OSD,3 副本
9 × 100
PG = --------- = 300 取最近的 2 次方 256
3
'验证:256 × 3 / 9 = 每 OSD 约 85 个 PG'
示例②:200 OSD,3 副本
200 × 100
PG = ----------- 6666 取最近的 2 次方
3
2^12 = 4096 2570
2^13 = 8192 1526(更近)
集群 PG 总量取 2^13 = 8192 比较合理
'验证:8192 × 3 / 200 = 每 OSD 约 123 个 PG,仍在合理范围'

💡 结果取最近的 2 的幂(方便数据均匀分布)

算完后顺手验一下:PG总数 × size ÷ OSD数 是否在 100~250 之间


size VS min_size#

这两个参数是副本池容错的核心

参数含义生产推荐值
size
==副本数==
数据一共存几份(包含原始那份)≥ 3
min_size
==与最小副本数==
I/O 服务需要的最少可用副本数size - 1(如 3 副本时设为 2)

工作机制

  • 集群正常时,所有 size 个 OSD 上的数据一致
  • 坏一块盘,剩余副本 ≥ min_size → I/O 照常跑
  • 剩余副本 < min_size → 池暂停 I/O 或只读,优先保数据一致性,宁可停服也不丢数据

💡 这就是 Ceph 的”宁死不屈”机制——数据安全比服务可用性更重要

Terminal window
🌰实战:把 3 副本改成 5 副本,同时提高 min_size
1)查看PG状态
root@Ceph-201 ~# ceph pg stat
1 pgs: 1 active+clean; 449 KiB data, 284 MiB used, 5.3 TiB / 5.3 TiB avail
root@Ceph-201 ~# ceph pg dump
'所有 PG 详细状态'
version 1287
stamp 2026-05-26T03:38:21.766113+0000
last_pg_scan 0
................
2)查看默认池现有规则
root@Ceph-201 ~# ceph osd pool ls detail
pool 1 '.mgr' replicated size 3 min_size 2
'可以查看指定的参数' # get 池子 key
root@Ceph-201 ~# ceph osd pool get .mgr size
size: 3
root@Ceph-201 ~# ceph osd pool get .mgr min_size
min_size: 2
3)修改规则
root@Ceph-201 ~# ceph osd pool get .mgr pg_autoscale_mode
pg_autoscale_mode: on
'如果开着 autoscale_mode,系统可能在你手动改完 pg_num 后立刻又给调回去'
# 我们在后面存储池管理中详细介绍这个选项
root@Ceph-201 ~# ceph osd pool set .mgr size 5
set pool 1 size to 5
root@Ceph-201 ~# ceph osd pool set .mgr min_size 3
set pool 1 min_size to 3
root@Ceph-201 ~# ceph osd pool ls detail
pool 1 '.mgr' replicated size 5 min_size 3 crush_rule 0
# 改成 5 副本后可以容忍任意 2 块盘故障(5-3=2),但代价是容量利用率更低

Peering 与 Backfill 详解#

Peering —— PG 状态协商#

🧱 前置概念:acting set 与 up set

在理解 peering 之前,先搞清楚 PG 里的 OSD 是怎么组织的

CRUSH 算法为每个 PG 算出一个 OSD 列表,指明该 PG 的副本应该落在哪几块盘上——这个列表就是 acting set

🌰 比如 PG.7 的 acting set = [OSD.0, OSD.1, OSD.2],意思是这个 PG 的 3 个副本(size=3)应分别存放在 OSD.0、OSD.1、OSD.2 三块盘上

🧱 主 OSD(Primary)

acting set 中的第一个 OSD 被指定为 主 OSD(Primary),其余为副本 OSD

角色干什么
主 OSDacting set 的第一个接收客户端读写请求、将写操作同步到副本、驱动 peering / recovery / backfill
副本 OSDacting set 的其余位置被动响应主 OSD 指令,同步数据、响应 log 查询

🌰 PG.7 的 acting set = [OSD.0, OSD.1, OSD.2] → OSD.0 是主,OSD.1 / OSD.2 是副本

正常情况下,还有一个 up set(当前实际在干活的 OSD 列表),两者保持一致:up set = acting set

如果某个 OSD 挂了,Monitor 会临时指派替代者,此时 up set 和 acting set 就不一致了(即后文的”临时 PG”机制)

概念含义一句话
acting setCRUSH 算出的目标 OSD 集合应该在哪”
up set当前实际在干活的 OSD 集合实际在哪”

🧱 Peering 是什么?

PG 的 acting set 里的 OSD 之间互相沟通、协商状态,达成共识——谁有最新数据、谁落后了、日志进度对齐到哪了

Tip

⚠️ 注意:PG 本身是逻辑实体,不干活

peering 的实际执行者是 acting set 里的 OSD 进程,==由主 OSD 牵头==、副本 OSD 响应——本质上就是这几个 OSD 在替这个 PG “对账”

📌 通俗理解:peering 就像三个副本”开会”

  • “你到哪了?我写到 log 第 100 条了""我才到 95,等我补一下”
  • 先把状态对齐,再决定下一步动作

什么时候会触发 peering?

触发场景说明
OSD 挂了又恢复它上面的 PG 落后了,需要和同伴对账
PG 数量变化pg_num / pgp_num 变了,PG 哈希边界重划,全部 PG 重新 peering
OSD 增删CRUSH 重新分配 PG 到不同 OSD
集群重启所有 PG 从零开始协商状态

Peering 的过程(简化版)

💡 一句话:说”PG.7 在 peering”和”主 OSD 在替 PG.7 peering”是同一件事

PG 是逻辑实体不干活,peering 由 acting set 里的 OSD 进程实际执行

Terminal window
PG.7 acting set = [OSD.0, OSD.1, OSD.2]
OSD.0 = OSD(Primary)
其余 OSD 为副本 OSD,只被动响应主 OSD 的指令
═══════════════════════════════════════
Step 1: '主 OSD' 发起 peering 请求
┌─────────────────────────────────────┐
OSD.0 (Primary) │
PG.7 peering 报一下你们的
PG Log 最后一条序号
├──────→ OSD.1 ──→ 回复: log #100 │
└──────→ OSD.2 ──→ 回复: log #98 │
└─────────────────────────────────────┘
Step 2: 确定权威日志(Authoritative Log)
┌─────────────────────────────────────┐
Primary 对比三份 log:
OSD.0: #100 (自己就是最新的) │
OSD.1: #100 ✅ 一致 │
OSD.2: #98 ❌ 落后 2 条 │
权威日志 = OSD.0 log
原则:挑最完整的一份
⚠️ 前提:被选中的 log 必须连续、
且属于当前 PG epoch——防止网络分区后
旧主带着"过期最长 log"回来造成脑裂
└─────────────────────────────────────┘
Step 3: 状态判定——该走哪条恢复路径?
┌─────────────────────────────────────┐
OSD.2 只差 2 log
recovery(增量恢复)
OSD.2 回放缺失的 log 条目即可
如果 OSD.2 整个 PG 目录都丢了
backfill(全量回填)
└─────────────────────────────────────┘

📌 peering 本身不搬数据,只是协商状态 + 决定恢复策略

数据搬运是 recovery 或 backfill 的事

🧱 PG Log vs 实际数据

peering 过程中反复提到的”PG Log”到底是什么?跟用户存的数据是一回事吗?

Terminal window
PG Log(操作日志) 实际数据(对象内容)
───────────────────────── ─────────────────────
记录"发生过什么修改操作"(写/删/改/克隆等) 用户存的东西本身
比如: 比如:
#98 write obj15 obj15 = 4MB(照片的第 3 个分片)
#99 delete obj8 obj1 = 4MB(文档的第 1 个分片)
#100 modify obj3 obj3 = 4MB(视频的第 5 个分片)
像一个"记账本" 像一个"仓库"
peering 对账本 轻量,秒级完成 scrubbing 翻仓库逐件盘点 重,费 I/O

📌 这就是为什么 peering 能几百个 PG 同时做(只对日志条目,几乎不碰磁盘)

而 backfill / recovery 要限流(搬实际数据),scrubbing 也要限速(逐字节读副本比对,同样是重 I/O)

为什么 peering 多了会”风暴”?

每个 PG peering 时,acting set 里的 OSD 要来回发消息

关键前提:一块 OSD 上托管着很多 PG(按官方推荐 ~100 个),每个 PG 的 acting set 都可能包含这块 OSD

Terminal window
1 PG peering:
只有这 1 PG acting set 里那几块 OSD 在通信 轻量,秒级完成
100 PG 同时 peering:
每块 OSD 上托管着 ~100 PG,这 100 PG peering 砸过来,
一块 OSD 可能同时卷入几十个 PG 的协商:
OSD 进程的消息队列堆成山
Monitor 心跳超时
PG 被标记为 down / stale(误伤!)

这就是前面说的 peering 风暴——不是 peering 本身开销大,而是几百个 PG 同时 peering 时,OSD 的消息处理能力被打穿


Backfill —— 全量数据回填#

🧱 Backfill 是什么?

当某个 OSD 上整个 PG 的数据需要从头同步时,Ceph 不走逐条 log 回放(recovery),而是直接扫描并全量拷贝 PG 的所有对象——这就是 backfill

  • recovery = 差几条 log,逐条追

  • backfill = 整个 PG 都要搬,全量拷

什么时候走 backfill 而不是 recovery?

场景走哪条路原因
OSD 短暂挂了又回来,只差几条 logrecovery增量补就行
新 OSD 加入集群,上面啥数据都没有backfill全量搬
PG 扩容,PG 被分配到之前未托管过它的 OSDbackfill该 OSD 上没有这个 PG 的存量数据,只能全量搬
OSD 永久替换(盘坏了换了块新的)backfill从零开始

Backfill 的过程

和 peering 一样,backfill 也是由主 OSD 驱动的——主 OSD 扫描 ==该PG== 落在自己盘上的所有对象,全量推送给目标 OSD

Terminal window
场景:OSD.3 是新加入的盘,PG.7 CRUSH 分配到了它上面
PG.7 acting set = [0, 1, 2] OSD.3 加入后 [0, 1, 3]
┌──────────────────────────────────────────────┐
OSD (OSD.0) │
PG.7 目录:
├── obj1 (4MB) │
├── obj8 (4MB) │
├── obj15 (4MB) │
└── ... (共 10000 个对象,约 40GB) │
└──────────┬───────────────────────────────────┘
Backfill:全量顺序扫描 & 推送
┌──────────────────────────────────────────────┐
OSD.3 (新盘,PG 目录为空) │
backfill 进度:
████████████░░░░░░░░ 67% (6.7K / 10K obj) │
磁盘写 I/O 持续拉满
└──────────────────────────────────────────────┘
同时,OSD.2 上的旧副本被标记为"待清理"(PG 成员变了)

为什么 backfill 不能太多并发?

先理解一个前提:backfill 的每一步——从源 OSD 读对象、写到目标 OSD——本质上都是磁盘顺序 I/O

  • 这里的磁盘,就是指 OSD 背后的那块物理盘
Terminal window
🌰 单个 PG backfill 时(比如 PG.7):
OSD PG.7 的对象在磁盘上是连续存放的
磁头从 A 位置一路扫到 B 位置,一口气读完
这是"顺序读"——磁头几乎不用跳,速度极快

一块盘上托管着几十上百个 PG,它们的对象各自占据不同的物理区域

多个 PG 同时 backfill 时:

Terminal window
50 PG 同时 backfill 在同一块盘上:
磁盘被要求同时服务 PG.1、PG.7、PG.3... 的数据
原本每个 PG 都是"一口气读完"的顺序 I/O,
现在被搅在一起,磁头在不同 PG 的区域之间反复横跳
顺序 I/O 退化成随机 I/O
大量时间浪费在"寻道"上,实际读数据的时间占比暴跌
吞吐量断崖式下跌,业务读写也被挤占

📌 核心:一块盘同一时间只做一件事(读或写某个 PG 的数据)效率最高,让它同时干好几件,磁头来回跳,总产出反而骤降


Peering → Recovery → Backfill 关系图#

Terminal window
OSD 挂掉 / PG 变化 / 集群事件
┌─────────┐
Peering 先协商,搞清楚"谁有、谁缺、缺多少"
└────┬────┘
PG Log 差得少?──── ──→ Recovery(增量回放 log)
恢复完成 active+clean
Backfill(全量扫描 & 拷贝对象)
'扫描 = 主 OSD 读自己的盘'
'拷贝 = 写到目标 OSD 的盘'
恢复完成 active+clean

📌 一句话:peering 是”对账”,recovery 是”打补丁”,backfill 是”重装系统”。


PGP 是什么#

PGP = Placement Group for Placement,即”用于数据放置的 PG 数量”

🧱 pg_num 和 pgp_num 的区别

参数干什么的通俗理解
pg_num池里创建多少个 PG池里有多少个”调度组”
pgp_num多少个 PG 参与数据分布有多少个调度组实际在干活

📌 pgp_num ≤ pg_num,通常两者保持相等


🧱 为什么需要 pgp_num?——安全扩容的”调速阀门”

  • 如果把 pg_num 和 pgp_num 同时拉满,集群瞬间要对所有已有数据重新分布
    • 全部 PG 同时 peering,==新PG== 集中 backfill,I/O 直接被打穿

pgp_num 就是调速阀门:pg_num 决定有多少个 PG 存在,pgp_num 决定其中多少个真正在干活

安全扩容三步走:

Terminal window
1) 扩大 pg_num → 只创建新 PG 的数据结构,不实际迁移数据
2) 逐步调大 pgp_num → 每次只搬迁一部分 PG,集群平稳过渡
3) pgp_num 对齐 pg_num → 全部 PG 正常参与数据分布

📌 pgp_num 分步的本质是”限流”——让 PG 分批 peering + backfill,而非全部 PG 同时搅动

最终搬的数据总量差不多,但每批只扰动一部分 PG,集群始终保持可服务状态


🧱 为什么分步调能奏效?——回头看 peering 和 backfill

维度peering 风暴backfill 并发
瓶颈在哪OSD 消息队列 / CPU磁盘 I/O 带宽
什么感觉PG 假死(被误标 down/stale)业务 I/O 卡顿、延迟飙升
怎么控pgp_num 分步,减少同时 peering 的 PG 数pgp_num 分步 + osd_max_backfills 限速

💡 Ceph 默认 osd_max_backfills = 1(一次只回填 1 个 PG),就是怕 backfill 把磁盘打穿


⚠️ 生产环境pg_numpgp_num 最终必须等齐,否则新 PG 不参与数据放置

但不要一次同步拉满——先调 pg_num,再逐步放大 pgp_num,每步确认集群 active+clean 后再继续

Terminal window
root@Ceph-201 ~# ceph osd pool get .mgr pg_num
pg_num: 1
root@Ceph-201 ~# ceph osd pool get .mgr pgp_num
pgp_num: 1
'两者通常保持相等'
✅️ 使用 set 进行调整

临时PG#

主 OSD 挂了怎么办❓️

CRUSH 会重新算 acting set,但 ==新主OSD== 上还没数据——此时需要一个==过渡机制==,这就是临时 PG

概念谁定的什么时候变一句话
acting setCRUSH 计算PG 数变化、OSD 增删应该在哪”
up setMonitor 根据 OSD 存活状态实时调整OSD 挂掉/恢复实际在哪”

📌 正常情况 acting set = up set

当主 OSD 挂了,acting set 里换了新人但新人还没数据,up set 就让有数据的老人先顶班

acting set 和 up set 暂时不一致,这就是临时 PG

Terminal window
正常状态:
PG.7 acting set = [0, 1, 2]
up set = [0, 1, 2] acting set 一致
OSD.0 = OSD
────────────────────────────────────────
Step 1:OSD.0 故障
────────────────────────────────────────
CRUSH 重新计算 acting set = [3, 1, 2]
OSD.3 被推举为新主 OSD,但盘上空空,还不能接读请求
────────────────────────────────────────
Step 2:申请临时 PG
────────────────────────────────────────
PG Monitor 申请过渡方案
OSD.1(原副本,有最新数据)升任"临时主 OSD"
up set = [1, 3, 2] '临时干活阵容'
acting set = [3, 1, 2] CRUSH 的目标阵容(不变)
⚠️ acting set up set(过渡期不一致)
────────────────────────────────────────
Step 3:backfill 回填数据
────────────────────────────────────────
临时主 OSD.1 PG.7 数据全量推给 OSD.3
────────────────────────────────────────
Step 4:恢复正常
────────────────────────────────────────
OSD.3 数据同步完毕 临时 PG 取消
up set 恢复 = acting set = [3, 1, 2]
OSD.3 正式就任新主 OSD

PG 状态#

PG 状态是判断集群数据分布是否健康的关键指标

日常只需重点关注 active + clean,其余都是过渡状态。

状态含义归类
active能正常处理读写✅ 理想
clean所有副本齐全且内容一致
—> 没有缺失和待修复的副本
✅ 理想
Tip

上面两个同时出现(active+clean)= 一切正常

状态含义归类
peeringOSD 之间对 PG Log,协商谁最新谁落后 → 决定恢复策略
—> 对的是操作日志,不是数据本身
==对账==
recovering逐条回放 PG Log,差多少补多少 → “打补丁”==增量恢复==
backfill全量扫描该 PG 对象,从头拷贝到新 OSD → “重装系统”==全量恢复==
wait-backfill排队等 backfill(受 osd_max_backfills 限制)
—> 默认一次只回填 1 个 PG
限流
backfill-toofull目标 OSD 使用率超阈值,backfill 挂起⚠️ 阻塞

peering → 决定走 recovering 还是 backfill → ✅️ 完成 → active+clean

状态含义归类
remappedacting set ❌️≠❌️ up set,PG 正由临时阵容代管 → ==临时 PG==🔄过渡
creatingPG 正在创建一次性
splittingPG 数量扩容,正在分裂一次性
replayOSD 崩溃后,PG 在等待客户端重放未确认操作🔄过渡
状态含义归类
scrubbing逐字节比对副本的==实际数据==,发现静默损坏(bit rot)
—> peering 是对 PG Log,scrub 是对数据本身
后台巡检
repairscrubbing 发现不一致 → 用正确副本覆盖损坏副本后台修复

异常 / 降级状态

状态含义
degraded部分副本挂掉或落后,但剩余副本 ≥ min_size,还能接 I/O
undersized当前可用副本数少于 size,但 ≥ min_size
down该 PG 必要的数据副本全部不可达,PG 下线
incompletePG 缺少关键信息(如日志断层),无法判断数据是否安全
inconsistentscrubbing 检测到副本间实际数据不一致 → 触发 repair
stalePG 所在 OSD 长时间没向 Monitor 报心跳,Monitor 不知道它什么状态
inactivePG 不能处理读写,等待持有最新数据的 OSD 回来
unclean有对象副本数不达标(与 clean 相反),通常正在恢复中
peeredpeering 已完成(状态协商好了),但副本还没补够,暂不接客
Important

遇到 PG 异常的常规思路

  1. 重启相关 OSD 服务
  2. 调整属性参数
  3. 重置 PG

存储池管理#

Terminal window
1)创建副本存储池(默认类型)
root@Ceph-201 ~# ceph osd pool create xixi replicated
pool 'xixi' created
⚠️ '默认不指定池子类型 --> 就是副本池' --> replicated
2)创建纠删码存储池
root@Ceph-201 ~# ceph osd pool create haha erasure
pool 'haha' created
3)查看存储池列表
root@Ceph-201 ~# ceph osd pool ls
.mgr
xixi <-- ✅️ 副本池
haha <-- ✅️ 纠删池
👆 '这两个是我们刚创建的'
# 我们再加一个选项 detail
root@Ceph-201 ~# ceph osd pool ls detail
'查看存储池详细信息🔍'
pool 1 '.mgr' replicated size 3 min_size 2 crush_rule 0 📌 'crush规则0'
pool 2 'xixi' replicated size 3 min_size 2 crush_rule 0 📌 'crush规则0'
pool 3 'haha' erasure profile default size 4 min_size 3 crush_rule 1 📌 '规则1'
==========================================================
root@Ceph-201 ~# ceph osd crush rule ls
"有哪些规则" --> 📌 只列出名字
replicated_rule
erasure-code
'很明显一个是副本池默认的crush规则, 另一个是纠删码池的默认crush规则'
# 创建crush规则参考之前的笔记📚
🌰 副本规则 `create-replicated`
🌰 纠删码规则 `create-erasure`
✅️ ceph osd crush rule dump <规则名>
"这条规则内部长什么样" --> 📌 完整 JSON
# 查看故障域详细的规则规则
✅️ ceph osd pool set <存储池名称> <参数名> <参数值>
# 关联存储池到新规则
4)查看创建池子的pg和pgp数
✅️ '查看单个池的指定属性'
'默认相同' --> 32 = 2的5次方
# Ceph 会根据集群 OSD 数量和池的用量,自动计算并动态调整 PG 数量
📌 我们创建池子的时候,并没有指定pg数 ❌️ --> 生产环境一定要指定
root@Ceph-201 ~# ceph osd pool get xixi pg_num
pg_num: 32
root@Ceph-201 ~# ceph osd pool get xixi pgp_num
pgp_num: 32
root@Ceph-201 ~# ceph osd pool get haha pg_num
pg_num: 32
root@Ceph-201 ~# ceph osd pool get haha pgp_num
pgp_num: 32
命令查看维度一句话
rados df”每个池用了多少、剩多少,按池算账”
ceph osd dfOSD 设备”每块盘用了多少、剩多少,按盘摸底”
Terminal window
5)查看存储池利用率
root@Ceph-201 ~# rados df
POOL_NAME USED OBJECTS CLONES COPIES ....
.mgr 1.3 MiB 2 0 6 ....
haha 0 B 0 0 0 ....
kpyun 0 B 0 0 0 ....
xixi 0 B 0 0 0 ....
'📌 重点在下面的统计'
total_objects 2
total_used 285 MiB
total_avail 5.3 TiB
total_space 5.3 TiB
root@Ceph-201 ~# ceph osd df
ID CLASS WEIGHT REWEIGHT SIZE AVAIL %USE PGS STATUS
0 hdd 0.293 1.000 300 GiB 300 GiB 0.01 44 up
1 hdd 0.488 1.000 500 GiB 500 GiB 0.01 58 up
...........
6)重命名存储池
root@Ceph-201 ~# ceph osd pool rename haha hehe
pool 'haha' renamed to 'hehe'
root@Ceph-201 ~# ceph osd pool ls | grep hehe | wc -l
1
Terminal window
7)创建时指定 PG 数量和关闭自动伸缩
root@Ceph-201 ~# ceph osd pool get .mgr pg_autoscale_mode
pg_autoscale_mode: on
'系统池这个选项是开着的 --> 系统可能在你手动改完 pg_num 后立刻又给调回去'
root@Ceph-201 ~# ceph osd pool create kpyun 128 128 --autoscale_mode off
✅️ 128 128 = pg_num 128, pgp_num 128

📌 自动伸缩(pg_autoscale_mode)是什么?

Ceph 会根据集群 OSD 数量和池的用量,自动计算并动态调整 PG 数量

如果开着 autoscale,系统可能在你手动改完 pg_num 后立刻又给调回去


为什么创建时关掉它? 既然你手动指定了 128 个 PG,就说明你算好了PG数量了

  • --autoscale_mode off 告诉 Ceph “PG 数量我来定,你别插手”

同理,后续用 set 修改 pg_num 前也需要先关 autoscale

Terminal window
'我在创建这个池子的时候,默认不指定池的类型 --> 副本池'
root@Ceph-201 ~# ceph osd pool ls detail | grep kpyun
pool 4 'kpyun' replicated size 3 min_size 2 crush_rule 0
root@Ceph-201 ~# ceph osd pool get kpyun pg_num
pg_num: 128
root@Ceph-201 ~# ceph osd pool get kpyun pgp_num
pgp_num: 128
'这次都是128 --> 而不是32'

📌 Ceph 的逻辑:⚠️ 创建一个池之后务必声明它的用途

否则 Monitor 不知道这个池是存 RBD 镜像还是当 CephFS 元数据池,持续报 HEALTH_WARN ❌️

类型业务一句话
rbd==块存储==“这池子给虚拟机/云盘用的”
cephfs==文件系统==“这池子给共享文件存储用的”
rgw==对象存储==“这池子给 S3 / Swift 对象网关用的”
Terminal window
root@Ceph-201 ~# ceph -s | grep -A2 health
health: HEALTH_WARN ❌️
Degraded data redundancy: 6 pgs undersized
3 pool(s) do not have an application enabled
📌 集群里有 3 个池子还没声明"我是干啥用的"
1)声明用途
✅️ ceph osd pool application enable <池名> <类型>
root@Ceph-201 ~# ceph osd pool application enable kpyun rbd
2)查看已声明的用途
✅️ ceph osd pool application get <池名>
root@Ceph-201 ~# ceph osd pool application get kpyun
{
"rbd": {}
}

删除存储池的两道锁#

Ceph 为了保护数据不被人手滑删掉,设计了两道锁:

Terminal window
机制一:nodelete 标记(池级锁)
'某个存储池'打上 nodelete=true 该池不可删除 ❌️
'默认值':false(可删除)✅️
机制二:mon_allow_pool_delete 全局开关(集群级锁)
Monitor 级别的总闸,📌'控制整个集群是否允许删池'
'默认值':false(不允许删除)❌️
⚠️ 两道锁都有一票否决权 --> 任一不通过都不能删池
允许删除的条件默认值默认能删吗
nodelete(池级)falsefalse✅ 能
mon_allow_pool_delete(集群级)truefalse❌ 不能

📌 实际删池时,nodelete 默认就是 false(没上锁),真正卡住你的是全局开关 mon_allow_pool_delete

  • 所以实验里只需要翻这一道开关就够了
    • 不是只开了一个就能删,而是另一个本来就没关
  • 📌 生产环境建议nodelete=true + mon_allow_pool_delete=false
    • 双重保险,防止手滑

ceph config 方式删除(推荐)#

Terminal window
'删除池的完整流程 —— ceph config 版'
1)强制删除试试
# 由于这是一个高风险操作,Ceph要求您提供更强的确认
1.需要输入两次存储池名称(xixi xixi)
2.使用 --yes-i-really-really-mean-it 参数
# 两次really强确认
root@Ceph-201 ~# ceph osd pool rm xixi xixi --yes-i-really-really-mean-it
Error EPERM: pool deletion is disabled; --> '删除失败' ❌️
"在删除存储池之前,您必须先将mon_allow_pool_delete配置选项设置为true"
2)检查 nodelete 标记
root@Ceph-201 ~# ceph osd pool get xixi nodelete
nodelete: false
'池级锁默认false --> 可以删除'
3)在 monitor 和 global 级别都开启允许删除
'global = 所有守护进程(mon/osd/mgr/mds/client),mon = 仅 Monitor'
# 实际上:设了 global,就完全不需要再设 mon
✅️ 老运维只认 mon, 后来 global 出现了,有些人就"两条都写上,求个心安"
root@Ceph-201 ~# ceph config set mon mon_allow_pool_delete true
root@Ceph-201 ~# ceph config set global mon_allow_pool_delete true
4)确认开关已生效
root@Ceph-201 ~# ceph config get mon mon_allow_pool_delete
true
root@Ceph-201 ~# ceph config get global mon_allow_pool_delete
Error EINVAL: unrecognized entity 'global'
'这是为什么??'
# global 不能用 get 查(不是具体守护进程类型),用 dump 来看
root@Ceph-201 ~# ceph config dump | grep mon_allow_pool_delete
ceph config dump # 导出所有配置项
global mon_allow_pool_delete true
mon mon_allow_pool_delete true
'global 和 mon 都 true,确认生效'
5)执行删除
root@Ceph-201 ~# ceph osd pool rm xixi xixi --yes-i-really-really-mean-it
pool 'xixi' removed
root@Ceph-201 ~# ceph osd pool ls | grep xixi | wc -l
0
6)安全收尾——关掉开关
root@Ceph-201 ~# ceph config set mon mon_allow_pool_delete false
root@Ceph-201 ~# ceph config set global mon_allow_pool_delete false

ceph config 配置管理#

Ceph 从 Squid 版本开始,引入了集中化配置数据库(Configuration Database),ceph config 命令是统一入口

传统 ceph.conf vs 配置数据库#

Terminal window
传统方式:'分散管理,一致性难保证'
1.N 个节点各存一份 `ceph.conf`
2.改配置 = 挨个 SSH 改文件,漏一台就不一致
---------------------------------------------
现代方式(Config DB):📌'Monitor 集中存储'
1.Monitor 内存着一份"配置总账"(存在 RocksDB 里)
2.你敲一条 `ceph config set` 写入总账,所有节点的守护进程自动拉取
3.一份数据,全集群读

💡 RocksDB 又是什么?

它是 Facebook 开源的一款嵌入式键值(Key-Value)数据库

非常轻量 —> 不需要单独部署服务,直接嵌在 Monitor 进程里跑,负责把==配置数据==持久化到磁盘上

Monitor 用它存两类东西:

  • ① 配置数据库(Config DB)

  • ② 集群 Map(OSD Map / PG Map / CRUSH Map 等)

说白了就是 Ceph 自己的”小账本”

优先级(由高到低):

① Config DB(ceph config set)→ ② ceph.conf 文件 → ③ 代码内置默认值

📌 最佳实践:日常运维优先用 ceph config 在线改,ceph.conf 仅作为静态补充离线批量配置

常用命令#

命令说明
ceph config dump导出所有配置项
常配合grep过滤
ceph config get <target> <option>查配置——<target>
可以是类型级或实例级
ceph config set <target> <option> <val>设配置——<target>
可以是类型级或实例级
ceph config rm <target> <option>删除配置(同上)
ceph config show <target> <option>查看某个进程实际生效的配置
合并全部来源,给出最终生效值
ceph config assimilate-conf -i ceph.conf把老 ceph.conf 导入配置数据库
粒度例子
类型级 —> 影响==一类守护进程==mon / osd / mgr
实例级 —> 精确到一个具体进程osd.0 / mon.Ceph-201
Tip

💡 get / set / rm<target> 可以是类型级(mon)也可以是实例级(mon.Ceph-201

  • show 通常跟实例级,看某个==具体进程==实际跑的是什么配置
Terminal window
💡 守护进程命名规则:`type.id`
osd.0 type.id
└── OSD 编号(Ceph 内部'守护进程编号',不是 Linux PID(重启会变))
└── 守护进程类型(mon / osd / mgr / mds / client)
`osd.0` = `osd` 类型的 `0` 号实例
📌 Monitor 用主机名当 ID(`mon.Ceph-201`),MDS Manager 同理
Important

📌 global 是==虚拟赋值层==

  • 可以往里写(set),但往里读(get)就报 unrecognized entity❌️

  • 验证 global 是否生效用 ceph config dump | grep

取值层级影响范围setget
global==全局====所有守护进程==❌,用 dump
mon类型所有 Monitor
osd类型所有 OSD
mgr类型所有 Manager
mds类型所有 MDS
client类型所有客户端
osd.0==实例==仅 osd.0 这一个进程
mon.Ceph-201==实例==仅 Ceph-201 上的 Monitor
Terminal window
'实操示例'
1)查看 monitor 级别是否允许删池
root@Ceph-201 ~# ceph config get mon mon_allow_pool_delete
false
2)设置 monitor 级别配置
root@Ceph-201 ~# ceph config set mon mon_allow_pool_delete true
3)查看mon.Ceph-201的所有配置
'这里已经具体到某台主机了'
root@Ceph-201 ~# ceph config show mon.Ceph-201
NAME ALUE
debug_mon 20/20
keyring $mon_data/keyring
log_to_file false
public_network 10.0.0.0/24
................
✅️ '后面也可以跟某个具体配置'
root@Ceph-201 ~# ceph config show mon.Ceph-201 public_network
10.0.0.0/24
4)global全局配置
root@Ceph-201 ~# ceph config get gobal public_network
Error EINVAL: unrecognized entity 'gobal' ❌️
'需要配置 👇'
root@Ceph-201 ~# ceph config dump | grep public_network
global advanced public_network 10.0.0.0/24

Dashboard 速览#

Dashboard 是 Ceph 自带的 Web 图形化管理界面(端口 8443),不想敲命令的时候用它

Tentacle(v20)换了新 UI —— 首页改叫 Overview,界面更现代

🔹 Tentacle 新版主要功能:

功能一句话
多集群管理一个页面管好几个 Ceph 集群,不用来回切
统一看健康状态、容量、告警
NVMe 高速存储网页上配 NVMe 盘、分命名空间
对象存储(RGW)多活同步、冷热分层、过期删除、权限策略,全在页面上点
文件共享(SMB)Linux 上的 CephFS 当作 Windows 共享文件夹用
性能监控看磁盘读写速度、延迟、带宽趋势
统一登录(OAuth2)对接公司已有的账号系统,不用单独记密码
配置管理改副本数、改 PG 数、换 CRUSH 规则,不用敲命令
角色权限(RBAC)管理员、只读、块存储管理员、对象存储管理员…各看各的
Tip

📌 Tentacle 附带的监控组件:Prometheus 3.6 + Grafana 12 + Alertmanager 0.28

💡 生产环境别忘了把 Dashboard 的自签名证书换成正规 CA 签发的证书

内置角色

角色能干啥一句话
administrator==全部权限==“超级管理员,什么都能动”
read-only只能看”参观者,点不坏任何东西”
block-managerRBD 块设备”管虚拟机云盘的”
rgw-manager对象网关”管 S3 存储桶的”
cephfs-manager文件系统”管共享目录的”
ceph dashboard 命令干什么
ac-user-create <用户名> -i <密码文件> <角色>创建用户
ac-user-show <用户名>查看用户信息
ac-user-set-password <用户名> -i <密码文件>修改密码
ac-user-set-roles <用户名> <角色>修改角色
ac-user-delete <用户名>删除用户
Terminal window
📌 复杂的操作上 Web 界面点,命令行记住👆上面 5 条够用了
'实例'
1)创建管理员用户 jiu,密码从文件读入
root@Ceph-201 ~# echo 'Redhat123.com' > /root/passwd.txt
⚠️ 防止 Password is too weak❌️ --> ✅️ '密码设置复杂一点'
root@Ceph-201 ~# ceph dashboard ac-user-create jiu -i /root/passwd.txt administrator
✅️ 刚创建的同时,把用户信息也打印出来了
{"username": "jiu", "password": "$2b$12$xn ...xxx", "roles": ["administrator"]

image-20260526094948461
image-20260526094948461

image-20260526095557741
image-20260526095557741

Terminal window
2)查看 admin 用户信息
root@Ceph-201 ~# ceph dashboard ac-user-show admin
✅️ 是admin用户呀!
{"username": "admin", "password": "$2b$12$Vq..xxx"
3)修改 jiu 的密码
root@Ceph-201 ~# echo 'Oldboy123.com' > /root/passwd.txt
root@Ceph-201 ~# ceph dashboard ac-user-set-password jiu -i /root/passwd.txt
✅️ 选项 --> ac-user-set-password
✅️ 后面没有角色, 只有一个密码文件📃
4)把 jiu 降级为只读
root@Ceph-201 ~# ceph dashboard ac-user-set-roles jiu read-only
✅️ 选项 & 更换的角色
{"username": "jiu", ...xxx "roles": ["read-only"],

image-20260526100311770
image-20260526100311770

Terminal window
5)删除 jiu
root@Ceph-201 ~# ceph dashboard ac-user-delete jiu
User 'jiu' deleted

image-20260526100420948
image-20260526100420948

Manager 的 Active / Standby 机制#

Dashboard 本质上是 Manager 进程提供的 HTTP 服务

Terminal window
URL: https://Ceph-201:8443/
root@Ceph-201 ~# curl -k https://Ceph-201:8443/
# -k 跳过证书
This resource can be found at <a href="https://10.0.0.202:8443/">
✅️ -L 可以实现自动跳转
🔹 为什么访问 Ceph-201 却跳到 Ceph-202❓️
1)显示集群中 active / standby
root@Ceph-201 ~# ceph -s | grep mgr
mgr: Ceph-202.xdeumk(active, since 88m), standbys: Ceph-201.cxdvrq
'Ceph 集群通常有多台 Manager(冗余),但同一时刻只有一个是 active'
✅️ 此时 active --> Ceph-202
✅️ 谁当 active mgr,Dashboard 就跑在谁上面
2)试试Ceph-202
root@Ceph-201 ~# curl -kI https://Ceph-202:8443/
HTTP/1.1 200 OK
'这个是可以通的'
https://Ceph-201:8443/
└→ standby mgr(Ceph-201): "我不当家,去Ceph-202找active"
└→ 重定向 https://10.0.0.202:8443/
✅️ 访问 standby mgr Dashboard 端口,会被重定向到 active mgr

🔹 选举规则

Manager 选举是先到先得——两边的 mgr 容器同时启动,谁先向 Monitor 注册成功谁就是 active,晚了半拍就成 standby

  • 这不是故障,是正常的 HA 设计:active 挂了,standby 秒级接替
Terminal window
3)查看mgr的状态
root@Ceph-201 ~# ceph mgr stat
✅️ JSON 格式更详细
{
"epoch": 72,
"available": true,
"active_name": "Ceph-202.xdeumk",
"num_standby": 1
}
4)看 Dashboard 实际跑在哪个 IP
root@Ceph-201 ~# ceph mgr services
✅️ 这个命令是真的实用
{
"dashboard": "https://10.0.0.202:8443/"
}
5)手动踢掉 active mgr,触发 standby 接替
✅️ 被踢的原 active 重启
# 用于主动切换(维护前可能会用)
root@Ceph-201 ~# ceph mgr fail
root@Ceph-201 ~# ceph mgr services
{
"dashboard": "https://10.0.0.201:8443/"
}
root@Ceph-201 ~# curl -kI https://Ceph-201:8443/
HTTP/1.1 200 OK ✅️

🔹 把 Dashboard 固定在某台机器上

如果不想让它跟着 active mgr 跑,可以显式指定 IP:

Terminal window
root@Ceph-201 ~# ceph config set mgr mgr/dashboard/server_addr 10.0.0.201
root@Ceph-201 ~# ceph config get mgr mgr/dashboard/server_addr
10.0.0.201
'终于用上 rm 选项了'
root@Ceph-201 ~# ceph config rm mgr mgr/dashboard/server_addr
root@Ceph-201 ~# ceph mgr fail
✅️ ceph mgr fail 一踢,mgr 重启 --> 重新加载配置,内存里的旧值清了
# mgr 不会热加载,得重启才生效

常用操作速查#

Terminal window
# ===================================
# 集群状态
# ===================================
ceph -s # 集群整体健康状态
ceph -w # 实时监控集群变化
ceph osd tree # OSD 树(含 class / 权重 / 状态)
ceph osd df # OSD 磁盘使用率
rados df # 存储池使用率(按池算账)
ceph mgr stat # Manager active/standby 状态(JSON)
ceph mgr services # Dashboard 实际跑在哪个 IP
# ===================================
# 存储池管理
# ===================================
ceph osd pool ls # 列出所有存储池
ceph osd pool ls detail # 存储池详细信息(类型/副本数/规则)
ceph osd pool create <name> <pg> <pgp> replicated # 创建副本池
ceph osd pool create <name> <pg> <pgp> erasure # 创建纠删码池
ceph osd pool create <name> <pg> <pgp> --autoscale_mode off # 创建时关闭自动伸缩
ceph osd pool rename <old> <new> # 重命名存储池
ceph osd pool rm <name> <name> --yes-i-really-really-mean-it # 删除存储池(双重确认)
ceph osd pool application enable <name> <rbd|cephfs|rgw> # 声明池用途
# ===================================
# 池属性管理
# ===================================
ceph osd pool get <name> <param> # 查单个属性(size / min_size / pg_num ...)
ceph osd pool set <name> <param> <val> # 修改属性
ceph osd pool get <name> pg_autoscale_mode # 查看自动伸缩是否开启
ceph osd pool get <name> nodelete # 查看池级删除锁状态
# ===================================
# CRUSH 规则
# ===================================
ceph osd crush rule ls # 列出所有 CRUSH 规则(只列名字)
ceph osd crush rule dump <rule> # 查看规则完整 JSON(故障域/副本数/设备类型)
# ===================================
# PG 管理
# ===================================
ceph pg stat # PG 状态概览
ceph pg dump # 所有 PG 详细状态(常配合 grep)
# ===================================
# 配置管理 (ceph config)
# ===================================
ceph config dump # 导出所有配置项(常配合 grep 过滤)
ceph config dump | grep <keyword> # 按关键字查配置
ceph config get <target> <option> # 查配置(类型级/实例级)
ceph config set <target> <option> <val> # 设配置(global/mon/osd/mgr 等)
ceph config rm <target> <option> # 删除配置
ceph config show <target> # 查看进程实际生效的全部配置
# ===================================
# Dashboard 用户管理
# ===================================
ceph dashboard ac-user-create <user> -i <passwd_file> <role> # 创建用户
ceph dashboard ac-user-show <user> # 查看用户信息
ceph dashboard ac-user-set-password <user> -i <passwd_file> # 修改密码
ceph dashboard ac-user-set-roles <user> <role> # 修改角色
ceph dashboard ac-user-delete <user> # 删除用户

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

存储池&&PG及配置管理
https://www.kpyun.fun/posts/services/storage/storage06/
作者
久棹
发布于
2026-04-08
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
久棹
只要胆子大,天天寒暑假!
公告
欢迎来到久棹的技术小站!本站专注 Linux 运维学习笔记分享,如有问题欢迎交流探讨 🎉
分类
标签
站点统计
文章
98
分类
11
标签
203
总字数
244,453
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.5
文章许可
CC BY-NC-SA 4.0

文章目录