Настройка SS14.Watchdog
Прежде чем нырять с головой, возможно, стоит как минимум пройти через хостинг ванильного сервера и научиться им управлять.
Также может быть полезно ознакомиться с настройкой среды разработки, так как вам понадобится как минимум установленный dotnet для компиляции Watchdog и установленный Python для запуска некоторых скриптов сборки сервера.
Также стоит пройти раздел о собственных кодовых базах, особенно если вы собираетесь использовать что-либо из этого с собственной кодовой базой.
SS14.Watchdog (кодовое имя Ian) — это наша обёртка для хостинга серверов, похожая на TGS для BYOND (но пока гораздо проще). Он занимается автообновлениями, мониторингом, автоматическими перезапусками и администрированием. Рекомендуем использовать его для нормальных развёртываний.
Процесс настройки
1. Проверка предварительных требований
Вам нужно иметь:
- .NET 10 SDK
- ASP .NET Core 10 Runtime
Оба они доступны на странице загрузки .NET 10.
В Linux используйте ваш любимый менеджер пакетов (apt, dnf, pacman, brew и т. д.) согласно инструкциям по установке от Microsoft.
2. Сборка
Следующий набор команд должен собрать Watchdog в системе Linux. Разумеется, вам придётся подстроить его под свою систему.
# Скачиваем репозиторий SS14.Watchdog и все подмодули и т. п.
git clone --recursive https://github.com/space-wizards/SS14.Watchdog
# Переходим в каталог SS14.Watchdog.
cd SS14.Watchdog
# Собираем Watchdog.
# Результат помещается в: SS14.Watchdog/bin/Release/net10.0/linux-x64/publish
dotnet publish -c Release -r linux-x64 --no-self-contained
Затем содержимое SS14.Watchdog/bin/Release/net10.0/linux-x64/publish можно скопировать в другое место. Здесь вы продолжите работу.
3. Запуск
Если вы следовали структуре, описанной выше, вам просто нужно открыть терминал в папке, которую вы скопировали выше, и запустить исполняемый файл SS14.Watchdog.
Конфигурация Watchdog
Файл конфигурации Watchdog — appsettings.yml
Конфигурация watchdog разделена на два основных раздела:
- Глобальные элементы, общие для всех экземпляров (серверов).
- Элементы для каждого экземпляра.
Serilog, AllowedHosts
Обычно их не нужно менять, и они слишком сложны для описания здесь.
BaseUrl
Это внешний URL Watchdog. Он автоматически передаётся экземплярам, чтобы они могли отмечаться в Watchdog. Он также используется в режимах обновления, которые требуют, чтобы клиенты подключались к Watchdog за ресурсами.
# Обычно то, что вам нужно, если только это не используется для клиентских ZIP-файлов.
BaseUrl: "http://localhost:5000/"
Urls
Это управляет тем, на каких интерфейсах размещается Watchdog, что в некоторых случаях может быть важно. В частности, это можно использовать, чтобы открыть Watchdog за пределами localhost без обратного прокси, так:
Urls: "http://*:5000"
Подробнее см. в соответствующей документации: docs.microsoft.com
Не забудьте соответственно скорректировать BaseUrl!
Уведомления
Теперь вы можете задать вебхук Discord для уведомлений, чтобы получать уведомления всякий раз, когда сервер падает; интеграция настолько проста, что достаточно добавить следующее в вашу конфигурацию.
Notification:
DiscordWebhook: "https://discord.com/api/webhooks/..."
Экземпляры
Каждый экземпляр — это отдельный игровой сервер, поэтому термины «экземпляр» и «сервер» можно использовать почти взаимозаменяемо.
Servers:
Instances:
example:
# Это задумано как «человеческое» имя экземпляра.
# На практике оно иногда используется в логах.
# Оно не влияет, например, на game.hostname.
Name: "Example"
# Это API-токен для внешнего доступа.
# (В отличие от API-токена, используемого внутренне между Watchdog и игровым сервером.
# Тот генерируется случайно.)
ApiToken: "you should choose a better token"
# Несколько вводя в заблуждение: это порт игрового сервера на localhost.
# Он НЕ будет автоматически синхронизироваться с реальным портом в конфигурации.
ApiPort: 1212
# Тип обновления и дальнейшие параметры управляют тем, откуда берётся серверное ПО.
# Этот пример — для официальных сборок сервера.
UpdateType: "Manifest"
Updates:
ManifestUrl: "https://wizards.cdn.spacestation14.com/fork/wizards/manifest"
# Ожидается, что сервер время от времени пингует Watchdog.
# (Вышеупомянутый BaseUrl передаётся серверу, чтобы это стало возможным.)
# Это подтверждает, что сервер, скажем так, не упал.
# Если он упал, сервер принудительно перезапускается.
# Однако запуск на некоторых системах может быть довольно долгим процессом.
TimeoutSeconds: 60
# Если включено, при зависании данные о состоянии сервера сохраняются для анализа.
# DumpOnTimeout: true
# TimeoutDumpType управляет тем, как это задаётся, но я не уверен в деталях.
# Программу, используемую для запуска сервера, можно задать здесь.
# Учтите, что в реальности это не должно требовать изменений, если вы не:
# A. Пытаетесь провести более продвинутую диагностику (например, подключить отладчик)
# B. Делаете что-то сильно отличающееся от запуска сервера Space Station 14
# RunCommand: "./wrapper.sh"
# Переменные окружения можно задать здесь.
# См., например, «Настройки производительности» в Руководстве оператора сервера.
# EnvironmentVariables:
# ROBUST_NUMERICS_AVX: "true"
Папка экземпляра сервера
Watchdog автоматически создаст структуру папок для каждого экземпляра сервера. Она находится в instances/<instanceId>, например instances/wizards_den / instances/wizards_den_two, относительно текущего рабочего каталога при запуске watchdog. В примере конфигурации выше это будет instances/example
В каждой папке экземпляра есть следующие файлы и папки:
binaries/: Используется для хранения клиентских бинарников при использовании типа обновления «Local», см. ниже.bin/: Содержит сами распакованные серверные бинарники.data/: Хранит серверные данные, такие как предпочтения игроков.config.toml: Файл конфигурации, который будет загружать сервер (watchdog переопределяет расположение по умолчанию —server_config.tomlрядом с .exe, чтобы его не удалили при сбросе сервера). Возможно, в первый раз вам придётся создать этот файл вручную.data.json: Содержит информацию watchdog. Если вы изменили тип обновления и получаете ошибки, удалите его.
Учтите, что хотя watchdog и занимается обновлениями сервера, вам всё ещё может понадобиться настроить config.toml согласно руководству оператора сервера.
Управление Watchdog
Есть две ключевые ситуации, когда возникает необходимость управлять watchdog.
Во-первых, watchdog обновляется только тогда, когда ему явно сообщают о необходимости проверить обновление или когда его перезапускают.
Во-вторых, вы можете просто захотеть принудительно перезапустить сервер.
Наконец, вы можете захотеть выключить сервер по окончании раунда. Например, для обслуживания.
Эти задачи можно выполнить следующими командами:
curl -v -X POST -u myInstance:ApiToken http://localhost:5000/instances/myInstance/restart
curl -v -X POST -u myInstance:ApiToken http://localhost:5000/instances/myInstance/update
curl -v -X POST -u myInstance:ApiToken http://localhost:5000/instances/myInstance/stop
Типы обновлений
Обновление Manifest
Сервер всё ещё не будет автоматически уведомляться об обновлениях, поэтому смотрите инструкции выше.
Тип Manifest — это метод, который используют все серверы Wizard’s Den, и мы рекомендуем его использовать. Manifest необходим для возможности записи повторов
Servers:
Instances:
example:
# (Это пример, НЕ копируйте его слепо. Иначе можете получить незаконченную конфигурацию)
UpdateType: "Manifest"
Updates:
ManifestUrl: "https://wizards.cdn.spacestation14.com/fork/wizards/manifest"
Обновления на основе Git
Метод обновления на основе Git не поддерживается. Хотя с ним проще всего начать, мы вряд ли сможем помочь, если он сломается. Вы в основном предоставлены сами себе.
Использование обновлений на основе Git предполагаемым образом может находиться в разных состояниях «поломки» из-за различных способов, которыми репозиторий может прийти в состояние, лучше всего описываемое как, ну, сломанное. Это не должно относиться к случаю, когда вы просто доставляете на сервер предварительно скомпилированные обновления через Git, но это тоже грязно и не то, как всё задумывалось работать.
SS14.Watchdog может компилировать и обновлять сервер, когда коммиты отправляются в ветку репозитория Git, содержащего исходный код вашего форка.
Для этого серверу нужны необходимые части среды разработки. Кроме того, вам всё ещё нужно написать Git-хук или что-то подобное, чтобы Watchdog уведомлялся об обновлениях, или иным образом заставить его периодически проверять обновления.
Servers:
Instances:
example:
# (Это пример, НЕ копируйте его слепо. Иначе можете получить незаконченную конфигурацию)
UpdateType: "Git"
Updates:
# BaseUrl: URL репозитория Git, за которым нужно следить.
# Он отличается от BaseUrl уровня всего Watchdog.
BaseUrl: "https://github.com/moonheart08/outer-rim-14/"
# Branch: ветка, за которой нужно следить.
Branch: "master"
# Hybrid ACZ: если включено, игровой сервер размещает клиентский zip, а не watchdog.
# С момента появления дельта-обновлений это теперь лучший способ справиться с этим.
HybridACZ: true
Обновления через Jenkins
Это древний метод, но он всё ещё должен работать.
Servers:
Instances:
example:
# (Это пример, НЕ копируйте его слепо. Иначе можете получить незаконченную конфигурацию)
UpdateType: "Jenkins"
Updates:
BaseUrl: "http://localhost:9938"
JobName: "Star"
Провайдер обновлений «Dummy»
Провайдер обновлений «Dummy» будет имитировать обновление всякий раз, когда к нему обращаются, а в остальном просто предполагает, что сервер уже распакован в bin/.
Поскольку Watchdog не проверяет обновления автоматически периодически, поддельные обновления не должны мешать.
Чтобы настроить это, используйте следующую конфигурацию обновлений в вашем appsettings.yml, в записи для экземпляра вашего сервера:
Servers:
Instances:
example:
# (Это пример, НЕ копируйте его слепо. Иначе можете получить незаконченную конфигурацию)
UpdateType: "Dummy"
Пользовательские автообновления
Не поддерживается, но отредактировать код SS14.Watchdog, чтобы добавить поддержку любого нужного вам механизма обновления, должно быть относительно несложно. См. UpdateProvider.cs.
Типы обновлений (DIY-издание)
Провайдер обновлений «Dummy», издание DIY-обновлений
Прежде чем пробовать это, убедитесь, что вы знакомы с тем, как в целом использовать провайдер обновлений «Dummy».
Настроить всё так, чтобы допускать обновления, относительно просто. Следующие инструкции — для Unix-подобных систем, но идея в любом случае должна быть понятна.
Начните с такой конфигурации:
Servers:
Instances:
example:
# (Это пример, НЕ копируйте его слепо. Иначе можете получить незаконченную конфигурацию)
UpdateType: "Dummy"
RunCommand: "./currentServer"
Основная идея этого механизма — использовать символические ссылки, чтобы переключать, какой каталог фактически используется.
Таким образом, нужны три скрипта: switchTo, switchTo1 и switchTo2:
switchTo:
#!/bin/sh
rm currentServer switch inactiveBin ; mkdir -p $1
ln -s $1/Robust.Server currentServer ; ln -s $2 switch ; ln -s $3 inactiveBin
echo Switching to $1
curl -v -X POST -u myInstance:ApiToken http://localhost:5000/instances/myInstance/update
switchTo1:
#!/bin/sh
./switchTo bin1 switchTo2 bin2
switchTo2:
#!/bin/sh
./switchTo bin2 switchTo1 bin1
Как только они станут исполняемыми (chmod +x switchTo*) и один из них будет запущен, запуск ./switch после этого будет переключать между двумя каталогами.
Таким образом, рабочий процесс таков: удалить всё в inactiveBin, затем распаковать туда новый сервер, затем запустить ./switch, чтобы подтвердить его.
Прежде чем очищать и распаковывать новую сборку сервера в inactiveBin, убедитесь, что сервер действительно перезапустился после любого предыдущего обновления и действительно больше не использует этот каталог.
DIY-сервер манифеста
Это быстрый скрипт, полезный при настройке DIY-сервера для типа обновления Manifest, описанного в разделе о манифесте.
Он предполагает, что у вас есть произвольный статический HTTP-сервер, и вам просто нужен скрипт для вывода JSON с обновлённой датой (так что вы можете просто перенести два файла на упомянутый статический HTTP-сервер и запустить обновление).
import json, datetime
nowish = datetime.datetime.now().isoformat()
print(json.dumps({"builds":{nowish: {"time": nowish, "client": {"url": "", "sha256": ""}, "server": {"linux-x64": {"url": "http://localhost:9283/SS14.Server_linux-x64.zip", "sha256": ""}}}}}))
Служба systemd
Чтобы позволить watchdog работать в фоне и автоматически запускаться вместе с сервером, вы можете создать файл службы. Он будет выглядеть примерно так.
Разумеется, настройте его под фактический каталог вашего watchdog.
Если в вашем дистрибутиве systemd не используется в качестве init, вам придётся преобразовать это в вашу соответствующую систему инициализации.
Из-за того, как работают службы, при необходимости вы не сможете использовать консоль сервера SS14 напрямую из терминала. Убедитесь, что вы дали себе права на сервере, чтобы использовать команды sudo или > для выполнения команд на сервере.
/etc/systemd/system/SS14.Watchdog.service
[Unit]
Description=SS14 Watchdog
After=network.target
[Service]
ExecStart=/path/to/SS14.Watchdog
WorkingDirectory=/path/to
Restart=on-failure
# Это не даёт systemd отправлять SIGTERM watchdog'у и отключать его, если один из серверов упадёт по OOM.
OOMPolicy=continue
# Это используется, чтобы метод git не падал сразу.
Environment="DOTNET_CLI_HOME=/tmp"
[Install]
WantedBy=default.target
Теперь перезагрузите демон systemd и включите службу, как обычно.
# Перезагружаем демон systemd (требуется при создании нового файла службы)
systemctl daemon-reload
# Запускаем службу Watchdog в фоне
systemctl start SS14.Watchdog
# Включаем службу Watchdog, чтобы она запускалась при старте системы.
systemctl enable SS14.Watchdog
Если вы ещё не знаете, как использовать systemctl, сейчас самое время это выяснить.
Для просмотра логов с этого момента можете использовать journalctl.
Сохранение серверов
Изменение конфигурации watchdog или его обновление требует его перезапуска, а по умолчанию это означает перезапуск всех игровых серверов, работающих под управлением watchdog. Начиная с коммита 6194ed4, watchdog поддерживает сохранение серверов. Это позволяет перезапускать его независимо, не затрагивая сами игровые серверы.
Чтобы настроить это, можно добавить следующее в ваш appsettings.yml:
Process:
PersistServers: true
С этой настройкой watchdog не будет завершать игровые серверы, когда завершается сам, и при перезапуске попытается найти предыдущий процесс игрового сервера, чтобы продолжить за ними следить.
Systemd
При хостинге watchdog как службы Systemd вышеописанного недостаточно. С настройками Systemd по умолчанию перезапуск watchdog привёл бы к тому, что Systemd сам убил бы процессы игровых серверов. Этого можно избежать, задав следующее в определении вашей службы:
[Service]
KillMode=process
Это заставит Systemd остановить только основной процесс watchdog, не заботясь о процессах игровых серверов под ним. Это, конечно, означает, что попытка systemctl stop ss14-watchdog не остановит игровые серверы, даже если они плохо себя ведут/зависли.
Общее устранение неполадок
Сервер перезапускается каждые 30 секунд
Это означает, что сервер неправильно взаимодействует с watchdog, и watchdog вынужден предполагать, что сервер завис или вроде того. Это происходит, если BaseUrl в конфигурации watchdog задан неправильно или иначе недоступен для игрового сервера.
System.IO.FileNotFoundException: Could not load file or assembly 'Mono.Posix.NETStandard, Version=1.0.0.0, Culture=neutral (…)
Текущая рабочая теория — это вызвано неправильными настройками dotnet publish. Приведённый ниже набор результатов тестов должен помочь объяснить.
dotnet publish -c Release -r linux-x64 --no-self-contained SS14.Watchdog -o test
RESULT: Mono.Posix.NETStandard.dll included, System.dll not included (as expected)
dotnet publish -c Release -r linux-x64 SS14.Watchdog -o test
RESULT: Mono.Posix.NETStandard.dll included, System.dll included
dotnet publish -c Release SS14.Watchdog -o test
RESULT: Mono.Posix.NETStandard.dll not included, System.dll not included
Поскольку Watchdog использует Mono.Posix.NETStandard.dll, чтобы помечать исполняемые файлы как исполняемые в Linux и Mac OS X, важно иметь его в этих ОС.
Старый пример конфигурации
(Этот раздел извлечён из более старой версии этого руководства с небольшими изменениями на случай, если он всё ещё пригодится. Он может быть устаревшим.)
Пример с наших официальных серверов (разумеется, токены скрыты):
Serilog:
Using: [ "Serilog.Sinks.Console", "Serilog.Sinks.Loki" ]
MinimumLevel:
Default: Information
Override:
SS14: Information
Microsoft: "Warning"
Microsoft.Hosting.Lifetime: "Information"
Microsoft.AspNetCore: Warning
WriteTo:
- Name: Console
Args:
OutputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3} {SourceContext}] {Message:lj}{NewLine}{Exception}"
Enrich: [ "FromLogContext" ]
# Раскомментируйте, чтобы watchdog писал логи в Loki
#Loki:
# Address: "{{ loki_addr }}"
# Name: "{{ server_id }}"
# Username: "{{ loki_user }}"
# password: "{{ loki_pass }}"
AllowedHosts: "*"
Notification:
DiscordWebhook: "https://discord.com/api/webhooks/..."
# URL API, по которому доступен ваш watchdog.
# Это НЕОБХОДИМО задать, чтобы игровые серверы могли взаимодействовать с watchdog.
# Если вы не хотите, чтобы watchdog был публично доступен, укажите здесь `http://localhost:5000/`.
BaseUrl: https://builds.spacestation14.io/watchdog/
Servers:
Instances:
# ID вашего сервера.
wizards_den:
# Имя сервера
Name: "Wizard's Den"
ApiToken: "foobar" # API-токен для удалённого управления этим экземпляром: запуск обновлений, перезапуск сервера.
ApiPort: 1212 # Порт API ИГРОВОГО СЕРВЕРА. Он должен совпадать с HTTP status API 1212 (описан ниже). Иначе watchdog не сможет связаться с игровым сервером для разных нужд.
# Конфигурация автообновления. Её можно опустить, если вам не нужны автообновления. Пример — для наших официально размещённых сборок.
# Альтернативы см. выше.
UpdateType: "Manifest"
Updates:
ManifestUrl: "https://wizards.cdn.spacestation14.com/fork/wizards/manifest"
# Любые переменные окружения, которые вы хотите указать.
EnvironmentVariables:
Foo: bar