作者:余凯
本系列文章由余凯执笔创作,联合作者:阿里云容器服务 谢石 对本文亦有贡献
前言
近几年,企业基础设施云原生化的趋势越来越强烈,从最开始的 IaaS 化到现在的微服务化,客户的颗粒度精细化和可观测性的需求更加强烈。容器网络为了满足客户更高性能和更高的密度,也一直在高速的发展和演进中,这必然对客户对云原生网络的可观测性带来了极高的门槛和挑战。为了提高云原生网络的可观测性,同时便于客户和前后线同学增加对业务链路的可读性,ACK 产研和AES联合共建,合作开发 ack net-exporter 和云原生网络数据面可观测性系列,帮助客户和前后线同学了解云原生网络架构体系,简化对云原生网络的可观测性的门槛,优化客户运维和售后同学处理疑难问题的体验 ,提高云原生网络的链路的稳定性。
鸟瞰容器网络,整个容器网络可以分为三个部分:Pod 网段,Service 网段和 Node 网段。这三个网络要实现互联互通和访问控制,那么实现的技术原理是什么?整个链路又是什么,限制又是什么呢?Flannel, Terway有啥区别?不同模式下网络性能如何?这些,需要客户在下搭建容器之前,就要依据自己的业务场景进行选择,而搭建完毕后,相关的架构又是无法转变,所以客户需要对每种架构特点要有充分了解。比如下图是个简图,Pod 网络既要实现同一个 ECS 的 Pod 间的网络互通和控制,又要实现不同 ECS Pod 间的访问, Pod 访问 SVC 的后端可能在同一个 ECS 也可能是其他 ECS,这些在不同模式下,数据链转发模式是不同的,从业务侧表现结果也是不一样的。
本文是[全景剖析容器网络数据链路]第二部分,主要介绍 Kubernetes Terway ENI 模式下,数据面链路的转转发链路,一是通过了解不同场景下的数据面转发链路,从而探知客户在不同的场景下访问结果表现的原因,帮助客户进一步优化业务架构;另一方面,通过深入了解转发链路,从而在遇到容器网络抖动时候,客户运维以及阿里云同学可以知道在哪些链路点进行部署观测手动,从而进一步定界问题方向和原因。
系列一:
系列三:
全景剖析阿里云容器网络数据链路(三)—— Terway ENIIP
系列四:
全景剖析阿里云容器网络数据链路(四)—— Terway IPVLAN+EBPF
系列五:
全景剖析阿里云容器网络数据链路(五)—— Terway ENI-Trunking
系列六:
全景剖析阿里云容器网络数据链路(六)—— ASM Istio******
Terway ENI 模式架构设计
Terway ENI 模式下,ENI 的网络都是和 VPC 同样的网段,ENI 网络就是从 Aliyun 的 VPC 网络中创建和绑定一个**弹性网卡 [ 1] 到 ECS 节点上, 然后 Pod 利用这个弹性网卡和别的网络互通,这里需要关注的是弹性网卡的数量是有限制的,具体的根据实例类型有不同的配额 [ 2] **。
[1] 弹性网卡
https://help.aliyun.com/document_detail/58496.html
[2] 实例类型有不同的配额
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 的 clusterIP 网段,数据链路会经过 veth1 网卡到宿主机 ECS 的 OS 内进行下一步判断,其他情况是走 eth0 直接进入到 VPC
如上图所示,我们可以容器的网络命名空间中通过 ip addr 看到一个 veth1@if19 的标志位,其中 ‘19' 这个将会协助我们在 ECS 的 OS 内找到找到和容器网络命名空间中的 veth pair 相对一个。在 ECS OS 内我们通过 ip addr | grep 19: 可以找到 cali38ef34581a9 这个虚拟网卡,这个就是 veth pair 在 ECS OS 侧相对的那一个。
到目前为止,容器访问 SVC 的 ClusterIP 时,容器和 OS 数据链路已经建立链接了,那么 ECS OS 内对于数据流量是怎么判断去哪个容器呢?通过 OS Linux Routing 我们可以看到,所有目的是 Pod CIDR 网段的流量都会被转发到 Pod 对应的 calico 虚拟往卡上,到这里为止,ECS OS 和 Pod 的网络命名空间已经建立好完整的出入链路配置了。
Terway ENI 模式容器网络数据链路剖析
针对容器网络特点,我们可以将 Terway ENI 模式下的网络链路大体分为以 Pod IP 对外提供服务和以 SVC 对外提供服务两个大的 SOP 场景,进一步细分可以拆分到 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
环境
ap-southeast-1.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 内对应v eth pair 是 cali5068e632525
在 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。
小结:可以访问到目的端
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
环境
ap-southeast-1.10.0.0.196 节点上存在两个 pod:centos-59cdc5c9c4-89f8x IP地址 10.0.0.202 和 nginx1-5969d8fc89-9t99h 和 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
环境
ap-southeast-1.10.0.0.196 节点上存在 pod:centos-59cdc5c9c4-89f8x IP地址 10.0.0.202
ap-southeast-1.10.0.2.80 节点上存在 pod:nginx-6f545cb57c-jmbrq 和 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,到 AVS 再回到 ECS2。
-
在 pod 内的 net namespace 中,直接命中 默认路有规则,从 eth0 网卡出 pod直接到 VPC。这里的 eth0 其实就是附属网卡 ENI,直接被挂载在了 pod 的 net ns, 走了 PCI 设备
-
该网卡为被分配的 pod 独占, 无法和其他 pod 进行共享
-
数据链路经过两次协议栈
场景四:集群内访问 SVC IP (Cluster IP),源端和 SVC 后端 Pod 为同一节点
环境
ap-southeast-1.10.0.0.196 节点上存在两个 pod:centos-59cdc5c9c4-89f8x IP地址 10.0.0.202 和 nginx1-5969d8fc89-9t99h 和 10.0.0.203
Service是 nginx1 集群内 clusterIP 是192.168.41.244, external IP 是 8.219.175.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,下一跳为 calixxxx 的路由,通过前文可以知道 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 -> ECS2 pod2 netns veth1。
-
在 pod 内的 net namespace中,命中 svc 的路由,从 veth1 网卡出 pod 到 ECS的 namespace,然后通过 linux routing 转到另一个pod 的 calixx 网卡。这里的 veth1 和 calixxx 是 veth pair
-
源端 pod 所分配的 veth,calicoxxx 网卡可以捕获到 svc IP 和源端 pod IP。SVC IP 会在源端 ECS host 内命中 ipvs/iptables 规则,做了 nat 转化。
-
目的段 pod 所分配的 veth,calicoxxx 网卡可以捕获 calicoxxx 网卡默认 ip 和目的 pod IP
-
该网卡为被分配的 pod 独占, 无法和其他 pod 进行共享
-
数据链路经过三次协议栈:Pod1, ECS OS 和 Pod2
场景五:集群内访问 SVC IP (Cluster IP),源端和 SVC 后端 Pod 为不同节点
环境
ap-southeast-1.10.0.0.196 节点上存在 pod:centos-59cdc5c9c4-89f8x IP地址 10.0.0.202
ap-southeast-1.10.0.2.80 节点上存在 pod:nginx-6f545cb57c-jmbrq 和 10.0.2.86
Service是 nginx 集群内 clusterIP 是192.168.204.233, external IP 是 8.219.199.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 -> cali38ef34581a9 -> ECS1 eth0 -> VPC -> ECS2 pod2 netns veth1
-
在客户端 pod 内的 net namespace 中,命中 svc 的路由,从 veth1 网卡出 pod 到 ECS 的 namespace,然后通过 linux routing 转到客户端 ECS eth0 网卡, 然后进入到 vpc 转发到目的 Pod 所属的 eth 网卡
-
源端 pod所分配的 veth,calicoxxx 网卡可以捕获到 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 进行共享
-
数据链路经过三次协议栈:Pod1, ECS1 OS 和 Pod2
场景六:集群内访问 SVC IP (External IP),源端和 SVC 后端 Pod 为同一节点
环境
ap-southeast-1.10.0.0.196 节点上存在两个 pod:centos-59cdc5c9c4-89f8x IP地址 10.0.0.202 和 nginx1-5969d8fc89-9t99h 和 10.0.0.203
Service 是 nginx1 集群内clusterIP是192.168.221.163, external IP 是 10.0.2.89
内核路由
centos-59cdc5c9c4-89f8x IP地址 10.0.0.202 ,该容器在宿主机表现的 PID 是2314075,该容器网络命名空间有指向容器 eth0 的默认路由和下一跳为 veth1, 目的网段为 service 的 ClusterIP 的两条路由
SLB 相关配置
在 SLB 控制台,可以看到虚拟服务器组的后端只有 nginx1-5969d8fc89-9t99h 的ENI eni-t4n6qvabpwi24w0dcy55
综上,可以判断如果访问的是 SVC 的 External IP, 是走默认路由 eth0,直接出 ECS 进入到 avs ,访问到 SLB 的实例,再由 SLB 实例转发到后端 eni 上
小结:可以访问到目的端
数据链路转发示意图
- 数据链路是 ECS1 pod1 netns eth0 -> VPC -> SLB -> VPC -> ECS1 pod2 netns eth0。数据链路不经过宿主机 host namespace,数据链路会先出 ECS1,到 AVS 再回到 ECS1。
- 在 pod 内的 net namespace 中,直接命中默认路有规则,从 eth0 网卡出 pod 直接到 VPC。这里的 eth0 其实就是附属网卡ENI,直接被挂载在了 pod 的 net ns, 走了 PCI 设备
- 该网卡为被分配的 pod 独占, 无法和其他 pod 进行共享
- 与 2.4 场景可以看到非常大的不同,虽然都是 前后端 Pod 都是部署在同一个 ECS 访问 SVC 的 IP,但是可以看到如果访问的是 SVC 的 ClusterIP,则数据链路会进入到 ECS OS 层面,会经过三次协议栈;如果访问的是 External IP,则不会经过 ECS OS,直接出 ECS,经过 SLB 转发到目的 Pod 上,只经过两次协议栈(Pod1 和Pod2)。
场景七:集群内访问 SVC IP(External IP),源端和 SVC 后端 Pod 为不同节点
环境
ap-southeast-1.10.0.0.196 节点上存在 pod:centos-59cdc5c9c4-89f8x IP地址 10.0.0.202
ap-southeast-1.10.0.2.80 节点上存在 pod:nginx-6f545cb57c-jmbrq 和 10.0.2.86
Service是 nginx 集群内 clusterIP 是 192.168.254.141, external IP 是 10.0.2.90
内核路由
centos-59cdc5c9c4-89f8x IP地址 10.0.0.202 ,该容器在宿主机表现的 PID 是 2314075,该容器网络命名空间有指向容器 eth0 的默认路由和下一跳为 veth1, 目的网段为 service 的 ClusterIP 的两条路由
SLB 相关配置
在 SLB 控制台,可以看到 lb-t4nih6p8w8b1dc7p587j9 虚拟服务器组的后端只有nginx-6f545cb57c-jmbrq的 ENI eni-t4n5kzo553dfak2sp68j
综上,可以判断如果访问的是 SVC 的 External IP, 是走默认路由 eth0,直接出 ECS 进入到 avs ,访问到 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 进行共享
-
与 2.5 场景可以看到非常大的不同,虽然都是前后端 Pod 都是部署在不同 ECS 访问 SVC 的 IP,但是可以看到如果访问的是 SVC 的 ClusterIP,则数据链路会进入到 ECS OS 层面,通过 ECS 的 eth0 出 ECS,进入到 AVS,会经过三次协议栈;如果访问的是 External IP,则不会经过 ECS OS,直接通过 Pod 所属的的附属 ENI 出 ECS,经过 SLB 转发到目的 Pod 上,只经过两次协议栈(Pod1 和Pod2)。
场景八:集群外访问 SVC External IP
环境
ap-southeast-1.10.0.2.80 节点上存在 pod:nginx-6f545cb57c-jmbrq 和 10.0.2.86
ap-southeast-1.10.0.1.233 节点上存在 pod:nginx-6f545cb57c-25k9z 和 10.0.1.239
Service 是 nginx 集群内 clusterIP 是 192.168.254.141, external IP 是 10.0.2.90
SLB 相关配置
在 SLB 控制台,可以看到 lb-t4nih6p8w8b1dc7p587j9 虚拟服务器组的后端服务器组是两个后端nginx pod 的的ENI eni-t4n5kzo553dfak2sp68j 和eni-t4naaozjxiehvmg2lwfo
从集群外部角度看,SLB 的后端虚拟服务器组是 SVC 的后端 Pod 所属的两个 ENI 网卡,内网的 IP 地址就是 Pod 的地址,没有经过后端 Pod 所在的 ECS 的 OS 层面,直接进入到了 OS 的的协议栈
小结:可以访问到目的端
数据链路转发示意图
- 数据链路:client -> SLB -> Pod ENI + Pod Port -> ECS1 Pod1 eth0
- 数据链路要经过一次内核协议栈,是 Pod1 协议栈
总结
本篇文章主要聚焦 ACK 在 Terway ENI 模式下,不同 SOP 场景下的数据链路转发路径。伴随着客户对性能的极致追求的需求,在 Terway ENI 模式下,一共可以分为 8 个 SOP 场景,并对这八个场景的转发链路,技术实现原理,云产品配置等一一梳理并总结,这对我们遇到 Terway ENI 架构下的链路抖动、最优化配置,链路原理等提供了初步指引方向。在 Terway ENI 模式下,ENI 是以 PCI 方式直接挂载到 Pod 的命名空间内,这就以为 ENI 属于被分配的 Pod 独享,而 ECS 所能部署的 Pod 数量取决于 ECS 所能挂载ENI网卡数量的限制,而这个限制和 ECS 的实例规格类型有关,比如神龙ecs.ebmg7.32xlarge,128C 512GB也只支持最多 32 个 ENI,这往往会造成资源的浪费和部署密度的降低,为了解决这个资源效率问题,ACK 带来了 Terway ENIIP 的方式,来实现ENI网卡可以被多个Pod所共享,这大大增加了单个 ECS 上的 Pod 数量 quota,提升了部署密度,这也是目前线上集群采用最多的架构。下一系列我们将进入到 Terway ENIIP 模式的全景解析——《ACK 全景剖析阿里云容器网络数据链路(三)—— Terway ENIIP》。
点击此处查看阿里云容器服务