Skip to content

Commit

Permalink
Configure GCLB in terraform (#2180)
Browse files Browse the repository at this point in the history
Because importing existing resources is awkward (and will end up
deleting/recreating most things if our names don't line up), I've
decided to put all the Load Balancer / Certificate stuff into terraform
now. I've tried to match what was set up manually on staging as closely
as possible. I also added an IPv6 address, since our App Engine
currently also has IPv6.

The google-managed certificate stuff is now set up in terraform, but
configuring the DNS `CNAME`/`A`/`AAAA` records still needs to be done
manually. I've added an output to the terraform to display all the
records that need to be created.

The existing Load Balancer and Certificate stuff needs to be deleted
from staging before merging this, and the DNS records need to be updated
after.
  • Loading branch information
michaelkedar committed May 13, 2024
1 parent d9747d4 commit 995765d
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 5 deletions.
20 changes: 20 additions & 0 deletions deployment/terraform/environments/oss-vdb-test/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions deployment/terraform/environments/oss-vdb-test/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ module "osv_test" {
affected_commits_backups_bucket = "osv-test-affected-commits"
affected_commits_backups_bucket_retention_days = 2

api_url = "api.test.osv.dev"
esp_version = "2.47.0"
website_domain = "test.osv.dev"
api_url = "api.test.osv.dev"
esp_version = "2.47.0"
}

output "website_dns_records" {
description = "DNS records that need to be created for the osv.dev website"
value = module.osv_test.website_dns_records
}


Expand Down
20 changes: 20 additions & 0 deletions deployment/terraform/environments/oss-vdb/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions deployment/terraform/environments/oss-vdb/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@ module "osv" {
affected_commits_backups_bucket = "osv-affected-commits"
affected_commits_backups_bucket_retention_days = 3

api_url = "api.osv.dev"
esp_version = "2.47.0"
website_domain = "osv.dev"
api_url = "api.osv.dev"
esp_version = "2.47.0"
}

output "website_dns_records" {
description = "DNS records that need to be created for the osv.dev website"
value = module.osv.website_dns_records
}

terraform {
backend "gcs" {
Expand Down
5 changes: 5 additions & 0 deletions deployment/terraform/modules/osv/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,8 @@ variable "esp_version" {
type = string
description = "ESP version to use for OSV API frontend image."
}

variable "website_domain" {
type = string
description = "Domain to serve the OSV website on. Domain ownership and DNS settings must be manually configured."
}
182 changes: 181 additions & 1 deletion deployment/terraform/modules/osv/website.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Website Cloud Run service
resource "google_cloud_run_v2_service" "website" {
project = var.project_id
name = "osv-website"
Expand Down Expand Up @@ -32,4 +33,183 @@ resource "google_cloud_run_service_iam_binding" "website" {
]
}

# TODO: Set up Google Cloud Load Balancing + Network Endpoint Group (NEG)
# SSL Certificates
resource "google_certificate_manager_dns_authorization" "website" {
project = var.project_id
name = "website-dnsauth"
description = "The dns auth for the osv.dev website"
domain = var.website_domain
}

resource "google_certificate_manager_certificate" "website" {
project = var.project_id
name = "website-cert"
description = "The osv.dev website cert"
managed {
domains = [var.website_domain, "*.${var.website_domain}"]
dns_authorizations = [
google_certificate_manager_dns_authorization.website.id
]
}
lifecycle {
replace_triggered_by = [google_certificate_manager_dns_authorization.website.id]
}
}

resource "google_certificate_manager_certificate_map" "website" {
project = var.project_id
name = "website-certmap"
description = "osv.dev website certificate map"
}

resource "google_certificate_manager_certificate_map_entry" "website" {
project = var.project_id
name = "website-certmap-entry"
description = "osv.dev website certificate map entry"
map = google_certificate_manager_certificate_map.website.name
certificates = [google_certificate_manager_certificate.website.id]
hostname = var.website_domain

lifecycle {
replace_triggered_by = [google_certificate_manager_certificate_map.website.id, google_certificate_manager_certificate.website.id]
}
}

# Load Balancer
module "gclb" {
source = "terraform-google-modules/lb-http/google//modules/serverless_negs"
version = "~> 10.0"

name = "website"
project = var.project_id

enable_ipv6 = true
create_ipv6_address = true
ssl = true
certificate_map = google_certificate_manager_certificate_map.website.id

load_balancing_scheme = "EXTERNAL_MANAGED"

create_url_map = false
url_map = google_compute_url_map.website.id

backends = {
appengine = {
groups = [
{
group = google_compute_region_network_endpoint_group.appengine_neg.id
}
]
protocol = "HTTPS"
enable_cdn = true
cdn_policy = {
cache_key_policy = {
include_host = true
include_protocol = true
include_query_string = true
}
signed_url_cache_max_age_sec = 0
}

iap_config = {
enable = false
}
log_config = {
enable = false
}
}

cloudrun = {
groups = [
{
group = google_compute_region_network_endpoint_group.website_neg.id
}
]
protocol = "HTTPS"
enable_cdn = true
cdn_policy = {
cache_key_policy = {
include_host = true
include_protocol = true
include_query_string = true
}
signed_url_cache_max_age_sec = 0
}
connection_draining_timeout_sec = 1

iap_config = {
enable = false
}
log_config = {
enable = false
}
}
}
}

resource "google_compute_region_network_endpoint_group" "website_neg" {
project = var.project_id
name = "website-neg"
network_endpoint_type = "SERVERLESS"
region = google_cloud_run_v2_service.website.location
cloud_run {
service = google_cloud_run_v2_service.website.name
}
}

resource "google_compute_region_network_endpoint_group" "appengine_neg" {
project = var.project_id
name = "appengine-neg"
network_endpoint_type = "SERVERLESS"
region = google_app_engine_application.app.location_id
app_engine {}
}

resource "google_compute_url_map" "website" {
project = var.project_id
name = "website-url-map"
default_service = module.gclb.backend_services.appengine.id

host_rule {
hosts = ["*"]
path_matcher = "allpaths"
}

path_matcher {
name = "allpaths"
default_service = module.gclb.backend_services.appengine.id
route_rules {
priority = 1
match_rules {
prefix_match = "/"
}
route_action {
# TODO(michaelkedar): adjust weights, then remove appengine fully migrated
weighted_backend_services {
backend_service = module.gclb.backend_services.appengine.id
weight = 100
}
weighted_backend_services {
backend_service = module.gclb.backend_services.cloudrun.id
weight = 0
}
}
}
}
}

# Output all the DNS records required for the website in one place.
output "website_dns_records" {
description = "DNS records that need to be created for the osv.dev website"
value = concat([
{
data = module.gclb.external_ip
name = "${var.website_domain}."
type = "A"
},
{
data = module.gclb.external_ipv6_address
name = "${var.website_domain}."
type = "AAAA"
}], google_certificate_manager_dns_authorization.website.dns_resource_record)
}

0 comments on commit 995765d

Please sign in to comment.