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
# 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 -fChaque 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 condition | Ce que cela signifie | Que faire |
|---|---|---|
SecretsNotReady | Le SecretsManagement référencé n'est pas prêt | Vérifiez la ressource SecretsManagement et son backend ESO/Sealed Secrets |
WaitingForCRDEstablished | Les CRDs d'un opérateur de capacité ne sont pas encore Established | Normal pendant l'installation ; vérifiez les pods de l'opérateur si cela persiste |
DependencyNotReady | Un datastore / gateway / Langfuse référencé n'est pas prêt | Inspectez la ressource référencée |
AutoWiringUnlicensed | Une référence a besoin de l'auto-wiring, qui n'est pas sous licence | Fournissez les champs manuels que le message nomme, ou appliquez une licence |
LicenseLimitExceeded | Vous avez dépassé un plafond d'instances sous licence | Réduisez les instances ou augmentez les limits dans la licence |
BackendNotImplemented | Un backend en ébauche (zalando / cockroachdb) a été sélectionné | Utilisez cnpg, ou adopt / external |
InfrastructureBlocked | Un 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 attendant | Lisez 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.
# Inspect a capability operator directly.
kubectl -n cnpg-system get pods
kubectl -n cert-manager get pods,events --sort-by=.lastTimestampProblè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 restePendingmê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 lesresources.requests/instancesdu datastore. - VolumeAttachFailed — un volume persistant n'a pas pu être attaché/monté (par ex. un disque managé Azure
cannot find Lunquand 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 :
# 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 :
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 :
L'IdP rejette la redirection (
AADSTS900971: No reply address provided, ou une non-correspondance de redirection). LibreChat construit son callback à partir deDOMAIN_SERVER, que l'opérateur dérive de l'hôte de la ChatUI. Définissezhostetingress.tls: truesur laChatUI(ou lechatUIdu Stack) pour queDOMAIN_SERVERdeviennehttps://<host>, puis enregistrezhttps://<host>/oauth/openid/callbackcomme URI de redirection Web dans l'IdP.La bordure renvoie son propre
403avant l'application (par ex. une pageMicrosoft-Azure-Application-Gateway/v2). Une WAF bloque le callback OIDC : les paramètres base64urlcode/state/id_tokendé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.L'application affiche « Authentication failed » avec
Unable to verify authorization request statedans les journaux LibreChat. Le saut à terminaison TLS fait voir à l'application du HTTP en clair ; un cookie de sessionSecureest donc abandonné et lestateOAuth est perdu. L'opérateur définit automatiquementSESSION_COOKIE_SECURE=falsedès quespec.ssoest 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
# 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}' | jqSi 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.