Einführung in die serverlose Orchestrierung mit Workflows

1. Einführung

c9b0cc839df0bb8f.png

Mit Workflows können Sie serverlose Workflows erstellen, die eine Reihe von serverlosen Aufgaben in einer von Ihnen definierten Reihenfolge verknüpfen. Sie können die Leistungsfähigkeit der APIs von Google Cloud, serverlose Produkte wie Cloud Functions und Cloud Run sowie Aufrufe von externen APIs kombinieren, um flexible serverlose Anwendungen zu erstellen.

Workflows erfordern keine Infrastrukturverwaltung und skalieren nahtlos mit der Nachfrage, einschließlich der Skalierung auf null. Mit dem nutzungsbasierten Preismodell zahlen Sie nur für die Ausführungszeit.

In diesem Codelab erfahren Sie, wie Sie verschiedene Google Cloud-Dienste und externe HTTP-APIs mit Workflows verbinden. Genauer gesagt, verbinden Sie zwei öffentliche Cloud Functions-Dienste, einen privaten Cloud Run-Dienst und eine externe öffentliche HTTP-API in einem Workflow.

Lerninhalte

  • Grundlagen von Workflows.
  • So stellen Sie eine Verbindung zwischen öffentlichen Cloud Functions und Workflows her.
  • Private Cloud Run-Dienste mit Workflows verbinden
  • Externe HTTP-APIs mit Workflows verbinden

2. Einrichtung und Anforderungen

Umgebung zum selbstbestimmten Lernen einrichten

  1. Melden Sie sich in der Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Gmail- oder G Suite-Konto haben, müssen Sie eines erstellen.

H_hgylo4zxOllHaAbPKJ7VyqCKPDUnDhkr-BsBIFBsrB6TYSisg6LX-uqmMhh4sXUy_hoa2Qv87C2nFmkg-QAcCiZZp0qtpf6VPaNEEfP_iqt29KVLD-gklBWugQVeOWsFnJmNjHDw

dcCPqfBIwNO4R-0fNQLUC4aYXOOZhKhjUnakFLZJGeziw2ikOxGjGkCHDwN5x5kCbPFB8fiOzZnX-GfuzQ8Ox-UU15BwHirkVPR_0RJwl0oXrhqZmMIvZMa_uwHugBJIdx5-bZ6Z8Q

jgLzVCxk93d6E2bbonzATKA4jFZReoQ-fORxZZLEi5C3D-ubnv6nL-eP-iyh7qAsWyq_nyzzuEoPFD1wFOFZOe4FWhPBJjUDncnTxTImT3Ts9TM54f4nPpsAp52O0y3Cb19IceAEgQ

Notieren Sie sich die Projekt-ID, also den projektübergreifend nur einmal vorkommenden Namen eines Google Cloud-Projekts. Der oben angegebene Name ist bereits vergeben und kann leider nicht mehr verwendet werden. Sie wird später in diesem Codelab als PROJECT_ID bezeichnet.

  1. Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Google Cloud-Ressourcen verwenden zu können.

Die Durchführung dieses Codelabs sollte keine oder nur geringe Kosten verursachen. Folgen Sie bitte der Anleitung im Abschnitt „Bereinigen“, in der Sie erfahren, wie Sie Ressourcen herunterfahren können, damit nach Abschluss dieser Anleitung keine Gebühren anfallen. Neue Nutzer von Google Cloud kommen für das Programm für den kostenlosen Testzeitraum mit einem Guthaben von 300$ infrage.

Cloud Shell starten

Während Sie Google Cloud von Ihrem Laptop aus per Fernzugriff nutzen können, wird in diesem Codelab Google Cloud Shell verwendet, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.

Klicken Sie in der GCP Console oben rechts in der Symbolleiste auf das Cloud Shell-Symbol:

STgwiN06Y0s_gL7i9bTed8duc9tWOIaFw0z_4QOjc-jeOmuH2TBK8l4udei56CKPLoM_i1yEF6pn5Ga88eniJQoEh8cAiTH79gWUHJdKOw0oiBZfBpOdcEOl6p29i4mvPe_A6UMJBQ

Die Bereitstellung und Verbindung mit der Umgebung sollte nur wenige Augenblicke dauern. Anschließend sehen Sie in etwa Folgendes:

r6WRHJDzL-GdB5VDxMWa67_cQxRR_x_xCG5xdt9Nilfuwe9fTGAwM9XSZbNPWvDSFtrZ7DDecKqR5_pIq2IJJ9puAMkC3Kt4JbN9jfMX3gAwTNHNqFmqOJ-3iIX5HSePO4dNVZUkNA

Diese virtuelle Maschine verfügt über sämtliche Entwicklertools, die Sie benötigen. Sie bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und läuft in Google Cloud, was die Netzwerkleistung und Authentifizierung erheblich verbessert. Für dieses Lab benötigen Sie lediglich einen Browser.

3. Workflows – Übersicht

Grundlagen

Ein Workflow besteht aus einer Reihe von Schritten, die mit der YAML-basierten Syntax für Workflows beschrieben werden. Dies ist die Definition des Workflows. Eine ausführliche Erläuterung der YAML-Syntax für Workflows finden Sie auf der Seite Syntaxreferenz.

Wenn ein Workflow erstellt wird, wird er bereitgestellt. Dadurch ist der Workflow für die Ausführung bereit. Eine Ausführung ist ein einzelner Durchlauf der Logik, die in der Definition eines Workflows enthalten ist. Alle Workflowausführungen sind unabhängig und das Produkt unterstützt eine hohe Anzahl gleichzeitiger Ausführungen.

Dienste aktivieren

In diesem Codelab verbinden Sie Cloud Functions und Cloud Run-Dienste mit Workflows. Sie verwenden Cloud Build und Cloud Storage auch beim Erstellen von Diensten.

Aktivieren Sie alle erforderlichen Dienste:

gcloud services enable \
  cloudfunctions.googleapis.com \
  run.googleapis.com \
  workflows.googleapis.com \
  cloudbuild.googleapis.com \
  storage.googleapis.com

Im nächsten Schritt verbinden Sie zwei Cloud Functions-Funktionen in einem Workflow.

4. Erste Cloud Functions-Funktion bereitstellen

Die erste Funktion ist ein Zufallszahlengenerator in Python.

Erstellen Sie ein Verzeichnis für den Funktionscode und wechseln Sie in dieses Verzeichnis:

mkdir ~/randomgen
cd ~/randomgen

Erstellen Sie eine main.py-Datei im Verzeichnis mit folgendem Inhalt:

import random, json
from flask import jsonify

def randomgen(request):
    randomNum = random.randint(1,100)
    output = {"random":randomNum}
    return jsonify(output)

Wenn diese Funktion eine HTTP-Anfrage empfängt, generiert sie eine zufällige Zahl zwischen 1 und 100 und gibt sie im JSON-Format an den Aufrufer zurück.

Die Funktion basiert auf Flask für die HTTP-Verarbeitung und muss als Abhängigkeit hinzugefügt werden. Abhängigkeiten in Python werden mit pip verwaltet und in einer Metadatendatei mit dem Namen requirements.txt ausgedrückt.

Erstellen Sie im selben Verzeichnis eine requirements.txt-Datei mit folgendem Inhalt:

flask>=1.0.2

Stellen Sie die Funktion mit einem HTTP-Trigger bereit und lassen Sie nicht authentifizierte Anfragen mit diesem Befehl zu:

gcloud functions deploy randomgen \
    --runtime python312 \
    --trigger-http \
    --allow-unauthenticated

Sobald die Funktion bereitgestellt wurde, können Sie die URL der Funktion in der Konsole unter dem Attribut url oder mit dem Befehl gcloud functions describe aufrufen.

Sie können die URL der Funktion auch mit dem folgenden curl-Befehl aufrufen:

curl $(gcloud functions describe randomgen --format='value(url)')

Die Funktion ist für den Workflow bereit.

5. Zweite Cloud Functions-Funktion bereitstellen

Die zweite Funktion ist ein Multiplikator. Die empfangene Eingabe wird mit 2 multipliziert.

Erstellen Sie ein Verzeichnis für den Funktionscode und wechseln Sie in dieses Verzeichnis:

mkdir ~/multiply
cd ~/multiply

Erstellen Sie eine main.py-Datei im Verzeichnis mit folgendem Inhalt:

import random, json
from flask import jsonify

def multiply(request):
    request_json = request.get_json()
    output = {"multiplied":2*request_json['input']}
    return jsonify(output)

Wenn diese Funktion eine HTTP-Anfrage empfängt, extrahiert sie den input aus dem JSON-Text, multipliziert ihn mit 2 und gibt das Ergebnis im JSON-Format an den Aufrufer zurück.

Erstellen Sie dieselbe requirements.txt-Datei im selben Verzeichnis mit folgendem Inhalt:

flask>=1.0.2

Stellen Sie die Funktion mit einem HTTP-Trigger bereit und lassen Sie nicht authentifizierte Anfragen mit diesem Befehl zu:

gcloud functions deploy multiply \
    --runtime python312 \
    --trigger-http \
    --allow-unauthenticated

Sobald die Funktion bereitgestellt wurde, können Sie die URL der Funktion auch mit dem folgenden curl-Befehl aufrufen:

curl $(gcloud functions describe multiply --format='value(url)') \
-X POST \
-H "content-type: application/json" \
-d '{"input": 5}'

Die Funktion ist für den Workflow bereit.

6. Zwei Cloud Functions verbinden

Verbinden Sie im ersten Workflow die beiden Funktionen.

Erstellen Sie eine workflow.yaml-Datei mit folgendem Inhalt.

- randomgenFunction:
    call: http.get
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/randomgen
    result: randomgenResult
- multiplyFunction:
    call: http.post
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/multiply
        body:
            input: ${randomgenResult.body.random}
    result: multiplyResult
- returnResult:
    return: ${multiplyResult}

In diesem Workflow rufen Sie eine Zufallszahl aus der ersten Funktion ab und übergeben sie an die zweite Funktion. Das Ergebnis ist die multiplizierte Zufallszahl.

Stellen Sie den ersten Workflow bereit:

gcloud workflows deploy workflow --source=workflow.yaml

Führen Sie den ersten Workflow aus:

gcloud workflows execute workflow

Nachdem der Workflow ausgeführt wurde, können Sie das Ergebnis mit der Ausführungs-ID aus dem vorherigen Schritt aufrufen:

gcloud workflows executions describe <your-execution-id> --workflow workflow

Die Ausgabe enthält result und state:

result: '{"body":{"multiplied":108},"code":200 ... } 

...
state: SUCCEEDED

7. Externe HTTP-API verbinden

Als Nächstes verbinden Sie math.js als externen Dienst im Workflow.

In math.js können Sie mathematische Ausdrücke so auswerten:

curl https://api.mathjs.org/v4/?'expr=log(56)'

Dieses Mal verwenden Sie die Cloud Console, um den Workflow zu aktualisieren. So finden Sie Workflows in der Google Cloud Console:

7608a7991b33bbb0.png

Suchen Sie Ihren Workflow und klicken Sie auf den Tab Definition:

f3c8c4d3ffa49b1b.png

Bearbeiten Sie die Workflowdefinition und fügen Sie einen Aufruf von math.js ein.

- randomgenFunction:
    call: http.get
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/randomgen
    result: randomgenResult
- multiplyFunction:
    call: http.post
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/multiply
        body:
            input: ${randomgenResult.body.random}
    result: multiplyResult
- logFunction:
    call: http.get
    args:
        url: https://api.mathjs.org/v4/
        query:
            expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
    result: logResult
- returnResult:
    return: ${logResult}

Der Workflow übergibt die Ausgabe der Multiplikationsfunktion jetzt an einen Log-Funktionsaufruf in math.js.

Die Benutzeroberfläche führt Sie durch die Bearbeitung und Bereitstellung des Workflows. Klicken Sie nach der Bereitstellung auf Execute, um den Workflow auszuführen. Es werden die Details der Ausführung angezeigt:

b40c76ee43a1ce65.png

Beachten Sie den Statuscode 200 und ein body mit der Ausgabe der Log-Funktion.

Du hast gerade einen externen Dienst in unseren Workflow integriert. Das ist super!

8. Cloud Run-Dienst bereitstellen

Im letzten Teil wird der Workflow mit einem Aufruf eines privaten Cloud Run-Dienstes abgeschlossen. Das bedeutet, dass der Workflow authentifiziert werden muss, um den Cloud Run-Dienst aufzurufen.

Der Cloud Run-Dienst gibt den math.floor der übergebenen Zahl zurück.

Erstellen Sie ein Verzeichnis für den Dienstcode und wechseln Sie in dieses Verzeichnis:

mkdir ~/floor
cd ~/floor

Erstellen Sie eine app.py-Datei im Verzeichnis mit folgendem Inhalt:

import json
import logging
import os
import math

from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['POST'])
def handle_post():
    content = json.loads(request.data)
    input = float(content['input'])
    return f"{math.floor(input)}", 200

if __name__ != '__main__':
    # Redirect Flask logs to Gunicorn logs
    gunicorn_logger = logging.getLogger('gunicorn.error')
    app.logger.handlers = gunicorn_logger.handlers
    app.logger.setLevel(gunicorn_logger.level)
    app.logger.info('Service started...')
else:
    app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

Cloud Run stellt Container bereit, daher benötigen Sie ein Dockerfile. Ihr Container muss an die Umgebungsvariablen 0.0.0.0 und PORT gebunden werden. Daher ist der Code oben erforderlich.

Wenn diese Funktion eine HTTP-Anfrage empfängt, extrahiert sie den input aus dem JSON-Text, ruft math.floor auf und gibt das Ergebnis an den Aufrufer zurück.

Erstellen Sie im selben Verzeichnis die folgende Dockerfile:

# Use an official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.7-slim

# Install production dependencies.
RUN pip install Flask gunicorn

# Copy local code to the container image.
WORKDIR /app
COPY . .

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app

Erstellen Sie den Container:

export SERVICE_NAME=floor
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

Nachdem der Container erstellt wurde, stellen Sie ihn in Cloud Run bereit. Beachten Sie das Flag no-allow-unauthenticated. Dadurch wird sichergestellt, dass der Dienst nur authentifizierte Aufrufe akzeptiert:

gcloud run deploy ${SERVICE_NAME} \
  --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
  --platform managed \
  --no-allow-unauthenticated

Nach der Bereitstellung ist der Dienst für den Workflow bereit.

9. Cloud Run-Dienst verbinden

Bevor Sie Workflows so konfigurieren können, dass der private Cloud Run-Dienst aufgerufen wird, müssen Sie ein Dienstkonto für Workflows erstellen:

export SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT}

Weisen Sie dem Dienstkonto die Rolle run.invoker zu. Dadurch kann das Dienstkonto authentifizierte Cloud Run-Dienste aufrufen:

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
    --member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
    --role "roles/run.invoker"

Aktualisieren Sie die Workflowdefinition in workflow.yaml, um den Cloud Run-Dienst einzuschließen. Beachten Sie, dass Sie auch das Feld auth einfügen, damit Workflows das Authentifizierungstoken in seinen Aufrufen des Cloud Run-Dienstes übergibt:

- randomgenFunction:
    call: http.get
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/randomgen
    result: randomgenResult
- multiplyFunction:
    call: http.post
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/multiply
        body:
            input: ${randomgenResult.body.random}
    result: multiplyResult
- logFunction:
    call: http.get
    args:
        url: https://api.mathjs.org/v4/
        query:
            expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
    result: logResult
- floorFunction:
    call: http.post
    args:
        url: https://floor-<random-hash>.run.app
        auth:
            type: OIDC
        body:
            input: ${logResult.body}
    result: floorResult
- returnResult:
    return: ${floorResult}

Workflow aktualisieren Diesmal wird das Dienstkonto übergeben:

gcloud workflows deploy workflow \
    --source=workflow.yaml \
    --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com

Führen Sie den Workflow aus:

gcloud workflows execute workflow

Nach einigen Sekunden können Sie sich die Workflowausführung ansehen, um das Ergebnis zu sehen:

gcloud workflows executions describe <your-execution-id> --workflow workflow

Die Ausgabe enthält die Ganzzahlen result und state:

result: '{"body":"5","code":200 ... } 

...
state: SUCCEEDED

10. Glückwunsch!

Herzlichen Glückwunsch zum Abschluss des Codelabs.

Behandelte Themen

  • Grundlagen von Workflows.
  • So stellen Sie eine Verbindung zwischen öffentlichen Cloud Functions und Workflows her.
  • Private Cloud Run-Dienste mit Workflows verbinden
  • Externe HTTP-APIs mit Workflows verbinden