-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Archive a clean copy of Terraform configs (#1565)
- Loading branch information
Showing
26 changed files
with
1,717 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Scale the API service up and down depending on usage. | ||
# | ||
# The target defines the resource to be scaled and its limits, while the | ||
# policies do the actual scaling (and define how much and how often to do so), | ||
# and the alarms ultimately define the conditions under which to scale and call | ||
# the policies when those conditions are met. | ||
|
||
resource "aws_appautoscaling_target" "target" { | ||
service_namespace = "ecs" | ||
resource_id = "service/${aws_ecs_cluster.main.name}/${aws_ecs_service.api_service.name}" | ||
scalable_dimension = "ecs:service:DesiredCount" | ||
min_capacity = 2 | ||
max_capacity = 4 | ||
} | ||
|
||
# Automatically scale capacity up by one | ||
resource "aws_appautoscaling_policy" "up" { | ||
name = "api_scale_up" | ||
service_namespace = aws_appautoscaling_target.target.service_namespace | ||
resource_id = aws_appautoscaling_target.target.resource_id | ||
scalable_dimension = aws_appautoscaling_target.target.scalable_dimension | ||
|
||
step_scaling_policy_configuration { | ||
adjustment_type = "ChangeInCapacity" | ||
cooldown = 60 | ||
metric_aggregation_type = "Maximum" | ||
|
||
step_adjustment { | ||
metric_interval_lower_bound = 0 | ||
scaling_adjustment = 1 | ||
} | ||
} | ||
} | ||
|
||
# Automatically scale capacity down by one | ||
resource "aws_appautoscaling_policy" "down" { | ||
name = "api_scale_down" | ||
service_namespace = aws_appautoscaling_target.target.service_namespace | ||
resource_id = aws_appautoscaling_target.target.resource_id | ||
scalable_dimension = aws_appautoscaling_target.target.scalable_dimension | ||
|
||
step_scaling_policy_configuration { | ||
adjustment_type = "ChangeInCapacity" | ||
cooldown = 60 | ||
metric_aggregation_type = "Maximum" | ||
|
||
step_adjustment { | ||
metric_interval_upper_bound = 0 | ||
scaling_adjustment = -1 | ||
} | ||
} | ||
} | ||
|
||
# CloudWatch alarm that triggers the autoscaling up policy | ||
resource "aws_cloudwatch_metric_alarm" "service_cpu_high" { | ||
alarm_name = "api_cpu_utilization_high" | ||
comparison_operator = "GreaterThanOrEqualToThreshold" | ||
datapoints_to_alarm = "1" | ||
evaluation_periods = "1" | ||
metric_name = "CPUUtilization" | ||
namespace = "AWS/ECS" | ||
period = "60" | ||
statistic = "Average" | ||
threshold = "55" | ||
|
||
dimensions = { | ||
ClusterName = aws_ecs_cluster.main.name | ||
ServiceName = aws_ecs_service.api_service.name | ||
} | ||
|
||
alarm_actions = [aws_appautoscaling_policy.up.arn] | ||
} | ||
|
||
# CloudWatch alarm that triggers the autoscaling down policy | ||
resource "aws_cloudwatch_metric_alarm" "service_cpu_low" { | ||
alarm_name = "api_cpu_utilization_low" | ||
comparison_operator = "LessThanOrEqualToThreshold" | ||
datapoints_to_alarm = "2" | ||
evaluation_periods = "2" | ||
metric_name = "CPUUtilization" | ||
namespace = "AWS/ECS" | ||
period = "60" | ||
statistic = "Average" | ||
threshold = "15" | ||
|
||
dimensions = { | ||
ClusterName = aws_ecs_cluster.main.name | ||
ServiceName = aws_ecs_service.api_service.name | ||
} | ||
|
||
alarm_actions = [aws_appautoscaling_policy.down.arn] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
# Domains and CDN/Caching Layers | ||
# | ||
# The DNS zone (defined by the `domain_name` variable) should be manually | ||
# created in the AWS console, but all the records for the domain and subdomains | ||
# are managed here in code. | ||
# | ||
# The domains all point to CloudFront distributions for caching and DOS | ||
# protection. These are only turned on if there is also an SSL certificate | ||
# (set in the `ssl_certificate_arn` variable, and which also needs to be | ||
# created manually in the AWS console). | ||
|
||
locals { | ||
# The domain of the API service's load balancer (not for public use). | ||
api_internal_subdomain = "api.internal" | ||
api_internal_domain = ( | ||
var.domain_name != "" | ||
? "${local.api_internal_subdomain}.${var.domain_name}" | ||
: "" | ||
) | ||
|
||
# Domain at which to serve archived, historical data (stored in S3). | ||
data_snapshots_subdomain = "archives" | ||
data_snapshots_domain = ( | ||
var.domain_name != "" | ||
? "${local.data_snapshots_subdomain}.${var.domain_name}" | ||
: "" | ||
) | ||
} | ||
|
||
# Domain DNS Recods ----------------------------------------------------------- | ||
|
||
data "aws_route53_zone" "domain_zone" { | ||
count = var.domain_name != "" ? 1 : 0 | ||
name = var.domain_name | ||
} | ||
|
||
# DNS record for the domain specified in the `domain_name` variable. | ||
resource "aws_route53_record" "api_domain_record" { | ||
count = var.domain_name != "" ? 1 : 0 | ||
|
||
zone_id = data.aws_route53_zone.domain_zone[0].zone_id | ||
name = var.domain_name | ||
type = "A" | ||
|
||
alias { | ||
name = aws_cloudfront_distribution.univaf_api_ecs[0].domain_name | ||
zone_id = aws_cloudfront_distribution.univaf_api_ecs[0].hosted_zone_id | ||
evaluate_target_health = false | ||
} | ||
} | ||
|
||
# The `www.` subdomain. It is an alias for the primary domain name. | ||
resource "aws_route53_record" "api_www_domain_record" { | ||
count = var.domain_name != "" ? 1 : 0 | ||
zone_id = data.aws_route53_zone.domain_zone[0].zone_id | ||
name = "www" | ||
type = "CNAME" | ||
records = [var.domain_name] | ||
ttl = 300 | ||
} | ||
|
||
# The `api.internal` subdomain. Used for the API service's load balancer so it | ||
# can be secured with HTTPS. | ||
resource "aws_route53_record" "api_load_balancer_domain_record" { | ||
count = var.domain_name != "" ? 1 : 0 | ||
|
||
zone_id = data.aws_route53_zone.domain_zone[0].zone_id | ||
name = local.api_internal_subdomain | ||
type = "A" | ||
|
||
alias { | ||
name = aws_alb.main.dns_name | ||
zone_id = aws_alb.main.zone_id | ||
evaluate_target_health = false | ||
} | ||
} | ||
|
||
# The `ecs.` subdomain. | ||
# This specifically points to the deployment on ECS (as opposed to a possible | ||
# external host). | ||
resource "aws_route53_record" "api_ecs_domain_record" { | ||
count = var.domain_name != "" ? 1 : 0 | ||
|
||
zone_id = data.aws_route53_zone.domain_zone[0].zone_id | ||
name = "ecs" | ||
type = "A" | ||
|
||
alias { | ||
name = aws_cloudfront_distribution.univaf_api_ecs[0].domain_name | ||
zone_id = aws_cloudfront_distribution.univaf_api_ecs[0].hosted_zone_id | ||
evaluate_target_health = false | ||
} | ||
} | ||
|
||
|
||
# CloudFront ------------------------------------------------------------------ | ||
|
||
# Use CloudFront as a caching layer in front of the API server that's running | ||
# in ECS. Enabled only if var.domain and var.ssl_certificate_arn are provided. | ||
resource "aws_cloudfront_distribution" "univaf_api_ecs" { | ||
count = ( | ||
var.domain_name != "" | ||
&& var.ssl_certificate_arn != "" ? 1 : 0 | ||
) | ||
enabled = true | ||
price_class = "PriceClass_100" # North America | ||
aliases = [ | ||
var.domain_name, | ||
"www.${var.domain_name}", | ||
"ecs.${var.domain_name}" | ||
] | ||
http_version = "http2and3" | ||
|
||
origin { | ||
origin_id = "ecs.${var.domain_name}" | ||
domain_name = local.api_internal_domain | ||
|
||
custom_header { | ||
name = var.api_cloudfront_secret_header_name | ||
value = var.api_cloudfront_secret | ||
} | ||
|
||
custom_origin_config { | ||
http_port = 80 | ||
https_port = 443 | ||
origin_ssl_protocols = ["SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2"] | ||
origin_protocol_policy = "https-only" | ||
} | ||
} | ||
|
||
default_cache_behavior { | ||
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] | ||
cached_methods = ["GET", "HEAD"] | ||
target_origin_id = "ecs.${var.domain_name}" | ||
viewer_protocol_policy = "redirect-to-https" | ||
min_ttl = 0 | ||
max_ttl = 3600 | ||
|
||
forwarded_values { | ||
headers = ["Host", "Origin", "Authorization", "x-api-key"] | ||
query_string = true | ||
|
||
cookies { | ||
forward = "none" | ||
} | ||
} | ||
} | ||
|
||
viewer_certificate { | ||
acm_certificate_arn = var.ssl_certificate_arn | ||
ssl_support_method = "sni-only" | ||
} | ||
|
||
restrictions { | ||
geo_restriction { | ||
restriction_type = "none" | ||
} | ||
} | ||
} | ||
|
||
# Provide a protective caching layer and a nice domain name for the S3 bucket | ||
# with historical data. (Allowing direct public access can get expensive.) | ||
# Docs: https://github.com/cloudposse/terraform-aws-cloudfront-s3-cdn | ||
module "univaf_data_snaphsots_cdn" { | ||
count = ( | ||
var.domain_name != "" | ||
&& var.ssl_certificate_arn != "" ? 1 : 0 | ||
) | ||
source = "cloudposse/cloudfront-s3-cdn/aws" | ||
version = "0.90.0" | ||
|
||
origin_bucket = aws_s3_bucket.data_snapshots.bucket | ||
dns_alias_enabled = true | ||
aliases = [local.data_snapshots_domain] | ||
parent_zone_id = data.aws_route53_zone.domain_zone[0].zone_id | ||
acm_certificate_arn = var.ssl_certificate_arn | ||
cloudfront_access_logging_enabled = false | ||
|
||
default_ttl = 60 * 60 * 24 * 7 # 1 Week | ||
http_version = "http2and3" | ||
allowed_methods = ["GET", "HEAD", "OPTIONS"] | ||
cached_methods = ["GET", "HEAD", "OPTIONS"] | ||
# By default, CORS headers are forwarded, but we don't really care about them | ||
# since the bucket is not operating in "website" mode. | ||
forward_header_values = [] | ||
|
||
# HACK: this module creates bad values if you don't explicitly set one or | ||
# more of namespace, environment, stage, name, or attributes. | ||
# Basically, Cloud Posse modules generate an internal ID from the above, | ||
# and that ID is used for lots of things. Bad stuff happens if it is empty. | ||
# This issue is marked as closed, but is not actually solved: | ||
# https://github.com/cloudposse/terraform-aws-cloudfront-s3-cdn/issues/151 | ||
namespace = "cp" | ||
name = "univaf_data_snaphsots_cdn" | ||
} |
Oops, something went wrong.