Ausrollen einer dockerisierten Anwendung auf OpenShift – Teil 2/3

Dieser Blogpost ist der zweite Teil der Serie Migration einer dockerisierten Anwendung auf OpenShift und wurde von Angela Stempfel und Christoph Raaflaub verfasst. Dieser Beitrag thematisiert den Aufbau einer OpenShift Konfiguration für das Deployment der Anwendung.

Im ersten Teil dieser Blogpost-Serie wurde aufgezeigt, wie Docker Images für den Betrieb auf OpenShift angepasst werden. Wie bringen wir jedoch diese Docker Images auf OpenShift zum Laufen? Der nächste Schritt ist das Deployment auf OpenShift. Dazu werden die benötigten Ressourcen-Definitionen, sprich OpenShift Konfiguration, engineert.

In diesem Blog zeigen wir anhand dem Kundenprojekt FMSx – Flottenmanagement Extended – die Migration auf die OpenShift Umgebung.

Vorgehen beim Erstellen der OpenShift Ressourcen

Folgende Schritte empfehlen wir beim Erstellen der yaml oder json Dateien, welche die Ressourcen Definitionen enthalten:

• Beim Hersteller nach Konfigurationen suchen
• weitere Suche im Internet (evtl. gibt es nicht-offizielle Beispiele bzw. Anleitungen)

Falls die Suche geglückt ist, sollte es ausprobiert und wenn nötig angepasst werden. Wenn keine passenden Templates oder Beispielprojekte vorhanden sind, ist die folgende Vorgehensweise zu empfehlen.

1. Engineeren der OpenShift Konfiguration
2. Konfiguration der Komponenten.
3. Kommunikation der Komponenten untereinander.

Für das Erstellen der Konfiguration benutze ich Werkzeuge von OpenShift. Mit dem OpenShift Command Line Interface, kurz OC-Tool, haben wir drei nützliche Befehle zur Hand:

  • oc new-build 
    Erstellt die BuildConfiguration mit allen notwendigen Ressourcen
  • oc new-app
    Erstellt die DeploymentConfiguration mit allen notwendigen Ressourcen
  • oc explain service.spec.ports
    Beschreibung für jede Ressource. Hier das Beispiel für die Port Definition der Spec Section innerhalb der Service Ressource.

Diese Befehle generieren für viele verschiedene Technologien automatisch die richtige Konfigurationen in OpenShift. Dabei wird auch der Source-to-Image (S2I) verwendet. Das sind vorgefertigte Build-Container, welche die angegebene Source buildet, paketiert und in ein Docker Image verpackt. Das resultierende Docker Image wird danach auf OpenShift deployed.

Mit dem --dry-run Flag werden keine Ressourcen im OpenShift angelegt. Über das -o yaml Flag lasse ich mir nur den Output der Befehle ausgeben, welchen ich als Basis nehme und danach weiter bearbeite.

oc new-app IMAGE --dry-run -o yaml

Überblick FMSx

FMSx ist das neue Flottenmanagement System der BLS, welche zukünftig als Lösung zur Verwaltung, Aktualisierung und Echtzeit-Überwachung der IT-Systeme einer Fahrzeugflotte eingesetzt wird. Sie beinhaltet im genaueren die Verwaltung und Konfiguration der im Zug installierten Komfortanwendungen (Fahrgastinformationssystem, Videoüberwachungssystem und automatische Fahrgastzählung). Des Weiteren beinhaltet dies die Entgegennahme und Weiterleitung der von Fahrzeuganwendungen generierte Daten an zentrale Systeme. Auch die Überwachung der Komfortanwendungen und Komponenten (z.B. Bildschirme, Anzeigen, Kameras) wird durch das System sichergestellt.

Die Anwendung besteht aus verschiedenen Komponenten und Umsystemen. Die wichtigsten werden in der folgenden Grafik dargestellt:

  • fmsx-web: Administrations User Interface
  • fmsx-cockpit: Backend zum User Interface
  • fmsx-hub: zentraler Kommunikationshub zwischen
    zentralen Anwendungen und angemeldeten
    Fahrzeugen
  • Fahrzeug: Fahrzeuge, welche über FMSx verwaltet werden
  • Message Broker: Messaging Kommunikationslösung der FMSx Komponenten und den Fahrzeugen
  • Minio: Persistierung der Dateien
  • Datenbank: Persistierung der Daten

Deployment Konfiguration

Anhand der FMSx Komponenten zeigen wir das Vorgehen für das Deployment verschiedener Technologien auf OpenShift.

Zuerst müssen alle Komponenten in einem Docker Container laufen. Wie das Dockerfile einer Spring Boot Anwendung aussehen kann, hat euch Christoph bereits im ersten Blogpost dieser Serie erklärt. Danach müssen die OpenShift Konfigurationen, also die *.yaml Files erstellt werden. (Konfigurationsfiles in json sind auch möglich, hier zeigen wir nur die yaml Variante.)
Die Ressourcen-Konfigurationen der FMSx Komponenten verwalten wir in OpenShift Templates. Damit können wir zum Zeitpunkt der Erstellung einzelne Werte mittels Parameter überschreiben.

Message Broker

Die FMSx Komponenten benutzen Messaging zur Kommunikation untereinander und auch mit den Fahrzeugen. Dazu haben wir den OpenSource Message Broker RabbitMQ gewählt.

Es gibt beim Hersteller ein offizielles Beispiel für das Deployment auf Kubernetes. Weil OpenShift eine Kubernetes Distribution ist, können wir diese Konfiguration verwenden. Wir haben das Beispiel leicht angepasst.

Wichtig beim Erstellen des yaml ist der Service-Name der Komponente.

- kind: Service
 apiVersion: v1
 metadata:
   name: message-broker
   labels:
     app: rabbitmq
     type: LoadBalancer

Der Name des RabbitMQ Broker Service ist message-broker, damit können andere Komponenten auf diesen zugreifen, bzw. diesen referenzieren. Dies werden wir in einem späteren Abschnitt sehen.

FMSx Hub, Cockpit (Java)

Diese zwei Komponenten enthalten die Flottenmanagement Logik.
Java Deployments sind einfach zu erstellen. Als Basis ist es von Vorteil, die Templates von OpenShift zu verwenden. In der OpenShift Web Console können wir das z.B das OpenJDK Template aus dem Catalog auswählen, dasselbe Template mit dem oc Tool aus dem openshift Namespace anwenden oder mit oc new-app docker-registery/image:tag erstellen.

Im FMSx setzen wir bei den Java Komponenten Spring Boot ein. Die Docker Images werden ausserhalb der Plattform gebaut, was dazu führt, dass wir die Build-Features vom OpenShift nicht benötigen.

In den folgenden Kapiteln erklären wir die benötigen OpenShift Ressourcen für den Betrieb der Java Spring Boot Anwendungen.

ImageStream
Der ImageStream ist die Referenz auf das Docker Image. Die Docker Images sind auf einer Docker Registry verfügbar.
Mit dem oc Tool können die Docker Images auf die OpenShift Plattform importiert werden: oc import-image

OpenShift Dokumentation

DeploymentConfiguration
Mit einer DeploymentConfiguration definieren wir im OpenShift, wie ein Docker Container betrieben werden soll.
Nachfolgend erläutern wir ein paar wichtige Abschnitte der DeploymentConfiguration, welche den Docker Container betreffen.

Umgebungsvariablen
Die Java Komponenten werden über Umgebungsvariablen für die verschiedenen Stages konfiguriert.

Auszug aus der FMSx-hub DeploymentConfiguration (Template)

apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
...
spec:
  ...
  template:
    ...
    spec:
      containers:
        - env:
            - name: SPRING_PROFILES_ACTIVE
              value: ${SPRING_PROFILES_ACTIVE}
            - name: AMQP_BROKER_HOSTNAME
              value: ${AMQP_BROKER_HOSTNAME}
            - name: AMQP_BROKER_PORT
              value: ${AMQP_BROKER_PORT}

Alle Umgebungsvariablen können im Template unter Parameters mit einem Initialwert definiert werden:

apiVersion: v1
kind: Template
metadata:
  name: fmsx-hub-template
objects:
  ...
parameters:
  - name: SPRING_PROFILES_ACTIVE
    description: Spring Profile to use
    value: h2
  - name: AMQP_BROKER_HOSTNAME
    description: Broker Url
    value: 'message-broker'
  - name: AMQP_BROKER_PORT
    description: Broker Port
    value: '5672'

Eine wichtige Umgebungsvariable ist die SPRING_PROFILES_ACTIVE Variable, welche das Spring Profile der Spring Boot Anwendung setzt. Damit wird definiert, mit welchem Profil die Anwendung laufen soll. So können wir verschiedene Ausprägungen der Anwendung unterscheiden. Einfache Umgebungen laufen z.B. mit einer In-Memory Datenbank und benötigen keine Konfiguration einer externen Datenbank.

Health Endpoints (Liveness & Readiness)
Wichtig ist es, dass diese Endpoints für alle Anwendungen definiert sind. Hiermit kann OpenShift den Zustand der Anwendung jederzeit abfragen.
Was genau der Unterschied zwischen der Readiness und Liveness ist könnt Ihr in diesem Blogpost nachlesen.

Bei Spring Boot wird oft die Actuator Library für Health Endpoints eingesetzt. So sieht die Definition in der DeploymentConfiguration aus:

apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
...
spec:
  ...
  template:
    ...
    spec:
      containers:
        ...
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /actuator/health
              port: 8081
              scheme: HTTP
            initialDelaySeconds: 120
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 2
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /actuator/health
              port: 8081
              scheme: HTTP
            initialDelaySeconds: 90
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 2

Request und Limits
Durch die Requests und Limits werden die Ressourcen, die ein Pod benutzen kann definiert. Dies ist wichtig für eine optimale Performance der Anwendungen:

apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
...
spec:
  ...
  template:
    ...
    spec:
      containers:
        ...
          resources:
            limits:
              cpu: 500m
              memory: 2Gi
            requests:
              cpu: 200m
              memory: 1Gi    

Netzwerk / Routing

Folgend eine Übersicht zum Routing, die zeigt, wie eine Anwendung / ein Container ihren Service zur Verfügung stellen kann. Dieses Zusammenspiel der verschiedenen Komponenten und Ressourcen sollte für das Erstellen der Konfiguration beachtet werden.

  • Der Service ermöglicht, innerhalb des Projektes, den Zugriff auf den Container.
  • Eine Route muss erstellt werden, damit der Service von ausserhalb OpenShift erreichbar ist. OpenShift erhält über die Route die Konfigurationsangaben für den Router.

Services
Wie im vorherigen Abschnitt erklärt, benötigt der Docker Container einen OpenShift Service, damit er seinen Service, z.B. eine API Schnittstelle, zur Verfügung stellen kann.
Der Service des der Komponente fmsx-hub ist wie folgt definiert:

apiVersion: v1
kind: Service
metadata:
  name: fmsx-hub
spec:
  ports:
    - name: 8081-tcp
      port: 8081
      protocol: TCP
      targetPort: 8081
    ...   

Die Anwendung fmsx-cockpit kommuniziert mit dem fmsx-hub und referenziert diesen über den Service-Namen. Dieser wird mit dem OpenShift DNS zu einer IP-Adresse aufgelöst.

containers:
  - env:
      - name: FMSX_HUB_URL
        value: 'http://fmsx-hub:8081/fmsx-hub'
      ...

Routen
Routen werden definiert, damit die Anwendungen über eine URL, von ausserhalb des OpenShift Cluster, erreichbar sind.

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: fmsx-cockpit
spec:
  host: fmsx-cockpit-stage-project.ocp.cluster.example
  port:
    targetPort: 8080-tcp
  to:
    kind: Service
    name: fmsx-cockpit       

Durch die obige Definition kann nun auf das Frontend über folgende URL zugegriffen werden:

Fazit

Wir hoffen, dass euch dieser Blogpost dabei hilft, Anwendungen auf OpenShift zu migrieren und welche Schritte beachtet werden müssen. In unserem nächsten und letzten Blogpost, welcher in einigen Wochen erscheint, möchten wir euch zeigen, wie unsere Jenkins Pipeline dazu aussieht.

Kommentare sind geschlossen.