일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- redis
- Spring cloud gateway
- circuitbreaker
- Spring Batch
- MDC
- DispatcherServlet
- 살아남았다.
- Elk
- 트랜잭션
- resilience4j
- 우아한 테크 코스
- 우아한테크코스
- Thread
- 최종 합격
- Gateway
- Kotlin
- 톰캣
- 커넥션 풀
- 우테코 5기
- HikariCP
- JWT
- 테스트코드
- spirng
- 오어스
- Transactio
- tomcat
- oauth
- AOP
- 우테코
- 동시성문제
- Today
- Total
코딩은 내일부터
무중단 배포 적용하기 본문
이번 포스팅은 무중단 배포에 대해서 알아보겠다.
개발을 하다 보면 배포되어 있는 구버전을 신버전으로 교체해야 할 때가 있다.
위의 사진과 같이 실행중인 버전의 프로세스를 종료하고 새로운 버전의 서비스를 빌드해서 배포하는 도중 서비스를 이용할 수 없는 다운타임이 생긴다.
이러한 다운타임이 발생하면 서비스를 사용하고 있는 사용자는 서비스를 사용할 수 없고, 극단적으로 해당 유저는 서비스를 이탈하는 상황이 발생할 수 있을 것이다.
그러면 이러한 다운타임 없이 어떻게 배포를 할 수 있을까?
무중단 배포(Zero-downtime Deployment)
무중단 배포는 위에서 말한 다운타임이 없는 즉, 중단하지 않은 상태로 배포를 한다는 것이다.
이러한 무중단 배포에도 여러 가지 방법이 존재하는데 이 중 가장 널리 알려진 세 가지 배포 전략에 대해 알아보겠다.
롤링(Rolling) 배포
이번 버전과 신규 버전을 하나씩 교체하면서 점진적으로 배포하는 방식이다.
위의 사진과 같이 로드밸런서가 교체 중인 서버는 트래픽을 차단하고 새로운 버전으로 교체한다.
이러한 과정을 반복해서 전체의 서버를 교체한다.
장점으로는 추가적인 서버 자원을 사용하지 않고 배포를 할 수 있지만,
평소에는 3대의 서버가 부하를 받고 있다가 새로운 버전으로 교체할 때 2대의 서버가 트래픽을 부담해야 해서 부하가 더 걸린다는 단점이 있다.
이러한 단점이 걱정되면 추가 서버를 1대 더 띄워 위와 같은 작업을 진행하면 될 것이다.
그리고 또 하나의 단점은 구버전과 신버전의 애플리케이션이 동시에 서비스되기 때문에 호환성 문제가 발생할 수 있다.
Blue-Green 배포
Blue-Green 배포는 두 개의 독립적인 환경 Blue, Green을 가지고 진행되는 방법이다.
먼저 Blue는 구버전을 Green은 신버전을 의미한다. 아래 사진과 같이 Green의 배포 준비가 완료되면 Blue에서 Green으로 트래픽을 한 번에 전환한다.
롤링 배포와 다르게 한 번에 버전을 바꾸기 때문에 호환성 문제가 발생하지 않는다.
카나리(Canary) 배포
카나리 배포는 점진적으로 구버전에 대한 트래픽을 신버전으로 옮긴다.
이렇게 보면 롤링 배포와 차이점이 없지만, 카나리 배포는 새로운 버전에 대한 오류를 찾는 거에 관점을 둔다.
배포하는 과정은 롤링+블루그린의 형태를 띄운다. 위의 사진과 같이 트래픽을 점차 신버전으로 옮기면서 새로운 버전에 이상이 있는지 오류를 감지하고 이상이 없다 판단하면 새로운 버전으로 트래픽을 옮긴다.
이러한 특징 때문에 A/B테스트를 진행하기 적합하다.
카나리 배포와 롤링 배포의 차이점을 정리하자면
롤링배포는 적은 비용으로 구버전을 신버전으로 점진적으로 교체하는데 목적을 뒀다면
카나리 배포는 트래픽을 조금씩 늘리면서 오류는 감지한다는데 목적이 있다.
무중단 배포 선택
Blue-Green 전략은 호환성 문제를 걱정할 필요가 없다. 기존 운영 환경과 새로운 운영 환경을 병렬로 구축하기 때문에 호환성 문제를 최소화하고 안정적인 배포를 보장하기 때문이다.
무중단 배포를 방법 중 하나로 카나리 방식을 고려하였다. 여러 서버에서 구버전 트래픽 설정 비율과 신버전 트래픽 설정 비율을 조절하여 오류 여부를 확인해 보는 방법도 흥미롭다고 생각하지만, 현재 EC2 서버가 한 대 운영 중이기 때문에 가장 간단하고 효율적인 방법으로 Blue-Green이 적합하다는 생각이다. 즉, 카나리 방식은 여러 서버를 가지고 있는 환경에서 더 적합하다고 생각한다.(나중에 해볼 예정)
그러면 현재 상황에서 제일 적합한 방법은 Bule-Green 전략이 적합하다고 결론을 내렸다.
Bule-Green 배포 적용하기
무중단 배포를 적용하기 전 서버 상황이다.
Docker를 사용하여 nginx와 서버를 띄워 놓은 상태이다.
여기에서 Blue-Green 배포를 사용하면 다음과 같이 구성될 것이다.
배포 순서는 다음과 같습니다.
- Github Action을 사용하여 신 버전을 빌드하고 이미지로 말아 도커 허브에 Push 합니다.
- Self hosted runner를 사용해서 EC2 서버에서 Shell Script를 실행합니다.
- Shell Script 동작
- 도커 허브에 올라가 있는 이미지를 pull 받습니다.
- 현재 애플리케이션이 띄워져 있는 색(blue, green)을 확인하고, 그의 반대되는 색의 컨테이너를 띄웁니다.
- 원래 띄워져 있던 컨테이너를 중단하고 제거합니다.
문제 발생
무중단 배포를 구현하면서 연속적인 배포 요청이 들어올 경우, 배포 스크립트가 동시에 실행될 가능성을 방지하기 위해 파일 기반의 락(lock) 메커니즘을 사용했습니다. 이는 두 번째 스크립트 실행 시 첫 번째 스크립트가 아직 완료되지 않았다면 추가 실행을 방지하기 위해 사용했다.
배포 스크립트의 동작 원리
스크립트가 시작될 때, deploy.lock 파일의 존재 여부를 체크한다. 이 파일이 존재한다면 "Deployment is in progress"라는 메시지를 출력하고 스크립트 실행을 중지하고, 파일이 존재하지 않는 경우에는 touch /tmp/deploy.lock 명령으로 새로운 락 파일을 생성하고 배포를 진행한다.
문제 발생 및 대응
하지만 이 방법도 완벽하지 않다. 예를 들어, 배포 프로세스가 비정상적으로 중단되거나 시스템이 다운될 경우, 락 파일이 제거되지 않아 배포가 영구적으로 막힐 수 있고, 연속적으로 배포 요청이 발생하면 락 파일로 인해 새로운 배포가 지연될 수 있습니다.
이러한 문제에 대응하기 위해 타임아웃 설정하여 일정 시간 후 자동으로 락 파일을 삭제하게 하는 방법도 있을 것이다.
짜잔 -완-