Loading...
墨滴

一介刁民

2021/11/07  阅读:21  主题:自定义主题1

一文读懂 underlay

二哥喜欢在推文里面附上大量的图,这些图有些是我自己画的,有些是我平时看各种资料时收藏的。在推文里引用图时,我尽量从官网下载,如果是书籍里的图,我会标明图的来源。

二哥一贯坚持一个观点:一图胜千言,晦涩冗长的技术文字可以用精致的图片完美地展现。据说人脑对图像的加工记忆能力大约是文字的1000倍,甭管它是真是假,我们对图片的敏感度和好感确实是远大于文字的,我们的脑袋可以长久地记住图片所包含的内容,却对大片的文字读过即忘。

我写设计文档的时候也会画图。文字总是抽象的,而图却是具象的。文学作品不适宜配过量的图,因为那样会限制读者对文字的想象力,每个人心中都有一个林黛玉才是美好的。但和文学作品不同,传递技术信息时,用图的方式可以更好地确保大家的理解是一致的且能达到事半功倍的效果,准确传递是首要目标。有三本我看过的书在这方面堪称典范:W.Richard Stevens《UNIX环境高级编程》、Marko Lukša《Kubernetes In Action》还有刘超《趣谈网络协议》。

今天我们聊聊容器网络的Underlay模式。

三大模式回顾

之前,二哥发过一篇推文“特洛伊木马-图解VXLAN容器网络通信方案”,当时主要聊的内容是容器网络方案中的一种,即通过VXLAN的方式将容器间的网络拓扑压扁,摊平,形成一个所谓flat netowrk。其实VXLAN只是实现“扁平网络”这个目标的众多方式之一。将这些方式稍加归纳整理,我们大致可以将它们分为以下三种模式:

  • Overlay模式 这是最自由、开箱即用的方案。特点是方便、易用、自由。但自由是有代价的,与主机间通信效率相比,它的传输性能会有20-30%左右的下降。

    性能损耗花在了什么地方呢?一个是隧道所带来的解/封装损耗,另一个是进出Pod的traffic要穿越两次网络栈(进两次,出也是两次)。解/封装的代价显而易见,而两次网络栈的穿越却很容易让人忽略。

    如图1所示,Pod traffic在Pod network namespace和Node的network namespace分别会被处理一次,如果Node的network namespace里有大量的iptables rule的话,会出现较长的处理时间。图1中用红色标示出了"iptables overhead",意思是这部分是额外的工作量,言下之意是其实这部分工作量可以去掉,Cilium正是基于eBPF跳过了这些overhead,从而实现了明显的性能提升。

    这种模式可供选择的实现有Flannel VXLAN,Calico IPIP等。

  • 主机间路由模式 这里所谓的主机是指组成K8s集群的Node。主机间路由其实是将各个Node当成了边界路由器,每个Node是一个AS(Autonomous System),这很好理解,毕竟Linux是自带路由功能的。虽然容器网络和宿主机网络是两个平行的网络,但容器间通信可以直接通过宿主机网络路由。这个时候它俩的关系其实很像电信、联通这些网络运营商和阿里云、腾讯云这些云平台之间的关系,它们各自独立运营宽带网络(若干AS组成),但是电信联通会转发来自云平台的流量,对于运营商来说,它被称为 Transit AS。

    这种模式优势非常明显:性能高,和主机间通信相比,容器间通信大概有10%左右的性能损耗,当然和Overlay模式一样,主机间路由同样会出现图1中所示的两次穿越网络栈的问题。

    这种模式的缺点也非常明显:不是你想要就可以,因为它需要用到BGP协议,如果你使用的是云平台托管的容器服务,你几乎没有插手使用BGP的机会。

    这种模式可供选择的实现有Flannel host-gw,Calico BGP等。

  • Underlay模式 Underlay这个词和Overlay相反,一下一上。这个模式特指让容器和宿主机处于同一网络,两者拥有相同的地位的网络方案。

    主机间路由模式算是Underlay模式的一个特殊场景。但主机路由模式其实还是将宿主机网络和容器网络进行了主客之分。主场和地盘是宿主机的,只是允许容器网络的流量自由进出罢了。这就像孙权想要去益州的话,得经过荆州,但刘备认为那只是为友情干杯,给他借道而已,他自己才是荆州的主人,最靓的那个仔。

    但Underlay模式却彻底抹去了地盘之争。这块地是大家的,大家生而平等,谁都可以自由进出。最重要的是没有任何性能损耗。

    阿里云、GKE、AWS、Azure均提供了这种模式。这篇和下一篇重点聊聊这种模式。

图 1:进出Pod的traffic穿越两次网络栈

“扁平-K8s网络模型漫谈”这篇推文从10000英尺的高空俯瞰了宿主机网络和容器网络的关系,给有需要的人。

广角看全景

用广角镜头拍摄的画面,在突出中央主体和前景的同时,还具有广泛的背景。本文要聊的中央主体和前景当然是下图中的Pod和虚拟机所组成的Underlay模式网络,但只关注它们是不够的,因为我们需要结合更多的背景来了解它们之间的关系。所以图2中我加入了更多的背景:Open vSwitch,VPC,接入交换机,汇聚交换机等等。

图 2:Underlay模式广角图

图2首先画出了一个数据中心主要的设备。进出物理机的流量会通过接入交换机、汇聚交换机和核心路由器。二哥是一个注重细节的人,你会发现连接不同等级的网络设备之间的线宽是不一样的,线越宽越代表它承载的流量越大,也意味着离骨干网越近。

同一个机架上的物理机通过接入交换机互联,而不同机架上的物理机则通过汇聚交换机互通。如果你愿意买个更广的镜头,会发现汇聚交换机用来连接一个可用区里所有的物理机,而核心交换机则连接了更多的可用区。

边界路由器限定了这个数据中心的边界,在它之外便是电信联通所运营的互联网,当然边界路由器会和多家运营商互联,此时它被称为Multihomed AS。边界路由器通过 BGP 协议,将自己数据中心里面的外网IP借助运营商的网络向外广播,告知全世界:我们在这里。

不同的数据中心则通过VPN相连。

细心的你一定发现了在可用区A和可用区B里,Pod,虚拟机和物理机这三者之间,网络连接方面有很大的不同。可用区A里面用到了Open vSwitch,而可用区B里面没有。另外在可用区B里,Pod的网络设备名我特意改成了veth。不同的可用区在二层是否互通没有统一的做法。不通的话,可以避免网络广播风暴、二层环路等问题,通的话可以实现大二层,都在一个广播域里,方便横向扩展以满足日益增长的东西流量。

这样的不同对进出Pod的traffic会有什么样子的影响呢?我们接着往下聊。

Network namespace

Network namespace的概念不复杂,但二哥觉得越是简单的东西,有的时候我们越容易忽略它的内涵。

一个 Linux 容器能看见的“网络栈”,实际上是被隔离在它自己的 Network namespace 当中的,Network namespace用来隔离包括网卡(Network Interface)、回环设备(Loopback Device)、网络栈、IP地址、端口等等在内的网络资源。对于一个进程来说,这些要素,其实就构成了它发起和响应网络请求的基本环境。

所谓“网络栈(Networking stack)”,包括了:路由表(Routing Table), network filter,iptables 规则等。它的特点是由可配置的数据组成。

另外还有一个栈也会被经常提起:TCP/IP协议栈。我们可以将TCP/IP栈看成是程序的代码部分,而网络栈看成是程序的数据部分。很显然TCP/IP栈应该是被这个OS上所有人共享的,无论是进程还是容器,甚至是基于qemu-kvm的虚拟机都共享着宿主机的协议栈,但网络栈却是各自独享的。

注意:这个说法不是特别准确,目的是为了让大家可以区分网络栈和TCP/IP栈。

图 3:root network namespace和Pod network namespace对比

图3将Node上初始的Network namespace命名为root。不要纠结这个词对不对,你懂我的意思就行。正常情况下,在这个VM上跑的非容器进程都是在Root network namespace里的。

这张图展示了一个概念:一台VM上会存在Root network namespace和多个Pod network namespace。嗯,我好像说了一句废话。

现在思考一个问题:Pod里面的outgoing traffic离开了Pod后,它和root network namespace会不会相遇?

答案是:可能。其实这取决于流量从Pod里的eth0离开后是经过Root Network namespace还是与之直接擦肩而过,而这一切都由容器网络的具体实现技术决定。下面是三种典型的实现技术。

veth+bridge+vtep

这种实现方式,我们称之为Overlay模式,如图2可用区B中容器网络所示。如果使用的是veth+bridge模式,那么traffic离开Pod后,首先会出现在veth的另一端,而另一端是插在bridge上面的,这也就意味着流量直接进入了bridge。

如果数据包的目的MAC地址为bridge本身,并且网桥设置了IP地址的话,那bridge认为它收到的数据包应该要发往创建网桥的那台主机,在我们这个示例中,主机就是VM。于是这个数据包将不会被转发到网桥上的任何设备,而是直接交给VM的上层(三层)协议栈去处理。

这个过程所带来的效果是traffic从一个子网(容器所在的网络)离开,进入了另外一个子网(VM所在的网络),这其实也就模拟了traffic通过物理交换机的网关离开局域网的过程。

在Pod内将网关设为bridge的IP地址,Pod的协议栈会将网络包的dest MAC设置为bridge本身的MAC,也即下一跳MAC设为bridge。

网关是一个颇能迷惑新手的概念,实际上网关IP在网络通信过程中的所有traffic中都不会出现,但它不可或缺,它的作用是为了给traffic离开子网时指明下一跳MAC地址。

可以看到这种情况下,流出Pod的traffic进入了Root network namespace。因为VTEP的存在以及流量需要穿越Root network namespace,与主机间通信效率相比,这里出现了20%-30%的性能损耗。

veth+root network namespace

这种实现方式,我们称之为主机(Node)间路由模式,如图2可用区C中容器网络所示。和可用区B相比,它也用到了veth,但因为没有使用bridge,vetch一端插在了Pod network namespace中,另一端直接插在了Root network namespace里。当traffic离开Pod并出现在veth另一端时,对于Root network namespace而言,它认为是它里面的一个网卡收到了ingress traffic。在Flannel host-gw,Calico BGP的实现中,Pod traffic需要经过Node的二层和三层的处理。

可以看到这种情况下,流出Pod的traffic也进入了Root network namespace。但与前一种模式相比,省去了VTEP这个解/封装环节,总性能损耗因此下降了很多,大概只损失了10%左右。

multi-NIC热插拔

这种实现方式,我们称之为Underlay模式,如图2中可用区A容器网络所示。英文是:multi-NIC hot swapping。它有两个关键的概念:multi-NIC(多网卡)和热插拔,合起来表示通过虚拟化的方式,在VM里热插拔多个网卡。在机器上使用多个网卡不是特别的事情,但加上了多个关键词就意味着完全不同的使用场景了:VM,热插拔,多网卡。下文微距部分,我们可以看到这三个关键词是如何催化出神奇的魔力的。

微距看Pod如何翻身为一等公民

微距可以尽可能地放大被摄物体,查看细节。我们来把可用区A放大看看。

networking-Underlay-微距

图 4:容器网络Underlay模式微距图

和可用区B、C最大的不同在于,在可用区A里面,Pod没有使用veth。咋一看这有点奇怪,没有veth的话,那么Pod里的traffic该如何离开容器网络又该如何路由呢?

在回答这个问题前,让我们先来看下图3。那张图其实在强调一个概念:root network namespace和Pod network namespace它们之间是相互独立的,平行的世界。让我们再复习下network namespace所隔离的内容:网卡、回环设备、网络栈、IP地址、端口等等。

这就表示:隔离特性使得流经这些namespace里,各自网络设备上面的流量是相互独立、平行的,尤其重要的是Pod里的流量进出这台虚拟机的时候,root network namespace无法感知到,所以在VM上对iptables、路由等设置对进出Pod的流量不起任何作用。traffic离开Pod和VM里的进程产生的traffic离开VM一样,都是离开各自的network namespace。

为了强调这样的平行关系,我在图4里画了两个蓝色的箭头,它们的出发点分别是VM和Pod,终点是穿过Open vSwitch的远方。traffic从各自的network namespace离开,互不见面,互不问候,互不干扰。

在这种模式下,可以看到这样的转变使得Pod摇身变成了和VM一样的一等公民。而在可用区B和C模式下,Pod还是要看VM的脸色才能传输数据的。但需要强调的是虽然Pod变成了一等公民,但Pod所在的容器网络和VM所在的宿主机网络依旧是平行的,前者由CNI负责管理。

这个非常重要的网络隔离特性为Underlay模式提供了技术基础。有了技术,有了蓝图还不行,得有砖头才能盖成房子。这不,multi-NIC热插拔来了。

我们知道在物理机上,受制于PCIe插槽的限制,一台机器可以允许插入的网卡数量是有限的,而网卡虚拟化的到来则突破了这个限制,只要内存允许,可以创建无限个虚拟网卡。但可以建虚拟网卡还只是第一步,还得把这些虚拟网卡动态插入到协议栈,且协议栈还能认得它们,不然创建出来的虚拟网卡就成了摆设了。如今,在虚拟化浪潮下,这都成为了现实,这为Underlay模式的出现提供了实现基础。

当CNI得知K8s会在该Node上创建一个新的Pod时,它会将手中已有的(一般会提前创建虚拟网卡)网卡插入到Pod的network namespace,并给它配置IP地址,路由等信息,这些信息是与云平台IaaS的网络服务强相关的,实际上无论是阿里云还是AWS,都提供了OpenAPI,以供CNI创建虚拟网卡并获取这些信息。

当你耐着性子听二哥啰嗦到这个地方的时候,也许会明白所谓的一等公民意味着什么:它意味着Pod和VM一起平等分享云平台服务商所提供的网络基础设施如SDN,VPC等,也因此获得和VM一样的网络传输性能。

其实不只是性能传输的平等性,我们可以看到Pod和VM都连接到了Open vSwitch上,这就使得我们可以通过OpenFlow在SDN控制平面来统一控制Pod和VM,如流量控制,流量监控,VLAN层级的隔离。

周志明老师在《凤凰架构》一书中说:对于真正的大型数据中心、大型系统,Underlay 模式才是最有发展潜力的网络模式。这种方案能够最大限度地利用硬件的能力,往往有着最优秀的性能表现。但也是由于它直接依赖于硬件与底层网络环境,必须根据软、硬件情况来进行部署,难以做到 Overlay 网络那样开箱即用的灵活性。

深以为然。

以上就是本文的全部内容。码字不易,喜欢本文的话请帮忙关注、点赞、点击"在看"。您的举手之劳是对二哥莫大的鼓励。谢谢! 理解这些东西非常重要,因为这是 Cilium 乃至广义 datapath 里非常核心的东西。如 果遇到底层网络问题,或者需要做 Cilium/kernel 调优,必须要理解包的收发/转发 路径。

关注公众号: 云原生 Serverless,了解更多 Serverless 、Knative,云原生相关资讯

关注公众号,回复 "进群",即可进群与众多云原生 Serverless 技术大佬探讨技术,探讨人生。

在这里插入图片描述
在这里插入图片描述

一介刁民

2021/11/07  阅读:21  主题:自定义主题1

作者介绍

一介刁民