Navin Cluster Agent
Le Navin Cluster Agent (module navin-manager/cluster-agent, Go) s'exécute dans un cluster Kubernetes géré par
navin-manager. Il remonte l'inventaire du cluster et applique les changements de ManagedComponent demandés par le
manager, après avoir vérifié la signature de chaque commande. Référence : CONTRACT.md section 7.14.
Import d'un cluster sans SSH
Un cluster est importé par son API uniquement. Récupérez le RBAC de moindre privilège de l'identité d'import :
GET /api/v1/clusters/{cluster_id}/kubernetes/import-rbac?namespace=navin-platform
Appliquez le yaml renvoyé avec un compte administrateur, puis enregistrez le cluster avec un kubeconfig contenant
le jeton du ServiceAccount navin-import (kubectl -n navin-platform create token navin-import). Cette identité peut
lire les nœuds, les namespaces, les CRD, les classes de stockage et d'ingress, lire le Deployment CoreDNS, et écrire
uniquement les ressources platform.navin.ai du namespace géré. Les Secrets, les workloads, les objets RBAC et tout
autre namespace sont refusés.
Installation
- Émettez l'identité de l'agent de ce cluster (une par cluster ; une nouvelle révoque la précédente) :
POST /api/v1/clusters/{cluster_id}/kubernetes/agent {"gateway_url": "https://manager.example:8462"}. La réponse contient le certificat client et sa clé privée (renvoyée une seule fois, jamais stockée), la CA du manager, la clé publique du manager et la configuration signée. - Créez le Secret
navin-cluster-agent-identitydans le namespace géré avec les fichiersconfig.json(l'objetconfig),manager.pem,tls.crt,tls.keyetca.crt. - Appliquez les manifestes de
GET /api/v1/clusters/{cluster_id}/kubernetes/agent/manifests?image=<image@sha256:...>: ServiceAccount, RBAC et un Deployment de 2 réplicas (anti affinité de pods, non root, système de fichiers en lecture seule).
RBAC de l'agent
- portée cluster, lecture seule : nœuds, namespaces, CRD, classes de stockage, classes d'ingress,
/version,/api,/apis; - namespace géré : le Lease
navin-cluster-agent(get, create, update), la ConfigMapnavin-cluster-agent-state(create, puis get et update de ce seul nom), les événements et les ressourcesplatform.navin.ai. Aucun Secret, aucun workload.
L'identité Kubernetes est le jeton du ServiceAccount du pod : il n'est valable que sur ce cluster. L'identité auprès du manager est le certificat client : la passerelle ne lui sert que les commandes de ce cluster et refuse (403, audité) un reçu pour la commande d'un autre cluster.
Connexion sortante
L'agent ouvre toutes les connexions : HTTPS (TLS 1.2 ou plus récent) vers la passerelle du manager avec son
certificat client, la CA du manager comme seul émetteur de confiance, sans les proxys de l'environnement. Aucun
Service, aucun port entrant. Il attend les commandes en long poll sur GET /v1/cluster-agent/commands (30 s au plus),
envoie l'inventaire sur /v1/cluster-agent/report et chaque résultat sur /v1/cluster-agent/receipts. Le manager
démarre la passerelle avec
python -m navin_manager.kubernetes.agent_gateway --host <adresse> --port <port> --tls-dir <dossier> --server-name <nom>.
Haute disponibilité
Seul le réplica qui détient le Lease agit. S'il disparaît, un autre réplica prend le Lease après son expiration
(lease_duration_s, 15 s par défaut) et continue avec les mêmes nonces, reçus et état désiré, conservés dans la
ConfigMap navin-cluster-agent-state. Une commande livrée au leader perdu sans reçu est relivrée par la passerelle
après 15 s ; si elle avait déjà été exécutée, le nouveau leader la refuse en nonce_replayed avec le résultat
d'origine, et le manager conserve le statut d'origine.
Commandes
Chaque commande est une enveloppe signée (Ed25519, JSON canonique, même enveloppe que le Node Agent). Elle est
refusée si la signature est invalide, la clé inconnue, la cible ou le tenant différent, la fenêtre de validité
expirée ou future, ou le nonce déjà utilisé. Opérations : managedcomponent.apply {name, spec},
managedcomponent.delete {name} (sensibles) et inventory.report (lecture seule).
Fonctionnement hors ligne
La configuration est signée : une configuration modifiée est refusée au démarrage. Quand le manager est injoignable
pendant offline_after_s, l'agent est hors ligne :
- il continue d'appliquer le dernier état désiré approuvé (un composant modifié ou supprimé à la main est rétabli) ; un état désiré dont la signature ne se vérifie plus n'est pas appliqué ;
- il refuse toute nouvelle opération sensible avec
manager_unreachable, y compris une commande correctement signée déposée dans le dossier de secours--inbox(chaque<nom>.jsonreçoit sa réponse dans<nom>.receipt.json) ; - les opérations en lecture seule continuent. Les reçus sont renvoyés au retour du manager.