概念介绍

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 函数来访问这个接口。见如下伪代码:

  1. open("/dev/kvm")
  2. ioctl(KVM_CREATE_VM)
  3. ioctl(KVM_CREATE_VCPU)
  4. for (;;) {
  5. ioctl(KVM_RUN)
  6. switch (exit_reason) {
  7. case KVM_EXIT_IO:
  8. case KVM_EXIT_HLT:
  9. }
  10. }

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?

Libvirt提供了什么?

目前,libvirt 已经成为使用最为广泛的对各种虚拟机进行管理的工具和应用程序接口(API),而且一些常用的虚拟机管理工具(如virsh、virt-install、virt-manager等)和云计算框架平台(如OpenStack、OpenNebula、Eucalyptus等)都在底层使用libvirt的应用程序接口。

图 3:libvirt 与 KVM 的关系
From: Libvirt Wiki

实操

Arch Linux 下安装配置

  1. [root@liqiang.io]# yay -Sy archlinux-keyring
  2. [root@liqiang.io]# yay -Sy qemu virt-manager virt-viewer dnsmasq vde2 bridge-utils openbsd-netcat
  3. [root@liqiang.io]# yay -Sy ebtables iptables
  4. [root@liqiang.io]# yay -Sy libguestfs
  5. [root@liqiang.io]# sudo systemctl enable libvirtd.service
  6. [root@liqiang.io]# sudo systemctl start libvirtd.service

这样就安装好了所有需要的软件,下一步就是配置一下:

  1. [root@liqiang.io]# cat /etc/libvirt/libvirtd.conf
  2. ... ...
  3. unix_sock_group = "libvirt"
  4. unix_sock_rw_perms = "0770"
  5. [root@liqiang.io]# sudo usermod -a -G libvirt $(whoami)
  6. [root@liqiang.io]# sudo systemctl restart libvirtd.service

virsh 操作

配置网络

  1. [root@liqiang.io]# sudo virsh net-define /etc/libvirt/qemu/networks/default.xml
  2. [root@liqiang.io]# sudo virsh net-start default
  3. [root@liqiang.io]# sudo virsh net-autostart default # 开机自启动
  4. [root@liqiang.io]#

配置控制台连接

  1. [root@liqiang.io]# sudo systemctl enable serial-getty@ttyS0.service
  2. [root@liqiang.io]# sudo systemctl start serial-getty@ttyS0.service
  3. [root@liqiang.io]#

创建 VM

  1. [root@liqiang.io]# sudo virt-install --name=testvm-00 \
  2. --os-type=Linux \
  3. --os-variant=centos7.0 \
  4. --vcpu=4 \
  5. --ram=4096 \
  6. --disk path=/home/liuliqiang/data/kvm/images/testvm00.img,size=30 \
  7. --graphics spice \
  8. --location=/home/liuliqiang/data/kvm/isos/CentOS-7-x86_64-DVD-2009.iso \
  9. --network bridge:virbr0

进入 VM

  1. [root@liqiang.io]# virsh console zhangsan

关闭 VM

  1. [root@liqiang.io]# virsh shutdown VM_NAME
  2. [root@liqiang.io]# virsh shutdown --domain VM_NAME
  3. [root@liqiang.io]# virsh destroy VM_NAME # force stop
  4. [root@liqiang.io]# virsh destroy --domain VM_NAME # force stop
  5. [root@liqiang.io]# virsh undefine --domain VM_NAME # remove vm

查看 VM 信息

  1. [root@liqiang.io]# virsh list --all
  2. Id Name State
  3. ----------------------------
  4. 1 200 running
  5. 2 envoy180 running
  6. ... ...
  7. - base-f-vm shut off
  8. [root@liqiang.io]#

Ref