手上有一台闲置的物理服务器,想把开发、测试、生产环境隔开,或者想把几台老业务机器收敛到一台高配机器上——这时候自建 KVM 虚拟化是最现实的方案。KVM(Kernel-based Virtual Machine,基于内核的虚拟机)已经是 Linux 内核的一部分,配合 libvirt 做管理、qemu 做设备模拟,性能接近原生,而且完全免费。但在实操中,从"装完包"到"虚拟机能上网、能跑满磁盘",中间有不少坑:VNC 连不上、装完系统没网、磁盘 IO 奇慢、虚拟机重启后 IP 变了。本文按真实部署顺序,把 KVM 虚拟化服务器创建虚拟机的完整流程讲一遍,包括网络模式选择、磁盘格式与总线、CPU 与内存分配,以及后期的热调整。
一、部署前:确认宿主机支持虚拟化并装好组件
第一步不是装软件,而是确认 CPU 打开了硬件辅助虚拟化,并且在 BIOS 里是启用状态。很多"装完 libvirt 才发现用不了"的情况,根源都在 BIOS 里 VT-x / AMD-V 被关掉了。
# 1. 确认 CPU 支持硬件虚拟化(输出大于 0 即可) egrep -c '(vmx|svm)' /proc/cpuinfo # vmx = Intel VT-x,svm = AMD-V # 2. 确认内核模块已加载 lsmod | grep kvm # 应看到 kvm、kvm_intel 或 kvm_amd # 3. 若模块未加载,手动加载并检查设备节点 modprobe kvm modprobe kvm_intel # AMD 机器用 modprobe kvm_amd ls -l /dev/kvm # 4. 确认宿主机自身不是虚拟机(嵌套虚拟化需额外配置) systemd-detect-virt
组件安装。RHEL/CentOS/Rocky 系列与 Debian/Ubuntu 系列的包名不同,注意区分:
# RHEL / CentOS / Rocky / AlmaLinux yum install -y qemu-kvm libvirt virt-install virt-manager bridge-utils libguestfs-tools systemctl enable --now libvirtd # Debian / Ubuntu apt install -y qemu-kvm libvirt-daemon-system libvirt-clients virtinst bridge-utils libguestfs-tools systemctl enable --now libvirtd # 验证服务与默认网络 systemctl status libvirtd virsh list --all virsh net-list --all
装完后 libvirt 会自带一个名为 default 的 NAT 网络,网段通常是 192.168.122.0/24,宿主机上会多出一张 virbr0 网桥。它能让虚拟机访问外网,但外部无法主动访问虚拟机——这也是后面要重点改造的地方。
二、网络配置:三种模式怎么选
网络是 KVM 虚拟机最容易出问题的环节。libvirt 提供三种典型模式,选择依据是"虚拟机需不需要被外部网络直接访问"。
| 模式 | 实现方式 | 外部能否直接访问虚拟机 | 典型场景 |
|---|---|---|---|
| NAT(默认) | virbr0 + iptables/nftables MASQUERADE,网段 192.168.122.0/24 | 不能,需端口转发 | 开发测试机、只需出网 |
| 桥接(Bridge) | 虚拟网卡桥接到物理网卡,虚拟机与宿主机同网段 | 能,虚拟机有独立 IP | 生产业务、对外提供服务 |
| 仅主机 / 隔离网络 | libvirt 创建但不接外网 | 不能 | 集群内网、数据库内网 |
2.1 创建桥接网卡
生产环境几乎都要用桥接,否则每台虚拟机都要做一次端口转发,管理成本极高。CentOS 7 及以前用 ifcfg 文件,RHEL 8/9 和 Ubuntu 建议统一用 nmcli,改错的概率更低。
# 查看当前连接名(记下物理网卡的连接名,如 eth0 / ens33 / enp1s0) nmcli connection show # 创建桥接接口 br0 nmcli connection add type bridge con-name br0 ifname br0 nmcli connection modify br0 ipv4.addresses 192.168.1.10/24 nmcli connection modify br0 ipv4.gateway 192.168.1.1 nmcli connection modify br0 ipv4.dns "223.5.5.5 8.8.8.8" nmcli connection modify br0 ipv4.method manual # 把物理网卡挂到桥上(这条命令会断开一次网络,请在本地控制台操作) nmcli connection add type bridge-slave con-name br0-slave ifname ens33 master br0 # 关闭原物理网卡连接并启用 br0 nmcli connection down ens33 nmcli connection up br0 # 验证 ip link show type bridge brctl show ip addr show br0
如果用传统 ifcfg 方式,配置大致是:
# /etc/sysconfig/network-scripts/ifcfg-br0 DEVICE=br0 TYPE=Bridge ONBOOT=yes BOOTPROTO=static IPADDR=192.168.1.10 PREFIX=24 GATEWAY=192.168.1.1 DNS1=223.5.5.5 DELAY=0 # /etc/sysconfig/network-scripts/ifcfg-ens33 DEVICE=ens33 TYPE=Ethernet ONBOOT=yes BRIDGE=br0 # 关键:物理网卡不再配 IP,只做桥的从属 # 删除或注释 IPADDR / PREFIX / GATEWAY
2.2 自定义 libvirt 网络
# 查看已有网络 virsh net-list --all virsh net-info default virsh net-dumpxml default # 定义一个新的隔离网络(用于集群内网) cat > /tmp/cluster-net.xml <<'EOF'EOF virsh net-define /tmp/cluster-net.xml virsh net-start cluster virsh net-autostart cluster cluster
三、磁盘:格式、总线与预分配策略
KVM 虚拟机的磁盘是一个宿主机上的镜像文件(或逻辑卷 / 块设备)。格式和总线选错,性能可能差一倍以上。
| 镜像格式 | 特点 | 适用 |
|---|---|---|
| raw | 无元数据开销,性能最好,可直接挂载,但不支持快照、创建即占满空间(除非用稀疏文件) | 性能敏感、数据库盘 |
| qcow2 | 写时复制、按需增长、支持快照与压缩、支持加密 | 通用场景、需要快照 |
总线方面,一定要用 virtio。默认的 IDE 模拟每次 I/O 都要多次 VM Exit(虚拟机退出到宿主机),随机写性能可能只有 virtio 的十分之一。网卡同理,model=virtio 才能跑满带宽。
# 创建 40G 的 qcow2 镜像(稀疏文件,实际占用随写入增长)
qemu-img create -f qcow2 /var/lib/libvirt/images/vm01.qcow2 40G
# 创建预分配元数据的 qcow2(写入性能更稳定,创建稍慢)
qemu-img create -f qcow2 -o preallocation=metadata \
/var/lib/libvirt/images/vm01.qcow2 40G
# 创建 raw 稀疏文件
qemu-img create -f raw /var/lib/libvirt/images/vm01.raw 40G
# 查看镜像信息与实际占用
qemu-img info /var/lib/libvirt/images/vm01.qcow2
ls -lh /var/lib/libvirt/images/vm01.qcow2
# 离线扩容(先扩镜像,再在虚拟机内扩分区与文件系统)
qemu-img resize /var/lib/libvirt/images/vm01.qcow2 +20G
# 格式转换
qemu-img convert -f qcow2 -O raw vm01.qcow2 vm01.raw
# 检查镜像一致性(操作镜像前建议做一次)
qemu-img check /var/lib/libvirt/images/vm01.qcow2
四、创建虚拟机:virt-install 完整命令
建议用 virt-install 命令行创建,便于复制、审计和批量化,图形化的 virt-manager 适合临时排查。先看看系统支持哪些 --os-variant:
osinfo-query os | egrep -i 'centos|rocky|ubuntu|debian|windows|openEuler' # --os-variant 会告诉 libvirt 优化时钟、默认设备型号和驱动,务必填准确
一条完整的创建命令(桥接网络 + virtio 磁盘网卡 + VNC 安装):
virt-install \ --name vm01 \ --os-variant centos8 \ --vcpus 2,maxvcpus=8 \ --memory 4096,maxmemory=16384 \ --disk path=/var/lib/libvirt/images/vm01.qcow2,format=qcow2,bus=virtio,cache=none,io=native \ --cdrom /data/iso/CentOS-8-x86_64-Minimal.iso \ --network bridge=br0,model=virtio \ --graphics vnc,listen=0.0.0.0,port=5901 \ --console pty,target_type=serial \ --boot cdrom,hd,menu=on \ --noautoconsole
各关键参数说明:
--vcpus 2,maxvcpus=8:当前 2 个 vCPU,最多可热加到 8 个,为后续扩容留口子。--memory 4096,maxmemory=16384:单位 MiB,同样预留热扩容上限。cache=none,io=native:绕过宿主机页缓存,配合 SSD 可降低延迟、避免双缓存;如果底层是机械盘或者内存非常紧张,可改用cache=writeback。--graphics vnc,listen=0.0.0.0:默认只监听 127.0.0.1,远程安装必须放开;生产环境应配合防火墙限制来源 IP。--console pty,target_type=serial:装完系统后可用virsh console直接进终端,不必依赖 VNC。- 如果用网络安装源,把
--cdrom换成--location http://mirrors.example.com/centos/8/os/x86_64/并加--extra-args "console=ttyS0"。
# 查看 VNC 端口,用客户端连过去完成系统安装 virsh vncdisplay vm01 # 安装过程中常用的域管理命令 virsh list --all virsh dominfo vm01 virsh start vm01 virsh shutdown vm01 # ACPI 关机,优雅 virsh destroy vm01 # 强制断电,等同拔电源,慎用 virsh reboot vm01 virsh autostart vm01 # 宿主机开机后自动拉起 virsh autostart --disable vm01
五、资源调整:CPU、内存、磁盘的热扩容与绑定
虚拟机创建后,资源不是一成不变的。libvirt 支持相当多的在线调整,但内存只能热减不能热加超过 maxmemory,CPU 热加需要 guest 内核配合,磁盘扩容要在 guest 内做两步。
5.1 CPU 调整与绑定
# 查看 vCPU 与物理 CPU 的映射关系 virsh vcpuinfo vm01 # 把 vCPU 0 绑定到物理 CPU 2(减少跨 NUMA 访问,降低抖动) virsh vcpupin vm01 0 2 virsh vcpupin vm01 1 3 # 热增加 vCPU(需先配置过 maxvcpus,且 guest 内要上线新 CPU) virsh setvcpus vm01 4 --live # guest 内确认 echo 1 > /sys/devices/system/cpu/cpu2/online lscpu # 配置写入持久化(--config 影响下次启动的定义) virsh setvcpus vm01 4 --config
5.2 内存调整与 NUMA
# 热调整内存(不能超过 maxmemory) virsh setmem vm01 8192 --live virsh setmem vm01 8192 --config # 查看内存实际用量(statm 中的"实际使用"比分配值更有参考价值) virsh dommemstat vm01 # NUMA 绑定,把虚拟机固定在 node 0 上 virsh numatune vm01 --nodeset 0 --mode strict # 查看宿主机 NUMA 拓扑,决定绑定策略 numactl --hardware lstopo-no-graphics # 需安装 hwloc
5.3 磁盘在线扩容(两步缺一不可)
# 第一步:宿主机上扩虚拟磁盘 virsh blockresize vm01 vda 60G # 或 virsh blockresize --domain vm01 --path /var/lib/libvirt/images/vm01.qcow2 --size 60G # 第二步:虚拟机内扩分区与文件系统 # 先确认磁盘已变大 lsblk fdisk -l /dev/vda # 场景 A:LVM pvresize /dev/vda2 lvextend -l +100%FREE /dev/mapper/centos-root xfs_growfs / # XFS # 或 resize2fs /dev/mapper/centos-root # ext4 # 场景 B:直接分区(无 LVM),用 growpart 扩分区号 growpart /dev/vda 2 xfs_growfs / df -h
5.4 快照与克隆
# 创建快照(qcow2 格式支持)
virsh snapshot-create-as vm01 --name snap-before-upgrade \
--description "2024-10-14 升级前" --atomic
virsh snapshot-list vm01
virsh snapshot-info vm01 snap-before-upgrade
virsh snapshot-revert vm01 snap-before-upgrade
virsh snapshot-delete vm01 snap-before-upgrade
# 克隆一台新虚拟机(源机需关机或处于一致状态)
virt-clone -o vm01 -n vm02 -f /var/lib/libvirt/images/vm02.qcow2
# 克隆后要改 hostname、删除 machine-id、重生成 SSH host key
cat /dev/null > /etc/machine-id
systemd-machine-id-setup
rm -f /etc/ssh/ssh_host_*
ssh-keygen -A
六、日常运维与故障排查清单
- 虚拟机起不来:先看
virsh list --all状态,再看日志/var/log/libvirt/qemu/vm01.log。 - libvirtd 连不上:检查
systemctl status libvirtd,普通用户需加入libvirt组,或使用virsh -c qemu:///system。 - 虚拟机没网:确认宿主机
br0有 IP、物理网卡已slave到 br0、虚拟机网卡model=virtio、guest 内网卡已ONBOOT=yes。 - 磁盘 IO 慢:确认
bus=virtio、cache=none、宿主机磁盘未做 RAID 降级、镜像未放在 NFS 上做同步写。 - VNC 连不上:确认
--graphics vnc,listen=0.0.0.0,防火墙放行 5900+ 端口,virsh vncdisplay查实际端口。 - 时钟漂移:确认
--os-variant正确,Linux guest 建议启用kvm-clock,Windows guest 安装 virtio 驱动并配置 NTP。 - 宿主机内存被吃光:检查是否给虚拟机分配了过量内存,或宿主机开启了 KSM(Kernel Samepage Merging)导致 CPU 上升。
# 常用排查命令合集 virsh domstats vm01 # 一次性拿到 CPU/内存/磁盘/网络统计 virsh domblklist vm01 # 磁盘列表 virsh domiflist vm01 # 网卡列表 virsh domifstat vm01 vnet0 # 网卡流量 virsh domblkstat vm01 vda # 磁盘 I/O 统计 journalctl -u libvirtd -f # libvirtd 日志 ls /var/log/libvirt/qemu/ # 各虚拟机日志目录
小结
KVM 虚拟化服务器创建虚拟机的标准路径是:确认硬件虚拟化 → 装 libvirt 组件 → 规划网络(生产用桥接)→ 建 virtio 磁盘镜像 → virt-install 创建 → VNC 装系统 → 按需做 CPU/内存/磁盘调整。看起来步骤多,但真正决定长期可用性的只有三件事:网络模式选对、磁盘总线用 virtio、资源上限在创建时就预留。这三件事在创建时花五分钟,能省掉后面无数次停机维护。
避坑建议:
- 新建虚拟机一定要写
--os-variant,否则时钟和设备默认值可能不合适,Windows 会出现时间越走越慢。 - 内存热加受
maxmemory限制,创建时就要把上限设大;CPU 同理用maxvcpus。 - 生产环境慎用
virsh destroy,它等价于拔电源,可能造成文件系统损坏。 - 快照不是备份。qcow2 快照链越长 I/O 越慢,且宿主机 disk 损坏时快照一起丢,重要数据必须另外做异地备份。
- 不要把所有虚拟机的镜像放在同一块机械盘上,随机 IOPS 会成为整个宿主机的瓶颈。
- 给宿主机留资源:建议宿主机自己保留 2-4GB 内存和 1-2 个物理核心,不要让虚拟机把资源分干净。
延伸阅读:虚拟机网络不通是自建虚拟化最高频的问题,通常与桥接配置、虚拟交换机和防火墙规则有关,可结合网络排查类文章一起看。
企业QQ咨询




