Kubesense

Resource & Metric Collection

Prepare Google Cloud for KubeSense — a read-only service account, the APIs each project needs, and the credential the controller uses. Common to both the Single Project and Organization paths.

Overview

KubeSense observes your Google Cloud estate using read-only credentials. It discovers your resources across Google Cloud services, keeps that inventory current, and pulls metrics for them from Cloud Monitoring — so the cloud estate appears alongside the Kubernetes telemetry KubeSense already collects.

Nothing is created, changed or deleted in your projects. Every API call KubeSense makes is a list, get or timeSeries.list.

The three steps on this page are common to both paths. Then choose one:

Single Project Setup

Organization Setup

Single ProjectOrganization
Use it whenYou have one project, or want to add a few by handYour estate spans many projects
IAM bound atThe projectThe organization, or chosen folders
Projects added laterYou add each oneEnrolled automatically
Extra stepsNoneA discovery preview you approve before anything is created

The Organization path works because GCP IAM inherits down the resource hierarchy: a single binding at an organization covers every project beneath it, including projects created later. There is nothing to deploy into each project — no per-project bootstrap, no stack to roll out, and no callback for KubeSense to receive. It is markedly simpler than the AWS equivalent.

How KubeSense authenticates

ModeUse it whenWhat is stored
Workload Identity (recommended)The KubeSense controller runs on GKENothing — the pod authenticates as its own identity
Service account keyThe controller runs anywhere elseThe key JSON, encrypted at rest

Workload Identity is the better path wherever it is available: there is no key to create, store, rotate or leak, and many organizations block key creation outright with constraints/iam.disableServiceAccountKeyCreation.

Prerequisites

  1. Permission to create a service account in one project
  2. Permission to create IAM bindings — at the project (roles/resourcemanager.projectIamAdmin) for a single project, or at the organization (roles/resourcemanager.organizationAdmin) or folders (roles/resourcemanager.folderAdmin) for the Organization path
  3. Permission to enable APIs in the projects being observed (roles/serviceusage.serviceUsageAdmin)
  4. The gcloud CLI signed in, or the Cloud Console if your policy forbids CLI changes
  5. Administrator access to the KubeSense dashboard

Throughout, replace my-project with your project ID — the alphanumeric identifier from the console's project picker, not the display name. gcloud config get-value project prints it.

The dashboard ships the setup for you: On the Organization screen, "Get the setup script" offers both a gcloud script that runs as-is in Google Cloud Shell and a single-file Terraform module. Either performs Step 1 below. Neither is required — Step 1 can be done entirely with gcloud or in the console.

Step 1 — Create the service account and grant read access

Two roles are needed in every case, both Google predefined and both read-only:

RoleWhy it is needed
roles/viewerDiscovers your resources — Compute Engine, Cloud SQL, GKE, Cloud Run, Pub/Sub and the rest.
roles/monitoring.viewerReads metrics from Cloud Monitoring. Without it KubeSense can see your resources but cannot chart them.

The Organization path adds two more:

RoleWhy it is needed
roles/browserReads the resource hierarchy — discovering projects and walking folders. The one most often forgotten; without it project and folder listing fails before anything else runs.
roles/serviceusage.serviceUsageConsumerReads which APIs each project has enabled, so the discovery preview can warn you.

For a single project

PROJECT=my-project
SA=kubesense-collector

gcloud iam service-accounts create "$SA" --project="$PROJECT" \
  --display-name="KubeSense collector"

SA_EMAIL="$SA@$PROJECT.iam.gserviceaccount.com"

for ROLE in roles/viewer roles/monitoring.viewer; do
  gcloud projects add-iam-policy-binding "$PROJECT" \
    --member="serviceAccount:$SA_EMAIL" --role="$ROLE" --condition=None
done

For an organization or folders

The setup script from the dashboard does this in one command (./kubesense-gcp-setup.sh --organization 123456789012, or --folders 4455,6677), and the Terraform module does the same as reviewable code. By hand:

ORG_ID=123456789012
PROJECT=my-ops-project
SA=kubesense-collector

gcloud iam service-accounts create "$SA" --project="$PROJECT" \
  --display-name="KubeSense collector"

SA_EMAIL="$SA@$PROJECT.iam.gserviceaccount.com"

for ROLE in \
  roles/browser \
  roles/viewer \
  roles/monitoring.viewer \
  roles/serviceusage.serviceUsageConsumer
do
  gcloud organizations add-iam-policy-binding "$ORG_ID" \
    --member="serviceAccount:$SA_EMAIL" --role="$ROLE" --condition=None
done

For folder scope use gcloud resource-manager folders add-iam-policy-binding with the folder ID instead.

Bind roles/browser at the organization node, not below it: Organization-scoped enrollment lists folders under the organization itself, so a roles/browser binding at a folder or project does not satisfy it. This is the single most common GCP setup failure, and it surfaces as PERMISSION_DENIED on resourcemanager.folders.list — the dashboard detects that specific error and shows the exact gcloud command to fix it.

If roles/viewer is not acceptable

Some organizations will not grant roles/viewer, even at project scope. Replace it with per-service viewer roles, keeping the others:

roles/monitoring.viewer          # always
roles/compute.viewer             # Compute Engine VMs, all load balancer types
roles/cloudsql.viewer            # Cloud SQL
roles/container.viewer           # GKE clusters
roles/run.viewer                 # Cloud Run
roles/redis.viewer               # Memorystore Redis
roles/bigquery.metadataViewer    # BigQuery
roles/pubsub.viewer              # Pub/Sub
roles/spanner.viewer             # Spanner
# …one per service you intend to collect

Understand the failure mode before going granular: A missing role does not raise an error banner. That resource type simply collects nothing — which looks exactly like owning no resources of that type. If you take this route, enable one service at a time and confirm each appears before moving on.

Step 2 — Enable the APIs for the services you want observed

This is the one GCP-specific step with no AWS or Azure equivalent, and it is the most common reason a correctly-configured project collects nothing.

Google requires each service's API to be enabled in the project being read. A project can be wired up perfectly — right service account, right roles, green in every list — and still return nothing for Compute Engine, because compute.googleapis.com was never switched on in it. No amount of extra IAM changes this, and enrollment cannot switch them on for you: API enablement is per-project configuration.

gcloud services enable --project="$PROJECT" \
  monitoring.googleapis.com \
  compute.googleapis.com \
  sqladmin.googleapis.com \
  container.googleapis.com

# what is already on
gcloud services list --enabled --project="$PROJECT"

monitoring.googleapis.com is required in every case — it is the source of all metrics. The rest are per-service. Enabling an API is free and does not by itself incur charges.

On the Organization path, the discovery preview reports which APIs are missing per project, so you can fix this before enrolling rather than after.

Step 3 — Give the KubeSense controller the credential

The controller authenticates as its own Kubernetes ServiceAccount. No key is created, nothing sensitive is stored in KubeSense, and nothing expires. Requires Workload Identity enabled on the cluster running KubeSense.

GKE_PROJECT=my-gke-project      # the project of the cluster running KubeSense

gcloud iam service-accounts add-iam-policy-binding "$SA_EMAIL" \
  --role=roles/iam.workloadIdentityUser \
  --member="serviceAccount:$GKE_PROJECT.svc.id.goog[kubesense/kubesense-controller]"

kubectl annotate serviceaccount -n kubesense kubesense-controller \
  iam.gke.io/gcp-service-account="$SA_EMAIL" --overwrite

kubectl rollout restart deployment/kubecol-controller -n kubesense

Confirm your namespace and ServiceAccount first — this example uses kubesense and kubesense-controller:

kubectl get pod <controller-pod> -n <namespace> -o jsonpath='{.spec.serviceAccountName}'

The binding names the cluster's project, not the service account's: The Workload Identity pool belongs to the project the GKE cluster runs in. If the service account lives in a different project, the member string must still use the CLUSTER's project — a cross-project binding built from the wrong project authorizes the wrong pool and impersonation fails.

Option B — service account key

Only when the controller does not run on GKE:

gcloud iam service-accounts keys create kubesense-key.json \
  --iam-account="$SA_EMAIL"

You paste the contents of this file when connecting. It is stored encrypted at rest and never displayed again. Treat the file as a secret and delete your local copy once pasted — a service account key does not expire on its own.

What gets collected

Every Google Cloud resource type KubeSense discovers, and every Cloud Monitoring metric it collects for each, is listed in the GCP resource and metric reference.

Next

Google Cloud is ready. Connect it: