您的位置:首页 > 运维架构 > Docker

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

2017-02-10 13:26 851 查看
作者:杨冬 欢迎转载,也请保留这段声明。谢谢!

出处: 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.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状态。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: