阿里云的terway网络插件拉平了云主机与容器的网络平面,实现了集群外主机直接访问容器IP的效果。本文通过实践来学习一下这个网络插件。

创建K8S集群

我们在阿里云上创建一个两个worker节点的K8S托管集群

网络插件选择terway,勾选IPvlan

然后“虚拟交换机”选择switch1,“Pod虚拟交换机”选择pod-switch(这两个交换机要提前创建),那么云主机的IP地址将会是192.168.0.0/24,Pod的IP地址将会是192.168.1.0/24

完成其他配置等待集群创建成功

创建Pod

我们创建一个工作负载,发布两个容器,容器的分布情况如下:

网络拓扑图

我们去192.168.0.48这台主机上查看一下它的网卡信息,如下:

其中eth0的IP为192.168.0.48/24;eth1没有IP;ipvl_6是eth1的一个ipvlan子设备,它的IP为192.168.0.48/32。

我们再来看一下48主机上的路由信息,如下:

接着,我们进入到nginx容器中去看一下Pod中的网卡及路由信息,如下:

我们发现,Pod中的eth0网卡也是主机上eth1网卡的一个ipvlan子设备(eth0@if6中的if6表示主机上的interface 6,从前面的截图中可以看到eth1网卡的编号为6)。

那么,我们基本可以得到该集群的逻辑网络拓扑图,如下:

连通性分析

接下来,我们来分析一下,各种场景下是如何进行通信的。

  • Pod1 -> Pod2(Pod1 Ping 192.168.1.47)

Pod1和Pod2的eth0网卡都是主机VM48的eth1网卡的ipvlan子设备。如果了解ipvlan的话,那么就会如果满足以下的条件,那么ipvlan子设备之间是可以直接通信的:(1)两个子设备都有IP(2)通信时源IP是其中一个设备的IP,目的IP是另一个设备的IP(3)数据包发送时要从其中的一个子设备发出(4)发送方的路由要显示对方为直达,不能经过其他网关

我们来看一下Pod1 Ping Pod2(Ping 192.168.1.47)的场景。

先看Pod1 -> Pod2:Pod1和Pod2的eth0网卡都有IP,满足上面的条件一。当Pod1 Ping Pod2时,根据Pod1中下面的路由,Pod1的数据包会从Pod1的eth0网卡出去,满足条件三。同时,由于从eth0网卡出去,所以源IP就会是eth0的IP,满足条件二。同时,路由显示是直达不需要经过网关,满足条件四。所以,Pod1的Ping包,Pod2是可以收到的。

Destination     Gateway    Genmask         Flags Metric Ref    Use Iface
192.168.1.0     0.0.0.0    255.255.255.0   UH    0    0        0   eth0

Pod2 -> Pod1的回复包,过程和上面是一样的,所以回复包Pod1可以收到。那么Pod1和Pod2之间是可以相互连通的。

由于篇幅有限,本文不对ipvlan进行详细介绍,如有兴趣,可以自行学习linux内核源码中ipvlan收发包的驱动函数。以后有机会再详细地介绍一下Linux下的虚拟网络设备veth、bridge、vxlan、ipip、macvlan、ipvlan等等。

  • Pod1 -> Pod3(Pod1 Ping 192.168.1.48)

根据Pod1中的路由表,当它Ping Pod3时,发现它与Pod3在同一个子网中,于是就会发起ARP请求。假设它能得到ARP的响应得到Pod3的MAC地址,那么它就会发送数据帧。

由于发送ARP请求与发送数据帧都是在网络的第二层,所以问题在于Pod1与Pod3是否在一个二层网络中。

Pod1中的eth0是VM48上eth1的一个ipvlan子设备,如果了解ipvlan的话,就知道它们是二层连通的。VM48的eth1与交换机pod-switch直接相连,那么它们也是二层连通的。pod-switch与VM49的eth1直接相连,所以它们也是二层连通的。最后VM49的eth1是Pod3的eth0的ipvlan父设备,所以它们也是二层连通的。

也就是说,Pod1的eth0与Pod3的eth0同处于一个二层网络中,所以它们是二层互通的,那么是可以相互Ping通的。

数据包的路径为:Pod1的eth0 -> VM48的eth1 -> switch1 -> VM49的eth1 -> Pod3的eth0

  • Pod1 -> VM48(Pod1 Ping 192.168.0.48)

VM48中有一个ipvl_6设备,它也是eth1的一个ipvlan子设备。所以,Pod1与VM48进行通信,与上面的Pod1 -> Pod2的通信机制类似,是两个ipvlan子设备之间的通信。那么我们来看看是否满足前面说到的四个条件。

首先ipvl_6也有IP 192.168.0.48,满足条件一。然后在Pod1中有如下的路由:

Destination     Gateway    Genmask         Flags Metric Ref    Use Iface
192.168.0.48    0.0.0.0    255.255.255.255 UH    0    0        0   eth0

这条路由表示,192.168.0.48这个IP可以直达,不用经过任何的网关,满足条件四。同时这条路由也决定了发送包是从Pod1的eth0网卡发出,满足条件三。由于是从eth0网卡出,那么源IP就是192.168.1.49,满足条件二。

所以,Pod1 Ping 192.168.0.48 的包,VM48是可以收到的。

  • VM48 -> Pod1(VM48 Ping 192.168.1.49)

VM48首先查看路由表,发现如下一条路由

Destination     Gateway    Genmask         Flags Metric Ref    Use Iface
192.168.1.49    0.0.0.0    255.255.255.255 UH    0    0        0   ipvl_6

也就是说,当从VM48上Ping Pod1时,会从ipvl_6网卡发送。此时,它完全满足ipvlan子设备通信的上述四个条件。

  • Pod1 -> VM49

首先查看Pod1上的路由表,发现默认网关为192.168.1.253,于是就会转发到该网关。完整的通信链路为:

Pod1的eth0 -> VM48的eth1 -> pod-switch -> 虚拟路由器的192.168.1.253接口 -> 虚拟路由器的192.168.0.253接口 -> switch1 -> VM49的eth0网卡

  • VM49 -> Pod1

该通信流程与上面的流程刚好相反。

  • 其他场景

还有几个其他场景,(1)Pod1访问switch1上的集群外主机,它的通信链路与Pod1 -> VM49是一样的 (2)switch1上的集群外主机访问Pod1,它的通信链路与VM49 -> Pod1是一样的


关注公众号《K8S小白》,阅读更多云原生网络相关文章

03-05 22:16