Notice
Recent Posts
Recent Comments
Link
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
Archives
Today
Total
관리 메뉴

사부작사부작

[인프라 구성] 분산 환경 및 배포 자동화 구축 본문

프로젝트

[인프라 구성] 분산 환경 및 배포 자동화 구축

민철킴 2023. 5. 4. 19:56

이 글은 토이 프로젝트를 만들며 사용된 AWS 서비스들의 역할과 배포 흐름을 써보려 합니다. 더불어 왜 oAuth 인프라를 분리했는지도 마지막에 다루겠습니다. 틀린 설명이 존재할 수 있습니다. 발견하시면 피드백 부탁드립니다. 
토이 프로젝트 :  books4dev.me

<인프라 설계도>

2개의 Availity Zone(AZ)으로 나눈 Multi AZ로 구성을 했다. 각 AZ마다 운영에 사용되는 서버를 배치했다. 그리고 Load Balancer를 둬서 각각 서버가 다른 요청을 처리하게 했다. 즉, 분산 환경이다. 2대의 웹 애플리케이션 서버(WAS)를 기본적으로 운영하고 있으며, Auto Scaling을 이용하여 필요에 따라 서버를 동적으로 확장할 수 있도록 구성했다. 각각의 WAS들은 도커 위에서 운영중이다.

Single AZ으로 구성하면 관리가 용이하고 비용면에서 이득이 있다. 하지만 단일 장애 지점(SPOF)으로 AZ에 장애가 발생하면 원활히 작동하지 않을 가능성이 높다.

단일 서버 운영의 단점도 있고 분산환경에서 운영을 해보고 싶었기에 위와 같이 구축했다. 또 배포 자동화도 처음 구축해봤다.

VPC(Virtual Private Cloud) : AWS에서 제공하는 가상 네트워크 서비스다. VPC를 생성한다는 의미는 하나의 AWS Region내에 네트워크 대역을 구성한다는 의미를 가진다.


인터넷 게이트웨이
 : 인터넷과 VPC의 Public Subnet 사이의 통신을 가능하게 해주는 게이트웨이다.


NAT(Network Address Translation) Instance
 : Private Subnet을 외부 인터넷에 연결시켜주는 역할을 한다. Public Subnet에 위치해, 인터넷 게이트웨이와 통신한다. Private과 Public 간의 통신을 중계해 준다. 처음엔 NAT Gateway를 사용했지만 내 경우엔 하루에 3천 원 정도 비용이 나왔다. NAT Instance는 EC2 프리티어로 만들어서 비용이 훨씬 저렴하다. 게이트웨이가 관리가 편하고 단일 장애 지점도 없다. 하지만 트래픽이 적은 토이 프로젝트라면 NAT Instance도 무방하다.


Bastion Server :
 ssh로 터미널 접속을 하여 서버 관리를 하는 경우에 활용하는 서버다. 외부로부터 보호된 네트워크에 접근하기 위한 게이트웨이 역할을 한다. 이 서버를 통해 외부에서 접근이 불가한 Private Subnet의 EC2에 접속한다. 인터넷 게이트웨이를 통과하는 일반 사용자의 트래픽과는 무관하다. 나는 중지해 두고 필요할 때만 켜서 사용 중이다.

프론트엔드 배포

내가 선택한 방법은 가비아에서 도메인을 사고 이걸 Route53에 연결했다. 그리고 S3에 Vue빌드 파일들을 저장했다. 이 저장 컨텐츠를 CloudFront가 캐싱해서 프론트 서버 역할을 한다. 그리고 CloudFront 주소를 Route53 도메인에 연결해주면 된다.

S3 : 프론트엔드 정적 파일과 이미지 저장소로 사용한다.

CloudFront : 프론트엔드 서버 역할을 하며, S3에 올린 컨텐츠를 캐싱해서 CloudFront의 캐시 서버에 저장해 둔다. 요청이 들어올 경우, CloudFront서버에서 바로 제공되므로 S3에 접근하지 않아, 빠른 응답속도를 가진다.
Route53 : CloudFront와 S3에 배포된 정적 컨텐츠에 연결해주는 역할을 한다.

 

백엔드 배포 과정

젠킨스 서버

  1. 백엔드 코드를 Github에서 Pull 받고 빌드한다.
  2. 도커파일을 사용해 이미지를 만들어 DockerHub에 Push 하고 서버 내의 이미지는 삭제한다.
  3. 코드에 포함된 deploy.sh와 appspec.yml을 AWS S3 버킷에 올린다.

CodeDeploy

  4. S3에 올린 deploy.sh와 appspec.yml 파일을 블루/그린 방식으로 Auto Scaling 그룹에 배포한다. 

  5. CodeDeploy에 의해 사전에 구성한 Auto Scaling 그룹이 자동으로 시작되며, 시작템플릿으로 미리 설정한 EC2 인스턴스들이 배포된다.

  6. 배포된 EC2 인스턴스에서 deploy.sh 스크립트를 실행한다. 내 경우엔 이 스크립트를 DockerHub에서 Pull 받고 Docker를 이용하여 스프링 애플리케이션을 실행하도록 구성했다.

 

deploy.sh : 배포 파일을 실행하는 스크립트

appspec.yml : AWS CodeDeploy에서 사용되는 배포 구성 파일

Auto Scaling 그룹 : 여러 대의 EC2 인스턴스를 하나의 그룹으로 묶어서 관리할 수 있게 해 준다. 인스턴스의 최소 개수, 최대개수를 설정할 수 있다. CPU 사용률 등의 옵션으로 인스턴스의 추가 삭제를 자동으로 관리해 준다.

시작 템플릿 : EC2 인스턴스를 시작하기 위한 설정 파일

블루/그린 배포 : 기존 버전(블루)과 새로운 버전(그린)을 별도의 환경에 띄운 후 트래픽을 전환하는 방식. 내 상황에서 블루/그린 각각은 서로 다른 Auto Scaling 그룹이다. 배포마다 생성된 Auto Scaling 그룹이 바뀌는 것이다.

oAuth 전용 인증서버 분리

현재의 상황에서는 로드 밸런서가 외부의 요청을 여러 서버로 나눠서 보내주고 있다. 그렇기에 인증이 성공적으로 이루어지지 않는다. 로그인 시도를 하면 카카오 서버에서 내 서버로 요청이 들어온다. 정확히는 아래 사진처럼 요청을 주고 받는다.

 

하지만 카카오에 요청을 보내는 서버와 응답을 받는 서버가 다르면 로그인이 실패하고 에러가 발생한다. 

 

인증 처리만 담당하는 서버를 구축하고 서브도메인을 붙혀서 이 문제를 해결했다.

 

하지만, 위 해결책은 완전한 해결책은 아니다. 규모가 커지면 이 oAuth용 서버도 scale-out 해야 할 상황이 존재할 수 있다. 그때는 스티키 세션을 구축해서 해결할 수 있다.

 

스티키 세션 : 로드 밸런서에서 사용자의 세션 정보를 추적하여 요청이 들어올 때마다 동일한 서버로 요청을 보내는 기능