对此我的解决方案是使用 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 发现服务知道 Service 中的节点,因此想法是使用 ZK 节点启动 Service。
此服务需要在创建 Zookeeper pod 的 ReplicationController (RC) 之前启动。
ZK 容器的启动脚本需要:
- 等待发现服务用它的节点填充 ZK 服务(这需要几秒钟,现在我只是在我的启动脚本的开头添加了一个 sleep 10 但更可靠的是你应该寻找服务其中至少有 3 个节点。)
- 在发现服务中查找构成服务的容器:
这是通过查询 API 来完成的。
KUBERNETES_SERVICE_HOST 环境变量在每个容器中都可用。
查找服务描述的端点是
URL="http(s)://$USERNAME:$PASSWORD@${KUBERNETES_SERVICE_HOST/api/v1/namespaces/${NAMESPACE}/endpoints/${SERVICE_NAME}"
其中NAMESPACE 是default,除非您更改它,如果您将服务命名为zookeeper,SERVICE_NAME 将是zookeeper。
你会得到构成服务的容器的描述,它们的 ip 在“ip”字段中。
你可以这样做:
curl -s $URL | grep '\"ip\"' | awk '{print $2}' | awk -F\" '{print $2}'
获取服务中的 IP 列表。
这样,使用上面定义的 ID 在节点上填充 zoo.cfg
您可能需要 USERNAME 和 PASSWORD 才能到达 google 容器引擎等服务的端点。这些需要放入 Secret 卷中(请参阅此处的文档: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 可能不是那么好:这取决于您如何配置存储。
对于任何类型的分布式服务,如 zookeeper、kafka、mongo、hdfs,您可能想要使用 emptyDir 类型的存储,所以它只是在该节点上(安装远程存储类型违背了分发这些服务的目的!)
emptyDir 会在同一个节点上重新加载数据,所以使用 NODE ID(节点 IP)作为 ID 似乎更符合逻辑,因为这样在同一个节点上重启的 pod 就会有数据。
这避免了数据的潜在损坏(如果一个新节点开始在同一个实际上不是空的目录中写入,谁知道会发生什么)以及 Kafka,如果代理 id 更改,主题被分配一个 broker.id, zookeeper 不更新主题 broker.id 并且主题看起来可用但指向错误的 broker.id 并且一团糟。
到目前为止,我还没有找到如何获取节点 IP,但我认为可以通过查找服务 pod 名称和部署它们的节点来在 API 中查找。
编辑 4
要获取节点 IP,可以从端点 API 获取 pod hostname == name
/api/v1/命名空间/默认/端点/
如上所述。
然后您可以从 pod 名称中获取节点 IP
/api/v1/namespaces/default/pods/
PS:这是受 Kubernetes 存储库中示例的启发(此处为 rethinkdb 示例:https://github.com/kubernetes/kubernetes/tree/master/examples/rethinkdb