백엔드 데이터 인프라 99편. Kafka 운영 기본 — Topic 생성·수정·삭제, Partition 추가, Partition Reassignment 로 broker 추가·제거, Preferred Leader Election, Rolling Restart, Graceful Shutdown 같은 DevOps 일상 명령을 풀어쓴 학습 노트.
이 글은 백엔드 데이터 인프라 시리즈 130편 중 99편이에요. Part 5-4 Configuration 까지 설정 영역을 잡았다면, 이번 99편부터는 Part 5-5 — Operations (6편) 입니다. 첫 글은 Kafka 일상 운영 — Topic(메시지 묶음 단위) 생성부터 Broker(Kafka 서버 한 대) 추가·제거까지 살펴봐요.
Kafka 운영이 어렵게 느껴지는 이유
Kafka 운영은 분산 시스템에서 가장 손이 많이 가는 영역이에요. 도구가 많고 시나리오가 풍부해서 그렇습니다.
첫째, CLI(명령줄 도구) 개수가 30개를 넘어요. kafka-topics·kafka-configs·kafka-reassign-partitions·kafka-consumer-groups·kafka-acls·kafka-storage·kafka-leader-election·... 어느 걸 언제 쓰는지가 첫 관문입니다.
둘째, Partition Reassignment(파티션 재할당) 의 복잡성입니다. broker 를 추가하면 기존 partition 일부를 새 broker 로 옮겨야 하는데, 대량 데이터 이동과 네트워크 부담을 같이 관리해야 해요.
셋째, Rolling Restart(무중단 순차 재시작) 의 정확성이에요. broker 를 한 대씩 재시작하면서 Replication(복제본 동기화) 을 유지하고 Leader(파티션의 쓰기 담당) 재선출을 최소화해야 합니다.
이 글에서 일상 운영 다섯 가지 영역을 한 번에 정리할게요.
1. Topic 운영
생성
$ kafka-topics.sh --bootstrap-server localhost:9092 \
--create --topic orders \
--partitions 20 --replication-factor 3 \
--config retention.ms=604800000
옵션 권장:
--partitions= 처음에 충분히 잡아두기 (늘리기만 가능, 줄이기는 안 됨)--replication-factor 3= 운영 환경 표준--config= topic 별 retention·compression 같은 설정
목록·정보
# 목록
$ kafka-topics.sh --bootstrap-server localhost:9092 --list
# 상세
$ kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic orders
# Under-replicated partitions (운영 모니터링)
$ kafka-topics.sh --bootstrap-server localhost:9092 --describe \
--under-replicated-partitions
Partition 추가
$ kafka-topics.sh --bootstrap-server localhost:9092 \
--alter --topic orders --partitions 40
여기서 시험 함정이 하나 있어요 — partition 을 추가해도 기존 메시지는 원래 partition 에 그대로 남아요. 새 메시지부터 재해시되기 때문에 key 기반 순서 보장이 깨질 수 있어서 신중히 다뤄야 합니다.
Config 변경
# 추가/변경
$ kafka-configs.sh --bootstrap-server localhost:9092 \
--entity-type topics --entity-name orders \
--alter --add-config "retention.ms=172800000,compression.type=zstd"
# 제거 (default 로)
$ kafka-configs.sh --bootstrap-server localhost:9092 \
--entity-type topics --entity-name orders \
--alter --delete-config "retention.ms"
삭제
$ kafka-topics.sh --bootstrap-server localhost:9092 \
--delete --topic orders
비동기입니다. 실제 삭제는 broker 가 백그라운드에서 처리해요.
2. Consumer Group 운영
그룹 목록
$ kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list
그룹 상태·lag
$ kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group order-workers
GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID
order-workers orders 0 1234 1240 6 consumer-1-...
order-workers orders 1 5678 5680 2 consumer-2-...
운영에서 가장 자주 보는 명령이에요. LAG(소비 지연 메시지 수) 가 운영 모니터링의 핵심입니다.
Offset Reset
# 처음부터
$ kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--group order-workers --topic orders \
--reset-offsets --to-earliest --execute
# 끝으로
$ kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--group order-workers --topic orders \
--reset-offsets --to-latest --execute
# 특정 시간
$ kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--group order-workers --topic orders \
--reset-offsets --to-datetime 2026-05-17T00:00:00.000 --execute
# 특정 offset
$ kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--group order-workers --topic orders --partition 0 \
--reset-offsets --to-offset 12345 --execute
운영에서 손에 꼽는 강력한 도구예요. bug 후 재처리나 사고 구간 skip 에 씁니다. 실행 전에 --dry-run 으로 한 번 미리 확인하는 게 안전해요.
그룹 삭제
$ kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--delete --group old-workers
활성 consumer 가 있으면 거부됩니다. 모든 consumer 를 종료한 뒤에 실행해야 해요.
3. Partition Reassignment — Broker 추가·제거
시나리오 — Broker 1, 2, 3 → Broker 4 추가
기존 partition 은 Broker 1~3 에만 분포해 있어요. Broker 4 를 추가했다면 기존 partition 일부를 4 로 옮겨야 의미가 있습니다.
Step 1: 현재 partition 분포 확인
# 이전 명령 결과
$ kafka-topics.sh --describe --topic orders
Topic: orders Partition: 0 Leader: 1 Replicas: 1,2,3 Isr: 1,2,3
Topic: orders Partition: 1 Leader: 2 Replicas: 2,3,1 Isr: 2,3,1
Topic: orders Partition: 2 Leader: 3 Replicas: 3,1,2 Isr: 3,1,2
Step 2: Reassignment JSON 생성
topics-to-move.json:
{
"topics": [{"topic": "orders"}],
"version": 1
}
자동 생성:
$ kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
--topics-to-move-json-file topics-to-move.json \
--broker-list "1,2,3,4" \
--generate
Current partition replica assignment
{...}
Proposed partition reassignment configuration
{
"version":1,
"partitions":[
{"topic":"orders","partition":0,"replicas":[4,2,3]},
...
]
}
Step 3: 실행
reassignment.json 저장 후:
$ kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
--reassignment-json-file reassignment.json \
--execute
여기서부터 대량 데이터 이동이 시작됩니다.
Step 4: 진행 확인
$ kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
--reassignment-json-file reassignment.json \
--verify
Reassignment of partition X is still in progress 또는 complete 가 떠요.
Throttling — 네트워크 부담 제한
대량 이동은 cluster 네트워크와 디스크를 한꺼번에 잡아먹어요. Throttle(전송 속도 제한) 로 막아둡니다.
$ kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
--reassignment-json-file reassignment.json \
--execute --throttle 50000000 # 50 MB/s
운영 환경에서는 필수예요. 안 걸어두면 정상 트래픽이 같이 흔들립니다.
완료 후 throttle 제거:
$ kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
--reassignment-json-file reassignment.json \
--verify # 자동으로 throttle 제거
4. Preferred Leader Election
문제
Reassignment 후나 broker 재시작 후에 Leader 가 특정 broker 한 곳에 몰리면서 부하가 한쪽으로 쏠릴 때가 있어요.
Topic 생성 시 각 partition 의 첫 replica 가 preferred leader(선호 리더) 로 지정돼요. 정상 운영이라면 이 preferred leader 가 실제 leader 로 자연스럽게 잡혀 있는 상태가 맞습니다.
명령
# 모든 topic 의 preferred leader election
$ kafka-leader-election.sh --bootstrap-server localhost:9092 \
--election-type preferred --all-topic-partitions
# 특정 topic
$ kafka-leader-election.sh --bootstrap-server localhost:9092 \
--election-type preferred --topic orders
Auto Leader Rebalance
# server.properties
auto.leader.rebalance.enable=true
leader.imbalance.per.broker.percentage=10
leader.imbalance.check.interval.seconds=300
true (기본) 로 두면 preferred leader 가 자동으로 회복돼요. 대부분 환경에서 이걸로 충분합니다.
5. Rolling Restart — 무중단 재시작
시나리오
설정 변경·security patch·버전 upgrade 같은 작업에서 모든 broker 를 재시작해야 할 때가 와요. 한 번에 다 재시작하면 서비스가 끊기니까 하나씩 순차로 갑니다.
Step 1: Broker 한 대씩
# Broker 1 종료 (graceful)
$ ssh broker-1
$ kafka-server-stop.sh
# 또는 systemd 사용 시
$ sudo systemctl stop kafka
# 재시작
$ kafka-server-start.sh -daemon config/server.properties
# 또는
$ sudo systemctl start kafka
Step 2: 다음 broker 전 확인
# Under-replicated partitions = 0 인지
$ kafka-topics.sh --bootstrap-server localhost:9092 --describe \
--under-replicated-partitions
--under-replicated-partitions 가 0 으로 떨어졌을 때만 다음 broker 로 넘어가요. 안 그러면 데이터 손실 위험이 따라옵니다.
Step 3: 반복
3 broker cluster 면 3 번 반복이에요. broker 사이에 Replication 이 회복될 시간을 충분히 줘야 합니다.
Graceful Shutdown — 자동 leadership transfer
# server.properties
controlled.shutdown.enable=true # 기본
controlled.shutdown.max.retries=3
true 면 종료 직전에 leadership 을 다른 replica 로 넘겨줘요. 클라이언트가 받는 영향이 최소화됩니다.
여기가 정말 중요해요 — 항상 controlled shutdown 사용. kill -9 같은 hard kill 은 unclean leader election(동기화 안 된 복제본이 리더가 되는 사고) 위험과 ISR(In-Sync Replicas, 동기화된 복제본 집합) 깨짐을 같이 부릅니다.
6. 자주 쓰는 도구 모음
| 도구 | 용도 |
|---|---|
kafka-topics.sh |
Topic CRUD |
kafka-configs.sh |
Topic/Broker config |
kafka-consumer-groups.sh |
Consumer group 상태·offset |
kafka-reassign-partitions.sh |
Partition 재할당 |
kafka-leader-election.sh |
Leader 재선출 |
kafka-acls.sh |
ACL 관리 |
kafka-storage.sh |
KRaft 저장소 포맷 |
kafka-server-start.sh·kafka-server-stop.sh |
Broker 제어 |
kafka-console-producer.sh·kafka-console-consumer.sh |
디버깅용 메시지 송수신 |
kafka-dump-log.sh |
Log segment 분석 |
kafka-broker-api-versions.sh |
Broker API 버전 확인 |
kafka-features.sh |
Cluster feature 관리 |
kafka-cluster.sh |
Cluster 정보 |
자동화 — Cruise Control
규모가 커지면 수동 reassignment 부담이 빠르게 늘어나요. 그래서 등장한 게 Cruise Control (LinkedIn 오픈소스) 입니다. 자동 partition balancing·dead broker replacement·rolling restart 같은 영역을 묶어서 처리해줘요.
- Broker 추가 → 자동 reassignment 제안 + 실행
- Goal-based optimization (CPU·디스크·네트워크 균형)
- Anomaly detection (lag·throughput drop)
운영 부담이 크게 줄어들어서 broker 수십~수백 대 환경에서는 사실상 표준처럼 쓰입니다.
한계·실무 함정
1. Partition 추가 = key 순서 깨짐
위에서 강조한 부분입니다. 비즈니스 영향을 한 번 평가한 다음에 들어가요.
2. Reassignment 없이 broker 추가
새 broker 가 partition 없이 idle 로 남아요. 반드시 reassignment 까지 같이 돌립니다.
3. Throttle 없이 reassignment
정상 트래픽 영향이 폭증해요. 항상 throttle.
4. Rolling Restart 시 under-replicated 무시
데이터 손실 위험이 생깁니다. 반드시 0 확인 후 진행.
5. Hard kill
controlled.shutdown 을 우회하면 unclean leader election 위험을 끌어옵니다.
6. auto.create.topics.enable=true + 운영
오타 topic 이 폭증해요. 운영 환경 false (94편).
시험 직전 한 번 더 — Kafka 운영 기본 함정 압축 노트
- Topic 운영 =
kafka-topics.sh로 CRUD +kafka-configs.sh로 config - 생성 권장 =
--partitions충분히 +--replication-factor 3 - Partition 추가 = 가능, 줄이기 X
- 추가 시 = 기존 메시지 partition 그대로, key 순서 깨질 수 있음
- Consumer Group =
kafka-consumer-groups.sh --describe로 LAG 모니터링 - Offset Reset =
--reset-offsets --to-earliest/latest/datetime/offset --dry-run으로 미리 확인- 활성 consumer 있으면 그룹 삭제 거부
- Partition Reassignment 4단계 = 현재 확인 → JSON 생성 (
--generate) → 실행 (--execute --throttle) → 진행 확인 (--verify) - Throttle 필수 — 운영 환경에서 안 하면 트래픽 영향
- Preferred Leader Election =
kafka-leader-election.sh또는auto.leader.rebalance.enable=true(기본) - Rolling Restart — 한 broker 씩 +
--under-replicated-partitions = 0확인 후 다음 controlled.shutdown.enable=true(기본) — graceful shutdown,kill -9절대 금지- 도구 모음 =
kafka-topics·configs·consumer-groups·reassign-partitions·leader-election·acls·storage·dump-log·features·cluster - 대규모 자동화 = Cruise Control (LinkedIn)
- 자동 balancing·dead broker replacement·anomaly detection
- 함정 — partition 추가 = key 순서 깨짐
- 함정 — reassignment 없는 broker 추가 = idle broker
- 함정 — throttle 없는 reassignment = 트래픽 영향
- 함정 — under-replicated 무시한 rolling restart = 데이터 손실
- 함정 — hard kill = unclean leader election 위험
공식 문서: Kafka Operations 에서 자세한 사양과 시나리오를 확인할 수 있어요.
시리즈 다른 편 (앞뒤 글 모음)
이전 글:
- 94편 — Kafka Broker 설정 30가지 (실무 핵심)
- 95편 — Kafka Topic 설정 (Retention · Compression · Cleanup)
- 96편 — Kafka Producer 설정 20가지 (Batching · Retries · Idempotence)
- 97편 — Kafka Consumer 설정 25가지 (Group · Commit · Fetch)
- 98편 — Kafka Admin Client 설정 (간결 정리)
다음 글: