Установка однозвенного кластера Apache ZooKeeper на Ubuntu 18.04

Что такое ZooKeeper
Apache ZooKeeper — централизованный сервис управления конфигурацией, именованием, распределённой синхронизацией и предоставлением групповых сервисов. Реализован на Java и даёт приложениям абстракцию общей иерархической базы данных (Znodes), что упрощает координацию распределённых процессов. ZooKeeper обеспечивает высокую пропускную способность, доступность, низкие задержки и управляемый доступ к Znodes. Чаще всего используется для хранения состояния, конфигураций и информации о расположении сервисов.
Важно: однозвенный экземпляр ZooKeeper подходит для тестов и разработки. Для отказоустойчивости создавайте кластер из нечётного числа узлов (3, 5 и т.д.).
Требования
- Сервер с Ubuntu 18.04.
- Доступ root или пользователь с sudo-привилегиями.
Подготовка системы
Сначала обновите пакетный индекс и установленные пакеты:
apt-get update -y
apt-get upgrade -y
После обновления перезагрузите систему, чтобы применить все изменения.
Установка Java
ZooKeeper написан на Java, поэтому нужен установленный JRE/JDK. В примере используется Oracle Java 11 из PPA (в исходном руководстве использован ppa:linuxuprising/java):
add-apt-repository ppa:linuxuprising/java
Обновите индекс и установите пакет по умолчанию для Oracle Java 11:
apt-get update -y
apt-get install oracle-java11-set-default
Проверьте версию Java:
java --version
Ожидаемый вывод (пример):
java 11.0.2 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.2+7-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.2+7-LTS, mixed mode)
Если вы предпочитаете OpenJDK, используйте openjdk-11-jre-headless или openjdk-11-jdk.
Создание пользователя ZooKeeper
Нельзя запускать сервисы от root. Создайте отдельного системного пользователя:
useradd zookeeper -m
usermod --shell /bin/bash zookeeper
Задайте пароль:
passwd zookeeper
Добавьте пользователя в группу sudo, если нужно выполнять административные действия от его имени:
usermod -aG sudo zookeeper
Установка ZooKeeper
Создайте каталог для данных ZooKeeper и задайте права:
mkdir -p /data/zookeeper
chown -R zookeeper:zookeeper /data/zookeeper
Перейдите в /opt и загрузите релиз ZooKeeper (в руководстве использована версия 3.4.9):
cd /opt
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.9/zookeeper-3.4.9.tar.gz
Распакуйте архив и переименуйте папку:
tar -xvzf zookeeper-3.4.9.tar.gz
mv zookeeper-3.4.9 zookeeper
chown -R zookeeper:zookeeper /opt/zookeeper
Замечание: используйте более новые версии ZooKeeper для продакшна; 3.4.9 здесь — пример из исходного руководства.
Настройка ZooKeeper
Создайте конфигурационный файл:
nano /opt/zookeeper/conf/zoo.cfg
Добавьте конфигурацию (приведён пример для однозвенного узла):
tickTime=2500
dataDir=/data/zookeeper
clientPort=2181
maxClientCnxns=80
Сохраните и закройте файл.
Запустите ZooKeeper вручную:
cd /opt/zookeeper
bin/zkServer.sh start
Ожидаемый вывод:
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
Подключитесь через клиент:
bin/zkCli.sh -server 127.0.0.1:2181
Пример приглашения после успешного подключения:
[zk: 127.0.0.1:2181(CONNECTED) 1]
Введите help, чтобы увидеть список доступных команд клиента.
Команды примера:
help
ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
... (и т.д.)
Для остановки сервера:
bin/zkServer.sh stop
Ожидаемый вывод:
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
Создание systemd-сервиса для ZooKeeper
Чтобы управлять ZooKeeper через systemd, создайте сервис-файл:
nano /etc/systemd/system/zookeeper.service
Вставьте следующие строки:
[Unit]
Description=Zookeeper Daemon
Documentation=http://zookeeper.apache.org
Requires=network.target
After=network.target
[Service]
Type=forking
WorkingDirectory=/opt/zookeeper
User=zookeeper
Group=zookeeper
ExecStart=/opt/zookeeper/bin/zkServer.sh start /opt/zookeeper/conf/zoo.cfg
ExecStop=/opt/zookeeper/bin/zkServer.sh stop /opt/zookeeper/conf/zoo.cfg
ExecReload=/opt/zookeeper/bin/zkServer.sh restart /opt/zookeeper/conf/zoo.cfg
TimeoutSec=30
Restart=on-failure
[Install]
WantedBy=default.target
Перезагрузите демона systemd, запустите и включите сервис при загрузке:
systemctl daemon-reload
systemctl start zookeeper
systemctl enable zookeeper
Проверка статуса:
systemctl status zookeeper
Пример вывода:
? zookeeper.service - Zookeeper Daemon
Loaded: loaded (/etc/systemd/system/zookeeper.service; disabled; vendor preset: enabled)
Active: active (running) since Wed 2019-03-06 15:03:01 UTC; 5s ago
Docs: http://zookeeper.apache.org
Process: 3909 ExecStart=/opt/zookeeper/bin/zkServer.sh start /opt/zookeeper/conf/zoo.cfg (code=exited, status=0/SUCCESS)
Main PID: 3926 (java)
Tasks: 17 (limit: 1113)
CGroup: /system.slice/zookeeper.service
??3926 java -Dzookeeper.log.dir=. -Dzookeeper.root.logger=INFO,CONSOLE -cp /opt/zookeeper/bin/../build/classes:/opt/zookeeper/bin/..
Mar 06 15:03:00 ubuntu1804 systemd[1]: Starting Zookeeper Daemon...
Mar 06 15:03:00 ubuntu1804 zkServer.sh[3909]: ZooKeeper JMX enabled by default
Mar 06 15:03:00 ubuntu1804 zkServer.sh[3909]: Using config: /opt/zookeeper/conf/zoo.cfg
Mar 06 15:03:01 ubuntu1804 zkServer.sh[3909]: Starting zookeeper ... STARTED
Mar 06 15:03:01 ubuntu1804 systemd[1]: Started Zookeeper Daemon.
Поздравляем — ZooKeeper установлен и управляется через systemd.
Безопасность и жёсткая настройка
В малом однозвенном развертывании безопасность часто упрощается, но для реальных сред выполните минимум этих шагов:
- Запускайте ZooKeeper под отдельным непривилегированным пользователем (как описано выше).
- Ограничьте доступ к порту 2181 межсетевым экраном (ufw/iptables), разрешив доступ только от доверенных хостов.
- Настройте аутентификацию и ACL для Znodes (SASL/ACL) перед запуском в публичной сети.
- Регулярно делайте резервные копии каталога dataDir (/data/zookeeper) и логов.
- Контролируйте JMX-доступ — выставляйте его только для мониторинга из доверенной сети.
Когда однозвенный ZooKeeper не подходит
- Для продакшн-кластеров с требованием отказоустойчивости: один узел — точка отказа. Используйте кластер из 3 или 5 узлов.
- Для сценариев с большой нагрузкой на запись: продумайте топологию и ресурсы JVM (heap, GC) и возможный шардинг поверх ZooKeeper.
- Если у вас нет контроля над сетью между узлами (нестабильные сети), потребуется настройка timeouts и резервных механизмов.
Альтернативные подходы
- Для простых координационных задач можно рассмотреть Consul, etcd или Redis (в зависимости от требований по семантике и консистентности).
- Для облачных окружений используйть управляемые сервисы (например, облачные ключи конфигурации) вместо собственного ZooKeeper.
Как перейти к многозвенной конфигурации (коротко)
- На каждом узле создайте тот же dataDir и установите одинаковый zoo.cfg с записями server.X.
- В /data/zookeeper создайте файл myid с числом X — идентификатором узла.
- Обеспечьте сетевую связность портов 2181 (клиенты), 2888 и 3888 (межузловая репликация), настройте firewall.
- Запустите все узлы — кворум сформируется.
Необходимые строки в zoo.cfg для кворума (пример):
server.1=10.0.0.1:2888:3888
server.2=10.0.0.2:2888:3888
server.3=10.0.0.3:2888:3888
Чек-листы по ролям
Sysadmin:
- Установить Java и системные зависимости.
- Создать пользователя zookeeper и каталоги данных.
- Настроить systemd-сервис и firewall.
- Настроить резервное копирование и мониторинг.
Разработчик:
- Проверить подключение клиента и список команд zkCli.sh.
- Создавать Znodes с ACL и тестировать сценарии чтения/записи.
- Проверять время отклика при пиковых нагрузках.
SRE/DevOps:
- Настроить метрики (JMX -> Prometheus), alerting и логирование.
- Тестировать восстановление из бэкапа и смену лидера в кворуме.
- Проводить плановые обновления и миграции без простоев.
Fact box — ключевые значения
- Дефолтный клиентский порт: 2181
- Примерная версия в руководстве: ZooKeeper 3.4.9
- Рекомендуемый минимум для кворума в продакшене: 3 узла (нечётное число)
- Язык реализации: Java (в примере Java 11)
Модель принятия решений
Если вы решаете, какой тип развёртывания нужен, используйте следующую логическую цепочку:
flowchart TD
A[Нужна отказоустойчивость?] -->|Да| B[Использовать 3+ узла]
A -->|Нет — тест/локально| C[Однозвенный ZooKeeper]
B --> D{Стабильная сеть между узлами}
D -->|Да| E[Развернуть на выделенных серверах]
D -->|Нет| F[Использовать управляемый сервис или облачное решение]
Критерии приёмки
- Сервис ZooKeeper запускается и находится в состоянии active (systemctl status).
- Клиент zkCli.sh успешно подключается к 127.0.0.1:2181 и выполняет базовые команды (ls, create, get).
- Доступ к порту 2181 ограничен только доверенными хостами.
- Директория dataDir заполняется и имеет корректные права владельца zookeeper:zookeeper.
Советы по отладке и распространённые ошибки
- Если сервис не стартует — проверьте логи /opt/zookeeper/logs и права на dataDir.
- Ошибка «NodeExists» при создании Znode означает, что узел уже существует — используйте set или delete.
- При формировании кворума проверьте синхронность часов на всех узлах (NTP). Несовпадение времени может вызывать проблемы с выбором лидера.
Резюме
Вы установили и настроили однозвенный Apache ZooKeeper на Ubuntu 18.04: подготовили систему, поставили Java, создали пользователя, скачали и настроили ZooKeeper, организовали systemd-сервис. Для продакшна планируйте многозвенную архитектуру, настройте безопасность и мониторинг.
Если нужно, я помогу:
- подготовить конфигурацию для 3-узлового кластера;
- добавить примеры безопасной аутентификации и ACL;
- написать unit-тесты для сценариев записи/чтения Znodes.
Краткое напоминание: однозвенный ZooKeeper хорош для разработки и тестов, но не для продакшна.