Building a Multi-Cloud Infrastructure with Terraform: A Complete Project Guide

DevOpshelianDevOpshelian
4 min read

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

  1. Install Terraform: Follow the instructions on the Terraform website.

  2. Configure Cloud Provider Credentials for AWS, GCP, and Azure as previously described.

  3. Create a Working Directory: Create a new directory for your project.

     mkdir multi-cloud-terraform
     cd multi-cloud-terraform
    

Creating a Terraform Project

  1. 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.

  1. 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
    
  2. On GCP, the startup script we added will automatically install Nginx.

  3. 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!

0
Subscribe to my newsletter

Read articles from DevOpshelian directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

DevOpshelian
DevOpshelian