Отказоустойчивость:
Подготовка серверов

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

Примечание

Начиная с версии 6.9.0 основной и резервный серверы не объединяются в общий кластер Docker Swarm: каждый сервер работает в собственном кластере, а данные между серверами передаются по внутренним IP-адресам. Если отказоустойчивость была настроена на версии ниже 6.9.0, обновите её в соответствии с инструкцией по обновлению.

Предупреждение

Механизм отказоустойчивости в данный момент доступен для DEB-based систем (Debian/Ubuntu).

Если вы используете RPM-based системы (RHEL, CentOS, Fedora и другие), рекомендуем получить консультацию у специалистов Compass. Пожалуйста, напишите нам в пространстве поддержки On-premise, Telegram или на почту support@getcompass.ru

Предварительные требования

Перед настройкой отказоустойчивости убедитесь, что:

  1. У вас есть два сервера:

  2. Оба сервера находятся в одной сети и им доступно минимум 3 адреса:

    • один внутренний IP-адрес для основного сервера;

    • один внутренний IP-адрес для резервного сервера;

    • один внешний и внутренний IP-адрес, используемый как виртуальный IP (VIP).

    Пример схемы размещения серверов и использования VIP:

    • основной сервер: внутренний IP — 192.168.1.4;

    • резервный сервер: внутренний IP — 192.168.1.5;

    • виртуальный IP (VIP) — 192.168.1.6, на который настроен DST-NAT с внешнего адреса 188.124.51.150.

    Примечание

    Виртуальный IP (VIP) — это дополнительный IP-адрес, который используется для балансировки и автоматического переключения трафика между основным и резервным серверами. VIP должен быть выделен в вашей внутренней сети. В процессе настройки Отказоустойчивости VIP будет привязан к вашему домену, используемому для доступа к Compass.

    Предупреждение

    Если у вас ранее уже был установлен сервер, подключать домен к внешнему IP VIP на этом шаге не требуется.

  3. Для сценария отказоустойчивости Compass использует встроенные базы данных в Docker. Подключение к внешним базам данных в этом режиме не поддерживается.

Настройка Docker

  1. Если ваша версия Compass on-premise ниже 6.9.0, то обновите окружение в соответствии с инструкцией по обновлению.

  2. На основном и резервном серверах проверьте, что версия Docker совпадает:

    sudo docker version --format '{{.Server.Version}}'
    
  3. На обоих серверах убедитесь, что Docker работает в Swarm-режиме:

    sudo docker info --format '{{.Swarm.LocalNodeState}}'
    

    Команда должна вернуть active.

    Если команда вернула inactive

    Переведите Docker в Swarm-режим, указав внутренний IP-адрес сервера:

    sudo docker swarm init --advertise-addr <внутренний IP сервера>
    

    Команда выведет подсказку о подключении других нод к кластеру - выполнять её не нужно.

Примечание

При настройке отказоустойчивости для второго сервера будут открыты порты:

  • 3306 и порты баз данных пространств (по умолчанию 35150–35164) - для репликации MySQL;

  • 9312, 9360, 9361 - для репликации Manticore.

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

Настройка репликации баз данных

  1. На основном сервере откройте конфигурационный файл configs/replication.yaml для редактирования любым текстовым редактором и заполните поля:

    # service_label — лейбл для обозначения сервисов сервера (основной, резервный).
    # Имя должно быть не длиннее 7 символов
    service_label: "primary"
    
    # mysql_server_id — идентификатор mysql сервера.
    # Каждый новый сервер должен иметь отличный идентификатор от предыдущего.
    # Для основного сервера установите значение 1, для резервного — значение 2.
    mysql_server_id: 1
    
    # start_octet — используется для определения сабсети для сервисов. Для каждого нового сервера необходимо инкрементировать на 10.
    # Для основного сервера установите значение 10, для резервного — значение 20.
    start_octet: 10
    
    # Запрещает автоматический переход сервера обратно в состояние Master.
    # Используется, если сервер переключился в состояние Backup:
    # в этом случае приложение не позволит автоматически вернуть его в состояние Master без ручного вмешательства администратора.
    master_state_changed_disable: true
    
    # Внутренний IP-адрес или hostname второго сервера отказоустойчивости
    # значение обязательно, если заполнен service_label
    # порт и протокол указывать не нужно
    peer_host: "<внутренний IP резервного сервера>"
    

    Предупреждение

    Рекомендуем оставлять значение master_state_changed_disable: true, если при отказе основного сервера выполняется переключение на резервный, и обратный перевод VIP с резервного сервера на основной должен выполняться только вручную.

    Обратите внимание: эта блокировка действует только для основного (primary) сервера.

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

    Если это первая установка основного сервера с нуля (ранее сервер не поднимался для установки приложения)

    На основном сервере выполните установку приложения:

    sudo python3 script/install.py
    

    Дождитесь завершения установки приложения на основном сервере.

    Если ранее приложение уже было установлено

    Выполните обновление основного сервера, чтобы применить изменения конфигурационного файла configs/replication.yaml:

    Примечание

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

    sudo python3 script/update.py
    

    Дождитесь завершения обновления основного сервера.

    На основном сервере создайте mysql-пользователя для репликации баз данных:

    sudo python3 script/replication/create_mysql_user.py --type monolith
    
    sudo python3 script/replication/create_mysql_user.py --type team
    

    Если у вас больше одной компании - выберете пункт «Все».

    На основном сервере запустите скрипт для старта репликации данных Manticore:

    Примечание

    В параметре master-mysql-server-id укажите значение поля mysql_server_id из конфигурационного файла configs/replication.yaml основного сервера

    sudo python3 script/replication/start_manticore_replication.py --type master --master-mysql-server-id 1 --need-update-company 1
    
  3. Скопируйте данные баз данных основного сервера на резервный.

    Для переноса данных на другой сервер требуется прокинуть ключ без passphrase с основного сервера на резервный.

    На основном сервере сгенерируйте ключ доступа, оставив passphrase пустым:

    ssh-keygen -t rsa -b 4096
    

    Затем на основном сервере выполните команду, чтобы скопировать созданный ключ на другой сервер, где:

    • remote_server_user — логин для подключения к резервному серверу;

    • remote_server_ip — IP-адрес резервного сервера.

    ssh-copy-id <remote_server_user>@<remote_server_ip>
    
  4. Для сохранения и отправки данных приложения на основном сервере необходимо выполнить скрипт script/backup_all_data.py из директории установщика.

    В скрипт передается параметр -dst, в котором:

    • remote_server_user — логин для подключения к резервному серверу;

    • remote_server_ip — IP-адрес резервного сервера;

    • remote_backup_folder — абсолютный путь до папки на резервном сервере, в которую необходимо сохранить копию данных (например, /home/compass_backup).

    Предупреждение

    Убедитесь, что директория remote_backup_folder имеет права для сохранения файлов от лица remote_server_user.

    sudo python3 script/backup_all_data.py \
       -dst remote_server_user@remote_server_ip:remote_backup_folder
    

    После выполнения скрипта резервная копия данных будет сохранена по пути remote_backup_folder на резервном сервере.

  5. На резервном сервере добавьте пользователя www-data, если тот отсутствует:

    sudo useradd -u 33 -g www-data -M -s /usr/sbin/nologin www-data
    
  6. На резервном сервере скопируйте данные приложения в новую директорию:

    sudo cp -a <remote_backup_folder>/compass /home/
    

    И поменяйте права для директорий:

    sudo chown -R root.root /home/compass; \
    sudo chown -R www-data.www-data /home/compass/company_configs; \
    sudo chown -R www-data.www-data /home/compass/default_file; \
    sudo chown -R www-data.www-data /home/compass/files; \
    sudo chown -R www-data.www-data /home/compass/tmp_files
    
  7. Скопируйте инсталлятор по новому пути (например, /home/on-premise/onpremise-installer) и перейдите в новую директорию с ним:

    mkdir -p <путь к новому инсталлятору>
    
    sudo cp -a /home/compass/installer/* <путь к новому инсталлятору>; \
    sudo cp -a /home/compass/installer/.version <путь к новому инсталлятору>/
    
    cd <путь к новому инсталлятору>
    
  8. Подготовьте скопированные конфигурационные файлы для дальнейшей работы:

    На резервном сервере в configs/global.yaml замените внутренний IP основного сервера на внутренний IP резервного:

    sudo sed -i 's/<внутренний ip основного сервера>/<внутренний ip резервного>/' configs/global.yaml
    
    # пример команды
    sudo sed -i 's/192.168.1.4/192.168.1.5/' configs/global.yaml
    

    Удалите файл с лейблом, скопированный с основного сервера:

    sudo rm -f .service_label
    
  9. На резервном сервере откройте конфигурационный файл configs/replication.yaml для редактирования любым текстовым редактором и заполните поля:

    Примечание

    Установите лейблы: «primary» (на основном сервере) и «reserve» (на резервном).

    # далее необходимо заполнить:
    # service_label — лейбл для обозначения сервисов сервера (основной, резервный).
    # Установите лейблы, которые ранее добавляли в шаге установки лейблов для нод: primary (на основном сервере) и reserve (на резервном).
    service_label: "reserve"
    
    # mysql_server_id — идентификатор mysql сервера.
    # Каждый новый сервер должен иметь отличный идентификатор от предыдущего.
    # Для основного сервера установите значение 1, для резервного — значение 2.
    mysql_server_id: 2
    
    # start_octet — используется для определения сабсети для сервисов. Для каждого нового сервера необходимо инкрементировать на 10.
    # Для основного сервера установите значение 10, для резервного — значение 20.
    start_octet: 20
    
    # Внутренний IP-адрес или hostname второго сервера отказоустойчивости
    # значение обязательно, если заполнен service_label
    # порт и протокол указывать не нужно
    peer_host: "<внутренний IP основного сервера>"
    
  10. Замените значения в файле src/values.compass.yaml:

    Примечание

    В команду ниже подставьте те значение, которые указали в конфигурационном файле

    sudo sed -i -e 's/service_label: primary/service_label: reserve/' \
       -e 's/master_service_label: reserve/master_service_label: primary/' \
       -e 's/mysql_server_id: 1/mysql_server_id: 2/' \
       -e 's/start_octet: 10/start_octet: 20/' \
       -e 's/subnet: 172.39.11.0\/24/subnet: 172.39.20.0\/24/' \
    "src/values.compass.yaml"
    
  11. Перенесите ключ-секрет шифрования базы данных на резервный сервер.

    Примечание

    Если на основном сервере не включено шифрование сообщений, этот пункт нужно пропустить.

    Перенос ключа-секрета шифрования базы данных

    Ключ-секрет хранится в кластере Docker Swarm основного сервера и на резервный автоматически не переносится.

    Проверьте, включено ли шифрование. На резервном сервере выполните в директории инсталлятора:

    grep -A4 "^database_encryption:" configs/database.yaml | grep "mode:"
    

    Если команда вернула mode: "none", шифрование выключено — пропустите этот пункт.

    На основном сервере сохраните ключ-секрет в файл:

    sudo docker exec $(sudo docker ps -q --filter name=php-monolith | head -1) \
       cat /run/secrets/compass_database_encryption_secret_key | sudo tee /root/compass_db_secret.b64 > /dev/null; \
    sudo chmod 600 /root/compass_db_secret.b64
    

    Отправьте файл на резервный сервер и удалите его на основном. Подставьте те же значения remote_server_user, remote_server_ip и remote_backup_folder, что и при создании резервной копии:

    sudo rsync -a /root/compass_db_secret.b64 <remote_server_user>@<remote_server_ip>:<remote_backup_folder>/; \
    sudo shred -u /root/compass_db_secret.b64
    

    На резервном сервере создайте ключ-секрет из файла и удалите файл:

    sudo docker secret create compass_database_encryption_secret_key <remote_backup_folder>/compass_db_secret.b64; \
    sudo shred -u <remote_backup_folder>/compass_db_secret.b64
    

    Проверьте, что ключ-секрет создан — в списке должен быть compass_database_encryption_secret_key:

    sudo docker secret ls
    
  12. На резервном сервере добавьте сертификат в список доверенных, затем обновите системное хранилище доверенных сертификатов:

    sudo cp -a certs/compassRootCA.crt /usr/local/share/ca-certificates/; \
    sudo update-ca-certificates
    
  13. На резервном сервере запустите скрипт для восстановления данных.

    При запуске скрипта вам будет предложено:

    • Выбрать нужный бэкап из списка доступных копий.

    • Подтвердить удаление текущих данных и завершение работы приложения. Если на резервном сервере не было установлено приложение Compass, то ничего удалено не будет.

    sudo python3 script/restore_db.py --force-update-company-db 0
    

    Дождитесь завершение выполнение скрипта. После этого проверьте состояние развертывания с помощью команды:

    sudo docker service ls | grep reserve | grep -vE "default-file|jitsi-custom"
    
  14. Запустите скрипт для обновления портов в сервисе go_database на резервном сервере:

    sudo python3 script/replication/update_database_port.py
    
  15. На резервном сервере инвалидируйте порты, на которых были созданы компании:

    При запуске скрипта вам будет предложено:

    • Выбрать идентификатор сервера с базой данных. Если используется односерверная установка, выберите d1.

    • Выбрать порты, которые необходимо инвалидировать (выберите все по очереди).

    sudo docker exec -it $(sudo docker ps | grep php_monolith | awk '{print $1}') bash -c \
       "php src/Compass/Pivot/sh/php/domino/invalid_port_repairer.php"
    

    Примечание

    Если скрипт показывает, что порты с нужным статусом отсутствуют — пропустите этот пункт.

  16. Восстановите компании на резервном сервере:

    sudo python3 script/replication/repair_all_teams.py
    
  17. Запустите на резервном сервере скрипты для создания mysql-пользователя для репликации баз данных:

    Предупреждение

    Скрипты репликации баз данных НЕ работают с пользовательскими базами данных.

    sudo python3 script/replication/create_mysql_user.py --type monolith
    
    sudo python3 script/replication/create_mysql_user.py --type team
    

    Если у вас больше одной компании - выберете пункт «Все».

  18. Перед началом запуска репликации на резервном сервере выполните сброс репликации:

    sudo python3 script/replication/reset_slave_replication.py --all-types --all-teams
    
  19. Далее на резервном сервере запустите скрипт для старта репликации:

    sudo python3 script/replication/start_slave_replication.py --all-types --all-teams --start-from-backup
    

    Дождитесь завершения репликации.

    Если в выводе скрипта получаете «No» для одной из позиций (IO, SQL, или другое),
    значит репликация не может завершиться успешно. В этом случае рекомендуется использовать скрипты из раздела управление процессом отказоустойчивости.

  20. Затем на резервном сервере запустите скрипт для старта репликации данных Manticore:

    Примечание

    В параметре master-mysql-server-id укажите значение поля mysql_server_id из конфигурационного файла configs/replication.yaml основного сервера.

    sudo python3 script/replication/start_manticore_replication.py \
       --type reserve --master-mysql-server-id 1
    
  21. Для проверки состояния репликации на резервном сервере запустите команду:

    sudo python3 script/replication/show_slave_replication_status.py --all-types --all-teams --log-level=3
    

    Внимание

    Перед выполнением переключения необходимо убедиться, что репликация завершила синхронизацию данных.
    Критерием готовности является значение поля Seconds_Behind_Master равное нулю, что указывает на отсутствие отставания реплики от мастера.

  22. На резервном сервере добавьте удалённый репозиторий к новому инсталлятору:

    git init
    git remote add origin https://github.com/getCompass/onpremise-installer.git
    git fetch
    git reset --hard origin/master
    git branch --set-upstream-to=origin/master master