- 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
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) |
| openssl | — | openssl version | OpenSSL 1.x ou 3.x |
| Bucket de stockage cloud | — | Pour les sauvegardes PostgreSQL + ClickHouse (S3, GCS ou Azure Blob) | — |
Exécuter toutes les vérifications en une seule fois
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
AGENTEYE_TOKEN.
Structure des répertoires :
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.
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.Running — cert-manager, cert-manager-cainjector, cert-manager-webhook.
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.Running.
kubectl describe pod -n traefik-public <nom-du-pod> 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 utiliseAvant d’installer, modifiezvalues-dashboard.yaml, qui restreint l’accès avec le champ portableservice.loadBalancerSourceRanges. Unvalues-internal.yamlparallèle est également fourni pour les environnements AWS qui préfèrent l’annotationservice.beta.kubernetes.io/aws-load-balancer-source-ranges. Choisissez l’un et utilisez-le de manière cohérente ; les étapes ci-dessous supposentvalues-dashboard.yaml.
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
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 :
- 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.10est rejetée par le fournisseur cloud ; utilisez203.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.
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 :
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 :
Running.
1.4 Attendre les LoadBalancers
Les deux instances Traefik ont besoin d’IP externes avant de continuer.EXTERNAL-IP (pas <pending>).
Si toujours en attente, surveillez l’attribution :
Ctrl+C une fois l’IP apparue. L’attribution d’IP prend généralement 2 à 5 minutes.
En cas d’échec : <pending> 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
Active.
2.2 Secret de tirage d’image
Ce secret s’authentifie auprès deghcr.io pour tirer les images conteneur d’AgentEye. Voir enterprise-docs/github-token.md pour savoir comment générer votre PAT.
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 :
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.
2.3 Identifiants PostgreSQL
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 connexionDATABASE_URL. Voir enterprise-docs/troubleshooting.md 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 :
48 (24 octets hex = 48 caractères).
2.4 Clé API admin
Stockez ADMIN_KEY dans votre gestionnaire de secrets immédiatement.
Vérification :
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 APIADMIN_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.
| 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 :
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 orgdefault. 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) refuse de s’exécuter tant que le serveur utilise encore la valeur dev intégrée.
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
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 :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) :3.3 Attendre les pods
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), 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 :
agent et redis apparaissent également et atteignent l’état Running) :
| Statut du pod | Cause probable | Commande de débogage |
|---|---|---|
ImagePullBackOff | Secret de tirage d’image incorrect ou PAT invalide | kubectl describe pod <name> -n agenteye |
CrashLoopBackOff | Variables d’environnement incorrectes (ex. DATABASE_URL) | kubectl logs <name> -n agenteye |
Pending | CPU/mémoire insuffisants ou aucun nœud disponible | kubectl describe pod <name> -n agenteye (vérifier les Events) |
3.4 Vérifier le stockage
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 |
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
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é) |
ingest-tls ou dashboard-tls n’est pas Ready :
Exécutez kubectl describe certificate <name> -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_DOMAINdoit résoudre vers le LB public,DASHBOARD_DOMAINvers le LB du tableau de bord. Tant que le CNAME/Alias ne se propage pas, la commande restepending. Une fois le DNS correct, cert-manager réessaie automatiquement (pas besoin de supprimer le Certificate). - Nom d’hôte non substitué. Si
dnsNamesaffiche encoreINGEST_DOMAIN_PLACEHOLDER/DASHBOARD_DOMAIN_PLACEHOLDER, vous avez sauté l’étape 3.1 — créezbase/certificates/domain.envet 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 commandependingindéfiniment.
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
| 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
POSTGRES_PASSWORD contenant des caractères non sûrs pour les URL qui cassent la DATABASE_URL. Voir enterprise-docs/troubleshooting.md.
3.8 Vérifier la connexion du tableau de bord au serveur
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
Sur AWS EKS, les LoadBalancers retournent un nom d’hôte au lieu d’une IP. RemplacezVérification :.ippar.hostnamedans les commandes ci-dessus.
4.2 Pointer le DNS vers les LoadBalancers
Créez des enregistrements DNS pour que les noms d’hôte debase/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
AavecAlias = Yes, cible = le nom d’hôte du LB. N’utilisez pas un simple A → IP ; les IP ELB changent. - Tout autre fournisseur :
CNAMEdu nom d’hôte vers le nom d’hôte du LB.
$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 :
{"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 :
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 permissionevents: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 :<cluster-name> par un identifiant significatif (ex. us-east-1-prod, staging).
Vérification : Le script affiche ==> Done! et liste les fichiers de sortie.
Ready: True.
Fichiers de sortie dans issued/<cluster-name>/ :
| 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 declient.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 avec IRSA, et la rotation des certificats est entièrement automatisée.
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
awsv2 authentifiée sur votre compte AWS. jqinstallé.- Variable d’environnement
AWS_REGIONdéfinie. - Permissions IAM sur votre identité appelante (limitez
Resourceàarn:aws:secretsmanager:<region>:<account>:secret:agenteye/mtls-client/*) :secretsmanager:CreateSecretsecretsmanager:DescribeSecretsecretsmanager:PutSecretValuesecretsmanager:TagResource
| Étape | Action |
|---|---|
| 1 | Émet / ré-extrait le certificat via cert-manager (identique au mode par défaut). |
| 2 | Appelle DescribeSecret sur agenteye/mtls-client/<cluster-name> 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=<cluster-name>. Exécutions suivantes : PutSecretValue pour publier une nouvelle version ; tag rafraîchi via TagResource. |
| 4 | Supprime issued/<cluster-name>/ uniquement après un téléversement réussi. En cas d’échec, le répertoire est conservé pour permettre une nouvelle tentative. |
aws secretsmanager restore-secret --secret-id agenteye/mtls-client/<cluster-name> 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.
5.2 Vérifier que le certificat fonctionne
Testez le certificat émis contre l’ingress mTLS :{"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-<name> -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
Envoyezcollector-mtls-secret.yaml à l’équipe qui opère le cluster collecteur. Ils l’appliquent :
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) |
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 :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ésagenteye.io/cert-type=mtls-client. Il alerte quand un certificat est dans les 30 jours avant expiration.
6.1 Activer les notifications Slack (optionnel)
6.2 Tester le CronJob
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 :
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, ciblezhttps://ingest.votre-entreprise.example/...au lieu de${PUBLIC_IP}et supprimez-k.
7.1 Vérification de santé
{"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ésevents:add dédiées pour les collecteurs :
"id", "name": "prod-collector", "permissions": ["events:add"], "created_at".
Vérification : Confirmez que la clé apparaît dans la liste des clés :
prod-collector apparaît dans la réponse.
Voir enterprise-docs/api-keys.md pour la référence complète de gestion des clés.
7.3 Ingérer un événement de test
{"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
Ouvrezhttps://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 :Vérification : L’événement de test de fumée doit apparaître dans la liste des événements avec la sessionGardez à 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.
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
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 queNettoyage :BACKUP_BUCKETest défini (la base fournit une valeur de bucket par défaut). Elle est ignorée uniquement siBACKUP_BUCKETest vide ou littéralementPLACEHOLDER. Pointez-le vers votre propre bucket et accordez au ServiceAccountagenteye-backupun accès en écriture avant de vous y fier (voir la section Sauvegardes ci-dessous).
7.6 Provisionner les organisations (multi-tenant)
Ignorez cette section pour un déploiement mono-tenant ; toutes les données résident dans l’orgdefault 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.Créer une org et ajouter son premier admin :org createrefuse de s’exécuter tant que le serveur utilise encore leORG_CH_SECRETdev intégré, et l’utilisateur ClickHouse par org qu’il provisionne dépend de ce secret étant fort et stable.
/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 <slug> --name <new name> | Renommer une org (slug inchangé). |
org delete --slug <slug> | Suppression logique + suppression de l’utilisateur ClickHouse de l’org ; données conservées. |
org purge --slug <slug> | Effacement irréversible des données ; l’org doit être deleted en premier ; jamais l’org default. |
member list --org <slug> | Lister les membres et leurs permissions. |
member update --org <slug> --email <email> [--set ...] [--add ...] [--remove ...] | Modifier les permissions d’un membre. |
member remove --org <slug> --email <email> | Retirer un membre de l’organisation. |
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 :Documentation associée
| Guide | Description |
|---|---|
| Déploiement géré | Guide de configuration d’un déploiement géré sur votre cluster Kubernetes |
| Bien démarrer | Procédure complète avec Docker Compose |
| Déploiement | Déploiement Docker, variables d’environnement et configuration |
| Gestion des tenants | Provisionnement des organisations et membres avec le CLI agenteye-orgctl |
| Configuration du jeton GitHub | Génération du PAT GitHub pour accéder aux artefacts |
| Installation du collecteur | Toutes les méthodes d’installation du collecteur |
| SDK Python | Référence complète de l’API du SDK |
| Clés API | Création et gestion des clés API |
| Dépannage | Problèmes courants et solutions |
Support
Envoyez un e-mail àsupport@exosphere.host pour obtenir de l’aide sur le déploiement.
