控制群组
控制群组(control group)(在此指南中简写为 cgroup)是 Linux kernel 的一项功能:在一个系统中运行的层级制进程组,您可对其进行资源分配(如 CPU 时间、系统内存、网络带宽或者这些资源的组合)。通过使用 cgroup,系统管理员在分配、排序、拒绝、管理和监控系统资源等方面,可以进行精细化控制。硬件资源可以在应用程序和用户间智能分配,从而增加整体效率。
控制群组可对进程进行层级式分组并标记,并对其可用资源进行限制。传统情况下,所有的进程分得的系统资源数量相近,管理员用进程 niceness 值进行调节。而用此方法,包含大量进程的应用程序可以比包含少量进程的应用程序获得更多资源,这与应用程序的重要程度无关。
资源管控器
资源管控器(也称为 cgroup 子系统)代表一种单一资源:如 CPU 时间或者内存。Linux kernel 提供一系列资源管控器,由 systemd 自动挂载。如需参考目前已挂载的资源管控器列表,请参见 /proc/cgroups,或使用 lssubsys 监控工具。
[root@localhost cpuset]# lssubsys
cpuset cpu,cpuacct memory devices freezer net_cls blkio perf_event hugetlb
或者
[root@localhost cpuset]# ls /sys/fs/cgroup/
blkio cpuacct cpuset freezer memory perf_event cpu cpu,cpuacct devices hugetlb net_cls systemd
• blkio —— 对输入 ∕ 输出访问存取块设备设定权限;
• cpu —— 使用 CPU 调度程序让 cgroup 的任务可以存取 CPU。它与 cpuacct 管控器一起挂载在同一 mount 上;
• cpuacct —— 自动生成 cgroup 中任务占用 CPU 资源的报告。它与 cpu 管控器一起挂载在同一 mount 上;
• cpuset —— 给 cgroup 中的任务分配独立 CPU(在多芯系统中)和内存节点;
• devices —— 允许或禁止 cgroup 中的任务存取设备;
• freezer —— 暂停或恢复 cgroup 中的任务;
• memory —— 对 cgroup 中的任务可用内存做出限制,并且自动生成任务占用内存资源报告;
• net_cls —— 使用等级识别符(classid)标记网络数据包,这让 Linux 流量控制器(tc 指令)可以识别来自特定 cgroup 任务的数据包;
• perf_event —— 允许使用 perf 工具来监控 cgroup;
• hugetlb —— 允许使用大篇幅的虚拟内存页,并且给这些内存页强制设定可用资源量。
[root@localhost ~]# yum install kernel-doc
[root@localhost ~]# ls /usr/share/doc/kernel-doc-3.10.0/Documentation/cgroups/
00-INDEX cpuacct.txt freezer-subsystem.txt memory.txt blkio-controller.txt cpusets.txt hugetlb.txt net_cls.txt cgroups.txt devices.txt memcg_test.txt net_prio.txt
1.建立一个CPU控制族群
首先进入cpu子系统对应的层级路径下:cd /sys/fs/cgroup/cpu
通过新建文件夹创建一个cpu控制族群:mkdir cg1,即新建了一个cpu控制族群:cg1
新建cg1之后,可以看到目录下自动建立了相关的文件,这些文件是伪文件。我们的测试示例主要用到cpu.cfs_period_us和cpu.cfs_quota_us两个文件。
cpu.cfs_period_us:cpu分配的周期(微秒),默认为100000。
cpu.cfs_quota_us:表示该control group限制占用的时间(微秒),默认为-1,表示不限制。如果设为50000,表示占用50000/10000=50%的CPU。
这里,我们设置占用30%的CPU,即把cpu.cfs_quota_us设置为30000。
[root@docker201.com /sys/fs/cgroup/cpuset]
$ echo 30000 > cpu.cfs_quota_us
2.编写测试程序
写了一个shell脚本,无限的循环计数。执行该脚本:
运行top命令查看:
可以看到cpu占用100%。
5、将该进程放到新建的control group中
其实就把该进程号4012写入到control group的tasks文件中再次查看top命令执行情况:
[root@docker201.com /sys/fs/cgroup/cpuset]
$ echo 4012 > tasks
[root@docker201.com ~]
$ top -d 0.1 -p 4012
可以看到cpu.sh程序占用的cpu控制在30%左右。
通过cgroup来限制KVM虚拟机使用的cpu和内存
启动cgconfig服务
[root@localhost ~]# service cgconfig start
在 /cgroup 目录下可以看到libvirt目录
[root@localhost ~]# ls /cgroup/cpuset/libvirt/qemu/
cgroup.event_control puset.memory_spread_page
cgroup.procs cpuset.memory_spread_slab
cpuset.cpu_exclusive cpuset.mems
cpuset.cpus cpuset.sched_load_balance
cpuset.mem_exclusive cpuset.sched_relax_domain_level
cpuset.mem_hardwall notify_on_release
cpuset.memory_migrate tasks
cpuset.memory_pressure
启动虚拟机
[root@localhost ~]# virsh start rhel6u4-6
Domain rhel6u4-6 started
现在可以看到虚拟机rhel6u4-6目录了
[root@localhost ~]# virsh list
Id Name State
----------------------------------------------------
1 rhel6u4-6 running
[root@localhost ~]# ls /cgroup/cpuset/libvirt/qemu/
cgroup.event_control cpuset.memory_spread_page
cgroup.procs cpuset.memory_spread_slab
cpuset.cpu_exclusive cpuset.mems
cpuset.cpus cpuset.sched_load_balance
cpuset.mem_exclusive cpuset.sched_relax_domain_level
cpuset.mem_hardwall notify_on_release
cpuset.memory_migrate rhel6u4-6
cpuset.memory_pressure tasks
[root@localhost ~]# ls /cgroup/cpuset/libvirt/qemu/rhel6u4-6/
cgroup.event_control cpuset.memory_spread_slab
cgroup.procs cpuset.mems
cpuset.cpu_exclusive cpuset.sched_load_balance
cpuset.cpus cpuset.sched_relax_domain_level
cpuset.mem_exclusive emulator
cpuset.mem_hardwall notify_on_release
cpuset.memory_migrate tasks
cpuset.memory_pressure vcpu0
cpuset.memory_spread_page vcpu1
查看虚拟机使用的cpu
[root@localhost ~]# watch -n 1 virsh vcpuinfo rhel6u4-6
VCPU: 0
CPU: 1
State: running
CPU time: 12.9s
CPU Affinity: yyyy
VCPU: 1
CPU: 0
State: running
CPU time: 7.0s
CPU Affinity: yyyy
限制虚拟机只能使用CPU0
[root@localhost ~]# cat /cgroup/cpuset/libvirt/qemu/rhel6u4-6/vcpu0/cpuset.cpus
0-3
[root@localhost ~]# cat /cgroup/cpuset/libvirt/qemu/rhel6u4-6/vcpu1/cpuset.cpus
0-3
[root@localhost ~]# echo 0 > /cgroup/cpuset/libvirt/qemu/rhel6u4-6/vcpu0/cpuset.cpus
[root@localhost ~]# echo 0 > /cgroup/cpuset/libvirt/qemu/rhel6u4-6/vcpu1/cpuset.cpus
[root@localhost ~]# watch -n 1 virsh vcpuinfo rhel6u4-6
Every 1.0s: virsh vcpuinfo rhel6u4-6 Wed Sep 4 21:16:27 2013
VCPU: 0
CPU: 0
State: running
CPU time: 13.4s
CPU Affinity: y---
VCPU: 1
CPU: 0
State: running
CPU time: 7.5s
CPU Affinity: y---
限制虚拟机使用的内存
[root@localhost ~]# cat /cgroup/memory/libvirt/qemu/rhel6u4-6/memory.limit_in_bytes
1935147008
[root@localhost ~]# cgset -r memory.limit_in_bytes=64M libvirt/qemu/rhel6u4-6
[root@localhost ~]# cat /cgroup/memory/libvirt/qemu/rhel6u4-6/memory.limit_in_bytes
67108864
如果虚拟机使用的内存大于限制值,kvm进程将会被内核杀掉
[root@localhost ~]# tail -f /var/log/messages
...
Sep 4 21:44:27 localhost kernel: Memory cgroup out of memory: Kill process 9705 (qemu-kvm) score 1000 or sacrifice child
Sep 4 21:44:27 localhost kernel: Killed process 9705, UID 107, (qemu-kvm) total-vm:1471536kB, anon-rss:32708kB, file-rss:4776kB
....
配置文件配置方法
[root@localhost Desktop]# vim /etc/cgconfig.conf
...
group libvirt/qemu/rhel6u4-6 { memory { memory.limit_in_bytes=512M ; } } group libvirt { cpuset { cpuset.cpus=0 ; } } group libvirt/qemu { cpuset { cpuset.cpus=0 ; } } group libvirt/qemu/rhel6u4-6 { cpuset { cpuset.cpus=0 ; } }
[root@localhost Desktop]# service cgconfig restart
Stopping cgconfig service: [ OK ]
Starting cgconfig service: [ OK ]
[root@localhost Desktop]# cat /cgroup/memory/libvirt/qemu/rhel6u4-6/memory.limit_in_bytes
536870912
[root@localhost Desktop]# cat /cgroup/cpuset/libvirt/qemu/rhel6u4-6/cpuset.cpus
0