在docker swarm上构建一个多节点Kafka集群

时间:2016-05-25 05:10:08

标签: docker apache-kafka docker-swarm

我找到了Kafka的这个码头图像

https://hub.docker.com/r/spotify/kafka/

我可以使用链接

中记录的命令轻松创建一个docker容器
docker run -p 2181:2181 -p 9092:9092 --env ADVERTISED_HOST=`boot2docker ip` --env ADVERTISED_PORT=9092 spotify/kafka

这很好。但我想配置一个在docker swarm上运行的“多个”节点Kafka集群。

我该怎么做?

4 个答案:

答案 0 :(得分:7)

编辑28/11/2017:

Kafka将listener.security.protocol.map添加到他们的config。这允许您根据您是在群集内部还是在群集外部来设置不同的侦听器地址和协议,并阻止Kafka对docker中发生的任何负载平衡或ip转换感到困惑。 Wurstmeister has a working docker image和示例compose file here。我尝试了一段时间,将一些docker机器节点设置为swarm,它似乎有效。

虽然我只是将Kafka图像附加到覆盖网络并运行Kafka控制台命令,但我现在想要与它进行交互。

希望有所帮助

下面的旧东西

我一直在尝试使用docker swarm模式的docker 1.12

创建节点

docker-machine create -d virtualbox  master
docker-machine create -d virtualbox  slave
master_config=$(docker-machine config master | tr -d '\"')
slave_config=$(docker-machine config slave | tr -d '\"')
master_ip=$(docker-machine ip master)
docker $master_config swarm init --advertise-addr $master_ip --listen-addr $master_ip:2377
worker_token=$(docker $master_config swarm join-token worker -q)
docker $slave_config swarm join --token $worker_token  $master_ip:2377
eval $(docker-machine env master)

创建zookeeper服务

docker service create --name zookeeper \
    --constraint 'node.role == manager' \
    -p 2181:2181 \
    wurstmeister/zookeeper

创建kafka服务

docker service create --name kafka \
    --mode global \
    -e 'KAFKA_PORT=9092' \
    -e 'KAFKA_ADVERTISED_PORT=9092' \
    -e 'KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092' \
    -e 'KAFKA_ZOOKEEPER_CONNECT=tasks.zookeeper:2181' \
    -e "HOSTNAME_COMMAND=ip r | awk '{ ip[\$3] = \$NF } END { print ( ip[\"eth0\"] ) }'" \
    --publish '9092:9092' \
    wurstmeister/kafka

虽然由于某种原因,这只能在入口或用户定义的覆盖网络中工作,如果您尝试通过其中一台客户机连接到Kafka,连接将会中断。

更改广告宣传的IP不会让事情变得更好......

docker service create --name kafka \
    --mode global \
    -e 'KAFKA_PORT=9092' \
    -e 'KAFKA_ADVERTISED_PORT=9092' \
    -e 'KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092' \
    -e 'KAFKA_ZOOKEEPER_CONNECT=tasks.zookeeper:2181' \
    -e 'KAFKA_LOG_DIRS=/kafka/kafka-logs' \
    -e "HOSTNAME_COMMAND=curl 192.168.99.1:5000" \
    --publish '9092:9092' \
    wurstmeister/kafka

我认为docker中新的网状网络和负载均衡可能会干扰Kafka连接的一些方式....

获取主机容器我有一个本地运行的烧瓶应用程序,我卷曲

from flask import Flask
from flask import request

app = Flask(__name__)

@app.route('/')
def hello_world():
    return request.remote_addr

答案 1 :(得分:2)

之前的方法提出了一些问题:

  1. 如何指定zookeeper节点的ID?
  2. 如何指定kafka节点和zookeeper节点的ID?
  3. #kafka configs echo "broker.id=${ID} advertised.host.name=${NAME} zookeeper.connect=${ZOOKEEPERS}" >> /opt/kafka/config/server.properties

    所有内容都应该可以在覆盖网络中解析。

    此外,在问题Cannot create a Kafka service and publish ports due to rout mesh network中,有评论指出不使用ingress网络。

    我认为最好的选择是使用docker compose with swarm来指定您的服务。我将用一个例子来编辑答案。

答案 2 :(得分:1)

在server.properties中设置broker.id = -1,以允许kafka自动生成代理ID。 Swarm模式很有用。

答案 3 :(得分:1)

需要考虑两个问题:网络和存储。

由于Kafka是有状态服务,因此在计算出cloud native storage之前,建议使用全局部署模式。也就是说,每个满足约束的swarm节点都有一个kafka容器。

另一个建议是对发布的端口使用host模式。

正确设置播发的侦听器选项也很重要,这样每个kafka经纪人都知道它在哪个主机上运行。使用swarm服务模板自动提供真实的主机名。

还要确保发布的端口与目标端口不同。

  kafka:
    image: debezium/kafka:0.8
    volumes:
      - ./kafka:/kafka/data
    environment:
      - ZOOKEEPER_CONNECT=zookeeper:2181
      - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true
      - KAFKA_MAX_MESSAGE_BYTES=20000000
      - KAFKA_MESSAGE_MAX_BYTES=20000000
      - KAFKA_CLEANUP_POLICY=compact
      - LISTENERS=PLAINTEXT://:9092
      - BROKER_ID=-1
      - ADVERTISED_LISTENERS=PLAINTEXT://{{.Node.Hostname}}:11092
    depends_on:
      - zookeeper
    deploy:
      mode: global
    ports:
      - target: 9092
        published: 11092
        protocol: tcp
        mode: host
    networks:
      - kafka

我现在无法解释所有选项,但它的配置是有效的。