Skip to content

Terraform module to create an ingress stack powered by AWS Application Load Balancer

Notifications You must be signed in to change notification settings

thoughtbot/terraform-alb-ingress

Repository files navigation

Terraform ALB Ingress

Provisions an ingress stack using an AWS Application Load Balancer suitable for deployments to EKS or ECS.

Major features:

  • Create an AWS ALB with a dedicated security group
  • Create an HTTP listener to redirect plaintext traffic to HTTPS
  • Create an HTTPS listener to forward traffic to one or more target groups
  • Create Route 53 aliases for public traffic
  • Create ACM certificates for SSL
  • Validate ACM certificates using Route 53
  • Create sensible Cloudwatch alarms for monitoring traffic
  • Support multi-account configurations
  • Support externally created certificates when not using Route 53

Example

module "ingress" {
  source = "[email protected]:thoughtbot/terraform-alb-ingress.git?ref=EXAMPLE"

  # Basic attributes
  description              = "My example application"
  name                     = "example-ingress"

  # Choose the domain name of the primary certificate of the HTTPS listener
  primary_certificate_domain  = "www.example.com"

  # Create and validate ACM certificates
  issue_certificate_domains = ["www.example.com", "beta.example.com"]
  validate_certificates     = true

  # Attach ACM certificates created outside the module
  attach_certificate_domains = ["example.com"]

  # Create aliases
  create_domain_aliases = ["www.example.com", "beta.example.com"]

  # Choose a Route 53 zone for aliases and certificate validation
  hosted_zone_name = "example.com"

  # Choose what should happen from CloudWatch alarms
  alarm_actions = [data.aws_sns_topic.cloudwatch_alarms]

  # Network configuration
  subnet_ids = data.aws_subnet_ids.public.ids
  vpc_id     = data.aws_vpc.example.id

  # Target group configuration
  target_groups = {
    canary = {
      health_check_path = "/healthz"
      health_check_port = "8080"
      name              = "canary"
    }
    stable = {
      health_check_path = "/healthz"
      health_check_port = "8080"
      name              = "stable"
    }
  }

  target_group_weights = {
    canary = 5
    stable = 95
  }
}

Multi-account Example

The primary module can issue ACM certificates, perform Route 53 ACM certificate validation, and create Route 53 aliases for a single hosted zone. If you have multiple hosted zones or multiple accounts, you can combine the main module with one or more submodules. For example, if you have example.com as a hosted zone in your network account and production.example.com as a hosted zone in your production account:

module "root_certificate" {
  source    = "github.com/thoughtbot/terraform-alb-ingress//modules/acm-certificate?ref=EXAMPLE"

  providers = {
    # AWS provider configuration for the production account. Must match the ALB.
    aws.certificate = aws.production,

    # AWS provider configuration for the network account.
    aws.route53 = aws.network
  }

  domain_name      = "example.com"
  hosted_zone_name = "example.com"
}

module "www_certificate" {
  providers = { aws.certificate = aws.production, aws.route53 = aws.network }
  source    = "github.com/thoughtbot/terraform-alb-ingress//modules/acm-certificate?ref=EXAMPLE"

  domain_name      = "www.example.com"
  hosted_zone_name = "example.com"
}

module "ingress" {
  providers = { aws.alb = aws.production, aws.route53 = aws.production }
  source    = "github.com/thoughtbot/terraform-alb-ingress?ref=EXAMPLE"

  # The domain name for the primary certificate on the HTTPS listener.
  primary_certificate_domain = "production.example.com"

  # Certificates managed by this module
  issue_certificate_domains = ["production.example.com"]

  # Externally created certificates
  attach_certificate_domains = ["example.com", "www.example.com"]

  # The name of the hosted zone where records for the ALB can be managed
  hosted_zone_name = "production.example.com"

  # Aliases which can be created in the primary hosted zone
  create_domain_aliases = ["production.example.com"]

  depends_on = [module.root_certificate, module.www_certificate]
}

module "root_alias" {
  source    = "github.com/thoughtbot/terraform-alb-ingress//modules/alb-route53-alias?ref=EXAMPLE"

  providers = {
    # AWS provider configuration for the production account. Must match the ALB.
    aws.certificate = aws.production,

    # AWS provider configuration for the network account.
    aws.route53 = aws.network
  }

  alb_dns_name     = module.ingress.alb_dns_name
  alb_zone_id      = module.ingress.alb_zone_id
  name             = "example.com"
  hosted_zone_name = "example.com"
}

module "www_alias" {
  providers = { aws.certificate = aws.production, aws.route53 = aws.network }
  source    = "github.com/thoughtbot/terraform-alb-ingress//modules/alb-route53-alias?ref=EXAMPLE"

  alb_dns_name     = module.ingress.alb_dns_name
  alb_zone_id      = module.ingress.alb_zone_id
  name             = "www.example.com"
  hosted_zone_name = "example.com"
}

Non-Route 53 Example

If you aren't using Route 53 as a DNS provider, you can issue certificates on your own and disable creation of aliases.

module "ingress" {
  providers = { aws.alb = aws, aws.route53 = aws }
  source    = "github.com/thoughtbot/terraform-alb-ingress?ref=EXAMPLE"

  # The domain name for the primary certificate on the HTTPS listener.
  primary_certificate_domain = "example.com"

  # Don't issue any certificates
  issue_certificate_domains = []

  # Externally created certificates
  attach_certificate_domains = ["example.com", "www.example.com"]

  # Don't create aliases
  create_domain_aliases = ["production.example.com"]
}

Requirements

Name Version
terraform >= 0.14.0
aws ~> 5.0

Providers

Name Version
aws ~> 5.0

Modules

Name Source Version
acm_certificate ./modules/acm-certificate n/a
alb ./modules/alb n/a
alias ./modules/alb-route53-alias n/a
cloudwatch_alarms ./modules/alb-cloudwatch-alarms n/a
http ./modules/alb-http-redirect n/a
https ./modules/alb-https-forward n/a
target_group ./modules/alb-target-group n/a

Resources

Name Type
aws_lb_target_group.legacy data source

Inputs

Name Description Type Default Required
alarm_actions SNS topics or other actions to invoke for alarms list(object({ arn = string })) [] no
alarm_evaluation_minutes Number of minutes of alarm state until triggering an alarm number 2 no
allow_overwrite Allow overwriting of existing DNS records bool false no
attach_certificate_domains Additional existing certificates which should be attached list(string) [] no
certificate_types Types of certificates to look for (default: AMAZON_ISSUED) list(string)
[
"AMAZON_ISSUED"
]
no
create_domain_aliases List of domains for which alias records should be created list(string) n/a yes
description Human description for this load balancer string n/a yes
enable_stickiness Set to true to use a cookie for load balancer stickiness bool false no
failure_threshold Percentage of failed requests considered an anomaly number 5 no
hosted_zone_name Hosted zone for AWS Route53 string null no
issue_certificate_domains List of domains for which certificates should be issued list(string) [] no
legacy_target_group_names Names of legacy target groups which should be included list(string) [] no
name Name for this load balancer string n/a yes
primary_certificate_domain Primary domain name for the load balancer certificate string n/a yes
security_group_name Name for the load balancer security group; defaults to name string null no
slow_response_threshold Response time considered extremely slow number 10 no
subnet_ids Subnets for this load balancer list(string) n/a yes
tags Tags to apply to created resources map(string) {} no
target_group_weights Weight for each target group (defaults to 100) map(number) {} no
target_groups Target groups to which this rule should forward
map(object({
health_check_path = string,
health_check_port = number,
name = string
}))
n/a yes
validate_certificates Set to false to disable validation via Route 53 bool true no
vpc_id VPC for the ALB string n/a yes

Outputs

Name Description
dns_name DNS name of the created application load balancer
http_listener The HTTP listener
https_listener The HTTPS listener
instance The load balancer
security_group Security group for the load balancer
zone_id Route53 zone of the created application load balancer

About

Terraform module to create an ingress stack powered by AWS Application Load Balancer

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Packages

No packages published