软硬件开发技术笔记
保持专注,拒绝内耗
docker中运行zookeeper
2022-01-16 21:30

本文演示如何在docker中运行zookeeper,以及链接方式
centos7.6系统上实验,其他环境操作类似

1. 基础环境准备

已经搭建好docker环境的本章节可以跳过
docker基本使用可以参见之前的文章,此处仅简单描述安装docker过程
宿主机准备源:

# mkdir /etc/yum.repos.d/back
# mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/back
# curl http://mirrors.aliyun.com/repo/Centos-7.repo > /etc/yum.repos.d/Centos-7.repo
# curl http://mirrors.aliyun.com/repo/epel-7.repo > /etc/yum.repos.d/epel.repo
# yum makecache

安装docker并启动

# yum install docker
# systemctl start docker
# systemctl enable docker

2. 运行单实例zookeeper

2.1 启动zookeeper

启动的的时候会从公网容器中拉取zookeeper镜像,因此第一次启动需要有个下载镜像pull的过程

#  docker run --name zookeeper-server --restart always -d zookeeper
8018a27ff505fa7d45219d371d1e0f5b945a4fe8a5b31325ee98b6acd5976e5b

启动后通过docker ps -a查询状态,如果STATUS不是up,说明启动有问题,需要排查

# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                    NAMES
8018a27ff505        zookeeper           "/docker-entrypoin..."   3 seconds ago       Up 2 seconds        2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp   zookeeper-server

参数解释:

--name           : 容器取名为zookeeper-server, 此名称可以随意定义
--restart always : 定义容器的重启策略,即在容器退出时总是重启容器,如果只是实验,该参数非必须
-d               : 以daemon方式运行
zookeeper        : zookeeper的镜像名称,docker会到网络仓库中拉取该名称的镜像,因此不可修改

通过上述docker ps -a可以看到该容器导出了2181/2888/3888/8080端口

2181: 客户端链接端口
2888: follower同步数据端口
3888: zookeeper选举端口
8080: 额外提供的一个restful-api的入口,可以按类似http://<zookeeper-docker-ip>:8080/commands/stat的方式执行四字命令

需要补充的是,这些端口仅暴露在容器内部,也就是仅容器之间可以访问,就是启动的其他容器可以访问
但是宿主机到容器、甚至其他节点到容器是访问不到的
可以在宿主机上通过netstat查看端口情况,正常应该看不到输出
(通过yum install net-tools可以获得netstat命令)

# netstat -anp | grep 2181

2.2 其他容器链接zookeeper

其他容器和zookeeper因为在同一网络,因此链接zookeeper的方法本质就是要知道zookeeper容器的ip地址
可以通过2种方法获取
方法一 (官方推荐方法):
如下使用--link zookeeper-server:zk将zookeeper-server的网络配置和环境变量共享给新启动的容器
其中zookeeper-server为运行zookeeper服务的容器,zk为该容器取的另外一个别名,可以随意设置

# docker run -ti --name client --link zookeeper-server:zk docker.io/centos:centos7.6.1810 /bin/bash

运行后,可以在新容器的环境变量和hosts文件中,获取和查看到zookeeper-server的地址和相关环境变量
环境变量:

[root@6e1159a751d7 /]# env | grep ^ZK
ZK_PORT_3888_TCP_ADDR=172.17.0.2
ZK_PORT_2888_TCP_ADDR=172.17.0.2
ZK_PORT_2888_TCP_PROTO=tcp
ZK_PORT_3888_TCP_PORT=3888
ZK_ENV_ZOO_DATA_DIR=/data
ZK_PORT_8080_TCP_PROTO=tcp
ZK_ENV_ZOO_INIT_LIMIT=5
ZK_ENV_ZOO_CONF_DIR=/conf
ZK_PORT_3888_TCP_PROTO=tcp
ZK_ENV_LANG=C.UTF-8
ZK_PORT=tcp://172.17.0.2:2181
ZK_PORT_8080_TCP_ADDR=172.17.0.2
ZK_ENV_ZOOCFGDIR=/conf
ZK_ENV_ZOO_STANDALONE_ENABLED=true
ZK_ENV_ZOO_AUTOPURGE_PURGEINTERVAL=0
ZK_PORT_8080_TCP=tcp://172.17.0.2:8080
ZK_PORT_2181_TCP_PORT=2181
ZK_ENV_ZOO_ADMINSERVER_ENABLED=true
ZK_PORT_2888_TCP_PORT=2888
ZK_PORT_8080_TCP_PORT=8080
ZK_PORT_2888_TCP=tcp://172.17.0.2:2888
ZK_ENV_ZOO_TICK_TIME=2000
ZK_PORT_2181_TCP_ADDR=172.17.0.2
ZK_ENV_ZOO_LOG_DIR=/logs
ZK_NAME=/client/zk
ZK_ENV_ZOO_AUTOPURGE_SNAPRETAINCOUNT=3
ZK_ENV_JAVA_HOME=/usr/local/openjdk-11
ZK_PORT_2181_TCP=tcp://172.17.0.2:2181
ZK_ENV_ZOO_DATA_LOG_DIR=/datalog
ZK_ENV_JAVA_VERSION=11.0.13
ZK_PORT_3888_TCP=tcp://172.17.0.2:3888
ZK_ENV_ZOO_SYNC_LIMIT=2
ZK_PORT_2181_TCP_PROTO=tcp
ZK_ENV_ZOO_MAX_CLIENT_CNXNS=60

hosts信息,其中可以通过zk/8018a27ff505/zookeeper-server任意名称链接到zookeeper-server

[root@6e1159a751d7 /]# cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      zk 8018a27ff505 zookeeper-server
172.17.0.3      6e1159a751d7

方法二:
在宿主机上获取zookeeper容器的ip地址,其他容器种可以通过该ip地址访问zookeeper

# docker inspect  zookeeper-server | grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAddress": "172.17.0.2",

无论通过上述方法一、方法二,链接到zookeeper本质是获取zookeeper-server的ip地址

2.3 容器外链接zookeeper

上面链接方法仅适用于容器间访问zookeeper,但是实际部署时,可能会有业务在容器之外,就会有在容器外访问zookeeper的场景
解决方法就是端口映射或者透传宿主机地址到容器里面,
端口映射就是将宿主机的port和容器内的port做映射,然后访问宿主机的port,就可以完成和zookeeper的通信

删除原来的容器,再重新启动容器,补充--publish 2181:2181参数,即可完成端口映射

# docker rm -f zookeeper-server

# docker run --name zookeeper-server --restart always --publish 2181:2181 -d zookeeper
0fbffd0a9f083c1eb1e6cd388599971f8c2052905e393b6e38ce1ca60d505474
# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                  NAMES
0fbffd0a9f08        zookeeper           "/docker-entrypoin..."   3 seconds ago       Up 2 seconds        2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, 8080/tcp   zookeeper-server

此时在宿主机上再通过netstat即可以看到2181端口的监听情况

# netstat -anp | grep 2181
tcp6       0      0 :::2181                 :::*                    LISTEN      29477/docker-proxy-

# ps -elf | grep 29477
4 S root      29477  24048  0  80   0 - 50192 futex_ 16:51 ?        00:00:00 /usr/libexec/docker/docker-proxy-current -proto tcp -host-ip 0.0.0.0 -host-port 2181 -container-ip 172.17.0.2 -container-port 2181
0 R root      29613  23755  0  80   0 - 28203 -      16:52 pts/1    00:00:00 grep --color=auto 29477

也可以在宿主机上访问zookeeper-server,其他节点也可以通过宿主机ip访问容器的zookeeper
以下通过zookeeper四字命令获取zookeeper的服务状态,是在宿主机上执行(可以通过yum install nc获取nc工具)

# echo srvr | nc 127.0.0.1 2181
Zookeeper version: 3.7.0-e3704b390a6697bfdf4b0bef79e3da7a4f6bac4b, built on 2021-03-17 09:46 UTC
Latency min/avg/max: 0/0.0/0
Received: 3
Sent: 2
Connections: 1
Outstanding: 0
Zxid: 0x0
Mode: standalone
Node count: 5

3. 运行多实例zookeeper

上述运行zookeeper是运行的standalone模式,即单节点无冗余,实际生产部署的时候,会按照zookeper的奇数原则将容器部署在多台服务器上

此处按照zookeeper容器官网上的实例,在同一个宿主机上部署3个zookeeper容器,并且将宿主机的2181/2182/2183映射给3个zookeper容器的2181端口

# cat stack.yml
version: '3.1'

services:
  zoo1:
    image: zookeeper
    restart: always
    hostname: zoo1
    ports:
      - 2181:2181
    environment:
      ZOO_MY_ID: 1
      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181

  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=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181

  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=zoo3:2888:3888;2181

执行部署流程

# docker swarm init
# docker stack deploy -c stack.yml zookeeper

部署后结果

# docker ps
CONTAINER ID        IMAGE                                                                               COMMAND                  CREATED             STATUS                  PORTS
     NAMES
0ae84ed27822        zookeeper@sha256:2c8c5c2db6db22184e197afde13e33dad849af90004c330f20b17282bcd5afd7   "/docker-entrypoin..."   2 seconds ago       Up Less than a second   2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp   zookeeper_zoo3.1.8jstwsbkq591my2qe5cf6z9va
e4b0b8e2d716        zookeeper@sha256:2c8c5c2db6db22184e197afde13e33dad849af90004c330f20b17282bcd5afd7   "/docker-entrypoin..."   5 seconds ago       Up 4 seconds            2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp   zookeeper_zoo2.1.jonbwugqcuiywkhx58bq0g0fr
31243f56dff8        zookeeper@sha256:2c8c5c2db6db22184e197afde13e33dad849af90004c330f20b17282bcd5afd7   "/docker-entrypoin..."   8 seconds ago       Up 7 seconds            2181/tcp, 2888/tcp, 3888/tcp, 8080/tcp   zookeeper_zoo1.1.l5yfrya1k8cdaewcb8fg5oxjo

# netstat -anp | grep 218* | grep LISTEN
tcp6       0      0 :::2183                 :::*                    LISTEN      24048/dockerd-curre
tcp6       0      0 :::2181                 :::*                    LISTEN      24048/dockerd-curre
tcp6       0      0 :::2182                 :::*                    LISTEN      24048/dockerd-curre

相关参考:

https://hub.docker.com/_/zookeeper
https://www.cnblogs.com/telwanggs/p/10855665.html
https://www.jianshu.com/p/21d66ca6115e
分类
mac
1篇
4篇
c
1篇
4篇
2篇
1篇
搜索