单节点环境搭建
拉取 zookeeper 镜像
docker pull zookeeper
zookeeper 单节点启动
docker run --name zk1 -d zookeeper
这个命令会在后台运行一个 zookeeper 容器, 名字是 zk1, 并且它默认会导出 2181 端口.
查看 zookeeper 镜像启动日志
docker logs zk1 -f
这个命令查看 ZK 的运行情况, 输出类似如下内容时, 表示 ZK 已经成功启动了:>>> docker logs -f my_zookeeper
ZooKeeper JMX enabled by default
Using config: /conf/zoo.cfg
...
2016-09-14 06:40:03,445 [myid:] - INFO [main:NIOServerCnxnFactory@89] - binding to port 0.0.0.0/0.0.0.0:2181
查看镜像中 zookeeper 的配置情况
docker exec -it zk1 /bin/bash
使用 vi 进入配置文件docker vi /conf/zoo.cfg
注意:这里需要先安装 vimapt-get update
apt-get install vim
注意:进入配置文件后,需要添加如下配置,不然下面无法查看 zookeeper 运行状态4lw.commands.whitelist=*
保存退出,重启 zookeeper 容器docker restart zk1
zookeeper 运行状态docker inspect zk1
查看 docker 容器的一些构建信息, 这里我主要是查询该容器的 ip 地址"IPAddress": "172.17.0.2"
接下在宿主机中执行命令, 查看 Zookeeper 运行状态(上面已经在配置文件中添加了配置)➜ ~ echo stat | nc 172.17.0.2 2181
Zookeeper version: 3.5.5-390fe37ea45dee01bf87dc1c042b5e3dcce88653, built on 05/03/2019 12:07 GMT
Clients:
/172.17.0.1:47470[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 1
Sent: 0
Connections: 1
Outstanding: 0
Zxid: 0x0
Mode: standalone
Node count: 5
使用 ZK 命令行客户端连接 ZK
因为刚才我们启动的那个 ZK 容器并没有绑定宿主机的端口, 因此我们不能直接访问它. 但是我们可以通过 Docker 的 link 机制来对这个 ZK 容器进行访问. 执行如下命令:docker run -it --rm --link zk1:zookeeper zookeeper zkCli.sh -server zookeeper
如果对 Docker 有过了解的话, 那么对上面的命令一定不会陌生了.
这个命令的含义是:
启动一个 zookeeper 镜像, 并运行这个镜像内的 zkCli.sh 命令, 命令参数是 "-server zookeeper"
将我们先前启动的名为 zk1 的容器连接(link) 到我们新建的这个容器上, 并将其主机名命名为 zookeeper
当我们执行了这个命令后, 就可以像正常使用 ZK 命令行客户端一样操作 ZK 服务了.
集群环境搭建
启动两个节点
重新按照如上命令启动两个节点, 加上 zk1 就 3 个节点了通过 docker inspect {container_name} 命令我们可以获取到所有 Zookeeper 单节点的 ip 地址
zk1: 172.17.0.2
zk2: 172.17.0.3
zk3: 172.17.0.4
配置
1、进入zk1, 编辑配置文件docker exec -it zk1 /bin/bash
2、加上集群的配置信息
注意:删掉 server.1=localhost:2888:3888;2181 添加 clientPort=2181dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
4lw.commands.whitelist=*
clientPort=2181
server.1=172.17.0.2:2888:3888
server.2=172.17.0.3:2888:3888
server.3=172.17.0.4:2888:3888
2888, 是zk之间通信的端口 3888, 是zk之间投票选举的端口
保存退出
3、修改服务名称为1root@db6f08303a62:/apache-zookeeper-3.5.5-bin# vi /data/myid
保存退出
4、zk2 和 zk3 同上配置,注意 zk2 的 myid 是 2,zk3 的 myid 是 3
全部保存退出,重启容器docker restart zk1
docker restart zk2
docker restart zk3
查看集群是否部署成功[root@localhost ~]# echo stat | nc 172.17.0.2 2181
Zookeeper version: 3.5.5-390fe37ea45dee01bf87dc1c042b5e3dcce88653, built on 05/03/2019 12:07 GMT
Clients:
/172.17.0.1:47604[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 4
Sent: 3
Connections: 1
Outstanding: 0
Zxid: 0x400000000
Mode: follower
Node count: 5
[root@localhost ~]# echo stat | nc 172.17.0.3 2181
Zookeeper version: 3.5.5-390fe37ea45dee01bf87dc1c042b5e3dcce88653, built on 05/03/2019 12:07 GMT
Clients:
/172.17.0.1:49454[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 2
Sent: 1
Connections: 1
Outstanding: 0
Zxid: 0x600000000
Mode: leader
Node count: 5
Proposal sizes last/min/max: -1/-1/-1
[root@localhost ~]# echo stat | nc 172.17.0.4 2181
Zookeeper version: 3.5.5-390fe37ea45dee01bf87dc1c042b5e3dcce88653, built on 05/03/2019 12:07 GMT
Clients:
/172.17.0.1:48764[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 2
Sent: 1
Connections: 1
Outstanding: 0
Zxid: 0x600000000
Mode: follower
Node count: 5
可以看到 zk2 成了 leader,zk1 和 zk3 为 follwer
修改容器映射端口
修改容器映射端口本来是需要在通过镜像运行成容器时通过-p 宿主机端口:容器端口指定的,但是前面我没有指定,直接运行了,导致后面通过Java API操作不了,这时候就需要将宿主机端口映射到容器端口上,这样就可以通过宿主机ip+宿主机与容器映射的端口访问了
1、先查出要修改的容器id[root@localhost root]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
93766fd0d8b1 zookeeper:latest "/docker-entrypoint.…" 5 hours ago Up 7 minutes 2888/tcp, 3888/tcp, 8080/tcp, 0.0.0.0:2183->2181/tcp zk3
acdff94409f3 zookeeper:latest "/docker-entrypoint.…" 5 hours ago Up 7 minutes 2888/tcp, 3888/tcp, 8080/tcp, 0.0.0.0:2182->2181/tcp zk2
a799f0737b84 zookeeper "/docker-entrypoint.…" 16 hours ago Up 7 minutes 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, 8080/tcp zk1
zk1 a799f0737b84
zk2 acdff94409f3
zk3 93766fd0d8b1
2、停止 3 个容器docker stop zk1
docker stop zk2
docker stop zk3
3、停止 Docker 服务systemctl stop docker
4、进入宿主机中的容器目录/var/lib/docker/containers
5、修改配置文件
查看所有的容器,前面的容器 id 就是这些文件前一部分的文件名
[root@localhost containers]# ls
591b9d439571b2f14d6bc92fef77d64f539cb768bb4146d6e8a1add106e8001a a799f0737b8482282541d3741b37adbba1359f27b821c40ae501f03ee2c70716
93766fd0d8b1028c8e2213d6cd32587983c9cb0b771c66c2210839741146e9af acdff94409f3c5adde4ad74a696d22993de0f3fed26d0f31625a5d261ee506f8
a6d52c51fbcff435f688a60cdab9612059b2d86ffaa21ee9fb0aa7ba670a232f c7cb139c2d341c7ce566c512123a2a29a551aaf2945674fb1ae21b7a4ffbdaf4
根据前面查到的容器id,进入hostconfig.json然后修改对应的配置[root@localhost containers]# vi a799f0737b8482282541d3741b37adbba1359f27b821c40ae501f03ee2c70716/hostconfig.json
# 如果之前没有端口映射, 应该有这样的一段:
"PortBindings":{}
# 增加一个映射, 这样写:
"PortBindings":{"2181/tcp":[{"HostIp":"","HostPort":"2181"}]}
# 前一个数字是容器端口, 后一个是宿主机端口.
# 而修改现有端口映射更简单, 把端口号改掉就行.
这里以zk1为例,其他两个分别修改为2181->2182,2181->2183
6、重新启动
启动docker服务systemctl start docker
启动三个容器docker start zk1
docker start zk2
docker start zk3
外部客户端就可以通过 宿主机ip+宿主机与容器映射的端口连接到该Zookeeper集群了
docker-compose 版 ZK 集群搭建
因为一个一个地启动 ZK 太麻烦了, 所以为了方便起见, 我们直接使用 docker-compose 来启动 ZK 集群.
首先创建一个名为 docker-compose.yml 的文件, 其内容如下:version: '2'
services:
zoo1:
image: zookeeper
restart: always
container_name: zoo1
ports:
- "2181:2181"
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
zoo2:
image: zookeeper
restart: always
container_name: zoo2
ports:
- "2182:2181"
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
zoo3:
image: zookeeper
restart: always
container_name: zoo3
ports:
- "2183:2181"
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
这个配置文件会告诉 Docker 分别运行三个 zookeeper 镜像, 并分别将本地的 2181, 2182, 2183 端口绑定到对应的容器的 2181 端口上.
ZOO_MY_ID 和 ZOO_SERVERS 是搭建 ZK 集群需要设置的两个环境变量, 其中 ZOO_MY_ID 表示 ZK 服务的 id, 它是1-255 之间的整数, 必须在集群中唯一. ZOO_SERVERS 是ZK 集群的主机列表.
接着我们在 docker-compose.yml 当前目录下运行:COMPOSE_PROJECT_NAME=zk_test docker-compose up
即可启动 ZK 集群了.
执行上述命令成功后, 接着在另一个终端中运行 docker-compose ps 命令可以查看启动的 ZK 容器:>>> COMPOSE_PROJECT_NAME=zk_test docker-compose ps
Name Command State Ports
----------------------------------------------------------------------
zoo1 /docker-entrypoint.sh zkSe ... Up 0.0.0.0:2181->2181/tcp
zoo2 /docker-entrypoint.sh zkSe ... Up 0.0.0.0:2182->2181/tcp
zoo3 /docker-entrypoint.sh zkSe ... Up 0.0.0.0:2183->2181/tcp注意, 我们在 "docker-compose up" 和 "docker-compose ps" 前都添加了 COMPOSE_PROJECT_NAME=zk_test 这个环境变量, 这是为我们的 compose 工程起一个名字, 以免与其他的 compose 混淆.
使用 Docker 命令行客户端连接 ZK 集群
通过 docker-compose ps 命令, 我们知道启动的 ZK 集群的三个主机名分别是 zoo1, zoo2, zoo3, 因此我们分别 link 它们即可:docker run -it --rm \
--link zoo1:zk1 \
--link zoo2:zk2 \
--link zoo3:zk3 \
--net zktest_default \
zookeeper zkCli.sh -server zk1:2181,zk2:2181,zk3:2181
通过本地主机连接 ZK 集群
因为我们分别将 zoo1, zoo2, zoo3 的 2181 端口映射到了 本地主机的2181, 2182, 2183 端口上, 因此我们使用如下命令即可连接 ZK 集群了:zkCli.sh -server localhost:2181,localhost:2182,localhost:2183
查看集群
我们可以通过 nc 命令连接到指定的 ZK 服务器, 然后发送 stat 可以查看 ZK 服务的状态, 例如:>>> echo stat | nc 127.0.0.1 2181
Zookeeper version: 3.4.9-1757313, built on 08/23/2016 06:50 GMT
Clients:
/172.18.0.1:49810[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 5/39/74
Received: 4
Sent: 3
Connections: 1
Outstanding: 0
Zxid: 0x200000002
Mode: follower
Node count: 4
>>> echo stat | nc 127.0.0.1 2182
Zookeeper version: 3.4.9-1757313, built on 08/23/2016 06:50 GMT
Clients:
/172.18.0.1:50870[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 2
Sent: 1
Connections: 1
Outstanding: 0
Zxid: 0x200000002
Mode: follower
Node count: 4
>>> echo stat | nc 127.0.0.1 2183
Zookeeper version: 3.4.9-1757313, built on 08/23/2016 06:50 GMT
Clients:
/172.18.0.1:51820[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 2
Sent: 1
Connections: 1
Outstanding: 0
Zxid: 0x200000002
Mode: leader
Node count: 4
通过上面的输出, 我们可以看到, zoo1, zoo2 都是 follower, 而 zoo3 是 leader, 因此证明了我们的 ZK 集群确实是搭建起来了.
k8s 部署 zookeeper 集群
部署方式
k8s 以 statefulset 方式部署 zookeeper 集群
statefulset 简介
StatefulSet 是 Kubernetes 提供的管理有状态应用的负载管理控制器 API。在 Pods 管理的基础上,保证 Pods 的顺序和一致性。与 Deployment 一样,StatefulSet 也是使用容器的 Spec 来创建 Pod,与之不同 StatefulSet 创建的 Pods 在生命周期中会保持持久的标记(例如 Pod Name)。
StatefulSet 适用于具有以下特点的应用:
具有固定的网络标记(主机名)
具有持久化存储
需要按顺序部署和扩展
需要按顺序终止及删除
需要按顺序滚动更新
安装 NFS
NFS 安装与配置
创建 zookeeper pv 挂载目录mkdir /data/tools/zk/pv
将 zookeeper pv 挂载目录
方法一
直接挂载到NFS共享目录
方法二
将创建的zookeeper pv挂载目录再挂载到NFS共享目录。
注:若都zk pv path都挂载到共享目录,则zk pv path不能相同
举例:
zk3个节点的path 对应NFS共享目录
共享目录1:/data/tools/pv/zk01
共享目录2:/data/tools/pv/zk02
共享目录3:/data/tools/pv/zk03
zk有3个节点要挂3个pv
pv1 name:k8s-pv-zk1
pv1 path:/data/tools/pv/zk01
pv2 name: k8s-pv-zk2
pv2 path: /data/tools/pv/zk02
pv3 name: k8s-pv-zk3
pv3 path: /data/tools/pv/zk03
注:pv path的路径要与NFS共享目录保持一致。
创建 PV 与 PVC
PV 与 PVC 简介
PersistentVolume(PV)是集群中由管理员配置的一段网络存储。 它是集群中的资源,就像节点是集群资源一样。 PV是容量插件,如Volumes,但其生命周期独立于使用PV的任何单个pod。 此API对象捕获存储实现的详细信息,包括NFS,iSCSI或特定于云提供程序的存储系统。
PersistentVolumeClaim(PVC)是由用户进行存储的请求。 它类似于pod。 Pod消耗节点资源,PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式(例如,可以一次读/写或多次只读)。
编写PV与PVC的yaml文件zookeeper-pv.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: k8s-pv-zk1
namespace: tools
annotations:
volume.beta.kubernetes.io/storage-class: "anything"
labels:
type: local
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path:/data/tools/pv/zk01
persistentVolumeReclaimPolicy: Recycle
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: k8s-pv-zk2
namespace: tools
annotations:
volume.beta.kubernetes.io/storage-class: "anything"
labels:
type: local
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path:/data/tools/pv/zk02
persistentVolumeReclaimPolicy: Recycle
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: k8s-pv-zk3
namespace: tools
annotations:
volume.beta.kubernetes.io/storage-class: "anything"
labels:
type: local
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path:/data/tools/pv/zk03
persistentVolumeReclaimPolicy: Recycle
注:以上方式是同时创建PV与PVC的yaml文件
创建pv与pvc
kubectl apply -f zookeeper-pv.yaml
创建 zookeeper 集群
编写 zookeepr.yaml 文件apiVersion: v1
kind: Service
metadata:
name: zk-hs
namespace: tools
labels:
app: zk
spec:
ports:
- port: 2888
name: server
- port: 3888
name: leader-election
clusterIP: None
selector:
app: zk
---
apiVersion: v1
kind: Service
metadata:
name: zk-cs
namespace: tools
labels:
app: zk
spec:
type: NodePort
ports:
- port: 2181
nodePort: 21811
name: client
selector:
app: zk
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
namespace: tools
spec:
selector:
matchLabels:
app: zk
maxUnavailable: 1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: zk
namespace: tools
spec:
selector:
matchLabels:
app: zk
serviceName: zk-hs
replicas: 3 #设置节点数量
updateStrategy:
type: RollingUpdate
podManagementPolicy: Parallel
template:
metadata:
labels:
app: zk
spec:
containers:
- name: zk
imagePullPolicy: Always
image: "zookeeper 镜像pull地址"
resources:
requests:
memory: "500Mi"
cpu: "0.5"
ports:
- containerPort: 2181
name: client
- containerPort: 2888
name: server
- containerPort: 3888
name: leader-election
command:
- sh
- -c
- "/data/ecs/zookeeper-3.4.3/bin/start-zookeeper.sh \
--servers=3 \
--data_dir=/data/zookeeper/data \
--data_log_dir=/data/zookeeper/data_log_dir \
--log_dir=/data/zookeeper/log \
--client_port=2181 \
--election_port=3888 \
--server_port=2888 \
--tick_time=2000 \
--init_limit=10 \
--sync_limit=5 \
--heap=512M \
--max_client_cnxns=60 \
--snap_retain_count=3 \
--purge_interval=12 \
--max_session_timeout=80000 \
--min_session_timeout=8000 \
--log_level=DEBUG"
readinessProbe:
exec:
command:
- sh
- -c
- "/data/zookeeper-3.4.3/bin/zookeeper-ready.sh 2181"
initialDelaySeconds: 10
timeoutSeconds: 5
livenessProbe:
exec:
command:
- sh
- -c
- "/data/zookeeper-3.4.3/bin/zookeeper-ready.sh 2181"
initialDelaySeconds: 10
timeoutSeconds: 5
volumeMounts:
- name: datadir
mountPath: /data/zookeeper
#securityContext:
# runAsUser: 1000
# fsGroup: 1000
volumeClaimTemplates:
- metadata:
name: datadir
annotations:
volume.beta.kubernetes.io/storage-class: "anything"
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 500Mi
执行 zookeeper.yaml 文件
kubectl apply -f zookeeper.yaml
对外暴露访问端口#创建zkService.yaml
touch zkService.yaml
#zkService.yaml内容
apiVersion: v1
kind: Service
metadata:
name: zk-cs
namespace: tools
labels:
app: zk
spec:
type: NodePort
ports:
- port: 2181
nodePort: 21811
name: client
selector:
app: zk
注:nodePort为对外暴露端口,端口号必须5位数字。建议与zookeeper.yaml合并。#执行zookeeper.yaml文件
kubectl apply -f zookeeper.yaml
检查节点 zookeeper 是否启动成功
检查 zookeeper 服务是否启动成功
docker ps -a|grep zk zk 为 name
zookeeper服务启动成功
检查集群是否启动成功#进入容器
docker exec -it 3612d5a53590 /bin/bash
#cd到zookeeper部署目录
cd /data/zookeeper-3.4.3/bin
#检查服务状态
./zkServer.sh status
显示如下表示启动成功:JMX enabled by default
Using config: /data/zookeeper-3.4.3/bin/../conf/zoo.cfg
Mode: leader/follower
注:3个节点会有一个leader,2个follower
显示如下表示启动失败:JMX enabled by default
Using config: /data/zookeeper-3.4.3/bin/../conf/zoo.cfg
Error contacting service. It is probably not running.
遇到的坑
问题一:pvc创建成功后状态为 pending
原因:pv与pvc的storage不一样,pvc的storage只能小于或等pvc的storage
解决方法:
1、修改pvc的yam文件,将storage值修改为小于或等pv的storage值
2、删除pvc
3、重新创建pvc
问题二:启动zk提示没有权限
原因:StatefulSet指定了用户使用非root用户部署
解决方法:注释StatefulSet中以下内容#securityContext:
# runAsUser: 1000
# fsGroup: 1000
问题三:zookeeper 启动成功但集群没有启动成功
错误描述:
JMX enabled by default
Using config: /data/ecs/zookeeper-3.4.3/bin/../conf/zoo.cfg
Error contacting service. It is probably not running.
原因一:创建数据目录的myid的值与zoo.cfg的server.1=ip:2888:3888
注:创建数据目录,zoo.cfg配置文件里dataDir指定的那个目录下创建myid文件,并且指定id,改id为你zoo.cfg文件中server.1=ip:2888:3888中的1.只要在myid头部写入1即可.同理其它两台机器的id对应上。
例:
节点1 server.1=ip:2888:3888
节点2 server.2=ip:2888:3888
节点1的 myid内容为1
节点2的 myid内容为2
解决方法一:
1、进入zookeeper部署的容器,
2、删除/data/zookeeper/data下所有内容
3、kill所有节点 zookeeper进程,让zookeeper重新启动。
解决方法二:
升级zookeeper版本至3.4.4及以上
other
设置 docker 固定 ip
因为我们要搭建的是集群环境,所以 ip 地址必须固定,因此需要自定义一种网络类型。sudo docker network create --subnet=192.168.0.0/24 staticnet
通过 docker network ls 可以查看到网络类型中多了一个 staticnet
使用新的网络类型创建并启动容器docker run --name zookeeper-1 --restart always --net staticnet --ip 192.168.0.10 -d zookeeper:3.4.11
通过 docker inspect 可以查看容器 ip 为 192.168.0.10,关闭容器并重启,发现容器 ip 并未发生改变。
进入容器进行配置
$ docker exec -ti 61a bash # 61a为容器id
登入后,我们只需要做2件事:
修改 zoo.cfg
在 zoo.cfg 文件中添加 zk 集群节点列表# vi /conf/zoo.cfgclientPort=2181
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
maxClientCnxns=60
server.1=192.168.0.10:2888:3888
server.2=192.168.0.11:2888:3888
server.3=192.168.0.12:2888:3888
server.4=192.168.0.13:2888:3888:observer
创建 myid 文件
在一步的 zoo.cfg 文件中我们可以看到 dataDir 的路径,在 /data 目录中创建表示当前主机编号的 myid 文件。该主机编号要与 zoo.cfg 文件中设置的编号一致。# echo 1 > /data/myid
保存修改后的镜像
因为我们上面对正在运行的容器做了三点修改,这也正是我们需要的集群配置,所以我们要将这个容器制作成镜像,如下操作:docker commit -m "create zk1" -a "coderluo" 61a zookeeper-1:3.4.11
到这里一台镜像已经制作好了,接下来就是一样的事情重复干几遍:
进入容器
修改 myid
保存修改制作为新镜像
完成后,这里要注意,第四台主机因为我们要让他作为 Observer,所以他需要在 zoo.cfg 中增加一行配置:peerType=observer
然后在执行上面和第2,3台机器一样的操作。
依次启动 4 台 zookeeper 实例
直接按照我下面的命令一次执行即可:$ docker run --name zookeeper-1 --restart always --net staticnet --ip 192.168.0.10 -d zookeeper-1:3.4.11 #第一台
35acd4f798c8154047f30af184145d8b4124ec8a4e8e4a549db0d333a1c33785
chong@L MINGW64 ~
$ docker run --name zookeeper-2 --restart always --net staticnet --ip 192.168.0.11 -d zookeeper-2:3.4.11 #第二台
7ef30c809183dc223e42e891880ad8c85381fac11d15da5c0455400b915c77bb
chong@L MINGW64 ~
$ docker run --name zookeeper-3 --restart always --net staticnet --ip 192.168.0.12 -d zookeeper-3:3.4.11 #第三台
f138451dd21ce5217eb6e4472116b3ffa32e9ea2afbcaae44ee4d633040299f9
chong@L MINGW64 ~
$ docker run --name zookeeper-4 --restart always --net staticnet --ip 192.168.0.13 -d zookeeper-4:3.4.11 #第四台
c662d3438db74414c9b0178bc756b6cf96cd0458cbc226e8854da4a06337d656
查看运行状态:$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c662d3438db7 zookeeper-4:3.4.11 "/docker-entrypoint.…" 6 seconds ago Up 4 seconds 2181/tcp, 2888/tcp, 3888/tcp zookeeper-4
f138451dd21c zookeeper-3:3.4.11 "/docker-entrypoint.…" 24 seconds ago Up 23 seconds 2181/tcp, 2888/tcp, 3888/tcp zookeeper-3
7ef30c809183 zookeeper-2:3.4.11 "/docker-entrypoint.…" 41 seconds ago Up 39 seconds 2181/tcp, 2888/tcp, 3888/tcp zookeeper-2
35acd4f798c8 zookeeper-1:3.4.11 "/docker-entrypoint.…" About a minute ago Up About a minute 2181/tcp, 2888/tcp, 3888/tcp zookeeper-1
总结
至此我们今天要搭建的四台 zk 实例组成的集群已经搞定了。
使用 Dockerfile 制作 zookeeper 镜像
基于 docker 搭建 zookeeper 和 kafka 集群(多台真机之间的集群)
三台真机,容器采用 host
192.168.0.128 192.168.0.141 192.168.0.142
zookeeper 集群搭建
在每台机上执行脚本#!/bin/bash
#Get zookeeper image
zkimage=`docker images | grep zookeeper | awk {'print $1'}`
if [ -n "$zkimage" ]
then
echo 'The zookeeper image is already existed.'
else
echo 'Pull the latest zookeeper image.'
docker pull zookeeper
fi
#Create network for zookeeper containers
zknet=`docker network ls | grep yapi_net | awk {'print $2'}`
if [ -n "$zknet" ]
then
echo 'The zknetwork is already existed.'
else
echo 'Create zknetwork.'
docker network create --subnet 172.30.0.0/16 yapi_net
fi
#Start zookeeper cluster
echo 'Start 3 zookeeper servers.'
rm -rf /opt/zookeeper_1/data /opt/zookeeper_1/datalog /var/log/zookeeper_1/log
rm -rf /opt/zookeeper_2/data /opt/zookeeper_2/datalog /var/log/zookeeper_2/log
rm -rf /opt/zookeeper_3/data /opt/zookeeper_3/datalog /var/log/zookeeper_3/log
mkdir -p /opt/zookeeper_1/data /opt/zookeeper_1/datalog /var/log/zookeeper_1/log
mkdir -p /opt/zookeeper_2/data /opt/zookeeper_2/datalog /var/log/zookeeper_2/log
mkdir -p /opt/zookeeper_3/data /opt/zookeeper_3/datalog /var/log/zookeeper_3/log
ZOO_SERVERS="server.1=192.168.0.128:2888:3888 server.2=192.168.0.142:2888:3888 server.3=192.168.0.141:2888:3888"#新版 ZOO_SERVERS="clientPort=2181 server.1=192.168.0.146:2888:3888 server.2=192.168.0.145:2888:3888"
docker run --network host -d --restart always -v /opt/zookeeper_1/data:/data -v /opt/zookeeper_1/datalog:/datalog -v /var/log/zookeeper_1/log:/logs -e ZOO_SERVERS="$ZOO_SERVERS" -e ZOO_MY_ID=1 --name zookeeper_1 -p 2182:2181 -p 2888:2888 -p 3888:3888 docker.io/zookeeper
注意每台机的 id 号不同
官方的镜像有可能配置的环境变量不同,需要修改脚本,参考 Entrypoint 文件,和配置文件,配置文件如下:clientPort=2181
dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
server.1=192.168.0.128:2888:3888
server.2=192.168.0.142:2888:3888
server.3=192.168.0.141:2888:3888
4lw.commands.whitelist=*
kafka 集群搭建
在每台机上执行脚本:#!/bin/bash
#Get zookeeper image
kfkimage=`docker images | grep 'docker.io/wurstmeister/kafka' | awk {'print $1'}`
if [ -n "$kfkimage" ]
then
echo 'The docker.io/wurstmeister/kafka is already existed.'
else
echo 'Pull the image.'
docker pull docker.io/wurstmeister/kafka
fi
#Create network for zookeeper containers
kfknet=`docker network ls | grep yapi_net | awk {'print $2'}`
if [ -n "$kfknet" ]
then
echo 'The kfknetwork is already existed.'
else
echo 'Create kfknetwork.'
docker network create --subnet 172.30.0.0/16 yapi_net
fi
#Start 3 zookeeper cluster
echo 'Start 3 kafka servers.'
rm -rf /opt/kafka_1/logdata
rm -rf /opt/kafka_2/logdata
rm -rf /opt/kafka_3/logdata
mkdir -p /opt/kafka_1/logdata
mkdir -p /opt/kafka_2/logdata
mkdir -p /opt/kafka_3/logdata
#kafka ip
kfk_1_ip='172.30.0.41'
kfk_2_ip='172.30.0.42'
kfk_3_ip='172.30.0.43'
#zk_jiqun_ip='172.30.0.31:2181'
zk_jiqun_ip='192.168.0.128:2181,192.168.0.142:2181,192.168.0.141:2181'
docker run --restart always -d --name kafka_1 --network host -e KAFKA_ZOOKEEPER_CONNECT=${zk_jiqun_ip} -e KAFKA_LISTENERS='PLAINTEXT://0.0.0.0:9092' -e KAFKA_BROKER_ID='141' -e KAFKA_ADVERTISED_LISTENERS='PLAINTEXT://192.168.0.141:9092' -v /opt/kafka_1/logdata:/kafka -p 9092:9092 docker.io/wurstmeister/kafka
注意 id 号 和 PLAINTEXT://192.168.0.141:9092,(创建容器后,再进入容器修改,restart 后会重置,所以必须在创建容器时,就要指定好环境变量。因为启动脚本会重新修改配置文件,所以要想修改环境变量,只需要在启动脚本里加一个即可)
补充:单机docker run -d --restart always -v /opt/zookeeper/data:/data -v /opt/zookeeper/datalog:/datalog -v /var/log/zookeeper/log:/logs --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 -p 8081:8080 docker.io/zookeeper
docker run --restart always -d --name kafka -e KAFKA_ZOOKEEPER_CONNECT=${zk_jiqun_ip} -e KAFKA_LISTENERS='PLAINTEXT://0.0.0.0:9092' -e KAFKA_BROKER_ID='163' -e KAFKA_ADVERTISED_LISTENERS='PLAINTEXT://172.18.72.163:9092' -v /opt/kafka/logdata:/kafka -p 9092:9092 docker.io/wurstmeister/kafka
补充2:云上部署
不同主机节点,zookeeper 采用 host 网络:因为采用容器网络,zookeeper 不同主机节点之间通信,找不到容器网络,不同主机节点,kafka 采用 host 网络,单参数KAFKA_ADVERTISED_LISTENERS='PLAINTEXT://172.18.72.163:9092' ,发消息时,会通过配置文件 PLAINTEXT://172.18.72.163:9092,找 kafka 集群的节点,线上配置私网即可,因为,服务之间可以通过私网访问,如果本地需要用来访问kafka时,就需要要配置公网 ip:因为远程,如果是私网,就会连接超时.
Reference
https://www.jianshu.com/p/65be2914e44e
https://zhuanlan.zhihu.com/p/72467871