浏览代码

infra: add `EC2` module to provision servers

- Add userdata to update packages
- Create security group for load balancer and ec2 servers
- Create application load balancer and its listener on port 80
- Create target groups for servers behind auto scaling groups
Aashish Goyal 1 年之前
父节点
当前提交
09b4f56a8e
共有 4 个文件被更改,包括 299 次插入0 次删除
  1. 21 0
      modules/ec2/outputs.tf
  2. 208 0
      modules/ec2/terraform.tf
  3. 4 0
      modules/ec2/userdata.sh
  4. 66 0
      modules/ec2/variables.tf

+ 21 - 0
modules/ec2/outputs.tf

@@ -0,0 +1,21 @@
+## Outputs
+
+output "alb_security_group_id" {
+  value = aws_security_group.alb_sg.id
+}
+
+output "ec2_security_group_id" {
+  value = aws_security_group.ec2_sg.id
+}
+
+output "alb_arn" {
+  value = aws_lb.alb_ec2.arn
+}
+
+output "alb_dns_name" {
+  value = aws_lb.alb_ec2.dns_name
+}
+
+output "autoscaling_group_arn" {
+  value = aws_autoscaling_group.ec2_autoscaling_group.arn
+}

+ 208 - 0
modules/ec2/terraform.tf

@@ -0,0 +1,208 @@
+## Security Group for ALB
+resource "aws_security_group" "alb_sg" {
+  name        = "alb-security-group"
+  description = "ALB security group to allow HTTP and HTTPS traffic"
+  vpc_id      = var.vpc_id
+
+  tags = var.tags
+}
+
+## Ingress Security Group Rule for ALB Security Group
+resource "aws_security_group_rule" "ingress_alb_sg_rule" {
+  for_each = var.ingress_alb_sg_rule
+
+  type                     = "ingress"
+  from_port                = each.value.from_port
+  to_port                  = each.value.to_port
+  protocol                 = each.value.protocol
+  cidr_blocks              = try(each.value.cidr_blocks, null)
+  source_security_group_id = try(each.value.source_security_group_id, null)
+  security_group_id        = aws_security_group.alb_sg.id
+}
+
+## Egress Security Group Rule for ALB Security Group
+resource "aws_security_group_rule" "egress_alb_sg_rule" {
+  for_each = var.egress_alb_sg_rule
+
+  type                     = "egress"
+  from_port                = each.value.from_port
+  to_port                  = each.value.to_port
+  protocol                 = each.value.protocol
+  cidr_blocks              = try(each.value.cidr_blocks, null)
+  source_security_group_id = lookup(each.value, "cidr_blocks", null) == null ? try(each.value.source_security_group_id, aws_security_group.ec2_sg.id, null) : null
+  security_group_id        = aws_security_group.alb_sg.id
+}
+
+## Security Group for EC2
+resource "aws_security_group" "ec2_sg" {
+  name        = "ec2-security-group"
+  description = "EC2 security group to allow traffic only from ALB"
+  vpc_id      = var.vpc_id
+
+  tags = var.tags
+}
+
+## Ingress Security Group Rule for EC2 Security Group
+resource "aws_security_group_rule" "ingress_ec2_sg_rule" {
+  for_each = var.ingress_ec2_sg_rule
+
+  type                     = "ingress"
+  from_port                = each.value.from_port
+  to_port                  = each.value.to_port
+  protocol                 = each.value.protocol
+  cidr_blocks              = try(each.value.cidr_blocks, null)
+  source_security_group_id = lookup(each.value, "cidr_blocks", null) == null ? try(each.value.source_security_group_id, aws_security_group.alb_sg.id, null) : null
+  security_group_id        = aws_security_group.ec2_sg.id
+}
+
+## Egress Security Group Rule for EC2 Security Group
+resource "aws_security_group_rule" "egress_ec2_sg_rule" {
+  for_each = var.egress_ec2_sg_rule
+
+  type                     = "egress"
+  from_port                = each.value.from_port
+  to_port                  = each.value.to_port
+  protocol                 = each.value.protocol
+  cidr_blocks              = try(each.value.cidr_blocks, null)
+  source_security_group_id = try(each.value.source_security_group_id, null)
+  security_group_id        = aws_security_group.ec2_sg.id
+}
+
+## Fetch Ubuntu Family AMI Id
+
+data "aws_ami" "ec2_ami" {
+  filter {
+    name   = "name"
+    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
+  }
+
+  filter {
+    name   = "virtualization-type"
+    values = ["hvm"]
+  }
+
+  most_recent = true
+
+  owners = ["amazon"]
+}
+
+## Target Group
+resource "aws_lb_target_group" "ec2_alb_target_group" {
+  name                 = var.ec2_alb_target_group.name
+  port                 = var.ec2_alb_target_group.port
+  protocol             = var.ec2_alb_target_group.protocol
+  vpc_id               = var.vpc_id
+  deregistration_delay = var.ec2_alb_target_group.deregistration_delay
+
+  tags = var.tags
+}
+
+## ALB
+resource "aws_lb" "alb_ec2" {
+  name                       = var.alb_ec2.name
+  enable_deletion_protection = var.alb_ec2.enable_deletion_protection
+  internal                   = var.alb_ec2.internal
+  load_balancer_type         = var.alb_ec2.load_balancer_type
+  security_groups            = [aws_security_group.alb_sg.id]
+  subnets                    = var.alb_subnet_ids
+
+  tags = var.tags
+
+  depends_on = [
+    aws_lb_target_group.ec2_alb_target_group
+  ]
+}
+
+## ALB Listener
+resource "aws_lb_listener" "alb_listener" {
+  for_each = var.alb_listener
+
+  load_balancer_arn = aws_lb.alb_ec2.arn
+  port              = each.value.port
+  protocol          = each.value.protocol
+  certificate_arn   = each.value.protocol == "HTTPS" ? try(each.value.certificate_arn, null) : null
+  ssl_policy        = each.value.protocol == "HTTPS" ? try(each.value.ssl_policy, null) : null
+
+  default_action {
+    type             = each.value.action_type
+    target_group_arn = each.value.action_type == "forward" ? aws_lb_target_group.ec2_alb_target_group.arn : null
+
+    dynamic "redirect" {
+      for_each = each.value.action_type == "redirect" ? [each.value.redirect] : []
+
+      content {
+        status_code = redirect.value.status_code
+        port        = redirect.value.port
+        protocol    = redirect.value.protocol
+      }
+    }
+  }
+
+  tags = var.tags
+
+  depends_on = [
+    aws_lb.alb_ec2
+  ]
+}
+
+## Launch Template
+resource "aws_launch_template" "ec2_launch_template" {
+  name = var.ec2_launch_template.name
+
+  block_device_mappings {
+    device_name = var.ec2_launch_template.device_name
+
+    ebs {
+      volume_size           = var.ec2_launch_template.ebs_volume_size
+      delete_on_termination = true
+      volume_type           = var.ec2_launch_template.ebs_volume_type
+    }
+  }
+
+  ebs_optimized          = var.ec2_launch_template.ebs_optimized
+  image_id               = data.aws_ami.ec2_ami.id
+  instance_type          = var.ec2_launch_template.instance_type
+  key_name               = var.ec2_launch_template.key_name
+  vpc_security_group_ids = [aws_security_group.ec2_sg.id]
+  update_default_version = true
+
+  user_data = filebase64("${path.module}/userdata.sh")
+
+  tag_specifications {
+    resource_type = "instance"
+
+    tags = var.tags
+  }
+}
+
+## AutoScaling Group
+resource "aws_autoscaling_group" "ec2_autoscaling_group" {
+  name = var.ec2_autoscaling_group.name
+
+  min_size                  = var.ec2_autoscaling_group.min_size
+  max_size                  = var.ec2_autoscaling_group.max_size
+  desired_capacity          = var.ec2_autoscaling_group.desired_capacity
+  vpc_zone_identifier       = [var.ec2_subnet_id]
+  default_cooldown          = var.ec2_autoscaling_group.default_cooldown
+  health_check_grace_period = var.ec2_autoscaling_group.health_check_grace_period
+
+  launch_template {
+    id      = aws_launch_template.ec2_launch_template.id
+    version = "$Latest"
+  }
+
+  target_group_arns = [aws_lb_target_group.ec2_alb_target_group.arn]
+
+  dynamic "tag" {
+    for_each = var.tags
+    content {
+      key                 = tag.key
+      value               = tag.value
+      propagate_at_launch = true
+    }
+  }
+
+  depends_on = [
+    aws_lb.alb_ec2
+  ]
+}

+ 4 - 0
modules/ec2/userdata.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+
+apt update -y
+apt upgrade -y

+ 66 - 0
modules/ec2/variables.tf

@@ -0,0 +1,66 @@
+## Variables
+
+variable "tags" {
+  type    = map(string)
+  default = {}
+}
+
+variable "vpc_id" {
+  type    = string
+  default = ""
+}
+
+variable "ingress_alb_sg_rule" {
+  type    = any
+  default = {}
+}
+
+variable "egress_alb_sg_rule" {
+  type    = any
+  default = {}
+}
+
+variable "ingress_ec2_sg_rule" {
+  type    = any
+  default = {}
+}
+
+variable "egress_ec2_sg_rule" {
+  type    = any
+  default = {}
+}
+
+variable "alb_subnet_ids" {
+  type    = list(string)
+  default = [""]
+}
+
+variable "ec2_subnet_id" {
+  type    = string
+  default = ""
+}
+
+variable "ec2_launch_template" {
+  type    = map(string)
+  default = {}
+}
+
+variable "ec2_alb_target_group" {
+  type    = map(string)
+  default = {}
+}
+
+variable "alb_ec2" {
+  type    = map(string)
+  default = {}
+}
+
+variable "alb_listener" {
+  type    = any
+  default = {}
+}
+
+variable "ec2_autoscaling_group" {
+  type    = map(string)
+  default = {}
+}