删除ceph挂载卷中的数据后ceph空间没有释放
有一个集群的ceph的存储空间被k8s的pod占满了,客户也不愿意扩容。现在就只能看可不可以删除一些不用的文件来释放一些存储空间,发现mysql占用的数据比较大,然后清理快40G的binlog,在容器中通过df -h
查看已经是减少的了。但ceph df
查看的使用率并没有变化,就很懵比~。由此引发了一些思考
文件系统是怎么删除文件的呢?
删除文件的过程:
以/var/log/messages这个文件为例,删除messages这个文件的过程大致如下:
- 找到/var/log/messages所在的inode
- 删除/var/log目录上有关messages的条目
- 空索引中/var/log/messages对应的inode数据(注意,不是删除inode,而是清空这个inode的数据),将此inode对应的位图改为空闲(如从1改为0)。事实上可以不清除数据,只将位图由1改为0,这样下次使用时会自动覆盖。
- 将/var/log/messages所占用的磁盘块重新标记为空闲。其实删除文件并不会对磁盘块做任何操作(清除数据),只会将相应的磁盘块的位图改为空闲,下次使用时仅仅只是覆盖现有磁盘块上的数据。如果没有在这些磁盘块上写入新文件,其数据仍然可以被找回来;但是一旦写入了新文件,就很难再找回原来的数据了。这就是为什么删除文件的过程相较其他操作要快得多。
由此可知,文件系统只是将文件头作一个已删除的标记,表明文件被删除了,即没有真正删除文件,只是标识删除。虽然文件系统知道这些block是未使用或者说可用的,但是底层的存储系统并不知道文件系统做的操作,会认为这些block仍在使用。
以这里mysql pod挂在的卷为例,它本身是稀疏格式的,也就是说它所占用objects会随着用户写入数据的增加而增加(Thin provision)。当用户删除数据以后,这些obejct不再使用,但并没有被释放。因为从Ceph的角度讲,它并不知道文件系统中发生的事情。
解决方法
SSD 具有一种称为 TRIM 的功能。从本质上讲,这是一种用于回收设备上未使用的块的方法,该块可能先前已被写入,但不再包含有效数据,因此可以返回到通用存储池以供重用。
Linux系统中都有一个命令 fstrim
,就是作TRIM操作,可以用于普通SSD与NVMe
有两种方式可以触发Trim/Discard请求,一种是由文件系统自动完成,一种是用户通过执行命令来完成。
一、文件系统自动完成
只要在挂载文件系统时指定discard参数即可,比如 mount -t ext4 -o discard device mountpoint,这样在文件系统中删除文件后会自动触发Trim/Discard操作,在块设备上释放占用的空间。需要注意的是,mount的discard参数会导致文件系统性能下降,在并发删除大量小文件时变得很慢,因此需要根据具体场景选择合适的长发方式。
二、用户执行命令
用户可以执行命令fstrim来触发Trim/Discard操作,采用这种方式mount文件系统时不需要discard参数。比如,fstrim -v mountpoint,就会释放对应块设备上不用的空间。
测试:
查看存储池
[root@zjjshen ~]# rados lspools
.rgw.root
images
volumestest
vms
k8s
创建一个卷并挂载到机器上
[root@zjjshen ~]# rbd create k8s/test --size 30G #创建块设备
[root@zjjshen ~]# rbd info k8s/test
rbd image 'test':
size 30GiB in 7680 objects
order 22 (4MiB objects)
block_name_prefix: rbd_data.6cc18c6b8b4567
format: 2
features: layering, exclusive-lock, object-map, fast-diff, deep-flatten
flags:
create_timestamp: Fri May 14 10:49:55 2021
[root@zjjshen ~]# rbd feature disable k8s/test exclusive-lock object-map fast-diff deep-flatten
[root@zjjshen ~]# rbd map k8s/test # 映射块设备
/dev/rbd13
[root@zjjshen ~]# mkdir /root/zjjshen # 创建挂载目录
[root@zjjshen ~]# mkfs.ext4 /dev/rbd13 # 格式化块设备
mke2fs 1.42.9 (28-Dec-2013)
Discarding device blocks: done
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=1024 blocks, Stripe width=1024 blocks
1966080 inodes, 7864320 blocks
393216 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2155872256
240 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information:
[root@zjjshen ~]# mount /dev/rbd13 /root/zjjshen/ # 挂载
[root@zjjshen ~]# df -h | grep zjjshen
/dev/rbd13 30G 45M 28G 1% /root/zjjshen
[root@zjjshen ~]# rbd du tstack_k8s/test
NAME PROVISIONED USED
test 30GiB 240MiB
快速生成大文件
# 生成10G的file文件
[root@zjjshen ~]# cd /root/zjjshen
[root@zjjshen zjjshen]# dd if=/dev/zero of=file bs=1M count=10000
10000+0 records in
10000+0 records out
10485760000 bytes (10 GB) copied, 3.39941 s, 3.1 GB/s
[root@zjjshen zjjshen]# du -sh file
9.8G file
[root@zjjshen zjjshen]# df -h | grep zjjshen
/dev/rbd13 30G 9.9G 19G 36% /root/zjjshen
[root@zjjshen zjjshen]# rbd du k8s/test
warning: fast-diff map is not enabled for test. operation may be slow.
NAME PROVISIONED USED
test 30GiB 10GiB
删除生成的文件,看rbd du
是否有变化
[root@zjjshen zjjshen]# rm -rf file
[root@zjjshen zjjshen]# df -h | grep zjjshen
/dev/rbd13 30G 45M 28G 1% /root/zjjshen
[root@zjjshen zjjshen]# rbd du k8s/test
warning: fast-diff map is not enabled for test. operation may be slow.
NAME PROVISIONED USED
test 30GiB 10GiB
可以看出,删除后ceph这边存储使用量是没有变化的
执行fstrim
[root@zjjshen zjjshen]# fstrim -v /root/zjjshen
/root/zjjshen: 10 GiB (10716344320 bytes) trimmed
[root@zjjshen zjjshen]# rbd du k8s/test
warning: fast-diff map is not enabled for test. operation may be slow.
NAME PROVISIONED USED
test 30GiB 240MiB
可以看出ceph查看的使用量已经减少了