Один и тот же backend в GCP можно запустить несколькими способами — от «дайте голую виртуальную машину, дальше я сам» до «вот функция, вызывайте её на событие». Выбор влияет на то, сколько эксплуатации ляжет на вас и сколько вы заплатите. Разберём варианты и как выбирать. Сеть и доступ, на которых всё стоит, — в основах GCP.

Cloud Run functions код на событие Cloud Run контейнер масштабируется до нуля GKE узлы ваши, управляющая часть у Google Compute Engine ОС, софт и обновления ваши

Снизу вверх растёт то, что берёт на себя Google, и убывает свобода. Выбор по умолчанию стоит посередине: обычный веб-сервис или API это Cloud Run, а кластер и машины берут, когда есть причина, которую можно записать.

Обязательно

Compute Engine

Нужно перенести сервис «как есть», с его systemd-юнитом и cron, или поставить то, что в контейнер не заворачивается. Compute Engine — виртуальные машины: вы получаете сервер с операционной системой и делаете с ним что хотите. Аналог EC2 в AWS.

Максимум контроля и максимум ответственности: вы сами ставите софт, накатываете обновления, настраиваете автозапуск, следите за диском. Облако отвечает только за «железо» под машиной.

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

Откуда облако берёт образ: Artifact Registry

«Отдал контейнер» — фраза, которая пропускает обязательный шаг: образ должен где-то лежать, и облако должно иметь право его скачать. В GCP это Artifact Registry — реестр в вашем проекте, по репозиторию на регион (он заменил более старый Container Registry, и в новых проектах берут именно его).

Путь от кода до работающего сервиса целиком:

# один раз: репозиторий и разрешение на вход
gcloud artifacts repositories create app --repository-format=docker --location=europe-west4
gcloud auth configure-docker europe-west4-docker.pkg.dev

# каждый раз: собрать, опубликовать, развернуть
docker build -t europe-west4-docker.pkg.dev/acme-prod/app/orders:1.4.2 .
docker push europe-west4-docker.pkg.dev/acme-prod/app/orders:1.4.2
gcloud run deploy orders --image europe-west4-docker.pkg.dev/acme-prod/app/orders:1.4.2 \
  --region europe-west4

Четыре вещи, которые полезно знать сразу. Права на скачивание образа выдаются служебной учётной записи сервиса или узлов кластера — то есть никаких секретов реестра в развёртывании не нужно. Реестр умеет хранить не только образы, но и пакеты (сборки, библиотеки), и это одно место вместо трёх. Сканирование на уязвимости включается на репозиторий одной настройкой. И реестр надо чистить правилами очистки: образ на каждый коммит через год превращается в заметную строку в счёте.

Отдельно стоит упомянуть, что публиковать образ руками обычно не приходится: сборка в облаке (Cloud Build) делает это сама, а gcloud run deploy --source . собирает образ из исходников, публикует его в реестр и разворачивает — одной командой, о которой ниже.

Google Kubernetes Engine (GKE)

Сервисов стало два десятка, у каждого свой выкат и свои реплики, и руками это уже не удержать. GKE — это Kubernetes, у которого управляющую часть (control plane) обслуживает Google, а вы работаете с рабочими узлами и деплоите контейнеры. Аналог EKS в AWS. Сам Kubernetes вырос внутри Google, и управляемый сервис здесь появился раньше, чем у конкурентов; в режиме Autopilot Google берёт на себя ещё и управление узлами.

Kubernetes берут, когда сервисов много и нужна оркестрация: автоперезапуск упавших контейнеров, раскатка без простоя, обнаружение сервисов, масштабирование по нагрузке. Для одного маленького сервиса это из пушки по воробьям. Общая механика кластера — в разделе Kubernetes.

У этого «из пушки по воробьям» есть конкретная цена. За управляющую часть Google берёт отдельную плату — 0,10 доллара в час за кластер, то есть около 72 долларов в месяц, и неважно, крутится в нём один под или триста. Бесплатных кредитов даётся ровно на один кластер: 74,40 доллара в месяц на биллинг-аккаунт, и только для зонального или Autopilot-кластера. Отсюда и совет «не берите GKE ради одного сервиса»: второй кластер начинает стоить денег ещё до того, как вы в него что-то положили.

Когда брать: несколько сервисов, команда знает Kubernetes, нужны единый выкат и переносимость.

Cloud Run

Сервис один, нагрузка приходит волнами, а платить за кластер ради него жалко. Cloud Run — золотая середина: вы упаковываете сервис в контейнер, а облако само запускает его по запросу и масштабирует, вплоть до нуля при отсутствии обращений. Кластер держать не нужно. От Lambda его отличает главное: один экземпляр Cloud Run обслуживает десятки запросов одновременно, а не один, поэтому пул соединений к базе и кэш в памяти здесь работают как в обычном сервисе, а стоит он при той же нагрузке дешевле. Отдал контейнер — получил работающий HTTP-сервис.

Когда брать: есть контейнер (или даже просто код — Cloud Run умеет собрать образ сам), поднимать ради него полноценный GKE не хочется, нагрузка неравномерная. Платите за фактическое потребление.

Две цифры, которые стоит знать заранее. Первая — сколько отводится на один запрос: по умолчанию 5 минут, поднять можно до 60. Вторая важнее: один экземпляр Cloud Run обслуживает несколько запросов одновременно — по умолчанию до 80, настраивается до 1000. Это главное отличие от AWS Lambda, где экземпляр занят ровно одним запросом. Следствий два. Код обязан быть потокобезопасным: внутри экземпляра запросы друг от друга никак не изолированы. И пул соединений к базе считается иначе — сотня экземпляров с пулом по десять соединений даёт базе тысячу подключений, а лимит у неё кончится раньше.

Чего не снимает: сервис должен быстро стартовать и переживать пересоздание (stateless).

Cloud Functions

Раз в час обработать файл в бакете или ответить на веб-хук — десять строк кода, ради которых заводить сервис смешно. Cloud Functions — код без сервера: вы загружаете функцию (на Java, Python, Node.js, Go и др.), а облако вызывает её на событие — HTTP-запрос, сообщение в Pub/Sub, файл в хранилище. Ниша та же, что у AWS Lambda.

Только не считайте Cloud Run и функции разными платформами: у функций два поколения, и второе разворачивается как обычный сервис Cloud Run. С 2024 года оно так и называется — Cloud Run functions, и ищут его в консоли не в отдельном разделе, а рядом с сервисами Cloud Run. Проще всего думать так: функция второго поколения — это тот же Cloud Run, у которого сборку контейнера и подписку на событие взяли на себя. Подробно — в статье про serverless.

Когда брать: небольшие событийные обработчики, нерегулярная нагрузка, желание платить строго за вызовы. Когда логика разрастается в полноценный сервис — сигнал переезжать в Cloud Run.

App Engine

Отдельно стоит App Engine — исторически первая PaaS-платформа Google для веб-приложений: отдаёте код, а Google держит веб-сервер, масштабирование и обновления. Сегодня для новых проектов чаще выбирают Cloud Run (гибче и на контейнерах), но App Engine всё ещё встречается.

Как выбрать

Простое правило по возрастанию контроля и эксплуатации:

  • Cloud Functions — событийная склейка, редкие или нерегулярные вызовы, минимум забот.
  • Cloud Run — есть контейнер или код, нужен HTTP-сервис без возни с кластером; в GCP это выбор по умолчанию для большинства сервисов.
  • GKE — много сервисов, нужна оркестрация и единый выкат, команда знает k8s.
  • Compute Engine — нужен полный контроль или перенос «как есть».

Частая ошибка новичка — начинать с GKE «потому что так делают все». Для одного-двух сервисов Cloud Run проще, дешевле и надёжнее.

Где это применяется

Выбор способа запуска — одно из первых архитектурных решений, и оно тянет за собой остальное. Куда бы ни поехал сервис, он опирается на сеть и доступ (привязанный сервисный аккаунт вместо ключей).

Дополнительно: при первом чтении можно пропустить

Глубже: Cloud Run не только про HTTP: задачирасширенное

Половина возможностей сервиса остаётся за кадром, если знать только про обработку запросов. У него два вида нагрузки:

Сервис (service) — то, о чём шла речь: контейнер, который слушает порт и обрабатывает запросы, масштабируется по нагрузке, умеет уходить в ноль.

Задача (job) — контейнер, который выполняется и завершается: миграция базы, ночная выгрузка, обработка файла, разовая операция. Никакого порта и никаких запросов, зато есть число попыток, параллельность и расписание.

gcloud run jobs create migrate --image $IMAGE --region europe-west4 \
  --task-timeout=10m --max-retries=1 --command=/app/migrate

gcloud run jobs execute migrate --region europe-west4 --wait

Чем это удобно: тот же образ, те же права служебной учётной записи, та же сеть — но для работы, у которой есть конец. Задачу можно запускать из конвейера (например, миграцию перед выкатом), по расписанию (планировщиком) или по событию.

Отсюда практический вывод: «нам нужна пакетная обработка, возьмём виртуальную машину» — часто лишний шаг. Если работа укладывается в образ контейнера и в предел времени задачи, её дешевле и проще запускать так.

Глубже: когда Cloud Run не подходитрасширенное

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

Долгие соединения и веб-сокеты. Они поддерживаются, но у запроса есть предельная длительность (настраивается, максимум порядка часа), и по её истечении соединение закрывается. Значит, клиент обязан переподключаться, а «висящее сутками соединение» невозможно по определению.

Фоновая работа после ответа. Это самая частая ловушка. По умолчанию процессор выделяется только во время обработки запроса: вы ответили клиенту, а поток, который продолжает что-то считать, притормаживается почти до остановки. Итог: задача, запущенная «в фоне» после ответа, выполняется минутами вместо секунд или не выполняется вовсе. Два выхода: включить постоянное выделение процессора (тогда платите и за простой) или вынести работу туда, где ей место — в очередь, в задачу, в отдельный сервис.

Локальный диск. Файловая система контейнера — в памяти, то есть запись большого файла на диск съедает память экземпляра и исчезает после его остановки. Всё, что надо сохранить, идёт в хранилище объектов.

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

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

Состояние в памяти между запросами. Экземпляр обрабатывает несколько запросов одновременно и живёт недолго; кэш в памяти допустим как ускорение, но не как хранилище.

Практическая формула: обычный веб-сервис или API — Cloud Run; всё остальное проверяем по списку выше. Если ни один пункт не мешает, дальше искать нечего.

Глубже: App Engine: когда братьрасширенное

У остальных вариантов в статье есть строка «когда брать», и стоит дать её и этому. Ответ короткий: новый сервис на App Engine обычно не начинают.

Причина не в том, что сервис плох — он работает и поддерживается. Причина в том, что его нишу занял Cloud Run: тот же принцип (отдал код, облако запускает и масштабирует), но с обычным образом контейнера вместо специфичной для платформы обвязки, с более гибкими настройками и без привязки к поддерживаемым средам исполнения.

Когда App Engine всё-таки уместен:

  • приложение уже на нём и работает — переезжать без причины смысла нет;
  • очень простой веб-сервис без контейнеров вовсе: загрузили код, получили адрес. Для прототипа или внутреннего инструмента это по-прежнему самый короткий путь;
  • нужны его специфичные возможности — встроенная очередь задач, встроенный планировщик, привычная команда развёртывания, — и переписывать их на отдельные сервисы не хочется.

Если ни один пункт не про вас, берите Cloud Run: у него ниже привязка к платформе (образ контейнера запускается где угодно) и больше возможностей настройки.

Глубже: как код попадает в облакорасширенное

«Как выбрать» отвечает на вопрос, куда, и оставляет без ответа вопрос, чем. Три способа, от простого к правильному.

Сборка и развёртывание одной командой. Cloud Run умеет взять исходники, собрать образ в облаке и развернуть его:

gcloud run deploy orders --source . --region europe-west4

Внутри произойдёт вот что: исходники уедут в облачную сборку, она соберёт образ (по вашему Dockerfile, а если его нет — сама определит вид проекта), опубликует его в реестр и развернёт. Локальный Docker для этого не нужен. Это самый быстрый способ увидеть работающий сервис, и для стендов его вполне достаточно.

Сборка в облаке по своему описанию (Cloud Build). Файл со шагами: собрать, прогнать тесты, опубликовать образ, развернуть. Это уже конвейер, только описанный в файле и выполняемый облаком:

steps:
  - name: gcr.io/cloud-builders/docker
    args: ['build', '-t', '$_IMAGE', '.']
  - name: gcr.io/cloud-builders/docker
    args: ['push', '$_IMAGE']
  - name: gcr.io/google.com/cloudsdktool/cloud-sdk
    args: ['gcloud', 'run', 'deploy', 'orders', '--image', '$_IMAGE', '--region', 'europe-west4']
substitutions:
  _IMAGE: europe-west4-docker.pkg.dev/$PROJECT_ID/app/orders:$SHORT_SHA

Запускается по событию из репозитория (триггер на ветвь или тег), и тег образа собирается из хеша коммита — то есть выполняется правило «один образ на всё», о котором статья про реестры.

Доставка по средам (Cloud Deploy). Отдельный сервис, который двигает один и тот же образ по средам: стенд, предпромышленная, промышленная — с подтверждениями между шагами, историей и откатом. Берут его, когда сред больше двух и нужен след «что и когда уехало в прод».

Что выбирают на практике: для пробы и для стенда — команда с исходниками; для рабочего проекта — сборка по описанию с триггером из репозитория; доставка по средам — когда появляется промышленный контур с подтверждением. И отдельный вариант, о котором стоит помнить: если у вас уже есть своя система сборки, ничего из этого брать не обязательно — достаточно опубликовать образ в реестр и вызвать развёртывание одной командой.

Коротко

  • Compute Engine это машина с полной свободой и полной ответственностью: софт, обновления, автозапуск и диск ваши; берут для переноса «как есть».
  • Образы живут в Artifact Registry, права на скачивание выдаются служебной учётной записи сервиса без секретов реестра, а публикует их обычно Cloud Build.
  • GKE обслуживает управляющую часть за 0,10 доллара в час на кластер, узлы и выкат ваши; для одного сервиса это из пушки по воробьям.
  • Cloud Run это выбор по умолчанию: контейнер или код, масштабирование до нуля, до 5 минут на запрос по умолчанию, несколько запросов на экземпляр; задачи Cloud Run закрывают миграции и разовую обработку тем же образом.
  • Cloud Run не подходит для долгих соединений без переподключения, фоновой работы после ответа без выделенного процессора, локального диска, фиксированного исходящего адреса без своей сети и особых требований к машине.
  • Cloud Functions второго поколения это Cloud Run functions; App Engine для новых сервисов не начинают, его нишу занял Cloud Run.
  • Порядок выбора по возрастанию контроля: функции, Cloud Run, GKE, Compute Engine; начинать с GKE «как все» для двух сервисов дорого.
  • Код попадает в облако командой с исходниками для пробы, сборкой по описанию Cloud Build с триггером из репозитория для рабочего проекта и Cloud Deploy для продвижения одного образа по средам.

Что почитать дальше