Skip to content

PlatformConfig ​

Ambito: cluster · Singleton (nome cluster)

PlatformConfig configura l'operatore stesso — il modo in cui distribuisce e gestisce la piattaforma. Oggi configura il container registry: fa puntare ogni immagine distribuita dall'operatore a un registry personalizzato (ad es. un mirror air-gapped), con le credenziali di pull, in un unico punto.

yaml
apiVersion: core.navique.com/v1alpha1
kind: PlatformConfig
metadata:
  name: cluster            # singleton — only "cluster" is honoured
spec:
  registry:
    # Mirror host, optionally with a path prefix.
    host: registry.example.com/mirror
    auth:
      secretRef:
        name: registry-pull-secret      # a kubernetes.io/dockerconfigjson Secret
        namespace: navique-system       # defaults to the operator system namespace

Cosa copre ​

Quando spec.registry.host è impostato, l'operatore applica il mirroring dell'host a ogni immagine che distribuisce — sostituisce l'host del registry preservando percorso e tag dell'immagine, così ghcr.io/cloudnative-pg/cloudnative-pg:1.29 diventa registry.example.com/mirror/cloudnative-pg/cloudnative-pg:1.29. Questo vale per:

  • Gli operatori di capacità inclusi — CloudNativePG, cert-manager, External Secrets, Sealed Secrets, gli operatori ClickHouse e Redis, MongoDB (MCK), gli operatori LiteLLM e Langfuse, Meilisearch, Sail/Istio. I valori delle immagini di ciascun chart vengono riscritti verso il mirror.
  • Le istanze di datastore e workload gestite dagli operatori — Redis, LiteLLM (gateway + job di migrazione), Langfuse (web + worker), LibreChat, Meilisearch, il control plane di Istio (istiod / ztunnel / CNI).
  • La console del management plane — il suo unico override del registry (non ha un'impostazione separata).

Il pull Secret referenziato da spec.registry.auth.secretRef viene propagato: l'operatore lo copia in ogni namespace in cui distribuisce (i namespace di sistema degli operatori di capacità e ogni namespace dei workload) e lo collega come imagePullSecrets sui chart, sui CR di istanza emessi e sui pod gestiti dall'operatore.

Cosa NON copre ​

  • L'immagine dell'operatore stesso. L'operatore è già in esecuzione, quindi non può usare un CR per decidere da dove scaricare sé stesso. Impostala in fase di installazione tramite l'Helm chart dell'operatore — image.repository e imagePullSecrets — che è anche il punto in cui fornire il registry di bootstrap per un'installazione air-gapped.
  • Le immagini operand di CloudNativePG e ClickHouse (le immagini server PostgreSQL / ClickHouse che l'operatore upstream seleziona autonomamente) ricevono il pull Secret ma mantengono il riferimento all'immagine predefinito dell'operatore — non esiste un tag stabile da fissare nuovamente in sicurezza. Replica queste immagini nel mirror allo stesso percorso di repository; il pull Secret consente ai pod delle istanze di autenticarsi presso il mirror.
  • Un paio di immagini init busybox interne ai chart Meilisearch / LibreChat non sono esposte come valori e non vengono riscritte.

Per un'installazione GitOps o air-gapped, precompila la PlatformConfig con l'Helm chart dell'operatore, così che già la prima installazione di un operatore di capacità avvenga tramite mirror:

bash
helm install navique deploy/helm \
  --set image.repository=registry.example.com/mirror/scigility/navique-ai-core-operator \
  --set imagePullSecrets[0].name=registry-pull-secret \
  --set registry.host=registry.example.com/mirror \
  --set registry.pullSecret.name=registry-pull-secret

È possibile impostare anche registry.pullSecret.dockerConfigJson per far creare il Secret al chart; in caso contrario deve già esistere nel namespace di sistema.

Valori predefiniti a livello di operatore ​

Oltre al registry, spec.defaults e spec.lifecycle configurano il modo in cui l'operatore distribuisce e gestisce tutto. La spec di un componente sovrascrive sempre il valore predefinito corrispondente.

yaml
spec:
  defaults:
    clusterDomain: cluster.local        # custom cluster DNS domain (computed service URLs)
    storageClass: fast-ssd              # default for managed-datastore PVCs
    commonLabels: { team: platform }    # stamped on every operator-created object
    commonAnnotations: { owner: ai }
    proxy:                              # injected as HTTP(S)_PROXY / NO_PROXY env
      httpProxy: http://proxy:3128
      httpsProxy: http://proxy:3128
      noProxy: .svc,.cluster.local,10.0.0.0/8
    scheduling:                        # default pod placement
      nodeSelector: { workload: platform }
      tolerations: [{ key: platform, operator: Exists }]
      priorityClassName: system-cluster-critical
    securityContext: { runAsNonRoot: true, seccompProfile: { type: RuntimeDefault } }
    imagePullPolicy: IfNotPresent
  registry:
    operandImages:                     # pin operator-chosen operand images (host-mirrored)
      postgres: ghcr.io/cloudnative-pg/postgresql:17.2
      clickhouse: clickhouse/clickhouse-server:25.3
  lifecycle:
    pauseUpgrades: false               # stop version-driven capability-operator re-applies
    retainOnUninstall: false           # keep a shared operator's release when its last consumer is removed
    maintenanceUntil: "2026-07-01T02:00:00Z"   # pause capability-operator upgrades until this time, then auto-resume
  runtime:
    logLevel: info                     # debug|info|warn|error — changes the operator's verbosity LIVE

Come vengono applicati. clusterDomain, storageClass, commonLabels/Annotations e operandImages vengono applicati direttamente alle risorse emesse dall'operatore. I valori predefiniti a livello di pod — proxy, scheduling, securityContext, imagePullPolicy e le label/annotation comuni — vengono applicati a ogni oggetto renderizzato dai chart inclusi tramite un unico post-renderer Helm, così raggiungono in modo uniforme gli operatori di capacità e i chart dei workload senza configurazione per singolo chart.

scheduling raggiunge ogni pod della piattaforma, non solo quelli renderizzati dai chart. La maggior parte dei pod applicativi (il gateway LiteLLM, Langfuse e i datastore) viene creata dagli operatori upstream a partire dai CR emessi da questo operatore — il post-renderer Helm non li vede mai. Per questo scheduling (nodeSelector / tolerations / affinity / priorityClassName) viene inoltre tradotto nello schema di posizionamento proprio di ciascun CR emesso: il blocco spec.affinity di CloudNativePG, lo spec.podTemplate di ClickHouse/Keeper, lo spec di OT-Redis, i componenti web/worker di Langfuse, l'overlay dello StatefulSet MongoDB e il blocco spec.podScheduling di LiteLLM — più i Deployment costruiti direttamente dall'operatore (management plane, guardrail proxy) e i CronJob di backup. Ogni campo viene impostato solo quando il workload non ne definisce già uno proprio, quindi un valore esplicito prevale. Un valore predefinito già impostato dal workload ha sempre la precedenza.

Un'avvertenza sul posizionamento: priorityClassName. Due CRD upstream non modellano questo campo, quindi quel singolo valore predefinito viene saltato per loro mentre nodeSelector/tolerations/affinity vengono applicati normalmente — Langfuse e il gateway LiteLLM (il cui spec.podScheduling copre gli altri tre). Il Gateway genera un evento di avviso PlacementUnsupported che nomina priorityClassName quando è impostato, invece di scrivere un campo che l'API server eliminerebbe.

Il posizionamento di LiteLLM richiede litellm-operator 0.24.0+

spec.podScheduling è stato aggiunto upstream in litellm-operator 0.24.0 (incluso dalla release 0.21.0 dell'operatore). Si applica sia al Deployment del proxy sia al Job di migrazione del database, così una migrazione non può mai essere schedulata dove il proxy non può essere eseguito. Su un litellm-operator più vecchio, installato dall'utente e adottato dalla piattaforma, il campo viene eliminato e il gateway mantiene il posizionamento predefinito.

proxy non è il registry. Un registry privato (Artifactory, Harbor, …) si configura tramite spec.registry.host + auth — è il meccanismo air-gap per le immagini. spec.defaults.proxy inietta le variabili d'ambiente standard in uscita HTTP_PROXY/HTTPS_PROXY/NO_PROXY per i cluster con egress limitato in cui i workload raggiungono servizi esterni (ad es. un'API LLM esterna) attraverso un forward proxy aziendale. HTTP_PROXY e HTTPS_PROXY selezionano il proxy in base allo schema dell'URL di destinazione (di solito con lo stesso valore) — non sono due registry. Lascia proxy non impostato sui cluster completamente air-gapped privi di egress.

lifecycle.maintenanceUntil è una finestra di manutenzione: finché l'ora corrente è antecedente, gli upgrade/re-apply degli operatori di capacità guidati dalla versione sono sospesi (equivalente a pauseUpgrades), poi riprendono automaticamente una volta trascorsa la finestra (l'operatore riaccoda alla scadenza). Una release non sana viene comunque riapplicata, così nulla resta guasto.

runtime.logLevel modifica la verbosità dei log dell'operatore a caldo (senza riavvio) al reconcile successivo. L'immagine dell'operatore stesso resta un aspetto di installazione impostato tramite l'Helm chart dell'operatore (image.repository / imagePullSecrets), non tramite questo CR — l'operatore è già in esecuzione quando legge PlatformConfig. L'operatore non emette alcuna telemetria di utilizzo, quindi non c'è nulla da disattivare.

Namespace di installazione degli operatori ​

Di default l'operatore installa ciascun operatore di capacità incluso nel proprio namespace dedicato (cnpg-system, litellm-system, cert-manager, external-secrets, sealed-secrets, langfuse-system, redis-system, mongodb-system, clickhouse-system, sail-operator). spec.operators consente di cambiare dove vengono collocati — più comunemente per consolidare tutti gli operatori di capacità in un unico namespace.

yaml
spec:
  operators:
    namespace: navique-operators       # install ALL capability operators here
    namespaces:                        # optional per-operator overrides (win over `namespace`)
      cloudnative-pg: data-system

Risoluzione (per operatore). Una voce per operatore in namespaces prevale → altrimenti lo spec.operators.namespace condiviso → altrimenti il namespace predefinito integrato dell'operatore. Lasciare spec.operators del tutto non impostato preserva il comportamento attuale: ogni operatore nel proprio namespace dedicato.

Chiavi di operatore valide per la mappa namespaces:

ChiaveNamespace predefinito
external-secretsexternal-secrets
sealed-secretssealed-secrets
cloudnative-pgcnpg-system
cert-managercert-manager
litellm-operatorlitellm-system
langfuse-operatorlangfuse-system
redis-operatorredis-system
mongodb-kubernetesmongodb-system
clickhouse-operatorclickhouse-system
sail-operatorsail-operator

Il namespace scelto viene creato se non esiste alla prima installazione dell'operatore.

Nota — spec.operators viene applicato in fase di installazione. Modificarlo dopo che un operatore di capacità è già installato non migra la release esistente nel nuovo namespace; per spostarlo l'operatore deve essere rimosso e ridistribuito.

Footprint del catalogo MCP incluso ​

spec.mcp regola la release del catalogo MCP incluso condivisa a livello di cluster (vedi MCPServer). Poiché un server del catalogo (ad es. la ricerca web) viene distribuito come un'unica release condivisa con conteggio dei riferimenti per l'intero cluster, il suo footprint si imposta qui anziché per singola ChatUI.

CampoDescrizione
footprintfull (SearXNG + Presidio + Playwright; predefinito) oppure minimal (solo ricerca — PII/rendering JS disattivati)
valuesOverlay libero di valori Helm unito nella release condivisa del catalogo

Come per spec.operators, una modifica del footprint non migra una release già distribuita.

Routing — Ingress o Gateway API ​

spec.routing seleziona come viene esposto l'ingress dei workload: Ingress classico (predefinito) oppure la Gateway API (HTTPRoute).

yaml
spec:
  routing:
    mode: Gateway                      # Ingress (default) | Gateway
    gatewayClassName: istio            # required for standalone; default "istio" under a mesh
    gateway:
      mode: managed                    # managed (operator owns it) | adopt | external
      name: navique
      namespace: navique-system
      clusterIssuer: letsencrypt-prod  # cert-manager gateway-shim for HTTPS listeners

Quando viene usata la modalità Gateway (risolta per workload): prevale lo spec.ingress.api del workload (Gateway/Ingress), altrimenti routing.mode == Gateway, altrimenti una ServiceMesh attiva (Istio è un'implementazione della Gateway API, quindi abilitare la mesh cambia automaticamente il routing). Il predefinito è Ingress — nessun cambiamento di comportamento finché non si sceglie esplicitamente.

Cosa fa l'operatore in modalità Gateway: sopprime l'Ingress upstream del workload ed emette una HTTPRoute (hostnames=[il tuo host], backend = il Service del workload) collegata a un Gateway condiviso che gestisce nel namespace di sistema — un listener HTTP per tutti i workload, più un listener HTTPS per host (gateway-shim di cert-manager, mode: Terminate) quando un workload imposta ingress.tls ed è configurato un clusterIssuer. La console del management plane, che non ha un Ingress classico, ottiene così finalmente un vero routing.

Un workload può forzare l'Ingress classico anche sotto una mesh con la propria via di fuga:

yaml
# on a Gateway / Langfuse / ChatUI / ManagementPlane
spec:
  ingress:
    enabled: true
    host: legacy.example.com
    api: Ingress        # override: keep classic Ingress for this workload

La modalità Gateway richiede che siano installati i CRD della Gateway API (gateway.networking.k8s.io) — li installa la ServiceMesh (Sail/Istio), oppure un controller standalone (Envoy Gateway, NGINX Gateway Fabric); l'operatore ne subordina il funzionamento alla loro presenza e, se mancano, riporta uno stato di attesa. Le annotation di basic-auth dell'ingress non hanno un equivalente nella Gateway API e non vengono trasferite (usa una AuthorizationPolicy della mesh).

Adottare un Gateway esistente (non crearne un secondo) ​

Se il tuo cluster ha già un Gateway per la stessa gatewayClassName — ad esempio uno creato con Terraform o Helm verso cui un load balancer esterno (Azure Application Gateway, un ALB, …) instrada già il traffico — devi indicare all'operatore di usarlo tramite routing.gateway:

yaml
spec:
  routing:
    mode: Gateway
    gatewayClassName: nginx
    gateway:
      mode: external          # reference it; the operator never modifies it (use "adopt" to manage labels)
      name: nginx-gateway
      namespace: nginx-gateway

Se lasci routing.gateway non impostato, l'operatore ripiega sulla creazione di un proprio Gateway di sua proprietà (navique nel namespace di sistema). Quando esiste già un altro Gateway per la stessa classe, quel secondo Gateway avvia un LoadBalancer di data plane parallelo che entra in conflitto con quello esistente sul load balancer interno del cloud (ad es. entrambi reclamano la porta 80), per cui il nuovo LoadBalancer non ottiene mai un indirizzo e il tuo proxy esterno continua a instradare verso un Gateway che ora non ha route — un 502 su tutta la piattaforma. Per evitarlo, l'operatore si rifiuta di creare un duplicato: lascia il workload in Pending con uno stato/evento InfrastructureBlocked che nomina il Gateway esistente e chiede di impostare routing.gateway. Impostarlo (come sopra) risolve il blocco.

L'operatore segnala inoltre un Gateway gestito il cui LoadBalancer di data plane è bloccato senza indirizzo (ad es. un SyncLoadBalancerFailed del cloud): il workload riporta InfrastructureBlocked con il dettaglio sottostante invece di apparire sano nel cluster pur essendo irraggiungibile dall'esterno.

Stratificazione e precedenza ​

  1. In fase di installazione (Helm/flag): l'immagine dell'operatore stesso + il suo pull Secret.
  2. A runtime (questo CR): tutto ciò che l'operatore distribuisce a valle.
  3. Per componente: un Gateway/Observability può comunque impostare il proprio spec.image.repository; un valore esplicito viene sottoposto a mirroring dell'host, non sostituito.

La modifica del registry dopo la distribuzione della piattaforma ha effetto man mano che ciascun componente esegue il reconcile successivo. La rimozione della PlatformConfig interrompe la riscrittura (le immagini tornano ai rispettivi registry upstream al reconcile successivo).

Stato ​

CampoSignificato
status.activeLa riscrittura con mirroring dell'host è attiva.
status.registryL'host del mirror attivo.
status.pullSecretIl pull Secret di origine risolto (namespace/name).
status.propagatedNamespacesNamespace in cui è stato copiato il pull Secret.

Una PlatformConfig con un nome diverso da cluster viene rifiutata con una condition NotSingleton e ignorata.

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