Skip to main content

Terraform

Workspace based terraform automation project setup for multi-cloud.

Cloud Module Reference​

  1. Azure
  2. AWS
  3. GCP
  4. Rover - Terraform visualizer

Folder structure of terrafrom project​

TERRAFORM
β”‚ .gitignore
β”‚ .terraform.lock.hcl
β”‚ main.tf # Main terraform file
β”‚ outputs.tf # Output variables
β”‚ provider.tf # All providers with version number declaration
β”‚ terrafrom.tfvars # Terraform's default variables definitions.
β”‚ variables.tf # Terraform variables declarations
β”‚
β”œβ”€β”€β”€.terraform
β”‚ β”‚ environment
β”‚ β”‚
β”‚ β”œβ”€β”€β”€modules
β”‚ β”‚ modules.json
β”‚ β”‚
β”‚ └───providers
β”‚ └───registry.terraform.io
β”‚
└───terraform.tfstate.d
β”œβ”€β”€β”€Test
β”œβ”€β”€β”€Uat
└───Prod

Sample files shared below

Note: terrafrom.tfvars is default variable definition file. Custom name is acceptable. but need to spacify the file name in every execution liek terraform apply var-file=test.env.tfvars

Init the terraform project​


terraform init (or) terraform init --upgrade

Terrafrom workspace​

# Create workspace
terrafrom workspace new Test
terrafrom workspace new Uat
terrafrom workspace new Prod

# Select/Change workspace
terraform workspace select Test

# List all workspace
terraform workspace list

# Deelte workspace
terraform workspace delete Test

Plan​

terraform plan  # terraform will take terraform.tfvars as default variable file.
terraform plan var-file=test.evn.tfvars

Apply​


terraform apply -y var-file=test.env.tfvars

Azure​

Authenticaton setup​

export ARM_SUBSCRIPTION_ID="<azure_subscription_id>"
export ARM_TENANT_ID="<azure_subscription_tenant_id>"
export ARM_CLIENT_ID="<service_principal_appid>"
export ARM_CLIENT_SECRET="<service_principal_password>"

Note: When authenticating as a Service Principal using a Client Secret, client_secret fields need to be set. This can also be sourced from the ARM_CLIENT_SECRET Environment Variable.

(or)

provider "azurerm" {
subscription_id = var.azure.subscription_id
# client_id = var.azure.client_id
# client_secret = var.azure.client_secret
tenant_id = var.azure.tenant_id
features {}
}

Secure State file in Azure Storeage​

terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.46.0"
}
}
backend "azurerm" {
resource_group_name = "tfstate"
storage_account_name = "<storage_account_name>"
container_name = "tfstate"
key = "terraform.tfstate"
}

}

AWS​

Authenticaton Setup​

export AWS_ACCESS_KEY_ID="anaccesskey"
export AWS_SECRET_ACCESS_KEY="asecretkey"
export AWS_DEFAULT_REGION="us-west-2"
terraform plan

Secure state file in AWS S3 Bucket​

terraform {
backend "s3" {
bucket = "mybucket"
key = "path/to/my/key"
region = "us-east-1"
}
}

GCP​

Authenticaton setup​

Secure state file in GCS (Google Cloud Storage)​

terraform {
backend "gcs" {
bucket = "tf-state-prod"
prefix = "terraform/state"
}
}

Sample terraform scripts​

Multi cloud terrafrom project

provider.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.2"
}
azurerm = {
source = "hashicorp/azurerm"
version = "2.98.0"
}
google = {
version = "~> 3.8"
}
random = "~> 2.2"
docker = "~> 2.7"
}
backend "azurerm" {
resource_group_name = "tfstate"
storage_account_name = "<storage_account_name>"
container_name = "tfstate"
key = "terraform.tfstate"
}
}

provider "aws" {
profile = var.aws.profile
region = var.aws.region
access_key = var.aws.access_key
secret_key = var.aws.secret_key
}

provider "azurerm" {
subscription_id = var.azure.subscription_id
# client_id = var.azure.client_id
# client_secret = var.azure.client_secret
tenant_id = var.azure.tenant_id
features {}
}

provider "google" {
credentials = file("account.json")
project = var.gcp.project_id
region = var.gcp.region
}

provider "docker" {
}
terraform.tfvars

aws = {
profile = "default" # ENV = AWS_PROFILE
region = "us-west-2" # ENV = AWS_REGION
access_key = "xxxxxxxxxxxxxxxxxxx" # ENV = AWS_ACCESS_KEY_ID
secret_key = "xxxxxxxxxxxxxxxxxxx" # ENV= AWS_SECRET_ACCESS_KEY
}
azure = {
subscription_id = "xxxx-xxxxx-xxxxx-xxxxx-xxxx-xxxx" # ENV = ARM_SUBSCRIPTION_ID
# client_id = "xxxx-xxxxx-xxxxx-xxxxx-xxxx-xxxx" # ENV = ARM_CLIENT_ID
# client_secret = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx" # ENV= ARM_CLIENT_SECRET
tenant_id = "xxxx-xxxxx-xxxxx-xxxxx-xxxx-xxxx" # ENV = ARM_TENANT_ID
location = "centralus"
}

gcp = {
project_id = "<project_id>"
region = "us-east1"
}


variables.tf
variable "aws" {
type = object({
profile = string
region = string
access_key = string
secret_key = string
})
}

variable "azure" {
type = object({
subscription_id = string
# client_id = string
# client_secret = string
tenant_id = string
location = string
})
}

variable "gcp" {
type = object({
project_id = string
region = string
})
}
output.tf
output "addresses" {
value = {
# aws = module.aws.network_address
# azure = module.azure.network_address
# gcp = module.gcp.network_address
# loadbalancer = module.loadbalancer.network_address
}
}

Landing Zone Creation​

Best Practices Reference