Skip to main content
GCP FinOps Cost Optimization Cloud Functions Terraform

Cut GCP Costs on Autopilot: Meet the CloudOn GCP FinOps Guardian

YN
Yaroslav Naumenko
|

Overview

The CloudOn GCP FinOps Guardian is a serverless solution that harnesses Google Cloud’s Recommender API to pinpoint cost savings and optimization opportunities across your entire GCP organization. It automatically detects idle resources, surfaces right-sizing recommendations, and delivers actionable insights directly to your Slack channel — all without any manual effort.

What’s Covered

Idle Resources

  • Idle Compute Engine VM instances
  • Idle persistent disks
  • Idle Cloud SQL instances
  • Unattached static IP addresses

Right-Sizing

  • Overprovisioned VM instances
  • Overprovisioned Cloud SQL instances

Cost Optimization

  • Committed use discount recommendations
  • Cloud Storage lifecycle policy suggestions

Architecture

The solution is built on fully managed GCP services and deployed entirely via Terraform.

ComponentDetails
Cloud FunctionPython 3.9 runtime, 512 MB memory, 300 s timeout, Pub/Sub trigger
Cloud SchedulerConfigurable cron schedule (default: daily)
Pub/SubDecouples scheduler from function invocation
Cloud StorageStores the function source archive
Service AccountLeast-privilege identity for the function

High-Level Flow

  1. Cloud Scheduler fires on the configured cron schedule and publishes a message to the Pub/Sub topic.
  2. The Pub/Sub trigger invokes the Cloud Function.
  3. The function iterates over every project in the GCP organization and calls the Recommender API for each supported recommender type.
  4. Findings are aggregated, formatted, and posted to the configured Slack webhook URL.

Supported Recommenders

Recommender NameAPI Resource Name
Idle VMgoogle.compute.instance.IdleResourceRecommender
VM Right-Sizinggoogle.compute.instance.MachineTypeRecommender
Idle Persistent Diskgoogle.compute.disk.IdleResourceRecommender
Idle Cloud SQLgoogle.cloudsql.instance.IdleRecommender
Cloud SQL Right-Sizinggoogle.cloudsql.instance.OverprovisionedRecommender
Idle Static IPgoogle.compute.address.IdleResourceRecommender
Committed Use Discounts (CPU)google.compute.commitment.UsageCommitmentRecommender
Committed Use Discounts (Memory)google.compute.commitment.UsageCommitmentRecommender
Cloud Storage Lifecyclegoogle.storage.bucket.ActivityInsight

Key Features

Idle Resource Detection

The Guardian scans every project for resources that are provisioned but not actively used — including VMs, disks, Cloud SQL instances, and static IP addresses — and reports the projected monthly savings for each finding.

Right-Sizing

For overprovisioned VMs and Cloud SQL instances, the function surfaces the recommended machine type or tier along with the expected cost reduction so engineers can act immediately.

Cost-Saving Commitments

The function evaluates your historical usage patterns and recommends committed use discounts (CUDs) where they would reduce spend, including both CPU-based and memory-based commitments.

Slack Notifications

All recommendations are delivered to a Slack channel via an incoming webhook. Each message includes the project ID, resource name, recommender type, priority, and estimated monthly savings.

Prerequisites

Deployment Permissions

The identity deploying the Terraform configuration needs the following roles on the organization or target projects:

  • roles/resourcemanager.organizationViewer
  • roles/iam.serviceAccountAdmin
  • roles/cloudfunctions.admin
  • roles/pubsub.admin
  • roles/cloudscheduler.admin
  • roles/storage.admin

Service Account Roles

The Cloud Function’s service account requires the following IAM roles.

Mandatory roles:

RolePurpose
roles/recommender.viewerRead Recommender API results
roles/resourcemanager.folderViewerEnumerate folders in the organization
roles/resourcemanager.projectViewerEnumerate projects
roles/browserBrowse the resource hierarchy

Optional roles (for organization-wide scanning):

RolePurpose
roles/resourcemanager.organizationViewerView organization-level metadata

Required APIs

Enable the following APIs before deployment:

gcloud services enable \
  cloudfunctions.googleapis.com \
  cloudscheduler.googleapis.com \
  pubsub.googleapis.com \
  recommender.googleapis.com \
  cloudresourcemanager.googleapis.com \
  storage.googleapis.com

Configuration

All runtime configuration is passed to the Cloud Function as environment variables, defined in main.tf.

resource "google_cloudfunctions_function" "finops_guardian" {
  name        = "gcp-finops-guardian"
  runtime     = "python39"
  entry_point = "main"

  available_memory_mb   = 512
  timeout               = 300
  trigger_http          = false

  event_trigger {
    event_type = "google.pubsub.topic.publish"
    resource   = google_pubsub_topic.finops_trigger.id
  }

  environment_variables = {
    ORGANIZATION_ID   = var.organization_id
    SLACK_WEBHOOK_URL = var.slack_webhook_url
    PROJECT_ID        = var.project_id
  }
}

Deployment

The solution is defined as five Terraform resources:

  1. google_storage_bucket — stores the function archive
  2. google_storage_bucket_object — uploads the zipped source code
  3. google_pubsub_topic — message bus between scheduler and function
  4. google_cloud_scheduler_job — triggers the function on a cron schedule
  5. google_cloudfunctions_function — the core scanning function

Example Terraform Variables

organization_id   = "123456789012"
project_id        = "my-finops-project"
region            = "us-central1"
slack_webhook_url = "https://hooks.slack.com/services/XXX/YYY/ZZZ"
scheduler_cron    = "0 9 * * 1"   # Every Monday at 09:00 UTC

Deploy

terraform init
terraform plan
terraform apply

Notifications

Each Slack message posted by the Guardian contains the following fields:

FieldDescription
ProjectGCP project ID where the resource lives
ResourceFull resource name
RecommenderHuman-readable recommender type
PriorityRecommendation priority (HIGH / MEDIUM / LOW)
Estimated Monthly SavingsProjected USD savings per month

Code Structure

FileResponsibility
main.pyEntry point; orchestrates scanning and Slack delivery
recommender.pyWraps the Recommender API; handles pagination and error handling
resource_recommender.pyMaps recommender names to resource types and formats findings

Adding New Recommenders

  1. Add the new recommender’s API resource name to the RECOMMENDERS list in recommender.py.
  2. Add a human-readable label for it in resource_recommender.py.
  3. Test locally against a non-production project before deploying.

Contributing

  1. Fork the repository and create a feature branch.
  2. Submit a pull request with a clear description of the change and any relevant test evidence.
  3. Ensure all existing tests pass and add new tests for any new recommender mappings.

Get Started

Clone the repository, fill in your terraform.tfvars, run terraform apply, and your GCP organization will start receiving weekly FinOps recommendations automatically.

YN

Yaroslav Naumenko

Cloud Infrastructure Architect specializing in PCI/HIPAA/FedRAMP compliant solutions at scale. Over a decade building on AWS & GCP.

Need Help With Your Cloud Infrastructure?

Book a free 15-minute call and let's discuss your needs.