AWS Nitro架构简介

AWS(Amazon Web Services)Nitro架构为Amazon的云服务提供了底层的支持。Nitro架构的总体设计思想是:轻量化的hypervisor配合定制化的硬件,让用户无法区分出运行在虚拟机内和运行在裸金属上操作系统的性能差异。为了实现定制化的硬件(ASIC),Amazon和以色列的一家芯片公司——Annapurna实验室合作,并在后面将其收购,其芯片的logo就是Annapurna山(世界第十高峰)。

 

AWS Nitro架构简介

原本基于Xen架构的虚拟化系统中,服务器既要运行提供给客户的虚拟机,也要运行Xen Hypervisor,还要运行Domain0中的各种设备模拟,包括网络、存储、管理、安全和监控等功能,导致服务器中大概只有七成的资源能够提供给用户。

 

AWS Nitro架构简介

为此,Nitro项目将焦点放在这三成的虚拟化损耗上,通过定制化的硬件,将这些虚拟化损耗挪到定制的Nitro系统上,让服务器上的资源基本上都能够提供给用户。

 

AWS Nitro架构简介

Nitro系统并不是一蹴而就的,而是经过了好几代的迭代发展,从原本的Xen架构慢慢过渡过来的。原本的Xen架构中,虚拟机的设备都是由Domain0的Amazon Linux模拟和管理,这样带来的问题是:虽然Domain0功能强大,但是却臃肿庞大,而且会抢占服务器的资源。

 

AWS Nitro架构简介

经过多代发展,Nitro架构终于将虚拟机的计算(主要是CPU和内存)和I/O(主要是网络和存储)子系统分离开来,将原本一个大的计算机系统分成两部分(如下图所示):

  1. 基于Intel主板的通用服务器系统,该系统主要提供计算资源。
  2. Amazon自己定制的Nitro系统,该系统主要提供I/O资源。

两个系统之间通过PCIe总线连接到一起,如下图所示:

AWS Nitro架构简介

Nitro系统主要由三部分组成:

  1. 以PCIe卡形式呈现的Nitro卡,主要包括支持网络功能的VPC(Virtual Private Cloud)卡,支持存储功能的EBS(Elastic Block Store)、Instance Storage卡和支持系统控制的Nitro Controller卡。
  2. Nitro安全芯片,该芯片提供Hardware Root of Trust,防止运行于通用服务器上的软件对non-volatile storage进行修改,比如虚拟机的UEFI程序。
  3. 运行于通用服务器的Nitro Hypervisor,这是个基于kvm的轻量级hypervisor,主要提供CPU和内存的管理功能,不提供设备的模拟(因为所有的设备都是通过透传的方式添加到虚拟机中)。

 

由于找不到详细的资料来解释两个系统之间是怎么通过PCIe总线连接到一起的,所以这边只能做个猜测。理论上,应该可以在Intel主板上插入一个PCIe扩展槽(PCIe riser)之类的卡,然后该卡对PCIe总线进行了扩展,让PCIe总线能够以连接线的方式扩展出来(目前PCIe的标准能支持的PCIe Gen3的最长连接线只有大概20厘米,两个系统的连接线一般不止这个,所以需要进行扩展),该连接线连接到Nitro系统的Nitro Controller上,Nitro Controller再和各种类型的Nitro卡(存储、网络)连接起来,控制这个扩展出来的PCIe连接线上能够看到的PCIe资源。这样,基于Intel主板的系统能够看到的PCIe外设资源完全可以通过Nitro Controller进行控制。

 

对于支持VMX功能的虚拟化系统而言,虚拟化的损耗主要来源于VM Exit导致CPU退出到root-operation mode,hypervisor对各种VM Exit的原因进行处理。VM Exit主要来源于两个方面:

  1. 设备模拟。
  2. DMA配置和数据拷贝。
  3. 中断传递。

对于Nitro Hypervisor而言,虚拟机运行起来后将会很少发生VM Exit,一方面是因为PCI设备都能够通过基于SR-IOV进行透传,hypervisor不进行设备模拟,解决了设备模拟,DMA配置和数据拷贝触发的VM Exit;另外一方面是在中断传递方面,采用了类似论文 A Comprehensive Implementation and Evalution of Direct Interrupt Delivery 介绍的DID (Direct Interrupt Delivery)方式,极大地减少了由于中断传输触发的VM Exit。

 

DID中断传输方式对是建立在普通的外部中断和IPI不触发VM Exit(kvm中,外部中断基本是会触发VM Exit的),只有NMI才会触发VM Exit的基础上,对各种中断的传输方式进行了一定的改造。

  1. SR-IOV透传的设备中断,当Hypervisor调度运行一个vCPU的时候,需修改IOMMU的中断重映射表,将VF产生的中断直接传递给运行vCPU的CPU。当vCPU退出,hypervisor需再次修改IOMMU的中断重映射表,让VF产生的中断在host看来是NMI以确保VF产生的中断能够被Hypervisor看到(中断传递的目标CPU可能在运行其他vCPU,这个时候就需要触发VM Exit),然后通过软件注入的方式将该中断传递给目标vCPU。
  2. 模拟设备产生的中断,基本思路是将模拟设备转化为IPI中断,原来的IPI由NMI替代,由于Nitro系统中,不再有模拟设备,所以可以跳过该部分。
  3. 定时器中断,也是属于外部中断的一种,只是该外部中断的传递不会经过IOMMU的中断重映射,所以为了确保该中断能够传递到正确的vCPU上,需要对定时器的配置进行限制。即CPU在运行vCPU的时候,需要确保CPU对应的LAPIC上配置的定时器都是vCPU的,如果不止,需要转移到其他的CPU上,当CPU不运行vCPU的时候,需要将vCPU相应的定时器转移到其他CPU上,并且产生的中断类型修改为NMI。
  4. 软件注入中断,这种类型的中断需要转化为硬件的Self-IPI,这样vCPU接收到的所有中断都能够被硬件LAPIC控制器感受到,在中断处理完毕后写EOI(End-of-Interrpt)告知硬件LAPIC控制器中断已经处理完毕可以继续处理下一个中断的时候,就不用触发VM Exit进行特殊的处理。因为如果硬件LAPIC没有接收到中断,而CPU去写EOI就可能造成LAPIC状态错乱。

 

Nitro架构不仅强大(虚拟机的性能在大部分情况下和裸机的性能相差远小于%),而且特别灵活,不仅可以基于Nitro Hypervisor运行虚拟机,而且可以基于一些常用的Hypervisor(如qemu-kvm,vmware)运行虚拟机,甚至可以直接裸跑操作系统。

AWS Nitro架构简介

AWS Nitro架构简介

 

参考资料

https://aws-de-media.s3.amazonaws.com/images/AWS_Summit_2018/June7/Alexandria/Introducing-Nitro.pdf

http://www.brendangregg.com/blog/2017-11-29/aws-ec2-virtualization-2017.html

https://www.hotchips.org/hc31/HC31_T1_AWS_Nitro_Hot_Chips_20190818-2.pdf

https://www.metricly.com/aws-nitro/

https://cseweb.ucsd.edu/~yiying/cse291j-winter20/reading/Nitro.pdf

https://www.allthingsdistributed.com/2020/09/reinventing-virtualization-with-aws-nitro.html

https://d1.awsstatic.com/events/reinvent/2019/REPEAT_2_Powering_next-gen_Amazon_EC2_Deep_dive_into_the_Nitro_system_CMP303-R2.pdf

https://www.kovarus.com/blog/deep-dive-into-the-aws-nitro-system/

https://www.twosixlabs.com/running-thousands-of-kvm-guests-on-amazons-new-i3-metal-instances/

https://compas.cs.stony*.edu/~mferdman/downloads.php/VEE15_Comprehensive_Implementation_and_Evaluation_of_Direct_Interrupt_Delivery.pdf