openstack映象:Cloudbase-init的定製化實現
在雲端計算openstack中,我們往往需要對建立的虛擬機器進行初始化以及特殊的定製過程。在Linux系統中,我們有Cloud-init,在Windows系統中,也有個類似的工具:Cloudbase-init
這裡的初始化和定製,更通俗的來說,就是在虛擬機器啟動尤其是首次啟動的時候,進行如主機名、網路、磁碟擴容、使用者和密碼等等的設定。在Cloudbase-init中是以外掛的形式來做的,在Linux的cloud-init中是以模組的形式來做的。
cloudbase-init的程式碼入口:
~cloudbaseinit.shell.main()
CONF = cloudbaseinit_conf.CONF LOG = oslo_logging.getLogger(__name__) def main(): CONF(sys.argv[1:]) logging.setup('cloudbaseinit') try: init.InitManager().configure_host() except Exception as exc: LOG.exception(exc) raise if __name__ == "__main__": main()
這裡有一個init.InitManager()類,用於封裝對plugin的各種操作。我們的核心操作在這個類裡面的configure_host方法中。
這裡在讀取配置檔案採用了和nova相同的方法:通過呼叫oslo_config庫來讀取。
init.InitManager().configure_host()
對主要步驟進行註解
def configure_host(self): service = None # 通過作業系統來判斷使用哪種util,windows是"WindowsUtils" osutils = osutils_factory.get_os_utils() # 如果是以模板啟動的虛擬機器可能會進行雜湊傳遞攻擊,這裡會重置服務密碼 if CONF.reset_service_password and sys.platform == 'win32': self._reset_service_password_and_respawn(osutils) LOG.info('Cloudbase-Init version: %s', version.get_version()) # 讀取Sysprep的登錄檔,數值為7為完成。 osutils.wait_for_boot_completion() # 第一個stage,處理pre_networking 過程的外掛,貌似只有ntplientplugin,根據需要在配置中開啟或關閉。 stage_success, reboot_required = self._handle_plugins_stage( osutils, None, None, plugins_base.PLUGIN_STAGE_PRE_NETWORKING) self._check_latest_version() if not (reboot_required and CONF.allow_reboot): # 第二個stage,處理pre_metadata_discovery中的外掛,貌似也只有一個plugin(mtuplugin)。 stage_success, reboot_required = self._handle_plugins_stage( osutils, None, None, plugins_base.PLUGIN_STAGE_PRE_METADATA_DISCOVERY) if not (reboot_required and CONF.allow_reboot): try: # 根據配置獲取DataSource。 service = metadata_factory.get_metadata_service() except exception.MetadaNotFoundException: LOG.error("No metadata service found") if service: LOG.info('Metadata service loaded: \'%s\'' % service.get_name()) if CONF.metadata_report_provisioning_started: LOG.info("Reporting provisioning started") service.provisioning_started() instance_id = service.get_instance_id() LOG.debug('Instance id: %s', instance_id) try: # 第3個Stage,在獲取DataSource之後,執行main部分的plugin,絕大部分的plugin都是在此部分進行的。 stage_success, reboot_required = self._handle_plugins_stage( osutils, service, instance_id, plugins_base.PLUGIN_STAGE_MAIN) finally: service.cleanup() .........後面的程式碼不是特別核心的操作了........
總結的話,就是cloudbase-init主要對plugin的操作有3個階段,如下:
pre-networking 階段:在傳送任何有效網路請求以前設定網路。(這一過程中應該只有ntpclient模組,可以設定開啟或不開啟)
pre-metadata-discovery 階段:在獲取DataSource之前做一些額外配置(這一過程應該也只有mtu模組),這個階段執行完成後會去獲取DataSource。
main 階段:在DataSource成功獲取之後,執行main階段的各個外掛來做初始化操作。
粗略的流程大概就是這個樣子,當然裡面還有很多的細節,比如,DataSource是如何獲取的,網路是怎麼配置的,configdrive和metadataservice的區別等等,後面我們可以詳細再看。