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/kafka
la imagen. Uso confluentinc
una imagen basada que no es lo mismo.
Solución del problema
Descargo de responsabilidadtl; 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.listeners
en el corredor. Asegúrese de que la dirección y los servidores enumerados como parte de bootstrap.servers
sean realmente resolubles ( ping
una IP/nombre de host, use netcat
para 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 confluentinc
imá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
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:9092
ejecutando 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:PLAINTEXT
que 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. ( kafka
aquí 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:29092
para la asignación de puerto de host
(con la configuración anterior)
Y si algo aún no funciona, KAFKA_LISTENERS
se 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:29092
para servidores de arranque y localhost:2181
para 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 PLAINTEXT
configuración de escucha anunciada arriba) para servidores de arranque y zookeeper:2181
para Zookeeper, al igual que cualquier otra comunicación de servicio de Docker (no requiere ningún reenvío de puerto)
Si usa docker run
comandos separados o Componer archivos, debe definir un archivo compartido network
manualmente
Consulte el archivo Compose de ejemplo para la pila completa de Confluent o uno más mínimo para un solo intermediario.
Pregunta relacionadaConéctese a Kafka en el host desde Docker (ksqlDB)
ApéndicePara cualquier persona interesada en las implementaciones de Kubernetes: https://operatorhub.io/?keyword=Kafka
No hay comentarios:
Publicar un comentario