-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add S3 tile caching to Terraform config #686
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,10 @@ resource "aws_cloudfront_distribution" "tilegarden" { | |
https_port = 443 | ||
origin_protocol_policy = "https-only" | ||
origin_ssl_protocols = ["TLSv1.2", "TLSv1.1", "TLSv1"] | ||
origin_read_timeout = 60 | ||
} | ||
|
||
domain_name = "${var.tilegarden_api_gateway_domain_name}" | ||
origin_path = "/latest" | ||
origin_id = "tilegardenOriginEastId" | ||
|
||
custom_header { | ||
|
@@ -17,16 +17,57 @@ resource "aws_cloudfront_distribution" "tilegarden" { | |
} | ||
} | ||
|
||
origin { | ||
custom_origin_config { | ||
http_port = 80 | ||
https_port = 443 | ||
|
||
# S3 websites don't support TLS :/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there an established way around this? It seems icky to send the second leg of the request over plaintext. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not if we're using the S3 website endpoint. I haven't looked at the other parts of the request path, but has there been consideration to hitting the dynamic endpoint first? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had assumed that we would need to use the S3 website endpoint in order to use redirect rules, is there a way of accomplishing that with the dynamic endpoint? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're just hitting static content, I think going over HTTP for this leg is OK. |
||
origin_protocol_policy = "http-only" | ||
origin_ssl_protocols = ["TLSv1.2", "TLSv1.1", "TLSv1"] | ||
} | ||
|
||
domain_name = "${aws_s3_bucket.tile_cache.website_endpoint}" | ||
origin_id = "tilegardenCacheOriginEastId" | ||
|
||
custom_header { | ||
name = "Accept" | ||
value = "image/png" | ||
} | ||
} | ||
|
||
aliases = ["tiles.${var.r53_public_hosted_zone}"] | ||
price_class = "${var.cloudfront_price_class}" | ||
enabled = true | ||
is_ipv6_enabled = true | ||
comment = "${var.project} (${var.environment})" | ||
|
||
# Tilegarden cache origin | ||
default_cache_behavior { | ||
allowed_methods = ["GET", "HEAD", "OPTIONS"] | ||
cached_methods = ["GET", "HEAD"] | ||
target_origin_id = "tilegardenCacheOriginEastId" | ||
|
||
forwarded_values { | ||
query_string = true | ||
|
||
cookies { | ||
forward = "none" | ||
} | ||
} | ||
|
||
viewer_protocol_policy = "redirect-to-https" | ||
min_ttl = 0 | ||
default_ttl = "300" # Five minutes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When I was testing out staging, I got some tiles that timed out, then the error message was cached for 5 minutes even though the Lambda function had actually succeeded and written the tile to S3. So that points to one issue that should be addressed, I assume on the origin definition--the "Origin Response Timeout" should be no shorter than the timeout on the Lambda function (currently 1 minute). I also think it makes sense to set the TTL for the "new tiles" endpoint as short as is reasonable, so that if anything goes wrong it won't be as long until it tries again. There might not actually be a period during which serving a cached response on the API Gateway origin saves a Lambda invocation--before the first one finishes there's no cached response to return, and the tile gets written to S3 before it gets returned from the Lambda function, so there might not be a time during which a request to the S3 cache would miss but one to the API Gateway origin would hit. So 5 minutes seems fine for the S3 origin (longer would probably be fine, too, but I don't know if there would be any advantage to it) but it should be overridden for the "new tiles" cache_behavior below, probably to also be 1 minute or slightly more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm glad you caught this, very subtle but important behavior here. I'll bump the Origin Read Timeout to 60 seconds, which should hopefully make timeouts less common. I agree, I don't see any benefit to caching the Lambda origin. Can you think of any downside to just setting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Actually now I'm thinking I might have missed an interaction in what I wrote above--would the redirect from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Good point, I think it will indeed cache the redirect -- see my note in the testing instructions above. Sounds like the TTLs should be identical for both origins. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, seems like. The change to |
||
max_ttl = "86400" # One day | ||
} | ||
|
||
# Tilegarden lambda origin for generating new tiles | ||
cache_behavior { | ||
allowed_methods = ["GET", "HEAD", "OPTIONS"] | ||
cached_methods = ["GET", "HEAD"] | ||
target_origin_id = "tilegardenOriginEastId" | ||
path_pattern = "/latest/*" | ||
|
||
forwarded_values { | ||
query_string = true | ||
|
@@ -53,4 +94,9 @@ resource "aws_cloudfront_distribution" "tilegarden" { | |
ssl_support_method = "sni-only" | ||
minimum_protocol_version = "TLSv1" | ||
} | ||
|
||
tags { | ||
Project = "${var.project}" | ||
Environment = "${var.environment}" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,3 +32,4 @@ PFB_DB_DATABASE= | |
PFB_DB_PASSWORD= | ||
PFB_DB_PORT= | ||
PFB_DB_USER= | ||
PFB_TILEGARDEN_CACHE_BUCKET= |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,8 +24,8 @@ | |
], | ||
"scripts": { | ||
"build-all-xml": "./scripts/build-all-xml.sh src/config src/config", | ||
"deploy": "yarn compile && claudia update --no-optional-dependencies ${LAMBDA_TIMEOUT:+--timeout ${LAMBDA_TIMEOUT}} ${LAMBDA_MEMORY:+--memory ${LAMBDA_MEMORY}} ${LAMBDA_SECURITY_GROUPS:+--security-group-ids ${LAMBDA_SECURITY_GROUPS}} ${LAMBDA_SUBNETS:+--subnet-ids ${LAMBDA_SUBNETS}}", | ||
"deploy-new": "yarn compile && claudia create --no-optional-dependencies --api-module dist/api --name ${PROJECT_NAME} --region ${LAMBDA_REGION} ${LAMBDA_ROLE:+--role ${LAMBDA_ROLE}} ${LAMBDA_TIMEOUT:+--timeout ${LAMBDA_TIMEOUT}} ${LAMBDA_MEMORY:+--memory ${LAMBDA_MEMORY}} ${LAMBDA_SECURITY_GROUPS:+--security-group-ids ${LAMBDA_SECURITY_GROUPS}} ${LAMBDA_SUBNETS:+--subnet-ids ${LAMBDA_SUBNETS}} && yarn parse-id", | ||
"deploy": "yarn compile && claudia update --no-optional-dependencies ${LAMBDA_TIMEOUT:+--timeout ${LAMBDA_TIMEOUT}} ${LAMBDA_MEMORY:+--memory ${LAMBDA_MEMORY}} ${LAMBDA_SECURITY_GROUPS:+--security-group-ids ${LAMBDA_SECURITY_GROUPS}} ${LAMBDA_SUBNETS:+--subnet-ids ${LAMBDA_SUBNETS}} ${PFB_TILEGARDEN_CACHE_BUCKET:+--set-env PFB_TILEGARDEN_CACHE_BUCKET=${PFB_TILEGARDEN_CACHE_BUCKET}}", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Following #673, Tilegarden reads the cache bucket name from |
||
"deploy-new": "yarn compile && claudia create --no-optional-dependencies --api-module dist/api --name ${PROJECT_NAME} --region ${LAMBDA_REGION} ${LAMBDA_ROLE:+--role ${LAMBDA_ROLE}} ${LAMBDA_TIMEOUT:+--timeout ${LAMBDA_TIMEOUT}} ${LAMBDA_MEMORY:+--memory ${LAMBDA_MEMORY}} ${LAMBDA_SECURITY_GROUPS:+--security-group-ids ${LAMBDA_SECURITY_GROUPS}} ${LAMBDA_SUBNETS:+--subnet-ids ${LAMBDA_SUBNETS}} ${PFB_TILEGARDEN_CACHE_BUCKET:+--set-env PFB_TILEGARDEN_CACHE_BUCKET=${PFB_TILEGARDEN_CACHE_BUCKET}} && yarn parse-id", | ||
"destroy": "claudia destroy", | ||
"dev": "nodemon -e js,mss,json,mml,mss --ignore dist/ --ignore '*.temp.mml' --exec yarn local", | ||
"lint": "eslint src", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,6 +77,10 @@ const writeToS3 = (tile, req) => { | |
const { z, x, y, job_id, config } = req.pathParameters | ||
key = `tile/${job_id}/${config}/${z}/${x}/${y}` | ||
/* eslint-enable camelcase */ | ||
} else if (key.startsWith('/')) { | ||
// API Gateway request.path object starts with a leading slash, | ||
// which would cause the uploaded object to have the wrong prefix. | ||
key = key.slice(1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While debugging, I noticed that cache tiles were getting written to the S3 bucket in an empty root directory (showing up as a whitespace character for the directory name). I'm pretty sure this is due to another difference between the API Gateway request object representations in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch and thanks for fixing it up. |
||
} | ||
|
||
const upload = new aws.S3().putObject({ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we're routing
/latest
requests directly to the cache, we no longer need to set up this path in the origin config.