Infra/Kafka, MQTT

로컬 VM에 Docker 및 Kafka 설치 (docker-compose.yml작성)

Nellie Kim 2024. 4. 22. 17:06
728x90

로컬 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

 

Releases · docker/compose

Define and run multi-container applications with Docker - docker/compose

github.com

 

잘 설치가 되었다. 

 

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개의 메시지를 확인할 수 있다!

 

 

 

메시지가 카프카에 잘 전달이 되었다. 이제 실제 프로젝트에 카프카를 적용해서 사용하면 된다.

 

카프카의 설정에 따라서 성능이 많이 달라지는 것 같은데,

토픽과 컨슈머, 컨슈머 그룹 등 세세한 설정을 잘 숙지하고 적용해서 앞으로 작업할 프로젝트에 최적화 된 카프카 설정을 적용해 보아야겠다! 😊