.
최근 글로벌 서비스용 데이터 인프라를 새로 구축하는 업무를 맡으면서 네트워크를 다룰 일이 크게 늘었다. 새 AWS 계정에 VPC를 만들고, 기존 계정의 리소스와 통신하도록 연결하고, 다른 리전과 데이터를 주고받는 구성을 잡아야 했다. 크로스 계정, 크로스 리전 통신 등.. 이렇게 본격적으로 다뤄보게 된건 처음이라 AWS 네트워크 인프라를 정리하면서 공부해 보려 한다.
이번글은 VPC 안에서 패킷이 나가고 들어오는 길을 만드는 구성요소에 대해 다뤄본다.
VPC와 서브넷
CIDR (Classless Inter-Domain Routing)
•
VPC와 서브넷의 대역은 모두 CIDR로 표현
•
IP/숫자 형태로 숫자는 32비트 IP 주소에서 앞에서부터 몇 비트를 고정하는지를 뜻하고, 나머지 비트가 그 대역 안에서 쓸 수 있는 주소가 됨
10.0.0.0/16
00001010.00000000 . 00000000.00000000
└──── 고정 16비트 ───┘ └── 자유 16비트 ──┘
(10.0 고정) (0.0 ~ 255.255)
→ 범위: 10.0.0.0 ~ 10.0.255.255
→ 개수: 2^16 = 65,536개
10.0.1.0/24
00001010.00000000.00000001 . 00000000
└────── 고정 24비트 ───────┘ └ 자유 8비트 ┘
(10.0.1 고정) (0 ~ 255)
→ 범위: 10.0.1.0 ~ 10.0.1.255
→ 개수: 2^8 = 256개
Plain Text
복사
IP 개수는 2^(32 - 숫자) 로 고정 비트가 1개 늘면 자유 비트가 1개 줄어 개수가 절반이 된다.
CIDR | 개수 | 예시 범위 | 주로 쓰는 곳 |
/16 | 65,536 | 10.0.0.0 ~ 10.0.255.255 | VPC 전체 |
/19 | 8,192 | 10.0.32.0 ~ 10.0.63.255 | 큰 서브넷 (EKS 등) |
/22 | 1,024 | 10.0.4.0 ~ 10.0.7.255 | 중간 서브넷 |
/24 | 256 | 10.0.1.0 ~ 10.0.1.255 | 일반 서브넷 |
/32 | 1 | 10.0.1.5 | IP 하나 (보안 그룹에서 특정 서버 하나만 허용할 때) |
/0 | 전체 | 0.0.0.0 ~ 255.255.255.255 | 모든 주소 (0.0.0.0/0) |
VPC (Virtual Private Cloud)
VPC는 AWS 안에 만드는 격리된 사설 네트워크로, 만들 때 사용할 IP 대역을 CIDR로 지정한다.
•
VPC 대역은 사설 범위(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) 안에서 직접 고름
•
크기는 /16(최대) ~ /28(최소). 보통 /16으로 크게 잡고 서브넷으로 나눠 씀
VPC 대역을 고를 때 가장 중요한 조건은 다른 네트워크와 겹치지 않는 것이다. 나중에 다른 VPC나 사내망과 연결할 때 대역이 겹치면 라우팅이 불가능하다. 여러 계정과 리전을 엮을 예정이라면 조직 차원에서 대역을 미리 나눠 할당받는 것이 일반적이다.
서브넷 (Subnet)
서브넷은 VPC 대역을 더 작게 나눈 조각이다.
•
서브넷 하나는 가용 영역(AZ) 하나에만 속하며, AZ 장애에 대비하려면 같은 용도의 서브넷을 AZ마다 만듦
•
같은 VPC 안의 서브넷끼리 대역이 겹치면 안 됨
•
서브넷마다 AWS가 5개 IP를 예약 (.0 네트워크, .1 라우터, .2 DNS, .3 예비, 마지막 주소)
•
서브넷 CIDR은 만든 뒤 바꿀 수 없으므로 처음부터 여유 있게 잡고 중간에 빈 대역을 남겨둠
예를 들어 10.0.0.0/16 VPC를 AZ 4개 기준으로 나누면 다음과 같은 모양이 된다.
용도 | 크기 | AZ-a | AZ-b | AZ-c | AZ-d |
public | /22 | 10.0.0.0 | 10.0.4.0 | 10.0.8.0 | 10.0.12.0 |
eks-private | /19 | 10.0.32.0 | 10.0.64.0 | 10.0.96.0 | 10.0.128.0 |
lb-private | /24 | 10.0.160.0 | 10.0.161.0 | 10.0.162.0 | 10.0.163.0 |
db-private | /24 | 10.0.200.0 | 10.0.201.0 | 10.0.202.0 | 10.0.203.0 |
프라이빗 서브넷을 용도별로 나누는 가장 큰 이유는 IP를 소비하는 주체끼리 서로의 IP를 뺏지 않게 하기 위해서다.
•
EKS는 Pod마다 서브넷 IP를 하나씩 사용 → Pod가 늘면 IP가 빠르게 소진
•
ALB는 트래픽이 늘면 내부 노드를 늘리면서 서브넷 IP를 추가로 가져감
•
RDS 장애 조치, Lambda, Glue 같은 서비스도 서브넷에 네트워크 인터페이스를 만들어 IP를 사용
한 서브넷에 섞여 있으면 Pod가 IP를 다 쓴 순간 ALB 확장이나 DB 장애 조치가 실패할 수 있다. 용도별로 나눠두면 소진이 그 서브넷 안에서 끝난다. 덤으로 IP 대역만 보고 어떤 종류의 리소스인지 알 수 있고, 다른 네트워크에서 들어오는 트래픽을 대역 단위로 허용할 때 범위를 좁게 잡을 수 있다.
퍼블릭 서브넷과 프라이빗 서브넷
서브넷 자체에는 퍼블릭/프라이빗 속성이 없고, 서브넷에 연결된 라우팅 테이블로 공개될건지 아닌지가 갈린다.
퍼블릭 서브넷 | 프라이빗 서브넷 | |
기본 경로 | 0.0.0.0/0 → IGW | 0.0.0.0/0 → NAT GW (또는 없음) |
인터넷에서 먼저 들어오는 연결 | 공인 IP가 있는 리소스는 가능 | 불가능 |
주로 두는 것 | NAT GW, 인터넷용 로드밸런서 | 애플리케이션, EKS 노드, DB |
라우팅 테이블
구조
라우팅 테이블은 이 목적지로 가는 패킷은 다음에 어디로 넘길지를 적어둔 표
Destination | Target | 의미 |
10.0.0.0/16 | local | VPC 안이면 직접 전달 (자동 생성, 삭제 불가) |
10.20.0.0/16 | tgw-xxxx | 다른 VPC 대역이면 Transit Gateway로 |
0.0.0.0/0 | nat-xxxx | 나머지 전부는 NAT Gateway로 |
•
Destination = 패킷이 최종적으로 가려는 곳 (CIDR)
•
Target = 그 패킷을 다음에 넘길 곳 (IGW, NAT GW, TGW, Peering, VPC Endpoint 등)
•
출발지는 표에 없음 → 이 테이블이 연결된 서브넷 자체가 출발지
Target에 들어가는 IGW, NAT GW, Transit Gateway는 이어지는 섹션에서 하나씩 다룬다.
라우팅 테이블은 최종 목적지까지의 전체 경로를 알지 못한다. 다음 홉(Target)까지만 정하고 그 다음은 넘겨받은 쪽의 라우팅이 결정한다.
규칙
•
가장 구체적인 경로가 우선 (longest prefix match). 10.20.5.10으로 가는 패킷은 0.0.0.0/0과 10.20.0.0/16에 모두 맞지만 범위가 더 좁은 /16 으로 감
•
서브넷 하나에는 라우팅 테이블이 딱 하나 연결됨. 테이블 하나는 여러 서브넷이 공유 가능
•
지정하지 않은 서브넷에는 VPC의 기본(main) 라우팅 테이블이 연결됨
•
서브넷 외에 IGW 같은 게이트웨이(엣지 연결)와 Transit Gateway 연결에도 라우팅 테이블이 붙음
라우팅은 길만 정함
•
라우팅 테이블은 허용이나 차단을 하지 않음
•
길이 있어도 보안 그룹이 막으면 통신이 안 되고, 보안 그룹이 열려 있어도 길이 없으면 패킷은 갈 곳이 없음
•
그리고 길은 왕복으로 필요함. 요청이 상대에게 도착해도 상대 쪽 라우팅 테이블에 우리 대역으로 돌아오는 경로가 없으면 응답이 돌아오지 못함
인터넷 게이트웨이 (IGW)
IGW는 VPC와 인터넷 사이의 출입문이다.
•
서브넷이 아니라 VPC에 붙는 리소스로 VPC당 하나
•
AWS가 관리하는 구성 요소라 대역폭 제한이 없고 이중화도 자동. 자체 요금도 없음
•
서브넷이 IGW를 쓰려면 그 서브넷의 라우팅 테이블에 0.0.0.0/0 → IGW 경로가 있어야 함
IGW가 실제로 하는 일은 공인 IP와 사설 IP 사이의 1:1 변환이다.
퍼블릭 서브넷의 EC2에 공인 IP가 붙어 있어도 EC2 안에서 네트워크 설정을 보면 사설 IP만 보인다. 공인 IP는 IGW가 들고 있다가 패킷이 지나갈 때 바꿔 쓴다.
나갈 때 EC2 (10.0.1.50) → IGW: 출발지를 3.35.10.99로 변경 → 인터넷
들어올 때 인터넷 → 3.35.10.99 → IGW: 목적지를 10.0.1.50으로 변경 → EC2
Plain Text
복사
그래서 인터넷과 직접 통신하려면 두 가지가 모두 필요함
•
리소스에 공인 IP가 있을 것
•
라우팅이 IGW로 향할 것
NAT 게이트웨이 (Network Address Translation)
역할
NAT 게이트웨이는 프라이빗 서브넷의 리소스가 인터넷으로 나가는 것만 가능하게 해준다. 이미지 pull, 패키지 설치, 외부 API 호출, AWS 서비스 API 호출처럼 서버가 바깥을 불러야 하는 일은 생각보다 많다.
•
퍼블릭 서브넷 안에 만듦 → NAT GW 자신도 인터넷으로 나가려면 IGW를 거쳐야 하기 때문
•
프라이빗 서브넷의 라우팅 테이블에 0.0.0.0/0 → NAT GW를 넣어 연결
•
시간 요금과 처리한 데이터 양(GB) 요금이 함께 붙음
주소 변환과 연결 기록
NAT는 말 그대로 주소를 바꿔 쓰는 장치다. IGW가 1:1 변환이라면 NAT GW는 여러 사설 IP를 공인 IP 하나로 모으는 N:1 변환이다.
패킷에는 프로토콜, 출발지 IP·포트, 목적지 IP·포트가 적혀 있다. NAT GW는 나가는 패킷의 출발지를 자기 IP와 새 포트로 바꾸고 그 대응 관계를 기록해둔다.
나갈 때
출발지 10.0.33.12:51000 → 3.35.10.20:40001 로 변경
기록: 40001번 = 10.0.33.12:51000 의 연결
응답이 올 때
목적지 3.35.10.20:40001 → 기록 조회 → 10.0.33.12:51000 으로 되돌림
기록에 없는 패킷이 올 때
돌려줄 대상을 모름 → 버림
Plain Text
복사
프라이빗 리소스가 인터넷에서 접근되지 않는 이유가 여기 있다. 응답은 내가 시작한 연결의 기록이 있으니 돌아올 수 있지만 바깥에서 먼저 시작한 연결은 기록이 없어 갈 곳이 없다.
TCP 연결이 정상 종료되거나 350초 동안 패킷이 오가지 않으면 연결 기록은 삭제된다. 그래서 응답까지 오래 걸리는 연결(긴 DB 쿼리 등)은 그 사이 기록이 지워져 응답이 버려진다. 클라이언트 쪽 TCP keepalive로 주기적으로 패킷을 흘려 기록을 살려두는 것이 일반적인 대응이다.
EIP(Elastic IP)와 AZ별 배치
퍼블릭 NAT GW는 만들 때 EIP를 반드시 하나 지정해야 한다. EIP는 계정이 소유하는 고정 공인 IP로 반납하기 전까지 바뀌지 않는다.
고정이어야 하는 이유
•
외부 파트너 API나 DB가 허용 IP 목록으로 접근을 제한하는 경우가 많음
•
이때 알려줄 주소가 NAT GW의 EIP
•
IP가 바뀌면 상대방 허용 목록이 깨져 수집이 갑자기 실패
연결이 많은 경우 EIP를 추가로 붙여 동시 연결 수를 늘릴 수도 있음. 참고로 EIP는 NAT GW 외에 EC2, 인터넷용 NLB에도 붙일 수 있고, 사용 중인 공인 IPv4에도 시간당 요금이 붙는다.
NAT GW는 서브넷 안에 만드는 리소스라 AZ 하나에 묶인다. 그래서 몇개를 어디에 둘지 골라야함
NAT GW 1개 공유 | AZ마다 1개 | |
시간 요금 | 1개분 | AZ 수만큼 |
AZ 간 데이터 전송 요금 | 다른 AZ에서 넘어올 때 발생 | 없음 |
장애 영향 | 그 AZ가 죽으면 모든 프라이빗 서브넷의 인터넷이 끊김 | 해당 AZ만 영향 |
외부에 알려줄 EIP | 1개 | AZ 수만큼 |
비용을 아껴야 하는 개발 환경은 1개, 운영 환경은 AZ마다 두는 경우가 많다. AZ마다 둔다면 프라이빗 라우팅 테이블도 AZ별로 나눠서 각자 같은 AZ의 NAT GW를 가리키게 한다.
Transit Gateway와 VPC Peering
다른 VPC와 사설 IP로 통신하는 방법은 크게 두 가지다.
VPC Peering
두 VPC를 1:1로 직접 잇는 연결이다.
•
다른 계정, 다른 리전의 VPC와도 연결 가능
•
전이(transitive) 라우팅이 안 됨. A-B, B-C가 연결돼 있어도 A에서 B를 거쳐 C로 갈 수 없음
•
상대 VPC의 IGW나 NAT GW를 빌려 쓸 수도 없음
•
VPC가 늘어나면 연결 수가 n(n-1)/2로 증가 (10개면 45개)
•
연결 자체 요금은 없고 데이터 전송 요금만 발생
Transit Gateway (TGW)
가운데에 라우터 하나를 두고 각 VPC가 그 라우터에 연결하는 허브 앤 스포크 구조. 이름은 게이트웨이지만 IGW나 NAT GW처럼 주소를 바꾸는 장치가 아니라 중앙 라우터라고 생각하면 됨.
VPC A
│
VPC D ── TGW ── VPC B
│
사내망 (VPN)
Plain Text
복사
•
각 VPC는 TGW에 연결(attachment) 하나만 만들면 됨
•
VPC뿐 아니라 Site-to-Site VPN, Direct Connect 같은 사내망 연결도 붙일 수 있음
•
TGW는 리전 단위 리소스. 다른 계정에는 RAM(Resource Access Manager)으로 공유해서 그 계정의 VPC를 붙임
•
다른 리전과는 TGW끼리 피어링으로 연결 (리전 간 피어링은 정적 경로만 지원)
•
연결당 시간 요금과 처리한 데이터 양 요금이 붙음
TGW에는 자체 라우팅 테이블이 있다. 어떤 연결이 어떤 TGW 라우팅 테이블을 쓸지 지정할 수 있어서, 같은 TGW에 붙어 있어도 개발 VPC와 운영 VPC가 서로 통신하지 못하게 나누는 식의 제어를 한 곳에서 할 수 있다.
비교
VPC Peering | Transit Gateway | |
구조 | 1:1 직접 연결 | 허브 앤 스포크 |
전이 라우팅 | 불가 | 가능 (TGW 라우팅 테이블로 제어) |
사내망(VPN) 연결 | 불가 | 가능 |
VPC가 많을 때 | 연결 수가 급증 | 연결 1개씩 추가 |
크로스 리전 | 피어링 자체로 가능 | TGW 간 피어링 |
비용 | 데이터 전송료만 | 연결 시간 요금 + GB당 요금 |
두 VPC만 잇고 끝이라면 Peering이 싸고 단순하지만 여러 VPC와 사내망, 여러 계정을 엮어야 하면 TGW를 사용
TGW와 Peering을 거치는 통신에는 주소 변환이 없다. VPC 밖으로 나간다고 항상 공인 IP로 바뀌는 것이 아니라, 주소 변환은 인터넷으로 나갈 때만 일어난다.
목적지 | 경로 | 출발지 IP |
인터넷 | NAT GW → IGW | NAT GW의 EIP |
다른 VPC, 사내망 | Transit Gateway, Peering | 사설 IP 그대로 |
이 차이 때문에 외부 SaaS에는 NAT GW의 공인 IP를 알려주고, 다른 계정의 VPC에는 우리 VPC의 사설 대역을 알려준다.
보안 그룹
보안 그룹(SG)은 리소스 단위로 거는 방화벽이다.
•
정확히는 EC2가 아니라 네트워크 인터페이스(ENI)에 붙음. ENI는 VPC 안의 가상 랜카드로, EC2뿐 아니라 RDS, 로드밸런서, Lambda도 서브넷에 ENI를 만들어 IP를 가짐.
•
허용 규칙만 있고 거부 규칙은 없음
•
ENI 하나에 여러 SG를 붙일 수 있고 규칙은 합집합으로 적용됨
SG는 연결 상태를 기억하여 보낸 요청의 응답은 인바운드 규칙이 없어도 들어온다. 그래서 연결을 시작하는 방향만 열면 된다.
•
요청을 보내는 쪽: 아웃바운드 허용 (기본값이 전체 허용)
•
요청을 받는 쪽: 인바운드 허용
CIDR와 SG 참조
보안그룹 규칙의 상대방 부분에 CIDR나 다른 SG ID 적을 수 있다. 보통 같은 VPC 안에서는 SG 참조가 권장된다.
CIDR로 허용 | SG 참조로 허용 | |
범위 | 그 대역의 모든 IP | 그 SG가 붙은 리소스만 |
IP가 바뀌면 | 규칙 수정이 필요할 수 있음 | 영향 없음 |
다른 VPC에서 오는 요청을 허용할 때는 연결 방식에 따라 다름
•
VPC Peering, 같은 리전의 TGW: 상대 VPC의 SG를 참조 가능
•
크로스 리전, 사내망: 상대 SG 정보를 알 수 없어 CIDR로 지정
패킷 경로 따라가보기 예시
지금까지 본 구성 요소를 묶어서 요청 하나가 실제로 어떤 길로 오가는지 따라가 보자
계정 A (우리) | 계정 B (상대) | |
VPC 대역 | 10.10.0.0/16 (A 대역) | 10.20.0.0/16 (B 대역) |
리소스 | 프라이빗 서브넷의 애플리케이션 서버 | 프라이빗 서브넷의 MSK 브로커 |
연결 | 두 VPC 모두 같은 리전의 TGW에 연결됨 |
다른 계정의 VPC로 가는 경로
계정 A의 EC2 → 계정 B의 MSK 브로커(같은 리전, TGW 경유)
계정 B의 MSK 브로커 → 계정 A의 EC2 (응답, TGW 경유)
같은 EC2 서버가 인터넷으로 나갈 때
•
비교를 위해 같은 서버가 외부 SaaS API를 호출하는 경우를 보면 경로가 완전히 다름
계정 A의 EC2 → 외부 Saas API(인터넷으로 나갈때)
다른 리전으로 갈 때
계정 A의 EC2 (서울 리전) → 계정 B의 MSK 브로커(버지니아 리전)
•
상대 VPC가 다른 리전에 있으면 TGW가 리전마다 하나씩 있고 둘을 TGW 피어링으로 이어줌
•
응답도 같은 단계를 거꾸로 밟으므로 양쪽 TGW 라우팅 테이블에 서로의 대역이 모두 있어야 함
정리
•
서브넷은 VPC 대역을 AZ 단위로 나눈 조각이고 퍼블릭/프라이빗은 라우팅 테이블이 정함. IP를 소비하는 주체별로 나눠두면 서로의 IP를 뺏지 않음
•
라우팅 테이블은 목적지별 다음 홉만 정하고 가장 구체적인 경로가 우선. 길은 왕복으로 필요
•
IGW는 VPC에 붙는 인터넷 출입문으로 공인 IP와 사설 IP를 1:1로 변환
•
NAT GW는 퍼블릭 서브넷에 두고 EIP를 붙여 프라이빗 리소스의 아웃바운드를 N:1로 변환. 연결 기록이 있는 응답만 돌려보내고 350초 유휴 시 기록이 사라짐
•
Peering은 1:1 직접 연결, TGW는 전이 라우팅과 사내망 연결이 되는 중앙 라우터
•
보안 그룹은 ENI에 붙는 stateful 방화벽이라 연결을 시작하는 방향만 열면 됨
•
사설망끼리의 통신은 NAT GW와 IGW를 거치지 않고 인터넷으로 나갈 때만 주소가 바뀜
다음 글에서는 로드밸런서와 DNS를 이어서 다뤄보겠다.





