cgroup
启动 Cloud Hypervisor 过程中的 cgroup 处理
内容来自 code wiki.
cgroup
问:当我在一个 bms 上创建多个 cloud hypervisor 的 microvm 时,cgroup 是如何设计的?什么时候创建 cgroup?
当在 bare-metal server (BMS) 上创建多个 Cloud Hypervisor microVM 时,Kuasar 会为每个 sandbox 设计和管理 cgroup,以实现资源隔离和控制。
Cgroup 的设计和创建时间
- Sandbox Cgroup 的创建:
- 当
KuasarSandboxer收到创建 sandbox 的请求时,它会首先尝试为该 sandbox 创建 cgroup。 - 在
KuasarSandboxer的create方法中 (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.rscreate_mock_pod_sandbox_config函数)。 - 除了主 sandbox cgroup,还会创建两个子 cgroup:
vcpucgroup (kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs),用于管理 vCPU 相关的 CPU 资源。pod_overheadcgroup (kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs),用于管理 pod overhead 相关的 CPU 资源。
- 创建时机: 这些 cgroup 在
KuasarSandboxer处理CreateSandbox请求时,VM 启动之前被创建。
- 当
- 资源限制的应用:
- 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 资源限制。 vcpu和pod_overheadcgroup 仅应用 CPU 资源限制 (kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs)。- 应用时机: 资源限制在 sandbox cgroup 创建后立即应用,同样在 VM 启动之前。
- cgroup 创建后,
- 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_overheadcgroup 中。 - 将所有 vCPU 线程加入到
vcpucgroup 中。
- 将 VMM 主进程加入到主 sandbox cgroup 和
- 加入时机: VMM 进程和 VCPU 线程在 MicroVM 启动并获取到其 PID 后,通过
add_to_cgroup方法 (kuasar-io/kuasar/vmm/sandbox/src/sandbox.rs) 加入到相应的 cgroup 中。
- 当 MicroVM 启动后,
- 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 视图正确。
- 目前 Kuasar 主要支持 cgroup V1 (
- Cgroup 的清理:
- 当 sandbox 被删除时,
KuasarSandboxer会调用sandbox_cgroups.remove_sandbox_cgroups(kuasar-io/kuasar/vmm/sandbox/src/cgroup.rs) 来清理所有相关的 cgroup。 - 清理过程包括将 cgroup 中的任务移动到父 cgroup,然后删除子 cgroup 和主 cgroup。
- 清理时机: 在
KuasarSandboxer的delete方法中 (kuasar-io/kuasar/vmm/sandbox/src/sandbox.rs)。
- 当 sandbox 被删除时,
总结:
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