note: zVALE,这又是IBM研究院的研究并发表的文章,可能是VALE的延伸。
现在数据中心的网络主要被两股趋势所主导:一个是为了无损的二层fabrics,基于增强的以太网和Infiniband,通过从性能和效能方面得到好处;另外一方面,是基于软件定义网络的灵活性,这使得重叠的虚拟网络成为可能(SDN是重叠的虚拟网络的动力)。现在的问题是这两方面存在一些冲突,物理的Fabrics通过流控制机制(Flow_based Control)来防止丢包,而虚拟网络(没有流控制机制)却是会丢包的。所以,这个文章提出了一种零丢失的重叠虚拟网络,这个原型叫做zOVN。
主要是介绍了两个技术背景,一个是网络虚拟化,另外一个是无损Fabrics,无损Fabrics比如说FCoE需要使用增强的以太网CEE。
网络虚拟化和无损的高性能要求的fabric这两个技术通常是走的不同的技术路线,他们都独立地给数据中心带来他们的各自的影响。
而这篇文章的目的就是要在虚拟化环境中分析比较有无流控机制(Flow_based Control)对工作负载性能的影响。
服务器虚拟化使得动态和自动的虚拟机创建、删除和迁移成为可能,数据中心的网络必须支持这些功能而不带来过多的限制。
需要的额外功能:除了虚拟机迁移和轻松的管理,使用 traffic isolation来保证安全性也很重要。
带来的问题:网络虚拟化往往会带来很多的问题,比如说VLAN不足,IP地址不足和mac地址不足等。
为了解决这些问题,提出了很多网络虚拟化的解决方案,比如说各种Virtual Overlay network的各种方案。
来自wiki的解释:
An overlay network is a computer network, which is built on the top of another network. Nodes in the overlay can be thought of as being connected by virtual or logical links, each of which corresponds to a path, perhaps through many physical links, in the underlying network. For example, distributed systems such as peer-to-peer networks and client-server applications are overlay networks because their nodes run on top of the Internet. The Internet was originally built as an overlay upon the telephone network, while today (through the advent of VoIP), the telephone network is increasingly turning into an overlay network built on top of the Internet.
overlay network的一个例子是VXLAN,vxlan(virtual Extensible LAN)虚拟可扩展局域网,是一种overlay的网络技术,使用MAC in UDP的方法进行封装,共50字节的封装报文头。可以参考这个文章,可以解决数据中心VLAN不足等问题。
第一个实验:Iperf测试是否丢包。
使用iperf(Iperf是一个网络性能测试工具,也就是LINUX下的网速测试)的两个generotor以全速填充traffic,然后根据统计信息计算得到图1中每一个点的丢包的数量。结果如下图所示:
如表一所示,几组实验环境的的配置不一样,所以,C1到C7的七个配置在10s窗口的不同点的总的转发流量也是不一样的。虚拟环境中的性能是和计算资源相关的,所以计算密集型的配置导致更低的吞吐量,使得丢包率也更低。比如这里的e1000,基本上没有什么丢包率。另外特别为虚拟化优化过的网卡,比如virtio就有更高的吞吐率,但是也导致虚拟交换机的溢出。性能特别优化的VALE还把丢包的瓶颈延伸到了虚拟机内核栈。所有这些丢包都是因为虚拟网络设备之间没有很好的流控机制所导致的。
第二个实验:
目的是为了测试虚拟交换机的可持续的不丢包的带宽大小。
我们把genetator的速度按照5Mb为增量进行实验,还是用前面的几组测试例子进行的测试。这个实验的结果测得了每一种情况下的饱和带宽。
但是发现即使远远低于饱和带宽的情况下,任虚拟环境中的丢包比物理环境的丢包高了几个数量级(分别是10-2和10-8)。这些噪音又印证了之前的分析——虚拟环境因为处理器资源和内存资源等的不稳定,使得网络性能也会更加不稳定。
融合虚拟网络需要满足应用程序的所有的要求,比如无损的要求(hpc和存储),io密集型的工作负载则需要性能要求(用户程序反应时间小于200ms等)。
那么为了达到比如无损的要求应该怎么做呢?首先需要分析I/O路径,然后保证路径上的每一点都是无损的,那么就基本上可以保证l流量会是无损的了。数据包是在虚拟机上面跑的程序间传输(travel)的,在travel的路径上,数据包从一个队列到另一个队列(队列是在不同的软件或者硬件组件中的)。这里我们要细描述这些队列系统,并主要强调每一对队列之间的流控机制。数据包路径的trace从图5可看出。
从这个图中可以看出,有Qdisc这样一个组件和它的队列,然后还有socket TX和RX buffer以及各种各样的网卡和交换机队列。这个图的左边表示发送路径,右边表示接收路径,下面将分别解释发送和接收的机制以及各种特殊的无损保证处理。
它是通过设置不同类型的网络接口队列,来改变数据包发送的速率和优先级,从而达到流量控制的目的。
内核如果需要某个接口发送数据包,他都需要按照这个接口的qdisc排队规则发送数据包,然后尽可能多地从Qdisc中取数据包,把他们交给网络适配器的驱动模块(驱动中如果没有队列,那就直接发送到网卡队列上面去;如果驱动有队列,那就在驱动的队列中排队)。linux对接收队列控制不够好,所以一般只控制发送队列。
当在虚拟机内核中处理包后,他们通过vnic到达hypervisor,然后再被转发到vswitch(提供了虚拟机和物理网卡适配器通信的桥)。这个桥需要扮演OVN 隧道功能(这就是前面提到的虚拟Overlay Network),把来自虚拟机的数据包封装并转发到物理适配器的队列;当通过物理网卡适配器以后,他们就被转发到目的服务器端。通过物理网卡适配器被转发给虚拟网桥。虚拟网桥要扮演OVN终结者的角色,将这个数据包封装,并转发给hypervisor,然后再转发给客户机操作系统。当被客户机内核处理后,这个数据包中午转发给目标的应用程序,至此完成发送接收。
基于详细的端到端的路径分析,我们定位了可能的丢包点,可能是在vswitch中,和接收路径的客户机内核,如下分析。
在发送端,用户程序产生数据包,然后发出send系统调用将这个数据包从用户空间复制到内核空间。然后,这个数据包就被存放到了一个叫做sk_buffer的数据结构中,并且放到TX buffer中(这个程序打开的socket的TX buffer)。这个程序通过系统调用的返回值,可以知道这个发送缓冲区是否溢出,所以这个操作是无损的。
然后包从socket发送缓冲区到了Qdisc(和虚拟接口相关的)的队列。Qdisc中存放的是一系列指针,指向socket中的数据包,这些指针根据一个选定的算法来排列,一般来说就是FIFO。为了在这个过程中防止丢包,我们增加了qdisc的队列长度,使得和所有sockets的发送队列的长度是一样的,但是这种改变需要更多的内存。这个Qdisc试图把数据包发送到网卡适配器的发送队列。如果这个发送队列到达了一个阈值,这个Qdisc就停止发送啦,这个传输则被暂停,这样就防止了数据传输内核路径上面的丢包;当TX队列比阈值小后,Qdisc就又继续传输。这样,只要Qdisc的长度配置的合适的话,这个客户机内部的传输就一定是无损的。
我们的架构是基于virtio技术的,这样,虚拟适配器队列也是在客户机操作系统和底层的hypervisor中共享的。(这样就不需要一次多余的拷贝啦:))。这个virtio适配器告知hypervisor新的数据包的入队(适配器的发送队列),然后基于QEMU的hypervisor软件就把这个从虚拟适配器中的发送队列中的数据包转发到vOVN的发送队列中去。
这个qemu网络线代码包含两个组件,分别是虚拟网络设备和网络后端。他们这里的网络后端使用了netmap,把这个netmap植入了最新的qemu的版本中,修改了一些必须的bug。我们使用了一个无损的方法在虚拟网络设备和后端之间。(我分析到XEN的IO环机制在接收过程是会丢包的,点击这里)。然后这个数据包在这个网桥上面被转发,跟我们使用的一般的交换机的原理是一样的,如果这个数据包是直接转发到其他的虚拟端口,那就根据mac地址转发。如果不是,则转发到物理端口(设置了监听模式)。从这里,这个被网桥消耗的包(LOCAL模式?也不一定)被封装(由于是overlay network),然后被放到物理适配器的发送队列,之后在增强的物理网络上把这个包发送到目的端。
就像之前提到的那样,现在的虚拟交换机还是不支持流控机制的,我们的实验从多个虚拟交换机出发也验证了这一点。因此我们重新设计了VALE vSWITCH来增加了内部的流控机制,使得发送的过程完全是无损的。
NAPI 是 Linux 上采用的一种提高网络处理效率的技术,它的核心概念就是不采用中断的方式读取数据,而代之以首先采用中断唤醒数据接收的服务程序,然后使用 POLL 的方法来轮询数据。
从物理适配器接收队列过来的数据包被ovn终结桥解封装,然后被放到虚拟网桥的发送队列,然后被转发到某个虚拟机接口的接收队列。这个虚拟交换机转发过程同样也是lossy的。这个数据包然后被qemu 虚拟机监控器复制到virtio的虚拟设备。虚拟设备的接收队列是被hypervisor和虚拟机内核共享的(想起来XEN也是这么回事,但是我分析到XEN的IO环机制在接收过程是会丢包的,点击这里)。虚拟机监控器在包接收时发出notify(xen的事件通道),而虚拟机接受到一个中断。这个中断根据linux的NPIV框架来进行处理。一个软中断发出,触发接收队列的消耗。这个数据包被穿送给netif_receive_skb函数(执行ip路由和过滤器功能)处理。如果这个包是给本地协议栈的,那么他被放到目标socket的接收缓存中。如果目标缓存满了,那么这个数据包将被丢弃掉。如果是tcp协议,丢失也不必担心,但是udp则不同。我们修改了linux内核,当目标socket接收队列到达一个阈值后,这个soft中断则停止产生,那么接收也就停止。然后程序消耗了socket中的数据后,那么这个接收过程又继续。这样就保证了无损的tcp和udp sockets。
就像之前提到的那样,我们的无损虚拟交换机是从我们研究的VALE中生发而来,基于netmap架构。它给每个虚拟机一个端口,加上一个物理端口。每一个端口都有一个发送队列和一个接收队列。这个转发的过程是lossy的,因为从接收队列总是尽快的把包转发到接收队列,而不管接收队列是不是满了。如果是,则包被丢弃。
我们设计了一个算法来表示虚拟交换机的无损。每一个发送端(生产者)都和一个接收队列Ij相连接。每一个接收端(消耗者)都和一个接收队列Ok相连接。当一个包生产出来后,这个发送者检查相应的输入队列是否满了。如果是的,这个发送端就睡一会儿,然后等到有空的缓冲区后再把这个包放入发送队列然后进行转发处理然后发送到出口队列。这个转发者会检查出口队列是否有足够的空间,如果这个队列有空间,那么转发者就会把把数据包传输到出口队列,然后唤醒相应的消费者(可能在等待着新到来的数据包)。在接受端,相应的输出队列也被检查,如果不空,则消耗它中间的数据包,如果是空的,则转发程序会把把输入队列中的包转发到这个输出队列。如果真的有数据拉取(pull)过来了,那么就会被消耗。否则这个接收端就会睡一会儿直到被发送端唤醒。这个虚拟交换机被设计为双pull/push的情况,当这个发送端更快的时候,它大部分时候就在睡觉,等待空余的空间,当接收端消耗数据的时候会把它唤醒。当接收端更快的时候,这个接收端大部分时候都在睡觉,发送端有新的数据时才把接收端唤醒。这样无损操作过程的开销可以减少到最小。伪代码如下图所示:
p.s:测试和评价相关的部分,有空再补充。
[zOVNnet]http://researcher.ibm.com/researcher/files/zurich-DCR/Got%20Loss%20Get%20zOVN.pdf
[zOVN]Crisan, Daniel, et al. "Got loss?: get zOVN!." Proceedings of the ACM SIGCOMM 2013 conference on SIGCOMM. ACM, 2013.
[ovelay network]http://en.wikipedia.org/wiki/Overlay_network
[vxlan]http://en.wikipedia.org/wiki/Virtual_Extensible_LAN
http://www.networkcomputing.com/networking/network-overlays-an-introduction/d/d-id/1234011?