cgroup
cgroups 是Linux内核提供的一种可以限制单个进程或者多个进程所使用资源的机制,可以对 cpu,内存等资源实现精确的控制,Docker 就使用了 cgroups 提供的资源限制能力来完成cpu,内存等部分的资源控制。
cgroups 的全称是control groups,cgroups为每种可以控制的资源定义了一个子系统。典型的子系统介绍如下:
cpu 子系统,主要限制进程的 cpu 使用率。
cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
memory 子系统,可以限制进程的 memory 使用量。
blkio 子系统,可以限制进程的块设备 io。
devices 子系统,可以控制进程能够访问某些设备。
net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
net_prio 子系统, 限制任务中网络流量的优先级.
pids 子系统, 限制控制组中进程可以派生出的进程数量。
freezer 子系统,可以挂起或者恢复 cgroups 中的进程。 namespace。
cgroup和namespace类似,也是将进程进行分组,但它的目的和namespace不一样,namespace是为了隔离进程组之间的资源,而cgroup是为了对一组进程进行统一的资源监控和限制。
[root@gz cpu]# ls -l /sys/fs/cgroup/
total 0
dr-xr-xr-x 7 root root 0 Nov 9 15:30 blkio
lrwxrwxrwx 1 root root 11 Aug 2 16:16 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Aug 2 16:16 cpuacct -> cpu,cpuacct
dr-xr-xr-x 7 root root 0 Nov 9 15:30 cpu,cpuacct
dr-xr-xr-x 5 root root 0 Nov 9 14:39 cpuset
dr-xr-xr-x 7 root root 0 Nov 9 15:30 devices
dr-xr-xr-x 5 root root 0 Nov 9 14:39 freezer
dr-xr-xr-x 5 root root 0 Nov 9 14:39 hugetlb
dr-xr-xr-x 7 root root 0 Nov 9 15:30 memory
lrwxrwxrwx 1 root root 16 Aug 2 16:16 net_cls -> net_cls,net_prio
dr-xr-xr-x 5 root root 0 Nov 9 14:39 net_cls,net_prio
lrwxrwxrwx 1 root root 16 Aug 2 16:16 net_prio -> net_cls,net_prio
dr-xr-xr-x 5 root root 0 Nov 9 14:39 perf_event
dr-xr-xr-x 7 root root 0 Nov 9 15:30 pids
dr-xr-xr-x 5 root root 0 Nov 9 14:39 rdma
dr-xr-xr-x 7 root root 0 Nov 9 15:22 systemd
cgroups限制CPU
在/sys/fs/cgroup/cpu新建
[root@gz cpu]# mkdir /sys/fs/cgroup/cpu/stress_test
[root@gz cpu]# ls -l /sys/fs/cgroup/cpu/stress_test/
total 0
-rw-r--r-- 1 root root 0 Nov 9 17:06 cgroup.clone_children
-rw-r--r-- 1 root root 0 Nov 9 17:06 cgroup.procs
-r--r--r-- 1 root root 0 Nov 9 17:06 cpuacct.stat
-rw-r--r-- 1 root root 0 Nov 9 17:06 cpuacct.usage
-r--r--r-- 1 root root 0 Nov 9 17:06 cpuacct.usage_all
-r--r--r-- 1 root root 0 Nov 9 17:06 cpuacct.usage_percpu
-r--r--r-- 1 root root 0 Nov 9 17:06 cpuacct.usage_percpu_sys
-r--r--r-- 1 root root 0 Nov 9 17:06 cpuacct.usage_percpu_user
-r--r--r-- 1 root root 0 Nov 9 17:06 cpuacct.usage_sys
-r--r--r-- 1 root root 0 Nov 9 17:06 cpuacct.usage_user
-rw-r--r-- 1 root root 0 Nov 9 17:06 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Nov 9 17:06 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Nov 9 17:06 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Nov 9 17:06 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Nov 9 17:06 cpu.shares
-r--r--r-- 1 root root 0 Nov 9 17:06 cpu.stat
-rw-r--r-- 1 root root 0 Nov 9 17:06 notify_on_release
-rw-r--r-- 1 root root 0 Nov 9 17:06 tasks
开启压测,记录stress PID
[root@gz ~]# stress --cpu 1 --timeout 600
如果要限制CPU 使用5% ,cpu.cfs_quota_us 写入5000。
[root@gz stress_test]# echo 50000 > cpu.cfs_quota_us # 限制50%CPU
[root@gz stress_test]# echo 20397 > tasks # 限制PID,进程结束会自动清空
前后对比
cgroups限制内存
mkdir /sys/fs/cgroup/memory/stress_test
cgroup.procs: 使用该组配置的进程列表。
memory.limit_in_bytes:内存使用限制。
memory.memsw.limit_in_bytes:内存和交换分区总计限制。
memory.swappiness: 交换分区使用比例。
memory.usage_in_bytes: 当前进程内存使用量。
memory.stat: 内存使用统计信息。
memory.oom_control: OOM 控制参数。
假设有进程 pid 1234,希望设置内存限制为 10MB,我们可以这样操作: limit_in_bytes 设置为 10MB
echo "10*1024*1024" | bc > /sys/fs/cgroup/memory/stress_test/memory.limit_in_bytes
swappiness 设置为 0,表示禁用交换分区,实际生产中可以配置合适的比例。
echo 0 > /sys/fs/cgroup/memory/stress_test/memory.swappiness
添加控制进程pid,当进程 1234 使用内存超过 10MB 的时候,默认进程 1234 会触发 OOM,被系统 Kill 掉。
echo 1234 > /sys/fs/cgroup/memory/stress_test/cgroup.procs
systemd
systemctl set-property nginx.service CPUQuota=150% MemoryLimit=500M
systemctl set-property mysql.service BlockIOWeight=1000 # IO 权重
cat /sys/fs/cgroup/memory/system.slice/nginx.service/memory.limit_in_bytes
524288000
默认即时生效
cat /etc/systemd/system/nginx.service.d/50-CPUQuota.conf
[Service]
CPUQuota=150%
修改或删除
[root@gz ~]# rm -rf /etc/systemd/system/nginx.service.d/
[root@gz ~]# systemctl daemon-reload
[root@gz ~]# systemctl reload nginx
man systemd.resource-control