我前段时间刚在一台 Ubuntu Server 22.04 上搭完 KVM 虚拟化环境,目标是同时跑几个隔离的 Linux 服务器,又不想每次都埋头敲 virsh 命令去创建虚拟机。最终选用了 KVM 与 virt-manager 的组合:KVM 负责高性能底层虚拟化,virt-manager 提供可视化管理界面,从下载 ISO 到装完系统全程图形化操作。这篇文章把从零到可用的完整过程记录下来,包括安装、远程连接 virt-manager、在图形界面里创建并安装一台 Ubuntu 22.04 虚拟机,以及我在实际部署中踩过的一些坑。无论你之前有没有接触过 KVM,只要手里有一台装好 Ubuntu Server 22.04 的机器,就可以跟着走一遍。
1. 先搞明白五层关系:KVM、QEMU、libvirt、virt-manager 各负责什么
很多朋友第一次接触 KVM 时,容易被一堆名词绕晕。我在帮别人排错时发现,大部分人卡住的原因不是命令不会敲,而是没搞清楚这几层软件分别干什么。这里先花点时间把概念理清楚,后面操作起来会顺很多。
1.1 这四层组件分别干什么
KVM(Kernel-based Virtual Machine)是 Linux 内核自带的一个虚拟化模块,它把 CPU 的硬件虚拟化能力暴露出来,比如 Intel 的 VT-x 和 AMD 的 SVM。你可以把 KVM 看作一个“硬件加速引擎”,它负责让虚拟机里的指令直接跑在物理 CPU 上,性能非常接近原生。
QEMU 是用户态的模拟器,负责模拟 CPU 以外的设备,比如磁盘控制器、网卡、显卡、USB 等。单靠 KVM 是没法跑起一台完整虚拟机的,它只解决 CPU 和内存这最核心的部分,设备模拟要靠 QEMU。所以你会经常看到“KVM/QEMU”连在一起写,这两个是搭配使用的。
libvirt 是一套管理虚拟机的 API 和守护进程,作用是统一管理 KVM、QEMU、存储池、网络、快照这些东西。virt-manager 并不直接对接 QEMU,它是通过 libvirt 来下发指令的。没有 libvirt,virt-manager 就是一个空壳。
virt-manager 只是一个图形客户端,真正干活的还是 KVM/QEMU 和 libvirt。它给你提供了创建虚拟机、分配资源、打开虚拟屏幕、管理快照的界面,相当于给开车的人一块仪表盘。
一句话总结:KVM 是发动机,QEMU 是整车组装,libvirt 是控制总线,virt-manager 是中控屏幕。
1.2 为什么我不在 Ubuntu Server 上选择 VirtualBox 或 VMware
如果你只是在自己电脑上临时跑个虚拟机,VirtualBox 当然够用。但在 Ubuntu Server 22.04 这种无头服务器场景下,我更推荐 KVM,原因很简单:
| 维度 | KVM/QEMU | VirtualBox | VMware Workstation |
|---|---|---|---|
| 虚拟化性能 | 接近原生 | 一般 | 较好 |
| 命令行自动化 | 强,virsh/virt-install 完善 | 较弱 | 一般 |
| 与 Linux 内核集成 | 内核原生模块 | 需要加载内核模块 | 需要安装闭源模块 |
| 许可证 | 开源免费 | 开源免费 | 商业收费 |
| 服务器长期运行稳定性 | 非常稳 | 一般 | 一般 |
在服务器上,没人愿意为了一个图形界面去装一套闭源虚拟化软件,也没人希望虚拟化层引入额外的内核模块负担。KVM 是 Linux 内核的一部分,只要 CPU 支持硬件虚拟化,装好之后基本就是“内核级”的性能。再加上 virt-manager 提供了不输给桌面虚拟化软件的操作体验,所以这个组合在 Ubuntu Server 上几乎是标准答案。
明白这些之后,接下来就可以动手了。
2. 动手前必须做的三项检查:CPU 虚拟化标志、BIOS 开关与网络拓扑
KVM 不是装完就能跑,它强依赖硬件虚拟化能力。我见过不少人装好之后虚拟机起不来,查到最后是 BIOS 里虚拟化开关没打开。所以在安装软件之前,先把环境确认一遍。
2.1 检查宿主机 CPU 是否支持硬件虚拟化
登录 Ubuntu Server 22.04,先执行这条命令:
grep -E '(vmx|svm)' /proc/cpuinfo | wc -l如果输出大于 0,说明 CPU 包含虚拟化标志。vmx 对应 Intel,svm 对应 AMD。如果输出是 0,先别急着装软件,大概率是 BIOS 里没开。
也可以装一个检查工具,输出会更友好:
sudo apt install -y cpu-checker sudo kvm-ok如果看到INFO: /dev/kvm exists和KVM acceleration can be used,那就没问题。如果看到KVM acceleration can NOT be used,继续往下看。
2.2 BIOS/UEFI 里的虚拟化开关
不同厂商的 BIOS 叫法不太一样,常见的有:
- Intel:Intel Virtualization Technology、VT-x、Virtualization
- AMD:SVM Mode、AMD-V
进入 BIOS 后,一般在 Advanced、Processor 或 Security 菜单下面。找到对应选项,改成 Enabled,保存重启。服务器如果有多路 CPU,也要确认所有 CPU 都开了。
还有一个容易忽略的点:如果打算在虚拟机里再跑虚拟机,需要开启嵌套虚拟化,这个后面会说。但至少第一层虚拟化必须在 BIOS 层面就打开,否则 KVM 完全无法发挥硬件加速作用。
2.3 内存、磁盘和网络规划
软件层面检查完之后,再看资源。KVM 本身几乎没有空闲开销,但虚拟机要实实在在占用内存和磁盘。
内存方面,我建议宿主机最少 8GB 起步。你要跑一台装 Ubuntu 22.04 的虚拟机,给 2GB 内存是能装完系统,但跑起来会很吃力,实际体验流畅至少给 4GB。如果之后计划同时跑两三台,那就把宿主机内存往上提。
磁盘方面,Ubuntu Server 22.04 的 live server ISO 大约 2GB 左右,虚拟磁盘我给虚拟机分配 20GB 比较合适。如果你用的是 qcow2 格式,默认是稀疏分配,也就是说虚拟机里用了多少,宿主机上才占多少物理空间,所以 20GB 的设置并不代表立刻占用 20GB 磁盘。
网络方面,这是很多人一开始没想清楚的问题。Ubuntu Server 22.04 安装后默认用的是 netplan 管理网络。如果你只是想让虚拟机自己上网,用 KVM 自带的 NAT 网络就行;如果你希望虚拟机像一个独立设备一样,能被局域网里的其他机器直接访问,那就需要提前规划好桥接网络。桥接的配置我在下一章一起讲,这里先知道这个区别就行。
3. 在 Ubuntu Server 22.04 上把 KVM 软件栈装到位
环境确认没问题后,开始安装软件。这里直接给出一套适合 Ubuntu Server 22.04 的完整软件包组合,然后逐一说清楚每个包的作用。
3.1 软件包选择与安装
先更新系统,再安装:
sudo apt update && sudo apt upgrade -y sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients virtinst bridge-utils cpu-checker virt-manager这里有几个容易被忽略的点:
- qemu-kvm:提供 KVM 加速的 QEMU 二进制文件,没有它虚拟机就只能纯软件模拟,慢到没法用。
- libvirt-daemon-system:提供 libvirtd 守护进程,负责管理虚拟机的生命周期。
- libvirt-clients:提供 virsh、virt-admin 等命令行工具。
- virtinst:提供 virt-install 命令,这个在无桌面环境下非常有用。
- bridge-utils:提供 brctl 等桥接管理工具,配置桥接网络时会用到。
- virt-manager:图形管理界面,后面可视化安装虚拟机全靠它。
- cpu-checker:提供 kvm-ok 检查命令,主要是验证环境用。
安装过程中如果报依赖错误,先执行一遍sudo apt --fix-broken install,通常能解决。安装完成后,检查一下内核模块是否加载成功:
lsmod | grep kvm正常情况下会看到 kvm_intel 或 kvm_amd,以及 kvm 模块。如果没加载,可以手动执行:
sudo modprobe kvm_intel sudo modprobe kvm_amd注意,Intel 和 AMD 只需要加载对应自己 CPU 的那一个,不是两个都加载。
3.2 启动 libvirtd 并把用户加入权限组
安装后 libvirtd 默认可能没有启动,需要手动启用并设置开机自启:
sudo systemctl enable --now libvirtd.service sudo systemctl status libvirtd看到active (running)就可以了。
接下来的操作非常关键:把当前用户加入 libvirt 和 kvm 组。否则普通用户连接 libvirt socket 会报权限错误,virt-manager 也无法正常使用:
sudo usermod -aG libvirt,kvm $USER修改组之后,需要重新登录或者执行newgrp libvirt才能生效。我建议直接退出 SSH 重新登录,省得后面调试的时候发现用户组没刷新。
验证一下:
virsh list --all virsh urivirsh list --all能正常输出虚拟机列表,说明 libvirt 工作正常。virsh uri会显示类似qemu:///system的结果。
3.3 检查默认存储池,规划 ISO 存放目录
libvirt 默认有一个存储池,路径是/var/lib/libvirt/images。查看一下:
virsh pool-list --all virsh vol-list default如果你的宿主机有单独的磁盘分区,比如挂在/data下,可以创建一个自定义存储池,避免虚拟机占用系统盘:
sudo mkdir -p /data/kvm virsh pool-define-as data dir --target /data/kvm virsh pool-start data virsh pool-autostart data这样做的意义在于:默认池在系统盘上,如果系统盘空间有限,后期扩容非常麻烦。单独划一个存储池,虚拟机镜像集中放,也好做备份。
3.4 如果你要桥接:使用 netplan 配置 br0
Ubuntu Server 22.04 的网络配置用的是 netplan。如果你决定让虚拟机走桥接模式,需要在安装完虚拟化软件后、创建虚拟机之前,先把网桥配置好。
先看一下当前网卡名称:
ip link show假设物理网卡叫 enp3s0,DHCP 上网,那 netplan 配置可以这样写:
# /etc/netplan/01-netcfg.yaml network: version: 2 ethernets: enp3s0: dhcp4: false bridges: br0: interfaces: [enp3s0] dhcp4: true parameters: stp: false forward-delay: 0应用配置时,我强烈建议用netplan try而不是netplan apply:
sudo netplan try它会先临时应用配置,如果配置有问题导致 SSH 断掉,几十秒后会自动回滚,不会把你锁在机器外面。这个命令救过我一次,当时我把网桥配错了,差点要跑到机房去接显示器。
配置生效后,ip addr show br0能看到 br0 获取到 IP。之后的虚拟机网卡选择 br0,就可以像普通设备一样出现在局域网里。
如果你不想折腾桥接,保留 KVM 默认的 NAT 网络也行。虚拟机可以正常上网,但从外部访问虚拟机需要做端口转发,比较麻烦。我一般在自己家里的服务器上直接用桥接,因为虚拟机想要有自己的独立 IP,被 NAS、监控系统、远程维护脚本直接访问。
4. virt-manager 不上服务器也能可视化:远程连接的两条路线
很多人误以为 virt-manager 必须装在 Ubuntu Server 上才能用。实际上 virt-manager 只是 libvirt 的客户端,它完全可以装在你的笔记本电脑上,通过 SSH 远程连接服务器。这在生产环境里是最干净、最安全的做法,不用在无头服务器上额外安装桌面环境。
4.1 推荐路线:在本机安装 virt-manager,通过 SSH 管理远程宿主机
假设你的工作站是一台 Ubuntu 桌面版,安装 virt-manager:
sudo apt install virt-manager如果你的工作站是 Windows,也可以考虑在 WSL 里跑 virt-manager,但图形转发配置比较麻烦,实际体验一般。更常见的做法是用 X server 转发,比如安装 Xming 之后用 SSH -X。这里我不展开讲 Windows 细节,毕竟不同客户端差异太大,重点说 Linux 工作站的方案。
先配置 SSH 免密登录,省得每次连接都输密码:
ssh-copy-id user@你的服务器IP然后打开 virt-manager,选择“文件” → “添加连接”,勾选“通过 SSH 连接”,输入user@你的服务器IP,连接即可。virt-manager 会自动拼出类似qemu+ssh://user@你的服务器IP/system的连接地址。
这个方案的好处是:服务器上不需要装任何图形组件,virt-manager 运行在本地,消耗的是本地资源,远程服务器只承担虚拟化计算。所有图形窗口,包括虚拟机的安装界面,都会通过 SPICE 或 VNC 通道显示到本地。
4.2 备用路线:在服务器上装图形环境,再用 X11 转发
如果你的工作站不好装 virt-manager,但又必须在服务器上运行它,可以装一个最小化的图形环境:
sudo apt install -y xorg xinit virt-manager然后用 X11 转发的方式启动:
ssh -X user@你的服务器IP virt-manager前提是你本机有 X server。Windows 用户可以装 Xming 或 X410,macOS 可以装 XQuartz。这种模式的体验没有本地安装好,图形响应会有一定延迟,但管道紧急时完全够用。
还有一种常用的方式:如果你只需要看虚拟机的屏幕,而不是管理整个 libvirt,可以单独安装 virt-viewer,它比 virt-manager 轻量得多。不过本文主题是可视化创建虚拟机,所以还是优先推荐 virt-manager。
4.3 连接前的自检命令
远程连接之前,先在工作站上验证一下 libvirt 是否能通过 SSH 访问:
virsh -c qemu+ssh://user@你的服务器IP/system list --all如果这个命令能正常列出虚拟机,virt-manager 添加连接基本不会出问题。如果提示权限错误,检查服务器上用户是否加入了 libvirt 组,以及 libvirtd 是否在运行。如果提示 SSH 公钥问题,检查ssh-copy-id是否执行成功。
5. 在 virt-manager 图形界面里装出一台 Ubuntu 22.04 虚拟机
环境跑通之后,接下来就是最关键的部分:用 virt-manager 可视化创建一台 Ubuntu 22.04 虚拟机。我会按实际操作顺序来写,尽量把每一步背后的逻辑也说清楚。
5.1 准备 ISO:注意这个路径是宿主机上的路径
首先,把 Ubuntu Server 22.04 的 ISO 放到宿主机上。这里有个非常容易踩的坑:如果你是远程用 virt-manager 连接服务器的,创建虚拟机时填写的 ISO 路径必须是服务器上的路径,而不是你本地电脑上的路径。有些朋友在本地上下载了 ISO,然后在 virt-manager 里找半天,最后报找不到文件,就是这个原因。
在服务器上执行:
sudo mkdir -p /var/lib/libvirt/images cd /var/lib/libvirt/images sudo wget https://releases.ubuntu.com/22.04.4/ubuntu-22.04.4-live-server-amd64.iso如果你本地已经有 ISO,也可以直接用 scp 传到服务器:
scp ubuntu-22.04.4-live-server-amd64.iso user@你的服务器IP:/var/lib/libvirt/images/放好之后,可以在 virt-manager 里用“浏览”找到这个文件,也可以直接填绝对路径。
5.2 新建虚拟机:内存、CPU、磁盘与网络的取舍
打开 virt-manager,确认左侧列表里能看到你的服务器连接,然后点击“创建新虚拟机”。
第一步选择“本地安装介质(ISO 镜像或光驱)”,点“前进”。在浏览窗口里找到/var/lib/libvirt/images下刚才上传的 ISO。virt-manager 通常会自动识别系统类型为 Ubuntu 22.04,识别不出来也没关系,手动选择Ubuntu 22.04即可。
第二步设置内存和 CPU。给 2 个 vCPU、4GB 内存是比较稳的组合。如果你宿主机资源紧张,1 个 vCPU、2GB 内存也能完成安装,但装完之后跑服务会吃力。我不建议在小内存下强行装带桌面的系统,Ubuntu Server 本身是无桌面的,2GB 也够用。
第三步设置磁盘。选择“创建 qcow2 磁盘镜像”,大小填 20GB。qcow2 格式是稀疏分配的,就是说虚拟机实际用了多少,硬盘才占多少,不是一次性占满 20GB。如果你勾选了“立即分配磁盘空间”,性能会好一点,但会立刻占满 20GB,宿主机磁盘紧张时就别勾。
第四步设置网络。如果你在第三章配置了 br0 桥接,这里直接选“Bridge br0”;如果没配置桥接,就保留默认的“Virtual network default: NAT”。这一步决定了虚拟机能不能被外网直接访问。
最后给虚拟机起个名字,比如ubuntu2204。勾选“安装前自定义配置”可以让你在启动前调整固件、显卡和显示协议。默认设置通常够用,但如果你想用 UEFI 启动,可以在这里把固件改成 UEFI。
5.3 开始安装:从启动到系统安装完成
点击“完成”之后,virt-manager 会创建虚拟机并启动,同时自动弹出虚拟机的图形窗口。如果是远程连接,virt-manager 会调用 virt-viewer 或者内置的 SPICE 客户端来显示画面。如果屏幕没有自动弹出,需要检查本地是否安装了 virt-viewer 或spice-client-gtk,装一下即可。
进入 Ubuntu Live Server 安装界面后,跟你在真机上安装 Ubuntu Server 没有区别:
- 选择语言和键盘布局。
- 配置网络。如果网络走 DHCP,这里会自动获取 IP。
- 配置镜像源地址,默认的官方源通常可用,国内网络环境可以考虑换源,但这一步在安装时操作比较繁琐,可以直接用默认源。
- 磁盘分区,选择“使用整个磁盘”,默认会自动创建合理分区。
- 创建用户名和密码,选择是否安装 OpenSSH Server。
- 等待安装完成,重启。
重启之后,虚拟机会从虚拟磁盘启动,而不是 ISO,这时安装基本就完成了。你可以登录系统,执行ip a查看 IP,ping -c4 8.8.8.8测试外网,ping -c4 你局域网网关测试局域网。
安装完成后,建议在 virt-manager 里给虚拟机拍一个快照,这样以后系统搞坏了可以直接回滚。右键虚拟机,选择“快照”,创建一个干净状态的快照。
5.4 无桌面环境下的替换方案:virt-install 一行创建
虽然本文主题是 virt-manager 可视化安装,但我也提一下 virt-install,因为它是无桌面环境下非常实用的补充工具。完全可以用命令创建出同样效果的虚拟机:
sudo virt-install \ --name ubuntu2204 \ --ram 4096 \ --vcpus 2 \ --disk path=/var/lib/libvirt/images/ubuntu2204.qcow2,size=20,format=qcow2 \ --cdrom /var/lib/libvirt/images/ubuntu-22.04.4-live-server-amd64.iso \ --os-variant ubuntu22.04 \ --network network=default \ --graphics spice \ --noautoconsole执行之后,虚拟机已经开始运行,你可以用virsh vncdisplay ubuntu2204找到 VNC 端口,再用 virt-viewer 或 VNC 客户端连接查看安装界面。
为什么我会提到 virt-install?因为有时候 virt-manager 在远程连接时显示窗口可能失效,或者你只是想快速创建一台虚拟机,命令行比打开图形界面点十几次鼠标要快得多。图形界面适合日常管理和排错,命令行适合批量部署和脚本化。
6. 我在实际部署中遇到过的四个坑,以及排查思路
KVM 本身很稳定,但整个环境牵涉到权限、网络、存储、远程显示,任何一个环节出错都会让人一头雾水。下面我把实际部署中遇到的高频问题列出来,每个都给出症状分析和排查链路。
6.1 权限坑:libvirt socket 拒绝访问
症状:执行virsh list --all报错failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission denied。
排查思路:先看自己属于哪些组:
id $USER如果输出里没有libvirt和kvm,说明之前usermod -aG没生效或没重新登录。执行sudo usermod -aG libvirt,kvm $USER后,重新登录再试。如果组没问题,再检查 libvirtd 状态:
systemctl status libvirtd如果守护进程没起来,执行sudo systemctl enable --now libvirtd.service。还有一种情况是你用了旧配置,Ubuntu Server 22.04 的 libvirtd 默认走 socket 激活,不需要手动改监听地址。网上很多老教程会让你改/etc/libvirt/libvirtd.conf里的监听参数,在 22.04 上基本用不上,改多了反而容易出问题。
6.2 控制台坑:点了安装界面却没有画面
症状:virt-manager 创建完虚拟机,窗口一闪而过,或者一直黑屏,看不到安装界面。
排查思路:先确认图形协议。在 virt-manager 的虚拟机详情里看“显示 SPICE”或“显示 VNC”。如果是 SPICE,但客户端没装 spice 支持,就会看不到画面。在本地工作站安装:
sudo apt install virt-viewer spice-client-gtk如果依然黑屏,可以改用 VNC。在虚拟机关机状态下编辑 XML,把 graphics 类型改成 VNC:
virsh edit ubuntu2204找到类似这样的配置:
<graphics type='spice' port='5900' autoport='yes'/>改成:
<graphics type='vnc' port='5900' autoport='no' listen='127.0.0.1'/>然后用 SSH 隧道转发过来:
ssh -L 5901:localhost:5900 user@你的服务器IP本地用 Remmina 或任何 VNC 客户端连接127.0.0.1:5901即可。这个方法在远程管理时非常实用,几乎能规避所有 SPICE 客户端兼容性问题。
6.3 网络坑:虚拟机起不了 DHCP,或者桥接后没有网
症状:虚拟机安装时网络一直获取不到 IP,或者桥接模式下虚拟机完全无法上网。
排查思路:先区分你是用 NAT 还是桥接。如果是默认 NAT,执行:
virsh net-list --all virsh net-dhcp-leases default如果 default 网络是 inactive 状态,启动它:
virsh net-start default virsh net-autostart default如果是桥接模式,先确认宿主机桥接本身通不通:
ip addr show br0 ping -c4 你局域网的网关IP如果 br0 通,虚拟机还是不行,检查虚拟机的 netplan 配置。Ubuntu Server 安装时如果没识别到网卡,默认可能没有生成网络配置。进入虚拟机系统后,手动配置:
# /etc/netplan/01-netcfg.yaml network: version: 2 ethernets: enp1s0: dhcp4: true然后:
sudo netplan apply还有一个常见问题是:桥接网卡后,宿主机 IP 无法访问。这种情况多半是 netplan 配置写错了,或者 DHCP 没获取到。用sudo netplan try回滚后再调整。
6.4 存储坑:ISO 和虚拟磁盘把宿主机占满
症状:宿主机磁盘告警,虚拟机运行缓慢,甚至无法启动。
排查思路:查看磁盘空间和镜像大小:
df -h du -sh /var/lib/libvirt/images/*这种情况通常有两个原因。一是 ISO 文件一直放在默认存储池目录下,一个 Ubuntu Server ISO 大约 2GB,如果还放了 Windows ISO,空间消耗会很明显。二是你创建虚拟磁盘时勾选了“立即分配磁盘空间”,或者 qcow2 镜像里的数据已经长大到预分配大小。
解决方法是把 ISO 挪到非存储池目录,比如/opt/iso,或只保留当前需要的 ISO。虚拟磁盘如果需要扩容,执行:
sudo qemu-img resize /var/lib/libvirt/images/ubuntu2204.qcow2 40G在虚拟机关机时操作,然后在虚拟机内部对分区做扩展。这个操作有一定风险,动手前务必先做好快照。
最后说一句我自己实际使用的体会:虚拟化这个东西,最忌讳在没搞清网络模型时直接开工。KVM 本身很稳定,所有这些组件在 Ubuntu Server 22.04 上已经非常成熟,真正让人熬夜排查的,几乎全是权限和网络问题。先把用户组、libvirtd、网桥这三样确认好,再用 virt-manager 去点鼠标,你会发现整个过程其实很顺。