Docker 部署 Kafka Eagle(EFAK)单机

大纲

前言

本文将介绍使用 Docker-Compose 部署 Kafka-Eagle(EFAK)的单机服务,实现对 Kafka 集群的管理和监控。

Kafka Eagle(EFAK)的介绍

Kafka Eagle(现已改名为 EFAK,Eagle For Apache Kafka)是一款国产开源 Kafka 集群监控系统,可以用来监视 Kafka 集群的 Broker 状态、Topic 信息、IO、内存、Consumer 线程、偏移量等信息,并进行可视化图表展示。独特的 KQL 还可以通过 SQL 在线查询 Kafka 中的数据。Kafka Eagle 自身支持单机和集群两种方式进行部署,在企业的生产环境中使用得比较多,尤其是大规模 Kafka 集群环境。

官方资源

部署规划

组件版本部署方式说明
ZooKeeper3.8.4Docker-Compose 集群(三节点)
Kafka3.9.0Docker-Compose 集群(三节点)
MySQL8.4.2Docker-Compose 单机
Kafka Eagle(EFAK)3.0.1Docker-Compose 单机

准备工作

在部署 Kafka Eagle 之前,需要将 Kafka 集群和 MySQL 提前部署好。值得一提的是,如果项目中已有 Kafka 集群和 MySQL 服务正在运行,则可以忽略跳过二者的部署操作。

MySQL 部署

提示

  • Kafka Eagle(EFAK)需要一个数据库来存储其配置数据,如用户数据、Kafka 集群的监控指标数据等。
  • 在默认情况下,Kafka Eagle(EFAK)使用的是 SQLite,而 SQLite 是存储在 EFAK 安装位置的嵌入式数据库。

Kafka 集群部署

提示

  • 本文使用的 Kafka 集群是依赖于 Zookeeper 集群的,因此需要将 Zookeeper 集群提前搭建起来。
  • 值得一提的是,从 Kafka 2.8.0 版本开始,Kafka 自身实现了 Raft 分布式一致性机制,这意味着 Kafka 集群是可以脱离 ZooKeeper 独立运行的。

完整的 YML 配置

特别注意

下述 docker-compose.yml 配置文件的内容可以直接复用,只需要简单更改数据卷(volumes)的配置,并将 192.168.56.112 更改为你自己宿主机的 IP 地址即可。

严格按照上述教程,通过 Docker-Compose 成功部署 Kafka 集群和 MySQL 后,docker-compose.yml 配置文件的完整内容如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
version: '3.5'

services:
mysql:
image: mysql:8.4.2
container_name: mysql
command: ["mysqld", "--mysql-native-password=ON"]
restart: always
ports:
- 3306:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
volumes:
- /usr/local/mysql:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- distributed-network

zookeeper01:
image: zookeeper:3.8.4
container_name: zookeeper01
restart: always
hostname: zookeeper01
ports:
- 2181:2181
environment:
TZ: Asia/Shanghai
ZOO_MY_ID: 1
ZOO_PORT: 2181
ZOO_4LW_COMMANDS_WHITELIST: ruok
ZOO_SERVERS: server.1=zookeeper01:2888:3888;2181 server.2=zookeeper02:2888:3888;2181 server.3=zookeeper03:2888:3888;2181
healthcheck:
test: ["CMD", "sh", "-c", "echo ruok | nc localhost 2181 | grep imok"]
interval: 30s
timeout: 10s
retries: 5
start_period: 20s
volumes:
- /usr/local/zookeeper/zookeeper01/data:/data
- /usr/local/zookeeper/zookeeper01/datalog:/datalog
networks:
- distributed-network

zookeeper02:
image: zookeeper:3.8.4
container_name: zookeeper02
restart: always
hostname: zookeeper02
ports:
- 2182:2181
environment:
TZ: Asia/Shanghai
ZOO_MY_ID: 2
ZOO_PORT: 2181
ZOO_4LW_COMMANDS_WHITELIST: ruok
ZOO_SERVERS: server.1=zookeeper01:2888:3888;2181 server.2=zookeeper02:2888:3888;2181 server.3=zookeeper03:2888:3888;2181
healthcheck:
test: ["CMD", "sh", "-c", "echo ruok | nc localhost 2181 | grep imok"]
interval: 30s
timeout: 10s
retries: 5
start_period: 20s
volumes:
- /usr/local/zookeeper/zookeeper02/data:/data
- /usr/local/zookeeper/zookeeper02/datalog:/datalog
networks:
- distributed-network

zookeeper03:
image: zookeeper:3.8.4
container_name: zookeeper03
restart: always
hostname: zookeeper03
ports:
- 2183:2181
environment:
TZ: Asia/Shanghai
ZOO_MY_ID: 3
ZOO_PORT: 2181
ZOO_4LW_COMMANDS_WHITELIST: ruok
ZOO_SERVERS: server.1=zookeeper01:2888:3888;2181 server.2=zookeeper02:2888:3888;2181 server.3=zookeeper03:2888:3888;2181
healthcheck:
test: ["CMD", "sh", "-c", "echo ruok | nc localhost 2181 | grep imok"]
interval: 30s
timeout: 10s
retries: 5
start_period: 20s
volumes:
- /usr/local/zookeeper/zookeeper03/data:/data
- /usr/local/zookeeper/zookeeper03/datalog:/datalog
networks:
- distributed-network

kafka01:
image: bitnami/kafka:3.9.0
container_name: kafka01
restart: always
hostname: kafka01
ports:
- 9093:9093
environment:
TZ: Asia/Shanghai
KAFKA_CFG_NODE_ID: 1
KAFKA_CFG_LISTENERS: PLAINTEXT://:9093
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.56.112:9093
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181/kafka
ALLOW_PLAINTEXT_LISTENER: yes
healthcheck:
test: ["CMD", "kafka-topics.sh", "--bootstrap-server", "kafka01:9093,kafka02:9094,kafka03:9095", "--list"]
interval: 30s
timeout: 15s
retries: 5
start_period: 30s
volumes:
- /usr/local/kafka/kafka01:/bitnami/kafka
depends_on:
zookeeper01:
condition: service_healthy
zookeeper02:
condition: service_healthy
zookeeper03:
condition: service_healthy
networks:
- distributed-network

kafka02:
image: bitnami/kafka:3.9.0
container_name: kafka02
restart: always
hostname: kafka02
ports:
- 9094:9094
environment:
TZ: Asia/Shanghai
KAFKA_CFG_NODE_ID: 2
KAFKA_CFG_LISTENERS: PLAINTEXT://:9094
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.56.112:9094
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181/kafka
ALLOW_PLAINTEXT_LISTENER: yes
healthcheck:
test: ["CMD", "kafka-topics.sh", "--bootstrap-server", "kafka01:9093,kafka02:9094,kafka03:9095", "--list"]
interval: 30s
timeout: 15s
retries: 5
start_period: 30s
volumes:
- /usr/local/kafka/kafka02:/bitnami/kafka
depends_on:
zookeeper01:
condition: service_healthy
zookeeper02:
condition: service_healthy
zookeeper03:
condition: service_healthy
networks:
- distributed-network

kafka03:
image: bitnami/kafka:3.9.0
container_name: kafka03
restart: always
hostname: kafka03
ports:
- 9095:9095
environment:
TZ: Asia/Shanghai
KAFKA_CFG_NODE_ID: 3
KAFKA_CFG_LISTENERS: PLAINTEXT://:9095
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.56.112:9095
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181/kafka
ALLOW_PLAINTEXT_LISTENER: yes
healthcheck:
test: ["CMD", "kafka-topics.sh", "--bootstrap-server", "kafka01:9093,kafka02:9094,kafka03:9095", "--list"]
interval: 30s
timeout: 15s
retries: 5
start_period: 30s
volumes:
- /usr/local/kafka/kafka03:/bitnami/kafka
depends_on:
zookeeper01:
condition: service_healthy
zookeeper02:
condition: service_healthy
zookeeper03:
condition: service_healthy
networks:
- distributed-network

networks:
distributed-network:
driver: bridge

Kafka Eagle 单机部署

初始化数据库

  • 创建数据库,用于 Kafka Eagle(EFAK)存储 Kafka 的监控指标数据
1
2
-- 创建数据库
CREATE DATABASE efak DEFAULT CHARACTER SET utf8mb4;
  • 创建数据库用户并授权访问,用于 Kafka Eagle(EFAK)连接 MySQL
1
2
3
4
5
6
7
8
-- 创建用户
CREATE USER 'efak'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

-- 用户授权
GRANT ALL PRIVILEGES ON efak.* TO 'efak'@'%';

-- 刷新权限
FLUSH PRIVILEGES;

提示

  • (1) 在初始化 MySQL 数据库时,只需要创建数据库,而不需要手动创建数据库表。这是因为 Kafka Eagle(EFAK)会在启动的时候自动创建所需的数据库表,前提是 Kafka Eagle(EFAK)用于连接 MySQL 的用户有对应的数据库操作权限。
  • (2) 值得一提的是,当不使用 MySQL 来存储 Kafka 的监控指标数据时,Kafka Eagle(EFAK)默认会使用 SQlite 作为数据库。

创建容器

特别注意

  • 下述配置内容是在上面用于部署 Kafka 集群和 MySQL 的 docker-compose.yml 配置文件的基础上更改而来的,其主要变化有以下几点:
  • (1) 新增 Kafka Eagle(EFAK)的配置
  • (2) Kafka 容器新增 JMX 服务的配置
  • (3) 去掉 Kafka 容器启动时的健康检测配置(healthcheck
  • (4) 更改 ZooKeeper 容器的 "四字命令" 配置为 mntr,conf,ruok,stat

为什么要去掉 Kafka 容器启动时的健康检测

  • 这是因为 Kafka Eagle(EFAK)需要依赖 Kafka 的 JMX 服务来对 Kafaka 实现监控,可是一旦启用 JMX,在 Kafka 容器内部不能再执行类似 kafka-topics.sh --bootstrap-server xxx --list 这样的命令,否则会抛出 JMX 端口占用冲突的异常。

为什么要更改 ZooKeeper 容器的四字命令配置

  • 这是因为 Kafka Eagle(EFAK)需要依赖 ZooKeeper 的 "四字命令" 来对 ZooKeeper 实现监控。在默认情况下,ZooKeeper 会禁用 "四字命令",这样会导致 Kafka Eagle(EFAK)无法正常监控 ZooKeeper 的运行状态,所以需要启用下面这几个 "四字命令"。
  • ruok:用于检查 Zookeeper 服务是否正常运行。
  • conf:返回当前 Zookeeper 集群的配置,例如节点配置、数据目录等。
  • stat:返回 Zookeeper 节点的状态,包括当前连接数、Zookeeper 节点的版本、日志文件信息等。
  • mntr:返回 Zookeeper 的监控信息,包括各个节点的状态、同步信息等,通常用于健康检测和性能监控。
  • 更改上面用于部署 Kafka 集群和 MySQL 的 docker-compose.yml 配置文件,并添加 Kafka Eagle(EFAK)的配置,完整的配置内容如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
version: '3.5'

services:
mysql:
image: mysql:8.4.2
container_name: mysql
command: ["mysqld", "--mysql-native-password=ON"]
restart: always
ports:
- 3306:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
volumes:
- /usr/local/mysql:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h localhost"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- distributed-network

zookeeper01:
image: zookeeper:3.8.4
container_name: zookeeper01
restart: always
hostname: zookeeper01
ports:
- 2181:2181
environment:
TZ: Asia/Shanghai
ZOO_MY_ID: 1
ZOO_PORT: 2181
ZOO_4LW_COMMANDS_WHITELIST: mntr,conf,ruok,stat
ZOO_SERVERS: server.1=zookeeper01:2888:3888;2181 server.2=zookeeper02:2888:3888;2181 server.3=zookeeper03:2888:3888;2181
healthcheck:
test: ["CMD", "sh", "-c", "echo ruok | nc localhost 2181 | grep imok"]
interval: 30s
timeout: 10s
retries: 5
start_period: 20s
volumes:
- /usr/local/zookeeper/zookeeper01/data:/data
- /usr/local/zookeeper/zookeeper01/datalog:/datalog
networks:
- distributed-network

zookeeper02:
image: zookeeper:3.8.4
container_name: zookeeper02
restart: always
hostname: zookeeper02
ports:
- 2182:2181
environment:
TZ: Asia/Shanghai
ZOO_MY_ID: 2
ZOO_PORT: 2181
ZOO_4LW_COMMANDS_WHITELIST: mntr,conf,ruok,stat
ZOO_SERVERS: server.1=zookeeper01:2888:3888;2181 server.2=zookeeper02:2888:3888;2181 server.3=zookeeper03:2888:3888;2181
healthcheck:
test: ["CMD", "sh", "-c", "echo ruok | nc localhost 2181 | grep imok"]
interval: 30s
timeout: 10s
retries: 5
start_period: 20s
volumes:
- /usr/local/zookeeper/zookeeper02/data:/data
- /usr/local/zookeeper/zookeeper02/datalog:/datalog
networks:
- distributed-network

zookeeper03:
image: zookeeper:3.8.4
container_name: zookeeper03
restart: always
hostname: zookeeper03
ports:
- 2183:2181
environment:
TZ: Asia/Shanghai
ZOO_MY_ID: 3
ZOO_PORT: 2181
ZOO_4LW_COMMANDS_WHITELIST: mntr,conf,ruok,stat
ZOO_SERVERS: server.1=zookeeper01:2888:3888;2181 server.2=zookeeper02:2888:3888;2181 server.3=zookeeper03:2888:3888;2181
healthcheck:
test: ["CMD", "sh", "-c", "echo ruok | nc localhost 2181 | grep imok"]
interval: 30s
timeout: 10s
retries: 5
start_period: 20s
volumes:
- /usr/local/zookeeper/zookeeper03/data:/data
- /usr/local/zookeeper/zookeeper03/datalog:/datalog
networks:
- distributed-network

kafka01:
image: bitnami/kafka:3.9.0
container_name: kafka01
restart: always
hostname: kafka01
ports:
- 9093:9093
- 19999:19999
environment:
TZ: Asia/Shanghai
KAFKA_CFG_NODE_ID: 1
KAFKA_CFG_LISTENERS: PLAINTEXT://:9093
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.56.112:9093
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181/kafka
ALLOW_PLAINTEXT_LISTENER: yes
KAFKA_JMX_PORT: 19999
KAFKA_JMX_OPTS: '-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka01 -Dcom.sun.management.jmxremote.port=19999'
volumes:
- /usr/local/kafka/kafka01:/bitnami/kafka
depends_on:
zookeeper01:
condition: service_healthy
zookeeper02:
condition: service_healthy
zookeeper03:
condition: service_healthy
networks:
- distributed-network

kafka02:
image: bitnami/kafka:3.9.0
container_name: kafka02
restart: always
hostname: kafka02
ports:
- 9094:9094
- 29999:29999
environment:
TZ: Asia/Shanghai
KAFKA_CFG_NODE_ID: 2
KAFKA_CFG_LISTENERS: PLAINTEXT://:9094
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.56.112:9094
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181/kafka
ALLOW_PLAINTEXT_LISTENER: yes
KAFKA_JMX_PORT: 29999
KAFKA_JMX_OPTS: '-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka02 -Dcom.sun.management.jmxremote.port=29999'
volumes:
- /usr/local/kafka/kafka02:/bitnami/kafka
depends_on:
zookeeper01:
condition: service_healthy
zookeeper02:
condition: service_healthy
zookeeper03:
condition: service_healthy
networks:
- distributed-network

kafka03:
image: bitnami/kafka:3.9.0
container_name: kafka03
restart: always
hostname: kafka03
ports:
- 9095:9095
- 39999:39999
environment:
TZ: Asia/Shanghai
KAFKA_CFG_NODE_ID: 3
KAFKA_CFG_LISTENERS: PLAINTEXT://:9095
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.56.112:9095
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181/kafka
ALLOW_PLAINTEXT_LISTENER: yes
KAFKA_JMX_PORT: 39999
KAFKA_JMX_OPTS: '-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka03 -Dcom.sun.management.jmxremote.port=39999'
volumes:
- /usr/local/kafka/kafka03:/bitnami/kafka
depends_on:
zookeeper01:
condition: service_healthy
zookeeper02:
condition: service_healthy
zookeeper03:
condition: service_healthy
networks:
- distributed-network

efak:
image: nickzurich/efak:3.0.1
container_name: efak
restart: always
ports:
- 8048:8048
environment:
TZ: Asia/Shanghai
EFAK_CLUSTER_ZK_LIST: zookeeper01:2181,zookeeper02:2181,zookeeper03:2181/kafka
EFAK_CLUSTER_KAFKA_EAGLE_OFFSET_STORAGE: kafka
EFAK_DB_USERNAME: efak
EFAK_DB_PASSWORD: 123456
EFAK_DB_DRIVER: com.mysql.cj.jdbc.Driver
EFAK_DB_URL: jdbc:mysql://mysql:3306/efak?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
depends_on:
- mysql
- kafka01
- kafka02
- kafka03
networks:
- distributed-network

networks:
distributed-network:
driver: bridge

重要参数说明

  • EFAK_CLUSTER_ZK_LIST:指定 ZooKeeper 集群的节点列表。
  • EFAK_CLUSTER_KAFKA_EAGLE_OFFSET_STORAGE:指定 Kafka 集群存储 Offset 的位置。
  • EFAK_DB_USERNAME:指定 Kafka Eagle(EFAK)连接数据库的用户名。
  • EFAK_DB_PASSWORD:指定 Kafka Eagle(EFAK)连接数据库的密码。
  • EFAK_DB_DRIVER:指定 Kafka Eagle(EFAK)连接数据库的驱动。
  • EFAK_DB_URL:指定 Kafka Eagle(EFAK)连接数据库的 URL。
  • KAFKA_JMX_PORT:指定 Kafka 使用的 JMX 监听端口。
  • KAFKA_JMX_OPTS:通过 Java 的系统属性配置 JMX 的详细选项,比如是否启用 JMX、RMI 主机名、RMI 端口、JMX 的身份认证、JMX 的 SSL 证书 等。
  • KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://192.168.56.112:9095这里的 192.168.56.112 是宿主机的 IP 地址或者公网 IP 地址。如果配置错误,会导致外部 Kafka 客户端无法正常连接 Docker 容器内的 Kafka 服务器
  • 创建并启动 Kafka Eagle(EFAK) 容器(请必须保证操作系统有 2G 空闲内存,否则容器会启动失败
1
sudo sudo docker-compose up -d

特别注意

  • 当不使用 MySQL 来存储 Kafka 的监控指标数据时,Kafka Eagle(EFAK)默认会使用 SQlite 作为数据库;此时如果希望持久化容器内的 SQlite 数据文件,可以通过数据卷挂载 Kafka Eagle(EFAK)容器内的 /hadoop/efak/db/ke.db 文件到宿主机内。
  • 在停止 Kafka 集群时,一定要等 Kafka 所有节点进程全部停止后,再停止 Zookeeper 集群。因为 Zookeeper 集群当中记录着 Kafka 集群的相关信息,Zookeeper 集群一旦先停止,Kafka 集群就没有办法再获取停止进程的信息,最后只能手动杀死 Kafka 进程了。

验证容器

查看容器状态

  • 查看所有 Kafka Eagle(EFAK) 容器的运行状态
1
sudo docker ps -a
1
2
3
4
5
6
7
8
ebc5136d2afb   nickzurich/efak:3.0.1   "entrypoint.sh"          44 seconds ago   Up 42 seconds             0.0.0.0:8048->8048/tcp, :::8048->8048/tcp, 8080/tcp                       efak
ed37bf8c8eac bitnami/kafka:3.9.0 "/opt/bitnami/script…" 17 minutes ago Up 16 minutes 9092/tcp, 0.0.0.0:9093->9093/tcp, :::9093->9093/tcp kafka01
c09ca638d783 bitnami/kafka:3.9.0 "/opt/bitnami/script…" 17 minutes ago Up 16 minutes 9092/tcp, 0.0.0.0:9095->9095/tcp, :::9095->9095/tcp kafka03
9f2636e03ad3 bitnami/kafka:3.9.0 "/opt/bitnami/script…" 17 minutes ago Up 16 minutes 9092/tcp, 0.0.0.0:9094->9094/tcp, :::9094->9094/tcp kafka02
d82f6b11979c zookeeper:3.8.4 "/docker-entrypoint.…" 17 minutes ago Up 17 minutes (healthy) 2888/tcp, 3888/tcp, 8080/tcp, 0.0.0.0:2182->2181/tcp, :::2182->2181/tcp zookeeper02
639310a6bdd2 zookeeper:3.8.4 "/docker-entrypoint.…" 17 minutes ago Up 17 minutes (healthy) 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, :::2181->2181/tcp, 8080/tcp zookeeper01
9d255997e30e zookeeper:3.8.4 "/docker-entrypoint.…" 17 minutes ago Up 17 minutes (healthy) 2888/tcp, 3888/tcp, 8080/tcp, 0.0.0.0:2183->2181/tcp, :::2183->2181/tcp zookeeper03
3361ac6e2d10 mysql:8.4.2 "docker-entrypoint.s…" 17 minutes ago Up 17 minutes (healthy) 33060/tcp, 0.0.0.0:3309->3306/tcp, :::3309->3306/tcp mysql
  • 若 Kafka Eagle(EFAK)容器启动失败,可以通过以下命令查看容器的启动日志来排查问题
1
2
# 查看启动日志
sudo docker logs -f --tail 100 efak

访问管理页面

  • (1) 浏览器通过 http://192.168.56.112:8048 访问 Kafka Eagle(EFAK)的控制台管理页面(如下所示),默认的登录账号和密码是 admin/123456,请记得将 192.168.56.112 更改为你自己宿主机的 IP 地址。

  • (2) 登录 Kafka Eagle(EFAK)的控制台后,浏览器通过 http://192.168.56.112:8048/tv 就可以访问监控数据大屏的页面(如下所示),请记得将 192.168.56.112 更改为你自己宿主机的 IP 地址。

特别注意

  • 在默认情况下,Kafka Eagle(EFAK)的监控数据大屏页面不会实时更新显示 Kafka 集群的监控指标图表,比如 CPU 与内存的使用率、生产速率、消费速率等。
  • 如果需要在 Kafka Eagle(EFAK)的 UI 中实时显示 Kafka 集群的监控指标图表,可以通过给 Kafka Eagle(EFAK)容器添加环境变量 EFAK_METRICS_CHARTS: true 来开启该功能。
  • 值得一提的是,Kafka 集群监控指标图表的渲染和数据获取会消耗一定的资源,如果 Kafka 的集群规模较大或者系统资源有限,建议通过禁用 EFAK_METRICS_CHARTS 选项(默认禁用)来减少系统负载。
  • (3) 当 Kafka 的 JMX 服务配置正确后,浏览器通过 http://192.168.56.112:8048/cluster/kafka 就可以访问 Kafka 的监控页面(如下所示),请记得将 192.168.56.112 更改为你自己宿主机的 IP 地址。

  • (4) 当 ZooKeeper 的 “四字命令” 配置正确后,浏览器通过 http://192.168.56.112:8048/cluster/zookeeper 就可以访问 ZooKeeper 的监控页面(如下所示),请记得将 192.168.56.112 更改为你自己宿主机的 IP 地址。

Kafka Eagle 部署问题

JMX 端口占用冲突

当 Kafka 容器新增 JMX 服务的配置后,在 Kafka 容器内部执行类似 kafka-console-producer.sh --broker-list xxx --topic test 这样的命令,会抛出 JMX 端口占用冲突的异常(如下所示)。解决方法是只在 Kafka 容器外执行管理命令。

1
2
3
4
5
6
7
8
9
10
11
12
Caused by: java.rmi.server.ExportException: Port already in use: 19999; nested exception is: 
java.net.BindException: Address already in use
at java.rmi/sun.rmi.transport.tcp.TCPTransport.listen(TCPTransport.java:346)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:243)
at java.rmi/sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:415)
at java.rmi/sun.rmi.transport.LiveRef.exportObject(LiveRef.java:147)
at java.rmi/sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:235)
at java.rmi/sun.rmi.registry.RegistryImpl.setup(RegistryImpl.java:223)
at java.rmi/sun.rmi.registry.RegistryImpl.<init>(RegistryImpl.java:182)
at jdk.management.agent/sun.management.jmxremote.SingleEntryRegistry.<init>(SingleEntryRegistry.java:49)
at jdk.management.agent/sun.management.jmxremote.ConnectorBootstrap.exportMBeanServer(ConnectorBootstrap.java:859)
at jdk.management.agent/sun.management.jmxremote.ConnectorBootstrap.startRemoteConnectorServer(ConnectorBootstrap.java:480)

Kafka Eagle 集群部署

在生产环境中,往往都需要部署多个 Kafka Eagle(EFAK) 实例,以此实现高可用。Kafka Eagle(EFAK)是天生支持集群(分布式)部署的,但由于 Kafka Eagle(EFAK)官方目前构建的 Docker 镜像并不支持集群部署功能。因此,如果需要部署 Kafka Eagle(EFAK)集群,只能是手动进行部署或者自行构建 Docker 镜像来实现,其中手动部署的教程请参考 官方文档 或者 本站教程

挂载 Kafka Eagle 配置文件无效

当使用的 Kafka Eagle(EFAK)镜像是 3.0.1 版本时,不能再通过数据卷挂载配置文件到容器内的方式(如下所示)来指定 system-config.properties 配置文件。因为 Kafka Eagle(EFAK)容器在每次启动时,都会拷贝默认的 system-config.properties 配置文件进行覆盖,导致外部挂载的配置文件也被 “重置”,详见这里的脚本代码。解决办法是,在 Docker-Compose 中通过环境变量来指定 Kafka Eagle(EFAK)的配置参数。值得一提的是,Kafka Eagle(EFAK)镜像支持的所有环境变量可以从 这里 获取得到。

1
2
3
4
5
6
7
8
9
10
11
12
13
version: '3.5'

services:
efak:
image: nickzurich/efak:3.0.1
container_name: efak
restart: always
ports:
- 8048:8048
environment:
- TZ: Asia/Shanghai
volumes:
- /usr/local/efak/system-config.properties:/opt/efak/conf/system-config.properties # 挂载的配置文件不会生效,且会被覆盖修改

内存不足导致容器启动失败

在 Kafka Eagle(EFAK)的项目源码中,有一个 ke.sh 启动脚本,该脚本里面有以下一行代码:

1
export KE_JAVA_OPTS="-server -Xmx2g -Xms2g -XX:MaxGCPauseMillis=20 -XX:+UseG1GC -XX:MetaspaceSize=128m -XX:InitiatingHeapOccupancyPercent=35 -XX:G1HeapRegionSize=16M -XX:MinMetaspaceFreeRatio=50 -XX:MaxMetaspaceFreeRatio=80"

其中 JVM 参数 -Xms2g 指定了初始堆内存为 2G,因此当操作系统的空闲内存不足 2G 时,会导致 Kafka Eagle(EFAK)容器启动失败。解决办法是,更改 Shell 脚本代码并重新构建 Kafka Eagle(EFAK)镜像,或者增加机器的物理内存(强烈推荐)。

监控大屏无法实时更新显示

在 Kafka Eagle(EFAK)的控制台中访问监控大屏页面时,发现即使有生产者正在发送消息和消费者正在消费消息,Kafka 集群的监控指标图表也无法实时更新显示或者没有任何监控数据显示(如下图所示)。这是因为 Kafka Eagle(EFAK)默认禁用了 Kafka 集群的监控指标图表实时更新。

解决办法是,通过给 Kafka Eagle(EFAK)容器添加环境变量 EFAK_METRICS_CHARTS: true 来开启 Kafka 集群的监控指标图表实时更新。

1
2
3
4
5
6
7
version: '3.5'

services:
efak:
image: nickzurich/efak:3.0.1
environment:
EFAK_METRICS_CHARTS: true

特别注意

在 Kafka Eagle(EFAK)的控制台中,Kafka 集群监控指标图表的渲染和数据获取会消耗一定的资源。如果 Kafka 的集群规模较大或者系统资源有限,建议通过禁用 EFAK_METRICS_CHARTS 选项(默认禁用)来减少系统负载。

Kafka Eagle 无法监控自己

在 Kafka Eagle(EFAK)的控制台中访问 EfakServer 的监控页面时,发现无法正常显示 EfakServer 的运行状态,监控页面一直显示提示信息 Processing 或者节点状态显示为 Offline,如下图所示:

这个问题可以忽略不解决,猜测(待验证)只有当 Kafka Eagle(EFAK)以集群(分布式)模式部署时,EfakServer 的监控页面才会正常显示相关监控信息,详细说明请看 这里

无法监控 ZooKeeper 集群

在 Kafka Eagle(EFAK)的控制台中访问 ZooKeeper 的监控页面时,发现无法正常显示 ZooKeeper 的运行状态,如下图所示:

这通常是由于 ZooKeeper 容器没有配置 “四字命令” 或者 “四字命令” 配置不正确导致的,因为 Kafka Eagle(EFAK)是基于 ZooKeeper 的 “四字命令” 来实现 ZooKeeper 运行状态的监控。解决办法是,为 ZooKeeper 容器添加对应的 “四字命令” 配置,如下所示:

1
2
3
4
5
6
zookeeper:
image: zookeeper:3.8.4
ports:
- 2181:2181
environment:
ZOO_4LW_COMMANDS_WHITELIST: mntr,conf,ruok,stat

无法监控 Kafka 集群

在 Kafka Eagle(EFAK)的控制台中访问 Kafka 的监控页面时,发现无法正常显示 Kafka 的运行状态,如下图所示:

这通常是由于 Kafka 容器没有配置 JMX 服务或者 JMX 服务配置不正确导致的,因为 Kafka Eagle(EFAK)是基于 JMX 服务来实现 Kafka 运行状态的监控。解决办法是,为 Kafka 容器添加对应的 JMX 配置,如下所示:

1
2
3
4
5
6
7
8
9
10
11
version: '3.5'

services:
kafka:
image: bitnami/kafka:3.9.0
ports:
- 9092:9092
- 19999:19999 # 映射 JMX 端口
environment:
KAFKA_JMX_PORT: 19999 # 指定 JMX 端口
KAFKA_JMX_OPTS: '-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka -Dcom.sun.management.jmxremote.port=19999'

参考教程