VETH (virtual Ethernet) 设备是本地虚拟以太网隧道,成对出现。veth-pair
就是一对的虚拟设备接口
,和 tap/tun
设备不同的是,它都是成对出现的。功能类似于网线
。本文结合bridge
、OpenvSwitch
和netns
说明 veth pair
的作用。
介绍
veth-pair
一端连着协议栈,一端彼此相连着,如下图:
正因为有这个特性,它常常充当着一个桥梁
,连接着各种虚拟网络设备
,典型的例子像:
使用veth-pair
也可以构建出复杂的虚拟网络结构,比如 OpenStack Neutron
。一个设备(Linux Device
)只能位于一个namespace
中,不同namespace
中的设备可以利用veth pair
进行桥接。
bridge 示例
创建一个veth-pair
,并与两个 netns
互联
# 1. 创建 veth-pair
$ ip link add veth1 type veth peer name veth2
$ ip link
21: veth2@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether c2:43:ac:c0:53:10 brd ff:ff:ff:ff:ff:ff
22: veth1@veth2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 26:91:22:3c:63:29 brd ff:ff:ff:ff:ff:ff
# 2. 创建 netns
$ ip netns add ns1
$ ip netns add ns2
# 3. 把两个tap设备分别分配到 netns 中
$ ip link set veth1 netns ns1
$ ip link set veth2 netns ns2
# 4. 为 netns 中的tap设备分配 ip 地址,并启用 tap 设备
$ ip netns exec ns1 ip addr add local 172.20.1.1/24 dev veth1
$ ip netns exec ns2 ip addr add local 172.20.1.2/24 dev veth2
$ ip netns exec ns1 ip link set veth1 up
$ ip netns exec ns2 ip link set veth2 up
# 5. 连通性验证
$ ip netns exec ns1 ping -c 1 172.20.1.2
PING 172.20.1.2 (172.20.1.2) 56(84) bytes of data.
64 bytes from 172.20.1.2: icmp_seq=1 ttl=64 time=0.064 ms
--- 172.20.1.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.064/0.064/0.064/0.000 ms
OpenvSwitch 示例
OVS
比 Linux Bridge
功能更强大,针对上述示例,采用 OVS
配置如下:
# 1. 创建 br0
$ ovs-vsctl show
2e6ffc1e-472a-48f5-9d19-84e4bf0bb7a5
ovs_version: "2.11.7"
$ ovs-vsctl add-br br0
$ ovs-vsctl show
2e6ffc1e-472a-48f5-9d19-84e4bf0bb7a5
Bridge "br0"
Port "br0"
Interface "br0"
type: internal
ovs_version: "2.11.7"
# 2. 创建两组 veth-pair
$ ip link add nveth1 type veth peer name oveth1
$ ip link add nveth2 type veth peer name oveth2
$ ip link set nveth1 up
$ ip link set oveth1 up
$ ip link set nveth2 up
$ ip link
# 3. 创建两个 netns
$ ip netns add ns1
$ ip netns add ns2
$ ip netns ls
ns2
ns1
# 4. 连接
$ ip link set nveth1 netns ns1
$ ovs-vsctl add-port br0 oveth1
$ ip link set nveth2 netns ns2
$ ovs-vsctl add-port br0 oveth2
# 5. 为 netns 中的 veth 配置 ip 地址
$ ip netns exec ns1 ip addr add 172.20.0.1/24 dev nveth1
$ ip netns exec ns2 ip addr add 172.20.0.2/24 dev nveth2
# 6. 配置查看
$ ovs-vsctl show
2e6ffc1e-472a-48f5-9d19-84e4bf0bb7a5
Bridge "br0"
Port "oveth1"
Interface "oveth1"
Port "br0"
Interface "br0"
type: internal
Port "oveth2"
Interface "oveth2"
ovs_version: "2.11.7"
$ 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
7: nveth1@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 66:6d:72:6b:e1:71 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.20.0.1/24 scope global nveth1
valid_lft forever preferred_lft forever
inet6 fe80::646d:72ff:fe6b:e171/64 scope link
valid_lft forever preferred_lft forever
$ 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
9: nveth2@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether de:f5:0d:10:1f:27 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.20.0.2/24 scope global nveth2
valid_lft forever preferred_lft forever
inet6 fe80::dcf5:dff:fe10:1f27/64 scope link
valid_lft forever preferred_lft forever
$ 7. ping验证
$ ip netns exec ns1 ping -c 1 172.20.0.2
PING 172.20.0.2 (172.20.0.2) 56(84) bytes of data.
64 bytes from 172.20.0.2: icmp_seq=1 ttl=64 time=0.046 ms
--- 172.20.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.046/0.046/0.046/0.000 ms
# 8. 抓包
$ ip netns exec ns1 tcpdump -i nveth1 -vv -nnt
tcpdump: listening on nveth1, link-type EN10MB (Ethernet), capture size 262144 bytes
IP (tos 0x0, ttl 64, id 8833, offset 0, flags [DF], proto ICMP (1), length 84)
172.20.0.1 > 172.20.0.2: ICMP echo request, id 2095, seq 318, length 64
IP (tos 0x0, ttl 64, id 51286, offset 0, flags [none], proto ICMP (1), length 84)
172.20.0.2 > 172.20.0.1: ICMP echo reply, id 2095, seq 318, length 64
$ tcpdump -i oveth1 -vv -nnt
tcpdump: listening on oveth1, link-type EN10MB (Ethernet), capture size 262144 bytes
IP (tos 0x0, ttl 64, id 24617, offset 0, flags [DF], proto ICMP (1), length 84)
172.20.0.1 > 172.20.0.2: ICMP echo request, id 2095, seq 92, length 64
IP (tos 0x0, ttl 64, id 8326, offset 0, flags [none], proto ICMP (1), length 84)
172.20.0.2 > 172.20.0.1: ICMP echo reply, id 2095, seq 92, length 64
$ tcpdump -i oveth2 -vv -nnt
tcpdump: listening on oveth2, link-type EN10MB (Ethernet), capture size 262144 bytes
IP (tos 0x0, ttl 64, id 33852, offset 0, flags [DF], proto ICMP (1), length 84)
172.20.0.1 > 172.20.0.2: ICMP echo request, id 2095, seq 109, length 64
IP (tos 0x0, ttl 64, id 16049, offset 0, flags [none], proto ICMP (1), length 84)
172.20.0.2 > 172.20.0.1: ICMP echo reply, id 2095, seq 109, length 64
$ ip netns exec ns2 tcpdump -i nveth2 -vv -nnt
tcpdump: listening on nveth2, link-type EN10MB (Ethernet), capture size 262144 bytes
IP (tos 0x0, ttl 64, id 12050, offset 0, flags [DF], proto ICMP (1), length 84)
172.20.0.1 > 172.20.0.2: ICMP echo request, id 2095, seq 190, length 64
IP (tos 0x0, ttl 64, id 54949, offset 0, flags [none], proto ICMP (1), length 84)
172.20.0.2 > 172.20.0.1: ICMP echo reply, id 2095, seq 190, length 64
容器和宿主机 veth pair 对应关系
ip link 方式
[root@2105d89721a8 /]# ip link show eth0
23: eth0@if24: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
23: eth0@if24
: 23
为该 veth-pair
peer
的 index
;24
为该 veth-pair
的 index
$ ip link show
24: veth05ae645@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
link/ether 76:7a:e0:31:a9:56 brd ff:ff:ff:ff:ff:ff link-netnsid 4
可以看到宿主机上 24: veth05ae645@if23
中 23/24
的释义和容器内正好相反
iflink 方式
[root@2105d89721a8 /]# cat /sys/class/net/eth0/iflink
24
$ cat /sys/class/net/veth05ae645/iflink
23
$ ip link show
24: veth05ae645@if23: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
link/ether 76:7a:e0:31:a9:56 brd ff:ff:ff:ff:ff:ff link-netnsid 4
$ ethtool -S veth05ae645
NIC statistics:
peer_ifindex: 23