1. 为什么在 Ubuntu 18.04 上装 Kafka 不是“点几下就完事”的事
Apache Kafka 这个名字,现在几乎成了实时数据管道的代名词。但很多人第一次接触它时,看到官方文档里那句“Download, unpack, start ZooKeeper, then start Kafka server”就以为只是解压运行两个脚本的事。我当年也是这么想的,结果在一台刚重装的 Ubuntu 18.04 虚拟机上折腾了整整一个下午——ZooKeeper 启动失败、Kafka 报错找不到 JAVA_HOME 、 kafka-topics.sh 执行直接抛 NoClassDefFoundError ,最后发现连 curl 都没装全。这根本不是安装软件,而是在给一套分布式消息系统的底层神经网络做首次通电测试。
Ubuntu 18.04 是个关键分水岭:它默认使用 OpenJDK 11,而 Kafka 2.8.x 及更早版本对 Java 11 的兼容性存在隐性陷阱;它的 systemd 单元文件管理逻辑和旧版 Ubuntu 差异明显;更重要的是,它自带的 apt 源里压根不提供 Kafka 官方包——你搜 sudo apt search kafka ,出来的全是无关的 Python 库或监控插件。所以标题里那个“Install”,实际含义是“从零构建一个可生产验证的 Kafka 运行环境”,而不是“用包管理器一键装好”。关键词 Apache Kafka 和 Ubuntu 18.04 组合在一起,本质上是在挑战 Linux 系统环境、Java 运行时、Shell 脚本执行链、网络端口策略这四层叠加的稳定性。如果你正卡在 wsl --install 太慢 或 sudo apt-get install jq 失败这类基础环节,别急着跳过——这些看似无关的依赖,恰恰是 Kafka 启动后健康检查脚本(比如 kafka-broker-api-versions.sh )的命脉。我见过太多人 Kafka 服务明明跑起来了,但用 kafka-console-consumer.sh 消费不到消息,最后排查发现是 jq 缺失导致元数据解析失败,消费者连 broker 的 API 版本都识别不了。所以这篇内容不是教你怎么敲命令,而是带你把 Kafka 在 Ubuntu 18.04 上的每一根“神经末梢”都接通、测通、压通。
2. 整体设计思路:为什么放弃 apt/yum,坚持手动部署二进制包
2.1 包管理器的幻觉与现实落差
先说结论: 绝对不要尝试用 apt-get install kafka 或 snap install kafka 来部署生产级 Kafka 。Ubuntu 18.04 的官方源里根本没有 Kafka 主程序包,社区维护的 kafka-server 包早已停止更新,最新版本停留在 0.10.2(发布于 2016 年),而当前主流稳定版已是 3.6.x。有人会说:“那我加个第三方 PPA 源?”——我试过 ppa:webupd8team/java 和 ppa:openjdk-r/ppa ,结果是 Java 版本冲突直接让系统 update-manager 崩溃。更致命的是,PPA 包通常把 Kafka 配置文件硬编码进 /etc/kafka/ ,日志路径写死在 /var/log/kafka/ ,而 Kafka 自身的 server.properties 里 log.dirs 参数又要求你手动指定磁盘路径。当这两套路径管理体系打架时,你得到的不是警告,而是 Kafka 启动瞬间因无法创建日志目录而静默退出, systemctl status kafka 显示 active (exited), journalctl -u kafka 却只有一行 Started Apache Kafka. ,连错误堆栈都不给你。
2.2 二进制包部署的不可替代性
我们选择下载官方 .tgz 包(比如 kafka_2.13-3.6.1.tgz ),核心逻辑有三层:
第一层是 版本可控性 。Kafka 的客户端协议(尤其是 SASL_SSL 认证、 idempotent producer 语义)在 2.8.x 到 3.5.x 之间有大量非向后兼容变更。如果你的业务系统用的是 Spring Kafka 2.8.x,却强行部署 Kafka 3.6.x,生产者发消息时可能触发 INVALID_PRODUCER_EPOCH 错误,而这个错误在 Kafka 2.8.x 里根本不存在。手动解压二进制包,你能精确控制 KAFKA_HOME 环境变量指向哪个版本目录,甚至可以并存 kafka_2.13-3.4.0 和 kafka_2.13-3.6.1 两个目录,用软链接切换,这是任何包管理器都无法提供的原子级版本管理能力。
第二层是 配置自由度 。官方二进制包里的 config/server.properties 是未经修改的原始模板,所有参数都以 # 注释形式存在。你可以直接取消注释 listeners=PLAINTEXT://:9092 ,也可以改成 listeners=SASL_PLAINTEXT://:9092 ,甚至能定义 listener.security.protocol.map=INTERNAL:SASL_PLAINTEXT,EXTERNAL:SSL 这种多监听器映射。而 PPA 包往往把 listeners 写死成 PLAINTEXT://127.0.0.1:9092 ,你改完配置重启服务,systemd 会因为权限问题拒绝加载新配置——因为 PPA 包把 Kafka 进程强制降权为 kafka 用户运行,而该用户对 /etc/kafka/ 目录没有写权限。
第三层是 调试可见性 。当你执行 bin/kafka-server-start.sh config/server.properties 时,控制台会实时打印出 JVM 启动参数、Log4j 初始化过程、ZooKeeper 连接状态。如果连接超时,你会看到 org.apache.zookeeper.KeeperException$ConnectionLossException 的完整堆栈;如果磁盘空间不足,会明确报 java.io.IOException: No space left on device 。而 systemd 封装的服务,这些关键日志默认被重定向到 journald 的二进制流里,你需要 journalctl -u kafka -o json-pretty | jq '.MESSAGE' 才能过滤出有效信息——这就回到了热搜词里那个 todo-tree: failed to find vscode-ripgrep 的困境:工具链断裂导致问题定位成本指数级上升。
提示:Ubuntu 18.04 的
systemd默认启用PrivateTmp=yes,这意味着 Kafka 进程看到的/tmp目录是隔离的。如果你在server.properties里配置log.dirs=/tmp/kafka-logs,Kafka 实际写入的是/tmp/systemd-private-xxx/kafka-logs,而kafka-topics.sh脚本默认读取的是宿主机/tmp/kafka-logs,结果就是主题创建成功但 broker 根本不认这个主题。这是手动部署必须绕开的第一个坑。
3. 核心细节解析:Java 环境、ZooKeeper 依赖与网络端口策略
3.1 Java 版本的精确锚定:为什么 OpenJDK 11 是双刃剑
Ubuntu 18.04 默认安装 OpenJDK 11,这看似省事,实则埋雷。Kafka 官方文档明确要求 Java 8 或 Java 11,但没告诉你一个关键细节: OpenJDK 11 的 java.security 策略文件默认禁用了 TLS 1.0 和 1.1 。而 Kafka 2.8.x 及更早版本的 SslTransportLayer 类,在初始化 SSLContext 时会尝试加载所有可用协议,包括已被禁用的 TLS 1.0。结果就是 Kafka broker 启动时卡在 Initializing SSL context


344

被折叠的 条评论
为什么被折叠?



