ブルーグリーンとカナリア、何を引き換えにするのか
한국어 원문으로 표시합니다.
한 줄 요약
블루그린과 카나리는 좋고 나쁨의 문제가 아니라, 롤백 속도·트래픽 제어 정밀도·리소스 비용 사이에서 무엇을 살 것인가의 문제다.
왜 이게 필요했나
배포를 한 번에 갈아 치우면 문제가 생겼을 때 되돌릴 시간이 곧 장애 시간이 된다. 그래서 배포 전략은 전부 "새 버전에 얼마나 조금씩 노출할 것인가"와 "문제가 보이면 얼마나 빨리 되돌릴 것인가"를 조절하는 장치다.
블루그린은 같은 규모의 두 환경을 띄워 두고 트래픽을 한 번에 전환한다. 전환 전에 prePromotionAnalysis 로 스모크 테스트를 돌려 그린이 정상인지 확인하고, 전환 후에는 scaleDownDelaySeconds 를 300~600초로 두어 구버전을 잠시 살려 둔다. 이 시간이 지나면 이전 버전 Pod 이 종료되므로 롤백 시 새로 Pod 을 생성해야 해 시간이 더 걸린다. 즉 이 딜레이가 곧 즉시 롤백의 유효기간이다.
카나리는 5% → 분석 → 20% → 50% → 100% 처럼 비율을 올리며 매 단계 지표로 판정한다. 여기서 순서가 결정적이다. setWeight 가 먼저 실행되어 카나리에 트래픽이 흐른 뒤에 analysis 가 시작되어야 실제 트래픽 기반 메트릭이 모인다. 순서를 뒤집으면 아무 데이터도 없는 상태에서 판정하게 된다.
어떻게 동작하나
자동 중단 임계값은 실사용에서 이런 모양이다. 성공률 0.99 이상(interval 30s, count 10, failureLimit 2), p95 지연 300ms 이하, 에러 로그율 0.005 이하. 조직 표준 SLO 가 성공률 99%, P95 300ms 이하라면 카나리 임계값도 거기에 맞춰야 앞뒤가 맞는다.
가장 흔한 함정은 Inconclusive 다. 카나리 트래픽이 너무 적어 쿼리가 NaN 을 반환하면 판정이 계속 미결로 남는다. 대응은 두 가지다. default(result[0], 1) 처럼 기본값을 주거나, analysis 앞에 pause 를 둬 표본을 모은다. 표본이 0 이면 판단할 수 없다는 사실 자체를 파이프라인이 알아야 한다. 그래서 잘 만든 분석 스크립트는 요청 수가 0 일 때 통과가 아니라 실패를 낸다.
선택 기준은 표로 정리된다. 트래픽 제어 정밀도는 카나리가 높고(1% 단위) 블루그린은 없다. 롤백 속도는 블루그린이 매우 빠르다. 리소스 비용은 블루그린이 Pod 2배다. 데이터 스키마 변경은 블루그린이 상대적으로 단순하다. 일반 규칙은 이렇다. 대부분의 서비스에는 카나리를, 결제나 인증처럼 한 건의 오류도 비용이 큰 서비스에는 블루-그린을. 롤링 업데이트를 쓴다면 표준값은 maxSurge 1, maxUnavailable 0 이다.
현장에서 만나는 모습
전략을 아무리 잘 골라도 DB 마이그레이션이 끼면 롤백이 깨진다. 롤링이든 블루그린이든 신·구 코드가 동시에 떠 있는 구간이 수십 초에서 수 분간 반드시 존재하기 때문이다. 스키마를 먼저 바꾸면 구 버전 코드가 깨지고, 코드를 먼저 바꾸면 새 코드가 아직 없는 스키마를 참조하다 깨진다. 어느 쪽을 먼저 해도 한쪽이 깨진다.
해법은 Expand-Contract 3단계다. Expand 에서 구·신 구조를 공존시키고, Migrate 에서 백필과 더블 라이트를 하고, Contract 에서 구 구조를 제거한다. 핵심은 롤백 비대칭성이다. Expand 롤백은 무시하면 되고 Migrate 롤백도 안전하지만, Contract 롤백은 구 컬럼을 이미 지웠으므로 단순 코드 롤백으로 못 돌아간다. 그래서 격언이 남는다. Expand 는 자유롭게, Contract 는 신중하게. 가장 흔한 실수는 한 릴리스에 Expand 와 Contract 를 같이 넣는 것이다.
되돌릴 수 없는 것들
배포 전략의 값어치는 되돌릴 수 있다는 데서 나온다. 그런데 어떤 것은 트래픽을 되돌려도 함께 돌아오지 않는다. 전략을 고르기 전에 이 목록을 먼저 확인해야 한다.
이미 보낸 것. 메일, 알림, 결제 승인, 외부 시스템에 보낸 요청. 새 버전이 잘못 보냈다면 롤백은 더 보내는 것을 멈출 뿐이고 이미 나간 것은 취소 안내를 한 통 더 보내는 수밖에 없다. 그래서 바깥으로 나가는 부작용이 있는 변경은 카나리 비율을 특히 작게 시작하고, 되돌릴 수 없는 지점을 배포 뒤로 미룰 수 있는지 먼저 본다.
지워진 데이터. 앞에서 본 Expand-Contract 의 Contract 가 이것이다. 컬럼을 지운 뒤에는 코드만 되돌려도 그 컬럼이 돌아오지 않는다.
형식이 바뀐 채로 쌓인 것. 새 버전이 캐시나 큐에 새 형식으로 써 넣었는데 롤백하면, 옛 버전이 그것을 읽다 실패한다. 캐시는 형식이 바뀔 때 열쇠도 함께 바꾸는 것이 이 문제를 통째로 없애는 방법이고, 큐라면 옛 버전이 새 형식을 건너뛸 수 있어야 한다.
한 방향으로만 가는 이전. 데이터를 새 저장소로 옮기면서 원본을 더 이상 쓰지 않게 만들면, 그 시점부터 롤백은 그 사이에 쌓인 것을 잃는다는 뜻이 된다.
그래서 배포 계획을 세울 때 두 가지를 함께 적어 둔다. 되돌리는 절차와 되돌릴 수 없는 지점이 언제인가이다. 뒤의 것을 적어 두지 않으면, 장애 한가운데에서 "지금 되돌려도 되나" 를 처음 판단하게 된다. 그 순간에는 아무도 차분하지 않다.
다음 실습에서 할 것
이 파드에는 Argo Rollouts 도 로드밸런서도 없다. 그래서 컨테이너 두 개를 8091(blue), 8092(green)에 띄우고, 활성 대상을 파일 하나로 표현해 전환·헬스체크·자동 롤백을 셸로 만든다. 카나리 비율 분배와 자동 중단 판정도 같은 방식으로 손에 익힌다. 트래픽을 어디로 보낼지 정하는 것이 파일 한 줄이라는 사실을 보고 나면, 실제 컨트롤러가 하는 일이 훨씬 선명해진다.