Linux网络设备veth pair和netns

虚构网络拓扑的实现当然离不开虚构网络设备的参加,明天咱们就来介绍一下Linux上的网络设备veth pair和netns。

Veth Pair 虚构网络接口

veth pari是成对呈现的一种虚构网络设备接口,一端连着网络协议栈,一端彼此相连。如下图所示:

因为它的这个个性,经常被用于构建虚构网络拓扑。例如连贯两个不同的网络命名空间(Network Namespace),连贯docker容器等,其中一个很常见的案例就是OpenStack Neutron底层用它来构建非常复杂的网络拓扑。

配置veth pair

  1. 创立一对veth pair

    ip link add veth0 type veth peer name veth1
  2. 别离给这两个虚构网卡启动并设置IP

    ip link set veth0 upip addr add 10.0.0.1/24 dev veth0ip link set veth1 upip addr add 10.0.0.2/24 dev veth1
  3. 此时的网络配置状况如下图

验证网络

  1. 确认网卡是否正确启动

    # 查看网卡ifconfig# 输入veth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 10.0.0.1  netmask 255.255.255.0  broadcast 0.0.0.0        inet6 fe80::4880:cff:fe37:b9de  prefixlen 64  scopeid 0x20<link>        ether 4a:80:0c:37:b9:de  txqueuelen 1000  (Ethernet)        RX packets 7  bytes 578 (578.0 B)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 7  bytes 578 (578.0 B)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0veth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 10.0.0.2  netmask 255.255.255.0  broadcast 0.0.0.0        inet6 fe80::c094:68ff:feed:451d  prefixlen 64  scopeid 0x20<link>        ether c2:94:68:ed:45:1d  txqueuelen 1000  (Ethernet)        RX packets 7  bytes 578 (578.0 B)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 7  bytes 578 (578.0 B)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  2. 测试Veth Pair 的连通性

    # 在宿主机器上ping veth0ping 10.0.0.1# 输入PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.051 ms64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.038 ms64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.044 ms^C--- 10.0.0.1 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 2999msrtt min/avg/max/mdev = 0.038/0.043/0.051/0.005 ms# 在宿主机器上ping veth1ping 10.0.0.2# 输入PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.056 ms64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.043 ms64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.039 ms64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.039 ms^C--- 10.0.0.2 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 2999msrtt min/avg/max/mdev = 0.039/0.044/0.056/0.008 ms

    进行完下面的测试你或者心里会想:“什么鬼?都在同一台机器上当然能够通信啊。”
    别着急,咱们上面开始学习另一项技术,Network Namespace,想方法把它放在不同的中央。

Network Namespce 网络命名空间

Linux 3.8内核中包含了6种命名空间:

命名空间形容
Mount(mnt)隔离挂载点
Process ID(process)隔离过程ID
Network(net)隔离网络设备、协定栈、端口等
InterProcess Communication(ipc)隔离过程间通信
UTS隔离Hostname和NIS域名
User ID(user)隔离用户和group ID

其中网络命名空间就是咱们明天要学习的内容。

配置网络命名空间

  1. 创立两个网络命名空间

    ip netns add ns0ip netns add ns1
  2. 将虚构网卡veth0和veth1别离挪动到ns0和ns1网络命名空间中

    ip link set veth0 netns ns0ip link set veth1 netns ns1
  3. 此时的网络配置状况如下图,在宿主机器上是看不到veth0和veth1的了

验证网络

  1. 测试网络连通性

    # 在宿主机器上ping veth0ping 10.0.0.1# 输入PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.From 10.0.0.1 icmp_seq=1 Destination Host UnreachableFrom 10.0.0.1 icmp_seq=2 Destination Host UnreachableFrom 10.0.0.1 icmp_seq=3 Destination Host UnreachableFrom 10.0.0.1 icmp_seq=4 Destination Host Unreachable# 在宿主机器上ping veth1ping 10.0.0.2# 输入PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.From 10.0.0.2 icmp_seq=1 Destination Host UnreachableFrom 10.0.0.2 icmp_seq=2 Destination Host UnreachableFrom 10.0.0.2 icmp_seq=3 Destination Host UnreachableFrom 10.0.0.2 icmp_seq=4 Destination Host Unreachable# 在ns0中ping本人ip netns exec ns0 ping 10.0.0.1# 输入connect: 网络不可达# 在ns0中ping veth1ip netns exec ns0 ping 10.0.0.2# 输入connect: 网络不可达

    却发现无论如何也ping不通,这是为什么呢?让咱们来看一下网络命名空间ns0ns1中的网络信息吧。

  2. 查问网络命名空间的网络信息

    # 在ns0中查看ipip netns exec ns0 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:0011: veth0@if10: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000    link/ether 4a:80:0c:37:b9:de brd ff:ff:ff:ff:ff:ff link-netnsid 1    # 在ns1中查看ipip 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:0010: veth1@if11: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000    link/ether c2:94:68:ed:45:1d brd ff:ff:ff:ff:ff:ff link-netnsid 0

能够看到不仅本地环回和veth的状态都是DOWN,就连veth的IP信息也没有了,这是因为在不同的网络命名空间中挪动虚构网络接口时会重置虚构网络接口的状态。

这里应用了ip a命令来查看网卡,因为ifconfig命令不会显示状态为down的网卡

批改veth pair配置

给网络命名空间中的veth配置IP并启动相干网卡

# 配置ns0ip netns exec ns0 ip addr add 10.0.0.1/24 dev veth0ip netns exec ns0 ip link set lo upip netns exec ns0 ip link set veth0 up# 配置ns1ip netns exec ns1 ip addr add 10.0.0.2/24 dev veth1ip netns exec ns1 ip link set lo upip netns exec ns1 ip link set veth1 up

再次验证网络

# 在ns0中ping本人ip netns exec ns0 ping 10.0.0.1# 输入PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.033 ms64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.069 ms64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.065 ms64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.067 ms^C--- 10.0.0.1 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3060msrtt min/avg/max/mdev = 0.033/0.058/0.069/0.016 ms# 在ns0中ping veth1ip netns exec ns0 ping 10.0.0.2# 输入PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.105 ms64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.050 ms64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.046 ms64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.046 ms^C--- 10.0.0.2 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3000msrtt min/avg/max/mdev = 0.046/0.061/0.105/0.026 ms# 在宿主机器上ping veth1ping 10.0.0.1# 输入PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.^C--- 10.0.0.1 ping statistics ---1 packets transmitted, 0 received, 100% packet loss, time 0ms# 在宿主机器上ping veth1ping 10.0.0.2# 输入PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.^C--- 10.0.0.2 ping statistics ---2 packets transmitted, 0 received, 100% packet loss, time 999ms

能够看到在宿主机器无奈连通任何一个网络命名空间,证实了网络命名空间的隔离个性。

同时两个网络命名空间是能够通信的,证实了veth pair的连通个性。

看到这里或者你会有这样一个想法,我是否把一个veth设置到netns中,另一个veth保留在宿主机器上呢?

答案是能够的,咱们接下来将实现这样的想法。

批改网络配置

  1. 将veth0移回宿主机器上,并配置网卡信息

    因为veth0在宿主机器上是看不到的,当然也无奈操作,因而须要从ns0中操作,默认状况下根网络命令空间的PID是1
    # 将veth0移回宿主机器上ip netns exec ns0 ip link set veth0 netns 1# 删除ns0ip netns del ns0# 启动veth0并配置ipip link set veth0 upip addr add 10.0.0.1/24 dev veth0
  2. 此时的网络配置状况如下图

测试网络连通性

# 在宿主机器上ping veth0ping 10.0.0.1# 输入PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.053 ms64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.034 ms64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.038 ms^C--- 10.0.0.1 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 2999msrtt min/avg/max/mdev = 0.034/0.041/0.053/0.007 ms# 在宿主机器上ping veth1ping 10.0.0.2# 输入PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.068 ms64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.048 ms64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.045 ms64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=0.040 ms^C--- 10.0.0.2 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 3000msrtt min/avg/max/mdev = 0.040/0.050/0.068/0.011 ms# 在ns1中ping veth0ip netns exec ns1 ping 10.0.0.1# 输入PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.071 ms64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.055 ms64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.046 ms64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.045 ms^C--- 10.0.0.1 ping statistics ---4 packets transmitted, 4 received, 0% packet loss, time 2999msrtt min/avg/max/mdev = 0.045/0.054/0.071/0.011 ms

应用veth pair咱们胜利的将宿主机器和网络命名空间的隔离性突破,建设了一个能够互联的网络。这样的场景相当于用一根网线把两个网络设备连贯到了一起,而veth pair就是这根”网线“。这种形式也被广泛应用到了docker网络中,前面咱们也会讲到如何得心应手的玩转docker网络。

接下来咱们将探讨学习Linux Bridge虚构网桥。

本文首发 Linux网络设备veth pair和netns 未经容许,不可转载。