注意

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

镜像加密

从 Pacific 版本开始,RBD 客户端可以在内部处理镜像级别的加密。这意味着您可以设置一个密钥,用于加密特定的 RBD 镜像。本页描述了 RBD 加密功能的范围。

注意

krbd 内核模块目前不支持加密。

注意

也可以使用外部工具(例如 dm-crypt、QEMU)来加密 RBD 镜像,其功能集和限制集可能与此处所述有所不同。

加密格式

默认情况下,RBD 镜像不加密。要加密 RBD 镜像,需要将其格式化为受支持的加密格式之一。格式化操作会将加密元数据持久化到镜像中。加密元数据通常包括诸如加密格式和版本、密码算法和模式规范,以及用于保护加密密钥的信息。加密密钥本身受用户保管的密钥(通常是密码)保护,该密钥永远不会持久化。基本的加密格式化操作将需要指定加密格式和密钥。

一些加密元数据可能作为镜像数据的一部分存储,通常会在原始镜像数据的开头写入一个加密头。这意味着加密镜像的有效镜像大小可能低于原始镜像大小。有关更多详细信息,请参阅支持的格式部分。

注意

除非明确(重新)格式化,否则加密镜像的克隆将固有地使用相同的格式和密钥进行加密。

注意

加密镜像的克隆始终是加密的。不支持重新格式化为明文。

注意

在格式化之前写入镜像的任何数据都可能变得不可读,尽管它可能仍占用存储资源。

注意

启用了日志功能的镜像无法被 RBD 客户端格式化和加密。

加密加载

格式化镜像是启用加密的必要先决条件。但是,所有 RBD API 仍会将格式化的镜像视为原始未加密镜像。特别是,加密的 RBD 镜像可以使用与任何其他镜像相同的 API 打开,并且可以读取/写入原始未加密数据。此类原始 IO 可能会危及加密格式的完整性,例如通过覆盖位于镜像开头的加密元数据。

为了安全地在格式化的镜像上执行加密 IO,在打开镜像后应应用额外的加密加载操作。加密加载操作需要提供加密格式和密钥,以解锁镜像本身及其每个显式格式化祖先镜像的加密密钥。成功执行加密加载操作后,打开镜像的所有 IO 都将进行加密/解密。对于克隆镜像,这也包括对祖先镜像的 IO。加密密钥将由 RBD 客户端存储在内存中,直到镜像关闭。

注意

一旦加载了加密,就不能再对打开的镜像上下文应用其他加密加载/格式化操作。

注意

一旦加载了加密,使用打开的镜像上下文检索镜像大小和父重叠的 API 调用将分别返回有效镜像大小和有效父重叠。

注意

一旦加载了加密,调整镜像大小的 API 调用将把指定的目标大小解释为有效镜像大小。

注意

如果显式格式化了加密镜像的克隆,则扁平化克隆镜像的操作将不再透明,因为父数据必须根据克隆镜像格式进行重新加密,因为它从父快照复制。如果在发出扁平化操作之前未加载加密,则克隆镜像中以前可访问的任何父数据都可能变得不可读。

注意

如果显式格式化了加密镜像的克隆,则缩小克隆镜像的操作将不再透明,因为在某些情况下(例如,如果克隆镜像具有快照,或者如果克隆镜像被缩小到与对象大小不一致的大小),它涉及从父快照复制一些数据,类似于扁平化。如果在发出缩小操作之前未加载加密,则克隆镜像中以前可访问的任何父数据都可能变得不可读。

注意

通过 rbd-nbd 将 RBD 镜像挂载为块设备时,可以自动应用加密加载。

支持的格式

LUKS

支持 LUKS1 和 LUKS2。数据布局完全符合 LUKS 规范。因此,RBD 格式化的镜像可以使用外部支持 LUKS 的工具(例如 dm-crypt 或 QEMU)加载。此外,可以在 RBD 外部创建的现有 LUKS 数据可以导入(通过将原始 LUKS 数据复制到镜像中)并通过 RBD 加密加载。

注意

LUKS 格式仅在基于 Linux 的系统上受支持。

注意

目前,仅支持 AES-128 和 AES-256 加密算法。此外,xts-plain64 是目前唯一受支持的加密模式。

要使用 LUKS 格式,首先格式化镜像

rbd encryption format [--cipher-alg {aes-128|aes-256}] {image-spec} {luks1|luks2} {passphrase-file}

加密格式化操作会生成 LUKS 头部并将其写入镜像开头。头部附加了一个包含随机生成的加密密钥的密钥槽,并受从 passphrase-file 读取的密码保护。

注意

在旧版本中,如果 passphrase-file 的内容以换行符结尾,则会将其剥离。

默认情况下,将使用 xts-plain64 模式下的 AES-256(这是当前推荐的模式,也是其他工具的通常默认设置)。格式化操作也允许选择 AES-128。RBD 目前不支持添加/删除密码,但可以使用兼容工具(例如 cryptsetup)将其应用于原始 RBD 数据。

LUKS 头部大小可以变化(LUKS2 中最大可达 136MiB),但通常最大为 16MiB,具体取决于安装的 libcryptsetup 版本。为了获得最佳性能,加密格式将把数据偏移量设置为与镜像条带周期大小对齐。例如,如果使用配置了 8MiB 对象大小的镜像,则预期最小开销为 8MiB;如果使用配置了 4MiB 对象大小和 条带计数为 3 的镜像,则预期最小开销为 12MiB。

在 LUKS1 中,扇区(最小加密单元)固定为 512 字节。LUKS2 支持更大的扇区,为了更好的性能,我们将默认扇区大小设置为最大 4KiB。小于扇区或未对齐到扇区开头的写入将触发客户端上的受保护读-修改-写链,并带来相当大的延迟惩罚。批量此类未对齐写入可能导致 IO 竞争,从而进一步降低性能。因此,建议在无法保证传入写入与扇区对齐的情况下避免使用 RBD 加密。

要映射 LUKS 格式化的镜像,请运行

rbd device map -t nbd -o encryption-passphrase-file={passphrase-file} {image-spec}

请注意,出于安全原因,加密格式化和加密加载操作都是 CPU 密集型的,可能需要几秒钟才能完成。对于实际镜像 IO 的加密操作,假设启用了 AES-NI,则应增加相对较小的微秒延迟,以及 CPU 利用率的小幅增加。

示例

创建一个有效大小为 50GiB 的 LUKS2 格式化镜像

rbd create --size 50G mypool/myimage
rbd encryption format mypool/myimage luks2 passphrase.bin
rbd resize --size 50G --encryption-passphrase-file passphrase.bin mypool/myimage

末尾的 rbd resize 命令会增加镜像大小以补偿与 LUKS2 头部相关的开销。

给定一个 LUKS2 格式化的镜像,创建一个具有相同有效大小的 LUKS2 格式化克隆

rbd snap create mypool/myimage@snap
rbd snap protect mypool/myimage@snap
rbd clone mypool/myimage@snap mypool/myclone
rbd encryption format mypool/myclone luks2 clone-passphrase.bin

给定一个有效大小为 50GiB 的 LUKS2 格式化镜像,创建一个具有相同有效大小的 LUKS1 格式化克隆

rbd snap create mypool/myimage@snap
rbd snap protect mypool/myimage@snap
rbd clone mypool/myimage@snap mypool/myclone
rbd encryption format mypool/myclone luks1 clone-passphrase.bin
rbd resize --size 50G --allow-shrink --encryption-passphrase-file clone-passphrase.bin --encryption-passphrase-file passphrase.bin mypool/myclone

由于 LUKS1 头部通常小于 LUKS2 头部,因此末尾的 rbd resize 命令会缩小克隆镜像,以摆脱不需要的空间余量。

给定一个有效大小为 50GiB 的 LUKS1 格式化镜像,创建一个具有相同有效大小的 LUKS2 格式化克隆

rbd resize --size 51G mypool/myimage
rbd snap create mypool/myimage@snap
rbd snap protect mypool/myimage@snap
rbd clone mypool/myimage@snap mypool/myclone
rbd encryption format mypool/myclone luks2 clone-passphrase.bin
rbd resize --size 50G --allow-shrink --encryption-passphrase-file passphrase.bin mypool/myimage
rbd resize --size 50G --allow-shrink --encryption-passphrase-file clone-passphrase.bin --encryption-passphrase-file passphrase.bin mypool/myclone

由于 LUKS2 头部通常大于 LUKS1 头部,因此开头的 rbd resize 命令会临时增加父镜像大小,以便在父快照中保留一些额外的空间,从而也保留在克隆镜像中。这对于使所有父数据在克隆镜像中都可访问是必需的。末尾的 rbd resize 命令会将父镜像缩小回其原始大小(这不会影响父快照),也会将克隆镜像缩小以摆脱未使用的保留空间。

这同样适用于创建未格式化(明文)镜像的格式化克隆,因为未格式化镜像根本没有头部。

要映射格式化的克隆,请提供克隆本身及其所有显式格式化的父镜像的加密格式和密码。提供 encryption-formatencryption-passphrase-file 选项的顺序基于镜像层次结构:从克隆镜像开始,然后是其父镜像,依此类推。

这是一个映射格式化克隆的命令示例

rbd device map -t nbd -o encryption-passphrase-file=clone-passphrase.bin,encryption-passphrase-file=passphrase.bin mypool/myclone

由 Ceph 基金会为您呈现

Ceph 文档是由非营利性 Ceph 基金会 资助和托管的社区资源。如果您希望支持这项工作和我们的其他努力,请考虑 立即加入