> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usechamber.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Google Cloud GKE

> Deploy a GPU-ready GKE cluster with Chamber on Google Cloud

The [`terraform-google-chamber-gke`](https://github.com/ChamberOrg/terraform-google-chamber-gke) module deploys a production-ready Google GKE cluster with GPU autoscaling, NVIDIA drivers, and the Chamber Agent — all in a single `terraform apply`.

## Prerequisites

<AccordionGroup>
  <Accordion title="Terraform >= 1.3.0">
    Install from [developer.hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install). Verify with `terraform version`.
  </Accordion>

  <Accordion title="gcloud CLI authenticated">
    Install the [gcloud CLI](https://cloud.google.com/sdk/docs/install) and authenticate:

    ```bash theme={null}
    gcloud auth login
    gcloud auth application-default login
    ```
  </Accordion>

  <Accordion title="Required GCP APIs enabled">
    Enable the required APIs in your project:

    ```bash theme={null}
    gcloud services enable \
      container.googleapis.com \
      compute.googleapis.com \
      iam.googleapis.com \
      --project=YOUR_PROJECT_ID
    ```
  </Accordion>

  <Accordion title="Chamber Console account">
    You need a cluster token and cluster ID from the [Chamber Console](https://app.usechamber.io). See [Getting a Cluster Token](/agent/installation#getting-a-cluster-token) for instructions.
  </Accordion>
</AccordionGroup>

## Quick Start

<Info>
  The GKE module requires explicit provider configuration because the `kubernetes`, `helm`, and `kubectl` providers need the cluster endpoint and credentials from the module outputs. The full configuration is shown below.
</Info>

<Steps>
  <Step title="Create main.tf">
    Create a new directory for your Terraform configuration and add a `main.tf` file:

    ```hcl theme={null}
    provider "google"     { project = var.gcp_project_id; region = var.gcp_region }
    provider "google-beta" { project = var.gcp_project_id; region = var.gcp_region }

    data "google_client_config" "default" {}

    provider "kubernetes" {
      host                   = "https://${module.chamber_gke.cluster_endpoint}"
      token                  = data.google_client_config.default.access_token
      cluster_ca_certificate = base64decode(module.chamber_gke.cluster_ca_certificate)
    }

    provider "helm" {
      kubernetes {
        host                   = "https://${module.chamber_gke.cluster_endpoint}"
        token                  = data.google_client_config.default.access_token
        cluster_ca_certificate = base64decode(module.chamber_gke.cluster_ca_certificate)
      }
    }

    provider "kubectl" {
      host                   = "https://${module.chamber_gke.cluster_endpoint}"
      token                  = data.google_client_config.default.access_token
      cluster_ca_certificate = base64decode(module.chamber_gke.cluster_ca_certificate)
      load_config_file       = false
    }

    module "chamber_gke" {
      source = "github.com/ChamberOrg/terraform-google-chamber-gke"

      gcp_project_id        = var.gcp_project_id
      gcp_region            = var.gcp_region
      cluster_name          = "my-gpu-cluster"
      chamber_cluster_token = var.chamber_cluster_token
      chamber_cluster_id    = var.chamber_cluster_id
    }

    variable "gcp_project_id" {
      type = string
    }

    variable "gcp_region" {
      type = string
    }

    variable "chamber_cluster_token" {
      type      = string
      sensitive = true
    }

    variable "chamber_cluster_id" {
      type = string
    }

    output "configure_kubectl" {
      value = module.chamber_gke.configure_kubectl
    }
    ```
  </Step>

  <Step title="Create terraform.tfvars">
    ```hcl theme={null}
    gcp_project_id        = "my-gcp-project"
    gcp_region            = "us-central1"
    chamber_cluster_token = "your-token-here"
    chamber_cluster_id    = "your-cluster-id"
    ```

    <Warning>
      Do not commit `terraform.tfvars` to version control. Add it to `.gitignore`. For CI/CD pipelines, use environment variables: `TF_VAR_chamber_cluster_token`.
    </Warning>
  </Step>

  <Step title="Deploy">
    ```bash theme={null}
    terraform init
    terraform plan
    terraform apply
    ```

    Deployment takes approximately **15-20 minutes**.
  </Step>

  <Step title="Configure kubectl">
    ```bash theme={null}
    $(terraform output -raw configure_kubectl)
    ```
  </Step>

  <Step title="Verify">
    ```bash theme={null}
    # Verify system nodes are ready
    kubectl get nodes -l purpose=system

    # Verify Karpenter is running
    kubectl get pods -n karpenter

    # Verify Chamber Agent is connected
    kubectl get pods -n chamber-system
    ```

    Your cluster should appear in the [Chamber Console](https://app.usechamber.io) under **Capacity Pools**.
  </Step>
</Steps>

## Using an Existing VPC

To deploy into an existing VPC instead of creating a new one:

```hcl theme={null}
module "chamber_gke" {
  source = "github.com/ChamberOrg/terraform-google-chamber-gke"

  gcp_project_id        = var.gcp_project_id
  gcp_region            = var.gcp_region
  cluster_name          = "my-gpu-cluster"
  chamber_cluster_token = var.chamber_cluster_token
  chamber_cluster_id    = var.chamber_cluster_id

  create_vpc        = false
  network_name      = "my-existing-vpc"
  subnetwork_name   = "my-existing-subnet"
  ip_range_pods     = "pods"
  ip_range_services = "services"
}
```

<Tip>
  The existing subnet must have secondary IP ranges named for pods and services. Cloud NAT must be configured for private node egress.
</Tip>

## Key Variables

The table below covers the most commonly configured variables. For the complete list, see the [module README on GitHub](https://github.com/ChamberOrg/terraform-google-chamber-gke#inputs).

### Required

| Variable                | Description                        | Type     |
| ----------------------- | ---------------------------------- | -------- |
| `gcp_project_id`        | GCP project ID                     | `string` |
| `cluster_name`          | Name of the GKE cluster            | `string` |
| `chamber_cluster_token` | Cluster token from Chamber Console | `string` |
| `chamber_cluster_id`    | Cluster ID from Chamber Console    | `string` |

### GCP

| Variable     | Description                                   | Default         |
| ------------ | --------------------------------------------- | --------------- |
| `gcp_region` | GCP region for the GKE cluster                | `"us-central1"` |
| `gcp_zones`  | Zones within the region (defaults to first 3) | `[]`            |

### VPC

| Variable          | Description                                               | Default         |
| ----------------- | --------------------------------------------------------- | --------------- |
| `create_vpc`      | Create a new VPC or use existing                          | `true`          |
| `network_name`    | Existing VPC name (required when `create_vpc = false`)    | `null`          |
| `subnetwork_name` | Existing subnet name (required when `create_vpc = false`) | `null`          |
| `vpc_cidr`        | CIDR block for new VPC primary subnet                     | `"10.0.0.0/16"` |

### GKE

| Variable                   | Description                                  | Default           |
| -------------------------- | -------------------------------------------- | ----------------- |
| `cluster_version`          | Kubernetes version                           | `"1.32"`          |
| `system_node_machine_type` | Machine type for system node pool            | `"e2-standard-4"` |
| `enable_private_endpoint`  | Private endpoint only (no public API access) | `false`           |

### GPU

| Variable                      | Description                           | Default                                                 |
| ----------------------------- | ------------------------------------- | ------------------------------------------------------- |
| `create_default_gpu_nodepool` | Create Terraform-managed GPU NodePool | `false`                                                 |
| `gpu_machine_families`        | GPU machine families for NodePool     | `["a2", "g2", "a3"]`                                    |
| `gpu_accelerator_types`       | GPU accelerator types                 | `["nvidia-l4", "nvidia-a100-80gb", "nvidia-h100-80gb"]` |
| `capacity_types`              | Capacity types (`on-demand`, `spot`)  | `["on-demand", "spot"]`                                 |
| `gpu_limits`                  | Maximum GPUs for NodePool             | `100`                                                   |

### Chamber

| Variable                | Description                         | Default    |
| ----------------------- | ----------------------------------- | ---------- |
| `chamber_agent_version` | Chamber Agent version               | `"latest"` |
| `enable_kai_scheduler`  | Enable KAI fractional GPU scheduler | `true`     |

## Key Outputs

| Output                            | Description                                |
| --------------------------------- | ------------------------------------------ |
| `cluster_name`                    | GKE cluster name                           |
| `cluster_endpoint`                | GKE API server endpoint                    |
| `network_name`                    | VPC network name                           |
| `configure_kubectl`               | gcloud command to configure kubectl        |
| `verification_commands`           | Commands to verify the deployment          |
| `karpenter_service_account_email` | Karpenter controller service account email |

For all outputs, see the [module README on GitHub](https://github.com/ChamberOrg/terraform-google-chamber-gke#outputs).

## GPU Pool Management

After deployment, you need GPU pools for Karpenter to know which GPU nodes to provision. There are two approaches:

<Tabs>
  <Tab title="Console-managed (default)">
    Manage GPU pools through the [Chamber Console](https://app.usechamber.io):

    1. Go to **Capacity Pools** > **Create Dynamic Pool**
    2. Select your cluster and configure GPU type, limits, and capacity types
    3. The pool syncs to your cluster automatically — Karpenter provisions GPU nodes on demand

    This is the recommended approach for most teams. It allows per-GPU-type management with real-time limit adjustments.
  </Tab>

  <Tab title="Terraform-managed">
    To manage GPU pools entirely through Terraform, set `create_default_gpu_nodepool = true`:

    ```hcl theme={null}
    module "chamber_gke" {
      source = "github.com/ChamberOrg/terraform-google-chamber-gke"

      # ... required variables ...

      create_default_gpu_nodepool = true
      gpu_machine_families        = ["a2", "g2"]
      gpu_accelerator_types       = ["nvidia-l4", "nvidia-a100-80gb"]
      capacity_types              = ["on-demand", "spot"]
      gpu_limits                  = 50
    }
    ```

    This creates a single broad NodePool covering the specified machine families and accelerator types.
  </Tab>
</Tabs>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Chamber Agent not connecting">
    Check the Chamber Agent logs:

    ```bash theme={null}
    kubectl logs -n chamber-system -l app.kubernetes.io/name=chamber-agent --tail=50
    ```

    Verify your `chamber_cluster_token` and `chamber_cluster_id` are correct.
  </Accordion>

  <Accordion title="GPU nodes not provisioning">
    1. Verify a GPU pool exists:
       ```bash theme={null}
       kubectl get nodepools.karpenter.sh
       ```
       If none exists, create one via the Chamber Console or set `create_default_gpu_nodepool = true`.

    2. Check Karpenter logs:
       ```bash theme={null}
       kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter --tail=100
       ```

    3. Verify GCENodeClass:
       ```bash theme={null}
       kubectl get gcenodeclasses
       ```
  </Accordion>

  <Accordion title="GPU pods stuck in Pending">
    Check the KAI Scheduler logs and pod events:

    ```bash theme={null}
    kubectl logs -n chamber-system -l app=kai-scheduler --tail=50
    kubectl describe pod <pod-name>
    ```
  </Accordion>
</AccordionGroup>

## Cleanup

```bash theme={null}
terraform destroy
```

<Warning>
  Ensure all GPU workloads are terminated before destroying to avoid orphaned resources.
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Submit your first GPU workload
  </Card>

  <Card title="Capacity Management" icon="chart-pie" href="/platform/capacity-management">
    Configure capacity pools and reservations
  </Card>

  <Card title="Agent Troubleshooting" icon="wrench" href="/agent/troubleshooting">
    Detailed troubleshooting guide
  </Card>

  <Card title="GitHub Repository" icon="github" href="https://github.com/ChamberOrg/terraform-google-chamber-gke">
    Full source, examples, and changelog
  </Card>
</CardGroup>
