Para que desde el exterior de una red puedan conectarse a dicha red hay que definir advertised.listeners
. Si usamos docker, KAFKA_ADVERTISED_LISTENERS
.
Cuándo un cliente se conecta a un clúster lo primero que hace es pedir los metadatos para saber qué bróker es el líder del clúster. Estos metadatos contienen la dirección de los endpoints disponibles para conectarse al líder.
LISTENERS
interfaces a las que se conecta KafkaADVERTISED_LISTENERS
cómo los clientes se nos conectanEn la web de Confluent está la guía que he usado para extraer la información de este documento. Allí hay una explicación mucho más extendida. Se trata incluso cómo conectar desde máquinas externas, no solo dentro de la misma máquina.
Vamos a usar compose, en concreto las imágenes de debezium de quay. Es importante saber la distribución porque la forma de nombrar las variables cambia entre ellas.
Usamos docker-compose.yml. Ahí definimos dos parámetros fundamentales:
El primero corresponde con listeners en la configuración de Kafka, el segundo con advertised.listeners.
Como hemos dicho, hay que decirle a Kafka:
Cuando se le pasa la ruta inicial de uno de los broker del clúster a un cliente, este se conecta con dicho broker el cual en respuesta le pasará unos metadatos donde van incluidas las direcciones especificadas en advertised_listeners, que serán las que usen finalmente los clientes para poder conectarse.
Dicho todo lo anterior, es fácil entender que en advertised tendremos que referirnos a puertos accesibles desde el exterior, por lo que la ruta tendrá que ser localhost, y no el nombre/identificador del servicio dentro de la red.
En resumen, tenemos dos situaciones:
En este caso basta con usar el nombre del servicio donde corre el broker como host al que conectarse desde dentro de la red. Típicamente kafka0, kafka1, etc.
Lo habitual será conectarnos a localhost, a un puerto expuesto fuera de la red privada. Los metadatos devolverán como comentamos los datos de advertised_listener. Como nos queremos conectar desde el exterior necestiamos que todos los broker del clUster tengan un puerto expuesto, que no puede ser el mismo para evitar conflictos, para poder conectarnos a dicho puerto.
Si tenemos por ejemplo 3 brokers, definiremos tal queremos
kafka1:
hostname: kafka1
ports:
- 9095:9095
environment:
- KAFKA_LISTENERS=INTERNAL://kafka1:9092,EXTERNAL://0.0.0.0:9095,CONTROLLER://kafka1:29092
- KAFKA_ADVERTISED_LISTENERS=INTERNAL://kafka1:9092,EXTERNAL://localhost:9095
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:INTERNAL,INTERNAL:INTERNAL,EXTERNAL:INTERNAL
kafka2:
hostname: kafka2
ports:
- 9096:9096
environment:
- KAFKA_LISTENERS=INTERNAL://kafka2:9092,EXTERNAL://0.0.0.0:9096,CONTROLLER://kafka2:29092
- KAFKA_ADVERTISED_LISTENERS=INTERNAL://kafka2:9092,EXTERNAL://localhost:9096
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:INTERNAL,INTERNAL:INTERNAL,EXTERNAL:INTERNAL
kafka3:
hostname: kafka3
ports:
- 9097:9097
environment:
- KAFKA_LISTENERS=INTERNAL://kafka3:9092,EXTERNAL://0.0.0.0:9097,CONTROLLER://kafka3:29092
- KAFKA_ADVERTISED_LISTENERS=INTERNAL://kafka3:9092,EXTERNAL://localhost:9097
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:INTERNAL,INTERNAL:INTERNAL,EXTERNAL:INTERNAL
Si por ejemplo queremos conectarnos con kafka-ui, y éste se encuentra en la misma red, tendremos que especificar, a la hora de configurar el clúster, host: kafka1
, port: 9092
. Si nos queremos conectar a este mismo clúster con conduktor, en cambio, tendremos que especificar, para conectarnos al primer broker, host: localhost
, port: 9095
.
Para más información genérica sobre redes en docker, ver Redes en Docker.