首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

k8s集群网络(11)-flannel vxlan overlay网络通讯

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

查看集群中所有的pod:

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

  • 有2个pod,10.1.55.2和10.1.74.5
  • pod 10.1.55.2,在host 172.20.11.42上
  • pod 10.1.74.5,在host 172.20.11.43上
  • 从10.1.55.2访问10.1.74.5,ping或者traceroute来验证pod间的通讯。
代码语言:javascript
复制
kubectl get pods -o wide --all-namespaces

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

代码语言:javascript
复制
kubectl-debug deployment-nginx-app-69b6bbfd6d-5k8pd --namespace default

从pod 10.1.55.2访问pod 10.1.74.5

代码语言:javascript
复制
ip addr
ping -c 4 10.1.74.5

ip addr
traceroute 10.1.74.5

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

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

数据在pod network namespace的路由

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

数据在宿主network namespace的路由:

代码语言:javascript
复制
ip addr|grep 42
route -n

我们发现10.1.74.0/24网段的访问下一跳ip地址是10.1.74.0/32,并且用flannel.1设备发送。而这个flannel.1设备就是flannel启动的时候根据vxlan类型网络在宿主上创建的,它属于vxlan设备,会完成对二层eth以太数据包到udp数据包的封装与拆封。其中的".1"代表vxlan这个二层网络id号为1,也对应了vxlan网络在etcd里的配置。这个时候数据包源ip为10.1.55.2,目标ip为10.1.74.5,源mac为pod 10.1.55.2 network namespace中veth设备mac,目标mac为下一跳ip 10.1.74.0/32的mac。

查询vtep端点mac地址:

我们在pod 10.1.55.2的宿主172.20.11.42上通过arp表查询10.1.74.0/32的mac地址为5e:75:7d:bf:98:03

代码语言:javascript
复制
ip addr|grep 42
ip neigh|grep 10.1.74.0
ip neigh show dev flannel.1

查询vtep端点mac地址转发接口

由于flannel.1设备是vxlan设备,会有转发接口与它的mac对应,我们继续在pod 10.1.55.2的宿主172.20.11.42上查询flannel.1设备的mac转发接口。

代码语言:javascript
复制
ip addr|grep 42
bridge fdb show |grep 5e:75:7d:bf:98:03
bridge fdb show dev flannel.1

我们发现flannel.1设备mac地址5e:75:7d:bf:98:03对应的转发接口为172.20.11.43,代表flannel.1设备将会把原始二层数据包(源ip为10.1.55.2,目标ip为10.1.74.5,源mac为pod 10.1.55.2 network namespace中veth设备mac,目标mac为10.1.74.0/32 mac)做为upd的payload发给172.20.11.43的8472端口(上一篇文章有端口配置)。而我们知道目标pod 10.1.74.5的宿主确实是172.20.11.43,而且其上的flannel.1设备同样会对8472端口的数据进行upd解包。

flannel.1设备upd封包

代码语言:javascript
复制
ip addr|grep 42
route -n

我们从pod 10.1.55.2的宿主172.20.11.42的路由表得知发往172.20.11.0/24网段为直连路由,使用宿主网络设备enp0s3发送。所以对于:

  • 外层udp包:源ip为172.20.11.42,目标ip为172.20.11.43,源mac为172.20.11.42 mac,目标mac为172.20.11.43 mac。目标端口为8472,vxlan id为1.
  • 内层二层以太包:源ip为10.1.55.2,目标ip为10.1.74.5,源mac为pod 10.1.55.2 network namespace中veth设备mac,目标mac为10.1.74.0/32 mac
  • 完成封包以后根据宿主路由表发向目标节点172.20.11.43。

目标节点处理upd封包

  • 目标节点172.20.11.43的8472端口接收到udp包之后,发现数据包里有vxlan id标识为1。由于linux内核支持vxlan,所以协议栈可以通过vxlan id判断这是一个vxlan数据报文,并且vxlan为1。然后找到宿主机器上vxlan id为1的vxlan设备处理,这里就是172.20.11.43上的flannel.1设备了。
  • flannel.1收到数据之后开始对vxlan udp报文拆包,去掉upd报文的ip,port,mac信息后得到内部的payload,发现是一个二层报文。
  • 对于这个二层报文继续拆包,得到里面的源ip是10.1.55.2,目标ip是10.1.74.5。
  • 根据172.20.11.43上路由表,将数据由linux bridge docker0做本地转发。
  • 根据以前文章,docker0作为linux bridge利用veth pair将数据转发到目标pod 10.1.74.5。

host的路由表和fdb转发表的写入

这里vxlan关键的两个点就是:

  • 宿主host的路由表的写入
  • flannel.1设备mac转发接口表的写入

那么这些数据是怎么写入host的呢?因为所有的host都运行flannel服务,而flannel连接etcd存储中心,所以每个host就知道自己的子网地址cidr是什么,也知道在这个cidr中自己的flannel.1设备ip地址和mac地址,同时也知道了其它host的子网cidr以及flannel.1设备ip地址和mac地址。而知道了这些信息,就可以在flannel启动的时候写入到路由表和fdb中了,以下面172.20.11.42宿主为例:

代码语言:javascript
复制
ip addr|grep 42
bridge fdb show dev flannel.1
etcdctl --ca-file /etc/etcd/ca.crt --cert-file /etc/etcd/etcd-client.crt --key-file /etc/etcd/etcd-client.key get /cloudnetwork/subnets/10.1.82.0-24
etcdctl --ca-file /etc/etcd/ca.crt --cert-file /etc/etcd/etcd-client.crt --key-file /etc/etcd/etcd-client.key get /cloudnetwork/subnets/10.1.74.0-24
etcdctl --ca-file /etc/etcd/ca.crt --cert-file /etc/etcd/etcd-client.crt --key-file /etc/etcd/etcd-client.key get /cloudnetwork/subnets/10.1.55.0-24

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

  • 每个宿主都有名字为flannel.x的vxlan网络设备来完成对于vxlan数据的udp封包与拆包,upd数据在宿主的8472端口上(端口值可配置)处理。
  • 数据从pod的network namespace进入到host的network namespace中。
  • 根据host network namespace中的路由表,下一跳ip为目标vxlan设备的ip,并且由当前host的flannel.x设备发送。
  • 根据host network namespace中的apr表找到下一跳ip的mac地址。
  • 根据host network namespace中fbd找到下一跳ip的mac地址对应的转发ip。
  • 当前host的flannel.x设备根据下一跳ip的mac地址对应的转发ip和本地路由表进行upd封包,这个时候:
    • 外层udp包:源ip为当前host ip,目标ip为mac转发表中匹配的ip,源mac为前host ip的mac,目标mac为fdb中匹配ip的mac。目标端口为8472(可配置),vxlan id为1(可配置).
    • 内层二层以太包:源ip为源pod ip,目标ip为目标pod ip,源mac为源pod mac,目标mac为host network namespace中路由表里下一跳ip的mac(一般为目标pod对应的host中flannel.x设备ip)。
  • 数据包由当前host路由到目标节点host。
  • 目标节点host的8472端口接收到udp包之后,发现数据包里有vxlan id标识.。然后根据linux vxlan协议,在目标宿主机器上找到与数据报文中vxlan id对应的vxlan设备,将数据交由其处理。
  • vxlan设备收到数据之后开始对vxlan udp报文拆包,去掉upd报文的ip,port,mac信息后得到内部的payload,发现是一个二层报文。然后继续对这个二层报文拆包,得到里面的源pod ip和目标pod ip。
  • 根据目标节点host上路由表,将数据由linux bridge docker0做本地转发。
  • 数据由linux bridge docker0利用veth pair转发到目标pod。
  • 每个宿主host的flannel服务启动的时候读取etcd中的vxlan配置信息,在宿主host的路由表和mac转发接口表fdb里写入相应数据。
下一篇
举报
领券