zk: 3.4.9 (3节点)
kubernetes: 1.17.2
容器镜像使用 CentOS7 + zk安装包自行封装.
问题描述
zk的3个节点全部启动, 集群也建起来了, 正常对外提供服务. 但是执行zkServer.sh status查询节点状态异常, 如下
$ ./bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/zookeeper-3.4.9/bin/../conf/zoo.cfg
Error contacting service. It is probably not running
使用jps可以看到zk进程
$ jps
26 QuorumPeerMain
120300 Jps
排查过程
按照参考文章1中所说, 修改bin/zkServer.sh, 查看status子命令的详细过程.
STAT=`"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \ -cp "$CLASSPATH" $JVMFLAGS org.apache.zookeeper.client.FourLetterWordMain \ $clientPortAddress $clientPort srvr 2> /dev/null \ | $GREP Mode`
将上述语句的2> /dev/null以及后面的管道过滤语句移除, 查看srvr指令的输出, 得到如下
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)
at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
Caused by: java.net.BindException: Address already in use
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
at sun.net.httpserver.ServerImpl.<init>(ServerImpl.java:100)
at sun.net.httpserver.HttpServerImpl.<init>(HttpServerImpl.java:50)
at sun.net.httpserver.DefaultHttpServerProvider.createHttpServer(DefaultHttpServerProvider.java:35)
at com.sun.net.httpserver.HttpServer.create(HttpServer.java:130)
at io.prometheus.jmx.shaded.io.prometheus.client.exporter.HTTPServer.<init>(HTTPServer.java:179)
at io.prometheus.jmx.shaded.io.prometheus.jmx.JavaAgent.premain(JavaAgent.java:31) ... 6 more
FATAL ERROR in native method: processing of -javaagent failed
和参考文章1中说的一样, 都是Address already in use, 但是ta没说是哪个端口啊...??
而且zk都正常运行了, 2181/3888这种被占用不是很正常的事情嘛...
下面就是碰运气的过程了, 按照参考文章2提到的dataLogDir目录没有成功创建, 或是myid路径不正确的问题...这些配置不正确能启动成功?
参考文章3提到了防火墙, 嗯...容器里根本没有防火墙. 另外/etc/hosts也没必要, server.X中的地址各节点是可以相互通信的(当然我也试了下, 不出所料??).
解决方法
最终的解决方法是参考文章5, 为了实现在容器环境下对zk容器的监控, 我们使用了jmx_exporter, 于是修改了zkServer.sh中的JVMFLAGS变量.
JVMFLAGS="$JVMFLAGS -javaagent:$JMX_DIR/jmx_prometheus_javaagent-0.15.0.jar=19105:$JMX_DIR/zookeeper.yaml"
将这一行注释掉, 再执行zkServer.sh status, 就可以了.
另外, 除了这个原因, 还有一个原因是, 我们的zoo.cfg配置不标准, 如下
clientPort:2181
server.0:zk-ha-test-busi-kafka-0.zk-ha-test-busi-kafka-svc.zjjpt-zk.svc.cs-hua.hpc:2888:3888
server.1:zk-ha-test-busi-kafka-1.zk-ha-test-busi-kafka-svc.zjjpt-zk.svc.cs-hua.hpc:2888:3888
server.2:zk-ha-test-busi-kafka-2.zk-ha-test-busi-kafka-svc.zjjpt-zk.svc.cs-hua.hpc:2888:3888
dataLogDir:/data/zk-ha-test-busi-kafka-0/log
dataDir:/data/zk-ha-test-busi-kafka-0
## ...省略
用冒号:代替了等号=, zk竟然可以正常运行??.
这样导致在zkServer.sh中在执行status子命令时, 从zoo.cfg中解析clientPort变量会有问题.
clientPort=`$GREP "^[[:space:]]*clientPort[^[:alpha:]]" "$ZOOCFG" | sed -e ‘s/.*=//‘`
后面的sed指令是按=进行切分的, 这样得到的结果为clientPort:2181, 是个非法数值.
修改zoo.cfg的格式后就可以了.