您的位置:首页 > 运维架构 > Linux

如何构建一台网络引导服务器(三) | Linux 中国

2019-01-02 09:55 477 查看
我们将向你展示如何设置一个更复杂的 iPXE 配置。它将允许终端用户以更容易的方式去选择引导哪个操作系统。它也可以配置为让系统管理员从一台中央服务器来统一管理引导菜单。
-- Gregory Bartholomew

致谢
译自 | fedoramagazine.org 
作者 | Gregory Bartholomew
译者 | LCTT / qhwdw

在 如何构建一台网络引导服务器(一)[1] 中,我们提供了一个极简的 iPXE[2] 引导脚本来引导你的网络引导镜像。许多用户除了使用网络引导镜像外,可能在机器本地也有一个操作系统。但是使用常见的工作站的 BIOS 去切换引导加载器是很笨拙的。在本系列文件的第三部分,我们将向你展示如何设置一个更复杂的 iPXE 配置。它将允许终端用户以更容易的方式去选择引导哪个操作系统。它也可以配置为让系统管理员从一台中央服务器来统一管理引导菜单。

一个交互式 iPXE 引导菜单

下面这些命令重定义了网络引导镜像的 boot.cfg 来作为一个交互式的 iPXE 引导菜单,并使用了一个 5 秒倒计时的定时器:

  1. $ MY_FVER=29

  2. $ MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)

  3. $ MY_DNS1=192.0.2.91

  4. $ MY_DNS2=192.0.2.92

  5. $ MY_NAME=server-01.example.edu

  6. $ MY_EMAN=$(echo $MY_NAME | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_NAME})

  7. $ MY_ADDR=$(host -t A $MY_NAME | awk '{print $4}')

  8. $ cat << END > $HOME/esp/linux/boot.cfg

  9. #!ipxe

  10. set timeout 5000

  11. :menu

  12. menu iPXE Boot Menu

  13. item --key 1 lcl 1. Microsoft Windows 10

  14. item --key 2 f$MY_FVER 2. RedHat Fedora $MY_FVER

  15. choose --timeout \${timeout} --default lcl selected || goto shell

  16. set timeout 0

  17. goto \${selected}

  18. :failed

  19. echo boot failed, dropping to shell...

  20. goto shell

  21. :shell

  22. echo type 'exit' to get the back to the menu

  23. set timeout 0

  24. shell

  25. goto menu

  26. :lcl

  27. exit

  28. :f$MY_FVER

  29. 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

  30. initrd --name initrd.img \${prefix}/initramfs-$MY_KRNL.img

  31. boot || goto failed

  32. END

上述菜单有五个节:

◈ menu 定义了显示在屏幕上的实际菜单内容。
◈ failed 提示用户发生了错误,并将用户带到 shell 以错误错误。
◈ shell 提供了交互式命令提示符。你可以在引导菜单出现时按下 Esc 键进入,或者是 boot 命令失败时也会进入到命令提示符。
◈ lcl 包含一个提供给 iPXE 退出的简单命令,以及返还控制权给 BIOS。在 iPXE 之后,无论你希望缺省引导的设备(即:工作站的本地硬件)是什么,都必须在你的工作站的 BIOS 中正确地作为下一个引导设备列出来。
◈ f29 包含前面文章提到同一个网络引导代码,但使用最终的退出代码来替换掉 goto failed

从你的 $HOME/esp/linux 目录中复制更新后的 boot.cfg 到所有客户端系统的 ESP 中。如果一切顺利,你应该会看到类似下面图片的结果:

一个服务器托管的引导菜单

你可以添加到网络引导服务器的另一个特性是,能够从一台中央位置去管理所有客户端的引导菜单。这个特性尤其适用于批量安装(升级)一个新版本的操作系统。在你将新内核和新的 initramfs 复制到所有客户端的 ESP 之后,这个特性可以让你执行一种 原子事务[3] 去切换所有客户端到新操作系统。

安装 Mojolicious:

  1. $ sudo -i

  2. # dnf install -y perl-Mojolicious

定义 “bootmenu” 应用程序:

  1. # mkdir /opt/bootmenu

  2. # cat << END > /opt/bootmenu/bootmenu.pl

  3. #!/usr/bin/env perl

  4. use Mojolicious::Lite;

  5. use Mojolicious::Plugins;

  6. plugin 'Config';

  7. get '/menu';

  8. app->start;

  9. END

  10. # chmod 755 /opt/bootmenu/bootmenu.pl

为 “bootmenu” 应用程序定义配置文件:

  1. # cat << END > /opt/bootmenu/bootmenu.conf

  2. {

  3. hypnotoad => {

  4. listen => ['http://*:80'],

  5. pid_file => '/run/bootmenu/bootmenu.pid',

  6. }

  7. }

  8. END

这是一个非常简单的 Mojolicious 应用程序,它监听 80 端口,并且只回应对 /menu 的请求。如果你想快速了解 Mojolicious 能做什么,运行 man Mojolicious::Guides::Growing 去查看手册。按 Q 键退出手册。

将 boot.cfg 移到我们的网络引导应用程序中作为一个名为 menu.html.ep 的模板:

  1. # mkdir /opt/bootmenu/templates

  2. # mv $HOME/esp/linux/boot.cfg /opt/bootmenu/templates/menu.html.ep

定义一个 systemd 服务去管理引导菜单应用程序:

  1. # cat << END > /etc/systemd/system/bootmenu.service

  2. [Unit]

  3. Description=Serves iPXE Menus over HTTP

  4. After=network-online.target

  5. [Service]

  6. Type=forking

  7. DynamicUser=true

  8. RuntimeDirectory=bootmenu

  9. PIDFile=/run/bootmenu/bootmenu.pid

  10. ExecStart=/usr/bin/hypnotoad /opt/bootmenu/bootmenu.pl

  11. ExecReload=/usr/bin/hypnotoad /opt/bootmenu/bootmenu.pl

  12. AmbientCapabilities=CAP_NET_BIND_SERVICE

  13. KillMode=process

  14. [Install]

  15. WantedBy=multi-user.target

  16. END

在本地防火墙中为 HTTP 服务添加一个例外规则,并启动 bootmenu 服务:

  1. # firewall-cmd --add-service http

  2. # firewall-cmd --runtime-to-permanent

  3. # systemctl enable bootmenu.service

  4. # systemctl start bootmenu.service

用 wget 测试它:

  1. $ sudo dnf install -y wget

  2. $ MY_BOOTMENU_SERVER=server-01.example.edu

  3. $ wget -q -O - http://$MY_BOOTMENU_SERVER/menu

以上的命令应该会输出类似下面的内容:

  1. #!ipxe

  2. set timeout 5000

  3. :menu

  4. menu iPXE Boot Menu

  5. item --key 1 lcl 1. Microsoft Windows 10

  6. item --key 2 f29 2. RedHat Fedora 29

  7. choose --timeout ${timeout} --default lcl selected || goto shell

  8. set timeout 0

  9. goto ${selected}

  10. :failed

  11. echo boot failed, dropping to shell...

  12. goto shell

  13. :shell

  14. echo type 'exit' to get the back to the menu

  15. set timeout 0

  16. shell

  17. goto menu

  18. :lcl

  19. exit

  20. :f29

  21. 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

  22. initrd --name initrd.img ${prefix}/initramfs-4.19.4-300.fc29.x86_64.img

  23. boot || goto failed

现在,引导菜单服务器已经正常工作了,重新构建 ipxe.efi 引导加载器,使用一个初始化脚本指向它。

第一步,先更新我们在本系列文章的第一部分中创建的 init.ipxe 脚本:

  1. $ MY_BOOTMENU_SERVER=server-01.example.edu

  2. $ cat << END > $HOME/ipxe/init.ipxe

  3. #!ipxe

  4. dhcp || exit

  5. set prefix file:///linux

  6. chain http://$MY_BOOTMENU_SERVER/menu || exit

  7. END

现在,重新构建引导加载器:

  1. $ cd $HOME/ipxe/src

  2. $ make clean

  3. $ make bin-x86_64-efi/ipxe.efi EMBED=../init.ipxe

将更新后的引导加载器复制到你的 ESP 中:

  1. $ cp $HOME/ipxe/src/bin-x86_64-efi/ipxe.efi $HOME/esp/efi/boot/bootx64.efi

将更新后的引导加载器复制到所有的客户端中之后,以后更新引导菜单只需要简单地编辑 /opt/bootmenu/templates/menu.html.ep 文件,然后再运行如下命令:

  1. $ sudo systemctl restart bootmenu.service

做一步的改变

如果引导菜单服务器工作正常,在你的客户端系统上的 boot.cfg 文件将更长。

比如,重新添加 Fedora 28 镜像到引导菜单中:

  1. $ sudo -i

  2. # MY_FVER=28

  3. # MY_KRNL=$(ls -c /fc$MY_FVER/lib/modules | head -n 1)

  4. # MY_DNS1=192.0.2.91

  5. # MY_DNS2=192.0.2.92

  6. # MY_NAME=$(</etc/hostname)

  7. # MY_EMAN=$(echo $MY_NAME | tr '.' "\n" | tac | tr "\n" '.' | cut -b -${#MY_NAME})

  8. # MY_ADDR=$(host -t A $MY_NAME | awk '{print $4}')

  9. # cat << END >> /opt/bootmenu/templates/menu.html.ep

  10. :f$MY_FVER

  11. 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

  12. initrd --name initrd.img \${prefix}/initramfs-$MY_KRNL.img

  13. boot || goto failed

  14. END

  15. # sed -i "/item --key 2/a item --key 3 f$MY_FVER 3. RedHat Fedora $MY_FVER" /opt/bootmenu/templates/menu.html.ep

  16. # systemctl restart bootmenu.service

如果一切顺利,你的客户端下次引导时,应该看到如下图所示的结果:


via: https://fedoramagazine.org/how-to-build-a-netboot-server-part-3/

作者:Gregory Bartholomew[5] 选题:lujun9972 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: