KVM虚拟机cpu资源限制和vcpu亲缘性绑定

前言

KVM中添加的实例存在资源分布不均的情况,这样如果有消耗资源的实例会影响到其他实例的服务正常运行,所以给kvm做资源限制是很有必要的,下面记录一下在centos7中KVM环境下使用cgroup限制vm实例资源的过程。

安装cgroup

[root@yufu ~]# yum install libcgroup libcgroup-devel libcgroup-tools-y

启动cgroup服务

[root@yufu ~]# systemctl start cgconfig

[root@yufu ~]# systemctl enable cgconfig

默认安装后目录文件并没有在/cgroup 目录下,而是在/sys/fs/cgoup 目录下。可以说使用find / -type d -name cgroup查找目录。

限制cpu资源

查看当前宿主机上有哪些实例并查看实例的进行号。
使用ps -ef 指令可以看到每个vm实例的进程号,一个示列在宿主机中就是一个进程。【通过进程名称查看进程号:pidof qemu-kvm

下面使用进程为 2106 的这个vm实例进测试:

进程号 2106 对应的实例是vm5,内存4G,cpu为2核心

在实例vm4中写一个消耗cpu的脚本测试,在宿主机中查看该进程消耗的cpu资源

#! /bin/bash

x=0
while [ True ];do
    x=$x+1
done;

宿主机执行 top -p 2106查看进程状态

Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.2 us,  0.0 sy,  0.0 ni, 95.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 98821584 total, 95922736 free,  2029444 used,   869412 buff/cache
KiB Swap:  8388604 total,  8388604 free,        0 used. 96262080 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                               
 2106 qemu      20   0 4549900 566812   9336 S 100.0  0.6  11:47.26 qemu-kvm  

可以看到cpu已经使用了100%

下面用cgroup控制这个进程的cpu资源

要对vm实例做资源限制,在cgroup目录下创建一个资源组vm5,然后在这个资源组中定义资源分配(可以一个vm定义一个资源组,容易管理,也可以给所有vm定义一个资源组)

  • 创建资源组
[root@yufu ~]# mkdir /sys/fs/cgroup/cpu/vm5

#资源组创建以后会有很多控制文件
[root@yufu ~]# ls /sys/fs/cgroup/cpu/vm5
cgroup.clone_children  cpuacct.stat          cpu.cfs_period_us  cpu.rt_runtime_us  notify_on_release
cgroup.event_control   cpuacct.usage         cpu.cfs_quota_us   cpu.shares         tasks
cgroup.procs           cpuacct.usage_percpu  cpu.rt_period_us   cpu.stat

查看当前进程

[root@yufu ~]# pidof qemu-kvm
2106 1642
  • 添加控制进程

将要限制的进程号加入到/sys/fs/cgroup/cpu/vm5/cgroup.procs

[root@yufu ~]# echo 2106 > /sys/fs/cgroup/cpu/vm5/cgroup.procs
  • 限制cpu资源使用

cpu.cfs_period_us和cpu.cfs_quota_us来限制该组中的所有进程在单位时间里可以使用的cpu时间。这里的cfs是完全公平调度器的缩写。cpu.cfs_period_us就是时间周期(微秒),默认为100000,即百毫秒。cpu.cfs_quota_us就是在这期间内可使用的cpu时间(微秒),默认-1,即无限制。

  • 查看默认值
[root@yufu ~]# cat  /sys/fs/cgroup/cpu/vm5/cpu.cfs_period_us 
100000
[root@yufu ~]# cat  /sys/fs/cgroup/cpu/vm5/cpu.cfs_quota_us 
-1
  • 对上面的两个值做调整
[root@yufu ~]# echo 80000 > /sys/fs/cgroup/cpu/vm5/cpu.cfs_period_us 
[root@yufu ~]# echo 40000 > /sys/fs/cgroup/cpu/vm5/cpu.cfs_quota_us
  • 再执行脚本测试
    在vm5上执行测试脚本,宿主机查看top
Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.1 us,  0.0 sy,  0.0 ni, 97.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 98821584 total, 95904496 free,  2047560 used,   869528 buff/cache
KiB Swap:  8388604 total,  8388604 free,        0 used. 96243984 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                               
 2106 qemu      20   0 4549900 567324   9336 S  50.0  0.6  12:02.15 qemu-kvm                                              

对比发现:长时间高负载下,限制了cpu资源的vm实例负载比没有做限制的实例负载要小。

同样,其他虚拟机实例按照上面同样的方式也可以对cpu资源进行限制

撤销资源限制

要撤销某个资源的限制,将该资源组中的tasks中的pid写到根 cgroup 的 tasks 文件即可,因为每个进程都属于且只属于一个 cgroup,加入到新的 cgroup 后,原有关系也就解除了。要删除一个 cgroup,可以用 rmdir 删除相应目录。不过在删除前,必须先让其中的进程全部退出,对应子系统的资源都已经释放,否则是无法删除的。

  • 撤销资源
[root@yufu vm5]# echo 2106 > /sys/fs/cgroup/cpu/tasks 
[root@yufu vm5]# echo 2111 > /sys/fs/cgroup/cpu/tasks 
[root@yufu vm5]# echo 2112 > /sys/fs/cgroup/cpu/tasks
  • 查看原来vm5实例中的pid已经被清空了
[root@yufu vm5]# cat tasks 

再执行脚本测试,cpu又是100%

Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.1 us,  0.0 sy,  0.0 ni, 95.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 98821584 total, 95905520 free,  2046364 used,   869704 buff/cache
KiB Swap:  8388604 total,  8388604 free,        0 used. 96245000 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                               
 2106 qemu      20   0 4549900 567324   9336 S 100.0  0.6  14:29.49 qemu-kvm 

KVM中虚拟机的cpu亲缘性绑定

默认情况下,kvm虚拟机实例并没有对vcpu做任何限制,当一个实例负载过高时,vcpu会在宿主机的cpu上来回切换,频繁的切换容易造成资源浪费,将vcpu与宿主机cpu对应绑定,能够有效提升cpu工作效率。

也可以将一个进程绑定在一个cpu上,使用taskset指令

cpu绑定方式

上面提到过,一个vm实例在宿主机中其实就是一个进程,绑定方式有两种:

taskset指令绑定进程cpu

使用taskset绑定是以vm实例上的所有vcpu为单位,与宿主机上的cpu进行绑定。比如:将vm4实例绑定在第4号cpu上,那么vm4实例中有4个vcpu,这4个vcpu都工作在了宿主机的第4号cpu上了。这种绑定方式粒度比较大

vcpupin子命令绑定

virsh vcpupin 子命令是KVM自带的指令工具,它可以把vm实例的每个vcpu与宿主机的cpu对应绑定,这种绑定方式粒度更小。

下面以vm4实例为例,查看其cpu运行情况和对其进程绑定

  • 查看vm4当前cpu绑定情况:
[root@yufu ~]# virsh vcpupin vm4
VCPU: CPU Affinity
----------------------------------
   0: 0-23      
   1: 0-23
 #默认2个vcpu没有进行绑定,可以在0-24号cpu上切换
  • 查看vcpu使用的时间
[root@yufu ~]# virsh vcpuinfo vm4
VCPU:           0
CPU:            10   #运行在10号cpu上
State:          running
CPU time:       14.2s
CPU Affinity:   yyyyyyyyyyyyyyyyyyyyyyyy

VCPU:           1
CPU:            8      #运行在8号cpu上
State:          running
CPU time:       6.8s
CPU Affinity:   yyyyyyyyyyyyyyyyyyyyyyyy

  • 将vm4的两个vcpu绑定在宿主机的第4号和第6号cpu上

cpu编号从0开始计数

[root@yufu ~]# virsh vcpupin vm4 0 3

[root@yufu ~]# virsh vcpupin vm4 1 5
  • 再看vcpu状态
[root@yufu ~]# virsh vcpuinfo vm4
VCPU:           0
CPU:            3
State:          running
CPU time:       14.5s
CPU Affinity:   ---y--------------------

VCPU:           1
CPU:            5
State:          running
CPU time:       7.3s
CPU Affinity:   -----y------------------

[root@yufu ~]# virsh vcpupin vm4
VCPU: CPU Affinity
----------------------------------
   0: 3
   1: 5

可以看到cpu已经绑定了,此时在vm4上做压力测试并在宿主机上看看cpu运行情况
上面使用指令绑定的方式只在当前系统环境有效,实例重启后就会失效,要永久生效需要在xml配置文件中定义

接着再把vm4的cpu使用资源做cgroup限制就就可以了:

  • 执行ps -ef获得vm4的pid为1636

  • 创建cgroup资源组vm4

[root@yufu ~]# mkdir /sys/fs/cgroup/cpu/vm4
  • 将vm4的pid写进cgroup.procs文件
[root@yufu ~]# cd /sys/fs/cgroup/cpu/vm4/

[root@yufu vm4]# echo 1636 > cgroup.procs
#当把进程pid加到 cgroup.procs后,系统会自动将该进程和进程下的线程加入到tasks文件中

[root@yufu vm4]# echo 80000 > cpu.cfs_period_us 
[root@yufu vm4]# echo 40000 > cpu.cfs_quota_us
  • 运行vm4消耗cpu脚本,查看宿主机进程状态和cpu

可以看到htop中,两个线程的cpu使用率一直在50%左右,且负载一直在第4个第6号cpu运行(这里就不上图了)

将cpu绑定信息写到xml配置文件

上面提到过,在命令行做的设置后,vm实例重启后,绑定信息就会失效,要想永久生效,需要将cpu的绑定信息写到该实例的xml配置文件中。

  • 在配置xml配置文件中添加绑定信息

停止vm4实例,编辑其xml文件

<domain type='kvm'>
  <name>vm4</name>
  <uuid>a140824a-800b-42bf-ae26-60e9ec6aa50f</uuid>
  <memory unit='KiB'>4097152</memory>
  <currentMemory unit='KiB'>4097152</currentMemory>
  <vcpu placement='static'>2</vcpu>
  #以下为添加内容
  <cputune>    
  <vcpupin vcpu='0' cpuset='3'/>
  <vcpupin vcpu='1' cpuset='5'/>
  </cputune>
  • 修改配置文件后要重载xml文件
[root@yufu qemu]# virsh define /etc/libvirt/qemu/vm4.xml 

再启动实例查看vcpu绑定信息

[root@yufu qemu]# virsh vcpuinfo vm4
VCPU:           0
CPU:            3
State:          running
CPU time:       14.2s
CPU Affinity:   ---y--------------------

VCPU:           1
CPU:            5
State:          running
CPU time:       4.3s
CPU Affinity:   -----y------------------

[root@yufu qemu]# virsh vcpupin vm4
VCPU: CPU Affinity
----------------------------------
   0: 3
   1: 5

关于kvm虚拟机的cpu优化和资源限制暂时记录到这里,后面有时间再对内存和io进行总结

posted on 2019-07-02 16:57  孤岛鱼夫  阅读(5573)  评论(0编辑  收藏  举报