Wprowadzenie do funkcji Cloud Run

Wprowadzenie do funkcji Cloud Run

Informacje o tym ćwiczeniu (w Codelabs)

subjectOstatnia aktualizacja: maj 7, 2025
account_circleAutorzy: Mete Atamel

1. Wprowadzenie

Omówienie

Funkcje Cloud Run to usługa Google Cloud typu funkcje jako usługa oparta na technologii Cloud Run i Eventarc, która zapewnia zaawansowaną kontrolę nad wydajnością i skalowalnością oraz większą kontrolę nad środowiskiem wykonawczym funkcji i aktywatorami z ponad 90 źródeł zdarzeń.

W tym laboratorium programistycznym dowiesz się, jak tworzyć funkcje Cloud Run, które reagują na wywołania HTTP i są uruchamiane przez wiadomości Pub/Sub oraz logi kontrolne Cloud.

Ten warsztat kodowania korzysta też z automatycznych aktualizacji obrazu podstawowego na potrzeby wdrażania funkcji, określając obraz podstawowy za pomocą flagi --base-image. Automatyczne aktualizacje obrazu podstawowego w Cloud Run umożliwiają Google automatyczne wprowadzanie poprawek zabezpieczeń do systemu operacyjnego i komponentów środowiska wykonawczego języka w obrazie podstawowym. Nie musisz ponownie tworzyć ani wdrażać usługi, aby zaktualizować obraz bazowy. Więcej informacji znajdziesz w artykule Automatyczne aktualizacje obrazu bazowego.

Jeśli wolisz nie używać automatycznych aktualizacji obrazu bazowego, możesz usunąć flagę --base-image z przykładów pokazanych w tym laboratorium kodu.

Czego się nauczysz

  • Omówienie funkcji Cloud Run i sposobu korzystania z automatycznych aktualizacji obrazu bazowego.
  • Jak napisać funkcję, która odpowiada na wywołania HTTP.
  • Jak napisać funkcję, która odpowiada na wiadomości Pub/Sub.
  • Jak napisać funkcję, która reaguje na zdarzenia Cloud Storage.
  • Jak podzielić ruch między 2 wersje.
  • Jak pozbyć się uruchomień „na zimno” za pomocą minimalnej liczby instancji

2. Konfiguracja i wymagania

Tworzenie folderu głównego

Utwórz folder główny ze wszystkimi przykładami.

mkdir crf-codelab
cd crf-codelab

Konfigurowanie zmiennych środowiskowych

Ustaw zmienne środowiskowe, których będziesz używać w trakcie tego ćwiczenia.

gcloud config set project <YOUR-PROJECT-ID>
REGION=<YOUR_REGION>

PROJECT_ID=$(gcloud config get-value project)

Włącz interfejsy API

Włącz wszystkie niezbędne usługi:

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  eventarc.googleapis.com \
  run.googleapis.com \
  logging.googleapis.com \
  pubsub.googleapis.com

3. Funkcja HTTP

W pierwszej kolejności utwórz funkcję Node.js, która odpowiada na żądania HTTP i która jest uwierzytelniana. Użyjemy też 10-minutowego limitu czasu, aby pokazać, że funkcja może mieć więcej czasu na odpowiadanie na żądania HTTP.

Utwórz

Utwórz folder aplikacji i otwórz go:

mkdir hello-http
cd hello-http

Utwórz plik index.js, który odpowiada na żądania HTTP:

const functions = require('@google-cloud/functions-framework');

functions.http('helloWorld', (req, res) => {
  res.status(200).send('HTTP with Node.js in Cloud Run functions!');
});

Utwórz plik package.json, aby określić zależności:

{
  "name": "nodejs-run-functions-codelab",
  "version": "0.0.1",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^2.0.0"
  }
}

Wdróż

Wdróż funkcję:

gcloud run deploy nodejs-run-function \
      --source . \
      --function helloWorld \
      --base-image nodejs22 \
      --region $REGION \
      --timeout 600 \
      --no-allow-unauthenticated

To polecenie używa pakietów kompilacji do przekształcenia kodu źródłowego funkcji w obraz kontenera gotowy do użycia w środowisku produkcyjnym.

Uwaga:

  • flaga --source służy do informowania Cloud Run o konieczności skompilowania funkcji w celu utworzenia uruchomialnej usługi opartej na kontenerze.
  • flaga --function (nowa) służy do ustawienia punktu wejścia nowej usługi jako sygnatury funkcji, którą chcesz wywołać.
  • flaga --base-image (nowa) określa środowisko obrazu podstawowego dla funkcji, np. nodejs22, python312, go123, java21, dotnet8, ruby33 lub php83. Więcej informacji o obrazach bazowych i pakietach zawartych w każdym obrazie znajdziesz w artykule Obrazy bazowe Runtimes.
  • (opcjonalnie) flaga --timeout pozwala funkcji na dłuższy limit czasu odpowiedzi na żądania HTTP. W tym przykładzie użyto 600 sekund, aby zademonstrować czas odpowiedzi wynoszący 10 minut.
  • (opcjonalnie) --no-allow-unauthenticated, aby uniemożliwić wywołanie funkcji przez innych użytkowników

Test

Przetestuj funkcję za pomocą tych poleceń:

# get the Service URL
SERVICE_URL="$(gcloud run services describe nodejs-run-function --region $REGION --format 'value(status.url)')"

# invoke the service
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

W odpowiedzi powinien wyświetlić się komunikat HTTP with Node.js in Cloud Run functions!.

4. Funkcja Pub/Sub

Drugą funkcję, którą utworzymy, będzie funkcja w Pythonie, która będzie wywoływana przez wiadomość Pub/Sub opublikowaną w określonym temacie.

Konfigurowanie tokenów uwierzytelniających Pub/Sub

Jeśli konto usługi Pub/Sub zostało włączone 8 kwietnia 2021 r. lub wcześniej, przypisz do niego rolę iam.serviceAccountTokenCreator:

PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member  serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
  --role roles/iam.serviceAccountTokenCreator

Utwórz

Utwórz temat Pub/Sub, który będzie używany w przykładzie:

TOPIC=cloud-run-functions-pubsub-topic
gcloud pubsub topics create $TOPIC

Utwórz folder aplikacji i otwórz go:

mkdir ../hello-pubsub
cd ../hello-pubsub

Utwórz plik main.py, który rejestruje wiadomość zawierającą identyfikator CloudEvent:

import functions_framework

@functions_framework.cloud_event
def hello_pubsub(cloud_event):
   print('Pub/Sub with Python in Cloud Run functions! Id: ' + cloud_event['id'])

Aby określić zależności, utwórz plik requirements.txt z podaną niżej treścią:

functions-framework==3.*

Wdróż

Wdróż funkcję:

gcloud run deploy python-pubsub-function \
       --source . \
       --function hello_pubsub \
       --base-image python313 \
       --region $REGION \
       --no-allow-unauthenticated

Pobierz numer projektu, który będzie używany do identyfikacji konta usługi.

PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')

Tworzenie aktywatora

gcloud eventarc triggers create python-pubsub-function-trigger  \
    --location=$REGION \
    --destination-run-service=python-pubsub-function  \
    --destination-run-region=$REGION \
    --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --transport-topic=projects/$PROJECT_ID/topics/$TOPIC \
    --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

Test

Przetestuj funkcję, wysyłając wiadomość do tematu:

gcloud pubsub topics publish $TOPIC --message="Hello World"

W logach powinien pojawić się otrzymany CloudEvent:

gcloud run services logs read python-pubsub-function --region $REGION --limit=10

5. Funkcja Cloud Storage

Następną funkcję utwórz w Node.js, aby reagowała na zdarzenia z zasobinku Cloud Storage.

Skonfiguruj

Aby używać funkcji Cloud Storage, przypisz do konta usługi Cloud Storage rolę uprawnień pubsub.publisher:

SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT \
  --role roles/pubsub.publisher

Utwórz

Utwórz folder aplikacji i otwórz go:

mkdir ../hello-storage
cd ../hello-storage

Utwórz plik index.js, który po prostu reaguje na zdarzenia Cloud Storage:

const functions = require('@google-cloud/functions-framework');

functions.cloudEvent('helloStorage', (cloudevent) => {
  console.log('Cloud Storage event with Node.js in Cloud Run functions!');
  console.log(cloudevent);
});

Utwórz plik package.json, aby określić zależności:

{
  "name": "nodejs-crf-cloud-storage",
  "version": "0.0.1",
  "main": "index.js",
  "dependencies": {
    "@google-cloud/functions-framework": "^2.0.0"
  }
}

Wdróż

Najpierw utwórz zasobnik Cloud Storage (lub użyj istniejącego zasobnika):

export BUCKET_NAME="gcf-storage-$PROJECT_ID"
​​export BUCKET="gs://gcf-storage-$PROJECT_ID"
gsutil mb -l $REGION $BUCKET

Wdróż funkcję:

gcloud run deploy nodejs-crf-cloud-storage \
 --source . \
 --base-image nodejs22 \
 --function helloStorage \
 --region $REGION \
 --no-allow-unauthenticated

Po wdrożeniu funkcji możesz ją wyświetlić w sekcji Cloud Run w Cloud Console.

Teraz utwórz aktywator Eventarc.

BUCKET_REGION=$REGION

gcloud eventarc triggers create nodejs-crf-cloud-storage-trigger \
  --location=$BUCKET_REGION \
  --destination-run-service=nodejs-crf-cloud-storage \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.finalized" \
  --event-filters="bucket=$BUCKET_NAME" \
  --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

Test

Przetestuj funkcję, przesyłając plik do zasobnika:

echo "Hello World" > random.txt
gsutil cp random.txt $BUCKET/random.txt

W logach powinien pojawić się otrzymany CloudEvent:

gcloud run services logs read nodejs-crf-cloud-storage --region $REGION --limit=10

6. Dzielenie ruchu

Funkcje Cloud Run obsługują wiele wersji funkcji, dzieląc ruch między różne wersje i przywracając funkcję do poprzedniej wersji.

W tym kroku wdroż 2 wersje funkcji, a następnie podziel ruch między nimi w proporcji 50–50.

Utwórz

Utwórz folder aplikacji i otwórz go:

mkdir ../traffic-splitting
cd ../traffic-splitting

Utwórz plik main.py z funkcją Pythona, która odczytuje zmienną środowiskową koloru i odpowie Hello World w tym kolorze tła:

import os

color = os.environ.get('COLOR')

def hello_world(request):
    return f'<body style="background-color:{color}"><h1>Hello World!</h1></body>'

Aby określić zależności, utwórz plik requirements.txt z podaną niżej treścią:

functions-framework==3.*

Wdróż

Wdróż pierwszą wersję funkcji z pomarańczowym tłem:

COLOR=orange
gcloud run deploy hello-world-colors \
 --source . \
 --base-image python313 \
 --function hello_world \
 --region $REGION \
 --allow-unauthenticated \
 --update-env-vars COLOR=$COLOR

Jeśli w tym momencie otworzysz w przeglądarce funkcję, aby wyświetlić w niej aktywator HTTP (dane wyjściowe URI z powyższego polecenia wdrożenia), powinna się ona wyświetlić na pomarańczowym tle: Hello World.

36ca0c5f39cc89cf.png

Wdróż drugą wersję z żółtym tłem:

COLOR=yellow
gcloud run deploy hello-world-colors \
 --source . \
 --base-image python313 \
 --function hello_world \
 --region $REGION \
 --allow-unauthenticated \
 --update-env-vars COLOR=$COLOR

Ponieważ jest to najnowsza wersja, podczas testowania funkcji powinieneś/powinnaś zobaczyć Hello World z żółtym tłem:

391286a08ad3cdde.png

Podział ruchu na 50–50

Aby podzielić ruch na wersje pomarańczową i żółtą, musisz znaleźć identyfikatory wersji usług Cloud Run. Aby wyświetlić identyfikatory wersji, użyj tego polecenia:

gcloud run revisions list --service hello-world-colors \
  --region $REGION --format 'value(REVISION)'

Dane wyjściowe powinny być podobne do tych:

hello-world-colors-00001-man
hello-world-colors-00002-wok

Teraz podziel ruch między te 2 wersje w ten sposób: (zaktualizuj X-XXX zgodnie z nazwami swoich wersji):

gcloud run services update-traffic hello-world-colors \
  --region $REGION \
  --to-revisions hello-world-colors-0000X-XXX=50,hello-world-colors-0000X-XXX=50

Test

Przetestuj funkcję, otwierając jej publiczny adres URL. Połowa wersji powinna być pomarańczowa, a druga połowa żółta:

36ca0c5f39cc89cf.png 391286a08ad3cdde.png

Więcej informacji znajdziesz w artykule Przywracanie, wdrażanie stopniowe i migracja ruchu.

7. Minimalna liczba instancji

W funkcjach Cloud Run możesz określić minimalną liczbę instancji funkcji, które mają być utrzymywane w gotowości do obsługi żądań. Jest to przydatne, ponieważ ogranicza liczbę uruchomień „na zimno”.

W tym kroku wdrożysz funkcję z wolną inicjalizacją. Zaobserwujesz problem z uruchomieniem „na zimno”. Następnie wdróż funkcję z wartością minimalnej liczby instancji ustawioną na 1, aby uniknąć uruchomień „na zimno”.

Utwórz

Utwórz folder aplikacji i otwórz go:

mkdir ../min-instances
cd ../min-instances

Utwórz plik main.go. Ta usługa w Go ma funkcję init, która czeka 10 sekund, aby symulować długą inicjalizację. Ma też funkcję HelloWorld, która odpowiada na wywołania HTTP:

package p

import (
        "fmt"
        "net/http"
        "time"
)

func init() {
        time.Sleep(10 * time.Second)
}

func HelloWorld(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "Slow HTTP Go in Cloud Run functions!")
}

Wdróż

Wdróż pierwszą wersję funkcji z domyślną minimalną wartością instancji równą 0:

gcloud run deploy go-slow-function \
 --source . \
 --base-image go123 \
 --function HelloWorld \
 --region $REGION \
 --no-allow-unauthenticated

Testowanie funkcji za pomocą tego polecenia:

# get the Service URL
SERVICE_URL="$(gcloud run services describe go-slow-function --region $REGION --format 'value(status.url)')"

# invoke the service
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

W przypadku pierwszego wywołania nastąpi 10-sekundowa zwłoka (zimny start), a potem zobaczysz wiadomość. Kolejne wywołania powinny być realizowane natychmiast.

Ustawianie minimalnej liczby instancji

Aby uniknąć uruchamiania „na zimno” przy pierwszym żądaniu, ponownie wdrożyć funkcję z flagą --min-instances ustawioną na 1 w następujący sposób:

gcloud run deploy go-slow-function \
 --source . \
 --base-image go123 \
 --function HelloWorld \
 --region $REGION \
 --no-allow-unauthenticated \
 --min-instances 1

Test

Ponownie przetestuj funkcję:

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL

Opóźnienie 10 sekund nie powinno już występować w przypadku pierwszego żądania. Dzięki minimalnej liczbie instancji problem z uruchomieniem „na zimno” podczas pierwszego wywołania (po długim czasie bez wywołania) został rozwiązany.

Więcej informacji znajdziesz w artykule o minimalnej liczbie instancji.

8. Gratulacje!

Gratulujemy ukończenia ćwiczeń.

Omówione zagadnienia

  • Omówienie funkcji Cloud Run i sposobu korzystania z automatycznych aktualizacji obrazu bazowego.
  • Jak napisać funkcję, która odpowiada na wywołania HTTP.
  • Jak napisać funkcję, która odpowiada na wiadomości Pub/Sub.
  • Jak napisać funkcję, która reaguje na zdarzenia Cloud Storage.
  • Jak podzielić ruch między 2 wersje.
  • Jak pozbyć się uruchomień „na zimno” za pomocą minimalnej liczby instancji