diff --git a/src/libs/kata-sys-util/src/k8s.rs b/src/libs/kata-sys-util/src/k8s.rs index be95d5d330..4ae31921e7 100644 --- a/src/libs/kata-sys-util/src/k8s.rs +++ b/src/libs/kata-sys-util/src/k8s.rs @@ -49,7 +49,7 @@ pub fn is_host_empty_dir(path: &str) -> bool { false } -// set_ephemeral_storage_type sets the mount type to 'ephemeral' +// update_ephemeral_storage_type sets the mount type to 'ephemeral' // if the mount source path is provisioned by k8s for ephemeral storage. // For the given pod ephemeral volume is created only once // backed by tmpfs inside the VM. For successive containers @@ -63,6 +63,8 @@ pub fn update_ephemeral_storage_type(oci_spec: &mut Spec) { if is_ephemeral_volume(&m.source) { m.r#type = String::from(mount::KATA_EPHEMERAL_VOLUME_TYPE); } else if is_host_empty_dir(&m.source) { + // FIXME support disable_guest_empty_dir + // https://github.com/kata-containers/kata-containers/blob/02a51e75a7e0c6fce5e8abe3b991eeac87e09645/src/runtime/pkg/katautils/create.go#L105 m.r#type = String::from(mount::KATA_HOST_DIR_VOLUME_TYPE); } } diff --git a/src/libs/kata-types/src/mount.rs b/src/libs/kata-types/src/mount.rs index 2ccc0feed2..b58e810d60 100644 --- a/src/libs/kata-types/src/mount.rs +++ b/src/libs/kata-types/src/mount.rs @@ -13,7 +13,7 @@ pub const KATA_VOLUME_TYPE_PREFIX: &str = "kata:"; pub const KATA_GUEST_MOUNT_PREFIX: &str = "kata:guest-mount:"; /// KATA_EPHEMERAL_DEV_TYPE creates a tmpfs backed volume for sharing files between containers. -pub const KATA_EPHEMERAL_VOLUME_TYPE: &str = "kata:ephemeral"; +pub const KATA_EPHEMERAL_VOLUME_TYPE: &str = "ephemeral"; /// KATA_HOST_DIR_TYPE use for host empty dir pub const KATA_HOST_DIR_VOLUME_TYPE: &str = "kata:hostdir"; diff --git a/src/runtime-rs/crates/resource/src/share_fs/mod.rs b/src/runtime-rs/crates/resource/src/share_fs/mod.rs index b7611964d6..b9abdb9df6 100644 --- a/src/runtime-rs/crates/resource/src/share_fs/mod.rs +++ b/src/runtime-rs/crates/resource/src/share_fs/mod.rs @@ -55,6 +55,7 @@ pub struct ShareFsVolumeConfig { pub target: String, pub readonly: bool, pub mount_options: Vec, + pub mount: oci::Mount, } pub struct ShareFsMountResult { diff --git a/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs b/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs index 295554f110..ce32779748 100644 --- a/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs +++ b/src/runtime-rs/crates/resource/src/share_fs/virtio_fs_share_mount.rs @@ -8,12 +8,15 @@ use agent::Storage; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use kata_types::k8s::is_watchable_mount; +use kata_types::mount; +use nix::sys::stat::stat; use std::fs; use std::os::unix::fs::PermissionsExt; use std::path::Path; const WATCHABLE_PATH_NAME: &str = "watchable"; const WATCHABLE_BIND_DEV_TYPE: &str = "watchable-bind"; +const EPHEMERAL_PATH: &str = "/run/kata-containers/sandbox/ephemeral"; use super::{ utils, ShareFsMount, ShareFsMountResult, ShareFsRootfsConfig, ShareFsVolumeConfig, @@ -105,6 +108,51 @@ impl ShareFsMount for VirtiofsShareMount { let storages = vec![watchable_storage]; + return Ok(ShareFsMountResult { + guest_path, + storages, + }); + } else if config.mount.r#type == mount::KATA_EPHEMERAL_VOLUME_TYPE { + // refer to the golang `handleEphemeralStorage` code at + // https://github.com/kata-containers/kata-containers/blob/9516286f6dd5cfd6b138810e5d7c9e01cf6fc043/src/runtime/virtcontainers/kata_agent.go#L1354 + + let source = &config.mount.source; + let file_stat = + stat(Path::new(source)).with_context(|| format!("mount source {}", source))?; + + // if volume's gid isn't root group(default group), this means there's + // an specific fsGroup is set on this local volume, then it should pass + // to guest. + let dir_options = if file_stat.st_gid != 0 { + vec![format!("fsgid={}", file_stat.st_gid)] + } else { + vec![] + }; + + let file_name = Path::new(source) + .file_name() + .context("get file name from mount.source")?; + let source = Path::new(EPHEMERAL_PATH) + .join(file_name) + .into_os_string() + .into_string() + .map_err(|e| anyhow!("failed to get ephemeral path {:?}", e))?; + + // Create a storage struct so that kata agent is able to create + // tmpfs backed volume inside the VM + let ephemeral_storage = agent::Storage { + driver: String::from(mount::KATA_EPHEMERAL_VOLUME_TYPE), + driver_options: Vec::new(), + source: String::from("tmpfs"), + fs_type: String::from("tmpfs"), + fs_group: None, + options: dir_options, + mount_point: source.clone(), + }; + + guest_path = source; + let storages = vec![ephemeral_storage]; + return Ok(ShareFsMountResult { guest_path, storages, diff --git a/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs b/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs index d1a01d0306..c75ea5ca12 100644 --- a/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs +++ b/src/runtime-rs/crates/resource/src/volume/share_fs_volume.rs @@ -10,6 +10,7 @@ use anyhow::{anyhow, Context, Result}; use super::Volume; use crate::share_fs::{ShareFs, ShareFsVolumeConfig}; +use kata_types::mount; // copy file to container's rootfs if filesystem sharing is not supported, otherwise // bind mount it in the shared directory. @@ -66,6 +67,7 @@ impl ShareFsVolume { target: file_name, readonly: false, mount_options: m.options.clone(), + mount: m.clone(), }) .await .context("share fs volume")?; @@ -101,7 +103,8 @@ impl Volume for ShareFsVolume { } pub(crate) fn is_share_fs_volume(m: &oci::Mount) -> bool { - m.r#type == "bind" && !is_host_device(&m.destination) + (m.r#type == "bind" || m.r#type == mount::KATA_EPHEMERAL_VOLUME_TYPE) + && !is_host_device(&m.destination) } fn is_host_device(dest: &str) -> bool { diff --git a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs index 834c68b77c..74853aec60 100644 --- a/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs +++ b/src/runtime-rs/crates/runtimes/virt_container/src/container_manager/container.rs @@ -15,6 +15,7 @@ use common::{ ProcessType, }, }; +use kata_sys_util::k8s::update_ephemeral_storage_type; use oci::{LinuxResources, Process as OCIProcess}; use resource::ResourceManager; use tokio::sync::RwLock; @@ -110,6 +111,7 @@ impl Container { .context("handler volumes")?; let mut oci_mounts = vec![]; let mut storages = vec![]; + for v in volumes { let mut volume_mounts = v.get_volume_mount().context("get volume mount")?; if !volume_mounts.is_empty() { @@ -378,6 +380,9 @@ fn amend_spec(spec: &mut oci::Spec, disable_guest_seccomp: bool) -> Result<()> { // hook should be done on host spec.hooks = None; + // special process K8s ephemeral volumes. + update_ephemeral_storage_type(spec); + if let Some(linux) = spec.linux.as_mut() { if disable_guest_seccomp { linux.seccomp = None;