このコンテンツは自動機械翻訳サービスによる翻訳版であり、皆さまの便宜のために提供しています。原本の英語版と異なる誤り、省略、解釈の微妙な違いが含まれる場合があります。ご不明な点がある場合は、英語版原本をご確認ください。
Cloudflareの中核は、コントロールプレーン、請求、分析を実行する中央集中型データセンターです。ユーザートラフィックを処理するグローバルに分散したエッジとは異なります。コアサーバーはベアメタルであるため、リブート中に問題が発生すると、その結果は急速に連鎖する可能性があります。
ブートシーケンスは、ハードウェアを初期化し、オペレーティングシステムに制御を引き渡す最新のファームウェア規格であるUEFIによって調整されています。その引き継ぎにおける小さな特異な問題が、重大な結果をもたらす可能性があります。
定期的なファームウェアアップデートの後、一部のコアサーバーは、以前のように数分で済むはずが、オンライン復旧に4時間かかっていました。本来1日だけのフリート全体展開だったものが、複数日にわたるログ記録になっていました。新しいノードは、最初の起動で完全なタイムアウトに直面しました。保守期間が嵩みました。エンジニアリングチームは、本来実行されるべきアップグレードを支援する必要がありました。
この挙動が明らかになったのは、長時間にわたって電源が切れていたノードをオンラインにしようとしたときでした。これらのノードのファームウェアは古く、解決するためには複数のアップデートが必要でした。さらに、一部の拠点のサーバーで使用されている最近のブートプロトコルの更新と合わせて、影響を受けたノードのブート時間が許容できないレベルになりました。
これは、ファームウェアの異常により発生した原因の追跡と、利用可能なすべてのネットワーク起動インターフェースを介した過度に広範な検索、起動とアップグレードの合計時間を数時間から数分に短縮した方法についてです。これまでに、UEFIの内部機能、ベンダー特有の不具合、最終的に問題を解決した自動化戦略について学んだことについてもご紹介します。
ネットワークブートインターフェイスにより、サーバーはローカルストレージからではなく、ネットワーク上でオペレーティングシステムを起動できます。これは、特にワークロードがグローバルに分散したフリートにおいて、マシンの起動方法を一元化された、自動化されたスケーラブルな制御を実現するために極めて重要です。当社のサーバーはさまざまな環境に配置され、目的も異なるため、特定のネットワークブートインターフェースに対する要件も異なります。2つの主要なインターフェイスは、Preboot実行環境(PXE)とUnified Extensible Firmware Interface(UEFI)HTTPSブートです。
リブートプロセスの一環として、サーバーは通常、さまざまな自動化上の理由でPXEを通過します。Cloudflareでは、HTTPやHTTPSなどの最新のプロトコルに対応するオープンソースのネットワークブートファームウェアであるオープンソースのiPXEを使用しています。これにより、コンピューターはWebサーバー、クラウド、または企業ストレージネットワークから直接オペレーティングシステムを起動することができ、速度と信頼性が大幅に向上します。
企業にとって、iPXEはブートプロセスをプログラム可能なワークフローに変えます。ITチームが特定のハードウェア構成に基づいたサーバーのプロビジョニングや、セキュアなディスクレスワークステーションの管理など、複雑なデプロイメントを自動化するための高度なスクリプト機能を提供します。
当社のハードウェアの一部は、HTTPSベースのUEFIネットワークブートをサポートしており、コンピュータのマザーボードのファームウェアがオペレーティングシステムファイルを安全にネイティブにダウンロードすることができます。
私たちの物語は、その命運のファームウェアのアップデートから始まります。更新後、最初の報告は内部チャンネルを通じて来ました。サーバーがオンラインに戻っていないということでした。監視ダッシュボードでは、マシンが予想よりはるかに長い間、OS以前の状態に留まっていることが示されました。私たちが最初に疑ったのは、ファームウェアのリグレッションでした。おそらく、アップデート自体が、起動プロセスをハングアップするバグを導入したのではないかと思いました。
それを防ぐため、影響を受けたマシンのシリアルコンソールをプルアップして、リアルタイムで起動サイクルを観察しました。ファームウェアの電源オンセルフテスト(POST)は正常に完了し、ハードウェアの初期化も正常でした。しかし、その後、サーバーはすぐにネットワークブートステージに到達してOSイメージをプルダウンするのではなく、待機し続けたのです。そして待つこと。
コンソールの出力が原因で、システムがIPv4 HTTPSネットワークの起動を試行し、数分後にタイムアウトし、次にIPv4 iPXEを試行し、再びタイムアウトし、両方を繰り返し、最終的に実際に成功するIPv6 HTTPSブートインターフェースに到達しました。
ネットワーク起動の失敗はすべて、タイムアウト応答を待つのにおよそ5分。正しいインターフェイスに到達する前に4回の試行が積み重なり、1回の起動サイクルが20分ほど無駄になったのです。定期的な再起動としては、面倒な作業です。ファームウェアのアップグレードの自動化には、コンポーネントごとに1回、複数回の再起動が必要で、20分間のペナルティが積み重なって、サーバーあたり4時間近くのアイドル状態待機がもたらされることになりました。
検索しないゲーム:私のブートインターフェイスを宣言します
ブートシーケンスを追跡して、タイムアウトパターンを分離した後に、その根本的な原因が明らかになりました。サーバーが利用可能なネットワークブートインタフェースを1つずつ検索し、それぞれが障害発生するのを待ってから進めていたのです。この問題の解決策は、推測する作業を完全に排除することでした。システムが応答しないインターフェースに時間を浪費することのないように、正しいブートインターフェースを事前に宣言するのです。
しかし、それを実践することは、決して簡単なことではありませんでした。次に説明するように、いくつかの障害に直面しました。ブートオートメーションワークフローの順序、変更をブロックできた設定、異なるネットワークインターフェースカードベンダーとの文字列フォーマットの違いです。
ブート自動化の流れは、ファームウェアの初期化、プリブート、カーネル起動の3つの段階に大きく分けられます。電源オン後、UEFIファームウェアがハードウェアと周辺機器の初期化を行い、その後、PXEプリブート環境が続きます。プリブートはネットワークカードをセットアップし、ブートローダーと呼ばれる小さなプログラムを実行してカーネルを起動します。さまざまなネットワークインターフェイスが適切なものであるかどうかを探るのは、このPXEの段階です。初回の起動では、ファームウェアのアップグレードがブートオートメーションワークフローに含まれます。
また、ファームウェアのアップグレードはそれぞれ再起動(およびそれに付随するネットワーク起動の試行シーケンス)を必要とするため、合計起動時間が4時間近くかかるという状況に達しました。
各ハードウェアまたはユースケースのプリブートPXEの段階で、早い段階でネットワークブートインターフェイスの順序を宣言するために、自動化シーケンスを再構築することにより、起動プロセスが不要になったため、合計時間を約1時間短縮することができました。確認するために、各ファームウェアのアップグレードに20分を費やす必要があります。
ネットワークブートインターフェイス順序を宣言しようとすると、2つの特定の制約が発生しました:
Legacy サポート:古いUEFIバージョンでは、ブート順序はサポートされていません。
存続:UEFIファームウェアのアップグレード後に設定設定がリセットされることが多い
こうしたエッジケースに対処するために、状態検証ステップを実装しました。ファームウェアの自動化により、変更後の設定が検証されます。設定が変更されたことを検出すると、設定を再適用し、再起動を実行します。
最初の起動はわずかに時間がかかるかもしれませんが、この変更により、それ以降のすべての起動に必要な時間が約20分から1分未満に大幅に短縮されます。
ネットワークブート設定の内部データ構造は、遅延ロードされていたFFI_IFR_REF3データ構造で、遅延ロードされていました。つまり、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;
これは、BIOSの起動時間を短縮するための業界標準の慣行ですが、これにより「ネットワークブートインターフェース」がプログラムによるスキャンから見えなくなってしまいました。構造がまだ「ロード」されていないため、当社の自動化は優先順位を検出できませんでした。
当社はベンダーと協力して、固定された「ブート注文モジュール」内で特定のトークンを有効化しました。これにより、手動のGUIでの操作を必要とせず、起動シーケンス中にネットワークブートインターフェースを強制的に検出します。
機器メーカーのUEFIには、Force Priority Httpv4 Httpv6 Pxev4 Pxev6という不変の設定があり、ブート順序を変更できなかったのです。
これには、ベンダーからの新しいBIOSバージョンと、起動順序を設定する際のデバッグセッションが必要でした。
ネットワークインターフェイスカード(NIC)のベンダーによって文字列が異なるため、iPXEを介してブート順序を設定するときに不一致が発生します。
例:
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
この問題を回避するために、CfHIIIConfig_Appツールに追加機能を実装し、完全な文字列を持たずにconfigを設定できるようにする必要がありました。
.*HTTP.*IPv4.*P1
設定は、受け入れられた設定文字列と照合され、正しい起動順序を選択します。現在、UEFIベンダーと協力して、ネットワークインターフェース文字列を標準化し、関連する情報(例:プロトコル、転送タイプ、ポート番号、物理スロットインデックスなど)を入力し、MACアドレスなどの製品の詳細をドロップします。必要な場合は、ネットワークインターフェースカードに埋め込まれたバイタル製品詳細情報から読み取ることができます。そうすることで、設定のドリフトとワイルドカードの使用の両方を排除します。
iPXEはこの変数をHEXとして読み込むため、出力される文字列を16進数として読んでいたのです。ネットワーク起動設定が変更されたかどうかを確認し、起動時間を短縮する(つまり、設定前に変数を出力する必要がない)ために、設定が変更されたことを示すuefi-same-hexというブールフラグを実装しました。
これにより、最初にshow を実行して比較し、設定が望ましい状態ではなかった場合にのみsetを実行する代わりに、単一のsetコマンドを実行できるようになりました。
# construct path to read the update variable
set buffer-var-guid 91468514-75bc-4bb5-8f33-91efff9e9b1f
set var-upd-path efivar/CfHIIVarUpd-${buffer-var-guid}
#Run the config change command
imgexec <signed CF UEFI configuration App> set ${uefi-setting}=${uefi-value}
#Compare the update variable with the expected value if it has changed.
#If it has changed, set the local variable to reboot the system
iseq ${uefi-same-hex} ${${var-upd-path}} || set has-changed ${uefi-diff-hex}
ネットワークの起動順序から当て推量で行う作業を排除することで、4時間かかっていた探求を3分間に短縮しました。その結果、変更が動的で、手動によるBIOS操作が不要なシステムになります。1つのBIOSファームウェアイメージがすべてのSKUを提供し、設定アップデートは既存のリリースパイプラインを介して大量にデプロイされ、ワークフロー全体はiPXEから動作します。
指標 | 変更注文前 | 変更注文後 |
|---|
ファームウェアのアップグレードの自動化 | 4時間弱 | 3分です |
後続のシングルブート | 約20分 | 1分未満 |
これらは、UEFIの内部を深く掘り下げ、OEMベンダーと緊密に協力してプログラム可能なブート注文制御などの機能を引き出し、iPXEのようなオープンソースツールを活用してスケーラブルな自動化を構築しなければ、これを実現することはできませんでした。
日を増すごとに、CloudflareのOpenBMCチームはコア製品全体でブートプロセスについて学習し、実験を続け、最適化していきます。ベアメタルインフラストラクチャを管理し、サーバーの起動時間の遅さに頭を悩ませている方に、この記事の内容が、自社のネットワーク起動シーケンスにおける不要な遅延を特定し排除するための実用的なフレームワークをお届けできたら幸いです。iPXEとネットワークブート自動化の詳細について興味をお持ちの方は、こちらをご覧ください。