虚拟化管理软件libvirt
1. 相关命令
1、安装:
yum install libvirt libvirt-daemon-kvm qemu-kvm
rpm -q virt-manager # 查看是否安装virt-manager
yum install virt-manager
2、启动libvirtd服务
systemctl status libvirtd
systemctl start libvirtd # 设置立即启动,仅本次会话有效
systemctl enable libvirtd # 设置开启自启动
2. 概述
内核管理着三个重要的资源:计算、网络和存储。计算指CPU和内存,网络指网络设备,存储指硬盘等。
2.1 qemu,KVM,Virsh
qemu
,其中的emu实际上是emulator,模拟器。所以单纯使用qemu是采用的完全虚拟化的模式。qemu实际上是作为GuestOS和真正的CPU、硬件之间的“中间商”,所有的指令都要从qemu中间过一手。
kvm: Kernel-based Virtual Machine,基于内核的虚拟机。kvm是Linux内核的一部分,提供了对硬件虚拟化的支持。通过kvm,Linux内核可以作为一个虚拟机管理程序(hypervisor),允许在一台物理机器上运行多个隔离的虚拟机。
在kvm中创建虚拟机硬盘时,qcow2格式为动态分配,raw格式为固定大小。
由于完全虚拟化是非常慢的,因此使用硬件辅助虚拟化技术Intel-VT,AMD-V。使用后CPU将开启相应的标志位。此时通过kvm
,GuestOS的CPU指令不需要再经过qemu转译,可以直接运行。因此,kvm需要在物理机的内核中设置相应的模块,来设置当前CPU是GuestOS在用还是HostOS在用。
接着,qemu将kvm整合进来,通过ioctl调用/dev/kvm接口,将有关CPU指令的部分交由内核模块来做,即qemu-kvm(qemu-system-XXX)。这样CPU的性能问题就得到了解决。但是由于qemu还会模拟其他的硬件,如Network和Disk等,因此qemu采用半虚拟化或直通的方式,让GuestOS加载特殊的驱动来做这件事。
例如网络需要加载virtio_net,存储需要加载virtio_blk,GuestOS需要安装这些半虚拟化驱动,GuestOS知道自己是虚拟机,所以数据直接发送给半虚拟化设备,经过特殊处理,例如排队,缓存,批量处理等性能优化方式,最终发送给真正的硬件,一定程度上提高了性能。
直接用qemu或qemu-kvm的较少,大多数通过virsh
启动。virsh属于libvirt工具,分服务端和客户端。libvirtd是一个daemon进程,是服务端,可以被本地的virsh调用,也可以被远程的virsh调用,virsh相当于客户端。
整个关系如下:
总的来说,qemu、kvm和virsh的关系如下:
-
kvm是Linux内核的一部分,主要负责CPU和内存的虚拟化。
-
qemu是一个开源的硬件虚拟化软件,可以独立运行,也可以和kvm结合来帮助处理I/O虚拟化和设备虚拟化等任务。
-
virsh是基于libvirt的命令行工具,用于管理不同的虚拟化技术,包括kvm/qemu在内。
2.2 libvirt
libvirt是对KVM虚拟机进行管理的工具和应用程序接口,一些常用的虚拟机管理工具(如virsh、virt-install、virt-manager等)和云计算框架平台(如OpenStack、ZStack、OpenNebula、Eucalyptus等)都在底层使用libvirt的应用程序接口。
在libvirt中涉及几个重要概念:
-
Node
:物理机器,上面运行着多个虚拟客户机。 -
Hypervisor
:也称虚拟机监控器VMM,如kvm、VMware、Hyper-V等,是虚拟化中的一个底层软件层,它可以虚拟化一个节点让其运行多个虚拟客户机。 -
Domain
:Hypervisor上运行的一个客户机操作系统实例,域(Domain)和实例(Instance)、客户机操作系统(GuestOS)、虚拟机(Virtual Machine)均为同一个概念。
3. libvirt API使用
libvirt源码地址:https://gitlab.com/libvirt/libvirt.git
一个简单的示例:通过调用libvirt的API来查询一些关于某个域的信息。
/**
* Get domain information via libvirt C API.
* Tested with libvirt-devel-2.0.0 on a RHEL 7.3 host system.
*/
#include <libvirt/libvirt.h>
#include <stdio.h>
int getDomainInfo(int id) {
virConnectPtr conn = NULL; /* the hypervisor connection */
virDomainPtr dom = NULL; /* the domain being checked */
virDomainInfo info; /* the information being fetched */
/* NULL means connect to local QEMU/KVM hypervisor */
conn = virConnectOpenReadOnly(NULL);
if (conn == NULL) {
fprintf(stderr, "Failed to connect to hypervisor\n");
return 1;
}
/* Find the domain by its ID */
dom = virDomainLookupByID(conn, id);
if (dom == NULL) {
fprintf(stderr, "Failed to find Domain %d\n", id);
virConnectClose(conn);
return 1;
}
/* Get virDomainInfo structure of the domain */
if (virDomainGetInfo(dom, &info) < 0) {
fprintf(stderr, "Failed to get information for Domain %d\n", id);
virDomainFree(dom);
virConnectClose(conn);
return 1;
}
/* Print some info of the domain */
printf("Domain ID: %d\n", id);
printf(" vCPUs: %d\n", info.nrVirtCpu);
printf(" maxMem: %d KB\n", info.maxMem);
printf(" memory: %d KB\n", info.memory);
if (dom != NULL)
virDomainFree(dom);
if (conn != NULL)
virConnectClose(conn);
return 0;
}
int main(int argc, char **argv) {
int dom_id = 1;
printf("-----Get domain info by ID via libvirt C API -----\n");
getDomainInfo(dom_id);
return 0;
}
编译:
gcc libvirt-demo.c -o libvirt-demo -lvirt
运行:
$ sudo ./libvirt-demo
-----Get domain info by ID via libvirt C API -----
Domain ID: 1
vCPUs: 2
maxMem: 4194304 KB
memory: 4194304 KB