Slim: OS Kernel Support for a Low-Overhead Container Overlay Network 阅读

摘要:现在容器已经成为了大型分布式应用程序的实际方法,而容器覆盖网络对于提供容器的可以自行是很重要的,但是该网络却会对吞吐量、延迟和CPU利用率等带来很大的影响,其中的关键就是依赖包转换来实现网络虚拟化。所以数据包在发送和接收的主机OS内核中会两次遍历网络协议栈,而Slim则是一个低开销的容器覆盖网络,是通过操作连接级元数据来实现网络虚拟化的,并和容器化应用程序保持了兼容性。

1 介绍

容器在现在已经成为了管理和部署大型分布式应用程序的常用方法,包括内存中的键值存储、web服务器、数据库和数据处理框架,它之所以这么广泛被使用,是因为容器一般是轻量级的,便于携带,单个物理机可以轻松的承载比标准虚拟机多十倍的容器,所以还节约了很大的成本。

而容器覆盖网络是为分布式容器应用程序提供可移植性的关键,它让容器不管被分配到哪里,以及主机上有哪些容器,都可以让一组容器可以使用自己独立的IP地址和端口号进行通信,从而消除了应程序开发人员之间协调端口和IP地址的负担,极大地简化了应用迁移的问题,比如现在的Docker和Swarm两种容器编制器。而目前的容器覆盖网络存在的问题,比如吞吐量大大减少,包延迟也大大增加,CPU利用率也增加了很多,而目前的一些优化技术比如包控制和虚拟化的硬件支持只能解决部分问题。关键问题就是它依赖于内部的多个包转换。

                                      

如图1a中,为用于网络虚拟化的操作系统,从中可以看出每个数据包必须从网路协议栈中经过两次,并且在发送端和接收端都有一个虚拟交换机,所以数据包需要先经过虚拟网络接口上的覆盖网络栈,然后通过虚拟交换机的数据包转换,再经过主机网络栈。这就类似于图1b的虚拟机覆盖网络,但是对于容器,OS内核完全了解每个网络的连接。

而文中的Slim,设计原则为:容器覆盖网络中的数据包只需要通过一次操作系统内核的网络栈,所以需要从覆盖网络中的数据平面移除数据包转换这一步骤,相反,通过操作连接级元数据来实现网络虚拟化,从而节省我们的CPU周期和减少包延迟。实现这样一个覆盖网络,我们的挑战有:(1)网络虚拟化必须与当今未修改的容器化应用程序兼容;(2)在数据平面上需要支持当前由容器覆盖网络实施的相同连网策略;(3)需要有与当前的容器覆盖网络相同的安全模式。而本文最大的贡献在于:(1)经过几个基准测试,本文认为当今的容器覆盖网络的主要瓶颈是全包处理(包转换、网络栈的额外遍历);(2)Slim是一种操作连接级元数据实现网络虚拟化的解决方案,与当前的应用程序和操作系统内核兼容,支持各种网络策略和相同于容器覆盖网络的安全模型;(3)体现了Slim对于各种流行的容器化应用程序提高的效率。从根本上讲,就是Slim将有效的虚拟化集成到操作系统的网络堆栈中,而网络对战是高效容器虚拟化生下的性能差距,Slim缩小了这个差距。

2 背景

本节,搜仙描述传统容器覆盖网络的体系机构,以及为什么本文设计对容器化应用程序有用,然后根据吞吐量、延迟和CPU利用率来量化当前容器覆盖网络解决方案的开销。最后,证明即使应用了已知的开销减少技术(包控制),开销仍然是显著的。

2.1 容器覆盖网络

关于容器覆盖网络可以参考本人另一篇文章:https://blog.csdn.net/LPAINI520/article/details/105664521,文章内有关于容器覆盖网络的相关介绍。而容器覆盖网络的架构则如下图2所示:

                      

                                                                        图2 容器覆盖网络的架构

从图中可以知道,它使用的是包转换来进行网络虚拟化,它显示了一个OS内核和一个使用名称空间和Cgroups构建的容器,Namespace隔离,从而防止容器内部访问主机的网络接口,Cgroups允许对容器内的应用程序使用的资源总量进行细粒度的控制,比如对CPU、内存和网络等资源。

在这样的容器覆盖网络中,最关键的一个组件是内核中的虚拟交换机,它主要有两个功能:(1)网络桥接,允许同一主机上的容器进行通信;(2)网络隧道,让容器内的流量可以通过物理网络。虚拟交换机通常使用Open VSwitch的内核模块进行配置,隧道协议则是VXLAN。而执行各种网络策略(访问控制、QOS等)是向虚拟网络接口或虚拟交换机发出策略更新,这些规则是根据应用程序的虚拟IP地址来指定的,并不是容器所在的物理主机来指定。而在覆盖网络中运行一组容器的主机必须在主机之间维护一致的全局网络视图,它们通常使用外部的、容错的分布式数据存储或者gossiping协议来实现。

2.2 容器覆盖网络的开销

数据包的开销:该网络的开销主要是操作系统内核中对每个数据包的处理,比如包转换和网络协议栈的开销等。在它的发包和收包的流程中,成本是高昂的,从图2中可以看出在覆盖网络上交付一个数据包,需要额外的网络协议栈的遍历,不只是容器内的协议栈,还有主机上的协议栈,还有包发送时候的封装和接收时候的解封装,从而让代价变得高昂。如下表1是覆盖网络和主机模式下的比较:

                                                                  表1覆盖网络模式和主机网络模式的比较

SetupThroughputRTT(μs)
Intra,Host48.4 ± 0.75.9 ± 0.2
Intra,Overlay37.4 ± 0.8 (23%)7.9 ± 0.2 (34%)
Inter,Host26.8 ± 0.111.3 ± 0.2
Inter,Overlay14.0 ± 0.4 (48%)20.9 ± 0.3 (85%)

表中为与使用主机模式相比,容器覆盖网络上单个TCP连接的吞吐量和延迟比较。Intra是同一物理机器上的连接;Inter是两个不同物理机器之间超过40gbps的连接。±表示标准差。括号中的数字显示了与使用主机模式相比的相对减速

量化的开销:为了了解产生表1中的性能差距来源,文中使用了标准的Linux内核CPU分析工具mpstat来度量CPU的利用率,专门去检查了两个不同物理主机上的覆盖网络,测试中将TCP连接的速度设置为10Gbps,然后利用mpstat来确定10次10秒的测试中,CPU周期花费在哪些地方,图3即为总体CPU利用率和具体的使用:

                                                                     

                                                                                       图3 CPU利用率的比较

图3,在不同覆盖网络设置下的CPU利用率是通过单个10Gbps TCP连接使用的虚拟核的数量来测量的。CPU周期花费:在用户级应用程序(usr)中,在内核中,但不包括中断处理(sys),以及服务于软件中断(soft)。误差条表示标准差

2.3 微调的数据平面

在这里,主要展示了一些现有的技术对于容器覆盖网络的性能问题的解决,但是对应的还是存在着大量的其他开销。

目前有几种已知的技术可以减少数据平面开销。比如包控制,它为网络接口创建多个队列(每个CPU内核),并使用一致的hash将包映射到不同的队列。这样,同一网络流量中的数据包只在一个核心上处理。因此,不同的内核不必访问相同的队列,从而消除了多核同步(例如,缓存线冲突、锁定)带来的开销。表2则是使用包控制的覆盖网络对容器的吞吐量和延迟的影响:

                                                                                 表2 吞吐量和延迟的比较

SetupThroughputRTT(μs)
Random LB14.0 ± 0.4(48%)20.9 ± 0.3(85%)
RPS24.1 ± 0.8(10%)20.8 ± 0.1(84%)
RFS24.5 ± 0.3 (9%)21.2 ± 0.2(88%)
Host26.8 ± 0.111.3 ± 0.2

表2为TCP吞吐量和延迟(往返时间32字节的TCP包)用于跨两个物理主机的容器覆盖网络上不同的包控制机制。±表示标准差。括号中的数字显示了与使用主机模式相比的相对减速。从表中可以看出,包控制的方法,可以提高吞吐量,但是他对CPU利用率的影响比吞吐量要小,延迟方面则基本没影响,数据包还是需要经过相同的包转换和两次协议栈,而Slim则直接关注于消除容器覆盖网络中每个包的处理开销。

3 Slim概述与设计

3.1 Slim概述

Slim提供了一个低开销的容器覆盖网络,在该网络中的数据包仅需要遍历网络协议栈一次。与其他容器覆盖网络的实现一样,Slim创建了一个配置完全与主机网络解耦的虚拟网络。容器没有可见的主机网络接口,它们仅使用OS内核创建的虚拟网络接口进行通信。为此,Slim就需要支持一些特性,(1)易于部署,即支持未经修改的原始应用程序的使用,(2)灵活,支持需要的网络策略,比如访问控制和QoS等,(3)安全,容器不能接触到主机内的信息,不能直接在主机网络上创建连接,也不能增加它的流量优先级。如下图4即为Slim的架构:

                                               

                                                                                  图4 Slim的架构

它主要有三个组件:(1)用户空间的shim层SlimSocket,它主要是为了与可执行文件进行动态链接;(2)用户空间路由器SlimRouter,工作在主机的Namespace中;(3)小型可选内核模块,SlimkernelModle,,它主要是为了解决一些问题,比如动态更改访问策略、增强安全性等,从而陈强操作系统内核。

Slim是通过操作连接级元数据来虚拟化网络的。SlimSocket会向可执行文件公开POSIX套接字接口,以截获与套接字相关的系统调用。当SlimSocket检测到一个应用程序正在尝试建立一个连接时,它会向SlimRouter发送一个请求。SlimRouter设置网络连接后,将对连接的访问作为文件描述符传递给容器内的进程。然后容器内的应用程序使用主机名称空间文件描述符来直接向主机网络发送或者接收数据包。因为SlimSocket具有与POSIX socket完全相同的接口,并且Slim动态地将SlimSocket链接到应用程序中,所以不需要修改应用程序的基础代码。所以在Slim中,数据包是直接进入主机网络中的,绕过了虚拟网络接口和虚拟交换机;所以这时候就需要一个单独的机制来支持各种灵活的控制平面策略(如访问控制)和数据平面策略(如速率限制、QoS)。控制平面策略隔离了容器化应用程序的不同组件。数据平面策略限制容器的网络资源使用,并允许对网络流量进行优先级划分。在当前的许多覆盖网络中,这两种类型的策略实际上都是在数据平面内实施的。例如,典型的网络防火墙检查每个数据包,以确定它是否被访问控制列表阻塞。

其中SlimRouter存储控制平面策略,并在连接时强制设置它们。这种方法避免了再次检查连接中每个包的需要。在创建连接之前,SlimRouter检查访问控制列表是否允许连接。当策略发生变化时,SlimRouter扫描所有现有的连接,并通过SlimKernModule删除任何违反更新的访问控制策略的连接的文件描述符。Slim利用现有的内核功能来实施dataplane策略。但是这时候却可能产生安全问题,因此Slim提供了一种安全模式,当启用了该模式时,Slim会利用内核模块来限制容器来主机名称控件文件描述符的能力,该内核模块有三个功能:(1)跟踪在容器内使用的文件描述符;(2)根据SlimRouter的请求对文件描述符进行更改;(3)禁用一些功能,比如getpeername、connect等,从而让系统更安全。

3.2 Slim设计

(1)虚拟化:Slim的虚拟化是不需要在数据平面中进行数据包转换的,同时还能保持与当前应用程序的兼容性。Slim它虚拟化网络的方式是区别于传统覆盖网络的,它采用的是操作连接级的元数据来进行虚拟化,从而当容器在主机上启动时,Slim在主机名称控件中分派SlimRouter的一个实例,Slim将用用户级的shim层(SlimSocket)链接到容器,当容器内的进程创建了一个连接,而不是进行标准的套接字调用时,SlimSocket向SlimRouter发送一个带有目标IP和端口号的请求,SlimRouter代表容器穿件一个连接,并向容器返回一个主机名称控件文件描述符,并且Slim支持传统的阻塞I/O和非阻塞I/O。如下图5即为非阻塞I/O的一个示例图:

         

                                                                                         图5 非阻塞I/O的连接设置与流程

从图中可以清楚的了解到我们阻塞I/O在Slim中执行的流程与文件描述符的一个改变过程。

(2)支持灵活的网络策略:这里的策略既包含了数据平面的还有控制平面的一些策略。对于控制平面策略,Slim支持覆盖包头字段的标准访问控制,从而可以过滤特定类型的流量或特定IP前缀的流量,一般策略规则是静态的,在创建连接时候实施访问控制,SlimRouter则负责维护当前的策略副本,从而在accept或connect的时候,SlimRouter可以去检查连接是否违反任何现有规则,从而拒绝违规操作。但是这里的访问控制策略却可以去动态的更改,而SlimRouter会保持每个连接的状态,包括源和目标IP地址、端口和相应的主机名称空间文件描述符。当访问控制策略更改时,SlimRouter会遍历所有当前连接,以查找更新的策略中禁止的连接。然后让SlimKernModule从容器中删除相应的文件描述符来中止这些连接。对于控制平面策略,Slim支持两种策略,速率限制和QoS,速率限制限制了容器可以食用的资源数量,QoS则负责确保某些应用程序的性能优于其他的应用程序,Slim也只需要设置正确的标识符,让操作系统内核识别生成流量的容器。在Slim中速率设置同时在每个链接和容器级别上实施,方式是与使用Linux流量控制程序tc的覆盖网络类似;QoS也是使用的tc,SlimRouter使用套接字选项设置服务类型字段来实现。对于IT工具,通常需要对工具进行修改,且工具是与SlimRouter交互,IT工具也需要将对应的规则注入到SlimRouter中,因为Slim本质上是基于连接的虚拟化方法。当然如果要是只需要基于静态链接的访问控制网络策略,则IT工具不需要更改。

(3)安全问题的解决:Slim在确保和当前的容器覆盖网络相同的安全策略是通过可选的内核模块SlimKernModule实现的,这个问题涉及想要绕过SlimSocket的潜在恶意容器。Slim向容器公开主机名称空间文件描述符,因此需要操作系统内核中额外的机制来跟踪和管理访问,SlimKernModule不允许使用这些文件描述符调用某些不安全的系统调用。例如,在Slim的情况下,标记的文件描述符不能与以下系统调用一起使用:connect、bind、getsockname、getpeername、setsockopt等。这将阻止容器学习它们的主机IP地址或增加它们的流量优先级。它还可以防止容器直接创建主机网络连接。对于非恶意容器,SlimSocket和SlimRouter模拟这些禁止的系统调用的功能,当然安全模式的连接设置时间会比传统的容器覆盖网络长。

3.3 Slim的实现

Slim的实现是基于Linux和Docker的,SlimSocket、SlimRouter和SlimKernModule分别在1184行C、1196行c++(不包括标准库)和1438行C中实现。原型依赖于标准覆盖网络Weave,用于需要数据平面处理的服务发现和数据包(例如,ICMP, UDP)。SlimSocket使用LD_PRELOAD来预加载动态链接到应用程序去,SlimSocket和SlimRouter之间的通信是通过Unix域套接字进行的。在非安全模式下,文件描述符通过sendmsg在SlimRouter和SlimSocket之间传递。对于安全模式,文件描述符通过SlimKernModule的跨进程文件描述符复制方法传递。

SlimRouter则允许网络操作员根据JSON文件中的源/目标IP地址前缀和端口将访问控制表示为条目列表。SlimRouter有一个命令行接口,网络操作员可以通过重新加载JSON文件来发出访问控制列表中的更改。Slim拒绝列表中匹配的任何连接。SlimRouter使用htb 队列实现速率限制,使用tc实现QoS的优先队列。SlimRouter和SlimKernModule通过由SlimKernModule创建的procfs中的一个虚拟文件进行通信。SlimKernModule将对该文件的写操作视为请求。访问虚拟文件需要主机根权限。

SlimKernModule通过替换系统调用表中的函数指针来干预系统调用。SlimKernModule在哈希表和不安全的系统调用列表中存储标记的文件描述符。SlimKernModule拒绝对标记文件描述符的不安全系统调用;SlimKernModule还对系统调用(如dup、dup2和close)进行干预,以确保正确地传播文件描述符标记。对于进程fork(例如,fork、vfork、Linux内核中的克隆),SlimKernModule使用sched进程fork作为回调函数。Slim不会改变进程分叉的行为。分叉的进程仍然有SlimSocket动态链接。

4 关于Slim的一些基准测试和比较

4.1 测试

图6为TCP连接的CPU利用率和故障分析。在图6a中,Slim和主机行重叠。在图6b中,usr条位于底部,可以忽略不计。误差条表示标准差;图7为两个Slim容器的总吞吐量的柱状图,其中一个容器的速率限制和访问控制策略更新。图8为使用Weave(各种配置)和Slim时Memcached的吞吐量和延迟。图8a中的Error bars显示了每秒完成的Memcached操作的标准偏差。

             

                                                             图6                                                                                        图7

                                  

                                                                                              图8

4.2 与其他应用的比较

   

                                                     表3 迁移Memcached容器的时间。±后面的数字表示标准差。

 WeaveSlim
Stop running container0.75 ± 0.020.75 ± 0.02
Extract into image0.43 ± 0.010.43 ± 0.01
Transfer container image0.44 ± 0.010.44 ± 0.01
Restore fs 0.82 ± 0.091.20 ± 0.10
Start SlimRouter-0.003 ± 0.001
Start container0.90 ± 0.090.94 ± 0.17
Total3.34 ± 0.12s3.76 ± 0.20s

5 结论

容器已经成为承载分布式应用程序的实际方法。提供可移植性的关键组件是容器覆盖网络,它在吞吐量、延迟和CPU利用率方面带来了巨大的开销,因为它在数据平面上增加了一个层。而使用Slim,一种低开销的容器覆盖网络,它通过操作连接级元数据来实现网络虚拟化。Slim透明地支持未经修改的、潜在恶意的应用程序。Slim将内存中的键值存储的吞吐量提高了71%,并将延迟降低了42%。Slim将内存中键值存储的CPU使用率降低56%,将web服务器的使用率降低22%-24%,将数据库服务器的使用率降低22%,将流处理框架的使用率降低10%。

Slim的源代码可以在https://github.com/danyangz/slim上找到。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值