如果我做:
sudo ip link add l4 type veth
sudo ip addr add "7.7.7.7/24" dev l4
ping 7.7.7.7
PING 7.7.7.7 (7.7.7.7) 56(84) bytes of data.
64 bytes from 7.7.7.7: icmp_seq=1 ttl=64 time=0.023 ms
64 bytes from 7.7.7.7: icmp_seq=2 ttl=64 time=0.102 ms
ping 正常
但在命名空间中:
sudo ip netns add test
sudo ip netns exec test ip link add l5 type veth
sudo ip netns exec test ip addr add "8.8.8.8/24" dev l5
sudo ip netns exec test ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2034ms
ping 失败。
为什么会有这种差异呢?
如何使 ping 在命名空间中工作?
答案1
总结:该问题与网络命名空间无关,也不韦特接口,而是两个本地 IP 之间的本地路由,通过洛界面。
这是一个简化版本,不需要韦特接口(也不是环回接口之外的任何接口)来重现该问题:
# ip address add 192.0.2.2/32 dev lo
# ping -c2 192.0.2.2
PING 192.0.2.2 (192.0.2.2) 56(84) bytes of data.
64 bytes from 192.0.2.2: icmp_seq=1 ttl=64 time=0.162 ms
64 bytes from 192.0.2.2: icmp_seq=2 ttl=64 time=0.108 ms
--- 192.0.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1061ms
rtt min/avg/max/mdev = 0.108/0.135/0.162/0.027 ms
# ip netns add test
# ip -netns test address add 192.0.2.3/32 dev lo
# ip netns exec test ping -c2 192.0.2.3
PING 192.0.2.3 (192.0.2.3) 56(84) bytes of data.
--- 192.0.2.3 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1027ms
# ip -netns test link set dev lo up
# ip netns exec test ping -c2 192.0.2.3
PING 192.0.2.3 (192.0.2.3) 56(84) bytes of data.
64 bytes from 192.0.2.3: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 192.0.2.3: icmp_seq=2 ttl=64 time=0.069 ms
--- 192.0.2.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.037/0.053/0.069/0.016 ms
选择完全不适当的接口(中间功能块)会产生同样的影响:
# ip -netns test link set dev lo down # previous state
# ip -netns test link add name test0 type ifb
# ip -netns test address add 192.0.2.4/32 dev test0
# ip -netns test route get 192.0.2.4
local 192.0.2.4 dev lo src 192.0.2.4 uid 0
cache <local>
# ip netns exec test ping -c2 192.0.2.4
PING 192.0.2.4 (192.0.2.4) 56(84) bytes of data.
--- 192.0.2.4 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1006ms
# ip -netns test link set dev lo up
# ip netns exec test ping -c2 192.0.2.4
PING 192.0.2.4 (192.0.2.4) 56(84) bytes of data.
64 bytes from 192.0.2.4: icmp_seq=1 ttl=64 time=0.025 ms
64 bytes from 192.0.2.4: icmp_seq=2 ttl=64 time=0.054 ms
--- 192.0.2.4 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1015ms
rtt min/avg/max/mdev = 0.025/0.039/0.054/0.015 ms
解释很简单:默认情况下,当任何IP 已分配给任何接口(甚至是完全不充分的接口,或者也是接口向下状态)试图达到任何分配给相同或其他 IP任何相同或其他接口,两个 IP 都属于同一主机,路由使用洛界面,这与弱宿主模型在 Linux 上使用。无论该接口的用途是什么:它根本不会被使用。重要的是洛接口已启动。创建新的网络命名空间时,它会自动接收洛界面,但在向下状态。任何本地流量要想在此网络命名空间中成功,洛接口必须被启动。
常见误用:将 IP 分配给 tun/tap 接口(网络数据包,无论是 IP 还是其他,都必须由后面的应用程序处理,而不是内核)。虽然从主机 ping IP 会按上述方式工作,但这不会帮助解决任何工作,并且会妨碍正确使用。
现在,如果我们的目标是在初始命名空间和测试命名空间之间进行路由,这里有一个工作示例,其中包含一对韦特接口:
# ip link add name vethtotest0 type veth peer netns test name vethtoinit0
# ip link set dev vethtotest0 up
# ip -netns test link set dev vethtoinit0 up
# ip address add 198.51.100.1/24 dev vethtotest0
# ip -netns test address add 198.51.100.2/24 dev vethtoinit0
# ip netns exec test ping 198.51.100.1
# ip netns exec test ping -c2 198.51.100.1
PING 198.51.100.1 (198.51.100.1) 56(84) bytes of data.
64 bytes from 198.51.100.1: icmp_seq=1 ttl=64 time=0.171 ms
64 bytes from 198.51.100.1: icmp_seq=2 ttl=64 time=0.101 ms
--- 198.51.100.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1055ms
rtt min/avg/max/mdev = 0.101/0.136/0.171/0.035 ms
仍然要使 ping 到 198.51.100.2 在测试命名空间内成功,洛接口必须处于打开状态。上一个测试不需要此接口,因为路由是通过vethtoinit0。