Kafka/Zookeeper instance on EC2: How to consume events using public IPs - deployment

I have a Kafka cluster running on EC2. The nodes are having internal as well as public IPs. I have configured the kafka config file server.properties with:
host.name=MY_PUBLIC_KAFKA_NODE_IP
I am looking for a configuration in which a dev-machine can consume the kafka events directly agnostic of internal/public IPs of kafka nodes. Only zookeeper node's public IP is exposed to the developers. With this configuration, when the dev-machine runs:
./bin/kafka-console-consumer.sh --zookeeper MY_PUBLIC_ZOOKEEPER_IP:2181 --topic test --from-beginning
I get following error:
[2016-01-18 19:00:57,388] WARN Fetching topic metadata with correlation id 61 for topics [Set(test)] from broker [id:1,host:ip-172-31-1-91.us-west-2.compute.internal,port:9092] failed (kafka.client.ClientUtils$)
java.nio.channels.ClosedChannelException
at kafka.network.BlockingChannel.send(BlockingChannel.scala:100)
at kafka.producer.SyncProducer.liftedTree1$1(SyncProducer.scala:73)
at kafka.producer.SyncProducer.kafka$producer$SyncProducer$$doSend(SyncProducer.scala:72)
at kafka.producer.SyncProducer.send(SyncProducer.scala:113)
at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:58)
at kafka.client.ClientUtils$.fetchTopicMetadata(ClientUtils.scala:93)
at kafka.consumer.ConsumerFetcherManager$LeaderFinderThread.doWork(ConsumerFetcherManager.scala:66)
at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:60)
The error suggests that the broker list contains internal IP of the kafka nodes. Is there a way to fix this configuration?

You need to set advertised.host.name property to an address/IP that will be resolvable by the client, which is in your case the AWS node's public address/IP.
You'll also have to allow inbound access in your AWS security group by adding your client's IP address there.
To do that, go to: Security groups > select the corresponding group > go to Inbound tab in the lower pane > click Edit > Add Rule > Custom TCP rule > TCP > 9092 > select My IP (if accessing AWS console from the client that's going to be used to access Kafka, otherwise add IP manually).

Related

Trouble with Apache Kafka to Allow External Connections

I'm just having a difficult time with Kafka right now, but I feel like I'm close.
I have two VMs on FreeNAS running locally. Both Running Ubuntu 18.04 LTS.
VM Graylog: 192.168.1.25. Running Graylog Server. Working well retrieving rsyslogs and apache from itself.
VM Kafka: 192.168.1.16. Running Kafka.
My goal is to have VM Graylog pull logs from VM Kafka, via a Graylog Kafka UDP input. The secondary goal is to replicate this, except tha the Kafka instance will sit on my VPS server feeding apache logs from a website. Of course, I want to test this in a dev environment first.
I am able to have my VM Kafka server successfully listen through this line of code:
/opt/kafka_2.13-2.6.0/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic rsyslog_kafka --from-beginning
This is my 60-kafka.conf file:
module(load="omkafka")
template(name="json"
type="list"
option.json="on") {
constant(value="{")
constant(value="\"#timestamp\":\"") property(name="timereported" dateFormat="rfc33$
constant(value="\",\"#version\":\"1")
constant(value="\",\"message\":\"") property(name="msg")
constant(value="\",\"host\":\"") property(name="hostname")
constant(value="\",\"severity\":\"") property(name="syslogseverity-text")
constant(value="\",\"facility\":\"") property(name="syslogfacility-text")
constant(value="\",\"programname\":\"") property(name="programname")
constant(value="\",\"procid\":\"") property(name="procid")
constant(value="\"}\n")
}
action(
broker=["192.168.1.16:9092"]
type="omkafka"
topic="rsyslog_kafka"
template="json"
)
I'm using the default server.properties file which doesn't contain any listeners, just the defaults. I do understand I need to set the listeners and advertised.listeners.
I've attempted the following settings to no avail:
Attempt 1:
listeners = PLAINTEXT://localhost:9092
advertised.listeners=PLAINTEXT://192.168.1.16:9092
Attempt 2:
listeners = PLAINTEXT://127.0.0.1:9092
advertised.listeners=PLAINTEXT://192.168.1.16:9092
This after reloading both Kafka and Rsyslog and confirming their statuses are active.
Example errors when attempting to read messages.
Bunch of these
[2020-08-20 00:52:42,248] WARN [Consumer clientId=consumer-console-consumer-70205-1, groupId=console-consumer-70205] Connection to node -1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
Followed by an infinite amount of these:
[2020-08-20 00:48:50,598] WARN [Consumer clientId=consumer-console-consumer-11975-1, groupId=console-consumer-11975] Error while fetching metadata with correlation id 254 : {rsyslog_kafka=LEADER_NOT_AVAILABLE} (org.apache.kafka.clients.NetworkClient)
I feel like I'm close. Perhaps there is something I'm just understanding. I've read lots of similar articles where they say just replace the IP addresses with your server. I feel like I've done that, with no success.
You need to set listeners to PLAINTEXT://0.0.0.0:9092 in order to bind externally.
The advertised listener ought to be set to an address that your consumers will be able to use to discover the cluster
Note: Docker Compose might be easier than VMs

Kafka consumer group script to see all consumer group not working

When I execute the below command in kafka
./kafka-consumer-groups.sh --bootstrap-server sample-address:9092 --list
I'm facing the below error
Error: Executing consumer group command failed due to org.apache.kafka.common.KafkaException: Failed to find brokers to send ListGroups
java.util.concurrent.ExecutionException: org.apache.kafka.common.KafkaException: Failed to find brokers to send ListGroups
at org.apache.kafka.common.internals.KafkaFutureImpl.wrapAndThrow(KafkaFutureImpl.java:45)
at org.apache.kafka.common.internals.KafkaFutureImpl.access$000(KafkaFutureImpl.java:32)
at org.apache.kafka.common.internals.KafkaFutureImpl$SingleWaiter.await(KafkaFutureImpl.java:89)
at org.apache.kafka.common.internals.KafkaFutureImpl.get(KafkaFutureImpl.java:262)
at kafka.admin.ConsumerGroupCommand$ConsumerGroupService.listGroups(ConsumerGroupCommand.scala:132)
at kafka.admin.ConsumerGroupCommand$.main(ConsumerGroupCommand.scala:58)
at kafka.admin.ConsumerGroupCommand.main(ConsumerGroupCommand.scala)
Caused by: org.apache.kafka.common.KafkaException: Failed to find brokers to send ListGroups
at org.apache.kafka.clients.admin.KafkaAdminClient$22.handleFailure(KafkaAdminClient.java:2610)
at org.apache.kafka.clients.admin.KafkaAdminClient$Call.fail(KafkaAdminClient.java:614)
at org.apache.kafka.clients.admin.KafkaAdminClient$TimeoutProcessor.handleTimeouts(KafkaAdminClient.java:730)
at org.apache.kafka.clients.admin.KafkaAdminClient$AdminClientRunnable.timeoutPendingCalls(KafkaAdminClient.java:798)
at org.apache.kafka.clients.admin.KafkaAdminClient$AdminClientRunnable.run(KafkaAdminClient.java:1092)
at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: org.apache.kafka.common.errors.TimeoutException: Timed out waiting for a node assignment.
In my case I noticed that we were using SSL
listeners=SSL://sample-address:9092
so I figured that I need to pass SSL properties in the command and it worked
bin/kafka-consumer-groups.sh --bootstrap-server sample-address:9092 --list --command-config /kafka/config/client-ssl.properties
client-ssl.properties
bootstrap.servers=sample-address:9092
security.protocol=SSL
ssl.truststore.location=/keys/truststore.jks
ssl.truststore.password=*****
ssl.keystore.location=/keys/keystore.jks
ssl.keystore.password=*****
After a lot of debugging, I have replicated this scenario and below solution working for me.
I have done changes in server.properties (that is mainly responsible for starting kafka server) instead of "localhost" pass "IP address" in listeners key.
Find detailed step below:-
These are configurations that you have to make sure while running a command.
Check for a correct IP address and port combination passed in command
bin/kafka-consumer-groups.sh --bootstrap-server 192.168.X.X:4848 --list
Main important point , configure listeners with IP address in server.properties correctly .
listeners=PLAINTEXT://**192.168.X.X:4848 --working**
listeners=PLAINTEXT://localhost:4848 --Not working
Post-change, restart kafka server.
Note:- This issue generally gets reproduce/comes in virtual box. After changing network setting like NAT to bridge.
I ran into the "Failed to find brokers to send ListGroups" problem but with the "Timed out waiting to send the call" exception.
In this case the problem was that the bootstrap server was not reachable from the machine where I was running the kafka-consumer-groups cli tool.
Since we have a VPC peering between our Kubernetes cluster in GCP and Confluent Cloud, I resolved the issue by executing the confluent cli tool inside the k8s cluster.

How to Setup a Public Kafka Broker Using a Dynamic DNS?

I configured a Kafka Cluster with 3 brokers using 3 Zookeepers along with each broker. Figure bellow presents a graphical representation of my cluster.
A producer and consumer test in the same network using the host 192.168.0.10 worked perfectly via kafka-console-producer and kafka-console-consumer commands.
Based on that context, when I try to produce some data via kafka-console-producer.sh --broker-list DYNAMIC_DNS_ADDR:30192,DYNAMIC_DNS_ADDR:30292,DYNAMIC_DNS_ADDR:30392 --topic twitter_tweets through the Internet, I am getting the following error:
[2018-12-10 09:59:20,772] ERROR Error when sending message to topic twitter_tweets with key: null, value: 16 bytes with error: (org.apache.kafka.clients.producer.internals.ErrorLoggingCallback)
org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for twitter_tweets-1: 1505 ms has passed since batch creation plus linger time
[2018-12-10 09:59:22,273] WARN [Producer clientId=console-producer] Connection to node 1 could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
Broker listeners are configured with the following properties:
listeners=PLAINTEXT://0.0.0.0:9092,SSL://0.0.0.0:9443
advertised.listeners=PLAINTEXT://192.168.0.241:9092,SSL://192.168.0.241:9443
Obviously, the IP address changed in each broker for the advertised.listeners property. I am using CentOS 6.10 and Kafka 2.0.1 for that setup. A telnet test worked. Another forward to a Kafka REST Proxy port is working via the Internet and listing all topics.
See https://rmoff.net/2018/08/02/kafka-listeners-explained/
You need two listeners—one responding to and advertising the internal addresses, one for the external one.
The key thing is that the listener that your client connects to will return the host address and port of that listener.
At the moment you're spoofing your external one to your internal one, and your external traffic is thus hitting the internal listener.
You need something like this (varying the IP/hostname of the aws_internal_listener as required per broker):
KAFKA_LISTENERS: aws_internal_listener://192.168.0.241:9092,external_listener://192.168.0.241:29092
KAFKA_ADVERTISED_LISTENERS: aws_internal_listener://192.168.0.241:9092,external_listener://DYNAMIC_DNS_ADDR:29092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: aws_internal_listener:PLAINTEXT,external_listener:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: aws_internal_listener
Then your port forwarder for DYNAMIC_DNS_ADDR should redirect connections to 29092 on the AWS node. The key thing is that external connections should not end up at the listener port on the host matching the internal listener (which advertises an internal 192.168.0 address)
Use kafkacat -L -b DYNAMIC_DNS_ADDR:29092 to debug and validate your config, as described in the article here.

unable to remove default kafka configuration in cloudera

In a PoC cloudera cluster provided with kafka(1 broker) I'm trying to send messages to the cluster with an external producer through a public IP. My cluster nodes are hosted in Azure and all of them are reachable from my local machine where the external producer is running.
Following this great article https://rmoff.net/2018/08/02/kafka-listeners-explained/ I figured out the kafka listeners config I need as this broker public IP is only reachable from my local machine and inside the cluster they can only communicate using their internal hostnames:
listeners=INTERNAL://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092
listener.security.protocol.map=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
advertised.listeners=INTERNAL://internal-broker-node-hostname:19092,EXTERNAL://public-broker-ip:9092
inter.broker.listener.name=INTERNAL
With this configuration when I try to start the broker I get this error:
org.apache.kafka.common.config.ConfigException: Only one of inter.broker.listener.name and security.inter.broker.protocol should be set.
Which makes sense as in Kafka doc for this property inter.broker.listener.name they say:
Name of listener used for communication between brokers. If this is unset, the listener name is defined by security.inter.broker.protocol. It is an error to set this and security.inter.broker.protocol properties at the same time.
The problem I'm facing is that I'm unable to unset security.inter.broker.protocol through the cloudera manager as I only have the option of switching options in a radio button.
How can I unset that property?
Internal and external are just strings
So, you could set PLAINTEXT for CDH and just redefine the external listener as being advertised
listeners=PLAINTEXT://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092
listener.security.protocol.map=EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
advertised.listeners=PLAINTEXT://internal-broker-node-hostname:19092,EXTERNAL://public-broker-ip:9092
You'll also want to make sure your external broker IPs are static

I can't produce data to Kafka when use the script, But I can list topics with the script

everybody,there is a virtual server in the local area network which ip is 192.168.18.230, and my machine ip is 192.168.0.175.
Today, I try to use my machine (192.168.0.175) to send some messages to my virtual server(192.168.18.230), with the Kafka console producer
$ bin/kafka-console-producer.sh --broker-list 192.168.18.230:9092 --topic test
but there is something wrong. The description of the problem is :
[2017-04-10 17:25:40,396] ERROR Error when sending message to topic test with key: null, value: 6 bytes with error: (org.apache.kafka.clients.producer.internals.ErrorLoggingCallback)
org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for test-0 due to 1568 ms has passed since batch creation plus linger time
But when I use the kafka-topics script to list topics, it works:
$ bin/kafka-topics.sh --list --zookeeper 192.168.18.230:2181
This problem confused me a very long period, can any body help me to solve it?
If you have a zookeeper instance which is running, you can of course ask the list of topics. However, it seems that you have no Kafka broker available.
You maybe have a zookeeper running but not Kafka.
Your Kafka producer might be running on a machine which cannot access your virtual machine where your Kafka broker is running.
Also, not only should the broker port be open, but also it must be answerable by the broker i.e, the (advertised) listeners of your Kafka broker must have your virtual machine IP (IP accessible from where your Kafka producer is running, because a VM can have multiple IPs and there is no rule that all IPs will be accessible).
For example, your virtual machine have two IPs 1.2.3.4 and 4.3.2.1 and your producer on another machine points to 1.2.3.4, you must be able first to ping and telnet to this IP.
Next, you must have this IP 1.2.3.4 in the advertised listeners in your Kafka broker.
advertised.listeners=PLAINTEXT://1.2.3.4:9092
You should set this IP only as your bootstrap.servers in your Kafka Producer.
You should also ensure that the port is not just open to localhost or 127.0.0.1 like for example, when you do netstat, it should not have just localhost:9092 or 127.0.0.1:9092, it should use any local address 0.0.0.0 or your IP 1.2.3.4:9092