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

Stella981
• 阅读 1020

前言

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子命令绑定

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

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进行总结

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Eclipse插件开发_学习_00_资源帖
一、官方资料 1.eclipseapi(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fhelp.eclipse.org%2Fmars%2Findex.jsp%3Ftopic%3D%252Forg.eclipse.platform.doc.isv%252Fguide%2
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这