文章

WSL2 开启 KVM 并创建虚拟机

WSL2(AMD 上的 Hyper-V 嵌套虚拟化先决条件要求主机操作系统是 Windows 2022 或 Windows 11) 使用过的是 Ubuntu 20.04 LTS

更换内核

安装编译环境

使用微软 WSL2 专用内核源码

1
2
sudo apt update && sudo apt -y upgrade
sudo apt -y install make gcc build-essential libncurses-dev bison flex libssl-dev libelf-dev cpu-checker qemu-kvm aria2 
1
2
3
wget https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/linux-msft-wsl-5.10.74.3.tar.gz
tar -zxvf linux-msft-wsl-5.10.74.3.tar.gz
cd WSL2-Linux-Kernel-linux-msft-wsl-5.10.74.3

使用当前系统配置

1
2
zcat /proc/config.gz > .config
make menuconfig

Virtualization中确认 Intel 支持已被选中,virtio-net 也被选中

按两次 ESC Processor type and features -> Linux guest support,选中 KVM Guest support

编译

1
make -j 8

使用新内核

新内核放到 windows 这边 并修改配置

1
2
cp arch/x86/boot/bzImage /mnt/c/Users/<username>/bzImage
vi /mnt/c/Users/<username>/.wslconfig

配置参考官方文档 : 主要还是 kernelCommandLinekernel

1
2
3
4
5
6
7
8
[wsl2]
nestedVirtualization=true
memory=48GB
swap=0
localhostForwarding=true
#英特尔 kernelCommandLine=intel_iommu=on iommu=pt kvm.ignore_msrs=1 kvm-intel.nested=1 kvm-intel.ept=1 kvm-intel.emulate_invalid_guest_state=0 kvm-intel.enable_shadow_vmcs=1 kvm-intel.enable_apicv=1
kernelCommandLine=amd_iommu=on iommu=pt kvm.ignore_msrs=1 kvm-amd.nested=1 kvm-amd.ept=1 kvm-amd.emulate_invalid_guest_state=0 kvm-amd.enable_shadow_vmcs=1 kvm-amd.enable_apicv=1
kernel=C:\\Users\\<username>\\bzImage

重新启动 WSL 2

打开 powershell 根据自己发行版名字调整(wsl –list)

1
wsl --shutdown Ubuntu-20.04
1
2
3
4
 uname -ar #查看内核版本
 kvm-ok #kvm是否可用
 #INFO: /dev/kvm exists
 #KVM acceleration can be used

开启 systemd

1
2
3
4
5
|2023年2月3日 16:51:33 已过时

|最新 wsl2 支持,/etc/wsl.conf
[boot]
systemd=true

使用 genie

安装文档参考官方

wsl2 1.0 支持systemd

1
2
3
4
genie -s
#Waiting for systemd....!!!
#第一次启动会很长,等待它结束会输出错误
#错误参考 https://github.com/arkane-systems/genie/wiki/Systemd-units-known-to-be-problematic-under-WSL

安装使用virsh

  • qemu-kvm 包含 KVM 的用户空间(Userspace)态组件;

  • libvirt* 打头的包内置用于管理虚拟化平台的工具;

  • bridge-utils 包含用于配置宿主机与虚拟机之间网络连结的工具;

  • virtinst 包含命令行版本的用于创建虚拟机的工具;

  • cloud-image-utils 包含用于解析 cloud-init 格式文件的工具(稍后用到!);

  • virt-manager 包内置用于创建和管理虚拟机的 GUI 工具。

1
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst cloud-image-utils virt-manager -y

需要添加当前用户到 libvirt 以及 kvm 组中

1
2
sudo adduser `id -un` libvirt
sudo adduser `id -un` kvm

查看是否运行

1
2
3
virsh list --all
# Id Name                 State
#----------------------------------

网络我是使用默认的可以参考这里

创建VM

使用的是img 格式的镜像启动 VM ubuntu-20.04-server-cloudimg-amd64.img 体积比较小。

查看镜像信息

1
2
3
4
5
6
7
8
9
qemu-img info ubuntu-20.04-server-cloudimg-amd64.img
#image: ubuntu-20.04-minimal-cloudimg-amd64.img
#file format: qcow2
#virtual size: 2.2 GiB (2361393152 bytes)
#disk size: 199 MiB
#cluster_size: 65536
#Format specific information:
#compat: 0.10
#refcount bits: 16

镜像默认空间很小,调整到自己喜欢的大小

1
qemu-img resize ubuntu-20.04-minimal-cloudimg-amd64.img 25G

Cloud-init 是适用于多种发行版镜像初始化任务的工业级别标准。该文件描述了将发行版镜像初始化为 VM 实例中的一些行为。教程

简单的 cloud-init 文件如下,默认用户(ubuntu)创建了同名密码

1
2
3
4
5
#cloud-config
password: ubuntu
chpasswd: { expire: False }
ssh_pwauth: True
hostname: ubuntu

cloud-localds 实用工具(位于 cloud-image-utils 包中)用于通过给定的 cloud-init 格式的文本文件生成对应的 .iso 初始化镜像。

1
cloud-localds /var/lib/libvirt/images/install.iso cloud.txt

其中,/var/lib/libvart/images/ 是 virsh 实用工具保存 VM 磁盘的默认路径,把上面img copy 到这里(创建多个VM需要cp多个)

1
cp ubuntu-20.04-server-cloudimg-amd64.img /var/lib/libvirt/images/ubuntu1.img

创建虚拟机

1
2
3
4
virt-install --name vm1 --ram=2048 --vcpus 1 \
--os-variant ubuntu20.04 --graphics none \
--disk /var/lib/libvirt/images/ubuntu1.img,device=disk,bus=virtio \
--disk /var/lib/libvirt/images/install.iso,device=cdrom --import

tips

 WSL2 使用桥接 issue ,不过每次开机删掉永远定义的虚拟交换机,重建后还会出现网络问题(网络慢,wife),还需要重启一下网络适配器….

WSL2-1.0

C:\Users\~\.wslconfig

1
2
3
4
5
6
7
8
9
[wsl2]
networkingMode = bridged
vmSwitch = Bridged //hyper-v 里面的桥接器名字
dhcp = false
nestedVirtualization=true
memory=48GB
swap=0
ipv6=true
#localhostForwarding=true
  • cd /lib/systemd/network/
  • 创建并编辑一个新文件: nano wsl_external.network
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Match]
Name=eth0

[Network]
Description=WSL_external
DHCP=true
IPv6AcceptRA=true
MulticastDNS=true
LLDP=true
EmitLLDP=true

[DHCP]
CriticalConnection=true
RouteMetric=10
UseDomains=true

sudo systemctl restart systemd-networkd

sudo systemctl enable systemd-networkd

  • /etc/wsl.conf文件
1
2
3
4
5
[boot]
systemd=true
[network]
generateResolvConf = false
## 修改 /etc/resolv.conf nameserver 8.8.8.8

sudo systemctl restart systemd-resolved.service

sudo systemctl enable systemd-resolved.service

参考

本文由作者按照 CC BY 4.0 进行授权