Linux 网络设备 veth pair 和 netns
虚构网络拓扑的实现当然离不开虚构网络设备的参加,明天咱们就来介绍一下 Linux 上的网络设备 veth pair 和 netns。
Veth Pair 虚构网络接口
veth pari 是成对呈现的一种虚构网络设备接口,一端连着网络协议栈,一端彼此相连。如下图所示:
因为它的这个个性,经常被用于构建虚构网络拓扑。例如连贯两个不同的网络命名空间(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
- 此时的网络配置状况如下图
验证网络
-
确认网卡是否正确启动
# 查看网卡 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 0 veth1: 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
-
测试 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 的了
验证网络
-
测试网络连通性
# 在宿主机器上 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: <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 11: 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 中查看 ip 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 10: 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 并启动相干网卡
# 配置 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
- 此时的网络配置状况如下图
测试网络连通性
# 在宿主机器上 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 未经容许,不可转载。