笔者:张首富
时间:2021-11-18
w x: Y18163201(注明来意)

阅读说明

本文内容为满满的技术干货;阅读本文可能需要一下技术:

docker

iptables

linux 网络基本命令

namespaces

如果上面技术你不是很了解也没关系,看到不懂的地方去查查;

Host 模式

None 模式

bridge 模式

了解了上面两种网络模式之后,我们来了解一下docker 容器里面常用的bridge模式;(但是官方文档指出不要使用默认的bridge网络,因为不安全)

bridge网络模式实际上是采用了 veth-pair虚拟网卡来实现的;那我们就先来看下 veth-pair是什么

veth-pair是什么

顾名思义,veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着。如下图所示:

https://zhangshoufu-images.oss-accelerate.aliyuncs.com/image-20211118162502959.png

正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备,典型的例子像“两个 namespace 之间的连接”,“Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络结构,比如 OpenStack Neutron。

我们来尝试创建一对veth,放到不同的namespaces来测试一下

# 创建ns1 和ns2 两个namespaces
$ ip netns  add ns1
$ ip nnetns add ns2

# 创建一对veth接口,分别较veth1 和veth2
$ ip link add name veth1 type veth peer name veth2
# 查看创建的一对veth网卡
$ ip link | grep veth
1848: veth2@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
1849: veth1@veth2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
# 把veth网卡放到相应的namespaces中,veth1   -->   ns1 ;veth2  --> ns2
$ ip link set veth1 netns  ns1
$ ip link set veth2 netns  ns2
$ ip link | grep veth     #当虚拟网卡放到对应的namespaces之后在当前的namespaces里面就看不到了
$ ip netns exec ns1 ip link |grep veth
1849: veth1@if1848: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
$ ip netns exec ns2 ip link |grep veth
1848: veth2@if1849: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
从上面实现结果可以看到我们已经成功的把Veth一对网卡放到了不同的NameSpaces里面去了,然后我们在来看一下他们是如何进行通信的
$ ip netns  exec ns1 ip link set veth1 name eth1			#更改网卡名称变成我们常见的eth形态
$ ip netns exec ns2 ip link set veth2 name eth2
$ ip netns  exec ns1 ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
1849: eth1@if1848: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 6a:e5:4e:70:4a:94 brd ff:ff:ff:ff:ff:ff link-netnsid 1
$ ip netns  exec ns2 ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
1848: eth2@if1849: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 9e:35:5f:8d:ad:c0 brd ff:ff:ff:ff:ff:ff link-netnsid 0

$ ip netns  exec ns1 ip addr add 172.17.3.1/24 dev eth1   #给ns1里面的网卡设置一个IP地址
$ ip netns exec ns2 ip addr add 172.17.3.2/24 dev eth2    #给ns2里面的网卡设置一个IP地址
$ ip netns exec ns1 ip link set eth1 up                   #启动这个网卡配置
$ ip netns exec ns2 ip link set eth2 up                   #启动这个网卡配置

$ ip netns exec ns1 ping 172.17.3.2                       #在ns1里面访问ns2
PING 172.17.3.2 (172.17.3.2) 56(84) bytes of data.
64 bytes from 172.17.3.2: icmp_seq=1 ttl=64 time=0.111 ms
^C
--- 172.17.3.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.111/0.111/0.111/0.000 ms
$ ip netns exec ns2 ping 172.17.3.1                       #在ns2里面访问ns1
PING 172.17.3.1 (172.17.3.1) 56(84) bytes of data.
64 bytes from 172.17.3.1: icmp_seq=1 ttl=64 time=0.087 ms
^C
--- 172.17.3.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.087/0.087/0.087/0.000 ms

上面实验结果我们可以看出来把一对虚拟网卡放在的不同的NameSpaces里面是可以正常的通信的,这也就是Veth-pair的基本实验操作,最简单的就是把他想象成一条网线,在网线的两边有两个网线口, 把NameSpaces想象房间,set的动作就是把网线插入到想通信的两个房间里面,插上之后给每个房间配置上IP地址之后,两个房间就能正常的通信了。

Bridge 模式

上面我们介绍了Veth-pair的实现方式了,那我们就开看一下这和docker bridge网络模式到地址有什么关系?首先我们先来看一下docker bridge网络模式的架构图