使用Docker快速搭建ZooKeeper高可用集群

目录

作者:杨冬 欢迎转载,也请保留这段声明。谢谢!
出处: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.shlink
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
#!/bin/bash
set -e
# Allow the container to be started with `--user`
if [ "$1" = 'zkServer.sh' -a "$(id -u)" = '0' ]; then
exec su-exec "$ZOO_USER" "$0" "$@"
fi
# Generate the config only if it doesn't exist
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
# Write myid only if it doesn't exist
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状态。