Настройка HA для Discourse в изолированной сети

Заранее спасибо.
Я планирую развернуть Discourse с высокой доступностью в производственной среде. Ниже приведён мой план настройки и некоторые условия окружения.

  1. Настройка с тремя серверами приложений и двумя серверами базы данных PostgreSQL. Один сервер PG всегда работает в режиме записи, а другой — только для чтения.

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

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

  4. Производственные серверы не имеют подключения к интернету, но я могу загружать образы из Docker Hub.

  5. У нас есть собственный сервер GitLab.

  6. Возможно ли создать образ Docker и развернуть его на нескольких серверах?

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

После выполнения команды ./launcher bootstrap app где-то вам нужно будет сохранить полученный образ контейнера (обычно это делается путем отправки его в реестр), а затем загрузить и запустить его на ваших трех серверах приложений.

Вам также понадобится центральный сервер Redis (и, возможно, его реплики). Кроме того, у вас отсутствует балансировщик нагрузки для распределения запросов между этими различными серверами приложений.

Спасибо за ответ @Falco

Мы используем балансировщик нагрузки HAProxy и репозиторий Nexus для хранения артефактов.

Привет, @Falco.

В моей рабочей среде у меня нет доступа к интернету, поэтому я планирую выполнить загрузку на машине с доступом в интернет, а затем перенести полученный образ загрузки на производственные серверы. Однако при этом на производственной виртуальной машине контейнер не запускается, потому что сервер Unicorn ожидает наличие родительского процесса с определённым ID, из-за чего он не работает.

Пожалуйста, помогите мне разобраться: нужно ли мне скопировать каталог /var/discourse, в котором была выполнена загрузка, на производственный сервер?

Что имеется в виду под «этим»? Сам процесс загрузки (bootstrap) или запуск ранее загруженного образа контейнера?

Когда я запускаю ранее собранный образ контейнера

Как вы сохранили и экспортировали изображение на продакшн-сервер?

Как именно вы пытаетесь запустить это сохранённое изображение в продакшене?

Ранее образ, собранный ранее, загружался в репозиторий Nexus, а затем извлекался из репозитория Nexus на продакшн-сервере.

Команда docker run генерируется с помощью ./launcher start-cmd app и выполняется на продакшн-сервере.

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

run-parts: выполнение /etc/runit/1.d/00-ensure-links
run-parts: выполнение /etc/runit/1.d/00-fix-var-logs
run-parts: выполнение /etc/runit/1.d/01-cleanup-web-pids
run-parts: выполнение /etc/runit/1.d/anacron
run-parts: выполнение /etc/runit/1.d/cleanup-pids
Очистка устаревших PID-файлов
run-parts: выполнение /etc/runit/1.d/copy-env
Запущен runsvdir, PID 42
chgrp: недопустимая группа: 'syslog'
ok: run: redis: (pid 51) 0s
ok: run: postgres: (pid 56) 0s
supervisor pid: 53 unicorn pid: 75
config/unicorn_launcher: строка 71: kill: (75) — процесс не найден
config/unicorn_launcher: строка 15: kill: (75) — процесс не найден
(53) завершение
ok: run: redis: (pid 51) 7s
ok: run: postgres: (pid 101) 0s
supervisor pid: 96 unicorn pid: 103
config/unicorn_launcher: строка 71: kill: (103) — процесс не найден
config/unicorn_launcher: строка 15: kill: (103) — процесс не найден
(96) завершение
ok: run: redis: (pid 51) 14s
ok: run: postgres: (pid 127) 0s
supervisor pid: 120 unicorn pid: 129
config/unicorn_launcher: строка 71: kill: (129) — процесс не найден
config/unicorn_launcher: строка 15: kill: (129) — процесс не найден
(120) завершение
ok: run: redis: (pid 51) 22s
timeout: down: postgres: 0s, обычно up, требуется up
ok: run: redis: (pid 51) 30s
timeout: down: postgres: 1s, обычно up, требуется up
ok: run: redis: (pid 51) 37s
ok: run: postgres: (pid 174) 0s
supervisor pid: 165 unicorn pid: 176
config/unicorn_launcher: строка 71: kill: (176) — процесс не найден
config/unicorn_launcher: строка 15: kill: (176) — процесс не найден
(165) завершение
ok: run: redis: (pid 51) 48s
ok: run: postgres: (pid 196) 1s
supervisor pid: 191 unicorn pid: 198
config/unicorn_launcher: строка 71: kill: (198) — процесс не найден
config/unicorn_launcher: строка 15: kill: (198) — процесс не найден
(191) завершение
ok: run: redis: (pid 51) 54s
timeout: down: postgres: 1s, обычно up, требуется up

Вы используете внешние PostgreSQL, Redis и Object Storage? Это ожидаемо при настройке высокой доступности (HA), и ваши производственные серверы, а также серверы сборки должны иметь доступ к этим внешним сервисам.

Просто тестирую сценарий: запуск процесса инициализации на одном сервере и запуск контейнерного образа после инициализации на другом сервере в режиме автономной работы.

Это верный способ, который не сработает.

Есть ли причина упоминать объектное хранилище? Неужели нельзя использовать внутреннее хранилище сервера?

В настройке HA нужно ли копировать каталог discourse, в котором выполнена загрузка, на все серверы приложений?

Как вы планируете работать с несколькими серверами приложений и загрузками пользователей? Общий сетевой диск между всеми серверами? Это может сработать, но наше официальное решение для этого — объектное хранилище с использованием API S3.

В этом нет необходимости, если вы

Да, я использую внешний сервер Postgres и кластер Redis.

3 сервера приложений, используемых для кластера Redis вместе с приложением.

Значит, мне нужно использовать общую директорию/хранилище для директории сборки discourse. Спасибо @Falco, теперь мне всё ясно.

Извините за беспокойство, @Falco, у меня остался один вопрос.

При выполнении шага перестройки (rebuild) будут ли затронуты существующие данные в базе данных PostgreSQL? Если да, то как с этим справиться?

Да, при перестройке выполняются миграции, которые изменяют как данные, так и структуру.

В среде с высокой доступностью (HA) необходимо следовать рекомендациям, представленным здесь: Introducing Post Deployment Migration