Введение в бессерверную оркестровку с помощью рабочих процессов

1. Введение

c9b0cc839df0bb8f.png

С помощью Workflows можно создавать бессерверные рабочие процессы, которые связывают ряд бессерверных задач в заданном вами порядке. Вы можете объединить возможности API Google Cloud, бессерверных продуктов, таких как Cloud Functions и Cloud Run, и вызовов внешних API для создания гибких бессерверных приложений.

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

В этом практическом занятии вы узнаете, как связать различные сервисы Google Cloud и внешние HTTP API с помощью рабочих процессов. В частности, вы подключите два общедоступных сервиса Cloud Functions, один частный сервис Cloud Run и внешний общедоступный HTTP API к рабочему процессу.

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

  • Основы рабочих процессов.
  • Как связать общедоступные облачные функции с рабочими процессами.
  • Как подключить частные облачные сервисы Cloud Run к рабочим процессам.
  • Как подключить внешние HTTP API к рабочим процессам.

2. Настройка и требования

Настройка среды для самостоятельного обучения

  1. Войдите в Cloud Console и создайте новый проект или используйте существующий. (Если у вас еще нет учетной записи Gmail или G Suite, вам необходимо ее создать .)

H_hgylo4zxOllHaAbPKJ7VyqCKPDUnDhkr-BsBIFBsrB6TYSisg6LX-uqmMhh4sXUy_hoa2Qv87C2nFmkg-QAcCiZZp0qtpf6VPaNEEfP_iqt29KVLD-gklBWugQVeOWsFnJmNjHDw

dcCPqfBIwNO4R-0fNQLUC4aYXOOZhKhjUnakFLZJGeziw2ikOxGjGkCHDwN5x5kCbPFB8 fiOzZnX-GfuzQ8Ox-UU15BwHirkVPR_0RJwl0oXrhqZmMIvZMa_uwHugBJIdx5-bZ6Z8Q

jgLzVCxk93d6E2bbonzATKA4jFZReoQ-fORxZZLEi5C3D-ubnv6nL-eP-iyh7qAsWyq_nyzzuEoPFD1wFOFZOe4FWhPBJjUDncnTxTImT3Ts9TM54f4nPpsAp52O0y3Cb19IceAEgQ

Запомните идентификатор проекта (Project ID) — уникальное имя для всех проектов Google Cloud (указанное выше имя уже занято и вам не подойдёт, извините!). В дальнейшем в этом практическом занятии оно будет обозначаться как PROJECT_ID .

  1. Далее вам потребуется включить оплату в Cloud Console, чтобы использовать ресурсы Google Cloud.

Выполнение этого практического задания не должно стоить дорого, если вообще что-либо. Обязательно следуйте инструкциям в разделе «Очистка», где указано, как отключить ресурсы, чтобы избежать дополнительных расходов после завершения этого урока. Новые пользователи Google Cloud имеют право на бесплатную пробную версию стоимостью 300 долларов США .

Запустить Cloud Shell

Хотя Google Cloud можно управлять удаленно с ноутбука, в этом практическом занятии вы будете использовать Google Cloud Shell — среду командной строки, работающую в облаке.

В консоли GCP щелкните значок Cloud Shell на панели инструментов в правом верхнем углу:

STgwiN06Y0s_gL7i9bTed8duc9tWOIaFw0z_4QOjc-jeOmuH2TBK8l4udei56CKPLoM_i1yEF6pn5Ga88eniJQoEh8cAiTH79gWUHJdKOw0oiBZfBpOdcEOl6p29i4mvPe_A6UMJBQ

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

r6WRHJDzL-GdB5VDxMWa67_cQxRR_x_xCG5xdt9Nilfuwe9fTGAwM9XSZbNPWvDSFtrZ7 DDecKqR5_pIq2IJJ9puAMkC3Kt4JbN9jfMX3gAwTNHNqFmqOJ-3iIX5HSePO4dNVZUkNA

Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Она предоставляет постоянный домашний каталог размером 5 ГБ и работает в облаке Google, что значительно повышает производительность сети и аутентификацию. Всю работу в этой лаборатории можно выполнять с помощью обычного браузера.

3. Обзор рабочих процессов

Основы

Рабочий процесс состоит из ряда шагов, описанных с использованием синтаксиса Workflows на основе YAML. Это определение рабочего процесса. Подробное объяснение синтаксиса Workflows YAML см. на странице справочника по синтаксису .

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

Включить службы

В этом практическом занятии вы будете подключать сервисы Cloud Functions и Cloud Run к рабочим процессам. Вы также будете использовать Cloud Build и Cloud Storage при создании сервисов.

Включите все необходимые службы:

gcloud services enable \
  cloudfunctions.googleapis.com \
  run.googleapis.com \
  workflows.googleapis.com \
  cloudbuild.googleapis.com \
  storage.googleapis.com

На следующем шаге вы объедините две облачные функции в единый рабочий процесс.

4. Разверните первую облачную функцию.

Первая функция — это генератор случайных чисел на языке Python.

Создайте директорию и перейдите в неё, чтобы сохранить код функции:

mkdir ~/randomgen
cd ~/randomgen

Создайте в указанной директории файл main.py со следующим содержимым:

import random, json
from flask import jsonify

def randomgen(request):
    randomNum = random.randint(1,100)
    output = {"random":randomNum}
    return jsonify(output)

При получении HTTP-запроса эта функция генерирует случайное число от 1 до 100 и возвращает его вызывающей стороне в формате JSON.

Эта функция использует Flask для обработки HTTP-запросов, и нам необходимо добавить его в качестве зависимости. В Python зависимости управляются с помощью pip и описываются в файле метаданных под названием requirements.txt .

Создайте в той же директории файл requirements.txt со следующим содержимым:

flask>=1.0.2

Разверните функцию с HTTP-триггером и разрешите неаутентифицированные запросы с помощью этой команды:

gcloud functions deploy randomgen \
    --runtime python312 \
    --trigger-http \
    --allow-unauthenticated

После развертывания функции вы можете увидеть ее URL-адрес в свойстве url , отображаемом в консоли или с помощью команды gcloud functions describe .

Вы также можете перейти по указанному URL-адресу функции с помощью следующей команды curl :

curl $(gcloud functions describe randomgen --format='value(url)')

Функция готова к использованию в рабочем процессе.

5. Развертывание второй облачной функции.

Вторая функция — это умножитель. Он умножает полученный входной сигнал на 2.

Создайте директорию и перейдите в неё, чтобы сохранить код функции:

mkdir ~/multiply
cd ~/multiply

Создайте в указанной директории файл main.py со следующим содержимым:

import random, json
from flask import jsonify

def multiply(request):
    request_json = request.get_json()
    output = {"multiplied":2*request_json['input']}
    return jsonify(output)

При получении HTTP-запроса эта функция извлекает input из тела JSON-запроса, умножает их на 2 и возвращает результат в формате JSON вызывающей стороне.

Создайте аналогичный файл requirements.txt в той же директории со следующим содержимым:

flask>=1.0.2

Разверните функцию с HTTP-триггером и разрешите неаутентифицированные запросы с помощью этой команды:

gcloud functions deploy multiply \
    --runtime python312 \
    --trigger-http \
    --allow-unauthenticated

После развертывания функции вы также можете перейти по указанному URL-адресу функции с помощью следующей команды curl :

curl $(gcloud functions describe multiply --format='value(url)') \
-X POST \
-H "content-type: application/json" \
-d '{"input": 5}'

Функция готова к использованию в рабочем процессе.

6. Соедините две облачные функции.

В первом варианте выполнения задачи соедините две функции.

Создайте файл workflow.yaml со следующим содержимым.

- randomgenFunction:
    call: http.get
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/randomgen
    result: randomgenResult
- multiplyFunction:
    call: http.post
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/multiply
        body:
            input: ${randomgenResult.body.random}
    result: multiplyResult
- returnResult:
    return: ${multiplyResult}

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

Разверните первый рабочий процесс:

gcloud workflows deploy workflow --source=workflow.yaml

Выполните первый рабочий процесс:

gcloud workflows execute workflow

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

gcloud workflows executions describe <your-execution-id> --workflow workflow

В выходных данных будут указаны result и state :

result: '{"body":{"multiplied":108},"code":200 ... } 

...
state: SUCCEEDED

7. Подключите внешний HTTP API.

Далее вы подключите math.js в качестве внешнего сервиса в рабочем процессе.

В math.js можно вычислять математические выражения следующим образом:

curl https://api.mathjs.org/v4/?'expr=log(56)'

На этот раз вы воспользуетесь Cloud Console для обновления нашего рабочего процесса. Найдите Workflows в Google Cloud Console:

7608a7991b33bbb0.png

Найдите свой рабочий процесс и перейдите на вкладку Definition :

f3c8c4d3ffa49b1b.png

Отредактируйте определение рабочего процесса и добавьте вызов math.js

- randomgenFunction:
    call: http.get
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/randomgen
    result: randomgenResult
- multiplyFunction:
    call: http.post
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/multiply
        body:
            input: ${randomgenResult.body.random}
    result: multiplyResult
- logFunction:
    call: http.get
    args:
        url: https://api.mathjs.org/v4/
        query:
            expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
    result: logResult
- returnResult:
    return: ${logResult}

Теперь в процессе работы результат функции умножения передается в вызов функции логирования в файле math.js

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

b40c76ee43a1ce65.png

Обратите внимание на код состояния 200 и body с выводом функции логирования.

Вы только что интегрировали внешний сервис в наш рабочий процесс, это просто здорово!

8. Разверните сервис Cloud Run.

В заключительной части завершите рабочий процесс вызовом частного сервиса Cloud Run. Это означает, что для вызова сервиса Cloud Run необходимо пройти аутентификацию.

Сервис Cloud Run возвращает результат math.floor для переданного числа.

Создайте директорию с кодом сервиса и перейдите в неё:

mkdir ~/floor
cd ~/floor

Создайте в указанной директории файл app.py со следующим содержимым:

import json
import logging
import os
import math

from flask import Flask, request

app = Flask(__name__)

@app.route('/', methods=['POST'])
def handle_post():
    content = json.loads(request.data)
    input = float(content['input'])
    return f"{math.floor(input)}", 200

if __name__ != '__main__':
    # Redirect Flask logs to Gunicorn logs
    gunicorn_logger = logging.getLogger('gunicorn.error')
    app.logger.handlers = gunicorn_logger.handlers
    app.logger.setLevel(gunicorn_logger.level)
    app.logger.info('Service started...')
else:
    app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

Cloud Run развертывает контейнеры, поэтому вам нужен Dockerfile , и ваш контейнер должен быть привязан к переменной окружения 0.0.0.0 и PORT , отсюда и приведенный выше код.

При получении HTTP-запроса эта функция извлекает input из тела JSON-запроса, вызывает метод math.floor и возвращает результат вызывающей стороне.

В той же директории создайте следующий Dockerfile :

# Use an official lightweight Python image.
# https://hub.docker.com/_/python
FROM python:3.7-slim

# Install production dependencies.
RUN pip install Flask gunicorn

# Copy local code to the container image.
WORKDIR /app
COPY . .

# Run the web service on container startup. Here we use the gunicorn
# webserver, with one worker process and 8 threads.
# For environments with multiple CPU cores, increase the number of workers
# to be equal to the cores available.
CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app

Создайте контейнер:

export SERVICE_NAME=floor
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

После сборки контейнера разверните его в Cloud Run. Обратите внимание на флаг no-allow-unauthenticated . Он гарантирует, что сервис будет принимать только аутентифицированные вызовы:

gcloud run deploy ${SERVICE_NAME} \
  --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
  --platform managed \
  --no-allow-unauthenticated

После развертывания сервис готов к работе.

9. Подключите сервис Cloud Run.

Прежде чем настраивать рабочие процессы для вызова частной службы Cloud Run, необходимо создать учетную запись службы, которую будут использовать рабочие процессы:

export SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT}

Предоставьте учетной записи службы роль run.invoker . Это позволит учетной записи службы вызывать аутентифицированные службы Cloud Run:

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
    --member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
    --role "roles/run.invoker"

Обновите определение рабочего процесса в workflow.yaml , добавив службу Cloud Run. Обратите внимание, что вы также включаете поле auth , чтобы убедиться, что рабочие процессы передают токен аутентификации в своих вызовах к службе Cloud Run:

- randomgenFunction:
    call: http.get
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/randomgen
    result: randomgenResult
- multiplyFunction:
    call: http.post
    args:
        url: https://<region>-<project-id>.cloudfunctions.net/multiply
        body:
            input: ${randomgenResult.body.random}
    result: multiplyResult
- logFunction:
    call: http.get
    args:
        url: https://api.mathjs.org/v4/
        query:
            expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"}
    result: logResult
- floorFunction:
    call: http.post
    args:
        url: https://floor-<random-hash>.run.app
        auth:
            type: OIDC
        body:
            input: ${logResult.body}
    result: floorResult
- returnResult:
    return: ${floorResult}

Обновите рабочий процесс. На этот раз передав учетную запись службы:

gcloud workflows deploy workflow \
    --source=workflow.yaml \
    --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com

Выполните рабочий процесс:

gcloud workflows execute workflow

Через несколько секунд вы сможете взглянуть на выполнение рабочего процесса и увидеть результат:

gcloud workflows executions describe <your-execution-id> --workflow workflow

В результате будет получено целочисленное result и state :

result: '{"body":"5","code":200 ... } 

...
state: SUCCEEDED

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

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

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

  • Основы рабочих процессов.
  • Как связать общедоступные облачные функции с рабочими процессами.
  • Как подключить частные облачные сервисы Cloud Run к рабочим процессам.
  • Как подключить внешние HTTP API к рабочим процессам.