概述虚拟化作为云计算的基础,是目前一个重要的趋势。通过虚拟化可以提高 IT 资源和应用程序的效率和可用性。基于内核的虚拟机 KVM 在 2008 年被 RedHat 收购后,在 IBM 和 RedHat 的联合推动下得到了全面的发展。最新发布的 RHEL 版本中已经全面支持了 KVM 虚拟机,并集成了一整套基于 libvirt 的管理工具 (virsh/virt-top/virt-install/virt-manager 等 )。虚拟化领域的主要厂商 VMware 的 vSphere 虚拟环境提供的 vSphere Client 让用户可通过直观的图形化方式管理 vCenter/ESX server/datacenter/cluster/VM 等对象。但是当被管理对象数量庞大时,使用 virt-manager 或者 vSphere Client 的图形化方式来处理一些日常事务就显得费时费力了。为此用户可以通过相应的 API 来编写程序管理这些日常事务。本文将介绍 libvirt API 和 vSphere SDK for Perl 在系统管理方面的应用。本文将对于开发人员、系统管理员、系统测试人员有所帮助。
使用 libvirt 管理 KVM 环境 libvirt 是一套实现 Linux 虚拟化功能的开源 API,旨在提供一种单一的方式管理多种不同的虚拟化方案。目前 libvirt 支持如下的 hypervisor:
- KVM/QEMU
- Xen
- LXC
- OpenVZ
- VirtualBox
- VMware ESX, workstation, player
- Microsoft Hyper-V
伴随着 libvirt,RHEL 最新的发行版还包含了一系列基于 libvirt 的工具用于简化虚拟机的维护管理:
- virt-install: 用于创建虚拟机
- virsh: 交互式/批处理 shell,可以用于完成虚拟环境的日常管理工作
- virt-manager: 一个图形化的界面 , 用于 Hypervisor 及其虚拟机的管理
- virt-clone: 用于虚拟机克隆
- virt-viewer: 安全连接虚拟机的图形控制台工具
虽然 libvirt 本身由 C 开发 , 它提供了多种主流语言的绑定。系统管理员可以自由选择他们熟悉的语言,如 Python、Perl、Ruby、Java、PHP 等 .
使用 virsh 管理 KVM 虚拟机基于 libvirt 的管理工具中最常用的是 virsh。virsh 命令的格式如下:
1
| virsh [OPTION] COMMAND ARG
|
在不提供任何参数时,virsh 提供一个交互式 shell。管理员可以通过 virsh 编写一些简单的 shell 脚本完成虚拟机/网络/存储的配置。下面的代码片段显示了 virsh 命令的使用方法。
- 使用 ssh 协议连接到 KVM hypervisor:
1
2
| [root@BJGSSLA]# virsh connect qemu+ssh://9.9.9.9/system
root@9.9.9.9's password:
|
- 列举域 (guest VM):
1
2
3
4
5
6
| [root@BJGSSLA]# virsh list
Id Name State
--------------------------
32 rhkvm running
33 rhkvm01 running
34 xpkvm running
|
- 列举域的详细信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
| [root@BJGSSLA]# virsh dominfo rhkvm
Id: 32
Name: rhkvm
UUID: 9d37e044-b134-c923-bbe6-0db40707ff9b
OS Type: hvm
State: running
CPU(s): 1
CPU time: 92.6s
Max memory: 524288 kB
Used memory: 524288 kB
Persistent: yes
Autostart: disable
Managed save: yes
|
- 挂起,继续,重启域:
1
2
3
4
5
6
| [root@BJGSSLA]# virsh suspend rhkvm
Domain rhkvm suspended
[root@BJGSSLA]# virsh resume rhkvm
Doamin rhkvm resumed
[root@BJGSSLA]# virsh reboot rhkvm
Domain rhkvm is being rebooted
|
- 快照管理:
1
2
3
4
5
6
7
| [root@BJGSSLA]# virsh snapshot-create rhkvm
Domain snapshot 1336311489 created
[root@BJGSSLA]# virsh snapshot-list rhkvm
Name Create Time State
-----------------------------------------------------
1336311489 2012-05-06 09:38:09 -0400 running
[root@BJGSSLA]# virsh snapshot-revert rhkvm 1336311489
|
注:在 KVM 虚拟环境中物理宿主机被称为节点 (node),每个 guest 被称为域 (domain) 。
基于 libvirt API 编写 Perl 脚本 virsh 可以胜任大部分日常的工作,更复杂的需求可以通过 libvirt API 编程实现。本节将介绍基于如何使用 libvirt for Perl 来获得更加精细的虚拟机信息。
CPAN 上的 Sys::Virt 模块即为 libvirt 的 Perl 绑定。首先根据 KVM 环境中 libvirt 的版本下载、编译、安装对应的 Sys-Virt 模块。本文的实验环境中使用 0.9.4 版 libvirt, 因此使用 Sys-Virt-0.9.4:
1
| http://search.cpan.org/~danberr/Sys-Virt-0.9.4/
|
编译安装 Sys::Virt 模块:
1
2
3
| [root@BJGSSLA]# perl Makefile.PL
[root@BJGSSLA]# make
[root@BJGSSLA]# make install
|
下面将通过编写一个简单的监控程序来介绍 libvirt API 的使用。在生产环境中,管理员经常需要监视虚拟机的 CPU 使用率。如果发现某些虚拟机的 CPU 使用率异常,管理员可以提醒虚拟机的主人或者挂起某些虚拟机来保证整个虚拟化环境的正常运转。
基于 libvirt 开发的虚拟机性能监视工具 virt-top 的文档中提供了一个简化的实现算法:
- 对虚拟机的 cpuTime 进行周期性采样。此值可以通过 Sys::Virt:omain 类的 get_info 方法得到,以纳秒为单位,记录了开机到目前所经过的 CPU 时间
- 假定两次采样的实际时间是 t1 和 t2,虚拟机 CPU 运行时间为 vt1 和 vt2
- 此虚拟机的 CPU 使用率可以按下式计算:
1
| %CPU = 100% * (vt2 - vt1) / ((t2-v1) * #_of_cores * 10^9)
|
上述公式中的采样实际时间 (t1 和 t2) 可以通过 Perl 标准库模块 Time::HiRes 的 gettimeofday 方法获得。 #_of_cores 表示宿主机的 CPU 核数。此参数可以通过 Sys::Virt 类的 get_node_info 方法得到。
清单 1. vcpu_util.pl1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| #!/usr/bin/perl -w
# usage: vcpu_util --uri uri --dom DOM_Name
use strict;
use warnings;
use Time::HiRes;
use Getopt:ong;
use Sys::Virt;
my ($uri, $dom);
# 从命令行参数中获得 hypervisor 连接信息和虚拟机名
GetOptions('uri=s' => \$uri, 'dom=s' => \$dom);
# 获得 hypervisor 连接对象
my $conn = Sys::Virt->new(address => $uri) or die \
"Cannot connect to the hypervisor: $uri. $!\n";
# 获得虚拟机对象
my $vm = $conn->get_domain_by_name($dom) or die \
"Cannot find the domain: $dom. $!\n";
my ($start_time, $end_time, $start_vtime, $end_vtime);
# 获得第一次采样的实际时间
$start_time = Time::HiRes::gettimeofday();
# 获得第一次采样的虚拟机 CPU 时间
$start_vtime = $vm->get_info()->{'cpuTime'};
# 等待下一次采样
sleep(1);
# 获得第二次采样的实际时间
$end_time = Time::HiRes::gettimeofday();
# 获得第二次采样的虚拟机 CPU 时间
$end_vtime = $vm->get_info()->{'cpuTime'};
# 获得宿主 CPU 的核数
my $n_cores = $conn->get_node_info()->{'cores'};
# 计算虚拟机 CPU 的利用率
my $util_rate = 100 * ($end_vtime - $start_vtime) / (($end_time - \
$start_time) * 1000000000 * $n_cores);
printf "CPU utilization of $dom in $uri is: %.2f%%.\n", $util_rate;
|
下面是某次运行的结果:
1
2
| [root@BJGSSLA]# ./vcpu_util.pl --uri qemu:///system --dom rhkvm
CPU utilization of rhkvm in qemu:///system is: 4.46%
|
|