1. מבוא
סקירה כללית
פונקציות Cloud Run הוא שירות Functions-as-a-Service של Google Cloud שמבוסס על Cloud Run ועל Eventarc. השירות הזה מאפשר לכם שליטה מתקדמת יותר בביצועים ובמדרגיות, ושליטה רבה יותר בזמן הריצה ובטריגרים של הפונקציות מתוך יותר מ-90 מקורות אירועים.
ב-codelab הזה נסביר איך ליצור פונקציות Cloud Run שמגיבות לקריאות HTTP, ומופעלות על ידי הודעות Pub/Sub ויומני Cloud Audit Logs.
ב-codelab הזה נעשה שימוש גם בעדכונים אוטומטיים של תמונת הבסיס לפריסות של פונקציות. כדי לעשות את זה, מציינים תמונת בסיס באמצעות הדגל --base-image. עדכונים אוטומטיים של תמונת הבסיס ב-Cloud Run מאפשרים ל-Google לבצע באופן אוטומטי תיקוני אבטחה במערכת ההפעלה וברכיבי זמן הריצה של השפה בתמונת הבסיס. לא צריך לבנות מחדש את השירות או לפרוס אותו מחדש כדי שתמונת הבסיס תתעדכן. מידע נוסף זמין במאמר בנושא עדכונים אוטומטיים של תמונות בסיס
אם אתם מעדיפים לא להשתמש בעדכונים אוטומטיים של תמונות בסיס, אתם יכולים להסיר את הדגל --base-image מהדוגמאות שמוצגות ב-codelab הזה.
מה תלמדו
- סקירה כללית של פונקציות Cloud Run והסבר על שימוש בעדכונים אוטומטיים של תמונות בסיס.
- איך כותבים פונקציה שמגיבה לקריאות HTTP.
- איך כותבים פונקציה שמגיבה להודעות Pub/Sub.
- איך כותבים פונקציה שמגיבה לאירועים ב-Cloud Storage.
- איך לפצל את התנועה בין שתי גרסאות.
- איך להימנע מהתחלה במצב התחלתי (cold start) באמצעות הגדרת מספר מינימלי של מופעים.
2. הגדרה ודרישות
יצירת תיקיית בסיס
יוצרים תיקיית שורש לכל הדוגמאות.
mkdir crf-codelab cd crf-codelab
הגדרה של משתני סביבה
מגדירים משתני סביבה שישמשו לאורך כל ה-codelab.
gcloud config set project <YOUR-PROJECT-ID> REGION=<YOUR_REGION> PROJECT_ID=$(gcloud config get-value project)
הפעלת ממשקי ה-API
מפעילים את כל השירותים הנדרשים:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ eventarc.googleapis.com \ run.googleapis.com \ logging.googleapis.com \ pubsub.googleapis.com
3. פונקציית HTTP
בפונקציה הראשונה, ניצור פונקציית Node.js מאומתת שמגיבה לבקשות HTTP. נשתמש גם בערך timeout של 10 דקות כדי להראות איך פונקציה יכולה לקבל יותר זמן להגיב לבקשות HTTP.
יצירה
יוצרים תיקייה לאפליקציה ועוברים לתיקייה:
mkdir hello-http cd hello-http
יוצרים קובץ index.js שמגיב לבקשות 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!');
});
יוצרים קובץ package.json כדי לציין את התלות:
{
"name": "nodejs-run-functions-codelab",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"@google-cloud/functions-framework": "^2.0.0"
}
}
Deploy
פורסים את הפונקציה:
gcloud run deploy nodejs-run-function \
--source . \
--function helloWorld \
--base-image nodejs22 \
--region $REGION \
--timeout 600 \
--no-allow-unauthenticated
הפקודה הזו משתמשת ב-buildpacks כדי להפוך את קוד המקור של הפונקציה לקובץ אימג' של קונטיינר שמוכן לייצור.
שימו לב:
- הדגל
--sourceמשמש כדי להנחות את Cloud Run ליצור את הפונקציה כשירות מבוסס-קונטיינר שאפשר להריץ - הדגל
--function(חדש) משמש להגדרת נקודת הכניסה של השירות החדש לחתימת הפונקציה שרוצים להפעיל - הדגל
--base-image(חדש) מציין את סביבת תמונת הבסיס של הפונקציה, כמוnodejs22,python312,go123,java21,dotnet8,ruby33אוphp83. לפרטים נוספים על תמונות בסיס ועל החבילות שכלולות בכל תמונה, אפשר לעיין במאמר תמונות בסיס של סביבות ריצה. - (אופציונלי) הדגל
--timeoutמאפשר לפונקציה להגיב לבקשות HTTP עם זמן קצוב לתפוגה ארוך יותר. בדוגמה הזו, נעשה שימוש ב-600 שניות כדי להדגים זמן תגובה של 10 דקות. - (אופציונלי)
--no-allow-unauthenticatedכדי למנוע הפעלה של הפונקציה על ידי הציבור
בדיקה
בודקים את הפונקציה באמצעות הפקודות הבאות:
# 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
אמורה להופיע התגובה HTTP with Node.js in Cloud Run functions!.
4. פונקציית Pub/Sub
עכשיו ניצור פונקציית Python שנייה שמופעלת על ידי הודעת Pub/Sub שפורסמה בנושא ספציפי.
הגדרת טוקנים לאימות ב-Pub/Sub
אם הפעלתם את חשבון השירות של Pub/Sub ב-8 באפריל 2021 או לפני כן, צריך להקצות את התפקיד iam.serviceAccountTokenCreator לחשבון השירות של Pub/Sub:
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
יצירה
יוצרים נושא Pub/Sub לשימוש בדוגמה:
TOPIC=cloud-run-functions-pubsub-topic gcloud pubsub topics create $TOPIC
יוצרים תיקייה לאפליקציה ועוברים לתיקייה:
mkdir ../hello-pubsub cd ../hello-pubsub
יוצרים קובץ main.py שמתעד הודעה שמכילה את מזהה 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'])
כדי לציין את התלות, יוצרים קובץ requirements.txt עם התוכן הבא:
functions-framework==3.*
Deploy
פורסים את הפונקציה:
gcloud run deploy python-pubsub-function \
--source . \
--function hello_pubsub \
--base-image python313 \
--region $REGION \
--no-allow-unauthenticated
מאחזרים את מספר הפרויקט שישמש לזהות של חשבון השירות.
PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')
יצירת הטריגר
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
בדיקה
כדי לבדוק את הפונקציה, שולחים הודעה לנושא:
gcloud pubsub topics publish $TOPIC --message="Hello World"
האירוע CloudEvent שהתקבל אמור להופיע ביומנים:
gcloud run services logs read python-pubsub-function --region $REGION --limit=10
5. פונקציה של Cloud Storage
בפונקציה הבאה, ניצור פונקציית Node.js שמגיבה לאירועים מקטגוריית Cloud Storage.
הגדרה
כדי להשתמש בפונקציות של Cloud Storage, צריך להקצות את תפקיד pubsub.publisher ב-IAM לחשבון השירות של Cloud Storage:
SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER) gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$SERVICE_ACCOUNT \ --role roles/pubsub.publisher
יצירה
יוצרים תיקייה לאפליקציה ועוברים לתיקייה:
mkdir ../hello-storage cd ../hello-storage
יוצרים קובץ index.js שמגיב לאירועים ב-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);
});
יוצרים קובץ package.json כדי לציין את התלות:
{
"name": "nodejs-crf-cloud-storage",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"@google-cloud/functions-framework": "^2.0.0"
}
}
Deploy
קודם כול יוצרים קטגוריה של Cloud Storage (או משתמשים בקטגוריה קיימת):
export BUCKET_NAME="gcf-storage-$PROJECT_ID" export BUCKET="gs://gcf-storage-$PROJECT_ID" gsutil mb -l $REGION $BUCKET
פורסים את הפונקציה:
gcloud run deploy nodejs-crf-cloud-storage \ --source . \ --base-image nodejs22 \ --function helloStorage \ --region $REGION \ --no-allow-unauthenticated
אחרי פריסת הפונקציה, אפשר לראות אותה בקטע Cloud Run ב-Cloud Console.
עכשיו יוצרים את הטריגר של 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
בדיקה
כדי לבדוק את הפונקציה, מעלים קובץ לקטגוריה:
echo "Hello World" > random.txt gsutil cp random.txt $BUCKET/random.txt
האירוע CloudEvent שהתקבל אמור להופיע ביומנים:
gcloud run services logs read nodejs-crf-cloud-storage --region $REGION --limit=10
6. יומני ביקורת של Cloud
בפונקציה הבאה, ניצור פונקציית Node.js שמקבלת אירוע של Cloud Audit Log כשנוצרת מכונה וירטואלית ב-Compute Engine. בתגובה, המערכת מוסיפה תווית למכונת ה-VM החדשה שנוצרה, ומציינת את היוצר של מכונת ה-VM.
איך מזהים מכונות וירטואליות חדשות שנוצרו ב-Compute Engine
כשמכונת VM נוצרת, מערכת Compute Engine פולטת 2 יומני ביקורת.
האירוע הראשון מופק בתחילת יצירת מכונת ה-VM. השני נפלט אחרי שנוצרת מכונה וירטואלית.
בשדות של הפעולות ביומני הביקורת יש ערכים שונים, first: true ו-last: true. יומן הביקורת השני מכיל את כל המידע שדרוש לנו כדי לסמן מופע, ולכן נשתמש בדגל last: true כדי לזהות אותו בפונקציות של Cloud Run.
הגדרה
כדי להשתמש בפונקציות של יומן הביקורת של Cloud, צריך להפעיל את יומני הביקורת ב-Eventarc. צריך גם להשתמש בחשבון שירות עם התפקיד eventarc.eventReceiver.
- מפעילים את סוגי היומנים קריאת אדמין, קריאת נתונים וכתיבת נתונים ב-Cloud Audit Logs עבור Compute Engine API.
- מקצים לחשבון השירות של Compute Engine שמוגדר כברירת מחדל את התפקיד
eventarc.eventReceiverב-IAM:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --role roles/eventarc.eventReceiver
יצירת הפונקציה
ב-Codelab הזה נעשה שימוש ב-node.js, אבל אפשר למצוא דוגמאות נוספות בכתובת https://github.com/GoogleCloudPlatform/eventarc-samples
יצירת קובץ package.json
{
"dependencies": {
"googleapis": "^84.0.0"
}
}
יצירת קובץ node.js
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const { google } = require("googleapis");
var compute = google.compute("v1");
exports.labelVmCreation = async (cloudevent) => {
const data = cloudevent.body;
// in case an event has >1 audit log
// make sure we respond to the last event
if (!data.operation || !data.operation.last) {
console.log("Operation is not last, skipping event");
return;
}
// projects/dogfood-gcf-saraford/zones/us-central1-a/instances/instance-1
var resourceName = data.protoPayload.resourceName;
var resourceParts = resourceName.split("/");
var project = resourceParts[1];
var zone = resourceParts[3];
var instanceName = resourceParts[5];
var username = data.protoPayload.authenticationInfo.principalEmail.split("@")[0];
console.log(`Setting label username: ${username} to instance ${instanceName} for zone ${zone}`);
var authClient = await google.auth.getClient({
scopes: ["https://www.googleapis.com/auth/cloud-platform"]
});
// per docs: When updating or adding labels in the API,
// you need to provide the latest labels fingerprint with your request,
// to prevent any conflicts with other requests.
var labelFingerprint = await getInstanceLabelFingerprint(authClient, project, zone, instanceName);
var responseStatus = await setVmLabel(
authClient,
labelFingerprint,
username,
project,
zone,
instanceName
);
// log results of setting VM label
console.log(JSON.stringify(responseStatus, null, 2));
};
async function getInstanceLabelFingerprint(authClient, project, zone, instanceName) {
var request = {
project: project,
zone: zone,
instance: instanceName,
auth: authClient
};
var response = await compute.instances.get(request);
var labelFingerprint = response.data.labelFingerprint;
return labelFingerprint;
}
async function setVmLabel(authClient, labelFingerprint, username, project, zone, instanceName) {
var request = {
project: project,
zone: zone,
instance: instanceName,
resource: {
labels: { "creator": username },
labelFingerprint: labelFingerprint
},
auth: authClient
};
var response = await compute.instances.setLabels(request);
return response.statusText;
}
Deploy
פורסים את הפונקציה:
gcloud run deploy gce-vm-labeler \ --source . \ --function labelVmCreation \ --region $REGION \ --no-allow-unauthenticated
עכשיו יוצרים את הטריגר. שימו לב איך הפונקציה מסננת ביומני הביקורת את הוספות של Compute Engine עם הדגל --trigger-event-filters.
gcloud eventarc triggers create gce-vm-labeler-trigger \ --location=$REGION \ --destination-run-service=gce-vm-labeler \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.audit.log.v1.written,serviceName=compute.googleapis.com,methodName=v1.compute.instances.insert" \ --service-account=$ROJECT_NUMBER-compute@developer.gserviceaccount.com
בדיקה
מגדירים את משתני הסביבה:
# if you're using europe-west1 as your region
ZONE=europe-west1-d
VM_NAME=codelab-crf-auditlog
מריצים את הפקודה הבאה כדי ליצור מכונת VM:
gcloud compute instances create $VM_NAME --zone=$ZONE --machine-type=e2-medium --image-family=debian-11 --image-project=debian-cloud
אחרי שהמכונה הווירטואלית נוצרת, התווית creator שנוספה אמורה להופיע במכונה הווירטואלית במסוף Cloud בקטע Basic information או באמצעות הפקודה הבאה:
gcloud compute instances describe $VM_NAME --zone=$ZONE
התווית אמורה להופיע בפלט כמו בדוגמה הבאה:
... labelFingerprint: ULU6pAy2C7s= labels: creator: atameldev ...
הסרת המשאבים
חשוב למחוק את מופע ה-VM. לא נשתמש בו שוב במעבדה הזו.
gcloud compute instances delete $VM_NAME --zone=$ZONE
7. פיצול תנועה
פונקציות Cloud Run תומכות בכמה גרסאות של הפונקציות, בחלוקת התנועה בין גרסאות שונות ובהחזרת הפונקציה לגרסה קודמת.
בשלב הזה, תפרסו 2 גרסאות של פונקציה ואז תחלקו את התנועה ביניהן באופן שווה.
יצירה
יוצרים תיקייה לאפליקציה ועוברים לתיקייה:
mkdir ../traffic-splitting cd ../traffic-splitting
יוצרים קובץ main.py עם פונקציית Python שקוראת משתנה סביבה של צבע ומחזירה את הערך Hello World בצבע הרקע הזה:
import os
color = os.environ.get('COLOR')
def hello_world(request):
return f'<body style="background-color:{color}"><h1>Hello World!</h1></body>'
כדי לציין את התלות, יוצרים קובץ requirements.txt עם התוכן הבא:
functions-framework==3.*
Deploy
פורסים את הגרסה הראשונה של הפונקציה עם רקע כתום:
COLOR=orange gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
בשלב הזה, אם תבדקו את הפונקציה על ידי הצגת טריגר ה-HTTP (פלט ה-URI של פקודת הפריסה שלמעלה) בדפדפן, אמור להופיע Hello World עם רקע כתום:

פורסים את הגרסה השנייה עם רקע צהוב:
COLOR=yellow gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
מכיוון שזו הגרסה האחרונה, אם תבדקו את הפונקציה, תראו את הערך Hello World עם רקע צהוב:

פיצול התנועה 50-50
כדי לפצל את התנועה בין הגרסאות הכתומות והצהובות, צריך למצוא את מזהי הגרסאות של שירותי Cloud Run. זו הפקודה להצגת מזהי הגרסאות:
gcloud run revisions list --service hello-world-colors \ --region $REGION --format 'value(REVISION)'
הפלט אמור להיראות כך:
hello-world-colors-00001-man hello-world-colors-00002-wok
עכשיו, מחלקים את התנועה בין שתי הגרסאות האלה באופן הבא (צריך לעדכן את X-XXX בהתאם לשמות הגרסאות):
gcloud run services update-traffic hello-world-colors \ --region $REGION \ --to-revisions hello-world-colors-0000X-XXX=50,hello-world-colors-0000X-XXX=50
בדיקה
כדי לבדוק את הפונקציה, נכנסים לכתובת ה-URL הציבורית שלה. במחצית מהמקרים תראו את הגרסה הכתומה, ובמחצית מהמקרים תראו את הגרסה הצהובה:

מידע נוסף זמין במאמר בנושא החזרות, השקות הדרגתיות והעברת תנועה.
8. מינימום מכונות
בפונקציות Cloud Run, אפשר לציין מספר מינימלי של מופעי פונקציות שיישארו במצב 'מוכנים' ויהיו זמינים לטיפול בבקשות. האפשרות הזו שימושית להגבלת מספר ההפעלות במצב התחלתי (Cold start).
בשלב הזה תפרסו פונקציה עם אתחול איטי. תראו את הבעיה של הפעלה במצב התחלתי (cold start). לאחר מכן, תפרסו את הפונקציה עם הערך המינימלי של המופע שמוגדר ל-1 כדי להימנע מהפעלה במצב התחלתי (cold start).
יצירה
יוצרים תיקייה לאפליקציה ועוברים אליה:
mkdir ../min-instances cd ../min-instances
יוצרים קובץ main.go. בשירות Go הזה יש פונקציה init שמשהה את הפעולה למשך 10 שניות כדי לדמות אתחול ארוך. יש לה גם פונקציה HelloWorld שמגיבה לקריאות 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!")
}
Deploy
פורסים את הגרסה הראשונה של הפונקציה עם ערך ברירת המחדל של המינימום של המופעים, שהוא אפס:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated
בודקים את הפונקציה באמצעות הפקודה הבאה:
# 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
בשיחה הראשונה תהיה השהיה של 10 שניות (הפעלה במצב התחלתי (cold start)) ואז תופיע ההודעה. קריאות חוזרות צריכות להחזיר ערך באופן מיידי.
הגדרת מספר מינימלי של מופעים
כדי להימנע מההפעלה במצב התחלתי (cold start) בבקשה הראשונה, צריך לפרוס מחדש את הפונקציה עם הערך 1 של הדגל --min-instances, באופן הבא:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated \ --min-instances 1
בדיקה
בודקים שוב את הפונקציה:
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
העיכוב של 10 שניות לא אמור להופיע יותר בבקשה הראשונה. בעיית ההפעלה במצב התחלתי (cold start) בקריאה הראשונה (אחרי זמן רב ללא קריאות) נפתרה, בזכות המקרים המינימליים.
מידע נוסף זמין במאמר בנושא שימוש במופעים מינימליים.
9. מעולה!
כל הכבוד, סיימתם את ה-Codelab!
מה נכלל
- סקירה כללית של פונקציות Cloud Run והסבר על שימוש בעדכונים אוטומטיים של תמונות בסיס.
- איך כותבים פונקציה שמגיבה לקריאות HTTP.
- איך כותבים פונקציה שמגיבה להודעות Pub/Sub.
- איך כותבים פונקציה שמגיבה לאירועים ב-Cloud Storage.
- איך לפצל את התנועה בין שתי גרסאות.
- איך להימנע מהתחלה במצב התחלתי (cold start) באמצעות הגדרת מספר מינימלי של מופעים.