TIG 서비스는 개발이 거의 완성되어 서비스를 출시 할 예정이다..!
기존에는 Github Actions 를 통한 CI/CD를 구축하긴 했지만 다운타임이 완전히 없던 것은 아니다. 내가 새로운 기능을 개발하거나 수정사항이 있어서 코드를 수정 한 후 develop 브랜치에 머지가 되면 자동으로 배포는 진행됐으나, 한 1분 정도 다운타임이 발생했다.
실제 사용자들이 사용하기 위해서는 무중단 배포가 반드시 필요했다.
블루 환경과 그린 환경을 열어두고, 한쪽에서 테스트를 진행해보고 운영 환경을 바꾸어가는 과정이 필요하다고 생각하기도 했고 프론트엔드 팀원분도 동의 해서 블루/그린 전략을 선택했다.
우리 서비스에서는 따로 Nginx 설정이 불필요하다고 느꼈고 따로 사용하지 않고 있었다. HTTPS 연결의 경우에는 Nginx를 사용하기도 하지만 AWS의 Load Balancer 를 통해서 연결해주고 있었다.
하지만 블루/그린 배포를 위해서는 Nginx 가 필요했다. (로드 밸런서로도 설정할 수 있는 것 같았는데 Nginx를 사용하는게 더 편해보였다)
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 블루와 그린 환경 정의
upstream blue_backend {
server app_blue:8081; # 블루 환경 포트
keepalive 32;
}
upstream green_backend {
server app_green:8082; # 그린 환경 포트
keepalive 32;
}
server {
listen 80;
# 공통 URL (api.tigleisure.com)
server_name api.tigleisure.com;
location / {
# 현재 활성화된 환경으로 라우팅 (green_backend 또는 blue_backend)
proxy_pass http://green_backend; # 초기에는 그린 환경으로 설정
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Health Check
location /tig/health {
proxy_pass http://green_backend/tig/health;
proxy_set_header Host $host;
}
}
}
코드는 위와 같이 구성했다. 일단 백엔드 서버의 url 이 https://api.tigleisure.com 이므로 이를 설정해주고, 블루 환경과 그린 환경의 포트를 달리 했다.
보통 블루/그린 배포 전략에서는 EC2 인스턴스를 두개 사용하여 독립된 인스턴스에서 환경을 관리하는 전략을 사용한다.
하지만 우리는 서버 비용에 돈을 많이 투자(?) 할 수 없기 때문에.. 하나의 EC2 인스턴스에서 포트를 달리하여 사용했다.
사용자들이 경험하는 흐름을 간단히 설명하자면 다음과 같다.
Load Balancer 에 의해 https(443) 으로 연결된다.Nginx 가 담당하여 올라가 있는 환경으로 연결해준다.docker-compose 를 통해서 블루 환경과 그린 환경, Nginx 에 대한 컨테이너를 띄워줘야 한다.
version: '3.8'
services:
blue:
build:
context: .
dockerfile: Dockerfile
image: nimikgnoej/tig-web:blue # 블루 환경용 이미지 태그
ports:
- "8081:8080" # 블루 환경 포트
env_file:
- .env
container_name: app_blue
green:
build:
context: .
dockerfile: Dockerfile
image: nimikgnoej/tig-web:green # 그린 환경용 이미지 태그
ports:
- "8082:8080" # 그린 환경 포트
env_file:
- .env
container_name: app_green
nginx:
image: nimikgnoej/tig-nginx:latest
build:
context: ./nginx
dockerfile: Dockerfile # nginx에 대한 Dockerfile
ports:
- "80:80" # 외부로 노출되는 포트
depends_on:
- blue
- green
container_name: nginx
3개의 이미지를 설정해주고 포트 또한 다르게 설정해준다. 이때 nginx 이미지는 블루,그린 환경에 depends_on 하도록 설정한다.
이렇게 설정하고 기존의 방식대로 배포를 하면 되긴 하지만 CD를 통해서 편하게 하고 싶었기 때문에 구글링을 통해 shell 코드를 찾았다.
# 현재 활성화된 환경 확인
IS_GREEN=$(docker ps | grep green)
if [ -z "$IS_GREEN" ]; then
# 현재 환경이 블루 -> 그린으로 전환
echo "Switching from BLUE to GREEN"
docker-compose pull green
docker-compose up -d green
# Health Check
echo "Performing health check for GREEN"
until [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8082/tig/health)" == "200" ]; do
echo "Waiting for GREEN environment to be healthy..."
sleep 5
done
# Nginx 설정 업데이트
echo "Updating Nginx to route traffic to GREEN"
sed -i 's/http:\/\/blue_backend/http:\/\/green_backend/' /home/ubuntu/nginx.conf
nginx -s reload
# 블루 환경 중지
echo "Stopping BLUE environment"
docker-compose stop blue
docker-compose rm -f blue
else
# 현재 환경이 그린 -> 블루로 전환
echo "Switching from GREEN to BLUE"
docker-compose pull blue
docker-compose up -d blue
# Health Check
echo "Performing health check for BLUE"
until [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8081/tig/health)" == "200" ]; do
echo "Waiting for BLUE environment to be healthy..."
sleep 5
done
# Nginx 설정 업데이트
echo "Updating Nginx to route traffic to BLUE"
sed -i 's/http:\/\/blue_backend/http:\/\/green_backend/' /home/ubuntu/nginx.conf
nginx -s reload
# 그린 환경 중지
echo "Stopping GREEN environment"
docker-compose stop green
docker-compose rm -f green
fi
해당 Shell 코드를 CD 파일에 사용했다. 기존 활성화 되어 있던 환경이 블루라면 블루 -> 그린 으로, 반대라면 반대로 설정해주는 코드이다.
결과적으로 성공 ^__^

헤헤