최근 회사에서 새롭게 진행하고 있는 프로젝트는 MSA(MicroService Architecture) 기반의 서비스입니다. MSA란 통합된 하나의 서버가 여러 가지 일을 하도록 기능이 분리된 것이 아니라, 기능별로 분리된 여러 서버에서 각자의 할 일만 효율적으로 처리하도록 디자인된 서비스를 말하는데요, 서버가 여러 대 운용되다 보니 VPC를 구성해서 클라우드 공간을 활용하는 것이 좋을 것 같아 AWS에서 권장하는 방법을 토대로 구축해보았습니다.
VPC가 그래서 뭐야?
VPC는 Virtual Private Cloud의 약자입니다. 쉽게 말하자면 VPN의 클라우드 버전이라고 생각하면 되는데요, VPN이 물리적으로 연결된 네트워크를 논리적으로 다른 네트워크처럼 취급하게 하듯이 VPC도 AWS라는 거대한 클라우드 안에 가상의 클라우드를 구축하는 것으로 이해하시면 됩니다. 현재 AWS에서 구동되는 모든 인스턴스는 VPC 안에서 구동되고 있습니다. 만약 한 번도 VPC를 생성한 적이 없다고 하더라도 이미 AWS에서 default로 생성한 VPC를 이용하고 있다는 뜻이죠.
MSA는 여러 대의 서버를 별도로 구동한다고 말씀드렸습니다. 이럴 때는 VPC를 구성해두고 서브넷을 설정한 뒤 그 안에서 각각의 서버를 구동시켜 통신하거나 VPC endpoint를 두는 방식을 사용하면 서버 간의 통신은 VPC 내부망에서의 통신으로 감당하여 훨씬 효율적이고, 상대적으로 보안에도 강하게 됩니다. 해당 서비스로 접속할 수 있는 엔트포인트 자체가 없을 테니까요.
그래서 어떻게 만든다고?
구축을 위해서 VPC 메뉴에서 직접 VPC와 라우팅 테이블, 서브넷 등을 구축해도 되지만 이왕이면 모든 구성을 한 번에 설정할 수 있도록 VPC 마법사를 이용해서 구축하는 것이 좋습니다.
마법사를 통해서 메뉴에 들어가면 단일 퍼블릭 서브넷 VPC와 퍼블릭 & 프라이빗 서브넷 VPC를 선택할 수 있습니다. 퍼블릭 서브넷 VPC와 프라이빗 서브넷 VPC는 인터넷에 접근이 가능한지 여부에 따라서 나뉘게 됩니다. 제대로 구성하려면 외부로 노출될 필요가 없는 각각의 서버들은 프라이빗 서브넷 VPC로 구성하고 라이브러리나 서버 업데이트를 위해 아웃바운드 요청이 필요한 경우에 한해 NAT 게이트웨이를 따로 구성하는 설정을 해주어야 하지만, 이번에는 단일 퍼블릭 서브넷 VPC로 구성해보도록 하겠습니다.
설정은 사실 특별할 것이 없습니다. VPC 이름과 서브넷의 CIDR, 가용 영역, 이름을 설정하면 사실 끝인데요. 이제 각각의 메뉴가 뭘 의미하는지를 알아볼 시간입니다.
우선 첫 번째 CIDR 블록을 보면 10.0.0.0/16으로 설정이 돼있습니다. 10으로 시작하는 IP 주소가 붙는 이유는 이 공간이 VPC 내부이기 때문입니다. 사설 IP 대역을 써야 한다는 의미죠. 사설 IP는 RFC1918에 규정되어 있습니다.
CIDR은 뭐냐 하면 IP 주소/서브넷 마스크 영역으로 표기하자는 약속입니다. 기존에 존재하던 Class A, B, C, D, E로는 유연한 IP 주소 분배가 어렵다고 해서 대두된 것인데, IP 주소는 4마디의 octet으로 되어있죠? 서브넷 마스크는 그 octet의 어디까지를 가릴 것인가를 명시한 건데, /16이면 좌측부터 16번째 자리의 수까지는 1을 넣어 가리겠다는 뜻입니다. 매우 대강 설명한 내용이기 때문에 이것을 자세히 알고 싶으시다면 다른 글을 읽어보시는 걸 추천드립니다. 아무튼 저 숫자가 작을수록 할당될 수 있는 IP 주소가 많아지고, 커질수록 적어집니다.
아무튼 이제 우리의 VPC는 10.0.xxx.xxx라는 IP를 할당받게 될 겁니다. 그리고 서브넷은 이 VPC 내부에 설정되는 것이므로 VPC의 CIDR 블록보다 숫자가 커야겠죠? 그래서 /24로 설정된 겁니다. 마지막 octet 몇 개가 이미 예약되어 있는데요, 다른 곳에서도 마찬가지로 0과 255는 각각 네트워크 주소와 브로드캐스트 주소로 예약됩니다. 이를 포함해서 총 5개의 IP 주소가 예약되어 있습니다. 1은 VPC 라우터용, 2는 DNS 서버용, 3은 예비용으로 예약된 값이므로, 총 251개의 IP가 사용 가능한 것으로 나타나는 것입니다.
또 여기서는 가용 영역을 ap-northeast-2a영역으로 설정했습니다. 가용 영역은 간단히 말해서 해당 리전 내에 논리적으로 연결된 클러스터를 말하는데, 대략 5만 대에서 8만 대의 물리적인 서버로 구성됩니다. 가용 영역은 최소 2개에서 5개까지로 다양하게 구성됩니다. 하나의 가용 영역에 장애가 생겼을 경우에도 서비스는 원활하게 돌아갈 필요가 있기 때문에 보통 다중 가용 영역에 서비스를 배포하고 로드 밸런싱을 통해 서빙하는 것이 일반적입니다.
다중 가용 영역 설정
또 다른 가용 영역에도 배포하기 위해서 추가 서브넷을 생성합니다. 이번에는 VPC 마법사가 아니라 서브넷 메뉴를 통해서 서브넷을 생성하겠습니다. 이번에는 ap-northeast-2c영역을 선택하고 생성해줍니다. a영역에서 세 번째 octet을 10으로 설정했으므로 이번에는 20으로 설정합니다.
라우팅 테이블
우리는 VPC 마법사를 이용했기 때문에 라우팅 테이블이 이미 생성돼 있을 겁니다. 방금 c영역에 새롭게 생성한 서브넷도 라우팅 테이블에 포함시켜야 하므로 해당 서브넷을 선택한 뒤 작업 - 라우팅 테이블 연결 편집 항목을 선택합니다.
이때 기본 라우팅 테이블에는 igw가 포함되어 있지 않으니, 새롭게 생성된 라우팅 테이블을 선택해주어야 합니다. 만약 해당 서브넷이 프라이빗이라면 igw는 포함될 필요가 없겠죠.
보안 그룹
보안 그룹은 가상의 방화벽을 말합니다. 인바운드 트래픽과 아웃바운드 트래픽 규칙을 설정하고자 할 때 사용하는데, 보안 그룹 생성 탭을 눌러 이름과 설명을 적고 우리가 생성한 VPC를 선택해주면 끝납니다. 우선은 기본적으로 ssh 접속을 위한 22 포트와 http 접속을 위한 80 포트를 인바운드 규칙으로 추가해줍니다. 아웃바운드 규칙은 특별히 건드릴 게 없습니다.
EC2 인스턴스 생성
트래픽이 잘 작동하는지 확인하기 위해 각각의 서브넷에 EC2 인스턴스를 하나씩 생성해줍니다. 인스턴스를 생성할 때는 인스턴스 구성의 네트워크 탭에서 아까 생성한 VPC를, 서브넷은 각각의 서브넷을 선택해서 생성하도록 합니다. 그리고 보안 그룹 구성에서 방금 생성한 보안 그룹을 선택하고 시작하면 됩니다. 인스턴스에 간단한 웹 서버를 구축해두면 생성된 인스턴스의 IP 주소로 요청이 잘 들어가는지 브라우저를 통해서도 간단히 확인해볼 수가 있습니다.
제가 실습한 AWS 워크숍 자료에서 간단한 웹서버를 제공하니, EC2 인스턴스를 만들 때 인스턴스 구성 - 고급 세부 정보 란에 아래 스크립트를 참고해 입력한 뒤 생성하면 별도의 설정 없이 웹서버를 구동시켜볼 수 있습니다.
#include https://kr-id-general.workshop.aws/sh/start.sh
로드밸런서 설정
로드밸런서를 통해서 트래픽을 적절히 분배해보도록 하겠습니다. 대개 서비스를 할 때는 HTTP나 HTTPS 트래픽을 사용하게 될 텐데요, 로드밸런서를 설정할 때 ALB(Application Load Balancer)를 선택해줍니다. 그리고 이번엔 두 개의 서로 다른 퍼블릭 서브넷(A와 C)이 존재하므로 인터넷 경계 스키마를 선택하고, 네트워크를 매핑해줍니다. 우리가 생성한 VPC를 선택하면 포함된 가용 영역이 나타나는데요, 아까 생성된 두 개의 서브넷이 나타날 겁니다. 우리는 두 서브넷 모두를 사용할 것이므로 선택을 해주도록 합시다.
그러고 나서는 다시 보안 그룹입니다. EC2를 만들 때 생성했던 보안 그룹이 있지만, 그것은 인스턴스가 잘 생성되었는지 테스팅하는 용도로 잠시 사용했던 것이니 새롭게 하나 더 만들어줍시다. 편의상 alb-sg라고 부르겠습니다. 로드밸런서는 ssh 접속 같은 것은 필요하지 않으니까 HTTP - Anywhere-IPv4를 선택해서 모든 IP에 대해 80 포트만 개방해줍니다.
보안 그룹이 생성되었다면 다시 로드밸런서 설정창으로 넘어와서 방금 생성된 보안 그룹을 선택하면 됩니다. 그러고 나서는 리스너 및 라우팅 설정을 해주어야 하는데, 이 친구의 역할은 80 포트로 들어온 트래픽을 감지해서 적절한 작업을 수행하도록 라우팅 해주는 것입니다. 여기서는 대상 그룹을 생성해서 두 개의 인스턴스 모두를 넣어주도록 합니다.
그냥 선택만 하면 안 되고 반드시 '아래에 보류 중인 것으로 포함' 버튼을 통해 대상에 넣어주어야 합니다. 생성이 되었다면 다시 로드밸런서 설정창으로 돌아와서 해당 그룹을 선택하면 완료입니다. 이제 저 인스턴스들은 로드밸런서로부터의 트래픽을 받을 수 있게 되었습니다. 그 말은 곧 직접 80 포트로 트래픽을 받을 일이 없다는 뜻이기도 합니다. EC2 인스턴스들의 보안 규칙을 수정해줍시다.
인바운드 규칙에서 기존에 있던 HTTP 트래픽을 삭제한 뒤, 새로운 규칙을 추가해서 다시 HTTP 유형을 선택한 뒤, 이번에는 로드밸런서에서 생성해 주었던 보안 그룹을 선택해줍니다. 아까 alb-sg로 생성한 그룹이요. 그러고 나면 잠시간 로드밸런서가 프로비저닝으로 표시되다가 활성 상태로 바뀌게 되고 로드밸런서를 사용할 수 있게 됩니다. 테스트를 하기 위해서 로드밸런서의 DNS 이름을 복사해 브라우저에 넣어봅니다.
이렇게 번갈아가면서 웹서버가 나타나는 것을 확인했다면 끝입니다.
Auto Scaling?
오토 스케일링을 사용하면 이와 같은 작업을 자동으로 하도록 설정할 수도 있습니다. 가령 여러 대의 서버 중 하나에 장애가 발생했을 때 해당 인스턴스를 자동으로 교체해 준다거나, 트래픽이 너무 과하게 몰리면 일시적으로 서버를 증설한다거나 하는 방식으로 유연하게 인스턴스를 시작/종료할 수 있도록 해줍니다. 이것을 하기 위해서 AMI와 템플릿이 필요합니다.
간략히 설명하면 아까 전에 로드밸런서에서 설정해주었던 타깃 그룹에 들어가서 등록된 인스턴스를 모두 제거한 뒤, Auto Scaling Group탭에 들어가 스케일링 그룹을 새롭게 생성합니다. 템플릿과 AMI를 넣어주고 VPC와 서브넷을 선택한 뒤에, 고급 옵션 구성에서 기존 로드 밸런서에 연결을 선택하고 타깃 그룹과 연결해줍니다. 해당 그룹에는 현재 인스턴스가 없습니다.
이제 원하는 용량과 최소, 최대 용량을 설정하고 조정 정책에서 평균 CPU 사용률에 따라서 조정하도록 설정해줍니다. 혹은 평균 네트워크 입/출력에 따라 설정해줄 수도 있습니다.
이렇게 하면 우리가 정해둔 한도 내에서 인스턴스가 늘어나기도 하고 줄어들기도 하는 것을 볼 수 있습니다.
Reference
이번 글은 대부분 AWS Builders에서 제공하는 튜토리얼을 바탕으로, 초심자분들이 이해하기 어려운 부분들에 대해 보충설명을 하는 방식으로 작성되었습니다. 부족한 정보가 있다면 해당 글을 참조해보시면 더욱 친절하고 자세하게 설명이 나와있을 겁니다.