linux veth设备路由,Linux网络设备veth pair和netns

  • Post author:
  • Post category:linux


Linux网络设备veth pair和netns

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

Veth Pair 虚拟网络接口

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

1460000037758233

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

配置veth pair

创建一对veth pair

ip link add veth0 type veth peer name veth1

分别给这两个虚拟网卡启动并设置IP

ip link set veth0 up

ip addr add 10.0.0.1/24 dev veth0

ip link set veth1 up

ip addr add 10.0.0.2/24 dev veth1

此时的网络配置情况如下图

1460000037758234

验证网络

确认网卡是否正确启动

# 查看网卡

ifconfig

# 输出

veth0: flags=4163 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

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 0

veth1: flags=4163 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

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

测试Veth Pair 的连通性

# 在宿主机器上ping veth0

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.051 ms

64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms

64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.038 ms

64 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 2999ms

rtt min/avg/max/mdev = 0.038/0.043/0.051/0.005 ms

# 在宿主机器上ping veth1

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.056 ms

64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.043 ms

64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.039 ms

64 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 2999ms

rtt 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

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

配置网络命名空间

创建两个网络命名空间

ip netns add ns0

ip netns add ns1

将虚拟网卡veth0和veth1分别移动到ns0和ns1网络命名空间中

ip link set veth0 netns ns0

ip link set veth1 netns ns1

此时的网络配置情况如下图,在宿主机器上是看不到veth0和veth1的了

1460000037758236

验证网络

测试网络连通性

# 在宿主机器上ping veth0

ping 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 Unreachable

From 10.0.0.1 icmp_seq=2 Destination Host Unreachable

From 10.0.0.1 icmp_seq=3 Destination Host Unreachable

From 10.0.0.1 icmp_seq=4 Destination Host Unreachable

# 在宿主机器上ping veth1

ping 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 Unreachable

From 10.0.0.2 icmp_seq=2 Destination Host Unreachable

From 10.0.0.2 icmp_seq=3 Destination Host Unreachable

From 10.0.0.2 icmp_seq=4 Destination Host Unreachable

# 在ns0中ping自己

ip netns exec ns0 ping 10.0.0.1

# 输出

connect: 网络不可达

# 在ns0中ping veth1

ip netns exec ns0 ping 10.0.0.2

# 输出

connect: 网络不可达

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

查询网络命名空间的网络信息

# 在ns0中查看ip

ip netns exec ns0 ip a

# 输出

1: lo: 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

11: veth0@if10: 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中查看ip

ip netns exec ns1 ip a

# 输出

1: lo: 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

10: veth1@if11: 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并启动相关网卡

# 配置ns0

ip netns exec ns0 ip addr add 10.0.0.1/24 dev veth0

ip netns exec ns0 ip link set lo up

ip netns exec ns0 ip link set veth0 up

# 配置ns1

ip netns exec ns1 ip addr add 10.0.0.2/24 dev veth1

ip netns exec ns1 ip link set lo up

ip 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 ms

64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.069 ms

64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.065 ms

64 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 3060ms

rtt min/avg/max/mdev = 0.033/0.058/0.069/0.016 ms

# 在ns0中ping veth1

ip 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 ms

64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.050 ms

64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.046 ms

64 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 3000ms

rtt min/avg/max/mdev = 0.046/0.061/0.105/0.026 ms

# 在宿主机器上ping veth1

ping 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 veth1

ping 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保留在宿主机器上呢?

答案是可以的,我们接下来将完成这样的想法。

修改网络配置

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

因为veth0在宿主机器上是看不到的,当然也无法操作,因此需要从ns0中操作,默认情况下根网络命令空间的PID是1

# 将veth0移回宿主机器上

ip netns exec ns0 ip link set veth0 netns 1

# 删除ns0

ip netns del ns0

# 启动veth0并配置ip

ip link set veth0 up

ip addr add 10.0.0.1/24 dev veth0

此时的网络配置情况如下图

1460000037758235

测试网络连通性

# 在宿主机器上ping veth0

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.053 ms

64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.039 ms

64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.034 ms

64 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 2999ms

rtt min/avg/max/mdev = 0.034/0.041/0.053/0.007 ms

# 在宿主机器上ping veth1

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.068 ms

64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.048 ms

64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=0.045 ms

64 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 3000ms

rtt min/avg/max/mdev = 0.040/0.050/0.068/0.011 ms

# 在ns1中ping veth0

ip 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 ms

64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.055 ms

64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.046 ms

64 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 2999ms

rtt 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 未经允许,不可转载。