1. Einführung
Übersicht
Cloud Run-Dienste eignen sich gut für Container, die unbegrenzt laufend auf HTTP-Anfragen warten. Cloud Run-Jobs eignen sich dagegen besser für Container, die bis zum Ende ausgeführt werden (derzeit bis zu 24 Stunden) und keine Anfragen verarbeiten. Zum Beispiel wäre die Verarbeitung von Datensätzen aus einer Datenbank, die Verarbeitung einer Liste von Dateien aus einem Cloud Storage-Bucket oder ein Vorgang mit langer Ausführungszeit wie die Berechnung von Pi gut geeignet, wenn sie als Cloud Run-Job implementiert würden.
Jobs können keine Anfragen verarbeiten oder einen Port überwachen. Das bedeutet, dass Jobs im Gegensatz zu Cloud Run-Diensten keinen Webserver bündeln sollten. Stattdessen sollten Jobcontainer beendet werden, sobald sie abgeschlossen sind.
In Cloud Run-Jobs können Sie mehrere Kopien des Containers parallel ausführen. Dazu geben Sie eine Reihe von Aufgaben an. Jede Aufgabe stellt eine laufende Kopie des Containers dar. Die Verwendung mehrerer Aufgaben ist nützlich, wenn jede Aufgabe eine Teilmenge der Daten unabhängig verarbeiten kann. So lässt sich beispielsweise die Verarbeitung von 10.000 Datensätzen aus Cloud SQL oder von 10.000 Dateien aus Cloud Storage schneller erledigen, wenn 10 Aufgaben parallel 1.000 Datensätze oder Dateien verarbeiten.
Die Verwendung von Cloud Run-Jobs erfolgt in zwei Schritten:
- Job erstellen:Enthält die gesamte Konfiguration, die zum Ausführen des Jobs erforderlich ist, z. B. das Container-Image, die Region und die Umgebungsvariablen.
- Job ausführen:Der Job wird neu ausgeführt. Optional können Sie Ihren Job so einrichten, dass er nach einem Zeitplan mit Cloud Scheduler ausgeführt wird.
In diesem Codelab lernen Sie zuerst eine Node.js-Anwendung kennen, mit der Sie Screenshots von Webseiten erstellen und in Cloud Storage speichern können. Anschließend erstellen Sie ein Container-Image für die Anwendung, führen sie in Cloud Run-Jobs aus, aktualisieren den Job, um mehr Webseiten zu verarbeiten, und führen den Job nach einem Zeitplan mit Cloud Scheduler aus.
Lerninhalte
- Screenshots von Webseiten mit einer App aufnehmen
- So erstellen Sie ein Container-Image für die Anwendung.
- Cloud Run-Job für die Anwendung erstellen
- So führen Sie die Anwendung als Cloud Run-Job aus.
- So aktualisieren Sie den Job.
- Den Job mit Cloud Scheduler planen
2. Einrichtung und Anforderungen
Umgebung zum selbstbestimmten Lernen einrichten
- Melden Sie sich in der Google Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eines erstellen.
- Der Projektname ist der Anzeigename für die Projektteilnehmer. Es handelt sich um eine Zeichenfolge, die von Google APIs nicht verwendet wird. Sie können sie jederzeit aktualisieren.
- Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich. Sie kann nach dem Festlegen nicht mehr geändert werden. Die Cloud Console generiert automatisch einen eindeutigen String. ist Ihnen meist egal, was es ist. In den meisten Codelabs musst du auf deine Projekt-ID verweisen, die üblicherweise als
PROJECT_ID
bezeichnet wird. Wenn Ihnen die generierte ID nicht gefällt, können Sie eine weitere zufällige ID generieren. Alternativ können Sie einen eigenen verwenden und nachsehen, ob er verfügbar ist. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts erhalten. - Zur Information gibt es noch einen dritten Wert, die Projektnummer, die von manchen APIs verwendet wird. Weitere Informationen zu allen drei Werten finden Sie in der Dokumentation.
- Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Cloud-Ressourcen/APIs verwenden zu können. Dieses Codelab ist kostengünstig. Sie können die von Ihnen erstellten Ressourcen oder das Projekt löschen, um Ressourcen herunterzufahren, um zu vermeiden, dass über diese Anleitung hinaus Kosten anfallen. Neue Google Cloud-Nutzer haben Anspruch auf das kostenlose Testprogramm mit 300$Guthaben.
Cloud Shell starten
Sie können Google Cloud zwar von Ihrem Laptop aus der Ferne bedienen, in diesem Codelab verwenden Sie jedoch Google Cloud Shell, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.
Klicken Sie in der Google Cloud Console rechts oben in der Symbolleiste auf das Cloud Shell-Symbol:
Die Bereitstellung und Verbindung mit der Umgebung dauert nur einen Moment. Wenn er abgeschlossen ist, sollten Sie in etwa Folgendes sehen:
Diese virtuelle Maschine verfügt über sämtliche Entwicklertools, die Sie benötigen. Es bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und läuft auf Google Cloud, wodurch die Netzwerkleistung und Authentifizierung erheblich verbessert werden. Alle Arbeiten in diesem Codelab können in einem Browser erledigt werden. Sie müssen nichts installieren.
gcloud einrichten
Legen Sie in Cloud Shell Ihre Projekt-ID und die Region fest, in der Sie den Cloud Run-Job bereitstellen möchten. Speichern Sie sie als Variablen des Typs PROJECT_ID
und REGION
. In Zukunft können Sie eine Region aus einem der Cloud Run-Standorte auswählen.
PROJECT_ID=[YOUR-PROJECT-ID] REGION=us-central1 gcloud config set core/project $PROJECT_ID
APIs aktivieren
Aktivieren Sie alle erforderlichen Dienste:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ run.googleapis.com
3. Code abrufen
Sie erkunden zuerst eine Node.js-Anwendung, um Screenshots von Webseiten zu erstellen und sie in Cloud Storage zu speichern. Später erstellen Sie ein Container-Image für die Anwendung und führen es als Job in Cloud Run aus.
Führen Sie in Cloud Shell den folgenden Befehl aus, um den Anwendungscode aus diesem Repository zu klonen:
git clone https://github.com/GoogleCloudPlatform/jobs-demos.git
Wechseln Sie zum Verzeichnis mit der Anwendung:
cd jobs-demos/screenshot
Sie sollten dieses Dateilayout sehen:
screenshot | ├── Dockerfile ├── README.md ├── screenshot.js ├── package.json
Nachfolgend finden Sie eine kurze Beschreibung der einzelnen Dateien:
screenshot.js
enthält den Node.js-Code für die Anwendung.package.json
definiert die Bibliotheksabhängigkeiten.Dockerfile
definiert das Container-Image.
4. Code ansehen
Mit dem integrierten Texteditor können Sie sich den Code ansehen. Klicken Sie dazu oben im Cloud Shell-Fenster auf die Schaltfläche Open Editor
.
Im Folgenden werden die einzelnen Dateien kurz erläutert.
screenshot.js
screenshot.js
fügt zuerst Puppeteer und Cloud Storage als Abhängigkeiten hinzu. Puppeteer ist eine Node.js-Bibliothek, mit der Sie Screenshots von Webseiten erstellen können:
const puppeteer = require('puppeteer'); const {Storage} = require('@google-cloud/storage');
Es gibt eine initBrowser
-Funktion zum Initialisieren von Puppeteer und die takeScreenshot
-Funktion, um Screenshots einer bestimmten URL zu erstellen:
async function initBrowser() { console.log('Initializing browser'); return await puppeteer.launch(); } async function takeScreenshot(browser, url) { const page = await browser.newPage(); console.log(`Navigating to ${url}`); await page.goto(url); console.log(`Taking a screenshot of ${url}`); return await page.screenshot({ fullPage: true }); }
Als Nächstes gibt es eine Funktion zum Abrufen oder Erstellen eines Cloud Storage-Buckets und eine weitere Funktion zum Hochladen des Screenshots einer Webseite in einen Bucket:
async function createStorageBucketIfMissing(storage, bucketName) { console.log(`Checking for Cloud Storage bucket '${bucketName}' and creating if not found`); const bucket = storage.bucket(bucketName); const [exists] = await bucket.exists(); if (exists) { // Bucket exists, nothing to do here return bucket; } // Create bucket const [createdBucket] = await storage.createBucket(bucketName); console.log(`Created Cloud Storage bucket '${createdBucket.name}'`); return createdBucket; } async function uploadImage(bucket, taskIndex, imageBuffer) { // Create filename using the current time and task index const date = new Date(); date.setMinutes(date.getMinutes() - date.getTimezoneOffset()); const filename = `${date.toISOString()}-task${taskIndex}.png`; console.log(`Uploading screenshot as '${filename}'`) await bucket.file(filename).save(imageBuffer); }
Die Funktion main
ist der Einstiegspunkt:
async function main(urls) { console.log(`Passed in urls: ${urls}`); const taskIndex = process.env.CLOUD_RUN_TASK_INDEX || 0; const url = urls[taskIndex]; if (!url) { throw new Error(`No url found for task ${taskIndex}. Ensure at least ${parseInt(taskIndex, 10) + 1} url(s) have been specified as command args.`); } const bucketName = process.env.BUCKET_NAME; if (!bucketName) { throw new Error('No bucket name specified. Set the BUCKET_NAME env var to specify which Cloud Storage bucket the screenshot will be uploaded to.'); } const browser = await initBrowser(); const imageBuffer = await takeScreenshot(browser, url).catch(async err => { // Make sure to close the browser if we hit an error. await browser.close(); throw err; }); await browser.close(); console.log('Initializing Cloud Storage client') const storage = new Storage(); const bucket = await createStorageBucketIfMissing(storage, bucketName); await uploadImage(bucket, taskIndex, imageBuffer); console.log('Upload complete!'); } main(process.argv.slice(2)).catch(err => { console.error(JSON.stringify({severity: 'ERROR', message: err.message})); process.exit(1); });
Beachten Sie Folgendes bei der Methode main
:
- URLs werden als Argumente übergeben.
- Der Bucket-Name wird als benutzerdefinierte
BUCKET_NAME
-Umgebungsvariable übergeben. Der Bucket-Name muss global in Google Cloud eindeutig sein. - Die Umgebungsvariable
CLOUD_RUN_TASK_INDEX
wird von Cloud Run-Jobs übergeben. Cloud Run-Jobs können mehrere Kopien der Anwendung als einzelne Aufgaben ausführen.CLOUD_RUN_TASK_INDEX
steht für den Index der laufenden Aufgabe. Der Standardwert ist null, wenn der Code außerhalb von Cloud Run-Jobs ausgeführt wird. Wenn die Anwendung als mehrere Aufgaben ausgeführt wird, ruft jede Aufgabe bzw. jeder Container die entsprechende URL ab, erstellt einen Screenshot und speichert das Bild im Bucket.
package.json
Die Datei package.json
definiert die Anwendung und gibt die Abhängigkeiten für Cloud Storage und Puppeteer an:
{ "name": "screenshot", "version": "1.0.0", "description": "Create a job to capture screenshots", "main": "screenshot.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Google LLC", "license": "Apache-2.0", "dependencies": { "@google-cloud/storage": "^5.18.2", "puppeteer": "^13.5.1" } }
Dockerfile
Dockerfile
definiert das Container-Image für die Anwendung mit allen erforderlichen Bibliotheken und Abhängigkeiten:
FROM ghcr.io/puppeteer/puppeteer:16.1.0 COPY package*.json ./ RUN npm ci --omit=dev COPY . . ENTRYPOINT ["node", "screenshot.js"]
5. Job bereitstellen
Bevor Sie einen Job erstellen, müssen Sie ein Dienstkonto erstellen, mit dem Sie den Job ausführen.
gcloud iam service-accounts create screenshot-sa --display-name="Screenshot app service account"
Weisen Sie dem Dienstkonto die Rolle storage.admin
zu, damit es zum Erstellen von Buckets und Objekten verwendet werden kann.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/storage.admin \ --member serviceAccount:screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
Sie können jetzt einen Cloud Run-Job bereitstellen, der die zum Ausführen des Jobs erforderliche Konfiguration enthält.
gcloud beta run jobs deploy screenshot \ --source=. \ --args="https://example.com" \ --args="https://cloud.google.com" \ --tasks=2 \ --task-timeout=5m \ --region=$REGION \ --set-env-vars=BUCKET_NAME=screenshot-$PROJECT_ID \ --service-account=screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
Dadurch wird die quellbasierte Bereitstellung verwendet und ein Cloud Run-Job erstellt, ohne ihn auszuführen.
Beachten Sie, wie die Webseiten als Argumente übergeben werden. Der Bucket-Name zum Speichern der Screenshots wird als Umgebungsvariable übergeben.
Sie können mehrere Kopien des Containers parallel ausführen. Geben Sie dazu mit dem Flag --tasks
eine Reihe von Aufgaben an, die ausgeführt werden sollen. Jede Aufgabe stellt eine laufende Kopie des Containers dar. Die Verwendung mehrerer Aufgaben ist nützlich, wenn jede Aufgabe eine Teilmenge der Daten unabhängig verarbeiten kann. Zu diesem Zweck erkennt jede Aufgabe ihren Index, der in der Umgebungsvariablen CLOUD_RUN_TASK_INDEX
gespeichert ist. Ihr Code ist dafür verantwortlich, zu bestimmen, welche Aufgabe welche Teilmenge der Daten verarbeitet. Beachten Sie in diesem Beispiel --tasks=2
. Dadurch werden zwei Container für die beiden URLs ausgeführt, die verarbeitet werden sollen.
Jede Task kann bis zu 24 Stunden ausgeführt werden. Sie können dieses Zeitlimit mit dem Flag --task-timeout
verkürzen, wie in diesem Beispiel. Alle Aufgaben müssen erfolgreich sein, damit der Job erfolgreich abgeschlossen werden kann. Standardmäßig werden fehlgeschlagene Aufgaben nicht wiederholt. Sie können festlegen, dass Aufgaben wiederholt werden sollen, wenn sie fehlschlagen. Wenn eine Aufgabe die Anzahl der Wiederholungsversuche überschreitet, schlägt der gesamte Job fehl.
Ihr Job wird standardmäßig mit so vielen Aufgaben wie möglich parallel ausgeführt. Dies entspricht der Anzahl der Tasks für Ihren Job bis maximal 100. Sie können die Parallelität für Jobs verringern, die auf ein Backend mit eingeschränkter Skalierbarkeit zugreifen. Beispiel: eine Datenbank, die eine begrenzte Anzahl aktiver Verbindungen unterstützt. Sie können die Parallelität mit dem Flag --parallelism
verringern.
6. Job ausführen
Bevor Sie den Job ausführen, listen Sie ihn auf, um zu prüfen, ob er erstellt wurde:
gcloud run jobs list ✔ JOB: screenshot REGION: us-central LAST RUN AT: CREATED: 2022-02-22 12:20:50 UTC
Führen Sie den Job mit dem folgenden Befehl aus:
gcloud run jobs execute screenshot --region=$REGION
Dadurch wird der Job ausgeführt. Sie können aktuelle und frühere Ausführungen auflisten:
gcloud run jobs executions list --job screenshot --region=$REGION ... JOB: screenshot EXECUTION: screenshot-znkmm REGION: $REGION RUNNING: 1 COMPLETE: 1 / 2 CREATED: 2022-02-22 12:40:42 UTC
Beschreiben Sie die Ausführung. Sie sollten das grüne Häkchen und die Meldung tasks completed successfully
sehen:
gcloud run jobs executions describe screenshot-znkmm --region=$REGION ✔ Execution screenshot-znkmm in region $REGION 2 tasks completed successfully Image: $REGION-docker.pkg.dev/$PROJECT_ID/containers/screenshot at 311b20d9... Tasks: 2 Args: https://example.com https://cloud.google.com Memory: 1Gi CPU: 1000m Task Timeout: 3600s Parallelism: 2 Service account: 11111111-compute@developer.gserviceaccount.com Env vars: BUCKET_NAME screenshot-$PROJECT_ID
Sie können den Status auch auf der Seite „Cloud Run-Jobs“ der Cloud Console ansehen:
Wenn Sie den Cloud Storage-Bucket prüfen, sollten Sie die beiden erstellten Screenshotdateien sehen:
Manchmal müssen Sie eine Ausführung stoppen, bevor sie abgeschlossen ist. Dies kann beispielsweise daran liegen, dass Sie den Job mit anderen Parametern ausführen müssen oder ein Fehler im Code vorliegt und Sie keine unnötige Rechenzeit verbrauchen.
Zum Beenden einer Ausführung Ihres Jobs müssen Sie die Ausführung löschen:
gcloud run jobs executions delete screenshot-znkmm --region=$REGION
7. Job aktualisieren
Neue Versionen des Containers werden nicht automatisch bei der nächsten Ausführung von Cloud Run-Jobs ausgewählt. Wenn Sie den Code für Ihren Job ändern, müssen Sie den Container neu erstellen und den Job aktualisieren. Durch die Verwendung getaggter Bilder können Sie ermitteln, welche Version des Images derzeit verwendet wird.
Ebenso müssen Sie den Job aktualisieren, wenn Sie einige Konfigurationsvariablen aktualisieren möchten. Bei nachfolgenden Ausführungen des Jobs werden der neue Container und die Konfigurationseinstellungen verwendet.
Aktualisieren Sie den Job und ändern Sie im Flag --args
die Seiten, von denen die App Screenshots erstellt. Aktualisieren Sie außerdem das Flag --tasks
, um die Anzahl der Seiten anzugeben.
gcloud run jobs update screenshot \ --args="https://www.pinterest.com" \ --args="https://www.apartmenttherapy.com" \ --args="https://www.google.com" \ --region=$REGION \ --tasks=3
Führen Sie den Job noch einmal aus. Übergeben Sie diesmal das Flag --wait
, um auf den Abschluss der Ausführungen zu warten:
gcloud run jobs execute screenshot --region=$REGION --wait
Nach ein paar Sekunden sollten Sie drei weitere Screenshots zum Bucket sehen:
8. Job planen
Bisher führen Sie Jobs manuell aus. In der Praxis möchten Sie Jobs wahrscheinlich als Reaktion auf ein Ereignis oder nach einem Zeitplan ausführen. Sehen wir uns an, wie Sie den Screenshot-Job mithilfe von Cloud Scheduler nach einem Zeitplan ausführen.
Prüfen Sie zuerst, ob die Cloud Scheduler API aktiviert ist:
gcloud services enable cloudscheduler.googleapis.com
Rufen Sie die Detailseite des Cloud Run-Jobs auf und klicken Sie auf den Abschnitt Triggers
:
Wählen Sie die Schaltfläche Add Scheduler Trigger
aus:
Auf der rechten Seite wird ein Steuerfeld geöffnet. Erstellen Sie einen Scheduler-Job, der jeden Tag um 9:00 Uhr mit dieser Konfiguration ausgeführt werden soll, und wählen Sie Continue
aus:
Wählen Sie auf der nächsten Seite das Compute Engine-Standarddienstkonto und dann Create
aus:
Es sollte nun ein neuer Cloud Scheduler-Trigger erstellt werden:
Klicken Sie auf View Details
, um die Cloud Scheduler-Seite aufzurufen.
Sie können bis 9:00 Uhr warten, bis der Planer aktiviert wird, oder den Cloud Scheduler manuell auslösen, indem Sie Force Run
auswählen:
Nach einigen Sekunden sollte der Cloud Scheduler-Job erfolgreich ausgeführt werden:
Außerdem sollten Sie drei weitere Screenshots sehen, die durch den Aufruf von Cloud Scheduler hinzugefügt wurden:
9. Glückwunsch
Glückwunsch, du hast das Codelab abgeschlossen.
Bereinigen (optional)
Es empfiehlt sich, Ressourcen zu bereinigen, um Gebühren zu vermeiden.
Wenn Sie das Projekt nicht benötigen, können Sie es einfach löschen:
gcloud projects delete $PROJECT_ID
Wenn Sie das Projekt benötigen, können Sie Ressourcen einzeln löschen.
Löschen Sie den Quellcode:
rm -rf ~/jobs-demos/
Löschen Sie das Artifact Registry-Repository:
gcloud artifacts repositories delete containers --location=$REGION
Löschen Sie das Dienstkonto:
gcloud iam service-accounts delete screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
Löschen Sie den Cloud Run-Job:
gcloud run jobs delete screenshot --region=$REGION
Löschen Sie den Cloud Scheduler-Job:
gcloud scheduler jobs delete screenshot-scheduler-trigger --location=$REGION
Löschen Sie den Cloud Storage-Bucket:
gcloud storage rm --recursive gs://screenshot-$PROJECT_ID
Behandelte Themen
- Screenshots von Webseiten mit einer App aufnehmen
- So erstellen Sie ein Container-Image für die Anwendung.
- Cloud Run-Job für die Anwendung erstellen
- So führen Sie die Anwendung als Cloud Run-Job aus.
- So aktualisieren Sie den Job.
- Den Job mit Cloud Scheduler planen