Building a Multi-Cloud Infrastructure with Terraform: A Complete Project Guide
Prerequisites
Ensure you have the following:
Terraform installed on your machine.
Accounts for each cloud provider: AWS, GCP, and Azure.
Basic knowledge of Terraform and Infrastructure as Code (IaC).
Configured CLI tools for each cloud provider.
Setting Up Your Environment
Install Terraform: Follow the instructions on the Terraform website.
Configure Cloud Provider Credentials for AWS, GCP, and Azure as previously described.
Create a Working Directory: Create a new directory for your project.
mkdir multi-cloud-terraform cd multi-cloud-terraform
Creating a Terraform Project
Create a Terraform Configuration File: Create a file named
main.tf
.terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 3.0" } google = { source = "hashicorp/google" version = "~> 3.0" } azurerm = { source = "hashicorp/azurerm" version = "~> 2.0" } } required_version = ">= 0.12" } provider "aws" { region = "us-west-1" } provider "google" { project = "your-gcp-project-id" region = "us-central1" } provider "azurerm" { features {} }
Provisioning Resources in AWS
EC2 Instance
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2
instance_type = "t2.micro"
tags = {
Name = "AWS-Web-Instance"
}
}
Storage
resource "aws_s3_bucket" "storage" {
bucket = "my-unique-bucket-name"
acl = "private"
}
Web Application Firewall (WAF)
resource "aws_wafv2_web_acl" "web_acl" {
name = "my-web-acl"
scope = "REGIONAL" # or "CLOUDFRONT"
default_action {
allow {}
}
rule {
name = "RateLimitRule"
priority = 1
action {
block {}
}
statement {
rate_based_statement {
limit = 2000
aggregate_key_type = "IP"
scope_down_statement {
byte_match_statement {
search_string = "bad-bot"
field_to_match {
uri_path {}
}
positional_constraint = "CONTAINS"
text_transformation = "NONE"
}
}
}
}
}
}
Private Endpoints
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.us-west-1.s3"
}
Provisioning Resources in GCP
Compute Engine Instance
resource "google_compute_instance" "web" {
name = "gcp-web-instance"
machine_type = "f1-micro"
zone = "us-central1-a"
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {}
}
metadata_startup_script = "apt-get update; apt-get install -y nginx"
}
Storage
resource "google_storage_bucket" "storage" {
name = "my-gcp-unique-bucket"
location = "US"
}
Web Application Firewall (WAF)
GCP uses Cloud Armor for WAF functionality. Here's a basic setup:
resource "google_compute_security_policy" "waf_policy" {
name = "my-waf-policy"
project = "your-gcp-project-id"
rule {
action = "deny(403)"
priority = 1000
match {
versioned_expr = "SRC_IPS_V1"
config {
src_ip_ranges = ["192.0.2.0/24"]
}
}
}
}
Private Endpoints
resource "google_compute_vpc_access_connector" "private_endpoint" {
name = "my-private-endpoint"
region = "us-central1"
network = "default"
min_throughput = 200
}
Provisioning Resources in Azure
Virtual Machine
resource "azurerm_linux_virtual_machine" "example" {
name = "example-vm"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
size = "Standard_B1s"
admin_username = "adminuser"
admin_password = "Password1234!"
network_interface_ids = [
azurerm_network_interface.example.id,
]
os_disk {
caching = "ReadWrite"
create_option = "FromImage"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
Storage
resource "azurerm_storage_account" "example" {
name = "examplestoracc"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
}
Web Application Firewall (WAF)
resource "azurerm_web_application_firewall_policy" "waf_policy" {
name = "my-waf-policy"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
custom_block_response_status_code = 403
rule_set {
name = "OWASP"
type = "OWASP"
}
}
Private Endpoints
resource "azurerm_private_endpoint" "example" {
name = "example-private-endpoint"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
subnet_id = azurerm_subnet.example.id
private_service_connection {
name = "example-connection"
private_connection_resource_id = azurerm_storage_account.example.id
is_manual_connection = false
}
}
Service Principal
resource "azurerm_ad_service_principal" "example" {
application_id = azurerm_ad_application.example.application_id
}
Deploying a Simple Application
Now that we have our instances provisioned, let’s deploy a simple web application on each of them.
On AWS EC2, install Nginx:
ssh -i your-key.pem ec2-user@your-aws-instance-ip sudo yum update -y sudo amazon-linux-extras install nginx1 sudo systemctl start nginx
On GCP, the startup script we added will automatically install Nginx.
On Azure, install Nginx:
ssh adminuser@your-azure-vm-ip sudo apt update sudo apt install nginx -y sudo systemctl start nginx
Managing Multi-Cloud with Terraform
Use the following Terraform commands to manage your multi-cloud infrastructure:
Initialize Terraform:
terraform init
Plan Your Infrastructure:
terraform plan
Apply Changes:
terraform apply
Destroy Infrastructure:
terraform destroy
Conclusion
With the addition of storage solutions, WAFs, private endpoints, and service principals, this guide provides a comprehensive overview of how to build a robust multi-cloud infrastructure using Terraform. Modify the configurations to meet your specific requirements, and ensure security best practices are followed.
Feel free to customize and expand upon these configurations as needed! If you have further specifications or questions, let me know!
Subscribe to my newsletter
Read articles from DevOpshelian directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by