メインコンテンツにスキップ

モジュール内のプロバイダー

複数のモジュールを持つ構成では、リソースとプロバイダー構成の関連付けについて、いくつかの特別な考慮事項があります。

構成内の各リソースは、1つのプロバイダー構成に関連付けられている必要があります。プロバイダー構成は、OpenTofuの他のほとんどの概念とは異なり、OpenTofu構成全体でグローバルであり、モジュール境界を越えて共有できます。プロバイダー構成は、ルートモジュールでのみ定義できます。

プロバイダーは、継承による*暗黙的*な方法、または`module`ブロック内の`providers`引数による*明示的*な方法の2つの方法で、子孫モジュールに渡すことができます。これらの2つのオプションについては、以下のセクションで詳しく説明します。

他の1つ以上のモジュールから呼び出されることを意図したモジュールには、`provider`ブロックを含めてはなりません。独自のプロバイダー構成を含むモジュールは、`for_each`、`count`、`depends_on`引数と互換性がありません。

プロバイダー構成は、リモートオブジェクトの破棄や状態の更新など、関連付けられたリソースに対するすべての操作に使用されます。 OpenTofuは、状態の一部として、各リソースへの変更の適用に最後に使用されたプロバイダー構成への参照を保持します。 `resource`ブロックが構成から削除されると、リソースの`provider`引数(存在する場合)は構成に存在しなくなるため、状態のこのレコードを使用して適切な構成が特定されます。

その結果、プロバイダー構成ブロックを構成から削除する前に、特定のプロバイダー構成に属するすべてのリソースが破棄されていることを確認する必要があります。 OpenTofuが、プロバイダー構成ブロックが使用できなくなった状態で追跡されているリソースインスタンスを検出した場合、計画中にエラーが返され、プロバイダー構成を再導入するように求められます。

モジュールにおけるプロバイダーのバージョン制約

プロバイダー*構成*はモジュール間で共有されますが、各モジュールは独自のプロバイダー要件を宣言する必要があります。これにより、OpenTofuは構成内のすべてのモジュールと互換性のある単一バージョンのプロバイダーがあることを確認し、プロバイダーのグローバル(モジュールに依存しない)識別子として機能するソースアドレスを指定できます。

モジュールが特定のプロバイダーの特定のバージョンを必要とすることを宣言するには、`terraform`ブロック内で`required_providers`ブロックを使用します

コードブロック
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
}
}
}

プロバイダー要件は、たとえば、「このモジュールはプロバイダー`hashicorp/aws`のバージョンv2.7.0を必要とし、`aws`として参照します」と述べています。ただし、AWSリージョンなどの、プロバイダーがアクセスするリモートエンドポイントを決定する構成設定は指定していません。構成設定はプロバイダー*構成*から提供され、特定のOpenTofu構成全体では、同じプロバイダーに対して複数の異なる構成を持つことができます。

モジュール内のプロバイダーエイリアス

モジュール内でプロバイダーの複数の構成名を宣言するには、`configuration_aliases`引数を追加します

コードブロック
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
configuration_aliases = [ aws.alternate ]
}
}
}

上記の要件は、リソースが`provider`引数を使用して参照できるエイリアスプロバイダー構成名`aws.alternate`が追加されていることを除いて、前と同じです。

共有モジュールを作成する場合は、`>=`制約を使用して、必要な最小限のプロバイダーバージョンのみを制約します。これは、モジュールが依存する機能を含む最小バージョンを指定する必要があり、したがって、モジュールユーザーは、構成の他の部分で他の機能が必要な場合に、より新しいプロバイダーバージョンを選択できるようになります。

暗黙的なプロバイダーの継承

単純な構成を簡単にするために、子モジュールは親モジュールからデフォルトのプロバイダー構成を自動的に継承します。つまり、明示的な`provider`ブロックはルートモジュールにのみ表示され、ダウンストリームモジュールはそのプロバイダーのリソースを宣言するだけで、ルートプロバイダー構成に自動的に関連付けられます。

たとえば、ルートモジュールには、子モジュールをインスタンス化する`provider`ブロックと`module`ブロックのみが含まれている場合があります

コードブロック
provider "aws" {
region = "us-west-1"
}

module "child" {
source = "./child"
}

子モジュールは、追加のプロバイダー構成を必要とせずに、このプロバイダーの任意のリソースを使用できます

コードブロック
resource "aws_s3_bucket" "example" {
bucket = "provider-inherit-example"
}

設定全体で各プロバイダーに対して単一の構成で十分な場合は、このアプローチを使用することをお勧めします。

より複雑な状況では、複数のプロバイダー構成が存在する場合や、子モジュールが親モジュールとは異なるプロバイダー設定を使用する必要がある場合があります。このような状況では、プロバイダーを明示的に渡す必要があります。

プロバイダーの明示的な受け渡し

子モジュールそれぞれが特定のプロバイダーの異なる構成を必要とする場合、または子モジュールが親モジュールとは異なるプロバイダー構成を必要とする場合は、`module` ブロック内で `providers` 引数を使用して、子モジュールで使用可能なプロバイダー構成を明示的に定義できます。例えば

コードブロック
# The default "aws" configuration is used for AWS resources in the root
# module where no explicit provider instance is selected.
provider "aws" {
region = "us-west-1"
}

# An alternate configuration is also defined for a different
# region, using the alias "usw2".
provider "aws" {
alias = "usw2"
region = "us-west-2"
}

# An example child module is instantiated with the alternate configuration,
# so any AWS resources it defines will use the us-west-2 region.
module "example" {
source = "./example"
providers = {
aws = aws.usw2
}
}

`module` ブロック内の `providers` 引数は、リソース内の`provider` 引数に似ていますが、モジュールには多くの異なるプロバイダーからのリソースが含まれる可能性があるため、単一の文字列ではなくマップです。

`providers` マップのキーは、子モジュールが想定するプロバイダー構成名であり、値は*現在の*モジュール内の対応する構成の名前です。

`module` ブロックで `providers` 引数が使用されると、すべてのデフォルトの継承動作がオーバーライドされるため、*すべて*の必要なプロバイダーのマッピングを列挙する必要があります。これは、暗黙的および明示的なプロバイダーの受け渡しを混在させた場合に発生する可能性のある混乱や予期しない事態を避けるためです。

追加のプロバイダー構成(`alias` 引数が設定されているもの)は、子モジュールによって自動的に継承されることは*決して*ないため、常に `providers` マップを使用して明示的に渡す必要があります。たとえば、2つのAWSリージョンでネットワーク間の接続を構成するモジュールは、ソースリージョンと宛先リージョンの両方 necessite する可能性があります。その場合、ルートモジュールは次のようになります。

コードブロック
provider "aws" {
alias = "usw1"
region = "us-west-1"
}

provider "aws" {
alias = "usw2"
region = "us-west-2"
}

module "tunnel" {
source = "./tunnel"
providers = {
aws.src = aws.usw1
aws.dst = aws.usw2
}
}

次に、サブディレクトリ `./tunnel` はプロバイダーの構成エイリアスを宣言する必要があるため、呼び出し元のモジュールは `providers` 引数でこれらの名前の構成を渡すことができます。

コードブロック
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
configuration_aliases = [ aws.src, aws.dst ]
}
}
}

その後、各リソースは、2つのプロバイダー構成のどちらを使用するかを選択するために、独自の `provider` 属性を `aws.src` または `aws.dst` に設定する必要があります。