Abrechnung der Nutzung mit Benachrichtigungen deaktivieren

In diesem Dokument wird erläutert, wie Sie die Abrechnung für ein Projekt automatisch deaktivieren, wenn die Kosten das Projektbudget erreichen oder überschreiten. Wenn Sie die Abrechnung für ein Projekt deaktivieren, werden alle Google Cloud Dienste im Projekt beendet, einschließlich der kostenlosen Dienste. Weitere Informationen zu differenzierten Reaktionen auf Budgetbenachrichtigungen finden Sie unter Ressourcennutzung mit Benachrichtigungen steuern.

Möglicherweise begrenzen Sie die Kosten, weil Sie einen maximalen Betrag für Google Cloudausgeben möchten. In diesen Fällen können Sie alle Ihre Google Cloud Dienste und deren Nutzung beenden, um Kosten zu vermeiden, wenn das Budgetlimit erreicht ist. Wenn Sie die Abrechnung für Ihr Projekt deaktivieren, können Sie Kosten vermeiden.

Beschränkungen

  • Zwischen dem Zeitpunkt, zu dem die Kosten anfallen, und dem Empfang von Budgetbenachrichtigungen verzögert sich Budgetbenachrichtigungen. Dabei können zusätzliche Kosten für die Nutzung entstehen, da zu der Zeit, zu der alle Dienste beendet wurde, eventuell noch keine vollständige Abrechnung erfolgt ist. Wenn Sie den Schritten in diesem Beispiel folgen, ist das keine Garantie dafür, dass die Ausgaben das Budget nicht überschreiten. Wenn Ihr Budget begrenzt ist, legen Sie das maximale Budget unterhalb des verfügbaren Guthabens fest, um Verzögerungen bei der Abrechnung zu berücksichtigen.

  • Die Abrechnung für ein Projekt, das mit einem Rechnungskonto verknüpft ist, kann nicht deaktiviert werden. Weitere Informationen zum Sperren und Entsperren von Projekten finden Sie unter Verknüpfung zwischen einem Projekt und seinem Rechnungskonto sichern.

Hinweise

Führen Sie die folgenden Aufgaben aus, bevor Sie beginnen:

  1. Cloud Billing API aktivieren
  2. Budget für ein einzelnes Projekt erstellen
  3. Programmatische Budgetbenachrichtigungen einrichten

Cloud Run-Funktion einrichten

Wenn Sie Cloud Billing für ein Projekt deaktivieren möchten, erstellen Sie eine Cloud Run-Funktion und konfigurieren Sie sie so, dass sie die Cloud Billing API aufruft.

  1. Führen Sie die Schritte unter Cloud Run-Funktion erstellen aus. Achten Sie darauf, dass der Triggertyp auf dasselbe Pub/Sub-Thema gesetzt ist, das vom Budget verwendet wird.
  2. Fügen Sie die folgenden Abhängigkeiten hinzu:

    Node.js

    Kopieren Sie Folgendes in Ihre package.json-Datei:

    {
      "name": "cloud-functions-billing",
      "private": "true",
      "version": "0.0.1",
      "description": "Examples of integrating Cloud Functions with billing",
      "main": "index.js",
      "engines": {
        "node": ">=16.0.0"
      },
      "scripts": {
        "compute-test": "c8 mocha -p -j 2 test/periodic.test.js --timeout=600000",
        "test": "c8 mocha -p -j 2 test/index.test.js --timeout=5000 --exit"
      },
      "author": "Ace Nassri <anassri@google.com>",
      "license": "Apache-2.0",
      "dependencies": {
        "@google-cloud/billing": "^4.0.0",
        "@google-cloud/compute": "^4.0.0",
        "google-auth-library": "^9.0.0",
        "googleapis": "^143.0.0",
        "slack": "^11.0.1"
      },
      "devDependencies": {
        "@google-cloud/functions-framework": "^3.0.0",
        "c8": "^10.0.0",
        "gaxios": "^6.0.0",
        "mocha": "^10.0.0",
        "promise-retry": "^2.0.0",
        "proxyquire": "^2.1.0",
        "sinon": "^18.0.0",
        "wait-port": "^1.0.4"
      }
    }
    

    Python

    Kopieren Sie Folgendes in Ihre requirements.txt-Datei:

    slackclient==2.9.4
    google-api-python-client==2.131.0
    

  3. Kopieren Sie den folgenden Code in Ihre Cloud Run-Funktion:

    Node.js

    const {CloudBillingClient} = require('@google-cloud/billing');
    const {InstancesClient} = require('@google-cloud/compute');
    
    const PROJECT_ID = process.env.GOOGLE_CLOUD_PROJECT;
    const PROJECT_NAME = `projects/${PROJECT_ID}`;
    const billing = new CloudBillingClient();
    
    exports.stopBilling = async pubsubEvent => {
      const pubsubData = JSON.parse(
        Buffer.from(pubsubEvent.data, 'base64').toString()
      );
      if (pubsubData.costAmount <= pubsubData.budgetAmount) {
        return `No action necessary. (Current cost: ${pubsubData.costAmount})`;
      }
    
      if (!PROJECT_ID) {
        return 'No project specified';
      }
    
      const billingEnabled = await _isBillingEnabled(PROJECT_NAME);
      if (billingEnabled) {
        return _disableBillingForProject(PROJECT_NAME);
      } else {
        return 'Billing already disabled';
      }
    };
    
    /**
     * Determine whether billing is enabled for a project
     * @param {string} projectName Name of project to check if billing is enabled
     * @return {bool} Whether project has billing enabled or not
     */
    const _isBillingEnabled = async projectName => {
      try {
        const [res] = await billing.getProjectBillingInfo({name: projectName});
        return res.billingEnabled;
      } catch (e) {
        console.log(
          'Unable to determine if billing is enabled on specified project, assuming billing is enabled'
        );
        return true;
      }
    };
    
    /**
     * Disable billing for a project by removing its billing account
     * @param {string} projectName Name of project disable billing on
     * @return {string} Text containing response from disabling billing
     */
    const _disableBillingForProject = async projectName => {
      const [res] = await billing.updateProjectBillingInfo({
        name: projectName,
        resource: {billingAccountName: ''}, // Disable billing
      });
      return `Billing disabled: ${JSON.stringify(res)}`;
    };

    Python

    import base64
    import json
    import os
    
    from googleapiclient import discovery
    
    PROJECT_ID = os.getenv("GCP_PROJECT")
    PROJECT_NAME = f"projects/{PROJECT_ID}"
    def stop_billing(data, context):
        pubsub_data = base64.b64decode(data["data"]).decode("utf-8")
        pubsub_json = json.loads(pubsub_data)
        cost_amount = pubsub_json["costAmount"]
        budget_amount = pubsub_json["budgetAmount"]
        if cost_amount <= budget_amount:
            print(f"No action necessary. (Current cost: {cost_amount})")
            return
    
        if PROJECT_ID is None:
            print("No project specified with environment variable")
            return
    
        billing = discovery.build(
            "cloudbilling",
            "v1",
            cache_discovery=False,
        )
    
        projects = billing.projects()
    
        billing_enabled = __is_billing_enabled(PROJECT_NAME, projects)
    
        if billing_enabled:
            __disable_billing_for_project(PROJECT_NAME, projects)
        else:
            print("Billing already disabled")
    
    
    def __is_billing_enabled(project_name, projects):
        """
        Determine whether billing is enabled for a project
        @param {string} project_name Name of project to check if billing is enabled
        @return {bool} Whether project has billing enabled or not
        """
        try:
            res = projects.getBillingInfo(name=project_name).execute()
            return res["billingEnabled"]
        except KeyError:
            # If billingEnabled isn't part of the return, billing is not enabled
            return False
        except Exception:
            print(
                "Unable to determine if billing is enabled on specified project, assuming billing is enabled"
            )
            return True
    
    
    def __disable_billing_for_project(project_name, projects):
        """
        Disable billing for a project by removing its billing account
        @param {string} project_name Name of project disable billing on
        """
        body = {"billingAccountName": ""}  # Disable billing
        try:
            res = projects.updateBillingInfo(name=project_name, body=body).execute()
            print(f"Billing disabled: {json.dumps(res)}")
        except Exception:
            print("Failed to disable billing, possibly check permissions")
    
    

  4. Legen Sie als Einstiegspunkt die richtige Funktion fest, die ausgeführt werden soll:

    Node.js

    Legen Sie als Einstiegspunkt stopBilling fest.

    Python

    Legen Sie als Einstiegspunkt stop_billing fest.

  5. Sehen Sie sich die Liste der automatisch festgelegten Umgebungsvariablen an, um festzustellen, ob Sie die Variable GOOGLE_CLOUD_PROJECT manuell für das Projekt festlegen müssen, für das Sie Cloud Billing deaktivieren möchten.

  6. Klicken Sie auf DEPLOY (Bereitstellen).

Dienstkontoberechtigungen konfigurieren

Ihre Cloud Run-Funktion wird als automatisch erstelltes Dienstkonto ausgeführt. Wenn Sie die Abrechnung deaktivieren möchten, müssen Sie dem Dienstkonto Berechtigungen für alle Dienste im Projekt erteilen, die es ändern muss. Gehen Sie dazu so vor:

  1. Sehen Sie sich die Details der Cloud Run-Funktion an, um das richtige Dienstkonto zu ermitteln. Das Dienstkonto ist am Ende der Seite aufgeführt.
  2. Rufen Sie in der Google Cloud Console die Seite IAM auf, um die entsprechenden Berechtigungen festzulegen.

    Zur IAM-Seite

  3. Wenn Sie die Berechtigungen für das Rechnungskonto ändern möchten, rufen Sie in der Google Cloud Console die Seite Kontoverwaltung auf, fügen Sie das Dienstkonto als Prinzipal zum Cloud-Rechnungskonto hinzu und legen Sie die entsprechenden Berechtigungen für das Rechnungskonto fest.

    Zur Seite „Kontoverwaltung“ in Cloud Billing

Weitere Informationen zum Konfigurieren von Berechtigungen für Cloud-Rechnungskonten

Prüfen, ob Cloud Billing deaktiviert ist

Wenn das Budget eine Benachrichtigung sendet, ist dem angegebenen Projekt kein Cloud-Rechnungskonto mehr zugeordnet. Führen Sie die Schritte unter Cloud Run-Funktion testen aus, um sicherzustellen, dass Ihre Funktion wie erwartet funktioniert.

Wenn der Vorgang erfolgreich war, wird das Projekt nicht mehr unter dem Cloud-Rechnungskonto angezeigt und die Ressourcen im Projekt sind deaktiviert. Dies gilt auch für die Cloud Run-Funktion, wenn sie sich im selben Projekt befindet.

Wenn Sie die Google Cloud Ressourcen im Projekt weiterhin verwenden möchten, müssen Sie in der Google Cloud Console Cloud Billing für Ihr Projekt manuell wieder aktivieren.

Nächste Schritte

In anderen Beispielen für programmatische Benachrichtigungen erfahren Sie, wie Sie Folgendes tun: