728x90
반응형
배경: 백엔드 빌드 중 다운타임 문제 논의 중 정리
핵심 개념
운영 환경을 항상 두 벌 유지한다.
[사용자]
│
[로드밸런서 / nginx]
│
├──→ [Blue 환경] ← 현재 운영 중 (트래픽 100%)
│
└──→ [Green 환경] ← 대기 중 (트래픽 0%)배포 순서:
1. Green에 새 버전 배포 + 테스트
2. 로드밸런서 전환 → Green이 운영 (트래픽 100%)
3. Blue는 대기 상태로 전환다음 배포 때는 Blue에 올리고 또 전환. 계속 교대.
장단점
장점
| 항목 | 내용 |
|---|---|
| 다운타임 0 | 전환이 nginx reload 수준 (수 밀리초) |
| 즉시 롤백 | 문제 생기면 이전 환경으로 트래픽 전환 — 재빌드 불필요 |
| 운영과 동일 환경 테스트 | Green이 실제 운영 인프라에서 뜬 채로 검증 가능 |
| 안전한 DB 마이그레이션 | 전환 전 Green에서 migration 결과 확인 가능 |
단점
| 항목 | 내용 |
|---|---|
| 인프라 비용 2배 | 서버/컨테이너 두 벌 항상 유지 |
| DB 공유 문제 | Blue/Green이 같은 DB를 보면 스키마 변경 시 충돌 가능 |
| 세션/캐시 동기화 | 전환 순간 기존 세션이 끊길 수 있음 (Stateless면 무관) |
| 구성 복잡도 | 단순 배포보다 CI/CD 스크립트가 복잡해짐 |
DB 스키마 변경 시 주의사항
Blue-Green의 가장 까다로운 부분. 전환 찰나에 두 버전이 같은 DB를 동시에 바라보는 순간이 생긴다.
Blue: v1 코드 → v1 스키마 읽음
Green: v2 코드 → v2 스키마 읽음 (컬럼 추가/변경)
↑ 전환 순간 두 버전이 같은 DB를 동시에 바라봄해결책: Expand-Contract 패턴
1단계 (Expand): DB에 새 컬럼 추가 (기존 컬럼 유지)
→ Blue는 새 컬럼 무시하고 정상 동작
2단계 (전환): Green으로 트래픽 이동
3단계 (Contract): 다음 배포 때 기존 컬럼 제거한 번에 스키마를 바꾸지 않고, 추가 → 전환 → 제거 두 단계로 나눠서 진행하는 방식.
유사 전략 비교
| 방식 | 다운타임 | 롤백 속도 | 인프라 비용 | 복잡도 |
|---|---|---|---|---|
| 기존 (stop→run) | 있음 | 재배포 필요 | 1배 | 낮음 |
| Blue-Green | 없음 | 즉시 | 2배 | 중간 |
| Rolling Update | 거의 없음 | 느림 | 1배 | 중간 |
| Canary | 없음 | 즉시 | 2배+ | 높음 |
Rolling Update
인스턴스를 하나씩 교체. 여러 인스턴스가 있을 때 유효.
v1, v1, v1 → v2, v1, v1 → v2, v2, v1 → v2, v2, v2Canary
일부 트래픽만 새 버전으로 서서히 전환. 문제 조기 감지 목적.
트래픽 5% → Green(신규)
트래픽 95% → Blue(기존)
이상 없으면 10% → 50% → 100% 순차 확대이 프로젝트(가계부)에 적용한다면
현재 문제: CI 배포 시 docker stop → docker run 사이 다운타임 발생.
최소 구현안 (컨테이너명 교체 방식)
Docker 네트워크 내에서 컨테이너명으로 통신하므로 호스트 포트 충돌 없이 Blue-Green 구현 가능.
1. 새 이미지로 backend-green 컨테이너 기동 (호스트 포트 노출 없음)
2. /actuator/health 헬스체크 통과 확인
3. nginx upstream을 backend-blue → backend-green으로 변경
4. nginx reload (graceful, 기존 커넥션 유지)
5. backend-blue 컨테이너 종료
6. 다음 배포를 위해 green/blue 역할 파일에 기록# nginx upstream 설정 예시
upstream backend {
server backend-green:8080; # 활성 환경에 따라 CI가 교체
}
CI 스크립트 변경 포인트
# 현재
docker stop backend-prod
docker run --name backend-prod ...
# Blue-Green 적용 후
ACTIVE=$(cat /deploy/active) # "blue" or "green"
NEXT=$([ "$ACTIVE" = "blue" ] && echo "green" || echo "blue")
docker run --name backend-$NEXT ...
# 헬스체크
sed -i "s/backend-$ACTIVE/backend-$NEXT/" /etc/nginx/upstream.conf
nginx -s reload
docker stop backend-$ACTIVE
echo $NEXT > /deploy/active
전제 조건
- Spring Boot Actuator 의존성 추가 (
/actuator/health엔드포인트) - 서버 메모리가 컨테이너 2개 동시 실행 가능한지 확인
- nginx 설정에서 upstream을 동적으로 교체 가능한 구조
참고
- 현재 프로젝트는 소규모라 빌드 다운타임(1~2분)을 감수하는 것도 실용적인 선택
- 트래픽이 늘거나 SLA가 중요해지는 시점에 도입 검토
- Kubernetes 사용 시
RollingUpdate전략이 기본값으로 제공됨
728x90
반응형
'개발환경, 인프라 > Docker' 카테고리의 다른 글
| [CI/CD] 깃랩 러너 볼륨 할당 문제 (0) | 2026.04.07 |
|---|---|
| [Docker] .gitlab-ci.yml, 잡컨테이너, docker-compose (0) | 2026.01.24 |
| 다중 환경 격리 구조 (0) | 2026.01.10 |
| 클라우드플레어 DDNS 설정 (0) | 2026.01.03 |
| 도커 이미지 레이어 수정에 따른 빌드 차이 확인 (0) | 2024.10.07 |
댓글