Skip to content

aws-ia/terraform-aws-route53-recovery-controller

Repository files navigation

AWS Route53 Application Recovery Controller Module

Amazon Route53 Application Recovery Controller (Route 53 ARC) is a set of Route 53 features that help you build applications with high availability. Route 53 ARC can continuously monitor your application's ability to recover from failure and control recovery across multiple AWS Availability Zones, AWS Regions, and on-premises environments. This Terraform module contains both Route 53 ARC readiness and recovery-cluster resources. You can deploy only the readiness resources, or both. For more information about creating a resilience strategy with Route 53 ARC, see Running recovery-oriented applications with Amazon Route 53 Application Recovery Controller, AWS CI/CD tools, and Terraform.

Example Architecture

Example Deployment of app with R53 ARC

Usage

The primary configuration variable is cells_definition. With this variable, you specify the AWS resources per Region that you want Route 53 ARC to monitor. See examples for working examples.

Readiness resources only

The following terraform.tfvars values create a recovery group. The recovery group consists of Region cells us-east-1 and us-west-2, each with a resource set of services elasticloadbalancing, autoscaling, dynamodb, and ec2-volume and their Amazon Resource Numbers (ARNs). Readiness checks are associated with each resource set.

name = "my-asg-elb-ddb-app"

cells_definition = {
  us-east-1 = {
    elasticloadbalancing = <arn>
    autoscaling          = <arn>
    dynamodb             = <arn>
    ec2-volume           = <arn>
  }
  us-west-2 = {
    elasticloadbalancing = <arn>
    autoscaling          = <arn>
    dynamodb             = <arn>
    ec2-volume           = <arn>
  }
}

Routing control cluster resources and Route 53 alias records

To define a managed Route 53 ARC cluster for your application, add the following Terraform variables.

create_recovery_cluster = true

hosted_zone = {
  name = "mycoolapp.com."
}

The example shown configures the following:

  • A recovery cluster with a single control panel.
  • One routing control per Region.
  • Safety rules. The default is one, but you can declare more than one.
  • One Route 53 health check per routing control.
  • Route 53 alias records for each load balancer for the domain specified.

Currently, this module supports active/passive for applications across Regions. The active Region is determined by your provider block or by var.primary_cell_region. (See "Inputs", later in this document.)

Available services

The R53 Readiness service supports monitoring many services, most of which have been implemented in this module or can easily be added / extended (even without a PR!). The service keys used in var.cells_definition must match a key in var.resource_type_name in variables.tf which links to the CloudFormation resource type that is accepted by Readiness service. Example:

variable "resource_type_name" {
  type        = map(string)
  description = "list of all service types you can pass and their associated Resource Set Type."

  default = {
    apigateway  = "AWS::ApiGatewayV2::Api"
    autoscaling = "AWS::AutoScaling::AutoScalingGroup"
    cloudwatch  = "AWS::CloudWatch::Alarm"
    dynamodb    = "AWS::DynamoDB::Table"
    ec2-volume  = "AWS::EC2::Volume"
    ...
  }
}

Adding a new service

If a service does not exist in the default var.resource_type_name value you can include it without a PR. We also ask that you please do open a PR to include it in default value.

Where you set your variables, simply define a new service key with the associated CloudFormation resource type. You must include all service keys that you plan to use in that root module. In the example below new-service is a new service that the Readiness can monitor. We add it to our local deployment and then use it immediately in var.cells_definition:

resource_type_name = {
  new-service = "AWS::NewService::NewAction"
  dynamodb    = "AWS::DynamoDB::Table"
  ...
}

cells_definition = {
  <region> = {
    new-service = <arn>
  }
}

Requirements

Name Version
terraform >= 0.15.0
aws >= 3.68

Providers

Name Version
aws.ap-northeast-1 >= 3.68
aws.ap-northeast-2 >= 3.68
aws.ap-northeast-3 >= 3.68
aws.ap-south-1 >= 3.68
aws.ap-southeast-1 >= 3.68
aws.ap-southeast-2 >= 3.68
aws.ca-central-1 >= 3.68
aws.eu-central-1 >= 3.68
aws.eu-north-1 >= 3.68
aws.eu-west-1 >= 3.68
aws.eu-west-2 >= 3.68
aws.eu-west-3 >= 3.68
aws.sa-east-1 >= 3.68
aws.us-east-1 >= 3.68
aws.us-east-2 >= 3.68
aws.us-west-1 >= 3.68
aws.us-west-2 >= 3.68

Modules

Name Source Version
recovery_cluster ./modules/recovery_cluster n/a
recovery_group ./modules/readiness_recovery_group n/a

Resources

Name Type
aws_lb.ap_northeast_1 data source
aws_lb.ap_northeast_2 data source
aws_lb.ap_northeast_3 data source
aws_lb.ap_south_1 data source
aws_lb.ap_southeast_1 data source
aws_lb.ap_southeast_2 data source
aws_lb.ca_central_1 data source
aws_lb.eu_central_1 data source
aws_lb.eu_north_1 data source
aws_lb.eu_west_1 data source
aws_lb.eu_west_2 data source
aws_lb.eu_west_3 data source
aws_lb.sa_east_1 data source
aws_lb.us_east_1 data source
aws_lb.us_east_2 data source
aws_lb.us_west_1 data source
aws_lb.us_west_2 data source

Inputs

Name Description Type Default Required
cells_definition Nested map where the key is a region you want to enable and keys referring to resource arns to enable. Services enabled are defined in var.resource_type_name. For examples, see the variables.tf file"
/
cells_definition = {
us-west-2 = {
elasticloadbalancing = "arn:aws:elasticloadbalancing:us-west-2:<>:loadbalancer/app/<>"
autoscaling = "arn:aws:autoscaling:us-west-2:<>:autoScalingGroup:
:autoScalingGroupName/<>
}
}
*/
map(map(string)) n/a yes
name Name to prefix resources. string n/a yes
create_recovery_cluster Create the Routing Control Cluster and associated resources. bool false no
hosted_zone Info about the hosted zone. If the name or zone_id is not passed, a search will be performed using the values provided. Leave null to not create Route53 Alias records (required for LB functionality).
object({
name = optional(string)
private_zone = optional(bool)
vpc_id = optional(string)
tags = optional(map(string))
zone_id = optional(string)
})
{
"name": null,
"zone_id": null
}
no
primary_cell_region (Optional) Region name of which Cell to make Route53 Primary. Defaults to default provider region if not set. string null no
resource_type_name list of all service types you can pass and their associated Resource Set Type. map(string)
{
"apigateway": "AWS::ApiGatewayV2::Api",
"autoscaling": "AWS::AutoScaling::AutoScalingGroup",
"cloudwatch": "AWS::CloudWatch::Alarm",
"dynamodb": "AWS::DynamoDB::Table",
"ec2-volume": "AWS::EC2::Volume",
"ec2-vpc": "AWS::EC2::VPC",
"ec2-vpn-cgw": "AWS::EC2::CustomerGateway",
"ec2-vpn-conn": "AWS::EC2::VPNConnection",
"ec2-vpn-gw": "AWS::EC2::VPNGateway",
"elasticloadbalancing": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"kafka": "AWS::MSK::Cluster",
"lambda": "AWS::Lambda::Function",
"rds": "AWS::RDS::DBCluster",
"route53": "AWS::Route53::HealthCheck",
"sns": "AWS::SNS::Topic",
"sqs": "AWS::SQS::Queue"
}
no
safety_rule_type Type of safety rules to create. Can only be "assertion" or "gating". string "assertion" no
safety_rules Configuration of the Safety Rules. Key is the name applied to the rule.
map(object({
wait_period_ms = number
inverted = bool
threshold = number
type = string
name_suffix = string
}))
{
"MinCellsActive": {
"inverted": false,
"name_suffix": "MinCellsActive",
"threshold": 1,
"type": "ATLEAST",
"wait_period_ms": 5000
}
}
no
tags Map of tags to be added to Readiness resources. map(string) null no

Outputs

Name Description
cells Cells per Region.
cluster Cluster information.
control_panel Control Panel information.
health_checks Health checks.
r53_aliases Route53 alias records, if created.
readiness_checks A Readiness check for each resource set.
recovery_group Recovery group resource.
resource_sets A Resource set for each service with ARN entries for each Region.
routing_controls Routing controls per cell.
safety_rules Safety rules.