확장 가능한 테라폼 코드 관리
- "조직이 커지면서 관리하는 테라폼 코드가 점점 복잡해지고 있어요"
- "무슨 테라폼 모듈을 만들고 어떻게 관리해야할지 감이 안와요"
- "도대체 하나의 테라폼 워크스페이스에 담아야 하는 리소스의 경계는 어디까지일까요?"
- "중복되는 테라폼 코드가 너무 많아지고 있어요"
위 4가지 질문에 대한 인사이트를 얻고자 유튜브 영상에 나온 내용을 글로 정리해보았습니다. 테라폼을 활용한 인프라 리소스의 관한 꿀팁들이 모두 담겨져 있어 꼭 영상을 한 번 보시는 것을 추 천드립니다.
목차
- 테라폼 모듈을 사용하라
- 외부 모듈을 사용하지 마라
- 모듈의 버전을 관리하라
- 두 종류의 테라폼 모듈을 관리하라
- 코드와 데이터를 분리하라
- 하나의 워크스페이스에 모든 것을 담지 마라
- 워크스페이스 간의 의존성을 관리하라
- 모든 것을 테라폼으로 관리하려 하지마라
확장가능한 코드란 ?
- 읽어야 하는 코드의 양이 적다 (가독성)
- 수정해야 하는 코드의 양이 적다 (유지보수)
테라폼 모듈을 사용하라
모듈(Module)
- 여러 테라폼 리소스를 하나의 논리적 그룹으로 관리하기 위해 사용하며 하나의 디렉토리 내에 .tf 혹은 .tf.json 파일로 구성된 콜렉션
루트 모듈 (Root Module)
- 테라폼 CLI가 plan / apply 등과 같이 실제로 수행하게 되는 작업 디렉토리의 테라폼 코드 모음
차일드 모듈 (Child Module)
- 다른 모듈의 테라폼 코드 내에서 호출(참조)하기 위한 목적으로 작성된 테라폼 코드 모음
테라폼 모듈
다른 모듈의 테라폼 코드 내에서 호출(참조)하기 위한 목적으로 작성된 테라폼 코드 모음이며 테라폼 문법에서 module 블록을 통해 호출하게 되는 테라폼 코드
resource "aws_iam_user" "claud" {
name = "claud"
}
resource "aws_iam_user_group_membership" "claud" {
user = aws_iam_user.claud.name
groups = ["sre", "backend"]
}
resource "aws_iam_user_policy_attachment" "claud_1" {
user = aws_iam_user.claud.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
resource "aws_iam_user" "albert" {
name = "albert"
}
...
위와 같이 반복되는 코드를 for_each문을 사용하여 아래와 같이 간단하게 표시할 수 있습니다.
locals {
users = [
{ name = "claud", groups = ["sre", "backend"] },
{ name = "tomas", groups = ["security", "intern"] },
{ name = "jeremy", groups = ["backend"] },
]
}
resource "aws_iam_user" "this" {
for_each = {
for user in local.users:
user.name => user
}
name = each.key
}
resource "aws_iam_user_group_membership" "this" {
for_each = {
for user in local.users:
user.name => user
}
user = each.key
groups = each.value.groups
}
하지만 1:N 관계에서는 상당히 복잡해지므로 모듈을 사용하는 것이 효율적입니다. 모듈을 사용하게 되면 복잡한 객체(리소스 집합)을 단순하게 관리할 수 있게 됩니다.
locals {
users = [
{ name = "claud", groups = ["sre", "backend"], polices = [...] },
{ name = "tomas", groups = ["security", "intern"], polices = [...] },
{ name = "jeremy", groups = ["backend"], polices = [...] },
]
}
module "user" {
source = "tedilabs/account/aws//modules/iam-user"
version = "~> 0.19.0"
for_each = {
for user in local.users :
user.name => user
}
name = each.key
groups = each.value.groups
policies = each.value.policies
}
테라폼 모듈을 사용해야 하는 이유
캡슐화 (Encapsulation)
- 객체지향 프로그램의 핵심 개념 중 하나로 객체의 응집도와 독립성을 높이기 위해 객체의 모듈화를 지향하는 것이며 객체의 모듈화가 잘 이루어지면 모듈 단위의 재사용이 매우 용이해지며 간편하게 유지보 수가 가능하다.
- 관련된 리소스를 하나의 모듈로 묶어서 캡슐화
외부 모듈을 사용하지 마라
테라폼 레지스트리 (Terraform Registry)
- 하시코프에서 공식적으로 운영하는 테라폼 프로바이더 및 모듈저장소, 공개된 테라폼 모듈을 쉽게 찾아 활용할 수 있음
모듈에 심각한 보안 문제점을 찾아 당장 고쳐야 한다면?
- AWS 프로바이더 신규 버전에서 추가된 기능을 적용하고 싶은데 모듈 내에 추상화되어 건들 수가 없다면 ?
- 리소스에서는 지원해주는 기능인데 모듈에서 해당 기능에 대한 인터페이스를 제공해주지 않고 있다면 ?
이러한 문제등이 발생할 수 있기 때문에 외부 모듈을 사용하는 것보다 아래 두 가지 방법이 권고됩니다.
-
DIY (Do It Your Self): 조직 내에서 직접 테라폼 모듈을 설계하고 작성하여 관리
-
Use After Fork: 외부 모듈을 사용하고자 한다면 조직 내부에 복제 후 사용
모듈의 버전을 관리하라
테라폼 모듈을 로컬 파일 경로를 통해 사용한다면 편리하지만 모듈의 버전을 선택할 수는 없습니다.
여러 워크스페이스에서 사용중인 로컬 모듈에 잘못된 수정을 한다면 어떻게 될까요?
- Git, 테라폼 레지스트리, 테라폼 클라우드 등 원격 모듈을 사용한다면 특정 버전의 모듈을 사용하도록 지정할 수 있습니다.
- 각 워크스페이스에서 원격 모듈의 특정 버전을 사용한다면 모듈을 변경하더라도 영향을 받지 않도록 할 수 있습니다.
모듈 블록 내 version은 버전 제약 조건 식을 지원합니다. 이를 잘 이용하면 불필요한 버전 값 업데이트 빈도수를 줄일 수 있습니다.
1.2.0
1.2.0 버전= 1.2.0
1.2.0 버전≥ 1.2.0
1.2.0 버전 이상 중 최신 버전≥ 1.2.0, < 2.0.0
1.2.0 버전 이상 2.0.0 버전 미만 중 최신 버전~> 1.2.0
1.2.x 버전 중 최신 버전~> 1.0
1.x 버전 중 최신 버전