성장 스택

PR에서 인프라 관리하기(Atlantis) – Terraform (2)

류큐큐 2025. 9. 8. 00:24

1편에서 말했듯, 이제 나는 인프라를 “PR 기반”으로 관리하고 있다.
그런데 여기서 자연스럽게 드는 질문이 있다.

“PR에서 terraform plan/apply는 누가 실행하지?”

 

당연하게 들리지만, 이 부분을 제대로 풀어내지 않으면 IaC는 금방 다시 ‘로컬 실행 지옥’으로 돌아간다.

기존 방식의 문제: 로컬 실행은 답이 아니다

초기에 나도 이렇게 했다:

terraform plan
terraform apply

 

 

그런데 팀이라면? 아니, 나 혼자인 경우에도 문제는 터진다:

  • 각자 다른 Terraform 버전 → 미묘한 차이로 에러 발생
  • 로컬 환경 의존성 → OS, CLI 설정, Provider 버전 차이
  • State 파일 충돌 → “Lock 걸려있는데요?”
  • 누가 apply 했는지 추적 어려움 → CloudTrail 뒤적이는 데 10분
  • 배포가 GitHub Actions/PR 흐름과 따로 놀음

결론: PR 기반 인프라를 하고 싶다면 plan/apply도 PR에서 자동화되어야 한다.
여기서 Atlantis가 등장한다.


핵심 해결책: Atlantis

Atlantis는 PR 이벤트를 기반으로 Terraform을 자동 실행해주는 전용 서버다.
구조는 단순하다.

GitHub PR → Atlantis → Terraform → AWS

 

애매한 CI/CD 트릭 없이, Terraform 전용으로 설계된 워크플로우.

Atlantis가 어떻게 동작하나?

흐름은 이렇게 간단하다.

  • PR 생성
    • Atlantis가 자동으로 terraform plan 실행
    • 결과를 PR 코멘트로 남김
  • 리뷰어가 확인
    • plan 정상인지, 보안/비용 문제 없는지 체크
  • PR 코멘트로 명령
    • Atlantis가 자동으로 terraform apply 실행
    • 결과도 PR 코멘트로 돌아옴
  • Merge
    • 모든 변경이 Git 기록에 남고, 재현 가능

Atlantis 인프라 구조 (내가 구축한 구성)

GitHub (PR Webhook)
      ↓
Application Load Balancer (HTTPS, /events)
      ↓
ECS Fargate (Atlantis 서버)
      ↓
Terraform 실행
      ↓
AWS 리소스 변경

 

구성 요소 요약

  • GitHub App – PR 이벤트를 Atlantis로 전달
  • ALB + HTTPS – Webhook 트래픽 처리
  • ECS Fargate – 서버리스로 Atlantis 컨테이너 실행
  • EFS – Terraform plugin cache + lock 관리
  • Secrets Manager – GitHub App 인증 정보 저장

한 번 구축해두면 거의 손댈 일 없다.

 

PR에 남는 실제 코멘트 예시

1. PR 생성 → 자동 Plan

**Atlantis Plan Results**

```diff
# aws_security_group_rule.api_https will be created
+ resource "aws_security_group_rule" "api_https" {
    + cidr_blocks = ["10.0.0.0/16"]
    + description = "Allow HTTPS from private subnet"
    + from_port   = 443
    + to_port     = 443
    + protocol    = "tcp"
    + type        = "ingress"
  }

Plan: 1 to add, 0 to change, 0 to destroy.
```

**Validation**
- 보안 스캔: OK
- 비용 변화: +$0
- 정책 검증: OK

👉 적용하려면 코멘트: `atlantis apply`

 

 

2. Apply 실행 후

**Atlantis Apply Results**

```
aws_security_group_rule.api_https: Creating...
aws_security_group_rule.api_https: Creation complete after 2s
```

**Apply 완료!**

 

3. 오류 발생 시

Error: Invalid Security Group ID "sg-invalid"

❌ plan 실패. 변경 후 다시 push하세요.
 

이 코멘트 형식만으로도 리뷰·검증·적용·히스토리가 모두 해결된다.


Atlantis 설치 요약 

너무 복잡해서 사람들이 기피하지만, 한번 만들어두면 끝이다.

Phase 1 — Terraform으로 Atlantis 인프라 배포

ECS, ALB, SG, EFS, CloudWatch Logs 자동 생성.

Phase 2 — GitHub App 설정 

Webhook URL, Permission 설정.

Phase 3 — Secrets Manager 

AppID / InstallationID / Private key 저장.

Phase 4 — ECS 재배포 + 테스트 

테스트 PR 하나 올려서 plan/apply 확인.

총 12분이면 끝난다.


🛡️ 보안 포인트 (중요한 것만)

GitHub App 권한

  • 필수: Contents / PR / Issues
  • 절대 금지: Admin, Actions, Secrets

Secrets는 무조건 Secrets Manager

HCL에 토큰 박는 건 진짜 위험하다.

네트워크

  • ECS Task → Private Subnet
  • ALB만 Public
  • Security Group으로 ALB → ECS만 허용

IAM 최소 권한

EC2/ELB/ECS 관련 Describe/Create 정도만 허용.
Action = "*" 는 즉시 아웃.


트러블슈팅(내가 실제 겪은 것들)

1. Atlantis가 PR에 코멘트를 안 남긴다

  • GitHub App 설치 누락
  • Webhook URL 오타
  • ALB → ECS SG 미설정
  • Private key 잘못 저장

2. plan은 되는데 apply는 안 된다

  • apply_requirements 충족 안 됨 (approve 필요)
  • Branch protection rule 충돌
  • GitHub App Write 권한 부족

3. state lock 충돌

  • 강제 unlock 필요할 때 있음 (주의)

4. apply에서 AWS 에러 발생

  • IAM 권한 부족
  • 리소스 이름 중복
  • depends_on 필요
  • Rate Limit

거의 여기서 다 걸린다.

 

실전 예시 – RDS 인스턴스 타입 변경

- instance_class = "db.t3.medium"
+ instance_class = "db.r6g.large"

 

PR 생성 → Atlantis plan 출력:

  • RDS 변경 1건
  • 비용: +$41.45 (57% 증가)
  • 다운타임 예상: 1~2분

리뷰어 코멘트:

  • “다운타임 있으니 새벽에 합시다.”
  • “롤백 계획은 어떻게?”
  • “Multi-AZ니까 문제 없어요.”
Modify complete after 2m15s

 

다음 글에서 다룰 내용

  • 내가 사용하는 모듈 패턴
  • tfsec / checkov / OPA / Infracost로 이루어진 PR 자동 검증 체계