health check

Untitled

현재 블루/그린 무중단 배포를 구현하고 있지만, 신규 어플리케이션에서 에러가 발생하면 서비스가 중단되는 문제가 발생한다. 트래픽을 신규 버전으로 전환하는 과정에서 신규 어플리케이션이 제대로 실행되었는지 확인하지 않았기 때문이다.

배포 전에 테스트를 진행하여 어플리케이션의 잠재된 버그를 발견하는 방법도 있겠지만, 모킹 함수를 구현함으로써 실제 로직과 다를 수 있다.

그리고 테스트로 발견할 수 없는 황당한 에러도 있다. 실제로 tsconfig.jsonpackage.json 의 설정을 수정하여 빌드 경로가 달라져 진입지점을 찾지 못하는 문제가 발생했다. (dist/main 에서 dist/src/main 이 되어 메인 파일을 찾지 못하는 에러였다.) 이는 빌드 후 실행까지 해야 알 수 있기 때문에 npm test 로 발견할 수 없는 에러다. 따라서 실제 배포 환경에서 트래픽을 전환하기 전에 서버 상태를 확인하는 과정이 필요하다.


문제의 배포 스크립트

# 신규 버전의 도커 컨테이너 실행
DOCKER_COMPOSE_FILE="compose.$RUN_TARGET-deploy.yml"
sudo docker-compose -f "$DOCKER_COMPOSE_FILE" pull
sudo docker-compose -f "$DOCKER_COMPOSE_FILE" up -d

# 도커 컨테이너가 실행될 때까지 일정 시간 기다리기
sleep 30

NGINX_ID=$(sudo docker ps --filter "name=nginx" --quiet)
NGINX_CONFIG="/etc/nginx/conf.d/default.conf"

# nginx 설정파일 조작
sudo docker exec $NGINX_ID /bin/bash -c "sed -i 's/was-$STOP_TARGET:$WAS_STOP_PORT/was-$RUN_TARGET:$WAS_RUN_PORT/' $NGINX_CONFIG"
sudo docker exec $NGINX_ID /bin/bash -c "sed -i 's/signal-$STOP_TARGET:$((WAS_STOP_PORT + 1))/signal-$RUN_TARGET:$((WAS_RUN_PORT + 1))/' $NGINX_CONFIG"
# nginx를 리로드하여 트래픽 전환
sudo docker exec $NGINX_ID /bin/bash -c "nginx -s reload"
...

위의 소스코드는 버전을 전환하는 과정이다. 신규 버전의 컨테이너가 시작되기까지 일정 시간 기다릴 뿐, 제대로 실행되었는지 확인하는 부분이 없다. nginx 설정 파일을 수정하여 트래픽을 전환하기 전에 어플리케이션이 제대로 실행되었는지 확인이 필요하다.


Step 1️⃣ health check용 API 만들기

먼저, 어플리케이션이 제대로 실행되었는지 확인하기 위한 API를 만들어야 한다. 추후에 해당 API로 요청을 보내고 응답이 정상적으로 오는지 그 여부를 기준으로 어플리케이션의 상태를 판단할 것이다.

import { Controller, Get } from '@nestjs/common';

@Controller()
export class AppController {
  @Get('/health-check')
  healthCheck(): boolean {
    return true;
  }
}

Step 2️⃣ healthcheck 옵션 작성하기

현재 도커 컴포즈를 이용해서 멀티 컨테이너 어플리케이션을 구축하고 있다. 배포 환경에서 실행되는 도커 컴포즈 파일에 다음과 같이 healthcheck 를 작성한다.