mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-04-09 13:32:08 +00:00
runtime-rs: Fix initial vCPU / memory with static_sandbox_resource_mgmt
InitialSizeManager::setup_config() is responsible for applying the
sandbox workload sizing (computed from containerd/CRI-O sandbox
annotations) to the hypervisor configuration before VM creation.
Previously, the workload vCPU count was only logged but never actually
added to default_vcpus, so the VM was always created with only the base
vCPUs from the configuration/annotations. This caused the
k8s-sandbox-vcpus-allocation test to fail with qemu-snp-runtime-rs:
a pod with default_vcpus=0.75 and a container CPU limit of 1.2 should
see ceil(0.75 + 1.2) = 2 vCPUs, but only got 1.
Additionally, the workload memory was being added to default_memory
unconditionally, diverging from the Go runtime which only applies both
CPU and memory additions when static_sandbox_resource_mgmt is enabled.
In the non-static path, adding workload resources here would cause
double-counting: once from setup_config() at sandbox creation, and
again from update_cpu_resources()/update_mem_resources() when
individual containers are added.
Guard both additions behind static_sandbox_resource_mgmt, matching the
Go runtime's behavior in src/runtime/pkg/oci/utils.go:
if sandboxConfig.StaticResourceMgmt {
sandboxConfig.HypervisorConfig.NumVCPUsF += sandboxConfig.SandboxResources.WorkloadCPUs
sandboxConfig.HypervisorConfig.MemorySize += sandboxConfig.SandboxResources.WorkloadMemMB
}
Fixes: k8s-sandbox-vcpus-allocation test failure on qemu-snp-runtime-rs
Signed-off-by: Fabiano Fidêncio <ffidencio@nvidia.com>
Made-with: Cursor
This commit is contained in:
@@ -142,15 +142,23 @@ impl InitialSizeManager {
|
|||||||
|
|
||||||
if self.resource.vcpu > 0.0 {
|
if self.resource.vcpu > 0.0 {
|
||||||
info!(sl!(), "resource with vcpu {}", self.resource.vcpu);
|
info!(sl!(), "resource with vcpu {}", self.resource.vcpu);
|
||||||
|
if config.runtime.static_sandbox_resource_mgmt {
|
||||||
|
hv.cpu_info.default_vcpus += self.resource.vcpu;
|
||||||
|
let new_vcpus_ceil = hv.cpu_info.default_vcpus.ceil() as u32;
|
||||||
|
if hv.cpu_info.default_maxvcpus < new_vcpus_ceil {
|
||||||
|
hv.cpu_info.default_maxvcpus = new_vcpus_ceil;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.resource.orig_toml_default_mem = hv.memory_info.default_memory;
|
self.resource.orig_toml_default_mem = hv.memory_info.default_memory;
|
||||||
if self.resource.mem_mb > 0 {
|
if self.resource.mem_mb > 0 {
|
||||||
// since the memory overhead introduced by kata-agent and system components
|
info!(sl!(), "resource with memory {}", self.resource.mem_mb);
|
||||||
// will really affect the amount of memory the user can use, so we choose to
|
if config.runtime.static_sandbox_resource_mgmt {
|
||||||
// plus the default_memory here, instead of overriding it.
|
hv.memory_info.default_memory += self.resource.mem_mb;
|
||||||
// (if we override the default_memory here, and user apllications still
|
if hv.memory_info.default_maxmemory < hv.memory_info.default_memory {
|
||||||
// use memory as they orignally expected, it would be easy to OOM.)
|
hv.memory_info.default_maxmemory = hv.memory_info.default_memory;
|
||||||
hv.memory_info.default_memory += self.resource.mem_mb;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -366,4 +374,114 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_config(
|
||||||
|
default_vcpus: f32,
|
||||||
|
default_maxvcpus: u32,
|
||||||
|
default_memory: u32,
|
||||||
|
default_maxmemory: u32,
|
||||||
|
static_sandbox_resource_mgmt: bool,
|
||||||
|
) -> TomlConfig {
|
||||||
|
use kata_types::config::Hypervisor;
|
||||||
|
|
||||||
|
let mut config = TomlConfig::default();
|
||||||
|
config
|
||||||
|
.hypervisor
|
||||||
|
.insert("qemu".to_owned(), Hypervisor::default());
|
||||||
|
config
|
||||||
|
.hypervisor
|
||||||
|
.entry("qemu".to_owned())
|
||||||
|
.and_modify(|hv| {
|
||||||
|
hv.cpu_info.default_vcpus = default_vcpus;
|
||||||
|
hv.cpu_info.default_maxvcpus = default_maxvcpus;
|
||||||
|
hv.memory_info.default_memory = default_memory;
|
||||||
|
hv.memory_info.default_maxmemory = default_maxmemory;
|
||||||
|
});
|
||||||
|
config.runtime.hypervisor_name = "qemu".to_owned();
|
||||||
|
config.runtime.static_sandbox_resource_mgmt = static_sandbox_resource_mgmt;
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_setup_config_static_applies_vcpu_and_memory() {
|
||||||
|
let mut config = make_config(1.0, 4, 256, 4096, true);
|
||||||
|
let mut mgr = InitialSizeManager {
|
||||||
|
resource: InitialSize {
|
||||||
|
vcpu: 1.2,
|
||||||
|
mem_mb: 512,
|
||||||
|
orig_toml_default_mem: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mgr.setup_config(&mut config).unwrap();
|
||||||
|
let hv = config.hypervisor.get("qemu").unwrap();
|
||||||
|
assert_eq!(hv.cpu_info.default_vcpus, 2.2);
|
||||||
|
assert_eq!(hv.memory_info.default_memory, 768);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_setup_config_non_static_does_not_apply() {
|
||||||
|
let mut config = make_config(1.0, 4, 256, 4096, false);
|
||||||
|
let mut mgr = InitialSizeManager {
|
||||||
|
resource: InitialSize {
|
||||||
|
vcpu: 1.2,
|
||||||
|
mem_mb: 512,
|
||||||
|
orig_toml_default_mem: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mgr.setup_config(&mut config).unwrap();
|
||||||
|
let hv = config.hypervisor.get("qemu").unwrap();
|
||||||
|
assert_eq!(hv.cpu_info.default_vcpus, 1.0);
|
||||||
|
assert_eq!(hv.memory_info.default_memory, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_setup_config_clamps_maxvcpus() {
|
||||||
|
let mut config = make_config(1.0, 2, 256, 4096, true);
|
||||||
|
let mut mgr = InitialSizeManager {
|
||||||
|
resource: InitialSize {
|
||||||
|
vcpu: 2.5,
|
||||||
|
mem_mb: 0,
|
||||||
|
orig_toml_default_mem: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mgr.setup_config(&mut config).unwrap();
|
||||||
|
let hv = config.hypervisor.get("qemu").unwrap();
|
||||||
|
assert_eq!(hv.cpu_info.default_vcpus, 3.5);
|
||||||
|
assert_eq!(hv.cpu_info.default_maxvcpus, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_setup_config_clamps_maxmemory() {
|
||||||
|
let mut config = make_config(1.0, 4, 256, 300, true);
|
||||||
|
let mut mgr = InitialSizeManager {
|
||||||
|
resource: InitialSize {
|
||||||
|
vcpu: 0.0,
|
||||||
|
mem_mb: 512,
|
||||||
|
orig_toml_default_mem: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mgr.setup_config(&mut config).unwrap();
|
||||||
|
let hv = config.hypervisor.get("qemu").unwrap();
|
||||||
|
assert_eq!(hv.memory_info.default_memory, 768);
|
||||||
|
assert_eq!(hv.memory_info.default_maxmemory, 768);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_setup_config_preserves_orig_toml_default_mem() {
|
||||||
|
let mut config = make_config(1.0, 4, 256, 4096, true);
|
||||||
|
let mut mgr = InitialSizeManager {
|
||||||
|
resource: InitialSize {
|
||||||
|
vcpu: 0.0,
|
||||||
|
mem_mb: 128,
|
||||||
|
orig_toml_default_mem: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mgr.setup_config(&mut config).unwrap();
|
||||||
|
assert_eq!(mgr.get_orig_toml_default_mem(), 256);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user