Linux内核中的cgroups详解

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的控制器

控制器功能描述
cpuCPU限制限制CPU使用率
cpuacctCPU统计统计CPU使用情况
memory内存限制限制内存使用
blkio块设备IO限制块设备IO
cpusetCPU绑定绑定进程到特定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的应用也将更加广泛。

评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值