Skip to main content

OpenCost on Microsoft Azure

Use this guide to deploy OpenCost components for Kubernetes Billing exports to Azure Blob Storage.

Prerequisites​

Before you begin, make sure you have:

  • Infrastructure & permissions
    • An AKS cluster
    • Cluster administrator access
  • Required cloud permissions
    • Contributor role at the subscription or resource group level
    • User Access Administrator role (required to manage service principals)
  • Required tools
    • Azure CLI (az)
    • kubectl
    • Helm (v3.x or later)

Set Up a Service Principal​

Create a Service Principal​

  1. In the Azure portal, navigate to Microsoft Entra ID.
  2. Under Manage, select App registrations and click + New registration.
  3. Set:
    • Name: opencost-sp
    • Supported account types: Single tenant
  4. After creating the application, note:
    • Application (client) ID
    • Directory (tenant) ID

Create a Client Secret​

  1. Open the newly created application.
  2. Under Manage, select Certificates & secrets and click + New client secret.
  3. Set a description and select an expiry period.
  4. Copy and save the generated secret value. This value cannot be retrieved later.

Assign Permissions​

  1. Navigate to the subscription that contains the AKS cluster.
  2. Open Access control (IAM).
  3. Click + Add → Add role assignment.
  4. Assign the following roles to the service principal:
    • Reader (required for cost metrics).
    • Storage Blob Data Contributor (required for Parquet exports).

Set Up the Storage Account​

  1. In the Azure portal, navigate to Storage accounts.
  2. Click Create and configure:
    • Name: for example, opencost-reports (must be globally unique, only lowercase letters and numbers).
    • Performance: leave the default value.
    • Redundancy: leave the default value.
  3. Create the storage account.
note

Use the storage account name consistently in the later steps.

Configure Access for Cloudaware​

  1. Open the newly created storage account.
  2. Go to Access control (IAM).
  3. Assign the Storage Blob Data Reader role to the service principal used for Cloudaware access:
    • Assign access to: User, group, or service principal.
    • Members: click + Select members and select the Cloudaware application (for example, cloudaware-api-access).

Create a Container for Exports​

  1. Navigate to Containers and click + Container.
  2. Set:
    • Name: for example, opencost-exports.
    • Public access level: Private.

Connect to the AKS Cluster​

  1. In the Azure portal, go to Kubernetes services.
  2. Select the target cluster.
  3. Click Connect and copy the credentials command.
  4. Run the az aks get-credentials command locally to merge cluster credentials into your kubeconfig.

Deploy Prometheus​

tip

If you use an external Prometheus instance, skip this step and review the Configuration notes (1) for external Prometheus below.

  1. Add the Prometheus Helm repository:

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

    kubectl create namespace prometheus-system
  3. Install Prometheus:

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

Deploy OpenCost​

  1. Add the OpenCost Helm repository:

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

    kubectl create namespace opencost
  3. Create a Kubernetes secret for the service principal credentials. Replace {YOUR_CLIENT_SECRET} with the value created in Step 1:

    kubectl create secret generic azure-secret \
    --from-literal=password={YOUR_CLIENT_SECRET} \
    --namespace opencost
  4. Install OpenCost:

    helm --namespace opencost upgrade --install opencost opencost/opencost -f - <<EOF
    serviceAccount:
    create: true
    name: opencost-sa
    opencost:
    prometheus:
    namespaceName: prometheus-system
    podAnnotations:
    prometheus.io/path: /metrics
    prometheus.io/port: "9003"
    prometheus.io/scrape: "true"
    EOF
tip

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

Configuration Notes​

Configure the following Helm values depending on your setup:

  1. If your cluster already has an external Prometheus, configure OpenCost to use the existing Prometheus instance. Replace {YOUR_PROMETHEUS_URL} with the correct endpoint:

    opencost:
    prometheus:
    external:
    enabled: true
    url: {YOUR_PROMETHEUS_URL}
  2. If your cluster uses prometheus-operator, enable ServiceMonitor; otherwise, OpenCost metrics will not be scraped automatically:

    opencost:
    metrics:
    serviceMonitor:
    enabled: true

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_AKS_CLUSTER_ID}, {YOUR_OPENCOST_STORAGE}, {YOUR_OPENCOST_PARQUET_AZURE_CONTAINER__NAME}, {YOUR_TENANT_ID}, and {YOUR_CLIENT_ID} with the appropriate values:

    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
    securityContext: null
    env:
    - name: OPENCOST_PARQUET_SVC_HOSTNAME
    value: "opencost.opencost.svc.cluster.local"
    - name: OPENCOST_PARQUET_STORAGE_BACKEND
    value: "azure"
    - name: OPENCOST_PARQUET_FILE_KEY_PREFIX
    value: "{YOUR_CLUSTER_PREFIX}/{YOUR_AKS_CLUSTER_ID}/"
    - name: OPENCOST_PARQUET_JSON_SEPARATOR
    value: "_"
    - name: OPENCOST_PARQUET_AZURE_STORAGE_ACCOUNT_NAME
    value: "{YOUR_OPENCOST_STORAGE}"
    - name: OPENCOST_PARQUET_AZURE_CONTAINER_NAME
    value: "{YOUR_OPENCOST_PARQUET_AZURE_CONTAINER__NAME}"
    - name: OPENCOST_PARQUET_AZURE_TENANT
    value: "{YOUR_TENANT_ID}"
    - name: OPENCOST_PARQUET_AZURE_APPLICATION_ID
    value: "{YOUR_CLIENT_ID}"
    - name: OPENCOST_PARQUET_AZURE_APPLICATION_SECRET
    valueFrom:
    secretKeyRef:
    name: azure-secret
    key: password
    EOF
    note

    Use the AKS cluster ID without the leading forward slash (/) in OPENCOST_PARQUET_FILE_KEY_PREFIX. Example:

    - name: OPENCOST_PARQUET_FILE_KEY_PREFIX
    value: prodk8s/subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/opencost/providers/Microsoft.ContainerService/managedClusters/opencost-aks/
  • To store reports in the root folder, use the command below, replacing {YOUR_AKS_CLUSTER_ID}, {YOUR_OPENCOST_STORAGE}, {YOUR_TENANT_ID}, and {YOUR_CLIENT_ID}:

    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
    securityContext: null
    env:
    - name: OPENCOST_PARQUET_SVC_HOSTNAME
    value: "opencost.opencost.svc.cluster.local"
    - name: OPENCOST_PARQUET_STORAGE_BACKEND
    value: "azure"
    - name: OPENCOST_PARQUET_FILE_KEY_PREFIX
    value: "{YOUR_AKS_CLUSTER_ID}/"
    - name: OPENCOST_PARQUET_JSON_SEPARATOR
    value: "_"
    - name: OPENCOST_PARQUET_AZURE_STORAGE_ACCOUNT_NAME
    value: "{YOUR_OPENCOST_STORAGE}"
    - name: OPENCOST_PARQUET_AZURE_CONTAINER_NAME
    value: "{YOUR_OPENCOST_PARQUET_AZURE_CONTAINER__NAME}"
    - name: OPENCOST_PARQUET_AZURE_TENANT
    value: "{YOUR_TENANT_ID}"
    - name: OPENCOST_PARQUET_AZURE_APPLICATION_ID
    value: "{YOUR_CLIENT_ID}"
    - name: OPENCOST_PARQUET_AZURE_APPLICATION_SECRET
    valueFrom:
    secretKeyRef:
    name: azure-secret
    key: password
    EOF
    note

    Use the AKS cluster ID without the leading forward slash (/) in OPENCOST_PARQUET_FILE_KEY_PREFIX.

    Example:

    - name: OPENCOST_PARQUET_FILE_KEY_PREFIX
    value: subscriptions/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee/resourceGroups/opencost/providers/Microsoft.ContainerService/managedClusters/opencost-aks/
warning

For multi‑cluster environments, deploy the Parquet exporter separately on each cluster.

Verify the Deployment​

  1. Check that all pods are running:

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

    kubectl port-forward -n opencost service/opencost 9090:9090

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

note

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

Next Steps​

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