エッジとベアメタルのシステムとサーバーを自動的にプロビジョニングして構成するためのベスト プラクティス

Last reviewed 2023-02-23 UTC

このドキュメントでは、次のような環境のエッジで実行されるデバイスに対して、信頼性が高く自動化されたプロビジョニング プロセスと構成プロセスを設計して実装する際のベスト プラクティスを紹介します。

エッジデバイスと IoT デバイスのプロビジョニング プロセスと構成プロセスを設計する場合や、これらのデバイスタイプをプロビジョニングするためのベスト プラクティスについて学習する場合は、このドキュメントをお読みください。

大量のデバイスを手動でプロビジョニングして構成すると、人的エラーが発生しやすく、フリートの拡大に合わせたスケーリングができません。たとえば、重要なプロビジョニングや構成タスクの実行を忘れた場合や、部分的または完全に文書化されていないプロセスに依存している場合などです。完全に自動化された信頼性の高いプロビジョニングと構成のプロセスが、これらの問題の解決に役立ちます。また、製造から廃棄まで、各デバイスのライフサイクルを管理するのに役立ちます。

用語

次の用語は、デバイスの自動プロビジョニングと構成のプロセスを実装および構築する方法を理解するうえで重要です。

  • エッジデバイス: 処理するデータの近くに環境エッジでデプロイするデバイス。
  • プロビジョニング プロセス: デバイスの構成を準備するために完了する必要がある一連のタスク。
  • 構成プロセス: デバイスが特定の環境で動作できるようにするために必要なタスクのセット。
  • 構成管理: 環境とデバイスの構成を管理するために継続的に実行する一連のタスク。
  • ベースイメージ: 自社が作成した、またはデバイスまたは OS のメーカーが作成した、最小限必要なオペレーティング システム(OS)またはファームウェア イメージ。
  • ゴールデン イメージ: デバイス用に作成するか、ベースイメージから準備する不変の OS イメージまたはファームウェア イメージ。ゴールデン イメージには、デバイスで割り当てられたタスクを実行するために必要なすべてのデータと構成情報が含まれます。さまざまなタスクに合わせて、さまざまなゴールデン イメージを準備できます。ゴールデン イメージタイプの類義語には、フレーバー、スピン、アーキタイプがあります。
  • シルバー イメージ: ゴールデン イメージとベースイメージに最小限の変更を適用してデバイス用に準備をする OS またはファームウェア イメージ。シルバー イメージを実行するデバイスは、デバイスがサポートする必要があるユースケースのニーズに応じて、初回起動時にプロビジョニングと構成を完了します。
  • シードデバイス: 外部依存関係なしで環境をブートストラップするデバイス。
  • ネットワーク ブート: デバイスに接続されたストレージ システムから、ソフトウェアと関連する構成情報をネットワークから取得できるようにするテクノロジー セット。

プロビジョニングと構成のプロセスのベスト プラクティス

目標を設定して一般的な誤りを回避するには、次のプロビジョニングと構成のベスト プラクティスを適用します。各ベスト プラクティスについては、それぞれのセクションで説明します。

プロビジョニングと構成のプロセスを自動化する

初回起動時や、必要なときには常に、デバイス内にインストールされたソフトウェア イメージのみを使用してデバイスをプロビジョニングして構成できる必要があります。

プロビジョニングと構成のプロセス中に必要なロジックを実装しないようにするには、プロセスのオーケストレーションと実装に必要なプリミティブを提供するツールを使用します。たとえば、cloud-init とその NoCloud データソースを、スクリプトや構成管理ツール(AnsiblePuppetChef など)とともに使用して、ローカルホストに対して実行できます。

信頼性の高いプロビジョニングと構成のプロセスを設計するには、これらのプロセス中に実行されたすべてのステップとタスクが有効で、可能な限り自動化された手法にする必要があります。たとえば、InSpec などの自動コンプライアンス テスト フレームワークを使用して、プロビジョニングと構成のプロセスが期待どおりに動作していることを確認できます。

このベスト プラクティスは、デバイスのプロビジョニングと構成を完了する必要がある場合に、単一障害点を回避し、手動での介入の必要性をなくす上で役立ちます。

用途に特化したデバイスを避ける

エッジデバイスを設計する場合は、目的と特殊性に関してばらつきを最小限に抑えます。この推奨事項は、すべてのエッジデバイスが互いに等しい必要がある、または同じ目的を共有することを意味するわけではありませんが、可能な限り同種のものにする必要があります。たとえば、サポートする必要があるワークロード タイプによってデバイス アーキタイプを定義できます。その後、これらのアーキタイプのプロパティに従って、デバイスをデプロイして管理できます。

このベスト プラクティスに従うには、特定のアーキタイプのデバイスからデバイスをランダムに選択できることを確認してから、次の操作を行います。

  • 同じアーキタイプの他のデバイスと同様にデバイスを扱います。このようにすることで、運用効率があることを示せます。
  • 追加のカスタマイズを行わずに、デバイスを同じアーキタイプのデバイスに置き換えます。このようにすることで、これらのアーキタイプが正しく実装されていることを示せます。

このベスト プラクティスにより、デバイスのフリートの差異が軽減され、環境やプロビジョニング、構成プロセスの断片化が減ります。

シードデバイスを使用して環境をブートストラップする

デバイスのプロビジョニングと構成の際に、循環依存関係の問題に直面することがあります。デバイスには、プロビジョニングと構成のためのインフラストラクチャのサポートが必要ですが、インフラストラクチャのプロビジョニングと構成が必要なため、インフラストラクチャは整っていません。

これは、シードデバイスを使用することで解決できます。シードデバイスには一時的な特殊用途があります。特殊用途が設計されたタスクを完了すると、デバイスはその動作とステータスを、関連するアーキタイプに適合させます。

たとえば、cloud-init を使用してデバイスを自動的に初期化する場合は、次の方法で cloud-init NoCloud データソースを構成する必要があります。

  1. NoCloud データソースのデータをファイル システムを通じてシードデバイスに提供します。
  2. シードデバイスが特別な目的で専用のプロビジョニングと構成を完了するのを待ちます。これには、ネットワーク経由で他のデバイスに NoCloud データソース データを提供することも含まれます。

    シードデバイスのプロビジョニングと構成のプロセスが、シードデバイスの一時的な特殊用途を削除する条件が満たされるまで待機します。これらの条件の例は次のとおりです。

    • 環境内にネットワーク経由で NoCloud データソース データを提供するデバイスが他にあるか。
    • クラスタ内に十分なノードがあるか。
    • 最初のバックアップは完了したか。
    • 障害復旧サイトの準備はできているか。
  3. シードデバイスからネットワーク経由で NoCloud データソース データをダウンロードする他のデバイスをプロビジョニングして構成します。一部のデバイスでは、ネットワーク経由で NoCloud データソース データを提供できる必要があります。

  4. シードデバイスのプロビジョニングと構成のプロセスが再開されます。これは、シードデバイスの特殊用途をドロップする条件が満たされているためです。フリートには、ネットワーク経由で NoCloud データソース データを提供するデバイスが他にもあるため、このような再開が必要になります。

  5. シードデバイスのプロビジョニングと構成のプロセスが特殊用途をドロップするため、シードデバイスを同じアーキタイプの他のデバイスと区別することはできません。

このベスト プラクティスを使用することで、インフラストラクチャをサポートせずに、また、特殊用途のデバイスを避けるベスト プラクティスに反することなく、環境をブートストラップできます。

デバイスのステートフル性を最小限に抑える

エッジデバイスを設計するときは、少なくともステートフル情報を保存する必要があります。エッジ デバイスには、ハードウェア リソースの制限や、厳しい環境にデプロイされる場合があります。機能するために必要なステートフル情報を最小限に抑えると、プロビジョニング、構成、バックアップ、復元のプロセスが簡素化されます。これは、このようなデバイスを均一に扱うことができるためです。たとえば、ステートレス エッジデバイスが誤動作し、回復できない場合は、同じアーキタイプの別のデバイスと交換して、中断やデータ損失を最小限に抑えます。

このベスト プラクティスは、データ損失や、プロセスが複雑すぎることによる予期せぬ問題を回避するのに役立ちます。ほとんどの複雑性は、異種混合のデバイス フリートをサポートする必要性に起因します。

OS とファームウェア イメージを自動的にビルドする

デバイスの初回起動時にコストのかかるプロビジョニングと構成のタスクを回避し、デバイス リソースを確保するために、OS とファームウェア イメージを利用可能にする前にカスタマイズします。たとえば、依存関係は、各デバイスの初回起動時にインストールするのではなく、イメージに直接インストールできます。

デバイスの OS とファームウェア イメージを準備する場合、ベースイメージから始めます。ベースイメージをカスタマイズすると、以下のことが可能になります。

  • ゴールデン イメージを生成します。ゴールデン イメージにはイメージ内のすべての依存関係が含まれているため、最初に起動時にこれらの依存関係をインストールする必要はありません。ゴールデン イメージの生成は複雑なタスクですが、プロビジョニングや構成時にデバイスとリソースを節約できます。
  • シルバー イメージを生成します。ゴールデン イメージとは異なり、シルバー イメージを実行するデバイスでは、初回起動時にすべてのプロビジョニングと構成のプロセスが完了します。シルバー イメージの生成はゴールデン イメージの生成より複雑ではありませんが、シルバー イメージを実行するデバイスがプロビジョニングと構成を行う際に、より多くの時間とリソースを消費します。

継続的インテグレーションと継続的デプロイ(CI/CD)プロセスの一環として、OS とファームウェア イメージをカスタマイズできます。カスタマイズしたイメージは、検証後にデバイスで自動的に使用可能になります。Cloud BuildGitHub ActionsGitLab CI または Jenkins などのツールを使用して実装する CI/CD プロセス/CDでは、次の一連のタスクを実行できます。

  1. カスタマイズしたイメージに対して自動検証を実行します。
  2. カスタマイズしたイメージを、デバイスが取得できるリポジトリに公開します。

CI/CD 環境と、イメージのビルドに必要な OS またはファームウェアで異なるハードウェア アーキテクチャが使用されている場合は、QEMU などのツールを使用してこれらのアーキテクチャをエミュレートできます。たとえば、x86_64 アーキテクチャARM ファミリーのハードウェア アーキテクチャをエミュレートできます。

OS またはファームウェア イメージをカスタマイズするには、それらを変更してエッジ環境でインストールする前に、テスト環境でその変更を検証できる必要があります。chroot などのツールを使用すると、コマンドを実行する前にルート ディレクトリを仮想的に変更できますが、物理的に変更することはできません。

たとえば、コマンド chroot /mnt/test-image apt-get install PACKAGENAME を実行すると、/mnt/test-image/ ではなく、OS またはファームウェア イメージのルート ディレクトリであるかのようにシステムが動作し、ディレクトリに PACKAGENAME がインストールされます。

このベスト プラクティスは、デバイスでイメージを使用できるようにする前に、OS とファームウェア イメージをカスタマイズするのに役立ちます。

デバイスで実行されているワークロードを確実にオーケストレートする

デバイスが異種のワークロードをサポートしている場合、次のツールを使用して、それらのワークロードをオーケストレートし、ライフサイクルを管理できます。

  • ワークロード オーケストレーション システム: Kubernetes などのワークロード オーケストレーション システムの使用は、複雑なオーケストレーションまたはライフサイクル管理要件を持つワークロードに適しています。これらのシステムは、複数のコンポーネントにまたがるワークロードにも適しています。どちらの場合も、オーケストレーションとワークロードのライフサイクル管理ロジックを自身で実装する必要はありません。デバイスにリソースの制約がある場合は、MicroK8sK3sエッジ プロファイルがインストールされた Anthos clusters on bare metal など、正規のリソースよりも少ないリソースを必要とする軽量の Kubernetes ディストリビューションをインストールできます。
  • init システム: systemd などの init システムの使用は、次の特性を持つワークロードに適しています。

    • シンプルなオーケストレーション要件
    • ワークロード オーケストレーション システムをサポートするためのリソースの不足
    • コンテナに配置できないワークロード

ワークロードのオーケストレーションを行うシステムを準備したら、システムを使用してプロビジョニング プロセスと構成プロセスの一部を実行することもできます。たとえば、プロビジョニングと構成のプロセスの一部として構成管理ツールを実行する必要がある場合は、他のワークロードと同様にワークロード オーケストレーション システムを使用できます。この方法の例については、DaemonSet による GKE ノードの自動ブートストラップをご覧ください。この記事では、Kubernetes を使用してクラスタノードで特権および非特権プロビジョニング タスクと構成タスクを実行する方法について説明します。

このベスト プラクティスは、デバイスで実行されているワークロードをオーケストレートできるようにするのに役立ちます。

デバイスの確認、認証、接続を行う

デバイスが他のデバイスやバックエンドなどの外部システムに接続する必要があるかどうかを確認するには、以下のサブセクションの推奨事項を検討してください。

適用する接続方法

  • 情報を交換する前に、情報をリクエストしている他の関係者を認証します。
  • 送信された情報が予期しないチャネル間を移動していないことを確認します。
  • 信頼できる実行環境に依存して、暗号化キー、認証キー、パスワードなどのシークレットを処理します。
  • 使用する前に、OS またはファームウェア イメージの整合性と信頼性を検証してください。
  • ユーザー提供の構成の有効性、整合性、信頼性を確認します。
  • 不要なソフトウェアをインストールせず、デバイスにすでに存在するソフトウェアを削除することで、攻撃対象領域を制限します。
  • 特権オペレーションとアカウントの使用を制限します。
  • デバイスのケースが物理的操作と改ざんを防止する必要がある場合、ケースの整合性を確認します。

避けるべき接続方法

  • 暗号化されていないチャネルで機密情報を送信しないでください。
  • 次のような特権アクセスを開いたままにしないでください。
    • 仮想または物理シリアルポートとシリアル コンソール。デバイスが物理的に改ざんされた場合にのみ、昇格された権限を使用してポートにアクセスできます。
    • ネットワークからのリクエストに応答し、特権オペレーションを実行できるエンドポイント。
  • OS やファームウェア イメージ、構成、ソースコード内にハードコードされた認証情報に依存しないでください。
  • 攻撃者が昇格した権限を取得するための情報を収集するのに役立つ可能性のある情報を開示しないでください。たとえば、デバイス上のデータを暗号化し、本番環境のデバイスで不要なトレース システムとロギング システムをオフにします。
  • ユーザーとワークロードが任意のコードを実行できないようにします。

次の方法をおすすめします。

  • デバイスの安全な通信チャネルを設計します。
  • デバイスのセキュリティ境界を回避できるバックドアを避けます。
  • デバイスが、攻撃者が悪用できる可能性のある不正なインターフェースを公開していないことを確認します。

デバイスをモニタリングする

手動で介入せずにデバイスの状態に関する情報を収集することは、環境の信頼性にとって不可欠です。必要なすべてのデータが自動的にデバイスから報告されるようにします。データを収集してモニタリングする主な理由は 2 つあります。データを収集してモニタリングする 1 つ目の理由は、デバイスが意図したとおりに動作していることを確認することです。データを収集してモニタリングする 2 番目の理由は、問題をプロアクティブに検出して予防的なメンテナンスを行うことです。たとえば、Cloud Monitoring を使用してモニタリング指標やイベントを収集できます。

問題の調査とトラブルシューティングに役立つように、通常のオペレーション中にデバイスをモニタリングするプロセスに加えて、詳細なモニタリング、トレース、デバッグ情報などの高解像度の診断データを収集するためのプロセスを設計、実装することをおすすめします。高解像度の診断データを収集してネットワーク経由で転送すると、コンピューティング、データ ストレージ、電力などのデバイス リソースの面で費用がかかる可能性があります。このため、高解像度の診断データを収集するプロセスは、必要な場合にのみ、詳しい調査が必要なデバイスに対してのみ有効にすることをおすすめします。たとえば、デバイスの 1 つが意図したとおりに動作せず、デバイスが報告する定期的なモニタリング データで問題を十分に診断できない場合は、そのデバイスに対して高解像度データの収集を有効にすると、問題の原因を調べるのに役立つ詳細情報が報告されます。

このベスト プラクティスにより、デバイスが不明な状態にならないようにし、デバイスのパフォーマンスを判断するために十分なデータを確保できます。

無人の起動とアップグレードをサポートする

プロビジョニング プロセスと構成プロセスを設計する際は、デバイスで無人の起動が可能であることと、必要なインフラストラクチャがあることを確認してください。最初の起動と無線アップグレードの提供の両方をサポートする無人ブート メカニズムを実装すると、インフラストラクチャの保守性が向上します。無人の起動を使用すると、起動またはアップグレード時に各デバイスを手動で操作する必要がなくなります。オペレーターが操作を誤ったり、デバイスのフリートすべてに必要なアクションを実行する時間が不足している場合があるため、手動で多数のデバイスを操作するとエラーが発生しやすくなります。

また、正しい OS やファームウェア イメージを起動するために各デバイスを事前に準備する必要はありません。たとえば、OS やファームウェア イメージの新しいバージョンをリリースし、デバイスがネットワークから起動手順を選択する際に選択できるオプションの 1 つとしてそのバージョンを利用できるようにします。

このベスト プラクティスは、デバイスで自動化および無人化された起動とアップグレードを行えるようにするのに役立ちます。

復元性に優れたプロセスを設計して実装する

完全に自動化されたプロビジョニングと構成のプロセスであっても、プロセスが正しく完了せず、デバイスが一貫性のない状態のままになるようなエラーが発生する可能性があります。再試行メカニズムとフォールバック メカニズムを実装して、デバイスがこのような障害から復旧できるようにしてください。たとえば、デバイスがプロビジョニング プロセスと構成プロセスの一部であるタスクを完了できない場合、その障害から自動的に回復を試みます。デバイスが障害から復旧するか、動作状態に戻ると、プロセスが失敗した時点から実行中のプロセスを再開できます。

このベスト プラクティスは、復元性のあるプロビジョニング プロセスと構成プロセスの設計と実装に役立ちます。

デバイスのライフサイクル全体をサポートする

プロビジョニングと構成のプロセスを設計する際は、それらのプロセスがデバイスのライフサイクル全体を管理できるようにする必要があります。デバイスのライフサイクルを効果的に管理するには、デバイスが比較的長期間実行される予定であっても、終了と廃棄の計画を立てる必要があります。

デバイスのライフサイクルを管理しないと、次のような問題が発生する可能性があります。

  • 持続的な高コスト: プロビジョニングと構成のプロセスを行った後に、ライフサイクル管理のサポートを導入することで、コストが増加する可能性があります。このサポートを設計の早い段階で計画することで、コストを削減できます。たとえば、プロビジョニング プロセスと構成プロセスがデバイスのライフサイクル全体をサポートしていない場合、ライフサイクルの各フェーズを適切に処理するには、各デバイスに手動で介入する必要があります。手動操作はコストがかかり、スケーリングできないことがよくあります。
  • 柔軟性の向上: ライフサイクル管理がサポートされないと、最終的にデバイスを更新または管理できなくなる可能性があります。たとえば、安全かつ効率的にデバイスをオフにするメカニズムがない場合、サポート終了と最終的な廃棄を管理することが難しい場合があります。

次のステップ