所以我的目标是以分布式方式建立一个由几个kafka经纪人组成的集群。但我看不出让经纪人了解彼此的方法。
据我所知,每个代理在其配置中都需要一个单独的ID,如果我从kubernetes启动容器,我无法保证或配置?
他们还需要有相同的advertised_host吗?
我是否缺少任何需要更改的参数才能让节点相互发现?
使用脚本在Dockerfile的末尾进行这样的配置是否可行?和/或共享卷?
我正在尝试使用spotify / kafka-image进行此操作,该图像具有预先配置的zookeeper + kafka组合,在vanilla Kubernetes上。
答案 0 :(得分:11)
我的解决方案是使用IP作为ID :修剪点数,您将获得一个唯一的ID,该ID也可以在容器外部提供给其他容器。
使用服务,您可以访问多个容器的IP(请参阅我的答案,如何执行此操作: what's the best way to let kubenetes pods communicate with each other?
因此,如果您使用IP作为唯一ID,也可以获取其ID。 唯一的问题是ID不是连续的或从0开始,但是zookeeper / kafka似乎并不介意。
编辑1:
后续问题涉及配置Zookeeper:
每个ZK节点都需要知道其他节点。 Kubernetes发现服务知道服务中的节点,因此我们的想法是使用ZK节点启动服务。
需要在创建Zookeeper pod的ReplicationController(RC)之前启动此服务。
ZK容器的启动脚本需要:
KUBERNETES_SERVICE_HOST
环境变量。
然后,找到服务描述的端点是 URL="http(s)://$USERNAME:$PASSWORD@${KUBERNETES_SERVICE_HOST/api/v1/namespaces/${NAMESPACE}/endpoints/${SERVICE_NAME}"
除非您更改NAMESPACE
default
,否则SERVICE_NAME
如果您命名为服务管理员,则curl -s $URL | grep '\"ip\"' | awk '{print $2}' | awk -F\" '{print $2}'
将成为zookeeper。
您可以获得构成服务的容器的描述,其ip位于“ip”字段中。 你可以这样做:
curl -s --insecure
获取服务中的IP列表。 然后,使用上面定义的ID
填充节点上的zoo.cfg您可能需要 USERNAME 和 PASSWORD 才能访问google容器引擎等服务上的端点。这些需要放在密码卷中(请参阅此处的文档:http://kubernetes.io/v1.0/docs/user-guide/secrets.html)
您还需要在Google容器引擎上使用{{1}},除非您在向容器中添加CA证书时遇到麻烦
基本上将卷添加到容器中,并从文件中查找值。 (与文档所说的相反,当base64编码时,不要将\ n放在用户名或密码的末尾:它只会让你的生活在阅读时变得更复杂)
编辑2:
您需要在Kafka节点上做的另一件事是获取IP和主机名,并将它们放在/ etc / hosts文件中。 Kafka似乎需要通过主机名知道节点,默认情况下这些节点不在服务节点中设置
编辑3:
经过多次试验后,使用IP作为ID的想法可能不会那么好:这取决于您如何配置存储。 对于像zookeeper,kafka,mongo,hdfs这样的任何类型的分布式服务,您可能想要使用emptyDir类型的存储,因此它只是在该节点上(安装远程存储类型会破坏分发这些服务的目的!) emptyDir将与同一节点上的数据进行重新连接,因此使用NODE ID(节点IP)作为ID似乎更合乎逻辑,因为在同一节点上重新启动的pod将具有该数据。 这样可以避免数据的潜在损坏(如果新节点开始在同一个dir中写入,实际上不是空的,谁知道会发生什么),还有Kafka,如果代理ID更改,主题被分配了broker.id, zookeeper没有更新主题broker.id,主题看起来像是可用但是指向错误的broker.id并且它是一团糟。
到目前为止,我还没有找到如何获取节点IP,但我认为可以通过查找服务pod名称然后查找部署它们的节点来查找API。
编辑4
要获取节点IP,您可以从端点API获取pod hostname == name / API / V1 /命名空间/默认/端点/ 如上所述。 然后你可以从pod名称中获取节点IP / API / V1 /命名空间/默认/荚/
PS:这是受Kubernetes回购中的示例启发的(此处为rethinkdb示例:https://github.com/kubernetes/kubernetes/tree/master/examples/rethinkdb
答案 1 :(得分:2)
看看 https://github.com/CloudTrackInc/kubernetes-kafka 它允许在kubernetes中启动Kafka并支持缩放和自动扩展。
答案 2 :(得分:2)
这在我的搜索中突出显示,但包含非常过时的信息。要使用更现代的解决方案进行更新,您应该使用StatefulSet部署,这将生成具有整数计数器而不是名称中的哈希的窗格,例如。卡夫卡控制器-0。
这当然是主机名,所以从那里使用awk提取固定的,不变的代理ID是一件简单的事情:
hostname | awk -F'-' '{print $3}'
最近Kafka最常用的容器有一个代理ID命令。
答案 3 :(得分:1)
我使用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
<强>配置:强>
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