11. 트러블슈팅
증상은 대부분 컨슈머에서 보이지만, 원인은 네 층 어디에나 있다 — 층부터 가른다
이 장에서 처음 나오는 말2개
poison pill- 역직렬화 실패 등으로 처리가 항상 실패하는 레코드. 컨슈머가 같은 오프셋에서 무한 재시도하며 그 파티션 소비가 멈춘다.
DLTDead Letter Topic- 처리에 계속 실패한 레코드를 치워 두는 별도 토픽. poison pill로 파티션 전체가 멈추는 것을 막는 안전판이다.
진단 순서 — 아래층부터 위로
섹션 제목: “진단 순서 — 아래층부터 위로”-
클러스터 — 브로커 파드가 다 살아 있나, URP가 0인가, active controller가 1인가. 여기가 아프면 위층 증상은 전부 파생이다
터미널 창 kubectl get pods -n kafkakubectl get kafka my-cluster -n kafka -o yaml # status 조건 확인 -
토픽/파티션 — 문제의 토픽에 리더 없는 파티션이 있나, ISR이 줄어 있나
터미널 창 kafka-topics.sh --bootstrap-server ... --describe --topic order.payment.completed -
프로듀서 — 앱 로그의 전송 오류(
NotEnoughReplicas· timeout), 버퍼 상태 (4장) -
컨슈머 — 그룹의 랙과 파티션 배정 상태, 리밸런스 로그 (5장)
터미널 창 kafka-consumer-groups.sh --bootstrap-server ... --describe --group notification-service
증상 카탈로그
섹션 제목: “증상 카탈로그”| 증상 | 원인일 확률이 높은 것 | 어디를 보나 |
|---|---|---|
프로듀서 NotEnoughReplicasException | 브로커 다운으로 ISR < min.insync.replicas — 유실 대신 쓰기 거부 중(3장) | URP · 죽은 브로커. 설정이 아니라 브로커를 고친다 |
| 랙이 전 파티션에서 증가 | 소비 처리량 < 생산 처리량 | 컨슈머 수(파티션 한도?) · 처리 병목(DB?) |
| 랙이 한 파티션만 증가 | poison pill(아래) 또는 핫 파티션(4장) | 그 파티션 담당 컨슈머 로그 · 키 분포 |
| 리밸런스가 반복되고 소비 정지 | 처리 지연으로 max.poll.interval.ms 초과 → 축출 → 반복 (5장의 루프) | 배치 크기(max.poll.records) 축소 · 처리 시간 |
RecordTooLargeException | 기본 최대 메시지 ~1MB 초과 | 큰 파일은 Kafka에 넣지 않는다 — 오브젝트 스토리지에 두고 참조만 흘린다 |
| 외부에서 bootstrap만 되고 타임아웃 | advertised 주소가 클라이언트 기준 무효 (9장) | kcat -L로 받은 주소 확인 |
| 새 컨슈머가 과거 데이터를 안 읽음 | auto.offset.reset=latest 기본값 (5장) | 의도가 처음부터면 earliest |
| 같은 메시지가 두 번 처리됨 | at-least-once의 정상 동작 (6장) | 고칠 곳은 Kafka가 아니라 소비자의 멱등 처리 |
| 브로커 디스크 만석 | 보존 계산과 유입의 불일치 · retention.bytes 미설정 | 아래 |
대표 시나리오 셋
섹션 제목: “대표 시나리오 셋”poison pill — 한 파티션만 멈춘다
섹션 제목: “poison pill — 한 파티션만 멈춘다”형식이 깨진 레코드 하나가 들어오면, 컨슈머는 그 오프셋에서 실패 → 재시도 → 실패를 반복한다. 커밋이 안 넘어가니 그 파티션 전체가 멈추고, 랙은 한 파티션만 자란다.
- 응급 — 그 오프셋을 건너뛰게 오프셋을 수동으로 옮긴다
(
kafka-consumer-groups.sh --reset-offsets --to-offset …, 그룹 정지 상태에서) - 재발 방지 — 역직렬화·처리 실패 시 N회 재시도 후 DLT로 치우고 다음으로 넘어가는 처리를 컨슈머에 넣는다 (Spring Kafka 등 주요 프레임워크에 내장 지원이 있다). DLT는 버리는 곳이 아니라 나중에 고쳐 재처리하는 대기소다 — 알람을 걸어 둔다
리밸런스 루프 — 그룹 전체가 멈춘다
섹션 제목: “리밸런스 루프 — 그룹 전체가 멈춘다”5장의 함정 그대로. 신호는 “랙 증가 + CPU 한가 + 리밸런스 로그 반복”.
처리 시간이 튀는 원인(외부 API 지연 · 대형 배치)을 찾고, 급한 불은 max.poll.records를
줄여서 끈다 — max.poll.interval.ms를 늘리는 것은 마지막 수단이다
(장애 감지도 그만큼 늦어진다).
디스크 만석 — 최악의 장애
섹션 제목: “디스크 만석 — 최악의 장애”디스크가 차면 브로커가 죽고, 복구해도 읽을 데이터부터 지워야 떠서 유실이 강제된다.
- 예방이 전부다 —
retention.bytes를 파티션마다 안전판으로 걸고, 70% 알람(10장) - “보존을 줄였는데 안 지워져요” — 삭제는 세그먼트 단위라 active 세그먼트는 안 지워진다
(2장). 유입이 적은 토픽은
segment.ms로 세그먼트를 잘게 굴려야 보존이 제때 먹는다
11장 요약
섹션 제목: “11장 요약”- 진단은 아래층부터 — 클러스터(URP) → 토픽(리더/ISR) → 프로듀서 → 컨슈머(랙)
- poison pill은 DLT + 재시도 상한으로 예방 — 응급은 오프셋 건너뛰기
- 리밸런스 루프는 poll 지연이 원인 — 배치를 줄이는 것이 먼저, 타임아웃 연장은 마지막
- 디스크 만석은 예방만 있다 —
retention.bytes안전판 · 70% 알람 ·segment.ms - 큰 파일은 참조만, 중복은 멱등으로 — Kafka 밖에서 고칠 문제를 Kafka에서 찾지 않는다
12. 용어 사전이 덱에 나온 용어 · 약어를 한 곳에서 다시 찾기.