云原生虚拟网络 tun/tap & veth-pair( 三 )


veth-pairveth-pair 就是一对的虚拟设备接口,它是成对出现的,一端连着协议栈,一端彼此相连着,在 veth 设备的其中一端输入数据,这些数据就会从设备的另外一端原样不变地流出:

云原生虚拟网络 tun/tap & veth-pair

文章插图
利用它可以连接各种虚拟设备,两个 namespace 设备之间的连接就可以通过 veth-pair 来传输数据 。
下面我们做一下实验,构造一个 ns1 和 ns2 利用 veth 通信的过程,看看veth是如何收发请求包的 。
# 创建两个namespaceip netns add ns1ip netns add ns2# 通过ip link命令添加vethDemo0和vethDemo1ip link add vethDemo0 type veth peer name vethDemo1# 将 vethDemo0 vethDemo1 分别加入两个 nsip link set vethDemo0 netns ns1ip link set vethDemo1 netns ns2# 给两个 vethDemo0 vethDemo1配上 IP 并启用ip netns exec ns1 ip addr add 10.1.1.2/24 dev vethDemo0ip netns exec ns1 ip link set vethDemo0 upip netns exec ns2 ip addr add 10.1.1.3/24 dev vethDemo1ip netns exec ns2 ip link set vethDemo1 up然后我们可以看到 namespace 里面设置好了各自的虚拟网卡以及对应的ip:
~ # ip netns exec ns1 ip addrroot@VM_243_186_centos1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group defaultlink/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:007: vethDemo0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether d2:3f:ea:b1:be:57 brd ff:ff:ff:ff:ff:ffinet 10.1.1.2/24 scope global vethDemo0valid_lft forever preferred_lft foreverinet6 fe80::d03f:eaff:feb1:be57/64 scope linkvalid_lft forever preferred_lft forever然后我们 ping vethDemo1 设备的 ip:
ip netns exec ns1 ping 10.1.1.3对两个网卡进行抓包:
~ # ip netns exec ns1 tcpdump -n -i vethDemo0root@VM_243_186_centostcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on vethDemo0, link-type EN10MB (Ethernet), capture size 262144 bytes20:19:14.339853 ARP, Request who-has 10.1.1.3 tell 10.1.1.2, length 2820:19:14.339877 ARP, Reply 10.1.1.3 is-at 0e:2f:e6:ce:4b:36, length 2820:19:14.339880 IP 10.1.1.2 > 10.1.1.3: ICMP echo request, id 27402, seq 1, length 6420:19:14.339894 IP 10.1.1.3 > 10.1.1.2: ICMP echo reply, id 27402, seq 1, length 64~ # ip netns exec ns2 tcpdump -n -i vethDemo1root@VM_243_186_centostcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on vethDemo1, link-type EN10MB (Ethernet), capture size 262144 bytes20:19:14.339862 ARP, Request who-has 10.1.1.3 tell 10.1.1.2, length 2820:19:14.339877 ARP, Reply 10.1.1.3 is-at 0e:2f:e6:ce:4b:36, length 2820:19:14.339881 IP 10.1.1.2 > 10.1.1.3: ICMP echo request, id 27402, seq 1, length 6420:19:14.339893 IP 10.1.1.3 > 10.1.1.2: ICMP echo reply, id 27402, seq 1, length 64通过上面的抓包,并结合ping相关概念,我们大致可以了解到:
  1. ping进程构造ICMP echo请求包,并通过socket发给协议栈;
  2. 协议栈根据目的IP地址和系统路由表,知道去 10.1.1.3 的数据包应该要由 10.1.1.2 口出去;
  3. 由于是第一次访问 10.1.1.3,刚开始没有它的 mac 地址,所以协议栈会先发送 ARP 出去,询问 10.1.1.3 的 mac 地址;
  4. 协议栈将 ARP 包交给 vethDemo0,让它发出去;
  5. 由于 vethDemo0 的另一端连的是 vethDemo1,所以ARP请求包就转发给了 vethDemo1;
  6. vethDemo1 收到 ARP 包后,转交给另一端的协议栈,做出 ARP 应答,回应告诉 mac 地址 ;
  7. 当拿到10.1.1.3 的 mac 地址之后,再发出 ping 请求会构造一个ICMP request 发送给目的地,然后ping命令回显成功;
总结本篇文章只是讲了两种常见的虚拟网络设备 。起因是在看 flannel 的时候,书里面都会讲到 flannel0 是一个 tun 设备,但是什么是 tun 设备却不明白,所以导致 flannel 也看的不明白 。

经验总结扩展阅读