From 02f3c41e9a6de3d6d0f5289aa296d6905b1206d3 Mon Sep 17 00:00:00 2001 From: Agnieszka Figiel Date: Tue, 3 Oct 2023 19:37:40 +0200 Subject: [PATCH] Load balancer --- infrastructure/base/main.tf | 7 + infrastructure/base/modules/dns/main.tf | 12 ++ infrastructure/base/modules/dns/outputs.tf | 7 + infrastructure/base/modules/dns/variables.tf | 9 + infrastructure/base/modules/env/main.tf | 14 ++ .../base/modules/load-balancer/main.tf | 158 ++++++++++++++++++ .../base/modules/load-balancer/outputs.tf | 8 + .../base/modules/load-balancer/variables.tf | 40 +++++ infrastructure/base/outputs.tf | 6 +- 9 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 infrastructure/base/modules/dns/main.tf create mode 100644 infrastructure/base/modules/dns/outputs.tf create mode 100644 infrastructure/base/modules/dns/variables.tf create mode 100644 infrastructure/base/modules/load-balancer/main.tf create mode 100644 infrastructure/base/modules/load-balancer/outputs.tf create mode 100644 infrastructure/base/modules/load-balancer/variables.tf diff --git a/infrastructure/base/main.tf b/infrastructure/base/main.tf index 9d126a3b..89a7a157 100644 --- a/infrastructure/base/main.tf +++ b/infrastructure/base/main.tf @@ -19,6 +19,7 @@ module "staging" { backend_min_scale = 0 frontend_max_scale = 1 backend_max_scale = 1 + dns_zone_name = module.dns.dns_zone_name domain = var.domain subdomain = "30x30" uptime_alert_email = var.uptime_alert_email @@ -26,3 +27,9 @@ module "staging" { database_name = "strapi" database_user = "strapi" } + +module "dns" { + source = "./modules/dns" + domain = var.domain + name = "skytruth" +} diff --git a/infrastructure/base/modules/dns/main.tf b/infrastructure/base/modules/dns/main.tf new file mode 100644 index 00000000..ab5176c3 --- /dev/null +++ b/infrastructure/base/modules/dns/main.tf @@ -0,0 +1,12 @@ +resource "google_project_service" "dns_api" { + service = "dns.googleapis.com" + disable_on_destroy = false +} + +resource "google_dns_managed_zone" "dns-zone" { + name = var.name + dns_name = "${var.domain}." + description = "${var.name} DNS zone" + + depends_on = [google_project_service.dns_api] +} diff --git a/infrastructure/base/modules/dns/outputs.tf b/infrastructure/base/modules/dns/outputs.tf new file mode 100644 index 00000000..08ccb34c --- /dev/null +++ b/infrastructure/base/modules/dns/outputs.tf @@ -0,0 +1,7 @@ +output "dns_name_servers" { + value = google_dns_managed_zone.dns-zone.name_servers +} + +output "dns_zone_name" { + value = google_dns_managed_zone.dns-zone.name +} diff --git a/infrastructure/base/modules/dns/variables.tf b/infrastructure/base/modules/dns/variables.tf new file mode 100644 index 00000000..274d6343 --- /dev/null +++ b/infrastructure/base/modules/dns/variables.tf @@ -0,0 +1,9 @@ +variable "domain" { + type = string + description = "Base domain for the DNS zone" +} + +variable "name" { + type = string + description = "Name for the DNS zone" +} diff --git a/infrastructure/base/modules/env/main.tf b/infrastructure/base/modules/env/main.tf index 028d15a8..5079c0c0 100644 --- a/infrastructure/base/modules/env/main.tf +++ b/infrastructure/base/modules/env/main.tf @@ -229,3 +229,17 @@ resource "google_project_service" "iam_service" { project = var.gcp_project_id service = "iam.googleapis.com" } + +module "load_balancer" { + source = "../load-balancer" + region = var.gcp_region + project = var.gcp_project_id + name = var.project_name + backend_cloud_run_name = module.backend_cloudrun.name + frontend_cloud_run_name = module.frontend_cloudrun.name + domain = var.domain + dns_managed_zone_name = var.dns_zone_name + # redirect_domain = var.redirect_domain + # redirect_domain_dns_managed_zone_name = var.redirect_dns_zone_name + subdomain = var.subdomain +} diff --git a/infrastructure/base/modules/load-balancer/main.tf b/infrastructure/base/modules/load-balancer/main.tf new file mode 100644 index 00000000..58aa9f4a --- /dev/null +++ b/infrastructure/base/modules/load-balancer/main.tf @@ -0,0 +1,158 @@ +// IP address +resource "google_compute_global_address" "ip_address" { + name = "${var.name}-lb" + ip_version = "IPV4" + address_type = "EXTERNAL" +} + +locals { + domain = var.subdomain == "" ? var.domain : "${var.subdomain}.${var.domain}" +} + +# ------------------------------------------------------------------------------ +# Load balancer config rules +# ------------------------------------------------------------------------------ + +# HTTPS + certificate handling +resource "google_compute_global_forwarding_rule" "load-balancer-forwarding-rule-https" { + name = "${var.name}-lb-forwarding-rule-https" + target = google_compute_target_https_proxy.load-balancer-https-proxy.id + port_range = "443" + load_balancing_scheme = "EXTERNAL" + ip_address = google_compute_global_address.ip_address.address +} + +resource "google_compute_target_https_proxy" "load-balancer-https-proxy" { + name = "${var.name}-lb-https-proxy" + url_map = google_compute_url_map.load-balancer-url-map.id + ssl_certificates = [google_compute_managed_ssl_certificate.load-balancer-certificate.id] +} + +resource "google_compute_managed_ssl_certificate" "load-balancer-certificate" { + name = "${var.name}-lb-cert" + + managed { + domains = [local.domain] + } +} + +# HTTP redirection to HTTPS +resource "google_compute_url_map" "http-redirect" { + name = "${var.name}-http-redirect" + + default_url_redirect { + redirect_response_code = "MOVED_PERMANENTLY_DEFAULT" // 301 redirect + strip_query = false + https_redirect = true // this is the magic + } +} + +resource "google_compute_target_http_proxy" "http-redirect" { + name = "${var.name}-http-redirect" + url_map = google_compute_url_map.http-redirect.self_link +} + +resource "google_compute_global_forwarding_rule" "http-redirect" { + name = "${var.name}-http-redirect" + target = google_compute_target_http_proxy.http-redirect.self_link + ip_address = google_compute_global_address.ip_address.address + port_range = "80" +} + +# ------------------------------------------------------------------------------ +# Load balancer core (URL mapping) +# ------------------------------------------------------------------------------ +resource "google_compute_url_map" "load-balancer-url-map" { + name = "${var.name}-lb" + description = "Load balancer for ${var.name}" + default_service = google_compute_backend_service.frontend_service.id + + host_rule { + hosts = [local.domain] + path_matcher = "site" + } + + path_matcher { + name = "site" + default_service = google_compute_backend_service.frontend_service.id + + path_rule { + paths = ["/backend/*"] + service = google_compute_backend_service.backend_service.id + } + } + + # host_rule { + # hosts = [local.redirect_domain] + # path_matcher = "redirect" + # } + + # path_matcher { + # name = "redirect" + # default_url_redirect { + # strip_query = false + # host_redirect = local.domain + # https_redirect = true + # } + # } +} + +resource "google_compute_region_network_endpoint_group" "cloudrun_backend_neg" { + provider = google-beta + name = "${var.name}-backend-neg" + network_endpoint_type = "SERVERLESS" + region = var.region + cloud_run { + service = var.backend_cloud_run_name + } +} + +resource "google_compute_region_network_endpoint_group" "cloudrun_frontend_neg" { + provider = google-beta + name = "${var.name}-frontend-neg" + network_endpoint_type = "SERVERLESS" + region = var.region + cloud_run { + service = var.frontend_cloud_run_name + } +} + +resource "google_compute_backend_service" "backend_service" { + name = "${var.name}-backend-service" + description = "${var.name} backend service" + + backend { + group = google_compute_region_network_endpoint_group.cloudrun_backend_neg.id + } + +} + +resource "google_compute_backend_service" "frontend_service" { + name = "${var.name}-frontend-service" + description = "${var.name} frontend service" + + backend { + group = google_compute_region_network_endpoint_group.cloudrun_frontend_neg.id + } + +} + +# DNS record +resource "google_dns_record_set" "frontend-dns-record-set" { + project = var.project + name = "${local.domain}." + type = "A" + ttl = 3600 + managed_zone = var.dns_managed_zone_name + rrdatas = [google_compute_global_address.ip_address.address] +} + +# DNS record +# resource "google_dns_record_set" "redirect-dns-record-set" { +# project = var.project +# name = "${local.redirect_domain}." +# type = "A" +# ttl = 3600 +# managed_zone = var.redirect_domain_dns_managed_zone_name +# rrdatas = [google_compute_global_address.ip_address.address] +# } diff --git a/infrastructure/base/modules/load-balancer/outputs.tf b/infrastructure/base/modules/load-balancer/outputs.tf new file mode 100644 index 00000000..f40665a0 --- /dev/null +++ b/infrastructure/base/modules/load-balancer/outputs.tf @@ -0,0 +1,8 @@ +output "load-balancer-ip" { + description = "The public IP address of the load balancer" + value = google_compute_global_address.ip_address.address +} + +output "load-balancer-names" { + value = google_compute_managed_ssl_certificate.load-balancer-certificate.managed.*.domains +} diff --git a/infrastructure/base/modules/load-balancer/variables.tf b/infrastructure/base/modules/load-balancer/variables.tf new file mode 100644 index 00000000..ba6214ef --- /dev/null +++ b/infrastructure/base/modules/load-balancer/variables.tf @@ -0,0 +1,40 @@ +variable "project" { + type = string + description = "The GCP project to deploy service into" +} + +variable "region" { + type = string + description = "The GCP region to deploy service into" +} + +variable "name" { + type = string + description = "Name to use on resources" +} + +variable "dns_managed_zone_name" { + type = string + description = "Name of the DNS Zone" +} + +variable "domain" { + type = string + description = "Base domain for the DNS zone" +} + +variable "subdomain" { + type = string + default = "" + description = "If set, it will be prepended to the domain to form a subdomain." +} + +variable "frontend_cloud_run_name" { + type = string + description = "Name of the frontend Cloud Run service" +} + +variable "backend_cloud_run_name" { + type = string + description = "Name of the backend Cloud Run service" +} diff --git a/infrastructure/base/outputs.tf b/infrastructure/base/outputs.tf index bcba564d..0576af78 100644 --- a/infrastructure/base/outputs.tf +++ b/infrastructure/base/outputs.tf @@ -6,9 +6,9 @@ output "staging_api_url" { value = module.staging.api_url } -# output "dns_name_servers" { -# value = module.dns.dns_name_servers -# } +output "dns_name_servers" { + value = module.dns.dns_name_servers +} # output "production_site_url" { # value = module.production.site_url