Multi-Cloud: Azure & GCP

Azure Fundamentals

18 min Lesson 2 of 28

Azure Fundamentals

Before you deploy a single resource in Azure, you must understand how Azure organises everything around you. This is not optional — misunderstanding the hierarchy is the root cause of cost blowouts, RBAC accidents, and compliance failures at scale. In this lesson you will build the mental model used by Azure architects at every major cloud workload.

The Azure Hierarchy

Azure structures tenancy through four nested levels: Management Groups → Subscriptions → Resource Groups → Resources. Every object you ever create lives at the bottom of this tree, and every policy or RBAC assignment you attach at any level cascades downward automatically.

Azure Resource Hierarchy Root Management Group Azure AD Tenant boundary · Global Policies Management Group: Production Enforce compliance policies Management Group: Non-Prod Dev / Staging subscriptions Subscription prod-payments Subscription prod-platform Subscription dev-shared Subscription staging-shared Resource Group rg-api-prod-eus Resource Group rg-db-prod-eus AKS / VM Storage / KV
Azure hierarchy: Management Groups wrap Subscriptions, which contain Resource Groups, which hold individual Resources.

Subscriptions: The Billing and Quota Boundary

A subscription is the fundamental unit of billing in Azure. Every resource you create is charged to exactly one subscription. But subscriptions are not just invoices — they also carry per-subscription service quotas (e.g. vCPU limits per region), separate RBAC roots, and independent networking address spaces.

Production workloads at scale use multiple subscriptions deliberately: one per environment (prod, staging, dev), one per business unit, or one per landing zone. This keeps blast radius small — a misconfigured RBAC assignment in a dev subscription cannot touch prod resources in a different subscription.

Enterprise Landing Zone pattern: Microsoft Cloud Adoption Framework prescribes a "Platform" subscription for shared networking and identity, plus one "Application" subscription per workload or team. Your RBAC, policy, and cost centre governance all flow through subscription boundaries. At Microsoft internal scale, teams run hundreds of subscriptions, each with a subscription owner who is accountable for spend and compliance in that boundary.

Resource Groups: Lifecycle Units, Not Just Folders

A resource group is a container inside a subscription. The critical insight is that a resource group represents a lifecycle boundary: when you delete a resource group, every resource inside it is deleted atomically. This single fact drives the grouping convention used in production:

  • Group by application lifecycle, not by resource type. Put a VM, its NIC, its NSG, its managed disk, and its Log Analytics workspace in the same resource group — they are all deployed and destroyed together.
  • Do not group by type (e.g. "all storage accounts in one RG"). This makes deletion, cost attribution, and RBAC painful.
  • Resource groups have a metadata region (where the group record is stored), but resources inside them can span any Azure region.

The naming convention used at enterprise scale: rg-{workload}-{environment}-{short-region}, for example rg-payments-prod-eus (East US) or rg-payments-prod-weu (West Europe).

Production pitfall — orphaned resources: Resources can be moved between resource groups, but not all resource types support moves. Some networking objects (e.g. a VNet with active peerings) cannot be moved while attached to other resources. Always check compatibility with az resource move --validate-only before a live migration, or you risk triggering a delete-and-recreate cycle with downtime.

ARM: Azure Resource Manager

Azure Resource Manager (ARM) is the control plane for every Azure operation. Whether you click in the Azure Portal, run az CLI, call the REST API directly, or deploy Bicep / Terraform — every request is authenticated through Azure Active Directory and dispatched by ARM to the appropriate resource provider (e.g. Microsoft.Compute, Microsoft.Network). ARM provides:

  • Declarative idempotent deployments — ARM templates (JSON) or Bicep describe desired state; ARM computes the delta and applies only what changed.
  • RBAC enforcement — every action is authorized at ARM before it reaches the resource provider. No bypass is possible via the portal.
  • Tagging — arbitrary key/value tags on any resource for cost attribution, automation triggers, and compliance scanning.
  • LocksReadOnly or CanNotDelete locks applied at the resource group or individual resource level prevent accidental changes to production infrastructure.
# --- 1. Log in and select the right subscription --- az login az account list --output table az account set --subscription "prod-payments-sub-id" # --- 2. Create a resource group with lifecycle tags --- az group create \ --name rg-payments-prod-eus \ --location eastus \ --tags environment=prod workload=payments costcenter=CC-2301 managed-by=terraform # --- 3. Verify --- az group show --name rg-payments-prod-eus --output table # --- 4. Apply a CanNotDelete lock --- az lock create \ --name lock-rg-payments-prod \ --resource-group rg-payments-prod-eus \ --lock-type CanNotDelete \ --notes "Production RG — lock owned by platform-team" # --- 5. List current locks on the group --- az lock list --resource-group rg-payments-prod-eus --output table

ARM Templates and Bicep: Infrastructure as Code

ARM accepts JSON templates natively, but Bicep is the modern first-class language for Azure IaC. Bicep compiles to ARM JSON and has full parity with the ARM API. Terraform also targets ARM via the azurerm provider — most large teams use Terraform for multi-cloud portability, while Azure-native shops use Bicep for tighter integration with Azure DevOps and GitHub Actions.

A minimal Bicep example that creates the resource group structure with a storage account:

// main.bicep — deploys a storage account into an existing resource group param location string = resourceGroup().location param env string = 'prod' param workload string = 'payments' var storageAccountName = 'st${workload}${env}${uniqueString(resourceGroup().id)}' resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: storageAccountName location: location kind: 'StorageV2' sku: { name: 'Standard_ZRS' // Zone-redundant — required for any prod storage } properties: { minimumTlsVersion: 'TLS1_2' allowBlobPublicAccess: false supportsHttpsTrafficOnly: true } tags: { environment: env workload: workload 'managed-by': 'bicep' } } output storageId string = storageAccount.id
# Deploy the Bicep template into the resource group az deployment group create \ --resource-group rg-payments-prod-eus \ --template-file main.bicep \ --parameters env=prod workload=payments \ --confirm-with-what-if # always preview in production

RBAC and the ARM Authorization Model

Every principal (user, group, service principal, managed identity) is granted a role on a scope. The scope can be a management group, subscription, resource group, or individual resource. Roles granted at a higher scope are inherited by all children. The three built-in roles you will use most are:

  • Owner — full control including RBAC assignment. Reserve for subscription owners only.
  • Contributor — create and manage resources, but cannot assign roles. Use for CI/CD service principals.
  • Reader — read-only view. Use for on-call engineers who do not need to make changes.
Managed Identity over Service Principals: When your application code running inside Azure (an AKS pod, a Function App, a VM) needs to call ARM or Azure services, use a Managed Identity instead of a service principal with a client secret. Managed identities have no credentials to rotate or leak — Azure handles the credential lifecycle automatically. This is the big-tech standard and is enforced by policy at many enterprises.

Regions, Availability Zones, and the Physical Model

Each Azure region (e.g. eastus, westeurope) is a set of data centres within a latency boundary. Regions that support Availability Zones (AZs) have three or more physically separate data centres with independent power, cooling, and networking — zonal deployments survive a single data centre loss with zero data loss and near-zero downtime. Always deploy production workloads across at least two AZs. Region pairs (e.g. East US / West US) provide geo-redundancy for disaster recovery.

The ARM resource type Microsoft.Resources/resourceGroups is global — it is not tied to an AZ. The resources inside the group are what you pin to zones. When creating an AKS cluster, VM Scale Set, or managed disk, always specify the zones explicitly.