namespace
namespace有好几种,这里主要关注的是network namespace。 每个network namespace都有自己的IP地址,路由表,端口范围,/proc/net目录等。例如在每个容器都可以任意绑定监听的端口不用担心冲突,也就是因为不同它们有不同的network namespace隔离。
veth pair
veth 是虚拟以太网卡(Virtual Ethernet)的缩写,veth总是成对出现,所以称为veth pair。 veth pair的原理很简单,就是一端输入数据,数据通过Linux内核协议栈后从另一端出来。
正由于有这个特性,它经常充当着一个桥梁,连接各类虚拟网络设备,典型的例子像“两个 namespace 之间的链接”,“Bridge、OVS 之间的链接”,“Docker 容器之间的链接” 等等。
Linux Bridge
但是如果两个以上虚拟网络设备互联,veth pair就捉襟见肘了,这就需要linux bridge出马了。 linux bridge任意物理设备(如:eth0)和虚拟设备(如:veth pair)都可以连在上面,数据可以从任意口进来,然后根据目的MAC地址选择从哪个口出去。 bridge-utils包里的brctl工具来管理bridge。
小实验
结合这三个概念做一个小实验:
建一个veth pair,使其能够互通
- 建一个veth pair 命名为veth0-0和veth0-1
ip link add veth0-0 type veth peer name veth0-1 ip link set up veth0-0 ip link set up veth0-1 - 配置互联IP
ip addr add 192.168.100.1/24 dev veth0-0 ip addr add 192.168.100.2/24 dev veth0-1 - 测试互通
ip a |grep veth0 查看接veth pair状态 从veth0-0 ping veth0-1测试,可以互通。
建一个namespace,把veth pair一端放到namespace
- 建一个namespace 命名ns0
ip netns add ns0 ip netns 查看ns - 把veth0-1放到ns0
ip link set veth0-1 netns ns0 ip netns exec ns0 ip link set up veth0-1 ip netns exec ns0 ip addr add 192.168.100.2/24 dev veth0-1 (需要重新配置IP,set up) ip netns exec ns0 ip a 查看veth0-1
ping -I veth0-0 192.168.100.2 从veth0-0 ping 测试互通正常。
ip netns exec ns0 ping 192.168.100.1 从veth0-1ping 测试互通正常。
这里有一点注意,新建的ns所有接口是down的,包括环回接口lo,所有这时在ns0里ping 自己的IP是不通的, 想ping通自己需要set up lo ip netns exec ns0 ip link set up lo,这时再ping 自己的IP就可以了。
建一个linux birdge,把veth0-0接到bridge
-
建一个linux bridge 命名br0 brctl addbr br0 ip link set up br0 brctl show br0 查看br0已经创建 ip a | grep br0 不过br0目前是down的 -
veth0-0接到br0 brctl addif veth0-0 br0 ip a | grep br0 br0现在up了 br0的MAC和veth0-0的一样了 -
测试一下互通,已经不通了。
tcpdump抓包分析
-
在veth0-1上抓包可以看到,veth0-1上收到了192.168.100.1的ARP请求,并做了回应。 -
在veth0-0上抓包看到,veth0-0发出了ARP请求,并收到了回应。 -
在br0上抓包看到,veth0-0收到的回应包都给了br0,所以协议栈得不到veth0-1的MAC地址,导致ping不通。 -
看一下br0上的的MAC地址学习,veth0-1的MAC是被br0学到了。 -
把veth0-0的IP192.168.100.1/24 挪到br0上试下
ip addr del 192.168.100.1/24 dev veth0-0 ip addr add 192.168.100.1/24 dev br0 测试可以正常互通了,不过是br0和veth0-1之间互通,veth0-0就相当一根网线一样了。
|