GCP Deployment Guide

This guide covers deploying AgentWeave agents to Google Cloud Platform using GKE with Workload Identity and native GCP integrations.

Table of Contents

  1. GCP Deployment Guide
    1. Prerequisites
    2. Architecture on GCP
    3. GKE Cluster Setup
      1. Create Cluster with gcloud
      2. Terraform Configuration
    4. Workload Identity Configuration
      1. Enable Workload Identity on Cluster
      2. Create Google Service Account
      3. Bind KSA to GSA
      4. ServiceAccount YAML
    5. Secret Manager Integration
      1. Create Secrets
      2. Using External Secrets Operator
    6. Cloud Logging Integration
      1. Configure Logging
      2. Custom Log Filters
    7. Cloud Monitoring
      1. Enable Managed Prometheus
      2. PodMonitoring for Agents
      3. Create Alerting Policies
    8. SPIRE on GCP
      1. SPIRE with GCP Node Attestation
      2. Persistent Disk for SPIRE
    9. Load Balancing
      1. Internal Load Balancer
      2. GKE Ingress with HTTPS
    10. Helm Deployment on GKE
    11. Terraform Complete Example
    12. Monitoring Dashboards
      1. Create Custom Dashboard
    13. Best Practices for GCP
    14. Troubleshooting
      1. Workload Identity Not Working
      2. Secret Manager Access Issues
    15. Next Steps

Prerequisites

  • GCP Project with billing enabled
  • gcloud CLI configured (gcloud auth login)
  • kubectl 1.24+
  • Helm 3.8+
  • Appropriate IAM permissions

Architecture on GCP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
┌─────────────────────────────────────────────────────────────┐
│                    Google Cloud Platform                    │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  VPC Network                                         │   │
│  │                                                      │   │
│  │  ┌────────────────┐  ┌────────────────┐             │   │
│  │  │ Subnet (Zone-A)│  │ Subnet (Zone-B)│             │   │
│  │  │                │  │                │             │   │
│  │  │  ┌──────────┐  │  │  ┌──────────┐  │             │   │
│  │  │  │   GKE    │  │  │  │   GKE    │  │             │   │
│  │  │  │  Nodes   │  │  │  │  Nodes   │  │             │   │
│  │  │  │          │  │  │  │          │  │             │   │
│  │  │  │ ┌──────┐ │  │  │  │ ┌──────┐ │  │             │   │
│  │  │  │ │Agent │ │  │  │  │ │Agent │ │  │             │   │
│  │  │  │ │ Pods │ │  │  │  │ │ Pods │ │  │             │   │
│  │  │  │ └──┬───┘ │  │  │  │ └──┬───┘ │  │             │   │
│  │  │  └────┼─────┘  │  │  └────┼─────┘  │             │   │
│  │  └───────┼────────┘  └───────┼────────┘             │   │
│  │          │                   │                      │   │
│  │          └───────┬───────────┘                      │   │
│  │                  │                                  │   │
│  │        ┌─────────┴─────────┐                        │   │
│  │        │  Cloud Load Bal.  │                        │   │
│  │        └───────────────────┘                        │   │
│  └──────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐     │
│  │   Secret     │  │  Cloud       │  │  Workload    │     │
│  │   Manager    │  │  Logging     │  │  Identity    │     │
│  └──────────────┘  └──────────────┘  └──────────────┘     │
└─────────────────────────────────────────────────────────────┘

GKE Cluster Setup

Create Cluster with gcloud

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# Set project and region
export PROJECT_ID=my-gcp-project
export REGION=us-central1
export CLUSTER_NAME=agentweave-cluster

gcloud config set project $PROJECT_ID

# Create VPC
gcloud compute networks create agentweave-vpc \
  --subnet-mode=custom \
  --bgp-routing-mode=regional

gcloud compute networks subnets create agentweave-subnet \
  --network=agentweave-vpc \
  --region=$REGION \
  --range=10.0.0.0/20 \
  --secondary-range pods=10.4.0.0/14 \
  --secondary-range services=10.0.16.0/20

# Create GKE cluster with Workload Identity
gcloud container clusters create $CLUSTER_NAME \
  --region=$REGION \
  --network=agentweave-vpc \
  --subnetwork=agentweave-subnet \
  --cluster-secondary-range-name=pods \
  --services-secondary-range-name=services \
  --enable-ip-alias \
  --enable-stackdriver-kubernetes \
  --enable-cloud-logging \
  --enable-cloud-monitoring \
  --workload-pool=$PROJECT_ID.svc.id.goog \
  --enable-autoscaling \
  --min-nodes=2 \
  --max-nodes=10 \
  --num-nodes=3 \
  --machine-type=e2-standard-4 \
  --disk-size=100 \
  --disk-type=pd-standard \
  --enable-shielded-nodes \
  --shielded-secure-boot \
  --shielded-integrity-monitoring \
  --addons=HorizontalPodAutoscaling,HttpLoadBalancing,GcePersistentDiskCsiDriver \
  --release-channel=regular

# Get credentials
gcloud container clusters get-credentials $CLUSTER_NAME --region=$REGION

Terraform Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# main.tf
module "gke" {
  source  = "terraform-google-modules/kubernetes-engine/google"
  version = "~> 29.0"

  project_id        = var.project_id
  name              = "agentweave-cluster"
  region            = var.region
  regional          = true
  kubernetes_version = "1.28"

  network           = module.vpc.network_name
  subnetwork        = module.vpc.subnets_names[0]
  ip_range_pods     = "pods"
  ip_range_services = "services"

  # Enable Workload Identity
  identity_namespace = "${var.project_id}.svc.id.goog"

  # Node pools
  node_pools = [
    {
      name               = "agentweave-pool"
      machine_type       = "e2-standard-4"
      min_count          = 2
      max_count          = 10
      initial_node_count = 3
      disk_size_gb       = 100
      disk_type          = "pd-standard"
      auto_repair        = true
      auto_upgrade       = true
      preemptible        = false

      node_metadata = "GKE_METADATA"
      workload_metadata_config = {
        mode = "GKE_METADATA"
      }
    }
  ]

  # Monitoring and logging
  monitoring_enable_managed_prometheus = true
  logging_enabled_components = ["SYSTEM_COMPONENTS", "WORKLOADS"]
  monitoring_enabled_components = ["SYSTEM_COMPONENTS"]

  # Security
  enable_shielded_nodes = true
  master_authorized_networks = [
    {
      cidr_block   = "0.0.0.0/0"
      display_name = "All"
    }
  ]
}

# VPC Module
module "vpc" {
  source  = "terraform-google-modules/network/google"
  version = "~> 8.0"

  project_id   = var.project_id
  network_name = "agentweave-vpc"
  routing_mode = "REGIONAL"

  subnets = [
    {
      subnet_name           = "agentweave-subnet"
      subnet_ip             = "10.0.0.0/20"
      subnet_region         = var.region
      subnet_private_access = true
    }
  ]

  secondary_ranges = {
    agentweave-subnet = [
      {
        range_name    = "pods"
        ip_cidr_range = "10.4.0.0/14"
      },
      {
        range_name    = "services"
        ip_cidr_range = "10.0.16.0/20"
      }
    ]
  }
}

Workload Identity Configuration

Enable Workload Identity on Cluster

1
2
3
4
# Enable Workload Identity (if not done during cluster creation)
gcloud container clusters update $CLUSTER_NAME \
  --region=$REGION \
  --workload-pool=$PROJECT_ID.svc.id.goog

Create Google Service Account

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Create GSA
gcloud iam service-accounts create agentweave-agent \
  --display-name="AgentWeave Agent Service Account"

# Grant permissions
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:agentweave-agent@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:agentweave-agent@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/logging.logWriter"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:agentweave-agent@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/monitoring.metricWriter"

Bind KSA to GSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Create namespace
kubectl create namespace agentweave

# Create Kubernetes Service Account
kubectl create serviceaccount agentweave-agent -n agentweave

# Bind KSA to GSA
gcloud iam service-accounts add-iam-policy-binding \
  agentweave-agent@$PROJECT_ID.iam.gserviceaccount.com \
  --role roles/iam.workloadIdentityUser \
  --member "serviceAccount:$PROJECT_ID.svc.id.goog[agentweave/agentweave-agent]"

# Annotate KSA
kubectl annotate serviceaccount agentweave-agent \
  -n agentweave \
  iam.gke.io/gcp-service-account=agentweave-agent@$PROJECT_ID.iam.gserviceaccount.com

ServiceAccount YAML

1
2
3
4
5
6
7
8
# serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: agentweave-agent
  namespace: agentweave
  annotations:
    iam.gke.io/gcp-service-account: agentweave-agent@PROJECT_ID.iam.gserviceaccount.com

Secret Manager Integration

Create Secrets

1
2
3
4
5
6
7
8
9
# Create secret
echo -n "my-api-key-value" | gcloud secrets create agentweave-api-key \
  --data-file=- \
  --replication-policy=automatic

# Grant access to service account
gcloud secrets add-iam-policy-binding agentweave-api-key \
  --member="serviceAccount:agentweave-agent@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

Using External Secrets Operator

Install External Secrets Operator:

1
2
3
4
5
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets \
  external-secrets/external-secrets \
  -n external-secrets-system \
  --create-namespace

Create SecretStore:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# secret-store.yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: gcpsm-secret-store
  namespace: agentweave
spec:
  provider:
    gcpsm:
      projectID: "PROJECT_ID"
      auth:
        workloadIdentity:
          clusterLocation: us-central1
          clusterName: agentweave-cluster
          serviceAccountRef:
            name: agentweave-agent

Create ExternalSecret:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: agentweave-secrets
  namespace: agentweave
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: gcpsm-secret-store
    kind: SecretStore
  target:
    name: agentweave-secrets
    creationPolicy: Owner
  data:
    - secretKey: api-key
      remoteRef:
        key: agentweave-api-key
    - secretKey: database-url
      remoteRef:
        key: agentweave-database-url

Cloud Logging Integration

Configure Logging

Cloud Logging is enabled by default on GKE. Configure structured logging:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# agent-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: agentweave-agent
  namespace: agentweave
spec:
  template:
    spec:
      containers:
        - name: agent
          env:
            # Enable structured JSON logging
            - name: AGENTWEAVE_LOG_FORMAT
              value: "json"
            # Set log level
            - name: AGENTWEAVE_LOG_LEVEL
              value: "INFO"
            # Add GCP metadata
            - name: GCP_PROJECT
              value: "PROJECT_ID"
            - name: GKE_CLUSTER
              value: "agentweave-cluster"

Custom Log Filters

Create log-based metrics:

1
2
3
4
5
6
# Create log-based metric
gcloud logging metrics create agentweave_errors \
  --description="AgentWeave error count" \
  --log-filter='resource.type="k8s_container"
  resource.labels.namespace_name="agentweave"
  severity="ERROR"'

Cloud Monitoring

Enable Managed Prometheus

1
2
3
4
# Enable Managed Prometheus
gcloud container clusters update $CLUSTER_NAME \
  --region=$REGION \
  --enable-managed-prometheus

PodMonitoring for Agents

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# pod-monitoring.yaml
apiVersion: monitoring.gke.io/v1
kind: PodMonitoring
metadata:
  name: agentweave-agent-monitoring
  namespace: agentweave
spec:
  selector:
    matchLabels:
      app: agentweave-agent
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics

Create Alerting Policies

1
2
3
4
5
6
7
8
9
10
# Create alert policy for high CPU
gcloud alpha monitoring policies create \
  --notification-channels=CHANNEL_ID \
  --display-name="AgentWeave High CPU" \
  --condition-display-name="CPU above 80%" \
  --condition-threshold-value=0.8 \
  --condition-threshold-duration=300s \
  --condition-filter='resource.type="k8s_pod"
    resource.labels.namespace_name="agentweave"
    metric.type="kubernetes.io/pod/cpu/core_usage_time"'

SPIRE on GCP

SPIRE with GCP Node Attestation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# spire-server-config-gcp.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: spire-server
  namespace: spire-system
data:
  server.conf: |
    server {
        bind_address = "0.0.0.0"
        bind_port = "8081"
        trust_domain = "agentweave.io"
        data_dir = "/run/spire/data"
    }

    plugins {
        DataStore "sql" {
            plugin_data {
                database_type = "postgres"
                connection_string = "postgresql://spire:password@postgres:5432/spire"
            }
        }

        NodeAttestor "gcp_iit" {
            plugin_data {
                projectid_allow_list = ["PROJECT_ID"]
                use_instance_metadata = true
            }
        }

        KeyManager "memory" {
            plugin_data {}
        }
    }

Persistent Disk for SPIRE

1
2
3
4
5
6
7
8
9
10
11
12
13
# spire-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: spire-server-data
  namespace: spire-system
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: standard-rwo
  resources:
    requests:
      storage: 10Gi

Load Balancing

Internal Load Balancer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ilb-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: agentweave-ilb
  namespace: agentweave
  annotations:
    cloud.google.com/load-balancer-type: "Internal"
    networking.gke.io/load-balancer-type: "Internal"
spec:
  type: LoadBalancer
  loadBalancerIP: 10.0.1.100  # Optional: Reserve internal IP
  selector:
    app: agentweave-agent
  ports:
    - name: https
      port: 8443
      targetPort: 8443
      protocol: TCP

GKE Ingress with HTTPS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# managed-cert.yaml
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: agentweave-cert
  namespace: agentweave
spec:
  domains:
    - agents.agentweave.io

---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: agentweave-ingress
  namespace: agentweave
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.global-static-ip-name: "agentweave-ip"
    networking.gke.io/managed-certificates: "agentweave-cert"
    kubernetes.io/ingress.allow-http: "false"
spec:
  rules:
    - host: agents.agentweave.io
      http:
        paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: agentweave-agent
                port:
                  number: 8443

Reserve static IP:

1
2
3
gcloud compute addresses create agentweave-ip \
  --global \
  --ip-version IPV4

Helm Deployment on GKE

Create values file for GKE:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# gke-values.yaml
agent:
  name: "gke-agent"
  trustDomain: "agentweave.io"

# ServiceAccount with Workload Identity
serviceAccount:
  create: true
  annotations:
    iam.gke.io/gcp-service-account: agentweave-agent@PROJECT_ID.iam.gserviceaccount.com

# Use GCP Secret Manager
externalSecrets:
  enabled: true
  backend: gcpsm
  projectID: PROJECT_ID

# Cloud Logging
observability:
  logging:
    level: INFO
    format: json
    destination: stdout  # GKE forwards to Cloud Logging

# Monitoring
monitoring:
  enabled: true
  type: managed-prometheus

# Storage
persistence:
  enabled: true
  storageClass: standard-rwo
  size: 10Gi

# Networking
service:
  type: LoadBalancer
  annotations:
    cloud.google.com/load-balancer-type: "Internal"

# Node selector for specific node pool
nodeSelector:
  cloud.google.com/gke-nodepool: agentweave-pool

# Resources
resources:
  requests:
    cpu: 1000m
    memory: 1Gi
  limits:
    cpu: 4000m
    memory: 4Gi

Deploy:

1
2
3
4
helm install agentweave-agent agentweave/agentweave \
  -f gke-values.yaml \
  -n agentweave \
  --create-namespace

Terraform Complete Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# terraform/main.tf

# GKE Cluster
module "gke" {
  source = "./modules/gke"
  # ... (as shown earlier)
}

# Workload Identity
resource "google_service_account" "agentweave" {
  account_id   = "agentweave-agent"
  display_name = "AgentWeave Agent"
  project      = var.project_id
}

resource "google_project_iam_member" "agentweave_secrets" {
  project = var.project_id
  role    = "roles/secretmanager.secretAccessor"
  member  = "serviceAccount:${google_service_account.agentweave.email}"
}

resource "google_service_account_iam_member" "workload_identity" {
  service_account_id = google_service_account.agentweave.name
  role               = "roles/iam.workloadIdentityUser"
  member             = "serviceAccount:${var.project_id}.svc.id.goog[agentweave/agentweave-agent]"
}

# Kubernetes Service Account
resource "kubernetes_service_account" "agentweave" {
  metadata {
    name      = "agentweave-agent"
    namespace = "agentweave"
    annotations = {
      "iam.gke.io/gcp-service-account" = google_service_account.agentweave.email
    }
  }

  depends_on = [module.gke]
}

# Secret Manager Secrets
resource "google_secret_manager_secret" "api_key" {
  secret_id = "agentweave-api-key"
  project   = var.project_id

  replication {
    automatic = true
  }
}

resource "google_secret_manager_secret_version" "api_key" {
  secret      = google_secret_manager_secret.api_key.id
  secret_data = var.api_key
}

# Helm Release
resource "helm_release" "agentweave" {
  name       = "agentweave-agent"
  repository = "https://charts.agentweave.io"
  chart      = "agentweave"
  namespace  = "agentweave"

  values = [
    templatefile("${path.module}/values.yaml.tpl", {
      project_id        = var.project_id
      service_account   = kubernetes_service_account.agentweave.metadata[0].name
      trust_domain      = var.trust_domain
    })
  ]

  depends_on = [
    module.gke,
    google_service_account_iam_member.workload_identity
  ]
}

Monitoring Dashboards

Create Custom Dashboard

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# dashboard.json
{
  "displayName": "AgentWeave Agents",
  "mosaicLayout": {
    "columns": 12,
    "tiles": [
      {
        "width": 6,
        "height": 4,
        "widget": {
          "title": "CPU Usage",
          "xyChart": {
            "dataSets": [{
              "timeSeriesQuery": {
                "timeSeriesFilter": {
                  "filter": "resource.type=\"k8s_pod\" resource.labels.namespace_name=\"agentweave\"",
                  "aggregation": {
                    "alignmentPeriod": "60s",
                    "perSeriesAligner": "ALIGN_RATE"
                  }
                }
              }
            }]
          }
        }
      }
    ]
  }
}

Create dashboard:

1
gcloud monitoring dashboards create --config-from-file=dashboard.json

Best Practices for GCP

  1. Use Workload Identity: Always prefer Workload Identity over service account keys
  2. Enable Shielded Nodes: Use shielded GKE nodes for additional security
  3. Regional Clusters: Deploy regional clusters for high availability
  4. Managed Prometheus: Use GKE's Managed Prometheus for monitoring
  5. Secret Manager: Store all secrets in Secret Manager, not in code
  6. VPC-native Clusters: Always use VPC-native clusters with IP aliasing
  7. Binary Authorization: Enable for production workloads

Troubleshooting

Workload Identity Not Working

1
2
3
4
5
6
7
8
9
10
11
12
# Verify service account binding
gcloud iam service-accounts get-iam-policy \
  agentweave-agent@$PROJECT_ID.iam.gserviceaccount.com

# Check pod service account
kubectl describe pod -n agentweave -l app=agentweave-agent

# Test from pod
kubectl run -it --rm test --image=google/cloud-sdk:slim \
  --serviceaccount=agentweave-agent \
  -n agentweave \
  -- gcloud auth list

Secret Manager Access Issues

1
2
3
4
5
# Test secret access
gcloud secrets versions access latest --secret=agentweave-api-key

# Check IAM permissions
gcloud secrets get-iam-policy agentweave-api-key

Next Steps


Related Documentation: