Перейти к основному содержанию
Это руководство соответствует симптомам, которые вы наиболее вероятно можете столкнуться в production, конкретному диагнозу и исправлению, чтобы вы могли разрешить инциденты из инструментов, которые у вас уже есть, без развертывания дополнительной инфраструктуры наблюдаемости. Оно охватывает сервер, коллектор, приборную панель, помощника ИИ, Python SDK, мониторинг здоровья и сертификатов, резервные копии, аналитику на основе ClickHouse и мультитенантность. Страницы приборной панели — это область видимости орга в /<org-slug>/…, а поток событий — это домашняя страница орга (/<org-slug>/). Названия страниц в этом руководстве (например /sessions, /queries) ссылаются на эти маршруты с областью видимости организации.

Просмотр журналов

AgentEye не поставляется с инфраструктурой логирования или мониторинга. Как сервер, так и приборная панель записывают структурированные журналы в stdout, поэтому вы можете читать их напрямую с помощью kubectl или docker; агрегатор не требуется.

Kubernetes

Следите за живыми журналами сервера и приборной панели:
Полезные варианты:
ЦельКоманда
Последние 200 строк (без отслеживания)kubectl logs -n agenteye -l app=server --tail=200 --timestamps
Журналы из предыдущего крахаkubectl logs -n agenteye <pod-name> --previous
Отслеживание всех реплик одновременноkubectl logs -n agenteye -l app=server --max-log-requests=10 -f
Postgres (StatefulSet)kubectl logs -n agenteye postgres-0 -f

Docker Compose

Корреляция одного запроса по приборной панели и серверу

Каждый запрос приборной панели помечается request_id и распространяется на сервер через заголовок x-request-id. Сервер повторяет его в заголовках ответа и в каждой строке журнала, которую он выдает для этого запроса. Чтобы проследить один запрос от конца до конца:
  1. Захватите идентификатор из заголовка ответа, например:
  2. Найдите этот идентификатор в журналах обоих pod:
Вы увидите строки proxy passthrough, withAuth: authorized и upstream response приборной панели рядом с парой http request received / http request completed сервера, все они имеют один и тот же request_id.

JSON-журналы и jq

Установите AE_LOG_JSON=1 на приборной панели (он включен по умолчанию при NODE_ENV=production), чтобы выдать один JSON-объект на строку. Затем фильтруйте структурно:
Rust-сервер выдает пары key=value трассировки, которые хорошо работают с grep без jq:

Увеличение детализации

КомпонентПеременная окруженияПример
СерверRUST_LOGRUST_LOG=debug или RUST_LOG=agenteye_server=debug,info
Приборная панельAE_LOG_LEVELAE_LOG_LEVEL=debug
debug на сервере добавляет строку api key authenticated для каждой аутентификации. debug на приборной панели добавляет строки upstream request, session validated и proxy passthrough.

Хранение журналов

Stdout контейнера эфемерный; kubelet ротирует файлы журналов (по умолчанию ~10 МиБ на контейнер) и хранит небольшое количество на диске. После удаления pod журналы теряются. Если вам нужно более длительное хранение или поиск по pod, направьте ваш кластер на сборщик логов (Loki, CloudWatch, Cloud Logging, Datadog и т. д.), который отслеживает /var/log/containers/. AgentEye не требует и не предписывает какой-либо конкретный выбор.

Проблемы с аутентификацией

docker pull не удается с ошибкой “unauthorized”

Убедитесь, что вы аутентифицировали Docker для GHCR с помощью вашего AGENTEYE_TOKEN:
Токен должен иметь разрешение read:packages на организацию agenteye-enterprise. Обратитесь к support@exosphere.host, если ваш токен не работает.

gh release download возвращает 404 или 401

  • Подтвердите, что AGENTEYE_TOKEN экспортирован в вашей оболочке: echo $AGENTEYE_TOKEN
  • Подтвердите, что вы используете GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ... (CLI gh читает GITHUB_TOKEN)
  • Токен должен иметь contents:read на agenteye-enterprise/releases

Проблемы сервера

Сервер не запускается с ошибкой “invalid port number”

Переменная POSTGRES_PASSWORD (или другой учетные данные) содержит специальные символы URL (/, +, =), которые нарушают анализ DATABASE_URL. Переформируйте пароль, используя шестнадцатеричное кодирование:
Затем обновите секрет Kubernetes и пароль внутри Postgres (или пересоздайте .env для Docker Compose), и перезагрузите сервер. См. полные шаги в enterprise-docs/kubernetes-deployment.md § “PostgreSQL credentials”.

Сервер выходит немедленно при запуске

Проверьте журналы контейнера:
Распространенные причины:
  • DATABASE_URL не установлен или неверно сформирован: сервер записывает ошибку и выходит.
  • Postgres недостижим: подтвердите, что контейнер Postgres или управляемая БД работают и хост/порт правильны.
  • Миграции не удались: проверьте журналы на наличие ошибок SQL.

GET /health возвращает не-200 или истекает

Сервер может все еще запускать миграции при первом запуске. Подождите несколько секунд и повторите попытку:
Если проблема сохраняется, проверьте docker logs agenteye-server на наличие ошибок.

GET /ready возвращает 503

/ready — это зонд готовности: он возвращает 503, когда сервер не может достичь Postgres или ClickHouse. Тело указывает на неправильную зависимость:
Исправьте зависимость, которую оно указывает как down: является ли pod ClickHouse/Postgres Running? Верны ли CLICKHOUSE_URL / DATABASE_URL и достижимы? На Kubernetes pod читает NotReady до восстановления /ready; это ожидаемо и является именно сигналом, по которому оповещения мониторинга здоровья должны срабатывать. Redis никогда не является причиной: он сообщается, но не приводит к отказу готовности.

Коллектор возвращает 401 Unauthorized

API ключ коллектора не имеет разрешения events:add, или ключ был отключен. Создайте новый ключ с правильным разрешением:

Аутентифицированные запросы вдруг стали медленными (~200ms вместо ~5ms)

Это симптом того, что Redis находится вниз, пока REDIS_URL установлен. Каждый вызов кэша истекает через 100 мс, затем переходит к Postgres; на путях аутентификации и OTP запрос выполняет два таких перехода. Подтвердите в журналах сервера:
Разрешение:
  1. redis-cli -h <your-redis> ping чтобы подтвердить, что Redis достижим в сетевом кластере.
  2. Если Redis был кратко отключен и теперь вернулся, перезагрузите pod сервера. redis::aio::ConnectionManager не восстанавливается надежно после падения основного соединения; перезагрузка pod выбирает новое соединение чисто. То же самое относится к приборной панели.
  3. Если вы не хотите запускать Redis прямо сейчас, отмените установку REDIS_URL в развертывании и перезагрузитесь. Обе службы работают без кэша (корректность сохраняется; задержка возвращается к базовому уровню до Redis).

Сервер сообщает OTP request rate-limited в журналах, но пользователь говорит, что попробовал только один раз

Проверьте, был ли Redis недостижим. Путь резервной копии использует SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes', что видит ранее созданные строки OTP. Если пользователь нажимал спам “Отправить” час, окно в 15 минут может все еще содержать ≥5 кодов. Разрешите либо ожидание прохождения окна, либо DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes' (консоль оператора).

Я изменил ALLOWED_EMAILS / SESSION_TTL_SECS / OTP_TTL_SECS и перезагрузился; ничего не произошло

Эти переменные окружения — это только семена первой загрузки. После того как таблица settings имеет строку для соответствующего ключа, эта строка является источником истины; переменная окружения читается один раз при первой загрузке, а затем игнорируется при каждой последующей перезагрузке. Чтобы изменить их после первой загрузки, войдите на приборную панель и отредактируйте их в /settings. Изменение применяется за считанные секунды на всех репликах; перезагрузка не требуется. Если вам необходимо принудительно пересеять из переменной окружения (редко, обычно полезно только в разработке), используйте DELETE FROM settings WHERE key = '<key>' и перезагрузите сервер. Bootstrap выберет текущее значение переменной окружения при следующей загрузке. Редактирование через /settings — поддерживаемый путь в production.

Проблемы коллектора

Коллектор запускается, но события не появляются на приборной панели

  1. Подтвердите, что коллектор работает: systemctl status agenteye-collector (Linux) или проверьте процесс.
  2. Подтвердите, что AGENTEYE_URL указывает на http(s)://your-server-host:8080/events (примечание: путь /events).
  3. Выполните одноразовый сброс, чтобы увидеть немедленный результат:
  4. Проверьте, что Python SDK действительно записывает файлы: ls ${AGENTEYE_HOME:-~/.agenteye}/events/
  5. Если файлы существуют в ${AGENTEYE_HOME:-~/.agenteye}/failed/, загрузки не удаются. Проверьте журналы коллектора на наличие ошибки, скорее всего 4xx (плохой ключ или URL) или проблема с сетью.

Файлы накапливаются в $AGENTEYE_HOME/events/ и не загружаются

  • Коллектор может не работать. Запустите его: agenteye-collector start; он автоматически сбрасывает существующие события при запуске.
  • Проверьте здоровье коллектора: agenteye-collector health
  • Коллектор может работать, но не может достичь сервера. Проверьте правила брандмауэра между хостами коллектора и сервера.

Файлы в $AGENTEYE_HOME/failed/

Файлы перемещаются в failed/ после исчерпания всех попыток повторения (по умолчанию: 5 попыток с экспоненциальной отсрочкой). Это означает либо:
  • Сервер вернул ошибку 4xx (плохой ключ, неправильный URL или проблема нагрузки)
  • Сервер был недостижим для всего окна повторения
Исправьте основную проблему, затем вручную переставьте в очередь:

Коллектор сообщает network error при каждой загрузке (рукопожатие TLS не удается)

Если curl -k для AGENTEYE_URL успешен, но двоичный файл коллектора при каждой загрузке не удается с error sending request for url (...), сервер AgentEye представляет сертификат TLS, который не подписан доверенным центром сертификации. Путь production — это имя хоста входящего ACME, настроенное в deploy/base/certificates/domain.env (см. kubernetes-deployment.md Фаза 3.1 / 4.2). Когда INGEST_DOMAIN разрешается на общественный LB Traefik и cert-manager выдал сертификат Let’s Encrypt, коллекторы проверяют сертификат сервера по хранилищу системного доверия без AGENTEYE_TLS_CA требуется; очистите его из конфигурации коллектора, если он был установлен против старого развертывания с самоподписанным сертификатом. Симптом: коллектор работал вчера, не удается сегодня после ~90-дневного перерыва. Это означает, что развертывание по-прежнему использует устаревший издатель selfsigned для ingest-tls. 90-дневный сертификат ротировался и закрепленный файл центра сертификации устарел. Исправьте окончательно, переключив кластер на издателя ACME (Фаза 3.1 руководства развертывания). Краткосрочная разблокировка: переизвлеките текущий сертификат сервера и обновите AGENTEYE_TLS_CA:
AGENTEYE_TLS_CA добавляет дополнительный якорь доверия; стандартные общественные корни по-прежнему доверены.

Сертификат ingest-tls застрял Ready: False после развертывания

Посмотрите на Events и указанный Order / Challenge. Распространенные причины:
  • DNS не разрешается на общественный LB. Валидатор HTTP-01 не может достичь INGEST_DOMAIN. Проверьте с помощью dig +short INGEST_DOMAIN; он должен разрешаться на тот же адрес, что и EXTERNAL-IP LoadBalancer traefik-public. cert-manager автоматически повторяет попытки после распространения DNS; нет необходимости удалять сертификат.
  • Порт 80 заблокирован на load balancer / security group. HTTP-01 требует, чтобы порт 80 был достижим от общественных валидаторов Let’s Encrypt. Если у вас есть вышестоящий WAF или SG, ограничивающий :80, откройте его (конфигурация Traefik перенаправляет на HTTPS, но Boulder следует перенаправлению и принимает ответ).
  • dnsNames не подставлены. Если kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}' показывает INGEST_DOMAIN_PLACEHOLDER, вы пропустили шаг domain.env; создайте его из domain.env.example и повторно примените.
  • Ограничено Let’s Encrypt. Повторяющиеся неудачные заказы для одного и того же имени хоста триггирует дублирование сертификатов или пределы сбоя валидации. Подождите не менее часа перед повторной попыткой; проверьте статус Order для точного сообщения об ограничении скорости.

Сертификат dashboard-tls застрял Ready: False / браузер все еще показывает предупреждение

Тот же поток диагностики, что и для ingest-tls выше (kubectl describe certificate dashboard-tls -n agenteye); DNS, port-80, placeholder и причины ограничения скорости все применяются, плюс два специфических для приборной панели:
  • DASHBOARD_DOMAIN разрешается на неправильный LoadBalancer. Он должен указывать на LB Traefik приборной панели, а не на общественный входящий. dig +short имя хоста и сравните с адресом LB приборной панели.
  • Экземпляр приборной панели Traefik не может служить заданием. Он должен быть установлен с объединенным файлом значений приборной панели, который включает поставщика Ingress с областью видимости для решателя HTTP-01 cert-manager. Без него решатель недостижим и заказ остается pending навсегда. Обновите экземпляр с предоставленными значениями; ожидающее задание затем завершается само по себе.
  • LoadBalancer был ограничен IP-адресами. Исходные диапазоны применяются к порту 80 также, что блокирует валидаторы Let’s Encrypt — как при первом выпуске, так и при каждом ~75-дневном обновлении. Переоткройте LB или согласуйте решатель DNS-01 с поддержкой перед его блокировкой.
Пока выпуск не удается, приборная панель продолжает служить своему предыдущему сертификату (или значению по умолчанию входящего при свежей установке) — доступ деградирован предупреждением браузера, никогда полностью недоступен.

CLI все еще пропускает проверку TLS после того, как приборная панель получила доверенный сертификат

--insecure сохраняется в cli.json при входе. После того как приборная панель служит общедоступно доверенным сертификатом, снова войдите с agenteye --base-url https://<your-dashboard-domain> --secure login; проверка сохраняется обратно включенной и предупреждение запуска исчезает.

Проблемы приборной панели

Невозможно отключить или отредактировать пользователя ADMIN_EMAIL

По дизайну. Пользователь, совпадающий с ADMIN_EMAIL, помечается как защищенный при каждом запуске сервера: приборная панель скрывает кнопку Отключить для этой строки, и API отклоняет DELETE /users/:id и PUT /users/:id для него с 403 Forbidden. Триггер базы данных также отклоняет прямые операторы UPDATE, которые отключили бы защищенную строку. Чтобы повернуть начальную загрузку администратора, измените ADMIN_EMAIL в своей среде и перезагрузите сервер. Новый адрес электронной почты помещается как защищенный. Предыдущий администратор сохраняет защищенный флаг до его очистки в базе данных (обычно в порядке, так как предыдущий адрес электронной почты по-прежнему является действительным администратором, пока вы явно не удалите его).

Приборная панель не показывает события

  1. Подтвердите, что URL сервера и API ключ правильны в переменных окружения приборной панели (AGENTEYE_SERVER_URL, AGENTEYE_API_KEY).
  2. API ключ приборной панели должен иметь разрешение events:read.
  3. Подтвердите, что события действительно были приняты: curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"

/errors пусто, но /events показывает красные строки

Более новые версии SDK выдают сбои как события agent_end / tool_result / hook_completed с outcome: "error" в нагрузке, а не как специальная строка event_type: "error". Страница /errors теперь соответствует обоим: любая строка, которую поток /events рисует красным (явный event_type='error', нагрузка outcome/status в наборе сбоев, is_error: true или истинное поле error) появляется на /errors. Если вы ранее видели, что ошибок нет в этом окне, пока красные строки были видны на /events, обновите приборную панель + сервер вместе (расширенный фильтр — это errored=true на GET /events) и два представления будут согласованы.

/models, /tools или /hooks медленно или не загружаются на широких диапазонах времени

Симптом: в большой таблице событий (миллионы строк) открытие /models, /tools или /hooks — или расширение диапазона времени до 7d, 30d или all — графики вращаются и затем показывают ошибку загрузки. Сервер логирует ошибку MEMORY_LIMIT_EXCEEDED ClickHouse (код 241) или превышение времени ожидания запроса для запроса latency_aggregate. Причина: старые сборки вычисляли откат и распределение часов этих страниц с помощью запроса, который читал полную нагрузку исходного события и сопарял события запроса/ответа с внутриполотной сортировкой и объединением. Поэтому пиковая память запроса росла с размером окна, поэтому на занятом тенанте широкий диапазон может превышать потолок памяти ClickHouse для каждого запроса. Исправление: обновитесь до сборки, которая включает это исправление. Откат теперь читает только компактные продвигаемые столбцы и сопаривает события с потоковой агрегацией, поэтому пиковая память больше не масштабируется с нагрузкой исходного события — широкие окна остаются хорошо в пределах потолка памяти и возвращаются за часть времени. Улучшение полностью на стороне запроса: оно применяется ко всем существующим данным при следующей загрузке страницы, без переприема или заполнения.

Приборная панель не загружается / пустая страница

Проверьте журналы контейнера приборной панели:
Наиболее распространенной причиной является отсутствие AGENTEYE_SERVER_URL или AGENTEYE_API_KEY, или указание на недостижимый сервер.

Аналитика / телеметрия приборной панели

Приборная панель отправляет анонимную телеметрию использования продукта в PostHog по умолчанию, маршрутизируемую через собственный путь приборной панели /ingest (обратный прокси на https://us.i.posthog.com). Отправка их от первого лица означает, что блокировщики объявлений браузера их не отбрасывают. Это независимо от основной функциональности приборной панели:
  • Контейнер приборной панели (не браузер) — это то, что достигает PostHog. Если его исходящий доступ к https://us.i.posthog.com заблокирован, телеметрия молча не включается; приборная панель работает нормально и никакие ошибки не всплывают пользователям.
  • Никогда не включаются данные агента, сеанса или события, только использование UI приборной панели.
  • Чтобы полностью отключить телеметрию, установите AE_ANALYTICS_DISABLED=1 на контейнер приборной панели и перезагрузитесь. См. Telemetry & privacy в руководстве развертывания.

Телеметрия CLI / телеметрия

CLI agenteye отправляет анонимную телеметрию использования в PostHog по умолчанию: какие команды запускаются, успех/статус выхода и продолжительность. Это независимо от функциональности CLI:
  • Машина, запускающая CLI, напрямую достигает https://us.i.posthog.com. Если его исходящий доступ заблокирован, телеметрия молча не включается (отправка ограничена по времени, поэтому команда никогда не задерживается) и CLI работает нормально.
  • Никогда не включаются данные агента, сеанса или события: аргументы команды и значения флагов (URL приборной панели, токен, адрес электронной почты, идентификаторы сеанса, фильтры запросов) никогда не отправляются.
  • Чтобы отключить его, установите AGENTEYE_ANALYTICS_DISABLED=1 (или кросс-инструментальный DO_NOT_TRACK=1) в окружении CLI. См. Telemetry & privacy в руководстве CLI.

Проблемы помощника ИИ

См. enterprise-docs/assistant.md для полной установки.

Пузырь помощника не появляется

Пузырь скрыт, если не все из следующих:
  • Вошедший пользователь имеет разрешение agent:use.
  • AGENTEYE_AGENT_URL установлен на приборной панели и служба agent достижима.
  • На служба agent настроена конечная точка LLM (ANTHROPIC_API_KEY, шлюз через ANTHROPIC_BASE_URL или Bedrock/Vertex). Если ничего не установлено, агент сообщает не сконфигурирован и пузырь остается скрытым.
Проверьте здоровье агента с хоста приборной панели: curl http://agent:9100/health должно вернуть {"status":"ok","llm_configured":true,...}.

Помощник говорит, что не может прочитать что-то

Инструменты ограничиваются для каждого пользователя. Если пользователь не имеет evaluations:read (или events:read, dashboards:read), соответствующие инструменты не предлагаются и помощник скажет, что не может прочитать эти данные. Предоставьте соответствующее разрешение на чтение.

assistant not configured (HTTP 503) при отправке

Контейнер agent не имеет настроенной конечной точки LLM, или AGENTEYE_AGENT_TOKEN приборной панели не совпадает с токеном агента. Установите оба и перезагрузитесь.

Контейнер agent перезагружается / выходит за пределы памяти под нагрузкой

Каждый разговор порождает короткоживущий дочерний процесс. Убедитесь, что контейнер работает с процессом инициализации (изображение использует tini; в Compose установите init: true) и дайте ему адекватные лимиты памяти. При необходимости уменьшите AGENTEYE_AGENT_MAX_STEPS.

Проблемы CLI

agenteye не запускается с ModuleNotFoundError: No module named 'click'

Свежая установка CLI agenteye версии 0.1.6 может зависать при запуске с:
0.1.6 полагалась на click, устанавливаемый косвенно посредством typer; текущие релизы typer больше не его вытягивают, поэтому чистая среда заканчивается отсутствующим пакетом. Обновитесь до 0.1.7 или новее, который зависит от click напрямую:
См. enterprise-docs/cli.md для руководства по установке.

Проблемы Python SDK

Файлы не появляются в $AGENTEYE_HOME/events/

SDK буферизирует события и сбрасывает каждые 500 мс по умолчанию. Если ваш процесс выходит перед сбросом, события могут быть потеряны. Вызовите agenteye.configure(flush_interval=0.1) для более быстрого сброса в короткоживущих скриптах или убедитесь, что ваш процесс работает достаточно долго для цикла сброса. Если AGENTEYE_HOME установлен, убедитесь, что SDK пишет в $AGENTEYE_HOME/events/, а не в ~/.agenteye/events/ (требуется SDK ≥ 0.0.1b5).

ValueError: Reserved field names cannot be used as custom fields

Названия timestamp, type и environment зарезервированы и не могут использоваться как пользовательские поля. Передача любого из них вызывает:
Переименуйте проблемное пользовательское поле. Обратите внимание, что session_id и agent_id — это явные параметры вызова события, а не пользовательские поля; передача одного из них снова как пользовательского поля вызывает TypeError.

Проблемы мониторинга здоровья

В Slack не приходят оповещения (Robusta)

Оповещение здоровья Robusta является opt-in; оно не отправляет ничего, пока не установлено и не указано на канал Slack. Проверьте выпуск и его раковину:
Распространенные причины: Slack api_key / slack_channel не были установлены (или токен был отозван); api_key — это токен облачного релея Robusta (robusta integrations slack), но объединенный disableCloudRouting: true требует токена бота Slack с собственным размещением (xoxb-…), или установите disableCloudRouting: false; раковина scope исключает пространство имен, в котором работают ваши pod (объединенные значения ограничивают область видимости agenteye); или пока не произошел сбой. Принудительно тестовое оповещение путем отключения pod:
См. enterprise-docs/health-monitoring.md для установки и конфигурации.

Сервер продолжает колебаться NotReady

Зонд готовности попадает в /ready, который не удается, когда Postgres или ClickHouse недостижимы. Если сервер циклирует внутрь и наружу из NotReady, зависимость периодически недоступна; проверьте pod ClickHouse и Postgres и CLICKHOUSE_URL / DATABASE_URL сервера. Подтвердите, что сообщает /ready:
Этот зонд намеренно терпим (щедрый порог отказа), поэтому устойчивое колебание указывает на реальную проблему зависимости, а не на чрезмерно агрессивный зонд. Живучесть остается на /health, поэтому колебание готовности не перезагрузит pod.

Проблемы мониторинга сертификатов

CronJob не отправляет уведомления Slack

Для cert-renewal-check CronJob требуется URL вебхука Slack, сохраненный в Secret. Проверьте его наличие:
Если отсутствует, создайте его:
Без секрета CronJob все еще работает и регистрирует результаты в stdout. Проверьте журналы с помощью:

Сертификат клиента истек до получения уведомления

CronJob работает каждые 12 часов. Если он не работал, проверьте его статус:
Инициируйте ручную проверку:
Чтобы немедленно переиздать истекший сертификат:
Затем примените переформированный collector-mtls-secret.yaml в кластер(ы), где работают коллекторы, и перезагрузитесь:

Проблемы резервного копирования

agenteye-backup не удается с ошибкой “No space left on device”

CronJob agenteye-backup выводит Postgres + ClickHouse в backup-tmp emptyDir временный том (по умолчанию 30Gi), затем потоком архив tar прямо в S3 — сжатый архив никогда не записывается обратно на временное хранилище, поэтому временное хранилище должно содержать только необработанные выгрузки, а не выгрузки + второй архив на диске. Pod, вытесненный / No space left on device, поэтому означает, что необработанные выгрузки превышают размер временного хранилища (выгрузка events ClickHouse доминирует и растет со временем). Проверьте журналы неудачного задания:
Исправление: в вашей оверлее поднимите sizeLimit emptyDir backup-tmp CronJob выше вашего итога необработанной выгрузки и убедитесь, что узел может действительно его держать (sizeLimit — это крышка, не резервирование). Если выгрузки превышают диск одного узла, замените emptyDir на PVC (EBS/PD) для backup-tmp или сожмите выгрузки у источника.
Более старые релизы писали .tar.gz в то же 20Gi временное хранилище, что и выгрузки, поэтому dumps + archive переполнял его и pod был вытеснен перед запуском загрузки — что выглядит как сбой S3, но на самом деле это диск. Потоковая передача загрузки избегает этого удвоения.

agenteye-backup не удается установить curl

Задание работает на образе postgres:16 и устанавливает curl при запуске для выгрузки ClickHouse по HTTP. В кластере без исходящего доступа к зеркалам пакетов Debian шаг apt-get не удается. Либо разрешите исходящий доступ из pod резервного копирования, либо встройте curl в зеркальный/пользовательский образ резервного копирования и ссылайтесь на него в вашей оверлее.

agenteye-backup работает, но ничего не попадает в хранилище объектов

База поставляется с реальным BACKUP_BUCKET (ts-prod-agenteye/backups) и agenteye-backup ServiceAccount. Задание потоком архив в S3 (tar cz … | aws s3 cp - s3://…). Если pod резервного копирования не имеет доступа на запись в ведро, загрузка ошибок — и потому что скрипт работает под set -euo pipefail, сбой в любом месте этого конвейера не удается во всем задании на шаге upload а не молча не включается (ловушка EXIT pod регистрирует backup FAILED during step: upload). Это также шаг, который вы достигаете после исправления временной эвакуации, поэтому если резервные копии ранее были вытеснены на шаге архивирования, убедитесь, что загрузка теперь приземляется. Найдите ошибку доступа S3 в журналах неудачного задания:
Исправление: в вашей оверлее установите BACKUP_BUCKET на ведро, которым вы владеете, и аннотируйте существующий ServiceAccount agenteye-backup с доступом на запись (IRSA / Workload Identity / Pod Identity). См. раздел Backups в enterprise-docs/kubernetes-deployment.md.

ClickHouse-поддерживаемые оценки / сеансы / запросы

Боковая панель страницы /queries пуста после обновления

Три таблицы (events, evaluations, agent_sessions) ожидаются. Если боковая панель SchemaBrowser пуста после обновления, сервер не применил DDL ClickHouse при запуске. Проверьте журналы сервера на failed to apply CH DDL statement:
Наиболее распространенной причиной является то, что ClickHouse недостижим во время запуска миграций. Сервер отказывается запускаться, если не может достичь CH, поэтому застрявший pod обычно имеет CrashLoopBackOff, а не молчаливо сломанную страницу запросов, но частичное применение DDL (одна выписка OK, следующие 5xx) оставляет схему полусырой. Перезагрузите pod сервера после проверки достижимости CH:

Новые оценки не появляются в /sessions или /queries

После обновления новые оценки пишутся в ClickHouse, не Postgres, и появляются в /sessions (ограничены на evaluations:read) и в /queries. Если они не появляются:
  1. Подтвердите, что конвейер оценщика включен (EVALUATOR_ENDPOINT установлен на сервере) и выдает терминальные результаты; проверьте наличие строк evaluation_finalized.
  2. Подтвердите, что CH достижим с сервера: kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping.
  3. Точечная проверка таблицы CH: kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'.

Запросы не удаются под нагрузкой с ошибкой “Memory limit exceeded”, или ClickHouse OOMKilled

Симптом: под тяжелой нагрузкой приборной панели/запроса аналитические страницы (поток событий, /sessions, представление моделей/задержки, редактор SQL) начинают не удаваться или истекать; сервер кратко колебется NotReady; и pod ClickHouse показывает растущее количество перезагрузок. Это почти всегда память, а не CPU или диск. Подтвердите, что это память (не проблема пропускной способности, которую исправила бы репликация):
  1. Проверьте pod на выходе из памяти:
    Reason: OOMKilled / Exit Code: 137 с растущим количеством перезагрузок является признаком.
  2. Спросите ClickHouse, что он отклоняет:
    Большое количество MEMORY_LIMIT_EXCEEDED — это подпись. Сообщение гласит maximum: N GiB — это N это 0.9 × лимит памяти pod (значение max_server_memory_usage_to_ram_ratio в deploy/base/clickhouse/configmap.yaml). Если тяжелые чтения нужны более чем N, они отклоняются.
  3. Исключите то, что не является проблемой — если CPU, часть количество и диск все низкие, добавление реплик/шардирования будет потраченной стоимостью:
Причина: лимит памяти pod ClickHouse слишком мал для аналитического рабочего набора. Самые тяжелые чтения вытягивают столбец payload с исходным JSON, запускают JSONExtract* над ним и используют FINAL — каждый может нуждаться в нескольких ГиБ. Если настроенные кэши (mark_cache_size + uncompressed_cache_size) больше pod, они усугубляют это: кэши заряжаются против того же бюджета и вытесняют память запроса. Исправление — масштабируйте память ClickHouse:
  1. Поднимите лимит памяти ClickHouse в вашей оверлее путем патчинга resources контейнера clickhouse StatefulSet (тот же механизм оверлея, используемый для resources других компонентов). Используемый бюджет сервера составляет 0.9 × limit, поэтому лимит 6Gi дает ~5.4 ГиБ, 16Gi дает ~14 ГиБ. Установите requests.memory на реальный пол также, чтобы планировщик его зарезервировал. Применение этого пересоздает CH pod (одна реплика → ~30–60 сек простоя аналитики); сделайте это в окне низкого трафика.
  2. Держите кэши в deploy/base/clickhouse/configmap.yaml пропорциональными лимиту — небольшие кэши (несколько сотен МиБ) безопасны на небольшом pod; только поднимите их вместе с соответствующим увеличением лимита памяти. Per-query max_memory_usage явно установлен в профиле users.xml (см. фиксированный раздел узла ниже) и держится ниже крышки уровня сервера (0.9 × limit), поэтому ни один запрос не разрешено более RAM, чем контейнер имеет.
  3. Если сам узел является потолком, проверьте хост памяти, который ClickHouse может видеть:
    Если это только немного выше лимита pod, переместите ClickHouse на больший узел (оптимизированный для памяти) — через селектор узла/сродство в вашей оверлее — перед дальнейшим поднятием лимита.
Когда вы не можете добавить память: запустите запросы в RAM и быстро отклоните — не пролейте на медленный диск. Если узел зафиксирован и pod не может вырасти, ограничьте то, что может использовать любой один запрос (поэтому один запрос не может занять весь узел) и на медленном (не-SSD) диске данных делайте не позволяйте большим агрегациям/сортировкам пролегчиться на диск. Пролегчивание на медленный диск медленнее, чем истечение времени чтения клиента сервера, поэтому пролегчивающий запрос возвращает 500 приборной панели в полете, пока ClickHouse продолжает молоть — держание запросов в RAM и быстрое отклонение редкого превышения бюджета (MEMORY_LIMIT_EXCEEDED, субсекунда) это то, что восстанавливает загрузку. Обратите внимание на подводный камень ClickHouse для применения этих:
  • Это профиль настройки, и ClickHouse читает <profiles> только из users_config (users.xml / users.d/*.xml) — никогда из config.d. Блок <profiles>, размещенный в config.d/agenteye.xml, является молчаливо игнорируемым (max_execution_time, max_memory_usage и т. д. просто не применяются). Объединенная конфигурация поэтому поставляется с ними как ключ users.xml в ConfigMap clickhouse-config, смонтированный по адресу /etc/clickhouse-server/users.d/agenteye.xml.
  • Поставляемые по умолчанию: max_memory_usage (потолок по запросу — один запрос не может потреблять весь бюджет сервера), max_bytes_before_external_group_by / max_bytes_before_external_sort = 0 (пролегчивание отключено) поэтому запросы остаются в RAM вместо того, чтобы ползти на медленный диск, и max_execution_time (охрана убежище, согласованная с истечением времени чтения клиента сервера).
  • Проверьте, что они живы (это также то, как вы обнаруживаете подводный камень config.d):
    Ожидайте ненулевого max_memory_usage и max_bytes_before_external_group_by = 0. Если max_memory_usage читается 0/default, профиль не применяется — проверьте, что живут в монтировании users.d, а не config.d.
Компромисс: с отключенным пролегчиванием запрос, чей рабочий набор превышает max_memory_usage, — это отклоняется (MEMORY_LIMIT_EXCEEDED) вместо завершения медленно — на медленном диске то быстрое отклонение предпочтительно, потому что пролегчивающий запрос превышал бы истечение времени клиента и все равно не удалось бы. Если ваш диск данных — это быстро (SSD), вы можете вместо этого поднять пороги max_bytes_before_external_* чтобы позволить большим запросам пролегчиться на диск и завершиться.

Мультитенантность (организации)

Ошибки при обновлении, которое включает организации (смешанные pod старого/нового сервера)

Симптом: во время катящегося развертывания рилиза, включающего орг, некоторые запросы не удаются: журналы сервера показывают there is no unique or exclusion constraint matching the ON CONFLICT specification на пути api_keys, и/или каналы оповещений/Slack/вебхука перестают срабатывать во время развертывания. Причина: обновление заменяет старый уникальный индекс экземпляра на api_keys(name) с частичными индексами для каждого орга и перемещает параметры канала оповещения (и default_user_permissions) из глобальной таблицы settings в org_settings для каждого орга. Pod старого сервера все еще выдает ON CONFLICT (name) (теперь нет соответствующего ограничения) и все еще читает конфигурацию канала из старых строк settings (теперь пусто). Старые и новые pod не могут безопасно сосуществовать для этих двух путей. Исправление: не делайте медленный откат для этого конкретного обновления на смешанные версии. Выполните чистое переключение: масштабируйте старый сервер до нуля (или используйте короткое окно обслуживания) и запустите новую версию вместе с ее миграциями, а не запускайте старые и новые реплики рядом. Обычный трафик и прием возобновляются сразу после переключения; это влияет только на окно переходной версии.

Провизионирование организации не удается на CREATE USER / CREATE ROW POLICY, или один орг может прочитать данные другого орга

Симптом: создание орга возвращает ошибку, упоминающую CREATE USER, CREATE ROW POLICY или управление доступом отключено; или, что хуже, члены одного орга видят события/оценки другого орга в редакторе SQL или помощнике. Причина: изоляция для каждого орга обеспечивается выделенным пользователем ClickHouse + политикой строк для каждого орга. Это требует управления доступом SQL для включения и users_without_row_policies_can_read_rows=false на ClickHouse. С отключенным управлением доступом провизионирование не может создать пользователя/политику; со значением политики строк по умолчанию, оставленным в его разрешительном значении, пользователь, имеющий SELECT но отсутствующую политику, читает все строки (сбой-открыт). Исправление: используйте объединенную конфигурацию deploy/base/clickhouse/, которая устанавливает оба. Если вы запускаете собственную конфигурацию ClickHouse, включите управление доступом SQL для внутреннего пользователя сервера и установите users_without_row_policies_can_read_rows=false (см. deploy/base/clickhouse/configmap.yaml), затем перезагрузите ClickHouse и пересоздайте орг с CLI agenteye-orgctl (см. enterprise-docs/tenant-management.md).

Пользователи организации теряют доступ ClickHouse после изменения ORG_CH_SECRET

Симптом: редактор SQL и помощник ИИ внезапно возвращают ошибки аутентификации ClickHouse для каждой организации сразу после изменения или несогласованной установки ORG_CH_SECRET на репликах. Причина: пароль ClickHouse каждого орга выводится как HMAC ORG_CH_SECRET. Ротация его (или запуск реплик с разными значениями) аннулирует сохраненный учетные данные ClickHouse каждого орга; производный пароль больше не совпадает с провизионированным пользователем. Исправление: установите ORG_CH_SECRET на одно крепкое значение перед провизионированием второго орга и держите его стабильным и идентичным на каждой реплике сервера. Перестройка загрузочного времени сервера пересобирает учетные данные ClickHouse каждого орга с текущего секрета при запуске, поэтому перезагрузка сервера