Esempi di risposte automatiche sul controllo dei costi

Architettura di riferimento di esempio

Diagramma di un esempio che utilizza le notifiche programmatiche di avviso budget per automatizzare una risposta di controllo dei costi.
Figura 1: illustra un esempio di utilizzo degli avvisi budget per automatizzare le risposte al controllo dei costi utilizzando Pub/Sub per le notifiche programmatiche e le funzioni Cloud Run per automatizzare una risposta.

Se sei attento ai costi e devi controllare il tuo ambiente in base al budget, puoi utilizzare le notifiche del budget programmatiche per automatizzare la risposta di controllo dei costi in base alla notifica del budget.

Le notifiche di budget utilizzano gli argomenti Pub/Sub per fornire lo stato in tempo reale del budget di fatturazione Cloud, utilizzando la scalabilità, la flessibilità e l'affidabilità del middleware enterprise orientato ai messaggi per il cloud.

Questo documento contiene esempi e istruzioni dettagliate su come utilizzare le notifiche del budget con le funzioni Cloud Run per automatizzare la gestione dei costi.

Configurare le notifiche relative al budget

Il primo passaggio consiste nell'abilitare un argomento Pub/Sub per il tuo budget. Questo aspetto è descritto in dettaglio in Gestire le notifiche di avviso di budget programmatico.

Dopo aver attivato le notifiche relative al budget, tieni presente quanto segue:

  • Argomento Pub/Sub: si tratta dell'endpoint di notifiche configurato per il budget.
  • ID budget: si tratta di un ID univoco del budget incluso in tutte le notifiche. Puoi trovare l'ID del budget in Gestisci notifiche. L'ID viene visualizzato dopo aver selezionato Collega un argomento Pub/Sub a questo budget.

La sezione Gestisci notifiche nella console Google Cloud, in cui puoi collegare un argomento Pub/Sub a un budget. Sono inclusi
         l'ID budget, il nome del progetto e l'argomento Pub/Sub.

Ascoltare le notifiche

Il passaggio successivo consiste nell'ascoltare le notifiche iscrivendosi all'argomento Pub/Sub. Se non hai un abbonato, Pub/Sub eliminerà i messaggi pubblicati e non potrai recuperarli in un secondo momento.

Sebbene esistano molti modi per abbonarsi all'argomento, in questi esempi vengono utilizzati gli attivatori delle funzioni Cloud Run.

Crea una funzione Cloud Run

Per creare una nuova funzione Cloud Run:

  1. Nella console Google Cloud, vai alla pagina Funzioni Cloud Run.

    Vai alla pagina Funzioni Cloud Run

  2. Fai clic su CREA FUNZIONE e assegna alla funzione un nome significativo per il tuo bilancio.

  3. In Trigger, seleziona Argomento Pub/Sub.

  4. Seleziona l'argomento configurato nel budget.

  5. Fornisci il codice sorgente e le dipendenze per l'esecuzione della funzione.

  6. Assicurati di impostare Funzione da eseguire sul nome della funzione corretto.

La pagina Crea funzione nella sezione Funzioni Cloud Run della console Google Cloud. Include il nome della funzione, la quantità di memoria assegnata, il tipo di trigger e l'argomento Pub/Sub configurato nel budget.

Descrivi la funzione Cloud Run

Per indicare alla funzione Cloud Run cosa deve fare con la notifica, puoi scrivere codice utilizzando l'editor in linea o caricare un file. Per informazioni dettagliate sulle notifiche che riceverà il tuo codice, consulta Formato delle notifiche.

Ad esempio, una funzione potrebbe registrare le notifiche Pub/Sub ricevute, gli attributi e i dati quando viene attivata da una notifica del budget. Per saperne di più, consulta Trigger Pub/Sub.

Visualizzare gli eventi delle funzioni Cloud Run

Dopo aver salvato la funzione Cloud Run, puoi fare clic su VISUALIZZA LOG per visualizzare le notifiche relative al budget registrate. Vengono visualizzati i log delle chiamate della funzione.

Mostra dove puoi trovare i log di visualizzazione sullo schermo e l'elenco degli eventi della funzione Cloud Run nella console Google Cloud.

Testa la funzione Cloud Run

Le notifiche vengono inviate a Pub/Sub e gli iscritti ricevono i messaggi. Per testare una notifica di esempio e assicurarti che la funzione funzioni come previsto, pubblica un messaggio in Pub/Sub utilizzando questo oggetto come corpo del messaggio:

{
    "budgetDisplayName": "name-of-budget",
    "alertThresholdExceeded": 1.0,
    "costAmount": 100.01,
    "costIntervalStart": "2019-01-01T00:00:00Z",
    "budgetAmount": 100.00,
    "budgetAmountType": "SPECIFIED_AMOUNT",
    "currencyCode": "USD"
}

Puoi anche aggiungere attributi dei messaggi, come l'ID account di fatturazione. Per ulteriori informazioni, consulta la documentazione completa sul formato delle notifiche.

Inviare notifiche a Slack

L'email non è sempre il modo migliore per rimanere al passo con i costi del cloud, soprattutto se il budget è fondamentale e tempestivo. Con le notifiche, puoi inoltrare i messaggi relativi al budget ad altri mezzi.

In questo esempio descriviamo come inoltrare le notifiche del budget a Slack. In questo modo, ogni volta che la fatturazione Cloud pubblica una notifica relativa al budget, una funzione Cloud Run utilizza un bot per pubblicare un messaggio in un canale Slack dello spazio di lavoro del bot.

Configurare un canale Slack e le autorizzazioni

Il primo passaggio consiste nel creare lo spazio di lavoro di Slack e i token utente del bot che vengono utilizzati per chiamare l'API Slack. I token API possono essere gestiti all'indirizzo https://api.slack.com/apps. Per istruzioni dettagliate, consulta Utenti bot sul sito di Slack.

Configura le notifiche di Slack.

Scrivere una funzione Cloud Run

  1. Crea una nuova funzione seguendo i passaggi descritti in Creare una funzione Cloud Run. Assicurati che l'attivatore sia impostato sullo stesso argomento Pub/Sub impostato per l'utilizzo del budget.

  2. Aggiungi le dipendenze:

    Node.js

    Copia quanto segue in package.json:

    {
      "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

    Copia quanto segue in requirements.txt:

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

  3. Scrivi codice o utilizza il seguente esempio per pubblicare notifiche sul budget in un canale di chat di Slack utilizzando l'API Slack.

  4. Assicurati che i seguenti parametri postMessage dell'API Slack siano impostati correttamente:

    • Token di accesso OAuth dell'utente del bot
    • Nome canale

Esempio di codice:

Node.js

const slack = require('slack');

// TODO(developer) replace these with your own values
const BOT_ACCESS_TOKEN =
  process.env.BOT_ACCESS_TOKEN || 'xxxx-111111111111-abcdefghidklmnopq';
const CHANNEL = process.env.SLACK_CHANNEL || 'general';

exports.notifySlack = async pubsubEvent => {
  const pubsubAttrs = pubsubEvent.attributes;
  const pubsubData = Buffer.from(pubsubEvent.data, 'base64').toString();
  const budgetNotificationText = `${JSON.stringify(
    pubsubAttrs
  )}, ${pubsubData}`;

  await slack.chat.postMessage({
    token: BOT_ACCESS_TOKEN,
    channel: CHANNEL,
    text: budgetNotificationText,
  });

  return 'Slack notification sent successfully';
};

Python

import base64
import json
import os

import slack
from slack.errors import SlackApiError

# See https://api.slack.com/docs/token-types#bot for more info
BOT_ACCESS_TOKEN = "xxxx-111111111111-abcdefghidklmnopq"
CHANNEL = "C0XXXXXX"

slack_client = slack.WebClient(token=BOT_ACCESS_TOKEN)


def notify_slack(data, context):
    pubsub_message = data

    # For more information, see
    # https://cloud.google.com/billing/docs/how-to/budgets-programmatic-notifications#notification_format
    try:
        notification_attr = json.dumps(pubsub_message["attributes"])
    except KeyError:
        notification_attr = "No attributes passed in"

    try:
        notification_data = base64.b64decode(data["data"]).decode("utf-8")
    except KeyError:
        notification_data = "No data passed in"

    # This is just a quick dump of the budget data (or an empty string)
    # You can modify and format the message to meet your needs
    budget_notification_text = f"{notification_attr}, {notification_data}"

    try:
        slack_client.api_call(
            "chat.postMessage",
            json={"channel": CHANNEL, "text": budget_notification_text},
        )
    except SlackApiError:
        print("Error posting to Slack")

Ora puoi testare la funzione Cloud Run per visualizzare un messaggio in Slack.

Impostare un limite (disattivare) alla fatturazione per interrompere l'utilizzo

Questo esempio mostra come limitare i costi e interrompere l'utilizzo di un progetto disattivando la fatturazione Cloud. La disattivazione della fatturazione in un progetto comporta l'interruzione di tutti i servizi Google Cloud al suo interno, inclusi i servizi di livello gratuito.

Perché disattivare la fatturazione?

Potresti limitare i costi perché hai un limite fisso alla quantità di denaro che puoi spendere su Google Cloud. Questo è tipico di studenti, ricercatori o sviluppatori che lavorano in ambienti sandbox. In questi casi, vuoi interrompere la spesa e potresti essere disposto a chiudere tutti i servizi e l'utilizzo di Google Cloud quando viene raggiunto il limite di budget.

Per il nostro esempio, utilizziamo acme-backend-dev come progetto non di produzione per il quale la fatturazione Cloud può essere disattivata in sicurezza.

Configura il limite di budget nella console Google Cloud.

Prima di iniziare a lavorare con questo esempio, assicurati di aver eseguito quanto segue:

  • Abilita l'API Cloud Billing. La funzione Cloud Run deve chiamare l'API Cloud Billing per disattivare la fatturazione Cloud per un progetto.

  • Configura un budget per monitorare i costi del progetto e attivare le notifiche relative al budget.

Mostra l&#39;elenco degli avvisi di Fatturazione cloud nella console Google Cloud.

Scrivere una funzione Cloud Run

Successivamente, devi configurare la funzione Cloud Run per chiamare l'API Cloud Billing. In questo modo, la funzione Cloud Run può disattivare la fatturazione Cloud per il nostro progetto di esempio acme-backend-dev.

  1. Crea una nuova funzione seguendo i passaggi descritti in Creare una funzione Cloud Run. Assicurati che l'attivatore sia impostato sullo stesso argomento Pub/Sub impostato per l'utilizzo del budget.

  2. Aggiungi le seguenti dipendenze:

    Node.js

    Copia quanto segue in package.json:

    {
      "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

    Copia quanto segue in requirements.txt:

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

  3. Copia il seguente codice nella funzione Cloud Run.

  4. Imposta la funzione da eseguire su stopBilling (Node) o stop_billing (Python).

  5. A seconda del runtime, la variabile di ambiente GOOGLE_CLOUD_PROJECT potrebbe essere impostata automaticamente. Esamina l'elenco delle variabili di ambiente impostate automaticamente e determina se devi impostare manualmente la variabile GOOGLE_CLOUD_PROJECT per il progetto per il quale vuoi limitare (disattivare) la fatturazione Cloud.

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")

Configura le autorizzazioni degli account di servizio

La funzione Cloud Run viene eseguita come un account di servizio creato automaticamente. Affinché l'account di servizio possa disattivare la fatturazione, devi concedergli le autorizzazioni corrette, ad esempio Amministratore fatturazione.

Per identificare l'account di servizio corretto, visualizza i dettagli della funzione Cloud Run. L'account di servizio è elencato nella parte inferiore della pagina.

Mostra dove trovare le informazioni sull&#39;account di servizio nella sezione della funzione Cloud Run della console Google Cloud.

Puoi gestire le autorizzazioni di amministratore della fatturazione nella pagina Fatturazione della console Google Cloud.

Per concedere all'account di servizio i privilegi di amministratore dell'account di fatturazione, seleziona il nome dell'account di servizio.

Mostra dove selezionare il nome dell&#39;account di servizio e il ruolo Amministratore account di fatturazione nella sezione Autorizzazioni della console Google Cloud.

Verifica che la fatturazione Cloud sia disattivata

Quando il budget invia una notifica, il progetto specificato non avrà più un account di fatturazione Cloud. Se vuoi testare la funzione, pubblica un messaggio di esempio con il messaggio di test precedente. Il progetto non sarà più visibile nell'account di fatturazione Cloud e le risorse al suo interno verranno disattivate, inclusa la funzione Cloud Run se si trova nello stesso progetto.

Mostra che il progetto di esempio non è più visibile nell&#39;elenco dei progetti collegati all&#39;account di fatturazione Cloud. In questo modo verifichi
         che la fatturazione Cloud sia disabilitata per il progetto.

Puoi riattivare manualmente la fatturazione Cloud per il tuo progetto nella console Google Cloud.

Controllare selettivamente l'utilizzo

Il capping (la disattivazione) della fatturazione Cloud come descritto nell'esempio precedente è binario e terminale. Il progetto è attivo o disattivato. Quando il progetto viene disattivato, tutti i servizi vengono interrotti e tutte le risorse vengono eventualmente eliminate.

Se hai bisogno di una risposta più sfumata, puoi controllare selettivamente le risorse. Ad esempio, se vuoi arrestare alcune risorse Compute Engine, ma lasciare Cloud Storage invariato, puoi controllare l'utilizzo in modo selettivo. In questo modo, il costo per ora viene ridotto senza disattivare completamente l'ambiente.

Puoi scrivere norme con tutte le sfumature che vuoi. Tuttavia, per il nostro esempio, il progetto esegue ricerche con una serie di macchine virtuali Compute Engine e memorizza i risultati in Cloud Storage. Questo esempio di funzione Cloud Run arresta tutte le istanze Compute Engine, ma non influisce sui risultati archiviati dopo il superamento del budget.

Scrivere una funzione Cloud Run

  1. Crea una nuova funzione seguendo i passaggi descritti in Creare una funzione Cloud Run. Assicurati che l'attivatore sia impostato sullo stesso argomento Pub/Sub impostato per l'utilizzo del budget.

  2. Assicurati di aver aggiunto le dipendenze descritte in Limitare (disattivare) la fatturazione per interrompere l'utilizzo.

  3. Copia il seguente codice nella funzione Cloud Run.

  4. Imposta la funzione da eseguire su limitUse (Node) o limit_use (Python).

  5. A seconda del runtime, la variabile di ambiente GCP_PROJECT potrebbe essere impostata automaticamente. Esamina l'elenco delle variabili di ambiente impostate automaticamente e determina se devi impostare manualmente la variabile GCP_PROJECT per il progetto che esegue le VM.

  6. Imposta il parametro ZONE. Questa è la zona in cui le istanze verranno messe in pausa per questo sample.

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 instancesClient = new InstancesClient();
const ZONE = 'us-central1-a';

exports.limitUse = 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})`;
  }

  const instanceNames = await _listRunningInstances(PROJECT_ID, ZONE);
  if (!instanceNames.length) {
    return 'No running instances were found.';
  }

  await _stopInstances(PROJECT_ID, ZONE, instanceNames);
  return `${instanceNames.length} instance(s) stopped successfully.`;
};

/**
 * @return {Promise} Array of names of running instances
 */
const _listRunningInstances = async (projectId, zone) => {
  const [instances] = await instancesClient.list({
    project: projectId,
    zone: zone,
  });
  return instances
    .filter(item => item.status === 'RUNNING')
    .map(item => item.name);
};

/**
 * @param {Array} instanceNames Names of instance to stop
 * @return {Promise} Response from stopping instances
 */
const _stopInstances = async (projectId, zone, instanceNames) => {
  await Promise.all(
    instanceNames.map(instanceName => {
      return instancesClient
        .stop({
          project: projectId,
          zone: zone,
          instance: instanceName,
        })
        .then(() => {
          console.log(`Instance stopped successfully: ${instanceName}`);
        });
    })
  );
};

Python

import base64
import json
import os

from googleapiclient import discovery

PROJECT_ID = os.getenv("GCP_PROJECT")
PROJECT_NAME = f"projects/{PROJECT_ID}"
ZONE = "us-west1-b"


def limit_use(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

    compute = discovery.build(
        "compute",
        "v1",
        cache_discovery=False,
    )
    instances = compute.instances()

    instance_names = __list_running_instances(PROJECT_ID, ZONE, instances)
    __stop_instances(PROJECT_ID, ZONE, instance_names, instances)


def __list_running_instances(project_id, zone, instances):
    """
    @param {string} project_id ID of project that contains instances to stop
    @param {string} zone Zone that contains instances to stop
    @return {Promise} Array of names of running instances
    """
    res = instances.list(project=project_id, zone=zone).execute()

    if "items" not in res:
        return []

    items = res["items"]
    running_names = [i["name"] for i in items if i["status"] == "RUNNING"]
    return running_names


def __stop_instances(project_id, zone, instance_names, instances):
    """
    @param {string} project_id ID of project that contains instances to stop
    @param {string} zone Zone that contains instances to stop
    @param {Array} instance_names Names of instance to stop
    @return {Promise} Response from stopping instances
    """
    if not len(instance_names):
        print("No running instances were found.")
        return

    for name in instance_names:
        instances.stop(project=project_id, zone=zone, instance=name).execute()
        print(f"Instance stopped successfully: {name}")

Configura le autorizzazioni degli account di servizio

  1. La funzione Cloud Run viene eseguita come un account di servizio creato automaticamente. Per controllare l'utilizzo, devi concedere all'account di servizio le autorizzazioni per tutti i servizi del progetto di cui ha bisogno per apportare modifiche.
  2. Per identificare l'account di servizio corretto, visualizza i dettagli della funzione Cloud Run. L'account di servizio è elencato nella parte inferiore della pagina.
  3. Nella console Google Cloud, vai alla pagina IAM per impostare le autorizzazioni appropriate.
    Vai alla pagina IAM
     
    Mostra la schermata IAM nella console Google Cloud,
         dove puoi impostare le autorizzazioni appropriate per l&#39;account di servizio
         che esegue la funzione Cloud Run.

Verifica che le istanze siano arrestate

Quando il budget invia una notifica, le macchine virtuali Compute Engine vengono interrotte.

Per testare la funzione, pubblica un messaggio di esempio con il messaggio di test precedente. Per verificare che la funzione sia stata eseguita correttamente, controlla le macchine virtuali Compute Engine nella console Google Cloud.