--- name: gcp-services description: Google Cloud Platform service patterns, IAM best practices, and common architectures. Use when designing or implementing GCP infrastructure. --- # GCP Services Skill ## Common Architecture Patterns ### Web Application (Cloud Run + Cloud SQL) ``` ┌─────────────────────────────────────────────────────────────┐ │ VPC │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ Public Subnet ││ │ │ ┌─────────────┐ ┌─────────────┐ ││ │ │ │ Cloud │ │ Cloud │ ││ │ │ │ Load │ │ NAT │ ││ │ │ │ Balancing │ │ │ ││ │ │ └──────┬──────┘ └──────┬──────┘ ││ │ └─────────┼───────────────────────────────────┼───────────┘│ │ │ │ │ │ ┌─────────┼───────────────────────────────────┼───────────┐│ │ │ │ Private Subnet │ ││ │ │ ┌──────▼──────┐ ┌───────▼─────┐ ││ │ │ │ Cloud Run │ │ Cloud SQL │ ││ │ │ │ (Service) │───────────────────▶│ PostgreSQL │ ││ │ │ └─────────────┘ └─────────────┘ ││ │ └─────────────────────────────────────────────────────────┘│ └─────────────────────────────────────────────────────────────┘ ``` ### Serverless (Cloud Functions + API Gateway) ``` ┌────────────┐ ┌─────────────┐ ┌─────────────┐ │ Cloud │────▶│ API │────▶│ Cloud │ │ CDN │ │ Gateway │ │ Functions │ └────────────┘ └─────────────┘ └──────┬──────┘ │ ┌──────────────────────────┼──────────────┐ │ │ │ ┌──────▼─────┐ ┌─────────┐ ┌────▼────┐ │ Firestore │ │ Cloud │ │ Secret │ └────────────┘ │ Storage │ │ Manager │ └─────────┘ └─────────┘ ``` ## IAM Best Practices ### Service Account with Least Privilege ```yaml # Service account for Cloud Run service resource "google_service_account" "app_sa" { account_id = "my-app-service" display_name = "My App Service Account" } # Grant specific permissions resource "google_project_iam_member" "app_storage" { project = var.project_id role = "roles/storage.objectViewer" member = "serviceAccount:${google_service_account.app_sa.email}" } resource "google_project_iam_member" "app_secrets" { project = var.project_id role = "roles/secretmanager.secretAccessor" member = "serviceAccount:${google_service_account.app_sa.email}" } ``` ### Workload Identity Federation ```python # Python - google-auth with workload identity from google.auth import default from google.cloud import storage # Automatically uses workload identity when on GKE/Cloud Run credentials, project = default() # Access Cloud Storage storage_client = storage.Client(credentials=credentials, project=project) bucket = storage_client.bucket("my-bucket") ``` ## Secret Manager Patterns ### Accessing Secrets ```python from google.cloud import secretmanager def get_secret(project_id: str, secret_id: str, version: str = "latest") -> str: """Access a secret from Secret Manager.""" client = secretmanager.SecretManagerServiceClient() name = f"projects/{project_id}/secrets/{secret_id}/versions/{version}" response = client.access_secret_version(request={"name": name}) return response.payload.data.decode("UTF-8") # Usage db_password = get_secret("my-project", "database-password") ``` ```typescript // TypeScript - @google-cloud/secret-manager import { SecretManagerServiceClient } from "@google-cloud/secret-manager"; async function getSecret( projectId: string, secretId: string, version: string = "latest" ): Promise { const client = new SecretManagerServiceClient(); const name = `projects/${projectId}/secrets/${secretId}/versions/${version}`; const [response] = await client.accessSecretVersion({ name }); return response.payload?.data?.toString() || ""; } ``` ### Cloud Run with Secret References ```yaml # Cloud Run service with secret environment variables apiVersion: serving.knative.dev/v1 kind: Service metadata: name: my-service spec: template: spec: containers: - image: gcr.io/my-project/my-app env: - name: DATABASE_PASSWORD valueFrom: secretKeyRef: name: database-password key: latest ``` ## Cloud Storage Patterns ### Signed URLs ```python from datetime import timedelta from google.cloud import storage def generate_signed_url( bucket_name: str, blob_name: str, expiration_minutes: int = 60 ) -> str: """Generate a signed URL for downloading a blob.""" storage_client = storage.Client() bucket = storage_client.bucket(bucket_name) blob = bucket.blob(blob_name) url = blob.generate_signed_url( version="v4", expiration=timedelta(minutes=expiration_minutes), method="GET", ) return url ``` ### Upload with Resumable Upload ```python from google.cloud import storage def upload_large_file( bucket_name: str, source_file: str, destination_blob: str ) -> str: """Upload a large file using resumable upload.""" storage_client = storage.Client() bucket = storage_client.bucket(bucket_name) blob = bucket.blob(destination_blob) # For files > 5MB, uses resumable upload automatically blob.upload_from_filename(source_file) return f"gs://{bucket_name}/{destination_blob}" ``` ## Firestore Patterns ### Async Operations ```python from google.cloud import firestore from google.cloud.firestore_v1.async_client import AsyncClient async def get_firestore_client() -> AsyncClient: """Create async Firestore client.""" return AsyncClient() async def get_user(user_id: str) -> dict | None: """Get a user document from Firestore.""" db = await get_firestore_client() doc_ref = db.collection("users").document(user_id) doc = await doc_ref.get() if doc.exists: return doc.to_dict() return None async def query_users_by_status(status: str) -> list[dict]: """Query users by status.""" db = await get_firestore_client() query = db.collection("users").where("status", "==", status) docs = await query.get() return [doc.to_dict() for doc in docs] ``` ### Transaction Pattern ```python from google.cloud import firestore def transfer_credits( from_user_id: str, to_user_id: str, amount: int ) -> bool: """Transfer credits between users atomically.""" db = firestore.Client() @firestore.transactional def update_in_transaction(transaction): from_ref = db.collection("users").document(from_user_id) to_ref = db.collection("users").document(to_user_id) from_snapshot = from_ref.get(transaction=transaction) to_snapshot = to_ref.get(transaction=transaction) from_credits = from_snapshot.get("credits") if from_credits < amount: raise ValueError("Insufficient credits") transaction.update(from_ref, {"credits": from_credits - amount}) transaction.update(to_ref, {"credits": to_snapshot.get("credits") + amount}) return True transaction = db.transaction() return update_in_transaction(transaction) ``` ## Cloud Functions Patterns ### HTTP Function with Validation ```python import functions_framework from flask import jsonify, Request from pydantic import BaseModel, ValidationError class CreateOrderRequest(BaseModel): customer_id: str items: list[dict] total: float @functions_framework.http def create_order(request: Request): """HTTP Cloud Function for creating orders.""" try: body = request.get_json(silent=True) if not body: return jsonify({"error": "Request body required"}), 400 order_request = CreateOrderRequest(**body) # Process order... result = process_order(order_request) return jsonify(result.dict()), 201 except ValidationError as e: return jsonify({"error": e.errors()}), 400 except Exception as e: print(f"Error: {e}") return jsonify({"error": "Internal server error"}), 500 ``` ### Pub/Sub Triggered Function ```python import base64 import functions_framework from cloudevents.http import CloudEvent @functions_framework.cloud_event def process_message(cloud_event: CloudEvent): """Process Pub/Sub message.""" # Decode the Pub/Sub message data = base64.b64decode(cloud_event.data["message"]["data"]).decode() print(f"Received message: {data}") # Process the message process_event(data) ``` ## Cloud Run Patterns ### Service with Health Checks ```python from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class HealthResponse(BaseModel): status: str version: str @app.get("/health", response_model=HealthResponse) async def health_check(): """Health check endpoint for Cloud Run.""" return HealthResponse(status="healthy", version="1.0.0") @app.get("/ready") async def readiness_check(): """Readiness check - verify dependencies.""" # Check database connection, etc. await check_database_connection() return {"status": "ready"} ``` ### Cloud Run Job ```python # main.py for Cloud Run Job import os from google.cloud import bigquery def main(): """Main entry point for Cloud Run Job.""" task_index = int(os.environ.get("CLOUD_RUN_TASK_INDEX", 0)) task_count = int(os.environ.get("CLOUD_RUN_TASK_COUNT", 1)) print(f"Processing task {task_index} of {task_count}") # Process batch based on task index process_batch(task_index, task_count) if __name__ == "__main__": main() ``` ## Cloud Logging ### Structured Logging ```python import json import logging from google.cloud import logging as cloud_logging # Setup Cloud Logging client = cloud_logging.Client() client.setup_logging() logger = logging.getLogger(__name__) def log_with_trace(message: str, trace_id: str, **kwargs): """Log with trace ID for request correlation.""" log_entry = { "message": message, "logging.googleapis.com/trace": f"projects/{project_id}/traces/{trace_id}", **kwargs } logger.info(json.dumps(log_entry)) # Usage log_with_trace( "Order processed", trace_id="abc123", order_id="order-456", customer_id="cust-789" ) ``` ### Custom Metrics ```python from google.cloud import monitoring_v3 def write_metric(project_id: str, metric_type: str, value: float): """Write a custom metric to Cloud Monitoring.""" client = monitoring_v3.MetricServiceClient() project_name = f"projects/{project_id}" series = monitoring_v3.TimeSeries() series.metric.type = f"custom.googleapis.com/{metric_type}" series.resource.type = "global" now = time.time() seconds = int(now) nanos = int((now - seconds) * 10**9) interval = monitoring_v3.TimeInterval( {"end_time": {"seconds": seconds, "nanos": nanos}} ) point = monitoring_v3.Point( {"interval": interval, "value": {"double_value": value}} ) series.points = [point] client.create_time_series(name=project_name, time_series=[series]) # Usage write_metric("my-project", "orders/processed", 1.0) ``` ## CLI Commands ```bash # Authentication gcloud auth login gcloud config set project my-project gcloud config list # Compute gcloud compute instances list gcloud compute ssh my-instance # Cloud Run gcloud run services list gcloud run deploy my-service --image gcr.io/my-project/my-app gcloud run services describe my-service # Cloud Functions gcloud functions list gcloud functions deploy my-function --runtime python311 --trigger-http gcloud functions logs read my-function # Secret Manager gcloud secrets list gcloud secrets create my-secret --data-file=secret.txt gcloud secrets versions access latest --secret=my-secret # Cloud Storage gsutil ls gs://my-bucket/ gsutil cp local-file.txt gs://my-bucket/ gsutil signurl -d 1h key.json gs://my-bucket/file.txt # Firestore gcloud firestore databases list gcloud firestore export gs://my-bucket/firestore-backup # Logging gcloud logging read "resource.type=cloud_run_revision" --limit=10 ``` ## Security Checklist - [ ] Use Service Accounts with least privilege - [ ] Enable VPC Service Controls for sensitive data - [ ] Use Secret Manager for all secrets - [ ] Enable Cloud Audit Logs - [ ] Configure Identity-Aware Proxy for internal apps - [ ] Use Private Google Access for GCE instances - [ ] Enable Binary Authorization for GKE - [ ] Configure Cloud Armor for DDoS protection - [ ] Use Customer-Managed Encryption Keys (CMEK) where required - [ ] Enable Security Command Center