news 2026/9/12 11:15:07

Firecracker 如何配置 vhost-user 块设备并对接外部存储后端

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Firecracker 如何配置 vhost-user 块设备并对接外部存储后端

Firecracker 如何配置 vhost-user 块设备并对接外部存储后端

【免费下载链接】firecrackerSecure and fast microVMs for serverless computing.项目地址: https://gitcode.com/GitHub_Trending/fi/firecracker

如果你的块设备 IO 需要在 Virtio 队列处理同层实现自定义逻辑——例如通过网络取回块数据、或实现精细的 readahead 算法——可以用 Firecracker 的 vhost-user 块设备:它把 Virtio 队列的处理委托给宿主机上的另一个用户态进程(backend),Firecracker 只作为 vhost-user 前端参与控制面。本文给出从启动 backend、通过 API 添加设备,到在 guest 内验证设备、并在启动后更新设备配置的完整操作路径。

注意:按 发布策略,vhost-user 块设备目前处于developer preview,文档明确建议不要在生产环境使用,且该功能可能随时变化。

前后端分工与交互时机

Vhost-user 是一个用户态协议。在这个架构中,Firecracker(前端)负责:

  • 通过 Unix domain socket(UDS)连接 backend;
  • 与 backend 和 guest 做 feature negotiation;
  • 处理 guest 发起的设备配置请求;
  • 把 guest 内存和 Virtio 队列信息(包括 guest 内存区域的 fd 和队列通知的 fd)共享给 backend。

backend 负责实际处理 guest 的 IO 请求。UDS socket 只用于控制面,不参与数据面。

有三个时间点前后端会发生交互:

  1. 设备初始化:创建 vhost-user 设备时,Firecracker 连接对应的 UDS socket,与 backend 协商 Virtio/Vhost feature 并获取设备配置;
  2. 设备激活:guest 驱动完成设备设置后,Firecracker 把内存表和 Virtio 队列信息共享给 backend;
  3. 配置更新:对 vhost-user 设备发送PATCH请求时,Firecracker 重新向 backend 请求设备配置,使新配置对 guest 可见。

拓扑上,每个 vhost-user 设备连接自己独立的 UDS socket,无法多设备共享一个 socket(协议层无法区分不同设备的消息)。一个 backend 进程可以服务多个设备,也可以每个设备对应独立 backend。

Firecracker 只实现了 vhost-user 前端。开源 backend 参考实现包括 Qemu、Cloud Hypervisor、crosvm 和 SPDK 中的 vhost-user-blk,也可以自行实现;文档示例以 Qemu 的vhost-user-blk为准。

准备条件

  • 一台满足 Firecracker 要求的 KVM 宿主机(x86_64 或 aarch64 Linux,参见 kernel 支持策略);
  • Firecracker 二进制,并以后台方式留出 API socket。getting-started 中的简化启动方式(不使用 jailer):
API_SOCKET="/tmp/firecracker.socket" sudo rm -f $API_SOCKET sudo ./firecracker --api-sock "${API_SOCKET}"
  • 一个 vhost-user backend 二进制和它服务的块文件(backing file)。测试框架中 Qemu backend 的启动命令形如vhost-user-blk --socket-path <socket> --blk-file <file>,见 utils_drive.py。

一个前提细节:UDS socket 由 backend 侧创建并监听,Firecracker 是连接方。因此要先启动 backend,再向 Firecracker 发PUT /drivessocket字段填 backend 实际监听的 socket 路径。

第一步:启动 vhost-user backend

文档给出的示例配置(Qemu backend):

vhost-user-blk --socket-path=${backend_socket} --blk-file=${drive_path}
  • ${backend_socket}:UDS socket 路径,替换成 backend 实际创建监听的路径;
  • ${drive_path}:backend 服务的块文件路径,替换为你准备的后端镜像/磁盘文件。

如果需要只读设备,只读属性配置在 backend 一侧而不是 Firecracker 一侧:测试框架对 Qemu backend 的只读场景就是在命令行追加--read-only(见 utils_drive.py)。只要 backend 通告VIRTIO_BLK_F_ROfeature,Firecracker 就会接受,设备表现为只读。

第二步:向 Firecracker 添加 vhost-user 块设备

在 microVM 的其他资源(boot-source、rootfs、网络等按 getting-started 配置完成)之后、启动实例之前,发送PUT /drives请求。文档示例:

curl --unix-socket ${fc_socket} -i \ -X PUT "http://localhost/drives/scratch" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ -d "{ \"drive_id\": \"scratch\", \"socket\": \"${backend_socket}\", \"is_root_device\": false }"

其中${fc_socket}是第一步中--api-sock传入的 API socket 路径(示例为/tmp/firecracker.socket),${backend_socket}与第一步中 backend 监听的 socket 路径一致。socket字段的定义("Path to the socket of vhost-user-block backend")可在 firecracker.yaml 中查到。

与 virtio 块设备不同,vhost-user 驱动没有path_on_hostis_read_onlyio_engine这些字段,请求体只需要drive_idsocketis_root_device

配置完成后按标准流程发送InstanceStart启动 microVM(getting-started 中的curl -X PUT "http://localhost/actions"请求)。

启动后验证设备

集成测试 test_drive_vhost_user.py 的做法是在 guest 内通过blockdev检查设备:

# 设备列表:确认 /dev/vdX 存在及 ro/rw 属性 blockdev --report # 指定设备的大小(字节):与 backend 侧块文件大小比对 blockdev --getsize64 /dev/vdb

测试中作为 root device 的 vhost-user 驱动对应/dev/vdablockdev --report首列显示rorw,用于确认只读/读写属性是否与 backend 配置一致。blockdev --getsize64的输出应与 backend 所服务块文件的大小相等(测试用stat获取文件字节数后与 guest 内查询值断言一致)。

启动后更新设备配置(PATCH)

vhost-user 场景下,Firecracker 不直接接触 backing file,backend 对文件的改动不会自动被 Firecracker 感知。vhost-user 协议中 backend 主动通知前端的VHOST_USER_BACKEND_CONFIG_CHANGE_MSG机制Firecracker 不支持,取而代之的是PATCH /drivesAPI:它只需要drive_id一个必填属性(其他可选属性对 vhost-user 无意义):

curl --unix-socket ${fc_socket} -i \ -X PATCH "http://localhost/drives/scratch" \ -H "accept: application/json" \ -H "Content-Type: application/json" \ -d "{ \"drive_id\": \"scratch\" }"

收到该请求后,Firecracker 会从 backend 重新获取设备配置并向 guest 发送配置变更通知。集成测试test_config_change验证过的流程是:backend 侧完成 resize → 对同一drive_idPATCH→ guest 内blockdev --getsize64报告新大小。

已知限制与工程注意事项

快照不支持。配置了 vhost-user 设备的 microVM 不能做快照,尝试创建快照会失败;集成测试断言的报错为Devices without snapshot support are present: vhost-user-block(id: rootfs)

重复 PUT 会重建连接。对已存在的drive_id再次发送PUT /drives,Firecracker 会关闭到 backend 的现有连接并建立新连接,可能需要重启 backend。

性能代价。为了让 backend 能处理 virtio 请求,guest 内存必须以共享内存映射(memfd_create+MAP_SHARED)提供。文档的测试观察到共享映射的 page fault 比私有映射最长慢约 24%,建议在自己的 workload 上先做性能剖析再决定是否使用 vhost-user。

没有宿主机 page cache。与直接读写宿主文件的 virtio 块设备不同,vhost-user 路径下 backing file 不经过 Firecracker,宿主机 page cache 的缓存和 readahead 收益不在此路径中,需要的话要在 backend 内实现自有缓存。

限流职责转移。virtio 块设备内置的 rate limiting 对 vhost-user 不生效,Firecracker 不参与请求处理,限流是 backend 的责任;也可以用 cgroups 限制 guest 的宿主 CPU 消耗来间接限制 IO。

安全边界。文档列出的要点:

  • guest 内存的 memfd fd 会出现在 Firecracker 进程的 procfs 中(形如lrwx------ ... 32 -> /memfd:guest_mem (deleted)),能访问该 fd 的宿主进程可观察到 guest 运行行为;在设备全部激活前 memfd 不会被关闭,因此需要把 Firecracker 的 procfs 访问限制在可信进程内;
  • 推荐用 jailer 运行 Firecracker,但 jailer 目前只能运行 Firecracker 二进制本身,backend 需要另外放进 jailer 或施加其他隔离措施,因为 guest 有可能触发 backend 代码中的缺陷;
  • backend 应实现等待 Firecracker 连接的超时,避免 Firecracker 提前退出导致资源耗尽;backend 崩溃时可向 Firecracker 发送SIGBUS之类的信号使其一并退出,避免遗留孤儿进程;
  • 使用 jailer 时注意 file size 资源限制不能小于最大的 guest 内存区域(memfd 被视为文件)。

相关文档

  • vhost-user 块设备:架构、backend 列表、安全考虑与示例配置
  • 启动后更新块设备:PATCH /drives 对 virtio 与 vhost-user 驱动的不同语义
  • 块设备 IO 引擎:Sync/Async引擎与 vhost-user 的对比位置
  • Getting Started:Firecracker 启动与 API 使用基础
  • test_drive_vhost_user.py:boot、设备排序、resize、快照失败的验证用例

【免费下载链接】firecrackerSecure and fast microVMs for serverless computing.项目地址: https://gitcode.com/GitHub_Trending/fi/firecracker

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 11:11:06

Android 16图形系统架构解析:从绘制到显示全链路拆解

做图形系统相关开发这些年&#xff0c;被问得最多的问题其实就一个&#xff1a;屏幕上的一张UI&#xff0c;到底是怎么从App里的代码变成像素的&#xff1f;尤其是到了Android 16这个版本&#xff0c;图形栈涉及的东西更多了&#xff0c;HDR、可变刷新率、多窗口、屏幕折叠形态…

作者头像 李华
网站建设 2026/9/12 11:10:22

移动端大语言模型压缩与优化技术解析

1. 项目背景与核心价值当Clawdbot在硅谷一夜爆红时&#xff0c;我正在调试一个本地化部署的LLM模型。手机突然弹出一条推送——这个仅用24小时就引发全球关注的项目&#xff0c;本质上在做一件极其简单却颠覆性的事&#xff1a;通过压缩和优化技术&#xff0c;将原本需要云端算…

作者头像 李华
网站建设 2026/9/12 11:09:50

STM32F417上Zxing二维码解码移植实战:内存规划与参数调优

简介&#xff1a;一套基于 STM32F417 的二维码解码工程方案&#xff0c;面向嵌入式开发者和对 Zxing 移植感兴趣的读者&#xff0c;主要解决在资源有限的 MCU 上完成二维码图像采集、预处理、解码与结果输出这一实际问题。资源以 1.54MB 的 zip 压缩包发布&#xff0c;内部共 2…

作者头像 李华
网站建设 2026/9/12 11:08:42

Transformer输出层设计:线性变换与Softmax原理详解

1. Transformer输出层设计原理Transformer模型的输出部分由线性层(Linear)和Softmax层组成&#xff0c;这是整个模型生成预测结果的关键环节。在GPT-2等自回归模型中&#xff0c;输出层负责将经过多层Transformer block处理后的高维特征表示转换为词汇表空间中的概率分布。1.1 …

作者头像 李华
网站建设 2026/9/12 11:06:52

树莓派搭建Kafka与RabbitMQ消息队列集群指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华