Linux网络虚拟化 名称空间和veth

Network namespace是linux内核提供的进行网络隔离的功能,每一个名称空间内有自己独立的网络协议栈,有自己独立的路由表等。Docker容器网络的实现和隔离就是通过网络名称空间实现的。 操作网...

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 link list 命令查看网卡配置信息的时候,是可以看到网卡最前边是有一个编号,这个就是网卡的唯一索引,然后看网卡名称veth2@if4,if4表示的就是对端的索引号为4。

attachments-2023-04-HWLTLodm643f7603a9563,png

另一端对应docker容器的网络,进入容器通过ip link list 可以看到他们的编号和这些veth是一一对应的!

主意:网卡的索引号在同一个名称空间内是唯一的,什么意思呢,也就是说如果你在其他网络名称空间内创建了veth然后移动到另外一个或者默认网络名称空间内,就会搞的很混乱。所以一般我们都是在默认名称空间内创建veth然后移动到其他名称空间,这样就比较好识别。


  • 发表于 2023-04-19 13:00
  • 阅读 ( 32 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
shitian
shitian

662 篇文章

作家榜 »

  1. shitian 662 文章
  2. 石天 437 文章
  3. 每天惠23 33 文章
  4. 小A 29 文章