Why Multi-Cloud?
Organizations adopt multi-cloud strategies for several compelling reasons: avoiding vendor lock-in, optimising for best-of-breed services (e.g. GCP BigQuery for analytics, AWS for compute, Azure for enterprise identity), regulatory requirements mandating geographic data distribution, and resilience against regional outages.
Terraform is uniquely suited to multi-cloud because it uses a single declarative language (HCL) for all providers. One team, one workflow, many clouds.
Configuring Multiple Providers
Terraform lets you define multiple providers in the same configuration. Each has its own required_providers entry and authentication:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.90"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
provider "azurerm" {
features {}
subscription_id = var.azure_subscription_id
}
provider "google" {
project = var.gcp_project_id
region = var.gcp_region
}
Provider Aliases for Multi-Region
Use alias to manage resources across multiple regions within the same provider:
provider "aws" {
region = "us-east-1"
alias = "us_east"
}
provider "aws" {
region = "eu-west-1"
alias = "eu_west"
}
resource "aws_instance" "us" {
provider = aws.us_east
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.medium"
}
resource "aws_instance" "eu" {
provider = aws.eu_west
ami = "ami-01720b5f421cf0179"
instance_type = "t3.medium"
}
Cross-Cloud Networking Pattern
A common multi-cloud pattern is connecting AWS and Azure via VPN or ExpressRoute. Here's how to set up the Terraform resources for both sides:
# AWS side โ Virtual Private Gateway
resource "aws_vpn_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = { Name = "multi-cloud-vpgw" }
}
resource "aws_customer_gateway" "azure" {
bgp_asn = 65000
ip_address = azurerm_public_ip.vpn.ip_address
type = "ipsec.1"
}
resource "aws_vpn_connection" "to_azure" {
vpn_gateway_id = aws_vpn_gateway.main.id
customer_gateway_id = aws_customer_gateway.azure.id
type = "ipsec.1"
static_routes_only = false
}
# Azure side โ VPN Gateway
resource "azurerm_virtual_network_gateway" "main" {
name = "azure-vpn-gateway"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
type = "Vpn"
vpn_type = "RouteBased"
sku = "VpnGw1"
ip_configuration {
public_ip_address_id = azurerm_public_ip.vpn.id
subnet_id = azurerm_subnet.gateway.id
}
}
Shared Remote State for Multi-Cloud
When infrastructure spans multiple clouds, you need a way for Terraform configurations to reference each other. Use remote state data sources:
# In your networking module (stored in S3)
terraform {
backend "s3" {
bucket = "company-terraform-state"
key = "networking/terraform.tfstate"
region = "us-east-1"
}
}
# In your application module โ read networking outputs
data "terraform_remote_state" "networking" {
backend = "s3"
config = {
bucket = "company-terraform-state"
key = "networking/terraform.tfstate"
region = "us-east-1"
}
}
resource "aws_instance" "app" {
subnet_id = data.terraform_remote_state.networking.outputs.private_subnet_id
}
Multi-Cloud Directory Structure
Organise your multi-cloud Terraform project by cloud and environment:
infrastructure/
โโโ modules/
โ โโโ networking/ # Reusable networking module
โ โโโ compute/ # Reusable compute module
โ โโโ database/ # Reusable database module
โโโ aws/
โ โโโ dev/
โ โ โโโ main.tf
โ โ โโโ terraform.tfvars
โ โโโ prod/
โ โโโ main.tf
โ โโโ terraform.tfvars
โโโ azure/
โ โโโ dev/
โ โโโ prod/
โโโ gcp/
โโโ dev/
โโโ prod/
Authentication Best Practices
| Cloud | Development | CI/CD (Production) |
|---|---|---|
| AWS | aws configure | OIDC with GitHub Actions / IAM Role |
| Azure | az login | Service Principal + Federated Identity |
| GCP | gcloud auth application-default login | Workload Identity Federation |
.tfvars files. Use environment variables, instance profiles, or managed identity instead.Common Multi-Cloud Patterns
Active-Active Multi-Cloud
Traffic is distributed across two clouds simultaneously. Requires a global load balancer (e.g. Cloudflare or AWS Global Accelerator) and data replication between clouds. Highest availability, highest complexity.
Cloud-of-Choice by Workload
Different workloads run on the best-suited cloud. Example: ML training on GCP Vertex AI, production web on AWS, enterprise identity on Azure AD. Data flows between clouds via API or managed replication.
Active-Passive Failover
Primary workload runs on one cloud; failover region is on another. Lower cost than active-active, provides cloud-level resilience for regulatory or business continuity requirements.
Designing Multi-Cloud Infrastructure Visually
CloudFormation's drag-and-drop canvas supports all 9 cloud providers simultaneously on the same canvas. Draw connections between AWS Transit Gateway and Azure ExpressRoute, then click Generate to get a complete multi-provider Terraform configuration with all provider blocks, cross-references, and variables correctly wired.
Try CloudFormation Free
Design infrastructure visually and generate production-ready Terraform in seconds โ 693 resources across 9 cloud providers.
๐ Open the Designer โ