Linux Bridge 基本概念

假设宿主机有 1 块与外网连接的物理网卡eth0,上面跑了 1 个虚机 VM1,现在有个问题是:
如何让 VM1 能够访问外网?
至少有两种方案

  1. 将物理网卡eth0直接分配给VM1,但随之带来的问题很多:
  • 宿主机就没有网卡,无法访问了;

  • 新的虚机,比如VM2 也没有网卡。

下面看推荐的方案

  1. 给 VM1 分配一个虚拟网卡 vnet0,通过 Linux Bridge br0 将 eth0 和 vnet0 连接来,如下图所示

KVM网络虚拟化 - 图1
Linux Bridge 是 Linux **上用来做 TCP/IP 二层协议交换的设备**,其功能大家可以简单的理解为是一个二层交换机或者Hub。多个网络设备可以连接到同一个 Linux Bridge,当某个设备收到数据包时,Linux Bridge 会将数据转发给其他设备。
在上面这个例子中,当有数据到达 eth0 时,br0会将数据转发给 vnet0,这样 VM1 就能接收到来自外网的数据;
反过来,VM1 发送数据给 vnet0,br0 也会将数据转发到 eth0,从而实现了 VM1 与外网的通信。
现在我们增加一个虚机 VM2,如下图所示
KVM网络虚拟化 - 图2

VM2 的虚拟网卡 vnet1 也连接到了 br0 上。
现在 VM1 和 VM2 之间可以通信,同时 VM1 和 VM2 也都可以与外网通信。

理解 virbr0


virbr0 是 KVM **默认创建的一个 Bridge,其作用是为连接其上的虚机网卡提供 NAT 访问外网的功能。
virbr0 默认分配了一个IP 192.168.122.1,并为连接其上的其他虚拟网卡提供 DHCP 服务。
下面我们演示如何使用 virbr0。
在 virt-manager 打开 VM1 的配置界面,
网卡 Source device 选择 “default”**,将 VM1 的网卡挂在 virbr0 上。

启动 VM1,brctl show 可以查看到 vnet0 已经挂在了 virbr0 上。
# brctlshow
bridge namebridge id STP enabledinterfaces
br08000.000c298decbe noeth0
virbr08000.fe540075dd1a yesvnet0
用 virsh 命令确认 vnet 就是 VM1 的虚拟网卡。
# virshdomiflist VM1
InterfaceType Source Model MAC
———————————————————————————-
vnet0network default rtl8139 52:54:00:75:dd:1a
virbr0 使用 dnsmasq 提供 DHCP 服务,可以在宿主机中查看该进程信息
# ps-elf|grep dnsmasq5S libvirt+ 2422 1 0 80 0 - 7054poll_s 11:26 ? 00:00:00 /usr/sbin/dnsmasq—conf-file=/var/lib/libvirt/dnsmasq/default.conf
在 /var/lib/libvirt/dnsmasq/ 目录下有一个 default.leases 文件,当 VM1 成功获得 DHCP 的 IP 后,可以在该文件中查看到相应的信息
# cat/var/lib/libvirt/dnsmasq/default.leases
144177 52:54:00:75:dd:1a192.168.122.6 ubuntu
上面显示 192.168.122.6 已经分配给 MAC 地址为 *52:54:00:75:dd:1a
的网卡,这正是 vnet0 的 MAC。之后就可以使用该 IP 访问 VM1 了。

虚拟机VLAN介绍

LAN 表示 Local Area Network,本地局域网,通常使用 Hub 和 Switch 来连接 LAN 中的计算机。
一般来说,两台计算机连入同一个 Hub 或者 Switch 时,它们就在同一个 LAN 中。

一个 LAN 表示一个广播域。其含义是:LAN 中的所有成员都会收到任意一个成员发出的广播包。

VLAN 表示 Virtual LAN。一个带有 VLAN 功能的switch 能够将自己的端口划分出多个 LAN。
计算机发出的广播包可以被同一个 LAN 中其他计算机收到,但位于其他 LAN 的计算机则无法收到。简单地说,VLAN 将一个交换机分成了多个交换机,限制了广播的范围,在二层将计算机隔离到不同的 VLAN 中。

比方说,有两组机器,Group A 和 B。
我们想配置成 Group A 中的机器可以相互访问,Group B 中的机器也可以相互访问,但是 A 和 B 中的机器无法互相访问。
一种方法是使用两个交换机,A 和 B 分别接到一个交换机。另一种方法是使用一个带 VLAN 功能的交换机,将 A 和 B 的机器分别放到不同的 VLAN 中。

请注意,VLAN 的隔离是二层上的隔离,A 和 B 无法相互访问指的是二层广播包(比如 arp)无法跨越 VLAN 的边界。
但在三层上(比如IP)是可以通过路由器让 A 和 B 互通的。概念上一定要分清。

现在的交换机几乎都是支持 VLAN 的。通常交换机的端口有两种配置模式: Access 和 Trunk。看下图
KVM网络虚拟化 - 图3
Access 口
这些端口被打上了 VLAN 的标签,表明该端口属于哪个 VLAN。不同 VLAN 用 VLAN ID 来区分,VLAN ID 的 范围是 1-4096。Access 口都是直接与计算机网卡相连的,这样从该网卡出来的数据包流入 Access 口后就被打上了所在 VLAN 的标签。Access 口只能属于一个 VLAN。

Trunk 口
假设有两个交换机 A 和 B。A 上有 VLAN1(红)、VLAN2(黄)、VLAN3(蓝);B 上也有 VLAN1、2、3那如何让 AB 上相同 VLAN 之间能够通信呢?

办法是将 A 和 B 连起来,而且连接 A 和 B 的端口要允许 VLAN1、2、3 三个 VLAN 的数据都能够通过。
这样的端口就是Trunk口了。VLAN1、2、3 的数据包在通过 Trunk 口到达对方交换机的过程中始终带着自己的 VLAN 标签。

了解了 VLAN 的概念之后,我们来看 KVM 虚拟化环境下是如何实现 VLAN 的。还是先看图,
KVM网络虚拟化 - 图4
eth0 是宿主机上的物理网卡,有一个命名为 eth0.10 的子设备与之相连。eth0.10 就是 VLAN 设备了,其 VLAN ID 就是 VLAN 10。eth0.10 挂在命名为 brvlan10 的 Linux Bridge 上,虚机 VM1 的虚拟网卡 vent0 也挂在 brvlan10 上。

这样的配置其效果就是:宿主机用软件实现了一个交换机(当然是虚拟的),上面定义了一个 VLAN10。eth0.10,brvlan10 和 vnet0 都分别接到 VLAN10 的 Access口上。而 eth0 就是一个 Trunk 口。
VM1 通过 vnet0 发出来的数据包会被打上 VLAN10 的标签。

eth0.10 的作用是:定义了 VLAN10brvlan10 的作用是:Bridge 上的其他网络设备自动加入到 VLAN10 中

我们再增加一个 VLAN20,见下图
KVM网络虚拟化 - 图5
这样虚拟交换机就有两个 VLAN 了,VM1 和 VM2 分别属于 VLAN10 和 VLAN20。对于新创建的虚机,只需要将其虚拟网卡放入相应的 Bridge,就能控制其所属的 VLAN。

VLAN 设备总是以母子关系出现,母子设备之间是一对多的关系。一个母设备(eth0)可以有多个子设备(eth0.10,eth0.20 ……),而一个子设备只有一个母设备