CCAAK · 섹션 6
Observability
이 섹션은 Troubleshooting의 입력값입니다. 장애 문항의 지문은 대개 메트릭 이름과 값으로 주어지므로, 메트릭 이름을 정확히 알지 못하면 문제를 읽을 수조차 없습니다. 메트릭을 이름 단위로 외우세요 — matching 유형에서 그대로 나옵니다.
학습 목표
- 핵심 4대 지표의 정상값과 이상 시 의미를 즉시 말할 수 있습니다.
UnderReplicatedPartitions와UnderMinIsrPartitionCount를 구분할 수 있습니다.- 컨슈머 lag을 세 가지 경로로 측정하고 각 경로의 한계를 설명할 수 있습니다.
- 컨트롤러 전용 메트릭으로 메타데이터 계층의 건강을 판단할 수 있습니다.
- 임계값을 "0이어야 하는 것"과 "비율로 봐야 하는 것"으로 나눠 알림을 설계할 수 있습니다.
이 도메인이 묻는 것
| 질문 형태 | 실제로 확인하는 것 |
|---|---|
"ActiveControllerCount가 2다. 무슨 뜻인가?" | 이 값은 클러스터 전체에서 정확히 1이어야 함 |
"OfflinePartitionsCount가 5다. 먼저 무엇을 하는가?" | 리더 없는 파티션의 의미와 우선순위 |
| "각 메트릭을 정상값과 연결하시오" (matching) | 0이어야 하는 것 vs 비율 지표 구분 |
| "컨슈머 lag을 확인하는 방법을 모두 고르시오" | CLI · 클라이언트 JMX · 브로커 측 오프셋 |
"RequestHandlerAvgIdlePercent가 0.05다" | 요청 처리 스레드 포화와 조치 |
핵심 개념 요약 — 4대 지표부터
Kafka 브로커는 JMX로 메트릭을 노출합니다. 수백 개가 있지만 대시보드 최상단에는 네 개만 두면 됩니다. 나머지는 이 네 개가 움직인 뒤에 봅니다.
| 메트릭 | 정상값 | 이상 시 의미 | 먼저 볼 것 |
|---|---|---|---|
kafka.server:type=ReplicaManager, |
0 | ISR이 전체 레플리카보다 작은 파티션 수. 복제가 뒤처짐 | 어느 브로커가 ISR에서 빠졌는가, 디스크·네트워크, 남은 스로틀 |
kafka.controller:type=KafkaController, |
0 | 리더가 없는 파티션 수. 읽기·쓰기 모두 불가 | 가장 심각한 신호. 브로커 다운 수와 RF를 즉시 확인 |
kafka.controller:type=KafkaController, |
노드당 0 또는 1, 클러스터 합 정확히 1 |
합이 0이면 컨트롤러 없음(메타데이터 변경 불가), 2 이상이면 분열 의심 | kafka-metadata-quorum.sh describe --status |
kafka.server:type=KafkaRequestHandlerPool, |
0~1 사이, > 0.3 이상적 |
요청 처리 스레드가 포화. 모든 지연이 함께 나빠짐 | num.io.threads(기본 8), 요청 급증 원인, 쿼터 |
URP와 UnderMinIsr — 헷갈리면 조치가 반대로 갑니다
| 메트릭 | 조건 | 쓰기 가능? |
|---|---|---|
UnderReplicatedPartitions |
|ISR| < |전체 레플리카| | min.insync.replicas를 만족하면 가능 |
AtMinIsrPartitionCount |
|ISR| = min.insync.replicas |
가능하지만 한 대만 더 빠지면 중단 |
UnderMinIsrPartitionCount |
|ISR| < min.insync.replicas |
불가 — acks=all 쓰기가 거부됩니다 |
브로커 · 복제 메트릭
| 메트릭 | 정상값 | 의미 |
|---|---|---|
ReplicaManager,name=IsrShrinksPerSecReplicaManager,name=IsrExpandsPerSec |
평시 0 | 브로커가 내려가면 축소, 복귀하면 확장이 일어납니다. 그 외에는 0이 기대값입니다. |
ReplicaManager,name=FailedIsrUpdatesPerSec |
0 | ISR 갱신 실패. 컨트롤러 통신 문제를 의심합니다. |
ReplicaFetcherManager,name=MaxLag, |
produce 배치 크기에 비례 | 팔로워와 리더 사이의 최대 메시지 lag. 계속 커지면 복제가 못 따라갑니다. |
FetcherLagMetrics,name=ConsumerLag, |
재할당 중 감소 추세 | 팔로워별 lag. 파티션 재할당이 진행되는지 판단하는 지표입니다. |
ControllerStats,name=UncleanLeaderElectionsPerSec |
항상 0 | 0이 아니면 데이터가 유실되었습니다. 사후 확인이 아니라 알림 대상입니다. |
ControllerStats,name=UncleanLeaderElectionsPerSec |
항상 0 | ISR 밖 레플리카가 리더가 된 횟수. 리더 교체 빈도는 IsrShrinksPerSec/IsrExpandsPerSec로 봅니다.
LeaderElectionRateAndTimeMs는 ZooKeeper 전용이라 KRaft에서 제거되었습니다. |
KafkaController,name=PreferredReplicaImbalanceCount |
평시 0 | 리더가 preferred가 아닌 파티션 수. 롤링 재시작 후 일시적으로 오릅니다. |
SocketServer,name=NetworkProcessorAvgIdlePercent |
0~1, > 0.3 | 네트워크 스레드 여유. 낮으면 num.network.threads(기본 3)를 검토합니다. |
RequestMetrics,name=TotalTimeMs, |
워크로드 기준선 대비 | 요청 전체 시간. queue · local · remote · response send로 분해해서 봅니다. |
RequestMetrics,name=RequestQueueTimeMs,... |
낮게 유지 | 큐 대기 시간이 크면 처리 스레드 부족입니다. |
SocketServer,name=ExpiredConnectionsKilledCount |
재인증 사용 시 0 | 재인증하지 않고 만료된 연결을 계속 쓰는 클라이언트가 있다는 신호입니다. |
컨트롤러 · 메타데이터 메트릭
| 메트릭 | 의미 | 해석 |
|---|---|---|
KafkaController,name=MetadataErrorCount |
이 노드가 메타데이터 로그 처리 중 만난 오류 수 | 0이 아니면 즉시 조사 대상입니다. 메타데이터 손상 가능성. |
KafkaController,name=LastAppliedRecordLagMs |
마지막으로 적용한 메타데이터 레코드의 지연 | 액티브 컨트롤러에서는 항상 0입니다. 스탠바이에서 이 값이 크면 뒤처진 것입니다. |
KafkaController,name=LastAppliedRecordOffsetKafkaController,name=LastCommittedRecordOffset |
적용·커밋된 메타데이터 오프셋 | 두 값의 차이가 계속 벌어지면 적용이 밀리고 있습니다. |
KafkaController,name=TimedOutBrokerHeartbeatCount |
브로커 하트비트 타임아웃 횟수 | 액티브 컨트롤러만 증가합니다. 늘어나면 브로커가 간헐적으로 끊기는 중입니다. |
컨슈머 lag 측정 3방법
같은 lag을 세 경로로 볼 수 있고, 세 경로가 보는 것이 미묘하게 다릅니다. 이 차이가 시험 문항이 됩니다.
| 방법 | 경로 | 장점 | 한계 |
|---|---|---|---|
| ① CLI | kafka-consumer-groups.sh --describe --group의 LAG 열
(= LOG-END-OFFSET − CURRENT-OFFSET) |
컨슈머에 손대지 않고 커밋된 오프셋 기준으로 즉시 확인 | 단발성 조회. 커밋 기준이라 처리했지만 아직 커밋 안 한 분량이 lag으로 보입니다 |
| ② 컨슈머 클라이언트 JMX | kafka.consumer:type=consumer-fetch-manager-metrics,의
records-lag-max |
컨슈머 실시간 상태. 대시보드·알림에 적합 | 컨슈머가 발행하는 메트릭입니다. 컨슈머가 죽으면 값 자체가 사라집니다 |
| ③ 브로커 측 오프셋 | kafka.log:type=Log,name=LogEndOffset,과
커밋 오프셋을 조합해 직접 계산 |
컨슈머가 없어도 토픽의 증가 속도를 볼 수 있습니다 | lag을 얻으려면 커밋 오프셋을 따로 가져와 계산해야 합니다 |
필수 CLI 명령어
# 파티션별 CURRENT-OFFSET / LOG-END-OFFSET / LAG
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group order-workers
# 활성 멤버와 각 멤버가 가진 파티션 수
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group order-workers --members
# 멤버별 실제 할당 파티션까지
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group order-workers --members --verbose
# 그룹 상태 요약: 코디네이터 / 할당 전략 / STATE / 멤버 수
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group order-workers --state
# 리더 · 에폭 · HighWatermark · MaxFollowerLag · voter/observer
bin/kafka-metadata-quorum.sh --bootstrap-server localhost:9092 describe --status
# 노드별 LogEndOffset / Lag / LastFetchTimestamp / LastCaughtUpTimestamp / Status
bin/kafka-metadata-quorum.sh --bootstrap-server localhost:9092 describe --replication
# Isr 가 Replicas 보다 짧은 파티션을 눈으로 찾습니다
bin/kafka-topics.sh --bootstrap-server localhost:9092 --describe
# 그룹 종류를 통합 조회 (Consumer / Share / Streams)
bin/kafka-groups.sh --bootstrap-server localhost:9092 --list
# 특정 로거만 DEBUG 로 (조사 후 반드시 원복)
bin/kafka-configs.sh --bootstrap-server localhost:9092 --broker-logger 0 \
--alter --add-config kafka.server.ReplicaManager=DEBUG
# 현재 로거 레벨 확인
bin/kafka-configs.sh --bootstrap-server localhost:9092 --broker-logger 0 --describe
반드시 외워야 할 값 — 임계값과 관련 설정
| 지표 | 임계 기준 | 움직였을 때 볼 설정 | 기본값 |
|---|---|---|---|
UnderReplicatedPartitions |
> 0 지속 시 경고 | num.replica.fetchers / replica.lag.time.max.ms |
1 / 30000 |
UnderMinIsrPartitionCount |
> 0 즉시 사고 | min.insync.replicas |
1 |
OfflinePartitionsCount |
> 0 즉시 사고 | default.replication.factor, unclean.leader.election.enable |
1 / false |
ActiveControllerCount 합계 |
≠ 1 즉시 사고 | controller.quorum.fetch.timeout.ms |
2000 |
UncleanLeaderElectionsPerSec |
> 0 즉시 사고 (유실 발생) | unclean.leader.election.enable |
false |
RequestHandlerAvgIdlePercent |
< 0.3 경고 | num.io.threads, queued.max.requests |
8 / 500 |
NetworkProcessorAvgIdlePercent |
< 0.3 경고 | num.network.threads |
3 |
PreferredReplicaImbalanceCount |
지속적으로 > 0이면 경고 | auto.leader.rebalance.enable, leader.imbalance.check.interval.seconds |
true / 300 |
LastAppliedRecordLagMs (스탠바이) |
지속 증가 시 경고 | metadata.log.dir 디스크 성능 |
null (첫 log.dirs) |
| 컨슈머 lag | 서비스 SLO 기준 | max.poll.records, max.poll.interval.ms |
500 / 300000 |
장애 시나리오와 대응
시나리오 1 — 컨슈머가 죽었는데 lag 알림이 오지 않았다
- 알림이
records-lag-max(컨슈머 발행 메트릭) 하나에만 걸려 있는지 확인합니다. - 컨슈머가 죽으면 그 메트릭도 사라집니다. 값이 커지는 게 아니라 없어지는 것입니다.
- 즉시 조치:
kafka-consumer-groups.sh --describe --group으로 현재 lag을 확인합니다. - 구조 개선: 메트릭 부재 자체(no data)에 알림을 걸고, 동시에 브로커에서 커밋 오프셋 기준 lag을 주기적으로 수집합니다.
- 그룹의 활성 멤버 수(
--members)에도 알림을 걸면 "컨슈머가 사라진 것"을 직접 감지할 수 있습니다.
시나리오 2 — 모든 요청 지연이 동시에 나빠졌다
RequestHandlerAvgIdlePercent를 봅니다. 0.3 미만이면 처리 스레드가 포화입니다.RequestQueueTimeMs가 커졌는지 확인합니다. 큐 대기가 지연의 대부분이면 스레드 부족이 확정입니다.NetworkProcessorAvgIdlePercent도 함께 봅니다. 이쪽이 낮으면 네트워크 스레드가 원인입니다.- 원인 트래픽을 특정합니다 — 쿼터 메트릭으로 사용자·클라이언트별 사용량을 봅니다.
- 단기 조치는
num.io.threads상향(cluster-wide라 재시작 불필요), 중기 조치는 쿼터 부여입니다.
시나리오 3 — ActiveControllerCount 합계가 0이 되었다
- 즉시
kafka-metadata-quorum.sh --bootstrap-controller ... describe --status를 실행합니다. - 리더가 없다면 쿼럼 과반이 살아 있는지 확인합니다. 과반을 잃으면 리더가 뽑히지 않습니다.
- 기존 파티션의 읽기·쓰기는 한동안 계속되지만 메타데이터 변경은 전부 실패합니다. 이 점을 관계자에게 먼저 알립니다.
- 컨트롤러 노드 간 네트워크를 확인합니다.
controller.quorum.fetch.timeout.ms(기본 2000)를 넘기면 선거가 반복됩니다. MetadataErrorCount가 올라 있으면 메타데이터 손상 가능성이 있으므로, 노드를 다시 포맷하기 전에describe --replication으로 과반의 데이터 보유를 확인합니다.
시나리오 4 — URP가 0으로 돌아오지 않는다
- 어느 브로커·파티션인지
kafka-topics.sh --describe로 좁힙니다. ReplicaFetcherManager MaxLag가 커지는 추세인지 봅니다. 커지면 복제가 뒤처지는 중입니다.- 남아 있는 스로틀을 확인합니다. 재할당 후
--verify를 생략했다면 여기서 걸립니다. IsrShrinksPerSec/IsrExpandsPerSec가 반복되면 특정 브로커의 디스크·네트워크를 봅니다.num.replica.fetchers(기본 1)를 올려 팔로워 fetch 병렬성을 확보합니다.
자주 나오는 함정
관련 케이스 스터디
- 케이스 2 · 컨슈머가 무한 리밸런스 루프에 빠졌다 — 그룹 상태 판독
- 케이스 6 · RF=3인데 브로커 1대 죽자 유실됐다 — ISR 메트릭으로 사전 감지
메트릭 전체 목록은 JMX 메트릭 치트시트, 운영 배경은 11장 운영 기초, lag 모니터링 실습은 예제 10에 있습니다. 이 지표들을 실제 조치로 잇는 방법은 Troubleshooting에서 다룹니다.
미니 퀴즈
메트릭 이름과 정상값 매칭이 중심입니다.
공식 문서 출처
- Monitoring — 4대 지표와 정상값, ISR 메트릭 3종,
UncleanLeaderElectionsPerSec,RequestHandlerAvgIdlePercent/NetworkProcessorAvgIdlePercent의 0.3 기준,records-lag-max가 컨슈머 발행임, 컨트롤러 메트릭,TotalTimeMs분해 - Basic Kafka Operations —
kafka-consumer-groups.sh --describe출력,--members/--state, 새 컨슈머 프로토콜의 DESCRIBE 권한 요구 - KRaft —
kafka-metadata-quorum.sh describe --status/--replication - Broker Configs —
num.io.threads,num.network.threads,num.replica.fetchers,queued.max.requests기본값과 갱신 모드