前言
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進行總結