Агент обновлений

soniks-agent — отдельный контейнер рядом с клиентом, который раскатывает образ клиента с портала: читает канал релизов станции, применяет образ в окне между проходами, проверяет его health-gate и откатывается на предыдущий при провале. Агент v1 меняет только образ клиента — определения спутников и конфигурацию тракта клиент получает с портала сам. Код и контракт — репозиторий soniks-agent; решения — «Агент v1» в Дорожная карта: надёжность сети.

Что видит владелец

На странице настроек станции (stations/<id>/config/, блок «Обновления»):

Поле

Кто задаёт

Что значит

Канал релизов

администраторы сети

stable (по умолчанию) или canary — какой digest образа станция получает

Обновления клиента

владелец

notify (по умолчанию) — агент только сообщает о новом образе; managed — применяет сам

Что агент сделал, видно там же и на странице станции: текущий и предыдущий образ, итог последнего применения (L1/L2, ошибка), доступный образ канала.

Включение

Агент — сервис того же docker-compose.yml, что и клиент. Блок soniks-agent в шаблоне закомментирован; раскомментируйте его и том soniks-agent в volumes:, затем:

docker compose up -d

Ничего в .env добавлять не нужно: агент читает те же STATION__ID, STATION__TOKEN, URL__BASE и HEALTH__PORT. Необязательные AGENT__* — в Переменные окружения.

Три условия, из-за которых блок именно такой:

  • тот же compose-проект. /healthz клиента не выведен на хост (ports: нет), агент читает его по имени сервиса внутри сети проекта;

  • каталог станции монтируется по тому же пути, что на хосте (${PWD}:${PWD}, working_dir: ${PWD}). Проект, рабочий каталог и файлы конфигурации агент берёт из лейблов своего контейнера и запускает docker compose с ними — иначе Docker считал бы это другим проектом. Запускайте docker compose up -d из каталога станции: ${PWD} берётся из оболочки;

  • docker.sock — агент управляет контейнером клиента через Docker хоста. Это права root на хосте; отсюда notify по умолчанию и режим managed только по решению владельца.

Что агент делает при обновлении

  1. Раз в минуту забирает GET /api/v2/stations/<id>/state/ и сравнивает release.client_image с образом, на котором поднят клиент.

  2. notify — строка в логе агента и поле «доступен» на портале.

  3. managed — образ скачивается сразу, применяется в окне: проход не идёт и до ближайшего дальше AGENT__WINDOW_IN_MINUTES.

  4. В docker-compose.override.yml станции агент вписывает image: сервиса soniks-client (остальные ключи файла сохраняются) и делает docker compose up -d soniks-client. Поэтому ручной docker compose up -d после этого поднимает тот же образ, а не тег из docker-compose.yml.

  5. Health-gate: L1 — клиент отвечает 200 на /healthz; L2test-flowgraph.sh в контейнере клиента дожил до таймаута (код 124) и оставил непустой водопад test.dat. Конфигурация портала передаётся L2 через окружение.

  6. Провал — откат на предыдущий образ и та же проверка L1. Этот digest агент не повторяет AGENT__RETRY_AFTER_HOURS, пока в канале не появится новый.

Агент не удаляет предыдущий образ: откат берёт его с самой станции.

Ручной откат и выключение

Поправьте image: в docker-compose.override.yml (или удалите файл, вернув тег из docker-compose.yml) и выполните docker compose up -d soniks-client. В managed агент через минуту применит образ канала снова — переключите станцию в notify на портале. Выключить агент — docker compose stop soniks-agent или закомментировать блок обратно.

Диагностика

docker compose logs -f soniks-agent
docker compose exec soniks-agent cat /var/lib/soniks-agent/state.json

«Compose станции недоступен, только наблюдаю» в логе — каталог станции не смонтирован по пути хоста или агент запущен не из compose. «Портал прислал не digest» — в канале релизов тег, а не имя@sha256:…; агент такое не применяет.