リソース間の参照

この講座では、Terraformでのリソース間参照について学びます。

  • リソースの属性参照の構文
  • VPCとサブネットの関連付け
  • 依存関係の自動解決
  • depends_on(明示的な依存関係)の使い方

1. 記載方法

AWSなどのクラウドサービスでインフラを構築する際、リソース同士は独立しているわけではなく、関係性を持っています。例えば、「作成したVPCの中に、サブネットを作りたい」という場合です。この時、サブネット側では「どのVPCに所属するか」を指定する必要があります。

1.1 参照の構文

リソースの値(属性)を参照するには、以下の構文を使用します。

リソースの型.リソース名.属性

例えば、aws_vpc というリソース型で、vpc という名前で定義したVPCの、ID(id)を参照したい場合は、以下のように記述します。

aws_vpc.vpc.id

各リソースで参照できる属性(id 以外にも arncidr_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_onaws_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の多用は並列実行の効率を損なうため、必要な場合のみ使用する