로컬 VM에 Docker 및 Kafka 설치 (docker-compose.yml작성)
로컬 VM에 Docker를 설치하고, 그 안에 카프카를 설치해서 콘솔 테스트까지 해보는 과정을 정리했다.
목차
1. Docker 설치
1) yum 패키지 설치
2) 도커 설치
3) 도커 실행
4) docker-compose 설치
2. Docker Hub에서 카프카 및 카프카UI 이미지 내려받기
1) 카프카 이미지 내려받기
2) 주키퍼 이미지 내려받기
3) 카프카 UI 이미지 내려받기
3. docker-compose.yml 설정
1) docker-compose.yml 작성
2) VM에서 포트포워딩 해주기
4. Kafka Cluster 실행
1) docker-compose 실행
2) docker-compose 실행 확인
5. Kafka Console Test
1) Container 내부 쉘 접속
2) Topic 생성
3) Producer 생성
4) Consumer 생성
5) 메시지 생성하여 테스트
1. Docker 설치
1) yum 패키지 설치
yum install -y yum-utils
2) 도커 설치
저장소 설정
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
🔽 너무 오래걸린다면 도커 수동 설치 🔽
두번째로 할 때는, 너무 오래걸려서
sudo curl -L -o /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
명령어로 수동 설치해주었다...
최신 버전의 Docker Engine을 설치
yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
3) 도커 실행
systemctl start docker
# 서버 실행 시 도커 엔진 자동 실행
systemctl enable docker
4) docker-compose 설치
실행하고자 하는 컨테이너들을 묶어서 한번에 실행할 수 있는 docker-compose를 설치
Kafka Cluster를 구성하는 컨테이너를 한번에 실행시킬 수 있고, 컨테이너의 옵션들을 설정/수정하기 쉬워진다고 한다.
curl -SL https://github.com/docker/compose/releases/download/v2.26.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
# 실행 권한 부여
chmod +x /usr/local/bin/docker-compose
# 설치가 완료되었는지 도커 컴포즈 버전 확인
docker-compose -v
https://github.com/docker/compose/releases
잘 설치가 되었다.
2. Docker Hub에서 카프카 및 카프카UI 이미지 내려받기
Docker Hub 홈페이지에서 검색하여 Image를 찾을 수도 있고, docker search zookeeper , docker search kafka 명령어를 입력하여 찾을 수도 있다.
1) 카프카 이미지 내려받기
pulling 수가 가장 많은 bitnami/kafka와 bitnami/zookeeper 를 pull 받는다.
# kafka image pull
docker pull bitnami/kafka
kafka:2.8.1 같이 명령어 뒤에 버전을 붙이지 않으면, 자동으로 최신버전이 pull 된다.
kafka 최신버전 이미지 pull 완료!
2) 주키퍼 이미지 내려받기
# zookeeper image pull
docker pull bitnami/zookeeper
3) 카프카 UI 이미지 내려받기
마찬가지로, 도커허브에서 제일 인기많은 카프카UI 를 내려받는다.
이 UI 가 없으면 모든 카프카 제어는 모바엑스에서 명령어로 실행해야 하기 때문에 불편하다. 필수로 받을 것!
docker pull provectuslabs/kafka-ui
역시 최신버전으로 pull 받기 완료!
3. docker-compose.yml 설정
Kafka Cluster를 한번에 실행하는 docker-compose는 docker-compose.yml에 명시되어 있는 services를 실행시킨다.
docker-compose.yml에 zookeeper와 kafka container를 구성해보자.
(docker-compose.yml 를 어디에 만들어야되나 한참 찾았는데, 그냥 내가 손수 만들면 되는 것이었다... )
서버에서 내가 원하는 위치에 docker-compose.yml 파일을 직접 만들면 된다.
나는 app 디렉토리를 생성하고 docker/kafka 디렉토리 안에 docker-compose.yml 파일을 생성해주었다.
이제 만든 파일을 클릭하면 MobaTextEditor가 열리면서 입력할 수 있게 된다.
docker-compose v2.25.0 이상 버전부터는
docker-compose.yml파일의 최상단에 작성된 version : '3' 이 필요없어졌다고 한다.
(version: '3' 을 썼더니 에러가 났다.. )
version은 삭제해주자.
1) docker-compose.yml 작성
services:
# Zookeeper 1 서비스 설정입니다.
zookeeper1:
image: 'bitnami/zookeeper'
restart: always
container_name: 'zookeeper1'
ports:
- '2181:2181' # 호스트와 컨테이너 간의 포트 포워딩: 호스트의 2181 포트와 컨테이너의 2181 포트 간에 통신이 이루어집니다.
environment:
- ZOO_SERVER_ID=1 # Zookeeper 서버 ID
# 리더 선출 및 쿼럼 통신을 위한 서버 ID, 호스트명 및 포트를 지정한 Zookeeper 앙상블 구성
- ZOO_SERVERS=zookeeper1:2888:3888::1
- ALLOW_ANONYMOUS_LOGIN=yes # 익명 로그인 허용 설정
user: root # 컨테이너 실행 시 사용할 사용자
# Kafka 브로커 1
kafka1:
image: 'bitnami/kafka'
container_name: 'kafka1'
ports:
- '9092:9092' # 호스트 포트와 컨테이너 포트 간의 포트 포워딩 설정: 호스트의 9092 포트와 컨테이너의 9092 포트 간에 통신이 이루어짐
- '8083:8083' # Kafka Connect REST API 포트
environment:
- KAFKA_BROKER_ID=1 # Kafka 브로커 ID
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092 # Kafka 브로커 리스너 설정 (Kafka 내부에서 접속할 정보)
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://192.168.255.255:9092 # 외부에서 접근 가능한 Kafka 브로커 주소
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper1:2181 #ZooKeeper의 주소를 KAFKA_CFG_ZOOKEEPER_CONNECT 환경 변수에 설정
- ALLOW_PLAINTEXT_LISTENER=yes # PLAINTEXT 리스너 허용 설정 (yes : 보안 없이 접속 가능)
- KAFKA_HEAP_OPTS=-Xmx1G -Xms1G # Kafka JVM 힙 메모리 설정
- KAFKA_ENABLE_KRAFT=no # Kafka KRaft 활성화 여부 설정 (no : Zookeeper 사용/ yes : Zookeeper 사용x)
- KAFKA_CFG_OFFSETS_TOPIC_REPLICATION_FACTOR=1 # 오프셋 토픽 복제 계수 설정
depends_on:
- zookeeper1
user: root # 컨테이너 실행 시 사용할 사용자
# Kafka UI
kafka-ui:
image: provectuslabs/kafka-ui
container_name: kafka-ui
ports:
#서버의 8989포트를 도커컨테이너의 8080포트와 연결 (이거 하면 뚫림!!기본이 8080제공인데, 내가 8080은 너무 많이 쓰니까 8089로 일부러 바꾼 설정!)
- "8989:8080" # 호스트 포트와 컨테이너 포트 간의 포트 포워딩 설정: 호스트의 8989 포트와 컨테이너의 8080 포트 간에 통신이 이루어짐
restart: always # 컨테이너 재시작 설정
environment:
- KAFKA_CLUSTERS_0_NAME=auto-driving # Kafka 클러스터 이름 설정
- KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=192.168.255.255:9092 # Kafka 클러스터 부트스트랩 서버 설정
- KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper1:2181
↓ docker-compose.yml 를 작성하며 궁금했던 점들 정리
1. 여기서 9092, 8083, 8989, 2181, 2888, 3888 포트는 무슨 포트야?
->
포트 9092: 카프카 기본 포트
포트 8083: Kafka Connect의 REST API에 대한 기본 포트 (Kafka Connect : Kafka를 데이터베이스, 파일 시스템, 메시지 대기열과 같은 외부 시스템과 연결하기 위한 프레임워크)
포트 2181: ZooKeeper 클라이언트가 ZooKeeper 앙상블에 연결하는 데 사용하는 클라이언트 포트. ZooKeeper와의 클라이언트 통신을 위한 기본 포트.
포트 2888: 리더 선택을 위해 ZooKeeper 앙상블의 ZooKeeper 서버 간 P2P 통신에 사용되는 포트. 각 ZooKeeper 서버는 이 포트에서 앙상블에 있는 다른 서버의 연결을 수신한다.
포트 3888: ZooKeeper 서버에서 리더 선택 알고리즘을 위해 사용하는 포트. 현재 리더가 실패하거나 연결할 수 없는 경우 새 리더를 선출하는 데 사용된다. 각 ZooKeeper 서버는 리더 선택에 참여하기 위해 이 포트를 수신한다.
포트 8989: 카프카 UI 기본포트가 8080인데, 8080은 자주 사용되니, 내가 임의로 바꿔준 포트이다. (docker-compose.yml 에 작성해서 바꿔주었다)
2. 내가 카프카 브로커를 1개말고 compose.yml에서 더 지정해주면 자동 생성이 되는 건가? 이미지를 받았으니까 알아서 여러개 복제해서 쓰는건가?
-> ㅇㅇ
3. 그러면 포트 번호는 내가 저렇게 KAFKA_CFG_LISTENERS=PLAINTEXT://:9094 이런식으로 지정하면 자동으로 포트가 뚫리나? 아니면 내가 무슨 설정해줘야해? 어디서?
-> 카프카 안에 포트 여는 설정은 따로 없고 compose.yml 여기서만 포트 열어주는 설정을 해주면 된다.
추가로 서버에서 방화벽에 해당 포트 열라고 설정하기 + vm에 포트포워딩으로 열어주기 도 해줘야 한다!
4. KAFKA_CFG_LISTENERS와 KAFKA_CFG_ADVERTISED_LISTENERS의 차이가 뭐야?
-> KAFKA_CFG_LISTENERS는 실제 주소이고 카프카 내부에서 접속할 정보이다.
KAFKA_CFG_ADVERTISED_LISTENERS는 외부에서 접속하기 위한 주소이다.
KAFKA_CFG_LISTENERS로 접속하기 전에 한번 거치는 프록시 서버? 또는 로드밸런서같은 느낌이라고 이해했다... !
5. 부트스트랩 서버 설정은 뭐지?
-> 카프카 클러스터의 '주소' 를 '부트스트랩서버'라고 한다고 한다!
2) VM에서 포트포워딩 해주기
내 노트북이 외부 서버가 아닌 로컬 VM 안의 OS(Rocky)를 바라보고 있기 때문에,
명시적으로 포트 포워딩을 해준다.
내 노트북이 외부 서버가 아니기 때문에 인식을 못할 수도 있기 때문이라고 한다...
(진짜 서버로 할 때는 포트 포워딩 안해줘도 된다고 한다..)
그리고 호스트도 내 노트북 IP가 아니라 모든 IP가 접근 가능하도록 0.0.0.0 으로 수정해주었고,
카프카UI 를 접근하는 호스트는 로컬호스트 IP명인 127.0.0.1 로 수정해주었다.
(내 로컬에서만 접근할 것이기 때문에)
서버 방화벽 설정에도 8989, 8083, 9092, 2181, 2888, 3888 포트는 들어와도 된다고 알려줘야겠지??
4. Kafka Cluster 실행
1) docker-compose 실행
docker-compose를 실행시킬 땐 해당 파일이 있는 경로로 이동해서 실행시키거나 파일을 명시해야 한다.
해당 경로로 이동한 경우
docker-compose up -d #d는 로그 없이 실행하는 명령어
그냥 실행할 경우 파일 명시
docker-compose -f /a/b/c/docker-compose.yml up -d
이제 열심히 만든 컴포즈 파일을 실행시켜주자. 카프카 클러스터가 실행될 수 있게!!
나는 카프카 경로에서 아래 명령어를 쳐봤다.
docker-compose up
완전 잘 된다!
2) docker-compose 실행 확인
아래 명령어로 실행 확인 하면, 내가 설정한 카프카1, 주키퍼1, 카프카UI 컨테이너 3개가 잘 실행이 되는 것이 보인다.
docker ps
카프카UI 를 확인해보니 카프카 브로커도 1개가 생성이 된 것을 확인할 수 있다.
5. Kafka Console Test
Kafka에서 제공하는 Console 명령어로 Producer, Subscriber 동작을 확인해보자.
VM SSH Session 2개 띄운 상태에서 진행하자. 하나는 프로듀서용 하나는 컨슈머용.
1) Container 내부 쉘 접속
Kafka 명령어를 입력하기 위해 Container 내부 쉘에 접속하자.
Cluster로 Broker 간 연결되어 있기 때문에 Kafka 컨테이너가 여러개라면 그 중 원하는 아무 컨테이너에서 진행하면 된다.
docker exec -it kafka1 bash
VM 2개 모두 명령어를 입력해서 컨테이너 내부 쉘에 접속하자.
Kafka에서 제공하는 기능(스크립트로 제공하는 듯)을 아래 경로로 들어가서 확인할 수 있다.
ls /opt/bitnami/kafka/bin/
해당 스크립트는 환경변수로 설정되어 있어서 /opt/bitnami/kafka/bin/ 경로 입력없이 실행시킬 수 있다.
2) Topic 생성
kafka-topics.sh --bootstrap-server kafka1:9092 --create --topic test-kafka
- bootstrap-server: Kafka Broker 주소 명시
- topic: topic 명
⇒ topic을 생성하지 않아도 Producer가 메시지를 전송하거나 Consumer가 메시지 대기하면 자동으로 생성된다.
나는 아래 명령어를 쳤다.
kafka1:9092 의 카프카 브로커에 test-kafka 라는 토픽을 만들겠다 라는 뜻의 명령어다.
토픽이 만들어졌다.
카프카UI 에서도 토픽이 생성된 것을 확인할 수 있다.
이제, 한 쪽은 Producer 를 생성하고 ,다른 한 쪽은 Consumer 를 생성하여 테스트 해보자.
3) Producer 생성
kafka-console-producer.sh --bootstrap-server kafka1:9092 --topic test-kafka
이 명령을 실행하면 Kafka 콘솔 생성자가 메시지 생성을 시작할 수 있도록 준비한다.
메시지를 입력할 수 있는 프롬프트가 표시된다.
4) Consumer 생성
kafka-console-consumer.sh --bootstrap-server kafka1:9092 --topic test-kafka
컨슈머도 생성이 되었다.
카프카UI 에도 확인할 수 있다.
5) 메시지 생성하여 테스트
Consumer를 실행시켰으면, Producer를 실행시킨 VM에서 > 메시지 입력창이 나타난 것이 확인되면 메시지를 입력합니다.
메시지를 입력했다.
메시지가 Kafka 클러스터의 지정된 Kafka (지금은 test-kafka)로 전송된다.
카프카 UI에서 확인을 해보자.
Topics > 토픽이름 클릭 > Messages 로 들어가면
내가 날린 2개의 메시지를 확인할 수 있다!
메시지가 카프카에 잘 전달이 되었다. 이제 실제 프로젝트에 카프카를 적용해서 사용하면 된다.
카프카의 설정에 따라서 성능이 많이 달라지는 것 같은데,
토픽과 컨슈머, 컨슈머 그룹 등 세세한 설정을 잘 숙지하고 적용해서 앞으로 작업할 프로젝트에 최적화 된 카프카 설정을 적용해 보아야겠다! 😊