1. 整体设计与方案选型
1.1 为什么选择KVM而不是其他虚拟化方案
银河麒麟高级服务器操作系统在国产化替代和信创项目中出镜率极高,尤其是V10版本,无论是党政机关还是金融、能源、教育行业,都能看到它的身影。而在服务器上跑虚拟机这件事,很多朋友第一反应是装VMware Workstation或者VirtualBox,但放在服务器场景里,这两个方案其实都不太合适。
VMware Workstation本身是个桌面级产品,依赖图形界面做管理,在无头服务器上跑起来既笨重又浪费资源,更不用说它还需要独立的授权成本。VirtualBox虽然在桌面端好用,但性能损耗相对明显,在大规模生产环境里很少被认真考虑。而KVM(Kernel-based Virtual Machine)是Linux内核原生的虚拟化模块,直接利用CPU的硬件虚拟化能力,在半虚拟化和全虚拟化场景下都有接近物理机的性能表现。
更重要的是,银河麒麟的服务器版本官方对KVM有完整的适配和文档支持,通过libvirt工具链可以完成虚机创建、生命周期管理、动态迁移等一系列操作。这意味着你不需要额外购买商业虚拟化软件,也不需要依赖某个特定图形工具,只需要一台带虚拟化能力的CPU,就能把整套虚拟化环境搭起来。
还有一个关键点:KVM是内核级组件,和银河麒麟的os以及内核版本深度绑定,不会出现“装个第三方软件导致系统库冲突”这类坑。对于需要长期稳定运行的生产服务器来说,这种内核原生方案在可靠性和维护成本上都更占优势。
1.2 环境准备与版本确认
动手之前,先把环境摸清楚。我这次实操用的系统是银河麒麟高级服务器操作系统V10 SP1,内核版本是4.19系列。需要说明的是,不同的小版本之间,软件包名称和默认配置可能会有细微差异,但整体流程是通用的。
第一步,确认CPU是否支持硬件虚拟化。KVM必须依赖Intel VT-x或AMD-V,否则装好了也用不了。用下面这个命令检查:
grep -E "(vmx|svm)" /proc/cpuinfo如果输出里能看到vmx(Intel)或者svm(AMD),说明CPU硬件虚拟化已经开启。如果没有输出,需要进BIOS/UEFI里找找Intel Virtualization Technology或者SVM Mode这类选项,把它打开。
第二步,确认系统版本和架构:
cat /etc/os-release uname -a我这次用的是x86_64架构,处理的是Intel志强系列CPU。如果你手里是ARM架构的机器(比如飞腾、鲲鹏),安装思路类似,但虚拟化扩展检查的命令可能不同,ARM架构一般通过/proc/cpuinfo里的hyp标志来判断。
第三步,确保系统里有足够的内存和磁盘空间。创建虚拟机不是光有个KVM就完事,每台虚机要划分独立的CPU核数、内存大小和磁盘镜像文件。我建议至少预留20GB以上的空闲磁盘空间,以及至少4GB的可用内存,否则后面创建虚机时会很局促。
另外,操作全程需要root权限,或者至少一个能通过sudo切换到root的账户。KVM的很多配置操作都需要修改系统级文件,普通用户没有这个权限。
2. 核心细节解析与实操要点
2.1 KVM相关内核模块与软件包
银河麒麟基于Linux内核开发,KVM对应的内核模块在系统里是默认存在的,但默认不一定加载。先检查一下模块是否已经加载:
lsmod | grep kvm正常情况下应该看到kvm_intel或kvm_amd模块,以及kvm模块。如果什么都没输出,可以用modprobe手动加载:
modprobe kvm modprobe kvm_intel注意,Intel平台加载kvm_intel,AMD平台加载kvm_amd,别搞混了。加载完之后用lsmod | grep kvm再确认一次。
软件包方面,银河麒麟的默认软件源里包含了KVM全套组件,不需要额外配置第三方源。主要需要安装的包有:
yum install -y qemu-kvm libvirt virt-install bridge-utils这几个包的分工很明确:qemu-kvm提供底层的模拟器,负责实际运行虚拟机;libvirt是虚拟化管理库,提供统一的管理接口;virt-install是命令行下创建虚拟机的工具;bridge-utils用来管理Linux网桥,后面配置虚拟网络要用。
顺便提一句,如果生产环境需要图形化管理界面,可以额外装virt-manager和virt-viewer,这两个是图形工具,适合有桌面环境的机器。在纯服务器环境里,我用得最多的还是命令行工具,脚本化方便,管理效率也更高。
2.2 BIOS/固件虚拟化支持检查
很多人装KVM时卡在第一步:模块加载报错,或者创建虚拟机时提示“KVM不可用”。这时候八成是BIOS里的虚拟化开关没打开。
进入BIOS的方法各品牌不一样,但大多是开机时按Del或F2。进去之后找“Advanced”或者“Processor Configuration”这类菜单,里面一般有Intel Virtualization Technology(Intel平台)或者SVM Mode(AMD平台),把它设为Enabled。
这里有个容易忽略的细节:有些服务器主板默认开了虚拟化,但如果你是在VMware或VirtualBox里再嵌套跑KVM(所谓的嵌套虚拟化),那么宿主虚拟化软件也要开启对应的嵌套虚拟化选项。比如在VMware Workstation里,需要给虚拟机开启“Virtualize Intel VT-x/EPT or AMD-V/RVI”选项。我在实验环境里就遇到过一次这个问题,外层的虚拟机软件没开嵌套虚拟化,里面装好的银河麒麟再怎么检查都提示不支持KVM,排查了半天才发现是这么回事。
系统层面确认虚拟化是否可用的命令是:
virsh capabilities | grep -i vmx如果输出里有vmx字段,说明libvirt已经检测到了硬件虚拟化能力。没有输出就说明CPU虚拟化没生效,先回BIOS确认。
还有个排查技巧:用dmesg | grep kvm查看内核日志。如果加载模块时报错,日志里会明确告诉你原因,比如“KVM: disabled by BIOS”,那就不用折腾系统了,直接去开BIOS开关。
3. 实操过程与核心环节实现
3.1 安装KVM相关软件包
环境确认无误之后,开始安装。银河麒麟的软件包管理兼容yum/dnf,安装命令和CentOS/RHEL系列基本一致。
yum install -y qemu-kvm libvirt virt-install bridge-utils安装过程如果提示找不到软件包,建议先执行一下yum clean all && yum makecache,把元数据缓存刷新一遍。有些刚装好的系统还没同步软件源,直接装会报错。
装完之后验证一下安装结果:
rpm -qa | grep -E "qemu|libvirt|virt-install"确认关键包都在。另外建议装一个云镜像工具,后面用镜像创建虚拟机时会用到:
yum install -y qemu-imgqemu-img是管理磁盘镜像的核心工具,创建虚拟机磁盘文件、查看镜像信息都靠它,虽然virt-install内部也会调用,但单独安装一个方便手工操作。
3.2 启动libvirtd服务
libvirtd是KVM虚拟化环境的核心守护进程,所有virsh和virt-install操作都得经过它。装完包之后,先启动服务再设置开机自启:
systemctl start libvirtd systemctl enable libvirtd systemctl status libvirtd看到active (running)状态就说明服务正常了。很多新手在这里会卡住,报错“Failed to start libvirtd.service”,原因通常是:
- 内核模块没加载,libvirtd启动时检测不到KVM能力。
- AppArmor/SELinux策略限制(银河麒麟默认SELinux可能是enforcing状态)。
- 之前装过其他虚拟化软件,和libvirtd的配置冲突。
遇到启动失败,先看详细日志:
journalctl -u libvirtd -n 50日志里会写清楚失败原因,对症处理。SELinux的问题,临时可以先setenforce 0测试,如果确认是SELinux拦截,再写对应策略,不要直接关掉SELinux了事,生产环境安全还是要保障。
启动成功之后,执行virsh list --all应该能正常返回虚拟列表(当前为空),说明libvirt已经能正常工作了。
3.3 配置桥接网络
KVM默认会创建一个NAT网络(virbr0),虚拟机可以通过它访问外网。但如果想让虚拟机直接暴露在局域网里,让其他物理机也能访问虚机IP,那就得配置桥接网络,把虚拟机的网卡桥接到物理网卡上。
先看看当前物理网卡的名称:
ip a我这里物理网卡是ens33,和CentOS系列常用的命名一致。桥接网络的配置思路是:创建一个bridge类型的连接(名称叫br0),把物理网卡ens33的地址配置迁移到br0上,然后ens33本身加入br0成为桥成员。
用nmcli操作比较直观:
# 创建桥接连接 nmcli connection add type bridge ifname br0 con-name br0 # 修改桥接连接的IP地址为原物理网卡的地址 nmcli connection modify br0 ipv4.addresses 192.168.1.100/24 ipv4.gateway 192.168.1.1 ipv4.dns 223.5.5.5 ipv4.method manual # 将物理网卡ens33接入桥 nmcli connection add type bridge-slave ifname ens33 master br0 # 停用并删除原来的以太网连接配置,避免IP冲突 nmcli connection down ens33 nmcli connection delete ens33 # 启动桥接连接 nmcli connection up br0注意,这里删除ens33网络连接只是删除了NetworkManager里的配置,并不会影响物理网卡设备本身。后续ens33作为桥成员的流量都通过br0转发。
配置完成后,用ip a确认br0获取了IP地址,brctl show查看桥成员列表。如果和物理机网络不互通,检查一下交换机端口是否限制了多MAC地址,以及防火墙是否放行了相关流量。
3.4 创建KVM虚拟机
网络准备好之后,就可以开始创建虚拟机了。创建虚拟机前需要准备一个系统镜像。我这次用的是一个CentOS 7的ISO镜像做演示,放在/data/iso目录下。
先创建虚拟机磁盘镜像:
qemu-img create -f qcow2 /data/kvm/centos7-test.qcow2 50G这里用的qcow2格式是KVM最常用的磁盘格式,支持稀疏文件、快照、COW(写时复制)等特性。50G是虚拟磁盘的最大容量,但实际占用空间会根据虚机内部实际写入数据量增长,不是一开始就占满50G。
然后使用virt-install创建虚拟机:
virt-install \ --name centos7-test \ --memory 4096 \ --vcpus 4 \ --disk path=/data/kvm/centos7-test.qcow2,format=qcow2,size=50 \ --cdrom /data/iso/CentOS-7-x86_64-Minimal-2009.iso \ --network bridge=br0,model=virtio \ --os-variant centos7.0 \ --graphics vnc,listen=0.0.0.0,port=5901 \ --noautoconsole参数拆解一下:
--name:虚拟机名称,后面所有管理操作都用它来标识。--memory和--vcpus:分配的内存(MB)和CPU核数。分配时要考虑宿主机的剩余资源,别把内存全部分出去,宿主机自身也需要内存。--disk:指定磁盘路径和格式,这里的size=50和前面qemu-img创建的50G对应。--cdrom:安装镜像路径。--network:指定使用br0桥接网络,网卡模型用virtio。virtio是半虚拟化IO模型,性能远好于模拟的e1000网卡,在Linux虚机里尤其明显。--os-variant:指定操作系统类型,可以让libvirt自动选择最优的虚拟化参数。可以用osinfo-query os查看可用列表。--graphics vnc:因为是服务器环境没有显示器,用VNC提供图形安装界面,listen=0.0.0.0表示允许远程连接,port=5901指定VNC端口。--noautoconsole:创建后不自动打开控制台,适合远程操作。
执行完上面的命令,虚机就创建成功了。通过virsh list --all能看到这台虚机。
3.5 通过VNC完成系统安装
创建命令执行后,虚拟机进入安装等待状态,但安装界面在VNC的5901端口。在本地电脑上用VNC客户端连接服务器IP的5901端口,就能看到CentOS的图形安装界面。
如果不想走图形安装,也可以用--location参数指定网络安装源、配合kickstart配置文件做全自动安装,这样效率更高,适合批量交付虚机。我之前批量交付测试环境时,就是先做好一个kickstart文件,然后用virt-install调用,一条命令一台虚机,十几台环境半小时内全部搞定。
VNC连上去之后,按照正常系统安装流程操作即可。安装完成后,虚机内部的操作系统和KVM宿主机的网络是二层打通的,直接能拿到局域网IP,从外部其他机器访问没有任何问题。
3.6 虚拟机日常管理命令
虚机创建成功之后,日常管理主要靠virsh。这里整理几个高频命令:
# 查看虚机列表(含运行中和已关闭) virsh list --all # 启动虚机 virsh start centos7-test # 正常关机(需虚机内装有ACPI驱动,virtio/ACPI默认支持) virsh shutdown centos7-test # 强制关机 virsh destroy centos7-test # 重启虚机 virsh reboot centos7-test # 查看虚机基本信息 virsh dominfo centos7-test # 进入虚机控制台(需要虚机配置了串口控制台) virsh console centos7-test如果你的管理机不方便敲命令,也可以在宿主机上装virt-manager图形工具,yum install -y virt-manager,通过远程X11转发或者本地桌面环境管理虚机。但说实话,用多了还是命令行最顺手,尤其是写脚本批量操作的时候。
4. 常见问题与排查技巧实录
4.1 CPU虚拟化未开启导致创建失败
创建虚机时如果报错“KVM hardware virtualization is not available”或者“kvm_intel: no hardware support”,百分之九十九是CPU虚拟化没打开。
排查顺序:先grep -E "(vmx|svm)" /proc/cpuinfo,如果输出为空,进BIOS开启硬件虚拟化。如果是物理机,重启进BIOS设置;如果是虚拟机嵌套虚拟化,检查外层虚拟化软件是否开启了嵌套虚拟化选项。
另外还有一种情况:CPU支持虚拟化,但内核模块加载失败。执行dmesg | grep kvm看内核日志,如果是“kvm: disabled by BIOS”提示,同样回 BIOS 设置;如果是模块签名或者内核版本不匹配,考虑更新内核或调整模块参数。
4.2 桥接网络不通,虚机无法访问外网
这是KVM配置中被问得最多的问题。桥接配置好了,但虚机内部上不了网,或者外部访问不了虚机。
首先确认宿主机桥接是否生效:
brctl show ip a如果br0有IP但ens33还是UP状态没有成为桥成员,说明配置没生效。检查NetworkManager的连接配置:
nmcli connection show删掉ens33原来的独立连接,只保留br0和br0-slave这两个连接,否则可能出现IP冲突。
其次检查iptables(firewalld)是否拦截了转发流量。KVM的桥接网络依赖宿主机开启IP转发。检查一下:
sysctl net.ipv4.ip_forward如果输出为0,需要开启:
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf sysctl -p另外firewalld默认会拦截FORWARD链的流量,如果开启了firewalld,需要放行:
firewall-cmd --permanent --add-masquerade firewall-cmd --reload和VMware里的NAT模式一样,KVM的桥接网络本身是靠二层广播的,理论上不需要NAT,但如果网关做了隔离策略,也可能要检查上游设备的配置。
最后,别忘了检查虚机内部的网络配置。桥接模式下虚机网卡的IP、网关、DNS都必须和宿主机所在的局域网一致,不能沿用NAT模式下的DHCP获取方式(除非局域网内有DHCP服务器)。如果静态配置错了,虚机有网卡也上不了网。
4.3 SELinux导致libvirtd启动失败或磁盘无法访问
银河麒麟默认的SELinux策略对libvirt有一定限制。如果你改过虚机磁盘镜像的存放目录,比如放在/home或者/data下,SELinux可能拦截libvirtd对该目录的访问,导致虚机无法启动,报错信息里有“Permission denied”或者关于svirt_image_t的字样。
解决方法有几种:
第一种,给目录打上正确的SELinux标签:
semanage fcontext -a -t virt_image_t "/data/kvm(/.*)?" restorecon -R /data/kvm第二种,如果不想折腾SELinux标签,可以关掉SELinux或者在/etc/selinux/config里把SELINUX设为permissive。但我不建议直接关闭,尤其是在生产环境,保持SELinux enabled状态,只对特定目录打标签是更稳妥的做法。
另外,如果你用了NFS或其他的网络存储作为虚机镜像目录,还要处理NFS的SELinux布尔值,setsebool -P virt_use_nfs 1,这个比较容易漏。
4.4 qemu-img与virt-install磁盘大小不一致
有时候你会遇到这种情况:用qemu-img手工创建了一个20G的镜像,但在virt-install里指定了size=50,结果虚机里看到的磁盘就是50G。原因是virt-install在指定磁盘路径已存在时会忽略该路径下已存在镜像的大小,直接用size参数重新定义磁盘大小。
避免这个问题的办法是:要么让virt-install自动创建磁盘(不预先执行qemu-img create),要么在virt-install里不写size参数,让它用已有镜像的实际大小。我习惯的做法是让virt-install负责磁盘创建,--disk path=/data/kvm/xxx.qcow2,size=50,format=qcow2,它内部会调用qemu-img自动创建并格式化。
还有个常见坑:虚机磁盘格式用raw还是qcow2。raw格式性能略好但占用空间大,qcow2支持快照和压缩,省空间。个人建议日常使用qcow2,性能差距在绝大多数场景下可以忽略,但快照和管理功能明显更实用。
4.5 常见问题速查表
| 故障现象 | 可能原因 | 排查命令/方法 |
|---|---|---|
| 创建虚机提示KVM不可用 | CPU虚拟化没开启/模块未加载 | grep -E "(vmx|svm)" /proc/cpuinfo,modprobe kvm_intel |
| libvirtd启动失败 | 模块未加载、SELinux拦截 | journalctl -u libvirtd -n 50 |
| 虚机无法访问外网 | 桥接配置错误、IP转发关闭 | brctl show,sysctl net.ipv4.ip_forward |
| 磁盘镜像文件无法访问 | SELinux标签错误 | ls -Z /data/kvm,semanage fcontext |
| VNC连不上 | 端口未放行、防火墙拦截 | ss -tlnp | grep 5901,firewall-cmd --list-ports |
| 虚机关机总是卡住 | 缺少ACPI支持 | 虚机系统内安装acpid服务 |
5. 实操心得与经验总结
整套流程走下来,几个体会比较深的地方整理一下。
第一,银河麒麟和KVM的兼容性真的做得不错。软件包只要从默认源里装基本不会缺依赖,内核模块也是内置的,不像某些国产Linux发行版需要自己编译模块,省了很多事。对做国产化替代的团队来说,银河麒麟 V10 + KVM 这套组合完全可以作为VMware的替代方案来规划。
第二,桥接网络是最值得提前做好的部分。虚机的网络通了,后面的管理就顺畅了;网络这块要是没配好,虚机装完了还是白搭,还得回来重新折腾。我踩过一次坑,是在服务器上配置了NetworkManager和network两个服务同时管理的场景,刚开始桥接一直不稳定,后来停用了network服务,交给NetworkManager统一管理,问题就解决了。建议在做桥接之前,先把宿主机的网络管理方式梳理清楚。
第三,virt-install的--os-variant参数不要偷懒省略。指定正确的系统类型,libvirt会帮你优化很多东西,比如选择合适的驱动模型、CPU模式、时钟源等。省一时手贱,后面虚机性能踩坑就得不偿失了。
第四,快照功能可以大胆用。qcow2格式的磁盘原生支持快照,在给虚机打补丁或者做变更前,先执行virsh snapshot-create-as centos7-test xxx创建一个快照,万一操作出问题可以直接回滚。这个习惯在测试环境和生产环境变更时都很有用,能省下不少重装系统的时间。
第五,性能调优方面,如果虚机跑的是高IO业务,建议把磁盘驱动从sata换成virtio-blk或者virtio-scsi,网络也全用virtio。银河麒麟的虚拟化栈对virtio系列驱动是原生支持的,做个简单迁移就能明显降低IO延迟,值得一试。
最后再分享一个小技巧:批量创建虚机的时候,别一台台敲命令,把virt-install参数写成一个shell脚本循环,把虚机名称、IP、配置参数都参数化,然后循环创建。我上次批量交付8台测试虚机,就是这么干的,整个过程不到10分钟全部完成。脚本化思维在运维场景里永远是第一生产力。
这套环境搭好之后,后面还能继续扩展做高可用、动态迁移、快照备份这些更深入的运维能力,每一块都有很多玩法。先把基础环境跑通,后面怎么用,就看你实际业务需求了。