使用 Docker 构建 Zookeeper 服务

1. 前言

在我们使用 Zookeeper 来进行各种功能的开发时,为了节约开发成本,我们通常使用的是 Zookeeper 的单机模式或者伪集群模式,但是在测试环境和生成环境中,我们需要的就是高可用高性能的 Zookeeper 服务来对我们的应用提供支持了。

那么如何搭建一个高可用高性能的 Zookeeper 服务集群呢?其实在 Zookeeper 集群模式这一节的内容中我们就搭建过集群数量为 3 的 Zookeeper 服务。在本节内容中,我们会使用另外一种更高效的方式来搭建我们的 Zookeeper 集群,这种方式就是使用容器引擎 Docker 来进行 Zookeeper 集群的构建。接下来我们来简单的了解一下 Docker,然后再使用 Docker 来安装 Zookeeper 。

2. Docker 介绍

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 系统或 Windows 系统上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。

首先我们来简单了解一下 Docker 的组成。在 Docker 中有 4 个基本组成:

  • Docker Image 镜像
  • Docker Container 容器
  • Docker Client 客户端
  • Docker Daemon 守护进程

Docker 和 Zookeeper 同样是 C/S 的架构,Docker 服务端通过 Docker Daemon 守护进程来维持长时间的运行,Docker Client 客户端通过 CLI 的 API 来对 Docker 服务端的 Docker Image 镜像和 Docker Container 容器来进行操作。我们通过 API 去 Docker Hub 的官网拉取 Image 镜像,然后通过 Image 镜像来创建 Container 容器。

在我们使用 Docker 来搭建 Zookeeper 集群的时候,也同样的先去 Docker Hub 的官网拉取 Zookeeper 的镜像,然后通过这个 Zookeeper 镜像就能创建 Zookeeper 的容器实例了。这个 Zookeeper 的容器实例就是一个 Zookeeper 服务,我们就可以通过 Zookeeper 客户端来进行连接和操作了。

简单了介绍了 Docker ,接下来我们介绍如何安装 Docker。

3. Docker 安装

在不同的操作系统中都可以安装 Docker ,本节内容中只演示 Ubuntu 环境下的 Docker 安装。本次安装演示的 Ubuntu 版本为 Ubuntu 20.04.1 LTS 。

  • apt 更换国内源

在安装应用之前,我们需要把 apt 更换为国内源,这里我们选择阿里云的 mirros.aliyun.com

# 备份 apt 源列表文件
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
# 更换源为 mirros.aliyun.com
sudo sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
# 更新源
sudo apt-get clean
sudo apt-get update

更换完毕后,我们还需要安装 apt 的一些工具,如 https,curl 等。

  • 安装 apt 依赖包
sudo apt-get -y install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
  • 获取 GPG 密钥证书

我们这里使用阿里云的镜像来获取 GPG 密钥:

curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

获取成功会返回 OK ,我们使用 apt-key finger 命令查看:

apt-key finger
# 输出密钥信息
/etc/apt/trusted.gpg
--------------------
pub   rsa4096 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]

密钥添加成功后,我们就可以开始后续的安装了。

  • 添加 Docker 源

为了更快速的安装 Docker,这里我们添加阿里云的 Docker 源,首先我们先使用 lsb_release -a 命令获取当前系统的 Codename:

lsb_release -a
# 输出系统信息
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.1 LTS
Release:        20.04
Codename:       focal

本系统的 Codename 也就是版本代码为 focal,我们在添加 Docker 源的时候就会使用这个版本:

# 添加 docker-ce 源,系统为 ubuntu,系统版本为 focal, stable 为 docker 稳定版。
sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu focal stable"

执行完毕后,我们需要更新 apt 源:

sudo apt-get update
  • Docker 安装

更新完源后,我们就可以开始安装 Docker 组件了:

sudo apt-get install docker-ce docker-ce-cli containerd.io

执行这一行命令需要一点时间,稍等片刻。完成后我们就可以来查看 Docker 是否安装成功了。

  • 查看 Docker 版本

使用 docker -v 来查看 Docker 版本:

docker -v
# 输出 docker 版本信息
Docker version 19.03.13, build 4484c46d9d

看到版本信息输出就说明我们的 Docker 源安装成功了。

Tips: 如果安装失败,需要注意系统的版本和添加的 Docker 源是否能使用。

安装成功后,我们来添加 Docker Image 镜像源。

  • 添加 Docker Image 镜像源

使用阿里云的 Docker Image 镜像源,需要登录阿里云官网开启 容器镜像服务

图片描述

添加 Docker Image 镜像源为阿里云镜像,这里同学们使用自己账号的加速器地址即可:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"]
}
EOF

添加完毕后,我们就可以启动我们的 Docker 服务了。

  • 启动 Docker
service docker start
# 输出启动信息
* Starting Docker: docker  

启动完成,接下来我们进行测试。

  • Docker 测试

执行测试命令:

docker run hello-world

输出:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete 
Digest: sha256:4cf9c47f86df71d48364001ede3a4fcd85ae80ce02ebad74156906caff5378bc
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

我们看到这段信息就说明,我们的 Docker 测试成功了。

那么接下来,我们就可以使用 Docker 来安装 Zookeeper 服务。

4. Docker 安装 Zookeeper

  • 查询镜像

我们可以去 Docker Hub 的官网查看 Zookeeper 的镜像:https://hub.docker.com/_/zookeeper

也可以使用 search 命令来查询 Zookeeper 镜像:

# 查询 zookeeper 镜像
docker search zookeeper

执行这条命令会输出很多 zookeeper 镜像,这里我们可以看到第一条就是官方的 zookeeper 镜像。

NAME		DESCRIPTION								STARS	OFFICIAL	AUTOMATED
zookeeper	Apache ZooKeeper is an open-source...	936		[OK]                
  • 拉取镜像

接下来我们开始拉取 Zookeeper 镜像:

# 拉取 zookeeper 镜像,默认是 latest
docker pull zookeeper
# 选择版本拉取就在后面跟上版本信息
docker pull zookeeper:3.6

这里我们选择 latest 版的镜像,执行 docker pull zookeeper 后开始拉取镜像:

Using default tag: latest
latest: Pulling from library/zookeeper
d121f8d1c412: Pull complete 
75deccc0fc24: Pull complete 
690f480f5f48: Pull complete 
b20f9556d3e0: Pull complete 
30b60f0b1627: Pull complete 
a774eb30ae9a: Pull complete 
99abe5102984: Pull complete 
f0154f2759c0: Pull complete 
Digest: sha256:6c051390cfae7958ff427834937c353fc6c34484f6a84b3e4bc8c512b53a16f6
Status: Downloaded newer image for zookeeper:latest
docker.io/library/zookeeper:latest
  • 查看本地镜像

拉取镜像完毕后,我们使用 images 命令来查看镜像:

# 查看镜像
docker images
# 输出信息
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
zookeeper           latest              36b7f3aa2340        10 days ago         252MB
  • 启动镜像

接下来我们就可以启动 zookeeper 镜像了。

# run 启动,-d 后台运行,--name 别名,-p 端口映射(可以写多个), 容器名称:版本(不写默认latest)
docker run -d --name=zookeeper -p 2181:2181 zookeeper

启动成功后会输出当前容器的 ID:

6e191d07172187ec27c2227ae99760177b2fe7dbca25061af35586dd7ee0d1cb
  • 查看容器

这里我们可以使用 container 命令来查看容器:

# 查看所有的容器
docker container ls -a

输出容器列表,我们可以看见刚才启动的 zookeeper 容器:

CONTAINER ID	IMAGE		COMMAND					CREATED			STATUS	PORTS     	NAMES
6e191d071721	zookeeper	"/docker-entrypoint.…"   3 minutes ago	Up 3 minutes       	 zookeeper
  • 进入容器

使用 exec 命令我们就可以进入已经启动的 zookeeper 容器:

docker exec -it zookeeper /bin/bash

进入容器后我们使用 ls 命令来查看 文件列表:

LICENSE.txt  NOTICE.txt  README.md  README_packaging.md  bin  conf  docs  lib

Zookeeper 的命令就在 bin 目录中,我们可以使用 zkCli.sh 连接 Zookeeper 服务端,也可以使用宿主机的客户端加映射的端口来连接 Docker 容器内的 Zookeeper 服务端。

想要退出容器的话使用 exit 命令即可。

  • 关闭容器

如果我们想要关闭容器,在容器外使用以下命令:

docker container stop zookeeper

如果这样来启动多个容器,然后一个一个配置的话,也是一件繁琐的事情。那么有没有一次性能启动多个 Zookeeper 的方式呢?接下来我们就使用 Docker Compose 来构建 Zookeeper 集群。

5. Docker Compose

Docker Compose 的定位是:定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)。

Docker Compose 中有两个重要的概念:

  • 服务 service :一个应用的容器,实际上可以包括多个运行相同镜像的容器实例。
  • 项目 project :由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

通过 Docker Compose,我们可以使用 docker-compose.yml 文件来配置应用程序需要的所有服务,然后使用 up 命令,就可以从 docker-compose.yml 文件配置中创建并启动所有服务。

首先我们来安装 Docker Compose。

5.1 Docker Compose 安装

我们可以直接从 Docker 官方 GitHub Release 上直接拉取编译好的二进制文件:

# 拉取 compose
curl -L https://github.com/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# 添加 docker-compose 命令
chmod +x /usr/local/bin/docker-compose
# 补全命令
curl -L https://raw.githubusercontent.com/docker/compose/1.8.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

执行完毕后,我们来查看 docker-compose 的版本:

docker-compose -v
# 输出版本信息
docker-compose version 1.27.4, build 40524192

5.2 构建 Zookeeper 集群

接下来我们就来使用 docker-compose.yml 文件,构建 Zookeeper 集群。

  • 创建 docker-compose.yml

首先我们在 /usr/local 目录下创建 zookeeper 文件夹,在 zookeeper 文件夹中创建 docker-compose.yml 文件:

mkdir /usr/local/zookeeper
touch /usr/local/zookeeper/docker-compose.yml

创建完成后,我们开始编写 docker-compose.yml 文件:

vi /usr/local/zookeeper/docker-compose.yml
# Zookeeper 版本
version: '3.6'

# 服务组
services:

  # 服务1
  zoo1:
    # 镜像:zookeeper
    image: zookeeper
    # 总是启动
    restart: always
    # 地址别名 zoo1
    hostname: zoo1
    # 端口暴露
    ports:
      - 2181:2181
    # 环境配置
    environment:
      # myid 文件值
      ZOO_MY_ID: 1
      # 集群服务列表
      ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
      
  # 服务2
  zoo2:
    image: zookeeper
    restart: always
    hostname: zoo2
    ports:
      - 2182:2181
    environment:
      ZOO_MY_ID: 2
      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181

  # 服务3
  zoo3:
    image: zookeeper
    restart: always
    hostname: zoo3
    ports:
      - 2183:2181
    environment:
      ZOO_MY_ID: 3
      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181
  • 启动

编写完成后,在 docker-compose.yml 的目录使用 docker-compose up 命令启动:

# 进入 docker-compose.yml 所在目录
cd /usr/local/zookeeper/
# 后台启动
docker-compose up -d
# 输出启动信息
Starting zookeeper_zoo1_1 ... done
Starting zookeeper_zoo3_1 ... done
Starting zookeeper_zoo2_1 ... done

启动成功后,我们可以使用 docker container ls -a 查看容器列表,我们也可以使用 ps 命令来查看 docker-compose 构建的容器:

docker-compose ps
      Name                    Command               State                          Ports                        
----------------------------------------------------------------------------------------------------------------
zookeeper_zoo1_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2181->2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp
zookeeper_zoo2_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2182->2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp
zookeeper_zoo3_1   /docker-entrypoint.sh zkSe ...   Up      0.0.0.0:2183->2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp

构建完成后,我们就可以使用 客户端来连接 Zookeeper 了。

  • 连接 Zookeeper 服务端

首先我们使用 exec 命令进入容器:

docker exec -it zookeeper_zoo1_1 /bin/bash

再使用 zkCli.sh 来连接 Zookeeper 服务端:

zkCli.sh -server localhost:2181,localhost:2182,localhost:2183

这样我们通过一个文件就构建了一个数量为 3 的 Zookeeper 集群,方便构建而且易于管理。

6. 总结

在本节内容中,我们学习了使用 Docker 来构建 Zookeeper 服务,还使用了 Docker Compose 构建了 Zookeeper 集群。以下是本节内容总结:

  1. Docker 安装。
  2. 使用 Docker 安装 Zookeeper 。
  3. 使用 Docker Compose 构建 Zookeeper 集群。