複数のクラウドアカウントや複数リージョンを同時に扱うとき、TerraformのProviderエイリアスは避けて通れません。公式仕様に沿って、設計・モジュール化・認証切り替えまでをコンパクトにまとめます。
出典はTerraform公式ドキュメント(https://developer.hashicorp.com/terraform/language/providers)に準拠し、バージョン依存の挙動は慎重に扱います。記事後半には試験で問われやすいポイントとサンプル問題も用意しました。
Terraformでは、同一プロバイダーに対して複数の設定(例: リージョンや認証情報違い)を持たせるためにaliasメタ引数を使います。エイリアスなしの設定はデフォルト構成、alias付きは別名の構成として扱われます。リソースやデータソース側ではproviderメタ引数でどの構成を使うかを明示できます。
モジュール配下では、デフォルトのプロバイダー構成は親から暗黙に利用されますが、エイリアス付き構成を使わせたい場合はmoduleブロックのprovidersマップで明示的に渡します。これが複数アカウント/リージョン運用の基本パターンです。
エイリアスの最小例(AWSを例示)
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
provider "aws" {
region = "ap-northeast-1" # デフォルト構成
}
provider "aws" {
alias = "usw2"
region = "us-west-2"
}
resource "aws_s3_bucket" "tokyo" {
bucket = "example-tokyo-bucket-unique"
}
resource "aws_s3_bucket" "oregon" {
provider = aws.usw2
bucket = "example-oregon-bucket-unique"
}
実務では、1) ルートで複数のエイリアスを定義して直接使う、2) モジュール化してprovidersマップで複数構成を注入する、3) スタック(ディレクトリ)を分けて状態も分離する、の3パターンがよく使われます。規模や分離要件(コンプライアンス/ blast radius)に応じて選びます。
複数アカウント(例: dev/prod)、複数リージョン(例: ap-northeast-1 / us-west-2)を横断する場合、アカウント境界はstateも分けるのが安全です。リージョン差は同一stateで扱ってもよいですが、変更衝突や並列実行を考えると業務要件次第で分離検討が必要です。
| パターン | 適用範囲 | メリット | 注意点/リスク |
|---|---|---|---|
| ルート直書き(複数alias) | 小〜中規模、単一チーム | シンプル、学習コスト低い | モノリス化しやすい、影響範囲が広がる |
| モジュール+providersマップ | 中〜大規模、チーム分割 | 明示的依存、再利用・テストが容易 | providers渡し忘れで暗黙のデフォルトに落ちやすい |
| スタック分割(状態も分離) | 厳格分離(アカウント/環境) | blast radius最小、権限最小化 | 横断変更が難しく運用に工夫が必要 |
マルチアカウント/リージョンとエイリアスの関係
モジュールへ複数プロバイダーを注入する例
module "multi_region" {
source = "./modules/multi_region"
providers = {
aws = aws # デフォルト(ap-northeast-1)
aws.usw2 = aws.usw2 # 別リージョン(us-west-2)
}
}
子モジュールは親のデフォルト構成を暗黙に使えますが、エイリアス付き構成は暗黙継承されません。子でエイリアスを使う場合、moduleブロックのprovidersマップで、子が参照するプロバイダー名(例: aws、aws.usw2)を、親の具体的なインスタンス(aws、aws.usw2など)にマッピングします。
キーは「子モジュール内で使う名前」、値は「親で定義した実体」を指します。値は式にできるため条件分岐は可能ですが、エイリアスの作成自体は動的には行えません(providerブロックはfor_each等をサポートしません)。
子モジュールで別リージョンを併用する例
# 親側
module "net" {
source = "./modules/net"
providers = {
aws = aws # デフォルト: ap-northeast-1
aws.usw2 = aws.usw2 # 追加: us-west-2
}
}
# 子モジュール側(./modules/net/main.tf)
terraform {
required_providers {
aws = { source = "hashicorp/aws" }
}
}
resource "aws_vpc" "primary" {
cidr_block = "10.0.0.0/16" # デフォルト構成(ap-northeast-1)
}
resource "aws_subnet" "west" {
provider = aws.usw2 # エイリアス構成(us-west-2)
cidr_block = "10.1.0.0/24"
vpc_id = "vpc-xxxxxxxx"
}
エイリアスごとに認証情報や権限を切り替えます。AWSではprofile、assume_role、環境変数など複数の経路があり、特定の優先順位で評価されます。各プロバイダーの公式ドキュメントに沿って、意図した方法のみを構成に記述するのが安全です。
アカウント単位の強い分離が必要な場合は、エイリアスだけでなくstateも環境/アカウントごとに分け、CIから実行ロールも分離します。リージョンは変数で切り替えられますが、エイリアス名は静的に保つのが移行しやすいです。
エイリアス別に資格情報を分ける例(AWS)
provider "aws" {
alias = "dev"
region = var.dev_region
profile = "dev"
}
provider "aws" {
alias = "prod"
region = var.prod_region
assume_role {
role_arn = var.prod_role_arn
session_name = "tf-prod"
}
}
resource "aws_kms_key" "dev" {
provider = aws.dev
description = "dev key"
}
resource "aws_kms_key" "prod" {
provider = aws.prod
description = "prod key"
}
stateは各リソースがどのプロバイダー構成で管理されるかの参照を保持します。エイリアス名自体の変更は慎重に。名称だけを変えると、同一API先であっても予期しない差分検出の温床になります。エイリアス名は長期的に安定した命名にしてください。
import(Terraform 1.5+のimportブロック)や移行でも、どのエイリアス構成を使うかを明示できます。plan/applyは、各リソースが参照するproviderメタ引数に基づいて適切な構成を使用します。
importブロックでエイリアスを指定(1.5+)
import {
to = aws_s3_bucket.oregon
id = "example-oregon-bucket-unique"
provider = aws.usw2
}
Associate/Professionalともに、エイリアスの定義場所、リソース/モジュールでの指定方法、暗黙の継承の範囲が頻出です。とくにモジュールに対してエイリアスを渡し忘れると、子がデフォルト構成を使ってしまい意図しないリージョン/アカウントに作用するケースを問われがちです。
provider引数は式を取れますが、エイリアス自体を動的生成することはできません。大量リージョン展開はディレクトリ分割やテンプレート化で補いましょう。
誤りやすい例と正しい指定
# 誤り(子でaws.usw2を使うのに親が渡していない)
module "m" {
source = "./m"
# providersマップが無い -> 子はデフォルトawsのみ
}
# 正
module "m" {
source = "./m"
providers = {
aws.usw2 = aws.usw2
}
}
Associate / Pro
問題 1
子モジュールが us-west-2 と ap-northeast-1 の両方でAWSリソースを作成します。子では aws.usw2 を明示的に使うリソースがあります。親モジュール側で正しい設定はどれですか?
正解: A
子がaws.usw2を参照するなら、親module.providersでキーaws.usw2を親の実体aws.usw2にマップする必要があります。デフォルトawsだけでは子のaws.usw2参照は解決されません。キー名のtypo(aws.use2など)も不可です。
エイリアスは動的に作れますか?(for_eachや変数で量産したい)
いいえ。providerブロックはcount/for_eachをサポートしません。必要な数だけ静的に定義し、モジュール側でprovidersマップを使って切り替えます。
子モジュールでデフォルト構成だけを使う場合、providersマップは必須ですか?
必須ではありません。親のデフォルト構成は暗黙に利用されます。エイリアス構成を子で使う場合のみ、providersマップで明示的に渡してください。
エイリアス名を後から変更するとどうなりますか?
stateが参照するプロバイダー構成キーが変わるため差分の原因になります。実体が同じでも予期せぬ影響が出る可能性があるため、原則リネームしない方針を推奨します。やむを得ない場合は計画的に段階移行し、planの差分と影響範囲を厳密に確認してください。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...