Billing Hierarchy: Cost Attribution & Budget Management
Billing Fundamentals
Organization
├── Projects (tạo resources)
└── Billing Accounts (track costs)
Multiple projects → 1 billing account
1 project → Can link to 1 billing accountKey relationship:
- Project: Where resources run (compute, storage, etc.)
- Billing Account: Receives invoice, pays for all linked projects
Billing Account Structure
bash
# List billing accounts
gcloud billing accounts list
# Link project to billing account
gcloud billing projects link PROJECT_ID \
--billing-account=BILLING_ACCOUNT_ID
# See which billing account project is linked to
gcloud billing projects describe PROJECT_IDCost Attribution Models
Model 1: Per-Project Costs
Simplest: Each project = separate cost center
project-prod: $10,000/month
project-staging: $2,000/month
project-dev: $500/monthLimitation: Cannot attribute costs within project (e.g., which service costs most?)
Model 2: Per-Label Costs
More granular: Use labels for cost allocation
python
# Query costs by label
from google.cloud import bigquery
query = """
SELECT
labels.key,
labels.value,
SUM(cost) as total_cost
FROM `project.billing.gcp_billing_export_v1_XXXXXX`
WHERE DATE(usage_start_time) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY labels.key, labels.value
HAVING SUM(cost) > 100 -- Only show costs > $100
ORDER BY total_cost DESC
"""
results = bigquery.Client().query(query).result()
for row in results:
print(f"{row.key}={row.value}: ${row.total_cost:.2f}")Model 3: Chargeback
Charge teams for their resource usage:
python
def calculate_chargeback():
"""Monthly chargeback per cost-center"""
# Get costs by cost-center label
costs_by_center = query_costs_by_label("cost-center")
charges = {}
for cost_center, cost in costs_by_center.items():
team = get_team_for_cost_center(cost_center)
# Calculate departmental overhead (e.g., 5%)
overhead = cost * 0.05
total_charge = cost + overhead
charges[team] = {
"direct_cost": cost,
"overhead": overhead,
"total": total_charge
}
# Send invoices
for team, charges_detail in charges.items():
send_email(
to=f"finance-{team}@company.com",
subject=f"GCP Chargeback - {team}",
body=f"""
Direct costs: ${charges_detail['direct_cost']:.2f}
Overhead (5%): ${charges_detail['overhead']:.2f}
Total: ${charges_detail['total']:.2f}
"""
)Budget Alerts
Alert on budget exceeded
bash
# Create budget alert
gcloud billing budgets create \
--billing-account=BILLING_ACCOUNT_ID \
--display-name="Monthly budget limit" \
--budget-amount=5000 \
--threshold-rule=percent=50,spend_basis=current_spend \
--threshold-rule=percent=90,spend_basis=current_spend \
--threshold-rule=percent=100,spend_basis=current_spendCustom budget alerting via Pub/Sub
python
from google.cloud import pubsub_v1, monitoring_v3
def create_budget_alert():
"""Alert via Pub/Sub when budget exceeded"""
# Create budget
service = billingbudgets.BudgetServiceClient()
budget = billingbudgets.Budget(
display_name="Q1 2024 Budget",
budget_amount=billingbudgets.BudgetAmount(
specified_amount={"currency_code": "USD", "units": 10000}
),
threshold_rules=[
billingbudgets.ThresholdRule(percent_spend_basis=90),
billingbudgets.ThresholdRule(percent_spend_basis=100)
],
notifications_rule=billingbudgets.NotificationsRule(
pubsub_topic=f"projects/PROJECT_ID/topics/budget-alerts",
schema_version="1.0"
)
)
service.create_budget(
parent=f"billingAccounts/{BILLING_ACCOUNT_ID}",
budget=budget
)Cost Optimization
Identify expensive resources
sql
-- Find top 10 most expensive resources
SELECT
resource.name,
resource.labels.value as resource_label,
SUM(cost) as total_cost,
COUNT(*) as line_items
FROM `project.billing.gcp_billing_export_v1_XXXXXX`
WHERE DATE(usage_start_time) >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
GROUP BY resource.name, resource.labels.value
ORDER BY total_cost DESC
LIMIT 10;
-- Find unused resources
SELECT
resource.name,
COUNT(*) as usage_count
FROM `project.billing.gcp_billing_export_v1_XXXXXX`
WHERE DATE(usage_start_time) >= DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)
GROUP BY resource.name
HAVING COUNT(*) < 10 -- Very low usage
ORDER BY usage_count ASC;Reservation discounts
bash
# Get discount for reserved capacity (25-55% off on-demand)
# Compute Engine reservations
gcloud compute reservations create prod-vms \
--project=PROJECT_ID \
--zone=us-central1-a \
--vm-family=N1 \
--local-ssd=0 \
--accelerator-type=nvidia-tesla-k80 \
--accelerator-count=2 \
--vm-count=10
# BigQuery slots (annual commitment)
gcloud compute reservations create bigquery-annual \
--annual-commitmentMulti-Project Billing
Consolidated billing account
Organization
├── Prod Project
│ ├── VM: $5,000
│ └── Database: $3,000
├── Staging Project
│ └── VM: $500
└── Billing Account
├── Month 1: $8,500
├── Month 2: $9,200
└── Consolidated invoiceBenefits:
- Single invoice
- Shared discounts (volume discounts across projects)
- Centralized payment
- Easier reconciliation
Terraform Billing Management
hcl
# Terraform: Budget alert + chargeback automation
resource "google_billing_budget" "monthly_budget" {
billing_account = var.billing_account_id
display_name = "Monthly team budget"
budget_amount {
specified_amount {
currency_code = "USD"
units = "50000"
}
}
threshold_rules {
percent_spend_basis = 50
}
threshold_rules {
percent_spend_basis = 90
}
threshold_rules {
percent_spend_basis = 100
}
notifications_rule {
pubsub_topic = google_pubsub_topic.budget_alerts.id
schema_version = "1.0"
monitoring_notification_channels = [
google_monitoring_notification_channel.email.id
]
}
}
# Cloud Function: Triggered by budget alert
resource "google_cloudfunctions_function" "chargeback" {
name = "monthly-chargeback"
runtime = "python39"
entry_point = "process_budget_alert"
source_archive_bucket = google_storage_bucket.functions.name
source_archive_object = google_storage_bucket_object.chargeback_zip.name
event_trigger {
event_type = "google.pubsub.topic.publish"
resource = google_pubsub_topic.budget_alerts.id
}
}Anti-Patterns
| Anti-pattern | Problem | Solution |
|---|---|---|
| One billing account per project | Cannot see total org spending | Consolidated billing account |
| No cost tracking labels | Cannot attribute costs | Mandatory labels |
| No budget alerts | Overspending invisible | Set alerts at key thresholds |
| No chargeback | Teams waste resources | Implement cost allocation |
| Manual invoicing | Errors, delays | Automated chargeback |
| No cost optimization | Waste money on unused resources | Regular cost audits |