文件的布局控制其内容如何映射到Ceph RADOS对象。可以使用虚拟扩展属性或xattrs读取和写入文件的布局。
布局xattrs的名称取决于文件是常规文件还是目录。 常规文件的布局xattrs称为ceph.file.layout,而目录的布局xattrs称为ceph.dir.layout。 在后面的示例引用ceph.file.layout的地方,当处理目录时,请适当替换dir。
布局字段
pool
字符串,提供ID或名称。 字符串只能包含在集合[a-zA-Z0-9_-。]中的字符。 文件的数据对象将存储在哪个RADOS池中。
pool_namespace
仅包含[a-zA-Z0-9_-。]集合中的字符的字符串。 在数据池中,将对象写入哪个RADOS命名空间。 默认为空(即默认名称空间)。
stripe_unit
整数(以字节为单位)。 文件的RAID 0分布中使用的数据块的大小(以字节为单位)。 文件的所有条带单元具有相等的大小。 最后一个条带单元通常不完整-即 它表示文件末尾的数据,以及直到固定条带单元大小末尾的未使用“空间”。
stripe_count
整数。 构成文件数据的RAID 0“条带”的连续条带单元的数量。
object_size
整数(以字节为单位)。 文件数据被分块到此大小的RADOS对象中。
RADOS对对象大小施加了可配置的限制:如果将CephFS对象大小增加到该限制之外,则写入可能不会成功。 OSD设置为osd_max_object_size,默认情况下为128MB。 非常大的RADOS对象可能会阻止群集的平稳运行,因此不建议将对象大小限制增加到默认值以上。
使用GETFATTR读取布局
将布局信息作为单个字符串读取:
$ touch file
$ getfattr -n ceph.file.layout file
# file: file
ceph.file.layout="stripe_unit=4194304 stripe_count=1 object_size=4194304 pool=cephfs_data"
读取各个布局字段:
$ getfattr -n ceph.file.layout.pool file
# file: file
ceph.file.layout.pool="cephfs_data"
$ getfattr -n ceph.file.layout.stripe_unit file
# file: file ceph.file.layout.stripe_unit="4194304"
$ getfattr -n ceph.file.layout.stripe_count file
# file: file
ceph.file.layout.stripe_count="1"
$ getfattr -n ceph.file.layout.object_size file
# file: file
ceph.file.layout.object_size="4194304"
注意 在读取布局时,通常会用名称来指示池。然而,在少数情况下,当池刚刚创建时,可能会输出ID。
在自定义之前,目录没有明确的布局。 如果从未修改过,尝试读取布局将失败:这表示将使用具有显式布局的下一个祖先目录的布局。
$ mkdir dir
$ getfattr -n ceph.dir.layout dir
dir: ceph.dir.layout: No such attribute
$ setfattr -n ceph.dir.layout.stripe_count -v 2 dir
$ getfattr -n ceph.dir.layout dir
# file: dir
ceph.dir.layout="stripe_unit=4194304 stripe_count=2 object_size=4194304 pool=cephfs_data"
使用setfattr修改布局字段:
$ ceph osd lspools
0 rbd
1 cephfs_data
2 cephfs_metadata
$ setfattr -n ceph.file.layout.stripe_unit -v 1048576 file2
$ setfattr -n ceph.file.layout.stripe_count -v 8 file2
$ setfattr -n ceph.file.layout.object_size -v 10485760 file2
$ setfattr -n ceph.file.layout.pool -v 1 file2 # 按ID设置池
$ setfattr -n ceph.file.layout.pool -v cephfs_data file2 # 按名称设置池
注意 使用setfattr修改文件的布局字段时,此文件必须为空,否则将发生错误。
# touch an empty file
$ touch file1
# modify layout field successfully
$ setfattr -n ceph.file.layout.stripe_count -v 3 file1
# write something to file1
$ echo "hello world" > file1
$ setfattr -n ceph.file.layout.stripe_count -v 4 file1
setfattr: file1: Directory not empty
清除布局
如果要从目录中删除显式布局,要恢复为继承其祖先的布局,可以这样做:
setfattr -x ceph.dir.layout mydir
同样,如果已设置pool_namespace属性并希望修改布局以使用默认命名空间:
# Create a dir and set a namespace on it
mkdir mydir
setfattr -n ceph.dir.layout.pool_namespace -v foons mydir
getfattr -n ceph.dir.layout mydir
ceph.dir.layout="stripe_unit=4194304 stripe_count=1 object_size=4194304 pool=cephfs_data_a pool_namespace=foons"
# Clear the namespace from the directory's layout
setfattr -x ceph.dir.layout.pool_namespace mydir
getfattr -n ceph.dir.layout mydir
ceph.dir.layout="stripe_unit=4194304 stripe_count=1 object_size=4194304 pool=cephfs_data_a"
布局的继承
文件在创建时继承其父目录的布局。 但是,对父目录布局的后续更改不会影响子项。
$ getfattr -n ceph.dir.layout dir
# file: dir
ceph.dir.layout="stripe_unit=4194304 stripe_count=2 object_size=4194304 pool=cephfs_data"
# 证明file1继承其父目录布局
$ touch dir/file1
$ getfattr -n ceph.file.layout dir/file1
# file: dir/file1
ceph.file.layout="stripe_unit=4194304 stripe_count=2 object_size=4194304 pool=cephfs_data"
# 现在,在创建第二个文件之前更新目录的布局
$ setfattr -n ceph.dir.layout.stripe_count -v 4 dir
$ touch dir/file2
# 证明file1的布局不变
$ getfattr -n ceph.file.layout dir/file1
# file: dir/file1
ceph.file.layout="stripe_unit=4194304 stripe_count=2 object_size=4194304 pool=cephfs_data"
# ...而file2具有父目录的新布局
$ getfattr -n ceph.file.layout dir/file2
# file: dir/file2
ceph.file.layout="stripe_unit=4194304 stripe_count=4 object_size=4194304 pool=cephfs_data"
如果中间目录没有设置布局,则作为目录后代创建的文件也会继承布局:
$ getfattr -n ceph.dir.layout dir
# file: dir
ceph.dir.layout="stripe_unit=4194304 stripe_count=4 object_size=4194304 pool=cephfs_data"
$ mkdir dir/childdir
$ getfattr -n ceph.dir.layout dir/childdir
dir/childdir: ceph.dir.layout: No such attribute
$ touch dir/childdir/grandchild
$ getfattr -n ceph.file.layout dir/childdir/grandchild
# file: dir/childdir/grandchild
ceph.file.layout="stripe_unit=4194304 stripe_count=4 object_size=4194304 pool=cephfs_data"
在MDS中添加数据池
在使用CephFS池之前,必须将其添加到元数据服务器。
$ ceph fs add_data_pool cephfs cephfs_data_ssd
$ ceph fs ls
# Pool should now show up ....
data pools: [cephfs_data cephfs_data_ssd ]
确保cephx密钥允许客户端访问此新池。
然后,可以更新CephFS中目录的布局,以使用添加的池:
$ mkdir /mnt/cephfs/myssddir
$ setfattr -n ceph.dir.layout.pool -v cephfs_data_ssd /mnt/cephfs/myssddir
在该目录中创建的所有新文件现在将继承其布局并将其数据放入新添加的池中。
可能会注意到主数据池(传递给fs new的池)中的对象计数继续增加,即使在您添加的池中创建了文件也是如此。 这是正常的:文件数据存储在布局指定的池中,但是少量元数据保存在主数据池中以供所有文件使用。