مقیاس‌بندی خودکار Cloud Run worker pools بر اساس حجم صف Pub/Sub با استفاده از CREMA

۱. مقدمه

نمای کلی

این آموزش به شما نشان می‌دهد که چگونه یک مخزن کارگر (مصرف‌کننده) Cloud Run را برای پردازش پیام‌های Pub/Sub مستقر کنید و به طور خودکار نمونه‌های مصرف‌کننده خود را بر اساس عمق صف با استفاده از مقیاس‌بندی خودکار معیارهای خارجی Cloud Run (CREMA) مقیاس‌بندی کنید.

آنچه یاد خواهید گرفت

در این آزمایشگاه کد، شما:

  • یک موضوع انتشار/زیرموضوع ایجاد کنید و در آن موضوع مشترک شوید و پیام‌ها را به آن ارسال کنید.
  • یک مخزن کارگر (مصرف‌کننده) Cloud Run مستقر کنید که پیام‌های Pub/Sub را مصرف کند.
  • پروژه CREMA را به عنوان یک سرویس Cloud Run در GitHub مستقر کنید تا به طور خودکار مجموعه کارگران خود را بر اساس تعداد پیام‌های موجود در اشتراک Pub/Sub مقیاس‌بندی کنید.
  • پیکربندی مقیاس‌پذیری خودکار خود را با ایجاد بار با اجرای یک اسکریپت پایتون به صورت محلی آزمایش کنید.

۲. پیکربندی متغیرهای محیطی

از آنجایی که متغیرهای محیطی زیادی در سراسر این آزمایشگاه کد استفاده می‌شوند، توصیه می‌کنیم اجرا کنید

set -u

که اگر سعی کنید از متغیر محیطی که هنوز تنظیم نشده است استفاده کنید، به شما هشدار می‌دهد. برای لغو این تنظیم، set +u را اجرا کنید.

ابتدا متغیر زیر را به شناسه پروژه خود تغییر دهید.

export PROJECT_ID=<YOUR_PROJECT_ID>

و سپس آن را به عنوان پروژه برای این آزمایشگاه کد تنظیم کنید.

gcloud config set project $PROJECT_ID

در مرحله بعد، متغیرهای محیطی مورد استفاده توسط این codelab را تنظیم کنید.

export REGION=us-central1
export TOPIC_ID=crema-pubsub-topic
export SUBSCRIPTION_ID=crema-pubsub-sub
export CREMA_SA_NAME=crema-service-account
export CONSUMER_SA_NAME=consumer-service-account
export CONSUMER_WORKER_POOL_NAME=worker-pool-consumer
export CREMA_SERVICE_NAME=my-crema-service

یک دایرکتوری برای این codelab ایجاد کنید

mkdir crema-pubsub-codelab
cd crema-pubsub-codelab

فعال کردن APIها

gcloud services enable \
        artifactregistry.googleapis.com \
        cloudbuild.googleapis.com \
        run.googleapis.com \
        parametermanager.googleapis.com

در آخر، مطمئن شوید که gcloud شما از آخرین نسخه استفاده می‌کند.

gcloud components update

۳. تنظیمات Pub/Sub

موضوع و اشتراک pull که worker pool شما پردازش خواهد کرد را ایجاد کنید. Bash

تاپیک رو ایجاد کنید.

gcloud pubsub topics create $TOPIC_ID

اشتراک را ایجاد کنید.

gcloud pubsub subscriptions create $SUBSCRIPTION_ID --topic=$TOPIC_ID

۴. حساب‌های کاربری IAM و سرویس‌ها

توصیه می‌شود برای هر منبع Cloud Run یک حساب کاربری سرویس ایجاد کنید. در این آزمایشگاه کد، موارد زیر را ایجاد خواهید کرد:

  • مشتری SA: هویت برای worker pool که پیام‌های Pub/Sub را پردازش می‌کند.
  • CREMA SA: هویت سرویس رسوب‌زدای خودکار CREMA.

ایجاد حساب‌های کاربری سرویس

ایجاد حساب کاربری مصرف‌کننده‌ی استخر کارگر:

gcloud iam service-accounts create $CONSUMER_SA_NAME \
  --display-name="PubSub Consumer Service Account"

ایجاد استخر کارگران CREMA service SA:

gcloud iam service-accounts create $CREMA_SA_NAME \
  --display-name="CREMA Autoscaler Service Account"

اعطای مجوز به Consumer SA

به حساب کاربری مصرف‌کننده‌ی مخزن کارگر (Worker Pool Consumer SA) مجوز دریافت پیام‌ها از اشتراک را اعطا کنید.

gcloud pubsub subscriptions add-iam-policy-binding $SUBSCRIPTION_ID \
  --member="serviceAccount:$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/pubsub.subscriber"

اعطای مجوز به CREMA SA

CREMA برای خواندن پارامترها، مقیاس‌بندی مجموعه کارگران و نظارت بر معیارهای Pub/Sub به مجوزهایی نیاز دارد.

  1. مدیریت پارامترهای دسترسی (خواننده پیکربندی):
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/parametermanager.parameterViewer"
  1. مقیاس‌پذیری Worker Pool (توسعه‌دهنده Cloud Run):
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/run.developer"
  1. مانیتور Pub/Sub:

نقش ناظر (Monitor) را اعطا کنید.

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/monitoring.viewer"

برای مشاهده، یک سیاست به اشتراک سرویس CREMA SA اضافه کنید

gcloud pubsub subscriptions add-iam-policy-binding $SUBSCRIPTION_ID \
  --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/pubsub.viewer"

CREMA SA همچنین به کاربر حساب کاربری سرویس نیاز دارد که برای تغییر تعداد نمونه‌ها لازم است:

gcloud iam service-accounts add-iam-policy-binding \
    $CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
    --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/iam.serviceAccountUser"

۵. مجوزهای SA را تأیید کنید

قبل از ادامه‌ی کار با codelab، مطمئن شوید که SA سرویس CREMA نقش‌های صحیح در سطح پروژه را دارد.

gcloud projects get-iam-policy $PROJECT_ID \
  --flatten="bindings[].members" \
  --format="table(bindings.role)" \
  --filter="bindings.members:serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com"

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

roles/monitoring.viewer
roles/parametermanager.parameterViewer
roles/run.developer

تأیید کنید که اشتراک Pub/Sub دارای سیاستی است که به سرویس CREMA SA اجازه مشاهده آن را می‌دهد.

gcloud pubsub subscriptions get-iam-policy $SUBSCRIPTION_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --format="table(bindings.role)"

باید منجر به

roles/pubsub.viewer

و تأیید کنید که CREMA SA نقش کاربر حساب کاربری سرویس را دارد

gcloud iam service-accounts get-iam-policy \
  $CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com"

باید منجر به موارد زیر شود

bindings:
  members: serviceAccount:crema-service-account@<PROJECT_ID>.iam.gserviceaccount.com
  role: roles/iam.serviceAccountUser

و Worker Pool Consumer SA نقش مشترک Pub/Sub را دارد.

gcloud pubsub subscriptions get-iam-policy $SUBSCRIPTION_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --format="table(bindings.role)"

باید منجر به

ROLE
roles/pubsub.subscriber

۶. ساخت و استقرار مخزن کارگران مصرف‌کننده

یک دایرکتوری برای کد مصرف‌کننده خود ایجاد کنید و آن را وارد کنید.

mkdir consumer
cd consumer
  1. یک فایل consumer.py ایجاد کنید
import os
import time
from google.cloud import pubsub_v1
from concurrent.futures import TimeoutError

# Configuration
PROJECT_ID = os.environ.get('PROJECT_ID')
SUBSCRIPTION_ID = os.environ.get('SUBSCRIPTION_ID')

subscription_path = f"projects/{PROJECT_ID}/subscriptions/{SUBSCRIPTION_ID}"

print(f"Worker Pool instance starting. Watching {subscription_path}...")

subscriber = pubsub_v1.SubscriberClient()

def callback(message):
    try:
        data = message.data.decode("utf-8")
        print(f"Processing job: {data}")
        time.sleep(5)  # Simulate work
        print(f"Done {data}")
        message.ack()
    except Exception as e:
        print(f"Error processing message: {e}")
        message.nack()

streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
print(f"Listening for messages on {subscription_path}...")

# Wrap subscriber in a 'with' block to automatically call close() when done.
with subscriber:
    try:
        # When `timeout` is not set, result() will block indefinitely,
        # unless an exception is encountered first.
        streaming_pull_future.result()
    except TimeoutError:
        streaming_pull_future.cancel()  # Trigger the shutdown.
        streaming_pull_future.result()  # Block until the shutdown is complete.
    except Exception as e:
        print(f"Streaming pull failed: {e}")
  1. ایجاد یک Dockerfile
FROM python:3.12-slim
RUN pip install google-cloud-pubsub
COPY consumer.py .
CMD ["python", "-u", "consumer.py"]
  1. استقرار استخر کارگران مصرف‌کننده

این آزمایشگاه کد توصیه می‌کند که برای شروع، worker pool را با 0 نمونه راه‌اندازی کنید، بنابراین می‌توانید ببینید که CREMA هنگام شناسایی پیام‌های Pub/Sub در اشتراک، worker pool را مقیاس‌بندی می‌کند.

gcloud beta run worker-pools deploy $CONSUMER_WORKER_POOL_NAME \
  --source . \
  --region $REGION \
  --service-account="$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --instances=0 \
  --set-env-vars PROJECT_ID=$PROJECT_ID,SUBSCRIPTION_ID=$SUBSCRIPTION_ID

۷. پیکربندی CREMA

  1. به دایرکتوری ریشه پروژه خود برگردید.
cd ..
  1. ایجاد فایل پیکربندی (Config File) فایلی با نام crema-config.yaml ایجاد کنید.
apiVersion: crema/v1
kind: CremaConfig
spec:
  pollingInterval: 30
  triggerAuthentications:
    - metadata:
        name: adc-trigger-auth
      spec:
        podIdentity:
          provider: gcp
  scaledObjects:
    - spec:
        scaleTargetRef:
          name: projects/PROJECT_ID_PLACEHOLDER/locations/REGION_PLACEHOLDER/workerpools/CONSUMER_WORKER_POOL_NAME_PLACEHOLDER
        triggers:
          - type: gcp-pubsub
            metadata:
              subscriptionName: "SUBSCRIPTION_ID_PLACEHOLDER"
              # Target number of undelivered messages per worker instance
              value: "10"
              mode: "SubscriptionSize"
            authenticationRef:
              name: adc-trigger-auth
  1. متغیرهای جایگزین
sed -i "s/PROJECT_ID_PLACEHOLDER/$PROJECT_ID/g" crema-config.yaml
sed -i "s/REGION_PLACEHOLDER/$REGION/g" crema-config.yaml
sed -i "s/CONSUMER_WORKER_POOL_NAME_PLACEHOLDER/$CONSUMER_WORKER_POOL_NAME/g" crema-config.yaml
sed -i "s/SUBSCRIPTION_ID_PLACEHOLDER/$SUBSCRIPTION_ID/g" crema-config.yaml
  1. تأیید کنید که crema-config.yaml شما صحیح است
if grep -q "_PLACEHOLDER" crema-config.yaml; then
  echo "❌ ERROR: Validations failed. '_PLACEHOLDER' was found in crema-config.yaml."
  echo "Please check your environment variables and run the 'sed' commands again."
else
  echo "✅ Config check passed: No placeholders found."
fi
  1. آپلود در مدیریت پارامترها

متغیرهای محیطی اضافی را برای Parameter Manager تنظیم کنید

export PARAMETER_ID=crema-config
export PARAMETER_REGION=global
export PARAMETER_VERSION=1

ایجاد منبع پارامتر

gcloud parametermanager parameters create $PARAMETER_ID \
  --location=$PARAMETER_REGION \
  --parameter-format=YAML

ایجاد پارامتر نسخه ۱

gcloud parametermanager parameters versions create $PARAMETER_VERSION \
  --parameter=crema-config \
  --project=$PROJECT_ID \
  --location=$PARAMETER_REGION \
  --payload-data-from-file=crema-config.yaml

تأیید کنید که پارامتر با موفقیت اضافه شده است

gcloud parametermanager parameters versions list \
  --parameter=$PARAMETER_ID \
  --location=$PARAMETER_REGION

شما باید چیزی شبیه به این ببینید

projects/<YOUR_PROJECT_ID>/locations/global/parameters/crema-config/versions/1

۸. سرویس CREMA را راه‌اندازی کنید

در این بخش، سرویس مقیاس‌بندی خودکار CREMA را مستقر خواهید کرد. از ایمیجی که به صورت عمومی در دسترس است استفاده خواهید کرد.

  1. متغیرهای محیطی مورد نیاز برای CREMA را تنظیم کنید
CREMA_CONFIG_PARAM_VERSION=projects/$PROJECT_ID/locations/$PARAMETER_REGION/parameters/$PARAMETER_ID/versions/$PARAMETER_VERSION
  1. مسیر نام نسخه را تأیید کنید
echo $CREMA_CONFIG_PARAM_VERSION

باید شبیه باشه

projects/<YOUR_PROJECT>/locations/global/parameters/crema-config/versions/1
  1. متغیر env را برای تصویر CREMA تنظیم کنید
IMAGE=us-central1-docker.pkg.dev/cloud-run-oss-images/crema-v1/autoscaler:1.0
  1. و سرویس CREMA را مستقر کنید

توجه داشته باشید که تصویر پایه مورد نیاز است.

gcloud beta run deploy $CREMA_SERVICE_NAME \
  --image=$IMAGE \
  --region=${REGION} \
  --service-account="${CREMA_SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
  --no-allow-unauthenticated \
  --no-cpu-throttling \
  --labels=created-by=crema \
  --base-image=us-central1-docker.pkg.dev/serverless-runtimes/google-24/runtimes/java25 \
  --set-env-vars="CREMA_CONFIG=${CREMA_CONFIG_PARAM_VERSION},OUTPUT_SCALER_METRICS=True,ENABLE_CLOUD_LOGGING=True"

۹. تست بار

  1. اسکریپتی بسازید که پیام‌ها را در موضوع Pub/Sub منتشر کند.
touch load-pubsub.sh
  1. کد زیر را به فایل load-pubsub.sh اضافه کنید.
#!/bin/bash
TOPIC_ID=${TOPIC_ID} 
PROJECT_ID=${PROJECT_ID}
NUM_MESSAGES=100

echo "Publishing $NUM_MESSAGES messages to topic $TOPIC_ID..."

for i in $(seq 1 $NUM_MESSAGES); do
  gcloud pubsub topics publish $TOPIC_ID --message="job-$i" --project=$PROJECT_ID &
  if (( $i % 10 == 0 )); then
    wait
    echo "Published $i messages..."
  fi
done
wait
echo "Done. All messages published."
  1. اجرای تست بارگذاری
chmod +x load-pubsub.sh
./load-pubsub.sh
  1. مقیاس‌بندی مانیتور ۳-۴ دقیقه صبر کنید. لاگ‌های CREMA را مشاهده کنید تا ببینید که بر اساس پیکربندی جدید authenticationRef، نمونه‌هایی را پیشنهاد می‌دهد.
gcloud logging read "resource.type=cloud_run_revision AND resource.labels.service_name=$CREMA_SERVICE_NAME AND textPayload:SCALER" \
  --limit=20 \
  --format="value(textPayload)" \
  --freshness=5m
  1. پردازش را مانیتور کنید. لاگ‌های مصرف‌کنندگان را مشاهده کنید تا ببینید که چگونه در حال چرخش هستند.
gcloud beta run worker-pools logs tail $CONSUMER_WORKER_POOL_NAME --region=$REGION

شما باید لاگ‌هایی مانند این را ببینید

Done job-100

۱۰. عیب‌یابی

ابتدا باید مشخص کنید که آیا مشکل از پیکربندی سرویس CREMA است یا از پیکربندی مصرف‌کننده PubSub.

مقیاس‌بندی خودکار مصرف‌کننده‌ی PubSub را به جای ۰، روی ۱ تنظیم کنید. اگر بلافاصله شروع به پردازش پیام‌های pubsub کرد، مشکل از CREMA است. اگر پیام‌های pubsub را پردازش نکرد، مشکل از مصرف‌کننده‌ی pubsub است.

۱۱. تبریک می‌گویم!

تبریک می‌گویم که آزمایشگاه کد را تمام کردید!

توصیه می‌کنیم مستندات Cloud Run را بررسی کنید.

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

  • نحوه ایجاد یک موضوع انتشار/زیرمجموعه و اشتراک و ارسال پیام به آن موضوع.
  • نحوه استقرار یک مخزن کارگر (مصرف‌کننده) Cloud Run که پیام‌های Pub/Sub را مصرف می‌کند.
  • نحوه استقرار پروژه CREMA در GitHub به عنوان یک سرویس Cloud Run برای مقیاس‌بندی خودکار مجموعه کارگران شما بر اساس تعداد پیام‌های موجود در اشتراک Pub/Sub.
  • چگونه پیکربندی مقیاس‌پذیری خودکار خود را با ایجاد بار با اجرای یک اسکریپت پایتون به صورت محلی آزمایش کنید.

۱۲. تمیز کردن

برای جلوگیری از تحمیل هزینه به حساب گوگل کلود خود برای منابع استفاده شده در این آموزش، می‌توانید منابعی را که در این آزمایشگاه کد ایجاد کرده‌اید حذف کنید یا می‌توانید کل پروژه را حذف کنید.

منابع استفاده شده در این آزمایشگاه کد را حذف کنید

  1. سرویس Cloud Run CREMA را حذف کنید
gcloud run services delete $CREMA_SERVICE_NAME --region=$REGION --quiet
  1. مصرف‌کننده‌ی استخر کارگر Cloud Run را حذف کنید
gcloud beta run worker-pools delete $CONSUMER_WORKER_POOL_NAME --region=$REGION --quiet
  1. اشتراک Pub/Sub و موضوع را حذف کنید
gcloud pubsub subscriptions delete $SUBSCRIPTION_ID --quiet
gcloud pubsub topics delete $TOPIC_ID --quiet
  1. پیکربندی مدیریت پارامتر را حذف کنید

نسخه داخل پارامتر را حذف کنید

gcloud parametermanager parameters versions delete $PARAMETER_VERSION \
  --parameter=$PARAMETER_ID \
  --location=$PARAMETER_REGION \
  --quiet

حالا پارامتر خالی را حذف کنید

gcloud parametermanager parameters delete $PARAMETER_ID \
  --location=$PARAMETER_REGION \
  --quiet
  1. حساب‌های سرویس را حذف کنید
gcloud iam service-accounts delete "$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" --quiet
gcloud iam service-accounts delete "$CONSUMER_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" --quiet

یا کل پروژه را حذف کنید

برای حذف کل پروژه، به مدیریت منابع بروید، پروژه‌ای را که در مرحله ۲ ایجاد کرده‌اید انتخاب کنید و حذف را انتخاب کنید. اگر پروژه را حذف کنید، باید پروژه‌ها را در Cloud SDK خود تغییر دهید. می‌توانید با اجرای gcloud projects list لیست تمام پروژه‌های موجود را مشاهده کنید.