[TIG] Nginx 와 블루/그린 배포

JEONG KI MIN·2024년 11월 22일

TIG

목록 보기
8/12

TIG 서비스는 개발이 거의 완성되어 서비스를 출시 할 예정이다..!

기존 상황

기존에는 Github Actions 를 통한 CI/CD를 구축하긴 했지만 다운타임이 완전히 없던 것은 아니다. 내가 새로운 기능을 개발하거나 수정사항이 있어서 코드를 수정 한 후 develop 브랜치에 머지가 되면 자동으로 배포는 진행됐으나, 한 1분 정도 다운타임이 발생했다.

실제 사용자들이 사용하기 위해서는 무중단 배포가 반드시 필요했다.

블루 환경과 그린 환경을 열어두고, 한쪽에서 테스트를 진행해보고 운영 환경을 바꾸어가는 과정이 필요하다고 생각하기도 했고 프론트엔드 팀원분도 동의 해서 블루/그린 전략을 선택했다.

Nginx 설정

우리 서비스에서는 따로 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 인스턴스에서 포트를 달리하여 사용했다.

사용자들이 경험하는 흐름을 간단히 설명하자면 다음과 같다.

  1. http(80) 으로 접속하면 Load Balancer 에 의해 https(443) 으로 연결된다.
  2. 80으로 들어오는 요청에 대해서는 Nginx 가 담당하여 올라가 있는 환경으로 연결해준다.

docker-compose.yml 설정

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 코드를 찾았다.

Shell 코드를 사용한 CD

# 현재 활성화된 환경 확인
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 파일에 사용했다. 기존 활성화 되어 있던 환경이 블루라면 블루 -> 그린 으로, 반대라면 반대로 설정해주는 코드이다.

결과적으로 성공 ^__^

profile
열심히 해볼게요

2개의 댓글

comment-user-thumbnail
2024년 11월 23일

헤헤

1개의 답글