OpenWrt + dnsmasq + raspberry pi 4B でstaging/productionの環境を分離するPXEブートを行った
Posted:
OpenWrt + dnsmasq + Raspberry Pi 4B PXE ブート調査
OpenWrt 上の dnsmasq を用いて Raspberry Pi 4B を タグベースで PXE 起動させる。
このメモの 192.0.2.100 は説明用の documentation address である。homecluster-infra から OpenWrt 実機へ反映する場合は、外部 inventory の openwrt_lan_ipaddr、openwrt_dhcp_ntp_servers、openwrt_gentoo_server_host を実値として明示し、documentation range が dnsmasq / TFTP / NFS endpoint に残っていれば反映前に止める。
最終的に目指した状態:
dhcp-boot=tag:rpi4-02,start4.elf,192.0.2.100,192.0.2.100
もしくはシンプルに:
dhcp-boot=start4.elf,192.0.2.100
と同等の挙動をタグ条件付きで再現する。
最初の症状
config host で set:rpi4-02 が出力されている dhcp-boot=tag:rpi4-02,… を設定 しかし PXE 起動しない タグ無しの dhcp-boot=start4.elf,192.0.2.100 なら起動する ここから調査開始。
次の内容で検証した
openwrtでは/etc/config/dhcpで設定ができる 次のコマンドでトライアンドエラーを繰り返した
vi /etc/config/dhcp && /etc/init.d/dnsmasq restart && cat /var/etc/dnsmasq.conf.*
Raspberry Pi の PXE 挙動の理解
dnsmasq ログより:
vendor class: PXEClient:Arch:00000:UNDI:002001
これは DHCP Option 60(Vendor Class)。
意味:
| フィールド | 意味 |
|---|---|
| PXEClient | PXE クライアント |
| Arch:00000 | BIOS 互換 |
| UNDI:002001 | PXE ドライババージョン |
重要点: Raspberry Pi の PXE は BOOTP フェーズと通常 DHCP フェーズがある このとき:
- host の set: タグが BOOTP フェーズで適用されない可能性がある
- そのため tag:rpi4-02 が効かないケースがある
dnsmasq の -M / dhcp-match の理解
-M, --dhcp-vendorclass=set:<tag>,<vendorclass>
OpenWrt UCI では:
list dhcp_match 'set:pxe,60,PXEClient'
これは:
dhcp-match=set:pxe,60,PXEClient
意味:
VendorClass に PXEClient を含むクライアントに pxe タグを付与 しかし今回は host タグでの制御を目指した。
config boot の正しい理解
最重要ポイント。 OpenWrt では:
config boot
option filename 'start4.elf'
option networkid 'rpi4-02'
option serveraddress '192.0.2.100'
option servername '192.0.2.100'
が
dhcp-boot=tag:rpi4-02,start4.elf,192.0.2.100,192.0.2.100
に変換される。
落とし穴 ① serveraddress / servername は両方必須
OpenWrt ドキュメント: https://openwrt.org/docs/guide-user/base-system/dhcp#booting_options
このセクションは dnsmasq の -M オプション構築について説明しているが、 config boot のパース仕様が明確に書かれていない。
実験で判明:
- serveraddress だけでは出力されない
- servername だけでも出力されない
- 両方必要
⚠️ エラーは出ない(静かに無視されdnsmasq向けの設定ファイルには書き出されない)
これは OpenWrt の UCI → dnsmasq 変換の仕様。
落とし穴 ② servername にホスト名を使うと失敗する可能性
dnsmasq の構文は:
dhcp-boot=<filename>,<servername>,<serveraddress>
Raspberry Pi PXE クライアントは:
- servername を DNS 解決する保証がない
- 名前解決失敗時に TFTP 失敗する可能性がある
実験の結果 servername に IP を指定することで安定することがわかった。 つまり
option servername '192.0.2.100'
option serveraddress '192.0.2.100'
が最も確実。
最終的に動作した設定
config host
option name 'rpi4-02'
option mac 'DC:A6:32:B4:85:A8'
option ip '192.0.2.253'
option networkid 'rpi4-02'
config boot
option filename 'start4.elf'
option networkid 'rpi4-02'
option serveraddress '192.0.2.100'
option servername '192.0.2.100'
生成される dnsmasq 設定:
config host
option name 'rpi4-02'
option mac 'DC:A6:32:B4:85:A8'
option ip '192.0.2.253'
option networkid 'rpi4-02'
config boot
option filename 'start4.elf'
option networkid 'rpi4-02'
option serveraddress '192.0.2.100'
option servername '192.0.2.100'
生成すると
dhcp-host=...,set:rpi4-02,...
dhcp-boot=tag:rpi4-02,start4.elf,192.0.2.100,192.0.2.100
これでタグ付き起動成功。
なぜ dhcp-boot=start4.elf,192.0.2.100 は常に動いたか?
これは tag 条件が無いためBOOTP フェーズでも必ず適用された。
TFTP ログの解釈
error 0 Early terminate received
file ... not found
これは:
- Raspberry Pi が複数回リトライする
- オプションファイルを探しに来る
- 必須でないファイルも探す
正常範囲。
設計上の考察
今回得られた知見:
- OpenWrt の config boot は動作する
- しかし両方のフィールド必須
- servername は IP にするのが安全
- Raspberry Pi PXE は BOOTP と DHCP が分離
- タグ付与タイミングに注意
ベストプラクティス(今回の環境)
- PXE ブートファイルは共通化可能
- stage / overlay 制御は DHCP Option 224 で渡す
- Linux 側で処理する方がデバッグしやすい
追加の知見(運用で詰まった点)
dhcp-broadcast が tag 条件付きの場合の落とし穴
OpenWrt の dnsmasq 生成で以下のような行が出ている場合:
dhcp-broadcast=tag:needs-broadcast
このとき needs-broadcast タグが付いていない端末には ユニキャスト応答が返る。
Raspberry Pi 側がユニキャストの OFFER を受理しない場合、DHCPREQUEST が出ずに止まる。
回避策は needs-broadcast タグを付与すること。
config host の bootfile が dnsmasq.conf に反映されないケース
UCI で option bootfile 'rpi4-stg/start4.elf' を設定しても、
/var/etc/dnsmasq.conf.* の dhcp-host=... 行に bootfile が出力されないことがある。
この場合、dhcp-boot=tag:... を config boot で明示する方が確実。
IP 再利用が効かない件
検証中に IP を使い回すと反映されないことがあった。
/tmp/dhcp.leases と /tmp/hosts/dhcp.cfg* が原因の可能性があるので、以下でリセットできる。
rm -f /tmp/dhcp.leases /tmp/hosts/dhcp.cfg*
/etc/init.d/dnsmasq restart