openstack kvm Openstack KVM网络优化_IP

 

  网络虚拟化是虚拟化技术中最复杂的部分,学习难度最大。 但因为网络是虚拟化中非常重要的资源,所以再硬的骨头也必须要把它啃下来。

为了让大家对虚拟化网络的复杂程度有一个直观的认识,请看下图:

openstack kvm Openstack KVM网络优化_外网_02

这是 OpenStack 官网上给出的计算节点(可以理解为 KVM 的宿主机)虚拟网络的逻辑图,上面的网络设备很多,层次也很复杂。
我第一次看到这张图,也着实被下了一跳。

不过大家也不要怕,万丈高楼从地起,虚拟网络再复杂,也是由一些基础的组件构成的。只要我们将这些基础组件的概念和它们之间的逻辑关系搞清楚了,就能深刻理解虚拟网络的架构,那么云环境下的虚拟化网络也就不在话下了。

下面我们来学习网络虚拟化中最重要的两个东西:Linux Bridge 和 VLAN

Linux Bridge 基本概念

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

至少有两种方案

  1. 将物理网卡eth0直接分配给VM1,但随之带来的问题很多: 宿主机就没有网卡,无法访问了; 新的虚机,比如 VM2 也没有网卡。 下面看推荐的方案
  2. 给 VM1 分配一个虚拟网卡 vnet0,通过 Linux Bridge  br0 将 eth0 和 vnet0 连接起来,如下图所示

Linux Bridge 是 Linux 上用来做 TCP/IP 二层协议交换的设备,其功能大家可以简单的理解为是一个二层交换机或者 Hub。多个网络设备可以连接到同一个 Linux Bridge,当某个设备收到数据包时,Linux Bridge 会将数据转发给其他设备。

在上面这个例子中,当有数据到达 eth0 时,br0 会将数据转发给 vnet0,这样 VM1 就能接收到来自外网的数据; 反过来,VM1 发送数据给 vnet0,br0 也会将数据转发到 eth0,从而实现了 VM1 与外网的通信。

现在我们增加一个虚机 VM2,如下图所示

openstack kvm Openstack KVM网络优化_DHCP_03

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

有了上面的基础知识,下一节将演示如何在实验环境中实现这套虚拟网络。

openstack kvm Openstack KVM网络优化_外网_04

配置 Linux Bridge br0

编辑 /etc/network/interfaces,配置 br0。

下面用 vimdiff 展示了对 /etc/network/interfaces 的修改

openstack kvm Openstack KVM网络优化_外网_05

有两点需要注意:

1. 之前宿主机的 IP 是通过 dhcp 配置在 eth0 上的;创建 Linux Bridge 之后,IP 就必须放到 br0 上了

2. 在 br0 的配置信息中请注意最后一行 “bridge_ports eth0”,其作用就是将 eth0 挂到 br0 上

重启宿主机,查看 IP 配置,可以看到 IP 已经放到 br0 上了

 

用 brctl show 查看当前 Linux Bridge 的配置。 eth0 已经挂到 br0 上了

 

除了 br0,大家应该注意到还有一个 virbr0 的 Bridge,而且 virbr0 上已经配置了 IP 地址 192.168.122.1。 virbr0 的作用我们会在后面介绍。

在宿主机中 CloudMan 已经提前创建好了虚机 VM1 和 VM2,现在都处于关机状态

# virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     VM1                            shut off
 -     VM2                            shut off

配置 VM1

下面我们在 virt-manager 中查看一下 VM1 的网卡配置(为了使大家能够熟练使用命令行工具 virsh 和图形工具 virt-manager,CloudMan 在演示的时候会同时用到它们,两个工具都很重要)

openstack kvm Openstack KVM网络优化_外网_06

可以看到虚拟网卡的 source device 我们选择的是 br0

下面我们启动 VM1,看会发生什么

# virsh start VM1
Domain VM1 started
 

# brctl show

bridge name     bridge id               STP enabled     interfaces
br0             8000.000c298decbe       no                    eth0
                                                                                  vnet0
virbr0          8000.000000000000       yes

brctl show 告诉我们 br0 下面添加了一个 vnet0 设备,通过 virsh 确认这就是VM1的虚拟网卡。

# virsh domiflist VM1
Interface  Type       Source     Model       MAC
-------------------------------------------------------
vnet0      bridge     br0        rtl8139     52:54:00:75:dd:1a

VM1 的 IP 是 DHCP 获得的(设置静态 IP 当然也可以),通过 virt-manager 控制台登录 VM1,查看 IP。

# ifconfig
eth0      Link encap:Ethernet  HWaddr 52:54:00:75:dd:1a
          inet addr:192.168.111.106  Bcast:192.168.111.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:ff:fe75:dd1a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:400 errors:0 dropped:0 overruns:0 frame:0
          TX packets:101 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:41950 (41.9 KB)  TX bytes:12583 (12.5 KB)

VM1 通过 DHCP 拿到的 IP 是 192.168.111.106,与宿主机(IP为192.168.111.107)是同一个网段。Ping 一下外网

root@VM1:~# ping www.baidu.com
PING www.a.shifen.com (180.97.33.108) 56(84) bytes of data.
64 bytes from 180.97.33.108: icmp_seq=1 ttl=53 time=34.9 ms
64 bytes from 180.97.33.108: icmp_seq=2 ttl=53 time=36.2 ms
64 bytes from 180.97.33.108: icmp_seq=3 ttl=53 time=38.8 ms

没问题,可以访问。

另外,在 VM1 中虚拟网卡是 eth0,并不是 vnet0。 vnet0 是该虚拟网卡在宿主机中对应的设备名称,其类型是 TAP 设备,这里需要注意一下。

配置 VM2

跟 VM1 一样,VM2 的虚拟网卡也挂在 br0上,启动 VM1,查看网卡信息

# virsh start VM2
Domain VM2 started
 

# brctl show

bridge name     bridge id               STP enabled     interfaces
br0             8000.000c298decbe       no                    eth0
                                                                                  vnet0
                                                                                  vnet1
virbr0          8000.000000000000       yes

br0 下面多了 vnet1,通过 virsh 确认这就是 VM2 的虚拟网卡。

# virsh domiflist VM2
Interface  Type       Source     Model       MAC
-------------------------------------------------------
vnet0      bridge     br0        rtl8139     52:54:00:cf:33:a1

VM2 通过 DHCP 拿到的 IP 是 192.168.111.108,登录 VM2,验证网络的连通性

Ping VM1

Ping 宿主机

Ping 外网

可见,通过 br0 这个 Linux Bridge,我们实现了 VM1、VM2、宿主机和外网这四者之间的数据通信。

 

virbr0

virbr0 是一种虚拟网络接口, 这是由于安装和启用了 libvirt 服务后生成的,libvirt 在服务器(host)上生成一个 virtual network switch (virbr0),host 上所有的虚拟机(guests)通过这个 virbr0 连起来。默认情况下 virbr0 使用的是 NAT 模式(采用 IP Masquerade),所以这种情况下 guest 通过 host 才能访问外部。

 

virbr0 默认分配了一个IP 192.168.122.1,并为连接其上的其他虚拟网卡提供 DHCP 服务。

 

下面我们演示如何使用 virbr0。

在 virt-manager 打开 VM1 的配置界面,网卡 Source device 选择 “default”,将 VM1 的网卡挂在 virbr0 上。

 

启动 VM1,brctl show 可以查看到 vnet0 已经挂在了 virbr0 上。

# brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.000c298decbe       no                    eth0
virbr0          8000.fe540075dd1a       yes                   vnet0

用 virsh 命令确认 vnet 就是 VM1 的虚拟网卡。

# virsh domiflist VM1
Interface  Type       Source     Model       MAC
-------------------------------------------------------
vnet0      network    default    rtl8139     52:54:00:75:dd:1a

virbr0 使用 dnsmasq 提供 DHCP 服务,可以在宿主机中查看该进程信息

 这里可以看到libvirt提供的默认dhcp配置文件路径 /var/lib/libvirt/dnsmasq/defualt.conf

 

# ps -elf|grep dnsmasq

  5 S libvirt+  2422     1  0  80   0 -  7054 poll_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
1441525677 52:54:00:75:dd:1a 192.168.122.6 ubuntu *

上面显示 192.168.122.6 已经分配给 MAC 地址为 52:54:00:75:dd:1a 的网卡,这正是 vnet0 的 MAC。之后就可以使用该 IP 访问 VM1 了,VM1也可以通过NAT访问外部网络。

 

Linux Bridge + VLAN

本节我们来看如何在实验环境中实施和配置如下 VLAN 网络

openstack kvm Openstack KVM网络优化_DHCP_07

配置 VLAN

编辑 /etc/network/interfaces,配置 eth0.10、brvlan10、eth0.20 和 brvlan20。

下面用 vmdiff 展示了对 /etc/network/interfaces 的修改

openstack kvm Openstack KVM网络优化_IP_08

重启宿主机,ifconfig 各个网络接口

openstack kvm Openstack KVM网络优化_外网_09

用 brctl show 查看当前 Linux Bridge 的配置。 eth0.10 和 eth0.20 分别挂在 brvlan10 和 brvlan20上了

openstack kvm Openstack KVM网络优化_外网_10

配置 VM1

在 virt-manager 中将 VM1 的虚拟网卡挂到 brvlan10 上。

openstack kvm Openstack KVM网络优化_外网_11

查看 Bridge,发现 brvlan10 已经连接了一个 vnet0 设备

openstack kvm Openstack KVM网络优化_IP_12

通过 virsh 确认这就是 VM1 的虚拟网卡。

openstack kvm Openstack KVM网络优化_IP_13

VM1启动后就可以正常和其他网络通信了。

Linux Bridge + VLAN = 虚拟交换机

现在对 KVM 的网络虚拟化做个总结。

  1. 物理交换机存在多个 VLAN,每个 VLAN 拥有多个端口。 同一 VLAN 端口之间可以交换转发,不同 VLAN 端口之间隔离。 所以交换机其包含两层功能:交换与隔离
  2. Linux 的 VLAN 设备实现的是隔离功能,但没有交换功能。 一个 VLAN 母设备(比如 eth0)不能拥有两个相同 ID 的 VLAN 子设备,因此也就不可能出现数据交换情况。
  3. Linux Bridge 专门实现交换功能。 将同一 VLAN 的子设备都挂载到一个 Bridge 上,设备之间就可以交换数据了。

总结起来,Linux Bridge 加 VLAN 在功能层面完整模拟现实世界里的二层交换机。

eth0 相当于虚拟交换机上的 trunk 口,允许 vlan10 和 vlan20 的数据通过 eth0.10,vent0 和 brvlan10 都可以看着 vlan10 的 access 口 eth0.20,vent1 和 brvlan20 都可以看着 vlan20 的 access 口。