文章首发于我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

作为一个技术人,保持对技术的敏感是必要的,尤其是在互联网这个行业,昨天还觉得移动互联网挺酷炫的,今天就被人工智能这波潮流给掩盖掉了锋芒,泯然众人矣。虽然我们不一定要赶时髦,踏踏实实做好技术才是好的,但保持这样一份好奇心,也许会让我们的技术之路走得更加顺畅一点。

对于云计算这个领域,虽然早已是陈词滥调,但新瓶装旧酒,总会玩出很多新鲜的花样。作为一个没什么经验的初学者,我斗胆预测一下 2018 年云计算领域的几大技术趋势,仅供参考。

混合云


混合云其实叫嚣了很多年,但一直没有得到真正的应用,现在大部分企业和个人还是部署公有云和私有云为主,随着市场的增长和用户需求的增加,尤其是对云安全这块的需求,相信在 2018 年会有众多客户将业务迁移到混合云上。公有云市场的一些大公司,像阿里云,腾讯云会大力布局其混合云市场,而私有云市场则会更多选择与公有云大公司合作来布局自己的混合云市场,另外,像 zstack 这样的混合云开源技术框架会得到较多青睐,兴许可以成为下一个 OpenStack。

微服务


2014 年,AWS 推出了 serverless (无服务器)计算服务 Lambda,微服务便是在这样一种模式下提出的一种架构设计思想。此后几年各大互联网公司都在引入微服务的设计思想,应用在自家的业务产品中。可以说,微服务架构设计得好,不管是开发测试,还是运维管理都会大大提升效率和增强产品的可维护性和可扩展性。2018 年,微服务将会引发一波小高潮。很多大公司会开放他们的微服务设计框架,及相关的开源项目。

kubernetes( k8s ) 容器编排


容器技术现在基本上已经成为各大互联网公司的标配,随着部署的容器应用的增多,容器云的编排与管理已经成了不得不面对的问题。k8s 的强势崛起,在短短时间之内就刮起一阵旋风,令 docker 家族闻风丧胆,最终不得不缴械投降,2018 年,k8s 会得到井喷式应用。

雾计算


雾计算,或者边缘计算,在学术界已经不算什么新鲜词了,但在工业界还少有耳闻,但其实 cisco 和一些物联网公司早已开发出自己的雾计算产品,并大量应用在网络边缘的计算设备中。据我所知的,智云这家公司早已推出自己的雾计算平台,并应用在很多物联网项目中,大公司中,百度在 2018 年年初也率先推出了自己的雾计算项目「智能边缘」,旨在通过提供 “IoT Edge SDK” 组件的方式进行数据的本地处理,结合 AI 技术,为用户打造实时响应,智能推断,安全可靠的服务体验。相信在 2018 年会有更多的雾计算产品出现,我们拭目以待吧。

以上就是我对 2018 年云计算这个领域技术趋势的大致预测,预测本身就代表着不确定性,但保持对新技术的敏感性,能让我们提前做一些准备,毕竟作为技术人,终身学习是最基本的职业素养。

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。

文章首发于我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

1. 什么是 vhost-user

在 vhost 的方案中,由于 vhost 实现在内核中,guest 与 vhost 的通信,相较于原生的 virtio 方式性能上有了一定程度的提升,从 guest 到 kvm.ko 的交互只有一次用户态的切换以及数据拷贝。这个方案对于不同 host 之间的通信,或者 guest 到 host nic 之间的通信是比较好的,但是对于某些用户态进程间的通信,比如数据面的通信方案,openvswitch 和与之类似的 SDN 的解决方案,guest 需要和 host 用户态的 vswitch 进行数据交换,如果采用 vhost 的方案,guest 和 host 之间又存在多次的上下文切换和数据拷贝,为了避免这种情况,业界就想出将 vhost 从内核态移到用户态。这就是 vhost-user 的实现。

2 vhost-user 的实现


vhost-user 和 vhost 的实现原理是一样,都是采用 vring 完成共享内存,eventfd 机制完成事件通知。不同在于 vhost 实现在内核中,而 vhost-user 实现在用户空间中,用于用户空间中两个进程之间的通信,其采用共享内存的通信方式。

vhost-user 基于 C/S 的模式,采用 UNIX 域套接字(UNIX domain socket)来完成进程间的事件通知和数据交互,相比 vhost 中采用 ioctl 的方式,vhost-user 采用 socket 的方式大大简化了操作。

vhost-user 基于 vring 这套通用的共享内存通信方案,只要 client 和 server 按照 vring 提供的接口实现所需功能即可,常见的实现方案是 client 实现在 guest OS 中,一般是集成在 virtio 驱动上,server 端实现在 qemu 中,也可以实现在各种数据面中,如 OVS,Snabbswitch 等虚拟交换机。

如果使用 qemu 作为 vhost-user 的 server 端实现,在启动 qemu 时,我们需要指定 -mem-path 和 -netdev 参数,如:

1
2
3
$ qemu -m 1024 -mem-path /hugetlbfs,prealloc=on,share=on \
-netdev type=vhost-user,id=net0,file=/path/to/socket \
-device virtio-net-pci,netdev=net0

指定 -mem-path 意味着 qemu 会在 guest OS 的内存中创建一个文件,share=on 选项允许其他进程访问这个文件,也就意味着能访问 guest OS 内存,达到共享内存的目的。

-netdev type=vhost-user 指定通信方案,file=/path/to/socket 指定 socket 文件。

当 qemu 启动之后,首先会进行 vring 的初始化,并通过 socket 建立 C/S 的共享内存区域和事件机制,然后 client 通过 eventfd 将 virtio kick 事件通知到 server 端,server 端同样通过 eventfd 进行响应,完成整个数据交互。

3 几个例子


开源社区中实现了一个项目 Vapp,主要是用来测试 vhost-user 的 C/S 模式的,github 地址如下:
https://github.com/virtualopensystems/vapp.git

使用:

1
2
3
4
5
6
7
$ git clone https://github.com/virtualopensystems/vapp.git
$ cd vapp
$ make
// 运行 server 端
$ ./vhost -s ./vhost.sock
// 运行 client 端
$ ./vhost -q ./vhost.sock

通过以上步骤,就可以启动 vhost-user 的 C/S 模式。

另外还有例子就是集成在虚拟交换机 Snabbswitch 上的 vhost-user,通过以下方式获得 vhost-user 分支:

1
2
3
4
5
$ git clone -b vhostuser --recursive https://github.com/SnabbCo/snabbswitch.git
$ cd snabbswitch
$ make
测试:
$ sudo src/snabbswitch -t apps.vhost.vhost_user

还有例子就是 qemu 上的实现,这也是最原早的实现,同样通过以下方式来获得使用:

1
2
3
4
5
$ git clone -b vhost-user-v5 https://github.com/virtualopensystems/qemu.git
$ mkdir qemu/obj
$ cd qemu/obj/
$ ../configure --target-list=x86_64-softmmu
$ make -j

除此之外,还有很多的实现,如 OVS 和 DPDK 上都有实现,这实际上是集成了 vhost-user 的通用 API。

4 总结


virtio,vhost,vhost-user 是基于场景和性能而提出的三种 guest 和 host 之间的通信方案,三种方案,各有优劣。
vhost-user 用在很多数据面之上的进程间通信,效率高。

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。

vhost 简介

文章首发于我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

1. 什么是 vhost


vhost 是 virtio 的一种后端实现方案,在 virtio 简介中,我们已经提到 virtio 是一种半虚拟化的实现方案,需要虚拟机端和主机端都提供驱动才能完成通信,通常,virtio 主机端的驱动是实现在用户空间的 qemu 中,而 vhost 是实现在内核中,是内核的一个模块 vhost-net.ko。为什么要实现在内核中,有什么好处呢,请接着往下看。

2. 为什么要用 vhost


在 virtio 的机制中,guest 与 用户空间的 Hypervisor 通信,会造成多次的数据拷贝和 CPU 特权级的上下文切换。例如 guest 发包给外部网络,首先,guest 需要切换到 host kernel,然后 host kernel 会切换到 qemu 来处理 guest 的请求, Hypervisor 通过系统调用将数据包发送到外部网络后,会切换回 host kernel , 最后再切换回 guest。这样漫长的路径无疑会带来性能上的损失。

vhost 正是在这样的背景下提出的一种改善方案,它是位于 host kernel 的一个模块,用于和 guest 直接通信,数据交换直接在 guest 和 host kernel 之间通过 virtqueue 来进行,qemu 不参与通信,但也没有完全退出舞台,它还要负责一些控制层面的事情,比如和 KVM 之间的控制指令的下发等。

3. vhost 的数据流程


下图左半部分是 vhost 负责将数据发往外部网络的过程, 右半部分是 vhost 大概的数据交互流程图。其中,qemu 还是需要负责 virtio 设备的适配模拟,负责用户空间某些管理控制事件的处理,而 vhost 实现较为纯净,以一个独立的模块完成 guest 和 host kernel 的数据交换过程。

vhost 与 virtio 前端的通信主要采用一种事件驱动 eventfd 的机制来实现,guest 通知 vhost 的事件要借助 kvm.ko 模块来完成,vhost 初始化期间,会启动一个工作线程 work 来监听 eventfd,一旦 guest 发出对 vhost 的 kick event,kvm.ko 触发 ioeventfd 通知到 vhost,vhost 通过 virtqueue 的 avail ring 获取数据,并设置 used ring。同样,从 vhost 工作线程向 guest 通信时,也采用同样的机制,只不过这种情况发的是一个回调的 call envent,kvm.ko 触发 irqfd 通知 guest。

4. 总结


vhost 与 kvm 的事件通信通过 eventfd 机制来实现,主要包括两个方向的 event,一个是 guest 到 vhost 方向的 kick event,通过 ioeventfd 实现;另一个是 vhost 到 guest 方向的 call event,通过 irqfd 实现。

代码分析整个通信的流程:
http://royluo.org/2014/08/22/vhost/

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。

文章首发于我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

1
2
本文是一篇翻译,翻译自:
https://software.intel.com/en-us/blogs/2015/06/12/user-space-networking-fuels-nfv-performance,文章有点老了,15年写的,但是文章总结了一些用户态的协议栈,很有学习参考的意义。

用户态协议栈


如今,作为一个网络空间的软件开发人员是非常激动人心的,因为工程师的角色随着这个世界的规则在逐渐发生改变。

过去这 15 年来,人们对高性能网络做了很多努力,网络模型也发生了很多改变,起初,数据包的收发都要推送到内核才能完成,现在,不用内核态的参与也可以完成。这种改变的背后主要是在解决以下的几个问题:1)用户态和内核态上下文切换的开销;2)软硬中断的开销;3)数据拷贝的开销等等。

最近,很多人在讨论 mTCP——一个实现了用户态协议栈的开源库,这种技术在很大程度上就颠覆了传统的网络模型,使得网络收发包的效率大大提升。它充分利用了 CPU 的亲和性,共享内存,批处理等技术来实现高效的 I/O 事件。与之类似的技术也相继被提出。

实验表明,mTCP 这种用户态协议栈,相较原生的内核协议栈,在处理多种流行的应用时的性能得到较大提升,如 SSLShader 提升了 33%,lighttpd 提升了 320%。

软件形态的改变离不开硬件的革新。由以前的单核系统到如今多核系统的性能扩展,直接导致了网络软件架构的改变。例如,以前内核所做的所有功能和处理,包括网络驱动程序,现在都可以被直接放到用户空间中来实现,应用程序可以直接访问底层的 NUMA 结构,利用 CPU 的亲和性,以及多核特性并行处理任务。这种设计避免了上下文之间的切换开销,可以显著降低数据传输的延迟和 CPU 使用,同时提高吞吐量和带宽。另外,提供一种运行到完成(run-to-completion)的模型能够让不同的核独立并行地完成不同的任务。

随着网络的发展,我们现在看到了大量的开源项目,都在将内核协议栈移到用户空间来做。它们的做法存在一些区别,像 mTCP,它的协议栈是从零开始开发的,而其他很多项目则是基于 FreeBSD 的来做,这主要是因为 FreeBSD 的协议栈具有 “最健壮的网络协议栈的声誉”,此外,很多存储解决方案也是采用的 FreeBSD 来作为其核心操作系统。当然,Linux 协议栈也是可以采用的。

这些用户态协议栈怎么做到绕过内核的,这就离不开 DPDK 的支持。利用 DPDK,用户态协议栈可以创建一个中断来将数据包从 NIC 的缓冲区直接映射到用户空间,然后利用协议栈的特性来管理 TCP/IP 数据包的处理和传输。

DPDK 还可以作为一些 vSwitch(虚拟交换机)的加速器,这些 vSwitch 包含 OpenFlow 协议的完整实现,以及与 OpenStack Neutron 的整合。

下面,我们收集了一些发现的开源项目,无论你决定使用一个 vSwitch 还是一个完整的网络协议栈,网络开发人员都有很多选择,可以将应用程序移到用户空间,并在多核系统上扩展性能。

DPDK-Enabled vSwitch:


OVS

Open vSwitch 是一个多核虚拟交换机平台,支持标准的管理接口和开放可扩展的可编程接口,支持第三方的控制接入。
https://github.com/openvswitch/ovs

Lagopus

Lagopus 是另一个多核虚拟交换的实现,功能和 OVS 差不多,支持多种网络协议,如 Ethernet,VLAN,QinQ,MAC-in-MAC,MPLS 和 PBB,以及隧道协议,如 GRE,VxLan 和 GTP。
https://github.com/lagopus/lagopus/blob/master/QUICKSTART.md

Snabb

Snabb 是一个简单且快速的数据包处理工具箱。
https://github.com/SnabbCo/snabbswitch/blob/master/README.md

xDPd

xDPd 是一个多平台,多 OpenFlow 版本支持的开源 datapath,主要专注在性能和可扩展性上。
https://github.com/bisdn/xdpd/blob/stable/README

从零开发的用户空间协议栈套件


mTCP

mTCP 是一个针对多核系统的高可扩展性的用户空间 TCP/IP 协议栈。
https://github.com/eunyoung14/mtcp/blob/master/README

Mirage-Tcpip

mirage-tcpip 是一个针对 MirageOS 这种 “库操作系统” 而开发的一个用户态网络协议栈,开发的语言是 OCaml。
https://github.com/mirage/mirage-tcpip

IwIP

IwIP 针对 RAM 平台的精简版的 TCP/IP 协议栈实现。
http://git.savannah.gnu.org/cgit/lwip.git/tree/README

移植版的用户空间协议栈套件


Arrakis

针对多核系统的用户空间 OS,移植于 IwIP。
https://github.com/UWNetworksLab/arrakis/blob/master/README_ARRAKIS

libuinet

用户空间的 TCP/IP 协议栈,移植于 FreeBSD。
https://github.com/pkelsey/libuinet/blob/master/README

NUSE (libos)

一个基于 Linux 的库操作系统,移植于 Linux。
https://github.com/libos-nuse/net-next-nuse/wiki/Quick-Start

OpenDP

一个针对 DPDK TCP/IP 协议栈的数据面,移植于 FreeBSD。
https://github.com/opendp/dpdk-odp/wiki

OpenOnload

一个高性能的用户态协议栈,移植于 IwIP。
http://www.openonload.org/download/openonload-201205-README.txt

OSv

一个针对虚拟机的开源操作系统。移植于 FreeBSD。
https://github.com/cloudius-systems/osv/blob/master/README.md

Sandstorm

一个针对个人服务器安全的开源网络平台,移植于 FreeBSD。
https://github.com/sandstorm-io/sandstorm/blob/master/README.md

总结


1、这篇文字的亮点在于总结了当前阶段业界出现的一些用户空间协议栈,对于文章标题提到的 NFV 在文中则只字未提,但其实意思也很明了了。用户空间的协议栈是随着硬件技术的发展,以及新鲜应用场景应运而生的,换句话说,对于像 NFV 这种对性能要求比较高的场景,采用用户态的协议栈是比较合适的。

2、文中是 2015 年写的,这意味着到现在为止,肯定出现了很多比上面总结还要多的方案,其中比较出名的有 SeaStar 和 腾讯开源的 F-Stack,后面找机会再进行详述,敬请期待吧。

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。

文章首发于我的公众号「Linux云计算网络」,欢迎关注,第一时间掌握技术干货!

Linux 是一个非常庞大的系统结构,模块众多,各个模块分工合作,共同运作着各自的任务,为 Linux 这个大家庭贡献着自己的力量。

Linux 网络子系统


其中,网络子系统是一个较为复杂的模块,如下图是 Linux 网络子系统的体系结构,自顶向下,可以分应用层、插口层(或协议无关层)、协议层和接口层(或设备驱动层),这个层级关系也分别对应着我们所熟悉的 OSI 七层模型(物理层、数据链路层、网络层、传输层、会话层、表示层和应用层)。

Linux 所有用户态的应用程序要访问链接内核都要依赖系统调用,这是内核提供给用户态的调用接口,这通常是由标准的 C 库函数来实现的。对于网络应用程序,内核提供了一套通用的 socket 系统调用的接口。

插口层,也叫协议无关层,它屏蔽了协议相关的操作,不论是什么协议(UDP,TCP),都提供一组通用的函数接口,也就是 socket 的实现。

协议层,用于实现各种具体的网络协议族,包括 TCP/IP,OSI 和 Unix 域的实现,每个协议族都包含自己的内部结构,例如,对于 TCP/IP 协议族,IP 是最底层,TCP 和 UDP 层在 IP 层的上面。

接口层,包括了通用设备接口,和网络设备通信的设备驱动程序,其中,包串口使用的 SLIP 驱动程序以及以太网使用的以太网驱动程序,以及环回口使用的都是这一层的设备。它对上提供了协议与设备驱动通信的通用接口,对下也提供了一组通用函数供底层网络设备驱动程序使用。具体的细节后面再开文章详细讲述。

以上是从分层的体系结构来看,下面从数据传输的角度来说说,一个数据包是如何依赖这些层次关系被发送/接收的。

首先,数据的发送过程,应用层组织好待发送的数据包,执行系统调用进入内核协议栈,按照层次关系分别进行包头的封装,如到达传输层,封装 TCP/UDP 的包头,进入网络层封装 IP 包头,进入接口层封装 MAC 帧,最后借助驱动将数据包从网卡发送出去。

然后,数据的接收过程正好与发包过程相反,是一个拆包的过程。接口层借助网卡 DMA 硬件中断感知数据包的到来,拆解包头,识别数据,借助软中断机制告知上层进行相应的收包处理,最终用户态执行系统调用接收数据包。

继续细化这个过程,其内部在实现上都是通过具体的数据结构来完成每一层的过渡的,譬如说,应用层和内核之间通过 struct sock 结构实现协议无关的接口调用进行交互,传输层提供 struct proto 的结构来支持多种协议,网络层通过 struct sk_buff 来传递数据,接口层定义 struct net_device 来完成和驱动程序的交互。

Linux 网络体系结构还是比较博大精深的,尤其是这套自顶向下的分层设计方式对很多技术都有借鉴意义。更具体的函数调用和数据收发过程,后面的文章再进行讲述,敬请期待。

总结


Linux 网络子系统的分层模型,数据收发过程,以及核心数据结构。

PS:文章未经我允许,不得转载,否则后果自负。

–END–

欢迎扫👇的二维码关注我的微信公众号,后台回复「m」,可以获取往期所有技术博文推送,更多资料回复下列关键字获取。