Docker部署Zookeeper集群
CentOS8.1在线安装Docker
# 1、更新yum包(可不更新)
yum update
# 2、安装需要的软件包, yum-util 提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
yum install -y yum-utils device-mapper-persistent-data lvm2
# 3、设置yum源(在国内镜像下载docker)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 4、安装docker
yum install -y docker-ce docker-ce-cli containerd.io
安装到第4步骤时,可能会遇到如下错误:
package docker-ce-3:20.10.6-3.el8.x86_64 requires containerd.io >= 1.4.1, but none of the providers can be installed
这是由于CentOS8.1的yum默认安装了 containerd.io 的1.2.0-3版本,不支持新版docker,于是我按照网上指定版本的安装了 containerd.io 1.4.1版本:
yum install https://download.docker.com/linux/centos/8/x86_64/stable/Packages/containerd.io-1.4.3-3.1.el8.x86_64.rpm
在安装 containerd.io 1.4.1时,可能遇到这种错误:
problem with installed package podman-1.4.2-5.module_el8.1.0+237+63e26edc.x86_64 package podman-1.4.2-5.module_el8.1.0+237+63e26edc.x86_64 requires runc, but none of the providers can be installed
这是由于CentOS8.1携带了podman,podman是与Docker有相似功能的开源容器项目(未来可期),鱼和熊掌,卸载:
dnf remove -y podman
卸载podman后重新安装containerd.io 1.4.1,然后再继续步骤4。
podman对比docker: podman VS docker
CentOS8.1离线安装Docker
待补充
安装Zookeeper
虚拟机集群IP
192.168.10.3
192.168.10.4
192.168.10.5
拉取镜像
docker pull zookeeper:3.4.13
官方版本3.4.13镜像是精简版,并且携带了实用镜像。
docker hub地址:zookeeper docker环境配置详细描述
创建docker网络
docker network create --driver bridge --subnet 100.100.1.0/24 --gateway 100.100.1.1 curr
–net curr 选择创建的curr网络,如果同一宿主机内的不同容器选择了同一网络,那么,这些容器就在同一个子网中。
–subnet 子网
–gateway 子网网关
–driver 网络模式
启动容器
执行命令
docker run --privileged=true -d --net curr -v /curr/zookeeper/logs:/logs -v /curr/zookeeper/conf:/conf -v /curr/zookeeper/data:/data -v /curr/zookeeper/datalog:/datalog --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -e ZOO_LOG4J_PROP="INFO,ROLLINGFILE" -e ZOO_MY_ID="0" -e ZOO_SERVERS="server.0=0.0.0.0:2888:3888 server.1=192.168.10.4:2888:3888 server.2=192.168.10.5:2888:3888" zookeeper:3.4.13;
格式分析
–privileged=true 让该容器拥有宿主机的权限
-d 容器后台运行
-e 设置容器的全局变量
-e ZOO_MY_ID="0" zookeeper的myid
-e ZOO_LOG4J_PROP="INFO,ROLLINGFILE" 启用zookeeper运行日志
-e ZOO_SERVERS="server.0=192.168.10.3:2888:3888 ..." 配置zoo.cfg里的servers.myid集群
-p 宿主机端口:容器内端口(端口映射)
-p 2181:2181 -p 2888:2888 -p 3888:3888
# 2181:对cline端提供服务
# 3888:选举leader使用
# 2888:集群内机器通讯使用(Leader监听此端口)
-v 挂载(通过挂载,可以在宿主机直接操作容器挂载地址处的文件,比如 zoo.cfg、zookeeper.log、myid、log4j.properties)。注意:挂载时,若容器内地址处存在文件,会被删除。
-v /curr/zookeeper/conf:/conf 宿主机地址:容器内地址
官方镜像生成容器初始化
1、生成容器内环境变量
ZOO_CONF_DIR=/conf
ZOO_DATA_DIR=/data
ZOO_DATA_LOG_DIR=/datalog
ZOO_LOG_DIR=/logs
ZOO_TICK_TIME=2000
ZOO_INIT_LIMIT=5
ZOO_SYNC_LIMIT=2
ZOO_AUTOPURGE_PURGEINTERVAL=0
ZOO_AUTOPURGE_SNAPRETAINCOUNT=3
ZOO_MAX_CLIENT_CNXNS=60
2、将zookeeper的conf文件夹下所有文件,拷贝到ZOO_CONF_DIR目录下
3、若ZOO_CONF_DIR路径下未找到zoo.cfg,会根据所有环境变量生成zoo.cfg,执行命令里-e ZOO_SERVERS=“…”也会添加到zoo.cfg
4、若ZOO_DATA_DIR路径下未找到myid文件,会根据-e ZOO_MY_ID=“0” 生成myid文件。
生成日志
要生成zookeeper运行时日志,需要满足两个条件:
1、第一次生成容器时,在命令行里添加 -e ZOO_LOG4J_PROP=“INFO,ROLLINGFILE”
2、在conf文件夹里,添加log4j.properties 文件(使用自带log4j.properties就可以)
集群部署
192.168.10.3
docker run --privileged=true -d --net curr -v /curr/zookeeper/logs:/logs -v /curr/zookeeper/conf:/conf -v /curr/zookeeper/data:/data -v /curr/zookeeper/datalog:/datalog --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -e ZOO_LOG4J_PROP="INFO,ROLLINGFILE" -e ZOO_MY_ID="0" -e ZOO_SERVERS="server.0=0.0.0.0:2888:3888 server.1=192.168.10.4:2888:3888 server.2=192.168.10.5:2888:3888" zookeeper:3.4.13;
192.168.10.4
docker run --privileged=true -d --net curr -v /curr/zookeeper/logs:/logs -v /curr/zookeeper/conf:/conf -v /curr/zookeeper/data:/data -v /curr/zookeeper/datalog:/datalog --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -e ZOO_LOG4J_PROP="INFO,ROLLINGFILE" -e ZOO_MY_ID="1" -e ZOO_SERVERS="server.0=192.168.10.3:2888:3888 server.1=0.0.0.0:2888:3888 server.2=192.168.10.5:2888:3888" zookeeper:3.4.13;
192.168.10.5
docker run --privileged=true -d --net curr -v /curr/zookeeper/logs:/logs -v /curr/zookeeper/conf:/conf -v /curr/zookeeper/data:/data -v /curr/zookeeper/datalog:/datalog --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -e ZOO_LOG4J_PROP="INFO,ROLLINGFILE" -e ZOO_MY_ID="2" -e ZOO_SERVERS="server.0=192.168.10.3:2888:3888 server.1=192.168.10.4:2888:3888 server.2=0.0.0.0:2888:3888" zookeeper:3.4.13;
注意保持myid和对应server.x=0.0.0.0:2181:2888:3888这种格式
部署过程遇到的问题
1、当所有容器启动后,查看日志,发现不同宿主机间的各个容器,只有2181端口互通,而3888选举端口全部互不相通,查看日志文件,发现如下ERROR 日志:
2021-05-25 15:59:04,136 [myid:0] - INFO [ListenerThread:QuorumCnxManager$Listener@736] - My election bind port: /192.168.10.3:3888
2021-05-25 15:59:04,137 [myid:0] - ERROR [/192.168.10.3:3888:QuorumCnxManager$Listener@760] - Exception while listening
java.net.BindException: Address not available (Bind failed)
at java.net.PlainSocketImpl.socketBind(Native Method)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.bind(ServerSocket.java:329)
at org.apache.zookeeper.server.quorum.QuorumCnxManager$Listener.run(QuorumCnxManager.java:739)
引起原因(个人理解):在配置集群ip时,全部使用了宿主机IP,比如当myid =0,设置server.0=192.168.10.3:2888:3888 server.1=192.168.10.4:2888:3888 server.2=192.168.10.5:2888:3888,如此设置,在没有使用的docker容器的虚拟机的上,没有问题。
但是在zookeeper存储于容器内,zookeeper绑定选举ip到192.168.10.3:3888,因为zookeeper绑定的是网卡ip,而容器内的网卡ip并不是192.168.10.3,而是在100.100.1.0/24子网下分配的ip。
解决方法:所有zookeeper配置同一设置为 server.0=0.0.0.0:2888:3888 server.1=192.168.10.4:2888:3888 server.2=192.168.10.5:2888:3888这种格式。
感谢大佬的文章:zookeeper集群无法正确启动
2、启动过程中,产生的WARN 日志:
2021-05-26 07:08:48,319 [myid:2] - WARN [RecvWorker:1:QuorumCnxManager$RecvWorker@1028] - Interrupting SendWorker
2021-05-26 07:08:48,319 [myid:2] - WARN [SendWorker:1:QuorumCnxManager$SendWorker@941] - Interrupted while waiting for message on queue
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:2014)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2088)
at java.util.concurrent.ArrayBlockingQueue.poll(ArrayBlockingQueue.java:418)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.pollSendQueue(QuorumCnxManager.java:1094)
at org.apache.zookeeper.server.quorum.QuorumCnxManager.access$700(QuorumCnxManager.java:74)
at org.apache.zookeeper.server.quorum.QuorumCnxManager$SendWorker.run(QuorumCnxManager.java:929)
引起原因:
如果是刚启动zookeeper报出这个错误,然后不再产生,这是是正常现象。是由于有的节点启动,而有的节点还没有启动,这段时间已经启动的节点就会去努力寻找没有启动的节点,就会报出这样的错误。
报错解决:
如果启动很长时间之后还在报错,修改每个节点的zoo.cfg文件中的相对应的server.x=0.0.0.0:2888:3888
修改完成后重启zookeeper,报错消失。
参考:
感谢
[1]: https://hub.docker.com/_/zookeeper
[2]: https://www.itdaan.com/tw/68e45d699d6c7c9bef64733521a9bd74
[3]: https://blog.csdn.net/u014284000/article/details/74508963