【大阪 / 横浜 / 徳島】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜 / 徳島】インフラ / サーバーサイドエンジニア募集中!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【200ヶ国以上に対応】グローバル eSIM「ビヨンドSIM」

【200ヶ国以上に対応】グローバル eSIM「ビヨンドSIM」

【中国への旅行・出張・駐在なら】中国SIMサービス「チョコSIM」

【中国への旅行・出張・駐在なら】中国SIMサービス「チョコSIM」

【グローバル専用サービス】北米・中国でも、ビヨンドのMSP

【グローバル専用サービス】北米・中国でも、ビヨンドのMSP

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

[Terraform]異なるtfstateに記述されているリソースの情報を参照する

インフラエンジニアの寺岡です。

TerraformのHCLを記述する際に便利なものに
terraform_remote_stateというデータソースがあります。
今回はこちらの紹介をしてみようと思います。

■terraform_remote_stateとは

異なるtfstateに記述されているリソースの情報を参照したい。
そんなときに利用すると便利なデータソースです。

そもそもTerraformにはtfstateという
terraform applyでデプロイを実行したときに
作成されたリソース情報が記録されているファイルがあります。

Terraformでインフラを構築する際に
複数の環境(踏み台/本番/開発など)がある場合は
terraform applyが他の環境に影響を及ぼさないように
環境ごとにtfstateを分けるのが鉄則です。

tfstateを分けた場合
踏み台環境で作成したリソースの情報を
本番環境でリソースを作成するときに参照したいということがあります。
その際に便利なのが「terraform_remote_state」です。

■どんなときに使うのか

AWSになりますが以下に1つ例を記載します。

サーバにSSHで接続する際は踏み台サーバを経由する前提とした場合
セキュリティグループとルールをTerraformで作成しようとするとどのようになるでしょうか。
まずは踏み台サーバ用のVPCとセキュリティグループ + ルールを作成すると思います。

bastion.tf

terraform {
  backend "s3" {
    bucket = "terraform-tfstate"
    key    = "terraform-blog/bastion.tfstate"
    region = "ap-northeast-1"
  }
}

resource "aws_vpc" "bastion" {
  cidr_block                     = "10.0.0.0/16"
  enable_dns_hostnames           = true

  tags {
    Name = "vpc-bastion"
  }
}

resource "aws_security_group" "bastion" {
  name        = "bastion-sg"
  description = "for bastion server"
  vpc_id      = "${aws_vpc.bastion.id}"

  tags {
    Name = "bastion-sg"
  }
}

resource "aws_security_group_rule" "prod_sg_rule" {
  security_group_id        = "${aws_security_group.bastion.id}"
  type                     = "ingress"
  from_port                = "22"
  to_port                  = "22"
  protocol                 = "tcp"
  cidr_blocks              = "XXX.XXX.XXX.XXX"
}

backendの設定でtfstateをbastion.tfstateという名前でS3に置いていますが
VPCとセキュリティグループ + 特定IPからの許可ルールを追加しているだけなのでこれは大丈夫です。
では、踏み台から「接続される側」の設定はどのようになるでしょうか。

production.tf

terraform {
  backend "s3" {
    bucket = "terraform-tfstate"
    key    = "terraform-blog/prod.tfstate"
    region = "ap-northeast-1"
  }
}

resource "aws_vpc" "prod" {
  cidr_block                     = "10.0.0.0/16"
  enable_dns_hostnames           = true

  tags {
    Name = "vpc-prod"
  }
}

resource "aws_security_group" "prod" {
  name        = "prod-sg"
  description = "for production server"
  vpc_id      = "${aws_vpc.prod.id}"

  tags {
    Name = "prod-sg"
  }
}

resource "aws_security_group_rule" "prod_sg_rule" {
  security_group_id        = "${aws_security_group.prod.id}"
  type                     = "ingress"
  from_port                = "22"
  to_port                  = "22"
  protocol                 = "tcp"
  source_security_group_id = "${何を指定すれば良い???}"
}

踏み台サーバからのSSH接続を許可したい場合は
踏み台用のセキュリティグループからのアクセスを許可する必要があるので
source_security_group_idで踏み台用のセキュリティグループのIDを指定する必要があります。

ただし、backendの記述で踏み台サーバとtfstateが分かれているので
このままでは、セキュリティグループのIDを参照することができません。

■どのように使うのか

できないことがわかったところで参照できるようにしたいと思います。
まずはbastion.tf側でoutputの設定を追加する必要があります。

bastion.tf

terraform {
  backend "s3" {
    bucket = "terraform-tfstate"
    key    = "terraform-blog/bastion.tfstate"
    region = "ap-northeast-1"
  }
}

resource "aws_vpc" "bastion" {
  cidr_block                     = "10.0.0.0/16"
  enable_dns_hostnames           = true

  tags {
    Name = "vpc-bastion"
  }
}

resource "aws_security_group" "bastion" {
  name        = "bastion-sg"
  description = "for bastion server"
  vpc_id      = "${aws_vpc.bastion.id}"

  tags {
    Name = "bastion-sg"
  }
}

resource "aws_security_group_rule" "prod_sg_rule" {
  security_group_id        = "${aws_security_group.bastion.id}"
  type                     = "ingress"
  from_port                = "22"
  to_port                  = "22"
  protocol                 = "tcp"
  cidr_blocks              = "XXX.XXX.XXX.XXX"
}

## 追加
output "security_group_id" {
  value = "${aws_security_group.bastion.id}"
}

異なるtfstateから値を参照する場合は
参照させたい値を事前にoutputで出力しておく必要があります。
今回は踏み台用セキュリティグループのIDを参照したいので
aws_security_group.bastion.idを出力しておきます。

この状態でproduction.tfからterraform_remote_stateで値を参照できます。

production.tf

terraform {
  backend "s3" {
    bucket = "terraform-tfstate"
    key    = "terraform-blog/prod.tfstate"
    region = "ap-northeast-1"
  }
}

resource "aws_vpc" "prod" {
  cidr_block                     = "10.0.0.0/16"
  enable_dns_hostnames           = true

  tags {
    Name = "vpc-prod"
  }
}

resource "aws_security_group" "prod" {
  name        = "prod-sg"
  description = "for production server"
  vpc_id      = "${aws_vpc.prod.id}"

  tags {
    Name = "prod-sg"
  }
}

resource "aws_security_group_rule" "prod_sg_rule" {
  security_group_id        = "${aws_security_group.prod.id}"
  type                     = "ingress"
  from_port                = "22"
  to_port                  = "22"
  protocol                 = "tcp"
  source_security_group_id = "${data.terraform_remote_state.bastion.security_group_id}"
}

## 追加
data "terraform_remote_state" "bastion" {
  backend = "s3"

  config {
    bucket = "terraform-tfstate"
    key    = "terraform-blog/bastion.tfstate"
    region = "ap-northeast-1"
  }
}

terraform_remote_stateというデータソースを使って
S3に保存している踏み台用のtfstateを読み込みます。
値はoutputで指定した名前で参照できるので
source_security_group_idに指定する値は
data.terraform_remote_state.bastion.security_group_idになります。

■まとめ

terraform_remote_stateは割とよく使うので覚えておいて損はないです。
これでtfstateを分けても問題ないですね!

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
1
読み込み中...
1 票, 平均: 1.00 / 11
10,612
X facebook はてなブックマーク pocket
【2025.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

【2025.6.30 Amazon Linux 2 サポート終了】Amazon Linux サーバー移行ソリューション

この記事をかいた人

About the author

寺岡佑樹

2016年ビヨンド入社、現在6年目のインフラエンジニア
MSPの中の人として障害対応時のトラブルシューティングを行いながら
AWSなどのパブリッククラウドを用いたインフラの設計/構築も行っている。
最近はDockerやKubernetesなどのコンテナ基盤の構築や
運用自動化の一環としてTerraformやPackerなどのHashicorpツールを扱うことが多く
外部の勉強会やセミナーで登壇するEvangelistの役割も担っている。

・GitHub
https://github.com/nezumisannn

・登壇経歴
https://github.com/nezumisannn/my-profile

・発表資料(SpeakerDeck)
https://speakerdeck.com/nezumisannn

・所有資格
AWS Certified Solutions Architect - Associate
Google Cloud Professional Cloud Architect