聊聊Nova Compute Driver的那些趣事
Openstack設(shè)計(jì)準(zhǔn)則
OpenStack是一個(gè)開源云計(jì)算平臺(tái)項(xiàng)目,旨在為公共及私有云的建設(shè)與管理提供軟件的開源實(shí)現(xiàn)??蓴U(kuò)展性和彈性是Openstack設(shè)計(jì)的準(zhǔn)則之一,即Openstack的各個(gè)組件以及組件內(nèi)部的模塊都應(yīng)該是可插拔的,并且可以隨意的增加插件而不需要修改已有的接口。Driver機(jī)制就是其中的一個(gè)很好的例子,Nova通過不同的driver支持不同的hypervisor,Cinder通過不同的driver支持不同的存儲(chǔ)后端,Neutron通過各種agent支持不同的網(wǎng)絡(luò)類型,Sahara通過各種plugin支持不同的Hadoop發(fā)行版等等,在Openstack幾乎處處存在這樣的影子。所有的driver都是可配置的,通過配置不同的driver,各個(gè)組件就能注冊不同的驅(qū)動(dòng),從而支持不同的資源類型。
何謂Compute Driver
說到Nova,相信大家都會(huì)想到它的功能就是管虛擬機(jī)的,甚至無意識地和Libvirt、QEMU、KVM等概念自動(dòng)關(guān)聯(lián)起來。我基本每次面試都會(huì)問及Nova的實(shí)現(xiàn)原理,大多數(shù)面試者都能回答說:Nova的原理嘛,就是調(diào)用Libvirt的API管理QEMU/KVM虛擬機(jī)。是的,我們部署Openstack時(shí)大都會(huì)使用libvirt driver,以至于很多人都誤以為Nova只是Libvirt的封裝,Nova只能管理虛擬機(jī)??墒聦?shí)上,Nova的功能遠(yuǎn)非如此,我特別需要強(qiáng)調(diào)的是:
- Libvirt只是眾多compute driver的其中一種。
- Nova可管的不僅僅是虛擬機(jī)。
要理解以上兩點(diǎn),我們首先需要理解Compute Driver究竟是什么?驅(qū)動(dòng)的概念相信大家都明白,我們買了一個(gè)新的相機(jī)或者U盤需要接入筆記本,完成的第一件事就是要安裝驅(qū)動(dòng)。許多驅(qū)動(dòng)是通用的,比如U盤,插入U(xiǎn)SB接口后就能用,這是因?yàn)閮?nèi)核內(nèi)置了該類型存儲(chǔ)設(shè)備的驅(qū)動(dòng)程序。有些設(shè)備的驅(qū)動(dòng)不是通用的,通常這種情況下,你購買設(shè)備時(shí)會(huì)順便配備一個(gè)小光盤,里面放的就是驅(qū)動(dòng)程序,需要安裝到你的電腦上才能使用該設(shè)備。因此,這里的驅(qū)動(dòng)可以認(rèn)為是設(shè)備與操作系統(tǒng)的交互接口,或者說代理。雖然硬件設(shè)備多種多樣,但操作系統(tǒng)定義的接口通常是固定的,比如open()、read()、write()、ioctl()、close()等,驅(qū)動(dòng)程序只要實(shí)現(xiàn)了這些接口,就能被操作系統(tǒng)識別、管理。同理,Nova相當(dāng)于操作系統(tǒng),而各種形形色色的hypervisor相當(dāng)于各種設(shè)備,而Compute Driver就相當(dāng)于驅(qū)動(dòng)程序。Compute Driver定義了將近120個(gè)接口,所有接口都在nova/virt/driver.py上定義和描述,如:
- spawn: 創(chuàng)建一個(gè)實(shí)例。
- destroy: 刪除一個(gè)實(shí)例。
- start: 對應(yīng)虛擬機(jī),就是開機(jī)操作。
- stop: 對應(yīng)虛擬機(jī),就是關(guān)機(jī)操作。
- reboot: 對應(yīng)虛擬機(jī),就是重啟操作。
- …
這些接口通常是固定不變的,也是所有具體實(shí)現(xiàn)必須遵循的規(guī)范,其描述了所有接口的作用、參數(shù)、返回類型等信息,比如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.
- """
- ...
注意:定義的接口并不要求全部實(shí)現(xiàn),根據(jù)具體的后端實(shí)現(xiàn),可以只實(shí)現(xiàn)其中的一部分接口,其它未實(shí)現(xiàn)的接口只需要簡單地拋出NotImplementedError異常即可。
LibvirtDriver是其中的一個(gè)實(shí)現(xiàn),它位于nova/virt/libvirt/driver.py,其中spawn()方法相當(dāng)于調(diào)用了libvirt的define()和start()方法。destroy()則相當(dāng)于調(diào)用了libvirt的destroy()方法和undefine方法,其它方法也都能找到對應(yīng)的調(diào)用關(guān)系。
理解了什么是Compute Driver,在回過頭來思考之前的兩個(gè)問題:
Libvirt只是眾多compute driver的其中一種。相信只要深入了解過Nova并閱讀過Nova源碼,不會(huì)有什么疑問,當(dāng)前最新版本的Nova項(xiàng)目中原生支持的Compute Driver包括:
- libvirt
- hyperv
- xenapi
- vmwareapi
- ironic
Nova可管的不僅僅是虛擬機(jī)。這很有趣,甚至難以置信,但這卻是事實(shí)。Nova管理的除了虛擬機(jī)之外的東西,有些可能只是一種嘗試,有些早已成為了歷史,也有些獨(dú)立門戶。帶著好奇心,不妨好好盤點(diǎn)下Nova除了能管虛擬機(jī),還能管理哪些有趣的玩意。
Openstack
有人看到這,開始質(zhì)疑這里標(biāo)題是不是錯(cuò)了,明明是談Nova能管什么,怎么突然岔開話題談Openstack,Nova不是Openstack其中一個(gè)組件么?難道Nova管理Nova?不管你信不信,這是真的。其實(shí)原理很簡單,把Compute Driver的所有實(shí)現(xiàn)替換為對另一個(gè)Nova API調(diào)用即可。比如spawn()方法,轉(zhuǎn)化為對另一個(gè)Nova API的"POST /servers"請求。我們把這種模式稱作級聯(lián)Openstack。
這有什么用呢?我們知道,Openstack目前越來越成熟穩(wěn)定,但一直沒能很好的支持大規(guī)模的擴(kuò)展,當(dāng)規(guī)模大到一定程度時(shí),數(shù)據(jù)庫、消息隊(duì)列等都會(huì)成為性能瓶頸,限制了單一Openstack規(guī)模的增長。社區(qū)為此也思考了一些方案,分Region、分Cell以及前面提到的級聯(lián)Openstack都是社區(qū)的一些嘗試,這些嘗試都是可行的,但又有其各自的問題。Region和Cell會(huì)在后續(xù)的文章中重點(diǎn)介紹,這里僅僅介紹下級聯(lián)Openstack,官方文檔參考OpenStack cascading solution。其原理如圖:
其實(shí)不僅Nova如此,其它所有組件都可以使用類似方法實(shí)現(xiàn)級聯(lián)從而實(shí)現(xiàn)大規(guī)模擴(kuò)展:
理論上,這種方法可以無限擴(kuò)展Openstack的節(jié)點(diǎn),沒有規(guī)模限制。事實(shí)上,部署和實(shí)現(xiàn)上還是存在不少挑戰(zhàn)問題的,比如如何同步各個(gè)child集群的信息以及網(wǎng)絡(luò)通信等。
目前社區(qū)已經(jīng)把這一部分實(shí)現(xiàn)邏輯單獨(dú)拿出來,并新開了兩個(gè)相關(guān)項(xiàng)目[Tricircle]((https://wiki.openstack.org/wiki/Tricircle)以及Trio2o,二者基本都是由華為在主導(dǎo),一個(gè)負(fù)責(zé)網(wǎng)絡(luò)管理,另一個(gè)負(fù)責(zé)實(shí)現(xiàn)級聯(lián)。目前這兩個(gè)項(xiàng)目還不是特別成熟,但還是提供了一種支持大規(guī)模Openstack集群的參考。
Docker
Docker這幾年非?;馃?,甚至有人說Docker會(huì)代替虛擬機(jī),K8S會(huì)代替Openstack,雖然這種描述過于夸張,也欠缺合理性,但這卻足以證明Docker的熱度。
也因此社區(qū)很早就開始嘗試集成Docker。在K版本Openstack中,Nova已經(jīng)支持了Docker驅(qū)動(dòng),能夠通過Nova來啟動(dòng)Docker容器。實(shí)現(xiàn)原理其實(shí)也不難,spawn()方法相當(dāng)于調(diào)用Docker的run接口(其實(shí)是調(diào)用的create()和start()API),而destory()方法則調(diào)用Docker的rm接口。其它接口與之類似。Nova的Docker驅(qū)動(dòng)項(xiàng)目地址為nova-docker。
但是,Docker畢竟是容器,它與虛擬機(jī)還是有差別的,使用Nova集成Docker,難以支持Docker的一些高級特性,比如link、volume等。于是又有人提出與Heat集成,通過Heat能夠充分利用Docker API,但缺乏調(diào)度機(jī)制。于是干脆單獨(dú)一個(gè)新的項(xiàng)目來專門提供容器服務(wù),支持多租戶和資源調(diào)度,這個(gè)項(xiàng)目名稱為magnum。再后來,magnum想專注于容器編排服務(wù),集成K8S、Docker Swarm等容器編排服務(wù),而單容器服務(wù)則又獨(dú)立一個(gè)項(xiàng)目Zun。
裸機(jī)
Nova既然能管理虛擬機(jī),那肯定會(huì)有人想,能不能管理我們的物理機(jī)呢?很好,Nova做到了。Nova很早就支持了裸機(jī)管理,原理就是原來對接Libvirt的接口,現(xiàn)在替換為調(diào)用IPMI接口,從而實(shí)現(xiàn)了裸機(jī)的管理。因此Nova的裸機(jī)驅(qū)動(dòng)其實(shí)就相當(dāng)于封裝了ipmitool命令,事實(shí)上,也正是對ipmitool的shell調(diào)用。
最開始,裸機(jī)管理的代碼實(shí)現(xiàn)是直接放在Nova源碼中的,后來分離出單獨(dú)的Ironic項(xiàng)目,提供裸機(jī)管理服務(wù)。
原來的IPMI封裝放在了ironic-conductor服務(wù),所有的裸機(jī)操作必須通過ironic-api調(diào)用。因此原來的Nova裸機(jī)驅(qū)動(dòng)實(shí)現(xiàn)由直接的IPMI封裝,替換為了ironic-api的封裝。
總結(jié)
除了以上提到的虛擬機(jī)、Openstack本身、Docker容器以及物理機(jī),Nova未來還有可能支持更多的東西,也許現(xiàn)在想不到,誰又說得準(zhǔn)以后的事呢。
【本文是51CTO專欄作者“付廣平”的原創(chuàng)文章,如需轉(zhuǎn)載請通過51CTO獲得聯(lián)系】