1. ホーム
  2. 記事一覧
  3. 【Terraformハンズオン】terraform remote stateの使い方を理解しよう

2025.03.12

【Terraformハンズオン】terraform remote stateの使い方を理解しよう

    IaCツールのTerraformを使用してプロジェクトを進めている場合、作成したリソースの情報を参照して別のリソースを作成したい場面に遭遇します。このような時に役立つのがterraform_remote_stateデータソースです。

    この記事ではterraform_remote_stateの基本と、使い方について解説します。

    Terraformを使用したインフラ構築をより効率的に進めるために必要な知識となるため、一緒に学んでいきましょう。

    terraform_remote_stateとは

    terraform_remote_stateは、Terraformのデータソースの1つであり、リモートバックエンドに保存されたtfstateファイルのoutput値を取得するために使用します。

    このデータソースは、異なるTerraformプロジェクト間や環境でリソース情報を共有する際に便利な機能です。

    The terraform_remote_state Data Source

    terraform_remote_stateのメリット

    このセクションでは、terraform_remote_stateを使用することでどのようなメリットがあるのかを解説します。

    プロジェクト間でtfstateの情報を共有できる

    terraform_remote_stateを利用すると、Terraformの異なるプロジェクト間でtfstateの情報を共有し、リソースのIDや設定情報を参照できます。

    VPC、EC2、RDSなどのリソースを、それぞれ異なるTerraformプロジェクトとして構築、管理する場合でも、各リソースのIDや設定情報をプロジェクト間で共有し参照することが可能です。

    こうすることで、別のプロジェクトで作成したVPCのIDを参照し、その中にEC2を構築するといったことができます。

    検証環境、本番環境などでstate情報を参照できる

    検証環境や本番環境など、環境ごとにtfstateファイルを分けていた場合にも有効です。

    検証環境で構築するリソースを本番環境のVPCに関連付ける場合でも、本番環境のVPC情報を検証環境から参照できるため、環境ごとの設定を適切に共有できます。

    tfstateに関しては、以下の記事で解説しています。

    tfstateファイルについての基礎 コアやプロバイダ、tfstateファイルの役割について理解しよう

    terraform_remote_stateデータソースを使用する条件

    terraform_remote_stateのデータソースを使用するには、次のような条件があります。

    outputブロックで値を出力していること

    terraform_remote_stateデータソースで値を使用するには、作成したリソースの情報をoutputブロックで出力する必要があります。

    outputブロックで値を出力していない場合はエラーになるため注意が必要です。

    Output Values

    root moduleでoutputした値のみ取得できる

    公式ドキュメントにも記載されていますが、terraform_remote_stateはroot moduleのoutputに定義された値のみ取得できます。

    moduleを使用してリソースを作成している場合、module内のoutputs.tfで値を定義するだけではterraform_remote_stateから参照することはできません。

    必ずroot moduleのoutputs.tfで、module内のoutputを出力するように設定する必要があります。

    以下に、moduleを使用したディレクトリ構成の例を示します。

    /terraform-project
    │── main.tf                # moduleの呼び出し側(root module)
    │── outputs.tf             # ここでoutputを定義する必要がある
    │── variables.tf
    │── terraform.tfstate
    └── modules
        ├── app
        │   ├── main.tf        # module appのリソース定義
        │   ├── outputs.tf     # modele app内でのみ有効
        │   ├── variables.tf
        │   └── terraform.tfstate
        ├── db
        │   ├── main.tf        # module dbのリソース定義
        │   ├── outputs.tf     # module db内でのみ有効
        │   ├── variables.tf
        │   └── terraform.tfstate
        └── network
            ├── main.tf        # module networkのリソース定義
            ├── outputs.tf     # module network内でのみ有効
            ├── variables.tf
            └── terraform.tfstate
    

    この構成では、modules/app/outputs.tfにoutputを定義しても、その値はterraform_remote_stateから直接参照することはできません。

    そのため、root moduleのoutputs.tfに、module内のoutputを渡してあげるためのoutputを定義する必要があります。

    moduleについては、次の記事で解説しています。

    【Terraformハンズオン】Terraformでモジュールを作成してみよう

    terraform_remote_stateハンズオン

    ここからは、VPCとEC2の構築するハンズオンを行います。

    本番環境と検証環境でディレクトリを分け、本番環境で作成したVPCの値を検証環境で使用します。

    前提条件

    このセクションでは、リモートバックエンドを使用してリソースを構築します。

    リモートバックエンドを使った環境構築は、以下の記事で解説していますので参照ください。

    Terraform AWS S3リモートバックエンドを用いてtfstateを管理してみよう

    ディレクトリ構成

    ディレクトリ構成は次のように構成しています。

    ├── prod # 本番環境
    │   ├── versions.tf
    │   ├── outputs.tf # vpcとsubnetの値を出力
    │   └── vpc.tf # vpcとsubnetを作成
    └── stg # 検証環境
        ├── versions.tf
        └── ec2.tf # prodのremote_stateを取得する

    prodディレクトリ

    使用するTerraformのバージョン、AWSプロバイダの情報などはversions.tfを作成します。

    # versions.tf
    
    terraform {
      required_version = ">= 1.0.0"
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 5.67.0"
        }
      }
      backend "s3" {
        bucket = "test-terraform" # 任意の作成済みバケットを指定
        key    = "prod/vpc/terraform.tfstate" # バケット内のパスを指定 remote_stateで使用するパスになる
        region = "ap-northeast-1"
      }
    }
    
    provider "aws" {
      region = "ap-northeast-1"
    }

    vpc.tfを作成し、VPCとsubnetを作成します。

    # vpc.tf
    
    # ------------------------------
    # VPC
    # ------------------------------
    
    resource "aws_vpc" "common_vpc" {
      cidr_block           = "10.0.0.0/16"
      enable_dns_support   = true
      enable_dns_hostnames = true
    }
    
    resource "aws_subnet" "public_a" {
      vpc_id                  = aws_vpc.common_vpc.id
      cidr_block              = "10.0.1.0/24"
      availability_zone       = "ap-northeast-1a"
      map_public_ip_on_launch = true
    }

    outputs.tfを作成し、VPC、subnetの情報を出力します。

    # outputs.tf
    
    output "common_vpc_id" {
      value = aws_vpc.common_vpc.id
    }
    
    output "public_subnet_a_id" {
      value = aws_subnet.public_a.id
    }

    この状態でinitを実行し、プロジェクトを初期化します。

    terraform init

    init完了後、applyを実行します。

    terraform apply

    apply後にoutputs.tfに記載した値がターミナルに出力されます。

    Outputs:
    
    common_vpc_id = "vpc-068411b1c46d248c4"
    public_subnet_a_id = "subnet-022ef95ad62531d5d"

    詳しくは後述しますが、remote_stateではoutputで出力されたkeyを指定して、値を使用します。

    stgディレクトリ

    続いてstgディレクトリもprodと同様、versions.tfを作成します。

    # versions.tf
    
    terraform {
      required_version = ">= 1.0.0"
      required_providers {
        aws = {
          source  = "hashicorp/aws"
          version = "~> 5.67.0"
        }
      }
      backend "s3" {
        bucket = "test-terraform"
        key    = "stg/ec2/terraform.tfstate"
        region = "ap-northeast-1"
      }
    }
    
    provider "aws" {
      region = "ap-northeast-1"
    }
    

    ec2.tfでは、terraform_remote_stateブロックを作成してprodのtfstateの情報を取得します。

    # ec2.tf
    
    # ------------------------------
    # AMI
    # ------------------------------
    
    data "aws_ami" "amazonlinux2_latest" {
      owners      = ["amazon"]
      most_recent = true
      filter {
        name = "name"
        values = ["amzn2-ami-hvm-2.0.*.0-x86_64-gp2"]
      }
    }
    
    # ------------------------------
    # reference remote state
    # ------------------------------
    
    data "terraform_remote_state" "common" {
      backend = "s3"
      config = {
        bucket = "test-terraform"
        key    = "prod/vpc/terraform.tfstate" # ここでprodのbackend設定を読み込む
        region = "ap-northeast-1"
      }
    }
    
    # ------------------------------
    # EC2
    # ------------------------------
    
    resource "aws_instance" "ec2" {
      ami           = data.aws_ami.amazonlinux2_latest.id
      instance_type = "t2.micro"
      
      # ここでremote_stateの値を使用する
      subnet_id     = data.terraform_remote_state.common.outputs.public_subnet_a_id

    terraform_remote_stateの基本的な構文は次のようになります。

    # 構文
    data.terraform_remote_state.<NAME>.outputs.<RESOURCE NAME>
    
    # 具体例 prod環境のpublic_subnet_a_idの値を取得
    subnet_id     = data.terraform_remote_state.common.outputs.public_subnet_a_id

    <NAME>data "terraform_remote_state" "common"commonの部分を指定し、<RESOURCE NAME>はoutputで出力したkeyを指定します。

    ファイルの作成が完了したら、prodの時と同様、initを実行し、applyします。

    terraform init
    
    terraform apply

    まとめ

    この記事では、Terraformのデータソースの1つであるterraform_remote_stateについて解説しました。

    terraform_remote_stateを利用することで、Terraformの異なるプロジェクト間でtfstateの情報を共有し、リソースのIDや設定情報を参照できます。

    大きいプロジェクトなどではerraform_remote_stateを使用して構築する場面もあるため、この記事を参考に手を動かしていただき、terraform_remote_stateの理解を深めていただければと思います。

    参考記事

    The terraform_remote_state Data Source

    tfstateファイルについての基礎 コアやプロバイダ、tfstateファイルの役割について理解しよう

    Output Values

    【Terraformハンズオン】Terraformでモジュールを作成してみよう

    Terraform AWS S3リモートバックエンドを用いてtfstateを管理してみよう

    Backend block configuration overview

    【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

    IT未経験者必見 USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

    プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。

    「フリーランスエンジニア」

    近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。

    「成功する人とそうでない人の違いは何か?」

    私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。

    比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。

    多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、

    note記事3000いいね超えの殿堂記事 LINE登録で記事を見る

    エンベーダー編集部

    エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。

    RareTECH 無料体験授業開催中! オンラインにて実施中! Top10%のエンジニアになる秘訣を伝授します! RareTECH講師への質疑応答可

    関連記事