GOOGLE ADS

lunes, 25 de abril de 2022

Conéctese a Kafka ejecutándose en Docker

Configuré un contenedor Kafka Docker de un solo nodo en mi máquina local como se describe en la documentación de Confluent (pasos 2-3).

Además, también expuse el puerto 2181 de Zookeeper y el puerto 9092 de Kafka para poder conectarme a ellos desde un cliente que se ejecuta en una máquina local:

$ docker run -d \
-p 2181:2181 \
--net=confluent \
--name=zookeeper \
-e ZOOKEEPER_CLIENT_PORT=2181 \
confluentinc/cp-zookeeper:4.1.0
$ docker run -d \
--net=confluent \
--name=kafka \
-p 9092:9092 \
-e KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092 \
-e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \
confluentinc/cp-kafka:4.1.0

Problema: cuando intento conectarme a Kafka desde la máquina host, la conexión falla porque can't resolve address: kafka:9092.

Aquí está mi código Java:

Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("client.id", "KafkaExampleProducer");
props.put("key.serializer", LongSerializer.class.getName());
props.put("value.serializer", StringSerializer.class.getName());
KafkaProducer<Long, String> producer = new KafkaProducer<>(props);
ProducerRecord<Long, String> record = new ProducerRecord<>("foo", 1L, "Test 1");
producer.send(record).get();
producer.flush();

La excepción:

java.io.IOException: Can't resolve address: kafka:9092
at org.apache.kafka.common.network.Selector.doConnect(Selector.java:235) ~[kafka-clients-2.0.0.jar:na]
at org.apache.kafka.common.network.Selector.connect(Selector.java:214) ~[kafka-clients-2.0.0.jar:na]
at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:864) [kafka-clients-2.0.0.jar:na]
at org.apache.kafka.clients.NetworkClient.ready(NetworkClient.java:265) [kafka-clients-2.0.0.jar:na]
at org.apache.kafka.clients.producer.internals.Sender.sendProducerData(Sender.java:266) [kafka-clients-2.0.0.jar:na]
at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:238) [kafka-clients-2.0.0.jar:na]
at org.apache.kafka.clients.producer.internals.Sender.run(Sender.java:176) [kafka-clients-2.0.0.jar:na]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]
Caused by: java.nio.channels.UnresolvedAddressException: null
at sun.nio.ch.Net.checkAddress(Net.java:101) ~[na:1.8.0_144]
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:622) ~[na:1.8.0_144]
at org.apache.kafka.common.network.Selector.doConnect(Selector.java:233) ~[kafka-clients-2.0.0.jar:na]
... 7 common frames omitted

Pregunta: ¿Cómo conectarse a Kafka ejecutándose en Docker? Mi código se ejecuta desde la máquina host, no desde Docker.

Nota: sé que teóricamente podría jugar con la configuración de DNS y /etc/hosts, sin embargo, es una solución alternativa, no debería ser así.

También hay una pregunta similar aquí, sin embargo, se basa en ches/kafkala imagen. Uso confluentincuna imagen basada que no es lo mismo.


Solución del problema

Descargo de responsabilidad

tl; dr: un reenvío de puerto simple desde el contenedor al host no funcionará, y no se deben modificar los archivos de host. ¿A qué IP/nombre de host + puerto exacto desea conectarse? Asegúrese de que el valor esté establecido como advertised.listenersen el corredor. Asegúrese de que la dirección y los servidores enumerados como parte de bootstrap.serverssean realmente resolubles ( pinguna IP/nombre de host, use netcatpara verificar los puertos...)

A continuación, se brindan respuestas para las imágenes Kafka de uso común, pero es el mismo Apache Kafka ejecutándose en un contenedor.
Solo dependes de cómo esté configurado. Y qué variables lo hacen así.

La siguiente respuesta usa confluentincimágenes acoplables para abordar la pregunta que se hizo, no wurstmeister/kafka. Más específicamente, las últimas imágenes no están bien mantenidas a pesar de ser una de las imágenes acoplables de Kafka más populares.

Las siguientes secciones intentan agregar todos los detalles necesarios para usar otra imagen.

wurstmeister/kafka

Consulte su sección README sobre la configuración del oyente. También lea su wiki de conectividad.

bitnami/kafka

Si quieres un recipiente pequeño, prueba estos. Las imágenes son mucho más pequeñas que las de Confluent y están mucho mejor mantenidas que las de wurstmeister. Consulte su README para la configuración del oyente.

debezium/kafka

Los documentos al respecto se mencionan aquí.

Nota: la configuración de host y puerto anunciada está obsoleta. Los oyentes anunciados cubren ambos. Al igual que los contenedores de Confluent, Debezium puede usar KAFKA_configuraciones de intermediario prefijadas para actualizar sus propiedades.

Otros

spotify/kafka is deprecated and outdated.
fast-data-dev or lensesio/box are great for an all in one solution, but are bloated if you only want Kafka
Your own Dockerfile - Why? Is something incomplete with these others? Start with a pull request, not starting from scratch.

For supplemental reading, a fully-functional docker-compose, and network diagrams, see this blog by @rmoff

Responder

El documento de inicio rápido de Confluent (Docker) asume que todas las solicitudes de producción y consumo estarán dentro de la red de Docker.

Puede solucionar el problema de conectarse kafka:9092ejecutando su código de cliente de Kafka dentro de su propio contenedor, ya que usa el puente de red de Docker, pero de lo contrario, deberá agregar algunas variables de entorno más para exponer el contenedor externamente, sin dejar de funcionar dentro. la red Docker.

Primero agregue una asignación de protocolo PLAINTEXT_HOST:PLAINTEXTque asignará el protocolo de escucha a un protocolo Kafka

Clave: KAFKA_LISTENER_SECURITY_PROTOCOL_MAP Valor:PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT

Luego configure dos oyentes anunciados en diferentes puertos. ( kafkaaquí se refiere al nombre del contenedor de la ventana acoplable; también podría tener un nombre broker, así que verifique dos veces su servicio + nombres de host). Observe que los protocolos coinciden con los valores del lado derecho de las asignaciones anteriores

Clave: KAFKA_ADVERTISED_LISTENERS Valor:PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092

Al ejecutar el contenedor, agregue -p 29092:29092para la asignación de puerto de host

tl; dr

(con la configuración anterior)

Y si algo aún no funciona, KAFKA_LISTENERSse puede configurar para incluir <PROTOCOL>://0.0.0.0:<PORT>dónde ambas opciones coinciden con la configuración anunciada y el puerto reenviado por Docker

Cliente en la misma máquina, no en un contenedor

La publicidad de localhost y el puerto asociado le permitirá conectarse fuera del contenedor, como era de esperar.

En otras palabras, cuando ejecute cualquier cliente de Kafka fuera de la red de Docker (incluidas las herramientas de la CLI que podría haber instalado localmente), utilícelo localhost:29092para servidores de arranque y localhost:2181para Zookeeper (requiere el reenvío de puertos de Docker)

Cliente en otra máquina

Si intenta conectarse desde un servidor externo, deberá anunciar el nombre de host externo/IP del host, así como/en lugar de localhost.
Simplemente anunciar localhost con un reenvío de puerto no funcionará porque el protocolo Kafka seguirá publicitando los oyentes que ha configurado.

Esta configuración requiere el reenvío de puertos Docker y el reenvío de puertos del enrutador (y cambios en el firewall/grupo de seguridad) si no está en la misma red local, por ejemplo, su contenedor se está ejecutando en la nube y desea interactuar con él desde su máquina local.

Cliente en un contenedor, en el mismo host

Esta es la configuración menos propensa a errores; puede usar nombres de servicio DNS directamente.

Cuando ejecute una aplicación en la red de Docker, use kafka:9092(consulte la PLAINTEXTconfiguración de escucha anunciada arriba) para servidores de arranque y zookeeper:2181para Zookeeper, al igual que cualquier otra comunicación de servicio de Docker (no requiere ningún reenvío de puerto)

Si usa docker runcomandos separados o Componer archivos, debe definir un archivo compartido networkmanualmente

Consulte el archivo Compose de ejemplo para la pila completa de Confluent o uno más mínimo para un solo intermediario.

Pregunta relacionada

Conéctese a Kafka en el host desde Docker (ksqlDB)

Apéndice

Para cualquier persona interesada en las implementaciones de Kubernetes: https://operatorhub.io/?keyword=Kafka

No hay comentarios:

Publicar un comentario

Regla de Firestore para acceder a la generación de subcolección Permisos faltantes o insuficientes

Tengo problemas con las reglas de Firestore para permitir el acceso a algunos recursos en una subcolección. Tengo algunos requests document...