Docker搭建Zookeeper&Kafka集群

前排提示:最新的docker-compole.yml请去github获取,README有相应的操做步骤。 Github地址:github.com/JacianLiu/d…java

最近在学习Kafka,准备测试集群状态的时候感受不管是开三台虚拟机或者在一台虚拟机开辟三个不一样的端口号都太麻烦了(嗯。。主要是懒)。mysql

环境准备

一台能够上网且有CentOS7虚拟机的电脑linux

为何使用虚拟机?由于使用的笔记本,因此每次链接网络IP都会改变,还要老是修改配置文件的,过于繁琐,不方便测试。(经过Docker虚拟网络的方式能够避免此问题,当时实验的时候没有了解到)git

Docker 安装

若是已经安装Docker请忽略此步骤github

  1. Docker支持如下的CentOS版本:
  2. CentOS 7 (64-bit):要求系统为64位、系统内核版本为 3.10 以上。
  3. CentOS 6.5(64-bit)或更高的版本:要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。
  4. CentOS 仅发行版本中的内核支持 Docker。

yum安装

Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看上文的前提条件来验证你的CentOS 版本是否支持 Docker 。sql

# 查看内核版本
$ uname -a
复制代码
#安装 Docker
$ yum -y install docker
复制代码
#启动 Docker 后台服务
$ service docker start
复制代码
# 因为本地没有hello-world这个镜像,因此会下载一个hello-world的镜像,并在容器内运行。
$ docker run hello-world
复制代码

脚本安装

  1. 使用 sudo 或 root 权限登陆 Centos。
  2. 确保 yum 包更新到最新。
$ sudo yum update
复制代码
  1. 获取并执行 Docker 安装脚本。
$ curl -fsSL https://get.docker.com -o get-docker.sh
# 执行这个脚本会添加 docker.repo 源并安装 Docker。
$ sudo sh get-docker.sh
复制代码

启动Docker

$ sudo systemctl start docker
复制代码
# 验证 docker 是否安装成功并在容器中执行一个测试的镜像。
$ sudo docker run hello-world
$ docker ps
复制代码

镜像加速

开始让我配置国内镜像源的时候我是拒绝的,可是使用以后发现那下载速度 duang~ 的一下就上去了。因此强烈建议你们配置国内镜像源。 打开/建立 /etc/docker/daemon.json 文件,添加如下内容:docker

{
  "registry-mirrors": ["http://hub-mirror.c.163.com"]
}
复制代码

Zookeeper集群搭建

Zookeeper镜像:zookeeper:3.4json

镜像准备

$ docker pull zookeeper:3.4
复制代码

查找镜像能够去 hub.docker.com/ docker pull images:TAG // 表明拉取 TAG 版本的 image 镜像安全

创建独立Zookeeper容器

咱们首先用最简单的方式建立一个独立的Zookeeper节点,而后咱们根据这个例子建立出其余的节点。bash

$ docker run --name zookeeper -p 2181:2181 -d zookeeper:3.4
复制代码

默认的,容器内配置文件在, /conf/zoo.cfg,数据和日志目录默认在 /data/datalog,须要的话能够将上述目录映射到宿主机。 参数解释

  1. --name:指定容器名字
  2. -p:为容器暴露出来的端口分配端口号
  3. -d:在后台运行容器并打印容器ID

集群搭建

其它节点的Zookeeper容器建立方式与建立独立容器相似,须要注意的是,要分别指定节点的id和修改文件中多节点的配置,相应的建立命令以下:

新建docker网络

$ docker network create zoo_kafka
$ docker network ls
复制代码

Zookeeper容器1

$ docker run -d \
     --restart=always \
     -v /opt/docker/zookeeper/zoo1/data:/data \
     -v /opt/docker/zookeeper/zoo1/datalog:/datalog \
     -e ZOO_MY_ID=1 \
     -p 2181:2181 \
     -e ZOO_SERVERS="server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888" \
     --name=zoo1 \
     --net=viemall-zookeeper \
     --privileged \
     zookeeper:3.4
复制代码

Zookeeper容器2

$ docker run -d \
     --restart=always \
     -v /opt/docker/zookeeper/zoo2/data:/data \
     -v /opt/docker/zookeeper/zoo2/datalog:/datalog \
     -e ZOO_MY_ID=2 \
     -p 2182:2181 \
     -e ZOO_SERVERS="server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888" \
     --name=zoo2 \
     --net=viemall-zookeeper \
     --privileged \
     zookeeper:3.4
复制代码

Zookeeper容器3

$ docker run -d \
     --restart=always \
     -v /opt/docker/zookeeper/zoo3/data:/data \
     -v /opt/docker/zookeeper/zoo3/datalog:/datalog \
     -e ZOO_MY_ID=3 \
     -p 2183:2181 \
     -e ZOO_SERVERS="server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888" \
     --name=zoo3 \
     --net=viemall-zookeeper \
     --privileged \
     zookeeper:3.4
复制代码

这种方式虽然也实现了咱们想要的,可是步骤过于繁琐,并且维护起来麻烦(懒癌晚期),因此咱们使用 docker-compose 的方式来实现。

docker-compose 搭建zookeeper集群

新建docker网络

$ docker network create --driver bridge --subnet 172.23.0.0/25 --gateway 172.23.0.1  zoo_kafka
$ docker network ls
复制代码

编写 docker-compose.yml 脚本

使用方式:

  1. 安装 docker-compose
# 获取脚本
$ curl -L https://github.com/docker/compose/releases/download/1.25.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 赋予执行权限
$chmod +x /usr/local/bin/docker-compose
复制代码
  1. 任意目录下新建 docker-compose.yml 文件,复制如下内容
  2. 执行命令 docker-compose up -d

命令对照

命令 解释
docker-compose up 启动全部容器
docker-compose up -d 后台启动并运行全部容器
docker-compose up --no-recreate -d 不从新建立已经中止的容器
docker-compose up -d test2 只启动test2这个容器
docker-compose stop 中止容器
docker-compose start 启动容器
docker-compose down 中止并销毁容器

docker-compose.yml下载地址:github.com/JacianLiu/d… docker-compose.yml详情

version: '2'
services:
 zoo1:
 image: zookeeper:3.4 # 镜像名称
 restart: always # 当发生错误时自动重启
 hostname: zoo1
 container_name: zoo1
 privileged: true
 ports: # 端口
 - 2181:2181
 volumes: # 挂载数据卷
 - ./zoo1/data:/data
 - ./zoo1/datalog:/datalog 
 environment:
 TZ: Asia/Shanghai
 ZOO_MY_ID: 1 # 节点ID
 ZOO_PORT: 2181 # zookeeper端口号
 ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888 # zookeeper节点列表
 networks:
 default:
 ipv4_address: 172.23.0.11

 zoo2:
 image: zookeeper:3.4
 restart: always
 hostname: zoo2
 container_name: zoo2
 privileged: true
 ports:
 - 2182:2181
 volumes:
 - ./zoo2/data:/data
 - ./zoo2/datalog:/datalog
 environment:
 TZ: Asia/Shanghai
 ZOO_MY_ID: 2
 ZOO_PORT: 2181
 ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
 networks:
 default:
 ipv4_address: 172.23.0.12

 zoo3:
 image: zookeeper:3.4
 restart: always
 hostname: zoo3
 container_name: zoo3
 privileged: true
 ports:
 - 2183:2181
 volumes:
 - ./zoo3/data:/data
 - ./zoo3/datalog:/datalog
 environment:
 TZ: Asia/Shanghai
 ZOO_MY_ID: 3
 ZOO_PORT: 2181
 ZOO_SERVERS: server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
 networks:
 default:
 ipv4_address: 172.23.0.13

networks:
 default:
 external:
 name: zoo_kafka
复制代码

验证

从图中咱们能够看出,有一个Leader,两个Flower,至此咱们的Zookeeper集群就已经搭建好了

Zookeeper

Kafka集群搭建

有了上面的基础,再去搞Kafka集群仍是问题吗?其实就是几个变量值不一样而已。

有了上边的例子,就不费劲去搞单节点的Kafka了,直接使用docker-compose的方式,部署三个节点,其实方式大同小异,上边也说到,其实就是一些属性不一样而已;这时候咱们就不须要再去新建 Docker 网络了,直接使用前边搭建 Zookeeper 集群时建立的网络便可!

环境准备

Kafka镜像:wurstmeister/kafka Kafka-Manager镜像:sheepkiller/kafka-manager

# 不指定版本默认拉取最新版本的镜像
docker pull wurstmeister/kafka
docker pull sheepkiller/kafka-manager
复制代码

编写 docker-compose.yml 脚本

使用方式:

  1. 安装 docker-compose
# 获取脚本
$ curl -L https://github.com/docker/compose/releases/download/1.25.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 赋予执行权限
$chmod +x /usr/local/bin/docker-compose
复制代码
  1. 任意目录下新建 docker-compose.yml 文件,复制如下内容
  2. 执行命令 docker-compose up -d

命令对照

命令 解释
docker-compose up 启动全部容器
docker-compose up -d 后台启动并运行全部容器
docker-compose up --no-recreate -d 不从新建立已经中止的容器
docker-compose up -d test2 只启动test2这个容器
docker-compose stop 中止容器
docker-compose start 启动容器
docker-compose down 中止并销毁容器

docker-compose.yml下载地址:github.com/JacianLiu/d… docker-compose.yml详细内容

version: '2'

services:
 broker1:
 image: wurstmeister/kafka
 restart: always
 hostname: broker1
 container_name: broker1
 privileged: true
 ports:
 - "9091:9092"
 environment:
 KAFKA_BROKER_ID: 1
 KAFKA_LISTENERS: PLAINTEXT://broker1:9092
 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker1:9092
 KAFKA_ADVERTISED_HOST_NAME: broker1
 KAFKA_ADVERTISED_PORT: 9092
 KAFKA_ZOOKEEPER_CONNECT: zoo1:2181/kafka1,zoo2:2181/kafka1,zoo3:2181/kafka1
 JMX_PORT: 9988
 volumes:
 - /var/run/docker.sock:/var/run/docker.sock
 - ./broker1:/kafka/kafka\-logs\-broker1
 external_links:
 - zoo1
 - zoo2
 - zoo3
 networks:
 default:
 ipv4_address: 172.23.0.14

 broker2:
 image: wurstmeister/kafka
 restart: always
 hostname: broker2
 container_name: broker2
 privileged: true
 ports:
 - "9092:9092"
 environment:
 KAFKA_BROKER_ID: 2
 KAFKA_LISTENERS: PLAINTEXT://broker2:9092
 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker2:9092
 KAFKA_ADVERTISED_HOST_NAME: broker2
 KAFKA_ADVERTISED_PORT: 9092
 KAFKA_ZOOKEEPER_CONNECT: zoo1:2181/kafka1,zoo2:2181/kafka1,zoo3:2181/kafka1
 JMX_PORT: 9988
 volumes:
 - /var/run/docker.sock:/var/run/docker.sock
 - ./broker2:/kafka/kafka\-logs\-broker2
 external_links:  # 链接本compose文件之外的container
 - zoo1
 - zoo2
 - zoo3
 networks:
 default:
 ipv4_address: 172.23.0.15

 broker3:
 image: wurstmeister/kafka
 restart: always
 hostname: broker3
 container_name: broker3
 privileged: true
 ports:
 - "9093:9092"
 environment:
 KAFKA_BROKER_ID: 3
 KAFKA_LISTENERS: PLAINTEXT://broker3:9092
 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker3:9092
 KAFKA_ADVERTISED_HOST_NAME: broker3
 KAFKA_ADVERTISED_PORT: 9092
 KAFKA_ZOOKEEPER_CONNECT: zoo1:2181/kafka1,zoo2:2181/kafka1,zoo3:2181/kafka1
 JMX_PORT: 9988
 volumes:
 - /var/run/docker.sock:/var/run/docker.sock
 - ./broker3:/kafka/kafka\-logs\-broker3
 external_links:  # 链接本compose文件之外的container
 - zoo1
 - zoo2
 - zoo3
 networks:
 default:
 ipv4_address: 172.23.0.16

 kafka-manager:
 image: sheepkiller/kafka-manager:latest
 restart: always
 container_name: kafka-manager
 hostname: kafka-manager
 ports:
 - "9000:9000"
 links:            # 链接本compose文件建立的container
 - broker1
 - broker2
 - broker3
 external_links:   # 链接本compose文件之外的container
 - zoo1
 - zoo2
 - zoo3
 environment:
 ZK_HOSTS: zoo1:2181/kafka1,zoo2:2181/kafka1,zoo3:2181/kafka1
 KAFKA_BROKERS: broker1:9092,broker2:9092,broker3:9092
 APPLICATION_SECRET: letmein
 KM_ARGS: -Djava.net.preferIPv4Stack=true
 networks:
 default:
 ipv4_address: 172.23.0.10

networks:
 default:
 external:   # 使用已建立的网络
 name: zoo_kafka
复制代码

验证

咱们打开kafka-manager的管理页面,访问路径是,宿主机ip:9000;

Kafka-Manager
若是所示,填写上 Zookeeper集群的地址,划到最下边点击 save 点击刚刚添加的集群,能够看到,集群中有三个节点
Kafka-Cluster

搭建过程当中遇到的问题

  1. 挂载数据卷无限重启,查看log提示:chown: changing ownership of ‘/var/lib/mysql/....‘: Permission denied 解决方式:
    • 在docker run中加入 --privileged=true 给容器加上特定权限
    • 临时关闭selinux: setenforce 0
    • 添加selinux规则,改变要挂载的目录的安全性文本
  2. kafka-manager报jmx相关错误, 解决方法:
    • 在每个kafka节点加上环境变量 JMX_PORT=端口
    • 加上以后发现连不上,又是网络链接的问题,因而又把每一个jmx端口暴露出来,而后fire-wall放行, 解决问题。
    • KAFKA_ADVERTISED_HOST_NAME这个最好设置宿主机的ip,宿主机之外的代码或者工具来链接,后面的端口也须要设置暴露的端口。
[error] k.m.j.KafkaJMX$ - Failed to connect to service:jmx:rmi:///jndi/rmi://9.11.8.48:-1/jmxrmi java.lang.IllegalArgumentException: requirement failed: No jmx port but jmx polling enabled!
复制代码
  1. 在容器中查看topic时报如下错误(不只仅是topic的命令,好像全部的都会出错)
$ bin/kafka-topics.sh --list --zookeeper zoo1:2181/kafka1,zoo2:2181/kafka1,zoo3:2181/kafka1
# 如下是错误
Error: Exception thrown by the agent : java.rmi.server.ExportException: Port already in use: 7203; nested exception is:
        java.net.BindException: Address already in use
复制代码

解决方法: 在命令前加上unset JMX_PORT;指令,上边的命令改造为:

$ unset JMX_PORT;bin/kafka-topics.sh --list --zookeeper zoo1:2181/kafka1,zoo2:2181/kafka1,zoo3:2181/kafka1
复制代码

附:Docker经常使用指令

# 查看全部镜像
docker images
# 查看全部运行中的容器
docker ps
# 查看全部容器
docker ps -a
# 获取全部容器ip
$ docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
# 查看容器内部日志
$ docker logs -f <容器ID>
# 进入容器内部
$ docker exec -it <容器ID> /bin/basj
# 建立容器 -d表明后台启动
docker run --name <容器名称> -e <参数> -v <挂载数据卷> <容器ID>
# 重启容器
docker restart <容器ID>
# 关闭容器
docker stop <容器id>
# 运行容器
docker start <容器id>
复制代码
相关文章
相关标签/搜索