--- id: devops-deployment-strategies title: 배포 전략 — Blue-Green / Canary / Rolling category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [devops, deployment, blue-green, canary, vibe-coding] tech_stack: { language: "Kubernetes / ECS / Lambda", applicable_to: ["Backend"] } applied_in: [] aliases: [blue-green, canary, rolling update, traffic shifting] --- # 배포 전략 > 사용자가 다운타임 / 사고를 보지 않게 하는 방법. **Rolling (점진), Blue-Green (즉시 전환), Canary (소수 → 전체)** 3종이 표준. 트래픽이 클수록 canary 가 안전. ## 📖 핵심 개념 - **Rolling**: 한 번에 N% 인스턴스 새 버전. 마지막까지 구버전 / 신버전 공존. - **Blue-Green**: 새 환경 (green) 풀 가동 → LB 한 번에 전환. - **Canary**: 신버전을 트래픽 1-5% 만 → 메트릭 확인 → 점진 확대. - **Feature flag**: 코드 deploy ≠ release. 가장 유연. ## 💻 코드 패턴 ### Kubernetes Rolling ```yaml apiVersion: apps/v1 kind: Deployment metadata: { name: api } spec: replicas: 10 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 # 한 번에 1개만 down maxSurge: 2 # 최대 2개 추가 template: spec: containers: - name: api image: api:v2 readinessProbe: { httpGet: { path: /ready, port: 8080 } } ``` readinessProbe 가 통과하기 전에는 traffic 안 받음. 부드러운 교체. ### Blue-Green (Argo Rollouts) ```yaml apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: { name: api } spec: strategy: blueGreen: activeService: api-active previewService: api-preview autoPromotionEnabled: false # 수동 승인 scaleDownDelaySeconds: 300 # 5분 후 옛것 down template: { ... v2 ... } ``` 옛 버전 (blue) 와 새 버전 (green) 동시 가동. service selector 만 바꿔 즉시 전환. 문제 시 즉시 롤백. ### Canary (Argo Rollouts) ```yaml spec: strategy: canary: maxSurge: "20%" maxUnavailable: 0 steps: - setWeight: 5 # 5% 트래픽 - pause: { duration: 5m } - analysis: # Prometheus 메트릭 자동 검증 templates: [ { templateName: success-rate } ] - setWeight: 25 - pause: { duration: 10m } - setWeight: 50 - pause: { duration: 10m } - setWeight: 100 ``` 자동 metric analysis → 임계값 미달 시 자동 롤백. ### Database 호환성 (deploy 와 함께) - expand-contract 패턴 (`DB_Migration_Safety.md` 참고). - 코드 N+1 버전이 schema N 도, N+1 도 호환되어야. ### Feature flag 결합 (가장 안전) ```ts if (await flags.isOn('checkout-v2', { userId })) { return newCheckoutFlow(); } return oldCheckoutFlow(); ``` 코드는 deploy, release 는 flag toggle. 사고 시 flag off — 재배포 X. ## 🤔 의사결정 기준 | 상황 | 권장 | |---|---| | 단일 인스턴스 | rolling 의미 없음. 짧은 down 또는 blue-green | | 작은 팀, 트래픽 적음 | rolling | | 트래픽 큼, 사고 비싼 | canary + auto-analysis | | Stateful (DB schema 변경) | expand-contract + canary | | Lambda / serverless | alias + weighted (canary 자연스러움) | | 모바일 앱 | staged rollout (Play Store / App Store) | ## ❌ 안티패턴 - **readinessProbe 없는 rolling**: 새 인스턴스가 준비 전 traffic 받음 → 사용자 에러. - **hot deploy without graceful shutdown**: 진행 중 요청 cut. - **DB 변경 + 코드 변경 동시**: 신구 코드가 다른 schema 가정 → 사고. expand-contract. - **canary 메트릭 없음**: "잘 되는지" 모르고 100% 확대. - **롤백 절차 없음**: 사고 시 panic. 1-click 또는 auto. - **environment 분리 없음**: dev = prod = 한 클러스터. - **secret 도 deploy 와 같이 변경**: rotation 따로. - **canary 가 5% 인데 그 5% 가 가장 활성 사용자**: 표본 편향. 라우팅 균등. ## 🤖 LLM 활용 힌트 - 트래픽 클수록 canary + analysis. - DB 변경은 항상 expand-contract. - Feature flag 가 release 의 진짜 단위. ## 🔗 관련 문서 - [[Feature_Flags_in_Practice]] - [[DB_Migration_Safety]] - [[Backend_Health_Check_Patterns]]