前言

环境采用了calico+ebgp/ibgp+交换机组成了一个扁平化网络,使用calico宣告POD IP,做到了POD与其他虚拟机和开发网落处在同一个平面的效果。

具体组网信息可以参考calico网站。

东西流量

Pod到Service流量

一般的应用大多数是以Pod到Service的形式去请求服务,从而出现东西方向的流量,目前集群的网络采用Calico作为网络插件,POD的IP由Calico进行统一分配,Service IP由集群K8s分配,并且配合Kube-proxy操作Iptable创建对应的规则。

首先,创建一个POD时,calico会同时在POD对应的主机生成对应的calico网桥calixxx,并且分配IP,并且通过calico组件路由宣告出去:

发送到calixxx的流量会转发至POD的eth0网卡,而从POD发出来的报文则是通过ARP 代理的方式转发至calixxx网桥。

而当一个Service创建之后,会根据选择器与POD标签配对,对应上POD IP并且被Kube-Proxy监控到,K8s会随即生成对应的DNS记录service.namespace.local.cluster:serviceclusterIP,然后在Iptables添加相应的规则记录,如(10.88.145.173为ServiceIP,10.90.1.127为POD IP):

一般的,在集群中从POD访问Service,再从Service到达对应的POD流程为(正向请求用①表示,回复报文用(1)表示):

下面梳理一下请求的主要过程:

  • ①POD向domian发送请求
  • ②由于没有IP,POD先向CoreDNS查询域名对应的IP地址
  • ③CoreDNS返回对应的Service IP
  • ④POD拿到IP之后,向该IP发送数据,对应的报文从calixxx网桥出来
  • ⑤从calixxx网桥出来后,进入Host Iptables链,进入IP tables之后,进入对应的链路如上图规则,最后得到Service对应的POD IP,并转发到此IP,此时会经过路由,分为两种情况,目标IP在同一节点上(路由表有记录)或者不在同一节点上(路由表无记录)
  • ⑥如果在同一节点上,根据路由表则会路由到目标IP对应的calixxx网桥
  • ⑦如果不在同一节点上,则根据路由表规则,会从bond1口出去
  • ⑧到达交换机,交换机有对应的路由条目,则会走到(3)和(4)过程进入Host,并且走到Iptables,通过路由,转到⑥过程
  • ⑨到达calixxx网桥之后会转发至POD eth0网卡,到达POD

应答过程:

  • (1)POD以传过来的源POD IP作为目的IP从eth0发出,通过ARP代理转发到calixxx网桥
  • (2)达到calixxx网桥之后会经过POD所在的节点的Host路由表,同样分为两种情况
  • (3)如果不在同一节点上,则会走bond1到交换机
  • (4)再从交换机到达对应的节点,之后便到达过程(5)
  • (5)经过路由表,到达目的IP 对应calixxx网桥
  • (6)再从网桥到达POD eth0

Pod到Pod流量

由于网络平面化,POD IP可以直通,所以会存在POD相互访问的场景,如隐私号应用等:

主要过程:

  • ①POD以目标POD的IP作为目的IP,从eth0发出,到达calixxx
  • ②到达calixxx网桥之后会进入Host内核Iptables链到达PREROUTING(路由前)
  • ③之后进入路由模块进行路由,路由判断该报文是否是发给本机的,如果是则往上收将进入INPUT链,此过程不在讨论范围,由于报文目的地址是POD IP,所以会转发出去
  • ④到达FORWARD链后进入POSTROUTING(路由后)
  • ⑤进入POSTROUTING会进行一些地址转换等操作后发往对应网卡或者网桥,如果路由结果表明该报文要通过网卡Bond1出去则会走到⑧过程,否则会走到⑥
  • ⑥表明目的IP在本机网桥上(即POD在同一节点上),则进入目的地址对应的calixxx网桥
  • ⑦再转发至POD eth0网卡到达目的地
  • ⑧报文从内核出来进入网卡,准备向外发出
  • ⑨到达交换机,由于交换机有所有POD的路由信息,所以他能正确处理经过的报文
  • ⑩经过路由后到达POD所在节点的入口网卡Bond1
  • 11.到达网卡之后会进入内核Linux协议栈进行Iptables规则链匹配(可能的路径为到③->④->⑤->⑥->⑦到达对应的POD)

回复过程:

  • (1)到达目的POD之后,应用根据源IP进行回应,转发至calixxx网桥
  • (2)到达网桥之后进入Linux协议栈,其过程会从③->④->⑤->(3)到达源POD
  • (3)到达源POD对应的网桥
  • (4)从网桥转发至POD eth0网卡,此时会经过Linux协议栈,最终报文从内核到用户空间送到应用。

南北流量

外部流量从Ingress(越过service)到Pod

client客户端请求POD应用,首先要创建对应的Service,并且创建Ingress路由。集群中采用Traefik作为Ingres Controller,以DeamonSet的方式部署,并且开启hostNetwork模式,与主机公用网络协议栈。并且接管所有到达主机的80端口、8080端口的报文。Traefik的原理主要是通过监控APIserver来监控Service、POD的变化,并维护路由,而且接管80端口的流量,转发到对应路由的POD IP上。

具体过程为:

简单解释一下过程:

  • ①(客户端首先向DNS服务器获取域名对应的IP)向目标IP发送请求,到达交换机
  • ②经过路由之后定向到目标IP所在的主机,由于设置了HA-proxy,请求会先到VIP对应的网卡bond1:1
  • ③从外联口进来之后进入内核程序处理
  • ④到达路由模块,判断报文是发送给本机的,则往上收
  • ⑤到达INPUT链,之后会根据端口号,发至对应的应用程序,由于是HA-proxy提供的代理,从而进入HA程序,程序代理到Hots3 IP上,所以从POSTROUTING出来之后会到达(15)过程,在到达⑤,往上到达Traefik程序
  • ⑥Traefik接管80端口的流量,进行路由匹配之后(拿到请求对应的POD IP),代理至POD IP
  • ⑦进入路由
  • ⑧进入OUTPUT链
  • ⑨进入POSTROUTING,通过路由之后,如果目的IP地址位于同一节点,则会路由到calixxx网桥,否则会走到(12)过程,到达交换机路由之后达到对应主机上(12->13->14->15->④->FORWARD->⑨->⑩)
  • ⑩到达calixxx网桥,然后到达POD eth0网卡

回复过程:

  • (1)到达calixxx网桥
  • (2)进入主机网络栈,返回Traefik代理:

之后从Traefik即主机网络栈出来到达外联口

  • (3)从外联口出来(SNAT),到达交换机
  • (4)到达客户端(DNAT)

外部流量直接到Pod

由于POD IP直接通过calico BGP路由宣告出去,因此POD网段与虚机、本地电脑处在同一平面,请求POD IP与请求虚拟机情况一致:

具体流程:

  • ①客户端请求到达交换机
  • ②交换机路由到目的地址对应的主机上
  • ③进入主机网络栈进行路由(简画)
  • ④可能会经过此过程(就是目标POD不在该节点上)
  • ⑤重新到达交换机
  • ⑥再次路由到达目标节点
  • ⑦进入主机网络栈
  • ⑧路由到calixxx网桥
  • ⑨到达POD eth0网卡

回复过程:

  • (1)发送至calixxx网桥
  • (2)进入到主机网络栈,进行路由
  • (3)发送至外联口bond1
  • (4)到达交换机,路由
  • (5)到达客户端(可能会经过NAT)

外部流量直接访问ServiceIP(特性)

将Service IP通过calico BGP协议路由宣告出去,从而实现了Service IP可以直通的场景:

具体流程:

  • ①被路由宣告的ServiceIP会出现在交换机路由表条目上,请求到达交换机
  • ②交换机进行路由,到达目的IP所在的对应节点(进群内任何一个节点)
  • ③从网卡接收报文,经过网络栈路由到达calixxx网桥(与访问service过程一至)
  • ④进入calixxx网桥
  • ⑤进入eth0

回复过程:

  • (1)从应用发出到达calixxx
  • (2)到达主机网络栈
  • (3)到达外联口网卡
  • (4)到达交换机
  • (5)到达客户端

总结

集群目前采用Iptables部署方式,依赖Iptables规则。如果集群Service过多会导致经常对Iptables频繁操作,并且如果表变得很大,更新表就会变得困难。

因此Iptables这块将来可能会遇到瓶颈。

calico网桥与容器网桥这段映射的具体实现是怎样,包括性能如何等还没有深入了解。

参考:

l2-interconnect-fabric

calico学习

Calico网络的原理、组网方式与使用