在上一篇文章中,我们通过在物理网卡上创建多个VNIC,实现了对物理网卡的复用。实际上,我们创建了一个如图1所示的网络环境。
图1 由VNIC和Zone创建的网络环境
由图1我们可用看出,我们创建了两个虚拟网卡(VNIC):v1和v2,它们和物理网卡bge0一起组成了在本机环境中的一个位于同一子网上的三个链路层可连接对象,即虚拟网卡对象(虽然bge0是一个物理设备,但对Solaris内核中的网络链路层而言,同v1和v2一样,都是链路层可连接对象)。图1中的全局zone和非全局zone都可用看作是一个独立的系统(Zone的引入的初衷就是为了实现软件上相互隔离的操作环境),它们的不同在于全局zone是操作系统安装后提供给用户的操作环境,非全局zone是由用户(一般是特权用户)在全局zone中创建的zone,特权用户可用在全局zone中创建VNIC和非全局zone。但在非全局zone中,即使是特权用户(即使是root用户)也不能创建非全局zone或VNIC。
在这篇文章中,我们将创建一个虚拟网络。在这个网络中,网络的核心组件网卡接口、链路层交换机和路由器都采用Solaris的虚拟化技术实现,在现实应用中,我们可用把这些网络组件当作实际的网络组件使用,并在这个网络中部署客户的网络服务,这些组件可以替代实际的网络组件,不同的是,系统管理员无需拔插网线,仅通过CLI(命令行接口)就可以管理这些组件。
在上一篇文章中,我介绍了VNIC,VNIC可以作为虚拟网络中的网卡来使用。同时,我们也可以使用Solaris具有独立IP协议栈的Zone(Exclusive IP Stack Zone)来实现虚拟路由器(三层交换机)。然而,作为一个完整的LAN,我们还需要链路层交换机来连接位于同一子网的主机。这里,我们可以使用Solaris Crossbow项目中引入的etherstub来扮演虚拟网络中的链路层交换机的角色。创建一个etherstub的命令是:
# dladm create-etherstub <etherstub_name>
我们可以通过"dladm show-link" 或 "dladm show-etherstub"来查看这个etherstub的信息:
# dladm show-link <etherstub_name>
或:
# dladm show-etherstub <etherstub_name>
使用"dladm delete-etherstub <etherstub_name>"可以删除这个etherstub。
下面,我将在不使用物理网络设备的情况下创建一个如图2所示的虚拟网络,而这个网络完全存在于一个Solaris系统中,并且独立于物理网络。如若使其存在并且运行,只需一台主机。
图2 由VNIC,etherstub和Zone创建的虚拟网络结构图
图2中展示了两个网络,我们的目的是让zrouter作为一个路由器,使两个网络中的虚拟主机zclient1和zclient2能相互通信。在这里,zclient1,zclient2和zrouter都是非全局Zone。vclient1,vclient2,vrouter1和vrouter2都是VNIC,VNIC下面标注的是分配给各个VNIC的IP地址。
首先,我们先创建两个etherstub作为链路层交换机:
global-zone# dladm create-etherstub etherstub1
global-zone# dladm create-etherstub etherstub2
global-zone# dladm show-etherstub
LINK
etherstub1
etherstub2
接下来,创建两个VNIC: vclient1和vrouter1,并将其连接到etherstub1上:
global-zone# dladm create-vnic -l etherstub1 vclient1
global-zone# dladm create-vnic -l etherstub1 vrouter1
同理,创建两个VNIC: vclient2和vrouter2,并将其连接到etherstub2上:
global-zone# dladm create-vnic -l etherstub2 vclient2
global-zone# dladm create-vnic -l etherstub2 vrouter2
此时,我们查看一下创建好的VNIC(其中,v1和v2是在上一篇文章中创建好的VNIC):
global-zone# dladm show-vnic
LINK OVER SPEED MACADDRESS MACADDRTYPE VID
v1 bge0 1000 2:8:20:7a:5d:ed random 0
v2 bge0 1000 2:8:20:ee:f0:cc random 0
vclient1 etherstub1 0 2:8:20:60:10:91 random 0
vrouter1 etherstub1 0 2:8:20:eb:f7:c random 0
vclient2 etherstub2 0 2:8:20:8f:86:da random 0
vrouter2 etherstub2 0 2:8:20:5b:d1:74 random 0
下面创建3个非全局Zone,zclient1,zclient2和zrouter:
global-zone# zonecfg -z zclient1
zclient1: No such zone configured
Use 'create' to begin configuring a new zone.
zonecfg:zclient1> create
zonecfg:zclient1> set zonepath=/export/home/zclient1
zonecfg:zclient1> set ip-type=exclusive
zonecfg:zclient1> add net
zonecfg:zclient1:net> set physical=vclient1
zonecfg:zclient1:net> end
zonecfg:zclient1> verify
zonecfg:zclient1> commit
zonecfg:zclient1> exit
global-zone# zonecfg -z zclient2
zclient2: No such zone configured
Use 'create' to begin configuring a new zone.
zonecfg:zclient2> create
zonecfg:zclient2> set zonepath=/export/home/zclient2
zonecfg:zclient2> set ip-type=exclusive
zonecfg:zclient2> add net
zonecfg:zclient2:net> set physical=vclient2
zonecfg:zclient2:net> end
zonecfg:zclient2> verify
zonecfg:zclient2> commit
zonecfg:zclient2> exit
global-zone# zonecfg -z zrouter
zrouter: No such zone configured
Use 'create' to begin configuring a new zone.
zonecfg:zrouter> create
zonecfg:zrouter> set zonepath=/export/home/zrouter
zonecfg:zrouter> set ip-type=exclusive
zonecfg:zrouter> add net
zonecfg:zrouter:net> set physical=vrouter1
zonecfg:zrouter:net> end
zonecfg:zrouter> add net
zonecfg:zrouter:net> set physical=vrouter2
zonecfg:zrouter:net> end
zonecfg:zrouter> verify
zonecfg:zrouter> commit
zonecfg:zrouter> exit
下面通过clone,安装上面刚创建的三个Zone,其中zone1是上一篇文章中创建的Zone,使用zoneadm(1M)中的clone子命令安装Zone会比zoneadm(1M)中的install子命令要快很多:
global-zone# zoneadm -z zclient1 clone zone1
global-zone# zoneadm -z zclient2 clone zone1
global-zone# zoneadm -z zrouter clone zone1
global-zone# zoneadm list -cv
ID NAME STATUS PATH BRAND IP
0 global running / ipkg shared
- zone1 installed /export/home/zone1 ipkg excl
- zclient1 installed /export/home/zclient1 ipkg excl
- zclient2 installed /export/home/zclient2 ipkg excl
- zrouter installed /export/home/zrouter ipkg excl
global-zone# zoneadm -z zclient1 boot
global-zone# zoneadm -z zclient2 boot
global-zone# zoneadm -z zrouter boot
然后,大家可以通过"zlogin -C <zone_name>"来配置如图2所示的每个Zone的IP地址。通过这一番配置,每个Zone的地址配置如下:
global-zone# zlogin zclient1 ifconfig -a4
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
vclient1: flags=1000863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST,IPv4> mtu 9000 index 2
inet 10.1.1.11 netmask ffffff00 broadcast 10.1.1.255
ether 2:8:20:60:10:91
global-zone# zlogin zclient2 ifconfig -a4
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
vclient2: flags=1000863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST,IPv4> mtu 9000 index 2
inet 10.1.2.11 netmask ffffff00 broadcast 10.1.2.255
ether 2:8:20:8f:86:da
global-zone# zlogin zrouter ifconfig -a4
lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
inet 127.0.0.1 netmask ff000000
vrouter1: flags=1000863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST,IPv4> mtu 9000 index 2
inet 10.1.1.12 netmask ffffff00 broadcast 10.1.1.255
ether 2:8:20:eb:f7:c
vrouter2: flags=1000863<UP,BROADCAST,NOTRAILERS,RUNNING,MULTICAST,IPv4> mtu 9000 index 3
inet 10.1.2.12 netmask ffffff00 broadcast 10.1.2.255
ether 2:8:20:5b:d1:74
此时,我们仍然无法从网络10.1.1.0/24上的主机zclient1连接到网络10.1.2.0/24上的主机zclient2,因为虽然zrouter中有两个IP接口,但是zrouter还未开启路由和转发数据包的服务。我们可以这样做来打开zrouter服务:
global-zone# zlogin zrouter routeadm -e ipv4-routing -u
global-zone# zlogin zrouter routeadm -e ipv4-forwarding -u
并开启zclient1和zclient2中的路由发现服务来建立默认路由(默认路由发现服务是打开的,如果被关闭了,就运行下面的命令):
global-zone# zlogin zclient1 routeadm -e ipv4-routing -u
global-zone# zlogin zclient2 routeadm -e ipv4-routing -u
这样,属于两个不同子网的主机zclient1和zclient2就可以相互连接了,我们可以用ping发包试一下:
global-zone# zlogin zclient1
[Connected to zone 'zclient1' pts/4]
root@zclient1:~# ping 10.1.2.11
10.1.2.11 is alive
root@zclient1:~# ping -U 10.1.2.11
10.1.2.11 is alive
在zclient2上,我们可以用snoop(1M)看到ICMP包应答:
global-zone# zlogin zclient2
[Connected to zone 'zclient2' pts/5]
root@zclient2:~# snoop -rd vclient2 udp or icmp
Using device vclient2 (promiscuous mode)
10.1.1.11 -> 10.1.2.11 ICMP Echo request (ID: 12967 Sequence number: 0)
10.1.2.11 -> 10.1.1.11 ICMP Echo reply (ID: 12967 Sequence number: 0)
10.1.1.11 -> 10.1.2.11 UDP D=33434 S=44329 LEN=64
10.1.2.11 -> 10.1.1.11 ICMP Destination unreachable (UDP port 33434 unreachable)
至此,我们已经用Crossbow项目中的网络虚拟化技术创建了一个由两个子网组成的网络,这就是所谓的NB(Network in a Box)。这么一个和物理网络隔绝的网络在实际提供网络服务的环境中作用不大,但我们能很方便地在一个物理主机上建立一个趋近于真实的并且“与世隔绝”的网络环境,这对网络服务器测试或网络实验会有很大帮助。如果想让zclient1和zclient2作为一个真正主机访问外网,或者将这两个非全局Zone作为网络服务器使用(比如,一个活动服务器,一个备份服务器)。我们可以这样设置一下zrouter使其作为可以访问外网10.11.19.0/24的路由器:
图3 连接到物理网络的虚拟网络
如图3所示,我们基于物理网卡bge0创建了一个名为v3的VNIC,并将其分配给zrouter:
global-zone# zoneadm -z zrouter halt
global-zone# zonecfg -z zrouter
global-zone# dladm create-vnic -l bge0 v3
global-zone# zonecfg -z zrouter
zonecfg:zrouter> add net
zonecfg:zrouter:net> set physical=v3
zonecfg:zrouter:net> end
zonecfg:zrouter> commit
zonecfg:zrouter> exit
global-zone# zoneadm -z zrouter boot
global-zone# zlogin zrouter ifconfig v3 plumb 10.11.19.172/24 up
global-zone# zlogin zrouter route add default 10.11.19.1
通过这番设置,一个物理主机上的虚拟网络就可以访问外部网络了。由此可见,Solaris Crossbow项目中的网络虚拟化技术对提供网络资源利用率,建立冗余网络服务器和提高安全性有很大作用。通过这样一个虚拟网络,我们不仅提供了一个真实网络下的服务环境,而且极大增加了物理资源的可用性,使复杂的网络配置不再局限于硬件的约束。
然而,Crossbow项目所带来的新特性不仅仅是网络虚拟化方面的技术。从下一篇文章里,我将开始介绍网络资源管理部分。