はじめに: ファームウェアアップデートが招いた4時間の悪夢
Cloudflareのコアサーバーは、世界中に分散するエッジ(Edge)とは異なり、中央データセンターでコントロールプレーン(Control Plane)、課金(Billing)、分析(Analytics)といった中核的な役割を担っています。これらはほとんどがベアメタル(Bare Metal)サーバーであり、起動プロセスはUEFI(Unified Extensible Firmware Interface)がハードウェアを初期化し、OSに制御を移す標準的な方法に従います。
問題は、日常的なファームウェアアップデートの後に発生しました。アップデートを完了した一部のコアサーバーで、ブート時間が従来の「数分」から「4時間」にまで延びてしまったのです。当然、予定していた1日で終わるはずのアップデート作業は数日間に引き伸ばされ、エンジニアは自動化されるべきアップグレードプロセスを延々と監視しなければなりませんでした。単純なファームウェアの回帰(Regression)バグを疑いましたが、実際の原因はもっと根本的なものでした。
この記事では、ブート時間を遅延させた「UEFIネットワークブートインターフェースの順次探索」問題を追跡し、それを解決するために適用した戦略を段階的に共有します。特に、単にiPXEの設定を数行変更したレベルではなく、ベンダーとの協業から内部ツールの開発までを含む総合的なアプローチであった点を強調したいと思います。
参考資料: この記事の内容は、Cloudflare公式ブログのケーススタディに基づいて作成しました。
本論1: 問題の核心、ブートインターフェースの「順次探索」
PXEとUEFI HTTPSブート、なぜ複数必要か
サーバーがネットワーク経由でOSを起動する方法は主に2つあります。1つ目は従来のPXE(Preboot Execution Environment)方式、2つ目はセキュリティが強化されたUEFI HTTPSブート方式です。CloudflareはオープンソースのネットワークブートファームウェアであるiPXEを使用してこの2つの方式をサポートし、ハードウェア構成に応じて適切なインターフェースを選択します。
問題はこの「選択」プロセスにありました。起動時にサーバーが利用可能なすべてのネットワークブートインターフェースを1つずつ試行し、各試行が失敗するまで約5分間待機した後、次のインターフェースに移行するという方式だったのです。
# ブート試行順序 (問題発生時)
[1] IPv4 HTTPSブート試行 → 5分待機後失敗
[2] IPv4 iPXEブート試行 → 5分待機後失敗
[3] IPv6 HTTPSブート試行 → 5分待機後失敗
[4] IPv6 iPXEブート試行 → 5分待機後失敗
[5] 正しいインターフェースに到達 (例: 特定NICのHTTPSブート)
# 総所要時間: 約20分 (単純ブート時)
単純なブート1回に20分かかるのは致命的です。さらに大きな問題は、ファームウェアアップグレードの自動化です。ブート順序を改善する前は、ファームウェアアップグレードに複数回の再起動が必要であり、そのたびに上記のような20分の時間がかかっていました。その結果、総アップグレード時間は約4時間にも達していたのです。
本論2: 解決策、「宣言的ブート順序」と自動化ツール
1. ブート自動化ワークフローの再構成
Cloudflareのブート自動化は、ファームウェア初期化 → 事前ブート(PXE) → カーネル起動の3段階に分かれています。問題が発生したのは、事前ブート段階でネットワークインターフェースを探索する部分でした。これを解決するために、ハードウェアとユースケースに合わせた正確なブートインターフェース順序を事前に宣言するようにワークフローを変更しました。
これには2つの制約を克服する必要がありました。
- レガシーサポート問題: 古いUEFIバージョンはブート順序設定をサポートしていません。
- 設定揮発性問題: UEFIファームウェアアップグレード時に設定値がリセットされる可能性があります。
これを解決するために**状態検証ステップ(State Validation)**を導入しました。ファームウェア自動化は設定変更後にこれを検証し、設定がリセットされた場合は再適用して再起動をトリガーします。最初のブートは少し遅くなる可能性がありますが、以降のすべてのブートは20分から1分未満に短縮されます。
2. ベンダーロック解除: 隠された設定の発見
問題をさらに深く掘り下げると、ベンダーが提供するUEFI設定のうち**'Force Priority Httpv4 Httpv6 Pxev4 Pxev6'という不変(Immutable)な値がブート順序の変更を妨げていました。この設定はEFI_IFR_REF3データ構造で保存されますが、この構造は遅延ローディング(Lazy Loading)**方式のため、プログラム的にアクセスするまでBIOS設定画面に表示されませんでした。
// UEFIネットワークブート設定の内部データ構造
// (この構造はGUIコールバックを介してのみ初期化される)
typedef struct _EFI_IFR_REF3 {
EFI_IFR_OP_HEADER Header;
EFI_IFR_QUESTION_HEADER Question;
EFI_QUESTION_ID QuestionId;
EFI_GUID FormSetId;
} EFI_IFR_REF3;
Cloudflareはベンダーと協力して**'Boot Order Module'**内の特定トークンを有効化することで、GUIなしでネットワークブートインターフェースを自動検出し、順序を変更できるようにしました。
3. NICベンダー別の文字列差異の克服
ブート順序をiPXEで設定する際に別の問題が発生しました。ネットワークインターフェースカード(NIC)ベンダーごとに、ブートインターフェースを識別する文字列が異なっていたためです。
# NICベンダー別のブートインターフェース文字列例
UEFI: HTTPS IPv4 Ethernet Network Adapter XXX-XXX-Y for OCP 3.0 P1
UEFI: HTTPS IPv4 Network Adapter - 50:00:E6:8F:4F:32 P1
この問題を解決するために、Cloudflareは内部ツールであるCfHIIConfig_Appに正規表現を使用した設定機能を追加しました。
# 正規表現を用いた部分文字列マッチング
.*HTTP.*IPv4.*P1
これにより、完全な文字列を知らなくても、プロトコル、転送方式、ポート番号、物理スロットインデックスのみで正しいブートインターフェースを選択できるようになりました。現在はベンダーと協力して、MACアドレスのような製品詳細情報を削除し、標準化された文字列のみを使用するよう努めています。
4. iPXE設定検証問題: HEX比較
iPXEはUEFI変数をHEX値として読み取るため、設定が正しく適用されたかどうかを確認することが困難でした。この問題を解決するために、uefi-same-hexというブーリアンフラグを実装しました。
# iPXEスクリプト: 設定変更および検証の自動化
# 設定変更後、変更の有無を確認して再起動の要否を決定
# 設定変更コマンド実行
imgexecset ${uefi-setting}=${uefi-value}
# 変更された変数と期待値を比較して変更を確認
# 変更されていればローカル変数に再起動シグナルを設定
iseq ${uefi-same-hex} ${${var-upd-path}} || set has-changed ${uefi-diff-hex}
このフラグにより、毎回showコマンドで変数を出力して比較する代わりに、単一のsetコマンドで設定と検証を同時に実行できるようになり、ブート時間をさらに短縮しました。
本論3: 結果と注意点
改善効果: 4時間 → 3分
| 指標 | 変更前 | 変更後 |
|---|---|---|
| ファームウェアアップグレード自動化 | 約4時間 | 3分 |
| 後続の単一ブート | 約20分 | 1分未満 |
この結果は、単にiPXEの設定を数行変更しただけでなく、UEFI内部構造への深い理解、ベンダーとの協業、自動化ツールの開発までを含む総合的な努力の成果です。
注意点と限界
- ベンダー依存性: この問題を解決する過程で、特定ハードウェアベンダーのUEFIファームウェア修正が必要でした。すべての環境で同じ方法で解決できるとは限りません。
- 初期設定時間: 状態検証ステップにより、最初のブートは以前より少し長くかかる可能性があります。
- 正規表現マッチングのリスク:
.*HTTP.*IPv4.*P1のようなワイルドカードマッチングは、設定が誤ったインターフェースとマッチングする可能性があります。継続的な標準化努力が必要です。
まとめと次のステップ
Cloudflareの事例は、ベアメタルサーバーを運用する際に「ブート時間」が単なる待ち時間ではなく、運用効率に直結する重要な最適化対象であることを示しています。特に、ファームウェアアップデートのように複数回の再起動が必要な作業では、ブート時間が全体の作業時間を左右する可能性があります。
この記事で扱った核心は「むやみに待つのではなく、ブートインターフェースを宣言的に制御しよう」ということです。この概念は、Cloudflareのインフラだけでなく、ベアメタルサーバーを扱うあらゆる環境で有用に適用できます。
次のステップとして推奨する学習方針:
- iPXEスクリプティングの応用: 公式ドキュメントを通じて、さまざまなブートシナリオとスクリプト作成方法を学んでみてください。
- UEFI内部構造の学習:
EFI_IFR_REF3のようなデータ構造を理解すると、ベンダーロック問題をより簡単に解決できます。 - ブート自動化ツールの構築: この記事で紹介された
CfHIIConfig_Appのように、独自の設定ツールを作成してみるのも良い練習になります。
合わせて読みたい記事:
