Один и тот же backend в GCP можно запустить несколькими способами — от «дайте голую виртуальную машину, дальше я сам» до «вот функция, вызывайте её на событие». Выбор влияет на то, сколько эксплуатации ляжет на вас и сколько вы заплатите. Разберём варианты и как выбирать. Сеть и доступ, на которых всё стоит, — в основах GCP.
Снизу вверх растёт то, что берёт на себя 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 для продвижения одного образа по средам.
Что почитать дальше
- Масштабирование и доступность в GCP — как из машин собрать устойчивую группу.
- Serverless в GCP — Cloud Run и функции подробно.
- Сеть в GCP — подсети и приватный доступ, к которым подключают сервис.
- Три уровня вычислений — машины, контейнеры и функции без привязки к провайдеру.