Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(modules): add multiple modules for loadbalancing and autoscaling #3

Merged
merged 1 commit into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
echo device_name=${{vars.DEVICE_NAME}} >> prod.tfvars
echo volume_size=${{vars.VOLUME_SIZE}} >> prod.tfvars
echo volume_type=${{vars.VOLUME_TYPE}} >> prod.tfvars
echo domain=${{vars.DOMAIN}} >> prod.tfvars

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
Expand Down
6 changes: 6 additions & 0 deletions modules/acm/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/acm_certificate
# TODO: add ssl cert to AWS ACM for domain
data "aws_acm_certificate" "ssl" {
domain = var.domain
statuses = ["ISSUED"]
}
3 changes: 3 additions & 0 deletions modules/acm/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "ssl" {
value = data.aws_acm_certificate.ssl
}
1 change: 1 addition & 0 deletions modules/acm/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
variable "domain" {}
73 changes: 73 additions & 0 deletions modules/alb/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb
resource "aws_lb" "alb" {
name = "alb"
internal = false
load_balancer_type = "application"
security_groups = [var.alb_sg_id]
subnets = [for subnet_id in var.public_subnets_id : subnet_id]
enable_deletion_protection = false

tags = {
"Name" = "${var.environment}-alb"
}
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group
resource "aws_lb_target_group" "alb_tg" {
name = "alb-tg"
port = 1337
protocol = "HTTP"
vpc_id = var.vpc_id
target_type = "instance"

health_check {
enabled = true
path = "/healthz"
port = "traffic-port"
protocol = "HTTP"
healthy_threshold = 2
unhealthy_threshold = 2
interval = 90
timeout = 6
matcher = "200-299"
}

tags = {
"Name" = "${var.environment}-alb-target-group"
}
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.alb.arn
port = "80"
protocol = "HTTP"

default_action {
type = "redirect"

redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.alb.arn
port = "443"
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy-2016-08"
certificate_arn = var.ssl_certificate.arn

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.alb_tg.arn
}
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_listener_certificate
resource "aws_lb_listener_certificate" "alb_certificate" {
listener_arn = aws_lb_listener.https.arn
certificate_arn = var.ssl_certificate.arn
}
7 changes: 7 additions & 0 deletions modules/alb/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
output "alb_tg_arn" {
value = aws_lb_target_group.alb_tg.arn
}

output "alb" {
value = aws_lb.alb
}
5 changes: 5 additions & 0 deletions modules/alb/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
variable "environment" {}
variable "alb_sg_id" {}
variable "public_subnets_id" {}
variable "vpc_id" {}
variable "ssl_certificate" {}
41 changes: 41 additions & 0 deletions modules/asg/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_group
resource "aws_autoscaling_group" "asg" {
name = "asg"
min_size = 1
max_size = 3
desired_capacity = 1
force_delete = true
default_cooldown = 60
vpc_zone_identifier = [for subnet_id in var.public_subnets_id : subnet_id]

tag {
key = "Name"
value = "${var.environment}-asg"
propagate_at_launch = true
}

launch_template {
id = var.launch_template_id
version = "$Latest"
}

target_group_arns = [var.alb_tg_arn]
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/autoscaling_policy
resource "aws_autoscaling_policy" "scale_out_policy" {
name = "scale-out-policy"
scaling_adjustment = 1
adjustment_type = "ChangeInCapacity"
cooldown = 60
autoscaling_group_name = aws_autoscaling_group.asg.name
}
resource "aws_autoscaling_policy" "scale_in_policy" {
name = "scale-in-policy"
scaling_adjustment = -1
adjustment_type = "ChangeInCapacity"
cooldown = 60
autoscaling_group_name = aws_autoscaling_group.asg.name

}

11 changes: 11 additions & 0 deletions modules/asg/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
output "asg_name" {
value = aws_autoscaling_group.asg.name
}

output "scale_out_policy" {
value = aws_autoscaling_policy.scale_out_policy
}

output "scale_in_policy" {
value = aws_autoscaling_policy.scale_in_policy
}
4 changes: 4 additions & 0 deletions modules/asg/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
variable "environment" {}
variable "public_subnets_id" {}
variable "launch_template_id" {}
variable "alb_tg_arn" {}
33 changes: 33 additions & 0 deletions modules/cloudwatch/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_metric_alarm
resource "aws_cloudwatch_metric_alarm" "scale_out_alarm" {
alarm_name = "scale-out-alarm"
alarm_description = "Metric to monitor high EC2 CPU utilization"
alarm_actions = [var.scale_out_policy.arn]
comparison_operator = "GreaterThanOrEqualToThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 120
statistic = "Average"
threshold = 5

dimensions = {
AutoScalingGroupName = var.asg_name
}
}
resource "aws_cloudwatch_metric_alarm" "scale_in_alarm" {
alarm_name = "scale-in-alarm"
alarm_description = "Metric to monitor low EC2 CPU utilization"
alarm_actions = [var.scale_in_policy.arn]
comparison_operator = "LessThanOrEqualToThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 120
statistic = "Average"
threshold = 3

dimensions = {
AutoScalingGroupName = var.asg_name
}
}
Empty file added modules/cloudwatch/output.tf
Empty file.
3 changes: 3 additions & 0 deletions modules/cloudwatch/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
variable "asg_name" {}
variable "scale_out_policy" {}
variable "scale_in_policy" {}
4 changes: 3 additions & 1 deletion modules/ec2/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ resource "aws_launch_template" "ec2_launch_template" {
key_name = var.ssh_key_name
# vpc_security_group_ids = [var.api_sg_id]

# TODO: IAM Instance profile for s3 access policy
iam_instance_profile {
name = var.iam_ec2_s3_profile.name
}

block_device_mappings {
device_name = var.device_name
Expand Down
3 changes: 3 additions & 0 deletions modules/ec2/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "launch_template_id" {
value = aws_launch_template.ec2_launch_template.id
}
1 change: 1 addition & 0 deletions modules/ec2/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ variable "volume_type" {}
variable "database" {}
variable "dbuser" {}
variable "dbpassword" {}
variable "iam_ec2_s3_profile" {}
75 changes: 75 additions & 0 deletions modules/iam/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "ec2_access_role" {
name = "ec2-access-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "ec2.amazonaws.com"
}
},
]
})

tags = {
"Name" = "${var.environment}-iam-ec2-access-role"
}
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy
data "aws_iam_policy" "cloudwatch_server_policy" {
arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy
resource "aws_iam_policy" "s3_policy" {
name = "s3-policy"
path = "/"
description = "Allow S3 access to API"

# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:DeleteObject",
"s3:GetObject",
"s3:PutObject",
]
Effect = "Allow"
Resource = [
"arn:aws:s3:::${var.s3_bucket.bucket}",
"arn:aws:s3:::${var.s3_bucket.bucket}/*"
]
},
]
})

tags = {
"Name" = "${var.environment}-iam-s3-policy"
}
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment
resource "aws_iam_policy_attachment" "s3_policy_role" {
name = "s3-policy-attachment"
roles = [aws_iam_role.ec2_access_role.name]
policy_arn = aws_iam_policy.s3_policy.arn
}
resource "aws_iam_policy_attachment" "cloudwatch_policy_role" {
name = "cloudwatch-policy-attachment"
roles = [aws_iam_role.ec2_access_role.name]
policy_arn = data.aws_iam_policy.cloudwatch_server_policy.arn
}

resource "aws_iam_instance_profile" "iam_ec2_s3_profile" {
name = "ec2-s3-profile"
role = aws_iam_role.ec2_access_role.name
}
3 changes: 3 additions & 0 deletions modules/iam/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "iam_ec2_s3_profile" {
value = aws_iam_instance_profile.iam_ec2_s3_profile
}
2 changes: 2 additions & 0 deletions modules/iam/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
variable "environment" {}
variable "s3_bucket" {}
17 changes: 17 additions & 0 deletions modules/route53/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/route53_zone
resource "aws_route53_zone" "hosted_zone" {
name = var.domain
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record
resource "aws_route53_record" "alb_alias" {
zone_id = aws_route53_zone.hosted_zone.zone_id
name = var.domain
type = "A"

alias {
zone_id = var.alb.zone_id
name = var.alb.dns_name
evaluate_target_health = true
}
}
2 changes: 2 additions & 0 deletions modules/route53/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
variable "domain" {}
variable "alb" {}
2 changes: 1 addition & 1 deletion modules/s3/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ resource "aws_s3_bucket_lifecycle_configuration" "s3_bucket_lifecycle_config" {
bucket = aws_s3_bucket.bucket.id

rule {
id = "rule-1"
id = "move_to_IA"
status = "Enabled"
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration#transition
transition {
Expand Down
3 changes: 3 additions & 0 deletions modules/s3/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "s3_bucket" {
value = aws_s3_bucket.bucket
}
29 changes: 20 additions & 9 deletions modules/sg/main.tf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group
resource "aws_security_group" "api_sg" {
name = "api-sg"
description = "Enable SSH,API,HTTP & HTTPS access on ports 22,1337,80 & 443"
resource "aws_security_group" "alb_sg" {
name = "alb-sg"
description = "Enable SSH,HTTP & HTTPS access on ports 22,80 & 443"
vpc_id = var.vpc_id

ingress {
Expand All @@ -25,12 +25,23 @@ resource "aws_security_group" "api_sg" {
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}

tags = {
Name = "${var.environment}-alb-sg"
}
}

resource "aws_security_group" "api_sg" {
name = "api-sg"
description = "Enable API access on port 1337"
vpc_id = var.vpc_id

ingress {
description = "API Port"
from_port = 1337
to_port = 1337
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "API Port"
from_port = 1337
to_port = 1337
protocol = "tcp"
security_groups = [aws_security_group.alb_sg.id]
}

egress {
Expand Down Expand Up @@ -66,6 +77,6 @@ resource "aws_security_group" "db_sg" {
# }

tags = {
Name = "database"
Name = "${var.environment}-db-sg"
}
}
4 changes: 4 additions & 0 deletions modules/sg/output.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
output "alb_sg_id" {
value = aws_security_group.alb_sg.id
}

output "api_sg_id" {
value = aws_security_group.api_sg.id
}
Expand Down
Loading
Loading