keelOS: 存储怎么设计才更好的适应AIO构架?
keelOS 的答案是两个池:宿主管一个放虚拟机的池,NAS 的盘整个交给 NAS 虚拟机,宿主永远不依赖任何一台虚拟机。按机器上盘的多少,它有三种布局,最少一块盘也能用。这篇讲为什么这样分,以及别的分法差在哪里。
一台机器,两种存储
AIO(All-in-One)是一台机器同时当 NAS 和虚拟机主机。它上面有两种性质不同的数据:
| 虚拟机的盘 | NAS 的数据 | |
|---|---|---|
| 内容 | 系统盘、镜像、检查点 | 照片、影视、备份、共享文件 |
| 容量 | 几十到几百 GB | 几 TB 到几十 TB |
| 要什么 | 随机读写快,所以放 SSD | 容量大、冗余可靠,多数放机械盘 |
| 谁在用 | 宿主上的虚拟化程序 | 局域网里的电脑、手机和别的虚拟机 |
问题是这两种数据由谁来管。全交给宿主,宿主一重启 NAS 和虚拟机一起停。全交给一台存储虚拟机,那台虚拟机一出问题所有虚拟机的盘都没了。存储怎么分,决定了这台机器哪一部分坏了会连累哪一部分。
先交代 keelOS 的结构
keelOS 分三层。最下面是 hyp,一个很小的 hypervisor,由 UEFI 启动后常驻内存,虚拟机的内存和 CPU 状态都在它手里。中间是 root,一个精简的 FreeBSD,负责驱动、ZFS、网络和设备模拟(bhyve)。最上面是虚拟机。
root 可以随时重启或升级:虚拟机暂停半分钟左右,内存留在 hyp 里不动,root 起来后原地继续,TCP 连接不断。所以在 keelOS 上,宿主重启不再等于全家停机。存储的设计要配得上这一点:宿主重启时,NAS 的盘也不能断。
别家怎么做:四种结构
现有的 AIO 方案把存储放在四种位置,每一种都有一个躲不开的代价。
| 结构 | 例子 | 池在哪 | 虚拟机的盘在哪 | 好处 | 代价 |
|---|---|---|---|---|---|
| 宿主就是 NAS | Unraid、TrueNAS、群晖 DSM、飞牛 fnOS | 宿主 | 宿主的池 | 最简单,一个界面管全部 | 宿主重启,NAS 和虚拟机一起停 |
| 存储虚拟机供全部存储 | napp-it AIO(ESXi 加一台 ZFS 存储虚拟机,“AIO”这个词的出处)、Nutanix 的 CVM | 存储虚拟机,HBA 直通给它 | 存储虚拟机上,经 NFS 或 iSCSI 回供给宿主 | 整台机器一个池,冗余、快照、备份都在一处 | 宿主依赖虚拟机:开机要先起存储虚拟机,等它就绪再挂载,再起别的虚拟机;它一挂,全部虚拟机的盘都挂 |
| 两个池 | Proxmox 加一台 TrueNAS 虚拟机 | NAS 的池在 NAS 虚拟机里;宿主另有一个放虚拟机的池 | 宿主的池 | 宿主不依赖虚拟机,NAS 挂了别的虚拟机照跑 | 盘要分成两拨 |
| 池在宿主,虚拟机只做协议 | vSAN File Services;Proxmox 宿主的 ZFS 加一个跑 Samba 的容器 | 宿主 | 宿主的池 | 一个池;文件服务和宿主隔开 | 要一条高效的宿主到虚拟机的文件通道;快照、配额要回头找宿主做 |
这张表是凭我们对这些产品的了解整理的,没有逐条去核对各家最新的版本。
第二种在机房里很成功。Nutanix 的每个节点都是这个结构,但它靠集群兜底:一个节点的存储虚拟机挂了,I/O 转到别的节点。家里和小办公室只有一台机器,没有别的节点可转。
keelOS 的选择:两个池,宿主不依赖虚拟机
keelOS 选第三种,并把它写成一条规矩:root 永远不依赖任何一台虚拟机。没有一台虚拟机在跑的时候,root 也能启动、能建虚拟机、能装系统。
zones池归 root:放虚拟机的系统盘、镜像和检查点,用 SSD。- NAS 的盘归 NAS 虚拟机:硬盘控制器整个直通过去,池由虚拟机里的 NAS 系统自己建,root 不碰。
- 虚拟机的盘不放在 NAS 上:NAS 虚拟机关了、升级了、换了另一个 NAS 系统,别的虚拟机照跑。
为什么不选另外三种:
- 宿主就是 NAS:keelOS 的 root 是可以随时重启的一层。共享服务放在 root 里,root 一重启 SMB 连接就断;放进虚拟机,连接只是暂停半分钟。
- 存储虚拟机供全部存储:单机上它是全部虚拟机的单点,开机和恢复的顺序也变复杂。
- 池在宿主、虚拟机只做协议:bhyve 上宿主到虚拟机的文件通道只有 virtio-9p,慢,Windows 权限要的扩展属性和 ACL 也传不全。
两个池的代价是盘要分成两拨。下面的三种布局就是在回答:有几块盘的时候,这两拨怎么分。
三种盘布局
按盘的数量选:盘够就用 A,盘少用 B,只有一块盘用 C。三种都是两个池,都守住“root 不依赖虚拟机”。
A 和 B 里 NAS 拿到的是真盘;C 里 NAS 的池叠在 root 的池上面。
| 布局 | 适合 | keelOS 装在哪 | zones(放虚拟机) |
NAS 的盘 | ISO 放哪 |
|---|---|---|---|---|---|
| A 标准 | 一块小的启动盘,两块 SSD,若干数据盘 | 单独一块启动盘 | 两块 SSD 做镜像 | 其余的 SSD/HDD 直通 | 启动盘剩下的空间 |
| B 盘少 | 一块或两块 SSD,若干数据盘 | 和 zones 同在一块盘上,或同在一对镜像盘上 |
那块盘或那对镜像的其余空间 | 其余的盘直通 | zones 里 |
| C 只有一块盘 | 迷你主机、试用 | 和 zones 同在这块盘上 |
这块盘的其余空间 | zones 上的一个 zvol |
zones 里 |
A 是标准做法。 系统、虚拟机、NAS 三拨盘互不相干:启动盘坏了换一块重装,zones 是镜像,坏一块 SSD 虚拟机不停,NAS 的冗余由 NAS 系统自己做。keelOS 的启动分区只占 2 GiB,启动盘剩下的空间正好放安装用的 ISO,这样刚装好、还没建池就能上传 ISO。
B 省一块盘。 keelOS 装在盘的开头,同一块盘剩下的空间建 zones。用一对镜像盘时,每块盘开头各有一份启动分区,坏任何一块都还能启动。
C 是盘实在少的时候。 NAS 虚拟机拿不到真盘,拿到的是 zones 上的一个 zvol,它在上面再建自己的文件系统。NAS 里删掉的空间能还给宿主:虚拟机里 TRIM 之后,zvol 在宿主上占的空间会掉回去,这一点实测过。代价是这块盘坏了全部都没了,要靠备份到别的机器。
盘怎么交给 NAS:整个控制器直通
A 和 B 里“其余的盘直通”指的是把硬盘控制器整个交给 NAS 虚拟机,不是把盘做成虚拟盘。NAS 系统用自己的驱动直接操作硬件,看到的是真盘:SMART、写缓存、真实的错误都在。TrueNAS 官方对虚拟化部署的建议也是这样。
| 控制器 | 在 keelOS 上的状态 |
|---|---|
| NVMe(整块盘就是一个控制器) | 实测通过,并且跨 root 重启不断 |
| 板载 SATA(AHCI) | 实测通过:带盘建池、写入、校验一致,scrub 0 错误;带盘跨 root 重启还没测 |
| SAS HBA(LSI IT 模式) | 还没有硬件测过 |
几条为 NAS 场景定的规矩:
- 按厂商、型号和序列号认设备,不按插槽。 换了插槽照常工作。
- 开机时就把这些设备留住,root 的驱动没机会碰它们。 root 不会自动导入 NAS 的池,两边同时写会毁数据。
- 一个设备只归一台虚拟机。 第二台要同一个设备时直接拒绝。
- IOMMU 由 hyp 管,不由 root 管。 root 重启时控制器的 DMA 一直有效,这是下一节能成立的原因。
控制器直通有一个前提:给 NAS 的盘和 root 自己用的盘不能在同一个控制器上。最常见的搭配是系统和 zones 用 NVMe,机械盘接板载 SATA 或 HBA,正好分得开。分不开的机器(系统盘和数据盘全在板载 SATA 上)要按盘而不是按控制器来交,这个还没做。
实测:宿主重启,存储不断
拿着整块 NVMe 的 NAS 虚拟机,在持续写盘时跨过了 root 重启,没有超时、没有复位、没有错误。开发机是双路 Xeon、192 GB 内存,NAS 虚拟机是 FreeBSD,直通的是一块 Intel P3600。
| 测试 | 结果 |
|---|---|
| NVMe 直通后的基本读写 | 虚拟机里读 1.37 GB/s;ZFS 池写 20 GB,scrub 0 错误 |
| 虚拟机一直 fsync 写盘,root 重启 4 次(2026-09-29) | 每次暂停 21–23 秒;写盘循环没断,没有 NVMe 超时和复位,池 ONLINE,scrub 0 错误 |
| 累计 root 重启次数 | 14 次,无错误 |
| 一台虚拟机带两个整块设备(NVMe 加一个没接盘的板载 AHCI),root 重启 5 次 | 两个设备都正常,0 错误 |
| 17 台虚拟机同时在跑,其中有这台 NAS | root 重启 65.5 秒,17 台全部恢复 |
| 运行中把 NVMe “拔掉”(关掉它上游端口的链路来模拟) | root 不受影响;只有这台虚拟机里的设备失效、池挂起 |
| 板载 SATA 控制器带盘直通(另一台开发机,2026-09-30) | 建池,写 2366 MiB 随机数据,导出再导入后 sha256 一致,scrub 0 错误 |
这能成立靠两件事。虚拟机的内存在 hyp 的池里,root 重启时不动。控制器的 IOMMU 映射也在 hyp 手里,所以虚拟机暂停的那一刻已经发给盘的命令照常做完,数据写进虚拟机的内存,恢复后补上中断。虚拟机里看到的只是一段 I/O 延迟。
网络这一侧有一个限制:用 SR-IOV 虚拟功能(VF)做网卡的虚拟机,现在在 root 重启时要关机再开。要让 NAS 的连接也不断,它的网卡用 virtio。
还没做完的
两个池的结构和控制器直通现在就能用;下面这些还没做,或者还没测。
- 布局 A 的 ISO 放启动盘:ISO 现在只能放在
zones里,启动盘 2 GiB 之后的空间还没用上。 - 网页按布局引导:安装向导只装到一块盘,建池(单盘、镜像、raidz)和第二份启动分区在装好后的“存储”页上做。页面还不会问“这块盘给虚拟机还是给 NAS”。
- 按盘交给 NAS:系统盘和数据盘在同一个控制器上的机器,现在只能用布局 C。
- SATA 控制器带盘跨 root 重启没测;SAS HBA 没有硬件。
- 布局 C 的调优:ZFS 叠在 zvol 上,两层的压缩、缓存、块大小怎么分工还没有实测数字。
- VF 跨 root 重启:带 VF 的虚拟机现在要关机再开。
- 第三方 NAS 系统带直通盘:飞牛 fnOS 作为虚拟机装过、能用;把直通的盘交给它建存储空间还没测。上面的实测用的都是 FreeBSD。
- 虚拟机备份到 NAS:还没有。
还有一件在计划里的事:keelNAS,我们自己出的一台 NAS 虚拟机,和 keelOS 并列的项目。现有的 NAS 系统都假设自己是宿主,带着虚拟机和应用功能,装进虚拟机后这些是多余的;keelNAS 只做存储(池、共享、权限、快照、SMART),为“当虚拟机”而设计。它现在只有调研和设计,没有代码。在那之前,NAS 虚拟机里装你喜欢的系统。
结语
AIO 的存储设计归结起来是一个问题:谁依赖谁。keelOS 的回答是宿主不依赖虚拟机,虚拟机的盘和 NAS 的盘各有各的池;再加上宿主重启时虚拟机和直通的盘都不断,三层里任何一层要动,都不必停掉另外两层。
选布局只看盘的数量:有启动盘、两块 SSD 和数据盘,用 A;SSD 不够,让系统和 zones 合用,用 B;只有一块盘,用 C。
相关的文章:《keelOS: 新时代的AIO系统,专为NAS爱好者打造!》讲整体,《keelOS: 强化VM的硬核技术,PCIe直通,SR-IOV,一个都不能少!》讲直通的细节。