尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Firecracker 网络接口限速热更新指南:PATCH /network-interfaces 的合并语义、令牌桶参数与底层实现

Firecracker 网络接口限速热更新指南:PATCH /network-interfaces 的合并语义、令牌桶参数与底层实现 Firecracker 网络接口限速热更新指南PATCH /network-interfaces 的合并语义、令牌桶参数与底层实现【免费下载链接】firecrackerSecure and fast microVMs for serverless computing.项目地址: https://gitcode.com/GitHub_Trending/fi/firecracker适用项目FirecrackerSecure and fast microVMs for serverless computing 关联文档docs/api_requests/patch-network-interface.md导读在 Firecracker 中网络接口virtio-net host TAP的 RX/TX 限速器rate limiter在接口创建PUT /network-interfaces/{id}boot 前时就已确定本指南讲解如何在微虚拟机启动之后通过一次PATCH /network-interfaces/{id}请求热更新其带宽与操作数ops限速参数包括请求体字段的合并更新merge语义、用 0 尺寸令牌桶取消限速的方法、令牌桶参数size/one_time_burst/refill_time的确切含义以及从 HTTP 层到 VMM 设备层的完整实现链路。读完本文你将能够在生产环境中无需重启微VM即可动态调整网络配额。1. 什么时候需要热更新网络接口限速Firecracker 面向 serverless 场景微VM 生命周期中往往不希望停机重启。然而实际负载会变化突发流量峰值、多租户带宽抢占、按量计费配额调整等都可能要求在不重建 microVM 的前提下动态调整某个网络接口的收发限速。为此Firecracker 在 REST API 上提供了专门的 PATCH 端点。与PUT创建/整体替换仅限 boot 前不同PATCH专门服务于 boot 后对已挂载网络设备限速参数的增量修改见 OpenAPI 规范 中对两个方法的操作描述方法路径operationId适用阶段语义PUT/network-interfaces/{iface_id}putGuestNetworkInterfaceByIDPre-boot only创建或覆盖网络接口完整配置PATCH/network-interfaces/{iface_id}patchGuestNetworkInterfaceByIDPost-boot only仅更新该接口的 RX/TX 限速器PATCH 成功后返回204 No Content输入非法返回400内部错误返回500可携带Error结构体。注意该端点只接受已经创建过的接口 ID且不允许在 boot 前调用详见 第 6 节。与之类似的boot 后仅限速器可更新的设计还出现在块设备上对应 patch-block.md但网络接口拥有独立的 RX/TX 两个方向更新模型略复杂。2. 第一步用 PUT 创建带限速的网络接口PATCH 的前提是先有一个网络接口。以文档中标准用法为例boot 前通过PUT /network-interfaces/iface_1创建接口并同时设定 RX/TX 双向各一个带宽令牌桶带宽单位字节PUT /network-interfaces/iface_1 HTTP/1.1 Host: localhost Content-Type: application/json Accept: application/json { iface_id: iface_1, host_dev_name: fctap1, guest_mac: 06:00:c0:a8:34:02, rx_rate_limiter: { bandwidth: { size: 1024, one_time_burst: 1048576, refill_time: 1000 } }, tx_rate_limiter: { bandwidth: { size: 1024, one_time_burst: 1048576, refill_time: 1000 } } }上述配置对应 NetworkInterface 完整结构必填host_dev_name宿主机上 TAP 设备名与iface_id可选guest_mac、mtu通过 VIRTIO_NET_F_MTU 通告给 guest范围 68~65535、rx_rate_limiter、tx_rate_limiter。本示例设定的实际含义size1024为桶容量refill_time1000毫秒表示桶从空到满需要 1000ms因此可持续速率≈1024 B/s约 1KiB/sone_time_burst10485761MiB允许接口在建立后一次性消费最多 1MiB 的额外突发额度。3. PATCH 请求体结构PartialNetworkInterface用于更新的请求体是PartialNetworkInterface结构定义见 firecracker.yaml字段类型必填说明iface_idstring是与 URL 路径中的{iface_id}必须一致rx_rate_limiterRateLimiter否接收方向新的限速配置tx_rate_limiterRateLimiter否发送方向新的限速配置其对应的强类型结构为NetworkInterfaceUpdateConfigsrc/vmm/src/vmm_config/net.rs代码注释直白地说明了这一 API 的定位Currently, only the RX and TX rate limiters can be updated. 当前只有 RX 和 TX 限速器可以被更新。也就是说你不能通过 PATCH 修改 guest_mac、mtu、host_dev_name 等其它属性——这属于 boot 前PUT的职责。由于结构上标注了#[serde(deny_unknown_fields)]请求体中出现任何未定义字段例如拼写错误的bytes而非bandwidth都会被 serde 直接拒绝并返回400这一点在 net.rs 的单元测试 中有专门覆盖构造bytes字段断言unwrap_err()。RateLimiter 结构每个方向上的rate_limiter又包含两个独立的令牌桶见 firecracker.yaml 的RateLimiter定义bandwidth令牌桶以字节为令牌控制每秒/突发可传输的数据量ops令牌桶以 I/O 操作数为令牌控制每秒可处理的包数量。也就是说限速是字节速率 包速率双维度独立的可以只配一个、两个都配、或都省略。TokenBucket 三参数语义两个桶共用TokenBucket结构同样在 firecracker.yaml三个参数的含义如下参数类型必填最小值含义sizeint64是0桶的总容量最大积攒的令牌数带宽桶单位字节ops 桶单位操作数one_time_burstint64否0初始一次性突发额度在容量之外、不随 refill 补充缺省视为 0refill_timeint64是0桶从空到满所需毫秒数补充速率由 size/refill_time 推导得出refill 只在初始突发额度耗尽后才开始规范中对补充机制的原话是The refill-rate is derived from size and refill_time, and it is the constant rate at which the tokens replenish.补充速率由 size 与 refill_time 导出是令牌补充的恒定速率。令牌消费本身不限瞬时速度——只要桶里有令牌就可以一次性全部烧掉因此突发流量被桶容量所限制而平均流量被补充速率所限制。这正是标准令牌桶算法在 Firecracker 中的落地实现见 src/vmm/src/rate_limiter/mod.rs代码为令牌桶先做 GCD 化简以避免乘除溢出并使用REFILL_TIMER_DURATION100ms 的定时器驱动补充。4. PATCHboot 后动态调整限速创建完成并 boot 之后任何时刻都可以发出 PATCH 请求来更新限速器。下面示例把iface_1的 RX 带宽提升到 1MiB/s并新增一个 2000 ops/s 的操作数限制PATCH /network-interfaces/iface_1 HTTP/1.1 Host: localhost Content-Type: application/json Accept: application/json { iface_id: iface_1, rx_rate_limiter: { bandwidth: { size: 1048576, refill_time: 1000 }, ops: { size: 2000, refill_time: 1000 } } }在实际部署中若通过 unix socket 使用 curl 向 Firecracker 的 API 套接字发请求等价的命令形如curl --unix-socket /run/firecracker.socket -i \ -X PATCH http://localhost/network-interfaces/iface_1 \ -H Content-Type: application/json \ -H Accept: application/json \ -d {iface_id:iface_1,rx_rate_limiter:{bandwidth:{size:1048576,refill_time:1000},ops:{size:2000,refill_time:1000}}}成功后返回204 No Content若路径中的 ID 与 body 中的iface_id不一致或请求体非法则返回400 Bad Request错误细节见Error结构。合并merge语义只更新你给出来的部分[!NOTE]关键语义PATCH 更新时请求体中的数据会与现有配置合并merged而不是整体覆盖。 以上述示例为例RX限速被更新但TX限速保持不变沿用创建时的 1024B/s 配置。这一行为并非巧合而是数据结构与实现层面的明确设计。NetworkInterfaceUpdateConfig的源码注释src/vmm/src/vmm_config/net.rs写道Only provided data will be updated. I.e. if any optional data is missing, it will not be nullified, but left unchanged. 只有提供的数据会被更新。任何缺失的可选数据都不会被置空而是保持不变。合并发生在桶粒度bucket 粒度即rx_rate_limiter、tx_rate_limiter、以及桶内部的bandwidth/ops各自独立只要在请求体中出现即整体生效未出现的一律保留旧值。这正是上面示例中省略tx_rate_limiter时 TX 方向纹丝不动的原因。由于这一语义需要特别留心如果你只想改bandwidth桶而保留现有ops桶那么请求中bandwidth三个参数要给全size与refill_time必填one_time_burst可选因为bandwidth一旦出现就会作为一个整体令牌桶被重新创建——缺省的one_time_burst会被视为 0 新建而不是继承旧桶的突发值。5. 取消限速0 尺寸令牌桶Firecracker 不支持直接传null来删掉限速器官方推荐的做法是给一个 0 尺寸的令牌桶size: 0且refill_time: 0。沿用前面的示例关闭 TX 方向的限速等效于不限速PATCH /network-interfaces/iface_1 HTTP/1.1 Host: localhost Content-Type: application/json Accept: application/json { iface_id: iface_1, tx_rate_limiter: { bandwidth: { size: 0, refill_time: 0 }, ops: { size: 0, refill_time: 0 } } }注意size与refill_time都是必填字段因此关闭限速必须同时显式给出size: 0与refill_time: 0二者缺一不可否则会因缺必填字段而返回 400。为什么 0 就能表示禁用在底层实现里令牌桶构造器TokenBucket::newsrc/vmm/src/rate_limiter/mod.rs有非常明确的短路逻辑// If either token bucket capacity or refill time is 0, disable limiting. if size 0 || complete_refill_time_ms 0 { return None; }即只要桶容量或补充时间为 0构造器直接返回None该桶就不会被挂载到设备上意味着对应的方向不再施加任何字节/操作数限制。这也是为什么0 尺寸令牌桶 取消限速能够成立——它并不代表速率被限到 0而是代表限速器不存在。6. 底层实现链路从 HTTP 请求到设备限速器一次 PATCH 请求在进程内的完整调用链如下可用于排查与加深理解HTTP 解析层请求进入 API server 后由parse_patch_netsrc/firecracker/src/api_server/request/net.rs处理校验路径参数iface_id非空否则按EmptyID处理并累计失败指标用serde_json::from_slice::NetworkInterfaceUpdateConfig反序列化 body失败即 400比对路径中的 id 与 body 中的iface_id不一致返回400 Bad Request错误文案为 The id from the path does not match the id from the body!成功后构造同步动作VmmAction::UpdateNetworkInterface(netif)src/vmm/src/rpc_interface.rs。同时该方法维护一组计数指标patch_api_requests.network_count/network_fails可用于观察 PATCH 调用与失败频率。RPC 调度层UpdateNetworkInterface在 rpc_interface.rs 的请求分派中执行且只允许在 boot 之后处理——在 preboot 阶段遇到该动作会直接报错代码中以check_unsupported(preboot_request(...))方式保证tests 中也有boot 前不允许 PATCH 更新的专门用例。这是因为 boot 前设备尚未建立 vhost/virtio 事件循环修改限速器没有意义。VMM 设备管理层动作落到Vmm::update_net_rate_limiterssrc/vmm/src/lib.rs其内部通过 device manager 的with_virtio_device按iface_id定位到对应Net设备并调用net.patch_rate_limiters(rx_bytes, rx_ops, tx_bytes, tx_ops)把请求体中的bandwidth桶映射为字节桶、ops桶映射为操作数桶四个方向参数RX/TX × bytes/ops分别传入并替换设备上已有的限速器实例。设备层生效Net设备的 virtio 队列事件处理在消费/生产包时都会经过令牌桶扣减替换限速器后后续所有包即按新参数计量无需重启 microVM也无需重建 TAP 或 virtio 设备。由于整个链路中 RX 与 TX、bandwidth 与 ops 都是各自独立的桶对象因此 第 4 节 的合并语义才能在每一层都严格成立。7. 常见错误与规避结合解析层代码与集成测试tests/integration_tests/functional/test_api.py把容易踩的坑归纳如下错误情形现象 / 原因PATCH 目标接口不存在或未创建返回 400设备管理器中找不到对应iface_id在 boot 前发送 PATCH返回错误该动作被 preboot 限制拦截必须在InstanceStart之后调用URL 路径 id 与 bodyiface_id不一致返回 400 The id from the path does not match the id from the body!请求体含未知字段如把bandwidth误写为bytesserde 因deny_unknown_fields拒绝返回 400令牌桶缺少必填字段如只有size没有refill_time反序列化失败返回 400想通过省略字段清空某方向的限速不会生效——省略意味着保持原样要清空必须显式size: 0refill_time: 0只传bandwidth却期望保留原opsops 会被保留合并语义但带宽桶整体重建其中one_time_burst缺失即按 0 处理需按新配置意图给全参数在发送批量或自动化 PATCH 之前建议先通过GET /machine-config级别的配置一致性思路或直接先 PUT 一个已知小配额再 PATCH 验证确认接口 ID 与当前生效限速避免在错误的合并假设下误配置。8. 与其它限速文档 / 测试的印证完整字段与数据结构规范含RateLimiter、TokenBucket、PartialNetworkInterface见 OpenAPI 规范。接口创建与校验逻辑MAC 冲突检测、同 ID 覆盖、TAP 打开失败等见 vmm_config/net.rs 中NetBuilder的实现与单元测试。HTTP 解析与 ID 校验的单测含非法字段bytes用例见 api_server/request/net.rs。令牌桶补充速率推导与 0 尺寸禁用逻辑见 rate_limiter/mod.rs。集成测试中对网络带 TX/RX 带宽限速TX/RX 带宽ops 组合限速以及boot 前后 PATCH 合法性的覆盖见 test_api.py。网络设备在宿主机侧的创建与调优背景可结合 network-setup.md 与 network-performance.md 阅读。小结PATCH /network-interfaces/{id}是 Firecracker 中微VM 不停机调整网络配额的标准入口。使用它的核心要点可浓缩为三条只改限速PATCH 仅接受iface_idrx_rate_limiter/tx_rate_limiter其余设备属性不可变按桶合并请求中出现的桶整体生效未出现的桶与方向保持原值更新bandwidth时请按新意图给全参数置 0 即禁用用size: 0, refill_time: 0的令牌桶关闭对应方向的限速而不是传null或省略字段。配合对令牌桶size/one_time_burst/refill_time语义补充速率由前两者推导的准确理解你就能在生产环境安全地动态管理每个接口的带宽与包速率。【免费下载链接】firecrackerSecure and fast microVMs for serverless computing.项目地址: https://gitcode.com/GitHub_Trending/fi/firecracker创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表