本文假设已经具备基本的路由交换基础。个人学习记录,欢迎指正。
Network namespace是linux内核提供的进行网络隔离的功能,每一个名称空间内有自己独立的网络协议栈,有自己独立的路由表等。Docker容器网络的实现和隔离就是通过网络名称空间实现的。
操作网络名称空间
# 添加
[root@localhost ~]# ip netns add ns1
# 查看
[root@localhost ~]# ip netns list
ns1
[root@localhost ~]# ip netns show
ns1
# 在名称空间内执行命令
[root@localhost ~]# ip netns exec ns1 ip a
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
# 进入名称空间
[root@localhost ~]# ip netns exec ns1 bash
# 执行命令,查看该名称空间的网卡信息
[root@localhost ~]# ip a
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
# 退出名称空间
[root@localhost ~]# exit
exit
# 删除
[root@localhost ~]# ip netns delete ns1
FAQ
Docker容器的网络名称空间怎么查看?
默认网络名称空间提供的入口文件在/var/run/netns/目录下,ip netns 命令默认也是读取的该目录下的入口文件。 Docker重新指定了该目录在/var/run/docker/netns/,所以如果想使用默认的ip netns命令管理docker的网络名称空间,只需要做一个软链到 /var/run/netns/就可以
# 测试环境使用,将docker容器的网络名称空间软链到/var/run/netns/ 并显示显示容器名
test -d /var/run/netns || mkdir /var/run/netns
for container in $(docker ps -a| awk '{print $NF}'| grep -v 'NAMES'); \
do \
ln -s $(docker inspect $container| grep SandboxKey| awk -F '"' '{print $4}') /var/run/netns/$container; \
done
ip netns list
veth
Virtual ethernet interface是一个虚拟的以太网接口,在linux中veth和普通网卡是一样对待的。veth总是成对出现的,被称为veth pair,可以简单的理解我们现实世界中的网线,一条网线有两个水晶头,主要进行设备间的互联互通。
操作veth
# 添加
ip link add veth1 type veth peer name veth2
# 查看
ip add
ip link show type veth
# 默认veth是down状态,所以需要up
ip link set veth1 up
# 配置ip
ip addr add 1.1.1.1/32 dev veth1
# 修改mac地址
ip link set veth1 addr ee:ee:ee:ee:ee:ee
# 将veth移动到其他网络名称空间
ip netns add ns1
ip link set dev veth1 netns ns1
# 删除,只要删除任意一端,整个veth pair即删除
ip link del veth2
模拟两台主机同网段通信
# 拓扑情况
# 两台终端通过一条网线互联
# 终端使用网络名称空间来模拟
# 新建两个名称空间
ip netns add ns1
ip netns add ns2
# 新建一条veth pair
ip link add veth1 type veth peer name veth2
# 分别将veth pair的两头插入终端
ip link set dev veth1 netns ns1
ip link set dev veth2 netns ns2
# 配置终端内网卡信息
ip netns exec ns1 ip addr add 10.0.12.1/24 dev veth1
ip netns exec ns1 ip link set veth1 up
ip netns exec ns2 ip addr add 10.0.12.2/24 dev veth2
ip netns exec ns2 ip link set veth2 up
# 测试两台终端互通
ip netns exec ns1 ping 10.0.12.2 -c 4
# 查看终端网络配置情况
[root@localhost ~]# ip netns exec ns1 ip a
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
4: veth1@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 52:6e:c4:c9:6b:75 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet 10.0.12.1/24 scope global veth1
valid_lft forever preferred_lft forever
inet6 fe80::506e:c4ff:fec9:6b75/64 scope link
valid_lft forever preferred_lft forever
[root@localhost ~]# ip netns exec ns2 ip a
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
3: veth2@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether d2:2c:22:bb:e4:99 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.0.12.2/24 scope global veth2
valid_lft forever preferred_lft forever
inet6 fe80::d02c:22ff:febb:e499/64 scope link
valid_lft forever preferred_lft forever
# 通信抓包信息
[root@localhost ~]# ip netns exec ns2 tcpdump -i veth2 -ne
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth2, link-type EN10MB (Ethernet), capture size 262144 bytes
11:02:16.500486 52:6e:c4:c9:6b:75 > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 10.0.12.2 tell 10.0.12.1, length 28
11:02:16.500511 d2:2c:22:bb:e4:99 > 52:6e:c4:c9:6b:75, ethertype ARP (0x0806), length 42: Reply 10.0.12.2 is-at d2:2c:22:bb:e4:99, length 28
11:02:16.500515 52:6e:c4:c9:6b:75 > d2:2c:22:bb:e4:99, ethertype IPv4 (0x0800), length 98: 10.0.12.1 > 10.0.12.2: ICMP echo request, id 1201, seq 1, length 64
11:02:16.500538 d2:2c:22:bb:e4:99 > 52:6e:c4:c9:6b:75, ethertype IPv4 (0x0800), length 98: 10.0.12.2 > 10.0.12.1: ICMP echo reply, id 1201, seq 1, length 64
11:02:17.524159 52:6e:c4:c9:6b:75 > d2:2c:22:bb:e4:99, ethertype IPv4 (0x0800), length 98: 10.0.12.1 > 10.0.12.2: ICMP echo request, id 1201, seq 2, length 64
11:02:17.524190 d2:2c:22:bb:e4:99 > 52:6e:c4:c9:6b:75, ethertype IPv4 (0x0800), length 98: 10.0.12.2 > 10.0.12.1: ICMP echo reply, id 1201, seq 2, length 64
11:02:18.549011 52:6e:c4:c9:6b:75 > d2:2c:22:bb:e4:99, ethertype IPv4 (0x0800), length 98: 10.0.12.1 > 10.0.12.2: ICMP echo request, id 1201, seq 3, length 64
11:02:18.549041 d2:2c:22:bb:e4:99 > 52:6e:c4:c9:6b:75, ethertype IPv4 (0x0800), length 98: 10.0.12.2 > 10.0.12.1: ICMP echo reply, id 1201, seq 3, length 64
11:02:19.572310 52:6e:c4:c9:6b:75 > d2:2c:22:bb:e4:99, ethertype IPv4 (0x0800), length 98: 10.0.12.1 > 10.0.12.2: ICMP echo request, id 1201, seq 4, length 64
11:02:19.572336 d2:2c:22:bb:e4:99 > 52:6e:c4:c9:6b:75, ethertype IPv4 (0x0800), length 98: 10.0.12.2 > 10.0.12.1: ICMP echo reply, id 1201, seq 4, length 64
11:02:21.749109 d2:2c:22:bb:e4:99 > 52:6e:c4:c9:6b:75, ethertype ARP (0x0806), length 42: Request who-has 10.0.12.1 tell 10.0.12.2, length 28
11:02:21.749178 52:6e:c4:c9:6b:75 > d2:2c:22:bb:e4:99, ethertype ARP (0x0806), length 42: Reply 10.0.12.1 is-at 52:6e:c4:c9:6b:75, length 28
FAQ
机器上有很多veth pair,怎么确定另一端是在哪个网络名称空间内
通过使用ip a命令查看网卡配置信息的时候,是可以看到网卡最前边是有一个编号,这个就是网卡的唯一索引,然后看网卡名称veth2@if4,if4表示的就是对端的索引号为4。
主意:网卡的索引号在同一个名称空间内是唯一的,什么意思呢,也就是说如果你在其他网络名称空间内创建了veth然后移动到另外一个或者默认网络名称空间内,就会搞的很混乱。所以一般我们都是在默认名称空间内创建veth然后移动到其他名称空间,这样就比较好识别。