Manjaro部署kvm虚拟机

Manjaro部署kvm虚拟机

检测是否支持kvm

CPU是否支持虚拟化

kvm需要宿主机cpu支持虚拟化(inter cpu的VT-x技术、AMD cpu的AMD-v技术)

1
grep -E "(vmx|svm)" --color=always /proc/cpuinfo

如果输出中有vmx 或者svm就说明支持虚拟化;如果没有任何的输出,说明未开启CPU虚拟化(需到BIOS中开启,不同品牌的开启方式都有所不同,网上都会有教程)或CPU不支持虚拟化(无缘虚拟机)

内核是否支持

  • KVM模块
    1
    zgrep KVM /proc/config.gz

    模块设定是y或m,则该模块可用

  • VirtIO模块
1
zgrep VIRTIO /proc/config.gz

准/半虚拟化是在全虚拟化的基础上,把客户操作系统进行了修改,增加了一个专门的API,这个API可以将客户操作系统发出的指令进行最优化。
KVM提供Virtio作为hypervisor和来宾之间的一层API。所有的Virtio有两部分组成:主机设备和客户驱动程序
模块设定是y或m,则该模块可用

  • 内核模块是否装载
    1
    2
    lsmod | grep kvm
    lsmod | grep virtio
    若没有返回任何信息,说明没有装载,需要自行装载,控制内核模块装载、卸载的命令由kmod软件包提供
    • 手动装/卸载
      1
      2
      sudo modprobe virtio				# 装载内核模块virtio
      sudo modprobe -r / rmmod virtio #卸载内核模块virtio
    • 开机装载
      开机时systemd 读取 /etc/modules-load.d/ 中的配置加载额外的内核模块。配置文件名称通常为/etc/modules-load.d/ <-program-> .conf ,配置内容为:一行一个要读取的模块名,而空行以及第一个非空格字符为#或;的行会被忽略
      1
      sudo vim /etc/modules-load.d/virtio-mod.conf
      添加需要的配置
      1
      2
      3
      4
      5
      6
      # Load virtio-net.ko at boot
      virtio #所有virtio设备
      #virtio-net #网络设备
      #virtio-blk #块设备
      #virtio-scsi #控制器设备
      #virtio-serial #串行设备
  • virtio 驱动安装

将镜像挂载到虚拟机对未识别设备进行驱动安装即可

安装

KVM在系统内核中,无需安装

安装qemu

Qemu是一个广泛使用的开源计算机仿真器和虚拟机,当作为仿真器时,可以在一种架构(如PC机)下运行另一种架构(如ARM)下的操作系统和程序。通过动态转化,可以获得很高的运行效率。当 QEME 作为虚拟机时,可以使用 xen 或 kvm 访问 CPU 的扩展功能(HVM),在主机 CPU 上直接执行虚拟客户端的代码,获得接近于真机的性能表现。

1
sudo pacman -S qemu

安装libvirt

libvirt是Linux上实现虚拟化功能的库,是长期稳定的C语言API,支持KVM/QEMU、Xen、LXC等主流虚拟化方案

1
sudo pacman -S libvirt virt-manager 	#virt-manager为图形前端

安装网络组件

1
sudo pacman -S ebtables dnsmasq bridge-utils openbsd-netcat
  • ebtables 桥接网络管理,用于 default NAT 网络

  • dnsmasq DHCP DNS 服务,用于 default NAT 网络

  • bridge-utils 桥接网络管理,用于桥接网络

  • openbsd-netcat 用于通过 SSH 管理

其他可选包

  • qemu-arch-extra 其它架构支持
  • qemu-block-gluster glusterfs block 支持
  • qemu-block-iscsi iSCSI block 支持
  • qemu-block-rbd RBD block 支持
  • samba - SMB/CIFS 服务器支持

配置

启动守护进程

1
2
sudo systemctl start libvirtd    	#启动libvirtd进程
sudo systemctl enable libvirtd #开机自起

启动 default NAT网络

1
sudo virsh net-start default
1
2
3
4
5
6
#出现错误可列出网络检查
sudo virsh net-list --all
#若没有任何网络,可手动定义网络;或有网络但ifconfig中没有,且启动错误也可手动添加
sudo virsh net-define /etc/libvirt/qemu/networks/default.xml
#标记为自动启动
sudo virsh net-autostart default

产考

将用户添加到kvm用户组

1
2
systemctl start libvirtd    	#启动libvirtd进程
systemctl enable libvirtd #开机自起

将用户添加到kvm用户组

1
sudo usermod -a -G kvm user_name

安装UEFI功能

安装UEFI固件

1
sudo pacman -S ovmf

配置

配置libvirtd启用UEFI,libvirt需要知道UEFI—>NVRAM中的配置文件映射

1
sudo vim /etc/libvirt/qemu.conf

找到nvram = [ ]去掉注释,默认的配置文件中NVRAM配置的是ovmf_code.fd文件的路径
查看/usr/share/ovmf/x64/目录下的内容对其进行配置

1
2
3
nvram = [
"/usr/share/ovmf/x64/OVMF_CODE.fd:/usr/share/ovmf/x64/OVMF_CODE.fd",
]

重启libvirtd

1
sudo systemctl restart libvirtd

显卡直通 (未成功,待研究)

可能踩坑安装了显卡闭源驱动

通过OVMF实现PCI直通

启用IOMMU

1
2
3
4
5
6
7
8
9
sudo vim /etc/default/grub
#修改GRUB_CMDLINE_LINUX=""
#Intel CPU(VT-d),使用 intel_iommu=on。
#AMD CPU(AMD-Vi),使用 amd_iommu=on
#iommu=pt 防止Linux试图接触(touching)无法直通的设备
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt"

#更新grub文件
sudo update-grub

重启后检查dmesg 以确认 IOMMU 已经被正确启用

1
dmesg | grep -e DMAR -e IOMMU

确保PCI设备被分配到IOMMU组中

创建脚本执行输出PCI 设备是如何被分配到 IOMMU 组之中的,如果没有任何输出,代表没有启用IOMMU支持或你的硬件不支持IOMMU

1
2
3
4
5
6
7
#!/bin/bash
shopt -s nullglob
for d in /sys/kernel/iommu_groups/*/devices/*; do
n=${d#*/iommu_groups/*}; n=${n%%/*}
printf 'IOMMU Group %s ' "$n"
lspci -nns "${d##*/}"
done;

隔离GPU

Linux 4.1 开始,内核包括了 vfio-pci 。这是一个 VFIO 驱动程序,与 pci-stub 的作用相同。但它可以在一定程度上控制设备,例如在不使用设备的时候将它们切换到 D3 状态

1
modinfo vfio-pci

查看显卡信息

1
2
3
4
5
6
7
8
./iommu.sh|grep NVIDIA

IOMMU Group 11 01:00.0 3D controller [0302]: NVIDIA Corporation GM108M [GeForce 940MX] [10de:134d] (rev a2)
#ID: 10de:134d
#01:00.0

cat /sys/bus/pci/devices/0000:01:00.0/modalias
#pci:v000010DEd0000134Dsv00001025sd00001133bc03sc02i00

加载vfio-pci并将ID参数传递给内核,如果有与该显卡同组(IOMMU Group 11)的设备也要将ID加进去

可通过命令:find /sys/kernel/iommu_groups/ -type l查询同组设备

1
2
3
4
sudo vim /etc/modprobe.d/vfio.conf
#加入内容,多个ID用 , 分隔
alias pci:v000010DEd0000134Dsv00001025sd00001133bc03sc02i00 vfio-pci
options vfio-pci ids=10de:134d

保证vfio-pci在其他图形驱动之前加载,在initramfs中静态绑定它和它的依赖项。按照vfio_pcivfiovfio_iommu_type1vfio_virqfd 的顺序添加到mkinitcpio。

确保modconf hookmkinitcpio.conf的 HOOKS 列表中

1
2
3
4
5
sudo vim /etc/mkinitcpio.conf
#找到MODULES修改相关参数顺序
MODULES=(... vfio_pci vfio vfio_iommu_type1 vfio_virqfd ...)
#找到HOOKS确保有参数modconf
HOOKS=(... modconf ...)

重新生成initramfs

生成initramfs映像/etc/mkinitcpio.conf并将其保存/boot/linux-custom.img

1
sudo mkinitcpio -c /etc/mkinitcpio.conf -g /boot/linux-custom.img -k 4.19.69-1-MANJARO

如果修改了/etc/modprobe.d/vfio.conf中的设备ID,就需要重新生成initramfs

重启验证vfio-pci是否已经正确加载并绑定到正确的设备

1
2
3
dmesg | grep -i vfio
#有设备且为ffffffff:ffffffff
#vfio_pci: add [10de:134d[ffffffff:ffffffff]] class 0x000000/00000000

vfio.conf中所绑定的设备(甚至是需要直通的设备)并不一定会出现在 dmesg 的输出之中。有时尽管设备没有出现在 dmesg 的输出中,但实际上在虚拟机中可以被使用

1
lspci -nnk -d 10de:134d

填坑:解除vfio绑定:还原修改,从新生成initramfssudo mkinitcpio -g /boot/initramfs-linux-lily.img -k 4.19.69-1-MANJARO

产考)

使用虚拟机

图形化方式使用

1
virt-manager

命令方式

创建磁盘镜像

1
2
qemu-img create -f qcow2 test.qcow2 40G 	# 动态大小
qemu-img create -f raw test.raw 40G # 直接分配大小

创建虚拟机
1
2
3
4
5
6
7
8
9
vir-install \
--name win \
--ram 1024 \
--vcpu 2 \
-f test.qcow2 \
--cdrom win.iso \
--network bridge=cloudbr0 \
--graphics vnc,listen=0.0.0.0,port=5959,password='123456',keymap='en-us' \
--force --autostart

—name 虚拟机名
—ram 内存
—vcpu CPU数
—f 磁盘镜像
—cdrom 安装镜像
—network 网路
—graphics 连接方式

产考:在 Arch Linux (Manjaro) 中使用 KVM 虚拟机/)

-------------本文结束感谢阅读-------------

欢迎关注我的其它发布渠道