1. 브로커와 컨트롤러의 개념
- 브로커(Broker)
- Kafka에서 데이터를 실제로 저장하고 서비스하는 주체
- 프로듀서(Producer)가 보낸 메시지를 저장하고, 컨슈머(Consumer)가 가져가도록 제공
- 브로커 여러 개가 있으면 파티션 단위로 데이터를 분산 저장하고 복제
- 컨트롤러(Controller)
- 클러스터의 두뇌 역할
- 브로커들의 상태를 관리, 리더 선출, 토픽 메타데이터 관리
- Kafka KRaft 모드에서는 컨트롤러끼리 Raft 합의를 통해 과반수 투표로 리더를 선출
즉, 브로커 = 데이터 저장소, 컨트롤러 = 클러스터 관리자 이다. 여기서 중요한건, 컨트롤러들은 대표를 선출해야하기 때문에 서로간 통신이 필요하고, 만약 컨트롤러가 분리되어 설치되어 있다면, 각 포트를 양방향 TCP 로 개방해주어야 한다는 것이다. 브로커 역시 각 브로커간 데이터를 송수신 하려면 포트를 개방해줘야 하지만, 브로커 포트는 단방향으로만 열어주면 된다.
즉 1번 PC 에 node.1 과 node.2 가 설치되어 있다면 9093, 9094 포트를, 2번 PC 의 node.3 의 9095 포트를 (양방향 TCP) 개방 해주어야 각 브로커들이 통신을 통해 리더를 선출할 수 있다.
2. 두 PC에서 브로커 설치를 위한 properties 설정법
1번 PC = 192.168.0.98 , 2번 PC 192.168.0.99 로 예를 들면
- 1번 PC 의 node.1
process.roles=broker,controller
node.id=1
controller.quorum.voters=1@192.168.0.98:9093,2@192.168.0.98:9094,3@192.168.0.99:9095
listeners=PLAINTEXT://0.0.0.0:9096,CONTROLLER://0.0.0.0:9093
advertised.listeners=PLAINTEXT://192.168.0.98:9096
inter.broker.listener.name=PLAINTEXT
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
controller.listener.names=CONTROLLER
log.dirs=~/kafka/logs/kraft-combined-logs-1
- 1번 PC 의 node.2
process.roles=broker,controller
node.id=2
controller.quorum.voters=1@192.168.0.98:9093,2@192.168.0.98:9094,3@192.168.0.99:9095
listeners=PLAINTEXT://0.0.0.0:9097,CONTROLLER://0.0.0.0:9094
advertised.listeners=PLAINTEXT://192.168.0.98:9097
inter.broker.listener.name=PLAINTEXT
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
controller.listener.names=CONTROLLER
log.dirs=~/kafka/logs/kraft-combined-logs-2
- 2번 PC 의 node.3
process.roles=broker,controller
node.id=3
controller.quorum.voters=1@192.168.0.98:9093,2@192.168.0.98:9094,3@192.168.0.99:9095
listeners=PLAINTEXT://0.0.0.0:9098,CONTROLLER://0.0.0.0:9095
advertised.listeners=PLAINTEXT://192.168.0.99:9098
inter.broker.listener.name=PLAINTEXT
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
controller.listener.names=CONTROLLER
log.dirs=~/kafka/logs/kraft-combined-logs-3
3. 실행 후 포트 확인
Kafka 실행 후 아래 명령어로 포트가 열렸는지 확인한다
ss -lntp | grep :90
1번 PC

2번 PC

4. 클러스터 검증 방법
- 컨트롤러 합의 확인
cd kafka/bin
./kafka-metadata-quorum.sh --bootstrap-server 192.168.0.98:9096 describe --status

- CurrentVoters: [1,2,3] → 세 노드가 모두 합의에 참여 했다는 것을 알 수 있다.
- LeaderId: X → 현재 컨트롤러 리더 노드이다.
- 토픽 생성 후 리더/복제 상태 확인
cd kafka/bin
./kafka-topics.sh --bootstrap-server 192.168.0.98:9096 --create --topic test-topic --partitions 3 --replication-factor 3
./kafka-topics.sh --bootstrap-server 192.168.0.98:9096 --describe --topic test-topic

- 파티션 리더가 1,2,3에 골고루 분산 되어있음을 볼 수 있다.
- Replicas, ISR에 [1,2,3] 모두 포함되어 있다.
5. 방화벽으로 포트를 차단한다면?
- 컨트롤러 포트(9093/9094/9095) 차단 시
- 컨트롤러 간 Raft 합의 불가
- 로그에 Controller connection failed, Quorum not achieved 등이 출력되며 클러스터가 비정상 종료
- 단방향으로 막을 경우, 프로세스가 살아있을 수 있고, 양방향 (in / out ) 으로 포트를 닫을경우 localhost 안에서도 통신이 불가하므로, kafka 가 실행되지 않는다.
# 1번 PC
sudo ufw deny 9093/tcp
sudo ufw status numbered
sudo ufw deny 9094/tcp
sudo ufw status numbered
# 2번 PC
sudo ufw deny 9095/tcp
sudo ufw status numbered


-> 단방향 차단시 3번 브로커(노드) 만 연결하지 못단다는 로그가 생성되고 과반 (1,2) 의 노드는 서로 통신 가능하기 때문에 프로세스가 죽지 않는다.
즉 in / out / 루프백 까지 포트를 차단하면 kafka 프로세스는 실행 후 얼마뒤에 종료된다.
- 브로커 포트(9096/9097/9098) 차단 시
- 클러스터 자체는 살아있지만 일부 파티션 리더/팔로워 간 복제가 안 됨
- 로그에 Under-replicated partitions 경고 발생
이 실험을 통해 왜 컨트롤러 포트는 양방향 열어야 하고, 브로커 포트는 Inbound만 열어주면 되는지 명확히 알 수 있다.
6. 헤어핀 현상
- 같은 서브넷 환경에서는 각 PC가 서로의 REAL IP를 직접 바라볼 수 있으므로, 설정 파일(listeners, advertised.listeners, controller.quorum.voters)에 해당 상대의 REAL IP만 정확히 적어주면 된다
-하지만 망연계(NAT) 인프라 환경에서는 상황이 달라진다.
- 내 PC가 가진 REAL IP와, 상대방이 나를 바라볼 때 사용하는 NAT 변환된 외부 IP가 다르다.
- 이 때문에 내가 내 설정에 localhost(혹은 REAL IP)를 그대로 쓰면, 상대는 NAT IP로만 접근할 수 있기 때문에 서로 인식이 어긋난다.
- 특히 같은 머신 안에서 자기 자신을 NAT IP로 호출하려 하면, 헤어핀 NAT(Loopback NAT) 기능이 필요하다.
- 장비나 방화벽이 이를 지원하지 않으면 **자기 자신을 인식하지 못하는 문제(헤어핀 현상)**가 발생한다.
- 두 PC 모두 broker+controller 로 운영(PC1: broker1/2, PC2: broker3) 하면서 이 구조에서 헤어핀 회피 + NAT 통과를 동시에 만족하려면
- controller.quorum.voters 는 모든 노드에서 동일한 문자열을 쓰고,
- 그 안의 호스트명을 /etc/hosts 로 각 PC에서 다르게 해석시키며,
- 브로커의 advertised.listeners 에도 호스트명을 쓰고 split-horizon(PC1과 PC2에서 다르게 해석)을 적용해야 한다.
node.1 설정 (PC1)
process.roles=broker,controller
node.id=1
# 모든 노드에서 "문자열 동일" (호스트명 사용)
controller.listener.names=CONTROLLER
controller.quorum.voters=1@ctrl-n1:9093,2@ctrl-n2:9094,3@ctrl-n3:9095
# 바인딩은 로컬 존재 주소(0.0.0.0 권장)
listeners=PLAINTEXT://0.0.0.0:9096,CONTROLLER://0.0.0.0:9093
# 광고는 호스트명(브로커용) 사용
advertised.listeners=PLAINTEXT://broker-n1:9096
inter.broker.listener.name=PLAINTEXT
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
log.dirs=/data/kafka/node1
node.2 설정(PC1)
process.roles=broker,controller
node.id=2
controller.listener.names=CONTROLLER
controller.quorum.voters=1@ctrl-n1:9093,2@ctrl-n2:9094,3@ctrl-n3:9095
listeners=PLAINTEXT://0.0.0.0:9097,CONTROLLER://0.0.0.0:9094
advertised.listeners=PLAINTEXT://broker-n2:9097
inter.broker.listener.name=PLAINTEXT
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
log.dirs=/data/kafka/node2
node.3 설정 (PC2)
process.roles=broker,controller
node.id=3
controller.listener.names=CONTROLLER
controller.quorum.voters=1@ctrl-n1:9093,2@ctrl-n2:9094,3@ctrl-n3:9095
listeners=PLAINTEXT://0.0.0.0:9098,CONTROLLER://0.0.0.0:9095
advertised.listeners=PLAINTEXT://broker-n3:9098
inter.broker.listener.name=PLAINTEXT
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
log.dirs=/data/kafka/node3
- /etc/hosts 파일 설정
PC 1
# 컨트롤러 이름 → 자기 자신은 REAL, 상대는 NAT
192.168.0.98 ctrl-n1
192.168.0.98 ctrl-n2
200.200.200.200 ctrl-n3
# 브로커 광고 이름 → 자기 자신(두 개)은 loopback/REAL, 상대는 NAT
127.0.0.1 broker-n1
127.0.0.1 broker-n2
200.200.200.200 broker-n3
PC2
# 컨트롤러 이름 → 상대는 NAT, 자기 자신은 REAL
100.100.100.100 ctrl-n1
100.100.100.100 ctrl-n2
192.168.0.99 ctrl-n3
# 브로커 광고 이름 → 상대는 NAT, 자기 자신은 loopback/REAL
100.100.100.100 broker-n1
100.100.100.100 broker-n2
127.0.0.1 broker-n3
- 기존 노드 구성이 같고, 데이터를 유지한다면 아래 진행 절차를 따르지 않아도 되지만, 새로 설정을 적용하여 재시작 하려 한다면
새로운 uuid 를 발급하고 세 브로커를 묶어주는 설정을 해야 한다.
CLUSTER_ID=$(bin/kafka-storage.sh random-uuid)
bin/kafka-storage.sh format -t $CLUSTER_ID -c server-1.properties
bin/kafka-storage.sh format -t $CLUSTER_ID -c server-2.properties
bin/kafka-storage.sh format -t $CLUSTER_ID -c server-3.properties
bin/kafka-storage.sh info -c server-1.properties # node.id=1 / 같은 cluster.id 확인'CS 공부 > 기타' 카테고리의 다른 글
| [ETC] 카프카 properties 파일 세부 분석 (3) | 2025.08.28 |
|---|---|
| [ETC] ESXi란 무엇인가? (0) | 2025.08.26 |
| [ETC] KAFKA 복습 및 설정 템플릿 (0) | 2025.08.22 |
| [etc] NTP 란 무엇인가? (0) | 2025.08.21 |
| [기타] Mac OS 에서 가상 윈도우 PC 로 원격 접속하기 (1) | 2025.08.18 |