Scale-to-zero의 품질은 replica 수가 0이 되는 순간이 아니라, 첫 메시지가 도착한 뒤 실제 효과와 ACK가 끝나는 시점까지의 전체 수명으로 판단합니다. 기동에서는 scaler·노드·Pod·앱·broker 준비를, 축소에서는 새 작업 수락 중단·진행 중 효과·재전달을 따로 세어야 합니다. “Running”이나 visible backlog=0만으로 준비·완료를 결론내리지 않는 것이 출발점입니다.
Polling부터 첫 ACK까지의 준비 지연
예를 들어 이벤트가 t=0에 도착하고 scaler 감지가 t=5, Node Ready가 t=35, 앱 초기화가 t=45, assignment가 t=52, 첫 효과와 ACK가 t=60에 끝났다면 cold-start SLO는 60초입니다. Pod Running이 t=40이었다는 사실만으로 40초에 처리 가능했다고 기록하면 안 됩니다. 각 시각을 같은 message ID로 연결해야 어느 단계가 p99를 만들었는지 알 수 있습니다.
consumer가 0개일 때 메시지가 도착하면, 먼저 scaler가 이벤트를 감지해 workload 활성화를 요청하고, Pod를 생성한 뒤 노드에 배치해야 합니다. 이어 이미지·앱 초기화·broker 연결·assignment를 거쳐야 첫 처리를 시작할 수 있습니다.
노드도 줄어 있다면 인스턴스 공급과 Node Ready 외에 CNI(네트워크 플러그인), CSI(스토리지 플러그인), DaemonSet(노드별 에이전트) 준비가 더해집니다. 따라서 첫 ACK 시각은 polling interval 하나가 아니라 각 단계의 소요 시간과 의존 관계로 계산해야 하며, 단계가 겹칠 수 있는지도 타임라인으로 확인해야 합니다.
그림을 글로 읽기
- 이벤트 도착·scaler 감지
- Pod·노드 배치 준비
- 이미지·앱 초기화
- 연결·assignment·fetch
- 처리·효과 커밋·ACK
- 이벤트 도착·scaler 감지 → Pod·노드 배치 준비: 활성화
- Pod·노드 배치 준비 → 이미지·앱 초기화: 실행 자원 준비
- 이미지·앱 초기화 → 연결·assignment·fetch: 소비 준비
- 연결·assignment·fetch → 처리·효과 커밋·ACK: 첫 작업 실행
Pod 상태가 Running으로 바뀌어도 필수 설정을 읽고 broker assignment를 받은 뒤라는 뜻은 아니므로, 메시지를 바로 처리할 준비가 됐다고 세지 않습니다. readiness 실패만으로 pull consumer의 fetch가 자동 중단되지 않는다면, 앱이 초기화와 assignment를 끝낸 뒤에만 소비를 시작하고 종료 신호를 받으면 새 fetch를 먼저 멈추도록 구현합니다. 그래야 종료 중 새 작업이 계속 들어오는 것을 막으면서 실제 처리 준비와 상태 표시를 같은 기준으로 맞출 수 있습니다.
Warm Node와 Warm Pod의 제거 비용 차이
| 유지 대상 | 줄일 수 있는 지연 | 남는 비용·지연 |
|---|---|---|
| warm node | 인스턴스 공급·부팅 | Pod 배치·이미지·앱 예열·연결 |
| image pre-pull | 이미지 다운로드 일부 | 버전별 이미지·앱 시작·초기화 |
| warm Ready Pod | 앱 준비·연결 비용 일부 | 실제 메시지 처리·할당·부하 확장 |
| 항상 최소 consumer | 첫 처리 준비 | 상시 CPU·메모리·연결·운영비 |
warm이라고 이름 붙인 Pod가 실제 Ready·broker 연결 상태가 아니면 준비 용량으로 세지 않습니다. 유휴 consumer도 Kafka assignment를 얻기 위한 group 조정이 필요할 수 있습니다. core controller·scaler·node provisioning 경로 자체가 scale-to-zero된 앱 노드에 의존해 순환 기동이 되지 않는지도 확인합니다.
허용 메시지 지연이 긴 배치와 즉시 응답해야 하는 사용자 요청은 다른 정책이 필요합니다. 긴 유휴 뒤 첫 메시지와 짧은 반복 burst의 비용을 따로 측정해 최소 용량을 정합니다.
Visible backlog와 in-flight 작업
최소 consumer를 유지할지는 첫 처리 SLO와 유휴 비용의 비교로 결정합니다. 긴 배치 지연을 허용할 수 있으면 warm node만 두고, 짧은 burst가 반복되며 rebalance 비용이 크면 Ready consumer나 cooldown을 유지하는 편을 검토합니다. 축소 장애에서는 visible=0, fetch 중단, 마지막 효과, ACK, process 종료를 각각 확인하고 어느 시점의 작업이 끊겼는지 진단합니다.
worker가 큐에서 메시지를 가져간 뒤에는 visible backlog에서 사라져도 DB 쓰기나 외부 효과가 끝나지 않은 in-flight 작업일 수 있습니다. 예를 들어 visible backlog=0인 시점에 축소를 완료하면 아직 확정하지 않은 작업을 끊을 수 있으므로, broker가 in-flight를 어떻게 정의하는지와 지표 지연을 확인하고 ACK 또는 commit이 어느 단계에서 발생하는지 함께 기록합니다.
Kafka에서는 committed lag가 마지막 커밋을 기준으로 하므로 처리 중 레코드 수와 항상 같은 값으로 보지 않습니다.
축소 요청이 오면 먼저 새 fetch와 자식 작업 수락을 막고, 이미 시작한 작업은 실제로 끝나면서 효과가 확정될 때까지 기다립니다. grace 안에 끝나면 효과를 확정한 뒤 ACK하고, 끝나지 않으면 checkpoint를 남기거나 안전하게 재전달해 새 worker가 이어서 처리하게 합니다. 효과가 이미 적용됐는지 응답만으로 알 수 없을 때는 같은 논리 키로 조회하고 멱등 처리해야 하며, replica 수를 0으로 만들려고 ACK부터 보내면 그 작업이 재전달되지 않아 누락될 수 있습니다.
제어기 Cooldown과 앱 Drain의 독립 경계
cooldown은 짧은 수요 변동마다 0으로 줄었다 깨어나는 진동을 줄일 수 있습니다. HPA stabilization은 활성 replica 조정의 다른 경계에 작용할 수 있으므로 사용하는 KEDA 구성의 역할을 확인합니다. 어느 창도 앱의 진행 중 작업을 자동으로 완료하거나 보상하지 않습니다.
준비에 40초가 걸리는데 20초 간격 burst마다 완전히 내려가면 매번 cold start를 치를 수 있습니다. 창을 늘리면 비용이 늘지만 반복 예열·rebalance를 줄일 수 있습니다. 이 예는 설계 가정이며 적절한 시간은 실제 분포·SLO·비용으로 정합니다.
첫 이벤트부터 마지막 실행까지의 수명 관측
이벤트 도착·감지·desired 변경·Node Ready·container 시작·assignment·첫 커밋·ACK 시각을 기록합니다. 축소에서는 fetch 중단·마지막 수락·마지막 효과·ACK·프로세스 종료를 분리합니다. 지표 API가 실패할 때도 작은 작업이 영원히 남지 않는 fallback과 경보를 검토합니다.
격리 환경에서 긴 유휴·반복 burst·노드 부족·처리 중 visible=0·종료 유예 초과를 시험합니다. 현재 작업에서 scale-to-zero를 실행하지 않았으므로 실제 첫 처리 p99나 비용 절감 수치를 제시하지 않습니다.