1. Einführung

Übersicht
Cloud Run-Dienste eignen sich gut für Container, die unbegrenzt ausgeführt werden und auf HTTP-Anfragen warten. Cloud Run-Jobs sind besser für Container geeignet, die bis zum Abschluss (derzeit bis zu 24 Stunden) ausgeführt werden und keine Anfragen bearbeiten. Die Verarbeitung von Datensätzen aus einer Datenbank, die Verarbeitung einer Liste von Dateien aus einem Cloud Storage-Bucket oder ein zeitaufwendiger Vorgang wie die Berechnung von Pi eignen sich gut für die Implementierung als Cloud Run-Job.
Jobs können keine Anfragen verarbeiten oder einen Port überwachen. Im Gegensatz zu Cloud Run-Diensten sollten Jobs daher keinen Webserver enthalten. Stattdessen sollten Jobcontainer beendet werden, wenn sie fertig sind.
In Cloud Run-Jobs können Sie mehrere Kopien Ihres Containers parallel ausführen, indem Sie eine Anzahl von Aufgaben angeben. Jede Aufgabe stellt eine laufende Kopie des Containers dar. Die Verwendung mehrerer Aufgaben ist nützlich, wenn jede Aufgabe eine Teilmenge Ihrer Daten unabhängig verarbeiten kann. Wenn Sie beispielsweise 10.000 Einträge aus Cloud SQL oder 10.000 Dateien aus Cloud Storage verarbeiten, kann dies schneller mit 10 Aufgaben erfolgen, die jeweils 1.000 Einträge oder Dateien parallel verarbeiten.
Die Verwendung von Cloud Run-Jobs erfolgt in zwei Schritten:
- Job erstellen:Dies umfasst die gesamte Konfiguration, die zum Ausführen des Jobs erforderlich ist, z. B. das Container-Image, die Region und die Umgebungsvariablen.
- Job ausführen:Dadurch wird eine neue Ausführung des Jobs erstellt. Optional können Sie Ihren Job so einrichten, dass er nach einem Zeitplan mit Cloud Scheduler ausgeführt wird.
In diesem Codelab sehen Sie sich zuerst eine Node.js-Anwendung an, mit der Screenshots von Webseiten erstellt und in Cloud Storage gespeichert werden. Anschließend erstellen Sie ein Container-Image für die Anwendung, führen es 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
- So erstellen Sie mit einer App Screenshots von Webseiten.
- So erstellen Sie ein Container-Image für die Anwendung.
- So erstellen Sie einen Cloud Run-Job für die Anwendung.
- So führen Sie die Anwendung als Cloud Run-Job aus.
- So aktualisieren Sie den Job.
- So planen Sie den Job mit Cloud Scheduler.
2. Einrichtung und Anforderungen
Einrichtung der Umgebung im eigenen Tempo
- 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 Teilnehmer dieses Projekts. Es handelt sich um einen String, der nicht von Google APIs verwendet wird. Sie können sie jederzeit aktualisieren.
- Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich (kann nach dem Festlegen nicht mehr geändert werden). In der Cloud Console wird automatisch ein eindeutiger String generiert. Normalerweise ist es nicht wichtig, wie dieser String aussieht. In den meisten Codelabs müssen Sie auf Ihre Projekt-ID verweisen (in der Regel als
PROJECT_IDangegeben). Wenn Ihnen die generierte ID nicht gefällt, können Sie eine andere zufällige ID generieren. Alternativ können Sie es mit einem eigenen Namen versuchen. Sie kann nach diesem Schritt nicht mehr geändert werden und bleibt für die Dauer des Projekts bestehen. - Zur Information: Es gibt einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten
- Als Nächstes müssen Sie die Abrechnung in der Cloud Console aktivieren, um Cloud-Ressourcen/-APIs zu verwenden. Die Durchführung dieses Codelabs kostet wenig oder gar nichts. Wenn Sie Ressourcen herunterfahren möchten, um Kosten zu vermeiden, die über diese Anleitung hinausgehen, können Sie die erstellten Ressourcen oder das Projekt löschen. Neue Google Cloud-Nutzer können am Programm Kostenlose Testversion mit einem Guthaben von 300$ teilnehmen.
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 Google Cloud Console rechts oben in der Symbolleiste auf das Cloud Shell-Symbol:

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

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. Alle Aufgaben in diesem Codelab können in einem Browser ausgeführt 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 diese als die Variablen PROJECT_ID und REGION ab. Künftig 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
Zuerst sehen Sie sich eine Node.js-Anwendung an, mit der Screenshots von Webseiten erstellt und in Cloud Storage gespeichert werden. 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 in das Verzeichnis, das die Anwendung enthält:
cd jobs-demos/screenshot
Das Dateilayout sollte so aussehen:
screenshot | ├── Dockerfile ├── README.md ├── screenshot.js ├── package.json
Hier eine kurze Beschreibung der einzelnen Dateien:
screenshot.jsenthält den Node.js-Code für die Anwendung.package.jsondefiniert die Bibliotheksabhängigkeiten.Dockerfiledefiniert das Container-Image.
4. Code ansehen
Klicken Sie oben im Cloud Shell-Fenster auf die Schaltfläche Open Editor, um den integrierten Texteditor zu verwenden.

Hier finden Sie eine kurze Beschreibung der einzelnen Dateien.
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 eine takeScreenshot-Funktion zum Erstellen von Screenshots einer bestimmten URL:
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 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 bei der Methode main Folgendes:
- URLs werden als Argumente übergeben.
- Der Bucket-Name wird als benutzerdefinierte Umgebungsvariable
BUCKET_NAMEübergeben. Der Bucket-Name muss global in Google Cloud eindeutig sein. - Eine Umgebungsvariable
CLOUD_RUN_TASK_INDEXwird von Cloud Run-Jobs übergeben. Cloud Run-Jobs können mehrere Kopien der Anwendung als eindeutige Aufgaben ausführen.CLOUD_RUN_TASK_INDEXsteht 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/jeder Container die URL ab, für die sie zuständig ist, 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
Die Datei 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 Konfiguration enthält, die zum Ausführen des Jobs erforderlich ist.
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-$RANDOM \ --service-account=screenshot-sa@$PROJECT_ID.iam.gserviceaccount.com
Dabei wird die quellbasierte Bereitstellung verwendet und ein Cloud Run-Job erstellt, ohne ihn auszuführen.
Beachten Sie, dass die Webseiten als Argumente übergeben werden. Der Bucket-Name zum Speichern der Screenshots wird als Umgebungsvariable übergeben.
Sie können mehrere Kopien Ihres Containers parallel ausführen, indem Sie mit dem Flag --tasks eine Anzahl von auszuführenden Aufgaben angeben. Jede Aufgabe stellt eine laufende Kopie des Containers dar. Die Verwendung mehrerer Aufgaben ist nützlich, wenn jede Aufgabe eine Teilmenge Ihrer Daten unabhängig verarbeiten kann. Dazu kennt jede Aufgabe ihren Index, der in der Umgebungsvariable 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. So wird dafür gesorgt, dass zwei Container für die beiden URLs ausgeführt werden, die wir verarbeiten möchten.
Jede Aufgabe kann bis zu 24 Stunden dauern. 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 konfigurieren, dass Aufgaben bei einem Fehler wiederholt werden. Wenn eine Aufgabe die Anzahl der Wiederholungsversuche überschreitet, schlägt der gesamte Job fehl.
Standardmäßig werden in Ihrem Job so viele Aufgaben wie möglich parallel ausgeführt. Das entspricht der Anzahl der Aufgaben für Ihren Job, maximal 100. Möglicherweise möchten Sie die Parallelität für Jobs, die auf ein Backend mit begrenzter Skalierbarkeit zugreifen, niedriger festlegen. Beispielsweise eine Datenbank, die nur eine begrenzte Anzahl aktiver Verbindungen unterstützt. Mit dem Flag --parallelism können Sie die Parallelität 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 vergangene 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-$RANDOM
Sie können den Status auch auf der Seite „Cloud Run-Jobs“ in der Cloud Console prüfen:

Wenn Sie den Cloud Storage-Bucket prüfen, sollten die beiden Screenshot-Dateien angezeigt werden:

Manchmal müssen Sie eine Ausführung beenden, bevor sie abgeschlossen ist, z. B. weil Sie feststellen, dass Sie den Job mit anderen Parametern ausführen müssen, oder weil ein Fehler im Code vorliegt und Sie keine unnötige Rechenzeit verwenden möchten.
Wenn Sie die Ausführung eines Jobs beenden möchten, müssen Sie die Ausführung löschen:
gcloud run jobs executions delete screenshot-znkmm --region=$REGION
7. Job aktualisieren
Neue Versionen Ihres Containers werden bei der nächsten Ausführung nicht automatisch von Cloud Run-Jobs übernommen. Wenn Sie den Code für Ihren Job ändern, müssen Sie den Container neu erstellen und Ihren Job aktualisieren. Mithilfe von getaggten Bildern können Sie ermitteln, welche Version des Bildes derzeit verwendet wird.
Ebenso müssen Sie den Job aktualisieren, wenn Sie einige der Konfigurationsvariablen aktualisieren möchten. Bei nachfolgenden Ausführungen des Jobs werden der neue Container und die neuen Konfigurationseinstellungen verwendet.
Aktualisieren Sie den Job und ändern Sie die Seiten, von denen die App Screenshots erstellt, im --args-Flag. Aktualisieren Sie auch das Flag --tasks entsprechend der Anzahl der Seiten.
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. Geben Sie die Zeit im Flag --wait an, um auf den Abschluss der Ausführungen zu warten:
gcloud run jobs execute screenshot --region=$REGION --wait
Nach einigen Sekunden sollten dem Bucket drei weitere Screenshots hinzugefügt werden:

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 wir den Screenshot-Job mit 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 für Cloud Run-Jobs auf und klicken Sie auf den Bereich Triggers:

Wählen Sie die Schaltfläche Add Scheduler Trigger aus:

Rechts wird ein Steuerfeld geöffnet. Erstellen Sie einen Scheduler-Job, der jeden Tag um 9:00 Uhr mit dieser Konfiguration ausgeführt wird, und wählen Sie Continue aus:

Wählen Sie auf der nächsten Seite das Standarddienstkonto für Compute aus und klicken Sie auf Create:

Sie sollten jetzt einen neuen Cloud Scheduler-Trigger sehen:

Klicken Sie auf View Details, um zur Seite „Cloud Scheduler“ zu gelangen.
Sie können warten, bis der Scheduler um 9:00 Uhr startet, 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 drei weitere Screenshots zu sehen sein, die durch den Aufruf von Cloud Scheduler hinzugefügt wurden:

9. Glückwunsch
Herzlichen Glückwunsch! Sie haben das Codelab abgeschlossen.
Bereinigen (optional)
Um Gebühren zu vermeiden, sollten Sie Ressourcen bereinigen.
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
- So erstellen Sie mit einer App Screenshots von Webseiten.
- So erstellen Sie ein Container-Image für die Anwendung.
- So erstellen Sie einen Cloud Run-Job für die Anwendung.
- So führen Sie die Anwendung als Cloud Run-Job aus.
- So aktualisieren Sie den Job.
- So planen Sie den Job mit Cloud Scheduler.