使用Gateway API访问Kafka - Strimzi

作者:API传播员 · 2025-11-23 · 阅读时间:6分钟
本文详细介绍了如何使用Gateway API的TLSRoute通过passthrough TLS模式安全访问Kafka集群,包括在KIND集群中配置Envoy Gateway、Strimzi和证书管理器,实现本地开发环境下的TLS加密连接和流量路由,解决了传统Ingress在Kafka访问中的限制问题。

背景

访问 Kafka

在之前的博客中,Jakub Scholz 介绍了 Strimzi 如何通过以下方式实现从 Kubernetes 集群外部访问 Kafka:

  • 使用 NodePort 服务
  • OpenShift 的 Route
  • LoadBalancer 服务
  • Ingress 资源

然而,这些方法存在一些限制:

  1. Kafka 客户端需要直接访问特定的代理,因此简单地通过负载均衡器将请求分散到 Kafka 集群可能导致错误的结果。
  2. Kafka 协议并非基于 HTTP,这意味着需要一些特殊的处理才能与简单的 Ingress 配合使用。

网关 API

网关 API 是一种比传统 Ingress 更灵活、可扩展的南北流量解决方案。虽然完整的 Gateway API 讨论超出了本文范围,但以下两种资源与 Kafka 的集成尤为重要:

  1. TCPRoute:用于代理未加密的 TCP 流量。
  2. TLSRoute:用于控制加密的 TCP 流量。

需要注意的是,HTTPRouteGRPCRoute 并不适用于 Kafka,因为 Kafka 不使用基于 HTTP 或 gRPC 的协议。

本文将重点介绍 TLSRoute,特别是使用 passthrough TLS 模式,其中 TLS 连接不会在网关控制器处终止,而是直接在 Kafka 代理处终止。


实践操作

如果您希望快速上手,可以克隆以下 GitHub 仓库,其中包含所有相关代码:GitHub 仓库

本地环境配置

在本示例中,我们将通过一些技巧使 KIND 集群支持本地开发,并通过 TLS 加密连接访问 Kafka。以下是主要步骤:

  1. 为 Kafka 代理创建一个包含主机名的证书。
  2. TLSRoute 网关控制器能够路由流量到 Kafka 之前,设置主机名到 KIND 集群的流量重定向。

配置步骤

  1. 创建一个自签名证书,适用于 *.strimzi.gateway.api.test,并配置 Kafka 客户端信任该证书。
  2. 在本地的 /etc/hosts 文件中,将以 .strimzi.gateway.api.test 结尾的 URL 映射到本地主机。
  3. 将本地终端的端口 9092 映射到 KIND 节点的端口 30992(这是运行在本地的 Docker 容器)。
  4. 部署 Envoy 网关 Pod,并通过 Kubernetes 的 NodePort 服务将端口 30992 映射到 Envoy 网关 Pod 的端口 9092

通过以上配置,流量可以像在公共网络中运行一样被路由到 KIND 集群。网络架构如下图所示:

流量路径如下:

  1. 从本地终端向 boostrap.strimzi.gateway.api.test:9092 发出请求。
  2. /etc/hosts 文件将请求重定向到 localhost
  3. KIND 集群的 Docker 容器将主机端口 9092 映射到容器端口 30992
  4. Kubernetes 的 NodePort 服务将流量从端口 30992 路由到 Envoy 网关 Pod。
  5. 使用 TLSRoute 配置 Envoy,将流量路由到 Kafka 代理。

KIND 集群设置

首先,创建一个 KIND 集群,使用以下 kind-config.yaml 文件:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
    extraPortMappings:
      - containerPort: 30992
        hostPort: 9092

在该配置中,hostPort: 9092 被映射到 containerPort: 30992,这意味着本地端口 9092 会通过 Docker 转发到 Kubernetes 节点的端口 30992

安装 Envoy Gateway

接下来,使用 helm 安装 Envoy Gateway。注意,Envoy Gateway 的工具(如 egctl)通常要求安装在 envoy-gateway-system 命名空间中。

安装完成后,需要部署一个具有特定 GatewayClassGateway,以监听正确的 NodePort。在创建 Gateway 之前,需先配置 GatewayClass,类似于 IngressClass,它定义了网关控制器可以协调的网关类型。

安装 Strimzi 和证书管理器

安装 Strimzi 和证书管理器后,创建一个自签名的证书和相关的 CA。以下是主要步骤:

  1. /etc/hosts 中添加以下内容:

    127.0.0.1 bootstrap.strimzi.gateway.api.test
    127.0.0.1 broker-0.strimzi.gateway.api.test
    127.0.0.1 broker-1.strimzi.gateway.api.test
    127.0.0.1 broker-2.strimzi.gateway.api.test
  2. 确保流量能够到达 Envoy Gateway Pod,并配置 Kafka 集群通告上述端点。


部署 Kafka 集群

在 KRaft 模式下创建 Kafka 集群,配置如下:

  • 集群包含 1 个控制器和 3 个代理。
  • 使用 scram-sha-512 身份验证保护监听器。
  • 使用证书管理器生成的自签名证书,而非 Strimzi 自动生成的证书。

以下是 Kafka 集群的资源定义:

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    version: 3.9.0
    replicas: 3
    listeners:
      - name: external
        port: 9092
        type: external
        tls: true
        authentication:
          type: scram-sha-512

创建 KafkaNodePool

为控制器和代理创建 KafkaNodePool,确保控制器节点 ID 从 0 开始,代理从 10 开始。


创建 TLSRoute

为 Kafka 集群创建以下 TLSRoute

  1. 一个指向引导服务的 TLSRoute
  2. 每个代理对应一个 TLSRoute

以下是 TLSRoute 的示例定义:

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: kafka-bootstrap
spec:
  rules:
    - backendRefs:
        - name: kafka-bootstrap-service

创建 Kafka 客户端配置

为了访问 Kafka,需要以下配置:

  1. KafkaUserSecret 中下载 sasl.jaas.config
  2. 下载由证书管理器生成的 CA 公共证书。
  3. 将 CA 证书转换为 JKS 格式。

以下脚本可帮助生成客户端配置文件:

#!/bin/bash
# 下载 Kafka 配置和证书
kubectl get secret kafka-user-secret -o jsonpath='{.data.sasl.jaas.config}' | base64 -d > /tmp/sasl.jaas.config
kubectl get secret kafka-ca-cert -o jsonpath='{.data.ca.crt}' | base64 -d > /tmp/ca.crt
keytool -import -trustcacerts -file /tmp/ca.crt -keystore /tmp/kafka-client.jks -storepass changeit

访问 Kafka

最后,使用 Strimzi 提供的 Docker 镜像和脚本访问 Kafka:

  1. 在一个终端中启动消费者:

    kafka-console-consumer.sh --bootstrap-server bootstrap.strimzi.gateway.api.test:9092 --topic test-topic
  2. 在另一个终端中启动生产者:

    kafka-console-producer.sh --bootstrap-server bootstrap.strimzi.gateway.api.test:9092 --topic test-topic

结论

本文展示了如何利用 Envoy Gateway 和 Gateway API 安全地访问 Kafka 集群。这种方法可能在未来成为 Kubernetes 网络的标准。虽然目前 Strimzi 对 Gateway API 的支持仍需手动配置,但未来可能会实现原生支持。

原文链接: https://strimzi.io/blog/2024/08/16/accessing-kafka-with-gateway-api/