Installer la Navin Platform sur Kubernetes avec Helm
Cette page installe la Navin Platform sur un cluster Kubernetes : les opérateurs du cluster, les services de données et
de sécurité, puis le chart enterprise-ai (API Control Plane, worker, portail, LiteLLM, vLLM, workers média). Elle
est réalisée par un ingénieur plateforme disposant des droits d'administration du cluster. Comptez un à deux jours
pour un premier cluster de production, surtout pour les secrets et les certificats.
En production, Argo CD installe tout depuis le dépôt en quatre couches (deploy/argocd/applicationset.yaml) :
infra, data, platform et apps. Un helm upgrade --install direct du chart est aussi décrit, pour un cluster
dont les dépendances existent déjà.
Avant de commencer
- Kubernetes 1.27 ou plus récent : le chart déclare
kubeVersion: ">=1.27.0-0". Vérifier :kubectl version. - Un pilote de stockage CSI avec une classe de stockage nommée
fast-ssd(ou changez le nom dansdeploy/data/*), etlocal-nvmepour le cache des modèles vLLM du profil GPU sur site. Voir Dimensionnement. - Un stockage objet compatible S3 joignable en HTTPS (Ceph RGW ou toute API S3) pour l'archive d'audit WORM, les artefacts média, les sauvegardes CloudNativePG et Velero.
- Un registre Harbor (ou un registre OCI équivalent) contenant les images, en miroir et signées, et une paire de clés Cosign : les politiques Kyverno refusent les images de plateforme non signées.
- Une zone DNS pour les noms publics (
<control-plane-host>,<portal-host>dans les manifestes) et une autorité de certification publique ou d'entreprise (TLS). - Des nœuds GPU NVIDIA portant le label
nvidia.com/gpu.present=truequand vLLM ou les workers média tournent sur GPU. - Outils sur le poste :
kubectl,helm3.16 ou plus récent,tofuouterraform,argocd,bao(CLI OpenBao). - Les flux de Ports et flux réseau ouverts.
Composants installés par les couches
| Couche | Composants et versions épinglées |
|---|---|
socle (module Terraform platform-bootstrap) | Cilium 1.16.5, cert-manager v1.16.2, chart Kyverno 3.3.4, KEDA 2.16.1, chart CloudNativePG 0.23.0, chart Velero 8.1.0, NVIDIA GPU Operator v24.9.1, chart Argo CD 7.7.11, namespaces avec leur niveau Pod Security |
infra | Politiques Cilium, émetteurs cert-manager, CRD ToolHive 0.59.0, politiques Kyverno, objets KEDA, planifications Velero, External Secrets 2.14.0, kube-prometheus-stack 92.16.0, CRD SPIRE 0.6.1 et SPIRE 0.30.4 |
data | Chart OpenBao 0.30.6, secrets de la plateforme, PostgreSQL (CloudNativePG), opérateur Redis 0.27.0 et réplication Redis 0.17.1, NATS 2.15.1, Qdrant 1.20.0, Temporal 1.7.0, opérateur ClickHouse 0.27.4, Keycloak (keycloakx 7.4.0) et son realm, OpenFGA 0.3.19, OPA |
platform | APISIX 2.18.2 et ses routes, LiveKit, OpenSearch 3.9.0, Alloy 1.14.4, OpenTelemetry Collector 0.178.1, Jaeger 4.16.1, Opik 2.2.137, règles d'alerte, ToolHive Operator 0.59.0 |
apps | deploy/helm/enterprise-ai |
Versions des charts : deploy/terraform/modules/platform-bootstrap/variables.tf (chart_versions) et
deploy/argocd/applicationset.yaml.
Étapes
-
Installer le socle du cluster. Le module Terraform
platform-bootstrapinstalle les opérateurs dont toutes les autres couches ont besoin (réseau, certificats, admission, autoscaling, opérateur PostgreSQL, sauvegardes, GPU, Argo CD), crée chaque namespace avec son niveau Pod Security et enregistre le cluster dans Argo CD avec le labeleai.io/environment.cd deploy/terraform/envs/onprem-gputofu init -backend-config=backend.hcltofu plan -var kube_context=<contexte-kube>tofu apply<contexte-kube>: contexte kubeconfig dédié au cluster cible (par défauteai-onprem, kubeconfig~/.kube/eai-onprem.yaml).backend.hcl: votre configuration partielle du backends3que déclaremain.tf. Le module exige aussicosign_public_key, la clé publique PEM avec laquelle Kyverno vérifie les images (-varou un fichier.tfvars).Résultat attendu :
kubectl get pods -n kube-system -l k8s-app=cilium,-n cert-manager,-n kyverno,-n keda,-n argocdmontrent des pods en cours d'exécution, etkubectl get nslisteenterprise-ai,eai-data,eai-security,observability,openbao,eai-sandbox.En cas d'échec :
tofu planmontre la ressource en erreur. Un chart impossible à télécharger signifie que le cluster n'accède pas aux dépôts de charts : utilisez le miroir de l'installation déconnectée (helm_repository_mirror). -
Préparer les classes de stockage. Les services de données demandent
fast-ssd; le cache vLLM du profil sur site demandelocal-nvme.kubectl get storageclassRésultat attendu :
fast-ssd(etlocal-nvmeavec GPU) dans la liste.En cas d'échec : créez les classes sur votre pilote CSI, ou remplacez
storageClassetstorageClassNamedansdeploy/data/*/values.yaml,deploy/data/postgres/cluster.yamletvllm.modelCache.storageClass. -
Enregistrer le projet GitOps et l'ApplicationSet. L'AppProject limite les sources et les destinations ; l'ApplicationSet génère une Application par composant pour chaque cluster portant le label d'environnement.
kubectl -n argocd apply -f deploy/argocd/appproject.yaml -f deploy/argocd/repository-toolhive.yaml \-f deploy/argocd/applicationset.yamlRésultat attendu :
argocd app list -l eai.io/environment=<env>liste les Applications des quatre couches.En cas d'échec : une liste vide signifie que le secret de cluster d'Argo CD n'a pas le label
eai.io/environment; ajoutez-le avecargocd cluster add <contexte-kube> --label eai.io/environment=<env>. -
Synchroniser la couche
infra. Endevetstagingla synchronisation est automatique ; enprodelle est manuelle, couche après couche.argocd app sync -l eai.io/environment=prod,eai.io/layer=infraargocd app wait -l eai.io/environment=prod,eai.io/layer=infra --health --timeout 1800Résultat attendu : chaque Application de la couche est
SyncedetHealthy;kubectl get clusterissuerlisteeai-internal-ca.En cas d'échec :
argocd app get <application>montre la ressource en erreur. Une CRD manquante est réessayée par Argo CD (10 tentatives, jusqu'à 10 minutes). -
Synchroniser la couche
data, puis initialiser OpenBao. OpenBao démarre scellé à la première installation : les secrets de tous les autres composants l'attendent.argocd app sync -l eai.io/environment=prod,eai.io/layer=datakubectl -n openbao exec -ti openbao-0 -- bao operator initkubectl -n openbao exec -ti openbao-0 -- bao operator unsealbash deploy/openbao/bootstrap.shbao operator unsealse lance une fois par part de clé de descellement demandée parinit, sur chaque pod OpenBao.bootstrap.shactive KV v2 (kv), Transit, la méthode d'authentification Kubernetes et les politiques.Résultat attendu :
bao statusafficheSealed false.En cas d'échec : gardez les clés de descellement et le jeton racine hors du cluster, dans le coffre de la banque. Un pod qui reste scellé après un redémarrage demande à nouveau les clés (ou un descellement automatique configuré dans
deploy/openbao/values.yaml). -
Écrire les secrets. Chaque service tiers lit ses identifiants dans un Secret produit par External Secrets depuis OpenBao. Le Control Plane lit les siens dans
kv/eai/<env>/control-plane.bao kv put kv/eai/prod/control-plane \EAI_DATABASE_URL='postgresql://eai:<mot-de-passe>@eai-postgres-rw.eai-data.svc:5432/eai?sslmode=verify-full&sslrootcert=/run/secrets/postgres-ca/ca.crt' \EAI_REDIS_URL='rediss://eai-control-plane:<mot-de-passe>@redis-master.eai-data.svc:6379/0' \EAI_MASTER_KEY='<cle-aleatoire>' EAI_OPENBAO_TOKEN='<jeton>' EAI_METRICS_TOKEN='<32-caracteres-aleatoires>'Les clés tirées sont celles de
controlPlane.secrets.keys(values-prod.yaml) ; leurs formats sont contrôlés parcontrolPlane.secretFormats(EAI_REDIS_URLcommence parrediss://,EAI_DATABASE_URLcontientsslmode=verify-full,EAI_NATS_URLcommence partls://). Écrivez les entrées des services tiers listées dans Secrets de la plateforme.Résultat attendu :
kubectl get externalsecret -AafficheSecretSyncedpour chaque entrée.En cas d'échec :
kubectl describe externalsecret <nom> -n <namespace>nomme le chemin ou la propriété manquante.dangerNe versionnez jamais une valeur secrète et n'en mettez jamais dans un fichier de valeurs. Générez chacune avec la commande de l'inventaire des secrets (
openssl rand -base64 32pour la plupart). -
Synchroniser la couche
platform. Elle installe la passerelle (APISIX), LiveKit, la pile d'observabilité et ToolHive Operator.argocd app sync -l eai.io/environment=prod,eai.io/layer=platformargocd app wait -l eai.io/environment=prod,eai.io/layer=platform --health --timeout 1800Résultat attendu : le Service APISIX a une adresse externe :
kubectl -n apisix get svc.En cas d'échec : un Service APISIX sans adresse signifie que le cluster n'a pas de répartiteur de charge (MetalLB, répartiteur cloud ou celui de votre équipe réseau).
-
Fixer les valeurs de votre site. Changez les noms et adresses d'exemple avant la première synchronisation de la couche
apps:<control-plane-host>,<portal-host>,<keycloak-host>,<s3-host>,<harbor-host>. Les valeurs à revoir figurent dans la référence des valeurs Helm :global.imageRegistry,controlPlane.config.EAI_CORS_ORIGINS,EAI_ALLOWED_HOSTS,EAI_TRUSTED_PROXIES,EAI_OIDC_ISSUER,portal.config.*,portal.ingress.host,networkSecurity.objectStorageFQDNs.Vérifiez le rendu hors ligne :
helm lint deploy/helm/enterprise-ai -f deploy/helm/enterprise-ai/values-prod.yamlhelm template eai deploy/helm/enterprise-ai -n enterprise-ai \-f deploy/helm/enterprise-ai/values-prod.yaml -f deploy/helm/enterprise-ai/values-ha.yaml > /tmp/eai.yamlRésultat attendu :
1 chart(s) linted, 0 chart(s) failed, et/tmp/eai.yamlcontient 38 objets avec les profils de production et HA (4 Deployments : Control Plane, worker, portail, LiteLLM ; le Job de migration ; ConfigMaps, ExternalSecrets, HPA, PDB, politiques Cilium, moniteurs).En cas d'échec : le message nomme la valeur ; comparez-la avec la page de référence.
-
Synchroniser la couche
apps. Le hookPreSynclancepython -m eai.migrateavant que les Deployments ne changent ; l'API refuse de démarrer enprodtant qu'une règle de production n'est pas respectée.argocd app sync -l eai.io/environment=prod,eai.io/layer=appsargocd app wait -l eai.io/environment=prod,eai.io/layer=apps --health --timeout 1800Sans Argo CD, sur un cluster dont les dépendances tournent déjà :
helm upgrade --install enterprise-ai deploy/helm/enterprise-ai -n enterprise-ai \-f deploy/helm/enterprise-ai/values-prod.yaml -f deploy/helm/enterprise-ai/values-onprem-gpu.yamlRésultat attendu :
kubectl -n enterprise-ai get podsmontre les pods Control Plane, worker, portail et LiteLLMRunning, et le Job de migrationCompleted.En cas d'échec :
kubectl -n enterprise-ai logs deploy/enterprise-ai-control-planeafficheunsafe production settings:suivi de chaque règle en défaut ; corrigez-les dans les valeurs ou dans OpenBao (Règles de production). -
Charger le modèle d'autorisation. OpenFGA a besoin du modèle de
deploy/policies/openfga/model.fga; les identifiants du store et du modèle vont danskv/eai/<env>/control-plane(EAI_OPENFGA_STORE_ID,EAI_OPENFGA_MODEL_ID).fga store create --name enterprise-ai --api-url https://openfga.eai-security.svc.cluster.local:8080fga model write --store-id <id-du-store> --file deploy/policies/openfga/model.fgaRésultat attendu :
fga model list --store-id <id-du-store>affiche un modèle.En cas d'échec : la clé partagée d'OpenFGA (
eai/platform/eai-security/openfga-preshared) doit être passée avec--api-token.
Vérifier
Suivez Vérifier l'installation. Le contrôle court :
curl -fsS <control-plane-url>/readyz
Sortie attendue : {"status": "ready", "checks": {"database": true, "migrations": true}, ...}.
Étapes suivantes
- Certificats TLS
- Première configuration
- Topologies d'hébergement pour la haute disponibilité et le multi-site
Dépannage
| Symptôme | Cause | Correction |
|---|---|---|
Pods refusés à l'admission par eai-verify-image-signatures | Image non signée avec la clé Cosign de la CI | Signez l'image dans Harbor, ou mettez-la en miroir sous */mirror et signez-la |
Pods refusés par eai-image-provenance | Image hors des projets Harbor signés et sans empreinte | Mettez l'image en miroir dans Harbor ou référencez-la par empreinte |
Une Application de données reste Progressing | PersistentVolumeClaim Pending | kubectl get pvc -A ; créez la classe de stockage fast-ssd |
ExternalSecret en SecretSyncedError | OpenBao scellé, ou chemin absent | bao status ; écrivez l'entrée de l'inventaire |
Control Plane en CrashLoopBackOff avec unsafe production settings | Une règle de production n'est pas respectée | Corrigez chaque réglage listé (Référence de configuration) |
| Job de migration en échec | Base injoignable ou TLS refusé | kubectl -n enterprise-ai logs job/<job> ; vérifiez EAI_DATABASE_URL et l'autorité montée pour sslrootcert |