搜索

在 OpenShift 中使用 AMQ Streams

download PDF
Red Hat AMQ 2021.Q3

用于 OpenShift Container Platform 上的 AMQ Streams 1.8

摘要

本指南描述了如何安装、配置和管理 Red Hat AMQ Streams 来构建大规模消息传递网络。

使开源包含更多

红帽承诺替换我们的代码、文档和网页属性中存在问题的语言。我们从这四个术语开始: master、slave、blacklist 和 whitelist。这些更改将在即将发行的几个发行本中逐渐实施。如需了解更多详细信息,请参阅 CTO Chris Wright 信息

第 1 章 AMQ 流概述

AMQ Streams 简化了在 OpenShift 集群中运行 Apache Kafka 的过程。

本指南提供有关配置 Kafka 组件和使用 AMQ Streams Operator 的说明。步骤与您可能想要修改部署的方式相关,并引进其他功能,如 Cruise Control 或分布式追踪。

您可以使用 AMQ Streams 自定义资源 配置部署。自定义资源 API 引用 描述了您可以在配置中使用的属性。

注意

您是否想要开始使用 AMQ Streams?有关逐步部署说明,请参阅 OpenShift 中的部署和升级 AMQ Streams 指南

1.1. Kafka 功能

Kafka 的底层数据流处理功能和组件架构可以提供:

  • 微服务和其他应用以极高的吞吐量和低延迟共享数据
  • 消息排序保证
  • 从数据存储中重获/重播消息以重建应用程序状态
  • 使用键值日志时删除旧记录的消息紧凑
  • 集群配置中的水平可扩展性
  • 数据复制来控制容错
  • 保留大量数据以便立即访问

1.2. Kafka 用例

Kafka 的功能使其适合:

  • 事件驱动的架构
  • 事件源,以捕获对应用状态的更改作为事件日志
  • 消息代理
  • 网站活动跟踪
  • 通过指标进行操作监控
  • 日志收集和聚合
  • 为分布式系统提交日志
  • 流处理,以便应用程序能够实时响应数据

1.3. AMQ 流如何支持 Kafka

AMQ Streams 提供容器镜像和 Operator,以便在 OpenShift 上运行 Kafka。AMQ Streams Operator 是运行 AMQ Streams 的基础。AMQ Streams 提供的 Operator 是专门构建的,具有可有效管理 Kafka 的专业操作知识。

Operator 简化了以下流程:

  • 部署和运行 Kafka 集群
  • 部署和运行 Kafka 组件
  • 配置对 Kafka 的访问
  • 保护对 Kafka 的访问
  • 升级 Kafka
  • 管理代理
  • 创建和管理主题
  • 创建和管理用户

1.4. AMQ Streams Operator

AMQ Streams 支持使用 Operator 的 Kafka 来部署和管理 Kafka 到 OpenShift 的组件和依赖项。

Operator 是一种打包、部署和管理 OpenShift 应用的方法。AMQ Streams Operator 扩展 OpenShift 功能,自动执行与 Kafka 部署相关的常见复杂任务。通过在代码中了解 Kafka 操作,Kafka 管理任务可以简化,无需人工干预。

Operator

AMQ Streams 提供 Operator 来管理在 OpenShift 集群中运行的 Kafka 集群。

Cluster Operator
部署和管理 Apache Kafka 集群、Kafka Connect、Kafka MirrorMaker、Kafka Bridge、Kafka Exporter 和 Entity Operator
实体 Operator
由主题 Operator 和 User Operator 组成
主题 Operator
管理 Kafka 主题
User Operator
管理 Kafka 用户

Cluster Operator 可以与 Kafka 集群同时部署 Topic Operator 和 User Operator 作为 Entity Operator 配置的一部分。

AMQ Streams 架构中的 Operator

Operators within the AMQ Streams architecture

1.4.1. Cluster Operator

AMQ Streams 使用 Cluster Operator 来部署和管理集群:

  • Kafka(包括 ZooKeeper、实体 Operator、Kafka Exporter 和 Cruise Control)
  • Kafka Connect
  • Kafka MirrorMaker
  • Kafka Bridge

自定义资源用于部署集群。

例如,部署 Kafka 集群:

  • OpenShift 集群中创建了带有集群配置的 Kafka 资源。
  • Cluster Operator 根据 Kafka 资源中声明的内容部署对应的 Kafka 集群。

Cluster Operator 也可以部署(通过配置 Kafka 资源):

  • 通过 KafkaTopic 自定义资源提供 operator 风格主题管理的主题 Operator
  • 一个 User Operator,通过 KafkaUser 自定义资源提供 operator 风格的用户管理

部署的 Entity Operator 中的 Topic Operator 和 User Operator 功能。

Cluster Operator 的架构示例

The Cluster Operator creates and deploys Kafka and ZooKeeper clusters

1.4.2. 主题 Operator

Topic Operator 提供了通过 OpenShift 资源管理 Kafka 集群中主题的方法。

Topic Operator 的架构示例

The Topic Operator manages topics for a Kafka cluster via KafkaTopic resources

Topic Operator 的角色是保留一组 KafkaTopic OpenShift 资源,描述与对应的 Kafka 主题同步中的 Kafka 主题。

特别是,如果 KafkaTopic 是:

  • 创建,主题 Operator 会创建该主题
  • 删除的,主题 Operator 会删除该主题
  • 更改,主题 Operator 更新该主题

在另一个方向上工作,如果一个主题是:

  • 在 Kafka 集群中创建,Operator 会创建一个 KafkaTopic
  • 从 Kafka 集群中删除,Operator 会删除 KafkaTopic
  • 在 Kafka 集群中更改,Operator 会更新 KafkaTopic

这可让您声明 KafkaTopic 作为应用程序部署的一部分,Topic Operator 将为您创建该主题。您的应用程序只需要处理从所需主题中产生或使用的内容。

Topic Operator 在主题 存储中维护每个主题 的信息,它与来自 Kafka 主题或 OpenShift KafkaTopic 自定义资源的更新持续同步。应用到本地内存中主题存储的操作的更新会保留在磁盘上的备份主题存储中。如果某个主题被重新配置或重新分配给其他代理,KafkaTopic 将始终保持最新状态。

1.4.3. User Operator

User Operator 通过监视 Kafka 用户描述 Kafka 用户并确保在 Kafka 集群中正确配置了这些用户来管理 Kafka 集群的 Kafka 用户。

例如,如果 KafkaUser 是:

  • 创建,User Operator 创建它描述的用户
  • 删除时,User Operator 会删除它所描述的用户
  • 更改后,User Operator 会更新它所描述的用户

与主题 Operator 不同,User Operator 不会将 Kafka 集群的任何更改与 OpenShift 资源同步。Kafka 主题可以直接由 Kafka 中的应用程序创建,但用户不必与 User Operator 并行直接在 Kafka 集群中管理。

User Operator 允许您将 KafkaUser 资源声明为应用程序部署的一部分。您可以为用户指定身份验证和授权机制。您还可以配置 用户配额 来控制对 Kafka 资源的使用,例如,确保用户不会专利对代理的访问。

创建用户时,会在 Secret 中创建用户凭据。您的应用需要使用用户 及其凭据进行身份验证,并生成或使用消息。

除了管理用于身份验证的凭证外,User Operator 还通过在 KafkaUser 声明中包含用户访问权限描述来管理授权规则。

1.4.4. AMQ Streams Operator 中的功能门

您可以使用功能 门来启用和禁用 Operator 的一些功能

功能门在操作器配置中设置,具有三个成熟度阶段:alpha、beta 或 General Availability(GA)。

如需更多信息,请参阅 功能门

1.5. AMQ Streams 自定义资源

使用 AMQ Streams 将 Kafka 组件部署到 OpenShift 集群可通过应用自定义资源进行高度配置。自定义资源作为自定义资源定义(CRD)添加的 API 实例创建,以扩展 OpenShift 资源。

CRD 用作描述 OpenShift 集群中自定义资源的配置说明,并为部署中使用的每个 Kafka 组件以及用户和主题提供 AMQ Streams。CRD 和自定义资源定义为 YAML 文件。AMQ Streams 发行版提供了示例 YAML 文件。

CRD 还允许 AMQ Streams 资源受益于原生 OpenShift 功能,如 CLI 访问和配置验证。

1.5.1. AMQ Streams 自定义资源示例

CRD 需要在集群中进行一次性安装,以定义用于实例化和管理 AMQ Streams 特定资源的 schema。

通过安装 CRD 在集群中添加新的自定义资源类型后,您可以根据具体规格创建资源实例。

根据集群设置,安装通常需要集群管理员特权。

注意

管理自定义资源的访问权限仅限于 AMQ Streams 管理员。如需更多信息,请参阅 OpenShift 上部署和升级 AMQ 流指南中的指定 AMQ 流 管理员

CRD 在 OpenShift 集群中定义 一种 新型资源,如 kind:Kafka

Kubernetes API 服务器允许基于 kind 创建自定义资源,并且从 CRD 中了解如何在添加到 OpenShift 集群时验证和存储自定义资源。

警告

当 CRD 被删除时,该类型的自定义资源也会被删除。另外,自定义资源创建的资源也会被删除,如 pod 和 statefulsets。

每个 AMQ Streams 特定自定义资源都符合 CRD 为资源类型定义的 schema AMQ Streams 组件的自定义资源具有常见的配置属性,这些属性在 spec 下定义。

要了解 CRD 和自定义资源之间的关系,让我们看一下 Kafka 主题的 CRD 示例。

Kafka 主题 CRD

apiVersion: kafka.strimzi.io/v1beta2
kind: CustomResourceDefinition
metadata: 1
  name: kafkatopics.kafka.strimzi.io
  labels:
    app: strimzi
spec: 2
  group: kafka.strimzi.io
  versions:
    v1beta2
  scope: Namespaced
  names:
    # ...
    singular: kafkatopic
    plural: kafkatopics
    shortNames:
    - kt 3
  additionalPrinterColumns: 4
      # ...
  subresources:
    status: {} 5
  validation: 6
    openAPIV3Schema:
      properties:
        spec:
          type: object
          properties:
            partitions:
              type: integer
              minimum: 1
            replicas:
              type: integer
              minimum: 1
              maximum: 32767
      # ...

1
主题 CRD 的元数据、名称和标识 CRD 的标签。
2
此 CRD 的规格,包括组(域)名称、复数名称和支持的 schema 版本,用于 URL 以访问该主题的 API。其他名称用于标识 CLI 中的实例资源。例如,oc get kafkatopic my-topicoc get kafkatopics
3
可以在 CLI 命令中使用短名称。例如,oc get kt 可用作缩写而不是 oc get kafkatopic
4
在自定义资源上使用 get 命令时显示的信息。
5
CRD 的当前状态,如资源的 schema 引用 中所述。
6
OpenAPIV3Schema 验证提供了用于创建主题自定义资源的验证。例如,一个主题至少需要一个分区和一个副本。
注意

您可以识别 AMQ Streams 安装文件提供的 CRD YAML 文件,因为文件名包含索引号后跟 'Crd'。

以下是 KafkaTopic 自定义资源的对应示例。

Kafka 主题自定义资源

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic 1
metadata:
  name: my-topic
  labels:
    strimzi.io/cluster: my-cluster 2
spec: 3
  partitions: 1
  replicas: 1
  config:
    retention.ms: 7200000
    segment.bytes: 1073741824
status:
  conditions: 4
    lastTransitionTime: "2019-08-20T11:37:00.706Z"
    status: "True"
    type: Ready
  observedGeneration: 1
  / ...

1
kindapiVersion 标识自定义资源是实例的 CRD。
2
个标签,仅适用于 KafkaTopicKafkaUser 资源,定义 Kafka 集群的名称(与 Kafka 资源的名称相同),该标签定义某个主题或用户所属的名称。
3
spec 显示主题的分区和副本数量,以及主题本身的配置参数。在本例中,消息保留周期保留在主题中,并指定日志的片段文件大小。
4
KafkaTopic 资源的状态条件。在 lastTransitionTime 中,类型 条件更改为 Ready

自定义资源可以通过平台 CLI 应用到集群。创建自定义资源时,它将使用与 Kubernetes API 内置资源相同的验证。

创建 KafkaTopic 自定义资源后,Tpic Operator 将获得通知,并在 AMQ Streams 中创建对应的 Kafka 主题。

1.6. 监听程序配置

侦听器用于连接到 Kafka 代理。

AMQ Streams 提供了一个 generic GenericKafkaListener 模式,其中包含用于通过 Kafka 资源配置监听器的属性。

The GenericKafkaListener 提供了用于监听器配置的灵活方法。您可以指定属性来配置 内部 侦听器,以便在 OpenShift 集群内连接,或者指定 外部 侦听器以连接 OpenShift 集群外部。

每个监听程序都 定义为 Kafka 资源中的一个数组。您可以根据需要配置任意数量的侦听器,只要它们的名称和端口是唯一的。

您可能希望配置多个外部监听器,例如,以处理来自需要不同身份验证机制的网络的访问。或者,您可能需要将 OpenShift 网络加入外部网络。在这种情况下,您可以配置内部侦听器( 使用ServiceDnsDomain 属性),以便不使用 OpenShift 服务 DNS 域(通常为 .cluster.local)。

有关监听器可用的配置选项的更多信息,请参阅 GenericKafkaListener 模式参考

配置监听程序来保护对 Kafka 代理的访问

您可以使用身份验证为安全连接配置监听程序。有关保护对 Kafka 代理的访问的更多信息,请参阅管理对 Kafka 的访问

为 OpenShift 外部的客户端访问配置外部侦听器

您可以使用指定的连接机制(如 loadbalancer),为 OpenShift 环境外的客户端访问配置外部侦听器。有关连接外部客户端的配置选项的更多信息,请参阅配置外部监听程序

监听程序证书

您可以为启用了 TLS 加密的 TLS 监听程序或者外部监听程序提供自己的服务器证书,称为 Kafka 侦听程序证书。如需更多信息,请参阅 Kafka 侦听程序证书

1.7. 文档规范

Replaceables

在本文档中,可替换的文本采用 单空间 格式,使用斜体、大写和连字符。

例如,在以下代码中,您要将 MY-NAMESPACE 替换为命名空间的名称:

sed -i 's/namespace: .*/namespace: MY-NAMESPACE/' install/cluster-operator/*RoleBinding*.yaml

第 2 章 部署配置

本章论述了如何使用自定义资源配置受支持的部署的不同方面:

  • Kafka 集群
  • Kafka Connect 集群
  • 支持 Source2Image 的 Kafka Connect 集群
  • Kafka MirrorMaker
  • Kafka Bridge
  • Sything Control
注意

应用到自定义资源的标签也会应用到由 Kafka MirrorMaker 组成的 OpenShift 资源。这提供了一种便捷的机制,可使资源根据需要进行标记。

2.1. Kafka 集群配置

本节论述了如何在 AMQ Streams 集群中配置 Kafka 部署。Kafka 集群使用 ZooKeeper 集群部署。部署也可以包括管理 Kafka 主题和用户的 Topic Operator 和 User Operator。

您可以使用 Kafka 资源配置 Kafka。配置选项也可用于 Kafka 资源中的 ZooKeeper 和 Entity Operator。Entity Operator 由 Topic Operator 和 User Operator 组成。

Kafka 资源的完整 schema 信息包括在 第 13.2.1 节 “Kafka 模式参考” 中。

监听程序配置

您可以配置监听程序以将客户端连接到 Kafka 代理。有关为连接代理配置监听程序的更多信息,请参阅 Listener 配置

授权对 Kafka 的访问

您可以将 Kafka 集群配置为允许或拒绝用户执行的操作。有关保护对 Kafka 代理的访问的更多信息,请参阅管理对 Kafka 的访问

管理 TLS 证书

在部署 Kafka 时,Cluster Operator 会自动设置并更新 TLS 证书,以在集群中启用加密和身份验证。如果需要,您可以在续订周期结束前手动续订集群和客户端 CA 证书。您还可以替换集群和客户端 CA 证书使用的密钥。如需更多信息,请参阅 手动重新更新 CA 证书和 替换私钥

其它资源

2.1.1. 配置 Kafka

使用 Kafka 资源的属性来配置 Kafka 部署。

除了配置 Kafka 外,您还可以为 ZooKeeper 和 AMQ Streams Operator 添加配置。常见的配置属性(如日志记录和健康检查)是为每个组件独立配置的。

此流程仅显示一些可能的配置选项,但尤为重要选项包括:

  • 资源请求(CPU / Memory)
  • 用于最大和最小内存分配的 JVM 选项
  • 侦听器(和客户端身份验证)
  • Authentication
  • 存储
  • 机架感知
  • 指标
  • 用于集群重新平衡的精简控制

Kafka 版本

Kafka 配置log.message.format .version 和 inter.broker.protocol.version 属性必须是指定 Kafka 版本(spec.kafka.version)支持的版本。属性表示附加到消息的日志格式版本,以及 Kafka 集群中使用的 Kafka 协议版本。在升级 Kafka 版本时,需要更新这些属性。如需更多信息,请参阅 OpenShift 上部署 和升级 AMQ Streams 中的升级 Kafka

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

有关 部署方法的说明,请参阅 OpenShift 指南中的部署和升级 AMQ Streams

流程

  1. 编辑 Kafka 资源的 spec 属性。

    您可以配置的属性显示在此示例配置中:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        replicas: 3 1
        version: 2.8.0 2
        logging: 3
          type: inline
          loggers:
            kafka.root.logger.level: "INFO"
        resources: 4
          requests:
            memory: 64Gi
            cpu: "8"
          limits:
            memory: 64Gi
            cpu: "12"
        readinessProbe: 5
          initialDelaySeconds: 15
          timeoutSeconds: 5
        livenessProbe:
          initialDelaySeconds: 15
          timeoutSeconds: 5
        jvmOptions: 6
          -Xms: 8192m
          -Xmx: 8192m
        image: my-org/my-image:latest 7
        listeners: 8
          - name: plain 9
            port: 9092 10
            type: internal 11
            tls: false 12
            configuration:
              useServiceDnsDomain: true 13
          - name: tls
            port: 9093
            type: internal
            tls: true
            authentication: 14
              type: tls
          - name: external 15
            port: 9094
            type: route
            tls: true
            configuration:
              brokerCertChainAndKey: 16
                secretName: my-secret
                certificate: my-certificate.crt
                key: my-key.key
        authorization: 17
          type: simple
        config: 18
          auto.create.topics.enable: "false"
          offsets.topic.replication.factor: 3
          transaction.state.log.replication.factor: 3
          transaction.state.log.min.isr: 2
          log.message.format.version: 2.8
          inter.broker.protocol.version: 2.8
          ssl.cipher.suites: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" 19
          ssl.enabled.protocols: "TLSv1.2"
          ssl.protocol: "TLSv1.2"
        storage: 20
          type: persistent-claim 21
          size: 10000Gi 22
        rack: 23
          topologyKey: topology.kubernetes.io/zone
        metricsConfig: 24
          type: jmxPrometheusExporter
          valueFrom:
            configMapKeyRef: 25
              name: my-config-map
              key: my-key
        # ...
      zookeeper: 26
        replicas: 3 27
        logging: 28
          type: inline
          loggers:
            zookeeper.root.logger: "INFO"
        resources:
          requests:
            memory: 8Gi
            cpu: "2"
          limits:
            memory: 8Gi
            cpu: "2"
        jvmOptions:
          -Xms: 4096m
          -Xmx: 4096m
        storage:
          type: persistent-claim
          size: 1000Gi
        metricsConfig:
          # ...
      entityOperator: 29
        tlsSidecar: 30
          resources:
            requests:
              cpu: 200m
              memory: 64Mi
            limits:
              cpu: 500m
              memory: 128Mi
        topicOperator:
          watchedNamespace: my-topic-namespace
          reconciliationIntervalSeconds: 60
          logging: 31
            type: inline
            loggers:
              rootLogger.level: "INFO"
          resources:
            requests:
              memory: 512Mi
              cpu: "1"
            limits:
              memory: 512Mi
              cpu: "1"
        userOperator:
          watchedNamespace: my-topic-namespace
          reconciliationIntervalSeconds: 60
          logging: 32
            type: inline
            loggers:
              rootLogger.level: INFO
          resources:
            requests:
              memory: 512Mi
              cpu: "1"
            limits:
              memory: 512Mi
              cpu: "1"
      kafkaExporter: 33
        # ...
      cruiseControl: 34
        # ...
        tlsSidecar: 35
        # ...
    1
    副本节点的数量。如果您的集群已经定义了主题,您可以 扩展集群
    2
    Kafka 版本,可按照 升级过程将其改为受支持的 版本。
    3
    指定 Kafka 日志记录器和日志级别 直接(内联)或通过ConfigMap 间接(外部)添加。自定义 ConfigMap 必须放在 log4j.properties 键下。对于 Kafka kafka.root.logger.level logger,您可以将日志级别设置为 INFO、ERROR、WARN、TRACE、DEBUG、FATAL 或 OFF。
    4
    请求保留 支持的资源、当前 cpu 和 memory ,以及限制,以指定可消耗的最大资源。
    5
    健康检查以了解 何时重新启动容器(存活度)以及容器何时可以接受流量(就绪度)。
    6
    用于优化运行 Kafka 的虚拟机(VM)性能的 JVM 配置选项
    7
    ADVANCED OPTION: 容器镜像配置,只在特殊情况下推荐这样做。
    8
    侦听器配置客户端如何通过 bootstrap 地址连接到 Kafka 集群。侦听器 配置为 内部或外部 侦听器,以便从 OpenShift 集群内部或外部进行连接
    9
    用于标识侦听器的名称。在 Kafka 集群中必须是唯一的。
    10
    Kafka 内侦听器使用的端口号。在给定 Kafka 集群中,端口号必须是唯一的。允许的端口号是 9092 及以上,但端口 9404 和 9999 除外,它们已用于 Prometheus 和 JMX。根据监听程序类型,端口号可能与连接 Kafka 客户端的端口号不同。
    11
    侦听器类型指定为 内部,或用于外部监听器,作为 路由负载均衡器、 节点端口入口
    12
    为每个侦听器启用 TLS 加密。默认为 false路由 监听程序不需要 TLS 加密。
    13
    定义是否分配了包括集群服务后缀(通常. cluster.local)在内的完全限定 DNS 名称。
    14
    15
    16
    由外部 证书颁发机构管理的 Kafka 侦听器 证书的可选配置。brokerCertChainAndKey 指定包含服务器证书和私钥的 Secret。您可以在任何启用 TLS 加密的监听程序上配置 Kafka 侦听程序证书。
    17
    授权在 Kafka 代理上启用简单、OAUTH 2.0 或 OPA 授权。简单授权使用 AclAuthorizer Kafka 插件。
    18
    19
    20
    存储 被配置为 临时持久声明或 jbod
    21
    22
    持久性存储具有 额外的配置选项,如用于动态卷置备的存储 idclass
    23
    将机架感知 配置为在不同机架之间分布副本。topologykey 必须与集群节点标签匹配。
    24
    启用了 Prometheus 指标。在本例中,为 Prometheus JMX Exporter(默认指标导出器)配置了指标数据。
    25
    通过 Prometheus JMX Exporter 将指标导出到 Grafana 仪表板的 Prometheus 规则,这可以通过引用包含 Prometheus JMX 导出器配置的 ConfigMap 来启用。您可以使用对包含 metricsConfig.valueFrom.configMapKeyRef.key 下的空文件的 ConfigMap 的引用来启用指标,而无需进一步配置。
    26
    zookeeper 特定的配置,其中包含与 Kafka 配置类似的属性。
    27
    ZooKeeper 节点的数量。zookeeper 集群或ensemble 通常使用奇数的节点(通常为三个、五个或 7 个)运行。大多数节点必须可用,才能保持有效的仲裁。如果 ZooKeeper 集群丢失其仲裁,它将停止响应客户端,Kafka 代理将停止工作。拥有稳定且高度可用的 ZooKeeper 集群对于 AMQ 流至关重要。
    28
    29
    30
    实体操作器 TLS sidecar 配置.实体 Operator 使用 TLS sidecar 与 ZooKeeper 进行安全通信。
    31
    指定 Topic Operator 日志记录器和日志级别。这个示例使用 内联 日志记录。
    32
    33
    Kafka Exporter 配置.Kafka Exporter 是一个可选组件,用于从 Kafka 代理提取指标数据,特别是消费者滞后数据。
    34
    Cruise Control 的可选配置,用于 重新平衡 Kafka 集群
    35
    插入控制 TLS sidecar 配置.cruise Control 使用 TLS sidecar 与 ZooKeeper 进行安全通信。
  2. 创建或更新资源:

    oc apply -f KAFKA-CONFIG-FILE

2.1.2. 配置实体 Operator

Entity Operator 负责管理正在运行的 Kafka 集群中与 Kafka 相关的实体。

Entity Operator 包括:

通过 Kafka 资源配置,Cluster Operator 可在部署 Kafka 集群时部署 Entity Operator,包括一个或多个操作器。

注意

部署后,实体 Operator 根据部署配置包含操作器。

Operator 会自动配置为管理 Kafka 集群的主题和用户。

2.1.2.1. 实体 Operator 配置属性

使用 Kafka.spec 中的 principal Operator 属性来配置 Entity Operator。

entity Operator 属性支持以下几个子属性:

  • tlsSidecar
  • topicOperator
  • userOperator
  • 模板

tlsSidecar 属性包含 TLS sidecar 容器的配置,用于与 ZooKeeper 通信。

template 属性包含 Entity Operator pod 的配置,如标签、注解、关联性和容限。有关配置模板的详情请参考 第 2.6 节 “自定义 OpenShift 资源”

topicOperator 属性包含 Topic Operator 的配置。当缺少这个选项时,Entity Operator 会在没有 Topic Operator 的情况下部署。

userOperator 属性包含 User Operator 的配置。当缺少这个选项时,Entity Operator 会在没有 User Operator 的情况下部署。

有关配置 Entity Operator 的属性的更多信息,请参阅 EntityUserOperatorSpec schema 参考

启用两个运算符的基本配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
  zookeeper:
    # ...
  entityOperator:
    topicOperator: {}
    userOperator: {}

如果将空对象({})用于 topicOperator 和 userOperator ,则所有属性都使用其默认值。

当缺少 topicOperatoruserOperator 属性时,Entity Operator 不会被部署。

2.1.2.2. 主题 Operator 配置属性

可以使用 topicOperator 对象中的附加选项来配置主题 Operator 部署。支持以下属性:

watchedNamespace
主题操作器监视 KafkaTopics 的 OpenShift 命名空间。默认为部署 Kafka 集群的命名空间。
reconciliationIntervalSeconds
定期协调之间的间隔(以秒为单位)。默认值 120.
zookeeperSessionTimeoutSeconds
ZooKeeper 会话超时,以秒为单位。默认值为 18
topicMetadataMaxAttempts
从 Kafka 获取主题元数据的尝试数量。每次尝试之间的时间都定义为指数回退。考虑在因为分区或副本数量而创建主题时增加这个值。默认 6.
image
image 属性可用于配置要使用的容器镜像。有关配置自定义容器镜像的详情,请参考 第 13.1.6 节 “image
资源
resources 属性配置分配给 Topic Operator 的资源数量。有关资源请求和限制配置的详情,请参阅 第 13.1.5 节 “资源
logging
logging 属性配置 Topic Operator 的日志。如需了解更多详细信息,请参阅 第 13.2.45.1 节 “logging

Topic Operator 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
  zookeeper:
    # ...
  entityOperator:
    # ...
    topicOperator:
      watchedNamespace: my-topic-namespace
      reconciliationIntervalSeconds: 60
    # ...

2.1.2.3. 用户 Operator 配置属性

用户 Operator 部署可以使用 userOperator 对象中的附加选项进行配置。支持以下属性:

watchedNamespace
用户操作员在其中监视 KafkaUsers 的 OpenShift 命名空间。默认为部署 Kafka 集群的命名空间。
reconciliationIntervalSeconds
定期协调之间的间隔(以秒为单位)。默认值 120.
zookeeperSessionTimeoutSeconds
ZooKeeper 会话超时,以秒为单位。默认值为 18
image
image 属性可用于配置要使用的容器镜像。有关配置自定义容器镜像的详情,请参考 第 13.1.6 节 “image
资源
resources 属性配置分配给 User Operator 的资源数量。有关资源请求和限制配置的详情,请参阅 第 13.1.5 节 “资源
logging
logging 属性配置 User Operator 的日志记录。如需了解更多详细信息,请参阅 第 13.2.45.1 节 “logging
secretPrefix
secretPrefix 属性在从 KafkaUser 资源创建的所有 Secret 的名称中添加前缀。例如,STRIMZI_SECRET_PREFIX=kafka- 将为所有 Secret 名称添加前缀 kafka-。因此,名为 my-user 的 KafkaUser 将创建名为 kafka-my-user 的 Secret。

User Operator 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
  zookeeper:
    # ...
  entityOperator:
    # ...
    userOperator:
      watchedNamespace: my-user-namespace
      reconciliationIntervalSeconds: 60
    # ...

2.1.3. Kafka 和 ZooKeeper 存储类型

作为有状态应用程序,Kafka 和 ZooKeeper 需要将数据存储在磁盘上。AMQ Streams 支持用于此数据的三种存储类型:

  • ephemeral
  • persistent
  • JBOD 存储
注意

JBOD 存储只支持 Kafka,不适用于 ZooKeeper。

在配置 Kafka 资源时,您可以指定 Kafka 代理使用的存储类型及其对应的 ZooKeeper 节点。您可以使用以下资源中的 storage 属性配置存储类型:

  • Kafka.spec.kafka
  • Kafka.spec.zookeeper

存储类型在 type 字段中配置。

警告

部署 Kafka 集群后,无法更改存储类型。

其它资源

2.1.3.1. 数据存储注意事项

高效的数据存储基础架构对于 AMQ 流的最佳性能至关重要。

块存储是必需的。文件存储(如 NFS)无法使用 Kafka。

从以下选项中为块存储选择:

注意

AMQ Streams 不需要 OpenShift 原始块卷。

2.1.3.1.1. 文件系统

建议您将存储系统配置为使用 XFS 文件系统。AMQ Streams 还与 ext4 文件系统兼容,但为了获得最佳结果,可能需要额外的配置。

2.1.3.1.2. Apache Kafka 和 ZooKeeper 存储

Apache Kafka 和 ZooKeeper 使用单独的磁盘。

支持三种类型的数据存储:

  • 临时(仅适用于开发的建议)
  • persistent
  • JBOD(只是一个磁盘绑定,仅适用于 Kafka)

如需更多信息,请参阅 Kafka 和 ZooKeeper 存储

在异步发送和从多个主题接收数据的大型集群中,固态驱动器(SSD)(虽然不必要)可以提高 Kafka 的性能。SSD 在 ZooKeeper 中特别有效,它需要快速、低延迟的数据访问。

注意

您不需要置备复制存储,因为 Kafka 和 ZooKeeper 都内置了数据复制。

2.1.3.2. 临时存储

临时存储使用 emptyDir 卷来存储数据。要使用临时存储,请将 type 字段设置为 ephemeral

重要

emptyDir 卷不是持久性的,存储在其中的数据会在 pod 重启时丢失。新 pod 启动后,它必须从集群的其他节点恢复所有数据。临时存储不适用于单节点 ZooKeeper 集群,或者适用于复制因数为 1 的 Kafka 主题。此配置将导致数据丢失。

临时存储示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
    storage:
      type: ephemeral
    # ...
  zookeeper:
    # ...
    storage:
      type: ephemeral
    # ...

2.1.3.2.1. 日志目录

Kafka 代理使用临时卷作为挂载到以下路径的日志目录:

/var/lib/kafka/data/kafka-logIDX

其中 IDX 是 Kafka 代理 pod 索引。例如 /var/lib/kafka/data/kafka-log0。

2.1.3.3. 持久性存储

永久存储使用持久卷声明 来调配用于存储数据的持久卷。持久卷声明可用于调配许多不同类型的卷,具体取决于要调配卷的 存储类。可以与持久卷声明一起使用的数据类型包括许多类型的 SAN 存储 和本地持久卷

若要使用持久存储,必须将 type 设置为 persistent-claim。持久性存储支持额外的配置选项:

id (可选)
存储标识号.对于 JBOD 存储声明中定义的存储卷,此选项是必需的。默认值为 0
大小 (必需)
定义持久卷声明的大小,如 "1000Gi"。
class (可选)
用于动态卷置备的 OpenShift 存储类
selector (可选)
允许选择要使用的特定持久性卷。它包含键:值对,代表用于选择此类卷的标签。
deleteClaim (optional)
指定在取消部署集群时是否需要删除持久卷声明的布尔值。默认为 false
警告

仅支持重新定义持久性卷大小的 OpenShift 版本支持在现有 AMQ Streams 集群中增加持久性卷的大小。要调整持久性卷的大小必须使用支持卷扩展的存储类。对于不支持卷扩展的其他 OpenShift 版本和存储类,您必须在部署集群前决定必要的存储大小。无法减少现有持久性卷的大小。

使用 1000Gi 大小的持久性存储配置片段示例

# ...
storage:
  type: persistent-claim
  size: 1000Gi
# ...

以下示例演示了存储类的使用。

使用特定存储类的持久性存储配置片段示例

# ...
storage:
  type: persistent-claim
  size: 1Gi
  class: my-storage-class
# ...

最后,可以利用 选择器 来选择特定的标记持久卷,以提供 SSD 等必要功能。

使用选择器的持久性存储配置片段示例

# ...
storage:
  type: persistent-claim
  size: 1Gi
  selector:
    hdd-type: ssd
  deleteClaim: true
# ...

2.1.3.3.1. 存储类覆盖

您可以为一个或多个 Kafka 代理或 ZooKeeper 节点指定不同的存储类,而不是使用默认存储类。例如,当存储类仅限于不同的可用区或数据中心时,这很有用。您可以使用 overrides 字段来实现这一目的。

在本例中,默认存储类名为 my-storage-class

使用存储类覆盖的 AMQ Streams 集群示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  labels:
    app: my-cluster
  name: my-cluster
  namespace: myproject
spec:
  # ...
  kafka:
    replicas: 3
    storage:
      deleteClaim: true
      size: 100Gi
      type: persistent-claim
      class: my-storage-class
      overrides:
        - broker: 0
          class: my-storage-class-zone-1a
        - broker: 1
          class: my-storage-class-zone-1b
        - broker: 2
          class: my-storage-class-zone-1c
  # ...
  zookeeper:
    replicas: 3
    storage:
      deleteClaim: true
      size: 100Gi
      type: persistent-claim
      class: my-storage-class
      overrides:
        - broker: 0
          class: my-storage-class-zone-1a
        - broker: 1
          class: my-storage-class-zone-1b
        - broker: 2
          class: my-storage-class-zone-1c
  # ...

配置的 overrides 属性后,卷使用以下存储类:

  • ZooKeeper 节点 0 的持久卷将使用 my-storage-class-zone-1a
  • ZooKeeper 节点 1 的持久卷将使用 my-storage-class-zone-1b
  • ZooKeeepr 节点 2 的持久卷将使用 my-storage-class-zone-1c
  • Kafka 代理 0 的持久性卷将使用 my-storage-class-zone-1a
  • Kafka 代理 1 的持久性卷将使用 my-storage-class-zone-1b
  • Kafka 代理 2 的持久性卷将使用 my-storage-class-zone-1c

overrides 属性目前只用于覆盖存储类配置。目前不支持覆盖其他存储配置字段。目前不支持存储配置中的其他字段。

2.1.3.3.2. 持久性卷声明命名

使用持久性存储时,它会使用以下名称创建持久性卷声明:

data-cluster-name-kafka-idx
用于存储 Kafka 代理 pod IDx 数据的卷的持久性卷声明。
data-cluster-name-zookeeper-idx
用于为 ZooKeeper 节点 pod idx 存储数据的卷的持久性卷声明。
2.1.3.3.3. 日志目录

Kafka 代理使用持久性卷作为挂载到以下路径的日志目录:

/var/lib/kafka/data/kafka-logIDX

其中 IDX 是 Kafka 代理 pod 索引。例如 /var/lib/kafka/data/kafka-log0。

2.1.3.4. 重新定义持久性卷大小

您可以通过增大现有 AMQ Streams 集群使用的持久性卷的大小来置备存储容量。在使用一个持久性卷或在 JBOD 存储配置中使用多个持久性卷的集群中,支持重新定义持久性卷大小。

注意

您可以增大但不能缩小持久性卷的大小。OpenShift 目前不支持缩小持久卷的大小。

先决条件

  • 个 OpenShift 集群,其支持卷大小调整。
  • Cluster Operator 正在运行。
  • 使用使用支持卷扩展的存储类创建的持久性卷的 Kafka 集群。

流程

  1. Kafka 资源中,增大分配给 Kafka 集群和 ZooKeeper 集群的持久性卷的大小。

    • 要增大分配给 Kafka 集群的卷大小,编辑 spec.kafka.storage 属性。
    • 要增大分配给 ZooKeeper 集群的卷大小,请编辑 spec.zookeeper.storage 属性。

      例如,将卷大小从 1000Gi 增加到 2000Gi

      apiVersion: kafka.strimzi.io/v1beta2
      kind: Kafka
      metadata:
        name: my-cluster
      spec:
        kafka:
          # ...
          storage:
            type: persistent-claim
            size: 2000Gi
            class: my-storage-class
          # ...
        zookeeper:
          # ...
  2. 创建或更新资源:

    oc apply -f KAFKA-CONFIG-FILE

    OpenShift 会响应来自 Cluster Operator 的请求,增加了所选持久性卷的容量。完成大小调整后,Cluster Operator 会重启所有使用调整大小持久性卷的 pod。这会自动发生。

其它资源

有关在 OpenShift 中调整持久性卷大小的更多信息,请参阅使用 Kubernetes 重新定义持久性卷 大小。

2.1.3.5. JBOD 存储概述

您可以将 AMQ Streams 配置为使用 JBOD,这是多个磁盘或卷的数据存储配置。JBOD 是为 Kafka 代理提供更多数据存储的一种方法。它还能提高性能。

一个或多个卷描述了 JBOD 配置,每个卷可以 临时 或永久 JBOD 卷声明的规则和限制与临时和永久存储的规则和限制相同。例如,您不能在置备后缩小持久性存储卷的大小,或者 type=ephemeral 时您无法更改 sizeLimit 的值。

2.1.3.5.1. JBOD 配置

若要将 JBOD 与 AMQ Streams 搭配使用,存储 类型 必须设置为 jbod。借助 volumes 属性,您可以描述组成 JBOD 存储阵列或配置的磁盘。以下片段显示了 JBOD 配置示例:

# ...
storage:
  type: jbod
  volumes:
  - id: 0
    type: persistent-claim
    size: 100Gi
    deleteClaim: false
  - id: 1
    type: persistent-claim
    size: 100Gi
    deleteClaim: false
# ...

创建 JBOD 卷后,无法更改 id。

用户可以从 JBOD 配置中添加或删除卷。

2.1.3.5.2. JBOD 和持久性卷声明

当使用持久性存储声明 JBOD 卷时,生成的持久性卷声明的命名方案如下:

data-id-cluster-name-kafka-idx
其中 id 是用于存储 Kafka 代理 pod idx 数据的卷 ID。
2.1.3.5.3. 日志目录

Kafka 代理将使用 JBOD 卷作为挂载到以下路径的日志目录:

/var/lib/kafka/data-id/kafka-log_idx_
其中 id 是用于存储 Kafka 代理 pod idx 数据的卷 ID。例如 /var/lib/kafka/data-0/kafka-log0。
2.1.3.6. 将卷添加到 JBOD 存储

这个步骤描述了如何在配置为使用 JBOD 存储的 Kafka 集群中添加卷。它不能应用到配置为使用任何其他存储类型的 Kafka 集群。

注意

在已经使用并被删除的 id 下添加新卷时,您必须确保之前使用的 PersistentVolumeClaims 已被删除。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator
  • 带有 JBOD 存储的 Kafka 集群

流程

  1. 编辑 Kafka 资源中的 spec.kafka.storage.volumes 属性。将新卷添加到 volumes 数组。例如,添加 ID 为 2 的新卷:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        # ...
        storage:
          type: jbod
          volumes:
          - id: 0
            type: persistent-claim
            size: 100Gi
            deleteClaim: false
          - id: 1
            type: persistent-claim
            size: 100Gi
            deleteClaim: false
          - id: 2
            type: persistent-claim
            size: 100Gi
            deleteClaim: false
        # ...
      zookeeper:
        # ...
  2. 创建或更新资源:

    oc apply -f KAFKA-CONFIG-FILE
  3. 创建新主题或将现有分区重新分配至新磁盘.

其它资源

有关重新分配主题的详情请参考 第 2.1.4.2 节 “分区重新分配”

2.1.3.7. 从 JBOD 存储中删除卷

这个步骤描述了如何从配置为使用 JBOD 存储的 Kafka 集群中删除卷。它不能应用到配置为使用任何其他存储类型的 Kafka 集群。JBOD 存储始终必须至少包含一个卷。

重要

为避免数据丢失,您必须先移动所有分区,然后再删除卷。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator
  • 带有两个或多个卷的 JBOD 存储的 Kafka 集群

流程

  1. 从要删除的磁盘中重新分配所有分区。分区中仍然分配到将要删除的磁盘中的任何数据都可能会丢失。
  2. 编辑 Kafka 资源中的 spec.kafka.storage.volumes 属性。从 volumes 阵列中删除一个或多个 。例如,删除 ID 为 12 的卷:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        # ...
        storage:
          type: jbod
          volumes:
          - id: 0
            type: persistent-claim
            size: 100Gi
            deleteClaim: false
        # ...
      zookeeper:
        # ...
  3. 创建或更新资源:

    oc apply -f KAFKA-CONFIG-FILE

其它资源

有关重新分配主题的详情请参考 第 2.1.4.2 节 “分区重新分配”

2.1.4. 扩展集群

2.1.4.1. 扩展 Kafka 集群
2.1.4.1.1. 在集群中添加代理

提高某个主题吞吐量的主要方法是增加该主题的分区数量。这是因为额外的分区允许在集群中的不同代理之间共享该主题的负载。但是,如果每个代理都受到使用更多分区的特定资源(通常是 I/O)限制,则不会增加吞吐量。相反,您需要在集群中添加代理。

当您在集群中添加额外的代理时,Kafka 不会自动为其分配任何分区。您必须决定从现有代理迁移到新代理的分区。

在所有代理之间重新分布分区后,应该减少每个代理的资源利用率。

2.1.4.1.2. 从集群中删除代理

因为 AMQ Streams 使用 StatefulSet 来管理代理 Pod,所以 您无法从集群中删除 任何 pod。您只能从集群中移除一个或多个数字最高的 pod。例如,在一个有 12 个代理的集群中,pod 被命名为 cluster-name-kafka-0 to cluster-name-kafka-11。如果您决定缩减一个代理,则会删除 cluster-name-kafka-11

在从集群中删除代理前,请确保它没有被分配给任何分区。您还应决定剩余的代理中哪些将负责要停用代理中的每个分区。代理没有分配分区后,您可以安全地缩减集群。

2.1.4.2. 分区重新分配

Topic Operator 目前不支持将副本分配给不同的代理,因此需要直接连接到代理 Pod 以将副本分配到代理。

在代理 pod 中,kafka-reassign-partitions.sh 实用程序允许您将分区重新分配给不同的代理。

它有三种不同的模式:

--generate
取一组主题和代理,并生成 重新分配 JSON 文件,该文件将导致这些主题的分区分配给这些代理。由于这适用于整个主题,因此当您只想重新分配某些主题的某些分区时,无法使用它。
--execute
重新分配 JSON 文件 并将其应用到集群中的分区和代理。因此获得分区的代理会成为分区领导的追随者。对于给定分区,新代理一旦捕获并加入 ISR(同步副本)后,旧的代理将停止成为追随者,并删除其副本。
--verify
使用与 --execute 步骤相同的 重新分配 JSON 文件,-- verify 检查文件中的所有分区是否已移到其预期代理中。如果重新分配完成后,--verify 也会移除任何有效的 节流。除非被删除,否则节流将继续影响群集,即使重新分配完成后也是如此。

只能在任何给定时间在集群中运行一个重新分配,且无法取消正在运行的重新分配。如果您需要取消重新分配,请等待它完成,然后执行另一个重新分配以恢复第一次重新分配的影响。kafka-reassign-partitions.sh 将显示此重新版本的重新分配 JSON 作为其输出的一部分。在需要停止进行中的重新分配时,应将非常大的重新分配分成几个较小的重新分配。

2.1.4.2.1. 重新分配 JSON 文件

重新分配 JSON 文件 有一个特定的结构:

{
  "version": 1,
  "partitions": [
    <PartitionObjects>
  ]
}

其中 <PartitionObjects> 是一个用逗号分开的对象列表,例如:

{
  "topic": <TopicName>,
  "partition": <Partition>,
  "replicas": [ <AssignedBrokerIds> ]
}
注意

虽然 Kafka 也支持 "log_dirs" 属性,但这不应用于 AMQ Streams。

以下是重新分配 JSON 文件的示例,该文件将 主题 4 的分区 4 分配给代理 2 47,并将 主题 2 的分区 2 分配给 代理 157

{
  "version": 1,
  "partitions": [
    {
      "topic": "topic-a",
      "partition": 4,
      "replicas": [2,4,7]
    },
    {
      "topic": "topic-b",
      "partition": 2,
      "replicas": [1,5,7]
    }
  ]
}

JSON 中没有包括的分区不会更改。

2.1.4.2.2. 在 JBOD 卷间重新分配分区

在 Kafka 集群中使用 JBOD 存储时,您可以选择在特定卷及其日志目录之间重新分配分区(每个卷都有一个日志目录)。要将分区重新分配给特定卷,请将 log_dirs 选项添加到重新分配 JSON 文件中的 <PartitionObjects> 中。

{
  "topic": <TopicName>,
  "partition": <Partition>,
  "replicas": [ <AssignedBrokerIds> ],
  "log_dirs": [ <AssignedLogDirs> ]
}

log_dirs 对象应包含与 replicas 对象中指定的副本数相同的日志目录 数量。该值应当是日志目录的绝对路径或 any 关键字。

例如:

{
      "topic": "topic-a",
      "partition": 4,
      "replicas": [2,4,7].
      "log_dirs": [ "/var/lib/kafka/data-0/kafka-log2", "/var/lib/kafka/data-0/kafka-log4", "/var/lib/kafka/data-0/kafka-log7" ]
}
2.1.4.3. 生成重新分配 JSON 文件

此流程描述了如何生成重新分配 JSON 文件,该文件使用 kafka-reassign-partitions.sh 工具为给定主题集重新分配所有分区。

先决条件

  • 一个正在运行的 Cluster Operator
  • Kafka 资源
  • 重新分配分区的一组主题

流程

  1. 准备名为 topic .json 的 JSON 文件,其中列出要移动的主题。它必须具有以下结构:

    {
      "version": 1,
      "topics": [
        <TopicObjects>
      ]
    }

    其中 <TopicObjects> 是一个以逗号分隔的对象列表,例如:

    {
      "topic": <TopicName>
    }

    例如,如果要重新分配 topic-a 和 topic- b 的所有 分区,则需要准备类似以下的 topic .json 文件:

    {
      "version": 1,
      "topics": [
        { "topic": "topic-a"},
        { "topic": "topic-b"}
      ]
    }
  2. topic.json 文件复制到其中一个代理 pod 中:

    cat topics.json | oc exec -c kafka <BrokerPod> -i -- \
      /bin/bash -c \
      'cat > /tmp/topics.json'
  3. 使用 kafka-reassign-partitions.sh 命令生成重新分配 JSON。

    oc exec <BrokerPod> -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --topics-to-move-json-file /tmp/topics.json \
      --broker-list <BrokerList> \
      --generate

    例如,将 topic-a 和 topic- b 的所有分区移动到 broker 47

    oc exec <BrokerPod> -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --topics-to-move-json-file /tmp/topics.json \
      --broker-list 4,7 \
      --generate
2.1.4.4. 手动创建重新分配 JSON 文件

如果要移动特定的分区,可以手动创建重新分配 JSON 文件。

2.1.4.5. 重新分配节流

分区重新分配可能是一个缓慢的过程,因为它涉及到在代理之间传输大量数据。为避免对客户端造成重大影响,您可以限制重新分配过程。这可能会导致重新分配需要更长的时间。

  • 如果限流太低,新分配的代理将无法与正在发布的记录保持同步,并且重新分配永远不会完成。
  • 如果限流太高,客户端就会受到影响。

例如,对于制作者而言,这可能会比等待确认的正常延迟更高。对于消费者而言,这可能会因为轮询之间延迟较高而导致吞吐量下降。

2.1.4.6. 扩展 Kafka 集群

这个步骤描述了如何在 Kafka 集群中增加代理数量。

先决条件

  • 现有的 Kafka 集群。
  • 名为 reassignment .json 的重新分配 JSON 文件 描述了如何在放大的集群中将分区重新分配给代理。

流程

  1. 通过增加 Kafka.spec.kafka.replicas 配置选项,根据需要添加多个新代理。
  2. 验证新代理 Pod 是否已启动。
  3. reassignment.json 文件复制到您稍后要执行命令的代理 pod 中:

    cat reassignment.json | \
      oc exec broker-pod -c kafka -i -- /bin/bash -c \
      'cat > /tmp/reassignment.json'

    例如:

    cat reassignment.json | \
      oc exec my-cluster-kafka-0 -c kafka -i -- /bin/bash -c \
      'cat > /tmp/reassignment.json'
  4. 使用同一代理 pod 的 kafka-reassign-partitions.sh 命令行工具执行分区重新分配。

    oc exec broker-pod -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --execute

    如果您要节流复制,您也可以使用 --throttle 选项,每秒使用节流率(以字节为单位)。例如:

    oc exec my-cluster-kafka-0 -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 5000000 \
      --execute

    此命令将显示两个重新分配 JSON 对象:第一个记录了正在移动的分区的当前分配。如果稍后需要恢复重新分配,您应该将其保存到本地文件(而不是 pod 中的文件)。第二个 JSON 对象是您在重新分配 JSON 文件中传递的目标重新分配。

  5. 如果您需要在重新分配期间更改节流,您可以使用具有不同节流率的同一命令行。例如:

    oc exec my-cluster-kafka-0 -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 10000000 \
      --execute
  6. 定期验证是否使用任何代理 Pod 的 kafka-reassign-partitions.sh 命令行工具完成重新分配。这与上一步中的命令相同,但使用 --verify 选项而不是 --execute 选项。

    oc exec broker-pod -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --verify

    例如:

    oc exec my-cluster-kafka-0 -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --verify
  7. --verify 命令报告每个分区成功完成时,重新分配已完成。最后的 --verify 还会导致移除任何重新分配节流。现在,如果您保存了 JSON,将分配还原到其原始代理中,您可以删除还原文件。
2.1.4.7. 缩减 Kafka 集群

这个步骤描述了如何减少 Kafka 集群中的代理数量。

先决条件

  • 现有的 Kafka 集群。
  • 名为 reassignment .json 的重新分配 JSON 文件 描述在 删除了最高编号 Pod 中的代理后,应如何将 分区重新分配给集群中的代理。

流程

  1. reassignment.json 文件复制到您稍后要执行命令的代理 pod 中:

    cat reassignment.json | \
      oc exec broker-pod -c kafka -i -- /bin/bash -c \
      'cat > /tmp/reassignment.json'

    例如:

    cat reassignment.json | \
      oc exec my-cluster-kafka-0 -c kafka -i -- /bin/bash -c \
      'cat > /tmp/reassignment.json'
  2. 使用同一代理 pod 的 kafka-reassign-partitions.sh 命令行工具执行分区重新分配。

    oc exec broker-pod -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --execute

    如果您要节流复制,您也可以使用 --throttle 选项,每秒使用节流率(以字节为单位)。例如:

    oc exec my-cluster-kafka-0 -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 5000000 \
      --execute

    此命令将显示两个重新分配 JSON 对象:第一个记录了正在移动的分区的当前分配。如果稍后需要恢复重新分配,您应该将其保存到本地文件(而不是 pod 中的文件)。第二个 JSON 对象是您在重新分配 JSON 文件中传递的目标重新分配。

  3. 如果您需要在重新分配期间更改节流,您可以使用具有不同节流率的同一命令行。例如:

    oc exec my-cluster-kafka-0 -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 10000000 \
      --execute
  4. 定期验证是否使用任何代理 Pod 的 kafka-reassign-partitions.sh 命令行工具完成重新分配。这与上一步中的命令相同,但使用 --verify 选项而不是 --execute 选项。

    oc exec broker-pod -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --verify

    例如:

    oc exec my-cluster-kafka-0 -c kafka -it -- \
      bin/kafka-reassign-partitions.sh --bootstrap-server localhost:9092 \
      --reassignment-json-file /tmp/reassignment.json \
      --verify
  5. --verify 命令报告每个分区成功完成时,重新分配已完成。最后的 --verify 还会导致移除任何重新分配节流。现在,如果您保存了 JSON,将分配还原到其原始代理中,您可以删除还原文件。
  6. 所有分区重新分配完成后,删除的代理不应对集群中的任何分区负责。您可以通过检查代理的数据日志目录是否包含任何实时分区日志来验证这一点。如果代理上的日志目录包含与扩展正则表达式 [a-zA-Z0-9.-]+\ 不匹配的目录。[a-z0-9]+-delete$ 仍然具有实时分区,不应停止。

    您可以执行以下命令检查:

    oc exec my-cluster-kafka-0 -c kafka -it -- \
      /bin/bash -c \
      "ls -l /var/lib/kafka/kafka-log_<N>_ | grep -E '^d' | grep -vE '[a-zA-Z0-9.-]+\.[a-z0-9]+-delete$'"

    其中 N 是要删除的 Pod 数。

    如果上述命令显示任何输出,则代理仍然有实时分区。在这种情况下,重新分配没有完成,或者重新分配 JSON 文件不正确。

  7. 确认代理没有实时分区后,您可以编辑 Kafka.spec.kafka.replicas 资源的 Kafka. spec.kafka.replicas,这会缩减 StatefulSet从而删除最高数字的代理 Pod。

2.1.5. 用于滚动更新的维护时间窗

通过维护时间窗,您可以计划对 Kafka 和 ZooKeeper 集群进行某些滚动更新,以便在方便的时间启动。

2.1.5.1. 维护时间窗概述

在大多数情况下,Cluster Operator 只更新 Kafka 或 ZooKeeper 集群,以响应对对应 Kafka 资源的更改。这可让您计划何时对 Kafka 资源应用更改,以最大程度降低对 Kafka 客户端应用程序的影响。

但是,在不对 Kafka 资源 进行任何相应的更改的情况下,可能会对 Kafka 和 ZooKeeper 集群进行一些更新。例如,如果 Cluster Operator 管理的 CA(证书授权机构)证书接近到期时间,则 Cluster Operator 将需要执行滚动重启。

虽然 pod 的滚动重启不应影响服务 的可用性 (假设正确的代理和主题配置),这可能会影响 Kafka 客户端应用程序 的性能。通过维护时间窗,您可以调度 Kafka 和 ZooKeeper 集群的自发滚动更新,以便在方便的时间开始。如果没有为群集配置维护时间窗,那么这种自发滚动更新可能会在不方便的时间(如在可预测的高负载期间)发生。

2.1.5.2. 维护时间窗定义

您可以通过在 Kafka.spec.maintenanceTimeWindows 属性中输入字符串数组来配置维护时间窗。每个字符串是一个 cron 表达式,解释为使用 UTC(协调世界时间,其实际用途与 Greenwich Mean Time 相同)。

以下示例配置了一个维护时间窗口,该时间窗口从午夜开始,到 01:59am(UTC)、周日、周一、星期二和周四结束:

# ...
maintenanceTimeWindows:
  - "* * 0-1 ? * SUN,MON,TUE,WED,THU *"
# ...

在实践中,维护窗口应当与 Kafka.spec.clusterCa.renewalDaysKafka.spec.clientsCa.renewalDays 属性一同设置,以确保在 配置的维护时间窗口中完成必要的 CA 证书续订。

注意

AMQ Streams 不完全根据给定的窗口调度维护操作。相反,对于每个协调,它会检查维护窗口当前是否"打开"。这意味着,给定时间窗内的维护操作启动可能会被 Cluster Operator 协调间隔延迟。因此维护时间窗必须至少是这个长。

其它资源

2.1.5.3. 配置维护时间窗

您可以配置维护时间窗,用于由支持的进程触发的滚动更新。

先决条件

  • OpenShift 集群。
  • Cluster Operator 正在运行。

流程

  1. Kafka 资源中添加或编辑 maintenanceTimeWindows 属性。例如,允许在 0800 到 1059 之间以及 1400 到 1559 之间的维护,您可以设置 maintenanceTimeWindows,如下所示:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        # ...
      zookeeper:
        # ...
      maintenanceTimeWindows:
        - "* * 8-10 * * ?"
        - "* * 14-15 * * ?"
  2. 创建或更新资源:

    oc apply -f KAFKA-CONFIG-FILE

其它资源

执行滚动更新:

2.1.6. 从终端连接到 ZooKeeper

大多数 Kafka CLI 工具可以直接连接到 Kafka,因此在正常情况下,您不需要连接到 ZooKeeper。zookeeper 服务通过加密和身份验证进行保护,它们不应该由不属于 AMQ Streams 的外部应用程序使用。

但是,如果要使用需要连接到 ZooKeeper 的 Kafka CLI 工具,您可以使用 ZooKeeper 容器中的终端,并连接 localhost:12181 作为 ZooKeeper 地址。

先决条件

  • OpenShift 集群可用。
  • Kafka 集群正在运行。
  • Cluster Operator 正在运行。

流程

  1. 使用 OpenShift 控制台打开终端,或者从 CLI 运行 exec 命令。

    例如:

    oc exec -ti my-cluster-zookeeper-0 -- bin/kafka-topics.sh --list --zookeeper localhost:12181

    务必使用 localhost:12181

    现在,您可以向 ZooKeeper 运行 Kafka 命令。

2.1.7. 手动删除 Kafka 节点

此流程描述了如何使用 OpenShift 注解删除现有 Kafka 节点。删除 Kafka 节点包括删除运行 Kafka 代理的 Pod 和相关的 PersistentVolumeClaim (如果集群部署了持久性存储)。删除后,Pod 及其相关的 PersistentVolumeClaim 会被自动重新创建。

警告

删除 PersistentVolumeClaim 可能会导致持久性数据丢失。只有在您遇到存储问题时才应执行以下步骤。

先决条件

有关运行 以下的说明,请参阅 OpenShift 指南中的部署和升级 AMQ Streams

流程

  1. 查找您要删除的 Pod 的名称。

    例如,如果集群命名为 cluster-name,pod 被命名为 cluster-name-kafka-index,其中 索引 以零开始,结尾是副本总数。

  2. 给 OpenShift 中的 容器集资源标注:

    使用 oc annotate:

    oc annotate pod cluster-name-kafka-index strimzi.io/delete-pod-and-pvc=true
  3. 等待下一次协调,当带有底层持久性卷声明的注解的 pod 被删除后再重新创建。

2.1.8. 手动删除 ZooKeeper 节点

此流程描述了如何使用 OpenShift 注释删除现有的 ZooKeeper 节点。删除 ZooKeeper 节点包括删除运行 ZooKeeper 的 Pod 和相关的 PersistentVolumeClaim (如果集群部署了持久性存储)。删除后,Pod 及其相关的 PersistentVolumeClaim 会被自动重新创建。

警告

删除 PersistentVolumeClaim 可能会导致持久性数据丢失。只有在您遇到存储问题时才应执行以下步骤。

先决条件

有关运行 以下的说明,请参阅 OpenShift 指南中的部署和升级 AMQ Streams

流程

  1. 查找您要删除的 Pod 的名称。

    例如,如果集群名为 cluster-name,pod 被命名为 cluster-name-zookeeper-index,其中 索引 从零开始,结尾是副本总数。

  2. 给 OpenShift 中的 容器集资源标注:

    使用 oc annotate:

    oc annotate pod cluster-name-zookeeper-index strimzi.io/delete-pod-and-pvc=true
  3. 等待下一次协调,当带有底层持久性卷声明的注解的 pod 被删除后再重新创建。

2.1.9. Kafka 集群资源列表

以下资源由 OpenShift 集群中的 Cluster Operator 创建:

共享资源

cluster-name-cluster-ca
使用用于加密集群通信的集群 CA 私钥的机密。
cluster-name-cluster-ca-cert
使用 Cluster CA 公钥的 secret。这个密钥可以用来验证 Kafka 代理的身份。
cluster-name-clients-ca
带有用于签署用户证书的 Clients CA 私钥的 secret
cluster-name-clients-ca-cert
使用 Clients CA 公钥的机密。此密钥可用于验证 Kafka 用户的身份。
cluster-name-cluster-operator-certs
使用集群操作器密钥与 Kafka 和 ZooKeeper 通信的机密。

zookeeper 节点

cluster-name-zookeeper
StatefulSet,它负责管理 ZooKeeper 节点 pod。
cluster-name-zookeeper-idx
由 Zookeeper StatefulSet 创建的 Pod。
cluster-name-zookeeper-nodes
无头服务需要直接解析 ZooKeeper pod IP 地址。
cluster-name-zookeeper-client
Kafka 代理用于连接 ZooKeeper 节点的服务作为客户端。
cluster-name-zookeeper-config
包含 ZooKeeper 辅助配置的 ConfigMap,由 ZooKeeper 节点 pod 挂载为卷。
cluster-name-zookeeper-nodes
使用 ZooKeeper 节点密钥的机密。
cluster-name-zookeeper
Zookeeper 节点使用的服务帐户。
cluster-name-zookeeper
为 ZooKeeper 节点配置的 Pod Disruption Budget。
cluster-name-network-policy-zookeeper
管理对 ZooKeeper 服务访问的网络策略.
data-cluster-name-zookeeper-idx
用于为 ZooKeeper 节点 pod idx 存储数据的卷的持久性卷声明。只有在选择了持久存储来调配持久卷以存储数据时,才会创建此资源。

Kafka 代理

cluster-name-kafka
StatefulSet,它负责管理 Kafka 代理 pod。
cluster-name-kafka-idx
由 Kafka StatefulSet 创建的 Pod。
cluster-name-kafka-brokers
需要 DNS 直接解析 Kafka 代理 Pod IP 地址的服务。
cluster-name-kafka-bootstrap
服务可用作从 OpenShift 集群内连接的 Kafka 客户端的 bootstrap 服务器。
cluster-name-kafka-external-bootstrap
为从 OpenShift 集群外部连接的客户端引导服务。只有在启用了外部侦听器时才创建此资源。当监听器名称为 外部 并且端口为 9094 时,旧服务名称将用于向后兼容。
cluster-name-kafka-pod-id
用于将流量从 OpenShift 集群外部路由到单个容器集的服务。只有在启用了外部侦听器时才创建此资源。当监听器名称为 外部 并且端口为 9094 时,旧服务名称将用于向后兼容。
cluster-name-kafka-external-bootstrap
从 OpenShift 集群外部连接的客户端的引导路由。只有在启用了外部侦听器并设置为 type route 时才会创建此资源。当监听器名称为 外部 并且端口为 9094 时,旧路由名称将用于向后兼容。
cluster-name-kafka-pod-id
从 OpenShift 集群外部的流量路由到单个容器集。只有在启用了外部侦听器并设置为 type route 时才会创建此资源。当监听器名称为 外部 并且端口为 9094 时,旧路由名称将用于向后兼容。
cluster-name-kafka-listener-name-bootstrap
为从 OpenShift 集群外部连接的客户端引导服务。只有在启用了外部侦听器时才创建此资源。新服务名称将用于所有其他外部侦听器。
cluster-name-kafka-listener-name-pod-id
用于将流量从 OpenShift 集群外部路由到单个容器集的服务。只有在启用了外部侦听器时才创建此资源。新服务名称将用于所有其他外部侦听器。
cluster-name-kafka-listener-name-bootstrap
从 OpenShift 集群外部连接的客户端的引导路由。只有在启用了外部侦听器并设置为 type route 时才会创建此资源。新路由名称将用于所有其他外部侦听器。
cluster-name-kafka-listener-name-pod-id
从 OpenShift 集群外部的流量路由到单个容器集。只有在启用了外部侦听器并设置为 type route 时才会创建此资源。新路由名称将用于所有其他外部侦听器。
cluster-name-kafka-config
包含 Kafka 辅助配置且由 Kafka 代理 Pod 挂载为卷的 ConfigMap。
cluster-name-kafka-brokers
使用 Kafka 代理密钥的 secret。
cluster-name-kafka
Kafka 代理使用的服务帐户。
cluster-name-kafka
为 Kafka 代理配置的 Pod Disruption Budget。
cluster-name-network-policy-kafka
管理对 Kafka 服务访问的网络策略。
strimzi-namespace-name-cluster-name-kafka-init
Kafka 代理使用的集群角色绑定。
cluster-name-jmx
用来保护 Kafka 代理端口的 JMX 用户名和密码的 secret。只有在 Kafka 中启用了 JMX 时才会创建此资源。
data-cluster-name-kafka-idx
用于存储 Kafka 代理 pod IDx 数据的卷的持久性卷声明。只有在选择了持久存储来调配持久卷以存储数据时才创建此资源。
data-id-cluster-name-kafka-idx
用于存储 Kafka 代理 pod ID 的卷 ID 的 持久性卷声明。只有在调配持久卷以存储数据时,才会为 JBOD 卷选择持久存储时创建此资源。

实体 Operator

只有在使用 Cluster Operator 部署 Entity Operator 时才会创建这些资源。

cluster-name-entity-operator
使用主题和用户操作器进行部署.
cluster-name-entity-operator-random-string
由 Entity Operator 部署创建的 Pod。
cluster-name-entity-topic-operator-config
带有主题 Operator 辅助配置的 ConfigMap。
cluster-name-entity-user-operator-config
带有用户 Operator 辅助配置的 ConfigMap.
cluster-name-entity-operator-certs
使用 Entity Operator 密钥与 Kafka 和 ZooKeeper 通信的 secret。
cluster-name-entity-operator
Entity Operator 使用的服务帐户。
strimzi-cluster-name-entity-topic-operator
Entity Topic Operator 使用的角色绑定。
strimzi-cluster-name-entity-user-operator
Entity User Operator 使用的角色绑定。

Kafka Exporter

只有在使用 Cluster Operator 部署 Kafka Exporter 时才会创建这些资源。

cluster-name-kafka-exporter
使用 Kafka 导出器部署.
cluster-name-kafka-exporter-random-string
由 Kafka Exporter 部署创建的 Pod。
cluster-name-kafka-exporter
用于收集消费者滞后指标的服务.
cluster-name-kafka-exporter
Kafka Exporter 使用的服务帐户。

Sything Control

只有在使用 Cluster Operator 部署 Cruise Control 时才会创建这些资源。

cluster-name-cruise-control
通过 Cruise 控制进行部署.
cluster-name-cruise-control-random-string
由 Cruise Control 部署创建的 Pod。
cluster-name-cruise-control-config
包含 Cruise Control 辅助配置的 ConfigMap,并被 Cruise Control pod 作为一个卷挂载。
cluster-name-cruise-control-certs
使用 Cruise Control 密钥与 Kafka 和 ZooKeeper 通信的机密。
cluster-name-cruise-control
用于与 Cruise Control 通信的服务.
cluster-name-cruise-control
Cruise Control 使用的服务帐户.
cluster-name-network-policy-cruise-control
管理对 Cruise 控制服务的访问的网络策略.

2.2. Kafka Connect/S2I 集群配置

本节论述了如何在 AMQ Streams 集群中配置 Kafka Connect 或 Kafka Connect with Source-to-Image(S2I)部署。

Kafka Connect 是一个集成工具包,用于使用连接器插件在 Kafka 代理和其他系统间流传输数据。Kafka Connect 提供了一个框架,用于将 Kafka 与外部数据源或目标(如数据库)集成,以使用连接器导入或导出数据。连接器是提供所需连接配置的插件。

如果使用 Kafka Connect,您可以配置 KafkaConnect 或 KafkaConnect S2I 资源。如果您使用 Source-to-Image( S2I )框架来部署 Kafka Connect,请使用 KafkaConnectS2I 资源。

重要

随着 KafkaConnect 资源引入 构建配置,AMQ Streams 现在可以使用数据连接所需的连接器插件自动构建容器镜像。因此,使用 Source-to-Image(S2I)进行 Kafka Connect 的支持已弃用,并将在 AMQ Streams 1.8 后被删除。要准备此更改,您可以将 Kafka Connect S2I 实例迁移到 Kafka Connect 实例

2.2.1. 配置 Kafka 连接

使用 Kafka Connect 设置到 Kafka 集群的外部数据连接。

使用 KafkaConnect 或 KafkaConnect S2I 资源的属性来配置 Kafka Connect 部署。此流程中演示的示例适用于 KafkaConnect 资源,但 KafkaConnectS2I 资源的属性相同。

Kafka 连接器配置

KafkaConnector 资源允许您以 OpenShift 原生方式为 Kafka Connect 创建和管理连接器实例。

在 Kafka Connect 配置中,您可以通过添加 strimzi.io/use-connector-resources 注解为 Kafka Connect 集群启用 KafkaConnectors。您还可以添加 构建配置,以便 AMQ Streams 会自动构建带有数据连接所需的连接器插件的容器镜像。Kafka Connect 连接器的外部配置通过 externalConfiguration 属性指定。

要管理连接器,您可以使用 Kafka Connect REST API,或使用 KafkaConnector 自定义资源。KafkaConnector 资源必须部署到与其链接的 Kafka Connect 集群相同的命名空间中。有关使用这些方法创建、重新配置或删除连接器的更多信息,请参阅 OpenShift 上部署和升级 AMQ Streams 中的创建和管理连接器

连接器配置作为 HTTP 请求的一部分传递给 Kafka Connect,并存储在 Kafka 本身中。ConfigMap 和机密是用于存储配置和机密数据的标准 OpenShift 资源。您可以使用 ConfigMap 和 Secret 配置连接器的某些元素。然后,您可以引用 HTTP REST 命令中的配置值,以便在需要时保持配置独立和安全。这个方法尤其适用于机密数据,如用户名、密码或证书。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

有关运行 以下的说明,请参阅 OpenShift 指南中的部署和升级 AMQ Streams

流程

  1. 编辑 KafkaConnect 或 KafkaConnect S2I 资源的 spec 属性。

    您可以配置的属性显示在此示例配置中:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect 1
    metadata:
      name: my-connect-cluster
      annotations:
        strimzi.io/use-connector-resources: "true" 2
    spec:
      replicas: 3 3
      authentication: 4
        type: tls
        certificateAndKey:
          certificate: source.crt
          key: source.key
          secretName: my-user-source
      bootstrapServers: my-cluster-kafka-bootstrap:9092 5
      tls: 6
        trustedCertificates:
          - secretName: my-cluster-cluster-cert
            certificate: ca.crt
          - secretName: my-cluster-cluster-cert
            certificate: ca2.crt
      config: 7
        group.id: my-connect-cluster
        offset.storage.topic: my-connect-cluster-offsets
        config.storage.topic: my-connect-cluster-configs
        status.storage.topic: my-connect-cluster-status
        key.converter: org.apache.kafka.connect.json.JsonConverter
        value.converter: org.apache.kafka.connect.json.JsonConverter
        key.converter.schemas.enable: true
        value.converter.schemas.enable: true
        config.storage.replication.factor: 3
        offset.storage.replication.factor: 3
        status.storage.replication.factor: 3
      build: 8
        output: 9
          type: docker
          image: my-registry.io/my-org/my-connect-cluster:latest
          pushSecret: my-registry-credentials
        plugins: 10
          - name: debezium-postgres-connector
            artifacts:
              - type: tgz
                url: https://repo1.maven.org/maven2/io/debezium/debezium-connector-postgres/1.3.1.Final/debezium-connector-postgres-1.3.1.Final-plugin.tar.gz
                sha512sum: 962a12151bdf9a5a30627eebac739955a4fd95a08d373b86bdcea2b4d0c27dd6e1edd5cb548045e115e33a9e69b1b2a352bee24df035a0447cb820077af00c03
          - name: camel-telegram
            artifacts:
              - type: tgz
                url: https://repo.maven.apache.org/maven2/org/apache/camel/kafkaconnector/camel-telegram-kafka-connector/0.7.0/camel-telegram-kafka-connector-0.7.0-package.tar.gz
                sha512sum: a9b1ac63e3284bea7836d7d24d84208c49cdf5600070e6bd1535de654f6920b74ad950d51733e8020bf4187870699819f54ef5859c7846ee4081507f48873479
      externalConfiguration: 11
        env:
          - name: AWS_ACCESS_KEY_ID
            valueFrom:
              secretKeyRef:
                name: aws-creds
                key: awsAccessKey
          - name: AWS_SECRET_ACCESS_KEY
            valueFrom:
              secretKeyRef:
                name: aws-creds
                key: awsSecretAccessKey
      resources: 12
        requests:
          cpu: "1"
          memory: 2Gi
        limits:
          cpu: "2"
          memory: 2Gi
      logging: 13
        type: inline
        loggers:
          log4j.rootLogger: "INFO"
      readinessProbe: 14
        initialDelaySeconds: 15
        timeoutSeconds: 5
      livenessProbe:
        initialDelaySeconds: 15
        timeoutSeconds: 5
      metricsConfig: 15
        type: jmxPrometheusExporter
        valueFrom:
          configMapKeyRef:
            name: my-config-map
            key: my-key
      jvmOptions: 16
        "-Xmx": "1g"
        "-Xms": "1g"
      image: my-org/my-image:latest 17
      rack:
        topologyKey: topology.kubernetes.io/zone 18
      template: 19
        pod:
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - key: application
                        operator: In
                        values:
                          - postgresql
                          - mongodb
                  topologyKey: "kubernetes.io/hostname"
        connectContainer: 20
          env:
            - name: JAEGER_SERVICE_NAME
              value: my-jaeger-service
            - name: JAEGER_AGENT_HOST
              value: jaeger-agent-name
            - name: JAEGER_AGENT_PORT
              value: "6831"
    1
    根据需要,使用 KafkaConnect 或 KafkaConnectS2I
    2
    为 Kafka Connect 集群启用 KafkaConnectors。
    3
    4
    Kafka Connect 集群的身份验证,使用 TLS 机制 (如下所示)、使用 OAuth bearer 令牌 或基于 SASL 的 SCRAM-SHA-512PLAIN 机制。默认情况下,Kafka Connect 使用纯文本连接连接到 Kafka 代理。
    5
    用于连接到 Kafka Connect 集群的 bootstrap 服务器
    6
    使用密钥名称进行 TLS 加密,在其下,TLS 证书以 X.509 格式存储到集群的 X.509 格式。如果证书存储在同一个 secret 中,则可以多次列出证书。
    7
    Kafka Connect worker 而不是连接器)配置。标准 Apache Kafka 配置可能会提供,仅限于不是由 AMQ Streams 直接管理的属性。
    8
    用于自动使用连接器插件构建容器镜像的 构建配置属性
    9
    (必需)配置推送新镜像的容器注册表。
    10
    (必需)要添加到新容器镜像的连接器插件及其工件列表。每个插件必须至少配置一个 工件
    11
    使用环境变量(如下所示)或卷 为 Kafka 连接器的外部配置。您还可以使用 Kubernetes 配置提供程序 从外部来源加载配置值
    12
    请求保留 支持的资源、当前 cpu 和 memory ,以及限制,以指定可消耗的最大资源。
    13
    指定 Kafka 连接日志记录器和日志级别 直接(内联)或通过ConfigMap 间接(外部)添加。自定义 ConfigMap 必须放在 log4j.properties 或 log4j2.properties 键下。对于 Kafka Connect log4j.rootLogger 日志记录器,您可以将日志级别设置为 INFO、ERROR、WARN、TRACE、DEBUG、FATAL 或 OFF。
    14
    健康检查以了解 何时重新启动容器(存活度)以及容器何时可以接受流量(就绪度)。
    15
    Prometheus metrics,通过引用包含本例中 Prometheus JMX 导出器配置的 ConfigMap 来启用它。您可以使用对包含 metricsConfig.valueFrom.configMapKeyRef.key 下的空文件的 ConfigMap 的引用来启用指标,而无需进一步配置。
    16
    运行 Kafka Connect 的虚拟机(VM)性能优化 JVM 配置选项
    17
    ADVANCED OPTION: 容器镜像配置,只在特殊情况下推荐这样做。
    18
    将机架感知 配置为在不同机架之间分布副本。topologykey 必须与集群节点标签匹配。
    19
    模板自定义.在这里,pod 被调度为反关联性,因此 pod 不会调度到具有相同主机名的节点。
    20
  2. 创建或更新资源:

    oc apply -f KAFKA-CONNECT-CONFIG-FILE
  3. 如果为 Kafka Connect 启用了授权,请配置 Kafka Connect 用户以启用对 Kafka Connect consumer 组和主题的访问

2.2.2. 多个实例的 Kafka Connect 配置

如果您正在运行多个 Kafka Connect 实例,您必须更改以下配置 属性 的默认配置:

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: my-connect
spec:
  # ...
  config:
    group.id: connect-cluster 1
    offset.storage.topic: connect-cluster-offsets 2
    config.storage.topic: connect-cluster-configs 3
    status.storage.topic: connect-cluster-status  4
    # ...
# ...
1
属于该实例的 Kafka Connect 集群组。
2
存储连接器偏移的 Kafka 主题。
3
存储连接器和任务状态配置的 Kafka 主题。
4
存储连接器和任务状态更新的 Kafka 主题。
注意

对于具有同一 group.id 的所有 Kafka Connect 实例,三个主题的值必须相同。

除非更改默认设置,否则每个连接到同一 Kafka 集群的 Kafka Connect 实例都使用相同的值部署。实际上,所有实例都合并在一起,在集群中运行并使用相同的主题。

如果多个 Kafka Connect 集群尝试使用相同的主题,Kafka Connect 将无法按预期工作并生成错误。

如果要运行多个 Kafka Connect 实例,请为每个实例更改这些属性的值。

2.2.3. 配置 Kafka Connect 用户授权

这个步骤描述了如何授权用户对 Kafka Connect 的访问。

当 Kafka 中使用任何类型的授权时,Kafka Connect 用户需要对消费者组的读/写访问权限以及 Kafka Connect 的内部主题。

用户组和内部主题的属性由 AMQ Streams 自动配置,或者可以在 KafkaConnect 或 KafkaConnect S2I 资源的 spec 中明确指定。

KafkaConnect 资源中的配置属性示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: my-connect
spec:
  # ...
  config:
    group.id: my-connect-cluster 1
    offset.storage.topic: my-connect-cluster-offsets 2
    config.storage.topic: my-connect-cluster-configs 3
    status.storage.topic: my-connect-cluster-status 4
    # ...
  # ...

1
属于该实例的 Kafka Connect 集群组。
2
存储连接器偏移的 Kafka 主题。
3
存储连接器和任务状态配置的 Kafka 主题。
4
存储连接器和任务状态更新的 Kafka 主题。

此流程演示了在使用 简单 授权时如何提供访问权限。

简单的授权使用由 Kafka AclAuthorizer 插件处理的 ACL 规则来提供正确的访问级别。有关将 KafkaUser 资源配置为使用简单授权的更多信息,请参阅 AclRule schema 引用

注意

运行多个实例时,使用者组和主题的默认值将有所不同。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 编辑 KafkaUser 资源中 的授权 属性,以便为用户提供访问权限。

    在以下示例中,使用 字面 名称值为 Kafka Connect 主题和消费者组配置访问权限:

    属性名称

    offset.storage.topic

    connect-cluster-offsets

    status.storage.topic

    connect-cluster-status

    config.storage.topic

    connect-cluster-configs

    group

    connect-cluster

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaUser
    metadata:
      name: my-user
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      # ...
      authorization:
        type: simple
        acls:
          # access to offset.storage.topic
          - resource:
              type: topic
              name: connect-cluster-offsets
              patternType: literal
            operation: Write
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-offsets
              patternType: literal
            operation: Create
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-offsets
              patternType: literal
            operation: Describe
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-offsets
              patternType: literal
            operation: Read
            host: "*"
          # access to status.storage.topic
          - resource:
              type: topic
              name: connect-cluster-status
              patternType: literal
            operation: Write
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-status
              patternType: literal
            operation: Create
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-status
              patternType: literal
            operation: Describe
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-status
              patternType: literal
            operation: Read
            host: "*"
          # access to config.storage.topic
          - resource:
              type: topic
              name: connect-cluster-configs
              patternType: literal
            operation: Write
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-configs
              patternType: literal
            operation: Create
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-configs
              patternType: literal
            operation: Describe
            host: "*"
          - resource:
              type: topic
              name: connect-cluster-configs
              patternType: literal
            operation: Read
            host: "*"
          # consumer group
          - resource:
              type: group
              name: connect-cluster
              patternType: literal
            operation: Read
            host: "*"
  2. 创建或更新资源。

    oc apply -f KAFKA-USER-CONFIG-FILE

2.2.4. 执行 Kafka 连接器重启

此流程描述了如何使用 OpenShift 注解手动触发 Kafka 连接器重启。

先决条件

  • Cluster Operator 正在运行。

流程

  1. 查找控制您要重启的 Kafka 连接器的 KafkaConnector 自定义资源的名称:

    oc get KafkaConnector
  2. 要重启连接器,请注解 OpenShift 中的 KafkaConnector 资源。例如,使用 oc annotate:

    oc annotate KafkaConnector KAFKACONNECTOR-NAME strimzi.io/restart=true
  3. 等待下一次协调发生(默认为每隔两分钟)。

    Kafka 连接器重启,只要协调过程检测到注解。当 Kafka Connect 接受重启请求时,该注解会从 KafkaConnector 自定义资源中删除。

其它资源

2.2.5. 执行 Kafka 连接器任务重启

此流程描述了如何使用 OpenShift 注解手动触发 Kafka 连接器任务重启。

先决条件

  • Cluster Operator 正在运行。

流程

  1. 查找控制您要重启的 Kafka 连接器任务的 KafkaConnector 自定义资源的名称:

    oc get KafkaConnector
  2. KafkaConnector 自定义资源中找到要重启的任务 ID。任务 ID 是非负整数,从 0 开始。

    oc describe KafkaConnector KAFKACONNECTOR-NAME
  3. 要重启连接器任务,请注解 OpenShift 中的 KafkaConnector 资源。例如,使用 oc annotate 重启任务 0:

    oc annotate KafkaConnector KAFKACONNECTOR-NAME strimzi.io/restart-task=0
  4. 等待下一次协调发生(默认为每隔两分钟)。

    Kafka 连接器任务重启,只要协调过程检测到注解。当 Kafka Connect 接受重启请求时,该注解会从 KafkaConnector 自定义资源中删除。

其它资源

2.2.6. 从使用 S2I 的 Kafka Connect 迁移到 Kafka Connect

对 Kafka Connect with S2I 和 KafkaConnectS2I 资源的支持已弃用。这会在 KafkaConnect 资源引入 构建配置 属性,用于使用连接器插件来自动构建容器镜像。

这个步骤描述了如何使用 S2I 实例将 Kafka Connect 迁移到标准 Kafka Connect 实例。为此,您需要配置一个新的 KafkaConnect 自定义资源来替换 KafkaConnectS2I 资源,然后删除该资源。

警告

迁移过程涉及从 KafkaConnectS2I 实例删除到新 KafkaConnect 实例部署成功时的停机时间。在此期间,连接器将不会运行和处理数据。但是,更改后,它们应从停止的时间点继续。

先决条件

  • 使用 KafkaConnectS2I 配置部署带有 S 2I 的 Kafka Connect
  • 与 S2I 的 Kafka Connect 使用带有使用 S2I 构建添加的连接器的镜像
  • sink 和源连接器实例是使用 KafkaConnector 资源或 Kafka Connect REST API 创建的

流程

  1. 使用与用于 Kafka connectS2I 资源的名称相同的名称创建新的 Kafka Connect 自定义资源。
  2. KafkaConnectS2I 资源属性复制到 KafkaConnect 资源。
  3. 如果指定,请确保使用相同的 spec.config 属性:

    • group.id
    • offset.storage.topic
    • config.storage.topic
    • status.storage.topic

      如果未指定这些属性,则使用默认值。在这种情况下,也将其从 KafkaConnect 资源配置中退出。

    现在,将特定于 KafkaConnect 资源的配置添加到新资源中。

  4. 添加 构建配置,以配置您要添加到 Kafka Connect 部署中的所有连接器和其他库。

    注意

    或者,您也可以使用连接器手动构建新镜像,并使用 .spec.image 属性指定它。

  5. 删除旧的 KafkaConnectS2I 资源:

    oc delete -f MY-KAFKA-CONNECT-S2I-CONFIG-FILE

    MY-KAFKA-CONNECT-S2I-CONFIG-FILE 替换为包含 KafkaConnectS2I 资源配置的文件名。

    另外,您可以指定资源的名称:

    oc delete kafkaconnects2i MY-KAFKA-CONNECT-S2I

    MY-KAFKA-CONNECT-S2I 替换为 KafkaConnectS2I 资源的名称。

    等待 Kafka Connect with S2I 部署被删除,并且 pod 已被删除。

    警告

    不得删除任何其他资源。

  6. 部署新的 KafkaConnect 资源:

    oc apply -f MY-KAFKA-CONNECT-CONFIG-FILE

    MY-KAFKA-CONNECT-CONFIG-FILE 替换为包含新 KafkaConnect 资源配置的文件名称。

    等待新镜像构建好,部署创建好,并且容器集已启动。

  7. 如果您使用 KafkaConnector 资源来管理 Kafka Connect 连接器,请检查所有预期的连接器是否存在并正在运行:

    oc get kctr --selector strimzi.io/cluster=MY-KAFKA-CONNECT-CLUSTER -o name

    MY-KAFKA-CONNECT-CLUSTER 替换为 Kafka Connect 集群的名称。

    通过 Kafka Connect 存储自动恢复连接器。即使您使用 Kafka Connect REST API 管理它们,您不应该手动重新创建它们。

2.2.7. Kafka Connect 集群资源列表

以下资源由 OpenShift 集群中的 Cluster Operator 创建:

connect-cluster-name-connect
用于创建 Kafka Connect worker 节点 pod 的 Deployment。
connect-cluster-name-connect-api
公开用于管理 Kafka Connect 集群的 REST 接口的服务。
connect-cluster-name-config
包含 Kafka Connect 辅助配置且由 Kafka 代理 Pod 挂载为卷的 ConfigMap。
connect-cluster-name-connect
为 Kafka Connect worker 节点配置的 Pod Disruption Budget。

2.2.8. Kafka Connect(S2I)集群资源列表

以下资源由 OpenShift 集群中的 Cluster Operator 创建:

connect-cluster-name-connect-source
镜像流,用作新构建的 Docker 镜像的基础镜像。
connect-cluster-name-connect
BuildConfig,它负责构建新的 Kafka Connect Docker 镜像。
connect-cluster-name-connect
将推送新构建 Docker 镜像的镜像流。
connect-cluster-name-connect
DeploymentConfig,它负责创建 Kafka Connect worker 节点 pod。
connect-cluster-name-connect-api
公开用于管理 Kafka Connect 集群的 REST 接口的服务。
connect-cluster-name-config
包含 Kafka Connect 辅助配置且由 Kafka 代理 Pod 挂载为卷的 ConfigMap。
connect-cluster-name-connect
为 Kafka Connect worker 节点配置的 Pod Disruption Budget。

2.2.9. 与 Debezium 集成以捕获更改数据

红帽 Debezium 是一个分布式更改数据捕获平台。它捕获数据库中的行级更改,创建更改事件记录,并将记录流传输到 Kafka 主题。Debezium 基于 Apache Kafka 构建。您可以将 Debezium 与 AMQ Streams 部署和集成。部署 AMQ Streams 后,您可以通过 Kafka Connect 将 Debezium 部署为连接器配置。Debezium 将更改事件记录传递到 OpenShift 上的 AMQ Streams。应用程序可以读取 这些更改事件流,并按发生更改事件的顺序访问更改事件。

Debezium 具有多个用途,包括:

  • 数据复制
  • 更新缓存和搜索索引
  • 简化单体式应用程序
  • 数据集成
  • 启用流查询

要捕获数据库更改,请使用 Debezium 数据库连接器部署 Kafka Connect。您可以配置 KafkaConnector 资源来定义连接器实例。

有关使用 AMQ Streams 部署 Debezium 的更多信息,请参阅 产品文档。Debezium 文档包括 Debezium 入门 指南,指导您完成设置服务和查看数据库更新事件记录所需的连接器所需的流程。

2.3. Kafka MirrorMaker 集群配置

本章论述了如何在 AMQ Streams 集群中配置 Kafka 镜像Maker 部署以在 Kafka 集群间复制数据。

您可以使用带有 MirrorMaker 或 MirrorMaker 2.0 的 AMQ Streams。MirrorMaker 2.0 是最新版本,为在 Kafka 集群间镜像数据提供了一种更有效的方法。

如果使用 MirrorMaker,您需要配置 KafkaMirrorMaker 资源。

以下流程演示了如何配置资源:

KafkaMirrorMaker 资源的完整 schema 信息包括在 KafkaMirrorMaker schema 引用 中。

2.3.1. Configuring Kafka MirrorMaker

使用 KafkaMirrorMaker 资源的属性来配置 Kafka MirrorMaker 部署。

您可以使用 TLS 或 SASL 身份验证为生产者和使用者配置访问控制。此流程演示了在使用者和制作者侧使用 TLS 加密和身份验证的配置。

先决条件

  • 有关运行 以下的说明,请参阅 OpenShift 指南中的部署和升级 AMQ Streams

  • 源和目标 Kafka 集群必须可用

流程

  1. 编辑 KafkaMirrorMaker 资源的 spec 属性。

    您可以配置的属性显示在此示例配置中:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker
    metadata:
      name: my-mirror-maker
    spec:
      replicas: 3 1
      consumer:
        bootstrapServers: my-source-cluster-kafka-bootstrap:9092 2
        groupId: "my-group" 3
        numStreams: 2 4
        offsetCommitInterval: 120000 5
        tls: 6
          trustedCertificates:
          - secretName: my-source-cluster-ca-cert
            certificate: ca.crt
        authentication: 7
          type: tls
          certificateAndKey:
            secretName: my-source-secret
            certificate: public.crt
            key: private.key
        config: 8
          max.poll.records: 100
          receive.buffer.bytes: 32768
          ssl.cipher.suites: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" 9
          ssl.enabled.protocols: "TLSv1.2"
          ssl.protocol: "TLSv1.2"
          ssl.endpoint.identification.algorithm: HTTPS 10
      producer:
        bootstrapServers: my-target-cluster-kafka-bootstrap:9092
        abortOnSendFailure: false 11
        tls:
          trustedCertificates:
          - secretName: my-target-cluster-ca-cert
            certificate: ca.crt
        authentication:
          type: tls
          certificateAndKey:
            secretName: my-target-secret
            certificate: public.crt
            key: private.key
        config:
          compression.type: gzip
          batch.size: 8192
          ssl.cipher.suites: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" 12
          ssl.enabled.protocols: "TLSv1.2"
          ssl.protocol: "TLSv1.2"
          ssl.endpoint.identification.algorithm: HTTPS 13
      include: "my-topic|other-topic" 14
      resources: 15
        requests:
          cpu: "1"
          memory: 2Gi
        limits:
          cpu: "2"
          memory: 2Gi
      logging: 16
        type: inline
        loggers:
          mirrormaker.root.logger: "INFO"
      readinessProbe: 17
        initialDelaySeconds: 15
        timeoutSeconds: 5
      livenessProbe:
        initialDelaySeconds: 15
        timeoutSeconds: 5
      metricsConfig: 18
       type: jmxPrometheusExporter
       valueFrom:
         configMapKeyRef:
           name: my-config-map
           key: my-key
      jvmOptions: 19
        "-Xmx": "1g"
        "-Xms": "1g"
      image: my-org/my-image:latest 20
      template: 21
        pod:
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - key: application
                        operator: In
                        values:
                          - postgresql
                          - mongodb
                  topologyKey: "kubernetes.io/hostname"
        connectContainer: 22
          env:
            - name: JAEGER_SERVICE_NAME
              value: my-jaeger-service
            - name: JAEGER_AGENT_HOST
              value: jaeger-agent-name
            - name: JAEGER_AGENT_PORT
              value: "6831"
      tracing: 23
        type: jaeger
    1
    2
    3
    4
    5
    6
    使用密钥名称进行 TLS 加密,其中 TLS 证书存储在 X.509 格式供使用者或生产者使用。如果证书存储在同一个 secret 中,则可以多次列出证书。
    7
    对使用者或生产者进行身份验证,使用此处所示的 TLS 机制,使用 OAuth bearer 令牌 或基于 SASL 的 SCRAM-SHA-512PLAIN 机制。
    8
    用于 使用者和 生产者 的 Kafka 配置选项。
    9
    使用特定 密码套件 为 TLS 版本运行外部侦听器的 SSL 属性
    10
    通过将 设置为 HTTPS启用主机名验证。空字符串将禁用验证。
    11
    如果 abort OnSendFailure 属性 设为 true,则 Kafka MirrorMaker 将退出,容器将在发送失败消息后重启。
    12
    使用特定 密码套件 为 TLS 版本运行外部侦听器的 SSL 属性
    13
    通过将 设置为 HTTPS启用主机名验证。空字符串将禁用验证。
    14
    包括的主题 (从源镜像到目标 Kafka 集群)。
    15
    请求保留 支持的资源、当前 cpu 和 memory ,以及限制,以指定可消耗的最大资源。
    16
    指定日志记录器和日志级别 通过 ConfigMap 直接(内联)或间接(外部)添加。自定义 ConfigMap 必须放在 log4j.properties 或 log4j2.properties 键下。MirrorMaker 有一个名为 mirrormaker.root.logger 的日志记录器。您可以将日志级别设置为 INFO、ERROR、WARN、TRACE、DEBUG、FATAL 或 OFF。
    17
    健康检查以了解 何时重新启动容器(存活度)以及容器何时可以接受流量(就绪度)。
    18
    Prometheus metrics,通过引用包含本例中 Prometheus JMX 导出器配置的 ConfigMap 来启用它。您可以使用对包含 metricsConfig.valueFrom.configMapKeyRef.key 下的空文件的 ConfigMap 的引用来启用指标,而无需进一步配置。
    19
    用于优化运行 Kafka MirrorMaker 的虚拟机(VM)性能的 JVM 配置选项
    20
    ADVANCED OPTION: 容器镜像配置,只在特殊情况下推荐这样做。
    21
    模板自定义.在这里,pod 被调度为反关联性,因此 pod 不会调度到具有相同主机名的节点。
    22
    23
    警告

    将 abort OnSendFailure 属性设置为 false 时,制作者会尝试发送主题中的下一个消息。原始消息可能会丢失,因为没有尝试重新发送失败的消息。

  2. 创建或更新资源:

    oc apply -f <your-file>

2.3.2. Kafka MirrorMaker 集群资源列表

以下资源由 OpenShift 集群中的 Cluster Operator 创建:

<mirror-maker-name>-mirror-maker
负责创建 Kafka MirrorMaker pod 的部署。
<mirror-maker-name>-config
包含 Kafka MirrorMaker 的辅助配置的 ConfigMap,并由 Kafka 代理 Pod 挂载为卷。
<mirror-maker-name>-mirror-maker
为 Kafka MirrorMaker worker 节点配置的 Pod Disruption Budget。

2.4. Kafka MirrorMaker 2.0 集群配置

本节论述了如何在 AMQ Streams 集群中配置 Kafka MirrorMaker 2.0 部署。

MirrorMaker 2.0 用于在数据中心内或之间的两个或多个活跃 Kafka 集群之间复制数据。

集群间的数据复制支持以下条件:

  • 发生系统故障时恢复数据
  • 聚合数据以进行分析
  • 对特定集群的数据访问的限制
  • 在特定位置置备数据以缩短延迟

如果使用 MirrorMaker 2.0,您需要配置 KafkaMirrorMaker2 资源。

MirrorMaker 2.0 引入了一种全新的在集群间复制数据的方法。

因此,资源配置与以前的 MirrorMaker 版本不同。如果您选择使用 MirrorMaker 2.0,当前没有传统支持,因此任何资源都必须手动转换为新格式。

MirrorMaker 2.0 复制数据的方式如下:

以下流程演示了如何为 MirrorMaker 2.0 配置资源:

KafkaMirrorMaker2 资源的完整 schema 包括在 KafkaMirrorMaker2 架构引用 中。

2.4.1. MirrorMaker 2.0 数据复制

MirrorMaker 2.0 使用源 Kafka 集群的信息,并将其写入目标 Kafka 集群。

MirrorMaker 2.0 使用:

  • 源集群配置以使用源集群的数据
  • 将数据输出到目标集群的目标集群配置

MirrorMaker 2.0 基于 Kafka Connect 框架,即管理集群间数据传输的 连接器。MirrorMaker 2.0 MirrorSourceConnector 将主题从源集群复制到目标集群。

将数据从一个集群 镜像 到另一个集群的过程是异步的。建议的模式是让信息与源 Kafka 集群一起生成,然后远程使用与目标 Kafka 集群类似的信息。

MirrorMaker 2.0 可以用于多个源集群。

图 2.1. 在两个集群间复制

MirrorMaker 2.0 复制

默认情况下,每 10 分钟检查源集群中的新主题。您可以通过在源连接器配置中添加 refresh.topics.interval.seconds 来更改频率。但是,增加操作的频率可能会影响整体性能。

2.4.2. 集群配置

您可以在 主动/ 被动或主动/主动 集群配置中使用 MirrorMaker 2.0。

  • 主动/主动 配置中,两个集群都处于活动状态并同时提供相同的数据,如果您想在不同的地理位置在本地提供相同的数据,这很有用。
  • 主动/被动 配置中,来自主动/被动群集的数据复制到被动群集中,该群集仍处于备用状态,例如,在发生系统故障时进行数据恢复。

预计生产者和消费者只能连接到活跃的集群。

每个目标目的地都需要一个 MirrorMaker 2.0 集群。

2.4.2.1. 双向复制(主动/主动)

MirrorMaker 2.0 架构支持 主动/主动 集群配置中的双向复制。

每个集群使用 和远程 主题的概念复制其他集群的数据。由于每个集群中存储了相同的主题,因此 MirrorMaker 2.0 会自动重命名远程主题来代表源集群。原始集群的名称前面是主题名称的前面。

图 2.2. 主题重命名

MirrorMaker 2.0 双向架构

通过标记原始集群,主题不会复制到该集群中。

在配置需要数据聚合的架构时,通过 远程 主题复制的概念非常有用。消费者可以订阅同一群集内的源和远程主题,无需单独的聚合集群。

2.4.2.2. 单向复制(主动/被动)

MirrorMaker 2.0 架构支持 主动/被动 集群配置中的单向复制。

您可以使用 主动/被动 集群配置进行备份,或将数据迁移到另一个集群。在这种情况下,您可能不希望自动重命名远程主题。

您可以通过在源连接器配置中添加 IdentityReplicationPolicy 来覆盖自动重命名。应用此配置后,主题会保留其原始名称。

2.4.2.3. 主题配置同步

主题配置会在源集群和目标集群之间自动同步。通过同步配置属性,可以减少重新平衡的需求。

2.4.2.4. 数据完整性

MirrorMaker 2.0 监控源主题,并将配置更改传播到远程主题,检查并创建缺少的分区。只有 MirrorMaker 2.0 可以写入远程主题。

2.4.2.5. 偏移跟踪

MirrorMaker 2.0 使用 内部主题 跟踪消费者组的偏移量。

  • 偏移同步 主题映射从记录元数据中复制主题分区的来源和目标偏移
  • checkpoint 主题映射源和目标集群中为各个消费者组中复制主题分区的最后提交偏移

检查点 主题的偏移会通过配置预先确定的时间间隔进行跟踪。这两个主题都允许从故障转移上的正确偏移位置完全恢复复制。

MirrorMaker 2.0 使用其 MirrorCheckpointConnector 来发送 检查点 以进行偏移。

2.4.2.6. 同步消费者组偏移

__consumer_offsets 主题存储关于每个消费者组已提交的偏移的信息。偏移同步定期将源集群使用者组的使用者偏移量传输到目标集群的使用者偏移主题。

偏移同步在 主动/被动 配置中特别有用。如果活跃集群停机,使用者应用可以切换到被动(standby)集群,并从最近传输的偏移位置获取。

使用主题偏移同步:

  • 通过将 sync. group.offsets.enabled 添加到 checkpoint 连接器配置来启用同步,并将 属性设置为 true。默认情况下禁用同步。
  • IdentityReplicationPolicy 添加到源和检查点连接器配置中,以便目标集群中的主题保留其原始名称。

要进行主题偏移同步,目标集群中的消费者组无法使用与源集群中的组相同的 id。

如果启用,则定期与源集群进行偏移同步。您可以通过将 sync. group.offsets.interval.secondsemit.checkpoints.interval.seconds 添加到 checkpoint 连接器配置来更改频率。属性指定消费者组偏移同步的频率(以秒为单位),以及发出用于偏移跟踪的检查点频率。两个属性的默认值都是 60 秒。您还可以使用 refresh. groups.interval.seconds 属性更改新使用者 组的检查频率,默认为每 10 分钟执行一次。

由于同步是基于时间的,因此使用者到被动群集的任何切换都可能会导致消息出现某种重复。

2.4.2.7. 连接检查

一个 心跳 的内部主题检查集群之间的连通性。

heartbeat 主题从源集群中复制。

目标集群使用该主题检查:

  • 集群之间的连接器正在运行
  • 源集群可用

MirrorMaker 2.0 使用其 MirrorHeartbeatConnector 发送执行这些检查 的心跳

2.4.3. ACL 规则同步

如果没有 使用 User Operator,则可以获得对远程主题的 ACL 访问权限。

如果使用 AclAuthorizer( 没有 User Operator),则管理对代理访问权限的 ACL 规则也适用于远程主题。能够读取源主题的用户可以读取其远程等效内容。

注意

OAuth 2.0 授权不支持以这种方式访问远程主题。

2.4.4. 使用 MirrorMaker 2.0 在 Kafka 集群间同步数据

使用 MirrorMaker 2.0 通过配置同步 Kafka 集群之间的数据。

配置必须指定:

  • 每个 Kafka 集群
  • 每个集群的连接信息,包括 TLS 身份验证
  • 复制流和方向

    • 集群到集群
    • 主题

使用 KafkaMirrorMaker2 资源的属性来配置 Kafka MirrorMaker 2.0 部署。

注意

以前版本的 MirrorMaker 继续受到支持。如果要使用为之前版本配置的资源,则必须将其更新为 MirrorMaker 2.0 所支持的格式。

MirrorMaker 2.0 为复制因素等属性提供默认配置值。最小配置(默认值保持不变)会类似如下:

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaMirrorMaker2
metadata:
  name: my-mirror-maker2
spec:
  version: 2.8.0
  connectCluster: "my-cluster-target"
  clusters:
  - alias: "my-cluster-source"
    bootstrapServers: my-cluster-source-kafka-bootstrap:9092
  - alias: "my-cluster-target"
    bootstrapServers: my-cluster-target-kafka-bootstrap:9092
  mirrors:
  - sourceCluster: "my-cluster-source"
    targetCluster: "my-cluster-target"
    sourceConnector: {}

您可以使用 TLS 或 SASL 身份验证为源和目标集群配置访问控制。此流程显示为源和目标集群使用 TLS 加密和身份验证的配置。

先决条件

  • 有关运行 以下的说明,请参阅 OpenShift 指南中的部署和升级 AMQ Streams

  • 源和目标 Kafka 集群必须可用

流程

  1. 编辑 KafkaMirrorMaker2 资源的 spec 属性。

    您可以配置的属性显示在此示例配置中:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker2
    metadata:
      name: my-mirror-maker2
    spec:
      version: 2.8.0 1
      replicas: 3 2
      connectCluster: "my-cluster-target" 3
      clusters: 4
      - alias: "my-cluster-source" 5
        authentication: 6
          certificateAndKey:
            certificate: source.crt
            key: source.key
            secretName: my-user-source
          type: tls
        bootstrapServers: my-cluster-source-kafka-bootstrap:9092 7
        tls: 8
          trustedCertificates:
          - certificate: ca.crt
            secretName: my-cluster-source-cluster-ca-cert
      - alias: "my-cluster-target" 9
        authentication: 10
          certificateAndKey:
            certificate: target.crt
            key: target.key
            secretName: my-user-target
          type: tls
        bootstrapServers: my-cluster-target-kafka-bootstrap:9092 11
        config: 12
          config.storage.replication.factor: 1
          offset.storage.replication.factor: 1
          status.storage.replication.factor: 1
          ssl.cipher.suites: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" 13
          ssl.enabled.protocols: "TLSv1.2"
          ssl.protocol: "TLSv1.2"
          ssl.endpoint.identification.algorithm: HTTPS 14
        tls: 15
          trustedCertificates:
          - certificate: ca.crt
            secretName: my-cluster-target-cluster-ca-cert
      mirrors: 16
      - sourceCluster: "my-cluster-source" 17
        targetCluster: "my-cluster-target" 18
        sourceConnector: 19
          tasksMax: 10 20
          config:
            replication.factor: 1 21
            offset-syncs.topic.replication.factor: 1 22
            sync.topic.acls.enabled: "false" 23
            refresh.topics.interval.seconds: 60 24
            replication.policy.separator: "" 25
            replication.policy.class: "io.strimzi.kafka.connect.mirror.IdentityReplicationPolicy" 26
        heartbeatConnector: 27
          config:
            heartbeats.topic.replication.factor: 1 28
        checkpointConnector: 29
          config:
            checkpoints.topic.replication.factor: 1 30
            refresh.groups.interval.seconds: 600 31
            sync.group.offsets.enabled: true 32
            sync.group.offsets.interval.seconds: 60 33
            emit.checkpoints.interval.seconds: 60 34
            replication.policy.class: "io.strimzi.kafka.connect.mirror.IdentityReplicationPolicy"
        topicsPattern: ".*" 35
        groupsPattern: "group1|group2|group3" 36
      resources: 37
        requests:
          cpu: "1"
          memory: 2Gi
        limits:
          cpu: "2"
          memory: 2Gi
      logging: 38
        type: inline
        loggers:
          connect.root.logger.level: "INFO"
      readinessProbe: 39
        initialDelaySeconds: 15
        timeoutSeconds: 5
      livenessProbe:
        initialDelaySeconds: 15
        timeoutSeconds: 5
      jvmOptions: 40
        "-Xmx": "1g"
        "-Xms": "1g"
      image: my-org/my-image:latest 41
      template: 42
        pod:
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - key: application
                        operator: In
                        values:
                          - postgresql
                          - mongodb
                  topologyKey: "kubernetes.io/hostname"
        connectContainer: 43
          env:
            - name: JAEGER_SERVICE_NAME
              value: my-jaeger-service
            - name: JAEGER_AGENT_HOST
              value: jaeger-agent-name
            - name: JAEGER_AGENT_PORT
              value: "6831"
      tracing:
        type: jaeger 44
      externalConfiguration: 45
        env:
          - name: AWS_ACCESS_KEY_ID
            valueFrom:
              secretKeyRef:
                name: aws-creds
                key: awsAccessKey
          - name: AWS_SECRET_ACCESS_KEY
            valueFrom:
              secretKeyRef:
                name: aws-creds
                key: awsSecretAccessKey
    1
    Kafka Connect 和 Mirror Maker 2.0 版本,版本 将始终相同。
    2
    3
    Kafka Connect 的 Kafka 集群别名,它必须指定 目标 Kafka 集群。Kafka 集群由 Kafka Connect 用于其内部主题。
    4
    正在同步 Kafka 集群的规格。
    5
    源 Kafka 集群的集群 别名
    6
    使用此处所示的 TLS 机制 (使用 OAuth bearer 令牌 或基于 SASL 的 SCRAM-SHA-512PLAIN 机制)对源集群进行身份验证。
    7
    8
    使用源 Kafka 集群的 TLS 证书以 X.509 格式存储的密钥名称进行 TLS 加密。如果证书存储在同一个 secret 中,则可以多次列出证书。
    9
    目标 Kafka 集群的集群 别名
    10
    目标 Kafka 集群的身份验证的配置方式与源 Kafka 集群相同。
    11
    12
    Kafka Connect 配置.标准 Apache Kafka 配置可能会提供,仅限于不是由 AMQ Streams 直接管理的属性。
    13
    使用特定 密码套件 为 TLS 版本运行外部侦听器的 SSL 属性
    14
    通过将 设置为 HTTPS启用主机名验证。空字符串将禁用验证。
    15
    目标 Kafka 集群的 TLS 加密配置方式与源 Kafka 集群相同。
    16
    17
    MirrorMaker 2.0 连接器使用的源集群的集群 别名
    18
    MirrorMaker 2.0 连接器使用的目标集群的集群 别名
    19
    创建远程主题的 MirrorSourceConnector配置配置 会覆盖默认配置选项。
    20
    连接器可以创建的任务数量上限。任务处理数据复制,并并行运行。如果基础架构支持处理开销,增加这个值可以提高吞吐量。Kafka Connect 在集群成员之间分发任务。如果任务数量超过工作程序,则为工作程序分配多项任务。对于接收器连接器,旨在为每个主题分区使用一个任务。对于源连接器,可以并行运行的任务数量也可能取决于外部系统。如果无法实现并行性,连接器会创建少于任务的最大数量。
    21
    在目标集群中创建的已镜像主题的复制因素。
    22
    MirrorSourceConnector offset-syncs 内部主题的复制因素,用于映射源和目标集群的偏移。
    23
    启用 ACL 规则同步 时,将应用 ACL 来同步主题。默认值为 true
    24
    可选设置,可更改新主题的检查频率。默认为每 10 分钟检查一次。
    25
    定义用于重命名远程主题的分隔符。
    26
    添加可覆盖远程主题自动重命名的策略。该主题不会用源集群的名称来附加名称,而是保留其原始名称。此可选设置对主动/被动备份和数据迁移很有用。要配置主题偏移同步,还必须为 checkpointConnector.config 设置此属性。
    27
    执行连接检查 的 MirrorHeartbeatConnector配置配置 会覆盖默认配置选项。
    28
    在目标集群中创建的心跳主题的复制因素。
    29
    跟踪偏移的 MirrorCheckpointConnector配置配置 会覆盖默认配置选项。
    30
    在目标集群中创建的检查点主题的复制因素。
    31
    可选设置,以更改新使用者组的检查频率。默认为每 10 分钟检查一次。
    32
    可选设置来同步消费者组偏移,这对于主动/被动配置中的恢复非常有用。默认情况下不启用同步。
    33
    如果启用了消费者组偏移的同步,您可以调整同步的频率。
    34
    调整检查偏移跟踪的频率。如果更改了偏移同步的频率,您可能还需要调整这些检查的频率。
    35
    定义为正则表达式模式的 源集群进行主题复制。这里我们请求所有主题。
    36
    来自 定义为正则表达式模式的 源集群的使用者组复制。在这里,我们按名称请求三个消费者组。您可以使用逗号分隔的列表。
    37
    请求保留 支持的资源、当前 cpu 和 memory ,以及限制,以指定可消耗的最大资源。
    38
    指定 Kafka 连接日志记录器和日志级别 直接(内联)或通过ConfigMap 间接(外部)添加。自定义 ConfigMap 必须放在 log4j.properties 或 log4j2.properties 键下。对于 Kafka Connect log4j.rootLogger 日志记录器,您可以将日志级别设置为 INFO、ERROR、WARN、TRACE、DEBUG、FATAL 或 OFF。
    39
    健康检查以了解 何时重新启动容器(存活度)以及容器何时可以接受流量(就绪度)。
    40
    用于优化运行 Kafka MirrorMaker 的虚拟机(VM)性能的 JVM 配置选项
    41
    ADVANCED OPTION: 容器镜像配置,只在特殊情况下推荐这样做。
    42
    模板自定义.在这里,pod 被调度为反关联性,因此 pod 不会调度到具有相同主机名的节点。
    43
    44
    45
    作为环境变量挂载到 Kafka MirrorMaker 的 OpenShift Secret 的外部配置。您还可以使用 Kubernetes 配置提供程序 从外部来源加载配置值
  2. 创建或更新资源:

    oc apply -f MIRRORMAKER-CONFIGURATION-FILE

2.4.5. 执行 Kafka MirrorMaker 2.0 连接器重启

此流程描述了如何使用 OpenShift 注解手动触发 Kafka MirrorMaker 2.0 连接器重启。

先决条件

  • Cluster Operator 正在运行。

流程

  1. 查找控制您要重启的 Kafka MirrorMaker 2.0 连接器的 KafkaMirrorMaker2 自定义资源的名称:

    oc get KafkaMirrorMaker2
  2. 从 Kafka MirrorMaker2 自定义资源中找到要重启的 Kafka MirrorMaker 2.0 连接器的名称。

    oc describe KafkaMirrorMaker2 KAFKAMIRRORMAKER-2-NAME
  3. 要重启连接器,请注解 OpenShift 中的 KafkaMirrorMaker2 资源。在本例中,oc annotate 会重启名为 my-source->my-target.MirrorSourceConnector 的连接器:

    oc annotate KafkaMirrorMaker2 KAFKAMIRRORMAKER-2-NAME "strimzi.io/restart-connector=my-source->my-target.MirrorSourceConnector"
  4. 等待下一次协调发生(默认为每隔两分钟)。

    Kafka MirrorMaker 2.0 连接器重启,只要协调过程检测到注解。当重启请求被接受时,该注解会从 KafkaMirrorMaker2 自定义资源中删除。

2.4.6. 执行 Kafka MirrorMaker 2.0 连接器任务重启

此流程描述了如何使用 OpenShift 注解手动触发 Kafka MirrorMaker 2.0 连接器任务的重启。

先决条件

  • Cluster Operator 正在运行。

流程

  1. 查找控制您要重启的 Kafka MirrorMaker 2.0 连接器的 KafkaMirrorMaker2 自定义资源的名称:

    oc get KafkaMirrorMaker2
  2. 查找 Kafka MirrorMaker 2.0 连接器的名称,以及从 KafkaMirrorMaker2 自定义资源重启的任务 ID。任务 ID 是非负整数,从 0 开始。

    oc describe KafkaMirrorMaker2 KAFKAMIRRORMAKER-2-NAME
  3. 要重启连接器任务,请注解 OpenShift 中的 KafkaMirrorMaker2 资源。在本例中,oc annotate restarts task 0 of a connector of my-source->my-target.MirrorSourceConnector:

    oc annotate KafkaMirrorMaker2 KAFKAMIRRORMAKER-2-NAME "strimzi.io/restart-connector-task=my-source->my-target.MirrorSourceConnector:0"
  4. 等待下一次协调发生(默认为每隔两分钟)。

    Kafka MirrorMaker 2.0 连接器任务重启,只要协调过程检测到注解。当重启任务请求被接受时,注解会从 KafkaMirrorMaker2 自定义资源中删除。

2.5. Kafka Bridge 集群配置

本节论述了如何在 AMQ Streams 集群中配置 Kafka Bridge 部署。

Kafka Bridge 为将基于 HTTP 的客户端与 Kafka 集群集成提供了一个 API。

如果使用 Kafka Bridge,您可以配置 KafkaBridge 资源。

KafkaBridge 资源的完整 schema 信息包括在 第 13.2.110 节 “KafkaBridge 模式参考” 中。

2.5.1. 配置 Kafka 网桥

使用 Kafka Bridge 向 Kafka 集群发出基于 HTTP 的请求。

使用 KafkaBridge 资源的属性来配置 Kafka Bridge 部署。

为了防止不同 Kafka 网桥实例处理客户端消费者请求时出现问题,必须使用基于地址的路由来确保请求路由到正确的 Kafka Bridge 实例。另外,每个独立的 Kafka Bridge 实例都必须有一个副本。Kafka Bridge 实例具有自己的状态,不与其他实例共享。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

有关运行 以下的说明,请参阅 OpenShift 指南中的部署和升级 AMQ Streams

流程

  1. 编辑 KafkaBridge 资源的 spec 属性。

    您可以配置的属性显示在此示例配置中:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaBridge
    metadata:
      name: my-bridge
    spec:
      replicas: 3 1
      bootstrapServers: my-cluster-kafka-bootstrap:9092 2
      tls: 3
        trustedCertificates:
          - secretName: my-cluster-cluster-cert
            certificate: ca.crt
          - secretName: my-cluster-cluster-cert
            certificate: ca2.crt
      authentication: 4
        type: tls
        certificateAndKey:
          secretName: my-secret
          certificate: public.crt
          key: private.key
      http: 5
        port: 8080
        cors: 6
          allowedOrigins: "https://strimzi.io"
          allowedMethods: "GET,POST,PUT,DELETE,OPTIONS,PATCH"
      consumer: 7
        config:
          auto.offset.reset: earliest
      producer: 8
        config:
          delivery.timeout.ms: 300000
      resources: 9
        requests:
          cpu: "1"
          memory: 2Gi
        limits:
          cpu: "2"
          memory: 2Gi
      logging: 10
        type: inline
        loggers:
          logger.bridge.level: "INFO"
          # enabling DEBUG just for send operation
          logger.send.name: "http.openapi.operation.send"
          logger.send.level: "DEBUG"
      jvmOptions: 11
        "-Xmx": "1g"
        "-Xms": "1g"
      readinessProbe: 12
        initialDelaySeconds: 15
        timeoutSeconds: 5
      livenessProbe:
        initialDelaySeconds: 15
        timeoutSeconds: 5
      image: my-org/my-image:latest 13
      template: 14
        pod:
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - key: application
                        operator: In
                        values:
                          - postgresql
                          - mongodb
                  topologyKey: "kubernetes.io/hostname"
        bridgeContainer: 15
          env:
            - name: JAEGER_SERVICE_NAME
              value: my-jaeger-service
            - name: JAEGER_AGENT_HOST
              value: jaeger-agent-name
            - name: JAEGER_AGENT_PORT
              value: "6831"
    1
    2
    3
    使用源 Kafka 集群的 TLS 证书以 X.509 格式存储的密钥名称进行 TLS 加密。如果证书存储在同一个 secret 中,则可以多次列出证书。
    4
    Kafka Bridge 集群的身份验证,使用 TLS 机制 (此处所示)、使用 OAuth bearer 令牌 或基于 SASL 的 SCRAM-SHA-512PLAIN 机制。默认情况下,Kafka Bridge 在不进行身份验证的情况下连接到 Kafka 代理。
    5
    对 Kafka 代理的 HTTP 访问.
    6
    CORS 访问 指定选定的资源和访问方法.请求中的附加 HTTP 标头描述了允许访问 Kafka 集群的原始数据
    7
    8
    9
    请求保留 支持的资源、当前 cpu 和 memory ,以及限制,以指定可消耗的最大资源。
    10
    指定 Kafka Bridge 日志记录器和日志级别 直接(内联)或通过ConfigMap 间接(外部)添加。自定义 ConfigMap 必须放在 log4j.properties 或 log4j2.properties 键下。对于 Kafka Bridge loggers,您可以将日志级别设置为 INFO、ERROR、WARN、TRACE、DEBUG、FATAL 或 OFF。
    11
    运行 Kafka 网桥的虚拟机(VM)的 JVM 配置选项 优化性能。
    12
    健康检查以了解 何时重新启动容器(存活度)以及容器何时可以接受流量(就绪度)。
    13
    ADVANCED OPTION: 容器镜像配置,只在特殊情况下推荐这样做。
    14
    模板自定义.在这里,pod 被调度为反关联性,因此 pod 不会调度到具有相同主机名的节点。
    15
  2. 创建或更新资源:

    oc apply -f KAFKA-BRIDGE-CONFIG-FILE

2.5.2. Kafka Bridge 集群资源列表

以下资源由 OpenShift 集群中的 Cluster Operator 创建:

bridge-cluster-name-bridge
部署,用于创建 Kafka Bridge worker 节点 pod。
bridge-cluster-name-bridge-service
公开 Kafka Bridge 集群的 REST 接口的服务。
bridge-cluster-name-bridge-config
包含 Kafka Bridge 辅助配置且由 Kafka 代理 Pod 挂载为卷的 ConfigMap。
bridge-cluster-name-bridge
为 Kafka Bridge worker 节点配置的 Pod Disruption Budget。

2.6. 自定义 OpenShift 资源

AMQ Streams 创建几个 OpenShift 资源,如 DeploymentStatefulSet、 PodServices,它们由 AMQ Streams 操作器管理。只有负责管理特定 OpenShift 资源的操作器才能更改该资源。如果您尝试手动更改由 operator 管理的 OpenShift 资源,Operator 会将您的更改还原。

但是,更改由 Operator 管理的 OpenShift 资源对于执行某些任务很有用,例如:

  • 添加控制 Istio 或其他服务如何处理 Pod 的自定义标签或注解
  • 管理集群如何创建 Loadbalancer-type Services

您可以使用 AMQ Streams 自定义资源中的 template 属性进行此类更改。template 属性在以下资源中受到支持:API 引用提供了有关可自定义字段的更多详情。

在以下示例中,使用 template 属性来修改 Kafka 代理的 StatefulSet 中的标签:

模板自定义示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  labels:
    app: my-cluster
spec:
  kafka:
    # ...
    template:
      statefulset:
        metadata:
          labels:
            mylabel: myvalue
    # ...

2.6.1. 自定义镜像拉取策略

AMQ Streams 允许您自定义 Cluster Operator 部署的所有 pod 中容器的镜像拉取策略。镜像拉取策略使用 Cluster Operator 部署中的环境变量 STRIMZI_IMAGE_PULL_POLICY 进行配置。STRIMZI_IMAGE_PULL_POLICY 环境变量可设置为三个不同的值:

Always
每次 pod 启动或重启时,都会从注册表调取容器镜像。
IfNotPresent
容器镜像只有在之前没有拉取(pull)时才从注册表中提取。
Never
容器镜像永远不会从注册表调取。

镜像拉取策略目前只能对所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群进行自定义。更改策略会导致所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群滚动更新。

其它资源

2.7. 配置 pod 调度

当两个应用调度到同一个 OpenShift 节点时,这两个应用可能使用相同的资源,如磁盘 I/O 并影响性能。这可能会导致性能下降。以避免与其他关键工作负载共享节点的方式,仅为 Kafka 使用正确的节点或专用一组节点是如何避免这些问题的最佳方法,调度 Kafka pod 是避免这些问题的最佳方法。

2.7.1. 指定关联性、容限和拓扑分布约束

使用关联性、容限和拓扑分布约束将 kafka 资源的 pod 调度到节点上。关联性、容限和拓扑分布约束使用以下资源中 的关联性容限topologySpreadConstraint 属性进行配置:

  • Kafka.spec.kafka.template.pod
  • Kafka.spec.zookeeper.template.pod
  • Kafka.spec.entityOperator.template.pod
  • KafkaConnect.spec.template.pod
  • KafkaConnectS2I.spec.template.pod
  • KafkaBridge.spec.template.pod
  • KafkaMirrorMaker.spec.template.pod
  • KafkaMirrorMaker2.spec.template.pod

关联性容限topologySpreadConstraint 属性的格式遵循 OpenShift 规范。关联性配置可以包含不同类型的关联性:

  • pod 关联性和反关联性
  • 节点关联性
注意

在 OpenShift 1.16 和 1.17 中,对 topologySpreadConstraint 的支持会被默认禁用。要使用 topologySpreadConstraint,您必须在 Kubernetes API 服务器和调度程序中启用 EvenPodsSpread 功能门。

2.7.1.1. 使用 pod 反关联性以避免关键应用程序共享节点

使用 pod 反关联性来确保关键应用永远不会调度到同一磁盘上。运行 Kafka 集群时,建议使用 pod 反关联性来确保 Kafka 代理不与其他工作负载(如数据库)共享节点。

2.7.1.2. 使用节点关联性将工作负载调度到特定的节点上

OpenShift 集群通常包含许多不同类型的工作程序节点。些已针对 CPU 繁重工作负载优化,有些则用于内存,另一些则可能针对存储(快速本地 SSD)或网络进行了优化。使用不同的节点有助于优化成本和性能。要获得最佳性能,务必要允许调度 AMQ Streams 组件以使用正确的节点。

OpenShift 使用节点关联性将工作负载调度到特定的节点上。通过节点关联性,您可以为要在其上调度 pod 的节点创建调度约束。约束指定为标签选择器。您可以使用内置节点标签(如 beta.kubernetes.io/instance-type) 或自定义标签来指定标签,以选择正确的节点。

2.7.1.3. 对专用节点使用节点关联性和容限

使用污点来创建专用节点,然后通过配置节点关联性和容限将 Kafka pod 调度到专用节点上。

集群管理员可以将选定的 OpenShift 节点标记为污点。具有污点的节点不在常规调度中,一般的 pod 不会调度到它们上运行。只有可以容许节点上设置的污点的服务才可以调度到其中。此类节点上运行的唯一其他服务是系统服务,如日志收集器或软件定义型网络。

在专用节点上运行 Kafka 及其组件可能会有许多优点。同一节点上运行的其他应用程序不会造成干扰或消耗 Kafka 所需的资源。这可提高性能和稳定性。

2.7.2. 配置 pod 反关联性,以将每个 Kafka 代理调度到不同的 worker 节点上

许多 Kafka 代理或 ZooKeeper 节点可以在同一 OpenShift worker 节点上运行。如果 worker 节点失败,它们都会同时不可用。要提高可靠性,您可以使用 podAntiAffinity 配置在不同的 OpenShift worker 节点上调度每个 Kafka 代理或 ZooKeeper 节点。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 编辑指定集群部署的资源中的 affinity 属性。要确保 Kafka 代理或 ZooKeeper 节点没有共享 worker 节点,请使用 strimzi.io/name 标签。将 topologyKey 设置为 kubernetes.io/hostname,以指定所选 pod 没有调度到具有相同主机名的节点。这仍然允许同一 worker 节点由单个 Kafka 代理和单个 ZooKeeper 节点共享。例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        template:
          pod:
            affinity:
              podAntiAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  - labelSelector:
                      matchExpressions:
                        - key: strimzi.io/name
                          operator: In
                          values:
                            - CLUSTER-NAME-kafka
                    topologyKey: "kubernetes.io/hostname"
        # ...
      zookeeper:
        # ...
        template:
          pod:
            affinity:
              podAntiAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  - labelSelector:
                      matchExpressions:
                        - key: strimzi.io/name
                          operator: In
                          values:
                            - CLUSTER-NAME-zookeeper
                    topologyKey: "kubernetes.io/hostname"
        # ...

    Where CLUSTER-NAME 是 Kafka 自定义资源的名称。

  2. 如果您甚至希望确保 Kafka 代理和 ZooKeeper 节点不共享相同的 worker 节点,请使用 strimzi.io/cluster 标签。例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        template:
          pod:
            affinity:
              podAntiAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  - labelSelector:
                      matchExpressions:
                        - key: strimzi.io/cluster
                          operator: In
                          values:
                            - CLUSTER-NAME
                    topologyKey: "kubernetes.io/hostname"
        # ...
      zookeeper:
        # ...
        template:
          pod:
            affinity:
              podAntiAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  - labelSelector:
                      matchExpressions:
                        - key: strimzi.io/cluster
                          operator: In
                          values:
                            - CLUSTER-NAME
                    topologyKey: "kubernetes.io/hostname"
        # ...

    Where CLUSTER-NAME 是 Kafka 自定义资源的名称。

  3. 创建或更新资源。

    oc apply -f KAFKA-CONFIG-FILE

2.7.3. 在 Kafka 组件中配置 pod 反关联性

Pod 反关联性配置有助于实现 Kafka 代理的稳定性和性能。通过使用 podAntiAffinity,OpenShift 不会将 Kafka 代理调度到与其他工作负载相同的节点上。通常,您想要避免在与其他网络或者存储密集型应用程序(如数据库、存储或其他消息传递平台)相同的 worker 节点上运行 Kafka。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 编辑指定集群部署的资源中的 affinity 属性。使用标签指定不应调度到同一节点上的 pod。topologyKey 应设置为 kubernetes.io/hostname,以指定不应将所选 pod 调度到具有相同主机名的节点。例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        template:
          pod:
            affinity:
              podAntiAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  - labelSelector:
                      matchExpressions:
                        - key: application
                          operator: In
                          values:
                            - postgresql
                            - mongodb
                    topologyKey: "kubernetes.io/hostname"
        # ...
      zookeeper:
        # ...
  2. 创建或更新资源。

    这可以使用 oc apply 来完成:

    oc apply -f KAFKA-CONFIG-FILE

2.7.4. 在 Kafka 组件中配置节点关联性

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 标记调度 AMQ Streams 组件的节点。

    可以使用 oc label 来完成此操作:

    oc label node NAME-OF-NODE node-type=fast-network

    或者,某些现有标签可以被重复使用。

  2. 编辑指定集群部署的资源中的 affinity 属性。例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        template:
          pod:
            affinity:
              nodeAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  nodeSelectorTerms:
                    - matchExpressions:
                      - key: node-type
                        operator: In
                        values:
                        - fast-network
        # ...
      zookeeper:
        # ...
  3. 创建或更新资源。

    这可以使用 oc apply 来完成:

    oc apply -f KAFKA-CONFIG-FILE

2.7.5. 设置专用节点并在节点上调度 pod

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 选择应当用作专用的节点。
  2. 确保这些节点上未调度工作负载。
  3. 在所选节点上设置污点:

    可以使用 oc adm taint 来完成此操作:

    oc adm taint node NAME-OF-NODE dedicated=Kafka:NoSchedule
  4. 另外,也向所选节点添加标签。

    可以使用 oc label 来完成此操作:

    oc label node NAME-OF-NODE dedicated=Kafka
  5. 编辑 指定集群部署的资源中的关联性容限 属性。

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        template:
          pod:
            tolerations:
              - key: "dedicated"
                operator: "Equal"
                value: "Kafka"
                effect: "NoSchedule"
            affinity:
              nodeAffinity:
                requiredDuringSchedulingIgnoredDuringExecution:
                  nodeSelectorTerms:
                  - matchExpressions:
                    - key: dedicated
                      operator: In
                      values:
                      - Kafka
        # ...
      zookeeper:
        # ...
  6. 创建或更新资源。

    这可以使用 oc apply 来完成:

    oc apply -f KAFKA-CONFIG-FILE

2.8. 日志记录配置

在 Kafka 组件和 AMQ Streams Operator 的自定义资源中配置日志级别。您可以在自定义资源的 spec.logging 属性中直接指定日志级别。或者,您可以使用 configMapKeyRef 属性在自定义资源中引用的 ConfigMap 中定义日志属性。

使用 ConfigMap 的优点是日志记录属性在一个位置维护,并可以被多个资源访问。您还可以为多个资源重复使用 ConfigMap。如果您使用 ConfigMap 指定 AMQ Streams Operator 的日志记录器,您也可以附加日志规格来添加过滤器。

您可以在日志记录规格中指定一个日志 类型

  • 直接指定日志级别时 内联
  • 引用 ConfigMap 时 外部

内联 日志记录配置示例

spec:
  # ...
  logging:
    type: inline
    loggers:
      kafka.root.logger.level: "INFO"

外部 日志记录配置示例

spec:
  # ...
  logging:
    type: external
    valueFrom:
      configMapKeyRef:
        name: my-config-map
        key: my-config-map-key

ConfigMap 名称和 的值是必需的。如果未设置 名称或 密钥,则会使用默认日志记录。

其它资源

Kafka 组件日志

Operator 日志

2.8.1. 为日志记录创建 ConfigMap

要使用 ConfigMap 定义日志属性,您需要创建 ConfigMap,然后在资源 spec 中的日志记录定义中引用它。

ConfigMap 必须包含适当的日志记录配置。

  • Kafka 组件、ZooKeeper 和 Kafka Bridge 的 log4j.properties
  • Topic Operator 和 User Operator 的 log4j2.properties

配置必须置于这些属性下。

在这一流程中,ConfigMap 为 Kafka 资源定义根日志记录器。

流程

  1. 创建 ConfigMap。

    您可以将 ConfigMap 作为 YAML 文件或属性文件创建。

    带有 Kafka 的根日志记录器定义的 ConfigMap 示例:

    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: logging-configmap
    data:
      log4j.properties:
        kafka.root.logger.level="INFO"

    如果您使用属性文件,请在命令行中指定该文件:

    oc create configmap logging-configmap --from-file=log4j.properties

    属性文件定义日志配置:

    # Define the logger
    kafka.root.logger.level="INFO"
    # ...
  2. 在资源的 spec 中定义 外部 日志记录,将 logging.valueFrom.configMapKeyRef.name 设置为 ConfigMap 的名称,valueFrom.configMapKeyRef.key 设置为此 ConfigMap 中的键。

    spec:
      # ...
      logging:
        type: external
        valueFrom:
          configMapKeyRef:
            name: logging-configmap
            key: log4j.properties
  3. 创建或更新资源。

    oc apply -f KAFKA-CONFIG-FILE

2.8.2. 在 Operator 中添加日志记录过滤器

如果您使用 ConfigMap 为 AMQ Streams Operator 配置(log4j2)日志记录级别,您也可以定义日志记录过滤器来限制日志中返回的内容。

当您有大量日志消息时,日志记录过滤器很有用。假设您将日志记录器的日志级别设置为 DEBUG(rootLogger.level="DEBUG")。日志记录过滤器减少了该级别上日志记录器返回的日志数量,因此您可以专注于特定的资源。设置过滤器后,将仅记录与过滤器匹配的日志消息。

过滤器使用 标记 来指定要包含在日志中的内容。您可以为标记指定一个 kind、namespace 和 name。例如,如果 Kafka 集群失败,您可以通过将 kind 指定为 Kafka 来隔离日志,并使用失败集群的命名空间和名称。

本例显示了名为 my-kafka-cluster 的 Kafka 集群的标记过滤器。

基本日志记录过滤器配置

rootLogger.level="INFO"
appender.console.filter.filter1.type=MarkerFilter 1
appender.console.filter.filter1.onMatch=ACCEPT 2
appender.console.filter.filter1.onMismatch=DENY 3
appender.console.filter.filter1.marker=Kafka(my-namespace/my-kafka-cluster) 4

1
MarkerFilter 类型比较了指定的过滤标记。
2
如果标志匹配,onMatch 属性接受日志。
3
如果标志不匹配,则 onMismatch 属性将拒绝日志。
4
用于过滤的标记格式为 KIND(NAMESPACE/NAME-OF-RESOURCE)。

您可以创建一个或多个过滤器。在这里,会针对两个 Kafka 集群过滤日志。

多个日志记录过滤器配置

appender.console.filter.filter1.type=MarkerFilter
appender.console.filter.filter1.onMatch=ACCEPT
appender.console.filter.filter1.onMismatch=DENY
appender.console.filter.filter1.marker=Kafka(my-namespace/my-kafka-cluster-1)
appender.console.filter.filter2.type=MarkerFilter
appender.console.filter.filter2.onMatch=ACCEPT
appender.console.filter.filter2.onMismatch=DENY
appender.console.filter.filter2.marker=Kafka(my-namespace/my-kafka-cluster-2)

为 Cluster Operator 添加过滤器

要向 Cluster Operator 添加过滤器,更新其日志记录 ConfigMap YAML 文件(install/cluster-operator/050-ConfigMap-strimzi-cluster-operator.yaml)。

流程

  1. 更新 050-ConfigMap-strimzi-cluster-operator.yaml 文件,将过滤器属性添加到 ConfigMap 中。

    在本例中,过滤器属性仅为 my-kafka-cluster Kafka 集群返回日志:

    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: strimzi-cluster-operator
    data:
      log4j2.properties:
        #...
        appender.console.filter.filter1.type=MarkerFilter
        appender.console.filter.filter1.onMatch=ACCEPT
        appender.console.filter.filter1.onMismatch=DENY
        appender.console.filter.filter1.marker=Kafka(my-namespace/my-kafka-cluster)

    或者,直接编辑 ConfigMap:

    oc edit configmap strimzi-cluster-operator
  2. 如果您更新了 YAML 文件而不是直接编辑 ConfigMap,请通过部署 ConfigMap 来应用更改:

    oc create -f install/cluster-operator/050-ConfigMap-strimzi-cluster-operator.yaml

为主题 Operator 或 User Operator 添加过滤器

要在 Topic Operator 或 User Operator 中添加过滤器,请创建或编辑日志记录 ConfigMap。

在这一流程中,使用 Topic Operator 的过滤器创建日志 ConfigMap。用户 Operator 也使用相同的方法。

流程

  1. 创建 ConfigMap。

    您可以将 ConfigMap 作为 YAML 文件或属性文件创建。

    在本例中,过滤器属性仅为 my-topic 主题返回日志:

    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: logging-configmap
    data:
      log4j2.properties:
        rootLogger.level="INFO"
        appender.console.filter.filter1.type=MarkerFilter
        appender.console.filter.filter1.onMatch=ACCEPT
        appender.console.filter.filter1.onMismatch=DENY
        appender.console.filter.filter1.marker=KafkaTopic(my-namespace/my-topic)

    如果您使用属性文件,请在命令行中指定该文件:

    oc create configmap logging-configmap --from-file=log4j2.properties

    属性文件定义日志配置:

    # Define the logger
    rootLogger.level="INFO"
    # Set the filters
    appender.console.filter.filter1.type=MarkerFilter
    appender.console.filter.filter1.onMatch=ACCEPT
    appender.console.filter.filter1.onMismatch=DENY
    appender.console.filter.filter1.marker=KafkaTopic(my-namespace/my-topic)
    # ...
  2. 在资源的 spec 中定义 外部 日志记录,将 logging.valueFrom.configMapKeyRef.name 设置为 ConfigMap 的名称,valueFrom.configMapKeyRef.key 设置为此 ConfigMap 中的键。

    对于 Topic Operator,日志记录在 Kafka 资源的 topicOperator 配置中指定。

    spec:
      # ...
      entityOperator:
        topicOperator:
          logging:
            type: external
            valueFrom:
              configMapKeyRef:
                name: logging-configmap
                key: log4j2.properties
  3. 通过部署 Cluster Operator 来应用更改:
create -f install/cluster-operator -n my-cluster-operator-namespace

2.9. 从外部源加载配置值

使用 Kubernetes Configuration Provider 插件,从外部来源加载配置数据。从 OpenShift 机密或 ConfigMap 加载数据。

假设您在 Kafka 命名空间外或 Kafka 集群外管理的 Secret。提供程序允许您在配置中引用 Secret 的值,而无需提取文件。您只需告诉提供商要使用的 Secret 并提供访问权限。供应商会在不需要重启 Kafka 组件的情况下加载数据,即使使用新的 Secret 或 ConfigMap 时也是如此。当 Kafka Connect 实例托管多个连接器时,此功能可避免中断。

该供应商独立于 AMQ Streams 运行。您可以使用它来加载所有 Kafka 组件的配置数据,包括生产者和使用者。例如,使用它来提供 Kafka Connect 连接器配置的凭据。

在这一流程中,外部 ConfigMap 为连接器提供配置属性。

注意

OpenShift 配置提供程序无法使用挂载的文件。例如,它无法加载需要信任存储或密钥存储位置的值。相反,您可以将 ConfigMap 或 Secret 挂载到 Kafka Connect pod 中,作为环境变量或卷。您可以使用 KafkaConnect.spec 中的 externalConfiguration 属性 添加配置。您无需通过这种方法设置访问权限。但是,当使用新 Secret 或 ConfigMap 作为连接器时,Kafka Connect 需要重启。这会导致所有 Kafka Connect 实例的连接器中断。

先决条件

  • OpenShift 集群可用。
  • Kafka 集群正在运行。
  • Cluster Operator 正在运行。

流程

  1. 创建包含配置属性的 ConfigMap 或 Secret。

    在本例中,名为 my-connector-configuration 的 ConfigMap 包含连接器属性:

    带有连接器属性的 ConfigMap 示例

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: my-connector-configuration
    data:
      option1: value1
      option2: value2

  2. 在 Kafka Connect 配置中指定 OpenShift 配置提供程序。

    此处显示的规格可支持从 Secret 和 ConfigMap 加载值。

    将外部卷设置为 ConfigMap 中的值的示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect
      annotations:
        strimzi.io/use-connector-resources: "true"
    spec:
      # ...
      config:
        # ...
        config.providers: secrets,configmaps 1
        config.providers.secrets.class: io.strimzi.kafka.KubernetesSecretConfigProvider 2
        config.providers.configmaps.class: io.strimzi.kafka.KubernetesConfigMapConfigProvider 3
      # ...

    1
    配置提供程序的别名用于定义其他配置参数。供应商参数使用 config.providers 中的别名,格式为 config.providers.${alias}.class
    2
    KubernetesSecretConfigProvider 提供 Secret 的值。
    3
    KubernetesConfigMapConfigProvider 提供 ConfigMap 中的值。
  3. 创建或更新资源以启用提供程序。

    oc apply -f KAFKA-CONNECT-CONFIG-FILE
  4. 创建允许访问外部 ConfigMap 中的值的角色。

    从 ConfigMap 访问值的角色示例

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: connector-configuration-role
    rules:
    - apiGroups: [""]
      resources: ["configmaps"]
      resourceNames: ["my-connector-configuration"]
      verbs: ["get"]
    # ...

    该规则授予角色权限来访问 my-connector-configuration ConfigMap。

  5. 创建角色绑定,以允许访问包含 ConfigMap 的命名空间。

    用于访问包含 ConfigMap 的命名空间的角色绑定示例

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: connector-configuration-role-binding
    subjects:
    - kind: ServiceAccount
      name: my-connect-connect
      namespace: my-project
    roleRef:
      kind: Role
      name: connector-configuration-role
      apiGroup: rbac.authorization.k8s.io
    # ...

    角色绑定授予访问 my-project 命名空间的角色权限。

    该服务帐户必须与 Kafka Connect 部署使用的相同。服务帐户名称格式为 CLUSTER_NAME-connect,其中 CLUSTER_NAMEKafkaConnect 自定义资源的名称。

  6. 在连接器配置中引用 ConfigMap。

    引用 ConfigMap 的连接器配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnector
    metadata:
      name: my-connector
      labels:
        strimzi.io/cluster: my-connect
    spec:
      # ...
      config:
        option: ${configmaps:my-project/my-connector-configuration:option1}
        # ...
    # ...

    ConfigMap 中属性值的占位符在连接器配置中引用。占位符结构为 configmaps:PATH-AND-FILE-NAME:PROPERTYKubernetesConfigMapConfigProvider 从外部 ConfigMap 中读取并提取 option1 属性值。

第 3 章 配置外部监听程序

使用外部监听程序向 OpenShift 环境外的客户端公开您的 AMQ Streams Kafka 集群。

在外部监听程序配置中指定要公开 Kafka 的连接 类型

  • NodePort 使用 NodePort 类型 服务
  • LoadBalancer 使用 Loadbalancer 类型 服务
  • Ingress 使用 Kubernetes IngressKubernetes 的 NGINX Ingress Controller
  • 路由 使用 OpenShift 路由 和 HAProxy 路由器

有关监听器配置的更多信息,请参阅 GenericKafkaListener 模式参考

注意

路由 只在 OpenShift 中被支持

3.1. 使用节点端口访问 Kafka

此流程描述了如何使用节点端口从外部客户端访问 AMQ Streams Kafka 集群。

要连接到代理,您需要 Kafka bootstrap 地址 的主机名和端口号,以及用于身份验证的证书。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 配置 Kafka 资源,并将外部监听程序设置为 nodeport 类型。

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        listeners:
          - name: external
            port: 9094
            type: nodeport
            tls: true
            authentication:
              type: tls
            # ...
        # ...
      zookeeper:
        # ...
  2. 创建或更新资源。

    oc apply -f KAFKA-CONFIG-FILE

    为每个 Kafka 代理和外部 bootstrap 服务 创建 NodePort 类型服务。bootstrap 服务将外部流量路由到 Kafka 代理。用于连接的节点地址被传播到 Kafka 自定义资源 的状态

    也使用与 Kafka 资源相同的名称来创建用于验证 kafka 代理身份的集群 CA 证书。

  3. 从 Kafka 资源 的状态检索您用来访问 Kafka 集群的 bootstrap 地址。

    oc get kafka KAFKA-CLUSTER-NAME -o=jsonpath='{.status.listeners[?(@.type=="external")].bootstrapServers}{"\n"}'
  4. 如果启用了 TLS 加密,请提取代理认证机构的公共证书。

    oc get secret KAFKA-CLUSTER-NAME-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt

    使用 Kafka 客户端中提取的证书来配置 TLS 连接。如果启用了任何身份验证,您还需要配置 SASL 或 TLS 身份验证。

3.2. 使用 loadbalancers 访问 Kafka

这个步骤描述了如何使用 loadbalancers 从外部客户端访问 AMQ Streams Kafka 集群。

要连接到代理,您需要 bootstrap 负载均衡器的地址, 以及用于 TLS 加密的证书。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 配置 Kafka 资源,并将外部监听程序设置为 loadbalancer 类型。

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        listeners:
          - name: external
            port: 9094
            type: loadbalancer
            tls: true
            # ...
        # ...
      zookeeper:
        # ...
  2. 创建或更新资源。

    oc apply -f KAFKA-CONFIG-FILE

    LoadBalancer 类型 服务和负载均衡器是为每个 Kafka 代理和一个外部 bootstrap 服务 创建的。bootstrap 服务将外部流量路由到所有 Kafka 代理。用于连接的 DNS 名称和 IP 地址会传播到 每个服务的状态

    也使用与 Kafka 资源相同的名称来创建用于验证 kafka 代理身份的集群 CA 证书。

  3. 从 Kafka 资源 的状态检索可用于访问 Kafka 集群的 bootstrap 服务地址。

    oc get kafka KAFKA-CLUSTER-NAME -o=jsonpath='{.status.listeners[?(@.type=="external")].bootstrapServers}{"\n"}'
  4. 如果启用了 TLS 加密,请提取代理认证机构的公共证书。

    oc get secret KAFKA-CLUSTER-NAME-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt

    使用 Kafka 客户端中提取的证书来配置 TLS 连接。如果启用了任何身份验证,您还需要配置 SASL 或 TLS 身份验证。

3.3. 使用 ingress 访问 Kafka

此流程演示了如何使用 Nginx Ingress 从 OpenShift 外部的外部客户端访问 AMQ Streams Kafka 集群。

要连接到代理,需要 Ingress bootstrap 地址的主机名(公告地址 ),以及用于身份验证的证书。

对于使用 Ingress 访问,端口始终为 443。

TLS passthrough

Kafka 通过 TCP 使用二进制协议,但 Kubernetes 的 NGINX Ingress Controller 旨在使用 HTTP 协议。为了能够通过 Ingress 传递 Kafka 连接,AMQ Streams 使用 Kubernetes NGINX Ingress Controller 的 TLS 直通功能。确保在 NGINX Ingress Controller 中为 Kubernetes 部署启用了 TLS passthrough。

由于它使用 TLS passthrough 功能,所以在使用 Ingress 公开 Kafka 时无法禁用 TLS 加密。

有关启用 TLS 直通的更多信息,请参阅 TLS 直通文档

先决条件

流程

  1. 配置 Kafka 资源,并将外部监听程序设置为 ingress 类型。

    指定 bootstrap 服务和 Kafka 代理的 Ingress 主机。

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        listeners:
          - name: external
            port: 9094
            type: ingress
            tls: true
            authentication:
              type: tls
            configuration: 1
              bootstrap:
                host: bootstrap.myingress.com
              brokers:
              - broker: 0
                host: broker-0.myingress.com
              - broker: 1
                host: broker-1.myingress.com
              - broker: 2
                host: broker-2.myingress.com
        # ...
      zookeeper:
        # ...
    1
    bootstrap 服务和 Kafka 代理的 Ingress 主机。
  2. 创建或更新资源。

    oc apply -f KAFKA-CONFIG-FILE

    为每个 Kafka 代理创建 ClusterIP 类型服务,以及一个额外的 bootstrap 服务。这些服务供 Ingress 控制器用于将流量路由到 Kafka 代理。还会为每个服务创建一个 Ingress 资源,以使用 Ingress 控制器公开它们。Ingress 主机传播到每个 服务的状态

    也使用与 Kafka 资源相同的名称来创建用于验证 kafka 代理身份的集群 CA 证书。

    使用 Kafka 客户端中的 配置 和端口 443(BOOTSTRAP-HOST:443)中指定的 bootstrap 主机 地址,作为 bootstrap 地址 连接到 Kafka 集群。

  3. 提取代理认证机构的公共证书。

    oc get secret KAFKA-CLUSTER-NAME-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt

    使用 Kafka 客户端中提取的证书来配置 TLS 连接。如果启用了任何身份验证,您还需要配置 SASL 或 TLS 身份验证。

3.4. 使用 OpenShift 路由访问 Kafka

此流程描述了如何使用路由从 OpenShift 外部的外部客户端访问 AMQ Streams Kafka 集群。

要连接到代理,您需要路由 bootstrap 地址 的主机名以及用于 TLS 加密的证书。

对于使用路由的访问,端口始终为 443。

先决条件

  • OpenShift 集群
  • 一个正在运行的 Cluster Operator

流程

  1. 配置 Kafka 资源,并将外部监听程序设置为 路由 类型。

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      labels:
        app: my-cluster
      name: my-cluster
      namespace: myproject
    spec:
      kafka:
        # ...
        listeners:
          - name: listener1
            port: 9094
            type: route
            tls: true
            # ...
        # ...
      zookeeper:
        # ...
    警告

    OpenShift Route 地址包含 Kafka 集群的名称、侦听器的名称以及在其中创建的命名空间的名称。例如,my -cluster-kafka-listener1-bootstrap-myproject (CLUSTER-NAME-kafka-LISTENER-NAME-bootstrap-NAMESPACE)。请注意,地址的长度不超过 63 个字符的最大限制。

  2. 创建或更新资源。

    oc apply -f KAFKA-CONFIG-FILE

    为每个 Kafka 代理和外部 bootstrap 服务 创建 ClusterIP 类型服务。服务将流量从 OpenShift 路由路由到 Kafka 代理。同时也为每个服务创建一个 OpenShift Route 资源,以利用 HAProxy 负载平衡器公开它们。用于连接的 DNS 地址会传播到每个 服务的状态

    也使用与 Kafka 资源相同的名称来创建用于验证 kafka 代理身份的集群 CA 证书。

  3. 从 Kafka 资源 的状态检索可用于访问 Kafka 集群的 bootstrap 服务地址。

    oc get kafka KAFKA-CLUSTER-NAME -o=jsonpath='{.status.listeners[?(@.type=="external")].bootstrapServers}{"\n"}'
  4. 提取代理认证机构的公共证书。

    oc get secret KAFKA-CLUSTER-NAME-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt

    使用 Kafka 客户端中提取的证书来配置 TLS 连接。如果启用了任何身份验证,您还需要配置 SASL 或 TLS 身份验证。

第 4 章 管理对 Kafka 的安全访问

您可以通过管理每个客户端对 Kafka 代理的访问权限来保护 Kafka 集群。

Kafka 代理和客户端之间的安全连接可以包含:

  • 为数据交换加密
  • 验证以证明身份
  • 允许或拒绝用户执行的操作的授权

本章解释了如何在 Kafka 代理和客户端之间设置安全连接,包含如下所述:

  • Kafka 集群和客户端的安全选项
  • 如何保护 Kafka 代理
  • 如何使用授权服务器进行基于 OAuth 2.0 令牌的身份验证和授权

4.1. Kafka 的安全选项

使用 Kafka 资源配置用于 Kafka 身份验证和授权的机制。

4.1.1. 监听程序验证

对于 OpenShift 集群内的客户端,您可以创建 普通 (无需加密)或 tls 内部 侦听器。

对于 OpenShift 集群外的客户端,您可以创建 外部 侦听器并指定连接机制,可以是 节点端口负载均衡器、 入口路由 (在 OpenShift 上)。

有关连接外部客户端的配置选项的更多信息,请参阅配置外部监听程序

支持的验证选项:

  1. 双向 TLS 身份验证(仅在启用了 TLS 加密的监听器中)
  2. SCRAM-SHA-512 验证
  3. 基于 OAuth 2.0 令牌的身份验证

您选择的身份验证选项取决于您要如何验证客户端对 Kafka 代理的访问。

图 4.1. Kafka 侦听程序验证选项

监听程序身份验证配置选项

侦听器 身份验证 属性用于指定特定于该侦听器的身份验证机制。

如果没有指定 身份验证 属性,侦听器不会验证通过该侦听器进行连接的客户端。侦听器将接受所有连接,无需身份验证。

在使用 User Operator 管理 KafkaUsers 时,必须配置身份验证。

以下示例显示:

  • 为 SCRAM-SHA-512 身份验证配置 的普通 监听器
  • 具有 mutual TLS 身份验证的 A tls 侦听器
  • 具有 mutual TLS 身份验证 的外部 监听程序

每个监听程序都使用 Kafka 集群中的唯一名称和端口进行配置。

注意

侦听器不能配置为使用为代理间通信保留的端口(9091 或 9090)和指标(9404)。

显示监听器身份验证配置的示例

# ...
listeners:
  - name: plain
    port: 9092
    type: internal
    tls: true
    authentication:
      type: scram-sha-512
  - name: tls
    port: 9093
    type: internal
    tls: true
    authentication:
      type: tls
  - name: external
    port: 9094
    type: loadbalancer
    tls: true
    authentication:
      type: tls
# ...

4.1.1.1. 双向 TLS 身份验证

双向 TLS 身份验证始终用于 Kafka 代理和 ZooKeeper pod 之间的通信。

AMQ Streams 可以配置 Kafka 以使用 TLS(传输层安全),以提供 Kafka 代理和客户端之间的加密通信,无论是否带有或不使用相互身份验证。为互相或双向身份验证,服务器和客户端都提供证书。当您配置相互身份验证时,代理会验证客户端(客户端身份验证),客户端验证代理(服务器身份验证)。

注意

TLS 身份验证更通常是单向,一个方验证另一方的身份。例如,当 Web 浏览器和 Web 服务器之间使用 HTTPS 时,浏览器会获得 Web 服务器身份验证。

4.1.1.2. SCRAM-SHA-512 验证

SCRAM(销售挑战响应身份验证机制)是一种身份验证协议,可以使用密码建立相互身份验证。AMQ Streams 可以配置 Kafka,以使用 SASL(简单身份验证和安全层) SCRAM-SHA-512 提供未加密和加密客户端连接的身份验证。

当 SCRAM-SHA-512 身份验证与 TLS 客户端连接一起使用时,TLS 协议提供加密,但不用于身份验证。

以下 SCRAM 属性可以安全地在未加密连接中使用 SCRAM-SHA-512:

  • 密码不会通过通信通道在明文中发送。相反,客户端和服务器都受到另一用户的挑战,难以提供他们知道验证用户密码的证明。
  • 服务器和客户端各自为每个身份验证交换生成新的挑战。这意味着交换具有应对重播攻击的弹性。

当使用 scr am-sha-512 配置 KafkaUser.spec.authentication.type 时,User Operator 将生成由大写和小写 ASCII 字母和数字组成的随机 12 个字符密码。

4.1.1.3. 网络策略

AMQ Streams 自动为每个在 Kafka 代理上启用的监听程序创建一个 NetworkPolicy 资源。默认情况下,NetworkPolicy 会 授予监听器访问所有应用程序和命名空间的权限。

如果要将网络级别的监听器访问限制为仅选择的应用程序或命名空间,请使用 networkPolicyPeers 属性。

使用网络策略作为监听器身份验证配置的一部分。每个监听器都可以具有不同的 networkPolicyPeers 配置。

如需更多信息,请参阅 Listener 网络策略 部分和 NetworkPolicyPeer API 参考

注意

您的 OpenShift 配置必须支持 Ingress NetworkPolicies,以便在 AMQ Streams 中使用网络策略。

4.1.1.4. 其他监听程序配置选项

您可以使用 GenericKafkaListenerConfiguration 模式 的属性在监听器中添加更多配置。

4.1.2. kafka 授权

您可以使用 Kafka. spec.kafka 资源中的 authorization 属性为 Kafka 代理配置授权。如果缺少 authorization 属性,则不启用授权,并且客户端没有限制。启用后,授权将应用到所有启用的监听程序。授权方法在 type 字段中定义。

支持的授权选项:

图 4.2. Kafka 集群授权选项

kafks 授权配置选项
4.1.2.1. 超级用户

无论访问限制如何,超级用户可以访问 Kafka 集群中的所有资源,并受所有授权机制的支持。

要为 Kafka 集群指定超级用户,请在 superUsers 属性中添加用户主体列表。如果用户使用 TLS 客户端身份验证,则其用户名是其证书主题的通用名称,前缀为 CN=

带有超级用户的示例配置

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  namespace: myproject
spec:
  kafka:
    # ...
    authorization:
      type: simple
      superUsers:
        - CN=client_1
        - user_2
        - CN=client_3
    # ...

4.2. Kafka 客户端的安全选项

使用 KafkaUser 资源,为 Kafka 客户端配置身份验证机制、授权机制和访问权限。在配置安全性方面,客户端以用户身份表示。

您可以验证并授权用户对 Kafka 代理的访问权限。身份验证允许访问,授权限制了对允许的操作的访问。

您还可以创建对 Kafka 代理具有不受约束访问权限的 超级用户

身份验证和授权机制必须与 用于访问 Kafka 代理的监听程序规格相符。

4.2.1. 为用户处理识别 Kafka 集群

KafkaUser 资源包含一个标签,用于定义它所属的 Kafka 集群的名称(从 Kafka 资源的名称衍生)。

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaUser
metadata:
  name: my-user
  labels:
    strimzi.io/cluster: my-cluster

该标签供 User Operator 用于标识 KafkaUser 资源、创建一个新用户,并在后续处理用户时也使用该标签。

如果标签与 Kafka 集群不匹配,User Operator 无法识别 KafkaUser,并且不会创建该用户。

如果 KafkaUser 资源的状态为空,请检查您的标签。

4.2.2. 用户身份验证

使用 KafkaUser.spec 中的 身份验证 属性配置用户身份验证。为用户启用的身份验证机制使用 type 字段指定。

支持的验证机制:

  • TLS 客户端身份验证
  • SCRAM-SHA-512 验证

如果没有指定身份验证机制,User Operator 不会创建用户或其凭证。

4.2.2.1. TLS 客户端身份验证

要使用 TLS 客户端身份验证,请将 type 字段设置为 tls

启用了 TLS 客户端身份验证的 KafkaUser 示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaUser
metadata:
  name: my-user
  labels:
    strimzi.io/cluster: my-cluster
spec:
  authentication:
    type: tls
  # ...

当 User Operator 创建用户时,它会创建一个名称与 KafkaUser 资源相同的新 Secret。Secret 包含用于 TLS 客户端身份验证的私钥和公钥。公钥包含在用户证书中,由客户端证书颁发机构(CA)签名。

所有键均采用 X.509 格式。

secret 以 PEM 和 PKCS #12 格式提供私钥和证书。

有关保护 Kafka 与 Secret 的通信的更多信息,请参阅 第 11 章 管理 TLS 证书

带有用户凭证的 Secret 示例

apiVersion: v1
kind: Secret
metadata:
  name: my-user
  labels:
    strimzi.io/kind: KafkaUser
    strimzi.io/cluster: my-cluster
type: Opaque
data:
  ca.crt: # Public key of the client CA
  user.crt: # User certificate that contains the public key of the user
  user.key: # Private key of the user
  user.p12: # PKCS #12 archive file for storing certificates and keys
  user.password: # Password for protecting the PKCS #12 archive file

4.2.2.2. SCRAM-SHA-512 Authentication

要使用 SCRAM-SHA-512 身份验证机制,请将 type 字段设置为 scr am-sha-512

启用了 SCRAM-SHA-512 身份验证的 KafkaUser 示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaUser
metadata:
  name: my-user
  labels:
    strimzi.io/cluster: my-cluster
spec:
  authentication:
    type: scram-sha-512
  # ...

当 User Operator 创建用户时,它会创建一个名称与 KafkaUser 资源相同的新 secret。该机密包含 password 密钥中生成的密码,该密码使用 base64 编码。若要使用该密码,必须对其进行解码。

带有用户凭证的 Secret 示例

apiVersion: v1
kind: Secret
metadata:
  name: my-user
  labels:
    strimzi.io/kind: KafkaUser
    strimzi.io/cluster: my-cluster
type: Opaque
data:
  password: Z2VuZXJhdGVkcGFzc3dvcmQ= 1
  sasl.jaas.config: b3JnLmFwYWNoZS5rYWZrYS5jb21tb24uc2VjdXJpdHkuc2NyYW0uU2NyYW1Mb2dpbk1vZHVsZSByZXF1aXJlZCB1c2VybmFtZT0ibXktdXNlciIgcGFzc3dvcmQ9ImdlbmVyYXRlZHBhc3N3b3JkIjsK 2

1
生成的密码 base64 编码。
2
用于 SASL SCRAM-SHA-512 身份验证的 JAAS 配置字符串,采用 base64 编码。

解码生成的密码:

echo "Z2VuZXJhdGVkcGFzc3dvcmQ=" | base64 --decode

4.2.3. 用户授权

用户授权使用 KafkaUser.spec 中的 授权 属性进行配置。用户启用的授权类型通过 type 字段指定。

要使用简单授权,您可以在 KafkaUser.spec.authorization 中将 type 属性设置为 simple。简单授权使用默认的 Kafka 授权插件 AclAuthorizer

或者,您可以使用 OPA 授权,或者已使用基于 OAuth 2.0 令牌的身份验证,您也可以使用 OAuth 2.0 授权

如果没有指定授权,User Operator 不会为用户置备任何访问权限。这种 KafkaUser 是否可以访问资源取决于所使用的授权程序。例如,对于 AclAuthorizer,这由其 allow.everyone.if.no.acl.found 配置决定。

4.2.3.1. ACL 规则

AclAuthorizer 使用 ACL 规则来管理对 Kafka 代理的访问。

ACL 规则为用户授予访问权限,用户在 acls 属性中指定。

有关 AclRule 对象的更多信息,请参阅 AclRule 架构引用

4.2.3.2. 超级用户访问 Kafka 代理

如果在 Kafka 代理配置中的超级用户列表中添加用户,则允许用户无限访问集群,无论 KafkaUser 中的 ACL 中定义的任何授权限制。

有关配置超级用户访问权限的更多信息,请参阅 Kafka 授权

4.2.3.3. 用户配额

您可以配置 KafkaUser 资源的 spec 来强制配额,以便用户不会超过配置的 Kafka 代理访问级别。您可以设置基于大小的网络使用情况和基于时间的 CPU 使用率阈值。您还可以添加分区变异配额,以控制用户请求更改分区的请求的速率。

使用用户配额的 KafkaUser 示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaUser
metadata:
  name: my-user
  labels:
    strimzi.io/cluster: my-cluster
spec:
  # ...
  quotas:
    producerByteRate: 1048576 1
    consumerByteRate: 2097152 2
    requestPercentage: 55 3
    controllerMutationRate: 10 4

1
对用户可以推送到 Kafka 代理的数据量的字节每秒配额
2
对用户可从 Kafka 代理获取的数据量的字节/秒配额
3
CPU 使用率限制为客户端组的时间百分比
4
每秒允许的并发分区创建和删除操作数(参数)

有关这些属性的更多信息,请参阅 KafkaUserQuotas 架构引用

4.3. 保护对 Kafka 代理的访问

要建立对 Kafka 代理的安全访问,您需要配置并应用:

  • Kafka 资源,用于:

    • 使用指定验证类型创建监听程序
    • 为整个 Kafka 集群配置授权
  • 通过监听程序安全访问 Kafka 代理的 Kafka User 资源

配置 Kafka 资源以设置:

  • 监听程序验证
  • 限制对 Kafka 侦听器的访问的网络策略
  • kafka 授权
  • 超级用户对代理进行无限制访问

身份验证是为每个监听器独立配置的。始终为整个 Kafka 集群配置授权。

Cluster Operator 创建监听程序并设置集群和客户端证书颁发机构(CA)证书,以便在 Kafka 集群中启用身份验证。

您可以通过 安装您自己的证书来替换 Cluster Operator 生成的证书。您还可以将 监听程序配置为使用由外部证书颁发机构管理的 Kafka 侦听器证书。证书以 PKCS #12 格式(.p12)和 PEM(.crt)格式提供。

使用 KafkaUser 启用特定客户端用来访问 Kafka 的身份验证和授权机制。

配置 KafkaUser 资源以设置:

  • 与启用的监听器验证匹配的身份验证
  • 与启用的 Kafka 授权匹配的授权
  • 用于控制客户端资源使用的配额

User Operator 根据所选的身份验证类型,创建代表客户端以及用于客户端身份验证的安全凭证的用户。

其它资源

有关以下模式的更多信息:

4.3.1. 保护 Kafka 代理

此流程演示了在运行 AMQ Streams 时保护 Kafka 代理的步骤。

为 Kafka 代理实施的安全性必须与为需要访问的客户端实施的安全性兼容。

  • Kafka.spec.kafka.listeners[*].authentication matches KafkaUser.spec.authentication
  • kafka.spec.kafka.authorizationKafkaUser.spec.authorization匹配

步骤演示了使用 TLS 身份验证的简单授权和监听器的配置。有关监听器配置的更多信息,请参阅 GenericKafkaListener 模式参考

另外,您可以使用 SCRAM-SHA 或 OAuth 2.0 进行 监听程序身份验证,使用 OAuth 2.0 或 OPA 进行 Kafka 授权

流程

  1. 配置 Kafka 资源。

    1. 配置 授权 属性。
    2. 配置 listens 属性,以创建具有身份验证的侦听器。

      例如:

      apiVersion: kafka.strimzi.io/v1beta2
      kind: Kafka
      spec:
        kafka:
          # ...
          authorization: 1
            type: simple
            superUsers: 2
              - CN=client_1
              - user_2
              - CN=client_3
          listeners:
            - name: tls
              port: 9093
              type: internal
              tls: true
              authentication:
                type: tls 3
          # ...
        zookeeper:
          # ...
      1
      2
      对 Kafka 拥有无限访问权限的用户主体列表。在使用 TLS 身份验证时,CN 是客户端证书的常用名称。
      3
      监听器身份验证机制可以为每个侦听器配置,并 指定为 mutual TLS、SCRAM-SHA-512 或基于令牌的 OAuth 2.0

      如果您要配置外部监听程序,其配置取决于所选的连接机制。

  2. 创建或更新 Kafka 资源。

    oc apply -f KAFKA-CONFIG-FILE

    使用 TLS 身份验证配置 Kafka 代理监听程序。

    为每个 Kafka 代理 pod 创建一个服务。

    创建一个服务作为连接到 Kafka 集群的 bootstrap 地址

    也使用与 Kafka 资源相同的名称来创建用于验证 kafka 代理身份的集群 CA 证书。

4.3.2. 保护用户对 Kafka 的访问

使用 KafkaUser 资源的属性来配置 Kafka 用户。

您可以使用 oc apply 创建或修改用户,使用 oc delete 删除现有用户。

例如:

  • oc apply -f USER-CONFIG-FILE
  • oc delete KafkaUser USER-NAME

当您配置 KafkaUser 身份验证和授权机制时,请确保它们与等同的 Kafka 配置匹配:

  • KafkaUser.spec.authentication matches Kafka.spec.kafka.listeners[*].authentication
  • KafkaUser.spec.authorizationKafka.spec.kafka.authorization匹配

此流程演示了如何使用 TLS 身份验证创建用户。您还可以创建具有 SCRAM-SHA 身份验证的用户。

所需的身份验证取决于为 Kafka 代理监听程序配置的身份验证类型

注意

Kafka 用户和 Kafka 代理之间的身份验证取决于每个用户的身份验证设置。例如,如果 Kafka 配置中没有启用 TLS 的用户,则无法验证它。

先决条件

KafkaUser 中的身份验证类型应与 Kafka 代理中配置的身份验证匹配。

流程

  1. 配置 KafkaUser 资源。

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaUser
    metadata:
      name: my-user
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      authentication: 1
        type: tls
      authorization:
        type: simple 2
        acls:
          - resource:
              type: topic
              name: my-topic
              patternType: literal
            operation: Read
          - resource:
              type: topic
              name: my-topic
              patternType: literal
            operation: Describe
          - resource:
              type: group
              name: my-group
              patternType: literal
            operation: Read
    1
    用户身份验证机制,定义为 mutual tls 或 scr am-sha-512
    2
    简单授权,这需要附带的 ACL 规则列表。
  2. 创建或更新 KafkaUser 资源。

    oc apply -f USER-CONFIG-FILE

    已创建用户,以及名称与 KafkaUser 资源相同的 Secret。Secret 包含用于 TLS 客户端身份验证的私钥和公钥。

有关使用安全连接到 Kafka 代理的属性配置 Kafka 客户端的详情,请参考在 OpenShift 指南中为 OpenShift 之外的客户端设置访问权限

4.3.3. 使用网络策略限制对 Kafka 侦听器的访问

您可以使用 networkPolicyPeers 属性将监听器的访问限制为所选应用程序。

先决条件

  • 个支持 Ingress NetworkPolicies 的 OpenShift 集群。
  • Cluster Operator 正在运行。

流程

  1. 打开 Kafka 资源。
  2. networkPolicyPeers 属性中,定义允许访问 Kafka 集群的应用程序 pod 或命名空间。

    例如,将 a tls 侦听程序配置为只允许来自标签 app 设置为 kafka-client 的应用程序 pod 的连接:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      kafka:
        # ...
        listeners:
          - name: tls
            port: 9093
            type: internal
            tls: true
            authentication:
              type: tls
            networkPolicyPeers:
              - podSelector:
                  matchLabels:
                    app: kafka-client
        # ...
      zookeeper:
        # ...
  3. 创建或更新资源。

    使用 oc apply:

    oc apply -f your-file

其它资源

4.4. 使用基于 OAuth 2.0 令牌的身份验证

AMQ Streams 支持使用 SASL OAUTHBEARER 机制进行 OAuth 2.0 身份验证。

OAuth 2.0 支持应用之间基于令牌的标准化身份验证和授权,使用中央授权服务器发布对资源的有限访问权限的令牌。

您可以配置 OAuth 2.0 身份验证,然后配置 OAuth 2.0 授权

OAuth 2.0 身份验证也可与 简单 或基于 OPA 的 Kafka 授权 一起使用。

通过使用基于 OAuth 2.0 令牌的身份验证,应用客户端可以访问应用服务器(称为 资源服务器)上的资源,而无需公开帐户凭据。

应用客户端通过访问令牌来进行身份验证,应用服务器也可以使用该令牌来确定要授予的访问权限级别。授权服务器处理关于访问权限的访问和咨询。

在 AMQ Streams 中:

  • Kafka 代理充当 OAuth 2.0 资源服务器
  • Kafka 客户端充当 OAuth 2.0 应用程序客户端

Kafka 客户端向 Kafka 代理进行身份验证。代理和客户端根据需要与 OAuth 2.0 授权服务器通信,以获取或验证访问令牌。

对于 AMQ Streams 的部署,OAuth 2.0 集成提供:

  • 对 Kafka 代理的服务器端 OAuth 2.0 支持
  • 客户端 OAuth 2.0 支持 Kafka MirrorMaker、Kafka Connect 和 Kafka Bridge

其它资源

4.4.1. OAuth 2.0 身份验证机制

AMQ Streams 支持 OAUTHBEARER 和 PLAIN 机制进行 OAuth 2.0 身份验证。这两种机制都允许 Kafka 客户端通过 Kafka 代理建立经过身份验证的会话。客户端、授权服务器和 Kafka 代理之间的身份验证流程因每种机制而异。

建议您将客户端配置为尽可能使用 OAUTHBEARER。OAUTHBEARER 提供比 PLAIN 更高的安全级别,因为客户端凭证 永远不会 与 Kafka 代理共享。只考虑在不支持 OAUTHBEARER 的 Kafka 客户端中使用 PLAIN。

如果需要,可以在同一个 oauth 侦听器上同时启用 OAUTHBEARER 和 PLAIN。

OAUTHBEARER 概述

Kafka 支持 OAUTHBEARER 身份验证机制,但必须明确配置它。另外,很多 Kafka 客户端工具在协议级别使用为 OAUTHBEARER 提供基本支持的库。

为简化应用程序开发,AMQ Streams 为上游 Kafka 客户端 Java 库(但不为其他库)提供 OAuth 回调处理程序。因此,您不需要为此类客户端自行编写回调处理程序。应用客户端可以使用回调处理程序来提供访问令牌。以其他语言编写的客户端(如 Go)必须使用自定义代码连接到授权服务器并获取访问令牌。

使用 OAUTHBEARER 时,客户端会启动与 Kafka 代理的会话进行凭证交换,其中凭证采用回调处理程序提供的 bearer 令牌的形式。通过使用回调,您可以通过以下三种方法之一配置令牌置备:

  • 客户端 ID 和 Secret(使用 OAuth 2.0 客户端凭证机制)
  • 长期访问令牌,在配置时手动获得
  • 长期存在的刷新令牌,在配置时手动获取

OAUTHBEARER 在 Kafka 代理的 oauth 监听程序配置中自动启用。您可以将 enableOauthBearer 属性设置为 true,但这不是强制要求。

  # ...
  authentication:
    type: oauth
    # ...
    enableOauthBearer: true
注意

OAUTHBEARER 身份验证只能由支持协议级别的 OAUTHBEARER 机制的 Kafka 客户端使用。

PLAIN 概述

PLAIN 是供所有 Kafka 客户端工具(包括 kafkacat 等开发人员工具)使用的简单身份验证机制。为了启用 PLAIN 与 OAuth 2.0 身份验证一同使用,AMQ Streams 包含服务器端回调,并通过 PLAIN 调用这个 OAuth 2.0

随着 PLAIN 的 AMQ Streams 实施,客户端凭据不会存储在 ZooKeeper 中。相反,客户端凭证在兼容授权服务器后面集中处理,这与使用 OAUTHBEARER 身份验证时类似。

当与 OAuth 2.0 over PLAIN 回调搭配使用时,Kafka 客户端使用以下方法之一向 Kafka 代理进行身份验证:

  • 客户端 ID 和 secret(使用 OAuth 2.0 客户端凭证机制)
  • 长期访问令牌,在配置时手动获得

客户端必须启用才能使用 PLAIN 身份验证,并提供 用户名和密码 。如果密码的前缀为 $accessToken:,后跟访问令牌的值,Kafka 代理会将密码解析为访问令牌。否则,Kafka 代理会将 用户名 解释为客户端 ID,密码 将解释为客户端 secret。

如果将 密码 设置为访问令牌,用户名 必须设置为 Kafka 代理从访问令牌获取的相同主体名称。这个过程取决于您如何使用 userNameClaim、fallbackUserNameClaimfallbackUser namePrefixuserInfoEndpointUri 配置用户名提取。它还取决于您的授权服务器;特别是,如何将客户端 ID 映射到帐户名称。

要使用 PLAIN,您必须在 Kafka 代理的 oauth 监听程序配置中启用它。

在以下示例中,除了默认启用的 OAUTHBEARER 外,还启用了 PLAIN。如果只使用 PLAIN,可以通过将 enableOauthBearer 设置为 false 来禁用 OAUTHB EARER。

  # ...
  authentication:
    type: oauth
    # ...
    enablePlain: true
    tokenEndpointUri: https://OAUTH-SERVER-ADDRESS/auth/realms/external/protocol/openid-connect/token

4.4.2. OAuth 2.0 Kafka 代理配置

OAuth 2.0 的 Kafka 代理配置涉及:

  • 在授权服务器中创建 OAuth 2.0 客户端
  • 在 Kafka 自定义资源中配置 OAuth 2.0 身份验证
注意

对于授权服务器,Kafka 代理和 Kafka 客户端都被视为 OAuth 2.0 客户端。

4.4.2.1. 授权服务器上的 OAuth 2.0 客户端配置

要将 Kafka 代理配置为验证在会话启动过程中收到的令牌,推荐的方法是在授权服务器中创建 OAuth 2.0 客户端 定义(配置为 机密 )并启用以下客户端凭证:

  • kafka 的客户端 ID(例如)
  • 客户端 ID 和机密作为身份验证机制
注意

您只需要在使用授权服务器的非公共内省端点时使用客户端 ID 和机密。在使用公共授权服务器端点时,通常不需要凭据,如进行快速本地 JWT 令牌验证一样。

4.4.2.2. Kafka 集群中的 OAuth 2.0 身份验证配置

要在 Kafka 集群中使用 OAuth 2.0 身份验证,例如,您可以使用身份验证方法 oauth 为 Kafka 集群自定义资源指定 TLS 侦听程序配置:

断言 OAuth 2.0 的身份验证方法类型

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
spec:
  kafka:
    # ...
    listeners:
      - name: tls
        port: 9093
        type: internal
        tls: true
        authentication:
          type: oauth
      #...

您可以配置 普通的tls 和外部 监听程序,但建议您不要使用使用 OAuth 2.0 禁用 TLS 加密 的纯 监听程序 或外部监听程序,因为这会对通过令牌 Sft 进行网络窃取和未经授权的访问造成漏洞。

您可以使用 type: oauth 为安全传输层配置 外部 监听程序,以便与客户端通信。

使用带有外部监听器的 OAuth 2.0

# ...
listeners:
  - name: external
    port: 9094
    type: loadbalancer
    tls: true
    authentication:
      type: oauth
    #...

tls 属性默认为 false,因此必须启用。

当您将身份验证类型定义为 OAuth 2.0 后,您可以根据验证类型添加配置,或者作为 快速本地 JWT 验证 或使用内省端点进行令牌验证

为监听程序配置 OAuth 2.0 的步骤以及描述和示例,请参考 为 Kafka 代理配置 OAuth 2.0 支持。

4.4.2.3. 快速本地 JWT 令牌验证配置

快速本地 JWT 令牌验证在本地检查 JWT 令牌签名。

本地检查可确保令牌:

  • 通过包含访问令牌的 Bearer 声明值(拼写错误)符合类型
  • 有效(未过期)
  • 具有与 validIssuerURI匹配的签发者

在配置监听器时,您可以指定一个 validIssuerURI 属性,以便拒绝授权服务器未发布的任何令牌。

在快速本地 JWT 令牌验证期间,不需要联系授权服务器。您可以通过指定 jwksEndpointUri 属性(OAuth 2.0 授权服务器公开的端点)来激活快速本地 JWT 令牌验证。端点包含用于验证签名 JWT 令牌的公钥,这些令牌由 Kafka 客户端作为凭据发送。

注意

与授权服务器的所有通信都应使用 TLS 加密来执行。

您可以在 AMQ Streams 项目命名空间中将证书信任存储配置为 OpenShift Secret,并使用 a tlsTrustedCertificates 属性指向包含信任存储文件的 OpenShift Secret。

您可能希望配置 userNameClaim 以 从 JWT 令牌正确提取用户名。如果要使用 Kafka ACL 授权,则需要在验证过程中根据用户的用户名进行识别。( JWT 令牌中的 声明通常是唯一的 ID,而不是用户名。)

用于快速本地 JWT 令牌验证的配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
spec:
  kafka:
    #...
    listeners:
      - name: tls
        port: 9093
        type: internal
        tls: true
        authentication:
          type: oauth
          validIssuerUri: <https://<auth-server-address>/auth/realms/tls>
          jwksEndpointUri: <https://<auth-server-address>/auth/realms/tls/protocol/openid-connect/certs>
          userNameClaim: preferred_username
          maxSecondsWithoutReauthentication: 3600
          tlsTrustedCertificates:
          - secretName: oauth-server-cert
            certificate: ca.crt
    #...

4.4.2.4. OAuth 2.0 内省端点配置

使用 OAuth 2.0 内省端点进行令牌验证,将收到的访问令牌视为不透明。Kafka 代理将访问令牌发送到内省端点,该端点使用验证所需的令牌信息进行响应。更重要的是,如果特定访问令牌有效,它将返回最新信息,以及关于令牌何时到期的信息。

要配置基于 OAuth 2.0 内省的验证,您需要指定一个 内省EndpointUri 属性,而不是为快速本地 JWT 令牌验证指定的 jwksEndpointUri 属性。根据授权服务器,您通常必须指定 clientId 和 client Secret,因为内省端点通常受到保护。

内省端点的配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
spec:
  kafka:
    listeners:
      - name: tls
        port: 9093
        type: internal
        tls: true
        authentication:
          type: oauth
          clientId: kafka-broker
          clientSecret:
            secretName: my-cluster-oauth
            key: clientSecret
          validIssuerUri: <https://<auth-server-address>/auth/realms/tls>
          introspectionEndpointUri: <https://<auth-server-address>/auth/realms/tls/protocol/openid-connect/token/introspect>
          userNameClaim: preferred_username
          maxSecondsWithoutReauthentication: 3600
          tlsTrustedCertificates:
          - secretName: oauth-server-cert
            certificate: ca.crt

4.4.3. Kafka 代理的会话重新身份验证

您可以配置 oauth 侦听程序,在 Kafka 客户端和 Kafka 代理间的 OAuth 2.0 会话中使用 Kafka 会话 重新身份验证。这种机制强制客户端与代理之间经过身份验证的会话在指定时间段后到期。会话过期时,客户端将通过重复使用现有连接而不是丢弃它来立即启动新会话。

会话重新身份验证默认为禁用。要启用它,您可以在 oauth 监听程序配置中为 maxSecondsWithoutReauthentication 设置一个时间值。同一属性用于为 OAUTHBEARER 和 PLAIN 身份验证配置会话重新身份验证。有关配置示例,请参阅 第 4.4.6.2 节 “配置 Kafka 代理的 OAuth 2.0 支持”

客户端使用的 Kafka 客户端库必须支持会话重新身份验证。

会话重新身份验证可用于 快速本地 JWT内省端点 令牌验证。

客户端重新身份验证

当代理经过身份验证的会话过期时,客户端必须通过向代理发送新的有效访问令牌来重新验证现有会话,而不丢弃连接。

如果令牌验证成功,则利用现有连接启动新的客户端会话。如果客户端无法重新验证,代理会在进一步尝试发送或接收消息时关闭连接。如果在代理中启用了重新身份验证机制,使用 Kafka 客户端库 2.2 或更高版本的 Java 客户端会自动重新验证。

会话重新身份验证也适用于刷新令牌(若使用)。会话过期时,客户端使用刷新令牌刷新访问令牌。然后,客户端使用新的访问令牌重新验证到现有会话。

OAUTHBEARER 和 PLAIN 的会话过期

当配置会话重新身份验证时,会话过期适用于 OAUTHBEARER 和 PLAIN 身份验证的不同。

对于 OAUTHBEARER 和 PLAIN,请使用客户端 ID 和 secret 方法:

  • 代理通过身份验证的会话将在配置的 maxSecondsWithoutReauthentication 时过期。
  • 如果访问令牌在配置的时间之前过期,会话将更早过期。

对于 PLAIN 使用长期访问令牌方法:

  • 代理通过身份验证的会话将在配置的 maxSecondsWithoutReauthentication 时过期。
  • 如果访问令牌在配置的时间之前过期,则重新身份验证会失败。虽然尝试重新身份验证会话,但 PLAIN 没有刷新令牌的机制。

如果没有 配置 maxSecondsWithoutReauthentication,OAUTHBEARER 和 PLAIN 客户端可以无限期地保持连接到代理,而无需重新身份验证。经过身份验证的会话不以访问令牌到期结尾。但是,在配置授权时需要考虑这一点,例如通过使用 keycloak 授权或安装自定义授权器。

4.4.4. OAuth 2.0 Kafka 客户端配置

使用以下方法配置了 Kafka 客户端:

  • 从授权服务器(客户端 ID 和 Secret)获取有效访问令牌所需的凭证
  • 使用授权服务器提供的工具获取有效的长期访问令牌或刷新令牌

发送到 Kafka 代理的唯一信息是访问令牌。用于与授权服务器进行身份验证以获取访问令牌的凭证永远不会发送到代理。

当客户端获取访问令牌时,不需要进一步与授权服务器通信。

最简单的机制是使用客户端 ID 和机密进行身份验证。使用长期访问令牌或长期提供的刷新令牌增加了复杂性,因为对授权服务器工具存在额外的依赖性。

注意

如果您使用长期访问令牌,您可能需要在授权服务器中配置客户端,以增加令牌的最长生命周期。

如果 Kafka 客户端没有直接配置访问令牌,客户端会联系授权服务器在 Kafka 会话启动时交换访问令牌的凭证。Kafka 客户端交换:

  • 客户端 ID 和机密
  • 客户端 ID、刷新令牌和(可选)Secret

4.4.5. OAuth 2.0 客户端身份验证流

在本节中,我们在 Kafka 会话启动过程中解释和视觉化 Kafka 客户端、Kafka 代理和授权服务器之间的通信流。流程取决于客户端和服务器配置。

当 Kafka 客户端将访问令牌作为凭证发送到 Kafka 代理时,需要验证令牌。

根据所使用的授权服务器以及可用的配置选项,您可能更愿意使用:

  • 基于 JWT 签名检查和本地令牌内省的快速本地令牌验证,而不联系授权服务器
  • 授权服务器提供的 OAuth 2.0 内省端点

使用快速本地令牌验证需要授权服务器提供 JWKS 端点以及用于验证令牌签名的公共证书。

另一种选择是在授权服务器上使用 OAuth 2.0 内省端点。每次建立新的 Kafka 代理连接时,代理会将从客户端收到的访问令牌传递给授权服务器,并检查响应以确认令牌是否有效。

还可以为以下项配置 Kafka 客户端凭证:

  • 使用之前生成的长期访问令牌直接进行本地访问
  • 与授权服务器联系以获取要发布的新访问令牌
注意

授权服务器可能只允许使用不透明访问令牌,这意味着无法进行本地令牌验证。

4.4.5.1. 客户端身份验证流示例

您可以在 Kafka 会话验证过程中看到用于不同配置的 Kafka 客户端和代理的通信流。

使用客户端 ID 和 secret 的客户端,代理将验证委派给授权服务器

Client using client ID and secret with broker delegating validation to authorization server

  1. Kafka 客户端使用客户端 ID 和机密从授权服务器请求访问令牌,以及可选的刷新令牌。
  2. 授权服务器生成新的访问令牌。
  3. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证来传递访问令牌。
  4. Kafka 代理使用自己的客户端 ID 和 secret,在授权服务器上调用令牌内省端点来验证访问令牌。
  5. 如果令牌有效,则创建 Kafka 客户端会话。

使用客户端 ID 和 secret 的客户端,代理执行快速本地令牌验证

Client using client ID and secret with broker performing fast local token validation

  1. Kafka 客户端从令牌端点通过授权服务器进行身份验证,使用客户端 ID 和 secret 以及可选的刷新令牌进行身份验证。
  2. 授权服务器生成新的访问令牌。
  3. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证来传递访问令牌。
  4. Kafka 代理使用 JWT 令牌签名检查和本地令牌内省在本地验证访问令牌。

使用长期访问令牌的客户端,并将代理委派验证到授权服务器

Client using long-lived access token with broker delegating validation to authorization server

  1. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证,以传递长期访问令牌。
  2. Kafka 代理使用自己的客户端 ID 和 secret,在授权服务器上调用令牌内省端点来验证访问令牌。
  3. 如果令牌有效,则创建 Kafka 客户端会话。

使用长期访问令牌的客户端,代理执行快速本地验证

Client using long-lived access token with broker performing fast local validation

  1. Kafka 客户端使用 SASL OAUTHBEARER 机制与 Kafka 代理进行身份验证,以传递长期访问令牌。
  2. Kafka 代理使用 JWT 令牌签名检查和本地令牌内省在本地验证访问令牌。
警告

快速本地 JWT 令牌签名验证仅适用于短期的令牌,因为如果令牌被撤销,则不会与授权服务器检查。令牌到期将写入令牌中,但取消可以在任何时间发生,因此在不联系授权服务器的情况下无法考虑该令牌。任何发布的令牌都将被视为有效,直到该令牌过期为止。

4.4.6. 配置 OAuth 2.0 身份验证

OAuth 2.0 用于 Kafka 客户端和 AMQ Streams 组件之间的交互。

要将 OAuth 2.0 用于 AMQ Streams,您必须:

4.4.6.1. 将红帽单点登录配置为 OAuth 2.0 授权服务器

这个步骤描述了如何将 Red Hat Single Sign-On 部署为授权服务器,并将其配置为与 AMQ Streams 集成。

授权服务器为身份验证和授权以及用户、客户端和权限的管理提供中央点。红帽单点登录有一个域概念,其中 代表一组单独的用户、客户端、权限和其他配置。您可以使用默认的 master 域,或者创建一个新域。每个域公开自己的 OAuth 2.0 端点,这意味着应用客户端和应用服务器都需要使用相同的域。

要将 OAuth 2.0 与 AMQ Streams 搭配使用,您可以使用 Red Hat Single Sign-On 部署来创建和管理身份验证域。

注意

如果您已经部署了红帽单点登录,您可以跳过部署步骤并使用当前的部署。

开始前

您需要熟悉使用红帽单点登录。

有关部署和管理说明,请参阅:

先决条件

  • AMQ Streams 和 Kafka 正在运行

对于 Red Hat Single Sign-On 部署:

流程

  1. 将红帽单点登录部署到您的 OpenShift 集群。

    在 OpenShift Web 控制台中检查部署的进度。

  2. 登录红帽单点登录管理控制台,为 AMQ Streams 创建 OAuth 2.0 策略。

    部署 Red Hat Single Sign-On 时会提供登录详情。

  3. 创建和启用域。

    您可以使用现有的 master 域。

  4. 如果需要,调整域的会话和令牌超时。
  5. 创建名为 kafka-broker 的客户端。
  6. Settings 选项卡中设置:

    • 访问类型机密
    • 标准流启用OFF,以禁用此客户端的 Web 登录
    • 支持服务于 ON,允许此客户端使用自己的名称进行身份验证
  7. 单击 Save,然后再继续。
  8. Credentials 选项卡中,记下 AMQ Streams Kafka 集群配置中使用的 secret。
  9. 为要连接到 Kafka 代理的任何应用程序客户端重复客户端创建步骤。

    为每个新客户端创建定义。

    在配置中,您将使用名称作为客户端 ID。

接下来要做什么

部署和配置授权服务器后,将 Kafka 代理配置为使用 OAuth 2.0

4.4.6.2. 配置 Kafka 代理的 OAuth 2.0 支持

这个步骤描述了如何配置 Kafka 代理,以便代理监听程序被启用为使用授权服务器使用 OAuth 2.0 身份验证。

我们建议通过配置 TLS 侦听器在加密接口上使用 OAuth 2.0。不建议纯监听器。

如果授权服务器使用由可信 CA 签名的证书并匹配 OAuth 2.0 服务器主机名,则 TLS 连接可以使用默认设置。否则,您可能需要使用探测器证书或禁用证书主机名验证来配置信任存储。

在配置 Kafka 代理时,在新连接的 Kafka 客户端的 OAuth 2.0 验证过程中,您有两个用于验证访问令牌的机制:

开始前

有关为 Kafka 代理监听程序配置 OAuth 2.0 身份验证的更多信息,请参阅:

先决条件

  • AMQ Streams 和 Kafka 正在运行
  • 部署了 OAuth 2.0 授权服务器

流程

  1. 在编辑器中更新Kafka 资源的 Kafka 代理配置( Kafka.spec.kafka)。

    oc edit kafka my-cluster
  2. 配置 Kafka 代理 监听程序 配置。

    每种侦听器的配置不一定是独立的,因为它们是独立的。

    此处的示例显示了为外部侦听器配置的配置选项。

    示例 1:配置快速本地 JWT 令牌验证

    #...
    - name: external
      port: 9094
      type: loadbalancer
      tls: true
      authentication:
        type: oauth 1
        validIssuerUri: <https://<auth-server-address>/auth/realms/external> 2
        jwksEndpointUri: <https://<auth-server-address>/auth/realms/external/protocol/openid-connect/certs> 3
        userNameClaim: preferred_username 4
        maxSecondsWithoutReauthentication: 3600 5
        tlsTrustedCertificates: 6
        - secretName: oauth-server-cert
          certificate: ca.crt
        disableTlsHostnameVerification: true 7
        jwksExpirySeconds: 360 8
        jwksRefreshSeconds: 300 9
        jwksMinRefreshPauseSeconds: 1 10

    1
    侦听器类型设置为 oauth
    2
    用于身份验证的令牌签发者的 URI。
    3
    用于本地 JWT 验证的 JWKS 证书端点 URI。
    4
    在令牌中包含实际用户名的令牌声明(或密钥)。用户名 是用于 标识用户的主体。userNameClaim 值将取决于身份验证流和使用的授权服务器。
    5
    (可选)激活 Kafka 重新身份验证机制,强制会话过期的时间与访问令牌相同。如果指定的值小于访问令牌过期的时间,客户端必须在实际令牌到期之前重新进行身份验证。默认情况下,会话不会在访问令牌过期时过期,客户端也不会尝试重新身份验证。
    6
    (可选)用于 TLS 连接到授权服务器的受信任证书。
    7
    (可选)禁用 TLS 主机名验证。默认为 false
    8
    JWKS 证书在过期前被视为有效的时间。默认值为 360 秒。如果您指定了更长的时间,请考虑允许访问撤销的证书的风险。
    9
    JWKS 证书刷新间隔的时间段。间隔必须至少比到期间隔短 60 秒。默认值为 300 秒。
    10
    连续尝试刷新 JWKS 公钥之间的最小暂停(以秒为单位)。当遇到未知签名密钥时,将在常规定期计划外调度 JWKS 密钥刷新,并且自上次刷新尝试后至少使用指定的暂停。刷新键遵循 exponential backoff 规则,不成功刷新会一直增加暂停,直到它到达 jwksRefreshSeconds。默认值为 1。

    示例 2:使用内省端点配置令牌验证

    - name: external
      port: 9094
      type: loadbalancer
      tls: true
      authentication:
        type: oauth
        validIssuerUri: <https://<auth-server-address>/auth/realms/external>
        introspectionEndpointUri: <https://<auth-server-address>/auth/realms/external/protocol/openid-connect/token/introspect> 1
        clientId: kafka-broker 2
        clientSecret: 3
          secretName: my-cluster-oauth
          key: clientSecret
        userNameClaim: preferred_username 4
        maxSecondsWithoutReauthentication: 3600 5

    1
    令牌内省端点的 URI。
    2
    用于标识客户端的客户端 ID。
    3
    客户端机密和客户端 ID 用于身份验证。
    4
    在令牌中包含实际用户名的令牌声明(或密钥)。用户名 是用于 标识用户的主体。userNameClaim 值将取决于所使用的授权服务器。
    5
    (可选)激活 Kafka 重新身份验证机制,强制会话过期的时间与访问令牌相同。如果指定的值小于访问令牌过期的时间,客户端必须在实际令牌到期之前重新进行身份验证。默认情况下,会话不会在访问令牌过期时过期,客户端也不会尝试重新身份验证。

    根据您应用 OAuth 2.0 身份验证的方式,以及授权服务器的类型,您可以使用额外的(可选)配置设置:

      # ...
      authentication:
        type: oauth
        # ...
        checkIssuer: false 1
        checkAudience: true 2
        fallbackUserNameClaim: client_id 3
        fallbackUserNamePrefix: client-account- 4
        validTokenType: bearer 5
        userInfoEndpointUri: https://OAUTH-SERVER-ADDRESS/auth/realms/external/protocol/openid-connect/userinfo 6
        enableOauthBearer: false 7
        enablePlain: true 8
        tokenEndpointUri: https://OAUTH-SERVER-ADDRESS/auth/realms/external/protocol/openid-connect/token 9
        customClaimCheck: "@.custom == 'custom-value'" 10
        clientAudience: AUDIENCE 11
        clientScope: SCOPE 12
    1
    如果您的授权服务器不提供 iss 声明,则无法执行签发者检查。在这种情况下,把 checkIssuer 设置为 false,且不指定 validIssuerUri。默认值为 true
    2
    如果您的授权服务器提供 ud (严重)申索,并且您希望强制进行使用者检查,请将 checkAudience 设置为 true。使用者检查可识别令牌的预期接收者。因此,Kafka 代理将拒绝在其 aud 声明中没有其 clientId 的令牌。默认为 false
    3
    授权服务器不能提供单个属性来标识常规用户和客户端。当客户端在其自己的名称中进行身份验证时,服务器可能会提供 客户端 ID。当用户使用用户名和密码进行身份验证时,为了获取刷新令牌或访问令牌,服务器可能会提供除客户端 ID 之外 的用户名 属性。使用此回退选项指定用户名声明(attribute),以便在主用户 ID 属性不可用时使用。
    4
    在适用 fallbackUserNameClaim 的情况下,可能还需要防止用户名声明的值与回退用户名声明的值冲突。请考虑存在名为 producer 的客户端,但也存在名为 producer 的常规用户。为了区分这两者,您可以使用此属性向客户端的用户 ID 添加前缀。
    5
    (仅在使用 内省EndpointUri时)取决于您使用的授权服务器,内省端点可能会也可能不会返回 令牌类型 属性,或者它可能包含不同的值。您可以指定内省端点必须包含的有效令牌类型值。
    6
    (仅在使用 内省EndpointUri时)可以配置或实施授权服务器,以免在内省端点响应中提供任何可识别的信息。若要获取用户 ID,您可以将 userinfo 端点的 URI 配置为回退。userNameClaimfallbackUserNameClaimfallbackUserNamePrefix 设置应用于 userinfo 端点的响应。
    7
    将其设置为 false' 以禁用监听器上的 OAUTHBEARER 机制。必须至少启用 PLAIN 或 OAUTHBEARER 中的一个。默认为 'true
    8
    设置为 true,以便在监听器上启用 PLAIN 身份验证,这是所有平台上所有客户端支持的。Kafka 客户端必须启用 PLAIN 机制并设置 用户名和密码 。PLAIN 可用于使用 OAuth 访问令牌或 OAuth 客户端Idsecret (客户端凭据)进行身份验证。该行为还由是否指定 tokenEndpointUri 来控制。默认为 false。如果指定了 tokenEndpointUri,并且客户端将 密码 设置为以字符串 $accessToken: 开头,服务器会将密码解析为访问令牌,用户名 为帐户用户名。否则,用户名 将解释为 clientId密码 解析为客户端 secret,代理用于在客户端名称中获取访问令牌。如果没有指定 tokenEndpointUri密码 始终解析为访问令牌,并且 用户名 始终被解释为帐户用户名,它必须与从令牌提取的主体 ID 匹配。这称为"no-client-credentials"模式,因为客户端必须始终自行获取访问令牌,并且无法使用 clientIdsecret
    9
    PLAIN 机制的其他配置,允许客户端进行身份验证,方法是传递 clientIdsecret 作为 用户名和密码 ,如上点所述。如果没有指定,客户端只能通过传递访问令牌作为 密码 参数通过 PLAIN 进行身份验证。
    10
    可以通过将此规则设置为 JsonPath 过滤器查询,在验证期间对 JWT 访问令牌应用其他自定义规则。如果访问令牌不包含必要的数据,则会被拒绝。使用 内省EndpointUri 时,自定义检查应用到内省端点响应 JSON。
    11
    (可选) 传递到 令牌端点的使用者参数。在获取用于代理身份验证的访问令牌时,会使用 使用者。它也用于 OAuth 2.0 的客户端名称,通过 PLAIN 客户端身份验证使用 clientIdsecret。这只会影响获取令牌的能力,以及令牌的内容,具体取决于授权服务器。它不会影响侦听器的令牌验证规则。
    12
    (可选)传递到令牌端点 的范围 参数。在获取用于代理身份验证的访问令牌时,会使用 范围。它也用于 OAuth 2.0 的客户端名称,通过 PLAIN 客户端身份验证使用 clientIdsecret。这只会影响获取令牌的能力,以及令牌的内容,具体取决于授权服务器。它不会影响侦听器的令牌验证规则。
  3. 保存并退出编辑器,然后等待滚动更新完成。
  4. 检查日志中的更新,或者查看 pod 状态转换:

    oc logs -f ${POD_NAME} -c ${CONTAINER_NAME}
    oc get pod -w

    滚动更新将代理配置为使用 OAuth 2.0 身份验证。

4.4.6.3. 将 Kafka Java 客户端配置为使用 OAuth 2.0

这个步骤描述了如何配置 Kafka 制作者和使用者 API,以使用 OAuth 2.0 与 Kafka 代理交互。

将客户端回调插件添加到 pom.xml 文件,并配置系统属性。

先决条件

  • AMQ Streams 和 Kafka 正在运行
  • 为对 Kafka 代理的 OAuth 访问部署并配置了 OAuth 授权服务器
  • 为 OAuth 2.0 配置 Kafka 代理

流程

  1. 将带有 OAuth 2.0 支持的客户端库添加到 Kafka 客户端的 pom.xml 文件中:

    <dependency>
     <groupId>io.strimzi</groupId>
     <artifactId>kafka-oauth-client</artifactId>
     <version>{oauth-version}</version>
    </dependency>
  2. 为回调配置系统属性:

    例如:

    System.setProperty(ClientConfig.OAUTH_TOKEN_ENDPOINT_URI, “https://<auth-server-address>/auth/realms/master/protocol/openid-connect/token”); 1
    System.setProperty(ClientConfig.OAUTH_CLIENT_ID, "<client-name>"); 2
    System.setProperty(ClientConfig.OAUTH_CLIENT_SECRET, "<client-secret>"); 3
    1
    授权服务器令牌端点的 URI。
    2
    客户端 ID,这是在授权服务器中创建 客户端 时使用的名称。
    3
    在授权服务器中创建 客户端 时创建的客户端机密。
  3. 在 Kafka 客户端配置中的 TLS 加密连接中启用 SASL OAUTHBEARER 机制:

    例如:

    props.put("sasl.jaas.config", "org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;");
    props.put("security.protocol", "SASL_SSL"); 1
    props.put("sasl.mechanism", "OAUTHBEARER");
    props.put("sasl.login.callback.handler.class", "io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler");
    1
    在这里,我们使用 SASL_SSL 通过 TLS 连接使用。对未加密的连接使用 SASL_PLAINTEXT
  4. 验证 Kafka 客户端可以访问 Kafka 代理。
4.4.6.4. 为 Kafka 组件配置 OAuth 2.0

这个步骤描述了如何将 Kafka 组件配置为使用授权服务器的 OAuth 2.0 身份验证。

您可以为以下对象配置身份验证:

  • Kafka Connect
  • Kafka MirrorMaker
  • Kafka Bridge

在这种情况下,Kafka 组件和授权服务器会在同一集群中运行。

开始前

有关为 Kafka 组件配置 OAuth 2.0 身份验证的更多信息,请参阅:

先决条件

  • AMQ Streams 和 Kafka 正在运行
  • 为对 Kafka 代理的 OAuth 访问部署并配置了 OAuth 授权服务器
  • 为 OAuth 2.0 配置 Kafka 代理

流程

  1. 创建客户端机密,并将它作为环境变量挂载到组件上。

    例如,此处我们为 Kafka Bridge 创建客户端 Secret

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Secret
    metadata:
     name: my-bridge-oauth
    type: Opaque
    data:
     clientSecret: MGQ1OTRmMzYtZTllZS00MDY2LWI5OGEtMTM5MzM2NjdlZjQw 1
    1
    clientSecret 键必须采用 base64 格式。
  2. 为 Kafka 组件创建或编辑资源,以便为身份验证属性配置 OAuth 2.0 身份验证。

    对于 OAuth 2.0 身份验证,您可以使用:

    • 客户端 ID 和 secret
    • 客户端 ID 和刷新令牌
    • 访问令牌
    • TLS

    KafkaClientAuthenticationOAuth 模式参考提供了每个模式的示例

    例如,此处的 OAuth 2.0 使用客户端 ID 和 secret 分配给 Kafka Bridge 客户端,以及 TLS:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaBridge
    metadata:
      name: my-bridge
    spec:
      # ...
      authentication:
        type: oauth 1
        tokenEndpointUri: https://<auth-server-address>/auth/realms/master/protocol/openid-connect/token 2
        clientId: kafka-bridge
        clientSecret:
          secretName: my-bridge-oauth
          key: clientSecret
        tlsTrustedCertificates: 3
        - secretName: oauth-server-cert
          certificate: tls.crt
    1
    验证类型设置为 oauth
    2
    用于身份验证的令牌端点的 URI。
    3
    TLS 到授权服务器的可信证书。

    根据您应用 OAuth 2.0 身份验证的方式以及授权服务器的类型,您可以使用额外的配置选项:

    # ...
    spec:
      # ...
      authentication:
        # ...
        disableTlsHostnameVerification: true 1
        checkAccessTokenType: false 2
        accessTokenIsJwt: false 3
        scope: any 4
        audience: kafka 5
    1
    (可选)禁用 TLS 主机名验证。默认为 false
    2
    如果授权服务器没有在 JWT 令牌中返回 拼写错误 (类型)声明,您可以应用 checkAccessTokenType: false 来跳过令牌类型检查。默认值为 true
    3
    如果您使用不透明令牌,您可以应用 accessTokenIsJwt: false,以便访问令牌不被视为 JWT 令牌。
    4
    (可选)从令牌端点请求令牌 的范围。授权服务器可能需要客户端指定范围。本例中为 任意.
    5
    (可选)从令牌端点请求令牌的 受众。授权服务器可能需要客户端指定受众。本例中为 kafka
  3. 将更改应用到 Kafka 资源的部署。

    oc apply -f your-file
  4. 检查日志中的更新,或者查看 pod 状态转换:

    oc logs -f ${POD_NAME} -c ${CONTAINER_NAME}
    oc get pod -w

    滚动更新配置组件,以使用 OAuth 2.0 身份验证与 Kafka 代理交互。

4.5. 使用基于 OAuth 2.0 令牌的授权

如果您在 Red Hat Single Sign-On 中使用 OAuth 2.0 进行基于令牌的身份验证,您还可以使用 Red Hat Single Sign-On 配置授权规则来限制客户端对 Kafka 代理的访问。身份验证建立用户的身份。授权决定该用户的访问级别。

AMQ Streams 支持通过 Red Hat Single Sign-On Authorization Services 使用基于 OAuth 2.0 令牌的授权,它允许您集中管理安全策略和权限。

Red Hat Single Sign-On 中定义的安全策略和权限用于授予对 Kafka 代理上资源的访问权限。用户和客户端与允许对 Kafka 代理执行特定操作的策略进行匹配。

默认情况下,Kafka 允许所有用户对代理进行完全访问,并提供 AclAuthorizer 插件以根据访问控制列表(ACL)配置授权。

zookeeper 存储允许或拒绝基于 用户名 访问资源的 ACL 规则。但是,使用红帽单点登录的 OAuth 2.0 基于令牌的授权为您要对 Kafka 代理实施访问控制提供了极大的灵活性。另外,您可以将 Kafka 代理配置为使用 OAuth 2.0 授权和 ACL。

4.5.1. OAuth 2.0 授权机制

AMQ Streams 中的 OAuth 2.0 授权使用 Red Hat Single Sign-On 服务器授权服务 REST 端点通过对特定用户应用定义的安全策略,并为该用户提供不同资源获得的权限列表,从而通过红帽单点登录来扩展基于令牌的身份验证。策略使用角色和组来匹配用户的权限。OAuth 2.0 授权根据红帽单点登录授权服务中用户收到的授权列表,在本地强制实施权限。

4.5.1.1. Kafka 代理自定义授权器

一个 Red Hat Single Sign-On 授权程序 (KeycloakRBACAuthorizer)由 AMQ Streams 提供。为了能够将 Red Hat Single Sign-On REST 端点用于 Red Hat Single Sign-On 提供的授权服务,您可以在 Kafka 代理上配置自定义授权程序。

授权者根据需要从授权服务器获取授予权限的列表,并在 Kafka Broker 上强制本地实施授权,从而对每个客户端请求做出快速的授权决策。

4.5.2. 配置 OAuth 2.0 授权支持

这个步骤描述了如何使用 Red Hat Single Sign-On Authorization Services 将 Kafka 代理配置为使用 OAuth 2.0 授权服务。

开始前

考虑您需要或希望限制某些用户的访问权限。您可以使用红帽单点登录 角色客户端 和用户 组合在红帽单点登录中配置访问权限。

通常,组用于根据组织部门或地理位置匹配用户。和 角色用于根据用户的功能匹配用户。

通过红帽单点登录,您可以将用户和组存储在 LDAP 中,而客户端和角色则无法以这种方式存储。存储和用户数据访问可能是您选择配置授权策略的一个因素。

注意

无论 Kafka 代理中实施的授权如何,超级用户 始终都对 Kafka 代理具有未经约束的访问权限。

先决条件

  • AMQ Streams 必须配置为使用 OAuth 2.0 和 Red Hat Single Sign-On 基于 令牌的身份验证。设置授权时,您可以使用相同的 Red Hat Single Sign-On 服务器端点。
  • OAuth 2.0 身份验证必须使用 maxSecondsWithoutReauthentication 选项进行配置,才能启用重新身份验证。

流程

  1. 访问 Red Hat Single Sign-On Admin 控制台,或使用 Red Hat Single Sign-On Admin CLI 为您在设置 OAuth 2.0 身份验证时创建的 Kafka 代理客户端启用授权服务。
  2. 使用授权服务为客户端定义资源、授权范围、策略和权限。
  3. 通过为用户和组分配角色和组,将权限绑定至用户和组。
  4. 通过在 编辑器 中更新 Kafka 代理配置(Kafka.spec.kafka),将 Kafka代理配置为使用 Red Hat Single Sign-On 授权。

    oc edit kafka my-cluster
  5. 将 Kafka 代理 kafka 配置配置为使用 keycloak 授权,并可以访问授权服务器和授权服务。

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        # ...
        authorization:
          type: keycloak 1
          tokenEndpointUri: <https://<auth-server-address>/auth/realms/external/protocol/openid-connect/token> 2
          clientId: kafka 3
          delegateToKafkaAcls: false 4
          disableTlsHostnameVerification: false 5
          superUsers: 6
          - CN=fred
          - sam
          - CN=edward
          tlsTrustedCertificates: 7
          - secretName: oauth-server-cert
            certificate: ca.crt
          grantsRefreshPeriodSeconds: 60 8
          grantsRefreshPoolSize: 5 9
        #...
    1
    类型 keycloak 启用红帽单点登录授权。
    2
    红帽单点登录令牌端点的 URI。对于生产环境,始终使用 HTTPs。当您配置基于令牌的 oauth 身份验证时,您可以将 jwksEndpointUri 指定为本地 JWT 验证的 URI。tokenEndpointUri URI 的主机名必须相同。
    3
    启用了授权服务的 Red Hat Single Sign-On 中的 OAuth 2.0 客户端定义的客户端 ID。通常, kafka 用作 ID。
    4
    (可选)如果 Red Hat Single Sign-On Authorization Services 策略拒绝访问,则会向 Kafka AclAuthorizer 委派授权。默认为 false
    5
    (可选)禁用 TLS 主机名验证。默认为 false
    6
    (可选)指定的 超级用户.
    7
    (可选)用于 TLS 连接到授权服务器的受信任证书。
    8
    (可选)两个连续的时间允许刷新运行。这是活跃会话的最大时间,用于检测 Red Hat Single Sign-On 上用户的任何权限更改。默认值为 60。
    9
    (可选)用于(并行)活动会话授权的线程数量。默认值为 5。
  6. 保存并退出编辑器,然后等待滚动更新完成。
  7. 检查日志中的更新,或者查看 pod 状态转换:

    oc logs -f ${POD_NAME} -c kafka
    oc get pod -w

    滚动更新将代理配置为使用 OAuth 2.0 授权。

  8. 以具有特定角色的客户端或用户访问 Kafka 代理,确保他们具有必要的访问权限,或者没有他们应该拥有的访问权限,来验证配置的权限。

4.5.3. 在 Red Hat Single Sign-On Authorization Services 中管理策略和权限

本节论述了 Red Hat Single Sign-On Authorization Services 和 Kafka 使用的授权模型,并定义了每个模型中的重要概念。

要授予访问 Kafka 的权限,您可以通过在 Red Hat Single Sign-On Sign-On 登陆到 Red Hat Single Sign-On 中创建 OAuth 客户端规格 将 Red Hat Single Sign-On Authorization Services 对象映射到 Kafka 资源。使用 Red Hat Single Sign-On Authorization Services 规则为用户帐户或服务帐户授予 Kafka 权限。

显示了 常见 Kafka 操作所需的不同用户权限,如创建和列出主题。

4.5.3.1. Kafka 和红帽单点登录授权模型概述

Kafka 和红帽单点登录授权服务使用不同的授权模型。

Kafka 授权模型

Kafka 的授权模型使用 资源类型。当 Kafka 客户端对代理执行操作时,代理使用配置的 KeycloakRBACAuthorizer 检查客户端的权限,具体取决于操作和资源类型。

Kafka 使用五个资源类型来控制访问: Topic、group ClustertransactionalIdDelegationToken。每一资源类型具有一组可用权限。

主题

  • create
  • 删除
  • describe
  • DescribeConfigs
  • 更改
  • AlterConfigs

  • describe
  • 删除

Cluster

  • create
  • describe
  • 更改
  • DescribeConfigs
  • AlterConfigs
  • IdempotentWrite
  • ClusterAction

TransactionalId

  • describe

DelegationToken

  • describe
Red Hat Single Sign-On Authorization Services 模型

红帽单点登录授权服务模型具有四个概念,用于定义和授予权限: 资源授权范围、 策略 和权限

资源
资源是一组资源定义,用于将资源与允许的操作匹配。例如,资源可以是单独的主题,或者名称以同一前缀开头的所有主题。资源定义与一组可用的授权范围相关联,后者代表一组资源上可用的所有操作。通常,只有一部分操作实际被允许。
授权范围
授权范围是针对特定资源定义的一组所有可用操作。当您定义新资源时,您可以添加所有范围集中的范围。
策略(policy)

策略是使用条件与帐户列表匹配的授权规则。策略可以匹配:

  • 基于 客户端 ID 或角色的服务帐户
  • 基于用户名、组或角色的用户帐户
权限
权限将特定资源定义的一组授权范围授予一组用户。

其它资源

4.5.3.2. 将 Red Hat Single Sign-On Authorization Services 映射到 Kafka 授权模型

Kafka 授权模型用作定义控制对 Kafka 访问的红帽单点登录角色和资源的基础。

要为用户帐户或服务帐户授予 Kafka 权限,请首先为 Kafka 代理在 Red Hat Single Sign-On 中创建 OAuth 客户端规格。然后,在客户端上指定红帽单点登录授权服务规则。通常,代表代理的 OAuth 客户端的客户端 ID 是 kafka (AMQ Streams 提供 的示例文件 使用 kafka 作为 OAuth 客户端 ID)。

注意

如果您有多个 Kafka 集群,您可以在所有这些集群中使用单个 OAuth 客户端(kafka)。这为您提供了一个统一空间,用于定义和管理授权规则。但是,您也可以使用不同的 OAuth 客户端 ID(如 my-cluster-kafkacluster-dev-kafka),并为每个客户端配置中为每个集群定义授权规则。

kafka 客户端定义必须在红帽单点管理控制台中启用 Authorization Enabled 选项。

所有权限都存在于 kafka 客户端范围内。如果您为不同的 Kafka 集群配置了不同的 OAuth 客户端 ID,它们各自需要一组独立的权限,即使它们属于同一红帽单点登录域。

当 Kafka 客户端使用 OAUTHBEARER 身份验证时,Red Hat Single Sign-On 授权器(KeycloakRBACAuthorizer)使用当前会话的访问令牌来检索 Red Hat Single Sign-On 服务器中的授权列表。若要检索授权,授权者将评估红帽单点登录授权服务策略和权限。

Kafka 权限的授权范围

初始红帽单点登录配置通常涉及上传授权范围,以创建在每个 Kafka 资源类型上执行的所有可能操作的列表。此步骤仅执行一次,然后再定义任何权限。您可以手动添加授权范围,而不是上传它们。

授权范围必须包含所有可能的 Kafka 权限,而不考虑资源类型:

  • create
  • 删除
  • describe
  • 更改
  • DescribeConfig
  • AlterConfig
  • ClusterAction
  • IdempotentWrite
注意

如果您确定不需要权限(如 IdempotentWrite),您可以从授权范围列表中省略它。但是,该权限将无法在 Kafka 资源上作为目标。

权限检查的资源模式

在执行权限检查时,资源模式用于与目标资源进行模式匹配。常规模式格式为 RESOURCE-TYPE:PATTERN-NAME

资源类型镜像 Kafka 授权模型。模式允许两个匹配选项:

  • 精确匹配(当模式不以 * 结尾
  • 前缀匹配(模式以 * 结尾

资源模式示例

Topic:my-topic
Topic:orders-*
Group:orders-*
Cluster:*

此外,常规模式格式可以加上 kafka-cluster:CLUSTER-NAME 前缀,后面添加一个逗号,其中 CLUSTER-NAME 是指 Kafka 自定义资源中的 metadata.name

具有集群前缀的资源的模式示例

kafka-cluster:my-cluster,Topic:*
kafka-cluster:*,Group:b_*

当缺少 kafka-cluster 前缀时,会假定为 kafka-cluster:*

在定义资源时,您可以将它与与资源相关的可能授权范围列表关联。设置任何对目标资源类型有用的操作。

虽然您可以向任何资源添加任何授权范围,但只有资源类型支持的范围才会被视为访问控制。

应用访问权限的策略

策略用于将权限定向到一个或多个用户帐户或服务帐户。目标可指:

  • 特定用户或服务帐户
  • 域角色或客户端角色
  • 用户组
  • 与客户端 IP 地址匹配的 JavaScript 规则

策略被赋予唯一名称,并可以重复利用以将多个权限作为多个资源的目标。

授予访问权限

使用细粒度权限将策略、资源和授权范围提取到一起,从而授予用户访问权限。

每个权限的名称应明确定义它授予哪些用户的权限。例如,开发团队 B 可以从以 x 开头的主题中读取 内容。

其它资源

4.5.3.3. Kafka 操作所需的权限示例

以下示例演示了在 Kafka 上执行常见操作所需的用户权限。

创建主题

要创建主题,特定主题或 Cluster:kafka-cluster 需要 Create 权限。

bin/kafka-topics.sh --create --topic my-topic \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

列出主题

如果用户对指定主题具有 描述 权限,则会列出该主题。

bin/kafka-topics.sh --list \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

显示主题详细信息

要显示主题的详细信息,主题需要 Description scribe 和 DescribeConfigs 权限。

bin/kafka-topics.sh --describe --topic my-topic \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

生成到一个主题的消息

要生成到某个主题的消息,主题需要Describe Write 权限。

如果尚未创建该主题,并且已启用主题自动创建,则需要有创建主题的权限。

bin/kafka-console-producer.sh  --topic my-topic \
  --broker-list my-cluster-kafka-bootstrap:9092 --producer.config=/tmp/config.properties

使用来自主题的消息

若要使用某个主题的消息,主题需要 描述读取 权限。从主题中消耗的消耗通常取决于将消费者偏移存储在消费者组中,这需要消费者组具有额外的 描述读取 权限。

匹配需要两个 资源。例如:

Topic:my-topic
Group:my-group-*
bin/kafka-console-consumer.sh --topic my-topic --group my-group-1 --from-beginning \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --consumer.config /tmp/config.properties

使用幂等生成器生成到主题的消息

除了生成主题的权限外,集群资源需要有额外的 IdempotentWrite 权限

匹配需要两个 资源。例如:

Topic:my-topic
Cluster:kafka-cluster
bin/kafka-console-producer.sh  --topic my-topic \
  --broker-list my-cluster-kafka-bootstrap:9092 --producer.config=/tmp/config.properties --producer-property enable.idempotence=true --request-required-acks -1

列出消费者组

在列出消费者组时,仅返回用户具有 Describe 权限的 组。或者,如果用户对 Cluster:kafka-cluster 具有 Describe 权限,则返回所有消费者组。

bin/kafka-consumer-groups.sh --list \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

显示消费者组详情

要显示消费者组的详细信息,需要对组具有 描述 权限,以及与该组关联的主题。

bin/kafka-consumer-groups.sh --describe --group my-group-1 \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

更改主题配置

要更改主题的配置,主题必须具有 描述Alter 权限。

bin/kafka-topics.sh --alter --topic my-topic --partitions 2 \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

显示 Kafka 代理配置

要使用 kafka-configs.sh 获取代理的配置,需要在 Cluster:kafka-cluster 上具有 Describe Configs 权限。

bin/kafka-configs.sh --entity-type brokers --entity-name 0 --describe --all \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

更改 Kafka 代理配置

要更改 Kafka 代理的配置,Cluster:kafka-cluster 需要 Describe Configs 和 AlterConfigs 权限。

bin/kafka-configs --entity-type brokers --entity-name 0 --alter --add-config log.cleaner.threads=2 \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

删除主题

要删除某个主题,主题上需要描述和删除 权限

bin/kafka-topics.sh --delete --topic my-topic \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

选择潜在分区

要为主题分区运行领导选择,需要在 Cluster:kafka-cluster 上具有 Alter 权限。

bin/kafka-leader-election.sh --topic my-topic --partition 0 --election-type PREFERRED  /
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --admin.config /tmp/config.properties

重新分配分区

要生成分区重新分配文件,需要对涉及的主题 描述 权限。

bin/kafka-reassign-partitions.sh --topics-to-move-json-file /tmp/topics-to-move.json --broker-list "0,1" --generate \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config /tmp/config.properties > /tmp/partition-reassignment.json

要执行分区重新分配,需要在 Cluster:kafka-cluster 上具有 Describe Alter 权限。此外,描述 涉及的主题的权限是必需的。

bin/kafka-reassign-partitions.sh --reassignment-json-file /tmp/partition-reassignment.json --execute \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config /tmp/config.properties

要在 Cluster:kafka-cluster 以及每个涉及的主题上验证分区重新分配、Describe AlterConfigs 权限是必需的。

bin/kafka-reassign-partitions.sh --reassignment-json-file /tmp/partition-reassignment.json --verify \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config /tmp/config.properties

4.5.4. 试用红帽单点登录授权服务

本例介绍了如何使用带有 keycloak 授权的红帽单点登录授权服务。使用 Red Hat Single Sign-On Authorization Services 对 Kafka 客户端实施访问限制。红帽单点登录授权服务使用授权范围、策略和权限来定义并应用对资源的访问控制。

红帽单点登录授权服务 REST 端点为经过身份验证的用户提供所授予资源权限的列表。授权列表(权限)从红帽单点登录服务器获取,作为 Kafka 客户端建立身份验证会话后的第一个操作。这个列表会在后台刷新,以便检测到对授权的更改。授权会在每个用户会话的 Kafka 代理上进行缓存和强制实施,以提供快速的授权决策。

AMQ Streams 提供了两个示例文件,其中包含用于设置 Red Hat Single Sign-On 的部署工件:

kafka-ephemeral-oauth-single-keycloak-authz.yaml
使用红帽单点登录为基于 OAuth 2.0 令牌的授权配置 Kafka 自定义资源示例。您可以使用自定义资源来部署使用 keycloak 授权和基于令牌的 oauth 身份验证的 Kafka 集群。
kafka-authz-realm.json
配置有示例组、用户、角色和客户端的红帽单点登录域示例。您可以将该域导入到 Red Hat Single Sign-On 实例,以设置精细的权限来访问 Kafka。

如果要通过 Red Hat Single Sign-On 尝试示例,请使用这些文件按照所示的顺序执行本节中概述的任务。

Authentication

当您配置基于令牌的 oauth 身份验证时,您可以将 jwksEndpointUri 指定为本地 JWT 验证的 URI。在配置 keycloak 授权时,您可以将 tokenEndpointUri 指定为 Red Hat Single Sign-On 令牌端点的 URI。两个 URI 的主机名必须相同。

使用组或角色策略定向权限

在红帽单点登录中,启用服务帐户的机密客户端可以使用客户端 ID 和机密以自己的名称向服务器进行身份验证。对于通常使用自有名称的微服务,而非作为特定用户的代理(如网站)而言,这非常方便。服务帐户可以像普通用户一样分配角色。但是,他们不能分配有组。因此,如果要使用服务帐户为微服务设置权限,则无法使用组策略,而是应使用角色策略。相反,如果您只想将某些权限限制为需要使用用户名和密码进行身份验证的普通用户帐户,您可以实现这一点,作为使用组策略而不是角色策略的一个副作用。本例中用于以 ClusterManager 开头的权限。通常使用 CLI 工具以交互方式执行集群管理。在使用生成的访问令牌验证 Kafka 代理前,要求用户登录是合适的。在这种情况下,访问令牌代表特定的用户,而不是客户端应用。

4.5.4.1. 访问红帽单点登录管理控制台

设置红帽单点登录,然后连接到其管理控制台,再添加预配置的域。使用示例 kafka-authz-realm.json 文件导入该域。您可以在管理控制台中检查为域定义的授权规则。规则授予对配置为使用 Red Hat Single Sign-On 域示例的 Kafka 集群上资源的访问权限。

先决条件

  • 正在运行的 OpenShift 集群。
  • AMQ Streams 示例/security/keycloak-authorization/kafka-authz-realm.json 文件包含预配置域。

流程

  1. 使用 Red Hat Single Sign-On Operator 安装 Red Hat Single Sign-On 服务器,如 Red Hat Single Sign-On 文档中的服务器安装和配置 中所述。
  2. 等待红帽单点登录实例运行。
  3. 获取外部主机名,以便能够访问管理控制台。

    NS=sso
    oc get ingress keycloak -n $NS

    在本例中,我们假定红帽单点登录服务器正在 sso 命名空间中运行。

  4. 获取 admin 用户的密码

    oc get -n $NS pod keycloak-0 -o yaml | less

    密码存储为 secret,因此获取 Red Hat Single Sign-On 实例的配置 YAML 文件,以标识 secret 的名称(secretKeyRef.name)。

  5. 使用机密的名称获取明文密码。

    SECRET_NAME=credential-keycloak
    oc get -n $NS secret $SECRET_NAME -o yaml | grep PASSWORD | awk '{print $2}' | base64 -D

    在本例中,我们假设 secret 的名称是 credentials -keycloak

  6. 使用用户名 admin 和您获取的密码登录管理控制台。

    使用 https://HOSTNAME 访问 OpenShift 入口。

    现在,您可以使用管理控制台将示例域上传到红帽单点登录。

  7. 单击 Add Realm 以 导入示例域。
  8. 添加 example /security/keycloak-authorization/kafka-authz-realm.json 文件,然后单击 Create

    现在,在管理控制台中,kafka-authz 作为当前域。

    默认视图显示 Master 域。

  9. 在 Red Hat Single Sign-On Admin Console 中,进入 Clients > kafka > Authorization > Settings,并检查 Decision Strategy 是否已设置为 Affirmative

    一个策略意味着,客户端必须至少满足一个策略才能访问 Kafka 集群。

  10. 在红帽单点管理控制台中,前往 用户角色和 客户端 以查看域配置。

    组用于创建用户组 和设置用户权限。组是分配了名称的用户组。它们用于将用户划分到地理、组织或部门单元中。组可以链接到 LDAP 身份提供程序。您可以通过自定义 LDAP 服务器 admin 用户界面让用户成为组的成员,例如,授予 Kafka 资源的权限。
    用户
    用户 用于创建用户。本例中定义了 alicebobAliceClusterManager 组的成员,bobClusterManager-my-cluster 组的成员。用户可以存储在 LDAP 身份提供商中。
    角色
    角色 将用户或客户端标记为具有特定权限。角色是类似于组的概念。它们通常用于为用户 添加 组织角色,并具有必要的权限。角色不能存储在 LDAP 身份提供商中。如果 LDAP 是必需的,您可以改为使用组,并将红帽单点登录角色添加到组,以便在为用户分配组时也获得相应的角色。
    客户端

    客户端 可以具有特定的配置。在本例中,配置了 kafkakafka-cliteam-a-clientteam-b-client 客户端。

    • kafka 客户端供 Kafka 代理用于执行必要的 OAuth 2.0 通信,以进行访问令牌验证。此客户端还包含授权服务资源定义、策略和授权范围,用于在 Kafka 代理上执行授权。授权配置在 Authorization 选项卡的 kafka 客户端中定义,在 Settings 选项卡中打开 授权启用 时可看到该配置。
    • kafka-cli 客户端是一个公共客户端,在使用用户名和密码进行身份验证时供 Kafka 命令行工具使用,以获取访问令牌或刷新令牌。
    • team-a-clientteam-b-client 客户端是机密客户端,代表对某些 Kafka 主题有部分访问权限的服务。
  11. 在 Red Hat Single Sign-On Admin Console 中,进入 Authorization > Permissions,以查看使用为域定义的资源和策略所授予的权限。

    例如,kafka 客户端有以下权限:

    Dev Team A can write to topics that start with x_ on any cluster
    Dev Team B can read from topics that start with x_ on any cluster
    Dev Team B can update consumer group offsets that start with x_ on any cluster
    ClusterManager of my-cluster Group has full access to cluster config on my-cluster
    ClusterManager of my-cluster Group has full access to consumer groups on my-cluster
    ClusterManager of my-cluster Group has full access to topics on my-cluster
    Dev 团队 A
    Dev 团队 A 域角色可以写入任何群集上以 x_ 开头的主题。这结合了名为 Topic:x_*、Describe Write 范围以及 Dev Team A 策略 的资源。Dev 团队 A 策略 与具有名为 Dev Team A 的域角色的所有用户匹配。
    Dev 团队 B
    Dev 团队 B 域角色可以从任何群集上以 x_ 开头的主题中读取。这结合了 主题:x_*Group:x_* 资源、Describe Read 范围以及 Dev Team B 策略。Dev 团队 B 策略匹配具有名为 Dev Team B 的域角色的所有用户。匹配的用户和客户端能够从主题中读取,并为名称以 x_ 开头的主题和消费者组更新所消耗的偏移量。
4.5.4.2. 使用 Red Hat Single Sign-On 授权部署 Kafka 集群

部署一个 Kafka 集群以连接到 Red Hat Single Sign-On 服务器。使用 kafka-ephemeral-oauth-single-keycloak-authz.yaml 文件将 Kafka 集群部署为 Kafka 自定义资源。这个示例使用 keycloak 授权和 oauth 身份验证部署单节点 Kafka 集群。

先决条件

  • 红帽单点登录授权服务器部署到 OpenShift 集群,并加载了示例域。
  • Cluster Operator 已部署到 OpenShift 集群中。
  • AMQ Streams 示例/security/keycloak-authorization/kafka-ephemeral-oauth-single-keycloak-authz.yaml 自定义资源。

流程

  1. 使用您部署的 Red Hat Single Sign-On 实例的主机名,为 Kafka 代理准备信任存储证书,以便与红帽单点登录服务器通信。

    SSO_HOST=SSO-HOSTNAME
    SSO_HOST_PORT=$SSO_HOST:443
    STOREPASS=storepass
    
    echo "Q" | openssl s_client -showcerts -connect $SSO_HOST_PORT 2>/dev/null | awk ' /BEGIN CERTIFICATE/,/END CERTIFICATE/ { print $0 } ' > /tmp/sso.crt

    证书是必需的,因为 OpenShift ingress 用于进行安全(HTTPS)连接。

  2. 将证书作为机密部署到 OpenShift。

    oc create secret generic oauth-server-cert --from-file=/tmp/sso.crt -n $NS
  3. 将主机名设置为环境变量

    SSO_HOST=SSO-HOSTNAME
  4. 创建并部署示例 Kafka 集群。

    cat examples/security/keycloak-authorization/kafka-ephemeral-oauth-single-keycloak-authz.yaml | sed -E 's#\${SSO_HOST}'"#$SSO_HOST#" | oc create -n $NS -f -
4.5.4.3. 为 CLI Kafka 客户端会话准备 TLS 连接

为交互式 CLI 会话创建新 pod。使用红帽单点登录证书为 TLS 连接设置信任存储。truststore 是连接到 Red Hat Single Sign-On 和 Kafka 代理。

先决条件

  • 红帽单点登录授权服务器部署到 OpenShift 集群,并加载了示例域。

    在 Red Hat Single Sign-On Admin 控制台中,检查分配给客户端的角色是否显示在 Clients > Service Account Roles 中。

  • 配置为连接到 Red Hat Single Sign-On 的 Kafka 集群已部署到 OpenShift 集群。

流程

  1. 使用 AMQ Streams Kafka 镜像运行一个新的交互式 pod 容器,以连接到正在运行的 Kafka 代理。

    NS=sso
    oc run -ti --restart=Never --image=registry.redhat.io/amq7/amq-streams-kafka-28-rhel7:1.8.0 kafka-cli -n $NS -- /bin/sh
    注意

    如果 oc 超时等待镜像下载,后续尝试可能会导致 AlreadyExists 错误。

  2. 附加到 pod 容器。

    oc attach -ti kafka-cli -n $NS
  3. 使用红帽单点登录实例的主机名,使用 TLS 为客户端连接准备证书。

    SSO_HOST=SSO-HOSTNAME
    SSO_HOST_PORT=$SSO_HOST:443
    STOREPASS=storepass
    
    echo "Q" | openssl s_client -showcerts -connect $SSO_HOST_PORT 2>/dev/null | awk ' /BEGIN CERTIFICATE/,/END CERTIFICATE/ { print $0 } ' > /tmp/sso.crt
  4. 为 TLS 连接到 Kafka 代理创建信任存储。

    keytool -keystore /tmp/truststore.p12 -storetype pkcs12 -alias sso -storepass $STOREPASS -import -file /tmp/sso.crt -noprompt
  5. 使用 Kafka bootstrap 地址作为 Kafka 代理的主机名,使用 tls 侦听器端口(9093)为 Kafka 代理准备证书。

    KAFKA_HOST_PORT=my-cluster-kafka-bootstrap:9093
    STOREPASS=storepass
    
    echo "Q" | openssl s_client -showcerts -connect $KAFKA_HOST_PORT 2>/dev/null | awk ' /BEGIN CERTIFICATE/,/END CERTIFICATE/ { print $0 } ' > /tmp/my-cluster-kafka.crt
  6. 将 Kafka 代理的证书添加到信任存储中。

    keytool -keystore /tmp/truststore.p12 -storetype pkcs12 -alias my-cluster-kafka -storepass $STOREPASS -import -file /tmp/my-cluster-kafka.crt -noprompt

    保持 会话处于打开状态,以检查授权访问权限。

4.5.4.4. 使用 CLI Kafka 客户端会话检查对 Kafka 的授权访问权限

利用交互式 CLI 会话,检查通过红帽单点登录域应用的授权规则。使用 Kafka 的示例制作者和消费者客户端应用检查,以创建具有不同访问权限级别的用户和服务帐户的主题。

使用 team-a-clientteam-b-client 客户端检查授权规则。使用 alice admin 用户对 Kafka 执行额外的管理任务。

本例中使用的 AMQ Streams Kafka 镜像包含 Kafka 制作者和使用者二进制文件。

先决条件

设置客户端和管理员用户配置

  1. 使用 team-a-client 客户端的身份验证属性准备 Kafka 配置文件。

    SSO_HOST=SSO-HOSTNAME
    
    cat > /tmp/team-a-client.properties << EOF
    security.protocol=SASL_SSL
    ssl.truststore.location=/tmp/truststore.p12
    ssl.truststore.password=$STOREPASS
    ssl.truststore.type=PKCS12
    sasl.mechanism=OAUTHBEARER
    sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      oauth.client.id="team-a-client" \
      oauth.client.secret="team-a-client-secret" \
      oauth.ssl.truststore.location="/tmp/truststore.p12" \
      oauth.ssl.truststore.password="$STOREPASS" \
      oauth.ssl.truststore.type="PKCS12" \
      oauth.token.endpoint.uri="https://$SSO_HOST/auth/realms/kafka-authz/protocol/openid-connect/token" ;
    sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
    EOF

    使用 SASL OAUTHBEARER 机制。这种机制需要客户端 ID 和客户端 secret,这意味着客户端首先连接到红帽单点登录服务器来获取访问令牌。然后,客户端连接到 Kafka 代理并使用访问令牌进行身份验证。

  2. 使用 team-b-client 客户端的身份验证属性准备 Kafka 配置文件。

    cat > /tmp/team-b-client.properties << EOF
    security.protocol=SASL_SSL
    ssl.truststore.location=/tmp/truststore.p12
    ssl.truststore.password=$STOREPASS
    ssl.truststore.type=PKCS12
    sasl.mechanism=OAUTHBEARER
    sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      oauth.client.id="team-b-client" \
      oauth.client.secret="team-b-client-secret" \
      oauth.ssl.truststore.location="/tmp/truststore.p12" \
      oauth.ssl.truststore.password="$STOREPASS" \
      oauth.ssl.truststore.type="PKCS12" \
      oauth.token.endpoint.uri="https://$SSO_HOST/auth/realms/kafka-authz/protocol/openid-connect/token" ;
    sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
    EOF
  3. 通过使用 curl 并执行密码授权身份验证来获取刷新令牌,从而对 admin 用户 alice 进行身份验证。

    USERNAME=alice
    PASSWORD=alice-password
    
    GRANT_RESPONSE=$(curl -X POST "https://$SSO_HOST/auth/realms/kafka-authz/protocol/openid-connect/token" -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=password&username=$USERNAME&password=$PASSWORD&client_id=kafka-cli&scope=offline_access" -s -k)
    
    REFRESH_TOKEN=$(echo $GRANT_RESPONSE | awk -F "refresh_token\":\"" '{printf $2}' | awk -F "\"" '{printf $1}')

    刷新令牌是一个离线令牌,寿命很长,且不会过期。

  4. 使用 admin 用户 alice 的身份验证属性准备 Kafka 配置文件。

    cat > /tmp/alice.properties << EOF
    security.protocol=SASL_SSL
    ssl.truststore.location=/tmp/truststore.p12
    ssl.truststore.password=$STOREPASS
    ssl.truststore.type=PKCS12
    sasl.mechanism=OAUTHBEARER
    sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
      oauth.refresh.token="$REFRESH_TOKEN" \
      oauth.client.id="kafka-cli" \
      oauth.ssl.truststore.location="/tmp/truststore.p12" \
      oauth.ssl.truststore.password="$STOREPASS" \
      oauth.ssl.truststore.type="PKCS12" \
      oauth.token.endpoint.uri="https://$SSO_HOST/auth/realms/kafka-authz/protocol/openid-connect/token" ;
    sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
    EOF

    kafka-cli 公共客户端用于 sasl .jaas.config 中的 oauth.client. id。由于它是公共客户端,因此不需要机密。客户端使用上一步中验证的刷新令牌进行身份验证。刷新令牌在后台请求访问令牌,然后发送到 Kafka 代理进行身份验证。

生成具有授权访问权限的消息

使用 team-a-client 配置检查您可以向以 a_ 或 x_ 开头的主题生成消息。

  1. 写入到 主题 my 主题。

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic my-topic \
      --producer.config=/tmp/team-a-client.properties
    First message

    此请求 返回未授权访问主题:[my-topic] 错误。

    team-a-client 具有开发团队 A 角色,允许它对以 a_ 开头的主题执行任何受支持的操作,但只能写入 x_ 开头的主题。名为 my-topic 的主题都不匹配这些规则。

  2. 写入主题 a_messages

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic a_messages \
      --producer.config /tmp/team-a-client.properties
    First message
    Second message

    成功生成消息到 Kafka。

  3. 按 CTRL+C 退出 CLI 应用。
  4. 检查 Kafka 容器日志中请求的 Authorization GRANTED 的调试日志。
oc logs my-cluster-kafka-0 -f -n $NS

使用具有授权访问权限的信息

使用 team-a-client 配置来使用来自主题 a_messages 的消息。

  1. 从主题 a_messages 获取消息.

    bin/kafka-console-consumer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic a_messages \
      --from-beginning --consumer.config /tmp/team-a-client.properties

    请求返回一个错误,因为 team-a-clientDev 团队 A 角色仅有权访问名称以 a_ 开头的消费者组。

  2. 更新 team-a-client 属性,以指定允许使用的自定义使用者组。

    bin/kafka-console-consumer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic a_messages \
      --from-beginning --consumer.config /tmp/team-a-client.properties --group a_consumer_group_1

    使用者从 a_messages 主题接收所有消息。

使用授权访问权限管理 Kafka

team-a-client 是一个没有集群级别访问权限的帐户,但可以用于一些管理操作。

  1. 列出主题.

    bin/kafka-topics.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/team-a-client.properties --list

    a_messages 主题返回。

  2. 列出消费者组。

    bin/kafka-consumer-groups.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/team-a-client.properties --list

    a_consumer_group_1 consumer 组返回。

    获取集群配置详情。

    bin/kafka-configs.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/team-a-client.properties \
      --entity-type brokers --describe --entity-default

    请求返回一个错误,因为操作需要 team-a-client 没有集群级别权限。

使用具有不同权限的客户端

使用 team-b-client 配置向以 b_ 开头的主题生成消息。

  1. 写入主题 a_messages

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic a_messages \
      --producer.config /tmp/team-b-client.properties
    Message 1

    此请求将 返回未授权访问主题:[a_messages] 错误。

  2. 写入到主题 b_messages

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic b_messages \
      --producer.config /tmp/team-b-client.properties
    Message 1
    Message 2
    Message 3

    成功生成消息到 Kafka。

  3. 写入主题 x_messages

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --producer.config /tmp/team-b-client.properties
    Message 1

    未授权访问主题:[x_messages] 错误返回,team-b-client 只能从主题 x_messages 中读取。

  4. 使用 team-a-client 写入主题 x_messages

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --producer.config /tmp/team-a-client.properties
    Message 1

    此请求 返回未授权访问主题:[x_messages] 错误。team-a-client 可以写入 x_messages 主题,但是如果主题尚不存在,则无权创建该主题。在 team-a-client 可以写入 x_messages 主题之前,管理员 高级用户 必须使用正确的配置创建它,如分区和副本的数量。

使用授权 admin 用户管理 Kafka

使用 admin 用户 alice 管理 Kafka。Alice 完全有权管理任何 Kafka 集群中的所有内容。

  1. 创建 x_messages 主题,作为 alice

    bin/kafka-topics.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/alice.properties \
      --topic x_messages --create --replication-factor 1 --partitions 1

    主题创建成功。

  2. 将所有主题列为 alice.

    bin/kafka-topics.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/alice.properties --list
    bin/kafka-topics.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/team-a-client.properties --list
    bin/kafka-topics.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/team-b-client.properties --list

    admin 用户 alice 可以列出所有主题,而 team-a-clientteam-b-client 只能列出他们有权访问的主题。

    Dev 团队 ADev 团队 B 角色均对以 x_ 开头的主题具有 权限,但它们无法看到其他团队的主题,因为它们没有描述它们 的权限

  3. 使用 team-a-client 生成到 x_messages 主题的信息:

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --producer.config /tmp/team-a-client.properties
    Message 1
    Message 2
    Message 3

    alice 创建 x_messages 主题时,会成功生成消息到 Kafka。

  4. 使用 team-b-client 生成消息到 x_messages 主题。

    bin/kafka-console-producer.sh --broker-list my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --producer.config /tmp/team-b-client.properties
    Message 4
    Message 5

    此请求 返回未授权访问主题:[x_messages] 错误。

  5. 使用 team-b-client 使用来自 x_messages 主题的信息:

    bin/kafka-console-consumer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --from-beginning --consumer.config /tmp/team-b-client.properties --group x_consumer_group_b

    使用者从 x_messages 主题接收所有消息。

  6. 使用 team-a-client 使用来自 x_messages 主题的消息。

    bin/kafka-console-consumer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --from-beginning --consumer.config /tmp/team-a-client.properties --group x_consumer_group_a

    此请求 返回未授权访问主题:[x_messages] 错误。

  7. 使用 team-a-client 使用来自以 a_ 开头的消费者组的消息。

    bin/kafka-console-consumer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --from-beginning --consumer.config /tmp/team-a-client.properties --group a_consumer_group_a

    此请求 返回未授权访问主题:[x_messages] 错误。

    Dev 团队 A 对x_ 开头的主题没有 读取 访问权限。

  8. 使用 alice 生成指向 x_messages 主题的消息。

    bin/kafka-console-consumer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --from-beginning --consumer.config /tmp/alice.properties

    成功生成消息到 Kafka。

    Alice 可以从任何主题读取或写入。

  9. 使用 alice 读取集群配置。

    bin/kafka-configs.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --command-config /tmp/alice.properties \
      --entity-type brokers --describe --entity-default

    本例的集群配置为空。

第 5 章 使用 AMQ Streams Operator

使用 AMQ Streams 操作器来管理您的 Kafka 集群,以及 Kafka 主题和用户。

5.1. 使用 Cluster Operator

Cluster Operator 用于部署 Kafka 集群和其他 Kafka 组件。

Cluster Operator 使用 YAML 安装文件进行部署。

注意

在 OpenShift 中,Kafka Connect 部署可以纳入 Source2Image 功能,以提供添加额外连接器的便捷方式。

5.1.1. Cluster Operator 配置

您可以使用支持的环境变量及其日志记录配置来配置 Cluster Operator。

环境变量与用于部署 Cluster Operator 镜像的容器配置相关。有关 镜像 配置的详情请参考 第 13.1.6 节 “image

STRIMZI_NAMESPACE

Operator 应操作的命名空间的逗号分隔列表。如果没有设置、设置为空字符串或设置为 *,Cluster Operator 将在所有命名空间中运行。Cluster Operator 部署可能会使用 OpenShift Downward API 自动将其设置为 Cluster Operator 部署到的命名空间。

Cluster Operator 命名空间的配置示例

env:
  - name: STRIMZI_NAMESPACE
    valueFrom:
      fieldRef:
        fieldPath: metadata.namespace

STRIMZI_FULL_RECONCILIATION_INTERVAL_MS
可选,默认为 120000 ms。定期协调之间的间隔,以毫秒为单位。
STRIMZI_OPERATION_TIMEOUT_MS
可选,默认为 300000 ms。内部操作的超时,以毫秒为单位。当在常规 OpenShift 操作需要比平时更长的集群中使用 AMQ Streams 时,这个值应该会增加(例如,因为 Docker 镜像下载速度较慢)。
STRIMZI_OPERATIONS_THREAD_POOL_SIZE
可选,默认为 10 worker 线程池大小,用于集群 Operator 运行的各种异步和阻止操作。
STRIMZI_OPERATOR_NAMESPACE

运行 AMQ Streams Cluster Operator 的命名空间的名称。不要手动配置这个变量。使用 OpenShift Downward API。

env:
  - name: STRIMZI_OPERATOR_NAMESPACE
    valueFrom:
      fieldRef:
        fieldPath: metadata.namespace
STRIMZI_OPERATOR_NAMESPACE_LABELS

可选。运行 AMQ Streams Cluster Operator 的命名空间的标签。命名空间标签用于在网络策略中配置命名空间选择器,以允许 AMQ Streams Cluster Operator 只能使用这些标签从命名空间中访问操作对象。如果没有设置,网络策略中的命名空间选择器会被配置为允许从 OpenShift 集群的任何命名空间访问 AMQ Streams Cluster Operator。

env:
  - name: STRIMZI_OPERATOR_NAMESPACE_LABELS
    value: label1=value1,label2=value2
STRIMZI_CUSTOM_RESOURCE_SELECTOR

可选。指定标签选择器,用于过滤操作器处理的自定义资源。Operator 仅在设置了指定标签的自定义资源上运行。没有这些标签的资源不会被 Operator 看到。标签选择器适用于 Kafka、Kafka ConnectKafkaConnectS2IKafkaBridgeKafkaMirrorMakerKafkaMirrorMaker2 资源。只有在对应的 Kafka 和 Kafka Connect 集群具有匹配的标签时,才会执行 Kafka Rebalance 和 KafkaConnector 资源。

env:
  - name: STRIMZI_CUSTOM_RESOURCE_SELECTOR
    value: label1=value1,label2=value2
STRIMZI_LABELS_EXCLUSION_PATTERN

可选,默认的 regex 模式是 ^app.kubernetes.io/(?!part-of)*。指定 regex 排除模式,用于将标签传播从主自定义资源过滤到其子资源。排除过滤器的标签不会应用到模板部分中的标签,如 spec.kafka.template.pod.metadata.labels

env:
  - name: STRIMZI_LABELS_EXCLUSION_PATTERN
    value: "^key1.*"
STRIMZI_KAFKA_IMAGES
必需。这提供了从 Kafka 版本到相应 Docker 镜像的映射,其中包含该版本的 Kafka 代理。所需语法为空格或用逗号分开的 <version>=<image> 对。例如 2.7.0=registry.redhat.io/amq7/amq-streams-kafka-27-rhel7:1.8.0, 2.8.0=registry.redhat.io/amq7/amq-streams-kafka-28-rhel7:1.8.0。当指定 Kafka.spec.kafka.version 属性但没有指定 Kafka 资源 中的 Kafka.spec.kafka.image 时会使用此方法。
STRIMZI_DEFAULT_KAFKA_INIT_IMAGE
可选,默认 registry.redhat.io/amq7/amq-streams-rhel7-operator:1.8.0。如果没有将镜像指定为 Kafka 资源中的 kafka-init-image,则在代理之前启动的 init 容器的镜像名称(即机架支持)没有指定为 kafka-init-image
STRIMZI_KAFKA_CONNECT_IMAGES
必需。这提供了从 Kafka 版本到相应 Docker 镜像的映射,其中包含该版本的 Kafka 连接。所需语法为空格或用逗号分开的 <version>=<image> 对。例如 2.7.0=registry.redhat.io/amq7/amq-streams-kafka-27-rhel7:1.8.0, 2.8.0=registry.redhat.io/amq7/amq-streams-kafka-28-rhel7:1.8.0。这在指定 KafkaConnect.spec.version 属性而不是 KafkaConnect.spec.image 时使用。
STRIMZI_KAFKA_CONNECT_S2I_IMAGES
必需。这提供了从 Kafka 版本到相应 Docker 镜像的映射,其中包含该版本的 Kafka 连接。所需语法为空格或用逗号分开的 <version>=<image> 对。例如 2.7.0=registry.redhat.io/amq7/amq-streams-kafka-27-rhel7:1.8.0, 2.8.0=registry.redhat.io/amq7/amq-streams-kafka-28-rhel7:1.8.0。这在指定 KafkaConnectS2I.spec.version 属性而不是 KafkaConnectS2I.spec.image 时使用。
STRIMZI_KAFKA_MIRROR_MAKER_IMAGES
必需。这提供了从 Kafka 版本到相应 Docker 镜像的映射,其中包含该版本的 Kafka 镜像制作器。所需语法为空格或用逗号分开的 <version>=<image> 对。例如 2.7.0=registry.redhat.io/amq7/amq-streams-kafka-27-rhel7:1.8.0, 2.8.0=registry.redhat.io/amq7/amq-streams-kafka-28-rhel7:1.8.0。这在指定 KafkaMirrorMaker.spec.version 属性而不是 KafkaMirrorMaker.spec.image 时使用。
STRIMZI_DEFAULT_TOPIC_OPERATOR_IMAGE
可选,默认 registry.redhat.io/amq7/amq-streams-rhel7-operator:1.8.0。部署主题 Operator 时要使用的镜像名称,如果没有将镜像指定为 Kafka 资源 中的 Kafka.spec.entityOperator.topicOperator.image
STRIMZI_DEFAULT_USER_OPERATOR_IMAGE
可选,默认 registry.redhat.io/amq7/amq-streams-rhel7-operator:1.8.0。在部署用户 operator 时要使用的镜像名称,如果没有在 Kafka 资源中指定为 Kafka.spec.entityOperator.userOperator.image 镜像名称
STRIMZI_DEFAULT_TLS_SIDECAR_ENTITY_OPERATOR_IMAGE
可选,默认 registry.redhat.io/amq7/amq-streams-kafka-28-rhel7:1.8.0。在部署 sidecar 容器时用作默认的镜像名称,该容器为 Entity Operator 提供 TLS 支持,如果没有将镜像指定为 Kafka 资源 中的 Kafka.spec.entityOperator.tlsSidecar.image
STRIMZI_IMAGE_PULL_POLICY
可选。ImagePullPolicy,它将应用到由 AMQ Streams Cluster Operator 管理的所有 pod 中的容器。有效值有 AlwaysifNotPresentNever。如果未指定,则将使用 OpenShift 的默认值。更改策略会导致所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群滚动更新。
STRIMZI_IMAGE_PULL_SECRETS
可选。以逗号分隔的 Secret 名称列表。此处引用的 secret 包含从中提取容器镜像的容器注册表的凭据。secret 在 imagePullSecrets 字段中用于 Cluster Operator 创建的所有 Pod。更改此列表会导致所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群进行滚动更新。
STRIMZI_KUBERNETES_VERSION

可选。覆盖从 API 服务器检测到的 Kubernetes 版本信息。

Kubernetes 版本覆盖的配置示例

env:
  - name: STRIMZI_KUBERNETES_VERSION
    value: |
           major=1
           minor=16
           gitVersion=v1.16.2
           gitCommit=c97fe5036ef3df2967d086711e6c0c405941e14b
           gitTreeState=clean
           buildDate=2019-10-15T19:09:08Z
           goVersion=go1.12.10
           compiler=gc
           platform=linux/amd64

KUBERNETES_SERVICE_DNS_DOMAIN

可选。覆盖默认的 OpenShift DNS 域名后缀。

默认情况下,OpenShift 集群中分配的服务的 DNS 域名使用默认的后缀 cluster.local

例如,对于代理 kafka-0

<cluster-name>-kafka-0.<cluster-name>-kafka-brokers.<namespace>.svc.cluster.local

DNS 域名被添加到用于主机名验证的 Kafka 代理证书中。

如果您在集群中使用不同的 DNS 域名后缀,请将 KUBERNETES_SERVICE_DNS_DOMAIN 环境变量从默认值改为您用来与 Kafka 代理建立连接的变量。

STRIMZI_CONNECT_BUILD_TIMEOUT_MS
可选,默认为 300000 ms。使用额外连接点构建新 Kafka Connect 镜像的超时时间,以毫秒为单位。使用 AMQ Streams 构建包含多个连接器的容器镜像或使用速度较慢的容器注册表时,应增加这个值。
STRIMZI_FEATURE_GATES
可选。启用或禁用由功能门控制的功能和功能。有关每个功能门的详情请参考 第 5.1.1.1 节 “功能门”
5.1.1.1. 功能门

AMQ Streams 操作器支持 功能门来 启用或禁用某些功能。启用功能门会更改相关 Operator 的行为,并将该功能引入您的 AMQ Streams 部署。

功能门的默认状态为 enableddisabled。要修改功能门的默认状态,请在操作器的配置中使用 STRIMZI_FEATURE_GATES 环境变量。您可以使用这个环境变量修改多个功能门。

功能门有三个成熟度阶段:

  • alpha - 通常默认禁用
  • Beta - 通常默认启用
  • 正式发行(GA)- 通常默认启用

Alpha 阶段功能可能实验性或不稳定,可能会有所变化,或者没有经过足够的测试以供生产环境使用。测试版阶段功能经过了良好的测试,其功能不太可能改变。GA 阶段的功能是稳定的,未来不应改变。如果 alpha 和 beta 阶段功能不有用,则会删除它们。

注意

功能门可能会在到达 GA 时被删除。这意味着该功能已合并到 AMQ Streams 核心功能中,无法再禁用。

表 5.1. 当所有功能门和 AMQ Streams 版本移到 alpha、beta 或 GA 时
功能门alphaBetaGA

ControlPlaneListener

1.8

-

-

ServiceAccountPatching

1.8

-

-

配置功能门

您可以使用操作器配置中的 STRIMZI_FEATURE_GATES 环境变量来配置功能门。指定以逗号分隔的功能门名称和前缀列表。+ 前缀启用功能门,而 - 前缀可禁用它。

启用 FeatureGate1 并禁用 FeatureGate2 的功能门配置示例

env:
  - name: STRIMZI_FEATURE_GATES
    value: +FeatureGate1,-FeatureGate2

5.1.1.1.1. control plane 侦听程序功能门

使用 ControlPlaneListener 功能门更改 Kafka 集群中用于代理间通信的通信路径。

OpenShift 控制平面管理在工作程序节点上运行的工作负载。Kubernetes API 服务器和控制器管理器等服务在 control plane 上运行。OpenShift 数据平面向容器(包括 CPU、内存、网络和存储)提供资源。

在 AMQ Streams 中,control plane 流量由维护 Kafka 集群所需状态的控制器连接组成。数据平面流量主要由领导代理和后续代理之间的数据复制组成。

当禁用 ControlPlaneListener 功能门时,control plane 和数据平面流量会通过端口 9091 上的相同内部监听程序。这是引入功能门前的默认行为。

当启用 ControlPlaneListener 时,control plane 流量通过端口 9090 上的专用 control plane 侦听 程序进行。数据平面流量在端口 9091 上继续使用内部监听程序。

使用 control plane 侦听器可能会提高性能,因为重要的控制器连接(如分区领导更改)不会因为代理间数据复制而延迟。

启用 control plane 侦听程序功能门

ControlPlaneListener 功能门处于 alpha 阶段,默认状态为 disabled。要启用它,请在 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量中指定 +ControlPlaneListener

在以下情况下必须禁用此功能门:

  • 从 AMQ Streams 1.7 及更早版本升级
  • 降级到 AMQ Streams 1.7 及更早版本
注意

ControlPlaneListener 功能门是在 AMQ Streams 1.8 中引入的,它应该在进入 beta 阶段前保留在 alpha 阶段。

5.1.1.1.2. 服务帐户补丁功能门

默认情况下,Cluster Operator 不会更新服务帐户。要允许 Cluster Operator 应用更新,请启用 ServiceAccountPatching 功能门。

+ServiceAccountPatching 添加到 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量中。

功能门当前处于 alpha 阶段并默认禁用。启用功能门后,Cluster Operator 会在每次协调中对服务帐户配置应用更新。例如,您可以在已创建操作对象后更改服务帐户标签和注解。

注意

ServiceAccountPatching 功能门是在 AMQ Streams 1.8 中引入的,它应该会一直处于多个发行版本的 alpha 阶段,然后进入 beta 阶段并默认启用。

5.1.1.2. 通过 ConfigMap 日志记录配置

Cluster Operator 的日志记录由 strimzi-cluster-operator ConfigMap 配置。

安装 Cluster Operator 时会创建一个包含日志配置的 ConfigMap。此 ConfigMap 在文件 install/cluster-operator/050-ConfigMap-strimzi-cluster-operator.yaml 中描述。您可以通过更改此 ConfigMap 中的 data 字段 log4j2.properties 来配置 Cluster Operator 日志。

要更新日志记录配置,您可以编辑 050-ConfigMap-strimzi-cluster-operator.yaml 文件,然后运行以下命令:

oc create -f install/cluster-operator/050-ConfigMap-strimzi-cluster-operator.yaml

或者,直接编辑 ConfigMap:

oc edit configmap strimzi-cluster-operator

要更改重新加载间隔的频率,请在创建的 ConfigMap 中的 monitorInterval 选项中设置一个时间(以秒为单位)。

如果在部署 Cluster Operator 时缺少 ConfigMap,则会使用默认的日志记录值。

如果在部署 Cluster Operator 后意外删除 ConfigMap,则会使用最新载入的日志配置。创建新 ConfigMap 以 加载新的日志配置。

注意

不要从 ConfigMap 中删除 monitorInterval 选项。

5.1.1.3. 使用网络策略限制 Cluster Operator 访问

Cluster Operator 可以和它管理的资源在同一命名空间中运行,也可以在单独的命名空间中运行。默认情况下,STRIMZI_OPERATOR_NAMESPACE 环境变量被配置为使用 OpenShift Downward API 来查找 Cluster Operator 在哪个命名空间中运行。如果 Cluster Operator 在与资源相同的命名空间中运行,则只需要本地访问权限,并且 AMQ Streams 允许。

如果 Cluster Operator 在一个独立的命名空间中运行,则 OpenShift 集群中的任何命名空间都可以访问 Cluster Operator,除非配置了网络策略。使用可选的 STRIMZI_OPERATOR_NAMESPACE_LABELS 环境变量,使用命名空间标签为 Cluster Operator 建立网络策略。通过添加命名空间标签,Cluster Operator 的访问权限仅限于指定的命名空间。

为 Cluster Operator 部署配置网络策略

#...
env:
  # ...
  - name: STRIMZI_OPERATOR_NAMESPACE_LABELS
    value: label1=value1,label2=value2
  #...

5.1.1.4. 定期协调

虽然 Cluster Operator 会响应从 OpenShift 集群收到所需集群资源的所有通知,但如果操作器没有运行,或者因任何原因未收到通知,则所需的资源将与正在运行的 OpenShift 集群的状态保持同步。

为了正确处理故障切换,由 Cluster Operator 执行定期协调过程,以便它可以将所需资源的状态与当前集群部署进行比较,以便在所有这些部署中保持一致状态。您可以使用 [STRIMZI_FULL_RECONCILIATION_INTERVAL_MS] 变量为定期协调设置时间间隔。

5.1.2. 调配基于角色的访问控制(RBAC)

要使 Cluster Operator 正常工作,需要在 OpenShift 集群中与资源(如 Kafka、Kafka Connect 等)以及受管资源(如 ConfigMap、Pod、Deployment StatefulSet 和 Services )交互。这种权限在 OpenShift 基于角色的访问控制(RBAC)资源中描述:

  • ServiceAccount,
  • 角色ClusterRole
  • role binding 和 ClusterRoleBinding

除了使用 ClusterRoleBinding 在其自身 ServiceAccount 中运行外,Cluster Operator 还为需要访问 OpenShift 资源的组件管理一些 RBAC 资源。

OpenShift 还包含特权升级保护,可防止在一个 ServiceAccount 下操作的组件授予授予授权 ServiceAccount 没有的其他 ServiceAccount s 特权。因为 Cluster Operator 必须能够创建 ClusterRoleBindings,以及它管理的资源所需的 RoleBindings,所以 Cluster Operator 还必须具有相同的权限。

5.1.2.1. 委派的权限

当 Cluster Operator 为所需的 Kafka 资源部署资源时,它还会创建 ServiceAccount、 RoleBindingsClusterRoleBindings,如下所示:

  • Kafka 代理 pod 使用一个名为 cluster-name-kafkaServiceAccount

    • 使用机架功能时,strimzi-cluster-name-kafka-init ClusterRoleBinding 用来通过 ClusterRole (名为 strimzi-kafka-broker)对集群中的节点授予这个 ServiceAccount 访问权限
    • 如果没有使用机架功能,且集群没有通过 nodeport 公开,则不会创建绑定
  • ZooKeeper pod 使用名为 cluster-name-zookeeperServiceAccount
  • Entity Operator pod 使用名为 cluster-name-entity-operatorServiceAccount

    • Topic Operator 生成带有状态信息的 OpenShift 事件,因此 ServiceAccount 绑定到名为 strimzi-entity-operatorClusterRole,它通过 strimzi-entity-operator RoleBinding授予此访问权限
  • KafkaConnect 和 KafkaConnect S2I 资源的 pod 使用名为 cluster-name-cluster-connectServiceAccount
  • KafkaMirrorMaker 的 pod 使用名为 cluster-name-mirror-makerServiceAccount
  • KafkaMirrorMaker2 的 pod 使用名为 cluster-name-mirrormaker2ServiceAccount
  • KafkaBridge 的 pod 使用名为 cluster-name-bridgeServiceAccount
5.1.2.2. ServiceAccount

Cluster Operator 最好使用 ServiceAccount 运行:

Cluster Operator 的 ServiceAccount 示例

apiVersion: v1
kind: ServiceAccount
metadata:
  name: strimzi-cluster-operator
  labels:
    app: strimzi

然后,Operator 的 Deployment 需要在其 spec.template.spec.serviceAccountName 中指定

Cluster Operator 部署 的部分示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: strimzi-cluster-operator
  labels:
    app: strimzi
spec:
  replicas: 1
  selector:
    matchLabels:
      name: strimzi-cluster-operator
      strimzi.io/kind: cluster-operator
  template:
      # ...

注意 12 行,其中 strimzi-cluster-operator ServiceAccount 指定为 serviceAccountName

5.1.2.3. ClusterRoles

Cluster Operator 需要使用 提供所需资源访问的 ClusterRole 运行。根据 OpenShift 集群设置,可能需要集群管理员来创建 ClusterRole。

注意

集群管理员权限只在创建 ClusterRole 时需要。Cluster Operator 不会在集群管理员帐户下运行。

ClusterRole 遵循最小 权限, 仅包含 Cluster Operator 运行 Kafka、Kafka Connect 和 ZooKeeper 集群所需的权限。第一组分配的权限允许 Cluster Operator 管理 OpenShift 资源,如 StatefulSetsDeploymentPodConfigMap。

Cluster Operator 使用 ClusterRole 在命名空间范围的资源级别和集群范围的资源级别授予权限:

具有 Cluster Operator 资源命名空间资源的 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: strimzi-cluster-operator-namespaced
  labels:
    app: strimzi
rules:
  - apiGroups:
      - "rbac.authorization.k8s.io"
    resources:
      # The cluster operator needs to access and manage rolebindings to grant Strimzi components cluster permissions
      - rolebindings
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - "rbac.authorization.k8s.io"
    resources:
      # The cluster operator needs to access and manage roles to grant the entity operator permissions
      - roles
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - ""
    resources:
      # The cluster operator needs to access and delete pods, this is to allow it to monitor pod health and coordinate rolling updates
      - pods
      # The cluster operator needs to access and manage service accounts to grant Strimzi components cluster permissions
      - serviceaccounts
      # The cluster operator needs to access and manage config maps for Strimzi components configuration
      - configmaps
      # The cluster operator needs to access and manage services and endpoints to expose Strimzi components to network traffic
      - services
      - endpoints
      # The cluster operator needs to access and manage secrets to handle credentials
      - secrets
      # The cluster operator needs to access and manage persistent volume claims to bind them to Strimzi components for persistent data
      - persistentvolumeclaims
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - "kafka.strimzi.io"
    resources:
      # The cluster operator runs the KafkaAssemblyOperator, which needs to access and manage Kafka resources
      - kafkas
      - kafkas/status
      # The cluster operator runs the KafkaConnectAssemblyOperator, which needs to access and manage KafkaConnect resources
      - kafkaconnects
      - kafkaconnects/status
      # The cluster operator runs the KafkaConnectS2IAssemblyOperator, which needs to access and manage KafkaConnectS2I resources
      - kafkaconnects2is
      - kafkaconnects2is/status
      # The cluster operator runs the KafkaConnectorAssemblyOperator, which needs to access and manage KafkaConnector resources
      - kafkaconnectors
      - kafkaconnectors/status
      # The cluster operator runs the KafkaMirrorMakerAssemblyOperator, which needs to access and manage KafkaMirrorMaker resources
      - kafkamirrormakers
      - kafkamirrormakers/status
      # The cluster operator runs the KafkaBridgeAssemblyOperator, which needs to access and manage BridgeMaker resources
      - kafkabridges
      - kafkabridges/status
      # The cluster operator runs the KafkaMirrorMaker2AssemblyOperator, which needs to access and manage KafkaMirrorMaker2 resources
      - kafkamirrormaker2s
      - kafkamirrormaker2s/status
      # The cluster operator runs the KafkaRebalanceAssemblyOperator, which needs to access and manage KafkaRebalance resources
      - kafkarebalances
      - kafkarebalances/status
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      # The cluster operator needs the extensions api as the operator supports Kubernetes version 1.11+
      # apps/v1 was introduced in Kubernetes 1.14
      - "extensions"
    resources:
      # The cluster operator needs to access and manage deployments to run deployment based Strimzi components
      - deployments
      - deployments/scale
      # The cluster operator needs to access replica sets to manage Strimzi components and to determine error states
      - replicasets
      # The cluster operator needs to access and manage replication controllers to manage replicasets
      - replicationcontrollers
      # The cluster operator needs to access and manage network policies to lock down communication between Strimzi components
      - networkpolicies
      # The cluster operator needs to access and manage ingresses which allow external access to the services in a cluster
      - ingresses
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - "apps"
    resources:
      # The cluster operator needs to access and manage deployments to run deployment based Strimzi components
      - deployments
      - deployments/scale
      - deployments/status
      # The cluster operator needs to access and manage stateful sets to run stateful sets based Strimzi components
      - statefulsets
      # The cluster operator needs to access replica-sets to manage Strimzi components and to determine error states
      - replicasets
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - ""
    resources:
      # The cluster operator needs to be able to create events and delegate permissions to do so
      - events
    verbs:
      - create
  - apiGroups:
      # OpenShift S2I requirements
      - apps.openshift.io
    resources:
      - deploymentconfigs
      - deploymentconfigs/scale
      - deploymentconfigs/status
      - deploymentconfigs/finalizers
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      # OpenShift S2I requirements
      - build.openshift.io
    resources:
      - buildconfigs
      - buildconfigs/instantiate
      - builds
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      # OpenShift S2I requirements
      - image.openshift.io
    resources:
      - imagestreams
      - imagestreams/status
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - networking.k8s.io
    resources:
      # The cluster operator needs to access and manage network policies to lock down communication between Strimzi components
      - networkpolicies
      # The cluster operator needs to access and manage ingresses which allow external access to the services in a cluster
      - ingresses
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - route.openshift.io
    resources:
      # The cluster operator needs to access and manage routes to expose Strimzi components for external access
      - routes
      - routes/custom-host
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - policy
    resources:
      # The cluster operator needs to access and manage pod disruption budgets this limits the number of concurrent disruptions
      # that a Strimzi component experiences, allowing for higher availability
      - poddisruptionbudgets
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update

第二个包括集群范围资源所需的权限。

为 Cluster Operator 带有集群范围资源的 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: strimzi-cluster-operator-global
  labels:
    app: strimzi
rules:
  - apiGroups:
      - "rbac.authorization.k8s.io"
    resources:
      # The cluster operator needs to create and manage cluster role bindings in the case of an install where a user
      # has specified they want their cluster role bindings generated
      - clusterrolebindings
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update
  - apiGroups:
      - storage.k8s.io
    resources:
      # The cluster operator requires "get" permissions to view storage class details
      # This is because only a persistent volume of a supported storage class type can be resized
      - storageclasses
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      # The cluster operator requires "list" permissions to view all nodes in a cluster
      # The listing is used to determine the node addresses when NodePort access is configured
      # These addresses are then exposed in the custom resource states
      - nodes
    verbs:
      - list

The strimzi-kafka-broker ClusterRole 代表 Kafka pod 中 init 容器所需的访问权限,用于机架功能。如 委派的特权 部分所述,Cluster Operator 还需要此角色才能委派此访问权限。

Cluster Operator 的 ClusterRole,允许它将 OpenShift 节点的访问权限委派给 Kafka 代理 pod

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: strimzi-kafka-broker
  labels:
    app: strimzi
rules:
  - apiGroups:
      - ""
    resources:
      # The Kafka Brokers require "get" permissions to view the node they are on
      # This information is used to generate a Rack ID that is used for High Availability configurations
      - nodes
    verbs:
      - get

The strimzi-topic-operator ClusterRole 代表 Topic Operator 所需的访问权限。如 委派的特权 部分所述,Cluster Operator 还需要此角色才能委派此访问权限。

Cluster Operator 的 ClusterRole,允许它将对事件的访问委托给主题 Operator

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: strimzi-entity-operator
  labels:
    app: strimzi
rules:
  - apiGroups:
      - "kafka.strimzi.io"
    resources:
      # The entity operator runs the KafkaTopic assembly operator, which needs to access and manage KafkaTopic resources
      - kafkatopics
      - kafkatopics/status
      # The entity operator runs the KafkaUser assembly operator, which needs to access and manage KafkaUser resources
      - kafkausers
      - kafkausers/status
    verbs:
      - get
      - list
      - watch
      - create
      - patch
      - update
      - delete
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      # The entity operator needs to be able to create events
      - create
  - apiGroups:
      - ""
    resources:
      # The entity operator user-operator needs to access and manage secrets to store generated credentials
      - secrets
    verbs:
      - get
      - list
      - watch
      - create
      - delete
      - patch
      - update

The strimzi-kafka-client ClusterRole 代表组件所需的访问,这些客户端使用客户端机架感知能力。如 委派的特权 部分所述,Cluster Operator 还需要此角色才能委派此访问权限。

Cluster Operator 的 ClusterRole,允许它将对 OpenShift 节点的访问委托给基于 Kafka 客户端的 pod

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: strimzi-kafka-client
  labels:
    app: strimzi
rules:
  - apiGroups:
      - ""
    resources:
      # The Kafka clients (Connect, Mirror Maker, etc.) require "get" permissions to view the node they are on
      # This information is used to generate a Rack ID (client.rack option) that is used for consuming from the closest
      # replicas when enabled
      - nodes
    verbs:
      - get

5.1.2.4. ClusterRoleBindings

对于包含集群范围资源的 ClusterRole,Operator 需要 Cluster RoleBindings RoleBindings 将其 ClusterRole 与其 ServiceAccount: ClusterRoleBinding s 相关联。

Cluster Operator 的 ClusterRoleBinding 示例

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: strimzi-cluster-operator
  labels:
    app: strimzi
subjects:
  - kind: ServiceAccount
    name: strimzi-cluster-operator
    namespace: myproject
roleRef:
  kind: ClusterRole
  name: strimzi-cluster-operator-global
  apiGroup: rbac.authorization.k8s.io

委派 所需的 ClusterRole 还需要 ClusterRoleBinding

Kafka 代理的 Cluster Operator 的 Cluster RoleBinding 示例

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: strimzi-cluster-operator-kafka-broker-delegation
  labels:
    app: strimzi
# The Kafka broker cluster role must be bound to the cluster operator service account so that it can delegate the cluster role to the Kafka brokers.
# This must be done to avoid escalating privileges which would be blocked by Kubernetes.
subjects:
  - kind: ServiceAccount
    name: strimzi-cluster-operator
    namespace: myproject
roleRef:
  kind: ClusterRole
  name: strimzi-kafka-broker
  apiGroup: rbac.authorization.k8s.io

用于 Kafka 客户端识别的 Cluster Operator 的 Cluster RoleBinding 示例

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: strimzi-cluster-operator-kafka-client-delegation
  labels:
    app: strimzi
# The Kafka clients cluster role must be bound to the cluster operator service account so that it can delegate the
# cluster role to the Kafka clients using it for consuming from closest replica.
# This must be done to avoid escalating privileges which would be blocked by Kubernetes.
subjects:
  - kind: ServiceAccount
    name: strimzi-cluster-operator
    namespace: myproject
roleRef:
  kind: ClusterRole
  name: strimzi-kafka-client
  apiGroup: rbac.authorization.k8s.io

包含有命名空间资源的 ClusterRole 只会使用 RoleBindings 绑定。

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: strimzi-cluster-operator
  labels:
    app: strimzi
subjects:
  - kind: ServiceAccount
    name: strimzi-cluster-operator
    namespace: myproject
roleRef:
  kind: ClusterRole
  name: strimzi-cluster-operator-namespaced
  apiGroup: rbac.authorization.k8s.io
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: strimzi-cluster-operator-entity-operator-delegation
  labels:
    app: strimzi
# The Entity Operator cluster role must be bound to the cluster operator service account so that it can delegate the cluster role to the Entity Operator.
# This must be done to avoid escalating privileges which would be blocked by Kubernetes.
subjects:
  - kind: ServiceAccount
    name: strimzi-cluster-operator
    namespace: myproject
roleRef:
  kind: ClusterRole
  name: strimzi-entity-operator
  apiGroup: rbac.authorization.k8s.io

5.1.3. 使用默认代理设置配置 Cluster Operator

如果您在 HTTP 代理上运行 Kafka 集群,您仍然可以传递数据。例如,您可以使用从代理外部推送和拉取数据的连接器运行 Kafka Connect。或者,您可以使用代理来连接授权服务器。

配置 Cluster Operator 部署以指定代理环境变量。Cluster Operator 接受标准代理配置(HTTP_PROXYHTTPS_PROXYNO_PROXY)作为环境变量。代理设置应用到所有 AMQ Streams 容器。

代理地址的格式为 http://IP-ADDRESS:PORT-NUMBER。要使用名称和密码设置代理,其格式为 http://USERNAME:PASSWORD@IP-ADDRESS:PORT-NUMBER

先决条件

此流程需要使用 OpenShift 用户帐户,该帐户可以创建自定义 ResourceDefinition、 ClusterRole 和 ClusterRoleBinding。在 OpenShift 集群中使用 Role Base Access Control(RBAC)通常意味着只有 system:admin 等 OpenShift 集群管理员才有创建、编辑和删除这些资源的权限。

流程

  1. 要向 Cluster Operator 添加代理环境变量,更新其 部署配置 (install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml)。

    Cluster Operator 的代理配置示例

    apiVersion: apps/v1
    kind: Deployment
    spec:
      # ...
      template:
        spec:
          serviceAccountName: strimzi-cluster-operator
          containers:
            # ...
            env:
            # ...
            - name: "HTTP_PROXY"
              value: "http://proxy.com" 1
            - name: "HTTPS_PROXY"
              value: "https://proxy.com" 2
            - name: "NO_PROXY"
              value: "internal.com, other.domain.com" 3
      # ...

    1
    代理服务器的地址。
    2
    代理服务器的安全地址.
    3
    直接访问的服务器的地址,作为代理服务器的例外。URL 用逗号分开。

    或者,直接编辑 Deployment

    oc edit deployment strimzi-cluster-operator
  2. 如果您更新了 YAML 文件而不是直接编辑 Deployment,请应用更改:

    oc create -f install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml

5.2. 使用主题 Operator

当您使用 KafkaTopic 资源创建、修改或删除主题时,Tpic Operator 可确保这些更改反映在 Kafka 集群中。

OpenShift 指南中的部署和升级 AMQ Streams 提供了部署 Topic Operator 的说明:

5.2.1. Kafka 主题资源

KafkaTopic 资源用于配置主题,包括分区和副本的数量。

KafkaTopic 的完整 schema 包括在 KafkaTopic schema 引用 中。

5.2.1.1. 为主题处理识别 Kafka 集群

KafkaTopic 资源包含一个标签,用于定义它所属的 Kafka 集群名称(从 Kafka 资源的名称衍生)。

例如:

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: topic-name-1
  labels:
    strimzi.io/cluster: my-cluster

该标签供主题 Operator 用于标识 KafkaTopic 资源、创建一个新主题,以及后续处理该主题。

如果标签与 Kafka 集群不匹配,主题 Operator 无法识别 KafkaTopic,且不会创建该主题。

5.2.1.2. Kafka 主题使用建议

处理主题时,应保持一致。始终在 OpenShift 中直接对 KafkaTopic 资源或主题运行。对于给定主题,避免在这两种方法之间进行定期切换。

使用反映主题性质的主题名称,并记住以后无法更改名称。

如果在 Kafka 中创建主题,请使用有效的 OpenShift 资源名称,否则 Topic Operator 将需要使用符合 OpenShift 规则的名称创建对应的 KafkaTopic

注意

OpenShift 中的标识符和名称建议在 OpenShift 社区文章中概述了标识符和名称

5.2.1.3. Kafka 主题命名约定

Kafka 和 OpenShift 分别为 Kafka 和 KafkaTopic.metadata.name 中的主题命名实施自己的验证规则。每个名称都无效。

使用 spec.topicName 属性,可以在 Kafka 中创建有效的主题,其名称对 OpenShift 中的 Kafka 主题无效。

spec.topicName 属性继承 Kafka 命名验证规则:

  • 名称不能超过 249 个字符。
  • Kafka 主题的有效字符为 ASCII 字母数字、._-
  • 该名称不能为. 或 . 但是, 可以在 名称中使用,如 exampleTopic. or .exampleTopic

不得更改 spec.topicName

例如:

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: topic-name-1
spec:
  topicName: topicName-1 1
  # ...
1
在 OpenShift 中,大写无效。

不能改为:

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: topic-name-1
spec:
  topicName: name-2
  # ...
注意

一些 Kafka 客户端应用程序(如 Kafka Streams)可以以编程方式在 Kafka 中创建主题。如果这些主题的名称具有无效的 OpenShift 资源名称,Topic Operator 会根据 Kafka 名称为其提供有效的 metadata.name。将替换无效字符,并在名称中附加一个哈希值。例如:

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: mytopic---c55e57fe2546a33f9e603caf57165db4072e827e
spec:
  topicName: myTopic
  # ...

5.2.2. 主题 Operator 主题存储

Topic Operator 使用 Kafka 将主题元数据描述为键值对。主题存储 基于 Kafka Streams 键值机制,机制使用 Kafka 主题来持久保留状态。

主题元数据缓存在内存中,并在 Topic Operator 中本地访问。从应用到本地内存中缓存的操作的更新会保留到磁盘上的备份主题存储中。主题存储将与来自 Kafka 主题或 OpenShift KafkaTopic 自定义资源的更新持续同步。以这种方式设置主题存储会快速处理操作,但如果内存缓存崩溃,它会自动从持久性存储中重新填充。

5.2.2.1. 内部主题存储主题

内部主题支持处理主题元数据。

__strimzi_store_topic
存储主题元数据的输入主题
__strimzi-topic-operator-kstreams-topic-store-changelog
保留压缩主题存储值的日志
警告

不要删除这些主题,因为它们是运行 Topic Operator 的关键。

5.2.2.2. 从 ZooKeeper 迁移主题元数据

在之前的 AMQ Streams 发行版中,主题元数据存储在 ZooKeeper 中。新进程删除了这个要求,将元数据放入 Kafka 集群,并在 Topic Operator 控制下。

当升级到 AMQ Streams 1.8 时,对主题存储的 Topic Operator 控制会无缝转换。元数据可以从 ZooKeeper 找到并迁移,旧存储也会被删除。

5.2.2.3. 降级到使用 ZooKeeper 存储主题元数据的 AMQ Streams 版本

如果您要恢复到早于 0.22 的 AMQ Streams 版本(使用 ZooKeeper 存储主题元数据),您仍然会将 Cluster Operator 降级到以前的版本,然后将 Kafka 代理和客户端应用程序降级到以前的 Kafka 版本。

但是,您还必须使用 kafka-admin 命令删除为主题存储创建的主题,并指定 Kafka 集群的 bootstrap 地址。例如:

oc run kafka-admin -ti --image=registry.redhat.io/amq7/amq-streams-kafka-28-rhel7:1.8.0 --rm=true --restart=Never -- ./bin/kafka-topics.sh --bootstrap-server localhost:9092 --topic __strimzi-topic-operator-kstreams-topic-store-changelog --delete && ./bin/kafka-topics.sh --bootstrap-server localhost:9092 --topic __strimzi_store_topic --delete

命令必须与用于访问 Kafka 集群的监听程序和身份验证对应。

Topic Operator 将从 Kafka 中主题的状态重建 ZooKeeper 主题元数据。

5.2.2.4. 主题 Operator 主题复制和扩展

推荐由 Topic Operator 管理的主题配置是主题复制因素 3,至少为 2 个以同步副本。

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: my-topic
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 1 1
  replicas: 3 2
  config:
    min.insync.replicas=2 3
  #...
1
主题的分区数量。通常情况下,1 分区就足够了。
2
副本主题分区的数量。目前,这无法在 KafkaTopic 资源中 更改,但可以使用 kafka-reassign-partitions.sh 工具进行修改。
3
消息必须成功写入或引发异常的最小副本分区数量。
注意

同步内副本与制作者应用的 ack 配置 结合使用。acks 配置决定消息必须复制到的追随者分区的数量,然后确认消息被确认为成功接收。Topic Operator 使用 acks=all 运行,在此情况下,所有内同步副本都必须确认消息。

当通过添加或删除代理来扩展 Kafka 集群时,不会更改复制因素配置,并且不会自动重新分配副本。但是,您可以使用 kafka-reassign-partitions.sh 工具更改复制因素,并手动将副本分配给代理。

另外,尽管 AMQ Streams 的 Cruise Control 集成无法更改主题的复制因素,但它为重新平衡 Kafka 而生成的优化结果包括传输分区副本并更改分区领导地位的命令。

5.2.2.5. 处理主题的更改

Topic Operator 需要解决的一个根本问题是没有单一的事实来源: KafkaTopic 资源和 Kafka 主题都可以独立于主题 Operator 进行修改。复杂的情况是,Topic Operator 可能无法实时观察每个末尾的更改。例如,当主题 Operator 停机时。

为解决这个问题,主题 Operator 会维护主题存储中每个主题的信息。当 Kafka 集群或 OpenShift 中发生更改时,它会同时查看其他系统和主题存储的状态,以确定需要更改什么内容才能保持所有同步。只要 Topic Operator 启动并在运行期间定期进行同样的操作。

例如,假设 Topic Operator 没有运行,并创建一个名为 my-topicKafkaTopic。当主题 Operator 启动时,主题存储不包含有关 my-topic 的信息,因此它可以推断 KafkaTopic 是在上次运行后创建的。Topic Operator 会创建与 my-topic 对应的主题,并将 my-topic 的元数据存储在主题存储中。

如果您更新 Kafka 主题配置或通过 KafkaTopic 自定义资源应用更改,则在 Kafka 集群协调后会更新主题存储。

主题存储还允许主题 Operator 管理在 Kafka 主题中更改主题配置并通过 OpenShift KafkaTopic 自定义资源 进行更新 的场景,只要更改不兼容。例如,可以对同一主题配置键进行更改,但更改不同的值。对于不兼容的更改,Kafka 配置将具有优先权,并且会相应地更新 KafkaTopic

注意

您还可以通过 oc delete -f KAFKA-TOPIC-CONFIG-FILE 命令使用 KafkaTopic 资源删除主题。要做到这一点,在 Kafka 资源的 spec.kafka.config 中必须将 delete.topic. enable 设置为 true (默认)。

5.2.3. 配置 Kafka 主题

使用 KafkaTopic 资源的属性来配置 Kafka 主题。

您可以使用 oc apply 创建或修改主题,使用 oc delete 删除现有主题。

例如:

  • oc apply -f <topic-config-file>
  • oc delete KafkaTopic <topic-name>

此流程演示了如何创建带有 10 个分区和 2 个副本的主题。

开始前

在进行更改前请考虑以下几点:

  • Kafka 不支持 通过 KafkaTopic 资源进行以下更改:

    • 使用 spec.topicName更改主题名称
    • 使用 spec.partitions减少分区大小
  • 您不能使用 spec.replicas 来更改最初指定的副本数量。
  • 使用键为主题增加 spec.partitions 将更改记录的分区方式,这在主题使用 语义分区 时特别有问题。

先决条件

流程

  1. 准备包含要创建的 KafkaTopic 的文件。

    KafkaTopic 示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: orders
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 10
      replicas: 2

    提示

    在修改主题时,您可以使用 oc get kafkatopic Order -o yaml 获取资源的当前版本

  2. 在 OpenShift 中创建 KafkaTopic 资源。

    oc apply -f TOPIC-CONFIG-FILE

5.2.4. 使用资源请求和限值配置主题 Operator

您可以将资源(如 CPU 和内存)分配给 Topic Operator,并为它消耗的资源量设置限制。

先决条件

  • Cluster Operator 正在运行。

流程

  1. 根据需要更新编辑器中的 Kafka 集群配置:

    oc edit kafka MY-CLUSTER
  2. Kafka 资源中的 spec.entityOperator.topicOperator.resources 属性中,为 Topic Operator 设置资源请求和限值。

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      # Kafka and ZooKeeper sections...
      entityOperator:
        topicOperator:
          resources:
            requests:
              cpu: "1"
              memory: 500Mi
            limits:
              cpu: "1"
              memory: 500Mi
  3. 应用新配置以创建或更新资源。

    oc apply -f KAFKA-CONFIG-FILE

5.3. 使用 User Operator

当使用 KafkaUser 资源创建、修改或删除用户时,User Operator 可确保这些更改反映在 Kafka 集群中。

OpenShift 指南中的部署和升级 AMQ Streams 提供了部署 User Operator 的说明:

有关模式的更多信息,请参阅 KafkaUser schema 参考

验证和授权对 Kafka 的访问

使用 KafkaUser 启用特定客户端用来访问 Kafka 的身份验证和授权机制。

有关使用 KafkUser 管理用户并保护对 Kafka 代理的访问的更多信息,请参阅保护对 Kafka 代理的访问。

5.3.1. 使用资源请求和限值配置 User Operator

您可以将资源(如 CPU 和内存)分配给 User Operator,并为它消耗的资源量设置限制。

先决条件

  • Cluster Operator 正在运行。

流程

  1. 根据需要更新编辑器中的 Kafka 集群配置:

    oc edit kafka MY-CLUSTER
  2. Kafka 资源中的 spec.entityOperator.userOperator.resources 属性中,为 User Operator 设置资源请求和限值。

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      # Kafka and ZooKeeper sections...
      entityOperator:
        userOperator:
          resources:
            requests:
              cpu: "1"
              memory: 500Mi
            limits:
              cpu: "1"
              memory: 500Mi

    保存文件并退出编辑器。Cluster Operator 会自动应用更改。

5.4. 使用 Prometheus 指标监控 Operator

AMQ Streams 操作器公开 Prometheus 指标数据。指标数据会被自动启用,其中包含以下相关信息:

  • 协调数
  • Operator 正在处理的自定义资源数量
  • 协调的持续时间
  • 来自操作器的 JVM 指标

另外,我们提供了一个 Grafana 仪表板示例。

如需有关 Prometheus 的更多信息,请参阅 OpenShift 指南中的 Deploying and upgrade AMQ Streams 中的 引入 Metrics to Kafka

第 6 章 Kafka Bridge

本章概述了 AMQ Streams Kafka Bridge,并帮助您开始使用 REST API 与 AMQ Streams 交互。

6.1. Kafka 网桥概述

您可以使用 AMQ Streams Kafka Bridge 作为接口,向 Kafka 集群发出特定类型的 HTTP 请求。

6.1.1. Kafka Bridge 接口

Kafka Bridge 提供了一个 RESTful 接口,允许基于 HTTP 的客户端与 Kafka 集群交互。  它提供了与 AMQ Streams 的 Web API 连接的优势,不需要客户端应用程序来解释 Kafka 协议。

API 有两个主要资源( 使用者和 主题 ),它们通过端点公开并可访问,以便与 Kafka 集群中的用户和生产者交互。资源仅与 Kafka 网桥相关,而不是与 Kafka 直接连接的消费者和生产者。

6.1.1.1. HTTP 请求

Kafka Bridge 支持对 Kafka 集群的 HTTP 请求,其方法如下:

  • 发送消息到一个主题。
  • 从主题检索消息.
  • 检索主题的分区列表。
  • 创建和删除消费者.
  • 订阅消费者了解主题,以便他们开始接收来自这些主题的信息。
  • 检索消费者订阅的主题列表。
  • 取消订阅消费者的主题.
  • 将分区分配给消费者.
  • 提交消费者偏移列表。
  • 寻找分区,以便使用者开始接受来自第一个或最后一个偏移位置的信息,或者给定的偏移位置。

这些方法提供 JSON 响应和 HTTP 响应代码错误处理。消息可以 JSON 或二进制格式发送。

客户端可以生成和使用消息,而无需使用原生 Kafka 协议。

其它资源

6.1.2. Kafka Bridge 支持的客户端

您可以使用 Kafka Bridge 将 内部和外部 HTTP 客户端应用程序与 Kafka 集群集成。

内部客户端
内部客户端是基于容器的 HTTP 客户端,与 Kafka Bridge 本身 在同一个 OpenShift 集群中运行。内部客户端可以访问在 Kafka Bridge 自定义资源中定义的主机上的 Kafka Bridge 和端口。
外部客户端
外部客户端是在 OpenShift 集群 外部 运行的 HTTP 客户端,其中部署并运行 Kafka Bridge。外部客户端可以通过 OpenShift Route、负载均衡器服务或使用 Ingress 访问 Kafka 网桥。

HTTP 内部和外部客户端集成

Internal and external HTTP producers and consumers exchange data with the Kafka brokers through the Kafka Bridge

6.1.3. 保护 Kafka 网桥

AMQ Streams 目前不为 Kafka Bridge 提供任何加密、身份验证或授权。这意味着,从外部客户端发送到 Kafka Bridge 的请求是:

  • 未加密,且必须使用 HTTP 而不是 HTTPS
  • 在没有验证的情况下发送

但是,您可以使用其他方法保护 Kafka 网桥的安全,例如:

  • 定义哪些容器集可以访问 Kafka 网桥的 OpenShift Network 策略。
  • 带有身份验证或授权的反向代理,如 OAuth2 代理。
  • API 网关.
  • 具有 TLS 终止的入口或 OpenShift 路由。

当连接到 Kafka Broker 时,Kafka Bridge 支持 TLS 加密以及 TLS 和 SASL 身份验证。在 OpenShift 集群中,您可以配置:

  • Kafka Bridge 和 Kafka 集群间的 TLS 或基于 SASL 的身份验证
  • Kafka 网桥和 Kafka 集群之间的 TLS 加密连接。

如需更多信息,请参阅 第 2.5.1 节 “配置 Kafka 网桥”

您可以使用 Kafka 代理中的 ACL 来限制可通过 Kafka Bridge 使用和生成的主题。

6.1.4. 访问 OpenShift 外部的 Kafka 网桥

部署后,AMQ Streams Kafka Bridge 只能由同一 OpenShift 集群中运行的应用程序访问。这些应用程序使用 kafka-bridge-name-bridge-service 服务来访问 API。

如果要使 Kafka Bridge 可供在 OpenShift 集群外运行的应用程序访问,您可以使用以下功能之一手动公开它:

  • LoadBalancer 或 NodePort 类型的服务
  • Ingress 资源
  • OpenShift 路由

如果您决定创建服务,请使用 选择器 中的以下标签来配置服务要将流量路由到的 pod:

  # ...
  selector:
    strimzi.io/cluster: kafka-bridge-name 1
    strimzi.io/kind: KafkaBridge
  #...
1
OpenShift 集群中 Kafka Bridge 自定义资源的名称。

6.1.5. 对 Kafka Bridge 的请求

指定数据格式和 HTTP 标头,以确保向 Kafka Bridge 提交有效的请求。

6.1.5.1. 内容类型标头

API 请求和响应正文始终编码为 JSON。

  • 在执行消费者操作时,如果存在非空正文,POST 请求必须提供以下 Content-Type 标头:

    Content-Type: application/vnd.kafka.v2+json
  • 在执行制作者操作时,POST 请求 必须提供 Content-Type 标头,指定生成的消息的 嵌入式数据格式。这可以是 json二进制

    嵌入式数据格式content-Type 标头

    JSON

    content-Type: application/vnd.kafka.json.v2+json

    二进制

    content-Type: application/vnd.kafka.binary.v2+json

嵌入式数据格式为每个消费者设置,如下一节所述。

如果 POST 请求 具有空正文,则不能 设置 Content-Type。空正文可用于创建具有默认值的消费者。

6.1.5.2. 嵌入式数据格式

嵌入式数据格式是 Kafka 消息通过 HTTP 从生产者传输到使用 Kafka 网桥的消费者的格式。支持两种嵌入的数据格式:JSON 和二进制。

在使用 /consumers/groupid 端点创建消费者时,POST 请求 正文必须指定嵌入的数据格式(JSON 或二进制)。这在 format 字段中指定,例如:

{
  "name": "my-consumer",
  "format": "binary", 1
...
}
1
二进制嵌入式数据格式.

创建使用者时指定的嵌入式数据格式必须与它将使用的 Kafka 消息的数据格式匹配。

如果您选择指定二进制嵌入式数据格式,后续制作者请求必须在请求正文中以 Base64 编码的字符串形式提供二进制数据。例如,在使用 /topics/topicname 端点发送信息时,records.value 必须采用 Base64 编码:

{
  "records": [
    {
      "key": "my-key",
      "value": "ZWR3YXJkdGhldGhyZWVsZWdnZWRjYXQ="
    },
  ]
}

制作者请求还必须提供与嵌入式数据格式对应的 Content-Type 标头,如 Content-Type: application/vnd.kafka.binary.v2+json

6.1.5.3. 消息格式

使用 /topics 端点 发送消息时,您将在请求正文中的 record 参数 中输入消息有效负载。

records 参数可以包含任何这些可选字段:

  • 消息 标头
  • 消息
  • 消息
  • 目标 分区

到 /topics 的 POST 请求示例

curl -X POST \
  http://localhost:8080/topics/my-topic \
  -H 'content-type: application/vnd.kafka.json.v2+json' \
  -d '{
    "records": [
        {
            "key": "my-key",
            "value": "sales-lead-0001"
            "partition": 2
            "headers": [
              {
                "key": "key1",
                "value": "QXBhY2hlIEthZmthIGlzIHRoZSBib21iIQ==" 1
              }
            ]
        },
    ]
}'

1
二进制格式的标头值,编码为 Base64。
6.1.5.4. 接受标头

创建消费者后,所有后续 GET 请求都必须以以下格式提供 Accept 标头:

Accept: application/vnd.kafka.EMBEDDED-DATA-FORMAT.v2+json

EMBEDDED-DATA-FORMATjson二进制

例如,当使用嵌入的 JSON 数据格式获取订阅的消费者的记录时,包括这个 Accept 标头:

Accept: application/vnd.kafka.json.v2+json

6.1.6. CORS

跨 Origin 资源共享(CORS)允许您指定在 Kafka 网桥 HTTP 配置 中访问 Kafka 集群的允许方法和原始 URL。

Kafka Bridge 的 CORS 配置示例

# ...
cors:
  allowedOrigins: "https://strimzi.io"
  allowedMethods: "GET,POST,PUT,DELETE,OPTIONS,PATCH"
  # ...

CORS 允许在不同域中的原始源之间 简单预先理解的请求

简单请求适用于使用 GETHEAD、POST 方法的标准请求。

预定义的请求会发送 HTTP OPTIONS 请求,作为检查实际请求是否安全发送的初始检查。确认后会发送实际请求。preflight 请求适用于需要更大保护的方法,如 PUTDELETE,以及使用非标准标头。

所有请求都需要其标头中有一个 Origin 值,这是 HTTP 请求的来源。

6.1.6.1. 简单请求

例如:这个简单请求标头将原始文件指定为 https://strimzi.io

Origin: https://strimzi.io

标头信息添加到请求中。

curl -v -X GET HTTP-ADDRESS/bridge-consumer/records \
-H 'Origin: https://strimzi.io'\
-H 'content-type: application/vnd.kafka.v2+json'

在 Kafka Bridge 的响应中,会返回 Access-Control-Allow-Origin 标头。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: * 1
1
返回星号(*)表示资源可以被任何域访问。
6.1.6.2. Preflighted 请求

使用 a OPTIONS 方法将初始 preflight 请求发送到 Kafka Bridge。HTTP OPTIONS 请求发送标头信息,以检查 Kafka Bridge 是否允许实际请求。

这里的 preflight 请求检查 POST 请求 是否从 https://strimzi.io 有效。

OPTIONS /my-group/instances/my-user/subscription HTTP/1.1
Origin: https://strimzi.io
Access-Control-Request-Method: POST 1
Access-Control-Request-Headers: Content-Type 2
1
Kafka Bridge 已被警告,实际请求是 POST 请求
2
实际的请求将与 Content-Type 标头一起发送。

OPTIONS 被添加到 preflight 请求的标题信息中。

curl -v -X OPTIONS -H 'Origin: https://strimzi.io' \
-H 'Access-Control-Request-Method: POST' \
-H 'content-type: application/vnd.kafka.v2+json'

Kafka Bridge 响应初始请求,以确认请求被接受。响应标头返回允许的来源、方法和标头。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://strimzi.io
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS,PATCH
Access-Control-Allow-Headers: content-type

如果原始或方法被拒绝,则返回错误消息。

实际请求不需要 Access-Control-Request-Method 标头,因为它已在 preflight 请求中确认,但它确实需要 origin 标头。

curl -v -X POST HTTP-ADDRESS/topics/bridge-topic \
-H 'Origin: https://strimzi.io' \
-H 'content-type: application/vnd.kafka.v2+json'

响应中显示允许的来源 URL。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://strimzi.io

其它资源

获取 CORS 规格

6.1.7. Kafka Bridge API 资源

有关 REST API 端点和描述的完整列表,包括请求和响应示例,请查看 Kafka Bridge API 参考

6.1.8. Kafka Bridge 部署

您可以使用 Cluster Operator 将 Kafka Bridge 部署到 OpenShift 集群中。

部署 Kafka Bridge 后,Cluster Operator 会在 OpenShift 集群中创建 Kafka Bridge 对象。对象包括 部署服务和 pod,各自名称都以 Kafka Bridge 自定义资源中指定的名称命名。

其它资源

6.2. Kafka Bridge quickstart

使用此快速入门尝试本地开发环境中的 AMQ Streams Kafka Bridge。您将学习如何:

  • 将 Kafka Bridge 部署到 OpenShift 集群
  • 使用端口转发向本地机器公开 Kafka Bridge 服务
  • 生成到 Kafka 集群中主题和分区的信息
  • 创建 Kafka 网桥消费者
  • 执行基本的消费者操作,如将消费者订阅到主题并检索您生成的信息

在这个快速启动中,HTTP 请求格式化为 curl 命令,您可以将它们复制并粘贴到您的终端。需要访问 OpenShift 集群。

确保您具有先决条件,然后按照本章中提供的顺序按照任务进行操作。

关于数据格式

在此快速入门中,您将以 JSON 格式(而非二进制)生成和使用消息。有关示例请求中使用的数据格式和 HTTP 标头的更多信息,请参阅 第 6.1.5 节 “对 Kafka Bridge 的请求”

快速启动的先决条件

  • 集群管理员对本地或远程 OpenShift 集群的访问权限。
  • 已安装 AMQ Streams。
  • 一个正在运行的 Kafka 集群,由 Cluster Operator 在 OpenShift 命名空间中部署。
  • Entity Operator 作为 Kafka 集群的一部分被部署并运行。

6.2.1. 将 Kafka Bridge 部署到 OpenShift 集群

AMQ Streams 包含一个 YAML 示例,用于指定 AMQ Streams Kafka Bridge 的配置。对此文件进行一些最小更改,然后将 Kafka Bridge 的实例部署到 OpenShift 集群。

流程

  1. 编辑 example /bridge/kafka-bridge.yaml 文件。

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaBridge
    metadata:
      name: quickstart 1
    spec:
      replicas: 1
      bootstrapServers: <cluster-name>-kafka-bootstrap:9092 2
      http:
        port: 8080
    1
    部署 Kafka Bridge 后,-bridge 会被附加到部署的名称和其他相关资源中。在本例中,Kafka Bridge 部署名为 quickstart-bridge, 随附的 Kafka Bridge 服务名为 quickstart-bridge-service
    2
    bootstrapServers 属性中,输入 Kafka 集群的名称作为 <cluster-name>
  2. 将 Kafka Bridge 部署到 OpenShift 集群:

    oc apply -f examples/bridge/kafka-bridge.yaml

    OpenShift 集群中会创建 Quickstart -bridge 部署、服务和其他相关资源。

  3. 验证 Kafka 网桥是否已成功部署:

    oc get deployments
    NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
    quickstart-bridge                  1/1     1            1          34m
    my-cluster-connect                 1/1     1            1          24h
    my-cluster-entity-operator         1/1     1            1          24h
    #...

接下来要做什么

将 Kafka Bridge 部署到 OpenShift 集群后,将 Kafka Bridge 服务公开给您的本地机器

其它资源

6.2.2. 将 Kafka Bridge 服务公开到您的本地机器

接下来,使用端口转发将 AMQ Streams Kafka Bridge 服务公开给 http://localhost:8080 上的本地机器。

注意

端口转发仅适用于开发和测试目的。

流程

  1. 列出 OpenShift 集群中 pod 的名称:

    oc get pods -o name
    
    pod/kafka-consumer
    # ...
    pod/quickstart-bridge-589d78784d-9jcnr
    pod/strimzi-cluster-operator-76bcf9bc76-8dnfm
  2. 连接到端口 8080 上的 quickstart-bridge pod:

    oc port-forward pod/quickstart-bridge-589d78784d-9jcnr 8080:8080 &
    注意

    如果本地计算机上的端口 8080 已在使用,请使用其它 HTTP 端口,如 8008

API 请求现在从本地机器的端口 8080 转发到 Kafka Bridge Pod 中的端口 8080。

6.2.3. 生成到主题和分区的消息

接下来,使用主题端点以 JSON 格式生成消息到 主题。您可以在请求正文中为消息指定目的地分区,如下所示。分区 端点 提供了一种备选方法,用于指定所有消息的单一目标分区,作为路径参数。

流程

  1. 在文本编辑器中,为带有三个分区的 Kafka 主题创建 YAML 定义。

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: bridge-quickstart-topic
      labels:
        strimzi.io/cluster: <kafka-cluster-name> 1
    spec:
      partitions: 3 2
      replicas: 1
      config:
        retention.ms: 7200000
        segment.bytes: 1073741824
    1
    部署 Kafka Bridge 的 Kafka 集群的名称。
    2
    主题的分区数量。
  2. 将文件保存到 example /topic 目录中,作为 bridge-quickstart-topic.yaml
  3. 在 OpenShift 集群中创建主题:

    oc apply -f examples/topic/bridge-quickstart-topic.yaml
  4. 使用 Kafka Bridge,为您创建的主题生成三个信息:

    curl -X POST \
      http://localhost:8080/topics/bridge-quickstart-topic \
      -H 'content-type: application/vnd.kafka.json.v2+json' \
      -d '{
        "records": [
            {
                "key": "my-key",
                "value": "sales-lead-0001"
            },
            {
                "value": "sales-lead-0002",
                "partition": 2
            },
            {
                "value": "sales-lead-0003"
            }
        ]
    }'
    • sales-lead-0001 发送至基于密钥哈希的分区。
    • sales-lead-0002 直接发送到分区 2。
    • sales-lead-0003 通过循环方法发送到 bridge-quickstart-topic 主题中的分区。
  5. 如果请求成功,Kafka Bridge 将返回一个 偏移数组,以及 200 代码 和内容类型 标头 application/vnd.kafka.v2+json。对于每条消息,偏移 阵列描述:

    • 消息发送到的分区
    • 分区的当前消息偏移

      响应示例

      #...
      {
        "offsets":[
          {
            "partition":0,
            "offset":0
          },
          {
            "partition":2,
            "offset":0
          },
          {
            "partition":0,
            "offset":1
          }
        ]
      }

接下来要做什么

在向主题和分区生成消息后,创建一个 Kafka 网桥使用者

其它资源

6.2.4. 创建 Kafka 网桥消费者

在 Kafka 集群中执行任何消费者操作前,您必须首先使用使用者端点创建 消费者。用户称为 Kafka 网桥消费者

流程

  1. 在名为 bridge-quickstart-consumer-group 的新使用者组中创建一个 Kafka 网桥使用者

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group \
      -H 'content-type: application/vnd.kafka.v2+json' \
      -d '{
        "name": "bridge-quickstart-consumer",
        "auto.offset.reset": "earliest",
        "format": "json",
        "enable.auto.commit": false,
        "fetch.min.bytes": 512,
        "consumer.request.timeout.ms": 30000
      }'
    • 用户名为 bridge-quickstart-consumer,嵌入式数据格式则设为 json
    • 定义了一些基本的配置设置:
    • 由于 enable.auto.commit 设置为 false,因此使用者不会自动向日志提交偏移。在此快速入门稍后您将手动提交偏移。

      如果请求成功,Kafka Bridge 会在响应正文返回使用者 ID(instance_id)和基本 URL(base_uri),以及 200 代码。

      响应示例

      #...
      {
        "instance_id": "bridge-quickstart-consumer",
        "base_uri":"http://<bridge-name>-bridge-service:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer"
      }

  2. 复制基本 URL(base_uri),以便在这个快速启动的其他消费者操作中使用。

接下来要做什么

现在,您已创建了 Kafka 网桥消费者,您可以为 它订阅主题

其它资源

6.2.5. 将 Kafka 网桥消费者订阅到主题

创建 Kafka 网桥消费者后,使用订阅端点将其 订阅 到一个或多个主题。订阅后,消费者开始收到生成到该主题的所有消息。

流程

  • 在向主题和分区 生成信息时,将消费者订阅您之前创建的 bridge-quickstart-topic 主题:

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/subscription \
      -H 'content-type: application/vnd.kafka.v2+json' \
      -d '{
        "topics": [
            "bridge-quickstart-topic"
        ]
    }'

    主题 数组可以包含一个主题(如下所示)或多个主题。如果要将消费者订阅与正则表达式匹配的多个主题,您可以使用 topic_pattern 字符串而不是 主题 数组。

    如果请求成功,Kafka Bridge 只会返回 204 (No Content)代码。

接下来要做什么

在将 Kafka 网桥使用者订阅到主题后,您可以从 消费者检索消息

其它资源

6.2.6. 从 Kafka Bridge 用户检索最新信息

接下来,通过从 记录 端点请求数据,从 Kafka 网桥使用者检索最新的消息。在生产环境中,HTTP 客户端可以重复调用此端点(在循环中)。

流程

  1. 为 Kafka 网桥使用者生成其他信息,如 向主题和分区生成消息 中所述。
  2. GET 请求 提交到 记录 端点:

    curl -X GET http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/records \
      -H 'accept: application/vnd.kafka.json.v2+json'

    创建并订阅 Kafka 网桥消费者后,第一个 GET 请求将返回空响应,因为轮询操作会启动重新平衡过程来分配分区。

  3. 重复步骤二,从 Kafka Bridge consumer 检索消息。

    Kafka Bridge 返回一个消息的数组来代表响应正文中的主题名称、键、值、分区和偏移全部全部信息 以及 200 个代码。消息默认从最新的偏移检索。

    HTTP/1.1 200 OK
    content-type: application/vnd.kafka.json.v2+json
    #...
    [
      {
        "topic":"bridge-quickstart-topic",
        "key":"my-key",
        "value":"sales-lead-0001",
        "partition":0,
        "offset":0
      },
      {
        "topic":"bridge-quickstart-topic",
        "key":null,
        "value":"sales-lead-0003",
        "partition":0,
        "offset":1
      },
    #...
    注意

    如果返回空的响应,会按照 向主题和分区生成消息 中所述为消费者生成更多记录,然后尝试再次检索消息。

接下来要做什么

从 Kafka 网桥使用者检索消息后,尝试 向日志提交偏移

其它资源

6.2.7. 将偏移提交到日志

接下来,使用 偏移端点 将偏移手动提交到 Kafka Bridge使用者接收的所有消息的日志中。这是必要的,因为您在创建 Kafka Bridge 用户时,之前创建的 Kafka 网桥消费者 被配置为使用 enable.auto.commit 设置为 false

流程

  • 将偏移量提交到 bridge-quickstart-consumer 的日志:

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/offsets

    由于没有提交请求正文,将为消费者收到的所有记录提交偏移。或者,请求正文可以包含一个数组(OffsetCommitSeekList),用于指定您要提交偏移的主题和分区。

    如果请求成功,Kafka Bridge 只会返回 204 代码。

接下来要做什么

向日志提交偏移后,尝试查找要 偏移的 端点。

其它资源

6.2.8. 寻找分区的偏移

接下来,使用 位置 端点配置 Kafka 网桥使用者,以从特定偏移检索分区的消息,然后从最新的偏移中检索。这在 Apache Kafka 中称为搜索操作。

流程

  1. 为 Quickstart -bridge-topic 主题的分区 0 寻找特定的偏移:

    curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bri