OSv –适用于虚拟化环境的Linux二进制兼容的unikernel

2020-12-13 19:26:49

OSv最初是由Cloudius Systems(现为ScyllaDB)设计和实现的,但是目前由一小部分志愿者维护和增强。如果您从事系统编程或想学习和帮助我们改进OSv,请通过OSv Google Group与我们联系论坛。有关如何格式化和发送补丁的详细信息,请阅读此Wiki(我们不接受请求请求)。

与为大量物理机设计的传统操作系统相比,OSv是一种开放源代码的通用模块化unikernel,旨在作为虚拟机在hypervisor上安全运行单个未修改的Linux应用程序。从头开始构建,可轻松实现微服务和无服务器应用程序的部署和管理,并具有卓越的性能。

OSv被设计为按原样运行未经修改的x86-64 Linuxbinaries,这实际上使其成为Linux二进制兼容的unikernel(有关Linux ABI兼容性的更多详细信息,请阅读此文档)。特别是OSv可以运行许多托管语言运行时,包括JVM,Python 2、3,Node.JS,Ruby,Erlang以及在这些运行时之上构建的应用程序,它还可以运行以直接编译为C,C ++,Golang和Rustas本机代码的语言编写的应用程序,以及GraalVM和WebAssembly /生成的本机映像瓦斯默。

OSv可以在Firecracker上以低至15 MB的内存在〜5 ms的速度下启动.OSv可以在许多虚拟机管理程序上运行,包括QEMU / KVM,Firecracker,Xen,VMWare,VirtualBox和Hyperperkit以及开放式云(如AWS EC2,GCE和OpenStack的。

为了在OSv上运行应用程序,需要通过融合OSv内核和应用程序文件来构建映像。可以通过以下两种方式从总体上实现这一目标:

通过使用位于./scripts/build的shell脚本,该脚本从源代码构建内核并将其与应用程序文件融合在一起,或者

通过使用使用预制内核并将其与应用程序文件组合在一起的主导轴工具来生成最终图像。

如果您打算尝试以最小的努力在OSv上运行您的应用程序,则应采用capstanroute。有关介绍,请阅读此速成班。有关绞盘的更多详细信息,请阅读此更详细的文档。主导轴可以从OSv常规发行版页面自动下载预建的OSv内核文件(ovs-loader.qemu),也可以从每晚发行版回购手动下载。

如果您熟悉make和GCC工具链,并想尝试最新的OSv代码,则应该阅读自述文件的这一部分,以指导您如何设置开发环境以及构建OSv内核和应用程序映像。

我们的目标是每年发布2-3次OSv。您可以在githubalong上找到最新的版本,其中包含已发布的许多工件,包括内核和某些模块。

此外,我们已经建立了基于Travis的CI / CD管道,其中每个对master和ipv6分支的提交都触发了最新内核的完整构建,并向夜间发行版repo发布了一些工件。每次提交还触发新Docker" build工具链"的发布。镜像到Docker中心。

在OSv Wiki页面的组件中很好地解释了OSv的设计。您可以在原始USENIX论文及其演示文稿中找到更多信息。

此外,您可以在主Wiki页面以及http://osv.io/和http://blog.osv.io/上找到很多有关特定OSv组件设计的好信息。不幸的是,其中一些信息可能是已过时(尤其是在http://osv.io/上),因此,如有疑问,最好在邮件列表中询问。

没有将OSv与其他Unikernel或Linux进行比较的官方最新性能指标。通常,OSv在磁盘I / O密集型工作负载中落后于Linux,部分原因是VFS围绕读/写操作的粗粒度锁定在Redis和Memcached的性能测试中显示,在网络I / O密集型工作负载中,OSv的性能应该更好(或者至少自从Linux以来已经进步了很多)。您可以找到一些旧的" #34;在主Wiki上,http://osv.io/benchmarks以及本自述文件底部列出的一些论文。

因此OSv可能不是最适合运行MySQL或ElasticSearch,但应该为诸如微服务或无服务器的一般无状态应用程序提供相当可靠的性能(至少如某些论文所示)。

目前(截至2020年5月),未压缩的OSv内核(kernel.elf工件)的大小约为6.7 MB(压缩后约为2.7 MB)。与Linux内核相比,这并不算小,而与其他unikernels相比,它却相当大。但是,请记住,OSv内核(为unikernel)提供以下Linux库的功能子集(请参阅Linux主机上的近似大小):

实际上链接了等效的静态版本的libstdc ++。so.6-整个存档,因此无需在映像中添加libstdc ++。so.6(无论是否需要它),任何C ++应用程序都可以运行。 ZFS实现,理论上以后可以将其提取为单独的库。这样做的目的是说明将OSv内核大小与Linux内核大小进行比较并不合理。

带有FS且已关闭网络的只读FS的OSv在Firecracker上的启动速度约为5毫秒,而在microvm机器上的QEMU上的启动速度甚至约为3毫秒。但是,通常,启动时间将取决于许多因素,例如虚拟机监控程序,包括单个半虚拟设备的设置,文件系统(ZFS,ROFS或RAMFS)以及一些启动参数。请注意,默认情况下,OSv映像使用ZFS文件系统构建。

例如,如今,Firecracker上ZFS映像的启动时间约为40毫秒,常规QEMU的启动时间约为200毫秒。而且,较新版本的QEMU(> = 4.0)通常更快地启动。在PVH / HVM模式下(即直接内核启动,通过run.py的-k选项启用)在QEMU上引导应该总是更快,因为OSv是在64位长模式下直接调用的。请参阅此Wiki,以简要了解OSv支持的引导方法。

--console serial-这将禁用初始化缓慢且可在QEMU上节省60-70毫秒的VGA控制台

--nopci-这会禁用PCI设备的枚举,尤其是在我们不知道PCI设备存在的情况下(带有microvm或Firecracker的QEMU)并且可以缩短10到20毫秒

--redirect = / tmp / out-如果应用程序日志很多,写入控制台会严重影响性能(30-40%),因此将标准输出和错误重定向到文件可能会大大提高性能

./scripts/run.py -e'-bootchart / hello' OSv v0.54.0-197-g1f0df4e4eth0:192.168.122.15磁盘读取(实模式):25.85ms,(+ 25.85ms)解压缩lzloader .elf:45.11ms,(+ 19.26ms)TLS初始化:45.72ms,(+ 0.61ms).init函数:47.61ms,(+ 1.89ms)SMP启动:48.08ms,(+ 0.47ms)VFS初始化:50.99ms ,(+ 2.91ms)网络初始化:51.12ms,(+ 0.14ms)pvpanic完成:51.25ms,(+ 0.13ms)pci枚举:61.55ms,(+ 10.29ms)驱动程序探测:61.55ms,(+ 0.00ms)已加载驱动程序:135.91ms,(+ 74.36ms)已安装ROFS:136.98ms,(+ 1.07ms)总时间:138.16ms,(+ 1.18ms)Cmdline:/ hello来自C代码的Hello

OSv至少需要15 M的内存才能运行Hello World应用程序。即使是2年前的一半,但与其他unikernels相比,它仍然很多。我们计划通过减小内核大小,向L1 / L2内存池添加自调整逻辑,以及使应用程序线程使用延迟分配的堆栈来进一步降低此数量。

OSv带有大约130个单元测试,该单元测试在每次提交时执行并在ScyllaDB服务器上运行。在测试/子树下还有一些额外的测试,目前还没有自动执行。

./scripts/build check#创建ZFS测试映像并在QEMU上运行所有测试。/scripts/buildcheck fs = rofs#创建ROFS测试映像并在QEMU上运行所有测试。/scripts/buildimage = tests&& \#创建ZFS测试映像并在Firecracker上运行所有测试。/scripts/test.py-p firecracker./scripts/build image = tests& \#创建ZFS测试映像并在QEMU上运行所有测试./scripts/test.py -p qemu_microvm#使用microvm机器

此外,还有一个自动化测试框架,可用于运行约30个真实应用程序,其中一些使用ab或wrk工具承受压力。目的是捕获单元测试可能遗漏的任何回归。

OSv只能在64位x86 Linux发行版上构建。请注意,这意味着" x86_64"或" amd64"版本,而不是32位" i386"版。

为了构建OSv内核,您需要一台具有Linux发行版的物理或虚拟机,GCC工具链以及所有必需的软件包和库。设置它的最快方法是使用OSv附带的Docker文件。您可以使用它们来构建自己的Docker映像,然后启动它以构建OSv内核或在其中的OSv上运行应用程序。主Docker文件依赖于Ubuntu或Fedora的预构建基础Docker映像,该映像在每次提交时都会发布到DockerHub。这将加快构建最终映像的速度,因为所有必需的软件包都应该已经是基本映像的一部分。

另外,您可以手动克隆OSv存储库,并使用setup.py安装所有必需的软件包和库,只要它支持Linux发行版,并且您的计算机上同时安装了git和python 3:

setup.py可以识别并安装许多Linux发行版的软件包,包括Fedora,Ubuntu,Debian,LinuxMint和RedHat(科学Linux,NauLinux,CentOS Linux,Red Hat Enterprise Linux,Oracle Linux)。请注意,我们仅积极维护和测试Ubuntu和Fedora,因此您使用其他发行版的里程可能会有所不同。实际上,Docker文件内部使用setup.py来获得相同的结果。

如果您喜欢在IDE中工作,我们建议您按照本Wiki页中的说明设置Eclipse CDT,或者建议使用JetBrains的CLion进行设置,以使用本指南中所述的所谓编译DB来与OSv makefile一起使用。

构建OSv就像使用shell脚本./scripts/build一样容易,该脚本通过委派给主要的makefile来构建内核,并使用诸如./scripts/module.py之类的Python脚本来构建应用程序并将其与将内核放入最终映像中,该映像位于./build/release/usr.img(或通常为./build/$(arch)/usr.img)。请注意,构建应用程序并不一定意味着在许多情况下都是从源代码构建应用程序二进制文件将使用shell脚本./scripts/manifest_from_host.sh位于Linux构建计算机上并从Linux复制计算机复制(有关详细信息,请参见此Wiki页面)。

#创建命令行和REST API服务器随附的默认映像./scripts/build#使用本机示例应用程序创建映像./scripts/build -j4 fs = rofs image = native-example#使用Spring Boot应用程序使用Java创建映像10 JRE./scripts/build JAVA_VERSION = 10 image = openjdk-zulu-9-spring-boot-example以上#使用' ls'创建映像/scripts/manifest_from_host.sh -w ls&& ./scripts/build --append-manifest#创建测试图像并在其中运行所有测试./scripts/build check#清理构建树./scripts/build clean

命令nproc将自动计算make和./scripts/build的作业/线程数。或者,环境变量MAKEFLAGS可以如下导出:

./scripts/build以qcow2格式创建映像build / last / usr.img。要将此映像转换为其他格式,请使用./scripts/converttool,它可以将映像转换为vmdk,vdi或raw格式。例如:

默认情况下,OSv内核是针对x86_64体系结构构建的,但也可以通过添加arch参数来为ARM构建一个内核,如下所示:

此时,仅Fedora以及相关的aarch64 gcc和库支持交叉编译OSv的aarch64版本。二进制文件可以使用./scripts/download_fedora_aarch64_packages.py脚本进行下载。请注意,简单的" hello world"该应用程序应该可以正常运行,但是由于缺少志愿者,总体上OSv的ARM部分并未得到很好的维护和测试,无法像x86_64一样进行测试。此外,同一简单示例可以在启用KVM加速的Raspberry PI 4上的QEMU上成功运行。有关aarch64端口的更多信息,请阅读此Wiki页面。

在引导过程结束时,OSv动态链接器从文件系统中将应用程序ELF和所有相关库加载到映像的一部分磁盘上。默认情况下,由./scripts/build构建的映像包含一个格式化为ZFS的磁盘,您可以在此处了解更多信息。ZFS是一个出色的读写文件系统,如果要在OSv上运行MySQL,它可能是一个完美的选择。但是,如果您想运行无状态应用程序,则可能会过失,在这种情况下,您可以考虑使用只读FS。最后,您还可以让OSv从RAMFS读取应用程序二进制文件,在这种情况下,文件系统将作为内核ELF的一部分嵌入。通过将./scripts/build的参数fs设置为以下三个值之一(zfs,rofs或ramfs),可以指定要构建映像磁盘的文件系统。

此外,可以安装NFS文件系统和新实现的Virtio-FS文件系统,该文件系统最近已转换为可作为模块插入的共享库。可以通过添加适当的条目/ etc / fstab或通过传递启动参数来设置NFS和Virtio-FS挂载,如本提交注释中所述。另外,最近对OSv进行了增强,使其能够从Virtio-FS文件系统启动。

默认情况下,run.py在KVM下运行OSv,具有4个vCPU和2 GB内存。您可以通过将相关参数传递给run.py来控制这些和其他数十个。有关如何使用脚本的详细信息,请运行./scripts/run.py --help。

run.py可以在QEMU / KVM,Xen和VMware上运行OSv映像。如果在KVM下运行,则可以通过按Ctrl + A X终止。

或者,您可以使用./scripts/firecracker.py在Firecracker上运行OSv。如果缺少,此脚本会自动下载Firecracker二进制文件,并接受大量参数,例如ot vCPU数,内存名称与run.py完全相同。您可以从此Wiki了解有关在Firecracker上运行OSv的更多信息。

请注意,为了在QEMU或Firecracker上的Linux上以最佳性能运行OSv,您需要启用KVM(这仅在物理Linux计算机,EC2" bare metal"(i3)实例或支持启用KVM的嵌套虚拟化)。验证KVM是否已启用的最简单方法是检查/ dev / kvm是否存在,并且您的用户帐户可以对其进行读写。将用户添加到kvm组中可能是必要的,例如所以:

有关构建和运行JVM,Node.JS,Python和其他托管运行时以及Rust,Golang或C / C ++ appson OSv的更多信息,请阅读此Wiki页面。有关可构建和运行的各种示例应用程序的更多信息。 OSv,请阅读osv-apps回购自述文件。

默认情况下,run.py在用户网络/ SLIRP开启的情况下启动OSv。要在性能更高的外部网络启动时启动OSv,您需要启用-n和-v选项,如下所示:

-v用于提供更好性能的KVM虚拟主机,其设置需要Tap设备,因此我们使用sudo。

默认情况下,OSv会生成类似dhcpd的线程,该线程会自动配置虚拟NIC。可以通过配置如下网络来在OSv内完成静态配置:

最后,请注意OSv的master分支仅实现网络堆栈的IPV4子集,如果需要IPV6,请从ipv6分支构建或使用发布到每晚发行版repo的IPV6内核。

可以跟踪和分析OSv内核和应用程序; 有关更多详细信息,请阅读此Wiki OSv带有管理/监视REST API服务器; 有关更多详细信息,请阅读此维基页面。 还有更轻量的监视REST API模块,它实际上是前一个模块的只读子集。 如果您想了解有关OSv的更多信息或提出问题,请在OSv Google Group论坛上与我们联系。您也可以在Twitter上关注我们。