Kafka는 고성능 분산 이벤트 스트리밍 플랫폼으로 데이터 파이프라인, 이벤트 pub-sub 등 다양한 목적으로 사용됩니다.
spring cloud stream을 이용한 이벤트 처리를 위해서 다양한 메시지 브로커가 사용될 수 있는데, kafka도 그 중 하나입니다.
이번 과정에서는 kafka를 Windows 환경에 간단하게 구성하는 방법을 살펴보도록 하겠습니다.
kafka 다운로드 페이지에서 kafka의 바이너리를 다운로드 받을 수 있습니다.
https://kafka.apache.org/downloads
작성 기점으로 3.6.1 버전이 사용되고 있지만, 3.3.1 버전을 기준으로 설명됩니다.
바이너리 다운로드 링크: https://archive.apache.org/dist/kafka/3.3.1/kafka_2.13-3.3.1.tgz

tgz 파일을 압축을 풀면 tar 묶음 파일이 등장하므로 다시 한 번 압축을 풀어 줍니다.

kafka는 분산 환경을 전제로 구성되어 있기 때문에 클러스터의 메타 데이터를 저장하고 관리하는 서비스로 zookeeper를 사용합니다.
zookeeper를 먼저 실행한 다음 kafka를 구동하도록 합니다.
로컬에서 띄우기 때문에 기본 설정값으로 바로 실행합니다.
zookeeper의 설정은 kafka 디렉토리의 conf/zookeeper.properties에서 확인 및 변경할 수 있습니다.
kafka-<<scala-version>>-<<kafka-version>> 폴더에 들어가서 cmd창을 엽니다.

zookeeper를 실행합니다. 실행 파일은 bin/windows/zookeeper-server-start.bat 파일입니다.
bin\windows\zookeeper-server-start.bat config\zookeeper.properties

zookeeper의 기본 포트는 2181 포트로 지정되어 있습니다.

kafka 서버의 실행 파일은 bin/windows/kafka-server-start.bat입니다.
기본 설정값으로 바로 실행합니다. kafka 서버의 설정 파일은 config/server.properties입니다.
bin\windows\kafka-server-start.bat config\server.properties


kafka 서버는 9092 포트로 실행됩니다.
kafka에서는 kafka 외부의 zookeeper를 이용해서 클러스터의 메타데이터를 관리하는 것에 한계를 느끼고, 메타데이터를 관리할 새로운 방법을 찾게 되었습니다.
이를 위해 kafka가 쿼럼 컨트롤러 역할을 수행할 수 있도록 kraft 모드가 생겨나게 되었습니다.

kraft 모드는 3.3.1 버전부터 프로덕션 레벨에 들어왔습니다.
kraft 모드로 실행하기 위한 방법은 config/kraft/REAME.md 파일에 작성되어 있는데, 여기서 간단하게 보도록 하겠습니다.
우선 kafka-storage 실행 파일을 이용해서 cluster의 아이디를 생성합니다.
bin\windows\kafka-storage.bat random-uuid
T00SyNf0RNOfZkOqlxfPlA
이렇게 생성한 uuid 값을 노드마다 입력해 줍니다.
bin\windows\kafka-storage.bat format -t <<uuid>> -c config\kraft\server.properties
Formatting /tmp/kraft-combined-logs with metadata.version 3.3-IV3.
그러면 kraft-combined-logs 디렉토리에서 meta.properties에 cluster의 아이디가 등록되어 있는 것을 확인할 수 있습니다.
#
#Thu Jan 18 12:45:44 KST 2024
cluster.id=T00SyNf0RNOfZkOqlxfPlA
node.id=1
version=1
kraft의 server.properties 파일을 이용해서 kafka 서버를 실행하면 kraft 모드로 실행됩니다.
bin\windows\kafka-server-start.bat config\kraft\server.properties
docker로 실행할 경우는 docker compose 파일을 이용해서 클러스터 형태로 기동할 수 있습니다.
이왕 compose로 기동하는 김에 kafka-ui도 넣어서 웹 서비스에서 kafka의 상태를 관리할 수 있도록 합니다
docker-compose.yml
version: '3.8'
services:
zookeeper:
image: confluentinc/cp-zookeeper
ports:
- '2181:2181' # <<host port>>:<<container port>>
environment:
# zookeeper의 포트 지정
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
kafka-1:
image: confluentinc/cp-kafka
ports:
- '9092:9092'
depends_on:
# zookeeper 컨테이너가 먼저 생성되어야 한다.
- zookeeper
environment:
# kafka 브로커 아이디(다른 노드에는 다른 아이디로 설정해야 한다)
KAFKA_BROKER_ID: 1
# zookeeper 접속 주소(service 이름대로 호스트 접근 가능)
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
# 리스너의 이름과 보안 방식 정의
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
# 클러스터 내부 브로커 사이에 통신하는 리스너의 이름
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
# 리스너의 호스트와 포트 지정
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-1:29092,EXTERNAL://localhost:9092
kafka-2:
image: confluentinc/cp-kafka
ports:
- '9093:9093'
depends_on:
# zookeeper 컨테이너가 먼저 생성되어야 한다.
- zookeeper
environment:
# kafka 브로커 아이디(다른 노드에는 다른 아이디로 설정해야 한다)
KAFKA_BROKER_ID: 2
# zookeeper 접속 주소(service 이름대로 호스트 접근 가능)
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
# 리스너의 이름과 보안 방식 정의
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
# 클러스터 내부 브로커 사이에 통신하는 리스너의 이름
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
# 리스너의 호스트와 포트 지정
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-2:29093,EXTERNAL://localhost:9093
kafka-3:
image: confluentinc/cp-kafka
ports:
- '9094:9094'
depends_on:
# zookeeper 컨테이너가 먼저 생성되어야 한다.
- zookeeper
environment:
# kafka 브로커 아이디(다른 노드에는 다른 아이디로 설정해야 한다)
KAFKA_BROKER_ID: 3
# zookeeper 접속 주소(service 이름대로 호스트 접근 가능)
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
# 리스너의 이름과 보안 방식 정의
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
# 클러스터 내부 브로커 사이에 통신하는 리스너의 이름
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
# 리스너의 호스트와 포트 지정
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka-3:29094,EXTERNAL://localhost:9094
kafka-ui:
image: provectuslabs/kafka-ui
container_name: kafka-ui
ports:
- "9000:8080"
restart: always
environment:
# 클러스터 이름
KAFKA_CLUSTERS_0_NAME=local
# 클러스터 접속 경로(멀티 노드라면 브로커 수만큼 지정)
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka-1:29092,kafka-2:29093,kafka-3:29094
# zookeeper 접속 경로
KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181
싱글 노드의 클러스터로 구성되었는데, 필요한 만큼 zookeeper와 kafka의 노드를 추가로 정의하여 클러스터를 구성할 수 있습니다.
docker-compose.yml 파일이 있는 디렉토리에서 docker compose up 명령어로 정의한 컨테이너를 동작시킵니다.
docker compose up -d

kafka-ui에 등록해 두었던 9000 포트로 접속하면(localhost:9000) kafka-ui를 통해 클러스터의 상태를 확인할 수 있고, 토픽을 새로 생성하여 메시지를 생성할 수도 있습니다.

