モチベーション


十数台のハードウェアPCを手に入れることができ、クラスタを構築することになった。

インストールするライブラリを頻繁に変更する可能性があるため、一括の環境更新がしやすいようネットワークブートによる環境構築を行うことにした。

本記事の対象


この投稿では、Ubuntu 22.04 Serverを用いて、PXEサーバー構築クライアントPCでインストールウィザード表示 までを対象としています。

なお、Autoinstallによる構成自動化については、別記事にまとめることにします。

作業環境


  • サーバーPC
    • OS:Ubuntu 22.04
    • NIC
      • オンボード 1Gbps NIC (Intel Corporation Ethernet Connection (17) I219-V (rev 11))
      • PCIe 1Gbps NIC (Intel Corporation 82574L Gigabit Network Connection)
  • クライアントPC
    • UEFI Bootに対応
    • NIC
      • オンボード 1Gbps NIC
      • PCIe 10Gbps NIC

作業手順


  1. まず、サーバー側とクライアント側をLANケーブルで接続します。
    • 後述する理由により、2口以上のポートがある場合、なるべくオンボードのNICドライバが安定しているNICを介して接続することを推奨します
  2. サーバー側のネットワーク設定を行います
    1. 先ほど接続したLANケーブルが刺さっているポート(PXE Bootを提供するポート)のインタフェース名を把握しておきます。
      • 以下の例では eno1 という名前のインタフェース を使用しています。
    2. そのインタフェースに静的IPを割り振ります
      • DHCPサーバーを途中で建てるのですが、その範囲外のIPを指定しましょう
      • やり方いろいろ
        • netplan
        • GUIから設定(今回私はこちらでやりました)
  • 以下の例では、 192.168.0.2/24 というIPを設定しています
  1. 以後基本は Netbooting the server installer on amd64 - Ubuntu公式フォーラム にのっとって行います

手順3について、一部、私の環境に合わせて変更しています。詳しくは以下の通りです:

20.04を22.04に読み替えている

上記記事はUbuntuの20.04をベースに解説していますが、22.04をベースにできるように変更しています。 20.04のコードネームは focal で 22.04のコードネームは jammy です。本投稿の下の方に今回使用した設定ファイルとディレクトリ構造についてまとめていますので、そちらも参考にしてください。

ファイルないよって怒られた

apt download shim-signed
dpkg-deb --fsys-tarfile shim-signed*deb | tar x ./usr/lib/shim/shimx64.efi.signed -O > /srv/tftp/bootx64.efi

apt download shim-signed
dpkg-deb --fsys-tarfile shim-signed*deb | tar x ./usr/lib/shim/shimx64.efi.signed.latest -O > /srv/tftp/bootx64.efi

UEFI bootingを使用

  • 今回、クライアントPCがUEFIに対応しているものであったため、Set up the files for legacy boot ではなく、 Set up the files for UEFI booting の方で行いました。
  • 近年のOSブートプロセスは、セキュリティ強化のために署名つきのものを使用しないといけない、など制約が厳しくなっているようです。
    • レガシーなブート方法(BIOS legacy boot)を紹介しているサイトがかなり多い印象です。
    • また、UEFI bootBIOS legacy bootの手順を混同しているもの、Autoinstall等の構成自動化と混ぜて解説しておりどこでつまづいたのか結局よくわからなくなるサイト等も多い印象です。
  • OSインストールのフローにおいて、PXE Boot構成自動化は排他な概念です。まず前者ができるところまで持っていって初めて後者ができるので、本記事の内容が出来次第、Autoinstall等の構成自動化に持っていった方が、トラブルシューティングがしやすいですね。

vmlinux → vmlinuz

grub.cfgでタイポがあります。

menuentry 'Ubuntu 22.04' {
        gfxmode $linux_gfx_mode
        linux /vmlinuz ip=dhcp url=http://192.168.62.2/iso/jammy-live-server-amd64.iso --
        initrd /initrd
}

つまづきポイント・デバッグ方法


とりあえず見直すなら

  • 使用するクライアントPCがどのブート方式に対応しているか(UEFI boot or BIOS legacy boot
  • それぞれのブート方式に適した起動用ファイルを使用しているか

はチェックしておくべきでしょう。

なんかこういう画面が出た

grubのプロンプトに落ちた画像

grub2がPXE Bootを行う際に何らかのトラブルが発生し、処理を続行できなくなった場合に grub> というプロンプト画面が表示されるようです。私の実施した環境ではこの現象が発生しました。

解決法:

  • クライアントPCとの接続を、10Gbps NICではなく、1Gbps NICを使って行う とこのプロンプト画面が表示されず、ウィザード画面まで進むことができました。

原因:

  • おそらく 10Gbps NIC との相性の問題と思います
    • Fetching Netboot Imageが表示されている間、本来はIPパケットを送受信して欲しいのに、PXE Serverの方でtcpdumpしてパケットを監視してみると、ARP RequestとARP Replyだけを送り合うだけの時間になっていた
    • grubのプロンプトに cat (tftp,192.168.62.2)/grub/grub.cfg って打つと、しばらく待ったのち、「could not resolve hardware address」的なエラーが返ってきた。これはすなわち、grubがIPアドレスをMACアドレスに変換することに失敗したということを意味しているはず。
    • ARP ReplyとPXEに関する記事を探したら、こういうのが出てきた
    • なので、なるべく安定しているであろうドライバを使える環境に移った方が良いと判断し、1G NICに繋ぎ直したら、治った

手順については記載があるサイトが多いのですが、実機によるトラブル報告は少ないので役に立つといいです。

最終的な設定ファイル群

HTTPサーバー

$ tree /var/www/html/
/var/www/html/
├── index.html
└── iso
    └── jammy-live-server-amd64.iso

TFTPサーバー

$ tree /srv/tftp/
/srv/tftp/
├── boot-amd64 -> /usr/share/cd-boot-images-amd64
├── bootx64.efi
├── grub
│   └── grub.cfg
├── grubx64.efi
├── initrd
├── unicode.pf2
└── vmlinuz

dnsmasq confファイル

$ cat /etc/dnsmasq.d/pxe.conf 
interface=eno1,lo

bind-interfaces
dhcp-range=eno1,192.168.0.100,192.168.0.200
dhcp-boot=pxelinux.0
dhcp-match=set:efi-x86_64,option:client-arch,7
dhcp-boot=tag:efi-x86_64,bootx64.efi
enable-tftp
tftp-root=/srv/tftp

grub.cfg

set default="0"
set timeout=-1

if loadfont unicode ; then
  set gfxmode=auto
  set locale_dir=$prefix/locale
  set lang=en_US
fi
terminal_output gfx_term

set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
if background_color 44,0,30; then
  clear
fi

function gfxmode {
  set gfxpayload="${1}"
  if [ "${1}" = "keep" ]; then
    set vt_handoff=vt.handoff=7
  else
    set vt_handoff=
  fi
}

set linux_gfx_mode=keep

export linux_gfx_mode

menuentry 'Ubuntu 22.04' {
  gfxmode $linux_gfx_mode
  linux /vmlinuz ip=dhcp url=http://192.168.0.2/iso/jammy-live-server-amd64.iso --
  initrd /initrd
}

参照した記事