cloud-init
documentation
cloud-init
は、クロスプラットフォームのクラウドインスタンスの初期化のための業界標準のマルチディストリビューション方法です。主要なパブリッククラウドプロバイダー、プライベートクラウドインフラストラクチャのプロビジョニングシステム、およびベアメタルインストールでサポートされています。
ブート中、cloud-init
は実行中のクラウドを識別し、システムをそれに応じて初期化します。クラウドインスタンスは、初回起動時に自動的にネットワーキング、ストレージ、SSH キー、パッケージなど、さまざまなシステムの側面がすでに設定された状態でプロビジョニングされます。
cloud-init
は、クラウドインスタンスを起動してそれに接続するために必要な接着剤を提供し、期待どおりに機能するようにします。
クラウドユーザーにとって、cloud-init
はクラウドインスタンスのインストール不要の初回起動時の構成管理を提供します。クラウドプロバイダーにとっては、クラウドに統合できるインスタンスのセットアップを提供します。
cloud-init
が何であるか、何を行い、どのように動作するかについて詳しく読みたい場合は、ツールの高レベルの紹介をご覧ください。
Introduction to cloud-init
クラウドインスタンスやサーバーの管理および構成は、複雑で時間のかかる作業になることがあります。cloud-init
は、システムを最小限の労力で起動し、すでに必要に応じて構成されているようにするために設計されたオープンソースの初期化ツールです。
これは、主に開発者、システム管理者、および他の IT プロフェッショナルによって使用され、VM、クラウドインスタンス、またはネットワーク上のマシンの構成を自動化します。簡潔にするため、このページの残りの部分ではインスタンスのみを参照しますが、議論にはベアメタルと VM も含まれていると仮定します。定型的なセットアップタスクを自動化することで、cloud-init
はシステムのプロビジョニングにおいて反復性と効率性を確保します。
cloud-init
の利点は何ですか?
新しいクラウドインスタンスを展開するとき、cloud-init
は供給された初期設定を取得し、その設定をインスタンスが作成されるときに自動的に適用します。これは、やるべきことリストを書いて、そのリストをcloud-init
に処理させるのと似ています。
cloud-init
の真の力は、設定命令を必要な回数だけ繰り返し使用でき、常に一貫性のある信頼性の高い結果を得られるという点にあります。システム管理者であり、複数のマシンを展開したい場合、手動でプロビジョニングするのにかかる時間と労力の一部でそれを行うことができます。
cloud-init
は何を行いますか?
cloud-init
は、通常新しいインスタンスが作成される際に行われるさまざまなタスクを処理できます。ホスト名の設定、ネットワークインタフェースの構成、ユーザーアカウントの作成、スクリプトの実行などのアクティビティに責任があります。これにより、展開プロセスが効率化され、クラウドインスタンスはすべて同じ方法で自動的に構成されるため、人為的エラーを引き起こす可能性が低下します。
cloud-init
はどのように動作しますか?
cloud-init
の動作は、ブートプロセス中に主に 2 つの異なるフェーズで行われます。最初のフェーズは、ネットワーキングが有効になる前の初期(ローカル)ブート段階で行われます。2 番目のフェーズは、cloud-init
がネットワーキング構成を適用した後の遅いブート段階で行われます。
初期ブート時
このネットワーキング前の段階では、cloud-init
はデータソースを発見し、そこからすべての構成データを取得し、ネットワーキングを構成します。この段階では、以下のようなことが行われます。
- データソースの特定:ハードウェアは、インスタンスが実行されているデータソースを特定するための組み込み値を確認します。データソースは、すべての構成データのソースです。
- 構成の取得:データソースが特定されると、
cloud-init
はそのデータソースから構成データを取得します。このデータにより、cloud-init
が取るべきアクションがわかります。これは、以下の形式で提供される場合があります。- インスタンスに関するメタデータ(マシン ID、ホスト名、ネットワーク構成など)、または
- ベンダーデータ
と/または
ユーザーデータ。これらは同じ形式を取りますが、ベンダーデータはクラウドベンダーから提供され、ユーザーデータはユーザーから提供されます。これらのデータは通常、ネットワーキング後の段階で適用され、次のようなものが含まれる場合があります。- ハードウェアの最適化
- 特定のクラウドプラットフォームとの統合
- SSH キー
- カスタムスクリプト
- ネットワーク構成の書き込み:
cloud-init
はネットワーク構成を書き込み、DNS を構成し、ネットワーキングサービスが起動されると適用される準備が整います。
遅いブート時
ネットワークが構成された後のブート段階では、cloud-init
はプロビジョニングに必須ではなかったタスクを実行します。これは、ベンダーデータおよび/またはユーザーデータで指定されたとおりに、実行中のインスタンスを必要に応じて構成する場所です。以下のことに注意を払います。
- 構成管理:
cloud-init
は、Puppet、Ansible、または Chef などのツールと連携して、より複雑な構成を適用し、システムが最新であることを確認します。 - ソフトウェアのインストール:
cloud-init
はこの段階でソフトウェアをインストールし、システムが完全に最新で使用可能であることを確認します。 - ユーザーアカウント:
cloud-init
はユーザーアカウントを作成および変更し、デフォルトのパスワードを設定し、権限を構成できます。 - ユーザースクリプトの実行:ユーザーデータにカスタムスクリプトが提供されている場合、
cloud-init
はそれを実行できます。これにより、指定された追加のソフトウェアがインストールされ、セキュリティ設定が適用されるなどの操作が可能です。また、インスタンスの authorized_keys ファイルに SSH キーを挿入することもできます。これにより、マシンへの安全なリモートアクセスが可能になります。
この段階が完了すると、インスタンスの構成が完了します!
要するに
## `cloud-init`の動作概要 `cloud-init`は、クラウド環境でのインスタンスや仮想マシンの初期設定と自動化を担うツールです。このプロセスは主に 2 つのフェーズに分けられます。 #### 初期ブート段階(ネットワーク前) このフェーズでは、`cloud-init`が以下の作業を行います: 1. **データソースの識別**:インスタンスが実行されているクラウドプラットフォームを特定するために、ハードウェアのビルトイン値を確認します。 2. **設定データの取得**:データソースからインスタンスのメタデータ(マシン ID、ホスト名、ネットワーク設定など)、ベンダーデータ、ユーザーデータを取得します。 3. **ネットワーク設定の書き込み**:ネットワーク設定を書き込み、DNS を設定し、ネットワーキングサービスが起動する際にこれらの設定が適用されるようにします。 #### 遅いブート段階(ネットワーク後) ネットワークが設定された後のフェーズでは、`cloud-init`は以下のタスクを実行します: 1. **設定管理**:Puppet、Ansible、Chef などのツールと連携して、より複雑な設定を適用し、システムを最新の状態に保ちます。 2. **ソフトウェアのインストール**:必要なソフトウェアをインストールし、システムアップデートを実行して、システムが完全に最新かつ使用可能な状態になるようにします。 3. **ユーザーアカウント**:ユーザーアカウントの作成や変更、デフォルトパスワードの設定、権限の設定を行います。 4. **ユーザースクリプトの実行**:カスタムスクリプトを実行して、指定されたソフトウェアのインストール、セキュリティ設定の適用などを行います。また、SSH キーをインスタンスの authorized_keys ファイルに挿入し、安全なリモートアクセスを可能にします。 これらのステップが完了すると、インスタンスは完全に設定され、使用準備が整います。次は何ですか?
cloud-init
の基本的な概要、機能、動作について把握したので、おそらく自分で試してみたいと思うでしょう。
さらに詳細に読むこともできます。異なるブート段階で cloud-init
が行う作業や、cloud-init
に渡すことができる構成の種類、およびそれらがどのように使用されるかについて詳しく説明されています。
Configuration sources
内部的には、cloud-init
は単一の構成を構築し、その後 cloud-init
の寿命全体で参照されます。この構成は複数のソースから構築され、キーが複数のソースで定義されている場合は、優先度の高いソースが優先度の低いソースを上書きします。
基本構成
優先度の低いものから高いものまで、構成ソースは次のとおりです。
- ハードコードされた構成:
cloud-init
のソース内に存在し、変更できない構成。 - 構成ディレクトリ:
/etc/cloud/cloud.cfg
および/etc/cloud/cloud.cfg.d
に定義されたもの。 - ランタイム構成:
/run/cloud-init/cloud.cfg
に定義されたもの。 - カーネルコマンドライン:カーネルコマンドラインで、
cc:
とend_cc
の間にあるものは、cloud-config ユーザーデータとして解釈されます。
これらの 4 つのソースが基本構成を構成します。
ベンダーデータとユーザーデータ
基本構成に追加されるのは、データソースによって提供されるベンダーデータとユーザーデータです。 これらはデータソースから取得され、インスタンスの起動時に定義されます。
Note
基本構成で定義されている内容の多くは、ベンダーデータとユーザーデータによって上書きできますが、基本構成ソースは ##cloud-config に準拠していません。
ネットワーク構成
ネットワーク構成は、他の cloud-init 構成とは独立して行われます。詳細については、ネットワーク構成のドキュメントを参照してください。
構成の指定
エンドユーザー
ユーザーデータをクラウドプロバイダーに渡します。cloud-init
をサポートするすべてのプラットフォームは、ユーザーデータを提供する方法を提供します。これを行う方法がわからない場合は、利用しているクラウドプラットフォームが提供するドキュメントを参照してください。また、データソースセクションに関連する cloud-init
ドキュメントがある場合もあります。
インスタンスが初期化されると、ユーザーデータを編集することはできません。ユーザーデータはクラウドから直接取得されるため、ローカルファイルにユーザーデータが含まれていても、次の起動時に上書きされる可能性があります。
ディストリビューションプロバイダー
基本構成を変更します。これは、通常、基本の cloud.cfg テンプレートを変更するための PR を提出し、ディストリビューションごとに /etc/cloud/cloud.cfg
をカスタマイズするために使用されます。さらに、/etc/cloud/cloud.cfg.d
にファイルを追加して、基本構成の一部を上書きすることもできます。
クラウドプロバイダー
ベンダーデータを渡します。これは、クラウドが独自のカスタマイズを提供するための推奨される方法です。一部の場合では、クラウドがサポートするイメージの場合に、ディストリビューションプロバイダーと同じ方法で基本構成を変更することが意味をなす場合もあります。
Boot stages
ブートには 5 つの段階があります:
- Detect
- Local
- Network
- Config
- Final
Detect
最初の段階で実行されるプラットフォーム識別ツールは ds-identify
と呼ばれます。このツールは、インスタンスが実行されているプラットフォームを検出します。このツールは、クラウドが見つからない場合に cloud-init を無効にし、有効なプラットフォームが検出された場合に cloud-init を有効にするために、init システムに統合されています。この段階は、すべての cloud-init のインストールに存在するわけではありません。
Local
- systemd service
cloud-init-local.service
- runs
- / が読み書き可能にマウントされるとすぐに
- blocks
- ブートのほとんどを可能な限りブロックし、ネットワークをブロックする必要があります
- modules
- なし
ローカルステージの目的は次のとおりです:
- 「ローカル」データソースを見つけること
- システムにネットワーク構成を適用すること(「フォールバック」を含む)
ほとんどの場合、このステージではそれ以上のことはしません。データソースを見つけ、使用するネットワーク構成を決定します。そのネットワーク構成は次のとおりです。
- datasource: メタデータ経由で提供されるクラウド提供のネットワーク構成。
- fallback:
Cloud-init
のフォールバックネットワーキングは、ゲストのネットワーク構成のための最も一般的なメカニズムであるかつてのeth0上のdhcp
の等価物をレンダリングします。 - none: ネットワーク構成を無効にするには、ファイル
/etc/cloud/cloud.cfg
に以下の内容を書き込みます:network: {config: disabled}
。
もし、これがインスタンスの初回起動である場合、選択されたネットワーク構成が適用されます。これには、以前の(古くなった)すべての設定、古い MAC アドレスを使用した永続的なデバイス名を含むクリアが含まれます。
この段階では、ネットワークの起動やすでに適用されている古い設定をブロックする必要があります。さもないと、それには DHCP フックや古いホスト名のブロードキャストなどの負の影響が生じる可能性があります。また、その後のシステムの復旧が奇妙な状態になる可能性もあります。なぜなら、その場合はネットワークデバイスを再起動する必要があるためです。
その後、Cloud-init は終了し、オペレーティングシステムの継続的な起動が、設定された通りにネットワーク構成を行うことを期待します。
Note
過去には、ローカルデータソースはネットワークなしで利用可能なもののみでした(たとえば ‘ConfigDrive’ など)。しかし、最近の DigitalOcean データソースの追加でわかるように、ネットワークが必要なデータソースでもこの段階で動作することがあります。
要するに
`cloud-init-local.service`はクラウド環境で Linux システムが起動する際に最初に実行されるサービスであり、システムの初期ネットワーク設定を行う役割を持ちます。このサービスは、システム起動時に速やかに実行され、不適切なネットワーク設定の適用を防ぎながら、適切なネットワーク設定を特定して適用します。このプロセスには、クラウドから提供されるメタデータに基づく設定、フォールバックとしての DHCP による自動設定、またはネットワーク設定を完全に無効化するオプションが含まれます。このステージが完了すると、cloud-init はシステムが残りの起動プロセスを続行し、ネットワークを正しく設定できることを期待して終了します。Network
- systemd service
- cloud-init.service
- runs
- ローカルステージと構成されたネットワーキングが起動した後
- blocks
- 可能な限り残りのブート
- modules
/etc/cloud/cloud.cfg
の中の cloud_init_modules
このステージでは、すべての構成されたネットワーキングがオンラインである必要があります。なぜなら、見つかったすべてのユーザーデータを完全に処理するからです。ここでの処理とは、次のことを行うことを意味します。
- http を含む任意の
##include
または##include-once
を取得する(再帰的に), - 圧縮されたコンテンツを解凍し、
- 発見された任意のパートハンドラを実行する。
このステージでは、disk_setup
および mounts
モジュールが実行され、ディスクのパーティション設定やフォーマット、マウントポイントの構成(たとえば /etc/fstab
内)が行われる可能性があります。これらのモジュールは、ネットワークを介してのみ利用可能なソースからの構成入力を受け取ることがあるため、それ以前に実行することはできません。たとえば、ユーザーがローカルマウントの方法を記述したネットワークリソースでユーザーデータを提供した場合が考えられます。
Azure などの一部のクラウドでは、このステージで /etc/fstab
に以前のインスタンスへの参照が含まれるファイルシステムが作成されます。したがって、このステージの後までに、cloud-init の実行に必要なもの以外の /etc/fstab
のエントリを作成しないでください。
このステージでは、パートハンドラとブートフックが実行されます。
要するに
`cloud-init.service` はクラウド上の仮想マシンや物理サーバーが起動する際に、ネットワークが利用可能になった後の段階で実行されるプロセスです。このサービスの主な目的は、ネットワーク経由で提供されるユーザーが指定したデータを取得し、処理することです。これには、特定のウェブページからのデータの取り込み、圧縮解除、および特定の操作を自動実行するスクリプトの実行が含まれます。また、ディスクの設定やファイルシステムのマウントポイントの設定など、システムのストレージ構成を設定する作業もこのステージで行われます。これらの処理を通じて、マシンはユーザーの要求に応じた形で正しく設定され、使用準備が整います。Config
- systemd service
- cloud-config.service
- runs
- ネットワークの後
- blocks
- 何もなし
- modules
/etc/cloud/cloud.cfg
の中の cloud_config_modules
このステージでは、構成モジュールのみが実行されます。ブートの他のステージに実際に影響を与えないモジュールがここで実行されます。runcmd
を含みます。
Final
- systemd service
- cloud-final.service
- runs
- ブートの最後の部分として(従来の “rc.local”)
- blocks
- 何もなし
- modules
/etc/cloud/cloud.cfg
の中の cloud_final_modules
このステージは、ブートの可能な限り遅い段階で実行されます。ユーザーがシステムにログインした後に実行することに慣れているスクリプトはここで正常に実行されるはずです。ここで実行されるものは次のとおりです。
- パッケージのインストール
- 構成管理プラグイン(Ansible、Puppet、Chef、salt-minion)
- ユーザー定義のスクリプト(つまり、ユーザーデータとして渡されたシェルスクリプト)
cloud-init
の完了を待機している外部のスクリプトは、cloud-init status --wait
サブコマンドを使用して、独自の systemd
ユニットの依存関係チェーンを記述する必要なしに、cloud-init
が完了するまで外部スクリプトをブロックするのに役立ちます。詳細については、status を参照してください。
要するに
`cloud-final.service`はクラウド環境での Linux システム起動プロセスの最終段階で実行されるサービスであり、伝統的な`rc.local`のような役割を果たします。このステージでは、システムの起動がほぼ完了した後に、パッケージのインストール、設定管理ツール(Ansible、Puppet、Chef、salt-minion など)のプラグインの実行、ユーザー定義スクリプト(例えば、ユーザーデータとして渡されたシェルスクリプト)などが行われます。`cloud-init`の処理が完了するまで外部スクリプトを待機させたい場合、`cloud-init status --wait`サブコマンドを使用することで、`cloud-init`が完了するまで外部スクリプトをブロックできます。これにより、独自の systemd ユニットの依存関係チェーンを書く必要がなくなります。First boot determination
Cloud-init
は、現在のブートが新しいインスタンスの最初のブートかどうかを判断し、適切な構成を適用する必要があります。インスタンスの最初のブートでは、「インスタンスごと」の構成をすべて実行する必要がありますが、その後のブートでは「ブートごと」の構成のみを実行する必要があります。このセクションでは、Cloud-init
がこの判断を行う方法と、なぜそれが必要かについて説明します。
実行時に、Cloud-init
はステージとブートをまたいで使用するための内部状態のキャッシュを保存します。
このキャッシュが存在する場合、Cloud-init
はこのシステムで以前に実行されたことがあります[1]。これが発生する可能性のある 2 つのケースがあります。最も一般的なのは、インスタンスが再起動され、これが 2 回目以降のブートである場合です。また、ファイルシステムが新しいインスタンスにアタッチされ、これがインスタンスの最初のブートである場合もあります。これが発生する最も明らかなケースは、起動済みのインスタンスからキャプチャされたイメージからインスタンスが起動される場合です。
デフォルトでは、Cloud-init
は実行時にキャッシュ内のインスタンス ID を実行時に決定したインスタンス ID と照合して、どのケースで実行されているかを判断しようとします。一致しない場合、これがインスタンスの最初のブートであり、そうでない場合は後続のブートです。内部的には、Cloud-init
はこの動作を check
と呼んでいます。
この動作は、起動済みのインスタンスからキャプチャされたイメージが正しく動作するために必要ですので、ジェネリックなクラウドイメージにはデフォルトで含まれています。しかし、この動作が問題を引き起こす場合もあります[2]。これらのケースでは、Cloud-init
はシステムに存在するインスタンス ID を無条件に信頼するように動作を変更するサポートがあります。これはつまり、キャッシュが存在する場合に Cloud-init
が新しいインスタンスを検出しないことを意味し、したがって、Cloud-init
が新しいインスタンス(およびそのための最初のブート)を検出する唯一の方法は、Cloud-init
のキャッシュを手動で削除することです。内部的には、この動作を trust
と呼んでいます。
これらの動作のどちらを使用するかを構成するには、Cloud-init
は manual_cache_clean
構成オプションを公開しています。false
(デフォルト)の場合、Cloud-init
はキャッシュ内のインスタンス ID が一致しない場合にキャッシュをチェックしてクリーンアップします(上述の通り、これがデフォルトです)。true
の場合、Cloud-init
は既存のキャッシュを信頼します(したがって、クリーンアップしません)。
まとめると
## 初回起動の判定について `cloud-init`は、現在の起動が新しいインスタンスの初回起動かどうかを判断する必要があります。この判断は、初回起動時には「インスタンスごと」の設定を、後続の起動時には「起動ごと」の設定を適用するために重要です。 #### キャッシュの使用 - `cloud-init`は実行時の内部状態をキャッシュとして保存します。 - キャッシュが存在する場合、`cloud-init`は以前にこのシステムで実行されたと判断します。 - インスタンス ID をキャッシュと実行時に確認し、一致しない場合は初回起動と判断します。 #### 振る舞いのカスタマイズ - **デフォルト(`check`):** インスタンス ID が一致しなければ、初回起動と判断し、キャッシュをクリーンします。 - **信頼モード(`trust`):** システム内のインスタンス ID を無条件で信頼し、新しいインスタンスの検出を行わないようにします。これを有効にするには、キャッシュを手動で削除する必要があります。 #### 設定オプション - `manual_cache_clean`オプションを使用して、これらの振る舞いをカスタマイズできます。 - `false`(デフォルト):インスタンス ID が一致しない場合にキャッシュをクリーンします。 - `true`:既存のキャッシュを信頼し、キャッシュをクリーンしません。要すると
`cloud-init`は、コンピュータがクラウド環境で初めて起動するか、それとも以前に起動したことがあるかを判断するために、インスタンスの起動時にいくつかのチェックを行います。主に、`cloud-init`は内部で状態を記録しており、この記録(キャッシュ)があるかどうかで、初回起動かどうかを判断します。もしキャッシュがあれば、それは以前に起動したことがあるとみなされます。ただし、キャッシュ内のインスタンス ID と現在のインスタンス ID が異なる場合、新しいインスタンスの初回起動と判断します。この振る舞いはデフォルトですが、問題が起こる場合もあるため、設定を変更して、cloud-init がキャッシュを無条件で信頼し、新しい起動を検出しないようにすることも可能です。この設定は、キャッシュの手動削除を行うことで、新しいインスタンスとして扱わせることができます。現在 `trust` モードであるインスタンスをイメージとしてキャプチャし、他のインスタンスを起動する場合、キャッシュを手動でクリーンアップする必要があります。そうしないと、キャプチャされたイメージから起動されたインスタンスはすべて、最初のブートをキャプチャされたインスタンスの後続のブートとして検出し、インスタンスごとの構成を適用しません。 これは機能的な問題ですが、潜在的なセキュリティ上の問題でもあります: `cloud-init` は最初のブート時に SSH ホストキーのローテーションを担当していますが、これはこれらのインスタンスでは発生しません。 [[1](https://cloudinit.readthedocs.io/en/latest/explanation/boot.html##id2)] したがって、このキャッシュが存在しない場合、`cloud-init` はこのシステムで実行されたことがないため、これがこのインスタンスの明確な最初のブートであることになります。 [[2](https://cloudinit.readthedocs.io/en/latest/explanation/boot.html##id3)] データソースの存在に厳密に依存するこの厳格な信頼の方法が問題を引き起こす場合があります。 - クラウドのメタデータサービスが不安定であり、`cloud-init` がそのプラットフォームでローカルにインスタンス ID を取得できない場合、`cloud-init` のインスタンス ID の決定が失敗することがあります。そのため、これがインスタンスの最初のブートか後続のブートかを判断することができなくなります([##1885527](https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1885527))。 - `cloud-init` が物理アプライアンスやデバイスをプロビジョニングするために使用され、攻撃者が異なるインスタンス ID を持つデータソースをデバイスに提示できる場合、`cloud-init` のデフォルトの動作では、これがインスタンスの最初のブートと検出され、攻撃者の構成でデバイスがリセットされます(これは、[NoCloud データソース](https://cloudinit.readthedocs.io/en/latest/explanation/boot.html##:~:text=observed%20with%20the-,NoCloud%20datasource,-in%20%231879530).)で観察されました([##1879530](https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1879530))。)。