Anleitung zur Verwendung von Cloud Storage FUSE mit Cloud Run


Diese Anleitung zeigt, wie Cloud Storage als Netzwerkdateisystem in einem Cloud Run-Dienst bereitgestellt wird. Derselbe Ansatz kann auch für einen Cloud Run-Job verwendet werden.

In dieser Anleitung wird der Open-Source-FUSE-Adapter verwendet, um Daten zwischen mehreren Containern und Diensten zu teilen.

Zum Bereitstellen eines Dateisystems muss Ihr Dienst die Ausführungsumgebung der zweiten Generation von Cloud Run verwenden. Cloud Run-Jobs verwenden automatisch die Umgebung der zweiten Generation.

Die Ausführungsumgebung der zweiten Generation ermöglicht die Bereitstellung von Netzwerkdateisystemen in einem Verzeichnis in einem Container. Durch das Bereitstellen eines Dateisystems können Sie Ressourcen zwischen einem Hostsystem und Instanzen gemeinsam nutzen und Ressourcen beibehalten, nachdem für eine Instanz ein automatische Speicherbereinigung durchgeführt wurde.

Die Verwendung eines Netzwerkdateisystems mit Cloud Run erfordert erweiterte Docker-Kenntnisse, da der Container mehrere Prozesse ausführen muss, einschließlich der Dateisystembereitstellung und des Anwendungsprozesses. In dieser Anleitung werden die erforderlichen Konzepte anhand eines praktischen Beispiels erläutert. Wenn Sie diese Anleitung jedoch an Ihre eigene Anwendung anpassen, müssen Sie die Auswirkungen der möglichen Änderungen verstehen.

Designübersicht

filesystem-architecture

Das Diagramm zeigt den Cloud Run-Dienst, der über den FUSE-Adapter gcsfuse eine Verbindung zum Cloud Storage-Bucket herstellt. Der Cloud Run-Dienst und der Cloud Storage-Bucket befinden sich in derselben Region, um Netzwerkkosten zu vermeiden und die beste Leistung zu erzielen.

Beschränkungen

  • In dieser Anleitung wird nicht beschrieben, wie ein Dateisystem ausgewählt wird, und es wird nicht auf die Produktionsbereitschaft eingegangen. Machen Sie sich mit den wichtigen Unterschieden gegenüber einem POSIX-Dateisystem und anderer Semantik von Cloud Storage FUSE vertraut.

  • In dieser Anleitung wird nicht gezeigt, wie Sie mit einem Dateisystem arbeiten und geht nicht auf Dateizugriffsmuster ein.

Ziele

  • Einen Cloud Storage-Bucket erstellen, der als Dateifreigabe dient.

  • Ein Dockerfile mit Systempaketen und dem init-Prozess erstellen, um die Bereitstellungs- und Anwendungsprozesse zu verwalten.

  • Bereitstellung in Cloud Run und Überprüfung des Zugriffs auf das Dateisystem im Dienst.

Kosten

In dieser Anleitung werden kostenpflichtige Komponenten von Google Cloud verwendet, darunter:

Hinweis

  1. Melden Sie sich bei Ihrem Google Cloud-Konto an. Wenn Sie mit Google Cloud noch nicht vertraut sind, erstellen Sie ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
  2. Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.

    Zur Projektauswahl

  3. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  4. Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.

    Zur Projektauswahl

  5. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  6. Cloud Run, Cloud Storage, Artifact Registry, and Cloud Build APIs aktivieren.

    Aktivieren Sie die APIs

  7. Installieren und initialisieren Sie die gcloud CLI.

Erforderliche Rollen

Bitten Sie Ihren Administrator, Ihnen die folgenden IAM-Rollen für Ihr Projekt zuzuweisen, um die Berechtigungen zu erhalten, die Sie zum Ausführen der Anleitung mit dem Mindestsatz an Rollen benötigen:

Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff verwalten.

Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.

gcloud-Standardeinstellungen einrichten

So konfigurieren Sie gcloud mit Standardeinstellungen für den Cloud Run-Dienst:

  1. Legen Sie ein Standardprojekt fest:

    gcloud config set project PROJECT_ID

    Ersetzen Sie PROJECT_ID durch den Namen des Projekts, das Sie für diese Anleitung erstellt haben.

  2. Konfigurieren Sie gcloud für die von Ihnen ausgewählte Region:

    gcloud config set run/region REGION

    Ersetzen Sie REGION durch die unterstützte Cloud Run-Region Ihrer Wahl.

Cloud Run-Standorte

Cloud Run ist regional. Die Infrastruktur, in der die Cloud Run-Dienste ausgeführt werden, befindet sich demnach in einer bestimmten Region. Aufgrund der Verwaltung durch Google sind die Anwendungen in allen Zonen innerhalb dieser Region redundant verfügbar.

Bei der Auswahl der Region, in der Ihre Cloud Run-Dienste ausgeführt werden, ist vorrangig, dass die Anforderungen hinsichtlich Latenz, Verfügbarkeit oder Langlebigkeit erfüllt werden. Sie können im Allgemeinen die Region auswählen, die Ihren Nutzern am nächsten liegt, aber Sie sollten den Standort der anderen Google Cloud-Produkte berücksichtigen, die von Ihrem Cloud Run-Dienst verwendet werden. Die gemeinsame Nutzung von Google Cloud-Produkten an mehreren Standorten kann sich auf die Latenz und die Kosten des Dienstes auswirken.

Cloud Run ist in diesen Regionen verfügbar:

Unterliegt Preisstufe 1

Unterliegt Preisstufe 2

  • asia-east2 (Hongkong)
  • asia-northeast3 (Seoul, Südkorea)
  • asia-southeast1 (Singapur)
  • asia-southeast2 (Jakarta)
  • asia-south1 (Mumbai, Indien)
  • asia-south2 (Delhi, Indien)
  • australia-southeast1 (Sydney)
  • australia-southeast2 (Melbourne)
  • europe-central2 (Warschau, Polen)
  • europe-west10 (Berlin)
  • europe-west12 (Turin)
  • europe-west2 (London, Vereinigtes Königreich) Blattsymbol Niedriger CO2-Ausstoß
  • europe-west3 (Frankfurt, Deutschland) Blattsymbol Niedriger CO2-Wert
  • europe-west6 (Zürich, Schweiz) Blattsymbol Niedriger CO2-Ausstoß
  • me-central1 (Doha)
  • me-central2 (Dammam)
  • northamerica-northeast1 (Montreal) Blattsymbol Niedriger CO2-Ausstoß
  • northamerica-northeast2 (Toronto) Blattsymbol Niedriger CO2-Ausstoß
  • southamerica-east1 (Sao Paulo, Brasilien) Blattsymbol Niedriger CO2-Ausstoß
  • southamerica-west1 (Santiago, Chile) Blattsymbol Niedriger CO2-Ausstoß
  • us-west2 (Los Angeles)
  • us-west3 (Salt Lake City)
  • us-west4 (Las Vegas)

Wenn Sie bereits einen Cloud Run-Dienst erstellt haben, können Sie dessen Region im Cloud Run-Dashboard der Google Cloud Console aufrufen.

Codebeispiel abrufen

So rufen Sie das gewünschte Codebeispiel ab:

  1. Klonen Sie das Repository der Beispiel-App auf Ihren lokalen Computer:

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    Sie können auch das Beispiel als ZIP-Datei herunterladen und extrahieren.

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    Sie können auch das Beispiel als ZIP-Datei herunterladen und extrahieren.

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git

    Sie können auch das Beispiel als ZIP-Datei herunterladen und extrahieren.

  2. Wechseln Sie in das Verzeichnis, das den Cloud Run-Beispielcode enthält:

    Node.js

    cd nodejs-docs-samples/run/filesystem/

    Python

    cd python-docs-samples/run/filesystem/

    Java

    cd java-docs-samples/run/filesystem/

Code verstehen

Normalerweise sollten Sie in einem Container einen einzelnen Prozess oder eine einzelne Anwendung ausführen. Die Ausführung eines einzelnen Prozesses pro Container vereinfacht die Verwaltung des Lebenszyklus mehrerer Prozesse: Verwaltung von Neustarts, Beenden des Containers, wenn ein Prozess fehlschlägt, und PID 1-Aufgaben wie Signalweiterleitung und Zombie Child Reaping. Wenn Sie jedoch Netzwerkdateisysteme in Cloud Run verwenden, müssen Sie Multi-Prozess-Container verwenden, um sowohl den Dateisystem-Bereitstellungsprozess als auch die Anwendung auszuführen. In dieser Anleitung wird gezeigt, wie der Container bei einem Prozessfehler beendet und die PID 1-Zuständigkeiten verwaltet werden. Der Bereitstellungsbefehl hat eine integrierte Funktion zur Verarbeitung von Wiederholungsversuchen.

Als Einstiegspunkt für den Container können Sie einen Prozessmanager zum Ausführen und Verwalten mehrerer Prozesse verwenden. In dieser Anleitung wird tini verwendet, ein Init-Ersatz, der Zombie-Prozesse bereinigt und die Signalweiterleitung durchführt. Insbesondere ermöglicht dieser Init-Prozess, das SIGTERM-Signal beim Herunterfahren an die Anwendung weiterzuleiten. Das SIGTERM-Signal kann für die ordnungsgemäße Beendigung der Anwendung genutzt werden. Weitere Informationen zum Lebenszyklus eines Containers in Cloud Run

Umgebungskonfiguration mit dem Dockerfile definieren

Für diesen Cloud Run-Dienst sind ein oder mehrere zusätzliche Systempakete erforderlich, die standardmäßig nicht verfügbar sind. Die RUN-Anweisung installiert tini als Init-Prozess und gcsfuse, den FUSE-Adapter. Weitere Informationen zum Arbeiten mit Systempaketen in Ihrem Cloud Run-Dienst finden Sie in der Anleitung zum Verwenden von Systempaketen.

Mit den nächsten Anweisungen erstellen Sie ein Arbeitsverzeichnis, kopieren den Quellcode und installieren die Anwendungsabhängigkeiten.

Der ENTRYPOINT gibt die Binärdatei des Init-Prozesses an, die der CMD-Anleitung vorangestellt ist. In diesem Fall ist es das Startskript. Dieser startet einen einzelnen Tini-Prozess und leitet dann alle empfangenen Signale an eine Sitzung weiter, die ihren Root in diesem untergeordneten Prozess haben.

Die CMD-Anweisung legt den Befehl fest, der beim Ausführen des Images, also des Startskripts, ausgeführt werden soll. Außerdem werden Standardargumente für den ENTRYPOINT bereitgestellt. Funktionsweise von CMD und ENTRYPOINT

Node.js


# Use the official Node.js image.
# https://hub.docker.com/_/node
FROM node:20-slim

# Install system dependencies
RUN apt-get update && apt-get install -y \
    curl \
    gnupg \
    lsb-release \
    tini && \
    gcsFuseRepo=gcsfuse-`lsb_release -c -s` && \
    echo "deb https://packages.cloud.google.com/apt $gcsFuseRepo main" | \
    tee /etc/apt/sources.list.d/gcsfuse.list && \
    curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
    apt-key add - && \
    apt-get update && \
    apt-get install -y gcsfuse && \
    apt-get clean

# Set fallback mount directory
ENV MNT_DIR /mnt/gcs

# Copy local code to the container image.
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY package*.json ./

# Install production dependencies.
RUN npm install --only=production

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

# Ensure the script is executable
RUN chmod +x /app/gcsfuse_run.sh

# Use tini to manage zombie processes and signal forwarding
# https://github.com/krallin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]

# Pass the wrapper script as arguments to tini
CMD ["/app/gcsfuse_run.sh"]

Python

# Use the official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.11-buster

# Install system dependencies
RUN set -e; \
    apt-get update -y && apt-get install -y \
    tini \
    lsb-release; \
    gcsFuseRepo=gcsfuse-`lsb_release -c -s`; \
    echo "deb https://packages.cloud.google.com/apt $gcsFuseRepo main" | \
    tee /etc/apt/sources.list.d/gcsfuse.list; \
    curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
    apt-key add -; \
    apt-get update; \
    apt-get install -y gcsfuse \
    && apt-get clean

# Set fallback mount directory
ENV MNT_DIR /mnt/gcs

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

# Install production dependencies.
RUN pip install -r requirements.txt

# Ensure the script is executable
RUN chmod +x /app/gcsfuse_run.sh

# Use tini to manage zombie processes and signal forwarding
# https://github.com/krallin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]

# Pass the startup script as arguments to Tini
CMD ["/app/gcsfuse_run.sh"]

Java

# Use the official maven/Java 11 image to create a build artifact.
# https://hub.docker.com/_/maven
FROM maven:3-eclipse-temurin-17-alpine as builder

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

# Build a release artifact.
RUN mvn package -DskipTests

# Use Eclipse Temurin for base image.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM eclipse-temurin:18-jdk-focal

# Install system dependencies
RUN set -e; \
    apt-get update -y && apt-get install -y \
    gnupg2 \
    tini \
    lsb-release; \
    gcsFuseRepo=gcsfuse-`lsb_release -c -s`; \
    echo "deb https://packages.cloud.google.com/apt $gcsFuseRepo main" | \
    tee /etc/apt/sources.list.d/gcsfuse.list; \
    curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | \
    apt-key add -; \
    apt-get update; \
    apt-get install -y gcsfuse && apt-get clean

# Set fallback mount directory
ENV MNT_DIR /mnt/gcs

# Copy the jar to the production image from the builder stage.
COPY --from=builder /app/target/filesystem-*.jar /filesystem.jar

# Copy the statup script
COPY gcsfuse_run.sh ./gcsfuse_run.sh
RUN chmod +x ./gcsfuse_run.sh

# Use tini to manage zombie processes and signal forwarding
# https://github.com/krallin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]

# Run the web service on container startup.
CMD ["/gcsfuse_run.sh"]

Prozesse im Startskript definieren

Das Startskript erstellt das Verzeichnis für den Bereitstellungspunkt, in dem auf den Cloud Storage-Bucket zugegriffen werden kann. Als Nächstes hängt das Skript den Cloud Storage-Bucket mit dem Befehl gcsfuse an den Bereitstellungspunkt des Dienstes an und startet dann den Anwendungsserver. Der Befehl gcsfuse hat eine integrierte Wiederholungsfunktion. Daher ist keine weitere Bash-Skripterstellung erforderlich. Schließlich wird mit dem Befehl wait geprüft, ob Hintergrundprozesse beendet werden, und dann das Skript beendet.

Node.js

#!/usr/bin/env bash
set -eo pipefail

# Create mount directory for service
mkdir -p $MNT_DIR

echo "Mounting GCS Fuse."
gcsfuse --debug_gcs --debug_fuse $BUCKET $MNT_DIR
echo "Mounting completed."

# Start the application
node index.js &

# Exit immediately when one of the background processes terminate.
wait -n

Python

#!/usr/bin/env bash
set -eo pipefail

# Create mount directory for service
mkdir -p $MNT_DIR

echo "Mounting GCS Fuse."
gcsfuse --debug_gcs --debug_fuse $BUCKET $MNT_DIR
echo "Mounting completed."

# 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.
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

Java

#!/usr/bin/env bash
set -eo pipefail

# Create mount directory for service
mkdir -p $MNT_DIR

echo "Mounting GCS Fuse."
gcsfuse --debug_gcs --debug_fuse $BUCKET $MNT_DIR
echo "Mounting completed."

# Start the application
java -jar filesystem.jar

# Exit immediately when one of the background processes terminate.
wait -n

Mit Dateien arbeiten

Node.js

Weitere Informationen zur Interaktion mit dem Dateisystem finden Sie unter index.js.

Python

Weitere Informationen zur Interaktion mit dem Dateisystem finden Sie unter main.py.

Java

Weitere Informationen zur Interaktion mit dem Dateisystem finden Sie unter FilesystemApplication.java.

Dienst versenden

  1. Erstellen Sie einen Cloud Storage-Bucket oder verwenden Sie einen vorhandenen Bucket:

    gsutil mb -l REGION gs://BUCKET_NAME
    

    Ersetzen Sie BUCKET_NAME durch den Namen des Cloud Storage-Buckets, also my-fuse-bucket. Cloud Storage-Bucket-Namen müssen global eindeutig sein und unterliegen den Benennungsanforderungen.

    Legen Sie -l fest, um den Standort des Buckets anzugeben. Beispiel: us-central1. Der Cloud Storage-Bucket sollte sich in derselben Region befinden wie die Cloud Run-Dienste, die auf ihn zugreifen müssen, um die Leistung zu optimieren und regionenübergreifende Netzwerkgebühren zu vermeiden.

  2. Erstellen Sie ein Dienstkonto, das als Dienstidentität dient:

    gcloud iam service-accounts create fs-identity
  3. Gewähren Sie dem Dienstkonto Zugriff auf den Cloud Storage-Bucket:

    gcloud projects add-iam-policy-binding PROJECT_ID \
         --member "serviceAccount:fs-identity@PROJECT_ID.iam.gserviceaccount.com" \
         --role "roles/storage.objectAdmin"
    
  4. Für eine Bereitstellung aus der Quelle löschen Sie das zusätzliche Dockerfile und benennen Sie die Anleitung in Dockerfile um.

    rm Dockerfile
    cp gcsfuse.Dockerfile Dockerfile
    
  5. Erstellen Sie das Container-Image und stellen Sie es in Cloud Run bereit:

    gcloud run deploy filesystem-app --source . \
        --execution-environment gen2 \
        --allow-unauthenticated \
        --service-account fs-identity \
        --update-env-vars BUCKET=BUCKET_NAME
    

    Mit diesem Befehl wird der Cloud Run-Dienst erstellt und bereitgestellt und die Ausführungsumgebung der zweiten Generation angegeben. Beim Bereitstellen aus der Quelle wird das Image basierend auf dem Dockerfile erstellt und das Image per Push in das Artifact Registry-Repository cloud-run-source-deploy übertragen.

    Weitere Informationen zum Bereitstellen aus Quellcode.

Debugging

Wenn die Bereitstellung nicht erfolgreich ist, prüfen Sie Cloud Logging auf weitere Details.

Wenn Sie alle Logs aus dem Bereitstellungsprozess abrufen möchten, verwenden Sie das Flag --foreground in Kombination mit dem Bereitstellungsbefehl im Startskript gcsfuse_run.sh:

  gcsfuse --foreground --debug_gcs --debug_fuse GCSFUSE_BUCKET MNT_DIRECTORY &
  

  • Fügen Sie --debug_http für die HTTP-Anfrage-/Antwort-Debug-Ausgabe hinzu.
  • Fügen Sie --debug_fuse hinzu, um die fuse-bezogene Debugging-Ausgabe zu aktivieren.
  • Fügen Sie --debug_gcs hinzu, um Informationen zu GCS-Anfragen und Zeitangaben auszugeben.

Weitere Tipps zur Fehlerbehebung finden Sie hier.

Testen

So testen Sie den gesamten Dienst:

  1. Rufen Sie im Browser die URL auf, die Sie im oben beschriebenen Bereitstellungsschritt erhalten haben.
  2. Im Cloud Storage-Bucket sollte nun eine neu erstellte Datei angezeigt werden.
  3. Klicken Sie auf die Datei, um sich den Inhalt anzeigen zu lassen.

Wenn Sie sich dafür entscheiden, mit der Entwicklung dieser Dienste fortzufahren, denken Sie daran, dass diese nur eingeschränkten IAM-Zugriff (Identity and Access Management) auf den Rest von Google Cloud haben und ihnen zusätzliche IAM-Rollen zugewiesen werden müssen, um auf viele andere Dienste zugreifen zu können.

Kostendiskussion

Cloud Storage-Preise sind stark abhängig vom Datenspeicher, der Menge der gespeicherten Daten nach Speicherklasse und Standort des Buckets, der Netzwerknutzung sowie der Menge an Daten, die aus den Buckets gelesen bzw. zwischen diesen verschobenen werden. Weitere Informationen zu Gebühren für Cloud Storage FUSE.

Der Preis für Cloud Run wird nach Ressourcennutzung und auf die nächste Zehntelsekunde gerundet berechnet, wobei Arbeitsspeicher, CPU, Anzahl der Anfragen und Netzwerknutzung berücksichtigt werden. Daher variieren die Kosten je nach Diensteinstellungen, Anzahl der Anfragen und Ausführungszeit.

Beispiel: 1 TiB Daten, die in einem Standard-Storage-Bucket in Iowa (us-central1) gespeichert werden, kostet 0,02 $ pro Monat und GiB, was ungefähr 1.024 GiB * 0,02 $ = 20,48 $ entspricht. Diese Schätzung hängt vom Cloud Run-Dienst und dem Cloud Storage-Bucket ab, der in derselben Region gehostet wird, um Kosten für ausgehenden Traffic zu reduzieren.

Sie können sich die einzelnen Preisseiten mit den aktuellen Preisen ansehen oder eine Schätzung im Google Cloud-Preisrechner abrufen.

Bereinigen

Wenn Sie ein neues Projekt für diese Anleitung erstellt haben, löschen Sie das Projekt. Wenn Sie ein vorhandenes Projekt verwendet haben und es beibehalten möchten, ohne die Änderungen in dieser Anleitung hinzuzufügen, löschen Sie die für die Anleitung erstellten Ressourcen.

Projekt löschen

Am einfachsten vermeiden Sie weitere Kosten, wenn Sie das zum Ausführen der Anleitung erstellte Projekt löschen.

So löschen Sie das Projekt:

  1. Wechseln Sie in der Google Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.

Anleitungsressourcen löschen

  1. Löschen Sie den Cloud Run-Dienst, den Sie in dieser Anleitung bereitgestellt haben:

    gcloud run services delete SERVICE-NAME

    Dabei ist SERVICE-NAME der von Ihnen ausgewählte Dienstname.

    Sie können Cloud Run-Dienste auch über die Google Cloud Console löschen.

  2. Entfernen Sie die Konfiguration der Standardregion gcloud, die Sie während der Einrichtung für die Anleitung hinzugefügt haben:

     gcloud config unset run/region
    
  3. Entfernen Sie die Projektkonfiguration:

     gcloud config unset project
    
  4. Löschen Sie sonstige Google Cloud-Ressourcen, die in dieser Anleitung erstellt wurden:

Nächste Schritte