在 OpenShift 中部署和管理 AMQ Streams


Red Hat AMQ Streams 2.5

在 OpenShift Container Platform 中部署和管理 AMQ Streams 2.5

摘要

使用 AMQ Streams operator 部署 Kafka 组件。配置 Kafka 组件以构建大规模消息传递网络。设置对 Kafka 集群的安全客户端访问,以及指标和距离追踪等功能。升级以使用新功能,包括最新支持的 Kafka 版本。

使开源包含更多

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。有关更多详情,请参阅我们的首席技术官 Chris Wright 提供的消息

第 1 章 部署概述

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

本指南提供有关部署和管理 AMQ Streams 的说明。部署选项和步骤使用 AMQ Streams 中包含的示例安装文件进行。虽然指南突出显示了重要的配置注意事项,但它并不涵盖所有可用选项。要深入了解 Kafka 组件配置选项,请参阅 AMQ Streams 自定义资源 API 参考

除了部署说明外,指南还提供了部署前和部署后指导。它涵盖了设置并保护对 Kafka 集群的客户端访问。另外,它探索额外的部署选项,如指标集成、分布式追踪和集群管理工具,如 Cruise Control 和 AMQ Streams Drain Cleaner。您还将发现有关管理 AMQ Streams 和微调 Kafka 配置的建议,以获得最佳性能。

AMQ Streams 和 Kafka 都提供了升级说明,以帮助保持部署最新。

AMQ Streams 设计为与所有类型的 OpenShift 集群兼容,无论其发行版无关。无论您的部署涉及公有云或私有云,还是要设置本地开发环境,本指南中的说明适用于所有情况。

1.1. AMQ Streams 自定义资源

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

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

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

1.1.1. AMQ Streams 自定义资源示例

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

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

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

注意

管理自定义资源的访问权限仅限于 AMQ Streams 管理员。如需更多信息,请参阅 第 4.5 节 “设计 AMQ Streams 管理员”

在 OpenShift 集群中,CRD 定义了一个新的资源 kind,如 kind:Kafka

Kubernetes API 服务器允许根据类型创建自定义资源,并通过 CRD 了解在添加到 OpenShift 时如何验证和存储自定义资源。

警告

删除 CustomResourceDefinition 时,该类型的自定义资源也会被删除。另外,自定义资源创建的 OpenShift 资源也会被删除,如 DeploymentPodServiceConfigMap 资源。

每个 AMQ Streams 特定的自定义资源符合为资源的类型的 CRD 定义的架构。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 的规格,包括组(域)名称、复数名称和受支持的模式版本,它们用于 URL 用于访问主题的 API。其他名称用于识别 CLI 中的实例资源。例如,oc get kafkatopic my-topicoc get kafkatopics
3
CLI 命令可以使用短名称。例如,oc get ktoc 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 自定义资源后,主题 Operator 会通知,并在 AMQ Streams 中创建相应的 Kafka 主题。

1.2. AMQ Streams operator

AMQ Streams operator 是专门构建的,具有专家操作知识,以便在 OpenShift 上有效地管理 Kafka。每个操作器都执行不同的功能。

Cluster Operator
Cluster Operator 在 OpenShift 上处理 Apache Kafka 集群的部署和管理。它自动设置 Kafka 代理和其他 Kafka 组件和资源。
Topic Operator
主题 Operator 管理 Kafka 集群中的创建、配置和删除主题。
User Operator
User Operator 管理需要访问 Kafka 代理的 Kafka 用户。

部署 AMQ Streams 时,您首先部署 Cluster Operator。然后,Cluster Operator 已准备好处理 Kafka 的部署。您还可以使用 Cluster Operator (推荐)或独立 Operator 部署 Topic Operator 和 User Operator。您可以将独立 Operator 与不是由 Cluster Operator 管理的 Kafka 集群一起使用。

主题 Operator 和 User Operator 是实体 Operator 的一部分。Cluster Operator 可以基于 Entity Operator 配置部署一个或多个 Operator。

重要

要部署独立 Operator,您需要设置环境变量以连接到 Kafka 集群。如果您使用 Cluster Operator 部署 Operator,则不需要设置这些环境变量,因为它们将由 Cluster Operator 设置。

1.2.1. 在 OpenShift 命名空间中观察 AMQ Streams 资源

Operator 在 OpenShift 命名空间中观察和管理 AMQ Streams 资源。Cluster Operator 可以监控单个命名空间、多个命名空间或 OpenShift 集群中的所有命名空间。主题 Operator 和用户 Operator 可以监视单个命名空间。

  • Cluster Operator 监视 Kafka 资源
  • 主题 Operator 监视 KafkaTopic 资源
  • User Operator 监视 KafkaUser 资源

主题 Operator 和 User Operator 只能监视命名空间中的单个 Kafka 集群。它们只能连接到单个 Kafka 集群。

如果多个主题 Operator 监视同一命名空间,则可能会出现名称冲突和主题删除。这是因为每个 Kafka 集群都使用具有相同名称的 Kafka 主题(如 __consumer_offsets)。请确定只有一个主题 Operator 会监视给定的命名空间。

当将多个用户 Operator 与单个命名空间一起使用时,带有给定用户名的用户可在多个 Kafka 集群中存在。

如果使用 Cluster Operator 部署 Topic Operator 和 User Operator,它们默认监控 Cluster Operator 部署的 Kafka 集群。您还可以使用 operator 配置中的 watchedNamespace 指定命名空间。

对于每个 Operator 的独立部署,您可以指定一个命名空间和与 Kafka 集群的连接,以便在配置中监视。

1.2.2. 管理 RBAC 资源

Cluster Operator 为需要访问 OpenShift 资源的 AMQ Streams 组件创建和管理基于角色的访问控制(RBAC)资源。

要使 Cluster Operator 正常工作,OpenShift 集群中的权限需要与 Kafka 资源交互,如 KafkaKafkaConnect,以及 ConfigMapPodDeploymentService 等受管资源。

通过以下 OpenShift RBAC 资源指定权限:

  • ServiceAccount
  • RoleClusterRole
  • RoleBindingClusterRoleBinding
1.2.2.1. 将权限委派给 AMQ Streams 组件

Cluster Operator 在名为 strimzi-cluster-operator 的服务帐户下运行。分配了集群角色,授予其为 AMQ Streams 组件创建 RBAC 资源的权限。角色绑定将集群角色绑定与服务帐户关联。

OpenShift 可防止在一个 ServiceAccount 下运行的组件授予授予 ServiceAccount 没有的另一个 ServiceAccount 特权。因为 Cluster Operator 会创建它管理的资源所需的 RoleBindingClusterRoleBinding RBAC 资源,所以它需要一个赋予同一权限的角色。

下表描述了 Cluster Operator 创建的 RBAC 资源。

表 1.1. ServiceAccount 资源
名称使用的

<cluster_name>-kafka

Kafka 代理 pod

<cluster_name>-zookeeper

ZooKeeper pod

<cluster_name>-cluster-connect

Kafka Connect pod

<cluster_name>-mirror-maker

MirrorMaker pod

<cluster_name>-mirrormaker2

MirrorMaker 2 pod

<cluster_name>-bridge

Kafka Bridge pod

<cluster_name>-entity-operator

Entity Operator

表 1.2. ClusterRole 资源
名称使用的

strimzi-cluster-operator-namespaced

Cluster Operator

strimzi-cluster-operator-global

Cluster Operator

strimzi-cluster-operator-leader-election

Cluster Operator

strimzi-kafka-broker

Cluster Operator,机架功能(使用时)

strimzi-entity-operator

Cluster Operator, Topic Operator, User Operator

strimzi-kafka-client

Cluster Operator,用于机架感知的 Kafka 客户端

表 1.3. ClusterRoleBinding 资源
名称使用的

strimzi-cluster-operator

Cluster Operator

strimzi-cluster-operator-kafka-broker-delegation

Cluster Operator,用于机架感知的 Kafka 代理

strimzi-cluster-operator-kafka-client-delegation

Cluster Operator,用于机架感知的 Kafka 客户端

表 1.4. Rolebinding 资源
名称使用的

strimzi-cluster-operator

Cluster Operator

strimzi-cluster-operator-kafka-broker-delegation

Cluster Operator,用于机架感知的 Kafka 代理

1.2.2.2. 使用一个 ServiceAccount 运行 Cluster Operator

Cluster Operator 最好使用 ServiceAccount 运行。

Cluster Operator 的 ServiceAccount 示例

apiVersion: v1
kind: ServiceAccount
metadata:
  name: strimzi-cluster-operator
  labels:
    app: strimzi

然后,Operator 的部署需要在 spec.template.spec.serviceAccountName 中指定。

Cluster Operator 的 Deployment 的部分示例

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:
    metadata:
      labels:
        name: strimzi-cluster-operator
        strimzi.io/kind: cluster-operator
    spec:
      serviceAccountName: strimzi-cluster-operator
      # ...

1.2.2.3. ClusterRole 资源

Cluster Operator 使用 ClusterRole 资源来提供对资源所需的访问权限。根据 OpenShift 集群设置,可能需要集群管理员来创建集群角色。

注意

只有在创建 ClusterRole 资源时才需要集群管理员权限。Cluster Operator 不会在集群管理员帐户下运行。

ClusterRole 资源遵循 最小特权原则,并只包含 Cluster Operator 操作 Kafka 组件集群所需的权限。第一个分配的权限集允许 Cluster Operator 管理 OpenShift 资源,如 DeploymentPodConfigMap

Cluster Operator 需要所有集群角色才能委派权限。

Cluster Operator 使用 strimzi-cluster-operator-namespacedstrimzi-cluster-operator-global 集群角色来授予命名空间范围的资源级别和集群范围的资源级别的权限。

Cluster Operator 的带有命名空间资源的 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: strimzi-cluster-operator-namespaced
  labels:
    app: strimzi
rules:
  # Resources in this role are used by the operator based on an operand being deployed in some namespace. When needed, you
  # can deploy the operator as a cluster-wide operator. But grant the rights listed in this role only on the namespaces
  # where the operands will be deployed. That way, you can limit the access the operator has to other namespaces where it
  # does not manage any clusters.
  - 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:
      - "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:
      - "" # legacy core events api, used by topic operator
      - "events.k8s.io" # new events api, used by cluster operator
    resources:
      # The cluster operator needs to be able to create events and delegate permissions to do so
      - events
    verbs:
      - create
  - apiGroups:
      # Kafka Connect Build on OpenShift requirement
      - build.openshift.io
    resources:
      - buildconfigs
      - buildconfigs/instantiate
      - builds
    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:
      - image.openshift.io
    resources:
      # The cluster operator needs to verify the image stream when used for Kafka Connect image build
      - imagestreams
    verbs:
      - get
  - 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

strimzi-cluster-operator-leader-election 集群角色代表领导选举机制所需的权限。

带有领导选举权限的 ClusterRole

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: strimzi-cluster-operator-leader-election
  labels:
    app: strimzi
rules:
  - apiGroups:
      - coordination.k8s.io
    resources:
      # The cluster operator needs to access and manage leases for leader election
      # The "create" verb cannot be used with "resourceNames"
      - leases
    verbs:
      - create
  - apiGroups:
      - coordination.k8s.io
    resources:
      # The cluster operator needs to access and manage leases for leader election
      - leases
    resourceNames:
      # The default RBAC files give the operator only access to the Lease resource names strimzi-cluster-operator
      # If you want to use another resource name or resource namespace, you have to configure the RBAC resources accordingly
      - strimzi-cluster-operator
    verbs:
      - get
      - list
      - watch
      - delete
      - patch
      - update

strimzi-kafka-broker 集群角色代表使用机架感知的 Kafka pod 中 init 容器所需的访问。

名为 strimzi-<cluster_name>-kafka-init 的角色绑定会为 <cluster_name>-kafka 服务账户分配访问集群内使用 strimzi-kafka-broker 角色的节点。如果没有使用 rack 功能,且集群没有通过 nodeport 公开,则不会创建绑定。

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

strimzi-entity-operator 集群角色代表 Topic Operator 和 User Operator 所需的访问权限。

主题 Operator 生成带有状态信息的 OpenShift 事件,因此 & lt;cluster_name> -entity-operator 服务帐户绑定到 strimzi-entity-operator 角色,该角色通过 strimzi-entity-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

strimzi-kafka-client 集群角色代表使用机架感知的 Kafka 客户端所需的访问。

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

1.2.2.4. ClusterRoleBinding 资源

Cluster Operator 使用 ClusterRoleBindingRoleBinding 资源将其 ClusterRoleServiceAccount 相关联:包含集群范围资源的集群角色需要集群角色绑定。

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

委派权限时使用的集群角色还需要集群角色绑定:

Cluster Operator 和 Kafka 代理机架意识的 ClusterRoleBinding 示例

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

Cluster Operator 和 Kafka 客户端的 ClusterRoleBinding 示例

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

仅包含命名空间的资源的集群角色仅使用角色绑定绑定。

Cluster Operator 的 RoleBinding 示例

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

Cluster Operator 和 Kafka 代理机架感知的 RoleBinding 示例

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

1.3. 使用 Kafka Bridge 与 Kafka 集群连接

您可以使用 AMQ Streams Kafka Bridge API 创建和管理消费者,并通过 HTTP 发送和接收记录,而不是原生 Kafka 协议。

设置 Kafka Bridge 时,您可以配置对 Kafka 集群的 HTTP 访问。然后,您可以使用 Kafka Bridge 来生成和消费来自集群的消息,以及通过其 REST 接口执行其他操作。

其他资源

1.4. 无缝 FIPS 支持

联邦信息处理标准(FIPS)是计算机安全和互操作性的标准。当在启用了 FIPS 的 OpenShift 集群上运行 AMQ Streams 时,AMQ Streams 容器镜像中使用的 OpenJDK 会自动切换到 FIPS 模式。在版本 2.4 中,AMQ Streams 可以在启用了 FIPS 的 OpenShift 集群上运行,而无需更改或特殊配置。它只使用 OpenJDK 中的 FIPS 兼容安全库。

最小密码长度

在 FIPS 模式下运行时,SCRAM-SHA-512 密码至少需要 32 个字符。从 AMQ Streams 2.4 中,AMQ Streams User Operator 中的默认密码长度也被设置为 32 个字符。如果您的 Kafka 集群带有使用小于 32 个字符的密码长度的自定义配置,则需要更新您的配置。如果您有少于 32 个字符的密码,则需要重新生成具有所需长度的密码。例如,您可以通过删除用户 secret 并等待 User Operator 创建具有适当长度的新密码来完成此操作。

重要

如果使用启用了 FIPS 的 OpenShift 集群,与常规 OpenShift 集群相比,可能会遇到更高的内存消耗。为了避免任何问题,我们建议将内存请求增加到至少 512Mi。

1.5. 文档约定

用户替换的值

用户替换的值(也称为 可替换值 )以尖括号(< >)一同显示。下划线(_)用于多词值。如果值引用代码或命令,也使用 monospace

例如,以下代码显示 &lt ;my_namespace > 必须替换为正确的命名空间名称:

sed -i 's/namespace: .*/namespace: <my_namespace>' install/cluster-operator/*RoleBinding*.yaml

1.6. 其他资源

第 2 章 AMQ Streams 安装方法

您可以通过两种方式将 AMQ Streams 在 OpenShift 4.10 上安装到 4.14。

安装方法Description

安装工件 (YAML 文件)

AMQ Streams 软件下载页面下载 Red Hat AMQ Streams 2.5 OpenShift Installation and Example Files。使用 oc 将 YAML 安装工件部署到 OpenShift 集群。首先,将 Cluster Operator 从 install/cluster-operator 部署到单个命名空间、多个命名空间或所有命名空间。

您还可以使用 install/ 工件来部署以下内容:

  • AMQ Streams 管理员角色(strimzi-admin)
  • 独立主题 Operator (topic-operator)
  • 独立用户 Operator (user-operator)
  • AMQ Streams Drain Cleaner (drain-cleaner)

OperatorHub

使用 OperatorHub 中的 AMQ Streams Operator 将 AMQ Streams 部署到单个命名空间或所有命名空间。

要获得最大的灵活性,请选择安装工件方法。OperatorHub 方法提供了一个标准配置,可让您利用自动更新。

注意

不支持使用 Helm 安装 AMQ Streams。

第 3 章 使用 AMQ Streams 部署的内容

为使用 AMQ Streams 分发的 OpenShift 提供了 Apache Kafka 组件。Kafka 组件通常作为集群运行,以实现高可用性。

使用 Kafka 组件的典型部署可能包括:

  • 代理节点的 Kafka 集群
  • 复制 ZooKeeper 实例的 zookeeper 集群
  • 用于外部数据连接的 Kafka 连接 集群
  • Kafka MirrorMaker 集群在二级集群中镜像 Kafka 集群
  • Kafka Exporter 来提取额外的 Kafka 指标数据以进行监控。
  • Kafka Bridge 为 Kafka 集群发出基于 HTTP 的请求
  • Cruise Control 在代理节点间重新平衡主题分区

并非所有组件都是必须的,但最少需要 Kafka 和 ZooKeeper。有些组件可以在没有 Kafka 的情况下部署,如 MirrorMaker 或 Kafka Connect。

3.1. 部署顺序

部署到 OpenShift 集群所需的顺序如下:

  1. 部署 Cluster Operator 来管理 Kafka 集群
  2. 使用 ZooKeeper 集群部署 Kafka 集群,并在部署中包含 Topic Operator 和 User Operator
  3. (可选)部署:

    • 如果没有使用 Kafka 集群部署它们,则主题 Operator 和用户 Operator
    • Kafka Connect
    • Kafka MirrorMaker
    • Kafka Bridge
    • 用于监控指标的组件

Cluster Operator 为组件创建 OpenShift 资源,如 DeploymentServicePod 资源。部署时,OpenShift 资源的名称会附加为组件指定的名称。例如,名为 my-kafka-cluster 的 Kafka 集群有一个名为 my-kafka-cluster-kafka 的服务。

第 4 章 准备 AMQ Streams 部署

通过完成任何必要的部署前任务,准备 AMQ Streams 部署。根据您的具体要求执行必要的准备步骤,如下所示:

注意

要在本指南中运行命令,您的集群用户必须有权管理基于角色的访问控制(RBAC)和 CRD。

4.1. 部署先决条件

要部署 AMQ Streams,您需要以下内容:

  • OpenShift 4.10 到 4.14 集群。

    AMQ Streams 基于 Strimzi 0.36.x。

  • oc 命令行工具已安装并配置为连接到正在运行的集群。

4.2. 下载 AMQ Streams 发行工件

要使用部署文件安装 AMQ Streams,请从 AMQ Streams 软件下载页面 下载并解压文件。

AMQ Streams 发行版本工件包括示例 YAML 文件,可帮助您将 AMQ Streams 组件部署到 OpenShift,执行通用操作和配置 Kafka 集群。

使用 oc 从下载的 ZIP 文件的 install/cluster-operator 文件夹中部署 Cluster Operator。有关部署和配置 Cluster Operator 的更多信息,请参阅 第 6.2 节 “部署 Cluster Operator”

另外,如果要使用带有不是由 AMQ Streams Cluster Operator 管理的 Kafka 集群的独立安装主题和用户 Operator,您可以从 install/topic-operatorinstall/user-operator 文件夹部署它们。

注意

AMQ Streams 容器镜像也通过 红帽生态系统目录 提供。但是,我们建议您使用提供的 YAML 文件来部署 AMQ Streams。

4.3. 将容器镜像推送到您自己的 registry

AMQ Streams 的容器镜像 Red Hat Ecosystem Catalog 提供。AMQ Streams 提供的安装 YAML 文件将直接 从红帽生态系统目录拉取镜像

如果您无法访问 红帽生态系统目录 或希望使用您自己的容器存储库,请执行以下操作:

  1. 拉取此处列出的 所有容器镜像
  2. 将其推送到您自己的 registry 中
  3. 更新安装 YAML 文件中的镜像名称
注意

发行版本支持的每个 Kafka 版本均有单独的镜像。

容器镜像namespace/RepositoryDescription

Kafka

  • registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1
  • registry.redhat.io/amq-streams/kafka-34-rhel8:2.5.1

用于运行 Kafka 的 AMQ Streams 镜像,包括:

  • Kafka Broker
  • Kafka Connect
  • Kafka MirrorMaker
  • ZooKeeper
  • TLS Sidecars
  • Sything Control

Operator

  • registry.redhat.io/amq-streams/strimzi-rhel8-operator:2.5.1

用于运行 Operator 的 AMQ Streams 镜像:

  • Cluster Operator
  • Topic Operator
  • User Operator
  • Kafka Initializer

Kafka Bridge

  • registry.redhat.io/amq-streams/bridge-rhel8:2.5.1

用于运行 AMQ Streams Kafka Bridge 的 AMQ Streams 镜像

AMQ Streams Drain Cleaner

  • registry.redhat.io/amq-streams/drain-cleaner-rhel8:2.5.1

用于运行 AMQ Streams Drain Cleaner 的 AMQ Streams 镜像

4.4. 创建用于向容器镜像 registry 进行身份验证的 pull secret

AMQ Streams 提供的安装 YAML 文件直接 从红帽生态系统目录拉取容器镜像。如果 AMQ Streams 部署需要身份验证,请在 secret 中配置身份验证凭据并将其添加到安装 YAML 中。

注意

通常不需要身份验证,但可能会在某些平台上请求。

先决条件

  • 您需要您的红帽用户名和密码或红帽 registry 服务帐户中的登录详情。
注意

您可以使用您的红帽订阅 从红帽客户门户 创建 registry 服务帐户。

流程

  1. 创建包含登录详情和从中拉取 AMQ Streams 镜像的容器 registry 的 pull secret:

    oc create secret docker-registry <pull_secret_name> \
        --docker-server=registry.redhat.io \
        --docker-username=<user_name> \
        --docker-password=<password> \
        --docker-email=<email>

    添加您的用户名和密码。电子邮件地址是可选的。

  2. 编辑 install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml 部署文件,以使用 STRIMZI_IMAGE_PULL_SECRET 环境变量指定 pull secret:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: strimzi-cluster-operator
    spec:
      # ...
      template:
        spec:
          serviceAccountName: strimzi-cluster-operator
          containers:
            # ...
            env:
              - name: STRIMZI_IMAGE_PULL_SECRETS
                value: "<pull_secret_name>"
    # ...

    secret 适用于 Cluster Operator 创建的所有 pod。

4.5. 设计 AMQ Streams 管理员

AMQ Streams 提供用于配置部署的自定义资源。默认情况下,查看、创建、编辑和删除这些资源的权限仅限于 OpenShift 集群管理员。AMQ Streams 提供了两个集群角色,可用于为其他用户分配这些权限:

  • strimzi-view 允许用户查看和列出 AMQ Streams 资源。
  • strimzi-admin 还允许用户创建、编辑或删除 AMQ Streams 资源。

安装这些角色时,它们将自动聚合(添加)这些权限到默认的 OpenShift 集群角色。strimzi-view 聚合到 view 角色,strimzi-admin 聚合到 editadmin 角色。由于聚合,您可能不需要将这些角色分配给已经具有类似权限的用户。

以下流程演示了如何分配允许非集群管理员管理 AMQ Streams 资源的 strimzi-admin 角色。

系统管理员可在部署 Cluster Operator 后指定 AMQ Streams 管理员。

先决条件

  • 用于管理 CRD 的 AMQ Streams 自定义资源定义(CRD)和基于角色的访问控制(RBAC)资源已使用 Cluster Operator 部署

流程

  1. 在 OpenShift 中创建 strimzi-viewstrimzi-admin 集群角色。

    oc create -f install/strimzi-admin
  2. 如果需要,请为需要它们的用户分配提供访问权限的角色。

    oc create clusterrolebinding strimzi-admin --clusterrole=strimzi-admin --user=user1 --user=user2

第 5 章 使用 Web 控制台从 OperatorHub 安装 AMQ Streams

在 OpenShift Container Platform Web 控制台中,从 OperatorHub 安装 AMQ Streams Operator。

本节中的步骤演示了如何:

5.1. 从 OperatorHub 安装 AMQ Streams Operator

您可以使用 OpenShift Container Platform Web 控制台中的 OperatorHub 安装并订阅 AMQ Streams Operator。

此流程描述了如何创建项目,并将 AMQ Streams Operator 安装到该项目中。项目是命名空间的表示。对于可管理性,最好使用命名空间来分隔功能。

警告

确保使用正确的更新频道。如果您位于受支持的 OpenShift 版本,则默认 stable 频道安装 AMQ Streams 通常是安全的。但是,我们不推荐在 stable 频道中启用自动更新。自动升级将在升级前跳过所有必要的步骤。仅在特定于版本的频道中使用自动升级。

先决条件

  • 使用具有 cluster-adminstrimzi-admin 权限的账户访问 OpenShift Container Platform Web 控制台。

流程

  1. 在 OpenShift Web 控制台中进入到 Home > Projects 页面,再创建一个用于安装的项目(命名空间)。

    在这个示例中,我们使用名为 amq-streams-kafka 的项目。

  2. 进入 Operators > OperatorHub 页面。
  3. Filter by keyword 框中滚动或输入关键字以查找 AMQ Streams operator。

    operator 位于 Streaming 和 Messaging 目录中。

  4. AMQ Streams 显示 Operator 信息。
  5. 阅读有关 Operator 的信息,再点 Install
  6. Install Operator 页面中,从以下安装和更新选项中选择:

    • 更新频道 :选择 Operator 的更新频道。

      • (默认) stable 频道包含所有最新的更新和发行版本,包括主版本、次版本和微版本,这些版本被认为经过充分测试和稳定。
      • amq-streams-X.x 频道包含主发行版本的次要和微版本更新,其中 X 是主版本的版本号。
      • amq-streams-X.Y.x 频道包含次要发行本版本的微版本更新,其中 X 是主版本的版本号,Y 是次版本号。
    • Installation Mode :选择您创建的项目,以便在特定命名空间中安装 Operator。

      您可以将 AMQ Streams Operator 安装到集群中的所有命名空间(默认选项)或特定命名空间。我们建议您将特定命名空间专用于 Kafka 集群和其他 AMQ Streams 组件。

    • 更新批准 :默认情况下,AMQ Streams Operator 由 Operator Lifecycle Manager (OLM)自动升级到最新的 AMQ Streams 版本。另外,如果您希望手动批准将来的升级,请选择 Manual。如需有关操作器的更多信息,请参阅 OpenShift 文档
  7. Install 将 Operator 安装到所选命名空间中。

    AMQ Streams Operator 将 Cluster Operator、CRD 和基于角色的访问控制(RBAC)资源部署到所选命名空间中。

  8. Operator 就绪可用后,进入 Operators > Installed Operators 来验证 Operator 是否已安装到所选命名空间中。

    状态将显示为 Succeeded

    现在,您可以使用 AMQ Streams operator 部署 Kafka 组件,从 Kafka 集群开始。

注意

如果您进入到 Workloads > Deployments,您可以查看 Cluster Operator 和 Entity Operator 的部署详情。Cluster Operator 的名称包含一个版本号:amq-streams-cluster-operator-<version>。使用 AMQ Streams 安装工件部署 Cluster Operator 时的名称不同。在本例中,名称是 strimzi-cluster-operator

5.2. 使用 AMQ Streams operator 部署 Kafka 组件

在 Openshift 上安装时,AMQ Streams Operator 使 Kafka 组件可从用户界面安装。

以下 Kafka 组件可用于安装:

  • Kafka
  • Kafka Connect
  • Kafka MirrorMaker
  • Kafka MirrorMaker 2
  • Kafka 主题
  • Kafka 用户
  • Kafka Bridge
  • Kafka Connector
  • Kafka Rebalance

您可以选择组件并创建实例。您至少创建一个 Kafka 实例。这个步骤描述了如何使用默认设置创建 Kafka 实例。您可以在执行安装前配置默认安装规格。

创建其他 Kafka 组件实例的过程相同。

先决条件

流程

  1. 在 Web 控制台中导航到 Operators &gt ; Installed Operators 页面,然后点击 AMQ Streams 来显示 Operator 详情。

    Provided APIs 中,您可以创建 Kafka 组件的实例。

  2. Kafka 下的 Create instance 创建 Kafka 实例。

    默认情况下,您将创建一个名为 my-cluster 的 Kafka 集群,它有三个 Kafka 代理节点和三个 ZooKeeper 节点。集群使用临时存储。

  3. Create 开始安装 Kafka。

    等待状态变为 Ready

第 6 章 使用安装工件部署 AMQ Streams

为部署 AMQ Streams 准备您的环境,您可以将 AMQ Streams 部署到 OpenShift 集群。使用由发行工件提供的安装文件。

AMQ Streams 基于 Strimzi 0.36.x。您可以将 AMQ Streams 2.5 在 OpenShift 4.10 上部署到 4.14。

使用安装文件部署 AMQ Streams 的步骤如下:

  1. 部署 Cluster Operator
  2. 使用 Cluster Operator 部署以下内容:

  3. 另外,还可根据要求部署以下 Kafka 组件:

注意

要在本指南中运行命令,OpenShift 用户必须具有管理基于角色的访问控制(RBAC)和 CRD 的权限。

6.1. 基本部署路径

您可以设置一个部署,其中 AMQ Streams 管理同一命名空间中的单个 Kafka 集群。您可以使用此配置进行开发或测试。或者,您可以在生产环境中使用 AMQ Streams 来管理不同命名空间中的多个 Kafka 集群。

任何 AMQ Streams 部署的第一步是使用 install/cluster-operator 文件安装 Cluster Operator。

单个命令应用 cluster-operator 文件夹中的所有安装文件: oc apply -f ./install/cluster-operator

该命令设置您需要创建和管理 Kafka 部署的所有内容,包括:

  • Cluster Operator (部署ConfigMap)
  • AMQ Streams CRD (CustomResourceDefinition)
  • RBAC 资源(ClusterRoleClusterRoleBindingRoleBinding)
  • Service account (ServiceAccount)

基本部署路径如下:

  1. 下载发行工件
  2. 创建用于部署 Cluster Operator 的 OpenShift 命名空间
  3. 部署 Cluster Operator

    1. 更新 install/cluster-operator 文件,以使用为 Cluster Operator 创建的命名空间
    2. 安装 Cluster Operator 以监视一个、多个命名空间或所有命名空间
  4. 创建 Kafka 集群

之后,您可以部署其他 Kafka 组件并设置对部署的监控。

6.2. 部署 Cluster Operator

Cluster Operator 负责在 OpenShift 集群中部署和管理 Kafka 集群。

当 Cluster Operator 运行时,它将开始监视 Kafka 资源的更新。

默认情况下,部署了 Cluster Operator 的单一副本。您可以使用领导选举机制添加副本,以便在出现问题时有其他 Cluster Operator 处于待机状态。如需更多信息,请参阅 第 8.5.3 节 “使用领导选举机制运行多个 Cluster Operator 副本”

6.2.1. 指定 Cluster Operator 监视的命名空间

Cluster Operator 监视部署了 Kafka 资源的命名空间中的更新。部署 Cluster Operator 时,您可以指定要在 OpenShift 集群中监视的命名空间。您可以指定以下命名空间:

监视多个所选命名空间会因为增加处理开销而对性能有影响。要优化命名空间监控的性能,通常建议监视单个命名空间或监控整个集群。监控单个命名空间允许集中监控特定于命名空间的资源,而监控所有命名空间则提供所有命名空间中集群资源的全面视图。

Cluster Operator 监视对以下资源的更改:

  • Kafka 集群的 Kafka。
  • Kafka Connect 集群的 KafkaConnect
  • KafkaConnector 用于在 Kafka Connect 集群中创建和管理连接器。
  • Kafka MirrorMaker 实例的 KafkaMirrorMaker。
  • Kafka MirrorMaker 2 实例的 KafkaMirrorMaker2
  • Kafka Bridge 实例的 KafkaBridge
  • Cruise Control 优化请求的 KafkaRebalance

在 OpenShift 集群中创建其中一个资源时,Operator 会从资源获取集群描述,并通过创建必要的 OpenShift 资源(如 Deployment、Pod、服务和 ConfigMap)开始为资源创建新集群。

每次更新 Kafka 资源时,Operator 都会对为资源组成集群的 OpenShift 资源执行对应的更新。

资源会被修补或删除,然后重新创建,以便资源反映集群的所需状态。此操作可能会导致滚动更新可能会导致服务中断。

删除资源时,操作器会取消部署集群并删除所有相关 OpenShift 资源。

注意

虽然 Cluster Operator 可以监控 OpenShift 集群中的一个、多个或所有命名空间,但主题 Operator 和 User Operator 会监视单个命名空间中的 KafkaTopicKafkaUser 资源。如需更多信息,请参阅 第 1.2.1 节 “在 OpenShift 命名空间中观察 AMQ Streams 资源”

6.2.2. 部署 Cluster Operator 以观察单个命名空间

此流程演示了如何部署 Cluster Operator 以监视 OpenShift 集群中的单个命名空间中的 AMQ Streams 资源。

先决条件

  • 您需要具有权限的帐户来创建和管理 CustomResourceDefinition 和 RBAC (ClusterRoleRoleBinding)资源。

流程

  1. 编辑 AMQ Streams 安装文件,以使用 Cluster Operator 将安装到的命名空间。

    例如,在此过程中,Cluster Operator 被安装到命名空间 my-cluster-operator-namespace 中。

    在 Linux 中,使用:

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

    在 MacOS 中,使用:

    sed -i '' 's/namespace: .*/namespace: my-cluster-operator-namespace/' install/cluster-operator/*RoleBinding*.yaml
  2. 部署 Cluster Operator:

    oc create -f install/cluster-operator -n my-cluster-operator-namespace
  3. 检查部署的状态:

    oc get deployments -n my-cluster-operator-namespace

    输出显示部署名称和就绪度

    NAME                      READY  UP-TO-DATE  AVAILABLE
    strimzi-cluster-operator  1/1    1           1

    READY 显示就绪/预期的副本数。当 AVAILABLE 输出显示为 1 时,部署成功。

6.2.3. 部署 Cluster Operator 以观察多个命名空间

此流程演示了如何部署 Cluster Operator,以便在 OpenShift 集群中的多个命名空间中监视 AMQ Streams 资源。

先决条件

  • 您需要具有权限的帐户来创建和管理 CustomResourceDefinition 和 RBAC (ClusterRoleRoleBinding)资源。

流程

  1. 编辑 AMQ Streams 安装文件,以使用 Cluster Operator 将安装到的命名空间。

    例如,在此过程中,Cluster Operator 被安装到命名空间 my-cluster-operator-namespace 中。

    在 Linux 中,使用:

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

    在 MacOS 中,使用:

    sed -i '' 's/namespace: .*/namespace: my-cluster-operator-namespace/' install/cluster-operator/*RoleBinding*.yaml
  2. 编辑 install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml 文件,以添加 Cluster Operator 将监视到 STRIMZI_NAMESPACE 环境变量的所有命名空间的列表。

    例如,在此过程中,Cluster Operator 会监视 watched-namespace-1,watched-namespace-2,watched-namespace-3

    apiVersion: apps/v1
    kind: Deployment
    spec:
      # ...
      template:
        spec:
          serviceAccountName: strimzi-cluster-operator
          containers:
          - name: strimzi-cluster-operator
            image: registry.redhat.io/amq-streams/strimzi-rhel8-operator:2.5.1
            imagePullPolicy: IfNotPresent
            env:
            - name: STRIMZI_NAMESPACE
              value: watched-namespace-1,watched-namespace-2,watched-namespace-3
  3. 对于列出的每个命名空间,请安装 RoleBindings

    在这个示例中,将这些命令的 watched-namespace 替换为在前一步中列出的命名空间,为 watched-namespace-1, watched-namespace-2, watched-namespace-3 重复这个操作:

    oc create -f install/cluster-operator/020-RoleBinding-strimzi-cluster-operator.yaml -n <watched_namespace>
    oc create -f install/cluster-operator/023-RoleBinding-strimzi-cluster-operator.yaml -n <watched_namespace>
    oc create -f install/cluster-operator/031-RoleBinding-strimzi-cluster-operator-entity-operator-delegation.yaml -n <watched_namespace>
  4. 部署 Cluster Operator:

    oc create -f install/cluster-operator -n my-cluster-operator-namespace
  5. 检查部署的状态:

    oc get deployments -n my-cluster-operator-namespace

    输出显示部署名称和就绪度

    NAME                      READY  UP-TO-DATE  AVAILABLE
    strimzi-cluster-operator  1/1    1           1

    READY 显示就绪/预期的副本数。当 AVAILABLE 输出显示为 1 时,部署成功。

6.2.4. 部署 Cluster Operator 以监视所有命名空间

此流程演示了如何部署 Cluster Operator,以便在 OpenShift 集群中的所有命名空间中监视 AMQ Streams 资源。

在这个模式中运行时,Cluster Operator 会自动管理创建的任何新命名空间中的集群。

先决条件

  • 您需要具有权限的帐户来创建和管理 CustomResourceDefinition 和 RBAC (ClusterRoleRoleBinding)资源。

流程

  1. 编辑 AMQ Streams 安装文件,以使用 Cluster Operator 将安装到的命名空间。

    例如,在此过程中,Cluster Operator 被安装到命名空间 my-cluster-operator-namespace 中。

    在 Linux 中,使用:

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

    在 MacOS 中,使用:

    sed -i '' 's/namespace: .*/namespace: my-cluster-operator-namespace/' install/cluster-operator/*RoleBinding*.yaml
  2. 编辑 install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml 文件,将 STRIMZI_NAMESPACE 环境变量的值设置为 sVirt

    apiVersion: apps/v1
    kind: Deployment
    spec:
      # ...
      template:
        spec:
          # ...
          serviceAccountName: strimzi-cluster-operator
          containers:
          - name: strimzi-cluster-operator
            image: registry.redhat.io/amq-streams/strimzi-rhel8-operator:2.5.1
            imagePullPolicy: IfNotPresent
            env:
            - name: STRIMZI_NAMESPACE
              value: "*"
            # ...
  3. 创建 ClusterRoleBindings,为 Cluster Operator 为所有命名空间赋予集群范围的访问权限。

    oc create clusterrolebinding strimzi-cluster-operator-namespaced --clusterrole=strimzi-cluster-operator-namespaced --serviceaccount my-cluster-operator-namespace:strimzi-cluster-operator
    oc create clusterrolebinding strimzi-cluster-operator-watched --clusterrole=strimzi-cluster-operator-watched --serviceaccount my-cluster-operator-namespace:strimzi-cluster-operator
    oc create clusterrolebinding strimzi-cluster-operator-entity-operator-delegation --clusterrole=strimzi-entity-operator --serviceaccount my-cluster-operator-namespace:strimzi-cluster-operator
  4. 将 Cluster Operator 部署到 OpenShift 集群。

    oc create -f install/cluster-operator -n my-cluster-operator-namespace
  5. 检查部署的状态:

    oc get deployments -n my-cluster-operator-namespace

    输出显示部署名称和就绪度

    NAME                      READY  UP-TO-DATE  AVAILABLE
    strimzi-cluster-operator  1/1    1           1

    READY 显示就绪/预期的副本数。当 AVAILABLE 输出显示为 1 时,部署成功。

6.3. 部署 Kafka

为了可以使用 Cluster Operator 管理 Kafka 集群,您必须将它部署为 Kafka 资源。AMQ Streams 提供示例部署文件来执行此操作。您可以使用这些文件同时部署主题 Operator 和 User Operator。

部署 Cluster Operator 后,使用 Kafka 资源来部署以下组件:

安装 Kafka 时,AMQ Streams 还会安装 ZooKeeper 集群并添加将 Kafka 与 ZooKeeper 连接所需的配置。

如果要尝试节点池功能的预览,您可以使用一个或多个节点池部署 Kafka 集群。节点池为一组 Kafka 节点提供配置。通过使用节点池,节点可以在同一 Kafka 集群中有不同的配置。

节点池不会被默认启用,因此您必须在使用 KafkaNodePools 功能门前启用 KafkaNodePools 功能门

如果您还没有将 Kafka 集群部署为 Kafka 资源,则无法使用 Cluster Operator 管理它。例如,这会应用到在 OpenShift 外部运行的 Kafka 集群。但是,您可以通过将其 部署为独立组件,使用 Topic Operator 和 User Operator 及 不是由 AMQ Streams 管理的 Kafka 集群。您还可以将其他 Kafka 组件与不是由 AMQ Streams 管理的 Kafka 集群部署并使用。

6.3.1. 部署 Kafka 集群

此流程演示了如何使用 Cluster Operator 将 Kafka 集群部署到 OpenShift 集群。

部署使用 YAML 文件来提供规格来创建 Kafka 资源。

AMQ Streams 提供以下示例 文件来创建 Kafka 集群:

kafka-persistent.yaml
使用三个 ZooKeeper 和三个 Kafka 节点部署持久集群。
kafka-jbod.yaml
部署具有三个 ZooKeeper 和三个 Kafka 节点的持久集群(每个都使用多个持久性卷)。
kafka-persistent-single.yaml
使用单个 ZooKeeper 节点和一个 Kafka 节点部署持久集群。
kafka-ephemeral.yaml
使用三个 ZooKeeper 和三个 Kafka 节点部署临时集群。
kafka-ephemeral-single.yaml
使用三个 ZooKeeper 节点和一个 Kafka 节点部署临时集群。

在此过程中,我们对 ephemeral(临时)persistent(持久) Kafka 集群部署使用示例。

临时集群
通常,临时(或临时)Kafka 集群适合开发和测试目的,不适用于生产环境。此部署使用 emptyDir 卷来存储代理信息(用于 ZooKeeper)和主题或分区(用于 Kafka)。使用 emptyDir 卷意味着其内容严格与 pod 生命周期相关,并在 pod 停机时被删除。
持久性集群

持久的 Kafka 集群使用持久性卷来存储 ZooKeeper 和 Kafka 数据。使用 PersistentVolumeClaim 获取 PersistentVolume,使其独立于 PersistentVolume 的实际类型。PersistentVolumeClaim 可以使用 StorageClass 来触发自动卷置备。如果没有指定 StorageClass,OpenShift 将尝试使用默认 StorageClass

以下示例显示了一些常见的持久性卷类型:

  • 如果您的 OpenShift 集群在 Amazon AWS 上运行,OpenShift 可以置备 Amazon EBS 卷
  • 如果您的 OpenShift 集群在 Microsoft Azure 上运行,OpenShift 可以置备 Azure Disk Storage 卷
  • 如果您的 OpenShift 集群在 Google Cloud 上运行,OpenShift 可以置备 Persistent Disk 卷
  • 如果您的 OpenShift 集群在裸机上运行,OpenShift 可以置备本地持久性卷

YAML 文件示例指定最新支持的 Kafka 版本,以及其支持的日志消息格式版本和 inter-broker 协议版本的配置。Kafka configinter.broker.protocol.version 属性必须是指定的 Kafka 版本 (spec.kafka.version) 支持的版本。属性表示 Kafka 集群中使用的 Kafka 协议版本。

从 Kafka 3.0.0 开始,当将 inter.broker.protocol.version 设置为 3.0 或更高版本时,log.message.format.version 选项将被忽略,不需要设置。

在升级 Kafka 时,需要对 inter.broker.protocol.version 的更新。

示例集群默认命名为 my-cluster。集群名称由资源名称定义,在部署集群后无法更改。要在部署集群前更改集群名称,请编辑相关 YAML 文件中的 Kafka 资源的 Kafka.metadata.name 属性。

默认集群名称和指定的 Kafka 版本

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    version: 3.5.0
    #...
    config:
      #...
      log.message.format.version: "3.5"
      inter.broker.protocol.version: "3.5"
  # ...

流程

  1. 创建并部署临时或持久集群。

    • 创建和部署临时集群:

      oc apply -f examples/kafka/kafka-ephemeral.yaml
    • 创建和部署持久集群:

      oc apply -f examples/kafka/kafka-persistent.yaml
  2. 检查部署的状态:

    oc get pods -n <my_cluster_operator_namespace>

    输出显示 pod 名称和就绪状态

    NAME                        READY   STATUS    RESTARTS
    my-cluster-entity-operator  3/3     Running   0
    my-cluster-kafka-0          1/1     Running   0
    my-cluster-kafka-1          1/1     Running   0
    my-cluster-kafka-2          1/1     Running   0
    my-cluster-zookeeper-0      1/1     Running   0
    my-cluster-zookeeper-1      1/1     Running   0
    my-cluster-zookeeper-2      1/1     Running   0

    my-cluster 是 Kafka 集群的名称。

    0 开始的连续索引号标识每个 Kafka 和 ZooKeeper pod。

    使用默认部署,您可以创建一个 Entity Operator 集群、3 个 Kafka pod 和 3 ZooKeeper pod。

    READY 显示就绪/预期的副本数。当 STATUS 显示为 Running 时,部署成功。

其他资源

Kafka 集群配置

6.3.2. (预览)部署 Kafka 节点池

此流程演示了如何使用 Cluster Operator 将 Kafka 节点池部署到 OpenShift 集群。节点池代表 Kafka 集群中共享相同配置的 Kafka 节点组。对于节点池中的每个 Kafka 节点,节点池中没有定义的任何配置都会继承 kafka 资源中的集群配置。

注意

节点池功能作为技术预览提供。节点池不会被默认启用,因此您必须在使用 KafkaNodePools 功能门前启用 KafkaNodePools 功能门

部署使用 YAML 文件来提供规格来创建 KafkaNodePool 资源。您可以将节点池与 Kafka 集群一起使用,该集群使用 KRaft (Kafka Raft metadata)模式或 ZooKeeper 进行集群管理。

重要

KRaft 模式在 Apache Kafka 或 AMQ Streams 中不适用于生产环境。

AMQ Streams 提供以下 示例文件,您可以使用它来创建 Kafka 节点池:

kafka.yaml
使用 3 个节点和 2 个不同的 Kafka 代理池部署 ZooKeeper。每个池都有 3 个代理。示例中的池使用不同的存储配置。
kafka-with-dual-role-kraft-nodes.yaml
使用共享代理和控制器角色的 KRaft 节点池部署 Kafka 集群。
kafka-with-kraft.yaml
部署 Kafka 集群,具有一个控制器节点池和一个代理节点池。
注意

您不需要立即开始使用节点池。如果您决定使用它们,您可以执行此处概述的步骤,以使用 KafkaNodePool 资源部署新的 Kafka 集群,或 迁移现有的 Kafka 集群

注意

如果要将现有 Kafka 集群迁移到使用节点池,请参阅 迁移现有 Kafka 集群的步骤

流程

  1. 从命令行启用 KafkaNodePools 功能门:

    oc set env deployment/strimzi-cluster-operator STRIMZI_FEATURE_GATES="+KafkaNodePools"

    或者,通过编辑 Cluster Operator Deployment 并更新 STRIMZI_FEATURE_GATES 环境变量:

    env
      - name: STRIMZI_FEATURE_GATES
        value: +KafkaNodePools

    这会更新 Cluster Operator。

    如果使用 KRaft 模式,还要启用 UseKRaft 功能门。

  2. 创建节点池。

    • 使用三个代理的两个节点池部署 Kafka 集群和 ZooKeeper 集群:

      oc apply -f examples/kafka/nodepools/kafka.yaml
    • 使用使用 dual-role 节点的单一节点池,以 KRaft 模式部署 Kafka 集群:

      oc apply -f examples/kafka/nodepools/kafka-with-dual-role-kraft-nodes.yaml
    • 使用 KRaft 模式部署 Kafka 集群,对于代理和控制节点有独立的节点池,:

      oc apply -f examples/kafka/nodepools/kafka-with-kraft.yaml
  3. 检查部署的状态:

    oc get pods -n <my_cluster_operator_namespace>

    输出显示节点池名称和就绪

    NAME                        READY   STATUS    RESTARTS
    my-cluster-entity-operator  3/3     Running   0
    my-cluster-pool-a-kafka-0   1/1     Running   0
    my-cluster-pool-a-kafka-1   1/1     Running   0
    my-cluster-pool-a-kafka-4   1/1     Running   0

    • my-cluster 是 Kafka 集群的名称。
    • pool-a 是节点池的名称。

      0 开始的连续索引号标识每个创建的 Kafka pod。如果使用 ZooKeeper,您还会看到 ZooKeeper pod。

      READY 显示就绪/预期的副本数。当 STATUS 显示为 Running 时,部署成功。

      有关部署的信息也会显示在 KafkaNodePool 资源的状态中,包括池中节点的 ID 列表。

      注意

      节点 ID 按顺序分配自集群中所有节点池中的 0 (零)。这意味着节点 ID 可能无法在特定节点池中按顺序运行。如果集群中节点 ID 序列出现差距,则会为要添加的下一个节点分配一个填充空白的 ID。缩减时,池中具有最高节点 ID 的节点会被删除。

其他资源

节点池配置

6.3.3. 使用 Cluster Operator 部署主题 Operator

此流程描述了如何使用 Cluster Operator 部署主题 Operator。可以部署主题 Operator 以在双向模式或单向模式中使用。要了解更多有关双向和单向主题管理的信息,请参阅 第 9.1 节 “主题管理模式”

注意

单向主题管理作为技术预览提供。默认情况下,不启用单向主题管理,因此您必须 启用 UnidirectionalTopicOperator 功能门 才能使用它。

您可以将 Kafka 资源的 entityOperator 属性配置为包含 topicOperator。默认情况下,Topic Operator 会监视 Cluster Operator 部署的 Kafka 集群命名空间中的 KafkaTopic 资源。您还可以使用 Topic Operator spec 中的 watchedNamespace 指定一个命名空间。单个主题 Operator 可以监视单个命名空间。一个命名空间应该只被一个主题 Operator 监视。

如果您使用 AMQ Streams 将多个 Kafka 集群部署到同一命名空间中,请只为一个 Kafka 集群启用 Topic Operator,或使用 watchedNamespace 属性配置 Topic Operator 以监视其他命名空间。

如果要将 Topic Operator 与不是由 AMQ Streams 管理的 Kafka 集群搭配使用,您必须将 Topic Operator 部署为独立组件

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

流程

  1. 编辑 Kafka 资源的 entityOperator 属性,使其包含 topicOperator

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      #...
      entityOperator:
        topicOperator: {}
        userOperator: {}
  2. 使用 EntityTopicOperatorSpec schema reference 中所述的属性配置 Topic Operator spec

    如果您希望所有属性使用默认值,请使用空对象({})。

  3. 创建或更新资源:

    oc apply -f <kafka_configuration_file>
  4. 检查部署的状态:

    oc get pods -n <my_cluster_operator_namespace>

    输出显示 pod 名称和就绪度

    NAME                        READY   STATUS    RESTARTS
    my-cluster-entity-operator  3/3     Running   0
    # ...

    my-cluster 是 Kafka 集群的名称。

    READY 显示就绪/预期的副本数。当 STATUS 显示为 Running 时,部署成功。

6.3.4. 使用 Cluster Operator 部署 User Operator

此流程描述了如何使用 Cluster Operator 部署 User Operator。

您可以将 Kafka 资源的 entityOperator 属性配置为包含 userOperator。默认情况下,User Operator 会监视 Kafka 集群部署命名空间中的 KafkaUser 资源。您还可以使用 User Operator spec 中的 watchedNamespace 指定命名空间。单个用户 Operator 可以监视单个命名空间。一个命名空间应该只被一个 User Operator 监视。

如果要将 User Operator 与不是由 AMQ Streams 管理的 Kafka 集群搭配使用,您必须将 User Operator 部署为独立组件

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

流程

  1. 编辑 Kafka 资源的 entityOperator 属性,使其包含 userOperator

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      #...
      entityOperator:
        topicOperator: {}
        userOperator: {}
  2. 使用 EntityUserOperatorSpec schema reference 中所述的属性配置 User Operator spec

    如果您希望所有属性使用默认值,请使用空对象({})。

  3. 创建或更新资源:

    oc apply -f <kafka_configuration_file>
  4. 检查部署的状态:

    oc get pods -n <my_cluster_operator_namespace>

    输出显示 pod 名称和就绪度

    NAME                        READY   STATUS    RESTARTS
    my-cluster-entity-operator  3/3     Running   0
    # ...

    my-cluster 是 Kafka 集群的名称。

    READY 显示就绪/预期的副本数。当 STATUS 显示为 Running 时,部署成功。

6.3.5. Kafka 集群资源列表

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

共享资源

cluster-name-cluster-ca
带有用于加密集群通信的 Cluster CA 私钥的 secret。
cluster-name-cluster-ca-cert
带有集群 CA 公钥的 secret。此密钥可用于验证 Kafka 代理的身份。
cluster-name-clients-ca
带有用于签署用户证书的 Clients CA 私钥的 secret
cluster-name-clients-ca-cert
带有客户端 CA 公钥的 secret。此密钥可用于验证 Kafka 用户的身份。
cluster-name-cluster-operator-certs
带有 Cluster operator 密钥的 secret,用于与 Kafka 和 ZooKeeper 通信。

Zookeeper 节点

cluster-name-zookeeper

提供给以下 ZooKeeper 资源的名称:

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

Kafka 代理

cluster-name-kafka

提供给以下 Kafka 资源的名称:

  • 用于管理 Kafka 代理 pod 的 StrimziPodSet。
  • Kafka pod 使用的服务帐户。
  • 为 Kafka 代理配置 PodDisruptionBudget。
cluster-name-kafka-idx

提供给以下 Kafka 资源的名称:

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

Entity Operator

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

cluster-name-entity-operator

提供给以下实体 Operator 资源的名称:

  • 使用主题和用户 Operator 部署。
  • Entity Operator 使用的服务帐户。
  • 网络策略管理对实体 Operator 指标的访问。
cluster-name-entity-operator-random-string
由实体 Operator 部署创建的 Pod。
cluster-name-entity-topic-operator-config
带有主题 Operator 的辅助配置的 ConfigMap。
cluster-name-entity-user-operator-config
带有用户 Operator 的辅助配置的 ConfigMap。
cluster-name-entity-topic-operator-certs
带有主题 Operator 密钥的 secret,用于与 Kafka 和 ZooKeeper 通信。
cluster-name-entity-user-operator-certs
带有用户 Operator 密钥的 secret,用于与 Kafka 和 ZooKeeper 通信。
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 导出器资源的名称:

  • 使用 Kafka 导出器进行部署。
  • 用于收集消费者滞后指标的服务。
  • Kafka Exporter 使用的服务帐户。
  • 网络策略用于管理对 Kafka 导出器指标的访问。
cluster-name-kafka-exporter-random-string
由 Kafka Exporter 部署创建的 Pod。

Sything Control

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

cluster-name-cruise-control

给定以下 Cruise 控制资源的名称:

  • 使用 Cruise Control 部署。
  • 用于与 Cruise Control 进行通信的服务。
  • Cruise Control 使用的服务帐户。
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 密钥的 secret,用于与 Kafka 和 ZooKeeper 通信。
cluster-name-network-policy-cruise-control
网络策略管理对 Cruise Control 服务的访问。

6.4. 部署 Kafka 连接

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

在 AMQ Streams 中,Kafka Connect 部署为分布式模式。Kafka Connect 也可以以独立模式工作,但 AMQ Streams 不支持它。

使用 连接器 的概念,Kafka Connect 提供了一个框架,用于将大量数据移到 Kafka 集群中,同时保持可扩展性和可靠性。

Cluster Operator 管理使用 KafkaConnector 资源部署的 Kafka Connect 集群,以及利用 KafkaConnector 资源创建的连接器。

要使用 Kafka Connect,您需要执行以下操作。

注意

术语 连接器 会互换使用,以表示在 Kafka Connect 集群或连接器类中运行的连接器实例。在本指南中,当含义从上下文中清除时,会使用术语 连接器

6.4.1. 将 Kafka Connect 部署到 OpenShift 集群

此流程演示了如何使用 Cluster Operator 将 Kafka Connect 集群部署到 OpenShift 集群。

Kafka Connect 集群部署使用可配置的节点数(也称为 worker),将连接器工作负载作为 任务 分发,以便消息流高度可扩展且可靠。

部署使用 YAML 文件来提供规格来创建 KafkaConnect 资源。

AMQ Streams 提供 示例配置文件。在此过程中,我们使用以下示例文件:

  • examples/connect/kafka-connect.yaml

流程

  1. 部署 Kafka 连接到 OpenShift 集群。使用 examples/connect/kafka-connect.yaml 文件来部署 Kafka Connect。

    oc apply -f examples/connect/kafka-connect.yaml
  2. 检查部署的状态:

    oc get pods -n <my_cluster_operator_namespace>

    输出显示部署名称和就绪度

    NAME                                 READY  STATUS   RESTARTS
    my-connect-cluster-connect-<pod_id>  1/1    Running  0

    my-connect-cluster 是 Kafka Connect 集群的名称。

    pod ID 标识创建的每个 pod。

    使用默认部署,您可以创建一个 Kafka Connect pod。

    READY 显示就绪/预期的副本数。当 STATUS 显示为 Running 时,部署成功。

6.4.2. 为多个实例配置 Kafka 连接

如果您运行多个 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 中的 Kafka Connect 集群 ID。
2
存储连接器偏移的 Kafka 主题。
3
存储连接器和任务状态配置的 Kafka 主题。
4
存储连接器和任务状态更新的 Kafka 主题。
注意

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

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

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

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

6.4.3. 添加连接器

Kafka Connect 使用连接器与其他系统集成来流传输数据。连接器是 Kafka Connector 类的实例,可以是以下类型之一:

源连接器
源连接器是一个运行时实体,它从外部系统获取数据并将其传送到 Kafka 作为信息。
sink 连接器
sink 连接器是一个运行时实体,它从 Kafka 主题获取信息并将其传送到外部系统。

Kafka Connect 使用插件架构为连接器提供实施工件。插件允许连接到其他系统,并提供额外的配置来操作数据。插件包括连接器和其他组件,如数据转换器和转换。连接器使用特定类型的外部系统运行。每个连接器都定义了其配置架构。您提供到 Kafka Connect 的配置,以在 Kafka Connect 中创建连接器实例。然后,连接器实例定义了一组用于在系统之间移动数据的任务。

使用以下方法之一将连接器插件添加到 Kafka Connect 中:

将插件添加到容器镜像后,您可以使用以下方法启动、停止和管理连接器实例:

您还可以使用这些选项创建新的连接器实例。

6.4.3.1. 自动使用连接器插件构建新容器镜像

配置 Kafka Connect,以便 AMQ Streams 会自动使用额外的连接器构建新容器镜像。您可以使用 KafkaConnect 自定义资源的 .spec.build.plugins 属性定义连接器插件。AMQ Streams 将自动下载连接器插件并将其添加到新容器镜像中。容器被推送到 .spec.build.output 中指定的容器存储库中,并在 Kafka Connect 部署中自动使用。

先决条件

您需要提供自己的容器 registry,其中可将镜像推送到、存储和拉取镜像。AMQ Streams 支持私有容器 registry 以及公共 registry,如 QuayDocker Hub

流程

  1. 通过在 .spec.build.output 中指定容器 registry 来配置 KafkaConnect 自定义资源,并在 .spec.build.plugins 中指定其他连接器:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect-cluster
    spec: 1
      #...
      build:
        output: 2
          type: docker
          image: my-registry.io/my-org/my-connect-cluster:latest
          pushSecret: my-registry-credentials
        plugins: 3
          - name: debezium-postgres-connector
            artifacts:
              - type: tgz
                url: https://repo1.maven.org/maven2/io/debezium/debezium-connector-postgres/2.1.3.Final/debezium-connector-postgres-2.1.3.Final-plugin.tar.gz
                sha512sum: c4ddc97846de561755dc0b021a62aba656098829c70eb3ade3b817ce06d852ca12ae50c0281cc791a5a131cb7fc21fb15f4b8ee76c6cae5dd07f9c11cb7c6e79
          - name: camel-telegram
            artifacts:
              - type: tgz
                url: https://repo.maven.apache.org/maven2/org/apache/camel/kafkaconnector/camel-telegram-kafka-connector/0.11.5/camel-telegram-kafka-connector-0.11.5-package.tar.gz
                sha512sum: d6d9f45e0d1dbfcc9f6d1c7ca2046168c764389c78bc4b867dab32d24f710bb74ccf2a007d7d7a8af2dfca09d9a52ccbc2831fc715c195a3634cca055185bd91
      #...
    1
    2
    (必需)推送新镜像的容器 registry 的配置。
    3
    (必需)添加到新容器镜像的连接器插件及其工件列表。每个插件必须配置至少一个 工件
  2. 创建或更新资源:

    $ oc apply -f <kafka_connect_configuration_file>
  3. 等待新容器镜像构建,并且部署 Kafka Connect 集群。
  4. 使用 Kafka Connect REST API 或 KafkaConnector 自定义资源使用您添加的连接器插件。
6.4.3.2. 使用 Kafka Connect 基础镜像中的连接器插件构建新容器镜像

使用 Kafka Connect 基础镜像中的连接器插件创建自定义 Docker 镜像,将自定义镜像添加到 /opt/kafka/plugins 目录中。

您可以使用 Red Hat Ecosystem Catalog 上的 Kafka 容器镜像作为基础镜像,使用额外的连接器插件创建自己的自定义镜像。

在启动时,Kafka Connect 的 AMQ Streams 版本会加载 /opt/kafka/plugins 目录中包含的任何第三方连接器插件。

流程

  1. 使用 registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 作为基础镜像,创建一个新的 Dockerfile

    FROM registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1
    USER root:root
    COPY ./my-plugins/ /opt/kafka/plugins/
    USER 1001

    插件文件示例

    $ tree ./my-plugins/
    ./my-plugins/
    ├── debezium-connector-mongodb
    │   ├── bson-<version>.jar
    │   ├── CHANGELOG.md
    │   ├── CONTRIBUTE.md
    │   ├── COPYRIGHT.txt
    │   ├── debezium-connector-mongodb-<version>.jar
    │   ├── debezium-core-<version>.jar
    │   ├── LICENSE.txt
    │   ├── mongodb-driver-core-<version>.jar
    │   ├── README.md
    │   └── # ...
    ├── debezium-connector-mysql
    │   ├── CHANGELOG.md
    │   ├── CONTRIBUTE.md
    │   ├── COPYRIGHT.txt
    │   ├── debezium-connector-mysql-<version>.jar
    │   ├── debezium-core-<version>.jar
    │   ├── LICENSE.txt
    │   ├── mysql-binlog-connector-java-<version>.jar
    │   ├── mysql-connector-java-<version>.jar
    │   ├── README.md
    │   └── # ...
    └── debezium-connector-postgres
        ├── CHANGELOG.md
        ├── CONTRIBUTE.md
        ├── COPYRIGHT.txt
        ├── debezium-connector-postgres-<version>.jar
        ├── debezium-core-<version>.jar
        ├── LICENSE.txt
        ├── postgresql-<version>.jar
        ├── protobuf-java-<version>.jar
        ├── README.md
        └── # ...

    COPY 命令指向要复制到容器镜像的插件文件。

    本例为 Debezium 连接器(MongoDB、MySQL 和 PostgreSQL)添加了插件,但并非所有文件都被列为 brevity。在 Kafka Connect 中运行的 Debezium 与任何其他 Kafka Connect 任务相同。

  2. 构建容器镜像。
  3. 将自定义镜像推送到容器 registry。
  4. 指向新容器镜像。

    您可以使用以下方法之一指向镜像:

    • 编辑 KafkaConnect 自定义资源的 KafkaConnect.spec.image 属性。

      如果设置,此属性会覆盖 Cluster Operator 中的 STRIMZI_KAFKA_CONNECT_IMAGES 环境变量。

      apiVersion: kafka.strimzi.io/v1beta2
      kind: KafkaConnect
      metadata:
        name: my-connect-cluster
      spec: 1
        #...
        image: my-new-container-image 2
        config: 3
          #...
      1
      2
      pod 的 docker 镜像。
      3
      配置 Kafka Connect worker (而不是连接器)。
    • 编辑 install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml 文件中的 STRIMZI_KAFKA_CONNECT_IMAGES 环境变量,然后重新安装 Cluster Operator。
6.4.3.3. 部署 KafkaConnector 资源

部署 KafkaConnector 资源来管理连接器。KafkaConnector 自定义资源提供了一种 OpenShift 原生方法来管理 Cluster Operator 连接器。您不需要发送 HTTP 请求来管理连接器,就像 Kafka Connect REST API 一样。您可以通过更新对应的 KafkaConnector 资源来管理正在运行的连接器实例,然后应用更新。Cluster Operator 更新正在运行的连接器实例的配置。您可以通过删除对应的 KafkaConnector 来删除连接器。

KafkaConnector 资源必须部署到与其链接到的 Kafka Connect 集群相同的命名空间中。

在此过程中显示的配置中,autoRestart 属性被设置为 true。这可让自动重启失败的连接器和任务。最多进行 7 个重启尝试,之后必须手动重新启动。您可以注解 KafkaConnector 资源来 重启连接器手动重启连接器任务

连接器示例

您可以使用您自己的连接器,或尝试 AMQ Streams 提供的示例。直到 Apache Kafka 3.1.0 之前,Apache Kafka 中包含文件连接器插件示例。从 Apache Kafka 的 3.1.1 和 3.2.0 版本开始,需要将示例 添加到插件路径中,作为任何其他连接器

AMQ Streams 为示例文件连接器插件提供了一个 示例 KafkaConnector 配置文件 (examples/connect/source-connector.yaml) ,它会创建以下连接器实例作为 KafkaConnector 资源:

  • 从 Kafka 许可证文件(源)读取每行的 FileStreamSourceConnector 实例,并将数据作为信息写入单个 Kafka 主题。
  • 从 Kafka 主题读取消息的 FileStreamSinkConnector 实例,并将信息写入临时文件(接收器)。

我们使用此流程使用示例文件创建连接器。

注意

示例连接器不应在生产环境中使用。

先决条件

  • Kafka Connect 部署
  • Cluster Operator 正在运行

流程

  1. 使用以下方法之一将 FileStreamSourceConnectorFileStreamSinkConnector 插件添加到 Kafka Connect 中:

  2. 在 Kafka Connect 配置中,将 strimzi.io/use-connector-resources 注解设置为 true

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect-cluster
      annotations:
        strimzi.io/use-connector-resources: "true"
    spec:
        # ...

    启用 KafkaConnector 资源后,Cluster Operator 会监视它们。

  3. 编辑 examples/connect/source-connector.yaml 文件:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnector
    metadata:
      name: my-source-connector 1
      labels:
        strimzi.io/cluster: my-connect-cluster 2
    spec:
      class: org.apache.kafka.connect.file.FileStreamSourceConnector 3
      tasksMax: 2 4
      autoRestart: 5
        enabled: true
      config: 6
        file: "/opt/kafka/LICENSE" 7
        topic: my-topic 8
        # ...
    1
    KafkaConnector 资源的名称,用作连接器的名称。使用对 OpenShift 资源有效的任何名称。
    2
    在其中创建连接器实例的 Kafka Connect 集群的名称。连接器必须部署到它们所链接的 Kafka Connect 集群相同的命名空间中。
    3
    连接器类的完整名称或别名。这应该存在于 Kafka Connect 集群使用的镜像中。
    4
    连接器可创建的最大 Kafka Connect 任务数量。
    5
    启用自动重启失败的连接器和任务。
    6
    连接器配置 作为键值对。
    7
    这个示例源连接器配置从 /opt/kafka/LICENSE 文件中读取数据。
    8
    将源数据发布到的 Kafka 主题。
  4. 在 OpenShift 集群中创建源 KafkaConnector

    oc apply -f examples/connect/source-connector.yaml
  5. 创建 examples/connect/sink-connector.yaml 文件:

    touch examples/connect/sink-connector.yaml
  6. 将以下 YAML 粘贴到 sink-connector.yaml 文件中:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnector
    metadata:
      name: my-sink-connector
      labels:
        strimzi.io/cluster: my-connect
    spec:
      class: org.apache.kafka.connect.file.FileStreamSinkConnector 1
      tasksMax: 2
      config: 2
        file: "/tmp/my-file" 3
        topics: my-topic 4
    1
    连接器类的完整名称或别名。这应该存在于 Kafka Connect 集群使用的镜像中。
    2
    连接器配置 作为键值对。
    3
    用于将源数据发布到的临时文件。
    4
    从中读取源数据的 Kafka 主题。
  7. 在 OpenShift 集群中创建 sink KafkaConnector

    oc apply -f examples/connect/sink-connector.yaml
  8. 检查是否创建了连接器资源:

    oc get kctr --selector strimzi.io/cluster=<my_connect_cluster> -o name
    
    my-source-connector
    my-sink-connector

    将 <my_connect_cluster> 替换为 Kafka Connect 集群的名称。

  9. 在容器中,执行 kafka-console-consumer.sh 来读取源连接器写入主题的消息:

    oc exec <my_kafka_cluster>-kafka-0 -i -t -- bin/kafka-console-consumer.sh --bootstrap-server <my_kafka_cluster>-kafka-bootstrap.NAMESPACE.svc:9092 --topic my-topic --from-beginning

    将 <my_kafka_cluster> 替换为 Kafka 集群的名称。

源和接收器连接器配置选项

连接器配置在 KafkaConnector 资源的 spec.config 属性中定义。

FileStreamSourceConnectorFileStreamSinkConnector 类支持与 Kafka Connect REST API 相同的配置选项。其他连接器支持不同的配置选项。

表 6.1. FileStreamSource 连接器类的配置选项
名称类型默认值Description

file

字符串

null

要写入消息的源文件。如果没有指定,则使用标准输入。

topic

list

null

将数据发布到的 Kafka 主题。

表 6.2. FileStreamSinkConnector 类的配置选项
名称类型默认值Description

file

字符串

null

要写入消息的目标文件。如果没有指定,则使用标准输出。

主题

list

null

从中读取数据的一个或多个 Kafka 主题。

topics.regex

字符串

null

与一个或多个 Kafka 主题匹配的正则表达式,以便从中读取数据。

6.4.3.4. 手动重启连接器

如果您使用 KafkaConnector 资源来管理连接器,请使用 restart 注解来手动触发连接器重启。

先决条件

  • Cluster Operator 正在运行。

流程

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

    oc get KafkaConnector
  2. 通过在 OpenShift 中注解 KafkaConnector 资源来重启连接器。

    oc annotate KafkaConnector <kafka_connector_name> strimzi.io/restart=true

    restart 注解设置为 true

  3. 等待下一个协调发生(默认为两分钟)。

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

6.4.3.5. 手动重启 Kafka 连接器任务

如果您使用 KafkaConnector 资源来管理连接器,请使用 restart-task 注解来手动触发连接器任务的重启。

先决条件

  • Cluster Operator 正在运行。

流程

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

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

    oc describe KafkaConnector <kafka_connector_name>
  3. 通过在 OpenShift 中注解 KafkaConnector 资源,使用 ID 重启连接器任务:

    oc annotate KafkaConnector <kafka_connector_name> strimzi.io/restart-task=0

    在本例中,任务 0 被重启。

  4. 等待下一个协调发生(默认为两分钟)。

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

6.4.3.6. 公开 Kafka Connect API

使用 Kafka Connect REST API 作为使用 KafkaConnector 资源管理连接器的替代选择。Kafka Connect REST API 作为一个运行在 <connect_cluster_name>-connect-api:8083 的服务其中 <connect_cluster_name> 是 Kafka Connect 集群的名称。服务在创建 Kafka Connect 实例时创建。

Kafka Connect REST API 支持的操作请参考 Apache Kafka Connect API 文档

注意

strimzi.io/use-connector-resources 注解启用 KafkaConnectors。如果您将注解应用到 KafkaConnect 资源配置,则需要将其删除以使用 Kafka Connect API。否则,Cluster Operator 会恢复使用 Kafka Connect REST API 进行的手动更改。

您可以将连接器配置添加为 JSON 对象。

添加连接器配置的 curl 请求示例

curl -X POST \
  http://my-connect-cluster-connect-api:8083/connectors \
  -H 'Content-Type: application/json' \
  -d '{ "name": "my-source-connector",
    "config":
    {
      "connector.class":"org.apache.kafka.connect.file.FileStreamSourceConnector",
      "file": "/opt/kafka/LICENSE",
      "topic":"my-topic",
      "tasksMax": "4",
      "type": "source"
    }
}'

该 API 仅在 OpenShift 集群中访问。如果要使 Kafka Connect API 可供 OpenShift 集群中运行的应用程序访问,您可以通过创建以下功能之一来手动公开它:

  • LoadBalancerNodePort 类型服务
  • Ingress 资源(仅限 Kubernetes)
  • OpenShift 路由(仅限 OpenShift)
注意

连接是不安全的,因此建议进行外部访问。

如果您决定创建服务,请使用 < connect_cluster_name>-connect-api 服务 选择器 中的标签来配置服务将流量路由到的 pod:

服务的选择器配置

# ...
selector:
  strimzi.io/cluster: my-connect-cluster 1
  strimzi.io/kind: KafkaConnect
  strimzi.io/name: my-connect-cluster-connect 2
#...

1
OpenShift 集群中的 Kafka Connect 自定义资源的名称。
2
Cluster Operator 创建的 Kafka Connect 部署的名称。

您还必须创建一个允许来自外部客户端的 HTTP 请求的 NetworkPolicy

允许请求 Kafka Connect API 的 NetworkPolicy 示例

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: my-custom-connect-network-policy
spec:
  ingress:
  - from:
    - podSelector: 1
        matchLabels:
          app: my-connector-manager
    ports:
    - port: 8083
      protocol: TCP
  podSelector:
    matchLabels:
      strimzi.io/cluster: my-connect-cluster
      strimzi.io/kind: KafkaConnect
      strimzi.io/name: my-connect-cluster-connect
  policyTypes:
  - Ingress

1
允许连接到 API 的 pod 标签。

要在集群外添加连接器配置,请使用 curl 命令中公开 API 的资源 URL。

6.4.3.7. 限制对 Kafka Connect API 的访问

仅将对 Kafka Connect API 的访问限制为可信用户,以防止未经授权的操作和潜在的安全问题。Kafka Connect API 提供了大量更改连接器配置的功能,这有助于采取安全措施。有权访问 Kafka Connect API 的人员可能会获得管理员可能假设的敏感信息是安全的。

Kafka Connect REST API 可以被经过身份验证访问 OpenShift 集群的任何人访问,并知道端点 URL,其中包括主机名/IP 地址和端口号。

例如,假设机构使用 Kafka Connect 集群和连接器将客户数据库的敏感数据流传输到中央数据库。管理员使用配置供应商插件存储与连接到客户数据库和中央数据库(如数据库连接详情和身份验证凭据)相关的敏感信息。配置提供程序保护此敏感信息无法向未授权用户公开。但是,有权访问 Kafka Connect API 的用户仍然可以获得对客户数据库的访问权限,而无需经过管理员的批准。他们可以通过设置一个假的数据库并将连接器配置为连接它。然后,他们可以修改连接器配置以指向客户数据库,但不是将数据发送到中央数据库,而是将其发送到假的数据库。通过将连接器配置为连接到假的数据库,可以截获连接到客户端数据库的登录详情和凭证,即使它们被安全地存储在配置提供程序中。

如果您使用 KafkaConnector 自定义资源,默认情况下,OpenShift RBAC 规则只允许 OpenShift 集群管理员更改连接器。您还可以指定非集群管理员来管理 AMQ Streams 资源。在 Kafka Connect 配置中启用 KafkaConnector 资源后,Cluster Operator 会恢复使用 Kafka Connect REST API 所做的更改。如果您不使用 KafkaConnector 资源,默认的 RBAC 规则不会限制对 Kafka Connect API 的访问。如果要使用 OpenShift RBAC 限制对 Kafka Connect REST API 的直接访问,则需要启用和使用 KafkaConnector 资源。

为了提高安全性,我们建议为 Kafka Connect API 配置以下属性:

org.apache.kafka.disallowed.login.modules

(Kafka 3.4 或更高版本)设置 org.apache.kafka.disallowed.login.modules Java 系统属性,以防止使用不安全的登录模块。例如,指定 com.sun.security.auth.module.JndiLoginModule 可防止使用 Kafka JndiLoginModule

禁止登录模块的配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: my-connect-cluster
  annotations:
    strimzi.io/use-connector-resources: "true"
spec:
  # ...
  jvmOptions:
    javaSystemProperties:
      - name: org.apache.kafka.disallowed.login.modules
        value: com.sun.security.auth.module.JndiLoginModule, org.apache.kafka.common.security.kerberos.KerberosLoginModule
# ...

只允许可信登录模块,并按照您使用的版本的 Kafka 的最新建议进行操作。作为最佳实践,您应该通过使用 org.apache.kafka.disallowed.login.modules 系统属性明确禁止 Kafka Connect 配置中不安全的登录模块。

connector.client.config.override.policy

connector.client.config.override.policy 属性设置为 None,以防止连接器配置覆盖 Kafka Connect 配置及其使用的用户和制作者。

指定连接器覆盖策略的配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: my-connect-cluster
  annotations:
    strimzi.io/use-connector-resources: "true"
spec:
  # ...
  config:
    connector.client.config.override.policy: None
# ...

6.4.3.8. 从 Kafka Connect API 切换到使用 KafkaConnector 自定义资源

您可以从使用 Kafka Connect API 切换到使用 KafkaConnector 自定义资源来管理连接器。要进行交换机,请按照所示的顺序执行以下操作:

  1. 使用配置部署 KafkaConnector 资源,以创建您的连接器实例。
  2. 通过将 strimzi.io/use-connector-resources 注解设置为 true,在 Kafka Connect 配置中启用 KafkaConnector 资源。
警告

如果在创建 KafkaConnector 资源前启用 KafkaConnector 资源,则删除所有连接器。

要从使用 KafkaConnector 资源切换到使用 Kafka Connect API,首先从 Kafka Connect 配置中删除启用 KafkaConnector 资源的注解。否则,Cluster Operator 会恢复使用 Kafka Connect REST API 进行的手动更改。

在进行交换机时 ,检查 KafkaConnect 资源的状态metadata.generation 的值(当前版本的部署)必须与 status.observedGeneration (资源最新协调)匹配。当 Kafka Connect 集群为 Ready 时,您可以删除 KafkaConnector 资源。

6.4.4. Kafka Connect 集群资源列表

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

connect-cluster-name-connect

提供给以下 Kafka Connect 资源的名称:

  • 创建 Kafka Connect worker 节点 pod 的部署(当 StableConnectIdentities 功能门被禁用时)。
  • StrimziPodSet 创建 Kafka Connect worker 节点 pod (当启用了 StableConnectIdentities 功能门时)。
  • 为 Connect pod 提供稳定 DNS 名称的无头服务(启用了 StableConnectIdentities 功能门时)。
  • 为 Kafka Connect worker 节点配置的 Pod Disruption Budget。
connect-cluster-name-connect-idx
由 Kafka Connect StrimziPodSet 创建的 Pod (当启用了 StableConnectIdentities 功能门时)。
connect-cluster-name-connect-api
公开用于管理 Kafka Connect 集群的 REST 接口的服务。
connect-cluster-name-config
包含 Kafka Connect 辅助配置的 ConfigMap,并由 Kafka 代理 pod 挂载为卷。

6.5. 部署 Kafka MirrorMaker

Kafka MirrorMaker 在两个或多个 Kafka 集群之间复制数据,并在数据中心之间复制数据。此过程称为镜像(mirror),以避免与 Kafka 分区复制概念混淆。MirrorMaker 使用来自源集群的消息,并将这些消息重新发布到目标集群。

集群间的数据复制支持以下场景:

  • 在系统失败时恢复数据
  • 从多个源集群整合数据以进行集中分析
  • 对特定集群的数据访问限制
  • 在特定位置置备数据以提高延迟

6.5.1. 将 Kafka MirrorMaker 部署到 OpenShift 集群中

此流程演示了如何使用 Cluster Operator 将 Kafka MirrorMaker 集群部署到 OpenShift 集群。

部署使用 YAML 文件来提供规格,根据部署的 MirrorMaker 版本创建 KafkaMirrorMakerKafkaMirrorMaker2 资源。

重要

Kafka MirrorMaker 1 (称为文档中的 MirrorMaker )已在 Apache Kafka 3.0.0 中弃用,并将在 Apache Kafka 4.0.0 中删除。因此,在 AMQ Streams 中还已弃用了用于部署 Kafka MirrorMaker 1 的 KafkaMirrorMaker 自定义资源。当使用 Apache Kafka 4.0.0 时,KafkaMirrorMaker 资源将从 AMQ Streams 中删除。作为替代方法,在 IdentityReplicationPolicy 中使用 KafkaMirrorMaker2 自定义资源。

AMQ Streams 提供 示例配置文件。在此过程中,我们使用以下示例文件:

  • examples/mirror-maker/kafka-mirror-maker.yaml
  • examples/mirror-maker/kafka-mirror-maker-2.yaml

流程

  1. 将 Kafka MirrorMaker 部署到 OpenShift 集群中:

    对于 MirrorMaker:

    oc apply -f examples/mirror-maker/kafka-mirror-maker.yaml

    对于 MirrorMaker 2:

    oc apply -f examples/mirror-maker/kafka-mirror-maker-2.yaml
  2. 检查部署的状态:

    oc get pods -n <my_cluster_operator_namespace>

    输出显示部署名称和就绪度

    NAME                                    READY  STATUS   RESTARTS
    my-mirror-maker-mirror-maker-<pod_id>   1/1    Running  1
    my-mm2-cluster-mirrormaker2-<pod_id>    1/1    Running  1

    my-mirror-maker 是 Kafka MirrorMaker 集群的名称。my-mm2-cluster 是 Kafka MirrorMaker 2 集群的名称。

    pod ID 标识创建的每个 pod。

    使用默认部署,您要安装单个 MirrorMaker 或 MirrorMaker 2 pod。

    READY 显示就绪/预期的副本数。当 STATUS 显示为 Running 时,部署成功。

6.5.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。

6.6. 部署 Kafka Bridge

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

6.6.1. 在 OpenShift 集群中部署 Kafka Bridge

此流程演示了如何使用 Cluster Operator 将 Kafka Bridge 集群部署到 OpenShift 集群。

部署使用 YAML 文件来提供规格来创建 KafkaBridge 资源。

AMQ Streams 提供 示例配置文件。在此过程中,我们使用以下示例文件:

  • examples/bridge/kafka-bridge.yaml

流程

  1. 将 Kafka Bridge 部署到 OpenShift 集群:

    oc apply -f examples/bridge/kafka-bridge.yaml
  2. 检查部署的状态:

    oc get pods -n <my_cluster_operator_namespace>

    输出显示部署名称和就绪度

    NAME                       READY  STATUS   RESTARTS
    my-bridge-bridge-<pod_id>  1/1    Running  0

    my-bridge 是 Kafka Bridge 集群的名称。

    pod ID 标识创建的每个 pod。

    使用默认部署,您会安装单个 Kafka Bridge pod。

    READY 显示就绪/预期的副本数。当 STATUS 显示为 Running 时,部署成功。

6.6.2. 将 Kafka Bridge 服务公开给本地机器

使用端口转发将 AMQ Streams Kafka Bridge 服务公开给 http://localhost:8080 中的本地机器。

注意

端口转发仅适用于开发和测试目的。

流程

  1. 列出 OpenShift 集群中的 pod 的名称:

    oc get pods -o name
    
    pod/kafka-consumer
    # ...
    pod/my-bridge-bridge-<pod_id>
  2. 在端口 8080 上连接到 Kafka Bridge pod:

    oc port-forward pod/my-bridge-bridge-<pod_id> 8080:8080 &
    注意

    如果本地计算机上的端口 8080 已在使用中,请使用其他 HTTP 端口,如 8008

API 请求现在从本地机器上的端口 8080 转发到 Kafka Bridge pod 的端口 8080。

6.6.3. 在 OpenShift 之外访问 Kafka Bridge

部署后,AMQ Streams Kafka Bridge 只能由在同一 OpenShift 集群中运行的应用程序访问。这些应用程序使用 &lt ;kafka_bridge_name&gt; -bridge-service 服务来访问 API。

如果要使 Kafka Bridge 可供 OpenShift 集群中运行的应用程序访问,您可以通过创建以下功能之一来手动公开它:

  • LoadBalancerNodePort 类型服务
  • Ingress 资源(仅限 Kubernetes)
  • OpenShift 路由(仅限 OpenShift)

如果您决定创建服务,请使用 < kafka_bridge_name>-bridge-service 服务 选择器 中的标签来配置服务将流量路由到的 pod:

  # ...
  selector:
    strimzi.io/cluster: kafka-bridge-name 1
    strimzi.io/kind: KafkaBridge
  #...
1
OpenShift 集群中的 Kafka Bridge 自定义资源的名称。

6.6.4. 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 acillary 配置的 ConfigMap,并由 Kafka 代理 pod 挂载为卷。
bridge-cluster-name-bridge
为 Kafka Bridge worker 节点配置的 Pod Disruption Budget。

6.7. AMQ Streams operator 的替代独立部署选项

您可以对 Topic Operator 和 User Operator 执行独立部署。如果使用不是由 Cluster Operator 管理的 Kafka 集群,请考虑这些 Operator 的独立部署。

您将操作器部署到 OpenShift。Kafka 可以在 OpenShift 外部运行。例如,您可以使用 Kafka 作为受管服务。您可以调整独立 Operator 的部署配置,以匹配 Kafka 集群的地址。

6.7.1. 部署独立主题 Operator

此流程演示了如何将主题 Operator 部署为主题管理的独立组件。您可以将独立主题 Operator 与不由 Cluster Operator 管理的 Kafka 集群一起使用。

独立部署可以处理任何 Kafka 集群。

独立部署文件由 AMQ Streams 提供。使用 05-Deployment-strimzi-topic-operator.yaml 部署文件来部署主题 Operator。添加或设置环境变量来连接 Kafka 集群。

主题 Operator 监视单一命名空间中的 KafkaTopic 资源。您可以在 Topic Operator 配置中指定要监视的命名空间以及与 Kafka 集群的连接。单个主题 Operator 可以监视单个命名空间。一个命名空间应该只被一个主题 Operator 监视。如果要使用多个主题 Operator,请配置每个主题来监视不同的命名空间。这样,您可以将主题 Operator 与多个 Kafka 集群一起使用。

先决条件

  • 您正在运行一个 Kafka 集群,供主题 Operator 连接。

    只要为连接正确配置独立主题 Operator,则 Kafka 集群可以在裸机环境、虚拟机或受管云应用程序服务上运行。

流程

  1. 编辑 install/topic-operator/05-Deployment-strimzi-topic-operator.yaml 独立部署文件中的 env 属性。

    独立主题 Operator 部署配置示例

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: strimzi-topic-operator
      labels:
        app: strimzi
    spec:
      # ...
      template:
        # ...
        spec:
          # ...
          containers:
            - name: strimzi-topic-operator
              # ...
              env:
                - name: STRIMZI_NAMESPACE 1
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace
                - name: STRIMZI_KAFKA_BOOTSTRAP_SERVERS 2
                  value: my-kafka-bootstrap-address:9092
                - name: STRIMZI_RESOURCE_LABELS 3
                  value: "strimzi.io/cluster=my-cluster"
                - name: STRIMZI_ZOOKEEPER_CONNECT 4
                  value: my-cluster-zookeeper-client:2181
                - name: STRIMZI_ZOOKEEPER_SESSION_TIMEOUT_MS 5
                  value: "18000"
                - name: STRIMZI_FULL_RECONCILIATION_INTERVAL_MS 6
                  value: "120000"
                - name: STRIMZI_TOPIC_METADATA_MAX_ATTEMPTS 7
                  value: "6"
                - name: STRIMZI_LOG_LEVEL 8
                  value: INFO
                - name: STRIMZI_TLS_ENABLED 9
                  value: "false"
                - name: STRIMZI_JAVA_OPTS 10
                  value: "-Xmx=512M -Xms=256M"
                - name: STRIMZI_JAVA_SYSTEM_PROPERTIES 11
                  value: "-Djavax.net.debug=verbose -DpropertyName=value"
                - name: STRIMZI_PUBLIC_CA 12
                  value: "false"
                - name: STRIMZI_TLS_AUTH_ENABLED 13
                  value: "false"
                - name: STRIMZI_SASL_ENABLED 14
                  value: "false"
                - name: STRIMZI_SASL_USERNAME 15
                  value: "admin"
                - name: STRIMZI_SASL_PASSWORD 16
                  value: "password"
                - name: STRIMZI_SASL_MECHANISM 17
                  value: "scram-sha-512"
                - name: STRIMZI_SECURITY_PROTOCOL 18
                  value: "SSL"

    1
    主题 Operator 的 OpenShift 命名空间,以监视 KafkaTopic 资源。指定 Kafka 集群的命名空间。
    2
    bootstrap 代理地址的主机和端口对,以发现并连接到 Kafka 集群中的所有代理。在服务器停机时,使用以逗号分隔的列表指定两个或多个代理地址。
    3
    用于标识主题 Operator 管理的 KafkaTopic 资源的标签。这不一定是 Kafka 集群的名称。它可以是分配给 KafkaTopic 资源的标签。如果您部署多个主题 Operator,则标签必须是唯一的。也就是说,Operator 无法管理同一资源。
    4
    (ZooKeeper)用于连接到 ZooKeeper 集群的地址的主机和端口对。这必须是 Kafka 集群正在使用的同一 ZooKeeper 集群。
    5
    (ZooKeeper) ZooKeeper 会话超时,以毫秒为单位。默认值为 18000 (18 秒)。
    6
    定期协调之间的间隔,以毫秒为单位。默认值为 120000 (2 分钟)。
    7
    从 Kafka 获取主题元数据的尝试次数。每次尝试之间的时间定义为指数 backoff。由于分区或副本数,当主题创建需要更长的时间时,请考虑增加这个值。默认值为 6 个尝试。
    8
    打印日志记录消息的级别。您可以将级别设置为 ERRORWARNINGINFODEBUGTRACE
    9
    启用 TLS 支持与 Kafka 代理的加密通信。
    10
    (可选)运行主题 Operator 的 JVM 使用的 Java 选项。
    11
    (可选)为主题 Operator 设置的调试(-D)选项。
    12
    (可选)如果通过 STRIMZI_TLS_ENABLED 启用 TLS,请跳过信任存储证书的生成。如果启用了此环境变量,代理必须使用公共可信证书颁发机构作为其 TLS 证书。默认值为 false
    13
    (可选)为 mTLS 身份验证生成密钥存储证书。把它设置为 false 可禁用 mTLS 到 Kafka 代理的客户端身份验证。默认值是 true
    14
    (可选)在连接到 Kafka 代理时启用对客户端身份验证的 SASL 支持。默认值为 false
    15
    (可选)客户端身份验证的 SASL 用户名。只有通过 STRIMZI_SASL_ENABLED 启用 SASL 时才强制。
    16
    (可选)客户端身份验证的 SASL 密码。只有通过 STRIMZI_SASL_ENABLED 启用 SASL 时才强制。
    17
    (可选)客户端身份验证的 SASL 机制。只有通过 STRIMZI_SASL_ENABLED 启用 SASL 时才强制。您可以将值设为 plain,scram-sha-256, 或 scram-sha-512
    18
    (可选)用于与 Kafka 代理通信的安全协议。默认值为 "PLAINTEXT"。您可以将值设为 PLAINTEXTSSLSASL_PLAINTEXTSASL_SSL
  2. 如果要连接到使用来自公共证书颁发机构证书的 Kafka 代理,请将 STRIMZI_PUBLIC_CA 设置为 true。将此属性设置为 true,例如,如果您使用 Amazon AWS MSK 服务。
  3. 如果您使用 STRIMZI_TLS_ENABLED 环境变量启用了 mTLS,请指定用于验证与 Kafka 集群的连接的密钥存储和信任存储。

    mTLS 配置示例

    # ....
    env:
      - name: STRIMZI_TRUSTSTORE_LOCATION 1
        value: "/path/to/truststore.p12"
      - name: STRIMZI_TRUSTSTORE_PASSWORD 2
        value: "TRUSTSTORE-PASSWORD"
      - name: STRIMZI_KEYSTORE_LOCATION 3
        value: "/path/to/keystore.p12"
      - name: STRIMZI_KEYSTORE_PASSWORD 4
        value: "KEYSTORE-PASSWORD"
    # ...

    1
    truststore 包含用于为 Kafka 和 ZooKeeper 服务器证书签名的证书颁发机构的公钥。
    2
    用于访问 truststore 的密码。
    3
    密钥存储包含 mTLS 身份验证的私钥。
    4
    用于访问密钥存储的密码。
  4. 部署主题 Operator。

    oc create -f install/topic-operator
  5. 检查部署的状态:

    oc get deployments

    输出显示部署名称和就绪度

    NAME                    READY  UP-TO-DATE  AVAILABLE
    strimzi-topic-operator  1/1    1           1

    READY 显示就绪/预期的副本数。当 AVAILABLE 输出显示为 1 时,部署成功。

6.7.1.1. (预览)为单向主题管理部署独立主题 Operator

单向主题管理仅通过 KafkaTopic 资源维护主题。有关单向主题管理的详情,请参考 第 9.1 节 “主题管理模式”

如果要尝试单向主题管理的预览,请按照以下步骤部署独立主题 Operator。

流程

  1. 取消部署当前独立主题 Operator。

    保留 KafkaTopic 资源,这些资源由主题 Operator 再次部署时获取。

  2. 编辑独立主题 Operator 的 Deployment 配置,以删除任何与 ZooKeeper 相关的环境变量:

    • STRIMZI_ZOOKEEPER_CONNECT
    • STRIMZI_ZOOKEEPER_SESSION_TIMEOUT_MS
    • TC_ZK_CONNECTION_TIMEOUT_MS
    • STRIMZI_USE_ZOOKEEPER_TOPIC_STORE

      它是定义是否使用 unidirectional Topic Operator 的 ZooKeeper 变量是否存在。单向主题管理不使用 ZooKeeper。如果没有 ZooKeeper 环境变量,则使用 unidirectional Topic Operator。否则会使用双向主题 Operator。

      如果存在时可以删除的其他未使用的环境变量:

    • STRIMZI_REASSIGN_THROTTLE
    • STRIMZI_REASSIGN_VERIFY_INTERVAL_MS
    • STRIMZI_TOPIC_METADATA_MAX_ATTEMPTS
    • STRIMZI_TOPICS_PATH
    • STRIMZI_STORE_TOPIC
    • STRIMZI_STORE_NAME
    • STRIMZI_APPLICATION_ID
    • STRIMZI_STALE_RESULT_TIMEOUT_MS
  3. (可选)将 STRIMZI_USE_FINALIZERS 环境变量设置为 false

    其他单向主题管理配置

    # ...
    env:
      - name: STRIMZI_USE_FINALIZERS
        value: "false"

    如果您不想使用终结器来控制 删除主题,请将此环境变量设置为 false

    单向主题管理的独立主题 Operator 部署配置示例

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: strimzi-topic-operator
      labels:
        app: strimzi
    spec:
      # ...
      template:
        # ...
        spec:
          # ...
          containers:
            - name: strimzi-topic-operator
              # ...
              env:
                - name: STRIMZI_NAMESPACE
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace
                - name: STRIMZI_KAFKA_BOOTSTRAP_SERVERS
                  value: my-kafka-bootstrap-address:9092
                - name: STRIMZI_RESOURCE_LABELS
                  value: "strimzi.io/cluster=my-cluster"
                - name: STRIMZI_FULL_RECONCILIATION_INTERVAL_MS
                  value: "120000"
                - name: STRIMZI_LOG_LEVEL
                  value: INFO
                - name: STRIMZI_TLS_ENABLED
                  value: "false"
                - name: STRIMZI_JAVA_OPTS
                  value: "-Xmx=512M -Xms=256M"
                - name: STRIMZI_JAVA_SYSTEM_PROPERTIES
                  value: "-Djavax.net.debug=verbose -DpropertyName=value"
                - name: STRIMZI_PUBLIC_CA
                  value: "false"
                - name: STRIMZI_TLS_AUTH_ENABLED
                  value: "false"
                - name: STRIMZI_SASL_ENABLED
                  value: "false"
                - name: STRIMZI_SASL_USERNAME
                  value: "admin"
                - name: STRIMZI_SASL_PASSWORD
                  value: "password"
                - name: STRIMZI_SASL_MECHANISM
                  value: "scram-sha-512"
                - name: STRIMZI_SECURITY_PROTOCOL
                  value: "SSL"
                - name: STRIMZI_USE_FINALIZERS
                  value: "true"

  4. 以标准的方式部署独立主题 Operator。

6.7.2. 部署独立用户 Operator

此流程演示了如何将 User Operator 部署为用户管理的独立组件。您可以将独立的 User Operator 与不由 Cluster Operator 管理的 Kafka 集群一起使用。

独立部署可以处理任何 Kafka 集群。

独立部署文件由 AMQ Streams 提供。使用 05-Deployment-strimzi-user-operator.yaml 部署文件来部署 User Operator。添加或设置环境变量来连接 Kafka 集群。

User Operator 监视单个命名空间中的 KafkaUser 资源。您可以在 User Operator 配置中指定要监视的命名空间以及与 Kafka 集群的连接。单个用户 Operator 可以监视单个命名空间。一个命名空间应该只被一个 User Operator 监视。如果要使用多个 User Operator,请配置每个 User Operator 以监视不同的命名空间。这样,您可以将 User Operator 与多个 Kafka 集群一起使用。

先决条件

  • 您正在运行一个 Kafka 集群,供 User Operator 连接。

    只要为连接正确配置独立用户 Operator,则 Kafka 集群可以在裸机环境、虚拟机或受管云应用程序服务上运行。

流程

  1. 编辑 install/user-operator/05-Deployment-strimzi-user-operator.yaml 独立部署文件中的以下 env 属性。

    独立用户 Operator 部署配置示例

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: strimzi-user-operator
      labels:
        app: strimzi
    spec:
      # ...
      template:
        # ...
        spec:
          # ...
          containers:
            - name: strimzi-user-operator
              # ...
              env:
                - name: STRIMZI_NAMESPACE 1
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace
                - name: STRIMZI_KAFKA_BOOTSTRAP_SERVERS 2
                  value: my-kafka-bootstrap-address:9092
                - name: STRIMZI_CA_CERT_NAME 3
                  value: my-cluster-clients-ca-cert
                - name: STRIMZI_CA_KEY_NAME 4
                  value: my-cluster-clients-ca
                - name: STRIMZI_LABELS 5
                  value: "strimzi.io/cluster=my-cluster"
                - name: STRIMZI_FULL_RECONCILIATION_INTERVAL_MS 6
                  value: "120000"
                - name: STRIMZI_WORK_QUEUE_SIZE 7
                  value: 10000
                - name: STRIMZI_CONTROLLER_THREAD_POOL_SIZE 8
                  value: 10
                - name: STRIMZI_USER_OPERATIONS_THREAD_POOL_SIZE 9
                  value: 4
                - name: STRIMZI_LOG_LEVEL 10
                  value: INFO
                - name: STRIMZI_GC_LOG_ENABLED 11
                  value: "true"
                - name: STRIMZI_CA_VALIDITY 12
                  value: "365"
                - name: STRIMZI_CA_RENEWAL 13
                  value: "30"
                - name: STRIMZI_JAVA_OPTS 14
                  value: "-Xmx=512M -Xms=256M"
                - name: STRIMZI_JAVA_SYSTEM_PROPERTIES 15
                  value: "-Djavax.net.debug=verbose -DpropertyName=value"
                - name: STRIMZI_SECRET_PREFIX 16
                  value: "kafka-"
                - name: STRIMZI_ACLS_ADMIN_API_SUPPORTED 17
                  value: "true"
                - name: STRIMZI_MAINTENANCE_TIME_WINDOWS 18
                  value: '* * 8-10 * * ?;* * 14-15 * * ?'
                - name: STRIMZI_KAFKA_ADMIN_CLIENT_CONFIGURATION 19
                  value: |
                    default.api.timeout.ms=120000
                    request.timeout.ms=60000

    1
    User Operator 的 OpenShift 命名空间,用于监视 KafkaUser 资源。只能指定一个命名空间。
    2
    bootstrap 代理地址的主机和端口对,以发现并连接到 Kafka 集群中的所有代理。在服务器停机时,使用以逗号分隔的列表指定两个或多个代理地址。
    3
    包含为 mTLS 身份验证签名的 CA (certificate 授权)的公钥(ca.crt)值的 OpenShift Secret
    4
    包含 CA 的私钥(ca.key)值的 OpenShift Secret,用于为 mTLS 身份验证为新用户证书签名。
    5
    用于标识由 User Operator 管理的 KafkaUser 资源的标签。这不一定是 Kafka 集群的名称。它可以是分配给 KafkaUser 资源的标签。如果部署多个 User Operator,则标签必须是唯一的。也就是说,Operator 无法管理同一资源。
    6
    定期协调之间的间隔,以毫秒为单位。默认值为 120000 (2 分钟)。
    7
    控制器事件队列的大小。队列的大小应至少与您希望 User Operator 操作的最大用户量一样。默认值为 1024
    8
    用于协调用户的 worker 池大小。较大的池可能需要更多资源,但它也会处理更多 KafkaUser 资源,默认值为 50
    9
    Kafka Admin API 和 OpenShift 操作的 worker 池大小。较大的池可能需要更多资源,但它也会处理更多的 KafkaUser 资源。默认为 4
    10
    打印日志记录消息的级别。您可以将级别设置为 ERRORWARNINGINFODEBUGTRACE
    11
    启用垃圾回收(GC)日志记录。默认值是 true
    12
    CA 的有效性周期。默认值为 365 天。
    13
    CA 的续订周期。续订周期从当前证书的到期日期后衡量。默认值为 30 天,以在旧证书过期前启动证书续订。
    14
    (可选)运行用户 Operator 的 JVM 使用的 Java 选项
    15
    (可选)为 User Operator 设置的调试(-D)选项
    16
    (可选)由 User Operator 创建的 OpenShift secret 名称的前缀。
    17
    (可选)指示 Kafka 集群是否支持使用 Kafka Admin API 管理授权 ACL 规则。当设置为 false 时,User Operator 将拒绝具有 simple 授权 ACL 规则的所有资源。这有助于避免 Kafka 集群日志中不必要的异常。默认值是 true
    18
    (可选) Semi-colon 分隔 Cron Expressions 列表,用于定义维护时间窗,其中过期用户证书。
    19
    (可选)配置 User Operator 以属性格式使用的 Kafka Admin 客户端的配置选项。
  2. 如果您使用 mTLS 连接到 Kafka 集群,请指定用于验证连接的 secret。否则,进入下一步。

    mTLS 配置示例

    # ....
    env:
      - name: STRIMZI_CLUSTER_CA_CERT_SECRET_NAME 1
        value: my-cluster-cluster-ca-cert
      - name: STRIMZI_EO_KEY_SECRET_NAME 2
        value: my-cluster-entity-operator-certs
    # ..."

    1
    包含为 Kafka 代理证书的 CA 的公钥(ca.crt)值的 OpenShift Secret
    2
    包含用于针对 Kafka 集群的 mTLS 身份验证的证书公钥(entity-operator.crt)和私钥(entity-operator.key)的 OpenShift Secret
  3. 部署 User Operator。

    oc create -f install/user-operator
  4. 检查部署的状态:

    oc get deployments

    输出显示部署名称和就绪度

    NAME                   READY  UP-TO-DATE  AVAILABLE
    strimzi-user-operator  1/1    1           1

    READY 显示就绪/预期的副本数。当 AVAILABLE 输出显示为 1 时,部署成功。

第 7 章 启用 AMQ Streams 功能门

AMQ Streams operator 使用功能门来启用或禁用特定功能和功能。通过启用功能门,您可以更改对应 Operator 的行为,从而向 AMQ Streams 部署引入了该功能。

功能门可能会被默认启用或禁用,具体取决于其成熟度等级。

要修改功能门的默认状态,请使用 Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量。您可以使用这个单一环境变量修改多个功能门。指定以逗号分隔的功能门名称和前缀列表。+ 前缀启用功能门和 - 前缀禁用它。

启用 FeatureGate1 并禁用 FeatureGate2的功能门配置示例

env:
  - name: STRIMZI_FEATURE_GATES
    value: +FeatureGate1,-FeatureGate2

7.1. ControlPlaneListener 功能门

ControlPlaneListener 功能门已移到 GA,这意味着它现已永久启用且无法禁用。启用 ControlPlaneListener 后,Kafka 控制器和代理之间的连接使用端口 9090 上的内部 control plane 侦听程序。在代理间复制数据,以及来自 AMQ Streams operator、Cruise Control 或 Kafka Exporter 的内部连接,在端口 9091 上使用 复制监听程序

重要

永久启用 ControlPlaneListener 功能门后,现在可以在 AMQ Streams 1.7 及更早版本和 AMQ Streams 2.3 及更新版本之间直接升级或降级。您必须首先升级或降级 AMQ Streams 版本 in-between,禁用 ControlPlaneListener 功能门,然后降级或升级(启用了功能门)到目标版本。

7.2. ServiceAccountPatching 功能门

ServiceAccountPatching 功能门已移到 GA,这意味着它现已永久启用且无法禁用。启用 ServiceAccountPatching 后,Cluster Operator 始终协调服务帐户并根据需要更新它们。例如,当您使用自定义资源的 template 属性更改服务帐户标签或注解时,Operator 会在现有服务帐户资源中自动更新它们。

7.3. UseStrimziPodSets 功能门

UseStrimziPodSets 功能门已移到 GA,这意味着它现已永久启用且无法禁用。对 StatefulSets 的支持已被删除,AMQ Streams 现在始终使用 StrimziPodSets 来管理 Kafka 和 ZooKeeper pod。

重要

永久启用 UseStrimziPodSets 功能门后,无法再直接从 AMQ Streams 2.4 及更新版本降级到 AMQ Streams 2.0 或更早版本。您必须首先通过一个 AMQ Streams 版本( in-between)进行降级,禁用 UseStrimziPodSets 功能门,然后降级到 AMQ Streams 2.0 或更早版本。

7.4. (Preview) UseKRaft 功能门

UseKRaft 功能门具有 禁用的 默认状态。

UseKRaft 功能门在没有 ZooKeeper 的情况下在 KRaft (Kafka Raft 元数据)模式中部署 Kafka 集群。ZooKeeper 和 KRaft 是用于管理 Kafka 集群中元数据和协调操作的机制。KRaft 模式消除了对 ZooKeeper 等外部协调服务的需求。在 KRaft 模式中,Kafka 节点使用代理、控制器或两者的角色。它们一起管理元数据,该元数据在分区之间复制。控制器负责协调操作和维护集群的状态。

此功能门目前仅适用于开发和测试。

重要

KRaft 模式在 Apache Kafka 或 AMQ Streams 中不适用于生产环境。

启用 UseKRaft 功能门需要启用 KafkaNodePools 功能门。要以 KRaft 模式部署 Kafka 集群,您必须使用 KafkaNodePool 资源。如需了解更多详细信息和示例,请参阅 第 6.3.2 节 “(预览)部署 Kafka 节点池”

当启用 UseKRaft 功能门时,Kafka 集群会在没有 ZooKeeper 的情况下部署。Kafka 自定义资源中的 .spec.zookeeper 属性会被忽略,但仍然需要存在。UseKRaft 功能门提供了一个 API,用于配置 Kafka 集群节点及其角色。API 仍在开发中,预期在 KRaft 模式为生产环境就绪前有所变化。

目前,AMQ Streams 中的 KRaft 模式有以下主要限制:

  • 不支持从 ZooKeeper 移动到 KRaft 集群或其他方法。
  • 只有 controller-only 节点无法单独进行滚动更新或单独更新。
  • 不支持升级和降级 Apache Kafka 版本或 AMQ Streams operator。用户可能需要删除集群,升级 Operator 并部署一个新的 Kafka 集群。
  • KRaft 模式 只支持 Un idirectional Topic Operator。您可以使用 UnidirectionalTopicOperator 功能门启用它。不支持 Bidirectional Topic Operator,当没有启用 UnidirectionalTopicOperator 功能门时,spec.entityOperator.topicOperator 属性 必须从 Kafka 自定义资源中删除。
  • 不支持 JBOD 存储。可以使用 type: jbod 存储,但 JBOD 数组只能包含一个磁盘。

启用 UseKRaft 功能门

要启用 UseKRaft 功能门,在 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量中指定 +UseKRaft,+KafkaNodePools

7.5. StableConnectIdentities 功能门

StableConnectIdentities 功能门的默认状态 被禁用

StableConnectIdentities 功能门使用 StrimziPodSet 资源来管理 Kafka Connect 和 Kafka MirrorMaker 2 pod,而不使用 OpenShift Deployment 资源。StrimziPodSets 为 pod 提供稳定的名称和稳定地址,在滚动升级过程中不会改变。这有助于最小化连接器任务的重新平衡数量。

启用 StableConnectIdentities 功能门

要启用 StableConnectIdentities 功能门,请在 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量中指定 +StableConnectIdentities

重要

在降级到 AMQ Streams 2.3 及更早的版本时,必须禁用 StableConnectIdentities 功能门。

7.6. (预览) KafkaNodePools 功能门

KafkaNodePools 功能门具有 禁用的 默认状态。

KafkaNodePools 功能门引入了一个新的 KafkaNodePool 自定义资源,该资源启用配置不同 Apache Kafka 节点池

节点池指的是 Kafka 集群中不同的 Kafka 节点组。每个池都有自己的唯一的配置,其中包括强制设置,如副本数、存储配置和分配的角色列表。您可以将 控制器 角色、代理 角色或两个角色都分配给 .spec.roles 字段中池中的所有节点。当与基于 ZooKeeper 的 Apache Kafka 集群一起使用时,必须将其设置为 broker 角色。与 UseKRaft 功能门一起使用时,它可以设置为 代理控制器 或两者。

此外,节点池可以自行配置资源请求和限值、Java JVM 选项和资源模板。没有在 KafkaNodePool 资源中设置的配置选项从 Kafka 自定义资源继承。

KafkaNodePool 资源使用 strimzi.io/cluster 标签来指示它们所属的 Kafka 集群。该标签必须设置为 Kafka 自定义资源的名称。

KafkaNodePool 资源的示例可在 AMQ Streams 提供 的示例配置文件 中找到。

启用 KafkaNodePools 功能门

要启用 KafkaNodePools 功能门,在 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量中指定 +KafkaNodePools。使用节点池的 Kafka 自定义资源还必须具有注解 strimzi.io/node-pools: enabled

7.7. (预览)UnidirectionalTopicOperator 功能门

UnidirectionalTopicOperator 功能门 禁用 默认状态。

UnidirectionalTopicOperator 功能门引入了一个单向主题管理模式,用于使用 KafkaTopic 资源创建 Kafka 主题。单向模式与使用 KRaft 进行集群管理兼容。使用单向模式,您可以使用 KafkaTopic 资源创建 Kafka 主题,然后由 Topic Operator 管理。对 KafkaTopic 资源之外的主题的任何配置更改都会被恢复。有关主题管理的详情,请参考 第 9.1 节 “主题管理模式”

启用 UnidirectionalTopicOperator 功能门

要启用 UnidirectionalTopicOperator 功能门,在 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量中指定 +UnidirectionalTopicOperator。要使 KafkaTopic 自定义资源使用此功能,strimzi.io/managed 注解默认设置为 true

7.8. 功能门版本

功能门有三个成熟度阶段:

  • alpha - 通常默认禁用
  • beta - 通常默认启用
  • GA (GA)- 通常始终启用

alpha 阶段功能可能是实验性或不稳定的,可能随时更改或尚未针对生产环境进行了测试。Beta 阶段功能经过良好测试,其功能可能不会改变。GA 阶段功能稳定,将来不应改变。如果 alpha 和 beta 阶段功能没有很有用,则它们会被删除。

  • ControlPlaneListener 功能门在 AMQ Streams 2.3 中移到 GA 阶段。它现已永久启用且无法禁用。
  • ServiceAccountPatching 功能门在 AMQ Streams 2.3 中移到 GA 阶段。它现已永久启用且无法禁用。
  • UseStrimziPodSets 功能门移到 AMQ Streams 2.5 中的 GA 阶段,并完全删除对 StatefulSets 的支持。它现已永久启用且无法禁用。
  • UseKRaft 功能门仅适用于开发,目前没有计划迁移至 beta 阶段的版本。
  • StableConnectIdentities 功能门处于 alpha 阶段,默认是禁用的。
  • KafkaNodePools 功能门处于 alpha 阶段,默认是禁用的。
  • UnidirectionalTopicOperator 功能门处于 alpha 阶段,默认是禁用的。
注意

当功能门到达 GA 时,可能会删除功能门。这意味着该功能已合并到 AMQ Streams 核心功能中,且无法禁用。

表 7.1. 功能门和 AMQ Streams 版本移到 alpha、beta 或 GA。
功能门AlphaBetaGA

ControlPlaneListener

1.8

2.0

2.3

ServiceAccountPatching

1.8

2.0

2.3

UseStrimziPodSets

2.1

2.3

2.5

UseKRaft

2.2

-

-

StableConnectIdentities

2.4

-

-

KafkaNodePools

2.5

-

-

UnidirectionalTopicOperator

2.5

-

-

如果启用了功能门,您可能需要在从特定的 AMQ Streams 版本升级或降级前禁用它。下表显示了在升级或降级 AMQ Streams 版本时需要禁用哪些功能门。

表 7.2. 在升级或降级 AMQ Streams 时禁用的功能门
禁用功能门从 AMQ Streams 版本升级降级到 AMQ Streams 版本

ControlPlaneListener

1.7 及更早版本

1.7 及更早版本

UseStrimziPodSets

-

2.0 及更早版本

StableConnectIdentities

-

2.3 及更早版本

第 8 章 配置部署

使用 AMQ Streams 自定义资源配置和管理 AMQ Streams 部署。AMQ Streams 为每个发行版本提供示例自定义资源,允许您配置和创建支持的 Kafka 组件实例。通过将自定义资源配置为根据您的特定要求包含其他功能来微调部署。对于 Kafka Connect 连接器的特定配置区域,如指标、日志记录和外部配置,您还可以使用 ConfigMap 资源。通过使用 ConfigMap 资源来融合配置,您可以集中维护。您还可以使用配置供应商从外部来源加载配置,我们建议提供 Kafka Connect 连接器配置的凭证。

使用自定义资源配置并创建以下组件的实例:

  • Kafka 集群
  • Kafka Connect 集群
  • Kafka MirrorMaker
  • Kafka Bridge
  • Sything Control

您还可以使用自定义资源配置来管理实例或修改部署,以引入其他功能。这可能包括支持以下配置:

  • (预览)指定节点池
  • 保护对 Kafka 代理的客户端访问
  • 从集群外部访问 Kafka 代理
  • 创建主题
  • 创建用户(客户端)
  • 控制功能门
  • 更改日志频率
  • 分配资源限值和请求
  • 引入功能,如 AMQ Streams Drain Cleaner、Cruise Control 或 distributed tracing。

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

注意

应用到自定义资源的标签也会应用到组成集群的 OpenShift 资源。这为资源提供了一个方便的机制来根据需要进行标记。

将更改应用到自定义资源配置文件

您可以使用 spec 属性将配置添加到自定义资源中。添加配置后,您可以使用 oc 将更改应用到自定义资源配置文件:

oc apply -f <kafka_configuration_file>

8.1. 使用示例配置文件

通过纳入其他支持的配置来进一步增强部署。从 AMQ Streams 软件下载页 提供了可下载发行工件的示例配置文件。

默认情况下,示例文件仅包含自定义资源的基本属性和值。您可以使用 oc 命令行工具下载并应用示例。在为部署构建自己的 Kafka 组件配置时,示例可作为起点。

注意

如果使用 Operator 安装 AMQ Streams,您仍然可以下载示例文件并使用它们上传配置。

发行版本工件包括一个包含配置示例 的示例 目录。

AMQ Streams 提供的配置文件示例

examples
├── user 1
├── topic 2
├── security 3
│   ├── tls-auth
│   ├── scram-sha-512-auth
│   └── keycloak-authorization
├── mirror-maker 4
├── metrics 5
├── kafka 6
│   └── nodepools 7
├── cruise-control 8
├── connect 9
└── bridge 10

1
KafkaUser 自定义资源配置,由 User Operator 管理。
2
KafkaTopic 自定义资源配置,由 Topic Operator 管理。
3
Kafka 组件的身份验证和授权配置。包括 TLS 和 SCRAM-SHA-512 身份验证的示例配置。Red Hat Single Sign-On 示例包括 Kafka 自定义资源配置和 Red Hat Single Sign-On 域规格。您可以使用示例尝试 Red Hat Single Sign-On 授权服务。另外,还有一个启用了 oauth 身份验证和 keycloak 授权指标的示例。
4
用于部署 Mirror Maker 的 Kafka 自定义资源配置。包括复制策略和同步频率配置示例。
5
指标配置,包括 Prometheus 安装和 Grafana 仪表板文件。
6
Kafka 自定义资源配置,用于部署 Kafka。包括临时或持久单节点部署的示例配置。
7
(预览) Kafka 集群中 Kafka 节点的 KafkaNodePool 配置。包括使用 KRaft (Kafka Raft metadata)模式或 ZooKeeper 的集群中节点配置示例。
8
使用 Cruise Control 的部署配置的 Kafka 自定义资源。包含 KafkaRebalance 自定义资源,从 Cruise Control 生成优化提议,以及示例配置,以使用默认或用户优化目标。
9
KafkaConnectKafkaConnector 自定义资源配置用于部署 Kafka Connect。包括单节点或多节点部署的配置示例。
10
Kafka Bridge 部署的 KafkaBridge 自定义资源配置。

8.2. 配置 Kafka

更新 Kafka 自定义资源的 spec 属性来配置 Kafka 部署。

另外,您还可以为 ZooKeeper 和 AMQ Streams Operator 添加配置。各个组件都独立配置通用配置属性,如日志记录和健康检查。

特别重要的配置选项包括:

  • 资源请求(CPU / Memory)
  • 最多和最小内存分配的 JVM 选项
  • 将客户端连接到 Kafka 代理的监听程序(以及客户端的身份验证)
  • 身份验证
  • 存储
  • 机架感知
  • 指标
  • 用于集群重新平衡的 Cruise Control

要深入了解 Kafka 集群配置选项,请参阅 AMQ Streams 自定义资源 API 参考

Kafka 版本

Kafka configinter.broker.protocol.version 属性必须是指定的 Kafka 版本 (spec.kafka.version) 支持的版本。属性表示 Kafka 集群中使用的 Kafka 协议版本。

从 Kafka 3.0.0 开始,当将 inter.broker.protocol.version 设置为 3.0 或更高版本时,log.message.format.version 选项将被忽略,不需要设置。

当升级 Kafka 版本时,需要对 inter.broker.protocol.version 进行更新。如需更多信息,请参阅升级 Kafka

管理 TLS 证书

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

Kafka 自定义资源配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    replicas: 3 1
    version: 3.5.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
      default.replication.factor: 3
      min.insync.replicas: 2
      inter.broker.protocol.version: "3.5"
    storage: 19
      type: persistent-claim 20
      size: 10000Gi
    rack: 21
      topologyKey: topology.kubernetes.io/zone
    metricsConfig: 22
      type: jmxPrometheusExporter
      valueFrom:
        configMapKeyRef: 23
          name: my-config-map
          key: my-key
    # ...
  zookeeper: 24
    replicas: 3 25
    logging: 26
      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: 27
    tlsSidecar: 28
      resources:
        requests:
          cpu: 200m
          memory: 64Mi
        limits:
          cpu: 500m
          memory: 128Mi
    topicOperator:
      watchedNamespace: my-topic-namespace
      reconciliationIntervalSeconds: 60
      logging: 29
        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: 30
        type: inline
        loggers:
          rootLogger.level: INFO
      resources:
        requests:
          memory: 512Mi
          cpu: "1"
        limits:
          memory: 512Mi
          cpu: "1"
  kafkaExporter: 31
    # ...
  cruiseControl: 32
    # ...

1
副本节点的数量。
2
Kafka 版本,可按照升级步骤将其改为受支持的版本。
3
Kafka 日志记录器和日志级别直接(内联)或通过 ConfigMap 间接添加(外部)。自定义 Log4j 配置必须放在 ConfigMap 中的 log4j.properties 键下。对于 Kafka kafka.root.logger.level 日志记录器,您可以将日志级别设置为 INFO, ERROR, WARN, TRACE, DEBUG,FATAL 或 OFF。
4
用于保留支持的资源、当前 cpu 和内存 以及限制的请求,以指定可消耗的最大资源。
5
健康检查以了解何时重启容器(持续)以及容器可以接受流量(就绪状态)。
6
JVM 配置选项,用于优化运行 Kafka 的虚拟机(VM)的性能。
7
ADVANCED OPTION:容器镜像配置,这只在特殊情况下建议使用。
8
侦听器配置客户端如何通过 bootstrap 地址连接到 Kafka 集群。监听器被配置为 internalexternal 监听程序,用于来自 OpenShift 集群内部或外的连接。
9
用于标识监听程序的名称。在 Kafka 集群中必须是唯一的。
10
Kafka 中监听程序使用的端口号。端口号必须在给定的 Kafka 集群中唯一。允许端口号为 9092 及更高版本,但端口 9404 和 9999 除外,它们已用于 Prometheus 和 JMX。根据监听程序类型,端口号可能与连接 Kafka 客户端的端口号不同。
11
监听程序指定为 internalcluster-ip (使用每个代理的 ClusterIP 服务公开 Kafka),或为外部监听程序指定为 route(只限 OpenShift), loadbalancer, nodeportingress(只限 Kubernetes)。
12
为每个监听程序启用 TLS 加密。默认为 false。需要启用 TLS 加密,将它设置为 true, 对于 routeingress 类型的监听器。
13
定义是否分配了包括集群服务后缀(通常为 .cluster.local)的完全限定 DNS 名称。
14
侦听器身份验证机制指定为 mTLS、SCRAM-SHA-512 或基于令牌的 OAuth 2.0。
15
外部监听程序配置指定 Kafka 集群如何在 OpenShift 外部公开,如通过 路由,loadbalancernodeport
16
由外部 CA (证书颁发机构)管理的 Kafka 侦听器证书的可选配置。brokerCertChainAndKey 指定包含服务器证书和私钥的 Secret。您可以在任何启用了 TLS 加密的监听程序中配置 Kafka 侦听器证书。
17
授权在 Kafka 代理上启用 simple、OAUTH 2.0 或 OPA 授权。简单授权使用 AclAuthorizer Kafka 插件。
18
代理配置。标准 Apache Kafka 配置可能会提供,仅限于不直接由 AMQ Streams 管理的属性。
19
持久性卷的存储大小可能会增加,并可以添加额外的卷到 JBOD 存储中。
20
持久性存储具有额外的配置选项,如用于动态卷置备的存储 idclass
21
机架感知配置,将副本分散到不同的机架、数据中心或可用性区域。topologyKey 必须与包含机架 ID 的节点标签匹配。此配置中使用的示例使用标准 topology.kubernetes.io/zone 标签指定区。
22
启用 Prometheus 指标。在本例中,为 Prometheus JMX Exporter (默认指标导出器)配置了指标。
23
通过 Prometheus JMX Exporter 将指标数据导出到 Grafana 仪表板的规则,通过引用包含 Prometheus JMX exporter 配置的 ConfigMap 来启用。您可以使用对 metricsConfig.valueFrom.configMapKeyRef.key 下包含空文件的 ConfigMap 的引用来启用指标。
24
特定于 ZooKeeper 的配置,其中包含与 Kafka 配置类似的属性。
25
ZooKeeper 节点数量。ZooKeeper 集群通常有奇数个节点,一般为三个、五个或七个。大多数节点都必须可用,才能保持有效的仲裁。如果 ZooKeeper 集群丢失了其仲裁,它将停止响应客户端,并且 Kafka 代理将停止工作。拥有稳定且高度可用的 ZooKeeper 集群对于 AMQ Streams 至关重要。
26
ZooKeeper 日志记录器和日志级别。
27
Entity Operator 配置,用于指定主题 Operator 和 User Operator 的配置。
28
实体 Operator TLS sidecar 配置。实体 Operator 使用 TLS sidecar 与 ZooKeeper 安全通信。
29
指定主题 Operator 日志记录器和日志级别。这个示例使用 内联 日志记录。
30
指定 User Operator 日志记录器和日志级别。
31
Kafka 导出程序配置。Kafka Exporter 是一个可选组件,用于在特定消费者滞后数据中从 Kafka 代理中提取指标数据。要使 Kafka Exporter 能够正常工作,消费者组需要使用。
32
Cruise Control 的可选配置,用于重新平衡 Kafka 集群。

8.2.1. 使用 Kafka 静态配额插件设置代理限制

使用 Kafka 静态配额插件在 Kafka 集群中的代理上设置吞吐量和存储限制。您可以通过配置 Kafka 资源来启用插件和设置限制。您可以设置字节阈值和存储配额,以在与代理交互的客户端上放置限制。

您可以为制作者和消费者带宽设置字节阈值。总限制在访问代理的所有客户端间分布。例如,您可以为制作者设置字节阈值 40 MBps。如果两个制作者正在运行,它们各自限制为 20 MBps 的吞吐量。

存储配额在软限制和硬限制之间节流 Kafka 磁盘存储限制。限制适用于所有可用磁盘空间。生产者在软限制和硬限制之间逐渐慢。限制可防止磁盘填满速度超过其容量。完整磁盘可能会导致难以重新处理的问题。硬限制是最大存储限制。

注意

对于 JBOD 存储,限制适用于所有磁盘。如果代理使用两个 1 TB 磁盘,并且配额为 1.1 TB,则一个磁盘可能会填满,另一个磁盘将几乎为空。

先决条件

  • 管理 Kafka 集群的 Cluster Operator 正在运行。

流程

  1. Kafka 资源的 config 添加插件属性。

    此示例配置中显示了插件属性。

    Kafka 静态配额插件配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        # ...
        config:
          client.quota.callback.class: io.strimzi.kafka.quotas.StaticQuotaCallback 1
          client.quota.callback.static.produce: 1000000 2
          client.quota.callback.static.fetch: 1000000 3
          client.quota.callback.static.storage.soft: 400000000000 4
          client.quota.callback.static.storage.hard: 500000000000 5
          client.quota.callback.static.storage.check-interval: 5 6

    1
    加载 Kafka Static Quota 插件。
    2
    设置制作者字节阈值。本示例中为 1 Mbps.
    3
    设置消费者字节阈值。本示例中为 1 Mbps.
    4
    为存储设置较低软限制。在本示例中为 400 GB。
    5
    为存储设置更高的硬限制。本例中为 500 GB。
    6
    设置存储检查间隔(以秒为单位)。本例中有 5 秒。您可以将其设置为 0 来禁用检查。
  2. 更新资源。

    oc apply -f <kafka_configuration_file>

8.2.2. 默认 ZooKeeper 配置值

当使用 AMQ Streams 部署 ZooKeeper 时,AMQ Streams 设置的一些默认配置与标准 ZooKeeper 默认值不同。这是因为 AMQ Streams 设置多个 ZooKeeper 属性,其值在 OpenShift 环境中运行 ZooKeeper。

AMQ Streams 中密钥 ZooKeeper 属性的默认配置如下:

表 8.1. AMQ Streams 中的默认 ZooKeeper 属性
属性默认值Description

tickTime

2000

以毫秒为单位的单空长度,它决定了会话超时的长度。

initLimit

5

在 ZooKeeper 集群中允许后续者获得的最大 tick 数量。

syncLimit

2

后续允许不与 ZooKeeper 集群中的领导不同步的最大 tick 数量。

autopurge.purgeInterval

1

启用 autopurge 功能,并在小时内设置清除服务器端 ZooKeeper 事务日志的时间间隔。

admin.enableServer

false

禁用 ZooKeeper admin 服务器的标记。AMQ Streams 不使用 admin 服务器。

重要

修改这些默认值作为 Kafka 自定义资源中的 zookeeper.config 可能会影响 ZooKeeper 集群的行为和性能。

8.3. (预览)配置节点池

更新 KafkaNodePool 自定义资源的 spec 属性来配置节点池部署。

注意

节点池功能作为技术预览提供。节点池不会被默认启用,因此您必须在使用 KafkaNodePools 功能门前启用 KafkaNodePools 功能门

节点池指的是 Kafka 集群中不同的 Kafka 节点组。每个池都有自己的唯一的配置,其中包括副本、角色和存储分配数量的强制设置。

另外,您还可以为以下属性指定值:

  • 指定内存和 cpu 请求和限值 的资源
  • 模板 为 Pod 和其他 OpenShift 资源指定自定义配置
  • jvmOptions,用于指定堆大小、运行时和其他选项的自定义 JVM 配置

Kafka 资源代表 Kafka 集群中所有节点的配置。KafkaNodePool 资源仅代表节点池中的节点的配置。如果没有在 KafkaNodePool 中指定配置属性,它将继承自 Kafka 资源。如果在两个资源中设置,则 KafkaNodePool 资源中指定的配置具有优先权。例如,如果节点池和 Kafka 配置都包含 jvmOptions,则使用节点池配置中指定的值。当在 KafkaNodePool.spec.jvmOptions 中设置了 -Xmx: 1024m,在 Kafka.spec.kafka.jvmOptions 中设置了 -Xms: 512m,节点会使用其节点池配置中的值。

KafkaKafkaNodePool 模式的属性不会被合并。为了说明,如果 KafkaNodePool.spec.template 只包含 podSet.metadata.labels,并且 Kafka.spec.kafka.template 包含 podSet.metadata.annotationspod.metadata.labels,则 Kafka 配置中的模板值会被忽略,因为节点池配置中有一个模板值。

节点池可用于以 KRaft 模式(使用 Kafka Raft 元数据)运行的 Kafka 集群,或使用 ZooKeeper 进行集群管理。如果使用 KRaft 模式,您可以为节点池中的所有节点指定角色,以作为代理、控制器或两者运行。如果使用 ZooKeeper,则节点必须设置为代理。

重要

KRaft 模式在 Apache Kafka 或 AMQ Streams 中不适用于生产环境。

要深入了解节点池配置选项,请参阅 AMQ Streams 自定义资源 API 参考

注意

虽然启用节点池的 KafkaNodePools 功能门处于 alpha 阶段,但 KafkaNodePool 资源中的副本和存储配置属性还必须存在于 Kafka 资源中。当使用节点池时,Kafka 资源中的配置会被忽略。同样,在使用 KRaft 模式时,在 Kafka 资源中也必须存在 ZooKeeper 配置属性。这些属性也会被忽略。

使用 ZooKeeper 在集群中节点池的配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: pool-a 1
  labels:
    strimzi.io/cluster: my-cluster 2
spec:
  replicas: 3 3
  roles:
    - broker 4
  storage: 5
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 100Gi
        deleteClaim: false
  resources: 6
      requests:
        memory: 64Gi
        cpu: "8"
      limits:
        memory: 64Gi
        cpu: "12"

1
节点池的唯一名称。
2
节点池所属的 Kafka 集群。节点池只能属于单个集群。
3
节点的副本数。
4
节点池中的节点的角色,只有使用带有 ZooKeeper 的 Kafka 时,才可以 代理
5
节点的存储规格。
6
用于保留支持的资源、当前 cpu 和内存 以及限制的请求,以指定可消耗的最大资源。

使用 KRaft 模式的集群中节点池的配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaNodePool
metadata:
  name: kraft-dual-role
  labels:
    strimzi.io/cluster: my-cluster
spec:
  replicas: 3
  roles: 1
    - controller
    - broker
  storage:
    type: jbod
    volumes:
      - id: 0
        type: persistent-claim
        size: 20Gi
        deleteClaim: false
  resources:
      requests:
        memory: 64Gi
        cpu: "8"
      limits:
        memory: 64Gi
        cpu: "12"

1
节点池中的节点的角色。在本例中,节点具有双角色作为控制器和代理。
注意

Kafka 资源的配置必须适合 KRaft 模式。目前,KRaft 模式有很多限制

8.3.1. (预览)将 ID 分配给节点池以进行扩展操作

此流程描述了如何在节点池中执行扩展操作时,Cluster Operator 对高级节点 ID 处理使用注解。您可以按顺序使用下一个 ID 来指定要使用的节点 ID,而不是 Cluster Operator。以这种方式管理节点 ID 可提供更多控制。

要添加一系列 ID,您可以为 KafkaNodePool 资源分配以下注解:

  • strimzi.io/next-node-ids 来添加用于新代理的 ID 范围
  • strimzi.io/remove-node-ids 来添加一系列 ID 以删除现有代理

您可以指定单个节点 ID、ID 范围或两者的组合。例如,您可以指定以下 ID 范围: [0, 1, 2, 10-20, 30] 来扩展 Kafka 节点池。通过这种格式,您可以指定单个节点 ID (01230)以及一系列 ID (10-20)。

在典型的场景中,您可以指定一个 ID 范围来向上扩展和单一节点 ID,以便在缩减时删除特定节点。

在此过程中,我们将扩展注解添加到节点池中,如下所示:

  • pool-a 分配一系列 ID 进行扩展
  • pool-b 分配一系列 ID 用于缩减

在扩展操作过程中,使用 ID,如下所示:

  • 扩展获取新节点范围内的最低可用 ID。
  • 缩减会删除范围中具有最高可用 ID 的节点。

如果在节点池中分配的节点 ID 序列中有差距,则要添加的下一个节点会被分配一个填充空白的 ID。

每次扩展操作后,不需要更新注解。任何未使用的 ID 仍对下一个扩展事件有效。

Cluster Operator 允许您以升序或降序指定 ID 范围,以便您可以按照节点扩展的顺序定义它们。例如,在扩展时,您可以指定一个范围,如 [1000-1999],并且新节点分配下一个最低 ID: 1000100110021003 等。相反,当缩减时,您可以指定一个范围,如 [1999-1000],确保具有下一个最高 ID 的节点已被删除 :100 3、100210011000 等。

如果没有使用注解指定 ID 范围,Cluster Operator 遵循其在扩展操作期间处理 ID 的默认行为。节点 ID 以 0 (零)开始,并在 Kafka 集群中按顺序运行。下一个最低 ID 分配给新节点。在集群中填充节点 ID 的差距。这意味着它们可能无法在节点池中按顺序运行。扩展的默认行为是在集群中添加下一个最低可用节点 ID;在缩减时,它会删除具有最高可用节点 ID 的节点。如果分配的 ID 范围被误格式化,则扩展范围没有 ID,或者缩减范围不适用于任何正在使用的节点,则应用默认方法。

流程

  1. 使用 ID 为节点池添加在扩展或缩减时要使用的 ID,如下例所示。

    用于向上扩展的 ID 会被分配给节点 池池

    为扩展分配 ID

    oc annotate kafkanodepool pool-a strimzi.io/next-node-ids="[0,1,2,10-20,30]"

    将节点添加到 时使用此范围内的最低可用 ID。

    用于缩减的 ID 分配给节点池 pool-b

    为缩减分配 ID

    oc annotate kafkanodepool pool-b strimzi.io/remove-node-ids="[60-50,9,8,7]"

    缩减 pool-b 时会删除此范围内的最高可用 ID。

  2. 现在,您可以扩展节点池。

    如需更多信息,请参阅以下:

    在协调时,如果注解被错误格式化,则会提供一个警告。

8.3.2. (预览)将节点添加到节点池中

这个步骤描述了如何扩展节点池来添加新节点。

在此过程中,我们从三个节点池( )开始:

节点池中的 Kafka 节点

NAME                       READY  STATUS   RESTARTS
my-cluster-pool-a-kafka-0  1/1    Running  0
my-cluster-pool-a-kafka-1  1/1    Running  0
my-cluster-pool-a-kafka-2  1/1    Running  0

节点 ID 在创建时附加到节点的名称中。我们添加节点 my-cluster-pool-a-kafka-3,节点 ID 为 3

注意

在此过程中,保存分区副本的节点 ID 会改变。考虑引用节点 ID 的任何依赖项。

先决条件

流程

  1. 在节点池中创建新节点。

    例如,节点池 pool-a 有三个副本。我们通过增加副本数量来添加节点:

    oc scale kafkanodepool pool-a --replicas=4
  2. 检查部署的状态,并等待节点池中的 pod 创建,并且状态为 READY

    oc get pods -n <my_cluster_operator_namespace>

    输出显示节点池中的四个 Kafka 节点

    NAME                       READY  STATUS   RESTARTS
    my-cluster-pool-a-kafka-0  1/1    Running  0
    my-cluster-pool-a-kafka-1  1/1    Running  0
    my-cluster-pool-a-kafka-2  1/1    Running  0
    my-cluster-pool-a-kafka-3  1/1    Running  0

  3. 在增加节点池中的节点数后重新分配分区。

    在扩展节点池后,您可以使用 Cruise Control add-brokers 模式将分区副本从现有代理移到新添加的代理中。

8.3.3. (预览)从节点池中删除节点

这个步骤描述了如何缩减节点池来删除节点。

在此过程中,我们从四个节点池( )开始:

节点池中的 Kafka 节点

NAME                       READY  STATUS   RESTARTS
my-cluster-pool-a-kafka-0  1/1    Running  0
my-cluster-pool-a-kafka-1  1/1    Running  0
my-cluster-pool-a-kafka-2  1/1    Running  0
my-cluster-pool-a-kafka-3  1/1    Running  0

节点 ID 在创建时附加到节点的名称中。我们删除节点 my-cluster-pool-a-kafka-3,节点 ID 为 3

注意

在此过程中,保存分区副本的节点 ID 会改变。考虑引用节点 ID 的任何依赖项。

先决条件

流程

  1. 在减少节点池中的节点数前重新分配分区。

    在缩减节点池前,您可以使用 Cruise Control remove-brokers 模式将分区副本移出要删除的代理。

  2. 在重新分配过程完成后,删除的节点没有实时分区,从而减少节点池中的 Kafka 节点数量。

    例如,节点池 pool-a 有四个副本。我们通过减少副本数来删除节点:

    oc scale kafkanodepool pool-a --replicas=3

    输出显示节点池中的三个 Kafka 节点

    NAME                        READY   STATUS    RESTARTS
    my-cluster-pool-b-kafka-0   1/1     Running   0
    my-cluster-pool-b-kafka-1   1/1     Running   0
    my-cluster-pool-b-kafka-2   1/1     Running   0

8.3.4. (预览)在节点池之间移动节点

这个步骤描述了如何在不停机的情况下在源和目标 Kafka 节点池之间移动节点。您可以在目标节点池中创建新节点并重新分配分区,以便从源节点池中的旧节点移动数据。当新节点上的副本同步时,您可以删除旧节点。

在此过程中,我们从两个节点池开始:

  • 具有三个副本的池 是目标节点池
  • 带有四个副本的 pool-b 是源节点池

我们扩展 pool-a,并重新分配分区并缩减 pool-b,这会导致以下内容:

  • pool-a 带有四个副本
  • 带有三个副本的 pool-b
注意

在此过程中,保存分区副本的节点 ID 会改变。考虑引用节点 ID 的任何依赖项。

先决条件

流程

  1. 在目标节点池中创建新节点。

    例如,节点池 pool-a 有三个副本。我们通过增加副本数量来添加节点:

    oc scale kafkanodepool pool-a --replicas=4
  2. 检查部署的状态,并等待节点池中的 pod 创建,并且状态为 READY

    oc get pods -n <my_cluster_operator_namespace>

    输出显示目标节点池中的四个 Kafka 节点

    NAME                       READY  STATUS   RESTARTS
    my-cluster-pool-a-kafka-0  1/1    Running  0
    my-cluster-pool-a-kafka-1  1/1    Running  0
    my-cluster-pool-a-kafka-4  1/1    Running  0
    my-cluster-pool-a-kafka-5  1/1    Running  0

    节点 ID 在创建时附加到节点的名称中。我们添加节点 my-cluster-pool-a-kafka-5,其节点 ID 为 5

  3. 将分区从旧节点重新分配给新节点。

    在缩减源节点池前,您可以使用 Cruise Control remove-brokers 模式将分区副本移出要删除的代理。

  4. 重新分配过程完成后,减少源节点池中的 Kafka 节点数量。

    例如,节点池 pool-b 具有四个副本。我们通过减少副本数来删除节点:

    oc scale kafkanodepool pool-b --replicas=3

    池中具有最高 ID 的节点已被删除。

    输出显示源节点池中的三个 Kafka 节点

    NAME                       READY  STATUS   RESTARTS
    my-cluster-pool-b-kafka-2  1/1    Running  0
    my-cluster-pool-b-kafka-3  1/1    Running  0
    my-cluster-pool-b-kafka-6  1/1    Running  0

8.3.5. (预览)迁移现有 Kafka 集群以使用 Kafka 节点池

这个步骤描述了如何迁移现有 Kafka 集群以使用 Kafka 节点池。更新 Kafka 集群后,您可以使用节点池来管理每个池中的节点配置。

注意

虽然启用节点池的 KafkaNodePools 功能门处于 alpha 阶段,但 KafkaNodePool 资源中的副本和存储配置还必须存在于 Kafka 资源中。使用节点池时会忽略配置。

流程

  1. 创建新的 KafkaNodePool 资源。

    1. 将资源命名为 kafka
    2. strimzi.io/cluster 标签指向现有的 Kafka 资源。
    3. 设置副本数和存储配置以匹配您当前的 Kafka 集群。
    4. 将角色设置为 代理

    迁移 Kafka 集群的节点池配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaNodePool
    metadata:
      name: kafka
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      replicas: 3
      roles:
        - broker
      storage:
        type: jbod
        volumes:
          - id: 0
            type: persistent-claim
            size: 100Gi
            deleteClaim: false

  2. 应用 KafkaNodePool 资源:

    oc apply -f <node_pool_configuration_file>

    通过应用此资源,您可以将 Kafka 切换到使用节点池。

    没有更改或滚动更新和资源与之前的资源相同。

  3. 更新 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量,使其包含 +KafkaNodePools

    env:
      - name: STRIMZI_FEATURE_GATES
        value: +KafkaNodePools
  4. 使用 strimzi.io/node-pools: enabled 注解,在 Kafka 资源中启用 KafkaNodePools 功能门。

    使用 ZooKeeper 在集群中节点池的配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
      annotations:
        strimzi.io/node-pools: enabled
    spec:
      kafka:
        version: 3.5.0
        replicas: 3
      # ...
      storage:
          type: jbod
          volumes:
          - id: 0
            type: persistent-claim
            size: 100Gi
            deleteClaim: false

  5. 应用 Kafka 资源:

    oc apply -f <kafka_configuration_file>

8.4. 配置实体 Operator

使用 Kafka.spec 中的 entityOperator 属性来配置实体 Operator。Entity Operator 用于管理在 Kafka 集群中运行的与 Kafka 相关的实体。它由以下 Operator 组成:

  • 管理 Kafka 主题的主题 Operator
  • 用于管理 Kafka 用户的用户 Operator

通过配置 Kafka 资源,Cluster Operator 可以部署 Entity Operator,包括一个或多个 Operator。部署后,Operator 会自动配置为处理 Kafka 集群的主题和用户。

每个 operator 只能监控单个命名空间。如需更多信息,请参阅 第 1.2.1 节 “在 OpenShift 命名空间中观察 AMQ Streams 资源”

entityOperator 属性支持多个子属性:

  • tlsSidecar
  • topicOperator
  • userOperator
  • 模板

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

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

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

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

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

启用这两个 Operator 的基本配置示例

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

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

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

8.4.1. 配置主题 Operator

使用 Kafka.spec.entityOperator 中的 topicOperator 属性来配置 Topic Operator。

注意

如果您使用单向主题管理的预览,则不会使用以下属性,并会被忽略: Kafka.spec.entityOperator.zookeeperSessionTimeoutSecondsKafka.spec.entityOperator.topicOperator.topicMetadataMaxAttempts。有关单向主题管理的详情,请参考 第 9.1 节 “主题管理模式”

支持以下属性:

watchedNamespace
主题 Operator 监视 KafkaTopic 资源的 OpenShift 命名空间。default 是部署 Kafka 集群的命名空间。
reconciliationIntervalSeconds
定期协调之间的间隔(以秒为单位)。默认 120
zookeeperSessionTimeoutSeconds
ZooKeeper 会话超时(以秒为单位)。默认 18
topicMetadataMaxAttempts
从 Kafka 获取主题元数据的尝试次数。每次尝试之间的时间都定义为指数避退。当主题创建可能会因为分区或副本数增加时,请考虑增加这个值。默认 6
image
image 属性可用于配置要使用的容器镜像。如需更多信息,请参阅有关 配置镜像 属性 提供的信息。
资源
resources 属性配置分配给 Topic Operator 的资源数量。您可以为 内存和 cpu 资源指定请求和限值。请求应该足以确保操作器的稳定性能。
logging
logging 属性配置 Topic Operator 的日志记录。如需更多信息,请参阅 主题 Operator 日志记录 上提供的信息。

主题 Operator 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
  zookeeper:
    # ...
  entityOperator:
    # ...
    topicOperator:
      watchedNamespace: my-topic-namespace
      reconciliationIntervalSeconds: 60
      resources:
        requests:
          cpu: "1"
          memory: 500Mi
        limits:
          cpu: "1"
          memory: 500Mi
    # ...

8.4.2. 配置用户 Operator

使用 Kafka.spec.entityOperator 中的 userOperator 属性来配置 User Operator。支持以下属性:

watchedNamespace
User Operator 监视 KafkaUser 资源的 OpenShift 命名空间。default 是部署 Kafka 集群的命名空间。
reconciliationIntervalSeconds
定期协调之间的间隔(以秒为单位)。默认 120
image
image 属性可用于配置要使用的容器镜像。如需更多信息,请参阅有关 配置镜像 属性 提供的信息。
资源
resources 属性配置分配给 User Operator 的资源数量。您可以为 内存和 cpu 资源指定请求和限值。请求应该足以确保操作器的稳定性能。
logging
logging 属性配置 User Operator 的日志记录。如需更多信息,请参阅 User Operator 日志记录 上提供的信息。
secretPrefix
secretPrefix 属性在 KafkaUser 资源创建的所有 Secret 的名称中添加前缀。例如,secretPrefix: 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
      resources:
        requests:
          cpu: "1"
          memory: 500Mi
        limits:
          cpu: "1"
          memory: 500Mi
    # ...

8.5. 配置 Cluster Operator

使用环境变量配置 Cluster Operator。在 Deployment 配置文件中,指定 Cluster Operator 的容器镜像的环境变量。

注意

AMQ Streams 发行工件提供的 Deployment 配置文件为 install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml

您可以使用以下环境变量来配置 Cluster Operator。如果您以待机模式运行 Cluster Operator 副本,则需要额外的 环境变量来启用领导选举机制

STRIMZI_NAMESPACE

以逗号分隔的 Operator 运行的命名空间列表。如果没有设置,则为空字符串,或设置为 *,Cluster Operator 在所有命名空间中运行。

Cluster Operator 部署可能会使用 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_ZOOKEEPER_ADMIN_SESSION_TIMEOUT_MS
可选,默认的 10000 ms。Cluster Operator 的 ZooKeeper admin 客户端的会话超时,以毫秒为单位。如果 Cluster Operator 的 ZooKeeper 请求因为超时问题定期失败,请增加这个值。通过 maxSessionTimeout 配置在 ZooKeeper 服务器端设置最大允许会话时间。默认情况下,最大会话超时值为 20 倍,即默认 tickTime (其默认值为 2000)为 40000 ms。如果您需要更高的超时,请更改 maxSessionTimeout ZooKeeper 服务器配置值。
STRIMZI_OPERATIONS_THREAD_POOL_SIZE
可选,默认 10。worker 线程池大小,用于各种异步和阻止由 Cluster Operator 运行的操作。
STRIMZI_OPERATOR_NAME
可选,默认为 pod 的主机名。在发出 OpenShift 事件时,Operator 名称标识 AMQ Streams 实例。
STRIMZI_OPERATOR_NAMESPACE

运行 Cluster Operator 的命名空间的名称。不要手动配置此变量。使用 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 集群中的任何命名空间中访问 Cluster Operator。

env:
  - name: STRIMZI_OPERATOR_NAMESPACE_LABELS
    value: label1=value1,label2=value2
STRIMZI_LABELS_EXCLUSION_PATTERN

可选,默认的正则表达式为 ^app.kubernetes.io/(?!part-of).*。用于过滤从主自定义资源传播到其子资源的正则表达式排除模式。标签排除过滤器不适用于模板部分中的标签,如 spec.kafka.template.pod.metadata.labels

env:
  - name: STRIMZI_LABELS_EXCLUSION_PATTERN
    value: "^key1.*"
STRIMZI_CUSTOM_{COMPONENT_NAME}_LABELS

可选。一个或多个自定义标签,应用到 {COMPONENT_NAME} 自定义资源创建的所有 pod。Cluster Operator 在创建自定义资源或下一次协调时会标记 pod。

标签可应用到以下组件:

  • KAFKA
  • KAFKA_CONNECT
  • KAFKA_CONNECT_BUILD
  • ZOOKEEPER
  • ENTITY_OPERATOR
  • KAFKA_MIRROR_MAKER2
  • KAFKA_MIRROR_MAKER
  • CRUISE_CONTROL
  • KAFKA_BRIDGE
  • KAFKA_EXPORTER
STRIMZI_CUSTOM_RESOURCE_SELECTOR

可选。用于过滤 Cluster Operator 处理的自定义资源的标签选择器。Operator 仅在设置了指定标签的自定义资源上运行。Operator 不会看到没有这些标签的资源。标签选择器适用于 Kafka, KafkaConnect, KafkaBridge, KafkaMirrorMaker, 和 KafkaMirrorMaker2 资源。只有在对应的 Kafka 和 Kafka Connect 集群具有匹配的标签时,才会执行 KafkaRebalanceKafkaConnector 资源。

env:
  - name: STRIMZI_CUSTOM_RESOURCE_SELECTOR
    value: label1=value1,label2=value2
STRIMZI_KAFKA_IMAGES
必需。从 Kafka 版本到包含该版本的 Kafka 代理的对应 Docker 镜像的映射。所需的语法为空格或以逗号分隔的 < version> = &lt;image> 对。例如 3.4.0=registry.redhat.io/amq-streams/kafka-34-rhel8:2.5.1, 3.5.0=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1。当指定了属性 Kafka.spec.kafka.version 但没有在 Kafka 资源的 Kafka.spec.kafka.image 时使用这个。
STRIMZI_DEFAULT_KAFKA_INIT_IMAGE
可选,默认 registry.redhat.io/amq-streams/strimzi-rhel8-operator:2.5.1。如果没有将镜像指定为 Kafka 资源中的 kafka-init-image,则用作 init 容器的默认镜像名称。init 容器在代理进行初始配置工作之前启动,如机架支持。
STRIMZI_KAFKA_CONNECT_IMAGES
必需。从 Kafka 版本映射到那个版本的 Kafka Connect 的对应 Docker 镜像。所需的语法为空格或以逗号分隔的 < version> = &lt;image> 对。例如 3.4.0=registry.redhat.io/amq-streams/kafka-34-rhel8:2.5.1, 3.5.0=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1。当指定 KafkaConnect.spec.version 属性但没有 KafkaConnect.spec.image 时,会使用它。
STRIMZI_KAFKA_MIRROR_MAKER_IMAGES
必需。此版本从 Kafka 版本到 MirrorMaker 的对应 Docker 镜像的映射。所需的语法为空格或以逗号分隔的 < version> = &lt;image> 对。例如 3.4.0=registry.redhat.io/amq-streams/kafka-34-rhel8:2.5.1, 3.5.0=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1。当指定 KafkaMirrorMaker.spec.version 属性但没有 KafkaMirrorMaker.spec.image 时,会使用它。
STRIMZI_DEFAULT_TOPIC_OPERATOR_IMAGE
可选,默认 registry.redhat.io/amq-streams/strimzi-rhel8-operator:2.5.1。如果没有将镜像指定为 Kafka 资源中的 Kafka.spec.entityOperator.topicOperator.image,则部署 Topic Operator 时使用的镜像名称作为默认镜像。
STRIMZI_DEFAULT_USER_OPERATOR_IMAGE
可选,默认 registry.redhat.io/amq-streams/strimzi-rhel8-operator:2.5.1。如果没有将镜像指定为 Kafka 资源中的 Kafka.spec.entityOperator.userOperator.image,则部署 User Operator 时使用的 镜像名称
STRIMZI_DEFAULT_TLS_SIDECAR_ENTITY_OPERATOR_IMAGE
可选,默认 registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1。如果没有将镜像指定为 Kafka 资源中的 Kafka.spec.entityOperator.tlsSidecar.image,则用作实体 Operator 的 sidecar 容器时使用的 镜像名称。sidecar 提供 TLS 支持。
STRIMZI_IMAGE_PULL_POLICY
可选。应用到 Cluster Operator 管理的所有 pod 中的容器的 ImagePullPolicy。有效值为 Always、ifNotP resent 和 Never。如果未指定,则使用 OpenShift 默认值。更改策略将导致所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群的滚动更新。
STRIMZI_IMAGE_PULL_SECRETS
可选。以逗号分隔的 Secret 名称列表。此处引用的 secret 包含从中拉取容器镜像的容器 registry 的凭证。secret 在 Cluster Operator 创建的所有 pod 的 imagePullSecrets 属性中指定。更改此列表会导致所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群的滚动更新。
STRIMZI_KUBERNETES_VERSION

可选。覆盖从 API 服务器检测到的 OpenShift 版本信息。

OpenShift 版本覆盖配置示例

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 集群中分配的服务具有使用默认后缀 cluster.local 的 DNS 域名。

例如,对于 broker 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 来构建包含许多连接器的容器镜像或使用较慢的容器 registry 时,请考虑增加这个值。
STRIMZI_NETWORK_POLICY_GENERATION

可选,默认为 true。资源的网络策略。网络策略允许 Kafka 组件间的连接。

将此环境变量设置为 false 以禁用网络策略生成。例如,您可能需要使用自定义网络策略,您可能需要执行此操作。自定义网络策略可让更多地控制组件间的连接。

STRIMZI_DNS_CACHE_TTL
可选,默认的 30。在本地 DNS 解析器中缓存成功名称查找的秒数。任何负值都表示缓存永久缓存。zero 意味着不会缓存,这可用于避免因为应用长缓存策略而连接错误。
STRIMZI_POD_SET_RECONCILIATION_ONLY
可选,默认为 false。当设置为 true 时,Cluster Operator 只协调 StrimziPodSet 资源,以及其它自定义资源(KafkaKafkaConnect 等)的任何更改。此模式可用于确保根据需要重新创建 pod,但不会对集群进行其他更改。
STRIMZI_FEATURE_GATES
可选。启用或禁用由 功能门控制的功能和功能
STRIMZI_POD_SECURITY_PROVIDER_CLASS
可选。配置可插拔 PodSecurityProvider 类,可用于为 Pod 和容器提供安全上下文配置。

8.5.1. 使用网络策略限制对 Cluster Operator 的访问

使用 STRIMZI_OPERATOR_NAMESPACE_LABELS 环境变量,使用命名空间标签为 Cluster Operator 建立网络策略。

Cluster Operator 可以在与它管理的资源相同的命名空间中运行,也可以在单独的命名空间中运行。默认情况下,STRIMZI_OPERATOR_NAMESPACE 环境变量被配置为使用 Downward API 查找运行 Cluster Operator 的命名空间。如果 Cluster Operator 在与资源相同的命名空间中运行,则 AMQ Streams 只需要本地访问。

如果 Cluster Operator 在单独命名空间中运行,则 OpenShift 集群中的任何命名空间都可以访问 Cluster Operator,除非配置了网络策略。通过添加命名空间标签,对 Cluster Operator 的访问仅限于指定的命名空间。

为 Cluster Operator 部署配置的网络策略

#...
env:
  # ...
  - name: STRIMZI_OPERATOR_NAMESPACE_LABELS
    value: label1=value1,label2=value2
  #...

8.5.2. 配置 Cluster Operator 的定期协调

使用 STRIMZI_FULL_RECONCILIATION_INTERVAL_MS 变量设置 Cluster Operator 定期协调的时间间隔。将其值替换为所需间隔(以毫秒为单位)。

为 Cluster Operator 部署配置的协调周期

#...
env:
  # ...
  - name: STRIMZI_FULL_RECONCILIATION_INTERVAL_MS
    value: "120000"
  #...

Cluster Operator 对从 OpenShift 集群接收的适用集群资源的所有通知做出反应。如果操作器没有运行,或者因为某种原因没有收到通知,资源将从正在运行的 OpenShift 集群状态不同步。为了正确处理故障转移,Cluster Operator 会执行定期协调过程,以便它可以将资源的状态与当前集群部署进行比较,以便在所有这些部署之间具有一致的状态。

其他资源

8.5.3. 使用领导选举机制运行多个 Cluster Operator 副本

默认 Cluster Operator 配置可让领导选举机制运行 Cluster Operator 的多个并行副本。一个副本被选为活跃领导值,并运行部署的资源。其他副本以待机模式运行。当领导停止或失败时,其中一个备用副本被选为新领导,并开始操作部署的资源。

默认情况下,AMQ Streams 使用单个 Cluster Operator 副本运行,该副本始终是领导副本。当单个 Cluster Operator 副本停止或失败时,OpenShift 会启动新的副本。

运行具有多个副本的 Cluster Operator 并不重要。但是,在出现重大故障导致的大规模中断时,在待机时具有副本非常有用。例如,假设多个 worker 节点或整个可用区失败。故障可能会导致 Cluster Operator pod 和许多 Kafka pod 同时停机。如果后续的 pod 调度导致资源丢失,这可能会在运行单个 Cluster Operator 时延迟操作。

8.5.3.1. 为 Cluster Operator 副本启用领导选举机制

在运行额外的 Cluster Operator 副本时,配置领导选举环境变量。支持以下环境变量:

STRIMZI_LEADER_ELECTION_ENABLED
可选,默认禁用(默认为 )。启用或禁用领导选举机制,允许额外的 Cluster Operator 副本在待机上运行。
注意

默认禁用领导选举机制。只有在安装时应用此环境变量时才启用。

STRIMZI_LEADER_ELECTION_LEASE_NAME
启用领导选举机制时需要。用于领导选举的 OpenShift Lease 资源的名称。
STRIMZI_LEADER_ELECTION_LEASE_NAMESPACE

启用领导选举机制时需要。创建用于领导选举 OpenShift Lease 资源的命名空间。您可以使用 Downward API 将其配置为部署 Cluster Operator 的命名空间。

env:
  - name: STRIMZI_LEADER_ELECTION_LEASE_NAMESPACE
    valueFrom:
      fieldRef:
        fieldPath: metadata.namespace
STRIMZI_LEADER_ELECTION_IDENTITY

启用领导选举机制时需要。配置在领导选举过程中使用的给定 Cluster Operator 实例的身份。对于每个 operator 实例,身份必须是唯一的。您可以使用 Downward API 将其配置为部署 Cluster Operator 的 pod 的名称。

env:
  - name: STRIMZI_LEADER_ELECTION_IDENTITY
    valueFrom:
      fieldRef:
        fieldPath: metadata.name
STRIMZI_LEADER_ELECTION_LEASE_DURATION_MS
可选,默认 15000 ms。指定获取租期有效的持续时间。
STRIMZI_LEADER_ELECTION_RENEW_DEADLINE_MS
可选,默认的 10000 ms。指定领导应尝试维护领导期。
STRIMZI_LEADER_ELECTION_RETRY_PERIOD_MS
可选,默认的 2000 ms。指定领导到租期锁定的更新频率。
8.5.3.2. 配置 Cluster Operator 副本

要以待机模式运行额外的 Cluster Operator 副本,您需要增加副本数并启用领导选举机制。要配置领导选举机制,请使用领导选举环境变量。

要进行所需的更改,请配置位于 install/cluster-operator/ 中的以下 Cluster Operator 安装文件:

  • 060-Deployment-strimzi-cluster-operator.yaml
  • 022-ClusterRole-strimzi-cluster-operator-role.yaml
  • 022-RoleBinding-strimzi-cluster-operator.yaml

领导选举具有自己的 ClusterRoleRoleBinding RBAC 资源,这些资源以 Cluster Operator 运行的命名空间为目标,而不是它监视的命名空间。

默认部署配置在与 Cluster Operator 相同的命名空间中创建一个名为 strimzi-cluster-operatorLease 资源。Cluster Operator 使用租期来管理领导选举机制。RBAC 资源提供使用 Lease 资源的权限。如果您使用不同的 Lease 名称或命名空间,请相应地更新 ClusterRoleRoleBinding 文件。

先决条件

  • 您需要具有权限的帐户来创建和管理 CustomResourceDefinition 和 RBAC (ClusterRoleRoleBinding)资源。

流程

编辑用于部署 Cluster Operator 的 Deployment 资源,该资源在 060-Deployment-strimzi-cluster-operator.yaml 文件中定义。

  1. replicas 属性从 default (1)更改为与所需副本数匹配的值。

    增加 Cluster Operator 副本的数量

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: strimzi-cluster-operator
      labels:
        app: strimzi
    spec:
      replicas: 3

  2. 检查是否设置了 leader election env 属性。

    如果没有设置,请配置它们。

    要启用领导选举机制,STRIMZI_LEADER_ELECTION_ENABLED 必须设置为 true (默认)。

    在本例中,租期的名称改为 my-strimzi-cluster-operator

    为 Cluster Operator 配置领导选举环境变量

    # ...
    spec
      containers:
        - name: strimzi-cluster-operator
          # ...
          env:
            - name: STRIMZI_LEADER_ELECTION_ENABLED
              value: "true"
            - name: STRIMZI_LEADER_ELECTION_LEASE_NAME
              value: "my-strimzi-cluster-operator"
            - name: STRIMZI_LEADER_ELECTION_LEASE_NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
            - name: STRIMZI_LEADER_ELECTION_IDENTITY
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name

    有关可用环境变量的描述,请参阅 第 8.5.3.1 节 “为 Cluster Operator 副本启用领导选举机制”

    如果您为领导选举机制中使用的 Lease 资源指定了不同的名称或命名空间,请更新 RBAC 资源。

  3. (可选)在 022-ClusterRole-strimzi-cluster-operator-role.yaml 文件中编辑 ClusterRole 资源。

    使用 Lease 资源的名称更新 resourceNames

    将 ClusterRole 引用更新为租期

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: strimzi-cluster-operator-leader-election
      labels:
        app: strimzi
    rules:
      - apiGroups:
          - coordination.k8s.io
        resourceNames:
          - my-strimzi-cluster-operator
    # ...

  4. (可选)在 022-RoleBinding-strimzi-cluster-operator.yaml 文件中编辑 RoleBinding 资源。

    使用 Lease 资源的名称以及创建它的命名空间更新 subjects.namesubjects.namespace

    将 RoleBinding 引用更新为租期

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: strimzi-cluster-operator-leader-election
      labels:
        app: strimzi
    subjects:
      - kind: ServiceAccount
        name: my-strimzi-cluster-operator
        namespace: myproject
    # ...

  5. 部署 Cluster Operator:

    oc create -f install/cluster-operator -n myproject
  6. 检查部署的状态:

    oc get deployments -n myproject

    输出显示部署名称和就绪度

    NAME                      READY  UP-TO-DATE  AVAILABLE
    strimzi-cluster-operator  3/3    3           3

    READY 显示就绪/预期的副本数。当 AVAILABLE 输出显示正确的副本数时,部署可以成功。

8.5.4. 配置 Cluster Operator HTTP 代理设置

如果您在 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>。

先决条件

  • 您需要具有权限的帐户来创建和管理 CustomResourceDefinition 和 RBAC (ClusterRoleRoleBinding)资源。

流程

  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 是用逗号分开的。

    或者,直接编辑 部署

    oc edit deployment strimzi-cluster-operator
  2. 如果您更新了 YAML 文件而不是直接编辑 Deployment,请应用更改:

    oc create -f install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml

8.5.5. 使用 Cluster Operator 配置禁用 FIPS 模式

当在启用了 FIPS 的 OpenShift 集群中运行时,AMQ Streams 会自动切换到 FIPS 模式。通过在 Cluster Operator 的部署配置中将 FIPS_MODE 环境变量设置为 禁用 FIPS 模式。禁用 FIPS 模式后,AMQ Streams 会在 OpenJDK 中为所有组件禁用 FIPS。禁用 FIPS 模式后,AMQ Streams 不兼容 FIPS。AMQ Streams operator 以及所有操作对象的运行方式与在启用了 FIPS 的 OpenShift 集群中运行的方式相同。

流程

  1. 要在 Cluster Operator 中禁用 FIPS 模式,更新其部署配置install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml) 并增加 FIPS_MODE 环境变量。

    Cluster Operator 的 FIPS 配置示例

    apiVersion: apps/v1
    kind: Deployment
    spec:
      # ...
      template:
        spec:
          serviceAccountName: strimzi-cluster-operator
          containers:
            # ...
            env:
            # ...
            - name: "FIPS_MODE"
              value: "disabled" 1
      # ...

    1
    禁用 FIPS 模式。

    或者,直接编辑 部署

    oc edit deployment strimzi-cluster-operator
  2. 如果您更新了 YAML 文件而不是直接编辑 Deployment,请应用更改:

    oc apply -f install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml

8.6. 配置 Kafka Connect

更新 KafkaConnect 自定义资源的 spec 属性来配置 Kafka Connect 部署。

使用 Kafka Connect 为 Kafka 集群设置外部数据连接。使用 KafkaConnect 资源的属性来配置 Kafka Connect 部署。

要深入了解 Kafka Connect 集群配置选项,请参阅 AMQ Streams 自定义资源 API 参考

KafkaConnector 配置

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

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

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

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

处理大量信息

您可以调整配置以处理大量信息。如需更多信息,请参阅处理大量信息

KafkaConnect 自定义资源配置示例

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/2.1.3.Final/debezium-connector-postgres-2.1.3.Final-plugin.tar.gz
            sha512sum: c4ddc97846de561755dc0b021a62aba656098829c70eb3ade3b817ce06d852ca12ae50c0281cc791a5a131cb7fc21fb15f4b8ee76c6cae5dd07f9c11cb7c6e79
      - name: camel-telegram
        artifacts:
          - type: tgz
            url: https://repo.maven.apache.org/maven2/org/apache/camel/kafkaconnector/camel-telegram-kafka-connector/0.11.5/camel-telegram-kafka-connector-0.11.5-package.tar.gz
            sha512sum: d6d9f45e0d1dbfcc9f6d1c7ca2046168c764389c78bc4b867dab32d24f710bb74ccf2a007d7d7a8af2dfca09d9a52ccbc2831fc715c195a3634cca055185bd91
  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: OTEL_SERVICE_NAME
          value: my-otel-service
        - name: OTEL_EXPORTER_OTLP_ENDPOINT
          value: "http://otlp-host:4317"
  tracing:
    type: opentelemetry 21

1
使用 KafkaConnect
2
为 Kafka Connect 集群启用 KafkaConnectors。
3
运行任务的 worker 的副本节点数量。
4
Kafka Connect 集群的身份验证,指定为 mTLS、基于令牌的 OAuth、基于 SASL 的 SCRAM-SHA-256/SCRAM-SHA-512 或 PLAIN。默认情况下,Kafka Connect 使用纯文本连接连接到 Kafka 代理。
5
用于连接到 Kafka 集群的 bootstrap 服务器。
6
TLS 加密,使用密钥名称,其中 TLS 证书存储为集群的 X.509 格式。如果证书存储在同一 secret 中,则可以多次列出。
7
worker 的 Kafka 连接配置(而不是连接器)。标准 Apache Kafka 配置可能会提供,仅限于不直接由 AMQ Streams 管理的属性。
8
构建用于自动使用连接器插件构建容器镜像的配置属性。
9
(必需)推送新镜像的容器 registry 的配置。
10
(必需)添加到新容器镜像的连接器插件及其工件列表。每个插件必须配置至少一个 工件
11
使用环境变量的连接器的外部配置,如此处或卷所示。您还可以使用配置供应商插件从外部来源加载配置值。
12
用于保留支持的资源、当前 cpu 和内存 以及限制的请求,以指定可消耗的最大资源。
13
指定 Kafka Connect 日志记录器和日志级别直接(内联)或通过 ConfigMap 间接(外部)。自定义 Log4j 配置必须放在 ConfigMap 中的 log4j.propertieslog4j2.properties 键下。对于 Kafka Connect log4j.rootLogger 日志记录器,您可以将日志级别设置为 INFO, ERROR, WARN, TRACE, DEBUG,FATAL 或 OFF。
14
健康检查以了解何时重启容器(持续)以及容器可以接受流量(就绪状态)。
15
Prometheus 指标,通过引用包含在此示例中 Prometheus JMX 导出器配置的 ConfigMap 启用。您可以使用对 metricsConfig.valueFrom.configMapKeyRef.key 下包含空文件的 ConfigMap 的引用来启用指标。
16
JVM 配置选项,用于优化运行 Kafka Connect 的虚拟机(VM)的性能。
17
ADVANCED OPTION:容器镜像配置,这只在特殊情况下建议使用。
18
SPECIALIZED OPTION:部署的机架感知配置。这是用于在同一位置(而非跨地区)部署的专用选项。如果您希望连接器从最接近的副本而不是领导副本使用,则使用此选项。在某些情况下,使用来自最接近的副本的消耗可以提高网络利用率或降低成本。topologyKey 必须与包含机架 ID 的节点标签匹配。此配置中使用的示例使用标准 topology.kubernetes.io/zone 标签指定区。要从最接近的副本使用,请在 Kafka 代理配置中启用 RackAwareReplicaSelector
19
模板自定义。此处的 pod 使用反关联性调度,因此 pod 不会调度到具有相同主机名的节点。
20
为分布式追踪设置环境变量。
21
使用 OpenTelemetry 启用分布式追踪。

8.6.1. 配置 Kafka Connect 用户授权

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

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

消费者组和内部主题的属性由 AMQ Streams 自动配置,也可以在 KafkaConnect 资源的 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 中的 Kafka Connect 集群 ID。
2
存储连接器偏移的 Kafka 主题。
3
存储连接器和任务状态配置的 Kafka 主题。
4
存储连接器和任务状态更新的 Kafka 主题。

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

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

注意

先决条件

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

流程

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

    在以下示例中,使用 字面 名称值为 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
            operations:
              - Create
              - Describe
              - Read
              - Write
            host: "*"
          # access to status.storage.topic
          - resource:
              type: topic
              name: connect-cluster-status
              patternType: literal
            operations:
              - Create
              - Describe
              - Read
              - Write
            host: "*"
          # access to config.storage.topic
          - resource:
              type: topic
              name: connect-cluster-configs
              patternType: literal
            operations:
              - Create
              - Describe
              - Read
              - Write
            host: "*"
          # consumer group
          - resource:
              type: group
              name: connect-cluster
              patternType: literal
            operations:
              - Read
            host: "*"
  2. 创建或更新资源。

    oc apply -f KAFKA-USER-CONFIG-FILE

8.7. 配置 Kafka MirrorMaker 2

更新 KafkaMirrorMaker2 自定义资源的 spec 属性,以配置 MirrorMaker 2 部署。MirrorMaker 2 使用源集群配置进行数据消耗和目标集群配置进行数据输出。

MirrorMaker 2 基于 Kafka Connect 框架,连接器 管理集群之间的数据传输。

您可以配置 MirrorMaker 2 以定义 Kafka Connect 部署,包括源和目标集群的连接详情,然后运行 MirrorMaker 2 连接器的集合来进行连接。

MirrorMaker 2 支持源和目标集群之间的主题配置同步。您可以在 MirrorMaker 2 配置中指定源主题。MirrorMaker 2 监控源主题。MirrorMaker 2 会检测并将更改传播到源主题到远程主题。更改可能包括自动创建缺少的主题和分区。

注意

在大多数情况下,您写入本地主题并从远程主题读取。虽然对远程主题不阻止写操作,但应该避免使用它们。

配置必须指定:

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

    • 集群到集群
    • topic 的主题

要深入了解 Kafka MirrorMaker 2 集群配置选项,请参阅 AMQ Streams 自定义资源 API 参考

注意

MirrorMaker 2 资源配置与之前的 MirrorMaker 版本不同,它现已弃用。当前不支持旧支持,因此任何资源都必须手动转换为新格式。

默认配置

MirrorMaker 2 为复制因素等属性提供默认配置值。最小配置保持不变,默认值如下:

MirrorMaker 2 的最小配置

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaMirrorMaker2
metadata:
  name: my-mirror-maker2
spec:
  version: 3.5.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: {}

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

您可以在 KafkaMirrorMaker2 资源中指定您要从源集群复制的主题和消费者组。您可以使用 topicsPatterngroupsPattern 属性进行此操作。您可以提供名称列表或使用正则表达式。默认情况下,如果您未设置 topicsPatterngroupsPattern 属性,则会复制所有主题和消费者组。您可以使用 ".*" 正则表达式来复制所有主题和消费者组。但是,尝试只指定您需要指定主题和消费者组,以避免在集群中造成不必要的额外负载。

处理大量信息

您可以调整配置以处理大量信息。如需更多信息,请参阅处理大量信息

KafkaMirrorMaker2 自定义资源配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaMirrorMaker2
metadata:
  name: my-mirror-maker2
spec:
  version: 3.5.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
    tls: 13
      trustedCertificates:
      - certificate: ca.crt
        secretName: my-cluster-target-cluster-ca-cert
  mirrors: 14
  - sourceCluster: "my-cluster-source" 15
    targetCluster: "my-cluster-target" 16
    sourceConnector: 17
      tasksMax: 10 18
      autoRestart: 19
        enabled: true
      config:
        replication.factor: 1 20
        offset-syncs.topic.replication.factor: 1 21
        sync.topic.acls.enabled: "false" 22
        refresh.topics.interval.seconds: 60 23
        replication.policy.class: "org.apache.kafka.connect.mirror.IdentityReplicationPolicy" 24
    heartbeatConnector: 25
      autoRestart:
        enabled: true
      config:
        heartbeats.topic.replication.factor: 1 26
        replication.policy.class: "org.apache.kafka.connect.mirror.IdentityReplicationPolicy"
    checkpointConnector: 27
      autoRestart:
        enabled: true
      config:
        checkpoints.topic.replication.factor: 1 28
        refresh.groups.interval.seconds: 600 29
        sync.group.offsets.enabled: true 30
        sync.group.offsets.interval.seconds: 60 31
        emit.checkpoints.interval.seconds: 60 32
        replication.policy.class: "org.apache.kafka.connect.mirror.IdentityReplicationPolicy"
    topicsPattern: "topic1|topic2|topic3" 33
    groupsPattern: "group1|group2|group3" 34
  resources: 35
    requests:
      cpu: "1"
      memory: 2Gi
    limits:
      cpu: "2"
      memory: 2Gi
  logging: 36
    type: inline
    loggers:
      connect.root.logger.level: INFO
  readinessProbe: 37
    initialDelaySeconds: 15
    timeoutSeconds: 5
  livenessProbe:
    initialDelaySeconds: 15
    timeoutSeconds: 5
  jvmOptions: 38
    "-Xmx": "1g"
    "-Xms": "1g"
  image: my-org/my-image:latest 39
  rack:
    topologyKey: topology.kubernetes.io/zone 40
  template: 41
    pod:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: application
                    operator: In
                    values:
                      - postgresql
                      - mongodb
              topologyKey: "kubernetes.io/hostname"
    connectContainer: 42
      env:
        - name: OTEL_SERVICE_NAME
          value: my-otel-service
        - name: OTEL_EXPORTER_OTLP_ENDPOINT
          value: "http://otlp-host:4317"
  tracing:
    type: opentelemetry 43
  externalConfiguration: 44
    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
运行任务的 worker 的副本节点数量。
3
Kafka Connect 的 Kafka 集群别名,它必须 指定目标 Kafka 集群。Kafka Connect 使用 Kafka 集群用于其内部主题。
4
正在同步的 Kafka 集群的规格。
5
源 Kafka 集群的集群别名。
6
源集群的身份验证,指定为 mTLS、基于令牌的 OAuth、基于 SASL 的 SCRAM-SHA-256/SCRAM-SHA-512 或 PLAIN。
7
用于连接到源 Kafka 集群的 Bootstrap 服务器。
8
TLS 加密,使用密钥名称,其中 TLS 证书存储为源 Kafka 集群的 X.509 格式。如果证书存储在同一 secret 中,则可以多次列出。
9
目标 Kafka 集群的集群别名。
10
目标 Kafka 集群的身份验证配置方式与源 Kafka 集群相同。
11
用于连接到目标 Kafka 集群的 bootstrap 服务器。
12
Kafka Connect 配置。标准 Apache Kafka 配置可能会提供,仅限于不直接由 AMQ Streams 管理的属性。
13
目标 Kafka 集群的 TLS 加密配置方式与源 Kafka 集群相同。
14
MirrorMaker 2 连接器。
15
MirrorMaker 2 连接器使用的源集群的集群别名。
16
MirrorMaker 2 连接器使用的目标集群的集群别名。
17
MirrorSourceConnector 的配置,用于创建远程主题。配置会覆盖 默认配置选项。
18
连接器可创建的最大任务数量。任务处理数据复制并并行运行。如果基础架构支持处理开销,增加这个值可以提高吞吐量。Kafka Connect 在集群成员间分发任务。如果任务数量超过 worker,则 worker 会被分配多个任务。对于 sink 连接器,旨在为每个主题分区消耗一个任务。对于源连接器,可以并行运行的任务数量也可能依赖于外部系统。如果无法实现并行性,则连接器会创建少于最大任务数。
19
启用自动重启失败的连接器和任务。最多进行 7 个重启尝试,之后必须手动重新启动。
20
在目标集群中创建的镜像主题的复制因素。
21
MirrorSourceConnector offset-syncs 内部主题的复制因素,用于映射源和目标集群的偏移。
22
启用 ACL 规则同步后,会将 ACL 应用到同步主题。默认值是 true。此功能与 User Operator 不兼容。如果使用 User Operator,请将此属性设置为 false
23
可选设置,用于更改新主题的检查频率。默认值为每 10 分钟进行一次检查。
24
添加可覆盖远程主题自动重命名的策略。该主题不会用源集群的名称来附加名称,而是保留其原始名称。此可选设置可用于主动/被动备份和数据迁移。必须为所有连接器指定属性。对于双向(active/active)复制,请使用 DefaultReplicationPolicy 类自动重命名远程主题,并为所有连接器指定 replication.policy.separator 属性来添加自定义分隔符。
25
执行连接检查的 MirrorHeartbeatConnector 的配置。配置会覆盖 默认配置选项。
26
在目标集群中创建的心跳主题的复制因素。
27
用于跟踪偏移的 MirrorCheckpointConnector 的配置。配置会覆盖 默认配置选项。
28
在目标集群中创建的检查点主题的复制因素。
29
可选设置,用于更改新消费者组的检查频率。默认值为每 10 分钟进行一次检查。
30
用于同步消费者组偏移的可选设置,这对于在主动/被动配置中恢复非常有用。默认不启用同步。
31
如果启用了使用者组偏移的同步,您可以调整同步的频率。
32
调整检查偏移跟踪的频率。如果您更改了偏移同步的频率,您可能需要调整这些检查的频率。
33
定义为以逗号分隔的列表或正则表达式模式的源集群的主题复制。源连接器复制指定的主题。checkpoint 连接器跟踪指定主题的偏移。此处我们按名称请求三个主题。
34
从以逗号分隔列表或正则表达式模式定义的源集群的消费者组复制。checkpoint 连接器复制指定的消费者组。此处我们按名称请求三个消费者组。
35
用于保留支持的资源、当前 cpu 和内存 以及限制的请求,以指定可消耗的最大资源。
36
指定 Kafka Connect 日志记录器和日志级别直接(内联)或通过 ConfigMap 间接(外部)。自定义 Log4j 配置必须放在 ConfigMap 中的 log4j.propertieslog4j2.properties 键下。对于 Kafka Connect log4j.rootLogger 日志记录器,您可以将日志级别设置为 INFO, ERROR, WARN, TRACE, DEBUG,FATAL 或 OFF。
37
健康检查以了解何时重启容器(持续)以及容器可以接受流量(就绪状态)。
38
JVM 配置选项,用于优化运行 Kafka MirrorMaker 的虚拟机(VM)的性能。
39
ADVANCED OPTION:容器镜像配置,这只在特殊情况下建议使用。
40
SPECIALIZED OPTION:部署的机架感知配置。这是用于在同一位置(而非跨地区)部署的专用选项。如果您希望连接器从最接近的副本而不是领导副本使用,则使用此选项。在某些情况下,使用来自最接近的副本的消耗可以提高网络利用率或降低成本。topologyKey 必须与包含机架 ID 的节点标签匹配。此配置中使用的示例使用标准 topology.kubernetes.io/zone 标签指定区。要从最接近的副本使用,请在 Kafka 代理配置中启用 RackAwareReplicaSelector
41
模板自定义。此处的 pod 使用反关联性调度,因此 pod 不会调度到具有相同主机名的节点。
42
为分布式追踪设置环境变量。
43
使用 OpenTelemetry 启用分布式追踪。
44
作为环境变量挂载到 Kafka MirrorMaker 的 OpenShift Secret 的外部配置。您还可以使用配置供应商插件从外部来源加载配置值。

8.7.1. 配置主动/主动或主动/被动模式

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

主动/主动集群配置
主动/主动配置有两个主动集群双向复制数据。应用程序可以使用任一集群。每个集群都可以提供相同的数据。这样,您可以在不同的地理位置提供相同的数据。因为消费者组在两个集群中都活跃,复制主题的使用者偏移不会重新同步到源集群。
主动/被动集群配置
主动/被动配置具有主动集群将数据复制到被动集群。被动集群保持在待机状态。在出现系统失败时,您可以使用被动集群进行数据恢复。

预期的结构是,生成者和消费者仅连接到活跃集群。每个目标目的地都需要一个 MirrorMaker 2 集群。

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

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

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

图 8.1. 主题重命名

MirrorMaker 2 双向架构

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

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

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

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

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

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

8.7.2. 配置 MirrorMaker 2 连接器

将 MirrorMaker 2 连接器配置用于编配 Kafka 集群之间的数据同步的内部连接器。

MirrorMaker 2 由以下连接器组成:

MirrorSourceConnector
源连接器将主题从源集群复制到目标集群。它还复制 ACL,且是 MirrorCheckpointConnector 才能运行所必需的。
MirrorCheckpointConnector
checkpoint 连接器会定期跟踪偏移。如果启用,它还在源和目标集群之间同步消费者组偏移。
MirrorHeartbeatConnector
heartbeat 连接器会定期检查源和目标集群之间的连接。

下表描述了连接器属性以及您配置为使用它们的连接器。

表 8.2. MirrorMaker 2 连接器配置属性
属性sourceConnectorcheckpointConnectorheartbeatConnector
admin.timeout.ms
管理任务的超时,如检测新主题。默认值为 60000 (1 分钟)。

replication.policy.class
定义远程主题命名约定的策略。默认为 org.apache.kafka.connect.mirror.DefaultReplicationPolicy

replication.policy.separator
在目标集群中用于主题命名的分隔符。默认情况下,分隔符设置为点(.)。分隔符配置仅适用于 DefaultReplicationPolicy 复制策略类,用于定义远程主题名称。IdentityReplicationPolicy 类不使用属性,因为主题会保留其原始名称。

consumer.poll.timeout.ms
轮询源集群时超时。默认值为 1000 (1 秒)。

 
offset-syncs.topic.location
offset-syncs 主题的位置,可以是 (默认)或 目标集群

 
topic.filter.class
选择要复制的主题的主题过滤器。默认为 org.apache.kafka.connect.mirror.DefaultTopicFilter

 
config.property.filter.class
用于选择要复制的主题配置属性的主题过滤器。默认为 org.apache.kafka.connect.mirror.DefaultConfigPropertyFilter

  
config.properties.exclude
不应复制的主题配置属性。支持以逗号分隔的属性名称和正则表达式。

  
offset.lag.max
在同步远程分区前,最大允许(不同步)偏移滞后。默认值为 100

  
offset-syncs.topic.replication.factor
内部 offset-syncs 主题的复制因素。默认值为 3

  
refresh.topics.enabled
启用检查新主题和分区。默认为 true

  
refresh.topics.interval.seconds
主题刷新的频率。默认为 600 (10 分钟)。默认情况下,检查源集群中的新主题每 10 分钟进行一次。您可以通过在源连接器配置中添加 refresh.topics.interval.seconds 来更改频率。

  
replication.factor
新主题的复制因素。默认值为 2

  
sync.topic.acls.enabled
启用从源集群同步 ACL。默认为 true。如需更多信息,请参阅 第 8.7.5 节 “为远程主题同步 ACL 规则”

  
sync.topic.acls.interval.seconds
ACL 同步的频率。默认为 600 (10 分钟)。

  
sync.topic.configs.enabled
启用从源集群同步主题配置。默认为 true

  
sync.topic.configs.interval.seconds
主题配置同步的频率。默认 600 (10 分钟)。

  
checkpoints.topic.replication.factor
内部 检查点 主题的复制因素。默认值为 3
 

 
emit.checkpoints.enabled
启用将消费者偏移同步到目标集群。默认为 true
 

 
emit.checkpoints.interval.seconds
消费者偏移同步的频率。默认值为 60 (1 分钟)。
 

 
group.filter.class
组过滤器,以选择要复制的消费者组。默认为 org.apache.kafka.connect.mirror.DefaultGroupFilter
 

 
refresh.groups.enabled
启用检查新的消费者组。默认为 true
 

 
refresh.groups.interval.seconds
消费者组刷新的频率。默认为 600 (10 分钟)。
 

 
sync.group.offsets.enabled
启用将消费者组偏移同步到目标集群 __consumer_offsets 主题。默认为 false
 

 
sync.group.offsets.interval.seconds
消费者组偏移同步的频率。默认值为 60 (1 分钟)。
 

 
emit.heartbeats.enabled
在目标集群中启用连接检查。默认为 true
  

emit.heartbeats.interval.seconds
连接检查的频率。默认为 1 ( 1 秒)。
  

heartbeats.topic.replication.factor
内部 心跳 主题的复制因素。默认值为 3
  

8.7.2.1. 更改消费者组偏移主题的位置

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

offset-syncs 主题
offset-syncs 主题映射复制主题元数据的源和目标偏移。
checkpoints 主题
checkpoints 主题映射源和目标集群中每个消费者组中复制的主题分区的最后提交偏移量。

因为它们被 MirrorMaker 2 内部使用,所以您不会直接与这些主题交互。

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

offset-syncs 主题的位置是 源集群。您可以使用 offset-syncs.topic.location 连接器配置将其更改为 目标集群。您需要对包含该主题的集群进行读/写访问。使用目标集群作为 offset-syncs 主题的位置,您也可以使用 MirrorMaker 2,即使您只有对源集群的读访问权限。

8.7.2.2. 同步消费者组偏移

__consumer_offsets 主题存储各个消费者组的提交偏移信息。偏移同步会定期将源集群的消费者组的使用者偏移转移到目标集群的使用者偏移量中。

偏移同步在主动/被动配置中特别有用。如果主动集群停机,消费者应用程序可以切换到被动(standby)集群,并从最后一个传输的偏移位置获取。

要使用主题偏移同步,请通过将 sync.group.offsets.enabled 添加到检查点连接器配置来启用同步,并将属性设置为 true。默认情况下禁用同步。

在源连接器中使用 IdentityReplicationPolicy 时,还必须在检查点连接器配置中进行配置。这样可确保为正确的主题应用镜像的消费者偏移。

消费者偏移仅针对目标集群中未激活的消费者组同步。如果消费者组位于目标集群中,则无法执行同步,并返回 UNKNOWN_MEMBER_ID 错误。

如果启用,则会定期从源集群同步偏移。您可以通过在检查点连接器配置中添加 sync.group.offsets.interval.secondsemit.checkpoints.interval.seconds 来更改频率。属性指定同步消费者组偏移的频率,以及为偏移跟踪发送检查点的频率。这两个属性的默认值为 60 秒。您还可以使用 refresh.groups.interval.seconds 属性更改检查新消费者组的频率,该属性默认为每 10 分钟执行。

由于同步基于时间,因此消费者到被动集群的任何切换都可能会导致一些消息重复。

注意

如果您有使用 Java 编写的应用程序,您可以使用 RemoteClusterUtils.java 工具通过应用同步偏移。实用程序从 checkpoints 主题获取消费者组的远程偏移。

8.7.2.3. 决定使用 heartbeat 连接器的时间

heartbeat 连接器发出心跳来检查源和目标 Kafka 集群之间的连接。内部 心跳 主题从源集群复制,这意味着 heartbeat 连接器必须连接到源集群。heartbeat 主题位于目标集群上,它允许它执行以下操作:

  • 识别它要从中镜像数据的所有源集群
  • 验证镜像进程的存活度和延迟

这有助于确保进程不会因为任何原因而卡住或已停止。虽然 heartbeat 连接器是监控 Kafka 集群之间的镜像进程的有价值的工具,但并非总是需要使用它。例如,如果您的部署具有低网络延迟或少量主题,您可能需要使用日志消息或其他监控工具来监控镜像过程。如果您决定不使用 heartbeat 连接器,只需从 MirrorMaker 2 配置中省略它。

8.7.2.4. 对齐 MirrorMaker 2 连接器的配置

为确保 MirrorMaker 2 连接器正常工作,请确保在连接器之间保持一致某些配置设置。具体来说,请确保以下属性在所有适用的连接器中具有相同的值:

  • replication.policy.class
  • replication.policy.separator
  • offset-syncs.topic.location
  • topic.filter.class

例如,source、检查点和 heartbeat 连接器的 replication.policy.class 的值必须相同。不匹配或缺失的设置会导致数据复制或偏移同步出现问题,因此必须使用同一设置保持所有相关连接器配置。

8.7.3. 配置 MirrorMaker 2 连接器制作者和消费者

MirrorMaker 2 连接器使用内部生产者和消费者。如果需要,您可以配置这些制作者和消费者来覆盖默认设置。

例如,您可以增加源制作者的 batch.size,将主题发送到目标 Kafka 集群,以更好地容纳大量信息。

重要

生产者和消费者配置选项取决于 MirrorMaker 2 的实施,并可能随时更改。

下表描述了每个连接器的生产者和消费者,以及您可以添加配置的位置。

表 8.3. 源连接器生成者和消费者
类型Description配置

制作者

将主题信息发送到目标 Kafka 集群。在处理大量数据时,请考虑调整此制作者的配置。

mirrors.sourceConnector.config: producer.override.*

制作者

写入 offset-syncs 主题,它将映射复制主题分区的源和目标偏移。

mirrors.sourceConnector.config: producer.*

消费者

从源 Kafka 集群检索主题信息。

mirrors.sourceConnector.config: consumer.*

表 8.4. Checkpoint 连接器生成者和消费者
类型Description配置

制作者

发送消费者偏移检查点。

mirrors.checkpointConnector.config: producer.override.*

消费者

加载 offset-syncs 主题。

mirrors.checkpointConnector.config: consumer.*

注意

您可以将 offset-syncs.topic.location 设置为 target 来使用目标 Kafka 集群作为 offset-syncs 主题的位置。

表 8.5. heartbeat 连接器制作者
类型Description配置

制作者

发送心跳。

mirrors.heartbeatConnector.config: producer.override prerequisites

以下示例演示了如何配置制作者和消费者。

连接器制作者和消费者的配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaMirrorMaker2
metadata:
  name: my-mirror-maker2
spec:
  version: 3.5.0
  # ...
  mirrors:
  - sourceCluster: "my-cluster-source"
    targetCluster: "my-cluster-target"
    sourceConnector:
      tasksMax: 5
      config:
        producer.override.batch.size: 327680
        producer.override.linger.ms: 100
        producer.request.timeout.ms: 30000
        consumer.fetch.max.bytes: 52428800
        # ...
    checkpointConnector:
      config:
        producer.override.request.timeout.ms: 30000
        consumer.max.poll.interval.ms: 300000
        # ...
    heartbeatConnector:
      config:
        producer.override.request.timeout.ms: 30000
        # ...

8.7.4. 指定最大数据复制任务数

连接器创建负责在 Kafka 中移动数据的任务。每个连接器由一个或多个任务组成,它们分布到运行任务的一组 worker pod 中。在复制大量分区或同步大量消费者组的偏移时,增加任务数量可以帮助解决性能问题。

任务并行运行。为 worker 分配一个或多个任务。单个任务由一个 worker pod 处理,因此您不需要多个 worker pod 超过任务。如果有多个任务,worker 会处理多个任务。

您可以使用 tasksMax 属性指定 MirrorMaker 配置中的最大连接器任务数量。在不指定最大任务数量的情况下,默认设置是单个任务。

heartbeat 连接器始终使用单个任务。

为源和检查点连接器启动的任务数量是最大可能任务数和 tasksMax 的值之间的较低值。对于源连接器,可能的最大任务数是从源集群复制的每个分区。对于检查点连接器,可能的最大任务数都是从源集群复制的每个消费者组。在设置最多任务数量时,请考虑分区数量和支持进程的硬件资源。

如果基础架构支持处理开销,增加任务数量可以提高吞吐量和延迟。例如,添加更多任务可减少在有大量分区或消费者组时轮询源集群所需的时间。

当您有大量分区时,为源连接器增加任务数量很有用。

为源连接器增加任务数量

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaMirrorMaker2
metadata:
  name: my-mirror-maker2
spec:
  # ...
  mirrors:
  - sourceCluster: "my-cluster-source"
    targetCluster: "my-cluster-target"
    sourceConnector:
      tasksMax: 10
  # ...

当您有大量消费者组时,为检查点连接器增加任务数量很有用。

增加检查点连接器的任务数量

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaMirrorMaker2
metadata:
  name: my-mirror-maker2
spec:
  # ...
  mirrors:
  - sourceCluster: "my-cluster-source"
    targetCluster: "my-cluster-target"
    checkpointConnector:
      tasksMax: 10
  # ...

默认情况下,MirrorMaker 2 每 10 分钟检查新消费者组。您可以调整 refresh.groups.interval.seconds 配置以更改频率。在调整降低时请小心。更频繁的检查可能会对性能造成负面影响。

8.7.4.1. 检查连接器任务操作

如果使用 Prometheus 和 Grafana 监控部署,您可以检查 MirrorMaker 2 性能。AMQ Streams 提供的 MirrorMaker 2 Grafana 仪表板示例显示了与任务和延迟相关的以下指标。

  • 任务数量
  • 复制延迟
  • 偏移同步延迟

8.7.5. 为远程主题同步 ACL 规则

将 MirrorMaker 2 与 AMQ Streams 搭配使用时,可以同步远程主题的 ACL 规则。但是,只有在您没有使用 User Operator 时,此功能才可用。

如果您使用 类型:在没有 User Operator 的情况下进行简单 授权,管理对代理的访问的 ACL 规则也适用于远程主题。这意味着,对源主题具有读取访问权限的用户也可以读取其远程等效内容。

注意

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

8.7.6. 保护 Kafka MirrorMaker 2 部署

此流程描述了概述保护 MirrorMaker 2 部署所需的配置。

源 Kafka 集群和目标 Kafka 集群需要单独的配置。您还需要单独的用户配置来提供 MirrorMaker 连接到源和目标 Kafka 集群所需的凭证。

对于 Kafka 集群,您可以为 OpenShift 集群内的安全连接指定内部监听程序,以及用于 OpenShift 集群外的连接的外部监听程序。

您可以配置身份验证和授权机制。为源和目标 Kafka 集群实施的安全选项必须与为 MirrorMaker 2 实施的安全选项兼容。

创建集群和用户身份验证凭证后,您可以在 MirrorMaker 配置中指定它们以进行安全连接。

注意

在此过程中,会使用 Cluster Operator 生成的证书,但 您可以通过安装自己的证书 来替换它们。您还可以将监听程序 配置为使用由外部 CA (证书颁发机构)管理的 Kafka 侦听器证书

开始前

在开始这个过程前,请查看 AMQ Streams 提供的示例配置文件。它们包括使用 mTLS 或 SCRAM-SHA-512 身份验证保护 MirrorMaker 2 部署的示例。示例指定用于在 OpenShift 集群内连接的内部监听程序。

这个示例提供了完整的授权配置,包括 MirrorMaker 2 所需的所有 ACL,以允许对源和目标 Kafka 集群的操作。

先决条件

  • AMQ Streams 正在运行
  • 源和目标集群的独立命名空间

此流程假设将源和目标集群安装到单独的命名空间,如果要使用 Topic Operator,则需要这样做。主题 Operator 只监视指定命名空间中的单个集群。

通过将集群划分为命名空间,您需要复制集群 secret,以便可以在命名空间外访问它们。您需要引用 MirrorMaker 配置中的 secret。

流程

  1. 配置两个 Kafka 资源,一个用于保护源 Kafka 集群,另一个用于保护目标 Kafka 集群。

    您可以为身份验证和启用授权添加监听程序配置。

    在本例中,为带有 TLS 加密和 mTLS 身份验证的 Kafka 集群配置了内部监听程序。启用 Kafka 简单 授权。

    使用 TLS 加密和 mTLS 身份验证的源 Kafka 集群配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-source-cluster
    spec:
      kafka:
        version: 3.5.0
        replicas: 1
        listeners:
          - name: tls
            port: 9093
            type: internal
            tls: true
            authentication:
              type: tls
        authorization:
          type: simple
        config:
          offsets.topic.replication.factor: 1
          transaction.state.log.replication.factor: 1
          transaction.state.log.min.isr: 1
          default.replication.factor: 1
          min.insync.replicas: 1
          inter.broker.protocol.version: "3.5"
        storage:
          type: jbod
          volumes:
          - id: 0
            type: persistent-claim
            size: 100Gi
            deleteClaim: false
      zookeeper:
        replicas: 1
        storage:
          type: persistent-claim
          size: 100Gi
          deleteClaim: false
      entityOperator:
        topicOperator: {}
        userOperator: {}

    使用 TLS 加密和 mTLS 身份验证的目标 Kafka 集群配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-target-cluster
    spec:
      kafka:
        version: 3.5.0
        replicas: 1
        listeners:
          - name: tls
            port: 9093
            type: internal
            tls: true
            authentication:
              type: tls
        authorization:
          type: simple
        config:
          offsets.topic.replication.factor: 1
          transaction.state.log.replication.factor: 1
          transaction.state.log.min.isr: 1
          default.replication.factor: 1
          min.insync.replicas: 1
          inter.broker.protocol.version: "3.5"
        storage:
          type: jbod
          volumes:
            - id: 0
              type: persistent-claim
              size: 100Gi
              deleteClaim: false
      zookeeper:
        replicas: 1
        storage:
          type: persistent-claim
          size: 100Gi
          deleteClaim: false
      entityOperator:
        topicOperator: {}
        userOperator: {}

  2. 在单独的命名空间中创建或更新 Kafka 资源。

    oc apply -f <kafka_configuration_file> -n <namespace>

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

    证书在 secret < cluster_name> -cluster-ca-cert 中创建。

  3. 配置两个 KafkaUser 资源,一个用于源 Kafka 集群的用户,另一个用于目标 Kafka 集群的用户。

    1. 配置与对应的源和目标 Kafka 集群相同的身份验证和授权类型。例如,如果您在源 Kafka 集群的 Kafka 配置中使用了 tls 验证和 simple 授权类型,请在 KafkaUser 配置中使用相同的。
    2. 配置 MirrorMaker 2 所需的 ACL,以允许对源和目标 Kafka 集群执行操作。

      内部 MirrorMaker 连接器和底层 Kafka Connect 框架使用 ACL。

    mTLS 验证的源用户配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaUser
    metadata:
      name: my-source-user
      labels:
        strimzi.io/cluster: my-source-cluster
    spec:
      authentication:
        type: tls
      authorization:
        type: simple
        acls:
          # MirrorSourceConnector
          - resource: # Not needed if offset-syncs.topic.location=target
              type: topic
              name: mm2-offset-syncs.my-target-cluster.internal
            operations:
              - Create
              - DescribeConfigs
              - Read
              - Write
          - resource: # Needed for every topic which is mirrored
              type: topic
              name: "*"
            operations:
              - DescribeConfigs
              - Read
          # MirrorCheckpointConnector
          - resource:
              type: cluster
            operations:
              - Describe
          - resource: # Needed for every group for which offsets are synced
              type: group
              name: "*"
            operations:
              - Describe
          - resource: # Not needed if offset-syncs.topic.location=target
              type: topic
              name: mm2-offset-syncs.my-target-cluster.internal
            operations:
              - Read

    mTLS 验证的目标用户配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaUser
    metadata:
      name: my-target-user
      labels:
        strimzi.io/cluster: my-target-cluster
    spec:
      authentication:
        type: tls
      authorization:
        type: simple
        acls:
          # Underlying Kafka Connect internal topics to store configuration, offsets, or status
          - resource:
              type: group
              name: mirrormaker2-cluster
            operations:
              - Read
          - resource:
              type: topic
              name: mirrormaker2-cluster-configs
            operations:
              - Create
              - Describe
              - DescribeConfigs
              - Read
              - Write
          - resource:
              type: topic
              name: mirrormaker2-cluster-status
            operations:
              - Create
              - Describe
              - DescribeConfigs
              - Read
              - Write
          - resource:
              type: topic
              name: mirrormaker2-cluster-offsets
            operations:
              - Create
              - Describe
              - DescribeConfigs
              - Read
              - Write
          # MirrorSourceConnector
          - resource: # Needed for every topic which is mirrored
              type: topic
              name: "*"
            operations:
              - Create
              - Alter
              - AlterConfigs
              - Write
          # MirrorCheckpointConnector
          - resource:
              type: cluster
            operations:
              - Describe
          - resource:
              type: topic
              name: my-source-cluster.checkpoints.internal
            operations:
              - Create
              - Describe
              - Read
              - Write
          - resource: # Needed for every group for which the offset is synced
              type: group
              name: "*"
            operations:
              - Read
              - Describe
          # MirrorHeartbeatConnector
          - resource:
              type: topic
              name: heartbeats
            operations:
              - Create
              - Describe
              - Write

    注意

    您可以通过将 type 设置为 tls-external 来使用 User Operator 外部发布的证书。如需更多信息,请参阅 KafkaUserSpec 模式参考

  4. 在您为源和目标 Kafka 集群创建的每个命名空间中创建或更新 KafkaUser 资源。

    oc apply -f <kafka_user_configuration_file> -n <namespace>

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

    User Operator 创建一个名称与 KafkaUser 资源相同的新 secret。secret 包含 mTLS 验证的私钥和公钥。公钥包含在用户证书中,该证书由客户端 CA 签名。

  5. 使用身份验证详情配置 KafkaMirrorMaker2 资源,以连接到源和目标 Kafka 集群。

    带有 TLS 加密和 mTLS 身份验证的 MirrorMaker 2 配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker2
    metadata:
      name: my-mirror-maker-2
    spec:
      version: 3.5.0
      replicas: 1
      connectCluster: "my-target-cluster"
      clusters:
        - alias: "my-source-cluster"
          bootstrapServers: my-source-cluster-kafka-bootstrap:9093
          tls: 1
            trustedCertificates:
              - secretName: my-source-cluster-cluster-ca-cert
                certificate: ca.crt
          authentication: 2
            type: tls
            certificateAndKey:
              secretName: my-source-user
              certificate: user.crt
              key: user.key
        - alias: "my-target-cluster"
          bootstrapServers: my-target-cluster-kafka-bootstrap:9093
          tls: 3
            trustedCertificates:
              - secretName: my-target-cluster-cluster-ca-cert
                certificate: ca.crt
          authentication: 4
            type: tls
            certificateAndKey:
              secretName: my-target-user
              certificate: user.crt
              key: user.key
          config:
            # -1 means it will use the default replication factor configured in the broker
            config.storage.replication.factor: -1
            offset.storage.replication.factor: -1
            status.storage.replication.factor: -1
      mirrors:
        - sourceCluster: "my-source-cluster"
          targetCluster: "my-target-cluster"
          sourceConnector:
            config:
              replication.factor: 1
              offset-syncs.topic.replication.factor: 1
              sync.topic.acls.enabled: "false"
          heartbeatConnector:
            config:
              heartbeats.topic.replication.factor: 1
          checkpointConnector:
            config:
              checkpoints.topic.replication.factor: 1
              sync.group.offsets.enabled: "true"
          topicsPattern: "topic1|topic2|topic3"
          groupsPattern: "group1|group2|group3"

    1
    源 Kafka 集群的 TLS 证书。如果它们位于单独的命名空间中,请将集群 secret 从 Kafka 集群的命名空间中复制。
    2
    使用 TLS 机制访问源 Kafka 集群的用户身份验证。
    3
    目标 Kafka 集群的 TLS 证书。
    4
    访问目标 Kafka 集群的用户身份验证。
  6. 在与目标 Kafka 集群相同的命名空间中创建或更新 KafkaMirrorMaker2 资源。

    oc apply -f <mirrormaker2_configuration_file> -n <namespace_of_target_cluster>

8.8. 配置 Kafka MirrorMaker (已弃用)

更新 KafkaMirrorMaker 自定义资源的 spec 属性,以配置 Kafka MirrorMaker 部署。

您可以使用 TLS 或 SASL 身份验证为生产者和消费者配置访问控制。此流程演示了如何在消费者和生成器端使用 TLS 加密和 mTLS 身份验证的配置。

要深入了解 Kafka MirrorMaker 集群配置选项,请参阅 AMQ Streams 自定义资源 API 参考

重要

Kafka MirrorMaker 1 (称为文档中的 MirrorMaker )已在 Apache Kafka 3.0.0 中弃用,并将在 Apache Kafka 4.0.0 中删除。因此,在 AMQ Streams 中还已弃用了用于部署 Kafka MirrorMaker 1 的 KafkaMirrorMaker 自定义资源。当使用 Apache Kafka 4.0.0 时,KafkaMirrorMaker 资源将从 AMQ Streams 中删除。作为替代方法,在 IdentityReplicationPolicy 中使用 KafkaMirrorMaker2 自定义资源。

KafkaMirrorMaker 自定义资源配置示例

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
  producer:
    bootstrapServers: my-target-cluster-kafka-bootstrap:9092
    abortOnSendFailure: false 9
    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
  include: "my-topic|other-topic" 10
  resources: 11
    requests:
      cpu: "1"
      memory: 2Gi
    limits:
      cpu: "2"
      memory: 2Gi
  logging: 12
    type: inline
    loggers:
      mirrormaker.root.logger: INFO
  readinessProbe: 13
    initialDelaySeconds: 15
    timeoutSeconds: 5
  livenessProbe:
    initialDelaySeconds: 15
    timeoutSeconds: 5
  metricsConfig: 14
   type: jmxPrometheusExporter
   valueFrom:
     configMapKeyRef:
       name: my-config-map
       key: my-key
  jvmOptions: 15
    "-Xmx": "1g"
    "-Xms": "1g"
  image: my-org/my-image:latest 16
  template: 17
    pod:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: application
                    operator: In
                    values:
                      - postgresql
                      - mongodb
              topologyKey: "kubernetes.io/hostname"
    mirrorMakerContainer: 18
      env:
        - name: OTEL_SERVICE_NAME
          value: my-otel-service
        - name: OTEL_EXPORTER_OTLP_ENDPOINT
          value: "http://otlp-host:4317"
  tracing: 19
    type: opentelemetry

1
副本节点的数量。
2
用于消费者和制作者的 Bootstrap 服务器。
3
消费者的组 ID。
4
消费者流的数量。
5
偏移 auto-commit 间隔(以毫秒为单位)。
6
TLS 加密,使用密钥名称,其中 TLS 证书存储为 X.509 格式,用于消费者或生成者。如果证书存储在同一 secret 中,则可以多次列出。
7
为消费者或生成者(指定为 mTLS、基于令牌的 OAuth、基于 SASL 的 SCRAM-SHA-256/SCRAM-SHA-512 或 PLAIN)进行身份验证。
8
consumer 和 producer 的 Kafka 配置选项。
9
如果将 abortOnSendFailure 属性设置为 true,则 Kafka MirrorMaker 将退出,容器将按照消息发送失败重启。
10
从源镜像到目标 Kafka 集群包含的主题列表。
11
用于保留支持的资源、当前 cpu 和内存 以及限制的请求,以指定可消耗的最大资源。
12
指定日志记录器和日志级别直接(内联)或通过 ConfigMap 间接添加(外部)。自定义 Log4j 配置必须放在 ConfigMap 中的 log4j.propertieslog4j2.properties 键下。MirrorMaker 只有一个日志记录器,名为 mirrormaker.root.logger。您可以将日志级别设置为 INFO, ERROR, WARN, TRACE, DEBUG, FATAL 或 OFF。
13
健康检查以了解何时重启容器(持续)以及容器可以接受流量(就绪状态)。
14
Prometheus 指标,通过引用包含在此示例中 Prometheus JMX 导出器配置的 ConfigMap 启用。您可以使用对 metricsConfig.valueFrom.configMapKeyRef.key 下包含空文件的 ConfigMap 的引用来启用指标。
15
JVM 配置选项,用于优化运行 Kafka MirrorMaker 的虚拟机(VM)的性能。
16
ADVANCED OPTION:容器镜像配置,这只在特殊情况下建议使用。
17
模板自定义。此处的 pod 使用反关联性调度,因此 pod 不会调度到具有相同主机名的节点。
18
为分布式追踪设置环境变量。
19
使用 OpenTelemetry 启用分布式追踪。
警告

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

8.9. 配置 Kafka Bridge

更新 KafkaBridge 自定义资源的 spec 属性来配置 Kafka Bridge 部署。

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

要深入了解 Kafka Bridge 集群配置选项,请参阅 AMQ Streams 自定义资源 API 参考

KafkaBridge 自定义资源配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaBridge
metadata:
  name: my-bridge
spec:
  replicas: 3 1
  bootstrapServers: <cluster_name>-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: OTEL_SERVICE_NAME
          value: my-otel-service
        - name: OTEL_EXPORTER_OTLP_ENDPOINT
          value: "http://otlp-host:4317"
  tracing:
    type: opentelemetry 16

1
副本节点的数量。
2
用于连接到目标 Kafka 集群的 bootstrap 服务器。使用 Kafka 集群的名称作为 < cluster_name>
3
TLS 加密,使用密钥名称,其中 TLS 证书存储为源 Kafka 集群的 X.509 格式。如果证书存储在同一 secret 中,则可以多次列出。
4
Kafka Bridge 集群的身份验证,指定为 mTLS、基于令牌的 OAuth、基于 SASL 的 SCRAM-SHA-256/SCRAM-SHA-512 或 PLAIN。默认情况下,Kafka Bridge 在没有身份验证的情况下连接到 Kafka 代理。
5
对 Kafka 代理的 HTTP 访问。
6
CORS 访问指定所选资源和访问方法。请求中的其他 HTTP 标头描述了允许访问 Kafka 集群的源。
7
消费者配置选项。
8
制作者配置选项。
9
用于保留支持的资源、当前 cpu 和内存 以及限制的请求,以指定可消耗的最大资源。
10
指定 Kafka Bridge 日志记录器和日志级别直接(内联)或通过 ConfigMap 间接(外部)。自定义 Log4j 配置必须放在 ConfigMap 中的 log4j.propertieslog4j2.properties 键下。对于 Kafka Bridge loggers,您可以将日志级别设置为 INFO, ERROR, WARN, TRACE, DEBUG, FATAL 或 OFF。
11
JVM 配置选项,用于优化运行 Kafka Bridge 的虚拟机(VM)的性能。
12
健康检查以了解何时重启容器(持续)以及容器可以接受流量(就绪状态)。
13
可选:容器镜像配置,仅在特殊情况下推荐。
14
模板自定义。此处的 pod 使用反关联性调度,因此 pod 不会调度到具有相同主机名的节点。
15
为分布式追踪设置环境变量。
16
使用 OpenTelemetry 启用分布式追踪。

8.10. 配置 Kafka 和 ZooKeeper 存储

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

  • Ephemeral (推荐只在开发时使用)
  • 持久性
  • JBOD (仅限 Kafka )

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

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

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

有关存储配置属性的更多信息,请参阅 schema 参考:

警告

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

8.10.1. 数据存储注意事项

要使 AMQ Streams 正常工作,有效的数据存储基础架构至关重要。我们强烈建议您使用块存储。AMQ Streams 仅测试用于块存储。文件存储(如 NFS)没有被测试,无法保证它可以正常工作。

为您的块存储选择以下选项之一:

注意

AMQ Streams 不需要 OpenShift 原始块卷。

8.10.1.1. 文件系统

Kafka 使用文件系统来存储信息。AMQ Streams 与 XFS 和 ext4 文件系统兼容,它们通常与 Kafka 一起使用。在选择和设置文件系统时,请考虑部署的底层架构和要求。

如需更多信息,请参阅 Kafka 文档中的 Filesystem Selection

8.10.1.2. 磁盘用量

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

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

注意

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

8.10.2. 临时存储

临时数据存储是临时的。节点上的所有 pod 共享本地临时存储空间。只要使用它的 pod 正在运行,数据就会保留。当 pod 被删除时,数据会丢失。虽然 pod 可以在高可用性环境中恢复数据。

由于其临时性质,仅推荐使用临时存储进行开发和测试。

临时存储使用 emptyDir 卷来存储数据。当 pod 分配给节点时,会创建一个 emptyDir 卷。您可以使用 sizeLimit 属性为 emptyDir 设置存储总量。

重要

临时存储不适用于单节点 ZooKeeper 集群或 Kafka 主题,复制因子为 1。

要使用临时存储,您可以将 KafkaZooKeeper 资源中的存储类型配置设置为 临时

临时存储配置示例

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

8.10.2.1. Kafka 日志目录的挂载路径

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

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

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

8.10.3. 持久性存储

持久数据存储在系统中断时保留数据。对于使用持久数据存储的 pod,数据会在 pod 失败后保留,并重启。

动态置备框架可创建带有持久性存储的集群。Pod 配置使用持久性卷声明 (PVC) 在持久性卷 (PV) 上发出存储请求。PV 是代表存储卷的存储资源。PV 独立于使用它们的 pod。PVC 请求创建 pod 时所需的存储量。PV 的底层存储基础架构不需要理解。如果 PV 与存储条件匹配,PVC 会绑定到 PV。

由于其永久性质,建议在生产环境中使用持久性存储。

PVC 可以通过指定 StorageClass 来请求不同类型的持久性存储。存储类定义存储配置集和动态置备 PV。如果没有指定存储类,则使用默认存储类。持久性存储选项可能包括 SAN 存储类型或本地持久性卷

要使用持久性存储,您可以将 KafkaZooKeeper 资源中的存储类型配置设置为 persistent-claim

在生产环境中,建议进行以下配置:

  • 对于 Kafka,使用一个或多个 type: persistent-claim 卷配置 type: jbod
  • 对于 ZooKeeper,配置 type: persistent-claim

持久性存储还具有以下配置选项:

id (可选)
存储标识号。对于 JBOD 存储声明中定义的存储卷,这个选项是必须的。默认值为 0。
Size (必需)
持久性卷声明的大小,如 "1000Gi"。
(可选)
用于动态卷置备的 OpenShift StorageClass存储类 配置包括详细描述卷配置集的参数。
selector (可选)
配置以指定特定 PV。提供 key:value 对,代表所选卷的标签。
deleteClaim (optional)
布尔值,用于指定在卸载集群时是否删除 PVC。默认为 false
警告

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

Kafka 和 ZooKeeper 持久性存储配置示例

# ...
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:
    storage:
      type: persistent-claim
      size: 1000Gi
# ...

如果没有指定存储类,则使用默认值。以下示例指定了存储类。

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

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

使用选择器 (selector)来指定提供某些功能的标记的持久性卷,如 SSD。

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

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

8.10.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:
      type: jbod
      volumes:
      - id: 0
        type: persistent-claim
        size: 100Gi
        deleteClaim: false
        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 属性目前仅用于覆盖存储类配置。目前不支持对其他存储配置属性覆盖。目前不支持其他存储配置属性。

8.10.3.2. 持久性存储的 PVC 资源

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

data-cluster-name-kafka-idx
用于存储 Kafka 代理 pod idx 数据的卷的 PVC。
data-cluster-name-zookeeper-idx
用于为 ZooKeeper 节点 pod idx 存储数据的卷的 PVC。
8.10.3.3. Kafka 日志目录的挂载路径

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

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

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

8.10.4. 重新调整持久性卷大小

只要存储基础架构支持,就可以调整集群使用的持久性卷而不造成数据丢失的风险。在配置更新后,AMQ Streams 会指示存储基础架构进行更改。使用 persistent-claim 卷的 AMQ Streams 集群支持存储扩展。

只有在每个代理使用多个磁盘时,才能减少存储。在将磁盘中的所有分区移动到同一代理(intra-broker)或同一集群(集群内)中的其他代理后,您可以删除磁盘。

重要

您无法缩小持久性卷的大小,因为它目前在 OpenShift 中不被支持。

先决条件

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

流程

  1. 编辑集群的 Kafka 资源。

    更改 size 属性,以增加分配给 Kafka 集群、ZooKeeper 集群或两者的持久性卷大小。

    • 对于 Kafka 集群,更新 spec.kafka.storage 下的 size 属性。
    • 对于 ZooKeeper 集群,更新 spec.zookeeper.storage 下的 size 属性。

    将卷大小增加到 2000Gi的 Kafka 配置

    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_configuration_file>

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

  3. 验证集群中相关 pod 的存储容量是否已增加:

    oc get pv

    带有增加存储的 Kafka 代理 pod

    NAME               CAPACITY   CLAIM
    pvc-0ca459ce-...   2000Gi     my-project/data-my-cluster-kafka-2
    pvc-6e1810be-...   2000Gi     my-project/data-my-cluster-kafka-0
    pvc-82dc78c9-...   2000Gi     my-project/data-my-cluster-kafka-1

    输出显示了与代理 pod 关联的每个 PVC 的名称。

其他资源

8.10.5. JBOD 存储

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

注意

Kafka 仅支持 JBOD 存储。

JBOD 配置由一个或多个卷描述,每个卷可以是 临时或 持久。JBOD 卷声明的规则和约束与临时存储和持久性存储的规则和约束相同。例如,在置备后,您无法缩小持久性存储卷的大小,或者当类型为 ephemeral 时无法更改 sizeLimit 的值。

要使用 JBOD 存储,您可以将 Kafka 资源中的存储类型配置设置为 jbodvolumes 属性允许您描述组成 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 配置中添加或删除卷。

8.10.5.1. JBOD 存储的 PVC 资源

当持久性存储用于声明 JBOD 卷时,它会创建一个具有以下名称的 PVC:

data-id-cluster-name-kafka-idx
用于存储 Kafka 代理 pod idx 数据的卷的 PVC。id 是用于存储 Kafka 代理 pod 数据的卷的 ID。
8.10.5.2. Kafka 日志目录的挂载路径

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

/var/lib/kafka/data-id/kafka-logidx

其中 id 是用于存储 Kafka 代理 pod idx 数据的卷的 ID。例如 /var/lib/kafka/data-0/kafka-log0

8.10.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_configuration_file>
  3. 创建新主题或将现有分区重新分配给新磁盘。

    提示

    Cruise Control 是一个重新分配分区的有效工具。要执行 intra-broker 磁盘平衡,您可以在 KafkaRebalance.spec 下将 rebalanceDisk 设置为 true

8.10.7. 从 JBOD 存储中删除卷

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

重要

为了避免数据丢失,您必须在删除卷前移动所有分区。

先决条件

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

流程

  1. 从您要删除的磁盘中重新分配所有分区。分区中的任何数据仍被分配给要删除的磁盘。

    提示

    您可以使用 kafka-reassign-partitions.sh 工具重新分配分区。

  2. 编辑 Kafka 资源中的 spec.kafka.storage.volumes 属性。从 volumes 阵列中删除一个或多个 。例如,使用 ids 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_configuration_file>

8.11. 配置 CPU 和内存限值和请求

默认情况下,AMQ Streams Cluster Operator 不会为其部署的操作对象指定 CPU 和内存资源请求和限值。确保足够分配资源对于在 Kafka 中保持稳定性并获得最佳性能至关重要。理想的资源分配取决于您的特定要求和用例。

建议通过 设置适当的请求和限值,为每个容器配置 CPU 和内存资源。

8.12. 配置 pod 调度

为了避免同一 OpenShift 节点上调度的应用程序之间的资源冲突导致性能下降,您可以独立于关键工作负载调度 Kafka pod。这可以通过选择特定节点或专门用于 Kafka 的一组节点来实现。

8.12.1. 指定关联性、容限和拓扑分布限制

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

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

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

  • Pod 关联性和反关联性
  • 节点关联性
8.12.1.1. 使用 pod 反关联性以避免关键应用程序共享节点

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

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

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

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

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

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

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

在专用节点上运行 Kafka 及其组件会有很多优点。没有其他应用程序在同一节点上运行,这可能会导致距离或消耗 Kafka 所需的资源。从而提高了性能和稳定性。

8.12.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"
        # ...

    其中 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"
        # ...

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

  3. 创建或更新资源。

    oc apply -f <kafka_configuration_file>

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

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

先决条件

  • 一个 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_configuration_file>

8.12.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_configuration_file>

8.12.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_configuration_file>

8.13. 配置日志记录级别

在 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 的 namekey 的值是必需的。如果没有设置 namekey,则会使用默认日志记录。

8.13.1. Kafka 组件和 Operator 的日志记录选项

有关为特定 Kafka 组件或 Operator 配置日志记录的更多信息,请参阅以下部分。

8.13.2. 为日志创建 ConfigMap

要使用 ConfigMap 定义日志记录属性,您可以创建 ConfigMap,然后将其引用为资源 spec 中的日志记录定义的一部分。

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

  • Kafka 组件、ZooZ 和 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 的名称,并将 logging.valueFrom.configMapKeyRef.key 设置为此 ConfigMap 中的键。

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

    oc apply -f <kafka_configuration_file>

8.13.3. 配置 Cluster Operator 日志

Cluster Operator 日志记录通过名为 strimzi-cluster-operatorConfigMap 来配置。安装 Cluster Operator 时会创建一个包含日志记录配置的 ConfigMap。文件的 install/cluster-operator/050- ConfigMap -strimzi-cluster-operator.yaml 中描述了此 ConfigMap。您可以通过更改此 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 设置决定了日志记录配置重新加载的频率。您还可以控制 Kafka AdminClientZooKTrustManager、Netty 和 OkHttp 客户端的日志级别。Netnetty 是 AMQ Streams 用于网络通信的框架,而 OkHttp 是用于发出 HTTP 请求的库。

如果在部署 Cluster Operator 时缺少 ConfigMap,则使用默认的日志记录值。

如果在部署 Cluster Operator 后意外删除 ConfigMap,则会使用最近载入的日志配置。创建新的 ConfigMap 以加载新的日志记录配置。

注意

不要从 ConfigMap 中删除 monitorInterval 选项。

8.13.4. 在 AMQ Streams 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 中添加过滤器

要在主题 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 的名称,并将 logging.valueFrom.configMapKeyRef.key 设置为此 ConfigMap 中的键。

    对于主题 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

8.14. 使用 ConfigMap 添加配置

使用 ConfigMap 资源在 AMQ Streams 部署中添加特定的配置。ConfigMap 使用键值对来存储非机密数据。添加到 ConfigMap 的配置数据在一个位置维护,并可在组件间重复使用。

ConfigMap 只能存储以下类型的配置数据:

  • 日志记录配置
  • 指标配置
  • Kafka 连接连接器的外部配置

您不能将 ConfigMap 用于其他配置区域。

在配置组件时,您可以使用 configMapKeyRef 属性添加对 ConfigMap 的引用。

例如,您可以使用 configMapKeyRef 引用为日志记录提供配置的 ConfigMap。您可以使用 ConfigMap 传递一个 Log4j 配置文件。您可以添加对 日志记录配置 的引用。

日志的 ConfigMap 示例

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

要将 ConfigMap 用于指标配置,您可以以同样的方式添加对组件的 metricsConfig 配置的引用。

externalConfiguration 属性从挂载到 pod 的 ConfigMap (或 Secret)中的数据作为环境变量或卷提供。您可以将外部配置数据用于 Kafka Connect 使用的连接器。数据可能与外部数据源相关,提供连接器与该数据源通信所需的值。

例如,您可以使用 configMapKeyRef 属性将 ConfigMap 中的配置数据作为环境变量传递。

提供环境变量值的 ConfigMap 示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: my-connect
spec:
  # ...
  externalConfiguration:
    env:
      - name: MY_ENVIRONMENT_VARIABLE
        valueFrom:
          configMapKeyRef:
            name: my-config-map
            key: my-key

如果您使用外部管理的 ConfigMap,请使用配置供应商加载 ConfigMap 中的数据。

8.14.1. 命名自定义 ConfigMap

AMQ Streams 在部署到 OpenShift 时 创建自己的 ConfigMap 和其他资源。ConfigMap 包含运行组件所需的数据。不得编辑 AMQ Streams 创建的 ConfigMap。

确保您创建的任何自定义 ConfigMap 的名称都与这些默认 ConfigMap 的名称相同。如果它们具有相同的名称,则它们将被覆盖。例如,如果您的 ConfigMap 与 Kafka 集群的 ConfigMap 的名称相同,则在对 Kafka 集群有更新时会覆盖它。

8.15. 从外部来源加载配置值

使用配置提供程序从外部来源加载配置数据。供应商独立于 AMQ Streams 运行。您可以使用它们为所有 Kafka 组件加载配置数据,包括制作者和消费者。您可以在组件的配置中引用外部源并提供访问权限。供应商在不需要重启 Kafka 组件或提取文件的情况下加载数据,即使引用新的外部源。例如,使用 provider 为 Kafka Connect 连接器配置提供凭证。该配置必须包含对外部源的任何访问权限。

8.15.1. 启用配置供应商

您可以使用组件的 spec 配置中的 config.providers 属性启用一个或多个配置供应商。

启用配置供应商的示例配置

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: my-connect
  annotations:
    strimzi.io/use-connector-resources: "true"
spec:
  # ...
  config:
    # ...
    config.providers: env
    config.providers.env.class: io.strimzi.kafka.EnvVarConfigProvider
  # ...

KubernetesSecretConfigProvider
从 OpenShift 机密加载配置数据。您可以在存储配置数据的 secret 中指定 secret 的名称和密钥。此提供程序可用于存储敏感配置数据,如密码或其他用户凭据。
KubernetesConfigMapConfigProvider
从 OpenShift 配置映射加载配置数据。您可以在保存配置数据的配置映射中指定配置映射的名称和密钥。此提供程序可用于存储非敏感配置数据。
EnvVarConfigProvider
从环境变量加载配置数据。您可以指定存储数据的环境变量的名称。此提供程序可用于配置容器中运行的应用程序,例如从从 secret 映射的环境变量加载证书或 JAAS 配置。
FileConfigProvider
从文件中加载配置数据。您可以指定存储数据的文件的路径。此提供程序可用于从挂载到容器中的文件中加载配置数据。
DirectoryConfigProvider
从目录中的文件加载配置数据。您可以指定存储配置文件的目录路径。此提供程序可用于加载多个配置文件并将配置数据整理到单独的文件中。

要使用作为 OpenShift Configuration Provider 插件一部分的 KubernetesSecretConfigProviderKubernetesConfigMapConfigProvider,您必须为包含配置文件的命名空间设置访问权限。

您可以在不设置访问权限的情况下使用其他供应商。您可以通过执行以下操作为 Kafka Connect 或 MirrorMaker 2 提供连接器配置:

  • 将配置映射或 secret 挂载到 Kafka Connect pod 中作为环境变量或卷
  • 在 Kafka Connect 或 MirrorMaker 2 配置中启用 EnvVarConfigProviderFileConfigProviderDirectoryConfigProvider
  • 使用 KafkaConnectKafkaMirrorMaker2 资源 spec 中的 externalConfiguration 属性传递连接器配置

使用供应商有助于防止通过 Kafka Connect REST 接口传递受限信息。您可以使用以下场景使用此方法:

  • 使用连接器用来连接和与数据源通信的值挂载环境变量
  • 使用用于配置 Kafka 连接连接器的值挂载属性文件
  • 将文件挂载到包含 TLS 信任存储的值和连接器使用的密钥存储值的目录中
注意

在为连接器使用新的 SecretConfigMap 时,需要重启,这可能会破坏其他连接器。

8.15.2. 从 secret 或配置映射加载配置值

使用 KubernetesSecretConfigProvider 从 secret 或 KubernetesConfigMapConfigProvider 提供配置属性,以便从配置映射中提供配置属性。

在此过程中,配置映射为连接器提供配置属性。属性指定为配置映射的键值。配置映射作为卷挂载到 Kafka Connect pod 中。

先决条件

  • Kafka 集群正在运行。
  • Cluster Operator 正在运行。
  • 您有一个包含连接器配置的配置映射。

带有连接器属性的配置映射示例

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

流程

  1. 配置 KafkaConnect 资源。

    • 启用 KubernetesConfigMapConfigProvider

    此处显示的规格支持从配置映射和 secret 加载值。

    使用配置映射和 secret 的 Kafka Connect 配置示例

    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.configmaps.class: io.strimzi.kafka.KubernetesConfigMapConfigProvider 2
        config.providers.secrets.class: io.strimzi.kafka.KubernetesSecretConfigProvider 3
      # ...

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

    oc apply -f <kafka_connect_configuration_file>
  3. 创建一个允许访问外部配置映射中值的角色。

    从配置映射中访问值的角色示例

    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 配置映射的角色权限。

  4. 创建角色绑定,以允许访问包含配置映射的命名空间。

    访问包含配置映射的命名空间的角色绑定示例

    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_name > 是 KafkaConnect 自定义资源的名称。

  5. 在连接器配置中引用配置映射。

    引用配置映射的连接器配置示例

    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}
        # ...
    # ...

    占位符结构是 configmaps:<path_and_file_name>:<property>KubernetesConfigMapConfigProvider 从外部配置映射读取并提取 option1 属性值。

8.15.3. 从环境变量加载配置值

使用 EnvVarConfigProvider 将配置属性作为环境变量提供。环境变量可以包含配置映射或 secret 的值。

在此过程中,环境变量为连接器提供与 Amazon AWS 通信的配置属性。连接器必须能够读取 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY。环境变量的值派生自挂载到 Kafka Connect pod 的 secret。

注意

用户定义的环境变量的名称不能以 KAFKA_STRIMZI_ 开头。

先决条件

  • Kafka 集群正在运行。
  • Cluster Operator 正在运行。
  • 您有一个包含连接器配置的 secret。

带有环境变量值的 secret 示例

apiVersion: v1
kind: Secret
metadata:
  name: aws-creds
type: Opaque
data:
  awsAccessKey: QUtJQVhYWFhYWFhYWFhYWFg=
  awsSecretAccessKey: Ylhsd1lYTnpkMjl5WkE=

流程

  1. 配置 KafkaConnect 资源。

    • 启用 EnvVarConfigProvider
    • 使用 externalConfiguration 属性指定环境变量。

    使用外部环境变量的 Kafka 连接配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect
      annotations:
        strimzi.io/use-connector-resources: "true"
    spec:
      # ...
      config:
        # ...
        config.providers: env 1
        config.providers.env.class: io.strimzi.kafka.EnvVarConfigProvider 2
      # ...
      externalConfiguration:
        env:
          - name: AWS_ACCESS_KEY_ID 3
            valueFrom:
              secretKeyRef:
                name: aws-creds 4
                key: awsAccessKey 5
          - name: AWS_SECRET_ACCESS_KEY
            valueFrom:
              secretKeyRef:
                name: aws-creds
                key: awsSecretAccessKey
      # ...

    1
    配置提供程序的别名用于定义其他配置参数。供应商参数使用 config.providers 的别名,格式为 config.providers.${alias}.class
    2
    EnvVarConfigProvider 提供来自环境变量的值。
    3
    环境变量从 secret 中获取一个值。
    4
    包含环境变量的 secret 名称。
    5
    存储在 secret 中的密钥的名称。
    注意

    secretKeyRef 属性引用 secret 中的密钥。如果您使用配置映射而不是 secret,请使用 configMapKeyRef 属性。

  2. 创建或更新资源以启用供应商。

    oc apply -f <kafka_connect_configuration_file>
  3. 在连接器配置中引用环境变量。

    引用环境变量的连接器配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnector
    metadata:
      name: my-connector
      labels:
        strimzi.io/cluster: my-connect
    spec:
      # ...
      config:
        option: ${env:AWS_ACCESS_KEY_ID}
        option: ${env:AWS_SECRET_ACCESS_KEY}
        # ...
    # ...

    占位符结构是 env:<environment_variable_name>EnvVarConfigProvider 从挂载的 secret 中读取并提取环境变量值。

8.15.4. 从目录中的文件加载配置值

使用 FileConfigProvider 从目录中的文件提供配置属性。文件可以是配置映射或 secret。

在此过程中,文件为连接器提供配置属性。数据库用户名和密码被指定为 secret 的属性。secret 作为一个卷挂载到 Kafka Connect pod。卷挂载到路径 /opt/kafka/external-configuration/<volume-name > 上。

先决条件

  • Kafka 集群正在运行。
  • Cluster Operator 正在运行。
  • 您有一个包含连接器配置的 secret。

带有数据库属性的 secret 示例

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
stringData:
  connector.properties: |- 1
    dbUsername: my-username 2
    dbPassword: my-password

1
属性文件格式的连接器配置。
2
配置中使用的数据库用户名和密码属性。

流程

  1. 配置 KafkaConnect 资源。

    • 启用 FileConfigProvider
    • 使用 externalConfiguration 属性指定该文件。

    使用外部属性文件的 Kafka 连接配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect
    spec:
      # ...
      config:
        config.providers: file 1
        config.providers.file.class: org.apache.kafka.common.config.provider.FileConfigProvider 2
      #...
      externalConfiguration:
        volumes:
          - name: connector-config 3
            secret:
              secretName: mysecret 4

    1
    配置提供程序的别名用于定义其他配置参数。
    2
    FileConfigProvider 提供来自属性文件的值。参数使用 config.providers 的别名,格式为 config.providers.${alias}.class
    3
    包含 secret 的卷名称。
    4
    secret 的名称。
  2. 创建或更新资源以启用供应商。

    oc apply -f <kafka_connect_configuration_file>
  3. 将连接器配置中的文件属性引用为占位符。

    引用该文件的连接器配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnector
    metadata:
      name: my-source-connector
      labels:
        strimzi.io/cluster: my-connect-cluster
    spec:
      class: io.debezium.connector.mysql.MySqlConnector
      tasksMax: 2
      config:
        database.hostname: 192.168.99.1
        database.port: "3306"
        database.user: "${file:/opt/kafka/external-configuration/connector-config/mysecret:dbUsername}"
        database.password: "${file:/opt/kafka/external-configuration/connector-config/mysecret:dbPassword}"
        database.server.id: "184054"
        #...

    占位符结构是 文件:<path_and_file_name>:<property>FileConfigProvider 从挂载的 secret 中读取并提取数据库 username 和 password 属性值。

8.15.5. 从目录中的多个文件加载配置值

使用 DirectoryConfigProvider 从目录中的多个文件中提供配置属性。文件可以是配置映射或 secret。

在此过程中,secret 为连接器提供 TLS 密钥存储和信任存储用户凭证。凭据位于单独的文件中。secret 作为卷挂载到 Kafka Connect pod 中。卷挂载到路径 /opt/kafka/external-configuration/<volume-name > 上。

先决条件

  • Kafka 集群正在运行。
  • Cluster Operator 正在运行。
  • 您有一个包含用户凭证的 secret。

使用用户凭证的 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> # Public key of the clients CA
  user.crt: <user_certificate> # Public key of the user
  user.key: <user_private_key> # Private key of the user
  user.p12: <store> # PKCS #12 store for user certificates and keys
  user.password: <password_for_store> # Protects the PKCS #12 store

my-user secret 为连接器提供密钥存储凭据(user.crtuser.key)。

在部署 Kafka 集群时生成的 <cluster_name>-cluster-ca-cert secret 提供集群 CA 证书作为信任存储凭证(ca.crt)。

流程

  1. 配置 KafkaConnect 资源。

    • 启用 DirectoryConfigProvider
    • 使用 externalConfiguration 属性指定文件。

    使用外部属性文件的 Kafka 连接配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect
    spec:
      # ...
      config:
        config.providers: directory 1
        config.providers.directory.class: org.apache.kafka.common.config.provider.DirectoryConfigProvider 2
      #...
      externalConfiguration:
        volumes: 3
          - name: cluster-ca 4
            secret:
              secretName: my-cluster-cluster-ca-cert 5
          - name: my-user
            secret:
              secretName: my-user 6

    1
    配置提供程序的别名用于定义其他配置参数。
    2
    DirectoryConfigProvider 提供来自目录中的文件的值。参数使用 config.providers 的别名,格式为 config.providers.${alias}.class
    3
    包含 secret 的卷名称。
    4
    集群 CA 证书的 secret 名称,以提供信任存储配置。
    5
    用户提供密钥存储配置的 secret 名称。
  2. 创建或更新资源以启用供应商。

    oc apply -f <kafka_connect_configuration_file>
  3. 将连接器配置中的文件属性引用为占位符。

    引用文件的连接器配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnector
    metadata:
      name: my-source-connector
      labels:
        strimzi.io/cluster: my-connect-cluster
    spec:
      class: io.debezium.connector.mysql.MySqlConnector
      tasksMax: 2
      config:
        # ...
        database.history.producer.security.protocol: SSL
        database.history.producer.ssl.truststore.type: PEM
        database.history.producer.ssl.truststore.certificates: "${directory:/opt/kafka/external-configuration/cluster-ca:ca.crt}"
        database.history.producer.ssl.keystore.type: PEM
        database.history.producer.ssl.keystore.certificate.chain: "${directory:/opt/kafka/external-configuration/my-user:user.crt}"
        database.history.producer.ssl.keystore.key: "${directory:/opt/kafka/external-configuration/my-user:user.key}"
        #...

    占位符结构是 directory:<path>:<file_name>DirectoryConfigProvider 从挂载的 secret 中读取并提取凭证。

8.16. 自定义 OpenShift 资源

AMQ Streams 部署会创建 OpenShift 资源,如 DeploymentPodService 资源。这些资源由 AMQ Streams operator 管理。只有负责管理特定 OpenShift 资源的操作器才能更改该资源。如果您尝试手动更改操作器管理的 OpenShift 资源,Operator 将还原您的更改。

如果要执行某些任务,更改 Operator 管理的 OpenShift 资源会很有用,例如:

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

要更改 OpenShift 资源,您可以使用各种 AMQ Streams 自定义资源的 spec 部分中的 template 属性。

以下是您可以应用更改的自定义资源列表:

  • Kafka.spec.kafka
  • Kafka.spec.zookeeper
  • Kafka.spec.entityOperator
  • Kafka.spec.kafkaExporter
  • Kafka.spec.cruiseControl
  • KafkaNodePool.spec
  • KafkaConnect.spec
  • KafkaMirrorMaker.spec
  • KafkaMirrorMaker2.spec
  • KafkaBridge.spec
  • KafkaUser.spec

有关这些属性的更多信息,请参阅 AMQ Streams 自定义资源 API 参考

AMQ Streams 自定义资源 API 参考提供了有关可自定义字段的更多详情。

在以下示例中,template 属性用于修改 Kafka 代理的 pod 中的标签。

模板自定义示例

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

8.16.1. 自定义镜像拉取策略

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

Always
每次 pod 启动或重启时,容器镜像都会从 registry 中拉取。
IfNotPresent
只有在容器镜像之前没有拉取时才从 registry 中拉取容器镜像。
Never
容器镜像从 registry 中拉取。

目前,镜像拉取策略一次只能为所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群自定义。更改策略将导致所有 Kafka、Kafka Connect 和 Kafka MirrorMaker 集群的滚动更新。

其他资源

8.16.2. 应用终止宽限期

应用终止宽限期,为 Kafka 集群提供足够时间来完全关闭。

使用 terminationGracePeriodSeconds 属性指定时间。将属性添加到 Kafka 自定义资源的 template.pod 配置中。

您添加的时间将取决于 Kafka 集群的大小。终止宽限期的 OpenShift 默认为 30 秒。如果您发现集群没有完全关闭,您可以提高终止宽限期。

每次 pod 重启时都会应用终止宽限期。当 OpenShift 发送一个 术语 (termination)信号到容器集中运行的进程时,周期开始。周期应反映在终止 pod 停止前将终止 pod 的进程传输到另一个 pod 所需的时间。在周期结束后,kill 信号将停止 pod 中仍在运行的任何进程。

以下示例为 Kafka 自定义资源添加 120 秒的终止宽限期。您还可以在其他 Kafka 组件的自定义资源中指定配置。

终止宽限期配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
    template:
      pod:
        terminationGracePeriodSeconds: 120
        # ...
    # ...

第 9 章 使用主题 Operator 管理 Kafka 主题

KafkaTopic 资源配置主题,包括分区和复制因素设置。当使用 KafkaTopic 创建、修改或删除主题时,主题 Operator 可确保这些更改反映在 Kafka 集群中。

如需有关 KafkaTopic 资源的更多信息,请参阅 KafkaTopic 模式参考

9.1. 主题管理模式

KafkaTopic 资源负责管理 Kafka 集群中的单个主题。Topic Operator 提供了两种管理 KafkaTopic 资源和 Kafka 主题的模式:

双向模式
双向模式需要 ZooKeeper 用于集群管理。在 KRaft 模式中使用 AMQ Streams 不兼容。
(预览)Unidirectional 模式
单向模式不需要 ZooKeeper 进行集群管理。它在 KRaft 模式中使用 AMQ Streams 兼容。
注意

单向主题管理作为技术预览提供。默认情况下,不启用单向主题管理,因此您必须 启用 UnidirectionalTopicOperator 功能门 才能使用它。

9.1.1. 双向主题管理

在双向模式中,主题 Operator 运行如下:

  • 当创建、删除或更改 KafkaTopic 时,主题 Operator 会在 Kafka 主题上执行对应的操作。
  • 同样,当在 Kafka 集群中创建、删除或更改主题时,主题 Operator 会在 KafkaTopic 资源上执行对应的操作。
提示

尝试坚持管理主题的方法,可以通过 KafkaTopic 资源或在 Kafka 中直接进行。避免在给定主题的两个方法间进行频繁切换。

9.1.2. (预览)Unidirectional 主题管理

在单向模式中,主题 Operator 运行如下:

  • 当创建、删除或更改 KafkaTopic 时,主题 Operator 会在 Kafka 主题上执行对应的操作。

如果在 Kafka 集群中直接创建、删除或修改一个主题,且没有对应的 KafkaTopic 资源,则 Topic Operator 不会管理该主题。Topic Operator 只管理与 KafkaTopic 资源关联的 Kafka 主题,不会影响在 Kafka 集群中独立管理的主题。如果 Kafka 主题存在 KafkaTopic,则会恢复资源外所做的任何配置更改。

9.2. 主题命名约定

KafkaTopic 资源包括主题的名称,以及一个标识它所属的 Kafka 集群名称的标签。

标识 Kafka 集群用于主题处理的标签

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: topic-name-1
  labels:
    strimzi.io/cluster: my-cluster
spec:
  topicName: topic-name-1

该标签提供 Kafka 资源的集群名称。主题 Operator 使用该标签作为确定要管理的 KafkaTopic 资源的机制。如果标签与 Kafka 集群不匹配,则 Topic Operator 无法看到 KafkaTopic,且不会创建主题。

Kafka 和 OpenShift 都有自己的命名验证规则,Kafka 主题名称在 OpenShift 中可能不是有效的资源名称。如果可能,请尝试并坚持适合两者的命名约定。

请考虑以下指南:

  • 使用反映主题性质的主题名称
  • 很简洁,并在 63 个字符下保留名称
  • 使用所有小写和连字符
  • 避免特殊字符、空格或符号

KafkaTopic 资源允许您使用 metadata.name 字段指定 Kafka 主题名称。但是,如果所需的 Kafka 主题名称不是有效的 OpenShift 资源名称,您可以使用 spec.topicName 属性来指定实际名称。spec.topicName 字段是可选的,当不存在时,Kafka 主题名称默认为主题的 metadata.name。创建主题时,无法稍后更改主题名称。

提供有效 Kafka 主题名称的示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: my-topic-1 1
spec:
  topicName: My.Topic.1 2
  # ...

1
在 OpenShift 中工作的有效主题名称。
2
使用大写和句点的 Kafka 主题名称,在 OpenShift 中无效。

如果多个 KafkaTopic 资源引用同一 Kafka 主题,则首先创建的资源被视为管理该主题的资源。更新较新的资源的状态以指示冲突,并且它们的 Ready 状态更改为 False

如果 Kafka 客户端应用程序(如 Kafka Streams)自动创建带有无效 OpenShift 资源名称的主题,则主题 Operator 会在双向模式中使用时生成一个有效的 metadata.name。它替换无效字符,并将哈希附加到名称中。但是,此行为不适用于(预览)单向模式。

替换无效主题名称的示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: my-topic---c55e57fe2546a33f9e603caf57165db4072e827e
  # ...

注意

如需有关集群中标识符和名称要求的更多信息,请参阅 OpenShift 文档 对象名称和 ID

9.3. 处理主题的更改

主题 Operator 如何处理对主题的更改取决于 主题管理的模式

  • 对于双向主题管理,配置更改会在 Kafka 主题和 KafkaTopic 资源之间同步。不兼容的更改会优先选择 Kafka 配置,并相应地调整 KafkaTopic 资源。
  • 对于单向主题管理(当前为预览),配置更改仅进入一个方向:从 KafkaTopic 资源到 Kafka 主题。对 KafkaTopic 资源外管理的 Kafka 主题的任何更改都会被恢复。

9.3.1. 双向主题管理的主题存储

对于双向主题管理,当没有单一数据源时,主题 Operator 能够处理对主题的更改。KafkaTopic 资源和 Kafka 主题可以独立修改,其中实时观察更改可能并不总是可行,特别是在 Topic Operator 无法正常工作时。为了解决这个问题,主题 Operator 维护一个主题存储,用于存储有关每个主题的主题配置信息。它将 Kafka 集群和 OpenShift 的状态与主题存储进行比较,以确定同步所需的更改。此评估在启动期间和定期的间隔发生,而主题 Operator 处于活跃状态时。

例如,如果主题 Operator 不活跃,并且在重启后会创建一个名为 my-topic 的新 KafkaTopic,则主题 Operator 会识别主题存储中没有 my-topic。它识别在最后一次操作后创建的 KafkaTopic。因此,主题 Operator 生成对应的 Kafka 主题,并将元数据保存在主题存储中。

主题存储可让 Topic Operator 管理在 Kafka 主题和 KafkaTopic 资源中更改主题配置的情况,只要更改兼容。当对 KafkaTopic 自定义资源更新或更改 Kafka 主题配置时,主题存储会在与 Kafka 集群协调后更新,只要更改兼容。

主题存储 基于 Kafka Streams 键值机制,它使用 Kafka 主题来保留状态。主题元数据缓存在内存中,并在主题 Operator 中本地访问。应用到本地内存缓存的操作更新会被保留到磁盘上的备份主题存储中。主题存储会与 Kafka 主题或 OpenShift KafkaTopic 自定义资源的更新同步。操作通过以这种方式设置的主题存储快速处理,但应该崩溃内存缓存崩溃,它会自动从持久性存储中重新填充。

内部主题支持处理主题存储中的主题元数据。

__strimzi_store_topic
用于存储主题元数据的输入主题
__strimzi-topic-operator-kstreams-topic-store-changelog
保留紧凑主题存储值的日志
警告

不要删除这些主题,因为它们对于 Topic Operator 的运行至关重要。

9.3.2. 将主题元数据从 ZooKeeper 迁移到主题存储

在之前的 AMQ Streams 版本中,主题元数据存储在 ZooKeeper 中。主题存储会删除这个要求,将元数据带到 Kafka 集群,并受 Topic Operator 控制。

当升级到 AMQ Streams 2.5 时,到主题存储的主题 Operator 控制是无缝的。元数据是从 ZooKeeper 查找并迁移,旧存储被删除。

9.3.3. 降级到使用 ZooKeeper 存储主题元数据的 AMQ Streams 版本

如果您要恢复到早于 1.7 的 AMQ Streams 版本,它使用 ZooKeeper 作为主题元数据存储,您仍会将 Cluster Operator 降级到之前的版本,然后将 Kafka 代理和客户端应用程序降级到以前的 Kafka 版本作为标准。

但是,还必须使用 kafka-topics 命令删除为主题存储创建的主题,指定 Kafka 集群的 bootstrap 地址。例如:

oc run kafka-admin -ti --image=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 --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 集群的监听程序和身份验证类型对应。

主题 Operator 将从 Kafka 中的主题状态重建 ZooKeeper 主题元数据。

9.3.4. 自动创建主题

应用程序可以在 Kafka 集群中触发自动创建主题。默认情况下,Kafka 代理配置 auto.create.topics.enable 被设置为 true,允许代理在应用程序尝试从不存在的主题生成或消耗时自动创建主题。应用程序也可能使用 Kafka AdminClient 自动创建主题。当应用程序与 KafkaTopic 资源一起部署时,在主题 Operator 可以响应 KafkaTopic 前,集群中的自动主题创建可能会发生。

对于双向主题管理,主题 Operator 会同步主题和 KafkaTopic 资源之间的更改。

如果您正在尝试单向主题管理预览,这可能意味着最初为应用部署创建的主题最初创建有默认主题配置。如果主题 Operator 会尝试根据应用程序部署中包含的 KafkaTopic 资源规格重新配置主题,则操作可能会失败,因为不允许对配置进行所需的更改。例如,如果更改意味着减少主题分区的数量。因此,在使用单向主题管理时,建议在 Kafka 集群配置中禁用 auto.create.topics.enable

9.4. 配置 Kafka 主题

使用 KafkaTopic 资源的属性来配置 Kafka 主题。对 KafkaTopic 中主题配置所做的更改会被传播到 Kafka。

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

例如:

  • oc apply -f <topic_config_file>
  • oc delete KafkaTopic <topic_name>

要能够删除主题,必须在 Kafka 资源的 spec.kafka.config 中将 delete.topic.enable 设置为 true (默认)。

此流程演示了如何创建包含 10 个分区和 2 个副本的主题。

注意

该流程与主题管理的双向和(预览)单向模式相同。

开始前

KafkaTopic 资源不允许以下更改:

  • 重命名 spec.topicName 中定义的主题。将检测到 spec.topicNamestatus.topicName 不匹配。
  • 使用 spec.partitions ( Kafka 不支持)减少分区数量。
  • 修改 spec.replicas 中指定的副本数量。
警告

增加带有键的主题的 spec.partitions 将更改记录分区,这可能会导致问题,特别是在主题使用语义分区时。

先决条件

  • 正在运行的 Kafka 集群使用 mTLS 身份验证和 TLS 加密配置 Kafka 代理监听程序。
  • 正在运行的主题 Operator (通常使用 Entity Operator 部署)。
  • 要删除主题,delete.topic.enable=true (默认)在 Kafka 资源的 spec.kafka.config 中。

流程

  1. 配置 KafkaTopic 资源。

    Kafka 主题配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: my-topic-1
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 10
      replicas: 2

    提示

    修改主题时,您可以使用 oc get kafkatopic my-topic-1 -o yaml 获取资源的当前版本。

  2. 在 OpenShift 中创建 KafkaTopic 资源。

    oc apply -f <topic_config_file>
  3. 等待主题的就绪状态更改为 True

    oc get kafkatopics -o wide -w -n <namespace>

    Kafka 主题状态

    NAME         CLUSTER     PARTITIONS  REPLICATION FACTOR READY
    my-topic-1   my-cluster  10          3                  True
    my-topic-2   my-cluster  10          3
    my-topic-3   my-cluster  10          3                  True

    READY 输出显示为 True 时,主题创建成功。

  4. 如果 READY 列留空,请从资源 YAML 或 Topic Operator 日志中获取有关状态的更多详细信息。

    状态信息提供有关当前状态原因的详细信息。

    oc get kafkatopics my-topic-2 -o yaml

    有关具有 NotReady 状态的主题详情

    # ...
    status:
      conditions:
      - lastTransitionTime: "2022-06-13T10:14:43.351550Z"
        message: Number of partitions cannot be decreased
        reason: PartitionDecreaseException
        status: "True"
        type: NotReady

    在本例中,主题未就绪的原因是,原始分区数量在 KafkaTopic 配置中被减少。Kafka 不支持此功能。

    重置主题配置后,status 会显示主题已就绪。

    oc get kafkatopics my-topic-2 -o wide -w -n <namespace>

    主题的状态更新

    NAME         CLUSTER     PARTITIONS  REPLICATION FACTOR READY
    my-topic-2   my-cluster  10          3                  True

    获取详情不显示任何信息

    oc get kafkatopics my-topic-2 -o yaml

    有关具有 READY 状态的主题详情

    # ...
    status:
      conditions:
      - lastTransitionTime: '2022-06-13T10:15:03.761084Z'
        status: 'True'
        type: Ready

9.5. 为复制和分区数量配置主题

由主题 Operator 管理的主题的建议配置是 3 的主题复制因素,最少为 2 个同步副本。

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: my-topic
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 10 1
  replicas: 3 2
  config:
    min.insync.replicas: 2 3
  #...
1
主题的分区数。
2
副本主题分区的数量。目前,无法在 KafkaTopic 资源中更改它,但可以使用 kafka-reassign-partitions.sh 工具进行修改。
3
消息必须成功写入或引发异常的最小副本数。
注意

in-sync 副本与生成者应用程序的 acks 配置一起使用。acks 配置决定了在确认消息被成功收到之前必须复制到的后续分区数量。双向主题 Operator 使用 acks=all 运行,用于其内部主题,其中消息必须被所有同步的副本确认。

当通过添加或删除代理来扩展 Kafka 集群时,复制因素配置不会被更改,且不会自动重新分配副本。但是,您可以使用 kafka-reassign-partitions.sh 工具更改复制因素,并手动将副本重新分配给代理。

另外,虽然 AMQ Streams 的 Cruise Control 集成无法更改主题的复制因素,但为重新平衡 Kafka 生成的优化提议包括传输分区副本和更改分区领导的命令。

9.6. (预览)管理 KafkaTopic 资源,而不影响 Kafka 主题

此流程描述了如何当前通过 KafkaTopic 资源管理的 Kafka 主题转换为非管理的主题。此功能在各种情况下非常有用。例如,您可能想要更新 KafkaTopic 资源的 metadata.name。您只能通过删除原始 KafkaTopic 资源并重新创建新资源来完成此操作。

通过使用 strimzi.io/managed=false 注解 KafkaTopic 资源,这表示 Topic Operator 应该不再管理该特定主题。这可让您在更改资源的配置或其他管理任务时保留 Kafka 主题。

如果您使用单向主题管理,您可以执行此任务。

注意

单向主题管理作为技术预览提供。默认情况下,不启用单向主题管理,因此您必须 启用 UnidirectionalTopicOperator 功能门 才能使用它。

流程

  1. 在 OpenShift 中注解 KafkaTopic 资源,将 strimzi.io/managed 设置为 false

    oc annotate kafkatopic my-topic-1 strimzi.io/managed=false

    KafkaTopic 资源中指定主题的 metadata.name,本例中为 my-topic-1

  2. 检查 KafkaTopic 资源的状态,以确保请求成功:

    oc get kafkatopics my-topic-1 -o yaml

    具有 Ready 状态的主题示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      generation: 124
      name: my-topic-1
      finalizer:
        strimzi.io/topic-operator
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 10
      replicas: 2
    
    # ...
    status:
      observedGeneration: 124 1
      topicName: my-topic-1
      conditions:
      - type: Ready
        status: True
        lastTransitionTime: 20230301T103000Z

    1
    资源成功协调意味着主题不再管理。

    metadata.generation (部署的当前版本)的 值必须与 status.observedGeneration (资源的最新协调)匹配

  3. 现在,您可以在不影响管理的 Kafka 主题的情况下更改 KafkaTopic 资源。

    例如,要更改 metadata.name,请执行以下操作:

    1. 删除原始 KafkTopic 资源:

      oc delete kafkatopic <kafka_topic_name>
    2. 重新创建具有不同 metadata.nameKafkTopic 资源,但使用 spec.topicName 来引用由原始管理的相同主题
  4. 如果您没有删除原始 KafkaTopic 资源,并且您希望再次恢复管理 Kafka 主题,请将 strimzi.io/managed 注解设置为 true 或删除注解。

9.7. (预览)为现有 Kafka 主题启用主题管理

此流程描述了如何为当前没有通过 KafkaTopic 资源管理的主题启用主题管理。您可以通过创建匹配的 KafkaTopic 资源来实现此目的。

如果您使用单向主题管理,您可以执行此任务。

注意

单向主题管理作为技术预览提供。默认情况下,不启用单向主题管理,因此您必须 启用 UnidirectionalTopicOperator 功能门 才能使用它。

流程

  1. 使用与 Kafka 主题相同的 metadata.name 创建 KafkaTopic 资源。

    或者,如果 Kafka 中的主题名称不是法律 OpenShift 资源名称,则使用 spec.topicName

    Kafka 主题配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: my-topic-1
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 10
      replicas: 2

    在本例中,Kafka 主题名为 my-topic-1

    主题 Operator 检查主题是否由另一个 KafkaTopic 资源管理。如果是,旧的资源具有优先权,并在新资源状态中返回资源冲突错误。

  2. 应用 KafkaTopic 资源:

    oc apply -f <topic_configuration_file>
  3. 等待 Operator 更新 Kafka 中的主题。

    Operator 使用具有相同名称的 KafkaTopicspec 更新 Kafka 主题。

  4. 检查 KafkaTopic 资源的状态,以确保请求成功:

    oc get kafkatopics my-topic-1 -o yaml

    具有 Ready 状态的主题示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      generation: 1
      name: my-topic-1
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 10
      replicas: 2
    # ...
    status:
      observedGeneration: 1 1
      topicName: my-topic-1
      conditions:
      - type: Ready
        status: True
        lastTransitionTime: 20230301T103000Z

    1
    对资源成功协调意味着主题现已被管理。

    metadata.generation (部署的当前版本)的 值必须与 status.observedGeneration (资源的最新协调)匹配

9.8. (预览)删除受管主题

单向主题管理支持通过 KafkaTopic 资源删除通过 OpenShift 终结器管理的主题。这由 STRIMZI_USE_FINALIZERS Topic Operator 环境变量控制。默认情况下,这被设置为 true,但如果您不想 主题 Operator 来添加终结器,则可以在主题 Operator env 配置中将其设置为 false

注意

单向主题管理作为技术预览提供。默认情况下,不启用单向主题管理,因此您必须 启用 UnidirectionalTopicOperator 功能门 才能使用它。

终结器(finalizers)可确保按顺序控制地删除 KafkaTopic 资源。Topic Operator 的终结器添加到 KafkaTopic 资源的元数据中:

控制删除主题的终结器

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  generation: 1
  name: my-topic-1
  finalizer:
    strimzi.io/topic-operator
  labels:
    strimzi.io/cluster: my-cluster

在本例中,为主题 my-topic-1 添加了终结器。finalizer 会阻止主题被完全删除,直到最终化过程完成为止。如果使用 oc delete kafkatopic my-topic-1 删除主题,则会在元数据中添加时间戳:

删除时的终结器时间戳

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  generation: 1
  name: my-topic-1
  finalizer:
    strimzi.io/topic-operator
  labels:
    strimzi.io/cluster: my-cluster
  deletionTimestamp: 20230301T000000.000

资源仍然存在。如果删除失败,则会在资源的状态中显示。

当成功执行最终任务时,终结器会从元数据中删除,并且资源会被完全删除。

终结器还阻止相关资源被删除。如果单向主题 Operator 没有运行,则无法删除 metadata.finalizer。因此,在 Operator 重启前,尝试删除包含 KafkaTopic 资源的命名空间不会完成,或者删除终结器(例如,使用 oc edit)。

第 10 章 使用 User Operator 管理 Kafka 用户

当使用 KafkaUser 资源创建、修改或删除用户时,User Operator 可确保这些更改反映在 Kafka 集群中。

有关 KafkaUser 资源的更多信息,请参阅 KafkaUser 模式参考

10.1. 配置 Kafka 用户

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

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

例如:

  • oc apply -f <user_config_file>
  • oc delete KafkaUser <user_name>

用户代表 Kafka 客户端。配置 Kafka 用户时,您可以启用客户端访问 Kafka 所需的用户身份验证和授权机制。使用的机制必须与等同的 Kafka 配置匹配。有关使用 KafkaKafkaUser 资源保护对 Kafka 代理的访问的更多信息,请参阅 保护对 Kafka 代理的访问

先决条件

  • 正在运行的 Kafka 集群使用 mTLS 身份验证和 TLS 加密配置 Kafka 代理监听程序。
  • 正在运行的 User Operator (通常使用 Entity Operator 部署)。

流程

  1. 配置 KafkaUser 资源。

    这个示例使用 ACL 指定 mTLS 身份验证和授权。

    Kafka 用户配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaUser
    metadata:
      name: my-user-1
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      authentication:
        type: tls
      authorization:
        type: simple
        acls:
          # Example consumer Acls for topic my-topic using consumer group my-group
          - resource:
              type: topic
              name: my-topic
              patternType: literal
            operations:
              - Describe
              - Read
            host: "*"
          - resource:
              type: group
              name: my-group
              patternType: literal
            operations:
              - Read
            host: "*"
          # Example Producer Acls for topic my-topic
          - resource:
              type: topic
              name: my-topic
              patternType: literal
            operations:
              - Create
              - Describe
              - Write
            host: "*"

  2. 在 OpenShift 中创建 KafkaUser 资源。

    oc apply -f <user_config_file>
  3. 等待用户的就绪状态更改为 True

    oc get kafkausers -o wide -w -n <namespace>

    Kafka 用户体验

    NAME       CLUSTER     AUTHENTICATION  AUTHORIZATION READY
    my-user-1  my-cluster  tls             simple        True
    my-user-2  my-cluster  tls             simple
    my-user-3  my-cluster  tls             simple        True

    READY 输出显示为 True 时,用户创建成功。

  4. 如果 READY 列留空,请从资源 YAML 或 User Operator 日志中获取有关状态的更多详细信息。

    消息提供有关当前状态的原因的详细信息。

    oc get kafkausers my-user-2 -o yaml

    具有 NotReady 状态的用户详情

    # ...
    status:
      conditions:
      - lastTransitionTime: "2022-06-10T10:07:37.238065Z"
        message: Simple authorization ACL rules are configured but not supported in the
          Kafka cluster configuration.
        reason: InvalidResourceException
        status: "True"
        type: NotReady

    在本例中,用户未就绪的原因是,在 Kafka 配置中没有启用简单的授权。

    用于简单授权的 Kafka 配置

      apiVersion: kafka.strimzi.io/v1beta2
      kind: Kafka
      metadata:
        name: my-cluster
      spec:
        kafka:
          # ...
          authorization:
            type: simple

    更新 Kafka 配置后,状态会显示用户已就绪。

    oc get kafkausers my-user-2 -o wide -w -n <namespace>

    用户的状态更新

    NAME       CLUSTER     AUTHENTICATION  AUTHORIZATION READY
    my-user-2  my-cluster  tls             simple        True

    获取详情不显示任何消息。

    oc get kafkausers my-user-2 -o yaml

    具有 READY 状态的用户详情

    # ...
    status:
      conditions:
      - lastTransitionTime: "2022-06-10T10:33:40.166846Z"
        status: "True"
        type: Ready

第 11 章 使用红帽构建的 Apicurio Registry 验证模式

对于 AMQ Streams,也可以使用红帽构建的 Apicurio Registry。

Apicurio Registry 是一个数据存储,用于在 API 和事件驱动的构架中共享标准事件模式和 API 设计。您可以使用 Apicurio Registry 将数据的结构与客户端应用程序分离,并使用 REST 接口在运行时共享和管理您的数据类型和 API 描述。

Apicurio Registry 存储用于序列化和反序列化消息的模式,然后可以从客户端应用程序引用这些消息,以确保它们发送和接收的信息与这些模式兼容。Apicurio Registry 为 Kafka 生成者和消费者应用程序提供 Kafka 客户端序列化器/反序列化器。Kafka 制作者应用程序使用 serializers 对符合特定事件模式的信息进行编码。Kafka 消费者应用程序使用反序列化器,它根据特定的模式 ID 验证信息是否被序列化使用正确的模式。

您可以使应用程序使用 registry 中的模式。这样可确保一致的模式使用,并有助于防止运行时出现数据错误。

其他资源

第 12 章 与红帽构建的 Debezium 集成以更改数据捕获

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

Debezium 具有多个用途,包括:

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

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

有关将红帽构建的 Debezium 与 AMQ Streams 一起部署的更多信息,请参阅产品文档。文档包括 Debezium 入门指南,指导您完成设置数据库更新事件记录所需的服务和连接器。

第 13 章 设置 Kafka 集群的客户端访问权限

部署 AMQ Streams 后,您可以设置对 Kafka 集群的客户端访问。要验证部署,您可以部署示例制作者和消费者客户端。否则,创建在 OpenShift 集群内部或外部提供客户端访问的监听程序。

13.1. 部署客户端示例

部署示例制作者和消费者客户端,以发送和接收消息。您可以使用这些客户端来验证 AMQ Streams 的部署。

先决条件

  • Kafka 集群可用于客户端。

流程

  1. 部署 Kafka producer。

    oc run kafka-producer -ti --image=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 --rm=true --restart=Never -- bin/kafka-console-producer.sh --bootstrap-server cluster-name-kafka-bootstrap:9092 --topic my-topic
  2. 在运行制作者的控制台中键入一条消息。
  3. Enter 来发送邮件。
  4. 部署 Kafka 使用者。

    oc run kafka-consumer -ti --image=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 --rm=true --restart=Never -- bin/kafka-console-consumer.sh --bootstrap-server cluster-name-kafka-bootstrap:9092 --topic my-topic --from-beginning
  5. 确认您在使用者控制台中看到传入的信息。

13.2. 配置监听程序以连接到 Kafka 代理

使用监听程序进行与 Kafka 代理的客户端连接。AMQ Streams 提供了一个通用的 GenericKafkaListener 模式,它带有通过 Kafka 资源配置监听程序的属性。GenericKafkaListener 提供了灵活的监听程序配置方法。您可以指定属性来配置 内部监听程序 以在 OpenShift 集群内连接,或 外部监听程序 用于在 OpenShift 集群外部连接。

指定在监听器配置中公开 Kafka 的 连接类型。选择的类型取决于您的要求,以及您的环境和基础架构。支持以下监听程序类型:

内部监听程序
  • 在同一 OpenShift 集群内连接的内部
  • cluster-ip 使用针对每个代理的 ClusterIP 服务公开 Kafka
外部监听程序
  • NodePort 使用 OpenShift 节点上的端口
  • LoadBalancer 使用负载均衡器服务
  • ingress 使用 Kubernetes IngressIngress NGINX Controller for Kubernetes (仅限 Kubernetes)
  • route 使用 OpenShift Route 和默认的 HAProxy 路由器(仅限 OpenShift)
重要

不要在 OpenShift 上使用 ingress,改为使用 route 类型。Ingress NGINX Controller 仅适用于 Kubernetes。路由类型 只在 OpenShift 中被支持。

内部 类型的监听程序配置使用无头服务和提供给代理 pod 的 DNS 名称。您可能需要将 OpenShift 网络加入到外部网络。在这种情况下,您可以配置 内部 类型监听程序(使用 useServiceDnsDomain 属性),以便不使用 OpenShift 服务 DNS 域(通常为 .cluster.local)。您还可以配置基于每个代理的 ClusterIP 服务的 Kafka 集群的 cluster-ip 类型。当您无法通过无头服务路由或者您希望纳入自定义访问机制时,这个选项是一个实用的选项。例如,您可以在为特定 Ingress 控制器或 OpenShift 网关 API 构建自己的类型的外部监听程序时使用此监听程序。

外部监听程序从需要不同身份验证机制的网络处理对 Kafka 集群的访问。您可以使用指定的连接机制(如 loadbalancer 或 route)为 OpenShift 环境外部访问配置外部监听程序。例如,负载均衡器可能不适用于某些基础架构,如裸机,节点端口提供更好的选项。

每个监听器都定义为 Kafka 资源中的一个数组。

侦听器配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
        configuration:
          useServiceDnsDomain: true
      - name: tls
        port: 9093
        type: internal
        tls: true
        authentication:
          type: tls
      - name: external
        port: 9094
        type: route
        tls: true
        configuration:
          brokerCertChainAndKey:
            secretName: my-secret
            certificate: my-certificate.crt
            key: my-key.key
    # ...

您可以根据需要配置多个监听程序,只要它们的名称和端口是唯一的。您还可以使用身份验证为安全连接配置监听程序。

如果要了解更多有关每种连接类型的 pros 和 cons,请参阅在 Strimzi 中访问 Apache Kafka

注意

如果您在使用外部监听程序时需要扩展 Kafka 集群,可能会触发所有 Kafka 代理的滚动更新。这取决于配置。

13.3. 使用监听程序设置对 Kafka 集群的客户端访问

使用 Kafka 集群的地址,您可以提供对同一 OpenShift 集群中的客户端的访问权限;或者,为不同 OpenShift 命名空间或外部 OpenShift 上的客户端提供外部访问。此流程演示了如何配置从 OpenShift 外部或从另一个 OpenShift 集群配置对 Kafka 集群的客户端访问。

Kafka 侦听器提供对 Kafka 集群的访问。客户端访问使用以下配置进行保护:

  1. 为 Kafka 集群配置了外部监听程序,它启用了 TLS 加密和 mTLS 身份验证,并启用了 Kafka 简单 授权。
  2. 为客户端创建一个 KafkaUser,它带有 mTLS 身份验证,以及为 简单 授权定义的访问控制列表(ACL)。

您可以将监听程序配置为使用 mutual tlsscram-sha-512oauth 身份验证。mTLS 始终使用加密,但在使用 SCRAM-SHA-512 和 OAuth 2.0 身份验证时也建议使用加密。

您可以为 Kafka 代理配置简单的oauthopa自定义授权。启用后,授权将应用到所有启用的监听程序。

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

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

您应该至少有一个监听程序支持您要用于 KafkaUser 的身份验证。

注意

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

AMQ Streams operator 自动配置过程并创建身份验证所需的证书:

  • Cluster Operator 创建监听程序并设置集群和客户端证书颁发机构(CA)证书,以便使用 Kafka 集群进行身份验证。
  • User Operator 根据所选的验证类型,创建代表客户端身份验证的用户和用于客户端身份验证的安全凭证。

您可以将证书添加到客户端配置中。

在此过程中,使用 Cluster Operator 生成的 CA 证书,但 您可以通过安装自己的证书 来替换它们。您还可以将监听程序 配置为使用由外部 CA (证书颁发机构)管理的 Kafka 侦听器证书

证书以 PEM (.crt) 和 PKCS #12 (.p12) 格式提供。此流程使用 PEM 证书。将 PEM 证书与使用 X.509 格式的证书的客户端一起使用。

注意

对于同一 OpenShift 集群和命名空间中的内部客户端,您可以在 pod 规格中挂载集群 CA 证书。如需更多信息,请参阅配置内部客户端以信任集群 CA

先决条件

  • Kafka 集群可供在 OpenShift 集群外运行的客户端进行连接
  • Cluster Operator 和 User Operator 在集群中运行

流程

  1. 使用 Kafka 侦听器配置 Kafka 集群。

    • 定义通过监听程序访问 Kafka 代理所需的身份验证。
    • 在 Kafka 代理上启用授权。

      侦听器配置示例

      apiVersion: kafka.strimzi.io/v1beta2
      kind: Kafka
      metadata:
        name: my-cluster
        namespace: myproject
      spec:
        kafka:
          # ...
          listeners: 1
          - name: external 2
            port: 9094 3
            type: <listener_type> 4
            tls: true 5
            authentication:
              type: tls 6
            configuration: 7
              #...
          authorization: 8
            type: simple
            superUsers:
              - super-user-name 9
        # ...

      1
      Generic Kafka listener schema reference 中描述了启用外部监听程序的配置选项。
      2
      用于标识监听程序的名称。在 Kafka 集群中必须是唯一的。
      3
      Kafka 中监听程序使用的端口号。端口号必须在给定的 Kafka 集群中唯一。允许端口号为 9092 及更高版本,但端口 9404 和 9999 除外,它们已用于 Prometheus 和 JMX。根据监听程序类型,端口号可能与连接 Kafka 客户端的端口号不同。
      4
      外部监听器类型指定为 route (只限 OpenShift), loadbalancer, nodeportingress (只限 Kubernetes)。内部监听程序指定为 internalcluster-ip
      5
      必需。侦听器上的 TLS 加密。对于 routeingress 类型监听程序,它必须设置为 true。对于 mTLS 身份验证,也使用 authentication 属性。
      6
      侦听器上的客户端身份验证机制。对于使用 mTLS 的服务器和客户端身份验证,您可以指定 tls: trueauthentication.type: tls
      7
      (可选)根据监听器类型的要求,您可以指定额外的 监听程序配置
      8
      授权指定为 simple,它使用 AclAuthorizer Kafka 插件。
      9
      (可选)无论 ACL 中定义的任何访问限制,Super 用户可以访问所有代理。
      警告

      OpenShift Route 地址由 Kafka 集群的名称、监听程序的名称以及它在其中创建的命名空间的名称组成。例如,my-cluster-kafka-listener1-bootstrap-myproject (CLUSTER-NAME-kafka-LISTENER-NAME-bootstrap-NAMESPACE)。如果您使用 路由 监听程序类型,请注意地址的整个长度不超过 63 个字符的最大值。

  2. 创建或更新 Kafka 资源。

    oc apply -f <kafka_configuration_file>

    Kafka 集群被配置为使用 mTLS 身份验证配置 Kafka 代理监听程序。

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

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

    一个服务也作为外部 bootstrap 地址为到 Kafka 集群的外部连接创建,使用 nodeport 监听器。

    验证 kafka 代理的身份的集群 CA 证书也会在 secret < cluster_name> -cluster-ca-cert 中创建。

    注意

    如果您在使用外部监听程序时需要扩展 Kafka 集群,可能会触发所有 Kafka 代理的滚动更新。这取决于配置。

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

    oc get kafka <kafka_cluster_name> -o=jsonpath='{.status.listeners[?(@.name=="<listener_name>")].bootstrapServers}{"\n"}'

    例如:

    oc get kafka my-cluster -o=jsonpath='{.status.listeners[?(@.name=="external")].bootstrapServers}{"\n"}'

    使用 Kafka 客户端中的 bootstrap 地址连接到 Kafka 集群。

  4. 创建或修改代表需要访问 Kafka 集群的客户端的用户。

    • 指定与 Kafka 侦听器相同的身份验证类型。
    • 指定 简单 授权的授权 ACL。

      用户配置示例

      apiVersion: kafka.strimzi.io/v1beta2
      kind: KafkaUser
      metadata:
        name: my-user
        labels:
          strimzi.io/cluster: my-cluster 1
      spec:
        authentication:
          type: tls 2
        authorization:
          type: simple
          acls: 3
            - resource:
                type: topic
                name: my-topic
                patternType: literal
              operations:
                - Describe
                - Read
            - resource:
                type: group
                name: my-group
                patternType: literal
              operations:
                - Read

      1
      标签必须与 Kafka 集群的标签匹配。
      2
      身份验证指定为 mutual tls
      3
      简单的授权需要包含 ACL 规则列表才能应用到用户。规则根据 用户名 (my-user)定义 Kafka 资源允许的操作。
  5. 创建或修改 KafkaUser 资源。

    oc apply -f USER-CONFIG-FILE

    创建用户,以及名称与 KafkaUser 资源相同的 secret。secret 包含 mTLS 身份验证的公钥和私钥。

    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> # Public key of the clients CA
      user.crt: <user_certificate> # Public key of the user
      user.key: <user_private_key> # Private key of the user
      user.p12: <store> # PKCS #12 store for user certificates and keys
      user.password: <password_for_store> # Protects the PKCS #12 store

  6. 从 Kafka 集群的 < cluster_name>-cluster-ca-cert secret 中提取集群 CA 证书。

    oc get secret <cluster_name>-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
  7. 从 < user_name&gt; secret 中提取用户 CA 证书。

    oc get secret <user_name> -o jsonpath='{.data.user\.crt}' | base64 -d > user.crt
  8. 从 < user_name&gt; secret 中提取用户的私钥。

    oc get secret <user_name> -o jsonpath='{.data.user\.key}' | base64 -d > user.key
  9. 使用 bootstrap 地址主机名和端口配置客户端以连接到 Kafka 集群:

    props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "<hostname>:<port>");
  10. 使用 truststore 凭证配置客户端以验证 Kafka 集群的身份。

    指定公共集群 CA 证书。

    truststore 配置示例

    props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SSL");
    props.put(SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG, "PEM");
    props.put(SslConfigs.SSL_TRUSTSTORE_CERTIFICATES_CONFIG, "<ca.crt_file_content>");

    SSL 是 mTLS 身份验证指定的安全协议。通过 TLS 为 SCRAM-SHA-512 身份验证指定 SASL_SSL。PEM 是信任存储的文件格式。

  11. 使用密钥存储凭证配置客户端,以便在连接到 Kafka 集群时验证用户。

    指定公钥证书和私钥。

    keystore 配置示例

    props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SSL");
    props.put(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG, "PEM");
    props.put(SslConfigs.SSL_KEYSTORE_CERTIFICATE_CHAIN_CONFIG, "<user.crt_file_content>");
    props.put(SslConfigs.SSL_KEYSTORE_KEY_CONFIG, "<user.key_file_content>");

    将密钥存储证书和私钥直接添加到配置中。以单行格式添加。在 BEGIN CERTIFICATEEND CERTIFICATE 分隔符之间,以换行符(\n)开头。也来自原始证书的 每行

    keystore 配置示例

    props.put(SslConfigs.SSL_KEYSTORE_CERTIFICATE_CHAIN_CONFIG, "-----BEGIN CERTIFICATE----- \n<user_certificate_content_line_1>\n<user_certificate_content_line_n>\n-----END CERTIFICATE---");
    props.put(SslConfigs.SSL_KEYSTORE_KEY_CONFIG, "----BEGIN PRIVATE KEY-----\n<user_key_content_line_1>\n<user_key_content_line_n>\n-----END PRIVATE KEY-----");

13.4. 使用节点端口访问 Kafka

使用节点端口从 OpenShift 集群外的外部客户端访问 AMQ Streams Kafka 集群。

要连接到代理,您可以为 Kafka bootstrap 地址指定主机名和端口号,以及用于 TLS 加密的证书。

该流程显示基本的 nodeport 侦听器配置。您可以使用监听程序属性启用 TLS 加密(tls)并指定客户端身份验证机制(身份验证)。使用 配置属性 添加额外的配置。例如,您可以将以下配置属性用于 nodeport 侦听器:

preferredNodePortAddressType
指定作为节点地址检查的第一个地址类型。
externalTrafficPolicy
指定服务是否将外部流量路由到节点本地还是集群范围的端点。
nodePort
覆盖 bootstrap 和 broker 服务的分配的节点端口号。

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

先决条件

  • 正在运行的 Cluster Operator

在此过程中,Kafka 集群名称为 my-cluster。侦听器的名称是 外部

流程

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

    例如:

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

    oc apply -f <kafka_configuration_file>

    在 secret my-cluster-cluster-ca-cert 中创建了用于验证 kafka 代理的身份的集群 CA 证书。

    为每个 Kafka 代理以及外部 bootstrap 服务创建 NodePort 类型服务。

    为 bootstrap 和代理创建的节点端口服务

    NAME                                 TYPE      CLUSTER-IP      PORT(S)
    my-cluster-kafka-external-0          NodePort  172.30.55.13    9094:31789/TCP
    my-cluster-kafka-external-1          NodePort  172.30.250.248  9094:30028/TCP
    my-cluster-kafka-external-2          NodePort  172.30.115.81   9094:32650/TCP
    my-cluster-kafka-external-bootstrap  NodePort  172.30.30.23    9094:32650/TCP

    用于客户端连接的 bootstrap 地址传播到 Kafka 资源的 status

    bootstrap 地址的状态示例

    status:
      clusterId: Y_RJQDGKRXmNF7fEcWldJQ
      conditions:
        - lastTransitionTime: '2023-01-31T14:59:37.113630Z'
          status: 'True'
          type: Ready
      listeners:
        # ...
        - addresses:
            - host: ip-10-0-224-199.us-west-2.compute.internal
              port: 32650
          bootstrapServers: 'ip-10-0-224-199.us-west-2.compute.internal:32650'
          certificates:
            - |
              -----BEGIN CERTIFICATE-----
    
              -----END CERTIFICATE-----
          name: external
          type: external
      observedGeneration: 2
     # ...

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

    oc get kafka my-cluster -o=jsonpath='{.status.listeners[?(@.name=="external")].bootstrapServers}{"\n"}'
    
    ip-10-0-224-199.us-west-2.compute.internal:32650
  4. 提取集群 CA 证书。

    oc get secret my-cluster-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
  5. 将您的客户端配置为连接到代理。

    1. 指定 Kafka 客户端中的 bootstrap 主机和端口作为连接到 Kafka 集群的 bootstrap 地址。例如,ip-10-0-224-199.us-west-2.compute.internal:32650
    2. 将提取的证书添加到 Kafka 客户端的信任存储中,以配置 TLS 连接。

      如果启用了客户端身份验证机制,您还需要在客户端上配置它。

注意

如果您使用自己的监听程序证书,请检查您是否需要将 CA 证书添加到客户端的信任存储配置中。如果是一个公共(外部)CA,您通常不需要添加它。

13.5. 使用 loadbalancers 访问 Kafka

使用 loadbalancers 从 OpenShift 集群外的外部客户端访问 AMQ Streams Kafka 集群。

要连接到代理,您可以为 Kafka bootstrap 地址指定主机名和端口号,以及用于 TLS 加密的证书。

该流程显示基本的 loadbalancer 侦听器配置。您可以使用监听程序属性启用 TLS 加密(tls)并指定客户端身份验证机制(身份验证)。使用 配置属性 添加额外的配置。例如,您可以将以下配置属性用于 loadbalancer 侦听程序:

loadBalancerSourceRanges
将流量限制为指定的 CIDR 列表(Classless Inter-Domain Routing)范围。
externalTrafficPolicy
指定服务是否将外部流量路由到节点本地还是集群范围的端点。
loadBalancerIP
在创建 loadbalancer 时请求特定的 IP 地址。

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

先决条件

  • 正在运行的 Cluster Operator

在此过程中,Kafka 集群名称为 my-cluster。侦听器的名称是 外部

流程

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

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      labels:
        app: my-cluster
      name: my-cluster
      namespace: myproject
    spec:
      kafka:
        # ...
        listeners:
          - name: external
            port: 9095
            type: loadbalancer
            tls: true
            authentication:
              type: tls
            # ...
        # ...
      zookeeper:
        # ...
  2. 创建或更新资源。

    oc apply -f <kafka_configuration_file>

    验证 kafka 代理的身份的集群 CA 证书也会在 secret my-cluster-cluster-ca-cert 中创建。

    为每个 Kafka 代理创建 loadbalancer 类型服务和负载均衡器,以及外部 bootstrap 服务。

    为 bootstrap 和代理创建的 LoadBalancer 服务和负载均衡器

    NAME                                  TYPE            CLUSTER-IP      PORT(S)
    my-cluster-kafka-external-0          LoadBalancer     172.30.204.234  9095:30011/TCP
    my-cluster-kafka-external-1          LoadBalancer     172.30.164.89   9095:32544/TCP
    my-cluster-kafka-external-2          LoadBalancer     172.30.73.151   9095:32504/TCP
    my-cluster-kafka-external-bootstrap  LoadBalancer     172.30.30.228   9095:30371/TCP
    
    NAME                                 EXTERNAL-IP (loadbalancer)
    my-cluster-kafka-external-0          a8a519e464b924000b6c0f0a05e19f0d-1132975133.us-west-2.elb.amazonaws.com
    my-cluster-kafka-external-1          ab6adc22b556343afb0db5ea05d07347-611832211.us-west-2.elb.amazonaws.com
    my-cluster-kafka-external-2          a9173e8ccb1914778aeb17eca98713c0-777597560.us-west-2.elb.amazonaws.com
    my-cluster-kafka-external-bootstrap  a8d4a6fb363bf447fb6e475fc3040176-36312313.us-west-2.elb.amazonaws.com

    用于客户端连接的 bootstrap 地址传播到 Kafka 资源的 status

    bootstrap 地址的状态示例

    status:
      clusterId: Y_RJQDGKRXmNF7fEcWldJQ
      conditions:
        - lastTransitionTime: '2023-01-31T14:59:37.113630Z'
          status: 'True'
          type: Ready
      listeners:
        # ...
        - addresses:
            - host: >-
                a8d4a6fb363bf447fb6e475fc3040176-36312313.us-west-2.elb.amazonaws.com
              port: 9095
          bootstrapServers: >-
            a8d4a6fb363bf447fb6e475fc3040176-36312313.us-west-2.elb.amazonaws.com:9095
          certificates:
            - |
              -----BEGIN CERTIFICATE-----
    
              -----END CERTIFICATE-----
          name: external
          type: external
      observedGeneration: 2
     # ...

    用于客户端连接的 DNS 地址会传播到每个 loadbalancer 服务的状态

    bootstrap loadbalancer 的状态示例

    status:
      loadBalancer:
        ingress:
          - hostname: >-
              a8d4a6fb363bf447fb6e475fc3040176-36312313.us-west-2.elb.amazonaws.com
     # ...

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

    oc get kafka my-cluster -o=jsonpath='{.status.listeners[?(@.name=="external")].bootstrapServers}{"\n"}'
    
    a8d4a6fb363bf447fb6e475fc3040176-36312313.us-west-2.elb.amazonaws.com:9095
  4. 提取集群 CA 证书。

    oc get secret my-cluster-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
  5. 将您的客户端配置为连接到代理。

    1. 指定 Kafka 客户端中的 bootstrap 主机和端口作为连接到 Kafka 集群的 bootstrap 地址。例如,a8d4a6fb363bf447fb6e475fc3040176-36312313.us-west-2.elb.amazonaws.com:9095
    2. 将提取的证书添加到 Kafka 客户端的信任存储中,以配置 TLS 连接。

      如果启用了客户端身份验证机制,您还需要在客户端上配置它。

注意

如果您使用自己的监听程序证书,请检查您是否需要将 CA 证书添加到客户端的信任存储配置中。如果是一个公共(外部)CA,您通常不需要添加它。

13.6. 使用 OpenShift 路由访问 Kafka

使用 OpenShift 路由从 OpenShift 集群外的客户端访问 AMQ Streams Kafka 集群。

为了可以使用路由,请在 Kafka 自定义资源中为 route 类型监听程序添加配置。应用时,配置会为外部 bootstrap 和集群中的每个代理创建一个专用路由和服务。客户端连接到 bootstrap 路由,该路由通过 bootstrap 服务路由以连接到代理。然后,使用 DNS 名称建立每个代理连接,该名称通过特定于代理的路由和服务将流量从客户端路由到代理。

要连接到代理,您可以为路由 bootstrap 地址指定主机名,以及用于 TLS 加密的证书。对于使用路由访问,端口始终为 443。

警告

OpenShift 路由地址包含 Kafka 集群的名称、监听程序的名称及其在其中创建的项目的名称。例如,my-cluster-kafka-external-bootstrap-myproject (<cluster_name>-kafka-<listener_name>-bootstrap-<namespace>)。请注意,地址的整个长度不超过 63 个字符的最大值。

该流程显示基本的监听程序配置。必须启用 TLS 加密(tls)。您还可以指定客户端身份验证机制(身份验证)。使用 配置属性 添加额外的配置。例如,您可以使用带有 路由 监听程序 的主机 配置属性来指定 bootstrap 和 per-broker 服务使用的主机名。

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

TLS 透传

为 AMQ Streams 创建的路由启用 TLS 透传。Kafka 通过 TCP 使用二进制协议,但路由旨在使用 HTTP 协议。为了能够通过路由路由 TCP 流量,AMQ Streams 使用带有 Server Name Indication (SNI)的 TLS 透传。

SNI 有助于识别并传递到 Kafka 代理的连接。在 passthrough 模式中,始终使用 TLS 加密。由于连接传递到代理,因此监听程序使用由内部集群 CA 签名的 TLS 证书,而不是入口证书。要将监听程序配置为使用您自己的监听程序证书,请使用 brokerCertChainAndKey 属性

先决条件

  • 正在运行的 Cluster Operator

在此过程中,Kafka 集群名称为 my-cluster。侦听器的名称是 外部

流程

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

    例如:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      labels:
        app: my-cluster
      name: my-cluster
      namespace: myproject
    spec:
      kafka:
        # ...
        listeners:
          - name: external
            port: 9094
            type: route
            tls: true 1
            authentication:
              type: tls
            # ...
        # ...
      zookeeper:
        # ...
    1
    对于 路由类型 监听程序,必须启用 TLS 加密(为true)。
  2. 创建或更新资源。

    oc apply -f <kafka_configuration_file>

    在 secret my-cluster-cluster-ca-cert 中创建了用于验证 kafka 代理的身份的集群 CA 证书。

    为每个 Kafka 代理以及外部 bootstrap 服务创建 ClusterIP 类型服务。

    另外,还会为每个服务创建一个路由,其中包含一个 DNS 地址 (host/port),以使用默认的 OpenShift HAProxy 路由器公开它们。

    路由已预先配置有 TLS 透传。

    为 bootstrap 和代理创建的路由

    NAME                                  HOST/PORT                                                   SERVICES                              PORT  TERMINATION
    my-cluster-kafka-external-0          my-cluster-kafka-external-0-my-project.router.com          my-cluster-kafka-external-0          9094  passthrough
    my-cluster-kafka-external-1          my-cluster-kafka-external-1-my-project.router.com          my-cluster-kafka-external-1          9094  passthrough
    my-cluster-kafka-external-2          my-cluster-kafka-external-2-my-project.router.com          my-cluster-kafka-external-2          9094  passthrough
    my-cluster-kafka-external-bootstrap  my-cluster-kafka-external-bootstrap-my-project.router.com  my-cluster-kafka-external-bootstrap  9094  passthrough

    用于客户端连接的 DNS 地址会传播到每个路由的 状态

    bootstrap 路由的状态示例

    status:
      ingress:
        - host: >-
            my-cluster-kafka-external-bootstrap-my-project.router.com
     # ...

  3. 使用目标代理使用 OpenSSL s_client 检查端口 443 上的 client-server TLS 连接。

    openssl s_client -connect my-cluster-kafka-external-0-my-project.router.com:443 -servername my-cluster-kafka-external-0-my-project.router.com -showcerts

    服务器名称是用于传递到代理连接的 SNI。

    如果连接成功,则返回代理的证书。

    代理的证书

    Certificate chain
     0 s:O = io.strimzi, CN = my-cluster-kafka
       i:O = io.strimzi, CN = cluster-ca v0

  4. Kafka 资源的状态检索 bootstrap 服务的地址。

    oc get kafka my-cluster -o=jsonpath='{.status.listeners[?(@.name=="external")].bootstrapServers}{"\n"}'
    
    my-cluster-kafka-external-bootstrap-my-project.router.com:443

    地址包含集群名称、监听程序名称、项目名称和路由器的域(本例中为router.com )。

  5. 提取集群 CA 证书。

    oc get secret my-cluster-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
  6. 将您的客户端配置为连接到代理。

    1. 指定 Kafka 客户端中的 bootstrap 服务和端口 443 的地址,作为连接到 Kafka 集群的 bootstrap 地址。
    2. 将提取的证书添加到 Kafka 客户端的信任存储中,以配置 TLS 连接。

      如果启用了客户端身份验证机制,您还需要在客户端上配置它。

注意

如果您使用自己的监听程序证书,请检查您是否需要将 CA 证书添加到客户端的信任存储配置中。如果是一个公共(外部)CA,您通常不需要添加它。

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

通过管理客户端对 Kafka 代理的访问来保护 Kafka 集群。指定保护 Kafka 代理和客户端的配置选项

Kafka 代理和客户端之间的安全连接可以包括以下内容:

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

为客户端指定的身份验证和授权机制必须与为 Kafka 代理指定的匹配。AMQ Streams Operator 自动配置过程并创建身份验证所需的证书。Cluster Operator 会自动为集群中的数据加密和身份验证设置 TLS 证书。

14.1. Kafka 的安全选项

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

14.1.1. 侦听器身份验证

在创建监听程序时,为 Kafka 代理配置客户端身份验证。使用 Kafka 资源中的 Kafka.spec.kafka.listeners.authentication 属性指定监听程序身份验证类型。

对于 OpenShift 集群内的客户端,您可以创建 普通 (无需加密)或 tls 内部监听程序内部监听程序 类型使用无头服务和提供给代理 pod 的 DNS 名称。作为无头服务的替代选择,您还可以创建一个 cluster-ip 类型的内部监听程序,以使用每个代理 ClusterIP 服务公开 Kafka。对于 OpenShift 集群外的客户端,您可以创建 外部监听程序 并指定连接机制,可以是 nodeportloadbalanceringress (仅限 Kubernetes) 或路由 (仅限 OpenShift)。

有关连接外部客户端的配置选项的更多信息,请参阅 第 13 章 设置 Kafka 集群的客户端访问权限

支持的身份验证选项:

  1. mTLS 身份验证(仅在启用了 TLS 的监听程序中)
  2. SCRAM-SHA-512 身份验证
  3. 基于 OAuth 2.0 令牌的身份验证
  4. 自定义身份验证

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

注意

在使用自定义身份验证前,尝试探索标准身份验证选项。自定义身份验证允许任何类型的 kafka 支持的验证。它可以提供更大的灵活性,但也增加了复杂性。

图 14.1. Kafka 侦听器身份验证选项

侦听器身份验证配置的选项

listener authentication 属性用于指定特定于该监听程序的身份验证机制。

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

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

以下示例显示了:

  • 为 SCRAM-SHA-512 身份验证配置 的普通 监听程序
  • 带有 mTLS 身份验证的 tls 侦听程序
  • 带有 mTLS 身份验证的 外部监听程序

每个监听器都配置有 Kafka 集群中的唯一名称和端口。

重要

当为客户端配置监听程序对代理的访问时,您可以使用端口 9092 或更高版本(9093、9094 等),但有一些例外。侦听程序无法配置为使用为 interbroker 通信(9090 和 9091)、Prometheus 指标(9404)和 JMX (Java 管理扩展)监控(9999)保留的端口。

侦听器身份验证配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  namespace: myproject
spec:
  kafka:
    # ...
    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
# ...

14.1.1.1. mTLS 身份验证

mTLS 身份验证总是用于 Kafka 代理和 ZooKeeper pod 之间的通信。

AMQ Streams 可将 Kafka 配置为使用 TLS (传输层安全)来提供 Kafka 代理和客户端之间的加密通信,并不使用 mutual 身份验证。对于 mutual 或双向身份验证,服务器和客户端都存在证书。当您配置 mTLS 身份验证时,代理会验证客户端(客户端身份验证),客户端验证代理(服务器身份验证)。

Kafka 资源中的 mTLS 侦听器配置需要以下内容:

  • tls: true 用于指定 TLS 加密和服务器身份验证
  • authentication.type: tls 指定客户端身份验证

当 Cluster Operator 创建 Kafka 集群时,它会创建一个名为 < cluster_name>-cluster-ca-cert 的新 secret。secret 包含 CA 证书。CA 证书采用 PEM 和 PKCS #12 格式。要验证 Kafka 集群,请将 CA 证书添加到客户端配置中的信任存储中。要验证客户端,请将用户证书和密钥添加到您的客户端配置的密钥存储中。有关为 mTLS 配置客户端的详情,请参考 第 14.2.2 节 “用户身份验证”

注意

TLS 身份验证更为常见,一方对另一个身份进行身份验证。例如,当在 Web 浏览器和 Web 服务器间使用 HTTPS 时,浏览器获取 Web 服务器的身份的概念验证。

14.1.1.2. SCRAM-SHA-512 身份验证

SCRAM (Salted Challenge Response Authentication Mechanism)是一个身份验证协议,可以使用密码建立 mutual 身份验证。AMQ Streams 可将 Kafka 配置为使用 SASL (Simple Authentication and Security Layer) SCRAM-SHA-512,以便在未加密的和加密的客户端连接中提供身份验证。

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

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

  • 密码不会通过通信频道以明确发送。相反,客户端和服务器都有其他挑战,从而证明他们知道验证用户的密码。
  • 服务器和客户端为每个身份验证交换生成一个新的挑战。这意味着交换对重播攻击具有弹性。

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

14.1.1.3. 网络策略

默认情况下,AMQ Streams 会自动为每个在 Kafka 代理上启用的监听程序创建一个 NetworkPolicy 资源。此 NetworkPolicy 允许应用程序连接到所有命名空间中的监听程序。使用网络策略作为监听程序配置的一部分。

如果要将对网络级别的监听程序的访问限制为只选择的应用程序或命名空间,请使用 networkPolicyPeers 属性。每个监听程序都可以有不同的 networkPolicyPeers 配置。如需有关网络策略对等点的更多信息,请参阅 NetworkPolicyPeer API 参考

如果要使用自定义网络策略,您可以在 Cluster Operator 配置中将 STRIMZI_NETWORK_POLICY_GENERATION 环境变量设置为 false。如需更多信息,请参阅 第 8.5 节 “配置 Cluster Operator”

注意

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

14.1.1.4. 提供监听程序证书

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

14.1.2. Kafka 授权

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

支持的授权选项:

图 14.2. Kafka 集群授权选项

kafka 授权配置的选项
14.1.2.1. 超级用户

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

要为 Kafka 集群指定超级用户,请在 superUsers 属性中添加用户主体列表。如果用户使用 mTLS 身份验证,用户名是 TLS 证书主题中前缀为 CN= 的通用名称。如果您没有使用 User Operator 并使用您自己的证书 mTLS,则用户名是完整证书主题。一个完整的证书主题可以有以下字段: CN=user,OU=my_ou,O=my_org,L=my_location,ST=my_state,C=my_country_code。省略任何不存在的字段。

带有超级用户的示例配置

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
        - CN=client_4,OU=my_ou,O=my_org,L=my_location,ST=my_state,C=US
        - CN=client_5,OU=my_ou,O=my_org,C=GB
        - CN=client_6,O=my_org
    # ...

14.2. Kafka 客户端的安全选项

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

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

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

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

有关配置 KafkaUser 资源以安全访问 Kafka 代理的更多信息,请参阅 第 13.3 节 “使用监听程序设置对 Kafka 集群的客户端访问”

14.2.1. 识别用于用户处理的 Kafka 集群

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

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

用户 Operator 使用该标签来识别 KafkaUser 资源并创建新用户,以及后续处理用户。

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

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

14.2.2. 用户身份验证

使用 KafkaUser 自定义资源为需要访问 Kafka 集群的用户(客户端)配置身份验证凭证。使用 KafkaUser.spec 中的 authentication 属性配置凭据。通过指定 类型,您可以控制生成的凭据。

支持的验证类型:

  • TLS 用于 mTLS 身份验证
  • 使用外部证书的 mTLS 身份验证的 tls-external
  • SCRAM-sha-512 用于 SCRAM-SHA-512 验证

如果指定了 tlsscram-sha-512,User Operator 会在创建用户时创建身份验证凭据。如果指定了 tls-external,用户仍然使用 mTLS,但不会创建身份验证凭证。当您提供自己的证书时使用这个选项。如果没有指定身份验证类型,User Operator 不会创建用户或其凭证。

您可以使用 tls-external 来使用 User Operator 外部发布的证书与 mTLS 进行身份验证。User Operator 不会生成 TLS 证书或 secret。您仍然可以通过 User Operator 管理 ACL 规则和配额,方式与使用 tls 机制时相同。这意味着,您在指定 ACL 规则和配额时使用 CN=USER-NAME 格式。USER-NAME 是 TLS 证书中给出的通用名称。

14.2.2.1. mTLS 身份验证

要使用 mTLS 身份验证,请将 KafkaUser 资源中的 type 字段设置为 tls

启用 mTLS 身份验证的用户示例

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

身份验证类型必须与用于访问 Kafka 集群的 Kafka 侦听器的等效配置匹配。

当用户由 User Operator 创建时,它会创建一个新的 secret,其名称与 KafkaUser 资源的名称相同。secret 包含 mTLS 的私钥和公钥。公钥包含在用户证书中,该证书在创建时由客户端 CA (证书授权)签名。所有密钥都是 X.509 格式。

注意

如果您使用 Cluster Operator 生成的客户端 CA,则当 Cluster Operator 更新客户端 CA 时,用户 Operator 生成的用户证书也会续订。

用户 secret 以 PEM 和 PKCS #12 的形式提供密钥和证书

使用用户凭证的 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> # Public key of the clients CA
  user.crt: <user_certificate> # Public key of the user
  user.key: <user_private_key> # Private key of the user
  user.p12: <store> # PKCS #12 store for user certificates and keys
  user.password: <password_for_store> # Protects the PKCS #12 store

配置客户端时,您可以指定以下内容:

  • 公共集群 CA 证书的 Truststore 属性用于验证 Kafka 集群的身份
  • 用户身份验证凭证的 Keystore 属性用于验证客户端

配置取决于文件格式 (PEM 或 PKCS #12)。这个示例使用 PKCS #12 格式存储,以及访问存储中凭证所需的密码。

以 PKCS #12 格式使用 mTLS 的客户端配置示例

bootstrap.servers=<kafka_cluster_name>-kafka-bootstrap:9093 1
security.protocol=SSL 2
ssl.truststore.location=/tmp/ca.p12 3
ssl.truststore.password=<truststore_password> 4
ssl.keystore.location=/tmp/user.p12 5
ssl.keystore.password=<keystore_password> 6

1
连接到 Kafka 集群的 bootstrap 服务器地址。
2
使用 TLS 加密时的安全协议选项。
3
truststore 位置包含了 Kafka 集群的公钥证书 (ca.p12)。在创建 Kafka 集群时,Cluster Operator 会在 < cluster_name>-cluster-ca-cert secret 中生成集群 CA 证书和密钥。
4
用于访问信任存储的密码(ca.password)。
5
密钥存储位置包含 Kafka 用户的公钥证书(user.p12)。
6
用于访问密钥存储的密码(user.password)。
14.2.2.2. 使用 User Operator 外部发布的证书进行 mTLS 验证

要使用 User Operator 外部发布的证书使用 mTLS 身份验证,您需要将 KafkaUser 资源中的 type 字段设置为 tls-external。不会为用户创建 secret 和凭证。

具有 mTLS 身份验证的用户示例,它使用 User Operator 外部发布的证书

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

14.2.2.3. SCRAM-SHA-512 身份验证

要使用 SCRAM-SHA-512 身份验证机制,您需要将 KafkaUser 资源中的 type 字段设置为 scram-sha-512

启用 SCRAM-SHA-512 验证的用户示例

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 创建时,它会创建一个新的 secret,其名称与 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
14.2.2.3.1. 自定义密码配置

创建用户时,AMQ Streams 会生成一个随机密码。您可以使用自己的密码而不是 AMQ Streams 生成的密码。要做到这一点,使用密码创建一个 secret,并在 KafkaUser 资源中引用它。

为 SCRAM-SHA-512 验证设定密码的用户示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaUser
metadata:
  name: my-user
  labels:
    strimzi.io/cluster: my-cluster
spec:
  authentication:
    type: scram-sha-512
    password:
      valueFrom:
        secretKeyRef:
          name: my-secret 1
          key: my-password 2
  # ...

1
包含预定义密码的 secret 名称。
2
存储在机密中的密码的密钥。

14.2.3. 用户授权

使用 KafkaUser 自定义资源为用户(客户端)配置需要访问 Kafka 集群的授权规则。使用 KafkaUser.spec 中的 authorization 属性配置规则。通过指定 类型,您可以控制使用哪些规则。

要使用简单的授权,您可以在 KafkaUser.spec.authorization 中将 type 属性设置为 simple。简单的授权使用 Kafka Admin API 管理 Kafka 集群中的 ACL 规则。User Operator 中的 ACL 管理是启用的,还是取决于您的 Kafka 集群中的授权配置。

  • 对于简单的授权,总是启用 ACL 管理。
  • 对于 OPA 授权,始终禁用 ACL 管理。授权规则在 OPA 服务器中配置。
  • 对于 Red Hat Single Sign-On 授权,您可以在 Red Hat Single Sign-On 中直接管理 ACL 规则。您还可以将授权委派给简单授权器作为配置中的回退选项。当启用到简单授权器时,用户 Operator 也会启用对 ACL 规则的管理。
  • 要使用自定义授权插件进行自定义授权,请使用 Kafka 自定义资源的 .spec.kafka.authorization 配置中的 supportsAdminApi 属性来启用或禁用支持。

授权是集群范围的。授权类型必须与 Kafka 自定义资源中的等效配置匹配。

如果没有启用 ACL 管理,AMQ Streams 会在包含任何 ACL 规则时拒绝资源。

如果您使用 User Operator 的独立部署,则默认启用 ACL 管理。您可以使用 STRIMZI_ACLS_ADMIN_API_SUPPORTED 环境变量来禁用它。

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

14.2.3.1. ACL 规则

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

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

有关 AclRule 对象的更多信息,请参阅 AclRule 模式参考

14.2.3.2. 超级用户对 Kafka 代理的访问

如果用户被添加到 Kafka 代理配置中的超级用户列表中,无论 KafkaUser 中 ACL 中定义的任何授权限制,用户都可以不受限制地访问集群。

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

14.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 模式参考

14.3. 保护对 Kafka 代理的访问

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

  • Kafka 资源:

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

Kafka 资源配置为设置:

  • 侦听器身份验证
  • 限制访问 Kafka 监听器的网络策略
  • Kafka 授权
  • 超级用户对代理不受限制访问

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

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

您可以通过安装自己的证书来替换 Cluster Operator 生成的证书

您还可以为启用了 TLS 加密的任何监听器提供自己的服务器证书和私钥。这些用户提供的证书称为 Kafka 侦听器证书。通过提供 Kafka 侦听器证书,您可以利用现有的安全基础架构,如机构的私有 CA 或公共 CA。Kafka 客户端需要信任用于为监听器证书签名的 CA。在需要时,您必须手动续订 Kafka 侦听器证书。证书以 PKCS #12 格式 (.p12) 和 PEM (.crt) 格式提供。

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

KafkaUser 资源配置为设置:

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

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

有关访问配置属性的更多信息,请参阅 schema 参考:

14.3.1. 保护 Kafka 代理

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

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

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

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

或者,您可以使用 SCRAM-SHA 或 OAuth 2.0 进行 监听器身份验证,OAuth 2.0 或 OPA 用于 Kafka 授权

流程

  1. 配置 Kafka 资源。

    1. 授权 配置授权属性。
    2. 配置 listeners 属性,以使用身份验证创建监听程序。

      例如:

      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 有无限访问权限的用户主体列表。在使用 mTLS 身份验证时,CN 是客户端证书的通用名称。
      3
      可以为每个监听器配置监听器验证机制,并指定为 mTLS、SCRAM-SHA-512 或基于令牌的 OAuth 2.0

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

  2. 创建或更新 Kafka 资源。

    oc apply -f <kafka_configuration_file>

    Kafka 集群被配置为使用 mTLS 身份验证配置 Kafka 代理监听程序。

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

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

    验证 kafka 代理的身份的集群 CA 证书也会在 secret < cluster_name> -cluster-ca-cert 中创建。

14.3.2. 保护用户对 Kafka 的访问

创建或修改 KafkaUser 以代表需要对 Kafka 集群安全访问权限的客户端。

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

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

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

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

注意

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

先决条件

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
            operations:
              - Describe
              - Read
          - resource:
              type: group
              name: my-group
              patternType: literal
            operations:
              - Read
    1
    用户身份验证机制,定义为 mutual tlsscram-sha-512
    2
    简单的授权,这需要包含 ACL 规则列表。
  2. 创建或更新 KafkaUser 资源。

    oc apply -f <user_config_file>

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

有关使用到 Kafka 代理的安全连接配置 Kafka 客户端的详情,请参考 第 13.3 节 “使用监听程序设置对 Kafka 集群的客户端访问”

14.3.3. 使用网络策略限制 Kafka 侦听程序的访问

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

先决条件

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

流程

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

    例如,要配置 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

14.3.4. 为 TLS 加密提供自己的 Kafka 侦听器证书

监听器提供对 Kafka 代理的客户端访问。在 Kafka 资源中配置监听程序,包括使用 TLS 进行客户端访问所需的配置。

默认情况下,监听程序使用由 AMQ Streams 生成的内部 CA (证书授权)证书签名的证书。Cluster Operator 在创建 Kafka 集群时生成 CA 证书。当您为 TLS 配置客户端时,您可以将 CA 证书添加到其信任存储配置中以验证 Kafka 集群。您还可以安装和使用自己的 CA 证书。或者,您可以使用 brokerCertChainAndKey 属性配置监听程序,并使用自定义服务器证书。

brokerCertChainAndKey 属性允许您使用监听程序级别自己的自定义证书访问 Kafka 代理。您可以使用自己的私钥和服务器证书创建 secret,然后在监听器的 brokerCertChainAndKey 配置中指定密钥和证书。您可以使用由公共(外部)CA 或私有 CA 签名的证书。如果由公共 CA 签名,您通常不需要将其添加到客户端的信任存储配置中。自定义证书不由 AMQ Streams 管理,因此您需要手动更新它们。

注意

侦听器证书仅用于 TLS 加密和服务器身份验证。它们不用于 TLS 客户端身份验证。如果要使用自己的证书进行 TLS 客户端身份验证,您必须安装和使用您自己的客户端 CA

先决条件

  • Cluster Operator 正在运行。
  • 每个监听器都需要以下内容:

如果您不使用自签名证书,您可以提供一个证书中包含整个 CA 链的证书。

如果为监听程序配置了 TLS 加密(tls: true),只能使用 brokerCertChainAndKey 属性。

注意

AMQ Streams 不支持将加密私钥用于 TLS。secret 中存储的私钥必须未加密的,才能正常工作。

流程

  1. 创建包含私钥和服务器证书的 Secret

    oc create secret generic my-secret --from-file=my-listener-key.key --from-file=my-listener-certificate.crt
  2. 编辑集群的 Kafka 资源。

    将监听程序配置为使用 configuration.brokerCertChainAndKey 属性中的 Secret、证书文件和私钥文件。

    启用 TLS 加密的 loadbalancer 外部监听程序配置示例

    # ...
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: external
        port: 9094
        type: loadbalancer
        tls: true
        configuration:
          brokerCertChainAndKey:
            secretName: my-secret
            certificate: my-listener-certificate.crt
            key: my-listener-key.key
    # ...

    TLS 侦听器配置示例

    # ...
    listeners:
      - name: plain
        port: 9092
        type: internal
        tls: false
      - name: tls
        port: 9093
        type: internal
        tls: true
        configuration:
          brokerCertChainAndKey:
            secretName: my-secret
            certificate: my-listener-certificate.crt
            key: my-listener-key.key
    # ...

  3. 应用新配置以创建或更新资源:

    oc apply -f kafka.yaml

    Cluster Operator 启动 Kafka 集群的滚动更新,该集群更新监听程序的配置。

    注意

    如果您更新监听程序已使用的 Secret 中的 Kafka 侦听器证书,也会启动滚动更新。

14.3.5. Kafka 监听器的服务器证书中的替代主题

要将 TLS 主机名验证用于您自己的 Kafka 侦听器证书,您必须为每个监听器 使用正确的 Subject Alternative Names (SANs)。证书 SAN 必须为以下内容指定主机名:

  • 集群中的所有 Kafka 代理
  • Kafka 集群 bootstrap 服务

如果您的 CA 支持,您可以使用通配符证书。

14.3.5.1. 内部监听程序的 SAN 示例

使用以下示例来帮助为内部监听程序在证书中指定 SAN 的主机名。

<cluster-name > 替换为 Kafka 集群的名称,<namespace > 替换为运行集群的 OpenShift 命名空间。

type: internal listener 的通配符示例

//Kafka brokers
*.<cluster-name>-kafka-brokers
*.<cluster-name>-kafka-brokers.<namespace>.svc

// Bootstrap service
<cluster-name>-kafka-bootstrap
<cluster-name>-kafka-bootstrap.<namespace>.svc

type: internal listener 的非通配符示例

// Kafka brokers
<cluster-name>-kafka-0.<cluster-name>-kafka-brokers
<cluster-name>-kafka-0.<cluster-name>-kafka-brokers.<namespace>.svc
<cluster-name>-kafka-1.<cluster-name>-kafka-brokers
<cluster-name>-kafka-1.<cluster-name>-kafka-brokers.<namespace>.svc
# ...

// Bootstrap service
<cluster-name>-kafka-bootstrap
<cluster-name>-kafka-bootstrap.<namespace>.svc

type: cluster-ip listener 的非通配符示例

// Kafka brokers
<cluster-name>-kafka-<listener-name>-0
<cluster-name>-kafka-<listener-name>-0.<namespace>.svc
<cluster-name>-kafka-<listener-name>-1
<cluster-name>-kafka-<listener-name>-1.<namespace>.svc
# ...

// Bootstrap service
<cluster-name>-kafka-<listener-name>-bootstrap
<cluster-name>-kafka-<listener-name>-bootstrap.<namespace>.svc

14.3.5.2. 外部监听程序的 SAN 示例

对于启用了 TLS 加密的外部监听程序,在证书中指定的主机名取决于外部监听程序 类型

表 14.1. sans 用于每种类型的外部监听程序
外部监听程序类型在 SAN 中,指定…​

ingress

所有 Kafka 代理 Ingress 资源的地址以及 bootstrap Ingress 的地址。

您可以使用匹配的通配符名称。

Route

所有 Kafka 代理 路由的地址 以及 bootstrap 路由的地址

您可以使用匹配的通配符名称。

LoadBalancer

所有 Kafka 代理 负载均衡器和 bootstrap loadbalancer 地址的地址。

您可以使用匹配的通配符名称。

nodeport

Kafka 代理 pod 可能调度到的所有 OpenShift worker 节点的地址。

您可以使用匹配的通配符名称。

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

AMQ Streams 支持使用 OAUTHBEARERPLAIN 机制使用 OAuth 2.0 身份验证

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

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

Kafka 代理和客户端都需要配置为使用 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 支持
  • 对 Kafka MirrorMaker、Kafka Connect 和 Kafka Bridge 的客户端 OAuth 2.0 支持

14.4.1. OAuth 2.0 身份验证机制

AMQ Streams 支持 OAUTHBEARER 和 PLAIN 机制进行 OAuth 2.0 身份验证。两个机制都允许 Kafka 客户端与 Kafka 代理建立经过身份验证的会话。客户端、授权服务器和 Kafka 代理之间的身份验证流因每种机制而异。

我们建议您将客户端配置为尽可能使用 OAUTHBEARER。OAUTHBEARER 提供比 PLAIN 更高的安全性,因为客户端凭证不会与 Kafka 代理共享。考虑仅在不支持 OAUTHBEARER 的 Kafka 客户端中使用 PLAIN。

您可以将 Kafka 代理监听程序配置为使用 OAuth 2.0 身份验证来连接客户端。如果需要,您可以在同一 oauth 侦听器上使用 OAUTHBEARER 和 PLAIN 机制。必须支持每个机制的属性必须在 oauth 侦听器配置中明确指定。

OAUTHBEARER 概述

OAUTHBEARER 在 oauth 侦听器配置中自动启用用于 Kafka 代理。您可以将 enableOauthBearer 属性设置为 true,但这不是必需的。

  # ...
  authentication:
    type: oauth
    # ...
    enableOauthBearer: true

许多 Kafka 客户端工具使用在协议级别为 OAUTHBEARER 提供基本支持的库。为了支持应用程序开发,AMQ Streams 为上游 Kafka Client Java 库(但不适用于其他库)提供了一个 OAuth 回调处理器。因此,您不需要编写自己的回调处理程序。应用程序客户端可以使用回调处理程序来提供访问令牌。使用 Go 等其他语言编写的客户端必须使用自定义代码连接到授权服务器并获取访问令牌。

使用 OAUTHBEARER 时,客户端使用 Kafka 代理启动会话,用于凭证交换,其中凭证采用回调处理器提供的 bearer 令牌形式。使用回调,您可以使用三种方式配置令牌置备:

  • 客户端 ID 和 Secret (通过使用 OAuth 2.0 客户端凭证 机制)
  • 长期访问令牌,在配置时手动获取
  • 长期刷新令牌,在配置时手动获取
注意

OAUTHBEARER 身份验证只能由支持协议级别的 OAUTHBEARER 机制的 Kafka 客户端使用。

PLAIN 概述

要使用 PLAIN,您必须在 Kafka 代理的 oauth 侦听器配置中启用它。

在以下示例中,除了 OAUTHBEARER 外,还启用了 PLAIN,这默认是启用的。如果只使用 PLAIN,可以通过将 enableOauthBearer 设置为 false 来禁用 OAUTHBEARER。

  # ...
  authentication:
    type: oauth
    # ...
    enablePlain: true
    tokenEndpointUri: https://OAUTH-SERVER-ADDRESS/auth/realms/external/protocol/openid-connect/token

PLAIN 是所有 Kafka 客户端工具使用的简单身份验证机制。要启用 PLAIN 以用于 OAuth 2.0 身份验证,AMQ Streams 提供了 OAuth 2.0 over PLAIN 服务器端的回调。

对于 PLAIN 的 AMQ Streams 实现,客户端凭证不会存储在 ZooKeeper 中。相反,客户端凭证会在兼容授权服务器后进行集中处理,这与使用 OAUTHBEARER 身份验证类似。

当与 OAuth 2.0 over PLAIN 回调一起使用时,Kafka 客户端使用以下方法之一与 Kafka 代理进行身份验证:

  • 客户端 ID 和 secret (通过使用 OAuth 2.0 客户端凭证机制)
  • 长期访问令牌,在配置时手动获取

对于这两种方法,客户端必须提供 PLAIN usernamepassword 属性,将凭证传递给 Kafka 代理。客户端使用这些属性传递客户端 ID 和机密或用户名和访问令牌。

客户端 ID 和 secret 用于获取访问令牌。

访问令牌作为 password 属性值传递。您可以使用或不使用 $accessToken: 前缀传递访问令牌。

  • 如果您在监听器配置中配置了令牌端点(tokenEndpointUri),则需要前缀。
  • 如果您没有在监听器配置中配置令牌端点(tokenEndpointUri),则不需要前缀。Kafka 代理将密码解释为原始访问令牌。

如果将密码设置为访问令牌,则必须将用户名设置为 Kafka 代理从访问令牌获取的相同的主体名称。您可以使用 userNameClaim,fallbackUserNameClaim,fallbackUsernamePrefix, 和 userInfoEndpointUri 属性在监听器中指定用户名提取选项。用户名提取过程还取决于您的授权服务器;特别是,它将客户端 ID 映射到帐户名称。

注意

使用 PLAIN 的 OAuth 不支持 密码 授权机制。您只能通过 SASL PLAIN 机制对 客户端凭证 (clientId + secret)或访问令牌进行"proxy"机制,如上所述。

14.4.2. OAuth 2.0 Kafka 代理配置

OAuth 2.0 的 Kafka 代理配置涉及:

  • 在授权服务器中创建 OAuth 2.0 客户端
  • 在 Kafka 自定义资源中配置 OAuth 2.0 身份验证
注意

与授权服务器相关,Kafka 代理和 Kafka 客户端都被视为 OAuth 2.0 客户端。

14.4.2.1. 授权服务器上的 OAuth 2.0 客户端配置

要配置 Kafka 代理以验证会话启动期间收到的令牌,建议的做法是在授权服务器中创建一个 OAuth 2.0 client 定义(配置为 confidential),并启用了以下客户端凭证:

  • 客户端 ID 为 kafka (例如)
  • 客户端 ID 和 Secret 作为身份验证机制
注意

在使用授权服务器的非公共内省端点时,您只需要使用客户端 ID 和 secret。使用公共授权服务器端点时通常不需要凭据,就像快速本地 JWT 令牌验证一样。

14.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
      #...

您可以在监听程序中配置 OAuth 2.0 身份验证。我们建议将 OAuth 2.0 身份验证与 TLS 加密一起使用(tls: true)。如果没有加密,连接容易通过令牌偏移而受到网络伪造和未授权访问的影响。

为安全传输层配置带有 type: oauth外部监听程序,以便与客户端通信。

使用带有外部监听程序的 OAuth 2.0

# ...
listeners:
  - name: external
    port: 9094
    type: loadbalancer
    tls: true
    authentication:
      type: oauth
    #...

tls 属性默认为 false,因此必须启用它。

当您将验证类型定义为 OAuth 2.0 时,您可以根据验证类型添加配置,可以是 fast local JWT validationtoken validation using an introspection endpoint

为监听器配置 OAuth 2.0 的步骤,带有描述和示例,请参考 为 Kafka 代理配置 OAuth 2.0 支持

14.4.2.3. 快速本地 JWT 令牌验证配置

快速本地 JWT 令牌验证在本地检查 JWT 令牌签名。

本地检查可确保令牌:

  • 通过包含访问令牌的 Bearer 的(typ)声明值来达到类型
  • 有效(未过期)
  • 具有与 validIssuerURI 匹配的签发者

在配置监听程序时,您可以指定 validIssuerURI 属性,以便授权服务器未签发的任何令牌都会被拒绝。

授权服务器不需要在快速本地 JWT 令牌验证期间联系。您可以通过指定 jwksEndpointUri 属性(OAuth 2.0 授权服务器公开的端点)来激活快速本地 JWT 令牌验证。端点包含验证已签名的 JWT 令牌的公钥,这些令牌由 Kafka 客户端作为凭证发送。

注意

所有与授权服务器的通信都应该使用 TLS 加密来执行。

您可以在 AMQ Streams 项目命名空间中将证书信任存储配置为 OpenShift Secret,并使用 tlsTrustedCertificates 属性指向包含 truststore 文件的 OpenShift Secret。

您可能想要配置 userNameClaim,以从 JWT 令牌正确提取用户名。如果需要,您可以使用 JsonPath 表达式,如 "['user.info'].['user.id']",从令牌中的嵌套 JSON 属性检索用户名。

如果要使用 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
    #...

14.4.2.4. OAuth 2.0 内省端点配置

使用 OAuth 2.0 内省端点验证令牌会将收到的访问令牌视为不透明。Kafka 代理向内省端点发送访问令牌,该端点使用验证所需的令牌信息进行响应。最重要的是,如果特定的访问令牌有效,它会返回最新的信息,以及令牌何时到期的信息。

要配置基于 OAuth 2.0 内省的验证,您可以指定一个 introspectionEndpointUri 属性,而不是为快速本地 JWT 令牌验证指定的 jwksEndpointUri 属性。根据授权服务器,通常必须指定 clientIdclientSecret,因为内省端点通常受到保护。

内省端点配置示例

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

14.4.3. Kafka 代理的会话重新身份验证

您可以将 oauth 侦听器配置为使用 Kafka 会话重新身份验证 Kafka 客户端和 Kafka 代理之间的 OAuth 2.0 会话。这种机制在定义的时间段内强制实施客户端和代理之间经过身份验证的会话的到期。当会话过期时,客户端会立即使用现有连接而不是丢弃它来启动新的会话。

会话重新身份验证默认被禁用。要启用它,您可以在 oauth 侦听器配置中为 maxSecondsWithoutReauthentication 设置时间值。相同的属性用于为 OAUTHBEARER 和 PLAIN 身份验证配置会话重新身份验证。有关配置示例,请参阅 第 14.4.6.2 节 “为 Kafka 代理配置 OAuth 2.0 支持”

会话重新身份验证必须由客户端使用的 Kafka 客户端库支持。

会话重新身份验证可用于快速 本地 JWT内省端点 令牌验证。

客户端重新身份验证

当代理的经过身份验证的会话过期时,客户端必须通过向代理发送新的有效的访问令牌来重新验证现有的会话。

如果令牌验证成功,则使用现有连接启动新的客户端会话。如果客户端无法重新验证,代理会在进一步尝试发送或接收消息时关闭连接。如果在代理上启用了重新身份验证机制,使用 Kafka 客户端库 2.2 或更高版本的 Java 客户端会自动重新验证。

如果使用,会话重新身份验证也适用于刷新令牌。当会话过期时,客户端会使用其刷新令牌来刷新访问令牌。然后,客户端使用新的访问令牌重新验证现有会话。

OAUTHBEARER 和 PLAIN 的会话过期

配置会话重新身份验证后,对于 OAUTHBEARER 和 PLAIN 身份验证,会话到期会有所不同。

对于 OAUTHBEARER 和 PLAIN,使用客户端 ID 和 secret 方法:

  • 代理的经过身份验证的用户会话将在配置的 maxSeconds withoutReauthentication 下过期。
  • 如果访问令牌在配置时间之前过期,则会话将过期。

对于使用长期访问令牌方法的 PLAIN:

  • 代理的经过身份验证的用户会话将在配置的 maxSeconds withoutReauthentication 下过期。
  • 如果访问令牌在配置时间之前过期,则重新身份验证将失败。虽然尝试会话重新身份验证,但 PLAIN 没有刷新令牌的机制。

如果没有配置 maxSecondsWithoutReauthentication,OAUTHBEARER 和 PLAIN 客户端可以无限期地连接到代理,而无需重新验证。经过身份验证的会话不会以访问令牌到期结尾。但是,这可以在配置授权时考虑,例如使用 keycloak 授权或安装自定义授权器。

14.4.4. OAuth 2.0 Kafka 客户端配置

Kafka 客户端配置有:

  • 从授权服务器获取有效访问令牌(客户端 ID 和 Secret)所需的凭证
  • 使用授权服务器提供的工具获取有效的长期访问令牌或刷新令牌

发送到 Kafka 代理的唯一信息是一个访问令牌。用于与授权服务器进行身份验证的凭证从不会发送到代理。

当客户端获取访问令牌时,不需要进一步与授权服务器通信。

最简单的机制是使用客户端 ID 和 Secret 进行身份验证。使用长期的访问令牌或长期的刷新令牌会增加复杂性,因为对授权服务器工具还有额外的依赖。

注意

如果您使用长期访问令牌,您可能需要在授权服务器中配置客户端,以增加令牌的最大生命周期。

如果 Kafka 客户端没有直接配置访问令牌,客户端会在 Kafka 会话发起授权服务器的过程中交换访问令牌的凭证。Kafka 客户端交换:

  • 客户端 ID 和 Secret
  • 客户端 ID、刷新令牌和(可选)secret
  • 用户名和密码,带有客户端 ID 和(可选)secret

14.4.5. OAuth 2.0 客户端身份验证流程

OAuth 2.0 身份验证流程取决于底层 Kafka 客户端和 Kafka 代理配置。该流还必须被使用的授权服务器支持。

Kafka 代理侦听器配置决定了客户端如何使用访问令牌进行身份验证。客户端可以传递客户端 ID 和机密来请求访问令牌。

如果侦听器配置为使用 PLAIN 身份验证,客户端可以通过客户端 ID 和 secret 或用户名和访问令牌进行身份验证。这些值作为 PLAIN 机制 usernamepassword 属性传递。

侦听器配置支持以下令牌验证选项:

  • 您可以使用基于 JWT 签名检查和本地令牌内省的快速本地令牌验证,而无需联系授权服务器。授权服务器提供带有公共证书的 JWKS 端点,用于验证令牌中的签名。
  • 您可以使用对授权服务器提供的令牌内省端点的调用。每次建立新的 Kafka 代理连接时,代理都会将从客户端收到的访问令牌传递给授权服务器。Kafka 代理检查响应以确认令牌是否有效。
注意

授权服务器可能只允许使用不透明访问令牌,这意味着无法进行本地令牌验证。

Kafka 客户端凭证也可以为以下类型的身份验证配置:

  • 使用之前生成的长期访问令牌直接进行本地访问
  • 与授权服务器联系以获取要发布的新访问令牌(使用客户端 ID 和 secret、刷新令牌或用户名和密码)
14.4.5.1. 使用 SASL OAUTHBEARER 机制的客户端身份验证流示例

您可以使用 SASL OAUTHBEARER 机制将以下通信流用于 Kafka 身份验证。

使用客户端 ID 和 secret 的客户端,并将代理委派给授权服务器

Client using client ID and secret with broker delegating validation to authorization server

  1. Kafka 客户端使用客户端 ID 和 secret 从授权服务器请求访问令牌,以及可选的刷新令牌。或者,客户端也可以使用用户名和密码进行身份验证。
  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 令牌签名验证仅适用于短期的令牌,因为如果已撤销令牌,就不会通过授权服务器检查该授权服务器。令牌到期时间写入到令牌,但可以随时进行撤销,因此不能在不联系授权服务器的情况下被考虑。任何发布的令牌都将被视为有效,直到其过期为止。

14.4.5.2. 使用 SASL PLAIN 机制的客户端身份验证流示例

您可以使用 OAuth PLAIN 机制将以下通信流用于 Kafka 身份验证。

使用客户端 ID 和 secret 的客户端以及代理获取客户端的访问令牌

Client using a client ID and secret with the broker obtaining the access token for the client

  1. Kafka 客户端或传递一个 clientId 作为用户名,以及一个 secret 作为密码。
  2. Kafka 代理使用令牌端点将 clientIdsecret 传递给授权服务器。
  3. 如果客户端凭据无效,授权服务器会返回一个新的访问令牌或错误。
  4. Kafka 代理使用以下方法之一验证令牌:

    1. 如果指定了令牌内省端点,Kafka 代理通过在授权服务器上调用端点来验证访问令牌。如果令牌验证成功,则会建立会话。
    2. 如果使用本地令牌内省,则不会向授权服务器发出请求。Kafka 代理使用 JWT 令牌签名检查在本地验证访问令牌。

使用长期访问令牌(无需客户端 ID 和 secret)的客户端

Client using a long-lived access token without a client ID and secret

  1. Kafka 客户端会传递用户名和密码。密码提供在运行客户端前手动和配置的访问令牌的值。
  2. 密码通过或不使用 $accessToken: 字符串前缀来传递,具体取决于 Kafka 代理侦听程序是否配置了令牌端点来进行身份验证。

    1. 如果配置了令牌端点,密码应该以 $accessToken: 前缀,以便代理知道 password 参数包含访问令牌,而不是客户端 secret。Kafka 代理将用户名解释为帐户用户名。
    2. 如果没有在 Kafka 代理监听器上配置令牌端点(强制使用 no-client-credentials 模式),密码应提供没有前缀的访问令牌。Kafka 代理将用户名解释为帐户用户名。在此模式中,客户端不使用客户端 ID 和 secret,password 参数始终解释为原始访问令牌。
  3. Kafka 代理使用以下方法之一验证令牌:

    1. 如果指定了令牌内省端点,Kafka 代理通过在授权服务器上调用端点来验证访问令牌。如果令牌验证成功,则会建立会话。
    2. 如果使用本地令牌内省,则不会向授权服务器发出请求。Kafka 代理使用 JWT 令牌签名检查在本地验证访问令牌。

14.4.6. 配置 OAuth 2.0 身份验证

OAuth 2.0 用于在 Kafka 客户端和 AMQ Streams 组件间交互。

要将 OAuth 2.0 用于 AMQ Streams,您必须:

14.4.6.1. 配置 OAuth 2.0 授权服务器

此流程描述了配置授权服务器以便与 AMQ Streams 集成所需的一般操作。

这些说明不是特定于产品的。

这些步骤取决于所选的授权服务器。有关如何设置 OAuth 2.0 访问的详情,请参考授权服务器的产品文档。

注意

如果您已经部署了授权服务器,您可以跳过部署步骤并使用您当前的部署。

流程

  1. 将授权服务器部署到集群中。
  2. 访问授权服务器的 CLI 或管理控制台,以便为 AMQ Streams 配置 OAuth 2.0。

    现在,准备授权服务器以用于 AMQ Streams。

  3. 配置 kafka-broker 客户端。
  4. 为应用程序的每个 Kafka 客户端组件配置客户端。

接下来要做什么

部署和配置授权服务器后,将 Kafka 代理配置为使用 OAuth 2.0

14.4.6.2. 为 Kafka 代理配置 OAuth 2.0 支持

此流程描述了如何配置 Kafka 代理,以便代理监听程序可以使用授权服务器使用 OAuth 2.0 身份验证。

我们建议通过带有 tls: true 的监听程序通过加密接口使用 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
    包含用于识别用户的实际用户名的令牌声明(或密钥)。其值取决于授权服务器。如有必要,可以使用类似 "['user.info'].['user.id']" 的 JsonPath 表达式,从令牌内的嵌套 JSON 属性检索用户名。
    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
    客户端 Secret 和客户端 ID 用于身份验证。
    4
    包含用于识别用户的实际用户名的令牌声明(或密钥)。其值取决于授权服务器。如有必要,可以使用类似 "['user.info'].['user.id']" 的 JsonPath 表达式,从令牌内的嵌套 JSON 属性检索用户名。
    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://<auth_server_address>/auth/realms/external/protocol/openid-connect/userinfo 6
        enableOauthBearer: false 7
        enablePlain: true 8
        tokenEndpointUri: https://<auth_server_address>/auth/realms/external/protocol/openid-connect/token 9
        customClaimCheck: "@.custom == 'custom-value'" 10
        clientAudience: audience 11
        clientScope: scope 12
        connectTimeoutSeconds: 60 13
        readTimeoutSeconds: 60 14
        httpRetries: 2 15
        httpRetryPauseMs: 300 16
        groupsClaim: "$.groups" 17
        groupsClaimDelimiter: "," 18
    1
    如果您的授权服务器不提供 iss 声明,则无法执行签发者检查。在这种情况下,将 checkIssuer 设置为 false,且不指定有效的Issuer Uri。默认为 true
    2
    如果您的授权服务器提供 aud (audience)声明,并且您想要强制进行使用者检查,请将 checkAudience 设置为 true。Audience 检查标识令牌的预期接收者。因此,Kafka 代理将拒绝在其 aud 声明中没有 clientId 的令牌。默认为 false
    3
    授权服务器可能不会提供单个属性来标识常规用户和客户端。当客户端在其自己的名称中进行身份验证时,服务器可能会提供 客户端 ID。当用户使用用户名和密码进行身份验证来获取刷新令牌或访问令牌时,除了客户端 ID 外,服务器可能会提供一个 username 属性。使用此回退选项指定在主用户 ID 属性不可用时要使用的用户名声明(attribute)。如有必要,可以使用 JsonPath 表达式(如 "['client.info'].['client.id']" 来检索回退用户名,以从令牌内嵌套的 JSON 属性检索用户名。
    4
    当有 fallbackUserNameClaim 时,可能还需要防止用户名声明的值和回退用户名声明之间的名称冲突。考虑存在名为 producer 的客户端,但也存在名为 producer 的普通用户。为了区分两者,您可以使用此属性向客户端的用户 ID 添加前缀。
    5
    (仅在使用 introspectionEndpointUri)取决于您使用的授权服务器,内省端点也可能不会返回 令牌 type 属性,或者可能包含不同的值。您可以指定来自内省端点必须包含的有效令牌类型值。
    6
    (仅在使用 introspectionEndpointUri时)授权服务器可以配置或实施,从而无法在内省端点响应中提供任何可识别的信息。要获得用户 ID,您可以将 userinfo 端点的 URI 配置为回退。userNameClaim,fallbackUserNameClaim, 和 fallbackUserNamePrefix 设置应用到 userinfo 端点的响应。
    7
    把它设置为 false,以禁用监听器上的 OAUTHBEARER 机制。必须至少启用 PLAIN 或 OAUTHBEARER 之一。默认为 true
    8
    设置为 true 以在监听器上启用 PLAIN 身份验证,在所有平台上的客户端都支持该身份验证。
    9
    PLAIN 机制的额外配置。如果指定,客户端可以使用 $accessToken: 前缀将访问令牌 作为密码 来通过 PLAIN 进行身份验证。对于生产环境,始终使用 https:// urls。
    10
    通过将其设置为 JsonPath 过滤器查询,可以在验证过程中对 JWT 访问令牌实施额外的自定义规则。如果访问令牌不包含必要的数据,则会被拒绝。使用 introspectionEndpointUri 时,自定义检查将应用到内省端点响应 JSON。
    11
    一个 audience 参数传递给令牌端点。在获取用于代理身份验证的访问令牌时,需要使用 audience。它还在使用 clientIdsecret 的 PLAIN 客户端验证中用于 OAuth 2.0 的客户端名称。这只会影响获取令牌的能力,以及令牌的内容,具体取决于授权服务器。它不会影响监听程序的令牌验证规则。
    12
    传递给令牌端点的 scope 参数。获取访问令牌进行代理身份验证时使用的 scope。它还在使用 clientIdsecret 的 PLAIN 客户端验证中用于 OAuth 2.0 的客户端名称。这只会影响获取令牌的能力,以及令牌的内容,具体取决于授权服务器。它不会影响监听程序的令牌验证规则。
    13
    连接到授权服务器时的连接超时(以秒为单位)。默认值为 60。
    14
    连接到授权服务器时的读取超时(以秒为单位)。默认值为 60。
    15
    将失败的 HTTP 请求重试到授权服务器的次数上限。默认值为 0, 表示没有执行重试。要有效地使用这个选项,请考虑减少 connectTimeoutSecondsreadTimeoutSeconds 选项的超时时间。但请注意,重试可能会阻止当前 worker 线程对其他请求使用,如果太多请求停滞,可能会导致 Kafka 代理无响应。
    16
    在尝试另一个失败 HTTP 请求重试到授权服务器前等待的时间。默认情况下,这段时间设为零,这意味着不会应用暂停。这是因为,导致失败请求的很多问题都是可快速解决的网络 glitches 或代理问题。但是,如果您的授权服务器处于压力或遇到高流量,您可能希望将此选项设置为 100 ms 或更高值,以减少服务器上的负载并增加成功重试的可能性。
    17
    JsonPath 查询,用于从 JWT 令牌或内省端点响应中提取组信息。默认情况下不设置这个选项。通过配置此选项,自定义授权程序可以根据用户组做出授权决策。
    18
    当以单一分隔字符串返回时,用于解析组的分隔符。默认值为 ','(comma)。
  3. 保存并退出编辑器,然后等待滚动更新完成。
  4. 检查日志中的更新,或者通过观察 pod 状态转换:

    oc logs -f ${POD_NAME} -c ${CONTAINER_NAME}
    oc get pod -w

    滚动更新将代理配置为使用 OAuth 2.0 身份验证。

14.4.6.3. 配置 Kafka Java 客户端以使用 OAuth 2.0

配置 Kafka producer 和消费者 API,以使用 OAuth 2.0 与 Kafka 代理交互。在您的客户端 pom.xml 文件中添加回调插件,然后为 OAuth 2.0 配置客户端。

在客户端配置中指定以下内容:

  • SASL (简单身份验证和安全层)安全协议:

    • SASL_SSL 用于通过 TLS 加密连接进行身份验证
    • SASL_PLAINTEXT 用于通过未加密的连接进行身份验证

      SASL_SSL 用于生产环境,并且 SASL_PLAINTEXT 仅用于本地开发。使用 SASL_SSL 时,需要额外的 ssl.truststore 配置。安全连接(https://)与 OAuth 2.0 授权服务器需要 truststore 配置。要验证 OAuth 2.0 授权服务器,请将授权服务器的 CA 证书添加到客户端配置的信任存储中。您可以使用 PEM 或 PKCS #12 格式配置信任存储。

  • Kafka SASL 机制:

    • OAUTHBEARER 用于使用 bearer 令牌的凭证交换
    • PLAIN 传递客户端凭证(clientId + secret)或访问令牌
  • 实现 SASL 机制的 JAAS (Java 身份验证和授权服务)模块:

    • org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule 实现 OAUTHBEARER 机制
    • org.apache.kafka.common.security.plain.PlainLoginModule 实现 PLAIN 机制
  • SASL 验证方法,它支持以下验证方法:

    • OAuth 2.0 客户端凭证
    • OAuth 2.0 密码授权(已弃用)
    • 访问令牌
    • 刷新令牌

添加 SASL 身份验证属性作为 JAAS 配置(sasl.jaas.config)。如何配置身份验证属性取决于您用于访问 OAuth 2.0 授权服务器的身份验证方法。在此过程中,属性在属性文件中指定,然后加载到客户端配置中。

注意

您还可以将身份验证属性指定为环境变量,或作为 Java 系统属性指定。对于 Java 系统属性,您可以使用 setProperty 设置它们,并使用 -D 选项在命令行中传递它们。

先决条件

  • AMQ Streams 和 Kafka 正在运行
  • 为 OAuth 访问 Kafka 代理部署并配置 OAuth 2.0 授权服务器
  • 为 OAuth 2.0 配置 Kafka 代理

流程

  1. 将带有 OAuth 2.0 支持的客户端库添加到 Kafka 客户端的 pom.xml 文件中:

    <dependency>
     <groupId>io.strimzi</groupId>
     <artifactId>kafka-oauth-client</artifactId>
     <version>0.13.0.redhat-00008</version>
    </dependency>
  2. 通过在属性文件中指定以下配置来配置客户端属性:

    • 安全协议
    • SASL 机制
    • JAAS 模块和身份验证属性,具体取决于所使用的方法

      例如,我们可以将以下内容添加到 client.properties 文件中:

      客户端凭证机制属性

      security.protocol=SASL_SSL 1
      sasl.mechanism=OAUTHBEARER 2
      ssl.truststore.location=/tmp/truststore.p12 3
      ssl.truststore.password=$STOREPASS
      ssl.truststore.type=PKCS12
      sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
        oauth.token.endpoint.uri="<token_endpoint_url>" \ 4
        oauth.client.id="<client_id>" \ 5
        oauth.client.secret="<client_secret>" \ 6
        oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \ 7
        oauth.ssl.truststore.password="$STOREPASS" \ 8
        oauth.ssl.truststore.type="PKCS12" \ 9
        oauth.scope="<scope>" \ 10
        oauth.audience="<audience>" ; 11

      1
      TLS 加密连接的 SASL_SSL 安全协议。仅对本地开发使用 SASL_PLAINTEXT 来进行本地开发。
      2
      SASL 机制指定为 OAUTHBEARERPLAIN
      3
      用于安全访问 Kafka 集群的信任存储配置。
      4
      授权服务器令牌端点的 URI。
      5
      客户端 ID,这是在授权服务器中创建客户端时使用的名称。
      6
      在授权服务器中创建 客户端 时创建的客户端 secret。
      7
      位置包含授权服务器的公钥证书(truststore.p12)。
      8
      用于访问 truststore 的密码。
      9
      truststore 类型。
      10
      (可选)从令牌端点请求令牌的范围。授权服务器可能需要客户端指定范围。
      11
      (可选)从令牌端点请求令牌的听众。授权服务器可能需要客户端指定使用者。

      密码授予机制属性

      security.protocol=SASL_SSL
      sasl.mechanism=OAUTHBEARER
      ssl.truststore.location=/tmp/truststore.p12
      ssl.truststore.password=$STOREPASS
      ssl.truststore.type=PKCS12
      sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
        oauth.token.endpoint.uri="<token_endpoint_url>" \
        oauth.client.id="<client_id>" \ 1
        oauth.client.secret="<client_secret>" \ 2
        oauth.password.grant.username="<username>" \ 3
        oauth.password.grant.password="<password>" \ 4
        oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \
        oauth.ssl.truststore.password="$STOREPASS" \
        oauth.ssl.truststore.type="PKCS12" \
        oauth.scope="<scope>" \
        oauth.audience="<audience>" ;

      1
      客户端 ID,这是在授权服务器中创建客户端时使用的名称。
      2
      (可选)在授权服务器中创建客户端时创建的客户端 secret。
      3
      password 授权身份验证的用户名。OAuth 密码授权配置(用户名和密码)使用 OAuth 2.0 密码授权方法。要使用密码授权,请在您的授权服务器上为客户端创建一个有限权限的用户帐户。帐户应像服务帐户一样操作。在进行身份验证需要用户帐户的环境中使用,但首先考虑使用刷新令牌。
      4
      密码以授予密码身份验证。
      注意

      SASL PLAIN 不支持使用 OAuth 2.0 密码授权方法传递用户名和密码(密码授权)。

      访问令牌属性

      security.protocol=SASL_SSL
      sasl.mechanism=OAUTHBEARER
      ssl.truststore.location=/tmp/truststore.p12
      ssl.truststore.password=$STOREPASS
      ssl.truststore.type=PKCS12
      sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
        oauth.token.endpoint.uri="<token_endpoint_url>" \
        oauth.access.token="<access_token>" ; 1
        oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \
        oauth.ssl.truststore.password="$STOREPASS" \
        oauth.ssl.truststore.type="PKCS12" \

      1
      Kafka 客户端的长期访问令牌。

      刷新令牌属性

      security.protocol=SASL_SSL
      sasl.mechanism=OAUTHBEARER
      ssl.truststore.location=/tmp/truststore.p12
      ssl.truststore.password=$STOREPASS
      ssl.truststore.type=PKCS12
      sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
        oauth.token.endpoint.uri="<token_endpoint_url>" \
        oauth.client.id="<client_id>" \ 1
        oauth.client.secret="<client_secret>" \ 2
        oauth.refresh.token="<refresh_token>" ; 3
        oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \
        oauth.ssl.truststore.password="$STOREPASS" \
        oauth.ssl.truststore.type="PKCS12" \

      1
      客户端 ID,这是在授权服务器中创建客户端时使用的名称。
      2
      (可选)在授权服务器中创建客户端时创建的客户端 secret。
      3
      Kafka 客户端的长期刷新令牌。
  3. 在 Java 客户端代码中输入 OAUTH 2.0 身份验证的客户端属性。

    显示客户端属性输入示例

    Properties props = new Properties();
    try (FileReader reader = new FileReader("client.properties", StandardCharsets.UTF_8)) {
      props.load(reader);
    }

  4. 验证 Kafka 客户端能否访问 Kafka 代理。
14.4.6.4. 为 Kafka 组件配置 OAuth 2.0

这个步骤描述了如何使用授权服务器将 Kafka 组件配置为使用 OAuth 2.0 身份验证。

您可以为以下配置身份验证:

  • Kafka Connect
  • Kafka MirrorMaker
  • Kafka Bridge

在这种情况下,Kafka 组件和授权服务器在同一集群中运行。

开始前

有关为 Kafka 组件配置 OAuth 2.0 身份验证的更多信息,请参阅 KafkaClientAuthenticationOAuth 模式参考。schema 引用包括配置选项示例。

先决条件

  • AMQ Streams 和 Kafka 正在运行
  • 为 OAuth 访问 Kafka 代理部署并配置 OAuth 2.0 授权服务器
  • 为 OAuth 2.0 配置 Kafka 代理

流程

  1. 创建客户端 secret,并将它作为环境变量挂载到组件。

    例如,这里为 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

    例如,这里的 OAuth 2.0 使用客户端 ID 和 secret 和 TLS 分配给 Kafka Bridge 客户端:

    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
        connectTimeoutSeconds: 60 6
        readTimeoutSeconds: 60 7
        httpRetries: 2 8
        httpRetryPauseMs: 300 9
    1
    (可选)禁用 TLS 主机名验证。默认为 false
    2
    如果授权服务器没有返回 JWT 令牌中的 typ (类型)声明,您可以应用 checkAccessTokenType: false 来跳过令牌类型检查。默认为 true
    3
    如果使用不透明令牌,您可以应用 accessTokenIsJwt: false,以便访问令牌不会被视为 JWT 令牌。
    4
    (可选)从令牌端点请求令牌的范围。授权服务器可能需要客户端指定范围。在这种情况下,它都是 any
    5
    (可选)从令牌端点请求令牌的听众。授权服务器可能需要客户端指定使用者。在本例中,是 kafka
    6
    (可选)连接到授权服务器时的连接超时(以秒为单位)。默认值为 60。
    7
    (可选)连接到授权服务器时的读取超时(以秒为单位)。默认值为 60。
    8
    (可选)将失败的 HTTP 请求重试到授权服务器的次数上限。默认值为 0, 表示没有执行重试。要有效地使用这个选项,请考虑减少 connectTimeoutSecondsreadTimeoutSeconds 选项的超时时间。但请注意,重试可能会阻止当前 worker 线程对其他请求使用,如果太多请求停滞,可能会导致 Kafka 代理无响应。
    9
    (可选)尝试对授权服务器进行另一个失败的 HTTP 请求重试前等待的时间。默认情况下,这段时间设为零,这意味着不会应用暂停。这是因为,导致失败请求的很多问题都是可快速解决的网络 glitches 或代理问题。但是,如果您的授权服务器处于压力或遇到高流量,您可能希望将此选项设置为 100 ms 或更高值,以减少服务器上的负载并增加成功重试的可能性。
  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 代理交互。

14.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 插件来配置基于 Access Control Lists (ACL)的授权。

ZooKeeper 存储 ACL 规则,该规则根据 用户名 授予或拒绝对资源的访问。但是,红帽单点登录基于 OAuth 2.0 令牌的授权在您希望实现对 Kafka 代理的访问控制方面具有更大的灵活性。另外,您可以将 Kafka 代理配置为使用 OAuth 2.0 授权和 ACL。

14.5.1. OAuth 2.0 授权机制

AMQ Streams 中的 OAuth 2.0 授权使用红帽单点登录服务器授权服务 REST 端点,通过在特定用户上应用定义的安全策略来扩展基于令牌的身份验证,并为该用户提供授予不同资源的权限列表。策略使用角色和组来匹配用户的权限。OAuth 2.0 授权根据从 Red Hat Single Sign-On Authorization Services 用户获得的授予者列表在本地强制实施权限。

14.5.1.1. Kafka 代理自定义授权器

AMQ Streams 提供了一个 Red Hat Single Sign-On authorizer (KeycloakAuthorizer)。为了对 Red Hat Single Sign-On 提供的授权服务使用 Red Hat Single Sign-On REST 端点,您可以在 Kafka 代理上配置自定义授权程序。

授权程序根据需要从授权服务器获取授予权限的列表,并在 Kafka Broker 上本地强制实施授权,为每个客户端请求做出快速授权决策。

14.5.2. 配置 OAuth 2.0 授权支持

这个步骤描述了如何使用 Red Hat Single Sign-On Authorization Services 将 Kafka 代理配置为使用 OAuth 2.0 授权服务。

开始前

考虑某些用户所需的访问权限或希望限制某些用户。您可以使用 Red Hat Single Sign-On 角色客户端 和用户 的组合在 Red Hat Single Sign-On 中配置访问权限。

通常,组用于根据机构部门或地理位置匹配用户。和 角色用于根据其功能匹配用户。

使用红帽单点登录,您可以在 LDAP 中存储用户和组,而客户端和角色不能以这种方式存储。在选择配置授权策略时,对用户数据的存储和访问可能是如何配置授权策略的因素。

注意

无论在 Kafka 代理上实现的授权是什么,超级用户 始终对 Kafka 代理具有不受限制的访问权限。

先决条件

  • AMQ Streams 必须通过 Red Hat Single Sign-On 配置为使用 OAuth 2.0 进行基于令牌的身份验证。设置授权时,您可以使用相同的 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 代理配置(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
          grantsMaxIdleSeconds: 300 10
          grantsGcPeriodSeconds: 300 11
          grantsAlwaysLatest: false 12
          connectTimeoutSeconds: 60 13
          readTimeoutSeconds: 60 14
          httpRetries: 2 15
          enableMetrics: false 16
        #...
    1
    类型 keycloak 启用 Red Hat Single Sign-On authorization。
    2
    Red Hat Single Sign-On 令牌端点的 URI。对于生产环境,始终使用 https:// urls。当您配置基于令牌的 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。
    10
    (可选)缓存中闲置授权可以被驱除的时间(以秒为单位)。默认值为 300。
    11
    (可选) 连续运行从缓存中清除过时的作业之间的时间(以秒为单位)。默认值为 300。
    12
    (可选)控制是否为新会话获取最新的授权。启用后,从 Red Hat Single Sign-On 检索并缓存该用户。默认值为 false
    13
    (可选)连接到 Red Hat Single Sign-On 令牌端点时的连接超时(以秒为单位)。默认值为 60。
    14
    (可选)连接到 Red Hat Single Sign-On 令牌端点时的读取超时(以秒为单位)。默认值为 60。
    15
    (可选)到授权服务器失败的 HTTP 请求的次数(无需暂停)的最大次数。默认值为 0, 表示没有执行重试。要有效地使用这个选项,请考虑减少 connectTimeoutSecondsreadTimeoutSeconds 选项的超时时间。但请注意,重试可能会阻止当前 worker 线程对其他请求使用,如果太多请求停滞,可能会导致 Kafka 代理无响应。
    16
    (可选)启用或禁用 OAuth 指标。默认值为 false
  6. 保存并退出编辑器,然后等待滚动更新完成。
  7. 检查日志中的更新,或者通过观察 pod 状态转换:

    oc logs -f ${POD_NAME} -c kafka
    oc get pod -w

    滚动更新将代理配置为使用 OAuth 2.0 授权。

  8. 通过以客户端或具有特定角色的用户访问 Kafka 代理来验证配置的权限,确保它们具有必要的访问权限,或者没有应该具有访问权限。

14.5.3. 在 Red Hat Single Sign-On 授权服务中管理策略和权限

本节论述了 Red Hat Single Sign-On Authorization 服务和 Kafka 使用的授权模型,并在每个模型中定义重要概念。

要授予访问 Kafka 的权限,您可以通过在 Red Hat Single Sign-On 中创建 OAuth 客户端规格 将 Red Hat Single Sign-On 授权服务对象映射到 Kafka 资源。使用 Red Hat Single Sign-On Authorization Services 规则为用户帐户或服务帐户授予 Kafka 权限。

示例显示了常见 Kafka 操作所需的不同用户权限,如创建和列出主题。

14.5.3.1. Kafka 和 Red Hat Single Sign-On 授权模型概述

Kafka 和 Red Hat Single Sign-On 授权服务使用不同的授权模型。

Kafka 授权模型

Kafka 的授权模型使用 资源类型。当 Kafka 客户端对代理执行操作时,代理使用配置的 KeycloakAuthorizer 来根据操作和资源类型检查客户端的权限。

Kafka 使用五个资源类型来控制访问: 主题集群TransactionalIdDelegationToken。每个资源类型都有一组可用权限。

Topic

  • 创建
  • 删除
  • Describe
  • DescribeConfigs
  • 更改
  • AlterConfigs

  • Describe
  • 删除

集群

  • 创建
  • Describe
  • 更改
  • DescribeConfigs
  • AlterConfigs
  • IdempotentWrite
  • ClusterAction

transactionalId

  • Describe

DelegationToken

  • Describe
Red Hat Single Sign-On Authorization Services 模型

Red Hat Single Sign-On Authorization Services 模型有四个概念来定义和授予权限:resources(资源), authorization scopes(授权范围), policies(政策), 和 permissions(权限)

Resources
资源是一组资源定义,用于将资源与允许的操作匹配。资源可以是单独的主题,例如,也可以是名称以相同前缀开头的所有主题。资源定义与一组可用的授权范围关联,它们代表资源上所有可用的操作。通常,实际上只允许这些操作的子集。
授权范围
授权范围是特定资源定义上所有可用操作的集合。当您定义新资源时,您可以从所有范围集中添加范围。
策略(policy)

策略是一个授权规则,它使用与帐户列表匹配的条件。策略可以匹配:

  • 基于客户端 ID 或角色 的服务帐户
  • 基于用户名、组或角色 的用户帐户
权限
权限为一组用户授予特定资源定义上的授权范围子集。

其他资源

14.5.3.2. 将 Red Hat Single Sign-On 授权服务映射到 Kafka 授权模型

Kafka 授权模型用作定义将控制对 Kafka 访问权限的 Red Hat Single Sign-On 角色和资源的基础。

要为用户帐户或服务帐户授予 Kafka 权限,您首先在 Red Hat Single Sign-On 中为 Kafka 代理创建 OAuth 客户端规格。然后,您可以在客户端上指定 Red Hat Single Sign-On Authorization Services 规则。通常,代表代理的 OAuth 客户端的客户端 ID 是 kafka。由 AMQ Streams 提供 的示例配置文件 使用 kafka 作为 OAuth 客户端 ID。

注意

如果您有多个 Kafka 集群,您可以将单个 OAuth 客户端(kafka)用于所有这些集群。这可让您定义一个统一空间,在其中定义和管理授权规则。但是,您还可以使用不同的 OAuth 客户端 ID (如 my-cluster-kafkacluster-dev-kafka),并在每个客户端配置中为每个集群定义授权规则。

kafka 客户端定义必须在 Red Hat Single Sign-On Admin 控制台中启用 Authorization Enabled 选项。

所有权限都存在于 kafka 客户端范围内。如果您使用不同的 OAuth 客户端 ID 配置不同的 Kafka 集群,则每个集群都需要一组单独的权限,即使它们是同一个 Red Hat Single Sign-On 域的一部分。

当 Kafka 客户端使用 OAUTHBEARER 身份验证时,Red Hat Single Sign-On 授权器(KeycloakAuthorizer)使用当前会话的访问令牌从 Red Hat Single Sign-On 服务器检索授权列表。为了检索授予,授权者评估 Red Hat Single Sign-On Authorization Services 策略和权限。

Kafka 权限的授权范围

初始的红帽单点登录配置通常涉及上传授权范围,以创建可在每个 Kafka 资源类型上执行的所有可能操作的列表。在定义任何权限前,仅执行此步骤一次。您可以手动添加授权范围,而不是上传它们。

授权范围必须包含所有可能的 Kafka 权限,而不考虑资源类型:

  • 创建
  • 删除
  • Describe
  • 更改
  • DescribeConfig
  • AlterConfig
  • ClusterAction
  • IdempotentWrite
注意

如果您确定您不需要权限(例如,Idempot entWrite),您可以从授权范围列表中省略它。但是,那个权限无法用于 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 规则

带有一个唯一名称,可以重复使用以多个资源为目标的多个权限。

授予访问权限的权限

使用细粒度权限将策略、资源和授权范围一起拉取给用户授予访问权限的策略、资源和授权范围。

每个权限的名称应明确定义其授予哪些用户的权限。例如,Dev Team B 可以从以 x 开头的主题中读取

其他资源

14.5.3.3. Kafka 操作所需的权限示例

以下示例演示了在 Kafka 上执行常见操作所需的用户权限。

创建主题

要创建主题,需要特定主题或 Cluster:kafka-clusterCreate 权限。

bin/kafka-topics.sh --create --topic my-topic \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

列出主题

如果用户对指定主题具有 Describe 权限,则会列出该主题。

bin/kafka-topics.sh --list \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

显示主题详情

要显示主题的详情,在主题上需要 DescribeDescribeConfigs 权限。

bin/kafka-topics.sh --describe --topic my-topic \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

生成消息到主题

要生成消息到主题,在主题上需要 DescribeWrite 权限。

如果主题尚未创建,并且启用了主题自动创建,则需要创建主题的权限。

bin/kafka-console-producer.sh  --topic my-topic \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --producer.config=/tmp/config.properties

使用来自主题的消息

为了消费主题中的消息,需要有主题的 DescribeRead 权限。在主题中使用通常依赖于将消费者偏移存储在消费者组中,这需要对消费者组需要额外的 DescribeRead 权限。

匹配需要两个 资源。例如:

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

使用幂等制作者向主题生成消息

除了生成主题的权限外,Cluster:kafka-cluster 资源还需要额外的 IdempotentWrite 权限。

匹配需要两个 资源。例如:

Topic:my-topic
Cluster:kafka-cluster
bin/kafka-console-producer.sh  --topic my-topic \
  --bootstrap-server 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

显示消费者组详情

要显示消费者组的详细信息,需要 Describe 权限以及与组关联的主题。

bin/kafka-consumer-groups.sh --describe --group my-group-1 \
  --bootstrap-server my-cluster-kafka-bootstrap:9092 --command-config=/tmp/config.properties

更改主题配置

要更改主题的配置,需要主题的 DescribeAlter 权限。

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 需要 DescribeConfigs 权限。

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 需要 DescribeConfigsAlterConfigs 权限。

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

删除主题

要删除主题,需要主题上的 DescribeDelete 权限。

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

重新分配分区

要生成分区重新分配文件,对涉及的主题需要 Describe 权限。

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 上需要 DescribeAlter 权限。另外,有关涉及的主题还需要 Describe 权限。

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,以及涉及的每个主题上需要验证分区重新分配、DescribeAlterConfigs 权限。

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

14.5.4. Try Red Hat Single Sign-On Authorization Services

本例解释了如何在 keycloak 授权中使用 Red Hat Single Sign-On Authorization Services。使用 Red Hat Single Sign-On Authorization Services 对 Kafka 客户端强制访问限制。Red Hat Single Sign-On Authorization Services 使用授权范围、策略和权限来定义并应用访问控制。

Red Hat Single Sign-On Authorization Services REST 端点提供经过身份验证的用户授予资源的权限列表。授权(权限)列表从 Red Hat Single Sign-On 服务器获取,作为 Kafka 客户端建立身份验证会话的第一个操作。该列表在后台刷新,以便检测到对授权的更改。授予会在 Kafka 代理本地缓存并强制每个用户会话,以提供快速授权决策。

AMQ Streams 提供 示例配置文件。这包括用于设置 Red Hat Single Sign-On 的示例文件:

kafka-ephemeral-oauth-single-keycloak-authz.yaml
使用 Red Hat Single Sign-On 为基于 OAuth 2.0 令牌的授权配置的 Kafka 自定义资源示例。您可以使用自定义资源来部署使用 keycloak 授权和基于令牌的 oauth 身份验证的 Kafka 集群。
kafka-authz-realm.json
配置了示例组、用户、角色和客户端的 Red Hat Single Sign-On 域示例。您可以将域导入到 Red Hat Single Sign-On 实例中,以设置精细的权限来访问 Kafka。

如果要使用 Red Hat Single Sign-On 尝试示例,请使用这些文件按照所示的顺序执行本节中所述的任务。

身份验证

当您配置基于令牌的 oauth 身份验证时,您可以指定 jwksEndpointUri 作为本地 JWT 验证的 URI。当您配置 keycloak 授权时,您可以指定 tokenEndpointUri 作为 Red Hat Single Sign-On 令牌端点的 URI。两个 URI 的主机名必须相同。

带有组或角色策略的目标权限

在 Red Hat Single Sign-On 中,启用了服务帐户的机密客户端可以使用客户端 ID 和 secret 向服务器进行身份验证。这对通常以自己的名称而不是特定用户代理(如网站)的微服务方便。服务帐户可以像常规用户一样分配角色。但是,他们无法分配组。因此,如果要使用服务帐户将权限传送到微服务,则无法使用组策略,而应使用角色策略。相反,如果您只想将某些权限限制为需要使用用户名和密码进行身份验证的普通用户帐户,您可以实现作为使用组策略而非角色策略的副作用。本例中使用了以 ClusterManager 开头的权限。执行集群管理通常使用 CLI 工具以互动方式完成。在使用生成的访问令牌向 Kafka 代理进行身份验证前,需要用户登录。在这种情况下,访问令牌代表特定用户,而不是客户端应用程序。

14.5.4.1. 访问 Red Hat Single Sign-On 管理控制台

设置 Red Hat Single Sign-On,然后连接到其管理控制台并添加预配置的域。使用示例 kafka-authz-realm.json 文件导入域。您可以在管理控制台中检查为域定义的授权规则。规则授予对配置为使用 Red Hat Single Sign-On 域示例的 Kafka 集群上的资源的访问权限。

先决条件

  • 一个正常运行的 OpenShift 集群。
  • 包含预配置的域的 AMQ Streams examples/security/keycloak-authorization/kafka-authz-realm.json 文件。

流程

  1. 使用 Red Hat Single Sign-On Operator 安装 Red Hat Single Sign-On 服务器,如 Red Hat Single Sign-On 文档中的 Server Installation and Configuration 所述。
  2. 等待 Red Hat Single Sign-On 实例正在运行。
  3. 获取外部主机名来访问管理控制台。

    NS=sso
    oc get ingress keycloak -n $NS

    在本例中,我们假定 Red Hat Single Sign-On 服务器在 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 的名称来获取明文密码。

    SECRET_NAME=credential-keycloak
    oc get -n $NS secret $SECRET_NAME -o yaml | grep PASSWORD | awk '{print $2}' | base64 -D

    在本例中,我们假定 secret 的名称是 credential-keycloak

  6. 使用用户名 admin 和密码您获取的密码登录管理控制台。

    使用 https://HOSTNAME 访问 Kubernetes Ingress

    现在,您可以使用管理控制台将示例域上传到 Red Hat Single Sign-On。

  7. 单击 Add Realm 以导入示例域。
  8. 添加 examples/security/keycloak-authorization/kafka-authz-realm.json 文件,然后点 Create

    现在,您有 kafka-authz 作为控制台中的当前域。

    默认视图显示 Master 域。

  9. 在 Red Hat Single Sign-On Admin 控制台中,进入 Clients > kafka > Authorization > Settings,检查 Decision Strategy 是否已设置为 Affirmative

    一个关系策略表示,必须至少满足一个策略,以便客户端访问 Kafka 集群。

  10. 在 Red Hat Single Sign-On Admin Console 中,进入 Groups, Users, RolesClients 来查看 realm 配置。

    用于创建用户组并设置用户权限。组是一组分配了名称的用户。它们用于将用户分为地理、组织或部门单元。组可以链接到 LDAP 身份提供程序。您可以通过自定义 LDAP 服务器 admin 用户界面让用户成为组的成员,例如,授予 Kafka 资源的权限。
    用户
    用户 用于创建用户。在本例中,定义了 alicebobaliceClusterManager 组的成员,bobClusterManager-my-cluster 组的成员。用户可以存储在 LDAP 身份提供程序中。
    角色
    Roles 代表用户或客户端具有特定权限。角色与组类似的概念。它们通常 用于标记 具有机构角色的用户并具有必要的权限。角色不能存储在 LDAP 身份提供程序中。如果 LDAP 是必需的,您可以使用组,并将 Red Hat Single Sign-On 角色添加到组中,以便在为用户分配他们获得对应角色的组时。
    客户端

    客户端可以 具有特定的配置。在本例中,配置了 kafka, kafka-cli, team-a-client, 和 team-b-client 客户端。

    • Kafka 代理使用 kafka 客户端来执行访问令牌验证所需的 OAuth 2.0 通信。此客户端还包含用于在 Kafka 代理上执行授权的授权服务资源定义、策略和授权范围。授权配置在 Authorization 选项卡的 kafka 客户端中定义,在从 Settings 标签页上切换 Authorization 时,它就会可见。
    • kafka-cli 客户端是一个公共客户端,在使用用户名和密码进行身份验证时,Kafka 命令行工具使用它来获取访问令牌或刷新令牌。
    • team-a-clientteam-b-client 客户端是代表可以部分访问某些 Kafka 主题的服务的机密客户端。
  11. 在 Red Hat Single Sign-On Admin 控制台中,进入 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
    开发团队 A
    Dev Team A realm 角色可写入任何集群上以 x_ 开头的主题。这会组合一个名为 Topic:xDescribeWrite 范围的资源,以及 Dev 团队 A 策略。Dev Team A 策略与具有名为 Dev Team A 的域角色匹配的所有用户匹配。
    Dev Team B
    Dev Team B realm 角色可以从任何集群中以 x_ 开头的主题中读取。这可组合 Topic:xöGroup:x the 资源、DescribeRead 范围,以及 Dev 团队 B 策略。Dev Team B 策略与具有名为 Dev Team B 的域角色匹配的所有用户。匹配用户和客户端能够读取主题,并为名称以 x_ 开头的主题和消费者组更新消耗的偏移量。
14.5.4.2. 使用 Red Hat Single Sign-On 授权部署 Kafka 集群

部署配置为连接到 Red Hat Single Sign-On 服务器的 Kafka 集群。使用 kafka-ephemeral-oauth-single-keycloak-authz.yaml 文件示例将 Kafka 集群部署为 Kafka 自定义资源。这个示例使用 keycloak 授权和 oauth 身份验证部署单节点 Kafka 集群。

先决条件

  • Red Hat Single Sign-On 授权服务器部署到 OpenShift 集群,并使用 example 域加载。
  • Cluster Operator 部署到 OpenShift 集群。
  • AMQ Streams examples/security/keycloak-authorization/kafka-ephemeral-oauth-single-keycloak-authz.yaml 自定义资源。

流程

  1. 使用您部署的 Red Hat Single Sign-On 实例的主机名,为 Kafka 代理准备信任存储证书,以便与 Red Hat Single Sign-On 服务器通信。

    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.pem

    需要该证书,因为 Kubernetes Ingress 用于建立安全(HTTPS)连接。

    通常没有单个证书,但一个证书链。您只需要提供最顶层的签发者 CA,该 CA 在 /tmp/sso.pem 文件中最后列出。您可以手动提取,或者使用以下命令:

    在证书链中提取顶级 CA 证书的命令示例

    split -p "-----BEGIN CERTIFICATE-----" sso.pem sso-
    for f in $(ls sso-*); do mv $f $f.pem; done
    cp $(ls sso-* | sort -r | head -n 1) sso-ca.crt

    注意

    可信 CA 证书通常从可信源获取,而不使用 openssl 命令。

  2. 将证书部署到 OpenShift 作为机密。

    oc create secret generic oauth-server-cert --from-file=/tmp/sso-ca.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 -
14.5.4.3. 为 CLI Kafka 客户端会话准备 TLS 连接

为交互式 CLI 会话创建一个新 pod。使用 Red Hat Single Sign-On 证书为 TLS 连接设置信任存储。信任存储是连接到 Red Hat Single Sign-On 和 Kafka 代理。

先决条件

  • Red Hat Single Sign-On 授权服务器部署到 OpenShift 集群,并使用 example 域加载。

    在 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/amq-streams/kafka-35-rhel8:2.5.1 kafka-cli -n $NS -- /bin/sh
    注意

    如果 oc time out 等待镜像下载,后续的尝试可能会导致 AlreadyExists 错误。

  2. 附加到 pod 容器。

    oc attach -ti kafka-cli -n $NS
  3. 使用 Red Hat Single Sign-On 实例的主机名,使用 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.pem

    通常没有单个证书,但一个证书链。您只需要提供最顶层的签发者 CA,该 CA 在 /tmp/sso.pem 文件中最后列出。您可以手动提取,或者使用以下命令:

    在证书链中提取顶级 CA 证书的命令示例

    split -p "-----BEGIN CERTIFICATE-----" sso.pem sso-
    for f in $(ls sso-*); do mv $f $f.pem; done
    cp $(ls sso-* | sort -r | head -n 1) sso-ca.crt

    注意

    可信 CA 证书通常从可信源获取,而不使用 openssl 命令。

  4. 为到 Kafka 代理的 TLS 连接创建一个信任存储。

    keytool -keystore /tmp/truststore.p12 -storetype pkcs12 -alias sso -storepass $STOREPASS -import -file /tmp/sso-ca.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.pem

    获取的 .pem 文件通常不是一个证书,而是一个证书链。您只需要提供最顶层的签发者 CA,该 CA 在 /tmp/my-cluster-kafka.pem 文件中最后列出。您可以手动提取,或者使用以下命令:

    在证书链中提取顶级 CA 证书的命令示例

    split -p "-----BEGIN CERTIFICATE-----" /tmp/my-cluster-kafka.pem kafka-
    for f in $(ls kafka-*); do mv $f $f.pem; done
    cp $(ls kafka-* | sort -r | head -n 1) my-cluster-kafka-ca.crt

    注意

    可信 CA 证书通常从可信源获取,而不使用 openssl 命令。在本例中,我们假定客户端在部署了 Kafka 集群的同一命名空间中的 pod 中运行。如果客户端从 OpenShift 集群外部访问 Kafka 集群,您必须首先确定 bootstrap 地址。在这种情况下,您还可以直接从 OpenShift secret 获取集群证书,且不需要 openssl。如需更多信息,请参阅 第 13 章 设置 Kafka 集群的客户端访问权限

  6. 将 Kafka 代理的证书添加到信任存储中。

    keytool -keystore /tmp/truststore.p12 -storetype pkcs12 -alias my-cluster-kafka -storepass $STOREPASS -import -file /tmp/my-cluster-kafka-ca.crt -noprompt

    使会话保持打开,以检查授权访问。

14.5.4.4. 使用 CLI Kafka 客户端会话检查对 Kafka 的授权访问

使用交互式 CLI 会话,检查通过 Red Hat Single Sign-On 域应用的授权规则。使用 Kafka 示例制作者和消费者客户端应用检查,以使用具有不同访问权限的用户和服务帐户创建主题。

使用 team-a-clientteam-b-client 客户端检查授权规则。使用 alice admin 用户在 Kafka 上执行额外的管理任务。

本例中使用的 AMQ Streams Kafka 镜像包含 Kafka producer 和消费者二进制文件。

先决条件

设置客户端和管理员用户配置

  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,这意味着客户端第一次连接到 Red Hat Single Sign-On 服务器以获取访问令牌。然后,客户端连接到 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。由于它是公共客户端,因此不需要 secret。客户端使用上一步中身份验证的刷新令牌进行身份验证。刷新令牌请求 scenes 后面的访问令牌,然后发送到 Kafka 代理进行身份验证。

生成具有授权访问权限的消息

使用 team-a-client 配置检查您可以生成消息到以 a_x_ 开头的主题。

  1. 写入主题 my-topic

    bin/kafka-console-producer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic my-topic \
      --producer.config=/tmp/team-a-client.properties
    First message

    此请求返回一个 Not authorized to access topics: [my-topic] 错误。

    team-a-client 有一个 Dev Team A 角色,该角色授予对以 a_ 开头的主题执行任何受支持的操作的权限,但只能写入以 x_ 开头的主题。名为 my-topic 的主题都匹配这些规则。

  2. 写入主题 a_messages

    bin/kafka-console-producer.sh --bootstrap-server 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 Team 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 消费者组。

    获取集群配置的详情。

    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 --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic a_messages \
      --producer.config /tmp/team-b-client.properties
    Message 1

    此请求返回一个 Not authorized to access topics: [a_messages] 错误。

  2. 写入主题 b_messages

    bin/kafka-console-producer.sh --bootstrap-server 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 --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --producer.config /tmp/team-b-client.properties
    Message 1

    无法访问主题的 Not authorized to access: [x_messages] 错误,team-b-client 只能从主题 x_messages 中读取。

  4. 使用 team-a-client 写入主题 x_messages

    bin/kafka-console-producer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --producer.config /tmp/team-a-client.properties
    Message 1

    此请求返回一个 Not authorized to access topics: [x_messages] 错误。team-a-client 可以写入 x_messages 主题,但如果尚不存在,则没有创建主题的权限。在 team-a-client 可以写入 x_messages 主题之前,管理员用户 必须使用正确配置(如分区和副本数)创建它。

使用授权管理员用户管理 Kafka

使用 admin 用户 alice 管理 Kafka。alice 具有管理任何 Kafka 集群上的所有内容的完整访问权限。

  1. alice 身份创建 x_messages 主题。

    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

    管理员用户 alice 可以列出所有主题,而 team-a-clientteam-b-client 只能列出他们有权访问的主题。

    Dev 团队 ADev 团队 B 角色对以 x_ 开头的主题具有 Describe 权限,但它们无法看到其他团队的主题,因为它们对它们没有 描述 权限。

  3. 使用 team-a-clientx_messages 主题生成信息:

    bin/kafka-console-producer.sh --bootstrap-server 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-clientx_messages 主题生成消息。

    bin/kafka-console-producer.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 --topic x_messages \
      --producer.config /tmp/team-b-client.properties
    Message 4
    Message 5

    此请求返回一个 Not authorized to access topics: [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

    此请求返回一个 Not authorized to access topics: [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

    此请求返回一个 Not authorized to access topics: [x_messages] 错误。

    Dev Team A 没有以 x_ 开始的主题的 Read 访问权限。

  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

    本例中的集群配置为空。

第 15 章 管理 TLS 证书

AMQ Streams 支持 TLS 用于 Kafka 和 AMQ Streams 组件间的加密通信。

AMQ Streams 建立加密的 TLS 连接,用于以下组件之间的通信:

  • Kafka 代理和 ZooKeeper 节点
  • Kafka 代理(interbroker 通信)
  • ZooKeeper 节点(中间通信)
  • AMQ Streams operator 和 Kafka 和 ZooKeeper
  • Cruise Control 和 Kafka
  • Kafka Exporter 和 Kafka

客户端和代理之间的连接使用监听程序,您必须将它们配置为使用 TLS 加密通信。您可以在 Kafka 自定义资源中配置这些监听程序,每个监听程序名称和端口号必须在集群中唯一。Kafka 代理和 Kafka 客户端之间的通信会根据为监听程序配置 tls 属性的方式进行加密。如需更多信息,请参阅 第 13 章 设置 Kafka 集群的客户端访问权限

下图显示了安全通信的连接。

图 15.1. Kafka 和 ZooKeeper 通信由 TLS 加密保护

安全通信

图中显示的端口如下:

control plane 侦听器(9090)
Kafka 控制器和代理之间的连接在端口 9090 上使用内部 control plane 监听程序,促进代理间通信。Kafka 客户端无法访问此监听程序。
复制监听程序(9091)
代理之间的数据复制以及 AMQ Streams operator、Cruise Control 和 Kafka Exporter 的内部连接,使用端口 9091 上的复制监听程序。Kafka 客户端无法访问此监听程序。
客户端连接(9092 或更高版本)的监听程序
对于 TLS 加密的通信(通过配置监听程序),内部和外部客户端连接到 Kafka 代理。外部客户端(producers 和 consumers)通过公告的监听程序端口连接到 Kafka 代理。
zookeeper 端口(2181)
用于连接 Kafka 的 ZooKeeper 端口。
ZooKeeper 间的通信端口(2888)
ZooKeeper 端口,用于在 ZooKeeper 节点之间进行干预。
ZooKeeper 领导选举端口(3888)
ZooKeeper 端口,用于 ZooKeeper 集群中的节点间的领导选举机制。
重要

当为客户端配置监听程序对代理的访问时,您可以使用端口 9092 或更高版本(9093、9094 等),但有一些例外。侦听程序无法配置为使用为 interbroker 通信(9090 和 9091)、Prometheus 指标(9404)和 JMX (Java 管理扩展)监控(9999)保留的端口。

15.1. 内部集群 CA 和客户端 CA

要支持加密,每个 AMQ Streams 组件需要自己的私钥和公钥证书。所有组件证书都由名为 集群 CA 的内部 CA (证书颁发机构)签名。

CA (证书授权机构)证书由 Cluster Operator 生成,以验证组件和客户端的身份。

同样,使用 mTLS 连接到 AMQ Streams 的每个 Kafka 客户端应用程序都需要使用私钥和证书。第二个内部 CA (名为 客户端 CA )用于为 Kafka 客户端签名证书。

集群 CA 和客户端 CA 均有自签名公钥证书。

Kafka 代理配置为信任由集群 CA 或客户端 CA 签名的证书。客户端不需要连接到的组件,如 ZooKeeper,只信任由集群 CA 签名的证书。除非禁用外部监听程序的 TLS 加密,否则客户端应用程序必须信任由集群 CA 签名的证书。对于执行 mTLS 身份验证的客户端应用程序也是如此。

默认情况下,AMQ Streams 会自动生成和更新集群 CA 或客户端 CA 发布的 CA 证书。您可以使用 Kafka.spec.clusterCaKafka.spec.clientsCa 属性来配置这些 CA 证书的管理。

注意

如果您不想使用 Cluster Operator 生成的 CA,您可以安装自己的集群和客户端 CA 证书。您提供的任何证书都不会由 Cluster Operator 更新。

15.2. Operator 生成的 secret

Cluster Operator 会自动设置和更新 TLS 证书,以便在集群中启用加密和身份验证。如果要在 Kafka 代理和客户端之间启用加密或 mTLS 身份验证,它还设置其他 TLS 证书。

在部署自定义资源时会创建 secret,如 KafkaKafkaUser。AMQ Streams 使用这些 secret 为 Kafka 集群、客户端和用户存储私钥和公钥证书。secret 用于在 Kafka 代理和代理和客户端之间建立 TLS 加密连接。它们也用于 mTLS 身份验证。

集群和客户端 secret 始终是对的:一个包含公钥,另一个包含私钥。

集群 secret
集群 secret 包含用于为 Kafka 代理证书签名的 集群 CA。连接客户端使用证书与 Kafka 集群建立 TLS 加密连接。证书验证代理身份。
客户端 secret
客户端 secret 包含用户为自己的客户端 证书签名的客户端 CA。这允许对 Kafka 集群进行 mutual 身份验证。代理通过证书验证客户端的身份。
用户 secret
用户 secret 包含私钥和证书。创建新用户时,secret 由客户端 CA 创建并签名。密钥和证书用于在访问集群时验证和授权用户。
注意

您可以为 TLS 侦听程序或启用了 TLS 加密的外部监听程序提供 Kafka 侦听器证书。使用 Kafka 侦听器证书合并您已就位的安全基础架构。

15.2.1. 使用 PEM 或 PKCS #12 格式的密钥和证书进行 TLS 身份验证

由 AMQ Streams 创建的 secret 以 PEM (Privacy Enhanced 邮件) 和 PKCS #12 (Public-Key Cryptography Standards) 格式提供私钥和证书。PEM 和 PKCS #12 是用于使用 SSL 协议的 TLS 通信的 OpenSSL 生成的密钥格式。

您可以配置 mutual TLS (mTLS)身份验证,它使用为 Kafka 集群和用户生成的 secret 中包含的凭证。

要设置 mTLS,您必须首先执行以下操作:

部署 Kafka 集群时,会使用公钥创建一个 <cluster_name>-cluster-ca-cert secret 来验证集群。您可以使用公钥为客户端配置信任存储。

当您创建 KafkaUser 时,会使用 密钥和证书创建一个 <kafka_user_name > secret 来验证用户(客户端)。使用这些凭证为客户端配置密钥存储。

当 Kafka 集群和客户端设置为使用 mTLS 时,您可以从 secret 中提取凭证并将其添加到客户端配置中。

PEM 密钥和证书

对于 PEM,您可以在客户端配置中添加以下内容:

truststore
  • CA .crt 来自 & lt;cluster_name>-cluster-ca-cert secret,这是集群的 CA 证书。
keystore
  • 来自 < kafka_user_name&gt; secret 的 user.crt,这是用户的公共证书。
  • 来自 < kafka_user_name&gt; secret 的 user.key,这是用户的私钥。
PKCS #12 密钥和证书

对于 PKCS #12,您可以在客户端配置中添加以下内容:

truststore
  • 来自 < cluster_name>-cluster-ca-cert secret 的 CA .p12,这是集群的 CA 证书。
  • CA .password 来自 & lt;cluster_name>-cluster-ca-cert secret,这是用于访问公共集群 CA 证书的密码。
keystore
  • 来自 < kafka_user_name > secret 的 user.p12,这是用户的公钥证书。
  • 来自 < kafka_user_name&gt; secret 的 user.password,这是用于访问 Kafka 用户的公钥证书的密码。

Java 支持 PKCS #12,以便您可以将证书的值直接添加到 Java 客户端配置中。您还可以从安全存储位置引用证书。使用 PEM 文件,您必须直接将证书添加到客户端配置中,格式为单行格式。选择适合在 Kafka 集群和客户端之间建立 TLS 连接的格式。如果您对 PEM 不熟悉,可以使用 PKCS #12。

注意

所有密钥的大小为 2048 位,默认情况下,从初始生成起的 365 天内有效。您可以更改有效期

15.2.2. Cluster Operator 生成的 secret

Cluster Operator 会生成以下证书,这些证书保存为 OpenShift 集群中的 secret。AMQ Streams 默认使用这些 secret。

集群 CA 和客户端 CA 为私钥和公钥有单独的 secret。

<cluster_name>-cluster-ca
包含集群 CA 的私钥。AMQ Streams 和 Kafka 组件使用私钥为服务器证书签名。
<cluster_name>-cluster-ca-cert
包含集群 CA 的公钥。Kafka 客户端使用公钥验证它们通过 TLS 服务器身份验证连接的 Kafka 代理的身份。
<cluster_name>-clients-ca
包含客户端 CA 的私钥。Kafka 客户端在连接到 Kafka 代理时,使用私钥为 mTLS 身份验证签名新的用户证书。
<cluster_name>-clients-ca-cert
包含客户端 CA 的公钥。在使用 mTLS 身份验证时,Kafka 代理使用公钥来验证客户端访问 Kafka 代理的客户端的身份。

用于 AMQ Streams 组件间通信的 secret 包含由集群 CA 签名的私钥和公钥证书。

<cluster_name>-kafka-brokers
包含 Kafka 代理的私钥和公钥。
<cluster_name>-zookeeper-nodes
包含 ZooKeeper 节点的私钥和公钥。
<cluster_name>-cluster-operator-certs
包含用于加密 Cluster Operator 和 Kafka 或 ZooKeeper 之间的通信的私钥和公钥。
<cluster_name>-entity-topic-operator-certs
包含用于加密主题 Operator 和 Kafka 或 ZooKeeper 之间的通信的私钥和公钥。
<cluster_name>-entity-user-operator-certs
包含用于加密 User Operator 和 Kafka 或 ZooKeeper 之间的通信的私钥和公钥。
<cluster_name>-cruise-control-certs
包含用于加密 Cruise Control 和 Kafka 或 ZooKeeper 之间的通信的私钥和公钥。
<cluster_name>-kafka-exporter-certs
包含用于加密 Kafka Exporter 和 Kafka 或 ZooKeeper 之间的通信的私钥和公钥。
注意

您可以提供自己的服务器证书和私钥,以使用 Kafka 侦听器证书 而不是集群 CA 签名的证书连接到 Kafka 代理。

15.2.3. 集群 CA secret

集群 CA secret 由 Kafka 集群中的 Cluster Operator 管理。

客户端只需要 <cluster_name> -cluster-ca-cert secret。所有其他集群 secret 都可通过 AMQ Streams 组件访问。如果需要,您可以使用 OpenShift 基于角色的访问控制来执行此操作。

注意

< cluster_name&gt; -cluster-ca-cert 中的 CA 证书必须被 Kafka 客户端应用程序信任,以便在通过 TLS 连接到 Kafka 代理时验证 Kafka 代理证书。

表 15.1. < cluster_name>-cluster-ca secret 中的字段
字段Description

ca.key

集群 CA 的当前私钥。

表 15.2. < cluster_name>-cluster-ca-cert secret 中的字段
字段Description

ca.p12

用于存储证书和密钥的 PKCS #12 存储。

ca.password

用于保护 PKCS #12 存储的密码。

ca.crt

集群 CA 的当前证书。

表 15.3. < cluster_name>-kafka-brokers secret 中的字段
字段Description

<cluster_name>-kafka-<num>.p12

用于存储证书和密钥的 PKCS #12 存储。

<cluster_name>-kafka-<num>.password

用于保护 PKCS #12 存储的密码。

<cluster_name>-kafka-<num>.crt

Kafka 代理 pod < num> 的证书。由 <cluster _name> -cluster-ca 中的当前或以前的集群 CA 私钥签名。

<cluster_name>-kafka-<num>.key

Kafka 代理 pod < num> 的私钥

表 15.4. < cluster_name>-zookeeper-nodes secret 中的字段
字段Description

<cluster_name>-zookeeper-<num>.p12

用于存储证书和密钥的 PKCS #12 存储。

<cluster_name>-zookeeper-<num>.password

用于保护 PKCS #12 存储的密码。

<cluster_name>-zookeeper-<num>.crt

ZooKeeper 节点 <num> 的证书。由 <cluster _name> -cluster-ca 中的当前或以前的集群 CA 私钥签名。

<cluster_name>-zookeeper-<num>.key

ZooKeeper pod < num> 的私钥

表 15.5. < cluster_name>-cluster-operator-certs secret 中的字段
字段Description

cluster-operator.p12

用于存储证书和密钥的 PKCS #12 存储。

cluster-operator.password

用于保护 PKCS #12 存储的密码。

cluster-operator.crt

Cluster Operator 和 Kafka 或 ZooKeeper 之间 mTLS 通信的证书。由 <cluster _name> -cluster-ca 中的当前或以前的集群 CA 私钥签名。

cluster-operator.key

Cluster Operator 和 Kafka 或 ZooKeeper 之间 mTLS 通信的私钥。

表 15.6. < cluster_name>-entity-topic-operator-certs secret 中的字段
字段Description

entity-operator.p12

用于存储证书和密钥的 PKCS #12 存储。

entity-operator.password

用于保护 PKCS #12 存储的密码。

entity-operator.crt

主题 Operator 和 Kafka 或 ZooKeeper 之间 mTLS 通信的证书。由 <cluster _name> -cluster-ca 中的当前或以前的集群 CA 私钥签名。

entity-operator.key

主题 Operator 和 Kafka 或 ZooKeeper 之间 mTLS 通信的私钥。

表 15.7. < cluster_name>-entity-user-operator-certs secret 中的字段
字段Description

entity-operator.p12

用于存储证书和密钥的 PKCS #12 存储。

entity-operator.password

用于保护 PKCS #12 存储的密码。

entity-operator.crt

用于 User Operator 和 Kafka 或 ZooKeeper 之间的 mTLS 通信的证书。由 <cluster _name> -cluster-ca 中的当前或以前的集群 CA 私钥签名。

entity-operator.key

User Operator 和 Kafka 或 ZooKeeper 间的 mTLS 通信的私钥。

表 15.8. < cluster_name>-cruise-control-certs secret 中的字段
字段Description

cruise-control.p12

用于存储证书和密钥的 PKCS #12 存储。

cruise-control.password

用于保护 PKCS #12 存储的密码。

cruise-control.crt

用于 Cruise Control 和 Kafka 或 ZooKeeper 之间的 mTLS 通信的证书。由 <cluster _name> -cluster-ca 中的当前或以前的集群 CA 私钥签名。

cruise-control.key

Cruise Control 和 Kafka 或 ZooKeeper 间的 mTLS 通信的私钥。

表 15.9. < cluster_name>-kafka-exporter-certs secret 中的字段
字段Description

kafka-exporter.p12

用于存储证书和密钥的 PKCS #12 存储。

kafka-exporter.password

用于保护 PKCS #12 存储的密码。

kafka-exporter.crt

用于 Kafka Exporter 和 Kafka 或 ZooKeeper 之间的 mTLS 通信的证书。由 <cluster _name> -cluster-ca 中的当前或以前的集群 CA 私钥签名。

kafka-exporter.key

Kafka Exporter 和 Kafka 或 ZooKeeper 间的 mTLS 通信的私钥。

15.2.4. 客户端 CA secret

客户端 CA secret 由 Kafka 集群中的 Cluster Operator 管理。

<cluster_name>-clients-ca-cert 中的正式是 Kafka 代理信任的证书。

& lt;cluster_name> -clients-ca secret 用于为客户端应用程序的证书签名。如果您打算在没有使用 User Operator 的情况下发布应用程序证书,则 AMQ Streams 组件和管理访问此 secret 必须可以被 AMQ Streams 组件访问。如果需要,您可以使用 OpenShift 基于角色的访问控制来执行此操作。

表 15.10. < cluster_name>-clients-ca secret 中的字段
字段Description

ca.key

客户端 CA 的当前私钥。

表 15.11. < cluster_name>-clients-ca-cert secret 中的字段
字段Description

ca.p12

用于存储证书和密钥的 PKCS #12 存储。

ca.password

用于保护 PKCS #12 存储的密码。

ca.crt

客户端 CA 的当前证书。

15.2.5. User Operator 生成的用户 secret

用户 secret 由 User Operator 管理。

当使用 User Operator 创建用户时,会使用用户名生成一个 secret。

表 15.12. user_name secret 中的字段
Secret 名称secret 中的字段Description

<user_name>

user.p12

用于存储证书和密钥的 PKCS #12 存储。

user.password

用于保护 PKCS #12 存储的密码。

user.crt

用户的证书,由客户端 CA 签名

user.key

用户的私钥

15.2.6. 在集群 CA secret 中添加标签和注解

通过在 Kafka 自定义资源中配置 clusterCaCert 模板属性,您可以将自定义标签和注解添加到 Cluster Operator 创建的 Cluster CA secret 中。标签和注解可用于识别对象并添加上下文信息。您可以在 AMQ Streams 自定义资源中配置模板属性。

为 secret 添加标签和注解的模板自定义示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
    template:
      clusterCaCert:
        metadata:
          labels:
            label1: value1
            label2: value2
          annotations:
            annotation1: value1
            annotation2: value2
    # ...

15.2.7. 在 CA secret 中禁用 ownerReference

默认情况下,集群和客户端 CA secret 使用设置为 Kafka 自定义资源的 ownerReference 属性创建。这意味着,当 Kafka 自定义资源被删除时,OpenShift 也会删除 CA secret (收集垃圾收集)。

如果要为新集群重复使用 CA,您可以通过在 Kafka 配置中将集群和客户端 CA secret 的 generateSecretOwnerReference 属性设置为 false 来禁用 ownerReference。当禁用 ownerReference 时,当删除对应的 Kafka 自定义资源时,OpenShift 不会删除 CA secret。

集群和客户端 CA 禁用 ownerReference 的 Kafka 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
# ...
spec:
# ...
  clusterCa:
    generateSecretOwnerReference: false
  clientsCa:
    generateSecretOwnerReference: false
# ...

15.3. 证书续订和有效期

集群 CA 和客户端 CA 证书只在有限的时间段内有效,称为有效期。这通常定义自生成证书以来的天数。

对于 Cluster Operator 自动创建的 CA 证书,您可以配置以下的有效性周期:

  • Kafka.spec.clusterCa.validityDays中的集群 CA 证书
  • Clients CA certificates in Kafka.spec.clientsCa.validityDays

两个证书的默认有效期为 365 天。手动安装的 CA 证书应定义自己的有效期。

当 CA 证书过期时,仍信任该证书的组件和客户端不接受来自其证书由 CA 私钥签名的对等点的连接。组件和客户端需要信任新的 CA 证书。

要允许在不丢失服务的情况下续订 CA 证书,Cluster Operator 会在旧的 CA 证书过期前启动证书续订。

您可以配置 Cluster Operator 创建的证书的续订周期:

  • Kafka.spec.clusterCa.renewalDays中的集群 CA 证书
  • Clients CA certificates in Kafka.spec.clientsCa.renewalDays

两个证书的默认续订周期为 30 天。

续订周期从当前证书的到期日期后测量。

根据续订周期的有效期

Not Before                                     Not After
    |                                              |
    |<--------------- validityDays --------------->|
                              <--- renewalDays --->|

要在创建 Kafka 集群后更改有效期和续订周期,您可以配置并应用 Kafka 自定义资源,并 手动更新 CA 证书。如果您不手动更新证书,则在下次自动更新证书时将使用新的周期。

证书有效期和续订周期的 Kafka 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
# ...
spec:
# ...
  clusterCa:
    renewalDays: 30
    validityDays: 365
    generateCertificateAuthority: true
  clientsCa:
    renewalDays: 30
    validityDays: 365
    generateCertificateAuthority: true
# ...

在续订期间,Cluster Operator 的行为取决于集群 CA 和客户端 CA 的 generateCertificateAuthority 证书生成属性的设置。

true
如果属性设为 true,Cluster Operator 会自动生成 CA 证书,并在续订周期内自动更新。
false
如果属性设为 false,Cluster Operator 不会生成 CA 证书。如果要安装自己的证书,则使用此选项。

15.3.1. 使用自动生成的 CA 证书的续订过程

Cluster Operator 在续订 CA 证书时按照以下顺序执行以下进程:

  1. 生成一个新的 CA 证书,但保留现有的密钥。

    新证书将旧证书替换为对应 Secret 中的名称 ca.crt

  2. 生成新的客户端证书(用于 ZooKeeper 节点、Kafka 代理和实体 Operator)。

    这并不严格是必需的,因为签名密钥没有改变,但它保留客户端证书的有效性周期与 CA 证书同步。

  3. 重启 ZooKeeper 节点,以便它们信任新的 CA 证书并使用新的客户端证书。
  4. 重启 Kafka 代理,以便它们信任新的 CA 证书并使用新的客户端证书。
  5. 重启主题和用户 Operator,以便它们信任新的 CA 证书并使用新的客户端证书。

    用户证书由客户端 CA 签名。用户 Operator 生成的用户证书会在客户端 CA 续订时续订。

15.3.2. 客户端证书续订

Cluster Operator 不知道使用 Kafka 集群的客户端应用程序。

当连接到集群时,并确保它们正确运行,客户端应用程序必须:

  • 信任 <cluster> - cluster-ca-cert Secret 中发布的集群 CA 证书。
  • 使用 < user-name&gt; Secret 中发布的凭证连接到集群。

    User Secret 以 PEM 和 PKCS #12 格式提供凭证,或者在使用 SCRAM-SHA 身份验证时提供密码。User Operator 在创建用户时会创建用户凭证。

您必须确保客户端在证书续订后继续工作。续订过程取决于客户端的配置方式。

如果要手动置备客户端证书和密钥,您必须生成新的客户端证书,并确保客户端在续订周期内使用新证书。在续订周期结束时无法执行此操作可能会导致客户端应用程序无法连接到集群。

注意

对于在同一 OpenShift 集群和命名空间中运行的工作负载,Secret 可以挂载为卷,因此客户端 Pod 可以从 Secret 的当前状态构建其密钥存储和信任存储。有关此过程的详情,请参阅配置内部客户端以信任集群 CA

15.3.3. 手动续订 Cluster Operator 管理的 CA 证书

Cluster Operator 会自动续订其相应证书续订周期开始时,集群和客户端 CA 证书会自动续订。但是,您可以使用 strimzi.io/force-renew 注解在证书续订周期开始前手动续订其中一个或两个证书。出于安全原因,您可能执行此操作,或者更改了证书的续订或有效期

更新的证书使用与旧证书相同的私钥。

注意

如果您使用自己的 CA 证书,则无法使用 force-renew 注解。相反,请按照流程 续订您自己的 CA 证书

先决条件

在此过程中,我们在 my-project 命名空间中使用名为 my-cluster 的 Kafka 集群。

流程

  1. strimzi.io/force-renew 注解应用到包含您要续订的 CA 证书的 secret。

    续订集群 CA secret

    oc annotate secret my-cluster-cluster-ca-cert -n my-project strimzi.io/force-renew=true

    续订客户端 CA secret

    oc annotate secret my-cluster-clients-ca-cert -n my-project strimzi.io/force-renew=true

  2. 在下一个协调时,Cluster Operator 会生成新证书。

    如果配置了维护时间窗,Cluster Operator 会在下一次维护时间窗内第一次协调时生成新的 CA 证书。

  3. 检查新 CA 证书的有效性周期。

    检查新集群 CA 证书的有效性周期

    oc get secret my-cluster-cluster-ca-cert -n my-project -o=jsonpath='{.data.ca\.crt}' | base64 -d | openssl x509 -noout -dates

    检查新客户端 CA 证书的有效性周期

    oc get secret my-cluster-clients-ca-cert -n my-project -o=jsonpath='{.data.ca\.crt}' | base64 -d | openssl x509 -noout -dates

    该命令返回一个 notBeforenotAfter date,这是 CA 证书的有效开始和结束日期。

  4. 更新客户端配置以信任新的集群 CA 证书。

    请参阅:

15.3.4. 手动从已过期的 Cluster Operator 管理的 CA 证书中恢复

Cluster Operator 会在续订周期开始时自动更新集群和客户端 CA 证书。然而,意外的操作问题或中断可能会阻止续订过程,如 Cluster Operator 的停机时间或 Kafka 集群不可用。如果 CA 证书过期,Kafka 集群组件无法相互通信,Cluster Operator 在无需人工干预的情况下无法续订 CA 证书。

要立即执行恢复,请按照给出的顺序操作此流程中所述的步骤。您可以从过期的集群和客户端 CA 证书中恢复。此过程涉及删除包含过期证书的 secret,以便 Cluster Operator 生成新证书的 secret。有关 AMQ Streams 中管理的 secret 的更多信息,请参阅 第 15.2.2 节 “Cluster Operator 生成的 secret”

注意

如果您使用自己的 CA 证书并使其过期,则该过程类似,但您需要 续订 CA 证书,而不是使用 Cluster Operator 生成的证书。

先决条件

在此过程中,我们在 my-project 命名空间中使用名为 my-cluster 的 Kafka 集群。

流程

  1. 删除包含过期 CA 证书的 secret。

    删除 Cluster CA secret

    oc delete secret my-cluster-cluster-ca-cert -n my-project

    删除 Clients CA secret

    oc delete secret my-cluster-clients-ca-cert -n my-project

  2. 等待 Cluster Operator 生成新证书。

    • 新的 CA 集群证书以验证 Kafka 代理的身份在相同名称的 secret 中创建了(my-cluster-cluster-ca-cert)。
    • 在相同名称的 secret 中创建了用于验证 Kafka 用户身份的新 CA 客户端证书(my-cluster-clients-ca-cert)。
  3. 检查新 CA 证书的有效性周期。

    检查新集群 CA 证书的有效性周期

    oc get secret my-cluster-cluster-ca-cert -n my-project -o=jsonpath='{.data.ca\.crt}' | base64 -d | openssl x509 -noout -dates

    检查新客户端 CA 证书的有效性周期

    oc get secret my-cluster-clients-ca-cert -n my-project -o=jsonpath='{.data.ca\.crt}' | base64 -d | openssl x509 -noout -dates

    该命令返回一个 notBeforenotAfter date,这是 CA 证书的有效开始和结束日期。

  4. 删除使用 CA 证书的组件 pod 和 secret。

    1. 删除 ZooKeeper secret。
    2. 等待 Cluster Operator 检测缺少的 ZooKeeper secret 并重新创建它。
    3. 删除所有 ZooKeeper pod。
    4. 删除 Kafka secret。
    5. 等待 Cluster Operator 检测缺少的 Kafka secret 并重新创建它。
    6. 删除所有 Kafka pod。

    如果您只恢复客户端 CA 证书,则只需要删除 Kafka secret 和 pod。

    您可以使用以下 oc 命令查找资源,并验证它是否已被删除。

    oc get <resource_type> --all-namespaces | grep <kafka_cluster_name>

    <resource_type > 替换为资源的类型,如 PodSecret

  5. 等待 Cluster Operator 检测缺少的 Kafka 和 ZooKeeper pod,并使用更新的 CA 证书重新创建它们。

    在协调时,Cluster Operator 会自动更新其他组件以信任新的 CA 证书。

  6. 验证 Cluster Operator 日志中没有与证书验证相关的问题。
  7. 更新客户端配置以信任新的集群 CA 证书。

    请参阅:

15.3.5. 替换 Cluster Operator 管理的 CA 证书使用的私钥

您可以替换由 Cluster Operator 生成的集群 CA 和客户端 CA 证书使用的私钥。当替换私钥时,Cluster Operator 会为新私钥生成一个新的 CA 证书。

注意

如果您使用自己的 CA 证书,则无法使用 force-replace 注解。相反,请按照流程 续订您自己的 CA 证书

先决条件

  • Cluster Operator 正在运行。
  • 安装 CA 证书和私钥的 Kafka 集群。

流程

  • strimzi.io/force-replace 注解应用到包含您要更新的私钥的 Secret

    表 15.13. 替换私钥的命令
    的私钥Secret注解命令

    集群 CA

    cluster-name-cluster-ca

    oc annotate secret CLUSTER-NAME-cluster-ca strimzi.io/force-replace=true

    客户端 CA

    cluster-name-clients-ca

    oc annotate secret CLUSTER-NAME-clients-ca strimzi.io/force-replace=true

在下一次协调时,Cluster Operator 将:

  • 为您注解的 Secret 生成新私钥
  • 生成新的 CA 证书

如果配置了维护时间窗,Cluster Operator 将在下次维护时间窗口中第一次协调时生成新的私钥和 CA 证书。

客户端应用程序必须重新加载 Cluster Operator 更新的集群和客户端 CA 证书。

15.4. 配置内部客户端以信任集群 CA

此流程描述了如何配置位于 OpenShift 集群中的 Kafka 客户端 - 连接到 TLS 侦听器 - 以信任集群 CA 证书。

为内部客户端实现此操作的最简单方法是使用卷挂载来访问 包含所需 证书和密钥的 Secret。

按照以下步骤配置由基于 Java 的 Kafka Producer、Consumer 和 Streams API 的集群 CA 签名的信任证书。

根据集群 CA 的证书格式,选择遵循的步骤:PKCS #12 (.p12) 或 PEM (.crt)。

这些步骤描述了如何挂载 Cluster Secret,该 Secret 验证 Kafka 集群的身份到客户端 pod。

先决条件

  • Cluster Operator 必须正在运行。
  • OpenShift 集群中需要有一个 Kafka 资源。
  • 您需要使用 TLS 连接的 OpenShift 集群内的 Kafka 客户端应用程序,并需要信任集群 CA 证书。
  • 客户端应用程序必须与 Kafka 资源在同一命名空间中运行。

使用 PKCS #12 格式 (.p12)

  1. 在定义客户端 pod 时,将集群 Secret 挂载为卷。

    例如:

    kind: Pod
    apiVersion: v1
    metadata:
      name: client-pod
    spec:
      containers:
      - name: client-name
        image: client-name
        volumeMounts:
        - name: secret-volume
          mountPath: /data/p12
        env:
        - name: SECRET_PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-secret
              key: my-password
      volumes:
      - name: secret-volume
        secret:
          secretName: my-cluster-cluster-ca-cert

    在这里挂载以下内容:

    • PKCS #12 会进入一个准确的路径中,这可以进行配置
    • 密码到环境变量中,可用于 Java 配置
  2. 使用以下属性配置 Kafka 客户端:

    • 安全协议选项:

      • security.protocol:使用 TLS 加密时 SSL (使用 mTLS 身份验证)。
      • security.protocol :在通过 TLS 使用 SCRAM-SHA 身份验证时 SASL_SSL
    • ssl.truststore.location,使用导入证书的 truststore 位置。
    • ssl.truststore.password,使用用于访问信任存储的密码。
    • ssl.truststore.type=PKCS12 来识别信任存储类型。

使用 PEM 格式(.crt)

  1. 在定义客户端 pod 时,将集群 Secret 挂载为卷。

    例如:

    kind: Pod
    apiVersion: v1
    metadata:
      name: client-pod
    spec:
      containers:
      - name: client-name
        image: client-name
        volumeMounts:
        - name: secret-volume
          mountPath: /data/crt
      volumes:
      - name: secret-volume
        secret:
          secretName: my-cluster-cluster-ca-cert
  2. 使用提取的证书在使用 X.509 格式的证书的客户端中配置 TLS 连接。

15.5. 配置外部客户端以信任集群 CA

此流程描述了如何配置位于 OpenShift 集群外的 Kafka 客户端 - 连接到 外部监听程序 - 以信任集群 CA 证书。当替换旧客户端 CA 证书时,请按照设置客户端和续订周期时按照以下步骤操作。

按照以下步骤配置由基于 Java 的 Kafka Producer、Consumer 和 Streams API 的集群 CA 签名的信任证书。

根据集群 CA 的证书格式,选择遵循的步骤:PKCS #12 (.p12) 或 PEM (.crt)。

这些步骤描述了如何从验证 Kafka 集群身份的集群 Secret 获取证书。

重要

& lt;cluster_name> -cluster-ca-cert secret 在 CA 证书续订期间包含多个 CA 证书。客户端必须将它们全部添加到其信任存储中。

先决条件

  • Cluster Operator 必须正在运行。
  • OpenShift 集群中需要有一个 Kafka 资源。
  • 您需要 OpenShift 集群外的 Kafka 客户端应用程序需要使用 TLS 连接,并需要信任集群 CA 证书。

使用 PKCS #12 格式 (.p12)

  1. 从 Kafka 集群的 < cluster_name> -cluster-ca-cert Secret 中提取集群 CA 证书和密钥。

    oc get secret <cluster_name>-cluster-ca-cert -o jsonpath='{.data.ca\.p12}' | base64 -d > ca.p12
    oc get secret <cluster_name>-cluster-ca-cert -o jsonpath='{.data.ca\.password}' | base64 -d > ca.password

    <cluster_name > 替换为 Kafka 集群的名称。

  2. 使用以下属性配置 Kafka 客户端:

    • 安全协议选项:

      • security.protocol :在使用 TLS 时 SSL
      • security.protocol :在通过 TLS 使用 SCRAM-SHA 身份验证时 SASL_SSL
    • ssl.truststore.location,使用导入证书的 truststore 位置。
    • ssl.truststore.password,使用用于访问信任存储的密码。如果 truststore 不需要此属性,则可以省略此属性。
    • ssl.truststore.type=PKCS12 来识别信任存储类型。

使用 PEM 格式(.crt)

  1. 从 Kafka 集群的 < cluster_name>-cluster-ca-cert secret 中提取集群 CA 证书。

    oc get secret <cluster_name>-cluster-ca-cert -o jsonpath='{.data.ca\.crt}' | base64 -d > ca.crt
  2. 使用提取的证书在使用 X.509 格式的证书的客户端中配置 TLS 连接。

15.6. 使用您自己的 CA 证书和私钥

安装和使用您自己的 CA 证书和私钥,而不使用 Cluster Operator 生成的默认值。您可以替换集群和客户端 CA 证书和私钥。

您可以使用以下方法切换到使用自己的 CA 证书和私钥:

  • 在部署 Kafka 集群前安装自己的 CA 证书和私钥
  • 在部署 Kafka 集群后,将默认 CA 证书和私钥替换为您自己的

在部署 Kafka 集群后替换默认 CA 证书和私钥的步骤与用来更新您自己的 CA 证书和私钥的步骤相同。

如果您使用自己的证书,则不会自动更新它们。您需要在过期前续订 CA 证书和私钥。

续订选项:

  • 仅续订 CA 证书
  • 续订 CA 证书和私钥(或替换默认值)

15.6.1. 安装您自己的 CA 证书和私钥

安装您自己的 CA 证书和私钥,而不使用 Cluster Operator 生成的集群和客户端 CA 证书和私钥。

默认情况下,AMQ Streams 使用以下 集群 CA 和客户端 CA secret,这些 secret 会自动续订。

  • 集群 CA secret

    • <cluster_name>-cluster-ca
    • <cluster_name>-cluster-ca-cert
  • 客户端 CA secret

    • <cluster_name>-clients-ca
    • <cluster_name>-clients-ca-cert

要安装自己的证书,请使用相同的名称。

先决条件

  • Cluster Operator 正在运行。
  • Kafka 集群尚未部署。

    如果您已经部署了 Kafka 集群,您可以将 默认 CA 证书替换为您自己的

  • 集群 CA 或客户端 CA 的 PEM 格式的您自己的 X.509 证书和密钥。

    • 如果要使用不是 Root CA 的集群或客户端 CA,则必须在证书文件中包含整个链。链应该按以下顺序排列:

      1. 集群或客户端 CA
      2. 一个或多个中间 CA
      3. root CA
    • 链中的所有 CA 都应该使用 X509v3 基本约束扩展进行配置。基本限制限制证书链的路径长度。
  • 用于转换证书的 OpenSSL TLS 管理工具。

开始前

Cluster Operator 以 PEM (Privacy Enhanced Mail) 和 PKCS #12 (Public-Key Cryptography Standards) 格式生成密钥和证书。您可以使用任一格式添加自己的证书。

有些应用程序无法使用 PEM 证书,且只支持 PKCS #12 证书。如果您没有 PKCS #12 格式的集群证书,请使用 OpenSSL TLS 管理工具从 ca.crt 文件中生成一个。

证书生成命令示例

openssl pkcs12 -export -in ca.crt -nokeys -out ca.p12 -password pass:<P12_password> -caname ca.crt

<P12_password > 替换为您自己的密码。

流程

  1. 创建一个包含 CA 证书的新 secret。

    仅使用 PEM 格式的证书创建客户端 secret

    oc create secret generic <cluster_name>-clients-ca-cert --from-file=ca.crt=ca.crt

    使用 PEM 和 PKCS #12 格式的证书创建集群 secret

    oc create secret generic <cluster_name>-cluster-ca-cert \
      --from-file=ca.crt=ca.crt \
      --from-file=ca.p12=ca.p12 \
      --from-literal=ca.password=P12-PASSWORD

    <cluster_name > 替换为 Kafka 集群的名称。

  2. 创建一个包含私钥的新 secret。

    oc create secret generic CA-KEY-SECRET --from-file=ca.key=ca.key
  3. 标记 secret。

    oc label secret CA-CERTIFICATE-SECRET strimzi.io/kind=Kafka strimzi.io/cluster=<cluster_name>
    oc label secret CA-KEY-SECRET strimzi.io/kind=Kafka strimzi.io/cluster=<cluster_name>
    • Label strimzi.io/kind=Kafka 标识 Kafka 自定义资源。
    • 标签 strimzi.io/cluster= &lt;cluster_name& gt; 标识 Kafka 集群。
  4. 注解 secret

    oc annotate secret CA-CERTIFICATE-SECRET strimzi.io/ca-cert-generation=CA-CERTIFICATE-GENERATION
    oc annotate secret CA-KEY-SECRET strimzi.io/ca-key-generation=CA-KEY-GENERATION
    • 注解 strimzi.io/ca-cert-generation=CA-CERTIFICATE-GENERATION 定义新 CA 证书的生成。
    • 注解 strimzi.io/ca-key-generation=CA-KEY-GENERATION 定义新 CA 密钥的生成。

      从 0 (零)作为您自己的 CA 证书的增量值(strimzi.io/ca-cert-generation=0)开始。在续订证书时设置更高的增量值。

  5. 为集群创建 Kafka 资源,将 Kafka.spec.clusterCaKafka.spec.clientsCa 对象配置为使用生成的 CA。

    将集群 CA 配置为使用您自己提供的证书片段 Kafka 资源示例

    kind: Kafka
    version: kafka.strimzi.io/v1beta2
    spec:
      # ...
      clusterCa:
        generateCertificateAuthority: false

15.6.2. 续订您自己的 CA 证书

如果您使用自己的 CA 证书,则需要手动续订它们。Cluster Operator 不会自动更新它们。在续订周期到期前续订 CA 证书。

当您续订 CA 证书并使用相同的私钥时,请执行以下步骤中的步骤。如果您要更新自己的 CA 证书和私钥,请参阅 第 15.6.3 节 “自行续订或替换 CA 证书和私钥”

该流程描述了以 PEM 格式续订 CA 证书。

先决条件

  • Cluster Operator 正在运行。
  • 您有 PEM 格式的新集群或客户端 X.509 证书。

流程

  1. 更新 CA 证书的 Secret

    编辑现有 secret 以添加新 CA 证书并更新证书生成注解值。

    oc edit secret <ca_certificate_secret_name>

    <ca_certificate_secret_name > 是 Secret 的名称,即 &lt ;kafka_cluster_name&gt; -cluster-ca-cert 用于集群 CA 证书,& lt;kafka_cluster_name&gt; -clients-ca-cert 用于客户端 CA 证书。

    以下示例显示了与集群 CA 证书的 secret,它与名为 my-cluster 的 Kafka 集群相关联。

    集群 CA 证书的 secret 配置示例

    apiVersion: v1
    kind: Secret
    data:
      ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0F... 1
    metadata:
      annotations:
        strimzi.io/ca-cert-generation: "0" 2
      labels:
        strimzi.io/cluster: my-cluster
        strimzi.io/kind: Kafka
      name: my-cluster-cluster-ca-cert
      #...
    type: Opaque

    1
    当前 base64 编码的 CA 证书
    2
    当前 CA 证书生成注解值
  2. 将新 CA 证书编码为 base64。

    cat <path_to_new_certificate> | base64
  3. 更新 CA 证书。

    复制上一步中的 base64 编码的 CA 证书,作为 data 下的 ca.crt 属性的值。

  4. 增加 CA 证书生成注解的值。

    使用更高的增量值更新 strimzi.io/ca-cert-generation 注解。例如,将 strimzi.io/ca-cert-generation=0 更改为 strimzi.io/ca-cert-generation=1。如果 Secret 缺少注解,则该值被视为 0, 因此添加值为 1 的注解。

    当 AMQ Streams 生成证书时,Cluster Operator 会自动递增证书生成注解。对于您自己的 CA 证书,请使用更高的增量值设置注解。该注解需要的值高于当前 secret 中的值,以便 Cluster Operator 可以滚动 pod 并更新证书。strimzi.io/ca-cert-generation 必须针对每个 CA 证书续订递增。

  5. 使用新的 CA 证书和密钥生成注解值保存 secret。

    使用新 CA 证书更新的 secret 配置示例

    apiVersion: v1
    kind: Secret
    data:
      ca.crt: GCa6LS3RTHeKFiFDGBOUDYFAZ0F... 1
    metadata:
      annotations:
        strimzi.io/ca-cert-generation: "1" 2
      labels:
        strimzi.io/cluster: my-cluster
        strimzi.io/kind: Kafka
      name: my-cluster-cluster-ca-cert
      #...
    type: Opaque

    1
    新的 base64 编码的 CA 证书
    2
    新的 CA 证书生成注解值

在下一个协调中,Cluster Operator 对 ZooKeeper、Kafka 和其他组件执行滚动更新,以信任新的 CA 证书。

如果配置了维护时间窗,Cluster Operator 将在下次维护时间窗内第一次协调 pod。

15.6.3. 自行续订或替换 CA 证书和私钥

如果您使用自己的 CA 证书和私钥,则需要手动续订它们。Cluster Operator 不会自动更新它们。在续订周期到期前续订 CA 证书。您还可以使用相同的步骤将 AMQ Streams Operator 生成的 CA 证书和私钥替换为您自己的。

在续订或替换 CA 证书和私钥时,请执行以下步骤中的步骤。如果您只更新自己的 CA 证书,请参阅 第 15.6.2 节 “续订您自己的 CA 证书”

该流程描述了以 PEM 格式续订 CA 证书和私钥。

在执行以下步骤前,请确保新 CA 证书的 CN (Common Name)与当前 CA 证书不同。例如,当 Cluster Operator 续订证书时自动添加 v<version_number&gt; 后缀来标识版本时。通过在每个续订中添加不同的后缀,对您自己的 CA 证书执行同样的操作。通过使用其他密钥生成新 CA 证书,您可以保留存储在 Secret 中的当前 CA 证书。

先决条件

  • Cluster Operator 正在运行。
  • 您有 PEM 格式的新集群或客户端 X.509 证书和密钥。

流程

  1. 暂停 Kafka 自定义资源的协调。

    1. 在 OpenShift 中注解自定义资源,将 pause-reconciliation 注解设置为 true

      oc annotate Kafka <name_of_custom_resource> strimzi.io/pause-reconciliation="true"

      例如,对于名为 my-clusterKafka 自定义资源:

      oc annotate Kafka my-cluster strimzi.io/pause-reconciliation="true"
    2. 检查自定义资源的状态条件是否显示 ReconciliationPaused 的更改:

      oc describe Kafka <name_of_custom_resource>

      lastTransitionTimetype 条件会变为 ReconciliationPaused

  2. 更新 CA 证书的 Secret

    1. 编辑现有 secret 以添加新 CA 证书并更新证书生成注解值。

      oc edit secret <ca_certificate_secret_name>

      <ca_certificate_secret_name > 是 Secret 的名称,即 KAFKA-CLUSTER-NAME-cluster-ca-cert 用于集群 CA 证书,KAFKA-CLUSTER-NAME-clients-ca-cert 用于客户端 CA 证书。

      以下示例显示了与集群 CA 证书的 secret,它与名为 my-cluster 的 Kafka 集群相关联。

      集群 CA 证书的 secret 配置示例

      apiVersion: v1
      kind: Secret
      data:
        ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0F... 1
      metadata:
        annotations:
          strimzi.io/ca-cert-generation: "0" 2
        labels:
          strimzi.io/cluster: my-cluster
          strimzi.io/kind: Kafka
        name: my-cluster-cluster-ca-cert
        #...
      type: Opaque

      1
      当前 base64 编码的 CA 证书
      2
      当前 CA 证书生成注解值
    2. 重命名当前的 CA 证书以保留它。

      将数据 下的当前 ca.crt 属性重命名为 ca- &lt;date& gt; .crt,其中 & lt;date> 是 YEAR-MONTH-DAYTHOUR-MINUTE-SECONDZ 格式的证书过期日期。例如 ca-2023-01-26T17-32-00Z.crt:保留属性的值,因为它保留当前的 CA 证书。

    3. 将新 CA 证书编码为 base64。

      cat <path_to_new_certificate> | base64
    4. 更新 CA 证书。

      data 下创建一个新的 ca.crt 属性,并将上一步中的 base64 编码的 CA 证书复制为 ca.crt 属性的值。

    5. 增加 CA 证书生成注解的值。

      使用更高的增量值更新 strimzi.io/ca-cert-generation 注解。例如,将 strimzi.io/ca-cert-generation=0 更改为 strimzi.io/ca-cert-generation=1。如果 Secret 缺少注解,则该值被视为 0, 因此添加值为 1 的注解。

      当 AMQ Streams 生成证书时,Cluster Operator 会自动递增证书生成注解。对于您自己的 CA 证书,请使用更高的增量值设置注解。该注解需要的值高于当前 secret 中的值,以便 Cluster Operator 可以滚动 pod 并更新证书。strimzi.io/ca-cert-generation 必须针对每个 CA 证书续订递增。

    6. 使用新的 CA 证书和密钥生成注解值保存 secret。

      使用新 CA 证书更新的 secret 配置示例

      apiVersion: v1
      kind: Secret
      data:
        ca.crt: GCa6LS3RTHeKFiFDGBOUDYFAZ0F... 1
        ca-2023-01-26T17-32-00Z.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0F... 2
      metadata:
        annotations:
          strimzi.io/ca-cert-generation: "1" 3
        labels:
          strimzi.io/cluster: my-cluster
          strimzi.io/kind: Kafka
        name: my-cluster-cluster-ca-cert
        #...
      type: Opaque

      1
      新的 base64 编码的 CA 证书
      2
      旧 base64 编码的 CA 证书
      3
      新的 CA 证书生成注解值
  3. 更新用于为您的新 CA 证书签名的 CA 密钥的 Secret

    1. 编辑现有 secret 以添加新的 CA 密钥并更新密钥生成注解值。

      oc edit secret <ca_key_name>

      <ca_key_name > 是 CA 密钥的名称,即 &lt ;kafka_cluster_name&gt; -cluster-ca 用于集群 CA 密钥,& lt;kafka_cluster_name&gt; -clients-ca 用于客户端 CA 密钥。

      以下示例显示了与集群 CA 密钥的 secret,它与名为 my-cluster 的 Kafka 集群相关联。

      集群 CA 密钥的 secret 配置示例

      apiVersion: v1
      kind: Secret
      data:
        ca.key: SA1cKF1GFDzOIiPOIUQBHDNFGDFS... 1
      metadata:
        annotations:
          strimzi.io/ca-key-generation: "0" 2
        labels:
          strimzi.io/cluster: my-cluster
          strimzi.io/kind: Kafka
        name: my-cluster-cluster-ca
        #...
      type: Opaque

      1
      当前 base64 编码的 CA 密钥
      2
      当前 CA 密钥生成注解值
    2. 将 CA 密钥编码为 base64。

      cat <path_to_new_key> | base64
    3. 更新 CA 密钥。

      复制上一步中的 base64 编码的 CA 密钥,作为 data 下的 ca.key 属性的值。

    4. 增加 CA 密钥生成注解的值。

      使用更高的增量值更新 strimzi.io/ca-key-generation 注解。例如,将 strimzi.io/ca-key-generation=0 更改为 strimzi.io/ca-key-generation=1。如果 Secret 缺少注解,它将被视为 0, 因此添加值为 1 的注解。

      当 AMQ Streams 生成证书时,Cluster Operator 会自动递增密钥生成注解。对于您自己的 CA 证书以及新的 CA 密钥,请使用更高的增量值设置注解。该注解需要的值高于当前 secret 中的值,以便 Cluster Operator 可以滚动 pod 并更新证书和密钥。strimzi.io/ca-key-generation 必须针对每个 CA 证书续订递增。

  4. 使用新的 CA 密钥和密钥生成注解值保存 secret。

    使用新 CA 密钥更新的 secret 配置示例

    apiVersion: v1
    kind: Secret
    data:
      ca.key: AB0cKF1GFDzOIiPOIUQWERZJQ0F... 1
    metadata:
      annotations:
        strimzi.io/ca-key-generation: "1" 2
      labels:
        strimzi.io/cluster: my-cluster
        strimzi.io/kind: Kafka
      name: my-cluster-cluster-ca
      #...
    type: Opaque

    1
    新的 base64 编码的 CA 密钥
    2
    新的 CA 密钥生成注解值
  5. 从暂停中恢复。

    要恢复 Kafka 自定义资源协调,请将 pause-reconciliation 注解设置为 false

    oc annotate --overwrite Kafka <name_of_custom_resource> strimzi.io/pause-reconciliation="false"

    您还可以删除 pause-reconciliation 注解来达到同样的操作。

    oc annotate Kafka <name_of_custom_resource> strimzi.io/pause-reconciliation-

    在下一个协调中,Cluster Operator 对 ZooKeeper、Kafka 和其他组件执行滚动更新,以信任新的 CA 证书。滚动更新完成后,Cluster Operator 将启动一个新的服务器证书来生成由新 CA 密钥签名的新的服务器证书。

    如果配置了维护时间窗,Cluster Operator 将在下次维护时间窗内第一次协调 pod。

  6. 等待滚动更新移至新的 CA 证书。
  7. 从 secret 配置中删除任何过时的证书,以确保集群不再信任它们。

    oc edit secret <ca_certificate_secret_name>

    删除旧证书的 secret 配置示例

    apiVersion: v1
    kind: Secret
    data:
      ca.crt: GCa6LS3RTHeKFiFDGBOUDYFAZ0F...
    metadata:
      annotations:
        strimzi.io/ca-cert-generation: "1"
      labels:
        strimzi.io/cluster: my-cluster
        strimzi.io/kind: Kafka
      name: my-cluster-cluster-ca-cert
      #...
    type: Opaque

  8. 启动集群的手动滚动更新,以获取对 secret 配置所做的更改。

    请参阅 第 27.9 节 “使用注解启动 Kafka 和 ZooKeeper 集群的滚动更新”

第 16 章 将安全上下文应用到 AMQ Streams pod 和容器

安全性上下文约束定义 pod 和容器的限制。通过指定安全上下文,pod 和容器仅具有所需的权限。例如,权限可以控制运行时操作或访问资源。

16.1. 通过 OpenShift 平台处理安全上下文

处理安全上下文取决于您使用的 OpenShift 平台的工具。

例如,OpenShift 使用内置安全性上下文约束(SCC)来控制权限。SCC 是控制 Pod 能够访问的安全功能的设置和策略。

默认情况下,OpenShift 会自动注入安全上下文配置。在大多数情况下,这意味着您不需要为 Cluster Operator 创建的 pod 和容器配置安全上下文。虽然您仍然可以创建和管理自己的 SCC。

如需更多信息,请参阅 OpenShift 文档

第 17 章 通过添加或删除代理来扩展集群

通过添加代理扩展 Kafka 集群可以提高集群的性能和可靠性。添加更多代理会增加可用资源,允许集群处理较大的工作负载并处理更多信息。它还可以通过提供更多副本和备份来提高容错。相反,删除使用率不足的代理可以降低资源消耗并提高效率。必须仔细进行缩放以避免中断或数据丢失。通过在集群中的所有代理间重新分发分区,每个代理的资源利用率会减少,这可以提高集群的整体吞吐量。

注意

要增加 Kafka 主题的吞吐量,您可以增加该主题的分区数量。这允许加载集群中的不同代理之间共享该主题。但是,如果每个代理都受特定资源(如 I/O)的限制,添加更多分区不会增加吞吐量。在这种情况下,您需要在集群中添加更多代理。

调整 Kafka.spec.kafka.replicas 配置会影响作为副本的集群中的代理数量。主题的实际复制因素由 default.replication.factormin.insync.replicas 的设置以及可用代理的数量决定。例如,复制因素 3 表示主题的每个分区在三个代理之间复制,确保在代理失败时进行容错。

副本配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    replicas: 3
    # ...
  config:
      # ...
      default.replication.factor: 3
      min.insync.replicas: 2
 # ...

当通过 Kafka 配置添加代理时,节点 ID 以 0 (零)开始,Cluster Operator 会为新节点分配下一个最低 ID。代理删除过程从集群中 ID 的最高代理 pod 开始。

如果您要使用节点池功能的预览来管理集群中的节点,您可以调整 KafkaNodePool.spec.replicas 配置以更改节点池中的节点数。另外,在使用节点池扩展现有集群时,您可以为 扩展操作分配节点 ID

当您添加或删除代理时,Kafka 不会自动重新分配分区。执行此操作的最佳方法是使用 Cruise Control。您可以在扩展集群或缩减时使用 Cruise Control 的 add-brokersremove-brokers 模式。

  • 在扩展 Kafka 集群后,使用 add-brokers 模式,将分区副本从现有代理移到新添加的代理中。
  • 在缩减 Kafka 集群前,使用 remove-brokers 模式,将分区副本从要删除的代理移出。

第 18 章 使用 Cruise Control 重新平衡集群

Cruise Control 是一个开源系统,支持以下 Kafka 操作:

  • 监控集群工作负载
  • 根据预定义的约束重新平衡集群

此操作可帮助运行更有效地使用代理 pod 的 Kafka 集群。

典型的集群可能会随着时间不均匀地加载。处理大量消息流量的分区可能无法在可用的代理中平均分布。要重新平衡集群,管理员必须监控代理上的负载,并将忙碌的分区手动分配给具有备用容量的代理。

Cruise Control 自动执行集群重新平衡过程。它基于 CPU、磁盘和网络负载(您可以批准或拒绝)为集群构建资源利用率 的工作负载模型。一组可配置的优化目标用于计算这些提议。

您可以在特定模式中生成优化方案。默认 full 模式在所有代理间重新平衡分区。您还可以使用 add-brokersremove-brokers 模式来适应扩展集群或缩减时的更改。

当您批准一个优化建议时,Cruise Control 会将它应用到您的 Kafka 集群。您可以使用 KafkaRebalance 资源配置和生成优化建议。您可以使用注解配置资源,以便自动或手动批准优化提议。

注意

18.1. Cruise Control 组件和功能

Cruise Control 包括四个主要组件 - Load Monitor、Anomaly Detector 和 Executor-​ 以及用于客户端交互的 REST API。AMQ Streams 使用 REST API 来支持以下 Cruise Control 功能:

  • 从优化目标生成优化建议。
  • 根据优化提议,重新平衡 Kafka 集群。
优化目标

优化目标描述了从重新平衡实现的特定目标。例如,目标是更加均匀地在代理间分发主题副本。您可以更改要通过配置包含哪些目标。目标定义为一个硬目标或软目标。您可以通过 Cruise Control 部署配置添加硬目标。您还有特定于这些类别的主要、默认和用户提供的目标。

  • 目标是预先设置的,必须满足优化建议才能成功。
  • 不需要满足软 目标 才能成功进行优化建议。如果达到所有硬目标,则可以设置它们。
  • 主要目标从 Cruise Control 中继承。有些是预先设置为硬目标。默认情况下,主目标用于优化提议。
  • 默认目标 与主要目标相同。您可以指定您自己的一组默认目标。
  • 用户提供的目标是 配置用于生成特定优化建议的默认目标子集。
优化提议

优化建议由您要从重新平衡实现的目标组成。您可以生成一个优化建议,以创建提议的更改概述以及重新平衡的结果。目标按照特定优先级顺序进行评估。然后您可以选择批准或拒绝提议。您可以拒绝使用调整的目标集合再次运行它。

您可以使用三种模式之一生成优化提议。

  • full 是默认模式,运行完全重新平衡。
  • add-brokers 是扩展 Kafka 集群时添加代理时使用的模式。
  • remove-brokers 是您在缩减 Kafka 集群时删除代理前使用的模式。

目前还不支持其他 Cruise Control 功能,包括自我修复、通知、编写目标以及更改主题复制因素。

其他资源

18.2. 优化目标概述

优化目标对 Kafka 集群的工作负载重新分配和资源利用率的限制。要重新平衡 Kafka 集群,Cruise Control 使用 优化目标来生成优化提议,您可以批准或拒绝。

18.2.1. 优先级的目标顺序

AMQ Streams 支持在 Cruise Control 项目中开发的大多数优化目标。支持的目标(以默认降序排列)如下:

  1. rack-awareness
  2. 一组主题的每个代理的最小领导副本数
  3. 副本容量
  4. 容量目标

    • 磁盘容量
    • 网络入站容量
    • 网络出站容量
    • CPU 容量
  5. 副本分发
  6. 潜在的网络输出
  7. 资源分配目标

    • 磁盘使用率分布
    • 网络入站使用分布
    • 网络出站使用分布
    • CPU 使用率分布
  8. 领导字节速率分布
  9. 主题副本分发
  10. 领导副本分发
  11. 首选领导选举机制
  12. intra-broker 磁盘容量
  13. intra-broker 磁盘用量分布

有关每个优化目标的更多信息,请参阅 Cruise Control Wiki 中的目标

注意

尚不支持"写您自己的目标"目标和 Kafka 分配目标。

18.2.2. AMQ Streams 自定义资源中的目标配置

您可以在 KafkaKafkaRebalance 自定义资源中配置优化目标。Cruise Control 具有必须满足的硬优化目标的配置,以及主要、默认和用户提供的优化目标。

您可以在以下配置中指定优化目标:

  • Main goals — Kafka.spec.cruiseControl.config.goals
  • Hard goals — Kafka.spec.cruiseControl.config.hard.goals
  • Default goals — Kafka.spec.cruiseControl.config.default.goals
  • 用户提供的目标 IANA - KafkaRebalance.spec.goals
注意

资源分布目标取决于代理资源的 容量限制

18.2.3. 硬和软优化目标

硬目标是在优化建议时 必须满足 的目标。没有作为硬目标配置的目标被成为软目标。您可以将软目标视为 最佳工作 目标: 它们不需要 在优化建议方面满足,但包含在优化计算中。违反一个或多个软目标但满足所有硬目标的优化建议有效。

Cruise Control 将计算满足所有硬目标以及尽可能多的软目标(按优先级顺序)的优化建议。无法满足所有硬目标的优化建议将由 Cruise 控制而拒绝,而不会发送给用户进行批准。

注意

例如,您可能有一个软目标来在集群间平均分配主题的副本(主题分布目标)。如果这样做可让所有配置的硬目标满足,则 Cruise Control 将忽略这个目标。

在 Cruise Control 中,以下 主要优化目标 被预先设置为硬目标:

RackAwareGoal; MinTopicLeadersPerBrokerGoal; ReplicaCapacityGoal; DiskCapacityGoal; NetworkInboundCapacityGoal; NetworkOutboundCapacityGoal; CpuCapacityGoal

您可以通过编辑 Kafka.spec.cruiseControl.config 中的 hard.goals 属性,在 Cruise Control 部署配置中配置硬目标。

  • 要从 Cruise Control 中继承预设置的硬目标,请不要在 Kafka.spec.cruiseControl.config中指定 hard.goals 属性
  • 要更改预设置的硬目标,请使用其完全限定域名在 hard.goals 属性中指定所需的目标。

硬优化目标的 Kafka 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
  zookeeper:
    # ...
  entityOperator:
    topicOperator: {}
    userOperator: {}
  cruiseControl:
    brokerCapacity:
      inboundNetwork: 10000KB/s
      outboundNetwork: 10000KB/s
    config:
      # Note that `default.goals` (superset) must also include all `hard.goals` (subset)
      default.goals: >
        com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundCapacityGoal,
        com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundCapacityGoal
      hard.goals: >
        com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkInboundCapacityGoal,
        com.linkedin.kafka.cruisecontrol.analyzer.goals.NetworkOutboundCapacityGoal
      # ...

增加配置的硬目标数量可减少 Cruise 控制生成有效优化建议的可能性。

如果在 KafkaRebalance 自定义资源中指定 skipHardGoalCheck: true,Cruise Control 不会检查 用户提供的优化目标(在 KafkaRebalance.spec.goals)是否包含 所有配置的 硬目标(hard.goals)。因此,如果用户提供的优化目标在 hard.goals 列表中,Cruise Control 仍会将它们视为硬目标,即使指定了 skipHardGoalCheck: true

18.2.4. 主要优化目标

所有用户都提供了主要的优化目标。没有在主优化目标中列出的目标不适用于 Cruise Control 操作。

除非更改 Cruise Control 部署配置,AMQ Streams 将以降序从 Cruise Control 中继承以下主要优化目标:

RackAwareGoal; ReplicaCapacityGoal; DiskCapacityGoal; NetworkInboundCapacityGoal; NetworkOutboundCapacityGoal; CpuCapacityGoal; ReplicaDistributionGoal; PotentialNwOutGoal; DiskUsageDistributionGoal; NetworkInboundUsageDistributionGoal; NetworkOutboundUsageDistributionGoal; CpuUsageDistributionGoal; TopicReplicaDistributionGoal; LeaderReplicaDistributionGoal; LeaderBytesInDistributionGoal; PreferredLeaderElectionGoal

其中一些目标被预先设置为硬目标

为降低复杂性,建议您使用继承的主要优化目标,除非您需要 完全 排除一个或多个目标在 KafkaRebalance 资源中使用。如果需要,可以在配置中为默认优化目标修改主要优化目标的优先级顺序(如果需要)。

如果需要,您可以在 Cruise Control 部署配置中配置主要优化目标: Kafka.spec.cruiseControl.config.goals

  • 要接受继承的主要优化目标,请不要在 Kafka.spec.cruiseControl.config 中指定 goals 属性。
  • 如果您需要修改继承的主要优化目标,请在 goals 配置选项中指定目标列表(按优先级降序排列)。
注意

为了避免生成优化建议时出现错误,请确保对 Kafka.spec.cruiseControl.config 中的 goalsdefault.goals 所做的任何更改都包含 hard.goals 属性指定的所有硬目标。要说明,还必须为主要优化目标和默认目标指定硬目标(作为子集)。

18.2.5. 默认优化目标

Cruise Control 使用默认优化目标来生成缓存的优化建议。有关缓存的优化建议的更多信息,请参阅 第 18.3 节 “优化提议概述”

您可以通过在 KafkaRebalance 自定义资源中设置 用户提供的优化目标 来覆盖默认的优化目标。

除非在 Cruise Control 部署配置中 指定 default.goals,否则主要优化目标将用作默认的优化目标。在这种情况下,缓存的优化建议是使用主要优化目标生成的。

  • 要使用主要优化目标作为默认目标,请不要在 Kafka.spec.cruiseControl.config 中指定 default.goals 属性。
  • 要修改默认优化目标,请编辑 Kafka.spec.cruiseControl.config 中的 default.goals 属性。您必须使用主要优化目标的子集。

默认优化目标的 Kafka 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
spec:
  kafka:
    # ...
  zookeeper:
    # ...
  entityOperator:
    topicOperator: {}
    userOperator: {}
  cruiseControl:
    brokerCapacity:
      inboundNetwork: 10000KB/s
      outboundNetwork: 10000KB/s
    config:
      # Note that `default.goals` (superset) must also include all `hard.goals` (subset)
      default.goals: >
        com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal,
        com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaCapacityGoal,
        com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskCapacityGoal
      hard.goals: >
        com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal
      # ...

如果没有指定默认优化目标,则使用主优化目标生成缓存的提议。

18.2.6. 用户提供的优化目标

用户提供的优化目标 缩小为特定优化提议配置的默认目标。您可以根据需要在 KafkaRebalance 自定义资源中的 spec.goals 中设置它们:

KafkaRebalance.spec.goals

用户提供的优化目标可以为不同的场景生成优化提议。例如,您可能希望在 Kafka 集群间优化领导副本分布,而无需考虑磁盘容量或磁盘利用率。因此,您可以创建一个 KafkaRebalance 自定义资源,其中包含用于领导副本分发的单个用户提供的目标。

用户提供的优化目标必须:

  • 包括所有配置的硬目标,或发生错误
  • 是主要优化目标的子集

要在生成优化建议时忽略配置的硬目标,请在 KafkaRebalance 自定义资源中添加 skipHardGoalCheck: true 属性。请参阅 第 18.6 节 “生成优化建议”

其他资源

18.3. 优化提议概述

配置 KafkaRebalance 资源来生成优化建议并应用推荐的更改。optimization proposal 是要生成一个更加均衡的 Kafka 集群、在代理中平均分配分区工作负载的建议概述。

每个优化建议都基于一组用于生成它的 优化目标,受代理资源 配置的任何容量限制

所有优化的提议都是对提议重新平衡的影响的估算。您可以批准或拒绝提议。您无法在不先生成优化建议的情况下批准集群重新平衡。

您可以在以下重新平衡模式下运行优化建议:

  • full
  • add-brokers
  • remove-brokers

18.3.1. 重新平衡模式

您可以使用 KafkaRebalance 自定义资源的 spec.mode 属性指定重新平衡模式。

full
full 模式通过在集群中的所有代理间移动副本来运行完全重新平衡。如果在 KafkaRebalance 自定义资源中没有定义 spec.mode 属性,则这是默认模式。
add-brokers
add-brokers 模式在扩展 Kafka 集群后通过添加一个或多个代理来使用。通常,在扩展 Kafka 集群后,新的代理仅用于托管新创建的主题的分区。如果没有创建新主题,则不会使用新添加的代理,现有代理仍保留在同一负载中。通过在向集群添加代理后立即使用 add-brokers 模式,重新平衡操作会将副本从现有代理移到新添加的代理中。您可以使用 KafkaRebalance 自定义资源的 spec.brokers 属性将新代理指定为列表。
remove-brokers
在通过删除一个或多个代理来缩减 Kafka 集群前使用 remove-brokers 模式。如果缩减 Kafka 集群,代理也会关闭,即使它们托管副本。这可能导致复制分区不足,并可能导致某些分区处于最小 ISR 下(同步副本)。为了避免这个问题,delete -brokers 模式会将副本从要删除的代理移出。当这些代理不再托管副本时,可以安全地运行缩减操作。您可以在 KafkaRebalance 自定义资源的 spec.brokers 属性中将您要删除的代理指定为列表。

通常,通过将负载分散到代理中,使用完整 重新平衡模式重新平衡 Kafka 集群。只有在您要扩展集群或缩减时,才使用 add-brokersremove-brokers 模式,并相应地重新平衡副本。

在三种不同的模式下,运行重新平衡的过程实际上相同。唯一的区别是通过 spec.mode 属性指定模式,如果需要,列出已添加或将通过 spec.brokers 属性删除的代理。

18.3.2. 优化提议的结果

生成优化建议时,会返回概述和代理负载。

概述
Summary 包含在 KafkaRebalance 资源中。概述概述了建议的集群重新平衡,并指示涉及的更改规模。KafkaRebalance 资源的 Status.OptimizationResult 属性中包含成功生成的优化建议概述。提供的信息是完整优化提议的总结。
代理加载
代理负载存储在 ConfigMap 中,其中包含为 JSON 字符串的数据。代理负载显示在提议重新平衡的之前和之后,以便您可以看到对集群中的每个代理的影响。

18.3.3. 手动批准或拒绝优化建议

优化建议概述显示了推荐的更改范围。

您可以使用 KafkaRebalance 资源的名称从命令行返回摘要。

返回优化建议概述

oc describe kafkarebalance <kafka_rebalance_resource_name> -n <namespace>

您还可以使用 jq 命令行 JSON 解析器工具。

使用 jq 返回优化建议概述

oc get kafkarebalance -o json | jq <jq_query>.

使用摘要来决定是否批准或拒绝优化提议。

批准优化建议
您可以通过将 KafkaRebalance 资源的 strimzi.io/rebalance 注解设置为 批准来批准 优化建议。Cruise Control 将提议应用到 Kafka 集群,并启动集群重新平衡操作。
拒绝优化建议
如果您选择不批准优化方案,您可以更改优化目标更新任何重新平衡性能调优选项,然后生成另一个提议。您可以通过将 strimzi.io/rebalance 注解设置为 refresh 来为 KafkaRebalance 资源生成新的优化建议。

使用优化建议来评估重新平衡所需的移动。例如,概述描述了 inter-broker 和 intra-broker 移动。在独立代理间重新平衡数据。当您使用 JBOD 存储配置时,在同一代理的磁盘间移动数据重新平衡。即使您没有提前并批准提议,此类信息也很有用。

因为在重新平衡时在 Kafka 集群中出现额外的负载,您可能会拒绝优化过程或延迟其批准。

在以下示例中,建议在单独的代理间重新平衡数据。重新平衡涉及在代理间移动 55 分区副本(数据总量为 12MB)。虽然分区副本间的移动对性能有高影响,但数据总数不大。如果总数据更大,您可以拒绝提议,或者在批准重新平衡时限制对 Kafka 集群性能的影响。

重新平衡性能调优选项有助于降低数据移动的影响。如果可扩展重新平衡周期,您可以将重新平衡分成较小的批处理。一次的数据移动较少可减少集群的负载。

优化提议概述示例

Name:         my-rebalance
Namespace:    myproject
Labels:       strimzi.io/cluster=my-cluster
Annotations:  API Version:  kafka.strimzi.io/v1alpha1
Kind:         KafkaRebalance
Metadata:
# ...
Status:
  Conditions:
    Last Transition Time:  2022-04-05T14:36:11.900Z
    Status:                ProposalReady
    Type:                  State
  Observed Generation:     1
  Optimization Result:
    Data To Move MB:  0
    Excluded Brokers For Leadership:
    Excluded Brokers For Replica Move:
    Excluded Topics:
    Intra Broker Data To Move MB:         12
    Monitored Partitions Percentage:      100
    Num Intra Broker Replica Movements:   0
    Num Leader Movements:                 24
    Num Replica Movements:                55
    On Demand Balancedness Score After:   82.91290759174306
    On Demand Balancedness Score Before:  78.01176356230222
    Recent Windows:                       5
  Session Id:                             a4f833bd-2055-4213-bfdd-ad21f95bf184

该提议还将 24 个分区领导移到不同的代理。这需要对 ZooKeeper 配置的更改,这会影响性能。

平衡分数是批准优化提议前和之后 Kafka 集群的整体平衡度量。平衡分数基于优化目标。如果满足所有目标,则分数为 100。当一个目标不满足时,分数会降低。比较均衡分数,以查看 Kafka 集群是否比重新平衡要小。

18.3.4. 自动批准优化建议

要节省时间,您可以自动执行批准优化方案的过程。通过自动化,当您生成优化建议时,它会进入集群重新平衡。

要启用优化提议 auto-approval 机制,请创建 KafkaRebalance 资源,并将 strimzi.io/rebalance-auto-approval 注解设置为 true。如果未设置注解或设置为 false,则优化提议需要手动批准。

启用 auto-approval 机制的重新平衡请求示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaRebalance
metadata:
  name: my-rebalance
  labels:
    strimzi.io/cluster: my-cluster
  annotations:
    strimzi.io/rebalance-auto-approval: "true"
spec:
  mode: # any mode
  # ...

在自动批准优化提议时,您仍然可以检查状态。在重新平衡完成后,KafkaRebalance 资源的状态将变为 Ready

18.3.5. 优化建议概述属性

下表解释了优化提议概述部分中包含的属性。

表 18.1. 优化建议概述中包含的属性
JSON 属性Description

numIntraBrokerReplicaMovements

在集群代理磁盘之间传输的分区副本数量。

重新平衡操作期间的性能影响 :高,但低于 numReplicaMovements

excludedBrokersForLeadership

尚不受支持。返回空列表。

numReplicaMovements

在独立代理之间移动的分区副本数量。

重新平衡操作期间的性能影响 :非常高。

onDemandBalancednessScoreBefore, onDemandBalancednessScoreAfter

在生成优化提议前和之后,测量 Kafka 集群的整体 平衡性

分数通过将每个违反的软目标从 100 中减去 BalancednessScore 的总和来计算。Cruise Control 根据几个因素,为每个优化目标分配一个 BalancednessScore,包括目标在 default.goals 或用户提供的目标列表中的位置。

Before 分数基于 Kafka 集群的当前配置。After 分数基于生成的优化提议。

intraBrokerDataToMoveMB

在同一代理的磁盘间移动的每个分区副本的大小总和(请参阅 numIntraBrokerReplicaMovements)。

重新平衡操作期间的性能影响 :变量.集群重新平衡所需的时间越大,完成集群重新平衡所需的时间。在同一代理的磁盘之间移动大量数据比不同的代理之间的影响要小(请参阅 dataToMoveMB)。

recentWindows

优化提议的指标窗口数量。

dataToMoveMB

移到独立代理的每个分区副本的大小总和(请参阅 numReplicaMovements)。

重新平衡操作期间的性能影响 :变量.集群重新平衡所需的时间越大,完成集群重新平衡所需的时间。

monitoredPartitionsPercentage

优化提议涵盖的 Kafka 集群中的分区百分比。受 excludedTopics 数量的影响。

excludedTopics

如果您在 KafkaRebalance 资源中的 spec.excludedTopicsRegex 属性中指定正则表达式,则此处列出了与该表达式匹配的所有主题名称。这些主题不包括在优化建议中的分区副本/领导移动的计算中。

numLeaderMovements

领导程序切换到不同副本的分区数量。这包括对 ZooKeeper 配置的更改。

重新平衡操作期间的性能影响 :非常低。

excludedBrokersForReplicaMove

尚不受支持。返回空列表。

18.3.6. 代理加载属性

代理负载存储在 ConfigMap 中(与 KafkaRebalance 自定义资源的名称相同),与 JSON 格式的字符串相同。此 JSON 字符串由一个 JSON 对象组成,每个代理 ID 的键链接到每个代理的多个指标。每个指标由三个值组成:第一个是应用优化提议前的指标值,第二个是应用提议后指标的预期值,第三个是前两个值之间的差别(在前减前)。

注意

当 KafkaRebalance 资源处于 ProposalReady 状态时,ConfigMap 会出现,并在重新平衡完成后保留。

您可以使用 ConfigMap 的名称从命令行查看其数据。

返回 ConfigMap 数据

oc describe configmaps <my_rebalance_configmap_name> -n <namespace>

您还可以使用 jq 命令行 JSON 解析器工具从 ConfigMap 中提取 JSON 字符串。

使用 jq 从 ConfigMap 提取 JSON 字符串

oc get configmaps <my_rebalance_configmap_name> -o json | jq '.["data"]["brokerLoad.json"]|fromjson|.'

下表解释了优化提议的代理加载 ConfigMap 中包含的属性:

JSON 属性Description

领导

此代理中分区领导的副本数。

replicas

此代理的副本数。

cpuPercentage

CPU 使用率作为定义的容量的百分比。

diskUsedPercentage

磁盘利用率作为定义的容量的百分比。

diskUsedMB

以 MB 为单位的绝对磁盘用量。

networkOutRate

代理的网络输出率总数。

leaderNetworkInRate

此代理上所有分区领导副本的网络输入率。

followerNetworkInRate

此代理上所有后续副本的网络输入率。

potentialMaxNetworkOutRate

如果此代理成为当前主机的所有副本的领导,则预测最大网络输出率将获得。

18.3.7. 缓存优化建议

Cruise Control 根据配置的默认优化目标维护缓存的优化建议。从工作负载模型生成,缓存的优化方案每 15 分钟更新一次,以反映 Kafka 集群的当前状态。如果您使用默认优化目标生成优化建议,Cruise Control 会返回最新的缓存提议。

要更改缓存的优化建议刷新间隔,请编辑 Cruise Control 部署配置中的 proposal.expiration.ms 设置。对于快速更改的集群,考虑一个较短的间隔,但这会增加 Cruise Control 服务器的负载。

18.4. 重新平衡性能调优概述

您可以为集群重新平衡调整几个性能调优选项。这些选项控制如何执行重新平衡中的分区副本和领导移动,以及分配给重新平衡操作的带宽。

18.4.1. 分区重新分配命令

优化建议 由单独的分区重新分配命令组成。当您 批准 一个提议时,Cruise Control 服务器会将这些命令应用到 Kafka 集群。

分区重新分配命令由以下一种操作组成:

  • 分区移动:将分区副本及其数据传输到新位置。分区移动可以采用两种形式之一:

    • Inter-broker move: 分区副本被移到不同代理上的日志目录中。
    • intra-broker move: 分区副本被移到同一代理的不同日志目录中。
  • 领导移动:这涉及切换分区副本的领导。

Cruise Control issues 分区重新分配命令到批处理中的 Kafka 集群。在重新平衡过程中集群的性能会受到每个批处理中包含的每种移动数量的影响。

18.4.2. 副本移动策略

集群重新平衡性能也会受到 副本移动策略的影响,该策略应用到分区重新分配命令的批处理。默认情况下,Cruise Control 使用 BaseReplicaMovementStrategy,它只是按照生成的顺序应用命令。但是,如果提议的早期有一些非常大的分区重新分配,则此策略可能会减慢其他重新分配的应用程序。

Cruise Control 提供四个替代的副本移动策略,可用于优化提议:

  • priorityitizeSmallReplicaMovementStrategy: Order reassignments 按顺序排列。
  • prioritizeitizeLargeReplicaMovementStrategy: Order reassignments 顺序降序。
  • PostponeUrpReplicaMovementStrategy: 优先考虑为没有处于不同步状态的分区的服务的重新分配。
  • prioritizeitizeMinIsrWithOfflineReplicasStrategy: 优先考虑重新分配(At/Under) MinISR 分区,并带有离线副本。只有在 Kafka 自定义资源的 spec 中将 cruiseControl.config.concurrency.adjuster.min.isr.check.enabled 设置为 true 时,此策略才会正常工作。

这些策略可以配置为序列。第一个策略尝试使用其内部逻辑比较两个分区重新分配。如果重新分配等同于,那么它将按顺序传递给下一个策略,以确定顺序等。

18.4.3. intra-broker 磁盘平衡

在同一代理的磁盘间移动大量数据比单独的代理的影响要小得多。如果您运行一个 Kafka 部署,它将 JBOD 存储与同一代理中的多个磁盘搭配使用,Cruise Control 可以在磁盘之间平衡分区。

注意

如果您将 JBOD 存储与单一磁盘配合使用,在代理磁盘平衡中,则会导致一个有 0 分区移动的成成,因为没有磁盘之间的平衡。

要执行内部磁盘平衡,请在 KafkaRebalance.spec 下将 rebalanceDisk 设置为 true。当将 rebalanceDisk 设置为 true 时,不要在 KafkaRebalance.spec 中设置 goals 字段,因为 Cruise Control 会自动设置 intra-broker 目标并忽略 inter-broker 目标。Cruise Control 不会同时执行 inter-broker 和 intra-broker 平衡。

18.4.4. 重新平衡调整选项

Cruise Control 提供了几个配置选项,用于调整上述讨论的重新平衡参数。您可以在 使用 Kafka 配置和部署 Cruise Control优化建议 级别时设置这些调整选项:

  • Cruise Control 服务器设置可以在 Kafka. spec.cruiseControl.config 下的 Kafka 自定义资源中设置。
  • 单个重新平衡性能配置可以在 KafkaRebalance.spec 下设置。

下表中总结了相关的配置。

表 18.2. 重新平衡性能调优配置
Cruise Control 属性KafkaRebalance 属性默认描述

num.concurrent.partition.movements.per.broker

concurrentPartitionMovementsPerBroker

5

每个分区重新分配批处理中的最大代理分区移动数

num.concurrent.intra.broker.partition.movements

concurrentIntraBrokerPartitionMovements

2

每个分区重新分配批处理中的最大 intra-broker 分区移动数

num.concurrent.leader.movements

concurrentLeaderMovements

1000

每个分区重新分配批处理中的最大分区领导更改数

default.replication.throttle

replicationThrottle

null (无限制)

分配给分区重新分配的带宽(以字节为单位)

default.replica.movement.strategies

replicaMovementStrategies

BaseReplicaMovementStrategy

用于决定为生成的提议执行分区重新分配命令的顺序(优先级顺序)的列表。对于 server 设置,使用逗号分隔的字符串以及策略类的完全限定域名(将 com.linkedin.kafka.cruisecontrol.executor.strategy. strategy 添加到每个类名称的开头)。对于 KafkaRebalance 资源设置,请使用策略类名称的 YAML 数组。

-

rebalanceDisk

false

启用内部磁盘平衡,在同一代理的磁盘之间平衡磁盘空间利用率。只适用于使用多个磁盘的 JBOD 存储的 Kafka 部署。

更改默认设置会影响重新平衡完成所需的时间,以及重新平衡期间 Kafka 集群上的负载。使用较低值可减少负载,但会增加花费的时间,反之亦然。

18.5. 使用 Kafka 配置和部署 Cruise 控制

配置 Kafka 资源,以使用 Kafka 集群部署 Cruise Control。您可以使用 Kafka 资源的 cruiseControl 属性来配置部署。为每个 Kafka 集群部署一个 Cruise Control 实例。

在 Cruise Control config 中使用 goals 配置来指定优化目标,以生成优化建议。您可以使用 brokerCapacity 更改与资源分发相关的目标的默认容量限制。如果代理在带有异构网络资源的节点上运行,您可以使用 覆盖 为每个代理设置网络容量限制。

如果将空对象({})用于 cruiseControl 配置,则所有属性都使用它们的默认值。

有关 Cruise Control 配置选项的更多信息,请参阅 AMQ Streams 自定义资源 API 参考

先决条件

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

流程

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

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

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      # ...
      cruiseControl:
        brokerCapacity: 1
          inboundNetwork: 10000KB/s
          outboundNetwork: 10000KB/s
          overrides: 2
          - brokers: [0]
            inboundNetwork: 20000KiB/s
            outboundNetwork: 20000KiB/s
          - brokers: [1, 2]
            inboundNetwork: 30000KiB/s
            outboundNetwork: 30000KiB/s
          # ...
        config: 3
          # Note that `default.goals` (superset) must also include all `hard.goals` (subset)
          default.goals: > 4
            com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal,
            com.linkedin.kafka.cruisecontrol.analyzer.goals.ReplicaCapacityGoal,
            com.linkedin.kafka.cruisecontrol.analyzer.goals.DiskCapacityGoal
            # ...
          hard.goals: >
            com.linkedin.kafka.cruisecontrol.analyzer.goals.RackAwareGoal
            # ...
          cpu.balance.threshold: 1.1
          metadata.max.age.ms: 300000
          send.buffer.bytes: 131072
          webserver.http.cors.enabled: true 5
          webserver.http.cors.origin: "*"
          webserver.http.cors.exposeheaders: "User-Task-ID,Content-Type"
          # ...
        resources: 6
          requests:
            cpu: 1
            memory: 512Mi
          limits:
            cpu: 2
            memory: 2Gi
        logging: 7
            type: inline
            loggers:
              rootLogger.level: INFO
        template: 8
          pod:
            metadata:
              labels:
                label1: value1
            securityContext:
              runAsUser: 1000001
              fsGroup: 0
            terminationGracePeriodSeconds: 120
        readinessProbe: 9
          initialDelaySeconds: 15
          timeoutSeconds: 5
        livenessProbe:
          initialDelaySeconds: 15
          timeoutSeconds: 5
        metricsConfig: 10
          type: jmxPrometheusExporter
          valueFrom:
            configMapKeyRef:
              name: cruise-control-metrics
              key: metrics-config.yml
    # ...
    1
    代理资源的容量限制。
    2
    当使用异构网络资源的节点运行时,覆盖为特定代理设置网络容量限制。
    3
    Cruise Control 配置。可以提供标准的 Cruise Control 配置,仅限于不直接由 AMQ Streams 管理的这些属性。
    4
    优化目标配置,其中包括用于默认优化目标(default.goals)、主要优化目标(目标)和硬目标(硬.goals)的配置。
    5
    为对 Cruise Control API 的只读访问启用并配置 CORS。
    6
    用于保留支持的资源、当前 cpu 和内存 以及限制的请求,以指定可消耗的最大资源。
    7
    通过 ConfigMap 直接添加 Cruise Control logger 和 loglevel (内联)或间接(外部)。自定义 Log4j 配置必须放在 ConfigMap 中的 log4j.properties 键下。Cruise Control 有一个名为 rootLogger.level 的单个日志记录器。您可以将日志级别设置为 INFO, ERROR, WARN, TRACE, DEBUG, FATAL 或 OFF。
    8
    模板自定义。这里的 pod 使用额外的安全属性调度。
    9
    健康检查以了解何时重启容器(持续)以及容器可以接受流量(就绪状态)。
    10
    启用 Prometheus 指标。在本例中,为 Prometheus JMX Exporter (默认指标导出器)配置了指标。
  2. 创建或更新资源:

    oc apply -f <kafka_configuration_file>
  3. 检查部署的状态:

    oc get deployments -n <my_cluster_operator_namespace>

    输出显示部署名称和就绪度

    NAME                      READY  UP-TO-DATE  AVAILABLE
    my-cluster-cruise-control 1/1    1           1

    my-cluster 是 Kafka 集群的名称。

    READY 显示就绪/预期的副本数。当 AVAILABLE 输出显示为 1 时,部署成功。

自动创建的主题

下表显示了部署 Cruise Control 时自动创建的三个主题。Cruise Control 正常工作且不得删除或更改这些主题。您可以使用指定的配置选项更改主题的名称。

表 18.3. 自动创建的主题
自动创建的主题配置默认主题名称创建方功能

metric.reporter.topic

strimzi.cruisecontrol.metrics

AMQ Streams Metrics Reporter

将 Metrics Reporter 中的原始指标存储在每个 Kafka 代理中。

partition.metric.sample.store.topic

strimzi.cruisecontrol.partitionmetricsamples

Sything Control

存储每个分区派生的指标。它们由指标示例聚合器创建。

broker.metric.sample.store.topic

strimzi.cruisecontrol.modeltrainingsamples

Sything Control

存储用于创建 Cluster Workload Model 的指标示例。

要防止删除 Cruise Control 所需的记录,在自动创建的主题中禁用日志压缩。

注意

如果在启用了 Cruise Control 的 Kafka 集群中更改自动创建主题的名称,旧的主题不会被删除,应手动删除旧的主题。

接下来要做什么

配置和部署 Cruise Control 后,您可以生成优化提议

其他资源

18.6. 生成优化建议

当您创建或更新 KafkaRebalance 资源时,Cruise Control 会根据配置的 优化目标 为 Kafka 集群生成优化建议。分析优化建议中的信息,并决定是否批准它。您可以使用优化提议的结果来重新平衡 Kafka 集群。

您可以在以下模式之一运行优化提议:

  • full (默认)
  • add-brokers
  • remove-brokers

您使用的模式取决于您是否在 Kafka 集群中已在运行的所有代理重新平衡 ; 或者要在扩展后或缩减 Kafka 集群前重新平衡。如需更多信息,请参阅使用代理扩展重新平衡模式

先决条件

  • 您已将 Cruise Control 部署到 AMQ Streams 集群。
  • 您已配置了优化目标,并选择性地对代理资源的容量限制。

有关配置 Cruise Control 的详情,请参考 第 18.5 节 “使用 Kafka 配置和部署 Cruise 控制”

流程

  1. 创建 KafkaRebalance 资源并指定适当的模式。

    完整 模式(默认)

    要使用 Kafka 资源中定义的 默认优化目标,请将 spec 属性留空。默认情况下,Cruise Control 以 完整 模式重新平衡 Kafka 集群。

    默认具有完全重新平衡的配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaRebalance
    metadata:
      name: my-rebalance
      labels:
        strimzi.io/cluster: my-cluster
    spec: {}

    您还可以通过 spec.mode 属性指定 完整 模式来运行完整的重新平衡。

    指定 完整 模式的配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaRebalance
    metadata:
      name: my-rebalance
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      mode: full

    add-brokers 模式

    如果要在扩展后重新平衡 Kafka 集群,请指定 add-brokers 模式。

    在这个模式中,现有副本被移到新添加的代理中。您需要将代理指定为列表。

    指定 add-brokers 模式的配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaRebalance
    metadata:
      name: my-rebalance
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      mode: add-brokers
      brokers: [3, 4] 1

    1
    扩展操作添加新添加的代理列表。此属性是必需的。
    remove-brokers 模式

    如果要在缩减前重新平衡 Kafka 集群,请指定 remove-brokers 模式。

    在这个模式中,副本将从要删除的代理移出。您需要指定作为列表删除的代理。

    指定 remove-brokers 模式的配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaRebalance
    metadata:
      name: my-rebalance
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      mode: remove-brokers
      brokers: [3, 4] 1

    1
    缩减操作要删除的代理列表。此属性是必需的。
    注意

    无论您使用的重新平衡模式是什么,以下步骤以及批准或停止重新平衡的步骤相同。

  2. 要配置 用户提供的优化目标 而不使用默认目标,请添加 goals 属性并输入一个或多个目标。

    在以下示例中,机架感知和副本容量配置为用户提供的优化目标:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaRebalance
    metadata:
      name: my-rebalance
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      goals:
        - RackAwareGoal
        - ReplicaCapacityGoal
  3. 要忽略配置的硬目标,请添加 skipHardGoalCheck: true 属性:

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaRebalance
    metadata:
      name: my-rebalance
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      goals:
        - RackAwareGoal
        - ReplicaCapacityGoal
      skipHardGoalCheck: true
  4. (可选)要自动批准优化提议,请将 strimzi.io/rebalance-auto-approval 注解设置为 true

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaRebalance
    metadata:
      name: my-rebalance
      labels:
        strimzi.io/cluster: my-cluster
      annotations:
        strimzi.io/rebalance-auto-approval: "true"
    spec:
      goals:
        - RackAwareGoal
        - ReplicaCapacityGoal
      skipHardGoalCheck: true
  5. 创建或更新资源:

    oc apply -f <kafka_rebalance_configuration_file>

    Cluster Operator 从 Cruise Control 请求优化提议。这可能需要几分钟时间,具体取决于 Kafka 集群的大小。

  6. 如果您使用自动批准机制,请等待优化提议的状态更改为 Ready。如果您没有启用自动批准机制,请等待优化提议的状态更改为 ProposalReady

    oc get kafkarebalance -o wide -w -n <namespace>
    PendingProposal
    PendingProposal 状态意味着重新平衡 Operator 正在轮询 Cruise Control API 来检查优化提议是否就绪。
    ProposalReady
    ProposalReady 状态表示优化提议已准备好审核和批准。

    当状态变为 ProposalReady 时,优化提议可以批准。

  7. 查看优化提议。

    优化建议包含在 KafkaRebalance 资源的 Status.Optimization Result 属性中。

    oc describe kafkarebalance <kafka_rebalance_resource_name>

    优化提议示例

    Status:
      Conditions:
        Last Transition Time:  2020-05-19T13:50:12.533Z
        Status:                ProposalReady
        Type:                  State
      Observed Generation:     1
      Optimization Result:
        Data To Move MB:  0
        Excluded Brokers For Leadership:
        Excluded Brokers For Replica Move:
        Excluded Topics:
        Intra Broker Data To Move MB:         0
        Monitored Partitions Percentage:      100
        Num Intra Broker Replica Movements:   0
        Num Leader Movements:                 0
        Num Replica Movements:                26
        On Demand Balancedness Score After:   81.8666802863978
        On Demand Balancedness Score Before:  78.01176356230222
        Recent Windows:                       1
      Session Id:                             05539377-ca7b-45ef-b359-e13564f1458c

    Optimization Result 部分中的属性描述了待处理的集群重新平衡操作。有关每个属性的描述,请参阅优化提议的内容

CPU 容量不足

如果 Kafka 集群被 CPU 使用率过载,您可能会在 KafkaRebalance 状态中看到 CPU 容量错误不足。值得注意的是,这个使用值不受 excludedTopics 配置的影响。虽然优化建议不会重新分配排除主题的副本,但它们的负载仍然考虑在利用率计算中。

CPU 使用率错误示例

com.linkedin.kafka.cruisecontrol.exception.OptimizationFailureException:
        [CpuCapacityGoal] Insufficient capacity for cpu (Utilization 615.21,
        Allowed Capacity 420.00, Threshold: 0.70). Add at least 3 brokers with
        the same cpu capacity (100.00) as broker-0. Add at least 3 brokers with
        the same cpu capacity (100.00) as broker-0.

注意

错误以百分比而不是 CPU 内核数的形式显示 CPU 容量。因此,它不会直接映射到 Kafka 自定义资源中配置的 CPU 数量。它像每个代理都有一个 虚拟 CPU,它在 Kafka.spec.kafka.resources.limits.cpu 中配置 CPU 的周期。这不会影响重新平衡行为,因为 CPU 使用率和容量之间的比率保持不变。

18.7. 批准优化建议

如果其状态是 ProposalReady,则可以批准 Cruise Control 生成的 优化提议。然后,Cruise Control 会将优化建议应用到 Kafka 集群,将分区重新分配给代理并更改分区领导。

小心

这不是一个空运行。在批准优化前,您必须:

先决条件

流程

对您要批准的优化提议执行这些步骤。

  1. 除非新生成了优化建议,否则请检查它是否基于有关 Kafka 集群状态的当前信息。要做到这一点,刷新优化建议以确保它使用最新的集群指标:

    1. 使用 strimzi.io/rebalance=refresh 注解 OpenShift 中的 KafkaRebalance 资源:

      oc annotate kafkarebalance <kafka_rebalance_resource_name> strimzi.io/rebalance=refresh
  2. 等待优化提议的状态更改为 ProposalReady

    oc get kafkarebalance -o wide -w -n <namespace>
    PendingProposal
    PendingProposal 状态意味着重新平衡 Operator 正在轮询 Cruise Control API 来检查优化提议是否就绪。
    ProposalReady
    ProposalReady 状态表示优化提议已准备好审核和批准。

    当状态变为 ProposalReady 时,优化提议可以批准。

  3. 批准您希望 Cruise Control 适用的优化方案。

    使用 strimzi.io/rebalance=approve 注解 OpenShift 中的 KafkaRebalance 资源:

    oc annotate kafkarebalance <kafka_rebalance_resource_name> strimzi.io/rebalance=approve
  4. Cluster Operator 会检测注解的资源,并指示 Cruise Control 来重新平衡 Kafka 集群。
  5. 等待优化提议的状态更改为 Ready

    oc get kafkarebalance -o wide -w -n <namespace>
    重新平衡
    Rebalancing 状态代表重新平衡正在进行。
    Ready
    Ready 状态表示重新平衡已完成。
    NotReady
    NotReady 状态意味着会出现错误,请参阅 修复 KafkaRebalance 资源的问题

    当状态变为 Ready 时,重新平衡已完成。

    要使用同一 KafkaRebalance 自定义资源生成另一个优化建议,请将 refresh 注解应用到自定义资源。这会将自定义资源移到 PendingProposalProposalReady 状态。然后,您可以检查优化提议并批准它(如果需要)。

18.8. 停止集群重新平衡

启动后,集群重新平衡操作可能需要一些时间才能完成并影响 Kafka 集群的整体性能。

如果要停止正在进行的集群重新平衡操作,请将 stop 注解应用到 KafkaRebalance 自定义资源。这指示 Cruise Control 完成当前的分区重新分配批处理,然后停止重新平衡。当重新平衡停止后,已完成的分区重新分配已被应用;因此,在重新平衡操作开始前 Kafka 集群的状态会有所不同。如果需要进一步重新平衡,您应该生成新的优化建议。

注意

在 intermediate(停止)状态中的 Kafka 集群的性能可能比初始状态更糟。

先决条件

  • 您已通过使用 approve 注解了 KafkaRebalance 自定义资源来批准优化的提议
  • KafkaRebalance 自定义资源的状态是 Rebalancing

流程

  1. 在 OpenShift 中注解 KafkaRebalance 资源:

    oc annotate kafkarebalance rebalance-cr-name strimzi.io/rebalance=stop
  2. 检查 KafkaRebalance 资源的状态:

    oc describe kafkarebalance rebalance-cr-name
  3. 等待状态变为 Stopped

18.9. 修复 KafkaRebalance 资源的问题

如果在创建 KafkaRebalance 资源或与 Cruise Control 交互时出现问题,则会在资源状态中报告错误,以及如何修复它的详情。资源也会进入 NotReady 状态。

要继续进行集群重新平衡操作,您必须修复 KafkaRebalance 资源本身或整个 Cruise Control 部署中的问题。问题可能包括以下内容:

  • KafkaRebalance 资源中的错误参数。
  • KafkaRebalance 资源中指定 Kafka 集群的 strimzi.io/cluster 标签缺失。
  • Cruise Control 服务器没有部署为 Kafka 资源中的 cruiseControl 属性。
  • 无法访问 Cruise Control 服务器。

修复这个问题后,您需要在 KafkaRebalance 资源中添加刷新 注解。在 "refresh" 期间,通过 Cruise Control 服务器请求一个新的优化提议。

先决条件

  • 您已 批准了优化建议
  • 重新平衡操作的 KafkaRebalance 自定义资源的状态为 NotReady

流程

  1. KafkaRebalance 状态获取有关错误的信息:

    oc describe kafkarebalance rebalance-cr-name
  2. 尝试解决 KafkaRebalance 资源中的问题。
  3. 在 OpenShift 中注解 KafkaRebalance 资源:

    oc annotate kafkarebalance rebalance-cr-name strimzi.io/rebalance=refresh
  4. 检查 KafkaRebalance 资源的状态:

    oc describe kafkarebalance rebalance-cr-name
  5. 等待状态变为 PendingProposal,或直接更改为 ProposalReady

第 19 章 使用分区重新分配工具

在扩展 Kafka 集群时,您可能需要添加或删除代理并更新分区分布或主题复制因素。要更新分区和主题,您可以使用 kafka-reassign-partitions.sh 工具。

AMQ Streams Cruise Control 集成或主题 Operator 支持更改主题的复制因素。但是,您可以使用 kafka-reassign-partitions.sh 工具更改主题的复制因素。

该工具也可用于重新分配分区并在代理间平衡分区分布,以提高性能。但是,建议使用 Cruise Control 自动分区重新分配和集群重新平衡。Cruise Control 可以在没有任何停机时间的情况下将主题从一个代理移到另一个代理,它是重新分配分区的最有效方法。

建议将 kafka-reassign-partitions.sh 工具作为单独的交互式 pod 运行,而不是在代理容器中运行。在代理容器中运行 Kafka bin/ 脚本可能会导致 JVM 从与 Kafka 代理相同的设置开始,这可能会导致中断。在单独的 pod 中运行 kafka-reassign-partitions.sh 工具,您可以避免出现这个问题。使用 -ti 选项运行 pod,创建一个交互式 pod,并在 pod 中运行 shell 命令。

使用终端运行交互式 pod

oc run helper-pod -ti --image=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 --rm=true --restart=Never -- bash

19.1. 分区重新分配工具概述

分区重新分配工具提供以下功能来管理 Kafka 分区和代理:

重新分发分区副本
通过添加或删除代理来扩展集群,并将 Kafka 分区从大量加载的代理移到使用不足的代理。要做到这一点,您必须创建一个分区重新分配计划,以标识要移动的主题和分区以及移动它们的位置。对于这种类型的操作,建议使用 Cruise Control,因为它 自动执行集群重新平衡过程
扩展主题复制因素和缩减
增加或减少 Kafka 主题的复制因素。要做到这一点,您必须创建一个分区重新分配计划,以标识分区之间的现有复制分配,以及使用复制因素更改的更新分配。
更改首选领导
更改 Kafka 分区的首选领导。如果当前首选领导不可用或者您要在集群中在代理间重新分发负载,这非常有用。要做到这一点,您必须创建一个分区重新分配计划,该计划通过更改副本顺序来指定每个分区的新首选领导。
将日志目录更改为使用特定的 JBOD 卷
将 Kafka 代理的日志目录更改为使用特定的 JBOD 卷。如果要将 Kafka 数据移动到不同的磁盘或存储设备中,这非常有用。要做到这一点,您必须创建一个分区重新分配计划,用于指定每个主题的新日志目录。

19.1.1. 生成分区重新分配计划

分区重新分配工具(kafka-reassign-partitions.sh)的工作原理,方法是生成一个分区分配计划,指定哪些分区应从其当前代理移到新代理中。

如果您对计划满意,您可以执行它。然后该工具执行以下操作:

  • 将分区数据迁移到新代理
  • 更新 Kafka 代理的元数据以反映新分区分配
  • 触发 Kafka 代理滚动重启,以确保新分配生效

分区重新分配工具有三种不同的模式:

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

在任意给定时间,集群中只能有一个重新分配,且无法取消正在运行的重新分配。如果需要取消重新分配,请等待它完成,然后执行另一个重新分配来恢复第一个重新分配的影响。kafka-reassign-partitions.sh 将打印这个 reversion 的重新分配 JSON 作为其输出的一部分。非常大的重新分配应该被分解为多个较小的重新分配,以防需要停止 in-progress 重新分配。

19.1.2. 在分区重新分配 JSON 文件中指定主题

kafka-reassign-partitions.sh 工具使用一个重新分配 JSON 文件来指定要重新分配的主题。如果要移动特定的分区,您可以生成重新分配 JSON 文件或手动创建文件。

基本重新分配 JSON 文件在以下示例中显示的结构,它描述了属于两个 Kafka 主题的三个分区。每个分区被重新分配给一组新的副本,这些副本由代理 ID 标识。需要 版本主题分区副本 属性。

分区重新分配 JSON 文件结构示例

{
  "version": 1, 1
  "partitions": [ 2
    {
      "topic": "example-topic-1", 3
      "partition": 0, 4
      "replicas": [1, 2, 3] 5
    },
    {
      "topic": "example-topic-1",
      "partition": 1,
      "replicas": [2, 3, 4]
    },
    {
      "topic": "example-topic-2",
      "partition": 0,
      "replicas": [3, 4, 5]
    }
  ]
}

1
重新分配 JSON 文件格式的版本。目前,只支持版本 1,因此这应该始终为 1。
2
指定要重新分配的分区的数组。
3
分区所属的 Kafka 主题的名称。
4
正在重新分配的分区 ID。
5
应该分配给这个分区副本的代理 ID 的排序数组。列表中的第一个代理是领导副本。
注意

未包含在 JSON 中的分区不会改变。

如果您只使用主题数组指定 主题,则分区重新分配工具会重新分配属于指定主题的所有分区。

重新分配 JSON 文件结构示例,用于重新分配主题的所有分区

{
  "version": 1,
  "topics": [
    { "topic": "my-topic"}
  ]
}

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

在 Kafka 集群中使用 JBOD 存储时,您可以在特定卷及其日志目录间重新分配分区(每个卷都有一个日志目录)。

要将分区重新分配给特定卷,请在重新分配 JSON 文件中为每个分区添加 log_dirs 值。每个 log_dirs 数组包含与 replicas 数组相同的条目数量,因为每个副本都应该分配给特定的日志目录。log_dirs 数组包含到日志目录的绝对路径或 特殊值任何 值表示 Kafka 可以为该副本选择任何可用的日志目录,这在 JBOD 卷间重新分配分区时非常有用。

使用日志目录重新分配 JSON 文件结构示例

{
  "version": 1,
  "partitions": [
    {
      "topic": "example-topic-1",
      "partition": 0,
      "replicas": [1, 2, 3]
      "log_dirs": ["/var/lib/kafka/data-0/kafka-log1", "any", "/var/lib/kafka/data-1/kafka-log2"]
    },
    {
      "topic": "example-topic-1",
      "partition": 1,
      "replicas": [2, 3, 4]
      "log_dirs": ["any",  "/var/lib/kafka/data-2/kafka-log3", "/var/lib/kafka/data-3/kafka-log4"]
    },
    {
      "topic": "example-topic-2",
      "partition": 0,
      "replicas": [3, 4, 5]
      "log_dirs": ["/var/lib/kafka/data-4/kafka-log5", "any",  "/var/lib/kafka/data-5/kafka-log6"]
    }
  ]
}

19.1.4. 分区重新分配节流

分区重新分配可能会是一个较慢的过程,因为它涉及在代理间传输大量数据。为了避免对客户端造成负面影响,您可以节流重新分配过程。使用带有 kafka-reassign-partitions.sh 工具的 --throttle 参数来节流重新分配。您可以为代理之间的分区移动指定每秒的最大阈值(以字节为单位)。例如,-- throttle 5000000 为移动 50 MBps 的分区设置最大阈值。

节流可能会导致重新分配更长的时间完成。

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

例如,对于生成者,这可能会清单高于等待确认的正常延迟。对于消费者,这可能会导致在轮询之间延迟更高的延迟导致的吞吐量下降。

19.2. 生成重新分配 JSON 文件来重新分配分区

使用 kafka-reassign-partitions.sh 工具生成重新分配 JSON 文件,以便在扩展 Kafka 集群后重新分配分区。添加或删除代理不会自动重新分发现有分区。要平衡分区分发并充分利用新代理,您可以使用 kafka-reassign-partitions.sh 工具重新分配分区。

您可以从连接到 Kafka 集群的交互式 pod 容器运行该工具。

以下流程描述了使用 mTLS 的安全重新分配过程。您需要一个使用 TLS 加密和 mTLS 身份验证的 Kafka 集群。

您需要以下内容来建立连接:

  • 当 Kafka 集群时,Cluster Operator 生成的集群 CA 证书和密钥
  • 当用户为客户端访问 Kafka 集群的用户创建时,User Operator 生成的用户 CA 证书和密钥

在此过程中,CA 证书和对应的密码会从集群和包含它们的用户 secret 中提取,这些 secret 以 PKCS #12 (.p12.password) 的格式提取。密码允许访问包含证书的 .p12 存储。您可以使用 .p12 存储来指定信任存储和密钥存储来验证与 Kafka 集群的连接。

先决条件

  • 您有一个正在运行的 Cluster Operator。
  • 您有一个基于配置了内部 TLS 加密和 mTLS 身份验证的 Kafka 资源运行 Kafka 集群。

    使用 TLS 加密和 mTLS 身份验证配置 Kafka

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        # ...
        listeners:
          # ...
          - name: tls
            port: 9093
            type: internal
            tls: true 1
            authentication:
              type: tls 2
        # ...

    1
    为内部监听程序启用 TLS 加密。
    2
    侦听器身份验证机制指定为 mutual tls
  • 正在运行的 Kafka 集群包含一组要重新分配的主题和分区。

    my-topic的主题配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: my-topic
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 10
      replicas: 3
      config:
        retention.ms: 7200000
        segment.bytes: 1073741824
        # ...

  • 有一个配置了 ACL 规则的 KafkaUser,它用于指定从 Kafka 代理生成和使用主题的权限。

    带有 ACL 规则的 Kafka 用户配置示例,允许对 my-topicmy-cluster执行操作

    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:
          # access to the topic
          - resource:
              type: topic
              name: my-topic
            operations:
              - Create
              - Describe
              - Read
              - AlterConfigs
            host: "*"
          # access to the cluster
          - resource:
              type: cluster
            operations:
              - Alter
              - AlterConfigs
            host: "*"
          # ...
      # ...

    1
    定义为 mutual tls 的用户身份验证机制。
    2
    简单的 ACL 规则授权和附带列表。

流程

  1. 从 Kafka 集群的 < cluster_name> -cluster-ca-cert secret 中提取集群 CA 证书和密钥。

    oc get secret <cluster_name>-cluster-ca-cert -o jsonpath='{.data.ca\.p12}' | base64 -d > ca.p12
    oc get secret <cluster_name>-cluster-ca-cert -o jsonpath='{.data.ca\.password}' | base64 -d > ca.password

    <cluster_name > 替换为 Kafka 集群的名称。当使用 Kafka 资源部署 Kafka 时,会使用 Kafka 集群名称(<cluster_name> -cluster-ca-cert)创建带有集群CA 证书的 secret。例如,my-cluster-cluster-ca-cert

  2. 使用 AMQ Streams Kafka 镜像运行新的交互式 pod 容器,以连接到正在运行的 Kafka 代理。

    oc run --restart=Never --image=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 <interactive_pod_name> -- /bin/sh -c "sleep 3600"

    <interactive_pod_name > 替换为 pod 的名称。

  3. 将集群 CA 证书复制到交互式 pod 容器。

    oc cp ca.p12 <interactive_pod_name>:/tmp
  4. 从具有访问 Kafka 代理权限的 Kafka 用户的 secret 中提取用户 CA 用户和密码。

    oc get secret <kafka_user> -o jsonpath='{.data.user\.p12}' | base64 -d > user.p12
    oc get secret <kafka_user> -o jsonpath='{.data.user\.password}' | base64 -d > user.password

    <kafka_user > 替换为 Kafka 用户的名称。当使用 KafkaUser 资源创建 Kafka 用户时,会使用 Kafka 用户名创建带有用户 CA 证书的 secret。例如,my-user

  5. 将用户 CA 证书复制到交互式 pod 容器。

    oc cp user.p12 <interactive_pod_name>:/tmp

    CA 证书允许交互式 pod 容器使用 TLS 连接到 Kafka 代理。

  6. 创建 config.properties 文件,以指定用于验证与 Kafka 集群的连接的信任存储和密钥存储。

    使用您在上一步中提取的证书和密码。

    bootstrap.servers=<kafka_cluster_name>-kafka-bootstrap:9093 1
    security.protocol=SSL 2
    ssl.truststore.location=/tmp/ca.p12 3
    ssl.truststore.password=<truststore_password> 4
    ssl.keystore.location=/tmp/user.p12 5
    ssl.keystore.password=<keystore_password> 6
    1
    连接到 Kafka 集群的 bootstrap 服务器地址。使用您自己的 Kafka 集群名称替换 < kafka_cluster_name>
    2
    使用 TLS 加密时的安全协议选项。
    3
    truststore 位置包含了 Kafka 集群的公钥证书 (ca.p12)。
    4
    用于访问信任存储的密码(ca.password)。
    5
    密钥存储位置包含 Kafka 用户的公钥证书(user.p12)。
    6
    用于访问密钥存储的密码(user.password)。
  7. config.properties 文件复制到交互式 pod 容器。

    oc cp config.properties <interactive_pod_name>:/tmp/config.properties
  8. 准备名为 topics.json 的 JSON 文件,以指定要移动的主题。

    将主题名称指定为用逗号分开的列表。

    重新分配 my-topic的所有分区的 JSON 文件示例

    {
      "version": 1,
      "topics": [
        { "topic": "my-topic"}
      ]
    }

    您还可以使用此文件 更改主题的复制因素

  9. topics.json 文件复制到交互式 pod 容器。

    oc cp topics.json <interactive_pod_name>:/tmp/topics.json
  10. 在交互式 pod 容器中启动 shell 进程。

    oc exec -n <namespace> -ti <interactive_pod_name> /bin/bash

    <namespace > 替换为运行 pod 的 OpenShift 命名空间。

  11. 使用 kafka-reassign-partitions.sh 命令生成重新分配 JSON。

    my-topic 分区移到指定的代理的命令示例

    bin/kafka-reassign-partitions.sh --bootstrap-server my-cluster-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --topics-to-move-json-file /tmp/topics.json \
      --broker-list 0,1,2,3,4 \
      --generate

19.3. 添加代理后重新分配分区

在增加 Kafka 集群中的代理数量后,使用 kafka-reassign-partitions.sh 工具生成的重新分配文件来重新分配分区。重新分配文件应描述如何将分区重新分配给 enlarged Kafka 集群中的代理。您可以将文件中指定的重新分配应用到代理,然后验证新分区分配。

此流程描述了使用 TLS 的安全扩展流程。您需要一个使用 TLS 加密和 mTLS 身份验证的 Kafka 集群。

kafka-reassign-partitions.sh 工具可用于重新分配 Kafka 集群中的分区,无论您是否通过集群管理所有节点,还是使用节点池预览来管理集群中的节点组。

注意

虽然您可以使用 kafka-reassign-partitions.sh 工具,但推荐对自动 分区重新分配和集群重新平衡进行 Cruise Control。Cruise Control 可以在没有任何停机时间的情况下将主题从一个代理移到另一个代理,它是重新分配分区的最有效方法。

先决条件

  • 您有一个基于配置了内部 TLS 加密和 mTLS 身份验证的 Kafka 资源运行 Kafka 集群。
  • 您已生成了一个重新分配 JSON 文件,名为 reassignment.json
  • 您正在运行连接到正在运行的 Kafka 代理的交互式 pod 容器。
  • 您作为 KafkaUser 配置有 ACL 规则,该规则指定管理 Kafka 集群及其主题的权限。

流程

  1. 通过增加 Kafka.spec.kafka.replicas 配置选项,根据需要添加任意数量的新代理。
  2. 验证新代理 pod 是否已启动。
  3. 如果没有这样做,请运行交互式 pod 容器来生成一个重新分配 JSON 文件,名为 reassignment.json
  4. reassignment.json 文件复制到交互式 pod 容器。

    oc cp reassignment.json <interactive_pod_name>:/tmp/reassignment.json

    <interactive_pod_name > 替换为 pod 的名称。

  5. 在交互式 pod 容器中启动 shell 进程。

    oc exec -n <namespace> -ti <interactive_pod_name> /bin/bash

    <namespace > 替换为运行 pod 的 OpenShift 命名空间。

  6. 使用交互式 pod 容器中的 kafka-reassign-partitions.sh 脚本运行分区重新分配。

    bin/kafka-reassign-partitions.sh --bootstrap-server
     <cluster_name>-kafka-bootstrap:9093 \
     --command-config /tmp/config.properties \
     --reassignment-json-file /tmp/reassignment.json \
     --execute

    <cluster_name > 替换为 Kafka 集群的名称。例如,my-cluster-kafka-bootstrap:9093

    如果您要节流复制,也可以使用每秒的 throttle 节流率传递 --throttle 选项。例如:

    bin/kafka-reassign-partitions.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 5000000 \
      --execute

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

    如果您需要在重新分配过程中更改节流,您可以使用具有不同节流率相同的命令。例如:

    bin/kafka-reassign-partitions.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 10000000 \
      --execute
  7. 使用任何代理 pod 的 kafka-reassign-partitions.sh 命令行工具验证重新分配是否已完成。这与上一步的命令相同,但使用 --verify 选项而不是 --execute 选项。

    bin/kafka-reassign-partitions.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --reassignment-json-file /tmp/reassignment.json \
      --verify

    --verify 命令报告正在移动的每个分区都成功完成时,重新分配已完成。最后 --verify 也会导致删除任何重新分配节流的影响。

  8. 现在,如果您保存了 JSON 以将分配恢复到其原始代理,您可以删除恢复文件。

19.4. 在删除代理前重新分配分区

在减少 Kafka 集群中的代理数量前,使用 kafka-reassign-partitions.sh 工具生成的重新分配文件来重新分配分区。重新分配文件必须描述如何将分区重新分配给 Kafka 集群中的其余代理。您可以将文件中指定的重新分配应用到代理,然后验证新分区分配。最高数字 pod 中的代理会首先被删除。

此流程描述了使用 TLS 的安全扩展流程。您需要一个使用 TLS 加密和 mTLS 身份验证的 Kafka 集群。

kafka-reassign-partitions.sh 工具可用于重新分配 Kafka 集群中的分区,无论您是否通过集群管理所有节点,还是使用节点池预览来管理集群中的节点组。

注意

虽然您可以使用 kafka-reassign-partitions.sh 工具,但推荐对自动 分区重新分配和集群重新平衡进行 Cruise Control。Cruise Control 可以在没有任何停机时间的情况下将主题从一个代理移到另一个代理,它是重新分配分区的最有效方法。

先决条件

  • 您有一个基于配置了内部 TLS 加密和 mTLS 身份验证的 Kafka 资源运行 Kafka 集群。
  • 您已生成了一个重新分配 JSON 文件,名为 reassignment.json
  • 您正在运行连接到正在运行的 Kafka 代理的交互式 pod 容器。
  • 您作为 KafkaUser 配置有 ACL 规则,该规则指定管理 Kafka 集群及其主题的权限。

流程

  1. 如果没有这样做,请运行交互式 pod 容器来生成一个重新分配 JSON 文件,名为 reassignment.json
  2. reassignment.json 文件复制到交互式 pod 容器。

    oc cp reassignment.json <interactive_pod_name>:/tmp/reassignment.json

    <interactive_pod_name > 替换为 pod 的名称。

  3. 在交互式 pod 容器中启动 shell 进程。

    oc exec -n <namespace> -ti <interactive_pod_name> /bin/bash

    <namespace > 替换为运行 pod 的 OpenShift 命名空间。

  4. 使用交互式 pod 容器中的 kafka-reassign-partitions.sh 脚本运行分区重新分配。

    bin/kafka-reassign-partitions.sh --bootstrap-server
     <cluster_name>-kafka-bootstrap:9093 \
     --command-config /tmp/config.properties \
     --reassignment-json-file /tmp/reassignment.json \
     --execute

    <cluster_name > 替换为 Kafka 集群的名称。例如,my-cluster-kafka-bootstrap:9093

    如果您要节流复制,也可以使用每秒的 throttle 节流率传递 --throttle 选项。例如:

    bin/kafka-reassign-partitions.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 5000000 \
      --execute

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

    如果您需要在重新分配过程中更改节流,您可以使用具有不同节流率相同的命令。例如:

    bin/kafka-reassign-partitions.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --reassignment-json-file /tmp/reassignment.json \
      --throttle 10000000 \
      --execute
  5. 使用任何代理 pod 的 kafka-reassign-partitions.sh 命令行工具验证重新分配是否已完成。这与上一步的命令相同,但使用 --verify 选项而不是 --execute 选项。

    bin/kafka-reassign-partitions.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --reassignment-json-file /tmp/reassignment.json \
      --verify

    --verify 命令报告正在移动的每个分区都成功完成时,重新分配已完成。最后 --verify 也会导致删除任何重新分配节流的影响。

  6. 现在,如果您保存了 JSON 以将分配恢复到其原始代理,您可以删除恢复文件。
  7. 当所有分区重新分配完成后,正在删除的代理不应负责集群中的任何分区。您可以通过检查代理的数据日志目录不包含任何实时分区日志来验证这一点。如果代理上的日志目录包含一个与扩展的正则表达式 \.[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 文件不正确。

  8. 当您确认代理没有实时分区时,您可以编辑 Kafka 资源的 Kafka.spec.kafka.replicas 属性来减少代理数量。

19.5. 更改主题的复制因素

要更改 Kafka 集群中主题的复制因素,请使用 kafka-reassign-partitions.sh 工具。这可以通过从连接到 Kafka 集群的交互式 pod 容器运行工具,并使用重新分配文件来描述主题副本是如何更改的。

此流程描述了使用 TLS 的安全进程。您需要一个使用 TLS 加密和 mTLS 身份验证的 Kafka 集群。

先决条件

  • 您有一个基于配置了内部 TLS 加密和 mTLS 身份验证的 Kafka 资源运行 Kafka 集群。
  • 您正在运行连接到正在运行的 Kafka 代理的交互式 pod 容器。
  • 您已生成了一个名为 reassignment.json 的重新分配 JSON 文件。
  • 您作为 KafkaUser 配置有 ACL 规则,该规则指定管理 Kafka 集群及其主题的权限。

请参阅 生成重新分配 JSON 文件

在此过程中,名为 my-topic 的主题有 4 个副本,我们希望将其减少到 3。名为 topics.json 的 JSON 文件指定主题,用于生成 reassignment.json 文件。

JSON 文件示例指定 my-topic

{
  "version": 1,
  "topics": [
    { "topic": "my-topic"}
  ]
}

流程

  1. 如果没有这样做,请运行交互式 pod 容器来生成一个重新分配 JSON 文件,名为 reassignment.json

    显示当前和建议的副本分配的重新分配 JSON 文件示例

    Current partition replica assignment
    {"version":1,"partitions":[{"topic":"my-topic","partition":0,"replicas":[3,4,2,0],"log_dirs":["any","any","any","any"]},{"topic":"my-topic","partition":1,"replicas":[0,2,3,1],"log_dirs":["any","any","any","any"]},{"topic":"my-topic","partition":2,"replicas":[1,3,0,4],"log_dirs":["any","any","any","any"]}]}
    
    Proposed partition reassignment configuration
    {"version":1,"partitions":[{"topic":"my-topic","partition":0,"replicas":[0,1,2,3],"log_dirs":["any","any","any","any"]},{"topic":"my-topic","partition":1,"replicas":[1,2,3,4],"log_dirs":["any","any","any","any"]},{"topic":"my-topic","partition":2,"replicas":[2,3,4,0],"log_dirs":["any","any","any","any"]}]}

    如果需要稍后恢复更改,在本地保存此文件的副本。

  2. 编辑 reassignment.json,以从每个分区中删除副本。

    例如,使用 jq 删除主题的每个分区列表中的最后一个副本:

    删除每个分区的最后一个主题副本

    jq '.partitions[].replicas |= del(.[-1])' reassignment.json > reassignment.json

    显示更新的副本的重新分配文件示例

    {"version":1,"partitions":[{"topic":"my-topic","partition":0,"replicas":[0,1,2],"log_dirs":["any","any","any","any"]},{"topic":"my-topic","partition":1,"replicas":[1,2,3],"log_dirs":["any","any","any","any"]},{"topic":"my-topic","partition":2,"replicas":[2,3,4],"log_dirs":["any","any","any","any"]}]}

  3. reassignment.json 文件复制到交互式 pod 容器。

    oc cp reassignment.json <interactive_pod_name>:/tmp/reassignment.json

    <interactive_pod_name > 替换为 pod 的名称。

  4. 在交互式 pod 容器中启动 shell 进程。

    oc exec -n <namespace> -ti <interactive_pod_name> /bin/bash

    <namespace > 替换为运行 pod 的 OpenShift 命名空间。

  5. 使用交互式 pod 容器中的 kafka-reassign-partitions.sh 脚本进行主题副本更改。

    bin/kafka-reassign-partitions.sh --bootstrap-server
     <cluster_name>-kafka-bootstrap:9093 \
     --command-config /tmp/config.properties \
     --reassignment-json-file /tmp/reassignment.json \
     --execute
    注意

    从代理中删除副本不需要任何代理数据移动,因此无需节流复制。如果要添加副本,您可能需要更改节流率。

  6. 验证对主题副本的更改是否已从任何代理 pod 使用 kafka-reassign-partitions.sh 命令行工具完成。这与上一步的命令相同,但使用 --verify 选项而不是 --execute 选项。

    bin/kafka-reassign-partitions.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --reassignment-json-file /tmp/reassignment.json \
      --verify

    --verify 命令报告正在移动的每个分区都成功完成时,重新分配已完成。最后 --verify 也会导致删除任何重新分配节流的影响。

  7. 使用 --describe 选项运行 bin/kafka-topics.sh 命令,以查看对主题的更改的结果。

    bin/kafka-topics.sh --bootstrap-server
      <cluster_name>-kafka-bootstrap:9093 \
      --command-config /tmp/config.properties \
      --describe

    减少主题副本数的结果

    my-topic  Partition: 0  Leader: 0  Replicas: 0,1,2 Isr: 0,1,2
    my-topic  Partition: 1  Leader: 2  Replicas: 1,2,3 Isr: 1,2,3
    my-topic  Partition: 2  Leader: 3  Replicas: 2,3,4 Isr: 2,3,4

第 20 章 为 AMQ Streams 设置指标和仪表板

收集指标对于了解 Kafka 部署的健康状况和性能至关重要。通过监控指标,您可以在问题变为关键前主动发现问题,并对资源分配和容量规划做出建议决策。如果没有指标数据,您可能会对 Kafka 部署的行为具有有限的可见性,这使得故障排除更困难和耗时。设置指标可节省长时间运行时和资源,并帮助确保 Kafka 部署的可靠性。

AMQ Streams 中的每个组件都提供了指标数据,从而深入了解其独立性能。虽然其他组件需要配置来公开指标暴露,但 AMQ Streams operator 默认自动公开 Prometheus 指标。这些指标包括:

  • 协调计数
  • 正在处理自定义资源数
  • 协调持续时间
  • JVM 指标

您还可以通过在 Kafka 资源的监听程序或授权配置中启用 enableMetrics 属性来收集特定于 oauth 身份验证和 opakeycloak 授权的指标。同样,您可以在自定义资源中启用 oauth 身份验证的指标,如 KafkaBridgeKafkaConnectKafkaMirrorMakerKafkaMirrorMaker2

您可以使用 Prometheus 和 Grafana 监控 AMQ Streams。当使用 Prometheus 规则配置时,Prometheus 会消耗集群中正在运行的 pod 的指标。Grafana 在仪表板中视觉化这些指标,为监控提供了一个直观的界面。

为便于指标集成,AMQ Streams 为 AMQ Streams 组件提供 Prometheus 规则和 Grafana 仪表板示例。您可以自定义 Grafana 仪表板示例以满足您的特定部署要求。您可以使用规则来定义根据特定指标触发警报的条件。

根据您的监控要求,您可以执行以下操作:

另外,您可以通过设置 分布式追踪,或使用 诊断工具 (report.sh)来检索故障排除数据,配置部署以跟踪消息端到端。

注意

AMQ Streams 为 Prometheus 和 Grafana 提供示例安装文件,它可以充当监控 AMQ Streams 部署的起点。为获得进一步的支持,请尝试与 Prometheus 和 Grafana 开发人员社区合作。

支持指标和监控工具的文档

如需有关指标和监控工具的更多信息,请参阅支持文档:

20.1. 使用 Kafka Exporter 监控消费者滞后

Kafka Exporter 是一个开源项目,用于增强对 Apache Kafka 代理和客户端的监控。您可以配置 Kafka 资源,以使用 Kafka 集群部署 Kafka 导出器。Kafka Exporter 从与偏移、消费者组、消费者滞后和主题相关的 Kafka 代理中提取额外的指标数据。例如,指标数据用于帮助识别较慢的用户。滞后数据作为 Prometheus 指标公开,然后可在 Grafana 中显示以进行分析。

Kafka Exporter 从 __consumer_offsets 主题读取,该主题存储消费者组的提交偏移信息。要使 Kafka Exporter 能够正常工作,消费者组需要正在使用。

Kafka Exporter 的 Grafana 仪表板是 AMQ Streams 提供的多个 Grafana 仪表板 之一。

重要

Kafka Exporter 仅提供与消费者滞后和消费者偏移相关的额外指标。对于常规 Kafka 指标,您必须在 Kafka 代理 中配置 Prometheus 指标。

消费者滞后表示消息的速度与消息的消耗的差别。具体来说,给定消费者组的消费者滞后指示分区中最后一个消息之间的延迟,以及当前由该消费者获取的消息之间的延迟。

lag 反映了与分区日志结束相关的消费者偏移的位置。

消费者在生成者和消费者偏移之间滞后

Consumer lag

这种差异有时被称为制作者偏移和消费者偏移之间的 delta : Kafka 代理主题分区中的读取和写入位置。

假设主题流 100 个消息。在制作者偏移(主题分区头)和最后一个偏移之间发生 1000 个消息,使用者读取的最后偏移时间为 10 秒的延迟。

监控消费者的重要性

对于依赖于实时数据的处理的应用程序,监控消费者来判断其是否不会变得太大。整个过程越好,流程从实时处理目标中得到的增长。

例如,消费者滞后可能是消耗太多的旧数据(这些数据尚未被清除)或出现计划外的关闭。

减少消费者滞后

使用 Grafana chart 分析滞后,检查操作是否减少对受影响的消费者组的影响。例如,如果对 Kafka 代理进行了调整以减少滞后,仪表板将显示 Lag by consumer group 图表下降,Messages consumed per minute 图表增加。

减少滞后的典型操作包括:

  • 通过添加新消费者来扩展消费者组
  • 增加保留时间以便消息保留在主题中
  • 添加更多磁盘容量以增加消息缓冲

减少消费者滞后的操作取决于底层基础架构和 AMQ Streams 的用例。例如,分发的消费者不太可能从其磁盘缓存中获取请求的服务从代理服务。在某些情况下,在消费者发现前,可以接受自动丢弃消息。

20.2. 监控 Cruise Control 操作

Cruise Control 监控 Kafka 代理,以跟踪代理、主题和分区的利用率。Cruise Control 还提供一组指标来监控其自身的性能。

Cruise Control 指标报告程序从 Kafka 代理收集原始指标数据。数据生成给由 Cruise Control 自动创建的主题。指标 用于为 Kafka 集群生成优化建议

Cruise Control 指标可用于对 Cruise Control 操作进行实时监控。例如,您可以使用 Cruise Control 指标来监控运行重新平衡操作的状态,或针对操作性能中检测到的任何异常情况提供警报。

您可以通过在 Cruise Control 配置中启用 Prometheus JMX Exporter 来公开 Cruise Control 指标。

注意

有关可用 Cruise Control 指标的完整列表,称为 sensors,请参阅 Cruise Control 文档

20.2.1. 监控均衡分数

Cruise Control 指标包括平衡分数。Balancedness 是在 Kafka 集群中平均分配工作负载的方法。

用于均衡分数的 Cruise Control 指标(balancedness-score)可能与 KafkaRebalance 资源中的均衡分数不同。Cruise Control 使用 aoma ly.detection.goals 计算每个分数,它可能与 KafkaRebalance 资源中使用的 default.goals 不同。a omaly.detection.goalsKafka 自定义资源的 spec.cruiseControl.config 中指定。

注意

刷新 KafkaRebalance 资源获取优化提议。如果满足以下条件之一,则会获取最新的缓存的优化建议:

  • KafkaRebalance 目标Kafka 资源的 default.goals 部分中配置的目标匹配
  • 未指定 KafkaRebalance 目标

否则,Cruise Control 会根据 KafkaRebalance 目标 生成一个新的优化建议。如果每次刷新中都会生成新的提议,这可能会影响性能监控。

20.2.2. 为异常检测设置警报

Cruise Control 的 omaly detector 提供了阻止生成优化目标(如代理故障)的条件的指标数据。如果要提高可见性,您可以使用 anomaly detector 提供的指标来设置警报并发送通知。您可以设置 Cruise Control 的 anomaly notifier,以根据这些指标通过指定的通知频道路由警报。另外,您可以设置 Prometheus 来提取 aomaly detector 提供的指标数据并生成警报。然后,Prometheus Alertmanager 可以路由 Prometheus 生成的警报。

Cruise Control 文档 提供有关 AnomalyDetector 指标和 aomaly notifier 的信息。

20.3. 指标文件示例

您可以在 AMQ Streams 提供 的示例配置文件 中找到 Grafana 仪表板和其他指标配置文件示例。

AMQ Streams 提供的指标文件示例

metrics
├── grafana-dashboards 1
│   ├── strimzi-cruise-control.json
│   ├── strimzi-kafka-bridge.json
│   ├── strimzi-kafka-connect.json
│   ├── strimzi-kafka-exporter.json
│   ├── strimzi-kafka-mirror-maker-2.json
│   ├── strimzi-kafka.json
│   ├── strimzi-operators.json
│   └── strimzi-zookeeper.json
├── grafana-install
│   └── grafana.yaml 2
├── prometheus-additional-properties
│   └── prometheus-additional.yaml 3
├── prometheus-alertmanager-config
│   └── alert-manager-config.yaml 4
├── prometheus-install
│    ├── alert-manager.yaml 5
│    ├── prometheus-rules.yaml 6
│    ├── prometheus.yaml 7
│    └── strimzi-pod-monitor.yaml 8
├── kafka-bridge-metrics.yaml 9
├── kafka-connect-metrics.yaml 10
├── kafka-cruise-control-metrics.yaml 11
├── kafka-metrics.yaml 12
└── kafka-mirror-maker-2-metrics.yaml 13

1
不同 AMQ Streams 组件的 Grafana 仪表板示例。
2
Grafana 镜像的安装文件。
3
其他配置用于提取 CPU、内存和磁盘使用的指标,这些指标直接从节点上的 OpenShift cAdvisor 代理和 kubelet 提供。
4
通过 Alertmanager 发送通知的 hook 定义。
5
用于部署和配置 Alertmanager 的资源。
6
用于 Prometheus Alertmanager 的警报规则示例(与 Prometheus 部署)。
7
Prometheus 镜像的安装资源文件。
8
PodMonitor 定义由 Prometheus Operator 转换为作业,以便 Prometheus 服务器直接从 pod 提取指标数据。
9
启用指标的 Kafka Bridge 资源。
10
为 Kafka Connect 定义 Prometheus JMX Exporter 重新标记规则的指标配置。
11
为 Cruise 控制定义 Prometheus JMX Exporter 重新标记规则的指标配置。
12
为 Kafka 和 ZooKeeper 定义 Prometheus JMX Exporter 重新标记规则的指标配置。
13
为 Kafka Mirror Maker 2.0 定义 Prometheus JMX Exporter 重新标记规则的指标配置。

20.3.1. Prometheus 指标配置示例

AMQ Streams 使用 Prometheus JMX Exporter 通过 HTTP 端点公开指标,该端点可由 Prometheus 服务器提取。

Grafana 仪表板依赖于 Prometheus JMX Exporter 重新标记规则,这些规则是为自定义资源配置中 AMQ Streams 组件定义的。

标签是一个名称值对。重新标记是动态写入标签的过程。例如,标签值可以从 Kafka 服务器和客户端 ID 的名称中派生。

AMQ Streams 提供了带有重新标记规则的自定义资源配置 YAML 文件示例。在部署 Prometheus 指标配置时,您可以部署示例自定义资源,或将指标配置复制到您自己的自定义资源定义中。

表 20.1. 带有指标配置的自定义资源示例
组件自定义资源YAML 文件示例

Kafka 和 ZooKeeper

Kafka

kafka-metrics.yaml

Kafka Connect

KafkaConnect

kafka-connect-metrics.yaml

Kafka MirrorMaker 2

KafkaMirrorMaker2

kafka-mirror-maker-2-metrics.yaml

Kafka Bridge

KafkaBridge

kafka-bridge-metrics.yaml

Sything Control

Kafka

kafka-cruise-control-metrics.yaml

20.3.2. 警报通知的 Prometheus 规则示例

由 AMQ Streams 提供的 指标配置文件 提供了警报通知的 Prometheus 规则示例。规则在示例 prometheus-rules.yaml 文件中指定,用于在 Prometheus 部署中使用

prometheus-rules.yaml 文件包含以下组件的示例规则:

  • Kafka
  • ZooKeeper
  • Entity Operator
  • Kafka Connect
  • Kafka Bridge
  • MirrorMaker
  • Kafka Exporter

文件中提供了每个示例规则的描述。

警报规则提供有关指标中观察到的特定条件的通知。规则在 Prometheus 服务器上声明,但 Prometheus Alertmanager 负责警报通知。

Prometheus 警报规则使用 PromQL 表达式来持续评估的条件。

当警报表达式变为 true 时,会满足条件,Prometheus 服务器会将警报数据发送到 Alertmanager。然后,Alertmanager 使用为部署配置的通信方法发送通知。

有关警报规则定义的一般点:

  • for 属性与规则一起使用,以确定在触发警报前必须保留条件的时间周期。
  • tick 是一个基本的 ZooKeeper 时间单元,以毫秒为单位,并使用 Kafka.spec.zookeeper.configtickTime 参数进行配置。例如,如果 ZooKeeper tickTime=3000,3 个 ticks (3 x 3000)等于 9000 毫秒。
  • ZookeeperRunningOutOfSpace 指标和警报的可用性取决于使用的 OpenShift 配置和存储实施。某些平台的存储实现可能无法提供指标提供警报所需的可用空间的信息。

Alertmanager 可以配置为使用电子邮件、天天消息或其他通知方法。根据您的具体需要,调整示例规则的默认配置。

20.3.3. Grafana 仪表板示例

如果部署 Prometheus 以提供指标,您可以使用 AMQ Streams 提供的 Grafana 仪表板示例来监控 AMQ Streams 组件。

示例仪表板在 example /metrics/grafana-dashboards 目录中作为 JSON 文件提供。

所有仪表板都提供 JVM 指标,以及特定于组件的指标。例如,AMQ Streams operator 的 Grafana 仪表板提供了它们正在处理的协调或自定义资源的数量信息。

示例仪表板没有显示 Kafka 支持的所有指标。仪表板填充了用于监控的指标集合。

表 20.2. Grafana 仪表板文件示例
组件JSON 文件示例

AMQ Streams operator

strimzi-operators.json

Kafka

strimzi-kafka.json

ZooKeeper

strimzi-zookeeper.json

Kafka Connect

strimzi-kafka-connect.json

Kafka MirrorMaker 2

strimzi-kafka-mirror-maker-2.json

Kafka Bridge

strimzi-kafka-bridge.json

Sything Control

strimzi-cruise-control.json

Kafka Exporter

strimzi-kafka-exporter.json

注意

当 Kafka Exporter 没有指标时,因为集群中还没有流量,Kafka Exporter Grafana 仪表板将显示 N/A 用于数字字段,且没有要 显示图形的数据

20.4. 通过配置启用 Prometheus 指标

要在 AMQ Streams for Prometheus 中启用和公开指标,请使用指标配置属性。

以下组件需要 metricsConfig 配置来公开指标:

  • Kafka
  • KafkaConnect
  • MirrorMaker
  • Sything Control
  • ZooKeeper

此配置可让 Prometheus JMX Exporter 通过 HTTP 端点公开指标。JMX 导出器 HTTP 端点的端口是 9404。Prometheus 提取此端点来收集 Kafka 指标。

您可以将 enableMetrics 属性设置为 true,以便为这些组件公开指标:

  • Kafka Bridge
  • OAuth 2.0 身份验证和授权框架
  • 用于授权的开放策略代理(OPA)

要在 AMQ Streams 中部署 Prometheus 指标配置,您可以使用自己的配置或 AMQ Streams 提供的示例自定义资源 配置文件

  • kafka-metrics.yaml
  • kafka-connect-metrics.yaml
  • kafka-mirror-maker-2-metrics.yaml
  • kafka-bridge-metrics.yaml
  • kafka-cruise-control-metrics.yaml
  • oauth-metrics.yaml

这些文件包含启用 Prometheus 指标所需的重新标记规则和配置。在使用 AMQ Streams 尝试 Prometheus 时,它们是很好的起点。

此流程演示了如何在 Kafka 资源中部署 Prometheus 指标配置示例。为其他资源部署示例文件时,此过程相同。

如果要包含 Kafka Exporter 指标,请在 Kafka 资源中添加 kafkaExporter 配置。

重要

Kafka Exporter 仅提供额外的与消费者滞后相关的指标。对于常规 Kafka 指标,您必须在 Kafka 代理 中配置 Prometheus 指标。

流程

  1. 使用 Prometheus 配置部署示例自定义资源。

    例如,对于每个 Kafka 资源,您可以应用 kafka-metrics.yaml 文件。

    部署示例配置

    oc apply -f kafka-metrics.yaml

    另外,您可以将 kafka-metrics.yaml 中的示例配置复制到您自己的 Kafka 资源中。

    复制示例配置

    oc edit kafka <kafka_configuration_file>

    复制 metricsConfig 属性及其引用您的 Kafka 资源的 ConfigMap

    Kafka 的指标配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      kafka:
        # ...
        metricsConfig: 1
          type: jmxPrometheusExporter
          valueFrom:
            configMapKeyRef:
              name: kafka-metrics
              key: kafka-metrics-config.yml
    ---
    kind: ConfigMap 2
    apiVersion: v1
    metadata:
      name: kafka-metrics
      labels:
        app: strimzi
    data:
      kafka-metrics-config.yml: |
      # metrics configuration...

    1
    复制 metricsConfig 属性,以引用包含指标配置的 ConfigMap。
    2
    复制指定指标配置的整个 ConfigMap
  2. 要部署 Kafka Exporter,请添加 kafkaExporter 配置。

    kafkaExporter 配置只在 Kafka 资源中指定。

    部署 Kafka Exporter 的配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
    spec:
      # ...
      kafkaExporter:
        image: my-registry.io/my-org/my-exporter-cluster:latest 1
        groupRegex: ".*" 2
        topicRegex: ".*" 3
        groupExcludeRegex: "^excluded-.*" 4
        topicExcludeRegex: "^excluded-.*" 5
        resources: 6
          requests:
            cpu: 200m
            memory: 64Mi
          limits:
            cpu: 500m
            memory: 128Mi
        logging: debug 7
        enableSaramaLogging: true 8
        template: 9
          pod:
            metadata:
              labels:
                label1: value1
            imagePullSecrets:
              - name: my-docker-credentials
            securityContext:
              runAsUser: 1000001
              fsGroup: 0
            terminationGracePeriodSeconds: 120
        readinessProbe: 10
          initialDelaySeconds: 15
          timeoutSeconds: 5
        livenessProbe: 11
          initialDelaySeconds: 15
          timeoutSeconds: 5
    # ...

    1
    ADVANCED OPTION:容器镜像配置,这只在特殊情况下建议使用。
    2
    指定指标中包含的消费者组的正则表达式。
    3
    指定指标中包含的主题的正则表达式。
    4
    指定指标中要排除的消费者组的正则表达式。
    5
    在指标中指定要排除的主题的正则表达式。
    6
    要保留的 CPU 和内存资源。
    7
    日志记录配置,以记录具有给定严重性(debug、info、warn、error、fatal)或以上的消息。
    8
    启用 Sarama 日志记录的布尔值,这是 Kafka Exporter 使用的 Go 客户端库。
    9
    自定义部署模板和 pod。
    10
    健康检查就绪度探测。
    11
    健康检查存活度探测。
注意

要使 Kafka Exporter 能够正常工作,消费者组需要使用。

为 Kafka Bridge 启用指标

要为 Kafka Bridge 公开指标,请在 KafkaBridge 资源中将 enableMetrics 属性设置为 true

Kafka Bridge 的指标配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaBridge
metadata:
  name: my-bridge
spec:
  # ...
  bootstrapServers: my-cluster-kafka:9092
  http:
    # ...
  enableMetrics: true
  # ...

为 OAuth 2.0 和 OPA 启用指标

要公开 OAuth 2.0 或 OPA 的指标,请在适当的自定义资源中将 enableMetrics 属性设置为 true

OAuth 2.0 指标

Kafka 资源中为 Kafka 集群授权和 Kafka 侦听器身份验证启用指标。

您还可以在其他 受支持组件 的自定义资源中启用 OAuth 2.0 身份验证的指标。

opa 指标
Kafka 集群授权启用指标与 OAuth 2.0 相同。

在以下示例中,为 OAuth 2.0 侦听器身份验证和 OAuth 2.0 (keycloak)集群授权启用指标。

为 OAuth 2.0 启用指标的集群配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  namespace: myproject
spec:
  kafka:
    # ...
    listeners:
    - name: external
      port: 9094
      type: loadbalancer
      tls: true
      authentication:
        type: oauth
        enableMetrics: true
      configuration:
        #...
    authorization:
      type: keycloak
      enableMetrics: true
  # ...

要将 OAuth 2.0 指标与 Prometheus 搭配使用,您可以使用 oauth-metrics.yaml 文件来部署示例 Prometheus 指标配置。将 ConfigMap 配置复制 oauth-metrics.yaml 文件包含到为 OAuth 2.0 启用指标的同一 Kafka 资源配置文件。

20.5. 查看 OpenShift 中的 Kafka 指标和仪表板

当 AMQ Streams 部署到 OpenShift Container Platform 时,通过 监控用户定义的项目提供指标。此 OpenShift 功能可让开发人员访问一个单独的 Prometheus 实例来监控自己的项目(如 Kafka 项目)。

如果启用了对用户定义的项目的监控,openshift-user-workload-monitoring 项目包含以下组件:

  • Prometheus operator
  • Prometheus 实例(由 Prometheus Operator 自动部署)
  • Thanos Ruler 实例

AMQ Streams 使用这些组件来消耗指标。

集群管理员必须为用户定义的项目启用监控,然后授予开发人员和其他用户权限来监控其自己的项目中的应用程序。

Grafana 部署

您可以将 Grafana 实例部署到包含 Kafka 集群的项目中。然后,Grafana 仪表板示例可用于在 Grafana 用户界面中视觉化 AMQ Streams 的 Prometheus 指标。

重要

openshift-monitoring 项目为核心平台组件提供监控。不要使用 此项目中的 Prometheus 和 Grafana 组件在 OpenShift Container Platform 4.x 上为 AMQ Streams 配置监控。

流程概述

要在 OpenShift Container Platform 中设置 AMQ Streams 监控,请按照以下步骤执行:

20.5.1. 先决条件

  • 已使用示例 YAML 文件 部署了 Prometheus 指标配置
  • 启用对用户定义的项目的监控。集群管理员已在 OpenShift 集群中创建了一个 cluster-monitoring-config 配置映射。
  • 集群管理员已分配了 monitoring-rules-editmonitoring-edit 角色。

有关创建 cluster-monitoring-config 配置映射并授予用户权限来监控用户定义的项目的的更多信息,请参阅 OpenShift 文档

20.5.2. 部署 Prometheus 资源

使用 Prometheus 获取 Kafka 集群中的监控数据。

您可以使用您自己的 Prometheus 部署,或使用 AMQ Streams 提供的示例指标配置文件 部署 Prometheus。要使用示例文件,请配置和部署 PodMonitor 资源。PodMonitors 直接从 Apache Kafka、Zook、Operator、Kafka Bridge 和 Cruise Control 的 pod 中提取数据。

然后,您要为 Alertmanager 部署示例警报规则。

先决条件

流程

  1. 检查是否启用了对用户定义的项目的监控:

    oc get pods -n openshift-user-workload-monitoring

    如果启用,则返回监控组件的 pod。例如:

    NAME                                   READY   STATUS    RESTARTS   AGE
    prometheus-operator-5cc59f9bc6-kgcq8   1/1     Running   0          25s
    prometheus-user-workload-0             5/5     Running   1          14s
    prometheus-user-workload-1             5/5     Running   1          14s
    thanos-ruler-user-workload-0           3/3     Running   0          14s
    thanos-ruler-user-workload-1           3/3     Running   0          14s

    如果没有返回 pod,则禁用对用户定义的项目的监控。请参阅 第 20.5 节 “查看 OpenShift 中的 Kafka 指标和仪表板” 中的先决条件。

  2. 示例/指标/prometheus-install/strimzi-pod-monitor.yaml 中定义了多个 PodMonitor 资源。

    对于每个 PodMonitor 资源,编辑 spec.namespaceSelector.matchNames 属性:

    apiVersion: monitoring.coreos.com/v1
    kind: PodMonitor
    metadata:
      name: cluster-operator-metrics
      labels:
        app: strimzi
    spec:
      selector:
        matchLabels:
          strimzi.io/kind: cluster-operator
      namespaceSelector:
        matchNames:
          - <project-name> 1
      podMetricsEndpoints:
      - path: /metrics
        port: http
    # ...
    1
    从其中提取指标的 Pod 项目,如 Kafka
  3. strimzi-pod-monitor.yaml 文件部署到运行 Kafka 集群的项目中:

    oc apply -f strimzi-pod-monitor.yaml -n MY-PROJECT
  4. 将示例 Prometheus 规则部署到同一项目中:

    oc apply -f prometheus-rules.yaml -n MY-PROJECT

20.5.3. 为 Grafana 创建服务帐户

AMQ Streams 的 Grafana 实例需要使用分配了 cluster-monitoring-view 角色的服务帐户运行。

如果使用 Grafana 呈现用于监控的指标,请创建一个服务帐户。

流程

  1. 在包含 Kafka 集群的项目中为 Grafana 创建 ServiceAccount

     oc create sa grafana-service-account -n my-project

    在本例中,在 my-project 命名空间中创建一个名为 grafana-service-account 的服务帐户。

  2. 创建一个 ClusterRoleBinding 资源,将 cluster-monitoring-view 角色分配给 Grafana ServiceAccount。此处的资源名为 grafana-cluster-monitoring-binding

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: grafana-cluster-monitoring-binding
      labels:
        app: strimzi
    subjects:
      - kind: ServiceAccount
        name: grafana-service-account
        namespace: my-project
    roleRef:
      kind: ClusterRole
      name: cluster-monitoring-view
      apiGroup: rbac.authorization.k8s.io
  3. ClusterRoleBinding 部署到同一项目中:

    oc apply -f grafana-cluster-monitoring-binding.yaml -n my-project
  4. 为服务帐户创建令牌 secret:

    apiVersion: v1
    kind: Secret
    metadata:
      name: secret-sa
      annotations:
        kubernetes.io/service-account.name: "grafana-service-account" 1
    type: kubernetes.io/service-account-token 2
    1
    指定服务帐户。
    2
    指定服务帐户令牌 secret。
  5. 创建 Secret 对象和访问令牌:

    oc create -f <secret_configuration>.yaml

    部署 Grafana 时需要访问令牌。

20.5.4. 使用 Prometheus 数据源部署 Grafana

部署 Grafana 以提供 Prometheus 指标。Grafana 应用程序需要配置 OpenShift Container Platform 监控堆栈。

OpenShift Container Platform 在 openshift-monitoring 项目中包括 Thanos Querier 实例。Thanos Querier 用于聚合平台指标。

要使用所需的平台指标,Grafana 实例需要一个可以连接到 Thanos Querier 的 Prometheus 数据源。要配置此连接,您需要创建一个配置映射来验证(使用令牌)到与 Thanos Querier 一起运行的 oauth-proxy sidecar。数据源.yaml 文件用作配置映射的来源。

最后,您可以使用作为卷挂载到包含 Kafka 集群的项目中的配置映射来部署 Grafana 应用程序。

流程

  1. 获取 Grafana ServiceAccount 的访问令牌:

    oc describe sa/grafana-service-account | grep Tokens:
    oc describe secret grafana-service-account-token-mmlp9 | grep token:

    在本例中,服务帐户名为 grafana-service-account。复制要在下一步中使用的访问令牌。

  2. 创建包含 Grafana 的 Thanos Querier 配置的 datasource.yaml 文件。

    将访问令牌粘贴到 httpHeaderValue1 属性中,如下所示。

    apiVersion: 1
    
    datasources:
    - name: Prometheus
      type: prometheus
      url: https://thanos-querier.openshift-monitoring.svc.cluster.local:9091
      access: proxy
      basicAuth: false
      withCredentials: false
      isDefault: true
      jsonData:
        timeInterval: 5s
        tlsSkipVerify: true
        httpHeaderName1: "Authorization"
      secureJsonData:
        httpHeaderValue1: "Bearer ${GRAFANA-ACCESS-TOKEN}" 1
      editable: true
    1
    GRAFANA-ACCESS-TOKEN :Grafras ServiceAccount 的访问令牌值。
  3. datasource.yaml 文件中创建一个名为 grafana-config 的配置映射:

    oc create configmap grafana-config --from-file=datasource.yaml -n MY-PROJECT
  4. 创建由 DeploymentService 组成的 Grafana 应用程序。

    grafana-config 配置映射作为数据源配置的卷挂载。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: grafana
      labels:
        app: strimzi
    spec:
      replicas: 1
      selector:
        matchLabels:
          name: grafana
      template:
        metadata:
          labels:
            name: grafana
        spec:
          serviceAccountName: grafana-service-account
          containers:
          - name: grafana
            image: grafana/grafana:10.0.3
            ports:
            - name: grafana
              containerPort: 3000
              protocol: TCP
            volumeMounts:
            - name: grafana-data
              mountPath: /var/lib/grafana
            - name: grafana-logs
              mountPath: /var/log/grafana
            - name: grafana-config
              mountPath: /etc/grafana/provisioning/datasources/datasource.yaml
              readOnly: true
              subPath: datasource.yaml
            readinessProbe:
              httpGet:
                path: /api/health
                port: 3000
              initialDelaySeconds: 5
              periodSeconds: 10
            livenessProbe:
              httpGet:
                path: /api/health
                port: 3000
              initialDelaySeconds: 15
              periodSeconds: 20
          volumes:
          - name: grafana-data
            emptyDir: {}
          - name: grafana-logs
            emptyDir: {}
          - name: grafana-config
            configMap:
              name: grafana-config
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: grafana
      labels:
        app: strimzi
    spec:
      ports:
      - name: grafana
        port: 3000
        targetPort: 3000
        protocol: TCP
      selector:
        name: grafana
      type: ClusterIP
  5. 将 Grafana 应用程序部署到包含 Kafka 集群的项目中:

    oc apply -f <grafana-application> -n <my-project>

20.5.5. 创建到 Grafana 服务的路由

您可以通过公开 Grafana 服务的路由来访问 Grafana 用户界面。

流程

  • 创建到 grafana 服务的边缘路由:

    oc create route edge <my-grafana-route> --service=grafana --namespace=KAFKA-NAMESPACE

20.5.6. 导入 Grafana 仪表板示例

使用 Grafana 在可自定义仪表板上提供 Prometheus 指标的视觉化。

AMQ Streams 以 JSON 格式为 Grafana 提供示例仪表板配置文件

  • examples/metrics/grafana-dashboards

此流程使用 Grafana 仪表板示例。

示例仪表板是监控关键指标的一个良好起点,但它们不显示 Kafka 支持的所有指标。您可以根据基础架构修改示例仪表板或添加其他指标。

流程

  1. 获取到 Grafana 服务的路由详情。例如:

    oc get routes
    
    NAME               HOST/PORT                         PATH  SERVICES
    MY-GRAFANA-ROUTE   MY-GRAFANA-ROUTE-amq-streams.net        grafana
  2. 在 Web 浏览器中,使用 Route 主机和端口的 URL 访问 Grafana 登录屏幕。
  3. 输入您的用户名和密码,然后单击 Log In

    默认的 Grafana 用户名和密码都是 admin。第一次登录后,您可以更改密码。

  4. Configuration > Data Sources 中,检查 Prometheus 数据源是否已创建。数据源在 第 20.5.4 节 “使用 Prometheus 数据源部署 Grafana” 中创建。
  5. + 图标,然后点 Import
  6. examples/metrics/grafana-dashboards 中,复制要导入的仪表板的 JSON。
  7. 将 JSON 粘贴到文本框中,然后点 Load
  8. 为其他 Grafana 仪表板重复步骤 5-7。

Dashboards 主页中查看导入的 Grafana 仪表板。

第 21 章 分布式追踪简介

分布式追踪跟踪分布式系统中应用程序之间的事务进度。在微服务架构中,追踪跟踪服务间的事务进度。跟踪数据可用于监控应用程序性能和调查目标系统和最终用户应用的问题。

在 AMQ Streams 中,追踪有助于对消息的端到端跟踪:从源系统到 Kafka,然后从 Kafka 到目标系统和应用程序。分布式追踪补充了 Grafana 仪表板中的指标的监控,以及组件日志记录器。

以下 Kafka 组件内置了对追踪的支持:

  • MirrorMaker 将来自源集群的信息追踪到目标集群
  • Kafka 连接到由 Kafka Connect 使用和生成的 trace 信息
  • Kafka Bridge 用来跟踪 Kafka 和 HTTP 客户端应用程序之间的信息

Kafka 代理不支持追踪。

您可以通过其自定义资源为这些组件启用和配置追踪。您可以使用 spec.template 属性添加追踪配置。

您可以使用 spec.tracing.type 属性指定追踪类型来启用追踪:

OpenTelemetry
指定 type: opentelemetry 以使用 OpenTelemetry。默认情况下,OpenTelemetry 使用 OTLP (OpenTelemetry 协议)导出器和端点来获取追踪数据。您可以指定 OpenTelemetry 支持的其他追踪系统,包括 Jaeger 追踪。要做到这一点,您可以在追踪配置中更改 OpenTelemetry exporter 和端点。
jaeger
指定 type:jaeger 来使用 OpenTracing 和 Jaeger 客户端来获取 trace 数据。
注意

type: jaeger tracing 的支持已被弃用。Jaeger 客户端现已停用,OpenTracing 项目存档。因此,我们不能保证其对将来的 Kafka 版本的支持。如果可能,我们将保持对 type: jaeger tracing 的支持,直到 2023 年 6 月为止。请尽快迁移到 OpenTelemetry。

21.1. 追踪选项

在 Jaeger 追踪系统中使用 OpenTelemetry 或 OpenTracing (已弃用)。

OpenTelemetry 和 OpenTracing 提供独立于追踪或监控系统的 API 规格。

您可以使用 API 检测应用程序代码以进行追踪。

  • 检测的应用程序会为跨分布式系统的单个请求生成 trace
  • trace 由定义特定工作单元的 span 组成。

Jaeger 是基于微服务的分布式系统的追踪系统。

  • Jaeger 实现追踪 API,并为工具提供客户端库。
  • Jaeger 用户界面允许您查询、过滤和分析 trace 数据。

Jaeger 用户界面显示一个简单的查询

The Jaeger user interface showing a simple query

21.2. 用于追踪的环境变量

当您为 Kafka 组件启用追踪或为 Kafka 客户端初始化 tracer 时,请使用环境变量。

追踪环境变量可能会改变。有关最新信息,请参阅 OpenTelemetry 文档OpenTracing 文档

下表描述了设置 tracer 的关键环境变量。

表 21.1. OpenTelemetry 环境变量
属性必需Description

OTEL_SERVICE_NAME

OpenTelemetry 的 Jaeger tracing 服务的名称。

OTEL_EXPORTER_JAEGER_ENDPOINT

用于追踪的导出器。

OTEL_TRACES_EXPORTER

用于追踪的导出器。默认设置为 otlp。如果使用 Jaeger 追踪,则需要将此环境变量设置为 jaeger。如果您使用另一个追踪实施,请指定使用的导出器

表 21.2. OpenTracing 环境变量
属性必需Description

JAEGER_SERVICE_NAME

Jaeger tracer 服务的名称。

JAEGER_AGENT_HOST

通过用户数据报协议(UDP)与 jaeger-agent 通信的主机名。

JAEGER_AGENT_PORT

用于通过 UDP 与 jaeger-agent 通信的端口。

21.3. 设置分布式追踪

通过在自定义资源中指定追踪类型,在 Kafka 组件中启用分布式追踪。在 Kafka 客户端中检测追踪程序,以便端到端跟踪消息。

要设置分布式追踪,请按照以下步骤执行:

21.3.1. 先决条件

在设置分布式追踪前,请确保将 Jaeger 后端组件部署到 OpenShift 集群中。我们建议使用 Jaeger operator 在 OpenShift 集群上部署 Jaeger。

有关部署说明,请参阅 Jaeger 文档

注意

为 AMQ Streams 以外的应用程序和系统设置追踪不在此内容范围内。

21.3.2. 在 MirrorMaker、Kafka Connect 和 Kafka Bridge 资源中启用追踪

MirrorMaker、M MirrorMaker 2、Kafka Connect 和 AMQ Streams Kafka Bridge 支持分布式追踪。配置组件的自定义资源,以指定并启用 tracer 服务。

在资源中启用追踪会触发以下事件:

  • 拦截器类在组件的集成消费者和制作者中更新。
  • 对于 MirrorMaker、M MirrorMaker 2 和 Kafka Connect,追踪代理根据资源中定义的追踪配置初始化 tracer。
  • 对于 Kafka Bridge,基于资源中定义的追踪配置的 tracer 由 Kafka Bridge 本身初始化。

您可以启用使用 OpenTelemetry 或 OpenTracing 的追踪。

MirrorMaker 和 MirrorMaker 2 中的追踪

对于 MirrorMaker 和 MirrorMaker 2,消息从源集群追踪到目标集群。跟踪数据记录消息输入和离开 MirrorMaker 或 MirrorMaker 2 组件。

Kafka Connect 中的追踪

对于 Kafka Connect,只有 Kafka Connect 生成和使用的消息才会被跟踪。要跟踪 Kafka Connect 和外部系统之间发送的消息,您必须在连接器中为这些系统配置追踪。

Kafka Bridge 中的追踪

对于 Kafka Bridge,由 Kafka Bridge 生成和使用的消息会被跟踪。也可以跟踪来自客户端应用程序的传入 HTTP 请求,以通过 Kafka Bridge 发送和接收信息。要获得端到端追踪,您必须在 HTTP 客户端中配置追踪。

流程

为每个 KafkaMirrorMakerKafkaMirrorMaker2、 KafkaConnectKafkaBridge 资源执行这些步骤。

  1. spec.template 属性中,配置 tracer 服务。

    • 使用追踪环境变量作为模板配置属性。
    • 对于 OpenTelemetry,将 spec.tracing.type 属性设置为 opentelemetry
    • 对于 OpenTracing,将 spec.tracing.type 属性设置为 jaeger

    使用 OpenTelemetry 的 Kafka Connect 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect-cluster
    spec:
      #...
      template:
        connectContainer:
          env:
            - name: OTEL_SERVICE_NAME
              value: my-otel-service
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://otlp-host:4317"
      tracing:
        type: opentelemetry
      #...

    使用 OpenTelemetry 的 MirrorMaker 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker
    metadata:
      name: my-mirror-maker
    spec:
      #...
      template:
        mirrorMakerContainer:
          env:
            - name: OTEL_SERVICE_NAME
              value: my-otel-service
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://otlp-host:4317"
      tracing:
        type: opentelemetry
    #...

    使用 OpenTelemetry 的 MirrorMaker 2 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker2
    metadata:
      name: my-mm2-cluster
    spec:
      #...
      template:
        connectContainer:
          env:
            - name: OTEL_SERVICE_NAME
              value: my-otel-service
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://otlp-host:4317"
      tracing:
        type: opentelemetry
    #...

    使用 OpenTelemetry 的 Kafka Bridge 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaBridge
    metadata:
      name: my-bridge
    spec:
      #...
      template:
        bridgeContainer:
          env:
            - name: OTEL_SERVICE_NAME
              value: my-otel-service
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://otlp-host:4317"
      tracing:
        type: opentelemetry
    #...

    使用 OpenTracing 的 Kafka Connect 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      name: my-connect-cluster
    spec:
      #...
      template:
        connectContainer:
          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
      #...

    使用 OpenTracing 的 MirrorMaker 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker
    metadata:
      name: my-mirror-maker
    spec:
      #...
      template:
        mirrorMakerContainer:
          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
    #...

    使用 OpenTracing 的 MirrorMaker 2 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker2
    metadata:
      name: my-mm2-cluster
    spec:
      #...
      template:
        connectContainer:
          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
    #...

    使用 OpenTracing 的 Kafka Bridge 的追踪配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaBridge
    metadata:
      name: my-bridge
    spec:
      #...
      template:
        bridgeContainer:
          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
    #...

  2. 创建或更新资源:

    oc apply -f <resource_configuration_file>

21.3.3. 为 Kafka 客户端初始化追踪

初始化 tracer,然后检测您的客户端应用程序以进行分布式追踪。您可以检测 Kafka producer 和使用者客户端,以及 Kafka Streams API 应用程序。您可以为 OpenTracing 或 OpenTelemetry 初始化 tracer。

使用一组 追踪环境变量 配置和初始化 tracer。

流程

在每个客户端应用程序中,为 tracer 添加依赖项:

  1. 将 Maven 依赖项添加到客户端应用程序的 pom.xml 文件中:

    OpenTelemetry 的依赖项

    <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
        <version>1.19.0.redhat-00002</version>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry.instrumentation</groupId>
      <artifactId>opentelemetry-kafka-clients-{OpenTelemetryKafkaClient}</artifactId>
      <version>1.19.0.redhat-00002</version>
    </dependency>
    <dependency>
      <groupId>io.opentelemetry</groupId>
      <artifactId>opentelemetry-exporter-otlp</artifactId>
      <version>1.19.0.redhat-00002</version>
    </dependency>

    OpenTracing 的依赖项

    <dependency>
        <groupId>io.jaegertracing</groupId>
        <artifactId>jaeger-client</artifactId>
        <version>1.8.1.redhat-00002</version>
    </dependency>
    <dependency>
      <groupId>io.opentracing.contrib</groupId>
      <artifactId>opentracing-kafka-client</artifactId>
      <version>0.1.15.redhat-00006</version>
    </dependency>

  2. 使用追踪环境变量定义 tracer 的配置。
  3. 创建一个 tracer,它使用环境变量初始化:

    为 OpenTelemetry 创建 tracer

    OpenTelemetry ot = GlobalOpenTelemetry.get();

    为 OpenTracing 创建 tracer

    Tracer tracer = Configuration.fromEnv().getTracer();

  4. 将 tracer 注册为全局 tracer:

    GlobalTracer.register(tracer);
  5. 检测您的客户端:

21.3.4. 检测用于追踪的生产者和消费者

检测应用程序代码,以在 Kafka 生成者和消费者中启用追踪。使用 decorator 模式或拦截器检测您的 Java 生成者和消费者应用程序代码以进行追踪。然后,您可以在生成或从主题检索信息时记录 trace。

OpenTelemetry 和 OpenTracing 检测项目提供支持生产者和消费者的类。

decorator 检测
对于 decorator 检测,请创建一个修改后的制作者或消费者实例以进行追踪。decorator 检测在 OpenTelemetry 和 OpenTracing 中有所不同。
拦截器检测
对于拦截器工具,请在消费者或制作者配置中添加追踪功能。OpenTelemetry 和 OpenTracing 的拦截器工具是相同的。

先决条件

  • 您已为 客户端初始化了追踪

    您可以通过在项目中添加追踪 JAR 作为依赖项来启用生成者和消费者应用中的检测。

流程

在每个制作者和消费者应用的应用程序代码中执行这些步骤。使用 decorator 模式或拦截器(拦截器)检测您的客户端应用程序代码。

  • 要使用 decorator 模式,请创建一个修改后的制作者或消费者实例来发送或接收消息。

    您传递了原始 KafkaProducerKafkaConsumer 类。

    OpenTelemetry 的 decorator 检测示例

    // Producer instance
    Producer < String, String > op = new KafkaProducer < > (
        configs,
        new StringSerializer(),
        new StringSerializer()
        );
        Producer < String, String > producer = tracing.wrap(op);
    KafkaTracing tracing = KafkaTracing.create(GlobalOpenTelemetry.get());
    producer.send(...);
    
    //consumer instance
    Consumer<String, String> oc = new KafkaConsumer<>(
        configs,
        new StringDeserializer(),
        new StringDeserializer()
        );
        Consumer<String, String> consumer = tracing.wrap(oc);
    consumer.subscribe(Collections.singleton("mytopic"));
    ConsumerRecords<Integer, String> records = consumer.poll(1000);
    ConsumerRecord<Integer, String> record = ...
    SpanContext spanContext = TracingKafkaUtils.extractSpanContext(record.headers(), tracer);

    OpenTracing 的 decorator 检测示例

    //producer instance
    KafkaProducer<Integer, String> producer = new KafkaProducer<>(senderProps);
    TracingKafkaProducer<Integer, String> tracingProducer = new TracingKafkaProducer<>(producer, tracer);
    TracingKafkaProducer.send(...)
    
    //consumer instance
    KafkaConsumer<Integer, String> consumer = new KafkaConsumer<>(consumerProps);
    TracingKafkaConsumer<Integer, String> tracingConsumer = new TracingKafkaConsumer<>(consumer, tracer);
    tracingConsumer.subscribe(Collections.singletonList("mytopic"));
    ConsumerRecords<Integer, String> records = tracingConsumer.poll(1000);
    ConsumerRecord<Integer, String> record = ...
    SpanContext spanContext = TracingKafkaUtils.extractSpanContext(record.headers(), tracer);

  • 要使用拦截器,请在制作者或消费者配置中设置拦截器类。

    您以通常的方式使用 KafkaProducerKafkaConsumer 类。TracingProducerInterceptorTracingConsumerInterceptor interceptor 类负责追踪功能。

    使用拦截器的制作者配置示例

    senderProps.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG,
        TracingProducerInterceptor.class.getName());
    
    KafkaProducer<Integer, String> producer = new KafkaProducer<>(senderProps);
    producer.send(...);

    使用拦截器的消费者配置示例

    consumerProps.put(ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG,
        TracingConsumerInterceptor.class.getName());
    
    KafkaConsumer<Integer, String> consumer = new KafkaConsumer<>(consumerProps);
    consumer.subscribe(Collections.singletonList("messages"));
    ConsumerRecords<Integer, String> records = consumer.poll(1000);
    ConsumerRecord<Integer, String> record = ...
    SpanContext spanContext = TracingKafkaUtils.extractSpanContext(record.headers(), tracer);

21.3.5. 检测用于追踪的 Kafka Streams 应用程序

检测应用程序代码,以在 Kafka Streams API 应用程序中启用追踪。使用 decorator 模式或拦截器检测 Kafka Streams API 应用程序以进行追踪。然后,您可以在生成或从主题检索信息时记录 trace。

decorator 检测
对于 decorator 检测,请创建一个修改后的 Kafka Streams 实例以进行追踪。OpenTracing 检测项目提供了一个 TracingKafkaClientSupplier 类,它支持 Kafka Streams 的检测。您可以创建一个 TracingKafkaClientSupplier 供应商接口的嵌套实例,它为 Kafka Streams 提供追踪工具。对于 OpenTelemetry,该过程相同,但您需要创建自定义 TracingKafkaClientSupplier 类来提供支持。
拦截器检测
对于拦截器工具,在 Kafka Streams producer 和 consumer 配置中添加追踪功能。

先决条件

  • 您已为 客户端初始化了追踪

    您可以通过在项目中添加追踪 JAR 作为依赖项来启用 Kafka Streams 应用程序中的检测。

  • 要使用 OpenTelemetry 检测 Kafka Streams,您需要编写自定义 TracingKafkaClientSupplier
  • 自定义 TracingKafkaClientSupplier 可以扩展 Kafka 的 DefaultKafkaClientSupplier,覆盖生成者和消费者创建方法,将实例嵌套与遥测相关的代码。

    自定义 TracingKafkaClientSupplier 示例

    private class TracingKafkaClientSupplier extends DefaultKafkaClientSupplier {
        @Override
        public Producer<byte[], byte[]> getProducer(Map<String, Object> config) {
            KafkaTelemetry telemetry = KafkaTelemetry.create(GlobalOpenTelemetry.get());
            return telemetry.wrap(super.getProducer(config));
        }
    
        @Override
        public Consumer<byte[], byte[]> getConsumer(Map<String, Object> config) {
            KafkaTelemetry telemetry = KafkaTelemetry.create(GlobalOpenTelemetry.get());
            return telemetry.wrap(super.getConsumer(config));
        }
    
        @Override
        public Consumer<byte[], byte[]> getRestoreConsumer(Map<String, Object> config) {
            return this.getConsumer(config);
        }
    
        @Override
        public Consumer<byte[], byte[]> getGlobalConsumer(Map<String, Object> config) {
            return this.getConsumer(config);
        }
    }

流程

为每个 Kafka Streams API 应用程序执行这些步骤。

  • 要使用 decorator 模式,请创建一个 TracingKafkaClientSupplier 供应商接口的实例,然后向 KafkaStreams 提供供应商接口。

    decorator 检测示例

    KafkaClientSupplier supplier = new TracingKafkaClientSupplier(tracer);
    KafkaStreams streams = new KafkaStreams(builder.build(), new StreamsConfig(config), supplier);
    streams.start();

  • 要使用拦截器,请在 Kafka Streams producer 和消费者配置中设置拦截器类。

    TracingProducerInterceptorTracingConsumerInterceptor interceptor 类负责追踪功能。

    使用拦截器的制作者和消费者配置示例

    props.put(StreamsConfig.PRODUCER_PREFIX + ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName());
    props.put(StreamsConfig.CONSUMER_PREFIX + ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName());

21.3.6. 引入了不同的 OpenTelemetry 追踪系统

您可以指定 OpenTelemetry 支持的其他追踪系统,而不是默认的 OTLP 系统。您可以通过在 AMQ Streams 提供的 Kafka 镜像中添加所需的工件来实现此目的。还必须设置任何所需的实现特定环境变量。然后,您可以使用 OTEL_TRACES_EXPORTER 环境变量启用新的追踪实施。

此流程演示了如何实施 Zipkin tracing。

流程

  1. 将追踪工件添加到 AMQ Streams Kafka 镜像的 /opt/kafka/libs/ 目录中。

    您可以使用 Red Hat Ecosystem Catalog 上的 Kafka 容器镜像作为基础镜像来创建新的自定义镜像。

    Zipkin 的 OpenTelemetry 工件

    io.opentelemetry:opentelemetry-exporter-zipkin

  2. 为新的追踪实施设置追踪导出器和端点。

    Zikpin tracer 配置示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaMirrorMaker2
    metadata:
      name: my-mm2-cluster
    spec:
      #...
      template:
        connectContainer:
          env:
            - name: OTEL_SERVICE_NAME
              value: my-zipkin-service
            - name: OTEL_EXPORTER_ZIPKIN_ENDPOINT
              value: http://zipkin-exporter-host-name:9411/api/v2/spans 1
            - name: OTEL_TRACES_EXPORTER
              value: zipkin 2
      tracing:
        type: opentelemetry
    #...

    1
    指定要连接的 Zipkin 端点。
    2
    Zipkin 导出器。

21.3.7. 自定义范围名称

追踪 span 是 Jaeger 中的逻辑工作单元,包括操作名称、开始时间和持续时间。span 具有内置名称,但您可以在使用的 Kafka 客户端检测中指定自定义范围名称。

指定自定义范围名称是可选的,只有在生成者和消费者客户端检测Kafka Streams 检测中使用 decorator 模式时才适用。

21.3.7.1. 为 OpenTelemetry 指定范围名称

无法使用 OpenTelemetry 直接指定自定义范围名称。相反,您可以通过向客户端应用程序添加代码来提取额外的标签和属性来检索范围名称。

提取属性的代码示例

//Defines attribute extraction for a producer
private static class ProducerAttribExtractor implements AttributesExtractor < ProducerRecord < ? , ? > , Void > {
    @Override
    public void onStart(AttributesBuilder attributes, ProducerRecord < ? , ? > producerRecord) {
        set(attributes, AttributeKey.stringKey("prod_start"), "prod1");
    }
    @Override
    public void onEnd(AttributesBuilder attributes, ProducerRecord < ? , ? > producerRecord, @Nullable Void unused, @Nullable Throwable error) {
        set(attributes, AttributeKey.stringKey("prod_end"), "prod2");
    }
}
//Defines attribute extraction for a consumer
private static class ConsumerAttribExtractor implements AttributesExtractor < ConsumerRecord < ? , ? > , Void > {
    @Override
    public void onStart(AttributesBuilder attributes, ConsumerRecord < ? , ? > producerRecord) {
        set(attributes, AttributeKey.stringKey("con_start"), "con1");
    }
    @Override
    public void onEnd(AttributesBuilder attributes, ConsumerRecord < ? , ? > producerRecord, @Nullable Void unused, @Nullable Throwable error) {
        set(attributes, AttributeKey.stringKey("con_end"), "con2");
    }
}
//Extracts the attributes
public static void main(String[] args) throws Exception {
        Map < String, Object > configs = new HashMap < > (Collections.singletonMap(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"));
        System.setProperty("otel.traces.exporter", "jaeger");
        System.setProperty("otel.service.name", "myapp1");
        KafkaTracing tracing = KafkaTracing.newBuilder(GlobalOpenTelemetry.get())
            .addProducerAttributesExtractors(new ProducerAttribExtractor())
            .addConsumerAttributesExtractors(new ConsumerAttribExtractor())
            .build();

21.3.7.2. 为 OpenTracing 指定范围名称

要为 OpenTracing 指定自定义范围名称,请在检测生产者和消费者时将 BiFunction 对象作为参数传递。

有关内置名称和指定自定义范围名称以检测客户端应用代码的更多信息,请参阅 OpenTracing Apache Kafka 客户端检测

第 22 章 检索诊断和故障排除数据

report.sh 诊断工具是由红帽提供的脚本,用于收集 OpenShift 上 AMQ Streams 部署故障排除的基本数据。它收集相关的日志、配置文件和其他诊断数据,以帮助识别和解决问题。运行脚本时,您可以指定额外的参数来检索特定数据。

先决条件

  • Bash 4 或更新版本
  • OpenShift oc 命令行工具已安装并配置为连接到正在运行的集群。

这会为 oc 命令行工具建立必要的身份验证,以与集群交互并检索所需的诊断数据。

流程

  1. 下载并提取工具。

    诊断工具可从 AMQ Streams 软件下载页面 获得。

  2. 在提取工具的目录中打开一个终端并运行报告工具:

    ./report.sh --namespace=<cluster_namespace> --cluster=<cluster_name> --out-dir=<local_output_directory>

    <cluster_namespace > 替换为 AMQ Streams 部署的实际 OpenShift 命名空间,< cluster_name > 替换为 Kafka 集群的名称,&lt ;local_output_directory > 替换为您要保存生成的报告的本地目录的路径。如果您没有指定目录,则会创建一个临时目录。

    根据需要包括其他可选报告选项:

    --bridge=<string>
    指定 Kafka Bridge 集群的名称,以获取其 pod 和日志上的数据。
    --connect=<string>
    指定 Kafka Connect 集群的名称,以获取其 pod 和日志上的数据。
    --mm2=<string>
    指定 Mirror Maker 2 集群名称,以获取其 pod 和日志的数据。
    --secrets=(off|hidden|all)

    指定 secret 详细程度。默认为 hidden。可用的选项如下:

    • 所有: 报告 Secret 密钥和数据值。
    • hidden :仅报告带有密钥的 Secret。数据值(如密码)会被删除。
    • off :不会报告 Secret。

    使用数据收集选项的请求示例

    ./report.sh --namespace=my-amq-streams-namespace --cluster=my-kafka-cluster --bridge=my-bridge-component --secrets=all --out-dir=~/reports

    注意

    如果需要,使用 chmod 命令将脚本的执行权限分配给您的用户。例如: chmod +x report.sh.

执行完脚本后,输出目录包含为 AMQ Streams 部署的每个组件收集的日志、配置和其他诊断数据的文件和目录。

报告诊断工具收集的数据

如果存在,则返回以下组件中的数据:

Cluster Operator

  • 部署 YAML 和日志
  • 所有相关 pod 及其日志
  • 与集群操作器相关的资源的 YAML 文件(ClusterRoles、ClusterRoleBindings)

drain Cleaner (如果存在)

  • 部署 YAML 和日志
  • Pod 日志

自定义资源

  • 自定义资源定义(CRD) YAML
  • 所有相关自定义资源(CR)的 YAML 文件

事件

  • 与指定命名空间相关的事件

配置

  • Kafka pod 日志和配置文件(strimzi.properties)
  • ZooKeeper pod 日志和配置文件(zookeeper.properties)
  • Entity Operator (Topic Operator, User Operator) pod 日志
  • Cruise Control pod 日志
  • Kafka Exporter pod 日志
  • 如果在选项中指定,网桥 pod 日志
  • 如果在选项中指定,请连接 pod 日志
  • 如果在选项中指定,MirrorMaker 2 pod 日志

secret (如果在选项中请求)

  • 与指定 Kafka 集群相关的所有 secret 的 YAML 文件

第 23 章 升级 AMQ Streams

将 AMQ Streams 安装升级到 2.5 版本,并从新功能、性能改进和增强的安全选项中受益。在升级过程中,Kafka 也更新至最新支持的版本,为 AMQ Streams 部署引入了额外的功能和程序错误修复。

如果您在新版本时遇到问题,AMQ Streams 可以 降级到 之前的版本。

发布的 AMQ Streams 版本可在 AMQ Streams 软件下载页面 中找到。

在不停机的情况下升级

对于配置了高可用性(至少 3 个和平均分布式分区)的主题,升级过程不应给消费者和生产者造成任何停机时间。

升级会触发滚动更新,其中代理会在进程的不同阶段重启一个。在这个时间内,整个集群可用性会临时减少,这可能会在代理失败时增加消息丢失的风险。

23.1. AMQ Streams 升级路径

AMQ Streams 提供了两个升级路径。

增量升级
增量升级涉及将 AMQ Streams 从以前的次版本升级到 2.5 版本。
多版本升级
多版本升级涉及将旧版本的 AMQ Streams 升级到单个升级中的 2.5 版本,跳过一个或多个中间版本。例如,可以直接从 AMQ Streams 2.3 升级到 AMQ Streams 2.5。

23.1.1. 升级时支持 Kafka 版本

升级 AMQ Streams 时,务必要确保与所使用的 Kafka 版本兼容非常重要。

即使支持的 Kafka 版本在旧版本和新版本之间有所不同,也可以进行多版本升级。但是,如果您试图升级到不支持当前 Kafka 版本的新 AMQ Streams 版本,则会出现 没有支持 Kafka 版本的错误。在这种情况下,您必须把 Kafka 自定义资源中的 spec.kafka.version 更改为新的 AMQ Streams 版本,将 Kafka Streams 升级的一部分升级为 AMQ Streams 升级的一部分。

  • Kafka 3.5.0 支持在生产环境中使用。
  • Kafka 3.4.0 仅支持升级到 AMQ Streams 2.5。

23.1.2. 从 1.7 更早的 AMQ Streams 版本升级

如果您要从 1.7 版本之前的版本升级到 AMQ Streams 的最新版本,请执行以下操作:

  1. 按照标准序列 将 AMQ Streams 升级到 1.7 版本。
  2. 使用 AMQ Streams 提供的 API 转换工具 将 AMQ Streams 自定义资源转换为 v1beta2
  3. 执行以下操作之一:

    • 升级到 AMQ Streams 1.8 (默认禁用 ControlPlaneListener 功能门)。
    • 升级到 AMQ Streams 2.0 或 2.2 (其中默认启用 ControlPlaneListener 功能门),并禁用了 ControlPlaneListener 功能门。
  4. 启用 ControlPlaneListener 功能门。
  5. 根据 标准序列 升级到 AMQ Streams 2.5。

AMQ Streams 自定义资源使用 1.7 版中的 v1beta2 API 版本启动。在升级到 AMQ Streams 1.8 或更高版本 ,必须转换 CRD 和自定义资源。有关使用 API 转换工具的详情,请参考 AMQ Streams 1.7 升级文档

注意

作为首次升级到 1.7 版本的替代选择,您可以从 1.7 安装自定义资源,然后转换资源。

现在,AMQ Streams 中永久启用了 ControlPlaneListener 功能。您必须升级到禁用的 AMQ Streams 版本,然后使用 Cluster Operator 配置中的 STRIMZI_FEATURE_GATES 环境变量启用它。

禁用 ControlPlaneListener 功能门

env:
  - name: STRIMZI_FEATURE_GATES
    value: -ControlPlaneListener

启用 ControlPlaneListener 功能门

env:
  - name: STRIMZI_FEATURE_GATES
    value: +ControlPlaneListener

23.2. 所需的升级序列

要在没有停机的情况下升级代理和客户端,您必须 按照以下顺序完成 AMQ Streams 升级步骤:

  1. 确保您的 OpenShift 集群版本被支持。

    OpenShift 4.10 支持 AMQ Streams 2.5 到 4.14。

    您可以以最少的停机时间来升级 OpenShift

  2. 升级 Cluster Operator
  3. 将所有 Kafka 代理和客户端应用程序 升级到最新的支持的 Kafka 版本。

23.3. 在短短停机时间的情况下升级 OpenShift

如果要升级 OpenShift,请参阅 OpenShift 升级路径文档,以检查升级路径以及正确升级节点的步骤。在升级 OpenShift 前 ,请检查您的 AMQ Streams 版本支持的版本

在进行升级时,您要保持 Kafka 集群可用。

您可以使用以下策略之一:

  1. 配置 pod 中断预算
  2. 使用以下方法之一滚动 pod:

    1. 使用 AMQ Streams Drain Cleaner
    2. 通过将注解应用到 pod 手动

当使用任一方法滚动 pod 时,您必须使用 maxUnavailable 属性设置 pod 中断预算为零。

注意

StrimziPodSet 自定义资源使用无法使用 maxUnavailable 值的自定义控制器来管理 Kafka 和 ZooKeeper pod。相反,maxUnavailable 值转换为 minAvailable 值。如果有三个代理 pod,并且 maxUnavailable 属性设置为 0 ( 零),min Available 设置为 3,则需要所有三个代理 pod 都可用,并允许零个 pod 不可用。

要使 Kafka 保持正常运行,还必须复制主题才能进行高可用性。这要求主题配置指定至少 3 个复制因素,最小同步副本的数量为复制因素的数量减 1。

为高可用性复制 Kafka 主题

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaTopic
metadata:
  name: my-topic
  labels:
    strimzi.io/cluster: my-cluster
spec:
  partitions: 1
  replicas: 3
  config:
    # ...
    min.insync.replicas: 2
    # ...

在高可用性环境中,Cluster Operator 在升级过程中为主题维护最少的同步副本,从而无需停机。

23.3.1. 使用 AMQ Streams Drain Cleaner 的滚动 pod

您可以使用 AMQ Streams Drain Cleaner 来在升级过程中驱除节点。AMQ Streams Drain Cleaner 使用滚动更新 pod 注解来注解 pod。这会通知 Cluster Operator 执行被驱除的 pod 的滚动更新。

pod 中断预算只允许指定数量的 pod 在给定时间不可用。在计划维护 Kafka 代理 pod 期间,pod 中断预算可确保 Kafka 继续在高可用性环境中运行。

您可以使用 Kafka 组件 的模板 自定义来指定 pod 中断预算。默认情况下,pod 中断预算只允许一个 pod 在给定时间不可用。

要使用 Drain Cleaner 来滚动 pod,您需要将 maxUnavailable 设置为 0 ( 零)。将 pod 中断预算减少为零可防止意外中断,因此必须手动驱除 pod。

指定 pod 中断预算

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
  name: my-cluster
  namespace: myproject
spec:
  kafka:
    # ...
    template:
      podDisruptionBudget:
        maxUnavailable: 0
# ...

23.3.2. 手动滚动 pod,同时保持可用的主题

在升级过程中,您可以通过 Cluster Operator 触发 pod 的手动更新。使用 Pod 资源,滚动更新会使用新 pod 重启资源的 pod。与使用 AMQ Streams Drain Cleaner 一样,您需要为 pod 中断预算将 maxUnavailable 值设置为零。

您需要观察需要排空的 pod。然后,您添加一个 pod 注解来进行更新。

在这里,注解会更新 Kafka 代理。

在 Kafka 代理 pod 上执行手动滚动更新

oc annotate pod <cluster_name>-kafka-<index> strimzi.io/manual-rolling-update=true

将 & lt;cluster_name > 替换为集群的名称。Kafka 代理 pod 被命名为 & lt;cluster-name&gt; -kafka-&lt; index>,其中 <index> 以零开始,结束于副本总数。例如,my-cluster-kafka-0

23.4. 升级 Cluster Operator

使用同样的方法升级 Cluster Operator,与初始部署方法相同。

使用安装文件
如果使用安装 YAML 文件部署 Cluster Operator,请通过修改 Operator 安装文件来执行升级,如 使用安装文件升级 Cluster Operator 所述。
使用 OperatorHub

如果您从 OperatorHub 部署 AMQ Streams,请使用 Operator Lifecycle Manager (OLM)将 AMQ Streams Operator 的更新频道改为新的 AMQ Streams 版本。

根据您选择的升级策略,更新频道将启动以下类型的升级:

  • 启动自动升级
  • 安装开始前需要批准的手动升级
注意

如果您订阅了 stable 频道,可以在不更改频道的情况下获得自动更新。但是,不建议启用自动更新,因为可能缺少任何预安装升级步骤。仅在特定于版本的频道中使用自动升级。

有关使用 OperatorHub 升级 Operator 的更多信息,请参阅 升级已安装的 Operator (OpenShift 文档)。

23.4.1. 升级 Cluster Operator 会返回 Kafka 版本错误

如果您将 Cluster Operator 升级到不支持当前使用的 Kafka 版本的版本,您会收到 不受支持的 Kafka 版本 错误。这个错误适用于所有安装方法,意味着您必须将 Kafka 升级到受支持的 Kafka 版本。将 Kafka 资源中的 spec.kafka.version 更改为支持的版本。

您可以使用 oc 检查错误信息,如包括在 Kafka 资源的 status 中的信息。

检查 Kafka 状态中的错误

oc get kafka <kafka_cluster_name> -n <namespace> -o jsonpath='{.status.conditions}'

将 <kafka_cluster_name> 替换为 Kafka 集群的名称,将 <namespace> 替换为运行 pod 的 OpenShift 命名空间。

23.4.2. 使用 OperatorHub 从 AMQ Streams 1.7 或更早版本升级

使用 OperatorHub 从 AMQ Streams 1.7 或更早版本升级时需要的操作

在将 AMQ Streams Operator 升级到 2.5 之前,您需要进行以下更改:

  • 将自定义资源和 CRD 转换为 v1beta2
  • 升级到禁用 ControlPlaneListener 功能门的 AMQ Streams 版本

这些要求在 第 23.1.2 节 “从 1.7 更早的 AMQ Streams 版本升级” 中进行了描述。

如果您要从 AMQ Streams 1.7 或更早版本升级,请执行以下操作:

  1. 升级到 AMQ Streams 1.7。
  2. AMQ Streams 软件下载页下载 AMQ Streams 1.8 提供的 Red Hat AMQ Streams API Conversion Tool
  3. 将自定义资源和 CRD 转换为 v1beta2

    如需更多信息,请参阅 AMQ Streams 1.7 升级文档

  4. 在 OperatorHub 中,删除 AMQ Streams Operator 的版本 1.7。
  5. 如果也存在,删除 AMQ Streams Operator 的版本 2.5。

    如果不存在,请进入下一步。

    如果 AMQ Streams Operator 的批准策略被设置为 Automatic,则集群中可能已存在 operator 版本 2.5。如果您在发行版本 前没有 将自定义资源和 CRD 转换为 v1beta2 API 版本,Operator 管理的自定义资源和 CRD 将使用旧的 API 版本。因此,2.5 Operator 处于 Pending 状态。在这种情况下,您需要删除 AMQ Streams Operator 版本 2.5 和版本 1.7。

    如果删除这两个 Operator,则协调将暂停,直到安装了新的 Operator 版本。立即按照以下步骤操作,以便对自定义资源的任何更改都不会延迟。

  6. 在 OperatorHub 中,执行以下操作之一:

    • 升级到 AMQ Streams Operator 的 1.8 版本(默认禁用 ControlPlaneListener 功能门)。
    • 升级至 AMQ Streams Operator 的 2.0 或 2.2 版本(其中禁用了 ControlPlaneListener 功能门),并禁用了 ControlPlaneListener 功能门。
  7. 立即升级到 AMQ Streams Operator 版本 2.5。

    安装的 2.5 operator 开始监视集群并执行滚动更新。您可能会注意到在此过程中,集群性能可能会临时降低。

23.4.3. 使用安装文件升级 Cluster Operator

此流程描述了如何升级 Cluster Operator 部署以使用 AMQ Streams 2.5。

如果您使用安装 YAML 文件部署 Cluster Operator,请按照以下步骤操作。

由 Cluster Operator 管理的 Kafka 集群的可用性不受升级操作的影响。

注意

有关如何升级到该版本的信息,请参阅支持 AMQ Streams 特定版本的文档。

先决条件

流程

  1. 记录在现有 Cluster Operator 资源( /install/cluster-operator 目录中)所做的任何配置更改。任何更改都会被 Cluster Operator 的新版本 覆盖
  2. 更新自定义资源,以反映 AMQ Streams 版本 2.5 支持的配置选项。
  3. 更新 Cluster Operator。

    1. 根据运行 Cluster Operator 的命名空间修改新 Cluster Operator 版本的安装文件。

      在 Linux 中,使用:

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

      在 MacOS 中,使用:

      sed -i '' 's/namespace: .*/namespace: my-cluster-operator-namespace/' install/cluster-operator/*RoleBinding*.yaml
    2. 如果您修改了现有 Cluster Operator Deployment 中的一个或多个环境变量,请编辑 install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml 文件以使用这些环境变量。
  4. 当您有更新的配置时,将其与安装资源的其余部分一起部署:

    oc replace -f install/cluster-operator

    等待滚动更新完成。

  5. 如果新的 Operator 版本不再支持您要从升级 Kafka 版本,Cluster Operator 会返回错误消息来声明版本不被支持。否则,不会返回任何错误消息。

    • 如果返回错误消息,升级到新 Cluster Operator 版本支持的 Kafka 版本:

      1. 编辑 Kafka 自定义资源。
      2. spec.kafka.version 属性改为受支持的 Kafka 版本。
    • 如果没有 返回错误消息,请进入下一步。您将稍后升级 Kafka 版本。
  6. 获取 Kafka pod 的镜像以确保升级成功:

    oc get pods my-cluster-kafka-0 -o jsonpath='{.spec.containers[0].image}'

    镜像标签显示新的 Operator 版本。例如:

    registry.redhat.io/amq-streams/strimzi-kafka-35-rhel8:2.5.1

Cluster Operator 升级到 2.5 版本,但其管理集群中运行的 Kafka 版本不会改变。

在 Cluster Operator 升级后,您必须执行 Kafka 升级

23.5. 升级 Kafka

将 Cluster Operator 升级到 2.5 后,下一步是将所有 Kafka 代理升级到最新支持的 Kafka 版本。

Kafka 升级由 Cluster Operator 通过 Kafka 代理的滚动更新来执行。

Cluster Operator 根据 Kafka 集群配置启动滚动更新。

如果 Kafka.spec.kafka.config 包含…​Cluster Operator 启动…​

inter.broker.protocol.versionlog.message.format.version

单个滚动更新。更新后,必须手动更新 inter.broker.protocol.version,然后是 log.message.format.version。更改每个目录都会触发进一步的滚动更新。

inter.broker.protocol.versionlog.message.format.version

两个滚动更新。

没有配置 inter.broker.protocol.versionlog.message.format.version

两个滚动更新。

重要

从 Kafka 3.0.0 开始,当将 inter.broker.protocol.version 设置为 3.0 或更高版本时,log.message.format.version 选项将被忽略,不需要设置。代理的 log.message.format.version 属性和用于主题的 message.format.version 属性已弃用,并将在以后的 Kafka 发行版本中删除。

作为 Kafka 升级的一部分,Cluster Operator 为 ZooKeeper 启动滚动更新。

  • 即使 ZooKeeper 版本没有改变,也会进行单个滚动更新。
  • 如果新版本的 Kafka 需要新的 ZooKeeper 版本,则会进行额外的滚动更新。

23.5.1. Kafka 版本

Kafka 的日志消息格式版本和 inter-broker 协议版本分别指定日志格式版本,日志格式版本附加到消息以及集群中使用的 Kafka 协议的版本。为确保使用了正确的版本,升级过程涉及对现有 Kafka 代理和客户端应用程序(使用者和生产者)进行配置更改。

下表显示了 Kafka 版本之间的区别:

表 23.1. Kafka 版本的不同
AMQ Streams 版本Kafka 版本间的代理协议版本日志消息格式版本zookeeper 版本

2.5

3.5.0

3.5

3.5

3.6.4

2.4

3.4.0

3.4

3.4

3.6.3

注意

AMQ Streams 2.5 使用 Kafka 3.5.0,但 Kafka 3.4.0 也支持进行升级。

间的代理协议版本

在 Kafka 中,用于内部代理通信的网络协议称为 inter-broker 协议。Kafka 的每个版本都有了一个内部代理协议的兼容版本。协议的次要版本通常会增加以匹配 Kafka 的次版本,如上表所示。

Kafka 资源中设置集群范围的协议版本。要更改它,您可以编辑 Kafka.spec.kafka.config 中的 inter.broker.protocol.version 属性。

日志消息格式版本

当制作者向 Kafka 代理发送消息时,消息使用特定格式进行编码。格式可以在 Kafka 发行版本间有所变化,因此消息指定了它们编码的消息格式版本。

用于设置特定消息格式版本的属性如下:

  • 主题的 message.format.version 属性
  • Kafka 代理的 log.message.format.version 属性

从 Kafka 3.0.0,消息格式版本值被假定为与 inter.broker.protocol.version 匹配,且不需要设置。这些值反映了使用的 Kafka 版本。

当升级到 Kafka 3.0.0 或更高版本时,您可以在更新 inter.broker.protocol.version 时删除这些设置。否则,请基于您要升级到的 Kafka 版本设置消息格式版本。

由在 Kafka 代理中设置的 log.message.format.version 定义的 message.format.version 的默认值。您可以通过修改其主题配置来手动设置主题的 message.format.version

23.5.2. 升级客户端的策略

升级 Kafka 客户端可确保它们从新版本的 Kafka 中引入的功能、修复和改进中受益。升级的客户端维护与其他升级的 Kafka 组件的兼容性。客户端的性能和稳定性也可能得到改进。

考虑升级 Kafka 客户端和服务器的最佳方法,以确保平稳过渡。所选升级策略取决于您是否先升级代理或客户端。从 Kafka 3.0 开始,您可以独立和顺序升级代理和客户端。决定升级客户端或代理首先取决于几个因素,如需要升级的应用程序数量以及可容忍的停机时间。

如果您在代理前升级客户端,一些新功能可能无法工作,因为代理尚不支持它们。但是,代理可以处理使用不同版本运行的制作者和消费者,并支持不同的日志消息版本。

当使用 Kafka 3.0 旧的 Kafka 版本时升级客户端

在 Kafka 3.0 之前,您可以使用 log.message.format.version 属性(或主题级别的 message.format.version 属性)为代理配置特定的消息格式。这允许代理支持使用过时消息格式的旧的 Kafka 客户端。否则,代理需要从旧的客户端转换信息,这会显著提高性能成本。

自 0.11 版以来,Apache Kafka Java 客户端支持最新的消息格式版本。如果所有客户端都使用最新的消息版本,您可以在升级代理时删除 log.message.format.versionmessage.format.version 覆盖。

但是,如果您仍然有使用较旧的消息格式版本的客户端,我们建议首先升级您的客户端。从消费者开始,在升级代理时,在删除 log.message.format.versionmessage.format.version 前升级制作者。这将确保所有客户端都可以支持最新的消息格式版本,并且升级过程可以平稳进行。

您可以使用此指标跟踪 Kafka 客户端名称和版本:

  • kafka.server:type=socket-server-metrics,clientSoftwareName=<name>,clientSoftwareVersion=<version>,listener=<listener>,networkProcessor=<processor>
提示

以下 Kafka 代理指标帮助监控消息 down-conversion 的性能:

  • kafka.network:type=RequestMetrics,name=MessageConversionsTimeMs,request={Produce|Fetch} 提供执行消息转换所需时间的指标。
  • kafka.server:type=BrokerTopicMetrics,name={Produce|Fetch}MessageConversionsPerSec,topic=([-.\w]+) 提供一段时间内转换的消息数量的指标。

23.5.3. Kafka 版本和镜像映射

升级 Kafka 时,请考虑 STRIMZI_KAFKA_IMAGES 环境变量和 Kafka.spec.kafka.version 属性的设置。

  • 每个 Kafka 资源都可以使用 Kafka.spec.kafka.version 配置。
  • Cluster Operator 的 STRIMZI_KAFKA_IMAGES 环境变量提供在给定 Kafka 资源中请求该版本时使用的 Kafka 版本和镜像之间的映射。

    • 如果没有配置 Kafka.spec.kafka.image,则使用给定版本的默认镜像。
    • 如果配置了 Kafka.spec.kafka.image,则默认镜像会被覆盖。
警告

Cluster Operator 无法验证镜像是否实际包含预期版本的 Kafka 代理。请小心,确保给定镜像对应于给定的 Kafka 版本。

23.5.4. 升级 Kafka 代理和客户端应用程序

将 AMQ Streams Kafka 集群升级到最新的支持的 Kafka 版本,以及 代理间的协议版本

您还应选择升级客户端的策略。在此流程的第 6 步中升级 Kafka 客户端。

先决条件

  • Cluster Operator 已启动并在运行。
  • 在升级 AMQ Streams Kafka 集群前,请检查 Kafka 资源的 Kafka.spec.kafka.config 属性不包含新的 Kafka 版本不支持的配置选项。

流程

  1. 更新 Kafka 集群配置:

    oc edit kafka <my_cluster>
  2. 如果配置,请检查 inter.broker.protocol.versionlog.message.format.version 属性是否已设置为 当前版本

    例如,如果从 Kafka 版本 3.4.0 升级到 3.5.0,则当前版本为 3.4 :

    kind: Kafka
    spec:
      # ...
      kafka:
        version: 3.4.0
        config:
          log.message.format.version: "3.4"
          inter.broker.protocol.version: "3.4"
          # ...

    如果没有配置 log.message.format.versioninter.broker.protocol.version,AMQ Streams 会在升级到下一个 Kafka 版本后将这些版本更新至当前的默认值。

    注意

    log.message.format.versioninter.broker.protocol.version 的值必须是字符串,以防止它们被解释为浮点号。

  3. 更改 Kafka.spec.kafka.version 以指定新的 Kafka 版本;保留 log.message.format.versioninter.broker.protocol.version,作为 当前 Kafka 版本的默认值。

    注意

    更改 kafka.version 可确保集群中的所有代理都会被升级,以使用新的代理二进制文件开始。在此过程中,一些代理会使用旧的二进制文件,而其他代理已升级到新二进制文件。在当前设置中保持不变 inter.broker.protocol.version,可确保代理可以在整个升级过程中继续相互通信。

    例如,如果从 Kafka 3.4.0 升级到 3.5.0 :

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      # ...
      kafka:
        version: 3.5.0 1
        config:
          log.message.format.version: "3.4" 2
          inter.broker.protocol.version: "3.4" 3
          # ...
    1
    Kafka 版本被改为新版本。
    2
    消息格式版本保持不变。
    3
    inter-broker 协议版本不会改变。
    警告

    如果新 Kafka 版本的 inter.broker.protocol.version 发生变化,则无法降级 Kafka。inter-broker 协议版本决定用于代理存储的持久元数据的模式,包括写入 __consumer_offsets 的消息。降级的集群不知道消息。

  4. 如果在 Kafka 自定义资源中定义了 Kafka 集群的镜像,在 Kafka.spec.kafka.image 中,更新 image 以指向新的 Kafka 版本的容器镜像。

    请参阅 Kafka 版本和镜像映射

  5. 保存并退出编辑器,然后等待滚动更新完成。

    通过观察 pod 状态转换来检查滚动更新的进度:

    oc get pods my-cluster-kafka-0 -o jsonpath='{.spec.containers[0].image}'

    滚动更新可确保每个 pod 都对新版本的 Kafka 使用代理二进制文件。

  6. 根据您选择 升级客户端的策略,升级所有客户端应用程序以使用客户端二进制文件的新版本。

    如果需要,将 Kafka Connect 和 MirrorMaker 的 version 属性设置为 Kafka 的新版本:

    1. 对于 Kafka Connect,更新 KafkaConnect.spec.version
    2. 对于 MirrorMaker,更新 KafkaMirrorMaker.spec.version
    3. 对于 MirrorMaker 2,更新 KafkaMirrorMaker2.spec.version
  7. 如果配置,将 Kafka 资源更新为使用新的 inter.broker.protocol.version 版本。否则,请转到第 9 步。

    例如,如果升级到 Kafka 3.5.0 :

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      # ...
      kafka:
        version: 3.5.0
        config:
          log.message.format.version: "3.4"
          inter.broker.protocol.version: "3.5"
          # ...
  8. 等待 Cluster Operator 更新集群。
  9. 如果配置,将 Kafka 资源更新为使用新的 log.message.format.version 版本。否则,请转到第 10 步。

    例如,如果升级到 Kafka 3.5.0 :

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      # ...
      kafka:
        version: 3.5.0
        config:
          log.message.format.version: "3.5"
          inter.broker.protocol.version: "3.5"
          # ...
    重要

    从 Kafka 3.0.0 开始,当将 inter.broker.protocol.version 设置为 3.0 或更高版本时,log.message.format.version 选项将被忽略,不需要设置。

  10. 等待 Cluster Operator 更新集群。

    • Kafka 集群和客户端现在使用新的 Kafka 版本。
    • 代理被配置为使用 Kafka 的新版本间的代理和消息格式版本发送信息。

23.6. 在升级 AMQ Streams 时切换到 FIPS 模式

将 AMQ Streams 升级到在启用了 FIPS 的 OpenShift 集群中以 FIPS 模式运行。在 AMQ Streams 2.4 之前,只能使用 FIPS_MODE 环境变量禁用 FIPS 模式在启用了 FIPS 的 OpenShift 集群上运行。在版本 2.4 中,AMQ Streams 支持 FIPS 模式。如果您在启用了 FIPS 的 OpenShift 集群上运行 AMQ Streams,FIPS_MODE 被设置为 disabled,您可以按照以下流程启用它。

先决条件

  • 启用 FIPS 的 OpenShift 集群
  • FIPS_MODE 环境变量设置为 disabled的现有 Cluster Operator 部署

流程

  1. 将 Cluster Operator 升级到 2.4 或更高版本,但将 FIPS_MODE 环境变量设置为 disabled
  2. 如果您最初部署了一个早于 2.3 的 AMQ Streams 版本,则可能会在其 PKCS #12 存储中使用旧的加密和摘要算法,该算法在启用了 FIPS 的情况下不被支持。要使用更新的算法重新创建证书,请更新集群和客户端 CA 证书。

  3. 如果您使用 SCRAM-SHA-512 验证,请检查用户的密码长度。如果它们长度少于 32 个字符,请使用以下方法之一生成新密码:

    1. 删除用户 secret,以便 User Operator 生成一个新密码有足够长度的新密码。
    2. 如果您使用 KafkaUser 自定义资源的 .spec.authentication.password 属性提供密码,请更新同一密码配置中引用的 OpenShift secret 中的密码。不要忘记更新您的客户端以使用新密码。
  4. 确保 CA 证书使用正确的算法,并且 SCRAM-SHA-512 密码足够长度。然后您可以启用 FIPS 模式。
  5. 从 Cluster Operator 部署中删除 FIPS_MODE 环境变量。这会重启 Cluster Operator,并滚动所有操作对象来启用 FIPS 模式。重启完成后,所有 Kafka 集群现在都启用了 FIPS 模式运行。

第 24 章 降级 AMQ Streams

如果您遇到您升级到的 AMQ Streams 版本的问题,您可以将安装恢复到之前的版本。

如果使用 YAML 安装文件安装 AMQ Streams,您可以使用上一版本中的 YAML 安装文件执行以下降级步骤:

如果以前的 AMQ Streams 版本不支持您使用的 Kafka 版本,只要日志消息格式版本附加到消息匹配,您也可以降级 Kafka。

警告

只有在使用安装文件安装 AMQ Streams 时,以下降级说明才适合。如果您使用其他方法(如 OperatorHub)安装 AMQ Streams,则该方法可能不支持降级,除非在文档中指定。为确保成功降级过程,需要使用受支持的方法。

24.1. 将 Cluster Operator 降级到以前的版本

如果您在 AMQ Streams 时遇到问题,可以恢复安装。

此流程描述了如何将 Cluster Operator 部署降级到以前的版本。

先决条件

开始前

检查 AMQ Streams 功能门的降级要求。如果永久启用功能门,您可能需要降级到可让您在降级到目标版本前禁用它的版本。

流程

  1. 记录在现有 Cluster Operator 资源( /install/cluster-operator 目录中)所做的任何配置更改。任何更改都会被 Cluster Operator 的早期版本 覆盖
  2. 恢复自定义资源,以反映您要降级的 AMQ Streams 版本支持的配置选项。
  3. 更新 Cluster Operator。

    1. 根据 Cluster Operator 运行的命名空间修改之前版本的安装文件。

      在 Linux 中,使用:

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

      在 MacOS 中,使用:

      sed -i '' 's/namespace: .*/namespace: my-cluster-operator-namespace/' install/cluster-operator/*RoleBinding*.yaml
    2. 如果您修改了现有 Cluster Operator Deployment 中的一个或多个环境变量,请编辑 install/cluster-operator/060-Deployment-strimzi-cluster-operator.yaml 文件以使用这些环境变量。
  4. 当您有更新的配置时,将其与安装资源的其余部分一起部署:

    oc replace -f install/cluster-operator

    等待滚动更新完成。

  5. 获取 Kafka pod 的镜像,以确保降级成功:

    oc get pod my-cluster-kafka-0 -o jsonpath='{.spec.containers[0].image}'

    镜像标签显示新的 AMQ Streams 版本,后跟 Kafka 版本。例如,NEW-STRIMZI-VERSION-kafka-CURRENT-KAFKA-VERSION

Cluster Operator 已降级为之前的版本。

24.2. 降级 Kafka

Kafka 版本降级由 Cluster Operator 执行。

24.2.1. 降级的 Kafka 版本兼容性

Kafka 降级取决于兼容的当前和目标 Kafka 版本,以及记录信息的状态。

如果以前的一个版本不支持在集群中已使用过的任何 inter.broker.protocol.version 设置,或者消息已被添加到使用较新的 log.message.format.version 的消息日志中时,则无法恢复到这个以前的 Kafka 版本。

inter.broker.protocol.version 决定用于代理存储的持久元数据的模式,如写入 __consumer_offsets 的消息的 schema。如果您降级到 Kafka 版本,它不知道之前在代理遇到数据的集群中使用的 inter.broker.protocol.version

如果目标降级版本 Kafka 具有:

  • 与当前版本 相同的 log.message.format.version,Cluster Operator 通过执行代理的单一滚动重启来降级。
  • 一个不同的 log.message.format.version,只有运行的集群始终log.message.format.version 设置为降级版本使用的版本时,才可以下载。这通常只有在更改 log.message.format.version 前中止升级过程时才会出现这种情况。在这种情况下,降级需要:

    • 如果两个版本的 interbroker 协议不同,则两个代理的滚动重启
    • 单个滚动重启(如果相同)

如果新版本使用了之前版本不支持的 log.message.format.version则无法 降级,包括在使用 log.message.format.version 的默认值时。例如,此资源可以降级到 Kafka 版本 3.4.0,因为 log.message.format.version 没有改变:

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
spec:
  # ...
  kafka:
    version: 3.5.0
    config:
      log.message.format.version: "3.4"
      # ...

如果 log.message.format.version 设置为 "3.5" 或没有值,则无法降级,因此该参数会为 3.5 的 3.5.0 代理使用默认值。

重要

从 Kafka 3.0.0 开始,当将 inter.broker.protocol.version 设置为 3.0 或更高版本时,log.message.format.version 选项将被忽略,不需要设置。

24.2.2. 降级 Kafka 代理和客户端应用程序

将 AMQ Streams Kafka 集群降级到 Kafka 的较低版本,如从 3.5.0 降级到 3.4.0。

先决条件

  • Cluster Operator 已启动并在运行。
  • 在降级 AMQ Streams Kafka 集群前,检查 Kafka 资源中的以下内容:

    • 重要信息: Kafka 版本的兼容性
    • Kafka.spec.kafka.config 不包含被降级到的 Kafka 版本不支持的选项。
    • Kafka.spec.kafka.config 有一个 log.message.format.versioninter.broker.protocol.version,由被降级到的 Kafka 版本支持。

      从 Kafka 3.0.0 开始,当将 inter.broker.protocol.version 设置为 3.0 或更高版本时,log.message.format.version 选项将被忽略,不需要设置。

流程

  1. 更新 Kafka 集群配置。

    oc edit kafka KAFKA-CONFIGURATION-FILE
  2. 更改 Kafka.spec.kafka.version 以指定之前的版本。

    例如,如果从 Kafka 3.5.0 降级为 3.4.0 :

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    spec:
      # ...
      kafka:
        version: 3.4.0 1
        config:
          log.message.format.version: "3.4" 2
          inter.broker.protocol.version: "3.4" 3
          # ...
    1
    Kafka 版本被改为之前的版本。
    2
    消息格式版本保持不变。
    3
    inter-broker 协议版本不会改变。
    注意

    log.message.format.versioninter.broker.protocol.version 的值必须是字符串,以防止它们被解释为浮点号。

  3. 如果 Kafka 版本的镜像与 Cluster Operator 的 STRIMZI_KAFKA_IMAGES 中定义的镜像不同,请更新 Kafka.spec.kafka.image

    请查看 第 23.5.3 节 “Kafka 版本和镜像映射”

  4. 保存并退出编辑器,然后等待滚动更新完成。

    检查日志中的更新,或者通过观察 pod 状态转换:

    oc logs -f CLUSTER-OPERATOR-POD-NAME | grep -E "Kafka version downgrade from [0-9.]+ to [0-9.]+, phase ([0-9]+) of \1 completed"
    oc get pod -w

    检查 Cluster Operator 日志中的 INFO 级别信息:

    Reconciliation #NUM(watch) Kafka(NAMESPACE/NAME): Kafka version downgrade from FROM-VERSION to TO-VERSION, phase 1 of 1 completed
  5. 降级所有客户端应用程序(消费者),以使用客户端二进制文件的早期版本。

    Kafka 集群和客户端现在使用以前的 Kafka 版本。

  6. 如果您要恢复到早于 1.7 的 AMQ Streams 版本,它使用 ZooKeeper 来存储主题元数据,请从 Kafka 集群中删除内部主题存储主题。

    oc run kafka-admin -ti --image=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 --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

第 25 章 处理大量信息

如果您的 AMQ Streams 部署需要处理大量信息,您可以使用配置选项来优化吞吐量和延迟。

生成者和消费者配置有助于控制对 Kafka 代理的请求大小和频率。有关配置选项的更多信息,请参阅以下内容:

您还可以将相同的配置选项与 Kafka Connect 运行时源连接器(包括 MirrorMaker 2)和接收器连接器使用的制作者和消费者一起使用。

源连接器
  • Kafka Connect 运行时的制作者会向 Kafka 集群发送信息。
  • 对于 MirrorMaker 2,因为源系统是 Kafka,消费者从源 Kafka 集群检索信息。
sink 连接器
  • Kafka Connect 运行时的用户从 Kafka 集群检索信息。

对于消费者,您可以增加在单个获取请求中获取的数据量,以减少延迟。您可以使用 fetch.max.bytesmax.partition.fetch.bytes 属性增加 fetch 请求大小。您还可以使用 max.poll.records 属性设置从消费者缓冲区返回的消息数的最大限制。

对于 MirrorMaker 2,在源连接器级别(consumer.*)配置 fetch.max.bytes, max.partition.fetch.bytes, 和 max.poll.records 值,因为它们与从源获取消息的特定消费者相关。

对于生成者,您可以增加在单个生成请求中发送的消息批处理的大小。您可以使用 batch.size 属性增加批处理大小。更大的批处理大小可减少准备好发送的未完成消息的数量以及消息队列中的 backlog 的大小。发送到同一分区的消息会并行批处理。当达到批处理大小时,将生成请求发送到目标集群。通过增加批处理大小,生成请求会延迟,并将更多消息添加到批处理中,并同时发送到代理。当您只有处理大量消息的几个主题分区时,这可以提高吞吐量。

考虑制作者为合适的生产批处理大小处理的记录的数量和大小。

使用 linger.ms 添加等待时间(毫秒)以在生成者负载减少时延迟生成请求。延迟意味着,如果记录在最大批处理大小下,可以添加更多记录到批处理中。

在连接器级别 (producer.override.*) 配置 batch.sizelinger.ms 值,因为它们与向目标 Kafka 集群发送信息的特定制作者相关。

对于 Kafka Connect 源连接器,到目标 Kafka 集群的数据流管道如下:

Kafka Connect 源连接器的数据流管道

External data source →(Kafka Connect tasks) source message queue → producer buffer → target Kafka topic

对于 Kafka Connect sink 连接器,到目标外部数据源的数据流管道如下:

Kafka Connect sink 连接器的数据流管道

source Kafka topic → (Kafka Connect tasks) sink message queue → consumer buffer → external data source

对于 MirrorMaker 2,目标 Kafka 集群的数据镜像管道如下:

MirrorMaker 2 的数据镜像管道

source Kafka topic → (Kafka Connect tasks) source message queue → producer buffer → target Kafka topic

制作者在其缓冲区中向目标 Kafka 集群中的主题发送信息。当发生这种情况时,Kafka Connect 任务将继续轮询数据源,以将信息添加到源消息队列中。

源连接器的制作者缓冲区的大小使用 producer.override.buffer.memory 属性进行设置。在缓冲区被清除前,任务会等待指定的超时周期(offset.flush.timeout.ms)。这应该有足够的时间,以便代理和偏移数据提交的信息可以确认发送消息。除关闭期间,源任务不会等待制作者为空消息队列,然后再提交偏移。

如果生成者无法满足源消息队列中消息的吞吐量,则缓冲区会被阻断,直到缓冲区内由 max.block.ms 绑定的时间周期内可用。在此期间,缓冲区中仍然发送任何未确认的信息。在确认和清除这些消息之前,新消息不会添加到缓冲区中。

您可以尝试以下配置更改,将未完成的消息的底层源消息队列保持在 manageable 大小下:

  • offset.flush.timeout.ms为单位增加默认值
  • 确保有足够的 CPU 和内存资源
  • 通过执行以下操作增加并行运行的任务数量:

    • 使用 tasksMax 属性增加并行运行的任务数量
    • 使用 replicas 属性增加运行任务的 worker 节点数量

根据可用的 CPU 和内存资源和 worker 节点数量,请考虑可以并行运行的任务数量。您可能需要继续调整配置值,直到它们具有所需的效果。

25.1. 为高容量信息配置 Kafka 连接

Kafka Connect 从源外部数据系统获取数据,并将其传递给 Kafka Connect 运行时制作者,使其复制到目标集群。

以下示例显示了使用 KafkaConnect 自定义资源的 Kafka Connect 配置。

处理大量消息的 Kafka 连接配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: my-connect-cluster
  annotations:
    strimzi.io/use-connector-resources: "true"
spec:
  replicas: 3
  config:
    offset.flush.timeout.ms: 10000
    # ...
  resources:
    requests:
      cpu: "1"
      memory: 2Gi
    limits:
      cpu: "2"
      memory: 2Gi
  # ...

为源连接器添加生成者配置,该连接器通过 KafkaConnector 自定义资源进行管理。

处理大量信息的源连接器配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnector
metadata:
  name: my-source-connector
  labels:
    strimzi.io/cluster: my-connect-cluster
spec:
  class: org.apache.kafka.connect.file.FileStreamSourceConnector
  tasksMax: 2
  config:
    producer.override.batch.size: 327680
    producer.override.linger.ms: 100
    # ...

注意

FileStreamSourceConnectorFileStreamSinkConnector 作为示例连接器提供。有关将它们部署为 KafkaConnector 资源的详情,请参考 第 6.4.3.3 节 “部署 KafkaConnector 资源”

为接收器连接器添加消费者配置。

处理大量消息的接收器连接器配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnector
metadata:
  name: my-sink-connector
  labels:
    strimzi.io/cluster: my-connect-cluster
spec:
  class: org.apache.kafka.connect.file.FileStreamSinkConnector
  tasksMax: 2
  config:
    consumer.fetch.max.bytes: 52428800
    consumer.max.partition.fetch.bytes: 1048576
    consumer.max.poll.records: 500
    # ...

如果您使用 Kafka Connect API 而不是 KafkaConnector 自定义资源来管理连接器,您可以将连接器配置添加为 JSON 对象。

添加用于处理大量消息的源连接器配置的 curl 请求示例

curl -X POST \
  http://my-connect-cluster-connect-api:8083/connectors \
  -H 'Content-Type: application/json' \
  -d '{ "name": "my-source-connector",
    "config":
    {
      "connector.class":"org.apache.kafka.connect.file.FileStreamSourceConnector",
      "file": "/opt/kafka/LICENSE",
      "topic":"my-topic",
      "tasksMax": "4",
      "type": "source"
      "producer.override.batch.size": 327680
      "producer.override.linger.ms": 100
    }
}'

25.2. 为高卷消息配置 MirrorMaker 2

MirrorMaker 2 从源集群获取数据,并将其传递给 Kafka Connect 运行时制作者,以便将其复制到目标集群。

以下示例显示了使用 KafkaMirrorMaker2 自定义资源的 MirrorMaker 2 的配置。

用于处理大量消息的 MirrorMaker 2 配置示例

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaMirrorMaker2
metadata:
  name: my-mirror-maker2
spec:
  version: 3.5.0
  replicas: 1
  connectCluster: "my-cluster-target"
  clusters:
  - alias: "my-cluster-source"
    bootstrapServers: my-cluster-source-kafka-bootstrap:9092
  - alias: "my-cluster-target"
    config:
      offset.flush.timeout.ms: 10000
    bootstrapServers: my-cluster-target-kafka-bootstrap:9092
  mirrors:
  - sourceCluster: "my-cluster-source"
    targetCluster: "my-cluster-target"
    sourceConnector:
      tasksMax: 2
      config:
        producer.override.batch.size: 327680
        producer.override.linger.ms: 100
        consumer.fetch.max.bytes: 52428800
        consumer.max.partition.fetch.bytes: 1048576
        consumer.max.poll.records: 500
    # ...
  resources:
    requests:
      cpu: "1"
      memory: Gi
    limits:
      cpu: "2"
      memory: 4Gi

25.3. 检查 MirrorMaker 2 消息流

如果使用 Prometheus 和 Grafana 监控部署,您可以检查 MirrorMaker 2 消息流。

AMQ Streams 提供的 MirrorMaker 2 Grafana 仪表板示例显示了与 flush 管道相关的以下指标。

  • Kafka Connect 的未完成消息队列中的消息数
  • producer 缓冲区的可用字节
  • 偏移提交超时时间(毫秒)

您可以使用这些指标来量化是否需要根据消息卷调整配置。

第 26 章 查找 Kafka 重启信息

当 Cluster Operator 重启了 OpenShift 集群中的一个 Kafka pod 后,它会将 OpenShift 事件发送到 pod 的命名空间中,解释 pod 重启的原因。有关了解集群行为的帮助,您可以从命令行检查重启事件。

提示

您可以使用 Prometheus 等指标集合工具导出和监控重启事件。将 metrics 工具与 事件导出器 一起使用,以适当的格式导出输出。

26.1. 重启事件的原因

Cluster Operator 会因为特定原因启动重启事件。您可以通过获取重启事件的信息来检查原因。

表 26.1. 重启原因
事件描述

CaCertHasOldGeneration

pod 仍然使用通过旧 CA 签名的服务器证书,因此需要在证书更新过程中重启。

CaCertRemoved

过期的 CA 证书已被删除,pod 会重启以使用当前证书运行。

CaCertRenewed

CA 证书已更新,pod 重启以使用更新的证书运行。

ClientCaCertKeyReplaced

用于为客户端 CA 证书签名的密钥已被替换,pod 作为 CA 续订服务器过程的一部分重启。

ClusterCaCertKeyReplaced

用于为集群的 CA 证书签名的密钥已被替换,pod 作为 CA 续订服务器过程的一部分重启。

ConfigChangeRequiresRestart

有些 Kafka 配置属性会动态更改,但其他 Kafka 配置属性需要重启代理。

FileSystemResizeNeeded

文件系统大小已增加,需要重启来应用它。

KafkaCertificatesChanged

Kafka 代理使用的一个或多个 TLS 证书已更新,需要使用重启。

ManualRollingUpdate

注解了 pod 或 StrimziPodSet 的用户,以便触发重启。

PodForceRestartOnError

发生错误,需要 pod 重启来重新处理。

PodHasOldRevision

在 Kafka 卷中添加或删除磁盘,需要重启来应用更改。使用 StrimziPodSet 资源时,如果需要重新创建 pod,则会提供相同的原因。

PodHasOldRevision

pod 的 StrimziPodSet 已更新,因此需要重新创建 pod。使用 StrimziPodSet 资源时,如果从 Kafka 卷添加或删除磁盘,则会提供相同的原因。

PodStuck

pod 仍然处于待处理状态,且没有调度或无法调度,因此 Operator 已在最终尝试运行它时重启 pod。

PodUnresponsive

AMQ Streams 无法连接到 pod,这可能表示代理没有正确启动,因此 Operator 会在尝试解决这个问题时重启它。

26.2. 重启事件过滤器

从命令行检查重启事件时,您可以指定一个 field-selector 来过滤 OpenShift 事件字段。

在使用 field-selector 过滤事件时,可以使用以下字段。

regardingObject.kind
重启的对象以及重启事件的对象始终是 Pod
regarding.namespace
pod 所属的命名空间。
regardingObject.name
pod 的名称,如 strimzi-cluster-kafka-0
regardingObject.uid
pod 的唯一 ID。
reason
pod 重启的原因,如 JbodVolumesChanged
reportingController
报告组件始终是 AMQ Streams 重启事件的 strimzi.io/cluster-operator
source
SourcereportingController 的旧版本。报告组件始终是 AMQ Streams 重启事件的 strimzi.io/cluster-operator
type
事件类型,可以是 WarningNormal。对于 AMQ Streams 重启事件,类型为 Normal
注意

在旧版本的 OpenShift 中,使用 相关前缀的字段 可能会改为使用 involvedObject 前缀。reportingController 之前被称为 reportingComponent

26.3. 检查 Kafka 重启

使用 oc 命令列出 Cluster Operator 启动的重启事件。通过使用 reportingController 事件字段将 Cluster Operator 设置为报告组件来过滤 Cluster Operator 发送的重启事件。

先决条件

  • Cluster Operator 在 OpenShift 集群中运行。

流程

  1. 获取 Cluster Operator 发送的所有重启事件:

    oc -n kafka get events --field-selector reportingController=strimzi.io/cluster-operator

    显示返回的事件示例

    LAST SEEN   TYPE     REASON                   OBJECT                        MESSAGE
    2m          Normal   CaCertRenewed            pod/strimzi-cluster-kafka-0   CA certificate renewed
    58m         Normal   PodForceRestartOnError   pod/strimzi-cluster-kafka-1   Pod needs to be forcibly restarted due to an error
    5m47s       Normal   ManualRollingUpdate      pod/strimzi-cluster-kafka-2   Pod was manually annotated to be rolled

    您还可以指定 reason 或其他 field-selector 选项来限制返回的事件。

    在这里添加了一个特定原因:

    oc -n kafka get events --field-selector reportingController=strimzi.io/cluster-operator,reason=PodForceRestartOnError
  2. 使用输出格式(如 YAML)返回一个或多个事件的详细信息。

    oc -n kafka get events --field-selector reportingController=strimzi.io/cluster-operator,reason=PodForceRestartOnError -o yaml

    显示详细事件输出的示例

    apiVersion: v1
    items:
    - action: StrimziInitiatedPodRestart
      apiVersion: v1
      eventTime: "2022-05-13T00:22:34.168086Z"
      firstTimestamp: null
      involvedObject:
          kind: Pod
          name: strimzi-cluster-kafka-1
          namespace: kafka
      kind: Event
      lastTimestamp: null
      message: Pod needs to be forcibly restarted due to an error
      metadata:
          creationTimestamp: "2022-05-13T00:22:34Z"
          generateName: strimzi-event
          name: strimzi-eventwppk6
          namespace: kafka
          resourceVersion: "432961"
          uid: 29fcdb9e-f2cf-4c95-a165-a5efcd48edfc
      reason: PodForceRestartOnError
      reportingController: strimzi.io/cluster-operator
      reportingInstance: strimzi-cluster-operator-6458cfb4c6-6bpdp
      source: {}
      type: Normal
    kind: List
    metadata:
      resourceVersion: ""
      selfLink: ""

以下字段已弃用,因此不会为这些事件填充它们:

  • firstTimestamp
  • lastTimestamp
  • source

第 27 章 管理 AMQ Streams

管理 AMQ Streams 需要执行各种任务来保持 Kafka 集群和相关资源平稳运行。使用 oc 命令检查资源的状态,配置维护窗口以进行滚动更新,并使用 AMQ Streams Drain Cleaner 和 Kafka Static Quota 插件等工具来有效地管理您的部署。

27.1. 使用自定义资源

您可以使用 oc 命令检索信息,并对 AMQ Streams 自定义资源执行其他操作。

oc 与自定义资源的 status 子资源一起使用,您可以获取有关资源的信息。

27.1.1. 对自定义资源执行 oc 操作

使用 oc 命令,如 get, describe, edit, 或 delete, 对资源类型执行操作。例如,oc get kafkatopics 检索所有 Kafka 主题和 oc get kafkas 列表,检索所有部署的 Kafka 集群。

在引用资源类型时,您可以使用单数和复数名称: oc get kafkas 获取与 oc get kafka 相同的结果。

您还可以使用资源 的短名称。学习短名称可在管理 AMQ Streams 时节省时间。Kafka 的短名称为 k,因此您也可以运行 oc get k 来列出所有 Kafka 集群。

oc get k

NAME         DESIRED KAFKA REPLICAS   DESIRED ZK REPLICAS
my-cluster   3                        3
表 27.1. 每个 AMQ Streams 资源的长和短名称
AMQ Streams 资源长名称短名称

Kafka

kafka

k

Kafka 主题

kafkatopic

kt

Kafka 用户

kafkauser

ku

Kafka Connect

kafkaconnect

kc

Kafka Connector

kafkaconnector

kctr

Kafka Mirror Maker

kafkamirrormaker

kmm

Kafka Mirror Maker 2

kafkamirrormaker2

kmm2

Kafka Bridge

kafkabridge

kb

Kafka Rebalance

kafkarebalance

kr

27.1.1.1. 资源类别

自定义资源的类别也可以在 oc 命令中使用。

所有 AMQ Streams 自定义资源都属于类别 strimzi,因此您可以使用 strimzi 通过一个命令获取所有 AMQ Streams 资源。

例如,运行 oc get strimzi 列出了给定命名空间中的所有 AMQ Streams 自定义资源。

oc get strimzi

NAME                                   DESIRED KAFKA REPLICAS DESIRED ZK REPLICAS
kafka.kafka.strimzi.io/my-cluster      3                      3

NAME                                   PARTITIONS REPLICATION FACTOR
kafkatopic.kafka.strimzi.io/kafka-apps 3          3

NAME                                   AUTHENTICATION AUTHORIZATION
kafkauser.kafka.strimzi.io/my-user     tls            simple

oc get strimzi -o name 命令返回所有资源类型和资源名称。-o name 选项以 type/name 格式获取输出

oc get strimzi -o name

kafka.kafka.strimzi.io/my-cluster
kafkatopic.kafka.strimzi.io/kafka-apps
kafkauser.kafka.strimzi.io/my-user

您可以将这个 strimzi 命令与其他命令合并。例如,您可以将其传递给 oc delete 命令,以删除单个命令中的所有资源。

oc delete $(oc get strimzi -o name)

kafka.kafka.strimzi.io "my-cluster" deleted
kafkatopic.kafka.strimzi.io "kafka-apps" deleted
kafkauser.kafka.strimzi.io "my-user" deleted

删除单个操作中的所有资源可能很有用,例如,当您测试新的 AMQ Streams 功能时。

27.1.1.2. 查询子资源的状态

您可以使用其他值传递给 -o 选项。例如,通过使用 -o yaml,您可以以 YAML 格式获取输出。使用 -o json 会将它返回为 JSON。

您可以查看 oc get --help 中的所有选项。

最有用的选项是 JSONPath 支持,它允许您传递 JSONPath 表达式来查询 Kubernetes API。JSONPath 表达式可以提取或导航任何资源的特定部分。

例如,您可以使用 JSONPath 表达式 {.status.listeners[? (@.name=="tls")].bootstrapServers} 从 Kafka 自定义资源的状态中获取 bootstrap 地址,并在 Kafka 客户端中使用它。

在这里,命令找到名为 tls 的监听程序的 bootstrapServers 值:

oc get kafka my-cluster -o=jsonpath='{.status.listeners[?(@.name=="tls")].bootstrapServers}{"\n"}'

my-cluster-kafka-bootstrap.myproject.svc:9093

通过更改名称条件,您还可以获取其他 Kafka 侦听程序的地址。

您可以使用 jsonpath 从任何自定义资源中提取任何其他属性或属性组。

27.1.2. AMQ Streams 自定义资源状态信息

status 属性为特定自定义资源提供状态信息。

下表列出了提供状态信息(部署时)和定义 status 属性的 schema 的自定义资源。

如需有关 schema 的更多信息,请参阅 AMQ Streams 自定义资源 API 参考

表 27.2. 提供状态信息的自定义资源
AMQ Streams 资源模式参考在…​ 中发布状态信息

Kafka

KafkaStatus 模式参考

Kafka 集群

KafkaTopic

KafkaTopicStatus 模式参考

Kafka 集群中的 Kafka 主题

KafkaUser

KafkaUserStatus 模式参考

Kafka 集群中的 Kafka 用户

KafkaConnect

KafkaConnectStatus schema 参考

Kafka Connect 集群

KafkaConnector

KafkaConnectorStatus 模式参考

KafkaConnector 资源

KafkaMirrorMaker2

KafkaMirrorMaker2Status 模式参考

Kafka MirrorMaker 2 集群

KafkaMirrorMaker

KafkaMirrorMakerStatus 模式参考

Kafka MirrorMaker 集群

KafkaBridge

KafkaBridgeStatus schema reference

AMQ Streams Kafka Bridge

KafkaRebalance

KafkaRebalance 模式参考

重新平衡的状态和结果

资源的 status 属性提供有关资源状态的信息。status.conditionsstatus.observedGeneration 属性都是所有资源通用的。

status.conditions
状态条件描述了资源的当前状态。状态条件属性可用于跟踪与资源相关的进度,达到其 所需状态,这由 spec 中指定的配置定义。状态条件属性提供资源更改的时间和原因,以及阻止或延迟 Operator 实际状态的事件详情。
status.observedGeneration
最后观察到的生成表示 Cluster Operator 资源的最新协调。如果 观察到的Generation 的值与 metadata.generation 的值(部署当前版本)不同,Operator 尚未处理对资源的最新更新。如果这些值相同,状态信息反映了资源的最新更改。

status 属性还提供特定于资源的信息。例如,KafkaStatus 提供有关监听器地址的信息,以及 Kafka 集群的 ID。

AMQ Streams 创建和维护自定义资源的状态,定期评估自定义资源的当前状态并相应地更新其状态。当使用 oc edit 在自定义资源上执行更新时,则其状态不可编辑。另外,更改 状态 不会影响 Kafka 集群的配置。

在这里,我们看到 Kafka 自定义资源的状态 属性。

Kafka 自定义资源状态

apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
metadata:
spec:
  # ...
status:
  clusterId: XP9FP2P-RByvEy0W4cOEUA 1
  conditions: 2
    - lastTransitionTime: '2023-01-20T17:56:29.396588Z'
      status: 'True'
      type: Ready 3
  listeners: 4
    - addresses:
        - host: my-cluster-kafka-bootstrap.prm-project.svc
          port: 9092
      bootstrapServers: 'my-cluster-kafka-bootstrap.prm-project.svc:9092'
      name: plain
      type: plain
    - addresses:
        - host: my-cluster-kafka-bootstrap.prm-project.svc
          port: 9093
      bootstrapServers: 'my-cluster-kafka-bootstrap.prm-project.svc:9093'
      certificates:
        - |
          -----BEGIN CERTIFICATE-----

          -----END CERTIFICATE-----
      name: tls
      type: tls
    - addresses:
        - host: >-
            2054284155.us-east-2.elb.amazonaws.com
          port: 9095
      bootstrapServers: >-
        2054284155.us-east-2.elb.amazonaws.com:9095
      certificates:
        - |
          -----BEGIN CERTIFICATE-----

          -----END CERTIFICATE-----
      name: external2
      type: external2
    - addresses:
        - host: ip-10-0-172-202.us-east-2.compute.internal
          port: 31644
      bootstrapServers: 'ip-10-0-172-202.us-east-2.compute.internal:31644'
      certificates:
        - |
          -----BEGIN CERTIFICATE-----

          -----END CERTIFICATE-----
      name: external1
      type: external1
  observedGeneration: 3 5

1
Kafka 集群 ID。
2
状态条件 描述了 Kafka 集群的当前状态。
3
Ready 条件表示 Cluster Operator 认为 Kafka 集群可以处理流量。
4
侦听器根据类型 描述 Kafka bootstrap 地址。
5
observedGeneration 值表示 Cluster Operator 对 Kafka 自定义资源的最后协调。
注意

状态中列出的 Kafka bootstrap 地址并不表示这些端点或 Kafka 集群处于 Ready 状态。

访问状态信息

您可以从命令行访问资源的状态信息。更多信息请参阅 第 27.1.3 节 “查找自定义资源的状态”

27.1.3. 查找自定义资源的状态

这个步骤描述了如何查找自定义资源的状态。

先决条件

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

流程

  • 指定自定义资源,并使用 -o jsonpath 选项应用标准 JSONPath 表达式来选择 status 属性:

    oc get kafka <kafka_resource_name> -o jsonpath='{.status}'

    此表达式返回指定自定义资源的所有状态信息。您可以使用点表示法(如 status.listenersstatus.observedGeneration )来微调您想要查看的状态信息。

其他资源

27.2. 使用标签和注解发现服务

通过服务发现,可以更轻松地在与 AMQ Streams 相同的 OpenShift 集群中运行客户端应用程序,以便与 Kafka 集群交互。

为用于访问 Kafka 集群的服务生成 服务发现 标签和注解:

  • 内部 Kafka bootstrap 服务
  • HTTP Bridge 服务

该标签有助于使服务发现,注解提供了客户端应用程序可用于进行连接的连接详情。

Service 资源的服务发现标签 strimzi.io/discovery 被设为 true。服务发现注解具有相同的键,为每个服务提供 JSON 格式的连接详情。

内部 Kafka bootstrap 服务示例
apiVersion: v1
kind: Service
metadata:
  annotations:
    strimzi.io/discovery: |-
      [ {
        "port" : 9092,
        "tls" : false,
        "protocol" : "kafka",
        "auth" : "scram-sha-512"
      }, {
        "port" : 9093,
        "tls" : true,
        "protocol" : "kafka",
        "auth" : "tls"
      } ]
  labels:
    strimzi.io/cluster: my-cluster
    strimzi.io/discovery: "true"
    strimzi.io/kind: Kafka
    strimzi.io/name: my-cluster-kafka-bootstrap
  name: my-cluster-kafka-bootstrap
spec:
  #...
HTTP Bridge 服务示例
apiVersion: v1
kind: Service
metadata:
  annotations:
    strimzi.io/discovery: |-
      [ {
        "port" : 8080,
        "tls" : false,
        "auth" : "none",
        "protocol" : "http"
      } ]
  labels:
    strimzi.io/cluster: my-bridge
    strimzi.io/discovery: "true"
    strimzi.io/kind: KafkaBridge
    strimzi.io/name: my-bridge-bridge-service

27.2.1. 返回服务的连接详情

您可以在从命令行或对应的 API 调用时指定发现标签来查找服务。

oc get service -l strimzi.io/discovery=true

检索服务发现标签时会返回连接详情。

27.3. 从一个终端连接到 ZooKeeper

ZooKeeper 服务使用加密和身份验证进行保护,并不适用于不属于 AMQ Streams 的外部应用程序。

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

先决条件

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

流程

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

    例如:

    oc exec -ti my-cluster-zookeeper-0 -- bin/zookeeper-shell.sh localhost:12181 ls /

    务必使用 localhost:12181

27.4. 暂停自定义资源的协调

有时,暂停由 AMQ Streams Operator 管理的自定义资源协调很有用,以便您可以执行修复或更新。如果暂停协调,Operator 会忽略对自定义资源所做的任何更改,直到暂停结束为止。

如果要暂停自定义资源的协调,请在其配置中将 strimzi.io/pause-reconciliation 注解设置为 true。这指示适当的 Operator 暂停自定义资源的协调。例如,您可以将注解应用到 KafkaConnect 资源,以便 Cluster Operator 的协调已暂停。

您还可以创建启用 pause 注解的自定义资源。自定义资源已创建,但它将被忽略。

先决条件

  • 管理自定义资源的 AMQ Streams Operator 正在运行。

流程

  1. 在 OpenShift 中注解自定义资源,将 pause-reconciliation 设置为 true

    oc annotate <kind_of_custom_resource> <name_of_custom_resource> strimzi.io/pause-reconciliation="true"

    例如,对于 KafkaConnect 自定义资源:

    oc annotate KafkaConnect my-connect strimzi.io/pause-reconciliation="true"
  2. 检查自定义资源的状态条件是否显示 ReconciliationPaused 的更改:

    oc describe <kind_of_custom_resource> <name_of_custom_resource>

    lastTransitionTimetype 条件会变为 ReconciliationPaused

    带有暂停协调条件类型的自定义资源示例

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaConnect
    metadata:
      annotations:
        strimzi.io/pause-reconciliation: "true"
        strimzi.io/use-connector-resources: "true"
      creationTimestamp: 2021-03-12T10:47:11Z
      #...
    spec:
      # ...
    status:
      conditions:
      - lastTransitionTime: 2021-03-12T10:47:41.689249Z
        status: "True"
        type: ReconciliationPaused

从 pause 恢复

  • 要恢复协调,您可以将注解设置为 false,或删除注解。

27.5. 滚动更新的维护时间窗

通过维护时间窗口,您可以调度 Kafka 和 ZooKeeper 集群的某些滚动更新,以便在方便的时间启动。

27.5.1. 维护时间窗概述

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

但是,对 Kafka 和 ZooKeeper 集群的一些更新可能会出现任何与 Kafka 资源对应的更改。例如,如果其管理的 CA (证书颁发机构)证书接近到期,Cluster Operator 需要执行滚动重启。

虽然 pod 的滚动重启应该不会影响服务的可用性 (假设正确的代理和主题配置),但它可能会影响 Kafka 客户端应用程序的性能。维护时间窗允许您调度 Kafka 和 ZooKeeper 集群的此类 spontaneous 滚动更新,以便在方便的时间启动。如果没有为集群配置维护时间窗,则此类更新可能会在不方便的时间进行,比如在可预测的高负载期间。

27.5.2. 维护时间窗定义

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

以下示例配置了一个维护时间窗,其从午夜开始,并以 01:59am (UTC)结束,在 Sundays、Mondays、Mondays、rednesdays 和 Thursdays 上结束:

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

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

注意

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

27.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_configuration_file>

27.6. 使用 AMQ Streams Drain Cleaner 驱除 pod

Kafka 和 ZooKeeper pod 可在 OpenShift 升级、维护或 pod 重新调度过程中被驱除。如果您的 Kafka 代理和 ZooKeeper pod 由 AMQ Streams 部署,您可以使用 AMQ Streams Drain Cleaner 工具来处理 pod 驱除。AMQ Streams Drain Cleaner 处理驱除而不是 OpenShift。您必须将 Kafka 部署的 podDisruptionBudget 设置为 0 ( 零)。然后,OpenShift 将不再允许自动驱除 pod。

通过部署 AMQ Streams Drain Cleaner,您可以使用 Cluster Operator 移动 Kafka pod 而不是 OpenShift。Cluster Operator 确保主题永远不会被复制。Kafka 可在驱除过程中保持操作。Cluster Operator 等待主题同步,因为 OpenShift worker 节点会连续排空。

准入 Webhook 通知对 Kubernetes API 的 pod 驱除请求的 AMQ Streams Drain Cleaner。然后,AMQ Streams Drain Cleaner 为 pod 添加一个滚动更新注解来排空。这会通知 Cluster Operator 执行被驱除的 pod 的滚动更新。

注意

如果您不使用 AMQ Streams Drain Cleaner,您可以添加 pod 注解来手动执行滚动更新

Webhook 配置

AMQ Streams Drain Cleaner 部署文件包含一个 ValidatingWebhookConfiguration 资源文件。资源提供了将 webhook 注册到 Kubernetes API 的配置。

配置定义了在 pod 驱除请求时要遵守的 Kubernetes API 的规则。规则指定仅与 pod/eviction 子资源 相关的 CREATE 操作会被截获。如果满足这些规则,API 会转发通知。

clientConfig 指向 AMQ Streams Drain Cleaner 服务和公开 webhook 的 /drainer 端点。Webhook 使用需要身份验证的安全 TLS 连接。caBundle 属性指定验证 HTTPS 通信的证书链。证书以 Base64 编码。

pod 驱除通知的 Webhook 配置

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
# ...
webhooks:
  - name: strimzi-drain-cleaner.strimzi.io
    rules:
      - apiGroups:   [""]
        apiVersions: ["v1"]
        operations:  ["CREATE"]
        resources:   ["pods/eviction"]
        scope:       "Namespaced"
    clientConfig:
      service:
        namespace: "strimzi-drain-cleaner"
        name: "strimzi-drain-cleaner"
        path: /drainer
        port: 443
        caBundle: Cg==
    # ...

27.6.1. 下载 AMQ Streams Drain Cleaner 部署文件

要部署并使用 AMQ Streams Drain Cleaner,您需要下载部署文件。

AMQ Streams Drain Cleaner 部署文件可从 AMQ Streams 软件下载页面 获得。

27.6.2. 使用安装文件部署 AMQ Streams Drain Cleaner

将 AMQ Streams Drain Cleaner 部署到运行 Cluster Operator 和 Kafka 集群的 OpenShift 集群。

AMQ Streams 设置默认 PodDisruptionBudget (PDB),在任何给定时间只允许一个 Kafka 或 ZooKeeper pod 不可用。要使用 Drain Cleaner 进行计划维护或升级,您必须设置 PDB 为零。这是为了防止 pod 的大量驱除,并确保 Kafka 或 ZooKeeper 集群仍然可用。您可以通过在 KafkaZooKeeper 模板中将 maxUnavailable 值设置为零。StrimziPodSet 自定义资源使用无法使用 maxUnavailable 值的自定义控制器来管理 Kafka 和 ZooKeeper pod。相反,maxUnavailable 值转换为 minAvailable 值。例如,如果有三个代理 pod,并且 maxUnavailable 属性设置为 0 ( 零),min Available 设置为 3,则需要所有三个代理 pod 可用,并允许零个 pod 不可用。

先决条件

  • 您已下载了 AMQ Streams Drain Cleaner 部署文件
  • 您有一个高度可用的 Kafka 集群部署,它运行了您要更新的 OpenShift worker 节点。
  • 复制主题以实现高可用性。

    主题配置指定至少 3 个复制因素,最小同步副本的数量为复制因素的数量减 1。

    为高可用性复制 Kafka 主题

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: my-topic
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 1
      replicas: 3
      config:
        # ...
        min.insync.replicas: 2
        # ...

排除 Kafka 或 ZooKeeper

如果您不想在 Drain Cleaner 操作中包含 Kafka 或 ZooKeeper pod,请更改 Drain Cleaner Deployment 配置文件中的默认环境变量。

  • STRIMZI_DRAIN_KAFKA 设置为 false 以排除 Kafka pod
  • STRIMZI_DRAIN_ZOOKEEPER 设置为 false 以排除 ZooKeeper pod

排除 ZooKeeper pod 的配置示例

apiVersion: apps/v1
kind: Deployment
spec:
  # ...
  template:
    spec:
      serviceAccountName: strimzi-drain-cleaner
      containers:
        - name: strimzi-drain-cleaner
          # ...
          env:
            - name: STRIMZI_DRAIN_KAFKA
              value: "true"
            - name: STRIMZI_DRAIN_ZOOKEEPER
              value: "false"
          # ...

流程

  1. 使用 template 设置,在 Kafka 资源的 Kafka 和 ZooKeeper 部分中将maxUnavailable 设置为 0 (零)。

    指定 pod 中断预算

    apiVersion: kafka.strimzi.io/v1beta2
    kind: Kafka
    metadata:
      name: my-cluster
      namespace: myproject
    spec:
      kafka:
        template:
          podDisruptionBudget:
            maxUnavailable: 0
    
      # ...
      zookeeper:
        template:
          podDisruptionBudget:
            maxUnavailable: 0
      # ...

    此设置可防止在计划中断时自动驱除 pod,导致 AMQ Streams Drain Cleaner 和 Cluster Operator 在不同的 worker 节点上滚动 pod。

    如果要使用 AMQ Streams Drain Cleaner 来排空 ZooKeeper 节点,为 ZooKeeper 添加相同的配置。

  2. 更新 Kafka 资源:

    oc apply -f <kafka_configuration_file>
  3. 部署 AMQ Streams Drain Cleaner。

    • 要在 OpenShift 上运行 Drain Cleaner,请应用 /install/drain-cleaner/openshift 目录中的资源。

      oc apply -f ./install/drain-cleaner/openshift

27.6.3. 使用 AMQ Streams Drain Cleaner

与 Cluster Operator 结合使用 AMQ Streams Drain Cleaner,从正在排空的节点移动 Kafka 代理或 ZooKeeper pod。运行 AMQ Streams Drain Cleaner 时,它会使用滚动更新 pod 注解来注解 pod。Cluster Operator 根据注解执行滚动更新。

流程

  1. 排空托管 Kafka 代理或 ZooKeeper pod 的指定 OpenShift 节点。

    oc get nodes
    oc drain <name-of-node> --delete-emptydir-data --ignore-daemonsets --timeout=6000s --force
  2. 检查 AMQ Streams Drain Cleaner 日志中的驱除事件,以验证 pod 是否已注解以重启。

    AMQ Streams Drain Cleaner 日志显示 pod 的注解

    INFO ... Received eviction webhook for Pod my-cluster-zookeeper-2 in namespace my-project
    INFO ... Pod my-cluster-zookeeper-2 in namespace my-project will be annotated for restart
    INFO ... Pod my-cluster-zookeeper-2 in namespace my-project found and annotated for restart
    
    INFO ... Received eviction webhook for Pod my-cluster-kafka-0 in namespace my-project
    INFO ... Pod my-cluster-kafka-0 in namespace my-project will be annotated for restart
    INFO ... Pod my-cluster-kafka-0 in namespace my-project found and annotated for restart

  3. 检查 Cluster Operator 日志中的协调事件以验证滚动更新。

    Cluster Operator 日志显示滚动更新

    INFO  PodOperator:68 - Reconciliation #13(timer) Kafka(my-project/my-cluster): Rolling Pod my-cluster-zookeeper-2
    INFO  PodOperator:68 - Reconciliation #13(timer) Kafka(my-project/my-cluster): Rolling Pod my-cluster-kafka-0
    INFO  AbstractOperator:500 - Reconciliation #13(timer) Kafka(my-project/my-cluster): reconciled

27.6.4. 观察 AMQ Streams Drain Cleaner 使用的 TLS 证书

默认情况下,Drain Cleaner 部署会监视包含其用于身份验证的 TLS 证书的 secret。Drain Cleaner 监视是否有变化,如证书续订。如果检测到更改,它会重启以重新加载 TLS 证书。Drain Cleaner 安装文件默认启用此行为。但是,您可以通过在 Drain Cleaner 安装文件的部署配置 (060-Deployment.yaml) 中将 STRIMZI_CERTIFICATE_WATCH_ENABLED 环境变量设置为 false 来禁用对证书的监控。

启用 STRIMZI_CERTIFICATE_WATCH_ENABLED 后,您还可以使用以下环境变量来监视 TLS 证书。

表 27.3. 排空用于监视 TLS 证书的清理环境变量
环境变量描述默认

STRIMZI_CERTIFICATE_WATCH_ENABLED

启用或禁用证书监视

false

STRIMZI_CERTIFICATE_WATCH_NAMESPACE

部署 Drain Cleaner 的命名空间以及证书 secret 存在的位置

strimzi-drain-cleaner

STRIMZI_CERTIFICATE_WATCH_POD_NAME

Drain Cleaner pod 名称

-

STRIMZI_CERTIFICATE_WATCH_SECRET_NAME

包含 TLS 证书的 secret 名称

strimzi-drain-cleaner

STRIMZI_CERTIFICATE_WATCH_SECRET_KEYS

包含 TLS 证书的 secret 中的字段列表

tls.crt, tls.key

控制监视操作的环境变量配置示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: strimzi-drain-cleaner
  labels:
    app: strimzi-drain-cleaner
  namespace: strimzi-drain-cleaner
spec:
  # ...
    spec:
      serviceAccountName: strimzi-drain-cleaner
      containers:
        - name: strimzi-drain-cleaner
          # ...
          env:
            - name: STRIMZI_DRAIN_KAFKA
              value: "true"
            - name: STRIMZI_DRAIN_ZOOKEEPER
              value: "true"
            - name: STRIMZI_CERTIFICATE_WATCH_ENABLED
              value: "true"
            - name: STRIMZI_CERTIFICATE_WATCH_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: STRIMZI_CERTIFICATE_WATCH_POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
              # ...

提示

使用 Downward API 机制配置 STRIMZI_CERTIFICATE_WATCH_NAMESPACESTRIMZI_CERTIFICATE_WATCH_POD_NAME

27.7. 使用注解删除 Kafka 节点

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

警告

删除 PersistentVolumeClaim 可能会导致持久性数据丢失,且不能保证集群可用。只有在遇到存储问题时才应执行以下步骤。

先决条件

  • 正在运行的 Cluster Operator

流程

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

    Kafka 代理 pod 的名称为 <cluster-name>-kafka-<index>,其中 <index> 从 0 开始,最高为副本数量减一。例如,my-cluster-kafka-0

  2. 在 OpenShift 中注解 Pod 资源。

    使用 oc annotate

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

27.8. 使用注解删除 ZooKeeper 节点

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

警告

删除 PersistentVolumeClaim 可能会导致持久性数据丢失,且不能保证集群可用。只有在遇到存储问题时才应执行以下步骤。

先决条件

  • 正在运行的 Cluster Operator

流程

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

    ZooKeeper pod 名为 &lt ;cluster-name&gt; -zookeeper-<index &gt ;,其中 <index > 以零开始,结束于副本减一个总数。例如,my-cluster-zookeeper-0

  2. 在 OpenShift 中注解 Pod 资源。

    使用 oc annotate

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

27.9. 使用注解启动 Kafka 和 ZooKeeper 集群的滚动更新

AMQ Streams 支持使用资源上的注解来通过 Cluster Operator 手动触发 Kafka 和 ZooKeeper 集群的滚动更新。滚动更新使用新的资源重启 pod。

在特殊 pod 或一组 pod 上手动执行滚动更新,通常只需要在特殊情况下进行滚动更新。但是,如果您通过 Cluster Operator 执行滚动更新,而不是直接删除 pod,请确保以下内容:

  • 手动删除 pod 不会与 Cluster Operator 操作冲突,如同时删除其他 pod。
  • Cluster Operator 逻辑处理 Kafka 配置规格,如同步副本数。

27.9.1. 使用 pod 管理注解执行滚动更新

此流程描述了如何触发 Kafka 集群或 ZooKeeper 集群的滚动更新。要触发更新,您可以在 StrimziPodSet 中添加注解,用于管理集群中运行的 pod。

先决条件

要执行手动滚动更新,您需要运行一个正在运行的 Cluster Operator 和 Kafka 集群。

流程

  1. 查找控制您要手动更新的 Kafka 或 ZooKeeper pod 的资源名称。

    例如,如果您的 Kafka 集群命名为 my-cluster,则对应的名称为 my-cluster-kafkamy-cluster-zookeeper

  2. 使用 oc annotate 在 OpenShift 中注解适当的资源。

    Annotating a StrimziPodSet

    oc annotate strimzipodset <cluster_name>-kafka strimzi.io/manual-rolling-update=true
    
    oc annotate strimzipodset <cluster_name>-zookeeper strimzi.io/manual-rolling-update=true

  3. 等待下一个协调发生(默认为两分钟)。触发注解资源中的所有 pod 的滚动更新,只要协调过程检测到注解。当所有 pod 的滚动更新完成后,注解会从资源中删除。

27.9.2. 使用 pod 注解执行滚动更新

此流程描述了如何使用 OpenShift Pod 注解手动触发现有 Kafka 集群或 ZooKeeper 集群的滚动更新。当注解多个 pod 时,连续滚动更新会在同一协调运行中执行。

先决条件

要执行手动滚动更新,您需要运行一个正在运行的 Cluster Operator 和 Kafka 集群。

无论使用了什么主题复制因素,您可以在 Kafka 集群上执行滚动更新。但是,对于 Kafka 在更新过程中保持操作,您需要执行以下操作:

  • 使用您要更新的节点运行的高可用性 Kafka 集群部署。
  • 复制的主题以实现高可用性。

    主题配置指定至少 3 个复制因素,最小同步副本的数量为复制因素的数量减 1。

    为高可用性复制 Kafka 主题

    apiVersion: kafka.strimzi.io/v1beta2
    kind: KafkaTopic
    metadata:
      name: my-topic
      labels:
        strimzi.io/cluster: my-cluster
    spec:
      partitions: 1
      replicas: 3
      config:
        # ...
        min.insync.replicas: 2
        # ...

流程

  1. 找到您要手动更新的 Kafka 或 ZooKeeper Pod 的名称。

    例如,如果您的 Kafka 集群命名为 my-cluster,则对应的 Pod 名称为 my-cluster-kafka-indexmy-cluster-zookeeper-index索引 从零开始,结束于副本总数。

  2. 在 OpenShift 中注解 Pod 资源。

    使用 oc annotate

    oc annotate pod cluster-name-kafka-index strimzi.io/manual-rolling-update=true
    
    oc annotate pod cluster-name-zookeeper-index strimzi.io/manual-rolling-update=true
  3. 等待下一个协调发生(默认为两分钟)。当在协调过程检测到注解时,就会触发被注解的 Pod 的滚动更新。完成 Pod 的滚动更新后,注解将从 Pod 中删除。

27.10. 使用注解执行 MirrorMaker 2 连接器重启

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

先决条件

  • Cluster Operator 正在运行。

流程

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

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

    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 连接器就会重启。当接受重启请求时,注解会从 KafkaMirrorMaker2 自定义资源中删除。

27.11. 使用注解执行 MirrorMaker 2 连接器任务重启

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

先决条件

  • Cluster Operator 正在运行。

流程

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

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

    oc describe KafkaMirrorMaker2 KAFKAMIRRORMAKER-2-NAME
  3. 要重启连接器任务,请在 OpenShift 中注解 KafkaMirrorMaker2 资源。在本例中,oc annotate restart task 0 of a connector named 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 连接器任务被重启,只要协调过程检测到注解。当接受重启任务请求时,注解会从 KafkaMirrorMaker2 自定义资源中删除。

27.12. 从持久性卷恢复集群

如果 Kafka 集群仍然存在,则可以从持久性卷(PV)恢复 Kafka 集群。

例如,您可能需要进行此操作:

  • 命名空间被意外删除
  • 整个 OpenShift 集群会丢失,但 PV 会保留在基础架构中

27.12.1. 从命名空间删除中恢复

由于持久性卷和命名空间之间的关系,可以从命名空间删除中恢复。PersistentVolume (PV) 是位于命名空间外的存储资源。PV 使用 PersistentVolumeClaim (PVC)挂载到 Kafka pod 中,该 PVC 位于命名空间内。

PV 的重新声明策略告知集群如何在删除命名空间时执行的操作。如果重新声明策略被设置为:

  • 删除 (默认)、当在命名空间中删除 PVC 时 PV 会被删除
  • Retain,当删除命名空间时 PV 不会删除。

如果确保在命名空间被意外删除时可以从 PV 中进行恢复,需要使用 persistentVolumeReclaimPolicy 属性在 PV 规格中将策略从 Delete 重置为 Retain

apiVersion: v1
kind: PersistentVolume
# ...
spec:
  # ...
  persistentVolumeReclaimPolicy: Retain

另外,PV 可以继承关联的存储类的重新声明策略。存储类用于动态卷分配。

通过为存储类配置 reclaimPolicy 属性,使用存储类的 PV 会使用适当的重新声明策略创建。存储类使用 storageClassName 属性为 PV 配置。

apiVersion: v1
kind: StorageClass
metadata:
  name: gp2-retain
parameters:
  # ...
# ...
reclaimPolicy: Retain
apiVersion: v1
kind: PersistentVolume
# ...
spec:
  # ...
  storageClassName: gp2-retain
注意

如果您使用 Retain 作为重新声明策略,但您想要删除整个集群,则需要手动删除 PV。否则,它们不会被删除,并可能导致不必要的资源。

27.12.2. 恢复丢失 OpenShift 集群

当集群丢失时,如果基础架构内保留,您可以使用磁盘/卷中的数据来恢复集群。恢复过程与删除命名空间相同,假设可以恢复 PV 并手动创建它们。

27.12.3. 从持久性卷中恢复已删除的集群

这个步骤描述了如何从持久性卷(PV)恢复已删除的集群。

在这种情况下,主题 Operator 会标识 Kafka 中存在的主题,但 KafkaTopic 资源不存在。

当进入重新创建集群的步骤时,有两个选项:

  1. 当您可以恢复所有 KafkaTopic 资源时,请使用 选项 1

    因此,必须在集群启动前恢复 KafkaTopic 资源,以便主题 Operator 不会删除对应的主题。

  2. 当您无法恢复所有 KafkaTopic 资源时,请使用选项 2

    在这种情况下,您可以在没有主题 Operator 的情况下部署集群,删除主题 Operator 主题存储元数据,然后使用 Topic Operator 重新部署 Kafka 集群,以便它可以从对应的主题重新创建 KafkaTopic 资源。

注意

如果没有部署 Topic Operator,则只需要恢复 PersistentVolumeClaim (PVC)资源。

开始前

在此过程中,PV 被挂载到正确的 PVC 以避免数据崩溃。为 PVC 指定一个 volumeName,这必须与 PV 的名称匹配。

如需更多信息,请参阅 持久性存储

注意

该流程不包括对 KafkaUser 资源的恢复,这些资源必须手动重新创建。如果需要保留密码和证书,则必须重新创建 secret,然后才能创建 KafkaUser 资源。

流程

  1. 检查集群中 PV 的信息:

    oc get pv

    显示带有数据的 PV 的信息。

    显示对此过程很重要的列示例:

    NAME                                         RECLAIMPOLICY CLAIM
    pvc-5e9c5c7f-3317-11ea-a650-06e1eadd9a4c ... Retain ...    myproject/data-my-cluster-zookeeper-1
    pvc-5e9cc72d-3317-11ea-97b0-0aef8816c7ea ... Retain ...    myproject/data-my-cluster-zookeeper-0
    pvc-5ead43d1-3317-11ea-97b0-0aef8816c7ea ... Retain ...    myproject/data-my-cluster-zookeeper-2
    pvc-7e1f67f9-3317-11ea-a650-06e1eadd9a4c ... Retain ...    myproject/data-0-my-cluster-kafka-0
    pvc-7e21042e-3317-11ea-9786-02deaf9aa87e ... Retain ...    myproject/data-0-my-cluster-kafka-1
    pvc-7e226978-3317-11ea-97b0-0aef8816c7ea ... Retain ...    myproject/data-0-my-cluster-kafka-2
    • NAME 显示每个 PV 的名称。
    • RECLAIM POLICY 显示 PV 被保留
    • CLAIM 显示到原始 PVC 的链接。
  2. 重新创建原始命名空间:

    oc create namespace myproject
  3. 重新创建原始 PVC 资源规格,将 PVC 链接到适当的 PV:

    例如:

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: data-0-my-cluster-kafka-0
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 100Gi
      storageClassName: gp2-retain
      volumeMode: Filesystem
      volumeName: pvc-7e1f67f9-3317-11ea-a650-06e1eadd9a4c
  4. 编辑 PV 规格,以删除绑定原始 PVC 的 claimRef 属性。

    例如:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      annotations:
        kubernetes.io/createdby: aws-ebs-dynamic-provisioner
        pv.kubernetes.io/bound-by-controller: "yes"
        pv.kubernetes.io/provisioned-by: kubernetes.io/aws-ebs
      creationTimestamp: "<date>"
      finalizers:
      - kubernetes.io/pv-protection
      labels:
        failure-domain.beta.kubernetes.io/region: eu-west-1
        failure-domain.beta.kubernetes.io/zone: eu-west-1c
      name: pvc-7e226978-3317-11ea-97b0-0aef8816c7ea
      resourceVersion: "39431"
      selfLink: /api/v1/persistentvolumes/pvc-7e226978-3317-11ea-97b0-0aef8816c7ea
      uid: 7efe6b0d-3317-11ea-a650-06e1eadd9a4c
    spec:
      accessModes:
      - ReadWriteOnce
      awsElasticBlockStore:
        fsType: xfs
        volumeID: aws://eu-west-1c/vol-09db3141656d1c258
      capacity:
        storage: 100Gi
      claimRef:
        apiVersion: v1
        kind: PersistentVolumeClaim
        name: data-0-my-cluster-kafka-2
        namespace: myproject
        resourceVersion: "39113"
        uid: 54be1c60-3319-11ea-97b0-0aef8816c7ea
      nodeAffinity:
        required:
          nodeSelectorTerms:
          - matchExpressions:
            - key: failure-domain.beta.kubernetes.io/zone
              operator: In
              values:
              - eu-west-1c
            - key: failure-domain.beta.kubernetes.io/region
              operator: In
              values:
              - eu-west-1
      persistentVolumeReclaimPolicy: Retain
      storageClassName: gp2-retain
      volumeMode: Filesystem

    在示例中,删除了以下属性:

    claimRef:
      apiVersion: v1
      kind: PersistentVolumeClaim
      name: data-0-my-cluster-kafka-2
      namespace: myproject
      resourceVersion: "39113"
      uid: 54be1c60-3319-11ea-97b0-0aef8816c7ea
  5. 部署 Cluster Operator。

    oc create -f install/cluster-operator -n my-project
  6. 重新创建集群。

    根据是否具有重新创建集群所需的所有 KafkaTopic 资源,请按照以下步骤操作。

    选项 1: 如果您拥有在丢失集群前存在 的所有 KafkaTopic 资源,包括 __consumer_offsets 中的提交偏移等内部主题:

    1. 重新创建所有 KafkaTopic 资源。

      在部署集群前,您必须重新创建资源,或者主题 Operator 将删除主题。

    2. 部署 Kafka 集群。

      例如:

      oc apply -f kafka.yaml

    选项 2: 如果您没有在丢失集群前存在的所有 KafkaTopic 资源:

    1. 部署 Kafka 集群,与第一个选项一样,但在部署前,通过从 Kafka 资源中删除 topicOperator 属性来没有 Topic Operator。

      如果在部署中包含 Topic Operator,则主题 Operator 将删除所有主题。

    2. 从 Kafka 集群中删除内部主题存储主题:

      oc run kafka-admin -ti --image=registry.redhat.io/amq-streams/kafka-35-rhel8:2.5.1 --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 集群的监听程序和身份验证类型对应。

    3. 通过使用 topicOperator 属性重新部署 Kafka 集群来启用 Topic Operator,以重新创建 KafkaTopic 资源。

      例如:

      apiVersion: kafka.strimzi.io/v1beta2
      kind: Kafka
      metadata:
        name: my-cluster
      spec:
        #...
        entityOperator:
          topicOperator: {} 1
          #...
    1
    在这里,我们显示没有额外属性的默认配置。您可以使用 EntityTopicOperatorSpec schema reference 中所述的属性指定所需的配置。
  7. 列出 KafkaTopic 资源来验证恢复:

    oc get KafkaTopic

27.13. 卸载 AMQ Streams

您可以使用 OpenShift Container Platform Web 控制台或 CLI 从 OperatorHub 卸载 AMQ Streams on OpenShift 4.10 到 4.14。

使用您用于安装 AMQ Streams 的相同方法。

卸载 AMQ Streams 时,您需要识别专门为部署创建的资源,并从 AMQ Streams 资源引用。

这些资源包括:

  • Secret (自定义 CA 和证书、Kafka Connect secret 和其他 Kafka secret)
  • 日志记录 ConfigMap (类型为 external

这些是由 Kafka,KafkaConnect,KafkaMirrorMaker, 或 KafkaBridge 配置引用的资源。

警告

删除 CustomResourceDefinitions 会导致相应自定义资源的垃圾回收(KafkaKafkaConnectKafkaMirrorMakerKafkaBridge)以及依赖于这些资源的资源(Deployments、StatefulSet 和其他依赖资源)。

27.13.1. 使用 Web 控制台从 OperatorHub 卸载 AMQ Streams

此流程描述了如何从 OperatorHub 卸载 AMQ Streams 并删除与部署相关的资源。

您可以从控制台执行这些步骤或使用替代 CLI 命令。

先决条件

  • 使用具有 cluster-adminstrimzi-admin 权限的账户访问 OpenShift Container Platform Web 控制台。
  • 您已确定要删除的资源。

    您可以使用以下 oc CLI 命令查找资源,并在卸载 AMQ Streams 时验证它们是否已被删除。

    查找与 AMQ Streams 部署相关的资源的命令

    oc get <resource_type> --all-namespaces | grep <kafka_cluster_name>

    <resource_type > 替换为您要检查的资源类型,如 secretconfigmap

流程

  1. 在 OpenShift Web 控制台中进入到 Operators > Installed Operators
  2. 对于已安装的 AMQ Streams operator,选择选项图标(三个垂直点),然后点 Uninstall Operator

    Operator 已从 Installed Operators 中删除。

  3. 导航到 Home > Projects,再选择安装 AMQ Streams 和 Kafka 组件的项目。
  4. Inventory 下的选项删除相关资源。

    资源包括:

    • 部署
    • StatefulSets
    • Pods
    • 服务
    • ConfigMaps
    • Secrets
    提示

    使用搜索来查找以 Kafka 集群名称开头的相关资源。您还可以在 Workloads 下找到资源。

备选CLI命令

您可以使用 CLI 命令从 OperatorHub 卸载 AMQ Streams。

  1. 删除 AMQ Streams 订阅。

    oc delete subscription amq-streams -n openshift-operators
  2. 删除集群服务版本(CSV)。

    oc delete csv amqstreams.<version>  -n openshift-operators
  3. 删除相关的 CRD。

    oc get crd -l app=strimzi -o name | xargs oc delete

27.13.2. 使用 CLI 卸载 AMQ Streams

此流程描述了如何使用 oc 命令行工具卸载 AMQ Streams 并删除与部署相关的资源。

先决条件

  • 使用具有 cluster-adminstrimzi-admin 权限的账户访问 OpenShift 集群。
  • 您已确定要删除的资源。

    您可以使用以下 oc CLI 命令查找资源,并在卸载 AMQ Streams 时验证它们是否已被删除。

    查找与 AMQ Streams 部署相关的资源的命令

    oc get <resource_type> --all-namespaces | grep <kafka_cluster_name>

    <resource_type > 替换为您要检查的资源类型,如 secretconfigmap

流程

  1. 删除 Cluster Operator Deployment、相关的 CustomResourceDefinitionsRBAC 资源。

    指定用于部署 Cluster Operator 的安装文件。

    oc delete -f install/cluster-operator
  2. 删除您在先决条件中标识的资源。

    oc delete <resource_type> <resource_name> -n <namespace>

    <resource_type > 替换为您要删除的资源类型,& lt;resource_name > 替换为资源名称。

    删除 secret 的示例

    oc delete secret my-cluster-clients-ca-cert -n my-project

27.14. 常见问题解答

第 28 章 在 AMQ Streams 上使用 Metering

您可以使用 OpenShift 上可用的 Metering 工具从不同的数据源生成 metering 报告。作为集群管理员,您可使用 Metering 来分析集群中的情况。您可以自行编写报告,也可以使用预定义的 SQL 查询来定义如何处理来自现有不同数据源的数据。使用 Prometheus 作为默认数据源,您可以针对 pod、命名空间和大多数其他 OpenShift 资源生成报告。

您还可以使用 OpenShift Metering operator 分析已安装的 AMQ Streams 组件,以确定您是否符合红帽订阅。

要将 metering 与 AMQ Streams 搭配使用,您必须首先在 OpenShift Container Platform 上安装和配置 Metering Operator。

28.1. Metering 资源

Metering 具有很多资源,可用于管理 Metering 的部署与安装以及 Metering 提供的报告功能。Metering 使用以下 CRD 管理:

表 28.1. Metering 资源
名称Description

MeteringConfig

为部署配置 metering 堆栈。包含用于控制 metering 堆栈各个组件的自定义和配置选项。

Reports

控制要使用的查询、查询运行时间、运行频率以及查询结果的存储位置。

ReportQueries

包含用于对 ReportDataSources 中包含的数据进行分析的 SQL 查询。

ReportDataSources

控制 ReportQueries 和 Reports 可用数据。支持配置 metering 中使用的不同数据库的访问权限。

28.2. AMQ Streams 的 metering 标签

下表列出了 AMQ Streams 基础架构组件和集成的 metering 标签。

表 28.2. Metering 标签
标签可能的值

com.company

Red_Hat

rht.prod_name

Red_Hat_Application_Foundations

rht.prod_ver

2023.Q3

rht.comp

AMQ_Streams

rht.comp_ver

2.5

rht.subcomp

基础架构

cluster-operator

entity-operator

topic-operator

user-operator

zookeeper

Application(应用程序)

kafka-broker

kafka-connect

kafka-connect-build

kafka-mirror-maker2

kafka-mirror-maker

cruise-control

kafka-bridge

kafka-exporter

drain-cleaner

rht.subcomp_t

infrastructure

application

例子

  • 基础架构示例(基础架构组件是 entity-operator

    com.company=Red_Hat
    rht.prod_name=Red_Hat_Application_Foundations
    rht.prod_ver=2023.Q3
    rht.comp=AMQ_Streams
    rht.comp_ver=2.5
    rht.subcomp=entity-operator
    rht.subcomp_t=infrastructure
  • 应用程序示例(集成部署名称为 kafka-bridge

    com.company=Red_Hat
    rht.prod_name=Red_Hat_Application_Foundations
    rht.prod_ver=2023.Q3
    rht.comp=AMQ_Streams
    rht.comp_ver=2.5
    rht.subcomp=kafka-bridge
    rht.subcomp_t=application

附录 A. 使用您的订阅

AMQ Streams 通过软件订阅提供。要管理您的订阅,请访问红帽客户门户中的帐户。

访问您的帐户

  1. 转至 access.redhat.com
  2. 如果您还没有帐户,请创建一个帐户。
  3. 登录到您的帐户。

激活订阅

  1. 转至 access.redhat.com
  2. 导航到 My Subscriptions
  3. 导航到 激活订阅 并输入您的 16 位激活号。

下载 Zip 和 Tar 文件

要访问 zip 或 tar 文件,请使用客户门户网站查找下载的相关文件。如果您使用 RPM 软件包,则不需要这一步。

  1. 打开浏览器并登录红帽客户门户网站 产品下载页面,网址为 access.redhat.com/downloads
  2. INTEGRATION AND AUTOMATION 目录中找到 AMQ Streams for Apache Kafka 项。
  3. 选择所需的 AMQ Streams 产品。此时会打开 Software Downloads 页面。
  4. 单击组件的 Download 链接。

使用 DNF 安装软件包

要安装软件包以及所有软件包的依赖软件包,请使用:

dnf install <package_name>

要从本地目录中安装之前下载的软件包,请使用:

dnf install <path_to_download_package>

更新于 2023-11-22

法律通告

Copyright © 2023 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.