Skip to content

fix:fix exec log grow to burst #423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion crates/runc-shim/src/runc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use containerd_shim::{
use log::{debug, error};
use nix::{sys::signal::kill, unistd::Pid};
use oci_spec::runtime::{LinuxResources, Process};
use runc::{Command, Runc, Spawner};
use runc::{Command, Runc, RuncGlobalArgs, Spawner};
use tokio::{
fs::{remove_file, File, OpenOptions},
io::{AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncWrite, BufReader},
Expand Down Expand Up @@ -455,7 +455,14 @@ impl ProcessLifecycle<ExecProcess> for RuncExecLifecycle {
async fn start(&self, p: &mut ExecProcess) -> containerd_shim::Result<()> {
let bundle = self.bundle.to_string();
let pid_path = Path::new(&bundle).join(format!("{}.pid", &p.id));
let log_path = Path::new(&bundle).join(format!("{}-exec.log", &p.id));
let custom_global_args = RuncGlobalArgs {
log: Some(log_path.clone()),
..Default::default()
};

let mut exec_opts = runc::options::ExecOpts {
custom_args: custom_global_args,
io: None,
pid_file: Some(pid_path.to_owned()),
console_socket: None,
Expand All @@ -475,6 +482,7 @@ impl ProcessLifecycle<ExecProcess> for RuncExecLifecycle {
.runtime
.exec(&self.container_id, &self.spec, Some(&exec_opts))
.await;
let _ = tokio::fs::remove_file(log_path).await;
if let Err(e) = exec_result {
if let Some(s) = socket {
s.clean().await;
Expand Down
8 changes: 6 additions & 2 deletions crates/runc/src/asynchronous/runc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::{
events,
options::*,
utils::{self, write_value_to_temp_file},
Command, Response, Result, Runc,
Command, Response, Result, Runc, RuncGlobalArgs,
};

// a macro tool to cleanup the file with name $filename,
Expand Down Expand Up @@ -138,11 +138,15 @@ impl Runc {
pub async fn exec(&self, id: &str, spec: &Process, opts: Option<&ExecOpts>) -> Result<()> {
let f = write_value_to_temp_file(spec).await?;
let mut args = vec!["exec".to_string(), "--process".to_string(), f.clone()];
let mut custom_global_args = RuncGlobalArgs {
..Default::default()
};
if let Some(opts) = opts {
args.append(&mut tc!(opts.args(), &f));
custom_global_args = opts.custom_args.clone();
}
args.push(id.to_string());
let mut cmd = self.command(&args)?;
let mut cmd = self.command_with_global_args(&args, custom_global_args)?;
match opts {
Some(ExecOpts { io: Some(io), .. }) => {
tc!(
Expand Down
86 changes: 84 additions & 2 deletions crates/runc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ pub mod utils;
const JSON: &str = "json";
const TEXT: &str = "text";

const DEBUG: &str = "--debug";
const LOG: &str = "--log";
const LOG_FORMAT: &str = "--log-format";
const ROOT: &str = "--root";
const ROOTLESS: &str = "--rootless";
const SYSTEMD_CGROUP: &str = "--systemd-cgroup";

pub type Result<T> = std::result::Result<T, crate::error::Error>;

/// Response is for (pid, exit status, outputs).
Expand Down Expand Up @@ -107,13 +114,88 @@ pub type Command = tokio::process::Command;
#[derive(Debug, Clone)]
pub struct Runc {
command: PathBuf,
args: Vec<String>,
global_args: RuncGlobalArgs,
spawner: Arc<dyn Spawner + Send + Sync>,
}

#[derive(Debug, Clone, Default)]
pub struct RuncGlobalArgs {
pub debug: Option<bool>,
pub log: Option<PathBuf>,
pub log_format: Option<String>,
pub root: Option<PathBuf>,
pub systemd_cgroup: Option<bool>,
pub rootless: Option<bool>,
}

impl Runc {
fn command(&self, args: &[String]) -> Result<Command> {
let args = [&self.args, args].concat();
let custom_global_args = RuncGlobalArgs {
debug: None,
log: None,
log_format: None,
root: None,
systemd_cgroup: None,
rootless: None,
};
self.command_with_global_args(args, custom_global_args)
}

fn command_with_global_args(
&self,
args: &[String],
custom_global_args: RuncGlobalArgs,
) -> Result<Command> {
let mut global_args_vec: Vec<String> = Vec::new();
if let Some(custom_debug) = custom_global_args.debug {
global_args_vec.push(DEBUG.to_string());
global_args_vec.push(custom_debug.to_string());
} else if let Some(debug) = self.global_args.debug {
global_args_vec.push(DEBUG.to_string());
global_args_vec.push(debug.to_string());
}

if let Some(custom_log) = custom_global_args.log {
global_args_vec.push(LOG.to_string());
global_args_vec.push(custom_log.to_string_lossy().to_string());
} else if let Some(log) = &self.global_args.log {
global_args_vec.push(LOG.to_string());
global_args_vec.push(log.to_string_lossy().to_string());
}

if let Some(custom_log_format) = custom_global_args.log_format {
global_args_vec.push(LOG_FORMAT.to_string());
global_args_vec.push(custom_log_format);
} else if let Some(log_format) = &self.global_args.log_format {
global_args_vec.push(LOG_FORMAT.to_string());
global_args_vec.push(log_format.to_string());
}

if let Some(custom_root) = custom_global_args.root {
global_args_vec.push(ROOT.to_string());
global_args_vec.push(custom_root.to_string_lossy().to_string());
} else if let Some(root) = &self.global_args.root {
global_args_vec.push(ROOT.to_string());
global_args_vec.push(root.to_string_lossy().to_string());
}

if let Some(systemd_cgroup) = custom_global_args.systemd_cgroup {
global_args_vec.push(SYSTEMD_CGROUP.to_string());
global_args_vec.push(systemd_cgroup.to_string());
} else if let Some(systemd_cgroup) = self.global_args.systemd_cgroup {
global_args_vec.push(SYSTEMD_CGROUP.to_string());
global_args_vec.push(systemd_cgroup.to_string());
}

if let Some(custom_rootless) = custom_global_args.rootless {
global_args_vec.push(ROOTLESS.to_string());
global_args_vec.push(custom_rootless.to_string());
} else if let Some(rootless) = self.global_args.rootless {
global_args_vec.push(ROOTLESS.to_string());
global_args_vec.push(rootless.to_string());
}

let args = [global_args_vec, args.to_vec()].concat();
let mut cmd = Command::new(&self.command);

// Default to piped stdio, and they may be override by command options.
Expand Down
91 changes: 45 additions & 46 deletions crates/runc/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,12 @@ use std::{
time::Duration,
};

use crate::{error::Error, utils, DefaultExecutor, Io, LogFormat, Runc, Spawner};
use crate::{error::Error, utils, DefaultExecutor, Io, LogFormat, Runc, RuncGlobalArgs, Spawner};

// constants for log format
pub const JSON: &str = "json";
pub const TEXT: &str = "text";

// constants for runc global flags
const DEBUG: &str = "--debug";
const LOG: &str = "--log";
const LOG_FORMAT: &str = "--log-format";
const ROOT: &str = "--root";
const ROOTLESS: &str = "--rootless";
const SYSTEMD_CGROUP: &str = "--systemd-cgroup";

// constants for runc-create/runc-exec flags
const CONSOLE_SOCKET: &str = "--console-socket";
const DETACH: &str = "--detach";
Expand All @@ -79,7 +71,7 @@ pub trait Args {
///
/// These options will be passed for all subsequent runc calls.
/// See <https://github.com/opencontainers/runc/blob/main/man/runc.8.md#global-options>
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
pub struct GlobalOpts {
/// Override the name of the runc binary. If [`None`], `runc` is used.
command: Option<PathBuf>,
Expand Down Expand Up @@ -203,64 +195,65 @@ impl GlobalOpts {
self.args()
}

fn output(&self) -> Result<(PathBuf, Vec<String>), Error> {
fn output(&self) -> Result<(PathBuf, RuncGlobalArgs), Error> {
let path = self
.command
.clone()
.unwrap_or_else(|| PathBuf::from("runc"));

let command = utils::binary_path(path).ok_or(Error::NotFound)?;

let mut args = Vec::new();

let mut global_args = RuncGlobalArgs {
debug: None,
log: None,
log_format: None,
root: None,
systemd_cgroup: None,
rootless: None,
};
// --root path : Set the root directory to store containers' state.
if let Some(root) = &self.root {
args.push(ROOT.into());
args.push(utils::abs_string(root)?);
global_args.root = Some(root.to_path_buf());
}

// --debug : Enable debug logging.
if self.debug {
args.push(DEBUG.into());
global_args.debug = Some(self.debug);
}

// --log path : Set the log destination to path. The default is to log to stderr.
if let Some(log_path) = &self.log {
args.push(LOG.into());
args.push(utils::abs_string(log_path)?);
global_args.log = Some(log_path.to_path_buf());
}

// --log-format text|json : Set the log format (default is text).
args.push(LOG_FORMAT.into());
args.push(self.log_format.to_string());
global_args.log_format = Some(self.log_format.to_string());

// --systemd-cgroup : Enable systemd cgroup support.
if self.systemd_cgroup {
args.push(SYSTEMD_CGROUP.into());
global_args.systemd_cgroup = Some(true);
}

// --rootless true|false|auto : Enable or disable rootless mode.
if let Some(mode) = self.rootless {
let arg = format!("{}={}", ROOTLESS, mode);
args.push(arg);
global_args.rootless = Some(mode);
}
Ok((command, args))
Ok((command, global_args))
}
}

impl Args for GlobalOpts {
type Output = Result<Runc, Error>;

fn args(&self) -> Self::Output {
let (command, args) = self.output()?;
let (command, global_args) = self.output()?;
let executor = if let Some(exec) = self.executor.clone() {
exec
} else {
Arc::new(DefaultExecutor {})
};
Ok(Runc {
command,
args,
global_args,
spawner: executor,
})
}
Expand Down Expand Up @@ -352,6 +345,7 @@ impl CreateOpts {
/// Container execution options
#[derive(Clone, Default)]
pub struct ExecOpts {
pub custom_args: RuncGlobalArgs,
pub io: Option<Arc<dyn Io>>,
/// Path to where a pid file should be created.
pub pid_file: Option<PathBuf>,
Expand Down Expand Up @@ -596,15 +590,11 @@ mod tests {
fn global_opts_test() {
let cfg = GlobalOpts::default().command("true");
let runc = cfg.build().unwrap();
let args = &runc.args;
assert_eq!(args.len(), 2);
assert!(args.contains(&LOG_FORMAT.to_string()));
assert!(args.contains(&TEXT.to_string()));

let cfg = GlobalOpts::default().command("/bin/true");
let runc = cfg.build().unwrap();
assert_eq!(runc.args.len(), 2);
let global_args = &runc.global_args;

if let Some(log_format) = &global_args.log_format {
assert!(TEXT == log_format);
}
let cfg = GlobalOpts::default()
.command("true")
.root("/tmp")
Expand All @@ -614,16 +604,25 @@ mod tests {
.systemd_cgroup(true)
.rootless(true);
let runc = cfg.build().unwrap();
let args = &runc.args;
assert!(args.contains(&ROOT.to_string()));
assert!(args.contains(&DEBUG.to_string()));
assert!(args.contains(&"/tmp".to_string()));
assert!(args.contains(&LOG.to_string()));
assert!(args.contains(&"/tmp/runc.log".to_string()));
assert!(args.contains(&LOG_FORMAT.to_string()));
assert!(args.contains(&JSON.to_string()));
assert!(args.contains(&"--rootless=true".to_string()));
assert!(args.contains(&SYSTEMD_CGROUP.to_string()));
assert_eq!(args.len(), 9);
let global_args = &runc.global_args;

if let Some(root) = &global_args.root {
assert!(root.to_string_lossy() == "/tmp");
}
if let Some(debug) = global_args.debug {
assert!(debug);
}
if let Some(log) = &global_args.log {
assert!(log.to_string_lossy() == "/tmp/runc.log");
}
if let Some(log_format) = &global_args.log_format {
assert!(log_format == "json");
}
if let Some(root_less) = global_args.rootless {
assert!(root_less);
}
if let Some(systemd_cgroup) = global_args.systemd_cgroup {
assert!(systemd_cgroup);
}
}
}
Loading