Azure Metrics Integration
- Overview
- Prerequisites
- Step 1: Create a Service Principal
- Step 2: Assign Monitoring Reader to Additional Subscriptions
- Step 3: Configure Kloudfuse via Helm
- Select the Resource Types to Collect
- Add a Resource Type That Isn’t Supported Yet
- Monitor Multiple Subscriptions
- Verify the Integration
- Troubleshooting
- External References
Kloudfuse collects Azure Monitor metrics using the Cloud Exporter — a scraper that runs inside your cluster and periodically pulls metrics from the Azure Monitor Metrics API. No additional agents or Azure-side configuration are required beyond the initial Service Principal setup.
For an overview of how this fits into the broader Azure integration architecture, see Azure Integration Architecture.
Overview
The Cloud Exporter polls the Azure Monitor Metrics API on a fixed interval — every minute by default — and stores the retrieved metric time series directly in Kloudfuse. It supports multiple Azure subscriptions simultaneously, so a single Cloud Exporter deployment can collect metrics from all subscriptions in your organization.
Metric collection is opt-in by resource type.
You list the Azure resource types you want in custom-values.yaml; Kloudfuse owns which metrics, aggregations, time grains, and dimension filters are collected for each type — you never specify individual metric names.
An empty or absent list collects nothing.
Kloudfuse supports built-in Azure Monitor metrics across Compute (Virtual Machines and Scale Sets), Containers (AKS), Networking (Load Balancers and Application Gateways), Storage (Storage Accounts, blobs, and file shares), Databases (Azure Database for PostgreSQL), Cache (Redis), Messaging (Event Hubs and IoT Hub), Cognitive Services, and Azure Data Explorer (Kusto). For the full list of supported resource types and the metrics collected under each, see Supported Azure Metrics.
For a resource type that is not in the catalog yet, define your own scrape jobs inline with customResourceTypes (see Add a Resource Type That Isn’t Supported Yet) — collected in addition to the catalog picks, without waiting for a release.
Prerequisites
-
A running Kloudfuse deployment (AKS, GKE, or EKS — the Cloud Exporter connects to Azure Monitor over HTTPS and works regardless of where the Kloudfuse cluster runs).
-
Azure CLI (
az) installed and authenticated, or access to the Azure Portal. -
Permissions to create app registrations and role assignments in your Azure Active Directory tenant.
Step 1: Create a Service Principal
The Cloud Exporter authenticates to Azure using a Service Principal. Create one using the Azure CLI:
az ad sp create-for-rbac \
--name kloudfuse-cloud-exporter \
--role "Monitoring Reader" \
--scopes /subscriptions/<subscription-id>
The output contains the values you need:
{
"appId": "<AZURE_CLIENT_ID>",
"displayName": "kloudfuse-cloud-exporter",
"password": "<AZURE_CLIENT_SECRET>",
"tenant": "<AZURE_TENANT_ID>"
}
Save appId, password, and tenant — you will use them in the Helm configuration.
The --role "Monitoring Reader" flag grants read-only access to Azure Monitor metrics for the specified subscription.
It does not grant access to resource configurations or any control-plane operations.
|
Step 2: Assign Monitoring Reader to Additional Subscriptions
If you want to collect metrics from multiple subscriptions, assign the Monitoring Reader role for each one:
az role assignment create \
--assignee <AZURE_CLIENT_ID> \
--role "Monitoring Reader" \
--scope /subscriptions/<additional-subscription-id>
Repeat for each subscription.
The subscription IDs are listed in the subscriptions field in the Helm values (see Step 3: Configure Kloudfuse via Helm).
Step 3: Configure Kloudfuse via Helm
Enable the Cloud Exporter
In your custom-values.yaml, enable the cloud-exporter under the global section:
global:
cloud-exporter:
enabled: true
Option A: Inline Credentials
Add the Azure credentials and subscription list directly in custom-values.yaml:
kfuse-cloud-exporter:
azure-metrics-exporter:
enabled: true
subscriptions:
- <subscription-id-1>
- <subscription-id-2>
secrets:
AZURE_CLIENT_ID: "<AZURE_CLIENT_ID>"
AZURE_TENANT_ID: "<AZURE_TENANT_ID>"
AZURE_CLIENT_SECRET: "<AZURE_CLIENT_SECRET>"
resourceTypes: # opt-in list; values from the supported catalog
- Microsoft.ContainerService/managedClusters
- Microsoft.Cache/Redis
scrapeInterval: 1m # optional, default 1m
Storing credentials in plain text in custom-values.yaml is convenient for initial setup but is not recommended for production.
Use Option B in production environments.
|
Option B: Kubernetes Secret (Recommended)
Create a Kubernetes secret in the Kloudfuse namespace (kfuse by default — replace if your installation uses a different namespace):
kubectl create secret generic azure-cloud-exporter-credentials \
--namespace <kloudfuse-namespace> \
--from-literal=AZURE_CLIENT_ID="<AZURE_CLIENT_ID>" \
--from-literal=AZURE_TENANT_ID="<AZURE_TENANT_ID>" \
--from-literal=AZURE_CLIENT_SECRET="<AZURE_CLIENT_SECRET>"
Reference the secret in custom-values.yaml:
kfuse-cloud-exporter:
azure-metrics-exporter:
enabled: true
subscriptions:
- <subscription-id-1>
- <subscription-id-2>
resourceTypes: # opt-in list; values from the supported catalog
- Microsoft.ContainerService/managedClusters
- Microsoft.Cache/Redis
scrapeInterval: 1m # optional, default 1m
extraEnv:
- name: AZURE_CLIENT_ID
valueFrom:
secretKeyRef:
name: azure-cloud-exporter-credentials
key: AZURE_CLIENT_ID
- name: AZURE_TENANT_ID
valueFrom:
secretKeyRef:
name: azure-cloud-exporter-credentials
key: AZURE_TENANT_ID
- name: AZURE_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: azure-cloud-exporter-credentials
key: AZURE_CLIENT_SECRET
Configuration Reference
The azure-metrics-exporter block accepts the following fields:
| Field | Required | Meaning |
|---|---|---|
|
yes |
Turns Azure metric collection on. |
|
yes |
One or more Azure subscription IDs to scrape. Every job queries all listed subscriptions. |
|
yes |
Service Principal (app registration) client ID. |
|
yes |
Azure Active Directory tenant ID. |
|
yes |
Service Principal client secret. The principal needs the Monitoring Reader role on the subscriptions. |
|
yes |
Resource types to collect, using values from the supported catalog. An empty or absent list collects nothing. |
|
no |
Customer-authored jobs for resource types not in the catalog, collected in addition to |
|
no |
How often every Azure job polls, as a Prometheus duration ( |
When you reference credentials from a Kubernetes secret (Option B), supply them through extraEnv instead of the inline secrets block, as shown above.
|
Apply the Helm Upgrade
helm upgrade --install kfuse oci://us-east1-docker.pkg.dev/mvp-demo-301906/kfuse-helm/kfuse \
-n kfuse \
--version <VERSION> \ (1)
-f custom-values.yaml
| 1 | Replace <VERSION> with a valid Kloudfuse release value. See Release Notes for the latest release. |
Select the Resource Types to Collect
The resourceTypes list is the opt-in set of Azure resource types Kloudfuse collects metrics for.
Use the exact resource type strings from Supported Azure Metrics — for example Microsoft.Cache/Redis.
Kloudfuse owns which metrics, aggregations, time grains, and dimension filters each type collects; you never specify individual metric names.
kfuse-cloud-exporter:
azure-metrics-exporter:
enabled: true
subscriptions:
- <subscription-id>
resourceTypes:
- Microsoft.ContainerService/managedClusters
- Microsoft.Cache/Redis
- Microsoft.DBforPostgreSQL/flexibleServers
How collection behaves:
-
Opt-in only. An empty or absent
resourceTypescollects nothing. -
Unrecognized entries are silently skipped. A type not in the catalog — a typo or an unsupported type — is dropped, while valid entries in the same list still collect. There is no warning; the supported set is the catalog.
-
Metric naming. Metrics are emitted as
<prefix>_<metric>, where<prefix>is derived from the resource type (shown per type in the catalog) and<metric>is the Azure metric name, lowercased with non-alphanumeric characters replaced by_. For example,Microsoft.Cache/Redisusedmemorybecomesazure_cache_redis_usedmemory. You do not control these names. -
One or more API calls per type. Metrics are grouped into jobs by (dimension filter × aggregation × time grain); Azure Monitor rejects an entire batch if any metric in it lacks a requested aggregation or filtered dimension. A single job collects at most 20 metrics.
Add a Resource Type That Isn’t Supported Yet
If a resource type is not in the catalog, define its collection jobs inline under customResourceTypes.
These jobs render in addition to resourceTypes, nothing is overwritten.
The shape mirrors the internal catalog: a map of Azure resource type to a list of jobs.
The following example collects Microsoft.DocumentDB/databaseAccounts (Cosmos DB), which is not in the catalog, alongside the usual catalog picks:
kfuse-cloud-exporter:
azure-metrics-exporter:
enabled: true
subscriptions:
- <subscription-id>
resourceTypes:
- Microsoft.ContainerService/managedClusters
customResourceTypes:
Microsoft.DocumentDB/databaseAccounts:
- jobName: Microsoft.DocumentDB/databaseAccounts_requests
metrics: [TotalRequests, MetadataRequests]
interval: PT1M
aggregation: [count]
- jobName: Microsoft.DocumentDB/databaseAccounts_consumption
metrics: [TotalRequestUnits, NormalizedRUConsumption]
interval: PT1M
aggregation: [average]
scrapeInterval: 1m
Each of the two jobs above requests a single aggregation, because Azure Monitor rejects the whole batch if any metric in a job does not support the requested aggregation. TotalRequests and MetadataRequests are collected with count, while TotalRequestUnits and NormalizedRUConsumption are collected with average.
Each job accepts the following fields:
| Field | Required | Meaning |
|---|---|---|
|
yes |
Becomes the Prometheus |
|
yes |
Azure metric names for this job (max 20, case-sensitive — see the notes below). All must share the job’s aggregation and dimension filter. |
|
yes |
Azure Monitor time grain, for example |
|
yes |
One or more of |
|
no |
Dimension filter, for example |
|
no |
Query window. Defaults to |
|
no |
Maximum number of dimension series returned, for example |
|
no |
|
Notes:
-
Use the exact Azure metric name. The value under
metricsis passed verbatim to the Azure Monitor API, so each name must match Azure’s exactly, including capitalization — for exampleTotalRequestUnits. -
Check each metric’s supported aggregations on that same page. A job must request only aggregations that every metric in it supports, or Azure returns a 400 for the batch — for example, Cosmos DB
TotalRequestssupports onlycount, whileProvisionedThroughputsupports onlymaximum. -
One job per (aggregation × time grain × dimension filter). Azure Monitor returns a 400 for the entire batch if any metric in a job lacks the requested aggregation or a filtered dimension. Split metrics that differ on any of these into separate jobs, as with
_requestsand_consumptionabove. -
The metric prefix is auto-derived the same way as catalog types —
Microsoft.DocumentDB/databaseAccountsbecomesazure_documentdb_databaseaccounts. The metric suffix is normalized per the naming rule above, soTotalRequestUnitslands asazure_documentdb_databaseaccounts_totalrequestunits. You do not set the prefix. -
Validated at render time. A job missing
jobName,metrics,interval, oraggregation— orcustomResourceTypesset withoutsubscriptions— fails the Helm install with a specific error, rather than shipping broken config that crashloops the metrics agent. -
Do not also name a custom type in
resourceTypes, or itsjobNamecollides with the catalog job.
Monitor Multiple Subscriptions
List every subscription you want to collect metrics from under subscriptions.
The Cloud Exporter collects metrics from all listed subscriptions using the same Service Principal, provided it has the Monitoring Reader role assigned on each one.
kfuse-cloud-exporter:
azure-metrics-exporter:
enabled: true
subscriptions:
- xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # Production
- yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy # Staging
- zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz # Development
resourceTypes: # applied to every listed subscription
- Microsoft.ContainerService/managedClusters
- Microsoft.Cache/Redis
Verify the Integration
Confirm the Cloud Exporter is Running
Check that the Cloud Exporter pod is healthy:
kubectl get pods -n <kloudfuse-namespace> -l app=azure-metrics-exporter
The pod status must be Running.
If it is CrashLoopBackOff, check the logs:
kubectl logs -n <kloudfuse-namespace> -l app=azure-metrics-exporter --tail=100
Common error messages are listed in the Troubleshooting section.
Confirm Metrics are Arriving in Kloudfuse
-
In the Kloudfuse UI, click the Metrics tab and select Explorer from the drop-down.
-
In the metric search field, type
azure_to list all ingested Azure Monitor metrics. Metrics follow the naming convention<prefix>_<metric_name>, where<prefix>is derived from the resource type and the metric name is lowercased with non-alphanumeric characters replaced by_, for example:Azure Monitor metric Kloudfuse metric name Microsoft.Compute/virtualMachines — Percentage CPUazure_compute_virtualmachines_percentage_cpuMicrosoft.Storage/storageAccounts — UsedCapacityazure_storage_storageaccounts_usedcapacityMicrosoft.Cache/Redis — usedmemoryazure_cache_redis_usedmemoryMicrosoft.ContainerService/managedClusters — node_cpu_usage_percentageazure_containerservice_managedclusters_node_cpu_usage_percentageMicrosoft.DBforPostgreSQL/flexibleServers — cpu_percentazure_dbforpostgresql_flexibleservers_cpu_percent -
Select a metric and set the time range to the last 15 minutes. A non-empty chart confirms end-to-end delivery.
| The first metrics appear approximately one scrape interval (one minute by default) after the Cloud Exporter pod starts. |
Troubleshooting
Cloud Exporter Pod is in CrashLoopBackOff
kubectl logs -n <kloudfuse-namespace> -l app=azure-metrics-exporter --tail=50
Common causes:
| Error message | Resolution |
|---|---|
|
The Client Secret is incorrect or has expired. Regenerate it: |
|
The Service Principal lacks the Monitoring Reader role on the target subscription. Run the role assignment command in Step 2: Assign Monitoring Reader to Additional Subscriptions. |
|
A subscription ID in the |
Secret key not found |
The Kubernetes secret name or key does not match the |
No Azure Metrics Appear in Kloudfuse
-
Confirm
resourceTypesis non-empty. An empty or absent list collects nothing (see Select the Resource Types to Collect). -
Confirm the Cloud Exporter pod is
Running(see Confirm the Cloud Exporter is Running). -
Wait at least one scrape interval (one minute by default) after the pod starts — the first scrape takes up to one interval to complete.
-
Check the Cloud Exporter logs for scrape errors:
kubectl logs -n <kloudfuse-namespace> -l app=azure-metrics-exporter | grep -i errorbash -
Confirm the subscription IDs in
custom-values.yamlmatch the subscriptions returned by:az account list --query "[].{Name:name,ID:id}" --output tablebash
Metrics for a Listed Resource Type Never Appear
If one entry in resourceTypes produces no metrics while others work, the type is most likely not in the supported catalog and was silently skipped — there is no warning.
-
Check the spelling and casing against Supported Azure Metrics. Entries must match exactly, for example
Microsoft.Cache/Redis. -
If the type genuinely is not in the catalog, collect it with
customResourceTypes(see Add a Resource Type That Isn’t Supported Yet).
Metrics from One Subscription are Missing
-
Confirm the subscription ID is listed in the
subscriptionsfield incustom-values.yaml. -
Confirm the Service Principal has the Monitoring Reader role on that subscription:
az role assignment list \ --assignee <AZURE_CLIENT_ID> \ --scope /subscriptions/<subscription-id> \ --query "[].{Role:roleDefinitionName,Scope:scope}" \ --output tablebash -
If the role is missing, add it with
az role assignment createas shown in Step 2: Assign Monitoring Reader to Additional Subscriptions.
TLS Verification Errors on AKS
If the Cloud Exporter cannot verify TLS certificates when connecting to Azure Monitor, it may be a corporate proxy or custom CA issue. Add the CA certificate to the pod’s trust store via the Helm values, or temporarily disable TLS verification for diagnosis only:
kfuse-cloud-exporter:
azure-metrics-exporter:
extraEnv:
- name: AZURE_SDK_DISABLE_CERT_VERIFICATION
value: "true"
| Disabling TLS verification exposes the connection to interception. Only use this for diagnostic purposes and re-enable it once the root cause is identified. |
External References
Prometheus Exporter
-
webdevops/azure-metrics-exporter — Prometheus exporter for Azure Monitor metrics — the open-source exporter used by the Kloudfuse Cloud Exporter pod.
-
azure-metrics-exporter configuration reference — full list of environment variables, scrape interval settings, and metric filter options.
-
Resource Graph query support — advanced targeting of resources by tag, type, or resource group using Azure Resource Graph queries.
Azure documentation