Проекты и биллинг
Как устроена «коробка», в которую складывают ресурсы GCP, откуда берутся деньги на счёт и почему бюджет с оповещением не останавливает трату.
Проект (project) — основная единица изоляции в Google Cloud. Ресурсы, права доступа, квоты, включённые API и счёт — всё живёт внутри проекта. Ресурс не может существовать «просто в облаке», он всегда принадлежит какому-то проекту.
Зачем нужен проект
Проект — это одновременно четыре границы, и понимание этого экономит нервы:
- Граница доступа. Права (IAM) выдаются на проект: дали человеку роль Editor в проекте
shop-dev— вshop-prodон всё ещё никто. - Граница денег. Счёт разбивается по проектам, и это самый простой способ понять, куда ушли деньги.
- Граница квот. Лимиты (сколько vCPU можно поднять, сколько запросов в минуту слать) считаются на проект.
- Граница API. Каждый сервис нужно включить в конкретном проекте. Включили Compute Engine в одном — в соседнем он всё ещё выключен.
Практический вывод: не сваливайте всё в один проект. Классический минимум — три проекта: -dev, -staging, -prod. Тогда неудачный эксперимент физически не может уронить или обчистить прод.
У проекта три имени, и это важно
| Идентификатор | Пример | Свойства |
| Project name (имя) | Магазин — прод | Просто подпись для людей. Можно менять, можно повторяться. |
| Project ID | shop-prod-471203 | Глобально уникален на весь Google Cloud, задаётся один раз и навсегда. Именно его требуют CLI и API. |
| Project number | 759214883012 | Числовой ID, генерируется автоматически. Встречается в сообщениях об ошибках и в адресах сервисных аккаунтов. |
Project ID нельзя переименовать — только удалить проект и создать новый. Поэтому не называйте проект test-1, если он потом станет продом. Разумная схема: компания-система-среда, например codechick-api-prod.
# создать проект с явным ID
gcloud projects create codechick-api-dev --name="CodeChick API — dev"
# посмотреть свои проекты
gcloud projects list
# сделать проект активным для всех последующих команд
gcloud config set project codechick-api-dev
Результат:
PROJECT_ID NAME PROJECT_NUMBER
codechick-api-dev CodeChick API — dev 759214883012
codechick-api-prod CodeChick API — prod 412007765531
Иерархия: организация → папка → проект
Пока вы учитесь с личного Google-аккаунта, проекты просто лежат рядом, без родителя. Как только компания подключает Cloud Identity или Google Workspace, появляется корневой узел — организация (Organization), а между ней и проектами можно вставлять папки (Folders).
Organization: codechick.io
├── Folder: Платформа
│ ├── Project: codechick-api-dev
│ ├── Project: codechick-api-staging
│ └── Project: codechick-api-prod
└── Folder: Аналитика
└── Project: codechick-bigquery
Смысл иерархии — в наследовании. Права и организационные политики (Org Policies), выданные на папку, автоматически действуют на все проекты внутри. Дали команде платформы роль на папку «Платформа» — она получила доступ ко всем трём проектам сразу и ничего не увидела в аналитике. А политика вроде «запретить создание ключей сервисных аккаунтов», навешенная на организацию, действует везде и её нельзя обойти внутри отдельного проекта.
Биллинг-аккаунт — отдельная сущность
Новички часто думают, что «оплата привязана к проекту». На самом деле Cloud Billing Account — самостоятельный объект: у него своя карта (или договор), свои администраторы и свои права. Отношение простое: один биллинг-аккаунт оплачивает много проектов, но у проекта в каждый момент времени ровно один биллинг-аккаунт.
# какие биллинг-аккаунты мне доступны
gcloud billing accounts list
# привязать проект к биллинг-аккаунту
gcloud billing projects link codechick-api-dev \
--billing-account=01A2B3-C4D5E6-7F8G9H
# проверить, к чему привязан проект
gcloud billing projects describe codechick-api-dev
Проект без биллинга — «мёртвый»: почти любой сервис откажется работать с ошибкой вида The billing account for the owning project is disabled in state absent. Ровно поэтому многие тратят полдня на «загадочные» ошибки в свежесозданном проекте: он просто не привязан к деньгам.
Чтобы привязать проект, нужны права в двух местах сразу: роль на проекте (Project Owner или Billing-роль) и роль Billing Account User на самом биллинг-аккаунте. В компаниях биллингом обычно владеет финансовый отдел, и разработчику дают именно эту вторую роль.
Квоты: почему нельзя поднять сто машин
Квоты защищают и Google (от исчерпания мощностей и от ботнетов), и вас (от бесконечного счёта из-за бага в скрипте). Их два вида:
- Rate quotas — ограничение скорости: например, столько-то запросов к API в минуту. Сбрасываются автоматически; если упёрлись, увидите
429 RESOURCE_EXHAUSTED. - Allocation quotas — ограничение количества: сколько vCPU можно держать в регионе, сколько внешних IP, сколько ТБ дисков. Не сбрасываются — освобождаются, когда вы удаляете ресурсы.
Новый проект (особенно на пробном периоде) получает очень скромные лимиты: например, GPU в нём обычно ноль, а число vCPU в регионе измеряется единицами. Это нормально. Повышение запрашивается в консоли, в разделе IAM & Admin → Quotas: выбираете нужную квоту, указываете новое значение и обоснование. Мелкие повышения часто одобряются автоматически за минуты, крупные — за пару дней.
# посмотреть квоты Compute Engine по текущему проекту
gcloud compute project-info describe --format="table(quotas.metric,quotas.limit,quotas.usage)"
Как это работает: бюджеты, метки и экспорт счёта
Самое опасное заблуждение звучит так: «я поставил бюджет 10 $, значит больше не спишут». Это не так. Бюджет в GCP — это оповещение, а не предохранитель. При достижении 50%, 90%, 100% порога вам приходит письмо, но ресурсы продолжают работать и тратить деньги.
Настоящий «стоп-кран» строится вручную: бюджет отправляет сообщение в Pub/Sub, его подхватывает Cloud Function и вызывает API, отвязывающий биллинг от проекта. Звучит сурово — потому что это и есть суровая мера: отвязка биллинга останавливает всё в проекте. Для учебного аккаунта достаточно бюджета с алертами и привычки удалять созданное.
Понять, куда именно уходят деньги, помогают labels (метки вида env=dev, team=backend) — они попадают в детализацию счёта. А для серьёзного анализа биллинг экспортируют в BigQuery и считают затраты обычным SQL.
Прикинуть счёт можно и до его получения. Вот прямолинейная арифметика того, во что обходится «забытая» лаборатория (цены условные, для порядка величин):
hours = 730 # часов в среднем месяце
vm_hour = 0.034 # $/час за e2-medium
disk_gb, disk_price = 10, 0.04 # 10 ГБ по $0.04 за ГБ в месяц
ip_hour = 0.010 # $/час за неиспользуемый статический IP
vm = vm_hour * hours
disk = disk_gb * disk_price
ip = ip_hour * hours
total = vm + disk + ip
print(f"Виртуальная машина e2-medium: {vm:7.2f} $")
print(f"Диск 10 ГБ (даже когда VM выключена): {disk:7.2f} $")
print(f"Статический IP, ни к чему не привязанный: {ip:7.2f} $")
print(f"ИТОГО за месяц: {total:7.2f} $")
print(f"Забыли на 3 месяца: {total * 3:.2f} $")
Результат:
Виртуальная машина e2-medium: 24.82 $
Диск 10 ГБ (даже когда VM выключена): 0.40 $
Статический IP, ни к чему не привязанный: 7.30 $
ИТОГО за месяц: 32.52 $
Забыли на 3 месяца: 97.56 $
Сто долларов за машину, которую вы включили «на посмотреть» и забыли, — это не страшилка, а самый распространённый сценарий в учебных аккаунтах.
И ещё одна приятная деталь про удаление: проект не исчезает мгновенно. Он переходит в состояние pending deletion и лежит там около 30 дней — за это время его можно восстановить командой gcloud projects undelete. А чтобы важный проект нельзя было снести случайно, на него вешают lien (замок):
gcloud resource-manager liens create \
--project=codechick-api-prod \
--restrictions=resourcemanager.projects.delete \
--reason="Продакшен: удаление только через тимлида"
Частые ошибки
- Бюджет считают предохранителем. Он только шлёт письма. Без Pub/Sub и функции-выключателя трата не остановится.
- Один проект на всё. Дев, прод и эксперименты в одной коробке — значит, общий IAM, общие квоты и общий счёт, в котором ничего не разобрать.
- Плохой project ID. Его нельзя изменить.
my-project-12345из туториала имеет привычку доживать до продакшена. - Забыли привязать биллинг и полдня ищут причину странных ошибок в свежем проекте.
- Просят у поддержки квоту, вместо того чтобы навести порядок. Часто «кончились vCPU» означает не малую квоту, а десяток забытых машин.
- Удалили проект и думают, что деньги перестали течь. Пока проект в pending deletion, часть ресурсов может ещё дотарифицироваться; и наоборот — «удалил случайно» лечится
undelete, но только в течение месяца. - Дают роль Owner всем подряд. Owner в проекте с биллингом — это право потратить любые деньги. Начинающим хватает Editor, а чаще — точечных ролей.
Итоги
- Проект — контейнер для ресурсов и одновременно граница прав, квот, включённых API и счёта.
- Из трёх имён проекта в командах и API используется project ID; он глобально уникален и не меняется.
- Иерархия организация → папка → проект даёт наследование прав и политик; у личного аккаунта организации просто нет.
- Биллинг-аккаунт — отдельный объект: один платит за много проектов, у проекта он один. Без привязки проект почти не работает.
- Квоты бывают на скорость (rate) и на количество (allocation); повышаются запросом из консоли.
- Бюджет = оповещение, а не стоп-кран. Реальная защита — привычка удалять ресурсы, метки для разбора счёта и, при желании, автоматическая отвязка биллинга.