【Docker网络原理分析一】创建ns+bridge实现两个隔离网络通信

环境: centos7.3

前提:最好了解namespace和bridge

对docker的学习以及docker网络的学习也有一段时间了,想通过linux的一些命令以及namespace和路由实现一个类似docker网络的结构。我们先创建两个网络namespace,相当于创建两个容器实现网络隔离。我们再通过brctl创建一个linux的网桥,这个网桥就类似于docker中的docker0网桥。创建两个了隔离的ns我们就可以想象成两天新买的服务器,它们没有网络配置。而新建的网桥就相当于一个类似路由器的设备。我们接下来就需要给两个"新的服务器"(ns)配置IP以及连接它们到网桥上。这样就完成了第一步,连接在"网桥"上的"两台主机"是可以通信的。

创建两个ns(可以类比于新买的两台服务器)

#创建两个ns
ip netns add net1
ip netns add net2
#创建成功了,查看两个ns
ip netns list
#如果创建错误了,使用下面命令删除
ip netns del <netns-name>

创建一个linux的网桥

#没有brctl先安装
yum  install -y bridge-utils
#创建一个linux的网桥
brctl addbr bridge0
#查看创建的网桥,注意新建网桥的state的是DOWN
#还能看到新建的网桥并没有配置IP
[root@localhost ~]# ip addr  show bridge0
6: bridge0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether fe:ff:11:30:b3:fd brd ff:ff:ff:ff:ff:ff
#通过brctl show查看,可以查看网桥上依附的接口
[root@localhost ~]# brctl show
bridge name	  bridge id		      STP enabled	  interfaces
bridge0		  8000.000000000000	      no	

以上的操作,我们先创建两个ns(两个服务器),一个bridge(路由器),接下来我们需要通过这个bridge让两个ns(两个服务器)能相互通信。现实社会中,我们需要一个网线把他们连接起来,在虚拟网络中,我们需要veth-pair设备,它是一对虚拟的网络设备对。就像使用网线那样,我们一端放在ns中,一端依附在网桥上,同时给ns端的设备配上IP地址。同时也给网桥配上IP地址。同理,我们也给另一个ns做相同的操作。这样就相当于,两台服务器通过网络设备对veth-pair 连接到路由器上。

#创建两对veth-pair设备
ip link add   veth1 type veth peer name veth_peer1
ip link add   veth2 type veth peer name veth_peer2
#查看创建的veth-pair设备(部分截图)
#新创建的设备都是DOWN状态,我们需要他们都启动了
7: veth_peer1@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether d2:64:d2:45:4d:33 brd ff:ff:ff:ff:ff:ff
8: veth1@veth_peer1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 42:54:a0:9b:a3:56 brd ff:ff:ff:ff:ff:ff
9: veth_peer2@veth2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 52:bf:16:34:9e:31 brd ff:ff:ff:ff:ff:ff
10: veth2@veth_peer2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether ba:51:66:8e:b8:19 brd ff:ff:ff:ff:ff:ff

现在创建好了网线,我们需要一端放入ns中。一端附着到网桥中,并且把他们state都启动起来。

#把veth1放到ns1中
ip link set veth1 netns net1
#把veth_peer1依附到bridge0上
ip link set veth_peer1 master bridge0
#把veth_peer1设置为启动状态
ip link set veth_peer1 up

#同理,下面的操作
ip link set veth2 netns net2
ip link set veth_peer2 master bridge0
ip link set veth_peer2 up

查看veth_peer的状态,以及依附到网桥上的接口

7: veth_peer1@if8: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master bridge0 state LOWERLAYERDOWN group default qlen 1000
    link/ether d2:64:d2:45:4d:33 brd ff:ff:ff:ff:ff:ff link-netnsid 1
9: veth_peer2@if10: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue master bridge0 state LOWERLAYERDOWN group default qlen 1000
    link/ether 52:bf:16:34:9e:31 brd ff:ff:ff:ff:ff:ff link-netnsid 2
[root@localhost ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
bridge0		8000.52bf16349e31	no		veth_peer1
							veth_peer2

我们给veth-pair依附到bridge上,另一端放入ns中,接下来需要把ns中的虚拟设备配置好IP并且启动。相当于服务器的网卡配置IP并且启动网卡。

#因为不同的ns,网络操作都是隔离的,我们需要在各自的ns中执行操作,就相当于各自的服务器中执行操作
#给net1中的veth1配置IP
ip netns exec net1 ip addr add  10.10.1.2/24 dev  veth1
#设置veth1状态是UP
ip netns exec net1 ip link set veth1 up
#查看net1中的网络设备
[root@localhost ~]# ip netns exec net1 ip addr 
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
8: veth1@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 42:54:a0:9b:a3:56 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.10.1.2/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::4054:a0ff:fe9b:a356/64 scope link 
       valid_lft forever preferred_lft forever
#同理,我们配置ns2
[root@localhost ~]# ip netns exec net2 ip addr add  10.10.1.3/24 dev  veth2
[root@localhost ~]# ip netns exec net2 ip link set veth2 up
[root@localhost ~]# ip netns exec net2 ip addr
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
10: veth2@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether ba:51:66:8e:b8:19 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.10.1.3/24 scope global veth2
       valid_lft forever preferred_lft forever
    inet6 fe80::b851:66ff:fe8e:b819/64 scope link 
       valid_lft forever preferred_lft forever

现在,有一根网线(veth-pair)把ns和bridg连接起来,但是bridge并没有配置IP地址,也没有启动。如果bridge没有IP地址,Linux协议栈不会给brige转发数据。所以我们需要配置bridge的地址以及启动它。

#配置bridge的地址
ip addr add 10.10.1.1/24 dev bridge0
#配置bridge0启动
ip link set bridge0 up
#查看配置好的bridge0
[root@localhost ~]# ip addr show bridge0
6: bridge0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 52:bf:16:34:9e:31 brd ff:ff:ff:ff:ff:ff
    inet 10.10.1.1/24 scope global bridge0
       valid_lft forever preferred_lft forever
    inet6 fe80::50bf:16ff:fe34:9e31/64 scope link 
       valid_lft forever preferred_lft forever

验证网络的联通性

[root@localhost ~]# ip netns exec net1 ping -c 4 10.10.1.3
PING 10.10.1.3 (10.10.1.3) 56(84) bytes of data.
64 bytes from 10.10.1.3: icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from 10.10.1.3: icmp_seq=2 ttl=64 time=0.057 ms
64 bytes from 10.10.1.3: icmp_seq=3 ttl=64 time=0.059 ms
64 bytes from 10.10.1.3: icmp_seq=4 ttl=64 time=0.064 ms

--- 10.10.1.3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.055/0.058/0.064/0.009 ms
[root@localhost ~]# ip netns exec net2 ping -c 4 10.10.1.2
PING 10.10.1.2 (10.10.1.2) 56(84) bytes of data.
64 bytes from 10.10.1.2: icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from 10.10.1.2: icmp_seq=2 ttl=64 time=0.060 ms
64 bytes from 10.10.1.2: icmp_seq=3 ttl=64 time=0.066 ms
64 bytes from 10.10.1.2: icmp_seq=4 ttl=64 time=0.063 ms

--- 10.10.1.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 0.055/0.061/0.066/0.004 ms

默认情况下,每个ns是无法ping通自己的,是因为默认的lo设备是DOWN状态的,所以,我们需要把lo设备启动了,这样就可以ping通自己了。

[root@localhost ~]# ip netns exec net2 ping -c 4 10.10.1.3
PING 10.10.1.3 (10.10.1.3) 56(84) bytes of data.
^C
--- 10.10.1.3 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1000ms

[root@localhost ~]# ^C
[root@localhost ~]# ip netns exec net2 ip link set lo up
[root@localhost ~]# ip netns exec net2 ping -c 4 10.10.1.3
PING 10.10.1.3 (10.10.1.3) 56(84) bytes of data.
64 bytes from 10.10.1.3: icmp_seq=1 ttl=64 time=0.033 ms
^C
--- 10.10.1.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.033/0.033/0.033/0.000 ms

以上实验的拓扑图如下所示:

正常的容器中,我们能和宿主机以及外部的网络通信,但是我们在隔离的网络中无法ping通宿主机的,唉?这是怎么回事呢?

[root@localhost ~]# ip netns exec net2 ping 192.168.159.14
connect: Network is unreachable

接下来,我们将实现ns和外部的网络互连。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值