问题描述
在 KVM 中,我们经常为虚拟机选择桥接网络,以使虚拟机暴露在内网中,可以被其他主机访问。
但是,使用桥接网络的问题是:虚拟机(Guest)无法访问宿主机(Host),而我们希望两者能够互相访问。
该笔记将记录:在 KVM 中,如何实现宿主机与虚拟机的相互访问,以及常见问题的处理方法。
问题原因
在 KVM 中,Guest 在桥接模式下,无法访问 Host 主机,这并不是错误,而是 macvtap 设备的特性。物理设备绑定到 macvtap 网桥,进入网桥的流量被转发到了设备上,不通过Host的IP网络栈。除此之外,从Host的IP网络栈发出的流量被发往物理设备,也不会反弹到macvtap设备上。
解决方案
方案一、创建隔离网络
原理简述:其实并不复杂,这种做法相当于“为 Guest 添加 NAT 网卡”,这样 Guest 访问 Host 主机。但是,实际上并没有 NAT 转发,所以称为隔离网络。
操作步骤如下:
# 在 Host 上,创建隔离网络(修改 KVM 网络)
cat > /tmp/isolated.xml <<EOF
<network>
<name>isolated</name>
<ip address='192.168.254.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.254.2' end='192.168.254.254' />
</dhcp>
</ip>
</network>
EOF
virsh net-define /tmp/isolated.xml
virsh net-autostart isolated
virsh net-start isolated
# 修改 Host 网络配置,使用隔离网络;
# 如果使用 virt-manager 图形化工具,在为虚拟机添加网卡,选择 isolated 网络
# 或者,使用 virsh edit 修改:
<devices>
<interface type='network'>
<source network='isolated'/>
<model type='virtio'/>
</interface>
</devices>
方案二、为 Host 创建 MACVLAN 网卡
原理简述:其实很简单,Guest 所使用的网卡都是基于物理网卡派生出来的 MACVLAN 类型网卡,那么我们也可以为 Host 创建 MACVLAN 类型网卡。这样,所有的 Guest 与 Host 便可通信,此时所有主机(Guest、Host)都使用同一物理网卡派生出来的 MACVLAN 类型网卡。
操作步骤如下:
# 在 Host 中,创建 macvlan 网卡
# ipv4.method auto:为了说明问题,我们没有使用冗长的网络配置
# ipv4.route-metric 0:为了使该 macvlan 网卡成为优先级最高的路由(这样我们就不用停止原先的网络配置)
nmcli connection add \
connection.type "macvlan" macvlan.mode "bridge" macvlan.parent "enp2s0f0" \
connection.interface-name "kvm-guest2host" \
connection.id "kvm-guest2host" \
ipv4.method auto \
ipv4.route-metric 0
nmcli connection up "kvm-guest2host"
# 在 Guest 中,要保证 Guest 也是使用 enp2s0f0 网卡派生的 macvtap 设备,并使用 bridge 模式
# 通常情况,不用修改,因为我们一般都使用这种模式。
注意事项:如果不了解 MACVLAN 与 MACVTAP 等等技术的背后工作方式,建议先阅读相关技术文章,复制粘贴并不能保证成功运行(虽然我们测试成功,但是我们无法枚举所有的场景)。
方案三、适用于我们的方案
解决方法:因为 Host 有两块网卡,所有的虚拟化主机使用第一块网卡,而第二块网卡我们专门留给 Host 使用,这样就绕开 macvtap 的问题
当然,最后我们通过这种方式实现 Guest 访问 Host 主机,因为我们不希望把环境搞的太复杂。但是对于 Linux 桌面环境,可以考虑前面的方案。
补充说明
# 03/11/2021 我们又重新审视我们的问题,最后放弃 Guest 访问 Host 的做法。因为只是一种特殊需求:Host 本就处于虚拟化的底层,不应该让 Guest 访问 Host 主机。而我们之所以希望 Guest 访问 Host,是因为我们建立一种不常见的环境。这种“不常见的环境”是指“我们的用法并不符合 KVM 的设计目的”。
参考文献
KVM/Networkinglibvirt network error - no 'default' network device foundB.9. Guest Can Reach Outside Network, but Cannot Reach Host when Using macvtap Interface Red Hat Enterprise Linux 6Enabling host-guest networking with KVM, Macvlan and Macvtap ♎ Furor Teutonicus