Ubuntu1804 安装 KVM
Ubuntu1804 安装 KVM
KVM(Kernel-based Virtual Machine,基于内核的虚拟机)是面向 Linux 系统的开源虚拟化解决方案,KVM 使用 Intel VT 或 AMD-V 等虚拟化扩展提供虚拟化功能。当我们在 Linux 机器上安装 KVM 时,它都会通过加载(基于 Intel 的 kvm-intel.ko 或基于 AMD 的 kvm-amd.ko)内核模块将其转换为 Hypervisor。
KVM 允许我们安装和运行(基于 Windows 和 Linux的)多个虚拟机,并通过 virt-manager 图形用户界面或 virt-install&virsh cli 命令创建和管理基于 KVM 的虚拟机。每一个客户虚拟机都拥有自己的操作系统和专用的虚拟硬件,例如 CPU(s), 内存, 网络接口和存储。
KVM 本身不执行任何硬件模拟,需要用户空间程序通过 /dev/kvm 接口设置一个客户机虚拟服务器的地址空间,向它提供模拟 I/O,并将它的视频显示映射回宿主的显示屏。目前这个应用程序是 QEMU。
Linux 上的用户空间、内核空间和虚机:
- Guest:客户机系统,包括CPU(vCPU)、内存、驱动(Console、网卡、I/O 设备驱动等),被 KVM 置于一种受限制的 CPU 模式下运行。
- KVM:运行在内核空间,提供 CPU 和内存的虚级化,以及客户机的 I/O 拦截。Guest 的 I/O 被 KVM 拦截后,交给 QEMU 处理。
- QEMU:修改过的被 KVM 虚机使用的 QEMU 代码,运行在用户空间,提供硬件 I/O 虚拟化,通过 IOCTL /dev/kvm 设备和 KVM 交互。
KVM 是实现拦截虚机的 I/O 请求的原理:
现代 CPU 本身实现了对特殊指令的截获和重定向的硬件支持,甚至新硬件会提供额外的资源来帮助软件实现对关键硬件资源的虚拟化从而提高性能。以 X86 平台为例,支持虚拟化技术的 CPU 带有特别优化过的指令集来控制虚拟化过程。通过这些指令集,VMM 很容易将客户机置于一种受限制的模式下运行,一旦客户机试图访问物理资源,硬件会暂停客户机运行,将控制权交回给 VMM 处理。VMM 还可以利用硬件的虚级化增强机制,将客户机在受限模式下对一些特定资源的访问,完全由硬件重定向到 VMM 指定的虚拟资源,整个过程不需要暂停客户机的运行和 VMM 的参与。由于虚拟化硬件提供全新的架构,支持操作系统直接在上面运行,无需进行二进制转换,减少了相关的性能开销,极大简化了VMM的设计,使得VMM性能更加强大。从 2005 年开始,Intel 在其处理器产品线中推广 Intel Virtualization Technology 即 IntelVT 技术。
QEMU-KVM:
其实 QEMU 原本不是 KVM 的一部分,它自己就是一个纯软件实现的虚拟化系统,所以其性能低下。但是,QEMU 代码中包含整套的虚拟机实现,包括处理器虚拟化,内存虚拟化,以及 KVM需要使用到的虚拟设备模拟(网卡、显卡、存储控制器和硬盘等)。
为了简化代码,KVM 在 QEMU 的基础上做了修改。VM 运行期间,QEMU 会通过 KVM 模块提供的系统调用进入内核,由 KVM 负责将虚拟机置于处理的特殊模式运行。当虚机进行 I/O 操作时,KVM 会从上次系统调用出口处返回 QEMU,由 QEMU 来负责解析和模拟这些设备。
从 QEMU 角度看,也可以说是 QEMU 使用了 KVM 模块的虚拟化功能,为自己的虚机提供了硬件虚拟化加速。除此以外,虚机的配置和创建、虚机运行所依赖的虚拟设备、虚机运行时的用户环境和交互,以及一些虚机的特定技术比如动态迁移,都是 QEMU 自己实现的。
KVM:
KVM 内核模块在运行时按需加载进入内核空间运行。KVM 本身不执行任何设备模拟,需要 QEMU 通过 /dev/kvm 接口设置一个 GUEST OS 的地址空间,向它提供模拟的 I/O 设备,并将它的视频显示映射回宿主机的显示屏。它是KVM 虚机的核心部分,其主要功能是初始化 CPU 硬件,打开虚拟化模式,然后将虚拟客户机运行在虚拟机模式下,并对虚机的运行提供一定的支持。以在 Intel 上运行为例,KVM 模块被加载的时候,它:
首先初始化内部的数据结构;
做好准备后,KVM 模块检测当前的 CPU,然后打开 CPU 控制及存取 CR4 的虚拟化模式开关,并通过执行 VMXON 指令将宿主操作系统置于虚拟化模式的根模式;
最后,KVM 模块创建特殊设备文件 /dev/kvm 并等待来自用户空间的指令。
接下来的虚机的创建和运行将是 QEMU 和 KVM 相互配合的过程。两者的通信接口主要是一系列针对特殊设备文件 /dev/kvm 的 IOCTL 调用。其中最重要的是创建虚机。它可以理解成KVM 为了某个特定的虚机创建对应的内核数据结构,同时,KVM 返回一个文件句柄来代表所创建的虚机。
针对该句柄的调用可以对虚机做相应地管理,比如创建用户空间虚拟地址和客户机物理地址、真实物理地址之间的映射关系,再比如创建多个 vCPU。KVM 为每一个 vCPU 生成对应的文件句柄,对其相应地 IOCTL 调用,就可以对vCPU进行管理。其中最重要的就是“执行虚拟处理器”。通过它,虚机在 KVM 的支持下,被置于虚拟化模式的非根模式下,开始执行二进制指令。在非根模式下,所有敏感的二进制指令都被CPU捕捉到,CPU 在保存现场之后自动切换到根模式,由 KVM 决定如何处理。
除了 CPU 的虚拟化,内存虚拟化也由 KVM 实现。实际上,内存虚拟化往往是一个虚机实现中最复杂的部分。CPU 中的内存管理单元 MMU 是通过页表的形式将程序运行的虚拟地址转换成实际物理地址。在虚拟机模式下,MMU 的页表则必须在一次查询的时候完成两次地址转换。因为除了将客户机程序的虚拟地址转换了客户机的物理地址外,还要将客户机物理地址转化成真实物理地址。
1. 验证Linux系统是否支持硬件虚拟化
egrep -c '(vmx|svm)' /proc/cpuinfo
如果上面的命令返回数字0,就表示CPU不支持硬件虚拟化,那么我们就只能使用Virtualbox或VMware来创建虚拟机了.如果返回的数字大于0,那么表示CPU支持硬件虚拟化,我们就能使用KVM来创建虚拟机.有的主板可能会禁用了CPU的硬件虚拟化功能,所以在创建KVM虚拟机之前,要确认BIOS里启用了硬件虚拟化.
请使用以下命令安装 kvm-ok 实用程序,它用于确定您的服务器是否能够运行硬件加速的 KVM 虚拟机:
sudo apt install cpu-checker
运行 kvm-ok 命令并验证输出:
sudo kvm-ok
--------------
INFO: /dev/kvm exists
KVM acceleration can be used
2. 安装KVM及其所需的软件包
运行以下命令安装 KVM 及其依赖项:
sudo apt update
sudo apt install qemu qemu-kvm qemu-system libvirt-bin bridge-utils virt-manager spice-client-gtk
qemu-kvm
为KVM管理程序提供硬件仿真的软件。libvirt-bin
用于管理虚拟化平台的软件。bridge-utils
一组用于配置以太网桥的命令行工具。virt-manager
提供了一个易于使用的GUI界面并支持命令行实用程序,用于通过libvirt管理虚拟机。
成功安装上述软件包后,您登录的本地用户将自动添加到 libvirtd 组中,并自动启动并启用 libvirtd
服务,如果 libvirtd
服务没有开启,则运行以下命令开启。
sudo service libvirtd start
sudo update-rc.d libvirtd enable
可以用如下命令查看验证 libvirtd 服务的状态:
service libvirtd status
3. 网络配置
KVM安装完成后,首先需要进行网络配置,KVM支持四种网络模式:
- 桥接模式
- NAT模式
- 用户网络模式
- 直接分配设备模式
主要讲一下前两种:
桥接(Bridge)模式
Bridge模式下,虚拟机需要配置自己的IP,然后虚拟出一个网卡,与宿主机的网卡一起挂到一个虚拟网桥上(类似于交换机)来访问外部网络。这种模式下,虚拟机拥有独立的IP,局域网其它主机能直接通过IP与其通信。简单理解,就是桥接模式下,虚机跟宿主机一样平等地存在,虚拟机和宿主机有平级的IP。
原本宿主机是通过网卡eth0连接外部网络的,网桥模式会新创建一个网桥br0,接管eth0来连接外部网络,然后将宿主机和虚拟机的网卡eth0都绑定到网桥上。
NAT(Network Address Translation)模式
NAT模式是KVM默认的网络模式,KVM会创建一个名为virbr0的虚拟网桥,但是宿主机和虚拟机对于网桥来说不是平等的了,网桥会把虚拟机藏在背后,虚拟机会被分配一个内网IP,而从外网访问不到虚拟机。
一般我们创建虚机是用来部署服务供使用的,所以都是用Bridge模式。
Ubuntu 18.04中,网络配置通过netplan来实现了,需要修改配置文件
/etc/netplan/01-network-manager-all.yaml
# Let NetworkManager manage all devices on this system
network:
ethernets:
eno1:
dhcp4: true
enp7s0:
dhcp4: no
dhcp6: no
version: 2
bridges:
br0:
interfaces: [eno1]
dhcp4: no
addresses: [192.168.xx.xx/23]
gateway4: 192.168.xx.1
nameservers:
addresses: [192.168.xx.xx,8.8.8.8]
renderer: NetworkManager
将宿主机原有网卡eno1挂到网桥br0上,并指定网桥br0的IP地址为192.168.40.241,nameservers指定DNS服务器。修改完后,通过sudo netplan apply
重启网络服务生效,然后通过ifconfig查看。
原来挂在eno1网卡下的IP现在挂到了br0上,宿主机及所有其它虚拟机都通过该网桥来与外部通讯。我们也可以通过brctl show
来直观地查看。
目前因为还没虚拟机,所以只有宿主机的网卡eno1挂在网桥br0上。
4. 虚拟机安装
创建 KVM 虚拟机的方式一共有 种:
- virt-manager(GUI 实用程序)
- virt-install 命令(CLI 实用程序)
- 从已有的image (debian10_base.qcow2)创建虚拟机
使用virt-manager创建虚拟机
要使用 virt-manager 工具创建虚拟机,可以在「终端」中执行如下命令打开:
sudo virt-manager
接下来就是简单的图形化操作,与其它虚拟机的使用方法类似,这里就不赘述了。
使用virt-install命通过CLI创建虚拟机
如果您配置的是 Ubuntu 18.04 Server,当然就需要类似使用以下 virt-install 命令从终端为 KVM 创建 VM 虚拟机。
sudo virt-install -n Sysgeek-Server --description "Test VM for Sysgeek" --os-type=Linux --os-variant=rhel7 --ram=1096 --vcpus=1 --disk path=/var/lib/libvirt/images/ sgserver.img,bus=virtio,size=10 --network bridge:br0 --graphics none --location /home/billyfu/rhel-server-7.3-x86_64-dvd.iso --extra-args console=ttyS0
请根据您的设置替换 VM 名称、描述,ISO 文件的位置和网桥信息。
从已有的image (debian10_base.qcow2)创建虚拟机
virt-install --name demo --memory 512 --disk /home/user/VMs/mydisk.img --import
安装完成后,我们再通过brctl show
来查看网桥挂载情况,br0下面已经多了一个vnet0虚拟网卡了。
开启虚拟机的virsh console登录
systemctl disable systemd-networked-wait-online
systemctl enable serial-getty@ttyS0.service
systemctl start serial-getty@ttyS0.service
开启后,可通过宿主机的console的方式直接登录虚拟机。
5. 虚拟机管理
virsh list --all # 列出所有虚拟机
virsh console # 从宿主机进入虚拟机virsh console,后面接虚拟机ID或名称
virsh start|shutdown # 启动与关闭虚拟机
virsh autostart dev-server1 # libvirtd启动时,自动启动虚拟机
virsh suspend dev-server1 # 挂起虚拟机
virsh resume dev-server1 # 恢复挂起的虚拟机
virsh undefine dev-server1 # 彻底销毁虚拟机,会删除虚拟机配置文件,但不会删除虚拟磁盘
virsh edit debian9 # 编辑虚拟机配置文件
brctl show # 虚拟机网络查看
virsh dumpxml +虚拟机名称 # 查看当前虚拟机的配置文件
virsh domblklist +虚拟机名称 # 查看当前虚拟机的磁盘存储位置
virsh domiflist + 虚拟机名称 # 查看当前虚拟机的网络状态
virsh snapshot-create-as + 虚拟机名称 + snapshot_name # 创建快照,内部快照,将会占用你当前磁盘的空间
virsh snapshot-revert + 虚拟机名称 + snapshot_name或–current # 恢复快照(最近的一次快照)
为虚拟机加入一块新的磁盘
首先创建image:qemu-img create -f qcow2(raw) /var/lib/libvirt/images/your_add_disk.qcow2(raw) 500G
创建attach xml,可仿照现有虚拟机的磁盘配置拷贝
使用virsh attach-device +虚拟机名称 + attach.xml --config(会永久生效,否则只本次生效)
注意:
virsh edit debian9(虚拟机名字) # 编辑虚拟机配置文件
<interface type='bridge'>
<mac address='52:54:00:42:0e:d2'/>
<source bridge='br0'/>
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
interface type='network' 要改为interface type='bridge‘