写点什么

技术解读:Cube 安全容器高并发低延时实践之路

腾讯云 IaaS 前沿技术团队

  • 2023-07-04
    北京
  • 本文字数:5744 字

    阅读完需:约 19 分钟

技术解读:Cube安全容器高并发低延时实践之路

随着云计算技术的发展,Serverless 凭借其免运维、按量付费和弹性伸缩等特点逐渐成为热门话题。然而,传统的虚拟化计算无法满足Serverless的需求,如高并发创建能力、冷启动速度等。为此,腾讯云技术团队推出了 Cube 轻量虚拟化产品,通过对管控流程、KVM、主机 OS、VMM、子机 OS 等进行全链路精简和优化,实现高性能、低开销、高密度的运行环境。Cube 还针对快照方案进行了深度优化,大幅提升启动速度,从而更好地满足 Serverless 场景的需求。

背景

随着云计算技术的持续演进,具有免运维,按量付费,弹性伸缩等特性的 serverless 逐渐成为行业关注的热点。从 Serverless 技术最有代表性的 FaaS 产品现网运营数据来看,有以下特点:


1) 单实例生命周期短, 平均执行时间 50ms, P95 小于 100ms

2) 并发创建能力要求高, 资源流转快, 每天近千万次的资源流转(创建/销毁)

3) 冷启动速度要求高, 要求百毫秒级的冷启动时延


在通用的虚拟化计算环境下,无法满足 Serverless 的以上特点, 根本原因是通用虚拟化的实例创建过程会涉及到和装箱, VPC、CBS、安全组等多个子系统的交互,实例创建往往需要等待数十秒的时间,无法满足 Serverless 对冷启动和高并发的诉求。 而实例本身的创建销毁时间远远大于实例本身的执行时间, 会导致大量的算力浪费。


在实际的运营中,通用虚拟机架构下,为了满足 Serverless 的运营指标诉求, 通常采取储备资源池的方案, 也就是提前创建好一批虚拟机实例, 直接用提前创建好并已运行的虚拟机实例来满足客户高并发高资源流转的诉求。 这个方案通过储备资源池来平衡客户高并发高资源流转的需求与平台低并发资源流转慢的矛盾, 但储备资源池会给平台带来比较大的呆滞成本以及很大的算力浪费。


为了让底层基础设施更加匹配 Serverless 的诉求, 腾讯云技术团队对管控流程、KVM、主机 OS、VMM、子机 OS 进行全链路精简和优化, 设计了 Cube 轻量虚拟化产品。Cube 方案能提供高性能、低开销、高密度运行环境,涵盖从主机 OS、虚拟化、虚拟机 OS 整套优化。


此外,Cube 还针对快照方案进行了技术栈深度优化,引入多项关键功能,将启动速度进一步提升,使得轻量级场景下的虚拟机运行更加迅速。通过这些优化,Cube 在有限空间内,能提供高性能、低开销的解决方案。

整体架构



技术挑战

虚拟机管控流程

通用虚拟机的创建流程涉及与虚拟化,网络,存储等诸多 IaaS 基础设施的交互,这是制约通用虚拟化高并发高资源流转能力的关键瓶颈。


Cube 轻量虚拟机创建流程完全与 IaaS 基础设施解耦, 将整个虚拟机的创建变成一个单台物理机内可以闭环的操作。

 

具体实现上,Cube 母机初始化时与 IaaS 基础设施交互, 得到可与 IaaS 交互的网络资源(VPC IP)与存储资源(CBS), 并在内部闭环管理网络和存储资源的分配。

  • 网络上,Cube 在 VPC 网络之上, 实现了一个单机维度的 Cube 网络, 而且这个网络可以通过 CubeGW 实现和 VPC 网络的互通;

  • 存储上,Cube 将本地盘和 CBS 云盘资源进行了切割管理,将只读存储通过 virtiofs 的方式暴露给虚拟机, 可写存储结合写时复制的技术以 virtio-blk 的方式暴露给虚拟机。


通过上述存储,网络等虚拟机配套资源全部在母机范围内的闭环管理,从管控流程上完全消除了外部基础设施的影响因素。

 

虚拟化底座(KVM)

KVM 作为虚拟化的底座,在通用 VM 场景中已经经过千锤百炼,然而在轻量虚拟化产品高并发超买的场景,却暴露出来了很多性能和时延相关问题,典型的如高并发操作下 lock contention 导致的时延。

首先是 irqfd 操作引入接近 100ms 时延。irqfd 是 KVM 提供给 VMM 的将 eventfd 绑定到 VM 中断的一个 feature,用户态的 VMM 通过 wirteirqfd,KVM 在内核层面将对应中断注入到 VM 中去,这个 feature 通常被 virtio 设备使用,比如 virtio 设备的队列事件,在 CUBE 产品中因为 irqfd 注册引入了 60ms 以上时延。



经过对 KVM 中 irqfd 注册流程分析,腾讯云技术团队针对非直通设备(CUBE 产品)场景彻底消除了这部分时延影响,而针对更为棘手的直通设备场景,积极在社区讨论终极解决方案。

 

另外一个典型时延问题是,nx-lpage-recovery 内核线程创建会导致创建 VM 引入 100ms 的抖动,是因为高并发场景下这个内核线程启动引入了同步等待,放大了 VM 创建的时延。



经过调查,腾讯云技术团队发现 nx-lpage 是 KVM 是为了缓解 ITLB multihit CPU 漏洞的软件缓解方案,而 nx-lpage-recovery 内核线程则是针对这组缓解方案造成性能损失的补偿机制。且不说这个补偿方案的效果,CUBE 产品环境中,该方案都不会触发这个问题(需要 VM 使用大页),再者新版的 Intel CPU 已经 fix 了这个硬件漏洞,看起来很普通的一个内核线程启动,在场景中竟然有这么大副作用,对 KVM 持续优化深入到每一个细节。


除了这些问题,针对高并发超买场景降低开销和时延,团队还对 KVM 的一些参数进行了调整和调优,比如 halt_poll_ns 等。

轻量化 VMM

社区近些年兴起基于 RUST 的轻量级 VMM,相比 QEMU 简化了设备模型,更小的内存和运行开销,在 CUBE 产品中,腾讯云技术团队基于 cloud-hypervisor 构建 VMM 组件(cube-hypervisor),是因为其在保持了轻量化的同时,有较为完备的现代 VMM 具备的基础功能,如热插拔/TDX 等。

存储架构调整



在产品架构上为了适配容器场景,腾讯云技术团队对 VM 存储进行读写分离,使用更为灵活的 virtiofsd 为容器提供 rootfs 目录,使用传统的 disk 为容器提供临时数据写盘。为了达到极致的性能,对 viriofsd 进行了 native 改造,改造后的 virtiofs 从独立进程变成了 CH 的一组线程,处理上优化了 vhost 逻辑,可以像普通 virtio 设备一样直接操作后端 fs。



快照方案提速

在技术演进方面,腾讯云技术团队对 VM 冷启动做了多项优化,如通过并发内核加载加速 VM 启动,以及调优启动过程中的阻塞行为,但仅仅通过调优只能将 VM 交付时间缩减到 100ms 左右,无法达到对启动时延的极致要求,而在实际场景中,不同 VM 的内核和 rootfs 都是一致的,针对这个高度重复的动作,是否有办法做到一次性优化么?答案是有的,这里,腾讯云技术团队选择了 VM 快照技术。

 


快照技术原本是 VMM 提供的对 VM 快照的保存和恢复,快照保存时,将 VM 暂停下来,将 VM 所有状态保存到快照文件中,快照恢复时,基于快照文件恢复 VM,恢复完成之后继续 VM 运行,快照技术语义上支持 1 to 1 的 VM 状态恢复,且对 VM 后端设备有一致性要求(磁盘/网卡)。

 


首先,需要对快照技术进行 1 to n 的 VM 状态恢复改造,实现 VM 内部状态和后端设备无关,并可以将保存的旧设备状态恢复到新设备。实际实现中,通过替换后端设备,以及基于快照中设备状态对设备进行重新初始化,实现了快照恢复过程中后端设备无感替换。


经过对快照技术持续优化,最终做到将 VM 交付时间从 100ms+降低到 20ms 以内,同时为单个 VM 减少了 20MB+内存(单机 1000 个 VM 节省 20G 内存)。

网络方案重构

资源池化是降低并发资源访问的法宝,在产品架构上,通过池化解决一众资源依赖问题,如磁盘池化,CGROUP 池化,以及网络设备池化,网络方面更是结合 ebpf 实现快速转发路径,已经努力将网络层面的开销降到了最低,然而高并发测试总是能够发现彩蛋,这一次是 TAP 设备,实测发现,VM 在 TAP 设备初始化上耗时 50ms 以上,MAX 甚至超过 100ms。

 


VM 创建过程需要对 TAP 设备做初始化,然而这个高并发的操作在母机内核触发了全局锁冲突,造成大量时延。很显然解决这个问题需要深入母机内核 TAP 做深度优化,然而有没有跟简单的办法呢,是否可以避免重复的 TAP 设备初始化动作呢?腾讯云技术团队对 TAP 网络方案进行了重新设计,将 TAP 设备的初始化放在了 TAP 池化初始化中,而 VM 的网络初始化只需要从池子中申请一个对应的资源就可以了,经过对方案的不断调优,成功将 VM 启动过程中 TAP 设备初始化降低到了 1ms 级别。

 

母机 OS

高并发场景下,高频的创建销毁会带来母机全局资源的锁竞争,导致性能的波动和不可预期性。

Cube 为了保证高并发场景下冷启动时延的可预期性, 通过以下技术手段来优化

  • 计算,网络,存储资源的池化

  • 对于无法池化的资源,尽量减小对全局资源的冲击

  • Mount/umount

在 mount/umount 过程中都需要全局的命名空间锁来保证关键路径的串行操作,在安全容器环境的构建中不但需要通过 overlayfs mount 创建容器的 rootfs,还需要各种形式的 bind mount 来实现 hosts,dns 等个性化配置。Cube 通过把这种个性化的 bind mount 转换成 overlayfs 的一个层次(layer)的方式使 mount/umount 次数减少到最低。

  • 进程创建/销毁

在进程的创建,销毁过程中也需要全局的 task 锁来确保关键路径的串行操作, 为了确保进程创建的时延有保证,cube 技术团队将进程销毁的优先级调低, 并引入排队机制串行执行进程的销毁操作。同时通过进程合并等手段减少虚拟机创建需要创建的进程数目。


除了高并发的优化,针对高密场景的资源复用,cube 也对虚拟机内核,虚拟机镜像,以及容器镜像的复用做了一些工作

  • 虚拟机镜像通过 pmem 设备方式在母机层面在所有虚拟机之间进行只读共享,子机通过 DAX 方式直接访问母机内存

  • 容器镜像的读写存储分离,只读部分通过 virtio-fs 暴露给虚拟机,并实现容器镜像和 page cache 在母机层面的复用; 可写部分通过 virtio-blk 暴露给虚拟机, 可写块存储使用空洞文件减少实际磁盘使用量的同时, 通过 reflink 和写时复制技术实现磁盘块的按需使用

子机 OS

通用虚拟机的设计目标是提供一个通用的计算环境,要求子机 OS(内核与操作系统)的功能足够丰富与灵活,但在 Serverless 场景中,过多的功能反而变成了一种负担,牺牲了极速的启动速度,也额外耗费了太多的资源。Cube 为了满足 Serverless 极致的用户体验,对子机 OS 的所有功能模块进行了深度的裁剪和优化。

 

子机镜像(虚拟机 rootfs)层面:

  • 裁剪掉所有不需要软件包,只保留极少数关键库和命令,镜像大小控制在 128MB 以下。

  • 使用 Cube-agent 作为 init 替换庞大的 systemd 体系,系统启动时只进行少量必须的初始化操作。

子机内核层面:

  • 关闭所有不需要的模块和功能,减少内核代码段和数据段的大小。

  • 调整内核各个子系统的 hash 表大小,减少额外内存消耗。

  • 调整预留内存的默认计算算法,提供更多资源给业务进程。


经过裁剪优化,1C128MB 的规格下,相比通用虚拟机秒级启动速度,Cube 虚拟机启动时间降至 80ms 以下,启动时内存消耗也降至 20MB 左右。

 

总结

目前在大量背景负载情况下,50 并发启动 Cube 轻量虚拟机的时延可以控制在 100 毫秒以下的水平。



回馈社区

值得一提的是,腾讯云技术团队在优化 Cube 在高密高并发场景下性能的同时也发现并修复了其他开源组件长期以来没有被发现的问题。

 

golang  runtime 相关:

  • 在高并发操作 tap 设备时会触发了 go runtime epoll 对象复用的 bug。

这是一个 go net epoll 模型的重大远古缺陷,已提交社区并推动修复。

internal/poll, runtime: got `not pollable` err when reading fifo or socket · Issue #59545 · golang/go · GitHub

 

kata container 相关:

  • 容器控制流程 hang 住的问题反馈与修复

runtime: all APIs are hang in the service.mu · Issue #6059 · kata-containers/kata-containers · GitHub

runtime: unix socket file leak · Issue #6171 · kata-containers/kata-containers · GitHub

 

cloud-hypervisor 相关:

https://github.com/cloud-hypervisor/cloud-hypervisor/pull/5428

  • 支持网络设备配置 offloading 能力 feature

vmm: add configuration for network offloading features by zhuangel · Pull Request #5029 · cloud-hypervisor/cloud-hypervisor · GitHub

  • 支持 block 设备 latency 统计

https://github.com/cloud-hypervisor/cloud-hypervisor/pull/5044

  • 解决 vcpu 异常退出造成死循环问题

vmm: properly set vcpu state when thread exited by zhuangel · Pull Request #5211 · cloud-hypervisor/cloud-hypervisor · GitHub

  • 优化 virtio console 信号线程

Do not start signal thread is there is no need. by zhuangel · Pull Request #5240 · cloud-hypervisor/cloud-hypervisor · GitHub

 

virtiofs 相关:

  • 在 cache=never 模式下,virtiofs 前端驱动的 private mmap 的 page cache 存在一致性问题。

[RFC PATCH] fuse: invalidate page cache pages before direct write - Hao Xu

  • 在 cache=never 模式下,对 shared_mmap 的缺乏支持。

[PATCH] fuse: add a new flag to allow shared mmap in FOPEN_DIRECT_IO mode - Hao Xu

  • 在 cache=always 模式下目录 page cache 失效,导致 readdir 性能变差。

passthrough: add KEEP_CACHE flag for directory file when cache=always (!172) · Merge requests · virtio-fs / virtiofsd · GitLab

  • 没必要的 open(/proc/pid/mountinfo)操作导致的 mount 操作时延抖动。

passthrough: open mountinfo proc file in case we readlly need (!167) · Merge requests · virtio-fs / virtiofsd · GitLab

  • 无效的后端读写 size 限制。

server: remove buffer size check for read/write (!161) · Merge requests · virtio-fs / virtiofsd · GitLab

 

腾讯云技术团队对这些问题提出了修复方案,并将其贡献给了上游社区。此外,根据使用场景在功能上做了进一步的增强。

  • virtiofs 设备增加了 ratelimiter 功能以支持 QoS。

Introduce RateLimiter to virtiofsd (!147) · Merge requests · virtio-fs / virtiofsd · GitLab

  • virtiofsd 新增加了 cache=part 模式,使得节省内存的同时不影响 readdir 操作的效率。

Add a new cache policy Part (!173) · Merge requests · virtio-fs / virtiofsd · GitLab

 

rust-vmm 相关:

  • 解决 linux-loader 没有正确处理 ELF align 的问题

https://github.com/rust-vmm/linux-loader/pull/128

  • 解决 virtio-queue 没有正确处理 descriptor align 问题

https://github.com/rust-vmm/vm-virtio/pull/220

 

展望

目前为止,Cube 对底层支撑功能以及各相关组件进行了大量深入的分析,并有针对性进行优化, 真正的做到了用户按量付费,平台按需生产,并且可以满足用户的性能诉求。


技术的道路没有尽头,后续随着技术方案的不断创新和迭代,腾讯云技术团队将不遗余力地持续提高 Cube 的底层性能,与此同时,在用户体验,易用性等方面做更多的探索和增强。

 

2023-07-04 13:127412

评论

发布
暂无评论
发现更多内容

架构师训练营 - 第八周作业

一个节点

极客大学架构师训练营

一个典型的大型互联网应用系统使用了哪些技术方案和手段

皮蛋

RCEP是重振全球经济和反对保护主义的有力工具

CECBC

经济建设 世界经济

week08作业

龙卷风

架构师一期

week4 代码重构 作业和学习总结

杨斌

一篇文章搞懂 @weakify 和 @strongify

疯清扬

objective-c weak weakify strongify 循环引用

架构师训练营 - 第八周总结

一个节点

极客大学架构师训练营

第八周作业

orchid9

关于“区块链+”的所有关键点

CECBC

区块链 监管

新基建为数字经济注入新动能

CECBC

区块链 大数据

第四周作业一

jingx

架构师训练营第八周课后练习

薛凯

架构师训练营 第三周 作业

阿光

架构师训练营第 2 期 第四周总结

月下独酌

极客大学架构师训练营

架构 2 期 - 第四周作业(1)

浮生一梦

极客大学架构师训练营 第四周作业 2组

架构师训练营第二期 Week 4 总结

bigxiang

极客大学架构师训练营

Week 4 -作业1

Sean Chen

架构一期第八周作业

Airs

第八周学习总结

饭桶

周练习 8

何毅曦

【第八周】课后作业

云龙

架构师训练营 第四周 学习总结

阿光

架构师训练营第二期 Week 4 作业

bigxiang

极客大学架构师训练营

《JavaScript高级程序设计》.pdf

田维常

Java 电子书

架构师训练营 1 期第 8 周:性能优化(二)- 作业

piercebn

极客大学架构师训练营

架构师训练营 第四周 作业

阿光

第八周课后练习

饭桶

还有人不知道JVM调优参数?一次性打包发给你

田维常

JVM jvm调优

国产大数据系统通过验收,”核高基”基础软件再下一城

陈泽云

人工智能 大数据 知识产权 操作系统

第八周总结

orchid9

架构师训练营 第三周 学习总结

阿光

技术解读:Cube安全容器高并发低延时实践之路_腾讯_InfoQ精选文章