VPC
VPC(Virtual Private Cloud)는 AWS 계정 전용의 격리된 가상 네트워크입니다. 온프레미스 데이터센터와 유사하게 IP 주소 범위, 서브넷, 라우팅 테이블, 네트워크 게이트웨이를 완전히 제어할 수 있습니다.
VPC의 주요 특징
- 완전한 네트워크 제어: IP 범위, 서브넷, 라우팅 테이블 설정
- 보안: Security Groups와 Network ACLs로 트래픽 제어
- 격리: 다른 AWS 계정과 논리적으로 분리
- 연결성: 인터넷, VPN, Direct Connect를 통한 연결
- 리전별 리소스: 각 리전마다 독립적인 VPC 생성
VPC가 필요한 이유
┌─────────────────────────────────────────────┐
│ 전통적인 데이터센터 │
│ - 물리적 서버 │
│ - 네트워크 장비 (라우터, 스위치) │
│ - 방화벽 │
│ - 높은 초기 비용 │
└─────────────────────────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ AWS VPC (가상 데이터센터) │
│ - EC2 인스턴스 │
│ - 소프트웨어 정의 네트워크 │
│ - Security Groups & NACLs │
│ - 사용한 만큼만 지불 │
└─────────────────────────────────────────────┘
📚 네트워킹 기초 지식
IP 주소와 CIDR 표기법
IPv4 기초
IPv4 주소: 32비트 (4바이트)
형식: xxx.xxx.xxx.xxx (각 옥텟은 0-255)
예: 192.168.1.10
Binary: 11000000.10101000.00000001.00001010
CIDR (Classless Inter-Domain Routing)
표기법: IP주소/접두사길이
예: 10.0.0.0/16
/16 의미:
- 처음 16비트는 네트워크 부분 (고정)
- 나머지 16비트는 호스트 부분 (가변)
- 총 2^16 = 65,536개의 IP 주소
CIDR 블록 크기:
/32 = 1개 IP (단일 호스트)
/24 = 256개 IP
/16 = 65,536개 IP
/8 = 16,777,216개 IP
공인 IP vs 사설 IP
사설 IP 범위 (RFC 1918)
Class A: 10.0.0.0 - 10.255.255.255 (/8)
Class B: 172.16.0.0 - 172.31.255.255 (/12)
Class C: 192.168.0.0 - 192.168.255.255 (/16)
VPC에서의 사용
# VPC CIDR 블록 예제
vpc_cidr_examples = {
"소규모": "10.0.0.0/24", # 256개 IP
"중규모": "10.0.0.0/16", # 65,536개 IP
"대규모": "10.0.0.0/8", # 16,777,216개 IP
}
# AWS VPC 권장 사항
# - /16 ~ /28 사이의 CIDR 블록 사용
# - 향후 확장을 고려하여 충분한 크기 선택
서브넷 계산
# 서브넷 분할 예제
def calculate_subnet(vpc_cidr, subnet_bits):
"""
VPC CIDR을 서브넷으로 분할
예: 10.0.0.0/16을 /24 서브넷으로 분할
- VPC: 10.0.0.0/16 (65,536개 IP)
- Subnet 1: 10.0.0.0/24 (256개 IP)
- Subnet 2: 10.0.1.0/24 (256개 IP)
- ...
- Subnet 256: 10.0.255.0/24 (256개 IP)
"""
vpc_prefix = 16 # /16
subnet_prefix = 24 # /24
num_subnets = 2 ** (subnet_prefix - vpc_prefix)
print(f"총 생성 가능한 /24 서브넷: {num_subnets}개")
return num_subnets
# 10.0.0.0/16 VPC를 /24 서브넷으로 분할
calculate_subnet("10.0.0.0/16", 24) # 256개 서브넷
🏗️ VPC 기본 구성 요소
1. VPC (Virtual Private Cloud)
# VPC 생성
aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=MyVPC}]'
# VPC 목록 조회
aws ec2 describe-vpcs
# VPC 속성
{
"VpcId": "vpc-12345678",
"CidrBlock": "10.0.0.0/16",
"State": "available",
"EnableDnsHostnames": true,
"EnableDnsSupport": true
}
VPC 설정 옵션
import boto3
ec2 = boto3.client('ec2')
# DNS 호스트 이름 활성화
ec2.modify_vpc_attribute(
VpcId='vpc-12345678',
EnableDnsHostnames={'Value': True}
)
# DNS 지원 활성화
ec2.modify_vpc_attribute(
VpcId='vpc-12345678',
EnableDnsSupport={'Value': True}
)
2. 서브넷 (Subnets)
서브넷은 VPC의 IP 주소 범위를 분할한 것
퍼블릭 vs 프라이빗 서브넷
┌────────────────────────────────────────────┐
│ VPC (10.0.0.0/16) │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 퍼블릭 서브넷 (10.0.1.0/24) │ │
│ │ - 인터넷 게이트웨이 연결 │ │
│ │ - 웹 서버, 로드 밸런서 │ │
│ │ - 공인 IP 할당 가능 │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ 프라이빗 서브넷 (10.0.2.0/24) │ │
│ │ - NAT 게이트웨이 경유 │ │
│ │ - 데이터베이스, 애플리케이션 서버 │ │
│ │ - 공인 IP 없음 │ │
│ └──────────────────────────────────────┘ │
└────────────────────────────────────────────┘
서브넷 생성
# 퍼블릭 서브넷 생성
aws ec2 create-subnet \
--vpc-id vpc-12345678 \
--cidr-block 10.0.1.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=Public-Subnet-1A}]'
# 프라이빗 서브넷 생성
aws ec2 create-subnet \
--vpc-id vpc-12345678 \
--cidr-block 10.0.2.0/24 \
--availability-zone us-east-1a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=Private-Subnet-1A}]'
# 퍼블릭 IP 자동 할당 활성화
aws ec2 modify-subnet-attribute \
--subnet-id subnet-12345678 \
--map-public-ip-on-launch
다중 AZ 서브넷 설계
# 프로덕션 환경 서브넷 설계
subnet_design = {
"us-east-1a": {
"public": "10.0.1.0/24",
"private": "10.0.2.0/24",
"database": "10.0.3.0/24"
},
"us-east-1b": {
"public": "10.0.11.0/24",
"private": "10.0.12.0/24",
"database": "10.0.13.0/24"
},
"us-east-1c": {
"public": "10.0.21.0/24",
"private": "10.0.22.0/24",
"database": "10.0.23.0/24"
}
}
# 서브넷 생성 자동화
def create_subnets(vpc_id, design):
ec2 = boto3.client('ec2')
for az, subnets in design.items():
for subnet_type, cidr in subnets.items():
response = ec2.create_subnet(
VpcId=vpc_id,
CidrBlock=cidr,
AvailabilityZone=az,
TagSpecifications=[{
'ResourceType': 'subnet',
'Tags': [
{'Key': 'Name', 'Value': f'{subnet_type}-{az}'},
{'Key': 'Type', 'Value': subnet_type}
]
}]
)
subnet_id = response['Subnet']['SubnetId']
# 퍼블릭 서브넷에 자동 공인 IP 할당
if subnet_type == 'public':
ec2.modify_subnet_attribute(
SubnetId=subnet_id,
MapPublicIpOnLaunch={'Value': True}
)
print(f"Created {subnet_type} subnet in {az}: {subnet_id}")
3. 라우팅 테이블 (Route Tables)
라우팅 테이블은 네트워크 트래픽의 경로를 결정
# 라우팅 테이블 생성
aws ec2 create-route-table \
--vpc-id vpc-12345678 \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=Public-RT}]'
# 라우트 추가
aws ec2 create-route \
--route-table-id rtb-12345678 \
--destination-cidr-block 0.0.0.0/0 \
--gateway-id igw-12345678
# 서브넷과 연결
aws ec2 associate-route-table \
--route-table-id rtb-12345678 \
--subnet-id subnet-12345678
라우팅 테이블 예제
퍼블릭 라우팅 테이블:
┌──────────────────┬─────────────────┬─────────────┐
│ Destination │ Target │ Status │
├──────────────────┼─────────────────┼─────────────┤
│ 10.0.0.0/16 │ local │ active │
│ 0.0.0.0/0 │ igw-12345678 │ active │
└──────────────────┴─────────────────┴─────────────┘
프라이빗 라우팅 테이블:
┌──────────────────┬─────────────────┬─────────────┐
│ Destination │ Target │ Status │
├──────────────────┼─────────────────┼─────────────┤
│ 10.0.0.0/16 │ local │ active │
│ 0.0.0.0/0 │ nat-12345678 │ active │
└──────────────────┴─────────────────┴─────────────┘
4. 인터넷 게이트웨이 (Internet Gateway)
VPC와 인터넷 간의 통신을 가능하게 함
# 인터넷 게이트웨이 생성
aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=MyIGW}]'
# VPC에 연결
aws ec2 attach-internet-gateway \
--internet-gateway-id igw-12345678 \
--vpc-id vpc-12345678
# 연결 확인
aws ec2 describe-internet-gateways \
--internet-gateway-ids igw-12345678
인터넷 게이트웨이 특징
- 수평 확장: 자동으로 확장되며 가용성이 높음
- 무료: 인터넷 게이트웨이 사용 자체는 무료
- VPC당 1개: 하나의 VPC에 하나의 IGW만 연결 가능
- 상태 비저장: 별도의 세션 정보 유지 안 함
🛠️ VPC 실습: 기본 아키텍처 구축
시나리오: 3-Tier 웹 애플리케이션 VPC
┌────────────────────────────────────────────────────────┐
│ 인터넷 (0.0.0.0/0) │
└──────────────────────┬─────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ 인터넷 게이트웨이 (IGW) │
└──────────────────────┬─────────────────────────────────┘
│
┌──────────────┴──────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ 퍼블릭 서브넷 │ │ 퍼블릭 서브넷 │
│ (AZ-A) │ │ (AZ-B) │
│ 10.0.1.0/24 │ │ 10.0.11.0/24 │
│ │ │ │
│ - ALB │ │ - ALB │
│ - NAT Gateway │ │ - NAT Gateway │
└────────┬─────────┘ └─────────┬────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ 프라이빗 서브넷 │ │ 프라이빗 서브넷 │
│ (AZ-A) │ │ (AZ-B) │
│ 10.0.2.0/24 │ │ 10.0.12.0/24 │
│ │ │ │
│ - EC2 (웹) │ │ - EC2 (웹) │
└────────┬─────────┘ └─────────┬────────┘
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ 프라이빗 서브넷 │ │ 프라이빗 서브넷 │
│ (AZ-A) │ │ (AZ-B) │
│ 10.0.3.0/24 │ │ 10.0.13.0/24 │
│ │ │ │
│ - RDS (Primary) │ │ - RDS (Standby) │
└──────────────────┘ └──────────────────┘
단계별 구축
import boto3
import json
class VPCBuilder:
def __init__(self, region='us-east-1'):
self.ec2 = boto3.client('ec2', region_name=region)
self.vpc_id = None
self.igw_id = None
self.subnets = {}
self.route_tables = {}
def create_vpc(self, cidr_block='10.0.0.0/16', name='MyVPC'):
"""VPC 생성"""
response = self.ec2.create_vpc(
CidrBlock=cidr_block,
TagSpecifications=[{
'ResourceType': 'vpc',
'Tags': [{'Key': 'Name', 'Value': name}]
}]
)
self.vpc_id = response['Vpc']['VpcId']
# DNS 설정
self.ec2.modify_vpc_attribute(
VpcId=self.vpc_id,
EnableDnsHostnames={'Value': True}
)
self.ec2.modify_vpc_attribute(
VpcId=self.vpc_id,
EnableDnsSupport={'Value': True}
)
print(f"✅ VPC 생성 완료: {self.vpc_id}")
return self.vpc_id
def create_internet_gateway(self):
"""인터넷 게이트웨이 생성 및 연결"""
response = self.ec2.create_internet_gateway(
TagSpecifications=[{
'ResourceType': 'internet-gateway',
'Tags': [{'Key': 'Name', 'Value': 'MyIGW'}]
}]
)
self.igw_id = response['InternetGateway']['InternetGatewayId']
# VPC에 연결
self.ec2.attach_internet_gateway(
InternetGatewayId=self.igw_id,
VpcId=self.vpc_id
)
print(f"✅ IGW 생성 및 연결 완료: {self.igw_id}")
return self.igw_id
def create_subnet(self, cidr_block, az, name, subnet_type='private'):
"""서브넷 생성"""
response = self.ec2.create_subnet(
VpcId=self.vpc_id,
CidrBlock=cidr_block,
AvailabilityZone=az,
TagSpecifications=[{
'ResourceType': 'subnet',
'Tags': [
{'Key': 'Name', 'Value': name},
{'Key': 'Type', 'Value': subnet_type}
]
}]
)
subnet_id = response['Subnet']['SubnetId']
self.subnets[name] = subnet_id
# 퍼블릭 서브넷인 경우 자동 공인 IP 할당
if subnet_type == 'public':
self.ec2.modify_subnet_attribute(
SubnetId=subnet_id,
MapPublicIpOnLaunch={'Value': True}
)
print(f"✅ 서브넷 생성 완료: {name} ({subnet_id})")
return subnet_id
def create_route_table(self, name, is_public=False):
"""라우팅 테이블 생성"""
response = self.ec2.create_route_table(
VpcId=self.vpc_id,
TagSpecifications=[{
'ResourceType': 'route-table',
'Tags': [{'Key': 'Name', 'Value': name}]
}]
)
rt_id = response['RouteTable']['RouteTableId']
self.route_tables[name] = rt_id
# 퍼블릭 라우팅 테이블인 경우 IGW로 라우트 추가
if is_public and self.igw_id:
self.ec2.create_route(
RouteTableId=rt_id,
DestinationCidrBlock='0.0.0.0/0',
GatewayId=self.igw_id
)
print(f"✅ 라우팅 테이블 생성 완료: {name} ({rt_id})")
return rt_id
def associate_route_table(self, rt_name, subnet_name):
"""라우팅 테이블과 서브넷 연결"""
self.ec2.associate_route_table(
RouteTableId=self.route_tables[rt_name],
SubnetId=self.subnets[subnet_name]
)
print(f"✅ 라우팅 테이블 연결: {rt_name} → {subnet_name}")
def build_3tier_vpc(self):
"""3-Tier VPC 아키텍처 전체 구축"""
print("🚀 3-Tier VPC 구축 시작...")
# 1. VPC 생성
self.create_vpc('10.0.0.0/16', '3Tier-VPC')
# 2. 인터넷 게이트웨이 생성
self.create_internet_gateway()
# 3. 서브넷 생성 (2개 AZ, 3개 계층)
azs = ['us-east-1a', 'us-east-1b']
for i, az in enumerate(azs):
base = i * 10
# 퍼블릭 서브넷 (웹 계층)
self.create_subnet(
f'10.0.{1+base}.0/24',
az,
f'Public-{az}',
'public'
)
# 프라이빗 서브넷 (애플리케이션 계층)
self.create_subnet(
f'10.0.{2+base}.0/24',
az,
f'Private-App-{az}',
'private'
)
# 프라이빗 서브넷 (데이터베이스 계층)
self.create_subnet(
f'10.0.{3+base}.0/24',
az,
f'Private-DB-{az}',
'private'
)
# 4. 라우팅 테이블 생성
self.create_route_table('Public-RT', is_public=True)
self.create_route_table('Private-RT', is_public=False)
# 5. 라우팅 테이블 연결
for az in azs:
self.associate_route_table('Public-RT', f'Public-{az}')
self.associate_route_table('Private-RT', f'Private-App-{az}')
self.associate_route_table('Private-RT', f'Private-DB-{az}')
print("\n🎉 3-Tier VPC 구축 완료!")
print(f"VPC ID: {self.vpc_id}")
print(f"IGW ID: {self.igw_id}")
print(f"서브넷 수: {len(self.subnets)}개")
return {
'vpc_id': self.vpc_id,
'igw_id': self.igw_id,
'subnets': self.subnets,
'route_tables': self.route_tables
}
# 사용 예제
if __name__ == '__main__':
builder = VPCBuilder(region='us-east-1')
result = builder.build_3tier_vpc()
print("\n📋 구축 결과:")
print(json.dumps(result, indent=2))
🔍 VPC 설계 모범 사례
1. CIDR 블록 선택
# ✅ 좋은 예: 충분한 여유 공간
good_vpc_cidr = "10.0.0.0/16" # 65,536개 IP
# ❌ 나쁜 예: 너무 작은 CIDR
bad_vpc_cidr = "10.0.0.0/24" # 256개 IP (확장 불가)
# 권장 사항:
# - /16: 대규모 프로덕션 환경
# - /20: 중규모 환경
# - /24: 개발/테스트 환경
2. 서브넷 설계 전략
# IP 주소 할당 전략
subnet_strategy = {
"예약": {
"AWS": 5, # AWS가 예약 (첫 4개 + 마지막 1개)
"설명": [
"10.0.0.0: 네트워크 주소",
"10.0.0.1: VPC 라우터",
"10.0.0.2: DNS 서버",
"10.0.0.3: 향후 사용",
"10.0.0.255: 브로드캐스트"
]
},
"사용가능": "전체 IP - 5"
}
# /24 서브넷: 256 - 5 = 251개 사용 가능
# /20 서브넷: 4,096 - 5 = 4,091개 사용 가능
3. 다중 AZ 설계
# 고가용성을 위한 다중 AZ 배치
최소 2개 AZ 사용 (권장 3개)
AZ-A:
- 퍼블릭: 10.0.1.0/24
- 프라이빗: 10.0.2.0/24
- DB: 10.0.3.0/24
AZ-B:
- 퍼블릭: 10.0.11.0/24
- 프라이빗: 10.0.12.0/24
- DB: 10.0.13.0/24
AZ-C:
- 퍼블릭: 10.0.21.0/24
- 프라이빗: 10.0.22.0/24
- DB: 10.0.23.0/24
4. 보안 그룹 계층화
# 계층별 보안 그룹 설계
security_groups = {
"ALB-SG": {
"inbound": [
{"port": 80, "source": "0.0.0.0/0", "protocol": "tcp"},
{"port": 443, "source": "0.0.0.0/0", "protocol": "tcp"}
]
},
"Web-SG": {
"inbound": [
{"port": 80, "source": "ALB-SG", "protocol": "tcp"}
]
},
"App-SG": {
"inbound": [
{"port": 8080, "source": "Web-SG", "protocol": "tcp"}
]
},
"DB-SG": {
"inbound": [
{"port": 3306, "source": "App-SG", "protocol": "tcp"}
]
}
}
📊 VPC 모니터링 및 문제 해결
VPC Flow Logs
# VPC Flow Logs 활성화
aws ec2 create-flow-logs \
--resource-type VPC \
--resource-ids vpc-12345678 \
--traffic-type ALL \
--log-destination-type cloud-watch-logs \
--log-group-name /aws/vpc/flowlogs \
--deliver-logs-permission-arn arn:aws:iam::account:role/flowlogsRole
# Flow Logs 조회
aws ec2 describe-flow-logs \
--filter "Name=resource-id,Values=vpc-12345678"
Flow Logs 형식
# Flow Log 레코드 예제
version account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status
2 123456789012 eni-abc123de 10.0.1.5 10.0.2.10 49152 80 6 10 5000 1234567890 1234567891 ACCEPT OK
Flow Logs 분석
import boto3
from datetime import datetime, timedelta
def analyze_flow_logs():
"""VPC Flow Logs 분석"""
logs = boto3.client('logs')
# CloudWatch Insights 쿼리
query = """
fields @timestamp, srcAddr, dstAddr, srcPort, dstPort, action
| filter action = "REJECT"
| stats count() as rejectedConnections by srcAddr
| sort rejectedConnections desc
| limit 20
"""
response = logs.start_query(
logGroupName='/aws/vpc/flowlogs',
startTime=int((datetime.now() - timedelta(hours=1)).timestamp()),
endTime=int(datetime.now().timestamp()),
queryString=query
)
query_id = response['queryId']
# 쿼리 결과 대기
import time
while True:
result = logs.get_query_results(queryId=query_id)
if result['status'] == 'Complete':
break
time.sleep(1)
# 결과 출력
print("🚫 거부된 연결 상위 20개 소스 IP:")
for row in result['results']:
src_ip = next(field['value'] for field in row if field['field'] == 'srcAddr')
count = next(field['value'] for field in row if field['field'] == 'rejectedConnections')
print(f" {src_ip}: {count}회")
return result['results']
# 사용 예제
analyze_flow_logs()
VPC 문제 해결
1. 인스턴스가 인터넷에 연결되지 않을 때
def troubleshoot_internet_connectivity(instance_id):
"""인터넷 연결 문제 진단"""
ec2 = boto3.client('ec2')
print(f"🔍 인스턴스 {instance_id} 인터넷 연결 진단 중...")
# 1. 인스턴스 정보 조회
instance = ec2.describe_instances(InstanceIds=[instance_id])
instance_data = instance['Reservations'][0]['Instances'][0]
subnet_id = instance_data['SubnetId']
vpc_id = instance_data['VpcId']
# 2. 공인 IP 확인
public_ip = instance_data.get('PublicIpAddress')
if not public_ip:
print("❌ 공인 IP 없음")
print(" 해결: Elastic IP 할당 또는 서브넷 자동 공인 IP 활성화")
else:
print(f"✅ 공인 IP: {public_ip}")
# 3. 서브넷 라우팅 테이블 확인
route_tables = ec2.describe_route_tables(
Filters=[
{'Name': 'association.subnet-id', 'Values': [subnet_id]}
]
)
has_igw_route = False
if route_tables['RouteTables']:
for route in route_tables['RouteTables'][0]['Routes']:
if route.get('GatewayId', '').startswith('igw-'):
has_igw_route = True
print(f"✅ 인터넷 게이트웨이 라우트 존재: {route['GatewayId']}")
break
if not has_igw_route:
print("❌ 인터넷 게이트웨이 라우트 없음")
print(" 해결: 라우팅 테이블에 0.0.0.0/0 → IGW 라우트 추가")
# 4. Security Group 확인
security_groups = instance_data['SecurityGroups']
print(f"\n🔒 Security Groups: {len(security_groups)}개")
for sg in security_groups:
sg_details = ec2.describe_security_groups(
GroupIds=[sg['GroupId']]
)
egress_rules = sg_details['SecurityGroups'][0]['IpPermissionsEgress']
has_outbound = any(
rule.get('IpRanges', [{}])[0].get('CidrIp') == '0.0.0.0/0'
for rule in egress_rules
)
if has_outbound:
print(f"✅ {sg['GroupName']}: 아웃바운드 트래픽 허용")
else:
print(f"❌ {sg['GroupName']}: 아웃바운드 트래픽 제한됨")
# 5. NACL 확인
nacls = ec2.describe_network_acls(
Filters=[
{'Name': 'association.subnet-id', 'Values': [subnet_id]}
]
)
print(f"\n🛡️ Network ACL 확인:")
if nacls['NetworkAcls']:
nacl = nacls['NetworkAcls'][0]
# Egress 규칙 확인
egress_rules = [r for r in nacl['Entries'] if r['Egress']]
allows_all = any(
r['CidrBlock'] == '0.0.0.0/0' and
r['RuleAction'] == 'allow'
for r in egress_rules
)
if allows_all:
print("✅ NACL이 아웃바운드 트래픽 허용")
else:
print("❌ NACL이 아웃바운드 트래픽 차단")
# 사용 예제
troubleshoot_internet_connectivity('i-1234567890abcdef0')
2. 서브넷 간 통신이 안 될 때
# 체크리스트:
1. 라우팅 테이블 확인
- VPC 내부 트래픽 (10.0.0.0/16 → local)
2. Security Group 확인
- 소스 SG에서 대상 SG로 트래픽 허용
3. NACL 확인
- 인바운드/아웃바운드 모두 허용
4. 네트워크 설정 확인
- 올바른 서브넷에 배치
- 정확한 프라이빗 IP 사용
🎓 VPC 기초
- Q: VPC에서 사용 가능한 CIDR 범위는?
- A: /16 ~ /28 (AWS 권장: /16)
- Q: /24 서브넷에서 실제 사용 가능한 IP 개수는?
- A: 251개 (256 - 5개 AWS 예약)
- Q: 퍼블릭 서브넷과 프라이빗 서브넷의 차이는?
- A: 퍼블릭은 IGW로 가는 라우트 존재, 프라이빗은 없음
- Q: 인터넷 게이트웨이의 주요 특징은?
- A: 수평 확장, 고가용성, VPC당 1개만 연결 가능
- Q: VPC Flow Logs는 무엇을 기록하나?
- A: ENI를 통과하는 IP 트래픽 정보 (허용/거부 모두)
📋 체크리스트
VPC 기본 설정
VPC CIDR 블록 계획 (향후 확장 고려)
DNS 호스트 이름 활성화
DNS 지원 활성화
태그 지정 (Name, Environment 등)
서브넷 설계
최소 2개 AZ 사용 (고가용성)
퍼블릭/프라이빗 서브넷 분리
계층별 서브넷 분리 (웹/앱/DB)
충분한 IP 주소 공간 확보
라우팅 설정
퍼블릭 라우팅 테이블 (IGW 연결)
프라이빗 라우팅 테이블 (NAT 연결)
서브넷-라우팅 테이블 연결 확인
보안
Security Groups 계층별 구성
NACL 기본 규칙 검토
VPC Flow Logs 활성화
최소 권한 원칙 적용
💡 실전 팁
1. VPC 설계 도구
# VPC 설계 계산기
def vpc_calculator(vpc_cidr, subnet_size):
"""VPC CIDR을 기반으로 서브넷 계획 계산"""
import ipaddress
network = ipaddress.ip_network(vpc_cidr)
subnets = list(network.subnets(new_prefix=subnet_size))
print(f"VPC: {vpc_cidr}")
print(f"총 IP: {network.num_addresses:,}개")
print(f"생성 가능한 /{subnet_size} 서브넷: {len(subnets)}개")
print(f"\n서브넷당 IP: {subnets[0].num_addresses}개")
print(f"서브넷당 사용 가능 IP: {subnets[0].num_addresses - 5}개")
print("\n처음 10개 서브넷:")
for i, subnet in enumerate(subnets[:10], 1):
print(f" {i}. {subnet}")
return subnets
# 예제: 10.0.0.0/16을 /24 서브넷으로 분할
vpc_calculator('10.0.0.0/16', 24)
2. VPC 비용 최적화
무료:
- VPC 자체
- 서브넷
- 라우팅 테이블
- 인터넷 게이트웨이
- Security Groups
- Network ACLs
유료:
- NAT Gateway ($0.045/시간 + 데이터 처리)
- VPC Endpoints ($0.01/시간)
- VPN Connection ($0.05/시간)
- VPC Flow Logs (CloudWatch Logs 비용)
비용 절감 팁:
1. NAT Gateway 대신 NAT Instance 고려 (소규모)
2. 불필요한 VPC Endpoints 제거
3. Flow Logs 필터링으로 로그 양 감소
3. VPC 자동화
# CloudFormation 템플릿 생성
def generate_vpc_cfn_template():
"""VPC CloudFormation 템플릿 생성"""
template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "3-Tier VPC Architecture",
"Parameters": {
"VpcCIDR": {
"Type": "String",
"Default": "10.0.0.0/16",
"Description": "VPC CIDR Block"
}
},
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": {"Ref": "VpcCIDR"},
"EnableDnsHostnames": True,
"EnableDnsSupport": True,
"Tags": [{"Key": "Name", "Value": "3Tier-VPC"}]
}
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [{"Key": "Name", "Value": "3Tier-IGW"}]
}
},
"AttachGateway": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": {"Ref": "VPC"},
"InternetGatewayId": {"Ref": "InternetGateway"}
}
},
"PublicSubnet1": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {"Ref": "VPC"},
"CidrBlock": "10.0.1.0/24",
"AvailabilityZone": {"Fn::Select": [0, {"Fn::GetAZs": ""}]},
"MapPublicIpOnLaunch": True,
"Tags": [{"Key": "Name", "Value": "Public-Subnet-1"}]
}
}
# ... 추가 리소스
},
"Outputs": {
"VPCId": {
"Description": "VPC ID",
"Value": {"Ref": "VPC"}
}
}
}
return template
import json
template = generate_vpc_cfn_template()
print(json.dumps(template, indent=2))
🔗 추가 학습 리소스
AWS 공식 문서
네트워킹 기초
실습 도구
VPC 구성 요소:
- VPC: 격리된 가상 네트워크 (CIDR 블록)
- 서브넷: VPC를 작은 네트워크로 분할
- 라우팅 테이블: 트래픽 경로 결정
- 인터넷 게이트웨이: VPC와 인터넷 연결
설계 원칙:
- 충분한 IP 공간 확보 (/16 권장)
- 다중 AZ로 고가용성 확보
- 퍼블릭/프라이빗 서브넷 분리
- 계층별 보안 그룹 구성
모니터링:
- VPC Flow Logs로 트래픽 분석
- CloudWatch Metrics 활용
- 정기적인 보안 감사
Share article