끄적끄적

Kafka Leader/Follower/ISR — Broker 1대가 죽었을 때 30초 장애를 겪고 배운 것들 (실무 설정값 포함) 본문

Back-end

Kafka Leader/Follower/ISR — Broker 1대가 죽었을 때 30초 장애를 겪고 배운 것들 (실무 설정값 포함)

mashko 2026. 2. 26. 21:14
반응형
⚡ Apache Kafka 실무 심화

Kafka Leader & Follower

파티션 리더/팔로워 동작 원리 · ISR · Preferred Leader · 실무 장애 시나리오 완전 정리

⚡ Kafka 3.x 기준 🔧 운영 설정값 포함 ⏱ 읽기 약 15분 🔥 실무 장애 복기 포함

📋 목차

  1. 들어가며 — Broker 1대가 죽었을 때 벌어진 일
  2. Leader와 Follower — 역할 분담의 핵심
  3. ISR(In-Sync Replica) — 가장 중요한 개념
  4. Leader Election — 리더는 어떻게 선출되나
  5. Preferred Leader Rebalancing — 실무에서 왜 중요한가
  6. acks 설정과 ISR의 관계 — 유실 vs 성능 트레이드오프
  7. 실무 장애 시나리오와 대응법
  8. 운영 핵심 설정값 총정리
📖 Section 01

들어가며 — Broker 1대가 죽었을 때 벌어진 일

Kafka 클러스터를 운영하던 중 Broker 1대에 디스크 장애가 났습니다. 순간적으로 Producer가 메시지를 보내지 못하는 현상이 발생했고, Consumer Lag이 급격히 쌓이기 시작했어요. 장애 시간은 약 30초. 짧은 것 같지만 실시간 주문 데이터가 흐르는 파이프라인에서 30초는 꽤 치명적이었습니다.

나중에 확인해보니 죽은 Broker에 파티션 리더가 몰려있었고, 팔로워들이 리더를 이어받는 과정에서 그 시간이 소요된 것이었습니다. 리더와 팔로워 개념, 그리고 ISR을 제대로 이해하고 있었다면 처음부터 리더가 특정 Broker에 몰리지 않도록 설계했을 겁니다.

💡
이 글을 읽으면 알 수 있는 것들:
① 리더와 팔로워가 정확히 어떤 역할을 하는지
② ISR이 뭔지, ISR에서 빠지면 무슨 일이 생기는지
acks=all이 왜 ISR과 연결되는지
④ Preferred Leader Rebalancing을 왜 주기적으로 해야 하는지
· · ·
👑 Section 02

Leader와 Follower — 역할 분담의 핵심

Kafka에서 각 파티션은 Replication Factor 수만큼 여러 Broker에 복제됩니다. 이 중 단 1개만 Leader, 나머지는 모두 Follower입니다.

Topic: order-events | Partition 0 | Replication Factor: 3
Producer
쓰기 요청
Broker 1
👑 LEADER
읽기/쓰기 모두 처리
←sync→
Broker 2
FOLLOWER
복제만 수행
←sync→
Broker 3
FOLLOWER
복제만 수행
Consumer Group
리더에서만 읽기
Broker 1 (Leader)
Partition 0
Kafka 2.4+ 이전: Consumer는 반드시 Leader에서만 읽음
Kafka 2.4+: Rack-aware 설정으로 가까운 Follower에서 읽기 가능 (Consumer Fetch from Follower)
역할 Leader Follower
쓰기(Producer) 전담 처리 직접 받지 않음
읽기(Consumer) 전담 처리 (기본) Kafka 2.4+ 설정 시 가능
복제 Follower에게 전달 Leader에서 Pull
장애 시 Follower 중 1개가 승격 Leader 승격 대기
개수 파티션당 1개 Replication Factor - 1개
🔑
핵심 포인트:
Follower는 Leader에게 데이터를 Push 받는 게 아니라 Pull 방식으로 가져갑니다.
Follower가 주기적으로 Leader에게 Fetch 요청을 보내 최신 데이터를 동기화하는 구조예요.
이 동기화가 얼마나 잘 따라가고 있는지를 나타내는 것이 바로 ISR입니다.
· · ·
🎯 Section 03

ISR(In-Sync Replica) — 가장 중요한 개념

ISR은 In-Sync Replica의 약자로, 리더와 거의 동일한 수준으로 복제가 동기화된 Replica들의 집합입니다. 리더는 항상 ISR에 포함되고, 팔로워는 동기화 상태에 따라 ISR에 들어가거나 나갑니다.

ISR 상태 — 정상 vs 지연 시나리오
✅ 정상 상태
Broker 1 (Leader) ✅ ISR
Broker 2 (Follower) ✅ ISR
Broker 3 (Follower) ✅ ISR
ISR = {1, 2, 3}
🚨 Broker 3 지연/장애 시
Broker 1 (Leader) ✅ ISR
Broker 2 (Follower) ✅ ISR
Broker 3 (Follower) ❌ OUT
ISR = {1, 2} — Broker 3 제외
replica.lag.time.max.ms 시간 내에 동기화 못 하면 ISR에서 제거됨
🚨
ISR이 줄어드는 게 왜 위험한가?
acks=all 설정 시 ISR 전체가 메시지를 받아야 Producer에게 ack를 보냅니다.
ISR이 1개(리더만)로 줄어든 상태에서 리더까지 죽으면 → ISR 밖의 팔로워가 리더로 승격 → 미복제 메시지 유실!
이것이 unclean.leader.election.enable 설정이 중요한 이유입니다.
 
 
 
ISR 관련 핵심 설정
Properties
# ISR 판단 기준 — 이 시간 내 동기화 못 하면 ISR 제외
replica.lag.time.max.ms=30000  # 기본 30초, 운영 환경 10초 권장

# 최소 ISR 수 — ISR이 이 수보다 적으면 Producer 쓰기 거부
min.insync.replicas=2  # Replication Factor 3일 때 2 권장

# Unclean Leader Election — ISR 밖의 팔로워를 리더로 허용할지
unclean.leader.election.enable=false  # 운영 환경 반드시 false!
# true로 하면: 가용성 ↑, 데이터 유실 위험 ↑
# false로 하면: 데이터 무결성 ↑, 리더 없는 파티션 발생 가능
⚠️
min.insync.replicas 실무 설정 공식:
Replication Factor가 N이면 min.insync.replicas = N/2 + 1 설정을 권장합니다.
RF=3 → min.insync.replicas=2 : Broker 1대 장애 허용
RF=5 → min.insync.replicas=3 : Broker 2대 장애 허용
· · ·
⚡ Section 04

Leader Election — 리더는 어떻게 선출되나

1

리더 장애 감지 — Controller Broker가 감지

Kafka 클러스터에는 Controller라는 특별한 Broker가 존재합니다 (Kafka 3.0+ KRaft 모드에서는 별도 Controller 프로세스). Controller는 ZooKeeper(또는 KRaft)를 통해 각 Broker의 상태를 모니터링하고 리더 장애를 감지합니다.

💡 Kafka 3.3+에서 KRaft 모드가 GA됐습니다. ZooKeeper 의존성이 제거되어 운영이 훨씬 단순해졌어요.
2

ISR 중 새 리더 선출

Controller는 해당 파티션의 ISR 목록에서 첫 번째 Broker를 새 리더로 선출합니다. ISR 순서는 Preferred Leader(최초 리더)가 가장 앞에 옵니다. unclean.leader.election.enable=false이면 ISR이 비어있을 경우 파티션이 리더 없이 오프라인 상태가 됩니다.

⚠️ ISR이 완전히 비면 min.insync.replicas를 충족 못해 Producer 쓰기가 거부됩니다!
3

새 리더 등록 및 Producer/Consumer 재연결

새 리더 정보가 Kafka 메타데이터에 업데이트되면, Producer와 Consumer는 자동으로 새 리더를 발견하고 재연결합니다. 이 과정이 실무에서 체감하는 "30초 장애"의 정체였습니다. session.timeout.msconnections.max.idle.ms 튜닝으로 단축 가능합니다.

· · ·
👑 Section 05

Preferred Leader Rebalancing — 왜 주기적으로 해야 하나

Topic을 생성할 때 Kafka는 파티션 리더를 각 Broker에 균등하게 분산시킵니다. 이 최초 할당된 리더를 Preferred Leader라고 합니다. 문제는 운영 중 Broker 재시작이나 장애가 반복되면 리더가 점점 특정 Broker에 몰리기 시작한다는 것입니다.

리더 쏠림 현상 — 실무에서 자주 발생
✅ 균등 분산 (초기)
Broker 1 👑👑 (P0, P1)
Broker 2 👑👑 (P2, P3)
Broker 3 👑👑 (P4, P5)
🚨 리더 쏠림 (운영 후)
Broker 1 👑👑👑👑👑👑 (P0~P5)
Broker 2 (Follower만)
Broker 3 (Follower만)
리더가 몰린 Broker 1에 읽기/쓰기 트래픽 집중 → 과부하 → 장애 위험
해결책: auto.leader.rebalance.enable 설정
auto.leader.rebalance.enable=true (기본값) 로 설정하면 Kafka가 주기적으로 Preferred Leader로 리밸런싱합니다.
수동으로 즉시 실행하려면: kafka-leader-election.sh --type preferred
현재 리더 분포 확인: kafka-topics.sh --describe --topic 토픽명
 
 
 
Preferred Leader 리밸런싱 — CLI
Shell
# 파티션 리더 분포 현황 확인
kafka-topics.sh \
  --bootstrap-server kafka1:9092 \
  --describe \
  --topic order-events

# 출력 예시
# Topic: order-events  Partition: 0  Leader: 1  Replicas: 1,2,3  Isr: 1,2,3
# Topic: order-events  Partition: 1  Leader: 1  Replicas: 2,3,1  Isr: 1,2,3  ← Preferred는 2인데 1이 리더!

# Preferred Leader로 즉시 리밸런싱
kafka-leader-election.sh \
  --bootstrap-server kafka1:9092 \
  --election-type PREFERRED \
  --all-topic-partitions
· · ·
⚖️ Section 06

acks 설정과 ISR의 관계 — 유실 vs 성능 트레이드오프

acks 설정 동작 방식 성능 메시지 유실 위험 적합한 상황
acks=0 ack 없이 바로 다음 전송 최고 매우 높음 로그 수집, 유실 허용 데이터
acks=1 Leader만 받으면 ack 보통 중간 일반 이벤트, 적당한 내구성
acks=all (-1) ISR 전체가 받아야 ack 낮음 최소화 결제, 주문 등 중요 데이터
🔬
acks=all + min.insync.replicas=2 조합 — 실무 황금 공식:
① Producer가 메시지 전송 → Leader가 수신
② Follower들이 Leader로부터 Pull → 복제
③ ISR 중 최소 2개(Leader 포함)가 복제 완료를 확인
④ Leader가 Producer에게 ack 전송
⑤ 이 시점부터 메시지는 안전하게 저장됨

결론: Broker 1대가 죽어도 나머지 2대 중 1대에 데이터가 있으므로 유실 없음!
· · ·
🚨 Section 07

실무 장애 시나리오와 대응법

🔴

시나리오 1 — ISR이 1개로 줄었는데 리더가 죽음

🚨 상황: Follower 2대가 느려 ISR에서 제거됨 → ISR={리더만}. 이 상태에서 리더 Broker 다운.
unclean.leader.election.enable=true 이면: ISR 밖 Follower가 리더 승격 → 미복제 메시지 유실!
unclean.leader.election.enable=false 이면: 파티션 리더 없음 → Producer/Consumer 완전 중단!
✅ 예방 설정:
1) replica.lag.time.max.ms를 낮게 설정 → ISR 이탈 빠르게 감지하고 알림
2) min.insync.replicas=2 → ISR이 1개가 되는 순간 Producer 쓰기 거부로 조기 인지
3) Broker 리소스(CPU/Disk I/O) 여유 충분히 확보 → Follower 지연 방지
🔴

시나리오 2 — 리더 쏠림으로 특정 Broker 과부하

🚨 상황: 여러 번의 Broker 재시작 후 파티션 리더가 Broker 1에 집중. Broker 1의 CPU/네트워크가 포화 상태. Consumer Lag 급증.
✅ 즉시 대응: kafka-leader-election.sh --election-type PREFERRED --all-topic-partitions 실행
✅ 예방: auto.leader.rebalance.enable=true + leader.imbalance.check.interval.seconds=300 설정으로 5분마다 자동 리밸런싱
🔴

시나리오 3 — Follower가 계속 ISR에서 탈락

🚨 상황: 특정 Broker의 Follower가 주기적으로 ISR에서 빠졌다가 들어오기를 반복. Consumer Lag 지표도 불안정.
✅ 원인 탐색 순서:
1) 해당 Broker 디스크 I/O 확인 (디스크 포화 → 복제 지연)
2) GC 로그 확인 (긴 GC Pause → 복제 스레드 멈춤)
3) 네트워크 bandwidth 확인 (대역폭 부족 → 복제 지연)
4) replica.lag.time.max.ms 값이 너무 낮게 설정된 건 아닌지 확인
· · ·
⚙️ Section 08

운영 핵심 설정값 총정리

 
 
 
server.properties — 운영 환경 권장 설정
Properties
### Replication 관련
default.replication.factor=3         # Topic 기본 복제 계수
min.insync.replicas=2               # 최소 ISR 수 (acks=all 시 적용)
unclean.leader.election.enable=false # 데이터 무결성 우선

### ISR 판단
replica.lag.time.max.ms=10000       # 10초 내 동기화 안 하면 ISR 제외
replica.fetch.min.bytes=1
replica.fetch.wait.max.ms=500

### Leader 리밸런싱
auto.leader.rebalance.enable=true
leader.imbalance.check.interval.seconds=300  # 5분마다 리밸런싱 체크
leader.imbalance.per.broker.percentage=10    # 10% 이상 불균형 시 리밸런싱

### Controller (KRaft 모드)
process.roles=broker,controller     # 소규모 클러스터: 겸용
# 대규모: broker / controller 역할 분리 권장
 
 
 
Producer 설정 — 메시지 유실 방지 완전체
YAML
spring.kafka.producer:
  acks: all                          # ISR 전체 확인
  retries: 3                          # 실패 시 재시도
  properties:
    enable.idempotence: true          # 중복 방지
    max.in.flight.requests.per.connection: 5
    delivery.timeout.ms: 120000      # 2분 내 최종 전달 보장
    request.timeout.ms: 30000        # 리더 응답 대기 30초
    retry.backoff.ms: 1000           # 재시도 간격 1초

⚡ "리더가 죽어도 서비스가 살아있는 것이 Kafka의 가치입니다"

Leader/Follower/ISR 이 3가지만 제대로 이해하면
Kafka 운영의 90%는 해결됩니다.
장애 때 당황하지 않으려면 평소에 ISR 모니터링과 리더 분포 확인을 습관화하세요 💪

비슷한 장애 경험 있으시면 댓글로 공유해 주세요!

#Kafka #KafkaLeader #KafkaFollower #ISR #카프카실무 #아파치카프카 #카프카운영 #LeaderElection #백엔드개발 #개발블로그 #카프카장애대응
반응형
Comments