TechFeedTechFeed
Cloud & DevOps

카나리 배포, 헬스체크, 에러율, 롤백 | 5% 트래픽에서 잡힌 회귀는?

카나리 배포 5% 승격 직후 결제 API 에러율이 뛴 백엔드 장애 케이스다. 헬스체크 초록·전체 평균 희석 미탐, 전량 롤백, deploy_group 슬라이스 메트릭, stable 대비 승격 게이트, 5→20→50→100 단계 승격과 자동 중단 전후 지표를 문제→시도→결과로 정리한다. 쿠버네티스·데브옵스·백엔드·API·개발자·관측·기능 플래그 연계 실무 가이드.

by

목요일 14:22, 스테이징에서 이틀 돌린 결제 API 핫픽스가 프로덕션 카나리 5%에 올라갔다. 레디니스 프로브는 초록, 배포 파이프라인은 초록, 슬랙 배포 채널에도 "canary healthy" 알림이 떴다. 14분 뒤 결제 5xx가 정상의 6배로 뛰었고, 온콜은 전량 롤백 버튼을 눌렀다.


문제는 코드 한 줄이 아니었다. 카나리 트래픽을 "살아 있음"만으로 통과시킨 관측이 문제였다. 헬스체크는 통과하는데 비즈니스 에러율·지연·특정 테넌트만 깨지는 회귀를 보지 못했다. 이 기록은 B2B 구독 결제 백엔드 팀이 카나리 5% 실패 → 전량 롤백 → 분석 파이프라인 재설계까지 간 문제·시도·결과를 시간순으로 복원한 케이스다. 기업명과 일부 수치는 익명 처리했다.


※ 2026년 상반기 배포 포스트모템·런북 초안을 바탕으로 재구성. 시각·비율은 교육용으로 단순화.


무엇이 깨졌나 | 14:22~15:18 타임라인

서비스는 쿠버네티스 Deployment 2개(stable / canary) 앞에 인그레스 가중치 라우팅을 둔 구조였다. 새 버전은 이미지 태그 한 칸, 환경 변수 두 개, 결제 벤더 SDK 마이너 업데이트가 묶여 있었다. 카나리 비율은 5% 고정, 승격은 수동 승인 한 번이었다.


시각사건관측
14:22canary 파드 3대 Ready/healthz 200, 배포 초록
14:24인그레스 가중치 95/5 적용전체 5xx 아직 정상 범위
14:31canary 쪽 p95 지연 상승대시보드는 전체 평균만 봄 → 미탐
14:36결제 확인 API 4xx/5xx 혼합 증가특정 테넌트 3곳이 먼저 티켓
14:48온콜 호출, 카나리 로그 필터 시작version=canary 라벨 누락 구간 발견
15:02가중치 0/100 롤백에러율 4분 내 정상대 복귀
15:18포스트모템 킥오프장애 체감 약 56분

전체 트래픽 기준으로 보면 5xx 상승폭은 "살짝 빨간" 정도였다. 카나리 5%에 몰린 실패가 평균에 희석된 탓이다. 고객 티켓은 평균보다 먼저 왔다.


카나리 배포 5% 트래픽과 전체 평균 메트릭이 어긋나는 개념도
전체 평균은 초록인데 카나리 슬라이스만 빨간 전형적인 희석 패턴

원인 분해 | 헬스체크 초록이 가린 네 가지

레디니스 프로브는 프로세스 기동과 DB 핑만 봤다. 결제 벤더 SDK 초기화 경로의 타임아웃·서명 헤더 변경은 프로브 범위 밖이었다. 포스트모템에서 묶은 원인은 네 갈래다.


  • 관측 단위 오류 — 성공률·지연·에러를 Deployment 전체 평균으로만 알림. canary 라벨 슬라이스가 대시보드에 없었다.
  • 라벨·트레이스 누락 — 일부 미들웨어가 version 라벨을 응답 메트릭에 안 붙였다. 카나리 실패를 stable로 오인하는 구간이 생겼다.
  • 스티키·캐시 혼선 — 세션 스티키가 있는 경로에서 같은 사용자가 stable과 canary를 오가며 서명 키 불일치 4xx가 났다.
  • 승격 기준이 기술 헬스뿐 — "파드 Ready + 5분간 전체 5xx < 1%" 만 있으면 수동 승격 가능. 결제 성공률·특정 엔드포인트·테넌트 슬라이스가 기준에 없었다.

기능 플래그로 코드 경로만 나누는 롤아웃과 겹치는 교훈이다. 트래픽 비율을 나눈 뒤에는 그 비율 안에서의 실패를 따로 봐야 한다. 관련: 기능 플래그 롤아웃 체크리스트, Unleash 기능 플래그 도입 케이스.


포스트모템 한 줄: "카나리는 5%만 태운 것이 아니라, 실패 신호도 5%로 희석했다. 평균이 아니라 슬라이스를 봤어야 했다."

시도 1 | 전량 롤백과 이미지 고정

당일 응급 조치는 단순했다. 인그레스 가중치를 0/100으로 돌리고 canary Deployment 레플리카를 0으로 내렸다. 에러율은 4분 안에 정상대로 돌아왔다. 이미지는 이전 태그로 고정했고, 벤더 SDK 업데이트가 들어간 커밋은 release 브랜치에서 분리했다.


롤백 자체는 성공했다. 다만 사후에 보면 롤백 결정까지 40분이 걸렸다. 그 사이 온콜은 전체 로그를 뒤졌고, 카나리만 필터하는 쿼리가 런북에 없었다. "배포 직후 이상이면 가중치 0" 한 줄이 런북 맨 위에 없었던 것이 1차 교훈이다.


프로덕션 배포 전 점검 목록에 카나리 롤백 한 줄 명령을 넣어 두라는 조언과 맞닿는다. 참고: 프로덕션 배포 체크리스트.


시도 2 | 슬라이스 메트릭과 승격 게이트

다음 주 스프린트에서 관측을 손봤다. 응답 메트릭·로그·트레이스에 deploy_group=stable|canary 라벨을 강제했고, 대시보드에 카나리 전용 패널 네 개를 고정했다.


게이트 항목이전이후(이 팀 값)
헬스/healthz 200healthz + 결제 벤더 핑(별도 프로브)
에러율전체 5xx < 1%canary 5xx ≤ stable+0.5%p, 최소 표본 200
지연없음canary p95 ≤ stable p95 × 1.2
비즈니스없음결제 승인 성공률 슬라이스 비교
승격5분 후 수동게이트 15분 연속 통과 후 승인

알림도 바꿨다. 전체 5xx 임계값만 있던 채널에 canary_error_budget_burn 을 추가했다. 카나리 실패율이 stable 대비 벌어지면 배포 채널에 바로 멘션된다. 구조화 로그에 deploy_group이 들어가면 온콜 쿼리 시간이 크게 줄었다. 관련: 프로덕션 구조화 로깅 체크리스트, Sentry 런타임 에러 모니터링.


stable과 canary 메트릭을 나란히 비교하는 관측 대시보드 스케치
승격 게이트는 전체 평균이 아니라 stable 대비 상대 비교로 바꿨다

시도 3 | 단계 승격과 자동 중단

3주차에는 비율을 5% 고정에서 5% → 20% → 50% → 100% 단계로 바꿨다. 각 단계는 게이트 통과 시간이 필요하다. 한 단계라도 실패하면 가중치를 0으로 돌리고 canary 파드를 스케일 다운한다. 도구는 팀 인프라에 맞춰 인그레스 가중치 + 간단한 분석 잡(cron)으로 시작했고, 이후 프로그레시브 딜리버리 컨트롤러 도입을 검토했다.


자동 중단 조건은 공격적으로 잡았다. 표본이 부족할 때는 승격하지 않고 기다린다. 트래픽이 적은 심야 카나리는 "에러 0건"이 곧 안전이 아니다. 최소 요청 수(이 팀은 단계당 200)를 못 채우면 다음 영업일 피크로 연다.


쿠버네티스 운영에서 롤아웃·프로브·HPA를 같이 볼 때와 같은 방향이다. 배포 객체만 초록이라고 끝이 아니다. 참고: 쿠버네티스 프로덕션 운영 가이드, 매니지드 쿠버네티스 비교.


카나리 게이트 판정 스케치 (의사코드)
// 메트릭 백엔드에서 stable / canary 슬라이스 조회 후 승격 여부 결정 function canPromote({ stable, canary, minSamples }) { if (canary.requests < minSamples) { return { ok: false, reason: 'insufficient_samples' } } const errDelta = canary.errorRate - stable.errorRate if (errDelta > 0.005) { return { ok: false, reason: 'error_budget', errDelta } } if (canary.p95ms > stable.p95ms * 1.2) { return { ok: false, reason: 'latency', p95: canary.p95ms } } if (canary.paySuccess < stable.paySuccess - 0.01) { return { ok: false, reason: 'business_success' } } return { ok: true } } // 실패 시: ingress weight canary=0, scale canary deploy to 0 // 성공 시: weight 5 → 20 → 50 → 100 (단계마다 동일 게이트)

코드보다 중요한 합의는 제품·CS와의 문구다. 카나리 중단은 "장애"가 아니라 의도된 안전 장치로 공유했다. 배포 채널에 실패 사유 코드(error_budget, latency, business_success)를 남기면 다음 핫픽스 범위가 좁아진다.


결과 | 도입 전후 숫자 비교

같은 유형의 회귀(벤더 SDK 헤더 불일치)를 스테이징 카나리 재현과, 이후 실제 소규모 카나리 실패 1건을 기준으로 방향을 비교했다. 절대값은 트래픽·스택마다 다르다.


지표개선 전개선 후
카나리 이상 → 롤백 결정약 40분약 6~12분(자동 게이트)
영향 트래픽 상한5% 고정 + 승격 시도단계 실패 시 즉시 0%
전체 평균 5xx만 본 미탐발생(희석)슬라이스 알림으로 감소
온콜 로그 필터 시간15분+deploy_group 쿼리 1~2분
잘못된 전량 승격해당 건에서 위험게이트 실패로 차단

카나리가 "버그를 없애 준" 것은 아니다. 달라진 것은 나쁜 버전이 받는 트래픽 상한과 발견 속도다. 회로 차단기가 실패의 형태를 바꾸는 것과 비슷한 역할이다. 외부 의존성 격리 사례: 외부 API 회로 차단기 도입 케이스.


중간에 밟은 함정 다섯

1. 표본 없이 초록 판정 — 심야 5% 카나리에서 요청 40건·에러 0으로 승격했다가, 아침 피크에 같은 버전이 터질 뻔했다. 최소 표본 게이트를 넣기 전이다.


2. 4xx를 전부 무시 — 초기에 5xx만 봤다. 서명 오류·스키마 오류는 4xx로 떨어져 카나리가 "건강"해 보였다. 결제 경로의 4xx 중 서버 귀책 코드를 별도 집계했다.


3. 스티키 세션과 가중치 충돌 — 쿠키 스티키가 있는 경로에서 사용자가 버전을 오가며 상태 머신이 깨졌다. 카나리 구간에는 스티키를 끄거나, 버전 고정 헤더를 강제했다.


4. 스테이징 카나리 생략 — "스테이징에 이미 올렸으니 프로덕션 5%면 충분"이 함정이었다. 스테이징 트래픽 패턴이 프로덕션 테넌트 분포와 달랐다. 이후 프로덕션 카나리 전에 섀도·리플레이 짧은 구간을 추가했다.


5. 웹훅·비동기 경로 제외 — HTTP 동기 API만 게이트에 넣고, 웹훅 재처리 워커는 카나리 밖에서 돌렸다. 비동기 중복·재시도 이슈는 다른 날 터졌다. 관련: 웹훅 재시도 폭주·멱등 키 케이스.


카나리 단계 승격 5-20-50-100과 자동 롤백 스위치 개념 이미지
단계 승격과 자동 중단이 붙은 뒤 온콜은 '평균' 대신 '사유 코드'를 본다

카나리가 맞는 배포, 아닌 배포

모든 변경에 카나리가 답은 아니다. 이 팀이 사내 가이드에 남긴 기준이다.


  • 잘 맞는 경우 — 무상태 API, 수평 확장 파드, 메트릭 라벨이 이미 있는 서비스, 롤백이 가중치 한 줄로 끝나는 구조.
  • 추가 설계가 필요한 경우 — 스키마 마이그레이션 동반 배포, 스티키 세션, 장시간 워크플로, 웹훅·큐 컨슈머. DB 변경은 expand-contract와 순서를 맞춰야 한다. 참고: 무중단 DB 스키마 마이그레이션 체크리스트.
  • 카나리보다 플래그가 나은 경우 — UI 카피·권한 매트릭스처럼 코드 경로만 갈라도 되는 변경. 트래픽 미러링 비용 없이 킬스위치가 가능하다.
  • 같이 써야 하는 것 — 구조화 로그, 에러 트래킹, 배포 주석(누가·무엇·왜), 롤백 한 줄 런북.

블루그린은 "한 번에 전환"에 가깝고, 카나리는 "비율로 검증"에 가깝다. 트래픽이 아주 낮으면 카나리 표본이 안 나와 블루그린 + 짧은 검증 창이 나을 수도 있다. 팀 트래픽과 관측 성숙도를 먼저 적고 고르는 편이 안전하다.


온콜 런북에 남은 체크 순서

배포 직후 이상이 의심될 때 보는 순서다. 문서 문장을 거의 그대로 옮겼다.


  1. 지금 카나리 가중치와 canary 파드 수를 확인한다. 불확실하면 가중치 0이 기본값이다.
  2. 대시보드에서 deploy_group=canary 에러율·p95·결제 성공률을 stable과 나란히 본다. 전체 평균만 보지 않는다.
  3. 최근 배포 diff에서 외부 SDK·환경 변수·피처 플래그 기본값을 확인한다.
  4. 게이트 실패 사유 코드가 있으면 그 코드로 이슈를 연다. "일단 스케일 아웃"은 마지막이다.
  5. 롤백 후 15분 동안 웹훅·큐 적체를 확인한다. 동기 API만 정상인 착시를 막는다.
  6. 포스트모템 초안에 타임라인·영향 테넌트·미탐 이유를 남기고, 게이트 임계값 조정이 필요한지 한 줄로 적는다.

고객 공지는 "전체 결제 장애" 대신 "일부 트래픽 경로에서 결제 확인 오류, 해당 경로 차단 완료"처럼 범위를 적는다. 지원 분류 시간이 줄었다.


참고 자료


패턴 이름과 도구 용어는 위 문서를 기준으로 했고, 본문 수치·타임라인은 익명 팀 포스트모템 재구성이다.


자주 묻는 질문

카나리 비율은 몇 %부터 시작하는 게 맞나요?

이 팀은 5%로 시작했지만, 일 트래픽이 매우 낮으면 5%도 표본이 안 나온다. 비율보다 최소 요청 수 게이트가 먼저다. 피크 시간대에 200~1000 표본을 모을 수 있는 비율을 고르고, 실패 시 즉시 0으로 돌릴 수 있는지만 확인하면 된다.


레디니스 프로브만으로 카나리 합격 처리할 수 있나요?

부족하다. 프로브는 "파드가 트래픽을 받을 준비"이지 "이 버전이 비즈니스적으로 안전한가"가 아니다. 에러율·지연·핵심 성공률 슬라이스를 승격 조건에 넣는 편이 안전하다.


블루그린과 카나리 중 무엇을 먼저 도입할까요?

롤백 경로가 없는 팀이면 블루그린으로 "한 번에 되돌리기"부터다. 트래픽이 충분하고 메트릭 라벨이 있으면 카나리로 영향 반경을 줄인다. 둘을 섞어 카나리 검증 후 그린으로 전환하는 팀도 많다.


DB 마이그레이션이 있는 배포도 카나리로 해도 되나요?

스키마가 확장(expand)만 하고 구버전이 새 스키마를 읽어도 되면 가능하다. 축소(contract)나 호환 깨는 변경을 같은 배포에 넣으면 카나리와 stable이 동시에 다른 가정을 하게 된다. 마이그레이션과 앱 배포를 단계로 쪼개는 편이 낫다.


자동 롤백이 오탐으로 배포를 자주 끊으면 어떻게 하나요?

임계값을 느슨하게 하기 전에 표본 수·에러 코드 필터·비교 기준(절대값 vs stable 대비)을 점검한다. 오탐이 많은 알림은 신뢰가 떨어져 결국 무시된다. 이 팀은 결제 4xx 중 클라이언트 입력 오류를 실패율에서 제외한 뒤 오탐이 줄었다.


기능 플래그만으로 충분하지 않나요? 카나리가 꼭 필요한가요?

플래그는 코드 경로를 나누고, 카나리는 빌드·설정·의존성 버전 전체를 나눈다. SDK 업그레이드·베이스 이미지·사이드카 설정처럼 플래그로 감싸기 어려운 변경은 카나리 쪽이 맞다. 둘을 같이 쓰는 구성이 실무에서 흔하다.


카나리 배포카나리롤백헬스체크쿠버네티스데브옵스백엔드API장애포스트모템개발자관측

함께 보면 좋은 문제 해결

EXPLORE / Cloud & DevOps

이어서 읽어보기

전체 토픽 둘러보기