网络命名空间

Net Namesapce,网络命名空间,不同netns的网络栈是完全隔离的,相互不能通信,命名空间内部可以有自己独立的路由表以及iptables。为了隔离出独立的协议栈,需要纳入命名空间的元素有进程、套接字、网络设备等。

网络命名空间操作

创建命名空间:

1
2
3
4
[root@localhost ~]# ip netns
[root@localhost ~]# ip netns add netns1
[root@localhost ~]# ip netns
netns1

在ns内执行命令:

1
2
3
[root@localhost ~]# ip netns exec netns1 ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

新创建的命名空间内默认只有lo设备。不同的网络命名空间之间可以转移设备,但是一个设备只能属于一个命名空间,所以一个设备从命名空间A转移到B,A中就看不到设备了。但是有些设备是不能被转移的,比如lo设备、vxlan设备、ppp设备、birdge设备等。如何知道设备是否能够被转移呢?通过属性NETIF_F_ETNS_LOCAL,如果这个属性为on,则不能转移。通过ethtool可以查看:

1
2
[root@localhost ~]# ethtool  -k lo | grep netns-local
netns-local: on [fixed]

Veth设备对

不同的网络命名空间是相互隔离的,如果想让两个命名空间进行通信可以使用Veth设备对,由名字可以看出Veth设备是成对出现的,可以理解为两个以太网卡并且中间通过网线连接,我们称一端为另一端的peer,数据的传输也很简单,在Veth设备的一端发送数据,它将数据直接发送到另一端,并触发另一端的接收操作。

Veth设备操作

创建Veth设备对:

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# ip link add veth0 type veth peer name veth1
[root@localhost ~]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:4b:b6:a5 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT
link/ether 02:42:57:0e:8b:de brd ff:ff:ff:ff:ff:ff
6: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 8a:2e:3c:94:e3:b1 brd ff:ff:ff:ff:ff:ff
7: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether a2:f7:c9:19:51:6d brd ff:ff:ff:ff:ff:ff

有两个设备创建出来了,veth0和veth1,分别把他们放在不同的命名空间里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@localhost ~]# ip netns
netns1
[root@localhost ~]# ip netns add netns2
[root@localhost ~]# ip netns
netns2
netns1
[root@localhost ~]# ip link set veth0 netns netns1
[root@localhost ~]# ip link set veth1 netns netns2
[root@localhost ~]# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:4b:b6:a5 brd ff:ff:ff:ff:ff:ff
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT
link/ether 02:42:57:0e:8b:de brd ff:ff:ff:ff:ff:ff

创建两个命名空间netns1,netns2,分别将veth0和veth1转移到两个命名空间里,所以在默认的网络命名空间是看不到的,现在将两个设备配置地址并启动,尝试在两个命名空间进行通信:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[root@localhost ~]# ip netns exec netns1 ip addr add 10.1.1.1/24  dev veth0
[root@localhost ~]# ip netns exec netns2 ip addr add 10.1.1.2/24 dev veth1
[root@localhost ~]# ip netns exec netns1 ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
7: veth0@if6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether a2:f7:c9:19:51:6d brd ff:ff:ff:ff:ff:ff link-netnsid 1
[root@localhost ~]# ip netns exec netns2 ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
6: veth1@if7: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 8a:2e:3c:94:e3:b1 brd ff:ff:ff:ff:ff:ff link-netnsid 0
[root@localhost ~]# ip netns exec netns1 ip link set dev veth0 up
[root@localhost ~]# ip netns exec netns2 ip link set dev veth1 up
[root@localhost ~]# ip netns exec netns2 ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.125 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=0.043 ms

网桥

网桥是一个二层网络设备,可以解析收发的报文,读取目标MAC地址的信息,和自己记录的MAC表结合,来决策报文的转发端口。实际网络中,网络拓扑不可能一直不变,如果一个设备移动到另一个端口上,而又没有发送任何数据,网桥就无法感知这个设备的变动,还是会向原来的端口转发数据包,这种情况下数据就会丢失。所以网桥对学习到的MAC地址表加上超时时间(默认5分钟)。