본문 바로가기
삽질 보고서

우리도 무중단 배포 할래요.

by 프람6 2024. 10. 27.

무중단 배포 도입 계기

배포를 할 때마다 시스템이 작동하지 않는 다운타임 이 발생하고, 다운타임 이 발생할 경우 사용자 경험을 저하시키게 됩니다.

이러한 이유로 서비스를 중단하지 않고 새로운 버전을 배포하는 무중단 배포를 도입하게 되었습니다.

무중단 배포 방식 선택 기준

무중단 배포 방식에는 여러가지가 존재하는데요, 그 중 대표적인 방식에는

  • Rolling
  • Blue/Green
  • Canary

가 있습니다.

세가지 배포 방식을 간단하게 설명하겠습니다.

Rolling 배포는 트래픽을 점진적으로 구버전에서 신버전으로 이동시키는 방법입니다.

Blue/Green 배포는 트래픽을 한번에 구버전에서 신버전으로 이동시키는 방법입니다.

Canary 배포는 트래픽을 점진적으로 구버전에서 신버전으로 이동시킨다는 점에서 Rolling 배포와 비슷합니다. 그러나 소수 인원을 대상으로 신버전을 일정 기간동안 운영하면서 이상이 없는지 확인한 후 모든 트래픽을 신버전으로 이동시킨다는 특징이 있습니다.

결론을 먼저 말하자면, 코딩해듀오는 Ngnix Docker를 활용한 Blue/Green 배포를 선택했습니다.

무중단 배포 방식을 Blue/Green으로 결정하게 된 과정을 기존 배포 방식과 비교하며 설명하겠습니다.

 

기존 인프라 구조

 

위 사진은 저희 서비스의 대략적인 운영 인프라 구조입니다.

운영 서버 EC2는 총 2개의 웹서버를 인스턴스 A, 인스턴스 B에서 각각 하나씩 운영하고 있습니다.

기존 배포 A의 배포가 완료된 뒤 B의 배포가 시작되는 방식으로 배포가 진행됩니다.

A 인스턴스에 다운타임이 발생하더라도 B 인스턴스가 정상적으로 운영되고 있기 때문에 Rolling 방식의 무중단 배포라고 할 수 있습니다.

기존 코딩해듀오 배포방식

기존의 CD 과정에서 EC2 인스턴스가 어떻게 관리되고 있는지 살펴보겠습니다.

우선 Github Action self hosted runner를 통해 첫번째 EC2 인스턴스(production A)의

구 버전 웹서버 도커 컨테이너를 신 버전 웹서버로 업데이트합니다.

그 후 production A의 배포가 완료되면 두 번째 인스턴스(production B)의 CD 스크립트가 실행됩니다. production B는 다운타임을 최소화하기 위해 production A의 웹 서버가 health check에 성공할 때까지 대기한 후 production B의 배포도 시작됩니다.

 

아래는 production B가 A의 health check 응답을 받아 production B의 배포까지 완료된 모습입니다.

 

다만, 아래 배포 진행 과정을 보면 알 수 있듯, Rolling 배포에는 몇가지 문제점이 존재했습니다.

B 인스턴스의 배포가 A 인스턴스의 배포 성공에 의존적이다 보니, 시작하기 전 찰나의 순간에 구버전과 신버전의 호환성 문제가 발생할 수 있습니다.

또한, 한 인스턴스에만 트래픽이 몰리게 됩니다.

Canary 배포 또한 Rolling 배포와 같이 호환성 문제가 발생할 수 있기 때문에 보류하였습니다.

그래서 도입한 것이 Blue/Green 무중단 배포입니다.

현재 운영중인 서비스의 환경을 blue, 새롭게 배포할 환경을 green 이라고 부릅니다. 새로 배포할 환경이 준비되면, blue 로 전송 되던 모든 트래픽을 green 으로 라우팅하는 방식입니다.

blue 환경은 다음 green 환경을 위해 제거됩니다.

새로운 환경인 green 으로 트래픽을 한번에 전송하기 때문에 이전 버전과의 호환성 문제가 발생하지 않고, 한 인스턴스에만 트래픽이 몰린다는 단점도 해결되었습니다.

 

Docker 및 Nginx를 통한 Blue/Green

코딩해듀오는 Blue/Green 무중단 배포를 위해, 각 인스턴스에 nginx를 리버스 프록시 서버로 두었습니다.

 

 

배포가 시작될 때, 각 인스턴스의 구 버전 웹서버와 신 버전 웹서버는 서로 다른 포트(8080, 8081)로 실행됩니다.

신 버전 웹서버가 잘 실행되었는지 각 인스턴스에서 5초 주기로 신 버전 웹서버를 health check합니다.

health-check에 성공하게 되면, nginx에 들어오는 http 트래픽을 구 버전에서 신 버전 웹서버로 전송합니다.

이로써, Rolling 배포와는 다르게 병렬적으로 두 인스턴스가 배포됩니다.

 

 

Rolling 배포와 또 다른 차이점으로는 구 버전 웹 서버는 신 버전 웹 서버의 배포가 끝나고 종료된다는 점입니다.

 

기존 Blue/Green 방식은 Green 환경과 Blue 환경을 유지하기 위해 기존 인스턴스 개수의 두 배의 인스턴스가 더 필요합니다.

인스턴스를 추가로 증설하면, 그만큼 비용이 증가한다는 단점이 있습니다.

이 문제를 Nginx로 해결할 수 있었습니다.

배포가 진행되는 과정에서 8080 포트 웹서버와 8081 포트 웹서버는 각각 Docker Container 로 관리됩니다.

Nginx를 사용해 80 포트로 들어온 요청을 8080 또는 8081로 라우팅하여 Blue/Green 무중단 인프라를 구성할 수 있었습니다.

최종적으로 무중단 배포가 완료된 상태는 아래와 같습니다.

 

 

추후 개선할 점

현재 구현된 무중단 배포에도 두가지 문제점이 있습니다.

첫번째는 A 인스턴스가 어떠한 이유로 배포에 실패하고 B 인스턴스만 배포가 성공했을 경우, A 인스턴스는 Blue 환경으로 B 인스턴스는 Green 환경으로 배포가 진행되게 됩니다.

그래서 배포 롤백이 구현되지 않는다면 버전 호환성 문제가 발생합니다.

두번째는 A 인스턴스와 B 인스턴스 안에 있는 nginx의 포트 포워딩이 동시에 일어나지 않는다는 문제입니다.

각각 인스턴스 안에 nginx는 localhost로 health check를 마친 후 포트 포워딩을 하는데, 이 시점이 동일하지 않아 마찬가지로 버전 호환성 문제가 발생합니다.

이 두가지 문제점을 해결하기 위해서는 Blue 환경에서 Green 환경으로 변경하는 시점에서 다른 인스턴스의 health check 까지 마친 다음 새로운 환경으로 배포해야 합니다.

즉 각 인스턴스가 자신의 Green 환경 배포 준비를 마친 후 다른 인스턴스도 준비가 됐는지 health check를 한 후 Green 환경으로 배포를 진행하는 작업이 필요합니다.

물론 이렇게 해도 nginx의 포트 포워딩이 끝나는 시점을 완전히 동일하게 맞출 수는 없지만 그래도 포트 포워딩을 시작하는 시점은 맞출 수 있습니다.

현재는 총 두 개의 인스턴스가 있어 각각 서로 health check가 가능하지만 스케일 아웃을 진행하게 된다면 각각 확인하는 것은 비효율적이므로 health check 용 서버를 두는 것도 고려해보아야 합니다.

공동 작성: 레모네, 프람, 레디

원글: 코딩해듀오 Wiki

 

😈무중단 배포

함께 하면 좋은 코딩, 코딩해듀오 💞. Contribute to woowacourse-teams/2024-coduo development by creating an account on GitHub.

github.com

 

'삽질 보고서' 카테고리의 다른 글

API 응답속도 개선하기  (1) 2025.01.30
테스트가 느려서 테스팅하기 싫을때  (0) 2025.01.24
Slack으로 코드리뷰 재촉하기  (0) 2024.10.27