Приключения с Kafka

Опубликовано: 22 авг. 2025 г.

На днях пришлось решать весьма любопытную проблему с подключением к Kafka. Возникла необходимость из защищенного контура подключаться к внешнему кластеру Kafka. На вход Python клиента подаются три ноды кластера, их адреса известны. Поды в защищенном контуре не имеют прямого доступа в интернет. Все HTTP запросы выполняются через специально поднятый прокси. Но Kafka работает не по HTTP. Для таких целей и прокси есть особый режим - в HTTP заголовках передается хост и порт, к которому требуется открыть тоннель, после обмена заголовками HTTP соединение остается активным. Далее сокет из этого HTTP соединения можно использовать как TCP тоннель к заданному порту. Но есть проблема - клиенту Kafka нельзя передать на вход сокет для подключения.

Решение проблемы с туннелем

Внутри того же Python процесса поднимается сокет слушающий на локальном порту и loopback интерфейсе и проксирует весь трафик в HTTP сокет полученный от внешнего прокси. Клиент Kafka в свою очередь подключается уже к локальному порту

Но ведь недостаточно иметь подключение лишь к одной ноде кластера. Клиент при подключении к любой из нод получает текущую топологию кластера и для стабильной работы должен иметь возможность подключаться к любой из нод. Одним туннелем здесь не обойтись. Открыть тоннель до каждого из целевых хостов не проблема, но при этом нужно каким-то образом сообщить об этих туннелях клиенту Kafka

Решение проблемы с несколькими нодами

На транспортном уровне роутинг по домену мы организовать не можем, а подключаться нужно к одному и тому же loopback интерфейсу. С другой стороны, ничто не мешает создать новые виртуальные loopback интерфейсы и каждому из них в файле hosts присвоить одному из доменов кластера Kafka. После чего для клиента Kafka все начинает работать совершенно прозрачным образом