← Übersicht  ·  Skripte & Dateien  ·  OpenShift · Build · Rollout

Build bis Rollout: S2I, ImageStream und Deployment

Du baust eine winzige Node.js-Anwendung aus lokalen Quellen mit Source-to-Image, verfolgst das Ergebnis bis zum Image-Digest und lässt einen OpenShift-Image-Trigger automatisch ein neues ReplicaSet ausrollen. Danach beweist du den Kubernetes-Weg für Konfigurationsänderungen.

Stand: 5. September 2026OKD / OCP 4.xAtlas B1, C3, C6ca. 45 Minuten

1 Die ganze Kette

Vier Übergaben verbinden Quelltext mit laufenden Pods. An jeder Übergabe entsteht ein anderer überprüfbarer Zustand.

Quelles2i-src/
liegt nur auf deinem Laptop
BuildBuildConfig
erzeugt einen Build und Build-Pod
ImageImageStreamTag
zeigt auf einen unveränderlichen Digest
RolloutDeployment
erzeugt ReplicaSet und Pods

Source-to-Image, kurz S2I, verbindet deinen Quelltext mit einem Builder-Image. Das Builder-Image kennt die Sprache und enthält Skripte zum Bauen und Starten. Der fertige Container enthält keine besondere S2I-Laufzeit.

Die zwei Signale: Ein neuer Image-Digest beweist den Build. Ein neues ReplicaSet beweist den Rollout. Ein neuer Pod allein reicht als Erklärung nicht, weil auch ein gelöschter Pod vom bestehenden ReplicaSet ersetzt werden kann.

2 Die Objekte einordnen

BegriffAufgabeEntsteht wie
BuildConfigdauerhafte Bauanweisung mit Quelle, Strategie, Builder und Ausgabezieldu legst sie an
Buildein konkreter Lauf dieser BauanweisungOpenShift generiert ihn
ImageStreamTagOpenShift-Zeiger wie hello-s2i:latest mit Historie zu Image-Digestsdu definierst den Stream, der Build aktualisiert den Tag
Image-Triggerbeobachtet den Tag und schreibt den neuen Digest in die Pod-Vorlageoc set triggers setzt eine Annotation
Deploymentbeschreibt Rollout-Strategie und gewünschte Pod-Vorlagedu legst es an
ReplicaSethält eine bestimmte Version der Pod-Vorlage in gewünschter Anzahl am Lebendas Deployment generiert es

3 Cluster und APIs prüfen

Du brauchst einen angemeldeten Benutzer mit Recht auf ein eigenes Projekt. Die interne Registry muss verfügbar sein.

Laptop · PowerShell
oc whoami
oc get co image-registry
oc get image.config.openshift.io cluster -o yaml
oc api-resources | Select-String -Pattern 'BuildConfig|ImageStream|Deployment'
Bash-Variante anzeigen
Laptop · Bash
oc whoami
oc get co image-registry
oc get image.config.openshift.io cluster -o yaml
oc api-resources | grep -E 'BuildConfig|ImageStream|Deployment'

Abbruchbedingung: Wenn image-registry nicht Available=True ist, zuerst den Registry-Betrieb klären. Der Build kann sonst erfolgreich kompilieren und beim Push des Ergebnisses trotzdem scheitern.

4 Lokalen Quelltext anlegen

Die drei Dateien bilden eine HTTP-Anwendung ohne zusätzliche npm-Pakete. S2I erkennt package.json und startet später npm start.

Laptop · PowerShell · legt lokale Lab-Dateien an
New-Item -ItemType Directory -Force -Path .\s2i-src | Out-Null

@'
{"name":"s2i-rollout-lab","version":"1.0.0","scripts":{"start":"node server.js"}}
'@ | Set-Content -LiteralPath .\s2i-src\package.json -Encoding utf8

@'
const http = require("http");
const fs = require("fs");
const version = fs.readFileSync("version.txt", "utf8").trim();
const port = Number(process.env.PORT || 8080);

http.createServer((request, response) => {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(`hello ${version}\n`);
}).listen(port, "0.0.0.0");
'@ | Set-Content -LiteralPath .\s2i-src\server.js -Encoding utf8

'v1' | Set-Content -LiteralPath .\s2i-src\version.txt -Encoding utf8
Get-ChildItem -LiteralPath .\s2i-src
Bash-Variante anzeigen
Laptop · Bash · legt lokale Lab-Dateien an
mkdir -p ./s2i-src

cat > ./s2i-src/package.json <<'EOF'
{"name":"s2i-rollout-lab","version":"1.0.0","scripts":{"start":"node server.js"}}
EOF

cat > ./s2i-src/server.js <<'EOF'
const http = require("http");
const fs = require("fs");
const version = fs.readFileSync("version.txt", "utf8").trim();
const port = Number(process.env.PORT || 8080);

http.createServer((request, response) => {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(`hello ${version}\n`);
}).listen(port, "0.0.0.0");
EOF

printf 'v1\n' > ./s2i-src/version.txt
find ./s2i-src -maxdepth 1 -type f -print

s2i-src/package.json, s2i-src/server.js und s2i-src/version.txt legst du an. Das Verzeichnis ist als lokales Lab-Artefakt in .gitignore ausgeschlossen.

5 ImageStream und BuildConfig anwenden

Die Quelle ist vom Typ Binary. Sie wird beim Start des Builds übertragen und nicht dauerhaft in der BuildConfig gespeichert.

Laptop · PowerShell
oc new-project build-rollout-lab

@'
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  name: hello-s2i
---
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: hello-s2i
spec:
  runPolicy: Serial
  source:
    type: Binary
  strategy:
    type: Source
    sourceStrategy:
      from:
        kind: DockerImage
        name: registry.access.redhat.com/ubi9/nodejs-20:latest
  output:
    to:
      kind: ImageStreamTag
      name: hello-s2i:latest
'@ | oc apply -f -
Bash-Variante anzeigen
Laptop · Bash
oc new-project build-rollout-lab

oc apply -f - <<'EOF'
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  name: hello-s2i
---
apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: hello-s2i
spec:
  runPolicy: Serial
  source:
    type: Binary
  strategy:
    type: Source
    sourceStrategy:
      from:
        kind: DockerImage
        name: registry.access.redhat.com/ubi9/nodejs-20:latest
  output:
    to:
      kind: ImageStreamTag
      name: hello-s2i:latest
EOF

Warum DockerImage beim Builder? Der Builder wird direkt aus der Red-Hat-Registry gezogen. Das Build-Ergebnis geht dagegen als ImageStreamTag in die integrierte OpenShift-Registry.

6 Den ersten S2I-Build verfolgen

S2I baut ein Image ohne Dockerfile, weil das Builder-Image die Verpackung schon kann. Es bringt zwei Skripte mit: assemble (baut, zur Build-Zeit) und run (startet, im Container). Der Gedanke: wer Java schreibt, soll kein Dockerfile pflegen – das Builder-Image kodiert die Best Practice.

Zwei Skripte im Builder-Image: assemble baut, run startet. Builder-Image z. B. ubi9/openjdk-17, ubi9/nodejs-20 assemble – Build-Zeit: kompilieren, Artefakt ablegen run – Laufzeit: die App starten (wird Entrypoint) save-artifacts – Cache retten (optional) usage – Hilfetext die Skripte kodieren die Best-Practice-Verpackung Red-Hat-Images respektieren beliebige UID (A7) eigene Skripte in .s2i/bin/ gewinnen über die des Images der S2I-Build-Ablauf 1 Builder-Image starten, Quellcode nach /tmp/src injizieren 2 assemble läuft: mvn package / npm ci && npm run build Artefakt an den Ort legen, den run erwartet (/deployments/app.jar) 3 den Container als neues Image committen, run als Entrypoint Umgebung: .s2i/environment oder env im BuildConfig lokal testen: s2i build . ubi9/openjdk-17 catalog (die s2i-CLI) debuggen: S2I_DEBUG=1, oc rsh in den Build-Pod Liberty-s2i: assemble legt das WAR nach /config/apps/ (Liberty-Zeichnung 10) Ergebnis ein gewöhnliches OCI-Image nichts S2I-spezifisches zur Laufzeit läuft überall, wie jedes andere Image Entrypoint ist das run-Skript landet als ImageStreamTag (C1) in der Registry (C5) Größe: enthält das ganze JDK – darum der Chained Build (unten) docker-image://-Referenz auch für ein reines Deployment inkrementeller Build save-artifacts schreibt den Dependency-Cache (~/.m2, node_modules) als tar nach stdout S2I stellt ihn im nächsten Build unter /tmp/artifacts wieder her assemble nutzt den Cache → keine erneuten Downloads aktivieren: strategy.sourceStrategy.incremental: true im BuildConfig spart bei Java-Builds Minuten – füllt aber das Cache-Layer und muss gepflegt werden Chained Build – kleines Laufzeit-Image Build-Stufe: volles JDK + Maven → produziert nur das Artefakt (die JAR) Runtime-Stufe: nur JRE, kopiert das Artefakt hinein oc new-build ... --to catalog-builder, dann oc new-build --source-image=catalog-builder ... --to catalog = dasselbe wie ein Docker-Multi-Stage-Build, nur mit S2I-Bausteinen der Gedanke: wer Java oder Node schreibt, soll kein Dockerfile pflegen – das Builder-Image kodiert Base-Image, Verpackung, Nicht-Root, Health-Defaults Merksatz: assemble = bauen (einmal), run = starten (jeder Pod), Ergebnis = normales Image wann oc new-app das alles automatisch aufsetzt: C4 OCP-Unterschied: identisch – S2I ist ein eigenes Projekt (die s2i-CLI läuft auch ohne Cluster), OpenShift ruft es über die BuildConfig auf.
Das Builder-Image kann die Verpackung schon. Es bringt assemble (baut zur Build-Zeit) und run (startet im Container) mit. S2I injiziert den Quellcode, lässt assemble laufen und committet den Container als neues Image mit run als Entrypoint. save-artifacts rettet den Dependency-Cache in den nächsten Build. Eigene Skripte in .s2i/bin/ gewinnen. Das Ergebnis ist ein ganz normales OCI-Image.
  • das Builder-Image bringt zwei Skripte mit: assemble (baut, zur Build-Zeit) und run (startet, im Container – wird der Entrypoint)
  • assemble: mvn package / npm run build anwerfen und das Ergebnis an den Ort legen, den run erwartet
  • der Ablauf: Builder starten → Quellcode nach /tmp/srcassemble → Container als neues Image committen mit run als Entrypoint
  • inkrementeller Build: save-artifacts hebt den ~/.m2-/node_modules-Cache in die nächste Runde – incremental: true im BuildConfig
  • eigene Skripte im Repo unter .s2i/bin/ überschreiben die des Images, .s2i/environment für Env-Variablen
  • Chained Build: Build-Stufe mit vollem JDK produziert nur das Artefakt, Runtime-Stufe mit nur JRE kopiert es hinein – kleines Laufzeit-Image, wie ein mehrstufiges Dockerfile
  • der Gedanke: wer Java schreibt, soll kein Dockerfile pflegen – das Builder-Image kodiert Base-Image, Verpackung, Nicht-Root
  • Red-Hat-Builder-Images (ubi9/openjdk-17, ubi9/nodejs-20) respektieren beliebige UID (A7)
  • lokal testen mit der s2i-CLI: s2i build . ubi9/openjdk-17 catalog – debuggen mit S2I_DEBUG=1 oder oc rsh
  • Was-wäre-wenn für die Bibliothek: ein nodejs-S2I für library-frontend (Angular-Build → statisches nginx) würde das zweistufige Dockerfile ersparen – heute baut die Pipeline das Frontend selbst (Node 22 im Container)
  • Liberty-s2i: assemble legt das WAR nach /config/apps/ (Liberty-Gedankenspiel Zeichnung 10)
  • das Ergebnis ist ein gewöhnliches OCI-Image – nichts S2I-spezifisches zur Laufzeit, läuft überall
  • OCP-Unterschied: identisch – S2I ist ein eigenes Projekt, OpenShift ruft es über die BuildConfig auf
  • S2I von innen durchspielen: Build bis Rollout – lokale Binärquelle bauen und assemble, run, Build-Pod sowie Image-Digest auseinanderhalten
Laptop · PowerShell
oc start-build hello-s2i --from-dir .\s2i-src --follow
oc get build,pod,imagestream,imagestreamtag
oc describe build hello-s2i-1
oc get istag hello-s2i:latest -o jsonpath='{.image.dockerImageReference}{"\n"}'
Bash-Variante anzeigen
Laptop · Bash
oc start-build hello-s2i --from-dir ./s2i-src --follow
oc get build,pod,imagestream,imagestreamtag
oc describe build hello-s2i-1
oc get istag hello-s2i:latest -o jsonpath='{.image.dockerImageReference}{"\n"}'
assembleDas Skript aus dem Builder-Image übernimmt den Quelltext, erkennt Node.js und bereitet das Laufzeit-Image vor.
runDieses Skript wird zum Startbefehl des fertigen Images und ruft für dieses Projekt npm start auf.
BuildahOpenShift lässt aus den S2I-Schritten ein Container-Image bauen und schiebt es in die integrierte Registry.
Digesthello-s2i:latest zeigt jetzt auf einen unveränderlichen Inhalt wie sha256:….

Die Skripte assemble und run sind wichtige Bestandteile des Builder-Images. Du legst sie in diesem Lab nicht an. Ein Projekt könnte sie unter .s2i/bin/ bewusst überschreiben.

7 Deployment, Service und Route anlegen

Das Deployment startet zunächst aus dem internen Registry-Namen. Danach bindest du es ausdrücklich an den ImageStreamTag.

Laptop · PowerShell oder Bash
oc create deployment hello-s2i --image=image-registry.openshift-image-registry.svc:5000/build-rollout-lab/hello-s2i:latest
oc set triggers deployment/hello-s2i --from-image=hello-s2i:latest -c hello-s2i
oc expose deployment hello-s2i --port=8080
oc expose service hello-s2i
oc rollout status deployment/hello-s2i --timeout=120s
oc get deployment,replicaset,pod -o wide
oc get route hello-s2i

Das Deployment besitzt das ReplicaSet über ownerReferences. Das ReplicaSet besitzt wiederum die Pods. Der Wert pod-template-hash verbindet jeden Pod mit genau der Vorlagenversion, aus der er entstand.

Laptop · nur lesen
oc get replicaset -l app=hello-s2i --sort-by=.metadata.creationTimestamp
oc get pod -l app=hello-s2i -o jsonpath='{range .items[*]}{.metadata.name}{" <- "}{.metadata.ownerReferences[0].kind}{"/"}{.metadata.ownerReferences[0].name}{"\n"}{end}'
oc get replicaset -l app=hello-s2i -o jsonpath='{range .items[*]}{.metadata.name}{" <- "}{.metadata.ownerReferences[0].kind}{"/"}{.metadata.ownerReferences[0].name}{"\n"}{end}'

8 Den Image-Trigger lesen

Bei einem Kubernetes-Deployment speichert OpenShift den Trigger in metadata.annotations. Er ist kein Feld der Kubernetes-Deployment-API.

Reines Kubernetes rollt nur aus, wenn sich die Pod-Vorlage ändert. Ein neuer Push unter demselben Tag ändert sie nicht – also passiert nichts, und du suchst den Fehler im Code. Der OpenShift-Image-Trigger löst das: er trägt den neuen Digest in die Vorlage. ConfigChange meint die Vorlage selbst – nicht referenzierte ConfigMaps.

Ein Rollout passiert nur, wenn sich die Pod-Vorlage ändert. reines Kubernetes – die Falle Pod-Vorlage: image: catalog:latest du pushst catalog:latest neu → die Vorlage ist byte-identisch → kein neues ReplicaSet → nichts passiert der Fix ist gebaut, aber nicht ausgerollt du suchst den Fehler im Code – stundenlang Regel außerhalb OpenShift: nie :latest, immer ein Digest oder eine Version der OpenShift-Image-Trigger eine Annotation am Deployment: image.openshift.io/triggers: '[{"from":{"kind": "ImageStreamTag","name":"catalog:latest"},"fieldPath": "spec.template.spec.containers[0].image"}]' der openshift-controller-manager beobachtet den Tag neuer Digest → er patcht die Vorlage: image: catalog@sha256:<neuer-digest> → Vorlage ändert sich → neues ReplicaSet → Rollout oc set triggers deploy/catalog --from-image=catalog:latest -c catalog ConfigChange eine Änderung an der Pod-Vorlage selbst löst aus beim Deployment: implizit (jede Vorlagenänderung) beim DeploymentConfig: type: ConfigChange deklarieren (B2) Grenze: meint die Vorlage, nicht referenzierte ConfigMaps oder Secrets gemountete ConfigMap geändert → Pod rollt nicht (B8) Abhilfe: checksum/config-Annotation (Helm) oder ein Reloader-Operator der universelle Weg oc rollout restart deploy/catalog setzt eine restartedAt-Annotation → Vorlagenänderung → Rollout liest dabei ConfigMaps/Secrets neu – der Ersatz für den fehlenden Trigger oc set triggers deploy/catalog --manual pausiert den Image-Trigger nicht verwechseln image.openshift.io/triggers = am Deployment (löst einen Rollout aus) BuildConfig-Trigger = am BuildConfig (löst einen Build aus, C2) Kette: Push → ImageStream-Digest (C1) → Trigger → Rollout (B1) Bibliothek: der Image-Trigger am Deployment je Dienst, gebaut wird außerhalb Merksatz: ohne Trigger und ohne wechselnden Tag läuft der alte Container weiter – der Image-Trigger schreibt den Digest, dann rollt es ConfigChange = Vorlage, nicht die referenzierten ConfigMaps/Secrets – dafür checksum/config oder oc rollout restart OCP-Unterschied: der Image-Trigger ist OpenShift-eigen – reines Kubernetes hat kein Äquivalent (nur externe Tools wie Keel oder Argo Image Updater).
Der Digest muss in die Vorlage. Reines Kubernetes rollt nur bei einer Änderung der Pod-Vorlage – ein erneuter :latest-Push ändert sie nicht, also passiert nichts. Die Annotation image.openshift.io/triggers lässt den openshift-controller-manager den ImageStreamTag beobachten und bei neuem Digest die Vorlage patchen → Rollout. ConfigChange meint die Vorlage selbst, nicht referenzierte ConfigMaps – dafür checksum/config oder oc rollout restart.
  • reines Kubernetes: die Pod-Vorlage sagt image: catalog:latest – ein erneuter Push unter demselben Tag ändert die Vorlage nicht, nichts passiert
  • der OpenShift-Image-Trigger ist eine Annotation am Deployment: image.openshift.io/triggers mit einem ImageStreamTag und einem fieldPath
  • der openshift-controller-manager beobachtet den Tag – neuer Digest → er patcht die Vorlage auf catalog@sha256:<digest> → neues ReplicaSet → Rollout
  • hinzufügen: oc set triggers deploy/catalog --from-image=catalog:latest -c catalog--manual pausiert ihn
  • DeploymentConfig hat denselben Mechanismus eingebaut als spec.triggers[].type: ImageChange (B2)
  • ConfigChange: eine Änderung an der Pod-Vorlage selbst löst aus – beim Deployment implizit, beim DeploymentConfig muss man type: ConfigChange deklarieren
  • wichtige Grenze: ConfigChange meint die Vorlage, nicht referenzierte ConfigMaps/Secrets – eine gemountete ConfigMap zu ändern rollt den Pod nicht (B8)
  • Abhilfe: checksum/config-Annotation (Helm rollt), oc rollout restart deploy/catalog, oder ein Reloader-Operator
  • oc rollout restart setzt eine restartedAt-Annotation → Vorlagenänderung → Rollout, und liest dabei ConfigMaps/Secrets neu
  • nicht verwechseln: image.openshift.io/triggers am Deployment (löst Rollout) vs BuildConfig-Trigger am BuildConfig (löst Build, C2)
  • die Trigger-Kette: Push → ImageStream-Digest (C1) → Trigger → neues ReplicaSet → Rollout (B1)
  • Bibliothek: kein Image-Trigger. Jenkins ruft helm upgrade --set image.tag=$GIT_SHA je Dienst – der Tag-Wert in der Pod-Vorlage ändert sich, also rollt Kubernetes ganz normal aus. Der Trigger-Weg wäre die Alternative, wenn nicht die CI den Tag setzt
  • OCP-Unterschied: der Image-Trigger ist OpenShift-eigen – reines Kubernetes hat kein Äquivalent (nur externe Tools wie Argo Image Updater)
  • beide Triggerwege durchspielen: Build bis Rollout – erst einen neuen Image-Digest automatisch ausrollen, danach eine Pod-Vorlagenänderung als ConfigChange-Wirkung beweisen
Laptop · PowerShell oder Bash · nur lesen
oc set triggers deployment/hello-s2i
oc get deployment hello-s2i -o jsonpath='{.metadata.annotations.image\.openshift\.io/triggers}{"\n"}'
oc get deployment hello-s2i -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'

Die Annotation nennt den beobachteten ImageStreamTag, den Container und den Pfad zum Image-Feld. Sobald sich der Digest des Tags ändert, schreibt OpenShift die neue aufgelöste Image-Referenz in spec.template. Kubernetes erkennt eine neue Pod-Vorlage und erzeugt das nächste ReplicaSet.

9 Einen automatischen Rollout beweisen

Terminal 1 beobachtet die Kette

Laptop · PowerShell oder Bash · laufen lassen
oc get build,deployment,replicaset,pod --watch

Terminal 2 baut Version 2

Laptop · PowerShell
$digestBefore = oc get istag hello-s2i:latest -o jsonpath='{.image.metadata.name}'
'v2' | Set-Content -LiteralPath .\s2i-src\version.txt -Encoding utf8
oc start-build hello-s2i --from-dir .\s2i-src --follow
oc rollout status deployment/hello-s2i --timeout=120s
$digestAfter = oc get istag hello-s2i:latest -o jsonpath='{.image.metadata.name}'
"Digest vorher: $digestBefore"
"Digest nachher: $digestAfter"
oc get replicaset -l app=hello-s2i --sort-by=.metadata.creationTimestamp
$hostName = oc get route hello-s2i -o jsonpath='{.spec.host}'
curl.exe "http://$hostName"
Bash-Variante anzeigen
Laptop · Bash
digest_before=$(oc get istag hello-s2i:latest -o jsonpath='{.image.metadata.name}')
printf 'v2\n' > ./s2i-src/version.txt
oc start-build hello-s2i --from-dir ./s2i-src --follow
oc rollout status deployment/hello-s2i --timeout=120s
digest_after=$(oc get istag hello-s2i:latest -o jsonpath='{.image.metadata.name}')
printf 'Digest vorher: %s\nDigest nachher: %s\n' "$digest_before" "$digest_after"
oc get replicaset -l app=hello-s2i --sort-by=.metadata.creationTimestamp
host_name=$(oc get route hello-s2i -o jsonpath='{.spec.host}')
curl "http://$host_name"

Erwartung: Die beiden Digests unterscheiden sich, ein zweites ReplicaSet erscheint und der HTTP-Aufruf antwortet mit hello v2. Damit sind Build, Tag-Fortschritt, Trigger und Rollout getrennt belegt.

10 ConfigChange richtig einordnen

Ein Kubernetes-Deployment braucht keinen eigenen ConfigChange-Trigger. Jede Änderung an seiner Pod-Vorlage erzeugt von sich aus einen neuen Rollout.

Laptop · ändert die Pod-Vorlage
oc set env deployment/hello-s2i LAB_CONFIG=v2
oc rollout status deployment/hello-s2i --timeout=120s
oc get replicaset -l app=hello-s2i --sort-by=.metadata.creationTimestamp
oc get deployment hello-s2i -o jsonpath='{.spec.template.spec.containers[0].env}{"\n"}'

oc set env ändert spec.template. Der Hash der Vorlage ändert sich und das Deployment erzeugt ein weiteres ReplicaSet. Genau das meint die ConfigChange-Wirkung bei einem Kubernetes-Deployment.

Wichtige Grenze: Wenn du nur den Inhalt einer referenzierten ConfigMap oder eines Secrets änderst, ändert sich die Pod-Vorlage nicht. Ein automatischer Rollout braucht dann zum Beispiel eine Prüfsummen-Annotation, einen Reloader-Controller oder bewusst oc rollout restart deployment/hello-s2i.

DeploymentConfig: Das ältere OpenShift-Objekt deklarierte ConfigChange als eigenen Trigger. DeploymentConfig ist seit OpenShift 4.14 veraltet. Für neue Anwendungen ist das Kubernetes-Deployment der normale Weg.

Image-Trigger gezielt entfernen
Laptop · optional
oc set triggers deployment/hello-s2i --from-image=hello-s2i:latest -c hello-s2i --remove
oc set triggers deployment/hello-s2i
oc get deployment hello-s2i -o jsonpath='{.metadata.annotations.image\.openshift\.io/triggers}{"\n"}'

Danach kann ein neuer Build den Tag aktualisieren, ohne dieses Deployment automatisch zu ändern. Ein expliziter Image-Wechsel oder ein erneutes Hinzufügen des Triggers bleibt möglich.

11 Dateien, Ressourcen und Besitz

ArtefaktKategorieUmgang
s2i-src/package.json, server.js, version.txtdu legst anlokale Binärquelle dieses Labs, nicht committen
ImageStream, BuildConfig, Deployment, Service, Routedu legst andeklarierter Sollzustand im Lab-Projekt
assemble und runwichtigkommen aus dem Builder-Image, nur bei absichtlicher Anpassung überschreiben
Build, Build-Pod, Image-Digest, ReplicaSet, Anwendungs-Podwird generiertbeobachten und diagnostizieren, nicht von Hand pflegen
integrierter Registry-Inhaltwird generiertliegt im Cluster-Storage und wird über Image-Pruning verwaltet

12 Fehler an der Übergabe eingrenzen

Fehlerbildzuerst prüfentypische Ursache
Build startet nichtoc describe bc/hello-s2ifehlende Binärquelle oder keine Berechtigung
Build scheitert beim Pushoc logs build/hello-s2i-1 und Registry-Operatorinterne Registry oder ihr Storage nicht verfügbar
Tag hat neuen Digest, aber kein RolloutTrigger-Annotation und ContainernameTrigger fehlt, ist entfernt oder zeigt auf das falsche Feld
Neues ReplicaSet, Pod startet nichtoc describe pod -l app=hello-s2iImage-Pull, Scheduling, Security Context oder Prozessfehler
Route antwortet nichtService, EndpointSlice und ReadinessPort oder Selector passt nicht zum Pod

Reproduzierbarkeit: Ein Binary-Build speichert den übertragenen Quelltext nicht als Git-Referenz in der BuildConfig. Das ist für dieses Lernlabor praktisch, aber keine gute Produktions-Pipeline. Dort sollte die Quelle versioniert und der erzeugte Digest nachvollziehbar einem Commit zugeordnet sein.

13 Lab vollständig aufräumen

Laptop · PowerShell · löscht nur Lab-Projekt und lokale Lab-Quelle
oc delete project build-rollout-lab
Remove-Item -Recurse -LiteralPath .\s2i-src
Bash-Variante anzeigen
Laptop · Bash · löscht nur Lab-Projekt und lokale Lab-Quelle
oc delete project build-rollout-lab
rm -rf -- ./s2i-src

Das Projekt löscht die angelegten Ressourcen und die erzeugten Build- sowie Rollout-Objekte gemeinsam. Der Builder in der externen Registry und OpenShift-Systemkomponenten bleiben unverändert.

14 Lernkontrolle

  • Ich kann erklären, welche Arbeit assemble und run übernehmen.
  • Ich kann Tag und Digest unterscheiden und beide am ImageStreamTag finden.
  • Ich kann die Besitzkette Deployment, ReplicaSet und Pod über ownerReferences belegen.
  • Ich kann zeigen, wo OpenShift den Image-Trigger an einem Kubernetes-Deployment speichert.
  • Ich kann erklären, warum eine Pod-Vorlagenänderung rollt, eine externe ConfigMap-Änderung allein aber nicht.
  • Ich kann für Build- und Rolloutfehler die richtige Übergabe zuerst prüfen.