公司产品有K8S版和 Docker Swarm版,kafka和zookeeper在同一个node,两个容器的数据目录都是映射出来的,但偏偏 Docker 版节点重启后 kafka 一直起不来,必须手工配置 broker.id 和 meta.properties 中的 broker.id 为新的才可以解决问题,或者删除 kafka 数据目录也能解决。这是错误日志:
ERROR Error while creating ephemeral at /brokers/ids/0, node already exists and owner '72067757872119809' does not match current session '72067836689711106'
这个问题折腾了两三天,还以为是自己做的 kafka 镜像有问题还专门改成了 bitnami/kafka 镜像,放 swarm service 环境依然不行,单独用 docker stack rm mykafka 来关闭则发现kafka服务器输出了关闭报错日志:Connection to node 1 (feekafka/10.0.2.17:19092) could not be established. Broker may not be available…… 致kafka无法正确关闭。
网上查资料尝试了很多方式都无法做到自动化,毕竟产品要给客户用的,客户可不会去手工敲打命令解决的。不过最终还是解决了,下面直接说思路。
思路:zookeeper 容器一起来,立即起一个 zookeeper-clean-brokers 容器作为客户端连到 zookeeper 服务器上,由于在同一个 swarm 因此连接是畅通的,接着客户端上执行 deleteall /brokers
命令删除 zookeeper 服务器上的 znode brokers,清除后再运行 kafka,此时kafka就可以起来了,即使服务器突然断电都不影响 kafka的正常起来了。
下面是相关核心代码:
version: '3.2' services: feezookeeper-cleanbrokers: image: zookeeper-feesec command: /bin/sh -c "/apache-zookeeper-3.5.9-bin/bin/zkCli.sh -server feezookeeper:2181 deleteall /brokers" networks: - feenet deploy: restart_policy: condition: none placement: constraints: - node.role == ${NODE_ROLE} networks: feenet: external: name: feepolicy_feenet
上面的代码 command 处是关键,它执行了一个 zkCli.sh 客户端脚本,连接成功后会自动执行 deleteall /brokers 命令来删除服务器上的 broker znode,也可以执行其他命令,比如 ls /,这会列出zk服务器上的所有 znode。