Skip to content

Апгрейд

Два бинаря для апгрейда: manager (docker-compose стек) и edge'и (один на хост). Оба следуют одному концептуальному flow: stage новые артефакты, swap их атомарно, fall back на предыдущую версию автоматически, если новая не приходит в здоровое состояние.

TL;DR

Manager:

bash
VER=v0.10.1
gh release download "$VER" --repo ongridio/ongrid \
    -p 'ongrid-*-linux-amd64.tar.xz*'
sha256sum -c "ongrid-${VER}-linux-amd64.tar.xz.sha256"
tar xf "ongrid-${VER}-linux-amd64.tar.xz"
cd     "ongrid-${VER}-linux-amd64"
sudo ./upgrade.sh

Edge'и (все, параллельно, из UI):

  • Edges → Upgrade all — manager пушит MethodFetchPackage каждому подключённому edge, каждый скачивает stage'нутый bundle из https://<manager>/edge/, stage'ит, рестартит, swap'ит, запускает. Сбои авто-rollback'аются на следующей загрузке.

Или для одиночного edge из shell:

bash
sudo systemctl restart ongrid-edge
# The ExecStartPre runs apply-pending-upgrade.sh which picks up any
# staged bundle and applies it before the new agent starts.

Остальная часть страницы объясняет, как всё это на самом деле работает, чтобы вы могли отлаживать, когда не работает.

Что вам не нужно делать

Редактировать .envupgrade.sh добавляет новые ключи, но никогда не перезаписывает ваши
Управлять сертификатамиcerts/ не трогается; ваш реальный TLS-сертификат сохраняется
Делать pull docker-образовTarball везёт их с собой — апгрейд работает офлайн
SSH-иться на edge'иАпгрейд edge идёт через UI manager (ADR-024)
Запускать миграцию схемыgorm AutoMigrate обрабатывает diff при запуске manager

Когда апгрейду нужна помощь

СитуацияЧто делать
Установка до v0.7.45 с именованными docker volumesПерезапустите с bash upgrade.sh --migrate-volumes — скрипт использует alpine-контейнер, чтобы скопировать легаси-volume в bind-mount layout
/healthz не возвращает 200 в течение 90sСкрипт WARN-ит, но не откатывается. Смотрите docker compose -f /opt/ongrid/docker-compose.yml logs ongrid
Хотите откатитьсяРаспакуйте tarball предыдущей версии и запустите его собственный upgrade.sh. Без миграции схемы это обычно чистый downgrade

Downtime — около 30s до 2min в зависимости от размера БД — schema diff gorm AutoMigrate доминирует на больших таблицах (chat_messages / audit_log).

Апгрейд manager: upgrade.sh

upgrade.sh живёт в каждом release-tarball и предназначен для запуска внутри свежераспакованного нового tarball. Он предполагает, что уже есть установка в ${ONGRID_INSTALL_DIR:-/opt/ongrid}/.

По порядку:

  1. Preflight. Верифицирует docker + compose v2, находит существующий .env. Срывается, если такого нет.
  2. Определяет старую vs новую версию из существующего .env и VERSION файла нового tarball. Логирует обе — полезно для support- тикетов.
  3. docker compose down, чтобы освободить data-volumes для любого migration-шага.
  4. Переутверждает ownership data-директорий под ${ONGRID_DATA_DIR}/ (mysql, prom, loki, tempo, grafana, embeddings, qdrant). Image- uid'ы давно не менялись, но это единственный безопасный дефолт — переутверждение идемпотентно.
  5. Restage конфиги из нового tarball в /opt/ongrid/: docker-compose.yml, prometheus.yml, prometheus-rules.yml, loki-config.yaml, tempo-config.yaml, grafana/, searxng/, nginx.conf, frontier.yaml, новые edge/ артефакты, новый VERSION файл. .env сохраняетсяupgrade.sh никогда не перезаписывает operator-edited env.
  6. Загружает новые docker-образы (ongrid.tar, ongrid-web.tar, frontier.tar, если присутствуют).
  7. Bumps ONGRID_VERSION= в .env, так что следующий compose-up берёт новый image-tag.
  8. docker compose up -d с новым env.
  9. Polls /healthz 60с.
  10. Banner со старой → новой версией, Web URL, полезными командами следующего шага.

Если что-то падает до шага 8, оператор может перезапустить после фикса underlying-issue — upgrade.sh идемпотентен. Если шаг 9 падает (/healthz никогда не возвращает 200), manager-логи из docker compose logs ongrid расскажут вам, что сломано.

Для zero-downtime запустите blue/green setup с двумя manager-хостами за load balancer; OSS single-host установка — это короткий downtime во время апгрейда (~30-60с).

Откуда приходят upgrade-артефакты: make package

Это operator-путь — как вы собираете tarball, если вы собираете из исходников вместо pull релиза. Из checkout ongridio/ongrid:

bash
make package

Порядок важен; вот что делает make package:

  1. fetch-promtail — скачать promtail-<os>-<arch>.zip с upstream Grafana-релиза, распаковать в bin/<os>-<arch>/promtail. Кэшируется.
  2. fetch-otelcol — то же для otelcol-contrib.
  3. fetch-node-exporter — то же для node_exporter.
  4. fetch-process-exporter — то же для process_exporter.
  5. build-edge-all — кросс-компиляция ongrid-edge для linux/amd64, linux/arm64, darwin/amd64, darwin/arm64.
  6. docker-build — собрать образ ongrid:<version>.
  7. docker-build-broker — собрать singchia/frontier:<ver> из $FRONTIER_SRC (или пропустить, если уже в local image store).
  8. docker-build-web — собрать ongrid-web:<version> (frontend SPA + nginx).
  9. build-edge-bundle — собрать edge-bundle-linux-amd64-<ver>.tar.gz из loose-бинарей.
  10. dist/package.sh — stage'ит всё в dist/stage/ongrid-<version>-linux-amd64/, docker save-ит три образа, tar.xz-ит всё это, вычисляет sha256 sidecar, кладёт под dist/out/.

Output:

dist/out/ongrid-v0.10.1-linux-amd64.tar.xz
dist/out/ongrid-v0.10.1-linux-amd64.tar.xz.sha256

Это артефакт, который вы scp-ите на prod-хост и подаёте ./upgrade.sh.

Offline RAG модель

BGE embedding-модель не package-зависимость — она медленно fetch'ится по CN-сетям, так что остаётся one-off шагом. Запустите make fetch-embedding-model один раз до make package, если хотите, чтобы ONGRID_EMBEDDING_PROVIDER=local работал из коробки при восстановлении.

Апгрейд edge: ADR-024 stage-then-swap

User-путь для апгрейда edge — это «кликнуть Upgrade в UI» или systemctl restart ongrid-edge после того, как bundle был stage'нут. Что на самом деле происходит, сверху вниз:

1. Manager триггерит, edge fetch'ит

При «Upgrade all edges» (или одного edge):

  • Manager читает dist/out/edge-bundle-<arch>-<ver>.tar.gz.sha256 из /opt/ongrid/edge/ (положено туда install.sh / upgrade.sh).
  • Manager отправляет MethodFetchPackage(url=https://<manager>/edge/<bundle>, sha256=<sha>, version=<ver>) через туннель целевым edge'ам.
  • nginx сервит bundle-байты из той же /edge/ директории.

2. Edge stage'ит

Получающий edge:

  • Скачивает bundle в /tmp/.
  • Верифицирует sha256 против манифеста, который послал manager.
  • Untar'ит в /var/lib/ongrid-edge/.upgrade/incoming/.
  • Валидирует каждую <sha> <mode> <src> <dest> строку MANIFEST.txt (sha совпадает, src существует).
  • Пишет «ready» marker.
  • Чисто выходит. systemd рестартит unit по Restart=always.

3. ExecStartPre systemd запускает swap

Unit отгружается с:

ini
ExecStartPre=-+/usr/local/lib/ongrid-edge/apply-pending-upgrade.sh
ExecStart=/usr/local/bin/ongrid-edge

Префикс + запускает hook как root несмотря на User=ongrid-edge; - позволяет отсутствующему/падающему скрипту выйти 0 без блокировки unit, так что pre-upgrade бинарь всегда стартует.

apply-pending-upgrade.sh делает, по порядку:

  1. Mode 1: auto-rollback, если предыдущий апгрейд запустился, но никогда не записал healthy_marker, совпадающий с last_upgrade_ver. Восстанавливает каждый <dest>.previous поверх <dest>. Чистит staging-директорию.
  2. Mode 2: bundle apply — для каждой строки MANIFEST.txt:
    • пере-верифицировать sha256,
    • cp -p $dest $dest.previous (snapshot для rollback),
    • cp $src $dest.new на той же файловой системе, так что финальный rename — POSIX-атомарный,
    • chmod $mode $dest.new,
    • mv -f $dest.new $dest.
  3. Mode 3: legacy single-file apply для back-compat с edge'ями, которые ещё не были bundle-upgraded (только agent-бинарь, без манифеста).
  4. Записывает last_upgrade_at и last_upgrade_ver для next-boot health check.

Затем ExecStart=/usr/local/bin/ongrid-edge запускает свежеsрапнутый бинарь.

4. Новый агент репортит healthy (или нет)

Новый агент, при успешном connect:

  • Пишет /var/lib/ongrid-edge/.upgrade/healthy_marker с версией, которую он запускает.
  • Репортит register через туннель со своей новой версией.

Если файл существует и совпадает с last_upgrade_ver к следующей загрузке, apply-pending-upgrade.sh объявляет успех, пrune'ит каждый .previous, чтобы освободить диск, чистит staging-директорию.

Если нет (агент упал, не может дотянуться до manager, что-то ещё), следующая загрузка триггерит auto-rollback: каждый .previous восстанавливается, staging-директория стирается, edge запускает предыдущую рабочую версию снова. Оператор видит это в UI (edge продолжает репортить «старую» версию после триггернутого апгрейда — clue, что что-то не так с новым bundle).

Bundle-инварианты

Каждый файл, который edge swap'ит, в bundle; каждый файл в bundle — это самодостаточный бинарь или скрипт. Это non-negotiable:

  • Agent-бинарь (ongrid-edge)
  • Plugin-бинари (promtail, otelcol-contrib, node_exporter, process_exporter)
  • Hook-скрипт (apply-pending-upgrade.sh)

Plugin-конфиги (promtail.yaml, otelcol.yaml) не в bundle — они живут в /etc/ongrid-edge/ и доставляются через туннель как live config. Так апгрейд агента не затирает конфиг, который оператор отредактировал вручную.

Не запекайте bundle обратно в docker-образ

Если вы собираете из исходников, bundle собирается dist/build-edge-bundle.sh на хосте во время package-сборки, не в контейнере. ADR-032 форсит это — пере-запекание его в образ двойной-pack'ит ~120 MB несжимаемых байт и ломает sha- цепь.

Где живут rollback'и

text
/usr/local/bin/ongrid-edge              # current
/usr/local/bin/ongrid-edge.previous     # last known good

/usr/local/lib/ongrid-edge/promtail
/usr/local/lib/ongrid-edge/promtail.previous

...etc.

/var/lib/ongrid-edge/.upgrade/
  last_upgrade_at                       # ISO timestamp
  last_upgrade_ver                      # version string
  healthy_marker                        # written by the new agent

Boot-последовательность после триггернутого апгрейда выглядит как:

text
boot 1 (pre-upgrade):
  apply-pending-upgrade.sh sees nothing staged; exit 0
  ongrid-edge v0.7.159 runs

(manager pushes bundle, edge stages it, edge exits clean)

boot 2 (apply):
  apply-pending-upgrade.sh
    mode 1: no healthy_marker yet, but no last_upgrade_at either → skip
    mode 2: applies bundle. /usr/local/bin/ongrid-edge.previous = v0.7.159
                            /usr/local/bin/ongrid-edge        = v0.10.1
            writes last_upgrade_at, last_upgrade_ver=v0.10.1
            clears healthy_marker
  ongrid-edge v0.10.1 runs
  v0.10.1 connects, writes healthy_marker=v0.10.1

(reboot, e.g. host updates)

boot 3 (settle):
  apply-pending-upgrade.sh
    mode 1: last_upgrade_ver=v0.10.1, healthy_marker=v0.10.1 → success
            prunes all .previous files
            clears last_upgrade_at, last_upgrade_ver
  ongrid-edge v0.10.1 runs

Failure-сценарий:

text
boot 2 (apply):
  apply-pending-upgrade.sh: applies bundle as above
  ongrid-edge v0.10.1 crashes immediately (e.g. config drift)
  systemd restarts repeatedly per Restart=always

boot 3 (rollback):
  apply-pending-upgrade.sh
    mode 1: last_upgrade_ver=v0.10.1, healthy_marker missing
            → roll back: restore .previous over each dest
              (ongrid-edge.previous → ongrid-edge, etc.)
            : > last_upgrade_at, rm -rf incoming/
  ongrid-edge v0.7.159 runs again (working)

Downgrade

Downgrade manager: распакуйте старый tarball, запустите ./upgrade.sh внутри. Пока миграции схемы БД не было в промежуточных релизах, это работает. Проверьте release-notes на любые «breaking schema change» предупреждения до downgrade.

Downgrade edge'ей: триггерните «upgrade» из UI до более старой версии bundle. Manager-логике неважно, в каком направлении версия движется.

Что дальше

  • Reference / env — имена env-переменных, чьи defaults меняются между релизами.
  • Air-gapped установка — как зеркалировать артефакты на приватный webserver, чтобы apply-pending-upgrade.sh мог всё ещё pull bundle, когда сам manager не в интернете.