Начало работы с функциями Cloud Run

1. Введение

Обзор

Функции Cloud Run — это предложение Google Cloud «Функции как услуга», основанное на Cloud Run и Eventarc , которое дает вам более расширенный контроль над производительностью и масштабируемостью, а также больший контроль над временем выполнения функций и триггерами из более чем 90+ источников событий.

В этой лаборатории кода вы узнаете, как создать функции Cloud Run, которые отвечают на HTTP-вызовы и активируются сообщениями Pub/Sub и журналами облачного аудита.

В этой лаборатории кода также используются автоматические обновления базового образа для развертывания функций путем указания базового образа с помощью флага --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

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

Обратите внимание на следующее:

  • флаг --source используется, чтобы сообщить Cloud Run о необходимости создания функции в работоспособном сервисе на основе контейнера.
  • флаг --function (новый) используется для установки точки входа новой службы в качестве сигнатуры функции, которую вы хотите вызвать.
  • Флаг --base-image (новый) указывает среду базового образа для вашей функции, например nodejs22 , python312 , go123 , java21 , dotnet8 , ruby33 или php83 . Дополнительные сведения о базовых образах и пакетах, включенных в каждый образ, см. в разделе Базовые образы среды выполнения .
  • (необязательно) флаг --timeout позволяет функции иметь более длительный таймаут для ответа на HTTP-запросы. В этом примере 600 секунд используются для демонстрации 10-минутного времени ответа.
  • (необязательно) --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. Функция публикации/подписки

Для второй функции давайте создадим функцию Python, запускаемую сообщением Pub/Sub, опубликованным в определенной теме.

Настройка токенов аутентификации Pub/Sub

Если вы включили учетную запись службы 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.

Настраивать

Чтобы использовать функции Cloud Storage, предоставьте IAM-роль pubsub.publisher учетной записи службы 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 облачной консоли.

Теперь создайте триггер 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 поддерживают несколько версий ваших функций, разделяя трафик между разными версиями и откатывая вашу функцию до предыдущей версии.

На этом этапе вы развернете две версии функции, а затем разделите трафик между ними 50-50.

Создавать

Создайте папку для приложения и перейдите в нее:

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

Создайте файл main.py с функцией Python, которая считывает переменную среды цвета и возвращает ответ 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.
  • Как разделить трафик между двумя ревизиями.
  • Как избавиться от холодного запуска с минимальными затратами.