Автоматическое масштабирование пулов рабочих процессов Cloud Run на основе объема очереди Pub/Sub с использованием CREMA.

1. Введение

Обзор

В этом руководстве показано, как развернуть пул рабочих процессов Cloud Run (потребителей) для обработки сообщений Pub/Sub и автоматически масштабировать экземпляры потребителей в зависимости от глубины очереди с помощью функции автоматического масштабирования внешних метрик Cloud Run (CREMA) .

Что вы узнаете

В этом практическом занятии вы:

  • Создайте тему и подписку Pub/Sub и отправляйте сообщения в эту тему.
  • Разверните пул рабочих процессов Cloud Run (потребителей), который будет получать сообщения из Pub/Sub.
  • Разверните проект CREMA на GitHub в качестве сервиса Cloud Run, чтобы автоматически масштабировать пул рабочих процессов в зависимости от количества сообщений в подписке Pub/Sub.
  • Проверьте конфигурацию автомасштабирования, создав нагрузку с помощью локального скрипта Python.

2. Настройка переменных среды

Поскольку в этом практическом занятии используется множество переменных окружения, мы рекомендуем запустить...

set -u

Эта команда выдаст предупреждение, если вы попытаетесь использовать переменную окружения, которая еще не была установлена. Чтобы отменить эту настройку, выполните set +u

Сначала измените следующую переменную на идентификатор вашего проекта.

export PROJECT_ID=<YOUR_PROJECT_ID>

а затем установите его в качестве проекта для этой практической работы.

gcloud config set project $PROJECT_ID

Далее установите переменные среды, используемые в этом практическом задании.

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

Создайте директорию для этого практического занятия.

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

3. Настройка системы публикации/подписки

Создайте тему и подписку на получение данных, которые будет обрабатывать ваш пул рабочих процессов. Bash

Создайте тему.

gcloud pubsub topics create $TOPIC_ID

Создайте подписку.

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

4. IAM и служебные учетные записи

Рекомендуется создавать учетную запись службы для каждого ресурса Cloud Run. В этом практическом задании вы создадите следующие учетные записи:

  • Пользовательское соглашение SA: Идентификация пула рабочих, обрабатывающих сообщения Pub/Sub.
  • CREMA SA: Идентификатор для сервиса автоматического масштабирования CREMA.

Создание учетных записей служб

Создайте пользовательское соглашение SA для пула рабочих:

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

Создайте пул рабочих сотрудников службы CREMA SA:

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

Предоставить разрешения компании Consumer SA

Предоставьте пользователю 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. Масштабирование пула рабочих процессов (разработчик облачных решений):
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$CREMA_SA_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/run.developer"
  1. Мониторинг публикации/подписки:

Предоставьте пользователю, осуществляющему мониторинг, роль наблюдателя.

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"

5. Проверьте права доступа SA.

Перед началом выполнения практического задания убедитесь, что у сервиса CREMA SA имеются необходимые роли на уровне проекта.

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

6. Создание и развертывание пула работников-потребителей.

Создайте директорию для вашего кода потребителя и войдите в неё.

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. Развернуть пул потребительских работников

В этом практическом задании рекомендуется сначала развернуть пул рабочих процессов с нулевым количеством экземпляров, чтобы вы могли наблюдать за масштабированием пула рабочих процессов CREMA при обнаружении сообщений Pub/Sub в подписке.

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

7. Настройка CREMA

  1. Вернитесь в корневой каталог вашего проекта.
cd ..
  1. Создайте файл конфигурации. Создайте файл с именем 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. Загрузка в менеджер параметров

Установите дополнительные переменные среды для менеджера параметров.

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

Создать параметр версии 1

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

8. Развертывание сервиса 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. Установите переменную окружения для образа 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"

9. Испытание под нагрузкой

  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. Подождите 3-4 минуты, пока не завершится масштабирование мониторинга. Просмотрите журналы 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

10. Устранение неполадок

В первую очередь, вам нужно определить, связана ли проблема с конфигурацией службы CREMA или с конфигурацией потребителя PubSub.

Установите значение автомасштабирования потребителя PubSub равным 1 вместо 0. Если он немедленно начнет обрабатывать сообщения PubSub, это проблема с CREMA. Если он не обрабатывает сообщения PubSub, проблема в потребителе PubSub.

11. Поздравляем!

Поздравляем с завершением практического занятия!

Мы рекомендуем ознакомиться с документацией Cloud Run .

Что мы рассмотрели

  • Как создать тему Pub/Sub и подписку, а также отправлять сообщения в эту тему.
  • Как развернуть пул рабочих процессов Cloud Run (потребитель), который получает сообщения из Pub/Sub.
  • Как развернуть проект CREMA на GitHub в качестве сервиса Cloud Run для автоматического масштабирования пула рабочих процессов в зависимости от количества сообщений в подписке Pub/Sub.
  • Как проверить конфигурацию автомасштабирования, создав нагрузку с помощью локального скрипта Python.

12. Уборка

Чтобы избежать списания средств с вашего аккаунта Google Cloud за ресурсы, использованные в этом руководстве, вы можете либо удалить ресурсы, созданные в этом практическом задании, либо удалить весь проект.

Удалите ресурсы, использованные в этом практическом занятии.

  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

Или удалите весь проект.

Чтобы удалить весь проект, перейдите в раздел «Управление ресурсами» , выберите проект, созданный на шаге 2, и нажмите «Удалить». Если вы удалите проект, вам потребуется изменить проекты в вашем Cloud SDK. Вы можете просмотреть список всех доступных проектов, выполнив gcloud projects list .