ACK容器网络数据链路(Terway ENIIP)

Terway ENIIP模式架构设计

弹性网卡(ENI)支持配置多个辅助IP的功能,单个弹性网卡(ENI)根据实例规格可以分配6-20个辅助IP,ENI多IP模式就是利用了这个辅助IP分配给容器,从而大幅提高了Pod部署的规模和密度。在网络联通的方式上,Terway支持选择veth pair策略路由和ipvlanl两种方案,主要考虑了以下两点。

1.在节点上如何将弹性网卡(ENI)的辅助IP的流量都走对应的弹性网卡,并使用弹性网卡本身的MAC地址而不被丢包。

2.如何兼容容器服务目前广泛的Centos 7.x的3.10的版本的内核。

image

Pod所使用的CIDR网段和节点的CIDR是同一个网段。

image

Pod内部可以得到是有一张网卡的,一个是eth0,其中eth0的IP就是Pod的IP,此网卡的MAC地址和控制台上的ENI的MAC地址不一致同时ECS上有多张ethx的网卡。

image

同时ECS上有多张ethx的网卡,说明ENI附属网卡并不是直接挂载到了Pod的网络命名空间。

image

image

Pod内有只有指向eth0的默认路由,说明Pod访问任何地址段都是从eth0为统一的出入口。

image

容器的网络命名空间中通过ip addr得到一个eth0@ifxxx的标志位,通过'xxx'可以得到ECS的OS内和容器网络命名空间中的相对应veth pair。在ECS OS内通过ip addr | grep xx:可以查看cali44ae9fbceeb虚拟网卡,这个就是veth pair在ECS OS侧相对的网卡对。

image

通过OS Linux Routing可以得到,所有目的是Pod IP的流量都会被转发到Pod对应的calixx虚拟往卡上。因此,ECS OS和Pod的网络命名空间已经建立好完整的出入链路配置了。

image

在veth pair中实现了多个Pod共享一个ENI的方式来提升了ECS的Pod部署密度,Terway Pod是通过daemonset的方式部署在每个节点上的。

image

通过下面命令可以得到每个节点上的Terway Pod。通过terway-cli show factory命令可以得到节点上的附属ENI数量、MAC地址以及每个ENI上的IP。

image

故Terway ENIIP模式总体可以归纳为:

  • 在网络联通的方式上,采用选择veth pair策略路由。

  • 一对veth pair来联通宿主机和Pod的网络空间,Pod的地址是来源于弹性网卡的辅助IP地址,并且节点上需要配置策略路由来保证辅助IP的流量经过它所属的弹性网卡。

  • 同主机上的容器通信直接通过主机上的路由到同一个主机上别的容器对应的veth上。

  • 不同主机的容器通信经过VPC的网络转发到对应的机器上,再通过机器上的路由转发到容器中。

  • 容器和其所在的宿主机之间的通信直接通过连接到宿主机Namespace的veth pair和路由打通。

  • 容器到其他主机通过VPC的网络转发到对应的机器,其他主机到容器通过VPC网络转发到对应的弹性网卡,然后通过路由转发到容器的veth上。

  • 容器到专线和共享服务也都是通过VPC的网络转发。

  • 容器到公网的访问经过vSwitch配置的SNAT网关直接将源IP转换成EIP的地址到外部网络。

  • 弹性网卡(ENI)支持配置多个辅助IP的功能,单个弹性网卡(ENI)根据实例规格可以分配6-20个辅助IP,ENI多IP模式就是利用了这个辅助IP分配给容器,从而大幅提高了Pod部署的规模和密度。

Terway ENIIP模式容器网络数据链路剖析

以将Terway ENI模式下的网络链路大体分为以Pod IP对外提供服务和以SVC对外提供服务两个大的SOP场景,进一步细分,可以归纳为12个不同的小的SOP场景。

image

对这12个场景的数据链路梳理合并,这些场景可以归纳为下面7类典型的场景:

  • 访问 Pod IP,同节点访问Pod。

  • 访问Pod IP/SVC IP(Cluster or Local),同节点Pod间互访(Pod属于同or不同ENI)。

  • 访问PodIP,异节点Pod间互访。

  • 集群内非SVC后端Pod所在节点访问SVC Cluster IP。

  • Cluster模式,集群内非SVC后端Pod所在节点访问SVC External IP。

  • Local模式,集群内非SVC后端Pod所在节点访问SVC External IP。

  • 集群外访问SVC External IP。

场景一:访问Pod IP,同节点访问Pod

环境

xxx.10.0.1.82节点上存在nginx-7d6877d777-zp5jg,IP地址10.0.1.104。

image

内核路由

nginx-7d6877d777-zp5jg,IP地址10.0.1.104,该容器在宿主机表现的PID是1094736,该容器网络命名空间有指向容器eth0的默认路由。

image

image

该容器eth0在ECS OS 内对应veth pair是calif03b26f9a43。

image

在ECS OS内,有指向Pod IP,下一跳为calixxxx的路由,通过前文可以知道calixxx网卡是和每个Pod内的veth1组成的pair。所以,Pod内访问SVC的CIDR会有指向veth1的路由,不会走默认的eth0路由。因此calixx网卡在这里的主要作用是用于:

1.节点访问Pod。

2.当节点或者Pod访问SVC的CIDR时,会走ECS OS内核协议栈转换,走到calixxx和veth1访问Pod。

image

小结

nginx-7d6877d777-zp5jg netns eth0可以抓到数据包。

image

nginx-7d6877d777-zp5jg calif03b26f9a43可以抓到数据包。

image

数据链路转发示意图:

image

  • 会经过calixx网卡,每个非host network的Pod会和calixx网卡形成veth pair,用于和其他Pod或Node进行通信。

  • 整个链路的请求不会经过Pod所分配的ENI,而是直接在OS的Namespace中命中IP规则被转发。

  • 整个请求链路是OS -> calixxxxx -> ECS Pod net eth0。

  • 整个链路会经过两次内核协议栈:ECS OS和Pod。

场景二:访问Pod IP/SVC IP(Cluster or Local),同节点Pod访问Pod(Pod属于同or不同ENI)

环境

xxx.10.0.1.82节点上存在nginx-7d6877d777-zp5jg,IP地址10.0.1.104。

xxx.10.0.1.82节点上存在centos-67756b6dc8-h5wnp,IP地址10.0.1.91。

image

Service是nginx,Cluster IP是192.168.2.115,External IP是10.0.3.62。

image

内核路由

nginx-7d6877d777-zp5jg IP地址10.0.1.104,容器在宿主机表现的PID是1094736,该容器网络命名空间有指向容器eth0的默认路由。

image

image

该容器eth0在ECS OS内对应veth pair是calif03b26f9a43。

image

用上述类似办法可以发现centos-67756b6dc8-h5wnp的veth pair的cali44ae9fbceeb,Pod网络空间只有默认路由。

image

image

在ECS OS内,有指向Pod IP,下一跳为calixxxx的路由,通过前文可以知道calixxx网卡是和每个Pod内的veth1组成的pair,所以,Pod内访问SVC的CIDR会有指向veth1的路由,不会走默认的eth0路由。因此calixx网卡在这里的主要作用是用于:

1.节点访问Pod。

2.当节点或者Pod访问 SVC的CIDR时,会走ECS OS内核协议栈转换,走到calixxx和eth0访问Pod。

image

说明相关的路由转发是在ECS OS层面进行的,Pod的calixx网卡起到了一个桥梁和连通的作用。

源端ECS上的IPVS规则(如果访问的是SVC IP)

如果同节点上访问的是SVC的IP(Cluster IP或External IP)。查看SVC的相关IPVS转发规则:

Service的ExternalTrafficPolicy是Local

SVC nginx Cluster IP是192.168.2.115,External IP是10.0.3.62,后端是10.0.1.104和10.0.3.58。

image

xxx.10.0.1.82节点:

对于SVC的Cluster IP,可以得到SVC的后端两个Pod都会被加到IPVS的转发规则。

image

对于SVC的External IP,可以得到SVC的后端,只有该节点的后端Pod 10.0.1.104才会被加到IPVS的转发规则。

image

在LoadBalancer的SVC模式下,如果ExternalTrafficPolicy为Local,对于Cluster IP来说,会将所有SVC后端Pod都会加到该节点的IPVS转发规则;对于External IP,只会将该节点上的SVC后端Pod才会加到IPVS规则中。如果该节点没有SVC后端Pod,则该节点上的Pod访问SVC的External IP将会失败。

Service的ExternalTrafficPolicy是Cluster

SVC nginx1 Cluster IP是192.168.2.253,External IP是10.0.3.63,后端是10.0.1.104和10.0.3.58。

image

xxx.10.0.1.82节点。

对于SVC的Cluster IP,可以得到SVC的后端两个Pod都会被加到IPVS的转发规则。

image

对于SVC的External IP,可以得到SVC的后端两个Pod都会被加到IPVS的转发规则。

image

在LoadBalancer的SVC模式下,如果ExternalTrafficPolicy为Cluster,对于Cluster IP或External IP来说,会将所有SVC后端Pod都会加到该节点的IPVS转发规则。

小结

Conntrack表信息

Service nginx的ExternalTrafficPolicy是Local

SVC nginx Cluster IP是192.168.2.115,External IP是10.0.3.62,后端是10.0.1.104和10.0.3.58。

  1. 如果访问的是SVC的Cluster IP,通过conntrack信息,可以得到src是源端Pod 10.0.1.91,dst是SVC Cluster IP 192.168.2.115,dport是SVC中的port。并且期望是10.0.1.104来回包给10.0.1.91。

image

  1. 如果访问的是SVC的External IP,通过conntrack信息,可以得到src是源端Pod 10.0.1.91,dst是SVC External IP为10.0.3.62中的port。并且期望是10.0.1.104来回包给10.0.1.91。

image

Service nginx1的ExternalTrafficPolicy是Cluster

SVC nginx1 Cluster IP是192.168.2.253,External IP是10.0.3.63,后端是0.0.1.104和10.0.3.58。

  1. 如果访问的是SVC的Cluster IP,通过conntrack信息,可以得到src是源端Pod 10.0.1.91,dst是SVC Cluster IP 192.168.2.253,dport是SVC中的port。并且期望是10.0.1.104来回包给10.0.1.91。

image

  1. 如果访问的是SVC的External IP,通过conntrack信息,可以得到src是源端Pod 10.0.1.91,dst是SVC External IP 10.0.3.63,dport是SVC中的port。并且期望是节点ECS的IP 10.0.1.82来回包给10.0.1.91。

image

综上可以得到src变换了多次,故在Cluster模式下,会存在丢失真实客户端IP的情况。

数据链路转发示意图:

image

  • 会经过calixx网卡,每个非host network的Pod会和calixx网卡形成veth pair,用于和其他Pod或Node进行通信。

  • 整个链路的请求不会经过Pod所分配的ENI,而是直接在OS的Namespace中命中IP规则被转发。

  • 整个请求链路是ECS1 Pod1 eth0 -> Pod1 calixxxx -> Pod2 calixxxx -> ECS1 Pod2 eth0。

  • 访问SVC IP,SVC会在源端Pod eth0和calixxx网卡捕捉到,在目的端Pod的eth0和calixxx时捕捉不到。

  • 在LoadBalancer的SVC模式下,如果ExternalTrafficPolicy为Local,对于Cluster IP来说,会将所有SVC后端Pod都会加到该节点的IPVS转发规则;对于External IP,只会将该节点上的SVC后端Pod才会加到IPVS规则中。

  • 在LoadBalancer的SVC模式下,如果ExternalTrafficPolicy为Cluster,对于Cluster IP或External IP来说,会将所有SVC后端Pod都会加到该节点的IPVS转发规则,同时无法保留src地址。

场景三:访问PodIP,异节点Pod间互访

环境

xxx.10.0.1.82节点上存在centos-67756b6dc8-h5wnp,IP地址10.0.1.91。

xxx.10.0.3.49节点上存在nginx-7d6877d777-lwrfc,IP地址10.0.3.58。

image

内核路由

centos-67756b6dc8-h5wnp,IP地址10.0.1.104,该容器在宿主机表现的PID是2211426,该容器网络命名空间有指向容器eth0的默认路由。

image

centos-67756b6dc8-h5wnp的veth pair的cali44ae9fbceeb,Pod网络空间只有默认路由。

image

在ECS OS内,有指向Pod IP,下一跳为calixxxx的路由,通过前文可以知道calixxx网卡是和每个Pod内的veth1组成的pair,所以Pod内访问SVC的CIDR会有指向veth1的路由,不会走默认的eth0路由。因此calixx网卡在这里的主要作用是用于:

1.节点访问Pod。

2.当节点或者Pod访问SVC的CIDR时,会走ECS OS内核协议栈转换,经过calixxx和eth0访问Pod。对于目的为外部地址,则经过Pod所属的ENI出ECS进入到了VPC。

image

小结

数据链路转发示意图:

image

  • 会经过calixx网卡,每个非host network的Pod会和calixx网卡形成veth pair,用于和其他Pod或Node进行通信。

  • 整个链路的请求不会经过Pod所分配的ENI,而是直接在OS的Namespace中命中IP规则被转发。

  • 出ECS后,根据要访问的Pod和该Pod ENI所属Vswitch,命中VPC路由规则或者直接VSW上的二层转发。

  • 整个请求链路是ECS1 Pod1 eth0-> ECS1 Pod1 calixxxxx-> ECS1 ethx -> vpc route rule(如有) -> ECS2 ethx -> ECS2 Pod2 calixxxxx -> ECS2 Pod2 eth0。

场景四:集群内非SVC后端Pod所在节点访问SVC Cluster IP

环境

xxx.10.0.3.49节点上存在nginx-7d6877d777-h4jtf,IP地址10.0.3.58。

xxx.10.0.1.82节点上存在centos-67756b6dc8-h5wnp,IP地址10.0.1.91。

image

Service1是nginx,Cluster IP是192.168.2.115,External IP是10.0.3.62。

image

Service2是nginx1,Cluster IP是192.168.2.253,External IP是10.0.3.63。

image

内核路由

内核路由部分,请参见场景二:访问Pod IP/SVC IP(Cluster or Local),同节点Pod访问Pod(Pod属于同or不同ENI)场景三:访问PodIP ,异节点Pod间互访小结中详细说明。

源端ECS上的IPVS规则

根据场景二:访问Pod IP/SVC IP(Cluster or Local),同节点Pod访问Pod(Pod属于同or不同ENI)小结中的源端ECS上的IPVS规则,可以得到:无论在哪种SVC模式下,对于Cluster IP来说,会将所有SVC后端Pod都会加到该节点的IPVS转发规则。

小结

Conntrack表信息

Service nginx的ExternalTrafficPolicy是Local

SVC nginx Cluster IP是192.168.2.115,External IP是10.0.3.62,后端是10.0.1.104和10.0.3.58。

xxx.10.0.1.82节点:

image

源端ECS上src是源端Pod 10.0.1.91,dst是SVC Cluster IP 192.168.2.115,dport是SVC中的port,并且期望是10.0.3.58来回包给10.0.1.91。

xxx.10.0.3.49节点:

image

目的端ECS上src是源端Pod 10.0.1.91,dst是Pod的IP 10.0.3.58,dport是Pod的port。并且期望此Pod来回包给10.0.1.91。

Service nginx1的ExternalTrafficPolicy是Cluster

SVC nginx1 ClusterIP是192.168.2.253,External IP是10.0.3.63,后端是10.0.1.104和10.0.3.58。

xxx.10.0.1.82节点:

image

源端ECS上src是源端Pod 10.0.1.91,dst是SVC Cluster IP 192.168.2.115,dport是SVC中的port。并且期望是10.0.3.58来回包给10.0.1.91。

xxx.10.0.3.49节点:

image

目的端ECS上src是源端Pod 10.0.1.91,dst是Pod的IP 10.0.3.58,dport是Pod的port。并且期望此Pod来回包给10.0.1.91。

对于Cluster IP来说,源端ECS会将所有SVC后端Pod都会加到该节点的IPVS转发规则,目的端ECS是捕获不到任何SVC Cluster IP信息的,只能捕获到源端Pod的IP,所以回包的时候会回到源端Pod的附属网卡上。

数据链路转发示意图:

image

  • 会经过calixx网卡,每个非host network的Pod会和calixx网卡形成veth pair,用于和其他Pod或Node进行通信。

  • 整个链路的请求不会经过Pod所分配的ENI,而是直接在OS的Namespace中命中IP规则被转发。

  • 出ECS后,根据要访问的Pod和该Pod ENI所属Vswitch,命中VPC路由规则或者直接VSW上的二层转发。

  • 整个请求链路是:

去方向:

ECS1 Pod1 eth0 -> ECS1 Pod1 calixxxxxx -> ECS1主网卡 eth0 -> vpc route rule(如有)-> ECS2附属网卡ethx -> ECS2 Pod2 calixxxxx -> ECS2 Pod2 eth0。

回方向:

ECS2 Pod2 eth0 -> ECS2 Pod2 calixxxxx -> ECS2附属网卡ethx -> vpc route rule(如有) -> ECS1附属网卡eth1 -> ECS1 Pod1 calixxxxxx -> ECS1 Pod1 eth0。

  • 对于Cluster IP来说,源端ECS会将所有SVC后端Pod都会加到该节点的IPVS转发规则,目的端ECS是捕获不到任何SVC Cluster IP信息的,只能捕获到源端Pod的IP,所以回包的时候会回到源端Pod的附属网卡上。

场景五:Cluster模式,集群内非SVC后端Pod所在节点访问SVC External IP

环境

xxx.10.0.3.49节点上存在nginx-7d6877d777-h4jtf ,IP地址10.0.3.58。

xxx.10.0.1.82节点上存在centos-67756b6dc8-h5wnp,IP地址10.0.1.91。

image

Service2是nginx1 ,Cluster IP是192.168.2.253,External IP是10.0.3.63。

image

内核路由

内核路由部分,请参见场景二:访问Pod IP/SVC IP(Cluster or Local),同节点Pod访问Pod(Pod属于同or不同ENI)场景三:访问PodIP ,异节点Pod间互访小结中详细说明。

源端ECS上的IPVS规则

根据场景二:访问Pod IP/SVC IP(Cluster or Local),同节点Pod访问Pod(Pod属于同or不同ENI)小结中的源端ECS上的IPVS规则,可以得到:ExternalTrafficPolicy为Cluster模式下,对于External IP来说,会将所有SVC后端Pod都会加到该节点的IPVS转发规则。

小结

Conntrack表信息

Service nginx1 的ExternalTrafficPolicy是Cluster

SVC nginx1 Cluster IP是192.168.2.253,External IP是10.0.3.63,后端是10.0.1.104和10.0.3.58。

xxx.10.0.1.82节点:

image

源端ECS上src是源端Pod 10.0.1.91,dst是SVC External IP 10.0.3.63,dport是SVC中的port。并且期望是10.0.3.58来回包给源端ECS的地址10.0.1.82。

xxx.10.0.3.49节点:

image

目的端ECS上src是源端Pod所在的ECS地址10.0.1.82,dst是Pod的IP 10.0.3.58,dport是Pod的port。并且期望此Pod来回包给源端ECS的地址10.0.1.82。

在ExternalTrafficPolicy为Cluster下,对于External IP来说,源端ECS会将所有SVC后端Pod都会加到该节点的IPVS转发规则,目的端ECS是捕获不到任何SVC External IP信息的,只能捕获到源端Pod所在的ECS的IP,所以回包的时候会回到源端Pod所在的ECS的主网卡上,这一点明显和场景四:群内非SVC后端Pod所在节点访问SVC Cluster IP小结中访问CusterIP有很明显区别。

数据链路转发示意图:

image

  • 会经过calixx网卡,每个非host network的Pod会和calixx网卡形成veth pair,用于和其他Pod或Node进行通信。

  • 整个链路的请求不会经过Pod所分配的ENI,而是直接在OS的Namespace中命中IP规则被转发。

  • 出ECS后,根据要访问的Pod和该Pod ENI所属Vswitch,命中VPC路由规则或者直接VSW上的二层转发。

  • 整个请求链路是ECS1 Pod1 eth0 -> ECS1 Pod1 calixxxx -> ECS1主网卡ENI eth0 -> vpc route rule(如有) -> ECS2附属网卡ethx -> ECS2 Pod2 calixxx -> ECS2 Pod2 eth0。

  • 在ExternalTrafficPolicy为Cluster下,对于External IP来说,源端ECS会将所有SVC后端Pod都会加到该节点的IPVS转发规则,目的端ECS是捕获不到任何SVC External IP信息的,只能捕获到源端Pod所在的ECS的IP,所以回包的时候会回到源端Pod所在的ECS的主网卡。

场景六:Local模式,集群内非SVC后端Pod所在节点访问SVC External IP

环境

xxx.10.0.3.49节点上存在nginx-7d6877d777-h4jtf IP地址10.0.3.58。

xxx.10.0.1.82节点上存在centos-67756b6dc8-h5wnp IP地址10.0.1.91。

image

Service1是nginx,Cluster IP是192.168.2.115 External IP是10.0.3.62。

image

内核路由

内核路由部分已经在场景二:访问Pod IP/SVC IP(Cluster or Local),同节点Pod访问Pod(Pod属于同or不同ENI)场景三:访问PodIP ,异节点Pod间互访小结中详细说明,这里不再进行过多阐述。

源端ECS上的IPVS规则

Service的ExternalTrafficPolicy是Local

SVC nginx Cluster IP是192.168.2.115,External IP是10.0.3.62,后端是10.0.1.104和10.0.3.58。

image

xxx.10.0.1.82节点:

对于SVC的External IP,可以得到SVC的后端,无任何转发规则。

image

根据场景二:访问Pod IP/SVC IP(Cluster or Local),同节点Pod访问Pod(Pod属于同or不同ENI)小结中的源端ECS上的IPVS规则,可以得到:ExternalTrafficPolicy为Local模式下,对于External IP来说,只会将本节点上的SVC的后端Pod加到节点上的IPVS转发规则,如果该节点没有SVC后端,则不会有任何可以转发的规则。

小结

Conntrack表信息

Service的ExternalTrafficPolicy是Local

SVC nginx1 Cluster IP是192.168.2.253,External IP是10.0.3.63,后端是10.0.1.104和10.0.3.58。

xxx.10.0.1.82无任何conntrack记录表生成。

image

数据链路转发示意图:

image

  • 会经过calixx网卡,每个非host network的Pod会和calixx网卡形成veth pair,用于和其他Pod或Node进行通信。

  • 整个链路的请求不会经过Pod所分配的ENI,而是直接在OS的Namespace中命中IP规则被转发。

  • 整个请求链路是ECS1 Pod1 eth0 -> ECS1 Pod1 calixxxx -> ECS host空间ipvs/iptables规则,无后端转发ep终止链路。

  • ExternalTrafficPolicy为Local模式下,对于External IP来说,只会将本节点上的SVC的后端Pod加到节点上的IPVS转发规则,如果该节点没有SVC后端,则不会有任何可以转发的规则。

场景七:集群外访问SVC External IP

环境

xxx.10.0.3.49节点上存在nginx-7d6877d777-h4jtf,IP地址10.0.3.58。

xxx.10.0.1.47节点上存在nginx-7d6877d777-kxwdb,IP地址10.0.1.29。

image

Service1是nginx,Cluster IP是192.168.2.115 External IP是10.0.3.62。

image

SLB相关配置

在SLB控制台,lb-xxxxx虚拟服务器组的后端服务器组是两个后端nginx Pod的ENI eni-j6c4qxbpnkgxxxxx和eni-j6c6r7mxxx。

image

从集群外部角度看,SLB的后端虚拟服务器组是SVC的后端Pod所属的两个ENI网卡,内网的IP地址就是Pod的地址。

小结

数据链路转发示意图

image

数据链路:client -> SLB -> Pod ENI + Pod Port -> ECS1 Pod1 eth0。