民生銀行:基於Ironic實現X86裸機自動化裝機實踐與優化

1 X86裸機管理背景

目前我們測試環境存在大量分散在不同網絡區域的各種型號的物理服務器,主要用於給需要物理機的開發人員臨時測試使用,使用完畢後通過工單申請回收。這些服務器分佈在不同的網絡區域,大多數服務器的網絡佈線和接入均已經就緒。

用戶在工單系統中申請一臺物理服務器時,審批通過後由變更經理派發任務給實施人員,再由實施人員手動通過帶外及ISO鏡像安裝操作系統。手動安裝操作系統從ISO鏡像準備到裝機完成大概需要20多分鐘的時間,交付時間長,並且均是重複的體力工作,實施人員工作繁重。

因此我們從2018年下半年開始思考如何優化如上流程,使用自動化工具替代之前的純手動裝機模式。

通過雲平臺、系統管理和開發部門深入分析,總結X86裸機裝機的需求如下:

  1. 支持行內標準鏡像,操作系統需要支持配置LVM並創建rootvg。
  2. 操作系統支持配置主機名,支持注入ssh密鑰以及初始化root密碼。
  3. 操作系統支持多網卡以及bond配置。
  4. 服務器支持分配在不同的網段及VLAN。
  5. 支持HBA卡識別過濾。
  6. 支持裝機網卡和業務網卡複用。
  7. 能夠支持裸機分佈在不同的網段和VLAN,不需要調整服務器原有的網絡佈線和接入。

目前實現X86自動化裝機的工具有很多,如Foreman、cloudboot等,我們調研發現能夠同時滿足如上需求並且易於與現有的雲管集成的只有OpenStack Ironic方案。

於是我們從2018年12月開始對OpenStack Ironic進行完全自主技術預研,之所以沒有找廠商方案,是因爲廠商的方案大多數需要綁定特定服務器或者SDN交換機。

2 OpenStack Ironic簡介

2.1 關於OpenStack Ironic項目

Ironic是OpenStack裸機管理組件,負責裸機資源的分配以及生命週期管理,通過該組件可以爲OpenStack雲平臺提供裸機服務。Ironic通常會協同OpenStack其他服務一起工作,具體分工如下:

  • Keystone:認證與授權。
  • Glance:爲裸機提供鏡像服務。
  • Nova:負責裸機調度,提供裸機服務。
  • Ironic:裸機管理,包括裸機信息錄入、硬件信息自動發現等。
  • Neutron:裸機網絡管理和配置。
  • Swift:保存Ironic部署日誌以及ConfigDrive數據

以上,比較容易混淆的是Ironic組件和Nova組件的分工,Ironic是裸機管理服務,可以類同爲企業的IT資產管理系統,而Nova是提供裸機服務的,可以認爲是給用戶分配物理服務器的組件。底層技術實現上,Ironic是Nova其中一種Compute Driver接口實現,和Libvirt平行,一個裸機node對應Nova的一個Hypervisor實例。Nova會通過調用Libvirt的Driver實現虛擬機創建、開關機、重啓等操作,通過調用PXE以及IPMI實現裸機的裝機、開關機、重啓等操作。

更多關於Ironic項目的介紹可參考官方文檔。

2.2 Ironic部署架構

我們的Ironic部署架構如圖2-1:

圖2-1 ironic部署架構

管理節點部署了Ironic相關組件、nova-compute服務(ironic driver)以及TFTP Server,它有兩個邏輯網卡(均配置了bond),功能如下:

  • 網卡1(eth0):Trunk接入,部署(provision)網絡與業務網絡複用網卡,根據VLAN號區分不同的網絡。每個網絡會啓動一個DHCP Server用於裸機的PXE引導。同時也是clean網絡、rescue網絡複用網卡。
  • 網卡2(eth1):Access接入,OpenStack管理網,用於OpenStack的各個組件通信。該網絡三層打通了物理服務器的帶外網絡訪問關係,用於調用IPMI指令。

裸機節點的網卡數量不等,根據業務需要,一般會配置4個網卡,其中一個網卡用於帶外,兩個網卡用於做bond,爲用戶的業務網絡,另一張網卡做心跳網絡(可選),這些網卡均提前做好了佈線和接入。

由於服務器的佈線和接入均是現成的,因此我們的Ironic沒有管理交換機配置,只需要根據VLAN選擇不同的Neutron Network即可,因此使用的網絡模型是flat。

我們在2019年1月份部署了一個測試環境,其間也遇到了不少的"坑",如Web console打不開、鏡像不支持LVM、SLES操作系統不支持bond配置等問題,我們針對這些問題進行了大量的優化開發工作,本文下一節將詳細介紹我們在實踐過程中遇到的問題以及解決方案。

3 使用Ironic遇到的那些"坑"

3.1 Web終端bug修復

虛擬機可以通過VNC實現Web終端遠程訪問,用戶可以通過Web頁面遠程訪問操作系統。但顯然裸機沒有VNC的概念。

不過裸機的Web終端可通過SOL(IPMI Serial Over LAN)實現。我們知道虛擬機的VNC是通過nova-novncproxy代理轉發到計算節點libvirt VNC的。裸機的console同理也是通過層層代理轉發實現的,首先conductor節點通過socat把IPMI SOL轉發到本地的一個端口中,如15900,然後通過nova-serialconsoleproxy負責轉發到conductor節點綁定的端口15900,即用戶訪問裸機的console流程如下:

Web console -> nova-serialconsoleproxy -> ironic-conductor -> IPMI SOL

不過社區代碼存在一個bug #1809418,nova-serialproxy校驗ironic裸機console地址時,由於類型不一致導致校驗100%失敗,結果無法通過nova get-serial-console獲取web console地址。我們發現這個問題並及時修復這個bug,目前已提交補丁代碼到社區併合併到master分支及rocky分支。新版本的Nova不會再出現這個問題了。

3.2 標準化鏡像問題

目前社區推薦製作Ironic鏡像方式是通過disk-image-builder(DIB)工具,官方文檔參考Build the ironic image。

然而,通過DIB工具製作的鏡像不符合行內的鏡像模板要求,比如LVM配置、安全加固等。爲了滿足行內鏡像規範要求,我們想到的最快捷的方法是直接使用行內的標準虛擬機鏡像。

但是,物理服務器和虛擬機的鏡像是有區別的,其中最明顯的區別就是驅動問題。虛擬機只需要安裝上virtio驅動即可啓動,物理服務器則必須安裝兼容的硬件驅動,否則可能由於硬盤不識別導致操作系統啓動失敗。

目前很多硬件驅動都是通過內核模塊的形式動態加載,操作系統啓動時通常會先加載一個臨時文件系統initramfs,然後由initramfs掛載真正的root文件系統,加載內核模塊。因此initramfs能夠識別硬盤是操作系統啓動成功的前提。因此當一個操作系統鏡像從一臺虛擬機或者一個物理機遷移到另一個物理機時,往往需要更新initramfs以適配目標物理機的硬件驅動。

我們調研了很多關於生成initramfs的方法,但往往適配了某一種機型後,啓在另外一種機型又啓動失敗了,進入dracut shell界面發現根本識別不了塊設備。目前我們的物理服務器機型和型號都非常多,如果針對每一個機型都製作一個鏡像,則鏡像會非常多,並且每來一個新的機型都需要重新制作鏡像。

我們受DIB工具dracut-ramdisk element的啓發(感謝社區),研究了其生成initramfs的方法,並結合我們對LVM的需求,實現了能夠兼容我們目前使用到的所有機型(如Dell GW730XD、ProLiant DL380 Gen9)initramfs生成方法,部分腳本如下:

KERNEL_VERSION=1.2.3 # 內核版本
# 需要在initramfs安裝的工具
BINARY_DEPS="tail head awk ifconfig cut expr route ping nc wget tftp grep" 
DRACUT_DRIVERS="virtio virtio_net virtio_blk" 
dracut -f -N \
     --install "$BINARY_DEPS" \
     --kernel-cmdline "rd.shell rd.driver.pre=ahci" \
     --kver "${KERNEL_VERSION}" \
     --add-drivers "$DRACUT_DRIVERS" \
     --add lvm \
     --mdadmconf \
     --lvmconf \
     -o "dash plymouth" \
     my-ramdisk

其中:

  • -N參數禁用Host-Only模式,這樣會儘可能多的安裝硬件驅動,而不是僅加載當前宿主機的硬件驅動。
  • rd.driver.pre預先加載ahci模塊是爲了能夠識別系統的SATA硬盤。
  • –add添加的lvm驅動則是爲了支持硬盤的LVM卷。

另外我們發現某些機型在開啓了drucut-cmdline的resume選項後會隨機啓動失敗,因此我們在grub中取消了resume選項。

3.3 網卡選擇策略優化

虛擬機的網卡都是虛擬的tap設備,而裸機的網卡則不一樣,它是真實的網卡並且關聯了物理接入信息,因此這就存在一個Neutron port與裸機的網卡關聯問題,更具體的說,假設創建一個新的裸機實例時,使用VLAN 100的VLAN類型網卡,分配了一個Neutron虛擬port,而物理服務器往往有8個甚至更多的網卡,ironic如何知道是哪個網卡的接入匹配port的配置呢?如果匹配不對,則網絡必然不通,因爲該網卡可能並沒有接入交換機或者配置的VLAN不一致,相當於把IP地址配在了一個錯誤的網卡上。

當只分配一個網絡時,ironic會選擇其中一個開啓了PXE的網卡作爲候選網卡,但如果存在多個網絡時,則可能匹配失敗,爲什麼會出現這種問題呢?我們分析了社區實現的網卡選擇算法。代碼位於ironic/drivers/modules/network/common.py模塊的get_free_port_like_object方法:

def get_free_port_like_object(task, vif_id, physnets):
    # ... 省略部分代碼
    def sort_key(port_like_obj):
        is_pg = isinstance(port_like_obj, objects.Portgroup)
        if is_pg:
            pg_physnets = network.get_physnets_by_portgroup_id(
                task, port_like_obj.id)
            pg_physnet = pg_physnets.pop()
            physnet_matches = pg_physnet in physnets
            pxe_enabled = True
        else:
            physnet_matches = port_like_obj.physical_network in physnets
            pxe_enabled = port_like_obj.pxe_enabled
        return (physnet_matches, is_pg, pxe_enabled)

    sorted_free_plos = sorted(free_port_like_objs, key=sort_key, reverse=True)
    return sorted_free_plos[0]

從代碼中我們可以總結社區實現的網卡從高到低的優先選擇順序爲:

  1. 匹配physical network的ironic port;
  2. 如果是portgroup,則優先選擇portgroup;
  3. 選擇開啓了pxe的ironic port;
  4. 根據Ironic的node的錄入順序選擇ironic port。

注意以上的physical network並不是對應neutron的network,而是對應ovs配置的bridge mapping中的physical network。而ironic port其實對應的就是裸機的物理網卡,portgroup即bond配置,在網卡調度時也被當作網卡的邏輯port,和物理port一同調度。

這裏假設我們的physical network都是一樣的,並且沒有配置bond,所有的網卡都開啓了pxe,則啓動裸機實例時必須滿足nova boot的–nic參數選擇的neutron network和ironic port的錄入順序一致,否則必然發生port映射錯位。

我們的場景通常都需要配置多網絡,但不能要求用戶嚴格按照裸機網卡的錄入順序選擇網絡,因此我們對網卡選擇策略進行了優化。在裸機port錄入時,我們添加了segmentation_id標籤(extra key),在物理網卡選擇時,如果Neutron的port關聯的network的segmentation_id與ironic port的segmentation_id一致,則優先選擇該物理網卡,實現的部分代碼如下:

def sort_key(port):
    port_seg_id = int(port.extra.get("segmentation_id", ""))
    network_seg_id = int(vif_network.get('provider:segmentation_id'))
    seg_match = port_seg_id == network_seg_id
    # ... 省略其它代碼部分
    return (seg_match, physnet_matches, is_pg, pxe_enabled)

這樣就可以通過物理網卡的segmentation_id與Neutron的虛擬port強制關聯起來一一映射,解決了網卡匹配錯位的情況。

3.4 引入新的裸機調度filter

Ironic的node會映射成Nova的一個hypervisor,虛擬機和裸機的調度都是通過nova-scheduler完成的。虛擬機調度時會選擇其中一個超售後的剩餘資源大於請求資源(flavor)的計算節點(hypervisor)作爲虛擬機啓動的宿主機,這種策略在調度虛擬機時是完全沒有問題的。

然而在調度裸機時會出現一個明顯的問題:當用戶請求一個低配的裸機實例時,可能會調度到一臺高配置的物理機。比如用戶申請一臺16C32G的裸機實例,可能調度到一臺32C128G的物理機上,這顯然不是我們所期望的。

因此我們自主研發實現了一個精確資源匹配的filter,該filter會精確匹配hypervisor的資源與用戶申請選擇的flavor資源,過濾掉資源不符合的hypervisor節點,核心代碼如下:

def host_passes(self, host_state, spec_obj):
    # ...省略部分代碼
    requested_vcpus = spec_obj.vcpus
    requested_ram = spec_obj.memory_mb
    if requested_vcpus != host_state.vcpus_total:
        return False
    if requested_ram != host_state.total_usable_ram_mb:
        return False
    return True

該filter會首先判斷是否裸機調度,如果是則調度時完全匹配用戶請求的資源與物理裸機的資源,如果沒有匹配的物理機,則直接調度失敗,有助於管理員快速地發現物理資源不足問題。

3.5 多網卡Bond支持優化

目前最新版本的cloud-init通過configdrive-2已經支持操作系統的高級網絡配置,如bond配置,參考官方文檔network config部分。但是支持的網絡配置工具目前僅包含如下三種:

  • eni: Ubuntu早期版本使用的網絡配置方法,通過修改etc/network/interfaces文件配置網絡。
  • sysconfig:rhel系列操作系統配置工具,如CentOS。通過修改etc/sysconfig/network-scripts/ifdown-ethX文件配置網卡。
  • netplan:一種較新的網絡配置工具,通過yaml文件配置網卡,目前ubuntu 18.04使用的該工具。

CentOS、Redhat等操作系統可以通過原生cloud-init配置bond。然而SUSE操作系統由於使用的是wicked網絡配置工具,目前cloud-init尚不支持該類型的bond配置。

爲了解決這個問題,我們自主研發了wicked網絡配置驅動,實現了SLES系列wicked網絡工具的高級網絡配置功能,從而解決了行內SLES操作系統的bond配置問題。目前準備把這部分功能代碼提交到社區。

4 使用Ironic實現自動化裝機優勢

4.1 自動化裝機,縮短交付時間

在使用Ironic組件之前,我們的開發測試環境的物理服務器安裝操作系統都是全手工完成的,實施工程師先要通過帶外上傳ISO鏡像,手動啓動物理服務器,通過BIOS配置啓動方式,然後進行一系列的操作系統初始化配置,如設置語言、創建LVM、主機名等,最後安裝grub後重啓操作系統,如圖4-1:

圖4-1 手動裝機流程及預估時間

如上這些步驟幾乎都是必須人工交互的重複體力工作,難以做到並行批量裝機,一臺物理服務器完成操作系統安裝大概需要20多分鐘的時間,耗費了工程師大量的精力和時間,並且難以實現快速交付。

通過OpenStack Ironic組件,我們開發測試環境的X86物理服務器操作系統安裝從原來的純手工模式轉化爲全自動模式,用戶只需要選擇安裝的操作系統,無需人工干預即可自動完成操作系統安裝。如下是我們測試部分機型實際裝機的統計時間:

生產廠商 型號 裝機時間
長城 GW-R720 377s
長城 GW-R730XD 362s
惠普 HP-SL2500 484s
聯想 R525 G3 538s

如上主要的時間花在物理服務器啓動後的硬件檢測時間。由於整個過程都是全自動的,因此可以進行批量裝機完成操作系統預安裝,相對於手動一臺一臺安裝,大大節省了實施人員的時間。

4.2 標準化操作系統

之前實施工程師手動安裝操作系統,不僅需要花費大量的時間,而且很容易配置出錯,常見的問題如LVM配置不規範、網卡配置錯誤、鏡像源地址錯誤等,出現配置錯誤需要實施人員返工,效率不高。

而通過Ironic自動化裝機,使用的是標準化鏡像模板,模板已完成操作系統的所有靜態配置,如:

  • LVM配置,rootvg大小固定;
  • 鏡像源配置;
  • 安全加固配置,如SSH訪問權限控制;

而操作系統的動態配置則可通過公有云流行的cloud-init開源工具完成初始化啓動配置,如:

  • 主機名配置;
  • 網卡配置,包括bond配置;
  • 密碼初始化及SSH密鑰注入;

操作系統升級、配置更新等操作,直接修改鏡像模板即可,大大減少了工作量,提升了效率。

4.3 多網絡區域統一管理

目前我們的X86物理服務器分佈在不同的網絡區域,不同網絡區域的服務器的IP段和VLAN接入不一樣。

裝機工具爲了能夠管理多網絡區域的物理服務器,通常有兩種策略:

  1. 部署節點配置多塊網卡,手動在交換機上配置與待裝機節點相同的網絡接入,每個網卡啓動DHCP服務。
  2. 在物理服務器上添加一塊部署網卡用於專門裝機時使用,配置與部署節點相同的網絡接入。

如上第一種方案非常不靈活,每當有一個新的網絡區域加入時,部署節點需要手動再添加一塊網卡。而第二種方案需要調整物理服務器原有的網絡接入,並且當裝機完成後,裝機網卡就沒用了,白白浪費交換機端口資源。

得益於OpenStack Neutron的多租戶網絡模型,使用Ironic方案使用Neutron的多租戶網絡功能,不僅不需要修改X86物理服務器的任何網絡接入配置,而且部署節點只需要一個trunk接入網卡即可適配所有VLAN以及IP地址段,一個網絡區域相當於一個邏輯VPC(Virtual Private Cloud),如圖4-2。

圖4-2 多網絡區域服務器管理

物理服務器部署網絡和業務網絡可共享複用,當添加一個新網絡區域服務器時,只需要創建一個新的VPC並指定新的VLAN號即可,無需任何的物理交換機配置修改。

4.4 標準API,便於雲管集成

Ironic是OpenStack的標準組件,具有統一的API標準,便於雲管平臺的集成。

5 總結與展望

Ironic是OpenStack裸機管理組件,我們在開源的基礎上修復了Ironic多個社區bug,優化了物理服務器的多網卡選擇策略以及物理服務器的調度算法,開發了新的驅動實現SUSE系列操作系統的高級網絡配置。通過OpenStack Ironic裸機管理組件實現開發測試環境的X86服務器自動裝機和管理,替代原來的純手動模式,從而縮短了物理服務器的裝機時間,減少實施人員的工作量,提升裝機效率。

然而,這還僅僅只是開始,未來我們還有許多工作需要做,如:

  • 進一步解決物理服務器的性能及硬件故障監控。
  • 作爲物理機管理模塊,與雲管平臺集成。

作者信息

  • 付廣平:任職民生銀行雲技術管理中心,負責雲計算相關技術研究。畢業於北京郵電大學,從2013開始從事OpenStack相關工作,參與了OpenStack Nova、Cinder、Oslo等項目社區開發,知乎專欄《OpenStack》作者。對Ceph、Docker等技術也有一定的瞭解。

  • 張立新:任職民生銀行系統管理中心,目前致力於測試環境管理工作。曾在職進修於中國科學院研究生院計算機技術專業,就業於HP從事操作系統和數據庫服務支持工作,期間提供建設銀行駐廠服務支持工作兩年,民生銀行服務支持工作一年。

  • 崔增順:任職民生銀行雲技術管理中心,目前致力於IaaS雲平臺工作,熟悉服務器/操作系統/存儲等。

  • 馬興超:任職民生銀行雲技術管理中心,主要負責雲管平臺的研究、建設和運維工作。曾就職於IBM負責小型機維護和災備相關項目建設。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章