[root@node2 ~]# rbd du --pool rbdpool myimage --user1
rbd: unrecognised option '--user1'
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 28 MiB
[root@node2 ~]# dd if=/dev/zero of=/mnt/ceph-data/test_100mb.dat bs=1M count=700
700+0 records in
700+0 records out
734003200 bytes (734 MB, 700 MiB) copied, 7.48139 s, 98.1 MB/s
[root@node2 ~]# df -h | grep ceph
/dev/rbd0 974M 701M 207M 78% /mnt/ceph-data
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 516 MiB
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 728 MiB
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 728 MiB
[root@node2 ~]# rm -f /mnt/ceph-data/test_100mb.dat
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 728 MiB
[root@node2 ~]# df -h | grep ceph
/dev/rbd0 974M 24K 907M 1% /mnt/ceph-data
[root@node2 ~]# dd if=/dev/zero of=/mnt/ceph-data/test222_100mb.dat bs=1M count=700
700+0 records in
700+0 records out
734003200 bytes (734 MB, 700 MiB) copied, 4.85672 s, 151 MB/s
[root@node2 ~]# df -h | grep ceph
/dev/rbd0 974M 701M 207M 78% /mnt/ceph-data
[root@node2 ~]# df -h | grep ceph
/dev/rbd0 974M 701M 207M 78% /mnt/ceph-data
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 860 MiB
[root@node2 ~]# ceph df detail
2025-12-19T11:19:28.380+0800 7f3f3908b640 -1 auth: unable to find a keyring on /etc/ceph/ceph.client.admin.keyring,/etc/ceph/ceph.keyring,/etc/ceph/keyring,/etc/ceph/keyring.bin,: (2) No such file or directory
2025-12-19T11:19:28.380+0800 7f3f3908b640 -1 AuthRegistry(0x7f3f3405eaa0) no keyring found at /etc/ceph/ceph.client.admin.keyring,/etc/ceph/ceph.keyring,/etc/ceph/keyring,/etc/ceph/keyring.bin,, disabling cephx
2025-12-19T11:19:28.381+0800 7f3f3908b640 -1 auth: unable to find a keyring on /etc/ceph/ceph.client.admin.keyring,/etc/ceph/ceph.keyring,/etc/ceph/keyring,/etc/ceph/keyring.bin,: (2) No such file or directory
2025-12-19T11:19:28.381+0800 7f3f3908b640 -1 AuthRegistry(0x7f3f3908a0d0) no keyring found at /etc/ceph/ceph.client.admin.keyring,/etc/ceph/ceph.keyring,/etc/ceph/keyring,/etc/ceph/keyring.bin,, disabling cephx
2025-12-19T11:19:28.381+0800 7f3f32d9d640 -1 monclient(hunting): handle_auth_bad_method server allowed_methods [2] but i only support [1]
2025-12-19T11:19:28.382+0800 7f3f3259c640 -1 monclient(hunting): handle_auth_bad_method server allowed_methods [2] but i only support [1]
2025-12-19T11:19:28.382+0800 7f3f3359e640 -1 monclient(hunting): handle_auth_bad_method server allowed_methods [2] but i only support [1]
2025-12-19T11:19:28.382+0800 7f3f3908b640 -1 monclient: authenticate NOTE: no keyring found; disabled cephx authentication
[errno 13] RADOS permission denied (error connecting to the cluster)
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.93
ssd 300 GiB 298 GiB 1.6 GiB 1.6 GiB 0.55
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.14
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 833 MiB 833 MiB 0 B 221 2.4 GiB 2.4 GiB 0 B 0.29 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 860 MiB
[root@node2 ~]# rm -f /mnt/ceph-data/test222_100mb.dat
[root@node2 ~]# dd if=/dev/zero of=/mnt/ceph-data/test333_100mb.dat bs=1M count=700
700+0 records in
700+0 records out
734003200 bytes (734 MB, 700 MiB) copied, 4.84126 s, 152 MB/s
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 860 MiB
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.93
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.55
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.14
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 833 MiB 833 MiB 0 B 221 2.4 GiB 2.4 GiB 0 B 0.29 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.94
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.55
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.15
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 833 MiB 833 MiB 0 B 221 2.4 GiB 2.4 GiB 0 B 0.29 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# rm -f /mnt/ceph-data/test333_100mb.dat
[root@node2 ~]# dd if=/dev/zero of=/mnt/ceph-data/test444_100mb.dat bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00916691 s, 1.1 GB/s
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.93
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.55
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.14
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 833 MiB 833 MiB 0 B 221 2.4 GiB 2.4 GiB 0 B 0.29 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.93
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.55
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.14
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 833 MiB 833 MiB 0 B 221 2.4 GiB 2.4 GiB 0 B 0.29 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# df -h | grep ceph
/dev/rbd0 974M 11M 897M 2% /mnt/ceph-data
[root@node2 ~]# dd if=/dev/zero of=/mnt/ceph-data/test555_100mb.dat bs=1M count=900
900+0 records in
900+0 records out
943718400 bytes (944 MB, 900 MiB) copied, 8.54251 s, 110 MB/s
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.94
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.56
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.14
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 860 MiB 860 MiB 0 B 227 2.5 GiB 2.5 GiB 0 B 0.30 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.94
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.56
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.14
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 860 MiB 860 MiB 0 B 227 2.5 GiB 2.5 GiB 0 B 0.30 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# df -h | grep ceph
/dev/rbd0 974M 911M 0 100% /mnt/ceph-data
[root@node2 ~]# rbd du --pool rbdpool myimage --id user1
NAME PROVISIONED USED
myimage 1 GiB 948 MiB
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.96
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.58
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.16
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 917 MiB 917 MiB 0 B 243 2.7 GiB 2.7 GiB 0 B 0.32 277 GiB N/A N/A N/A 0 B 0 B
[root@node2 ~]# ls /mnt
ceph-data
[root@node2 ~]# ls /mnt/ceph-data/
lost+found test444_100mb.dat test555_100mb.dat
[root@node2 ~]# rm -f /mnt/ceph-data/test444_100mb.dat
[root@node2 ~]# rm -f /mnt/ceph-data/test555_100mb.dat
[root@node2 ~]# ls /mnt/ceph-data/
lost+found
[root@node2 ~]# ceph df detail --id user1
--- RAW STORAGE ---
CLASS SIZE AVAIL USED RAW USED %RAW USED
hdd 600 GiB 582 GiB 18 GiB 18 GiB 2.96
ssd 300 GiB 298 GiB 1.7 GiB 1.7 GiB 0.58
TOTAL 900 GiB 881 GiB 19 GiB 19 GiB 2.16
--- POOLS ---
POOL ID PGS STORED (DATA) (OMAP) OBJECTS USED (DATA) (OMAP) %USED MAX AVAIL QUOTA OBJECTS QUOTA BYTES DIRTY USED COMPR UNDER COMPR
device_health_metrics 1 1 0 B 0 B 0 B 0 0 B 0 B 0 B 0 277 GiB N/A N/A N/A 0 B 0 B
testpool 5 64 5.2 GiB 5.2 GiB 0 B 1.37k 15 GiB 15 GiB 0 B 2.68 184 GiB N/A N/A N/A 0 B 0 B
rbdpool 6 64 917 MiB 917 MiB 0 B 243 2.7 GiB 2.7 GiB 0 B 0.32 277 GiB
你这个实验现象本身是完全正确的 ,而且它恰好暴露了 RBD + 文件系统 + 稀疏 object + 延迟回收这几层机制叠加后的真实行为。
我给你一个先给结论 → 再逐层拆解 → 最后逐条对照你日志的完整分析。
一、先给结论(非常重要)
你看到的现象不是"Ceph 超额写入"或"越界写入",
而是:
- 文件删除 ≠ 底层 object 立刻释放
- RBD 是稀疏映像(thin-provisioned)
- 新写入会优先复用 image 内已经分配过的 object
- 只有当 image 的"逻辑使用"超过 image size,才会真正失败
所以:
"删除文件后空间没立刻回收,但仍能继续写大文件"是 RBD 的正常、必然行为。
二、先澄清一个非常关键的概念(90% 误解来源)
你这里涉及了 三种"空间"
| 层级 | 你看到的工具 | 含义 |
|---|---|---|
| 文件系统空间 | df -h /mnt/ceph-data |
ext4/xfs 视角 |
| RBD image 空间 | rbd du myimage |
image 已分配 object |
| Ceph pool 空间 | ceph df detail |
pool 实际 object 使用 |
这三者不会同步变化。
三、逐层解释你看到的"反直觉行为"
1️⃣ 为什么 rm 后 df 立刻变空?
bash
rm test_100mb.dat
df -h
这是文件系统层行为:
- inode 被释放
- block map 被释放
- ext4/xfs 认为空间"可用了"
👉 但它只是在 image 里打了"洞(hole)"
2️⃣ 为什么 rbd du 没变?
bash
rbd du myimage
USED 728 MiB (删除前后不变)
这是RBD 层行为:
- object 仍然存在
- object 内部只是某些 extent 变成 hole
- object 本身不会因为文件删除而立刻删除
👉 Ceph 不会主动"拆 object"
3️⃣ 那为什么还能继续写一个 700MB 的新文件?
这是最关键的地方 👇
因为:
新写入优先复用 image 内"已经存在的 object 和 stripe_unit"
你的 image:
-
size = 1GiB
-
已经有 ~728MiB object 被创建过
-
删除文件只是:
- 在 object 里打洞
- 没有释放 object
所以新写:
text
700MB
实际上:
- 大量写入命中了 已有 object 的 hole
- 没有新 object 被创建
- image 的"已分配 object 总量"增长很慢甚至不增长
这就是你看到:
bash
df -h → 用了 700M
rbd du → 从 728M → 860M(小幅上涨)
四、你"看起来像是越界写"的根本原因
你这里有一个非常自然但错误的直觉:
"之前删了 700MB,再写 700MB + 700MB ≈ 1.4GB,
image 才 1GB,怎么还能写?"
正确理解是:
image size 限制的是"最大逻辑地址",不是"历史累计写入量"。
举个最直观的比喻(强烈建议记住)
把 RBD image 想成:
一个 1GB 大小的"虚拟硬盘地址空间"
-
删除文件 ≠ 硬盘缩小
-
删除文件 ≠ 硬盘被"清零"
-
只是:
- 标记哪些块"现在没人用"
你只要:
- 不写到 1GB 以外的逻辑地址
- 不新创建超过 image 覆盖范围的 object
👉 就永远不会越界
五、什么时候"真的会写不进去"?
只有一种情况 👇
❌ 真正失败的条件
text
写入的文件布局
→ 需要访问 image offset > image_size
也就是:
- 文件系统认为还有空间
- 但 RBD image 地址空间已经用完
- 新的 stripe_unit / object_no 超过 image 边界
这时你会看到:
- write() 返回 ENOSPC
- dmesg 里有 rbd I/O error
六、你日志里一个"非常典型"的细节(你可能没注意)
你这里有一段:
bash
dd count=900
df -h → 100%
rbd du → 948 MiB
这一步说明:
- image 的 object 已经非常接近满
- 新写开始逼近 image 末尾
- 再继续写就会真正失败
👉 这正好验证了:Ceph 没有超配 image
七、为什么 Ceph 不在 rm 时立刻释放 object?
这是设计选择,不是缺陷:
原因 1:性能
-
删除文件是高频操作
-
立刻删除 object 会引发:
- 大量 PG 更新
- recovery / rebalance 抖动
原因 2:稀疏对象(hole)
- object 是稀疏的
- hole 不占物理空间
- 删除 extent ≠ 删除 object
原因 3:复用优先
- 未来写入可以复用 object
- 减少 object churn
八、那"真正释放空间"要怎么做?
1️⃣ RBD image 层
bash
rbd sparsify myimage
- 会扫描 image
- 回收全空 object
- 这是你现在最需要的命令
2️⃣ 文件系统层(ext4)
bash
fstrim /mnt/ceph-data
- 通知下层哪些块是 hole
- 对 SSD / 稀疏设备非常重要
九、把你这个实验一句话总结(你可以直接写到笔记里)
在 RBD 上删除文件只会在 image 中产生 hole,不会立即释放 object;
后续写入会优先复用这些已存在的 object,因此即使"删除 + 新写"的文件大小之和超过 image size,仍可能成功;
只有当新的写入需要扩展到 image 的逻辑边界之外时,才会真正失败。
十、你这个实验其实"非常成功"
因为它完整验证了:
- striping
- object 复用
- 稀疏 image
- 延迟回收
- image size 的真实含义