[VMware] iPXE を使用した Nested ESXi の PXE ブート

本記事では、AlmaLinux 9.5 を PXE サーバーとして構築し、iPXE を活用して Nested ESXi 8.0
をネットワーク (UEFI PXE) で起動する検証を行いました。

以下の記事では ESXi 標準の bootx64.efi のみを使って PXE ブートする手順を記載しましたが、
iPXE を使うと iPXE メニュー や HTTP 経由での boot.cfg 取得が容易になるメリットがあります。

もし「検証環境などで複数バージョンの ESXi をまとめて PXE ブートしたい」、「HTTP で大きい
ファイルを安定して配布したい」といったニーズがあるなら、有用かもしれません。

<PXE サーバー OS / ネットワーク構成>
PXE サーバー OS: AlmaLinux 9.5
PXE サーバー IP: 192.168.1.70
DHCP/TFTP: dnsmasq を使用
DHCP で配布する IP 範囲: 192.168.1.230 ~ 192.168.1.250
SELinux: 無効化

<PXE ブート対象(クライアント)>
Nested ESXi
使用する ESXi イメージ:
VMware-VMvisor-Installer-8.0U3-24022510.x86_64.iso
VMware-VMvisor-Installer-8.0U2-22380479.x86_64.iso
VMware-VMvisor-Installer-8.0U1-21495797.x86_64.iso
VMware-VMvisor-Installer-8.0-20513097.x86_64.iso
セキュアブート: 無効

<iPXE を使用した PXE ブートの大まかな流れ>
1. UEFI が PXE (dhcp + tftp) → ipxe.efi をロード
2. iPXE が独自ネットワークスタックで DHCP 再取得 → 外部メニュー (menu.ipxe) を
  HTTP などで読み込み
3. iPXE メニュー でユーザーが ESXi バージョンを選択 →
  chain http://…/bootx64.efi -c http://…/boot.cfg
4. ESXi ローダー (bootx64.efi) が boot.cfg を参照し、prefix=… でモジュールを取得
5. ESXi カーネル が展開・初期化 → インストーラ起動

SELinux の無効化 (検証向け)

# 一時的に無効化
setenforce 0

# 設定ファイルを編集し、再起動後も無効化
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
reboot

dnsmasq (DHCP+TFTP) のインストールと設定

1. dnsmasq のインストール

dnf install -y dnsmasq

2. TFTP 用ディレクトリの作成

mkdir -p /var/lib/tftpboot

3. /etc/dnsmasq.conf の編集

vi などで /etc/dnsmasq.conf を開き、以下を追記

# 使用するネットワークインターフェイス名
interface=ens33

# DHCP で配布するIPアドレス範囲 (12時間リース)
dhcp-range=192.168.1.230,192.168.1.250,12h

# デフォルトゲートウェイ (ルーター) のIP
dhcp-option=3,192.168.1.254

# DNSサーバー
dhcp-option=6,192.168.1.24

# UEFI PXE 用ブートファイルを指定
dhcp-boot=ipxe.efi

# TFTP サーバーを有効化
enable-tftp
tftp-root=/var/lib/tftpboot

# ログ出力 (トラブルシュート用)
log-dhcp

4. dnsmasq の起動と自動起動設定

systemctl enable dnsmasq
systemctl start dnsmasq

Apache (HTTPサーバー) のインストールとファイアウォール設定

1. Apache のインストール

dnf install -y httpd
systemctl enable httpd
systemctl start httpd

2. ファイアウォール設定

firewall-cmd --permanent --add-service=dhcp
firewall-cmd --permanent --add-service=tftp
firewall-cmd --permanent --add-service=http
firewall-cmd --reload

これで DHCP (67/UDP), TFTP (69/UDP), HTTP (80/TCP) が外部からアクセス
可能になります。

iPXE EFI イメージの準備 (iPXE EFI イメージ (ipxe.efi) のビルド)

<参考>
https://ipxe.org/download
-> Source code

1. CRB リポジトリを有効化する

まずは、CodeReady Linux Builder (CRB) リポジトリを有効化します。
このリポジトリが無効化されていると、nasm や gnu-efi-devel といったパッケージを
インストールできない可能性があります。

dnf install -y dnf-plugins-core
dnf config-manager --set-enabled crb
dnf update -y

1. dnf-plugins-core: リポジトリ管理に必要なプラグイン群
2. –set-enabled crb: CRB リポジトリを有効化する
3. dnf update -y: パッケージ情報を最新化

2. 必要パッケージのインストール

dnf install -y gcc binutils make perl nasm gnu-efi gnu-efi-devel elfutils-libelf-devel

1. gcc, binutils, make, perl: 基本的なビルドツール
2. nasm: x86 アセンブリコードを扱うために必要
3. gnu-efi, gnu-efi-devel: UEFI アプリケーションのライブラリ・ヘッダ
4. elfutils-libelf-devel: ELF 関連のヘッダ/ライブラリ

3. iPXE ソースコードの取得

cd ~
git clone https://github.com/ipxe/ipxe.git
cd ipxe

4. 埋め込みスクリプト (embedded.ipxe) の作成

埋め込みスクリプトを作成することで、iPXE が起動すると自動的に dhcp → menu.ipxe
を取得しに行く挙動が実装できます。

vi embedded.ipxe で以下を作成します。

#!ipxe

# ネットワークをDHCPで取得
dhcp

# iPXE メニューを chain
chain http://192.168.1.70/ipxe/menu.ipxe

埋め込みスクリプト (embedded.ipxe) の作成をしない場合や http://boot.ipxe.org/ipxe.efi からビルド済みの iPXE バイナリを取得する
場合などには、iPXE 起動時に手動で dhcp 及び chain コマンドを実行する必要
があります。


手動で都度コマンドを実行するのも面倒なので、本記事では ipxe.efi をビルドして
自動化しています。

5. iPXE のビルド (UEFI 用)

ipxe/src ディレクトリに移動し、ターゲットを指定してコンパイルします。

cd src

# 埋め込みスクリプト(embedded.ipxe) ありの場合
make bin-x86_64-efi/ipxe.efi EMBED=../embedded.ipxe

成功すると ipxe/src/bin-x86_64-efi/ipxe.efi が生成。

6. ipxe.efi の配置 (TFTP ルート)

cp bin-x86_64-efi/ipxe.efi /var/lib/tftpboot/

これで TFTP 経由でビルドした ipxe.efi を配布できるようになります。

iPXE メニュー (menu.ipxe) の作成

1. ファイル配置

menu.ipxe は、ユーザーが起動する ESXi のバージョンを一覧から選ぶためのメニューです。
今回、HTTP サーバーの /var/www/html/ipxe/ ディレクトリに配置します。

mkdir -p /var/www/html/ipxe
vi /var/www/html/ipxe/menu.ipxe

iPXE メニューを embedded.ipxe に組み込むことも可能です。
ただし、組み込む場合、変更を加える度にビルドし直さないとダメになるので、
今回は外に出す構成としています。

2. menu.ipxe のサンプル

kernel … -c … の指定で、ESXi ローダー (bootx64.efi) と boot.cfg の両方を iPXE
の chainloading 方式で起動する形です。

#!ipxe

:start

menu iPXE Boot Menu

item --gap --            !!!!!!!!!!!!!!!!! Select an ESXi version to install !!!!!!!!!!!!!!!!!
item esxi80u3            ESXi 8.0 U3
item esxi80u2            ESXi 8.0 U2
item esxi80u1a           ESXi 8.0 U1
item esxi80ga            ESXi 8.0 GA

item --gap --            ============================= Utilities =============================
item shell               iPXE shell
item reboot              Reboot

choose target && goto ${target}

:esxi80u3
echo          Booting ESXi 8.0 U3
kernel http://192.168.1.70/esxi80u3/efi/boot/bootx64.efi -c http://192.168.1.70/esxi80u3/boot.cfg
boot

:esxi80u2
echo          Booting ESXi 8.0 U2
kernel http://192.168.1.70/esxi80u2/efi/boot/bootx64.efi -c http://192.168.1.70/esxi80u2/boot.cfg
boot

:esxi80u1a
echo          Booting ESXi 8.0 U1
kernel http://192.168.1.70/esxi80u1/efi/boot/bootx64.efi -c http://192.168.1.70/esxi80u1/boot.cfg
boot

:esxi80ga
echo          Booting ESXi 8.0 GA
kernel http://192.168.1.70/esxi80ga/efi/boot/bootx64.efi -c http://192.168.1.70/esxi80ga/boot.cfg
boot

:shell
echo          Entering iPXE shell...
shell
goto start

:reboot
reboot

ESXi のインストーラファイルを HTTP サーバー(/var/www/html)へ配置

1. ISO をマウント・コピー

今回 AlmaLinux は仮想マシンとして作成しているため、当該仮想マシンに ESXi の
インストーラー(ISO) をマウントし、各ファイルを Apache の公開ディレクトリ
(/var/www/html/esxi80u3 等) にコピーします。

#以下は esxi80u3 のみですが、同様に esxi80ga, esxi80u1, esxi80u2 の ISO も /var/www/html/ 以下に展開します。

mkdir -p /mnt/esxi80u3_iso
mount -o loop /dev/sr0 /mnt/esxi80u3_iso

mkdir -p /var/www/html/esxi80u3
cp -r /mnt/esxi80u3_iso/* /var/www/html/esxi80u3/

umount /mnt/esxi80u3_iso

今回は ESXi 8.0 GA/U1/U2/U3 を用意したため現在の /var/www/html/ 配下は
以下のようになっています。

/var/www/html
├── esxi80ga
│   ├── boot.cfg
│   ├── efi/boot/ (bootx64.efi 等)
│   ├── upgrade/ (esximage.zip 等)
│   ├── 各種 ESXi モジュール (b.b00, k.b00, *.v00 など)
│   └── ...
│
├── esxi80u1
│   ├── boot.cfg
│   ├── efi/boot/ (bootx64.efi 等)
│   ├── upgrade/ (esximage.zip 等)
│   ├── 各種 ESXi モジュール (b.b00, k.b00, *.v00 など)
│   └── ...
│
├── esxi80u2
│   ├── boot.cfg
│   ├── efi/boot/ (bootx64.efi 等)
│   ├── upgrade/ (esximage.zip 等)
│   ├── 各種 ESXi モジュール (b.b00, k.b00, *.v00 など)
│   └── ...
│
├── esxi80u3
│   ├── boot.cfg
│   ├── efi/boot/ (bootx64.efi 等)
│   ├── upgrade/ (esximage.zip 等)
│   ├── 各種 ESXi モジュール (b.b00, k.b00, *.v00 など)
│   └── ...
│
└── ipxe
    └── menu.ipxe

boot.cfg のパス修正 (HTTP でモジュールを読み込む)

ESXi はネットワークブート時(PXE 起動時)に boot.cfg を読み込み、prefix パラメータ
を参照して各モジュール (b.b00 / k.b00 / *.v00 など) をダウンロードします。

今回、複数バージョン (esxi80ga / esxi80u1 / esxi80u2 / esxi80u3)」を用意しているため、
各ディレクトリ内に boot.cfg があり、それぞれ prefix=http://192.168.1.70/esxi80ga/
(esxi80ga 部分はバージョンごとに書き換える) などに書き換える必要があります。

/var/www/html
├── esxi80ga
│   ├── boot.cfg   ← "/" を全て削除した後、prefix に prefix=http://192.168.1.70/esxi80ga/ を追記
│   └── ...
├── esxi80u1
│   ├── boot.cfg   ← "/" を全て削除した後、prefix に prefix=http://192.168.1.70/esxi80u1/ を追記
│   └── ...
├── esxi80u2
│   ├── boot.cfg   ← "/" を全て削除した後、prefix に prefix=http://192.168.1.70/esxi80u2/ を追記
│   └── ...
└── esxi80u3
    ├── boot.cfg   ← "/" を全て削除した後、prefix に prefix=http://192.168.1.70/esxi80u3/ を追記
    └── ...

まずは、各 ESXi の boot.cfg 内のファイルパス指定における “/” を全て削除。

cd /var/www/html/
find . -maxdepth 2 -type f -name 'boot.cfg' -exec sed -i 's|/||g' {} \;

次に、各 ESXi の boot.cfg 内の prefix に http://192.168.1.70/esxi80ga/ (esxi80ga
部分はバージョンごとに異なる) を追記します。

for d in esxi80ga esxi80u1 esxi80u2 esxi80u3; do
  sed -i 's|^prefix=.*|prefix=http://192.168.1.70/'"$d"'/|' "$d/boot.cfg"
done

上記コマンド実行後、以下のようになっています。
(例: ESXI 8.0 U3)

bootstate=0
title=Loading ESXi installer
timeout=5
prefix=http://192.168.1.70/esxi80u3/
kernel=b.b00
kernelopt=runweasel cdromBoot
modules=jumpstrt.gz --- useropts.gz --- features.gz --- k.b00 --- uc_intel.b00 --- uc_amd.b00 --- uc_hygon.b00 --- procfs.b00 --- vmx.v00 --- vim.v00 --- tpm.v00 --- sb.v00 --- s.v00 --- atlantic.v00 --- bcm_mpi3.v00 --- bnxtnet.v00 --- bnxtroce.v00 --- brcmfcoe.v00 --- cndi_igc.v00 --- dwi2c.v00 --- elxiscsi.v00 --- elxnet.v00 --- i40en.v00 --- iavmd.v00 --- icen.v00 --- igbn.v00 --- intelgpi.v00 --- ionic_cl.v00 --- ionic_en.v00 --- irdman.v00 --- iser.v00 --- ixgben.v00 --- lpfc.v00 --- lpnic.v00 --- lsi_mr3.v00 --- lsi_msgp.v00 --- lsi_msgp.v01 --- lsi_msgp.v02 --- mtip32xx.v00 --- ne1000.v00 --- nenic.v00 --- nfnic.v00 --- nhpsa.v00 --- nipmi.v00 --- nmlx5_cc.v00 --- nmlx5_co.v00 --- nmlx5_rd.v00 --- ntg3.v00 --- nvme_pci.v00 --- nvmerdma.v00 --- nvmetcp.v00 --- nvmxnet3.v00 --- nvmxnet3.v01 --- pvscsi.v00 --- qcnic.v00 --- qedentv.v00 --- qedrntv.v00 --- qfle3.v00 --- qfle3f.v00 --- qfle3i.v00 --- qflge.v00 --- rdmahl.v00 --- rste.v00 --- sfvmk.v00 --- smartpqi.v00 --- vmkata.v00 --- vmksdhci.v00 --- vmkusb.v00 --- vmw_ahci.v00 --- bmcal.v00 --- clusters.v00 --- crx.v00 --- drivervm.v00 --- elx_esx_.v00 --- btldr.v00 --- dvfilter.v00 --- esx_ui.v00 --- esxupdt.v00 --- tpmesxup.v00 --- weaselin.v00 --- esxio_co.v00 --- infravis.v00 --- loadesx.v00 --- lsuv2_hp.v00 --- lsuv2_in.v00 --- lsuv2_ls.v00 --- lsuv2_nv.v00 --- lsuv2_oe.v00 --- lsuv2_oe.v01 --- lsuv2_sm.v00 --- native_m.v00 --- qlnative.v00 --- trx.v00 --- vcls_pod.v00 --- vdfs.v00 --- vds_vsip.v00 --- vmware_e.v00 --- hbrsrv.v00 --- vsan.v00 --- vsanheal.v00 --- vsanmgmt.v00 --- tools.t00 --- xorg.v00 --- gc.v00 --- imgdb.tgz --- basemisc.tgz --- resvibs.tgz --- esxiodpt.tgz --- imgpayld.tgz
build=8.0.3-0.0.24022510
updated=0

仮想マシンの作成

ポートグループは PXE サーバーと同じにします。

ファームウェアは EFI、セキュアブートは無効にします。

仮想マシンの起動

仮想マシンを起動すると自動で iPXE Boot Menu が表示されるので、インストールしたい
ESXi のバージョンを選択し、Enter を押下。

バージョン選択後、boot.cfg や各モジュールが読み込まれ ESXi が起動し始めれば OK です。

今回は iPXE を使用して Nested ESXi をネットワーク (UEFI PXE) ブートしてみました。

上記と合わせて kickstart を実行させることで、更に ESXi のインストールを自動化する
ことができます。

kickstart については以下でブログにしたので、参考になれば幸いです。

iPXE を使用した PXE ブートについては、以下公式ドキュメントが公開されています。

iPXE および HTTP を使用した ESXi インストーラの起動

タイトルとURLをコピーしました