runtime-rs: add the sandbox's shm volume support

Docker containers support specifying the shm size using the --shm-size
option and support sandbox-level shm volumes, so we've added support for
shm volumes. Since Kubernetes doesn't support specifying the shm size,
it typically uses a memory-based emptydir as the container's shm, and
its size can be specified.

Signed-off-by: Fupan Li <fupan.lfp@antgroup.com>
This commit is contained in:
Fupan Li
2025-09-09 10:42:59 +08:00
committed by Fabiano Fidêncio
parent d48c542a52
commit 4a92fc1129
12 changed files with 153 additions and 17 deletions

View File

@@ -90,9 +90,9 @@ impl ResourceManager {
inner.setup_after_start_vm().await
}
pub async fn get_storage_for_sandbox(&self) -> Result<Vec<Storage>> {
pub async fn get_storage_for_sandbox(&self, shm_size: u64) -> Result<Vec<Storage>> {
let inner = self.inner.read().await;
inner.get_storage_for_sandbox().await
inner.get_storage_for_sandbox(shm_size).await
}
pub async fn handler_rootfs(

View File

@@ -17,7 +17,9 @@ use hypervisor::{
},
BlockConfig, Hypervisor, VfioConfig,
};
use kata_types::mount::Mount;
use kata_types::mount::{
Mount, DEFAULT_KATA_GUEST_SANDBOX_DIR, KATA_EPHEMERAL_VOLUME_TYPE, SHM_DIR,
};
use kata_types::{
config::{hypervisor::TopologyConfigInfo, TomlConfig},
mount::{adjust_rootfs_mounts, KATA_IMAGE_FORCE_GUEST_PULL},
@@ -326,12 +328,33 @@ impl ResourceManagerInner {
Ok(())
}
pub async fn get_storage_for_sandbox(&self) -> Result<Vec<Storage>> {
pub async fn get_storage_for_sandbox(&self, shm_size: u64) -> Result<Vec<Storage>> {
let mut storages = vec![];
if let Some(d) = self.share_fs.as_ref() {
let mut s = d.get_storages().await.context("get storage")?;
storages.append(&mut s);
}
let shm_size_option = format!("size={}", shm_size);
let mount_point = format!("{}/{}", DEFAULT_KATA_GUEST_SANDBOX_DIR, SHM_DIR);
let shm_storage = Storage {
driver: KATA_EPHEMERAL_VOLUME_TYPE.to_string(),
mount_point,
source: "shm".to_string(),
fs_type: "tmpfs".to_string(),
options: vec![
"noexec".to_string(),
"nosuid".to_string(),
"nodev".to_string(),
"mode=1777".to_string(),
shm_size_option,
],
..Default::default()
};
storages.push(shm_storage);
Ok(storages)
}

View File

@@ -40,8 +40,6 @@ const KATA_HOST_SHARED_DIR: &str = "/run/kata-containers/shared/sandboxes/";
/// share fs (for example virtio-fs) mount path in the guest
pub const KATA_GUEST_SHARE_DIR: &str = "/run/kata-containers/shared/containers/";
pub(crate) const DEFAULT_KATA_GUEST_SANDBOX_DIR: &str = "/run/kata-containers/sandbox/";
pub const PASSTHROUGH_FS_DIR: &str = "passthrough";
const RAFS_DIR: &str = "rafs";

View File

@@ -7,11 +7,11 @@
use std::path::{Path, PathBuf};
use super::Volume;
use crate::share_fs::DEFAULT_KATA_GUEST_SANDBOX_DIR;
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use hypervisor::device::device_manager::DeviceManager;
use kata_sys_util::mount::{get_mount_path, get_mount_type};
use kata_types::mount::DEFAULT_KATA_GUEST_SANDBOX_DIR;
use kata_types::mount::KATA_EPHEMERAL_VOLUME_TYPE;
use nix::sys::stat::stat;
use oci_spec::runtime as oci;

View File

@@ -9,6 +9,7 @@ mod default_volume;
mod ephemeral_volume;
pub mod hugepage;
mod share_fs_volume;
mod shm_volume;
pub mod utils;
pub mod direct_volume;
@@ -67,10 +68,15 @@ impl VolumeResource {
// handle mounts
for m in oci_mounts {
let read_only = get_mount_options(m.options()).iter().any(|opt| opt == "ro");
let volume: Arc<dyn Volume> = if ephemeral_volume::is_ephemeral_volume(m) {
let volume: Arc<dyn Volume> = if shm_volume::is_shm_volume(m) {
Arc::new(
shm_volume::ShmVolume::new(m)
.with_context(|| format!("new shm volume {:?}", m))?,
)
} else if ephemeral_volume::is_ephemeral_volume(m) {
Arc::new(
ephemeral_volume::EphemeralVolume::new(m)
.with_context(|| format!("new shm volume {:?}", m))?,
.with_context(|| format!("new ephemeral volume {:?}", m))?,
)
} else if is_block_volume(m) {
// handle block volume

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2019-2022 Alibaba Cloud
// Copyright (c) 2019-2022 Ant Group
//
// SPDX-License-Identifier: Apache-2.0
//
use std::path::PathBuf;
use super::Volume;
use anyhow::Result;
use async_trait::async_trait;
use hypervisor::device::device_manager::DeviceManager;
use kata_sys_util::mount::{get_mount_path, get_mount_type};
use kata_types::mount::{
DEFAULT_KATA_GUEST_SANDBOX_DIR, KATA_EPHEMERAL_VOLUME_TYPE, SHM_DEVICE, SHM_DIR,
};
use oci_spec::runtime as oci;
use tokio::sync::RwLock;
#[derive(Debug)]
pub(crate) struct ShmVolume {
mount: oci::Mount,
}
impl ShmVolume {
pub(crate) fn new(m: &oci::Mount) -> Result<Self> {
let mut mount = oci::Mount::default();
mount.set_destination(m.destination().clone());
mount.set_typ(Some("bind".to_string()));
mount.set_source(Some(
PathBuf::from(DEFAULT_KATA_GUEST_SANDBOX_DIR).join(SHM_DIR),
));
mount.set_options(Some(vec!["rbind".to_string()]));
Ok(Self { mount })
}
}
#[async_trait]
impl Volume for ShmVolume {
fn get_volume_mount(&self) -> anyhow::Result<Vec<oci::Mount>> {
Ok(vec![self.mount.clone()])
}
fn get_storage(&self) -> Result<Vec<agent::Storage>> {
Ok(vec![])
}
async fn cleanup(&self, _device_manager: &RwLock<DeviceManager>) -> Result<()> {
// No cleanup is required for ShmVolume because it is a mount in guest which
// does not require explicit unmounting or deletion in host side.
Ok(())
}
fn get_device_id(&self) -> Result<Option<String>> {
Ok(None)
}
}
pub(crate) fn is_shm_volume(m: &oci::Mount) -> bool {
get_mount_path(&Some(m.destination().clone())).as_str() == SHM_DEVICE
&& get_mount_type(m).as_str() != KATA_EPHEMERAL_VOLUME_TYPE
}