✅ 개요
배포할 때마다 블루/그린 서버가 번갈아가며 실행되는 것은 확인했지만
배포 과정 중 새로고침을 눌러보면 일정시간동안 502 Bad Gateway 오류가 발생한다.
물론 시간이 지나면 서비스가 다시 정상작동하긴 하지만 단 한순간 이라도 서비스가 끊기지 않는 것이 무중단 배포의 핵심이다.
이번 포스트에서는 이 문제를 해결하는 과정에 대해 이야기하도록 하겠다.
✅ 문제 원인 파악
아무래도 서버를 실행시키는 부분에서 문제가 발생했을 거라고 생각했다.
그 부분은 바로 CodeDeploy에 의해 EC2에 관련 파일들이 다운로드 됐을 때 실행되는 start-server.sh이다.
#!/bin/bash
NGINX_CONF="/etc/nginx/sites-available/default"
cd /home/ubuntu/sscanner/docker-compose/
# 이미지 업데이트
docker pull 211125297893.dkr.ecr.ap-northeast-2.amazonaws.com/sscanner-backend
# 현재 실행 중인 서버 확인 (블루 서버가 실행 중인지 확인)
if docker ps | grep -q "blue-server"; then
echo "블루 서버가 실행 중입니다. 그린 서버로 배포합니다."
# 그린 서버 배포
docker compose -f compose.green.yml up -d green --build
# 블루 서버 삭제
docker compose -f compose.blue.yml down
# 사용하지 않는 이미지 삭제
docker image prune -af
NEW_SERVER="green"
else
echo "그린 서버가 실행 중입니다. 블루 서버로 배포합니다."
# 블루 서버 배포
docker compose -f compose.blue.yml up -d blue --build
# 그린 서버 삭제
docker compose -f compose.green.yml down
# 사용하지 않는 이미지 삭제
docker image prune -af
NEW_SERVER="blue"
fi
echo "------- $NEW_SERVER 서버 배포 완료 --------"
실행 중인 서버를 파악해 실행 중이지 않은 서버를 실행하고 실행 중인 서버는 삭제한다.
if docker ps | grep -q "blue-server"; then
echo "블루 서버가 실행 중입니다. 그린 서버로 배포합니다."
# 그린 서버 배포
docker compose -f compose.green.yml up -d green --build
# 블루 서버 삭제
docker compose -f compose.blue.yml down
명령어들은 순차적으로 실행되기 때문에 일반적으로는 새로운 서버가 배포되고 기존 서버가 내려가야 하는 것이 맞다.
하지만 네트워크 지연, 데이터베이스와 같은 연결정보 셋팅 등의 변수가 있기 때문에 특정 시간동안 기다려줘야 하는 부분이 들어가야 한다고 생각했다.
✅ 시도1: 일정 시간동안 sleep
가장 단순하게 새로운 서버를 실행하고 나서 sleep 명령어를 통해 특정 시간 동안 기다려주었다.
# 현재 실행 중인 서버 확인 (블루 서버가 실행 중인지 확인)
if docker ps | grep -q "blue-server"; then
echo "블루 서버가 실행 중입니다. 그린 서버로 배포합니다."
# 그린 서버 배포
docker compose -f compose.green.yml up -d green --build
# 30초간 대기
sleep 30
# 블루 서버 삭제
docker compose -f compose.blue.yml down
결과
총 5번을 시도하였는데 딱 1번 성공했고 2번 502에러가 발생하였다.
나머지 2번은 CodeDeploy 배포 과정 중 Timeout 에러가 발생해 배포를 실패하였다.
30초가 너무 길었던 것이다.
그렇다고 줄여도 네트워크 상황이란건 가변적이기 때문에 완벽한 무중단배포를 보장하기 어렵다고 판단했다.
✅ 시도2: while문을 통해 주기적으로 컨테이너 상황을 체크
고정적인 시간을 기다리는 것보다 서버 컨테이너의 상태를 주기적으로 확인해서 실행이 체크되면 기존 서버 컨테이너를 내리는 식으로 구현해보았다.
2초마다 컨테이너의 실행여부를 확인한다.
if docker ps | grep -q "blue-server"; then
echo "블루 서버가 실행 중입니다. 그린 서버로 배포합니다."
# 그린 서버 배포
docker compose -f compose.green.yml up -d green --build
# 그린 서버가 준비될 때까지 대기
echo "그린 서버가 준비 중입니다. 상태를 확인합니다..."
while ! docker ps | grep -q "green-server"; do
sleep 2
echo "그린 서버 준비 중..."
done
echo "그린 서버가 준비되었습니다. 블루 서버 종료 중..."
# 블루 서버 삭제
docker compose -f compose.blue.yml down
이러면 고정적인 시간을 기다릴때마다 가변적인 상황을 더 잘 대비할 수 있다.
결과
총 5번을 시도하였는데 의외로 5번 모두 502 에러가 발생하였다.
단순히 docker ps로 컨테이너 상태를 확인해서 컨테이너가 실행 중이라고 해도 완전히 스프링부트 서버가 준비됐다는 것을 의미하진 않는다고한다.
✅ 시도3: Health 체크 하기
실행 중인 서버에 /health로 API 요청을 보내 Health 체크를 한다.
# 현재 실행 중인 서버 확인 (블루 서버가 실행 중인지 확인)
if docker ps | grep -q "blue-server"; then
echo "블루 서버가 실행 중입니다. 그린 서버로 배포합니다."
# 그린 서버 배포
docker compose -f compose.green.yml up -d green --build
# 그린 서버가 준비될 때까지 대기
echo "그린 서버가 준비 중입니다. 상태를 확인합니다..."
while ! curl -sf <http://localhost:8082/health>; do
sleep 2
echo "그린 서버 준비 중..."
done
# nginx 새로고침
sudo service nginx reload
# 블루 서버 삭제
docker compose -f compose.blue.yml down
컨트롤러 선언
해당 Health 체크를 받아줄 API를 하나 선언해준다.
@RestController
public class HealthController {
@GetMapping("/health")
public String health() {
return "ok";
}
}
결과
총 5번 시도했다.
5번 모두 502 에러가 발생하지 않았다!
기존 서버가 종료되는 동안 새 서버/이전 서버 왔다갔다 하는 현상은 있지만 에러없이 서비스를 이용할 수 있게 되었다.
'데브코스 > 실습 & 프로젝트' 카테고리의 다른 글
[2-3차 프로젝트] Sonar를 통해 코드 정적분석하기 - 2. 프로젝트에 Sonar 분석 도입하기 (1) | 2024.10.28 |
---|---|
[2-3차 프로젝트] Sonar를 통해 코드 정적분석하기 - 1. SonarCloud 환경설정하기 (1) | 2024.10.28 |
[2-3차 프로젝트] 블루/그린 배포 방식으로 CI/CD 파이프라인 구축하기 - 2. CI/CD 파이프라인 구축 (0) | 2024.10.27 |
[2-3차 프로젝트] 블루/그린 배포 방식으로 CI/CD 파이프라인 구축하기 - 1. 인프라 구성하기 (0) | 2024.10.27 |
[1차 프로젝트] - Toss Payments 결제 API를 통해 Spring boot 서버 구현하기 (4) | 2024.09.12 |