Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Hallo an alle auf diesem Blog! Dies ist der dritte Beitrag einer Reihe, in der wir zeigen, wie man moderne Webanwendungen auf Red Hat OpenShift bereitstellt.

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

In den beiden vorherigen Beiträgen haben wir gezeigt, wie Sie moderne Webanwendungen in nur wenigen Schritten bereitstellen und wie Sie ein neues S2I-Image zusammen mit einem handelsüblichen HTTP-Server-Image wie NGINX verwenden und verkettete Builds verwenden, um Produktionsbereitstellungen zu orchestrieren .

Heute zeigen wir, wie Sie einen Entwicklungsserver für Ihre Anwendung auf der OpenShift-Plattform ausführen und mit dem lokalen Dateisystem synchronisieren. Außerdem sprechen wir darüber, was OpenShift-Pipelines sind und wie sie als Alternative zu verknüpften Assemblys verwendet werden können.

OpenShift als Entwicklungsumgebung

Entwicklungsworkflow

Wie in erwähnt erster BeitragDer typische Entwicklungsprozess für moderne Webanwendungen ist einfach eine Art „Entwicklungsserver“, der Änderungen an lokalen Dateien verfolgt. Wenn sie auftreten, wird die Anwendungserstellung ausgelöst und anschließend im Browser aktualisiert.

In den meisten modernen Frameworks ist ein solcher „Entwicklungsserver“ in die entsprechenden Kommandozeilentools eingebaut.

Lokales Beispiel

Sehen wir uns zunächst an, wie dies funktioniert, wenn Anwendungen lokal ausgeführt werden. Nehmen wir die Anwendung als Beispiel Reagieren aus früheren Artikeln, obwohl in allen anderen modernen Frameworks fast die gleichen Workflow-Konzepte gelten.
Um also den „Dev-Server“ in unserem React-Beispiel zu starten, geben wir den folgenden Befehl ein:

$ npm run start

Dann sehen wir im Terminalfenster etwa Folgendes:

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Und unsere Anwendung wird im Standardbrowser geöffnet:

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Wenn wir nun Änderungen an der Datei vornehmen, sollte die Anwendung im Browser aktualisiert werden.

OK, bei der Entwicklung im lokalen Modus ist alles klar, aber wie erreicht man dasselbe unter OpenShift?

Entwicklungsserver auf OpenShift

Wenn Sie sich erinnern, in vorherigen Posthaben wir uns die sogenannte Ausführungsphase des S2I-Images angesehen und festgestellt, dass das Serve-Modul standardmäßig für die Wartung unserer Webanwendung verantwortlich ist.

Allerdings schaut man genauer hin Skript ausführen In diesem Beispiel enthält es die Umgebungsvariable $NPM_RUN, mit der Sie Ihren Befehl ausführen können.

Zum Beispiel können wir das Nodeshift-Modul verwenden, um unsere Anwendung bereitzustellen:

$ npx nodeshift --deploy.env NPM_RUN="yarn start" --dockerImage=nodeshift/ubi8-s2i-web-app

Hinweis: Das obige Beispiel wurde gekürzt, um die allgemeine Idee zu veranschaulichen.

Hier haben wir unserer Bereitstellung die Umgebungsvariable NPM_RUN hinzugefügt, die die Laufzeit anweist, den Befehl „garn start“ auszuführen, der den React-Entwicklungsserver in unserem OpenShift-Pod startet.

Wenn Sie sich das Protokoll eines laufenden Pods ansehen, sieht es etwa so aus:

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Das alles wird natürlich nichts bringen, bis wir den lokalen Code mit dem Code synchronisieren können, der ebenfalls auf Änderungen überwacht wird, aber auf einem Remote-Server lebt.

Remote- und lokalen Code synchronisieren

Glücklicherweise kann Nodeshift problemlos bei der Synchronisierung helfen, und Sie können den Befehl watch verwenden, um Änderungen zu verfolgen.

Nachdem wir also den Befehl zum Bereitstellen des Entwicklungsservers für unsere Anwendung ausgeführt haben, können wir den folgenden Befehl bedenkenlos verwenden:

$ npx nodeshift watch

Dadurch wird eine Verbindung zum laufenden Pod hergestellt, den wir etwas zuvor erstellt haben, die Synchronisierung unserer lokalen Dateien mit dem Remote-Cluster wird aktiviert und die Dateien auf unserem lokalen System werden auf Änderungen überwacht.

Wenn wir nun also die Datei src/App.js aktualisieren, reagiert das System auf diese Änderungen, kopiert sie auf den Remote-Cluster und startet den Entwicklungsserver, der dann unsere Anwendung im Browser aktualisiert.

Um das Bild zu vervollständigen, zeigen wir, wie diese gesamten Befehle aussehen:

$ npx nodeshift --strictSSL=false --dockerImage=nodeshift/ubi8-s2i-web-app --build.env YARN_ENABLED=true --expose --deploy.env NPM_RUN="yarn start" --deploy.port 3000

$ npx nodeshift watch --strictSSL=false

Der Befehl watch ist eine Abstraktion zusätzlich zum Befehl oc rsync. Sie können mehr über seine Funktionsweise erfahren hier.

Dies war ein Beispiel für React, aber genau dieselbe Methode kann auch mit anderen Frameworks verwendet werden. Legen Sie einfach die Umgebungsvariable NPM_RUN nach Bedarf fest.

Openshift-Pipelines

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Als nächstes sprechen wir über ein Tool wie OpenShift Pipelines und wie es als Alternative zu verketteten Builds verwendet werden kann.

Was sind OpenShift-Pipelines?

OpenShift Pipelines ist ein Cloud-natives CI/CD-System für kontinuierliche Integration und Bereitstellung, das für die Organisation von Pipelines mit Tekton entwickelt wurde. Tekton ist ein flexibles Open-Source-Kubernetes-natives CI/CD-Framework, mit dem Sie die Bereitstellung auf verschiedenen Plattformen (Kubernetes, serverlos, virtuelle Maschinen usw.) automatisieren können, indem Sie von der zugrunde liegenden Ebene abstrahieren.

Um diesen Artikel zu verstehen, sind einige Kenntnisse über Pipelines erforderlich. Wir empfehlen Ihnen daher dringend, ihn zuerst zu lesen offizielles Lehrbuch.

Einrichten Ihrer Arbeitsumgebung

Um mit den Beispielen in diesem Artikel herumzuspielen, müssen Sie zunächst Ihre Arbeitsumgebung vorbereiten:

  1. Installieren und konfigurieren Sie einen OpenShift 4-Cluster. In unseren Beispielen werden hierfür CodeReady Container (CRD) verwendet, eine Installationsanleitung finden Sie hier hier.
  2. Nachdem der Cluster bereit ist, müssen Sie Pipeline Operator darauf installieren. Keine Angst, es ist einfach, Installationsanleitung hier.
  3. Herunterladen Tekton-CLI (tkn) hier.
  4. Führen Sie das Befehlszeilentool „create-react-app“ aus, um eine Anwendung zu erstellen, die Sie dann bereitstellen (dies ist eine einfache Anwendung). Reagieren).
  5. (Optional) Klonen Sie das Repository, um die Beispielanwendung lokal mit npm install und dann npm start auszuführen.

Das Anwendungs-Repository verfügt außerdem über einen k8s-Ordner, der die Kubernetes/OpenShift-YAMLs enthält, die zur Bereitstellung der Anwendung verwendet werden. Es wird Aufgaben, ClusterTasks, Ressourcen und Pipelines geben, die wir darin erstellen werden Lagerstätten.

Lass uns anfangen

Der erste Schritt für unser Beispiel besteht darin, ein neues Projekt im OpenShift-Cluster zu erstellen. Rufen wir dieses Projekt „webapp-pipeline“ auf und erstellen es mit dem folgenden Befehl:

$ oc new-project webapp-pipeline

Dieser Projektname wird später im Code erscheinen. Wenn Sie sich also für einen anderen Namen entscheiden, vergessen Sie nicht, den Beispielcode entsprechend zu bearbeiten. Ab diesem Punkt gehen wir nicht von oben nach unten, sondern von unten nach oben vor: Das heißt, wir erstellen zunächst alle Komponenten des Förderers und erst dann den Förderer selbst.

Also, zunächst einmal...

Aufgaben

Lassen Sie uns ein paar Aufgaben erstellen, die dann bei der Bereitstellung der Anwendung in unserer Pipeline helfen. Die erste Aufgabe – apply_manifests_task – ist für die Anwendung der YAML der Kubernetes-Ressourcen (Dienst, Bereitstellung und Route) verantwortlich, die sich im k8s-Ordner unserer Anwendung befinden. Die zweite Aufgabe – update_deployment_task – ist für die Aktualisierung eines bereits bereitgestellten Images auf das von unserer Pipeline erstellte verantwortlich.

Machen Sie sich keine Sorgen, wenn es noch nicht ganz klar ist. Tatsächlich handelt es sich bei diesen Aufgaben um so etwas wie Dienstprogramme, und wir werden sie etwas später genauer betrachten. Erstellen wir sie zunächst einfach:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/tasks/update_deployment_task.yaml
$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/tasks/apply_manifests_task.yaml

Anschließend prüfen wir mit dem CLI-Befehl tkn, ob die Aufgaben erstellt wurden:

$ tkn task ls

NAME                AGE
apply-manifests     1 minute ago
update-deployment   1 minute ago

Hinweis: Dies sind lokale Aufgaben für Ihr aktuelles Projekt.

Clusteraufgaben

Cluster-Aufgaben sind grundsätzlich dasselbe wie einfache Aufgaben. Das heißt, es handelt sich um eine wiederverwendbare Sammlung von Schritten, die beim Ausführen einer bestimmten Aufgabe auf die eine oder andere Weise kombiniert werden. Der Unterschied besteht darin, dass eine Cluster-Aufgabe überall im Cluster verfügbar ist. Um die Liste der Cluster-Aufgaben anzuzeigen, die beim Hinzufügen von Pipeline Operator automatisch erstellt werden, verwenden wir erneut den tkn-CLI-Befehl:

$ tkn clustertask ls

NAME                       AGE
buildah                    1 day ago
buildah-v0-10-0            1 day ago
jib-maven                  1 day ago
kn                         1 day ago
maven                      1 day ago
openshift-client           1 day ago
openshift-client-v0-10-0   1 day ago
s2i                        1 day ago
s2i-go                     1 day ago
s2i-go-v0-10-0             1 day ago
s2i-java-11                1 day ago
s2i-java-11-v0-10-0        1 day ago
s2i-java-8                 1 day ago
s2i-java-8-v0-10-0         1 day ago
s2i-nodejs                 1 day ago
s2i-nodejs-v0-10-0         1 day ago
s2i-perl                   1 day ago
s2i-perl-v0-10-0           1 day ago
s2i-php                    1 day ago
s2i-php-v0-10-0            1 day ago
s2i-python-3               1 day ago
s2i-python-3-v0-10-0       1 day ago
s2i-ruby                   1 day ago
s2i-ruby-v0-10-0           1 day ago
s2i-v0-10-0                1 day ago

Lassen Sie uns nun zwei Cluster-Aufgaben erstellen. Der erste generiert das S2I-Image und sendet es an die interne OpenShift-Registrierung. Die zweite besteht darin, unser Image auf Basis von NGINX zu erstellen und die Anwendung, die wir bereits erstellt haben, als Inhalt zu verwenden.

Erstellen und senden Sie das Bild

Beim Erstellen der ersten Aufgabe wiederholen wir, was wir bereits im vorherigen Artikel über verknüpfte Baugruppen getan haben. Denken Sie daran, dass wir das S2I-Image (ubi8-s2i-web-app) zum „Erstellen“ unserer Anwendung verwendet haben und am Ende ein Image erhalten haben, das in der internen OpenShift-Registrierung gespeichert ist. Jetzt verwenden wir dieses S2I-Web-App-Image, um eine DockerFile für unsere App zu erstellen, und verwenden dann Buildah, um den eigentlichen Build durchzuführen und das resultierende Image in die interne OpenShift-Registrierung zu übertragen, da OpenShift genau das tut, wenn Sie Ihre Anwendungen mit NodeShift bereitstellen .

Woher wissen wir das alles, fragen Sie? Aus offizielle Version des offiziellen Node.js, wir haben es einfach kopiert und für uns modifiziert.

Erstellen wir nun die Clusteraufgabe „s2i-web-app“:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/s2i-web-app-task.yaml

Wir werden dies nicht im Detail analysieren, sondern uns nur auf den Parameter OUTPUT_DIR konzentrieren:

params:
      - name: OUTPUT_DIR
        description: The location of the build output directory
        default: build

Standardmäßig ist dieser Parameter gleich build, wo React den zusammengestellten Inhalt ablegt. Andere Frameworks verwenden andere Pfade, in Ember ist es beispielsweise dist. Die Ausgabe unserer ersten Clusteraufgabe wird ein Bild sein, das das von uns gesammelte HTML, JavaScript und CSS enthält.

Erstellen Sie ein Image basierend auf NGINX

Unsere zweite Clusteraufgabe sollte für uns ein NGINX-basiertes Image erstellen und dabei den Inhalt der bereits erstellten Anwendung verwenden. Im Wesentlichen ist dies der Teil des vorherigen Abschnitts, in dem wir uns mit verketteten Builds befasst haben.

Dazu erstellen wir – genau wie oben – eine Cluster-Aufgabe „webapp-build-runtime“:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/clustertasks/webapp-build-runtime-task.yaml

Wenn Sie sich den Code für diese Cluster-Aufgaben ansehen, können Sie feststellen, dass er weder das Git-Repository angibt, mit dem wir arbeiten, noch die Namen der Images, die wir erstellen. Wir geben lediglich an, was genau wir an Git übertragen, oder ein bestimmtes Bild, wo das endgültige Bild ausgegeben werden soll. Aus diesem Grund können diese Cluster-Aufgaben bei der Arbeit mit anderen Anwendungen wiederverwendet werden.

Und hier gehen wir elegant zum nächsten Punkt über ...

Ressourcen

Da also, wie wir gerade gesagt haben, Cluster-Aufgaben so allgemein wie möglich sein sollten, müssen wir Ressourcen erstellen, die als Eingabe (das Git-Repository) und als Ausgabe (die endgültigen Bilder) verwendet werden. Die erste Ressource, die wir benötigen, ist Git, wo sich unsere Anwendung befindet, etwa so:

# This resource is the location of the git repo with the web application source
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: web-application-repo
spec:
  type: git
  params:
    - name: url
      value: https://github.com/nodeshift-starters/react-pipeline-example
    - name: revision
      value: master

Hier ist PipelineResource vom Typ Git. Der URL-Schlüssel im Abschnitt „params“ verweist auf ein bestimmtes Repository und gibt den Master-Zweig an (dies ist optional, wir schreiben ihn jedoch der Vollständigkeit halber).

Jetzt müssen wir eine Ressource für das Bild erstellen, in der die Ergebnisse der s2i-web-app-Aufgabe gespeichert werden. Dies geschieht folgendermaßen:

# This resource is the result of running "npm run build",  the resulting built files will be located in /opt/app-root/output
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: built-web-application-image
spec:
  type: image
  params:
    - name: url
      value: image-registry.openshift-image-registry.svc:5000/webapp-pipeline/built-web-application:latest

Hier ist die PipelineResource vom Typ „Bild“ und der Wert des URL-Parameters verweist auf die interne OpenShift-Image-Registrierung, insbesondere auf diejenige, die sich im Namespace „webapp-pipeline“ befindet. Vergessen Sie nicht, diese Einstellung zu ändern, wenn Sie einen anderen Namespace verwenden.

Und schließlich wird die letzte Ressource, die wir benötigen, ebenfalls vom Typ Image sein und dies wird das endgültige NGINX-Image sein, das dann während der Bereitstellung verwendet wird:

# This resource is the image that will be just the static html, css, js files being run with nginx
apiVersion: tekton.dev/v1alpha1
kind: PipelineResource
metadata:
  name: runtime-web-application-image
spec:
  type: image
  params:
    - name: url
      value: image-registry.openshift-image-registry.svc:5000/webapp-pipeline/runtime-web-application:latest

Beachten Sie auch hier, dass diese Ressource das Bild in der internen OpenShift-Registrierung im Namespace webapp-pipeline speichert.

Um alle diese Ressourcen auf einmal zu erstellen, verwenden wir den Befehl create:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/resources/resource.yaml

Sie können sicherstellen, dass die Ressourcen wie folgt erstellt wurden:

$ tkn resource ls

Förderrohrleitung

Nachdem wir nun alle notwendigen Komponenten haben, bauen wir daraus eine Pipeline zusammen, indem wir sie mit dem folgenden Befehl erstellen:

$ oc create -f https://raw.githubusercontent.com/nodeshift/webapp-pipeline-tutorial/master/pipelines/build-and-deploy-react.yaml

Aber bevor wir diesen Befehl ausführen, schauen wir uns diese Komponenten an. Der erste ist der Name:

apiVersion: tekton.dev/v1alpha1
kind: Pipeline
metadata:
  name: build-and-deploy-react

Dann sehen wir im Abschnitt „Spezifikation“ einen Hinweis auf die Ressourcen, die wir zuvor erstellt haben:

spec:
  resources:
    - name: web-application-repo
      type: git
    - name: built-web-application-image
      type: image
    - name: runtime-web-application-image
      type: image

Anschließend erstellen wir die Aufgaben, die unsere Pipeline ausführen muss. Zunächst muss die von uns bereits erstellte Aufgabe „s2i-web-app“ ausgeführt werden:

tasks:
    - name: build-web-application
      taskRef:
        name: s2i-web-app
        kind: ClusterTask

Diese Aufgabe benötigt Eingabeparameter (Gir-Ressource) und Ausgabeparameter (Ressource für erstellte Webanwendungsbilder). Wir übergeben ihm außerdem einen speziellen Parameter, damit TLS nicht überprüft wird, da wir selbstsignierte Zertifikate verwenden:

resources:
        inputs:
          - name: source
            resource: web-application-repo
        outputs:
          - name: image
            resource: built-web-application-image
      params:
        - name: TLSVERIFY
          value: "false"

Die nächste Aufgabe ist fast dieselbe, nur dass hier die bereits erstellte Clusteraufgabe „webapp-build-runtime“ heißt:

name: build-runtime-image
    taskRef:
      name: webapp-build-runtime
      kind: ClusterTask

Wie bei der vorherigen Aufgabe übergeben wir eine Ressource, aber jetzt ist es „built-web-application-image“ (die Ausgabe unserer vorherigen Aufgabe). Und als Ausgabe setzen wir wieder das Bild. Da diese Aufgabe nach der vorherigen ausgeführt werden muss, fügen wir das Feld runAfter hinzu:

resources:
        inputs:
          - name: image
            resource: built-web-application-image
        outputs:
          - name: image
            resource: runtime-web-application-image
        params:
        - name: TLSVERIFY
          value: "false"
      runAfter:
        - build-web-application

Die nächsten beiden Aufgaben sind für die Verwendung der Service-, Routen- und Bereitstellungs-YAML-Dateien verantwortlich, die sich im k8s-Verzeichnis unserer Webanwendung befinden, und auch für die Aktualisierung dieser Bereitstellung beim Erstellen neuer Images. Wir haben diese beiden Clusteraufgaben am Anfang des Artikels definiert.

Starten des Förderers

Damit sind alle Teile unserer Pipeline erstellt und wir führen sie mit dem folgenden Befehl aus:

$ tkn pipeline start build-and-deploy-react

In dieser Phase wird die Befehlszeile interaktiv verwendet und Sie müssen als Reaktion auf jede ihrer Anforderungen die entsprechenden Ressourcen auswählen: Wählen Sie für die Git-Ressource „web-application-repo“ und dann für die erste Bildressource „built-web-application“ aus -image und schließlich für die zweite Bildressource –runtime-web-application-image:

? Choose the git resource to use for web-application-repo: web-application-repo (https://github.com/nodeshift-starters/react-pipeline-example)
? Choose the image resource to use for built-web-application-image: built-web-application-image (image-registry.openshift-image-registry.svc:5000/webapp-pipeline/built-web-
application:latest)
? Choose the image resource to use for runtime-web-application-image: runtime-web-application-image (image-registry.openshift-image-registry.svc:5000/webapp-pipeline/runtim
e-web-application:latest)
Pipelinerun started: build-and-deploy-react-run-4xwsr

Lassen Sie uns nun den Status der Pipeline mit dem folgenden Befehl überprüfen:

$ tkn pipeline logs -f

Sobald die Pipeline gestartet und die Anwendung bereitgestellt wurde, können wir die veröffentlichte Route mit dem folgenden Befehl anfordern:

$ oc get route react-pipeline-example --template='http://{{.spec.host}}'

Zur besseren Visualisierung können Sie unsere Pipeline im Entwicklermodus der Webkonsole im Abschnitt anzeigen Pipelines, wie in Abb. 1.

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Abb.1. Überprüfung laufender Pipelines.

Durch Klicken auf eine laufende Pipeline werden zusätzliche Details angezeigt, wie in Abbildung 2 dargestellt.

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Reis. 2. Zusätzliche Informationen zur Pipeline.

Nach weiteren Informationen können Sie in der Ansicht laufende Anwendungen sehen Topologie, wie in Abb.3 dargestellt.

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Abb. 3. Gestartete Kapsel.

Durch Klicken auf den Kreis in der oberen rechten Ecke des Symbols wird unsere Anwendung geöffnet, wie in Abb. 4 dargestellt.

Moderne Anwendungen auf OpenShift, Teil 3: OpenShift als Entwicklungsumgebung und OpenShift Pipelines

Reis. 4. React-Anwendung ausführen.

Abschluss

Deshalb haben wir gezeigt, wie Sie einen Entwicklungsserver für Ihre Anwendung unter OpenShift ausführen und ihn mit dem lokalen Dateisystem synchronisieren. Wir haben uns auch angeschaut, wie man mit OpenShift Pipelines eine verkettete Build-Vorlage simuliert. Alle Beispielcodes aus diesem Artikel finden Sie hier hier.

Zusätzliche Ressourcen (EN)

Ankündigungen zu kommenden Webinaren

Wir starten eine Reihe von Freitags-Webinaren über native Erfahrungen mit Red Hat OpenShift Container Platform und Kubernetes:

Source: habr.com

Kommentar hinzufügen