철수는 오늘따라 게임이 너무 하고 싶습니다. 컴퓨터를 켰지만 화가나게 윈도우 업데이트가 자동으로 수행됩니다. 철수는 너무 너무 답답했습니다.
이 처럼 유저가 서비스를 이용할 수 없는 시간을 downtime이라고 합니다.
하지만 컴퓨터가 2대라면 어떨까요? 응 다른 컴퓨터로 게임하면 그만이야~
서비스를 운영할 때도 이와 같은 상황이 존재합니다. 서버가 1개일 때 구버전의 서비스를 신버전으로 교체하기 위해서는 불가피하게 일정시간동안 서버를 꺼야합니다. 이는 사소해 보이지만 보안의 6요소중 하나인 availability(고가용성)을 보장하지 않습니다. 사용자가 매번 서버의 상황을 이해하고 지켜볼 의무는 없습니다.
그럼 이런 downtime없이 업데이트를 하는 방법(무중단 배포)은 무엇이 있을까요?
일단 최소 서버를 2대 구동할 수 있기만 하면 됩니다.
1. 롤링 배포
트래픽을 점진적으로 구버전에서 신버전으로 옮기는 방식
- 인스턴스를 추가하고 새로운 버전을 실행해서 로드밸런서 연결 → 구버전 인스턴스를 하나씩 연결을 끊고 업데이트 진행후 연결 → 마지막 인스턴스는 연결 안함
- v1이 실행되고 있는 서버 하나를 로드밸런서에서 떼어내고 업데이트 후 재연결
장점 - 많은 오케스트레이션 툴에서 지원, 많은 서버 자원이 필요하지 않음
단점 - 1.2방식의 경우 일시적으로 인스턴스가 줄어 서버 당 부담하는 트래픽 양이 늘어남
2. blue-green 배포
현재 운영 서비스 환경 - blue / 새로 배포할 환경 - green
blue, green을 나란히 구성해두고 배포 시점에 로드 밸런서가 blue → green으로 전환. 성공 시 blue 제거 or 유지
장점 - 한번에 트래픽을 새 버전으로 옮기기 떄문에 호환성 문제 x
단점 - 실제 운영에 필요한 2배의 리소스 확보 필요
3. 카나리 배포
점진적으로 트래픽을 신버전으로 옮기는 것은 롤링과 비슷. 하지만 핵심은 신버전 오류를 조기에 감지하는것
소수의 트래픽만 신버전에 옮겨서 서비스를 운영하게하고 이상이 없다면 모든 트래픽 이동
장점 - 신버전 위험 최소화
단점 - 롤링과 같이 호환성 문제
4. 그럼 어떤 상황에 어떤 배포 전략을 선택해야 하는가?
배포간 구/신 버전이 동시에 공존하면 안되는 경우
- 블루/그린 배포
운영환경에서 최소한으로 테스트 해보고 싶은 경우
- 카나리 배포
작은 규모의 애플리케이션, 자원이 제한된 환경
- 롤링 업데이트
사용자 피드백을 중시하고 위험을 최소화하고 싶은 경우
- 카나리 배포
고가용성과 안정성이 중요한 대규모 서비스
- 블루-그린 배포
클라우드 네이티브 애플리케이션, 빠른 배포 주기가 필요한 경우
- 카나리 배포, 롤링 업데이트
5. 내가 원하는 전략 조건
처음엔 최대한 실무에서 사용하는것 처럼 blue-green 배포전략을 시도하려 했으나… 실패했습니다. 이유는 머니머니해도 머니…
- 저사양의 fargate를 사용해도 모니터링, 부하테스트 추가로 개수가 꽤 많아질 것 같아 비용이 막대할 것
- ecs를 사용하면서 또 추가로 사용해야하는 aws 서비스 (ALB, VPC 등) 사용법을 공부해야하고, 비용 문제
나만의 조건
- 오케스트레이션 툴을 사용하지 않는다.
- 비용이 최대한 저렴해야 한다.
- 인스턴스 하나에 서버를 운영해야 한다.
실패 과정을 겪고나서 깨달았던것은 가장 중요한것이 비용이라는것… 그리고 제 개인적인 생각으로는(맞는지는 모르겠습니다) 일단 오케스트레이션 툴을 도입하는 순간 비용이 비약적으로 상승한다는 것입니다. 이 역할을 메꾸기 위해서 최대한 내가 직접 github actions이나 서버에서 쉘스크립트를 잘 짜서 관리하도록 해야합니다. 이에 맞는 배포전략을 짜봅시다.
포트 기반 blue-green 배포
예를 들어, 8080, 8081 포트를 서버 포트로 사용하면서, 리버스 프록시(nginx, apache)로 switching를 활용하여 업데이트하고 실행하는 방식입니다.
내가 생각한 전체적인 흐름
- v*.* branch가 master로부터 분기되면 github actions trigger
- gradle로 프로젝트를 build하고 jar 생성
- scp를 사용해서 jar을 내 ec2로 전송
- ssh로 ec2에 접근하여 $DEPLOY_PATH에 작성해둔 deploy.sh(포트를 확인하고 switching 작업을 수행) 실행
- 헬스체크를 하고 성공, 실패를 discord webhook 전송
# References
https://hudi.blog/zero-downtime-deployment/
https://velog.io/@gehwan96/CICD-배포-전략-정리
https://dev.classmethod.jp/articles/ci-cd-deployment-strategies-kr/
'Back-end > IBAS-spring-project' 카테고리의 다른 글
Blue/Green 배포 (Nginx + github actions + Docker compose) (0) | 2024.06.21 |
---|---|
Blue/Green 배포 (Nginx + github actions) without Docker (0) | 2024.06.17 |
JPA 연관관계 (일대일, 일대다, 다대일, 다대다) (0) | 2023.08.25 |
프로세스, 그리고 Docker와 VM (0) | 2023.08.06 |
RESTful API (0) | 2023.07.27 |