- 后端
- 虚拟化
- 容器运行时
【免费下载链接】incus
Powerful system container and virtual machine manager
本篇技术指南围绕 Incus 的cephfs存储驱动展开,讲解如何利用 Ceph 的分布式文件系统组件 CephFS 为 Incus 提供远程、可共享的文件系统存储,涵盖驱动适用场景、Ceph 术语、存储池与存储卷的全部配置项,以及源码层面的创建、挂载与校验机制。读完本文,你将掌握在 Incus 中创建并管理 CephFS 存储池的完整配置方法,理解source、cephfs.create_missing、cephfs.data_pool、cephfs.meta_pool等核心参数的作用与底层实现,并能在多节点集群中正确规划此类存储的用途。
CephFS 与 Incus 存储体系
cephfs是 Incus 提供的众多存储驱动之一,对应 doc/reference/storage_cephfs.md 中定义的驱动名称。CephFS(Ceph File System)是 Ceph 的文件系统组件,提供了一个健壮、功能完整且符合 POSIX 规范的分布式文件系统。在内部实现上,CephFS 将文件映射到 Ceph 对象(object)上存储,并将文件元数据(例如文件属主、目录路径、访问权限)存放在一个独立的数据池中。
Ceph 本身是一个开源存储平台,数据保存在基于 RADOS(Reliable Autonomic Distributed Object Store,可靠自主分布式对象存储)的存储集群中。它具有很高的可扩展性,并且由于是无单点故障的分布式系统,可靠性也非常出色。Ceph 为块存储和文件系统提供了不同的组件:
- Ceph RBD(RADOS Block Device):Ceph 的块存储组件,将数据和工作负载分布到整个 Ceph 集群,支持精简配置(thin provisioning),因此允许资源超配。在 Incus 中对应
ceph驱动。 - CephFS:Ceph 的文件系统组件,即本文介绍的
cephfs驱动所使用的底层存储。
需要特别注意的是,Incus 中名为ceph的驱动只使用 Ceph RBD(块存储)功能,而非完整的 Ceph 功能;若需要基于 Ceph 提供文件系统类型的存储卷,则应选用cephfs驱动。
Ceph 基础术语
在深入配置之前,先厘清 Ceph 的常用术语(源自 doc/reference/storage_ceph.md 中共享的 Ceph 术语说明):
- 对象(Object):Ceph 存储数据的基本单位。
- OSD(Object Storage Daemon,对象存储守护进程):负责存储和管理数据的守护进程。
- 池(Pool):Ceph 存储的逻辑分区,用于存放对象,也被称为数据池(data pool)、存储池(storage pool)或 OSD 池(OSD pool)。
一个CephFS 文件系统由两个 OSD 存储池组成:一个存放实际的数据,另一个存放文件的元数据。这种数据与元数据分离的设计是 CephFS 高性能与可扩展性的基础。
cephfs驱动在 Incus 中的定位
Incus 的cephfs驱动并不是一个通用的块存储驱动,它有着明确的适用范围。原文档明确指出:
cephfs驱动只能用于内容类型(content type)为filesystem的自定义存储卷。
对于其他类型的存储卷,应使用ceph驱动。ceph驱动同样可以为内容类型为filesystem的自定义存储卷提供服务,但它的实现方式是在 Ceph RBD 镜像之上叠加一个文件系统(由block.filesystem配置项控制,详见 doc/reference/storage_ceph.md)。这种"模拟"方式带来一个关键限制:由于文件系统叠加在单个 RBD 镜像之上,内容类型为filesystem的自定义存储卷同一时刻只能被分配给一个实例;如果需要多个实例(甚至是不同集群成员上的实例)同时共享一个filesystem类型的自定义卷,就必须使用cephfs驱动。
这一约束在驱动源码中有直接体现。driver_cephfs.go 中Info()方法返回的驱动信息显示:
VolumeTypes: []VolumeType{VolumeTypeCustom}, // 仅支持自定义存储卷 VolumeMultiNode: d.isRemote(), // 支持多节点共享 BlockBacking: false, // 非块设备后端 MountedRoot: true, // 以挂载根路径方式使用而CreateVolume的实现(driver_cephfs_volumes.go)则对卷类型做了硬性校验,非自定义卷(VolumeTypeCustom)或非文件系统内容类型(ContentTypeFS)都会直接返回ErrNotSupported。这从源码层面印证了"仅用于 filesystem 内容类型的自定义存储卷"这一限制。
与本地存储驱动的差异
与大多数存储驱动不同,cephfs驱动不会主动搭建存储系统,而是假定你已经安装并运行了一个可访问的 Ceph 集群(这与ceph驱动共享同一前提)。此外,cephfs提供的是远程存储:受内部网络影响,存储访问可能比本地存储稍慢;但在集群环境中,远程存储具有巨大优势——所有集群成员都能访问完全相同的存储池与内容,无需在成员之间同步存储池数据。从源码看,driver_cephfs.go 中的isRemote()方法直接返回true,Info()中的Remote与VolumeMultiNode字段均以此为据,确认了该驱动属于远程、多节点可共享的存储类型。
池的完全控制权
Incus 假定自己拥有对 OSD 存储池的完全控制权。因此,不应在 Incus 使用的 OSD 存储池中维护任何非 Incus 拥有的文件系统实体,因为 Incus 可能会将其删除。这一原则同样适用于ceph驱动,属于两个 Ceph 相关驱动共享的行为约定。
创建 CephFS 存储池的两种方式
cephfs驱动提供了两种接入 CephFS 文件系统的方式,二者通过配置项组合决定:
- 使用已有文件系统:预先在 Ceph 集群中创建好 CephFS 文件系统,然后通过存储池的
source配置项指定要使用的文件系统(或文件系统路径)。 - 自动创建:设置
cephfs.create_missing为true,Incus 会自动创建文件系统,以及配置项cephfs.data_pool和cephfs.meta_pool所指定的数据与元数据 OSD 池。
从 driver_cephfs.go 的Create()实现可以完整还原这套流程的底层逻辑:
- 首先检查
source配置,缺失时直接报错Missing required source name/path; - 将
cephfs.path与source进行一致性校验(cephfs.path必须与source匹配),并解析出文件系统名fsName与路径fsPath; - 调用
fsExists()判断目标 CephFS 是否已存在。若已存在,则拒绝设置cephfs.create_missing、cephfs.osd_pg_num、cephfs.meta_pool、cephfs.data_pool等与创建文件系统相关的键; - 若文件系统不存在,则必须设置
cephfs.create_missing=true,否则报错The requested CephFS doesn't exist。创建时cephfs.osd_pg_num若未指定,源码中会默认设为32(注释说明 Ceph 会在必要时自动调整该值); - 依次检查并创建元数据池与数据池(缺失时执行
ceph osd pool create),最后通过ceph fs new <fsName> <meta_pool> <data_pool>创建文件系统; - 完成创建后,Incus 会临时挂载该文件系统,创建
source指定的目录路径,并要求该路径必须为空(源码中Only empty CephFS paths can be used as a storage pool)。整个流程由revert机制兜底,任何一步失败都会回滚已创建的 OSD 池与文件系统。
fsExists()与osdPoolExists()的具体实现位于 driver_cephfs_utils.go,两者都通过调用ceph命令查询,并依据退出码判断:错误状态码为2时确认目标不存在,其他非零状态码则视为无法确定(可能为网络问题或 Ceph 内部问题),直接返回错误。
挂载的底层实现
cephfs驱动通过内核 Ceph 文件系统挂载 CephFS。在 utils_ceph.go 的CephBuildMount()中,Incus 会从 Ceph 集群收集三样关键信息来构造挂载参数:
- FSID(
CephFsid()):Ceph 集群的唯一标识; - Monitors(
CephMonitors()):monitor 节点地址列表,优先使用 v2 协议地址(ms_mode=prefer-crc),否则回退到 v1 协议(ms_mode=legacy); - Keyring(
CephKeyring()):客户端密钥。若密钥为空,则认为禁用了 cephx 认证。
最终构造出的挂载源形如user@fsid.fsName=/path,挂载选项包含mon_addr、name、secret等,随后通过TryMount()挂载到GetPoolMountPath(d.name)(driver_cephfs.go)。Mount()方法会先检查挂载点是否已是 Ceph 挂载点,避免重复挂载。
存储池配置选项
下表整理了cephfs驱动的存储池配置项(源自 doc/config_options.txt 中storage_cephfs-common配置组,同时对应 driver_cephfs.go 中Validate()的校验规则):
| 配置项 | 类型 | 默认值 | 作用域 | 说明 |
|---|---|---|---|---|
source | string | -(必填) | 本地(local) | 要使用的现有 CephFS 文件系统或文件系统路径;创建存储池时必填 |
cephfs.cluster_name | string | ceph | 全局(global) | 包含 CephFS 文件系统的 Ceph 集群名称,对应常量CephDefaultCluster(见 driver_ceph_utils.go) |
cephfs.user.name | string | admin | 全局(global) | 使用的 Ceph 用户,默认admin,对应常量CephDefaultUser |
cephfs.create_missing | bool | false | 全局(global) | 是否自动创建文件系统以及缺失的数据、元数据 OSD 池 |
cephfs.data_pool | string | - | 全局(global) | 创建文件系统时使用的数据 OSD 池名称 |
cephfs.meta_pool | string | - | 全局(global) | 创建文件系统时使用的元数据 OSD 池名称 |
cephfs.osd_pg_num | string | -(创建时实际默认32) | 全局(global) | 创建缺失 OSD 池时使用的pg_num值 |
cephfs.path | string | / | 全局(global) | CephFS 挂载的基础路径 |
cephfs.fscache | bool | false | 全局(global) | 是否启用内核fscache与cachefilesd缓存 |
volatile.pool.pristine | string | true | 全局(global) | 记录 CephFS 文件系统在创建时是否为空的内部状态 |
其中几个关键配置项的源码行为值得展开:
cephfs.cluster_name与cephfs.user.name:在 driver_cephfs.go 的FillConfig()中,若二者为空会自动填充默认值ceph与admin。所有底层ceph命令都会以--name client.<user>和--cluster <cluster>的方式携带这两个参数。source的必填性:Create()中若source为空会直接报错,它是连接具体 CephFS 文件系统的唯一入口。cephfs.path与source的关系:cephfs.path可以理解为存储池在 CephFS 文件系统中的子路径,创建时若两者不一致会报错cephfs.path must match the source。cephfs.fscache:使用validate.Optional(validate.IsBool)校验,开启后允许内核通过fscache/cachefilesd对 CephFS 数据做本地缓存,可提升热点数据访问性能,但需宿主机内核与用户态支持。
创建存储池示例
使用已有 CephFS 文件系统创建存储池:
incus storage create mypool cephfs source=myfs/data cephfs.cluster_name=ceph cephfs.user.name=admin自动创建文件系统及 OSD 池:
incus storage create mypool cephfs \ cephfs.create_missing=true \ cephfs.meta_pool=myfs_meta \ cephfs.data_pool=myfs_data \ cephfs.osd_pg_num=64 \ cephfs.path=/data需要注意,cephfs.path指定的路径在文件系统创建时必须为空,否则创建会被拒绝。
存储卷配置选项
cephfs驱动存储池中的存储卷同样支持一组配置项,源自 doc/config_options.txt 中storage_volume_cephfs-common配置组。由于该驱动仅支持filesystem内容类型的自定义卷,多数选项与文件权限、ID 映射和快照管理相关:
| 配置项 | 类型 | 默认值 | 生效条件 | 说明 |
|---|---|---|---|---|
size | string | 同volume.size | 适用驱动 | 存储卷的大小/配额 |
initial.uid | int | 同volume.initial.uid或0 | filesystem自定义卷 | 卷在实例中的属主 UID |
initial.gid | int | 同volume.initial.gid或0 | filesystem自定义卷 | 卷在实例中的属主 GID |
initial.mode | int | 同volume.initial.mode或711 | filesystem自定义卷 | 卷在实例中的权限模式 |
security.shared | bool | 同volume.security.shared或false | 自定义块卷 | 允许卷被多个实例共享(对cephfs而言天然多实例可共享) |
security.shifted | bool | 同volume.security.shifted或false | 自定义卷 | 启用 ID 移位(ID shifting),使卷在实例内以隔离的 ID 范围呈现 |
security.unmapped | bool | 同volume.security.unmapped或false | 自定义卷 | 禁用卷的 ID 映射 |
snapshots.expiry | string | 同volume.snapshot.expiry | 自定义卷 | 快照自动过期时间 |
snapshots.expiry.manual | string | 同volume.snapshot.expiry.manual | 自定义卷 | 手动快照的过期时间 |
snapshots.pattern | string | 同volume.snapshot.pattern或snap%d | 自定义卷 | 自动快照的命名模式,其中%d会被替换为时间戳等参数 |
snapshots.schedule | string | 同volume.snapshot.schedule | 自定义卷 | 自动快照的调度计划(cron 格式) |
这些选项与cephfs驱动能力的对应关系如下:
- 共享能力:
cephfs驱动天然支持多实例共享filesystem自定义卷(VolumeMultiNode为true),这是它相对于ceph驱动的核心优势之一。 - ID 映射:
security.shifted与security.unmapped控制卷在实例内的 ID 映射行为,与 Incus 通用的 ID 映射机制一致。 - 初始属主与权限:
initial.uid/initial.gid/initial.mode决定卷挂载进实例时的属主与权限位,默认分别为0/0/711。
快照支持与迁移行为
原文档明确指出:如果服务器端启用了快照功能,cephfs驱动支持快照。结合 driver_cephfs.go 的MigrationTypes()实现可以看出,该驱动的数据迁移(包括卷复制、迁移、备份恢复)走的是rsync通道:
if contentType != ContentTypeFS { return nil } // Do not support xattr transfer on cephfs return []localMigration.Type{ { FSType: migration.MigrationFSType_RSYNC, Features: rsyncFeatures, // delete + compress(可选) + bidirectional }, }值得注意的细节是:cephfs驱动不支持 xattr(扩展属性)传输,即通过 rsync 迁移卷时不会保留扩展属性。rsyncFeatures会根据rsync.compression配置决定是否携带compress特性。此外,Info()中OptimizedImages与PreservesInodes均为false,说明该驱动既没有针对镜像的优化路径,也不保留 inode 编号——这与 CephFS 的元数据存储模型一致。卷的复制(CreateVolumeFromCopy)与备份恢复(CreateVolumeFromBackup)也均基于 rsync/归档解包实现(见 driver_cephfs_volumes.go)。
运行环境要求与注意事项
综合源码与文档,使用cephfs驱动前需要确认以下前提:
- Ceph 集群可用:驱动不负责搭建存储系统,必须预先准备一个可访问的 Ceph 集群,并提供 monitor、FSID 与客户端密钥信息。
- 宿主机工具:driver_cephfs.go 的
load()会校验宿主机上是否存在ceph与rbd两个命令,缺失任一都会报Required tool 'xxx' is missing;同时会记录rbd --version输出版本作为驱动版本。 - IncusOS 场景:若运行在 IncusOS 环境,
load()还会检查ceph服务是否已启用。 - 内核挂载支持:驱动通过内核 Ceph 文件系统挂载(
TryMount(..., "ceph", ...)),宿主机内核需包含 Ceph 文件系统支持。 - 路径必须为空:用作存储池的 CephFS 路径在创建时必须为空目录。
- 存储池专属性:不要在与 Incus 共用的 OSD 池中放置非 Incus 管理的实体,Incus 可能将其删除。
与其他驱动的选型小结
在 Incus 的存储规划中,cephfs与ceph两个驱动均基于 Ceph 但定位不同,原文档给出的选型要点如下:
- 需要块存储(实例镜像、块设备卷)→ 使用
ceph驱动(RBD)。 - 需要可多实例共享的
filesystem自定义卷→ 使用cephfs驱动。 ceph驱动也可承载filesystem内容类型的自定义卷,但同一时刻只能绑定一个实例;cephfs驱动则可跨实例、跨集群成员共享。
综上,cephfs驱动是 Incus 中面向"分布式共享文件系统卷"场景的专用方案。若你的部署需要多个容器/虚拟机同时读写同一份自定义卷数据(例如共享代码目录、共享配置、横向扩展的工作节点),并且底层已有 Ceph 集群,cephfs就是原文档推荐的实现路径。更进一步地,可结合 doc/howto/storage_pools.md 了解存储池的通用管理命令,或阅读 doc/reference/storage_ceph.md 对比 Ceph RBD 驱动的完整能力与限制,从而在 doc/reference/storage_drivers.md 所述的各驱动之间做出合理选择。
- 后端
- 虚拟化
- 容器运行时
【免费下载链接】incus
Powerful system container and virtual machine manager
相关推荐
my2sql高级功能全解析:DML统计、大事务分析与数据库监控
my2sql高级功能全解析:DML统计、大事务分析与数据库监控 my2sql是一款强大的MySQL binlog解析工具,能够生成原始SQL、回滚SQL、去除主
数据库数据同步CLIConsoleControl与NuGet集成:快速部署与版本管理的完整流程
ConsoleControl与NuGet集成:快速部署与版本管理的完整流程 ConsoleControl是一个强大的C 类库,能够帮助开发者在WinForms或
UI库/组件开发工具Incus存储管理完全攻略:ZFS、Btrfs、Ceph等存储驱动深度对比
Incus存储管理完全攻略:ZFS、Btrfs、Ceph等存储驱动深度对比 Incus是一个强大的系统容器和虚拟机管理器,其存储管理功能提供了多种存储驱动程序来
后端虚拟化容器运行时
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考