全景剖析阿里云容器网络数据链路(一):Flannel

作者:余凯

本系列文章由余凯执笔创作,联合作者:阿里云云原生应用平台 谢石 对本文亦有贡献

前言

近几年,企业基础设施云原生化的趋势越来越强烈,从最开始的 IaaS 化到现在的微服务化,客户的颗粒度精细化和可观测性的需求更加强烈。容器网络为了满足客户更高性能和更高的密度,也一直在高速的发展和演进中,这必然对客户对云原生网络的可观测性带来了极高的门槛和挑战。为了提高云原生网络的可观测性,同时便于客户和前后线同学增加对业务链路的可读性,ACK 产研和 AES 联合共建,合作开发 ack net-exporter 和云原生网络数据面可观测性系列,帮助客户和前后线同学了解云原生网络架构体系,简化对云原生网络的可观测性的门槛,优化客户运维和售后同学处理疑难问题的体验 ,提高云原生网络的链路的稳定性。

鸟瞰容器网络,整个容器网络可以分为三个部分:Pod 网段,Service 网段和 Node 网段。这三个网络要实现互联互通和访问控制,那么实现的技术原理是什么?整个链路又是什么,限制又是什么呢?Flannel, Terway 有啥区别?不同模式下网络性能如何?这些,需要客户在下搭建容器之前,就要依据自己的业务场景进行选择,而搭建完毕后,相关的架构又是无法转变,所以客户需要对每种架构特点要有充分了解。比如下图是个简图,Pod 网络既要实现同一个ECS的Pod间的网络互通和控制,又要实现不同 ECS Pod 间的访问, Pod 访问 SVC 的后端可能在同一个 ECS 也可能是其他 ECS,这些在不同模式下,数据链转发模式是不同的,从业务侧表现结果也是不一样的。

全景剖析阿里云容器网络数据链路(一):Flannel_第1张图片

本文是[全景剖析容器网络数据链路]第一部分,主要介绍 Kubernetes Flannel 模式下,数据面链路的转转发链路,一是通过了解不同场景下的数据面转发链路,从而探知客户在不同的场景下访问结果表现的原因,帮助客户进一步优化业务架构;另一方面,通过深入了解转发链路,从而在遇到容器网络抖动时候,客户运维以及阿里云同学可以知道在哪些链路点进行部署观测手动,从而进一步定界问题方向和原因。

系列二:

全景剖析阿里云容器网络数据链路(二):Terway ENI

系列三:

全景剖析阿里云容器网络数据链路(三):Terway ENIIP

系列四:

全景剖析阿里云容器网络数据链路(四):Terway IPVLAN+EBPF

系列五:

全景剖析阿里云容器网络数据链路(五):Terway ENI-Trunking

系列六:

全景剖析阿里云容器网络数据链路(六):ASM Istio

Flannel 模式架构设计

Flannel 模式下,ECS 只有一个主网卡 ENI,无其他附属网卡,ECS 和节点上的 Pod 与外部通信都需要通过主网卡进行。ACK Flannel 会在每个节点创建 cni0 虚拟网卡作为 Pod 网络和 ECS 的主网卡 eth0 之间的桥梁。

全景剖析阿里云容器网络数据链路(一):Flannel_第2张图片

全景剖析阿里云容器网络数据链路(一):Flannel_第3张图片

集群的每个节点会起一个 flannel agent,并且会给每个节点预分配一个 Pod CIDR,这个 Pod CIDR 是ACK集群的 Pod CIDR 的子集。

全景剖析阿里云容器网络数据链路(一):Flannel_第4张图片

容器的网络命名空间内会有一个 eth0 的虚拟网卡,同时存在下一跳指向该网卡的路由,该网卡会作为容器和宿主内核进行数据交换的出入口。容器和宿主机之间的数据链路是通过 veth pair 进行交换的,现在我们已经找到 veth pair 其中一个,如何去找另一个 veth 呢?

 title=

全景剖析阿里云容器网络数据链路(一):Flannel_第5张图片

如上图所示,我们可以容器的网络命名空间中通过 p addr 看到一个 eth0@if81 的标志位,其中 ‘81' 这个将会协助我们在 ECS 的 OS 内找到找到和容器网络命名空间中的 veth pair 相对一个。在 ECS OS 内我们通过 ip addr | grep 81: 可以找到 vethd7e7c6fd 这个虚拟网卡,这个就是 veth pair 在 ECS OS 侧相对的那一个。

 title=

到目前为止容器内和 OS 数据链路已经建立链接了,那么 ECS OS 内对于数据流量是怎么判断去哪个容器呢?通过 OS Linux Routing 我们可以看到,所有目的是 Pod CIDR 网段的流量都会被转发到 cni0 这张虚拟网卡,那么 cni0 是通过 bridge 方式将不同目的的数据链路指向到不同的 vethxxx。到这里为止,ECS OS 和 Pod 的网络命名空间已经建立好完整的出入链路配置了。

全景剖析阿里云容器网络数据链路(一):Flannel_第6张图片

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

针对容器网络特点,我们可以将 Flannel 模式下的网络链路大体分为以 Pod IP 对外提供服务和以 SVC 对外提供服务两个大的 SOP 场景,进一步细分可以拆分到 10 个不同的小的 SOP 场景。

全景剖析阿里云容器网络数据链路(一):Flannel_第7张图片

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

  • Client 和服务端 Pod 部署于同一个 ECS
  • Client 和服务端 Pod 部署于不同 ECS
  • 访问 SVC External IP, ExternalTrafficPolicy 为 Cluster 时,Client 和服务端 Pod 部署于不同ECS,其中client为集群外
  • 访问 SVC External IP, ExternalTrafficPolicy 为 Local 时, Client 和服务端 Pod 部署于不同 ECS,其中client为集群内
  • 访问 SVC External IP, ExternalTrafficPolicy 为 Local 时, Client 和服务端 Pod 部署于不同 ECS,其中 client 为集群外

场景一:Client和服务端Pod部署于同一个ECS

此场景包含下面几个子场景,数据链路可以归纳为一种:

  1. 以 Pod IP 对外提供服务,Client 和 Pod 部署于同一个节点;
  2. 以 SVC ClusterIP 对外提供服务,Client 和 SVC 后端 Pod 部署于同一节点;
  3. 以 SVC ExternalIP 对外提供服务,ExternalTrafficPolicy 为 Cluster/Local 情况下,Client 和 SVC 后端 Pod 部署于同一节点

环境

 title=

ap-southeast-1.10.0.0.180 节点上存在两个pod:centos-67756b6dc8-rmmxt  IP地址172.23.96.23  和 nginx-7d6877d777-6jkfg 和172.23.96.24

内核路由

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

 title=

 title=

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

全景剖析阿里云容器网络数据链路(一):Flannel_第8张图片

 title=

通过上述类似的办法,可以找到nginx-7d6877d777-6jkfg  IP地址172.23.96.24,该容器在宿主机表现的 PID 是2981608,该容器 eth0 在 ECS OS 内对应veth pair是vethd3fc7ff4

全景剖析阿里云容器网络数据链路(一):Flannel_第9张图片

在 ECS OS 内,有指向 Pod CIDR,下一跳为 cni0 的路由,以及 cni0 中有两个容器的vethxxx 网桥信息

全景剖析阿里云容器网络数据链路(一):Flannel_第10张图片

全景剖析阿里云容器网络数据链路(一):Flannel_第11张图片

小结:可以访问到目的端

全景剖析阿里云容器网络数据链路(一):Flannel_第12张图片

▲数据链路转发示意图

全景剖析阿里云容器网络数据链路(一):Flannel_第13张图片

▲内核协议栈示意图

  • 数据链路:ECS1 Pod1 eth0 ->  vethxxx1 -> cni0 -> vethxxxx2 -> ECS1 Pod2 eth0
  • 数据链路要经过三次内核协议栈,分别是 Pod1 协议栈, ECS OS 协议栈 和 Pod2 协议栈

场景二:Client 和服务端 Pod 部署于不同 ECS

此场景包含下面几个子场景,数据链路可以归纳为一种:

  1. 以 Pod IP 对外提供服务,Client 和 Pod 部署于不同节点;
  2. 以 SVC ClusterIP 对外提供服务,Client和SVC 后端Pod部署于不同节点;
  3. 以 SVC ExternalIP 对外提供服务,ExternalTrafficPolicy 为 Cluster 情况下,集群内 Client 和 SVC 后端 Pod 部署于不同节点;

环境

 title=

ap-southeast-1.10.0.0.180 节点上存在两个 pod:centos-67756b6dc8-rmmxt  IP地址172.23.96.23  和 nginx1-76c99b49df-7plsr  IP 地址172.23.96.163

Service nginx1 的 ExternalTrafficPlicy 为 Cluster

全景剖析阿里云容器网络数据链路(一):Flannel_第14张图片

内核路由

Pod 网络空间和 ECS OS 网络空间的数据交换在 2.1 场景一中已经做了详细描述,此处不再果断篇幅描述。

源端 Pod 所在 ECS 的 IPVS 规则

可以看到,源端数据链路访问 svc 的clusterip 192.168.13.23 时,如果链路到达 ECS 的OS 内,会命中 ipvs 规则,被解析到 svc 的后端 endpoint 之一(本实例中只有一个 pod,所以 endpoint 只有一个)

 title=

小结:可以成功访问到目的端

全景剖析阿里云容器网络数据链路(一):Flannel_第15张图片

▲数据链路转发示意图

VPC 路由表会自动配置目的地址是 pod CIDR, 下一跳为 POD 网段所归属的 ECS 的自定义路由条目,该规则由 ACK 管控测通过 openapi 调用 VPC 去配置,无需手动配置和删除

全景剖析阿里云容器网络数据链路(一):Flannel_第16张图片

全景剖析阿里云容器网络数据链路(一):Flannel_第17张图片

▲内核协议栈示意图

Conntack 表信息(访问 SVC 情况)

Node1:

src是源pod IP,dst是svc的ClusterIP,并且期望是由svc的其中一个endpoint 172.23.96.163 来回消息给源端 pod

 title=

Node2:

目的 pod 所在 ECS 上 conntrack 表记录是由源端 pod 访问目的 pod,不会记录 svc 的clusterip 地址

 title=

  • 数据链路:ECS1 Pod1 eth0 ->  vethxxx1 -> cni0 -> ECS 1 eth0 ->  VPC -> ECS2 eth0 -> cni0 ->  vethxxxx2 -> ECS2 Pod2 eth0
  • 数据链路要经过四次内核协议栈,分别是 Pod1 协议栈, ECS1 OS 协议栈 , ECS2 OS 协议栈和 Pod2 协议栈
  • VPC 路由表会自动配置目的地址是 pod CIDR, 下一跳为 POD 网段所归属的 ECS 的自定义路由条目,该规则由 ACK 管控测通过 openapi 调用 VPC 去配置,无需手动配置和删除
  • 如果访问的 SVC 的 cluster IP,或者是 Cluster 模式下,访问 SVC 的 externalIP,数据链路通过veth pair进到 ECS OS 内后,会命中相应的 IPVS 规则,并根据负载规则,选择IPVS的某一个后端,进而打到其中的一个 SVC 的后端 endpoint,SVC 的 IP 只会再 PoD 的 eth0 , veth pair vethxxx 被捕捉到,其他链路环节不会捕捉到 svc 的 IP

场景三:ExternalTrafficPolicy 为 Local时,Client 和服务端 Pod 部署于集群内不同 ECS

此场景包含下面几个子场景,数据链路可以归纳为一种:

1.以SVC ExternalIP对外提供服务,ExternalTrafficPolicy 为 Local情况下,集群内 Client 和 SVC 后端 Pod 部署于不同节点;

环境

 title=

ap-southeast-1.10.0.0.180 节点上存在两个pod:centos-67756b6dc8-rmmxt  IP地址172.23.96.23  和 nginx1-76c99b49df-7plsr  IP 地址172.23.96.163

Service nginx1 ExternalTrafficPolicy 为 Local

全景剖析阿里云容器网络数据链路(一):Flannel_第18张图片

内核路由

Pod 网络空间和 ECS OS 网络空间的数据交换在 2.1 场景一中已经做了详细描述,此处不再果断篇幅描述。

源端 Pod 所在 ECS 的 IPVS 规则

可以看到,源端数据链路访问 svc 的 externalip  8.219.164.113 时,如果链路到达 ECS 的OS内,会命中ipvs规则,但是我们可以看到EcternalIP  并没有相关的后端 endpoint,链路达到 OS 后,会命中 IPVS 规则,但是没有后端 pod,所以会出现 connection refused

 title=

小结:不可以访问到目的端,此时会访问失败,Connection refused

全景剖析阿里云容器网络数据链路(一):Flannel_第19张图片

▲数据链路转发示意图

全景剖析阿里云容器网络数据链路(一):Flannel_第20张图片

▲内核协议栈示意图

  • 数据链路:ECS1 Pod1 eth0 ->  vethxxx1 ->
  • 数据链路要经过一次半内核协议栈,分别是 Pod1 协议栈,半个 ECS1 OS 协议栈
  • 如果访问的 SVC 的 External IP,或者是 Local 模式下,访问 SVC 的 externalIP,数据链路通过 veth pair 进到 ECS OS内后,会命中相应的 IPVS 规则,但是由于 Local 模式,External IP的 IPVS 为空,所以命中规则但是无转发后端,整个链路会在 ipvs 终止,访问失败。所以建议集群内采用 clusterip 访问,这也是 k8s 官方推荐的最佳实践。

场景四:ExternalTrafficPolicy 为 Local 时,Client 来自于集群外

此场景包含下面几个子场景,数据链路可以归纳为一种:A.访问SVC External IP, ExternalTrafficPolicy 为 Local时, Client 和服务端 Pod 部署于不同 ECS,其中 client 为集群外

环境

 title=

Deployment为nginx1, 分别为三个pod nginx1-76c99b49df-4zsdj和nginx1-76c99b49df-7plsr 部署在 ap-southeast-1.10.0.1.206 ECS上,最后一个pod nginx1-76c99b49df-s6z79 部署在其他节点 ap-southeast-1.10.0.1.216 上

Service nginx1 的ExternalTrafficPlicy 为 Local

全景剖析阿里云容器网络数据链路(一):Flannel_第21张图片

内核路由

Pod 网络空间和 ECS OS 网络空间的数据交换在 2.1 场景一中已经做了详细描述,此处不再果断篇幅描述。

SLB 相关配置

从 SLB 控制台,可以看到 SLB 后端的虚拟服务器组中只有两个 ECS 节点ap-southeast-1.10.0.1.216 和 ap-southeast-1.10.0.1.206。集群内的其他节点 ,比如 ap-southeast-1.10.0.0.180 并未被加到 SLB 的后端虚拟服务器组中。虚拟服务器组的 IP 为 ECS 的 IP,端口为 service 里面的 nodeport 端口 32580.

 title=

故 ExternalTrafficPolicy 为 Local 模式下,只有有 Service 后端 pod 所在的 ECS 节点才会被加入到 SLB 的后端虚拟服务器组中,参与 SLB 的流量转发,集群内的其他节点不参与 SLB 的转发

SLB 虚拟服务器组 ECS 的 IPVS 规则

从SLB的虚拟服务器组中的两个 ECS 可以看到,对于 nodeip+nodeport 的 ipvs转发规则是不同。ExternalTrafficPolicy 为 Local 模式下,只有该节点上的护短 pod 才会被加到该节点的 ipvs 转发规则中,其他节点上的后端 pod 不会加进来,这样保证了被 SLB 转发的链路,只会被转到该节点上的 pod,不会转发到其他节点上。

node1:ap-southeast-1.10.0.1.206

 title=

node1:ap-southeast-1.10.0.1.216

 title=

小结:可以访问到目的端

全景剖析阿里云容器网络数据链路(一):Flannel_第22张图片

▲数据链路转发示意图

该图示意了只有后端 pod 所在 ECS 才会加到 SLB 后端中,从集群外部访问 SVC 的externalIP(SLB IP)的情况,可见数据链路只会被转发到虚拟服务器组中的 ECS,不会再被转发到集群内其他节点上。

全景剖析阿里云容器网络数据链路(一):Flannel_第23张图片

▲内核协议栈示意图

Conntack 表信息

Node:

src 是集群外部客户端IP,dst 是节点 IP,dport 是 SVC 中的 nodeport。并且期望是由该 ECS 上的 pod 172.23.96.82 来回包给源端

 title=

  • 数据链路:client ->  SLB  -> ECS eth0 + ECS nodeport  ->  cni0 ->  vethxxxxx -> ECS1 Pod1 eth0
  • 数据链路要经过两次内核协议栈,分别是 Pod1 协议栈, ECS1 OS 协议栈
  • ExternalTrafficPolicy 为 Local 模式下,只有有 Service 后端 pod 所在的 ECS 节点才会被加入到SLB的后端虚拟服务器组中,参与 SLB 的流量转发,集群内的其他节点不参与 SLB 的转发

场景五:ExternalTrafficPolicy 为 Cluster 时,Client 来自于集群外

此场景包含下面几个子场景,数据链路可以归纳为一种:

1.访问 SVCExternal IP, ExternalTrafficPolicy 为 Cluster 时, Client 和服务端 Pod部署于不同 ECS,其中 client 为集群外

环境

 title=

Deployment为nginx1, 分别为三个pod nginx1-76c99b49df-4zsdj和nginx1-76c99b49df-7plsr 部署在 ap-southeast-1.10.0.1.206 ECS上,最后一个pod nginx1-76c99b49df-s6z79 部署在其他节点 ap-southeast-1.10.0.1.216 上

Service nginx2 的 ExternalTrafficPlicy 为 Cluster

全景剖析阿里云容器网络数据链路(一):Flannel_第24张图片

内核路由

Pod 网络空间和 ECS OS 网络空间的数据交换在 2.1 场景一中已经做了详细描述,此处不再果断篇幅描述。

SLB 相关配置

从SLB 控制台,集群内所有节点ap-southeast-1.10.0.0.180、ap-southeast-1.10.0.1.216 和 ap-southeast-1.10.0.1.206 都被加到SLB的虚拟服务器组中。其中 虚拟服务器组的 IP 为 ECS 的 IP,端口为 service 里面的 nodeport 端口 30875.

全景剖析阿里云容器网络数据链路(一):Flannel_第25张图片

故 ExternalTrafficPolicy 为 CLuster 模式下,集群内所有的 ECS 节点都会被加入到 SLB 的后端虚拟服务器组中,参与 SLB 的流量转发。

SLB 虚拟服务器组 ECS 的 IPVS 规则

从SLB的虚拟服务器组中的可以看到,对于 nodeip+nodeport 的 ipvs 转发规则是一致的。ExternalTrafficPolicy为 CLuster 模式下,所有的 service 后端 pod 都会被加到所有节点的 ipvs 的转发规则中,即使是该节点有后端 pod,流量也不一定会被转发到该节点上 pod,可能会被转发到其他节点上的后端 pod。

node1:ap-southeast-1.10.0.1.206 (该节点有后端pod)

 title=

node1:ap-southeast-1.10.0.1.216 (该节点有后端pod)

 title=

node3:     ap-southeast-1.10.0.0.180 (该节无后端pod)

 title=

小结:可以访问到目的端

全景剖析阿里云容器网络数据链路(一):Flannel_第26张图片

▲数据链路转发示意图

该图示意了集群内所有 ECS 都会被加到 SLB 后端中,从集群外部访问 SVC 的externalIP(SLB IP)的情况,数据流量可能会被转发到其他节点上

内核协议栈示意图:

内核协议栈示意图已经在 2.4 场景一中已经做了详细描述,此处不再果断篇幅描述。

Conntack 表信息

链路1:

ap-southeast-1.10.0.0.180:

此时数据链路对应示意图中的链路1,可以看到数据链路被转到 ap-southeast-1.10.0.0.180 节点,该节点上并没有 service 的后端 pod,通过 conntrack 信息,可以看到

src 是集群外部客户端 IP,dst 是节点 IP,dport 是 SVC 中的 nodeport。并且期望是172.23.96.163 来回包给 10.0.0.180 。通过前述信息,可以得知172.23.96.163 是nginx1-76c99b49df-7plsr pod,部署在 ap-southeast-1.10.0.1.206

 title=

ap-southeast-1.10.0.1.206:

通过此节点conntrack 表,可以看到src是 node  ap-southeast-1.10.0.0.180,dst 是 172.23.96.163的80 端口,回包也是直接回给 node  ap-southeast-1.10.0.0.180.

 title=

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

链路2:

src 是集群外部客户端 IP,dst 是节点IP,dport 是 SVC 中的 nodeport。并且期望是由该 ECS 上的 pod 172.23.96.82 来回包给 172.23.96.65,此地址是 SLB 集群中的一个地址

 title=

  • 数据链路:情景一:client ->  SLB  -> ECS eth0 + ECS nodeport  ->  cni0 ->  vethxxxxx -> ECS1 Pod1 eth0情景二:client ->  SLB  -> ECS1 eth0 + ECS1 nodeport  -> VPC Routing ->  ECS2 eth0 + pod port   -> cni0 ->  vethxxxxx -> ECS2 Pod1 eth0
  • 数据链路要经过三次内核协议栈,分别是 ECS1 OS、 ECS2 OS 协议栈 和 Pod 协议栈
  • ExternalTrafficPolicy 为 CLuster 模式下,kubernetes 所有 ECS 节点都会被加入到 SLB 的后端虚拟服务器组中,参与 SLB 的流量转发,此时会存在数据路在集群内被多个 ECS 转发的场景,该情况下会丢失真实客户端IP的情况

总结

本篇文章主要聚焦 ACK 在 Flannel 模式下,不同 SOP 场景下的数据链路转发路径。随着微服务化和云原生化,网络场景日趋复杂,作为 kubernetes 原生的网络模型——Flannel,不同的访问环境,一共可以分为10个 SOP 场景。通过深入简出的剖析,可以归纳为5个场景,并对这五个场景的转发链路,技术实现原理,云产品配置等一一梳理并总结,这对我们遇到 Flannel 架构下的链路抖动、最优化配置,链路原理等提供了初步指引方向。接下来将进入到阿里自研的 CNI 接口 Terway 模式,也是目前线上集群使用最多的模式,下一系列我们先带来 Terway  ENI 模式的全景解析——ACK 全景剖析阿里云容器网络数据链路(二):Terway ENI。

点击此处了解阿里云容器服务

你可能感兴趣的:(阿里云云原生容器)