How to manage AWS multiple regions and availability zones using terraform

0 votes

Hi,
I have implemented terraform template to create below AWS resources
custom VPC
3 private and 3 public subnets
NAT gateway for the private subnet and IGW for the public subnet

launch EC2 instance in the public subnet

launch RDS instance in a private subnet

My question, I have implemented this terraform for the Mumbai region. I want to do this for all-region and its AZ. How can we achieve this? For example, my client asked me to deploy in the Virginia region. After someday another client asking me to deploy on the Oregon region. Whenever we decide to deploy on the Virginia region, then it will assign to region and AZ terraform code. Below is my Terraform template. Kindly help me to achieve and correct my code if possible. Many thanks.

#Provider-AWS
provider "aws" {
  version = "~> 2.0"
  region  = var.region
}

#variables
variable "project_name" {
}

variable "env" {
}

variable "region" {
}

#Virtual Private Cloud
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16" # 65536 ip addresses
  tags = {
    Name = "${var.project_name}${var.env}"
      }
}

# Internet Gateway
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "${var.project_name}${var.env}"
      }
}

resource "aws_route_table" "igw" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "igw-${var.project_name}${var.env}"
      }
}

resource "aws_route" "igw" {
  route_table_id = aws_route_table.igw.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id = aws_internet_gateway.main.id
}

# Network Gateway
resource "aws_route_table" "ngw" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "ngw-${var.project_name}${var.env}"
      }
}

resource "aws_route" "ngw" {
  route_table_id = aws_route_table.ngw.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id = aws_nat_gateway.main.id
}

#EIP Assign for NAT Gateway
resource "aws_eip" "nat" {
  vpc = true
}

resource "aws_nat_gateway" "main" {
  allocation_id = aws_eip.nat.id
  subnet_id = aws_subnet.public-ap-south-1a.id
  tags = {
    Name = "${var.project_name}${var.env}"
      }
}

#### public- Subnet 1a
resource "aws_subnet" "public-ap-south-1a" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.100.0/24"
  availability_zone_id = "aps1-az2"
  tags = {
    Name = "public-ap-south-1a-${var.project_name}${var.env}"
      }
}

resource "aws_route_table_association" "public-ap-south-1a" {
  subnet_id = aws_subnet.public-ap-south-1a.id
  route_table_id = aws_route_table.igw.id
}

#### public Subnet- 1b
resource "aws_subnet" "public-ap-south-1b" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.101.0/24"
  availability_zone_id = "aps1-az1"
  tags = {
   Name = "public-ap-south-1b-${var.project_name}${var.env}"
     }
}

resource "aws_route_table_association" "public-ap-south-1b" {
  subnet_id = aws_subnet.public-ap-south-1b.id
  route_table_id = aws_route_table.igw.id
}

#### public Subnet -1c

resource "aws_subnet" "public-ap-south-1c" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.102.0/24"
  availability_zone_id = "aps1-az3"
  tags = {
    Name = "public-ap-south-1c-${var.project_name}${var.env}"
      }
}

resource "aws_route_table_association" "public-ap-south-1c" {
  subnet_id = aws_subnet.public-ap-south-1c.id
  route_table_id = aws_route_table.igw.id
}

#### private Subnet - 1a
resource "aws_subnet" "private-ap-south-1a" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
  availability_zone_id = "aps1-az2"
  tags = {
    Name = "private-ap-south-1a-${var.project_name}${var.env}"
      }
}

resource "aws_route_table_association" "private-ap-south-1a" {
  subnet_id = aws_subnet.private-ap-south-1a.id
  route_table_id = aws_route_table.ngw.id
}

#### private Subnet -1b
resource "aws_subnet" "private-ap-south-1b" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.2.0/24"
  availability_zone_id = "aps1-az1"
  tags = {
    Name = "private-ap-south-1b-${var.project_name}${var.env}"
      }
}

resource "aws_route_table_association" "private-ap-south-1b" {
  subnet_id = aws_subnet.private-ap-south-1b.id
  route_table_id = aws_route_table.ngw.id
}

#### private 1c
resource "aws_subnet" "private-ap-south-1c" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.3.0/24"
  availability_zone_id = "aps1-az3"
  tags = {
    Name = "private-ap-south-1c-${var.project_name}${var.env}"
      }
}

resource "aws_route_table_association" "private-ap-south-1c" {
  subnet_id = aws_subnet.private-ap-south-1c.id
  route_table_id = aws_route_table.ngw.id
}

#resource "aws_security_group" "rds"
#{
#  vpc_id = aws_vpc.main.id
#}

##RDS Instance
resource "aws_db_instance" "main" {
  allocated_storage = 20
  storage_type = "gp2"
  engine = "mysql"
  engine_version = "5.7"
  instance_class = "db.t2.micro"
  identifier = "rds-${var.project_name}${var.env}"
  name = "demoinstance"
  username = "admin"
  password = "xxxxxxx"
  skip_final_snapshot = false
  # notes time of creation of rds.tf file
  final_snapshot_identifier = "rds-${var.project_name}${var.env}-updated"
  vpc_security_group_ids = [aws_security_group.rds.id]
  db_subnet_group_name = aws_db_subnet_group.main.id
  lifecycle {
    prevent_destroy = true
  }
  tags = {
    Name = "rds-${var.project_name}${var.env}"
  }
}
resource "aws_db_subnet_group" "main" {
  name = "db-private-subnets"
  subnet_ids = [
    aws_subnet.private-ap-south-1a.id,
    aws_subnet.private-ap-south-1b.id,
    aws_subnet.private-ap-south-1c.id
  ]

  tags = {
    Name = "subnet-group-${var.project_name}${var.env}"
  }
}

##APP-Server
resource "aws_instance" "appserver" {
  ami = "ami-xxxxxxxxxxx"
  associate_public_ip_address = true
  instance_type = "t2.micro"
  subnet_id = aws_subnet.public-ap-south-1a.id
  vpc_security_group_ids = ["${aws_security_group.appserver.id}"]
  key_name = aws_key_pair.main.key_name
  tags = {
    Name = "appserver-${var.project_name}${var.env}"
    #Name = "appserver-Development"
  }
}

#Declare-key
variable "key_name" {
default = "PrivateKey"
}

resource "tls_private_key" "example" {
algorithm = "RSA"
rsa_bits = 4096
}

resource "aws_key_pair" "main" {
  key_name = "${var.project_name}-${var.env}"
  public_key = "${tls_private_key.example.public_key_openssh}"
}

output "appserver_public_ip" {
  value = aws_instance.appserver.public_ip
}

# Security-Group
resource "aws_security_group" "appserver" {
  name = "${var.project_name}${var.env}-appserver"
  description = "Application server ${var.env}"
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "${var.project_name}${var.env}"
  }
}

resource "aws_security_group_rule" "rdp-appserver-world" {
  type = "ingress"
  from_port = 3389
  to_port = 3389
  protocol = "tcp"
  # Please restrict your ingress to only necessary IPs and ports.
  # Opening to 0.0.0.0/0 can lead to security vulnerabilities
  # You may want to set a fixed ip address if you have a static ip
  security_group_id = aws_security_group.appserver.id
  cidr_blocks = ["0.0.0.0/0"]
}

resource "aws_security_group_rule" "rdp-appserver-web_server" {
  type = "egress"
  from_port = 80
  to_port = 80
  protocol = "tcp"
  security_group_id = aws_security_group.appserver.id
  source_security_group_id = aws_security_group.web_server.id
}

resource "aws_security_group_rule" "mysql-appserver-rds" {
  type = "egress"
  from_port = 3306
  to_port = 3306
  protocol = "tcp"
  security_group_id = aws_security_group.appserver.id
  source_security_group_id = aws_security_group.rds.id
}

##WebServer
resource "aws_security_group" "web_server" {
  name = "${var.project_name}${var.env}-web-servers"
  description = "For Web servers ${var.env}"
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "${var.project_name}${var.env}"
      }
}

resource "aws_security_group_rule" "rdp-web_server-appserver" {
  type = "ingress"
  from_port = 22
  to_port = 22
  protocol = "tcp"
  security_group_id = aws_security_group.web_server.id
  source_security_group_id = aws_security_group.appserver.id
}

##RDS Security Group
resource "aws_security_group" "rds" {
    name = "rds-${var.project_name}${var.env}"
    description = "For RDS ${var.env}"
vpc_id = aws_vpc.main.id
  tags = {
    Name = "${var.project_name}${var.env}"
  }
}

resource "aws_security_group_rule" "mysql-rds-web_server" {
  type = "ingress"
  from_port = 3306
  to_port = 3306
  protocol = "tcp"
  security_group_id = aws_security_group.rds.id
  source_security_group_id = aws_security_group.web_server.id
}

resource "aws_security_group_rule" "mysql-rds-appserver" {
  type = "ingress"
  from_port = 3306
  to_port = 3306
  protocol = "tcp"
  security_group_id = aws_security_group.rds.id
  source_security_group_id = aws_security_group.appserver.id
}
Jul 20, 2020 in Terraform by Lakshminarayanan
• 1,360 points

recategorized Jul 20, 2020 by MD 2,587 views

1 answer to this question.

0 votes

Hi,

When you run your Terraform code it will use your AWS profile to authenticate with AWS. So you need to create different profiles according to your need. And replace the profile name according to your use case. Except for the provider name all other codes will remain the same.

answered Jul 20, 2020 by MD
• 95,200 points

Hi @MD,

Bro, I'm asking about AZ updates in subnets, for instance. For example, the Below terraform template is to create subnets in the ap-south-1 region. 

resource "aws_subnet" "private-ap-south-1c" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.3.0/24"
  availability_zone_id = "aps1-az3"
  tags = {
    Name = "private-ap-south-1c-${var.project_name}${var.env}"
      }
}
If region us-east-1, 
resource "aws_subnet" "private-us-east-1a" {
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.3.0/24"
  availability_zone_id = "use1-az3"
  tags = {
    Name = "private-ap-south-1c-${var.project_name}${var.env}"
      }
}

So two variables changed here one is subnet and another one in AZ. I would like to do it automatically not manually update. I want to get information from the terminal

region=
AZ =
subnets = 

I hope you understand my question. 

Then use the variable concept. You can change your required value at run time.
Ok bro. I will do same
you can use data "aws_availability_zones" data source to get the names of available az's in region

Related Questions In Terraform

0 votes
1 answer

How to create a VPC in AWS using Terraform?

Hi@akhtar, You can find the script in the ...READ MORE

answered Jul 21, 2020 in Terraform by MD
• 95,200 points
364 views
0 votes
1 answer

How to create a route table in AWS using Terraform code?

Hi@akhtar, You can use aws_route_table resources in your ...READ MORE

answered Jul 21, 2020 in Terraform by MD
• 95,200 points
1,027 views
0 votes
1 answer

How to add a route for IGW in AWS using Terraform code?

Hi@akhtar, Terraform has one keyword named route. It allows ...READ MORE

answered Jul 22, 2020 in Terraform by MD
• 95,200 points
496 views
0 votes
1 answer

How to create one S3 bucket in AWS using Terraform?

Hi@akhtar, You need to set aws provider name ...READ MORE

answered Jul 23, 2020 in Terraform by MD
• 95,200 points
326 views
+15 votes
2 answers

Git management technique when there are multiple customers and need multiple customization?

Consider this - In 'extended' Git-Flow, (Git-Multi-Flow, ...READ MORE

answered Mar 26, 2018 in DevOps & Agile by DragonLord999
• 8,450 points
1,127 views
+2 votes
1 answer
0 votes
1 answer

How to create one key in AWS using terraform?

Hi@akhtar, You can use aws_key_pair resource n terraform. ...READ MORE

answered Jun 11, 2020 in Terraform by MD
• 95,200 points
690 views
0 votes
1 answer

How to create a rds snapshot from running rds instance in AWS using terraform?

Hi, I think you can use aws_db_instance resource to ...READ MORE

answered Jul 20, 2020 in Terraform by MD
• 95,200 points
1,022 views