如何構建一台網路引導伺服器(三)
在 如何構建一台網路引導伺服器(一) 中,我們提供了一個極簡的 iPXE 引導腳本來引導你的網路引導鏡像。許多用戶除了使用網路引導鏡像外,可能在機器本地也有一個操作系統。但是使用常見的工作站的 BIOS 去切換引導載入器是很笨拙的。在本系列文件的第三部分,我們將向你展示如何設置一個更複雜的 iPXE 配置。它將允許終端用戶以更容易的方式去選擇引導哪個操作系統。它也可以配置為讓系統管理員從一台中央伺服器來統一管理引導菜單。
一個互動式 iPXE 引導菜單
下面這些命令重定義了網路引導鏡像的 boot.cfg
來作為一個互動式的 iPXE 引導菜單,並使用了一個 5 秒倒計時的定時器:
$ MY_FVER=29
$ MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)
$ MY_DNS1=192.0.2.91
$ MY_DNS2=192.0.2.92
$ MY_NAME=server-01.example.edu
$ MY_EMAN=$(echo $MY_NAME | tr '.' "n" | tac | tr "n" '.' | cut -b -${#MY_NAME})
$ MY_ADDR=$(host -t A $MY_NAME | awk '{print $4}')
$ cat << END > $HOME/esp/linux/boot.cfg
#!ipxe
set timeout 5000
:menu
menu iPXE Boot Menu
item --key 1 lcl 1. Microsoft Windows 10
item --key 2 f$MY_FVER 2. RedHat Fedora $MY_FVER
choose --timeout ${timeout} --default lcl selected || goto shell
set timeout 0
goto ${selected}
:failed
echo boot failed, dropping to shell...
goto shell
:shell
echo type 'exit' to get the back to the menu
set timeout 0
shell
goto menu
:lcl
exit
:f$MY_FVER
kernel --name kernel.efi ${prefix}/vmlinuz-$MY_KRNL initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=$MY_DNS1 nameserver=$MY_DNS2 root=/dev/disk/by-path/ip-$MY_ADDR:3260-iscsi-iqn.$MY_EMAN:fc$MY_FVER-lun-1 netroot=iscsi:$MY_ADDR::::iqn.$MY_EMAN:fc$MY_FVER console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-$MY_KRNL.img
boot || goto failed
END
上述菜單有五個節:
menu
定義了顯示在屏幕上的實際菜單內容。failed
提示用戶發生了錯誤,並將用戶帶到 shell 以錯誤錯誤。shell
提供了互動式命令提示符。你可以在引導菜單出現時按下Esc
鍵進入,或者是boot
命令失敗時也會進入到命令提示符。lcl
包含一個提供給 iPXE 退出的簡單命令,以及返還控制權給 BIOS。在 iPXE 之後,無論你希望預設引導的設備(即:工作站的本地硬體)是什麼,都必須在你的工作站的 BIOS 中正確地作為下一個引導設備列出來。f29
包含前面文章提到同一個網路引導代碼,但使用最終的退出代碼來替換掉goto failed
。
從你的 $HOME/esp/linux
目錄中複製更新後的 boot.cfg
到所有客戶端系統的 ESP 中。如果一切順利,你應該會看到類似下面圖片的結果:
一個伺服器託管的引導菜單
你可以添加到網路引導伺服器的另一個特性是,能夠從一台中央位置去管理所有客戶端的引導菜單。這個特性尤其適用於批量安裝(升級)一個新版本的操作系統。在你將新內核和新的 MARKDOWN_HASH50929bac7304e38629221d43c18db25eMARKDOWNHASH
複製到所有客戶端的 ESP 之後,這個特性可以讓你執行一種 [原子事務](https://en.wikipedia.org/wiki/Atomicity(database_systems)) 去切換所有客戶端到新操作系統。
安裝 Mojolicious:
$ sudo -i
# dnf install -y perl-Mojolicious
定義 「bootmenu」 應用程序:
# mkdir /opt/bootmenu
# cat << END > /opt/bootmenu/bootmenu.pl
#!/usr/bin/env perl
use Mojolicious::Lite;
use Mojolicious::Plugins;
plugin 'Config';
get '/menu';
app->start;
END
# chmod 755 /opt/bootmenu/bootmenu.pl
為 「bootmenu」 應用程序定義配置文件:
# cat << END > /opt/bootmenu/bootmenu.conf
{
hypnotoad => {
listen => ['http://*:80'],
pid_file => '/run/bootmenu/bootmenu.pid',
}
}
END
這是一個非常簡單的 Mojolicious 應用程序,它監聽 80 埠,並且只回應對 /menu
的請求。如果你想快速了解 Mojolicious 能做什麼,運行 man Mojolicious::Guides::Growing
去查看手冊。按 Q
鍵退出手冊。
將 boot.cfg
移到我們的網路引導應用程序中作為一個名為 menu.html.ep
的模板:
# mkdir /opt/bootmenu/templates
# mv $HOME/esp/linux/boot.cfg /opt/bootmenu/templates/menu.html.ep
定義一個 systemd 服務去管理引導菜單應用程序:
# cat << END > /etc/systemd/system/bootmenu.service
[Unit]
Description=Serves iPXE Menus over HTTP
After=network-online.target
[Service]
Type=forking
DynamicUser=true
RuntimeDirectory=bootmenu
PIDFile=/run/bootmenu/bootmenu.pid
ExecStart=/usr/bin/hypnotoad /opt/bootmenu/bootmenu.pl
ExecReload=/usr/bin/hypnotoad /opt/bootmenu/bootmenu.pl
AmbientCapabilities=CAP_NET_BIND_SERVICE
KillMode=process
[Install]
WantedBy=multi-user.target
END
在本地防火牆中為 HTTP 服務添加一個例外規則,並啟動 bootmenu 服務:
# firewall-cmd --add-service http
# firewall-cmd --runtime-to-permanent
# systemctl enable bootmenu.service
# systemctl start bootmenu.service
用 wget
測試它:
$ sudo dnf install -y wget
$ MY_BOOTMENU_SERVER=server-01.example.edu
$ wget -q -O - http://$MY_BOOTMENU_SERVER/menu
以上的命令應該會輸出類似下面的內容:
#!ipxe
set timeout 5000
:menu
menu iPXE Boot Menu
item --key 1 lcl 1. Microsoft Windows 10
item --key 2 f29 2. RedHat Fedora 29
choose --timeout ${timeout} --default lcl selected || goto shell
set timeout 0
goto ${selected}
:failed
echo boot failed, dropping to shell...
goto shell
:shell
echo type 'exit' to get the back to the menu
set timeout 0
shell
goto menu
:lcl
exit
:f29
kernel --name kernel.efi ${prefix}/vmlinuz-4.19.4-300.fc29.x86_64 initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=192.0.2.91 nameserver=192.0.2.92 root=/dev/disk/by-path/ip-192.0.2.158:3260-iscsi-iqn.edu.example.server-01:fc29-lun-1 netroot=iscsi:192.0.2.158::::iqn.edu.example.server-01:fc29 console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-4.19.4-300.fc29.x86_64.img
boot || goto failed
現在,引導菜單伺服器已經正常工作了,重新構建 ipxe.efi
引導載入器,使用一個初始化腳本指向它。
第一步,先更新我們在本系列文章的第一部分中創建的 init.ipxe
腳本:
$ MY_BOOTMENU_SERVER=server-01.example.edu
$ cat << END > $HOME/ipxe/init.ipxe
#!ipxe
dhcp || exit
set prefix file:///linux
chain http://$MY_BOOTMENU_SERVER/menu || exit
END
現在,重新構建引導載入器:
$ cd $HOME/ipxe/src
$ make clean
$ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe
將更新後的引導載入器複製到你的 ESP 中:
$ cp $HOME/ipxe/src/bin-x86_64-efi/ipxe.efi $HOME/esp/efi/boot/bootx64.efi
將更新後的引導載入器複製到所有的客戶端中之後,以後更新引導菜單只需要簡單地編輯 /opt/bootmenu/templates/menu.html.ep
文件,然後再運行如下命令:
$ sudo systemctl restart bootmenu.service
做一步的改變
如果引導菜單伺服器工作正常,在你的客戶端系統上的 boot.cfg
文件將更長。
比如,重新添加 Fedora 28 鏡像到引導菜單中:
$ sudo -i
# MY_FVER=28
# MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)
# MY_DNS1=192.0.2.91
# MY_DNS2=192.0.2.92
# MY_NAME=$(</etc/hostname)
# MY_EMAN=$(echo $MY_NAME | tr '.' "n" | tac | tr "n" '.' | cut -b -${#MY_NAME})
# MY_ADDR=$(host -t A $MY_NAME | awk '{print $4}')
# cat << END >> /opt/bootmenu/templates/menu.html.ep
:f$MY_FVER
kernel --name kernel.efi ${prefix}/vmlinuz-$MY_KRNL initrd=initrd.img ro ip=dhcp rd.peerdns=0 nameserver=$MY_DNS1 nameserver=$MY_DNS2 root=/dev/disk/by-path/ip-$MY_ADDR:3260-iscsi-iqn.$MY_EMAN:fc$MY_FVER-lun-1 netroot=iscsi:$MY_ADDR::::iqn.$MY_EMAN:fc$MY_FVER console=tty0 console=ttyS0,115200n8 audit=0 selinux=0 quiet
initrd --name initrd.img ${prefix}/initramfs-$MY_KRNL.img
boot || goto failed
END
# sed -i "/item --key 2/a item --key 3 f$MY_FVER 3. RedHat Fedora $MY_FVER" /opt/bootmenu/templates/menu.html.ep
# systemctl restart bootmenu.service
如果一切順利,你的客戶端下次引導時,應該看到如下圖所示的結果:
via: https://fedoramagazine.org/how-to-build-a-netboot-server-part-3/
作者:Gregory Bartholomew 選題:lujun9972 譯者:qhwdw 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive