【问题标题】:Kafka in Kubernetes Cluster- How to publish/consume messages from outside of Kubernetes ClusterKubernetes 集群中的 Kafka - 如何从 Kubernetes 集群外部发布/使用消息
【发布时间】:2017-06-11 14:40:29
【问题描述】:
  1. 我已经在 Kubernetes 集群中部署并运行了 Kafka。我正在使用来自 docker hub 的这张图片 - https://hub.docker.com/r/cloudtrackinc/kubernetes-kafka/
  2. 我的 kubernetes 集群中有 3 个 kube 节点。我有 3 个 Kafka 和 3 个 zookeeper 应用程序正在运行,并且我有 zoo1、zoo2、zoo3 和 kafka-1、kafka-2 和 kafka-3 与它们对应运行。我能够从 kubernetes 集群内部发布/使用,但我无法从 kubernetes 集群外部发布/使用,即从不属于 kubernetes 集群的外部机器发布/使用。
  3. 我能够从外部机器访问 kube-nodes - 基本上我可以使用名称/IP ping 它们。
  4. 我没有使用任何外部负载平衡器,但我有一个可以解析我的外部计算机和 kube 节点的 DNS。
  5. 在这种情况下,使用 NodePort 或 ExternalIP 公开 Kafka 服务不起作用。
  6. 在 Kafka RC YML 中设置 KAFKA_ADVERTISED_HOST_NAMEKAFKA_ADVERTISED_LISTENERS 最终在 server.properties 中设置 ADVERTISED_HOST_NAME/ADVERTISED_LISTENERS 属性都无助于从 kubernetes 集群外部访问 kafka。

请建议我如何从 kubernetes 集群外部发布/使用。非常感谢!

【问题讨论】:

    标签: docker apache-kafka kubernetes


    【解决方案1】:

    与其重新发明轮子并自己构建它,不如使用https://strimzi.io添加外部侦听器的解决方案

    来自文档 - https://strimzi.io/docs/operators/latest/deploying.html#setup-external-clients-str

    外部监听器通过指定外部类型来暴露 Kafka:

    • route 使用 OpenShift 路由和默认 HAProxy 路由器

    • loadbalancer 使用负载均衡器服务

    • nodeport 使用 Kubernetes 节点上的端口

    • ingress 使用 Kubernetes Ingress 和 NGINX Ingress Controller for Kubernetes

    然后这将添加您可以从 pod(用于节点端口)或负载均衡器/服务入口查询的适当资源

    还可以选择安装“Kafka Bridge”,其运行方式与 Confluent 的 Kafka REST 代理非常相似。

    【讨论】:

      【解决方案2】:

      我能够通过进行以下更改来解决我的问题 -

      1. 在 YML 中使用 NodeSelector 让 kafka pod 在 kube 集群的特定节点上运行。

      2. KAFKA_ADVERTISED_HOST_NAME 设置为 Kube 主机名,此 Kafka POD 已配置为在其中运行(如步骤 1 中所配置)

      3. 使用 NodePort 暴露 Kafka 服务,并将 POD 端口设置为与暴露的 NodePort 相同,如下所示 -

        spec:
          ports:
            - name: broker-2
              port: **30031**
              targetPort: 9092
              nodePort: **30031**
              protocol: TCP
          selector:
            app: kafka-2
            broker_id: "2"
          type: NodePort
        

      现在,您可以使用 host:exposedPort 从 kube 集群外部访问 Kafka 代理

      【讨论】:

        【解决方案3】:

        我在从 AWS 上的 k8s 集群外部访问 kafka 时遇到了同样的问题。我设法通过使用从版本 0.10.2 开始支持多个接口的 kafka 侦听器功能来解决这个问题。

        这是我配置 kafka 容器的方式。

            ports:
            - containerPort: 9092
            - containerPort: 9093
            env:
            - name: KAFKA_ZOOKEEPER_CONNECT
              value: "zookeeper:2181"
            - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
              value: "INTERNAL_PLAINTEXT:PLAINTEXT,EXTERNAL_PLAINTEXT:PLAINTEXT"
            - name: KAFKA_ADVERTISED_LISTENERS
              value: "INTERNAL_PLAINTEXT://kafka-internal-service:9092,EXTERNAL_PLAINTEXT://123.us-east-2.elb.amazonaws.com:9093"
            - name: KAFKA_LISTENERS
              value: "INTERNAL_PLAINTEXT://0.0.0.0:9092,EXTERNAL_PLAINTEXT://0.0.0.0:9093"
            - name: KAFKA_INTER_BROKER_LISTENER_NAME
              value: "INTERNAL_PLAINTEXT"
        

        除此之外,我还配置了两个服务。一种用于内部(无头)通信,另一种用于外部(LoadBalancer)通信。

        希望这会节省人们的时间。

        【讨论】:

        • 嗨,我想按照你的解决方案,因为我有同样的问题和类似的设置。你能再解释一下吗,我不明白你是怎么做到的。
        【解决方案4】:

        我通过使用 Confluent 的 Kafka REST 代理映像解决了这个问题。

        https://hub.docker.com/r/confluentinc/cp-kafka-rest/

        REST 代理的文档在这里:

        http://docs.confluent.io/3.1.2/kafka-rest/docs/index.html

        步骤 A:使用最新的 Kafka 版本构建 Kafka 代理 docker 映像

        我使用了基于您使用的同一映像的自定义构建的 Kafka 代理映像。您基本上只需要更新 cloudtrackinc 的映像以使用 Kafka 版本 0.10.1.0,否则它将无法正常工作。只需从 cloudertrackinc 的镜像更新 Dockerfile 以使用最新的 wurstmeister kafka 镜像并重建 docker 镜像。

        - FROM wurstmeister/kafka:0.10.1.0
        

        我将每个 Kafka 代理的 ADVERTISED_HOST_NAME 设置为 POD 的 IP,这样每个代理都会获得一个唯一的 URL。

        - name: ADVERTISED_HOST_NAME
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        

        步骤 B:设置 cp-kafka-rest 代理以使用您的 Kafka 代理集群

        Kafka Rest Proxy 必须与您的 Kafka 代理集群在同一个集群中运行。

        您至少需要为 cp-kafka-rest 映像提供两个环境变量才能运行。 KAFKA_REST_HOST_NAME 和 KAFKA_REST_ZOOKEEPER_CONNECT。您可以设置 KAFKA_REST_HOST_NAME 使用 POD 的 IP。

        - name: KAFKA_REST_HOST_NAME
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: KAFKA_REST_ZOOKEEPER_CONNECT
          value: "zookeeper-svc-1:2181,zookeeper-svc-2:2181,zookeeper-svc-3:2181"
        

        步骤 C:将 Kafka REST 代理公开为服务

        spec: type: NodePort or LoadBalancer ports: - name: kafka-rest-port port: 8082 protocol: TCP

        您可以使用 NodePort 或 LoadBalancer 来利用单个或多个 Kafka REST Proxy pod。

        使用 Kafka REST 代理的优缺点

        优点:

        1. 您可以轻松扩展 Kafka 代理集群
        2. 您不必在集群外公开 Kakfa 代理
        3. 您可以将负载均衡器与代理一起使用。
        4. 您可以使用任何类型的客户端访问 Kafka 集群(即 curl)。重量很轻。

        缺点:

        1. Kakfa 集群顶部的另一个组件/层。
        2. 消费者是在代理 pod 中创建的。这需要由您的 REST 客户端跟踪。
        3. 性能不理想:REST 而不是原生 Kafka 协议。虽然如果您部署多个代理,这可能会有所帮助。我不会将此设置用于大流量。对于少量消息流量,这可能没问题。

        所以,如果你能忍受上述问题,那就试试 Kafka Rest Proxy。

        【讨论】:

        • 谢谢@yuqing mai。我还能够使我的初始配置工作。请看我对这个问题的回答。
        【解决方案5】:

        目前这似乎是不可能的,kafka 的网络架构在这个话题上相当糟糕。新的消费者使用一个代理列表,它返回 zookeeper 的主机,但不幸的是,它位于不同的网络中,因此无法从本地客户端访问它。 kafka 的不足之处在于,无法指定代理和 zookeeper 服务器。这可以防止客户端从外部访问系统。

        我们暂时使用busybox解决了这个问题,我们在其中安装了与kafka交互的工具。在我们的例子中plunger

        【讨论】:

        • 谢谢@Dag 是的,在 kubernetes 中运行的 Kafka 集群在不同的 n/w 中。但是由于集群机器和外部机器都可以由内部 DNS 服务器解析,是否有一种方法或解决方法可以从外部机器发布/使用消息?此外,由于我已经使用 NodePort 公开了 kafka 服务,因此我可以使用 : 连接到 Kafka,但只能从 kubernetes 集群中的机器 n/w 并且在 n/ 外部的机器上同样不起作用w 虽然我可以从外部机器访问/ping这些kube节点。
        • 互联网上的一些资源说人们已经使用 ADVERTISED_HOST_NAME 在 AWS/Cloud 上使其在外部工作,这可能是因为公共 IP...外部负载均衡器 dns
        猜你喜欢
        • 2020-07-22
        • 2019-11-25
        • 1970-01-01
        • 1970-01-01
        • 2020-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多