上一篇文章里我们介绍了k8s集群中flannel udp overlay网络的创建,这在里我们基于上一篇文章中的例子,来介绍在flannel udp overlay网络中pod到pod的通讯。

在介绍之前我们先大致了一下linux TUN设备:

  • linux TUN device:Linux TUN device是一种网络设备,它可以有自己的ip地址,其最重要的特性就是可以被应用程序监听读写,被监听读写的对象为三层ip数据包。

  • TUN device一端连接网络内核空间,另一端连接用户空间的应用程序。

  • 用户空间的应用程序有能力通过TUN device读写修改三层ip数据包。

  • 数据从内核空间进入TUN device的时候,该设备会把数据交给用户空间的应用程序,使得应用程序有机会根据自己的逻辑修改ip数据包。

  • 用户空间的应用程序可以把数据发给TUN device,该设备会把数据交由内核空间进行路由转发。

  • flannel udp模式就是利用TUN device,由flannel进程完成对原始ip包的udp封包,然后转发并解包。

查看集群中所有的pod:

我们用以前文章里部署的nginx application为例子,对于这个应用:

  • 有2个pod,10.1.55.2和10.1.74.6

  • pod 10.1.55.2,在host 172.20.11.42上

  • pod 10.1.74.6,在host 172.20.11.43上

  • 我们从10.1.55.2访问10.1.74.6,ping或者traceroute

kubectl get pods -o wide --all-namespaces

利用以前文章中的kubectl-debug进入pod 10.1.55.2调试:

kubectl-debug deployment-nginx-app-69b6bbfd6d-5k8pd --namespace default
ip addr

从pod 10.1.55.2访问pod 10.1.74.6

ip addr
ping -c 4 10.1.74.6


ip addr
traceroute 10.1.74.6

我们发现无论是ping命令还是traceroute命令都可以从pod 10.1.55.2访问的到pod 10.1.74.6,说明flannel udp overlay网络是没有问题的。

我们分析数据是如何从pod 10.1.55.2访问的到pod 10.1.74.6的

数据在pod network namespace的路由

根据以前文章,10.1.55.2 pod从自己的network namespace访问10.1.74.6,根据10.1.55.2 pod network namespace的路由表,数据进入了10.1.55.2 pod宿主 172.20.11.42 network namespace的linux bridge docker0中。


数据在宿主network namespace的路由:

ip addr|grep 42
route -n

我们发现10.1.0.0/16网段的访问是直连路由,并且用flannel0设备发送。而这个flannel0设备就是flannel启动的时候在宿主机上创建的TUN device。这个时候ip数据包源ip为10.1.55.2,目标ip为10.1.74.6,数据由在内核空间进入了flannel0 TUN设备,然后由这个设备进入用户空间的flannel进程。

flannel进程udp封包

  • flannel进程在用户空间对原始ip包进行upd封包

    • 对于原始三层包:源ip为10.1.55.2,目标ip为10.1.74.6

    • 对于外层udp包:源ip为172.20.11.42,目标ip为172.20.11.43,目标port为8285(可以配置),源端口为随机端口。

  • flannel确定upd封包目标ip

    flannel连接着etcd,而etcd中已经存储overlay各个子网网段和host的关系,所以对于这个case,flannel判断目标ip10.1.74.6属于子网10.1.74.0/24,而这个子网就在host 172.20.11.43,所以udp封包的目标ip就确定了。

  • flannel确定upd封包源ip

    根据当前host路由表,发往172.20.11.0/24宿主子网的数据都由enp0s3设备发送,而这个设备的ip地址就是172.20.11.42,所以udp封包的源ip就确定了。

  • 数据由内核发送路由到目标host 172.20.11.43 上。

目标节点处理upd封包

  • 目标节点172.20.11.43的8285端口接收到udp包之后交由flannel进程处理,数据由内核空间进入程序用户空间。

  • flannel进程开始对这个upd数据解包,去掉upd的ip和port数据信息,得到内层的原始ip包。然后把这个包发送给TUN device flannel0,数据由应用程序的用户空间进入内核空间。

  • 在内核空间根据路由表进行转发

  • 根据172.20.11.43上路由表,将数据由linux bridge docker0做本地转发。

  • 根据以前文章,docker0作为linux bridge利用veth pair将数据转发到目标pod 10.1.74.6。

总结flannel udp overlay网络pod到pod的通讯过程如下:

  • 每个宿主都有名字为flannel0的TUN网络设备来完成对于原始ip数据包的udp封包与拆包,upd数据在宿主的8285端口上(端口值可配置)的flannel进程处理。

  • 数据从原始pod的network namespace进入到host的network namespace中。

  • 根据host network namespace中的路由表,下一跳ip为目标为直连,并且由当前host的TUN设备flannel0发送。

  • 当前host的TUN设备flannel0将数据从内核空间交给用户空间应用程序flannel。

  • 户空间应用程序flannel根据目标ip属于哪个子网,然后在etcd中查询这个子网所在的目标host,最后完成upd封包,这个时候:

    • 对于原始三层包:源ip为源pod ip,目标ip为目标pod ip。

    • 对于外层udp包:源ip为当前host的ip,目标ip为flannel在etcd中查询的匹配ip,目标port为8285(可以配置),源端口为随机端口。

  • flannel将upd包发送给TUN设备flannel0,数据由用户空间进入内核空间。

  • 数据在内核空间根据路由策略发送到目标宿主的8285端口。

  • 目标宿主的8285端口为flannel进程,数据由内核空间进入用户空间。

  • flannel进程对udp数据拆包,去掉ip和port信息,得到内层的原始ip包。然后把这个包发送给TUN device flannel0,数据由应用程序用户空间进入内核空间。

  • 根据目标节点host上路由表,将数据由linux bridge docker0做本地转发。

  • 数据由linux bridge docker0利用veth pair转发到目标pod。

目前先写到这里,下一篇文章里我们继续介绍k8s集群中underlay网络和overlay网络的总结对比。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐