Kubernetes-Deployments referenzieren Container-Images per String: Registry, Repository, Tag oder Digest. Das funktioniert überall. OpenShift ergänzt ImageStreams und BuildConfigs, damit Teams Images im Cluster benennen, Builds aus Git oder Dockerfiles anstoßen und bei Tag-Wechsel ausrollen können — ohne dass jede Person zuerst manuell in eine externe Registry pusht.

Die Plattform-Schicht hilft, bis sie es nicht tut. Manche Teams nutzen OpenShift-Builds für alles. Andere bauen in CI, pushen nach Harbor oder ECR und konsumieren Images nur auf dem Cluster. Beide Muster sind valide. Dieser Beitrag erklärt, was ImageStreams und BuildConfigs leisten, wie S2I sich von Dockerfile-Builds unterscheidet und wann Builds auf dem Cluster ganz entfallen können.

Wofür ImageStreams existieren

Auf plain Kubernetes ändert sich nichts, wenn man unter demselben Tag ein anderes Image in der Registry ablegt — bis etwas neu zieht oder Pods neu starten. Tags sind veränderlich; der Cluster bemerkt das nicht automatisch.

Ein ImageStream ist ein OpenShift-Objekt, das einen oder mehrere Tags trackt und auf tatsächlichen Image-Inhalt zeigt — oft in der internen OpenShift-Registry, manchmal in einer externen. Deployments und BuildConfigs können imagestream-name:tag statt einer langen Registry-URL referenzieren.

Vorteile in der Praxis:

  • Stabile Namen im Projektweb:latest im YAML meint den ImageStream des Projekts, nicht „was :latest heute auf Docker Hub bedeutet“.
  • Rollouts auslösen — wenn ein Tag neuen Inhalt bekommt, kann OpenShift DeploymentConfigs (Legacy) triggern oder ähnliches Verhalten mit Deployments und Image-Change-Triggern verdrahten.
  • Promotion zwischen Umgebungen — ImageStreamTag von Staging nach Production importieren oder retaggen, ohne Anwendungs-Manifeste umzuschreiben.

ImageStreams ersetzen keine Registries. Sie sind eine Abstraktions- und Tracking-Schicht über Registry-Speicher.

Prüfen, was im Projekt existiert:

oc get imagestream
oc describe imagestream web
oc get istag

Die istag-Kurzform listet ImageStreamTags — die konkreten Tag-Einträge, die in Manifesten referenziert werden.

ImageStream-Grundlagen

Ein ImageStream hält Metadaten und eine Historie von Tags. Jeder Tag dokumentiert, welche Image-ID (Digest) er gerade referenziert.

Tags erscheinen, wenn ein Build fertig ist oder ein Image importiert wird:

apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  name: web
  namespace: shop-staging
spec:
  tags:
    - name: "1.2.0"
      from:
        kind: DockerImage
        name: "registry.example.com/shop/web:1.2.0"
      importPolicy:
        scheduled: true
      referencePolicy:
        type: Source

Tag-Namen und Image-Referenzen mit Doppelpunkten in Anführungszeichen setzen — YAML-Parser behandeln Doppelpunkte sensibel.

Externen Tag in den ImageStream des Projekts importieren:

oc import-image web:1.2.0 --from="registry.example.com/shop/web:1.2.0" --confirm
oc tag registry.example.com/shop/web:1.2.0 web:latest --import

Deployments referenzieren den ImageStream über die interne Namenskonvention:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: shop-staging
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: "image-registry.openshift-image-registry.svc:5000/shop-staging/web:latest"
          ports:
            - containerPort: 8080

In der Praxis setzen oc new-app und BuildConfigs die korrekte Pull-Spec. Handgeschriebenes YAML sollte dem entsprechen, was oc describe deployment auf einem funktionierenden Cluster zeigt.

Prüfen, ob ein Tag aufgelöst ist:

oc get imagestreamtag web:latest -o yaml
oc describe imagestreamtag web:latest

Hat der Tag kein Image, scheiterten Builds oder Imports — das Deployment scheitert später mit Pull-Fehlern.

BuildConfig im Überblick

Eine BuildConfig beschreibt wie Image-Inhalt für einen ImageStream-Tag entsteht: Quelle, Strategie, Output-Ziel und Trigger.

Listen und inspizieren:

oc get buildconfig
oc describe buildconfig web
oc get builds
oc logs -f build/web-3

Jeder Build ist eine Ausführung einer BuildConfig — vergleichbar mit einem Job für Image-Produktion.

Typische BuildConfig-Form:

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: web
  namespace: shop-staging
spec:
  source:
    type: Git
    git:
      uri: "https://github.com/example/shop-web.git"
      ref: main
  strategy:
    type: Source
    sourceStrategy:
      from:
        kind: ImageStreamTag
        name: "nodejs-20:latest"
        namespace: openshift
      env:
        - name: NPM_CONFIG_LOGLEVEL
          value: warn
  output:
    to:
      kind: ImageStreamTag
      name: "web:latest"
  triggers:
    - type: ConfigChange
    - type: GitHub
      github:
        secretReference:
          name: web-github-secret

Wichtige Felder:

  • source — Git, Binary oder Dockerfile-Kontext.
  • strategy — Source (S2I), Docker oder Custom.
  • output.to — welcher ImageStreamTag das gebaute Image erhält.
  • triggers — Rebuild bei Git-Push, Image-Change oder Config-Change.

Build manuell starten:

oc start-build web
oc start-build web --from-dir=.
oc start-build web --commit main

Erfolg oder Fehler abwarten, bevor Deployments rollen sollen:

oc logs -f build/web-4
oc describe build web-4

Fehlgeschlagene Builds lassen alte Tags stehen. Das ist sicherer als kaputte Images auszurollen — verwirrend, wenn man annimmt, ein Git-Push habe den Cluster schon aktualisiert.

S2I vs. Dockerfile-Builds

OpenShift unterstützt mehrere Build-Strategien. Am häufigsten sind Source-to-Image (S2I) und Docker.

S2I (Source-Strategie) — OpenShift injiziert Quellcode in ein Builder-Image, das ein Runtime-Image zusammenbaut (Node, Python, Java usw.). Code und wenige Umgebungsvariablen reichen; die Plattform wendet Konventionen an.

Wann S2I passt:

  • Das Team will standardisierte, gepflegte Builder-Images aus dem openshift-Namespace.
  • Anwendungen folgen Framework-Defaults ohne exotische OS-Pakete.
  • Betrieb will keine Dockerfiles für jeden Microservice pflegen.

Beispiel S2I-Strategie-Abschnitt:

strategy:
  type: Source
  sourceStrategy:
    from:
      kind: ImageStreamTag
      name: "python-311:latest"
      namespace: openshift
    env:
      - name: FLASK_APP
        value: app.py

Docker-Strategie — OpenShift führt docker build (oder Äquivalent) gegen ein Dockerfile im Git-Kontext oder hochgeladenem Verzeichnis aus.

Wann Dockerfile-Builds passen:

  • Die App braucht eigene Base-Layer, Pakete oder Multi-Stage-Builds, die Standard-Builder nicht abdecken.
  • Security oder Compliance verlangt ein geprüftes Dockerfile als Vertrag.
  • Dasselbe Dockerfile baut bereits in CI und soll identisch auf dem Cluster laufen.

Beispiel Docker-Strategie-Abschnitt:

strategy:
  type: Docker
  dockerStrategy:
    dockerfilePath: Dockerfile
    buildArgs:
      - name: HTTP_PROXY
        value: "http://proxy.example.com:8080"

Schnell auf einem laufenden Cluster vergleichen:

oc describe buildconfig web | grep -A5 "Strategy"
oc get build web-5 -o yaml | grep -A10 strategy

Keine Strategie ist „OpenShift-er“. S2I tauscht Flexibilität gegen Geschwindigkeit und Konsistenz. Dockerfile tauscht Konvention gegen Kontrolle. Viele Plattformen nutzen Dockerfile in CI, Import im Cluster und überspringen beides auf OpenShift.

Scheitert ein Build, zuerst oc describe build und oc logs build/... lesen, bevor man Deployment-ImagePullBackOff jagt. Fehlende Git-Secrets, fehlende Builder-ImageStreamTags in openshift, falsche Dockerfile-Pfade und OOM beim Kompilieren sind die üblichen Verdächtigen.

Wann In-Cluster-Builds wegfallen

Nicht jede OpenShift-Installation braucht BuildConfigs. Cluster-Builds überspringen, wenn:

  • CI bereits baut, scannt, signiert und pusht in eine Registry, der der Cluster vertraut.
  • Build-Reproduzierbarkeit zur Pipeline außerhalb OpenShift passen muss — eine Quelle der Wahrheit für Tags und Digests.
  • Ressourcen-Kosten — Kompilate auf Cluster-Nodes konkurrieren mit App-Workloads; große Monorepos verstärken das.
  • Compliance — nur freigegebene Pipelines dürfen Release-Artefakte erzeugen.

Alternatives Muster:

  1. CI pusht registry.example.com/shop/web:1.2.0.
  2. OpenShift importiert oder taggt das Image in einen ImageStream (optional, aber nützlich für stabile In-Cluster-Namen).
  3. Deployment referenziert ImageStream-Tag oder externen Digest direkt.

Import ohne Build:

oc tag registry.example.com/shop/web:1.2.0 web:1.2.0 --import
oc set image deployment/web web=web:1.2.0

Oder externes Image per Digest für Unveränderlichkeit:

containers:
  - name: web
    image: "registry.example.com/shop/web@sha256:abc123def456..."

ImageStreams helfen weiter als Dokumentation und Promotion-Griffe, auch ohne BuildConfig. Sie sind nicht nur Build-Output.

Pull aus externer Registry braucht Pull-Secrets am richtigen Service Account:

oc create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=puller \
  --docker-password='TOKEN' \
  --docker-email=ops@example.com
oc secrets link default regcred --for=pull

ImagePullBackOff nach erfolgreichem CI-Build bedeutet meist fehlendes Pull-Secret — kein schlechtes Dockerfile. Standard-Frameworks passen oft zu S2I; eigene OS-Layer zu Dockerfile oder CI. Reife Pipelines pushen oft nach Harbor oder ECR und importieren Tags in ImageStreams für stabile In-Cluster-Namen.

Abschluss

ImageStreams und BuildConfigs sind OpenShifts Weg, Images in einem Projekt zu benennen, zu bauen und zu tracken. Sie glänzen, wenn Teams Git-Push zu Image zu Rollout wollen, ohne zuerst eine separate Pipeline zusammenzubauen. Sie sind optional, wenn reifes CI Build, Scan und Push schon besitzt. Beide Pfade zu verstehen — Build auf dem Cluster versus Import von außen — verhindert Kampf mit der Plattform oder doppelte Arbeit. Mit einem Service, einem ImageStream-Tag und einem klaren Owner, wer das Image produziert, anfangen. Der Rest des Modells skaliert von dort.