GCP for DevOps — Cost Optimization Exercises
Practice Exercises — Cost Optimization
Exercise 1: Set Up Budget Alerts
Create a budget with alert thresholds for a project.
- Enable the billing budgets API
- Create a Pub/Sub topic for billing alerts
- Configure a budget of $100/month with alerts at 50%, 75%, and 100%
- Verify the budget is created
Show Answer
# Enable the API
$ gcloud services enable billingbudgets.googleapis.com
# Create Pub/Sub topic
$ gcloud pubsub topics create billing-alerts
# Create the budget (via Console or API)
# Console: Billing → Budgets & alerts → Create Budget
# Set amount: $100
# Set thresholds: 50%, 75%, 100%
# Set notification channel: billing-alerts topic
# Verify
$ gcloud pubsub topics list | grep billing-alerts
name: projects/my-project/topics/billing-alerts
Exercise 2: Find and Clean Up Idle Resources
Identify idle VMs, unattached disks, and unused static IPs.
- List all VM rightsizing recommendations
- Find unattached persistent disks
- Find unused static IP addresses
- Calculate potential monthly savings
Show Answer
# List VM recommendations
$ gcloud recommender recommendations list \
--project=my-project \
--location=us-central1-a \
--recommender=google.compute.instance.IdleResourceRecommender
# Find unattached disks
$ gcloud compute disks list \
--filter="NOT users:*" \
--format="table(name,zone,sizeGb,type)"
# Find unused static IPs ($7.30/month each)
$ gcloud compute addresses list \
--filter="status=RESERVED" \
--format="table(name,region,address)"
# Clean up
$ gcloud compute disks delete DISK_NAME --zone=ZONE --quiet
$ gcloud compute addresses delete IP_NAME --region=REGION --quiet
Exercise 3: Create a Spot VM Pool for CI/CD
Set up a managed instance group using Spot VMs for CI/CD build agents.
- Create an instance template with Spot provisioning
- Create a managed instance group with 3 Spot instances
- Enable autoscaling between 1 and 10 instances
- Compare the cost with regular VMs
Show Answer
# Create Spot instance template
$ gcloud compute instance-templates create ci-spot-template \
--machine-type=e2-standard-4 \
--provisioning-model=SPOT \
--instance-termination-action=DELETE \
--image-family=debian-12 \
--image-project=debian-cloud \
--boot-disk-size=50GB \
--metadata=startup-script='#!/bin/bash
apt-get update && apt-get install -y docker.io
systemctl start docker'
# Create MIG
$ gcloud compute instance-groups managed create ci-build-pool \
--zone=us-central1-a \
--template=ci-spot-template \
--size=3
# Enable autoscaling
$ gcloud compute instance-groups managed set-autoscaling ci-build-pool \
--zone=us-central1-a \
--min-num-replicas=1 \
--max-num-replicas=10 \
--target-cpu-utilization=0.7
# Cost comparison (e2-standard-4):
# On-demand: ~$97/month × 3 = $291/month
# Spot: ~$29/month × 3 = $87/month
# Savings: ~$204/month (70% reduction)
Exercise 4: Set Up Cloud Storage Lifecycle Policies
Configure lifecycle rules to automatically move objects to cheaper storage classes.
- Create a storage bucket
- Apply lifecycle rules: Nearline after 30 days, Coldline after 90 days, delete after 365 days
- Verify the lifecycle configuration
Show Answer
# Create bucket
$ gcloud storage buckets create gs://my-data-lifecycle-demo \
--location=us-central1 \
--default-storage-class=STANDARD
# Create lifecycle rules file
$ cat > lifecycle.json << 'EOF'
{
"lifecycle": {
"rule": [
{
"action": {"type": "SetStorageClass", "storageClass": "NEARLINE"},
"condition": {"age": 30, "matchesStorageClass": ["STANDARD"]}
},
{
"action": {"type": "SetStorageClass", "storageClass": "COLDLINE"},
"condition": {"age": 90, "matchesStorageClass": ["NEARLINE"]}
},
{
"action": {"type": "Delete"},
"condition": {"age": 365}
}
]
}
}
EOF
# Apply lifecycle rules
$ gcloud storage buckets update gs://my-data-lifecycle-demo \
--lifecycle-file=lifecycle.json
# Verify
$ gcloud storage buckets describe gs://my-data-lifecycle-demo \
--format="json(lifecycle)"
# Cleanup
$ gcloud storage rm -r gs://my-data-lifecycle-demo
Exercise 5: Query Billing Data in BigQuery
Write BigQuery SQL queries to analyze costs by service, project, and label.
- Write a query for top 5 most expensive services this month
- Write a query for daily cost trend (last 7 days)
- Write a query to find cost by team label
Show Answer
-- Top 5 most expensive services this month
SELECT
service.description AS service,
ROUND(SUM(cost), 2) AS total_cost
FROM `billing_data.gcp_billing_export_v1_XXXXX`
WHERE invoice.month = FORMAT_DATE('%Y%m', CURRENT_DATE())
GROUP BY service
ORDER BY total_cost DESC
LIMIT 5;
-- Daily cost trend (last 7 days)
SELECT
DATE(usage_start_time) AS date,
ROUND(SUM(cost), 2) AS daily_cost
FROM `billing_data.gcp_billing_export_v1_XXXXX`
WHERE usage_start_time >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY date
ORDER BY date DESC;
-- Cost by team label
SELECT
(SELECT value FROM UNNEST(labels) WHERE key = 'team') AS team,
ROUND(SUM(cost), 2) AS total_cost
FROM `billing_data.gcp_billing_export_v1_XXXXX`
WHERE invoice.month = FORMAT_DATE('%Y%m', CURRENT_DATE())
GROUP BY team
HAVING team IS NOT NULL
ORDER BY total_cost DESC;
Cleanup
# Delete Spot instance group
$ gcloud compute instance-groups managed delete ci-build-pool \
--zone=us-central1-a --quiet
# Delete instance template
$ gcloud compute instance-templates delete ci-spot-template --quiet
# Delete lifecycle demo bucket
$ gcloud storage rm -r gs://my-data-lifecycle-demo
# Delete Pub/Sub topic
$ gcloud pubsub topics delete billing-alerts
Next Chapter → Practice Projects