-
Notifications
You must be signed in to change notification settings - Fork 3
[BE] 무중단 배포
iamjooon2 edited this page Nov 21, 2023
·
5 revisions
서버를 재배포하고 다시 실행되는 동안 유저는 서비스를 이용할 수 없게 되고, 이를 다운타임이라고 합니다. 사용자 불편함을 최소로 하기 위해 무중단 배포를 적용하여 다운타임을 제거해봅시다.
서버를 하나씩 점진적으로 새로운 버전으로 바꾸는 방식
서버를 하나씩 점진적으로 새로운 버전으로 바꾸는 방식인 롤링과 비슷한 방식이지만 새로운 버전을 소수의 유저들에게만 배포를 해보고 문제가 없는 것을 확인하면 점차 많은 유저들에게 배포하는 방식입니다
새로운 버전으로 한번에 바꾸는 방식으로 보통 현재 버전을 Blue, 새 버전을 Green이라 한다. 현재 버전과 동일한 서버 구성을 새로운 버전으로 만든 후, 문제가 없을 때 기존의 Blue 서버를 제거할 수 있습니다.
카나리, 롤링의 경우 구버전과 신버전이 동시에 서비스 될 가능성이 있어 호환성 문제가 일어날 수 있고, 에러 발생시 기존 버전으로 롤백이 용이하다는 이유로 블루/그린 배포 방식을 선택하게 되었습니다.
- 현재 구동중인 서버 포트 확인합니다
- 사용하고 있지 않은 포트에 신버전(green) 배포
- 신버전이 제대로 배포된 경우에만 4, 5만 진행. 제대로 배포되지 않았으면 구버전(blue) 그대로 유지
- 포트 스위칭
- 구버전(blue) 종료
- 이전에 작업하고 있을 수도 있으므로 gracefully shutdown
사용한 스크립트는 다음과 같습니다
#!/bin/sh
echo "> 현재 구동중인 서버 포트 확인"
RESPONSE_8080=$(curl -s http://localhost:8080/actuator/health)
echo "> $RESPONSE_8080"
UP_COUNT=$(echo $RESPONSE_8080 | grep 'UP' | wc -l)
if [ $UP_COUNT -ge 1 ]
then # $UP_COUNT >= 1 ("UP" 문자열이 있는지 검증)
IDLE_PROFILE=dev2
IDLE_PORT=8081
else
IDLE_PROFILE=dev1
IDLE_PORT=8080
fi
echo "> $IDLE_PROFILE 에서 구동중인 애플리케이션 pid 확인"
IDLE_PID=$(pgrep -f ${IDLE_PORT}-zipgo-backend-0.0.1-SNAPSHOT.jar)
echo "> pid: $IDLE_PID"
if [ -z "$IDLE_PID" ]
then
echo "> 구동중인 서버가 없습니다"
else
echo "> kill -9 $IDLE_PID"
sudo kill -9 $IDLE_PID
sleep 5
fi
echo "> 신버전을 배포합니다"
echo "> 배포할 프로필 $IDLE_PROFILE"
echo "> 배포할 포트 $IDLE_PORT"
sudo chmod +x ~/${IDLE_PORT}-zipgo-backend-0.0.1-SNAPSHOT.jar
sudo nohup java \
-Dspring.profiles.active=$IDLE_PROFILE \
-Dspring.config.import=file:/home/ubuntu/env.properties \
~/${IDLE_PORT}-zipgo-backend-0.0.1-SNAPSHOT.jar > ~/application.log 2>&1 &
echo "> $IDLE_PROFILE 30초 후 Health check 시작"
echo "> curl -s http://localhost:$IDLE_PORT/actuator/health "
sleep 30
for retry_count in {1..5}
do
RESPONE=$(curl -s http://localhost:$IDLE_PORT/actuator/health)
up_count=$(echo $RESPONE | grep 'UP' | wc -l)
if [ $up_count -ge 1 ]
then # $up_count >= 1 ("UP" 문자열이 있는지 검증)
echo "> Health check 성공"
break
else
echo "> Health check의 응답을 알 수 없거나 혹은 status가 UP이 아닙니다 "
echo "> Health check: ${RESPONE}"
fi
if [ $retry_count -eq 10 ]
then
echo "> Health check 실패 "
echo "> 배포를 종료합니다"
exit 1
fi
echo "> Health check 실패 재시도..."
sleep 10
done
echo "> 리버스 프록시 대상 포트를 변경합니다"
sleep 1
echo "> 전환할 포트: $IDLE_PORT"
echo "set \$service_url http://127.0.0.1:${IDLE_PORT};" |sudo tee /etc/nginx/conf.d/service-url.inc
echo "> Nginx Reload"
sudo service nginx reload
if [ $IDLE_PORT -eq 8081 ]
then
FORMER_PID=$(sudo netstat -lntp | grep 8080 | awk '{print $7}' | cut -d'/' -f1)
else
FORMER_PID=$(sudo netstat -lntp | grep 8081 | awk '{print $7}' | cut -d'/' -f1)
fi
echo "> 이전 서버를 종료합니다"
sudo kill -15 $FORMER_PID
echo "> 완료"
완료된 후, Nginx에서 리버스 프록시 설정 포트를 새로 배포한 포트로 변경시켜줍니다.