Platform Admin Quickstart -- Deploy and Manage in 45 Minutes¶
Time: 45 minutes Difficulty: Intermediate What you'll do: Deploy the CSA-in-a-Box foundation infrastructure using Bicep, configure monitoring and alerting, and set up cost management budgets and alerts so you can operate the platform from day one.
Prerequisites¶
- Azure subscription with Owner role at the subscription level
- Azure CLI 2.50+ -- Install guide
- Bicep CLI 0.22+ (bundled with recent Azure CLI; verify with
az bicep version) - Git -- git-scm.com
- A target Azure region selected (e.g.,
eastus2,usgovvirginia)
Architecture Diagram¶
graph TB
subgraph Deployment["Bicep Templates"]
ALZ["ALZ Layer<br/>Logging, Policy, Hub VNet"]
DMLZ["DMLZ Layer<br/>Purview, Key Vault, DNS"]
DLZ["DLZ Layer<br/>Storage, Databricks,<br/>Synapse, Data Factory"]
SHARED["Shared Modules<br/>Private Endpoints, NSGs,<br/>Dashboards, Alerts"]
end
subgraph AzureResources["Azure Resources"]
HUB["Hub VNet<br/>Firewall, Bastion"]
SPOKE["Spoke VNet<br/>Data Platform Subnets"]
DATA["Data Services<br/>ADLS, Databricks, Synapse"]
GOV["Governance<br/>Purview, Key Vault"]
end
subgraph Operations["Operational Layer"]
MONITOR["Azure Monitor<br/>Diagnostic Settings"]
DASH["Dashboards<br/>Platform Health"]
ALERTS["Alert Rules<br/>Service Health, Metrics"]
COST["Cost Management<br/>Budgets, Forecasts"]
end
ALZ --> HUB
DMLZ --> GOV
DLZ --> DATA
SHARED --> SPOKE
AzureResources --> MONITOR
MONITOR --> DASH
MONITOR --> ALERTS
COST --> ALERTS Step 1 -- Clone and Review Structure¶
Bicep templates are organized under deploy/bicep/:
deploy/bicep/
landing-zone-alz/ # Azure Landing Zone -- logging, policy, hub networking
01_Logging/ # Log Analytics, diagnostic settings
02_Policy/ # Azure Policy assignments and custom definitions
03_Network/ # Hub VNet, Firewall, Bastion, VPN Gateway
modules/ # Reusable ALZ modules
DMLZ/ # Data Management LZ -- Purview, Key Vault, DNS zones
DLZ/ # Data LZ -- Storage, Databricks, Synapse, Data Factory
shared/ # Cross-cutting: networking, dashboards, alerts, security
gov/ # Azure Government variant modules
Deploy sequentially: ALZ first (foundation), then DMLZ (governance), then DLZ (data services).
Step 2 -- Configure Parameters¶
Copy the sample parameter files and customize them for your environment.
Key Parameters¶
| Parameter | Description |
|---|---|
location | Target Azure region |
environmentPrefix | Environment name prefix (e.g., dev, prd) |
hubVnetAddressPrefix | Hub VNet CIDR (e.g., 10.0.0.0/16) |
spokeVnetAddressPrefix | Spoke VNet CIDR (e.g., 10.1.0.0/16) |
logAnalyticsWorkspaceId | Resource ID of the Log Analytics workspace |
keyVaultName | Globally unique Key Vault name |
storageAccountName | Globally unique storage account name |
adminGroupObjectId | Entra ID group for platform admins |
Environment-Specific Overrides¶
cp deploy/bicep/landing-zone-alz/03_Network/samples/baseline.sample.bicep \
deploy/bicep/landing-zone-alz/03_Network/dev.parameters.json
Replace all placeholder values (<sub-id>, <region>, <prefix>) with your environment specifics.
Step 3 -- Deploy the Landing Zone¶
Deploy the three layers in order using az deployment sub create.
Deploy ALZ Foundation¶
LOCATION="eastus2"
ENV_PREFIX="dev"
az deployment sub create \
--name "alz-logging-${ENV_PREFIX}" \
--location "$LOCATION" \
--template-file deploy/bicep/landing-zone-alz/01_Logging/logging/logging.bicep \
--parameters location="$LOCATION" environmentPrefix="$ENV_PREFIX"
az deployment sub create \
--name "alz-policy-${ENV_PREFIX}" \
--location "$LOCATION" \
--template-file deploy/bicep/landing-zone-alz/02_Policy/main.bicep \
--parameters location="$LOCATION" environmentPrefix="$ENV_PREFIX"
az deployment sub create \
--name "alz-network-${ENV_PREFIX}" \
--location "$LOCATION" \
--template-file deploy/bicep/landing-zone-alz/03_Network/hubNetworking/hubNetworking.bicep \
--parameters location="$LOCATION" environmentPrefix="$ENV_PREFIX"
Deploy DMLZ and DLZ¶
az deployment sub create \
--name "dmlz-${ENV_PREFIX}" \
--location "$LOCATION" \
--template-file deploy/bicep/DMLZ/main.bicep \
--parameters location="$LOCATION" environmentPrefix="$ENV_PREFIX"
az deployment sub create \
--name "dlz-${ENV_PREFIX}" \
--location "$LOCATION" \
--template-file deploy/bicep/DLZ/main.bicep \
--parameters location="$LOCATION" environmentPrefix="$ENV_PREFIX"
For a complete walkthrough, see Tutorial 01: Foundation Platform.
Step 4 -- Verify Deployment¶
Check Resource Groups¶
az group list \
--query "[?starts_with(name, '${ENV_PREFIX}')].{Name:name, Location:location, State:properties.provisioningState}" \
--output table
Expected resource groups: {prefix}-rg-logging, {prefix}-rg-network, {prefix}-rg-governance, {prefix}-rg-data.
Verify Networking¶
az network vnet peering list \
--resource-group "${ENV_PREFIX}-rg-network" \
--vnet-name "${ENV_PREFIX}-vnet-hub" \
--query "[].{Peering:name, State:peeringState}" \
--output table
az network private-dns zone list \
--resource-group "${ENV_PREFIX}-rg-network" \
--query "[].{Zone:name, RecordSets:numberOfRecordSets}" \
--output table
Peering state should be Connected. Private DNS zones should exist for privatelink.blob.core.windows.net, privatelink.dfs.core.windows.net, and others.
Test Private Endpoint Connectivity¶
# Verify private endpoint DNS resolves to private IP
nslookup ${ENV_PREFIX}datalake.blob.core.windows.net
az network private-endpoint list \
--resource-group "${ENV_PREFIX}-rg-data" \
--query "[].{Name:name, Status:privateLinkServiceConnections[0].privateLinkServiceConnectionState.status}" \
--output table
Step 5 -- Configure Monitoring¶
Enable Diagnostic Settings¶
az monitor diagnostic-settings list \
--resource "/subscriptions/<sub-id>/resourceGroups/${ENV_PREFIX}-rg-data/providers/Microsoft.Storage/storageAccounts/${ENV_PREFIX}datalake" \
--query "[].{Name:name, Workspace:workspaceId}" \
--output table
# If missing, create them
az monitor diagnostic-settings create \
--name "send-to-loganalytics" \
--resource "/subscriptions/<sub-id>/resourceGroups/${ENV_PREFIX}-rg-data/providers/Microsoft.Storage/storageAccounts/${ENV_PREFIX}datalake" \
--workspace "/subscriptions/<sub-id>/resourceGroups/${ENV_PREFIX}-rg-logging/providers/Microsoft.OperationalInsights/workspaces/${ENV_PREFIX}-la" \
--metrics '[{"category":"Transaction","enabled":true}]' \
--logs '[{"category":"StorageRead","enabled":true},{"category":"StorageWrite","enabled":true}]'
Deploy Dashboard and Alert Rules¶
az deployment group create \
--resource-group "${ENV_PREFIX}-rg-logging" \
--template-file deploy/bicep/shared/modules/dashboards/platformDashboard.bicep \
--parameters workspaceId="/subscriptions/<sub-id>/resourceGroups/${ENV_PREFIX}-rg-logging/providers/Microsoft.OperationalInsights/workspaces/${ENV_PREFIX}-la"
az deployment group create \
--resource-group "${ENV_PREFIX}-rg-logging" \
--template-file deploy/bicep/shared/modules/alerts/serviceHealth.bicep \
--parameters actionGroupId="/subscriptions/<sub-id>/resourceGroups/${ENV_PREFIX}-rg-logging/providers/Microsoft.Insights/actionGroups/platform-admins"
az deployment group create \
--resource-group "${ENV_PREFIX}-rg-logging" \
--template-file deploy/bicep/shared/modules/alerts/alertRules.bicep \
--parameters workspaceId="/subscriptions/<sub-id>/resourceGroups/${ENV_PREFIX}-rg-logging/providers/Microsoft.OperationalInsights/workspaces/${ENV_PREFIX}-la"
Verify Data Flowing to Log Analytics¶
az monitor log-analytics query \
--workspace "${ENV_PREFIX}-la" \
--analytics-query "Usage | summarize TotalMB=sum(Quantity) by DataType | order by TotalMB desc | take 10" \
--output table
Step 6 -- Set Up Cost Management¶
Create a Monthly Budget¶
az consumption budget create \
--budget-name "${ENV_PREFIX}-monthly-budget" \
--amount 5000 \
--time-grain Monthly \
--start-date "2026-05-01" \
--end-date "2027-04-30" \
--resource-group "${ENV_PREFIX}-rg-data" \
--category Cost
Configure Cost Alert Thresholds¶
az consumption budget create \
--budget-name "${ENV_PREFIX}-cost-alerts" \
--amount 5000 \
--time-grain Monthly \
--start-date "2026-05-01" \
--end-date "2027-04-30" \
--category Cost \
--notifications '{
"Actual_50_Percent": {
"enabled": true, "operator": "GreaterThan", "threshold": 50,
"contactEmails": ["platform-team@contoso.com"], "thresholdType": "Actual"
},
"Actual_80_Percent": {
"enabled": true, "operator": "GreaterThan", "threshold": 80,
"contactEmails": ["platform-team@contoso.com","finance@contoso.com"], "thresholdType": "Actual"
},
"Forecasted_100_Percent": {
"enabled": true, "operator": "GreaterThan", "threshold": 100,
"contactEmails": ["platform-team@contoso.com","management@contoso.com"], "thresholdType": "Forecasted"
}
}'
Review Current Spend and Tags¶
az costmanagement query \
--type ActualCost --scope "subscriptions/<sub-id>" \
--timeframe MonthToDate \
--dataset-grouping name="ResourceGroup" type="Dimension" --output table
Ensure all resource groups carry cost-allocation tags:
az group list \
--query "[?starts_with(name, '${ENV_PREFIX}')].{Name:name, CostCenter:tags.CostCenter, Owner:tags.Owner}" \
--output table
az group update \
--name "${ENV_PREFIX}-rg-data" \
--tags CostCenter="DataPlatform" Owner="platform-team" Environment="$ENV_PREFIX"
Step 7 -- Operational Readiness¶
Verify DR and Backup¶
# Verify storage replication -- production should use GRS or RA-GRS
az storage account list \
--query "[?starts_with(name, '${ENV_PREFIX}')].{Name:name, SKU:sku.name}" \
--output table
# List backup policies
az backup policy list \
--vault-name <vault-name> \
--resource-group <rg-name> \
--query "[].{Name:name, Type:properties.backupManagementType}" \
--output table
Verify Break-Glass Access and Lock Resources¶
az ad user list \
--filter "startswith(displayName, 'BreakGlass')" \
--query "[].{Name:displayName, UPN:userPrincipalName}" \
--output table
Test break-glass access per the Break-Glass Access Runbook. Apply locks:
az lock create --name "protect-production" \
--resource-group "${ENV_PREFIX}-rg-data" --lock-type CanNotDelete
az lock create --name "protect-governance" \
--resource-group "${ENV_PREFIX}-rg-governance" --lock-type CanNotDelete
Day-2 Operations Checklist¶
- Daily: Review Azure Service Health for active incidents
- Weekly: Review cost trends and compare against budget
- Weekly: Check Log Analytics ingestion volume
- Weekly: Review failed pipeline runs in Data Factory and Databricks
- Monthly: Run the DR Drill Runbook
- Monthly: Rotate secrets approaching expiry (Key Rotation Runbook)
- Monthly: Review RBAC assignments for drift
- Quarterly: Review Azure Advisor recommendations
- Quarterly: Re-assess reserved instance coverage
- Quarterly: Conduct a tabletop security exercise
- Annually: Conduct a full Well-Architected Framework review
Troubleshooting¶
| Symptom | Probable Cause | Resolution |
|---|---|---|
az deployment sub create fails with AuthorizationFailed | Missing Owner role at subscription scope | Verify role with az role assignment list --assignee <upn> --scope /subscriptions/<sub-id> |
| Bicep compilation error on deploy | Bicep CLI version mismatch | Update with az bicep upgrade and verify minimum 0.22 |
VNet peering stuck in Initiated state | Peering created in only one direction | Create the reciprocal peering from spoke to hub VNet |
| Private DNS resolution returns public IP | Private DNS zone not linked to VNet | Link the zone: az network private-dns link vnet create |
| Diagnostic settings show no data after 1 hour | Resource provider not emitting for selected categories | Verify categories with az monitor diagnostic-settings categories list --resource <id> |
Budget creation fails with InvalidTimeGrain | Start date is in the past or not first of month | Use a future first-of-month date |
| Cost query returns empty results | Cost Management data has a 24-48 hour delay | Wait for data to populate; use Portal for near-real-time estimates |
az consumption budget command not found | Azure CLI consumption extension missing | Install with az extension add --name consumption |
Related Resources¶
- Architecture Overview -- full CSA-in-a-Box architecture
- Tutorial 01: Foundation Platform -- detailed deployment walkthrough
- IaC & CI/CD Best Practices -- Bicep authoring patterns
- Cost Optimization Best Practices -- cost optimization strategies
- Monitoring & Observability -- Log Analytics, dashboards, alerts
- Disaster Recovery -- RPO/RTO, failover, backup
- Hub-Spoke Topology -- network architecture
- Break-Glass Access Runbook -- emergency access
- Data Pipeline Failure Runbook -- pipeline troubleshooting
- DR Drill Runbook -- DR exercise procedures