AWS爆竹是如何运作的:深度潜水(2019年)

2020-05-02 17:58:50

任何推动像AWS Lambdanan这样的技术的东西都需要非常快。它需要是安全的。虽然AWS本可以采用现有技术,但为了满足这两个主要要求,他们选择了构建新的“鞭炮”(Firecracker),既快速(它可以在125ms内引导Linux并开始执行用户空间进程)又安全,它使用硬件虚拟化等技术将一个Lambda环境与另一个环境隔离开来。在这篇文章中,我们将深入探讨如何……。

虽然阅读大量源代码并弄清楚引擎盖下发生的事情当然很有趣,但这不如启动您最喜欢的编辑器并在Linux下创建一个轻量级虚拟机环境那么有趣。使用Sparkler,将构建一个虚拟机监视器(VMM)来管理虚拟机,同时为其运行的虚拟机提供特定的环境。我们还将编写一个在虚拟机内部运行的小型“操作系统”。VMM模拟..。

如果您想了解KVM是如何工作的,同时熟悉示例代码,我建议您阅读这篇关于Sparkler的文章。

运行未经修改的操作系统,特别是源代码不可用的操作系统,意味着虚拟机必须非常类似于真实的PC。QEMU或Virtual Box确实使用KVM来尽可能加快来宾速度,但它们也使用BIOS例程、各种传统设备和外围设备(如显卡、声卡和存储卡)来模拟真实的PC。这就是为什么很容易运行现成的MS-DOS、Microsoft Windows或二进制Linux发行版(如Fedora或Ubuntu)的原因。

但是,对于这些传统设备和其他设备,KVM直接对它们的支持非常有限。此外,当操作系统引导时,引导加载程序通常依赖BIOS例程来处理屏幕、键盘和磁盘等硬件。例如,QEMU使用SeaBIOS作为其BIOS固件的选择,并且附带SeaBIOS。如果没有BIOS例程,它就不是一台真正的PC,这将阻止它运行现成的操作系统。

最重要的收获是,有很多遗留代码,如BIOS和成熟外围设备的仿真,在设计为尽可能接近地仿真PC的虚拟化系统中,这些代码相对非常慢。

当PC启动时,CPU处于实模式或16位模式。BIOS运行开机自检或开机自检,将引导加载程序从指定的引导设备读取到RAM中的设置位置,并将控制权移交给它。引导加载程序通常使用BIOS例程来显示文本、读取磁盘、获取系统信息等。

事实证明,Linux内核根本不需要BIOS例程。执行此操作的是引导加载程序。Linux有所谓的“引导协议”,它告诉引导加载程序或引导时存在的任何其他程序,如何布局内核和RAM中的支持数据结构,以及如何将控制权传递给内核。对于x86体系结构,引导协议可用于实模式、32位和64位模式。

因此,就像我们将监控程序二进制文件加载到分配的客户内存中一样,Firecracker加载Linux内核,按照Linux内核引导协议设置所需的数据结构,如初始栈、命令行参数。请参见Firecracker Git Repo中的以下文件:

这样就不需要在引导过程中加载任何BIOS例程。这通过消除启用引导加载程序或根本不需要BIOS例程所需的所有复杂性,简化了虚拟机的设计。

在小型Sparkler监视器程序中,也没有使用任何BIOS例程。另外,因为根本没有BIOS。例如,printstr例程使用out x86指令输出字符,这会导致VM退出。这些出口由Spakler程序处理,该程序使用putc()库函数将字符显示到终端上。类似的事情也发生在“爆竹”中。通过内存映射为Linux内核设置了一个虚拟串行控制台.。

“爆竹”的另一个聪明之处在于,它运行Linux内核的虚拟机只有很少的设备。x86上的Linux假定存在中断控制器和间隔计时器。这些都是非常基本的,因为CPU没有内置这些。虽然可以在VMM中模拟这些设备,但KVM提供了一种更好的替代方法。它能够在内核中为您模拟它们。这是件大事。请记住,只要没有VM.。

如果您查看由Firecracker模拟的PS/2键盘控制器的源代码,您会注意到它非常稀疏,并且它只实现了一个主函数rigerctrl_alt_del(),这非常不言而喻。

VirtIO需要更多的解释。真正的硬件设备有各种各样的怪癖,而且编程相当复杂