How to Create an Azure Storage Account for Cost Management Export

Set up storage accounts for cost data exports

8 min readUpdated January 2025

How to Create an Azure Storage Account for Cost Management Export

Azure Cost Management allows you to export your cost and usage data to an Azure Storage account for long-term retention, custom analysis, or integration with third-party tools. This guide walks you through creating a dedicated storage account optimized for cost data exports.

Overview

Cost Management exports generate CSV files containing detailed billing data that can be exported daily, weekly, or monthly. Before you can configure an export, you need a storage account with the proper configuration to receive this data. This guide covers creating a storage account specifically designed for cost data, including the optimal settings for performance, security, and cost efficiency.

Prerequisites

Before you begin, ensure you have:

  • Azure subscription with active billing
  • Contributor or Owner role on the subscription or resource group where you'll create the storage account
  • Cost Management Contributor role on the billing scope you want to export
  • Azure Portal access or Azure CLI/PowerShell installed
  • Understanding of Azure resource groups and naming conventions

Step-by-Step Guide

Step 1: Plan Your Storage Account Configuration

Before creating the storage account, decide on these key settings:

Resource Group: Create a dedicated resource group for billing infrastructure (e.g., rg-billing-exports)

Region: Choose a region close to where you'll analyze the data. For global organizations, consider the primary location of your FinOps team.

Performance Tier: Standard performance is sufficient for cost exports (exports are not performance-intensive)

Redundancy: Locally Redundant Storage (LRS) is usually adequate for cost data, as you can regenerate exports if needed

Access Tier: Hot tier for frequently accessed data, Cool tier if you archive older exports

Step 2: Create Storage Account via Azure Portal

  1. Navigate to Storage Accounts

    • Sign in to the Azure Portal
    • Click Create a resource > Storage account
    • Or search for "Storage accounts" in the top search bar
  2. Configure Basics

    • Subscription: Select your Azure subscription
    • Resource group: Create new or select existing (e.g., rg-billing-exports)
    • Storage account name: Enter a globally unique name (e.g., sacostexports<company>)
      • Must be 3-24 characters, lowercase letters and numbers only
      • Example: sacostexportscontoso
    • Region: Select your preferred region (e.g., East US)
    • Performance: Standard
    • Redundancy: Locally-redundant storage (LRS)
  3. Configure Advanced Settings

    • Security:
      • Enable "Require secure transfer for REST API operations"
      • Enable "Allow enabling public access on containers" (required for some export scenarios)
      • Set "Minimum TLS version" to TLS 1.2
      • Disable "Enable storage account key access" if using Azure AD authentication only
    • Data Lake Storage Gen2:
      • Enable "Hierarchical namespace" if you plan to use advanced data lake features
      • Not required for basic cost exports
    • Blob storage:
      • Set "Access tier" to Hot (or Cool if you'll archive data)
  4. Configure Networking

    • Network access:
      • Select "Enable public access from all networks" (simplest for getting started)
      • Or "Enable public access from selected virtual networks and IP addresses" for enhanced security
    • Network routing: Microsoft network routing (default)
  5. Configure Data Protection

    • Recovery:
      • Enable "Enable point-in-time restore for containers" (optional, adds cost)
      • Enable "Enable soft delete for blobs" (7 days retention recommended)
    • Tracking:
      • Enable "Enable versioning for blobs" (optional, useful for audit trail)
  6. Add Tags (optional but recommended)

    • Environment: Production
    • Purpose: CostManagement
    • ManagedBy: FinOps
    • CostCenter: Finance
  7. Review and Create

    • Review all settings
    • Click Create
    • Wait 1-2 minutes for deployment to complete

Step 3: Create Storage Account via Azure CLI

# Set variables
RESOURCE_GROUP="rg-billing-exports"
LOCATION="eastus"
STORAGE_ACCOUNT="sacostexportscontoso"

# Create resource group
az group create \
  --name $RESOURCE_GROUP \
  --location $LOCATION \
  --tags Environment=Production Purpose=CostManagement ManagedBy=FinOps

# Create storage account
az storage account create \
  --name $STORAGE_ACCOUNT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --sku Standard_LRS \
  --kind StorageV2 \
  --access-tier Hot \
  --https-only true \
  --min-tls-version TLS1_2 \
  --allow-blob-public-access true \
  --tags Environment=Production Purpose=CostManagement

# Enable soft delete for blobs (7 days)
az storage blob service-properties delete-policy update \
  --account-name $STORAGE_ACCOUNT \
  --enable true \
  --days-retained 7

# Display storage account details
az storage account show \
  --name $STORAGE_ACCOUNT \
  --resource-group $RESOURCE_GROUP \
  --output table

Step 4: Create Storage Account via PowerShell

# Set variables
$ResourceGroup = "rg-billing-exports"
$Location = "East US"
$StorageAccountName = "sacostexportscontoso"

# Create resource group
New-AzResourceGroup `
  -Name $ResourceGroup `
  -Location $Location `
  -Tag @{Environment="Production"; Purpose="CostManagement"; ManagedBy="FinOps"}

# Create storage account
New-AzStorageAccount `
  -ResourceGroupName $ResourceGroup `
  -Name $StorageAccountName `
  -Location $Location `
  -SkuName Standard_LRS `
  -Kind StorageV2 `
  -AccessTier Hot `
  -EnableHttpsTrafficOnly $true `
  -MinimumTlsVersion TLS1_2 `
  -AllowBlobPublicAccess $true `
  -Tag @{Environment="Production"; Purpose="CostManagement"}

# Enable blob soft delete
Enable-AzStorageDeleteRetentionPolicy `
  -ResourceGroupName $ResourceGroup `
  -StorageAccountName $StorageAccountName `
  -RetentionDays 7

# Display storage account information
Get-AzStorageAccount `
  -ResourceGroupName $ResourceGroup `
  -Name $StorageAccountName

Step 5: Create Container for Cost Exports

After creating the storage account, create a container to store the export files:

Via Azure Portal:

  1. Navigate to your storage account
  2. Select Containers under Data storage
  3. Click + Container
  4. Name: cost-exports (or exports)
  5. Public access level: Private (no anonymous access)
  6. Click Create

Via Azure CLI:

# Create container
az storage container create \
  --name cost-exports \
  --account-name $STORAGE_ACCOUNT \
  --auth-mode login

# Verify container creation
az storage container list \
  --account-name $STORAGE_ACCOUNT \
  --auth-mode login \
  --output table

Via PowerShell:

# Get storage account context
$Context = (Get-AzStorageAccount `
  -ResourceGroupName $ResourceGroup `
  -Name $StorageAccountName).Context

# Create container
New-AzStorageContainer `
  -Name "cost-exports" `
  -Context $Context `
  -Permission Off

# List containers
Get-AzStorageContainer -Context $Context

Step 6: Configure Access Permissions

Grant Cost Management service permission to write to your storage account:

Via Azure Portal:

  1. Navigate to your storage account
  2. Select Access Control (IAM) from the left menu
  3. Click + Add > Add role assignment
  4. Role: Storage Blob Data Contributor
  5. Assign access to: User, group, or service principal
  6. Members: Search for "Microsoft.CostManagement" or "Cost Management"
  7. Click Review + assign

Via Azure CLI:

# Get storage account ID
STORAGE_ACCOUNT_ID=$(az storage account show \
  --name $STORAGE_ACCOUNT \
  --resource-group $RESOURCE_GROUP \
  --query id \
  --output tsv)

# Assign Storage Blob Data Contributor role to Cost Management
az role assignment create \
  --assignee "00000000-0000-0000-0000-000000000000" \
  --role "Storage Blob Data Contributor" \
  --scope $STORAGE_ACCOUNT_ID

# Note: Replace the assignee with the actual Cost Management service principal ID
# You may need to grant access during export configuration instead

Step 7: Enable Lifecycle Management (Optional)

Configure automatic archival or deletion of old export files:

Via Azure Portal:

  1. Navigate to your storage account
  2. Select Lifecycle Management under Data management
  3. Click + Add rule
  4. Rule name: ArchiveOldExports
  5. Rule scope: Limit blobs with filters
  6. Blob type: Block blobs
  7. Blob subtype: Base blobs
  8. Configure actions:
    • Move to cool storage after: 90 days
    • Move to archive storage after: 180 days
    • Delete after: 730 days (2 years)
  9. Filter set: cost-exports/
  10. Click Add

Via Azure CLI:

# Create lifecycle policy JSON
cat > lifecycle-policy.json << EOF
{
  "rules": [
    {
      "enabled": true,
      "name": "ArchiveOldExports",
      "type": "Lifecycle",
      "definition": {
        "actions": {
          "baseBlob": {
            "tierToCool": {
              "daysAfterModificationGreaterThan": 90
            },
            "tierToArchive": {
              "daysAfterModificationGreaterThan": 180
            },
            "delete": {
              "daysAfterModificationGreaterThan": 730
            }
          }
        },
        "filters": {
          "blobTypes": ["blockBlob"],
          "prefixMatch": ["cost-exports/"]
        }
      }
    }
  ]
}
EOF

# Apply lifecycle policy
az storage account management-policy create \
  --account-name $STORAGE_ACCOUNT \
  --resource-group $RESOURCE_GROUP \
  --policy @lifecycle-policy.json

Step 8: Document Storage Account Details

Record these details for configuring your cost export:

  • Storage account name: sacostexportscontoso
  • Container name: cost-exports
  • Resource ID: Found in storage account Overview page
  • Connection string: Found in storage account Access keys (if needed)
  • Region: eastus

Best Practices

Security

  • Use Azure AD authentication instead of storage account keys when possible
  • Enable firewall rules to restrict access to specific IPs or VNets after initial setup
  • Enable soft delete to protect against accidental deletion (7-30 days retention)
  • Disable public blob access unless specifically required
  • Use Private Endpoints for enhanced security in production environments

Cost Optimization

  • Use LRS redundancy for cost data (not mission-critical data)
  • Implement lifecycle policies to automatically move old exports to Cool or Archive tier
  • Monitor storage costs as exports can grow quickly with detailed data
  • Delete unnecessary exports after data has been processed or archived elsewhere

Naming Conventions

  • Storage account: sa<purpose><environment><company> (e.g., sacostexportsprodcontoso)
  • Container: cost-exports, billing-exports, or exports
  • Resource group: rg-billing-<environment> (e.g., rg-billing-prod)

Organization

  • Dedicated resource group for all billing/cost management resources
  • Consistent tagging for cost allocation and governance
  • Separate storage accounts for different environments (dev, test, prod)
  • Document naming conventions for export folders and files

Troubleshooting

Storage Account Name Already Taken

Problem: Error "The storage account named X is already taken"

Solution: Storage account names must be globally unique across all Azure customers. Try:

  • Adding your company name or abbreviation: sacostexportscontoso
  • Adding random numbers: sacostexports2025
  • Using a different prefix: billingexportscontoso

Cannot Create Storage Account in Subscription

Problem: "Quota exceeded" or subscription limit error

Solution:

  • Check subscription limits: Azure Portal > Subscriptions > Usage + quotas
  • Request quota increase via Azure Support
  • Delete unused storage accounts
  • Use an existing storage account with a new container

Cost Management Cannot Write to Storage Account

Problem: Export fails with "Access denied" or "Authorization failed"

Solution:

  • Verify Storage Blob Data Contributor role is assigned
  • Check that "Allow enabling public access on containers" is enabled (required for some export types)
  • Ensure storage account firewall allows Cost Management service
  • Verify container exists and name matches export configuration

High Storage Costs

Problem: Unexpected storage costs accumulating

Solution:

  • Review current storage usage: Storage account > Metrics > Used capacity
  • Implement lifecycle management to archive/delete old exports
  • Check if blob versioning or soft delete retention is too long
  • Consider moving to Cool tier if access is infrequent
  • Export at lower frequency (weekly vs daily) if appropriate

Container Not Visible in Export Configuration

Problem: Cannot select container when configuring export

Solution:

  • Ensure you have Cost Management Contributor role on billing scope
  • Verify storage account is in same Azure AD tenant
  • Check that container name follows naming rules (lowercase, no special chars)
  • Try creating export via Azure CLI/PowerShell if Portal has issues

Next Steps

After creating your storage account:

  1. Configure Cost Management Export: Set up automated daily or weekly exports

    • See: "How to Enable Cost Management Export to Azure Storage"
  2. Set Up IAM Roles: Grant appropriate team members access to view cost data

    • See: "How to Grant IAM Roles for Azure Cost Management Data Export"
  3. Integrate with Analytics Tools: Connect storage account to Power BI, Azure Synapse, or other tools

    • See: "How to View Azure Billing Data in Azure Synapse or Power BI"
  4. Configure Monitoring: Set up alerts for export failures or storage capacity issues

    • See: "How to Monitor Cost Export Status and Data Freshness in Azure"
  5. Implement Security: Review and harden storage account security settings

    • See: "How to Secure Cost Management Data in Azure Storage and Synapse"

Related Resources

Frequently Asked Questions

Find answers to common questions

If you receive the error indicating the storage account name is already taken, remember that storage account names must be globally unique across Azure. To resolve this, modify your desired name by incorporating your organization’s name or abbreviation (e.g., 'sacostexportscontoso'), adding random numbers (e.g., 'sacostexports2025'), or using a different prefix (e.g., 'billingexportscontoso'). This approach will help you create a unique name that complies with Azure's naming rules.

Need Professional Help?

Our team of experts can help you implement and configure these solutions for your organization.