Das erste Deploy auf OpenShift fühlt sich an wie Ankunft. Routes lösen auf, Pods werden Ready, jemand sagt „wir sind jetzt auf der Plattform“. Day two ist, wenn der Cluster ohne Applaus weiterläuft — Upgrades kommen, Quotas beißen, Logs tauchen nicht mehr auf, und die Grenze zwischen Anwendungs- und Plattformproblem wird unscharf.

Ich war in Anwendungsteams, die OpenShift wie gemietetes Kubernetes mit schönerer Console behandelten. Das hält, bis es nicht mehr hält. Dieser Beitrag richtet sich an Engineers, die Services auf geteiltem OpenShift betreiben — nicht Cluster-Admins, aber Leute, die verstehen müssen, was nach Go-live passiert.

Day two ist, wo der Komfort endet

Day-one-Probleme sind sichtbar: Image-Pull-Fehler, fehlende Secrets, Route-Host-Tippfehler. Day-two-Probleme sind systemisch:

Cluster-Upgrades ändern API-Versionen, Operator-Versionen und manchmal Default-Security-Profile.

Kapazität ist geteilt; der Batch-Job des Nachbarn beeinflusst Scheduling.

Observability hängt an Agenten und Collectors, die die Plattform installiert hat — oder vergessen hat im Namespace zu aktivieren.

Backups decken vielleicht etcd und Cluster-Metadaten ab, während das Datenbank-Backup noch die eigene Aufgabe ist — oder umgekehrt, je nach Vertrag.

Policy — SCCs, Network-Policy-Baselines, Compliance-Operatoren — entwickelt sich ohne Deploy aus dem eigenen Repo.

Das macht niemanden zum Cluster-Admin. Es verlangt zu wissen, was man besitzt, was die Plattform besitzt, und wann man mit einem guten Ticket die Brücke überquert.

Upgrade-Bewusstsein ohne Control Plane zu besitzen

Auf managed OpenShift (ROSA, ARO) oder Enterprise-Clustern, die ein Plattformteam betreibt, triggern Anwendungsteams selten Control-Plane-Upgrades. Sie spüren sie trotzdem.

Vor einem Upgrade-Fenster veröffentlichen Plattformteams oft Zielversionen und Wartungspläne. Anwendungsteams sollten:

Release Notes zum OpenShift-Versions-Sprung lesen — entfernte APIs brechen Manifeste still, bis Apply-Zeit.

Mit oc get apirequestcounts oder den API-Inspection-Tools der Plattform prüfen, welche entfernten API-Versionen in den eigenen Namespaces vorkommen.

In Non-Prod auf der Zielversion oder dem Channel testen, wenn ein Pre-Upgrade-Cluster existiert.

Operator-Subscriptions für Drittanbieter-Operatoren im Namespace prüfen — Channel-Bumps müssen oft zu OCP passen.

Beispiel-Check für veraltete Deployments-API-Nutzung:

oc get apirequestcounts | grep -i apps
oc api-resources --api-group=apps --verbs=list

Während des Upgrades kurze API-Unverfügbarkeit, Node-Reboots und Pod-Rescheduling erwarten. Anwendungen mit Single-Replica und strikten PodDisruptionBudgets vor dem Fenster prüfen — nicht währenddessen.

Nach dem Upgrade verifizieren:

  • Routes liefern weiter Traffic
  • CronJobs und Jobs liefen planmäßig
  • Custom Metrics und ServiceMonitors scrapen weiter
  • Webhook- oder Admission-Integrationen succeeden noch

Wenn etwas clusterweit bricht — Console-Login, Default-Ingress, Monitoring-Stack — ist das Plattform-Eskalation. Wenn nur der eigene Namespace failt, mit recenten Manifest-Änderungen und Image-Tags starten, aber den Upgrade-Zeitstempel im Ticket nennen.

Monitoring auf OpenShift

OpenShift liefert Cluster Monitoring auf Basis von Prometheus-Operator-Mustern. Anwendungsteams exponieren Metriken typischerweise über ServiceMonitor oder PodMonitor — wenn RBAC und Namespace-Labels es erlauben.

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: shop-api
  namespace: payments-prod
  labels:
    team: payments
spec:
  selector:
    matchLabels:
      app: shop-api
  endpoints:
    - port: metrics
      interval: "30s"
      path: "/metrics"

Plattformteams verlangen oft bestimmte Labels, damit die Prometheus-Instanz der Plattform den Monitor aufnimmt. Den Label-Vertrag vor dem Merge von YAML klären, das nie scraped.

Nützliche Gewohnheiten:

Dashboards — bereitgestelltes Grafana oder zentrale Observability der Organisation. Nicht nur auf oc get pods verlassen.

Alerts — Anwendungs-SLO-Alerts ans eigene Team; Infrastruktur-Alerts an die Plattform. Mischen erzeugt Alert Fatigue und falsche Eskalationen.

Console-Monitoring-Tab — hilfreich für schnelle Checks; kein Ersatz für Retention und Query-Power im richtigen Metrics-Store.

openshift-state-metrics und kube-state-metrics — plattformseitig; trotzdem nützlich für Pod-Restart-Counts und Quota-Druck im Namespace.

Wenn Metriken nach einem Upgrade verschwinden, prüfen, ob ServiceMonitor-Labels noch zum Plattform-Selector passen, bevor man Regression in der App annimmt.

Logging und wo Anwendungsteams einhaken

OpenShift Cluster Logging (Loki-basiert in aktuellen Generationen, oder legacy Elasticsearch je nach Version und Install) aggregiert Plattform- und Workload-Logs. Anwendungsteams:

Loggen nach stdout/stderr — Twelve-Factor-Gewohnheit; Cluster-Agenten sammeln über die Container-Runtime.

Strukturieren Logs — JSON oder key=value erleichtert Suche in Kibana, Grafana Loki oder dem SIEM.

Vermeiden, kritische Logs nur auf ephemeralen Container-Filesystem-Pfaden zu schreiben — bei Restart weg, im Incident schmerzhaft.

Retention kennen — Plattform-Retention ist nicht unendlich; audit-kritische Logs exportieren, wenn Compliance längere Historie verlangt.

Suche per CLI, wenn die Console langsam ist:

oc logs deployment/shop-api -n payments-prod --tail=200
oc logs deployment/shop-api -n payments-prod -c shop-api --since=1h

Bei Multi-Replica-Deployments während Incidents aggregieren:

oc logs deployment/shop-api -n payments-prod --all-containers=true --tail=50

Wenn Logs nie in der zentralen UI erscheinen, mit Namespace, Pod-Label und ungefährem Zeitstempel eskalieren — Plattformteams finden Lücken in der Collection-Pipeline schneller als Raten.

Resource Quotas und Limits auf geteilten Clustern

Geteilte OpenShift-Cluster nutzen ResourceQuota und LimitRange, um Namespace-Verbrauch zu deckeln. Plattformteams definieren Rahmen; Anwendungsteams deployen darin.

Typische ResourceQuota:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: payments-prod-quota
  namespace: payments-prod
spec:
  hard:
    pods: "40"
    requests.cpu: "8"
    requests.memory: "16Gi"
    limits.cpu: "16"
    limits.memory: "32Gi"
    services.loadbalancers: "2"
    persistentvolumeclaims: "10"

LimitRange setzt Defaults und Deckel pro Pod oder Container:

apiVersion: v1
kind: LimitRange
metadata:
  name: payments-prod-limits
  namespace: payments-prod
spec:
  limits:
    - type: Container
      default:
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      max:
        cpu: "2"
        memory: "4Gi"
      min:
        cpu: "50m"
        memory: "64Mi"

Aktuellen Verbrauch vor Scale oder Lasttests prüfen:

oc describe quota -n payments-prod
oc describe limitrange -n payments-prod

Quota-exceeded-Fehler wirken wie Scheduling-Failures oder Admission-Denial — nicht immer offensichtlich in App-Logs. Die Meldungsform kennen:

Error creating: pods "shop-api-7d9f-" is forbidden:
 exceeded quota: payments-prod-quota,
 requested: limits.cpu=4,
 used: limits.cpu=14,
 limited: limits.cpu=16

Das ist nicht Kubernetes, das nörgelt. Das ist der Vertrag, den man durch Deploy in einen geteilten Namespace eingegangen ist.

Requests, Limits und ehrliche Kapazität

Jeder Container sollte requests und limits deklarieren — mindestens CPU und Memory. OpenShift-Scheduling und Quota-Rechnung nutzen Requests; Limits deckeln Burst und OOM-Verhalten.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: shop-api
  namespace: payments-prod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: shop-api
  template:
    metadata:
      labels:
        app: shop-api
    spec:
      containers:
        - name: shop-api
          image: "ghcr.io/example/shop-api:2.4.1"
          ports:
            - containerPort: 8080
              name: http
          resources:
            requests:
              cpu: "250m"
              memory: "512Mi"
            limits:
              cpu: "1"
              memory: "1Gi"

Unterdeklarierte CPU erzeugt Noisy-Neighbor-Scheduling; überdeklariertes Memory blockiert andere vom Schedulen, auch im Idle. Nutzung monatlich prüfen — Metriken, nicht Schätzungen.

Vertical Pod Autoscaler oder Plattform-Empfehlungen existieren vielleicht; Adoption hängt von der Org-Policy ab. Autoscaling nicht aktivieren, das mit GitOps-verwalteten Replica-Counts kämpft, ohne Ignore-Regeln abzustimmen.

Backup-Mindset für Anwendungsteams

Backup auf OpenShift hat Schichten. Klären, was die Organisation wirklich wiederherstellt:

Cluster-etcd und Konfiguration — Plattform-Scope; stellt das Cluster-Skelett wieder her, nicht unbedingt Datenbankinhalte.

PersistentVolume-Snapshots — vielleicht automatisiert durch CSI-Treiber oder Backup-Operatoren; Retention und RPO/RTO kennen.

Anwendungsdaten — Datenbanken, Object Storage, Message Queues — oft weiter Aufgabe des Anwendungsteams, auch mit PVs.

Secrets und Konfiguration in Git — GitOps hilft, Manifeste neu zu bauen; Secrets brauchen separate Rotation und Backup-Policy.

Operatoren und CRDs — Namespace-YAML ohne den reconcilierenden Operator wiederherstellen erzeugt stillen Drift.

Fragen an Plattform oder Architekt einmal schriftlich:

  • Was wird für unseren Namespace automatisch gesichert?
  • Welche Restore-Drills laufen jährlich?
  • Wer initiiert Restore — App-Team oder Plattform?
  • Gibt es Cross-Region-Kopien für genutzte PVs?

Anwendungsteam-Gewohnheiten, die unabhängig helfen:

Stateful Dependencies dokumentieren — welche PVC-Namen zählen, welches externe SaaS autoritative Daten hält.

Restore in Staging testen — ein Backup, das niemand restored hat, ist Optimismus.

Versions-Migrationspfade — Restore plus Major-DB-Upgrade kann ein Runbook sein.

Nicht annehmen, „die Plattform sichert OpenShift“ heißt „mein Service ist morgen wieder da“.

Plattform- versus Team-Scope

Grobe Aufteilung, die ich funktionieren sah:

ThemaMeist PlattformMeist Anwendungsteam
Control-Plane-Upgradesjanur Bewusstsein
Nodes, Machine PoolsjaSymptome melden
Cluster Operators (Logging, Monitoring)jaApp-Integration konfigurieren
Namespace, Quota, LimitRangejaÄnderungen anfragen
Deployment, Service, Routeneinja
Anwendungs-Datenbank-Backupteilweiseja
Ingress/Router-DefaultsjaRoute konfigurieren
SCC-Zuweisung an Service Accountsoft Plattformanfragen + begründen
NetworkPolicy-Baselineoft PlattformNamespace-Regeln innerhalb Policy

Grauzonen existieren. Die Tabelle ist Gesprächsstarter mit dem Plattformteam, kein universelles Gesetz.

Wann an das Plattformteam eskalieren

Früh eskalieren, wenn:

Symptome clusterweit sind — mehrere Namespaces, Console-Fehler, Default-Routes failen.

Nodes NotReady oder breite Scheduling-Failures — nicht eine einzelne Deployment-Fehlkonfiguration.

Operator-Health degraded — ClusterOperator-Status nicht Available für Kernkomponenten.

Zertifikats- oder Identity-Probleme — OAuth, Ingress-Zerts, Service-Serving-Certs betreffen viele Services.

Quota- oder SCC-Änderungen nötig — höhere Limits oder custom SCC; kubectl kann nicht selbst gewähren.

Storage Class oder Snapshot-Restore — PV-Provisioning failt für alle in der Class.

Netzwerkpfad außerhalb des Namespaces — Corporate Firewall, DNS-Forwarder, Egress-Proxies.

Verdacht auf Plattform-Upgrade-Regression — Timeline korreliert mit Wartungsfenster.

Nicht leer eskalieren. Mitbringen:

  • Namespace und betroffene Ressourcennamen
  • Zeitstempel in UTC
  • oc describe-Output für failende Pods, Events, Routes
  • recente Änderungen — Merges, Image-Tags, Scale-Events
  • Kundenauswirkung — Error Rate, fehlgeschlagene Transaktionen, nur intern
  • was bereits versucht wurde — Rollbacks, Log-Checks, Replica-Scale

Beispiel-Event-Snippet fürs Ticket:

Warning  FailedCreate  replicaset/shop-api-7d9f  admittance denied:
 container shop-api has runAsUser 1001,
 pod securityContext fsGroup is 1001,
 SCC restricted-v2 does not allow

Das macht aus vague „Pods pending“ ein actionable SCC-Gespräch.

Auf Anwendungsseite bleiben, wenn ein Deployment nach dem eigenen Merge regressed, Probes auf einem eigenen Pfad failen oder Logs Business-Logic-Fehler zeigen — keine kube Events. Plattformteams respektieren Teams, die vor Eskalation prüfen.

Runbooks und Upgrade-Drills

Kurzes Runbook pro Namespace: Ownership, Dependencies, Quota-Headroom, Rollback-Pfad, Checks im Upgrade-Fenster und Eskalations-Template mit den Feldern, die die Plattform beim letzten Mal verlangt hat. Post-Upgrade-Checkliste nach jeder Wartung laufen, auch wenn nichts kaputt wirkt.

Abschluss

OpenShift Day-two-Betrieb für Anwendungsteams ist vor allem Grenzen: Upgrade-Bewusstsein ohne Control Plane zu besitzen, Observability über Plattform-Tooling mit Anwendungs-Instrumentierung, Kapazität über Quotas und ehrliche Requests, Backup-Klarheit statt Annahmen, Eskalation mit Belegen statt Panik.

Die Plattform trägt Cluster-Gewicht. Anwendungsteams tragen Service-Zuverlässigkeit innerhalb des gegebenen Rahmens. Die Zusammenarbeit funktioniert, wenn beide Seiten wissen, auf welcher Seite der Linie sie stehen — und wann man gemeinsam zur Brücke geht.

Wer heute auf OpenShift läuft, einen Produktions-Namespace wählen und drei Fragen ohne Notizen beantworten: Wie viel Quota-Headroom bleibt? Wen pagt man bei Control-Plane-Upgrade-Failure? Wann wurde zuletzt ein Backup-Restore-Pfad für die Stateful-Schicht verifiziert? Lücken dort sind Day-two-Schulden, die man vor dem nächsten Wartungsfenster einplanen sollte.