شروع کار با توابع Cloud Run

1. مقدمه

نمای کلی

توابع Cloud Run یک سرویس Google Cloud Functions-as-a-Service است که توسط Cloud Run و Eventarc ارائه می‌شود و به شما کنترل پیشرفته‌تری بر عملکرد و مقیاس‌پذیری می‌دهد و کنترل بیشتری در مورد زمان اجرا و راه‌اندازهای عملکردها از بیش از ۹۰ منبع رویداد به شما می‌دهد.

این لبه کد شما را در ایجاد عملکردهای Cloud Run که به تماس‌های HTTP پاسخ می‌دهند و توسط پیام‌های Pub/Sub و گزارش‌های Cloud Audit فعال می‌شوند، راهنمایی می‌کند.

این کد لبه همچنین از به روز رسانی خودکار تصویر پایه برای استقرار عملکرد با تعیین یک تصویر پایه با استفاده از پرچم --base-image استفاده می کند. به‌روزرسانی خودکار تصویر پایه برای Cloud Run به Google امکان می‌دهد تا وصله‌های امنیتی سیستم عامل و اجزای زمان اجرا زبان تصویر پایه را به طور خودکار ایجاد کند. برای اینکه تصویر پایه به روز شود، نیازی به بازسازی یا استفاده مجدد از سرویس خود ندارید. برای اطلاعات بیشتر، به‌روزرسانی خودکار تصویر پایه را بررسی کنید

اگر ترجیح می‌دهید از به‌روزرسانی خودکار تصویر پایه استفاده نکنید ، می‌توانید پرچم --base-image را از نمونه‌های نشان‌داده‌شده در این لبه کد حذف کنید.

چیزی که یاد خواهید گرفت

  • مروری بر عملکردهای Cloud Run و نحوه استفاده از به روز رسانی خودکار تصویر پایه.
  • نحوه نوشتن تابعی که به تماس های HTTP پاسخ می دهد.
  • نحوه نوشتن تابعی که به پیام‌های Pub/Sub پاسخ می‌دهد.
  • نحوه نوشتن تابعی که به رویدادهای Cloud Storage پاسخ می دهد.
  • نحوه تقسیم ترافیک بین دو نسخه
  • نحوه خلاص شدن از شر سرما با حداقل موارد شروع می شود.

2. راه اندازی و الزامات

یک پوشه ریشه ایجاد کنید

یک پوشه ریشه برای تمام مثال ها ایجاد کنید.

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

این دستور از buildpack ها برای تبدیل کد منبع تابع شما به یک تصویر ظرف آماده برای تولید استفاده می کند.

لطفا به موارد زیر توجه کنید:

  • پرچم --source برای گفتن به Cloud Run استفاده می شود تا تابع را در یک سرویس مبتنی بر کانتینر قابل اجرا بسازد.
  • پرچم --function (جدید) برای تنظیم نقطه ورودی سرویس جدید به عنوان امضای تابعی که می خواهید فراخوانی شود استفاده می شود.
  • پرچم --base-image (جدید) محیط تصویر پایه را برای عملکرد شما مشخص می کند، مانند nodejs22 ، python312 ، go123 ، java21 ، dotnet8 ، ruby33 ، یا php83 . برای جزئیات بیشتر در مورد تصاویر پایه و بسته های موجود در هر تصویر، به تصاویر پایه Runtimes مراجعه کنید.
  • (اختیاری) پرچم --timeout به تابع اجازه می دهد تا زمان بیشتری برای پاسخ به درخواست های HTTP داشته باشد. در این مثال، 600 ثانیه برای نشان دادن زمان پاسخ دهی دقیقه ای استفاده می شود.
  • (اختیاری) --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 منتشر شده در یک موضوع خاص راه اندازی می شود.

توکن‌های Pub/Sub auth را تنظیم کنید

اگر حساب سرویس 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. عملکرد ذخیره سازی ابری

برای تابع بعدی، اجازه دهید یک تابع Node.js ایجاد کنیم که به رویدادهای یک سطل ذخیره‌سازی ابری پاسخ می‌دهد.

راه اندازی کنید

برای استفاده از توابع 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"
  }
}

مستقر کنید

ابتدا یک سطل 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 Run از ویرایش های متعدد توابع شما پشتیبانی می کند، ترافیک را بین نسخه های مختلف تقسیم می کند و عملکرد شما را به نسخه قبلی برمی گرداند.

در این مرحله، 2 ویرایش از یک تابع را اجرا می کنید و سپس ترافیک را بین آنها 50-50 تقسیم می کنید.

ایجاد کنید

یک پوشه برای برنامه ایجاد کنید و به پوشه بروید:

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

یک فایل main.py با یک تابع پایتون ایجاد کنید که متغیر محیط رنگی را می خواند و با 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.png391286a08ad3cdde.png

برای اطلاعات بیشتر به بازگشت، عرضه تدریجی و انتقال ترافیک مراجعه کنید.

7. حداقل موارد

در توابع Cloud Run، می‌توانید حداقل تعداد نمونه عملکرد را مشخص کنید تا گرم نگه داشته شوند و برای ارائه درخواست‌ها آماده باشند. این برای محدود کردن تعداد شروع سرد مفید است.

در این مرحله، یک تابع با مقدار دهی اولیه آهسته اجرا می کنید. مشکل شروع سرد را مشاهده خواهید کرد. سپس، برای خلاص شدن از شر شروع سرد، تابعی را با حداقل مقدار نمونه تنظیم شده روی 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 ثانیه ای (شروع سرد) مشاهده خواهید کرد و سپس پیام را مشاهده خواهید کرد. تماس‌های بعدی باید فوراً برگردند.

حداقل نمونه ها را تنظیم کنید

برای خلاص شدن از شر شروع سرد در اولین درخواست، تابع را با پرچم --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 ثانیه تاخیر را مشاهده کنید. مشکل شروع سرد برای اولین فراخوان (پس از مدت طولانی بدون) به لطف حداقل موارد از بین رفته است!

برای اطلاعات بیشتر به استفاده از حداقل نمونه ها مراجعه کنید.

8. تبریک می گویم!

برای تکمیل کد لبه تبریک می گویم!

آنچه را پوشش داده ایم

  • مروری بر عملکردهای Cloud Run و نحوه استفاده از به روز رسانی خودکار تصویر پایه.
  • نحوه نوشتن تابعی که به تماس های HTTP پاسخ می دهد.
  • نحوه نوشتن تابعی که به پیام‌های Pub/Sub پاسخ می‌دهد.
  • نحوه نوشتن تابعی که به رویدادهای Cloud Storage پاسخ می دهد.
  • نحوه تقسیم ترافیک بین دو نسخه
  • نحوه خلاص شدن از شر سرما با حداقل موارد شروع می شود.