퍼블릭 서브넷을 인터넷에 연결하기

AWSBeginner
지금 연습하기

소개

배송 애플리케이션이 VPC 안에 준비되어 있지만 공개 서비스는 아직 외부 요청을 받을 수 없습니다. 빠진 경로를 구축합니다. 인터넷 게이트웨이를 VPC에 연결하고, 애플리케이션 서브넷의 라우팅 테이블에 기본 경로를 추가한 뒤, 애플리케이션 네트워크 인터페이스에 퍼블릭 주소를 연결합니다.

먼저 '애플리케이션 서브넷을 포함한 VPC 만들기'를 완료하세요. 이 새 환경은 자체 VPC, 서브넷, 애플리케이션, 접근 규칙을 제공하며 이전 VM을 재사용하지 않습니다. CLI는 이미 구성되어 있습니다. 작업과 무관한 참조 네트워크와 제공된 모든 애플리케이션 리소스를 유지하세요.

자격증 시험 관련성

이 실습은 다음 시험 주제를 직접 연습할 기회를 제공합니다.

인터넷 게이트웨이 연결하기

이 단계에서는 제공된 애플리케이션 네트워크를 확인하고 해당 VPC에 인터넷 게이트웨이를 연결합니다.

명령은 Terminal에서 실행하고 옆의 AWS View를 클릭하세요. 이 뷰는 CLI와 같은 리소스 상태를 읽습니다. application-network VPC에는 public-subnet과 private-subnet이 있습니다. 제공된 애플리케이션은 public-subnet의 프라이빗 주소 10.20.1.10을 사용합니다.

cd /home/labex/project

Name 태그로 애플리케이션 VPC를 선택합니다. --filters는 서버 결과를 제한하고 --query는 ID를 선택합니다. $(...)는 ID를 셸 변수에 저장하여 나머지 단계에서 사용하게 합니다.

VPC_ID=$(aws ec2 describe-vpcs \
  --filters Name=tag:Name,Values=application-network \
  --query 'Vpcs[0].VpcId' \
  --output text)

선택한 네트워크의 서브넷을 조회합니다.

aws ec2 describe-subnets \
  --filters "Name=vpc-id,Values=$VPC_ID" \
  --query 'Subnets[].{CIDR:CidrBlock,ID:SubnetId}' \
  --output table

범위는 10.20.1.0/24와 10.20.2.0/24입니다. 별도의 10.99.0.0/16 참조 네트워크는 이 작업과 무관하므로 유지하세요.

HTTP는 이 애플리케이션 엔드포인트가 사용하는 요청과 응답 프로토콜입니다. 포트는 수신 서비스를 식별합니다. 애플리케이션은 TCP 포트 80에서 수신 대기합니다. AWS View에서 Request application · client A를 클릭하세요. 제공된 클라이언트 198.51.100.10에서 외부 요청을 보냅니다. 결과는 Connection failed이며 No public address가 표시됩니다. 애플리케이션은 있지만 공개 경로가 아직 완성되지 않았습니다.

**인터넷 게이트웨이(IGW)**는 VPC의 공개 라우팅 경로를 인터넷에 연결합니다. 생성과 연결은 별개의 작업입니다. 새 게이트웨이에 태그를 지정하여 자신의 실습 리소스를 식별하세요. 따옴표로 감싼 태그 명세는 하나의 인수입니다.

IGW_ID=$(aws ec2 create-internet-gateway \
  --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=parcel-internet},{Key=Project,Value=parcel}]' \
  --query 'InternetGateway.InternetGatewayId' \
  --output text)

이 게이트웨이만 선택한 애플리케이션 VPC에 연결합니다.

aws ec2 attach-internet-gateway --internet-gateway-id "$IGW_ID" --vpc-id "$VPC_ID"

연결에 성공해도 명령 출력은 없습니다. 대신 리소스 관계를 조회합니다.

aws ec2 describe-internet-gateways \
  --internet-gateway-ids "$IGW_ID" \
  --query 'InternetGateways[].{ID:InternetGatewayId,Attachments:Attachments}' \
  --output json

연결 정보는 자신의 VPC를 가리키며 상태는 available입니다. AWS View는 이제 VPC 아래에 인터넷 게이트웨이를 표시합니다. 연결만으로는 서브넷 경로나 애플리케이션의 퍼블릭 주소가 제공되지 않습니다. 저장된 ID를 유지하려면 이 Terminal을 계속 열어 두세요.

퍼블릭 서브넷 기본 경로 추가하기

이 단계에서는 퍼블릭 서브넷의 인터넷 트래픽을 연결한 게이트웨이로 보냅니다.

라우팅 테이블은 대상 주소 범위를 전달 대상에 매핑합니다. 각 서브넷은 연결된 테이블을 사용하며 명시적인 연결이 없으면 VPC의 기본 테이블을 사용합니다. 이 환경에는 별도로 연결된 public-routes와 private-routes가 제공됩니다. 애플리케이션 VPC 안의 public-routes를 선택합니다.

PUBLIC_ROUTE_TABLE_ID=$(aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=public-routes \
  --query 'RouteTables[0].RouteTableId' \
  --output text)

경로와 연결 정보를 함께 조회합니다.

aws ec2 describe-route-tables \
  --route-table-ids "$PUBLIC_ROUTE_TABLE_ID" \
  --query 'RouteTables[].{ID:RouteTableId,Routes:Routes,Associations:Associations}' \
  --output json

연결 정보는 public-subnet을 식별합니다. 기존 10.20.0.0/16 경로의 대상은 local이며 VPC 트래픽을 VPC 내부에 유지합니다. 이 로컬 경로를 삭제하거나 private-routes를 변경하지 마세요.

기본 경로 0.0.0.0/0은 더 구체적인 경로와 일치하지 않는 IPv4 대상을 포함합니다. --gateway-id로 인터넷 게이트웨이를 전달 대상으로 지정합니다.

aws ec2 create-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id "$IGW_ID"

응답에는 Return: true가 포함됩니다. 테이블을 다시 조회합니다.

aws ec2 describe-route-tables \
  --route-table-ids "$PUBLIC_ROUTE_TABLE_ID" \
  --query 'RouteTables[].Routes[].{Destination:DestinationCidrBlock,Target:GatewayId,State:State}' \
  --output table

기본 경로는 자신의 igw-...를 가리키고 상태는 active입니다. 로컬 경로는 유지됩니다. AWS View도 public-routes 아래에 같은 게이트웨이를 가리키는 0.0.0.0/0을 표시합니다. Request application · client A를 다시 클릭하세요. 여전히 No public address로 실패합니다. 서브넷에는 공개 경로가 생겼지만 애플리케이션에는 자체 퍼블릭 IPv4 주소가 필요합니다.

퍼블릭 주소 연결 및 HTTP 테스트하기

이 단계에서는 제공된 애플리케이션에 탄력적 IP를 연결하고 외부 요청을 성공시킵니다.

탄력적 IP는 계정에 할당되는 퍼블릭 IPv4 주소로, 지원되는 리소스에 연결할 수 있습니다. 할당 ID는 예약된 주소를 식별하고 연결 ID는 리소스와의 연결을 식별합니다. 정리할 때 연결과 할당을 모두 제거합니다.

**네트워크 인터페이스(ENI)**는 애플리케이션의 네트워크 연결과 프라이빗 IP를 제공합니다. 이 실습에는 애플리케이션 인터페이스가 제공되므로 인스턴스를 만들거나 운영체제를 구성할 필요가 없습니다. VPC와 이름으로 인터페이스를 선택합니다.

ENI_ID=$(aws ec2 describe-network-interfaces \
  --filters "Name=vpc-id,Values=$VPC_ID" Name=tag:Name,Values=application-interface \
  --query 'NetworkInterfaces[0].NetworkInterfaceId' \
  --output text)

VPC에서 사용할 주소를 할당하고 할당 ID를 저장합니다.

ALLOCATION_ID=$(aws ec2 allocate-address \
  --domain vpc \
  --query 'AllocationId' \
  --output text)

애플리케이션 인터페이스에 주소를 연결하고 연결 ID를 저장합니다.

ASSOCIATION_ID=$(aws ec2 associate-address \
  --allocation-id "$ALLOCATION_ID" \
  --network-interface-id "$ENI_ID" \
  --query 'AssociationId' \
  --output text)

변경된 인터페이스 상태를 조회합니다.

aws ec2 describe-network-interfaces \
  --network-interface-ids "$ENI_ID" \
  --query 'NetworkInterfaces[].{ID:NetworkInterfaceId,PrivateIP:PrivateIpAddress,PublicIP:Association.PublicIp}' \
  --output table

프라이빗 주소는 여전히 10.20.1.10이고 퍼블릭 필드에는 이제 주소가 있습니다. AWS View의 애플리케이션 카드에 퍼블릭 주소와 게이트웨이 경로가 함께 표시됩니다. Request application · client A를 클릭하세요.

결과는 Success, 원본 주소 198.51.100.10, 대상 포트 80, 본문 Application online입니다. 제공된 애플리케이션이 반환한 HTTP 응답입니다. 구성된 리소스 목록만으로는 요청이 작동한다는 사실을 입증할 수 없습니다.

애플리케이션에 퍼블릭 주소와 인터넷 게이트웨이 경로가 있고 클라이언트 A가 HTTP 응답을 받음

예시 결과: 퍼블릭 서브넷에 게이트웨이 경로와 애플리케이션 주소가 표시되고 요청은 Application online을 반환합니다. ID와 할당된 주소는 달라질 수 있습니다.

준비된 접근 규칙은 이 클라이언트와 포트를 허용합니다. 다음 실습에서 이 규칙을 제어하는 방법을 배우므로 여기서는 변경하지 마세요.

경로 장애 관찰 및 복구하기

이 단계에서는 경로 하나를 제거하고 요청 실패를 관찰한 뒤 작동하는 경로를 복구합니다.

퍼블릭 주소는 라우팅을 대신하지 않습니다. 자신이 만든 기본 경로만 제거하고 제공된 로컬 경로는 유지합니다.

aws ec2 delete-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0

퍼블릭 주소가 여전히 연결되어 있는지 확인합니다.

aws ec2 describe-addresses \
  --allocation-ids "$ALLOCATION_ID" \
  --query 'Addresses[].{PublicIP:PublicIp,Interface:NetworkInterfaceId}' \
  --output table

AWS View의 public-routes에는 이제 로컬 경로만 있습니다. 이전 응답에 Previous request가 표시될 수 있으며 이는 변경된 구성을 설명하지 않습니다. Request application · client A를 클릭하여 새 요청을 보내세요. 퍼블릭 주소가 유지되어도 결과는 Connection failed로 바뀝니다.

퍼블릭 주소는 유지되지만 기본 경로가 없어 새 요청이 실패함

진단 예시: 애플리케이션의 퍼블릭 주소는 남아 있고 public-routes에는 로컬 경로만 있으며 새 요청은 실패합니다.

같은 연결된 게이트웨이를 가리키는 경로를 복구합니다.

aws ec2 create-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id "$IGW_ID"

응답에는 Return: true가 포함됩니다. AWS View에 경로가 다시 표시되면 Request application · client A를 다시 클릭하세요. Success와 Application online이 돌아옵니다. 여러 설정을 동시에 바꾸지 않고 라우팅만 변경 조건으로 분리했습니다.

자신의 공개 경로 제거하기

이 단계에서는 자신이 만든 주소, 경로, 게이트웨이만 제거하며 제공된 애플리케이션 네트워크와 참조 네트워크는 유지합니다.

리소스에는 의존성이 있습니다. 먼저 주소와 인터페이스의 연결을 해제합니다.

aws ec2 disassociate-address --association-id "$ASSOCIATION_ID"

그런 다음 할당을 해제합니다. 연결만 해제하면 할당된 리소스가 남습니다.

aws ec2 release-address --allocation-id "$ALLOCATION_ID"

게이트웨이 연결을 해제하기 전에 자신의 기본 경로를 제거합니다.

aws ec2 delete-route \
  --route-table-id "$PUBLIC_ROUTE_TABLE_ID" \
  --destination-cidr-block 0.0.0.0/0
aws ec2 detach-internet-gateway --internet-gateway-id "$IGW_ID" --vpc-id "$VPC_ID"

마지막으로 연결이 해제된 게이트웨이를 삭제합니다.

aws ec2 delete-internet-gateway --internet-gateway-id "$IGW_ID"

이 제거 명령들은 성공해도 출력이 없습니다. 태그에 의존하지 말고 전체 목록을 조회하여 리소스가 없음을 확인합니다.

aws ec2 describe-addresses --query 'Addresses' --output json
aws ec2 describe-internet-gateways --query 'InternetGateways' --output json

이 새 환경에서는 두 조회 모두 []를 반환합니다. 제공된 서브넷의 경로를 다시 확인합니다.

aws ec2 describe-route-tables \
  --route-table-ids "$PUBLIC_ROUTE_TABLE_ID" \
  --query 'RouteTables[].Routes[].{Destination:DestinationCidrBlock,Target:GatewayId}' \
  --output table

로컬 경로만 남습니다. 제공된 VPC, 서브넷, 애플리케이션 인터페이스는 여전히 존재합니다. AWS View에는 자신의 게이트웨이나 퍼블릭 주소가 더 이상 표시되지 않습니다. Request application · client A를 한 번 더 클릭하세요. 삭제된 공개 경로는 요청을 처리할 수 없습니다. 목록 조회 실패는 리소스 정리가 완료되었다는 증거가 아닙니다.

이 단계의 완료 검사를 실행하세요.

요약

인터넷 게이트웨이를 연결하고 애플리케이션 서브넷에 연결된 테이블에 기본 경로를 추가한 뒤 탄력적 IP를 연결했습니다. 실제 HTTP 접근을 테스트하고, 퍼블릭 주소가 있어도 경로를 제거하면 요청이 실패한다는 점을 확인했습니다. 이후 경로를 복구하고 자신이 만든 실습 리소스만 제거했습니다.

'보안 그룹으로 애플리케이션 접근 제어하기'를 이어서 학습하여 어떤 외부 요청이 애플리케이션에 도달할 수 있는지 제한하세요.