cgroups的cpu配置
parent
6f30093001
commit
6c3f98ad98
@ -1,110 +0,0 @@
|
|||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use nix::sys::signal::kill;
|
|
||||||
use nix::unistd::Pid;
|
|
||||||
use nix::sys::signal::Signal;
|
|
||||||
use std::path::Path;
|
|
||||||
use crate::{create_dir, get_container_info, ContainerInfo};
|
|
||||||
use crate::error::Result;
|
|
||||||
|
|
||||||
static CGROUP_PATH: &str = "/sys/fs/cgroup/rocker";
|
|
||||||
|
|
||||||
pub enum CgroupLevel {
|
|
||||||
V1,
|
|
||||||
V2,
|
|
||||||
V3,
|
|
||||||
V4,
|
|
||||||
V5,
|
|
||||||
V6,
|
|
||||||
V7,
|
|
||||||
V8,
|
|
||||||
V9,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for CgroupLevel {
|
|
||||||
fn from(value: &str) -> Self {
|
|
||||||
match value {
|
|
||||||
"v1" => CgroupLevel::V1,
|
|
||||||
"v2" => CgroupLevel::V2,
|
|
||||||
"v3" => CgroupLevel::V3,
|
|
||||||
"v4" => CgroupLevel::V4,
|
|
||||||
"v5" => CgroupLevel::V5,
|
|
||||||
"v6" => CgroupLevel::V6,
|
|
||||||
"v7" => CgroupLevel::V7,
|
|
||||||
"v8" => CgroupLevel::V8,
|
|
||||||
"v9" => CgroupLevel::V9,
|
|
||||||
_ => todo!("invalid cgroup level"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for CgroupLevel {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::V1 => write!(f, "v1"),
|
|
||||||
Self::V2 => write!(f, "v2"),
|
|
||||||
Self::V3 => write!(f, "v3"),
|
|
||||||
Self::V4 => write!(f, "v4"),
|
|
||||||
Self::V5 => write!(f, "v5"),
|
|
||||||
Self::V6 => write!(f, "v6"),
|
|
||||||
Self::V7 => write!(f, "v7"),
|
|
||||||
Self::V8 => write!(f, "v8"),
|
|
||||||
Self::V9 => write!(f, "v9"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CgroupLevel {
|
|
||||||
fn default() -> Self {
|
|
||||||
CgroupLevel::V1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Cgroup {
|
|
||||||
pub procs: Vec<i32>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&ContainerInfo> for Cgroup {
|
|
||||||
fn from(container_inro: &ContainerInfo) -> Self {
|
|
||||||
// let container_inro = get_container_info(container_id).unwrap();
|
|
||||||
let l = CgroupLevel::from(container_inro.cgroup_level.as_str());
|
|
||||||
let cgroup_path = format!("{CGROUP_PATH}_{l}/{}", container_inro.id);
|
|
||||||
let mut v = vec![];
|
|
||||||
for pid in std::fs::read_to_string(format!("{cgroup_path}/cgroup.procs")).unwrap_or_default().lines() {
|
|
||||||
let pid = pid.parse::<i32>().unwrap();
|
|
||||||
v.push(pid);
|
|
||||||
}
|
|
||||||
Self {
|
|
||||||
procs: v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Cgroup {
|
|
||||||
pub fn create(container_id: &str, pid: i32, l: CgroupLevel) -> Result<()> {
|
|
||||||
let cgroup_path = format!("{CGROUP_PATH}_{l}/{container_id}");
|
|
||||||
create_dir(&cgroup_path, false)?;
|
|
||||||
// 打开 cgroup.procs, 写入pid
|
|
||||||
std::fs::write(format!("{cgroup_path}/cgroup.procs"), pid.to_string())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove(container_id: &str) {
|
|
||||||
let container_inro = get_container_info(container_id).unwrap();
|
|
||||||
let _self = Self::from(&container_inro);
|
|
||||||
for pid in _self.procs {
|
|
||||||
let _ = kill(Pid::from_raw(pid), Signal::SIGKILL);
|
|
||||||
let pid_path = Path::new("/proc").join(pid.to_string());
|
|
||||||
(0..100).any(|i|{
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(i));
|
|
||||||
pid_path.exists() == false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
let l = container_inro.cgroup_level;
|
|
||||||
let container_group_path = format!("{CGROUP_PATH}_{l}/{container_id}");
|
|
||||||
let _ = std::fs::remove_dir(&container_group_path);
|
|
||||||
println!("删除cgroup {container_group_path}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,150 @@
|
|||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use nix::sys::signal::kill;
|
||||||
|
use nix::unistd::Pid;
|
||||||
|
use nix::sys::signal::Signal;
|
||||||
|
use serde::de::value;
|
||||||
|
use std::path::Path;
|
||||||
|
use crate::{create_dir, get_container_info, ContainerInfo};
|
||||||
|
use crate::error::Result;
|
||||||
|
|
||||||
|
static CGROUP_PATH: &str = "/sys/fs/cgroup/rocker";
|
||||||
|
|
||||||
|
pub enum CgroupLevel {
|
||||||
|
V1,
|
||||||
|
V2,
|
||||||
|
V3,
|
||||||
|
V4,
|
||||||
|
V5,
|
||||||
|
V6,
|
||||||
|
V7,
|
||||||
|
V8,
|
||||||
|
V9,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for CgroupLevel {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
match value {
|
||||||
|
"v1" => CgroupLevel::V1,
|
||||||
|
"v2" => CgroupLevel::V2,
|
||||||
|
"v3" => CgroupLevel::V3,
|
||||||
|
"v4" => CgroupLevel::V4,
|
||||||
|
"v5" => CgroupLevel::V5,
|
||||||
|
"v6" => CgroupLevel::V6,
|
||||||
|
"v7" => CgroupLevel::V7,
|
||||||
|
"v8" => CgroupLevel::V8,
|
||||||
|
"v9" => CgroupLevel::V9,
|
||||||
|
_ => todo!("invalid cgroup level"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CgroupLevel {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::V1 => write!(f, "v1"),
|
||||||
|
Self::V2 => write!(f, "v2"),
|
||||||
|
Self::V3 => write!(f, "v3"),
|
||||||
|
Self::V4 => write!(f, "v4"),
|
||||||
|
Self::V5 => write!(f, "v5"),
|
||||||
|
Self::V6 => write!(f, "v6"),
|
||||||
|
Self::V7 => write!(f, "v7"),
|
||||||
|
Self::V8 => write!(f, "v8"),
|
||||||
|
Self::V9 => write!(f, "v9"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for CgroupLevel {
|
||||||
|
fn default() -> Self {
|
||||||
|
CgroupLevel::V1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Cgroup {
|
||||||
|
pub procs: Vec<i32>,
|
||||||
|
pub populated: i32
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Cgroup {
|
||||||
|
fn from(container_id: &str) -> Self {
|
||||||
|
let cgroup_path = format!("{CGROUP_PATH}/{}", container_id);
|
||||||
|
let procs = std::fs::read_to_string(format!("{cgroup_path}/cgroup.procs"))
|
||||||
|
.unwrap_or_default()
|
||||||
|
.lines()
|
||||||
|
.filter_map(|pid|pid.parse::<i32>().ok())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// 找到 cgroup.events 第一行的值
|
||||||
|
let populated = std::fs::read_to_string(format!("{cgroup_path}/cgroup.events"))
|
||||||
|
.unwrap_or_default()
|
||||||
|
.lines()
|
||||||
|
.next()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.split(" ")
|
||||||
|
.nth(1)
|
||||||
|
.unwrap_or("0")
|
||||||
|
.parse::<i32>()
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
procs,
|
||||||
|
populated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cgroup {
|
||||||
|
pub fn create(container_id: &str, pid: i32, cgroup_s: &str) -> Result<()> {
|
||||||
|
let cgroup_path = format!("{CGROUP_PATH}/{container_id}");
|
||||||
|
create_dir(&cgroup_path, false)?;
|
||||||
|
|
||||||
|
// 根据 cgroup_s 写入指定参数
|
||||||
|
let _ = cgroup_s.split(" ")
|
||||||
|
.map(|s|s.split("="))
|
||||||
|
.map(|mut x|(x.next(), x.next()))
|
||||||
|
.filter_map(|(dev, value)| {
|
||||||
|
if let (Some(dev), Ok(value)) = (dev, value.unwrap_or("").parse::<i32>()) {
|
||||||
|
Some((dev, value))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).for_each(|(dev, value)| {
|
||||||
|
match (dev, value) {
|
||||||
|
("cpu", 1..=100) => {
|
||||||
|
if let Ok(_) = std::fs::write(format!("{cgroup_path}/cpu.max"), format!("{} 100000", 100000 / 100 * value)) {
|
||||||
|
println!("cpu 限制 {value}% 成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
("memory", 1..=4096) => {
|
||||||
|
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("🔴 没有定义的 cgroup 参数: {dev}={value}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加入控制组
|
||||||
|
std::fs::write(format!("{cgroup_path}/cgroup.procs"), pid.to_string())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(container_id: &str) {
|
||||||
|
let _self = Self::from(container_id);
|
||||||
|
for pid in _self.procs {
|
||||||
|
let _ = kill(Pid::from_raw(pid), Signal::SIGKILL);
|
||||||
|
let pid_path = Path::new("/proc").join(pid.to_string());
|
||||||
|
(0..100).any(|i|{
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(i));
|
||||||
|
pid_path.exists() == false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let cgroup_path = format!("{CGROUP_PATH}/{container_id}");
|
||||||
|
let _ = std::fs::remove_dir(&cgroup_path);
|
||||||
|
println!("删除cgroup {cgroup_path}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue