☰
Rocky Linux 9.6上部署KVM虚拟化平台:从环境校验到生产落地的完整指南
2026/9/30 11:51:26 网站建设 项目流程

1. 内容整体设计与思路拆解

1.1 为什么偏偏是Rocky Linux和KVM这对组合

先聊点实际的。KVM(Kernel-based Virtual Machine)这玩意儿在Linux圈子里有多流行,不用我多啰嗦,从公有云底层到企业内部机房的虚拟化集群,到处都能看到它的影子。而Rocky Linux作为RHEL(Red Hat Enterprise Linux)的社区重建版本,天生就继承了红帽系对KVM的那套原生支持和完整工具链,这两者搭配在一起,基本上就是“原厂验证”和“社区存续”的完美结合。

前阵子有个朋友问过我一个问题:为什么不用之前用得挺顺手的CentOS,非要折腾Rocky Linux?这里有个背景需要稍微展开一下。CentOS不再像以前那样提供长期稳定版本之后,大量生产环境急需一个“换血”的目标,而Rocky Linux正好补上了这个生态位。它扛起了“二进制兼容RHEL”这面大旗,对已经在CentOS上跑得飞起的那套自动化脚本、业务代码、运维流程来说,迁移成本非常低。再加上它在RHEL 9系基础上的GPG签名校验和软件仓库同步机制极其严密,生产环境用起来心理踏实。

再从KVM本身的定位来看,它和Rocky Linux的合作算是“神形兼备”。KVM是一个基于内核的虚拟化模块,直接跑在硬件虚拟化扩展之上,不像Xen那种需要额外维护一个Dom0,也不像VirtualBox那样主要面向桌面个人用户。用KVM跑虚拟机,客户机是标准的Linux进程被内核调度器管理,IO路径短,性能损耗小,这是很多评测机构反复验证过的结论。所以从选型逻辑上讲,Rocky Linux 9.6 + KVM,适合的画像就是那批想摆脱CentOS停更焦虑、又不想被商业虚拟化平台绑定,同时手里还攥着一堆物理服务器等着接手的人群。

这次我搭的这套环境,目标也很朴素:一台1U的商用服务器,两颗中端CPU,64G内存,两块NVMe固态做系统盘,一块HDD做数据盘。选中这种配置是因为它能代表相当一部分中小企业机房的普遍情况,既有升级余量,又不是那种为了跑个KVM还得单独配置存储网络的豪华环境。

1.2 我这套方案选型背后的那些“为什么”

很多人跟着教程装完KVM就算完事,但我习惯在动手之前先想清楚几个问题,这样后面踩坑的概率能降低不少。

第一,为什么不直接用默认安装Minimal镜像,后续再一个个装组件?说实话,Minimal安装确实最节省空间,但KVM虚拟化平台需要一堆依赖项,例如libvirt、qemu-kvm、virt-install、bridge-utils这些。如果从Minimal开始装,倒也能装完,只是你需要花不少时间在依赖关系上。我这次的做法比较务实:安装系统时选择Server with GUI的定制化模块,把虚拟化主机相关的软件包勾选上。这样装出来的系统,图形管理工具和命令行工具同时在位,后续做配置演示、图形化建虚拟机、命令行批量操作都能覆盖,对新手更友好,对老手也不拖后腿。

第二,存储和网络怎么规划。很多人在KVM上栽跟头,不是栽在CPU虚拟化配置上,而是栽在桥接网络和存储池上。我这次规划为网络采用桥接模式,存储采用目录池(directory pool)方式,数据盘单独挂载点处理。这样的好处是:桥接网络让虚拟机直接从物理交换机获取IP,局域网内访问没有任何额外NAT规则需要维护;目录池则让你能够用标准文件(qcow2)来保存虚拟硬盘,备份、迁移都方便。

第三,关于“此平台不支持虚拟化的amd-v”这类问题。每次在网上做KVM部署咨询,都有大量提问集中在BIOS里没开VT-d或者AMD-V导致KVM无法启动。所以我在环境准备阶段就把CPU虚拟化校验放在前面,而且针对Intel和AMD两家的标志位都做了检查。这个看起来微不足道的步骤,实际操作中能拦下不少初学者80%的问题。

下边就开始正式动手。整个安装流程分为四个大的阶段:环境检查与前置条件确认、核心软件包安装与验证、虚拟机的创建与实例化管理、网络与性能调优。按照这个顺序走下来,哪怕你手里只是一台刚开箱的物理服务器,也能顺顺当当把一套可用的KVM平台跑起来。

2. 环境准备与虚拟化前提校验

2.1 CPU虚拟化检查:连这步都省了,后面全是坑

打开服务器终端,第一件事不是急着装包,而是确认这台机器的CPU虚拟化扩展是否可用。命令很简单:

grep -E -c '(vmx|svm)' /proc/cpuinfo

如果返回的数字是0,那就别继续了,先重启进BIOS开启Intel VT-x或者AMD-V。这里要区分一个概念:vmx是Intel的虚拟化扩展标识,svm是AMD的虚拟化扩展标识。绝大多数服务器默认是开启的,但有些二手设备、定制机、甚至部分低端主板会把虚拟化功能藏在一个不起眼的菜单里,名字可能叫“SVM Mode”或者“Intel Virtualization Technology”,记得把状态从Disabled改成Enabled。

还有一个细节值得提醒:有些机器是支持半虚拟化(Para-virtualization)的,但KVM对这类情况支持有限,所以最好是检查到vmx或svm标志之后,再用kvm-ok类的工具做一次综合校验。当然,Rocky Linux仓库里没有kvm-ok,我们可以用另一种方式验证KVM模块是否已经加载:

lsmod | grep kvm

正常情况下能看到kvm_intel或kvm_amd模块,分别对应Intel和AMD的CPU。如果lsmod里什么都看不到,说明模块没有被自动加载,这种时候你可以先手动载入:

modprobe kvm_intel

如果modprobe报错,比如no symbol version for module_layout这种,大概率是内核版本和KVM模块不匹配,升级内核或重建模块就能解决。

2.2 操作系统安装与基础配置的要点

我这次使用的系统镜像是Rocky Linux 9.6的DVD版。选择DVD镜像而不是Minimal,除了前面提到的方便性考虑,还有一个原因是9.6版本的安装器在网络安装环境下可能需要额外配置安装源,DVD可以直接把软件包都打包在本地,省去很多不必要的网络等待。

安装过程有几个值得留意的选项。软件选择(Software Selection)这一步,务必勾选“带GUI的服务器”里面的虚拟化相关功能。如果在安装阶段忘了勾选,也不用重新装系统,后面用dnf module install补上即可。分区分区时,我给根目录留了80GB空间,给/var/lib/libvirt/images这个KVM默认存储路径所在的分区单独分配了500GB。这点对生产环境特别重要,因为后续虚拟机的磁盘镜像都在这个目录下,如果根分区被日志撑爆,那KVM的虚拟机会进入只读模式,故障排查会非常痛苦。

安装完成的系统,建议第一时间更新内核和安全补丁,然后设置好主机名和网络。这里有个实操心得:主机名最好能体现机器用途,比如kvm-host-01,方便后面用libvirt API或者其他管理工具识别。网络部分,如果是静态IP固化为桥接准备,建议直接编辑/etc/NetworkManager/system-connections/下的连接文件,避免用传统network.service脚本在9系系统上遇到兼容性问题。

nmcli con mod ens33 ipv4.addresses 192.168.10.20/24 nmcli con mod ens33 ipv4.gateway 192.168.10.1 nmcli con mod ens33 ipv4.dns "114.114.114.114 8.8.8.8" nmcli con up ens33

设置好静态IP之后,顺手把SELinux确认好。Rocky Linux 9.6的SELinux默认是Enforcing,很多教程图省事直接改成Disabled,我不太建议这么干。KVM在SELinux强势模式下完全能正常工作,只是需要正确配置标签。尤其是自定义存储池目录时,需要确保目录的安全上下文正确,否则虚拟机会出现“Permission denied”之类的怪问题。

3. 核心软件包安装与基础工具链

3.1 极简安装步骤:一条dnf命令锁定全套KVM

环境就绪后,安装KVM主体包的过程简单得让人有点意外。Rocky Linux仓库里已经把所有KVM相关组件都整理好了,直接执行:

dnf install -y qemu-kvm libvirt virt-install bridge-utils

这条命令一次装好了四类核心组件。qemu-kvm是KVM的用户态工具和QEMU系统模拟器,负责实际的CPU模拟和设备模拟;libvirt是虚拟化管理API层,提供统一的命令行和API接口;virt-install是命令行创建虚拟机的利器;bridge-utils则是配置Linux网桥的依赖工具。

装完以后,有人习惯顺手把libvirt-client和virt-viewer之类的也装上,这个看个人需求。virt-viewer可以用来打开虚拟机的图形控制台,对新手来说很直观,但如果是纯命令行环境,不需要它也能正常操作。我这边因为要写教程,所以把virt-manager也一并装上了,它是一个图形化管理界面,有点类似Windows下的Hyper-V管理器,适合不习惯敲命令的场景。

服务启动这块有个小坑,libvirtd在9系版本上虽然可以通过systemd直接管理,但默认可能不启用自动启动。记得执行:

systemctl enable --now libvirtd systemctl status libvirtd

看到状态是active (running)之后,再用virsh version验证一下libvirt和QEMU版本。正常情况下会输出libvirt版本号,以及QEMU emulator的版本信息,这就证明主要工具链已经通了。

3.2 内核模块与用户态工具的配合机制

聊点稍微深层的原理。KVM的架构可以简单理解成两层:内核态的KVM模块负责处理虚拟机CPU模式切换、内存虚拟化这些“脏活累活”;用户态的QEMU则负责提供各种外设的模拟,比如虚拟网卡、IDE控制器、显示设备等。这两者之间的通信通过/dev/kvm这个字符设备完成。

所以当你在Rocky Linux里跑虚拟机时,实际上是在和两个层面的东西打交道:内核态的kvm模块提供CPU虚拟化的加速能力;QEMU进程运行在用户态,模拟出整台机器的硬件环境。也正因为这种分工,所以一旦出现性能问题,排查时要先分清是进程调度、IO等待还是设备模拟造成的瓶颈,不能一股脑把账算在CPU头上。

用云服务器类比可能更好理解:KVM就相当于一个硬盘上的“房东”,QEMU是那个负责装修、出租的“管家”,虚拟机是入住“房客”,libvirt则是管理整个租房合同体系的“中介平台”。这套架构虽然层级多,但每一层都有明确分工,维护起来反而比耦合在一起的方案轻松得多。

3.3 virt-install、virsh还是virt-manager:三种工具的适用边界

软件装好之后,你会面临一个选择:用哪条路径来创建和管理虚拟机?

我用下来最直观的结论是:virt-manager适合那些图形界面环境下的交互式操作,比如你想像配VMware那样调内存、挂光驱、调显示分辨率,图形化的操作效率更高;virt-install适合命令行脚本化的批量部署,一旦你熟悉了它的参数体系,把一条创建命令写进Shell脚本,妥妥的“一条命令建一台虚拟机”;virsh则是最核心的日常管理工具,查状态、做迁移、做快照、动态挂载设备,全靠它。

这条选择路径不用太纠结。绝大多数人都会经历“图形界面入门→virt-install批量创建→virsh按需管理”这样的进阶过程。所以这篇博文里我三种工具都会覆盖到,你可以根据自己的使用场景对号入座。

4. 虚拟机创建与实例化管理全实操

4.1 先搞定存储池和网络

创建虚拟机之前,先把最基础的存储和网络准备好,这两样是虚拟机的“燃料”。存储池我建议用目录方式,把数据盘挂载到/data/kvm下,然后定义这个目录为libvirt的存储池。

mkdir -p /data/kvm/images virsh pool-define-as --name kvm-data --type dir --target /data/kvm/images virsh pool-start kvm-data virsh pool-autostart kvm-data

这里涉及一个libvirt的概念叫Storage Pool(存储池)。初学者经常搞混存储池和存储卷的区别。简单说,存储池是划定的一块存储空间,比如一个目录、一个LVM卷组、一个iSCSI目标;而存储卷则是在存储池里创建的虚拟磁盘文件。所以我们创建虚拟机时,实际上需要先在存储池中创建一个存储卷,再把这个卷作为虚拟机的硬盘。

网络方面,默认的NAT模式(default网络)可以满足刚出厂的虚拟机直接上网需求,但生产环境我强烈建议改成桥接。所谓桥接,就是让虚拟机直接接入到物理网卡的同一个二层网络,宿主机的摸得到的交换机端口,虚拟机也能摸到。配置方式是在/etc/libvirt/qemu/networks/下定义一个桥接网络:

<network> <name>br0</name> <forward mode="bridge"/> <bridge name="br0"/> </network>

当然,前提是你已经创建好了物理网卡的桥接接口br0。这个过程在Rocky Linux里要用NetworkManager完成,稍微有点繁琐,后边常见问题章节我会贴上完整的操作记录。

4.2 用virt-install真正创建一台虚拟机

万事俱备,现在我们来创建第一台虚拟机。假设我准备做一个CentOS Stream 9的测试机器,2核CPU、4GB内存、40GB磁盘,放在刚才的kvm-data存储池里。virt-install命令如下:

virt-install \ --name test-vm01 \ --memory 4096 \ --vcpus 2 \ --disk pool=kvm-data,size=40,format=qcow2 \ --os-variant centos-stream9 \ --network network=br0,model=virtio \ --cdrom /data/iso/CentOS-Stream-9-latest-x86_64-dvd1.iso \ --graphics vnc,listen=0.0.0.0,port=5901

拆解一下这几个关键参数。--memory和--vcpus是基础资源配额,需要结合宿主机物理资源和你对虚拟机的预期压力来定,不要贪多,总共64G内存的机器塞满虚拟机可能会造成内存抖动;--disk pool=kvm-data,size=40,format=qcow2表示在kvm-data池里创建一个40GB的qcow2格式磁盘镜像;--network network=br0,model=virtio表示接到br0桥接网络上,网卡模型选virtio提升性能;--cdrom指定系统安装镜像;--graphics vnc,listen=0.0.0.0,port=5901表示开放VNC远程桌面端口给用户做图形安装。

这里要特别说一下--os-variant参数。很多人忽略这个参数,随便填个generic,结果系统类型识别不准,导致CPU模型优化、时钟源调整这些自动优化项都用不上。可以用osinfo-query os命令查看Rocky系统支持的os-variant列表,找到你安装的客户机系统对应的标识,填进去。

执行完virt-install后,它会自动连接VNC客户端以便你完成系统的安装向导。如果你和我一样用的是命令行环境,可以用virt-viewer连过去,或者直接在浏览器里用VNC客户端连接服务器的5901端口。整个安装过程跟裸机装系统一模一样,按部就班分区、选择软件包、设置root密码即可。

4.3 云镜像方案:比ISO安装快十倍

如果你不是要定制系统安装,而是只想快速拉起一堆同质化的虚拟机,我强烈建议用云镜像(Cloud Image)。

Rocky的云镜像可以从官方仓库下载,一般是一个.qcow2文件。用法也很简单,用qemu-img把镜像复制出一个新卷,然后用virt-install从已有磁盘启动,不再需要安装步骤:

cp /data/iso/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 /data/kvm/images/test-vm02.qcow2 qemu-img resize /data/kvm/images/test-vm02.qcow2 50G virt-install \ --name test-vm02 \ --memory 2048 \ --vcpus 2 \ --disk path=/data/kvm/images/test-vm02.qcow2,format=qcow2 \ --network network=br0,model=virtio \ --import \ --os-variant rocky9

这个方案最大的优势就是快,省去了安装向导那一整套交互动作,几分钟以内就能拉起一台讲道理的Linux虚拟机。后面如果要把虚拟机数量扩展到几十台,配合cloud-init注入ssh密钥、主机名和初始密码,完全可以在脚本里批量完成,这对那些经常需要搭建测试环境、开发环境的团队来说简直就是神器。

4.4 快照、迁移和自动启动:从“能用”到“好用”

虚拟机创建完成后,下一步就是日常管理动作。这块我挑三个核心场景讲讲实操。

快照。快照是虚拟化的灵魂功能之一,在升级软件、改配置之前拉一个快照,出了问题可以秒回滚。命令极简:

virsh snapshot-create-as test-vm01 --name before-upgrade --description "升级前快照"

恢复的话:

virsh snapshot-revert test-vm01 --current

这里有个经验之谈:虚拟机在运行状态打快照,进程内存状态会一并保存,文件系统内部也会被打上标记,但这要求客户机里的QEMU Guest Agent正常运行,所以生产环境最好装上guest-agent(一般叫qemu-guest-agent)并开启服务,不然快照的成功率和数据一致性会打折扣。

迁移。KVM不像VMware vMotion那样完全无感知迁移,但热迁移配合共享存储也能达到类似效果。因为篇幅关系我不展开聊太大范围的在线迁移,只说一个常用的冷迁移场景:把一台虚拟机整体打包到另一台宿主机上。

流程是这样:先virsh shutdown test-vm01,然后导出配置文件:

virsh dumpxml test-vm01 > /tmp/test-vm01.xml

然后把磁盘文件和配置文件一起拷到目标宿主机上,在那边用:

virsh define /tmp/test-vm01.xml

重新定义这台虚拟机即可。整个过程并不复杂,真正复杂的地方在迁移前的规划:IP是否冲突、存储路径是否一致、CPU型号差异是否会触发迁移失败,这些都需要你在执行之前逐一确认。

自动启动。服务器重启后能自己把虚拟机拉起来,这是生产环境的刚需。给虚拟机设置开机自启:

virsh autostart test-vm01

这个操作会在/etc/libvirt/qemu/autostart/目录下生成一个软链接,libvirtd服务启动时会自动加载这些虚拟机。对应的取消命令是virsh autostart --disable test-vm01。

5. 网络桥接配置与性能优化细节

5.1 手把手配置br0网桥,告别NAT限制

默认NAT模式的最大问题是局域网内其他机器无法直接访问虚拟机,排查问题时要绕来绕去。我几乎在生产环境一律配置桥接。在Rocky Linux 9.6上,桥接配置推荐用NetworkManager的命令行工具来操作,不推荐直接编辑ifcfg-*文件,因为在9系里NetworkManager对ifcfg的解析已经相对弱化。

先创建网桥接口:

nmcli connection add type bridge autoconnect yes con-name br0 ifname br0

把物理网卡ens33作为从设备接入:

nmcli connection add type ethernet autoconnect yes con-name bridge-slave-ens33 ifname ens33 master br0

给br0配置IP:

nmcli connection modify br0 ipv4.addresses 192.168.10.20/24 ipv4.gateway 192.168.10.1 ipv4.dns "114.114.114.114 8.8.8.8" ipv4.method manual

最后重启网络服务:

nmcli connection down ens33 && nmcli connection up br0

这套操作下来,br0就接管了原来的IP地址,ens33变成了仅桥接通道。在虚拟机里把网络模式配成network=br0,虚拟机就能像宿主机一样直接暴露在局域网里。

这块有几个常见坑值得提前讲。第一个是SELinux会拦截桥接数据包,所以在Rocky自带的防火墙和SELinux规则下,交叉流量可能被丢掉。如果虚拟机之间想互通局域网,建议把虚拟机的安全域加到libvirt这个zone里,或者适当放行。第二个是NetworkManager可能会因为NetworkManager-ovs等插件的存在产生配置冲突,如果发现br0起不来,检查一下nmcli connection show里的连接状态,把自动配置的虚拟网桥删掉再重建。

5.2 VirtIO驱动的避坑指南与性能对比

如果打算认认真真跑KVM的虚拟机,VirtIO驱动是绕不开的话题。VirtIO本质上是KVM为了减少设备模拟开销而设计的一套半虚拟化IO协议,它让虚拟机里的驱动绕过传统设备模拟路径,直接和宿主机上的vhost通信,性能上几乎可以逼近裸机。

实操中,在virt-install命令行里,--network model=virtio指定虚拟网卡,--disk bus=virtio指定磁盘控制器类型。这样配置之后,虚拟机里的磁盘速度和网络吞吐会有显著提升。有人可能会关心和默认e1000网卡或IDE控制器相比差距有多大。以我的实测经验来说,在同样的读写压力测试下,VirtIO磁盘顺序读能比IDE模拟高出3到5倍,网络PPS(包转发速率)也有一倍以上的提升。所以除非特殊兼容性要求,只要网卡原厂支持,就用virtio。

这里有个容易栽的跟头:安装操作系统时,如果客户机是旧版Windows(比如Windows 7或Server 2008),它不带VirtIO驱动,开机会蓝屏。解决方法是提前备份一个virtio-win的iso挂在光驱里,安装系统时手动加载驱动。对Windows Server 2019及以后的版本,virtio-win的支持已经极其完善,基本能直接装上。

5.3 内存、CPU与磁盘IOPS的调优策略

硬件虚拟化的调优方向通常集中在CPU、内存、磁盘IO这三块。

CPU方面,KVM默认使用QEMU的host-passthrough或host-model模式,这种模式下客户机能使用宿主CPU的大部分新特性,诸如AVX-512、SMEP、SMAP等,对性能敏感的数据库虚拟机尤其重要。如果发现命令执行时客户机的CPU特性被限制,可以这样修改:

virsh edit test-vm01

将<cpu mode='host-model'/>改成<cpu mode='host-passthrough'/>,保存后重启虚拟机生效。注意,这在部分云环境中可能不适用,因为云租户的物理CPU是随机调度的,跨代迁移可能不兼容。

内存方面,开启KSM(Kernel Samepage Merging)能对多个虚拟机共享相同的只读内存页做合并,理论上可以减少内存占用。在Rocky上可以这样启用:

echo 1 > /sys/kernel/mm/ksm/run

但KSM的合并过程本身会耗费CPU,在生产环境做性能追踪时,有时也会反过来导致性能不稳定。我的建议是:如果是多个跑同样负载的Windows虚拟机,KSM收益可观;如果是异构混杂的Linux虚拟机,收益就有限,甚至得不偿失。

磁盘IOPS优化方面,最硬核的招数是用blktap或者io_uring这类异步IO引擎。libvirt里可以给磁盘配置driver name='qemu' type='qcow2' cache='none' iothread='1',这样IO线程就不会被主QEMU线程拖累,在并发读写测试中通常能获得明显提升。

<disk type='file' device='disk'> <driver name='qemu' type='qcow2' cache='none' io='native' iothread='1'/> <source file='/data/kvm/images/test-vm01.qcow2'/> <target dev='vda' bus='virtio'/> </disk>

这里cache='none'的意思是绕过宿主机的页缓存直接写磁盘,对数据库这类对数据一致性要求高的应用是标准配置,但要注意这种做法会增加物理磁盘的写压力,如果你的底层是HDD而不是SSD,体验会差很多。

6. 常见问题与排查技巧实录

6.1 libvirtd起不来或模块加载失败

这个问题的出现概率挺高。情况一:systemctl start libvirtd会提示失败,用journalctl -xe查看日志时能看到Failed to initialize network。这种情况多半是默认的虚拟网络virbr0没有正常创建。解决方案是先检查/var/lib/libvirt/network/default.xml是否存在,不存在就重新定义:

virsh net-undefine default virsh net-define /usr/share/libvirt/networks/default.xml virsh net-start default virsh net-autostart default

情况二:内核KVM模块加载失败。lsmod | grep kvm看不到输出时,先用dmesg | grep kvm查内核日志,如果提示kvm: module verification failed,那很可能是因为内核和模块版本不匹配,需要重新构建内核模块或升级内核。

6.2 虚拟机创建时报“CPU不支持虚拟化”

这个报错信息在网上到处都是。排查思路其实很直接,按下面三步走:

一是确认BIOS里的虚拟化开关是否开启。要特别留神的是,有些主板厂商把VT-d和VT-x分别设置,两者都可能影响KVM。可以看/proc/cpuinfo是否包含vmx标志。

二是检查宿主机是否本身就是一台虚拟机,如果是嵌套虚拟化场景(虚拟机里再装KVM),默认情况下嵌套虚拟化是关闭的,需要在内核加载模块时指定nested=1。Intel和AMD的处理方式相似,在/etc/modprobe.d/kvm.conf里加一行:

options kvm_intel nested=1

AMD则是options kvm_amd nested=1。

三是确认是否有别的Hypervisor占用了VT-x功能。如果你之前在这台机器上跑过VMware Workstation或者VirtualBox,而且没有彻底卸载干净,它的内核模块会产生干扰,开机时甚至直接报错。这种时候就老老实实把所有第三方虚拟化软件清理干净,重启系统再试。

6.3 VNC连不上、桥接断网、快照无法恢复

VNC连不上的原因,七成情况下是防火墙。Rocky Linux 9.6默认的firewalld会拦截非必要端口,需要在防火墙上放行5900-5915段:

firewall-cmd --permanent --add-port=5900-5915/tcp firewall-cmd --reload

另外注意VNC监听地址,我建议--graphics vnc,listen=0.0.0.0这种方式在生产环境虽然方便,但安全上确实裸奔。更稳妥的做法是只监听内网IP,再用SSH隧道本地转发VNC端口。

桥接断网这个,有一个特别常见的低级错误:创建br0时把物理网卡ip地址从原接口挪走后,忘了给br0配置IP,结果宿主机自己都断网了。解决办法是在操作之前先把NetworkManager的配置文件备份好,事故发生时可以快速恢复。真要是手边没有备份,补救方式也很简单:重启物理机,进入单用户模式或者通过BMC远程控制台重新恢复NetworkManager配置。

快照无法恢复,常见原因是磁盘格式不支持。qcow2格式支持快照,但raw格式的磁盘需要先转换成qcow2才能打快照:

qemu-img convert -f raw -O qcow2 test-vm01.raw test-vm01.qcow2

6.4 常见问题速查表

现象核心原因快速解决方案
libvirtd启动失败默认网络未定义用virsh net-define重建default网络
KVM模块加载失败CPU虚拟化扩展关闭或模块不匹配BIOS开启VT-x/AMD-V,或更新内核
虚拟机无法创建CPU不支持x86-64-v2更换支持硬件的服务器,或调整CPU模型
客户机磁盘性能差磁盘bus类型为IDE改为bus=virtio
虚拟机IP分配异常桥接配置错误用nmcli重建br0,确认物理网卡从设备正确
VNC连接失败防火墙拦截端口放行5900-5915,或使用SSH隧道
快照无法恢复raw格式不支持快照转换成qcow2格式后再操作
SELinux阻止读取磁盘存储目录上下文错误用semanage fcontext和restorecon修正

7. 运维监控与日常管理建议

7.1 宿主机负载监控与虚拟机资源用量统计

KVM宿主机跑起来后,日常运维的核心工作就是监控宿主机和虚拟机的资源使用情况。绝不要只盯着top看,因为虚拟机的资源消耗分散在多个QEMU进程里,每个虚拟机通常对应一个qemu-system-x86_64进程,你只有结合virsh才能准确归因到具体是哪台虚拟机在吃CPU。

推荐的组合打法是这样:

virsh list --all virsh dominfo test-vm01 virsh domstats test-vm01 --cpu-total --balloon

dominfo能查看虚拟机的基本配置,domstats能拿到实时CPU和内存统计。如果需要自动化采集,建议部署telegraf+prometheus这类工具,libvirt exporter插件能帮你把宿主机的hypervisor指标和每台虚拟机的状态一齐拉取。实践中我发现,很多自建机房的故障预警都来自磁盘IO等待时间,而domstats里的vcpu.wait字段能非常直观地反映虚拟机CPU饥饿情况。

7.2 定时备份虚拟机和快速恢复演练

数据安全是虚拟化平台绕不开的话题。我给自己的虚拟机设计了一套基于rsync+qemu-img的冷备策略:每周日凌晨,用脚本对所有处于关机状态的虚拟机做一次全量复制,把qcow2文件搬到另一台备份服务器。

脚本大致是这样:

#!/bin/bash BACKUP_DIR=/backup/kvm/weekly DATE=$(date +%Y%m%d) for vm in $(virsh list --name --all); do virsh shutdown $vm 2>/dev/null || true sleep 5 cp -a /data/kvm/images/${vm}.qcow2 ${BACKUP_DIR}/${vm}-${DATE}.qcow2 done

说实话,冷备有个劣势——停机窗口。你也可以用virsh snapshot-create-as做在线快照,然后把快照导出,但这样会占更多存储空间。我的习惯是:重要虚拟机用快照做日常保护,关键业务虚拟机每周做一次冷备,双保险。

恢复演练是另一件很重要但常被忽略的事。不要等到真正出故障了才第一次尝试恢复流程。建议在下一台空闲机器上,一个月做一次从备份到启动虚拟机的完整演练,把踩过的坑提前踩完。

7.3 日志审计:libvirt和qemu的日志都藏在哪里

出了问题找日志,这是运维的基本动作。libvirt的日志默认在/var/log/libvirt/libvirtd.log,QEMU实例的日志则输出到/var/log/libvirt/qemu/目录下的对应文件里。每台虚拟机一个日志文件,文件名就是虚拟机名,内容包含QEMU进程的启动参数、设备热插拔事件、崩溃时的stderr输出。

有一次遇到某台虚拟机莫名其妙重启,查了半天系统日志都没发现异常,最后打开QEMU日志才发现是磁盘IO错误导致QEMU给客户机发了ASHUTDOWN事件。这种交叉查证的思路,一定要在排查问题时优先考虑。同时在危机关头,dmesg能给你不少宿主机内核层面的线索,比如OOM Killer是否杀了QEMU进程,那台虚拟机会直接“消失”不说,还会看到Out of memory: Killed process之类的记录。

7.4 安全加固与权限管理的几个建议

KVM平台的安全加固,我的建议集中在三个方面。

其一,尽量减少对宿主机root凭据的暴露。日常操作用普通用户,配合sudo机制提权到virsh命令即可。libvirt还可以通过polkit做细粒度授权,比如只给运维组用户管理某几台虚拟机的权限。

其二,如果远程管理虚拟机,尽量使用SSH隧道转发VNC/Spice端口,不要在公网上直接暴露图形端口。firewalld和服务监听地址能限制的尽量限制,尤其避免VNC/Spice监听到0.0.0.0。

其三,UEFI安全启动(SecureBoot)对虚拟机的保护也值得开启,现在Rocky 9系的OVMF固件包已经很成熟了,创建UEFI虚拟机时指定--boot uefi即可。它能把非签名固件和恶意Bootkit挡在虚拟机启动链之外,对安全敏感场景价值很大。

8. 进阶扩展与生产环境落地建议

8.1 在KVM之上搭建Webvirtcloud或Cockpit

如果是团队共同使用这台KVM宿主机,把管理界面做成Web访问会友好很多。Rocky 9自带Cockpit,安装启用后服务默认运行在9090端口,登录后能在“虚拟机”页面看到所有虚拟机状态,并支持创建、开机、关机和VNC窗口操作。启用方式:

dnf install -y cockpit cockpit-machines systemctl enable --now cockpit.socket

Cockpit适合轻量管理和简单演示。如果项目有更系统的多宿主机管理需求,WebVirtCloud这类开源Web面板可以统一纳管多台KVM宿主机,租户隔离、模板分发、备份恢复都有现成的模块,部署方式和功能细节后续可以单独展开写一篇。反正先把宿主机装好,后面长成什么样都顺理成章。

8.2 用Ansible实现批量部署KVM虚拟机的思路

当虚拟机的数量上到两位数,手打命令管理就不太现实了。这时候Ansible就发挥威力了。思路比较简单:用Ansible Playbook调用virt-install或libvirt模块,批量创建虚拟机集群。

大致流程是:定义一个hosts文件,列出所有宿主机和创建参数;用community.libvirt.virt模块创建虚拟机;再用cloud_init模块注入初始配置。配合模板变量,可以做到“define一次,到处部署”。

举个非常简化的Playbook片段:

- name: Create KVM virtual machines hosts: kvm_hosts tasks: - name: Create VM with virt-install command: > virt-install --name {{ vm_name }} --memory {{ vm_memory }} --vcpus {{ vm_vcpus }} --disk pool=kvm-data,size={{ vm_disk }} --network network=br0,model=virtio --cdrom {{ iso_path }} --os-variant {{ os_variant }} --noautoconsole

关键是要设计好变量模板,将VM规格、系统镜像路径、网络配置都做成参数,这样在需要快速搭建一批测试环境或开发环境时,一条命令就能拉起一堆机器。

8.3 冷热迁移、嵌套虚拟化和未来扩展思考

说到生产落地,就离不开迁移方案。前面讲了冷迁移,热迁移在KVM同样可以实现。热迁移的前提是虚拟机磁盘放在共享存储上(比如NFS、iSCSI、Ceph RBD),再配合libvirt的virsh migrate --live命令,可以让虚拟机在不关机的情况下从宿主机A迁移到宿主机B。

实际使用中热迁移有个容易被忽略的条件:两台宿主机的CPU型号尽量一致,或者都使用host-model CPU模式,否则原机上能用的CPU指令集到目标机上可能不支持,迁移过程中虚拟机会直接挂起或崩溃。我的建议是,在搭建多宿主机集群前就统一硬件型号,避免中途换设备被迫处理兼容性问题。

再高一点的角度,KVM本身就是很多私有云和超融合平台的基石。OpenStack的Nova默认支持KVM作为计算驱动,ZStack、SmartX等国产商业虚拟化产品底层也是KVM。它的门槛和灵活性让它成为想自建云平台的团队绕不开的一环。装一套KVM只是起点,后续是继续在上面折腾OpenStack,还是只求稳定的虚拟化集群,就看团队需求了。

9. 最后想说的

我这次完整跑完Rocky Linux 9.6上部署KVM的全过程,最大的感觉是这套组合的成熟度已经完全不需要你去“折腾”了——它不是个玩具,是个能直接搬进机房里去当生产基础的底座。整个过程中最费时间的永远不是安装命令本身,而是那些看起来不起眼的细节:BIOS开关、SELinux标签、网桥配置、VirtIO驱动。只要这些前置工作做扎实了,后面就是按部就班的流程。

如果你正准备给自己手头的物理服务器搭一套KVM平台,就从环境校验开始一步步走,遇到问题先按前面速查表里的思路排查一遍。真要是碰到冷门问题,多翻journalctl和dmesg日志,大多数情况下答案就写在日志里。

对了,最后再分享一个小技巧:装完KVM之后,我建议顺手把virsh net-list --all的输出看一眼,确认default网络处于active状态。很多人在第一次建虚拟机时失败,并不是因为KVM有问题,而是默认网络没起来。这种不起眼的小细节,往往是整套平台“能用”和“好用”的分水岭。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询