聊聊Nova Compute Driver的那些趣事
Openstack設計準則
OpenStack是一個開源云計算平臺項目,旨在為公共及私有云的建設與管理提供軟件的開源實現。可擴展性和彈性是Openstack設計的準則之一,即Openstack的各個組件以及組件內部的模塊都應該是可插拔的,并且可以隨意的增加插件而不需要修改已有的接口。Driver機制就是其中的一個很好的例子,Nova通過不同的driver支持不同的hypervisor,Cinder通過不同的driver支持不同的存儲后端,Neutron通過各種agent支持不同的網絡類型,Sahara通過各種plugin支持不同的Hadoop發行版等等,在Openstack幾乎處處存在這樣的影子。所有的driver都是可配置的,通過配置不同的driver,各個組件就能注冊不同的驅動,從而支持不同的資源類型。
何謂Compute Driver
說到Nova,相信大家都會想到它的功能就是管虛擬機的,甚至無意識地和Libvirt、QEMU、KVM等概念自動關聯起來。我基本每次面試都會問及Nova的實現原理,大多數面試者都能回答說:Nova的原理嘛,就是調用Libvirt的API管理QEMU/KVM虛擬機。是的,我們部署Openstack時大都會使用libvirt driver,以至于很多人都誤以為Nova只是Libvirt的封裝,Nova只能管理虛擬機。可事實上,Nova的功能遠非如此,我特別需要強調的是:
- Libvirt只是眾多compute driver的其中一種。
- Nova可管的不僅僅是虛擬機。
要理解以上兩點,我們首先需要理解Compute Driver究竟是什么?驅動的概念相信大家都明白,我們買了一個新的相機或者U盤需要接入筆記本,完成的第一件事就是要安裝驅動。許多驅動是通用的,比如U盤,插入USB接口后就能用,這是因為內核內置了該類型存儲設備的驅動程序。有些設備的驅動不是通用的,通常這種情況下,你購買設備時會順便配備一個小光盤,里面放的就是驅動程序,需要安裝到你的電腦上才能使用該設備。因此,這里的驅動可以認為是設備與操作系統的交互接口,或者說代理。雖然硬件設備多種多樣,但操作系統定義的接口通常是固定的,比如open()、read()、write()、ioctl()、close()等,驅動程序只要實現了這些接口,就能被操作系統識別、管理。同理,Nova相當于操作系統,而各種形形色色的hypervisor相當于各種設備,而Compute Driver就相當于驅動程序。Compute Driver定義了將近120個接口,所有接口都在nova/virt/driver.py上定義和描述,如:
- spawn: 創建一個實例。
- destroy: 刪除一個實例。
- start: 對應虛擬機,就是開機操作。
- stop: 對應虛擬機,就是關機操作。
- reboot: 對應虛擬機,就是重啟操作。
- …
這些接口通常是固定不變的,也是所有具體實現必須遵循的規范,其描述了所有接口的作用、參數、返回類型等信息,比如spawn接口:
- def spawn(self, context, instance, image_meta, injected_files,
- admin_password, network_info=None, block_device_info=None):
- """Create a new instance/VM/domain on the virtualization platform.
- Once this successfully completes, the instance should be
- running (power_state.RUNNING).
- If this fails, any partial instance should be completely
- cleaned up, and the virtualization platform should be in the state
- that it was before this call began.
- :param context: security context
- :param instance: nova.objects.instance.Instance
- This function should use the data there to guide
- the creation of the new instance.
- :param nova.objects.ImageMeta image_meta:
- The metadata of the image of the instance.
- :param injected_files: User files to inject into instance.
- :param admin_password: Administrator password to set in instance.
- :param network_info: instance network information
- :param block_device_info: Information about block devices to be
- attached to the instance.
- """
- ...
注意:定義的接口并不要求全部實現,根據具體的后端實現,可以只實現其中的一部分接口,其它未實現的接口只需要簡單地拋出NotImplementedError異常即可。
LibvirtDriver是其中的一個實現,它位于nova/virt/libvirt/driver.py,其中spawn()方法相當于調用了libvirt的define()和start()方法。destroy()則相當于調用了libvirt的destroy()方法和undefine方法,其它方法也都能找到對應的調用關系。
理解了什么是Compute Driver,在回過頭來思考之前的兩個問題:
Libvirt只是眾多compute driver的其中一種。相信只要深入了解過Nova并閱讀過Nova源碼,不會有什么疑問,當前最新版本的Nova項目中原生支持的Compute Driver包括:
- libvirt
- hyperv
- xenapi
- vmwareapi
- ironic
Nova可管的不僅僅是虛擬機。這很有趣,甚至難以置信,但這卻是事實。Nova管理的除了虛擬機之外的東西,有些可能只是一種嘗試,有些早已成為了歷史,也有些獨立門戶。帶著好奇心,不妨好好盤點下Nova除了能管虛擬機,還能管理哪些有趣的玩意。
Openstack
有人看到這,開始質疑這里標題是不是錯了,明明是談Nova能管什么,怎么突然岔開話題談Openstack,Nova不是Openstack其中一個組件么?難道Nova管理Nova?不管你信不信,這是真的。其實原理很簡單,把Compute Driver的所有實現替換為對另一個Nova API調用即可。比如spawn()方法,轉化為對另一個Nova API的"POST /servers"請求。我們把這種模式稱作級聯Openstack。
這有什么用呢?我們知道,Openstack目前越來越成熟穩定,但一直沒能很好的支持大規模的擴展,當規模大到一定程度時,數據庫、消息隊列等都會成為性能瓶頸,限制了單一Openstack規模的增長。社區為此也思考了一些方案,分Region、分Cell以及前面提到的級聯Openstack都是社區的一些嘗試,這些嘗試都是可行的,但又有其各自的問題。Region和Cell會在后續的文章中重點介紹,這里僅僅介紹下級聯Openstack,官方文檔參考OpenStack cascading solution。其原理如圖:
其實不僅Nova如此,其它所有組件都可以使用類似方法實現級聯從而實現大規模擴展:
理論上,這種方法可以無限擴展Openstack的節點,沒有規模限制。事實上,部署和實現上還是存在不少挑戰問題的,比如如何同步各個child集群的信息以及網絡通信等。
目前社區已經把這一部分實現邏輯單獨拿出來,并新開了兩個相關項目[Tricircle]((https://wiki.openstack.org/wiki/Tricircle)以及Trio2o,二者基本都是由華為在主導,一個負責網絡管理,另一個負責實現級聯。目前這兩個項目還不是特別成熟,但還是提供了一種支持大規模Openstack集群的參考。
Docker
Docker這幾年非常火熱,甚至有人說Docker會代替虛擬機,K8S會代替Openstack,雖然這種描述過于夸張,也欠缺合理性,但這卻足以證明Docker的熱度。
也因此社區很早就開始嘗試集成Docker。在K版本Openstack中,Nova已經支持了Docker驅動,能夠通過Nova來啟動Docker容器。實現原理其實也不難,spawn()方法相當于調用Docker的run接口(其實是調用的create()和start()API),而destory()方法則調用Docker的rm接口。其它接口與之類似。Nova的Docker驅動項目地址為nova-docker。
但是,Docker畢竟是容器,它與虛擬機還是有差別的,使用Nova集成Docker,難以支持Docker的一些高級特性,比如link、volume等。于是又有人提出與Heat集成,通過Heat能夠充分利用Docker API,但缺乏調度機制。于是干脆單獨一個新的項目來專門提供容器服務,支持多租戶和資源調度,這個項目名稱為magnum。再后來,magnum想專注于容器編排服務,集成K8S、Docker Swarm等容器編排服務,而單容器服務則又獨立一個項目Zun。
裸機
Nova既然能管理虛擬機,那肯定會有人想,能不能管理我們的物理機呢?很好,Nova做到了。Nova很早就支持了裸機管理,原理就是原來對接Libvirt的接口,現在替換為調用IPMI接口,從而實現了裸機的管理。因此Nova的裸機驅動其實就相當于封裝了ipmitool命令,事實上,也正是對ipmitool的shell調用。
最開始,裸機管理的代碼實現是直接放在Nova源碼中的,后來分離出單獨的Ironic項目,提供裸機管理服務。
原來的IPMI封裝放在了ironic-conductor服務,所有的裸機操作必須通過ironic-api調用。因此原來的Nova裸機驅動實現由直接的IPMI封裝,替換為了ironic-api的封裝。
總結
除了以上提到的虛擬機、Openstack本身、Docker容器以及物理機,Nova未來還有可能支持更多的東西,也許現在想不到,誰又說得準以后的事呢。
【本文是51CTO專欄作者“付廣平”的原創文章,如需轉載請通過51CTO獲得聯系】