1 - 概述
所有组件
代码分析
kuasar 代码仓库中共有如下 11 个 Cargo.toml:
-
Cargo.toml
-
shim/Cargo.toml
-
vmm/task/Cargo.toml
-
runc/Cargo.toml
-
quark/Cargo.toml
-
wasm/Cargo.toml
-
vmm/sandbox/src/bin
-
vmm/sandbox/src/bin/qemu/main.rs
-
runc/src/main.rs
-
quark/src/main.rs
-
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二进制文件
-
Shim二进制文件 containerd-shim-kuasar-vmm-v2
- 功能:作为containerd和VMM sandboxer之间的桥梁
- 位置:
shim/src/bin/containerd-shim-kuasar-vmm-v2.rs - 作用:接收containerd的CRI调用,转发给VMM sandboxer
-
VMM Sandboxer二进制文件 cloud_hypervisor (VMM sandboxer的一个实现)
- 功能:基于Cloud Hypervisor的虚拟机监控器和沙箱管理器
- 位置:
vmm/sandbox/src/bin/cloud_hypervisor/main.rs - 作用:创建和管理Cloud Hypervisor虚拟机实例,处理容器生命周期
-
虚拟机内部任务服务器 vmm-task
- 功能:在虚拟机内部运行的任务服务器
- 位置:
vmm/task/src/main.rs - 作用:在VM内部处理容器的创建、启动、停止等操作
外部依赖的二进制文件
-
Cloud Hypervisor本体
- 这是外部的Cloud Hypervisor项目提供的二进制文件
- Kuasar通过调用这个二进制文件来实际启动和管理虚拟机
总结: 最核心的是这4个二进制文件:
containerd-shim-kuasar-vmm-v2(Kuasar提供)cloud_hypervisorVMM sandboxer (Kuasar提供)vmm-task(Kuasar提供)cloud-hypervisor(外部Cloud Hypervisor项目提供)
这是启动Cloud Hypervisor microVM的最小二进制文件集合。其他的sandboxer(如wasm、quark、runc)以及对应的shim在这个场景下都不需要。
典型的工作流程
- containerd 接收到创建Pod/容器的请求
- containerd-shim-kuasar-vmm-v2 被containerd调用
- cloud_hypervisor (VMM sandboxer) 被shim启动
- VMM sandboxer调用外部的 cloud-hypervisor 二进制文件创建虚拟机
- 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: 显示命令输出
这个序列图展示了以下关键步骤:
主要阶段
- 请求发起: 用户通过kubectl/crictl发起Pod创建请求
- Shim启动: containerd根据RuntimeClass选择并启动kuasar shim
- Sandbox创建: Shim与VMM Sandboxer通信,请求创建新的沙箱
- VM创建: VMM Sandboxer调用Cloud Hypervisor创建虚拟机
- VM初始化: 虚拟机启动,内部的vmm-task服务开始运行
- 容器管理: 通过VM内外通信在虚拟机内创建和启动容器
- 运行时操作: 支持exec、logs等运行时操作
关键组件职责
- containerd-shim-kuasar-vmm-v2: CRI到Kuasar的适配层
- cloud_hypervisor (VMM Sandboxer): 虚拟机生命周期管理
- cloud-hypervisor: 实际的hypervisor进程
- vmm-task: VM内部的容器管理服务
这个架构实现了容器在轻量级虚拟机中的强隔离运行。
2 - 生命周期
仅考虑创建 cloud hypervisor microvm 的场景。
组件生命周期分析
长时间运行的服务组件(守护进程)
-
containerd
- 类型: 外部长期运行的系统服务
- 生命周期: 系统级守护进程,通过systemd管理
- 功能: 容器运行时管理,接收CRI调用
-
VMM Sandboxer (
cloud_hypervisor)- 类型: Kuasar提供的长期运行服务
- 生命周期: 通过systemd服务启动并持续运行
- 服务文件:
vmm/service/kuasar-vmm.service - 功能:
- 监听Unix Socket等待沙箱创建请求
- 管理多个虚拟机实例的生命周期
- 与containerd shim通信
-
cloud-hypervisor进程
- 类型: 外部hypervisor守护进程
- 生命周期: 每个VM对应一个进程,VM存在期间持续运行
- 功能: 实际的虚拟机监控和硬件模拟
-
vmm-task (VM内部)
- 类型: VM内部的任务服务器
- 生命周期: 随VM启动而启动,VM存在期间持续运行
- 功能: 在VM内部处理容器操作请求
短时间运行的临时组件
-
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 - 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
-
消除重复开销
-
只有一个进程处理与 hypervisor 的交互
-
共享内存池和连接池
-
统一的 VM 生命周期管理
-
-
保持完整兼容性
-
containerd 仍然看到熟悉的 shim v2 接口
-
每个 sandbox 保持独立的进程边界
-
故障隔离和资源清理机制不变
-
-
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 --> [*]