リソース間の参照
この講座では、Terraformでのリソース間参照について学びます。
- リソースの属性参照の構文
- VPCとサブネットの関連付け
- 依存関係の自動解決
- depends_on(明示的な依存関係)の使い方
1. 記載方法
AWSなどのクラウドサービスでインフラを構築する際、リソース同士は独立しているわけではなく、関係性を持っています。例えば、「作成したVPCの中に、サブネットを作りたい」という場合です。この時、サブネット側では「どのVPCに所属するか」を指定する必要があります。
1.1 参照の構文
リソースの値(属性)を参照するには、以下の構文を使用します。
リソースの型.リソース名.属性
例えば、aws_vpc というリソース型で、vpc という名前で定義したVPCの、ID(id)を参照したい場合は、以下のように記述します。
aws_vpc.vpc.id
各リソースで参照できる属性(id 以外にも arn や cidr_block など)は、リソースごとにTerraform Registryのドキュメント(例:aws_vpc)の「Attribute Reference」セクションにまとめられています。
1.2 サンプル
実際に値を参照するサンプルを説明します。
今回は、VPCとサブネットを作り、サブネットに指定するVPCのIDに、作成したVPCのIDを設定する方法を紹介します。
まず、VPCは通常通りのコードで構いません。
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "test-vpc"
}
}
サブネットの定義部分です。
resource "aws_subnet" "subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.1.0/24"
tags = {
Name = "test-subnet"
}
}
この中で、vpc_id = aws_vpc.vpc.id の部分がポイントです。
こうすることで、サブネットに指定されるVPCのIDは、直前の vpc のIDとなります。
| ⚠️ 「has not been declared」エラーが出る場合 |
|---|
aws_vpc.vpc.id の部分で、リソース名(2つ目の vpc)を間違えると「A managed resource "aws_vpc" "xxx" has not been declared」というエラーが発生します。エラーが出たら、リソース定義の名前(resource "aws_vpc" "vpc" の "vpc" 部分)と参照先が一致しているか確認してください。 |
1.3 実行順序の自動制御
リソース間の参照による依存関係と作成順序の例を以下に示します。
graph LR VPC[VPC] -- "vpc_idを参照" --> Subnet[サブネット] Subnet -- "subnet_idを参照" --> SG[セキュリティグループ]
この記述の重要な点は、Terraformがリソースを作成する順番を自動的に判断してくれることです。
aws_subnet を作るためには、vpc_id が必要。
vpc_id を知るためには、先に aws_vpc が作られていないといけない。
Terraformはこの関係性をコードから読み取り、「まずはVPCを作成し、その完了後にサブネットを作成する」という正しい順序で処理を実行します。
2. 実際に使ってみる
具体的に実行してみます。
2.1 コードの記載
先ほど説明したVPCとサブネットを作るコードを、main.tf に作成します。
provider "aws" {
region = "ap-northeast-1"
}
# 1. VPCの定義
resource "aws_vpc" "vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "test-vpc"
}
}
# 2. Subnetの定義(VPCを参照)
resource "aws_subnet" "subnet" {
# ここでVPCのIDを参照しています
vpc_id = aws_vpc.vpc.id
cidr_block = "10.0.1.0/24"
tags = {
Name = "test-subnet"
}
}
2.2 リソースの作成
terraform apply コマンドで、リソースを作成します。
terraform apply
作成されたリソースの中で、まずは test-vpc から確認してみましょう。
サブネットを確認します。ここでポイントとなるのは、VPCの項目で、test-vpc のIDが正しく設定されていることです。これにより、無事にIDの参照ができていることが確認できます。
2.3 リソースの削除
最後に、作成したリソースを削除しておきます。
terraform destroy
3. depends_on
3.1 記載方法
明示的な依存関係 (depends_on)
前回は、リソースの値を参照することで、Terraformが自動的に作成順序を判断してくれる「暗黙的な依存関係」について学びました。
しかし、「リソース同士で値の参照(idなど)はしていないけれど、作成順序を守らせたい」というケースが存在します。このような場合に利用するのが、depends_on というメタ引数です。
なぜ必要なのか?
Terraformは基本的に、依存関係のないリソースは可能な限り並列(同時)に作成して、構築時間を短縮しようとします。
しかし、これによって困る場面があります。例えばアプリケーションのセットアップ時です。
「Webサーバ」と「データベース」を作るとします。これらが同時に作られ始めた場合、データベースの構築が完了する前に、Webサーバが起動してデータベースへ接続を試みてしまい、エラーになる(アプリケーションが起動しない)可能性があります。
この場合、「データベースの作成が完全に終わってから、Webサーバを作り始めてほしい」という指示を出す必要があります。
記載方法
リソースブロックの中に、以下のように記述します。こうすることで、depends_on の中で定義したリソースが作成されるまで、作成が保留されます。
resource "リソース型" "名前" {
depends_on = [
リソース型.依存先のリソース名
]
}
また、depends_on の中には複数のリソースを、カンマ区切りで記載することができます。
resource "リソース型" "名前" {
depends_on = [
リソース型.依存先のリソース名1,
リソース型.依存先のリソース名2
]
}
3.2 サンプルコード(EC2とRDSの例)
ここでは概念を理解するために、EC2(Webサーバ)とRDS(データベース)の例を見てみましょう。
EC2の設定の中で、RDSのIDなどを直接参照していない場合でも、depends_on を使うことで順序を強制できます。
# 1. データベース (RDS)
resource "aws_db_instance" "db" {
allocated_storage = 10
engine = "mysql"
instance_class = "db.t3.micro"
username = "admin"
password = "password"
# ...その他の設定
}
# 2. Webサーバ (EC2)
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t2.micro"
# ここがポイント
# "aws_db_instance.db" の作成完了を待ってから、このEC2を作り始める
depends_on = [
aws_db_instance.db
]
}
このように、aws_instance.web 側に depends_on で aws_db_instance.db を指定することで、aws_db_instance.db が確実に作成されてから、aws_instance.web が作成されます。
なお、EC2とRDSは作成に時間がかかりコストも発生しやすいこと、また作成順序の制御は裏側の処理であり挙動が見えにくいため、今回はハンズオンを省略します。
3.3 注意点
depends_on は便利な機能ですが、多用しすぎるとTerraformのメリットである「並列実行による高速化」を損なってしまいます。
前回学んだ「値の参照(暗黙的な依存関係)」で解決できる場合はそちらを優先し、どうしても順序制御が必要な場合のみ depends_on を使用するのがベストプラクティスです。
4. まとめ
この講座では、Terraformにおけるリソース間の参照について学びました。
リソース型.リソース名.属性の構文でリソースの値を参照できる- 値を参照すると、Terraformが自動的に作成順序を判断してくれる(暗黙的な依存関係)
- depends_onで明示的に依存関係を指定できる
depends_onは値の参照がなくても順序を強制したい場合に使用するdepends_onの多用は並列実行の効率を損なうため、必要な場合のみ使用する