IM8(아임에잇) 오토스케일링 적용기

안녕하세요. 이음소시어스 개발팀 서버개발자 육승찬(루)입니다.

오늘은 이음소시어스의 핫한 서비스 “IM8(아임에잇)“의 오토스케일링 적용경험을 공유하려고 합니다. 먼저 오토스케일링에 대한 이야기를 하기 앞서서, 아임에잇이 어떤 서비스인지 간단하게 설명하고 시작하겠습니다.

IM8 (아임에잇) ?

직장인을 위한 프리미엄 소개팅 서비스

im8_1

IM8은 2013년 10월에 런칭되어 “까다로운 신원인증으로 높은 매칭 신뢰도를 주자”를 목표로 열심히 발전해 왔습니다. IM8의 8은 8개의 회원 타입(스마트커리어비주얼유니크글로벌밀리언패밀리액티브)을 의미합니다.

im8_2

현재 아임에잇의 모든 서버는 AWS를 통해서 운용하고 있습니다. 그럼 본격적으로 AWS x IM8 오토스케일링 적용기를 공유해보겠습니다. GOGO~

기존 서버

처음에는 IM8 API 서버를 EC2(t2.medium) 한대로 운영해왔습니다. 이후 트래픽의 증가에 따라 ELB에 EC2(t2.medium) 서버 2대를 붙여 운영하는 구조로  발전했습니다. 하지만 점점 더 트래픽이 증가하면서 피크 시간대에 서버가 터지는 일이 발생하기 시작했습니다. 그래서 현재 서버구조의 문제점을 정리하고 문제점을 개선하기로 결정했습니다.

서버 증설 방법

1. ELB에 서버를 더 붙이자 OR 서버의 스팩을 올리자 !

하루 두 번 푸시가 갈 때 아임에잇에 가장 접속자가 많이 몰립니다. 왜냐하면, 실제 매칭이 되는 시점에 사용자가 들어와서 상대방의 프로필을 확인하는 구조이기 때문입니다. 그래서 일반시간대에는 많은 서버가 필요 없습니다. 이 방법의 장점은 적은 시간 안에 문제를 해결할 수 있다는 점입니다. 하지만 비용적인 측면에서 굉장히 안 좋다고 판단했습니다. 접속자가 많지 않아도 항상 여러 대의 서버가 띄워져 있고 비용을 계속 지불하기 때문입니다.

2. AutoScaling (v)

접속자가 별로 없는 시간에는 최소한의 서버를 유지하고 피크 시간대에 여러 서버를 유지하는 방법입니다. 하루 두 번 피크가 있는 아임에잇에게 아주 좋은 방법이라고 생각합니다. (대부분 서비스에 좋지 않을까하는 생각이.. :D ) 평상시에는 최소한의 서버를 유지하기 때문에 비용적인 측면에서도 굉장히 유리했습니다. 그래서 이번 기회에 아임에잇에 AutoScaling을 적용해보기로 했습니다.

AutoScaling 준비하기

  • 결제서버 분리
  • 통일된 인스턴스 만들기
  • Scaling되는 서버를 항상 최신으로 유지하기
  • Scaling Rule 정하기
  • 서버를 띄우는 시간이 있기 때문에 푸시가 나가기전에 미리 띄우기 (Pre-warm)

1. 결제서버 분리

아임에잇은 모바일과 웹에서 PG서비스를 붙여서 결제할 수 있도록 제공하고 있습니다. 특정 PG는 요청 가능한 서버의 IP를 제한하고 있는 경우가 있어서 결제서버를 분리해야 했습니다. 기존 서버에서 사용하던 IP를 결제서버에 붙이고 내부에서만 통신 가능한 결제서버를 만들었습니다.

  • 기존 서버구조
기존 서버 구조

기존 서버 구조

  • 결제서버를 분리한 구조
새로운 서버 구조

새로운 서버 구조

2. 통일된 인스턴스 만들기

AWS에서 제공하고 있는 오토스케일링 기능은 미리 정의한 규칙에 따라서 인스턴스가 띄워지고 내려가는 형태로 동작합니다. 인스턴스는 AutoScalingGroup에 등록해놓은 AMI를 이용하여 띄우게 됩니다. 원래 사용하고 있던 서버 2대는 완전히 같은 인스턴스가 아니였습니다. 하나를 나중에 띄웠기 때문에 시스템 라이브러리 같은 경우 조금씩 버전이 달랐습니다. 그래서 이번 기회에 통일된 인스턴스를 만들고자 했고, 구조는 아래와 같습니다.

server

  • 시스템 라이브러리 설치 (ex. git)
  • API Rails App 설정
  • Puma 설정
  • Nginx 설정
  • Papertrail 설정 (로그 수집)

3. 서버를 항상 최신으로 유지하기

오토스케일링 되고있는 서버들은 항상 최신의 코드를 유지해야 하고 같은 응답을 줄 수 있어야 합니다. 아임에잇은 Git으로 소스코드를 관리하고 배포에는 Capistrano를 사용합니다. 지금까지는 서버 2대만을 최신으로 유지하면 됐기 때문에 아래의 순서로 배포를 해왔습니다.

  • Git fetching
  • whenever에 등록된 스케줄링 crontab에 등록
  • Puma Reload

오토스케일링을 적용하기 시작하면 서버가 딱 몇 대라고 가정할 수 없습니다. 그래서 모든 서버를 항상 최신으로 유지하기 위한 아래 두 가지 정리해봤습니다.

  • EC2 Instance가 시작되는 시점에 최신으로 만들기

EC2 설정 중에 “User Data“라는 부분이 있습니다. 인스턴스가 띄워지는 시점에 명령어를 실행시킬 수 있도록 할 수 있습니다. 여기서 소스코드를 최신상태로 유지하고 puma를 띄우는 등의 명령을 할 수 있습니다. 이렇게 하면 스케일링 돼서 실행되는 서버도 최신코드를 유지할 수 있게 됩니다. 쉽고 빠르게 모든 서버의 최신상태로 유지할 수 있지만 매 서버가 띄워질 때마다 Ruby 라이브러리 설치(bundle install)하기 때문에 서버가 띄워지고도 최신상태로 유지하는데 시간이 더 걸린다는 단점이 있습니다.

  • 최신의 AMI를 사용하기

이 방법은 미리 최신의 AMI를 항상 유지하고 서버가 띄워지는 부분에 대해서는 신경을 쓰지 않아도 됩니다. 코드를 한 번만 최신으로 유지하면 되고 라이브러리 설치 시간도 매우 줄일 수 있다는 장점이 있습니다. Ruby 라이브러리 중에 ELBAS라는 라이브러리가 있습니다. Capistrano와 연동되어 배포시 실행되고 있는 인스턴스를 최신으로 만들어주고, AMI까지 만들어주는 아주 좋은 녀석입니다… 이 라이브러리를 사용하면 빠르고 쉽게 항상 최신의 AMI를 유지할 수 있습니다.

4. Scaling Rule 정하기

처음에 AutoScalingGroup만 만들면 아무리 기다려도 서버는 스케일링 되지 않습니다… 그래서 어떤 규칙에 의해서 스케일링 할 건지 정해줘야 합니다. 먼저 AutoScalingGroup 설정을 보시면 “Instances“, “Desired“, “Min“, “Max“가 있습니다. Instances는 현재 서버의 개수, Min은 최소 서버 수, Max는 최대 서버 수를 의미합니다. Desired는 스케일링이 돼서 현재 몇 대를 희망하고 있는지를 의미합니다. Desired와 Instances의 수가 같으면 더는 서버를 띄우거나 내릴 필요가 없다는 의미입니다.

아임에잇에서는 서버를 띄우는 규칙 2지와 서버를 내리는 규칙 2가지를 사용하고 있습니다.

  • Add 1 instance (CPUCreditBalance < 9)

10분안에 CPUCreditBalance의 수치가 9 미만이라는 알람 두번이 울리면 인스턴스를 띄워라!

이 규칙은 CPUCreditBalance 수치에 따라서 동작하게 됩니다. 아임에잇 서버는 현재 t2계열의 인스턴스를 사용하고 있습니다. T2계열의 인스턴스에는  CPUCredit라는 개념이 존재합니다. 크레딧이 부족하면 CPU 연산 능력이 매우 떨어지기 때문에 새로운 서버 한 대를 띄우도록 하고 있습니다.

  • Add 2 instances (CPUUtilization >= 60)

2분안에 CPUUtilization의 수치가 60% 이상이라는 알람 두번이 울리면 인스턴스를 띄워라!

평소에는 CPU 사용률이 평온하다가 피크시간이 되면 갑자기 막 올라갑니다. 그래서 CPU사용률이 60% 이상이 되면 인스턴스 2대를 띄우도록 하고 있습니다. (피크시간이 아니면 올라갈 일이 거의 없기 때문)

  • Delete 1 instance (CPUUtilization < 25), Delete 2 instances (CPUUtilization < 15)

1분에 한번씩 CPU 사용률이 낮다는 알람 10번이 울리면 인스턴스를 내려라 !

피크시간이 지나고 나면 급격히 사용률이 떨어지기 때문에 인스턴스를 내리기 시작합니다. 하지만 인스턴스를 내리는 옵션을 상당히 까다롭습니다. 알람이 울리는 10분은 같지만 연속적으로 10번이 울려야 하기 때문입니다. 이유는 인스턴스를 내려도 되는 상황인지 확실시 하고 싶었기 때문입니다. 대게 인스턴스를 띄워서 생기는 문제보다 내리면서 생기게 되는 문제가 많기 때문입니다..

5. Pre-warm

아마 대부분의 프로그래머분들은 장애를 원하지 않을 것 입니다. 이음소시어스 개발팀도 장애가 나지않게 하기 위해서 노력을 하고 있습니다. 아임에잇 서비스의 경우 12:30, 19:00에 푸시를 보내고 있습니다. 실제로 푸시를 보내고 나서 오토스케일링 룰에 따라 서버를 띄우기 시작하면 대처가 좀 늦습니다. 갑자기 들어오는 트래픽을 버티지 못하고 아예 서버 한대가 죽어버리는 일도 있었습니다. 그래서 12:20, 18:50에 서버를 미리 띄워놓고 있습니다.  서버를 미리 띄우는 코드는 Python으로 작성했고 Crontab에서 실행되도록 하고 있습니다.

 

정리

이번 포스팅에서 아임에잇의 오토스케일링 적용 경험을 적어보았습니다. 사실 이번 포스팅을 작성하면서 너무 뻔한 글이 되지 않을까 걱정이 많았습니다. 이미 오토스케일링에 대한 글도 많고 참고할 부분도 많아서 잘 쓸 수 있을지 고민이 되었기 때문입니다. 그래서 더 자세히, 숨김없이 써보려고 노력했습니다.

오토스케일링을 적용하면서 가장 크게 얻은 두 가지는 비용절감과 불안감이 사라졌다는 것입니다. 기존 서버 비용 보다 45%의 비용을 절감할 수 있었습니다. 그리고 평소보다 가입자가 많은 날은 트래픽에 서버가 죽을까 하는 불안감이 있었습니다. 오토스케일링이 만병통치약은 아니지만 룰에 의해서 확장하고 수축하는 구조 덕분에 더 많은 트래픽을 커버할 수 있게 되어 불안감이 해소되었습니다.

마치며..

이번 오토스케일링을 사용하면서 ELBAS라는 라이브러리가 참 좋다고 느꼈습니다. 너무 쉽게 AMI를 최신으로 유지할 수 있는 방법을 제공해줬기 때문인데요. 그래서 이 라이브러리의 핵심적인 부분을 파이썬 코드로 작성해봤습니다 (파이썬을 오래 쓰다보니 재밌는건 파이썬으로 구현해보고 싶은 맘이 생기네요..)

 

 

  • Hyeon

    안녕하세요. 오토스케일링 검색하다가 사용법은 대충 알겠는데 기존에 사용하던 EC2 인스턴스를 어떻게 연동하나 궁금해서 댓글로 여쭤봅니다.