上一篇 下一篇 分享链接 返回 返回顶部

香港物理服务器KVM虚拟化怎么搭建?虚机创建、VirtIO与网络桥接步骤

发布人:Minchunlin 发布时间:2026-10-07 15:23 阅读量:7

要在香港物理服务器上搭建 KVM 虚拟化环境,推荐先明确宿主机与虚拟机的网络关系,再安装 KVM、libvirt 和 VirtIO 组件。下面以 Ubuntu Server 24.04 LTS 作为宿主机和 Linux 虚拟机系统,使用 qemu-kvm + libvirt + virt-install + Netplan Linux 网桥 完成部署,目标是创建一台能够独立启动、通过 VirtIO 连接磁盘和网卡、并接入物理网络的虚拟机。

网络桥接并不是把宿主机的公网 IP 同时分配给虚拟机,而是让宿主机和虚拟机分别拥有独立地址,共同接入物理网卡所在的二层网络。香港机房的上游交换网络可能限制额外 MAC 地址或额外公网 IP,因此在正式修改网卡前,必须确认服务商是否允许桥接、是否提供附加 IP、是否需要登记虚拟机 MAC 地址。

一、部署目标与适用环境配图

围绕香港物理服务器上的 KVM 虚拟化部署,A5数据提供入门建站、Xeon Gold 与 AMD EPYC 等多类硬件平台,结合 SSD、NVMe、DDR5 内存及不同带宽线路,为宿主机运行多台虚拟机、数据库、业务后台和接口服务提供资源基础。香港产品还覆盖多 IP 配置,可配合独立地址分配与桥接网络架构,承载从常规建站到多任务计算的虚拟化场景。

一、部署目标与适用环境

1.1 本文采用的环境

项目示例配置
物理服务器系统Ubuntu Server 24.04 LTS amd64
虚拟化方案KVM/QEMU
管理组件libvirt、virsh、virt-install
宿主机网络Netplan + systemd-networkd + Linux Bridge
虚拟机系统Ubuntu Server 24.04 LTS cloud image
虚拟磁盘qcow2,VirtIO Block
虚拟网卡VirtIO Network
示例虚拟机2 vCPU、4 GB 内存、40 GB 磁盘
网络目标虚拟机通过 br0 直接接入物理网络

示例中的 198.51.100.0/24、203.0.113.0/24 和 192.0.2.0/24 属于文档专用地址,只用于展示配置格式,不能直接填入生产环境。实际地址、网关、掩码、DNS 和 IPv6 参数应以香港物理服务器服务商提供的网络资料为准。

1.2 桥接、NAT 与路由模式的区别

模式虚拟机地址入站访问适用条件
物理网桥与物理网络同一网段或由服务商路由分配可直接访问服务商允许额外 MAC 或额外 IP
libvirt NAT私有地址,例如 192.168.122.0/24默认不能直接入站只有一个公网 IP,先验证虚拟化功能
路由型网络虚拟机使用独立私网或公网网段由宿主机或上游路由转发服务商提供路由网段或允许静态路由

如果服务器只有一个公网 IPv4,且该地址已经配置在宿主机的 br0 上,虚拟机不能重复使用这个地址。此时应申请额外公网 IP,或者先使用 NAT 网络完成 KVM 验证。

桥接模式下,宿主机不需要为了转发虚拟机流量而开启 IPv4 转发。只有 NAT 或路由型网络才需要根据设计启用转发功能。

二、准备条件与风险控制

2.1 确认硬件虚拟化能力

登录物理服务器后先检查系统、CPU 和网卡名称:

cat /etc/os-release
uname -r
lscpu | egrep 'Architecture|CPU\(s\)|Model name|Virtualization'
ip -br link
ip -br addr
ip route

Intel 平台通常显示 VT-x 或 vmx,AMD 平台通常显示 AMD-V 或 svm。也可以直接统计 CPU 标志:

egrep -c '(vmx|svm)' /proc/cpuinfo

返回大于 0 通常说明系统能够看到硬件虚拟化扩展。若返回 0,可能是 BIOS 中没有开启虚拟化,也可能是当前服务器本身运行在不支持嵌套虚拟化的虚拟机中。

ip -br link 的示例结果如下:

lo               UNKNOWN        127.0.0.1/8 ::1/128
eno1             UP

这里的 eno1 只是示例。生产环境可能使用 enp1s0、ens160 或其他名称,后续所有网桥配置都必须替换成实际物理接口名称。

2.2 确认服务商网络限制

在香港机房的物理服务器上部署桥接时,至少核对以下内容:

  • 是否允许一台物理服务器出现多个源 MAC 地址。
  • 额外公网 IP 是否绑定到服务器端口、服务器 MAC,或需要登记虚拟机 MAC。
  • 网关是否与 IP 位于同一网段。
  • 如果公网地址是 /32,服务商是否要求使用 on-link 路由。
  • 是否需要使用特定 VLAN ID。
  • 服务器断开管理网络后,是否能够通过带外控制台、串口控制台或救援系统恢复配置。
  • 是否存在端口安全、ARP 检查、源地址检查或单 MAC 限制。

如果服务商明确禁止额外 MAC,直接把虚拟机接入 br0 后,常见现象是宿主机仍然可以访问公网,但虚拟机无法获取地址、无法访问网关,或者只能单向通信。这类问题不是 KVM 软件安装错误,需要改用 NAT 或路由型网络。

2.3 备份宿主机网络配置

修改远程服务器的网络配置前先备份:

sudo mkdir -p /root/backup
sudo cp -a /etc/netplan /root/backup/netplan-$(date +%F-%H%M%S)
sudo ip addr show > /root/backup/ip-addr-before.txt
sudo ip route show > /root/backup/ip-route-before.txt

如果服务器通过 SSH 远程管理,建议同时保持以下条件:

  • 保留当前 SSH 会话,不要立即关闭。
  • 使用第二个 SSH 会话执行网络变更。
  • 提前打开服务商控制台。
  • 先使用 netplan try,不要一开始就直接执行不可逆的远程网络切换。
  • 不要在没有控制台的情况下执行 iptables -F、nft flush ruleset 或删除所有 Netplan 文件。

三、安装 KVM、libvirt 与虚拟机工具

3.1 安装依赖

以下命令适用于 Ubuntu Server 24.04 LTS:

sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt install -y \
  qemu-kvm \
  libvirt-daemon-system \
  libvirt-clients \
  virtinst \
  qemu-utils \
  cloud-image-utils \
  bridge-utils \
  cpu-checker

启用并检查 libvirt 服务:

sudo systemctl enable --now libvirtd
sudo systemctl is-active libvirtd
sudo systemctl is-enabled libvirtd

预期结果分别为:

active
enabled

检查 KVM 设备和宿主机能力:

ls -l /dev/kvm
sudo virt-host-validate qemu

virt-host-validate 可能显示多项 PASS。个别与图形、IOMMU 或可选功能相关的项目出现 WARN,不一定影响普通 KVM 虚拟机创建;但如果 /dev/kvm 不存在,或者核心 KVM 检查失败,应先处理 BIOS、内核模块或服务器虚拟化层问题。

检查相关内核模块:

lsmod | egrep 'kvm|kvm_intel|kvm_amd'

Intel 主机常见模块包括:

kvm_intel
kvm

AMD 主机常见模块包括:

kvm_amd
kvm

如果没有自动加载,可以根据 CPU 类型手动加载:

sudo modprobe kvm_intel

或:

sudo modprobe kvm_amd

不要在无法确认 CPU 类型时同时强制加载两个厂商模块。修改模块加载文件前,应先通过 lscpu 确认平台。

3.2 检查 libvirt 连接

sudo virsh -c qemu:///system version
sudo virsh -c qemu:///system list --all

qemu:///system 表示连接系统级 libvirt,虚拟机文件通常位于 /var/lib/libvirt/images。不要把生产虚拟机误创建到 qemu:///session,因为会导致存储位置、权限和开机自启行为与系统级实例不同。

如果需要让非 root 用户使用 virsh,可以将用户加入相关组:

sudo usermod -aG libvirt,kvm "$USER"

重新登录后检查:

id
virsh -c qemu:///system list --all

生产环境仍建议使用受控管理账号,并避免给不必要的用户授予修改虚拟机、磁盘或网络的权限。

四、配置物理网卡与 Linux 网桥

4.1 确认当前地址归属

执行:

ip -br addr
ip route

在桥接配置完成后,物理接口通常不再直接持有公网地址,地址应配置在 br0 上。典型结构如下:

eno1       UP
br0        UP             198.51.100.10/24
default via 198.51.100.1 dev br0

如果仍有地址配置在 eno1,可能会出现 ARP、路由或源地址选择异常。

4.2 静态公网地址配置

创建或编辑 Netplan 文件:

sudo nano /etc/netplan/01-br0.yaml

以下配置是静态地址示例,必须替换为服务商实际参数:

四、配置物理网卡与 Linux 网桥配图

network:
  version: 2
  renderer: networkd

  ethernets:
    eno1:
      dhcp4: false
      dhcp6: false

  bridges:
    br0:
      interfaces:
        - eno1
      addresses:
        - 198.51.100.10/24
      routes:
        - to: default
          via: 198.51.100.1
      nameservers:
        addresses:
          - 1.1.1.1
          - 8.8.8.8
      parameters:
        stp: false
        forward-delay: 0

需要注意:

  • eno1 必须替换为真实物理网卡。
  • 宿主机公网地址只配置在 br0,不要同时配置在 eno1。
  • 198.51.100.10/24 和 198.51.100.1 只是文档地址。
  • 如果服务商明确要求 STP,不能擅自关闭;普通单上联服务器通常不需要在主机侧启用 STP。
  • 如果使用 IPv6,应单独补充真实 IPv6 地址、网关和路由,不要因为设置了 dhcp6: false 而误关闭实际需要的 IPv6 服务。

先检查语法:

sudo netplan generate

没有错误输出通常表示 YAML 语法和字段基本正确。远程服务器使用以下命令试运行:

sudo netplan try --timeout 120

命令会临时应用配置并等待确认。确认第二个 SSH 会话、网关和 DNS 均正常后,再确认配置。如果连接中断且没有确认,Netplan 通常会在超时后恢复原配置。

确认后检查:

ip -br addr show br0
ip route
networkctl status br0 --no-pager
bridge link

预期应看到:

  • br0 处于 UP 状态。
  • 宿主机公网地址在 br0 上。
  • 默认路由的设备为 br0。
  • eno1 是 br0 的从接口。
  • br0 没有重复的默认路由。

4.3 DHCP 地址配置

如果服务商网络本身通过 DHCP 分配地址,可以使用下面的配置:

network:
  version: 2
  renderer: networkd

  ethernets:
    eno1:
      dhcp4: false
      dhcp6: false

  bridges:
    br0:
      interfaces:
        - eno1
      dhcp4: true
      dhcp6: false
      parameters:
        stp: false
        forward-delay: 0

执行:

sudo netplan generate
sudo netplan try --timeout 120

DHCP 场景下不需要手动写默认网关,但仍应确认上游是否允许通过桥接接口获取地址。

4.4 /32 地址和特殊网关

部分服务商会提供 /32 主机地址,同时给出一个不在同一子网内的网关。这种情况下,Netplan 需要显式告诉内核网关可以通过当前接口直连。例如:

network:
  version: 2
  renderer: networkd

  ethernets:
    eno1:
      dhcp4: false

  bridges:
    br0:
      interfaces:
        - eno1
      addresses:
        - 203.0.113.10/32
      routes:
        - to: 203.0.113.1/32
          scope: link
        - to: default
          via: 203.0.113.1
          on-link: true
      nameservers:
        addresses:
          - 1.1.1.1
          - 8.8.8.8
      parameters:
        stp: false
        forward-delay: 0

on-link: true 不能套用到所有网络。只有在服务商明确给出这类 /32 路由方式时才使用,否则可能产生错误路由。

4.5 验证宿主机网络

先从宿主机测试网关,再测试公网地址和 DNS:

ping -c 3 198.51.100.1
ping -c 3 1.1.1.1
getent hosts archive.ubuntu.com
curl -4 --connect-timeout 8 -I https://archive.ubuntu.com

如果网关能通但公网地址不通,重点检查默认路由、服务商出口策略和防火墙。如果公网地址能通但域名解析失败,检查 nameservers 和本机解析服务。

不要在此阶段直接创建虚拟机。宿主机网络必须先稳定,否则虚拟机故障与宿主机桥接故障会混在一起。

五、准备虚拟机磁盘与初始化数据

5.1 创建镜像目录并获取系统镜像

确认磁盘空间:

df -h /var/lib/libvirt
sudo mkdir -p /var/lib/libvirt/images

下载 Ubuntu 24.04 cloud image:

cd /var/lib/libvirt/images
sudo wget -O ubuntu-24.04-server-cloudimg-amd64.img \
  https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img

生产环境应根据镜像发布方提供的校验值验证文件:

sha256sum ubuntu-24.04-server-cloudimg-amd64.img

将结果与对应发布页面提供的 SHA256 值比对。不要把未校验的镜像直接用于承载重要业务。

5.2 创建虚拟机磁盘

复制基础镜像作为虚拟机磁盘:

sudo cp --reflink=auto \
  /var/lib/libvirt/images/ubuntu-24.04-server-cloudimg-amd64.img \
  /var/lib/libvirt/images/hk-vm01.qcow2

扩展虚拟磁盘到 40 GB:

sudo qemu-img resize \
  /var/lib/libvirt/images/hk-vm01.qcow2 40G

检查格式和容量:

sudo qemu-img info /var/lib/libvirt/images/hk-vm01.qcow2

qcow2 是精简分配格式,虚拟容量为 40 GB 不代表宿主机立即占用 40 GB。应同时监控底层文件系统空间,避免多个虚拟磁盘过度分配导致宿主机写满。

设置文件权限:

sudo chown libvirt-qemu:libvirt-qemu \
  /var/lib/libvirt/images/hk-vm01.qcow2
sudo chmod 0640 /var/lib/libvirt/images/hk-vm01.qcow2

如果系统中的 QEMU 运行用户不同,应先确认:

ps -ef | grep '[q]emu-system'
getent passwd libvirt-qemu

5.3 编写 cloud-init 用户数据

创建初始化目录:

sudo mkdir -p /var/lib/libvirt/cloud-init/hk-vm01
cd /var/lib/libvirt/cloud-init/hk-vm01

创建 user-data:

#cloud-config
hostname: hk-vm01
manage_etc_hosts: true

users:
  - name: admin
    gecos: Virtual Machine Administrator
    groups:
      - sudo
    shell: /bin/bash
    sudo: ALL=(ALL) NOPASSWD:ALL
    lock_passwd: true
    ssh_authorized_keys:
      - ssh-ed25519 AAAA_REPLACE_WITH_YOUR_PUBLIC_KEY admin@example

ssh_pwauth: false
disable_root: true
package_update: false
package_upgrade: false

final_message: "cloud-init completed after $UPTIME seconds"

ssh_authorized_keys 中的内容必须替换为管理员自己的公钥。不要把示例字符串直接作为生产密钥,也不要在公开文档、工单或脚本中保存私钥。

创建 meta-data:

instance-id: hk-vm01-20240601
local-hostname: hk-vm01

5.4 配置虚拟机网络初始化方式

DHCP 场景

如果上游网络提供 DHCP,可以创建:

version: 2
ethernets:
  ens3:
    dhcp4: true
    dhcp6: false

保存为 network-config.yaml。

静态公网场景

如果服务商为虚拟机提供了独立公网 IP,可以使用:

version: 2
ethernets:
  ens3:
    dhcp4: false
    dhcp6: false
    addresses:
      - 198.51.100.20/24
    routes:
      - to: default
        via: 198.51.100.1
    nameservers:
      addresses:
        - 1.1.1.1
        - 8.8.8.8

这里的 ens3 是 Linux 虚拟机中 VirtIO 网卡常见的接口名,但仍应在虚拟机启动后通过 ip -br link 验证。如果服务商给的是 /32 地址,应按服务商提供的路由方式补充 on-link: true,不能直接照搬 /24 示例。

5.5 创建 cloud-init seed ISO

sudo cloud-localds \
  --network-config=network-config.yaml \
  /var/lib/libvirt/images/hk-vm01-seed.iso \
  user-data \
  meta-data

检查文件:

ls -lh /var/lib/libvirt/images/hk-vm01-seed.iso
sudo file /var/lib/libvirt/images/hk-vm01-seed.iso

设置权限:

sudo chown libvirt-qemu:libvirt-qemu \
  /var/lib/libvirt/images/hk-vm01-seed.iso
sudo chmod 0640 /var/lib/libvirt/images/hk-vm01-seed.iso

cloud-init seed ISO 只在首次初始化时发挥主要作用。修改其中的 SSH 密钥、主机名或网络配置后,已有虚拟机不一定会自动重新执行,需要通过 cloud-init 清理、重新挂载 seed,或者直接在虚拟机内部修改配置。

六、创建并启动 KVM 虚拟机

6.1 使用 virt-install 创建虚拟机

以下命令创建一台 2 vCPU、4 GB 内存、40 GB 磁盘的虚拟机:

六、创建并启动 KVM 虚拟机配图

sudo virt-install \
  --connect qemu:///system \
  --name hk-vm01 \
  --memory 4096 \
  --currentMemory 4096 \
  --vcpus 2 \
  --cpu host-passthrough \
  --osinfo detect=on,require=off \
  --import \
  --disk path=/var/lib/libvirt/images/hk-vm01.qcow2,format=qcow2,bus=virtio,discard=unmap \
  --disk path=/var/lib/libvirt/images/hk-vm01-seed.iso,device=cdrom \
  --network bridge=br0,model=virtio \
  --graphics none \
  --video none \
  --console pty,target_type=serial \
  --noautoconsole

参数作用如下:

  • --connect qemu:///system:使用系统级 libvirt。
  • --import:导入已有 cloud image,不进入传统安装程序。
  • --cpu host-passthrough:将宿主机 CPU 特性尽量提供给虚拟机,适合不考虑跨不同 CPU 主机迁移的场景。
  • bus=virtio:使用 VirtIO 磁盘接口。
  • model=virtio:使用 VirtIO 网卡。
  • discard=unmap:允许虚拟机发送块回收请求,是否真正生效还取决于 qcow2、宿主机文件系统和底层存储。
  • --graphics none:不创建图形控制台。
  • --console pty,target_type=serial:通过串口控制台观察启动状态。

如果 virt-install 的 --osinfo detect=on,require=off 在当前版本不被接受,可以先查询可用系统类型:

osinfo-query os | grep -i ubuntu

再将参数替换为查询结果中的有效值。不要因为系统识别失败而随意指定与实际系统不符的版本,尤其是在启用 UEFI、设备模型或驱动优化时。

6.2 启动与查看虚拟机

sudo virsh start hk-vm01
sudo virsh domstate hk-vm01
sudo virsh dominfo hk-vm01

预期状态:

running

连接串口控制台:

sudo virsh console hk-vm01

退出控制台通常使用:

Ctrl + ]

查看虚拟机网卡、磁盘和地址信息:

sudo virsh domiflist hk-vm01
sudo virsh domblklist hk-vm01
sudo virsh domifaddr hk-vm01

对于桥接网络,domifaddr 不一定能立即显示地址,因为 libvirt 未必能从桥接流量中自动获得 DHCP 租约。此时应以虚拟机内部的 ip addr 为准。

6.3 设置开机自动启动

确认虚拟机首次启动和登录正常后,再设置自启:

sudo virsh autostart hk-vm01
sudo virsh dominfo hk-vm01 | grep -i autostart

预期:

Autostart:      enable

宿主机重启后,libvirt 服务需要正常启动,虚拟机才会按照自启标记启动。因此还要检查:

systemctl is-enabled libvirtd

七、验证 VirtIO 驱动与网络桥接

7.1 宿主机检查桥接关系

ip link show master br0
bridge link show
sudo virsh domiflist hk-vm01

示例状态:

Interface  Type       Source  Model    MAC
------------------------------------------------
vnet0      bridge     br0     virtio   52:54:00:xx:xx:xx

桥接中通常可以看到:

  • 物理接口 eno1 从属于 br0。
  • 虚拟接口 vnet0 从属于 br0。
  • 虚拟机网卡模型为 virtio。
  • 虚拟机 MAC 地址唯一。

进一步查看转发表:

bridge fdb show br br0

如果虚拟机已启动并产生流量,通常能看到对应 MAC 地址在 vnet0 上学习到。没有 MAC 学习记录时,检查虚拟机是否真正启动、网卡是否启用,以及 virsh domiflist 是否显示正确的桥接源。

7.2 虚拟机内部检查网卡

登录虚拟机后执行:

ip -br link
ip -br addr
ip route

安装检查工具:

sudo apt update
sudo apt install -y ethtool pciutils

检查 VirtIO 网卡驱动:

sudo ethtool -i ens3

典型结果:

driver: virtio_net
version: 1.0
firmware-version:
bus-info: virtio0

如果接口名称不是 ens3,先执行:

ip -br link

再把命令中的接口名替换为实际名称。

检查虚拟磁盘:

lsblk -d -o NAME,MODEL,TRAN,SIZE
sudo lspci -nnk

Ubuntu cloud image 中磁盘常见名称是 vda,网卡驱动常见为 virtio_net。如果磁盘显示为 vda,通常说明已经使用 VirtIO Block;如果网卡驱动显示为 virtio_net,说明 VirtIO 网络驱动已加载。

Linux 内核通常已经内置这些驱动,不需要另行安装。Windows 虚拟机则应在安装系统前准备对应的 VirtIO 驱动介质,并在安装存储控制器或网卡时加载驱动。将已部署系统从 SATA/IDE 磁盘直接切换到 VirtIO 磁盘存在无法启动的风险,必须先创建快照或完整备份,并保留原磁盘控制器作为回滚路径。

7.3 验证虚拟机网络

依次从低层到高层测试:

ip route
ping -c 3 198.51.100.1
ping -c 3 1.1.1.1
getent hosts archive.ubuntu.com
curl -4 --connect-timeout 8 -I https://archive.ubuntu.com

不同结果对应不同判断:

七、验证 VirtIO 驱动与网络桥接配图

  • 虚拟机没有地址:先查 cloud-init、静态配置、DHCP 和网卡状态。
  • 能通网关但不能通公网:查默认路由、服务商出口策略和上游 ACL。
  • 能通公网 IP 但不能解析域名:查 DNS。
  • DNS 正常但 HTTPS 失败:查虚拟机防火墙、时间同步、MTU 和上游访问策略。
  • 宿主机正常、虚拟机完全不能访问:重点检查额外 MAC 限制和桥接转发。

确认 SSH 服务只监听预期地址:

sudo ss -lntup

如果启用了 UFW,只开放实际需要的端口:

sudo ufw status verbose
sudo ufw allow 22/tcp

执行防火墙调整前要确认当前 SSH 端口和管理来源。不要在远程会话中直接重置全部防火墙规则,以免同时中断宿主机和虚拟机管理链路。

八、常见异常与处理顺序

8.1 /dev/kvm 不存在

检查:

ls -l /dev/kvm
egrep -c '(vmx|svm)' /proc/cpuinfo
dmesg | grep -i kvm

处理方向:

  • BIOS 未开启硬件虚拟化。
  • 当前系统运行在不支持嵌套虚拟化的环境中。
  • 内核模块没有加载。
  • 服务器厂商限制了虚拟化扩展。

不要通过修改虚拟机配置绕过 /dev/kvm 缺失问题。QEMU 可以在部分场景下使用软件模拟,但性能和部署目标不适合普通生产虚拟机。

8.2 修改桥接后 SSH 断开

优先使用第二个 SSH 会话或带外控制台确认:

ip -br addr
ip route
networkctl status br0 --no-pager
journalctl -u systemd-networkd -b --no-pager -n 100

如果 netplan try 尚未确认,等待超时自动回滚。如果已经执行了 netplan apply,通过控制台恢复备份文件,再重新生成配置:

sudo cp -a /root/backup/netplan-YYYY-MM-DD-HHMMSS/. /etc/netplan/
sudo netplan generate
sudo netplan apply

其中目录名必须替换为实际备份目录。恢复操作会再次触发网络切换,应在控制台或可靠的第二会话中进行。

8.3 宿主机正常,虚拟机无法获取地址

检查虚拟机网卡来源:

sudo virsh domiflist hk-vm01
bridge link show

检查虚拟机接口状态:

ip -br link
sudo ethtool ens3

如果使用 DHCP,确认上游 DHCP 服务是否允许第二个 MAC。很多数据中心公网网络并不提供给虚拟机自动分配地址,即使宿主机地址来自 DHCP,虚拟机也可能无法获得租约。

如果静态地址配置正确但仍不能通信,检查:

  • 虚拟机 IP 是否与宿主机重复。
  • 网关和掩码是否使用服务商给出的值。
  • 虚拟机 MAC 是否需要登记。
  • 端口是否限制多个源 MAC。
  • 是否误把公网地址配置在了宿主机和虚拟机两端。

8.4 虚拟机能通网关但无法访问公网

检查虚拟机默认路由:

ip route

正常情况下应存在类似:

default via 198.51.100.1 dev ens3

再检查宿主机是否误启用了复杂的过滤规则:

sudo nft list ruleset
sudo ufw status verbose

不要直接清空现有规则。先确认规则是否针对 br0、vnet0 或相关转发链,并按照现有防火墙策略增加最小放行项。

如果宿主机和虚拟机均配置了同一公网 IP,会出现 ARP 抖动、连接随机中断和地址漂移。此时应立即停止虚拟机或移除重复地址,恢复唯一地址分配。

8.5 虚拟机没有 VirtIO 网卡

检查虚拟机 XML:

sudo virsh dumpxml hk-vm01 | grep -A8 -B2 '

应能看到类似配置:



如果使用了其他模型,可以通过 virsh edit 修改,但修改前应先关机并备份 XML:

sudo virsh dumpxml hk-vm01 > /root/hk-vm01.xml.backup
sudo virsh shutdown hk-vm01
sudo virsh edit hk-vm01

修改 XML 属于直接变更虚拟硬件配置,错误的 XML 可能导致虚拟机无法启动。完成后使用:

sudo virsh define /root/hk-vm01.xml.backup

进行恢复时,必须确认备份文件是目标版本,而不是旧配置。

8.6 虚拟机无法从磁盘启动

检查磁盘和启动顺序:

sudo virsh domblklist hk-vm01
sudo virsh dumpxml hk-vm01 | grep -E '

常见原因包括:

  • 使用了错误架构的镜像。
  • 镜像文件下载不完整。
  • --import 未使用,导致启动流程不符合 cloud image。
  • qcow2 文件权限不允许 QEMU 读取。
  • seed ISO 被当成主启动盘。
  • 镜像本身没有适合当前启动模式的引导结构。

确认权限:

namei -l /var/lib/libvirt/images/hk-vm01.qcow2

不要在未备份的情况下使用 qemu-img convert 覆盖原盘。转换到新文件并验证后,再考虑替换生产磁盘。

8.7 香港机房上游限制额外 MAC

可以使用抓包辅助判断,但抓包内容可能包含公网通信数据,应限制权限和时间:

sudo tcpdump -ni br0 'arp or icmp'

如果虚拟机发出的 ARP 请求能够在 br0 看到,但没有收到网关响应,同时宿主机正常,较大概率是上游端口策略、MAC 白名单或 IP-MAC 绑定问题。

处理顺序应为:

  1. 在服务商控制面板登记虚拟机 MAC。
  2. 确认额外公网 IP 已绑定到服务器。
  3. 确认是否需要关闭源地址检查或申请桥接权限。
  4. 如果无法解除限制,改用 NAT 或路由型网络。

九、NAT 作为临时回退方案

如果服务商暂时不允许桥接,可以使用 libvirt 默认 NAT 网络验证虚拟机本身是否正常。确认默认网络状态:

sudo virsh net-list --all

启动并设置自启:

sudo virsh net-start default
sudo virsh net-autostart default

创建 NAT 虚拟机时,把网络参数从:

--network bridge=br0,model=virtio

改为:

--network network=default,model=virtio

启动后查看 DHCP 租约:

sudo virsh net-dhcp-leases default

NAT 模式下,虚拟机一般可以主动访问外部网络,但不能直接使用独立公网地址。需要从公网访问虚拟机时,应额外设计端口映射、路由或应用层接入方式,不应把 NAT 误认为公网桥接。

NAT 回退不会解决服务商对公网额外 MAC 的限制,但可以将问题拆分为两部分:先验证 KVM、VirtIO、磁盘和虚拟机系统,再单独处理公网网络接入。

十、上线前验收项目

10.1 宿主机验收

sudo systemctl is-active libvirtd
sudo systemctl is-enabled libvirtd
sudo virt-host-validate qemu
ip -br addr show br0
ip route
bridge link show
df -h /var/lib/libvirt

验收要点:

  • libvirtd 为 active 且设置为开机启动。
  • /dev/kvm 存在,核心虚拟化检查通过。
  • br0 处于 UP 状态。
  • 宿主机 IP 和默认路由位于 br0。
  • 物理网卡属于 br0。
  • 虚拟机镜像所在文件系统有足够余量。

10.2 虚拟机验收

sudo virsh domstate hk-vm01
sudo virsh dominfo hk-vm01
sudo virsh domiflist hk-vm01
sudo virsh domblklist hk-vm01
sudo virsh autostart hk-vm01

进入虚拟机后:

hostnamectl
ip -br addr
ip route
sudo ethtool -i ens3
lsblk -d -o NAME,MODEL,TRAN,SIZE
systemctl is-system-running

核心验收结果应包括:

  • 虚拟机状态为 running。
  • vCPU 和内存配置符合计划。
  • 网卡源为 br0,模型为 virtio。
  • 磁盘以 vda 或其他 VirtIO 设备出现。
  • ethtool -i 显示 virtio_net。
  • SSH 密钥登录成功,密码登录符合安全策略。
  • 能够访问网关、外部 IP 和 DNS。
  • 宿主机重启后虚拟机能够自动启动。

10.3 服务暴露面检查

虚拟机上线前查看监听端口:

sudo ss -lntup

仅开放业务所需端口,并确认管理端口来源受到限制。宿主机和虚拟机应分别维护防火墙策略,不要因为使用了桥接就默认认为虚拟机继承了宿主机的安全规则。

十一、回滚与清理操作

11.1 回滚宿主机网桥

如果桥接配置导致宿主机网络异常:

  1. 通过第二个 SSH 会话或带外控制台登录。
  2. 找到之前保存的备份目录。
  3. 恢复 Netplan 文件。
  4. 重新生成并应用配置。
  5. 检查 br0、路由和 SSH。

示例:

sudo ls -ld /root/backup/netplan-*
sudo cp -a /root/backup/netplan-YYYY-MM-DD-HHMMSS/. /etc/netplan/
sudo netplan generate
sudo netplan try --timeout 120

如果原始配置不是桥接,而是直接使用 eno1,恢复后应确认公网地址重新位于 eno1,而不是残留在 br0。

11.2 回滚虚拟机网络

如果只有虚拟机网络不通,可以先关机,再将虚拟机接口从桥接改为 NAT:

sudo virsh shutdown hk-vm01
sudo virsh edit hk-vm01

将接口来源从:


改为类似:


保存后启动:

sudo virsh start hk-vm01
sudo virsh domiflist hk-vm01

如果系统内部保存了静态公网配置,切换到 NAT 后还需要改回 DHCP 或 NAT 网段配置,否则虚拟机仍可能保留不可达的公网地址。

11.3 删除虚拟机但保留磁盘

先关闭虚拟机:

sudo virsh shutdown hk-vm01

确认状态:

sudo virsh domstate hk-vm01

再解除定义:

sudo virsh undefine hk-vm01

该操作通常只删除 libvirt 定义,不会自动删除磁盘。需要保留数据时,确认磁盘文件仍然存在:

ls -lh \
  /var/lib/libvirt/images/hk-vm01.qcow2 \
  /var/lib/libvirt/images/hk-vm01-seed.iso

11.4 删除虚拟机及其磁盘

只有在确认不需要恢复、已完成备份并核对目标文件名后,才删除磁盘:

sudo virsh shutdown hk-vm01
sudo virsh undefine hk-vm01
sudo rm -f \
  /var/lib/libvirt/images/hk-vm01.qcow2 \
  /var/lib/libvirt/images/hk-vm01-seed.iso
sudo rm -rf /var/lib/libvirt/cloud-init/hk-vm01

rm -f 不会进入回收站,路径错误可能造成不可恢复的数据删除。生产环境应先执行 ls -lh,并使用虚拟机名称、磁盘 UUID 或备份清单进行二次核对。

11.5 最终回滚清单

  • 宿主机 Netplan 原始目录已备份。
  • 物理网卡原始 IP 和默认路由已记录。
  • 虚拟机 XML 已导出。
  • 虚拟机磁盘已有可恢复副本或快照。
  • 虚拟机可以在 br0 与 NAT 网络之间切换。
  • 服务商已确认额外 MAC、额外 IP 和 VLAN 规则。
  • 删除操作没有误触宿主机系统盘或其他虚拟机磁盘。
  • 通过控制台验证了网络断开后的恢复路径。
  • 宿主机和虚拟机均完成重启后验收。