100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
HCL

Provisioning Azure and GCP Resources

Understand how the azurerm and google providers differ from AWS in structure and authentication, with practical examples of provisioning core resources on each cloud.

Multi-Cloud & ProvisioningIntermediate10 min readJul 9, 2026
Analogies

Provisioning Azure and GCP Resources

Terraform's multi-cloud, provider-plugin architecture means the same core language and workflow apply to Azure and GCP just as they do to AWS, but each provider mirrors its own cloud's resource model and authentication conventions closely. The azurerm provider organizes almost everything under a resource group, a concept unique to Azure's management hierarchy, while the google provider organizes resources under a project, GCP's top-level billing and IAM boundary. Understanding these organizing concepts is essential before writing any resource blocks for either cloud.

🏏

Cricket analogy: Terraform's provider-plugin model is like the same laws of cricket applying whether you're playing at Lord's or the MCG, but each ground has its own local conventions — Lord's slope, MCG's drop-in pitch — you must respect before setting a field.

Azure: resource groups as the organizing unit

Almost every azurerm resource requires a resource_group_name argument, because Azure requires all resources to belong to exactly one resource group, which acts as a logical container for lifecycle management, access control, and cost tracking. A typical Azure Terraform configuration therefore starts by declaring an azurerm_resource_group resource (or referencing an existing one via data source), and every subsequent resource references its name and location.

🏏

Cricket analogy: Every azurerm resource needing resource_group_name is like every player at an IPL franchise needing to belong to exactly one squad roster — you can't field a player without first registering the franchise, and every subsequent signing references that squad.

hcl
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "main" {
  name     = "rg-webapp-prod"
  location = "East US"
}

resource "azurerm_virtual_network" "main" {
  name                = "vnet-webapp"
  address_space       = ["10.1.0.0/16"]
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
}

resource "azurerm_linux_virtual_machine" "web" {
  name                = "vm-web-01"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  size                = "Standard_B2s"
  admin_username      = "azureadmin"

  network_interface_ids = [azurerm_network_interface.web.id]

  admin_ssh_key {
    username   = "azureadmin"
    public_key = file("~/.ssh/id_rsa.pub")
  }

  os_disk {
    caching              = "ReadWrite"
    storage_account_type = "Standard_LRS"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }
}

The azurerm provider's near-empty features {} block is not decorative — it's a required argument that configures provider-wide behaviors (like whether deleted resource groups are purged) and Terraform will refuse to initialize the provider without it, even with all defaults.

GCP: projects, regions, and zones

The google provider is configured with a project ID and a default region/zone, and most resources inherit location settings from the provider block unless overridden per resource. GCP's naming convention tends to be resource-type-first (google_compute_instance, google_storage_bucket, google_sql_database_instance), and authentication is typically handled via a service account key file or, preferably, Application Default Credentials resolved from the environment (e.g. Workload Identity in CI).

🏏

Cricket analogy: The google provider's project ID with a default region mirrors a bilateral series' host board setting the default venue and pitch conditions, while individual matches (resources) can still be assigned a different ground when specifically scheduled otherwise.

hcl
provider "google" {
  project = "acme-prod-247501"
  region  = "us-central1"
  zone    = "us-central1-a"
}

resource "google_compute_network" "main" {
  name                    = "vpc-webapp"
  auto_create_subnetworks = false
}

resource "google_compute_subnetwork" "main" {
  name          = "subnet-webapp"
  ip_cidr_range = "10.2.0.0/24"
  region        = "us-central1"
  network       = google_compute_network.main.id
}

resource "google_compute_instance" "web" {
  name         = "web-01"
  machine_type = "e2-medium"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-12"
    }
  }

  network_interface {
    subnetwork = google_compute_subnetwork.main.id
    access_config {}
  }
}

A common cross-cloud pitfall: assuming resource argument names and required scaffolding transfer directly between providers. Azure requires a resource group for virtually everything; GCP requires a project and, for networking, an explicit auto_create_subnetworks = false if you intend to manage subnets yourself rather than use the legacy auto-mode network. Skipping these provider-specific requirements is one of the most common sources of first-time multi-cloud Terraform errors.

Multi-cloud configurations

It is entirely valid to declare azurerm, google, and aws providers in the same Terraform configuration when a workload genuinely spans clouds — for example, replicating data to a secondary cloud for disaster recovery. In practice, most teams still isolate each cloud's resources into its own root module or workspace to keep blast radius and state file size manageable, using outputs and remote state data sources to pass values (like a VPN gateway IP) between the two configurations when cross-cloud references are actually needed.

🏏

Cricket analogy: Declaring azurerm, google, and aws providers together is like a franchise fielding players contracted across three different domestic leagues in one squad for a genuine multi-format tour, though most teams still keep each league's roster in its own file.

  • azurerm resources are almost universally scoped to a resource group, which must exist before other resources reference it.
  • The azurerm provider requires a features {} block even when accepting all defaults.
  • google provider resources are scoped to a project and inherit region/zone defaults from the provider block.
  • GCP resource type names are prefixed with google_ and follow a resource-type-first naming convention.
  • Multi-cloud configurations can declare multiple cloud providers together, but most teams isolate each cloud into its own root module for manageable blast radius.
  • Provider-specific scaffolding (resource groups on Azure, projects/auto_create_subnetworks on GCP) is a common source of first-time errors when moving between clouds.

Practice what you learned

Was this page helpful?

Topics covered

#HCL#TerraformInfrastructureAsCodeStudyNotes#DevOps#ProvisioningAzureAndGCPResources#Provisioning#Azure#GCP#Resources#CloudComputing#StudyNotes#SkillVeris