본문으로 건너뛰기
무중단 배포 가이드 - Blue-Green, Canary 전략
Table of Contents

배포 중 서비스가 멈추는 악몽

금요일 새벽 4시, 새로운 기능을 배포하기 위해 서비스를 잠시 중단했습니다. ‘5분이면 충분하겠지’라고 가볍게 생각했지만, 현실은 달랐습니다. 예상치 못한 데이터베이스 마이그레이션 에러가 발생했고, 5분이라던 계획은 30분의 장애로 이어졌습니다.

$ kubectl apply -f deployment-v2.yaml
deployment.apps/payment-service configured

# 5분 후...
$ kubectl get pods
NAME                              READY   STATUS             RESTARTS
payment-service-v2-7d4c8-qwert    0/1     CrashLoopBackOff   5

# 사용자들의 불만이 쏟아집니다
[Slack #alerts] Payment API returning 502 errors
[Slack #alerts] 500+ users affected
[Slack #support] Customers can't complete checkout

다운타임: 23분 영향받은 사용자: 1,247명 예상 매출 손실: $8,500

롤백을 시도하려 했지만, 이미 데이터베이스 스키마가 변경되어 이전 버전으로 되돌리는 것조차 쉽지 않았습니다. 결국 프로덕션 환경에서 급하게 핫픽스를 적용하느라 30분 넘게 서비스가 불안정했습니다.

“배포할 때마다 이렇게 마음을 졸여야 할까요?”

이것이 바로 우리가 **무중단 배포(Zero Downtime Deployment)**를 반드시 도입해야 하는 이유입니다.

이 글에서는 롤링 업데이트(Rolling Update), 블루-그린(Blue-Green), 카나리(Canary) 배포 전략을 활용하여 중단 없이 안전하게 프로덕션을 배포하는 방법과 2025년 쿠버네티스(Kubernetes) 환경에서 검증된 실전 패턴을 다룹니다.

다운타임이 초래하는 비용

1분의 중단이 가져오는 손실

업종별로 1분의 다운타임이 발생시키는 비용은 생각보다 큽니다.

  • E-commerce (대형): $11,000
  • 금융 서비스: $9,000
  • 전자상거래 (중소형): $3,600
  • SaaS 서비스: $2,300
  • 미디어/뉴스: $1,500

평균적으로 배포 중단 시간이 15분이라고 가정할 때, 중소형 서비스조차 약 $54,000의 손실을 입을 수 있습니다.

기존 배포 방식의 문제점

전통적인 배포 방식은 다음과 같은 위험을 안고 있습니다.

  1. 서비스 중단 후 업데이트: 기존 Pod를 모두 삭제하고 새 Pod가 뜰 때까지 서비스가 멈춥니다.
  2. 롤백 불가능한 데이터베이스 변경: 스키마 변경이 호환성을 고려하지 않고 이루어지면 되돌릴 수 없습니다.
  3. 검증되지 않은 버전의 즉시 배포: 모든 트래픽이 한 번에 새 버전으로 이동하여, 버그가 있을 경우 모든 사용자가 영향을 받습니다.
  4. 수동 롤백의 어려움: 장애 발생 시 롤백 명령어를 찾고 실행하는 데 귀중한 시간이 소모됩니다.

무중단 배포의 효과

  1. 100% 서비스 가용성: 사용자는 배포가 진행되는지조차 느끼지 못합니다.
  2. 안전하고 빠른 롤백: 문제 발견 시 30초 이내에 이전 버전으로 복구할 수 있습니다.
  3. 점진적 검증: 소수의 사용자에게 먼저 테스트하여 리스크를 최소화합니다.
  4. 비즈니스 리스크 제거: 배포 실패로 인한 매출 손실과 브랜드 이미지 타격을 방지합니다.

3가지 핵심 무중단 배포 전략

각 전략은 상황과 목적에 따라 선택할 수 있습니다.

전략다운타임인프라 비용롤백 속도복잡도추천 사례
롤링 업데이트 (Rolling)없음기존 인프라 유지~2분낮음일반적인 배포
블루-그린 (Blue-Green)거의 없음2배 (일시적)<30초중간즉시 롤백 필요 시
카나리 (Canary)없음1.1~1.2배<30초높음고위험 배포

트래픽 흐름 비교

  • Rolling Update: 기존 버전을 하나씩 새 버전으로 교체합니다. (점진적, 5~10분 소요)
  • Blue-Green: 새 버전을 완벽히 준비한 후 트래픽을 한 번에 전환합니다. (즉시 전환)
  • Canary: 소수의 사용자(5%)에게 먼저 배포하고 점차 확대합니다. (검증 위주, 30분~2시간 소요)

롤링 업데이트 (Rolling Update)

개념

쿠버네티스의 기본 배포 전략으로, 기존 Pod를 하나씩 새 버전으로 교체합니다. 인프라 자원을 효율적으로 사용하면서 무중단 배포를 구현할 수 있습니다.

쿠버네티스 설정 예시

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-service
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # 최대 1개 Pod 추가 생성 가능
      maxUnavailable: 1  # 최대 1개 Pod 중단 가능
  template:
    metadata:
      labels:
        app: payment-service
        version: v2
    spec:
      containers:
      - name: payment
        image: payment-service:v2.0.0
        ports:
        - containerPort: 8080
        
        # Readiness Probe: 트래픽을 받을 준비가 되었는지 확인
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          failureThreshold: 3
          
        # Liveness Probe: 컨테이너가 정상적으로 살아있는지 확인
        livenessProbe:
          httpGet:
            path: /health/live
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          failureThreshold: 3
          
        # Graceful Shutdown: 종료 시 기존 요청 처리 대기
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 15"]

장점과 단점

  • 장점: 추가 인프라 비용이 거의 들지 않고, 설정이 간편합니다.
  • 단점: 배포 중간에 구버전과 신버전이 공존하므로 호환성 문제가 발생할 수 있으며, 롤백에 시간이 다소 소요됩니다.

블루-그린 (Blue-Green) 배포

개념

현재 운영 중인 환경(Blue)과 동일한 환경(Green)을 하나 더 구성하여 새 버전을 배포합니다. Green 환경에서 충분한 테스트를 마친 후, 로드밸런서나 서비스의 트래픽을 Green으로 즉시 전환합니다.

쿠버네티스 구현 방법

  1. **Blue 환경 (v1)**이 운영 중인 상태에서 **Green 환경 (v2)**을 배포합니다.
  2. Green 환경의 Pod가 모두 준비되고 헬스 체크를 통과했는지 확인합니다.
  3. Service의 라벨 셀렉터(Label Selector)를 변경하여 트래픽을 Green으로 전환합니다.
# 트래픽 전환 예시
kubectl patch service payment-service -p '{"spec":{"selector":{"version":"green"}}}'

장점과 단점

  • 장점: 문제 발생 시 30초 이내에 이전 환경(Blue)으로 즉시 롤백할 수 있습니다. 실제 운영 환경과 동일한 상태에서 테스트가 가능합니다.
  • 단점: 두 배의 리소스가 필요하므로 비용 부담이 있습니다. 데이터베이스 스키마 변경 시 호환성 유지에 주의해야 합니다.

카나리 (Canary) 배포

개념

광산의 카나리아처럼, 위험을 감지하기 위해 소수의 사용자에게만 먼저 새 버전을 배포합니다. 문제가 없으면 점진적으로 트래픽 비율을 높여(5% -> 25% -> 50% -> 100%) 전체에 배포합니다.

Nginx Ingress를 활용한 구현

Nginx Ingress Controller의 Annotation을 사용하여 정교한 트래픽 분할이 가능합니다.

# ingress-canary.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: payment-service-canary
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10" # 10% 트래픽만 전달
spec:
  # ... (생략)

고급 라우팅

  • 헤더 기반: 특정 헤더(X-Canary: true)를 가진 요청만 새 버전으로 보낼 수 있어 내부 테스터에게 유용합니다.
  • 쿠키 기반: 특정 쿠키를 가진 사용자 그룹을 지정하여 테스트할 수 있습니다.

장점과 단점

  • 장점: 실제 사용자 트래픽으로 검증하므로 신뢰도가 높고, 문제 발생 시 영향 범위를 최소화할 수 있습니다.
  • 단점: 설정과 모니터링이 복잡하며, 전체 배포 완료까지 시간이 오래 걸립니다.

어떤 전략을 선택해야 할까요?

  • 일반적인 웹 서비스: 롤링 업데이트로 충분한 경우가 많습니다. 리소스 효율성이 좋고 관리가 편합니다.
  • 결제, 금융 시스템: 블루-그린 배포가 적합합니다. 장애 시 즉각적인 롤백이 무엇보다 중요하기 때문입니다.
  • 대규모 플랫폼, 핵심 기능 변경: 카나리 배포를 권장합니다. 일부 사용자에게 먼저 검증하여 대형 장애를 예방해야 합니다.

무중단 배포와 데이터베이스 마이그레이션

애플리케이션은 무중단으로 배포하더라도, 데이터베이스 스키마가 변경되면 장애가 발생할 수 있습니다. 이를 방지하기 위해 3단계 마이그레이션을 적용해야 합니다.

  1. 확장 (Expand): 새 컬럼을 추가하되, 기존 코드는 구 컬럼을 계속 사용합니다. (하위 호환성 유지)
  2. 전환 (Migrate): 애플리케이션을 새 컬럼을 사용하도록 업데이트하여 배포합니다. 데이터도 마이그레이션합니다.
  3. 축소 (Contract): 더 이상 사용하지 않는 구 컬럼을 삭제합니다.

결론

무중단 배포는 단순한 기술적 선택이 아니라, 사용자 경험과 비즈니스 안정성을 지키기 위한 필수 요건입니다.

  • 가용성: 배포 중에도 서비스는 멈추지 않습니다.
  • 안정성: 문제 발생 시 즉시 되돌릴 수 있는 안전장치를 마련합니다.
  • 속도: 개발팀은 두려움 없이 더 자주, 더 빠르게 배포할 수 있습니다.

여러분의 상황에 맞는 전략을 선택하여, 다음 배포부터는 “배포 공포증”에서 벗어나시길 바랍니다.

이 글 공유하기:
My avatar

글을 마치며

이 글이 도움이 되었기를 바랍니다. 궁금한 점이나 의견이 있다면 댓글로 남겨주세요.

더 많은 기술 인사이트와 개발 경험을 공유하고 있으니, 다른 포스트도 확인해보세요.

유럽살며 여행하며 코딩하는 노마드의 여정을 함께 나누며, 함께 성장하는 개발자 커뮤니티를 만들어가요! 🚀


관련 포스트