我的 Kafka Docker 容器无法连接到我的 Zookeeper Docker 容器。

9

我想要在一台Ubuntu服务器上同时使用confluent/kafkaconfluent/zookeeper

我正在使用以下配置:

docker run -e ZOOKEEPER_CLIENT_PORT=2181 --name zookeeper confluent/zookeeper

docker run --name kafka -e KAFKA_ADVERTISED_HOST_NAME=kafka -e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 -e KAFKA_CREATE_TOPICS=testtopic:1:1 confluent/kafka

但是这会导致错误:无法连接到zookeeper:2181。

我希望将其他容器连接到zookeeper:2181,并通过kafka:kafka:9092访问kafka,该怎么做?


1
这两个容器已经被弃用。请使用 confluentinc/kafka 和 Zookeeper。另外,请使用 Docker compose,并阅读此博客 https://rmoff.net/2018/08/02/kafka-listeners-explained/。 - OneCricketeer
感谢 @cricket_007 - 我一开始使用的是 Docker Compose,但镜像开始出现问题(上周还好好的),所以我一直在按照上面的方式运行镜像来帮助调试失败的容器。我将尝试使用上述命令,使用 confluentinc/kafkaconfluentinc/zookeeper - fuzzi
4个回答

16

有多种方法可以解决这个问题。但在我们深入了解之前,您需要了解您的方法存在两个问题:

  • 当您使用 docker run 时,zookeeper 主机无法访问,因为每个容器都在不同的网络隔离中运行
  • kafka 可能会启动并尝试连接到 zookeeper,但此时 zookeeper 还没有准备好

解决网络问题

有很多方法可以解决这些问题

使用 --net=host 来在主机网络上同时运行两个容器

使用 docker network create <name> 命令创建一个新的网络,并在启动两个容器时使用 --net=<name>

或者您可以将 kafka 容器运行在 zookeeper 容器的网络中。

在启动 kafka 容器时使用 --net=container:zookeeper,这将确保 zookeeper 主机可访问。这不是推荐的方法,除非你有一些强烈的理由要这么做。因为一旦 zookeeper 容器关闭,kafka 容器的网络也会关闭。但为了便于理解,我在这里列出了这个选项

解决启动竞争问题

您可以在启动 zookeeperkafka 之间留出一定的时间间隔,以确保在 kafka 启动时 zookeeper 已经运行

另一个选择是在 docker run 命令中使用 --restart=on-failure 标志。这将确保容器在失败时重新启动,并尝试重新连接到 zookeeper,希望此时 zookeeper 已经启动。

相比于使用 docker run,我更喜欢使用 docker-compose 来运行这样的关联容器。您可以通过创建一个简单的 docker-compose.yml 文件,然后使用 docker-compose up 命令来实现。

version: "3.4"
services:
  zookeeper:
    image: confluent/zookeeper
    environment:
      - ZOOKEEPER_CLIENT_PORT=2181
  kafka:
    image: confluent/kafka
    environment:
      - KAFKA_ADVERTISED_HOST_NAME=kafka
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
      - KAFKA_CREATE_TOPICS=testtopic:1:1
    depends_on:
      - zookeeper
    restart: on-failure

docker run -e ZOOKEEPER_CLIENT_PORT=2181 --name zookeeper confluent/zookeeper 后面跟着 docker run --name kafka -e KAFKA_ADVERTISED_HOST_NAME=kafka -e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 -e KAFKA_CREATE_TOPICS=testtopic:1:1 --net=container:zookeeper confluent/kafka 没有起作用,并显示了 "无法连接到 zookeeper:2181"。 - fuzzi
你有延迟后再做吗? - Tarun Lalwani
是的,我执行了第一个命令,它显示:"INFO 绑定到端口 0.0.0.0/0.0.0.0:2181",然后等待了2分钟,检查它仍在运行,然后执行了第二个命令。 - fuzzi
请尝试使用 localhost:2181 - Tarun Lalwani
谢谢,这个可以用!不过我想让它在zookeeper中工作。也许有另一个环境变量可以与zookeeper一起使用来设置advertised_name。 - fuzzi
最好使用docker-compose而不是仅使用docker - Tarun Lalwani

3

我正在使用Mac系统,这完全没问题。因为在Mac中“host”网络无法正常工作,所以我只需创建一个名为kafka_net的网络,并将容器放在那里。

version: "3.4"
services:
  zookeeper:
    image: confluent/zookeeper
    environment:
      - ZOOKEEPER_CLIENT_PORT=2181
    networks:
      - kafka_net
  kafka:
    image: confluent/kafka
    environment:
      - KAFKA_ADVERTISED_HOST_NAME=kafka
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
    depends_on:
      - zookeeper
    networks:
      - kafka_net
    restart: on-failure
networks:
  kafka_net:
    driver: "bridge"

为了确保一切顺利:

登录到Zookeeper容器,然后执行以下操作:

zookeeper-shell localhost:2181 => You should see something like 'Welcome to ZooKeeper!' after all the big chunk of text

登录到Kafka容器中,然后执行以下操作:

kafka-topics --zookeeper zookeeper:2181 --list # empty list
kafka-topics --zookeeper zookeeper:2181 --create --topic first_topic --replication-factor 1 --partitions 1
kafka-topics --zookeeper zookeeper:2181 --list # you will see the first_topic
kafka-console-producer --broker-list localhost:9092 --topic first_topic # type some text and ctrl + c
kafka-console-consumer --bootstrap-server localhost:9092 --zookeeper zookeeper:2181 --topic first_topic --from-beginning # you will see the stuff you typed first_topic

如果仍然存在问题,可以查看官方示例。 https://github.com/confluentinc/cp-docker-images/tree/5.2.2-post/examples 如果还有问题,请发布问题,我会提供帮助。

1

Docker会在隔离网络中启动容器,称为默认桥接,除非您明确指定网络。

您可以通过不同的方式成功,以下是两种最简单的方法:

  1. Put containers into same user-defined bridge network

    # create net
    docker network create foo
    docker run --network=foo -e ZOOKEEPER_CLIENT_PORT=2181 --name zookeeper confluent/zookeeper
    docker run --network=foo --name kafka -e KAFKA_ADVERTISED_HOST_NAME=kafka -e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 -e KAFKA_CREATE_TOPICS=testtopic:1:1 confluent/kafka
    
  2. Expose ports and connect through localhost

    docker run -p 2181:2181 -e ZOOKEEPER_CLIENT_PORT=2181 --name zookeeper confluent/zookeeper
    docker run --name kafka -e KAFKA_ADVERTISED_HOST_NAME=kafka -e KAFKA_ZOOKEEPER_CONNECT=host.docker.internal:2181 -e KAFKA_CREATE_TOPICS=testtopic:1:1 confluent/kafka
    
注意:在第二种方法中,您应该使用 host.docker.internal 作为主机名,并公开(发布)端口 2181 给第一个容器,以便在本地主机上可用。

我尝试了第一个选项,但在运行第二行时,它抛出了“org.I0Itec.zkclient.exception.ZkException: Unable to connect to zookeeper:2181”的异常。 - fuzzi
我尝试了第二个选项,但我也收到了无法连接到zookeeper:2181的错误信息。 - fuzzi
KAFKA_CREATE_TOPICS 对于这些容器无效,而且在这里您不需要 Docker 主机 DNS 名称。 - OneCricketeer

0
 docker network create kafka-zookeeper

等待网络创建完成

 docker run -it -d --network=kafka-zookeeper --name zookeeper zookeeper

等待ZooKeeper启动并运行

 docker run -it -d --network=kafka-zookeeper --name kafka -e KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181 --restart=on-failure -e ALLOW_PLAINTEXT_LISTENER=yes -e KAFKA_CFG_LISTENERS=PLAINTEXT://:9092 -e KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 bitnami/kafka

Kafka 应该可以正常连接。

这些正在以 -d 分离模式运行,因此您需要前往 Docker 桌面应用程序查看每个容器的日志。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接