Terraform으로 AWS 등 인프라를 관리하다 보면 하나의 Terrafrom, 조금 더 정확히는 terraform.tfstate
파일에 모두 관리하지 않고 나누어서 관리하게 된다.
As Terraform configurations get larger, it's much more manageable and safer to split one large configuration into many smaller ones linked together with terraform_remote_state data sources.
Terrafrom 문서에서도 위처럼 관리하다 보면 점점 리소스가 많아지게 되는데 하나의 큰 설정으로 관리하지 않고 더 작은 설정으로 나누고 terraform_remote_state
로 연결해서 사용하라고 권하고 있다.
일단 하나의 .tfstate
로 관리하는 리소스가 많아지면 plan
이나 apply
를 할 때도 시간이 점점 오래 걸리게 되므로 자연히 여러 .tfstate
로 나누게 된다. 이렇게 나누는 명확한 기준은 아직 찾지 못했지만 만들다 보면 같이 사용하는 리소스끼리 관리하면서 필요에 따라 나누게 된다. 위의 문서도 초반에 읽었었지만, 그때는 terraform_remote_state
로 연결한다는 의미를 잘 이해하지 못했는데 이 글에서는 이렇게 나눈 .tfstate
를 연결해서 사용하는 방법을 설명한다.
예제를 위한 VPC용 Terrafrom 구성
먼저 VPC를 하나 만들기 위해 vpc
폴더 아래 Terraform을 구성해 보자. 다음과 같은 vpc/terraform.tf
파일을 하나 만들어보자.(파일명을 중요하지 않다.)
terraform {
backend "s3" {
bucket = "kr.ne.outsider.terraform"
key = "vpc/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
lock_table = "TerraformLock"
acl = "bucket-owner-full-control"
}
}
이는 전에 설명한대로 .tfstate
파일을 S3에 저장하는 설정이다. 여기서 kr.ne.outsider.terraform
S3 버킷과 TerraformLock
DynamoDB 테이블은 이미 만들어져 있다고 가정한다. 이 설정을 두고 초기화를 하면 .tfstate
를 저장할 백엔드를 초기화한다.
$ terraform init
Initializing the backend...
Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your environment. If you forget, other
commands will detect it and remind you to do so if necessary.
이제 VPC를 만들어 보자. 다음은 vpc/vpc.tf
파일이다.
resource "aws_vpc" "example" {
cidr_block = "172.10.0.0/20"
tags {
Name = "example"
}
}
resource "aws_subnet" "example_a" {
vpc_id = "${aws_vpc.example.id}"
cidr_block = "172.10.0.0/24"
availability_zone = "ap-northeast-1a"
}
resource "aws_subnet" "example_c" {
vpc_id = "${aws_vpc.example.id}"
cidr_block = "172.10.1.0/24"
availability_zone = "ap-northeast-1c"
}
이를 사용해서 terraform apply
를 하면 AWS에 VPC가 만들어진다.
별도의 tfstate로 EC2 관리
위에서 만든 VPC 안에 EC2 인스턴스를 관리하기 위해 ec2
폴더를 만들어서 관리하기 위해 ec2/terraform.tf
를 만들어서 백엔드를 초기화한다(terraform init
).
terraform {
backend "s3" {
bucket = "kr.ne.outsider.terraform"
key = "ec2/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
lock_table = "TerraformLock"
acl = "bucket-owner-full-control"
}
}
이제 EC2 인스턴스를 띄우는 Terraform 구성을 만들 차례로 다음과 같은 ec2/ec2.tf
파일을 생성한다.
resource "aws_instance" "example-server" {
ami = "ami-785c491f"
instance_type = "t2.micro"
subnet_id = "subnet-6315f62a"
key_name = "key-pair-name"
tags {
Name = "examples"
}
}
여기서 보면 subnet_id
를 직접 하드 코딩해서 subnet-6315f62a
로 지정했다. 이 서브넷은 앞에서 만든 VPC의 서브넷이기는 하지만 한 폴더에서 관리했다면 ${aws_subnet.example_a.id}
처럼 참조해서 사용했겠지만 여기서는 별도의 폴더로 분리했으므로(.tfstate
가 다르므로) 이렇게 참조를 할 수가 없다. AWS 웹 콘솔에 들어가서 서브넷 ID를 찾아서 지정해 줄 수는 있지만, 매번 할 때도 귀찮고 이 아이디를 보고 어떤 서브넷인지 알기가 어려우므로 코드를 읽기도 좋지 않다.
terraform_remote_state 데이터 소스
이 문제는 terraform_remote_state 데이터 소스를 사용하면 해결할 수 있다. terraform_remote_state
는 원격으로 관리하는 tfstate를 데이터소스로 가져와서 참조하는 역할을 한다.
먼저 원격 상태 파일을 다른 설정에서 가져다 쓰려면 내보낼 값을 지정해 주어야 한다. 여기서는 ec2에서 vpc를 가져다 사용할 것이므로 vpc쪽에서 외부에서 참조할 수 있는 값을 지정해 주어야 한다. 다음과 같은 vpc/output.tf
파일을 생성한다.
output "vpc_subnet_a_id" {
value = "${aws_subnet.example_a.id}"
}
이는 aws_subnet.example_a.id
의 값을 vpc_subnet_a_id
라는 이름으로 외부에 노출하는 설정이다. 이 설정을 원격 상태 파일에 적용하려면 terraform refresh
를 실행해야 한다.
$ terraform refresh
Acquiring state lock. This may take a few moments...
aws_vpc.example: Refreshing state... (ID: vpc-f7c49293)
aws_subnet.example_a: Refreshing state... (ID: subnet-6315f62a)
aws_subnet.example_c: Refreshing state... (ID: subnet-720e282a)
Outputs:
vpc_subnet_a_id = subnet-6315f62a
실행하면 마지막에 output으로 노출한 설정값이 표시된 것을 볼 수 있다.
이제 ec2
에서 이 VPC의 원격 상태 파일을 참조하는 설정을 ec2/data.tf
로 만든다.
data "terraform_remote_state" "vpc" {
backend = "s3"
config {
bucket = "kr.ne.outsider.terraform"
key = "vpc/terraform.tfstate"
region = "ap-northeast-1"
encrypt = true
lock_table = "TerraformLock"
acl = "bucket-owner-full-control"
}
}
이는 데이터소스로 위에서 S3에 지정한 tfstate
를 참조한 설정이다. config
에는 tfstate
를 정의한 설정을 같게 지정해서 사용하면 된다. 이 데이터는 원격에 있으므로 ec2
폴더 쪽에서도 데이터 갱신을 한번 해주어야 한다.
$ terraform refresh
data.terraform_remote_state.vpc: Refreshing state...
이제 terraform console
에서 이 값을 확인해 보면 앞에서 하드 코딩한 값이 제대로 출력되는 것을 볼 수 있다.
$ terraform console
> data.terraform_remote_state.vpc.vpc_subnet_a_id
subnet-6315f62a
data.terraform_remote_state.vpc.vpc_subnet_a_id
참조를 사용하면 subnet-6315f62a
를 사용하는 대신 더 읽기 쉬운 이름을 지정할 수 있고 각 tfstate
를 연결해서 사용할 수 있다.
Comments