Skip to content

무중단 배포 도입기

ohjoohyung edited this page Oct 5, 2021 · 5 revisions

무중단 배포 도입기

보고 또 보고 서비스의 백엔드 서버는 로드 밸런서 뒤에서 두 인스턴스로 운영되고 있다.
로드 밸런서는 두 인스턴스를 upstream 서버로 보고, 요청을 보낸 클라이언트의 ip를 기반으로 어떤 서버에 해당 요청을 보낼지 결정한다.
그런데 만약 요청을 보낼 서버가 내려가 있는 상태면 다른 서버로 그 요청을 전달한다.

Jenkins는 배포를 진행할 때 이 두 서버에 차례대로 들어가서 기존의 애플리케이션을 종료하고, 새로 만든 jar 파일을 이용해서 애플리케이션을 실행한다.
이것을 Rolling Deployment 방식이라고 한다. (Rolling Deployment 방식은 다양한 방법으로 구현할 수 있다.)

즉 지금 우리 인프라 구조는 사실 이미 무중단 배포가 자연스럽게 적용된 상태였다.

고려한 부분

Rolling Deployment 방식으로 배포를 진행하면 어느 한 서버가 잠시 내려가 있어도 다른 서버가 부하를 감당하기 때문에 다운 타임이 없다.
하지만 이 Rolling Deployment 방식에는 몇 가지 아쉬운 점이 있다:

  • 특정 서버에서 새로운 애플리케이션을 실행할 때 다른 서버에 부하가 집중된다.
  • 애플리케이션이 실행되지 않고 문제가 발생하면 롤백을 할 수 없다. 기존에 돌아가고 있던 애플리케이션을 종료하기 때문이다.
  • 런타임 문제가 발생하면 애플리케이션을 직접 다시 실행해야한다.

그래서 Rolling Deployment 방식을 조금 변형해서 도입해보았다.

도입 후 현재 배포 흐름

  1. Jenkins가 jar 파일을 빌드한다.
  2. 첫번째 서버에 ssh 프로토콜로 들어가서 현재 애플리케이션이 실행되고 있지 않은 다른 포트에 새로운 애플리케이션을 실행한다.
  3. 잘 실행되고 있는지 health check를 한다.
  4. Health check에 성공하면 다른 서버로 ssh 한다.
  5. 두 번째 서버에서도 기존 애플리케이션이 실행되고 있지 않은 포트에 새로운 애플리케이션을 실행한다.
  6. 잘 실행되고 있는지 health check를 한다.
  7. Health check에 성공하면 로드 밸런싱을 하고 있는 리버스 프록시로 ssh 한다.
  8. 리버스 플록시가 바라보고 있는 포트를 바꾸고, 바뀐 설정을 적용하기 위해 reload 한다.

즉, Rolling Deployment 방식인데 따로 애플리케이션을 실행하고, 모두 잘 작동하는지 확인 후에 포트를 바꾼다는 점이 특이한 부분이다.

해당 방식을 사용하면 다음과 같은 장점이 있다:

  1. 새로운 애플리케이션에 문제가 발생해도 기존 애플리케이션이 잘 돌아가고 있는 상태다.
  2. 다른 서버가 부하를 모두 감당하지 않아도 된다.
  3. 기존 애플리케이션으로 쉽게 롤백 할 수 있다.

구체적인 방법

/infra/port api

현재 애플리케이션이 어떤 포트에서 실행되고 있는지 알려주는 api를 만든다.
8080 포트에서 애플리케이션이 실행되고 있으면 8000 포트를 쓰고,
8000 포트에서 실행되고 있으면 8080 포트에 새로운 애플리케이션을 실행한다.

/infra/health api

현재 애플리케이션이 잘 실행되고 있는지 확인할 수 있는 api를 만든다.
애플리케이션을 실행시키고 10초후부터 30초동안 1초 간격으로 해당 api에 요청을 보낸다.
만약 'UP’이라는 응답이 돌아오면 애플리케이션이 잘 작동되고 있다고 보고 Jenkins에서 해당 서버와 ssh 를 종료한다.

nginx 리버스 프록시

리버스 프록시 역할을 하고 있는 엔직엑스 설정을 두 개 준비한다. (nginx.conf, nginx2.conf)
하나의 설정 파일은 두 upstream 서버의 8080 포트를 바라보도록 하고, 다른 하나는 8000번 포트를 바라보도록 한다.
그리고 배포할 때마다 알맞는 설정 파일을 사용하여 nginx를 reload 한다. (nginx는 동적으로 reload 할 수 있어서 변경된 설정이 바로 적용된다.)

  • 8080 포트와 8000 포트를 사용한 이유는 현재 ec2 보안 설정에서 이 두 포트에 대한 접근을 허용한 상태이기 때문이다.
  • 설정 파일을 두 개로 나누고 번갈아 가며 사용한 이유는 Nginx 설정을 변경하는 것 중, upstream 서버들의 포트 번호를 바꾸는 것보다 이렇게 두 개의 파일을 바꿔가며 쓰는 것이 훨씬 빠르고 간편해서다.

develop 서버

develop 서버에는 production 환경에 도입하기 전에 시험삼아 적용했고,
실제 production 환경에 도입하기 전에 시험삼아 적용했던 것이라 다시 되돌려 놓았다.
develop 서버의 역할이 예상하지 못한 에러를 찾는 것이라고 생각했기 때문이다.
그리고 부하를 분산시킬 이유도 없기 때문에 오버엔지니어링 느낌도 있다.

Clone this wiki locally