kafka 部署

226 阅读5分钟

最近在学习 kafka 的时候在部署这一步遇到了些困难,没有采用 kafka+zookeeper 的部署方式,采用了 kafka3 新的部署方式。

记录一下部署过程中踩的坑。

一下的部署都使用 docker 进行部署

1. 部署方式

1.1. kafka+zookeeper 的部署方式

在 kafka3 版本之前需要用到 zookeeper 来管理 kafka 的元数据,调节 Broker 节点以实现分布式一致性,类似于 rocketMQ 的 nameServer。

同时还要负责 kafka 集群中 leader 和 controller 的选举。

1.2. kafka3 (Raft) 部署方式

在 kafka3 之后引入了 Raft 算法,通过 Raft 算法就可以实现自己集群内部的 leader 和 controller 的选举工作,然后由内部的 Controller Quorum 管理元数据,有原本的维护两个服务到现在只需要维护一个服务,工作量大大降低,稳定性也进一步提高。

但是使用新的部署方式会有一个问题,部署过 etcd 的朋友可能会知道启动时的配置十分麻烦,有些配置是 raft 算法必须的,因此 docker-compose可能会比较复杂。

2. 使用 kafka3(Raft)部署方式的 docker-compose

 networks:
   kafka:
     driver: bridge
 
 services:
   kafka:
     image: docker.io/bitnami/kafka:3.6.2
     hostname: kafka
     container_name: kafka
     volumes:
       - "kafka_data:/bitnami"
     ports:
       - "9092:9092"    # 宿主机访问
       - "19092:19092"  # 容器网络内访问
       - "9093:9093"    # 控制器通信端口
     environment:
       # KRaft 模式核心配置
       - KAFKA_CFG_NODE_ID=0
       - KAFKA_CFG_PROCESS_ROLES=controller,broker
       - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
       - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true
       # 多监听器配置
       - KAFKA_CFG_LISTENERS=PLAINTEXT_HOST://:9092,PLAINTEXT://:19092,CONTROLLER://:9093
       - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT_HOST://kafka:9092
       - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
       - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
       - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT_HOST
     networks:
       - kafka
   
   kafka-ui:
     container_name: kafka-ui
     image: provectuslabs/kafka-ui:latest
     ports:
       - 8080:8080
     depends_on:
       - kafka
     environment:
       DYNAMIC_CONFIG_ENABLED: "TRUE"
       # 指定 Kafka broker 地址为容器网络内可访问的服务名
       KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
     networks:
       - kafka
 
 volumes:
   kafka_data:
     driver: local

以上就是部署的docker-compose

在我部署的过程并没有部署kafka集群,因为是学习,单节点kafka已经够用,以后如果有需要还会部署kafka集群。

此文件中一共部署了两个服务,一个是kafka,一个是kafka-ui用来后台管理 kafka

在此文件中最重要的就是environment如何写,这也是本文章的重点

3. kafka部署environment详解

1. KRaft模式设置

 environment:
   - KAFKA_CFG_NODE_ID=0
   - KAFKA_CFG_PROCESS_ROLES=controller,broker
   - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
   - KAFKA_AUTO_CREATE_TOPICS_ENABLE=true
  • 配置说明:

    • NODE_ID=0:节点唯一标识。
    • PROCESS_ROLES:节点同时担任控制器和 broker 角色(单节点模式)。
    • CONTROLLER_QUORUM_VOTERS:控制器选举配置(单节点只需自身)。
    • AUTO_CREATE_TOPICS_ENABLE:自动创建 Topic(实测不生效)。

2. 监听器配置

 - KAFKA_CFG_LISTENERS=PLAINTEXT_HOST://:9092,PLAINTEXT://:19092,CONTROLLER://:9093
 - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT_HOST://localhost:9092,PLAINTEXT://kafka:19092
  • 配置说明:

    • LISTENERS:定义监听地址和端口。

      • PLAINTEXT_HOST:供宿主机访问,绑定 9092 端口。
      • PLAINTEXT:供容器网络内访问,绑定 19092 端口。
      • CONTROLLER:控制器通信,绑定 9093 端口。
    • ADVERTISED_LISTENERS:对外通告的地址(客户端连接时使用)。

      • PLAINTEXT_HOST:客户端需使用 localhost:9092 连接。
      • PLAINTEXT:容器内服务使用 kafka:19092 连接。
  • 注意事项:

    • 如果是线上部署那么 9092 对应的监听地址一定要是客户端可以访问的地址,比如 go 程序要访问 kafka,那么访问 kafka 之后会先拿到ADVERTISED_LISTENERS中写好的地址,如果 9092 端口对应的地址是 localhost 那么 go 程序就会访问localhost:9092但是因为是容器部署,或者不在同一台主机上部署,就会访问不到,所以返回的已经是一个外网或者同一内网可访问的地址。

3.协议设置

 - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
 - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
 - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT_HOST
  • 配置说明:

    • LISTENER_SECURITY_PROTOCOL_MAP

      • CONTROLLER:对应 PLAINTEXT,控制器之间进行通信使用明文
      • PLAINTEXT:对应 PLAINTEXT,容器网络内部通信使用明文
      • PLAINTEXT_HOST:对应 PLAINTEXT,外部访问使用明文通信,这里可以改为 SSL,kafka 支持多种安全协议
    • CONTROLLER_LISTENER_NAMES

      • 指定用于 Controller 与 Broker 之间通信 的监听器名称。在 KRaft 模式(无 ZooKeeper)下,Controller 负责管理集群元数据、执行 Leader 选举等核心协调任务。

      • 这表明使用名为 CONTROLLER 的监听器处理 Controller 相关的通信。通常需要在 listeners 中定义该监听器:

         - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093
        

        这里的 CONTROLLER://:9093 表示 Controller 通信使用 9093 端口。

    • KAFKA_CFG_INTER_BROKER_LISTENER_NAME

      • 指定 Broker 之间 内部通信 使用的监听器名称。例如,当一个 Broker 需要与其他 Broker 同步数据或交换元数据时,会使用此监听器。

        配置示例

         - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT_HOST
        

        这表明 Broker 间通信使用名为 PLAINTEXT_HOST 的监听器。通常需要在 advertised.listeners 中定义该监听器:

         - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT_HOST://kafka:9092
        

        这里的 PLAINTEXT_HOST://kafka:9092 表示 Broker 间通过 kafka 主机名和 9092 端口通信。

以上来看 kafka使用 KRaft 的配置还是比较繁琐的,但是客户端和 kafka 之间使用明文通信不太安全,代表着有人知道了 ip+port,那他就也可以使用我的 kafka。因此 kafka 针对外部访问有多种安全协议

4. kafka 针对外部访问安全协议

Kafka 提供四种主要的安全协议:

  1. PLAINTEXT:明文传输,不加密(默认)
  2. SSL/TLS:使用 SSL/TLS 加密通信
  3. SASL_PLAINTEXT:明文传输,但使用 SASL 进行身份验证
  4. SASL_SSL:SSL/TLS 加密 + SASL 身份验证

具体实现方式 TODO