Skip to content

Commit 995765d

Browse files
authored
Configure GCLB in terraform (#2180)
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.
1 parent d9747d4 commit 995765d

File tree

6 files changed

+241
-5
lines changed

6 files changed

+241
-5
lines changed

deployment/terraform/environments/oss-vdb-test/.terraform.lock.hcl

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

deployment/terraform/environments/oss-vdb-test/main.tf

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ module "osv_test" {
1313
affected_commits_backups_bucket = "osv-test-affected-commits"
1414
affected_commits_backups_bucket_retention_days = 2
1515

16-
api_url = "api.test.osv.dev"
17-
esp_version = "2.47.0"
16+
website_domain = "test.osv.dev"
17+
api_url = "api.test.osv.dev"
18+
esp_version = "2.47.0"
19+
}
20+
21+
output "website_dns_records" {
22+
description = "DNS records that need to be created for the osv.dev website"
23+
value = module.osv_test.website_dns_records
1824
}
1925

2026

deployment/terraform/environments/oss-vdb/.terraform.lock.hcl

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

deployment/terraform/environments/oss-vdb/main.tf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ module "osv" {
1313
affected_commits_backups_bucket = "osv-affected-commits"
1414
affected_commits_backups_bucket_retention_days = 3
1515

16-
api_url = "api.osv.dev"
17-
esp_version = "2.47.0"
16+
website_domain = "osv.dev"
17+
api_url = "api.osv.dev"
18+
esp_version = "2.47.0"
1819
}
1920

21+
output "website_dns_records" {
22+
description = "DNS records that need to be created for the osv.dev website"
23+
value = module.osv.website_dns_records
24+
}
2025

2126
terraform {
2227
backend "gcs" {

deployment/terraform/modules/osv/variables.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,8 @@ variable "esp_version" {
5757
type = string
5858
description = "ESP version to use for OSV API frontend image."
5959
}
60+
61+
variable "website_domain" {
62+
type = string
63+
description = "Domain to serve the OSV website on. Domain ownership and DNS settings must be manually configured."
64+
}

deployment/terraform/modules/osv/website.tf

Lines changed: 181 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Website Cloud Run service
12
resource "google_cloud_run_v2_service" "website" {
23
project = var.project_id
34
name = "osv-website"
@@ -32,4 +33,183 @@ resource "google_cloud_run_service_iam_binding" "website" {
3233
]
3334
}
3435

35-
# TODO: Set up Google Cloud Load Balancing + Network Endpoint Group (NEG)
36+
# SSL Certificates
37+
resource "google_certificate_manager_dns_authorization" "website" {
38+
project = var.project_id
39+
name = "website-dnsauth"
40+
description = "The dns auth for the osv.dev website"
41+
domain = var.website_domain
42+
}
43+
44+
resource "google_certificate_manager_certificate" "website" {
45+
project = var.project_id
46+
name = "website-cert"
47+
description = "The osv.dev website cert"
48+
managed {
49+
domains = [var.website_domain, "*.${var.website_domain}"]
50+
dns_authorizations = [
51+
google_certificate_manager_dns_authorization.website.id
52+
]
53+
}
54+
lifecycle {
55+
replace_triggered_by = [google_certificate_manager_dns_authorization.website.id]
56+
}
57+
}
58+
59+
resource "google_certificate_manager_certificate_map" "website" {
60+
project = var.project_id
61+
name = "website-certmap"
62+
description = "osv.dev website certificate map"
63+
}
64+
65+
resource "google_certificate_manager_certificate_map_entry" "website" {
66+
project = var.project_id
67+
name = "website-certmap-entry"
68+
description = "osv.dev website certificate map entry"
69+
map = google_certificate_manager_certificate_map.website.name
70+
certificates = [google_certificate_manager_certificate.website.id]
71+
hostname = var.website_domain
72+
73+
lifecycle {
74+
replace_triggered_by = [google_certificate_manager_certificate_map.website.id, google_certificate_manager_certificate.website.id]
75+
}
76+
}
77+
78+
# Load Balancer
79+
module "gclb" {
80+
source = "terraform-google-modules/lb-http/google//modules/serverless_negs"
81+
version = "~> 10.0"
82+
83+
name = "website"
84+
project = var.project_id
85+
86+
enable_ipv6 = true
87+
create_ipv6_address = true
88+
ssl = true
89+
certificate_map = google_certificate_manager_certificate_map.website.id
90+
91+
load_balancing_scheme = "EXTERNAL_MANAGED"
92+
93+
create_url_map = false
94+
url_map = google_compute_url_map.website.id
95+
96+
backends = {
97+
appengine = {
98+
groups = [
99+
{
100+
group = google_compute_region_network_endpoint_group.appengine_neg.id
101+
}
102+
]
103+
protocol = "HTTPS"
104+
enable_cdn = true
105+
cdn_policy = {
106+
cache_key_policy = {
107+
include_host = true
108+
include_protocol = true
109+
include_query_string = true
110+
}
111+
signed_url_cache_max_age_sec = 0
112+
}
113+
114+
iap_config = {
115+
enable = false
116+
}
117+
log_config = {
118+
enable = false
119+
}
120+
}
121+
122+
cloudrun = {
123+
groups = [
124+
{
125+
group = google_compute_region_network_endpoint_group.website_neg.id
126+
}
127+
]
128+
protocol = "HTTPS"
129+
enable_cdn = true
130+
cdn_policy = {
131+
cache_key_policy = {
132+
include_host = true
133+
include_protocol = true
134+
include_query_string = true
135+
}
136+
signed_url_cache_max_age_sec = 0
137+
}
138+
connection_draining_timeout_sec = 1
139+
140+
iap_config = {
141+
enable = false
142+
}
143+
log_config = {
144+
enable = false
145+
}
146+
}
147+
}
148+
}
149+
150+
resource "google_compute_region_network_endpoint_group" "website_neg" {
151+
project = var.project_id
152+
name = "website-neg"
153+
network_endpoint_type = "SERVERLESS"
154+
region = google_cloud_run_v2_service.website.location
155+
cloud_run {
156+
service = google_cloud_run_v2_service.website.name
157+
}
158+
}
159+
160+
resource "google_compute_region_network_endpoint_group" "appengine_neg" {
161+
project = var.project_id
162+
name = "appengine-neg"
163+
network_endpoint_type = "SERVERLESS"
164+
region = google_app_engine_application.app.location_id
165+
app_engine {}
166+
}
167+
168+
resource "google_compute_url_map" "website" {
169+
project = var.project_id
170+
name = "website-url-map"
171+
default_service = module.gclb.backend_services.appengine.id
172+
173+
host_rule {
174+
hosts = ["*"]
175+
path_matcher = "allpaths"
176+
}
177+
178+
path_matcher {
179+
name = "allpaths"
180+
default_service = module.gclb.backend_services.appengine.id
181+
route_rules {
182+
priority = 1
183+
match_rules {
184+
prefix_match = "/"
185+
}
186+
route_action {
187+
# TODO(michaelkedar): adjust weights, then remove appengine fully migrated
188+
weighted_backend_services {
189+
backend_service = module.gclb.backend_services.appengine.id
190+
weight = 100
191+
}
192+
weighted_backend_services {
193+
backend_service = module.gclb.backend_services.cloudrun.id
194+
weight = 0
195+
}
196+
}
197+
}
198+
}
199+
}
200+
201+
# Output all the DNS records required for the website in one place.
202+
output "website_dns_records" {
203+
description = "DNS records that need to be created for the osv.dev website"
204+
value = concat([
205+
{
206+
data = module.gclb.external_ip
207+
name = "${var.website_domain}."
208+
type = "A"
209+
},
210+
{
211+
data = module.gclb.external_ipv6_address
212+
name = "${var.website_domain}."
213+
type = "AAAA"
214+
}], google_certificate_manager_dns_authorization.website.dns_resource_record)
215+
}

0 commit comments

Comments
 (0)