Skip to main content
Skip table of contents

OpenCost Deployment for Microsoft Azure

This guide explains how to deploy OpenCost for an AKS cluster.

Prerequisites

Before starting the deployment, ensure you have the following:

  • Infrastructure & permissions:

    • AKS cluster

    • Administrator access to the cluster

  • Cloud permissions:

    • Contributor role at the subscription or resource group level

    • User Access Administrator role (required to manage service principals)

  • Tools:

    • az CLI tool

    • kubectl CLI tool

    • helm CLI tool (v3.x or later)

Step 1. Configure Service Principal

Create a service principal

  1. In the Azure Portal, navigate to Microsoft Entra ID.

  2. Under Manage, select App registrations. Click +New registration.

  3. Set the following:

    • 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. 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. Navigate to 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)

Step 2. Set up Storage Account

  1. In the Azure Portal, navigate to Storage accounts.

  2. Click Create and configure the following:

    • Name: exampleopencost

    • Performance: Standard

    • Redundancy: any

  3. Open the newly created storage account.

  4. Navigate to Access Control (IAM) and assign Storage Blob Data Reader role to the service principal created for Cloudaware access:

    • Assign access to: User, group, or service principal

    • Members: click +Select members → select the Cloudaware application, e.g. cloudaware-api-access (see Azure Start Guide)

  5. Navigate to Containers and create a new container with the following settings:

    • Name: opencost-exports

    • Public access level: Private

Step 3. Connect to AKS Cluster

  1. Go to Kubernetes services.

  2. Select the created cluster.

  3. Click Connect. Copy credentials

  4. Run the az aks get-credentials command.

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

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 for the service principal credentials. Replace <YOUR_CLIENT_SECRET> with the value created in Step 1:

    CODE
    kubectl create secret generic azure-secret \
      --from-literal=password=<YOUR_CLIENT_SECRET> \
      --namespace opencost
  4. Install OpenCost:

    CODE
    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

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

Step 6. Deploy 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_TENANT_ID>, and <YOUR_CLIENT_ID> 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: "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: "opencost"
      - 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

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

CODE
- 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> 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: "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: "opencost"
      - 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

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

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

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

Step 7. Verify 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 9090:9090

    Open http://localhost:9090 in your browser.

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 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.