Vai al contenuto principale
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.

Prerequisiti

Eseguite ogni comando di verifica prima di iniziare. Ogni controllo deve essere superato.
RequisitoMinimoComando di VerificaRisultato atteso
Cluster Kubernetes1.27+kubectl versionServer Version >= v1.27
Kustomize (incluso in kubectl)Kustomize v1.14+ (incluso in kubectl 1.27+)kubectl kustomize --helpStampa il testo di utilizzo
Helmv3helm versionVersion:"v3.x.x"
RBAC cluster-adminkubectl auth can-i create namespacesyes
StorageClass predefinitakubectl get storageclassAlmeno una riga contrassegnata come (default)
Supporto LoadBalancerDipende dal cloud (EKS, GKE, AKS supportano questo per impostazione predefinita)
GitHub PATecho $AGENTEYE_TOKENNon vuoto (vedere enterprise-docs/github-token.md)
opensslopenssl versionOpenSSL 1.x o 3.x
Bucket di archiviazione cloudPer 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 per i requisiti completi.

Eseguire tutti i controlli contemporaneamente

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

Testate:
Risultato atteso: il file esiste. Se non esiste, il clone non è riuscito — controllate il vostro AGENTEYE_TOKEN. Struttura directory:
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.

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.
Testate:
Risultato atteso: 3 pod tutti Runningcert-manager, cert-manager-cainjector, cert-manager-webhook.
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.
Testate:
Risultato atteso: 1 pod Running.
Risultato atteso: la IngressClass esiste (non è la classe predefinita). Se non riesce: controllate kubectl describe pod -n traefik-public <pod-name> 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

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:
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:
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:
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:
Testate:
Risultato atteso: 1 pod Running.
Risultato atteso: la IngressClass esiste.

1.4 Attendere i LoadBalancer

Entrambe le istanze Traefik hanno bisogno di IP esterni prima di procedere.
Testate: entrambi i servizi mostrano un EXTERNAL-IP (non <pending>). Se ancora in sospeso, aspettate l’assegnazione:
Premete Ctrl+C una volta che l’IP appare. L’assegnazione dell’IP di solito richiede 2-5 minuti. Se non riesce: <pending> 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

Testate:
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 per come generare il vostro PAT.
Testate:
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:
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.

2.3 Credenziali PostgreSQL

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 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:
Risultato atteso: il secret esiste.
Risultato atteso: 48 (24 byte hex = 48 caratteri).

2.4 Chiave API Admin

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 per il modello di permessi completo.
Memorizzate ADMIN_KEY nel vostro gestore di segreti immediatamente.
Testate:
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.
ChiaveScopo
ADMIN_EMAILUtente 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_EMAILSAllowlist 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_FROMRelè 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_TLSUno di starttls (predefinito), tls o none.
DEFAULT_ORG_NAME, DEFAULT_ORG_SLUGOpzionale. 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:
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) rifiuta di eseguire mentre il server è ancora sul default dev incorporato.
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

Output atteso (tra qualsiasi secret predefinito):
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:
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):
L’overlay include la base automaticamente; applicate uno, non entrambi.

3.3 Aspettare i pod

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), e Redis è una cache best-effort, quindi nessuno dei due ha bisogno di essere Ready affinché la piattaforma serva il traffico. Testate:
Risultato atteso (i pod opzionali agent e redis compaiono anche e raggiungono Running):
Se non riesce:
Stato PodCausa probabileComando di Debug
ImagePullBackOffSecret di pull dell’immagine scadente o PATkubectl describe pod <name> -n agenteye
CrashLoopBackOffVariabili d’ambiente scadenti (ad es. DATABASE_URL)kubectl logs <name> -n agenteye
PendingCPU/memoria insufficiente o nessun nodokubectl describe pod <name> -n agenteye (controllate Events)

3.4 Verificare l’archiviazione

Risultato atteso, entrambi con stato Bound:
PVCCapacitàSupporta
postgres-data-postgres-050GiArchivio relazionale/metadati PostgreSQL
clickhouse-data-clickhouse-0100GiArchivio 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

Risultato atteso: 3 certificati, tutti Ready: True:
NomeEmittenteScopo
mtls-caselfsignedCA privata per l’emissione di certificati client mTLS (validità 10 anni)
ingest-tlsletsencrypt-prodCertificato TLS pubblico per l’endpoint di acquisizione (90 giorni, rinnovato automaticamente)
dashboard-tlsletsencrypt-prodCertificato TLS pubblico per la dashboard (90 giorni, rinnovato automaticamente)
Se ingest-tls o dashboard-tls non è Ready: kubectl describe certificate <name> -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

Risultato atteso:
NomePianificazioneScopo
agenteye-backup0 3 * * *Backup giornaliero di Postgres + ClickHouse alle 03:00 UTC
cert-renewal-check0 3,15 * * *Avvisi di scadenza certificato alle 03:00 e 15:00 UTC

3.7 Verificare che il server sia stato avviato correttamente

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.

3.8 Verificare che la dashboard sia connessa al server

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

Su AWS EKS, i LoadBalancer restituiscono un hostname invece di un IP. Sostituite .ip con .hostname nei comandi di cui sopra.
Testate:
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:
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:
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:
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:
Sostituite <cluster-name> con un identificatore significativo (ad es. us-east-1-prod, staging). Testate: lo script stampa ==> Done! ed elenca i file di output.
Risultato atteso: Ready: True. File di output in issued/<cluster-name>/:
FileScopo
client.crtCertificato client (validità 90 giorni)
client.keyChiave privata client
ca.crtCertificato CA per la verifica del server
collector-mtls-secret.yamlSecret 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 con IRSA, e la rotazione del certificato è completamente senza mani.
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:<region>:<account>:secret:agenteye/mtls-client/*):
    • secretsmanager:CreateSecret
    • secretsmanager:DescribeSecret
    • secretsmanager:PutSecretValue
    • secretsmanager:TagResource
Cosa fa lo script in questa modalità:
PassaggioAzione
1Emette / ri-estrae il certificato tramite cert-manager (uguale alla modalità predefinita).
2Chiama DescribeSecret su agenteye/mtls-client/<cluster-name> per decidere creare-vs-aggiornare.
3Al primo avvio: CreateSecret con un payload JSON a tre chiavi (client.crt, client.key, ca.crt), taggato AgentEyeCluster=<cluster-name>. Sui successivi avvii: PutSecretValue per pubblicare una nuova versione; tag aggiornato tramite TagResource.
4Cancella issued/<cluster-name>/ 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/<cluster-name> prima di ritentare. Per il cablaggio completo del pod (SecretProviderClass, setup IRSA, comportamento di rotazione, troubleshooting) consultate enterprise-docs/single-pod-deployment.md.

5.2 Verificare che il certificato funzioni

Testate il certificato emesso rispetto all’ingresso mTLS:
Risultato atteso: {"status":"ok"} Se non riesce:
ErroreCausaCorrezione
certificate requiredCertificato non presentatoControllate i percorsi file nel comando curl
bad certificateMancata corrispondenza CAVerificate che mtls-ca-issuer abbia emesso il certificato: kubectl describe certificate mtls-client-<name> -n agenteye
connection refusedHostname sbagliato o LB non raggiungibileControllate /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:
Quindi configurate il collector per montare il secret e utilizzare i percorsi certificato:
Consultate enterprise-docs/collector-installation.md per la configurazione completa del collector inclusi i montaggi del volume Kubernetes. Testate (nel cluster del collector):
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 client90 giorni
Auto-rinnovocert-manager rinnova 15 giorni prima della scadenza
Validità CA10 anni
Avvisi di scadenzaCronJob 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:
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)

Senza questo secret, il CronJob continua a funzionare e registra lo stato del certificato nello stdout. Testate:
Risultato atteso: il secret esiste.

6.2 Testare il CronJob

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:

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

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:
Testate: la risposta include "id", "name": "prod-collector", "permissions": ["events:add"], "created_at". Testate: verificate che la chiave appaia nell’elenco di chiavi:
Risultato atteso: prod-collector appare nella risposta. Consultate enterprise-docs/api-keys.md per il riferimento di gestione completo delle chiavi.

7.3 Acquisire un evento di test

Risultato atteso: {"accepted":1,"skipped":0} con HTTP 200. Se non riesce:
Codice di stato HTTPCausa
401Chiave API non valida o mancante
403La chiave manca del permesso events:add
Errore di handshake TLSProblema 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:
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

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:

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:
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 …):
ComandoCosa fa
org listElenca le organizzazioni e il loro stato.
org rename --slug <slug> --name <new name>Rinomina un’organizzazione (slug invariato).
org delete --slug <slug>Soft-delete + rilascia l’utente ClickHouse dell’organizzazione; dati conservati.
org purge --slug <slug>Wipe dei dati irreversibile; l’organizzazione deve essere prima deleted; mai l’organizzazione default.
member list --org <slug>Elenca i membri e i loro permessi.
member update --org <slug> --email <email> [--set ...] [--add ...] [--remove ...]Modificare i permessi di un membro.
member remove --org <slug> --email <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.

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-<timestamp>.tar.gz, che si decomprime in:
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)