Deploying Multi-Cloud Infrastructure with Terraform Modules
Modern infrastructure is no longer confined to a single region, account, or even cloud provider. As systems scale, the ability to orchestrate resources across multiple environments becomes essential. Terraform’s provider system enables exactly this—but only if you understand how to structure modules correctly.
In this post, I’ll walk through:
The provider alias pattern for reusable modules
How
configuration_aliasesworksWiring providers into modules using the
providersmapA Docker-based quick start
And finally, deploying a production-ready Kubernetes workload on Amazon EKS using Terraform
Why Provider Design Matters in Terraform
Terraform separates infrastructure logic (modules) from environment configuration (providers).
This separation becomes critical when:
Deploying across multiple AWS regions
Working with multiple AWS accounts
Combining different providers (AWS, Kubernetes, Docker)
A common mistake is trying to define providers inside modules. This breaks reusability and makes modules rigid.
The correct pattern: 👉 Providers are defined in the root module and passed into child modules
The Provider Alias Pattern for Modules
When working with multiple regions or accounts, you define multiple provider instances using aliases.
Root Module
provider "aws" {
alias = "primary"
region = "us-east-1"
}
provider "aws" {
alias = "replica"
region = "us-west-2"
}
These represent two distinct AWS environments.
Module Definition
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
configuration_aliases = [aws.primary, aws.replica]
}
}
}
Key Insight: configuration_aliases
This tells Terraform:
“This module expects multiple AWS provider instances”
“Specifically, aliases named
primaryandreplica”
Without this, Terraform cannot safely map providers into the module.
Wiring Providers into the Module
module "multi_region_app" {
source = "../../modules/multi-region-app"
app_name = "my-app"
providers = {
aws.primary = aws.primary
aws.replica = aws.replica
}
}
This providers map explicitly connects:
- Root module providers → Module expectations
Using Providers Inside the Module
resource "aws_s3_bucket" "primary" {
provider = aws.primary
bucket = "${var.app_name}-primary"
}
resource "aws_s3_bucket" "replica" {
provider = aws.replica
bucket = "${var.app_name}-replica"
}
Each resource is pinned to a specific provider instance.
Why Modules Must Not Define Their Own Providers
If a module defines its own providers:
It hardcodes regions and credentials
It becomes non-reusable
It prevents multi-environment deployments
Instead, modules should:
Declare what providers they need
Let the root module decide how those providers are configured
This is a core Terraform design principle.
Quick Start: Running Containers with the Docker Provider
Before jumping into Kubernetes, Terraform can manage containers locally using the Docker provider.
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0"
}
}
}
provider "docker" {}
resource "docker_image" "nginx" {
name = "nginx:latest"
}
resource "docker_container" "nginx" {
image = docker_image.nginx.image_id
name = "terraform-nginx"
ports {
internal = 80
external = 8080
}
}
After running:
terraform apply
Nginx becomes available at:
👉 http://localhost:8080
This is a fast way to validate container behavior before deploying to a cloud platform.
From Containers to Kubernetes: Deploying on Amazon EKS
Once you understand container basics, the next step is orchestration. Terraform integrates directly with Kubernetes through providers.
Step 1: Provision an EKS Cluster
Using the official AWS module:
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "terraform-challenge-cluster"
cluster_version = "1.29"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
eks_managed_node_groups = {
default = {
desired_size = 2
instance_types = ["t3.small"]
}
}
}
This provisions:
Managed Kubernetes control plane
Worker nodes
Networking infrastructure
Step 2: Configure the Kubernetes Provider
provider "kubernetes" {
host = module.eks.cluster_endpoint
cluster_ca_certificate = base64decode(
module.eks.cluster_certificate_authority_data
)
exec {
command = "aws"
args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
}
}
How Authentication Works
Terraform executes:
aws eks get-tokenAWS returns a temporary authentication token
The Kubernetes provider uses this token to authenticate
This approach:
Avoids static credentials
Leverages IAM securely
Step 3: Deploy a Kubernetes Workload
resource "kubernetes_deployment" "nginx" {
metadata {
name = "nginx-deployment"
}
spec {
replicas = 2
selector {
match_labels = {
app = "nginx"
}
}
template {
metadata {
labels = {
app = "nginx"
}
}
spec {
container {
name = "nginx"
image = "nginx:latest"
port {
container_port = 80
}
}
}
}
}
}
After deployment:
kubectl get pods
You should see running pods across your cluster.
How Terraform Connects Everything
Terraform builds a dependency graph:
EKS cluster is created
Outputs (endpoint, certificate) are exposed
Kubernetes provider consumes these outputs
Kubernetes resources deploy into the cluster
This seamless chaining is one of Terraform’s most powerful features.
Cost Considerations
Running an EKS cluster is not free:
Control plane: ~$0.10/hour
EC2 nodes: variable (~$4–6/day)
Networking and storage costs
👉 Approximate daily cost: $7–12
Always run:
terraform destroy
after testing to avoid unnecessary charges.
Key Takeaways
Provider aliasing enables multi-region and multi-account deployments
configuration_aliasesdefines expected provider inputs for modulesThe
providersmap wires root configurations into modules explicitlyTerraform can manage everything from local containers → Kubernetes clusters
EKS + Kubernetes integration showcases Terraform’s full orchestration power
Final Thoughts
Today’s workflow demonstrated a complete progression:
Local Docker → Multi-provider Terraform modules → Kubernetes on AWS
This is the foundation of modern infrastructure engineering:
Modular
Environment-agnostic
Fully automated
Mastering provider patterns is what unlocks Terraform at scale.





