Kubernetes多节点上的Kafka

所以我的目标是以分散的方式build立几个卡夫卡经纪人集群。 但我看不出让经纪人意识到对方的方法。

据我了解,每个经纪人都需要在他们的configuration中有一个单独的ID,如果我从kubernetes启动容器,我不能保证或configuration。

他们还需要有相同的advertised_host?

有什么参数我错过了,需要改变的节点发现彼此?

在Dockerfile的末尾用脚本做这样的configuration是否可行? 和/或共享音量?

我目前正在尝试在香草Kubernetes上使用具有预configuration的zookeeper + kafka组合的spotify / kafka-image。

我的解决scheme是使用IP作为ID :修剪点,你得到一个独特的ID,也可以在容器之外的其他容器。

使用服务,您可以访问多个容器的IP(请参阅我在此处的回答,了解如何执行此操作: 让kubenetes pod相互通信的最佳方法是什么?

所以如果你使用IP作为唯一的ID,你也可以得到他们的ID。 唯一的问题是ID不是连续的或者从0开始,但是动物园pipe理员/卡夫卡似乎并不介意。

编辑1:

跟进关注configurationZookeeper:

每个ZK节点需要知道其他节点。 Kubernetes发现服务了解服务中的节点,所以想法是用ZK节点启动服务

此服务需要在创buildZookeeper窗格的ReplicationController(RC)之前启动。

ZK容器的启动脚本将需要:

  • 等待发现服务用它的节点来填充ZK服务(这需要几秒钟,现在我只是在启动脚本的开头添加一个睡眠10,但更可靠的是你应该寻找服务,至less有3个节点在里面。)
  • 在发现服务中查找构成服务的容器:这是通过查询API来完成的。 KUBERNETES_SERVICE_HOST环境variables在每个容器中都可用。 然后find服务描述的端点

URL="http(s)://$USERNAME:$PASSWORD@${KUBERNETES_SERVICE_HOST/api/v1/namespaces/${NAMESPACE}/endpoints/${SERVICE_NAME}"

除非您更改了NAMESPACE ,否则NAMESPACEdefault ,如果您将您的服务动物园pipe理员命名为SERVICE_NAME ,则SERVICE_NAME将为动物园pipe理员。

在那里你可以看到形成服务的容器的描述,他们的ip在“ip”字段中。 你可以做:

 curl -s $URL | grep '\"ip\"' | awk '{print $2}' | awk -F\" '{print $2}' 

获取服务中的IP列表。 这样,使用上面定义的ID在节点上填充zoo.cfg

您可能需要USERNAMEPASSWORD才能访问Google容器引擎等服务上的端点。 这些需要放在一个秘密卷(见这里的文档: http : //kubernetes.io/v1.0/docs/user-guide/secrets.html )

您还需要在Google Container Engine上使用curl -s --insecure ,除非您经历将CA证书添加到您的Pod的麻烦

基本上将容量添加到容器,并从文件中查找值。 (与文档所说的不同的是,在base64编码时不要将\ n放在用户名或密码的末尾:这会让你的阅读变得更加复杂)

编辑2:

你需要在Kafka节点上做的另一件事是获取IP和主机名,并把它们放在/ etc / hosts文件中。 Kafka似乎需要通过主机名来了解节点,而这些默认情况下并没有在服务节点中设置

编辑3:

经过多次尝试,使用IP作为ID的想法可能不是那么好:这取决于如何configuration存储。 对于像zookeeper,kafka,mongo,hdfs等任何types的分布式服务,您可能需要使用emptyDirtypes的存储,因此它只是在该节点上(挂载远程存储types会破坏发布这些服务的目的!)emptyDir将与同一节点上的数据进行同步,因此使用NODE ID(节点IP)作为ID似乎更符合逻辑,因为在同一节点上重新启动的Pod将具有该数据。 这样可以避免潜在的数据损坏(如果新节点开始在相同的目录中写入,而实际上并不是空的,那么谁知道会发生什么)以及Kafka,如果代理ID发生变化,主题被分配一个broker.id, zookeeper不更新主题broker.id和主题看起来像它是可用的但指向错误的broker.id,这是一个烂摊子。

到目前为止,我还没有find如何获取节点IP,但我认为可以通过查找服务pod名称,然后查找它们所在的节点来查找API。

编辑4

要获取节点IP,您可以从端点API / api / v1 / namespaces / default / endpoints /中获取pod主机名==名称,如上所述。 那么你可以通过/ api / v1 / namespaces / default / pods /

PS:这是从Kubernetes回购的例子中得到启发(rethinkdb的例子在这里: https : //github.com/kubernetes/kubernetes/tree/master/examples/rethinkdb

我用docker-compose做了这个(Kubernetes的区别在于你可以通过你的service.yaml传递ID并且有2个服务):

 kafka1: build: kafka-0.8.1/ ports: - 9092 links: - zookeeper environment: - ID=1 kafka2: build: kafka-0.8.1/ ports: - 9092 links: - zookeeper environment: - ID=2 

configuration:

 broker.id=${ID} port=9092 advertised.host.name=${HOST} advertised.port=9092 num.network.threads=3 num.io.threads=8 socket.send.buffer.bytes=102400 socket.receive.buffer.bytes=102400 socket.request.max.bytes=104857600 log.dirs=/kafka/kafka-logs-${ID} num.partitions=200 num.recovery.threads.per.data.dir=1 log.retention.hours=168 log.segment.bytes=1073741824 log.retention.check.interval.ms=300000 log.cleaner.enable=false zookeeper.connect=${DOCKER_ZOOKEEPER_1_PORT_2181_TCP_ADDR}:${DOCKER_ZOOKEEPER_1_PORT_2181_TCP_PORT} zookeeper.connection.timeout.ms=6000 

SH:

 #!/bin/bash echo "Running config" export HOST=`grep $HOSTNAME /etc/hosts | awk '{print $1}'` export ID=${ID:?} perl -p -i -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : $&/eg' < /broker.template > $KAFKA_HOME/config/server.properties echo "Done" echo "starting kafka with:" echo "$KAFKA_HOME/config/server.properties" echo "" cat $KAFKA_HOME/config/server.properties $KAFKA_HOME/bin/kafka-server-start.sh $KAFKA_HOME/config/server.properties 

这显示在我的search显着,但包含非常过时的信息。 要用更现代的解决scheme来更新,你应该使用一个StatefulSet部署,它将生成一个有整数计数器而不是哈希名字的荚,例如。 卡夫卡控制器-0。

这当然是主机名,所以从这里使用awk提取一个固定的,不变的代理ID是一件简单的事情:

 hostname | awk -F'-' '{print $3}' 

现在卡夫卡最受欢迎的容器有一个经纪人ID命令。