Перейти к содержимому

Устранение неполадок (симптом → диагноз → исправление)

Каждая запись следует одной и той же структуре: симптом, который вы видите, как подтвердить, что это именно он, и исправление. Приведённые строки лога — это фактические строки движка, так что вы можете искать их через grep. Там, где существует более глубокий runbook, запись ссылается на соответствующую страницу, а не выводит его заново.

Перезапуск не выводит его повторно (хранится только хеш токена, в setup.token в каталоге данных). Пока пользователей ещё нет, восстановление безопасно: остановите движок, удалите setup.token, запустите его — генерируется и выводится новый токен. Это работает только на установке без пользователей, поэтому это не путь для захвата. Токен выводится только в stdout (journal под systemd, лог контейнера в Docker/Kubernetes) — никогда в файлы логов.

Пользователи уже существуют в этом каталоге данных — вы не на первой загрузке. Либо войдите с существующим администратором, либо для действительно свежего старта используйте свежий --data-dir.

Движок предупреждает о ключах при первой загрузке

Заголовок раздела «Движок предупреждает о ключах при первой загрузке»
generated a new audit signing key; back it up path=/var/lib/olivares/audit-signing.key
generated a local TLS certificate; clients must trust it, or pin it with --pin-sha256=<pin_sha256> (that value, verbatim) cert=/var/lib/olivares/tls.crt cert_fingerprint_sha256=d38567e8…378c4e7f pin_sha256=JsdrhrY77Me8miAmobJsqamE3NDWIOSBrDTwbHkyCD0

Оба намеренны, и первый — это тот, который аукнется позже: принудительного депонирования (escrow) нет — скопируйте audit-signing.key за пределы сервера сейчас и закрепите публичный ключ (GET /v1/audit/pubkey) за пределами сервера, иначе будущая компрометация хоста оставит вас неспособными доказать целостность собственного ledger (резервное копирование и восстановление).

Строка TLS печатает два хэша, и они не взаимозаменяемы: cert_fingerprint_sha256 — это хэш сертификата, тот, что показывает браузер; pin_sha256 — хэш SPKI конечного сертификата, и только его сравнивает --pin-sha256. Скопируйте это значение дословно:

Окно терминала
olivares status --server https://127.0.0.1:8443 \
--pin-sha256 JsdrhrY77Me8miAmobJsqamE3NDWIOSBrDTwbHkyCD0

Если вместо этого закрепить отпечаток сертификата, ошибки неверного значения флага не будет — это корректный 32-байтовый хэш, поэтому соединение будет предпринято и отклонено с TLS SPKI pin mismatch, и эта ошибка сообщит значение, которое следовало использовать. Для curl --pinnedpubkey sha256//… добавьте завершающее дополнение =: движок намеренно печатает base64 без дополнения, чтобы значение выводилось без кавычек и переживало копирование, но curl требует дополненную форму.

Сгенерированная справка CLI описывает olivares doctor так: diagnose this host installation without printing secrets (CLI). Флаги включают --data-dir, --mode (auto | user | system), --init (auto | systemd | openrc | launchd), --config, --unit, --binary, --server, --timeout, --ca-cert, --audit-tenant, --check-updates. Не считайте эту таблицу дополнительным текстом справки; это эта сгенерированная команда.

olivares doctor сообщает проверку с именем agentops-layout (CHANGELOG.md [26.9.0]; cmd/olivares/cmd_doctor.go doctorAgentOpsCheck). Это не подкоманда. Она измеряет родную раскладку AgentOps, которую записывает манифест владения: управляемый drop-in должен существовать со своим mode и называть записанные claude HOME, каталог токенов и workspace; runtime env должен существовать с mode конфигурации (значения никогда не читаются); workspace должен быть каталогом (docs/RELEASE-INSTALLER.md).

Статусы, которые возвращает проверка:

Status When
not_applicable no readable manifest; malformed manifest; or the manifest records no AgentOps files (dropin, runtime-env, workspace_dir all empty)
fail drop-in does not reference a recorded token ($dataDir/claude-home, $dataDir/run, or workspace_dir); workspace path is absent or is not a directory
unknown drop-in or workspace is not readable
pass drop-in, runtime-env (values not read) and workspace directory agree with the record

Required равно false, пока манифест не запишет хотя бы один файл AgentOps; затем проверка required. Строки исправления, которые печатает движок, включают rerun install-agentops.sh; the managed drop-in and the recorded layout disagree и recreate the recorded workspace or rerun install-agentops.sh with OLIVARES_WORKSPACE_DIR.

И текст, и -o json содержат имена ключей и пути, но никогда значения конфигурации (docs/RELEASE-INSTALLER.md).

Сначала проверьте, подключено ли вообще что-нибудь. Движок прямо сообщает об этом при загрузке:

ingest: no observation sources configured (OLIVARES_SOURCES_CONFIG.sources is empty); no connector will ingest — the estate runs on no live traffic

Движок не запускается с конфигурацией источников

Заголовок раздела «Движок не запускается с конфигурацией источников»

Если OLIVARES_SOURCES_CONFIG указывает на отсутствующий, нечитаемый файл или файл с невалидным JSON, olivares serve завершается с кодом 1. Ищите ошибку запуска load sources operator config: OLIVARES_SOURCES_CONFIG, содержащую refusing to start instead of silently omitting operator configuration. Проверьте путь с точки зрения службы или контейнера, убедитесь, что их пользователь может прочитать файл, проверьте JSON и перезапустите движок. Эта ошибка файла препятствует запуску; движок не продолжает работать с пустой картой из-за неё.

После успешного запуска ищите ingest: wired source … kind=… для каждого источника. Источник, который не удалось создать, логирует ingest: failed to register in-process source; not wired с указанием причины.

Три причины покрывают почти все случаи, все по замыслу (руководство по pgAudit):

  1. Сервер не логирует в UTC. Записи с аббревиатурой зоны, отличной от UTC, пропускаются, а не получают неверную временную метку — задайте log_timezone = 'UTC'.
  2. csvlog — это пакет, а не хвост (tail). follow применяется только к jsonlog; источник csvlog принимает данные на каждом проходе, а не непрерывно.
  3. Аудируемые классы отключены — проверьте, что pgaudit.log включает read, write.

Ожидаемо на свежей установке: при отсутствии объявленных grant’ов каждый наблюдаемый доступ честно считается «неожиданным». Это начальное состояние, а не баг — разберите его, объявив grant’ы, которые вы намереваетесь предоставить.

Прочитайте тело. 503 — это не ready и не успех. То, что /livez остаётся 200, означает только, что процесс жив; то, что /pod-readyz остаётся 200, означает только здоровье пода (хранилище достижимо) без проверки лидерства и без зонда возможности первой загрузки. Ни то ни другое не разблокирует стандартный Helm chart или плоский манифест, которые подключают /readyz как контейнерный readinessProbe.

  • {"status":"unavailable","store":"down"} — хранилище недоступно. На SQLite: переполнен диск, проблемы с PVC, права доступа к файлу. На Postgres: доступность и учётные данные. Liveness намеренно продолжает проходить (процесс жив), так что ничто не зацикливается на перезапуске при сбое хранилища; перезапустите pod/сервис вручную после исправления хранилища, если оно остаётся заклиненным.
  • {"status":"standby","store":"up","leader":false} — резервный узел HA, отвечающий честно. Это не ошибка: Service маршрутизирует на лидера; резервные узлы дренируются по замыслу. Если все реплики сообщают standby, выбор лидера застрял — проверьте связность advisory-lock Postgres.
  • {"status":"setup_blocked","store":"up","leader":true,"setup_required":true,"code":"cross_tenant_admin_pool_not_configured"} — первая загрузка PostgreSQL не может авторитетно перечислить организации. Создайте административную роль NOSUPERUSER BYPASSRLS и --admin-dsn (Postgres в Kubernetes). В теле — фиксированное указание. Пока это предварительное условие не исправлено, стандартный зонд readiness держит под Not Ready. Не переназначайте зонд, чтобы это скрыть.
  • {"status":"setup_unavailable","store":"up","leader":true,"code":"setup_state_unavailable"} — этот узел не смог наблюдать, настроена ли установка. setup_required опущен, потому что его значение неизвестно. Это не известная пустая установка.
  • {"status":"setup_unavailable","store":"up","leader":true,"setup_required":true,"code":"setup_probe_unavailable"} — установка заведомо не настроена, но зонд возможности первой загрузки отказал по причине, отличной от отказа административного пула. Таймаут — не доказательство пустого парка.

200 {"status":"ok",…,"setup_required":true} — другое наблюдение: первичную настройку можно пытаться выполнить. POST /v1/setup по-прежнему повторяет проверки власти. Этот 200 не расходует бюджет доступности; эти 503 — да.

В топологии с одной репликой по умолчанию автоматического failover нет — восстановление — это перепланирование StatefulSet плюс переподключение тома RWO (следите за ошибками Multi-Attach; том привязывает восстановление к своей AZ). Автоматический failover — это свойство HA-топологии (Postgres + реплики + общий ключ подписи). Никогда не запускайте продакшен с отключённым хранением: emptyDir теряет ключ подписи при каждом перепланировании.

Латентность приёма p99 растёт (обратное давление)

Заголовок раздела «Латентность приёма p99 растёт (обратное давление)»

Шина блокирует, а не отбрасывает — растущий p99 olivares_ingest_duration_seconds — это задуманный сигнал того, что подписчик насыщен, а не потеря данных. Назовите виновника напрямую:

olivares_eventbus_queue_depth / olivares_eventbus_queue_capacity > 0.9

Метки по подписчикам указывают на медленный модуль; olivares_eventbus_publish_blocked_total подсчитывает события обратного давления. Обычная коренная причина — пропускная способность записи в хранилище (потолок единственного писателя SQLite) — это исправление через ёмкость (перейти на Postgres или снизить амплификацию записи), а не ручка для тюнинга. Медленные выходные коннекторы (webhook, SIEM) никогда не должны быть синхронными подписчиками.

С включённой распределённой шиной (OLIVARES_BUS_CONFIG) помните, что межузловой мост работает не более одного раза (at-most-once): насыщенный мост заполняет olivares_eventbus_bridge_pending_messages и затем отбрасывает удалённые события, подсчитанные в olivares_eventbus_bridge_dropped_total — оповещайте о любом росте и поднимайте по пейджеру, когда olivares_eventbus_bridge_connected == 0.

Рост olivares_auth_login_attempts_total{outcome="locked_out"} означает, что ограничитель отклонил попытку: аккаунт заблокирован собственными повторными неудачами либо его уже перебирал клиентский адрес с чередой неудач за ним. Аккаунт с чистой историей никогда не блокируется из-за чужих неудач с того же адреса — вместо этого он ждёт секунду. И то и другое снимается само; расследуйте источник неудач, а не повышайте лимиты.

Сначала разберитесь, что вы запустили: audit verify по умолчанию завершается с кодом 0 даже при неудачной цепочке (результат находится в JSON-отчёте) — автоматизация должна использовать --strict или разбирать отчёт:

Окно терминала
olivares audit verify --tenant $TENANT --data-dir /var/lib/olivares --strict \
--pubkey <BASE64-PINNED-OFF-BOX>

Закрепите внесерверный публичный ключ: без закреплений верификатор доверяет ключам, прочитанным с (возможно скомпрометированного) хоста — приемлемо как рекомендательная проверка, но не как доказательство нарушения целостности. Затем классифицируйте по полю reason:

Причина Класс Реакция
hash-mismatch, prev-mismatch, head-mismatch, tail-truncated подделка или усечение рассматривайте как SEV1: сохраните сервер, сверьте с внесерверной контрольной точкой
checkpoint-sig-invalid, checkpoint-link-mismatch, event-sig-invalid подделка или неверный ключ SEV1, если только вы не можете доказать путаницу с хранением ключей
seq-gap удаление или несогласованность восстановления сверьте с внесерверной контрольной точкой, прежде чем кричать о подделке
event-sig-missing возможно, устаревшие записи до включения подписи ограничьте это --from на границе включения; отсутствие до границы ожидаемо

Восстановленная резервная копия, которая проходит наивный обход, но расходится с вашей закреплённой внесерверной контрольной точкой — это случай аномалии восстановления; именно ради этого сравнения и существует закрепление.

Контрольные точки перестали записываться (каденция по умолчанию 1ч; OlivaresAuditCheckpointStale срабатывает на 2ч). Проверьте лог движка на наличие ошибок контрольных точек и записываемость хранилища — пока оно растёт, ваш якорь доказательства нарушения целостности стареет.

Назначение с неизвестным kind пропускается и логируется (notify: destination has unknown connector kind; skipped — проверьте написание kind). Для приёмников событий POST …/subscriptions/{id}/test отправляет доставку, за которой вы можете наблюдать, а конечные точки должны быть HTTPS (отправка в SIEM).


Если симптома здесь нет, и собственное сообщение движка его не объясняет — это баг документации; пожалуйста, сообщите о нём, приложив строку лога.