Docker 在无法连接到 kafka 的 Azure 容器实例上使用 zookeeper、kafka 和 python 脚本编写多容器

Docker compose multi-container with zookeeper, kafka and python script on Azure container instances not able to connect to kafka

我正在尝试获得一个 zookeeper/kafka 非集群设置,以便能够使用 python 脚本与容器通信。我希望能够 运行 一个 zookeeper/kafka 容器和 2 个或更多带有 python 脚本的容器与 zookeeper/kafka 通信,所有 运行 都在容器或容器中Azure 上的群组。

为了测试这一点,我创建了下面的 docker 容器组,将 zookeeper 和 kafka 作为 2 个服务,第三个服务启动一个简单的 python 脚本来生成稳定的消息速度到卡夫卡主题。我使用的docker-compose.yml如下:

version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    container_name: zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - 22181:2181
    networks:
      - my-network

  kafka:
    image: confluentinc/cp-kafka:latest
    container_name: kafka
    depends_on:
      - zookeeper
    ports:
      - 29092:29092
    networks:
      - my-network
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
  kafka_producer:
    build: ../kafka_producer
    image: annabotkafka.azurecr.io/kafka_producer:v1
    container_name: kafka_producer
    depends_on:
      - kafka
    volumes:
      - .:/usr/src/kafka_producer
    networks:
      - my-network
    environment:
      KAFKA_SERVERS: kafka:9092
networks:
  my-network:
    driver: bridge

kafka_producer.py脚本如下:

import os
from time import sleep
import json
from confluent_kafka import Producer

def acked(err, msg):
    if err is not None:
        print("Failed to deliver message: {0}: {1}"
              .format(msg.value(), err.str()))
    else:
        print("Message produced: {0}".format(msg.value()))

# Function to send a status message out on the status topic
def send_status(producer,counter):
    msg = {'counter':counter}
    json_dump = json.dumps(msg)
    producer.produce("counter", json_dump.encode('utf-8'), callback=acked)
    producer.poll()

# Define kafkaProducer to push messages to the status topic
producer = Producer({'bootstrap.servers': 'kafka:9092'})

for j in range(9999):
    print("Iteration", j)
    send_status(producer, j)
    sleep(2)

当我 'docker-compose up' 在我的 Ubuntu 20.04 开发机器上执行此操作时,我得到了预期的行为:向 kafka 生产者发送的消息流。

在我 'docker-compuse push' 将其添加到 Azure 容器实例并使用图像在 Azure 中创建容器后,kafka_producer 脚本似乎无法再连接到位于 [=38 的 kafka 代理=].

这些是容器组启动后的日志:

Iteration 0
%3|1629363616.468|FAIL|rdkafka#producer-1| [thrd:kafka:9092/bootstrap]: kafka:9092/bootstrap: Failed to resolve 'kafka:9092': Name or service not known (after 25ms in state CONNECT)
%3|1629363618.465|FAIL|rdkafka#producer-1| [thrd:kafka:9092/bootstrap]: kafka:9092/bootstrap: Failed to resolve 'kafka:9092': Name or service not known (after 22ms in state CONNECT, 1 identical error(s) suppressed)
Iteration 1
Iteration 2

我知道容器组位于同一个网络子网和单个主机上,所以我希望它能像在本地开发机器上一样运行。

我的下一步将是使用不同的 python 脚本创建单独的容器,我希望在该容器组中与 kafka 进行通信。将生产者脚本放在同一个容器组中并不是我的长期期望,但我相信这种更简单的设置应该可行。

对我哪里出错有什么建议吗?

来自 Azure 文档

Within a container group, container instances can reach each other via localhost on any port, even if those ports aren't exposed externally on the group's IP address or from the container.

这听起来像是容器正在使用主机网络,而不是像您在 Compose 中设置的那样 Docker 网桥(您的代码可以正常工作)

因此,您应该联系 localhost:29092

如果您实际上不需要消息持久性,那么我建议您在脚本之间通过 HTTP、gRPC 或 Zeromq 使用套接字,而不是使用 Kafka 容器