Alle Rezepte
OpenShift 4.18+ · OLM v0 · Veeam Kasten · Kyverno

OLM-Operatoren:
Resources pro Container anpassen

Die Subscription kann Resources überschreiben – aber nur für alle Container im Operator-Pod gleichzeitig. Wer nur einen Container ändern will, muss an die CSV. Neun Abschnitte vom OLM-Grundaufbau bis zur Kyverno-Policy, die den Wert auch über Upgrades hinweg hält.

0Das Problem800m, 10m, beide 400m 1OLM im ÜberblickObjekte und Ablauf 2Die CSVOriginal und Kopie 3SubscriptionWarum sie nicht reicht 4CSV patchenEinmalige Lösung 5Operator vs. ServicesCSV oder K10-CR 6Kyverno-PolicyDauerhafte Lösung 7AlternativenFünf Varianten im Vergleich 8KurzfassungFünf Sätze
0

Das Problem: ein Wert für zwei Container

Ein über den OperatorHub installierter Operator läuft als Pod, oft mit zwei Containern: manager für die eigentliche Operator-Logik und kube-rbac-proxy als Sidecar, der den Metrics-Endpunkt schützt.

Der konkrete Fall

  • Pod k10-kasten-operator-…-controller-manager-… hat zwei Container
  • Container manager fordert 800m CPU an, der Sidecar nur 10m
  • Ziel: nur manager auf 400m senken
  • Setzt man den Wert in der Subscription (Web-Console → Operator → Subscription → Resources), landen beide Container bei 400m

Wer steuert was

OLM-Objekte und ihr Einfluss auf die Container des Operator-Pods Subscription, InstallPlan, CSV und Deployment bilden eine Kette bis zum Operator-Pod. Resources aus der Subscription wirken auf alle Container, ein CSV-Patch nur auf einen. Der manager-Container verwaltet über die K10-CR die Kasten-Services. Bei einem Operator-Upgrade entsteht eine neue CSV und ein manueller Patch geht verloren. Subscription InstallPlan CSV Deployment resources gilt für alle Container Operator-Pod manager 800m → 400m kube-rbac-proxy 10m bleibt Patch pro Container K10 CR spec = Helm-Values Kasten-Services catalog-svc, jobs-svc … verwaltet Operator-Upgrade neue CSV, Patch geht verloren wirkt auf alle Container wirkt pro Container
1

OLM im Überblick

Der Operator Lifecycle Manager installiert, aktualisiert und überwacht Operatoren. Er besteht aus zwei Controllern – und fünf Objekten, die man auseinanderhalten muss.

Catalog Operator

Löst Abhängigkeiten auf, erzeugt InstallPlans und beobachtet Kataloge auf neue Versionen.

OLM Operator

Beobachtet CSVs und führt deren Install-Strategie aus: legt Deployments, RBAC und alles Weitere an.

Die beteiligten Objekte

ObjektKurznameAufgabeBild
CatalogSourcecatsrcKatalog mit verfügbaren Operator-Paketen und VersionenVersandkatalog
Subscriptionsub„Paket X aus Channel Y, Updates automatisch oder manuell“Abo
InstallPlanipBerechnete Liste der Ressourcen für eine Installation oder ein UpdateLieferschein
ClusterServiceVersioncsvBeschreibung einer konkreten Operator-Version: Deployment-Spec, RBAC, CRDs, MetadatenBauplan
OperatorGroupogLegt fest, welche Namespaces der Operator beobachtetZuständigkeitsbereich

Ablauf einer Installation

  1. Subscription anlegenPer Web-Console oder YAML.
  2. InstallPlan entstehtDer Catalog Operator findet in der CatalogSource die passende Version.
  3. FreigabeBei installPlanApproval: Automatic sofort, bei Manual erst nach Bestätigung.
  4. CRDs, RBAC und CSV werden angelegtDurch den InstallPlan.
  5. Deployment entstehtDer OLM Operator liest die CSV und erzeugt daraus das Deployment des Operators.
  6. Operator-Pod startetAus dem Deployment.
Nützliche Befehle
oc get sub,ip,csv -n <namespace>
oc get csv -n <namespace> -o wide
oc describe sub <name> -n <namespace>
2

Die CSV: Original, nicht Kopie

Die ClusterServiceVersion ist das zentrale Objekt. Sie beschreibt genau eine Version eines Operators, z. B. k10-kasten-operator-….vX.Y.Z – inklusive der vollständigen Deployment-Spezifikation.

Wichtige Felder

FeldInhalt
spec.install.spec.deployments[]Vollständige Deployment-Spezifikation des Operators, inklusive Container, Images und Resources
spec.install.spec.permissions
…/clusterPermissions
Role- und ClusterRole-Regeln
spec.customresourcedefinitions.ownedCRDs, die der Operator verwaltet
spec.version, spec.replacesVersionskette für Upgrades

Wer gewinnt?

OLM gleicht das Deployment ständig mit der CSV ab.

Änderung anErgebnis
Deploymentwird von OLM zurückgesetzt – steht nicht in der CSV
CSVwird sofort ins Deployment ausgerollt
Operator-UpgradeOLM legt eine neue CSV mit neuem Namen an; die alte samt allen manuellen Änderungen verschwindet
Das Deployment ist die Kopie, die CSV das Original. Wer nur die Kopie ändert, verliert.
Container und CPU-Requests einer CSV anzeigen
CSV=$(oc get csv -n kasten-io -o name | grep k10-kasten-operator-)

oc get $CSV -n kasten-io -o jsonpath='{range .spec.install.spec.deployments[*]}{.name}{"\n"}{range .spec.template.spec.containers[*]}  {.name}: {.resources.requests.cpu}{"\n"}{end}{end}'

Liefert pro Deployment die Container in ihrer Reihenfolge – daraus ergibt sich der Index für den Patch in Abschnitt 4.

3

Warum die Subscription nicht reicht

Die Subscription bietet unter spec.config Overrides für das Operator-Deployment. Sie liegen über der CSV und überstehen damit auch Upgrades – haben aber keinen Container-Selektor.

Verfügbare Overrides in spec.config

  • env, envFrom
  • volumes, volumeMounts
  • resources
  • nodeSelector, tolerations, affinity

Der Haken

Laut Red-Hat-Dokumentation gelten die Werte aus spec.config.resources für alle Container im Pod, den OLM erzeugt.

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: <subscription-name>
  namespace: kasten-io
spec:
  channel: stable
  name: <package-name>
  source: <catalog-source>
  sourceNamespace: openshift-marketplace
  config:
    resources:
      requests:
        cpu: 400m      # gilt für manager UND kube-rbac-proxy
Die Einsparung verpufft: Der Sidecar springt von 10m auf 400m. In Summe sind danach 800m reserviert statt der angestrebten 410m – gegenüber vorher (810m) praktisch nichts gewonnen. Bei Operatoren mit mehreren kleinen Sidecars steigt die Summe sogar über den Ausgangswert.
4

Einmalige Lösung: CSV patchen

Pro Container lässt sich der Wert nur in der CSV ändern. Das wirkt sofort – hält aber nur bis zum nächsten Operator-Upgrade.

Schritt 1 · Subscription-Override entfernen

Sonst überschreibt die Subscription den Patch wieder für alle Container.

oc patch sub <subscription-name> -n kasten-io --type=json \
  -p '[{"op":"remove","path":"/spec/config/resources"}]'
Schritt 2 · Index des Containers ermitteln

Mit dem Befehl aus Abschnitt 2. Der JSON-Patch adressiert Container über ihre Position in der Liste, nicht über ihren Namen.

Schritt 3 · Nur diesen Container patchen

Beispiel: Deployment 0, Container 1.

oc patch $CSV -n kasten-io --type=json -p '[
  {"op":"replace",
   "path":"/spec/install/spec/deployments/0/spec/template/spec/containers/1/resources/requests/cpu",
   "value":"400m"}
]'

replace durch add ersetzen, falls noch kein requests.cpu gesetzt ist. Liegt ein CPU-Limit unter 400m, dieses ebenfalls anpassen.

Schritt 4 · Ergebnis am Pod prüfen
oc get pod -n kasten-io -l control-plane=controller-manager \
  -o jsonpath='{range .items[0].spec.containers[*]}{.name}: {.resources.requests.cpu}{"\n"}{end}'
Einschränkung: Beim nächsten Operator-Upgrade entsteht eine neue CSV mit den Standardwerten. Der Patch ist dann weg – ohne Meldung.
5

Abgrenzung: Operator-Pod vs. Kasten-Services

Veeam Kasten besteht aus zwei Ebenen, die leicht verwechselt werden. Für die Anwendung selbst gibt es einen sauberen, dokumentierten Weg – für den Operator-Pod nicht.

EbeneBeispieleVerwaltet vonResources anpassen über
Operatork10-kasten-operator-…-controller-managerOLM (CSV)CSV-Patch bzw. Kyverno
Kasten-Anwendungcatalog-svc, jobs-svc, executor-svc, Prometheus, Worker-PodsKasten-Operator anhand der K10-CRHelm-Values in der K10-CR

Resources der Kasten-Anwendung

Veeam dokumentiert die Anpassung pro Deployment und Container über Helm-Values in der K10-CR:

resources:
  catalog-svc:
    catalog-svc:
      requests:
        cpu: 300m
        memory: 1.5Gi
Weitere Stellschrauben laut Kasten-Doku
WertWirkt auf
global.resourcesglobaler Fallback mit niedrigster Priorität
prometheus.server.resourcesPrometheus-Pod
genericVolumeSnapshot.resourcesalle temporären Worker-Pods
ActionPodSpec / ActionPodSpecBindingWorker-Pods granular pro Pod-Typ, Namespace oder Policy – erfordert workerPodCRDs.enabled=true
workerPodMetricSidecar.resourcesMetrics-Sidecar der Worker-Pods
Diese Werte überstehen Upgrades, weil sie in der K10-CR liegen. Für den Operator-Pod selbst greifen sie nicht.
6

Dauerhafte Lösung: Kyverno-Mutate-Policy

Kyverno läuft als Admission-Webhook. Legt OLM eine neue CSV an oder ändert eine bestehende, setzt Kyverno den gewünschten Wert, bevor das Objekt gespeichert wird. Es gibt kein Zeitfenster mit dem alten Wert.

Warum nicht einfach ArgoCD?

ArgoCD verwaltet Objekte über ihren Namen. Die CSV heißt nach jedem Upgrade anders (…vX.Y.1 → …vX.Y.2). Ein Patch in Git trifft die neue CSV nicht, Self-Heal hilft hier also nicht. ArgoCD verwaltet stattdessen die Kyverno-Policy – und die bleibt bei Operator-Upgrades unverändert.

ArgoCD ist ein Wachmann mit Namensliste. Kyverno ist ein Türsteher, der jeden kontrolliert, der hereinkommt – egal wie er heißt.

Die Policy

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: k10-operator-manager-cpu
  annotations:
    policies.kyverno.io/title: Kasten-Operator manager CPU-Request
    policies.kyverno.io/description: >-
      Setzt den CPU-Request des Containers "manager" im Kasten-Operator
      auf 400m, unabhängig von der CSV-Version.
spec:
  rules:
  - name: manager-cpu-400m
    match:
      any:
      - resources:
          kinds: ["operators.coreos.com/v1alpha1/ClusterServiceVersion"]
          namespaces: ["kasten-io"]
          names: ["k10-kasten-operator-*"]
          operations: ["CREATE", "UPDATE"]
    mutate:
      foreach:
      - list: "request.object.spec.install.spec.deployments"
        foreach:
        - list: "element.spec.template.spec.containers"
          preconditions:
            all:
            - key: "{{ element.name }}"
              operator: Equals
              value: manager
          patchesJson6902: |-
            - op: add
              path: /spec/install/spec/deployments/{{elementIndex0}}/spec/template/spec/containers/{{elementIndex1}}/resources/requests/cpu
              value: 400m

Was die Policy tut

TeilWirkung
matchNur CSVs des Kasten-Operators in kasten-io. Der Wildcard-Name trifft jede Version.
äußeres foreachLäuft über alle Deployments der CSV.
inneres foreachLäuft über alle Container des jeweiligen Deployments.
preconditionsFiltert auf den Container manager – seine Position in der Liste ist egal.
elementIndex0 / elementIndex1Indizes der äußeren und inneren Schleife für den JSON-Patch-Pfad.
op: addSetzt den Wert, ob er schon existiert oder nicht – vorausgesetzt, resources.requests ist als Objekt vorhanden.

Einführung Schritt für Schritt

Schritt 1 · Containernamen prüfen

Mit dem Befehl aus Abschnitt 2. Heißt der Container anders, value: manager in der Policy anpassen.

Schritt 2 · Subscription-Override entfernen

spec.config.resources aus der Subscription löschen – sonst liegt der Wert für alle Container wieder darüber (Befehl in Abschnitt 4, Schritt 1).

Schritt 3 · Policy per ArgoCD ausrollen

Zum Beispiel im Repo unter policies/kyverno/.

Schritt 4 · Bestehende CSV einmal anstoßen

Admission-Webhooks greifen nur bei Änderungen. Die bereits vorhandene CSV muss deshalb einmal angefasst werden:

oc annotate $CSV -n kasten-io kyverno-touch="$(date +%s)" --overwrite
Schritt 5 · Ergebnis prüfen
# In der CSV
oc get $CSV -n kasten-io -o jsonpath='{range .spec.install.spec.deployments[*].spec.template.spec.containers[*]}{.name}: {.resources.requests.cpu}{"\n"}{end}'

# Am laufenden Pod
oc get pod -n kasten-io -l control-plane=controller-manager \
  -o jsonpath='{range .items[0].spec.containers[*]}{.name}: {.resources.requests.cpu}{"\n"}{end}'

# Kyverno-Events
oc get events -n kasten-io --field-selector reason=PolicyApplied

Hinweise

  • Copied CSVs: Bei Install-Mode AllNamespaces kopiert OLM die CSV in jeden Namespace. Die Einschränkung auf namespaces: ["kasten-io"] verhindert, dass Kyverno diese Kopien mutiert.
  • Status-Updates: OLM aktualisiert den CSV-Status häufig. Das läuft über die /status-Subresource und löst die Policy nicht aus.
  • Limits: Soll auch das Limit angepasst werden, einen zweiten Patch-Eintrag für /resources/limits/cpu ergänzen.
  • Support: Kyverno ist nicht Teil der Red-Hat-Subscription. Nested foreach mit elementIndex0/1 setzt eine aktuelle Kyverno-Version voraus – die Policy zuerst auf einem Testcluster prüfen.
Stiller Fehler bei Webhook-Ausfall: Ist Kyverno nicht erreichbar und steht die Webhook-failurePolicy auf Ignore, legt OLM die CSV ohne Mutation an. Kein Fehler, keine Warnung – der Operator läuft einfach wieder mit 800m. Nach jedem Upgrade die Werte kontrollieren.
7

Alternativen im Vergleich

Kyverno ist nicht die einzige Option. Welche passt, hängt davon ab, ob eine Zusatzkomponente akzeptabel ist und wie oft der Operator aktualisiert wird.

VarianteÜberlebt UpgradeZeitfenster mit altem WertZusatzkomponenteAufwand
Subscription config.resourcesjaneinkeinegering, aber nur für alle Container
CSV manuell patchenneinja, bis manuell gepatchtkeinebei jedem Upgrade
CSV patchen + installPlanApproval: Manual + Runbooknein (bewusst nachgezogen)kurzkeinepro Upgrade ein Schritt
CronJob, der die aktuelle CSV sucht und patchtjaja, bis zum nächsten Laufkeineeinmalig, RBAC für CSV nötig
Kyverno-Mutate-PolicyjaneinKyvernoeinmalig
CronJob-Variante als Skizze

Sucht die aktuelle CSV, ermittelt den Index von manager und patcht gezielt diesen Container:

CSV=$(oc get csv -n kasten-io -o name | grep k10-kasten-operator-)
IDX=$(oc get $CSV -n kasten-io -o json \
  | jq '.spec.install.spec.deployments[0].spec.template.spec.containers | map(.name) | index("manager")')
oc patch $CSV -n kasten-io --type=json \
  -p "[{\"op\":\"add\",\"path\":\"/spec/install/spec/deployments/0/spec/template/spec/containers/$IDX/resources/requests/cpu\",\"value\":\"400m\"}]"

Benötigt einen ServiceAccount mit get, list, patch auf clusterserviceversions.operators.coreos.com im Namespace kasten-io.

8

Kurzfassung

Das Wichtigste in fünf Sätzen.

  1. Das Deployment eines OLM-Operators ist nur eine Kopie.Das Original ist die CSV.
  2. Subscription-Overrides überstehen Upgrades– gelten aber für alle Container im Pod.
  3. CSV-Patches wirken pro Container– gehen aber beim Upgrade verloren.
  4. Kasten-Services werden über die K10-CR konfiguriertPro Container, upgradefest – betrifft aber nicht den Operator-Pod.
  5. Kyverno mutiert jede neue CSV beim AnlegenWerte pro Container bleiben dauerhaft gesetzt, ohne Zeitfenster und GitOps-tauglich.