Глубокое погружение в проблемы подключения Kafka к ZooKeeper
Устранение неполадок подключения Kafka к ZooKeeper: практические проверки конфигурации, сети, таймаутов, логов и нагрузки на брокеры.
Глубокое погружение в проблемы подключения Kafka к ZooKeeper
Проблемы подключения Kafka к ZooKeeper в основном затрагивают старые кластеры Kafka и кластеры, которые не перешли на режим KRaft. Новые развертывания Kafka могут работать без ZooKeeper, но многие производственные системы по-прежнему зависят от него. Если ваши брокеры используют zookeeper.connect в server.properties, ZooKeeper все еще является частью вашей плоскости управления и заслуживает такого же внимания, как и сам Kafka.
Когда брокер Kafka не может поддерживать свою сессию ZooKeeper, симптомы могут выглядеть серьезнее, чем простая проблема подключения. Брокеры могут перезапускаться. Выборы контроллера могут повторяться. Разделы могут становиться недоступными. В логах могут появляться истечения сессий, отставки контроллера или повторные попытки подключения. Производители и потребители могут видеть только косвенный эффект: ошибки метаданных, таймауты или нестабильные лидеры.
Начните с роли ZooKeeper. В кластерах Kafka на основе ZooKeeper брокеры регистрируются там, выборы контроллера зависят от него, а координация метаданных кластера происходит через него. Если брокер теряет сессию ZooKeeper на достаточно долгое время для ее истечения, Kafka считает, что брокер покинул кластер. Даже если процесс брокера все еще работает, кластер может переместить лидерство от него.
Первая проверка проста и часто выявляет проблему: проверьте zookeeper.connect на каждом брокере.
zookeeper.connect=zk01.example.com:2181,zk02.example.com:2181,zk03.example.com:2181/kafka
zookeeper.connection.timeout.ms=18000
zookeeper.session.timeout.ms=18000
Строка подключения должна перечислять участников ансамбля, к которым Kafka может обратиться. Если вы используете chroot-путь, такой как /kafka, включайте его последовательно на каждом брокере. Не настраивайте половину брокеров с /kafka, а другую половину без него; они будут вести себя так, как будто общаются с разными кластерами Kafka. Если вы используете chroot, создайте его сначала или подтвердите его существование с помощью инструментов ZooKeeper.
Проверьте DNS, а также текст конфигурации. Имя хоста, которое правильно разрешается с вашего ноутбука, может не разрешаться из подсети брокера. Выполняйте проверки с хоста брокера Kafka, а не с бастиона, если только бастион не имеет того же сетевого пути.
getent hosts zk01.example.com
nc -vz zk01.example.com 2181
nc -vz zk02.example.com 2181
nc -vz zk03.example.com 2181
Успешное TCP-подключение не доказывает, что ZooKeeper здоров, но неудачное подключение достаточно, чтобы продолжить исследование брандмауэров, групп безопасности, маршрутизации, DNS или конфигурации слушателя. Проверьте каждый брокер Kafka на каждый узел ZooKeeper. Частичная связность хуже, чем полный сбой, потому что отказ может проявиться только тогда, когда брокер пытается подключиться к одному конкретному участнику ансамбля.
Четырехбуквенные команды ZooKeeper могут помочь, если они включены. Многие установки ограничивают их, поэтому не предполагайте, что они работают. Если разрешено, ruok должен вернуть imok, а mntr может показать полезную статистику сервера.
echo ruok | nc zk01.example.com 2181
echo mntr | nc zk01.example.com 2181
Если эти команды отключены, используйте поддерживаемые административные инструменты или ваш стек мониторинга. Суть в том, чтобы ответить на простой вопрос: слушает ли ZooKeeper, участвует ли в ансамбле и отвечает ли быстро?
Затем проверьте здоровье ансамбля ZooKeeper. Ансамбль из трех узлов может выдержать отказ одного узла ZooKeeper. Он не может выдержать два. Ансамбль из пяти узлов может выдержать два. Избегайте ансамблей четного размера, потому что они увеличивают стоимость без улучшения кворума так, как ожидают люди. Три и пять — распространенные варианты.
На стороне ZooKeeper посмотрите на zoo.cfg. Подтвердите clientPort, tickTime, initLimit, syncLimit и строки серверов. Убедитесь, что объявленные имена хостов серверов доступны между узлами ZooKeeper, а не только от брокеров Kafka. Пиры ZooKeeper нуждаются в своих собственных портах для кворума и выборов лидера. Брокер Kafka может достичь порта 2181, в то время как сам ансамбль ZooKeeper нездоров из-за блокировки пирового трафика.
Настройка таймаута сессии — еще один распространенный источник путаницы. Kafka запрашивает у ZooKeeper таймаут сессии, но ZooKeeper применяет ограничения на основе своей собственной конфигурации. В ZooKeeper минимальный таймаут сессии обычно составляет 2 * tickTime, а максимальный — 20 * tickTime, если не переопределено конкретными настройками сервера. Это означает, что значение таймаута Kafka вне допустимого диапазона может быть скорректировано ZooKeeper.
Если tickTime=2000, обычный допустимый диапазон сессии составляет примерно от 4 до 40 секунд. Настройка Kafka, такая как zookeeper.session.timeout.ms=18000, вписывается в этот диапазон. Очень низкий таймаут может вызывать ложные сбои во время коротких сетевых пауз или пауз сборки мусора. Очень высокий таймаут может замедлить обнаружение реальных сбоев брокера. Вы выбираете между чувствительностью и стабильностью.
Не меняйте tickTime без необходимости. Это влияет на ансамбль ZooKeeper, а не только на Kafka. Если вам нужна большая устойчивость к паузам брокера, часто лучше начать с пересмотра zookeeper.session.timeout.ms Kafka, поведения JVM брокера и состояния сети, прежде чем изменять тайминги ZooKeeper.
Логи обычно рассказывают историю, если выстроить их по временным меткам. На брокерах Kafka ищите сообщения об отключениях ZooKeeper и истечении сессий:
rg -i "zookeeper|session|expired|controller|reconnect" /var/log/kafka/server.log
Шаблоны важнее одной строки. Одноразовое переподключение во время планового перезапуска ZooKeeper может быть безвредным. Повторяющееся истечение каждые несколько минут указывает на нестабильность. Истечение во время сборки мусора указывает на паузы JVM или перегрузку брокера. Истечение в одно и то же время на многих брокерах указывает на ZooKeeper, сеть или общее событие инфраструктуры.
На узлах ZooKeeper проверьте изменения лидера, предупреждения fsync, ограничение подключений и задержку запросов. ZooKeeper чувствителен к задержкам диска, потому что записывает журналы транзакций. Медленный диск может сделать сервис доступным, но при этом неспособным отвечать достаточно быстро для стабильных сессий.
Сетевая задержка и потеря пакетов более важны для ZooKeeper, чем пропускная способность. Брокерам Kafka не нужна огромная пропускная способность к ZooKeeper, но им нужна надежная связь с низкой задержкой. Если брокеры и ZooKeeper разделены удаленными сетями, ожидайте проблем. Держите их рядом. В облачных средах избегайте маршрутизации трафика от брокера к ZooKeeper через ненужный NAT, перегруженные брандмауэры или кросс-региональные пути.
Конкуренция за ресурсы на брокере Kafka может выглядеть точно как проблема ZooKeeper. Если JVM останавливает мир для длительной паузы сборки мусора, брокер может пропустить пульс. Если ЦП насыщен, обработка пульса может быть задержана. Если хост застрял в высоком ожидании ввода-вывода, Kafka может не успевать за координационной работой. Проверьте метрики брокера в те же временные метки, что и отключения ZooKeeper.
Полезные вопросы на стороне брокера: увеличилось ли использование кучи перед отключением, увеличилось ли время паузы GC, было ли высоким ожидание дискового ввода-вывода, увеличились ли сетевые ретрансмиссии, и были ли в то же время крупные перераспределения разделов или перемещения лидеров? Брокер, тонущий под нагрузкой, может нуждаться в меньшем количестве лидеров разделов, лучшем диске, настройке JVM или переносе трафика. Увеличение таймаутов ZooKeeper может скрыть симптом, не устраняя причину.
Согласованность конфигурации легко упустить из виду. Все брокеры Kafka в одном кластере должны использовать одну и ту же строку подключения ZooKeeper и chroot. Они также должны иметь уникальные значения broker.id. Дублированный идентификатор брокера может вызвать путаницу в регистрации, потому что два процесса пытаются представлять одного и того же брокера.
Если вы недавно изменили имена хостов ZooKeeper, сертификаты, правила брандмауэра или конфигурации брокера Kafka, сравните работающий брокер с неисправным. Небольшие различия распространены: старый DNS-суффикс, отсутствующий chroot-путь, группа безопасности, прикрепленная к двум брокерам, но не к третьему, или опечатка в одном файле окружения systemd.
Восстановление зависит от того, что сломалось. Если отсутствовало правило брандмауэра, исправьте его и перезапустите затронутый брокер, если он не переподключается чисто. Если ZooKeeper потерял кворум, сначала восстановите кворум, прежде чем перезапускать брокеры Kafka. Если брокер истек из-за перегрузки, перезапуск может временно вернуть его, но проблема вернется, если не снять давление.
Используйте последовательные перезапуски. Перезапуск всех брокеров Kafka сразу из-за нестабильности ZooKeeper может превратить частичный сбой в полный. Восстановите здоровье ZooKeeper, затем перезапускайте или восстанавливайте брокеры по одному, наблюдая за стабильностью контроллера и лидерством разделов.
Для долгосрочной стабильности мониторьте обе стороны. На ZooKeeper следите за задержкой запросов, ожидающими запросами, изменениями лидера, статусом синхронизации последователей, дисковым пространством и перезапусками процессов. На Kafka следите за изменениями контроллера, офлайн-разделами, недореплицированными разделами, перезапусками брокеров и логами, упоминающими истечение сессии ZooKeeper. Оповещайте о повторяющихся шаблонах, а не только о полной смерти процесса.
Самое чистое решение для команд, планирующих более крупное обновление, может быть миграция от ZooKeeper к режиму KRaft Kafka. Это проект, а не шаг реагирования на инцидент. Он требует планирования версий, проверок совместимости и тщательной миграционной работы. До тех пор относитесь к ZooKeeper как к производственной инфраструктуре. Держите его маленьким, близким к Kafka, последовательно настроенным, мониторимым и скучным.
Один практический шаблон runbook — создать небольшую матрицу во время инцидента. Поместите брокеры Kafka на одну ось, а узлы ZooKeeper на другую. Заполните каждую ячейку результатом nc -vz host 2181 и, если доступно, простой проверкой здоровья ZooKeeper. Это превращает расплывчатые отчеты "Kafka не может достичь ZooKeeper" в видимый шаблон. Если каждый брокер не может достичь zk02, исследуйте zk02 или его сетевой путь. Если только broker-4 не может достичь каждого узла ZooKeeper, исследуйте хост этого брокера, таблицу маршрутизации, DNS или брандмауэр.
Синхронизация времени также может иметь значение. Механика сессий ZooKeeper не требует идеально одинаковых настенных часов для каждой операции, но сильно смещенные часы затрудняют интерпретацию логов и могут нарушить окружающую автоматизацию, сертификаты и мониторинг. Поддерживайте NTP или chrony здоровыми на узлах Kafka и ZooKeeper. Когда временные метки расходятся во время сбоя, люди тратят время на поиск неправильной последовательности событий.
Будьте осторожны с контейнеризированными или оркестрированными развертываниями ZooKeeper. ZooKeeper хранит идентичность и данные на диске. Если поды перемещаются и теряют постоянную идентичность, или если обнаружение сервисов направляет клиентов на узлы, которые не готовы, Kafka может видеть нестабильное поведение подключения. Идентичность в стиле StatefulSet, постоянные тома, стабильный DNS и проверки готовности имеют значение. Ансамбль ZooKeeper не должен вести себя как набор одноразовых статлесс веб-подов.
Настройки безопасности добавляют еще один слой. Если недавно были введены SASL, TLS или сетевая политика, сбои подключения могут сначала выглядеть как простые проблемы достижимости. Проверьте, показывают ли логи Kafka ошибки аутентификации, ошибки рукопожатия или ошибки авторизации, а не таймауты TCP. Порт может быть открыт, в то время как сессия все еще терпит неудачу, потому что брокер не может аутентифицироваться в ZooKeeper.
После инцидента сохраните краткую запись точного симптома, коренной причины и исправления. Проблемы ZooKeeper часто повторяются, потому что первоначальный ремонт был локальным: одно правило брандмауэра, один перезапуск брокера, одно увеличение таймаута. Хорошая заметка после инцидента должна указывать, был ли у кластера кворум, какие брокеры потеряли сессии, уменьшился ли ISR, изменился ли контроллер, и какой мониторинг поймает это раньше в следующий раз.
Если вы устраняете неполадки из Kubernetes или другого планировщика, также проверьте, где приземлились рабочие нагрузки Kafka и ZooKeeper. Сетевая проблема на уровне узла, проблема с диском или событие нехватки ЦП могут повлиять только на поды, запланированные там. Перемещение пода может показаться исправлением проблемы, но реальная проблема может быть на хосте. Сравните события и метрики узлов, прежде чем объявлять приложение исправленным.
Резервные копии и снимки требуют осторожности. Каталоги данных ZooKeeper не следует снимать casually, пока процесс активен, если ваш метод резервного копирования не предназначен для этого. Для метаданных Kafka поврежденное или устаревшее состояние ZooKeeper может быть чрезвычайно разрушительным. Следуйте поддерживаемым практикам резервного копирования ZooKeeper и тестируйте процедуры восстановления вдали от производства. Резервная копия, которую никто не восстанавливал, — это только надежный файл.
Лучшее профилактическое действие — держать ZooKeeper скучным. Не размещайте его вместе с тяжелыми брокерами Kafka, если можете этого избежать. Держите его диски надежными. Держите размер кучи консервативным и мониторимым. Ограничьте тех, кто может изменять состав ансамбля. Большинство инцидентов ZooKeeper, которые я видел, были вызваны не экзотическими ошибками; они произошли из-за обычного дрейфа инфраструктуры вокруг небольшого сервиса, который все забыли, что он критичен.