diff --git a/enviroments/dev/main.tf b/enviroments/dev/main.tf new file mode 100644 index 0000000000..ce6158c8ef --- /dev/null +++ b/enviroments/dev/main.tf @@ -0,0 +1,4 @@ +module "dev" { + source = "../../modules" +} + \ No newline at end of file diff --git a/providers.tf b/enviroments/dev/providers.tf similarity index 68% rename from providers.tf rename to enviroments/dev/providers.tf index c41e3650b5..c29947b37a 100644 --- a/providers.tf +++ b/enviroments/dev/providers.tf @@ -2,10 +2,11 @@ terraform { required_providers { aws = { source = "hashicorp/aws" + version = "~> 6.0" } } } provider "aws" { - region = "us-west-2" -} + region = "us-west-2" +} \ No newline at end of file diff --git a/enviroments/qa/main.tf b/enviroments/qa/main.tf new file mode 100644 index 0000000000..2a79e66470 --- /dev/null +++ b/enviroments/qa/main.tf @@ -0,0 +1,13 @@ +module "qa" { + source = "../../modules/web" + + environment = { + name = qa + network_prefix = "10.1" + + } + + min_size = 1 + max_size = 1 +} + \ No newline at end of file diff --git a/enviroments/qa/outputs.tf b/enviroments/qa/outputs.tf new file mode 100644 index 0000000000..7c89c90dc1 --- /dev/null +++ b/enviroments/qa/outputs.tf @@ -0,0 +1,3 @@ +output "environment_url" { + value = module.qa.environment_url +} \ No newline at end of file diff --git a/enviroments/qa/providers.tf b/enviroments/qa/providers.tf new file mode 100644 index 0000000000..c29947b37a --- /dev/null +++ b/enviroments/qa/providers.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 6.0" + } + } +} + +provider "aws" { + region = "us-west-2" +} \ No newline at end of file diff --git a/main.tf b/main.tf deleted file mode 100644 index 9b32ce06bb..0000000000 --- a/main.tf +++ /dev/null @@ -1,24 +0,0 @@ -data "aws_ami" "app_ami" { - most_recent = true - - filter { - name = "name" - values = ["bitnami-tomcat-*-x86_64-hvm-ebs-nami"] - } - - filter { - name = "virtualization-type" - values = ["hvm"] - } - - owners = ["979382823631"] # Bitnami -} - -resource "aws_instance" "web" { - ami = data.aws_ami.app_ami.id - instance_type = "t3.nano" - - tags = { - Name = "HelloWorld" - } -} diff --git a/modules/main.tf b/modules/main.tf new file mode 100644 index 0000000000..15fb29c4a4 --- /dev/null +++ b/modules/main.tf @@ -0,0 +1,193 @@ +data "aws_ami" "app_ami" { + most_recent = true + owners = var.ami_filter.owners + + filter { + name = "name" + values = [var.ami_filter.name] + } + + filter { + name = "architecture" + values = ["x86_64"] + } + + filter { + name = "root-device-type" + values = ["ebs"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } +} + +module "web_vpc" { + source = "terraform-aws-modules/vpc/aws" + version = "~> 6.0" + + name = "${var.environment.name}-web-vpc" + cidr = "${var.environment.network_prefix}.0.0/16" + + azs = ["us-west-2a", "us-west-2b", "us-west-2c"] + + private_subnets = [ + "${var.environment.network_prefix}.1.0/24", + "${var.environment.network_prefix}.2.0/24", + "${var.environment.network_prefix}.3.0/24" + ] + + public_subnets = [ + "${var.environment.network_prefix}.101.0/24", + "${var.environment.network_prefix}.102.0/24", + "${var.environment.network_prefix}.103.0/24" + ] + + map_public_ip_on_launch = true + + enable_nat_gateway = false + enable_vpn_gateway = false + + tags = { + Terraform = "true" + Environment = var.environment.name + } +} + +module "alb" { + source = "terraform-aws-modules/alb/aws" + version = "~> 9.0" + + name = "${var.environment.name}-web-alb" + load_balancer_type = "application" + + vpc_id = module.web_vpc.vpc_id + subnets = module.web_vpc.public_subnets + + security_group_ingress_rules = { + all_http = { + from_port = 80 + to_port = 80 + ip_protocol = "tcp" + description = "Allow HTTP web traffic" + cidr_ipv4 = "0.0.0.0/0" + } + } + + security_group_egress_rules = { + all = { + ip_protocol = "-1" + cidr_ipv4 = "0.0.0.0/0" + } + } + + listeners = { + http = { + port = 80 + protocol = "HTTP" + + forward = { + target_group_key = "web-instance" + } + } + } + + target_groups = { + web-instance = { + name_prefix = "web" + protocol = "HTTP" + port = 80 + target_type = "instance" + create_attachment = false + + health_check = { + enabled = true + path = "/" + port = "traffic-port" + healthy_threshold = 2 + unhealthy_threshold = 2 + timeout = 5 + interval = 30 + matcher = "200" + } + } + } + + tags = { + Environment = var.environment.name + Project = "Terraform-Learning" + } +} + +resource "aws_security_group" "web_instance_sg" { + name_prefix = "web-instance-sg-" + description = "Allow HTTP traffic from ALB to EC2" + vpc_id = module.web_vpc.vpc_id + + ingress { + description = "Allow HTTP from ALB" + from_port = 80 + to_port = 80 + protocol = "tcp" + security_groups = [module.alb.security_group_id] + } + + egress { + description = "Allow all outbound traffic" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "${var.environment.name}-web-instance-sg" + } +} + +module "autoscaling" { + source = "terraform-aws-modules/autoscaling/aws" + version = "9.2.1" + + name = "${var.environment.name}-web-asg" + + min_size = var.min_size + max_size = var.max_size + desired_capacity = var.desired_capacity + + vpc_zone_identifier = module.web_vpc.public_subnets + + health_check_type = "ELB" + health_check_grace_period = 300 + + launch_template_name = "web-asg-template" + launch_template_description = "Launch template for web ASG" + update_default_version = true + + image_id = data.aws_ami.app_ami.id + instance_type = var.instance_type + security_groups = [aws_security_group.web_instance_sg.id] + + user_data = base64encode(<<-EOF +#!/bin/bash +dnf update -y +dnf install -y httpd +systemctl start httpd +systemctl enable httpd +echo "Hello from Terraform Auto Scaling behind ALB" > /var/www/html/index.html +EOF + ) + +traffic_source_attachments = { + web_alb = { + traffic_source_identifier = module.alb.target_groups["web-instance"].arn + traffic_source_type = "elbv2" + } +} + + tags = { + Environment = var.environment.name + Project = "Terraform-Learning" + } +} \ No newline at end of file diff --git a/modules/outputs.tf b/modules/outputs.tf new file mode 100644 index 0000000000..1f129c19fa --- /dev/null +++ b/modules/outputs.tf @@ -0,0 +1,11 @@ +output "environment_url" { + value = module.alb.dns_name +} + +output "vpc_id" { + value = module.web_vpc.vpc_id +} + +output "autoscaling_group_name" { + value = module.autoscaling.autoscaling_group_name +} \ No newline at end of file diff --git a/modules/variables.tf b/modules/variables.tf new file mode 100644 index 0000000000..5fc51df5af --- /dev/null +++ b/modules/variables.tf @@ -0,0 +1,49 @@ +variable "instance_type" { + description = "Type of EC2 instance to provision" + type = string + default = "t3.micro" +} + +variable "ami_filter" { + description = "Name filter and owner for AMI" + type = object({ + name = string + owners = list(string) + }) + + default = { + name = "al2023-ami-2023.*-x86_64" + owners = ["amazon"] + } +} + +variable "environment" { + description = "Deployment environment details" + type = object({ + name = string + network_prefix = string + }) + + default = { + name = "dev" + network_prefix = "10.0" + } +} + +variable "min_size" { + description = "Minimum number of instances in the ASG" + type = number + default = 1 +} + +variable "max_size" { + description = "Maximum number of instances in the ASG" + type = number + default = 2 +} + +variable "desired_capacity" { + description = "Desired number of instances in the ASG" + type = number + default = 1 +} \ No newline at end of file diff --git a/outputs.tf b/outputs.tf deleted file mode 100644 index b35171bef1..0000000000 --- a/outputs.tf +++ /dev/null @@ -1,7 +0,0 @@ -#output "instance_ami" { -# value = aws_instance.web.ami -#} - -#output "instance_arn" { -# value = aws_instance.web.arn -#} diff --git a/variables.tf b/variables.tf deleted file mode 100644 index c750667e0f..0000000000 --- a/variables.tf +++ /dev/null @@ -1,4 +0,0 @@ -#variable "instance_type" { -# description = "Type of EC2 instance to provision" -# default = "t3.nano" -#}