Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Wer zahlt eigentlich? Die API-Abrechnung in Google Cloud entwirrt

By Joshua FoxApr 30, 20269 min read

Diese Seite ist auch in English, Español, Français, Italiano, 日本語 und Português verfügbar.

Google Cloud rechnet die meisten Cloud-Kosten projektbezogen ab. Aber welchem Projekt?

Bei einem Resource-basierten Dienst wie Google Compute Engine ist die Antwort einfach – die Kosten gehen an das Projekt, das die Resource (etwa eine VM) enthält.

Rufen Sie hingegen eine API für einen Google Cloud-Dienst wie Vision, Translate oder BigQuery auf, ist das Abrechnungsmodell flexibler. Ein Teil der Kosten oder die gesamten Kosten werden einem von Ihnen festgelegten "Client"-Projekt zugeordnet – so lassen sich Kosten verschiedenen Geschäftsbereichen oder Projekten zuweisen.

Dieser Blogbeitrag erklärt:

  • Was das "Client"-Projekt bedeutet und wie Sie es festlegen.
  • Die wichtigsten Muster, nach denen die Abrechnung an ein Projekt geknüpft wird – über verschiedene Diensttypen hinweg.
  • Warum die Google-Dokumentation fast ausschließlich vom "quota project" spricht, wenn es um die Abrechnung geht, und wie sich dies zum "billing project" verhält.
  • Wie Sie für jeden API-Aufruf herausfinden, welchem Projekt er in Rechnung gestellt wurde.
  • Wie Sie die Kostenzuordnung zu Geschäftsbereichen in den Griff bekommen.

Quota-/Billing-Project festlegen

Wenn ein API-Call die Google Cloud-Infrastruktur erreicht, durchläuft sie folgende Hierarchie, um das Client-Projekt zu ermitteln – das bei Nicht-Resource-Diensten zugleich für die Abrechnung herangezogen wird. (Die Konzepte "quota project" vs. "billing project" erläutere ich weiter unten.)

  • Die Auswertung übernimmt Googles Service Infrastructure/Service Control und sorgt damit für ein einheitliches Verhalten über alle von Google verwalteten Dienste hinweg.
  • Berechtigungen: Damit ein Projekt als Client festgelegt werden kann, muss der aufrufende Principal – etwa ein Service Account, ein Nutzer, eine Workforce Identity Federation oder eine Workload Identity Federation – in diesem Projekt die Rolle Service Usage Consumer besitzen. (Ob ein Service Account in diesem oder einem anderen Projekt definiert ist, spielt keine Rolle.)
  • Dies gilt für Google Cloud Platform-Dienste, jedoch nicht zwingend für andere Google-Dienste wie Workspace oder Maps.
  • Sie legen das Client-Projekt mit den folgenden Methoden fest – in dieser Vorrangreihenfolge.

Wege, den Client festzulegen

1. Im Request angegeben

  • HTTP-Header: Der HTTP-Header X-goog-user-project lässt sich direkt im Request übergeben. Praktisch bei reinen REST-Calls, etwa mit curl.
  • Client Library Configuration: Das Projekt, das über Client-Optionen in den Google Cloud SDKs gesetzt wird. Hier ein Beispiel mit der Python Google Cloud Client Library.
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. Umgebungsvariable

Der Wert der Umgebungsvariable GOOGLE_CLOUD_QUOTA_PROJECT. Diesen Wert zu setzen gilt als Best Practice, um das Quota-Projekt in containerisierten Umgebungen dynamisch festzulegen, statt es per ClientOptions hart zu kodieren.

3. API-Key

Das Projekt, in dem der für den Call verwendete API-Key generiert wurde.

4. ADC Quota Project

Für die lokale Umgebung (meist in der Entwicklung) wird dies mit gcloud auth application-default set-quota-project gesetzt.

Die Falle in der lokalen Entwicklung: Wenn Sie gcloud auth application-default login ausführen, ohne ein Client-Projekt für Quota und Abrechnung zu setzen, authentifizieren sich Ihre lokalen Skripte bei den meisten APIs mit einem speziellen, eingeschränkten Projekt (dem "Cloud SDK project" 764086051850). Da dieses global geteilt wird, ist die Nutzung stark gedrosselt, und der Fehler "Quota exceeded for project 764086051850" tritt nahezu sofort auf. Vermeiden lässt sich das, indem Sie den Client-Wert setzen.

5. Authentifizierungs-Token

  • Service Account: Das Projekt, dem der Service Account gehört, der den Request ausführt (auch bei impersonierten Service Accounts).
  • OAuth Client ID: Das Projekt, dem die OAuth 2.0 Client ID gehört, mit der das Endnutzer-Token erzeugt wurde.

6. Workforce Identity Federation

Ist der Principal für die API ein Workforce Identity Federation-Nutzer, wird das User-Project des Workforce Pools verwendet.

Warum spricht Google von "Quota project" und nicht von "Billing project"?

Google Cloud-Dokumentation und ‑Parameter verwenden überwiegend den Begriff "quota project", während "billing project" nur selten auftaucht.

Es gibt Ausnahmen. So nutzt etwa die gcloud-Dokumentation verwirrenderweise beide Begriffe nebeneinander, obwohl es um denselben Parameter geht: billing/quota_project für die persistente Tool-Konfiguration und --billing-project für das Kommandozeilen-Flag.

Dazu folgende Erklärung: In der gesamten Google Cloud erfüllen die Client-Einstellungen auf Infrastrukturebene genau eine Aufgabe: Sie legen das quota-Projekt fest, das vom API-Gateway verwendet wird, während die Abrechnung an das Resource-Projekt geht. Bei Nicht-Resource-basierten Diensten findet das Abrechnungssystem jedoch keine serverseitige Resource, der die Kosten zugeordnet werden könnten – und so fällt die Abrechnung standardmäßig auf das Quota-Projekt zurück.

Resource-basierte vs. nicht-Resource-basierte Dienste

Der wesentliche Unterschied liegt zwischen Diensten, die nach Resources abgerechnet werden, und solchen ohne. Beginnen wir mit einer Übersicht:

Diensttyp Primärer Abrechnungstreiber Primärer Quota-Treiber Beispiele
Resource-basiert Projekt, das die Resource enthält Client-Projekt Compute Engine, Spanner, Cloud Run
Client-basiert Client-(Quota-)Projekt Client-Projekt Vision API, Translate API

Resource-basierte APIs: Identifizierbares serverseitiges Projekt.

Dazu gehören Googles Infrastruktur-, Storage- und Compute-APIs. Sie sind zustandsbehaftet. Wenn Sie sie aufrufen, fordern Sie Google auf, ein bestimmtes Asset oder bestimmte Daten in einem Projekt zu lesen, zu ändern oder zu löschen. Das Billing-Projekt ist jenes, in dem die Resource liegt, und wird üblicherweise in der URL angegeben. Das Quota-Projekt hingegen ergibt sich aus der Client-Einstellung.

Es gibt Sonderfälle wie Cloud Storage, Pub/Sub und BigQuery, die weiter unten beschrieben werden.

Einige Beispiele:

  • Compute Engine API: Verwaltung virtueller Maschinen, Disks und Netzwerke. GET https://compute.googleapis.com/compute/v1/projects/{project}/zones/{zone}/instances
  • Cloud Spanner API: Abfrage oder Verwaltung relationaler Datenbanken. POST https://spanner.googleapis.com/v1/projects/{project}/instances/{instance}/databases/{database}/sessions
  • Cloud Run ist "serverless", aber Sie verwalten den Cloud Run-Dienst, nicht Google – daher gilt Resource-basierte Abrechnung. Die URL des Cloud Run-Dienstes enthält kein Projekt und liegt nicht unter der Domain googleapis.com.

Client-basierte Quota und Abrechnung: Keine serverseitige Resource

Bei zustandslosen APIs, die schlicht einen global geteilten Algorithmus bereitstellen, gibt es keine Resource in irgendeinem Projekt, und auch in der REST-URL taucht kein Server auf. Hier wird die Abrechnung über die Client-Einstellung bestimmt.

Einige Beispiele:

  • Cloud Natural Language API: Sie übergeben einen Absatz und erhalten eine Sentiment-Analyse zurück. POST https://language.googleapis.com/v1/documents:analyzeSentiment
  • Cloud Video Intelligence API: Sie übergeben ein Video und erhalten Labels der darin enthaltenen Objekte. POST https://videointelligence.googleapis.com/v1/videos:annotate

Cloud Storage: Die Option "Requester Pays"

Cloud Storage ist Resource-basiert, auch wenn die URL keine Projekt-ID in dieser Form enthält: GET https://storage.googleapis.com/storage/v1/b/{bucket}/o/{object}

Es existiert dennoch ein serverseitiges Projekt, das das API-Gateway anhand des Bucket-Namens auflöst.

Wie bei anderen Resource-basierten APIs geht die Abrechnung an das Projekt des Buckets, während die Quota dem angegebenen Client zugeordnet wird.

Ändern lässt sich das über die für Cloud Storage einzigartige Option "Requester Pays". Aktiviert der Bucket-Eigentümer Requester Pays, muss der API-Aufrufer ein abrechenbares Projekt (über die oben genannten Client-Einstellungen) angeben; dieses Projekt wird dann für Egress und API-Operationen belastet (für die Storage-Kosten kommt allerdings weiterhin der Bucket-Eigentümer auf).

BigQuery: Zwei separate Resource-Typen

BigQuery ist insofern besonders, als Storage und Compute in unterschiedlichen Projekten liegen können.

  • Storage wird dem Projekt in Rechnung gestellt, dem die Resource gehört: dem Dataset mit den gespeicherten Daten.
  • Query Processing wird dem Projekt in Rechnung gestellt, in dem der Query-Job läuft. Auch wenn ein Job eine Form von Compute ist, behandelt BigQuery ihn als eigenständige, zustandsbehaftete Resource. Er wird seinem Projekt in Rechnung gestellt, das sich vom Storage-Projekt und vom Projekt, in dem der Job gestartet wird, unterscheiden kann.

Pub/Sub: Topics und Subscriptions können in unterschiedlichen Projekten liegen

Wie bei anderen Resource-basierten Diensten sind die Kosten in Pub/Sub an die Resource-Zugehörigkeit geknüpft – unabhängig davon, wer den API-Call ausführt –, und die Client-Einstellungen dienen nur der Quota-Berechnung.

Ungewöhnlich an Pub/Sub ist allerdings, dass die Resources selbst über mehrere Projekte verteilt sein können:

  • Das Topic ist die maßgebliche Resource für die Abrechnung der Nachrichtenveröffentlichung.
  • Eine Pub/Sub-Subscription ist eine eigene Resource, die in einem anderen Projekt erstellt werden kann als das Topic oder der aufrufende Client. Sie bestimmt die Abrechnung für Delivery-Throughput, Datentransfer (Egress) und Subscription-bezogenen Storage.

Das abgerechnete Projekt für einen Service-Aufruf finden

Im Folgenden einige Wege, um das Projekt zu ermitteln, dem ein bestimmter Aufruf in Rechnung gestellt wird. Ein standardmäßiges Feld "billed_project" gibt es in einem Google Cloud API-Log nicht, doch in der Regel lässt sich die Information herausfinden.

Voraussetzung: Um API-Calls nachzuverfolgen, müssen Sie zunächst die Data Access Audit Logs für die jeweilige API (z. B. Cloud Storage, BigQuery) in dem Projekt aktivieren, das Ihrer Vermutung nach belastet wird. Das erledigen Sie in der Google Cloud Console unter IAM & Admin -> Audit Logs.

Für Google Cloud-Dienste allgemein

Filtern Sie die Logs nach dem entsprechenden Dienst:

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

Und optional nach Methode, zum Beispiel

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

Suchen Sie das Feld resource.labels.project_id im Log-Eintrag. Es weist das abgerechnete Projekt aus – egal ob Resource-basiertes oder Client-basiertes Projekt. (Eine Ausnahme bilden Cloud Storage Requester Pays-Buckets.) Diese Information ist auch dann sichtbar, wenn Sie über ein projektübergreifendes Log Sink Daten aus mehreren Projekten betrachten.

Für BigQuery Compute Jobs

Da BigQuery Compute und Storage trennt, müssen Sie gezielt die Compute-Execution-Logs statt der Storage-Logs auswerten. Führen Sie diese Query im Logs Explorer aus und suchen Sie wie bei anderen Google-Diensten das Feld 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"

Für GCS Requester Pays

Bei Cloud Storage Requester Pays-Buckets zeigen die Audit Logs die Nummer des belasteten Projekts (in Hexadezimal) unter protoPayload.authorizationInfo.resource an, hinter "projects/", zum Beispiel als "projects/0000004d9813b13".

Die Lösung für die Kostenzuordnung

Wenn Sie wissen, wie sich diese Abrechnungslogs sichtbar machen lassen, besteht die nächste Aufgabe darin, sie auf Ihr Geschäft abzubilden – etwa auf einzelne Geschäftsbereiche oder Business-Projekte.

Meine Aufgabe als Cloud Architect bei DoiT International ist es, Kunden bei der Kostenoptimierung zu beraten, und DoiT bietet dazu in DoiT Cloud Intelligence eine ganze Suite leistungsfähiger Tools. So gruppiert und verteilt etwa DoiT Cost Allocation Kosten nach Geschäftsdimensionen.

Einige Dienste unterstützen Labels, die bei der Kostenzuordnung helfen:

  • Bei Resource-basierten Diensten können Sie nach Resource zuweisen und der Resource optional Labels passend zu Ihren Geschäftskategorien hinzufügen.
  • Eine Besonderheit: Der API-Aufruf vieler Generative AI-Modelle kann eigene Cost-Labels entgegennehmen, die für die Zuordnung verwendet werden.
  • Auch Vertex AI Pipelines bieten ein einzigartiges Feature zur Kostenzuordnung. Die Pipeline selbst verursacht geringe Kosten, kann aber – und das ist entscheidender – mehrere Arten von Resources erzeugen. Vertex AI hängt automatisch das Label vertex-ai-pipelines-run-billing-id an jede dabei erzeugte Resource, was die Zuordnung der Kosten zum gesamten Pipeline-Run erleichtert.

Für die meisten nicht-Resource-basierten Dienste sind die GCP-Kostendaten allerdings nicht nach Nutzer oder anderen Merkmalen gelabelt, mit denen sich Geschäftskategorien sauber trennen ließen.

Ein Lösungsansatz: Legen Sie mehrere Projekte an, die als Client dienen. Google Cloud-Organisationen nutzen ohnehin meist viele Projekte, in Ordnern strukturiert. Diese Projekte lassen sich dann als Client setzen, um Kosten Geschäftskategorien zuzuordnen. Sie können ansonsten leer bleiben, und Sie müssen den Client-Code nicht im Billing-Projekt ausführen – entscheidend ist allein das Client-Projekt beim Aufruf. Auf diese Weise dienen die Projekte selbst als "Label" für die jeweilige Geschäftseinheit.