Kubesense

Resource & Metric Collection

Prepare Azure for KubeSense — an App Registration with read-only roles, and optionally workload identity instead of a client secret. Common to both the Single and Multi Subscription paths.

Overview

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

Nothing is created, changed or deleted in your subscriptions. Every call KubeSense makes is an ARM list/get or an Azure Monitor metrics read.

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

Single Subscription Setup

Multi-Subscription Setup

Single SubscriptionMulti Subscription
Use it whenYou have one subscription, or want to add a few by handYour estate spans many subscriptions
Access granted atThe subscriptionManagement groups, or named subscriptions
Subscriptions added laterYou add each oneEnrolled automatically
Extra stepsNoneA discovery preview you approve before anything is created

The Multi Subscription path works because Azure RBAC inherits down the management-group tree: a single Reader assignment at a management group covers every subscription beneath it, including subscriptions created later. There is nothing to deploy into each subscription — no per-subscription bootstrap, no stack to roll out, and no callback for KubeSense to receive.

How KubeSense authenticates

ModeUse it whenWhat is stored
Client secretAnywhere. The default, and the only option on the Single Subscription path.The secret, encrypted at rest
Workload identityThe KubeSense controller runs on AKS. Multi Subscription only.Nothing — the pod authenticates as its own identity

The client secret is the part that will eventually bite you: Azure expires secrets on a 6–24 month clock set by tenant policy, and does not report the expiry date over its API. When a secret lapses, collection stops for every subscription that credential owns, at once. Workload identity has no secret and never expires — where the controller runs on AKS, prefer it. Otherwise record the expiry date in KubeSense so it can warn you.

Prerequisites

  1. Permission to create an App Registration in your Entra ID tenant
  2. Permission to create role assignments on the scopes you want observed — Owner or User Access Administrator on those subscriptions or management groups
  3. The az CLI signed in, or the Azure portal if your policy forbids CLI changes
  4. Administrator access to the KubeSense dashboard

The dashboard ships the setup for you: On the App Registration screen, "Get the setup script" offers both a shell script that runs as-is in Azure Cloud Shell and a Terraform module. Either performs Step 1 below. Neither is required — Step 1 can be done entirely in the portal.

Step 1 — Create the App Registration and grant read access

Two roles are needed, both Azure built-ins and both read-only:

RoleWhy it is needed
ReaderDiscovers your resources — every Azure service KubeSense collects.
Monitoring ReaderReads metrics from Azure Monitor. Without it KubeSense can see your resources but cannot chart them.

Run it in Azure Cloud Shell, where the az CLI is preinstalled and already signed in. Upload it with Cloud Shell's Upload button, then:

chmod +x kubesense-azure-setup.sh

# Preferred — one management group covers its whole subtree:
./kubesense-azure-setup.sh --management-groups <MANAGEMENT-GROUP-ID>

# Or name subscriptions explicitly:
./kubesense-azure-setup.sh --subscriptions <SUB-ID-1>,<SUB-ID-2>

The script creates the App Registration and its service principal, grants Reader and Monitoring Reader on each scope, then creates a client secret and prints the values the connection screens ask for. Re-running is safe: an existing App Registration and service principal are reused rather than duplicated, and an assignment that already exists is reported and skipped.

Prefer a management group over a subscription list: An assignment at a management group covers subscriptions added to it later, so a new subscription is enrolled with no action from you. A subscription list has to be edited every time your estate changes.

Or with Terraform

# terraform.tfvars
management_group_ids = ["mg-production"]
terraform init
terraform apply
terraform output -raw client_secret

It creates the same App Registration and the same two read-only role assignments, and outputs the same values — including the secret's expiry date, which Terraform knows exactly and you would otherwise copy from the portal by hand.

One difference worth knowing before you choose: Terraform stores the generated client secret in its state file in plaintext. That is inherent to the resource, not something the module can avoid, so anyone who can read your state backend can read the credential. The script prints the secret once and stores it nowhere, which is why it is the recommended path wherever policy forbids secrets in state.

Doing it by hand

  1. Entra ID → App registrations → New registration. Name it kubesense-collector. Note the Directory (tenant) ID and Application (client) ID from the Overview page.
  2. Certificates & secrets → New client secret. Copy the Value — not the Secret ID — and note the expiry date.
  3. On each management group or subscription: Access control (IAM) → Add role assignment, and assign both Reader and Monitoring Reader to the kubesense-collector service principal.

Copy the secret's Value, not its Secret ID: The two look alike, sit next to each other, and only one works. This is the single most common Azure setup mistake.

Step 2 — (Optional) Use workload identity instead of a secret

Skip this if you are using a client secret, or if the controller does not run on AKS. Workload identity is available on the Multi Subscription path only. It requires three things.

1. A federated credential on the App Registration, bound to your AKS cluster's OIDC issuer and the controller's namespace and service account:

az aks show -n <cluster> -g <rg> --query oidcIssuerProfile.issuerUrl -o tsv

az ad app federated-credential create --id <APP-OBJECT-ID> --parameters '{
  "name": "kubesense-controller",
  "issuer": "<AKS-OIDC-ISSUER-URL>",
  "subject": "system:serviceaccount:kubesense:kubesense-controller",
  "audiences": ["api://AzureADTokenExchange"]
}'

2. The controller pod labelled for workload identity, so AKS projects a token into it:

metadata:
  labels:
    azure.workload.identity/use: "true"

3. Reader and Monitoring Reader on the scopes, exactly as in Step 1 — the roles sit on the same service principal either way.

KubeSense reads the projected token from AZURE_FEDERATED_TOKEN_FILE and exchanges it for an ARM token. If that variable is unset the controller reports it explicitly rather than failing quietly; the usual cause is the missing pod label.

What gets collected

Every Azure resource type KubeSense discovers, and every Azure Monitor metric it collects for each, is listed in the Azure resource and metric reference.

Next

Azure is ready. Connect it: