Search

Terraform: 인프라 코드로 관리하기

현회사에서는 거의 대부분의 서비스를 테라폼으로 관리 생성한다. 이번에 컨슈머를 개발해 ECS로 배포해야 하는 상황이 왔는데, 테라폼을 써본적이 없어서 공부할겸 정리해본다.

Terraform 이란

인프라를 코드로 관리하는 도구(IaC: Infrastructure as Code)
클라우드나 온프레미스 환경에서 인프라를 생성/변경/삭제 가능
.tf 파일에 원하는 상태를 작성하면, Terraform이 현재 상태와 비교해 필요한 변경을 수행

왜 사용할까?

서버 하나 배포하려면 매번-
1.
EC2 생성
2.
보안 그룹 설정
3.
로드밸런서 + Target Group 연결
4.
Route53에서 레코드 생성
5.
IAM 권한 설정
6.
CodeDeploy/Autoscaling 구성
→ dev, stage, prod 별로 매번 반복
위 수동 과정을 자동화
장점
환경별 코드 재사용 (변수만 바꿔 배포 가능)
Git으로 변경 이력 관리 가능
코드 리뷰 가능

기본 명령어

init - 테라폼 작업을 위해 모듈/플러그인 설치 등 초기화
plan - 리소스 변경 정보 미리 확인
apply - 실제 리소스 반영
destroy - 리소스 제거
AWS 인프라 정보를 가져와야 하기 때문에 AWS 리소스에 접근 권한을 가진 유저 Profile 필요

주요 블록

terraform { ... }
프로젝트 메타데이터
required_providers(플러그인 버전 고정)
backend(상태 저장소) 등 프로젝트 메타 설정
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } backend "s3" { bucket = "tf-state-bucket" key = "ecs/app/terraform.tfstate" region = "ap-northeast-2" } }
HCL
복사
provider "aws" { ... }
AWS 리전/자격 등 프로바이더 설정
provider "aws" { region = "ap-northeast-2" profile = "my-aws-profile" }
HCL
복사
variable "..." { ... }
외부에서 주입할 값 정의
변수의 타입, 기본값, 설명 등 명시
variable "app_name" { description = "애플리케이션 이름" type = string }
Bash
복사
locals { ... }
여러 변수/값을 조합하거나 변환해 중간 계산 결과를 저장
외부 주입 변수나 내부 로직을 합쳐 재활용 가능한 값을 만드는 용도
variable "app_name" { description = "앱 기본 이름" } locals { env = terraform.workspace app_name = "${var.app_name}-${terraform.workspace}" ecs_service_name = "${local.app_name}-service" } resource "aws_ecs_service" "this" { name = local.ecs_service_name }
Bash
복사
.tfvars에서 app_name = "worker" 주입
local.app_name = "worker-dev" (env가 dev 일때)
local.ecs_service_name = "worker-dev-service"
data "..." "..." { ... }
이미 존재하는 외부 리소스(또는 다른 Terraform state)에 접근해 정보 조회
data "aws_iam_role" "task_role" { name = var.ecs_task_role }
HCL
복사
여기서 var.ecs_task_role.tfvars나 CLI로 주입된 값
AWS에 이미 존재하는 IAM Role을 찾아서 ARN 등 속성값을 가져올 수 있음.
resource "..." "..." { ... }
실제 리소스 생성/변경/삭제
예시 (ECS Task Definition):
resource "aws_ecs_task_definition" "task_definition" { family = var.ecs_service_name container_definitions = file("container_definitions.json") cpu = var.cpu memory = var.memory requires_compatibilities = ["EC2"] network_mode = "awsvpc" }
HCL
복사
family: 태스크 정의 그룹 이름
network_mode: 네트워크 모드 (awsvpc = ENI 직접 부여)
requires_compatibilities: Fargate / EC2 모드 지정
container_definitions: 실제 컨테이너 실행 스펙(JSON 파일로)
module "..." { ... }
재사용 가능한 테라폼 코드 조각 가져와 실행
module "<모듈_이름>" { source = "<모듈_위치>" # 모듈이 요구하는 변수들 var_name_1 = "값" var_name_2 = local.가공값 }
Bash
복사
source
모듈 코드의 위치를 지정
로컬 경로(../modules/ecs_module), Git repo, Terraform Registry URL 모두 가능
변수 전달
모듈 내부의 variable 정의에 값을 주입
var., local., data. 등 현재 프로젝트의 값을 전달할 수 있음
출력값 사용
모듈 내부에서 output "..."로 정의한 값은 module.<모듈_이름>.<output_이름> 으로 참조 가능
다른 서비스에서 동일한 ECS 설정 재활용 가능

디렉토리 & 파일구조 (예시)

ECS의 경우 공통 리소스(infra/)와 애플리케이션 리소스(app/)를 분리하여 관리
<서비스명>/ ├─ infra/ │ ├─ backend.tf # state 저장소(S3) & 락 설정 │ ├─ terraform.tf # required_providers, 버전 등 │ ├─ variables.tf │ ├─ terraform.tfvars │ └─ main.tf # 인프라 모듈 호출(출력: ECR URL, 시크릿 맵 등) └─ app/ ├─ backend.tf ├─ terraform.tf ├─ variables.tf # env별로 달라지는 값(리소스 스펙, 네트워크 등) ├─ env-dev.tfvars ├─ env-prod.tfvars └─ main.tf # 원격 state(ECR/시크릿) + ECS 모듈 호출
Plain Text
복사
인프라(infra) 모듈
공통 리소스 생성:
ECR: 이미지 저장소
Secrets Manager: 환경별 시크릿 관리
IAM User/Role: 배포 계정 권한
output으로 ECR URL, 환경별 시크릿 이름 맵 등을 노출 → 나중에 app/에서 원격 state(data "terraform_remote_state") 로 이 값을 받아 사용가능
앱(app) 모듈
ECS Task Definition: 컨테이너 이미지, 포트, 환경변수, 시크릿
ECS Service: 롤링 업데이트, 로드밸런서 연결, 오토스케일링
환경별 차이는 env-*.tfvars로 CPU/메모리/서브넷/이미지 태그 구분
.tvars 파일
Terraform 변수(variable "...")에 실제 값을 주입하는 파일
환경별(dev, prod 등)로 다른 값이 필요할 때 주로 사용
예시:
# env-dev.tfvars app_name = "worker" ecs_task_role = "ecsTaskRoleDev" cpu = 256 memory = 512 desired_task_number = 1
Bash
복사
위와 같은 파일이 있을때 아래와 같이 적용하면 dev 환경변수 값으로 실행
terraform apply -var-file=env-dev.tfvars
Bash
복사
Terraform 실행 흐름 요약
변수 주입.tfvars 파일에서 환경별 변수 값 로드
값 가공locals 블록에서 변수 조합·변환으로 재사용 가능한 형태로 준비
외부 정보 조회data 블록으로 기존 리소스나 원격 state에서 참조값 확보
리소스 생성·변경resource 블록으로 신규 인프라 생성 및 상태 반영