runtime-rs: support ephemeral storage for emptydir

Add support for ephemeral storage and k8s emptydir.

Depends-on:github.com/kata-containers/tests#5161

Fixes: #4730

Signed-off-by: Bin Liu <bin@hyper.sh>
This commit is contained in:
Bin Liu 2022-09-23 19:19:08 +08:00
parent 949ffcc457
commit 8d4ced3c86
6 changed files with 62 additions and 3 deletions

View File

@ -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);
}
}

View File

@ -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";

View File

@ -55,6 +55,7 @@ pub struct ShareFsVolumeConfig {
pub target: String,
pub readonly: bool,
pub mount_options: Vec<String>,
pub mount: oci::Mount,
}
pub struct ShareFsMountResult {

View File

@ -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,

View File

@ -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 {

View File

@ -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;