記一次ARM服務器(鯤鵬920)的PXE批量裝機遇到的坑

 由於近期項目需要,在對一批華為鯤鵬920的ARM服務器(型號為天宮TG225 B1)進行批量裝機的過程中,遇到了各種各樣千奇百怪的bug(換個高情商的說法就是遇到了各種各樣和x86服務器不一樣的地方),遂記錄本文,以供後續可能遇到問題時參考。

 

在閱讀本文前,建議先閱讀兩篇前序文章《如何在20分鐘內批量部署20台ESXi服務器》以及《使用PXE+NFS EFI引導安裝RHEL6/7以及Kickstart安裝》,有助於理解本文中提到的各種問題。(該兩篇文章均可以在本平台上搜到)

本次實施中使用的服務器為天宮TG225 B1型號,CPU使用的是2顆基於ARM的華為鯤鵬920 32核雙路型號,硬盤使用的是8塊960G SSD,RAID卡使用的是Adeptec 3152-8i。實施的具體工作是需要批量將幾十台該型號服務器批量配置為RAID5,並批量安裝上麒麟V10的操作系統。實施思路為,首先使用虛擬機搭建pxe dhcp server環境,使服務器用pxe引導clonezilla通過腳本的方式進行RAID配置,然後使用pxe引導麒麟OS手動安裝第一台服務器,使用該機器安裝後自動生成的kickstart腳本進行後續服務器的自動部署麒麟操作系統。由於麒麟V10目前的版本是基於centos8,所以可以類比上述兩篇文章中提到的批量部署RHEL的經驗。下面就針對本次實施中遇到的問題逐一進行分析。

 

一、關於PXE獲取到IP之後無ACK,無法獲取引導文件。

 

目前ARM服務器基本都是使用UEFI的方式進行引導,我們只需要關注EFI方式引導即可,Legacy引導已經隨着時代的發展被掃進歷史的垃圾桶。

 

正常情況下通過DHCP引導的PXE安裝, DHCPdiscover -> DHCPoffer -> DHCPRequest -> DHCPACK,但是很奇怪的是在我們這個型號的服務器上始終沒有發現有DHCP ACK的記錄,這就意味着服務器無法獲取到EFI引導文件。原來以為是我的dhcpd.conf配置寫的不對,仔細核對了一翻發現沒有問題,也在虛擬機測試了一下能正常引導。經過一翻搜索,發現原來是鯤鵬920的ARM服務器,在dhcpd的vendor-class-identifier 參數定義有特殊的字符串,下面給出本次實施中使用的dhcpd.conf的部分配置文件。

 

subnet 192.168.3.0 netmask 255.255.255.0
{
    range 192.168.3.10 192.168.3.239;
    option routers 192.168.3.3;
    next-server 192.168.3.3;

    class "HW-client" {
        match if substring
            (option vendor-class-identifier, 0, 9) =
            "HW-Client";
        if option architecture-type = 00:0b {
                # Huawei Kunpeng 920 ARM64 aarch64 EFI BIOS
                filename "images/BOOTAA64.EFI";
            }
    }

    class "pxeclients" {
        match if substring
            (option vendor-class-identifier, 0, 9) =
            "PXEClient";
        if option architecture-type = 00:07 or
            option architecture-type = 00:09 {
                # x86-64 EFI BIOS
                filename "images/shim.efi";
                # filename "images/BOOTX64.efi";
            } else if option architecture-type = 00:0b {
                # ARM64 aarch64 EFI BIOS
                filename "images/BOOTAA64.EFI";
            } else {
                # Legacy non-EFI BIOS
                filename "pxelinux.0";
            }
    }
}

 

為了兼顧多種平台的pxe引導需要,我們一般使用dhcpd.conf 中的class類功能進行不同cpu平台的區分,x86平台基本上默認vendor-class-identifier 標識符都是 PXEClient 這個字符串,而ARM的生態目前還遠不如x86這樣高度統一,這就造成了不同的廠商可能會對各自生產的平台進行自定義,對於鯤鵬920的平台,需要將 vendor-class-identifier 設為 HW-Client,見上面配置文件的標紅部分,注意該標識符大小寫必須完全一致。在修改了vendor-class-identifier之後,終於能正常獲取efi引導文件。

 

從UEFI的規範文件中我們看到,arm平台和x86平台的efi引導文件是不一樣的,如下圖。

 

 

所以本次的實施中,我們需要從麒麟aarch64的安裝ISO中,提取名為BOOTAA64.EFI以及grubaa64.efi,以引導至grub efi的bootloader界面進一步進行安裝程序的後續引導。需要注意的是x86平台和arm64平台的efi文件都是不通用的。

 

二、關於clonezilla的arm64版本。

 

clonezilla目前的官方正式發佈的版本裏面,只有x86-64的iso,經過一番尋找,在官網找到了experimental 的實驗性質的arm64的版本iso,下載地址為 //free.nchc.org.tw/clonezilla-live/experimental/arm/20200414-focal/ ,這個是基於ubuntu 20.04 arm64的版本。實測可以正常用於引導本次實施中使用的鯤鵬920的TG225 B1服務器。

至於為什麼要選擇clonezilla用來自動配RAID,前序文章有提到,這裡再寫一下。其一是clonezilla的iso較小(約300M)引導較快;其二是它支持通過grub的引導參數來傳遞自定義參數,且支持的參數語法非常的靈活,諸如運行自定義腳本、掛載nfs此類都不在話下,如此一來引導之後調用raid卡的管理工具進行自動配raid的操作就不足為奇了。

 

三、關於Adaptec的RAID卡的配置工具。

 

前序文章中我們在上一次實施x86的批量裝機,大多配的是LSI/BCM/AVAGO的RAID卡,使用storcli的命令行工具可以方便的進行RAID配置。Adaptec的RAID卡也有自家的命令行管理工具叫arcconf ,使用方法跟前序文章中提到的 storcli 基本只有參數語法的差別。下面分享一下本次實施中使用的arcconf的命令。

 

arcconf DELETE 1 ARRAY ALL noprompt
arcconf create 1 logicaldrive max 5 0 8 0 9 0 10 0 11 0 12 0 13 0 14 0 15 noprompt

 

大致解釋一下這個參數的意思,delete 1是指對raid controller 1進行刪除操作,刪除對象是 array all 即所有raid組,noprompt是不提示直接刪除。第二行的create 1 是指對raid controller 1 logicaldrive進行創建邏輯盤即raid組,max是指使用raid組的最大空間,5是指raid5,後面的0 8一直到0 15是指將哪些盤加入raid組中,這個盤號可以使用 arcconf list 1來獲取。

 

 

四、關於麒麟V10進行pxe引導的一系列詭異問題及bug。

 

menuentry 'Install Kylin V10 @ ARM64 UEFI Manually' --class red --class gnu-linux --class gnu --class os {
    linux /images/kylin/vmlinuz ip=dhcp inst.repo=//192.168.3.3/kylin console=tty0 video=VGA-1:640x480-32@60me
    # linux /images/kylin/vmlinuz rd.debug ip=dhcp inst.repo=nfs:192.168.3.3:/mnt/kylin/ console=tty0 video=VGA-1:640x480-32@60me
    initrd /images/kylin/initrd.img
}

menuentry 'Install Kylin V10 @ ARM64 UEFI Kickstart' --class red --class gnu-linuxefi --class gnu --class os {
    linux /images/kylin/vmlinuz ip=dhcp inst.ks=//192.168.3.3/ks.cfg console=tty0 video=VGA-1:640x480-32@60me
    initrd /images/kylin/initrd.img
}

 

上面是我們在本次實施中最終成功引導的grub引導參數,供參考。

arm64的grub的內核和initrd行的關鍵字跟x86不一樣,x86的efi方式引導的內核和initrd行的關鍵字分別是 linuxefi 和 initrdefi,不知道為何到了arm64中,又改回跟legacy模式引導一樣 linux 和 initrd 了,實測如果跟x86平台一樣在上述關鍵字後面加上efi的後綴,無法正常引導。

 

在正常獲取了內核和initrd之後,就應該引導到安裝界面了。但是在參考了kylinV10的安裝光盤的grub配置文件,原來是沒有 console=tty0 這個參數的。實測中發現如果不加這個參數,則會導致加載完內核和initrd之後一直就卡在光標閃爍的界面不動了無法進到安裝界面,加了console的參數才正常。這個問題非常的詭異,使用光盤iso安裝就不需要,而使用pxe就需要,怎麼也說不過去。

 

 

在前序文章中,我們使用nfs方式來掛載rhel7的安裝iso進行pxe安裝。然而在本次的實施中,使用nfs掛載kylinV10的介質始終無法引導到安裝界面,更為神奇的是在我們的dhcp server的虛擬機的日誌中是能很明顯的看到nfs的成功掛載安裝介質目錄的動作的。後續無奈只能使用http方式,這樣便可以順利引導到安裝界面了。猜測可能是kylinV10的bug,在不指定版本的情況下默認應該是掛載的NFSv4,也可能是只支持v3吧。

 

在踩了上面3個坑之後,終於看到了久違的安裝界面,但是問題又來了。在安裝界面無法正常獲取到安裝介質的repo,這就直接導致了無法選擇需要安裝的包無法繼續安裝。後面在麒麟廠商技術支持的指導下,我們發現原來是到了這個安裝界面之後,網卡沒能正常獲取到ip地址,這個肯定是kylinV10的bug了。要解決這個問題,在圖形安裝界面的網卡配置那裡,把網卡關一下再開一下,正確獲取到IP之後,安裝源就能正常獲取到了。然後我們就對第一台服務器通過手動的方式完成了安裝,安裝完成重啟進系統之後,在/root目錄下面,它生成了kickstart的cfg文件,可以用於後續其它機器的批量自動安裝OS。

 

但是這裡又出現了另外一個問題,如果到安裝界面後不能正確dhcp獲取到IP,那就意味着後面使用kickstart的批量安裝時同樣會由於無法獲取到IP而造成自動安裝失敗。為了解決這個問題,廠商建議是使用新版的install.img來進行安裝,由於我們的http的安裝介質是直接用廠商提供的iso掛載的,如果要替換這個文件,還得把iso解壓出來,費時費力。經過分析,由於是第一次獲取不到IP,那麼我們在kickstart的文件裏面,在安裝開始前手動跑一下dhclient 獲取一下IP,最終發現這個方法是可行的。操作起來很簡單,編輯ks的cfg文件,在文件最開始,加入如下三行即可。

%pre
/sbin/dhclient
%end

 

最後的最後,我們還發現,手動安裝的kylinV10自動生成的kickstart文件,在分區的部分會生成一些帶有小數大小的分區或LV,而安裝程序在解析kickstart文件時,遇到帶有小數時直接就報錯無法繼續安裝。解決辦法也很簡單,直接編輯kickstart文件,在分區/LV配置部分,把小數點及後面的小數直接刪掉。在這個地方也能出現這樣明顯的bug是我萬萬沒想到的。