AWS(Amazon Web Services)Nitro架構為Amazon的雲服務提供了底層的支持。Nitro架構的總體設計思想是:輕量化的hypervisor配合定製化的硬體,讓用戶無法區分出運行在虛擬機內和運行在裸金屬上作業系統的性能差異。為了實現定製化的硬體(ASIC),Amazon和以色列的一家晶片公司——Annapurna實驗室合作,並在後面將其收購,其晶片的logo就是Annapurna山(世界第十高峰)。
原本基於Xen架構的虛擬化系統中,伺服器既要運行提供給客戶的虛擬機,也要運行Xen Hypervisor,還要運行Domain0中的各種設備模擬,包括網絡、存儲、管理、安全和監控等功能,導致伺服器中大概只有七成的資源能夠提供給用戶。
為此,Nitro項目將焦點放在這三成的虛擬化損耗上,通過定製化的硬體,將這些虛擬化損耗挪到定製的Nitro系統上,讓伺服器上的資源基本上都能夠提供給用戶。
Nitro系統並不是一蹴而就的,而是經過了好幾代的迭代發展,從原本的Xen架構慢慢過渡過來的。原本的Xen架構中,虛擬機的設備都是由Domain0的Amazon Linux模擬和管理,這樣帶來的問題是:雖然Domain0功能強大,但是卻臃腫龐大,而且會搶佔伺服器的資源。
經過多代發展,Nitro架構終於將虛擬機的計算(主要是CPU和內存)和I/O(主要是網絡和存儲)子系統分離開來,將原本一個大的計算機系統分成兩部分(如下圖所示):
基於Intel主板的通用伺服器系統,該系統主要提供計算資源。
Amazon自己定製的Nitro系統,該系統主要提供I/O資源。
兩個系統之間通過PCIe總線連接到一起,如下圖所示:
Nitro系統主要由三部分組成:
以PCIe卡形式呈現的Nitro卡,主要包括支持網絡功能的VPC(Virtual Private Cloud)卡,支持存儲功能的EBS(Elastic Block Store)、Instance Storage卡和支持系統控制的Nitro Controller卡。
Nitro安全晶片,該晶片提供Hardware Root of Trust,防止運行於通用伺服器上的軟體對non-volatile storage進行修改,比如虛擬機的UEFI程序。
運行於通用伺服器的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主要來源於兩個方面:
對於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的基礎上,對各種中斷的傳輸方式進行了一定的改造。
SR-IOV透傳的設備中斷,當Hypervisor調度運行一個vCPU的時候,需修改IOMMU的中斷重映射表,將VF產生的中斷直接傳遞給運行vCPU的CPU。當vCPU退出,hypervisor需再次修改IOMMU的中斷重映射表,讓VF產生的中斷在host看來是NMI以確保VF產生的中斷能夠被Hypervisor看到(中斷傳遞的目標CPU可能在運行其他vCPU,這個時候就需要觸發VM Exit),然後通過軟體注入的方式將該中斷傳遞給目標vCPU。
模擬設備產生的中斷,基本思路是將模擬設備轉化為IPI中斷,原來的IPI由NMI替代,由於Nitro系統中,不再有模擬設備,所以可以跳過該部分。
定時器中斷,也是屬於外部中斷的一種,只是該外部中斷的傳遞不會經過IOMMU的中斷重映射,所以為了確保該中斷能夠傳遞到正確的vCPU上,需要對定時器的配置進行限制。即CPU在運行vCPU的時候,需要確保CPU對應的LAPIC上配置的定時器都是vCPU的,如果不止,需要轉移到其他的CPU上,當CPU不運行vCPU的時候,需要將vCPU相應的定時器轉移到其他CPU上,並且產生的中斷類型修改為NMI。
軟體注入中斷,這種類型的中斷需要轉化為硬體的Self-IPI,這樣vCPU接收到的所有中斷都能夠被硬體LAPIC控制器感受到,在中斷處理完畢後寫EOI(End-of-Interrpt)告知硬體LAPIC控制器中斷已經處理完畢可以繼續處理下一個中斷的時候,就不用觸發VM Exit進行特殊的處理。因為如果硬體LAPIC沒有接收到中斷,而CPU去寫EOI就可能造成LAPIC狀態錯亂。
Nitro架構不僅強大(虛擬機的性能在大部分情況下和裸機的性能相差遠小於%),而且特別靈活,不僅可以基於Nitro Hypervisor運行虛擬機,而且可以基於一些常用的Hypervisor(如qemu-kvm,vmware)運行虛擬機,甚至可以直接裸跑作業系統。
下面開始聚焦安全方面:
參考資料
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.stonybrook.edu/~mferdman/downloads.php/VEE15_Comprehensive_Implementation_and_Evaluation_of_Direct_Interrupt_Delivery.pdf
https://blog.csdn.net/lindahui2008/article/details/109397778