I'm trying to acces kafka from outside kubernetes on my local machine. I'm using spring application to produce events on a topic. This is my deployment file for kafka:
kind: Deployment
metadata:
name: kafka-broker0
labels:
app: kafka
spec:
replicas: 2
selector:
matchLabels:
app: kafka
id: "0"
template:
metadata:
labels:
app: kafka
id: "0"
spec:
containers:
- name: kafka
image: wurstmeister/kafka
ports:
- containerPort: 9092
env:
- name: KAFKA_ADVERTISED_PORT
value: "30718"
- name: KAFKA_ADVERTISED_HOST_NAME
value: 192.168.1.240
- name: KAFKA_ZOOKEEPER_CONNECT
value: zoo1:2181
- name: KAFKA_BROKER_ID
value: "0"
- name: KAFKA_CREATE_TOPICS
value: LaunchScraper:1:1
And service file id:
kind: Service
metadata:
name: kafka-services
labels:
name: kafka
spec:
selector:
app: kafka
id: "0"
ports:
- protocol: TCP
name: kafka-port
port: 9092
type: NodePort
I've allready created a zookeeper pod on kubernetes. My spring boot application shows this error:
2020-09-25 23:56:29.123 WARN 44324 --- [ad | producer-1] org.apache.kafka.clients.NetworkClient : [Producer clientId=producer-1] Connection to node -1 (/192.168.1.240:9092) could not be established. Broker may not be available.
Deploying Kafka on Kubernetes was actually not as trivial as I first thought, but it worked after many trials and errors. Many examples you find on the internet did not work for me with the current version of Kubernetes / Kafka. What worked was:
A working example config would be (as replacement for your Deployment and Service, probably not minimal):
apiVersion: v1
kind: Service
metadata:
labels:
service: kafka
name: kafka
spec:
type: NodePort
ports:
- name: "9092"
port: 9092
protocol: TCP
targetPort: 9092
- name: "9093"
port: 9093
protocol: TCP
targetPort: 9093
- name: "32092"
port: 32092
protocol: TCP
targetPort: 32092
nodePort: 32092
selector:
service: kafka-instance
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
service: kafka-instance
name: kafka-instance
spec:
selector:
matchLabels:
service: kafka-instance
serviceName: "kafka"
replicas: 1
template:
metadata:
labels:
service: kafka-instance
spec:
containers:
- env:
- name: MY_HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: MY_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KAFKA_ADVERTISED_LISTENERS
value: INTERNAL://$(MY_POD_NAME).kafka.default.svc.cluster.local:9093,CLIENT://$(MY_POD_NAME).kafka.default.svc.cluster.local:9092,EXTERNAL://$(MY_HOST_IP):32092
- name: KAFKA_INTER_BROKER_LISTENER_NAME
value: INTERNAL
- name: KAFKA_LISTENERS
value: INTERNAL://:9093,CLIENT://:9092,EXTERNAL://:32092
- name: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP
value: INTERNAL:PLAINTEXT,CLIENT:PLAINTEXT,EXTERNAL:PLAINTEXT
- name: KAFKA_PORT
value: "9092"
- name: KAFKA_RESTART_ATTEMPTS
value: "10"
- name: KAFKA_RESTART_DELAY
value: "5"
- name: KAFKA_ZOOKEEPER_CONNECT
value: zoo1:2181
- name: KAFKA_ZOOKEEPER_SESSION_TIMEOUT
value: "6000"
- name: ZOOKEEPER_AUTOPURGE_PURGE_INTERVAL
value: "0"
image: wurstmeister/kafka
name: kafka-instance
ports:
- containerPort: 9092
If you don't already have a zookeeper, just add that and it should work:
apiVersion: v1
kind: Service
metadata:
labels:
service: zoo1
name: zoo1
spec:
ports:
- name: "2181"
port: 2181
targetPort: 2181
selector:
service: zoo1-instance
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
service: zoo1-instance
name: zoo1-instance
spec:
selector:
matchLabels:
service: zoo1-instance
serviceName: "zoo1"
replicas: 1
template:
metadata:
labels:
service: zoo1-instance
spec:
containers:
- image: wurstmeister/zookeeper
name: zoo1-instance
ports:
- containerPort: 2181
It seems like you've not fixed a nodePort in your service. When you make it to the value you've entered in KAFKA_ADVERTISED_PORT. Also set the KAFKA_ADVERTISED_HOST to your K8s node hostname/DNS.
In the spec for your sevice add nodePort: 30718
under the ports
entry. Then in your client, try to connect on 30718 port using the node's address or hostname
Also, if you're looking to deploy Kafka on production, I'd recommend using operators like Strimzi https://Strimzi.io