Google Cloud addebita la maggior parte delle spese cloud ai progetti. Ma a quale progetto?
La risposta è semplice per un servizio basato su Resource come Google Compute Engine: l'addebito viene assegnato al progetto che contiene la Resource, ad esempio una VM.
Quando invece si chiama un'API per un servizio Google Cloud come Vision, Translate o BigQuery, il modello di fatturazione è più flessibile. Una parte o la totalità degli addebiti è legata a un progetto "Client" che si specifica, consentendo di attribuire i costi a diverse business unit o progetti.
In questo blog post vedremo:
- Cosa significa progetto "Client" e come specificarlo.
- I principali pattern per associare la fatturazione a un progetto, nei diversi tipi di servizi.
- Perché la documentazione Google parla quasi sempre di "quota project" quando si discute di fatturazione, e che relazione ha con il "billing project".
- Come scoprire, per una determinata chiamata API, a quale progetto è stata addebitata.
- Come superare le difficoltà nell'attribuzione dei costi alle categorie di business.
Come impostare il progetto Quota/Billing
Quando una chiamata API raggiunge l'infrastruttura Google Cloud, viene valutata la seguente gerarchia per determinare il progetto Client che, per i servizi non basati su Resource, viene utilizzato anche per la fatturazione. (I concetti di "quota project" e "billing project" sono illustrati più avanti.)
- La valutazione viene effettuata dal Service Infrastructure/Service Control di Google, che garantisce un comportamento uniforme tra i servizi gestiti da Google.
- Permessi: per poter specificare un progetto come Client, il principal che effettua la chiamata — un Service Account, un utente, una Workforce Identity Federation o una Workload Identity Federation — deve disporre del ruolo Service Usage Consumer in quel progetto. (È irrilevante che il Service Account sia definito in quel progetto o in un altro.)
- Questo vale per i servizi di Google Cloud Platform, ma non necessariamente per altri servizi Google come Workspace o Maps.
- Il progetto Client si specifica con le seguenti tecniche, in questo ordine di precedenza.
Come specificare il Client
1. Specificato nella richiesta
- HTTP Header: l'header HTTP
X-goog-user-projectpuò essere passato direttamente nella richiesta. Utile nelle chiamate REST raw, ad esempio con curl. - Configurazione della Client Library: il progetto impostato tramite client options nei Google Cloud SDK. Di seguito un esempio con la Python Google Cloud Client library.
from google.cloud import translate_v3from google.api_core.client_options import ClientOptions# 1. Define the billing projectoptions = ClientOptions(quota_project_id="your-billing-project-id")# 2. Inject it when creating the clientclient = translate_v3.TranslationServiceClient(client_options=options)2. Variabile d'ambiente
Il valore della variabile d'ambiente GOOGLE_CLOUD_QUOTA_PROJECT. Definirla è una best practice per impostare dinamicamente il quota project in ambienti containerizzati, senza doverlo scrivere hardcoded tramite ClientOptions.
3. API Key
Il progetto in cui è stata generata l'API Key utilizzata per la chiamata.
4. ADC Quota Project
Per l'ambiente locale (di norma in sviluppo) si imposta con gcloud auth application-default set-quota-project.
La trappola dello sviluppo locale: Se si esegue
gcloud auth application-default loginsenza impostare un progetto Client per quota e fatturazione, gli script locali autenticheranno la maggior parte delle API tramite un progetto speciale e limitato (il "Cloud SDK project"764086051850). Essendo condiviso a livello globale, l'utilizzo è fortemente limitato e gli errori"Quota exceeded for project 764086051850"compaiono quasi subito. Si può evitare impostando il valore Client.
5. Token di autenticazione
- Service Account: il progetto proprietario del Service Account che effettua la richiesta (inclusi i Service Account impersonati).
- OAuth Client ID: il progetto proprietario dell'OAuth 2.0 Client ID utilizzato per generare il token dell'utente finale.
6. Workforce Identity Federation
Se il principal dell'API è un utente Workforce Identity Federation, viene utilizzato il workforce pools user project.
Perché Google parla di "Quota project" e non di "Billing project"?
La documentazione e i parametri di Google Cloud usano quasi sempre il termine "quota project", mentre "billing project" compare di rado.
Ci sono però delle eccezioni. Ad esempio, la documentazione di gcloud usa, in modo poco chiaro, entrambi i termini fianco a fianco, pur trattandosi dello stesso parametro: billing/quota_project per la configurazione persistente dello strumento e --billing-project per il flag della command-line.
La spiegazione è questa. In tutto Google Cloud le impostazioni Client fanno una sola cosa a livello di infrastruttura: definiscono il progetto quota utilizzato dall'API gateway, mentre la fatturazione viene attribuita al progetto della Resource. Per i servizi non basati su Resource, però, il sistema di fatturazione non trova alcuna Resource lato server da addebitare e quindi, per default, fattura sul quota project.
Servizi basati su Resource vs. servizi non basati su Resource
La differenza principale è tra i servizi fatturati per Resource e quelli senza Resource. Partiamo da un riepilogo:
| Tipo di servizio | Driver di fatturazione principale | Driver di quota principale | Esempi |
|---|---|---|---|
| Basato su Resource | Progetto che contiene la resource | Progetto Client | Compute Engine, Spanner, Cloud Run |
| Basato su Client | Progetto Client (Quota) | Progetto Client | Vision API, Translate API |
API basate su Resource: progetto lato server identificabile.
Sono le API di infrastruttura, storage e compute di Google. Sono stateful: chiamandole, si chiede a Google di leggere, modificare o eliminare un asset o dei dati specifici che risiedono in un progetto. Il billing project è quello in cui si trova la Resource, di solito specificato nell'URL. Il quota project, al contrario, è determinato dall'impostazione Client.
Esistono alcuni casi particolari, come Cloud Storage, Pub/Sub e BigQuery, illustrati di seguito.
Alcuni esempi:
- Compute Engine API: gestione di virtual machine, dischi e reti.
GET https://compute.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instances - Cloud Spanner API: interrogazione o gestione di database relazionali.
POST https://spanner.googleapis.com/v1/projects/{project}/instances/{instance}/databases/{database}/sessions - Cloud Run è "serverless", ma il responsabile del servizio Cloud Run è l'utente, non Google: per questo ha una fatturazione basata su Resource. L'URL del servizio Cloud Run non contiene un progetto e non si trova sul dominio
googleapis.com.
Quota e fatturazione basate su Client: nessuna Resource lato server
Per le API stateless, che sono semplicemente un algoritmo condiviso a livello globale, non esiste alcuna Resource in alcun progetto e nessun server compare nell'URL REST. In questi casi la fatturazione è determinata dall'impostazione Client.
Alcuni esempi:
- Cloud Natural Language API: si passa un paragrafo e l'API restituisce un'analisi del sentiment.
POST https://language.googleapis.com/v1/documents:analyzeSentiment - Cloud Video Intelligence API: si passa un video e l'API restituisce le label degli oggetti al suo interno.
POST https://videointelligence.googleapis.com/v1/videos:annotate
Cloud Storage: l'opzione Requester Pays
Cloud Storage è un servizio basato su Resource project, anche se nell'URL non compare un project ID, come in: GET https://storage.googleapis.com/storage/v1/b/{bucket}/o/{object}
Ha comunque un progetto lato server, individuato dall'API gateway in base al nome del bucket.
Come per le altre API basate su Resource, la fatturazione viene assegnata al progetto del bucket, mentre la quota è assegnata al Client specificato.
Questo comportamento può però essere modificato tramite l'opzione "Requester Pays", esclusiva di Cloud Storage. Quando il proprietario del bucket abilita Requester Pays, chi invoca l'API deve fornire un progetto fatturabile (tramite le impostazioni Client menzionate sopra), e tale progetto viene addebitato per l'egress e le operazioni API (lo storage continua invece a essere a carico del proprietario del bucket).
BigQuery: due tipi di Resource separati
BigQuery è atipico, perché storage e compute possono risiedere in progetti diversi.
- Lo storage viene addebitato al progetto proprietario della Resource: il dataset con i dati memorizzati.
- L'elaborazione delle query viene addebitata al progetto in cui viene eseguito il job di query. Anche se un job è una forma di compute, viene trattato come una Resource a sé stante e stateful. Viene addebitato al proprio progetto, che può differire sia da quello dello storage sia da quello in cui il job viene avviato.
Pub/Sub: Topic e Subscription possono trovarsi in progetti diversi
Come per gli altri servizi basati su Resource, in Pub/Sub i costi sono legati alla proprietà della Resource, indipendentemente da chi effettua la chiamata API, e le impostazioni Client servono solo a calcolare le quote.
Pub/Sub è però atipico perché le Resource stesse possono essere distribuite tra più progetti:
- Il Topic è la Resource che determina la fatturazione per la pubblicazione dei messaggi.
- Una subscription Pub/Sub è una Resource a sé stante, che può essere creata in un progetto diverso da quello del Topic o del Client che effettua la chiamata. Determina la fatturazione per il throughput di delivery, il trasferimento dati (egress) e lo storage a livello di subscription.
Come individuare il progetto addebitato per una chiamata di servizio
Vediamo alcuni modi per individuare il progetto addebitato per una determinata chiamata. Nei log delle API Google Cloud non esiste un campo standard "billed_project", ma in genere il dato è ricavabile.
Prerequisito: per tracciare le chiamate API è necessario abilitare prima i Data Access Audit logs per l'API specifica (es. Cloud Storage, BigQuery) nel progetto che si sospetta venga addebitato. Lo si fa dalla console Google Cloud, in IAM & Admin -> Audit Logs.
Per i servizi Google Cloud in generale
Filtri i log per il servizio di interesse:
logName=~"cloudaudit.googleapis.com"protoPayload.serviceName="[SERVICE_NAME].googleapis.com"E, in via opzionale, per metodo, ad esempio:
logName=~"cloudaudit.googleapis.com/data_access"protoPayload.serviceName="vision.googleapis.com"protoPayload.methodName="google.cloud.vision.v1.ImageAnnotator.AnnotateImage"Individui il campo resource.labels.project_id all'interno della voce di log. Questo campo identifica il progetto addebitato, sia esso quello basato su Resource o quello basato su Client. (L'eccezione sono i bucket Cloud Storage Requester Pays.) L'informazione resta visibile anche quando si visualizza un mix di dati di progetto attraverso un Log Sink multi-progetto.
Per i Compute Job di BigQuery
Poiché BigQuery separa il compute dallo storage, occorre esaminare in modo specifico i log di esecuzione del compute, e non quelli dello storage. Esegua questa query in Logs Explorer e, come per gli altri servizi Google, individui il campo resource.labels.project_id.
resource.type="bigquery_project"protoPayload.methodName=("google.cloud.bigquery.v2.JobService.InsertJob" OR "google.cloud.bigquery.v2.JobService.Query")protoPayload.metadata."@type"="type.googleapis.com/google.cloud.audit.BigQueryAuditMetadata"Per GCS Requester Pays
Nei bucket Cloud Storage Requester Pays, gli audit log mostrano il numero del progetto addebitato (in esadecimale) sotto protoPayload.authorizationInfo.resource, dopo "projects/", ad esempio come "projects/0000004d9813b13".
La soluzione per l'attribuzione dei costi
Una volta capito come far emergere questi log di fatturazione, la sfida successiva è collegarli al business: ad esempio a specifici reparti o progetti aziendali.
Il mio compito come Cloud Architect in DoiT International è affiancare i clienti nell'ottimizzazione dei costi, e DoiT mette a disposizione una suite di strumenti potenti all'interno di DoiT Cloud Intelligence per raggiungere questo obiettivo. Ad esempio, DoiT Cost Allocation raggruppa e attribuisce i costi per dimensione di business.
Alcuni servizi supportano label che facilitano l'attribuzione dei costi:
- Per i servizi basati su Resource si può allocare per Resource, aggiungendo eventualmente label per farle corrispondere alle proprie categorie di business.
- In via eccezionale, le chiamate API a molti modelli di Generative AI possono ricevere label di costo personalizzate da utilizzare per l'attribuzione.
- Anche le pipeline di Vertex AI offrono una funzionalità di attribuzione dei costi piuttosto unica. La Pipeline in sé ha un costo contenuto, ma soprattutto può generare diversi tipi di risorse. Vertex AI applica automaticamente la label
vertex-ai-pipelines-run-billing-ida ciascuna Resource generata, agevolando l'attribuzione dei costi all'esecuzione complessiva della Pipeline.
Per la maggior parte dei servizi non basati su Resource, però, i dati di costo di GCP non riportano label per utente o altre informazioni che consentano di separare le categorie di business.
Una possibile soluzione: creare più progetti che facciano da Client. Le organizzazioni Google Cloud utilizzano abitualmente molti progetti, organizzati in cartelle. Questi progetti possono essere impostati come Client per allocare i costi alle categorie di business. Possono essere altrimenti vuoti e non è necessario eseguire il codice client all'interno del progetto di fatturazione: ciò che conta è il progetto Client indicato nella chiamata. In questo modo i progetti stessi diventano la "label" che identifica la business unit.