1. Введение



Eventarc упрощает подключение сервисов Cloud Run к событиям из различных источников. Он позволяет создавать архитектуры, управляемые событиями, в которых микросервисы слабо связаны и распределены. Eventarc берет на себя обработку событий, их доставку, безопасность, авторизацию и обработку ошибок.
Workflows — это полностью управляемая платформа оркестровки, которая выполняет сервисы в порядке, заданном вами: рабочий процесс. Эти рабочие процессы могут объединять сервисы, размещенные на Cloud Run или Cloud Functions, сервисы Google Cloud, такие как Cloud Vision AI и BigQuery, а также любые API на основе HTTP.
В этом практическом занятии вы создадите событийно-ориентированную оркестровку микросервисов для обработки изображений. Вы будете использовать рабочие процессы (Workflows) для организации порядка, входных и выходных данных 4 облачных функций обработки изображений. Затем вы настроите оркестровку для реагирования на события облачного хранилища в слабосвязанном режиме с помощью Eventarc.
В итоге вы получите гибкую, но структурированную бессерверную архитектуру для обработки изображений.

Что вы узнаете
- Обзор Eventarc и рабочих процессов.
- Как развернуть сервисы Cloud Functions
- Как организовать работу сервисов с помощью рабочих процессов.
- Как настроить рабочие процессы на реагирование на события облачного хранилища с помощью Eventarc
2. Настройка и требования
Настройка среды для самостоятельного обучения
- Войдите в консоль Google Cloud и создайте новый проект или используйте существующий. Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .



- Название проекта — это отображаемое имя участников данного проекта. Это строка символов, не используемая API Google. Вы всегда можете его изменить.
- Идентификатор проекта уникален для всех проектов Google Cloud и является неизменяемым (его нельзя изменить после установки). Консоль Cloud автоматически генерирует уникальную строку; обычно вам неважно, какая она. В большинстве практических заданий вам потребуется указать идентификатор вашего проекта (обычно обозначается как
PROJECT_ID). Если сгенерированный идентификатор вас не устраивает, вы можете сгенерировать другой случайный идентификатор. В качестве альтернативы вы можете попробовать свой собственный и посмотреть, доступен ли он. После этого шага его нельзя изменить, и он сохраняется на протяжении всего проекта. - К вашему сведению, существует третье значение — номер проекта , которое используется некоторыми API. Подробнее обо всех трех значениях можно узнать в документации .
- Далее вам потребуется включить оплату в консоли Cloud для использования ресурсов/API Cloud. Выполнение этого практического задания не потребует больших затрат, если вообще потребует. Чтобы отключить ресурсы и избежать дополнительных расходов после завершения этого урока, вы можете удалить созданные ресурсы или удалить проект. Новые пользователи Google Cloud имеют право на бесплатную пробную версию стоимостью 300 долларов США .
Запустить Cloud Shell
Хотя Google Cloud можно управлять удаленно с ноутбука, в этом практическом занятии вы будете использовать Google Cloud Shell — среду командной строки, работающую в облаке.
В консоли Google Cloud нажмите на значок Cloud Shell на панели инструментов в правом верхнем углу:

Подготовка и подключение к среде займут всего несколько минут. После завершения вы должны увидеть что-то подобное:

Эта виртуальная машина содержит все необходимые инструменты разработки. Она предоставляет постоянный домашний каталог объемом 5 ГБ и работает в облаке Google, что значительно повышает производительность сети и аутентификацию. Вся работа в этом практическом задании может выполняться в браузере. Вам не нужно ничего устанавливать.
Настройте gcloud
В Cloud Shell укажите идентификатор проекта и регион, в который вы хотите развернуть приложение. Сохраните их как переменные PROJECT_ID и REGION . Список доступных регионов см. в разделе «Расположения Cloud Functions» .
PROJECT_ID=your-project-id gcloud config set project $PROJECT_ID
Получите исходный код
Исходный код приложения находится в папке processing-pipelines репозитория eventarc-samples .
Клонируйте репозиторий:
git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git
Перейдите в папку eventarc-samples/processing-pipelines :
cd eventarc-samples/processing-pipelines
3. Обзор архитектуры
Архитектура приложения выглядит следующим образом:

- Изображение сохраняется во входной сегмент, что приводит к генерации события создания в Cloud Storage.
- Событие создания объекта Cloud Storage считывается Eventarc через триггер Cloud Storage и передается в рабочие процессы в виде объекта CloudEvent.
- На первом этапе рабочего процесса сервис облачных функций Filter использует API Vision для определения безопасности изображения. Если изображение безопасно, рабочий процесс переходит к следующим шагам.
- На втором этапе рабочего процесса сервис облачных функций Labeler извлекает метки изображения с помощью Vision API и сохраняет их в выходной буфер.
- На третьем этапе Resizer , еще один сервис облачных функций, изменяет размер изображения с помощью ImageSharp и сохраняет измененное изображение в выходной буфер.
- На последнем этапе сервис облачных функций Watermarker добавляет к измененному размеру изображению водяной знак из меток, полученных с помощью Labeler, используя ImageSharp, и сохраняет изображение в выходной буфер.
Приложение запускается событием из облачного хранилища, поэтому оно является событийно-ориентированным. Обработка изображений происходит в рамках рабочего процесса, поэтому это оркестровка. В конечном итоге, это событийно-ориентированная оркестровка для гибкой, но структурированной бессерверной архитектуры для обработки изображений.
4. Создайте корзины.
Создайте входной сегмент для загрузки изображений пользователями и выходной сегмент для сохранения обработанных изображений в конвейере обработки изображений.
Выполните следующие действия в Cloud Shell:
REGION=us-central1 BUCKET1=$PROJECT_ID-images-input-$RANDOM BUCKET2=$PROJECT_ID-images-output-$RANDOM gsutil mb -l $REGION gs://$BUCKET1 gsutil mb -l $REGION gs://$BUCKET2
5. Разверните службу фильтра.
Начнём с развертывания первого сервиса. Этот сервис Cloud Functions получает информацию о корзине и файле, определяет, является ли изображение безопасным, с помощью Vision API и возвращает результат.
Во-первых, включите необходимые сервисы для Cloud Functions gen2 и Vision API:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ run.googleapis.com \ vision.googleapis.com
Внутри корневой папки processing-pipelines разверните службу:
SERVICE_NAME=filter gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --entry-point Filter.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v3/filter/csharp
После развертывания функции задайте URL-адрес сервиса в переменной, он понадобится нам позже:
FILTER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
6. Разверните службу маркировки.
Вторая служба Cloud Functions получает информацию о сегменте и файле, извлекает метки изображения с помощью Vision API и сохраняет метки в выходной сегмент.
Внутри корневой папки processing-pipelines разверните службу:
SERVICE_NAME=labeler gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Labeler.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/labeler/csharp
После развертывания функции задайте URL-адрес сервиса в переменной, он понадобится нам позже:
LABELER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
7. Разверните службу изменения размера.
Этот сервис Cloud Functions получает информацию о хранилище и файле, изменяет размер изображения с помощью ImageSharp и сохраняет изображение в выходное хранилище.
Внутри корневой папки processing-pipelines разверните службу:
SERVICE_NAME=resizer gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Resizer.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/resizer/csharp \ --timeout=120s
Обратите внимание на значение timeout в 2 минуты, которое дает функции изменения размера дополнительное время для обработки.
После развертывания функции задайте URL-адрес сервиса в переменной, он понадобится нам позже:
RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
8. Разверните службу водяных знаков.
Этот сервис Cloud Functions получает информацию о корзине, файле и метках, считывает файл, добавляет метки в качестве водяного знака к изображению с помощью ImageSharp и сохраняет изображение в выходную корзину.
Внутри корневой папки processing-pipelines разверните службу:
SERVICE_NAME=watermarker gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Watermarker.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/watermarker/csharp
После развертывания функции задайте URL-адрес сервиса в переменной, он понадобится нам позже:
WATERMARKER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
На данном этапе все четыре облачные функции должны быть развернуты и работать:

9. Определите и разверните рабочий процесс.
Используйте рабочие процессы, чтобы объединить сервисы фильтрации, разметки, изменения размера и добавления водяных знаков в один рабочий процесс. Рабочие процессы будут организовывать вызов этих сервисов в том порядке и с параметрами, которые мы определим.
Во-первых, включите необходимые службы для рабочих процессов:
gcloud services enable \ workflows.googleapis.com \ workflowexecutions.googleapis.com
Определять
Workflows получает в качестве параметра объект CloudEvent. Этот объект будет получен из Eventarc после создания триггера. На первых двух шагах Workflows регистрирует событие и извлекает из него информацию о корзине и файле:
main:
params: [event]
steps:
- log_event:
call: sys.log
args:
text: ${event}
severity: INFO
- extract_bucket_and_file:
assign:
- bucket: ${event.data.bucket}
- file: ${event.data.name}
На этапе filter Workflows обращается к службе фильтрации, развернутой ранее. Затем она регистрирует данные и проверяет безопасность файла:
- filter:
call: http.post
args:
url: FILTER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: filterResponse
- log_safety:
call: sys.log
args:
text: ${filterResponse.body.safe}
severity: INFO
- check_safety:
switch:
- condition: ${filterResponse.body.safe == true}
next: label
next: end
На этапе label Workflows обращается к службе добавления меток и получает ответ (три верхние метки):
- label:
call: http.post
args:
url: LABELER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: labelResponse
На этапе resize Workflows обращается к службе изменения размера и получает ответ (корзину и файл изображения измененного размера):
- resize:
call: http.post
args:
url: RESIZER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${bucket}
file: ${file}
result: resizeResponse
На этапе watermark рабочие процессы вызывают службу нанесения водяных знаков, используя измененное изображение и метки, и получают результат (измененное изображение с водяным знаком):
- watermark:
call: http.post
args:
url: WATERMARKER_URL # TODO: Replace
auth:
type: OIDC
body:
bucket: ${resizeResponse.body.bucket}
file: ${resizeResponse.body.file}
labels: ${labelResponse.body.labels}
result: watermarkResponse
На final этапе Workflows возвращает код состояния HTTP от служб разметки, изменения размера и водяных знаков:
- final:
return:
label: ${labelResponse.code}
resize: ${resizeResponse.code}
watermark: ${watermarkResponse.code}
Развертывать
Перед развертыванием рабочего процесса убедитесь, что URL-адреса служб заменены URL-адресами развернутых функций либо вручную, либо с помощью sed :
Внутри корневой папки processing-pipelines перейдите в папку image-v3 , где находится файл workflows.yaml :
cd image-v3/
Запустите команду sed , чтобы заменить URL-адреса-заполнители фактическими URL-адресами развернутых служб:
sed -i -e "s|FILTER_URL|${FILTER_URL}|" workflow.yaml
sed -i -e "s|LABELER_URL|${LABELER_URL}|" workflow.yaml
sed -i -e "s|RESIZER_URL|${RESIZER_URL}|" workflow.yaml
sed -i -e "s|WATERMARKER_URL|${WATERMARKER_URL}|" workflow.yaml
Разверните рабочий процесс:
WORKFLOW_NAME=image-processing
gcloud workflows deploy $WORKFLOW_NAME \
--source=workflow.yaml \
--location=$REGION
Через несколько секунд вы увидите развернутый рабочий процесс в консоли:

10. Создайте триггер
Теперь, когда рабочий процесс развернут, последний шаг — подключить его к событиям Cloud Storage с помощью триггера Eventarc.
Одноразовая настройка
Сначала включите необходимые службы для Eventarc:
gcloud services enable \ eventarc.googleapis.com
Создайте учетную запись службы, которую вы будете использовать в триггере Eventarc.
SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Eventarc trigger image processing service account"
Предоставьте учетной записи службы роль workflows.invoker , чтобы она могла вызывать рабочие процессы из Eventarc:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/workflows.invoker \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
Предоставьте учетной записи службы роль eventarc.eventReceiver , чтобы ее можно было использовать в
Триггер облачного хранилища:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/eventarc.eventReceiver \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
Предоставьте учетной записи службы Cloud Storage роль pubsub.publisher . Это необходимо для работы триггера Cloud Storage в Eventarc:
STORAGE_SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_ID)"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member serviceAccount:$STORAGE_SERVICE_ACCOUNT \
--role roles/pubsub.publisher
Создавать
Выполните следующие действия, чтобы создать триггер. Этот триггер будет фильтровать события создания новых файлов из входного сегмента Cloud Storage и передавать их в рабочий процесс, который мы определили ранее:
TRIGGER_NAME=trigger-image-processing gcloud eventarc triggers create $TRIGGER_NAME \ --location=$REGION \ --destination-workflow=$WORKFLOW_NAME \ --destination-workflow-location=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET1" \ --service-account=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
В разделе Eventarc консоли Cloud Console вы можете убедиться, что триггер создан и готов к работе:

11. Протестируйте конвейер.
Конвейер обработки изображений готов к приему событий из облачного хранилища. Для тестирования конвейера загрузите изображение во входной сегмент:
gsutil cp beach.jpg gs://$BUCKET1
Как только вы загрузите изображение, вы должны увидеть сообщение о выполнении рабочего процесса в активном состоянии:

Примерно через минуту вы увидите сообщение об успешном завершении выполнения. Также вы сможете увидеть входные и выходные данные рабочего процесса:

Если вы выведете содержимое выходного хранилища, вы увидите уменьшенное изображение, уменьшенное изображение с водяным знаком и подписи к изображению:
gsutil ls gs://$BUCKET2 gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400-watermark.jpeg gs://$PROJECT_ID-images-output-$RANDOM/beach-400x400.png gs://$PROJECT_ID-images-output-$RANDOM/beach-labels.txt
Для перепроверки вы можете открыть уменьшенное изображение с водяным знаком, чтобы увидеть результат:

12. Поздравляем!
Поздравляем, вы завершили практическое занятие!
Что мы рассмотрели
- Обзор Eventarc и рабочих процессов.
- Как развернуть сервисы Cloud Functions
- Как организовать работу сервисов с помощью рабочих процессов.
- Как настроить рабочие процессы на реагирование на события облачного хранилища с помощью Eventarc