Появилась задачка мигрировать ZooKeeper-сервера на новые, при этом Kafka должна продолжать работать.
Просто взять и подменить адреса в server.properties — не вариант: Kafka хранит в ZooKeeper своё состояние, и при переключении на “чистый” кластер всё развалится.
Перенос dataDir с остановкой тоже не подходит — будет простой.
Есть третий, рабочий способ: расширяем текущий кластер ZooKeeper новыми нодами и потом исключаем старые. Рассказываю, как сделал это у себя.
Вводные:
Был ZooKeeper-кластер из 3 старых нод.
Новые — тоже 3, плюс одна временная для обеспечения кворума.
Новые сервера за NAT: внешние адреса доступны со старых, но не существуют локально на новых машинах.
Подготовка:
На старых нодах в zoo.cfg включаем:
reconfigEnabled=true
А в zkEnv.sh добавляем временно:
export SERVER_JVMFLAGS="$SERVER_JVMFLAGS -Dzookeeper.skipACL=yes"
Это нужно, чтобы не возиться с ACL при реконфигурации.
Добавляем новые ноды:
Разворачиваем ZooKeeper на новых машинах (как угодно — вручную, Ansible), но не запускаем его.
На старой ZooKeeper-ноде:
zkCli.sh
reconfig -add server.4=<dns_name>:2888:3888:participant;2181
Указываем DNS-имя новой ноды (резолвится во внешний IP).
ZooKeeper создаёт новый zookeeper.cfg.dynamic.<id> и прописывает его в zoo.cfg автоматически.
Запускаем ZooKeeper на новой, только что добавленной ноде.
Проблема с bind’ом:
Когда запускаем zk-4, видим, что он не может создать сокет на внешнем IP, ведь он не существует на машине (из-за NAT).
Поэтому на новой ноде руками правим zookeeper.cfg.dynamic.<id>, заменяя внешний адрес на внутренний, локальный IP ноды (из NAT-сети).
Повторяем для остальных нод
Каждый раз при reconfig -add создаётся новый dynamic config, и снова приходится вручную править IP-адреса на новых серверах.
Переключение Kafka
Когда в ZooKeeper уже 7 нод (3 старых + 4 новых), на Kafka-брокерах в server.properties указываем новые адреса ZooKeeper, а старые пока оставляем:
zookeeper.connect=new1:2181,new2:2181,new3:2181,old1:2181,old2:2181
Рестартим Kafka.
Удаление старых нод
На одной из новых нод:
zkCli.sh
reconfig -remove <old_id>
Удаляем старые ноды по myid.
ZooKeeper снова создаст новый конфиг — и его снова нужно поправить на новых машинах (внутренние IP вместо внешних).
Удаляем старые ZooKeeper-адреса из server.properties Kafka
Останавливаем старые ZooKeeper-ноды
На новых ZooKeeper:
Убираем skipACL
Можно убрать reconfigEnabled, если не нужен
В итоге переезд выполнен без downtime на работающем кластере kafka.
#zookeeper