Terway ENI模式架构设计
Terway ENI模式下,ENI的网络与VPC的网络是相同的网段,ENI网络就是从阿里云的VPC网络中创建和绑定一个弹性网卡到ECS节点上,然后Pod利用这个弹性网卡和其他网络完成互通。但弹性网卡的数量存在限制,详细信息,请参见实例规格族。
Pod所使用的CIDR网段和节点的CIDR是同一个网段。
Pod内部可以得到两张网卡,eth0和veth1。其中,eth0的IP为Pod的IP,此网卡的MAC地址和控制台上ENI的MAC地址可以匹配,表明此网卡为附属ENI网卡,被直接挂载到了Pod的网络命名空间内。
控制台信息如下所示:
Pod内有指向eth0的默认路由,同时还有指向目的网段为192.168.0.0/16、下一跳为veth1网卡的路由。其中,192.168.0.0/16网段为集群的Service网段,表明集群内Pod访问SVC的Cluster IP网段。数据链路会经过veth1网卡到宿主机ECS的OS内进行下一步判断。其他情况下,数据链路会经由eth0直接进入VPC。
容器的网络命名空间中通过ip addr
可以查看veth1@if19的标志位,通过'19'可以在ECS的OS内得到和容器网络命名空间中的veth pair相匹配的另一张网卡。在ECS OS内通过ip addr | grep 19:
可以得到cali38ef34581a9这个虚拟网卡,这个就是在ECS OS侧相对应的veth pair。
到目前为止,容器访问SVC的Cluster IP时,容器和OS数据链路之间的连接已经建立。通过OS Linux Routing,所有目的是Pod CIDR网段的流量都会被转发到Pod对应的calixxx虚拟网卡。因此,ECS OS和Pod的网络命名空间之间已经建立起完整的出入链路配置。
Terway ENI模式容器网络数据链路剖析
针对容器网络特点,可以将Terway ENI模式下的网络链路大致分为以Pod IP对外提供服务和以SVC对外提供服务两个主要场景,进一步细分可以拆分为8个不同的小的SOP场景。
对这8个场景的数据链路进行梳理合并后,可以归纳出以下8类典型场景。
TerwayENI架构下,不同的数据链路访问情况可以总结归纳为8类:
•访问Pod IP,同节点访问Pod。
•访问Pod IP,同节点Pod之间互访。
•访问Pod IP,异节点Pod间互访。
•集群内访问SVC IP(Cluster IP),源端和SVC后端Pod为同一节点。
•集群内访问SVC IP(Cluster IP),源端和SVC后端Pod为不同节点。
•集群内访问SVC IP(External IP),源端和SVC后端Pod为同一节点。
•集群内访问SVC IP(External IP),源端和SVC后端Pod为不同节点。
•集群外访问SVC External IP。
场景一:访问Pod IP,同节点访问Pod
环境
xxx.10.0.0.196节点上存在nginx1-5969d8fc89-9t99h和10.0.0.203。
内核路由
nginx1-5969d8fc89-9t99h IP地址10.0.0.203,该容器在宿主机表现的PID是1094736,该容器网络命名空间有指向容器eth0的默认路由和下一跳为veth1,目的网段为Service的两条路由。
该容器veth1在ECS OS内对应veth pair是cali5068e632525
。
在ECS OS内,有指向Pod IP,下一跳为calixxx的路由,通过前文可以知道calixxx网卡与每个Pod内的veth1配对。所以,Pod内访问SVC的CIDR会有指向veth1的路由,不会走默认的eth0路由。因此,calixxx网卡在这里的主要作用为:
1.节点访问Pod。
2.当节点或者Pod访问SVC的CIDR时,会走ECS OS内核协议栈转换,走到calixxx和veth1访问Pod。
小结
nginx1-5969d8fc89-9t99h netns veth1可以抓到数据包。
nginx1-5969d8fc89-9t99h cali5068e632525可以抓到数据包。
数据链路转发示意图:
数据链路是ECS -> Linux routing -> calicxxx -> Pod net ns veth1,数据链路完成宿主机ns切换至Pod ns。
通过宿主机上的路由切换至Pod所属的veth pair。
该网卡为被分配的Pod独占,无法和其他Pod进行共享。
场景二:访问Pod IP,同节点Pod访问Pod
环境
xxx.10.0.0.196节点上存在两个Pod:centos-59cdc5c9c4-89f8x,IP地址为10.0.0.202,以及nginx1-5969d8fc89-9t99h,IP地址为10.0.0.203。
内核路由
centos-59cdc5c9c4-89f8x IP地址10.0.0.202,该容器在宿主机表现的PID是2314075,该容器网络命名空间有指向容器eth0的默认路由和下一跳为veth1,目的网段为Service的两条路由。
通过上述类似的方法,可以得到nginx1-5969d8fc89-9t99h IP地址为10.0.0.203,该容器在宿主机表现的PID是1094736。
小结
centos-59cdc5c9c4-89f8x netns eth1可以抓到数据包。
nginx1-5969d8fc89-9t99h netns eth1可以抓到数据包。
数据链路转发示意图:
数据链路是Pod1 netns eth1 -> VPC -> Pod2 netns eth2。数据链路不经过宿主机Host Namespace,数据链路会先出ECS,再到VPC,再回到原来的ECS。
在Pod内的net Namespace中,直接命中默认路由规则,从eth0网卡出Pod直接到VPC。这里的eth0则为附属网卡ENI,直接被挂载在了Pod的net ns,走了PCI网卡。
该网卡为被分配的Pod独占,无法和其他Pod进行共享。
场景三:访问Pod IP,异节点Pod访问Pod
环境
xxx.10.0.0.196节点上存在Pod:centos-59cdc5c9c4-89f8x,IP地址为10.0.0.202。
xxx.10.0.2.80节点上存在Pod:nginx-6f545cb57c-jmbrq,IP地址为10.0.2.86。
内核路由
centos-59cdc5c9c4-89f8x IP地址10.0.0.202,该容器在宿主机表现的PID是2314075,该容器网络命名空间有指向容器eth0的默认路由和下一跳为veth1,目的网段为Service的两条路由。
通过上述类似的方法,可以得到nginx-6f545cb57c-jmbrq,IP地址10.0.2.86,该容器在宿主机表现的PID是1083623。
小结
centos-59cdc5c9c4-89f8x netns eth0可以抓到数据包。
nginx-6f545cb57c-jmbrq netns eth0可以抓到数据包。
数据链路转发示意图:
数据链路是ECS1 Pod1 netns eth0 -> VPC -> ECS2 Pod2 netns eth0。数据链路不经过宿主机Host Namespace,数据链路会先出ECS1,到VPC再回到ECS2。
在Pod内的net Namespace中,直接命中默认路由规则,从eth0网卡出Pod直接到VPC。这里的eth0则为附属网卡ENI直接被挂载在了Pod的net ns,走了PCI设备。
该网卡为被分配的Pod独占,无法和其他Pod共享。
场景四:集群内访问SVC IP(Cluster IP),源端和SVC后端Pod为同一节点
环境
xxx.10.0.0.196节点上存在两个Pod:centos-59cdc5c9c4-89f8x,IP地址为10.0.0.202,以及nginx1-5969d8fc89-9t99h,IP地址为10.0.0.203。
Service是nginx1集群内Cluster IP是192.168.41.244,External IP是8.xxx.xxx.179。
内核路由
centos-59cdc5c9c4-89f8x,IP地址10.0.0.202,该容器在宿主机表现的PID是2314075,该容器网络命名空间有指向容器eth0的默认路由和下一跳为veth1,目的网段为Service的两条路由。
该容器eth0在ECS OS内对应的veth pair是cali38ef34581a9。
通过上述类似的方法,可以得到nginx1-5969d8fc89-9t99h,IP地址10.0.0.203,该容器在宿主机表现的PID是1094736,该容器eth0在ECS OS内veth pair是cali5068e632525。
在ECS OS内,有指向Pod IP,下一跳为calixxx的路由。通过前文可以知道calixxx网卡是和每个Pod内的veth1组成的pair,所以,Pod内访问SVC的CIDR会有指向veth1的路由,不会走默认的eth0路由。因此calixx网卡在这里的主要作用为:
1.节点访问Pod。
2.当节点或者Pod访问SVC的CIDR时,会走ECS OS内核协议栈转换,走到calixxx和veth1访问Pod。
小结
centos-59cdc5c9c4-89f8x netns veth1可以抓到数据包。
centos-59cdc5c9c4-89f8x netns cali38ef34581a9可以抓到数据包。
nginx1-5969d8fc89-9t99h netns veth1可以抓到数据包。
nginx1-5969d8fc89-9t99h netns cali5068e632525可以抓到数据包。
数据链路转发示意图:
数据链路是ECS1 Pod1 netns veth1 -> calixxx1 -> calixxx2 -> ECS1 Pod2 netns veth1。
在Pod内的net Namespace中,命中SVC的路由,从veth1网卡出Pod到ECS的Namespace,然后通过Linux Routing转到另一个Pod的calixx网卡。这里的veth1和calixxx是veth pair。
源端Pod所分配的veth,calixxxxx网卡可以捕获到SVC IP和源端Pod IP。SVC IP会在源端ECS Host内命中ipvs/iptables规则,做Nat转换。
目的端Pod所分配的veth,calixxxxx网卡可以捕获calixxxxx网卡默认IP和目的Pod IP。
该网卡为被分配的Pod独占,无法和其他Pod进行共享。
场景五:集群内访问SVC IP(Cluster IP),源端和SVC后端Pod为不同节点
环境
xxx.10.0.0.196节点上存在Pod:centos-59cdc5c9c4-89f8x,IP地址10.0.0.202。
xxx.10.0.2.80节点上存在Pod:nginx-6f545cb57c-jmbrq,IP地址10.0.2.86。
Service是Nginx的Cluster IP,地址为192.168.204.233,External IP是8.xxx.xxx.33。
内核路由
centos-59cdc5c9c4-89f8x,IP地址10.0.0.202,该容器在宿主机表现的PID是2314075,该容器网络命名空间有指向容器eth0的默认路由和下一跳为veth1,目的网段为Service。
该容器eth0在ECS OS内对应的veth pair是cali38ef34581a9。
通过上述类似的方法,可以得到nginx-6f545cb57c-jmbrq,IP地址10.0.2.86,该容器在宿主机上表现的PID是1083623,该Pod网卡ENI被直接挂载到了Pod的网络命名空间内。
小结
数据链路转发示意图:
数据链路是ECS1 Pod1 netns veth1 -> calixxx -> ECS1 eth0 -> VPC -> ECS2 Pod2 netns veth1。
在客户端Pod内的net Namespace中,命中SVC的路由,从veth1网卡出Pod到ECS的Namespace,然后通过Linux Routing转发到客户端ECS eth0网卡,然后进入到VPC转发到目的Pod所属的eth网卡。
源端Pod所分配的veth,calixxxxx网卡可以捕获到SVC IP和源端Pod IP。
SVC IP会在源端ECS Host内命中ipvs/iptables规则,进行Fnat转化。在源端ECS所属的eth0只能捕获到ipvs/iptables规则所分配的目的Pod IP和源ECS IP。
目的Pod内eth0所捕获的IP是源端ECS IP和目的Pod IP(源Pod IP和SVC IP不会体现)。
该网卡为被分配的Pod独占,不和其他Pod进行共享。
场景六:集群内访问SVC IP(External IP),源端和SVC后端Pod为同一节点
环境
xxx.10.0.0.196节点上存在两个Pod:centos-59cdc5c9c4-89f8x,IP地址10.0.0.202,以及nginx1-5969d8fc89-9t99h,IP地址10.0.0.203。
Service是nginx1集群内Cluster IP是192.168.221.163,External IP是10.0.2.89。
内核路由
centos-59cdc5c9c4-89f8x,IP地址10.0.0.202,该容器在宿主机表现的PID是2314075,该容器网络命名空间有指向容器eth0的默认路由和下一跳为veth1,目的网段为Service的Cluster IP的两条路由。
SLB相关配置
虚拟服务器组的后端只有nginx1-5969d8fc89-9t99h的ENI eni-t4n6qvabpxxx。
综上,可以判断如果访问的是SVC的External IP,是走默认路由到eth0,直接出ECS进入到VPC,访问到SLB的实例,再由SLB实例转发到后端ENI上。
小结
数据链路转发示意图:
数据链路是ECS1 Pod1 netns eth0 -> VPC -> SLB -> VPC -> ECS1 Pod2 netns eth0。数据链路不经过宿主机Host Namespace,数据链路会先出ECS1,再到VPC,再回到ECS1。
在Pod内的net Namespace中,直接命中默认路由规则,从eth0网卡出Pod直接到VPC。这里的eth0其实就是附属网卡ENI,直接被挂载在了Pod的net ns,走了PCI设备。
该网卡为被分配的Pod独占,无法和其他Pod共享。
与场景四:集群内访问SVC IP(Cluster IP),源端和SVC后端Pod为同一节点场景可以得到非常大的不同,虽然都是前后端Pod都是部署在同一个ECS访问SVC的IP,但是可以得到如果访问的是SVC的Cluster IP,则数据链路会进入到ECS OS层面;如果访问的是External IP,则不会经过ECS的操作系统,直接出ECS,经过SLB转发到目的Pod上。
场景七:集群内访问SVC IP(External IP),源端和SVC后端Pod为不同节点
环境
xxx.10.0.0.196节点上存在Pod:centos-59cdc5c9c4-89f8x,IP地址10.0.0.202。
xxx.10.0.2.80节点上存在Pod:nginx-6f545cb57c-jmbrq,IP地址10.0.2.86。
Service是Nginx的Cluster IP,地址为192.168.254.141,External IP是10.0.2.90。
内核路由
centos-59cdc5c9c4-89f8x IP地址10.0.0.202,该容器在宿主机表现的PID是2314075,该容器网络命名空间有指向容器eth0的默认路由和下一跳为veth1,目的网段为Service的Cluster IP的两条路由。
SLB相关配置
在SLB控制台,可以得到lb-t4nih6p8w8b1dc7xxx虚拟服务器组的后端只有nginx-6f545cb57c-jmbrq的ENI eni-t4n5kzo553dfaxxx。
综上,可以判断如果访问的是SVC的External IP,经过默认路由到eth0,直接出ECS进入到VPC,访问到SLB的实例,再由SLB实例转发到后端ENI上。
小结
数据链路转发示意图:
数据链路是ECS1 Pod1 netns eth0 -> VPC -> SLB -> VPC -> ECS2 Pod2 netns eth0。数据链路不经过宿主机Host Namespace,数据链路会先出ECS1,到SLB再回到ECS2。
在Pod内的net Namespace中,直接命中默认路由规则,从eth0网卡出Pod直接到VPC。这里的eth0则为附属网卡ENI,直接被挂载在了Pod的net ns,走了PCI设备。
该网卡为被分配的Pod独占,无法和其他Pod进行共享。
与场景五:集群内访问SVC IP(Cluster IP),源端和SVC后端Pod为不同节点场景可以得到非常大的不同,虽然都是前后端Pod都是部署在不同ECS访问SVC的IP,但是可以得到如果访问的是SVC的Cluster IP,则数据链路会进入到ECS OS层面,通过ECS的eth0出ECS,进入到VPC;如果访问的是External IP,则不会经过ECS OS,直接通过Pod所属的附属ENI出ECS,经过SLB转发到目的Pod上。
场景八:集群外访问SVC External IP
环境
xxx.10.0.2.80节点上存在Pod:nginx-6f545cb57c-jmbrq,IP地址10.0.2.86。
xxx.10.0.1.233节点上存在Pod:nginx-6f545cb57c-25k9z,IP地址10.0.1.239。
Service是Nginx的Cluster IP,地址为192.168.254.141,External IP是10.0.2.90。
SLB相关配置
在SLB控制台,可以得到lb-xxx拟服务器组的后端服务器组是两个后端Nginx Pod的ENI eni-t4n5kzo5xxx和eni-t4naaozjxxx。
从集群外部角度看,SLB的后端虚拟服务器组是SVC的后端Pod所属的两个ENI网卡,内网的IP地址就是Pod的地址,没有经过后端Pod所在的ECS的OS层面,直接进入到了OS的协议栈。
小结
数据链路转发示意图:
数据链路:client -> SLB -> Pod ENI + Pod Port。