마지막 setWeight: 100을 왜 지워야 하는가
2부의 사고에서는 rollbackWindow로 step을 건너뛴 뒤, 컨트롤러가 역탐색으로 마지막 weight 100을 선택했습니다.
롤백 대상 20대 중 2대만 준비된 순간에 트래픽이 전부 넘어간 이유입니다.
steps 끝의 setWeight: 100을 지우면 이때 선택하는 값을 낮출 수 있습니다.
마지막 setWeight: 100을 제거한다
공통 차트의 steps를 다음과 같이 바꿉니다.
steps:
- setWeight: 5
- pause:
duration: 10m
- - setWeight: 1001부에서 봤듯 컨트롤러는 남은 step이 없으면 최종 weight를 100으로 계산합니다.
따라서 정상 배포에서는 전체 파드가 준비되면 트래픽을 100%로 늘리고 승격합니다.
롤백 대상 파드가 아직 준비 중일 때는 step 끝에서 거꾸로 찾은 5를 적용합니다.
초기 파드에는 5%만 보내고, 전체 ReplicaSet이 준비되면 100%로 전환합니다.
준비 중에는 장애 버전으로 트래픽이 남는다
사고 당시처럼 복구 버전이 2대만 준비됐다면 이 구간의 분배는 다음과 같습니다.
복구 버전 canary 5%
장애 버전 stable 95%초기 파드에 전체 요청이 몰리는 상황은 막지만, 나머지 파드가 준비될 때까지 요청의 95%는 장애 버전으로 갑니다.
승격하려면 기존 설정에서도 전체 ReplicaSet이 준비돼야 했습니다.
이 조건은 그대로이고, 파드가 준비되는 동안 트래픽을 보내는 비율만 바뀝니다.
100을 지운 뒤 남는 값도 봐야 한다
100을 지워도 남은 weight대로 보낸 요청을 초기 canary가 감당하지 못하면 과부하가 발생할 수 있습니다.
파드마다 처리 용량과 부하가 같다고 가정하면, 초기 파드가 감당할 수 있는 전체 규모를 다음처럼 계산할 수 있습니다.
초기 파드로 감당할 수 있는 전체 규모
≈ minPodsPerReplicaSet / 남는 트래픽 비율minPodsPerReplicaSet: 2일 때의 계산입니다.
| 마지막으로 남는 weight | 초기 2대로 대응할 수 있는 전체 규모 |
|---|---|
| 1% | 약 200대 |
| 5% | 약 40대 |
| 10% | 약 20대 |
| 50% | 약 4대 |
이 계산만으로 안전을 판단할 수는 없으므로 실제 부하와 파드당 처리량도 확인해야 합니다.
최대 100대까지 늘어나는 서비스라면 5%도 초기 2대에 과할 수 있습니다.
이런 서비스는 남는 weight를 더 낮추거나 초기 파드를 늘려야 합니다.
base와 서비스 override를 각각 확인한다
서비스가 steps를 선언하면 공통 차트의 리스트를 통째로 대체합니다.
따라서 자체 steps를 가진 서비스는 base와 별도로 수정해야 합니다.
| 기존 steps의 weight | 확인할 변경 |
|---|---|
[1, 5, 100], [5, 100] | 마지막 100 제거 후 남은 5의 용량 확인 |
[10, 50, 100] | 100을 지워도 50이 남으므로 앞 단계까지 조정 |
[100] | 이 하나도 역탐색 대상이므로 변경 필요 |
steps: [] | 역탐색할 setWeight가 없어 이번 경로에는 직접 노출되지 않음 |
최종 렌더된 manifest에서 마지막 weight를 확인해야 합니다.
CI에서도 100이 남아 있는지, 더 낮은 값이어도 초기 용량을 넘는지 검사해야 합니다.
다른 설정으로 막을 수는 없을까
| 설정 | 이번 경로에서의 한계 |
|---|---|
dynamicStableScale | stable 크기를 줄여도 역탐색 결과는 같고, 실패 시 돌아갈 여유 용량은 줄어듦 |
setCanaryScale | 정상 배포에서 미리 확장하는 데 쓰지만, step을 건너뛴 뒤에도 보호한다고 볼 수 없음 |
minPodsPerReplicaSet 인상 | 초기부터 충분한 파드를 확보할 수 있지만 평소 Canary 비용도 증가 |
| step analysis | rollbackWindow가 분석 자체를 건너뜀 |
예를 들어 최소 파드를 전체 replica와 같은 20대로 잡으면 초기 용량 문제를 피할 수 있습니다.
대신 평소 트래픽 5%로 검증할 때도 새 버전 파드 20대를 실행해야 합니다.
최소 파드 수 2에도 배경이 있었다
2025-05에는 작은 weight에서도 단일 파드에 요청이 몰리지 않도록 base chart에 minPodsPerReplicaSet: 2를 추가했습니다.
그해 6월에는 rollbackWindow.revisions: 3을 추가했고, 8월에는 현재와 유사하게 traffic routing을 구성했습니다.
2025년 하반기부터 소규모 워크로드에는 최소 파드 수의 예외가 늘었습니다.
2026-07에 비프로덕션 replica를 줄인 뒤, 8월에는 0·1대 워크로드의 목표와 최소 파드 수가 충돌하는 문제가 드러났습니다.
전체 목표가 1인데 canary 하한이 2이면 승격 조건에 도달하지 못할 수 있고, 0까지 줄이는 Consumer에서는 최소 파드 조건이 scale-to-zero와 충돌할 수 있습니다.
0대부터 100대 이상까지 규모가 다른 서비스에 기본값 하나를 적용하다 보니 예외가 늘었고, 이 값이 각 워크로드에 맞는지 CI에서 검증하지도 못했습니다.
이번 사고에서도 초기 파드 수는 2대로 정해졌는데, 전체 20대가 준비되기 전에 트래픽을 100% 보냈습니다.
그래서 최소 파드 수를 바꿀 때도 남는 weight와 서비스의 최대 replica 규모를 함께 봐야 합니다.
장애 중에는 어떤 명령을 쓸까
| 수단 | 역할과 주의점 |
|---|---|
retry | 실패한 Rollout을 다시 진행. Analysis도 재시작하면 높은 서비스 오류율에 다시 abort될 수 있음 |
promote | 현재 pause를 진행. abort 자체를 해제하는 수단은 아님 |
promote --full | step·Analysis를 건너뛰는 수동 승격. 별도의 weight 보호 경로 사용 |
GitOps rollback / undo | 이전 pod template으로 복귀. rollbackWindow 조건에 따라 빠른 롤백 경로 진입 |
이미 정상 버전으로 되돌아왔고 Rollout 상태만 완료되지 않았다면 promote --full로 수동 승격할 수 있습니다.
서비스 전체 오류율을 다시 읽는 retry와는 구분해야 합니다.
수동 조치 뒤에는 Git의 선언 상태도 맞춰야 합니다.
런북에도 이 후속 작업까지 포함해야 합니다.
검증은 정상 배포와 실제 롤백까지
이 문제는 정상 배포만으로 드러나지 않습니다.
같은 이전 revision으로 돌아가면서, 변경 전후 weight와 Available replica를 함께 봐야 합니다.
서비스 자체 steps를 확인하는 경우에는 관찰 시간을 줄여 다음 설정으로 비교할 수 있습니다.
# 변경 전
steps:
- setWeight: 5
- pause:
duration: 10s
- setWeight: 100# 변경 후
steps:
- setWeight: 5
- pause:
duration: 10swindow 범위 안에 남아 있는 ReplicaSet을 대상으로, 일부 파드만 준비된 동안의 weight를 관찰해야 합니다.
| 구간 | 확인할 것 |
|---|---|
| 변경 전 롤백 | 전체가 준비되기 전에 weight 100이 관측되는가 |
| 변경 후 롤백 | 준비 중 weight 5를 유지하는가 |
| 변경 후 완료 | 전체 ReplicaSet 준비 후 100%로 승격하는가 |
base를 상속하는 서비스는 설정 전파도 따로 확인합니다.
helm template으로 변경 전후 manifest를 비교하고, 상속 서비스 하나에 적용해 같은 롤백 동작을 관찰한 뒤 범위를 넓힙니다.
작은 stage 환경에서는 사고 당시의 20대 중 2대에 100%라는 피해 규모까지 재현하기 어려울 수 있습니다.
피해 규모를 재현하지 못하더라도 파드가 준비되기 전에 weight가 100%로 바뀌는지는 확인할 수 있습니다.
이 설정을 언제 다시 볼 것인가
2026-08-27에는 v1.8.2의 보호 조건과 업스트림 수정안을 확인했습니다.
당시 검토한 수정 방향은 canary의 실제 Available replica 비율에 맞춰 traffic weight를 제한하는 것이었습니다.
이 수정이 실제 사용하는 컨트롤러 버전에 반영되면, 마지막 setWeight: 100을 제거한 우회 설정이 여전히 필요한지도 다시 확인할 수 있습니다.
버전이 바뀌면 역탐색이나 step 처리 순서도 달라질 수 있으므로, 업그레이드마다 정상 배포·window 안의 롤백·abort와 promote --full 대응을 회귀 검증에 포함해야 합니다.
여러 클러스터의 컨트롤러 버전이 다르면 각각 확인해야 합니다.