Published on

pulumi awsx ec2 vpc 구성 가이드

Authors
  • avatar
    Name
    Indo Yoon
    Twitter

Pulumi에서 AWSX와 EC2를 함께 쓸 때 가장 단순한 조합은 AWSX의 VPC 헬퍼로 네트워크를 만들고, 인스턴스는 AWS 프로바이더의 EC2 리소스로 선언하는 방식이에요. AWSX는 서브넷과 라우팅, NAT 게이트웨이처럼 반복되는 네트워크 작업을 줄여 주지만 인스턴스의 세부 설정까지 대신해 주지는 않아요. 그래서 네트워크는 AWSX에 맡기고 인스턴스는 명시적으로 관리하는 쪽이 운영에서 예측하기 쉬워요.

한눈에 보기

구성 요소의 역할을 먼저 나눠 두면 코드가 훨씬 단순해져요.

  • AWSX는 별도의 프로바이더가 아니라 Pulumi AWS 프로바이더 위에 얹힌 상위 라이브러리예요. AWS 리소스를 더 적은 코드로 선언하도록 돕는 도구예요.
  • awsx.ec2.Vpc는 VPC, 퍼블릭·프라이빗 서브넷, 인터넷 게이트웨이, NAT 게이트웨이, 라우팅 테이블을 한 번에 만들어요.
  • EC2 인스턴스는 aws.ec2.Instance, 시작 템플릿, 오토 스케일링 그룹 같은 AWS 프로바이더 리소스로 선언해요.
  • 두 세계를 잇는 값은 서브넷 ID와 보안 그룹 ID예요. AWSX가 만든 결과를 그대로 참조하면 연결이 끝나요.
  • 검증은 pulumi preview로 교체 여부를 먼저 확인하고, 문제가 없을 때 pulumi up을 실행하는 순서가 안전해요.

정리하면 "네트워크는 AWSX, 컴퓨팅은 AWS 프로바이더"라는 역할 분담이에요. 이 구도만 잡으면 나머지는 참조를 이어 붙이는 작업이 돼요.

AWSX와 AWS 프로바이더 비교

같은 VPC를 만들어도 두 방식의 코드량과 유연성이 달라요. 아래 표는 어느 쪽을 골라야 할지 판단할 때 쓰는 기준이에요.

항목AWSX의 VPC 헬퍼AWS 프로바이더 직접 선언
추상화 수준자주 쓰는 구성을 묶은 상위 추상화리소스 단위의 낮은 추상화
선언 범위VPC·서브넷·라우팅·인터넷 게이트웨이·NAT 게이트웨이를 한 번에필요한 리소스를 각각 선언
서브넷 설계가용 영역 수와 서브넷 스펙으로 결정CIDR과 가용 영역을 직접 지정
NAT 게이트웨이전략 옵션으로 개수와 배치를 결정직접 만들고 라우팅 테이블에 연결
코드 길이짧고 읽기 쉬움길지만 의도가 그대로 드러남
유연성기본값을 벗어나는 튜닝은 제한적거의 모든 옵션을 제어
어울리는 경우표준적인 계층형 네트워크를 빠르게 만들 때기존 네트워크와 정확히 맞춰야 할 때

AWSX가 만든 VPC는 아래 속성으로 다른 리소스에 연결해요. 모두 Output으로 감싸여 있다는 점이 중요해요.

속성의미
vpcId생성된 VPC의 식별자
publicSubnetIds퍼블릭 서브넷 식별자 목록
privateSubnetIds프라이빗 서브넷 식별자 목록
natGateways생성된 NAT 게이트웨이 목록

Output은 값이 아니라 값의 약속이에요. 인스턴스에 넘길 때는 apply로 감싸서 꺼내거나, 같은 스택 안의 다른 리소스가 Output을 그대로 받도록 넘겨야 해요.

단계별 구성 방법

순서를 지키는 것이 중요해요. 네트워크, 보안 그룹, 인스턴스 순으로 쌓으면 참조가 한 방향으로만 흘러요.

프로젝트와 스택 준비

pulumi new aws-typescript처럼 언어별 템플릿으로 프로젝트를 만들고, pulumi config set aws:region으로 리전을 고정해요. 스택은 개발과 운영을 나눠 두는 편이 좋아요. 같은 코드로 dev와 prod 스택을 따로 만들면 VPC CIDR이나 NAT 전략만 스택 설정으로 바꿀 수 있어요.

상태 파일은 Pulumi Cloud나 S3 같은 원격 백엔드에 두세요. 로컬 상태는 팀 단위 운영에서 가장 자주 사고가 나는 지점이에요.

AWSX로 VPC 선언

awsx.ec2.Vpc에 cidrBlock, numberOfAvailabilityZones, natGateways 전략, tags를 넘겨요. 서브넷 구성을 직접 제어하고 싶다면 subnetSpecs에 퍼블릭과 프라이빗 타입을 나눠 지정하고, 각 서브넷의 크기는 cidrMask로 정해요.

여기서 정한 가용 영역 수가 이후 서브넷 목록의 길이를 결정해요. 나중에 가용 영역 수를 바꾸면 서브넷이 다시 만들어질 수 있으니 처음 설계할 때 여유를 두는 편이 좋아요.

보안 그룹 정의

보안 그룹은 AWS 프로바이더의 aws.ec2.SecurityGroup으로 선언하고 vpcId에 vpc.vpcId를 넘겨요. 인바운드 규칙은 CIDR 대역보다 다른 보안 그룹 ID를 참조하는 방식이 관리하기 쉬워요. 애플리케이션 보안 그룹과 로드밸런서 보안 그룹을 분리해 두면 규칙이 서로 얽히지 않아요.

SSH를 전체 대역에 열어 두는 구성은 피하고, 세션 관리자나 배스천 경유 접속을 검토하세요.

EC2 인스턴스 연결

인스턴스는 aws.ec2.Instance로 선언해요. ami는 aws.ec2.getAmi로 조회하거나 고정 식별자를 쓰고, instanceType, subnetId, vpcSecurityGroupIds를 지정해요. subnetId에는 vpc.publicSubnetIds나 vpc.privateSubnetIds에서 고른 값을 apply로 꺼내 넘겨요.

프라이빗 서브넷에 두는 인스턴스는 NAT 게이트웨이나 VPC 엔드포인트가 없으면 외부 통신이 막혀요. 패키지 설치와 이미지 풀링 경로를 먼저 확인한 뒤 서브넷을 골라야 해요.

스택 출력과 검증

vpcId, 서브넷 목록, 인스턴스 식별자를 스택 출력으로 내보내면 다른 스택이나 운영 도구에서 참조할 수 있어요. 배포 전에는 pulumi preview로 교체 대상과 삭제 대상을 확인하세요. 인스턴스가 교체로 표시된다면 AMI 조회 결과가 바뀌었거나 서브넷이 재생성된 경우일 수 있어요.

상황별 선택 기준

  • 이미 운영 중인 VPC가 있다면 새로 만들지 마세요. aws.ec2.getVpc와 aws.ec2.getSubnets 같은 데이터 소스로 기존 값을 읽고 인스턴스에 넘기는 편이 안전해요.
  • 네트워크를 새로 설계해도 된다면 AWSX의 VPC 헬퍼가 빠릅니다. 표준적인 퍼블릭·프라이빗 분리가 자동으로 만들어져요.
  • 개발 환경에서는 기본 VPC를 쓰는 선택지도 있어요. awsx.ec2.DefaultVpc로 계정의 기본 VPC를 참조하면 네트워크 코드를 거의 쓰지 않아도 돼요.
  • 비용을 아끼고 싶다면 NAT 게이트웨이 전략을 먼저 조정하세요. NAT 게이트웨이는 생성한 수만큼 과금되므로 전략 선택이 곧 비용 구조예요.
  • 가용성이 중요하다면 가용 영역마다 서브넷과 NAT를 두는 쪽이 좋아요. 대신 리소스 수와 관리 포인트가 늘어나요.
  • 오토 스케일링이 필요하다면 인스턴스를 직접 선언하기보다 시작 템플릿과 오토 스케일링 그룹으로 옮기는 편이 확장에 유리해요.

운영할 때 주의할 점

NAT 게이트웨이 전략을 바꾸면 서브넷과 라우팅 테이블이 다시 만들어질 수 있어요. 운영 중인 스택에서는 전략 변경을 곧 네트워크 교체로 보고, 사전에 pulumi preview로 영향을 확인해야 해요.

AMI 조회 방식도 조심해야 해요. 필터로 최신 이미지를 가져오면 이미지가 갱신될 때마다 인스턴스가 교체 대상으로 잡혀요. 자동 교체를 원하지 않는다면 이미지 식별자를 고정하고, 교체가 필요할 때만 값을 갱신하세요.

리소스 보호 옵션도 활용하세요. 상태 저장소나 데이터베이스처럼 지워지면 곤란한 리소스에는 protect를 걸어 두면 실수로 인한 삭제를 막을 수 있어요. 반대로 개발 스택은 pulumi destroy로 정리할 계획을 미리 세워 두면 비용이 새지 않아요.

보안 그룹 규칙은 코드 리뷰 대상으로 삼으세요. 전체 대역 인바운드, 지나치게 넓은 이그레스, 관리 포트 노출은 배포 한 번으로 그대로 운영에 반영돼요. 태그 전략도 함께 정해 두면 비용 추적과 소유자 파악이 쉬워져요.

스택 분리도 운영의 기본이에요. 개발과 운영이 같은 스택을 공유하면 한쪽 변경이 다른 쪽에 그대로 전파돼요. 리전과 계정이 다르면 스택도 반드시 나눠야 해요.

자주 묻는 질문

AWSX만으로 EC2 인스턴스까지 만들 수 있나요?

AWSX 문서에서 EC2 항목은 VPC와 서브넷 같은 네트워크 구성 중심으로 설명돼요. 인스턴스는 AWS 프로바이더의 aws.ec2.Instance나 시작 템플릿으로 선언하는 예시가 일반적이에요. AWSX가 만든 서브넷 ID와 보안 그룹 ID를 넘겨 주면 같은 스택 안에서 자연스럽게 연결돼요.

기존에 쓰던 VPC를 그대로 두고 인스턴스만 추가하려면 어떻게 하나요?

aws.ec2.getVpc와 aws.ec2.getSubnets로 기존 네트워크 값을 읽고, 인스턴스의 subnetId에 그대로 넘겨요. 이때 AWSX로 VPC를 새로 만들면 안 되고, 기존 리소스를 Pulumi가 관리해야 한다면 pulumi import로 상태에 편입할지 먼저 결정해야 해요.

NAT 게이트웨이 전략은 무엇을 기준으로 고르나요?

프라이빗 서브넷에서 외부로 나갈 일이 없다면 NAT를 두지 않는 전략이 가장 단순해요. 외부 통신이 필요하지만 비용을 줄이고 싶다면 하나만 두는 전략, 가용 영역별 독립성을 원한다면 가용 영역마다 두는 전략을 골라요. 전략을 바꾸면 라우팅이 다시 만들어질 수 있으니 운영 중 변경은 신중해야 해요.

프라이빗 서브넷의 인스턴스에는 어떻게 접속하나요?

세션 관리자를 통한 접속, 배스천 호스트 경유, VPN이나 전용선을 통한 접근이 일반적이에요. 퍼블릭 서브넷에 관리 포트를 열어 두는 방식은 지양하고, 접속 경로도 코드로 선언해 두면 재현이 쉬워요.

서브넷 CIDR이 겹치면 어떻게 되나요?

VPC 대역과 서브넷 대역이 겹치거나 서브넷끼리 겹치면 생성 단계에서 실패해요. subnetSpecs로 직접 지정할 때는 가용 영역별로 대역을 겹치지 않게 나누고, 기존 네트워크와 연결할 계획이 있다면 대역 중복 여부를 먼저 확인하세요.

출처

Pulumi로 만든 네트워크를 실제 배포 흐름에 붙이는 방법은 Pulumi 스택과 CI/CD 배포 파이프라인 구성하기 글에서 이어서 다뤄요. 스택 분리, 미리보기 승인 단계, 상태 백엔드 설정처럼 운영에서 자주 부딪히는 지점을 함께 정리해 두었어요.