# Kubernetes 없이 Docker Compose로 구현하는 제로 다운타임 블루-그린 배포
Kubernetes 같은 오케스트레이터 없이도 블루-그린 배포를 구현할 수 있습니다. Docker Compose, nginx, 그리고 잘 설계된 graceful shutdown 로직만 있으면 충분합니다. 이 접근 방식은 전용 서버나 가상 머신에서 작업하는 팀에게 특히 적합하며, 경제적 또는 아키텍처상의 이유로 전체 클러스터를 사용하는 것이 비현실적인 상황에 유용합니다. 이 글에서는 웹 서비스와 백그라운드 워커의 지속적 배포에 대한 기술적 구현을 다루며, 메시지 처리 특성과 상태 관리를 고려합니다.
Docker Compose에서의 블루-그린 아키텍처
기본 구성에서 각 애플리케이션은 복제되어 있습니다: blue와 green 두 개의 독립적인 인스턴스가 있습니다. 둘 다 docker-compose.prod.yml에서 별도의 서비스로 실행되지만, 한 번에 하나의 인스턴스만 트래픽을 받습니다. 라우팅은 리버스 프록시(nginx 예시에서처럼)가 담당하며, 배포 중에 upstream 주소를 전환합니다. 핵심 원칙: 새로운 인스턴스가 완전히 시작되어 헬스 체크를 통과한 후에야 이전 인스턴스를 중지합니다.
구성 시 각 인스턴스의 포트를 명시적으로 지정해야 합니다:
web-blue:
ports:
- "127.0.0.1:8002:8000"
web-green:
ports:
- "127.0.0.1:8003:8000"
이렇게 하면 nginx가 localhost와 특정 포트를 통해 필요한 인스턴스에 접근할 수 있습니다. 이 설정은 충돌을 피하고 생명 주기 관리를 단순화합니다.
백그라운드 워커 관리
큐(RabbitMQ 등)에서 메시지를 소비하는 백그라운드 프로세스(워커)는 특별한 접근이 필요합니다. 단순히 컨테이너를 중지하면 메시지 손실이나 비멱등 연산 시 재처리가 발생할 수 있습니다. 해결책은 애플리케이션 수준에서 graceful shutdown을 구현하는 것입니다.
이는 is_accepting 플래그를 가진 싱글톤 클래스로 구현됩니다. 각 작업을 처리하기 전에 워커는 이 플래그를 확인합니다:
is_accepting == True인 경우 — 작업을 실행합니다.is_accepting == False인 경우 —requeue=True로 메시지를 큐로 반환합니다.
SIGTERM 신호를 받으면 플래그를 False로 설정한 후, 현재 작업이 모두 완료될 때까지(5~10초 버퍼 포함) 대기한 뒤 종료합니다. 이렇게 하면 메시지 손실이나 데이터 불일치가 발생하지 않습니다.
중요한 세부 사항:
- 멀티 프로세스 워커(예: ProcessPoolExecutor)의 경우
is_accepting상태가 모든 자식 프로세스에서 접근 가능해야 합니다. 그렇지 않으면 일부 소비자가 새로운 작업을 계속 처리할 수 있습니다. - 비멱등 연산은 추가 보호 장치가 필요합니다: 재처리는 데이터 무결성을 훼손할 수 있습니다.
- 분산 플래그(예: Redis 내)를 사용하면 아키텍처가 복잡해지지만 고부하 시스템에서는 정당화될 수 있습니다.
배포 스크립트: 단계별 로직
배포 스크립트는 인스턴스 간 전환을 자동화합니다. 웹 서비스와 워커 모두 동일한 로직이지만 진입점이 다릅니다.
주요 단계:
- 활성 인스턴스 확인(nginx 구성 분석 또는 실행 중 컨테이너 목록 확인).
- 비활성 인스턴스 시작(
docker compose up -d). - 새로운 인스턴스의 준비 상태 확인(헬스 체크, 최대 30회 시도, 2초 간격).
- nginx 구성 업데이트 및
nginx -s reload실행. - 모든 활성 HTTP 요청 완료 대기(보통 5초).
- 이전 인스턴스 중지(
docker compose stop).
웹 서비스 예시:
echo "server 127.0.0.1:${INACTIVE_PORT};" > "$UPSTREAM_CONF"
nginx -t && nginx -s reload
sleep 5
$COMPOSE stop web-${ACTIVE}
이 순서는 트래픽이 준비되지 않은 서비스로 절대 향하지 않도록 하고, 완전 전환 후에야 이전 인스턴스를 종료합니다.
데이터베이스 스키마 호환성과 마이그레이션
블루-그린 배포의 주요 도전 과제 중 하나는 동일한 데이터베이스에 대해 두 버전의 애플리케이션을 동시에 실행하는 것입니다. 오류를 피하기 위해 모든 마이그레이션은 뒤로 호환되어야 합니다.
권장 접근—2단계 업데이트:
- 첫 번째 배포: 코드에서 사용 중단된 필드/테이블 사용을 제거하지만 데이터베이스 구조는 유지. 새 버전과 이전 버전 모두 정상 작동.
- 두 번째 배포(트래픽 완전 전환 후): 사용되지 않는 스키마 요소 제거 마이그레이션 실행.
이 방법은 작업 횟수를 늘리지만 스키마 비호환으로 인한 이전 인스턴스 충돌 위험을 제거합니다.
핵심 포인트
- Docker Compose에서의 블루-그린 배포는 Kubernetes 없이 가능하지만 인스턴스와 프록시를 수동 관리해야 합니다.
- 워커의 graceful shutdown은 필수입니다—없으면 메시지가 손실되거나 중복될 수 있습니다.
- 모든 데이터베이스 마이그레이션은 뒤로 호환되어야 하며, 필드 제거는 2단계 접근이 필요합니다.
- 트래픽 전환 전에 새로운 인스턴스의 헬스 체크는 필수입니다.
- Nginx 구성은 원자적으로 업데이트되고
nginx -t로 검증되어야 합니다.
— Editorial Team
아직 댓글이 없습니다.