IBM Z DACH - Group home

Automatische s390x Container Image Bereitstellung

  
Wir arbeiten in unserem Umfeld täglich mit Container Images und täglich werden zig Milliarden davon gebaut, geprüft, teils öffentlich zur Verfügung gestellt und auf ihren Zielsystemen deployt. Fast alle bekannten Produkte stellen freundlicherweise ihre Images direkt in unterschiedlichen Varianten zur Verfügung. Wie PostgreSQL, welches von amd64 über arm64v8 und ppc64le bis zur s390x alle weitverbreiteten Architekturen abdeckt. Wir können uns frei bedienen und direkt loslegen. Aber was ist, wenn ein Image mal nicht für s390x – also für die IBM Z Platform wie die IBM z16 und IBM LinuxONE zur Verfügung steht? Wie kann ich für diese Systeme Container Images zur Verfügung stellen und was ist, wenn ich nur ein Image wie Grafana habe – dieses aber noch nicht für s390x existiert? Auf diese Fragen sind wir gestoßen und haben uns deshalb auf den Weg gemacht, darauf Antworten zu finden.

Konzept

Wir, das sind Carlo Bongiovanni, Cayo Moraes, @Steffen Herzog und @Thomas Schwärzl, waren uns schnell einig, wie wir diese Herausforderung lösen möchten. Natürlich mit CloudNative Werkzeugen und selbstverständlich so automatisiert, dass wir im Idealfall nicht ständig etwas manuell anpassen müssen.

"Am besten wäre, wir geben einer Pipeline über einen Trigger ein Image als Input und sie gibt uns ein fertiges s390x Image in die Registry aus ohne, dass wir etwas manuell anpassen müssen."

​​​
Unsere Erfahrung hat uns dabei bereits gesagt, dass das nicht "so mal kurz" gemacht ist und wir sicher auf ein einige Hürden treffen werden. Prinzipiell ist es möglich, Container Images von einer Architektur in eine andere zu konvertieren. Es hängt jedoch von einigen Faktoren ab.

Ein Ansatz zum Konvertieren von Container Images von einer Architektur in eine andere ist, die Anwendung in einer Umgebung der Zielarchitektur neu zu bauen und das Ergebnis als neues Image zu packen. Dies funktioniert jedoch nur, wenn die Anwendung quelloffen und portabel ist und alle Abhängigkeiten auf der Zielarchitektur verfügbar sind.

Ein anderer Ansatz besteht darin, das Image in eine virtuelle Umgebung der Zielarchitektur zu emulieren. Das kann jedoch dazu führen, dass das Image langsamer wird und möglicherweise nicht alle Funktionen unterstützt.

Es gibt auch spezielle Tools wie "qemu-user-static" welche es durch Emulation ermöglichen, Container Images von einer Architektur auf einer anderen auszuführen. Jedoch ist dieses Vorgehen nicht für produktive Umgebungen geeignet.

Wir haben uns dazu entschlossen, die erste Variante, sprich das Erstellen von neuen Images mit quelloffener Software durchzuführen. Wir erstellten uns kurzerhand eine Architekturzeichnung, notierten unser Ziel und definierten neben den Proof of Concept (POC) Bedingungen auch die ersten Tools, welche wir für unseren POC verwenden wollen. Neben einem Red Hat OpenShift Container Platform Cluster auf IBM Z, haben wir uns für Tekton als Pipeline Engine, buildah zum Bauen von Images, sowie Skopeo für das Kopieren und Ablegen der Container Images innerhalb der OpenShift Registry entschieden. Als Testimage haben wir uns für die Blogging Platform Ghost sowie Elasticsearch, entschieden. Nachfolgend beschreiben wir, was wir bisher umgesetzt haben und welche nächsten Schritte wir angehen möchten.

Umsetzung

Wie erwähnt haben wir uns für Tekton als Pipeline Engine entschieden und die einzelnen Schritte definiert, welche die Pipeline in unserem POC durchlaufen soll.

Die geplanten Pipeline Schritte


Wir verwenden ein wenig komplexes Git Repository Design, ohne im ersten Schritt die Versionierung und zukünftiges Berechtigungsmanagement zu berücksichtigen. In diesem Git Repository befindet sich je Image ein Ordner, in welchem mindestens ein Dockerfile, zusammen mit weiteren für den Bau des Images benötigten Dateien wie der entrypoint.sh oder den Sourcen, enthalten ist.

Bei einer Änderung des Git Repository durch einen git commit wird eine Webhook ausgelöst, welche die Tekton Pipeline im OpenShift Cluster auf der IBM Z aktiviert.

Die Tekton Pipeline selbst ist für den POC ebenfalls auf das notwendigste reduziert. Das Pullen der Sourcen und das Bauen mit anschließendem Ablegen des Images. Nach einem erfolgreichen "setup", also checkout des Git Repository, prüfen wir dieses nach geänderten Ordnern, um nur diesen weiter für den Build zu betrachten. Ändert sich also etwas im Ghost Ordner, wird nicht das Elasticsearch oder hello-world Image erneut gebaut.
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: build-pipeline
spec:
  workspaces:
    - name: source
  params:
    - name: git-url
      description: The url for the git repository
    - name: git-revision
      description: The git revision (branch, tag, or sha) that should be built
      default: main
    - name: git-reponame
      description: Name of the git repository
  tasks:
    - name: setup
      taskRef:
        name: setup
      params:
        - name: git-url
          value: $(params.git-url)
        - name: git-revision
          value: $(params.git-revision)
    - name: build
      taskRef:
        name: build
      params:
        - name: git-url
          value: $(params.git-url)
        - name: git-revision
          value: $(params.git-revision)
        - name: dirs
          value: $(tasks.setup.results.changed-dirs)
        - name: my-namespace
          value: $(tasks.setup.results.current-namespace)
        - name: architecture
          value: "s390x"
      runAfter:
        - setup
Im Build Prozess prüfen wir zuerst, ob das übermittelte Image Manifest existiert und erstellen, sofern noch nicht vorhanden, mittels des buildah manifest create ein neues. Anschließend haben wir eine Schleife erstellt, welche je übermittelter Zielarchitektur ein Image erstellt und via buildah push das Image in die Registry überführt. Hier ein kleiner Auszug aus dem Build Task.

# Build image(s) for target architecture(s)
for arch in $(params.architecture)
do 
buildah --layers --storage-driver=$(params.STORAGE_DRIVER) bud \
    --tag "${REGISTRY}/${MYNAMESPACE}/${IMAGE_NAME}:${IMAGE_TAG}" \
    --platform linux/$arch \
    --format=$(params.FORMAT) \
    --tls-verify=false \
    ${BUILD_PATH}
done

Wie eingangs erwähnt, ist es nicht so einfach ganz ohne manuelle Eingriffe neue Images für eine neue Zielarchitektur zur Verfügung zu stellen. Mindestens der FROM Teil im Dockerfile muss angepasst werden, um eine s390x kompatible Grundlage zu haben. Anschließend kommen je nach Image weitere Anpassungen bei benötigten Libraries oder Tools. Das Bauen der Images unter OpenShift auf der Z Platform lief ohne Probleme – die Methode via QEMU haben wir nicht getestet.

Wir planen, als Nächstes durch automatisierte Tests die im Dockerfile notwendigen Änderungen zu ermitteln und direkt als Änderung zu implementieren. Dies bringt uns unserem Wunsch näher, möglichst wenig manuell am Quell-Image zu verändern.

Es ist wichtig zu beachten, dass dies nur ein allgemeiner Überblick darüber ist, wie dieser Prozess durchgeführt werden kann, und es kann je nach Anwendung und Architektur unterschiedliche Schritte und Anpassungen geben. Es ist empfehlenswert, sich gründlich über die Tools und Methoden zu informieren und zu testen, bevor ihr sie in einer produktiven Umgebung einsetzt.

Wie baut ihr eure Images für die IBM Z Platform? Habt ihr selbst schon eine solche Pipeline? Vermisst ihr ein Image, welches ihr gerne auf der IBM Z und IBM LinuxONE sehen möchtet? Tretet gerne mit uns in Kontakt oder lasst es uns in den Kommentaren wissen.