Moment Note

무중단 배포 완벽 비교: 블루-그린 vs 카나리

CI/CD & DevOps ·

운영 중인 서비스를 중단 없이 새 버전으로 바꾸는 일은 쉬워 보이지만, 실제로는 수백만 원짜리 장애를 유발하는 가장 흔한 원인 중 하나입니다. 블루-그린, 카나리, 롤링 업데이트—세 전략은 각각 뚜렷한 트레이드오프를 가지며, 잘못 선택하면 롤백이 오히려 더 큰 다운타임을 만들기도 합니다. 이 글에서는 세 전략의 동작 원리와 실전 구현 방법, 그리고 롤백 시나리오까지 낱낱이 비교합니다.

세 전략의 핵심 개념

블루-그린(Blue-Green)은 현재 운영 환경(Blue)과 동일한 용량의 새 환경(Green)을 병렬로 구성한 뒤, 로드밸런서 또는 DNS 레벨에서 트래픽을 한 번에 전환하는 방식입니다. 전환 순간까지 두 환경이 모두 살아있으므로 롤백이 빠르고 확실합니다. 단점은 리소스가 두 배 필요하다는 점입니다.

카나리(Canary)는 새 버전을 전체 트래픽의 일부(예: 5~10%)에만 먼저 노출하고, 에러율·지연시간 등 핵심 지표를 관찰하며 단계적으로 비중을 높이는 전략입니다. 실제 사용자 트래픽으로 검증하기 때문에 테스트 환경에서 잡지 못한 문제를 조기에 발견할 수 있습니다. 트래픽 분리 복잡도가 올라가고, 두 버전의 DB 스키마를 동시에 지원해야 하는 경우 설계가 까다롭습니다.

롤링 업데이트(Rolling Update)는 인스턴스 또는 파드를 하나씩(또는 소그룹씩) 순차적으로 교체하는 방식입니다. 추가 인프라 없이 제자리에서 교체하므로 비용 효율적이지만, 전환 중 두 버전이 동시에 요청을 처리합니다. 롤백 시 이미 교체된 인스턴스를 다시 내려야 하므로 시간이 걸립니다.

전략별 상세 비교

항목 블루-그린 카나리 롤링 업데이트
트래픽 전환 방식 한 번에 100% 비율 단계적 증가 인스턴스 순차 교체
추가 리소스 2배 (일시적) 소규모 추가 파드/VM 거의 없음
롤백 속도 매우 빠름 (DNS/LB 전환) 빠름 (비율 0%로) 느림 (재교체 필요)
버전 공존 기간 없음 (순간 전환) 수십 분~수 시간 교체 완료까지
DB 스키마 호환성 필요 (전환 전 마이그레이션) 필수 (양방향 호환) 필수 (양방향 호환)
복잡도 높음 낮음
적합한 상황 대규모 변경, 빠른 롤백 필요 위험 최소화, 점진 검증 소규모 패치, 비용 절감

쿠버네티스 환경 구현 예시

블루-그린: Service 셀렉터 전환

블루-그린의 핵심은 Service 오브젝트의 selector를 바꾸는 것입니다. 두 Deployment를 미리 올려두고, 준비가 완료되면 Service만 전환합니다.

# blue-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-blue
spec:
  replicas: 4
  selector:
    matchLabels:
      app: myapp
      slot: blue
  template:
    metadata:
      labels:
        app: myapp
        slot: blue
    spec:
      containers:
      - name: myapp
        image: myapp:v1.0.0
---
# green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-green
spec:
  replicas: 4
  selector:
    matchLabels:
      app: myapp
      slot: green
  template:
    metadata:
      labels:
        app: myapp
        slot: green
    spec:
      containers:
      - name: myapp
        image: myapp:v2.0.0
---
# service.yaml (처음엔 blue를 가리킴)
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  selector:
    app: myapp
    slot: blue   # ← 여기만 green으로 바꾸면 전환 완료
  ports:
  - port: 80
    targetPort: 8080

Green Deployment가 Ready 상태임을 확인한 뒤 아래 명령 하나로 전환합니다.

# 트래픽을 green으로 전환
kubectl patch service myapp-svc 
  -p '{"spec":{"selector":{"app":"myapp","slot":"green"}}}'

# 롤백이 필요하다면
kubectl patch service myapp-svc 
  -p '{"spec":{"selector":{"app":"myapp","slot":"blue"}}}'

카나리: Argo Rollouts 가중치 분할

쿠버네티스 네이티브로 카나리를 구현하는 가장 현실적인 방법은 Argo Rollouts입니다. steps 배열로 트래픽 비율과 대기 시간을 선언합니다.

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: myapp-rollout
spec:
  replicas: 10
  strategy:
    canary:
      steps:
      - setWeight: 5          # 1단계: 5% 전송
      - pause: {duration: 10m}
      - setWeight: 20         # 2단계: 20%
      - pause: {duration: 10m}
      - setWeight: 50
      - pause: {duration: 5m}
      - setWeight: 100        # 최종 전환
      analysis:               # 자동 분석 게이트
        templates:
        - templateName: error-rate-check
        startingStep: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:v2.0.0

pause 구간에서 Prometheus 지표(에러율, p99 지연시간)를 자동으로 검증하고 임계치 초과 시 자동 롤백됩니다. 수동으로 즉시 롤백하려면 kubectl argo rollouts abort myapp-rollout 명령을 씁니다.

롤백 전략과 DB 마이그레이션 주의사항

배포 전략을 고를 때 가장 먼저 물어야 할 질문은 “DB 스키마가 바뀌는가”입니다. 컬럼 추가처럼 하위 호환이 가능한 변경은 세 전략 모두 무난하지만, 컬럼 삭제나 타입 변경은 두 버전이 공존하는 카나리·롤링에서 심각한 문제를 일으킵니다.

실전에서 검증된 패턴은 Expand/Contract(확장-수축)입니다. ① 새 컬럼 추가(Expand) → ② 양방향 호환 코드 배포 → ③ 데이터 백필 → ④ 구 컬럼 제거(Contract) 순서로 진행하면 롤백 시점에도 DB가 안전합니다. 블루-그린이라도 전환 전에 반드시 Expand 단계까지만 마이그레이션을 완료해야 합니다.

롤백 의사결정 기준으로는 배포 직후 5분간 에러율 증가 여부를 모니터링하는 5분 룰이 널리 쓰입니다. Prometheus + Alertmanager 조합으로 rate(http_requests_total{status=~"5.."}[5m]) > 0.01 알람을 걸어두면 자동화가 가능합니다.

실전 팁: 전략 선택 기준

  • 스타트업·소규모 서비스: 롤링 업데이트가 기본값입니다. kubectl 기본 제공이고, 추가 비용이 없습니다. maxSurge/maxUnavailable로 속도를 조절하세요.
  • 결제·인증 등 고위험 변경: 블루-그린을 선택하세요. 롤백 시간이 수 초 이내여야 하고, 비용은 일시적으로 감수할 수 있는 경우입니다.
  • AI 모델 교체, 대규모 UX 변경: 카나리가 최적입니다. 특정 사용자 그룹(지역, 가입일, 등급)에게만 먼저 노출하는 타겟 카나리로 발전시키면 A/B 테스트와 결합할 수 있습니다.
  • 서버리스(Lambda, Cloud Run): 트래픽 가중치 기능이 네이티브로 제공되므로 카나리 구현 비용이 낮습니다. Lambda의 경우 aws lambda update-alias --routing-config로 비율을 조정합니다.

어떤 전략을 선택하든 헬스체크 엔드포인트(/healthz, /readyz)를 정확히 구현하는 것이 전제입니다. 헬스체크가 틀리면 롤아웃 자동화 전체가 무너집니다. Readiness probe는 “이 파드가 트래픽을 받을 준비가 됐는가”를 정확히 반영해야 하며, 초기화 완료 전에 OK를 반환하는 코드가 가장 흔한 실수입니다.

마무리

블루-그린은 확실하지만 비싸고, 카나리는 안전하지만 복잡하며, 롤링은 간단하지만 롤백이 느립니다. 정답은 없습니다. 변경의 위험도, 인프라 비용, 팀의 운영 성숙도를 함께 고려해 전략을 선택하고, 무엇보다 롤백 절차를 배포 전에 문서화하고 훈련해두는 것이 가장 중요합니다. 장애 중에 처음 만나는 명령어는 반드시 실수를 낳습니다.

자주 묻는 질문

Q. 블루-그린에서 두 배 비용이 부담스러운데 줄일 방법이 있나요?

A. Green 환경을 배포 직전에 오토스케일링으로 빠르게 프로비저닝하고, 전환 확인 후 Blue를 즉시 스케일 다운하면 두 환경이 동시에 풀 용량으로 운영되는 시간을 15~30분 내로 줄일 수 있습니다. Spot/Preemptible 인스턴스로 Green을 구성하면 비용을 추가로 절감할 수 있습니다.

Q. 카나리 배포 중 DB 마이그레이션이 실패하면 어떻게 되나요?

A. 카나리와 DB 마이그레이션은 반드시 분리해야 합니다. 마이그레이션은 코드 배포 이전에 완료하고(Expand만), 코드가 구버전·신버전 모두 새 스키마를 읽을 수 있도록 설계합니다. 마이그레이션 실패 시 코드 배포 자체를 시작하지 않는 게이트를 CI/CD 파이프라인에 삽입하는 것이 표준 방식입니다.

Q. 쿠버네티스 기본 롤링 업데이트와 Argo Rollouts 카나리, 어느 것을 먼저 도입해야 하나요?

A. 쿠버네티스를 막 도입했다면 내장 롤링 업데이트로 시작하세요. Argo Rollouts는 분석 게이트, 실험, 트래픽 가중치 분할이 필요해질 때 추가하는 것이 운영 부담을 낮추는 현실적인 순서입니다. 대부분의 팀은 6~12개월 롤링 운영 경험 후 카나리로 넘어갑니다.