Azure FinOps Lab is a Terraform-first cost optimization sandbox for learning how to control Azure spend before, during, and after deployment. It creates a small workload plus the FinOps controls around it: budgets, alerts, tags, policy, Cost Management exports, Infracost checks, auto-shutdown, dashboards, and evidence capture.
The default profile is intentionally low cost. The lab gives you enough Azure infrastructure to measure and optimize without deploying expensive platform services.
| Area | What it deploys | Why it matters |
|---|---|---|
| Platform resource group | Log Analytics, action group, cost export storage, dashboard, workbook | Central place for cost visibility and evidence. |
| Workload resource group | Small Windows IIS VM, VNet, subnet, NSG, public IP | A real workload for rightsizing, shutdown, and tag exercises. |
| Budgets | Subscription and workload resource group budgets | Shows actual and forecasted cost thresholds. |
| Policy | Required tag audit and allowed VM SKU audit | Teaches governance without blocking labs by default. |
| Cost export | Scheduled subscription actual-cost export to Storage | Builds the reporting pipeline for offline analysis. |
| CI/CD | Terraform validation, security checks, Infracost, manual lifecycle | Teaches FinOps controls before apply. |
deploy_budgets = true
deploy_tag_policy = true
deploy_cost_export = true
deploy_workload_vm = true
deploy_monitoring = true
deploy_auto_shutdown = true
deploy_dashboards = true
monthly_subscription_budget_amount = 150
monthly_lab_rg_budget_amount = 50
policy_effect = "Audit"
vm_size = "Standard_B1s"
auto_shutdown_time = "1900"Keep policy_effect = "Audit" for workshops. Move to Deny only after validating the lab and explaining the blast radius.
| Profile | File | Purpose | Default posture |
|---|---|---|---|
| Dev | environments/dev.tfvars |
Fast validation with no Cost Management export. | Lowest cost |
| Lab | environments/lab.tfvars |
Main workshop profile with budgets, export, workload, and dashboards. | Recommended |
| Full | environments/full.tfvars |
Bigger comparison VM budget and SKU for rightsizing discussions. | Higher cost |
Prerequisites:
- Terraform 1.9 or later
- Azure CLI
- PowerShell 7+
- Azure permissions for resource groups, budgets, policy assignments, and Cost Management exports
az login
az account set --subscription "<subscription-id>"
Copy-Item terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with subscription_id, owner, budget_contact_emails, admin_source_ip_cidr,
# budget_start_date for the current month, and cost_export_start_date to a future date.
.\scripts\Test-FinOpsLabStatic.ps1
terraform init
terraform plan -var-file="environments/lab.tfvars"Apply, smoke test, and destroy:
.\scripts\Invoke-FinOpsLabLifecycle.ps1 -Environment lab -Apply -SmokeTest -Destroy -AutoApprove| Scenario | What you practice |
|---|---|
| Budget guardrails | Configure subscription and resource group budgets with actual and forecasted thresholds. |
| Tag governance | Audit missing cost tags and discuss when to move from Audit to Deny. |
| Infracost PR review | Review cost deltas before infrastructure changes merge. |
| Auto-shutdown | Reduce compute cost using Dev/Test VM shutdown schedules. |
| Rightsizing | Compare VM SKU choices and capture Advisor-style optimization evidence. |
| Cost export | Export actual costs for reporting and Power BI or spreadsheet analysis. |
| Dashboard evidence | Use the portal dashboard, workbook, and scripts to collect proof of controls. |
- The VM is the only default compute workload and uses
Standard_B1s. - Azure budgets and policies are subscription-scope controls; use a lab subscription when learning.
- Cost export availability can vary by billing setup. If your tenant blocks it, set
deploy_cost_export = false. admin_source_ip_cidrdefaults to0.0.0.0/32, which is intentionally not a useful public RDP source.- Terraform state contains generated VM credentials. Keep state private and never commit local state.
- Destroy the lab after practice unless you are intentionally collecting cost data over time.
| Start here | Purpose |
|---|---|
| Wiki home | Map of the full documentation set. |
| Book-style guide | End-to-end explanation of the lab and learning path. |
| Architecture overview | Resource layout and data flow. |
| Scenarios | Hands-on exercises. |
| Apply, smoke, destroy runbook | Exact live-lab sequence. |
| Variables | Input reference and recommended defaults. |
| Troubleshooting | Common permissions and deployment issues. |
terraform fmt -check -recursive
terraform init -backend=false -reconfigure
terraform validateOptional tools:
tflint --init
tflint --recursive
checkov -d . --framework terraform
gitleaks detect --source . --redactAzure-FinOps-Lab/
|-- main.tf
|-- variables.tf
|-- outputs.tf
|-- environments/
|-- modules/
|-- scripts/
|-- docs/images/
|-- wiki/
`-- .github/workflows/
MIT. See LICENSE.