这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

Learning Kuasar

Kuasar 学习笔记

1 - 介绍

Kuasar介绍

1.1 - Kuasar介绍

Kuasar介绍

https://github.com/skyao/kuasar


介绍

Kuasar 是一款高效的容器运行时,通过支持多种沙箱技术提供云原生全场景容器解决方案。它采用 Rust 语言编写,基于沙箱 API 提供标准沙箱抽象层。此外,Kuasar 还提供优化框架以加速容器启动并减少不必要的开销。

在当前发展阶段,没有任何单一的基础容器技术能够完美支持所有云原生场景的需求。我们的目标是提供更优的解决方案,以管理和平衡企业对容器隔离性、安全性、通用性、运行速度及资源消耗等方面的需求。

kuasar的优点

在容器领域,沙盒是一种用于将容器进程相互隔离以及与操作系统本身隔离的技术。随着沙盒 API 的引入,沙盒已成为 containerd 中的第一类公民。随着容器领域中越来越多的沙盒技术出现,预计将提出一个名为“沙盒管理器”的管理服务。

Kuasar 支持多种类型的沙盒管理器,使用户能够根据应用需求为每个应用选择最合适的沙盒管理器。

与其他容器运行时相比,Kuasar 具有以下优势:

  • 统一沙盒抽象:沙盒在 Kuasar 中是一流公民,因为 Kuasar 完全基于沙盒 API 构建,该 API 由 containerd 社区于 2022 年 10 月预览。Kuasar 充分利用了沙盒 API 的优势,提供了一种统一的沙盒访问和管理方式,并提高了沙盒运维效率。
  • 多沙盒共置:Kuasar 内置支持主流沙盒,允许多种类型的沙盒在单个节点上运行。Kuasar 能够平衡用户对安全隔离、快速启动和标准化的需求,并使无服务器节点资源池满足各种云原生场景要求。
  • 优化框架:通过移除所有暂停容器并将 shim 进程替换为单个驻留沙盒器进程,Kuasar 进行了优化,带来了 1:N 进程管理模型,其性能优于当前的 1:1 shim v2 进程模型。基准测试结果显示,Kuasar 的沙盒启动速度提升 2 倍,而管理资源开销降低了 99%。更多详情请参考性能。
  • 开放与中立:Kuasar 致力于构建一个开放且兼容的多沙盒技术生态系统。得益于沙盒 API,集成沙盒技术更加便捷且节省时间。Kuasar 对沙盒技术保持开放和中立的态度,因此所有沙盒技术都受到欢迎。目前,Kuasar 项目正在与 WasmEdge、openEuler 和 QuarkContainers 等开源社区和项目合作。

Kuasar 的技术优势主要包括:

  • 灵活的插件沙盒扩展能力

    Kuasar 具有灵活的插件沙盒扩展能力。它提供了一个更对开发者友好的沙盒访问框架,使得主流沙盒的持续集成成为可能。

  • 清晰统一的沙盒定义

    Kuasar 基于最新的沙盒 API,具有清晰统一的沙盒定义。沙盒的管理逻辑与容器分离,不再像以前那样耦合在一起。而且这将得到上游 containerd 社区的原生支持。

  • 简化容器 API 调用链

    Kuasar 拥有简化的容器 API 调用链。如您所见,容器运行时可以在无需像以前那样在“shim”中进行额外转换的情况下管理容器。

  • 高效的 Kuasar 沙盒器

    Kuasar 拥有高效的沙盒器和优化的框架:

    • 它的进程是驻留的,这意味着启动时间更短。
    • 它的进程模块是 1:N,这意味着随着容器数量的增加,其资源开销不会增加。
    • 它是用 Rust 编写的,这意味着高性能、高安全性和低开销。
  • 消失的“pause”容器

    Kuasar 移除“暂停”容器的原因是安全容器是一个自然的 Pod 模型。这种优化减少了由暂停容器引入的资源开销和启动时间。

功能

支持的沙箱

Sandboxer Sandbox Status
MicroVM Cloud Hypervisor Supported
QEMU Supported
Firecracker Planned in 2025
StratoVirt Supported
Wasm WasmEdge Supported
Wasmtime Supported
App Kernel Quark Supported
runC runC Supported

架构

Kuasar 中的沙盒器使用各自的容器隔离技术,并且它们也是基于新的沙盒插件机制构建的 containerd 外部插件。关于沙盒器插件的讨论已在 containerd 问题中提出,并在该评论中附有社区会议记录和幻灯片。现在这一功能已被纳入 2.0 里程碑。

目前,Kuasar 提供三种类型的沙盒器——MicroVM 沙盒器、App Kernel 沙盒器和 Wasm 沙盒器——所有这些都被证明在多租户环境中是安全的隔离技术。沙盒器的一般架构由两个模块组成:一个模块实现沙盒 API 以管理沙盒的生命周期,另一个模块实现任务 API 以处理与容器相关的操作。

MicroVM 沙盒器

在 microVM 沙盒场景中,VM 进程提供基于开源 VMM(虚拟机管理器)如 Cloud Hypervisor、StratoVirt、Firecracker 和 QEMU 的完整虚拟机和 Linux 内核。所有这些虚拟机都必须在支持虚拟化的节点上运行,否则将无法工作!因此,MicroVM 沙盒器的 vmm-sandboxer 负责启动虚拟机并调用 API,而 vmm-task 作为虚拟机中的初始化进程,扮演运行容器进程的角色。容器 IO 可以通过 vsock 或 uds 导出。

microVM 沙盒器避免了在主机上运行 shim 进程的必要性,带来了一种更干净、更易于管理的架构,每个 pod 只有一个进程。

App Kernel Sandboxer

App Kernel 沙盒启动 KVM 虚拟机和 guest 内核,无需任何应用级虚拟机管理程序或 Linux 内核。这允许针对启动过程进行定制优化,减少内存开销,并提高 IO 和网络性能。此类应用内核沙盒的例子包括 gVisor 和 Quark。

Quark 是一个应用内核沙盒,它使用自己的虚拟机管理程序 QVisor 和定制的内核 QKernel 。通过对这些组件进行定制修改,Quark 可以实现显著的性能提升。

应用内核沙盒器 quark-sandboxer 启动 Qvisor 并创建一个名为 Qkernel 的应用内核。每当 containerd 需要在沙盒中启动容器时, QVisor 中的 quark-task 将调用 Qkernel 来启动一个新容器。同一 Pod 内的所有容器将在同一个进程中运行。

Wasm Sandboxer

Wasm 沙盒,如 WasmEdge 或 Wasmtime,非常轻量级,但目前可能对某些应用存在限制。 wasm-sandboxer 和 wasm-task 在 WebAssembly 运行时中启动容器。每当 containerd 需要在沙盒中启动容器时, wasm-task 会创建新进程,启动新的 WasmEdge 运行时,并在其中运行 Wasm 代码。同一 Pod 中的所有容器将与 wasm-task 进程共享相同的 Namespace/Cgroup 资源。

Runc Sandboxer

除了安全容器,Kuasar 还为 runC 容器提供了运行能力。为了生成一个独立的命名空间, runc-sandboxer 通过双重克隆创建一个轻微的过程,然后成为 PID 1。基于这个命名空间, runc-task 可以创建容器进程并加入该命名空间。如果容器需要私有命名空间,它会为自己 unshare 一个新的命名空间。

1.2 - Kuasar背景

Kuasar背景介绍

https://kuasar.io/docs/background/sandbox-rise/


大约在 2018 年,各种云原生容器隔离技术逐渐出现。我们将这项技术称为“沙盒”。

而沙盒是一个自然的 POD 模型。它为一组容器提供了一个隔离环境。存在一些典型的沙盒:microVM 沙盒、application-kernel沙盒和 WASM 沙盒。

它们是为不同云原生场景下的企业需求而生的,因此具有不同的优势维度。

如您所见,microVM 沙盒适用于安全且通用的多租户情况。应用内核沙盒适用于高效且通用的多租户情况。WASM 沙盒适用于非常轻量级任务的情况,例如函数计算。

痛点与趋势

现在,主流云厂商在其产品中使用了多种沙箱技术。但没有任何单一的容器运行时能够同时直接运行上述沙箱。

因此,用户不得不维护多个容器运行时来管理不同的沙箱,这增加了运维(operation and maintenance)的压力。

此外,由于当前的容器运行时缺乏平滑的演进路径,大多数企业仍然停滞不前,无法将其产品的最新沙箱技术整合到产品中。

去年,主流容器运行时‘containerd’在社区呼声下,在其预览版本中引入了沙箱 API。

我们相当确定沙盒即将到来,它应该成为容器运行时的一个新的第一类公民。

我们需要一个多沙盒容器运行时。

它使沙盒成为一等公民。

它自然支持主流沙盒技术。

它有一个插件、可扩展和可进化的机制。

所以这就是 Kuasar 诞生的原因。

1.3 - codewiki上的介绍

Kuasar资料收集

https://codewiki.google/github.com/kuasar-io/kuasar

1.3.1 - kuasar介绍

Kuasar sandbox 介绍

https://codewiki.google/github.com/kuasar-io/kuasar#introduction-to-kuasar-sandboxes


Kuasar 是一个多沙盒容器运行时,它统一了多种容器隔离技术于一致的 Sandbox API 框架下。它管理 MicroVM、App Kernel、WebAssembly(Wasm)和 runC 沙盒。这种做法在安全性和性能之间为云原生应用实现了平衡。

Kuasar 与容器运行时集成,特别是通过 containerdshim proxy 进行集成。这个代理充当 CRI runtime V2 backend ,在 containerd 和 Kuasar 的各种沙盒进程之间调解 Sandbox APITask API 请求。使用 Unix 域套接字(UDS)和 VSock 进行高效通信。更多详情请参考容器运行时集成。 Kuasar 提供不同的沙盒类型,每个都针对不同的隔离需求:

  • MicroVM Sandbox (VMM): 这个沙盒编排虚拟机环境,抽象设备管理、cgroup 控制、网络和存储。它通过在专用虚拟机中运行工作负载提供强隔离。
  • App Kernel Sandbox (Quark): quark-sandboxer 守护进程使用应用级虚拟机管理器管理容器化环境。这种设置利用定制内核优化性能。
  • WebAssembly Sandbox (Wasm): wasm-sandboxer 在 WebAssembly 运行时中启动容器,例如 WasmtimeWasmEdge 。这实现了 Wasm 模块的效率和可移植性执行。
  • runC Sandbox: runc-sandboxer 提供基于 runC 的容器功能,创建隔离的命名空间并管理容器生命周期。

单个居民 sandboxer 进程可以管理多个容器,采用 1:N 进程管理模型。与传统的 1:1 shim v2 模型相比,这减少了开销,并消除了 pause containers 。该项目使用 Rust 实现了许多组件,以提高效率和内存安全性。有关这些功能的更多信息,请参阅多沙盒功能概述和 Kuasar 的核心架构和设计原则。

Kuasar 沙盒介绍

Kuasar 是一个多沙盒容器运行时,旨在为各种部署场景提供云原生解决方案。它主要使用 Rust 实现,将多种容器隔离技术统一在一致的 Sandbox API 框架下,并借鉴了预览的 containerd API 的灵感。这种设计使 Kuasar 能够管理多种沙盒类型,包括 MicroVM、App Kernel、Wasm 和 runC 沙盒,在安全性、启动速度和标准化之间取得平衡。该项目的架构通过移除 pause containers 并采用 1:N 进程管理模型来优化性能,其中单个驻留的 sandboxer 进程可以管理多个容器,与传统 1:1 shim v2 模型相比,从而降低了开销。

Kuasar 的设计核心围绕几个关键组件和架构原则。它通过专门的沙盒器支持不同的隔离技术。例如,MicroVM 沙盒器( vmm-sandboxer ),位于 vmm 目录中,负责协调虚拟机环境,抽象设备管理、cgroup 控制、网络和存储。类似地,App Kernel 沙盒器( quark-sandboxer )在 quark 中,使用应用级虚拟机管理程序管理容器化环境。Wasm 沙盒器( wasm-sandboxer ),位于 wasm ,处理 WebAssembly 沙盒和容器,并与 WasmtimeWasmEdge 等运行时集成。最后, runC 沙盒器( runc-sandboxer )在 runc 中,管理基于传统 runC 的容器沙盒。

Kuasar 与容器编排系统的集成,特别是与 containerd 的集成,通过专门的 shim 实现。这些 shim 位于 shim 目录中,作为代理代理,在 containerd 和相应的 Kuasar 沙盒进程之间转发 Sandbox APITask API 请求。这种模块化设计确保 Kuasar 能够扩展其功能到不同的容器环境,同时保持与现有容器生态系统的兼容性。Kuasar 组件的整体构建、安装和测试过程由 MakefileMakefile 管理,以及位于 scripts 的补充脚本处理,从编译自定义 containerd 到配置超虚拟机和客户操作系统镜像,涵盖了所有方面。有关构建和安装的更多详细信息,请参阅构建和安装过程。

Kuasar 的核心架构和设计原则

Kuasar 是一个用 Rust 编写的有效容器运行时,旨在通过多种沙盒技术为各种场景提供云原生解决方案。其核心架构在一致的 Sandbox API 下统一了多种隔离技术,实现了安全、启动速度和标准化的平衡。

Kuasar 的一项基础设计原则是 Multi-Sandbox Colocation ,它允许不同的沙盒类型——MicroVM、App Kernel、Wasm 和 runC ——在单个节点上并发运行。这种方法使用户能够为他们的工作负载选择最合适的隔离级别。例如,MicroVM 沙盒提供强隔离,适合不可信的工作负载,而 runC 沙盒为可信应用提供轻量级的容器化。 Sandbox API ,正如 containerd 所预览的,作为统一接口,抽象掉了每种底层隔离技术的复杂性。这为容器运行时提供了一个一致的管理层,更多细节请参考容器运行时集成。

Kuasar 的 Optimized Framework 优先考虑性能和资源效率。一个关键的设计选择是移除 pause containers ,并将多个 shim 进程替换为单个驻留的 sandboxer 进程。这形成了一个 1:N 进程管理模型,其中单个 sandboxer 管理多个容器,与传统 1:1 shim v2 模型相比显著降低了开销。这种架构在不同沙盒类型中始终如一地实施。例如, vmm-sandboxer 编排虚拟机环境, quark-sandboxer 管理 App Kernel 沙盒, wasm-sandboxer 处理 Wasm 容器。这些沙盒器通过专用适配器与 containerd 通信,例如在 shim 中找到的适配器,它们转发 Sandbox APITask API 请求。该项目还维护一个路线图,概述了未来的增强功能和特性,表明持续关注优化和新功能。

整个 Kuasar 项目是用 Rust 语言实现的,这一选择强调了效率、内存安全性和并发性。这一点在主 (root) 目录中的源代码组织结构中表现得十分明显,其中核心组件、文档以及每种沙盒类型的工具都被系统地组织起来。在 MakefileMakefile 中,这些组件的构建、安装和测试被协调管理,展示了一个模块化和可配置的构建过程。该项目还致力于构建一个开放和中立生态系统,正如在 README.mdREADME.md 中所强调的那样,该生态系统旨在集成多样的沙盒技术并促进社区贡献,具体细节在 CONTRIBUTING.md 中有详细说明。

多沙盒功能概述

Kuasar 将多种隔离技术统一在一致的 Sandbox API 框架下,使多种沙盒类型能在单个节点上并发运行。这种方法在云原生环境中平衡了安全性、启动速度和标准化。其核心架构,如《Kuasar 核心架构与设计原则》所述,利用单个驻留的 sandboxer 进程来管理多个容器,通过移除 pause containers 优化资源使用并简化进程管理模型。

Kuasar 的多沙盒功能包括:

  • MicroVM Sandbox (VMM): 该沙盒利用开源虚拟机监视器(VMM)如 Cloud HypervisorQEMUStratoVirt 来协调虚拟机环境。 vmm-sandboxer 负责设备管理、cgroup 控制、网络和存储。在这些虚拟机中, vmm-task 组件作为 init 进程运行,管理容器和进程的生命周期。更多信息请参阅 微虚拟机沙盒( VMM
  • App Kernel Sandbox (Quark): quark-sandboxer 守护进程使用应用级虚拟机管理程序管理容器化沙盒环境。这种设置利用定制内核为应用内核工作负载提供优化性能。更多细节可在 应用内核沙盒( Quark 中找到。
  • WebAssembly Sandbox (Wasm): wasm-sandboxer 在 WebAssembly 运行时(如 WasmtimeWasmEdge )中启动容器。这使 Wasm 模块在容器化环境中能够高效和便携地执行。Kuasar 的 containerd-shim 集成特别利用这些运行时来执行 Wasm 模块和管理资源限制。更多信息请参阅 WebAssembly 沙盒( Wasm
  • runC Sandbox: runc-sandboxer 提供基于 runC 的容器功能,通过双重分叉机制创建隔离的命名空间。这些命名空间内的 runc-task 管理容器进程,确保与 OCI 规范兼容。更多详情请参阅 runC 沙盒

这些沙盒类型通过一个 shim 代理与 containerd 集成,该代理充当 CRI runtime V2 backend 。这个代理在 containerd 和相应的 Kuasar 沙盒进程之间转发 Sandbox APITask API 请求,使用 Unix 域套接字(UDS)和 VSock 进行进程间通信。有关此集成的详细说明,请参阅容器运行时集成。

构建和安装过程

Kuasar 的构建和安装过程主要通过一个 Makefile 和一套 shell 脚本进行协调,这些工具促进了其各种沙盒组件、定制容器运行时和客操作系统实体的编译和部署。该基础设施支持不同的虚拟机管理程序、WebAssembly 运行时和内核版本。

中央 MakefileMakefile )管理整个构建生命周期,包括编译 vmmwasmquarkrunc 沙盒器。它通过 HYPERVISOR (默认值为 cloud_hypervisor )、 GUESTOS_IMAGE (默认值为 centos )、 WASM_RUNTIME (默认值为 wasmedge )和 KERNEL_VERSION 等变量实现灵活配置。这些变量决定了构建哪些与 VMM 相关的组件、使用哪种类型的客户操作系统镜像以及集成特定的 WebAssembly 运行时。 Makefile 还负责将编译后的二进制文件和相关 systemd 服务文件安装到标准系统目录中。

Makefile 相补充, scripts 目录包含专门的 shell 脚本。 scripts/build 子目录专注于准备关键依赖。例如, build-containerd.shscripts/build/build-containerd.sh )自动化编译 Kuasar 特定的 containerd 二进制文件,并将其配置为与 Kuasar 的各种沙盒类型(如 kuasar-runckuasar-vmmkuasar-quarkkuasar-wasm )作为 proxy_plugins 集成。另一个脚本 cargo-vendor.shscripts/build/cargo-vendor.sh )通过为 Kuasar 的子项目提供 Rust 依赖,确保可重复构建,允许离线编译。

scripts/install 子目录提供了部署 Kuasar 的详细脚本,特别是 VMM 沙盒器。这些脚本针对不同场景,为 x86_64 和 aarch64 架构提供基于源代码的编译和基于二进制的安装。例如, build-and-install-kuasar-vmm.shscripts/install/build-and-install-kuasar-vmm.sh )通过编译 Cloud-Hypervisor (Kuasar VMM 沙盒器)、Kuasar 特有的 containerdvirtiofsd 从源代码进行完整安装。它还处理 crictl 的安装和配置,利用 Docker 或 Podman 等容器运行时进行隔离构建。为了在 x86_64 上更快部署, install-kuasar-vmm-x86.shscripts/install/install-kuasar-vmm-x86.sh )使用相同组件的预编译二进制文件。两种安装方法都包括下载组件的校验和验证,并提供交互式提示以获取用户确认。一个专门的 uninstall-kuasar-vmm.shscripts/install/uninstall-kuasar-vmm.sh )脚本提供了一种全面移除 Kuasar 相关组件的方式,包括停止 systemd 服务、删除二进制文件以及清理配置文件。

此外,VMM 组件在 vmm/scripts 中包含用于生成客机操作系统根文件系统和镜像的专业脚本。这涉及创建与 Kata Containers 兼容的镜像,并构建基于 CentOS 的根文件系统。 vmm/scripts/kernel 中的脚本用于为各种 VMM(如 Cloud Hypervisor、QEMU 和 StratoVirt)定制 Linux 内核镜像,并为 Kuasar 安全容器定制内核,通常针对最小内存占用进行优化。

文档与社区资源

Kuasar 提供了各种资源来促进理解、集成和社区参与。

docs 目录中提供全面的文档。这包括有关将 Kuasar 与 containerd 等容器运行时集成的详细指南,概述了 shim proxy 的功能以及 vmmquarkwasm 沙盒器的配置。还提供了针对不同虚拟机管理程序(如 QEMU 和 StratoVirt)构建、安装和配置 Kuasar 的具体说明。此外,文档还提供了在 Kubernetes 中部署基于 Wasm 的大型语言模型(LLM)推理应用程序的指导,展示了 Kuasar Wasm 能力的实际应用。

除了文档之外,该项目通过多种途径鼓励社区参与。 ROADMAP.md 文件概述了核心框架、测试、Kubernetes 功能支持和安全方面的未来开发计划及改进。贡献由 CONTRIBUTING.md 指导,其中详细说明了工作流程、代码审查过程和提交信息格式标准。 CODE_OF_CONDUCT.md 文件确立了社区期望,并参考了 CNCF 行为准则。 ADOPTERS.md 中提供了采用 Kuasar 的组织和项目的相关信息,而 MAINTAINERS.md 列出了官方项目维护者和团队。变更和版本历史计划在 CHANGELOG 目录中进行跟踪。

1.3.2 - 容器运行时集成

Kuasar 容器运行时集成

https://codewiki.google/github.com/kuasar-io/kuasar#container-runtime-integration


Kuasar 与容器运行时(特别是 containerd )通过一个专门的 shim proxy 进行集成。这个代理充当一个 CRI runtime V2 backend ,在 containerd 和 Kuasar 的各种沙箱进程之间中继请求。这个 shim 的主要功能是将 Sandbox API 请求转发到相应的 Kuasar 沙箱进程(例如 VMM 或 Wasm 沙箱进程),并将 Task API 请求转发到低级任务器,从而将复杂的处理工作从代理本身卸载。

shim 组件是使 containerd 能够协调 Kuasar 的多样化沙盒的核心,包括 MicroVMs ( kuasar-vmm ) 和 WebAssembly 模块 ( kuasar-wasm )。针对这些不同环境有特定的 shim 二进制文件,例如用于 MicroVMs 的 containerd-shim-kuasar-vmm-v2 和用于 Wasm 工作负载的 containerd-shim-kuasar-wasm-v2 。这些适配器被构建并安装到系统中,通常在 /usr/local/bin/ 中,使用位于 shim/MakefileMakefile 进行构建和安装。

containerd 与 Kuasar 沙盒进程之间的交互依赖于进程间通信机制。对于 kuasar-vmm ,通信通常通过 VSock 进行,这适用于虚拟化环境。对于 kuasar-wasm ,通常使用 Unix 域套接字(UDS)进行高效通信。 shim 负责建立和管理这些通信通道。

要集成 Kuasar 与 containerd ,需要在 containerd 的配置文件中进行特定修改,该文件通常位于 /etc/containerd/config.toml 。这些修改定义了 runtime_typesandbox_mode 设置,用于 kuasar-vmmkuasar-wasm 运行时,指定 containerd 如何调用 Kuasar 的 shims。此外,必须使用 ENABLE_CRI_SANDBOXES=1 环境变量启动 containerd ,以启用 containerd Sandbox API ,这对 Kuasar 的运行至关重要。

提供有关构建、安装和配置 Kuasar shimcontainerd 的全面指南,详细说明了先决条件和必要的系统调整。有关 shim 内部结构的更多详细信息,请参阅 Shim 代理架构和通信机制。

代理架构和通信机制

Kuasar shim 作为 CRI runtime V2 backend ,在 containerd 和 Kuasar 的 sandboxer 进程之间进行通信中介。这种架构允许 containerd 通过一致接口管理多样化的 Kuasar 沙盒,包括 MicroVM 和 WebAssembly (Wasm) 环境。Shim 主要作为代理,将 Sandbox API 请求转发到相应的 sandboxer (例如 vmm-sandboxerwasm-sandboxer ),将 Task API 请求转发到低级的 tasker ,从而最小化 Shim 对这些请求的内部处理。

沙盒的核心功能通过 Service<T> 结构实现,该结构遵循 Shim 特性。这个 Service 包含一个 KuasarServer<T> ,封装了与 Kuasar 组件交互的业务逻辑。这个 KuasarServer 又包括一个用于沙盒操作的 SandboxHandler<T> 和一个用于管理任务的 TaskHandler

containerdshim 以及 Kuasar 的 sandboxertasker 进程之间的进程间通信(IPC)通过不同的传输机制实现。对于 VMM 工作负载, containerd-shim-kuasar-vmm-v2 利用 VSockTransport ,实现通过虚拟套接字进行通信,这在虚拟化环境中很常见。这对于使用 MicroVMs 隔离容器的场景尤其相关。 shim/src/io.rs 中的 VSockTransport 管理虚拟套接字端口分配以防止冲突,并处理 containerd 管道和虚拟套接字流之间的数据传输。

对于 Wasm 工作负载, containerd-shim-kuasar-wasm-v2 采用 UdsTransport (Unix 域套接字)。这适用于 Wasm 沙盒可能不需要完整虚拟机的情况,可在主机系统内部提供高效的 IPC。 shim/src/io.rs 中的 UdsTransport 直接使用提供的管道路径, containerd 负责 UDS I/O 复制。

两个 shim 都建立与 Kuasar sandboxertasker 进程的连接。 shim/src/sandbox.rs 中的 SandboxHandler 负责将 containerd-shim TTRPC 请求转换为 containerd-sandbox v2 控制器的 gRPC 调用,管理从创建到关闭的沙盒的完整生命周期。 shim/src/task.rs 中的 TaskHandler 作为代理,将 containerd 垫片 Task API 调用转发到底层 TaskClient ,并与 SandboxHandler 协调容器和进程生命周期管理以及资源分配。这种架构确保了 containerd 可以无缝地与 Kuasar 的各种沙盒技术交互。有关 containerd 集成的更多详细信息,请参阅容器运行时集成。

构建与安装 Kuasar Shim

Kuasar containerd shim 通过位于 shim/MakefileMakefile 进行构建和安装。这个 Makefile 协调编译和安装两个不同的 shim 二进制文件: containerd-shim-kuasar-vmm-v2containerd-shim-kuasar-wasm-v2 。这些二进制文件使 containerd 能够分别与 Kuasar 的 VMM 和 Wasm 运行时集成。构建过程利用 cargo build --release 创建优化的可执行文件。构建完成后, install 目标将这些二进制文件移动到系统的 /usr/local/bin/ 目录,确保它们对 containerd 可用。

与 shim 构建互补,Kuasar 项目还包含一个用于构建自定义 containerd 二进制文件的脚本。该脚本位于 scripts/build/build-containerd.sh ,克隆 containerd 仓库的 Kuasar 特定分支,进行编译,并生成 config.toml 文件。此配置文件对于集成 Kuasar 运行时至关重要,它定义了 runtime_type 的设置,用于 kuasar-runckuasar-vmmkuasar-quarkkuasar-wasm ,并配置 proxy_plugins 以促进与各自的沙盒服务通信。这种自定义的 containerd 设置对于确保 shim 能够正确地与 Kuasar 的多沙盒功能交互至关重要。若要深入了解这些 shim 如何与 containerd 集成,请参阅 Kuasar 运行时的 Containerd 配置。

shim 服务和沙盒/任务管理

Kuasar 中的 containerd shim 服务充当关键的中介,将来自 containerd 的请求转换为由 Kuasar 的沙盒器和任务服务管理的操作。该服务主要由 Service<T> 结构实现,该结构遵循 containerdShim 特性。 Service<T> 利用一个 KuasarServer<T> 实例来封装与 Kuasar 后端交互所需的应用逻辑。

KuasarServer<T> 的核心包含两个关键组件: SandboxHandler<T>TaskHandlerSandboxHandler<T> 负责协调沙盒的生命周期。当 containerd 请求创建、启动、停止或删除沙盒等操作时, SandboxHandler 接收这些 TTRPC 请求,并将它们转换为对 containerd-sandbox v2 控制器的相应 gRPC 调用。这种委托确保实际的沙盒管理,包括资源分配和隔离,由 Kuasar 沙盒器处理。 SandboxHandler 还管理沙盒的本地文件系统设置和清理,例如创建根目录和挂载共享内存,具体细节请参见沙盒状态管理和持久化。

同样地,TaskHandler 负责管理沙箱内任务(容器和进程)的生命周期。它充当代理角色,将 containerd 适配层的任务 API 调用转发至底层的 TaskClient,后者再与 Kuasar Task Service 进行通信。当 containerd 请求创建、启动或删除容器或进程时,KuasarServer 中的 TaskHandler 会拦截这些请求。例如在容器创建请求中,它首先通过 SandboxHandler 准备沙箱环境,接着使用 ContainerIoTransport 配置 I/O 流,最后将任务创建委托给 TaskClient。该架构确保所有容器和进程操作(包括 I/O 管理)均由 Kuasar 任务服务协调执行,并通过 gRPC 实现进程间通信。关于 containerd 如何配置以与这些 Kuasar 运行时交互的具体细节,详见《Kuasar 运行时的 containerd 配置指南》。

Kuasar 运行时的 Containerd 配置

# /etc/containerd/config.toml

# ... other containerd configurations ...

[plugins."io.containerd.grpc.v1.cri"]
  # ... other CRI plugin configurations ...
  disable_apparmor = true # Important: AppArmor is not supported, must be true

  [plugins."io.containerd.grpc.v1.cri".containerd]
    # ... other containerd configurations within CRI plugin ...

    [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kuasar-vmm]
      runtime_type = "io.containerd.kuasar-vmm.v2"
      sandbox_mode = "shim"

    [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kuasar-wasm]
      runtime_type = "io.containerd.kuasar-wasm.v2"
      sandbox_mode = "shim"

# ... rest of the config.toml ...

将 Kuasar 与 containerd 集成需要对 containerd 配置文件进行特定修改,该文件通常位于 /etc/containerd/config.toml 。这些修改定义了 containerd 如何与 Kuasar 的各种沙箱运行时进行交互。Kuasar shim 充当 CRI runtime V2 backend 负责协调这种通信,详情请参阅 “容器运行时集成”部分

对于 kuasar-vmm (MicroVM)和 kuasar-wasm (WebAssembly)运行时,需要配置 containerd runtime_type 和 sandbox_mode 设置。对于 kuasar-vmm ,需要将 runtime_type 设置为 “io.containerd.kuasar-vmm.v2” , sandbox_mode 设置为 “shim” 。类似地,对于 kuasar-wasm , runtime_type 设置为 “io.containerd.kuasar-wasm.v2” , sandbox_mode 也相同。此配置的示例可在 docs/shim/README.md 中找到。

除了这些运行时特定的设置之外, containerd 中的 AppArmor 功能不受 Kuasar 支持,因此需要配置项 disable_apparmor = true 。此外,要启用 containerd 的 Sandbox API ,必须使用环境变量 ENABLE_CRI_SANDBOXES=1 启动 containerd 。此环境变量对于 containerd 正确使用 sandbox_mode = “shim” 设置并将沙箱管理委托给 Kuasar 至关重要。

安装脚本(例如 scripts/install/build-and-install-kuasar-vmm.sh 和 scripts/install/install-kuasar-vmm-x86.sh )会自动将系统中的 containerd 二进制文件替换为 Kuasar 兼容版本,并将 Kuasar 特有的 config.toml 文件复制到 /etc/containerd/config.toml ,其中包含必要的配置。另一方面, uninstall-kuasar-vmm.sh 脚本可以根据需要删除这些配置以及 Kuasar 特有的 containerd ,具体说明请参见 scripts/install/README.md 。

1.3.3 - MicroVM 沙箱

Kuasar MicroVM 沙箱

https://codewiki.google/github.com/kuasar-io/kuasar#microvm-sandbox-vmm


Kuasar 的 MicroVM (VMM) 沙箱实现利用虚拟机技术,为容器工作负载提供了一个强大且隔离的环境。这项功能是 Kuasar 多沙箱方法的核心,它在提供强大隔离保障的同时,还能保持性能。VMM 沙箱为每个沙箱编排一个虚拟机,抽象化了复杂的设备管理、cgroup 控制、网络和存储配置。这种抽象化使得容器能够在专用的虚拟机中运行,从而确保它们与其他容器和宿主机系统完全隔离。

VMM 沙箱环境的核心由几个关键组件构成。 vmm-sandboxer 组件负责协调虚拟机的生命周期,包括启动、停止和管理这些 microvm 的资源。在每个客户虚拟机内部,一个名为 vmm-task 轻量级进程以进程 ID 1 运行。该 vmm-task 负责管理客户虚拟机内部的容器和进程生命周期,处理资源分配、网络配置和异步 I/O 操作。主机与客户虚拟机的 vmm-task 之间的通信主要依赖于基于 vsock ttrpc ,从而实现高效的进程间通信,而无需将客户虚拟机的网络暴露给主机。

为了支持各种虚拟机管理程序,例如 Cloud Hypervisor、QEMU 和 StratoVirt,Kuasar 的 VMM 沙箱提供了灵活的集成机制。这包括针对特定虚拟机管理程序的客户端 API 和生命周期管理。该系统还支持针对这些不同的 VMM 和 Kuasar 安全容器对 Linux 内核镜像进行广泛的定制。这种定制(详见“微型虚拟机的 Linux 内核定制” 小节)通常侧重于优化内核以实现最小的内存占用,并根据具体用例将其分为 micro-kernel 或 mini-kernel 。

创建客户操作系统环境涉及多个构建过程。这包括构建客户操作系统根文件系统和镜像、编译 vmm-task 和 runc 二进制文件,以及配置 NVDIMM/DAX 头文件以优化性能。这些过程由脚本协调,以确保客户环境为容器执行做好充分准备。

VMM 沙箱利用过程宏简化了从 Rust 结构体生成命令行参数的过程,从而增强了可配置性和可维护性。这些宏将结构化的 Rust 数据转换为结构化的参数对象或原始命令行参数字符串,方便对虚拟机管理程序和客户机环境进行动态配置。更多信息,请参阅 “使用过程宏派生命令行参数”。

总的来说,Kuasar 的 VMM 沙箱为安全隔离的容器执行提供了一个强大而灵活的解决方案,它通过其 shim proxy 架构与现有的容器运行时(如 containerd 紧密集成,如容器运行时集成中所述。

VMM 编排和 Hypervisor 集成

Kuasar 通过其核心组件 KuasarSandboxer 和 KuasarSandbox ,协调虚拟机 (VM) 沙箱环境,抽象化设备管理、cgroup 控制、网络和存储。该架构支持与各种 Hypervisor(例如 Cloud Hypervisor、QEMU 和 StratoVirt)集成,每种管理程序都由特定的客户端 API 和生命周期管理提供支持。

定义在 vmm/sandbox/src/sandbox.rs 中的 KuasarSandboxer 和 KuasarSandbox 结构体分别实现了 Sandboxer 和 Sandbox 特性,用于管理 KuasarSandbox 实例、其虚拟机和容器的集合。KuasarSandboxer 负责整个沙箱的创建、启动、停止、删除和恢复。 KuasarSandbox KuasarSandboxer 一个基于虚拟机的沙箱,负责管理其 vm 、容器、网络配置以及与 SandboxServiceClient 通信。这包括诸如持久化和恢复沙箱状态、初始化 ttrpc 连接、在虚拟机内设置沙箱以及同步时钟等操作。

不同的虚拟机管理程序实现,包括 Cloud Hypervisor( vmm/sandbox/src/cloud_hypervisor 中的 CloudHypervisorVM 、 CloudHypervisorVMConfig 和 ChClient )、 QemuVM ( vmm/sandbox/src/qemu 中的 QemuVMConfig 、 StratoVirtVM 和 QmpClient )以及 StratoVirt( vmm/sandbox/src/stratovirt 中的 StratoVirtVM、 StratoVirtVMConfig 和 QmpClient ),提供了特定的 VM 和配置结构。这些实现定义了用于创建虚拟机实例 Hooks VMFactory 接口,以及用于启动、停止、挂载、分离和健康检查等操作的 VM 接口。Hooks 特性允许在虚拟机生命周期中注入自定义逻辑,例如 pre_start 和 post_start 操作,而 Recoverable 特性则允许在重启后恢复虚拟机状态。

设备管理由通用的 Device 和 Bus 特性抽象化,这些特性定义在 vmm/sandbox/src/device.rs 文件中,块设备、网络设备和控制台的具体实现则位于相应的虚拟机管理程序目录中。例如, vmm/sandbox/src/cloud_hypervisor/devices 管理 cloud_hypervisor 的设备。类似地,资源隔离的 cgroup 控制由 vmm/sandbox/src/cgroup.rs 处理,该文件提供了创建分层 cgroup、应用资源限制和分配进程的功能。网络配置(包括 NetworkInterface 和 IP 地址管理)在 vmm/sandbox/src/network 目录中进行管理,而存储连接则由 vmm/sandbox/src/storage 进行管理。

这些 VMM 沙箱的命令行参数源自 Rust 结构体,并使用了诸如 CmdLineParams 和 CmdLineParamSet 之类的过程宏,详情请参阅“使用过程宏派生命令行参数” 一文,从而能够动态生成 cloud-hypervisor 和 virtiofsd 的参数。每个 VMM 后端的 KuasarSandboxer 入口点位于 vmm/sandbox/src/bin 目录下,负责协调参数解析、配置加载(例如, vmm/sandbox/src/config.rs 中的 Config::load_config )、跟踪、信号处理和状态恢复。

客户端与沙箱服务的通信由位于 vmm/sandbox/src/client.rs 中的 SandboxServiceClient 管理,它支持 ttrpc 连接,并支持多种套接字类型(Unix、VSock、HVSock),用于执行诸如健康检查、沙箱设置和时钟同步等操作。关于 ttrpc 协议和代码生成等整体架构,包括如何从 protobuf 定义生成 Rust 代码,在 “TTRPC 协议和代码生成”一节中有更详细的阐述。

Guest OS 镜像和根文件系统生成

在 Kuasar 中构建客户操作系统根文件系统和镜像的过程涉及多个精心编排的步骤,旨在为各种虚拟机监控器 (VMM) 创建定制环境。主要的编排工作由 vmm/scripts/image/build.sh 脚本负责,该脚本管理根文件系统的创建,并可选择性地生成 initrd 或完整的可引导镜像。此脚本支持不同的容器运行时环境,包括 containerd 、 docker 和 isulad ,以便在容器化环境中执行根文件系统构建过程。

为了构建完整的与 Kata Containers 兼容的根文件系统镜像,需要使用 vmm/scripts/image/build_image.sh 中的脚本。该脚本会验证根文件系统,计算最佳磁盘大小,使用 qemu-img 创建原始磁盘镜像,并使用 parted 对其进行分区。然后,它会格式化根分区(支持 ext4 或 xfs ),复制根文件系统的内容,并在启用 AGENT_INIT 时优化 systemd 组件以减小镜像大小。一个值得注意的特性是可以使用 nsdax 工具配置 NVDIMM/DAX 标头,该工具会插入特定的元数据以启用支持 pmem 的 NVDIMM 设备功能。

基于 CentOS 的根文件系统使用 vmm/scripts/image/centos/build_rootfs.sh 中的脚本构建。此过程包括构建 Kuasar 的 vmm-task 二进制文件、安装 Go 运行时环境、编译 runc 二进制文件,然后将这些组件以及必要的 glibc 库和列表中指定的其他 RPM 包填充到一个临时根文件系统目录中。许多常用的构建工具(例如用于构建 vmm-task 和 runc 工具)集中在 vmm/scripts/image/common.sh 中,从而提高了模块化程度,并允许在不同根文件系统构建中重复使用。Rust 工具链( vmm-task 的依赖项)的安装由 vmm/scripts/image/install_rust.sh 处理,该脚本确保安装 rustup 并添加用于交叉编译的 unknown-linux-musl 目标。

nsdax 工具(实现于 vmm/scripts/image/nsdax.gpl.c )对于配置 NVDIMM/DAX 头部至关重要。该 C 工具会将 PFN(页帧号)元数据块嵌入到 NVDIMM 镜像文件中。该元数据块基于 Linux 内核 NVDIMM 驱动程序,包含数据偏移和对齐等信息,使内核能够正确解析 NVDIMM 区域。该工具的 main 功能是解析命令行参数,初始化 nd_pfn_sb 结构,使用 nd_fletcher64 和 nd_sb_checksum 计算其校验和,并将该结构写入镜像中的特定偏移量 ( SZ_4K )。这样就实现了双主引导记录 (MBR) 设置,支持 DAX 的系统可以读取第二个 MBR,而其他系统则读取第一个 MBR。

针对 microvm 的 Linux 内核定制

Kuasar 项目包含一个专用框架,用于构建和定制适用于各种虚拟机监控器 (VMM) 和安全容器的 Linux 内核镜像。该流程强调一种“添加式”定制方法,旨在最大限度地减少内存占用和冷启动时间。与从完整的内核配置开始并移除功能不同,该方法选择性地添加必要的功能,从而可以精确控制内核的资源消耗和性能。

内核定制框架主要在 vmm/scripts/kernel 目录下管理,支持多种虚拟机管理程序 (VMM),包括 Cloud Hypervisor、QEMU 和 StratoVirt,以及 Kuasar 安全容器。 vmm/scripts/kernel/build-kernel/build-kernel.sh 脚本负责协调此过程,根据目标架构和内核类型动态选择配置片段。它使用内核构建系统工具将这些片段合并,从而在编译前生成最终的 .config 文件。

支持两种主要的定制内核类型:

  • micro-kernel :专为无服务器和轻量级虚拟机设计,这些内核优先考虑最小的内存开销和低延迟,通常采用 MMIO 总线结构。

  • mini-kernel :这些内核提供更复杂应用程序所需的高级功能,例如 ACPI、SCSI、NFS 和对内核模块的支持,通常使用 PCI 总线结构。

kernel 目录中的特定构建脚本处理每个虚拟机管理程序 (VMM) 的细微差别。例如, vmm/scripts/kernel/cloud_hypervisor/build.sh 专门用于在 x86-64 上为 Cloud Hypervisor 构建 vmlinux.bin ,而 vmm/scripts/kernel/qemu/build.sh 则专注于为 QEMU 生成 bzImage ,并启用 BLK_DEV_INITRD 和 VIRTIO 驱动程序等关键选项。类似地, vmm/scripts/kernel/stratovirt/build.sh 构建专为 openEuler 和 StratoVirt 定制的 aarch64 vmlinux.bin 镜像。

“附加”定制方法的设计选择确保仅包含对 Kuasar VMM 沙箱至关重要的功能,从而缩小攻击面,增强安全态势,并提升性能。有关该方法和性能影响的更多详细信息,请参阅 vmm/scripts/kernel/build-kernel/how-to-tailor-linux-kernel-for-kuasar-security-container.md 。

VMM 任务生命周期和运行时管理

vmm-task 组件负责协调客户虚拟机 (VM) 环境中容器和进程的生命周期。它在客户虚拟机内部以进程 ID 1 运行,管理初始化、资源分配、网络和异步 I/O。该系统利用 ttrpc 进行进程间通信,并利用 tokio 实现并发,从而能够高效地管理容器工作负载。

vmm-task 服务的主要入口点位于 vmm/task/src/main.rs 。该组件初始化虚拟机环境,设置必要的文件系统和内核参数。它还配置一个 ttrpc 服务器,以公开用于管理任务、沙箱和流式传输的服务,从而允许外部组件与虚拟机的内部进程交互。vmm vmm-task 还处理操作系统信号,包括回收子进程和管理优雅关机。

vmm-task 的配置参数由 vmm/task/src/config.rs 中的 TaskConfig 结构管理。该配置通过解析 /proc/cmdline 中的内核命令行参数动态确定,从而允许在运行时进行灵活调整,而无需依赖外部配置文件。

vmm-task 中的容器和进程管理由 shim 层负责,该层在 vmm/task/src/container.rs 中实现。此层充当 containerd 和符合 OCI 标准的运行时(例如 runc 之间的中介。它负责创建容器、解析 OCI Spec 、设置存储以及管理 stdio 重定向。该组件区分初始容器进程和后续 exec 进程,从而提供不同的生命周期管理。一个值得注意的设计是 ShimExecutor ,这是一个自定义的 spawner,它与 containerd-shim 监控系统集成,可以精确地跟踪进程生命周期。错误报告机制完善,可以从 runc 日志文件中提取详细信息。vmm vmm-task 还与 SandboxResources 集成,以管理容器存储生命周期。

沙箱的资源管理集中在 vmm/task/src/sandbox.rs 中的 SandboxResources 内。该组件负责管理存储卷,包括添加、延迟和垃圾回收。它与 vmm/task/src/device.rs 中的 DeviceMonitor 交互 DeviceMonitor 以跟踪和管理块设备和 SCSI 设备。DeviceMonitor 监听内核 uevent,并允许其他组件订阅设备相关事件,从而确保系统能够感知可用硬件。此外, vmm/task/src/sandbox.rs 还负责设置 Linux 命名空间(IPC、UTS、PID)并配置 sysctl 参数以维护沙箱的隔离性。vmm vmm/task/src/mount.rs 中的 get_cgroup_mounts 函数生成必要的 cgroup 挂载配置,支持 v1 和 v2 层次结构。

网络配置由位于 vmm/task/src/netlink.rs Handle 结构处理。该组件提供了一个基于 rtnetlink 高级 API,用于管理客户虚拟机内的网络接口、IP 地址和路由表,通常供代理服务使用。这包括启用环回、更新接口、添加和删除 IP 地址以及管理路由等操作,所有这些操作都使用 protobuf 定义的结构,以实现无缝的 RPC 集成。

I/O 和流管理对于容器功能至关重要,并在 vmm/task/src/io.rs 文件中实现。该文件定义了 ProcessIO 及相关函数,用于管理容器进程的 stdin 、 stdout 和 stderr ,支持多种机制,例如 FIFO、控制台套接字、直接流和 vsock 。它还处理控制台连接,提供用于数据复制的异步函数,并包含一个符合 AsyncRead 和 AsyncWrite 特性的 vsock 流的 VsockIo 实现。vmm vmm/task/src/streaming.rs 中的 Streaming 服务通过 ttrpc 实现流功能,管理标准流的 I/O 通道。此外, vmm/task/src/debug.rs 提供了通过 VSOCK 建立调试控制台的功能,为虚拟机或容器提供 shell 接口。

TTRPC 协议和代码生成

Kuasar 虚拟机监控器 (VMM) 利用 ttrpc 进行进程间通信,而 ttrpc 依赖于从 protobuf 定义生成 Rust 代码。此代码生成过程由 vmm/common/build.rs 构建脚本管理,实现了不同 VMM 组件之间无缝的数据交换和远程过程调用。

vmm/common/build.rs 脚本利用 ttrpc-codegen crate 将 .proto 文件(例如 sandbox.proto 、 events.proto 和 fieldpath.proto )转换为 Rust 源代码。生成的代码为 ttrpc 协议提供了必要的客户端和服务端实现,确保类型安全且高效的通信。例如, vmm/common/src/api/mod.rs 中的 sandbox_ttrpc 和 streaming_ttrpc 模块分别提供了沙箱管理和数据流服务的特定 ttrpc 绑定。

为了维护代码质量并抑制自动生成文件中不必要的警告,构建脚本会进行一些生成后修改。它会移除 #![allow(box_pointers)] 代码检查,该检查用于解决与特定 Rust 特性的兼容性问题,并将 #![allow(clippy::all)] 插入到生成的 _ttrpc.rs 文件中。这确保了自动生成的代码中可能出现的 clippy 警告被抑制,从而保持代码库的整洁,使其专注于开发者编写的逻辑。这使得项目能够专注于生成的 API 组件的语义正确性,而不会被那些并非由开发者直接维护的代码的风格检查所分散注意力。

使用过程宏推导命令行参数

Kuasar 利用过程宏从 Rust 结构体生成命令行参数,简化了定义和解析各种组件参数的过程。这种方法支持两种主要的生成方式:创建结构化的 Param 对象和生成原始命令行参数字符串。这些宏定义在 vmm/sandbox/derive/src/lib.rs 文件中。

CmdLineParams 宏为 crate::param::ToParams trait 生成一个实现,产生一个 crate::param::Param 对象向量。每个 Param 对象代表一个结构化参数,包含一个名称和一个 Property 对象列表。这使得命令行参数能够以详细且有序的方式表示,其中参数中的每个属性都可以具有特定的配置,例如 param 、 key 、 predicate 、 generator 、 ignore_key 和 ignore 属性。这些属性支持对属性生成进行动态控制,允许基于 Rust 表达式有条件地包含或转换值。

相反, CmdLineParamSet 宏会为 crate::param::ToCmdLineParams trait 生成一个实现,该实现会输出一个表示原始命令行参数的 String 向量。此宏处理结构体字段,并使用带有 key 和 ignore 子属性的 param 属性来自定义命令行键或排除字段。它按类型(例如布尔值、原始类型、 Vec 或 Option )对字段进行分类,并将参数生成委托给专门的 crate::param 类型。这种方法通过抽象将 Rust 数据结构转换为可执行参数的过程,简化了命令行接口的创建。

这两个宏 convert_case 利用 syn 和 quote crate 来解析 Rust 语法树和生成新的 Rust 代码。convert_case crate 用于将标识符转换为 kebab-case 格式,以确保生成的命令行参数格式一致。

1.4 - Kuasar资料收集

Kuasar资料收集

官方资料

官方网站: https://kuasar.io/

官方文档:https://kuasar.io/docs/

官方博客:https://kuasar.io/blog/

代码仓库: https://github.com/kuasar-io/kuasar

AI 工具

code wiki

https://codewiki.google/github.com/kuasar-io/kuasar

AI 推荐的代码阅读工具

问: 我想系统的学习一个开源项目的代码,理解他的功能,流程,设计,以及实现细节,请问业界有什么比较好的AI工具可以帮助我? 答: gemini 的答复如下。可以参考

这是一个非常好的问题。在 AI 时代,阅读和理解开源代码的效率已经有了质的飞跃。过去我们可能需要几天时间通过打断点、画图来理解一个模块,现在利用 AI 工具可以将这个过程缩短到几小时甚至几十分钟。

要系统地学习一个开源项目(功能 -> 流程 -> 设计 -> 细节),单纯靠“对话”是不够的,你需要的是具有“全代码库上下文(Global Codebase Context)”意识的工具

以下是目前业界公认最高效的 AI 辅助读码工具方案,按推荐程度排序:

第一梯队:全库感知 IDE (当前最强方案)

这一类工具直接集成了编辑器,并对整个项目进行了索引(Indexing)。这意味着它们不仅仅是看你当前打开的文件,而是“读过”了整个项目。

1. Cursor (强力推荐)

目前业界公认体验最好的 AI 代码编辑器(基于 VS Code 修改)。

  • 杀手级功能 - @Codebase:在对话框输入 @Codebase,然后问“这个项目的鉴权流程是怎样的?”,它会检索整个项目,找到相关文件,并总结给你。
  • 引用跳转与解释:选中一段复杂的代码,按 Cmd+L,它不仅解释这段代码,还能分析它调用了哪里的函数,以及被哪里调用。
  • 文档索引:你可以把该开源项目的官方文档链接加进去(@Docs),让它结合文档和代码给你解释设计思路。

2. Windsurf (by Codeium)

Cursor 的强力竞争对手,最近非常火。

  • Flow 模式:它有一种“Cascade”能力,能够非常深度地感知上下文。当你问它一个功能时,它会主动打开相关的文件,甚至在终端运行命令来辅助理解。它的“代码感知力”在某些复杂场景下甚至优于 Cursor。

第二梯队:代码库搜索引擎 & 问答系统

如果你不想换 IDE,或者项目特别巨大(比如 Linux 内核、Kubernetes 这种 GB 级别的代码),IDE 的本地索引可能会卡死,这时需要云端索引工具。

1. Sourcegraph Cody

Sourcegraph 本身就是做代码搜索起家的,Cody 是他们的 AI 插件。

  • 核心优势:企业级/超大项目支持。它的 Graph Context 技术非常精准。对于复杂的开源项目,你可以直接在 VS Code 插件里问:“User 类在数据库中是如何定义的?”,它能精准定位到 Schema 定义文件。
  • Web 界面:你甚至不需要下载代码,直接在 Sourcegraph 网页版上加载 GitHub 仓库链接,就可以开始对项目提问。

2. Greptile

这是一个专门为“理解代码库”设计的 API 和工具。

  • 核心场景:它专门针对“Onboarding(入职/上手)”场景优化。你可以把 GitHub 仓库发给它,它会像一个资深架构师一样,回答你关于架构、依赖关系的问题。

第三梯队:可视化与设计辅助 (理解宏观架构)

理解代码不仅是看字,更要看图。

1. AI 生成 Mermaid 流程图

结合 Claude 3.5 Sonnet (目前逻辑最强的模型) 或 ChatGPT-4o

  • 用法:复制核心业务逻辑代码(或利用 Cursor 选中代码),提示词:请分析这段代码的执行流程,并为我生成一个 Mermaid Sequence Diagram(时序图),展示各个模块的交互。
  • 效果:将生成的代码贴到 Notion 或 Mermaid Live Editor 中,你就能立刻得到一张清晰的时序图。这对于理解“流程”至关重要。

系统化学习路径建议 (配合 AI 工具)

有了工具,还需要正确的方法。建议按照以下 “五步法” 进行:

第一步:宏观认知 (Claude/GPT-4 + Readme)

  • 动作:把项目的 README.mdCONTRIBUTING.md 发给 AI。
  • Prompt我是这个项目的新手,请总结这个项目的核心功能解决了什么问题?它的核心技术栈是什么?主要的架构模式(MVC, Microservices等)是什么?

第二步:寻找入口 (Cursor/Windsurf)

  • 动作:寻找程序的启动点(如 main.go, index.ts, Application.java)。
  • Prompt (@Codebase)请帮我找到这个项目的入口文件,并分析程序启动时主要初始化了哪些服务或组件?

第三步:追踪核心链路 (关键步骤)

  • 动作:选择一个最具代表性的功能(比如电商项目的“下单”,IM项目的“发送消息”)。
  • Prompt (@Codebase)请带我追踪“用户登录”这一功能的完整代码链路。从 HTTP 收到请求开始,经过了哪些 Controller、Service,直到数据库查询。请列出涉及的关键文件。
  • 可视化:让 AI 把这个链路生成 时序图

第四步:理解实现细节与设计模式

  • 动作:打开核心类或复杂函数。
  • Prompt这段代码使用了什么设计模式?(例如:这里用了工厂模式还是策略模式?)为什么要这样设计?如果不这样写会有什么坏处?
  • 技巧:这步能帮你学到“设计”,而不仅仅是“实现”。

第五步:验证理解 (生成测试)

  • 动作:这是检验你是否真的读懂了的大招。
  • Prompt我想验证我对这个 calculatePrice 函数的理解,请帮我为它写一个单元测试,覆盖主要的一个边缘情况。
  • 逻辑:如果你能运行并通过 AI 写的测试,或者你能指出 AI 写的测试哪里不对,说明你彻底懂了。

总结推荐

  • 最推荐的组合Cursor (编辑器) + Claude 3.5 Sonnet (模型选择)
    • 理由:Cursor 的 @Codebase 索引能力配合 Claude 目前地表最强的代码逻辑能力,是目前读源码的“版本答案”。
  • 辅助手段:遇到复杂的交互逻辑,立刻让 AI 画 Mermaid 图

你可以找一个你感兴趣的开源项目(例如一个小型的 Web 框架或工具库),下载 Cursor 试一下这套流程,效率会有惊人的提升。

2 - 快速开始

Kuasar快速开始

2.1 - 安装

Kuasar安装

https://kuasar.io/docs/developer/build/

信息:

  • 操作系统: linux mint 22
  • 内核: 6.8

cloud hypervisor

MicroVM:要启动基于 MicroVM 的沙盒,必须在主机上安装虚拟机管理程序。

基于 cloud hypervisor 做验证, 安装文档:

https://github.com/cloud-hypervisor/cloud-hypervisor/blob/main/docs/building.md

准备工作:

mkdir -p $HOME/work/soft/cloudhypervisor

export CLOUDH=$HOME/work/soft/cloudhypervisor

cd $CLOUDH

安装依赖包:

sudo apt-get update
sudo apt install git build-essential m4 bison flex uuid-dev qemu-utils musl-tools

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

rustup target add x86_64-unknown-linux-musl

clone 代码并开始构建:

mkdir -p ~/work/code/cloud-hypervisor
cd ~/work/code/cloud-hypervisor

git clone https://github.com/cloud-hypervisor/cloud-hypervisor.git
cd cloud-hypervisor

cargo build --release
sudo setcap cap_net_admin+ep ./target/release/cloud-hypervisor

此时构建好的 cloud-hypervisor 二进制文件在 ./target/release/ 目录下,可以执行命令看一下版本:

$ ./target/release/cloud-hypervisor --version

cloud-hypervisor v48.0-51-g68f9e8244

文件大小 3.9M. 真不大:

ls -lh ./target/release/cloud-hypervisor   
-rwxrwxr-x 2 sky sky 3.9M Oct 16 11:17 ./target/release/cloud-hypervisor

安全起见,不用 master 分支构建,改用最新的 release tag,然后采用静态链接:

rm -rf target

git checkout v48.0
cargo build --release --target=x86_64-unknown-linux-musl --all
sudo setcap cap_net_admin+ep ./target/x86_64-unknown-linux-musl/release/cloud-hypervisor

./target/x86_64-unknown-linux-musl/release/cloud-hypervisor --version
cloud-hypervisor v48.0

ls -lh ./target/x86_64-unknown-linux-musl/release/cloud-hypervisor 
-rwxrwxr-x 2 sky sky 4.0M Oct 16 15:31 ./target/x86_64-unknown-linux-musl/release/cloud-hypervisor

静态链接也才4M,没大多少.

microVM

3 - 组件

Kuasar 组件分析

3.1 - 概述

Kuasar 组件概述

所有组件

代码分析

kuasar 代码仓库中共有如下 11 个 Cargo.toml:

  1. Cargo.toml

  2. shim/Cargo.toml

  3. vmm/task/Cargo.toml

  4. runc/Cargo.toml

  5. quark/Cargo.toml

  6. wasm/Cargo.toml

  7. vmm/sandbox/src/bin

  8. vmm/sandbox/src/bin/qemu/main.rs

  9. runc/src/main.rs

  10. quark/src/main.rs

  11. wasm/src/main.rs

通过对上述所有 Cargo.toml 文件的分析,kuasar项目总共会打包出以下二进制文件。

二进制文件总览

kuasar项目总共会打包出8个主要的二进制文件,分为以下几类:

1. Shim 二进制文件 (2个)

  • containerd-shim-kuasar-vmm-v2
    • 功能:VMM sandboxer的containerd shim
    • main入口:shim/src/bin/containerd-shim-kuasar-vmm-v2.rs
  • containerd-shim-kuasar-wasm-v2
    • 功能:WASM sandboxer的containerd shim
    • main入口:shim/src/bin/containerd-shim-kuasar-wasm-v2.rs

2. Sandboxer 二进制文件 (4个)

  • quark-sandboxer
    • 功能:App-Kernel沙箱运行时
    • main入口:quark/src/main.rs
  • runc-sandboxer
    • 功能:传统runc沙箱运行时的包装器
    • main入口:runc/src/main.rs
  • wasm-sandboxer
    • 功能:WebAssembly沙箱运行时(支持WasmEdge和Wasmtime)
    • main入口:wasm/src/main.rs
  • vmm-task
    • 功能:VMM任务服务器(在虚拟机内部运行)
    • main入口:vmm/task/src/main.rs

3. VMM Hypervisor 二进制文件 (3个)

这些都在vmm/sandbox模块中定义:

  • qemu
    • 功能:基于QEMU的虚拟机监控器
    • main入口:vmm/sandbox/src/bin/qemu/main.rs
  • cloud_hypervisor
    • 功能:基于Cloud Hypervisor的虚拟机监控器
    • main入口:vmm/sandbox/src/bin/cloud_hypervisor/main.rs
  • stratovirt
    • 功能:基于StratoVirt的虚拟机监控器
    • main入口:vmm/sandbox/src/bin/stratovirt/main.rs

4. 测试工具 (1个)

  • kuasar-e2e
    • 功能:端到端测试工具
    • main入口:tests/e2e/src/main.rs

关于Cargo.toml的说明

并不是所有的Cargo.toml都会打包出二进制文件:

  • vmm/common/Cargo.toml: 这是一个库(library)模块,不生成二进制文件,只提供给其他模块使用的共享代码
  • vmm/sandbox/derive/Cargo.toml: 这是一个过程宏库,不生成独立的二进制文件

所以总结来说,kuasar项目会生成8个主要的可执行二进制文件,覆盖了从容器运行时到虚拟机监控器的完整技术栈。

cloud hypervisor 相关

相关的二进制文件

如果只考虑启动Cloud Hypervisor的microVM,需要使用到的二进制文件包括:

必需的Kuasar二进制文件

  1. Shim二进制文件 containerd-shim-kuasar-vmm-v2

    • 功能:作为containerd和VMM sandboxer之间的桥梁
    • 位置:shim/src/bin/containerd-shim-kuasar-vmm-v2.rs
    • 作用:接收containerd的CRI调用,转发给VMM sandboxer
  2. VMM Sandboxer二进制文件 cloud_hypervisor (VMM sandboxer的一个实现)

    • 功能:基于Cloud Hypervisor的虚拟机监控器和沙箱管理器
    • 位置:vmm/sandbox/src/bin/cloud_hypervisor/main.rs
    • 作用:创建和管理Cloud Hypervisor虚拟机实例,处理容器生命周期
  3. 虚拟机内部任务服务器 vmm-task

    • 功能:在虚拟机内部运行的任务服务器
    • 位置:vmm/task/src/main.rs
    • 作用:在VM内部处理容器的创建、启动、停止等操作

外部依赖的二进制文件

  1. Cloud Hypervisor本体

    • 这是外部的Cloud Hypervisor项目提供的二进制文件
    • Kuasar通过调用这个二进制文件来实际启动和管理虚拟机

总结: 最核心的是这4个二进制文件:

  1. containerd-shim-kuasar-vmm-v2 (Kuasar提供)
  2. cloud_hypervisor VMM sandboxer (Kuasar提供)
  3. vmm-task (Kuasar提供)
  4. cloud-hypervisor (外部Cloud Hypervisor项目提供)

这是启动Cloud Hypervisor microVM的最小二进制文件集合。其他的sandboxer(如wasm、quark、runc)以及对应的shim在这个场景下都不需要。

典型的工作流程

  1. containerd 接收到创建Pod/容器的请求
  2. containerd-shim-kuasar-vmm-v2 被containerd调用
  3. cloud_hypervisor (VMM sandboxer) 被shim启动
  4. VMM sandboxer调用外部的 cloud-hypervisor 二进制文件创建虚拟机
  5. vmm-task 在虚拟机内部启动,处理容器相关操作
    sequenceDiagram
    participant User as 用户/Kubernetes
    participant Containerd as containerd
    participant Shim as containerd-shim-kuasar-vmm-v2
    participant VMM as cloud_hypervisor (VMM Sandboxer)
    participant CH as cloud-hypervisor (外部二进制)
    participant VM as Virtual Machine
    participant Task as vmm-task (VM内部)

    Note over User, Task: Cloud Hypervisor MicroVM 创建流程

    %% 1. 创建Pod/容器请求
    User->>Containerd: 创建Pod请求 (via CRI)
    Note right of User: kubectl/crictl create pod

    %% 2. Containerd调用Shim
    Containerd->>Shim: 启动 containerd-shim-kuasar-vmm-v2
    Note right of Containerd: containerd识别runtime类型<br/>选择kuasar-vmm runtime

    %% 3. Shim与VMM Sandboxer通信
    Shim->>VMM: 通过Unix Socket连接VMM Sandboxer
    Shim->>VMM: 发送CreateSandbox请求
    Note right of Shim: 传递容器规格、网络配置等

    %% 4. VMM Sandboxer创建虚拟机
    VMM->>VMM: 生成Cloud Hypervisor配置
    Note right of VMM: 配置CPU、内存、网络、存储等

    VMM->>CH: 调用cloud-hypervisor二进制
    Note right of VMM: 启动hypervisor进程

    CH->>VM: 创建并启动虚拟机
    Note right of CH: 初始化VM硬件、加载内核

    %% 5. VM内部初始化
    VM->>Task: 启动vmm-task服务
    Note right of VM: VM启动后自动运行vmm-task

    Task->>VMM: 建立VM内外通信连接
    Note right of Task: 通过vsock或其他方式

    %% 6. 创建容器
    VMM->>Task: 发送CreateContainer请求
    Note right of VMM: 传递容器镜像、配置等

    Task->>Task: 在VM内创建容器
    Note right of Task: 设置namespace、挂载、进程等

    Task->>VMM: 返回创建成功响应

    %% 7. 启动容器
    VMM->>Task: 发送StartContainer请求
    Task->>Task: 启动容器进程
    Task->>VMM: 返回启动成功响应

    %% 8. 响应链路返回
    VMM->>Shim: 返回Sandbox创建成功
    Shim->>Containerd: 返回成功响应
    Containerd->>User: Pod/容器创建完成

    %% 9. 运行时管理(可选)
    Note over Shim, Task: 运行时操作 (exec, logs, stats等)
    User->>Containerd: 执行命令 (kubectl exec)
    Containerd->>Shim: 转发exec请求
    Shim->>VMM: 发送exec请求
    VMM->>Task: 转发到VM内部
    Task->>Task: 在容器内执行命令
    Task->>VMM: 返回执行结果
    VMM->>Shim: 转发结果
    Shim->>Containerd: 返回结果
    Containerd->>User: 显示命令输出

这个序列图展示了以下关键步骤:

主要阶段

  1. 请求发起: 用户通过kubectl/crictl发起Pod创建请求
  2. Shim启动: containerd根据RuntimeClass选择并启动kuasar shim
  3. Sandbox创建: Shim与VMM Sandboxer通信,请求创建新的沙箱
  4. VM创建: VMM Sandboxer调用Cloud Hypervisor创建虚拟机
  5. VM初始化: 虚拟机启动,内部的vmm-task服务开始运行
  6. 容器管理: 通过VM内外通信在虚拟机内创建和启动容器
  7. 运行时操作: 支持exec、logs等运行时操作

关键组件职责

  • containerd-shim-kuasar-vmm-v2: CRI到Kuasar的适配层
  • cloud_hypervisor (VMM Sandboxer): 虚拟机生命周期管理
  • cloud-hypervisor: 实际的hypervisor进程
  • vmm-task: VM内部的容器管理服务

这个架构实现了容器在轻量级虚拟机中的强隔离运行。

3.2 - 生命周期

Kuasar 组件生命周期

仅考虑创建 cloud hypervisor microvm 的场景。

组件生命周期分析

长时间运行的服务组件(守护进程)

  1. containerd

    • 类型: 外部长期运行的系统服务
    • 生命周期: 系统级守护进程,通过systemd管理
    • 功能: 容器运行时管理,接收CRI调用
  2. VMM Sandboxer (cloud_hypervisor)

    • 类型: Kuasar提供的长期运行服务
    • 生命周期: 通过systemd服务启动并持续运行
    • 服务文件: vmm/service/kuasar-vmm.service
    • 功能:
      • 监听Unix Socket等待沙箱创建请求
      • 管理多个虚拟机实例的生命周期
      • 与containerd shim通信
  3. cloud-hypervisor进程

    • 类型: 外部hypervisor守护进程
    • 生命周期: 每个VM对应一个进程,VM存在期间持续运行
    • 功能: 实际的虚拟机监控和硬件模拟
  4. vmm-task (VM内部)

    • 类型: VM内部的任务服务器
    • 生命周期: 随VM启动而启动,VM存在期间持续运行
    • 功能: 在VM内部处理容器操作请求

短时间运行的临时组件

  1. containerd-shim-kuasar-vmm-v2

    • 类型: 临时进程
    • 生命周期 :
      • 由containerd为每个Pod启动
      • Pod删除时退出
    • 功能: 作为containerd和VMM sandboxer之间的桥梁
    timeline
    title 组件生命周期时序

    section 系统启动
        系统启动 : containerd启动
                : VMM Sandboxer启动 (通过systemd)

    section Pod创建请求
        请求到达 : containerd接收创建请求
        Shim启动 : containerd启动shim进程
        VM创建 : VMM Sandboxer启动cloud-hypervisor
               : VM启动,vmm-task启动

    section Pod运行期间
        稳定运行 : containerd (持续运行)
                : VMM Sandboxer (持续运行)
                : cloud-hypervisor (持续运行)
                : vmm-task (持续运行)
                : containerd-shim (持续运行)

    section Pod删除
        清理阶段 : containerd-shim退出
                : VM被销毁
                : cloud-hypervisor进程退出
                : vmm-task随VM退出

Cloud Hypervisor 场景

以连续创建并删除3个Cloud Hypervisor microVM为例,各个组件的参与流程和生命周期:

    gantt
    title Kuasar Cloud Hypervisor - 3个Pod的组件生命周期
    dateFormat YYYY-MM-DD
    axisFormat %m-%d
    
    section 持久服务 (长期运行)
    containerd daemon     :done, containerd, 2024-01-01, 2024-01-05
    vmm-sandboxer service :done, vmmsandboxer, 2024-01-01, 2024-01-05
    virtiofsd daemon      :done, virtiofsd, 2024-01-01, 2024-01-05
    
    section Pod-1 (临时组件)
    Cloud Hypervisor-1    :active, chv1, 2024-01-01, 2024-01-02
    vmm-task-1 (Guest)    :active, task1, 2024-01-01, 2024-01-02
    Container Process-1   :active, container1, 2024-01-01, 2024-01-02
    
    section Pod-2 (临时组件)
    Cloud Hypervisor-2    :active, chv2, 2024-01-02, 2024-01-03
    vmm-task-2 (Guest)    :active, task2, 2024-01-02, 2024-01-03
    Container Process-2   :active, container2, 2024-01-02, 2024-01-03
    
    section Pod-3 (临时组件)
    Cloud Hypervisor-3    :active, chv3, 2024-01-03, 2024-01-04
    vmm-task-3 (Guest)    :active, task3, 2024-01-03, 2024-01-04
    Container Process-3   :active, container3, 2024-01-03, 2024-01-04

长时间运行,服务于全部 3 次创建和删除的组件是:

  • containerd daemon
  • vmm-sandboxer service
  • virtiofsd daemon

时间线视图

    timeline
    title Kuasar Cloud Hypervisor - 连续3个Pod生命周期
    
    section 系统启动
        系统初始化 : containerd daemon启动
                  : vmm-sandboxer service启动
                  : virtiofsd daemon启动
                  
    section Pod-1 创建
        MicroVM-1启动  : Cloud Hypervisor-1进程启动
                      : vmm-task-1 (Guest PID 1)启动
                      : 容器进程-1运行
                     
    section Pod-2 创建
        MicroVM-2启动  : Cloud Hypervisor-2进程启动
                      : vmm-task-2 (Guest PID 1)启动
                      : 容器进程-2运行
                     
    section Pod-3 创建
        MicroVM-3启动  : Cloud Hypervisor-3进程启动
                      : vmm-task-3 (Guest PID 1)启动  
                      : 容器进程-3运行
                     
    section 清理阶段
        清理Pod-1     : 容器进程-1停止
                     : Cloud Hypervisor-1退出
                     : vmm-task-1终止
                     
        清理Pod-2     : 容器进程-2停止
                     : Cloud Hypervisor-2退出
                     : vmm-task-2终止
                     
        清理Pod-3     : 容器进程-3停止
                     : Cloud Hypervisor-3退出
                     : vmm-task-3终止
                     
    section 持续服务
        后台运行     : containerd daemon (持续运行)
                    : vmm-sandboxer service (持续运行)
                    : virtiofsd daemon (持续运行)

详细交互流程图

    sequenceDiagram
    participant User as kubectl/crictl
    participant CD as containerd
    participant VMS as vmm-sandboxer
    participant CHV1 as Cloud Hypervisor-1
    participant Task1 as vmm-task-1 (Guest)
    participant Runc1 as runc-1 (Guest)
    participant CHV2 as Cloud Hypervisor-2
    participant Task2 as vmm-task-2 (Guest)
    participant CHV3 as Cloud Hypervisor-3
    participant Task3 as vmm-task-3 (Guest)
    
    Note over User,Task3: === Pod-1 创建流程 ===
    
    User->>CD: CreateSandbox(pod-1)
    CD->>VMS: CreateSandbox API
    VMS->>VMS: Factory.create_vm()
    VMS->>CHV1: 启动 cloud-hypervisor 进程
    activate CHV1
    CHV1->>Task1: 启动 vmm-task (PID 1)
    activate Task1
    Task1->>VMS: vsock连接注册
    VMS-->>CD: CreateSandboxResponse
    
    User->>CD: CreateContainer(container-1)
    CD->>VMS: CreateContainer API  
    VMS->>Task1: CreateContainer (via vsock)
    Task1->>Runc1: runc create + start
    activate Runc1
    Task1-->>VMS: Success
    VMS-->>CD: Success
    
    Note over User,Task3: === Pod-2 创建流程 ===
    
    User->>CD: CreateSandbox(pod-2)
    CD->>VMS: CreateSandbox API
    VMS->>CHV2: 启动 cloud-hypervisor 进程
    activate CHV2
    CHV2->>Task2: 启动 vmm-task (PID 1)
    activate Task2
    Task2->>VMS: vsock连接注册
    VMS-->>CD: CreateSandboxResponse
    
    User->>CD: CreateContainer(container-2)
    CD->>VMS: CreateContainer API
    VMS->>Task2: CreateContainer (via vsock)
    Task2->>Task2: runc create + start
    VMS-->>CD: Success
    
    Note over User,Task3: === Pod-3 创建流程 ===
    
    User->>CD: CreateSandbox(pod-3)
    CD->>VMS: CreateSandbox API
    VMS->>CHV3: 启动 cloud-hypervisor 进程
    activate CHV3
    CHV3->>Task3: 启动 vmm-task (PID 1)
    activate Task3
    Task3->>VMS: vsock连接注册
    VMS-->>CD: CreateSandboxResponse
    
    Note over User,Task3: === 删除流程 (按创建顺序) ===
    
    User->>CD: StopSandbox(pod-1)
    CD->>VMS: StopSandbox API
    VMS->>CHV1: SIGTERM/shutdown
    CHV1->>Task1: VM shutdown
    deactivate Runc1
    deactivate Task1
    deactivate CHV1
    
    User->>CD: StopSandbox(pod-2)
    CD->>VMS: StopSandbox API
    VMS->>CHV2: SIGTERM/shutdown
    deactivate Task2
    deactivate CHV2
    
    User->>CD: StopSandbox(pod-3)
    CD->>VMS: StopSandbox API
    VMS->>CHV3: SIGTERM/shutdown
    deactivate Task3
    deactivate CHV3

架构组件图:

    graph TB
    subgraph "Host System (持久层)"
        CD[containerd daemon<br/>📍 长期运行]
        VMS[vmm-sandboxer service<br/>📍 长期运行<br/>Unix Socket:/run/vmm-sandboxer.sock]
        VFS[virtiofsd<br/>📍 长期运行]
        Shim[containerd-shim-kuasar-vmm-v2<br/>📍 可选组件]
    end
    
    subgraph "Pod-1 (临时)"
        CHV1[Cloud Hypervisor-1<br/>⏱️ 临时进程]
        subgraph "Guest VM-1"
            Task1[vmm-task-1<br/>⏱️ Guest PID 1]
            Runc1[runc-1<br/>⏱️ 容器管理器]
            Proc1[container-process-1<br/>⏱️ 应用进程]
        end
    end
    
    subgraph "Pod-2 (临时)"
        CHV2[Cloud Hypervisor-2<br/>⏱️ 临时进程]
        subgraph "Guest VM-2"
            Task2[vmm-task-2<br/>⏱️ Guest PID 1]
            Runc2[runc-2<br/>⏱️ 容器管理器]
            Proc2[container-process-2<br/>⏱️ 应用进程]
        end
    end
    
    subgraph "Pod-3 (临时)"
        CHV3[Cloud Hypervisor-3<br/>⏱️ 临时进程]
        subgraph "Guest VM-3"
            Task3[vmm-task-3<br/>⏱️ Guest PID 1]
            Runc3[runc-3<br/>⏱️ 容器管理器]
            Proc3[container-process-3<br/>⏱️ 应用进程]
        end
    end
    
    CD --> VMS
    VMS --> CHV1
    VMS --> CHV2  
    VMS --> CHV3
    
    CHV1 --> Task1
    Task1 --> Runc1
    Runc1 --> Proc1
    
    CHV2 --> Task2
    Task2 --> Runc2
    Runc2 --> Proc2
    
    CHV3 --> Task3
    Task3 --> Runc3
    Runc3 --> Proc3
    
    VMS -.vsock.-> Task1
    VMS -.vsock.-> Task2
    VMS -.vsock.-> Task3
    
    VFS -.virtio-fs.-> CHV1
    VFS -.virtio-fs.-> CHV2
    VFS -.virtio-fs.-> CHV3
    
    style CD fill:#e1f5fe
    style VMS fill:#e1f5fe
    style VFS fill:#e1f5fe
    style CHV1 fill:#fff3e0
    style CHV2 fill:#fff3e0
    style CHV3 fill:#fff3e0
    style Task1 fill:#f3e5f5
    style Task2 fill:#f3e5f5
    style Task3 fill:#f3e5f5

进程生命周期状态图

    stateDiagram-v2
    [*] --> SystemInit: 系统启动
    
    SystemInit --> ContainerdRunning: 启动containerd
    ContainerdRunning --> VMSandboxerRunning: 启动vmm-sandboxer
    VMSandboxerRunning --> VirtioFSRunning: 启动virtiofsd
    VirtioFSRunning --> Ready: 持久服务就绪
    
    Ready --> ParallelCreation: 开始并行创建3个Pod
    
    state ParallelCreation {
        [*] --> Pod1Creating
        [*] --> Pod2Creating
        [*] --> Pod3Creating
        
        state Pod1Creating {
            [*] --> CHV1Starting: Cloud Hypervisor-1启动
            CHV1Starting --> Task1Ready: vmm-task-1初始化
            Task1Ready --> Container1Running: 容器-1运行
            Container1Running --> Pod1Ready: Pod-1就绪
        }
        
        state Pod2Creating {
            [*] --> CHV2Starting: Cloud Hypervisor-2启动
            CHV2Starting --> Task2Ready: vmm-task-2初始化
            Task2Ready --> Container2Running: 容器-2运行
            Container2Running --> Pod2Ready: Pod-2就绪
        }
        
        state Pod3Creating {
            [*] --> CHV3Starting: Cloud Hypervisor-3启动
            CHV3Starting --> Task3Ready: vmm-task-3初始化
            Task3Ready --> Container3Running: 容器-3运行
            Container3Running --> Pod3Ready: Pod-3就绪
        }
        
        Pod1Ready --> AllPodsReady
        Pod2Ready --> AllPodsReady
        Pod3Ready --> AllPodsReady
    }
    
    ParallelCreation --> AllPodsRunning: 所有Pod创建完成
    AllPodsRunning --> ParallelDeletion: 开始并行删除
    
    state ParallelDeletion {
        [*] --> Pod1Deleting
        [*] --> Pod2Deleting
        [*] --> Pod3Deleting
        
        state Pod1Deleting {
            [*] --> Container1Stopping: 停止容器-1
            Container1Stopping --> CHV1Shutdown: 关闭Cloud Hypervisor-1
            CHV1Shutdown --> Task1Terminated: vmm-task-1终止
            Task1Terminated --> Pod1Deleted: Pod-1已删除
        }
        
        state Pod2Deleting {
            [*] --> Container2Stopping: 停止容器-2
            Container2Stopping --> CHV2Shutdown: 关闭Cloud Hypervisor-2
            CHV2Shutdown --> Task2Terminated: vmm-task-2终止
            Task2Terminated --> Pod2Deleted: Pod-2已删除
        }
        
        state Pod3Deleting {
            [*] --> Container3Stopping: 停止容器-3
            Container3Stopping --> CHV3Shutdown: 关闭Cloud Hypervisor-3
            CHV3Shutdown --> Task3Terminated: vmm-task-3终止
            Task3Terminated --> Pod3Deleted: Pod-3已删除
        }
        
        Pod1Deleted --> AllPodsDeleted
        Pod2Deleted --> AllPodsDeleted
        Pod3Deleted --> AllPodsDeleted
    }
    
    ParallelDeletion --> ServicesContinue: 所有Pod清理完成
    ServicesContinue --> Ready: 持久服务继续运行
    
    note right of Ready
        持久服务层组件:
        - containerd daemon
        - vmm-sandboxer service
        - virtiofsd daemon
        这些组件持续运行
    end note
    
    note right of AllPodsRunning
        3个Pod并行运行中:
        - Pod-1: CHV1 + Task1 + Container1
        - Pod-2: CHV2 + Task2 + Container2  
        - Pod-3: CHV3 + Task3 + Container3
    end note

简化版本:

    stateDiagram-v2
    [*] --> SystemReady: 持久服务启动
    
    state SystemReady {
        [*] --> ContainerdRunning
        [*] --> VMSandboxerRunning
        [*] --> VirtioFSRunning
    }
    
    SystemReady --> CreatePods: 开始创建Pod
    
    state CreatePods {
        [*] --> CreatingPod1
        [*] --> CreatingPod2
        [*] --> CreatingPod3
        
        CreatingPod1 --> Pod1Running: CHV1+Task1+Container1
        CreatingPod2 --> Pod2Running: CHV2+Task2+Container2
        CreatingPod3 --> Pod3Running: CHV3+Task3+Container3
    }
    
    CreatePods --> AllRunning: 3个Pod都在运行
    AllRunning --> DeletePods: 开始删除Pod
    
    state DeletePods {
        [*] --> DeletingPod1
        [*] --> DeletingPod2
        [*] --> DeletingPod3
        
        DeletingPod1 --> Pod1Deleted: 清理CHV1+Task1+Container1
        DeletingPod2 --> Pod2Deleted: 清理CHV2+Task2+Container2
        DeletingPod3 --> Pod3Deleted: 清理CHV3+Task3+Container3
    }
    
    DeletePods --> SystemReady: 持久服务继续运行

资源管理视图

    graph TD
    subgraph "持久服务层 (长期运行)"
        A[containerd daemon]
        B[vmm-sandboxer service]
        C[virtiofsd daemon]
    end
    
    subgraph "Pod-1 (临时组件)"
        D1[Cloud Hypervisor-1]
        E1[vmm-task-1]
        F1[runc + container-1]
    end
    
    subgraph "Pod-2 (临时组件)"
        D2[Cloud Hypervisor-2]
        E2[vmm-task-2]
        F2[runc + container-2]
    end
    
    subgraph "Pod-3 (临时组件)"
        D3[Cloud Hypervisor-3]
        E3[vmm-task-3]
        F3[runc + container-3]
    end
    
    A --> B
    B -.管理.-> D1
    B -.管理.-> D2
    B -.管理.-> D3
    
    D1 --> E1
    E1 --> F1
    D2 --> E2
    E2 --> F2
    D3 --> E3
    E3 --> F3
    
    C -.virtio-fs.-> D1
    C -.virtio-fs.-> D2
    C -.virtio-fs.-> D3
    
    style A fill:#e8f5e8,stroke:#2e7d2e,stroke-width:2px
    style B fill:#e8f5e8,stroke:#2e7d2e,stroke-width:2px
    style C fill:#e8f5e8,stroke:#2e7d2e,stroke-width:2px
    style D1 fill:#ffe8e8,stroke:#d32f2f,stroke-width:2px
    style D2 fill:#ffe8e8,stroke:#d32f2f,stroke-width:2px
    style D3 fill:#ffe8e8,stroke:#d32f2f,stroke-width:2px
    style E1 fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
    style E2 fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
    style E3 fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px

3.3 - shim特殊设计

Kuasar shim 组件的特殊设计

背景:发现 greptile 在回答时说 shim 是 1:1 模型,但看 kuasar 的介绍又说 kuasar 特意对 shim 进行了优化,采用 1:N 模型。所以深挖了一下。

问: containerd-shim-kuasar-vmm-v2 这个组件,在连续创建 cloud hypervisor 的 microvm 时,是会为每个 micorovm 的创建而启动一个 containerd-shim-kuasar-vmm-v2 实例,还是一直重用一个 containerd-shim-kuasar-vmm-v2 实例?

再问:关于这一点,我看到 kuasar 的介绍中提到:

优化框架:通过移除所有暂停容器并将 shim 进程替换为单个驻留沙盒器进程,Kuasar 进行了优化,带来了 1:N 进程管理模型,其性能优于当前的 1:1 shim v2 进程模型。基准测试结果显示,Kuasar 的沙盒启动速度提升 2 倍,而管理资源开销降低了 99%。更多详情请参考性能。

greptile的回答:

containerd-shim-kuasar-vmm-v2 确实会为每个 microVM 的创建而启动一个新的实例,但所有实例都连接到同一个长期运行的 sandboxer 进程。 这是 Kuasar 实现性能优化的关键架构设计。

Kuasar 的双层架构设计原理

Kuasar 采用了一种巧妙的双层架构,既保持了与 containerd shim v2 API 的完全兼容性,又实现了显著的性能优化:

第一层:Shim 层(1:1 模型)

  • 每个 sandbox 仍然有一个独立的 containerd-shim-kuasar-vmm-v2 实例
  • 这些 shim 进程变得极其轻量,主要负责:
    • 接收 containerd 的 API 调用
    • 转发请求给 sandboxer 进程
    • 处理 I/O 管道和信号

第二层:Sandboxer 层(1:N 模型)

  • 单一的长期运行的 sandboxer 进程(如 kuasar-vmm
  • 管理多个 Cloud Hypervisor microVM 实例
  • 处理所有重量级操作

整体架构图

    graph TD
    subgraph "Container Orchestrator Layer"
        K8s[Kubernetes]
        Containerd[containerd daemon]
    end
    
    subgraph "Shim Layer (1:1 Model)"
        Shim1["containerd-shim-kuasar-vmm-v2<br/>Instance 1<br/>PID: 1001<br/>轻量级进程"]
        Shim2["containerd-shim-kuasar-vmm-v2<br/>Instance 2<br/>PID: 1002<br/>轻量级进程"]
        Shim3["containerd-shim-kuasar-vmm-v2<br/>Instance 3<br/>PID: 1003<br/>轻量级进程"]
    end
    
    subgraph "Sandboxer Layer (1:N Model)"
        VMM["kuasar-vmm<br/>单一驻留进程<br/>PID: 2000<br/>systemd 服务"]
        Socket["/run/vmm-sandboxer.sock"]
    end
    
    subgraph "Hypervisor Layer"
        VM1["Cloud Hypervisor<br/>microVM 1<br/>sandbox-abc123"]
        VM2["Cloud Hypervisor<br/>microVM 2<br/>sandbox-def456"]
        VM3["Cloud Hypervisor<br/>microVM 3<br/>sandbox-ghi789"]
    end
    
    K8s --> Containerd
    Containerd --> Shim1
    Containerd --> Shim2
    Containerd --> Shim3
    
    Shim1 -.->|Unix Socket<br/>ttrpc gRPC| Socket
    Shim2 -.->|Unix Socket<br/>ttrpc gRPC| Socket
    Shim3 -.->|Unix Socket<br/>ttrpc gRPC| Socket
    
    Socket --> VMM
    
    VMM --> VM1
    VMM --> VM2
    VMM --> VM3
    
    style Shim1 fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    style Shim2 fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    style Shim3 fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    style VMM fill:#fff3e0,stroke:#e65100,stroke-width:3px
    style VM1 fill:#f3e5f5,stroke:#4a148c
    style VM2 fill:#f3e5f5,stroke:#4a148c
    style VM3 fill:#f3e5f5,stroke:#4a148c
    style Socket fill:#e8f5e8,stroke:#2e7d32

进程创建和通信时序图

    sequenceDiagram
    participant Containerd
    participant Shim1 as containerd-shim-kuasar-vmm-v2 #1
    participant Shim2 as containerd-shim-kuasar-vmm-v2 #2  
    participant VMM as kuasar-vmm (驻留进程)
    participant CH1 as Cloud Hypervisor #1
    participant CH2 as Cloud Hypervisor #2
    
    Note over VMM: kuasar-vmm 作为 systemd 服务<br/>已经在运行,监听 /run/vmm-sandboxer.sock
    
    rect rgb(240, 248, 255)
        Note right of Containerd: 创建第一个 sandbox
        Containerd->>+Shim1: 启动新的 shim 实例
        Shim1->>Shim1: fork() 新进程,绑定到 sandbox ID
        Shim1->>+VMM: ttrpc: CreateSandbox(id: "sandbox-abc123")
        VMM->>VMM: 在内存中注册新 sandbox
        VMM->>+CH1: 启动 Cloud Hypervisor microVM 1
        CH1->>CH1: 初始化 VM,分配资源
        CH1-->>-VMM: microVM 1 启动完成
        VMM-->>-Shim1: CreateSandboxResponse
        Shim1-->>-Containerd: 返回成功
    end
    
    rect rgb(255, 248, 240)
        Note right of Containerd: 并行创建第二个 sandbox  
        Containerd->>+Shim2: 启动新的 shim 实例
        Shim2->>Shim2: fork() 新进程,绑定到不同 sandbox ID
        Shim2->>+VMM: ttrpc: CreateSandbox(id: "sandbox-def456")
        VMM->>VMM: 复用现有连接和内存结构
        VMM->>+CH2: 启动 Cloud Hypervisor microVM 2
        CH2->>CH2: 初始化 VM,分配资源
        CH2-->>-VMM: microVM 2 启动完成
        VMM-->>-Shim2: CreateSandboxResponse
        Shim2-->>-Containerd: 返回成功
    end
    
    Note over Shim1, VMM: 两个 shim 实例同时连接到<br/>同一个 kuasar-vmm 进程

资源优化对比图

    graph LR
    subgraph "传统 Shim v2 (1:1 模型) - 资源重复"
        direction TB
        C1[Container 1] --> S1["Shim 1<br/>重量级<br/>内存: 50MB<br/>CPU: 10%"]
        C2[Container 2] --> S2["Shim 2<br/>重量级<br/>内存: 50MB<br/>CPU: 10%"]  
        C3[Container 3] --> S3["Shim 3<br/>重量级<br/>内存: 50MB<br/>CPU: 10%"]
        S1 --> R1["Runtime 1<br/>hypervisor API"]
        S2 --> R2["Runtime 2<br/>hypervisor API"]
        S3 --> R3["Runtime 3<br/>hypervisor API"]
        
        TotalOld["总资源:<br/>内存: 150MB<br/>CPU: 30%<br/>进程数: 6"]
    end
    
    subgraph "Kuasar 优化 (1:1 + 1:N 混合) - 资源共享"
        direction TB
        C4[Container 1] --> S4["Shim 1<br/>轻量级<br/>内存: 2MB<br/>CPU: 0.1%"]
        C5[Container 2] --> S5["Shim 2<br/>轻量级<br/>内存: 2MB<br/>CPU: 0.1%"]
        C6[Container 3] --> S6["Shim 3<br/>轻量级<br/>内存: 2MB<br/>CPU: 0.1%"]
        S4 --> VMM2["kuasar-vmm<br/>单一重量级进程<br/>内存: 20MB<br/>CPU: 5%"]
        S5 --> VMM2
        S6 --> VMM2
        VMM2 --> V1[microVM 1]
        VMM2 --> V2[microVM 2]
        VMM2 --> V3[microVM 3]
        
        TotalNew["总资源:<br/>内存: 26MB (节省 83%)<br/>CPU: 5.3% (节省 82%)<br/>进程数: 4 (节省 33%)"]
    end
    
    style S1 fill:#ffcdd2,stroke:#c62828
    style S2 fill:#ffcdd2,stroke:#c62828
    style S3 fill:#ffcdd2,stroke:#c62828
    style S4 fill:#e8f5e8,stroke:#2e7d32
    style S5 fill:#e8f5e8,stroke:#2e7d32
    style S6 fill:#e8f5e8,stroke:#2e7d32
    style VMM2 fill:#fff3e0,stroke:#e65100
    style TotalOld fill:#ffebee,stroke:#b71c1c
    style TotalNew fill:#f1f8e9,stroke:#33691e

代码实现细节

Shim 层的轻量化实现

shim/src/service.rs 可以看到,每个 shim 实例的核心职责:

// 每个 shim 实例都有独立的 ID 和数据结构
2impl<Transport> Shim for Service<Transport> {
3    async fn new(_runtime_id: &str, id: &str, _namespace: &str, _config: &mut Config) -> Self {
4        let exit = Arc::new(ExitSignal::default());
5        Self {
6            kuasar_server: Box::new(KuasarServer::new(id, exit).await),
7        }
8    }
9}
10
11// 但所有 shim 实例都连接到同一个 sandboxer 地址
12impl<T: ContainerIoTransport> KuasarServer<T> {
13    pub async fn new(id: &str, exit: Arc<ExitSignal>) -> Self {
14        let channel = Endpoint::from_static("https://www.kuasar.io")
15            .connect_with_connector(service_fn(
16                |_: Uri| UnixStream::connect(T::sandboxer_addr()), // 同一个 socket 地址!
17            ))
18            .await
19            .expect("sandboxer should be running");
20    }
21}

Sandboxer 层的单实例架构

vmm/sandbox/src/bin/qemu/main.rs 可以看到,sandboxer 作为单一进程运行:

#[tokio::main]
2async fn main() {
3    // 创建单一的 sandboxer 实例
4    let mut sandboxer: KuasarSandboxer<QemuVMFactory, QemuHooks> = KuasarSandboxer::new(
5        config.sandbox,
6        config.hypervisor.clone(),
7        QemuHooks::new(config.hypervisor),
8    );
9    
10    // 在指定地址监听,为所有 shim 提供服务
11    containerd_sandbox::run(
12        "kuasar-vmm-sandboxer-qemu",
13        &args.listen,  // /run/vmm-sandboxer.sock
14        &args.dir,
15        sandboxer,     // 单一实例管理多个 sandbox
16    )
17    .await
18    .unwrap();
19}

性能优化的关键机制

优化效果饼图:

    pie title 资源使用分布 (Kuasar vs 传统)
    "轻量级 Shim 进程" : 5
    "共享的 sandboxer 进程" : 95
  1. 消除重复开销

    • 只有一个进程处理与 hypervisor 的交互

    • 共享内存池和连接池

    • 统一的 VM 生命周期管理

  2. 保持完整兼容性

    • containerd 仍然看到熟悉的 shim v2 接口

    • 每个 sandbox 保持独立的进程边界

    • 故障隔离和资源清理机制不变

  3. 99% 资源节省的实现

    • 大部分 shim 实例从重量级变为轻量级

    • 重量级的 VM 管理逻辑只有一份

    • 避免重复的 hypervisor API 连接

生命周期管理流程

    stateDiagram-v2
    [*] --> SystemdStart: 系统启动
    SystemdStart --> SandboxerReady: kuasar-vmm 服务启动
    SandboxerReady --> ShimCreate: containerd 创建容器
    
    state ShimCreate {
        [*] --> ForkShim: fork 新的 shim 进程
        ForkShim --> ConnectSandboxer: 连接到 sandboxer socket
        ConnectSandboxer --> CreateVM: 通过 ttrpc 创建 microVM
        CreateVM --> [*]
    }
    
    ShimCreate --> MultipleVMs: 可以创建多个 VM
    
    state MultipleVMs {
        VM1: Cloud Hypervisor 1
        VM2: Cloud Hypervisor 2 
        VM3: Cloud Hypervisor 3
        
        VM1 --> SandboxerManaged: 由同一个 sandboxer 管理
        VM2 --> SandboxerManaged
        VM3 --> SandboxerManaged
    }
    
    MultipleVMs --> ShimDelete: 容器删除
    
    state ShimDelete {
        [*] --> StopVM: 通知 sandboxer 停止 VM
        StopVM --> CleanupShim: shim 进程退出
        CleanupShim --> [*]
    }
    
    ShimDelete --> SandboxerReady: sandboxer 继续运行
    SandboxerReady --> SystemdStop: 系统关闭
    SystemdStop --> [*]

4 - 流程

Kuasar 功能和流程分析

4.1 - Cloud Hypervisor

Kuasar 中使用 Cloud Hypervisor 的流程

4.1.1 - 启动

启动 Cloud Hypervisor

4.1.1.1 - 启动概述

启动 Cloud Hypervisor 的流程概述

Kuasar 中 Cloud Hypervisor microVM 启动全流程

1. 整体架构

Kuasar 通过以下组件实现 Cloud Hypervisor microVM 的管理:

  • containerd-shim-kuasar-vmm-v2: containerd 的 shim 插件
  • kuasar-vmm-sandboxer-clh: Cloud Hypervisor 专用的 sandbox 服务
  • CloudHypervisorVM: VM 实例管理器
  • CloudHypervisorVMFactory: VM 工厂类

2. 详细启动流程

第一阶段:Sandbox 创建 (create)

  1. containerd 调用 shim

    • containerd 通过 CRI API 调用 containerd-shim-kuasar-vmm-v2
    • shim 连接到 kuasar-vmm-sandboxer-clh 服务
  2. Sandboxer 初始化

    rustCopy code1// vmm/sandbox/src/bin/cloud_hypervisor/main.rs
    2let mut sandboxer: KuasarSandboxer<CloudHypervisorVMFactory, CloudHypervisorHooks> =
    3    KuasarSandboxer::new(config.sandbox, config.hypervisor, CloudHypervisorHooks::default());
    
  3. VM 实例创建

    rustCopy code1// CloudHypervisorVMFactory::create_vm
    2let mut vm = CloudHypervisorVM::new(id, &netns, &s.base_dir, &self.vm_config);
    
  4. 设备配置

    • 添加 rootfs (pmem 设备): Pmem::new("rootfs", &image_path, true)
    • 添加随机数生成器: Rng::new("rng", &entropy_source)
    • 添加 vsock 设备: Vsock::new(3, &guest_socket_path, "vsock")
    • 添加控制台设备: Console::new(&console_path, "console")
    • 添加文件系统设备: Fs::new("fs", &virtiofsd_socket, "kuasar")
  5. Cgroup 设置

    rustCopy code1sandbox_cgroups = SandboxCgroup::create_sandbox_cgroups(&cgroup_parent_path, &s.sandbox.id)?;
    2sandbox_cgroups.update_res_for_sandbox_cgroups(&s.sandbox)?;
    

第二阶段:VM 启动 (start)

  1. 网络准备

    rustCopy code1if !sandbox.data.netns.is_empty() {
    2    sandbox.prepare_network().await?;
    3}
    
  2. 启动 virtiofsd

    rustCopy code1async fn start_virtiofsd(&self) -> Result<u32> {
    2    create_dir_all(&self.virtiofsd_config.shared_dir).await?;
    3    let params = self.virtiofsd_config.to_cmdline_params("--");
    4    let mut cmd = tokio::process::Command::new(&self.virtiofsd_config.path);
    5    cmd.args(params.as_slice());
    6    // 在指定的网络命名空间中启动
    7    set_cmd_netns(&mut cmd, self.netns.to_string())?;
    8}
    
  3. 启动 Cloud Hypervisor

    rustCopy code1async fn start(&mut self) -> Result<u32> {
    2    let mut params = self.config.to_cmdline_params("--");
    3    for d in self.devices.iter() {
    4        params.extend(d.to_cmdline_params("--"));
    5    }
    6    
    7    let mut cmd = tokio::process::Command::new(&self.config.path);
    8    cmd.args(params.as_slice());
    9    set_cmd_netns(&mut cmd, self.netns.to_string())?;
    10    let child = cmd.spawn()?;
    11}
    
  4. API 客户端创建

    rustCopy code1match self.create_client().await {
    2    Ok(client) => self.client = Some(client),
    3    Err(e) => return Err(e),
    4};
    

第三阶段:Guest 系统配置

  1. 内核启动参数

    rustCopy code1const DEFAULT_KERNEL_PARAMS: &str = "console=hvc0 \
    2root=/dev/pmem0p1 \
    3rootflags=data=ordered,errors=remount-ro \
    4ro rootfstype=ext4 \
    5task.sharefs_type=virtiofs";
    
  2. Agent 通信建立

    • VM 通过 vsock 设备与 host 通信
    • agent_socket: "hvsock://{guest_socket_path}:1024"
  3. 文件系统挂载

    • rootfs 通过 pmem 设备挂载
    • 共享目录通过 virtiofs 挂载

第四阶段:监控和管理

  1. 进程监控

    rustCopy code1let sandbox_clone = sandbox_mutex.clone();
    2monitor(sandbox_clone);
    
  2. Cgroup 管理

    rust
    Copy code
    1sandbox.add_to_cgroup().await?;
    

3. 关键配置参数

VM 配置示例

tomlCopy code1[hypervisor]
2path = "/usr/local/bin/cloud-hypervisor"
3vcpus = 1
4memory_in_mb = 1024
5kernel_path = "/var/lib/kuasar/vmlinux.bin"
6image_path = "/var/lib/kuasar/kuasar.img"
7hugepages = true
8entropy_source = "/dev/urandom"
9
10[hypervisor.virtiofsd]
11path = "/usr/local/bin/virtiofsd"
12log_level = "info"
13cache = "never"
14thread_pool_size = 4

生成的 Cloud Hypervisor 命令行

bashCopy code1cloud-hypervisor \
2    --api-socket /path/to/api.sock \
3    --cpus boot=1 \
4    --memory size=1073741824,shared=on,hugepages=on \
5    --kernel /var/lib/kuasar/vmlinux.bin \
6    --cmdline "console=hvc0 root=/dev/pmem0p1 ..." \
7    --pmem file=/var/lib/kuasar/kuasar.img,id=rootfs,readonly=on \
8    --rng src=/dev/urandom,iommu=off \
9    --vsock cid=3,socket=/path/to/task.vsock \
10    --console file=/tmp/task.log \
11    --fs tag=kuasar,socket=/path/to/virtiofs.sock

4. 设备热插拔支持

Cloud Hypervisor 还支持设备的热插拔:

rustCopy code1async fn hot_attach(&mut self, device_info: DeviceInfo) -> Result<(BusType, String)> {
2    let client = self.get_client()?;
3    let addr = client.hot_attach(device_info)?;
4    Ok((BusType::PCI, addr))
5}
6
7async fn hot_detach(&mut self, id: &str) -> Result<()> {
8    let client = self.get_client()?;
9    client.hot_detach(id)?;
10    Ok(())
11}

5. 错误处理和恢复

系统具备完整的错误处理和恢复机制:

  • 启动失败时自动清理网络和 cgroup
  • 支持 sandbox 状态恢复
  • 进程监控和异常退出处理

这个流程展示了 Kuasar 如何将 Cloud Hypervisor 集成到 containerd 生态系统中,提供了完整的 microVM 容器运行时解决方案。

4.1.1.2 - 文件

启动 Cloud Hypervisor 过程中的文件传递

内容来自 code wiki.


文件传递

问: 仅仅考虑通过 cloud hypervisor 启动 microvm 的过程,kuasar 是如何将容器镜像,虚拟机 rootfs,kernel 等文件传递给 cloud hypervisor 并启动 microvm 实例的?

在 Kuasar 中,通过 Cloud Hypervisor 启动 MicroVM 实例时,容器镜像、虚拟机 rootfs 和 kernel 等文件通过以下方式传递和使用:

  1. 内核 (Kernel)
  2. 虚拟机 Root Filesystem (Rootfs)
  3. 容器镜像 (Container Image)

总结来说,Kuasar 通过以下机制将这些文件传递给 Cloud Hypervisor 并启动 MicroVM:

  1. 文件路径配置:内核和 rootfs 的路径在 CloudHypervisorVMConfig 配置中指定,并在 CloudHypervisorVM 实例创建时用于构建 cloud-hypervisor 的命令行参数。
  2. 设备抽象:rootfs 作为 Pmem 设备添加到虚拟机中,由 CloudHypervisorVMFactory 处理。
  3. VirtioFS 共享:容器镜像内容通过 virtio-fs 共享机制传递。宿主机上运行的 virtiofsd 进程将宿主机上的共享目录暴露给 guest VM,guest VM 通过 virtio-fs 设备访问这些数据。

KuasarSandboxer 的 Cloud Hypervisor 后端入口点位于 vmm/sandbox/src/bin/cloud_hypervisor/main.rs。它加载配置 vmm/sandbox/src/cloud_hypervisor/config.rs,并使用 CloudHypervisorVMFactory vmm/sandbox/src/cloud_hypervisor/factory.rs 来创建和管理 CloudHypervisorVM 实例。实际启动 cloud-hypervisor 进程和 virtiofsd 进程的逻辑则在 CloudHypervisorVM vmm/sandbox/src/cloud_hypervisor/mod.rs 中实现。

Kernel 生成与传递

    graph TD
    subgraph Host System
        A[Kuasar Build Environment] --> B(Linux Kernel Customization)
        B --> C{build-kernel.sh}
        C --Tailored Kernel Configuration--> D[Kernel Source Directory]
        D --Kernel fragments--> E(Merge Kernel Fragments)
        E --Final .config--> F(Kernel Compilation)
        F --vmlinux.bin--> G[Kernel Binary: /var/lib/kuasar/vmlinux.bin]
    end

    subgraph Cloud Hypervisor VM Launch
        G --> H{Cloud Hypervisor Process}
        H --kernel_path parameter--> I[MicroVM Instance]
    end
  1. 内核定制:Kuasar 为 Cloud Hypervisor 定制 Linux 内核。此过程采用“增量定制”方法,即只添加必要的特性,以优化内存占用和启动时间,如 Linux Kernel Customization for MicroVMs 所述。
  2. 构建脚本build-kernel.sh 脚本 ( vmm/scripts/kernel/build-kernel/build-kernel.sh ) 负责整个内核构建过程。它根据目标架构 (--arch) 和内核类型 (--kernel-type) 动态选择配置片段。
  3. 配置合并:脚本使用 kernel build system utilities 合并这些配置片段,生成最终的 .config 文件 ( vmm/scripts/kernel/build-kernel/build-kernel.sh )。
  4. 内核编译.config 文件用于编译内核,生成 vmlinux.binbzImage,具体取决于 VMM 和架构,例如 Cloud Hypervisor 的 vmlinux.bin
  5. 文件放置:编译好的内核文件(如 vmlinux.bin)会被放置在宿主机上的特定路径,通常是 /var/lib/kuasar/vmlinux.bin ( docs/vmm/README.md )。
  6. 传递给 MicroVM:在启动 cloud-hypervisor 进程时,Kuasar 会将 kernel_path 参数设置为这个内核文件的路径 ( CloudHypervisorConfigvmm/sandbox/src/cloud_hypervisor/config.rs )。Cloud Hypervisor 会加载此内核并启动 MicroVM 实例。
    sequenceDiagram
    participant KuasarBuildEnv as Kuasar Build Environment
    participant BuildKernelSh as build-kernel.sh
    participant KernelSourceDir as Kernel Source Directory
    participant CloudHypervisorConfig as Cloud Hypervisor Config
    participant CloudHypervisorVMM as Cloud Hypervisor VMM Process
    participant MicroVMGuest as MicroVM Guest

    KuasarBuildEnv->>BuildKernelSh: 启动内核构建
    BuildKernelSh->>KernelSourceDir: 根据架构/类型选择内核片段
    KernelSourceDir-->>BuildKernelSh: 提供内核片段
    BuildKernelSh->>BuildKernelSh: 合并片段生成 .config
    BuildKernelSh->>BuildKernelSh: 编译内核 (vmlinux.bin)
    BuildKernelSh-->>KuasarBuildEnv: 输出 vmlinux.bin 到 /var/lib/kuasar/vmlinux.bin
    KuasarBuildEnv->>CloudHypervisorConfig: 配置 kernel_path = /var/lib/kuasar/vmlinux.bin
    CloudHypervisorConfig->>CloudHypervisorVMM: 将 kernel_path 作为参数传递给 Cloud Hypervisor
    CloudHypervisorVMM->>MicroVMGuest: 加载 vmlinux.bin 作为 guest 内核

Root Filesystem 生成与传递

    graph TD
    subgraph Host System
        A[Kuasar Build Environment] --> B(Guest OS Rootfs Build Scripts)
        B --build.sh--> C{Containerized Build Environment}
        C --centos/build_rootfs.sh--> D[Install Rust & Go]
        D --> E(Compile vmm-task & runc)
        E --> F[Populate Rootfs Directory: /tmp/kuasar-rootfs]
        F --build_image.sh--> G[Validate Rootfs]
        G --> H(Create Raw Disk Image)
        H --> I(Partition & Format)
        I --Copy Rootfs Content--> J[Rootfs Image: /var/lib/kuasar/kuasar.img]
        J --Optional: nsdax utility--> K(NVDIMM/DAX Header Configuration)
        K --> J
    end

    subgraph Cloud Hypervisor VM Launch
        J --> L{Cloud Hypervisor Process}
        L --image_path parameter (as Pmem device)--> M[MicroVM Instance]
    end
  1. Rootfs 构建脚本:Kuasar 使用 vmm/scripts/image/build.sh 脚本来构建 guest OS 的 root filesystem。这个脚本可以在容器化环境中执行构建过程 ( vmm/scripts/image/build.sh )。
  2. 具体构建过程:CentOS-based 的 rootfs 通过 vmm/scripts/image/centos/build_rootfs.sh 脚本构建 ( vmm/scripts/image/centos/build_rootfs.sh )。这包括:
  3. 镜像生成vmm/scripts/image/build_image.sh 脚本 ( vmm/scripts/image/build_image.sh ) 负责将 rootfs 目录转换为一个完整的 Kata Containers 兼容的 rootfs 镜像:
  4. 文件放置:生成的 rootfs 镜像文件(如 kuasar.img)会被放置在宿主机上的特定路径,通常是 /var/lib/kuasar/kuasar.img ( docs/vmm/README.md )。
  5. 传递给 MicroVMCloudHypervisorVMFactory 在创建 VM 实例时,如果 image_path 不为空,会将这个镜像文件作为 Pmem 设备添加到虚拟机中。这意味着 rootfs 是以持久内存设备的形式挂载到 MicroVM 中的。
    sequenceDiagram
    participant KuasarBuildEnv as Kuasar Build Environment
    participant BuildSh as build.sh
    participant CentOSBuildRootfsSh as centos/build_rootfs.sh
    participant TmpRootfsDir as /tmp/kuasar-rootfs (Temporary)
    participant BuildImageSh as build_image.sh
    participant QemuImgParted as qemu-img / parted
    participant NsdaxUtility as nsdax utility (Optional)
    participant CloudHypervisorConfig as Cloud Hypervisor Config
    participant CloudHypervisorVMM as Cloud Hypervisor VMM Process
    participant MicroVMGuest as MicroVM Guest

    KuasarBuildEnv->>BuildSh: 启动 rootfs 构建 (例如通过 containerd/docker 容器)
    BuildSh->>CentOSBuildRootfsSh: 在容器内执行具体构建逻辑
    CentOSBuildRootfsSh->>CentOSBuildRootfsSh: 安装 Rust & Go
    CentOSBuildRootfsSh->>CentOSBuildRootfsSh: 编译 vmm-task & runc
    CentosBuildRootfsSh->>TmpRootfsDir: 填充临时 rootfs 目录
    CentosBuildRootfsSh-->>BuildSh: 完成临时 rootfs 准备
    BuildSh->>BuildImageSh: 启动镜像生成脚本
    BuildImageSh->>BuildImageSh: 验证 rootfs
    BuildImageSh->>QemuImgParted: 创建原始磁盘镜像,分区,格式化
    QemuImgParted->>TmpRootfsDir: 从临时 rootfs 目录复制内容到磁盘镜像
    BuildImageSh->>NsdaxUtility: (可选) 配置 NVDIMM/DAX 头
    NsdaxUtility-->>BuildImageSh: 返回更新后的镜像
    BuildImageSh-->>KuasarBuildEnv: 输出 kuasar.img 到 /var/lib/kuasar/kuasar.img
    KuasarBuildEnv->>CloudHypervisorConfig: 配置 image_path = /var/lib/kuasar/kuasar.img
    CloudHypervisorConfig->>CloudHypervisorVMM: 将 image_path 作为 Pmem 设备参数传递
    CloudHypervisorVMM->>MicroVMGuest: 挂载 Pmem 设备作为 guest rootfs

容器镜像传递到 MicroVM

    graph TD
    subgraph Host System
        A[Containerd / iSulad Runtime] --> B(Container Image Layers)
        B --> C{Shared Directory: /base_dir/shared_dir_suffix}
        C --virtiofsd process--> D[virtiofsd Socket: /base_dir/virtiofs.sock]
        D --vmm-sandboxer configures--> E{Cloud Hypervisor Process}
        E --virtio-fs device--> F[MicroVM Instance]
    end

    subgraph Guest MicroVM
        F --virtio-fs driver in guest kernel--> G[Guest OS]
        G --Mount Shared Directory--> H[Container Rootfs Available]
        H --vmm-task process in guest--> I(Container Runtime Operations)
    end
  1. 共享目录:Kuasar 的 MicroVM 沙箱通过 virtio-fs 设备共享机制将容器镜像内容传递给 guest VM。在 CloudHypervisorVMnew 方法中,会为 virtiofsd 配置一个 shared_dir ( vmm/sandbox/src/cloud_hypervisor/mod.rs ),这个目录通常是 sandbox 的 base_dir 下的 SHARED_DIR_SUFFIX ( vmm/common/src/lib.rs )。容器镜像的层叠文件系统等内容会被准备到这个共享目录中。
  2. 启动 virtiofsdCloudHypervisorVM ( vmm/sandbox/src/cloud_hypervisor/mod.rs ) 负责启动 virtiofsd 进程 (start_virtiofsd 方法)。virtiofsd 进程监听一个 Unix socket (socket_path) ( vmm/sandbox/src/cloud_hypervisor/mod.rs ) 并将宿主机上的 shared_dir 暴露出来。
  3. Virtio-FS 设备添加CloudHypervisorVMFactory ( vmm/sandbox/src/cloud_hypervisor/factory.rs ) 在创建 VM 时,会添加一个 virtio-fs 设备,将其 socket 路径设置为 virtiofsd_config.socket_path,并使用 tag="kuasar"
  4. Guest VM 访问:Guest VM 中的 vmm-task ( docs/vmm/README.md ) 作为 PID 1 进程,负责管理容器生命周期。它会利用 guest 内核中的 virtio-fs 驱动通过这个 virtio-fs 设备与宿主机上的 virtiofsd 进程通信,从而访问共享文件,并作为容器的 rootfs 使用。DEFAULT_KERNEL_PARAMS 中包含 task.sharefs_type=virtiofs ( vmm/sandbox/src/stratovirt/config.rs ) 确保 guest 内核启用 virtiofs 相关参数。
    sequenceDiagram
    participant HostSystem as Host System
    participant ContainerdIsuadRuntime as Containerd/iSulad Runtime
    participant SharedDirectory as Shared Directory (/base_dir/shared_dir_suffix)
    participant VirtiofsdProcess as virtiofsd Process
    participant VMMController as vmm-sandboxer (CloudHypervisorVM)
    participant CloudHypervisorVMM as Cloud Hypervisor VMM Process
    participant MicroVMGuest as MicroVM Guest
    participant VMMTaskProcess as vmm-task (PID 1 in Guest)

    ContainerdIsuadRuntime->>SharedDirectory: 准备/提取容器镜像层叠文件系统到共享目录
    VMMController->>SharedDirectory: (通过 virtiofsd_config.shared_dir 配置)
    VMMController->>VirtiofsdProcess: 启动 virtiofsd 进程 (通过 start_virtiofsd 方法)
    VirtiofsdProcess->>VirtiofsdProcess: 监听 Unix Socket (/base_dir/virtiofs.sock) 并提供共享目录服务
    VMMController->>CloudHypervisorVMM: 添加 virtio-fs 设备,指定 socket_path 和 tag="kuasar"
    CloudHypervisorVMM->>MicroVMGuest: 模拟 virtio-fs 设备,连接到宿主机上的 virtiofsd socket
    MicroVMGuest->>VMMTaskProcess: Guest 内核启动参数包含 task.sharefs_type=virtiofs
    VMMTaskProcess->>MicroVMGuest: 通过 guest 内核中的 virtio-fs 驱动挂载共享目录
    MicroVMGuest-->>SharedDirectory: Guest OS 通过 virtio-fs 挂载访问容器 rootfs
    VMMTaskProcess->>VMMTaskProcess: 管理容器生命周期,使用共享的 rootfs

容器镜像共享

问:请详细介绍一下kuasar启动 cloud hypervisor 的 microvm 的过程中,容器镜像是如何共享的,最好用 mermaid 画序列图来帮助理解整个过程。

在 Kuasar 启动 Cloud Hypervisor microVM 的过程中,容器镜像的共享主要通过 virtio-fs 设备进行。vmm-sandboxer 作为 containerd 的沙箱插件,负责管理沙箱生命周期。当创建一个新的沙箱时,它会启动 Cloud Hypervisor 虚拟机并在其中运行 vmm-task 作为 PID 1 进程,virtiofsd 作为辅助进程。容器镜像(rootfs)通过 virtio-fs 挂载到 guest VM 内部,供 vmm-taskrunc 使用。

以下是容器镜像共享的详细过程及序列图:

  1. containerd-shim 请求创建沙箱和容器
  2. vmm-sandboxer 准备 Cloud Hypervisor 虚拟机
  3. virtiofsd 启动
  4. Cloud Hypervisor 启动并连接 virtiofsd
  5. vmm-task 启动并挂载 virtio-fs
  6. 容器镜像共享

通过上述步骤,宿主机上的容器镜像(以及其他需要共享的文件)通过 virtio-fs 机制,以文件系统挂载的方式透明地共享给 guest VM 中的容器。

    sequenceDiagram
    participant Containerd
    participant ContainerdShim
    participant VmmSandboxer
    participant CloudHypervisor
    participant Virtiofsd
    participant VmmTask
    participant Runc

    Containerd->>ContainerdShim: CreateContainer Request (OCI Bundle)
    ContainerdShim->>VmmSandboxer: CreateSandbox/Container (ttrpc)

    VmmSandboxer->>VmmSandboxer: Initialize CloudHypervisorVM
    VmmSandboxer->>VmmSandboxer: Configure virtio-fs device (socket_path, shared_dir)

    VmmSandboxer->>Virtiofsd: Start virtiofsd (shared_dir=base_dir/shared_suffix, socket_path)
    activate Virtiofsd
    Virtiofsd->>Virtiofsd: Create Unix Domain Socket

    VmmSandboxer->>CloudHypervisor: Start Cloud Hypervisor VM (kernel, image, virtio-fs device, kernel_params="...task.sharefs_type=virtiofs...")
    activate CloudHypervisor
    CloudHypervisor->>Virtiofsd: Connect to virtiofsd Unix Domain Socket

    CloudHypervisor->>VmmTask: Launch Guest VM & VmmTask (PID 1)
    activate VmmTask
    VmmTask->>VmmTask: Parse kernel_params (task.sharefs_type=virtiofs)
    VmmTask->>VmmTask: Mount virtio-fs device to /run/kuasar/storage/containers/
    VmmTask-->>CloudHypervisor: Mount successful

    VmmSandboxer->>VmmSandboxer: Process container Mounts (rootfs, bind mounts)
    VmmSandboxer->>VmmSandboxer: Create host shared directories/files (in base_dir/shared_suffix)
    VmmSandboxer->>VmmSandboxer: Bind mount host paths to shared directories

    VmmSandboxer->>VmmTask: CreateContainer (ttrpc, with ANNOTATION_KEY_STORAGE)

    VmmTask->>VmmTask: Read ANNOTATION_KEY_STORAGE
    VmmTask->>VmmTask: Identify container rootfs/mounts from /run/kuasar/storage/containers/

    VmmTask->>Runc: CreateContainer (OCI Spec with adjusted rootfs/mount paths)
    activate Runc
    Runc->>VmmTask: Container created
    deactivate Runc

    VmmTask->>ContainerdShim: Container created response
    ContainerdShim->>Containerd: Container created response

4.1.1.3 - cgroup

启动 Cloud Hypervisor 过程中的 cgroup 处理

内容来自 code wiki.


cgroup

问:当我在一个 bms 上创建多个 cloud hypervisor 的 microvm 时,cgroup 是如何设计的?什么时候创建 cgroup?

当在 bare-metal server (BMS) 上创建多个 Cloud Hypervisor microVM 时,Kuasar 会为每个 sandbox 设计和管理 cgroup,以实现资源隔离和控制。

Cgroup 的设计和创建时间

  1. Sandbox Cgroup 的创建:
    • KuasarSandboxer 收到创建 sandbox 的请求时,它会首先尝试为该 sandbox 创建 cgroup。
    • KuasarSandboxercreate 方法中 ( kuasar-io/kuasar/vmm/sandbox/src/sandbox.rs ),会调用 SandboxCgroup::create_sandbox_cgroups 函数 ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs )。
    • 这个函数会创建一个主 sandbox cgroup,路径格式为 {cgroup_parent_path}/{sandbox_id}。默认的 cgroup_parent_path"kuasar-vmm" ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs ),但也可以通过 PodSandboxConfig 中的 cgroup_parent 字段来指定,例如 Kubernetes 环境下可能为 /kubepods/burstable/podxxx ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs create_mock_pod_sandbox_config 函数)。
    • 除了主 sandbox cgroup,还会创建两个子 cgroup:
      • vcpu cgroup (kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs),用于管理 vCPU 相关的 CPU 资源。
      • pod_overhead cgroup (kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs),用于管理 pod overhead 相关的 CPU 资源。
    • 创建时机: 这些 cgroup 在 KuasarSandboxer 处理 CreateSandbox 请求时,VM 启动之前被创建。
  2. 资源限制的应用:
    • cgroup 创建后,KuasarSandboxer 会调用 sandbox_cgroups.update_res_for_sandbox_cgroups ( kuasar-io/kuasar/vmm/sandbox/src/sandbox.rs ) 来应用资源限制。
    • 这个函数 ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs ) 会根据 SandboxData 中定义的资源 (LinuxContainerResources) 对主 sandbox cgroup 应用 CPU、内存、cpuset 和 hugetlb 资源限制。
    • vcpupod_overhead cgroup 仅应用 CPU 资源限制 ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs )。
    • 应用时机: 资源限制在 sandbox cgroup 创建后立即应用,同样在 VM 启动之前。
  3. VMM 进程和 VCPU 线程加入 Cgroup:
    • 当 MicroVM 启动后,vmm-sandboxer 会获取 VMM 进程的 PID 和其 vCPU 线程的 PID ( kuasar-io/kuasar/vmm/sandbox/src/sandbox.rs )。
    • 它会调用 sandbox_cgroups.add_process_into_sandbox_cgroups ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs ):
      • 将 VMM 主进程加入到主 sandbox cgroup 和 pod_overhead cgroup 中。
      • 将所有 vCPU 线程加入到 vcpu cgroup 中。
    • 加入时机: VMM 进程和 VCPU 线程在 MicroVM 启动并获取到其 PID 后,通过 add_to_cgroup 方法 ( kuasar-io/kuasar/vmm/sandbox/src/sandbox.rs ) 加入到相应的 cgroup 中。
  4. Cgroup V1 和 V2 的支持:
    • 目前 Kuasar 主要支持 cgroup V1 ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs )。
    • vmm-task (PID 1 在 Guest VM 内) 也会处理 cgroup 的挂载配置,get_cgroup_mounts 函数 ( kuasar-io/kuasar/vmm/task/src/mount.rs ) 会根据 unified_cgroup_hierarchy 参数生成 cgroup 挂载点,支持 cgroup v1 和 v2 两种模式,确保 Guest VM 内的 cgroup 视图正确。
  5. Cgroup 的清理:
    • 当 sandbox 被删除时,KuasarSandboxer 会调用 sandbox_cgroups.remove_sandbox_cgroups ( kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs ) 来清理所有相关的 cgroup。
    • 清理过程包括将 cgroup 中的任务移动到父 cgroup,然后删除子 cgroup 和主 cgroup。
    • 清理时机:KuasarSandboxerdelete 方法中 ( kuasar-io/kuasar/vmm/sandbox/src/sandbox.rs )。

总结:

Kuasar 在创建每个 MicroVM sandbox 时,会在宿主机上动态创建一套分层的 cgroup 结构 (sandbox -> vcpu/pod_overhead)。这些 cgroup 在 VM 启动前创建并配置资源限制,在 VM 启动后将 VMM 进程和 vCPU 线程加入相应的 cgroup 进行管理,以确保每个 MicroVM 及其内部组件都运行在预定义的资源限制内,从而实现多个 MicroVM 在 BMS 上的隔离和高效运行。

    sequenceDiagram
    participant KuasarSandboxer
    participant SandboxCgroup
    participant MicroVM
    participant VMMProcess
    participant VCPUThreads

    KuasarSandboxer->>SandboxCgroup: create_sandbox_cgroups(cgroup_parent_path, sandbox_id)
    activate SandboxCgroup
    SandboxCgroup->>SandboxCgroup: Create main sandbox cgroup ({parent_path}/{sandbox_id})
    SandboxCgroup->>SandboxCgroup: Create vcpu cgroup ({sandbox_id}/vcpu) (CPU subsystem only)
    SandboxCgroup->>SandboxCgroup: Create pod_overhead cgroup ({sandbox_id}/pod_overhead) (CPU subsystem only)
    deactivate SandboxCgroup

    KuasarSandboxer->>SandboxCgroup: update_res_for_sandbox_cgroups(sandbox_data)
    activate SandboxCgroup
    SandboxCgroup->>SandboxCgroup: Apply CPU, Memory, CPUSet, HugeTlb limits to main sandbox cgroup
    SandboxCgroup->>SandboxCgroup: Apply CPU limits to vcpu cgroup
    SandboxCgroup->>SandboxCgroup: Apply CPU limits to pod_overhead cgroup
    deactivate SandboxCgroup

    KuasarSandboxer->>MicroVM: Start MicroVM (e.g., Cloud Hypervisor)
    activate MicroVM
    MicroVM->>VMMProcess: Launch VMM process
    VMMProcess->>VCPUThreads: Spawn VCPU threads
    MicroVM-->>KuasarSandboxer: VMM Process PID, VCPU Thread PIDs

    KuasarSandboxer->>SandboxCgroup: add_process_into_sandbox_cgroups(VMM_PID, VCPU_TIDs)
    activate SandboxCgroup
    SandboxCgroup->>SandboxCgroup: Add VMM_PID to main sandbox cgroup
    SandboxCgroup->>SandboxCgroup: Add VMM_PID to pod_overhead cgroup
    SandboxCgroup->>SandboxCgroup: Add VCPU_TIDs to vcpu cgroup
    deactivate SandboxCgroup

    KuasarSandboxer->>KuasarSandboxer: MicroVM and containers run with cgroup isolation

    alt Sandbox Deletion
        KuasarSandboxer->>SandboxCgroup: remove_sandbox_cgroups()
        activate SandboxCgroup
        SandboxCgroup->>SandboxCgroup: Move all tasks from cgroups to parent
        SandboxCgroup->>SandboxCgroup: Delete vcpu cgroup
        SandboxCgroup->>SandboxCgroup: Delete pod_overhead cgroup
        SandboxCgroup->>SandboxCgroup: Delete main sandbox cgroup
        deactivate SandboxCgroup
    end

4.1.1.4 - vmm task

启动 Cloud Hypervisor 过程中 vmm task 的启动方式

vmm task 启动

问:cloud hypervisor 的 microvm 里面的 kuasar agent,是通过什么方式启动的?systemd,还是 init 脚本?

在 Cloud Hypervisor MicroVM 内部,Kuasar agent (即 vmm-task) 是作为 PID 1 进程启动的,它会处理操作系统的初始化和信号,而不是通过传统的 systemdinit 脚本启动。

以下是 vmm-task 启动方式的详细说明:

  1. 作为 PID 1 启动:根据 [MicroVM Sandbox (VMM)](#microvm-sandbox-vmm) 和 VMM Task Lifecycle and Runtime Management 描述,vmm-task 在 Guest VM 内部作为 PID 1 进程运行。这意味着它是 Guest OS 启动后执行的第一个用户空间进程,负责管理容器和进程的生命周期,以及处理资源分配、网络配置和异步 I/O 操作。
  2. 初始化 VM 环境vmm-task 的主要入口点在 kuasar-io/kuasar/vmm/task/src/main.rs。这个组件会初始化 VM 的环境,设置必要的文件系统和内核参数。它还配置了一个 ttrpc 服务器,用于暴露服务以管理任务、沙箱和流,允许外部组件与 VM 的内部进程进行交互。
  3. 处理操作系统信号:作为 PID 1 进程,vmm-task 还负责处理操作系统信号,包括回收子进程和管理优雅关机,这在 kuasar-io/kuasar/vmm/task/src/main.rshandle_signals 函数中有体现。
  4. 配置通过内核命令行参数vmm-task 的配置参数由 TaskConfig 结构管理,该结构在 kuasar-io/kuasar/vmm/task/src/config.rs 中定义。这些配置是通过解析来自 /proc/cmdline 的内核命令行参数动态确定的,允许在运行时灵活调整,而无需依赖外部配置文件。例如,通过 kernel_params = "task.debug" 可以在 vmm-task 中启用调试控制台功能。如 docs/vmm/README.md 中“Developer Guide”部分的“Set up a debug console”所述,task.debug 会作为 kernel_params 传递。

因此,Kuasar agent (vmm-task) 不依赖 systemd 或传统的 init 脚本在 Guest VM 中启动,而是直接作为 MicroVM 的 PID 1 进程运行,并根据内核命令行参数进行配置和初始化。

    sequenceDiagram
    participant CloudHypervisor
    participant GuestKernel
    participant VmmTask

    CloudHypervisor->>GuestKernel: Boot Guest VM (kernel, initrd, kernel_params="...task.sharefs_type=virtiofs task.debug=true...")
    activate GuestKernel
    GuestKernel->>VmmTask: Execute vmm-task as PID 1
    activate VmmTask

    VmmTask->>VmmTask: `initialize()` function in `main.rs`
    VmmTask->>VmmTask: Call `TaskConfig::new()`
    VmmTask->>VmmTask: Parse kernel command-line arguments from `/proc/cmdline` to create `TaskConfig`
    VmmTask->>VmmTask: Set tracing (if `config.enable_tracing` is true)
    VmmTask->>VmmTask: Initialize logger (`init_logger`)
    VmmTask->>VmmTask: Call `early_init_call()`
    VmmTask->>VmmTask: Setup environment variables from `ENVS`
    VmmTask->>VmmTask: Initialize VM rootfs (`init_vm_rootfs()`)
    VmmTask->>VmmTask: Mount static mounts (e.g., `/proc`, `/sys`, `/dev`, `/run`, `/dev/shm`, `/dev/pts`)
    VmmTask->>VmmTask: Mount cgroup filesystems based on `get_cgroup_mounts`
    VmmTask->>VmmTask: Set default `sysctl` parameters (e.g., `vm.overcommit_memory`)

    alt Sharefs Type is "virtiofs"
        VmmTask->>VmmTask: Mount `SHAREFS_VIRTIOFS_MOUNTS` (e.g., `virtiofs` for `KUASAR_STATE_DIR`)
    else Sharefs Type is "9p"
        VmmTask->>VmmTask: Mount `SHAREFS_9P_MOUNTS` (e.g., `9p` for `KUASAR_STATE_DIR`)
    end

    alt Debug Mode Enabled (`config.debug` is true)
        VmmTask->>VmmTask: Call `listen_debug_console("vsock://-1:1025", &config.debug_shell)`
    end

    VmmTask->>VmmTask: Call `late_init_call()`
    VmmTask->>VmmTask: Setup DNS by bind mounting `KUASAR_STATE_DIR/RESOLV_FILENAME` to `/etc/resolv.conf` (if exists)

    VmmTask->>VmmTask: Create TTRPC Server (`create_ttrpc_server()`)
    VmmTask->>VmmTask: Create `TaskService`
    VmmTask->>VmmTask: Create `SandboxService`
    VmmTask->>VmmTask: Create `StreamingService`
    VmmTask->>VmmTask: Register services and bind to `vsock://-1:1024`
    VmmTask->>VmmTask: Start TTRPC Server

    VmmTask->>VmmTask: Listen for OS signals (`handle_signals()`)
    loop Signal Handling
        VmmTask->>VmmTask: Handle `SIGTERM`, `SIGINT`, `SIGCHLD`, `SIGUSR1`, etc.
        alt SIGCHLD
            VmmTask->>VmmTask: `waitpid()` for child processes
            VmmTask->>VmmTask: Notify monitor about child exit/termination
        end
        alt SIGUSR1
            VmmTask->>VmmTask: Toggle tracing and re-initialize logger
        end
    end