3. 环境准备:Docker 部署 Kafka、Zookeeper、Kafka Connect 集群

好,咱们进入实操环节。这一章的目标很明确——用 Docker 把 Debezium 依赖的底层基础设施搭起来。说白了,就是 Kafka、Zookeeper 和 Kafka Connect 这三件套。

我见过不少新手在这步卡住,要么是版本不匹配,要么是网络配置搞错。其实没那么复杂,咱们一步步来。

3.1 整体架构概览

先看一张图,搞清楚这几个组件之间的关系。你想想看,Debezium 要捕获数据库变更,总得有个地方存放变更事件吧?Kafka 就是那个地方。Zookeeper 负责协调 Kafka 集群,而 Kafka Connect 则是 Debezium 的运行容器。

核心关系: Debezium 以 Connector 插件的形式运行在 Kafka Connect 中,捕获的变更事件写入 Kafka Topic,Zookeeper 负责集群元数据管理。

Debezium 环境组件关系图 Zookeeper 集群协调 / 元数据存储 Kafka Broker 事件存储 / 消息队列 Kafka Connect 运行 Debezium Connector 部署说明 1. Zookeeper 先启动,Kafka 依赖它做 Leader 选举 2. Kafka Broker 启动后,Kafka Connect 才能注册 3. Debezium Connector 插件放在 Kafka Connect 的插件目录 4. 启动顺序:Zookeeper → Kafka → Kafka Connect

3.2 版本选择与镜像拉取

版本这事,我吃过亏。早期有个项目用了 Kafka 2.8 和 Debezium 1.6,结果有个 API 不兼容,排查了一整天。后来我养成了个习惯——先查 Debezium 官方文档的版本兼容矩阵。

组件 推荐版本 镜像名称
Zookeeper 3.8.1 confluentinc/cp-zookeeper:7.4.0
Kafka Broker 3.4.0 confluentinc/cp-kafka:7.4.0
Kafka Connect 3.4.0 confluentinc/cp-kafka-connect:7.4.0

我的建议: 用 Confluent 的镜像,而不是 Apache 官方镜像。Confluent 的镜像集成了更多实用工具,而且版本一致性更好。我在生产环境一直这么用,没出过问题。

拉取镜像很简单,一行命令搞定:

docker pull confluentinc/cp-zookeeper:7.4.0
docker pull confluentinc/cp-kafka:7.4.0
docker pull confluentinc/cp-kafka-connect:7.4.0

3.3 使用 Docker Compose 一键部署

手动一个个启动容器太麻烦,而且容易搞乱网络配置。我个人习惯用 Docker Compose,把所有服务定义在一个文件里,一键启动。

创建一个 docker-compose.yml 文件:

version: '3.8'

services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.4.0
    container_name: zookeeper
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000
    ports:
      - "2181:2181"
    networks:
      - debezium-net

  kafka:
    image: confluentinc/cp-kafka:7.4.0
    container_name: kafka
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
      KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
    ports:
      - "9092:9092"
    networks:
      - debezium-net

  connect:
    image: confluentinc/cp-kafka-connect:7.4.0
    container_name: kafka-connect
    depends_on:
      - kafka
    environment:
      CONNECT_BOOTSTRAP_SERVERS: kafka:9092
      CONNECT_REST_PORT: 8083
      CONNECT_GROUP_ID: "debezium-connect-group"
      CONNECT_CONFIG_STORAGE_TOPIC: "connect-configs"
      CONNECT_OFFSET_STORAGE_TOPIC: "connect-offsets"
      CONNECT_STATUS_STORAGE_TOPIC: "connect-status"
      CONNECT_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
      CONNECT_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
      CONNECT_INTERNAL_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
      CONNECT_INTERNAL_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter"
      CONNECT_REST_ADVERTISED_HOST_NAME: "kafka-connect"
      CONNECT_PLUGIN_PATH: "/usr/share/java,/etc/kafka-connect/jars"
    ports:
      - "8083:8083"
    volumes:
      - ./debezium-connector:/etc/kafka-connect/jars
    networks:
      - debezium-net

networks:
  debezium-net:
    driver: bridge

注意: KAFKA_ADVERTISED_LISTENERS 这个参数很容易配错。如果你在本地开发,用 localhost:9092;如果容器间通信,用服务名 kafka:9092。我曾经因为这里写错了,导致客户端连不上 Kafka,折腾了半小时。

3.4 启动集群并验证

文件写好了,启动就一行命令:

docker-compose up -d

启动后,检查一下所有容器是否正常运行:

docker ps

你应该能看到三个容器都在运行状态。接下来验证一下各个组件是否正常工作。

验证 Zookeeper

docker exec -it zookeeper zookeeper-shell localhost:2181
# 输入 stat 查看状态

验证 Kafka

docker exec -it kafka kafka-topics --bootstrap-server localhost:9092 --list

如果返回空列表,说明 Kafka 正常工作。因为还没创建任何 Topic。

验证 Kafka Connect

curl http://localhost:8083/connectors

返回 [] 表示 Connect 正常运行,还没有注册任何 Connector。

验证要点: 三个组件都返回正常状态,说明环境准备完毕。如果某个组件启动失败,先检查日志:docker logs <容器名>。大部分问题都是端口冲突或网络配置错误。

3.5 部署 Debezium Connector 插件

Kafka Connect 跑起来了,但还没装 Debezium 的插件。你需要下载 Debezium 的 Connector 包,放到 Connect 的插件目录。

我习惯在项目目录下创建一个 debezium-connector 文件夹,然后把插件包解压进去:

mkdir -p debezium-connector
cd debezium-connector
wget https://repo1.maven.org/maven2/io/debezium/debezium-connector-mysql/2.3.0.Final/debezium-connector-mysql-2.3.0.Final-plugin.tar.gz
tar -xzf debezium-connector-mysql-2.3.0.Final-plugin.tar.gz

注意,上面的 docker-compose.yml 里已经配置了卷挂载:

volumes:
  - ./debezium-connector:/etc/kafka-connect/jars

所以插件包解压后,重启 Connect 容器即可加载:

docker restart kafka-connect

重启后,检查插件是否注册成功:

curl http://localhost:8083/connector-plugins

你应该能看到类似这样的输出:

[
  {
    "class": "io.debezium.connector.mysql.MySqlConnector",
    "type": "source",
    "version": "2.3.0.Final"
  }
]

避坑指南: 我曾经遇到过插件加载失败的情况,原因是插件目录下有多个版本的 jar 包冲突。建议只放一个版本的 Debezium Connector,不要混放多个版本。

3.6 本章小结

到这步,环境就全搭好了。你有了一个完整的 CDC 基础设施:Zookeeper 管协调,Kafka 存事件,Kafka Connect 跑 Debezium。下一章咱们会在这个环境上,真正配置一个 MySQL 的 Debezium Connector,开始捕获数据变更。

嗯,其实环境准备是最枯燥但最关键的一步。我见过太多人急着写代码,结果环境没配好,后面全是坑。按这个流程走,基本不会出问题。