我最近在帮客户做国产化迁移的时候,频繁被问到银河麒麟高级服务器操作系统上怎么搭KVM、怎么建虚拟机。老实讲,网上关于KVM的教程一抓一大把,但大多数是拿Ubuntu或者CentOS做演示的,真到了银河麒麟V10这个环境下,你会遇到不少“看似一样但又不完全一样”的坑。比如默认源能不能用、libvirt的版本对不对得上、virt-install安装时图形化界面起不来等等。这篇就基于我自己在麒麟V10上从零装KVM到跑起第一个虚拟机的完整过程,把关键的决策点、参数设置、踩坑记录都写清楚,给正在做类似事情的朋友一个参考。
整个操作流程其实可以拆成四大块:环境确认、安装组件、配置网络、创建虚拟机。每一块里都有一些容易翻车的小细节,我会在对应的位置都点出来,建议你照着顺序做,别跳步。尤其是网络桥接那块,很多人虚拟机建好了但是外部访问不了,问题基本都出在这里。
1. 动手前的思路梳理:为什么在银河麒麟上选KVM
1.1 虚拟化方案的取舍逻辑
先聊聊为什么在银河麒麟上优先考虑KVM而不是其他方案。银河麒麟V10基于Linux 4.19内核,社区版和企业版的内核都保留了完整的KVM内核模块支持。相比于在Linux上跑VirtualBox或者用QEMU纯软件模拟,KVM的优势在于它是内核级的虚拟化方案,虚拟机直接调度物理CPU的计算单元,性能损耗极低。在我实际压测中,KVM虚拟机的CPU性能损耗基本可以控制在5%以内,而纯QEMU模拟动辄30%以上的损耗,两者完全不是一个量级。
还有一种思路是在银河麒麟上装VMware Workstation,那个其实也能跑,但有两个问题:一是VMware依赖内核模块,银河麒麟的内核版本和官方支持的版本经常对不上,需要手动打补丁,升级内核后还得重新编译模块;二是VMware Workstation更偏桌面级应用,放在服务器上做长期稳定运行不太合适。KVM配合libvirt这套组合是Linux服务器领域的标准方案,无论是单机虚拟化还是对接OpenStack等云平台,都能平滑扩展。
1.2 环境确认与前置检查
安装前最重要的一件事,就是确认这台机器的CPU虚拟化功能已经开启。你可以通过下面的命令快速检查:
egrep -c '(vmx|svm)' /proc/cpuinfo如果输出结果是0,说明CPU的虚拟化扩展没有被启用,这种情况下KVM模块是加载不起来的。此时需要进入服务器的BIOS设置里,找到类似"Intel Virtualization Technology"或"SVM Mode"的选项,开启后重启系统再验证一次。
接着确认系统版本信息和内存资源:
cat /etc/os-release free -h df -h /var银河麒麟V10的操作系统标识一般能看到"Kylin Linux Advanced Server release V10"这样的字样。内存方面,建议宿主机至少8GB起步,其中给虚拟机预留的容量要提前规划好。磁盘方面,虚拟机的磁盘镜像文件默认会存储在/var/lib/libvirt/images目录下,所以要确认这个目录所在的磁盘分区有足够的可用空间。
还有一点容易被忽略:干净的系统环境建议先执行一次yum update把系统基础包更新到最新状态,然后再装KVM相关组件。更新过程中如果遇到内核升级,重启一次让新内核生效再做虚拟化操作,可以避免一些因内核版本过旧导致的兼容性问题。
2. KVM安装与依赖解析
2.1 用yum快速完成基础组件安装
银河麒麟V10兼容CentOS的使用习惯,软件管理同样使用yum包管理器。安装KVM所需的核心组件,一条命令就能搞定:
yum install -y qemu-kvm libvirt virt-install bridge-utils这几个包的职责分别是:
- qemu-kvm:提供QEMU虚拟化后端,负责处理CPU和内存的虚拟化实现。
- libvirt:虚拟化管理库,提供统一的管理API,virsh命令行工具就是它自带的。
- virt-install:命令行下创建虚拟机的工具,支持通过参数指定系统镜像、磁盘、网络等信息。
- bridge-utils:网络桥接工具集,包含brctl命令,是用来创建和管理Linux网桥的关键组件。
安装完成后,建议顺手把virt-viewer也装上,它是SPICE/VNC协议的客户端,可以通过图形界面连接虚拟机屏幕:
yum install -y virt-viewer2.2 软件源配置的几个细节
银河麒麟V10默认配置的yum源有时候访问速度不太稳定,尤其是在下载qemu-kvm这种体积比较大的包时特别明显。建议提前准备一个速度更快的镜像源。
在更换源之前,先备份原有的repo配置:
mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/然后创建新的repo文件,指向阿里云或华为云的镜像源。这里以阿里云为例,新建/etc/yum.repos.d/kylin.repo,写入如下内容:
[ks10-adv-os] name=Kylin Linux Advanced Server 10 - Os baseurl=https://mirrors.aliyun.com/kylin/KYLIN_V10_SP1/adv/os/x86_64/ gpgcheck=0 enabled=1 [ks10-adv-updates] name=Kylin Linux Advanced Server 10 - Updates baseurl=https://mirrors.aliyun.com/kylin/KYLIN_V10_SP1/adv/updates/x86_64/ gpgcheck=0 enabled=1注意:这里的baseurl路径需要根据你实际的系统小版本号灵活调整,V10的SP1和SP2路径会有差异。如果不确定的话,先用浏览器访问https://mirrors.aliyun.com/kylin/ 看一下实际目录结构,再修改对应的小版本号。
换完源之后执行yum clean all && yum makecache生成新的缓存索引,然后再去安装KVM组件,速度会有明显提升。
2.3 内核模块加载与libvirtd服务管理
KVM组件安装之后,需要确认内核模块是否已经正确加载。执行以下命令:
modprobe kvm_intel如果你的CPU是AMD平台,加载的模块名是kvm_amd:
modprobe kvm_amd加载成功后可以通过lsmod | grep kvm查看模块状态。如果这里提示模块找不到,大概率是前面确认过的CPU虚拟化功能没有在BIOS里打开,再回去检查一遍。
接下来启动libvirtd守护进程,并将其设置为开机自启:
systemctl enable --now libvirtd正常情况下,执行systemctl status libvirtd会看到active (running)的状态。同时,systemd也会自动创建/var/run/libvirt目录,如果该目录缺失,后续virsh命令会报"Failed to connect socket to '/var/run/libvirt/libvirt-sock'"的错误。遇到这种情况,重启libvirtd服务或者重建目录并重启服务即可。
3. 创建KVM虚拟机的完整实操
3.1 准备虚拟机磁盘镜像
创建虚拟机之前,先规划好磁盘镜像的存放位置和大小。我习惯把镜像集中放到/opt/kvm目录下,便于维护:
mkdir -p /opt/kvm使用qemu-img创建虚拟机的磁盘镜像文件。这里我以创建一个50GB的qcow2格式镜像为例:
qemu-img create -f qcow2 /opt/kvm/ubuntu-server.qcow2 50G关于磁盘格式,qcow2和raw是两种最常见的选择。qcow2支持写时复制、快照、压缩等高级特性,创建时占用空间小,后续扩容也方便,是绝大多数场景下的首选。raw格式性能略好,但不支持快照,文件创建即占满全部空间,50GB就真的会占用50GB的宿主机磁盘。我建议除非你有特别明确的性能需求,否则统一用qcow2就行了。
3.2 网络模式选择与桥接配置
网络配置是创建虚拟机过程中最容易被疏忽的环节。libvirt默认安装后,会自动创建一个名为virbr0的NAT网桥,虚拟机通过NAT方式可以访问外部网络,但宿主机之外的设备无法直接访问虚拟机。这在测试环境里问题不大,但如果虚拟机需要对外提供服务,就必须切换到桥接模式。
查看当前网桥状态的命令:
brctl show创建桥接网络的方法如下。假设宿主机当前使用的物理网卡是eno1,我们创建一个名为br0的网桥,并把eno1桥接进去。修改/etc/sysconfig/network-scripts/ifcfg-br0:
DEVICE=br0 TYPE=Bridge BOOTPROTO=static NAME=br0 ONBOOT=yes IPADDR=192.168.1.100 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 DNS1=223.5.5.5同时修改物理网卡的配置文件ifcfg-eno1:
DEVICE=eno1 TYPE=Ethernet BOOTPROTO=none NAME=eno1 ONBOOT=yes BRIDGE=br0修改完两个文件后重启网络服务:
systemctl restart network重启后通过ip addr show br0确认网桥是否获得了对应的IP地址。
重要提示:配置桥接网络时如果操作不当,很容易造成宿主机网络中断,尤其是远程连接的服务器。稳妥的做法是先把上述配置文件写好后,用一个短命令验证配置正确性,或者先在本地控制台操作。万一真的断网了,重启服务器或者到机房接显示器把配置回滚即可。
3.3 使用virt-install命令行安装虚拟机
磁盘和网络都准备好之后,就可以正式创建虚拟机了。下面是我实际使用的virt-install命令,以安装Ubuntu Server 22.04为例:
virt-install \ --name ubuntu-server \ --ram 4096 \ --vcpus 4 \ --disk path=/opt/kvm/ubuntu-server.qcow2,format=qcow2,bus=virtio \ --network bridge=br0,model=virtio \ --os-variant ubuntu22.04 \ --cdrom /opt/iso/ubuntu-22.04.3-live-server-amd64.iso \ --graphics vnc,listen=0.0.0.0,port=5901 \ --noautoconsole这些参数的含义:
- --name:虚拟机实例的名称,后续用virsh操作时都靠这个名字来识别。
- --ram:分配给虚拟机的内存大小,单位MB。
- --vcpus:分配的虚拟CPU核数。
- --disk:指定磁盘镜像路径和格式,bus=virtio表示使用virtio半虚拟化磁盘驱动,性能远优于模拟IDE。
- --network:指定网络模式。这里用的是前面配置好的br0桥接,model=virtio同样是为了性能。
- --os-variant:告诉libvirt操作系统类型,不同的系统对应不同的虚拟化推荐配置。可以用
osinfo-query os命令查看系统支持的os-variant列表。 - --cdrom:指定安装介质ISO镜像路径。
- --graphics:配置图形输出方式。这里设置VNC监听所有地址,端口5901,方便后续远程安装。
- --noautoconsole:安装时不自动打开控制台,而是让安装过程在后台运行。
如果安装的是Windows虚拟机,需要在--disk和--cdrom参数中额外添加virtio-win驱动镜像,否则安装过程中会识别不到磁盘:
virt-install \ --name win2019 \ --ram 8192 \ --vcpus 4 \ --disk path=/opt/kvm/win2019.qcow2,format=qcow2,bus=virtio \ --disk path=/opt/iso/virtio-win-0.1.229.iso,device=cdrom \ --network bridge=br0,model=virtio \ --os-variant win2k19 \ --cdrom /opt/iso/Windows_Server_2019.iso \ --graphics vnc,listen=0.0.0.0,port=5902 \ --noautoconsole3.4 安装后的虚拟机管理命令
安装过程中可以通过VNC客户端连接虚拟机的屏幕,完成操作系统的初始化配置。由于安装了qemu-kvm,virt-viewer也提供命令行方式连接VNC:
virt-viewer --connect qemu:///system ubuntu-server虚拟机安装完成后,常用的管理命令如下:
# 查看所有虚拟机列表(包含关机状态) virsh list --all # 启动虚拟机 virsh start ubuntu-server # 正常关机(发送ACPI关机信号) virsh shutdown ubuntu-server # 强制关机 virsh destroy ubuntu-server # 重启 virsh reboot ubuntu-server # 设置开机自启 virsh autostart ubuntu-server # 取消开机自启 virsh autostart --disable ubuntu-server # 删除虚拟机(仅删除定义,不删除磁盘文件) virsh undefine ubuntu-server如果一个虚拟机不再需要了,完整的清理流程应该是:先virsh shutdown正常关机,再virsh undefine删除虚拟机定义,最后手动删除磁盘镜像文件。这样不会留下残留配置,磁盘空间也能及时释放。
4. 常见问题与排查技巧实录
4.1 图形界面无法打开或安装卡住
用virt-install创建虚拟机时,如果加了--graphics vnc参数但VNC始终连不上,先检查libvirtd的状态和端口监听情况:
systemctl status libvirtd netstat -tlnp | grep 5901如果没有监听5901端口,大概率是libvirtd没有正常启动。另外检查/etc/libvirt/libvirtd.conf中的listen_tls和listen_tcp配置项,将listen_tls设置为0,listen_tcp设置为1,并确保listen_addr没有限制在127.0.0.1。修改后重启libvirtd服务。
还有一种情况是在服务器没有图形桌面的环境下运行virt-manager,会直接报"cannot open display"。这时候要么改用命令行virt-install配合VNC连接,要么安装x11vnc配合Xvfb做一个虚拟显示环境。我的建议是直接走VNC路线,最简单省事。
4.2 CPU虚拟化扩展未正确启用
KVM安装好了,但创建虚拟机时提示类似"KVM is not available"的错误。按以下顺序排查:
# 1. 确认模块已加载 lsmod | grep kvm # 2. 确认CPU虚拟化标志 grep -E '(vmx|svm)' /proc/cpuinfo # 3. 查看kvm设备的权限 ls -l /dev/kvm如果/dev/kvm不存在,说明内核模块没加载成功,或者宿主机CPU本身不支持虚拟化。如果是/dev/kvm存在但权限不对,用chmod 666 /dev/kvm临时解决,或者将当前用户加入到kvm和libvirt用户组中:
usermod -aG kvm,libvirt $(whoami)还有一点,某些云厂商的云服务器实例虽然开放了CPU虚拟化标志,但没有透传完整的虚拟化指令集,这种情况下KVM也无法正常工作。如果是物理服务器,还需要确认BIOS里VT-x/AMD-V选项没有被安全启动(Secure Boot)锁住。
4.3 Windows虚拟机安装慢或者蓝屏
用KVM装Windows系统,最常见的两个问题:一是安装过程中找不到硬盘,二是系统反复蓝屏重启。
找不到硬盘的问题,几乎都是因为缺少virtio驱动。解决办法就是在virt-install中额外挂载virtio-win驱动镜像(类似前面示例中的写法),在Windows安装界面选择磁盘时,点击"加载驱动程序",选择virtio驱动后,磁盘就能正常识别了。
系统反复蓝屏的问题,多半是因为CPU模式不兼容。默认情况下负责分配CPU模式的工具可能会使用host-passthrough模式,这在某些Windows版本上会触发异常。解决办法是在virt-install参数中显式指定CPU模式:
--cpu host-model或者在创建后通过virsh edit win2019修改CPU配置为<cpu mode='host-model'/>。
4.4 桥接网络配置后宿主机断网
这个坑我踩过不止一次。配置桥接时,如果物理网卡原本配置了IP地址,而你直接把它改成bridge模式却没有同步配置好br0的IP,网络就会立即断开。正确做法是:
- 先把br0的配置文件写完整,包括IP地址、网关、DNS。
- 把物理网卡的配置改为BOOTPROTO=none且BRIDGE=br0。
- 同时把两个文件都保存好再重启网络服务。
如果远程连接已经断了,可以让机房帮忙重启服务器,重启后如果配置写对了,网络会自动恢复。另外建议在配置桥接前先在/etc/sysconfig/network-scripts/目录下备份原来的网卡配置文件,这样出了问题还能快速还原。
4.5 虚拟机开机自启动失败
设置virsh autostart后,重启宿主机发现虚拟机没有自动启动。这通常是由于libvirtd服务启动时挂载的默认存储池还没就绪导致的。
我遇到过的场景是:虚拟机磁盘文件放在自定义目录/opt/kvm,但这个目录没有加入libvirt默认存储池,导致libvirtd在开机阶段无法找到磁盘文件,虚拟机启动失败。
解决办法是把自定义目录添加到默认存储池中:
virsh pool-define-as --name default --type dir --target /opt/kvm virsh pool-build default virsh pool-start default virsh pool-autostart default注意如果默认池指向的是/var/lib/libvirt/images,而你偏偏把镜像放在/opt/kvm下,虚拟机定义里的source file路径会直接指向/opt/kvm下的文件。此时检查pool配置是否真的改过来了,最直接的方式是查看虚拟机XML中的磁盘路径,确认真实路径和libvirt启动时能访问到的路径一致。
5. 提升虚拟机使用体验的进阶配置
5.1 内存和CPU热插拔配置
KVM支持对运行中的虚拟机进行内存和CPU的热插拔操作,这在生产环境调整资源时特别有用。要实现热插拔,需要在虚拟机的XML配置中启用对应的能力。
先编辑虚拟机配置:
virsh edit ubuntu-server在<memory>标签中使用带单位的值,并在<currentMemory>中设置当前的活跃内存值。CPU热插拔需要在<vcpu>标签中添加current=属性,同时使用最大可用CPU数量。例如:
<memory unit='GiB'>16</memory> <currentMemory unit='GiB'>8</currentMemory> <vcpu placement='static' current='4'>8</vcpu>配置好之后,通过virsh命令进行动态调整:
# 调整内存到12GB virsh setmem ubuntu-server 12G --live # 调整CPU到6核 virsh setvcpus ubuntu-server 6 --live注意:热插拔功能依赖虚拟机内部的操作系统支持,Linux内核和Windows Server版本都有不同的兼容性要求,生产环境操作前请先在测试虚拟机验证一遍。
5.2 VNC访问密码与安全性
默认情况下,libvirt创建的VNC服务是没有任何访问认证的,只要网络能连通5901端口,任何人都能连接到虚拟机屏幕。为了安全,建议在虚拟机XML配置中增加VNC密码认证。
编辑虚拟机配置,在<graphics>标签中加入password属性:
<graphics type='vnc' port='5901' listen='0.0.0.0' passwd='YourPass123'>修改后重启虚拟机生效。同理,如果是生产环境,VNC端口最好不要暴露在公网,用防火墙限制只允许特定IP访问,或者通过SSH隧道的方式访问VNC端口。
5.3 磁盘快照与备份方案
KVM提供了两种快照方式:磁盘快照和系统快照。磁盘快照只保存磁盘当前状态,系统快照同时包含内存状态和磁盘状态。对于运行中的生产虚拟机,推荐使用系统快照:
# 创建包含内存状态的快照 virsh snapshot-create-as ubuntu-server snap1 "backup before update" --disk-only --atomic快速恢复操作:
# 查看快照列表 virsh snapshot-list ubuntu-server # 恢复快照 virsh snapshot-revert ubuntu-server snap1不过快照并不能替代完整的备份方案,建议同时定期执行离线备份,直接复制qcow2磁盘文件:
cp /opt/kvm/ubuntu-server.qcow2 /backup/ubuntu-server-$(date +%F).qcow2如果虚拟机在运行中,直接复制qcow2文件可能导致文件不一致,最稳妥的办法是先virsh snapshot-create-as做一个一致性快照,然后复制快照文件,或者干脆在虚拟机内部用tar备份关键数据。
6. 常用运维操作与注意事项速查
6.1 虚拟机克隆
KVM虚拟机克隆有两种方式:完整克隆会复制整个磁盘镜像并生成独立的虚拟机;链接克隆则基于原磁盘制作差异盘,只占用增量空间。
完整克隆:
virt-clone --original ubuntu-server --name ubuntu-server-clone --file /opt/kvm/ubuntu-server-clone.qcow2链接克隆需要先在原虚拟机磁盘上创建快照,然后基于快照创建。这种方法节省大量磁盘空间,但如果原虚拟机删除或损坏,所有链接克隆的虚拟机都会受影响,测试环境用用还行,生产环境不推荐。
6.2 查看虚拟机的资源监控
查看一台正在运行的虚拟机的CPU和内存使用情况:
virsh vcpuinfo ubuntu-server virsh dommemstat ubuntu-server这些命令在排查虚拟机的性能瓶颈时非常有用。如果在宿主机上用top或者htop看到多个qemu进程占用CPU较高,这是正常的,因为KVM会为每个虚拟CPU创建一个qemu线程,CPU核数越多,看到的qemu进程也越多。
6.3 常见命令速查表
| 功能 | 命令 |
|---|---|
| 列出所有虚拟机 | virsh list --all |
| 启动虚拟机 | virsh start vm-name |
| 关闭虚拟机 | virsh shutdown vm-name |
| 强制关机 | virsh destroy vm-name |
| 重启虚拟机 | virsh reboot vm-name |
| 设置开机自启 | virsh autostart vm-name |
| 导出虚拟机XML配置 | virsh dumpxml vm-name |
| 修改虚拟机XML配置 | virsh edit vm-name |
| 查看VNC端口信息 | virsh vncdisplay vm-name |
| 创建快照 | virsh snapshot-create-as vm-name snap-name |
| 恢复快照 | virsh snapshot-revert vm-name snap-name |
| 删除虚拟机定义 | virsh undefine vm-name |
6.4 宿主机防火墙与虚拟机的联动
在使用桥接网络时,虚拟机的流量会通过宿主机物理网卡转发,此时宿主机自身的防火墙规则需要特别注意。最典型的例子是:虚拟机开启了HTTP服务,但宿主机防火墙没有放行对应端口,外部用户通过宿主机访问虚拟机时就会被拦截。
排查这个问题的方法是,在宿主机上执行:
iptables -L -n看有没有针对FORWARD链的限制规则。如果确认是防火墙拦了,可以在防火墙中放行对应的转发规则,或者临时关闭防火墙来测试。另外注意银河麒麟V10自带的firewalld管理工具,修改规则前先确认当前的服务启动状态和默认zone配置。
我个人在KVM虚拟化环境里配置防火墙的习惯是:宿主机上只开放必需的端口,虚拟机内部业务端口通过NAT或桥接后的独立安全策略管理,尽量不给宿主机通过物理网卡直接暴露VM业务端口的机会,这样即使虚拟机被攻击,也不会让宿主机暴露面扩大。
写到这里,KVM在银河麒麟高级服务器操作系统上的整个搭建过程、虚拟机创建流程、网络桥接配置以及各种常见问题的排查思路,基本都覆盖到了。如果你也是从CentOS或其他Linux发行版转过来的,会发现银河麒麟的KVM操作习惯几乎和它们一模一样,没有太多学习成本。唯一的区别可能集中在对国产化内核版本的适配还有一些底层模块的加载顺序上,只要按照上面的顺序一步一步来,通常不会出什么大问题。
最后分享一个小技巧:在配置任何比较关键的虚拟化参数之前,先virsh dumpxml把当前的配置导出一份,放到一个安全目录里。出了问题或者配置改乱了的时候,直接virsh define导回来,就能快速恢复一个可用的状态。这个习惯帮我省了不止一次救火的时间。