簡體   English   中英

從 k8s 中的另一個命名空間連接到 kafka

[英]Connecting to kafka from another namespace inside k8s

我的 minikube 中的 kafka 和 zookeeper 有以下配置:

apiVersion: v1
kind: Service
metadata:
  name: kafka-service
  namespace: kafka
spec:
  selector:
    app: kafka
  ports:
    - protocol: TCP
      port: 9092
      name: kafka-port
    - protocol: TCP
      port: 9094
      name: kafka-port-out
    - protocol: TCP
      port: 2181
      name: kafka-zk
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-deployment
  namespace: kafka
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafka
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        app: kafka
        k8s-app: kube-dns
    spec:
      containers:
        - name: kafka-container
          image: bitnami/kafka:latest
          env:
          - name: 'ALLOW_PLAINTEXT_LISTENER'
            value: 'yes'
          - name: 'KAFKA_CFG_ZOOKEEPER_CONNECT'
            value: 'zookeeper-service:2181'
          - name: 'KAFKA_CFG_LISTENERS'
            value: 'PLAINTEXT://:9092'
          - name: 'KAFKA_CFG_ADVERTISED_LISTENERS' # if I comment this and the next line it works only locally
            value: 'PLAINTEXT://kafka-service.kafka:9092'
          ports:
            - containerPort: 9092
              name: kafka-port
            - containerPort: 9094
              name: kafka-port-out
            - containerPort: 5555
              name: kafka-port-jmx
            - containerPort: 2181
              name: kafka-zk

這是我的動物園管理員的配置:

apiVersion: v1
kind: Service
metadata:
  name: zookeeper-service
  namespace: kafka
spec:
  selector:
    app: zookeeper
  ports:
    - protocol: TCP
      port: 2181
      name: zookeeper-port
    - protocol: TCP
      port: 2888
      name: zookeeper-peer
    - protocol: TCP
      port: 3888
      name: leader-election
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: zookeeper-deployment
  namespace: kafka
spec:
  replicas: 1
  selector:
    matchLabels:
      app: zookeeper
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        app: zookeeper
        k8s-app: kube-dns
    spec:
      containers:
        - name: zookeeper-container
          image: bitnami/zookeeper:latest
          env:
            - name: 'ALLOW_ANONYMOUS_LOGIN'
              value: 'yes'
            - name: 'ZOOKEEPER_ID'
              value: '1'
          ports:
            - containerPort: 2181
              name: zookeeper-port
            - containerPort: 2888
              name: zookeeper-peer
            - containerPort: 3888
              name: leader-election

我還有另一個部署:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafkacat-deployment
#  namespace: debug # I was using it from another namespace, but it was not working so I've tried to use the same
  namespace: kafka
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafkacat
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        app: kafkacat
        k8s-app: kube-dns
    spec:
      containers:
      - name: kafkacat-container
        image: edenhill/kafkacat:1.5.0

然后我嘗試 te.net 它,它有效。

telnet kafka-service.kafka 9092
Trying 10.101.87.127...
Connected to kafka-service.kafka.svc.cluster.local.
Escape character is '^]'.

這是 nslookup

nslookup kafka-service.kafka
Server:     10.96.0.10
Address:    10.96.0.10#53

Name:   kafka-service.kafka.svc.cluster.local
Address: 10.101.87.127

但是當我試圖達到它時,我得到的是:

kafkacat -b kafka-service.kafka:9092 -L
% ERROR: Failed to acquire metadata: Local: Timed out

所以我猜問題出在 Kafka 配置中:如果我評論 env var KAFKA_CFG_ADVERTISED_LISTENERS它會像這樣工作:

# kafkacat -b kafka-service.kafka:9092 -L
Metadata for all topics (from broker -1: kafka-service.kafka:9092/bootstrap):
 1 brokers:
  broker 1001 at kafka-deployment-858c5c7f98-tt7sr:9092
 2 topics:
  topic "my_topic" with 1 partitions:
    partition 0, leader 1001, replicas: 1001, isrs: 1001
  topic "__consumer_offsets" with 50 partitions:
    partition 0, leader 1001, replicas: 1001, isrs: 1001

如果我嘗試生成一條消息:

kafkacat -b kafka-service.kafka:9092 -P -t my_topic
oi
% ERROR: Local: Host resolution failure: kafka-deployment-858c5c7f98-w2dm5:9092/1001: Failed to resolve 'kafka-deployment-858c5c7f98-w2dm5:9092': Temporary failure in name resolution (after 15382734ms in state INIT)

然后,如果我嘗試消費:

kafkacat -b kafka-service.kafka:9092 -C -t my_topic
% ERROR: Local: Host resolution failure: kafka-deployment-858c5c7f98-w2dm5:9092/1001: Failed to resolve 'kafka-deployment-858c5c7f98-w2dm5:9092': Temporary failure in name resolution (after 15406287ms in state INIT)

我嘗試配置KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka-service.kafka.svc.cluster.local:9092但是當我嘗試使用 kafkacat 獲取信息時仍然超時。

這就是為什么通告的偵聽器是無法從本地計算機訪問的主機名的原因。 如何修復集群中的 Kafka 配置?

我應用了與您提供的完全相同的清單,只是在 kafka-deployment pod 上的 /dev/null 中添加了一個 follow tail,並且能夠生成和使用主題。

我在 k3d 中運行一個 k3s 集群:

└[~]> kubectl get nodes                                                    
NAME               STATUS   ROLES    AGE   VERSION
k3d-dev-server     Ready    master   31m   v1.17.3+k3s1
k3d-dev-worker-1   Ready    <none>   31m   v1.17.3+k3s1

kafka部署清單:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafkacat-deployment
  #  namespace: debug # I was using it from another namespace, but it was not working so I've tried to use the same
  namespace: kafka
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafkacat
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        app: kafkacat
        k8s-app: kube-dns
    spec:
      containers:
        - name: kafkacat-container
          image: edenhill/kafkacat:1.5.0
          resources: {}
          command:
            - sh
            - -c
            - "exec tail -f /dev/null"

來自 Kafka 命名空間中的 kafka-deployment pod 的終端日志:

/ # kafkacat -b kafka-service.kafka:9092 -L
Metadata for all topics (from broker 1001: kafka-service.kafka:9092/1001):
 1 brokers:
  broker 1001 at kafka-service.kafka:9092 (controller)
 0 topics:
/ # kafkacat -b kafka-service.kafka:9092 -P -t my_topic
hi from kafkacat

/ # kafkacat -b kafka-service.kafka:9092 -C -t my_topic
hi from kafkacat
% Reached end of topic my_topic [0] at offset 1

/ # kafkacat -b kafka-service:9092 -L
Metadata for all topics (from broker -1: kafka-service:9092/bootstrap):
 1 brokers:
  broker 1001 at kafka-service.kafka:9092 (controller)
 1 topics:
  topic "my_topic" with 1 partitions:
    partition 0, leader 1001, replicas: 1001, isrs: 1001
/ # kafkacat -b kafka-service:9092 -P -t my_topic
hi from kafka2

/ # kafkacat -b kafka-service:9092 -C -t my_topic
hi from kafkacat
hi from kafka2
% Reached end of topic my_topic [0] at offset 2

來自 debug 命名空間的 kafka-deployment 的終端日志:

└[~]> kubectl exec -it kafkacat-deployment-76f9c9db6d-8fth4 -n debug -- ash
/ # kafkacat -b kafka-service.kafka:9092 -L
Metadata for all topics (from broker 1001: kafka-service.kafka:9092/1001):
 1 brokers:
  broker 1001 at kafka-service.kafka:9092 (controller)
 1 topics:
  topic "my_topic" with 1 partitions:
    partition 0, leader 1001, replicas: 1001, isrs: 1001
/ # kafkacat -b kafka-service.kafka:9092 -P -t my_topic
hi from debug namespace

/ # kafkacat -b kafka-service.kafka:9092 -C -t my_topic
hi from kafkacat
hi from kafka2
hi from debug namespace
% Reached end of topic my_topic [0] at offset 3

在為 minikube 中的錯誤應用解決方法后,我也讓它在 minikube 中工作:

minikube ssh
sudo ip link set docker0 promisc on

刪除了正在運行的 kafka-deployment pod,它在兩個命名空間中都有效:

(⎈ |minikube:default)➜  ~ kubectl delete pod -n kafka kafka-deployment-5c4f64599f-kn9xt
pod "kafka-deployment-5c4f64599f-kn9xt" deleted
(⎈ |minikube:default)➜  ~ kubectl exec -n kafka -it kafkacat-deployment-b595d9ccd-4bht7 -- ash
/ # kafkacat -b kafka-service.kafka:9092 -L
Metadata for all topics (from broker 1003: kafka-service.kafka:9092/1003):
 1 brokers:
  broker 1003 at kafka-service.kafka:9092 (controller)
 0 topics:
/ # 
(⎈ |minikube:default)➜  ~ kubectl exec -n debug -it kafkacat-deployment-b595d9ccd-pgzv6 -- ash
/ # kafkacat -b kafka-service.kafka:9092 -L
Metadata for all topics (from broker 1003: kafka-service.kafka:9092/1003):
 1 brokers:
  broker 1003 at kafka-service.kafka:9092 (controller)
 0 topics:
/ #

免責聲明

這是使用融合的 docker 圖像進行測試的,它適用於我本地的 minikube 環境。

要從不同的名稱空間訪問 kafka,您可以使用類似以下的內容

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kafka-deployment
  namespace: kafka
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kafka
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        app: kafka
        k8s-app: kube-dns
    spec:
      containers:
        - name: kafka-container
          image: confluentinc/cp-kafka:latest
          env:
            - name: KAFKA_POD_IP
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
            - name: KAFKA_ADVERTISED_LISTENERS
              value: PLAINTEXT://${KAFKA_POD_IP}:9092
            - name: KAFKA_INTER_BROKER_LISTENER_NAME
              value: PLAINTEXT
            - name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
              value: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
            - name: KAFKA_ZOOKEEPER_CONNECT
              value: zookeeper-service:2181
          command: [ "sh","-c" ]
          args:
              - 'KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://${KAFKA_POD_IP}:9092" && /etc/confluent/docker/run'
          ports:
            - containerPort: 9092
              name: kafka-port
            - containerPort: 9094
              name: kafka-port-out
            - containerPort: 5555
              name: kafka-port-jmx
            - containerPort: 2181
              name: kafka-zk

請注意,盡管這是一種變通方法。

首選解決方案是為您的 kafka 服務器創建狀態集。 您將能夠通過 fqdn 引用 pod...

pod-name.stateful-setname.servicename

如果服務器出現故障,這也將為您提供更穩定的環境,有狀態集將以相同的名稱再次啟動。 這意味着您的聽眾不會摔倒。

https://kube.netes.io/docs/concepts/workloads/controllers/statefulset/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM