Linux内核中的cgroups详解
引言
cgroups(Control Groups)是Linux内核中的一项重要功能,它允许限制、记录和隔离进程组的资源使用(如CPU、内存、IO等)。cgroups为容器技术提供了资源管理的基础,是实现容器资源限制的核心机制。本文将深入探讨Linux内核中的cgroups机制,包括其原理、使用方法和应用。
cgroups的基本概念
1. cgroups的定义
cgroups是一种内核机制,用于限制、记录和隔离进程组的资源使用。
2. cgroups的优势
- 资源限制:限制进程组的资源使用
- 资源监控:监控进程组的资源使用情况
- 资源隔离:隔离不同进程组的资源
- 优先级管理:为不同进程组分配不同的资源优先级
3. cgroups的版本
- cgroups v1:早期版本,功能有限
- cgroups v2:新版本,提供更统一的接口
cgroups的架构
1. cgroups的层次结构
cgroup根目录
├── system.slice
│ ├── sshd.service
│ └── nginx.service
├── user.slice
│ └── user-1000.slice
└── machine.slice
└── docker-12345.scope
2. cgroups的控制器
| 控制器 | 功能 | 描述 |
|---|---|---|
| cpu | CPU限制 | 限制CPU使用率 |
| cpuacct | CPU统计 | 统计CPU使用情况 |
| memory | 内存限制 | 限制内存使用 |
| blkio | 块设备IO | 限制块设备IO |
| cpuset | CPU绑定 | 绑定进程到特定CPU |
| freezer | 进程冻结 | 冻结/解冻进程 |
| devices | 设备访问 | 控制设备访问权限 |
| net_cls | 网络分类 | 网络流量分类 |
| net_prio | 网络优先级 | 网络流量优先级 |
| hugetlb | 大页内存 | 限制大页内存使用 |
| pids | 进程数限制 | 限制进程数量 |
3. cgroups的挂载
# cgroups v1挂载点
/sys/fs/cgroup/cpu/
/sys/fs/cgroup/memory/
/sys/fs/cgroup/blkio/
# cgroups v2挂载点
/sys/fs/cgroup/
cgroups v1的使用
1. 创建cgroup
# 创建cgroup
mkdir /sys/fs/cgroup/cpu/mygroup
# 设置CPU限制
echo 50000 > /sys/fs/cgroup/cpu/mygroup/cpu.cfs_quota_us # 50% CPU
echo 100000 > /sys/fs/cgroup/cpu/mygroup/cpu.cfs_period_us # 100ms周期
# 设置内存限制
echo 512M > /sys/fs/cgroup/memory/mygroup/memory.limit_in_bytes
echo 256M > /sys/fs/cgroup/memory/mygroup/memory.soft_limit_in_bytes
# 设置IO限制
echo "8:0 wbps=10485760" > /sys/fs/cgroup/blkio/mygroup/blkio.throttle.write_bps_device
# 添加进程
echo <pid> > /sys/fs/cgroup/cpu/mygroup/tasks
2. 查看cgroup信息
# 查看CPU使用情况
cat /sys/fs/cgroup/cpu/mygroup/cpu.stat
# 查看内存使用情况
cat /sys/fs/cgroup/memory/mygroup/memory.stat
# 查看IO使用情况
cat /sys/fs/cgroup/blkio/mygroup/blkio.throttle.io_serviced
3. 删除cgroup
# 删除cgroup
rmdir /sys/fs/cgroup/cpu/mygroup
cgroups v2的使用
1. 挂载cgroups v2
# 检查cgroups v2
mount | grep cgroup2
# 挂载cgroups v2
mount -t cgroup2 none /sys/fs/cgroup
2. 创建cgroup
# 创建cgroup
mkdir /sys/fs/cgroup/mygroup
# 设置CPU限制
echo "max 50000 100000" > /sys/fs/cgroup/mygroup/cpu.max # 50% CPU
# 设置内存限制
echo "max 512M" > /sys/fs/cgroup/mygroup/memory.max
echo "low 256M" > /sys/fs/cgroup/mygroup/memory.low
# 设置IO限制
echo "8:0 rbps=max wbps=10485760" > /sys/fs/cgroup/mygroup/io.max
# 添加进程
echo <pid> > /sys/fs/cgroup/mygroup/cgroup.procs
3. 查看cgroup信息
# 查看cgroup信息
cat /sys/fs/cgroup/mygroup/cpu.stat
cat /sys/fs/cgroup/mygroup/memory.stat
cat /sys/fs/cgroup/mygroup/io.stat
cgroups的API
1. libcgroup库
#include <libcgroup.h>
int main() {
struct cgroup *cgroup;
struct cgroup_controller *cgc;
int ret;
// 初始化libcgroup
cgroup_init();
// 创建cgroup
cgroup = cgroup_new_cgroup("mygroup");
if (!cgroup) {
fprintf(stderr, "Failed to create cgroup\n");
return 1;
}
// 添加CPU控制器
cgc = cgroup_add_controller(cgroup, "cpu");
cgroup_controller_set_uint64(cgc, "cpu.cfs_quota_us", 50000);
cgroup_controller_set_uint64(cgc, "cpu.cfs_period_us", 100000);
// 添加内存控制器
cgc = cgroup_add_controller(cgroup, "memory");
cgroup_controller_set_uint64(cgc, "memory.limit_in_bytes", 512 * 1024 * 1024);
// 创建cgroup
ret = cgroup_create_cgroup(cgroup, 0);
if (ret) {
fprintf(stderr, "Failed to create cgroup\n");
cgroup_free(cgroup);
return 1;
}
// 添加进程
ret = cgroup_add_task(cgroup, getpid());
if (ret) {
fprintf(stderr, "Failed to add task\n");
cgroup_free(cgroup);
return 1;
}
// 清理
cgroup_free(cgroup);
return 0;
}
2. 系统调用
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
// 创建cgroup目录
mkdir("/sys/fs/cgroup/cpu/mygroup", 0755);
// 设置CPU限制
int fd = open("/sys/fs/cgroup/cpu/mygroup/cpu.cfs_quota_us", O_WRONLY);
write(fd, "50000", 5);
close(fd);
fd = open("/sys/fs/cgroup/cpu/mygroup/cpu.cfs_period_us", O_WRONLY);
write(fd, "100000", 6);
close(fd);
// 添加进程
fd = open("/sys/fs/cgroup/cpu/mygroup/tasks", O_WRONLY);
char pid[10];
sprintf(pid, "%d", getpid());
write(fd, pid, strlen(pid));
close(fd);
return 0;
}
cgroups的应用场景
1. 容器资源限制
Docker、Kubernetes等容器平台使用cgroups限制容器资源。
# Docker资源限制
docker run --cpus=0.5 --memory=512m nginx
# Kubernetes资源限制
cat > pod.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: "0.5"
memory: "512Mi"
requests:
cpu: "0.2"
memory: "256Mi"
EOF
2. 进程资源控制
限制单个进程或进程组的资源使用。
# 限制进程CPU使用
taskset -c 0-1 nice -n 19 ./myprogram
# 使用cgroups限制
mkdir /sys/fs/cgroup/cpu/myprogram
echo 50000 > /sys/fs/cgroup/cpu/myprogram/cpu.cfs_quota_us
echo 100000 > /sys/fs/cgroup/cpu/myprogram/cpu.cfs_period_us
echo $$ > /sys/fs/cgroup/cpu/myprogram/tasks
3. 系统服务管理
systemd使用cgroups管理系统服务。
# 查看服务的cgroup
systemctl status nginx
# 设置服务的资源限制
cat > /etc/systemd/system/nginx.service.d/limits.conf << 'EOF'
[Service]
CPUQuota=50%
MemoryLimit=512M
EOF
systemctl daemon-reload
systemctl restart nginx
cgroups的性能影响
1. 性能考虑
- 创建开销:cgroup的创建开销很小
- 运行时开销:几乎没有运行时开销
- 资源监控:会有一定的开销
2. 优化策略
- 合理设置限制:避免过度限制
- 使用cgroups v2:新系统推荐使用v2
- 避免嵌套过深:减少cgroup层次
3. 性能测试
# 测试cgroup创建时间
time mkdir /sys/fs/cgroup/cpu/test && rmdir /sys/fs/cgroup/cpu/test
# 测试资源限制性能
time cgexec -g cpu:test ./benchmark
实际案例分析
1. 限制应用程序资源
#!/bin/bash
# 创建cgroup
mkdir -p /sys/fs/cgroup/{cpu,memory}/myapp
# 设置CPU限制
echo 25000 > /sys/fs/cgroup/cpu/myapp/cpu.cfs_quota_us # 25% CPU
echo 100000 > /sys/fs/cgroup/cpu/myapp/cpu.cfs_period_us
# 设置内存限制
echo 256M > /sys/fs/cgroup/memory/myapp/memory.limit_in_bytes
# 启动应用
./myapp &
APP_PID=$!
# 添加到cgroup
echo $APP_PID > /sys/fs/cgroup/cpu/myapp/tasks
echo $APP_PID > /sys/fs/cgroup/memory/myapp/tasks
# 监控资源使用
while true; do
echo "CPU usage: $(cat /sys/fs/cgroup/cpu/myapp/cpuacct.usage_percpu)"
echo "Memory usage: $(cat /sys/fs/cgroup/memory/myapp/memory.usage_in_bytes)"
sleep 1
done
2. Docker资源限制
# 运行容器并限制资源
docker run --name limited-container \
--cpus=1.5 \
--memory=512m \
--blkio-weight=500 \
--restart unless-stopped \
nginx
# 查看容器的cgroup
docker inspect --format '{{ .Id }}' limited-container
ls -l /sys/fs/cgroup/cpu/docker/<container-id>
3. Kubernetes资源管理
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
resources:
limits:
cpu: "1"
memory: "256Mi"
requests:
cpu: "0.5"
memory: "128Mi"
结论
cgroups是Linux内核中实现资源管理的重要机制,它为容器技术提供了基础支持。通过cgroups,我们可以限制、监控和隔离进程组的资源使用,提高系统的可靠性和安全性。理解cgroups的原理和使用方法,对于系统管理、容器开发和性能优化都有重要意义。随着容器技术的不断发展,cgroups的应用也将更加广泛。

6163

被折叠的 条评论
为什么被折叠?



