Skip to content

Dépannage ​

L'opérateur est conçu pour être auto-explicatif : lorsque quelque chose est en attente ou ne va pas, les status.conditions de la ressource et les Events Kubernetes vous disent exactement ce qu'il attend. Commencez par là.

Premières étapes ​

bash
# The resource's conditions, events, and phase.
kubectl -n <ns> describe gateway <name>

# Just the conditions.
kubectl -n <ns> get gateway <name> -o jsonpath='{.status.conditions}' | jq

# The operator's own logs.
kubectl -n navique-system logs deploy/navique-ai-core-operator -f

Chaque ressource expose une condition Ready plus des conditions par phase (SecretsReady, OperatorsReady, DatastoreReady, WorkloadReady, …), chacune avec un reason et un message.

Lire les conditions ​

Reason de conditionCe que cela signifieQue faire
SecretsNotReadyLe SecretsManagement référencé n'est pas prêtVérifiez la ressource SecretsManagement et son backend ESO/Sealed Secrets
WaitingForCRDEstablishedLes CRDs d'un opérateur de capacité ne sont pas encore EstablishedNormal pendant l'installation ; vérifiez les pods de l'opérateur si cela persiste
DependencyNotReadyUn datastore / gateway / Langfuse référencé n'est pas prêtInspectez la ressource référencée
AutoWiringUnlicensedUne référence a besoin de l'auto-wiring, qui n'est pas sous licenceFournissez les champs manuels que le message nomme, ou appliquez une licence
LicenseLimitExceededVous avez dépassé un plafond d'instances sous licenceRéduisez les instances ou augmentez les limits dans la licence
BackendNotImplementedUn backend en ébauche (zalando / cockroachdb) a été sélectionnéUtilisez cnpg, ou adopt / external
InfrastructureBlockedUn pod de datastore géré ne peut pas démarrer pour une raison d'infrastructure du cluster que l'opérateur ne peut pas résoudre en attendantLisez le message — il nomme le pod et la cause (non planifiable, attachement de volume, pull d'image) — et corrigez-le au niveau du cluster

Une ressource qui remet en file d'attente en attendant est normale — l'opérateur remet en file d'attente plutôt que d'échouer pour un « pas encore prêt ». Une ressource bloquée à Ready=False avec un reason d'erreur est celle à investiguer.

Diagnostics d'installation d'opérateur de capacité ​

Lorsqu'un opérateur de capacité ne démarre pas, l'opérateur inspecte son namespace et fait remonter la cause dans le status de la ressource consommatrice — par exemple un reason Waiting d'un conteneur, un OOM/last-termination, ou le dernier Warning event comme FailedMount: secret "webhook-server-cert" not found. Ainsi, une installation amont bloquée est expliquée dans la ressource qui en a besoin.

bash
# Inspect a capability operator directly.
kubectl -n cnpg-system get pods
kubectl -n cert-manager get pods,events --sort-by=.lastTimestamp

Problèmes courants ​

Le manager est tué par OOM ​

Le moteur Helm intégré au binaire rend les charts en processus et a besoin de mémoire. Donnez au manager ~1Gi — les limites Kubebuilder par défaut sont trop basses et ne se manifestent qu'in-cluster. Voir Configuration.

Un opérateur de capacité ne devient pas prêt ​

Le plus souvent un certificat de webhook manquant (cert-manager non prêt) ou un RBAC insuffisant. cert-manager est traité comme un prérequis universel et amené en premier ; confirmez qu'il est sain. Vérifiez que le RBAC d'installation étendu de l'opérateur est en place.

Un datastore reste bloqué en InfrastructureBlocked ​

Un PostgresCluster, ClickHouseCluster, RedisInstance, MongoCluster ou MeilisearchInstance géré dont les pods ne peuvent pas démarrer signale Ready=False avec la raison InfrastructureBlocked au lieu du message générique « en attente… » (le même détail remonte dans un message de composant Stack et un événement Warning). Le message nomme le pod et la cause sous-jacente, vous évitant un kubectl describe :

  • Unschedulable — le planificateur n'a pas pu placer un pod (le plus souvent Insufficient cpu/memory). La planification est par nœud : une demande qui dépasse la capacité libre d'un nœud reste Pending même si la capacité libre totale du cluster semble suffisante. Ajoutez un nœud, augmentez le maximum du node pool / la limite du cluster-autoscaler (vérifiez qu'il n'est pas en backoff de scale-up), ou réduisez les resources.requests / instances du datastore.
  • VolumeAttachFailed — un volume persistant n'a pas pu être attaché/monté (par ex. un disque managé Azure cannot find Lun quand un nœud atteint son nombre maximal de disques de données pour sa taille de VM, ou une erreur d'attachement CSI). Replanifiez le pod sur un nœud disposant d'emplacements de disque libres, ou utilisez une SKU de VM plus grande.
  • ImagePullFailed — l'image ne peut pas être tirée (registry/tag incorrect, pull secret manquant, registry injoignable). Vérifiez le miroir de registry et la configuration du pull secret.

L'opérateur continue de re-planifier (requeue) tout du long — il ne renvoie aucune erreur et n'annule rien — de sorte que la ressource se rétablit d'elle-même une fois la cause résolue au niveau du cluster.

Un opérateur de capacité ne s'installe pas — conflict with "argocd-controller": .spec.versions ​

Un datastore/workload reste Ready=False avec une erreur du type install langfuse-operator: failed to install CRD … conflict with "argocd-controller": .spec.versions. Cela se produit quand une CRD amont a été installée auparavant par une autre app GitOps depuis supprimée — l'app n'existe plus, mais ses CRDs n'ont jamais été élaguées (les CRDs ne le sont jamais), elles subsistent donc en portant la propriété de champ Server-Side-Apply périmée de cette app. Helm installe les CRDs d'un chart depuis son répertoire crds/ via un chemin qui ne force pas les conflits SSA, donc le propriétaire résiduel bloque l'installation.

L'opérateur corrige désormais cela automatiquement : avant d'installer un opérateur de capacité, il détecte un gestionnaire de champ étranger (argocd-controller, flux, …) sur ses CRDs déclarées et réinitialise cette propriété périmée (de façon non destructive — le spec et les instances ne sont pas touchés). Si vous le rencontrez sur un build d'opérateur plus ancien, nettoyez-le manuellement :

bash
# Confirmez qu'aucune app GitOps active ne gère réellement la CRD (juste un tombstone périmé) :
kubectl get crd <crd> -o jsonpath='{range .metadata.managedFields[*]}{.manager}({.operation}){"\n"}{end}'
# Réinitialisez le bookkeeping de propriété de champ (ne touche ni le spec ni les instances) :
kubectl patch crd <crd> --type=merge -p '{"metadata":{"managedFields":[{}]}}'
# Puis laissez l'opérateur réessayer (il refait la file automatiquement).

Les CRDs d'un nouveau kind ne sont pas trouvés ​

Juste après l'installation d'un chart porteur de CRD, il existe une petite course connue où le nouveau kind n'est pas encore dans le cache de discovery. L'opérateur traite un NoResourceMatchError transitoire comme un requeue et récupère automatiquement — cela devrait se résorber en une réconciliation ou deux.

Un nouveau CRD est absent après une installation kustomize ​

Lors d'une installation depuis les sources, un CRD doit être listé dans config/crd/kustomization.yaml ou kustomize l'omet silencieusement (envtest passe quand même, ce qui peut le masquer). Utilisez les overlays fournis, qui incluent tous les CRDs.

L'auto-wiring ne se produit pas ​

L'auto-wiring est sous licence. Sans la fonctionnalité auto-wiring, l'opérateur utilise vos champs manuels et émet une condition AutoWiringUnlicensed nommant exactement ce qu'il faut définir. Pour la création de clé Gateway→Langfuse, rappelez-vous qu'elle nécessite aussi un déploiement Langfuse Enterprise — voir Auto-wiring.

La suppression d'une ressource reste bloquée ​

Un finalizer exécute le nettoyage (suppression des CRs émis, désinstallation des releases possédées). Vérifiez les logs de l'opérateur ; si une dépendance référencée est elle-même bloquée, le finalizer attend. Il ne supprimera pas les ressources adoptées/externes.

Si une CRD reste bloquée en Terminating (ainsi que toute chaîne de propriétaires au-dessus — par exemple un Stack ou un ChatUI dont la suppression ne se termine jamais), recherchez une ressource personnalisée résiduelle de cette CRD qui porte encore un finalizer appartenant à un opérateur amont déjà désinstallé. Un tel finalizer est orphelin — son contrôleur n'existe plus pour le retirer —, de sorte que ni l'objet ni le finalizer apiextensions de nettoyage de la CRD au-dessus ne peuvent jamais aboutir. L'opérateur retire désormais ces finalizers automatiquement lors de la désinstallation d'un opérateur de capacité ; cela ne devrait donc plus se reproduire. Pour rétablir un cluster déjà bloqué, supprimez une fois le finalizer mort :

bash
kubectl patch <kind> <name> -n <ns> --type=merge -p '{"metadata":{"finalizers":null}}'

La connexion SSO de ChatUI échoue derrière une WAF / passerelle à terminaison TLS ​

Lorsqu'une ChatUI (LibreChat) est précédée d'un ingress à terminaison TLS ou d'une WAF externe (par ex. une Azure Application Gateway), la connexion OIDC/SSO peut échouer de trois façons distinctes et superposées — corrigez-les de l'extérieur vers l'intérieur :

  1. L'IdP rejette la redirection (AADSTS900971: No reply address provided, ou une non-correspondance de redirection). LibreChat construit son callback à partir de DOMAIN_SERVER, que l'opérateur dérive de l'hôte de la ChatUI. Définissez host et ingress.tls: true sur la ChatUI (ou le chatUI du Stack) pour que DOMAIN_SERVER devienne https://<host>, puis enregistrez https://<host>/oauth/openid/callback comme URI de redirection Web dans l'IdP.

  2. La bordure renvoie son propre 403 avant l'application (par ex. une page Microsoft-Azure-Application-Gateway/v2). Une WAF bloque le callback OIDC : les paramètres base64url code/state/id_token déclenchent les règles SQLi OWASP (942430 / 942440) comme faux positifs. Ajoutez une exclusion étroite, par règle pour ces noms d'arguments sur le chemin /oauth/* et laissez le reste de la WAF en mode Prevention. Confirmez la règle exacte à partir des journaux WAF/pare-feu avant de l'exclure.

  3. L'application affiche « Authentication failed » avec Unable to verify authorization request state dans les journaux LibreChat. Le saut à terminaison TLS fait voir à l'application du HTTP en clair ; un cookie de session Secure est donc abandonné et le state OAuth est perdu. L'opérateur définit automatiquement SESSION_COOKIE_SECURE=false dès que spec.sso est activé — c'est donc géré d'emblée. Si le problème persiste, vérifiez que le pod LibreChat en cours porte cette variable (l'opérateur gère la ConfigMap *-librechat-configenv).

Un symptôme différent — la connexion atteint l'application mais échoue avec auth_failed et registered with "local" provider — signifie qu'un compte préexistant (par ex. créé auparavant par la gestion des identités) possède déjà cette adresse e-mail sous un fournisseur non-OIDC. La suppression de la CR Identity/User correspondante démantèle désormais le compte LibreChat via un finalizer ; si un compte orphelin est antérieur, supprimez-le une fois avec le npm run delete-user <email> fourni, puis reconnectez-vous.

Obtenir une vue d'ensemble ​

bash
# All Navique resources across the cluster.
kubectl get -A \
  licenses.core.navique.com,secretsmanagements.core.navique.com,\
postgresclusters.core.navique.com,clickhouseclusters.core.navique.com,\
redisinstances.core.navique.com,mongoclusters.core.navique.com,\
meilisearchinstances.core.navique.com,gateways.core.navique.com,\
langfuses.core.navique.com,chatuis.core.navique.com

# License status (features + limits in effect).
kubectl get license cluster -o jsonpath='{.status}' | jq

Si la version de chart embarqué ou l'état de Provenance d'une ressource est en question, c'est exposé dans le status à des fins d'auditabilité — voir Provenance et cycle de vie.

Cœur open source sous AGPL-3.0. Les composants Enterprise sont propriétaires et soumis à licence.