使用 Docker 一步搞定 ZooKeeper 集群的搭建

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.sh link
#!/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:

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

主机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

主机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

上面三个命令需要注意的地方有:通过-e选项指定了ZOO_MY_ID和ZOO_SERVERS的值,在容器启动时根据这两个环境变量的值在容器中生成/data/myid文件和/conf/zoo.cfg文件。如果还有其它更详细的配置信息,想要通过配置文件挂载到容器内部的方式启动,则不需要指定前两个值,即使指定了也没有用处,容器会直接使用配置文件中的配置信息。另外,容器启动时指定了--net=host 和 --privileged 选项,使得容器可以使用主机的ip地址和端口进行通信。

下面验证一下集群是否工作正常:

[yangdong@centos7-A ~]$ echoruok|nc 192.168.71.167 2181
imok[yangdong@centos7-A ~]$ echoruok|nc 192.168.71.168 2181
imok[yangdong@centos7-A ~]$ echoruok|nc 192.168.71.169 2181
imok[yangdong@centos7-A ~]$
[yangdong@centos7-A ~]$ echostat| 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 ~]$ echostat| 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 ~]$ echostat| 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状态。

阅读更多
个人分类: docker zookeeper
上一篇hbase大规模数据写入的优化历程
下一篇docker容器中搭建kafka集群环境
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭