Skip to content

Risoluzione dei problemi ​

L'operatore è progettato per essere autoesplicativo: quando qualcosa è in sospeso o non funziona, le status.conditions della risorsa e gli Event di Kubernetes indicano esattamente che cosa si sta aspettando. Inizia da lì.

Primi passi ​

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

Ogni risorsa espone una condition Ready più condition per fase (SecretsReady, OperatorsReady, DatastoreReady, WorkloadReady, …), ciascuna con un reason e un message.

Leggere le condition ​

Reason della conditionChe cosa significaChe cosa fare
SecretsNotReadyLa SecretsManagement referenziata non è prontaControlla la risorsa SecretsManagement e il relativo backend ESO/Sealed Secrets
WaitingForCRDEstablishedI CRD di un operatore di capacità non sono ancora EstablishedNormale durante l'installazione; se persiste, controlla i pod dell'operatore
DependencyNotReadyUn datastore / gateway / Langfuse referenziato non è prontoEsamina la risorsa referenziata
AutoWiringUnlicensedUn riferimento richiede l'auto-wiring, che non è in licenzaFornisci i campi manuali indicati nel messaggio, oppure applica una licenza
LicenseLimitExceededHai superato un limite di istanze previsto dalla licenzaRiduci le istanze o aumenta i limits nella licenza
BackendNotImplementedÈ stato selezionato un backend solo predisposto (zalando / cockroachdb)Usa cnpg, oppure adopt / external
InfrastructureBlockedIl pod di un datastore gestito non può avviarsi per un motivo legato all'infrastruttura del cluster che l'operatore non può risolvere attendendoLeggi il messaggio — indica il pod e la causa (non schedulabile, collegamento del volume, pull dell'immagine) — e risolvi il problema a livello di cluster

Una risorsa che rimette in coda il reconcile mentre attende è normale — l'operatore rimette in coda invece di restituire un errore per "non ancora pronto". La risorsa da analizzare è quella bloccata su Ready=False con un reason di errore.

Diagnostica dell'installazione degli operatori di capacità ​

Quando un operatore di capacità non si avvia, l'operatore ne ispeziona il namespace e riporta la causa nello status della risorsa che lo utilizza — per esempio il reason Waiting di un container, un OOM/ultima terminazione, oppure l'ultimo evento Warning come FailedMount: secret "webhook-server-cert" not found. In questo modo un'installazione upstream bloccata viene spiegata nella risorsa che ne ha bisogno.

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

Problemi comuni ​

Il manager viene terminato per OOM ​

Il motore Helm integrato nel binario esegue il rendering dei chart in-process e ha bisogno di memoria. Assegna al manager ~1Gi — i limiti predefiniti di Kubebuilder sono troppo bassi e il problema si manifesta solo nel cluster. Vedi Configurazione.

Un operatore di capacità non diventa pronto ​

Nella maggior parte dei casi si tratta di un certificato del webhook mancante (cert-manager non pronto) o di un RBAC insufficiente. cert-manager è trattato come prerequisito universale e viene garantito per primo; verifica che sia in buono stato. Controlla che l'ampio RBAC di installazione dell'operatore sia presente.

Un datastore resta bloccato in InfrastructureBlocked ​

Un PostgresCluster, ClickHouseCluster, RedisInstance, MongoCluster o MeilisearchInstance gestito i cui pod non possono avviarsi riporta Ready=False con reason InfrastructureBlocked invece del generico messaggio "in attesa…" (lo stesso dettaglio viene propagato nel messaggio del componente di uno Stack e in un evento Warning). Il messaggio della condition indica il pod e la causa sottostante, così non devi usare kubectl describe per trovarla:

  • Unschedulable — lo scheduler non è riuscito a collocare un pod (il più delle volte Insufficient cpu/memory). La schedulazione avviene per nodo: una richiesta che supera la capacità libera di ogni singolo nodo resta Pending anche quando la capacità libera totale del cluster sembra sufficiente. Aggiungi un nodo, aumenta il massimo del node pool / il limite del cluster-autoscaler (verifica che non sia in backoff di scale-up), oppure riduci resources.requests / instances del datastore.
  • VolumeAttachFailed — un volume persistente non ha potuto essere collegato/montato (ad es. un errore cannot find Lun di un Azure managed disk quando un nodo ha raggiunto il numero massimo di dischi dati per la sua dimensione di VM, oppure un errore di attach CSI). Rischedula il pod su un nodo con slot per dischi liberi, oppure usa uno SKU di VM più grande.
  • ImagePullFailed — non è possibile scaricare l'immagine (registry/tag errati, pull secret mancante, registry non raggiungibile). Verifica il mirror del registry e la configurazione dei pull secret.

L'operatore continua a rimettere in coda per tutto il tempo — non restituisce errori né esegue rollback — quindi la risorsa si ripristina da sola una volta risolta la causa a livello di cluster.

Un operatore di capacità non si installa — conflict with "argocd-controller": .spec.versions ​

Un datastore/workload resta su Ready=False con un errore come install langfuse-operator: failed to install CRD … conflict with "argocd-controller": .spec.versions. Questo accade quando un CRD upstream è stato installato in precedenza da un'altra app GitOps che nel frattempo è stata eliminata — l'app non c'è più ma i suoi CRD non sono mai stati rimossi (i CRD non lo sono mai), quindi rimangono portando con sé l'ownership dei campi Server-Side-Apply obsoleta di quell'app. Helm installa i CRD di un chart dalla sua directory crds/ tramite un percorso che non forza i conflitti SSA, quindi il proprietario rimasto blocca l'installazione.

L'operatore ora si ripara automaticamente: prima di installare qualsiasi operatore di capacità rileva un field manager estraneo (argocd-controller, flux, …) sui CRD dichiarati e ne reimposta l'ownership obsoleta (in modo non distruttivo — spec e istanze restano invariati). Se riscontri il problema con una build meno recente dell'operatore, risolvilo manualmente:

bash
# Confirm no live GitOps app actually manages the CRD (only a stale tombstone):
kubectl get crd <crd> -o jsonpath='{range .metadata.managedFields[*]}{.manager}({.operation}){"\n"}{end}'
# Reset the field-ownership bookkeeping (does not touch the spec or any instances):
kubectl patch crd <crd> --type=merge -p '{"metadata":{"managedFields":[{}]}}'
# Then let the operator retry (it requeues automatically).

I CRD di un kind appena installato non vengono trovati ​

Subito dopo l'installazione di un chart che include CRD, esiste una piccola race condition nota in cui il nuovo kind non è ancora nella cache di discovery. L'operatore tratta un NoResourceMatchError transitorio come una rimessa in coda e si ripristina automaticamente — il problema dovrebbe risolversi entro uno o due reconcile.

Un nuovo CRD manca dopo un'installazione kustomize ​

Quando installi dai sorgenti, un CRD deve essere elencato in config/crd/kustomization.yaml, altrimenti kustomize lo omette silenziosamente (envtest passa comunque, il che può nascondere il problema). Usa gli overlay forniti, che includono tutti i CRD.

L'auto-wiring non avviene ​

L'auto-wiring è soggetto a licenza. Senza la funzionalità auto-wiring, l'operatore usa i tuoi campi manuali ed emette una condition AutoWiringUnlicensed che indica esattamente cosa impostare. Per la generazione delle chiavi Gateway→Langfuse, ricorda che serve anche un deployment Langfuse Enterprise — vedi Auto-wiring.

L'eliminazione di una risorsa resta bloccata ​

Un finalizer sta eseguendo la pulizia (rimozione delle CR emesse, disinstallazione delle release possedute). Controlla i log dell'operatore; se una dipendenza referenziata è a sua volta bloccata, il finalizer attende. Non elimina le risorse adottate/esterne.

Se un CRD resta bloccato in Terminating (insieme a qualsiasi catena di proprietari al di sopra — ad es. uno Stack o una ChatUI che non termina mai l'eliminazione), cerca una custom resource residua di quel CRD che porta ancora un finalizer appartenente a un operatore upstream già disinstallato. Un finalizer di questo tipo è orfano — il suo controller non esiste più per rimuoverlo — quindi l'oggetto, e il finalizer di pulizia del CRD di apiextensions al di sopra, non possono mai completarsi. L'operatore ora rimuove automaticamente questi finalizer durante la disinstallazione degli operatori di capacità, quindi il problema non dovrebbe ripresentarsi. Per ripristinare un cluster già bloccato, rimuovi una volta il finalizer inattivo:

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

Il login SSO di ChatUI fallisce dietro un WAF / gateway con terminazione TLS ​

Quando una ChatUI (LibreChat) si trova dietro un ingress con terminazione TLS o un WAF esterno (ad es. un Azure Application Gateway), l'accesso OIDC/SSO può fallire in tre modi distinti e sovrapposti — risolvili partendo dal più esterno:

  1. L'IdP rifiuta il redirect (AADSTS900971: No reply address provided, oppure una mancata corrispondenza del redirect). LibreChat costruisce la propria callback a partire da DOMAIN_SERVER, che l'operatore ricava dall'host della ChatUI. Imposta host e ingress.tls: true sulla ChatUI (o su chatUI dello Stack) così che DOMAIN_SERVER diventi https://<host>, e registra https://<host>/oauth/openid/callback come redirect URI di tipo Web nell'IdP.

  2. L'edge restituisce un proprio 403 prima dell'app (ad es. una pagina Microsoft-Azure-Application-Gateway/v2). Un WAF sta bloccando la callback OIDC: i parametri base64url code/state/id_token attivano le regole OWASP SQLi (942430 / 942440) come falsi positivi. Aggiungi un'esclusione mirata, per singola regola, per quei nomi di argomento sul percorso /oauth/* e mantieni il resto del WAF in modalità Prevention. Prima di escludere, conferma la regola esatta dai log del WAF/firewall.

  3. L'app mostra "Authentication failed" con Unable to verify authorization request state nei log di LibreChat. Il salto con terminazione TLS fa sì che l'app veda HTTP in chiaro, quindi un cookie di sessione Secure viene scartato e lo state OAuth va perso. L'operatore imposta automaticamente SESSION_COOKIE_SECURE=false ogni volta che spec.sso è abilitato, quindi il caso è gestito di serie — se lo riscontri ancora, verifica che il pod LibreChat in esecuzione abbia quella variabile d'ambiente (l'operatore possiede la ConfigMap *-librechat-configenv).

Un sintomo diverso — il login raggiunge l'app ma fallisce con auth_failed e registered with "local" provider — indica che un account preesistente (ad es. uno creato in precedenza dalla gestione delle identità) possiede già quell'email con un provider non OIDC. L'eliminazione della CR Identity/User proprietaria ora rimuove l'account LibreChat tramite un finalizer; se un account orfano è precedente a questo comportamento, rimuovilo una volta con il comando incluso npm run delete-user <email> e accedi di nuovo.

Ottenere il quadro completo ​

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

Se la versione del chart incluso o lo stato di provenienza di una risorsa sono in dubbio, vengono esposti nello status per garantire la verificabilità — vedi Provenienza e ciclo di vita.

Nucleo open source sotto AGPL-3.0. I componenti Enterprise sono proprietari e soggetti a licenza.