Blue Green 배포와 Rolling 배포 비교

Blue Green 배포와 Rolling 배포 비교

한눈에 보기

Blue/Green은 기존 환경과 새 환경을 동시에 준비한 뒤 traffic destination을 전환한다. 문제가 생기면 이전 환경으로 다시 보내기 쉬운 대신, 전환 기간에 거의 두 벌의 용량과 환경 동기화가 필요하다. Rolling은 기존 instance를 작은 batch로 새 버전으로 교체해 추가 용량을 조절하기 쉽지만 배포 내내 두 버전이 같은 DB·cache·message를 함께 사용한다. 어떤 방식을 쓰든 rollback은 code만 과거로 돌리는 일이 아니다. Schema와 event가 backward compatible하고, 종료 중 instance의 connection이 drain되며, 자동 중단 기준이 있어야 한다.

목차

배포 전략은 새 버전을 섞는 방법이다

배포는 binary를 server에 복사하는 동작으로 끝나지 않는다. 사용자의 traffic을 어떤 비율과 순서로 새 version에 연결할지 결정해야 한다.

현재 상태: v1 instance 4개가 traffic 100% 처리
목표 상태: v2 instance 4개가 traffic 100% 처리

Blue/Green과 Rolling의 핵심 차이는 교체 단위다.

flowchart LR
    A[v1 fleet]
    B[v2 fleet]
    C[Traffic router]
    A --> C
    B --> C

둘 다 downtime을 줄일 수 있지만 “배포 명령이 성공했다”는 사실만으로 무중단이 보장되지는 않는다. 새 instance가 준비되기 전에 traffic을 받거나, 기존 instance가 요청 처리 중 종료되면 오류가 생긴다.

Blue Green 배포의 기본 흐름

현재 production인 blue와 별도의 green 환경을 만든다.

sequenceDiagram
    participant P as Pipeline
    participant B as Blue v1
    participant G as Green v2
    participant R as Router

    P->>G: Provision and deploy
    P->>G: Smoke test
    P->>R: Shift traffic to green
    R->>G: New requests
    P->>G: Observe
    P->>B: Decommission after rollback window

전환 전 green에는 production과 동일한 configuration contract, network policy, secret, autoscaling 기준이 있어야 한다. “동일한 환경”은 instance ID까지 같다는 뜻이 아니라 runtime 조건과 의존성이 동등하다는 뜻이다.

Blue/Green의 장점은 이전 환경을 그대로 남길 수 있다는 점이다.

정상: router → green v2
문제: router → blue v1

하지만 blue가 rollback target이 되려면 전환 이후에 생긴 데이터와 schema를 여전히 이해할 수 있어야 한다. Code environment만 보존했다고 rollback이 가능한 것은 아니다.

Rolling 배포의 기본 흐름

Rolling은 일부 instance를 제거하고 새 version으로 채우는 과정을 반복한다.

1단계  v1 v1 v1 v1
2단계  v1 v1 v1 v2
3단계  v1 v1 v2 v2
4단계  v1 v2 v2 v2
5단계  v2 v2 v2 v2

Kubernetes Deployment를 예로 들 수 있다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-api
spec:
  replicas: 4
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  minReadySeconds: 15
  progressDeadlineSeconds: 600

maxUnavailable: 0은 업데이트 중 desired replica보다 ready instance가 줄지 않게 하고 maxSurge: 1은 하나의 추가 Pod를 허용한다. Cluster에 추가 자원이 없으면 새 Pod가 schedule되지 않아 rollout이 멈출 수 있다.

예시 수치

Replica와 시간은 가상 값이다. 실제 traffic과 startup time, cluster capacity를 기준으로 정한다.

두 전략의 차이를 한눈에 비교하기

기준 Blue/Green Rolling
교체 단위 환경 전체 instance batch
신구 공존 전환 전후 두 환경 rollout 동안 같은 service
추가 용량 최대 거의 100% maxSurge만큼 조절
Code rollback traffic 재전환이 빠를 수 있음 이전 version을 다시 rollout
사전 검증 Green을 production traffic 전 test 새 batch readiness 중심
Blast radius 전환 비율에 따라 큼 batch 크기로 제한
환경 drift 위험 Blue/Green 설정 차이 같은 template이면 상대적으로 작음
Stateful data 두 환경 동기화가 어려움 공유 store 호환이 필수

표의 우열은 workload에 따라 달라진다. 예를 들어 traffic router가 하나의 환경만 0% 또는 100%로 전환한다면 Blue/Green의 첫 production traffic blast radius가 크다. Weight 전환을 지원하면 점진적으로 줄일 수 있다.

무중단을 결정하는 것은 Readiness와 Draining이다

새 instance는 process가 실행 중이라는 이유만으로 traffic을 받으면 안 된다. Configuration load, DB connection, cache warm-up처럼 요청 처리에 필요한 준비가 끝나야 한다.

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  periodSeconds: 5
  timeoutSeconds: 2
  failureThreshold: 3

기존 instance를 제거할 때도 endpoint 목록에서 빠지는 것과 실제 load balancer 전파에는 간격이 있다. Application은 종료 signal을 받으면 readiness를 내리고 새 요청을 거부하며 진행 중 요청을 drain한다.

sequenceDiagram
    participant O as Orchestrator
    participant P as Old instance
    participant L as Load balancer

    O->>P: Termination begins
    P->>P: readiness false
    O->>L: remove endpoint
    L--xP: stop new traffic
    P->>P: finish in-flight requests
    P-->>O: exit

종료 흐름은 컨테이너의 PID 1 문제와 시그널 처리와 연결된다.

Blue Green의 Traffic 전환은 즉시가 아닐 수 있다

Load balancer target group을 바꾸는 방식과 DNS record를 바꾸는 방식은 rollback 속도가 다르다.

DNS는 TTL과 client cache 때문에 일부 client가 이전 endpoint를 계속 사용할 수 있다.

00:00 DNS green으로 변경
00:10 일부 client green
02:00 오래 cache한 client blue

이 기간에는 Blue와 Green이 모두 실제 production traffic을 받을 수 있다. Blue를 즉시 종료하면 stale DNS client가 실패한다.

Router 수준의 target 전환도 existing TCP/WebSocket connection은 이전 environment에 남을 수 있다. 다음을 확인한다.

“한 번에 100% 전환”도 공존 기간이 있다

Control plane의 routing 설정과 실제 client connection이 동시에 바뀐다고 가정하지 않는다.

Rolling의 maxSurge와 maxUnavailable 계산하기

Replica 10개에서 maxUnavailable: 20%, maxSurge: 30%라면 Kubernetes는 percentage rounding 규칙에 따라 unavailable 허용량과 추가 Pod 수를 계산한다. 작은 replica 수에서는 percentage 하나가 큰 비율 차이를 만든다.

설정 가용성 추가 자원 속도
unavailable 0, surge 1 높음 1개 필요 비교적 느림
unavailable 1, surge 0 용량 감소 추가 없음 workload에 따라
unavailable 25%, surge 25% 균형 일부 필요 비교적 빠름

새 version의 CPU/memory가 늘었다면 기존 capacity 계산으로 surge Pod가 schedule되지 않을 수 있다. 반대로 autoscaler가 반응하기 전에 많은 Pod를 띄우면 resource pressure가 생긴다.

minReadySeconds는 잠깐 readiness를 통과했다가 바로 죽는 Pod를 안정된 것으로 너무 빨리 보지 않게 한다. progressDeadlineSeconds는 rollout 진행 정체를 상태로 표시하지만 그 자체가 모든 platform에서 자동 rollback을 수행한다고 가정해서는 안 된다. Pipeline이 상태를 읽고 중단·rollback하는 정책이 필요하다.

신구 버전이 공유하는 DB를 먼저 확인하기

Rolling 동안 v1과 v2는 같은 DB에 동시에 query한다. Blue/Green도 DB를 환경 밖에서 공유하는 구성이 흔하다.

Breaking schema 변경을 code와 한 번에 배포하면 한 버전이 깨진다.

-- 위험한 예: v1이 아직 old_name을 읽고 있다.
ALTER TABLE customer
  DROP COLUMN old_name;

호환 기간을 둔다.

1. 새 column 추가
2. v1과 v2가 공존 가능한 write/read 배포
3. backfill과 검증
4. v2로 완전 전환
5. rollback window 종료
6. old column 제거

Blue로 traffic을 되돌려도 v2가 저장한 새 enum, 긴 값, 새로운 state를 v1이 읽지 못하면 rollback이 실패한다. 이 문제는 무중단 배포에서 DB 마이그레이션 순서에서 확장한다.

Message와 Cache도 버전 호환이 필요하다

배포 중 v2 producer가 만든 event를 v1 consumer가 받을 수 있다.

{
  "eventType": "ORDER_CONFIRMED",
  "schemaVersion": 2,
  "orderId": "order_demo_42",
  "channel": "mobile"
}

새 field를 추가하고 구버전이 unknown field를 무시할 수 있다면 호환되기 쉽다. Required field 삭제나 의미 변경은 어렵다.

Cache도 serialization version이 다르면 역직렬화에 실패할 수 있다.

cache key = profile:v2:<user-id>

Versioned key로 분리하거나 두 version이 읽을 수 있는 format을 사용한다. Deploy 때 cache 전체 삭제에 의존하면 thundering herd와 DB 부하가 생길 수 있다.

Rollback이 실제로 가능한 시점

Rollback은 다음 세 층을 되돌릴 수 있어야 한다.

질문
Traffic 이전 instance로 다시 보낼 수 있는가
Code/config 이전 artifact와 config가 남아 있는가
Data/protocol 이전 code가 현재 data와 event를 이해하는가

Blue/Green의 traffic rollback은 router 변경으로 빠를 수 있다. Rolling rollback은 이전 image를 다시 batch 배포하므로 시간이 걸린다. 하지만 data compatibility가 깨졌다면 둘 다 안전하지 않다.

Rollback 가능 시점을 명시한다.

T0 green/rolling 시작
T1 traffic 전환 완료
T2 관찰 window
T3 backward compatibility 종료
T4 destructive migration

T3 전에는 code rollback이 가능해야 한다. T4 뒤에는 restore나 forward fix가 필요할 수 있다. Pipeline과 runbook에 이 경계를 기록한다.

Database restore는 단순 rollback이 아니다

전환 이후 정상 사용자가 만든 data를 과거 snapshot으로 되돌리면 유실된다. Schema rollback과 data recovery를 분리한다.

Session과 Background Job을 다루는 방법

In-memory session을 instance에 저장하면 Rolling 교체와 Blue/Green 전환 때 사용자가 logout될 수 있다. Shared session store 또는 stateless token을 사용하거나 session affinity의 전환 영향을 설계한다.

WebSocket은 connection이 오래 유지된다.

HTTP short request → 수 초 안에 drain
WebSocket session   → 수 시간 지속 가능

강제 종료 deadline, reconnect protocol, client backoff, resume token이 필요하다.

Background worker는 새/구 version이 같은 queue를 소비할 수 있다. Job payload schema와 side effect가 호환되어야 하며 중복 처리에 대비한다.

async function handleJob(job: JobEnvelope) {
  if (!supportedVersions.has(job.schemaVersion)) {
    await deadLetter(job, "unsupported_schema");
    return;
  }

  await processIdempotently(job.id, () => execute(job));
}

가상 예시다. Deploy 중 worker concurrency를 줄이거나 queue를 version별로 분리할 필요가 있는지 workload에 따라 정한다.

용량과 비용을 계산하기

Blue/Green은 전환 순간 양쪽 environment가 production scale에 가까울 수 있다.

평상시 100 instance
전환 시 blue 100 + green 100 + 검증 traffic 여유

Rolling은 maxSurge만큼 추가하지만 update 중 ready capacity와 실제 throughput이 같지는 않다. 새 version의 startup CPU spike와 cache cold miss가 있다.

Capacity 계산에 포함할 항목:

Blue와 Green이 각각 DB pool 100개를 열면 전환 중 connection이 두 배가 된다. Green warm-up을 production dependency에 그대로 흘려보내기 전에 제한한다.

Canary는 두 전략과 다른 축이다

Canary는 소량 traffic으로 위험을 제한하는 release 방식이다. Blue/Green의 green environment에 1% traffic을 먼저 보낼 수도 있고 Rolling의 첫 batch를 canary로 오래 관찰할 수도 있다.

flowchart LR
    A[New version]
    B[1 percent]
    C[10 percent]
    D[50 percent]
    E[100 percent]
    A --> B --> C --> D --> E

단순 instance 비율이 user traffic 비율과 같지 않을 수 있다. Sticky session, regional traffic, hot shard 때문에 canary가 특정 사용자군만 받을 수 있다.

Canary 분석은 sample size와 business metric을 고려한다. Error rate가 낮아도 checkout conversion이나 processing latency가 나빠질 수 있다.

자동 중단과 승격 기준 만들기

Pipeline의 “green healthy”는 health endpoint 한 번 성공보다 강해야 한다.

단계 확인
기동 모든 instance ready, crash loop 없음
Smoke 핵심 read/write path 성공
기술 지표 error rate, latency, saturation
업무 지표 주문 성공률, 결제 승인률
호환성 구버전 consumer와 DB query
보안 image provenance와 scan gate

가상 기준을 configuration으로 표현할 수 있다.

promotion:
  observationWindow: 15m
  minimumRequests: 10000
  gates:
    errorRateIncrease: "< 0.2%"
    p95LatencyIncrease: "< 15%"
    crashLoopCount: 0

실제 threshold는 baseline 변동과 SLO에서 정한다. Traffic이 적어 sample이 부족하면 자동 성공으로 처리할지, 관찰 시간을 늘릴지 결정한다.

Rollback signal도 사용자 영향 전에 탐지할 수 있어야 한다.

배포 전략 선택 질문

Blue/Green이 어울리는 경우:

Rolling이 어울리는 경우:

둘 중 하나를 조직 표준으로 정하더라도 stateful worker, edge server, mobile backend처럼 workload 특성에 따라 예외가 생긴다.

실패 시나리오를 포함한 검증

새 Version

공존과 종료

Rollback

구현 체크리스트

전략과 용량

호환성과 관측

복구

마무리

Blue/Green과 Rolling은 이름보다 신구 version을 어떤 범위와 시간 동안 공존시키는지가 중요하다. Blue/Green은 환경을 병렬로 준비해 traffic을 바꾸므로 code rollback이 빠를 수 있지만 이중 용량과 환경 동등성이 필요하다.

Rolling은 instance를 작은 batch로 교체해 추가 자원을 조절할 수 있지만 rollout 내내 두 version이 같은 DB, event, cache를 사용한다. maxSurgemaxUnavailable은 availability와 capacity 사이의 정책이다.

두 전략 모두 readiness와 connection draining이 없으면 무중단이 아니다. 또한 router만 되돌린다고 rollback이 완성되지 않는다. 새 version이 기록한 data를 이전 version이 읽을 수 있어야 하고 destructive migration은 rollback window 뒤로 미뤄야 한다.

결국 배포 전략은 infrastructure 옵션 하나가 아니라 호환성, 용량, 관측, 중단 기준, 복구 시간을 함께 정하는 운영 계약이다.

관련 노트

참고 자료