Skip to content

GCP위에서 자동으로 서버 100대 운영해보기

안녕하세요. Harrison Jung입니다.

이번에 블랙데이에는 간단한 외주 작업을 했었습니다. 간단한 이벤트를 웹상에서 구현하는 일이었는데요. 처음의 의도와는 다르게 많은 서버를 다루게 되어 관련된 사항을 블로그에 올려볼까 합니다.

프로젝트의 개요는 이랬습니다. 사용자들이 웹 페이지에 접속하면 사용자의 이름을 입력하고 추첨 버튼을 누르면 실시간으로 사용자의 이름이 들어간 결과물을 출력하는 작업이었습니다. PHP에서 GD를 이용하여 간단한 이미지 파일을 다루는 작업이었습니다만, 아무래도 이게 실시간으로 이미지를 다뤄야 하다보니 CPU를 상당히 많이 먹는 문제가 있었습니다. 처음엔 그냥 이렇게 크게 많은 사람이 사용하지 않겠거니 하고 간단히 설계한 시스템이었는데, 중간에 갑작스럽게 시스템을 추가해야 하는 거라서, 기능을 추가하면서 설계를 바꿔야 하는 그런 상황이었죠.

 

위의 스크린샷은 피크타임때를 지났을때의 화면입니다 (…)
피크타임때 활성사용자수는 2만을 넘어갔고 분당 이미지 처리수는 약 10만에 달했습니다.

당연히 한두대의 서버로 해결이 거의 불가능한 상황이었죠.
다행히 애초에 Google Cloud Load Balancer 에 연결해 놓은 상황이었고, 해당 시스템은 독립된 인스턴스 그룹으로 묶여 있었습니다. ( 아쉽게도 오토스케일링은 되질 않더라구요.)

그래서! 몇가지 작업을 통해 적은 비용으로 위의 처리를 할 수 있도록 시스템을 수정을 했습니다.

  1. 각 서버들은 n1-standard-1 ( 1vCPU / 3.75GB Ram ) 으로 된 머신들로 통일 했습니다. 유동성 있게 대응하려면 멀티 코어보다는 오히려 낮은 코어의 서버로 관리하는게 좀 더 자유로울꺼 같았습니다.
  2. 메인 컨트롤을 해야 하는 1번 서버를 제외하고 나머지 보조 서버들은 “선점형 요금제” 서버를 선택하였습니다. 선점형 요금제를 사용하게 되면 해당 서버는 최대 24시간동안 사용이 가능하고 혹은 언제 갑자기 종료될지 예상이 되지 않지만 지속성있는 프로세스가 아닌 웹서버의 경우에는 괜찮다 판단이 되었습니다. 대신에 요금이 매우 저렴합니다. 참고로 n1-standard-1 을 선점형으로 사용하게 될경우 시간당 0.023$ ( 26원 ) 에 불과합니다. 심지어 구글의 요금 시스템은 시간당이 아니라 분당 요금제로 계산이 됩니다. 따라서 만약에 10분 가량만 사용하게 될경우에는 4.3원에 불과합니다.
  3. 각각의 서버들의 상태를 일일이 체크해서 평균을 내는게 제일 좋지만 그렇게 개발하기에는 시간이 모자랐으므로 메인 서버의 현재상태만 5분단위 평균을 내서 관리하는걸로 적당히 타협했습니다. 실제로 사용할 경우에는 5분 단위로 모든 서버의 평균을 내는게 좋다고 봅니다.
  4. 각 서버를 관리하는 방법은 node.js 를 이용하여 google cloud npm 을 활용하였습니다. 오늘의 포스팅은 이게 핵심입니다.
  5. 3번에서 말한대로 일정 점유율을 넘어가거나 혹은 일정 수준이하로 내려가면 자동으로 조절하도록 스크립트를 작성하였습니다. 예를들면 5분 평균이 35%를 넘어가면 1분단위로 서버를 한대씩 늘리고, 25% 이하가 되면 1대씩 줄이는 방법을 사용했습니다.
  6. 새로운 서버를 그냥 만들어서는 의미가 없으므로 1번 서버를 스냅샷을 떠서 그 스냅샷을 활용했습니다.

위의 방법을 이용하여 관리를 하다 보니 피크 타임때는 100대 가량의 서버가 실시간으로 동작하게 되었고 서버 폴트등의 문제는 보고되지 않았습니다.

위의 방법으로 관리하다 보니 서버가 마구 늘어났고, 사실, 서버가 30대가 넘어가면 인스턴스 목록에 탭이 생기는것을 처음 알았습니다. ( 그동안 그렇게 많은 댓수를 쓸일이 없다 보니.. )

그럼 실제로 과정을 보도록 하겠습니다.

우선 자동으로 서버를 생성하려면 원본이 있어야 합니다. 모든게 설정되어 있고, 해당 소스가 있어야 하고, 서버가 부팅되면 자동으로 모든게 이뤄질 수 있는 원본이 필요한데, 그 원본은 1번 서버의 스냅샷을 통해서 해결했습니다. GCP위에서 해당 인스턴스에 들어가면 디스크에 관련된 부분을 볼 수 있는데, 해당 디스크를 스냅샷으로 복제해놓고 해당 스냅샷을 이용하여 동일한 설정, 소스코드를 가지고 있는 서버를 구성한것입니다. 실제로 서비스용도로 사용할 경우에는 Git Repo에서 가져오는 부분들이라던가 좀 더 세세한 기능이 필요하겠지만, 이벤트용으로는 이정도로 충분할 것입니다.

다음으로 해당 스냅샷을 통해서 실제 서버를 구성하는 부분은 상당히 많은 옵션을 설정해야 합니다. 그래서 구글에서는 REST API를 다루는 부분을 통해서 옵션을 복!붙! 할 수 있도록 해놨습니다.

대부분의 뭔가를 생성하는 페이지에는 하단에 위와같은 부분이 있습니다. REST 버튼을 눌러보면 json형태로 되어 있는 옵션이 있는데 이 부분을 가져다가 소스코드에 옵션을 넣어야 하는 부분에 넣으면 됩니다. 자세한 부분은 코드 설명시 다시 하도록 하겠습니다.

다음으로 각각의 이벤트에는 생성 이벤트와 On ready 이벤트가 각각 발생됩니다. 예를들어서 디스크를 생성하겠다는 명령뒤에는 생성되었다는 이벤트가 발생하지만 바로 사용이 가능한것이 아닙니다. 실제로 사용을 하려면 On Ready 가 되어야 가능합니다. 예를들어서 디스크를 생성하고 준비 되면 그 다음에 VM머신에 붙일 수 있고 VM머신에 붙이고 해당 머신이 생성되고 준비 되면 그 다음에 준비된 후에 인스턴스 그룹에 붙일 수 있습니다. 그제서야 Load Balancer가 해당 머신으로도 트래픽을 보내기 시작합니다.

또한 선점형 인스턴스의 특징중의 하나인데, 언제 종료될지 모릅니다… (……! )

따라서 중간 중간 체크해서 종료된 인스턴스는 다시 부팅을 해주는 명령을 해줘야 합니다.

CPU의 사용율이 낮아져서 남게되는 인스턴스는 1번을 제외한 오래된 인스턴스부터 종료해주면 됩니다. 최소 과금단위가 10분이상 1분단위이므로 가장 오래된 서버는 10분을 넘었을 가능성이 높거든요. 따라서 오래된 서버 부터 종료시키고 삭제를 시킵니다.

그럼 소스코드를 보도록 하겠습니다. 가능한 주석은 코드안에 통합해서 넣었습니다.

 

 

생각보다는 예외처리가 되어 있지 않습니다.
개념을 이해하는 수준에서 보아주시고, 실제로 사용시에는 꼭 예외 처리를!

Be First to Comment

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.