[Terraform] Refer to resource information described in different tfstate

My name is Teraoka and I am an infrastructure engineer.

One useful
data source when writing Terraform HCL is terraform_remote_state.
I would like to introduce it this time.

What is terraform_remote_state?


This is a convenient data source for when you want to refer to information about resources described in different tfstates

Terraform

has a file called tfstate that records the resource information created when deploying with terraform apply

When building infrastructure with Terraform,
if you have multiple environments (springboard/production/development, etc.),

it is a rule of thumb to separate tfstate for each environment so that terraform apply does not affect other environments

If you separate tfstate,

you may want to refer to
the information of resources created in the bastion In such cases, "terraform_remote_state" is useful.

■When to use it

Below is an example using AWS

If you are going to connect to a server via SSH via a bastion server,
how would you create a security group and rules using Terraform?
First, you would create a VPC and security group + rules for the bastion server.

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" }

In the backend settings, tfstate is stored in S3 under the name bastion.tfstate,
but this is fine because it only adds a VPC and security group + an allow rule from a specific IP.
So, what about the settings on the "connected side" from the bastion?

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 = "${What should I specify???}" }

If you want to allow SSH connections from a bastion server,
you need to allow access from the bastion's security group, so
you need to specify the ID of the bastion's security group in source_security_group_id.

However, since the backend description separates the bastion server and tfstate,
you will not be able to reference the security group ID in this state.

■How to use it

Now that I understand that this is not possible, I would like to be able to refer to it.
First, you need to add an output setting to bastion.tf.

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" } ## Add output "security_group_id" { value = "${aws_security_group.bastion.id}" }

If you want to reference a value from a different tfstate,
you must first output the value you want to reference.
In this case, we want to reference the ID of the bastion security group, so
we will output aws_security_group.bastion.id.

In this state, you can reference the value from production.tf using 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}" } ## Add data "terraform_remote_state" "bastion" { backend = "s3" config { bucket = "terraform-tfstate" key = "terraform-blog/bastion.tfstate" region = "ap-northeast-1" } }

Use the terraform_remote_state data source
to read the tfstate for the bastion stored in S3.
The value can be referenced by the name specified in output, so
the value specified for source_security_group_id
is data.terraform_remote_state.bastion.security_group_id.

■Summary

Since terraform_remote_state is used quite often, it's worth remembering.
Now there's no problem with separating tfstate!

If you found this article helpful , please give it a like!
1
Loading...
1 vote, average: 1.00 / 11
11,330
X facebook Hatena Bookmark pocket

The person who wrote this article

About the author

Yuki Teraoka

Joined Beyond in 2016 and is currently in his 6th year as an Infrastructure Engineer
MSP, where he troubleshoots failures while
also designing and building infrastructure using public clouds such as AWS.
Recently, I
have been working with Hashicorp tools such as Terraform and Packer as part of building container infrastructure such as Docker and Kubernetes and automating operations, and I
also play the role of an evangelist who speaks at external study groups and seminars.

・GitHub
https://github.com/nezumisannn

・Presentation history
https://github.com/nezumisannn/my-profile

・Presentation materials (SpeakerDeck)
https://speakerdeck.com/nezumisannn

・Certification:
AWS Certified Solutions Architect - Associate
Google Cloud Professional Cloud Architect