Accessing enterprise infrastructure used to involve wrestling with data center provisioning and on-prem hardware. With Azure, resource deployment is largely declarative—describe the state you want, and let the platform manage the details. In practice, Azure’s interface and CLI each have quirks that can trip up even seasoned engineers. Below, a concise guide to provisioning, configuring, and troubleshooting a basic Azure workload, with focus on automation and robust practices.
Prerequisites
- Azure account (use MFA for all privileged accounts)
az
CLI (version 2.47.0+)az --version # If missing, install: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli
- Resource Group created
az group create --name demo-grp --location eastus
Resource Provisioning: VM Example
A common scenario: spin up an Ubuntu VM for CI runners.
az vm create \
--resource-group demo-grp \
--name ci-agent \
--image UbuntuLTS \
--admin-username devops \
--ssh-key-values ~/.ssh/id_rsa.pub \
--size Standard_B2ms
Note: The Standard_B2ms
SKU offers 2 vCPUs and 8GB RAM. For ephemeral workloads, Spot instances (--priority Spot
) can cut costs but risk interruption.
Gotcha: The default NSG (Network Security Group) rules may block SSH access. Open port 22, but restrict source IPs.
az vm open-port --port 22 --resource-group demo-grp --name ci-agent --priority 1000 --priority 1000
Check the public IP:
az vm show --show-details --resource-group demo-grp --name ci-agent --query publicIps -o tsv
Automation via ARM & Bicep
For reproducibility, define resources as code. Prefer Bicep over raw ARM JSON for readability.
ci-vm.bicep Example:
resource vm 'Microsoft.Compute/virtualMachines@2022-11-01' = {
name: 'ci-agent'
location: resourceGroup().location
properties: {
hardwareProfile: { vmSize: 'Standard_B2ms' }
osProfile: {
adminUsername: 'devops'
computerName: 'ci-agent'
linuxConfiguration: {
disablePasswordAuthentication: true
ssh: {
publicKeys: [
{
keyData: loadTextContent('~/.ssh/id_rsa.pub')
path: '/home/devops/.ssh/authorized_keys'
}
]
}
}
}
storageProfile: { imageReference: { publisher: 'Canonical'; offer: 'UbuntuServer'; sku: '18.04-LTS'; version: 'latest' } }
networkProfile: { ... } // fill out or parametrize for reuse
}
}
Deploy:
az deployment group create --resource-group demo-grp --template-file ci-vm.bicep
Pro Tip: Tag all resources (--tags env=dev,owner=infra
) for cost tracking and lifecycle management.
Monitoring & Troubleshooting
Azure resources emit metrics via Azure Monitor. For VMs, enable diagnostics:
az vm diagnostics set --resource-group demo-grp --vm-name ci-agent --settings './diag-config.json'
Non-obvious detail: Logs tend to surface in Azure Storage, not the portal by default. Set up Log Analytics workspace for better querying.
VM out of quota? Error:
Operation could not be completed as it results in exceeding approved StandardBSFamily Cores quota.
Request quota increase via the Azure Portal, not via CLI.
Clean Up
Unintended resource drift can incur surprise costs. Tear down with:
az group delete --name demo-grp --no-wait --yes
Resource locks (az lock create
) can prevent accidental deletions, but aren’t bulletproof—permissions can always be escalated.
Alternative: For simple workloads or experimentation, consider Azure Cloud Shell—no local setup needed, but limited persistence.
No guide covers every organizational policy or every transient bug. Expect UI deprecations and CLI breaking changes in minor version bumps. Always verify resource states via the portal or az resource list
after automation.