관리 메뉴

나는 문어~ 꿈을 꾸는 문어~

AWS 네트워크 구성하고 모델 서빙하기 (2) 모델 서빙 서버 생성 및 로드밸런서 사용 (EC2, ALB, Flask) 본문

MLOPS & 백엔드

AWS 네트워크 구성하고 모델 서빙하기 (2) 모델 서빙 서버 생성 및 로드밸런서 사용 (EC2, ALB, Flask)

harrykur139 2022. 10. 10. 11:14

이전 포스팅에서 AWS 리소스들을 이용해 VPC 네트워크를 구축했다. 이전 포스팅 링크는 다음과 같다.

https://harrykur139.tistory.com/29

 

AWS 네트워크 구성하고 모델 서빙하기 (1) 네트워크 구축 (VPC, Subnet, Internet gateway, NAT gateway, Route Tab

AWS를 처음 배웠을 때, EC2라는 서비스를 사용했다. 이 서비스는 그냥 데이터 센터에 있는 컴퓨터를 빌려쓰는 것이었고, 클릭 몇 번으로 만들 수 있었다. 클릭 몇 번으로 만들어진 이 인스턴스에

harrykur139.tistory.com

 

이 시리즈에서 완성할 네트워크 구조는 아래와 같다.

이번 포스팅에서 만들 리소스들이다.

  • EC2(Bastion server) : private subnet에는 직접 접근할 수 없게 네트워크를 설계했다. 이 곳에 접근하기 위해서는 public subnet을 통해 접근해야한다. 그러므로 해당 역할을 하는 EC2 서버를 만들어 이를 통해 private subnet의 리소스에 접근할 것이다.
  • EC2(Web server) : 실제로 외부로 서비스할 웹서버가 구동되는 EC2 인스턴스를 만들 것이다. 2개의 private subnet 각각에 1개씩 생성할 것이다.
  • Application Load Balancer : 하나의 엔드포인트로 두 개의 EC2 인스턴스로 부하분산을 하기 위해 필요한 리소스다.
  • 보안 그룹 : 외부에서 들어오는 요청을 허용하기 위해 2개의 보안 그룹을 만들 것이다. Bastion server를 위해 SSH 22번포트를 허용하는 보안그룹과, 로드밸런서를 위해 HTTP 80번 포트를 열어주는 보안그룹을 만들 것이다.

 

 

보안 그룹 생성

VPC 페이지에서 보안 그룹 탭을 클릭한 후 보안 그룹 생성을 클릭하자.

 

아래와 같이 이름을 설정하고 VPC를 생성한 VPC로 설정하자. 인바운드 규칙에서는 SSH를 모든 IP에 대하여 허용해주고 생성을 하자. (설명을 필수로 적으라고 하는데 그냥 디폴트랑 같이 적어도 된다.)

 

private subnet에 위치한 web server 용 ec2에 사용할 보안 그룹을 만들어주자.

 

 

아래와 같이 로드밸런서를 위한 보안그룹도 HTTP 규칙을 열어 생성해주자.

 

EC2 (Bastion server) 생성

AWS EC2 페이지에 들어가서 인스턴스 탭을 누르고 인스턴스 시작 버튼을 누르자.

 

이름을 입력하고 OS는 디폴트로 선택된 Amazon Linux를 그대로 사용한다.

 

키 페어는 기존의 것을 선택하거나 생성하고, 네트워크 설정은 편집을 눌러서 아래와 맞게 우리가 생성한 리소스들을 선택해준다. 외부에서 접속할 것이기 때문에 퍼블릭 IP 자동 할당은 활성화를 해주자. 그리고 인스턴스 생성 버튼을 눌러주자.

 

 

생성한 후 인스턴스 탭에서 방금 만든 인스턴스를 클릭해 퍼블릭 IP를 확인하고 이를 이용해 SSH 접속을 해보자.

접속이 잘 되는 것을 확인할 수 있다. 지금까지 생성한 VPC, 서브넷, 라우트테이블, 인터넷 게이트웨이 등의 많은 리소스를 적절하게 생성하였기에 EC2를 생성하고 접속할 수 있는 것이다.

 

 

EC2 (Web server) 생성

이제 두 개의 Flask 웹서버 전용 EC2 인스턴스를 생성할 것이다. 이 과정은 Bastion server용 EC2 인스턴스 생성 과정과 거의 같다. 우선 인스턴스 생성 버튼을 눌러서 들어가자. 이름은 my-web-ec2-1으로 입력하고 os는 아마존 리눅스로 하자.

 

네트워크 설정은 편집을 누른 후 VPC를 my-vpc로 선택하고, 서브넷은 첫 번째 private 서브넷으로 설정한다. private이기 때문에 퍼블릭 IP는 필요없으므로 비활성화를 선택하고, 보안그룹은 my-web-security-group을 선택한다. 그리고 인스턴스를 하나 만들어주자.

 

또 하나의 EC2 인스턴스를 만들어야한다. 이름은 my-web-ec2-2로 하고 네트워크 설정의 서브넷을 my-private-subnet2로 하여 만들어주자.

 

결과적으로 Bastion 까지 총 3개의 EC2 인스턴스가 생성된 것을 확인할 수 있다.

 

 

Private 서브넷의 EC2 접속하기

private 서브넷의 경우 Internet gateway와 직접 연결되어 있지 않기 때문에 public 서브넷의 bastion server를 통해 접속해야한다. 사실 bastion server가 이를 위한 서버이긴 하다.

 

현재 나는 윈도우에서 key 파일을 통해 bastion 서버에 접속하고 있다. bastion 서버에서 private 서브넷의 ec2에 접속하기 위해서는 윈도우의 파일을 bastion 서버에 넣어놓아야한다. scp 프로토콜을 사용하여 파일을 전송하자.

 

사실 bastion server를 통해 두 번 접속하지 않고 한 번에 private에 접속하는 것처럼 세팅할 수도 있지만 우선은 이렇게 하자. public과 private에 접속하는 key가 동일한 것도 별로 좋진 않은 것 같지만 우선은 그냥 하자. home 경로에 key를 저장하는 것도 별로 좋진 않은 것 같다. 근데 우선 그냥 하자.

scp -i keykey.pem keykey.pem ec2-user@3.36.52.70:~/

 

그리고 bastion server에 접속하여 ls 명령어로 키페어를 확인하자.

이제 file 권한을 안전하게 만들어주고 (이것을 하지 않으면 오류가 나면서 접속이 되지 않는다.) private 서브넷의 ec2에 접속해보자.

 

먼저 ec2의 private ip를 확인해야하는데 아래 화면에서 확인할 수 있다.

 

접속해보자. 접속이 되면 bastion server의 ip에서 private 서브넷의 ec2 ip로 바뀌는 것을 확인할 수 있다. 두 번째 ec2도 동일한 방법으로 접속이 가능하다.

 

ALB (Application Load Balancer) 생성

두 개의 private ec2로 향하는 요청을 분산하기 위해 로드밸런서를 생성해보자. 먼저 로드밸런서 생성을 클릭한다.

 

HTTP 요청을 처리할 것이기 때문에 Application Load Balancer를 클릭해주자.

 

이름을 입력해주고

 

네트워크 설정을 해준다. 이 부분은 로드밸런서를 VPC에 연결하는 부분이다. 따라서 두 개의 가용영역을 선택한 후 각각에 속한 public subnet을 선택해준다.

 

보안그룹은 이 전에 만들었던 alb의 보안그룹을 선택한다.

 

이제 로드밸런서의 요청을 받을 target group을 설정하기위해 create target group을 클릭하자.

 

이름과 포트를 바꿔주자. 5000은 로드밸런서가 EC2에 요청을 보낼 때 5000번 포트로 바꿔 보낸다는 뜻이다. health check path는 default인 /로 두자. 로드밸런서는 / 경로로 요청을 보내고 정상적 응답이 오면 EC2의 서버가 정상 가동하는 것으로 인식하고 요청을 처리하기 시작한다. 설정을 한 후 다음으로 넘어가자.

 

두 ec2 인스턴스를 클릭하고 Include as pending below 버튼을 누른 후 아래의 create target group 버튼을 눌러 target group을 생성한다.

 

다시 로드밸런서 생성 화면으로 돌아와서 새로고침을 누른 후 방금 만든 my-target-group을 선택한다. 그리고 최하단의 create load balancer를 클릭하면 로드밸런서 생성이 완료된다.

 

 

로드밸런서 작동 확인

로드밸런서에서 ec2의 5000번 포트로 요청을 하도록 세팅하였기 때문에 보안 그룹에서 5000번 포트를 열어줘야한다.

 

이제 두 EC2에 각각 접속해서 index.html 같은 파일을 만들어 아무 텍스트나 입력 후 저장하자. 그리고 다음 명령어로 간단한 http 서버를 5000번 포트로 열어보자.

python -m SimpleHTTPServer 5000

 

 

두 서버에서 모두 정상적인 요청 처리가 이루어지는 것을 확인할 수 있다.

 

target group을 확인해보면 두 서버 모두 health check가 완료된 것을 알 수 있다.

 

 

Flask로 모델 서빙

서버 코드는 이전의 포스팅들에서 사용했던 코드를 재탕하기로 하자. 코드 링크는 다음과 같다.

https://github.com/euiraekim/flask-model-serving

 

위 코드의 health check 경로는 /가 아니라 /health이므로 이 부분 설정을 수정하자.

 

이제 각 서버에 접속하여 아래 명령어들을 입력해 서버를 실행하자. 이 포스팅은 네트워크 구축이 주 목적이므로 도커 설치나 도커를 통한 flask 실행 등은 하지 않는다. 그냥 개발서버를 띄울 것이다.

sudo yum install git # git 설치
git clone https://github.com/euiraekim/flask-model-serving.git # 클론 레포지토리
cd flask-model-serving # 폴더 변경
pip3 install -r requirements.txt # 패키지들 설치
python3 app.py # flask 앱 실행

 

명령어를 모두 실행하면 아래와 같이 health check 요청이 오는 것을 확인할 수 있다.

 

 

이제 드디어 마지막으로 로드밸런서에 요청을 보내보도록 하자. 우선 아래 빨간 네모칸에서 로드밸런서의 도메인 네임을 확인할 수 있다. 저기로 요청을 보내보자.

 

postman을 이용하여 오청을 보내봤다. 네 개의 입력값을 보낸 결과, virginica 클래스라고 올바르게 예측 값을 응답하는 것을 확인했다.

 

postman에서 send를 마구마구 광클하면 아래와 같이 두 서버에서 요청을 번갈아 처리하는 것을 알 수 있다.

Comments