[Terraform] 모듈 주의 사항
카테고리: terraform
태그: terraform
🎯모듈 주의 사항
모듈을 만들 때는 다음과 같은 사항을 주의해야 합니다.
- 파일 경로
- 인라인 블록
파일 경로
기본적으로 테라폼은 현재 작업 중인 디렉터리를 기준으로 경로를 해석합니다. terraform apply를 실행하는 디렉터리와 동일한 디렉터리에 있는 테라폼 구성 파일에서 file 함수를 사용하는 것, 즉 루트 모듈에서 file 함수를 사용하는 것은 가능하지만, 별도의 폴더에 정의된 모듈에서 file 함수를 사용할 수는 없습니다.
이 문제를 해결하기 위해 path.<TYPE> 형태의 경로 참조 표현식을 사용할 수 있습니다. 테라폼은 다음 유형의 경로 참조를 지원합니다.
path.module: 표현식이 정의된 모듈의 파일 시스템 경로를 반환합니다.path.root: 루트 모듈의 파일 시스템 경로를 반환합니다.path.cwd: 현재 작업 중인 디렉터리의 파일 시스템 경로를 반환합니다. 테라폼을 사용할 때 이것은path.root와 동일하지만 테라폼의 일부 기능은 루트 모듈 디렉터리 이외의 디렉터리에서 작동하므로 경로가 달라집니다.
사용자 데이터 스크립트의 경우 모듈 자체에 상대 경로가 필요하므로 template_file 데이터 소스에서 path.module을 사용해야 합니다.
data "template_file" "user_data" {
template = file("$(path.module)/user-data.sh")
vars = {
server_port = var.server_port
db_address = data.terraform_remote_state.db.outputs.address
db_port = data.terraform_remote_state.db.outputs.port
}
}
인라인 블록
일부 테라폼 리소스의 구성은 인라인 블록 또는 별도의 리소스로 정의할 수 있습니다. 모듈을 만들 때는 항상 별도의 리소스를 사용하는 것이 좋습니다.
예를 들어, aws_security_group 리소스를 사용하면 다음의 모듈에서 볼 수 있듯 인라인 블록을 통해 수신(ingress) 및 송신(egress) 규칙을 정의할 수 있습니다.
resource "aws_security_group" "alb" {
name = "${var.cluster_name}-alb"
ingress {
from_port = local.http_port
to_port = local.http_port
protocol = local.tcp.protocol
cidr_blocks = local.all_ips
}
egress {
from_port = local.any_port
to_port = local.any_port
protocol = local.any_protocol
cidr_blocks = local.all_ips
}
}
별도의 aws_security_group_rule 리소스를 사용하여 정확히 동일한 수신 및 송신 규칙을 정의하도록 이 모듈을 변경해야 합니다. 모듈의 두 보안 그룹 모두에 이 작업을 수행합니다.
resource "aws_security_group" "alb" {
name = "${var.cluster_name}-alb"
}
resource "aws_security_group_rule" "allow_http_inbound" {
type = "ingress"
security_group_id = aws_security_group.alb.id
from_port = local.http_port
to_port = local.http_port
protocol = local.tcp_protocol
cidr_blocks = local.all_ips
}
resource "aws_security_group_rule" "allow_all_outbound" {
type = "egress"
security_group_id = aws_security_group.alb.id
from_port = local.any_port
to_port = local.any_port
protocol = local.any_protocol
cidr_blocks = local.all_ips
}
인라인 블록 대신 별도의 리소스를 사용해야 하는 이유
인라인 블록과 별도의 리소스를 혼합하여 사용하려고 하면 라우팅 규칙이 충돌하여 덮어쓰는 오류가 발생합니다. 따라서 둘 중 하나만 사용해야 합니다. 이 제한 사항으로 인해 모듈을 작성할 때 항상 인라인 블록 대신 별도의 리소스를 사용해야합니다. 그렇지 않으면 모듈의 유연성이 떨어집니다.
예를 들어 모듈 내의 모든 수신 및 송신 규칙이 별도의 aws_security_group_rule 리소스로 정의된 경우 사용자가 모듈 외부에서 사용자 정의 규칙을 추가할 수 있도록 모듈을 유연하게 만들 수 있습니다. 이를 위해 aws_security_group의 ID를 출력 변수로 내보냅니다.
output "alb_security_group_id" {
value = aws_security_group.alb.id
description = "The ID of the Security Group attached to the load balancer"
}
이제 스테이징 환경에서 테스트를 위해 포트를 추가로 노출해야 한다고 가정하겠습니다. aws_security_group_rule 리소스를 루트 모듈에 추가하기만 하면 됩니다.
resource "aws_security_group_rule" "allow_testing_inbound" {
type = "ingress"
security_group_id = module.webserver_cluster.alb_security_group.id
from_port = 12345
to_port = 12345
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
aws_security_group과 같이 인라인 블록과 별도의 리소스를 모두 사용할 수 있는 리소스에는 다음의 것들이 있습니다. 이러한 유형의 리소스를 사용할 때는 항상 별도의 리소스를 정의하시기 바랍니다.
- aws_security_group과 aws_security_group_rule
- aws_route_table과 aws_route
- aws_network_acl과 aws_network_acl_rule
👍 개인 공부 기록용 블로그입니다. 오류나 조언이 있으시면 언제든지 댓글 혹은 메일로 남겨주시면 감사하겠습니다! 😄
댓글남기기