운영과 보안 — 클러스터 건강 유지와 "누가 뭘 할 수 있는가" 통제
Kafka를 기본 설정으로 두면 통신이 평문(PLAINTEXT)이고, 아무나 topic에 쓸 수 있다. 개발/테스트에만 허용되는 상태다. 프로덕션에선 (1) 클러스터가 건강한지 감시하고, (2) 누가 접속하고 무엇을 할 수 있는지 통제해야 한다.
이 글은 Kafka 운영의 두 축과, 실제로 보안을 어떻게 적용하는지(SASL_SSL/SCRAM 설정, 인증서, ACL)까지 다룬다. 읽고 나면 broker와 client에 보안을 설정할 수 있다.
운영의 두 축
- 클러스터 건강 — broker가 살아있고, 복제가 따라잡고, 리더가 정상인가.
- 보안 — 인증(누가), 인가(뭘 할 수 있는가), 암호화(통신 노출 여부).
클러스터 건강 — KRaft와 복제 감시
Kafka 4.x는 KRaft로 메타데이터를 관리한다(장 01·06). 운영자가 봐야 할 것:
- URP(under-replicated partitions) — ISR < 복제본 수. 복제가 안 따라잡아 장애 내성 저하. 핵심 경보(장 06).
- ISR shrink/expand 빈도 — 잦으면 broker 불건강(GC·디스크·네트워크).
- controller 활성 상태 — active controller는 1개여야 정상.
- request latency — broker 응답 지연.
JMX(보통 포트 9999)로 메트릭 수집(Prometheus/JMX exporter). URP/ISR 모니터링 없이는 장애 감지 불가.
보안 3계층 — 암호화·인증·인가를 분리하는 이유
| 계층 | 담당 | 수단 |
|---|---|---|
| 암호화(encryption) | 통신 내용 보호 | SSL/TLS |
| 인증(authentication) | 접속 주체 확인 | SASL(PLAIN/SCRAM/GSSAPI/OAUTHBEARER) 또는 mTLS |
| 인가(authorization) | 권한 제어 | ACL(kafka-acls.sh) |
왜 3계층을 분리하는가 — 심층 방어(defense in depth). 한 계층이 뚫려도 다른 층이 방어.
SASL 메커니즘 — PLAIN은 평문이다
| 메커니즘 | 비고 |
|---|---|
| PLAIN | 자격증명 평문 전송 → 반드시 SSL과 함께(SASL_SSL) |
| SCRAM-SHA-256/512 | 자격증명이 broker에 저장(해시). SSL 없이도 상대적 안전 |
| GSSAPI(Kerberos) | 기업 환경, 복잡 |
| OAUTHBEARER | JWT/OAuth 연동 |
자주 틀리는 함정: "SASL만 켜면 안전하다" — SASL/PLAIN은 평문 → SSL 없이면 도청 취약. 반드시
SASL_SSL.
보안 프로토콜 조합
security.protocol |
암호화 | 인증 | 용도 |
|---|---|---|---|
PLAINTEXT |
X | X | 개발 전용 |
SSL |
O | mTLS(선택) | TLS 암호화 |
SASL_PLAINTEXT |
X | SASL | 인증만 (평문) |
SASL_SSL |
O | SASL | 프로덕션 표준 |
SASL_SSL/SCRAM 적용 방법 — 단계별 가이드
이제 실제로 보안을 어떻게 켜는지 단계별로 보자. SCRAM-SHA-256 + SSL 조합을 예로.
1단계: SCRAM 자격증명 생성 (broker에 사용자 추가)
# Kafka 4.3 — broker에 SCRAM 사용자 'alice' 추가
bin/kafka-configs.sh --bootstrap-server localhost:9092 \
--alter --add-config 'SCRAM-SHA-256=[password=alice-secret]' \
--entity-type users --entity-name alice
# 확인
bin/kafka-configs.sh --bootstrap-server localhost:9092 \
--describe --entity-type users --entity-name alice
이 자격증명은 KRaft 메타데이터에 저장된다(구 ZK와 다름).
2단계: broker 설정 (server.properties)
# 리스너 설정
listeners=SASL_SSL://:9092
advertised.listeners=SASL_SSL://broker1.example.com:9092
# SASL 메커니즘
sasl.enabled.mechanisms=SCRAM-SHA-256
sasl.mechanism.inter.broker.protocol=SCRAM-SHA-256
# 인가(Authorizer) 활성화
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
# ACL 없을 때 기본 거부
allow.everyone.if.no.acl.found=false
# super.users (모든 권한)
super.users=User:admin
# SSL 설정
ssl.keystore.location=/etc/kafka/keystore.jks
ssl.keystore.password=changeit
ssl.key.password=changeit
ssl.truststore.location=/etc/kafka/truststore.jks
ssl.truststore.password=changeit
3단계: SSL 인증서 준비 (keytool)
# 1. 키스토어 생성 (broker 인증서)
keytool -keystore /etc/kafka/keystore.jks -alias broker1 -validity 365 \
-genkey -keyalg RSA -dname "CN=broker1.example.com" \
-storepass changeit -keypass changeit
# 2. CA 인증서로 서명 (실제 환경)
# (자체 서명 인증서는 학습용; 프로덕션은 정식 CA 사용)
# 3. 트러스트스토어 생성 (client가 broker 인증서 검증용)
keytool -keystore /etc/kafka/truststore.jks -alias CARoot -import \
-file ca-cert -storepass changeit -noprompt
4단계: client 설정 (producer/consumer)
# 보안 프로토콜
security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-256
# JAAS (자격증명)
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
username="alice" \
password="alice-secret";
# SSL (broker 인증서 검증)
ssl.truststore.location=/etc/kafka/client-truststore.jks
ssl.truststore.password=changeit
또는 JAAS 파일 방식 (kafka_client_jaas.conf):
KafkaClient {
org.apache.kafka.common.security.scram.ScramLoginModule required
username="alice"
password="alice-secret";
};
5단계: ACL 부여
# alice에게 my-topic 쓰기 권한
bin/kafka-acls.sh --bootstrap-server localhost:9092 \
--add --allow-principal User:alice \
--operation WRITE --operation READ \
--topic my-topic
# alice에게 consumer group 'my-group' 권한
bin/kafka-acls.sh --bootstrap-server localhost:9092 \
--add --allow-principal User:alice \
--operation READ \
--group my-group
# ACL 확인
bin/kafka-acls.sh --bootstrap-server localhost:9092 --list
6단계: 보안 적용 후 producer/consumer 실행
# 보안 설정이 담긴 client properties 파일로 실행
bin/kafka-console-producer.sh --topic my-topic \
--producer.config /etc/kafka/client.properties \
--bootstrap-server broker1.example.com:9092
bin/kafka-console-consumer.sh --topic my-topic \
--consumer.config /etc/kafka/client.properties \
--bootstrap-server broker1.example.com:9092
보안 설정은 broker 재기동이 필요하다. 학습 환경에서는 무거울 수 있으니, PLAINTEXT 환경에서 동작을 먼저 확인한 뒤 보안을 적용하라.
ACL — 리소스와 작업
ACL은 리소스별로 "누가( principal) 무슨 작업(operation)을 할 수 있는가"를 정의한다:
| 리소스 종류 | 작업 예 |
|---|---|
topic |
READ, WRITE, CREATE, DELETE, ALTER, DESCRIBE |
group |
READ, DESCRIBE |
cluster |
CLUSTER_ACTION, DESCRIBE |
transactionalId |
WRITE, DESCRIBE |
# User:bob에게 orders topic 읽기 + my-group group 읽기
bin/kafka-acls.sh --add \
--allow-principal User:bob \
--operation READ --topic orders \
--operation READ --group my-group \
--bootstrap-server localhost:9092
# prefix 매칭 (모든 'logs-' topic에 쓰기)
bin/kafka-acls.sh --add \
--allow-principal User:logger \
--operation WRITE --topic logs- --resource-pattern-type prefixed \
--bootstrap-server localhost:9092
JMX 모니터링 설정
broker의 JMX 메트릭을 노출하려면:
# broker 기동 시 JMX 포트 지정
export JMX_PORT=9999
bin/kafka-server-start.sh config/server.properties
핵심 지표:
| 지표 | 의미 |
|------|------|
| kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions | URP 수 (0이 정상) |
| kafka.server:type=ReplicaManager,name=IsrShrinksPerSec | ISR 축소 빈도 |
| kafka.network:type=RequestMetrics,name=TotalTimeMs | 요청 지연 |
| kafka.controller:type=KafkaController,name=ActiveControllerCount | 활성 controller (1이 정상) |
Prometheus + JMX Exporter로 수집·Grafana로 시각화하는 게 운영 표준.
KRaft 운영 — broker 추가/제거
- broker 추가: 새 broker 기동 + partition 복제 이동(
kafka-reassign-partitions.sh). - controller 추가/제거: quorum 재구성(KIP-853 동적 quorum,
controller.quorum.bootstrap.servers).
# partition reassignment (broker 추가 후 부하 분산)
bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
--topics-to-move-json-file topics.json \
--broker-list "0,1,2" --generate
# → 생성된 계획으로 --execute
흔히 묻는 것, 흔히 틀리는 것
| 오해 | 정정 |
|---|---|
| "SASL만 켜면 안전하다" | PLAIN은 평문 자격증명 → SASL_SSL 필수 |
| "보안은 나중에 붙인다" | 재기동·호환성 비용. 설계 단계부터 권장 |
| "ACL 없으면 다 허용이다" | allow.everyone.if.no.acl.found 설정에 따라 다름 |
| "JMX는 옵션" | URP/ISR/지연 모니터링 없이는 장애 감지 불가 |
| "KRaft는 ZK와 운영 명령이 같다" | controller.quorum.bootstrap.servers(KIP-853)가 최신 |
| "mTLS는 클라이언트만" | broker 간 통신에도 권장 |
더 깊이
- 동적 broker 구성:
kafka-configs.sh --entity-type brokers로 재기동 없이 설정 변경. - partition reassignment throttle:
--throttle로 대량 복제 시 운영 트래픽 보호. - mTLS(상호 TLS): 클라이언트가 X.509 인증서 제시 → broker truststore로 검증. broker 간 통신 권장.
- OAUTHBEARER: JWT/OAuth 토큰 기반 인증(KIP-255). 클라우드 환경에서 유용.
요약 — 이 글의 결론
- 운영 2축: 클러스터 건강(KRaft/복제) + 보안 3계층.
- 건강 감시: JMX(포트 9999)로 URP·ISR·controller·지연. URP가 핵심 경보.
- 보안 3계층: 암호화(SSL), 인증(SASL/mTLS), 인가(ACL).
- SASL_SSL/SCRAM 적용: (1) SCRAM 자격증명 생성 → (2) broker 설정(listeners/SASL/SSL/ACL) → (3) SSL 인증서(keytool) → (4) client 설정(JAAS+truststore) → (5) ACL 부여 → (6) 보안 적용 후 실행.
- ACL:
kafka-acls.sh. 리소스(topic/group/cluster) × 작업(READ/WRITE/...). 기본 거부 권장. - KRaft 운영:
controller.quorum.bootstrap.servers(KIP-853 동적). broker 추가 시 reassignment.
생각해 볼 문제
- 보안 3계층이 각각 해결하는 위협을 말하라.
- SASL/PLAIN을 SSL 없이 쓰면 왜 위험한가? SCRAM이 상대적으로 안전한 이유는?
- SCRAM 자격증명을 broker에 추가하는 명령을 써 보라.
- SASL_SSL을 적용하기 위한 broker 설정 항목 5가지를 말하라.
- ACL로 "User:alice가 orders topic에 쓰기·읽기" 권한을 부여하는 명령은?
- URP가 운영 경보의 핵심인 이유는? JMX로 뭘 봐야 하는가?
참고
- Security Overview - 접근 2026-07-09
- Security Model - 접근 2026-07-09
- Authentication using SASL - 접근 2026-07-09
- SSL encryption - 접근 2026-07-09
- Authorization and ACLs - 접근 2026-07-09
- Operations — KRaft - 접근 2026-07-09
'Tech Artifacts > Kafka' 카테고리의 다른 글
| Kafka - 13. mirror maker 2 (0) | 2026.07.10 |
|---|---|
| Kafka - 11. kafka streams (0) | 2026.07.09 |
| Kafka - 10. kafka connect (0) | 2026.07.09 |
| Kafka - 09. schema registry (1) | 2026.07.09 |
| Kafka - 08. delivery semantics (0) | 2026.07.09 |
