Stay organized with collections
Save and categorize content based on your preferences.
This document explains how to use budget notifications to selectively
control resource usage.
When you
disable billing on a project,
all services stop and all resources are eventually deleted. If you need a more
nuanced response, you can selectively control resources. For example, you can
stop some Compute Engine resources while leaving Cloud Storage resources
intact. Stopping only some resources reduces your costs without completely
disabling your environment.
In the following example, the project runs research with a number of
Compute Engine virtual machines (VMs) and stores results in
Cloud Storage buckets. Using the budget notifications as the trigger, after
the budget is exceeded, this Cloud Run function shuts down all
Compute Engine instances, but doesn't affect the stored results.
Before you begin
Before you begin, you must complete the following tasks:
Copy the following code into your Cloud Run function:
Node.js
const{CloudBillingClient}=require('@google-cloud/billing');const{InstancesClient}=require('@google-cloud/compute');constPROJECT_ID=process.env.GOOGLE_CLOUD_PROJECT;constPROJECT_NAME=`projects/${PROJECT_ID}`;constinstancesClient=newInstancesClient();constZONE='us-central1-a';exports.limitUse=asyncpubsubEvent=>{constpubsubData=JSON.parse(Buffer.from(pubsubEvent.data,'base64').toString());if(pubsubData.costAmount<=pubsubData.budgetAmount){return`No action necessary. (Current cost: ${pubsubData.costAmount})`;}constinstanceNames=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]=awaitinstancesClient.list({project:projectId,zone:zone,});returninstances.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)=>{awaitPromise.all(instanceNames.map(instanceName=>{returninstancesClient.stop({project:projectId,zone:zone,instance:instanceName,}).then(()=>{console.log(`Instance stopped successfully: ${instanceName}`);});}));};
Python
importbase64importjsonimportosfromgoogleapiclientimportdiscoveryPROJECT_ID=os.getenv("GCP_PROJECT")PROJECT_NAME=f"projects/{PROJECT_ID}"ZONE="us-west1-b"deflimit_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"]ifcost_amount <=budget_amount:print(f"No action necessary. (Current cost: {cost_amount})")returncompute=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"notinres:return[]items=res["items"]running_names=[i["name"]foriinitemsifi["status"]=="RUNNING"]returnrunning_namesdef__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 """ifnotlen(instance_names):print("No running instances were found.")returnfornameininstance_names:instances.stop(project=project_id,zone=zone,instance=name).execute()print(f"Instance stopped successfully: {name}")
Set the Entry point to the correct function to execute:
Set the ZONE parameter. This parameter is the zone where instances
are stopped when the budget is exceeded.
Click DEPLOY.
Configure service account permissions
Your Cloud Run function runs as an automatically created service
account. To control usage, you need to grant the service account permissions to
any services on the project that it needs to modify by completing the following
steps:
Identify the correct service account by viewing the details of your
Cloud Run function. The service account is
listed at the bottom of the page.
Go to the IAM page in the Google Cloud console to set the
appropriate permissions.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-03-05 UTC."],[[["This guide details how to use budget notifications to manage resource usage selectively, allowing you to halt specific resources, such as Compute Engine instances, while preserving others, such as Cloud Storage."],["By setting up a Cloud Run function triggered by budget notifications, you can automatically stop Compute Engine virtual machines when a budget threshold is exceeded, thus reducing costs without fully disabling the environment."],["To get started, you'll need to enable the Cloud Billing API, create a budget, and configure programmatic budget notifications, followed by setting up a Cloud Run function with specific dependencies and code."],["The Cloud Run function code provided in Node.js and Python allows you to list and stop running instances in a designated zone, with customizable parameters for different project zones or projects."],["After deploying the function, it is crucial to configure the appropriate service account permissions to allow the Cloud Run function to modify resources and to test the function to confirm that instances are properly stopped."]]],[]]