概述

说到Overlay网络,主要解决Host主机跨网段时候,虚拟网络段之间互相通信问题。

例如: VM网络段10.239.0.0/16 网段,但是下层分别Host主机位于172.16.1.0/24; 172.16.2.0/24两个网络段,上层路由无法通过主机路由进行通信,需要使用Overlay网络了。主要由于网络虚拟化以后网络变巨大了。

在容器方面,如果您的kubernetes节点不在同一个网段上需要组成集群,就需要使用隧道网络技术,解决之前host-gw主机路由模型缺点集群不能跨主机组网。当前隧道网络主要用到ipip,vxlan,隧道。这篇文章介绍vxlan隧道。

L3 overlay网络

容器、虚拟化网络往往规模非常大,整个虚拟网络做成一个大二层网络,arp风暴,IP分布式分配等难题都会遇到。L3 overlay 组网络类似L2 overlay,但是每个节点增加一个网关。也就是说每个主机负责一个网段例如:

  • 容器网络段是: 10.239.0.0/16
  • 每个主机分别占用一个24位网段: Host 1: 10.239.0.0/24 , Host 2: 10.239.1.0/24, Host3: 10.239.2.0/24 .. HostN: 10.239.(n-1).0/24

跨节点的容器间通信只能走L3,都会经过网关转发,需要走vxlan网络,性能下降一些。

缺点

跨节点的容器间通信需要进行vxlan封包解包,性能下降。

优化点

现在网络组件还有更加智能设计,在同一网段,跨节点走容器通信host-gw模式,在不同网段节点跨节点容器网络通信走vxlan, 效率提更高。

L3 overlay (vxlan) 容器架构

这次也是以kubernetes经典网络组件flannel vxlan模式为基础进行解说。同一台主机容器网络通信可以参考容器网络模式: host-gw 介绍,内容基本一样,下面主要介绍通过vxlanl3 overlay实现容器跨网络通信

容器跨网段通信路由到vxlan接口

回顾flannelhost-gw实现跨机器通信设计在k8s集群上,经常使用多台主机组成大容器网络,主机之间容器怎么样通信呢?

  • 首先,遵循不同网段主机进行通信时候需要通过路由器进行转发。
  • 其次,Host可以认为本主机所有容器和其他主机上通信路由器, br0 连接本机容器交换机器一端, eth0 相当于连接其他网络段一端。
  • 第三, 集群每台主机都负责一个网段,每台主机都包含集群容器网络所有ip段路由表。

跨主机通信容器,就是不在同一网络段容器,通过主机上网关host-gw路由表,把数据包路由制定host机器上如图:
跨主机网络和容器网络.jpg
vxlan 隧道网络是通过vxlan接口进行网络叠加,数据怎么转到vxlan接口上,这个工作当然是有路由协议。

添加和设置vxlan接口

在配置修改路由配置前,先要有vxlan接口,需要设置这个vxlan接口IP地址。

  • Host1: 容器网络段10.239.0.0/24, br0: 10.239.0.1/24, vxlan flannel0: 10.239.0.0/32, vxlan id: 42
  • Host2: 容器网络段10.239.1.0/24, br0: 10.239.1.1/24, vxlan flannel0: 10.239.1.0/32, vxlan id: 42

两个vxlan接口可以互相通信,他们vxlan id 必须是一样的。vxlan 和 br0 网络数据流向通过route路由转向的。当然两个接口都以根网络空间TCP/IP栈内部交换,不是二层封包交换。
跨主机网络和容器网络vxlan-第 1 页.jpg

添加路由到vxlan接口

host-gw所有节点网络段路由都在主机上路由表上进行配置,所以名字为host-gw主机网关,主机处理路由意思。使用vxlan以后,跨主机容器路由有vxlan内部进行处理。所以主机上路由表相对简单,所以其他节点容器网段统一使用下面命令路由格式:

  1. $ ip route dst_node_container_network_segment via dst_node_vxlan_ip dev flannel0 onlink

以上面两台主机网络为例子
Host1 上路由配置

  1. host1$ ip route add 10.239.1.0/24 via 10.239.1.0 dev flannel0 onlink

Host2

  1. host2$ ip route add 10.239.0.0/24 via 10.239.0.0 dev flannel0 onlink

看到onlink有点疑惑,看到网段后也是有点疑惑,由于主机上IP和这个路由不在同一网段上本来不能添加这样路由,但是加了onlink就允许添加了。特殊性由接口flanlel0 vxlan接口处理。如图:
跨主机网络和容器网络vxlan-第 2 页.jpg

容器隧道-vxlan

K8s最基础容器网络组件flannel的vxlan模式下,各个主机节点是共用一个vxlan Id, 是同一个vxlan网络,暂时没有vxlan进行多网络隔离,使用更多vxlan高级功能。只是以vxlan作为隧道使用,实现容器集群跨网段作用。

接口特殊性

一般网络接口默认任务工作与TCP/IP第二层: 链路层。vxlan接口同时工作在TCP/IP 两个层:

  • 链路层: vxlan 接口工作第二层,可以接受它对应的网络命名空间TCP/IP栈上路由调配。
  • 应用层: vxlan 默认配置会占用主机上UDP端口作为Server。
    • Server服务接收外部机器vxlan隧道数据,解包后数据通过vxlan链路层一端进入接口所在网络空间TCP/IP栈,数据包继续按照网络空间路由进入到对应应用上。
    • 链路层一端接收到数据包以后进入应用层一端,进行隧道封包。所有TCP/IP协议包封装以后都是常规UDP协议,通过UDP端口发过对应主机上vxlan 应用端口。

      接口通信方式-叠加网络

      以两个接口互相发送ping包为基础进行讲述,普通网络和vxlan隧道叠加网络互相发送ping包区别

以太两个接口间通信

在同一网段下Host1 ping host2,两台主机上接口互相通信如下:
同一网段两台主机ping.jpg

同一网段两个主机vxlan接口进行通信

两台主机vxlan网段通信,例如host1下执行下面命令

  1. $ ping 10.239.1.0

IP匹配主机上root network namspace路由配置, 如下:

  1. 10.239.1.0/24 via 10.239.1.0 dev flannel0 onlink

这个网段通信都走接口flannel0, 下一跳路由地址是10.239.1.0 下面图是 vxlan(flannel0) 通信过程:
两台机器vxlan互相ping.jpg

TCP栈路由规则,数据包由flannel0vxlan接口发送,vxlan接口不直接方式链路层数据,需要通过内核vxlan 应用层发送数据步骤;

  • 组装ping包: 源地址 Host1 flannel0 接口IP地址,由路由配置决定由这个接口发出; 目标地址是10.239.1.0也就是Host2 flannel设备IP地址
  • 内核TCP栈需要通过arp表10.239.1.0对应MAC地址host2 flannel0 mac, 填入目标mac地址;源MAC地址Host1 flannel0 mac 地址。
  • flannel0是vxlan不能直接发送链路层数据,需要通过内核vxlan app进行隧道封包。(vxlan app: 这个内核处理模块占用端口,这里称呼为vxlan app)
  • vxlan app 通过flannl0vxlan设备fdb查询: host2 flanel0 mac 对端VTEP IP,端口[172.1.1.3:8742]。两个vxlan接口不是链路层通信,是通过UDP通信。对端vxlan app接收数据包通过flannel0接口再次进入tcp/ip栈
  • vxlan app 把ping封装 + 二层协议数据包到vxlan协议UDP包里面,通过eth0进行发送。这个ping封装到包换VXLAN的UDP包。vxlan 也是network on UDP
  • Host2网卡接收以后,在root network namspace上vxlan app接收UDP, 解开以后还原成在链路层传输包, 发现是匹配接口flannel0MAC,在这个接口对应TCP栈回应这个ping数据包。
  • 返回路程和发送基本一致。

虽然经过主机网络,当时两个主机flannel0犹如接口同一交换机器上两个设备,同一网络上进行通信。

解释 同一网段下两个网络接口通信时候链路层MAC地址没有被路由器替换, 源MAC地址和目标MAC地址就是通信两个设备接口MAC地址。

两个网段上主机vxlan接口进行通信

再分析一下,如果两台Host机器在不同网络段上,两个vxlan接口通信。同样Host1,执行下面ping命令,发送对端Host3 vxlan 接口:

  1. $ ping 10.239.2.0

IP匹配主机上root network namspace路由配置, 如下:

  1. 10.239.2.0/24 via 10.239.2.0 dev flannel0 onlink

这个网段通信都走接口flannel0, 下一跳路由地址是10.239.2.0 下面图是 vxlan(flannel0) 通信过程:
两台机器vxlan互相ping-第 2 页.jpg
跨网段和同一网段差别

  • 外部封包: 经过路由器,所以链路层协议源MAC和目的MAC,被替换。
  • vxlan内部: 源MAC和目标MAC通信还是同一网段时候一样,没有被替换。

    隧道目的

    1. 在容器overlay网络都有一个共同特点,所以容器节点 vxlan/tun 接口(无论这些接口所在节点间跨了多少路由器),这些接口都模拟成接入到同一网络交换机(虚拟)所有接口。好像他们间两两通信在同一网络通信两个接口。这样可以实现在跨网段,跨机房情况下同样可以构建容器网络。

容器Overlay网络世界

容器Overlay网络世界如同下面图,所有容器集群上所以节点的vxlan接口/tun接口都虚拟成接入同一交换机上网络接口,如图:

容器vxlan世界.jpg

虚拟接口数据投递

VXLAN 是一隧道网络/叠加网络, 两个接口进行数据交换,分为内层报文和外层封装。根据上一章两个VXLAN接口发送Ping包通信步骤发现,VXLAN接口间通信普通以太网链路层不一样,需要通过VTEP IP 和VTEP port进行通信。不要通过ARP表和FDB表,把对端接口IP转化对端接口VTEP 地址,这样才可以把数据包封装到VXLAN协议里面,发送对端接口对应VXLAN app绑定端口上

VXLAN 网络路由表

VXLAN 网络路由信息包含两张表ARP, FDB表。 由于VXLAN属于二层接口,内部报文里面还是需要添加二层网络信息需要用到ARP。

  1. ARP: IP -> MAC

通过ARP表,内部二层协议信息已经填写完毕了。封装VXLAN协议需要数据装入UDP包,UDP填写目标IP地址,端口号,需要通过FDB(forward database)。

  1. FDB: MAC -> DST VTEP Addr [IP:PORT] VTEP ADDR(对端 vxlan 所在机器IP地址,vxlan 占用端口)

在Flannel k8s 容器集群网络中,每个VXLAN接口设备协议栈里ARP表保存了整个网络所以节点VXLAN接口MAC地址->设备IP对应信息, FDB表保存了所有VXLAN VTEP 地址 【所在节点 IP: vxlan 端口。 由于所以接口协议栈都保存一样ARP和FDB, 好像大网络就是一个设备,共同维护维护一张投递路由表】:
容器vxlan世界-第 2 页.jpg

解释 容器网络规模和ARP,FDB规模关系。两个表条目数就是容器集群节点数目一致。

接口和投递信息维护

VXLAN ARP 和 FDB 两个表维护有下面三种

  • VXLAN 通过多播地址进行广播:通过多播地址ARP, FDB信息广播。优点:自动维护,缺点是不是所有环境都支持多播。
  • 动态更新: 配置 l2miss 和 l3miss 钩子。如果找不到MAC地址需要VTEP时候触发两l2miss通知,当找不到对应IP的MAC地址触发l3miss
  • 静态配置: 网络组件启动时候预先配置对应VXLAN的ARP表和FDB表。把ARP和FDB过期时间设置为不过期

在k8s网络组件里面一般都第三种,第二种。在flannel网络组件里面vxlan模式使用第三种。第二种缺陷是,首次建立时候处理慢导致网络卡问题。由于k8s添加和删除节点时候才会触发节点vxlan接口ARP表和FDB表才会添加、删除条目。

Flannel组件使用ETCD 分布式kv数据库,数据库存放每个节点flannel vxlan网卡MAC地址,即使机器重新启动以后可,重新创建vxlan网卡时候,也可以使用同一个MAC地址。每个Host节点flannel网络组件Agent订阅ECTD指点节点路径,如果有新节点加入/有节点删除,触发实时更新ARP表和FDB表。保持每个节点路由信息都是一致的。
例如:

Host1:
Host1 机器维护flannel0接口和Host2 flannel0接口通信 ARP表项:

  1. host1$ ip neigh add 10.239.1.0 lladdr <host2 flannel0 mac> dev flannel0

Host1 机器维护flannel0接口Host2 flannel0vxlan fdb 投递项目:

  1. host1$ bridge fdb append <host2 flannel0 mac> dev flannel0 dst <host2 ip addr>

Host2:
Host2 机器维护flannel0接口和Host1 flannel0接口通信 ARP表项:

  1. host2$ ip neigh add 10.239.0.0 lladdr <host1 flannel0 mac> dev flannel0

Host2 机器维护flannel0接口Host1 flannel0vxlan fdb 投递项目:

  1. host2$ bridge fdb append <host2 flannel0 mac> dev flannel0 dst <host2 ip addr>

数据包路由和组装过程

Overlay网络数据包装比普通网络接口多一个外部封装,里面涉及到两组二层源地址和目标mac地址, 两组IP源和目标地址。外层封包是vxlan VTEP地址。主要vxlan设备地址和VTEP IP:端口 是两个不同地址需要区分。
两台主机vxlan网段通信,例如host1下执行下面命令

  1. $ ping 10.239.1.0

IP匹配主机上root network namspace路由配置, 如下:

  1. 10.239.1.0/24 via 10.239.1.0 dev flannel0 onlink

引发vxlan数据包组装过程简述如下图:
vxlan组包过程.jpg

注意

  • flannel0接口ARP表由程序[flannel-agent]把所以节点flannel0网卡和IP地址配置进入,而且不会过时。只有增加或者删除节点触发增加和删除
  • flannel0接口fdb表有程序flannel-agent]把所以节点flannel0 mac 和VTEP地址配置进去,而且不会过时。只有增加或者删除节点触发增加和删除

容器网段数据包的路由流向

VXLAN容器网段数据包流向,在同一主机上面和host-gw都是一致的,当时在跨跨主机间容器通信需要由vxlan进行二次封包,和host-gw主机路由方式有一定区别。下面主要讨论这个有区别部分。

跨主机容器之间访问

容器出来以后,路由到br0过程已经在容器网络模式: host-gw 介绍上说明了,这里不再描述。主要描述在root network namespace使用vxlan隧道发送数据的步骤:

  • 主机root network namespace路由表,找到对应容器网络段10.239.1.0/24下一跳路由器IP【host2 flannel0 IP 10.239.1.0/32】,通过flannel0 VXLAN 接口发送。
  • flannel0 通过arp表【由fannel-agent预先配置好】IP: 10.239.1.0 对应MAC地址【host2 flannel0 MAC】,修改数据包目标MAC地址。
  • flannel0 VXLAN 不能发送二层网络数据,有VXLAN内核应用通过UDP端口发送。之前网络包封装到VXLAN协议包playload里面,称为隧道封装。
  • 和普通网络接口比较,两个VXLAN 接口间发送数据通过UDP通信建立隧道到。两个接口通信除了ARP表,还需要VXLAN接口配置FDB【投递数据库表】,两个接口间才可以通信。
  • FDB 解决对端接口MAC地址转化对端接口VTEP IP:PORT。在容器网络中VTEP IP,接口所在主机IP地址,端口VXLAN APP 占用端口

跨主机容器互相访问.jpg

注意 黑色虚线

  • 在同一网络命名空间内,同一TCP/IP栈上数据传递,并不是网络接口间互相发送数据。

    蓝色虚线

  • 代表容器节点两个vxlan虚拟连接。两个设备无论中间跨了多少网络,都虚拟通过vxlan承载虚拟成,同一网络下相邻两个接口通信

    VXLAN

  • 两个VXLAN数据包【内层封包】传递必须依赖VXLAN封包【外层封包】承载。

数据包返回和发送基本一致
跨主机容器互相访问-回应.jpg

注意 Flannel0 ARP表FDB在每台机器都有相同配置,统一由flannel agnet 配置

参考