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>
複製代碼
相關文章
相關標籤/搜索