오늘은 지난 번 글에 이어서 본격적으로 도커로 카프카 환경을 구축해보겠습니다!
저는 일단 주키퍼를 사용하지 않고 Kraft를 활용해서 브로커들을 관리할 예정이기에
카프카는 3.5.1 버전을 활용하고 주키퍼는 별도로 사용하지 않겠습니다.
1. 네트워크 구성
networks:
data_network: # 카프카 클러스터 간의 내부 통신에 사용되는 네트워크
먼저 data_natwork 라는 네트워크를 정의하였습니다. 이 네트워크는 카프카 클러스터 내의 다양한 서비스 간의 내부 통신을 위해 사용될 예정이며 이는 도커 내부 네트워크를 사용함으로써 서비스들이 서로를 효율적이게 찾을 수 있도록 해줍니다!
2. 볼륨 구성
# 볼륨 구성
volumes:
DataVolume00: # 로컬 드라이버를 사용하는 볼륨
driver: local
DataVolume01:
driver: local
DataVolume02:
driver: local
볼륨 구성은 DataVolume0n이라는 n개의 볼륨을 정의하였습니다. 볼륨들은 카프카가 데이터를 저장하는데 사용될 예정이며, local 드라이버 설정을 통하여 각각의 컨테이너의 데이터 저장 공간이 유지 될 수 있도록 하였습니다. 컨테이너가 재시작되거나 업데이트 되어도 데이터가 유실되지 않고 보존되도록 하는 설정입니다. 만약 특정 볼륨을 특정 경로에 지정하고 싶다면 이 부분을 수정하면 됩니다!
3. 브로커 구성
# 서비스 구성
services:
# 카프카 브로커 00 설정
Broker00:
image: bitnami/kafka:3.5.1-debian-11-r44 # 카프카 이미지 버전 선택
restart: unless-stopped # 재시작 정책
container_name: BrokerContainer00 # 컨테이너 명명
ports:
- '10000:9094' # 포트 바인딩
environment: # 환경변수 설정
- KAFKA_CFG_BROKER_ID=0
- KAFKA_CFG_NODE_ID=0
- KAFKA_KRAFT_CLUSTER_ID=c3dpbGlnaHQtNGZjMy05MTk5LTllMGY
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@Broker00:9093,1@Broker01:9093,2@Broker02:9093
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://Broker00:9092,EXTERNAL://127.0.0.1:10000
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
networks:
- data_network
volumes:
- "DataVolume00:/bitnami/kafka"
이미지 - 이미지는 bitnami/kafka:3.5.1을 사용하였습니다.
재시작 정책 - 'unless-stopped' 재시작 정책의 경우 수동으로 멈추지 않는 한 자동으로 재시작 될 수 있도록 하였습니다.
컨테이너 이름 - 'BrokerContainer<n>' 브로커의 이름은 브로커 컨테이너에 브로커당 구분 번호를 붙였습니다.
포트 바인딩 - 9094 브로커 포트와 외부 포트 10000을 바인딩하여 외부에서도 접근시 해당 포트를 사용 할 수 있도록 하였습니다.
카프카 브로커 환경 변수
해당 브로커 설정은 다른 브로커 서버들과 동일하게 설정할 예정으로 작성하였습니다.
#### 1. `KAFKA_CFG_BROKER_ID=0`
- **설명**: 각 카프카 브로커는 클러스터 내에서 고유한 ID를 가집니다. `BROKER_ID`는 이 브로커의 식별자로 클러스터 내에서 다른 브로커와 구별하기 위해 사용됩니다.
#### 2. `KAFKA_CFG_NODE_ID=0`
- **설명**: `NODE_ID`도 브로커의 고유 식별자로 사용되며 특히 새로운 Kafka 버전에서 `BROKER_ID`와 동일한 역할을 합니다. 일관성을 위해 이 값을 `BROKER_ID`와 동일하게 설정합니다.
#### 3. `KAFKA_KRAFT_CLUSTER_ID= Base64로 인코딩된 UUID`
- **설명**: Kafka를 KRaft 모드(클러스터 구성 관리를 위한 Zookeeper-free 모드)로 운영할 때 필요한 클러스터 ID입니다. 이는 클러스터의 고유 식별자 역할을 합니다.
#### 4. `KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@Broker00:9093,1@Broker01:9093,2@Broker02:9093`
- **설명**: 클러스터 내의 컨트롤러 노드에 대한 투표자 설정입니다. 각 투표자는 `id@host:port` 형식을 사용하여 지정됩니다. 이 설정은 클러스터의 리더 선출과 결정을 위해 중요합니다.
#### 5. `ALLOW_PLAINTEXT_LISTENER=yes`
- **설명**: 이 변수는 평문(암호화되지 않은) 리스너를 허용할지 여부를 결정합니다. 보안이 중요하지 않은 개발 또는 테스트 환경에서 유용합니다.
#### 6. `KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true`
- **설명**: 이 설정을 활성화하면 존재하지 않는 토픽에 대한 첫 번째 메시지가 수신될 때 카프카가 자동으로 토픽을 생성합니다.
#### 7. `KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094`
- **설명**: 카프카 브로커가 수신 대기할 리스너 목록입니다. 여기서 `PLAINTEXT`, `CONTROLLER`, `EXTERNAL`은 각각 다른 용도로 사용되는 리스너 유형을 나타냅니다.
#### 8. `KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://Broker00:9092,EXTERNAL://127.0.0.1:10000`
- **설명**: 클라이언트가 연결을 시도할 때 카프카 브로커가 광고하는 리스너 주소입니다. 이는 클라이언트가 브로커에 접속하기 위해 사용하는 주소입니다.
크래프트 ( Kraft )
Kraft 모드를 사용하는 브로커 환경에선 KAFKA_KRAFT_CLUSTER_ID를 설정하여 같이 구성할 브로커들을 하나로 묶어줘야합니다.
카프카 크래프트 모드 (KRaft)는 Apache Kafka의 새로운 운영 모드로, Kafka의 Zookeeper 의존성을 제거하기 위해 도입된 합의 프로토콜 입니다. KRaft란 Kafka 클러스터의 메타데이터 관리를 위해 ZooKeeper를 사용하는 기존 방식에서 Kafka자체에서 메타데이터 관리할 수 있도록 통합하여 사용할 수 있도록 만들어진 기능으로 Kafka 2.8 버전 이상부터 사용 할 수 있습니다.
KAFKA_KRAFT_CLUSTER_ID의 경우 Base64로 인코딩 된 UUID를 사용한다고 합니다. 너무 짧은 경우 이슈가 발생할 수 있고 단순 uuid 생성으로도 적합하지는 않다고 합니다.
참조 : https://github.com/bitnami/containers/issues/29027
4. Kafka Ui 구성
WebUI:
image: provectuslabs/kafka-ui:latest
restart: always
container_name: KafkaWebUI
ports:
- '8080:8080'
environment:
- KAFKA_CLUSTERS_0_NAME=MyLocalKafkaCluster
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=Broker00:9092,Broker01:9092,Broker02:9092
- DYNAMIC_CONFIG_ENABLED=true
- KAFKA_CLUSTERS_0_AUDIT_TOPICAUDITENABLED=true
- KAFKA_CLUSTERS_0_AUDIT_CONSOLEAUDITENABLED=true
depends_on:
- Broker00
- Broker01
- Broker02
networks:
- data_network
저는 Kafka UI를 활용하여 카프카 클러스터 직접보고 관리할 예정이라 컴포즈에 해당 환경도 추가하였습니다.
Kafka UI는 카프카 클러스터의 토픽, 파티션, 메세지 등을 시각적으로 관리할 수 있게해주는 웹 기반 인터페이스입니다!
주요 설정만 좀 알아보도록 하겠습니다.
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=Broker00:9092,Broker01:9092,Broker02:9092
kafka ui가 연동할 broker의 주소목록입니다.
DYNAMIC_CONFIG_ENABLED=true
Kafka ui의 동적 구성 기능을 활성화 합니다. 이것은 처음 설정할때 전달한 클러스터 정보 말고 동적으로 클러스터를 추가할 수 있도록 하는 설정입니다.
- Configure new cluster
이 페이지를 통하여 클러스터를 동적으로 추가 할 수 있습니다!
KAFKA_CLUSTERS_0_AUDIT_TOPICAUDITENABLED=true
위 설정은 카프카 클러스터 내의 토픽관련 이벤트의 로그를 기록하는 옵션입니다. 이러한 이벤트를 카프카 ui를 통해 추적가능 합니다.
KAFKA_CLUSTERS_0_AUDIT_CONSOLEAUDITENABLED=true
위 설정은 카프카 ui를 통한 조작을 로깅합니다.
위 두가지 설정에 대한 내용은 가이드 문서에서는 못찾았습니다.
https://docs.kafka-ui.provectus.io/configuration/misc-configuration-properties
Misc configuration properties - UI for Apache Kafka
Setting log level (trace, debug, info, warn, error). Default: debug
docs.kafka-ui.provectus.io
하지만 해당 깃헙에 가면 사용되고 있고 코드상에도 해당 부분의 설정을 사용하는 부분이 존재합니다.
https://github.com/provectus/kafka-ui/tree/53a6553765a806eda9905c43bfcfe09da6812035
GitHub - provectus/kafka-ui: Open-Source Web UI for Apache Kafka Management
Open-Source Web UI for Apache Kafka Management. Contribute to provectus/kafka-ui development by creating an account on GitHub.
github.com
depends_on:
- Broker00
- Broker01
- Broker02
depends_on 설정은 브로커 서버 3개로 지정하여 브로커 서버가 실행되면 카프카 ui가 실행되도록 하였습니다.
자 이제 모든 구성을 하나의 Compose 파일로 작성하고 실행해보도록 하겠습니다!
5. 도커 컴포즈 파일 전체
networks:
data_network: # 카프카 클러스터 간의 내부 통신에 사용되는 네트워크
# 볼륨 구성
volumes:
DataVolume00: # 로컬 드라이버를 사용하는 볼륨
driver: local
DataVolume01:
driver: local
DataVolume02:
driver: local
# 서비스 구성
services:
# 카프카 브로커 00 설정
Broker00:
image: bitnami/kafka:3.5.1-debian-11-r44 # 카프카 이미지 버전 선택
restart: unless-stopped # 재시작 정책
container_name: BrokerContainer00 # 컨테이너 명명
ports:
- '10000:9094' # 포트 바인딩
environment: # 환경변수 설정
- KAFKA_CFG_BROKER_ID=0
- KAFKA_CFG_NODE_ID=0
- KAFKA_KRAFT_CLUSTER_ID=c3dpbGlnaHQtNGZjMy05MTk5LTllMGY
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@Broker00:9093,1@Broker01:9093,2@Broker02:9093
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://Broker00:9092,EXTERNAL://127.0.0.1:10000
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
networks:
- data_network
volumes:
- "DataVolume00:/bitnami/kafka"
# 카프카 브로커 01 및 02는 Broker00과 유사하게 설정되었으나 포트, 컨테이너 이름, 브로커 ID 및 노드 ID에 차이가 있음
Broker01:
image: bitnami/kafka:3.5.1-debian-11-r44
restart: always
container_name: BrokerContainer01
ports:
- '10001:9094'
environment:
- KAFKA_CFG_BROKER_ID=1
- KAFKA_CFG_NODE_ID=1
- KAFKA_KRAFT_CLUSTER_ID=c3dpbGlnaHQtNGZjMy05MTk5LTllMGY
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@Broker00:9093,1@Broker01:9093,2@Broker02:9093
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://Broker01:9092,EXTERNAL://127.0.0.1:10001
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
networks:
- data_network
volumes:
- "DataVolume01:/bitnami/kafka"
Broker02:
image: bitnami/kafka:3.5.1-debian-11-r44
restart: always
container_name: BrokerContainer02
ports:
- '10002:9094'
environment:
- KAFKA_CFG_BROKER_ID=2
- KAFKA_CFG_NODE_ID=2
- KAFKA_KRAFT_CLUSTER_ID=c3dpbGlnaHQtNGZjMy05MTk5LTllMGY
- KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@Broker00:9093,1@Broker01:9093,2@Broker02:9093
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://Broker02:9092,EXTERNAL://127.0.0.1:10002
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3
- KAFKA_CFG_TRANSACTION_STATE_LOG_MIN_ISR=2
- KAFKA_CFG_PROCESS_ROLES=controller,broker
- KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
networks:
- data_network
volumes:
- "DataVolume02:/bitnami/kafka"
WebUI:
image: provectuslabs/kafka-ui:latest
restart: always
container_name: KafkaWebUI
ports:
- '8080:8080'
environment:
- KAFKA_CLUSTERS_0_NAME=MyLocalKafkaCluster
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=Broker00:9092,Broker01:9092,Broker02:9092
- DYNAMIC_CONFIG_ENABLED=true
- KAFKA_CLUSTERS_0_AUDIT_TOPICAUDITENABLED=true
- KAFKA_CLUSTERS_0_AUDIT_CONSOLEAUDITENABLED=true
depends_on:
- Broker00
- Broker01
- Broker02
networks:
- data_network
6. Compose Build , 컴포즈 빌드!
다음 명령어로 빌드합니다!
docker-compose up --build
KafkaWebUi 의 depend on 설정으로 인해 broker 서버가 다 준비되면 실행되기에 연결에 문제 없이 실행될 것입니다.
제가 사전에 compose.yml 내에 Kafka UI 구성에 작성한 클러스터입니다.
정상적으로 구동 되었다면 3개의 브로커 서버의 현재 상태가 보일 것 입니다. 토픽을 생성해보록 하겠습니다!
Add a Topic을 클릭합시다!
토픽을 생성할 수 있습니다!! 간단하게 테스트 토픽을 생성하도록 하겠습니다.
짜잔~ ! 토픽이 생성되었고 우측 상단 Produce Message를 클릭하시면 테스트 메세지를 전송할 수 있습니다!
Hello World를 전송해보겠습니다!
전송에 성공한 것을 볼 수 있습니다! 여기까지 하였으면 완료입니다!
오늘은 이렇게 docker로 카프카와 카프카 ui 환경을 구축해보았습니다!
이제 개발을 위하여 테스트 환경이 구축되었으니 원하시는 서비스를 구축하고 테스트하시면 좋을 것 같습니다!
카프카를 구축하면서 몇가지는 내용들은 별도의 글로 더 자세히 써야겠다는 생각이 들었습니다.
해당 내용들은 추후 글로 작성하도록 하겠습니다!
읽어주셔서 감사합니다!
'Kafka' 카테고리의 다른 글
1탄 카프카란? kafka 란? (0) | 2024.02.20 |
---|