Skip to main content
Skip table of contents

OpenCost Deployment for Google Cloud

This guide explains how to deploy OpenCost for a GKE cluster.

Prerequisites

Before you begin, ensure you have the following:

  • Infrastructure:

    • An GKE cluster in Standard mode (not Autopilot*) with Workload Identity enabled

  • Required cloud permissions (GCP IAM roles):

    • roles/container.admin – required for GKE administration

    • roles/iam.serviceAccountAdmin – required to manage Service Accounts

    • roles/storage.admin – required to manage GCS bucket

    • roles/apikeys.admin – required to manage API keys

  • Required tools:

    • Google Cloud CLI (gcloud)

    • kubectl

    • Helm (v3.x or later)

*Autopilot is not supported due to the managed Prometheus configuration.

Step 1. Set up access

Create a service account

  1. In the Google Cloud console, navigate to IAM & Admin -> Service Accounts.

  2. Click +Create service account.

  3. Set the following:

    • Name: opencost-sa (the service account name used in this guide)

    • Description: Service account for OpenCost

  4. Assign the required role:

    • roles/compute.viewer

  5. Click Done to create the account.

Configure workload identity

  1. Return to the Service Accounts list. Open the newly created service account.

  2. Select the tab ‘Principals with access’. Click Grant access.

  3. Add the following principal: <YOUR_GCP_PROJECT_ID>.svc.id.goog[opencost/opencost-sa] where <YOUR_GCP_PROJECT_ID> is a placeholder for your GCP Project ID and opencost-sa is a placeholder for your Google service account

  4. Assign the Workload Identity User role and save.

Create a service account key

  1. Navigate back to the Service Accounts list. Click on Actions (three-dot) menu → Manage keys.

  2. Click Add KeyCreate new key.

  3. Select JSON and click Create.

  4. Download and store the key securely. The key will be required later when creating the Kubernetes secret.

Create an API key

  1. Navigate to APIs & Services -> Credentials.

  2. Click +Create Credentials and select API key.

  3. Copy the generated key.

  4. From the Actions (three-dot) menu of the new key, select Edit API key.

  5. Under API restrictions, select Restrict key. Check the box ‘Cloud Billing API’ (cloudbilling.googleapis.com) → OK. Click Save.

Step 2. Set up the storage bucket

  1. Navigate to Cloud Storage -> Buckets.

  2. Click +Create.

  3. Configure the bucket:

    • Name: e.g., opencost-bucket

    • Location type: Region

    • Storage class: Standard
      Leave the remaining settings as is.

  4. Click Create.

  5. Navigate to Permissions+ Grant Access.

    • Select Principal: opencost-sa@<YOUR_GCP_PROJECT_ID>.iam.gserviceaccount.com where <YOUR_GCP_PROJECT_ID> is a placeholder for your GCP Project ID

    • Select Role: Storage Object User
      Click Save.

Note that the storage bucket name must be globally unique.

Step 3. Create the cluster connection file

  1. Navigate to Kubernetes EngineClusters.

  2. Click the Actions (three-dot) menu next to the cluster and select Connect.

  3. Copy the gcloud command and run it in your terminal. This generates the kubeconfig file needed to access the cluster.

Step 4. Deploy Prometheus

  1. Add the Prometheus Helm repository:

    CODE
    helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
  2. Create the Prometheus namespace:

    CODE
    kubectl create namespace prometheus-system
  3. Install Prometheus:

    CODE
    helm install prometheus prometheus-community/prometheus \
      --namespace prometheus-system \
      --set prometheus-pushgateway.enabled=false \
      --set alertmanager.enabled=false

If you use an external Prometheus instance, skip this step and review the notes in Step 5.

Step 5. Deploy OpenCost

  1. Add the OpenCost Helm repository:

    CODE
    helm repo add opencost https://opencost.github.io/opencost-helm-chart
  2. Create the OpenCost namespace:

    CODE
    kubectl create namespace opencost
  3. Create a Kubernetes secret with the service account key. Replace /path/to/your/service-account-key.json with your file path.

    CODE
    kubectl create secret generic google-application-credentials \
      --from-file=config.json=/path/to/your/service-account-key.json \
      --namespace opencost
  4. Install OpenCost. Replace <YOUR_PROJECT_ID> and <YOUR_API_KEY> in the command below:

    CODE
    helm --namespace opencost upgrade --install opencost opencost/opencost -f - <<EOF
    podSecurityContexts:
      runAsUser: 1001
      runAsGroup: 1001
      fsGroup: 1001
    
    extraVolumes:
      - name: configs
        emptyDir: {}
    
    serviceAccount:
      create: true
      name: opencost-sa
      annotations:
        iam.gke.io/gcp-service-account: "opencost-sa@<YOUR_PROJECT_ID>.iam.gserviceaccount.com"
    opencost:
      prometheus:
        namespaceName: prometheus-system
      exporter:
        cloudProviderApiKey: <YOUR_API_KEY>
        extraVolumeMounts:
          - mountPath: /var/configs
            name: configs
            readOnly: false
    podAnnotations:
      prometheus.io/path: /metrics
      prometheus.io/port: "9003"
      prometheus.io/scrape: "true"
    EOF

The podAnnotations ensure that Prometheus scrapes metrics from the OpenCost pods, enabling label-based cost attribution in reports.

If your cluster already has an external Prometheus, configure OpenCost to use the existing Prometheus instance by setting the following Helm values (replace <YOUR_PROMETHEUS_URL> with the correct endpoint):

CODE
opencost:
  prometheus:
    external:
      enabled: true
      url: <YOUR_PROMETHEUS_URL>

If your cluster uses prometheus-operator, enable ServiceMonitor; otherwise OpenCost metrics will not be scraped automatically. Set the following Helm values:

CODE
opencost:
  metrics:
    serviceMonitor:
      enabled: true

Step 6. Deploy the Parquet exporter

Install the OpenCost Parquet Exporter.

  • To store reports in subfolders or use a naming prefix, use the command below, replacing <YOUR_CLUSTER_PREFIX>, <YOUR_GKE_CLUSTER_ID>* and "opencsot-bucket" (the storage bucket name used in this guide) with the appropriate values.

    CODE
    helm install parquet-exporter opencost/opencost-parquet-exporter \
      --namespace opencost \
      --set schedule="0 */12 * * *" \
      --set existingServiceAccount=opencost-sa \
      --values - <<EOF
    resources:
      limits:
        cpu: "1"
        memory: 1Gi
      requests:
        cpu: 100m
        memory: 100Mi
    env:
      - name: OPENCOST_PARQUET_SVC_HOSTNAME
        value: "opencost.opencost.svc.cluster.local"
      - name: OPENCOST_PARQUET_STORAGE_BACKEND
        value: "gcp"
      - name: OPENCOST_PARQUET_FILE_KEY_PREFIX
        value: "<YOUR_CLUSTER_PREFIX>"/"<YOUR_GKE_CLUSTER_ID>"
      - name: OPENCOST_PARQUET_JSON_SEPARATOR
        value: "_"
      - name: OPENCOST_PARQUET_GCP_BUCKET_NAME
        value: "opencost-bucket"
      - name: OPENCOST_PARQUET_GCP_CREDENTIALS_JSON
        valueFrom:
          secretKeyRef:
            name: google-application-credentials
            key: config.json
    EOF

*Note that for <YOUR_GKE_CLUSTER_ID>, Cloudaware expects the value in the format projects/<YOUR_PROJECT_ID>/zones/region/clusters/<YOUR_CLUSTER_NAME>. To retrieve this value, run the following command:

CODE
gcloud container clusters describe <CLUSTER_NAME> \
  --project <GCP_PROJECT_ID> \
  --region <GCP_REGION> \
  --format="value(selfLink)" | sed 's|.*/projects/|projects/|'

  • To store reports in the root folder, use the command below, replacing <YOUR_GKE_CLUSTER_ID>* and "opencsot-bucket" (the storage bucket name used in this guide) with the appropriate values.

    CODE
    helm install parquet-exporter opencost/opencost-parquet-exporter \
      --namespace opencost \
      --set schedule="0 */12 * * *" \
      --set existingServiceAccount=opencost-sa \
      --values - <<EOF
    resources:
      limits:
        cpu: "1"
        memory: 1Gi
      requests:
        cpu: 100m
        memory: 100Mi
    env:
      - name: OPENCOST_PARQUET_SVC_HOSTNAME
        value: "opencost.opencost.svc.cluster.local"
      - name: OPENCOST_PARQUET_STORAGE_BACKEND
        value: "gcp"
      - name: OPENCOST_PARQUET_FILE_KEY_PREFIX
        value: "<YOUR_GKE_CLUSTER_ID>/"
      - name: OPENCOST_PARQUET_JSON_SEPARATOR
        value: "_"
      - name: OPENCOST_PARQUET_GCP_BUCKET_NAME
        value: "opencost-bucket"
      - name: OPENCOST_PARQUET_GCP_CREDENTIALS_JSON
        valueFrom:
          secretKeyRef:
            name: google-application-credentials
            key: config.json
    EOF

*Note that for <YOUR_GKE_CLUSTER_ID>, Cloudaware expects the value in the format projects/<YOUR_PROJECT_ID>/zones/<YOUR-ZONE>/clusters/<YOUR_CLUSTER_NAME>. To retrieve this value, run the following command:

CODE
gcloud container clusters describe <CLUSTER_NAME> \
  --project <GCP_PROJECT_ID> \
  --region <GCP_REGION> \
  --format="value(selfLink)" | sed 's|.*/projects/|projects/|'

For multi-cluster environments, deploy the Parquet Explorer separately on each cluster.

Step 7. Verify the deployment

  1. Check that all pods are running:

    CODE
    kubectl get pods -n prometheus
    kubectl get pods -n opencost
  2. Access the OpenCost UI:

    CODE
    kubectl port-forward -n opencost service/opencost 9003:9003

    Then open http://localhost:9003 in your browser.

The first Parquet export may take up to 24 hours. To verify the export, check your storage bucket for newly created files.

Next steps

Return to the parent guide to proceed with the Kubernetes Billing setup in Cloudaware.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.