概念介绍
Qemu
Qemu 是一个模拟器,它向 Guest OS 模拟 CPU 和其他硬件,Guest OS 认为自己和硬件直接打交道,其实是同 Qemu 模拟出来的硬件打交道,Qemu 将这些指令转译给真正的硬件。
由于所有的指令都要从 Qemu 里面过一手,因而性能较差。
图 1:Qemu 架构图 |
---|
From:KVM-Qemu-Libvirt三者之间的关系 |
KVM
KVM 是 linux 内核的模块,它需要 CPU 的支持,采用硬件辅助虚拟化技术 Intel-VT,AMD-V,内存的相关如 Intel 的 EPT 和 AMD 的 RVI 技术,Guest OS 的 CPU 指令不用再经过 Qemu 转译,直接运行,大大提高了速度,KVM 通过 /dev/kvm 暴露接口,用户态程序可以通过 ioctl 函数来访问这个接口。见如下伪代码:
open("/dev/kvm")
ioctl(KVM_CREATE_VM)
ioctl(KVM_CREATE_VCPU)
for (;;) {
ioctl(KVM_RUN)
switch (exit_reason) {
case KVM_EXIT_IO:
case KVM_EXIT_HLT:
}
}
KVM 内核模块本身只能提供 CPU 和内存的虚拟化,所以它必须结合 QEMU 才能构成一个完成的虚拟化技术,这就是下面要说的 qemu-kvm。
qemu-kvm
Qemu 将 KVM 整合进来,通过 ioctl 调用 /dev/kvm 接口,将有关 CPU 指令的部分交由内核模块来做。kvm 负责 cpu 虚拟化+内存虚拟化,实现了cpu 和内存的虚拟化,但 kvm 不能模拟其他设备。qemu 模拟 IO 设备(网卡,磁盘等),kvm 加上 qemu 之后就能实现真正意义上服务器虚拟化。因为用到了上面两个东西,所以称之为 qemu-kvm。
Qemu 模拟其他的硬件,如 Network, Disk,同样会影响这些设备的性能,于是又产生了 pass through 半虚拟化设备 virtio_blk, virtio_net,提高设备性能。
图 2:Qemu-KVM 架构 |
---|
From:UCSB CS290B |
Libvirt
为什么需要Libvirt?
- Hypervisor 比如 qemu-kvm 的命令行虚拟机管理工具参数众多,难于使用。
- Hypervisor 种类众多,没有统一的编程接口来管理它们,这对云环境来说非常重要。
- 没有统一的方式来方便地定义虚拟机相关的各种可管理对象。
Libvirt提供了什么?
- 它提供统一、稳定、开放的源代码的应用程序接口(API)、守护进程 (libvirtd)和和一个默认命令行管理工具(virsh)。
- 它提供了对虚拟化客户机和它的虚拟化设备、网络和存储的管理。
- 它提供了一套较为稳定的 C 语言应用程序接口。目前,在其他一些流行的编程语言中也提供了对 libvirt 的绑定,在 Python、Perl、Java、Ruby、PHP、OCaml 等高级编程语言中已经有 libvirt 的程序库可以直接使用。
- 它对多种不同的 Hypervisor 的支持是通过一种基于驱动程序的架构来实现的。libvirt 对不同的 Hypervisor 提供了不同的驱动,包括 Xen 的驱动,对 QEMU/KVM 有 QEMU 驱动,VMware 驱动等。在 libvirt 源代码中,可以很容易找到 qemu_driver.c、xen_driver.c、xenapi_driver.c、vmware_driver.c、vbox_driver.c 这样的驱动程序源代码文件。
- 它作为中间适配层,让底层 Hypervisor 对上层用户空间的管理工具是可以做到完全透明的,因为 libvirt 屏蔽了底层各种 Hypervisor 的细节,为上层管理工具提供了一个统一的、较稳定的接口(API)。
- 它使用 XML 来定义各种虚拟机相关的受管理对象。
目前,libvirt 已经成为使用最为广泛的对各种虚拟机进行管理的工具和应用程序接口(API),而且一些常用的虚拟机管理工具(如virsh、virt-install、virt-manager等)和云计算框架平台(如OpenStack、OpenNebula、Eucalyptus等)都在底层使用libvirt的应用程序接口。
图 3:libvirt 与 KVM 的关系 |
---|
From: Libvirt Wiki |
实操
Arch Linux 下安装配置
[root@liqiang.io]# yay -Sy archlinux-keyring
[root@liqiang.io]# yay -Sy qemu virt-manager virt-viewer dnsmasq vde2 bridge-utils openbsd-netcat
[root@liqiang.io]# yay -Sy ebtables iptables
[root@liqiang.io]# yay -Sy libguestfs
[root@liqiang.io]# sudo systemctl enable libvirtd.service
[root@liqiang.io]# sudo systemctl start libvirtd.service
这样就安装好了所有需要的软件,下一步就是配置一下:
[root@liqiang.io]# cat /etc/libvirt/libvirtd.conf
... ...
unix_sock_group = "libvirt"
unix_sock_rw_perms = "0770"
[root@liqiang.io]# sudo usermod -a -G libvirt $(whoami)
[root@liqiang.io]# sudo systemctl restart libvirtd.service
virsh 操作
配置网络
[root@liqiang.io]# sudo virsh net-define /etc/libvirt/qemu/networks/default.xml
[root@liqiang.io]# sudo virsh net-start default
[root@liqiang.io]# sudo virsh net-autostart default # 开机自启动
[root@liqiang.io]#
配置控制台连接
[root@liqiang.io]# sudo systemctl enable serial-getty@ttyS0.service
[root@liqiang.io]# sudo systemctl start serial-getty@ttyS0.service
[root@liqiang.io]#
创建 VM
[root@liqiang.io]# sudo virt-install --name=testvm-00 \
--os-type=Linux \
--os-variant=centos7.0 \
--vcpu=4 \
--ram=4096 \
--disk path=/home/liuliqiang/data/kvm/images/testvm00.img,size=30 \
--graphics spice \
--location=/home/liuliqiang/data/kvm/isos/CentOS-7-x86_64-DVD-2009.iso \
--network bridge:virbr0
进入 VM
[root@liqiang.io]# virsh console zhangsan
关闭 VM
[root@liqiang.io]# virsh shutdown VM_NAME
[root@liqiang.io]# virsh shutdown --domain VM_NAME
[root@liqiang.io]# virsh destroy VM_NAME # force stop
[root@liqiang.io]# virsh destroy --domain VM_NAME # force stop
[root@liqiang.io]# virsh undefine --domain VM_NAME # remove vm
查看 VM 信息
[root@liqiang.io]# virsh list --all
Id Name State
----------------------------
1 200 running
2 envoy180 running
... ...
- base-f-vm shut off
[root@liqiang.io]#