문제 발생
기존에는 개발의 편의성을 위해 GCP에 띄워놓은 Kafka를 통해 테스트를 했지만 서버를 띄우지 않았을 때는 어쩔 수 없이 로컬에서 해야 하기 때문에 로컬의 개발 편의성을 조금이라도 가져보고자 Docker를 사용하기로 했다. 사실 윈도우상에서 직접 Zookeeper, Kafka, Kafka Connect를 실행하면 문제가 많아서라는 이유도 있다. 어쨌든 Docker로 옮겨보고자 했으나 문제가 몇 가지 발생했다... 문제는 다음과 같다.
- 컨테이너 간 통신
- 호스트 머신에서 컨테이너 내의 Kafka 접근
- Docker 컨테이너와 호스트 머신 DB 연결
이거 말고도 자잘한 문제가 있었지만 위의 세 가지가 가장 큰 문제였다.
컨테이너 간 통신 및 컨테이너 내 Kafka 접근 해결하기
Docker의 컨테이너는 독립된 공간이기 때문에 컨테이너끼리 통신을 하려면 추가적인 작업이 필요하다. 나는 이전에 Docker Compose 설정을 해놓은 yaml 파일이 있었기에 이걸 사용했다. 그런데 그냥 가져다 사용하니 문제가 발생했다. 클라우드상에서는 잘 작동하던데 로컬에서는 안 되는 것이다. 보통은 반대 상황에서 문제가 많이 발생한다...
version: '2'
services:
zookeeper:
image: confluentinc/cp-zookeeper:latest
container_name: zookeeper
hostname: zookeeper
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: 2181
networks:
my-network:
ipv4_address: 172.18.0.100
kafka:
image: confluentinc/cp-kafka:latest
container_name: kafka
hostname: kafka
ports:
- "9092:9092"
- "9093:9093"
environment:
KAFKA_ADVERTISED_HOST_NAME: 172.18.0.101
KAFKA_LISTENERS: INSIDE://kafka:9092, OUTSIDE://kafka:9093
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092, OUTSIDE://localhost:9093
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT, OUTSIDE:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- zookeeper
networks:
my-network:
ipv4_address: 172.18.0.101
connect:
image: ness727/my-custom-kafka-connect:latest
container_name: connect
hostname: connect
ports:
- "8083:8083"
depends_on:
- kafka
- zookeeper
environment:
CONNECT_BOOTSTRAP_SERVERS: kafka:9092
CONNECT_REST_PORT: 8083
CONNECT_GROUP_ID: "quickstart-avro"
CONNECT_CONFIG_STORAGE_TOPIC: "quickstart-avro-config"
CONNECT_OFFSET_STORAGE_TOPIC: "quickstart-avro-offsets"
CONNECT_STATUS_STORAGE_TOPIC: "quickstart-avro-status"
CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: 1
CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: 1
CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: 1
CONNECT_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
CONNECT_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
CONNECT_INTERNAL_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
CONNECT_INTERNAL_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
CONNECT_REST_ADVERTISED_HOST_NAME: "connect"
CONNECT_LOG4J_ROOT_LOGLEVEL: WARN
CONNECT_PLUGIN_PATH: "/usr/share/java"
CONNECT_ZOOKEEPER_CONNECT: "zookeeper:2181"
networks:
my-network:
ipv4_address: 172.18.0.102
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
my-network:
external: true
name: delibird-network
로컬 dev용으로 새로 만든 Docker Compose 파일이다. 기존의 내용과 달라진 부분은 Kafka와 Kafka Connect 설정 부분이다. 먼저 Kafka부터 살펴보자.
Kafka 설정

Kafka broker 설정이 이전과 바뀐 부분은 여기만 보면 된다. 기존에는 kafka:9092 이렇게 호스트와 포트만 설정되어 있었지만 이렇게만 하면 호스트 머신 개발 어플리케이션에서 Kafka를 인식하지 못한다. 그렇기 때문에 호스트 머신에서 접속하는 부분과 내부적으로 통신하는 부분을 나눠 설정해야 한다.
https://taaewoo.tistory.com/59
[Kafka] Docker로 Kafka 구성 시 Host machine과 통신하기 위한 listener 설정 방법
Kafka Publish, Subscribe 모델 구조로 이루어진 분산 메세징 시스템 관련 글 [Spark] Spark structured streaming으로 Kafka topic 받기 #1 - Kafka 클러스터 구성하기 [Spark] Spark structured streaming으로 Kafka topic 받기 #2 - S
taaewoo.tistory.com
위 블로그에서 많이 도움을 받았다.
그리고 새로 배운 부분은 외부와 연결되는 포트를 9092가 아닌 9093 같이 달리 하는 것인데 이 부분은 HTTP 포트 80를 포트포워딩하는 경우를 생각하면 될 것 같다. 이렇게 해야 보안상 좋다고 한다.
Docker 컨테이너와 호스트 머신 DB 연결 해결하기
여기서 조금 헤맸다. 그 이유는 클라우드 상에서는 아예 따로 GCP에서 제공하는 SQL 서비스를 이용하던 것이 있어서 해당 주소만 적어주면 됐기 때문이다. 그런데 localhost는 외부로 나가는 통신이 아니기 때문에 조금 다르게 접근해야 한다.
extra_hosts:
- "host.docker.internal:host-gateway"

일단 위의 Docker Compose 설정 파일에서 Kafka Connect 부분을 보면 위와 같은 부분이 있다. 이 부분이 이전과 다른 부분인데, 새로 추가된 부분이다. 이 설정을 해놓고 호스트 머신의 localhost로 요청하는 설정을 추가로 해주어야 한다.
{
"name": "delibird-sink-connect",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector",
"connection.url": "jdbc:mysql://host.docker.internal:3306/delibird",
"connection.user": "유저ID",
"connection.password": "비밀번호",
"auto.create": "true",
"auto.evolve": "true",
"delete.enabled": "false",
"tasks.max": "1",
"topics": "order_products"
}
}
기존 같았으면 http://localhost:3306 여기로 요청을 보내야 하겠지만 이렇게 설정하면 안 된다. Postman으로 위 설정을 한다고 하면 요청을 보내는 것은 호스트 머신이지만 실제로 설정이 반영되고 작동하는 곳은 컨테이너 내의 Kafka Connect이다. 그렇기 때문에 컨테이너 내에서 호스트 머신으로 DB 요청을 보내야 하지만 컨테이너의 localhost는 컨테이너 내부에 있기 때문에 호스트 머신의 DB로 요청이 가지 않는 것이다.
localhost -> host.docker.internal
로 바꿔서 작성해야 한다. 이렇게 하면 Docker에서 호스트 머신의 localhost로 연결시켜 준다.
{
"name": "product-source-connect",
"config": {
"connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector",
"connection.url": "jdbc:mysql://host.docker.internal:3306/delibird",
"connection.user": "유저ID",
"connection.password": "비밀번호",
"mode": "incrementing",
"incrementing.column.name": "id",
"table.whitelist": "delibird.order_products",
"topic.prefix": "source_",
"tasks.max": "1"
}
}
그리고 source connect도 동일하게 경로를 변경해주어야 한다.
보통은 여기까지 설정했으면 잘 작동될 것이지만 만약 아직도 해결이 안 된다면 다음 몇 가지를 확인해 보아야 한다.
- 오타가 없는지 <- 제일 중요!!
- DB 유저 정보가 정확한지
- DB 포트 번호 확인
여기서 제일 중요한 부분은 오타가 없는지 확인을 꼭 해봐야 한다는 점이다. 나는 토픽명에 오타가 있어서 이거 때문에 몇 시간이나 날렸다;; 오타를 잘 확인하도록 하자...
'공부 > Kafka' 카테고리의 다른 글
| [Kafka] Confluent Kafka 실행 및 Connect 사용하기 (0) | 2024.07.04 |
|---|---|
| [Kafka Connect] Kafka Connect Source DB 반영 안 되는 문제 해결하기 (0) | 2024.05.28 |
| [Kafka Connect] Kafka Connect Sink DB에 저장이 안 될 때 (0) | 2024.05.27 |
| [Kafka Connect] Docker로 Kafka Connect 사용하기 (0) | 2024.05.26 |