From 5998cde4bf2317b134c46cb087884f1dacfc3ff7 Mon Sep 17 00:00:00 2001 From: Nimrod Shneor Date: Sat, 29 May 2021 13:31:42 +0300 Subject: [PATCH] Add support for cgroups managed by systemd --- Cargo.lock | 98 +++++++++++++++++++++++++++++-- Cargo.toml | 1 + src/cgroups/common.rs | 15 ++++- src/cgroups/v2/mod.rs | 2 + src/cgroups/v2/systemd_manager.rs | 24 ++++++++ src/create.rs | 11 +++- src/main.rs | 13 ++-- 7 files changed, 151 insertions(+), 13 deletions(-) create mode 100644 src/cgroups/v2/systemd_manager.rs diff --git a/Cargo.lock b/Cargo.lock index 9eb862e43d..00ff1bda81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,6 +46,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "build-env" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1522ac6ee801a11bf9ef3f80403f4ede6eb41291fac3dde3de09989679305f25" + [[package]] name = "byteorder" version = "1.4.3" @@ -69,6 +75,12 @@ version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -126,7 +138,17 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "cstr-argument" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20bd4e8067c20c7c3a4dea759ef91d4b18418ddb5bd8837ef6e2f2f93ca7ccbb" +dependencies = [ + "cfg-if 0.1.10", + "memchr", ] [[package]] @@ -156,12 +178,39 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "crc32fast", "libc", "miniz_oxide", ] +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63f713f8b2aa9e24fec85b0e290c56caee12e3b6ae0aeeda238a75b28251afd6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7684cf33bb7f28497939e8c7cf17e3e4e3b8d9a0080ffa4f8ae2f515442ee855" + [[package]] name = "futures" version = "0.3.13" @@ -319,13 +368,24 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" +[[package]] +name = "libsystemd-sys" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e03fd580bcecda68dcdcd5297085ade6a3dc552cd8b030d2b94a9b089ef7ab8" +dependencies = [ + "build-env", + "libc", + "pkg-config", +] + [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -375,7 +435,7 @@ checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" dependencies = [ "bitflags", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", ] @@ -452,6 +512,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "prctl" version = "1.0.0" @@ -597,7 +663,7 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "winapi", ] @@ -619,6 +685,21 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "systemd" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f722cabda922e471742300045f56dbaa53fafbb4520fca304e51258019bfe91d" +dependencies = [ + "cstr-argument", + "foreign-types", + "libc", + "libsystemd-sys", + "log", + "memchr", + "utf8-cstr", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -686,6 +767,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +[[package]] +name = "utf8-cstr" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55bcbb425141152b10d5693095950b51c3745d019363fc2929ffd8f61449b628" + [[package]] name = "vec_map" version = "0.8.2" @@ -755,4 +842,5 @@ dependencies = [ "regex", "serde", "serde_json", + "systemd", ] diff --git a/Cargo.toml b/Cargo.toml index 4cbe34dfeb..cd93430ab8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,4 @@ once_cell = "1.6.0" futures = { version = "0.3", features = ["thread-pool"] } regex = "1.5" oci_spec = { version = "0.1.0", path = "./oci_spec" } +systemd = "0.8.2" \ No newline at end of file diff --git a/src/cgroups/common.rs b/src/cgroups/common.rs index 77ae5abe0a..efa4925b81 100644 --- a/src/cgroups/common.rs +++ b/src/cgroups/common.rs @@ -10,6 +10,7 @@ use anyhow::{bail, Result}; use nix::unistd::Pid; use oci_spec::LinuxResources; use procfs::process::Process; +use systemd::daemon::booted; use crate::cgroups::v1; use crate::cgroups::v2; @@ -50,7 +51,17 @@ pub fn write_cgroup_file>(path: P, data: &str) -> Result<()> { Ok(()) } -pub fn create_cgroup_manager>(cgroup_path: P) -> Result> { +pub fn create_cgroup_manager>( + cgroup_path: P, + systemd_cgroup: bool, +) -> Result> { + if systemd_cgroup { + if !booted()? { + bail!("systemd cgroup flag passed, but systemd support for managing cgroups is not available"); + } + log::info!("systemd cgroup manager will be used"); + return Ok(Box::new(v2::SystemDCGroupManager::new(cgroup_path.into())?)); + } let cgroup_mount = Process::myself()? .mountinfo()? .into_iter() @@ -84,7 +95,7 @@ pub fn create_cgroup_manager>(cgroup_path: P) -> Result Ok(Box::new(v1::manager::Manager::new(cgroup_path.into())?)), - } + } } _ => bail!("could not find cgroup filesystem"), } diff --git a/src/cgroups/v2/mod.rs b/src/cgroups/v2/mod.rs index df18307cd2..fe96f86daa 100644 --- a/src/cgroups/v2/mod.rs +++ b/src/cgroups/v2/mod.rs @@ -7,3 +7,5 @@ mod io; pub mod manager; mod memory; mod pids; +pub mod systemd_manager; +pub use systemd_manager::SystemDCGroupManager; diff --git a/src/cgroups/v2/systemd_manager.rs b/src/cgroups/v2/systemd_manager.rs new file mode 100644 index 0000000000..bde76fe401 --- /dev/null +++ b/src/cgroups/v2/systemd_manager.rs @@ -0,0 +1,24 @@ +use anyhow::Result; +use nix::unistd::Pid; +use oci_spec::LinuxResources; +use std::path::PathBuf; + +use crate::cgroups::common::CgroupManager; + +pub struct SystemDCGroupManager {} + +impl SystemDCGroupManager { + pub fn new(cgroup_path: PathBuf) -> Result { + Ok(SystemDCGroupManager {}) + } +} + +impl CgroupManager for SystemDCGroupManager { + fn apply(&self, linux_resources: &LinuxResources, pid: Pid) -> Result<()> { + Ok(()) + } + + fn remove(&self) -> Result<()> { + Ok(()) + } +} diff --git a/src/create.rs b/src/create.rs index 5cd967c52f..92ff1e756c 100644 --- a/src/create.rs +++ b/src/create.rs @@ -31,7 +31,12 @@ pub struct Create { } impl Create { - pub fn exec(&self, root_path: PathBuf, command: impl Command) -> Result<()> { + pub fn exec( + &self, + root_path: PathBuf, + systemd_cgroup: bool, + command: impl Command, + ) -> Result<()> { let bundle_canonicalized = fs::canonicalize(&self.bundle) .unwrap_or_else(|_| panic!("failed to canonicalied {:?}", &self.bundle)); let container_dir = root_path.join(&self.container_id); @@ -80,6 +85,7 @@ impl Create { rootfs, spec, csocketfd, + systemd_cgroup, container, command, )?; @@ -96,6 +102,7 @@ fn run_container>( rootfs: PathBuf, spec: oci_spec::Spec, csocketfd: Option, + systemd_cgroup: bool, container: Container, command: impl Command, ) -> Result { @@ -104,7 +111,7 @@ fn run_container>( let namespaces: Namespaces = linux.namespaces.clone().into(); let cgroups_path = utils::get_cgroup_path(&linux.cgroups_path, container.id()); - let cmanager = cgroups::common::create_cgroup_manager(&cgroups_path)?; + let cmanager = cgroups::common::create_cgroup_manager(&cgroups_path, systemd_cgroup)?; match fork::fork_first( pid_file, diff --git a/src/main.rs b/src/main.rs index dc058d261d..fad24e388e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,9 +15,8 @@ use youki::create; use youki::signal; use youki::start; -use youki::utils; use youki::cgroups; - +use youki::utils; /// High-level commandline option definition /// This takes global options as well as individual commands as specified in [OCI runtime-spec](https://github.com/opencontainers/runtime-spec/blob/master/runtime.md) @@ -32,6 +31,9 @@ struct Opts { log: Option, #[clap(long)] log_format: Option, + /// Enable systemd cgroup manager, rather then use the cgroupfs directly. + #[clap(short, long)] + systemd_cgroup: bool, /// command to actually manage container #[clap(subcommand)] subcmd: SubCommand, @@ -81,8 +83,10 @@ fn main() -> Result<()> { let root_path = PathBuf::from(&opts.root); fs::create_dir_all(&root_path)?; + let systemd_cgroup = opts.systemd_cgroup; + match opts.subcmd { - SubCommand::Create(create) => create.exec(root_path, LinuxCommand), + SubCommand::Create(create) => create.exec(root_path, systemd_cgroup, LinuxCommand), SubCommand::Start(start) => start.exec(root_path), SubCommand::Kill(kill) => { // resolves relative paths, symbolic links etc. and get complete path @@ -144,7 +148,8 @@ fn main() -> Result<()> { // remove the cgroup created for the container // check https://man7.org/linux/man-pages/man7/cgroups.7.html // creating and removing cgroups section for more information on cgroups - let cmanager = cgroups::common::create_cgroup_manager(cgroups_path)?; + let cmanager = + cgroups::common::create_cgroup_manager(cgroups_path, systemd_cgroup)?; cmanager.remove()?; } std::process::exit(0)