Skip to content

This Terraform module provides a flexible way to create highly available NAT instances on AWS

License

Notifications You must be signed in to change notification settings

scamfield/terraform-aws-nat-instance

Repository files navigation

AWS NAT Instance Terraform module with some HA

This Terraform module provides a flexible way to create highly available NAT instances on AWS.

While I am a proponent of using NAT instances, I would recommend that for production use, it's best to stick with the NAT Gateways provided by AWS or use them instead.

Prerequisite

  • Cloudtrail must be enabled in order to capture ASG events.
  • The lambda scripts currently assume that instances have "-nat-" in their name and that private subnets have "-private-" in their name, which may not always be the case. While this approach works, a more flexible solution is being explored.

Usage

If you already have the VPC setup without terraform, you can put in the id's like this:

module "nat" {
  source = "github.com/scamfield/terraform-aws-nat-instance"

  name = module.vpc.name

  aws_key_name = "ssh-key"

  vpc_id = "vpc-056d68ea46d510b09"
  public_subnet_ids  = ["subnet-0873b9d701bf16b22", "subnet-0a9b98b6fefe81141"]
  private_subnet_ids = ["subnet-0619e46d25c65c108", "subnet-0b907bfbb53c10637"]

}

If you're utilizing the widely-used terraform-aws-modules/vpc/aws module, you can simply pass in the relevant details from the module. However, make sure that the vpc module is executed first.

module "nat" {
  source = "github.com/scamfield/terraform-aws-nat-instance"

  name = module.vpc.name

  aws_key_name = "ssh-key"

  vpc_id = module.vpc.vpc_id
  public_subnet_ids  = module.vpc.public_subnets
  private_subnet_ids = module.vpc.private_subnets

}

How it works

This Terraform module is designed to deploy an auto-scaling group in each availability zone. Each group includes one EC2 instance with a minimum and maximum capacity of one. The group is also configured with an ENI interface that acts as the destination for 0.0.0.0/0 routing table. This design ensures that the auto-scaling group can handle availability zone outages.

In case of a failure within the auto-scaling group, an event is triggered, which is then picked up by EventBridge. EventBridge, in turn, invokes a Lambda function that is authorized to update the routing table for the failed EC2 instance's subnet to a different one.

diagram

Contributing

Report issues/questions/feature requests on in the issues section.

Requirements

Name Version
terraform >= 0.13.5
aws >= 3.22.0
template >= 2.1

Providers

Name Version
aws >= 3.22.0
template >= 2.1

Modules

No modules.

Resources

Name Type
aws_autoscaling_group.asg resource
aws_cloudwatch_log_group.nat_failover_logs resource
aws_eip.eip resource
aws_iam_instance_profile.nat_profile resource
aws_iam_policy.nat_failover_lambda_policy resource
aws_iam_role.nat_failover_lambda resource
aws_iam_role.role resource
aws_iam_role_policy.modify_routes resource
aws_iam_role_policy_attachment.nat_failover_lambda resource
aws_lambda_function.nat_failover_lambda resource
aws_lambda_permission.allow_sns resource
aws_launch_template.launch_template resource
aws_network_interface.eni resource
aws_security_group.sg_nat resource
aws_security_group_rule.sgr_nat_inbound resource
aws_security_group_rule.sgr_nat_out resource
aws_sns_topic.nat_failover_topic resource
aws_sns_topic_subscription.nat_failover_lambda resource
aws_ami.ami data source
aws_caller_identity.current data source
aws_iam_policy_document.assume_role_policy data source
aws_iam_policy_document.policy data source
aws_region.current data source
aws_subnet.eni_subnet data source
aws_subnet.first data source
aws_subnet.subnets data source
aws_vpc.vpc data source
template_cloudinit_config.cloudinit data source
template_file.cloudinit_base data source
template_file.nat_failover_systemd data source
template_file.nat_failover_trigger_script data source

Inputs

Name Description Type Default Required
aws_key_name n/a string "" no
instance_type n/a string "t4g.micro" no
name n/a string "default" no
private_subnet_ids n/a list(string) n/a yes
public_subnet_ids n/a list(string) n/a yes
vpc_id n/a string n/a yes

Outputs

No Outputs.

Known Issues

If you come across the following error during deployment, it might be because the subnets have not been created yet or are invalid. This is due to looping through the subnets, causing the error to occur:

Error: Invalid for_each argument
│
│   on .terraform/modules/nat/data.tf line 36, in data "aws_subnet" "subnets":
│   36:   for_each = toset(concat(var.private_subnet_ids, var.public_subnet_ids))
│     ├────────────────
│     │ var.private_subnet_ids is list of string with 2 elements
│     │ var.public_subnet_ids is list of string with 2 elements
│
│ The "for_each" value depends on resource attributes that cannot be determined until apply, so Terraform cannot
│ predict how many instances will be created. To work around this, use the -target argument to first apply only the
│ resources that the for_each depends on.

Authors

Module is maintained by Stephen Camfield with help from these awesome contributors.

License

About

This Terraform module provides a flexible way to create highly available NAT instances on AWS

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published