This project does the following:
- builds a vpc (10.0.0.0/16)
- creates 4 subnets, 2 public and 2 private
- creates a public-facing ALB
- creates an ASG for the ec2 instance. I did this as a best practice to make sure uptime is optimal in the event of an instance failure
- As part of the ASG, also created a role/policy in the event we need access to the ec2 instance, which would be available via SSM
- creates the security groups for the ALB as well as the ec2 instance. The ec2 sg has limited access only allowing traffic from the ALB security group
- creates a self-signed cert that is uploaded to ACM, to be used by the ALB
- and outputs a few things for testing
- As always, setting up terraform in a new account can lead to a "chicken or the egg" scenario. Terragrunt helps a ton with this as it will create your state bucket and terraform dynamodb lock table for you. In this case, I wrote a quick little bash script
backend_scripts/install_backend.sh
. Its not ideal, but it does solve the issue of having a state bucket and dynamodb lock table. Other solutions are to use terraform for this, but it still involves a two step process which then you have to move state around anyways. I took the easier route here. - With the ASG, you really don't have access to ec2 instance information that is readily available to lookup. In this case, The output for the IP address has to wait until the ASG module is done, so the ec2 instance can be looked up. Now this accounts for the point in time ec2 instance running. If the instance were to get terminated, the output would be outdated and need to be re-ran to get the new IP.
- Permissions. Since keys are needed for github actions (or Roles if you have self-hosted runners in your VPC) there is an assumption that the keys/Role have the permissions needed to create the needed infrastructure. Due to the nature of Terraform and what it can all manage,this tends to be Admin rights, or a collection of rather broad permissions.
This deployment doesn't use workspaces, but rather a very flat file system approach. All files for all environments could sit right in the repo root.
Deployment steps are:
Terraform init. This is using our "demo" backend parameters:
terraform init -backend-config=demo.config.tfbackend
Terraform validate to be sure everything checks out:
terraform validate
Terraform Plan to see what all we are about to build. This is using our "demo" tfvars file which could also be dev/stage/prod:
terraform plan -var-file=demo.tfvars
Terraform Apply to execute our build. You will be asked to verify what is all being created, "yes" is the olny option to continue:
terraform apply -var-file=demo.tfvars
Terraform destroy. Finally when all is done, we can clean up all resources created:
terraform destroy -var-file=demo.tfvars
Verifying the setup:
- once the Terraform Apply is done, you will have 2 outputs, 1 for the public ALB DNS Name (HTTP will redirect to HTTPS), 2 an output of the ec2 instance IP address that can be verified in the Console. These outputs are also documented below.
I tired to be as thorough as possible in regards to deploying the environment. As far as testing the deployments:
deployment type | tested | passing |
---|---|---|
locally | yes | yes |
github action | yes | yes |
gitlab pipeline | no | N/A |
Name | Version |
---|---|
terraform | ~> 1.8.0 |
Name | Version |
---|---|
aws | 5.52.0 |
tls | 4.0.5 |
Name | Source | Version |
---|---|---|
alb | terraform-aws-modules/alb/aws | 9.9.0 |
asg | terraform-aws-modules/autoscaling/aws | 7.6.0 |
demo_web_sg | terraform-aws-modules/security-group/aws | 5.1.2 |
vpc | terraform-aws-modules/vpc/aws | 5.8.1 |
Name | Type |
---|---|
aws_acm_certificate.demo | resource |
aws_eip.nat | resource |
tls_private_key.demo | resource |
tls_self_signed_cert.demo | resource |
aws_ami.demo_site | data source |
aws_instances.demo | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
environment | n/a | string |
"demo" |
no |
nat_node_count | n/a | string |
n/a | yes |
region | n/a | string |
"us-east-1" |
no |
tag_environment | n/a | string |
n/a | yes |
vpc_azs | n/a | list(string) |
n/a | yes |
vpc_cidr | n/a | string |
n/a | yes |
vpc_dnsnames | n/a | bool |
n/a | yes |
vpc_dnssupport | n/a | string |
n/a | yes |
vpc_enable_nat_gateway | n/a | bool |
n/a | yes |
vpc_enable_vpn_gateway | n/a | bool |
n/a | yes |
vpc_name | n/a | string |
n/a | yes |
vpc_private_subnets | n/a | list(string) |
n/a | yes |
vpc_public_subnets | n/a | list(string) |
n/a | yes |
vpc_reuse_nat_ips | n/a | bool |
n/a | yes |
Name | Description |
---|---|
alb_endpoint | Public ALB DNS Name |
ec2_ip_address | EC2 IP Address |