Настройка SS14.Watchdog

Info

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

Также может быть полезно ознакомиться с настройкой среды разработки, так как вам понадобится как минимум установленный 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. Если вы изменили тип обновления и получаете ошибки, удалите его.

Info

Учтите, что хотя 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

Info

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

Тип Manifest — это метод, который используют все серверы Wizard’s Den, и мы рекомендуем его использовать. Manifest необходим для возможности записи повторов

Servers:
  Instances:
    example:
      # (Это пример, НЕ копируйте его слепо. Иначе можете получить незаконченную конфигурацию)
      UpdateType: "Manifest"
      Updates:
        ManifestUrl: "https://wizards.cdn.spacestation14.com/fork/wizards/manifest"

Обновления на основе Git

Здесь водятся драконы!

Метод обновления на основе Git не поддерживается. Хотя с ним проще всего начать, мы вряд ли сможем помочь, если он сломается. Вы в основном предоставлены сами себе.

Warning

Использование обновлений на основе Git предполагаемым образом может находиться в разных состояниях «поломки» из-за различных способов, которыми репозиторий может прийти в состояние, лучше всего описываемое как, ну, сломанное. Это не должно относиться к случаю, когда вы просто доставляете на сервер предварительно скомпилированные обновления через Git, но это тоже грязно и не то, как всё задумывалось работать.

SS14.Watchdog может компилировать и обновлять сервер, когда коммиты отправляются в ветку репозитория Git, содержащего исходный код вашего форка.

Info

Для этого серверу нужны необходимые части среды разработки. Кроме того, вам всё ещё нужно написать 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, вам придётся преобразовать это в вашу соответствующую систему инициализации.

Info

Из-за того, как работают службы, при необходимости вы не сможете использовать консоль сервера 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

Subpages