[Terraform] Refer to resource information described in different tfstate

table of contents
My name is Teraoka and I am an infrastructure engineer
useful
, there's a
This time, I'd like to introduce it.
What is terraform_remote_state?
you want to reference information about resources described in different tfstate files
This data source is useful when
Terraform
when a deployment is executed using terraform apply
has a file called tfstate, which records resource information created
When building infrastructure with Terraform,
if you have multiple environments (such as a jump host, production, and development),
so that `terraform apply` doesn't affect other environments
it's essential to separate the tfstate for each environment
When you split tfstate,
information about resources created in the jump environment
you may want to reference
This is where "terraform_remote_state" comes in handy.
■When to use it
Below is an example using AWS
If we assume that SSH connections to the server are made via a jump server,
how would we create security groups and rules using Terraform?
First, I think we would create a VPC and security groups + rules for the jump 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 configuration, the tfstate is stored in S3 under the name bastion.tfstate,
but this is fine as it only involves adding a VPC and security group plus an allow rule for specific IP addresses.
So, what about the settings on the "receiving side" from the jump host?
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 jump server,
you need to allow access from the jump server's security group, so
you need to specify the ID of the jump server's security group using `source_security_group_id`.
However, because the backend description separates the jump server and tfstate,
it is not possible to reference the security group ID in this state.
■How to use it
Now that we've determined that it's not possible, I'd like to make it accessible.
First, we need to add the output setting to the bastion.tf file.
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}" }
When referencing values from different tfstates,
you need to output the values you want to reference beforehand.
In this case, we want to reference the ID of the bastion security group, so
we 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" } }
We use the `terraform_remote_state` data source
to read the `tfstate` for the jump host stored in S3.
The value can be referenced by the name specified in `output`, so
the value to specify for `source_security_group_id`
will be `data.terraform_remote_state.bastion.security_group_id`.
Summary
`terraform_remote_state` is used quite often, so it's worth remembering.
This means you can split the `tfstate` file without any problems!
1
