作者:余凯
本系列文章由余凯执笔创作,联结作者:阿里云云原生利用平台 谢石 对本文亦有奉献
前言
近几年,企业基础设施云原生化的趋势越来越强烈,从最开始的 IaaS 化到当初的微服务化,客户的颗粒度精细化和可观测性的需要更加强烈。容器网络为了满足客户更高性能和更高的密度,也始终在高速的倒退和演进中,这必然对客户对云原生网络的可观测性带来了极高的门槛和挑战。为了进步云原生网络的可观测性,同时便于客户和前后线同学减少对业务链路的可读性,ACK 产研和 AES 联结共建,合作开发 ack net-exporter 和云原生网络数据面可观测性系列,帮忙客户和前后线同学理解云原生网络架构体系,简化对云原生网络的可观测性的门槛,优化客户运维和售后同学解决疑难问题的体验,进步云原生网络的链路的稳定性。
鸟瞰容器网络,整个容器网络能够分为三个局部:Pod 网段,Service 网段和 Node 网段。这三个网络要实现互联互通和访问控制,那么实现的技术原理是什么?整个链路又是什么,限度又是什么呢?Flannel,Terway 有啥区别?不同模式下网络性能如何?这些,须要客户在下搭建容器之前,就要根据本人的业务场景进行抉择,而搭建结束后,相干的架构又是无奈转变,所以客户须要对每种架构特点要有充沛理解。比方下图是个简图,Pod 网络既要实现同一个 ECS 的 Pod 间的网络互通和管制,又要实现不同 ECS Pod 间的拜访,Pod 拜访 SVC 的后端可能在同一个 ECS 也可能是其余 ECS,这些在不同模式下,数据链转发模式是不同的,从业务侧体现后果也是不一样的。
本文是 [全景分析容器网络数据链路] 第一局部,次要介绍 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 agent,并且会给每个节点预调配一个 Pod CIDR,这个 Pod CIDR 是 ACK 集群的 Pod CIDR 的子集。
容器的网络命名空间内会有一个 eth0 的虚构网卡,同时存在下一跳指向该网卡的路由,该网卡会作为容器和宿主内核进行数据交换的出入口。容器和宿主机之间的数据链路是通过 veth pair 进行替换的,当初咱们曾经找到 veth pair 其中一个,如何去找另一个 veth 呢?
如上图所示,咱们能够容器的网络命名空间中通过 p addr 看到一个 eth0@if81 的标记位,其中‘81′ 这个将会帮助咱们在 ECS 的 OS 内找到找到和容器网络命名空间中的 veth pair 绝对一个。在 ECS OS 内咱们通过 ip addr | grep 81: 能够找到 vethd7e7c6fd 这个虚构网卡,这个就是 veth pair 在 ECS OS 侧绝对的那一个。
到目前为止容器内和 OS 数据链路曾经建设链接了,那么 ECS OS 内对于数据流量是怎么判断去哪个容器呢?通过 OS Linux Routing 咱们能够看到,所有目标是 Pod CIDR 网段的流量都会被转发到 cni0 这张虚构网卡,那么 cni0 是通过 bridge 形式将不同目标的数据链路指向到不同的 vethxxx。到这里为止,ECS OS 和 Pod 的网络命名空间曾经建设好残缺的出入链路配置了。
Flannel 模式容器网络数据链路分析
针对容器网络特点,咱们能够将 Flannel 模式下的网络链路大体分为以 Pod IP 对外提供服务和以 SVC 对外提供服务两个大的 SOP 场景,进一步细分能够拆分到 10 个不同的小的 SOP 场景。
对这 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
此场景蕴含上面几个子场景,数据链路能够演绎为一种:
- 以 Pod IP 对外提供服务,Client 和 Pod 部署于同一个节点;
- 以 SVC ClusterIP 对外提供服务,Client 和 SVC 后端 Pod 部署于同一节点;
- 以 SVC ExternalIP 对外提供服务,ExternalTrafficPolicy 为 Cluster/Local 状况下,Client 和 SVC 后端 Pod 部署于同一节点
环境
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 的默认路由
该容器 eth0 在 ECS OS 内对应 veth pair 是 vethd7e7c6fd
通过上述相似的方法,能够找到 nginx-7d6877d777-6jkfg IP 地址 172.23.96.24,该容器在宿主机体现的 PID 是 2981608,该容器 eth0 在 ECS OS 内对应 veth pair 是 vethd3fc7ff4
在 ECS OS 内,有指向 Pod CIDR,下一跳为 cni0 的路由,以及 cni0 中有两个容器的 vethxxx 网桥信息
小结:能够拜访到目标端
▲数据链路转发示意图
▲内核协定栈示意图
- 数据链路:ECS1 Pod1 eth0 -> vethxxx1 -> cni0 -> vethxxxx2 -> ECS1 Pod2 eth0
- 数据链路要通过三次内核协定栈,别离是 Pod1 协定栈,ECS OS 协定栈 和 Pod2 协定栈
场景二:Client 和服务端 Pod 部署于不同 ECS
此场景蕴含上面几个子场景,数据链路能够演绎为一种:
- 以 Pod IP 对外提供服务,Client 和 Pod 部署于不同节点;
- 以 SVC ClusterIP 对外提供服务,Client 和 SVC 后端 Pod 部署于不同节点;
- 以 SVC ExternalIP 对外提供服务,ExternalTrafficPolicy 为 Cluster 状况下,集群内 Client 和 SVC 后端 Pod 部署于不同节点;
环境
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
内核路由
Pod 网络空间和 ECS OS 网络空间的数据交换在 2.1 场景一中曾经做了详细描述,此处不再果决篇幅形容。
源端 Pod 所在 ECS 的 IPVS 规定
能够看到,源端数据链路拜访 svc 的 clusterip 192.168.13.23 时,如果链路达到 ECS 的 OS 内,会命中 ipvs 规定,被解析到 svc 的后端 endpoint 之一(本实例中只有一个 pod,所以 endpoint 只有一个)
小结:能够胜利拜访到目标端
▲数据链路转发示意图
VPC 路由表会主动配置目标地址是 pod CIDR,下一跳为 POD 网段所归属的 ECS 的自定义路由条目,该规定由 ACK 管控测通过 openapi 调用 VPC 去配置,无需手动配置和删除
▲内核协定栈示意图
Conntack 表信息(拜访 SVC 状况)
Node1:
src 是源 pod IP,dst 是 svc 的 ClusterIP,并且冀望是由 svc 的其中一个 endpoint 172.23.96.163 来回音讯给源端 pod
Node2:
目标 pod 所在 ECS 上 conntrack 表记录是由源端 pod 拜访目标 pod,不会记录 svc 的 clusterip 地址
- 数据链路: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 部署于不同节点;
环境
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
内核路由
Pod 网络空间和 ECS OS 网络空间的数据交换在 2.1 场景一中曾经做了详细描述,此处不再果决篇幅形容。
源端 Pod 所在 ECS 的 IPVS 规定
能够看到,源端数据链路拜访 svc 的 externalip 8.219.164.113 时,如果链路达到 ECS 的 OS 内,会命中 ipvs 规定,然而咱们能够看到 EcternalIP 并没有相干的后端 endpoint,链路达到 OS 后,会命中 IPVS 规定,然而没有后端 pod,所以会呈现 connection refused
小结:不能够拜访到目标端,此时会拜访失败,Connection refused
▲数据链路转发示意图
▲内核协定栈示意图
- 数据链路: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 为集群外
环境
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
内核路由
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.
故 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
node1:ap-southeast-1.10.0.1.216
小结:能够拜访到目标端
▲数据链路转发示意图
该图示意了只有后端 pod 所在 ECS 才会加到 SLB 后端中,从集群内部拜访 SVC 的 externalIP(SLB IP)的状况,可见数据链路只会被转发到虚构服务器组中的 ECS,不会再被转发到集群内其余节点上。
▲内核协定栈示意图
Conntack 表信息
Node:
src 是集群内部客户端 IP,dst 是节点 IP,dport 是 SVC 中的 nodeport。并且冀望是由该 ECS 上的 pod 172.23.96.82 来回包给源端
- 数据链路: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 为集群外
环境
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
内核路由
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.
故 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)
node1:ap-southeast-1.10.0.1.216 (该节点有后端 pod)
node3: ap-southeast-1.10.0.0.180 (该节无后端 pod)
小结:能够拜访到目标端
▲数据链路转发示意图
该图示意了集群内所有 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
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.
综上能够看到 src 变换了屡次,故在 CLuster 模式下,会存在失落实在客户端 IP 的状况
链路 2:
src 是集群内部客户端 IP,dst 是节点 IP,dport 是 SVC 中的 nodeport。并且冀望是由该 ECS 上的 pod 172.23.96.82 来回包给 172.23.96.65,此地址是 SLB 集群中的一个地址
- 数据链路:情景一: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。
点击 此处 理解阿里云容器服务