PlatformConfig
Geltungsbereich: clusterweit · Singleton (Name cluster)
PlatformConfig konfiguriert den Operator selbst — wie er die Plattform bereitstellt und verwaltet. Aktuell konfiguriert er die Container-Registry: Jedes vom Operator bereitgestellte Image lässt sich an einer Stelle auf eine eigene Registry (z. B. einen Air-Gap-Mirror) umleiten, samt Pull-Zugangsdaten.
apiVersion: core.navique.com/v1alpha1
kind: PlatformConfig
metadata:
name: cluster # Singleton — nur "cluster" wird berücksichtigt
spec:
registry:
# Mirror-Host, optional mit Pfadpräfix.
host: registry.example.com/mirror
auth:
secretRef:
name: registry-pull-secret # ein kubernetes.io/dockerconfigjson-Secret
namespace: navique-system # Standard: System-Namespace des OperatorsWas abgedeckt wird
Ist spec.registry.host gesetzt, spiegelt der Operator jedes bereitgestellte Image am Host: Er tauscht den Registry-Host aus und behält Image-Pfad und Tag bei, sodass aus ghcr.io/cloudnative-pg/cloudnative-pg:1.29 die Referenz registry.example.com/mirror/cloudnative-pg/cloudnative-pg:1.29 wird. Das gilt für:
- Die gebündelten Capability-Operatoren — CloudNativePG, cert-manager, External Secrets, Sealed Secrets, die ClickHouse- und Redis-Operatoren, MongoDB (MCK), die LiteLLM- und Langfuse-Operatoren, Meilisearch, Sail/Istio. Die Image-Werte jedes Charts werden auf den Mirror umgeschrieben.
- Die Datastore- und Workload-Instanzen, die die Operatoren verwalten — Redis, LiteLLM (Gateway + Migrations-Job), Langfuse (Web + Worker), LibreChat, Meilisearch, die Istio-Control-Plane (istiod / ztunnel / CNI).
- Die Management-Plane-Konsole — ihre einzige Möglichkeit zur Registry-Umleitung (sie hat keine eigene Einstellung).
Das in spec.registry.auth.secretRef referenzierte Pull-Secret wird propagiert: Der Operator kopiert es in jeden Namespace, in den er bereitstellt (die System-Namespaces der Capability-Operatoren und jeden Workload-Namespace), und trägt es als imagePullSecrets in die Charts, die erzeugten Instanz-CRs und die vom Operator verwalteten Pods ein.
Was NICHT abgedeckt wird
- Das eigene Image des Operators. Der Operator läuft bereits und kann nicht per CR entscheiden, woher er sich selbst zieht. Setzen Sie das zur Installationszeit über das Operator-Helm-Chart —
image.repositoryundimagePullSecrets—, das auch die Bootstrap-Registry für eine Air-Gap-Installation liefert. - CloudNativePG- und ClickHouse-Operand-Images (die PostgreSQL- bzw. ClickHouse-Server-Images, die der Upstream-Operator selbst wählt) erhalten das Pull-Secret, behalten aber die Standard-Image-Referenz des Operators — es gibt kein stabiles Tag, das sich von hier aus sicher neu setzen ließe. Spiegeln Sie diese unter demselben Repository-Pfad; das Pull-Secret ermöglicht den Instanz-Pods die Authentifizierung am Mirror.
- Einige tief eingebettete
busybox-Init-Images in den Meilisearch-/ LibreChat-Charts sind nicht als Werte verfügbar und werden nicht umgeschrieben.
Seeding zur Installationszeit (empfohlen)
Für eine GitOps- oder Air-Gap-Installation sollte die PlatformConfig mit dem Operator-Helm-Chart geseedet werden, damit bereits die allererste Capability-Operator-Installation gespiegelt erfolgt:
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-secretregistry.pullSecret.dockerConfigJson kann zusätzlich gesetzt werden, damit das Chart das Secret erzeugt; andernfalls muss es bereits im System-Namespace existieren.
Operatorweite Standardwerte
Über die Registry hinaus konfigurieren spec.defaults und spec.lifecycle, wie der Operator alles bereitstellt und verwaltet. Die eigene Spezifikation einer Komponente überschreibt stets den passenden Standardwert.
spec:
defaults:
clusterDomain: cluster.local # eigene Cluster-DNS-Domain (berechnete Service-URLs)
storageClass: fast-ssd # Standard für PVCs verwalteter Datastores
commonLabels: { team: platform } # auf jedes vom Operator erstellte Objekt geprägt
commonAnnotations: { owner: ai }
proxy: # als HTTP(S)_PROXY / NO_PROXY injiziert
httpProxy: http://proxy:3128
httpsProxy: http://proxy:3128
noProxy: .svc,.cluster.local,10.0.0.0/8
scheduling: # Standard-Pod-Platzierung
nodeSelector: { workload: platform }
tolerations: [{ key: platform, operator: Exists }]
priorityClassName: system-cluster-critical
securityContext: { runAsNonRoot: true, seccompProfile: { type: RuntimeDefault } }
imagePullPolicy: IfNotPresent
registry:
operandImages: # vom Operator gewählte Operand-Images pinnen (gespiegelt)
postgres: ghcr.io/cloudnative-pg/postgresql:17.2
clickhouse: clickhouse/clickhouse-server:25.3
lifecycle:
pauseUpgrades: false # versionsgetriebene Re-Applies der Capability-Operatoren stoppen
retainOnUninstall: false # Release eines geteilten Operators behalten, wenn der letzte Verbraucher entfernt wird
maintenanceUntil: "2026-07-01T02:00:00Z" # Capability-Operator-Upgrades bis zu diesem Zeitpunkt pausieren, dann automatisch fortsetzen
runtime:
logLevel: info # debug|info|warn|error — ändert die Ausführlichkeit LIVEWie sie angewendet werden. clusterDomain, storageClass, commonLabels/Annotations und operandImages werden direkt auf die vom Operator erzeugten Ressourcen angewendet. Die Pod-Ebenen-Standardwerte — proxy, scheduling, securityContext, imagePullPolicy sowie die gemeinsamen Labels/ Annotationen — werden über einen einzigen Helm-Post-Renderer auf jedes von den gebündelten Charts gerenderte Objekt angewendet, sodass sie die Capability-Operatoren und die Workload-Charts einheitlich erreichen — ohne Konfiguration pro Chart.
scheduling erreicht jeden Plattform-Pod, nicht nur die aus Charts gerenderten. Die meisten Anwendungs-Pods (das LiteLLM-Gateway, Langfuse und die Datastores) werden von Upstream-Operatoren aus den CRs erzeugt, die dieser Operator ausgibt — der Helm-Post-Renderer sieht sie nie. Deshalb wird scheduling (nodeSelector / tolerations / affinity / priorityClassName) zusätzlich in das jeweilige Platzierungs-Schema jedes ausgegebenen CR übersetzt: den spec.affinity-Block von CloudNativePG, das spec.podTemplate von ClickHouse/Keeper, das spec von OT-Redis, die Komponenten web/worker von Langfuse, das StatefulSet-Overlay von MongoDB und der spec.podScheduling-Block von LiteLLM — dazu die selbst erstellten Deployments des Operators (Management-Plane, Guardrail-Proxy) und die Backup-CronJobs. Jedes Feld wird nur gesetzt, wenn der Workload es nicht bereits selbst definiert; ein expliziter Wert gewinnt also.
Eine Platzierungs-Einschränkung: priorityClassName. Zwei Upstream-CRDs modellieren dieses Feld nicht, daher wird dieser eine Standardwert für sie übersprungen, während nodeSelector/tolerations/affinity normal angewendet werden — Langfuse und das LiteLLM-Gateway (dessen spec.podScheduling die übrigen drei abdeckt). Das Gateway löst ein PlacementUnsupported-Warn-Event aus, das priorityClassName benennt, statt ein Feld zu schreiben, das der API-Server ohnehin entfernen würde.
LiteLLM-Platzierung erfordert litellm-operator 0.24.0+
spec.podScheduling kam upstream in litellm-operator 0.24.0 hinzu (seit Operator-Release 0.21.0 mitgeliefert). Es gilt sowohl für das Proxy-Deployment als auch für den Datenbank-Migrations-Job, sodass eine Migration nie dort eingeplant werden kann, wo der Proxy nicht laufen darf. Bei einem älteren, selbst installierten und von der Plattform adoptierten litellm-operator wird das Feld entfernt und das Gateway behält die Standardplatzierung.
proxy ist nicht die Registry. Eine private Registry (Artifactory, Harbor, …) wird über spec.registry.host + auth konfiguriert — das ist der Air-Gap- Image-Mechanismus. spec.defaults.proxy injiziert die Standard- HTTP_PROXY/HTTPS_PROXY/NO_PROXY-Variablen für Cluster mit eingeschränktem Egress, in denen Workloads externe Dienste (z. B. eine externe LLM-API) über einen Unternehmens-Forward-Proxy erreichen. HTTP_PROXY vs. HTTPS_PROXY wählen den Proxy nach dem Schema der Ziel-URL (üblicherweise derselbe Proxy-Wert) — es sind keine zwei Registries. Auf vollständig air-gapped Clustern ohne Egress proxy weglassen.
lifecycle.maintenanceUntil ist ein Wartungsfenster: Solange die aktuelle Zeit davor liegt, werden versionsgetriebene Capability-Operator-Upgrades/Re-Applies pausiert (entspricht pauseUpgrades) und nach Ablauf automatisch fortgesetzt (der Operator stellt zum Stichtag erneut in die Queue). Ein fehlerhaftes Release wird weiterhin neu angewendet, damit nichts kaputt bleibt.
runtime.logLevel ändert die Log-Ausführlichkeit des Operators live (ohne Neustart) beim nächsten Reconcile. Das eigene Image des Operators bleibt ein Installationszeit-Belang über das Operator-Helm-Chart (image.repository / imagePullSecrets), nicht über diese CR. Der Operator sendet keine Nutzungs- Telemetrie, daher gibt es nichts abzuwählen.
Installations-Namespaces der Operatoren
Standardmäßig installiert der Operator jeden gebündelten Capability-Operator in seinen eigenen, dedizierten Namespace (cnpg-system, litellm-system, cert-manager, external-secrets, sealed-secrets, langfuse-system, redis-system, mongodb-system, clickhouse-system, sail-operator). Mit spec.operators lässt sich steuern, wohin sie installiert werden — am häufigsten, um alle Capability-Operatoren in einem einzigen Namespace zusammenzufassen.
spec:
operators:
namespace: navique-operators # ALLE Capability-Operatoren hier installieren
namespaces: # optionale Overrides pro Operator (haben Vorrang vor `namespace`)
cloudnative-pg: data-systemAuflösung (pro Operator). Ein Eintrag pro Operator in namespaces gewinnt → sonst der gemeinsame spec.operators.namespace → sonst der eingebaute Standard-Namespace des Operators. Bleibt spec.operators vollständig unausgefüllt, gilt das heutige Verhalten weiter: jeder Operator in seinem eigenen, dedizierten Namespace.
Gültige Operator-Schlüssel für die namespaces-Map:
| Schlüssel | Standard-Namespace |
|---|---|
external-secrets | external-secrets |
sealed-secrets | sealed-secrets |
cloudnative-pg | cnpg-system |
cert-manager | cert-manager |
litellm-operator | litellm-system |
langfuse-operator | langfuse-system |
redis-operator | redis-system |
mongodb-kubernetes | mongodb-system |
clickhouse-operator | clickhouse-system |
sail-operator | sail-operator |
Der gewählte Namespace wird angelegt, falls er nicht existiert, wenn der Operator erstmals installiert wird.
Hinweis —
spec.operatorswird zur Installationszeit angewendet. Eine Änderung, nachdem ein Capability-Operator bereits installiert ist, migriert das vorhandene Release nicht in den neuen Namespace; der Operator muss abgebaut und neu bereitgestellt werden, um ihn zu verschieben.
Umfang des gebündelten MCP-Katalogs
spec.mcp konfiguriert das clusterweit geteilte gebündelte MCP-Katalog-Release (siehe MCPServer). Da ein Katalogserver (z. B. Websuche) als ein gemeinsames, referenzgezähltes Release für den gesamten Cluster bereitgestellt wird, wird sein Umfang hier festgelegt — nicht pro ChatUI.
| Feld | Beschreibung |
|---|---|
footprint | full (SearXNG + Presidio + Playwright; Standard) oder minimal (nur Suche — PII/JS-Rendering aus) |
values | Frei wählbares Helm-Values-Overlay, das in das gemeinsame Katalog-Release eingemischt wird |
Wie bei spec.operators migriert eine Umfangsänderung ein bereits bereitgestelltes Release nicht.
Routing — Ingress oder Gateway API
spec.routing wählt, wie der Workload-Ingress bereitgestellt wird: klassischer Ingress (Standard) oder die Gateway API (HTTPRoutes).
spec:
routing:
mode: Gateway # Ingress (Standard) | Gateway
gatewayClassName: istio # für Standalone erforderlich; Standard "istio" mit Mesh
gateway:
mode: managed # managed (Operator besitzt ihn) | adopt | external
name: navique
namespace: navique-system
clusterIssuer: letsencrypt-prod # cert-manager-Gateway-Shim für HTTPS-ListenerWann Gateway-Modus gilt (pro Workload aufgelöst): das workload-eigene spec.ingress.api gewinnt (Gateway/Ingress), sonst routing.mode == Gateway, sonst ein aktives ServiceMesh (Istio ist eine Gateway-API-Implementierung, das Aktivieren des Mesh schaltet das Routing also automatisch um). Der Standard ist Ingress — keine Verhaltensänderung, bis Sie aktiv zustimmen.
Was der Operator im Gateway-Modus tut: Er unterdrückt den Upstream-Ingress des Workloads und erzeugt eine HTTPRoute (hostnames=[Ihr Host], Backend = der Workload-Service), angebunden an ein vom Operator verwaltetes gemeinsames Gateway im System-Namespace — ein HTTP-Listener für alle Workloads, plus einen Host-spezifischen HTTPS-Listener (cert-manager-Gateway-Shim, mode: Terminate), wenn ein Workload ingress.tls setzt und ein clusterIssuer konfiguriert ist. Die Management-Plane-Konsole, die keinen klassischen Ingress hat, erhält so endlich echtes Routing.
Ein Workload erzwingt auch unter einem Mesh klassischen Ingress über seinen eigenen Ausweg:
# auf einem Gateway / Langfuse / ChatUI / ManagementPlane
spec:
ingress:
enabled: true
host: legacy.example.com
api: Ingress # Override: klassischen Ingress für diesen Workload behaltenDer Gateway-Modus erfordert die Gateway-API-CRDs (gateway.networking.k8s.io) — das ServiceMesh (Sail/Istio) installiert sie, oder ein Standalone-Controller (Envoy Gateway, NGINX Gateway Fabric); der Operator prüft darauf und meldet einen Wartestatus, wenn sie fehlen. Basic-Auth-Ingress- Annotationen haben kein Gateway-API-Äquivalent und werden nicht übernommen (stattdessen eine Mesh-AuthorizationPolicy).
Ein vorhandenes Gateway übernehmen (kein zweites anlegen)
Wenn Ihr Cluster bereits ein Gateway für denselben gatewayClassName besitzt — etwa eines, das per Terraform oder Helm bereitgestellt wurde und an das ein externer Load Balancer (Azure Application Gateway, ein ALB, …) bereits routet —, müssen Sie dem Operator über routing.gateway mitteilen, dieses zu verwenden:
spec:
routing:
mode: Gateway
gatewayClassName: nginx
gateway:
mode: external # referenzieren; der Operator ändert es nie (mit "adopt" verwaltet er Labels)
name: nginx-gateway
namespace: nginx-gatewayLassen Sie routing.gateway unausgefüllt, legt der Operator ersatzweise ein eigenes Gateway an und besitzt es (navique im System-Namespace). Existiert bereits ein anderes Gateway derselben Klasse, startet dieses zweite Gateway einen parallelen Data-Plane-LoadBalancer, der mit dem vorhandenen auf dem internen Load Balancer der Cloud kollidiert (z. B. beanspruchen beide Port 80); der neue LoadBalancer erhält daher nie eine Adresse, und Ihr externer Proxy routet weiter zu einem Gateway, das nun keine Routen mehr hat — ein plattformweites 502. Um das zu verhindern, weigert sich der Operator, ein Duplikat anzulegen: Er belässt den Workload auf Pending mit einem InfrastructureBlocked-Status/-Event, das das vorhandene Gateway benennt und Sie auffordert, routing.gateway zu setzen. Das Setzen (wie oben) löst die Blockade auf.
Der Operator macht außerdem ein verwaltetes Gateway sichtbar, dessen Data-Plane- LoadBalancer keine Adresse erhält (z. B. ein Cloud-SyncLoadBalancerFailed): Der Workload meldet InfrastructureBlocked mit dem zugrunde liegenden Detail, statt im Cluster gesund zu wirken, während er von außen nicht erreichbar ist.
Schichtung & Vorrang
- Installationszeit (Helm/Flags): das eigene Image des Operators + dessen Pull-Secret.
- Laufzeit (diese CR): alles, was der Operator nachgelagert bereitstellt.
- Pro Komponente: ein
Gateway/Observabilitydarf weiterhin eine eigenespec.image.repositorysetzen; ein expliziter Wert wird am Host gespiegelt, nicht ersetzt.
Eine Änderung der Registry nach der Bereitstellung der Plattform wird wirksam, sobald die jeweilige Komponente als Nächstes abgeglichen wird. Das Entfernen der PlatformConfig beendet das Umschreiben (Images kehren beim nächsten Abgleich zu ihren Upstream-Registries zurück).
Status
| Feld | Bedeutung |
|---|---|
status.active | Host-Mirror-Umschreibung ist aktiv. |
status.registry | Der aktive Mirror-Host. |
status.pullSecret | Das aufgelöste Quell-Pull-Secret (namespace/name). |
status.propagatedNamespaces | Namespaces, in die das Pull-Secret kopiert wurde. |
Eine PlatformConfig mit einem anderen Namen als cluster wird mit der Bedingung NotSingleton abgelehnt und ignoriert.