운영과 보안 — 클러스터 건강 유지와 "누가 뭘 할 수 있는가" 통제

Kafka를 기본 설정으로 두면 통신이 평문(PLAINTEXT)이고, 아무나 topic에 쓸 수 있다. 개발/테스트에만 허용되는 상태다. 프로덕션에선 (1) 클러스터가 건강한지 감시하고, (2) 누가 접속하고 무엇을 할 수 있는지 통제해야 한다.

이 글은 Kafka 운영의 두 축과, 실제로 보안을 어떻게 적용하는지(SASL_SSL/SCRAM 설정, 인증서, ACL)까지 다룬다. 읽고 나면 broker와 client에 보안을 설정할 수 있다.

운영의 두 축

  1. 클러스터 건강 — broker가 살아있고, 복제가 따라잡고, 리더가 정상인가.
  2. 보안 — 인증(누가), 인가(뭘 할 수 있는가), 암호화(통신 노출 여부).

클러스터 건강 — 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.

생각해 볼 문제

  1. 보안 3계층이 각각 해결하는 위협을 말하라.
  2. SASL/PLAIN을 SSL 없이 쓰면 왜 위험한가? SCRAM이 상대적으로 안전한 이유는?
  3. SCRAM 자격증명을 broker에 추가하는 명령을 써 보라.
  4. SASL_SSL을 적용하기 위한 broker 설정 항목 5가지를 말하라.
  5. ACL로 "User:alice가 orders topic에 쓰기·읽기" 권한을 부여하는 명령은?
  6. URP가 운영 경보의 핵심인 이유는? JMX로 뭘 봐야 하는가?

참고

'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