AWS VPC, 제대로 이해하기 1: Hands-On
VPC 학습을 위해 데모 VPC, 서브넷, 라우팅 테이블 인터넷 게이트웨이 등을 구성하는 것이 본 포스팅의 목표입니다.
안녕하세요. 지난 AWS VPC, 제대로 이해하기에 이어 VPC Demo 환경을 제작하고자 합니다.
제작할 구조는 아래와 같습니다.
VPC, Subnet, Internet Gateway, Bastion의 네가지 개념을 학습하기 위함이며,
각 개념을 단계 별로, 총 4단계를 구성하여 위의 아키텍처를 제작해보겠습니다.
1. VPC 생성
먼저 VPC를 처음 사용한다면, 기본적으로 Default VPC 하나를 확인할 수 있습니다.
우측 상단의 Create VPC를 선택해서 VPC를 생성해보도록 하겠습니다.
IPv4 CIDR는 10.0.0.0/16 으로 지정하겠습니다.
그렇다면 VPC-A는 어떤 범위를 가질 수 있을까요?
10.0.0.0 ~ 10.0.255.255 범위의 $2^{16}=63,536$ 개의 IP 대역을 가질 수 있습니다.
VPC의 CIDR 제한은 /16 까지이기 때문에 더 큰 범주를 갖지 못합니다. 가령, /15는 불가합니다.
범위를 넘는 다면 AWS가 위와 같은 안내 문구를 노출시킵니다.
Tenancy는 EC2 인스턴스가 실행되는 방법을 정의할 수 있는데, Default와 Dedicate 중 하나를 선택합니다.
Default는 공유 하드웨어, Dedicate는 전용 하드웨어를 의미하며, 후자는 굉장히 비싼 값을 지불해야 합니다.
이렇게 VPC를 하나 생성해보았습니다.
이제 Subnet 등 하위 구성요소를 설정하겠습니다.
Edit CIDRs
추가적으로, VPC 내에 여러 CIDR를 등록하고 싶다면 VPC CIDR 수정을 선택해서 추가/삭제할 수 있습니다.
가령, 10.1.0.0/16를 아래와 같이 추가할 수 있습니다.
저는 시험삼아 10.1.0.0/16을 생성했다가 지워서 Disassociated 된 것도 볼 수 있는데요.
생성했다가 삭제하면 위 처럼 표시됩니다.
CIDR 추가는 시험삼아 설정한 것이라, 10.1.0.0/16를 삭제하고 이어가겠습니다.
2. Subnet 생성
위에서 생성한 VPC 내에 Subnet을 생성해보도록 하겠습니다.
AWS 콘솔창의 VPCs 아래 Subnets에서 확인할 수 있습니다.
이 떄, 특정 VPC의 Subnet 만을 조회하고 싶을 때 아래와 같이 Filtering을 사용하면 편하게 조회할 수 있습니다.
이번엔 VPC-A에 두 개의 서브넷을 생성해보겠습니다.
서브넷의 정보는 다음과 같습니다.
- PublicSubnetA: ap-northeast-2a, 10.0.0.0/24
- PrivateSubnetA: ap-northeast-2a, 10.0.1.0/24
위와 같이 생성하고 나면, 이제 아래와 같이 VPC-A에 생성된 두 개의 Subnet을 확인할 수 있습니다.
각 서브넷이 가지는 IP 대역을 확인해보겠습니다.
먼저, PublicSubnetA의 IPv4 CIDR는 10.0.0.0/24입니다.
이는 10.0.0.0 ~ 10.0.0.255 까지의 대역을 가지기 때문에 총 $2^8=256$ 개의 IP를 설정할 수 있습니다.
하지만, PublicSubnetAdml Available IPv4 address를 확인해보면 251 (개)를 확인할 수 있는데요.
이는 서브넷 생성 시, AWS가 사용할 IP 5개를 미리 예약하기 때문에,
해당 IP를 사용할 수 없어서 251개가 사용하다고 명시된 내용입니다.
PrivateSubnetA도 마찬가지입니다.
이름을 PublicSubnet, PrivateSubnet으로 설정해두긴 했지만, 현재까지는 두 서브넷 모두 고립된 상태로 그 어떤 접근도 할 수 없는 상태입니다. PublicSubnet이 아직 Public한 상태가 아니라는 의미입니다.
그렇다면, Public Subnet을 어떻게 하면 외부에 접근할 수 있도록 할까요?
여러 방법 중 하나는, Internet Gateway를 사용해서 외부의 Internet과 연결할 수 있습니다.
3. Internet Gateway
Public Subnet을 외부 인터넷과 연결하기 위해서는 Internet Gateway를 사용할 수 있습니다.
이를 증명하기 위해서, 아래를 단계 별로 확인해보도록 하겠습니다.
#1. Public subnet에 EC2 하나를 먼저 생성해서 인터넷 연결이 불가함을 보이고
#2. Internet Gateway를 생성한 후
#3. Route tables을 설정해서 Internet연결이 되도록 Routing 한 다음에
#4. EC2에서 연결을 성공함
#1. EC2 Instance: Bastion Server
테스트 용도의 EC2 Instance를 생성하고, 이름을 Bastion이라고 명명하겠습니다.
Bastion은 본 게시글이 뒷 부분에 설명하겠습니다.
EC2를 생성하기 전, Public Subnet의 Auto-assign IPv4 기능을 활성화하겠습니다.
그 다음 EC2 인스턴스를 생성합니다.
이름은 BastionHost으로 지정하고, 데모이기 때문에 따로 Key Pair는 지정하지 않았습니다.
중요한 점은, Network settings인데요.
생성한 VPC-A와 PublicSubnetA를 선택해주어야 합니다.
PublicSubnetA를 선택하면 Auto-assign public IP가 Enable 상태가 되어 있는데, 위에서 해당 Subnet의 Default 설정을 변경해주었기 때문에 설정된 값입니다. 만약, 해당 설정을 하지 않았다면 Disable 값이 기본 설정되어 있습니다.
이렇게 Launch Instance 버튼을 클릭하면 하기 그림처럼 새로운 EC2 인스턴스가 생성된 것을 확인할 수 있습니다.
그럼 PublicSubnetA 내에 생성된 EC2 인스턴스가 정말 외부 접속이 불가능한지 확인해보겠습니다.
아래에서는 Public IPv4가 설정되어 있음을 확인하고 EC2에 연결 시도를 합니다.
연결에 실패한 것을 확인할 수 있습니다.
그럼 이제 Internet gateway로 Public 연결을 시도해보겠습니다.
#2. Internet Gateway
아래와 같이 아주 간단하게 Internet Gateway를 생성하고 VPC를 연결해줍니다.
Internet Gateway와 VPC가 연결되어 있다고 해서 인터넷 연결이 되는 게 아닌데요. Route table을 설정해주어야 합니다.
#3. Route tables
데모 생성에 앞서, Route Table이 무엇인지 확인해보겠습니다.
📌 Route Table?
VPC에는 Route Table을 사용하여 네트워크 트래픽이 전달되는 위치를 제어합니다.
VPC의 각 서브넷을 라우팅 테이블에 연결하는데, 이는 서브넷에 대한 라우팅을 제어합니다.
서브넷을 특정 라우팅 테이블과 명시적으로 연결할 수 있으며, 그렇지 않으면 서브넷이 기본 라우팅 테이블과 암시적으로 연결됩니다.
서브넷은 한 번에 하나의 라우팅 테이블에만 연결할 수 있지만 여러 서브넷을 동일한 서브넷 라우팅 테이블에 연결할 수 있습니다.
그럼 다시 데모를 생성해보겠습니다.
Subnet의 Network 구성을 설정하기 위해서는 Route tables에 Route 정보를 입력해야 합니다.
Route Tables를 확인하면 VPC의 Default Route Table을 확인할 수 있습니다.
명시적 연결이 없는 서브넷들이 연결되어 있는데, 명시적으로 정의하는 것이 훨씬 좋은 방법이니,
각 Subnet에 맞는 Route Table을 생성하겠습니다.
PublicRouteTable을 생성하고, Public Subnet에 연결합니다.
생성된 RouteTable에 routing 설정을 할텐데요.
기본적으로 설정되어 있는 10.0.0.0/16 → local, 내부 VPC 요청은 내부로 연결시키는 규칙 다음으로,
0.0.0.0/0 → Internet Gateway(Demo-IGW)로 연결 하는 규칙을 생성합니다.
#4. Successful EC2 Connection
ping 명령어로 인터넷 접속이 잘 되는 것을 확인할 수 있습니다.
4.Bastion
PublicSubnet에 위치한 EC2 인스턴스가 외부로 향하는 인터넷 연결을 성공한 것을 확인했습니다.
이번에는 이 Public EC2 인스턴스에서 Private Subnet에 접근할 수 있도록 Bastion을 사용해보도록 하겠습니다.
아래 부분을 구현합니다.
Bastion는 프라이빗 서브넷에 대한 인터넷 액세스는 없는데,
사용자가 프라이빗 서브넷에 없는 EC2 인스턴스에 액세스하고 싶을 때 사용합니다.
Bastion Host
✔️ 위치: EC2 인스턴스이며 퍼블릭 서브넷
✔️ 기능: 퍼블릭 서브넷에 있는 EC2 인스턴스로 프라이빗 서브넷에 있는 EC2 인스턴스에 액세스
✔️ 동작: 프라이빗 서브넷에 있는 EC2 인스턴스에 액세스
1. SSH로 배스천 호스트에 연결
2. 이 배스천 호스트에서 다시 SSH로 프라이빗 서브넷의 EC2 인스턴스에 연결
보안 규칙
Public Subnet
PublicSubnet에 위치한 BastionHost는 퍼블릭 CIDR 액세스 혹은 사용자의 인터넷 액세스만 허용하는 등 인터넷 액세스 최소한으로 제한해야 합니다. 또, Bastion Hos는 22번 포트를 허용하여 SSH 액세스가 가능하게 만들어야 합니다.
Private Subnet
Bastion Host의 보안 그룹을 허용하거나, Private IP를 허용해야 합니다.
그럼 지금부터 Bastion을 사용해서 PrivateSubnet에 위치한 EC2 Instance에 SSH로 연결할 수 있는 데모를 생성하겠습니다.
#1. Private Route Table 설정
PrivateSubnet에 적용했던 RouteTable과 동일하게 PrivateSubnet에도 RouteTable을 생성하여 적용합니다.
단, 이번에는 PublicSubnet에서 적용했던 Routing 규칙을 설정할 필요가 없습니다.
PrivateSubnet은 외부로 연결되는 그 어떤 접근도 허용하지 않을 예정이기 때문입니다.
#2. Create KeyPair
이제 Private EC2 Instance 접근을 위한 KeyPair를 생성합니다.
Key Pair는 DemoKeyPair의 이름으로 생성하여, 추후 생성할 Private EC2 Instance에 접근 시 액세스 권한으로 부여할 예정입니다.
참고로 Key Pair는 EC2 인스턴스를 시작하기 전에 선택한 키 쌍에 대한 액세스 권한이 있는지 확인합니다.
#3. Create Private EC2 Instance
이제 VPC-A의 PrivateSubnet에 새로운 EC2 인스턴스를 생성합니다.
이름은 PrivateInstance로 설정하고, 기본으로 설정되는 Amazon Linux 2023 AMI를 그대로 사용하겠습니다.
Key Pair는 위에서 생성한 DemoKeyPair 키를 사용하여, 해당 EC2에 접근 시 액세스 권한을 DemoKeyPair 키로 하게끔 만들겠습니다.
중요한 점은 VPC-A의 PrivateSubnet에 해당 인스턴스를 생성한다는 것입니다.
#4. Accessing Instance using the Bastion
Bastion을 사용한 Private EC2 Instance를 접근하기 위해서는 위에서 발급했던 Key Pair가 필요합니다.
Bastion은 Public Instance에서 Private Instance를 접근하는 방식이기 때문에,
SSH 접근을 시도할 Public Instance 내부에 해당 Key Pair가 존재해야겠죠.
다운받은 Key Pair를 해당 인스턴스 내로 복사하겠습니다.
필자는 vi 편집기를 사용해서 파일을 생성했습니다.
이제 접근이 잘되는지 확인해보겠습니다.
접근을 위해 PemKey 파일 권한을 400로 설정해주고, ssh 명령어를 통해 접근합니다.
$ chmod 400 DemoKeyPair.pem
$ ssh ec2-user@<<ec2-private-ip>> -i DemoKeyPair.pem
Private Instance는 외부 연결을 하지 않기 때문에 인터넷 연결이 불가합니다.
때문에 ping 명령어로 google.com에 전송 시도를 하려고 해도 위와 같이 실패됩니다.
그럼 지금까지 Public Subnet, Private Subnet을 생성하고 Bastion으로 각 서버에 접근하는 방식을 테스트해보았습니다.