简介:Kafka-Manager(CMAK)2.0.0.2 是面向 Kafka 运维人员、后端开发与集群管理者的可视化管理工具包,主要用于集群监控、主题与消费者组管理、在线配置调整及基于角色的权限控制,适合需要快速搭建 Kafka 管理界面的测试与生产环境。压缩包共 780 个文件,约 92.38MB,其中 604 个 html 页面构成 Web 管理界面,101 个 jar 为运行依赖,另含 js、css、字体、图片等前端静态资源,以及 bat 启动脚本、conf 配置文件和 md 说明文档,目录结构完整。已有 392 人学习下载。该版本为预编译包,解压后可在多种 JDK 环境下运行,省去自行编译与版本适配的麻烦;借助实时节点状态、分区与副本分布展示,以及主题创建删除、消费进度查看和在线配置修改,读者可较快完成集群日常巡检、容量观察与故障定位,提升 Kafka 运维效率。
1. 9000 端口先占坑,装完打不开的那次
kafka-manager(CMAK)2.0.0.2 这个 zip 解压出来就能跑,真正卡住人的从来不是安装本身,而是它默认要占 9000 端口、默认要去连 broker 的 9999 JMX、默认认一个你没指定的 JDK。最常见的翻车长这样:包解压对了、application.conf也改了,浏览器打开一片空白,回头翻日志才发现机器上 9000 早被别的服务占了,CMAK 悄没声地起在别的端口上,而前台输出里那行Listening for HTTP on /0.0.0.0:9000压根没人看。这套环境适合手里已经有一两个 Kafka 集群、想找个网页把 topic 列表和消费组 lag 看明白的人,也适合刚接手一套别人搭的集群、连有几个 broker 都还没数清的接手者。装不好不会炸集群,但会让你在排障时少一只眼睛。
2. 版本对齐:JDK 8、ZooKeeper 3.4+ 和 Kafka 下拉框
CMAK 是个纯读侧的 Web 应用,它不碰 Kafka 的数据面,只做三件事:连 ZooKeeper 读元数据、连 broker 的 JMX 读指标、连 Kafka 读消费组 offset。这三条链路对应三套版本约束,任何一条对不上,症状都很像——页面能打开,但某块内容一直空着。所以装之前先把这张表在心里过一遍,比装完再回来猜要省事得多。
2.1 一张对照表,省掉三次重装
| 组件 | 建议版本 | 说明 |
|---|---|---|
| JDK | 8u2xx(首选)/ 11 | CMAK 自身进程用,和 Kafka 集群的 JDK 无关 |
| ZooKeeper | 3.4.10 ~ 3.6.x | 建议复用 Kafka 的 ZK,用 chroot 隔开 |
| Kafka | 0.11.0 ~ 2.4 | 页面里的版本下拉必须和集群实际版本对齐 |
| CMAK | 2.0.0.2 | 预编译 zip,不需要 sbt |
| 内存 | 2G 起 | 堆给 1G~2G,topic 上万的给 4G |
| 系统 | 主流 Linux 发行版 | 只要能跑 JDK 8 就行 |
这里要提醒一下:CMAK 连的 ZooKeeper,和 Kafka 集群用的 ZooKeeper,通常是同一个。也就是说cmak.zkhosts里填的地址,多半就是你 Kafka 配置里zookeeper.connect那一串。这不是巧合,CMAK 就是靠读/brokers/ids、/brokers/topics这些节点来判断集群长什么样的。
2.2 JDK 怎么装,8 和 11 的差别落在哪
2.0.0.2 的 jar 用 JDK 8 和 11 都能加载,社区里绝大多数人跑在 8 上,是因为踩过的坑少。JDK 11 能跑,但脚本里不显式指定-java-home时,它会去抓机器上默认那个java,一旦那台机器上还有 17 或者更新的版本,启动就是秒退。所以我的习惯是:装 JDK 8,然后在启动命令里把路径写死。
# Ubuntu / Debian 装 JDK 8 sudo apt-get update sudo apt-get install -y openjdk-8-jdk # CentOS / RHEL 走这条 # sudo yum install -y java-1.8.0-openjdk-devel # 确认装上了,输出必须是 1.8.0_xxx java -version # 记下真实路径,后面 -java-home 要用 readlink -f $(which java)readlink -f这一步别省。/usr/bin/java通常是个软链,指向/etc/alternatives/java,再指向/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java。CMAK 的-java-home参数要的是JDK 根目录,不是bin/java,你要给它/usr/lib/jvm/java-8-openjdk-amd64,多写一层jre就会报找不到 java。
注意:如果这台机器上同时有 JDK 8 和 11,别去动全局的
update-alternatives,那会连带影响机器上其他 Java 服务。CMAK 用-java-home单独指定就够了。
2.3 ZooKeeper 侧要留出来的东西
CMAK 会在 ZK 根节点下建自己的目录,存集群登记信息、收藏的 topic、用户配置这些。如果直接写在 Kafka 的 ZK 根上,根目录会变得很乱,而且以后想换一台 CMAK 或者起第二套实例,容易互相打架。常见做法是给它一个 chroot:
# 在 Kafka 自带的 zookeeper-shell 里建一个空节点 $KAFKA_HOME/bin/zookeeper-shell.sh zk1:2181 <<'EOF' create /cmak "" quit EOF建完/cmak之后,cmak.zkhosts写成zk1:2181,zk2:2181,zk3:2181?chroot=/cmak。注意这个?chroot=是 CMAK 自己的语法,不是 ZK 客户端的通用写法,写错了不会报错,只会连到根节点上去,然后你会看到一堆找不到/clusters节点的告警。
还有一个容易被忽略的点:如果 Kafka 集群本身在 ZK 上配了 chroot(比如zookeeper.connect=zk1:2181/kafka),那 CMAK 添加集群时填的 ZK 地址也要带上/kafka,否则它读的是 ZK 根,什么都读不到。这两种 chroot 是两回事,一个是 CMAK 自己的家目录,一个是 Kafka 的家目录,别混。
3. 解压到首次启动:脚本参数和 application.conf 的最小改动
拿到的是预编译 zip,里面lib/目录已经打好了所有 jar,直接解压即可,不需要 sbt 编译。这一步能省二十分钟,但也正因为跳过了编译,出问题时没有构建日志可看,只能靠启动日志,所以第一次启动务必前台跑,别上来就 nohup。
3.1 目录布局与解压位置
# 统一放 /opt 下,别解压到 /root 或 /tmp sudo mkdir -p /opt/cmak sudo unzip kafka-manager\(CMAK\)-2.0.0.2.zip -d /opt/cmak # 解压出来目录名带版本号,做个软链,以后升级只改软链 cd /opt/cmak && ls sudo ln -s /opt/cmak/cmak-2.0.0.2 /opt/cmak/current # 确认关键目录都在 ls /opt/cmak/current # bin conf lib logs解压后重点看三个地方:bin/cmak是启动脚本,conf/application.conf是唯一需要改的配置文件,lib/下一堆 jar 不用管。logs/目录可能不存在,第一次启动时脚本会自己建。
之所以建议用软链而不是直接改目录名,是因为升级的时候你只要解压新版本、把current指过去、重启进程,回滚就是把软链指回来,而不用去改 systemd 单元或者启动脚本里的路径。
3.2 application.conf 里必须改的四行
这个文件是 HOCON 格式,看着像 JSON 但不完全是,等号两边的空格无所谓,字符串的引号不能省。文件里有一大堆被注释掉的选项,别全打开,先改这四处:
# 1. ZooKeeper 地址,多节点逗号隔开,带 chroot 就接 ?chroot= cmak.zkhosts="zk1:2181,zk2:2181,zk3:2181?chroot=/cmak" # 2. 基础认证,9000 端口别裸奔 basicAuthentication.enabled=true basicAuthentication.username="admin" basicAuthentication.password="换成你自己的" basicAuthentication.realm="CMAK" # 3. 挂在反向代理子路径下时才需要,直接访问就注释着 # play.http.context="/cmak" # 4. 排查阶段开 DEBUG,稳定后改回 INFO # akka.loglevel = "DEBUG"cmak.zkhosts这四个字要认准。老版本 kafka-manager 里这个键叫kafka-manager.zkhosts,从 1.3.x 改名到 CMAK 之后就是这个新名字,拿旧文档抄配置的人经常在这里栽跟头,配置改了不生效,因为程序压根没读那一行。
basicAuthentication那三行是可选项,但只要这台机器不是纯内网隔离,我都建议开。CMAK 的权限模型很粗,登录后基本是全能操作,包括删 topic(如果你在集群配置里开了这个开关),所以认证是最后一道门槛。
play.http.context只在你用 Nginx 把它挂在https://xxx/cmak这种路径下时才需要打开。直接http://ip:9000访问的话保持注释,否则首页会 404,而且 404 得很干净,让人以为是没启动。
3.3 前台试跑一次,再交给后台
cd /opt/cmak/current # 第一次必须前台跑,盯住前 30 秒的输出 bin/cmak -Dconfig.file=conf/application.conf \ -java-home /usr/lib/jvm/java-8-openjdk-amd64 \ -Dhttp.port=9000三个参数分开说。-Dconfig.file是 Play 框架约定的配置入口,指向conf/application.conf,路径写相对或者绝对都行,但工作目录必须是 CMAK 根目录,否则它找不到conf下面的 logback 配置。-java-home是让脚本用指定 JDK 启动,前面说过,这是避开 JDK 版本坑最直接的一招。-Dhttp.port改监听端口,9000 被占的时候用它换一个,比如 19000。
看到Listening for HTTP on /0.0.0.0:9000且进程没退出,就说明起来了,Ctrl+C停掉,换成后台方式:
nohup bin/cmak -Dconfig.file=conf/application.conf \ -java-home /usr/lib/jvm/java-8-openjdk-amd64 \ -Dhttp.port=9000 \ -J-Xms1g -J-Xmx2g \ -J-Duser.timezone=Asia/Shanghai \ > /dev/null 2>&1 & # 确认进程和端口 ps -ef | grep cmak | grep -v grep ss -lntp | grep 9000-J前缀是 Play 启动脚本约定的 JVM 参数传递方式,-D是给应用自己的。-Xms1g -Xmx2g这组值不是拍的:CMAK 的堆主要花在读 ZK 节点和缓存 topic 列表上,几百个 topic 的集群 1G 够用,上万个 topic 的集群 2G 起,给 4G 也不过分。给小了不会立刻报错,而是跑几个小时后开始频繁 GC,页面刷新越来越慢,最后卡死,这种慢性的问题最难查。
-J-Duser.timezone=Asia/Shanghai只影响日志时间戳,但排查问题时日志时间和你的手表差八小时,很难受,顺手加上。
后台启动我把 stdout 丢到/dev/null,因为 CMAK 通过 logback 把日志写进logs/application.log,nohup.out里只有很少的东西,留着反而一直涨。真要长期跑,用 systemd 托管比 nohup 靠谱,Restart=on-failure能兜住偶发的进程退出。
4. 接入 Kafka 集群:JMX 先开,表单再填
CMAK 启动起来只是有了个空壳,页面上什么都没有,必须手动添加一个集群。这里的顺序不能反:先去 Kafka 那边把 JMX 端口开出来并重启 broker,再回 CMAK 填表单。反过来做的话,集群加进去指标一直是空的,你会以为是 CMAK 的问题,实际上是 broker 那边根本没开端口。
4.1 Kafka 侧先开 JMX 端口
# 写进 kafka-server-start 的启动环境,或者直接 export 后启动 export KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote \ -Dcom.sun.management.jmxremote.port=9999 \ -Dcom.sun.management.jmxremote.rmi.port=9999 \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -Djava.rmi.server.hostname=10.0.0.11" # 每台 broker 都要重启一次生效 $KAFKA_HOME/bin/kafka-server-stop.sh $KAFKA_HOME/bin/kafka-server-start.sh -daemon $KAFKA_HOME/config/server.properties这六行里最容易被漏掉的是java.rmi.server.hostname。JMX 走 RMI,客户端连上 9999 之后,服务端会告诉客户端"你去连这个地址拿数据",如果不显式指定,它返回的是127.0.0.1,CMAK 在另一台机器上拿到这个地址当然连不上,症状就是端口能 telnet 通,但指标永远拉不出来。所以这里必须写 broker 自己的、CMAK 能访问到的 IP。
jmxremote.rmi.port和jmxremote.port设成同一个值也是为了省事,不设的话 RMI 会随机开一个端口回连,中间有防火墙就过不去。
CMAK 轮询 JMX 时默认连的是 9999,这个值在代码里写死的,配置文件里没有对应项。所以全集群的 broker 统一用 9999 最省心,改成别的端口就得改代码重新打包,不值当。
4.2 添加集群的字段逐个说
页面右上角Cluster→Add Cluster,表单字段不多,但每个都有讲究:
| 字段 | 怎么填 | 填错的后果 |
|---|---|---|
| Cluster Name | 唯一名字,建议带环境前缀 | 重名会覆盖,改名要删了重建 |
| Cluster Zookeeper Hosts | Kafka 的 ZK 地址,带 Kafka 的 chroot | 填错 broker 数一直是 0 |
| Kafka Version | 和集群实际版本严格对齐 | 消费组 offset 读不出来 |
| Enable JMX Polling | 勾上 | 不勾就没有 CPU、流量、请求速率曲线 |
| Poll consumer information | 中小集群勾上 | 不勾看不到消费组列表 |
| Enable Active Offset Cache | topic 多的集群勾上 | 每次刷新都打 ZK,慢 |
| Enable Topic Deletion | 生产环境别勾 | 页面上多个删除按钮,手滑就麻烦 |
Kafka Version这个下拉框,选项从 0.8.2 一路排到 2.x,选错了不会报错,但消费组那一页会一直空着。原因是不同版本的 offset 存放位置不一样,0.8.x 存在 ZK 里,0.9 之后挪到了 Kafka 内部的__consumer_offsetstopic,CMAK 按你选的版本走不同的读取路径。所以别图省事随便选个最高版本,去server.properties里或者kafka-topics.sh --version确认一下。
Cluster Zookeeper Hosts这里有个细节:格式是host:port,多个用逗号分隔,如果 Kafka 配了 chroot,就写成zk1:2181,zk2:2181/kafka——注意斜杠只跟在最后一个地址后面,这是 ZK 连接串的通用写法。
4.3 SASL/SSL 集群的附加配置
如果目标集群开了 SASL 认证,CMAK 光在表单里填是不够的,它自己作为客户端连 Kafka 的时候也得带上凭证。做法是在启动参数里塞一个 JAAS 文件:
// conf/kafka_client_jaas.conf KafkaClient { org.apache.kafka.common.security.plain.PlainLoginModule required username="cmak" password="对应密码"; };# 启动命令里追加这两个 -J 参数 nohup bin/cmak -Dconfig.file=conf/application.conf \ -java-home /usr/lib/jvm/java-8-openjdk-amd64 \ -Dhttp.port=9000 \ -J-Djava.security.auth.login.config=/opt/cmak/current/conf/kafka_client_jaas.conf \ -J-Xmx2g \ > /dev/null 2>&1 &这里要分清两件事:Kafka 的 SASL 是 broker 的认证,ZooKeeper 的 ACL 是 ZK 的认证,两套东西互不相干。CMAK 读元数据走 ZK,读 offset 走 Kafka,所以集群要是两边都开了认证,你两边都得配。ZK 那边开了 ACL 的话,还得额外配-Dzookeeper.sasl.client或者 digest 认证,具体看你的 ZK 是怎么开的。
注意:JAAS 文件的权限设成 600,并且属主是跑 CMAK 的那个用户。这文件里有明文密码,其他用户可读是个隐患。
5. 排查:启动失败、指标空白、Broker 数为 0
装 CMAK 出问题,症状看着五花八门,实际能归到五类。下面这五条是我遇到过次数最多的,每条都按"看到什么—为什么—怎么办"写,照着对号入座基本能定位。
5.1 启动秒退,日志里是 UnsupportedClassVersionError
现象:前台执行bin/cmak之后一两秒就回到 shell,logs/application.log里翻到java.lang.UnsupportedClassVersionError或者NoSuchMethodError: java.nio.ByteBuffer.flip()。
原因:脚本没有用-java-home指定 JDK,抓了机器上默认那个java,而默认那个是 11 或 17。UnsupportedClassVersionError是 class 文件版本比运行环境高,NoSuchMethodError是 JDK 9 之后ByteBuffer.flip()返回值变了导致的二进制不兼容,两种报错指向同一个根因。
解决:启动命令里显式加-java-home /usr/lib/jvm/java-8-openjdk-amd64,路径用readlink -f $(which java)确认过。改完先前台跑一次,看到Listening for HTTP再转后台。
5.2 进程在,但浏览器打不开 9000
现象:ps -ef | grep cmak能看到 java 进程,浏览器访问http://ip:9000超时或者连不上。
原因:最多的情况是 9000 已经被别的服务占了,CMAK 实际上压根没起来,或者起在了别的端口上;其次是监听地址绑在了127.0.0.1;再其次是机器上的防火墙没放行。
解决:
# 先看谁在占 9000 ss -lntp | grep 9000 # 看 CMAK 实际监听在哪个端口 ss -lntp | grep java # 确认监听地址,0.0.0.0 才是对外 # 本地能通、外面不通,看防火墙 sudo firewall-cmd --list-ports sudo firewall-cmd --add-port=9000/tcp --permanent && sudo firewall-cmd --reload确认是端口冲突之后,启动命令加-Dhttp.port=19000换一个,同时把防火墙和反向代理一起改掉。
5.3 启动报 Secret key is not set,或页面直接 500
现象:日志里出现Configuration error[Secret key is not set]之类的字样,进程起不来;或者进程起来了,访问首页直接 500,日志里有 Play 的配置异常。
原因:application.conf里play.http.secret.key那一行默认是注释掉的。Play 框架用它来签名 session cookie,没设的时候部分版本会直接拒绝启动。有些人从旧版本迁移过来,旧配置里没这一项,升级完就打不开了。
解决:在application.conf里补一行,值随便生成一个 32 位以上的随机串:
# 生成方式:head -c 32 /dev/urandom | base64 play.http.secret.key="换成你生成的那串"改完重启。这一项不影响功能,但缺了就是起不来,属于典型的配置项玄学。
5.4 集群加进去了,Brokers 一直显示 0
现象:添加集群时没报错,保存后进 Cluster 页面,Broker 数是 0,Topic 列表空的,页面一直转圈。
原因:三种可能——cmak.zkhosts指到了另一个 ZK 实例;Kafka 在 ZK 上配了 chroot 但填地址时没带/kafka;ZK 开了 ACL 而 CMAK 没配置认证。前两种占九成。
解决:绕开 CMAK,直接用 zookeeper-shell 手连一遍,看节点在不在:
$KAFKA_HOME/bin/zookeeper-shell.sh zk1:2181/kafka <<'EOF' ls /brokers/ids ls /brokers/topics quit EOF/brokers/ids里能列出[0, 1, 2]这样的节点号,说明 ZK 地址和 chroot 都对,问题在 CMAK 的配置上,回去检查cmak.zkhosts;如果这里是空的,说明你连的这个 ZK 根本不是 Kafka 用的那个,或者 chroot 写错了。这一步是分水岭,先做它,别在 CMAK 里反复删了重加。
5.5 JMX 勾了,但指标曲线一直是空白
现象:Topic 和 Partition 信息都正常,Broker 页面也有,但 CPU、网络流量、请求速率这些曲线一直是平的或者干脆没线;消费组的 lag 也显示不出来。
原因:broker 没开 JMX 端口;开了但没设java.rmi.server.hostname,CMAK 拿到127.0.0.1回连失败;或者中间的防火墙只放行了 9999,没放行 RMI 的回连端口。
解决:
# 在 broker 上看 JMX 参数在不在 jcmd $(pgrep -f kafka.Kafka) VM.system_properties | grep jmxremote # 在 CMAK 机器上验连通性 telnet 10.0.0.11 9999telnet通但不一定拉得到数据,因为 RMI 还要建第二条连接。所以最稳的验证是在 CMAK 机器上用jconsole 10.0.0.11:9999连一下,能连上看到 MBean,CMAK 就一定能读到。连不上就回去检查java.rmi.server.hostname和jmxremote.rmi.port,把回连端口也固定成 9999 并放进防火墙。
6. 验收:从端口探活到拉出第一条消费 lag
装完最怕的是"看起来能打开"就算完事,结果上线一周后有人问某个消费组积压多少,你打开 CMAK 一看数据是空的。所以下面这套验收,我每次都从头走一遍,七项全绿才算装完。
# 1. 进程和端口 ps -ef | grep cmak | grep -v grep ss -lntp | grep 9000 # 2. HTTP 探活,返回 200 才算 Play 真的起来了 curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9000/ # 3. 日志里不该有反复刷的 ERROR grep "ERROR" /opt/cmak/current/logs/application.log | tail -n 20 # 4. 拿 CMAK 的 lag 和官方脚本对一遍,数字对得上才算真的读通了 $KAFKA_HOME/bin/kafka-consumer-groups.sh \ --bootstrap-server kafka1:9092 \ --describe --group demo-group第 4 步是整套验收里最关键的一步,也是最容易被跳过的一步。CMAK 显示的 lag 和kafka-consumer-groups.sh的输出必须一致,如果 CMAK 那边显示 0 而脚本显示几千,说明它读 offset 的路径没通——通常是Kafka Version下拉选错了,或者Poll consumer information没勾。这种"看起来有数但数是错的"状态,比空白更危险。
| 检查项 | 期望结果 | 不通过先看哪里 |
|---|---|---|
| 进程 | ps里有 java 进程且带 cmak 参数 | logs/application.log尾部 |
| 端口 | 0.0.0.0:9000处于 LISTEN | ss -lntp看谁占了 |
| 首页 | curl 返回 200 | 认证配置、play.http.context |
| 登录 | 用配置的账号能进 | basicAuthentication三行 |
| 集群 | Broker 数与集群实际一致 | cmak.zkhosts、chroot |
| Topic | 列表与kafka-topics.sh --list一致 | Kafka Version 下拉 |
| 消费组 | lag 与官方脚本一致 | JMX、Poll consumer information |
| 指标 | CPU、流量曲线有起伏 | JMX_PORT、9999 连通性 |
还有一个长期运行的观察点:装完别就撒手不管,第二天回来tail -f logs/application.log看几十行,如果ConnectionLoss或者 ZK session 超时的日志在反复刷,说明 ZK 那边不稳或者cmak.zkhosts只写了一个节点。把 ZK 三个节点全写进去,比出问题再重启管用。
从那以后我每次解压完,启动命令里都强制带上-java-home,装完先ss -lntp | grep 9000抢在浏览器之前确认端口,最后一定要拿kafka-consumer-groups.sh对一遍 lag 数字才敢交付。这套动作看着啰嗦,但比事后被人问"这个数怎么不对"要轻松得多。希望帮到你。
本文还有配套的精品资源,点击获取