이미 잘 사용하고 있는 분들이 많겠지만, 개인적으로 한번쯤 정리해보고 싶었던 부분이라 글을 작성하게 되었다.
리소스를 생성하든, 함수를 생성하든 나에게 이름을 짓는 순간은 가장 심혈을 기울이게 되는 순간 중 하나이다. 미래의 나를 위한 가독성, 협업을 위해서, 유지 보수, 오류 감소, 문서로서의 역할 등등... 네이밍 컨벤션이 중요한 이유는 넘친다. IaC 도입의 긍정적인 효과—공동작업과 재사용성, 기술의 자산화 등—을 온전히 누리기 위해서는 네이밍 컨벤션에 대한 협의가 반드시 이루어져야한다고 생각한다.
어떻게 하면 '좋은' 인프라를 위한 네이밍을 할 수 있을지 Best Practice를 기반으로 정리하였다. 주관적인 견해와 수집한 정보들을 바탕으로 작성한 것이므로 다음 내용이 정답이 아님을 미리 밝힌다.
-
(dash)대신 _
(underscore) 사용AWS 콘솔에서 리소스를 생성할 때는 주로 -를 사용한 케밥케이스(e.g. prd-crm-web-ec2)를 사용하여 리소스를 생성했는데 ...
테라폼 공식 문서에 있는 예제들도 주로 스네이크 케이스를 사용하고 있다. 리소스 이름, 데이터 소스 이름, 변수 이름, 출력 등 모든 곳에서 _를 사용하는 것이 좋다고 한다.
-는 테라폼에서 뺄셈이나 요소 제거등에 사용될 수 있기 때문이다. -를 연산자로 사용하는 경우 자원 이름에도 -를 사용했을 때 오류가 발생할 잠재적인 위험이 있기 때문에 자원 이름에 - 사용을 지양한다고.
그리고 이건 개인적으로 느낀 장점인데, _를 쓰면 해당 어구를 더블클릭했을 때 전체 선택이 된다. private_nat 는 더블클릭하면 한번에 선택되지만 private-nat는 그렇지 않다. _를 쓰면 여러 블럭을 한번에 수정할때 편해진다.
✅ Do
resource "aws_eks_cluster" "my_cluster" {}
❌ Do Not
resource "aws_eks_cluster" "my-cluster" {}
가독성 향상을 위해 소문자를 사용한다.
리소스 유형(type)을 리소스 이름(name)에 반복하는 것을 지양한다.
중복을 방지하고 이름을 간결하게 유지해서 리소스의 용도를 명확하게 할 수 있다.
테라폼은 다음과 같은 구조로 작성되는데,
<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
<IDENTIFIER> = <EXPRESSION>
}
블록 타입이 resource라고 가정했을 때 다음과 같은 구조를 갖게 된다.
resource "<PROVIDER>_<TYPE>" "<NAME>" {
# Block contents
argument_1 = "value"
argument_2 = "value"
# Nested Block
nested_block {
# Block contents
}
}
여기서 "" 부분의 이 리소스 명칭이다. AWS의 라우팅 테이블을 생성한다면 "aws_route_table"과 같이 표기한다. 이때 뒤에 오는 ""에 aws, route_table과 반복을 피하는 것을 권고한다. 대신 용도를 구분할 수 있도록 public, private 등의 명칭만 표기하는 것을 추천한다.
✅ Do
resource "aws_route_table" "public" {}
resource "aws_vpc_endpoint" "apigateway" {}
❌ Do Not
resource "aws_route_table" "public_route_table" {}
resource "aws_vpc_endpoint" "apigateway_endpoint" {}
단, 여러 값을 포함하게 되는 경우—variable 블록에서 list(...)
or map(...)
를 사용하거나 output 블록에서 반환되는 값이 복수형인 경우 등—에는 복수형으로 표기한다.
✅ Do
output "rds_instance_endpoint" {
description = "An instance endpoint"
value = aws_rds_cluster_instance.this.endpoint
}
output "rds_cluster_instance_endpoints" {
description = "A list of all cluster instance endpoints"
value = aws_rds_cluster_instance.this.*.endpoint
}
❌ Do Not
output "rds_instance_endpoints" {
description = "An instance endpoint"
value = aws_rds_cluster_instance.this.endpoint
}
단, depends_on
이나 lifecycle
인자는 tag 보다 뒤에 명시한다.
✅ Do
resource "aws_nat_gateway" "this" {
count = 2
allocation_id = "..."
subnet_id = "..."
tags = {
Name = "..."
}
depends_on = [aws_internet_gateway.this]
lifecycle {
create_before_destroy = true
}
}
❌ Do Not
resource "aws_nat_gateway" "this" {
count = 2
tags = "..."
depends_on = [aws_internet_gateway.this]
lifecycle {
create_before_destroy = true
}
allocation_id = "..."
subnet_id = "..."
}
e.g. description , type, default, validation
{name}
은 provider 접두사가 없는 리소스 또는 데이터 소스 이름{type}
은 리소스 소스의 유형{attribute}
은 출력에서 반환되는 속성
✅ Do
output "security_group_id" {
description = "The ID of the security group"
value = "")
}
❌ Do Not
output "this_security_group_id" {
description = "The ID of the security group"
value = element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), [""]), 0)
}
참고) 네이밍 외에 스타일 컨벤션과 관련된 부분은 다음 명령어로 해결할 수 있다.
terraform fmt
막상 이렇게 정리해보니까 내가 지키지 않고 있는 규칙들도 있어서 (특히 리소스 타입과 이름을 중복하는 것) 차근차근 수정해나가야겠다. 이렇게 사용하다가 불편함이 생기면 또 업데이트 해보겠습니다 !
Terraformer로 기존에 사용 중인 AWS 인프라를 Terraform 코드로 가져오기 (0) | 2023.05.12 |
---|
댓글 영역