Dieser Beitrag wurde verfasst, weil wir viele Gespräche mit unseren Kunden über die Entwicklung von Anwendungen auf Kubernetes und über die Besonderheiten dieser Entwicklung auf OpenShift geführt haben.

Wir beginnen normalerweise mit der These, dass Kubernetes einfach Kubernetes ist, während OpenShift bereits eine Kubernetes-Plattform ist, ähnlich wie Microsoft AKS oder Amazon EKS. Jede dieser Plattformen hat ihre eigenen Vorteile, die auf eine bestimmte Zielgruppe ausgerichtet sind. Danach fließt das Gespräch bereits in einen Vergleich der Stärken und Schwächen der jeweiligen Plattformen über.
Im Grunde dachten wir darüber nach, diesen Beitrag mit der Schlussfolgerung zu schreiben: „Hört zu, es spielt keine Rolle, wo der Code ausgeführt wird, auf OpenShift oder auf AKS, auf EKS, auf einem beliebigen benutzerdefinierten Kubernetes oder auf irgendeinem Kubernetes (um es kurz zu machen, nennen wir es KUK) – es ist tatsächlich einfach, sowohl dort als auch dort.“
Dann hatten wir geplant, ein einfaches "Hello World" zu nehmen und anhand dieses Beispiels zu zeigen, was gemeinsam ist und was die Unterschiede zwischen KUK und der Red Hat OpenShift Container Platform (nachfolgend OCP oder einfach OpenShift) sind.
Doch während des Schreibens dieses Beitrags wurde uns klar, dass wir so sehr an OpenShift gewöhnt sind, dass wir einfach nicht bemerken, wie es gewachsen ist und sich in eine großartige Plattform verwandelt hat, die viel mehr ist als nur eine Kubernetes-Distribution. Wir haben uns daran gewöhnt, die Reife und Einfachheit von OpenShift als selbstverständlich zu betrachten und dabei seine hervorragenden Eigenschaften außer Acht zu lassen.
Im Grunde ist es an der Zeit für aktives Bedauern, und jetzt werden wir Schritt für Schritt den Einsatz unseres "Hello World" auf KUK und OpenShift vergleichen, und wir werden dies so objektiv wie möglich tun (außer vielleicht, dass wir gelegentlich persönliche Meinungen zu dem Thema äußern). Wenn Sie an einer rein subjektiven Meinung zu diesem Thema interessiert sind, können Sie sie lesen . In diesem Beitrag werden wir uns jedoch an die Fakten und nur an die Fakten halten.
Cluster
Also, für unser "Hello World" benötigen wir Cluster. Zunächst einmal sagen wir "nein" zu allen öffentlichen Clouds, um keine Kosten für Server, Registries, Netzwerke, Datentransfers usw. zu haben. Daher wählen wir einen einfachen Ein-Knoten-Cluster auf (für KUK) und (für den OpenShift-Cluster). Beide Varianten sind in der Installation wirklich einfach, benötigen jedoch ziemlich viele Ressourcen auf Ihrem Laptop.

Build auf KUK
Also, lass uns anfangen.
Schritt 1 – wir erstellen unser Container-Image
Ich beginne damit, unser "Hello World" auf minikube zu deployen. Dafür benötigen wir:
- 1. Installiertes Docker.
- 2. Installiertes Git.
- 3. Installiertes Maven (in diesem Projekt wird eigentlich die mvnw-Binärdatei verwendet, also ist es nicht erforderlich).
- 4. Tatsächlich der Quellcode, d.h. ein Klon des Repositories
Zuerst muss ein Quarkus-Projekt erstellt werden. Keine Sorge, wenn Sie noch nie mit der Webseite Quarkus.io gearbeitet haben – das ist einfach. Wählen Sie einfach die Komponenten aus, die Sie in Ihrem Projekt verwenden möchten (RestEasy, Hibernate, Amazon SQS, Camel usw.), und dann konfiguriert Quarkus alles für Sie, ohne dass Sie irgendetwas tun müssen; es richtet das Maven-Archetyp ein und stellt alles auf GitHub bereit. Das heißt, mit nur einem Mausclick ist alles bereit. Dafür lieben wir Quarkus.

Der einfachste Weg, um unser "Hello World" in ein Container-Image zu packen, ist die Verwendung von Quarkus-Maven-Erweiterungen für Docker, die die gesamte erforderliche Arbeit erledigen. Mit dem Erscheinen von Quarkus ist das wirklich einfach und unkompliziert geworden: Sie fügen die Erweiterung container-image-docker hinzu und können Images mit Maven-Befehlen erstellen.
./mvnw quarkus:add-extension -Dextensions="container-image-docker"
Und schließlich bauen wir unser Image mit Maven. Dabei verwandelt sich unser Quellcode in ein fertiges Container-Image, das bereits in einer Container-Ausführungsumgebung gestartet werden kann.

./mvnw -X clean package -Dquarkus.container-image.build=true
Und das war's, jetzt können Sie den Container mit dem Befehl docker run starten und unseren Dienst auf Port 8080 bereitstellen, sodass er erreichbar ist.
docker run -i --rm -p 8080:8080 gcolman/quarkus-hello-world

Nachdem der Container-Instanz gestartet wurde, müssen wir nur noch mit dem Befehl curl überprüfen, dass unser Dienst funktioniert:
![]()
Also, alles funktioniert und es war wirklich einfach und unkompliziert.
Schritt 2 – Übertragen unseres Containers in ein Container-Image-Repository
Momentan wird das von uns erstellte Image lokal in unserem lokalen Container-Repository gespeichert. Wenn wir dieses Image in unserer Kubernetes-Umgebung verwenden möchten, müssen wir es in ein anderes Repository hochladen. Kubernetes hat diese Funktionen nicht eingebaut, deshalb werden wir Docker Hub verwenden. Es ist erstens kostenlos und zweitens machen es (fast) alle so.
Das ist auch ganz einfach, man braucht nur ein Konto bei Docker Hub.
Also, melden wir uns bei Docker Hub an und laden unser Image dort hoch.

Schritt 3 – Kubernetes starten
Es gibt viele Möglichkeiten, die Kubernetes-Konfiguration für unser "Hello World" zusammenzustellen, aber wir werden die einfachste davon verwenden, weil wir so sind...
Zuerst starten wir den Minikube-Cluster:
minikube start
Schritt 4 – Wir deployen unser Container-Image
Jetzt müssen wir unseren Code und das Container-Image in Kubernetes-Konfigurationen umwandeln. Mit anderen Worten, wir benötigen eine Pod- und Deployment-Definition, die auf unser Container-Image auf Dockerhub verweist. Einer der einfachsten Wege, dies zu tun, ist der Befehl zum Erstellen eines Deployments, indem wir auf unser Image verweisen:

kubectl create deployment hello-quarkus --image=gcolman/quarkus-hello-world:1.0.0-SNAPSHOT
Mit diesem Befehl haben wir Kubernetes gesagt, dass es eine Deployment-Konfiguration erstellen soll, die eine Pod-Spezifikation für unser Container-Image enthalten muss. Dieser Befehl wendet auch diese Konfiguration auf unseren Minikube-Cluster an und erstellt ein Deployment, das unser Container-Image herunterlädt und einen Pod im Cluster startet.
Schritt 5 – Wir öffnen den Zugriff auf unseren Dienst
Jetzt, wo wir unser Container-Image bereitgestellt haben, ist es an der Zeit zu überlegen, wie wir den externen Zugriff auf diesen RESTful-Service konfigurieren, der in unserem Code programmiert ist.
Hier gibt es viele Möglichkeiten. Zum Beispiel können wir den Befehl expose verwenden, um automatisch die entsprechenden Kubernetes-Komponenten wie Services und Endpoints zu erstellen. Genau das werden wir tun, indem wir den Befehl expose für unser Deployment-Objekt ausführen:
kubectl expose deployment hello-quarkus --type=NodePort --port=8080
Lass uns einen Moment auf die Option "--type" des Expose-Befehls eingehen.
Wenn wir expose machen und die für den Betrieb unseres Dienstes erforderlichen Komponenten erstellen, müssen wir unter anderem gewährleisten, dass von außen auf den Dienst hello-quarkus zugegriffen werden kann, der in unserem softwaredefinierten Netzwerk sitzt. Und der Parameter type ermöglicht es uns, solche Dinge wie Lastenausgleichsserver zu erstellen und zu verbinden, um den Verkehr in dieses Netzwerk zu leiten.
Wenn wir also type=LoadBalancer, geben wir automatisch einen Lastenausgleichsserver in der öffentlichen Cloud in Betrieb, um eine Verbindung zu unserem Kubernetes-Cluster herzustellen. Das ist natürlich großartig, man muss jedoch verstehen, dass eine solche Konfiguration stark an eine bestimmte öffentliche Cloud gebunden sein wird und es schwieriger ist, sie zwischen Kubernetes-Instanzen in verschiedenen Umgebungen zu übertragen.
In unserem Beispiel type=NodePort, das heißt, der Zugriff auf unseren Dienst erfolgt über die IP-Adresse des Knotens und die Portnummer. Diese Möglichkeit erfordert keine öffentlichen Clouds, bringt jedoch eine Reihe zusätzlicher Schritte mit sich. Erstens benötigen wir einen eigenen Load-Balancer, daher werden wir einen NGINX-Load-Balancer in unserem Cluster bereitstellen.
Schritt 6 – Load-Balancer einrichten
Minikube verfügt über eine Reihe plattforminterner Funktionen, die die Erstellung der erforderlichen Komponenten für den externen Zugriff, wie Ingress-Controller, erleichtern. Minikube wird mit dem Nginx-Ingress-Controller geliefert, und wir müssen ihn nur aktivieren und konfigurieren.
minikube addons enable ingress
Jetzt erstellen wir mit einem einzigen Befehl den Nginx-Ingress-Controller, der innerhalb unseres Minikube-Clusters funktioniert:
ingress-nginx-controller-69ccf5d9d8-j5gs9 1/1 Running 1 33m
Schritt 7 – Ingress konfigurieren
Jetzt müssen wir den Nginx-Ingress-Controller so konfigurieren, dass er die Anfragen an hello-quarkus akzeptiert.


Und schließlich müssen wir diese Konfiguration anwenden.

kubectl apply -f ingress.yml
![]()
Da wir das alles auf unserem Computer machen, fügen wir einfach die IP-Adresse unseres Knotens in die Datei /etc/hosts ein, um HTTP-Anfragen an unser Minikube an den NGINX-Load-Balancer zu leiten.
192.168.99.100 hello-quarkus.info
Alles klar, jetzt ist unser Minikube-Dienst von außen über den Nginx-Ingress-Controller zugänglich.

Na, das war doch einfach, oder? Oder nicht so sehr?

Starten in OpenShift (Code Ready Containers)
Und jetzt schauen wir uns an, wie das alles auf der Red Hat OpenShift Container Platform (OCP) funktioniert.
Wie im Fall von Minikube wählen wir das Schema mit einem einzelnen Knoten in Form von Code Ready Containers (CRC). Früher hieß es Minishift und basierte auf dem OpenShift-Origin-Projekt, jetzt ist es CRC und basiert auf der OpenShift Container Platform von Red Hat.
Hier können wir einfach nicht widerstehen zu sagen: 'OpenShift ist großartig!'
Ursprünglich dachten wir, wir würden schreiben, dass die Entwicklung auf OpenShift sich nicht von der Entwicklung auf Kubernetes unterscheidet. Und im Grunde genommen stimmt das auch. Aber während wir diesen Beitrag schrieben, erinnerten wir uns, wie viele unnötige Schritte man unternehmen muss, wenn man kein OpenShift hat, und deshalb ist es, um es noch einmal zu sagen, großartig. Wir lieben es, wenn alles einfach ist, und wie einfach unser Beispiel im Vergleich zu Minikube auf OpenShift bereitgestellt und gestartet wird, hat uns tatsächlich dazu bewegt, diesen Beitrag zu schreiben.
Lassen Sie uns den Prozess durchgehen und sehen, was wir tun müssen.
Also, im Beispiel mit Minikube haben wir mit Docker begonnen... Halt, wir brauchen Docker nicht mehr auf dem Rechner installiert zu haben.
Und lokales Git benötigen wir nicht.
Und Maven ist auch nicht nötig.
Und es ist nicht nötig, ein Container-Image manuell zu erstellen.
Und es ist nicht nötig, ein Container-Image-Repository zu suchen.
Und es ist nicht nötig, einen Ingress-Controller zu installieren.
Und auch Ingress zu konfigurieren, ist nicht nötig.
Ihr habt es verstanden, ja? Um unsere Anwendung in OpenShift zu starten und bereitzustellen, braucht man nichts davon. Der Prozess sieht folgendermaßen aus.
Schritt 1 – Starten Sie Ihr OpenShift-Cluster
Wir verwenden Code Ready Containers von Red Hat, was im Grunde dasselbe wie Minikube ist, jedoch mit einem voll funktionsfähigen Ein-Knoten-Cluster von Openshift.
crc start
Schritt 2 – Führen Sie den Build und die Bereitstellung der Anwendung im OpenShift-Cluster durch
Genau in diesem Schritt zeigt sich die Einfachheit und Benutzerfreundlichkeit von OpenShift in vollem Umfang. Wie in allen Kubernetes-Distributionen gibt es viele Möglichkeiten, eine Anwendung im Cluster zu starten. Und wie im Fall von KUK wählen wir absichtlich die einfachste.
OpenShift wurde immer als Plattform zur Erstellung und Ausführung von containerisierten Anwendungen entwickelt. Das Erstellen von Containern war immer ein wesentlicher Bestandteil dieser Plattform, daher gibt es hier eine Menge zusätzlicher Kubernetes-Ressourcen für entsprechende Aufgaben.
Wir werden den OpenShift-Prozess Source 2 Image (S2I) verwenden, der mehrere verschiedene Möglichkeiten bietet, um unseren Quellcode (Code oder Binärdateien) in ein im OpenShift-Cluster ausführbares Container-Image zu verwandeln.
Dafür benötigen wir zwei Dinge:
- unseren Quellcode im Git-Repository
- Ein Builder-Image, auf dessen Grundlage der Build durchgeführt wird.
Es gibt viele solcher Images, sowohl von Red Hat als auch von der Community, und wir werden das OpenJDK-Image verwenden, da ich ein Java-Anwendung baue.
Wir können einen S2I-Build sowohl über die grafische Konsole von OpenShift Developer als auch über die Befehlszeile starten. Wir verwenden den Befehl new-app und geben ihm an, wo das Builder-Image und unser Quellcode zu finden sind.

oc new-app registry.access.redhat.com/ubi8/openjdk-11:latest~https://github.com/gcolman/quarkus-hello-world.git
Fertig, unsere Anwendung wurde erstellt. Dabei hat der S2I-Prozess Folgendes erledigt:
- Einen Build-Pod für alles, was mit der Erstellung der Anwendung zu tun hat, erstellt.
- Die OpenShift-Baukonfiguration erstellt.
- Das Builder-Image in das interne Docker-Registry von OpenShift heruntergeladen.
- «Hello World» in das lokale Repository geklont.
- Ich sah, dass dort eine maven-pom vorhanden ist, und daher habe ich die Anwendung mit maven kompiliert.
- Ich habe ein neues Container-Image erstellt, das die kompilierte Java-Anwendung enthält, und dieses Image in das interne Container-Registry gelegt.
- Ich habe ein Kubernetes-Deployment mit den Spezifikationen für den Pod, den Dienst usw. erstellt.
- Ich habe das Container-Image deployt.
- Ich habe den Build-Pod entfernt.
In dieser Liste steht viel, aber das Wichtigste ist, dass der gesamte Build ausschließlich innerhalb von OpenShift erfolgt, das interne Docker-Registry befindet sich innerhalb von OpenShift, und der Build-Prozess erstellt alle Kubernetes-Komponenten und startet sie im Cluster.
Wenn man den Start von S2I in der Konsole visuell verfolgt, kann man sehen, wie beim Ausführen des Builds der Build-Pod gestartet wird.

Und jetzt schauen wir uns die Logs des Builder-Pods an: Zum einen sieht man, wie maven seine Arbeit verrichtet und Abhängigkeiten für den Build unserer Java-Anwendung herunterlädt.

Nachdem der maven-Build abgeschlossen ist, wird das Container-Image gebaut, und danach wird dieses gebaute Image in das interne Repository hochgeladen.

Alles, der Build-Prozess ist abgeschlossen. Lassen Sie uns nun sicherstellen, dass die Pods und Dienste unserer Anwendung im Cluster gestartet wurden.
oc get service
![]()
Das ist alles. Und nur ein Befehl. Wir müssen nur noch diesen Dienst für den externen Zugriff exponieren.
Schritt 3 – den Dienst für den externen Zugriff exponieren
Wie im Fall von KUB, benötigt unsere "Hello World"-Anwendung auf der OpenShift-Plattform ebenfalls einen Router, um den externen Datenverkehr auf den Dienst innerhalb des Clusters zu lenken. In OpenShift geschieht dies sehr einfach. Erstens ist standardmäßig ein Routing-Komponente namens HAProxy im Cluster installiert (diese kann durch NGINX ersetzt werden). Zweitens gibt es hier spezielle Ressourcen, die umfassende Anpassungsmöglichkeiten bieten und als Routes bezeichnet werden und den Ingress-Objekten im guten alten Kubernetes ähneln (tatsächlich haben die OpenShift-Routes das Design der Ingress-Objekte stark beeinflusst, die nun auch in OpenShift verwendet werden können), aber für unser "Hello World" und in fast allen anderen Fällen reicht uns die Standard-Route ohne zusätzliche Anpassung.
Um für "Hello World" einen routbaren FQDN zu erstellen (ja, in OpenShift gibt es eigenen DNS für die Namensauflösung von Diensten), führen wir einfach ein Expose für unseren Dienst aus:

oc expose service quarkus-hello-world
Wenn Sie sich den gerade erstellten Route ansehen, finden Sie dort den FQDN und weitere Informationen zur Routing-Konfiguration:
oc get route
![]()
Und schließlich rufen wir unseren Dienst aus dem Browser auf:

Und jetzt war das wirklich einfach!
Wir lieben Kubernetes und alles, was diese Technologie ermöglicht, sowie Einfachheit und Leichtigkeit. Kubernetes wurde entwickelt, um die Nutzung von verteilten, skalierbaren Containern erheblich zu vereinfachen, aber für die Bereitstellung von Anwendungen reicht diese Einfachheit heute nicht mehr aus. Hier kommt OpenShift ins Spiel, das mit der Zeit geht und Kubernetes anbietet, das sich in erster Linie an Entwickler richtet. Es wurden große Anstrengungen unternommen, um die OpenShift-Plattform speziell für Entwickler zu optimieren, einschließlich der Schaffung von Tools wie S2I, ODI, Developer Portal, OpenShift Operator Framework, Integration mit IDEs, Entwicklerkatalogen, Integration mit Helm, Monitoring und vielen anderen.
Wir hoffen, dass dieser Artikel für Sie interessant und nützlich war. Weitere Ressourcen, Materialien und andere nützliche Dinge für die Entwicklung auf der OpenShift-Plattform finden Sie im Portal .
Quelle: habr.com
