본문으로 이동
Kim Jongwon
← 전체 프로젝트

AWS 네트워크 | 개인 PoC, 과정 자료로 자율 진행 | 2026.03.25 - 2026.04.06

AWS Multi-VPC 3-Tier Infrastructure with Terraform

VPC 3개로 사용자, 관리자, 서비스 경로를 나눈 AWS 인프라

VPC 3개로 사용자, 관리자, 서비스 경로를 나누고, EC2 Nginx → EKS 504를 원인 두 가지로 나눠 복구했습니다.

네트워크

VPC 3개

MAIN, MGMT, SERVICE

접근 경로

4개

정적, 동적, 관리자, 서비스

배포 후 점검

8단계

도메인부터 DB 연결까지

트래픽 경계

VPC 3개와 접근 경로 4개

Terraform으로 인프라를 만들고, 배포 뒤에는 8단계 점검 순서대로 연결을 확인했습니다.

MAIN

10.0.0.0/16

서비스 본체, 공개/앱/DB 서브넷

MGMT

10.1.0.0/16

관리자 VPN 접속

SERVICE

10.2.0.0/16

외부 비공개 ECS 서비스

정적

CloudFront → S3

동적

CloudFront → ALB(WAF) → Nginx → EKS → Aurora

관리자

OpenVPN → MGMT–MAIN 피어링

서비스

ECS → NAT → ECR

Terraform으로 관리한 범위

VPC, 서브넷, 라우팅피어링, 보안 그룹CloudFront, WAF, ALBEKS, Aurora, OpenVPN, ECSACM, Route53, S3, ECR
VPC 3개와 4개 접근 경로 요약

문제 해결 과정

EC2 Nginx → EKS 요청이 504로 실패했습니다

보안 그룹을 고친 뒤에도 실패가 남아, 원인이 하나가 아니라 두 개라는 것을 확인했습니다.

  1. Nginx → EKS 요청 504

    Terraform으로 인프라는 모두 만들어졌지만, EC2 Nginx에서 EKS로 보낸 요청이 504로 실패했습니다.

  2. 워커 노드에 보안 그룹 미적용

    EKS 설정에 넣은 보안 그룹은 컨트롤 플레인에만 붙고 워커 노드에는 적용되지 않았습니다. 노드 템플릿(launch template)에 노드 보안 그룹을 연결했습니다.

  3. 클러스터 내부 주소를 밖에서 호출

    보안 그룹을 고친 뒤에도 실패했습니다. Nginx가 클러스터 안에서만 통하는 ClusterIP 주소로 요청하고 있었습니다.

  4. NodePort로 연결 복구

    PoC에서는 워커 노드의 NodePort로 연결을 복구했습니다. 노드 주소에 의존하는 방식이라, 운영에서는 Ingress, ALB로 바꿔야 한다는 점을 함께 기록했습니다.

원인 분석 문서 보기 ↗

설계 배경

경로를 VPC 단위로 나눈 이유

사용자 요청, 관리자 접속, DB, 별도 서비스가 같은 네트워크 경로를 쓰면 한 곳의 문제가 전체로 번집니다. 용도별로 VPC와 경로를 나눌 필요가 있었습니다.

직접 한 일

  • MAIN/MGMT/SERVICE VPC로 사용자, 관리자, 서비스 경로를 나누는 구조를 설계했습니다.
  • Terraform 루트 모듈에서 AWS 자원 사이의 연결 관계를 관리했습니다.
  • 배포 후 도메인, 인증서, 클러스터, DB 연결까지 8단계 점검 항목을 만들어 순서대로 확인했습니다.

결과

  • VPC 3개로 사용자, 관리자, 서비스 경로 분리
  • EC2 Nginx → EKS 504를 원인 두 가지로 나눠 복구
  • 배포 후 8단계 점검 항목 정리

네트워크 구조

VPC 3개로 나눈 접근 경로

세 VPC가 맡는 역할과 요청이 지나가는 경로입니다.

  • MAIN VPC에 공개, 애플리케이션, DB 서브넷을 두고 ALB, EC2 Nginx, EKS, Aurora를 계층별로 배치했습니다. 테스트 앱으로 WordPress를 EKS에 올렸습니다.
  • CloudFront가 정적 요청은 S3로, 동적 요청은 WAF → ALB → EC2 Nginx → EKS → Aurora로 보냅니다.
  • 관리자는 MGMT VPC의 OpenVPN으로 접속해 VPC 피어링으로 MAIN에 들어가고, SERVICE VPC는 외부에 노출되지 않는 ECS 서비스를 둡니다.
  • Terraform 루트 모듈에서 VPC, 피어링, 보안 그룹, ALB, EKS, Aurora, OpenVPN, ECS, CloudFront를 순서대로 연결했습니다.
  • ALB에 WAF를 붙이고, S3 공개 차단과 CloudFront OAC, ECR 푸시 시 이미지 스캔, EC2 IMDSv2 강제, EBS와 Aurora 저장소 암호화를 Terraform 코드에 넣었습니다.
AWS VPCTerraformCloudFront/WAF/ALBEKSAurora MySQL

배포 후 점검 8단계

  1. 1 Route 53: 도메인 네임서버 위임 확인
  2. 2 ACM: 인증서 발급, 도메인 검증 완료
  3. 3 kubeconfig: kubectl get nodes 응답 확인
  4. 4 CloudFront HTTPS: EC2 Nginx 경유 WordPress 접속 확인
  5. 5 ECR: docker push 이미지 등록 확인
  6. 6 ALB: 대상 그룹 healthy, HTTP 200 응답
  7. 7 OpenVPN: MGMT에서 MAIN으로 피어링 접속 확인
  8. 8 Aurora: EKS Pod에서 DB 연결 확인

전체 구조

아키텍처

MAIN/MGMT/SERVICE VPC와 정적, 동적, 관리자 경로를 나눈 전체 다이어그램입니다.

MAIN VPC, MGMT VPC, SERVICE VPC와 CloudFront, WAF, ALB, EKS, Aurora, OpenVPN 경로를 보여주는 AWS 아키텍처 다이어그램
전체 아키텍처: MAIN/MGMT/SERVICE VPC와 트래픽 경로 원본 보기

핵심 코드

루트 모듈에서 VPC를 연결하는 코드

각 VPC 모듈의 출력을 피어링, ALB, CloudFront 모듈에 넘겨 경로를 연결합니다. 일부 인수는 생략했습니다.

main.tf: VPC 모듈 연결 (일부 인수 생략)

main.tf

module "vpc_main" {
  source      = "./modules/vpc-main"
}

module "vpc_mgmt" {
  source      = "./modules/vpc-mgmt"
}

module "vpc_service" {
  source      = "./modules/vpc-service"
}

module "peering" {
  source      = "./modules/peering"
  main_vpc_id = module.vpc_main.vpc_id
  mgmt_vpc_id = module.vpc_mgmt.vpc_id
}

module "alb" {
  source  = "./modules/alb"
  waf_arn = module.waf.waf_arn
}

module "eks" {
  source = "./modules/eks"
}

module "aurora" {
  source = "./modules/aurora"
}

module "cloudfront" {
  source       = "./modules/cloudfront"
  alb_dns_name = module.alb.alb_dns_name
}

직접 확인하기

코드와 자료

아래 링크에서 코드, 설계 문서, 실행 기록을 직접 확인할 수 있습니다.

맡은 범위

  • 개인 PoC: VPC, 라우팅, 보안 그룹, 4개 접근 경로의 Terraform 코드와 배포 후 점검 8단계를 직접 작성했습니다.

범위와 한계: 개인 PoC 당시의 구축, 복구 기록입니다. 지금 같은 환경을 다시 띄워 운영하고 있지는 않습니다.