注意
本文档适用于 Ceph 的开发版本。
文件布局
文件的布局控制其内容如何映射到 Ceph RADOS 对象。您可以使用虚拟扩展属性或 xattrs 来读取和写入文件的布局。
客户端在写入文件布局时必须使用 p 标志。请参阅 布局和配额限制(“p”标志)。
布局 xattrs 的名称取决于文件是常规文件还是目录。常规文件的布局 xattrs 称为 ceph.file.layout,而目录的布局 xattrs 称为 ceph.dir.layout。在后续示例中,当涉及目录时,ceph.file.layout 替换为相应的 dir。
提示
您的 Linux 发行版可能默认不包含用于操作 xattrs 的命令,所需的软件包通常称为 attr。
布局字段
- pool
这是一个字符串,包含 ID 或名称。字符串只能包含集合
[a-zA-Z0-9\_-.]中的字符。它确定存储文件数据对象的 RADOS 池。- pool_id
这是一个数字字符串。这是 Ceph 在创建 RADOS 池时分配的池 ID。
- pool_name
这是一个字符串。这是用户在创建池时定义的 RADOS 池的名称。
- pool_namespace
这是一个仅包含集合
[a-zA-Z0-9\_-.]中字符的字符串。它确定对象将被写入数据池中的哪个 RADOS 命名空间。默认情况下为空(即默认命名空间)。- stripe_unit
这是一个整数。用于分配文件数据的数据块大小(以字节为单位)。文件的所有条带单元大小均相等。最后一个条带单元通常只部分填充数据:它包含文件数据直到 EOF,以及填充固定条带单元大小余额的填充。
- 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_name file
# file: file
ceph.file.layout.pool_name="cephfs_data"
$ getfattr -n ceph.file.layout.pool_id file
# file: file
ceph.file.layout.pool_id="5"
$ 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"
以 json 格式获取布局。如果未为特定 inode 设置特定布局,系统会反向遍历目录路径并找到具有布局的最接近的祖先目录,并以 json 格式返回。文件布局也可以使用 ceph.file.layout.json vxattr 以 json 格式检索。
一个名为 inheritance 的虚拟字段被添加到 json 输出中以显示布局状态。inheritance 字段可以具有以下值
@default 表示系统默认布局 @set 表示已为该特定 inode 设置了特定布局 @inherited 表示返回的布局已从祖先继承
$ getfattr -n ceph.dir.layout.json --only-values /mnt/mycephs/accounts
{"stripe_unit": 4194304, "stripe_count": 1, "object_size": 4194304, "pool_name": "cephfs.a.data", "pool_id": 3, "pool_namespace": "", "inheritance": "@default"}
使用 setfattr 写入布局
使用 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 # Setting pool by ID
$ setfattr -n ceph.file.layout.pool -v cephfs_data file2 # Setting pool by name
$ setfattr -n ceph.file.layout.pool_id -v 1 file2 # Setting pool by ID
$ setfattr -n ceph.file.layout.pool_name -v cephfs_data file2 # Setting pool by name
注意
当使用 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
文件和目录布局也可以使用 json 格式设置。设置布局时会忽略 inheritance 字段。此外,如果同时指定了 pool_name 和 pool_id 字段,则优先考虑 pool_name 以更好地消除歧义。
$ setfattr -n ceph.file.layout.json -v '{"stripe_unit": 4194304, "stripe_count": 1, "object_size": 4194304, "pool_name": "cephfs.a.data", "pool_id": 3, "pool_namespace": "", "inheritance": "@default"}' file1
清除布局
如果您希望从目录中删除明确的布局,以恢复继承其祖先的布局,您可以这样做
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"
# Demonstrate file1 inheriting its parent's layout
$ 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"
# Now update the layout of the directory before creating a second file
$ setfattr -n ceph.dir.layout.stripe_count -v 4 dir
$ touch dir/file2
# Demonstrate that file1's layout is unchanged
$ 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"
# ...while file2 has the parent directory's new layout
$ 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"
向文件系统添加数据池
在使用 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 的池)中的对象计数仍在继续增加。这是正常的:文件数据存储在布局指定的池中,但少量元数据保留在所有文件的主数据池中。