# 4. KVM 网络配置

2024年7月16日20分钟阅读

- FormalSciences/ComputerScience
- OperatingSystem/Virtualization
- KVM

## KVM 网络基础

KVM（Kernel-based Virtual Machine）网络是指在 KVM 虚拟化环境中，为虚拟机提供的网络连接和通信机制。通过 KVM 网络，虚拟机可以与其他虚拟机、宿主机以及外部网络进行通信。

网络类型 | 描述 | 优点 | 缺点 | 适用场景
--- | --- | --- | --- | ---
NAT 网络 | 虚拟机通过宿主机的网络接口与外部通信，IP 地址被隐藏。 | 配置简单，适合需要外部通信的虚拟机。 | 虚拟机间通信需额外配置，网络性能可能受限。 | 适合不需外部访问但需访问外网的虚拟机。
桥接网络 | 虚拟机直接连接物理网络接口，拥有独立 IP 地址，可直接与其他设备通信。 | 与物理网络无缝集成，适合需外部访问的虚拟机。 | 配置较复杂，需适当配置物理网络接口。 | 适合需要直接对外提供服务的虚拟机。
内部网络 | 仅允许虚拟机之间的通信，不与宿主机或外部网络通信。 | 提供隔离网络，适合测试和开发。 | 虚拟机无法与外部网络通信。 | 适合需要隔离的测试和开发环境。
仅主机网络 | 允许虚拟机与宿主机通信，但不与外部网络通信。 | 简单隔离，适合虚拟机与宿主机通信。 | 虚拟机无法与外部网络通信。 | 适合虚拟机与宿主机需要频繁交互的场景。

## KVM 网络安装与准备

你可以选择使用任意一款网络管理工具，这里**推荐使用`NetworkManager`**来管理网络桥接。

### 安装 NetworkManager

非 Fedora/RHEL 系列，需要手动安装 NetworkManager，并配置 NetworkManager 接管网络。

    # Debian/Ubuntu 系列
    sudo apt-get update
    sudo apt-get install -y network-manager

### 配置系统网络支持

1. 启用 NetworkManager

       # 启动并启用 NetworkManager 服务
       sudo systemctl start NetworkManager
       sudo systemctl enable NetworkManager

2. 创建并配置网络桥接

   使用`nmcli`工具创建一个新的桥接接口。例如，创建名为`br0`的桥接接口并将现有的以太网接口（假设为`eth0`）添加到桥接中。

       sudo nmcli connection add type bridge autoconnect yes con-name br0 ifname br0
       sudo nmcli connection add type bridge-slave autoconnect yes con-name br0-slave ifname eth0 master br0
       sudo nmcli connection modify br0 ipv4.method auto
       sudo nmcli connection up br0

3. 确认桥接网络配置

   使用以下命令确认桥接网络是否正确配置。

       nmcli connection show
       ip a

4. 确认内核模块加载情况

   确保KVM相关的内核模块已加载：

       lsmod | grep kvm

### 示例配置文件

对于`NetworkManager`的配置文件（一般位于`/etc/NetworkManager/system-connections/`目录下），你可以手动编辑这些文件进行更复杂的配置。例如，编辑`br0`的配置文件：

    [connection]
    id=br0
    type=bridge
    interface-name=br0
    autoconnect=true

    [ipv4]
    method=auto

    [ipv6]
    method=auto

### 其他注意事项

1. 防火墙配置：确保你的防火墙规则允许桥接网络的流量。
2. 验证桥接网络：创建一个虚拟机并将其连接到`br0`桥接网络，验证网络连接是否正常。

## NAT 网络

**KVM 默认会创建一个名为 `default` 的 NAT 网络。**这个网络通常在安装 libvirt 时自动创建和启用。

1. 检查并启用默认网络：

   检查 `default` 网络是否已经存在并启用：

       sudo virsh net-list --all

   如果默认网络未启用，可以通过以下命令启用：

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

2. 查看默认网络配置：

   查看默认网络的详细配置：

       sudo virsh net-dumpxml default

   典型的默认网络配置如下：

       <network>
         <name>default</name>
         <uuid>……</uuid>
         <forward mode='nat'>
           <nat>
             <port start='1024' end='65535'/>
           </nat>
         </forward>
         <bridge name='virbr0' stp='on' delay='0'/>
         <mac address='52:54:00:d3:9b:fb'/>
         <ip address='192.168.122.1' netmask='255.255.255.0'>
           <dhcp>
             <range start='192.168.122.2' end='192.168.122.254'/>
           </dhcp>
         </ip>
       </network>

3. 创建虚拟机：

   创建一台连接到 `default` 网络的虚拟机。可以使用 `virt-install` 命令来完成：

       sudo virt-install \
         --name myvm \
         --ram 4096 \
         --disk path=/var/lib/libvirt/images/myvm_storage.qcow2,size=32 \
         --vcpus 2 \
         --os-type linux \
         --os-variant ubuntu20.04 \
         --network network=default \
         --graphics none \
         --console pty,target_type=serial \
         --location 'https://mirrors.tuna.tsinghua.edu.cn/ubuntu/dists/focal/main/installer-amd64/' \
         --extra-args 'console=ttyS0,115200n8 serial'

4. 验证虚拟机网络连接：

   登录到虚拟机，并验证其网络连接：

       ping -c 4 8.8.8.8

   检查虚拟机是否能够获得 IP 地址：

       ip a

### `virsh` 创建自定义 NAT 网络

通过 `virsh` 命令创建自定义 NAT 网络，并配置 DHCP 和 IP 地址范围。

1. 创建网络配置文件：

   创建一个自定义网络配置文件（如 `custom-net.xml`）：

       <network>
         <name>custom-net</name>
         <forward mode='nat'/>
         <bridge name='virbr1' stp='on' delay='0'/>
         <mac address='52:54:00:12:34:56'/>
         <ip address='192.168.100.1' netmask='255.255.255.0'>
           <dhcp>
             <range start='192.168.100.2' end='192.168.100.254'/>
           </dhcp>
         </ip>
       </network>

2. 定义并启动网络：

   使用 `virsh` 命令定义并启动该网络：

       sudo virsh net-define custom-net.xml
       sudo virsh net-start custom-net
       sudo virsh net-autostart custom-net

3. 查看自定义网络状态：

   确认网络已启用：

       sudo virsh net-list --all

在上面的 `custom-net.xml` 文件中，已经定义了 DHCP 范围：

    <ip address='192.168.100.1' netmask='255.255.255.0'>
      <dhcp>
        <range start='192.168.100.2' end='192.168.100.254'/>
      </dhcp>
    </ip>

此配置表示：

- 网关地址：192.168.100.1
- DHCP 范围：192.168.100.2 到 192.168.100.254

### `NetworkManager` 创建自定义 NAT 网络

1. 确保 NetworkManager 已启用：

       sudo systemctl enable --now NetworkManager

2. 创建 NetworkManager 桥接连接：

   编辑 NetworkManager 配置文件，创建一个桥接网络（例如 `/etc/NetworkManager/system-connections/bridge-br1.nmconnection`）：

       [connection]
       id=bridge-br1
       type=bridge
       autoconnect=true

       [bridge]
       stp=true

       [ipv4]
       method=manual
       address1=192.168.100.1/24

       [ipv6]
       method=ignore

3. 重启 NetworkManager 服务：

       sudo systemctl restart NetworkManager

4. 验证桥接网络：

   确认新的桥接网络已创建并启用：

       nmcli connection show

## 桥接网络

使用 NetworkManager 的 `nmcli` 命令来创建和配置桥接网络接口，并将物理接口绑定到网桥。

1. 创建桥接接口：

   使用 `nmcli` 命令创建一个新的桥接接口：

       sudo nmcli connection add type bridge ifname br0

2. 配置桥接接口的 IP 地址：

   为桥接接口配置 IP 地址：

       sudo nmcli connection modify br0 ipv4.addresses 192.168.1.100/24 ipv4.method manual
       sudo nmcli connection modify br0 ipv4.gateway 192.168.1.1
       sudo nmcli connection modify br0 ipv4.dns "8.8.8.8,8.8.4.4"
       sudo nmcli connection modify br0 connection.autoconnect yes

3. 将物理接口绑定到桥接接口：

   假设物理接口为 `eth0`，使用 `nmcli` 将其绑定到 `br0`：

       sudo nmcli connection add type ethernet ifname eth0 master br0

4. 启用桥接接口：

   启用桥接接口 `br0` 和物理接口 `eth0`：

       sudo nmcli connection up br0
       sudo nmcli connection up eth0

5. 编辑虚拟机的 XML 配置文件：

   假设虚拟机名称为 `testvm`，使用以下命令编辑其 XML 配置文件：

       sudo virsh edit testvm

6. 添加桥接网络接口配置：

   在 `<devices>` 部分中添加以下内容，将 `br0` 作为桥接接口：

       <interface type='bridge'>
         <mac address='52:54:00:12:34:56'/>
         <source bridge='br0'/>
         <model type='virtio'/>
         <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
       </interface>

7. 保存并退出：

   保存配置文件并退出编辑器。

8. 重启虚拟机：

   重启虚拟机使新的网络配置生效：

       sudo virsh shutdown testvm
       sudo virsh start testvm

## 内部网络

内部网络允许虚拟机之间进行通信，而无需通过外部网络。这种网络模式适用于需要隔离的测试环境或需要内部通信的应用。

1. 创建内部网络 XML 配置文件

   首先，创建一个 XML 文件（如 `internal-net.xml`），定义内部网络的配置：

       <network>
         <name>internal-net</name>
         <forward mode='none'/>
         <bridge name='virbr1' stp='on' delay='0'/>
         <ip address='192.168.200.1' netmask='255.255.255.0'>
           <dhcp>
             <range start='192.168.200.2' end='192.168.200.254'/>
           </dhcp>
         </ip>
       </network>

在上面的 XML 文件中，已定义网络名称为 `internal-net`，IP 地址范围为 `192.168.200.2` 到 `192.168.200.254`。

2. 定义并启动网络

   使用 `virsh` 命令定义并启动内部网络：

       sudo virsh net-define internal-net.xml
       sudo virsh net-start internal-net
       sudo virsh net-autostart internal-net

3. 编辑虚拟机的 XML 配置文件：

       sudo virsh edit <vm_name>

4. 在 `<devices>`部分中添加以下内容，将 `internal-net`作为网络接口：

       <interface type='network'>
           <mac address='52:54:00:12:34:56'/>
           <source network='internal-net'/>
           <model type='virtio'/>
           <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
       </interface>

5. 保存并退出编辑器。

6. 重启虚拟机使新的网络配置生效：

       sudo virsh shutdown <vm_name>
       sudo virsh start <vm_name>

## 仅主机网络

仅主机网络（Host-only Network）允许虚拟机与宿主机通信，但不允许虚拟机与外部网络通信。这种网络模式适用于需要虚拟机与宿主机进行隔离通信的场景。

1. 创建仅主机网络 XML 配置文件

   创建一个 XML 文件（如 `host-only-net.xml`），定义仅主机网络的配置：

       <network>
         <name>host-only-net</name>
         <forward mode='none'/>
         <bridge name='virbr2' stp='on' delay='0'/>
         <ip address='192.168.150.1' netmask='255.255.255.0'>
           <dhcp>
             <range start='192.168.150.2' end='192.168.150.254'/>
           </dhcp>
         </ip>
       </network>

   在上面的 XML 文件中，已定义网络名称为 `host-only-net`，IP 地址范围为 `192.168.150.2` 到 `192.168.150.254`。

2. 定义并启动网络

   使用 `virsh` 命令定义并启动仅主机网络：

       sudo virsh net-define host-only-net.xml
       sudo virsh net-start host-only-net
       sudo virsh net-autostart host-only-net

3. 编辑虚拟机的 XML 配置文件：

       sudo virsh edit <vm_name>

4. 在 `<devices>`部分中添加以下内容，将 `host-only-net` 作为网络接口：

       <interface type='network'>
         <mac address='52:54:00:12:34:56'/>
         <source network='host-only-net'/>
         <model type='virtio'/>
         <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
       </interface>

5. 保存并退出编辑器。

6. 重启虚拟机使新的网络配置生效：

       sudo virsh shutdown <vm_name>
       sudo virsh start <vm_name>

## 高级网络功能

### VLAN 配置

使用 NetworkManager 和 `nmcli` 命令创建 VLAN 网络。

1. 创建 VLAN 接口：

   假设物理接口为 `eth0`，VLAN ID 为 100，VLAN 接口命名为 `eth0.100`：

       sudo nmcli connection add type vlan con-name vlan100 dev eth0 id 100

2. 配置 VLAN 接口 IP 地址：

   为 VLAN 接口配置 IP 地址：

       sudo nmcli connection modify vlan100 ipv4.addresses 192.168.100.1/24 ipv4.method manual
       sudo nmcli connection modify vlan100 ipv4.gateway 192.168.100.254
       sudo nmcli connection modify vlan100 ipv4.dns "8.8.8.8,8.8.4.4"
       sudo nmcli connection up vlan100

3. 使用 `virsh` 配置 VLAN 网络

   1. 编辑虚拟机的 XML 配置文件：

       sudo virsh edit <vm_name>

   2. 在 `<devices>`部分中添加以下内容，将 `vlan100`作为网络接口：

       <interface type='network'>
       <mac address='52:54:00:12:34:56'/>
       <source network='vlan100'/>
       <model type='virtio'/>
       <vlan>
        <tag id='100'/>
       </vlan>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
       </interface>

   3. 保存并退出编辑器。

   4. 重启虚拟机使新的网络配置生效：

       sudo virsh shutdown <vm_name>
       sudo virsh start <vm_name>

### 配置虚拟机的多网卡

1. 编辑虚拟机的 XML 配置文件：

    sudo virsh edit <vm_name>

2. 在 `<devices>`部分中添加多个 `<interface>`元素，每个代表一个网络接口：

    <interface type='network'>
      <mac address='52:54:00:12:34:56'/>
      <source network='default'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <interface type='network'>
      <mac address='52:54:00:12:34:57'/>
      <source network='vlan100'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </interface>

3. 保存并退出编辑器。

4. 重启虚拟机使新的网络配置生效：

    sudo virsh shutdown <vm_name>
    sudo virsh start <vm_name>

### 配置网络带宽限制

1. 编辑虚拟机的 XML 配置文件：

    sudo virsh edit <vm_name>

2. 在 `<interface>` 元素中添加 `<bandwidth>` 元素，设置带宽限制参数，例如：

    <interface type='network'>
      <mac address='52:54:00:12:34:56'/>
      <source network='default'/>
      <model type='virtio'/>
      <bandwidth>
        <inbound average='1000' peak='2000' burst='512'/>
        <outbound average='1000' peak='2000' burst='512'/>
      </bandwidth>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

以上配置将网络带宽限制为入站和出站各 1000 Kbps 平均速率，2000 Kbps 峰值速率，512 KB 突发流量。

3. 保存并退出编辑器。

4. 重启虚拟机使新的网络配置生效：

    sudo virsh shutdown <vm_name>
    sudo virsh start <vm_name>

- 在宿主机和虚拟机上安装 `iperf`：

      sudo apt install iperf3  # Ubuntu
      sudo yum install iperf3  # CentOS/RHEL

- 在虚拟机上启动 `iperf` 服务端：

      iperf3 -s

- 在宿主机上运行 `iperf` 客户端进行带宽测试：

      iperf3 -c <vm_ip_address>

- 检查测试结果，验证带宽限制是否生效。

通过以上步骤使用 NetworkManager 和 `nmcli` 命令配置 VLAN 网络、为虚拟机添加多个网卡，并使用 `virsh` 配置网络带宽限制。同时，可以通过 `iperf` 工具验证网络带宽限制的效果。

## 管理和监控虚拟网络

### `virsh` 命令管理网络

命令 | 描述
--- | ---
`virsh net-list --all` | 列出所有虚拟网络
`virsh net-info <network>` | 显示虚拟网络的信息
`virsh net-dumpxml <network>` | 显示虚拟网络的 XML 配置
`virsh net-create <network.xml>` | 创建虚拟网络
`virsh net-destroy <network>` | 销毁虚拟网络
`virsh net-start <network>` | 启动虚拟网络
`virsh net-autostart <network>` | 设置虚拟网络开机自启
`virsh net-undefine <network>` | 取消定义虚拟网络
`virsh net-edit <network>` | 编辑虚拟网络的 XML 配置
`virsh net-update <network> <command> <section> <xml>` | 更新虚拟网络
`virsh net-dhcp-leases <network>` | 列出网络的 DHCP 租约

### 监控网络性能

#### 使用 `iftop` 和 `vnstat` 等工具

1. 安装 `iftop` 和 `vnstat`

        # 在 Ubuntu 上
       sudo apt install iftop vnstat

       # 在 CentOS/RHEL 上
       sudo yum install iftop vnstat

2. 使用 `iftop` 监控实时网络流量：

        sudo iftop -i <network_interface>

   `iftop` 会显示实时的网络流量，包括发送和接收数据的主机 IP 和带宽使用情况。

3. 使用 `vnstat` 监控网络流量：

   初始化 `vnstat`数据库：

       sudo vnstat -u -i <network_interface>

   - 查看实时流量：

         sudo vnstat -l

   - 查看流量统计：

         sudo vnstat

   - 查看详细流量统计：

         sudo vnstat -d  # 查看每日流量统计
         sudo vnstat -m  # 查看每月流量统计
         sudo vnstat -t  # 查看每小时流量统计

#### 分析网络流量和性能

1. 分析流量数据：
   - 使用 `iftop` 和 `vnstat` 收集的流量数据，可以帮助识别网络瓶颈和高流量的主机。
2. 优化网络配置：
   - 根据监控数据，优化虚拟网络的配置，例如调整网络带宽限制、优化网络拓扑结构等。
3. 监控网络接口的性能：
   - 定期检查和分析网络接口的性能，确保虚拟网络的稳定性和高效运行。

## 安全配置

### 配置防火墙规则

#### 使用 `iptables` 配置防火墙

1. 安装 `iptables`：

       # 在 CentOS/RHEL 上
       sudo yum install iptables-services
       sudo systemctl enable --now iptables

       # 在 Ubuntu 上
       sudo apt install iptables

2. 配置基本规则：

   允许虚拟机网络通信：

       sudo iptables -A FORWARD -i virbr0 -o eth0 -j ACCEPT
       sudo iptables -A FORWARD -i eth0 -o virbr0 -j ACCEPT

3. 保存规则：

       # 在 CentOS/RHEL 上
       sudo service iptables save

       # 在 Ubuntu 上
       sudo iptables-save | sudo tee /etc/iptables/rules.v4

#### 配置 `firewalld` 管理规则

1. 安装 `firewalld`：

       # 在 CentOS/RHEL 上
       sudo yum install firewalld
       sudo systemctl enable --now firewalld

       # 在 Ubuntu 上
       sudo apt install firewalld
       sudo systemctl enable --now firewalld

2. 配置基本规则：

   允许虚拟机网络通信：

       sudo firewall-cmd --zone=public --add-interface=virbr0 --permanent
       sudo firewall-cmd --zone=public --add-masquerade --permanent
       sudo firewall-cmd --reload

### 网络隔离与访问控制

#### 使用 VLAN 实现网络隔离

1. 创建 VLAN 接口：

   使用 `nmcli`创建 VLAN 接口：

       sudo nmcli connection add type vlan con-name vlan100 dev eth0 id 100
       sudo nmcli connection modify vlan100 ipv4.addresses 192.168.100.1/24 ipv4.method manual

sudo nmcli connection up vlan100

    2. **配置虚拟机使用 VLAN**：

    使用 `virt-manager` 或 `virsh` 配置虚拟机连接到 VLAN 网络。

    #### 配置虚拟机访问控制列表（ACL）

    1. **使用 `virsh` 配置 ACL**：

    为虚拟机创建网络 ACL 规则：

    ```shell
    sudo virsh nwfilter-define /etc/libvirt/nwfilter/myfilter.xml

配置 `myfilter.xml`文件示例：

    <filter name='myfilter' chain='ipv4'>
      <uuid>...</uuid>
      <rule action='accept' direction='in' priority='500'>
        <mac address='52:54:00:12:34:56'/>
      </rule>
      <rule action='drop' direction='in' priority='1000'/>
    </filter>

2. 应用 ACL 到虚拟机：

   编辑虚拟机的 XML 配置文件，应用网络过滤器：

       <interface type='network'>
         <mac address='52:54:00:12:34:56'/>
         <source network='default'/>
         <model type='virtio'/>
         <filterref filter='myfilter'/>
       </interface>

   重启虚拟机使 ACL 生效。

## 故障排查

### 常见网络问题及解决方法

#### 虚拟机无法连接网络

1. 检查虚拟机的网络配置：
   - 确认虚拟机的网络接口配置正确。
   - 使用 `virsh dumpxml <vm_name>` 命令查看虚拟机的 XML 配置，确保 `<interface>` 部分配置正确。
2. 检查虚拟网络状态：
   - 使用 `virsh net-list --all` 命令查看虚拟网络是否启动。
   - 如果虚拟网络未启动，使用 `virsh net-start <network_name>` 启动虚拟网络。
3. 检查宿主机的网络配置：
   - 确认宿主机的网络接口和桥接配置正确。
   - 使用 `nmcli connection show` 命令查看 NetworkManager 的连接状态，确保相关接口已连接。
4. 检查虚拟机的 IP 地址：
   - 登录到虚拟机，使用 `ip a` 命令查看虚拟机的 IP 地址是否正确分配。
   - 如果未分配 IP 地址，检查 DHCP 配置是否正确。

#### 网络性能问题

1. 检查网络带宽限制：
   - 确认是否为虚拟机配置了带宽限制。
   - 使用 `virsh edit <vm_name>` 命令检查 `<bandwidth>` 配置。
2. 检查网络流量：
   - 使用 `iftop` 和 `vnstat` 等工具监控网络流量，识别高流量主机和瓶颈。
3. 优化网络配置：
   - 调整虚拟机的网络接口配置，例如使用 Virtio 网络驱动以提高性能。
   - 使用桥接网络模式，确保虚拟机与物理网络的高效通信。

### 日志查看与分析

#### 查看 `libvirt` 网络日志

1. libvirt 日志路径：
   - 在 CentOS/RHEL 上，`libvirt` 日志通常位于 `/var/log/libvirt/` 目录下。
   - 在 Ubuntu 上，`libvirt` 日志通常位于 `/var/log/libvirt/` 目录下。
2. 查看网络日志：
   - 使用 `tail -f /var/log/libvirt/libvirtd.log` 命令查看实时日志。
   - 使用 `grep` 命令筛选关键字以查找特定问题，例如 `grep "network" /var/log/libvirt/libvirtd.log`。

#### 使用系统日志进行排查

1. 查看系统日志：
   - 使用 `journalctl` 命令查看系统日志，例如 `journalctl -u libvirtd` 查看 `libvirtd` 服务的日志。
2. 检查网络相关日志：
   - 使用 `dmesg` 命令查看内核日志，查找与网络相关的错误信息。