Voraussetzung: Zugang zum Namespace
library. Statt eines echten IBM-WAS-Images stehen generische
Red-Hat-UBI-Images stellvertretend für „die kommerzielle Middleware“
– die Kubernetes-Mechanik dahinter ist real und identisch. Schritt 2 liest nur
echte Cluster-Objekte, ohne sie zu ändern.
1 Die Lizenz-Schranke live provozieren
Kommerzielle Images prüfen im Entrypoint eine Lizenz-Variable, bevor der Server startet.
# der Entrypoint einer typischen kommerziellen Middleware, nachgebaut:
cat <<'EOF' | oc apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-concordia
namespace: library
spec:
replicas: 1
selector: { matchLabels: { app: demo-concordia } }
template:
metadata: { labels: { app: demo-concordia } }
spec:
containers:
- name: was
image: registry.access.redhat.com/ubi9/ubi-minimal:latest
command:
- sh
- -c
- |
if [ "$LICENSE" != "accept" ]; then
echo "You must accept the license terms to start this container.";
echo "Set LICENSE=accept in the environment.";
exit 1;
fi
echo "Lizenz akzeptiert, Server startet"; sleep 3600
EOF
oc get pods -n library -l app=demo-concordia -w
# CrashLoopBackOff, restartCount steigt
oc logs -n library -l app=demo-concordia
# "You must accept the license terms..." - die ganze Diagnose in einer Zeile
oc set env deployment/demo-concordia -n library LICENSE=accept
oc rollout status deployment/demo-concordia -n library
oc logs -n library -l app=demo-concordia
# "Lizenz akzeptiert, Server startet"
Genau das Symptom aus dem Atlas: CrashLoopBackOff mit steigendem
restartCount, die Readiness-Probe wird nie grün, und die ganze Diagnose
steht in einer Zeile oc logs. Der typische Irrweg ist, zuerst
einen Konfig- oder Portfehler zu suchen, statt zuerst in die Logs zu schauen.
Wer entscheidetDie Zustimmung ist rechtlich bindend – sie gehört explizit ins Deployment und ins Repo, nicht in ein Basis-Image gebacken. Betrieb, Einkauf oder Recht verantworten sie, nicht der Entwickler nebenbei.
2 Pull-Secret und Entitlement prüfen
Volle RHEL-Pakete brauchen zwei getrennte Dinge – ein Pull-Secret und ein Entitlement. UBI braucht keins von beidem.
# 1 - Pull-Secret: steht ein Eintrag fuer registry.redhat.io drin?
oc get secret pull-secret -n openshift-config \
-o jsonpath='{.data.\.dockerconfigjson}' | base64 -d \
| grep -o '"registry.redhat.io"' || echo "kein Eintrag fuer registry.redhat.io"
# 2 - Entitlement: liegen die Zertifikate im Cluster bereit?
oc get secret etc-pki-entitlement -n openshift-config-managed --ignore-not-found
oc get secret etc-pki-entitlement -n openshift-config-managed \
-o jsonpath='{.data}' 2>/dev/null | grep -o '"[^"]*\.pem"' || echo "kein Entitlement-Secret gefunden"
# zum Vergleich: ein reiner UBI-Pull braucht nichts davon
oc run demo-ubi-pull -n library --image=registry.access.redhat.com/ubi9/ubi-minimal:latest \
--restart=Never -- true
oc get pod demo-ubi-pull -n library
# Completed, ganz ohne Pull-Secret-Eintrag fuer registry.redhat.io
Fehlt der Pull-Secret-Eintrag, scheitert schon der FROM-Pull mit
unauthorized: authentication required. Fehlt der Entitlement-Mount, scheitert
erst der dnf-Schritt mit Repository ... is not available –
der Build kommt also weiter, bevor er bricht. Beide Fehler abzugrenzen von
manifest unknown (ein falscher Tag) und no space left
(Node-Disk, Schritt 3).
3 Image-Größen real vergleichen
Ein WAS-traditional-Image ist 1,5 bis 2,5 GB, Open Liberty 200 bis 400 MB, ein UBI-Fat-Jar rund 150 MB – ohne eigene Builds real nachprüfbar.
# reale, oeffentlich ziehbare Images vergleichen (kein Pull noetig, nur Metadaten):
for img in \
registry.access.redhat.com/ubi9/ubi-minimal:latest \
registry.access.redhat.com/ubi9/openjdk-17:latest \
icr.io/appcafe/open-liberty:full-java17-openj9-ubi
do
echo "== $img =="
oc image info "$img" 2>/dev/null | grep -E '^(Digest|Size)' \
|| skopeo inspect "docker://$img" 2>/dev/null | grep -E '"Digest"|"Size"' \
|| echo " (Registry nicht erreichbar von hier - Werte laut Hersteller-Doku pruefen)"
done
Der größte Hebel bleibt die Layer-Reihenfolge: Stabiles (OS,
Runtime, JDK) nach unten, den Code (WAR, Fat Jar) nach oben, Dependencies vor dem
App-Code kopieren – dann trifft ein Commit nur den obersten Layer. Ein
chained build mit einer ubi-minimal-Runtime-Stage
(build-kette-openshift.html)
lässt die Build-Werkzeuge draussen. Alte Tags räumt
skopeo delete oder der Registry-Pruner auf.
4 Die Admin-Konsole per passthrough erreichen
Eine Admin-Konsole mit selbstsigniertem Zertifikat bricht an einer
edge-Route – passthrough reicht TLS unverändert
durch.
# ein selbstsignierter HTTPS-Testserver, steht fuer die WAS-Admin-Konsole:
cat <<'EOF' | oc apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-console
namespace: library
spec:
replicas: 1
selector: { matchLabels: { app: demo-console } }
template:
metadata: { labels: { app: demo-console } }
spec:
containers:
- name: tls-testserver
image: registry.access.redhat.com/ubi9/ubi-minimal:latest
command:
- sh
- -c
- |
microdnf install -y openssl >/dev/null 2>&1
openssl req -x509 -newkey rsa:2048 -keyout /tmp/key.pem -out /tmp/cert.pem \
-days 1 -nodes -subj "/CN=demo-console" 2>/dev/null
openssl s_server -key /tmp/key.pem -cert /tmp/cert.pem -accept 9443 -www
ports:
- containerPort: 9443
EOF
oc expose deployment/demo-console -n library --port=9443 --target-port=9443
cat <<'EOF' | oc apply -f -
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: demo-console
namespace: library
spec:
to: { kind: Service, name: demo-console }
port: { targetPort: 9443 }
tls: { termination: passthrough }
EOF
HOST=$(oc get route demo-console -n library -o jsonpath='{.spec.host}')
curl -sk "https://$HOST/" | head -5
# openssl s_server antwortet mit dem eigenen, selbstsignierten Zertifikat -
# genau das, was eine edge-Route nicht durchlassen wuerde
passthrough kennt nur den Host aus der SNI, bevor entschlüsselt wird
– deshalb kann es kein Pfad-Routing. Der Nachteil bleibt derselbe wie bei jeder
Admin-Konsole mit mehreren Replicas: sie schreibt in einen laufenden Pod, die
Änderung ist beim nächsten Neustart weg
(H2/H3),
keine Historie, kein Review. Legitim nur für einen einmaligen Blick – mit einer
NetworkPolicy eingesperrt.
5 Typische Fallen
| Symptom | meist |
|---|---|
CrashLoopBackOff ohne offensichtlichen Grund | zuerst oc logs prüfen – oft steht die Ursache in der ersten Zeile (Lizenz, fehlende Env) |
unauthorized: authentication required beim FROM | Pull-Secret-Eintrag für registry.redhat.io fehlt |
Repository ... is not available beim dnf-Schritt | Entitlement-Mount fehlt, nicht das Pull-Secret |
| Route liefert einen Zertifikatsfehler für die Admin-Konsole | edge/reencrypt statt passthrough gewählt |
| Konsolen-Änderung nach Rollout wieder weg | erwartet – die Konsole schreibt in einen nicht-persistenten Pod, kein Ersatz für Konfiguration als Code |
6 Wie das Projekt es macht
Die Bibliothek nutzt keine kommerzielle Middleware – alle Images
bauen auf UBI, brauchen weder Lizenz-Variable noch Entitlement
(build-kette-openshift.html).
Diese Anleitung zeigt das Muster für den Fall, dass doch einmal ein kommerzielles
Image dazukommt: LICENSE=accept explizit im Deployment, dokumentiert im
Merge-Request – die Concordia-Referenz im Atlas macht genau das. Die eigenen
Build-Layer bleiben dabei immer auf UBI, nur das Basis-Image der Middleware selbst
braucht das Entitlement.