Aller au contenu principal

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 dans deploy/data/*), et local-nvme pour 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=true quand vLLM ou les workers média tournent sur GPU.
  • Outils sur le poste : kubectl, helm 3.16 ou plus récent, tofu ou terraform, argocd, bao (CLI OpenBao).
  • Les flux de Ports et flux réseau ouverts.

Composants installés par les couches​

CoucheComposants 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
infraPolitiques 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
dataChart 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
platformAPISIX 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
appsdeploy/helm/enterprise-ai

Versions des charts : deploy/terraform/modules/platform-bootstrap/variables.tf (chart_versions) et deploy/argocd/applicationset.yaml.

Étapes​

  1. Installer le socle du cluster. Le module Terraform platform-bootstrap installe 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 label eai.io/environment.

    cd deploy/terraform/envs/onprem-gpu
    tofu init -backend-config=backend.hcl
    tofu plan -var kube_context=<contexte-kube>
    tofu apply

    <contexte-kube> : contexte kubeconfig dédié au cluster cible (par défaut eai-onprem, kubeconfig ~/.kube/eai-onprem.yaml). backend.hcl : votre configuration partielle du backend s3 que déclare main.tf. Le module exige aussi cosign_public_key, la clé publique PEM avec laquelle Kyverno vérifie les images (-var ou un fichier .tfvars).

    Résultat attendu : kubectl get pods -n kube-system -l k8s-app=cilium, -n cert-manager, -n kyverno, -n keda, -n argocd montrent des pods en cours d'exécution, et kubectl get ns liste enterprise-ai, eai-data, eai-security, observability, openbao, eai-sandbox.

    En cas d'échec : tofu plan montre 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).

  2. Préparer les classes de stockage. Les services de données demandent fast-ssd ; le cache vLLM du profil sur site demande local-nvme.

    kubectl get storageclass

    Résultat attendu : fast-ssd (et local-nvme avec GPU) dans la liste.

    En cas d'échec : créez les classes sur votre pilote CSI, ou remplacez storageClass et storageClassName dans deploy/data/*/values.yaml, deploy/data/postgres/cluster.yaml et vllm.modelCache.storageClass.

  3. 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.yaml

    Ré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 avec argocd cluster add <contexte-kube> --label eai.io/environment=<env>.

  4. Synchroniser la couche infra. En dev et staging la synchronisation est automatique ; en prod elle est manuelle, couche après couche.

    argocd app sync -l eai.io/environment=prod,eai.io/layer=infra
    argocd app wait -l eai.io/environment=prod,eai.io/layer=infra --health --timeout 1800

    Résultat attendu : chaque Application de la couche est Synced et Healthy ; kubectl get clusterissuer liste eai-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).

  5. 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=data
    kubectl -n openbao exec -ti openbao-0 -- bao operator init
    kubectl -n openbao exec -ti openbao-0 -- bao operator unseal
    bash deploy/openbao/bootstrap.sh

    bao operator unseal se lance une fois par part de clé de descellement demandée par init, sur chaque pod OpenBao. bootstrap.sh active KV v2 (kv), Transit, la méthode d'authentification Kubernetes et les politiques.

    Résultat attendu : bao status affiche Sealed 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).

  6. É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 par controlPlane.secretFormats (EAI_REDIS_URL commence par rediss://, EAI_DATABASE_URL contient sslmode=verify-full, EAI_NATS_URL commence par tls://). Écrivez les entrées des services tiers listées dans Secrets de la plateforme.

    Résultat attendu : kubectl get externalsecret -A affiche SecretSynced pour chaque entrée.

    En cas d'échec : kubectl describe externalsecret <nom> -n <namespace> nomme le chemin ou la propriété manquante.

    danger

    Ne 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 32 pour la plupart).

  7. 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=platform
    argocd app wait -l eai.io/environment=prod,eai.io/layer=platform --health --timeout 1800

    Ré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).

  8. 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.yaml
    helm 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.yaml

    Résultat attendu : 1 chart(s) linted, 0 chart(s) failed, et /tmp/eai.yaml contient 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.

  9. Synchroniser la couche apps. Le hook PreSync lance python -m eai.migrate avant que les Deployments ne changent ; l'API refuse de démarrer en prod tant qu'une règle de production n'est pas respectée.

    argocd app sync -l eai.io/environment=prod,eai.io/layer=apps
    argocd app wait -l eai.io/environment=prod,eai.io/layer=apps --health --timeout 1800

    Sans 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.yaml

    Résultat attendu : kubectl -n enterprise-ai get pods montre les pods Control Plane, worker, portail et LiteLLM Running, et le Job de migration Completed.

    En cas d'échec : kubectl -n enterprise-ai logs deploy/enterprise-ai-control-plane affiche unsafe production settings: suivi de chaque règle en défaut ; corrigez-les dans les valeurs ou dans OpenBao (Règles de production).

  10. 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 dans kv/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:8080
    fga model write --store-id <id-du-store> --file deploy/policies/openfga/model.fga

    Ré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​

Dépannage​

SymptômeCauseCorrection
Pods refusés à l'admission par eai-verify-image-signaturesImage non signée avec la clé Cosign de la CISignez l'image dans Harbor, ou mettez-la en miroir sous */mirror et signez-la
Pods refusés par eai-image-provenanceImage hors des projets Harbor signés et sans empreinteMettez l'image en miroir dans Harbor ou référencez-la par empreinte
Une Application de données reste ProgressingPersistentVolumeClaim Pendingkubectl get pvc -A ; créez la classe de stockage fast-ssd
ExternalSecret en SecretSyncedErrorOpenBao scellé, ou chemin absentbao status ; écrivez l'entrée de l'inventaire
Control Plane en CrashLoopBackOff avec unsafe production settingsUne règle de production n'est pas respectéeCorrigez chaque réglage listé (Référence de configuration)
Job de migration en échecBase injoignable ou TLS refusékubectl -n enterprise-ai logs job/<job> ; vérifiez EAI_DATABASE_URL et l'autorité montée pour sslrootcert