作者:杨冬 欢迎转载,也请保留这段声明。谢谢!
出处:https://andyyoung01.github.io/ 或 http://andyyoung01.16mb.com/
ZooKeeper为分布式应用提供高效、高可用的分布式协调服务,它有三种运行模式:单机模式、伪集群模式和集群模式。本文通过探索ZooKeeper的官方Docker镜像,来看看怎样快速搭建一个ZooKeeper的高可用集群。
Docker容器将应用打包成一个单一的镜像,这对应用程序的部署提供了很大的便利。如果我们以传统的方式部署应用程序,首先需要将应用的依赖环境部署好,如果程序的依赖比较单一,部署时还不至于非常麻烦;但如果应用程序的依赖比较复杂,在部署时就会比较耗时。ZooKeeper依赖于Java,以传统方式部署时,首先应在主机上配置好JAVA运行时,如果通过Docker的方式部署,JAVA运行时已经打包到ZooKeeper的镜像中,我们只需要拉取镜像,然后在启动容器时给定合适的配置信息即可。
使用ZooKeeper的Docker镜像和ZooKeeper编译后的tar包有区别吗?下面就来看看ZooKeeper的Docker镜像是如何构建的。ZooKeeper的官方镜像地址有关于此镜像的一些信息,从页面上得到其Dockerfile的地址,便可以查看镜像的构建过程。整个文件中第27行代码,表明镜像构建时,从ZooKeeper的官方网站上下载了指定版本的tar文件。所以我们得知该镜像是以官方的tar文件为基础,加入了JAVA运行时及一些启动脚本,来控制镜像启动时的行为。镜像构建时加入的启动脚本docker-entrypoint.sh也是比较关键的:
docker-entrypoint.shlink1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #!/bin/bash set -e if [ "$1" = 'zkServer.sh' -a "$(id -u)" = '0' ]; then exec su-exec "$ZOO_USER" "$0" "$@" fi if [ ! -f "$ZOO_CONF_DIR/zoo.cfg" ]; then CONFIG="$ZOO_CONF_DIR/zoo.cfg" echo "clientPort=$ZOO_PORT" >> "$CONFIG" echo "dataDir=$ZOO_DATA_DIR" >> "$CONFIG" echo "dataLogDir=$ZOO_DATA_LOG_DIR" >> "$CONFIG" echo 'tickTime=2000' >> "$CONFIG" echo 'initLimit=5' >> "$CONFIG" echo 'syncLimit=2' >> "$CONFIG" for server in $ZOO_SERVERS; do echo "$server" >> "$CONFIG" done fi if [ ! -f "$ZOO_DATA_DIR/myid" ]; then echo "${ZOO_MY_ID:-1}" > "$ZOO_DATA_DIR/myid" fi exec "$@"
|
从这个脚本文件中得知,如果在启动镜像时没有提供zoo.cfg文件,则该脚本通过提供给docker命令的环境变量ZOO_SERVERS来生成zoo.cfg文件;myid文件也是一样,如果没有提供,则通过传入的ZOO_MY_ID环境变量来生成该文件。所以上面这个启动脚本对于通过Docker成功搭建高可用集群时十分关键的。
下面就开始高可用集群的搭建,集群有3个节点,包括:
centos7-A:192.168.71.167
centos7-B:192.168.71.168
centos7-C:192.168.71.169
首先在三个节点上通过docker pull zookeeper
命令拉取ZooKeeper的最新版本的镜像。然后在三个节点上分别启动docker镜像:
主机A:
1 2 3 4 5 6 7 8
| [yangdong@centos7-A ~]$ docker run -d \ > -e ZOO_MY_ID=1 \ > -e ZOO_SERVERS="server.1=192.168.71.167:2888:3888 server.2=192.168.71.168:2888:3888 server.3=192.168.71.169:2888:3888" \ > --name=zookeeper \ > --net=host \ > --privileged \ > zookeeper a0dc03eaf6fe8569fe37617f3d2ee614fe1e5d2b9b8f911811d8af660541ff6f
|
主机B:
1 2 3 4 5 6 7 8
| [yangdong@centos7-B ~]$ docker run -d \ > -e ZOO_MY_ID=2 \ > -e ZOO_SERVERS="server.1=192.168.71.167:2888:3888 server.2=192.168.71.168:2888:3888 server.3=192.168.71.169:2888:3888" \ > --name=zookeeper \ > --net=host \ > --privileged \ > zookeeper 51370c39cc552a4330b1da6b1071a776332d45203bcbf80cbdc9d9dc56c40077
|
主机C:
1 2 3 4 5 6 7 8
| [yangdong@centos7-C ~]$ docker run -d \ > -e ZOO_MY_ID=3 \ > -e ZOO_SERVERS="server.1=192.168.71.167:2888:3888 server.2=192.168.71.168:2888:3888 server.3=192.168.71.169:2888:3888" \ > --name=zookeeper \ > --net=host \ > --privileged \ > zookeeper 38abcc8ad245707e8e39b24b78e408219907874a5949bc46e904e23f5bd67141
|
上面三个命令需要注意的地方有:通过-e选项指定了ZOO_MY_ID和ZOO_SERVERS的值,在容器启动时根据这两个环境变量的值在容器中生成/data/myid文件和/conf/zoo.cfg文件。如果还有其它更详细的配置信息,想要通过配置文件挂载到容器内部的方式启动,则不需要指定前两个值,即使指定了也没有用处,容器会直接使用配置文件中的配置信息。另外,容器启动时指定了--net=host
和--privileged
选项,使得容器可以使用主机的ip地址和端口进行通信。
下面验证一下集群是否工作正常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| [yangdong@centos7-A ~]$ echo ruok|nc 192.168.71.167 2181 imok[yangdong@centos7-A ~]$ echo ruok|nc 192.168.71.168 2181 imok[yangdong@centos7-A ~]$ echo ruok|nc 192.168.71.169 2181 imok[yangdong@centos7-A ~]$ [yangdong@centos7-A ~]$ echo stat | nc 192.168.71.167 2181 Zookeeper version: 3.4.9-1757313, built on 08/23/2016 06:50 GMT Clients: /192.168.71.167:58366[0](queued=0,recved=1,sent=0) Latency min/avg/max: 0/0/0 Received: 3 Sent: 2 Connections: 1 Outstanding: 0 Zxid: 0x0 Mode: follower Node count: 4 [yangdong@centos7-A ~]$ echo stat | nc 192.168.71.168 2181 Zookeeper version: 3.4.9-1757313, built on 08/23/2016 06:50 GMT Clients: /192.168.71.167:51164[0](queued=0,recved=1,sent=0) Latency min/avg/max: 0/0/0 Received: 1 Sent: 0 Connections: 1 Outstanding: 0 Zxid: 0x100000000 Mode: leader Node count: 4 [yangdong@centos7-A ~]$ echo stat | nc 192.168.71.169 2181 Zookeeper version: 3.4.9-1757313, built on 08/23/2016 06:50 GMT Clients: /192.168.71.167:46106[0](queued=0,recved=1,sent=0) Latency min/avg/max: 0/0/0 Received: 1 Sent: 0 Connections: 1 Outstanding: 0 Zxid: 0x100000000 Mode: follower Node count: 4
|
通过上面的命令可见集群搭建成功,并且有一个节点为leader状态。