注意

本文档适用于 Ceph 开发版本。

文件布局

文件的布局控制其内容如何映射到 Ceph RADOS 对象。您可以使用虚拟扩展属性或 xattrs。

客户端在写入文件的布局时必须使用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

这是一个整数。文件数据分布中使用的数据块的大小(以字节为单位)。文件的所有 stripe_unit 具有相同的大小。最后一个 stripe_unit 通常只有部分满:它包含文件数据直到 EOF 以及填充固定 stripe_unit 大小剩余空间的填充。

stripe_count

整数。构成文件数据 RAID 0 “stripe” 的连续 stripe_unit 数量。

object_size

整数。对象的大小(以字节为单位)。文件数据被分块成此大小的 RADOS 对象。

提示

RADOS 对对象大小执行可配置的限制:如果您将 CephFS 对象大小增加到该限制以上,则写入可能不会成功。OSD 设置是osd_max_object_size,默认为 128MB。

使用 ... 读取布局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"

Note

在读取布局时,池通常会以名称指示。然而,在池刚刚创建的罕见情况下,可能会输出 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.jsonvxattr。

添加一个名为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

Note

修改布局字段。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_namepool_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的那个)中的对象计数仍在继续增加。这是正常的:文件数据存储在布局指定的池中,但所有文件的一小部分元数据都保留在主要数据池中。

由 Ceph 基金会带给您

Ceph 文档是一个社区资源,由非盈利的 Ceph 基金会资助和托管Ceph Foundation. 如果您想支持这一点和我们的其他工作,请考虑加入现在加入.