Перейти к основному содержимому
Версия: 3.0

Кластер с резервным узлом

Два сервера с одинаковой установкой используют одну базу данных PostgreSQL, но платформа работает только на одном из них. Если основной узел выходит из строя, платформу запускают на резервном, и он продолжает работу с теми же данными. Общие требования к кластеру и сравнение с вариантом распределения нагрузки — в разделе Установка в режиме кластера. Если диалогов больше, чем выдерживает один сервер, используйте распределение нагрузки.

Два работающих узла нельзя

В этой схеме платформа работает только на одном узле. Если запустить её на обоих, каждый экземпляр будет держать ботов и настройки в собственной памяти и не узнает об изменениях, сделанных на другом. Если вы случайно запустили платформу на обоих узлах, остановите резервный и перезапустите основной.

Схема​

Два узла iQBot за единым адресом, общая база данных PostgreSQL с репликой

Сплошные линии показывают рабочие связи, пунктирные — связи резервного узла и реплики, которые включаются при отказе.

ЭлементНазначение
Узел 1 и узел 2Одинаковые установки iQBot с языковым сервером. Служба iqbot запущена только на основном узле.
Единый адрес (VIP)Адрес, по которому работают iQChannels и администраторы. Он переходит на тот узел, где запущена платформа. Это значение IQB_EXTERNAL_URL.
Единый адрес базы данныхАдрес, который всегда указывает на текущий основной сервер PostgreSQL.
PostgreSQLОсновной сервер и реплика. В базе лежат боты, диалоги, пользователи и модели NLU, поэтому узлы iQBot не хранят ничего своего.

Что нужно подготовить​

  • Два сервера Linux x64 одинаковой конфигурации, подходящей под требования. Память языкового сервера нужна на каждом узле.
  • Отказоустойчивая PostgreSQL 13 или новее с единым адресом записи, см. общие требования.
  • Виртуальный IP-адрес и DNS-имя для него, например bot.example.com.
  • Дистрибутив и файлы языковых моделей, одинаковой версии на обоих узлах.

Шаг 1. Отказоустойчивая база данных​

Подготовьте PostgreSQL с репликацией и единым адресом записи, как описано в разделе Установка в режиме кластера. Базу и пользователя создайте на основном сервере, как в шаге 1 раздела Установка iQBot на Linux.

Шаг 2. Установите основной узел​

Выполните шаги 2–7 раздела Установка iQBot на Linux. В файле .env задайте общие для кластера значения:

IQB_DATABASE_URL=postgres://iqbot:<пароль>@db.example.com:5432/iqbot
IQB_IQBFS_STORAGE=database
IQB_PRODUCTION=true
IQB_EXTERNAL_URL=https://bot.example.com
IQB_ADMIN_EMAIL=admin@example.com
IQB_ADMIN_PASSWORD=<стойкий пароль>

Здесь db.example.com — единый адрес базы данных, bot.example.com — имя виртуального адреса iQBot. Режим IQB_IQBFS_STORAGE=database обязателен: в нём боты, настройки и ключ подписи токенов хранятся в базе, а не на диске узла. Если в каталоге data/bots дистрибутива уже есть боты, при первом запуске на пустую базу они попадут в базу.

Проверьте, что платформа поднялась:

curl http://localhost:3000/status

Все компоненты должны быть в состоянии up. Затем создайте тестового бота и убедитесь, что вход в консоль работает.

Шаг 3. Установите резервный узел​

  1. Повторите шаги 2–5 и 7 раздела Установка iQBot на Linux на втором сервере. Файл .env скопируйте с первого узла без изменений. В шаге 7 включите только службу iqbot-lang, службу iqbot не включайте. Языковой сервер на резервном узле оставьте запущенным, он занимает память, но ускоряет переключение.

  2. Выполните пробный запуск. Остановите службу на основном узле, запустите на резервном и откройте консоль:

    # на узле 1
    sudo systemctl stop iqbot
    # на узле 2
    sudo systemctl start iqbot
    curl http://localhost:3000/status

    В консоли должны быть все боты, созданные через первый узел, а вход под той же учётной записью работать без повторной настройки. Токен, выданный первым узлом, второй узел тоже принимает.

  3. Остановите службу на резервном узле и отключите её автозапуск на обоих узлах: запуском теперь управляет схема переключения, а не загрузка сервера.

    sudo systemctl stop iqbot
    sudo systemctl disable iqbot
  4. Запустите службу на основном узле. Если вы используете keepalived, это сделает скрипт запуска, см. ниже.

Ограничение памяти

Языковой сервер и NLU установлены на обоих узлах, но под нагрузкой работает только один. Не планируйте на резервном узле меньше ресурсов, чем на основном: после отказа он принимает всю нагрузку.

Шаг 4. Единый адрес и HTTPS​

Обратный прокси-сервер (NGINX) с сертификатом для bot.example.com установите на оба узла. Он слушает все адреса сервера и передаёт запросы на http://127.0.0.1:3000. На резервном узле платформа не запущена, и прокси отвечает ошибкой 502, пока узел не станет основным. Подробности настройки HTTPS — в разделе Безопасность iQBot.

Виртуальный адрес должен принадлежать только тому узлу, где запущена платформа. Как переключать его, решает ваша инфраструктура: балансировщик с проверкой состояния, ручное переключение или keepalived.

Переключение на резервный узел вручную​

Порядок одинаков для отказа и для плановых работ:

  1. Убедитесь, что платформа на основном узле остановлена: sudo systemctl stop iqbot. Если сервер недоступен, отключите его от сети или выключите, чтобы он не вернулся с запущенной платформой.
  2. Переведите виртуальный адрес на резервный узел.
  3. Запустите платформу на резервном узле: sudo systemctl start iqbot.
  4. Дождитесь, когда curl http://localhost:3000/status покажет up для всех компонентов. Запуск занимает меньше минуты.
  5. Проверьте, что бот отвечает в iQChannels.

Состояние диалогов хранится в базе данных, поэтому после переключения диалог клиента продолжается. Сообщения, отправленные во время переключения, могут остаться без ответа.

Автоматическое переключение с keepalived​

Если переключение должно происходить без участия человека, виртуальным адресом и запуском службы управляет keepalived. Ниже пример для двух узлов. Замените адреса, имя сетевого интерфейса и пароль своими значениями и проверьте схему на тестовом контуре, прежде чем использовать её в продуктиве.

Скрипт проверки /etc/keepalived/iqbot-check.sh (на обоих узлах, chmod +x):

#!/bin/bash
VIP=10.0.0.100
# Резервному узлу платформа не нужна: проверка проходит
ip -4 addr show | grep -q " $VIP/" || exit 0
# После запуска платформе даётся три минуты
F=/run/iqbot-promoted
[ -f $F ] && [ $(( $(date +%s) - $(stat -c %Y $F) )) -lt 180 ] && exit 0
curl -fs -m 3 http://127.0.0.1:3000/status > /dev/null

Скрипт запуска и остановки /etc/keepalived/iqbot-notify.sh (на обоих узлах, chmod +x):

#!/bin/bash
case "$1" in
master) touch /run/iqbot-promoted; systemctl start iqbot ;;
backup) systemctl stop iqbot ;;
esac

Файл /etc/keepalived/keepalived.conf. На втором узле значение priority задайте 90:

vrrp_script chk_iqbot {
script "/etc/keepalived/iqbot-check.sh"
interval 5
fall 3
rise 2
weight -60
}

vrrp_instance IQBOT {
state BACKUP
nopreempt
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass <пароль>
}
virtual_ipaddress {
10.0.0.100/24
}
track_script {
chk_iqbot
}
notify_master "/etc/keepalived/iqbot-notify.sh master"
notify_backup "/etc/keepalived/iqbot-notify.sh backup"
notify_fault "/etc/keepalived/iqbot-notify.sh backup"
notify_stop "/etc/keepalived/iqbot-notify.sh backup"
}

Как это работает. Узел, получивший виртуальный адрес, запускает платформу, а узел, потерявший его, останавливает. Если на узле с адресом /status перестаёт отвечать, его приоритет падает ниже приоритета второго узла, и адрес переходит туда. Параметр nopreempt не даёт адресу вернуться на исправившийся узел сам, чтобы платформа не переключалась туда и обратно.

Проверка отказоустойчивости​

Проверьте схему до выхода в продуктив:

  1. Создайте тестового бота через основной узел и запомните его идентификатор.
  2. Остановите основной узел так, как это сделает отказ: выключите сервер или остановите службу.
  3. Дождитесь переключения. Откройте консоль по https://bot.example.com/admin/, тестовый бот должен быть в списке.
  4. Отправьте сообщение боту из iQChannels и убедитесь, что ответ пришёл.
  5. Верните основной узел в строй. Он должен стать резервным и не запускать платформу.

Обновление кластера​

Обновлять нужно оба узла до одной версии. Платформа меняет структуру базы при обновлении, поэтому на время миграции работа прекращается.

  1. Сделайте резервную копию базы данных, см. Резервное копирование и обновление.
  2. Остановите автоматическое переключение (sudo systemctl stop keepalived на обоих узлах) и службу iqbot на основном узле.
  3. Замените дистрибутив на обоих узлах.
  4. На основном узле один раз запустите платформу с IQB_AUTO_MIGRATE=true, проверьте /status и работу одного бота, затем уберите переменную.
  5. Верните автоматическое переключение. Резервный узел останется остановленным.

Что не входит в схему​

  • Распределение нагрузки и работа нескольких экземпляров одновременно: см. Кластер с распределением нагрузки.
  • Общее хранилище файлов: платформа в режиме IQB_IQBFS_STORAGE=database хранит всё в базе, общий диск не нужен.
  • Резервирование iQChannels и iQGPT: они настраиваются отдельно в своих продуктах.