在 KVM/Libvirt 中:如何在一台主机上拥有两个具有相同 IP 范围的 NAT 网络?

在 KVM/Libvirt 中:如何在一台主机上拥有两个具有相同 IP 范围的 NAT 网络?

我正在尝试使用 KVM 和 libvirt 来测试虚拟机中的一些基础设施设置,基本上我是在网络内启动虚拟机。

就我而言,该虚拟机和网络必须始终具有相同的静态 IP 配置(例如网络 192.168.125.0/24,虚拟机 IP 为 192.168.125.50)。

现在我想知道是否可以在同一主机上并行运行两个这样的测试。但是,在这种情况下,libvirt 不允许我同时创建两个具有相同 IP 范围的 NAT 网络。

有没有办法解决这个限制?

答案1

这是可能的,但您需要自己处理所有网络设置。基本过程如下所示:

  1. 手动创建几个桥接设备。为他们提供不同的 IP 地址,(a) 位于不同的网络上,(b) 位于不同的网络上不是在 192.168.125.0/24 网络上。

  2. 为每个虚拟网络创建一个命名空间,并通过接口将其链接到相应的网桥veth。为该接口指定 (a) 地址 192.168.125.1/24 和 (b) 与关联网桥位于同一网络上的地址。

  3. dnsmasq在配置为为 192.168.125.0/24 网络提供 DHCP 地址的每个命名空间中运行一项服务。为您的虚拟机配置静态条目(要求您在创建虚拟机时在虚拟机上设置静态 MAC 地址),或者仅将其配置为分发单个地址。

  4. 在命名空间中设置伪装规则,以伪装来自 192.168.125.0/24 网络的流量。

所有这些看起来都是这样的:

#!/bin/sh

ip link add br-net1 type bridge
ip link add br-net2 type bridge

ip addr add 10.10.10.1/24 dev br-net1
ip addr add 10.20.20.1/24 dev br-net2

ip link set br-net1 up
ip link set br-net2 up

ip netns add net1
ip netns add net2

ip link add net1-ext type veth peer name net1-int netns net1
ip link add net2-ext type veth peer name net2-int netns net2
ip link set net1-ext master br-net1 up
ip link set net2-ext master br-net2 up

ip -n net1 addr add 192.168.125.1/24 dev net1-int
ip -n net1 addr add 10.10.10.10/24 dev net1-int
ip -n net1 link set net1-int up
ip -n net1 route add default via 10.10.10.1

ip -n net2 addr add 192.168.125.1/24 dev net2-int
ip -n net2 addr add 10.20.20.10/24 dev net2-int
ip -n net2 link set net2-int up
ip -n net2 route add default via 10.20.20.1

ip netns exec net1 iptables -t nat -A POSTROUTING -s 192.168.125.0/24 -j MASQUERADE
ip netns exec net2 iptables -t nat -A POSTROUTING -s 192.168.125.0/24 -j MASQUERADE

rm -f /tmp/net1.{log,pid}
rm -f /tmp/net2.{log,pid}

ip netns exec net1 \
  dnsmasq -C /dev/null -k --dhcp-range 192.168.125.50,192.168.125.50 \
  --log-facility /tmp/net1.log --log-dhcp \
  --pid-file=/tmp/net1.pid \
  &

ip netns exec net2 \
  dnsmasq -C /dev/null -k --dhcp-range 192.168.125.50,192.168.125.50 \
  --log-facility /tmp/net2.log --log-dhcp \
  --pid-file=/tmp/net2.pid \
  &

这些更改都不是持久的,因此只需重新启动即可清除所有内容。


完成上述配置后,我可以net1像这样启动虚拟机:

virt-install \
  --cloud-init ssh-key=/home/lars/.ssh/id_rsa_default.pub  \
  --disk pool=default,size=10,backing_store=jammy-server-cloudimg-amd64.img,backing_format=qcow2 -n ubuntu.net1.virt -r 4096  \
  --import  \
  --osinfo ubuntujammy  \
  --noautoconsole \
  --network bridge=br-net1

或者像net2这样:

virt-install \
  --cloud-init ssh-key=/home/lars/.ssh/id_rsa_default.pub  \
  --disk pool=default,size=10,backing_store=jammy-server-cloudimg-amd64.img,backing_format=qcow2 -n ubuntu.net2.virt -r 4096  \
  --import  \
  --osinfo ubuntujammy  \
  --noautoconsole \
  --network bridge=br-net2

两台机器都会有地址192.168.125.50。我可以通过ssh在适当的命名空间中运行来 ssh 进入这些机器:

sudo ip netns exec net1 ssh -i ~/.ssh/id_rsa_oddbit [email protected]

通过此配置,机器能够访问我的主持人,但他们没有一般的出站访问权限。要启用此功能,需要MASQUERADE在主机上添加一些附加规则。

相关内容