תחילת העבודה עם פונקציות Cloud Run

1. מבוא

סקירה כללית

פונקציות Cloud Run הן חבילת השירות של Google Cloud מסוג Functions as a Service שמבוססת על Cloud Run ו-Eventarc. היא מספקת לכם שליטה מתקדמת יותר על הביצועים והתאימות לעומס, ועל זמן הריצה והטריגרים של הפונקציות מיותר מ-90 מקורות אירועים.

בקודלאב הזה נסביר איך יוצרים פונקציות של Cloud Run שמגיבות לשיחות HTTP, ומופעלות על ידי הודעות Pub/Sub ויומני ביקורת של Cloud.

ב-codelab הזה נעשה גם שימוש בעדכונים אוטומטיים של קובץ האימג' הבסיסי לפריסות של פונקציות, על ידי ציון קובץ אימג' בסיסי באמצעות הדגל --base-image. עדכונים אוטומטיים של קובץ האימג' הבסיסי ב-Cloud Run מאפשרים ל-Google להחיל תיקוני אבטחה באופן אוטומטי על רכיבי מערכת ההפעלה ועל רכיבי סביבת זמן הריצה של השפה בקובץ האימג' הבסיסי. אין צורך ליצור מחדש את השירות או לפרוס אותו מחדש כדי לעדכן את קובץ האימג' הבסיסי. מידע נוסף זמין במאמר עדכונים אוטומטיים של קובצי אימג' בסיסיים

אם אתם מעדיפים לא להשתמש בעדכונים אוטומטיים של קובצי אימג' בסיסיים, תוכלו להסיר את הדגל --base-image מהדוגמאות שמוצגות ב-codelab הזה.

מה תלמדו

  • סקירה כללית על פונקציות Cloud Run ועל השימוש בעדכונים אוטומטיים של קובצי אימג' בסיסיים.
  • איך כותבים פונקציה שתגיב לבקשות HTTP.
  • איך לכתוב פונקציה שמגיבה להודעות Pub/Sub.
  • איך כותבים פונקציה שמגיבה לאירועים ב-Cloud Storage.
  • איך לפצל את התנועה בין שתי גרסאות.
  • איך להימנע מהפעלה במצב התחלתי (cold start) באמצעות מכונות מינימליות.

2. הגדרה ודרישות

יצירת תיקיית Root

יוצרים תיקיית root לכל הדוגמאות.

mkdir crf-codelab
cd crf-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. נשתמש גם בזמן קצוב לתפוגה של 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"
  }
}

פריסה

פורסים את הפונקציה:

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.*

פריסה

פורסים את הפונקציה:

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 Function

בפונקציה הבאה נשתמש ב-Node.js כדי ליצור פונקציה שתגיב לאירועים מקטגוריה של Cloud Storage.

הגדרה

כדי להשתמש בפונקציות של Cloud Storage, מקצים לחשבון השירות של Cloud Storage את תפקיד ה-IAM 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

יצירה

יוצרים תיקייה לאפליקציה ומנווטים לתיקייה:

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"
  }
}

פריסה

קודם כול יוצרים קטגוריה של 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.

עכשיו יוצרים את הטריגר של 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 Run תומכות בכמה גרסאות של הפונקציות, בחלוקת התנועה בין גרסאות שונות ובחזרה לגרסה קודמת של הפונקציה.

בשלב הזה, תפרסו 2 גרסאות של פונקציה ואז תחלקו את התנועה ביניהן ביחס של 50-50.

יצירה

יוצרים תיקייה לאפליקציה ומנווטים לתיקייה:

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.*

פריסה

פורסים את הגרסה הראשונה של הפונקציה עם רקע כתום:

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 עם רקע כתום:

36ca0c5f39cc89cf.png

פורסים את הגרסה השנייה עם רקע צהוב:

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 עם רקע צהוב:

391286a08ad3cdde.png

חלוקת התנועה ביחס של 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 הציבורית שלה. חצי מהזמן אמורה להופיע הגרסה הכתומה, ובחצי השני אמורה להופיע הגרסה הצהובה:

36ca0c5f39cc89cf.png 391286a08ad3cdde.png

מידע נוסף זמין במאמר החזרות לאחור, השקות הדרגתיות והעברת תנועה.

7. מספר מינימלי של מכונות

בפונקציות של Cloud Run, אפשר לציין מספר מינימלי של מכונות פונקציה שיישמרו במצב 'מוכנות' ויהיה אפשר להשתמש בהן כדי למלא בקשות. האפשרות הזו שימושית להגבלת מספר ההפעלות הראשוניות (cold start).

בשלב הזה, תפרסו פונקציה עם אתחול איטי. תוכלו לראות את הבעיה של ההפעלה במצב התחלתי (cold start). לאחר מכן, תפרסו את הפונקציה עם ערך המכונה המינימלי שמוגדר כ-1 כדי להיפטר מזמן ההפעלה הראשונית.

יצירה

יוצרים תיקייה לאפליקציה ועוברים אליה:

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!")
}

פריסה

פורסים את הגרסה הראשונה של הפונקציה עם ערך ברירת המחדל של אפס למכונה המינימלית:

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) בבקשה הראשונה, צריך לפרוס מחדש את הפונקציה עם הדגל --min-instances מוגדר ל-1 באופן הבא:

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) בקריאה הראשונה (אחרי זמן רב ללא קריאה) נפתרה, בזכות מכונות מינימום!

מידע נוסף זמין במאמר שימוש במספר מינימלי של מכונות.

8. מעולה!

כל הכבוד על השלמת ה-Codelab!

מה עסקנו בו

  • סקירה כללית על פונקציות Cloud Run ועל השימוש בעדכונים אוטומטיים של קובצי אימג' בסיסיים.
  • איך כותבים פונקציה שתגיב לבקשות HTTP.
  • איך לכתוב פונקציה שמגיבה להודעות Pub/Sub.
  • איך כותבים פונקציה שמגיבה לאירועים ב-Cloud Storage.
  • איך לפצל את התנועה בין שתי גרסאות.
  • איך להימנע מהפעלה במצב התחלתי (cold start) באמצעות מכונות מינימליות.