Intro
오늘은 Terraform 프로젝트 구조를 어떻게 가져가면 좋을지 고민했던 내용들을 공유해보도록 하겠습니다.
(참고로 폴더구조는 정해진 정답은 없으며 팀구성원과 관리 특성에 맞게 구성하시면 됩니다.)
환경별 구성은 어떻게 가져갈까 ?
대부분의 소스코드와 인프라는 DEV(개발), PROD(운영), QA(검증) 이렇게 3가지 환경으로 나누어 구성을 하게 됩니다. (물론 비용을 줄이기위해 DEV나 QA를 생략하기도 합니다)
이 경우 테라폼 프로젝트에서는 DEV, PROD, QA 환경을 어떻게 나누어서 가져가야 할까요? 이것이 첫번째 이슈 였습니다.
크게 3가지 방법이 있겠는데요.
- 방법1 : git repository를 각각 가져간다.
- 방법2 : git repository는 1개로 가져가고 branch를 DEV, PROD, QA로 나눈다
- 방법3: git repository는 1개로 branch도 master로 한개로 가져가고 폴더를 DEV, PROD, QA로 나눈다.
위 3가지 모두 틀린 방법은 아닙니다. 다만 어떤 선택이 관리적인 포인트를 줄 일 수 있을까를 보았을때 방법3이 가장 관리하기 쉽다는 결론을 내렸습니다.
그 이유는 비교적 단순한데요. 방법1은 git repository를 여러개로 나누면 권한이나 설정을 각각 다 관리해줘야하는 번거로움이 있다는 단점이 있었고, 방법2는 branch를 git checkout 명령어로 왔다갔다 해야하는 번거로움이 있다는 단점이 있었습니다. 또한 이 경우 휴먼 에러를 유발하기 쉽죠.
리소스 구조는 어떻게 가져갈까?
예를 들어 아래와 같이 테라폼 프로젝트를 만들고 DEV, PROD, QA 세가지 폴더로 나누었다고 할때 각각의 폴더안에 기본적으로 main.tf 파일을 생성하고 리소스를 생성하게 됩니다.
terraform
└──DEV
└──main.tf
└──PROD
└──main.tf
└──QA
└──main.tf
각 환경별 폴더 경로에 모든 tf파일로 관리하기
Terraform은 terraform apply
명령어를 통해 파일명에 상관없이 현재 위치에 있는 모든 .tf 파일을 읽어 옵니다.
예를들어 아래와같이 terraform에 DEV폴더에서 main 리소스와 elb, ec2를 생성하는 .tf파일을 생성한다고 가정했을때 main.tf
elb.tf
ec2.tf
로 파일을 추가할 수 있고 DEV폴더 경로에서 terraform apply
를 하면 3곳의 파일에 있는 리소스들을 생성하게 됩니다.
terraform
└──DEV
└──main.tf
└──ec2.tf
└──elb.tf
└──PROD
└──main.tf
└──QA
└──main.tf
이렇게 되면 .tfstate 를 한번에 관리할 수 있기 때문에 리소스별로 연계되어 있는 서비스를 생성할때도 좋습니다.
단, .tfstate 를 한번에 관리할 수 있게 되면서 단점이 생길 수도 있습니다. 모든 리소스가 하나의 .tfstate파일에 저장되기 때문에 .tfstate파일이 꼬여버려서 사용할 수 없게 되거나 (그럴일은 없어야 겠지만) .tfstate 파일이 사라져버린다면 이것 또한 엄청난 리스크가 될 수 있습니다.
각 환경별 폴더 경로에서 리소스별로 tf파일로 관리하기
그래서 생각해본것이 아래 구조 처럼 리소스를 폴더별로 나누고 각각 .tfstate를 관리 하면 어떻까? 하는 것이었습니다.
terraform
└──DEV
└──main.tf
└──EC2
└──ec2.tf
└──ELB
└──elb.tf
└──PROD
└──main.tf
└──QA
└──main.tf
자 이렇게 되면 눈에 한번에 들어와서 좋고 .tfstate도 나눠서 관리할 수 있게 되기 때문에 리스크를 줄일 수 있게 되었습니다. 그런데 이 구조의 치명적인 문제점이 하나 있습니다.
.tfstate 파일을 각각 관리 하기 때문에 리소스별로 참고해야하는 정보가 있을 경우 참고 할 수가 없게 됩니다. 예를들어 Lambda 함수를 생성 할때 iam role 설정하는데 LAMBDA라는 폴더와 IAM이라는 폴더가 나뉘어져 있으면 .tfstate 파일이 각각 생성되기 때문에 서로의 리소스를 참조할 수가 없습니다.
terraform
└──DEV
└──main.tf
└──LAMBDA
└──lambda.tf
└──IAM
└──iam_role.tf
즉, 아래와 같이 role
에서 참조 할 수 없게 됩니다.
resource "aws_lambda_function" "example" {
filename = "example.zip"
function_name = "example_lambda"
role = aws_iam_role.example_iam_role.arn
#....omit
}
참고로 .tfstate 파일은 terraform init
을 하면 아래와 같이 각 경로에 .terraform 폴더아래에 생성이 됩니다.
terraform
└──DEV
└──terraform.tfstate
└──main.tf
└──LAMBDA
└──terraform.tfstate
└──lambda.tf
└──IAM
└──terraform.tfstate
└──iam_role.tf
그래서 내린 결론은 문제점 2가지를 해결해보자
- .tfstate파일이 꼬이지 않도록 하자
- .tfstate 파일이 사라지지 않도록 하자
- + 여기에 폴더로 리소스를 나누고 싶다면 module을 만들어서 관리하자
위 두가지를 해결하기 위해서 .tfstate lock기능을 사용하는 방법과 backend 설정을 통해 .tfstate를 별도의 스토리지에서 관리하는 방법을 사용하였습니다.
terraform을 사용하기 위해 이 두가지 방법은 반드시 사용하게 되는데요. 다음시간에는 이 두가지 방법을 어떻게 사용하는지를 다뤄보도록 하겠습니다.
'IT > Terraform' 카테고리의 다른 글
[Terraform] AWS 리소스별로 레이아웃을 나누는 방법 (2) | 2022.03.07 |
---|---|
[Terraform] 테라폼에서 사용할 코드 케이스 정해보기 (1) | 2022.01.22 |
[Terraform] 테라폼 Locking과 Backup (S3, DynamoDB) (0) | 2022.01.19 |
[Terraform] 테라폼 소스 git push가 안돼는 이슈 해결책 (git push 특정 경로 제외시키기) (0) | 2022.01.12 |
[DevOps]테라폼(Terraform)이란? (0) | 2021.05.20 |