Chase's Daily Chase's Daily
Chase's Daily
© 2026 Chasedaily.cn 版权所有. 本网站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议, 转载请注明出处 京ICP备2026068377号-1

VirtFusion 被控节点部署实录:私有 /31 传输段 + 公网 /24 三层路由环境下的桥接与存储规划

摘要:本文记录一台裸金属服务器在"上游只给一个私有 /31 传输段 + 一段公网 /24 三层路由"的特殊网络结构下,如何完成 VirtFusion 被控节点(Hypervisor)的安装、存储规划、网络改造与首台虚拟机验收。文中包含全部输入命令与服务器回显,可直接照抄。

1. 环境与拓扑

1.1 硬件与软件

项目配置
CPU / 内存x86_64(支持 VT-x/AMD-V),约 4 TB RAM
系统盘1.92 TB NVMe(GPT:EFI 100 MB + 根分区 1.8 T)
数据盘15.36 TB NVMe(初始无分区表,4Kn 原生扇区)
操作系统Debian 13 (Trixie),x86_64
面板VirtFusion 7.x(控制端 Control Server 已独立部署完成)
网络单网卡 enp1s0f0np0(万兆/25G 光口)

1.2 上游网络结构

这是本次部署最特殊的地方,务必先理解清楚:

                    ┌────────────────────────────┐
                    │        上游路由器           │
                    │      10.0.0.74/31          │
                    └─────────────┬──────────────┘
                                  │ 私有 /31 传输段(点对点)
                                  │
                    ┌─────────────┴──────────────┐
                    │      被控节点(本机)        │
                    │  enp1s0f0np0                │
                    │    ├─ 10.0.0.75/31          │  ← 传输段地址
                    │    └─ 203.0.113.1/32        │  ← 宿主机公网地址
                    │  默认路由: via 10.0.0.74    │
                    │            src 203.0.113.1  │
                    └─────────────┬──────────────┘
                                  │ 三层路由:203.0.113.0/24 → 10.0.0.75
                    ┌─────────────┴──────────────┐
                    │  公网块 203.0.113.0/24      │
                    │  .1 = 宿主机                │
                    │  .2 ~ .253 = 客户虚拟机     │
                    └────────────────────────────┘

原始 /etc/network/interfaces:

root@sg-hv-01:~# cat /etc/network/interfaces
source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto enp1s0f0np0
iface enp1s0f0np0 inet static
    address 10.0.0.75/31
    gateway 10.0.0.74
    dns-nameservers 1.1.1.1
    dns-nameservers 8.8.8.8
    post-up ip addr replace 203.0.113.1/24 dev enp1s0f0np0
    post-up ip route replace default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1
root@sg-hv-01:~# ip route
default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1
10.0.0.74/31 dev enp1s0f0np0 proto kernel scope link src 10.0.0.75
203.0.113.0/24 dev enp1s0f0np0 proto kernel scope link src 203.0.113.1

root@sg-hv-01:~# ip route get 8.8.8.8
8.8.8.8 via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1 uid 0
    cache

三个关键结论:

  1. 上游把整段 203.0.113.0/24 三层路由到传输段地址 10.0.0.75,而不是把公网段放在二层同网段。
  2. 默认路由的源地址被显式钉在 203.0.113.1(否则出网会拿 10.0.0.75 当源地址)。
  3. 宿主机上把 /24 直接配在物理网卡上(上游模板的写法)——这是后续所有网络问题的根源,第 6 节会详细说明。

2. 部署前检查

root@sg-hv-01:~# fdisk -l
Disk /dev/nvme0n1: 1.75 TiB, 1920383410176 bytes          # 系统盘
Disk model: 1.92TB NVMe
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
Disklabel type: gpt
Device          Start        End    Sectors   Size Type
/dev/nvme0n1p1   2048     206847     204800   100M EFI System
/dev/nvme0n1p2 206848 3750746847 3750540000   1.8T Linux filesystem

Disk /dev/nvme1n1: 13.97 TiB, 15360000000000 bytes        # 数据盘(无分区表)
Disk model: 15.36TB NVMe
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
root@sg-hv-01:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p2  1.8T  814M  1.7T   1% /
/dev/nvme0n1p1   99M  9.0M   90M  10% /boot/efi

root@sg-hv-01:~# free -g
               total        used        free      shared  buff/cache   available
Mem:            4095           1        4088           0           6        4094

检查硬件虚拟化(KVM 是硬性前提):

root@sg-hv-01:~# ls -l /dev/kvm
crw-rw---- 1 root kvm 10, 232 Oct 15 15:40 /dev/kvm

root@sg-hv-01:~# grep -oE 'vmx|svm' /proc/cpuinfo | sort -u
vmx
注意:数据盘为 4Kn 原生扇区(logical/physical 均为 4096),格式化与分区对齐都需按 4K 处理。

3. 存储规划

3.1 设计目标

用途方案
虚拟机磁盘15.36 TB NVMe → ext4 → 挂载 /homedata
交换空间系统盘上 4 GiB swapfile
虚拟机数据最终落点/homedata/vf-data/disk(通过面板指定)

3.2 为什么 swap 用文件而不是分区

根分区 nvme0n1p2 已经从 206848 扇区占到磁盘末尾(3750746847),没有任何空闲空间。要划出独立的 swap 分区,必须:

  1. 用救援系统(IPMI 挂载 ISO)离线 e2fsck + resize2fs 缩小已占满整盘的根文件系统;
  2. 重建分区表并新增分区。

而内核与 KVM/QEMU 对待 swapfile 与 swap 分区没有实质区别,收益为零、风险极高。因此采用 swapfile。本机内存充裕,交换空间仅作为极端情况下的兜底、不作为日常内存扩展,因此设置为 4 GiB。

3.3 15.36 TB 数据盘:ext4 参数选择

root@sg-hv-01:~# wipefs -a /dev/nvme1n1
root@sg-hv-01:~# parted -s /dev/nvme1n1 mklabel gpt
root@sg-hv-01:~# parted -s /dev/nvme1n1 mkpart primary ext4 1MiB 100%
root@sg-hv-01:~# partprobe /dev/nvme1n1; udevadm settle
root@sg-hv-01:~# mkfs.ext4 -m 0 -T largefile -L homedata /dev/nvme1n1p1
mke2fs 1.47.2 (1-Jan-2025)
Discarding device blocks: done
Creating filesystem with 3749992960 4k blocks and 14648409 inodes
Filesystem UUID: 7c4e1d92-58ab-4f36-9c0d-2b7e5a1f8d64
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, ...
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

两个关键的"最大化可用空间"参数:

参数默认值的问题本方案
-m 0ext4 默认给 root 保留 5% 块,15.36 TB 上即约 768 GB 白白锁死数据盘无需保留,直接 -m 0
-T largefile默认 16 KiB/inode,15.36 TB 会生成约 9.4 亿 inode,inode 表占上百 GB,fsck 极慢1 MiB/inode(约 1465 万 inode),虚拟机镜像全是大文件,完全够用

挂载与持久化:

root@sg-hv-01:~# mkdir -p /homedata
root@sg-hv-01:~# echo "UUID=$(blkid -s UUID -o value /dev/nvme1n1p1) /homedata ext4 defaults,noatime,nofail 0 2" >> /etc/fstab
root@sg-hv-01:~# systemctl daemon-reload && mount -a
root@sg-hv-01:~# df -hT /homedata
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme1n1p1 ext4   14T  2.1M   14T   1% /homedata
为什么必须用 UUID:本机有两块 NVMe,实测硬重启后内核枚举顺序会变化,nvme0n1 与 nvme1n1 会互换。若 fstab 里写 /dev/nvme1n1p1,下次启动就会挂错盘甚至挂不上。nofail 用于避免掉盘导致远程机器进入 emergency mode。

3.4 4 GiB swapfile

root@sg-hv-01:~# fallocate -l 4G /swapfile
root@sg-hv-01:~# chmod 600 /swapfile
root@sg-hv-01:~# mkswap -L vfswap /swapfile
Setting up swapspace version 1, size = 4 GiB (4294967296 bytes)
LABEL=vfswap, UUID=d94a2b63-7e15-4a8c-b0f2-3c6d98e14a77

root@sg-hv-01:~# swapon /swapfile
root@sg-hv-01:~# echo '/swapfile none swap sw 0 0' >> /etc/fstab
root@sg-hv-01:~# swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   4G   0B   -2

root@sg-hv-01:~# free -h
               total        used        free      shared  buff/cache   available
Mem:           4.0Ti       1.3Gi       4.0Ti       1.0Mi       6.4Gi       4.0Ti
Swap:          4.0Gi          0B       4.0Gi

踩坑记录:ext4 上 fallocate 生成的是 unwritten extent,个别内核会拒绝 swapon 并报 Invalid argument。若遇到,用 dd 原地实写覆盖(不会额外占用空间)后重新 mkswap/swapon:

dd if=/dev/zero of=/swapfile bs=4M count=1024 conv=notrunc status=progress
mkswap -L vfswap /swapfile && swapon /swapfile

3.5 数据盘最终状态

root@sg-hv-01:~# lsblk -f
NAME        FSTYPE FSVER LABEL    UUID                                 FSAVAIL FSUSE% MOUNTPOINTS
nvme0n1
└─nvme0n1p1 ext4   1.0   homedata 7c4e1d92-58ab-4f36-9c0d-2b7e5a1f8d64   13.9T     0% /homedata
nvme1n1
├─nvme1n1p1 vfat   FAT32          4A21-9C0B                              89.5M     9% /boot/efi
└─nvme1n1p2 ext4   1.0            b3f81a47-6d20-4c95-a7e3-91c4f0b28e5d    1.7T     1% /

(注意此处 nvme0n1 已经是 15.36 TB 数据盘——与第 2 节的枚举顺序相反,正是"盘符不稳定"的实证。)


4. 安装被控节点(Hypervisor)

4.1 安装脚本安全审计

官方被控安装脚本:https://install.virtfusion.net/hypervisor-install.sh。在生产机上执行前,先下载并逐段审计其对系统的影响。

审计结论:

行为是否发生影响
修改 /etc/network/interfaces否不动网络配置
创建网桥 / 修改 IP / 修改路由否不动网络配置
销毁 libvirt 默认网络是(virsh net-destroy default)有益:避免 192.168.122.0/24 与既有网段冲突
覆盖 /etc/dnsmasq.conf 并停用 dnsmasq 服务是宿主机 DNS 来自 interfaces 的 dns-nameservers,无影响
启用 UFW是,但 default allow incoming/outgoing/routed不会造成失联
建立 /home/vf-data/{disk,os,server,tmp,lock,conf}是虚拟机数据默认目录(见 7.3 的路径规划)
监听端口8892/tcp (https)控制端 ↔ 被控通信端口

4.2 安装

建议在 tmux / screen 中执行(脚本会安装 QEMU、libvirt、PHP 栈并生成 4096 位 DH 参数,耗时数分钟):

root@sg-hv-01:~# tmux new -s vf
root@sg-hv-01:~# ( set -euo pipefail; (command -v apt-get >/dev/null && apt-get update && apt-get install -y curl) || (command -v dnf >/dev/null && dnf -y install curl); curl -fsSL https://install.virtfusion.net/hypervisor-install.sh | bash )

安装尾部输出:

[ OK ] Supervisor installation and configuration completed.
[INFO] Configuring firewall using UFW...
[ OK ] Firewall (UFW) configuration completed.
[INFO] Checking virtualization (KVM) support...
[ OK ] x86 virtualization flags detected and /dev/kvm present.
[ OK ] KVM appears available: /dev/kvm present.

[INFO] Log file: /var/log/2026-10-15-160759-hypervisor-install.log
[INFO] Rollback script retained at: /tmp/2026-10-15-160759-vf-hypervisor-rollback.sh

╔═══════════════════════════════════════════════════════════════════╗
║                                                                   ║
║          VirtFusion Hypervisor Installation Completed             ║
║                                                                   ║
║       This hypervisor can now be added to the control server      ║
║                                                                   ║
╚═══════════════════════════════════════════════════════════════════╝
脚本会生成回滚脚本(/tmp/*-vf-hypervisor-rollback.sh),不要删除。VirtFusion 不提供卸载程序,装错只能重装系统。

4.3 安装后自检

root@sg-hv-01:~# systemctl is-active vf-nginx vf-php8-fpm libvirtd supervisor
active
active
active
active

root@sg-hv-01:~# ss -lntp | grep 8892
LISTEN 0 511 0.0.0.0:8892 0.0.0.0:* users:(("nginx",pid=1800,fd=6),("nginx",pid=1799,fd=6),...)
LISTEN 0 511   [::]:8892   [::]:* users:(("nginx",pid=1800,fd=7),("nginx",pid=1799,fd=7),...)

root@sg-hv-01:~# virsh net-list --all
 Name      State      Autostart   Persistent
----------------------------------------------
 default   inactive   no          yes

root@sg-hv-01:~# virsh nwfilter-list
 UUID                                  Name
----------------------------------------------------------------
 ...                                   allow-ipv6
 ...                                   no-ipv6-spoofing
 ...                                   vf-clean-v4
 ...                                   vf-clean-v4v6

在控制端面板添加被控后(地址 203.0.113.1,端口 8892),面板可读取到被控的内存与运行时间指标,说明通信链路已建立:

内存      1%
          3315 MB of 4193280 MB Used
          4189965 MB Free
运行时间   up 18:48, load average: 0.80, 0.51, 0.33

5. 网络方案选型

VirtFusion 支持以下被控网络类型:Bridged、Libvirt Routed、Libvirt Network、NAT v1、MacVTap、Open vSwitch Bridged(面板中"类型"下拉项)。

5.1 逐一排除

类型在本环境是否可用原因
MacVTap(默认)不可用于公网 IP 直通MacVTap 在 bridge 模式下宿主机无法与自己的虚拟机通信,客户机只能把网关指向上游 10.0.0.74(跨网段网关),Windows 及部分模板不支持;且会失去 IP 防伪与防火墙能力
Bridged(标准桥接)不适用标准桥接要求公网 IP 与宿主机同二层;本环境是三层路由,桥接后上游无法 ARP 到客户机 IP
NAT v1可用(备选)客户机获取私网 IP、由宿主机 NAT 出网,通过面板做端口/域名映射。不需要改动物理网卡,但客户无法自由使用任意端口
Libvirt Routed本方案采用与"私有 /31 + 公网 /24 三层路由"结构天然匹配:宿主机作为客户机的网关完成三层转发
面板中被控设置页明确提示:网络过滤(IP 防伪)仅在 Libvirt Routed / Bridged / Libvirt Network / NAT v1 下生效,MacVTap 与 Open vSwitch Bridged 不可用——这也是排除 MacVTap 的重要依据。

5.2 判定上游是三层路由还是二层

root@sg-hv-01:~# apt install -y iputils-arping
root@sg-hv-01:~# ip neigh show 10.0.0.74
10.0.0.74 dev enp1s0f0np0 lladdr 00:11:22:33:44:55 REACHABLE

root@sg-hv-01:~# arping -c 3 -I enp1s0f0np0 203.0.113.200   # 一个未使用的地址
ARPING 203.0.113.200 from 203.0.113.1 enp1s0f0np0
Sent 3 probes (3 broadcast(s))
Received 0 response(s)

无人应答 → 上游未对公网段做代理 ARP,符合三层路由特征。最终判定以首台虚拟机的实测为准(见第 8 节)。

5.3 目标架构

            上游 10.0.0.74
                  │
        enp1s0f0np0│  10.0.0.75/31
                  │  203.0.113.1/32
                  │
            ┌─────┴─────┐
            │   宿主机   │  默认路由 via 10.0.0.74 src 203.0.113.1
            │  ip_forward=1
            └─────┬─────┘
                  │ br0  203.0.113.254/24  ← 客户机统一网关
        ┌─────────┼─────────┐
      VM .2     VM .3     VM .4 ...

6. 网络改造(高风险操作)

6.1 事故复盘:为什么不能在业务会话里直接 ip addr del

这次改造中发生过一次真实的失联事故,值得完整记录。

原始配置把 203.0.113.1/24 直接配在物理网卡上。为了让 libvirt 的路由型网络能使用该网段,必须先把物理网卡上的 /24 收窄为 /32,操作直觉上是:

ip addr del 203.0.113.1/24 dev enp1s0f0np0
ip addr add 203.0.113.1/32 dev enp1s0f0np0
ip route replace default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1

结果:第一条命令执行后 SSH 立即断开,后两条从未执行。

root@sg-hv-01:~# ip addr del 203.0.113.1/24 dev enp1s0f0np0

连接断开
连接主机(代理服务器)...
connection is closed by foreign host

原因有两层:

  1. 删除 203.0.113.1 意味着你当前 SSH 连接所使用的本地源地址消失,已建立的 socket 无法再选出合法的源地址,连接立即中断;
  2. 三行命令是逐行执行的,第一行就把 shell 杀掉,后两行从未运行——机器最终处于"公网地址被删、新地址未加"的状态,从外部彻底不可达。

恢复方式:由于 /etc/network/interfaces 未被修改(改动仅在运行时),硬重启即自动恢复原始网络配置(post-up 会重新把 /24 与默认路由加回来)。

6.2 安全策略:三条铁律

基于上述事故,后续所有涉及"当前连接所依赖的地址/网卡"的变更,必须满足:

  1. 不在业务会话中执行:把整批变更交给独立执行单元(systemd-run),SSH 断开后命令仍会跑完。
  2. 必须有定时自动回滚:变更前挂一个 10 分钟后的回滚任务,只有在变更验证通过后才取消它。若变更失败或自己再也连不上,机器会自动回到可用状态。
  3. 尽量留第二条命:临时增加一个同网段的备用管理地址,从该地址登录后再做手术。
前置条件:具备带外管理(IPMI / KVM over IP)或机房可代为硬重启。没有带外管理的单网卡机器,不应执行本文第 6 节的操作。

6.3 备用管理地址(可选,用于手术期间保命)

root@sg-hv-01:~# ip addr add 203.0.113.250/32 dev enp1s0f0np0
root@sg-hv-01:~# ip -br a show enp1s0f0np0
enp1s0f0np0  UP  10.0.0.75/31  203.0.113.1/24  203.0.113.250/32

# 从另一台机器验证后,再持久化到 interfaces(post-up 行)
root@sg-hv-01:~# sed -i '/203.0.113.1\/24/a\    post-up ip addr replace 203.0.113.250/32 dev enp1s0f0np0' /etc/network/interfaces
root@sg-hv-01:~# ifquery enp1s0f0np0 >/dev/null && echo "语法 OK"
语法 OK

验证(在另一台机器上执行):

$ ssh -o ConnectTimeout=5 root@203.0.113.250 hostname
sg-hv-01
备用地址只承担运维入口,不参与路由、不作为网关、面板也不识别它;建议在面板 IP 段中标记为"保留"。若不需要,删除 interfaces 中对应行并 ip addr del 即可。

6.4 变更脚本

回滚脚本 /root/net-rollback.sh:

#!/usr/bin/env bash
exec >>/root/net-rollback.log 2>&1; date; set -x
virsh net-destroy br0 2>/dev/null; virsh net-undefine br0 2>/dev/null
ip addr del 203.0.113.1/32 dev enp1s0f0np0 2>/dev/null
ip addr add 203.0.113.1/24 dev enp1s0f0np0 2>/dev/null
ip route replace default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1
sed -i 's#203.0.113.1/32#203.0.113.1/24#' /etc/network/interfaces
ip -br a; ip route; echo ROLLED-BACK

libvirt 网络定义 /root/network.xml:

<network>
  <name>br0</name>
  <forward mode='route' dev="enp1s0f0np0"/>
  <bridge name='br0' stp='on' delay='0'/>
  <ip address='203.0.113.254' netmask='255.255.255.0'/>
</network>

变更脚本 /root/net-switch.sh(自带分步自检,任一步失败立即回滚):

#!/usr/bin/env bash
exec >>/root/net-switch.log 2>&1; set -x
fail() { echo "FAILED: $*"; /root/net-rollback.sh; exit 1; }

ip addr del 203.0.113.1/24 dev enp1s0f0np0 || fail "del /24"
ip addr add 203.0.113.1/32 dev enp1s0f0np0 || fail "add /32"
ip addr add 203.0.113.250/32 dev enp1s0f0np0 2>/dev/null || true
ip route replace default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1 || fail "default route"

virsh net-define /root/network.xml || fail "net-define"
virsh net-autostart br0
virsh net-start br0 || fail "net-start"
ip route | grep -q "203.0.113.0/24 dev br0" || fail "br0 route missing"

sed -i 's#203.0.113.1/24#203.0.113.1/32#' /etc/network/interfaces

ip -br a; ip route; virsh net-list --all
echo "SUCCESS"

执行前的静态检查:

root@sg-hv-01:~# bash -n /root/net-switch.sh && bash -n /root/net-rollback.sh && echo "脚本语法 OK"
脚本语法 OK

root@sg-hv-01:~# virt-xml-validate /root/network.xml network && echo "XML OK"
/root/network.xml validates
XML OK

6.5 执行

从备用管理地址(203.0.113.250)登录的新会话中执行:

root@sg-hv-01:~# systemd-run --on-active=10min --unit=net-rollback --collect /root/net-rollback.sh
Running timer as unit: net-rollback.timer
Will run service as unit: net-rollback.service

root@sg-hv-01:~# systemctl list-timers net-rollback.timer --no-pager
NEXT                        LEFT LAST PASSED UNIT               ACTIVATES
Thu 2026-10-15 16:57:20 CST 9min -    -      net-rollback.timer net-rollback.service

1 timers listed.

root@sg-hv-01:~# systemd-run --unit=net-switch --collect /root/net-switch.sh
Running as unit: net-switch.service; invocation ID: fb2d440841244efd83baad8a67d2c6d9

执行日志:

root@sg-hv-01:~# cat /root/net-switch.log
+ ip addr del 203.0.113.1/24 dev enp1s0f0np0
+ ip addr add 203.0.113.1/32 dev enp1s0f0np0
+ ip addr add 203.0.113.250/32 dev enp1s0f0np0
+ true
+ ip route replace default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1
+ virsh net-define /root/network.xml
Network br0 defined from /root/network.xml

+ virsh net-autostart br0
Network br0 marked as autostarted

+ virsh net-start br0
Network br0 started

+ ip route
+ grep -q '203.0.113.0/24 dev br0'
+ sed -i s#203.0.113.1/24#203.0.113.1/32# /etc/network/interfaces
+ ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
enp1s0f0np0      UP             10.0.0.75/31 203.0.113.250/32 203.0.113.1/32 fe80::1/64
br0              DOWN           203.0.113.254/24
+ ip route
default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1
10.0.0.74/31 dev enp1s0f0np0 proto kernel scope link src 10.0.0.75
203.0.113.0/24 dev br0 proto kernel scope link src 203.0.113.254 linkdown
+ virsh net-list --all
 Name      State      Autostart   Persistent
----------------------------------------------
 br0       active     yes         yes
 default   inactive   no          yes

+ echo SUCCESS
SUCCESS
关于 br0 DOWN 与路由上的 linkdown 标记:Linux 网桥在没有成员端口时即处于 NO-CARRIER 状态,operstate 显示 down,其直连路由被标记 linkdown。这不是故障。当第一台虚拟机的 tap 接口接入 br0 后,网桥转为 UP,标记随之消失。

6.6 验证与取消回滚

root@sg-hv-01:~# ip link show br0
5: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:54:00:9e:4b:17 brd ff:ff:ff:ff:ff:ff

root@sg-hv-01:~# sysctl -n net.ipv4.ip_forward
1

root@sg-hv-01:~# ping -c2 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=56 time=1.55 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=56 time=1.56 ms
--- 1.1.1.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms

尖括号中出现 UP 标志即表示网桥已管理性启用(NO-CARRIER 仅为无成员端口)。libvirt 在启动路由型网络时会自动开启 net.ipv4.ip_forward。

验证通过后立即取消回滚定时器,否则 10 分钟后变更会被撤销:

root@sg-hv-01:~# systemctl stop net-rollback.timer
root@sg-hv-01:~# systemctl list-units 'net-rollback*' --all
  UNIT LOAD ACTIVE SUB DESCRIPTION
0 loaded units listed.

7. VirtFusion 面板配置

7.1 被控网络

被控 → 网络 → 添加:

字段值说明
名称public-v4-routed面板内的标识
类型Libvirt 路由即 Libvirt Routed
接口名称br0填网桥名,不是物理网卡名
MTU留空默认 1500
IP 段分组-- 无 --可选
面板只是引用该 libvirt 网络,不会重建它。配置完成后宿主机侧 virsh net-list --all 应仍为 br0 active / autostart yes。

7.2 被控主接口与启用

  • 被控 → 常规 → 打开 已启用(否则面板提示"虚拟机管理器未启用",无法创建服务器、不收集指标)。
  • 若表单中存在主接口(Primary Interface)字段,填 enp1s0f0np0(该字段供 MacVTap 等模式使用)。

7.3 存储路径

被控默认的虚拟机存储路径为 /home/vf-data/disk,位于系统盘。将其指向 15.36 TB 数据盘:

root@sg-hv-01:~# mkdir -p /homedata/vf-data/disk
root@sg-hv-01:~# ls -ld /home/vf-data/disk /homedata/vf-data/disk
drwxr-xr-x 3 virtfusion virtfusion /home/vf-data/disk
drwxr-xr-x 2 root       root       /homedata/vf-data/disk

root@sg-hv-01:~# chown -R virtfusion:virtfusion /homedata/vf-data
root@sg-hv-01:~# ls -ld /homedata/vf-data/disk
drwxr-xr-x 2 virtfusion virtfusion /homedata/vf-data/disk

被控 → 存储 → Edit Storage:

字段值
类型Local (Default mountpoint)
DatastoreNVMe-4T
Path/homedata/vf-data/disk
Max Capacity∞ 或 14000

保存后面板重新扫描,容量应显示约 14 TB。

常见疏漏:只执行 mkdir -p /homedata/vf-data 而漏掉末级 disk。面板 Path 指向不存在的目录会导致建机失败:

# df -hT /homedata/vf-data/disk
df: /homedata/vf-data/disk: No such file or directory

关于 OS 模板目录:VirtFusion 的 OS 模板存放在 /home/vf-data/os,该目录仍在系统盘(与 conf/ 同级)。不要把整层 /home/vf-data 绑定到数据盘——会覆盖 /home/vf-data/conf/dnsmasq/,导致 libvirt 网络启动 dnsmasq 时找不到 conf-dir。若模板占用过大,只迁移 os 这一层。

7.4 IP 段

被控 → IP 段 → 新建 IPv4 段:

字段值
段 / 掩码203.0.113.0/24 / 255.255.255.0
网关203.0.113.254(必须等于 br0 上的地址,客户机才能 ARP 到)
DNS1.1.1.1、8.8.8.8
保留.0 .1 .250 .254 .255

保存后分配给该被控与 br0 网络,再逐个添加可分配的 IP。

保留地址的取舍:

地址原因
.1宿主机自身公网地址(SSH、8892 通信、默认路由源地址)
.254br0 网关,所有客户机的默认网关
.250备用管理地址(运维生命线,可选)
.0 / .255三层路由下技术可用,但客户机内部按 /24 计算时会被视为网络号/广播地址,部分系统与工具会异常(Windows 尤甚);VirtFusion 官方文档亦建议按惯例保留(compliance)

一个 /24 的实际可售数量:256 - 5 = 251。


8. 首台虚拟机验收

分配 203.0.113.2,创建最小规格虚拟机(需先在 OS 模板 中准备好可用模板,Linux 模板须勾选 cloud-init,否则客户机不会自动应用分配到的 IP)。

宿主机侧:

root@sg-hv-01:~# virsh list --all
 Id   Name              State
--------------------------------
 1    vm-test-01        running

root@sg-hv-01:~# virsh domiflist vm-test-01
 Interface   Type     Source   Model    MAC
-------------------------------------------------------------------
 vnet0       bridge   br0      virtio   52:54:00:c7:2f:8a

root@sg-hv-01:~# ip -br a show br0
br0   UP   203.0.113.254/24

root@sg-hv-01:~# ip route | grep 203.0.113
203.0.113.0/24 dev br0 proto kernel scope link src 203.0.113.254

(网桥接入 tap 后转为 UP,此前的 linkdown 标记消失。)

客户机内(VNC 控制台):

# ip -br a
eth0   UP   203.0.113.2/24

# ip route
default via 203.0.113.254 dev eth0
203.0.113.0/24 dev eth0 proto kernel scope link src 203.0.113.2

验收判据(三条全通即方案成立):

# 客户机 → 网关
# ping -c2 203.0.113.254
2 packets transmitted, 2 received, 0% packet loss

# 客户机 → 公网
# ping -c2 8.8.8.8
2 packets transmitted, 2 received, 0% packet loss

# 外部 → 客户机公网 IP
$ ping -c2 203.0.113.2
2 packets transmitted, 2 received, 0% packet loss

9. 重启持久化验收

所有改动落地后必须重启复核一次:

root@sg-hv-01:~# reboot

重启后:

root@sg-hv-01:~# ip -br a show enp1s0f0np0
enp1s0f0np0  UP  10.0.0.75/31  203.0.113.1/32  fe80::1/64

root@sg-hv-01:~# ip route
default via 10.0.0.74 dev enp1s0f0np0 src 203.0.113.1
10.0.0.74/31 dev enp1s0f0np0 proto kernel scope link src 10.0.0.75
203.0.113.0/24 dev br0 proto kernel scope link src 203.0.113.254

root@sg-hv-01:~# virsh net-list --all
 Name      State      Autostart   Persistent
----------------------------------------------
 br0       active     yes         yes
 default   inactive   no          yes

root@sg-hv-01:~# sysctl -n net.ipv4.ip_forward
1

root@sg-hv-01:~# findmnt /homedata && df -hT /homedata
TARGET    SOURCE         FSTYPE OPTIONS
/homedata /dev/nvme0n1p1 ext4   rw,noatime
Filesystem     Type  Size  Used Avail Use% Mounted on
/dev/nvme0n1p1 ext4   14T  2.1M   14T   1% /homedata

root@sg-hv-01:~# swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   4G   0B   -2

root@sg-hv-01:~# ping -c2 1.1.1.1
2 packets transmitted, 2 received, 0% packet loss

宿主机侧持久化涉及的三个位置:

内容持久化方式
10.0.0.75/31、203.0.113.1/32、默认路由/etc/network/interfaces 的 address 与 post-up
br0(含 203.0.113.254/24)与 ip_forwardlibvirt 网络 autostart=yes,开机由 libvirtd 自动创建
/homedata、/swapfile/etc/fstab(必须用 UUID,磁盘枚举顺序会变化)

10. 故障排查手册

10.1 libvirt 报 Network is already in use by interface <nic>

error: Failed to start network br0
error: Network is already in use by interface enp1s0f0np0

原因:物理网卡上仍存在与该 libvirt 网络完全相同的网段路由(例如残留的 203.0.113.1/24 直连路由)。libvirt 的 networkCheckRouteCollision() 会遍历 /proc/net/route,当某条路由的(网络地址 & 掩码)与网络定义完全一致时报错。

处理:把物理网卡上的 /24 收窄为 /32(/32 与 /24 掩码不同,不再触发冲突),操作务必遵循第 6.2 节的三条铁律。

10.2 客户虚拟机无法出网

# 1) 客户机的包是否到达网桥
root@sg-hv-01:~# tcpdump -ni br0 icmp -c 5

# 2) 是否被转发出去
root@sg-hv-01:~# tcpdump -ni enp1s0f0np0 icmp -c 5

# 3) 转发链是否被拦截
root@sg-hv-01:~# iptables -S FORWARD | head -20

# 4) 转发开关
root@sg-hv-01:~# sysctl -n net.ipv4.ip_forward

判定与处置:

现象结论处置
包从 enp1s0f0np0 发出(源地址为客户机公网 IP)但无任何回包上游未将公网段三层路由至本机,而是依赖二层 ARP由宿主机代客户机应答 ARP:
sysctl -w net.ipv4.conf.enp1s0f0np0.proxy_arp=1
并写入 /etc/sysctl.d/99-vf-proxyarp.conf 持久化
包根本没有出现在 br0 上客户机未获得 IP/网关(通常是模板未启用 cloud-init)通过 VNC 进入客户机手动核对 ip a / ip route,并检查模板 cloud-init 配置
包在 br0 上出现但未出现在物理网卡转发被拦截检查 iptables -S FORWARD 与 UFW(官方安装脚本设置为 default allow routed)

10.3 面板无法连接被控(8892 不通)

root@sg-hv-01:~# systemctl is-active vf-nginx
active
root@sg-hv-01:~# ss -lntp | grep 8892
LISTEN 0 511 0.0.0.0:8892 0.0.0.0:* users:(("nginx",pid=1800,fd=6),...)
  • 宿主机 UFW 默认放行入站,如自行调整过规则需放行 8892/tcp;
  • 上游若有防火墙策略,需允许控制端 IP 访问被控 8892/tcp;
  • 面板中填写的被控地址必须是可从控制端路由到达的地址(本例为 203.0.113.1)。

10.4 存储路径不存在导致建机失败

见 7.3 节的"常见疏漏",补建目录并 chown virtfusion:virtfusion 后在面板重新保存。


11. 经验清单

必须做

  • 单网卡机器执行网络改造前,确认具备 IPMI/KVM 带外管理或机房可代为硬重启。
  • 所有改变"当前连接所依赖地址"的操作,一律用 systemd-run 独立单元执行,并挂定时自动回滚。
  • fstab 一律使用 UUID=;数据盘建议加 nofail。
  • 虚拟机存储路径在面板中显式指向大容量数据盘,并确保目录已创建、属主正确。
  • 改动后重启复核一遍。

禁止做

  • 在业务 SSH 会话里直接 ip addr del 掉当前连接使用的地址。
  • systemctl restart networking(会抖动接口,风险与上一条等价)。
  • 用 /dev/nvmeXn1 之类的盘符写 fstab 或脚本(枚举顺序会变)。
  • 把整层 /home/vf-data 绑定到数据盘(会遮盖 conf/dnsmasq/)。
  • 保留地址(.1/.254)分配给客户。

附录 A:宿主机侧文件清单

路径用途
/root/network.xmllibvirt 路由型网络定义(br0)
/root/net-switch.sh网络改造脚本(含分步自检)
/root/net-rollback.sh回滚脚本
/root/net-switch.log、/root/net-rollback.log执行日志
/etc/network/interfaces.ok-<时间戳>改造前的网络配置备份
/tmp/*-vf-hypervisor-rollback.shVirtFusion 安装脚本生成的回滚脚本
/var/log/*-hypervisor-install.log被控安装日志

附录 B:参考资料

上一篇 已经是第一篇了
下一篇 Debian 13 内核升级实录:修复 CVE-2026-99999(PwnEscape)虚拟机逃逸漏洞

暂无评论

正在验证… Ctrl + Enter 发送

还没有评论,来说点什么吧

© 2026 Chasedaily.cn 版权所有. 本网站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议, 转载请注明出处
京ICP备2026068377号-1