← Blog

Comment on a simplifié notre stack IA avec LiteLLM chez Evaneos

Cet article a également été publié sur tech.evaneos.com (en anglais).

L'équipe plateforme d'Evaneos partage son retour d'expérience sur l'intégration de LiteLLM, un proxy unifié supportant 100+ providers IA, dans leur infrastructure Kubernetes gérée en GitOps avec FluxCD.

Le contexte : quand la technologie devient trop « variée »

Evaneos a rencontré un problème classique après avoir expérimenté plusieurs modèles et providers d'IA générative. Nous avions accumulé des clés API qui commençaient à ressembler au trousseau d'un concierge : OpenAI, Anthropic, Gemini, Deepgram.

Cette fragmentation soulevait plusieurs questions critiques :

  • Quelle clé appartient à quel projet ?
  • Comment suivre les coûts par provider ?
  • Comment éviter les points de défaillance uniques ?
  • Comment avoir de la visibilité sur les requêtes ?

La solution : LiteLLM, un proxy qui unifie l'accès à 100+ providers IA avec une API unique compatible OpenAI.

La stack : simple mais solide

  • Kubernetes (GKE)
  • FluxCD pour la gestion GitOps
  • Helm pour le packaging
  • PostgreSQL pour la configuration et les métriques
  • Langfuse pour le tracing et l'observabilité

La mise en place étape par étape

1. Organisation des fichiers

platform/components/helm/litellm/
├── config.yaml
├── helmrelease.yaml
├── helmrepository.yaml
├── kustomization.yaml
├── ns.yaml
└── rbac.yaml

2. Repository Helm

apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: litellm
spec:
  url: oci://ghcr.io/berriai
  interval: 1h
  type: oci

3. Configuration HelmRelease

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: litellm
spec:
  releaseName: litellm
  interval: 60m
  driftDetection:
    mode: enabled
  rollback:
    cleanupOnFail: true
  values:
    pdb:
      enabled: true
      maxUnavailable: 1
    resources:
      requests:
        cpu: 200m
        memory: 1500Mi
      limits:
        memory: 4Gi

Points clés de cette configuration :

  • La détection de dérive (driftDetection) rattrape les modifications manuelles
  • Le Pod Disruption Budget garantit la disponibilité lors des mises à jour
  • Le rollback automatique en cas d'échec de déploiement
  • Ressources : 1,5Gi nominal, jusqu'à 4Gi sous charge

4. PostgreSQL : déploiement externe

Plutôt que d'utiliser la base de données incluse dans la chart, nous avons déployé PostgreSQL séparément, pour une meilleure gestion des sauvegardes, un scaling indépendant, et une intégration de supervision simplifiée.

5. Gestion des secrets

Les clés API et credentials stockés comme Secrets Kubernetes :

  • Credentials de base de données
  • Clés API des providers
  • Clé master du proxy
  • Clé de chiffrement (salt)

6. Configuration du proxy

general_settings:
  master_key: os.environ/PROXY_MASTER_KEY
  salt_key: os.environ/LITELLM_SALT_KEY

litellm_settings:
  callbacks: ["langfuse"]
  json_logs: true

model_list:
  - model_name: "provider/*"
    litellm_params:
      model: "provider/*"
      litellm_credential_name: provider_name

credential_list:
  - credential_name: provider_name
    credential_values:
      api_key: os.environ/PROVIDER_API_KEY

7. Orchestration avec Kustomize

Kustomize génère automatiquement les ConfigMaps depuis les fichiers de configuration, garantissant que toutes les ressources restent versionnées dans Git.

Le workflow quotidien

1. Le développeur commit des changements de config dans Git
   ↓
2. L'équipe revoit la pull request
   ↓
3. Merge sur la branche main
   ↓
4. FluxCD détecte les changements (toutes les heures ou via webhook)
   ↓
5. Déploiement automatique avec rollback en cas d'échec

Les bénéfices concrets

Clarté : La configuration centralisée remplace les clés API éparpillées dans tous les projets.

Moins de stress : GitOps garantit que l'état de production correspond toujours au dépôt Git ; revenir en arrière sur un changement ne demande qu'un git revert.

Visibilité : L'intégration Langfuse donne accès aux coûts par modèle, aux patterns d'utilisation, aux métriques de latence et à l'efficacité des prompts.

Flexibilité : Tester un modèle alternatif ne nécessite que de modifier quelques lignes YAML et ouvrir une pull request.

Sécurité : Authentification, chiffrement et contrôles d'accès via les mécanismes natifs Kubernetes.

Leçons apprises

Mémoire : 512Mi initial s'est révélé insuffisant. LiteLLM peut rapidement consommer de la mémoire, surtout si vous loggez les prompts. Recommandation : minimum 1,5Gi avec une limite à 4Gi.

Jobs de migration et PodDisruptionBudget : Définir ttlSecondsAfterFinished sur les jobs de migration de base de données évite qu'un job terminé ne soit comptabilisé comme pod actif et ne bloque la configuration HA.

Préférence pour une base externe : Une instance PostgreSQL autonome offre une meilleure stabilité, gestion des sauvegardes, et évite les mauvaises surprises par rapport aux solutions embarquées.

Gestion des credentials : Le système de nommage des credentials LiteLLM permet le pattern « définir une fois, référencer partout », en accord avec le principe DRY.

Conclusion

La mise en place ressemble à l'installation d'une bonne plomberie : une fois que c'est fait, on n'y pense plus et ça fonctionne. Tout est versionné et déployé automatiquement, ce qui permet de se concentrer sur les vrais cas d'usage plutôt que sur la maintenance de l'infrastructure.