Jemand sagt „wir laufen auf OpenShift“, und ein Kubernetes-Lernender hört „wir laufen auf etwas völlig anderem“. Das trifft selten zu. OpenShift ist eine Distribution von Kubernetes mit Red-Hat-Verpackung, opinionierten Defaults und zusätzlichen Plattform-APIs. Der Scheduler plant weiter Pods. Deployments rollen weiter ReplicaSets aus. Services wählen Pods weiter über Labels.

Das habe ich auf die harte Tour gelernt. Monate lang war ich mit kubectl, Ingress und Namespace-RBAC auf Vanilla-Clustern unterwegs. Dann kam ein Team auf OpenShift — und plötzlich fühlte ich mich wieder wie Anfänger. Nicht weil Pods anders liefen, sondern weil die Front Door für HTTP eine Route war, das Sicherheitsmodell SCCs kannte und oc Shortcuts hatte, die ich nicht kannte.

Dieser Beitrag ist für genau diesen Übergang. Ich werde nicht so tun, OpenShift sei trivial oder identisch mit jedem Managed-Kubernetes-Angebot. Ich trenne, was sauber übertragbar ist, von dem, wofür man die Docs bewusst lesen sollte.

Gleicher Kubernetes-Kern darunter

OpenShift liefert eine getestete, supported Kubernetes-Version aus. Die API-Gruppen des Alltags — apps/v1 Deployments, v1 Services und ConfigMaps, batch/v1 Jobs — sind Upstream-Kubernetes-Ressourcen.

Wer dieses Deployment schreiben kann, lässt es auf OpenShift gleich laufen:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  labels:
    app: api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: registry.example.com/team/api:1.4.0
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 256Mi
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10

Anwenden mit kubectl oder oc — beide sprechen mit demselben API-Server:

kubectl apply -f deployment.yaml
# or
oc apply -f deployment.yaml

Prüfen wie gewohnt:

kubectl get deploy,rs,pod -l app=api
kubectl describe pod -l app=api
kubectl logs -l app=api --tail=50

Auf OpenShift funktionieren dieselben Befehle. oc bringt Komfort — oc status, oc logs -f deployment/api, Project-Wechsel — ist aber kein separater Orchestrator. Eher kubectl plus plattformbewusste Helfer.

Was vertraut bleibt:

  • Pod-Lifecycle, Probes, Restart-Policies
  • Deployments, StatefulSets, DaemonSets, CronJobs
  • Services, Endpoints, EndpointSlices, DNS im Cluster
  • ConfigMaps, Secrets, PersistentVolumeClaims
  • NetworkPolicy (mit OVN-Kubernetes als Default-CNI auf modernem OpenShift)
  • RBAC mit Roles, RoleBindings, ClusterRoles

Wenn Dokumentation sagt „Kubernetes macht X“, macht OpenShift meist auch X — außer die Plattform legt einen Wrapper oder strengeren Default darüber.

Herstellerpaket — was Red Hat ergänzt

OpenShift „nur Kubernetes“ zu nennen, unterschätzt die Plattformschicht. „Völlig anders“ zu sagen, übertreibt. Die ehrliche Mitte: Red Hat liefert Kubernetes plus integrierten Produktstack.

Typischerweise gehören dazu:

  • OpenShift Router — exponiert HTTP/S über Route-Objekte (OpenShifts etabliertes Edge-Muster)
  • Ingress Controller — ebenfalls verfügbar; Ingress-Ressourcen funktionieren, oft neben Routes
  • Eingebaute Image Registryimage-registry.openshift-image-registry.svc im Cluster
  • Operators und OLM — installieren und lifecycle-verwalten Plattform- und Drittanbieter-Software
  • Web-Konsole — GUI für Projects, Routes, Builds, Monitoring
  • Monitoring und Logging — Prometheus, Alertmanager, Cluster-Logging-Operators auf vielen Installationen vorkonfiguriert
  • Security Context Constraints — Pod-Admission-Regeln über Pod Security Standards hinaus
  • Projects — Namespaces mit Extra-Metadaten und Default-Quotas/Limits

Nicht alles davon berührt man am ersten Tag. Anwendungsentwickler arbeiten oft mit Projects, Routes, Deployments, Services und Secrets. Plattformteams leben in Operators, SCCs, Cluster-Netzwerk und Upgrade-Kanälen.

Das Paket zählt für Betrieb, nicht für das Mental Model „Ich deploye eine containerisierte App hinter einem Service.“ Das bleibt.

Routes — die HTTP-Front-Door, die man zuerst trifft

Auf vielen Vanilla-Clustern heißt HTTP-Ingress Ingress-Ressource plus separat installierter Ingress-Controller (nginx, traefik, AWS ALB usw.). OpenShift hat Route seit Jahren als First-Class-API unter route.openshift.io.

Eine Route mappt externen Hostnamen und Pfad auf einen Service:

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: api
  labels:
    app: api
spec:
  host: api.apps.cluster.example.com
  to:
    kind: Service
    name: api
    weight: 100
  port:
    targetPort: 8080
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Redirect

Der OpenShift Router (historisch HAProxy-basiert; Implementierungen entwickeln sich) beobachtet Route-Objekte und konfiguriert Edge-Load-Balancing. Edge-TLS-Terminierung ist üblich — der Router beendet HTTPS und leitet HTTP an den Service im Cluster weiter.

Wer Ingress kennt, findet Routes vertraut mit anderen Feldnamen:

KonzeptIngress (typisch)OpenShift Route
Externer Hostnamespec.rules[].hostspec.host
Backend-Servicebackend.servicespec.to.name
Portport.numberspec.port.targetPort
TLSspec.tlsspec.tls mit Termination-Modi

OpenShift unterstützt auch Standard-Ingress-Ressourcen. Teams standardisieren manchmal auf Ingress für Portabilität und nutzen Routes, wo Plattform-Defaults einfacher sind. Beides kann koexistieren. Ich habe Teams gesehen, die pro Umgebung ein Muster wählen, um Verwirrung zu vermeiden.

Für kubectl-Nutzer:

oc get route
oc describe route api
kubectl get route -n my-project

Routes sind der größte „das fühlt sich anders an“-Moment für Kubernetes-Nutzer. Kein Grund, Deployments neu zu lernen — eher ein neues Objekt an der Edge.

Security Context Constraints — Pod-Security mit OpenShift-Geschmack

Kubernetes hat heute Pod Security Admission mit restricted, baseline und privileged. OpenShift ergänzt Security Context Constraints (SCCs) — eine ältere, reichere Admission-Schicht, die viele Cluster noch prägt.

Eine SCC beantwortet Fragen wie:

  • Darf dieser Pod als root (UID 0) laufen?
  • Welche Volume-Typen sind erlaubt?
  • Darf hostNetwork oder hostPID genutzt werden?
  • Welche SELinux-Kontexte sind zulässig?

Standardmäßig landen die meisten User-Workloads auf restricted-v2 oder ähnlich benannten SCCs. Das bedeutet:

  • Container sollten nicht annehmen, als root laufen zu dürfen
  • Privileged Pods brauchen explizite Freigabe
  • Manche Helm-Charts für permissive Cluster scheitern, bis Security Contexts angepasst sind

Symptome sehen aus wie Kubernetes-Admission-Fehler:

oc describe pod failing-app-xxxxx
# Events:
#   Warning  FailedCreate  ... unable to validate against any security context constraint

Vergleichen mit:

oc get scc
oc describe scc restricted-v2

Typische Fix-Pfade:

  • runAsNonRoot: true und konkreten runAsUser im Pod-Spec setzen
  • Weniger restriktive SCC über RBAC anfragen (Plattformteam-Entscheidung, nicht selbst vergeben)
  • Chart oder Image anpassen, damit kein root nötig ist

Ich habe Nachmittage mit SCC-Fehlern verbracht, die wie mysteriöses „Pod hängt ewig pending“ wirkten. Das Deployment war in Ordnung. Das Image wollte root. Die Plattform sagte nein. OpenShift war nicht feindselig — sie setzte eine Baseline durch, die ich zuerst lesen sollte.

SCCs überschneiden sich konzeptionell mit Pod Security Standards. Auf neueren OpenShift-Versionen konvergiert die Story, aber SCCs bleiben das Objekt, das Plattform-Admins bei Incidents durchsuchen.

Projects — Namespaces mit Plattform-Semantik

Ein Project ist ein Kubernetes-Namespace plus OpenShift-Metadaten. Im Alltag ist es dieselbe Isolationsgrenze:

oc project my-team-dev
kubectl config set-context --current --namespace=my-team-dev
oc get all

Projects auflisten:

oc get projects
kubectl get namespaces

Unterschiede, die in der Praxis zählen:

  • Die Web-Konsole spricht von „Projects“
  • Default-ResourceQuotas und LimitRanges werden oft pro Project von Admins gesetzt
  • oc new-project erstellt einen Namespace und setzt RBAC für den Ersteller
  • Manche clusterweiten Policies referenzieren Project-Labels

Wer Namespaces, RBAC und Quotas versteht, hat bei Projects kein neues Konzept — nur den Namen, den OpenShift in UX und Docs nutzt. Beim YAML-Schreiben denke ich weiter in Namespaces; die API akzeptiert metadata.namespace in beiden Welten.

Operators — wie Plattform-Software installiert wird

OpenShift setzt stark auf das Operator-Muster. Ein Operator ist ein Controller, der Custom Resources beobachtet und komplexe Software reconciled — Datenbanken, Service Meshes, den Ingress/Router-Stack selbst.

Operator Lifecycle Manager (OLM) installiert Operators aus Katalogen. Cluster-Admins subscriben einen Operator; OLM erzeugt CSVs, Deployments und CRDs.

Als Anwendungsentwickler trifft man Operators, wenn:

  • Eine DBA PostgreSQL über eine PostgresCluster-CR statt rohem StatefulSet-YAML bereitstellt
  • Das Monitoring vom Cluster-Operator verwaltet wird, den man nicht anfasst
  • Das Team einen Vendor-Operator für eine Message Queue im Namespace installiert

Als Lernender aus Helm-only-Clustern verschiebt sich: manche Infrastruktur ist eine CRD mit Reconciliation-Loop, kein Chart, das man manuell upgraded.

Nützliche Discovery-Befehle:

oc get csv -A
oc get operators
oc get crd | head
kubectl api-resources | grep -i postgres

Man muss keine Operators schreiben, um auf OpenShift zu arbeiten. Man sollte erkennen, wann ein Workload „nur Kubernetes-YAML“ ist vs. „vom Operator-CR verwaltet“ — Upgrades und Backups können Operator-owned sein.

Wann Kubernetes-Skills sauber übertragen

Wer das auf jedem Kubernetes-Cluster kann, schafft es auf OpenShift mit wenig Reibung:

Anwendungen deployen und ausrollen — Deployments, Rollouts, kubectl rollout status, Image-Updates.

Pod-Fehler debuggenkubectl describe pod, Logs, Events, Probe-Miskonfiguration, OOMKilled, Image-Pull-Fehler.

Internen Traffic verdrahten — ClusterIP-Services, DNS-Namen, Port-Abgleich zwischen Service und Container.

Konfiguration verwalten — ConfigMaps und Secrets, Env-Vars, Volume-Mounts.

RBAC-Grundlagen — wer was in welchem Namespace/Project anlegen darf.

YAML lesen und dry-run nutzenkubectl apply --dry-run=server -f fängt viele Probleme vor dem Apply ab.

GitOps-Workflows — Argo CD und Flux laufen auf OpenShift; sie reconcilen dieselben Ressourcentypen (plus Routes und andere OpenShift-CRs, wenn genutzt).

NetworkPolicy-Denken — Label-Selectoren, explizite Allow-Regeln, Default-Deny, wenn Policies Pods selektieren.

Am besten übertragen sich schichtweises Debugging und Events lesen. OpenShift-Incidents beginnen weiter mit „was hat sich in Pod-, Service- und Route-Schicht geändert?“

Ehrliche Grenzen — was nicht automatisch übertragbar ist

Das hätte mir früher jemand auflisten sollen.

Ingress-Muskelgedächtnis reicht nicht. Routes sind das native Edge-Objekt. Ingress funktioniert, aber Docs, Samples und Kollegen-Snippets setzen oft Routes voraus. Beide Namen lernen, wenn die Organisation beides nutzt.

Security-Annahmen aus permissiven Labs brechen. Kind und minikube lassen oft privileged Pods zu. OpenShift vielleicht nicht. Charts, die lokal „einfach liefen“, brauchen Security-Context-Review.

Plattform-Namespaces gehören nicht einem selbst. openshift-*, kube-* und Operator-Namespaces verwaltet der Cluster. Beliebiges YAML dort anzuwenden ist ein schneller Weg, das Vertrauen des Plattformteams zu verlieren.

BuildConfigs und ImageStreams sind OpenShift-spezifisch. Manche Teams bauen außerhalb (CI, Tekton, GitHub Actions) und deployen nur. Andere nutzen oc new-app und BuildConfigs. Vor dem Kopieren alter Tutorials klären, welches Muster das Team nutzt.

Storage Classes und CSI-Treiber sind cluster-spezifisch. PVCs funktionieren gleich; Storage-Class-Namen und Performance sind nicht portabel.

Dokumentations-Streuung. Man liest Kubernetes-Docs, OpenShift-Docs und Vendor-Operator-Docs. Die Antwort auf „welche API-Version?“ hängt von der Kubernetes-Minor-Version des Clusters ab — oc version prüfen.

oc vs kubectl Policy. Manche Organisationen standardisieren auf oc wegen Audit-Wrappern oder Login-Integration. Manche erlauben kubectl mit kubeconfig von oc login. Fragen statt annehmen.

Lizenzierung und Support-Grenzen. OpenShift ist ein kommerzielles Produkt mit Subscription-Stufen. Das beeinflusst Upgrade-Takt, Support-Anrufe und was das Plattformteam ändert. Kein technisches Skill-Gap, aber Workflow-Unterschied.

Das invalidiert Kubernetes-Lernen nicht. Es ist die Packaging-Steuer obendrauf.

oc und kubectl — praktisches Nebeneinander

oc enthält kubectl-kompatible Befehle. Viele Teams nutzen beides oder aliassen:

oc login https://api.cluster.example.com:6443
oc whoami
oc project my-team-dev

kubectl get pods
oc get pods

oc apply -f app/
kubectl apply -f app/

OpenShift-spezifische Helfer, die sich lohnen:

oc status
oc get route
oc logs -f deployment/api
oc rsh deployment/api
oc set env deployment/api LOG_LEVEL=debug
oc rollout restart deployment/api

oc explain funktioniert für Route und andere OpenShift-Typen:

oc explain route.spec.tls
kubectl explain route.spec.tls

Ich greife aus Gewohnheit noch zu kubectl. Ich nutze oc für Login, Project-Kontext oder Route-bewusste Ausgabe. Ein primäres Tool pro Shell-Session wählen; Kontext-Mischen verwirrt mehr als Befehls-Mischen.

Ein bescheidener Lernpfad

Wer Kubernetes-Grundlagen schon hat, sollte nicht bei null anfangen. Ich würde OpenShift so schichten:

  1. Zugang holenoc login, oc whoami, Projects listen, Default-Project setzen.
  2. Etwas Langweiliges deployen — Deployment + Service, Pods und Endpoints bestätigen.
  3. Exponieren — Route anlegen, Hostname aufrufen, TLS-Verhalten prüfen.
  4. Absichtlich kaputt machen — falscher Selector, failing Readiness Probe, Non-Root-Verletzung — und jedes mit describe/logs/events fixen.
  5. Eine SCC und eine Quota lesen — verstehen, warum die Plattform blockiert oder gedrosselt hat.
  6. Herausfinden, was Operators besitzen — eine CRD identifizieren, von der der Stack abhängt, und Status-Felder lesen.

Das hat mich ein paar fokussierte Tage gekostet, nicht Monate. Das Kubernetes-Fundament war der Teil, der wirklich Zeit sparte.

OpenShift vs „Kubernetes in der Cloud“ — kurze Einordnung

Managed Kubernetes (EKS, GKE, AKS) liefert eine Control Plane und lässt viele Add-ons als Wahl. OpenShift liefert mehr vorgefertigte Entscheidungen: Router, Registry-Integration, Konsole, Default-Monitoring, SCCs.

Kein Modell ist universell besser. OpenShift tauscht Flexibilität bei Komponentenwahl gegen integrierten Betrieb. Vanilla Kubernetes tauscht Integration gegen Pick-your-own Ingress, Policy-Engine und Observability-Stack.

Vergleichen, was die eigene Organisation wirklich betreibt — nicht Marketing-Folien.

Abschluss

OpenShift vs Kubernetes ist die falsche Binärfrage. Besser: Was ist Upstream-Kubernetes, und was ist Red-Hat-Plattform darüber?

Deployments, Services, Probes und RBAC sind die gemeinsame Sprache. Routes, SCCs, Projects und Operators sind der lokale Dialekt. Den Dialekt lernt man, wenn man ihn braucht — meist an der Edge, bei Admission und im Gespräch mit Plattform-Admins.

Ich google SCC-Fehlermeldungen noch immer. Ich prüfe Endpoints vor Routes, wenn HTTP ausfällt. Die Kernskills aus kubectl-zentriertem Lernen waren nicht umsonst. Sie waren der Teil, der am ersten Tag überging.