Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

¿Quién paga la cuenta? Cómo se asigna la facturación de APIs en Google Cloud

By Joshua FoxApr 30, 20269 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

Google Cloud factura la mayoría de los gastos de la nube a proyectos. Pero ¿a qué proyecto?

La respuesta es sencilla en un servicio basado en Recursos como Google Compute Engine: el cargo se asigna al proyecto que contiene el Recurso, por ejemplo una VM.

Ahora bien, cuando llamas a una API de un servicio de Google Cloud como Vision, Translate o BigQuery, el modelo de facturación es más flexible. Una parte o la totalidad de los cargos se asocia a un proyecto "Client" que tú especificas, lo que permite atribuir los costos a distintas unidades de negocio o proyectos.

En este artículo vas a ver:

  • Qué es el proyecto "Client" y cómo se especifica.
  • Los principales patrones para asociar la facturación a un proyecto, según el tipo de servicio.
  • Por qué la documentación de Google usa casi siempre la expresión "quota project" al hablar de facturación, y cómo se relaciona con el "billing project".
  • Cómo averiguar, para cualquier invocación de API, a qué proyecto se le facturó.
  • Cómo resolver los retos de atribuir costos a categorías de negocio.

Cómo definir el proyecto de cuota/facturación

Cuando una llamada a una API llega a la infraestructura de Google Cloud, se evalúa la siguiente jerarquía para determinar el proyecto Client, que en los servicios no basados en Recursos también se usa para la facturación. (Más abajo explico los conceptos de "quota project" vs "billing project".)

  • La evaluación la realiza el Service Infrastructure/Service Control de Google, que aporta un comportamiento unificado en los servicios gestionados por Google.
  • Permisos: para poder especificar un proyecto como Client, el principal que invoca —ya sea una Service Account, un usuario, o Workforce Identity Federation o Workload Identity Federation— debe tener el rol Service Usage Consumer en ese proyecto. (No importa si la Service Account está definida en ese proyecto o en otro.)
  • Esto se aplica a los servicios de Google Cloud Platform, pero no necesariamente a otros servicios de Google como Workspace o Maps.
  • Puedes especificar el proyecto Client con las siguientes técnicas, en este orden de precedencia.

Formas de especificar el Client

1. Especificado en la solicitud

  • Encabezado HTTP: el encabezado HTTP X-goog-user-project se puede pasar directamente en la solicitud. Útil en llamadas REST en crudo, por ejemplo con curl.
  • Configuración de la Client Library: el proyecto que se define mediante client options en los SDKs de Google Cloud. Aquí tienes un ejemplo con la Client library de Google Cloud para Python.
from google.cloud import translate_v3
from google.api_core.client_options import ClientOptions
# 1. Define the billing project
options = ClientOptions(quota_project_id="your-billing-project-id")
# 2. Inject it when creating the client
client = translate_v3.TranslationServiceClient(client_options=options)

2. Variable de entorno

El valor de la variable de entorno GOOGLE_CLOUD_QUOTA_PROJECT. Definir este valor es una buena práctica para configurar dinámicamente el quota project en entornos en contenedores, sin dejarlo fijo en el código mediante ClientOptions.

3. API Key

El proyecto en el que se generó la API Key utilizada para hacer la llamada.

4. ADC Quota Project

En el entorno local (normalmente en desarrollo), se define con gcloud auth application-default set-quota-project.

La trampa del desarrollo local: Si ejecutas gcloud auth application-default login sin definir un proyecto Client para cuota y facturación, tus scripts locales van a autenticarse contra la mayoría de las APIs usando un proyecto especial y limitado (el "Cloud SDK project" 764086051850). Como ese proyecto se comparte a nivel global, el uso está muy restringido y casi de inmediato aparecen errores de "Quota exceeded for project 764086051850". Esto se evita configurando el valor de Client.

5. Token de autenticación

  • Service Account: el proyecto al que pertenece la Service Account que hace la solicitud (incluidas las Service Accounts impersonadas).
  • OAuth Client ID: el proyecto al que pertenece el OAuth 2.0 Client ID utilizado para generar el token del usuario final.

6. Workforce Identity Federation

Si el principal de la API es un usuario de Workforce Identity Federation, se usa el user project del workforce pool.

¿Por qué Google habla de "Quota project" y no de "Billing project"?

La documentación y los parámetros de Google Cloud emplean casi siempre el término "quota project", mientras que "billing project" rara vez aparece.

Hay excepciones. Por ejemplo, la documentación de gcloud usa de forma confusa ambos términos en paralelo, aunque se trate del mismo parámetro: billing/quota_project para la configuración persistente de la herramienta y --billing-project para el flag de línea de comandos.

La explicación es esta. En todo Google Cloud, la configuración de Client hace una sola cosa a nivel de infraestructura: fija el proyecto de cuota que utiliza el API gateway, mientras que la facturación se dirige al proyecto del Recurso. Sin embargo, en los servicios no basados en Recursos, el sistema de facturación no encuentra un Recurso del lado del servidor al cual facturar, por lo que la facturación recae por defecto en el quota project.

Servicios basados en Recursos vs. no basados en Recursos

La diferencia principal está entre los servicios facturados por Recursos y los que no. Empecemos por un resumen:

Tipo de servicio Driver principal de facturación Driver principal de cuota Ejemplos
Basado en Recursos Proyecto que contiene el recurso Proyecto Client Compute Engine, Spanner, Cloud Run
Basado en Client Proyecto Client (Quota) Proyecto Client Vision API, Translate API

APIs basadas en Recursos: proyecto identificable del lado del servidor.

Son las APIs de infraestructura, almacenamiento y cómputo de Google. Son stateful. Cuando las llamas, le estás pidiendo a Google que lea, modifique o elimine un activo o un dato concreto que reside en un proyecto. El billing project es donde reside el Recurso, y suele especificarse en la URL. En cambio, el quota project se determina por la configuración de Client.

Hay algunos casos especiales como Cloud Storage, Pub/Sub y BigQuery, que se detallan más abajo.

Algunos ejemplos:

  • Compute Engine API: gestión de máquinas virtuales, discos y redes. GET https://compute.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instances
  • Cloud Spanner API: consulta o gestión de bases de datos relacionales. POST https://spanner.googleapis.com/v1/projects/{project}/instances/{instance}/databases/{database}/sessions
  • Cloud Run es "serverless", pero quien gestiona el servicio Cloud Run eres tú, no Google, así que la facturación se basa en Recursos. La URL del servicio Cloud Run no incluye proyecto y no está bajo el dominio googleapis.com.

Cuota y facturación basadas en Client: sin Recurso del lado del servidor

En las APIs stateless que son simplemente un algoritmo compartido a nivel global, no hay Recurso en ningún proyecto y tampoco aparece un servidor en la URL REST. En estos casos, la facturación se determina por la configuración de Client.

Algunos ejemplos:

  • Cloud Natural Language API: le pasas un párrafo y devuelve un análisis de sentimiento. POST https://language.googleapis.com/v1/documents:analyzeSentiment
  • Cloud Video Intelligence API: le pasas un video y devuelve etiquetas de los objetos que aparecen en él. POST https://videointelligence.googleapis.com/v1/videos:annotate

Cloud Storage: la opción Requester Pays

Cloud Storage es un servicio basado en Recursos, aunque no incluya un project ID en la URL con esta forma: GET https://storage.googleapis.com/storage/v1/b/{bucket}/o/{object}

Aun así, tiene un proyecto del lado del servidor, que el API gateway resuelve a partir del nombre del bucket.

Al igual que en otras APIs basadas en Recursos, la facturación se asigna al proyecto del bucket, mientras que la cuota se asigna al Client especificado.

Esto se puede modificar con la opción "Requester Pays", exclusiva de Cloud Storage. Cuando el dueño del bucket habilita Requester Pays, quien invoca la API debe indicar un proyecto facturable (mediante la configuración de Client mencionada arriba), y a ese proyecto se le facturan el egreso y las operaciones de la API (aunque el dueño del bucket sigue pagando el almacenamiento).

BigQuery: dos tipos de Recursos por separado

BigQuery es atípico porque el almacenamiento y el cómputo pueden vivir en proyectos diferentes.

  • El almacenamiento se factura al proyecto dueño del Recurso: el dataset con los datos almacenados.
  • El procesamiento de consultas se factura al proyecto donde se ejecuta el job de consulta. Aunque un job es un tipo de cómputo, se trata como un Recurso distinto y stateful. Se factura a su propio proyecto, que puede ser distinto tanto del proyecto de almacenamiento como del proyecto desde el que se inicia el job.

Pub/Sub: los Topics y las Subscriptions pueden estar en proyectos distintos

Como en otros servicios basados en Recursos, los costos de Pub/Sub están atados a la titularidad del Recurso, sin importar quién haga la llamada a la API, y la configuración de Client se utiliza solo para calcular las cuotas.

La particularidad de Pub/Sub es que los propios Recursos pueden estar repartidos entre proyectos:

  • El Topic es el Recurso que determina la facturación de la publicación de mensajes.
  • Una suscripción de Pub/Sub es un Recurso por sí misma, que puede crearse en un proyecto distinto del Topic o del Client que invoca. Esto determina la facturación del throughput de entrega, la transferencia de datos (egreso) y el almacenamiento a nivel de suscripción.

Cómo encontrar el proyecto facturado en una invocación de servicio

A continuación, algunas formas de identificar el proyecto al que se factura una invocación concreta. No existe un campo estándar "billed_project" dentro de un log de API de Google Cloud, pero por lo general el dato se puede obtener.

Requisito previo: para rastrear las llamadas a las APIs, primero debes habilitar los Data Access Audit logs de la API correspondiente (por ejemplo, Cloud Storage, BigQuery) en el proyecto que sospechas que se está facturando. Esto se hace en la consola de Google Cloud, en IAM & Admin -> Audit Logs.

Para servicios de Google Cloud en general

Filtra los logs por el servicio correspondiente:

logName=~"cloudaudit.googleapis.com"
protoPayload.serviceName="[SERVICE_NAME].googleapis.com"

Y, si quieres, también por método, por ejemplo

logName=~"cloudaudit.googleapis.com/data_access"
protoPayload.serviceName="vision.googleapis.com"
protoPayload.methodName="google.cloud.vision.v1.ImageAnnotator.AnnotateImage"

Ubica el campo resource.labels.project_id dentro de la entrada del log. Ese campo identifica el proyecto facturado, ya sea el proyecto basado en Recursos o el proyecto basado en Client. (La excepción son los buckets de Cloud Storage con Requester Pays.) Esta información se puede ver incluso al consultar una mezcla de datos de varios proyectos a través de un Log Sink multiproyecto.

Para BigQuery Compute Jobs

Dado que BigQuery separa el cómputo del almacenamiento, debes mirar específicamente los logs de ejecución de cómputo, no los de almacenamiento. Ejecuta esta consulta en Logs Explorer y, como con otros servicios de Google, ubica el 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"

Para GCS Requester Pays

En los buckets de Cloud Storage con Requester Pays, los audit logs muestran el número del proyecto facturado (en hexadecimal) bajo protoPayload.authorizationInfo.resource, después de "projects/", por ejemplo como "projects/0000004d9813b13".

La solución para la atribución de costos

Una vez que sabes cómo sacar a la luz estos logs de facturación, el siguiente reto es vincularlos con tu negocio: por ejemplo, con departamentos o proyectos de negocio concretos.

Mi rol como Cloud Architect en DoiT International es asesorar a los clientes sobre cómo optimizar sus costos, y DoiT ofrece un conjunto de herramientas potentes en DoiT Cloud Intelligence para conseguirlo. Por ejemplo, DoiT Cost Allocation agrupa y atribuye los costos por dimensión de negocio.

Algunos servicios admiten labels que ayudan en la atribución de costos:

  • En los servicios basados en Recursos, puedes asignar por Recurso y, opcionalmente, agregar labels al Recurso para que coincidan con tus categorías de negocio.
  • De forma excepcional, la invocación de la API en muchos modelos de Generative AI puede recibir labels de costo personalizados para usarse en la atribución.
  • Los pipelines de Vertex AI también ofrecen una capacidad única de atribución de costos. El Pipeline en sí tiene un costo pequeño, pero, lo más importante, puede generar varios tipos de recursos. Vertex AI adjunta automáticamente el label vertex-ai-pipelines-run-billing-id a cada Recurso que crea, lo que ayuda a atribuir los costos a la ejecución del Pipeline en su conjunto.

Sin embargo, en la mayoría de los servicios no basados en Recursos, los datos de costos de GCP no llevan labels por usuario u otra información que permita separar las categorías de negocio.

Una solución es esta: crea varios proyectos para que actúen como Client. Las organizaciones de Google Cloud suelen utilizar muchos proyectos, organizados en carpetas. Esos proyectos pueden definirse como Client para asignar los costos a categorías de negocio. Pueden estar vacíos en lo demás, y no hace falta ejecutar el código del cliente en el proyecto de facturación: lo que importa es el proyecto Client en la invocación. De este modo, los propios proyectos funcionan como el "label" que designa la unidad de negocio.