在Docker Swarm上构建多节点Kafka集群

11

我找到了这个Kafka的docker镜像

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个回答

7

编辑于2017年11月28日:

Kafka在他们的配置文件中添加了listener.security.protocol.map。这允许您根据您是否在集群内部或外部设置不同的侦听器地址和协议,并防止Kafka受到Docker中发生的任何负载平衡或IP转换的困扰。Wurstmeister有一个可用的Docker镜像和示例组合文件在这里。我以前尝试过使用一些Docker机器节点作为Swarm,它似乎可以工作。

但实际上,我现在只需要将Kafka映像附加到覆盖网络并在需要与其交互时运行Kafka控制台命令。

希望这能帮助到你。


以下是旧内容

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

创建节点

docker-machine create -d virtualbox  master
docker-machine create -d virtualbox  worker
master_config=$(docker-machine config master | tr -d '\"')
worker_config=$(docker-machine config worker | 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 $worker_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中的新Mesh网络和负载均衡可能会影响Kafka连接......

为了获取主机容器,我有一个本地运行的Flask应用程序,可以通过curl访问。

from flask import Flask
from flask import request

app = Flask(__name__)

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

当我使用以上命令运行kafka和zookeeper时,kafka进程失败,并报告它无法识别主机zookeeper或tasks.zookeeper。你知道我做错了什么吗? - Arshad Ansari
抱歉,我通过添加缺失的覆盖网络来修复了它。需要创建一个新的覆盖网络,并使用--network选项将该新网络添加到上面显示的服务命令中。 - Arshad Ansari
哎呀,这是老掉牙的了。Kafka已经添加了一些协议以使其正常工作,并且现在Docker通常更好了。只需按照这个家伙的文档和教程进行操作: wurstmeister/kafkadocker-compose-swarm.yml - Richard Mathie

3

之前的方法引发了一些问题:

  1. 如何指定zookeeper节点的ID?
  2. 如何指定kafka节点和zookeeper节点的ID?

#kafka配置 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来指定您的服务。我将编辑答案并给出一个示例。


1
嗨,Fabio,你有示例或链接吗? - Raf

2
有两个问题需要考虑:网络和存储。
由于Kafka是有状态的服务,在找到云原生存储之前,建议使用全局部署模式。也就是说,每个满足约束条件的Swarm节点都将有一个Kafka容器。
另一个建议是对发布的端口使用主机模式。
还要确保正确设置广告侦听器选项,以便每个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

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

1

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


2
当您替换损坏的代理节点时,使用自动生成的代理ID可能会出现问题,因为它们不会占据与离开的节点相同的位置,因此无法获取损坏代理“留下的”分区。 - Frank de Jonge

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