GCP for DevOps — Resource Labels & Governance

3 minute read

Resource Labels & Governance

Labels are key-value pairs attached to GCP resources that enable cost allocation, automation, and governance. Combined with organization policies and asset inventory, labels form the backbone of cloud resource management at scale.

Labeling Strategy

Label Taxonomy:
┌──────────────────────────────────────────────────────────┐
│  Resource Labels                                          │
│                                                           │
│  Business Labels         Technical Labels                 │
│  ┌──────────────────┐   ┌──────────────────────────┐    │
│  │  team=platform    │   │  env=prod                 │    │
│  │  cost-center=1234 │   │  app=web-api              │    │
│  │  owner=alice      │   │  component=frontend       │    │
│  │  department=eng   │   │  managed-by=terraform     │    │
│  └──────────────────┘   └──────────────────────────┘    │
│                                                           │
│  Operational Labels      Security Labels                  │
│  ┌──────────────────┐   ┌──────────────────────────┐    │
│  │  backup=daily     │   │  data-class=confidential  │    │
│  │  patch-group=a    │   │  compliance=pci           │    │
│  │  auto-delete=true │   │  encryption=cmek          │    │
│  └──────────────────┘   └──────────────────────────┘    │
└──────────────────────────────────────────────────────────┘

Apply Labels to Resources

# Label a Compute Engine instance
$ gcloud compute instances update web-server-1 \
    --zone=us-central1-a \
    --update-labels=team=platform,env=prod,app=web-api,cost-center=eng-1234
Updated [web-server-1].

# Label a GKE cluster
$ gcloud container clusters update production \
    --zone=us-central1-a \
    --update-labels=team=platform,env=prod
Updating production...done.

# Label a Cloud Storage bucket
$ gcloud storage buckets update gs://my-data-bucket \
    --update-labels=team=data,env=prod,data-class=internal

# Label a Cloud SQL instance
$ gcloud sql instances patch my-db \
    --database-flags="" \
    --update-labels=team=backend,env=prod

List Resources by Label

# Find all production VMs
$ gcloud compute instances list \
    --filter="labels.env=prod" \
    --format="table(name,zone,machineType,labels)"
NAME            ZONE            MACHINE_TYPE    LABELS
web-server-1    us-central1-a   e2-standard-2   env=prod,team=platform
api-server-1    us-central1-b   e2-standard-4   env=prod,team=backend

# Find all resources owned by a team
$ gcloud compute instances list --filter="labels.team=platform"
$ gcloud container clusters list --filter="resourceLabels.team=platform"
$ gcloud sql instances list --filter="settings.userLabels.team=platform"

Enforce Labels with Organization Policies

Use a custom organization policy or a Cloud Function to enforce labeling:

# label_enforcer.py — Cloud Function triggered by Cloud Asset Inventory
from google.cloud import asset_v1
from google.cloud import compute_v1

REQUIRED_LABELS = ['team', 'env', 'cost-center']

def check_labels(event, context):
    """Check that new resources have required labels."""
    asset = event.get('asset', {})
    resource = asset.get('resource', {})
    labels = resource.get('data', {}).get('labels', {})
    
    missing = [l for l in REQUIRED_LABELS if l not in labels]
    
    if missing:
        resource_name = asset.get('name', 'unknown')
        print(f"VIOLATION: {resource_name} missing labels: {missing}")
        # Send Slack alert or create ticket
        send_alert(resource_name, missing)

Cloud Asset Inventory for Governance

# Search for all resources without the 'team' label
$ gcloud asset search-all-resources \
    --scope=projects/my-project \
    --query="NOT labels.team:*" \
    --asset-types="compute.googleapis.com/Instance" \
    --format="table(name,assetType,labels)"

# Export all resources with their labels to BigQuery
$ gcloud asset export \
    --project=my-project \
    --output-bigquery-force \
    --output-bigquery-dataset=asset_inventory \
    --output-bigquery-table=resources \
    --content-type=resource
Export in progress...done.

# Query unlabeled resources in BigQuery
# SELECT name, asset_type FROM asset_inventory.resources
# WHERE labels IS NULL OR ARRAY_LENGTH(labels) = 0

Label-Based Cost Reports

-- Cost by team label (BigQuery billing export)
SELECT
  (SELECT value FROM UNNEST(labels) WHERE key = 'team') AS team,
  (SELECT value FROM UNNEST(labels) WHERE key = 'env') AS environment,
  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, environment
ORDER BY total_cost DESC;

Label-Based Automation

# Auto-stop dev VMs at night (Cloud Scheduler + Function)
# The function stops all VMs with label env=dev

# Schedule: Every weekday at 8 PM
$ gcloud scheduler jobs create http stop-dev-vms \
    --schedule="0 20 * * 1-5" \
    --uri="https://REGION-PROJECT.cloudfunctions.net/stop-dev-vms" \
    --http-method=POST \
    --oidc-service-account-email=scheduler-sa@PROJECT.iam.gserviceaccount.com

# Schedule: Every weekday at 8 AM (restart)
$ gcloud scheduler jobs create http start-dev-vms \
    --schedule="0 8 * * 1-5" \
    --uri="https://REGION-PROJECT.cloudfunctions.net/start-dev-vms" \
    --http-method=POST \
    --oidc-service-account-email=scheduler-sa@PROJECT.iam.gserviceaccount.com

Labeling Best Practices

Practice Example Benefit
Use lowercase keys team not Team Consistency
Use hyphens in keys cost-center not cost_center GCP convention
Keep values short prod not production-environment Readability
Standardize values prod/staging/dev Filtering accuracy
Document label taxonomy Wiki/README Team alignment
Automate enforcement Org policy + Cloud Function Compliance
Review regularly Monthly audit Remove stale labels

Common Mistakes

Mistake Impact Fix
No labeling standard Inconsistent cost attribution Document and enforce taxonomy
Labels applied inconsistently Inaccurate reports Automate with Terraform/IaC
Too many labels Complexity, hard to manage Limit to 5-8 required labels
Not labeling IaC resources Terraform resources unlabeled Add labels block to all resources

Quick Reference

Task Command
Add labels to VM gcloud compute instances update VM --update-labels=KEY=VALUE
Remove labels gcloud compute instances update VM --remove-labels=KEY
Filter by label gcloud compute instances list --filter="labels.KEY=VALUE"
Search unlabeled resources gcloud asset search-all-resources --query="NOT labels.KEY:*"
Export assets to BigQuery gcloud asset export --output-bigquery-dataset=DATASET

Next → Practice Exercises

Updated: