Part 6 - Create web server instances.

By Ben Outram / 2018-06-15

Create a new file web.tf which we will add the following configuration to.

Create a key pair that will be assigned to our instances:

resource "aws_key_pair" "deployer" {
  key_name   = "terraform_deployer"
  public_key = "${file(var.public_key_path)}"
}

Create a new EC2 launch configuration. This will be used with our auto scaling group.

resource "aws_launch_configuration" "launch_config" {
  name_prefix                 = "terraform-example-web-instance"
  image_id                    = "${lookup(var.amis, var.region)}"
  instance_type               = "${var.instance_type}"
  key_name                    = "${aws_key_pair.deployer.id}"
  security_groups             = ["${aws_security_group.default.id}"]
  associate_public_ip_address = true
  user_data                   = "${data.template_file.provision.rendered}"

  lifecycle {
    create_before_destroy = true
  }
}

Create the auto scaling group:

resource "aws_autoscaling_group" "autoscaling_group" {
  launch_configuration = "${aws_launch_configuration.launch_config.id}"
  min_size             = "${var.autoscaling_group_min_size}"
  max_size             = "${var.autoscaling_group_max_size}"
  target_group_arns    = ["${aws_alb_target_group.group.arn}"]
  vpc_zone_identifier  = ["${aws_subnet.main.*.id}"]

  tag {
    key                 = "Name"
    value               = "terraform-example-autoscaling-group"
    propagate_at_launch = true
  }
}

We need to enable inbound traffic for the web server instances in our default security group. The security group has already been defined in project.tf in part two as resource aws_security_group.default. Find this resource block which is currently:

resource "aws_security_group" "default" {
  name        = "terraform_security_group"
  description = "Terraform example security group"
  vpc_id      = "${aws_vpc.vpc.id}"

  # Allow outbound internet access.
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags {
    Name = "terraform-example-security-group"
  }
}

Within this block nest three new ingress rules in-line.

The first two rules will restrict inbound SSH and ICMP echo traffic by IP address to the same list of CIDR blocks that we allowed to access the application load balancer earlier in part four. This will use the value assigned to variable allowed_cidr_blocks in our user.tfvars file.

The third rule will restrict inbound HTTP traffic to only allow traffic from the load balancer. Here the application load balancer security group is specified.

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = "${var.allowed_cidr_blocks}"
  }

  ingress {
    from_port   = 8
    to_port     = 0
    protocol    = "icmp"
    cidr_blocks = "${var.allowed_cidr_blocks}"
  }

  ingress {
    from_port       = 80
    to_port         = 80
    protocol        = "tcp"
    security_groups = ["${aws_security_group.alb.id}"]
  }

Finally let's define new variables that we have introduced in configuration blocks during this section.

Add the following to variables.tf:

variable "amis" {
  type = "map"
}
variable "instance_type" {}
variable "autoscaling_group_min_size" {}
variable "autoscaling_group_max_size" {}

Assign the variable values in terraform.tfvars. A map of Amazon Machine Image ID's (AMI's) needs to be defined for looking up the machine image id from the AWS region that's been configured. Make sure that there is at least an ID entry for the region that has been configured which in our case is eu-west-1.

Here we will use the image identifier for "Amazon Linux AMI 2017.09.1 (HVM), SSD Volume Type".

amis = {
  "eu-west-1" = "ami-ebd02392"
}

Assign the variable value for the instance type that we will use. This is chosen based on the requirements of the application that you plan to run. We will be running the Spring Boot S3 Example project which has minimal CPU and memory requirements so we will choose the small general purpose instance type t2.micro.

instance_type = "t2.micro"

Define the minimum and maximum sizes of the auto scaling group:

autoscaling_group_min_size = 3
autoscaling_group_max_size = 5

We can now try another plan. The security group should be indicated as being changed:

$ terraform plan -var-file="user.tfvars"

Terraform will perform the following actions:

  + aws_autoscaling_group.autoscaling_group
  + aws_key_pair.deployer
  + aws_launch_configuration.launch_config
  ~ aws_security_group.default

Plan: 3 to add, 1 to change, 0 to destroy.

After reviewing the plan, let's create those web server instances!

$ terraform apply -var-file="user.tfvars"

Apply complete! Resources: 3 added, 1 changed, 0 destroyed.

You can find all the source code for this part of the lab here in GitHub.

More posts in this series.