runtime-rs: Fix calculation of odd memory sizes

An odd memory size leads to the runtime breaking during its startup, as
shown below:
```
Warning  FailedCreatePodSandBox  34s   kubelet            Failed to
create pod sandbox: rpc error: code = Unknown desc = failed to start
sandbox
"708c81910f4e67e53b4170b6615083339b220154cb9a0c521b3232cdb40d50f9":
failed to create containerd task: failed to create shim task:
Others("failed to handle message start sandbox in task handler\n\nCaused
by:\n    0: start vm\n    1: set vm base config\n    2: set vm
configuration\n    3: Failed to set vm configuration VmConfigInfo {
vcpu_count: 2, max_vcpu_count: 16, cpu_pm: \"on\", cpu_topology:
CpuTopology { threads_per_core: 1, cores_per_die: 1, dies_per_socket: 1,
sockets: 1 }, vpmu_feature: 0, mem_type: \"shmem\", mem_file_path: \"\",
mem_size_mib: 4513, serial_path:
Some(\"/run/kata/708c81910f4e67e53b4170b6615083339b220154cb9a0c521b3232cdb40d50f9/console.sock\"),
pci_hotplug_enabled: true }\n    4: vmm action error:
MachineConfig(InvalidMemorySize(4513))\n\nStack backtrace:\n   0:
anyhow::error::<impl anyhow::Error>::msg\n   1:
hypervisor::dragonball::vmm_instance::VmmInstance::handle_request\n   2:
hypervisor::dragonball::vmm_instance::VmmInstance::set_vm_configuration\n
3: hypervisor::dragonball::inner::DragonballInner::set_vm_base_config\n
4: <hypervisor::dragonball::Dragonball as
hypervisor::Hypervisor>::start_vm::{{closure}}::{{closure}}\n   5:
<hypervisor::dragonball::Dragonball as
hypervisor::Hypervisor>::start_vm::{{closure}}\n   6:
<virt_container::sandbox::VirtSandbox as
common::sandbox::Sandbox>::start::{{closure}}::{{closure}}\n   7:
<virt_container::sandbox::VirtSandbox as
common::sandbox::Sandbox>::start::{{closure}}\n   8:
runtimes::manager::RuntimeHandlerManager::handler_task_message::{{closure}}::{{closure}}\n
9:
runtimes::manager::RuntimeHandlerManager::handler_task_message::{{closure}}\n
10: <service::task_service::TaskService as
containerd_shim_protos::shim::shim_ttrpc_async::Task>::create::{{closure}}\n
11: <containerd_shim_protos::shim::shim_ttrpc_async::CreateMethod as
ttrpc::asynchronous::utils::MethodHandler>::handler::{{closure}}\n  12:
<tokio::time::timeout::Timeout<T> as
core::future::future::Future>::poll\n  13:
ttrpc::asynchronous::server::HandlerContext::handle_msg::{{closure}}\n
14: <core::future::poll_fn::PollFn<F> as
core::future::future::Future>::poll\n  15:
<ttrpc::asynchronous::server::ServerReader as
ttrpc::asynchronous::connection::ReaderDelegate>::handle_msg::{{closure}}::{{closure}}\n
16: tokio::runtime::task::core::Core<T,S>::poll\n  17:
tokio::runtime::task::harness::Harness<T,S>::poll\n  18:
tokio::runtime::scheduler::multi_thread::worker::Context::run_task\n
19: tokio::runtime::scheduler::multi_thread::worker::Context::run\n  20:
tokio::runtime::context::runtime::enter_runtime\n  21:
tokio::runtime::scheduler::multi_thread::worker::run\n  22:
<tokio::runtime::blocking::task::BlockingTask<T> as
core::future::future::Future>::poll\n  23:
tokio::runtime::task::core::Core<T,S>::poll\n  24:
tokio::runtime::task::harness::Harness<T,S>::poll\n  25:
tokio::runtime::blocking::pool::Inner::run\n  26:
std::sys::backtrace::__rust_begin_short_backtrace\n  27:
core::ops::function::FnOnce::call_once{{vtable.shim}}\n  28:
std::sys::pal::unix:🧵:Thread:🆕:thread_start")
```

As we cannot control what the users will set, let's just round it up to
the next acceptable value.

Signed-off-by: Champ-Goblem <cameron@northflank.com>
Signed-off-by: Fabiano Fidêncio <fidencio@northflank.com>
This commit is contained in:
Champ-Goblem 2025-06-25 18:42:09 +02:00 committed by Fabiano Fidêncio
parent a43e06e0eb
commit 91cadb7bfe

View File

@ -22,6 +22,8 @@ struct InitialSize {
orig_toml_default_mem: u32,
}
const MIB: i64 = 1024 * 1024;
// generate initial resource(vcpu and memory in MiB) from annotations
impl TryFrom<&HashMap<String, String>> for InitialSize {
type Error = anyhow::Error;
@ -168,10 +170,15 @@ fn get_nr_vcpu(resource: &LinuxContainerCpuResources) -> u32 {
fn convert_memory_to_mb(memory_in_byte: i64) -> u32 {
if memory_in_byte < 0 {
0
} else {
(memory_in_byte / 1024 / 1024) as u32
return 0;
}
let mem_size = (memory_in_byte / MIB) as u32;
// memory size must be 2MB aligned for hugepage support
if mem_size % 2 != 0 {
return mem_size + 1;
}
mem_size
}
// from the upper layer runtime's annotation (e.g. crio, k8s), get the *cpu quota,
@ -227,7 +234,7 @@ mod tests {
input: InputData {
period: Some(100_000),
quota: Some(220_000),
memory: Some(1024 * 1024 * 512),
memory: Some(512 * MIB),
},
result: InitialSize {
vcpu: 3,
@ -235,6 +242,19 @@ mod tests {
orig_toml_default_mem: 0,
},
},
TestData {
desc: "Odd memory in resource limits",
input: InputData {
period: None,
quota: None,
memory: Some(513 * MIB),
},
result: InitialSize {
vcpu: 0,
mem_mb: 514,
orig_toml_default_mem: 0,
},
},
]
.to_vec()
}