Use Fabric modules when possibile

This commit is contained in:
Wiktor Niesiobędzki 2024-02-14 19:54:32 +00:00 committed by Wiktor Niesiobędzki
parent d158aecba1
commit 19be54a72f
7 changed files with 245 additions and 315 deletions

View File

@ -74,7 +74,7 @@ Before we deploy the architecture, you will need the following information:
4. Copy the following command into a console and replace __[consumer-project-id]__ and __[producer-a-project-id]__ and __[producer-b-project-id]__ with your projects IDs. Then run the following command to run the terraform script and create all relevant resources for this architecture: 4. Copy the following command into a console and replace __[consumer-project-id]__ and __[producer-a-project-id]__ and __[producer-b-project-id]__ with your projects IDs. Then run the following command to run the terraform script and create all relevant resources for this architecture:
terraform apply -var consumer_project_id=[consumer-project-id] -var producer_a_project_id=[producer-a-project-id] -var producer_b_project_id=[producer-b-project-id] terraform apply -var consumer_project_id=[consumer-project-id] -var producer_a_project_id=[producer-a-project-id] -var producer_b_project_id=[producer-b-project-id] -var region=[gcp-region]
The resource creation will take a few minutes… but when its complete, you should see an output stating the command completed successfully with a list of the created resources. The resource creation will take a few minutes… but when its complete, you should see an output stating the command completed successfully with a list of the created resources.
@ -85,13 +85,13 @@ __Congratulations__! You have successfully deployed an HTTP Load Balancer with C
You can simply invoke the service by calling You can simply invoke the service by calling
Check the default path (producer A): Check the default path (producer A):
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$LB_IP/anything curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$(terraform output -raw lb_ip)/uuid
Specifically call the producer A path: Specifically call the producer A path:
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$LB_IP/anything/a/* curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$(terraform output -raw lb_ip)/a/uuid
Specifically call the producer B path: Specifically call the producer B path:
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$LB_IP/anything/b/* curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$(terraform output -raw lb_ip)/b/uuid
## Cleaning up your environment ## Cleaning up your environment
@ -106,12 +106,11 @@ The above command will delete the associated resources so there will be no billa
| name | description | type | required | default | | name | description | type | required | default |
|---|---|:---:|:---:|:---:| |---|---|:---:|:---:|:---:|
| [consumer_project_id](variables.tf#L17) | The consumer project, in which the GCLB and Cloud Armor should be created. | <code>string</code> | ✓ | | | [consumer_project_id](variables.tf#L17) | The consumer project, in which the GCLB and Cloud Armor should be created. | <code>string</code> | ✓ | |
| [prefix](variables.tf#L22) | Prefix used for resource names. | <code>string</code> | ✓ | | | [producer_a_project_id](variables.tf#L28) | The producer A project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | <code>string</code> | ✓ | |
| [producer_a_project_id](variables.tf#L31) | The producer A project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | <code>string</code> | ✓ | | | [producer_b_project_id](variables.tf#L33) | The producer B project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | <code>string</code> | ✓ | |
| [producer_b_project_id](variables.tf#L36) | The producer B project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | <code>string</code> | ✓ | | | [region](variables.tf#L47) | The GCP region in which the resources should be deployed. | <code>string</code> | ✓ | |
| [project_create](variables.tf#L41) | Create project instead of using an existing one. | <code>bool</code> | | <code>false</code> | | [prefix](variables.tf#L22) | Prefix used for resource names. | <code>string</code> | | <code>&#34;&#34;</code> |
| [region](variables.tf#L47) | The GCP region in which the resources should be deployed. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> | | [project_create_config](variables.tf#L38) | Create project instead of using an existing one. | <code title="object&#40;&#123;&#10; billing_account &#61; string&#10; parent &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [zone](variables.tf#L53) | The GCP zone for the VM. | <code>string</code> | | <code>&#34;europe-west1-b&#34;</code> |
## Outputs ## Outputs
@ -123,12 +122,15 @@ The above command will delete the associated resources so there will be no billa
```hcl ```hcl
module "psc-glb-and-armor-test" { module "psc-glb-and-armor-test" {
source = "./fabric/blueprints/networking/psc-glb-and-armor" source = "./fabric/blueprints/networking/psc-glb-and-armor"
prefix = "test" prefix = "test"
project_create = true project_create_config = {
billing_account = var.billing_account_id
}
consumer_project_id = "project-1" consumer_project_id = "project-1"
producer_a_project_id = "project-2" producer_a_project_id = "project-2"
producer_b_project_id = "project-3" producer_b_project_id = "project-3"
region = "europe-west2"
} }
# tftest modules=6 resources=57 # tftest modules=14 resources=57
``` ```

View File

@ -1,5 +1,5 @@
/** /**
* Copyright 2023 Google LLC * Copyright 2024 Google LLC
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,95 +14,131 @@
* limitations under the License. * limitations under the License.
*/ */
module "consumer_project" { module "consumer-project" {
source = "../../../modules/project" source = "../../../modules/project"
name = var.consumer_project_id name = var.consumer_project_id
project_create = var.project_create project_create = var.project_create_config != null
billing_account = try(var.project_create_config.billing_account)
parent = try(var.project_create_config.parent)
prefix = var.prefix
services = [ services = [
"iam.googleapis.com", "iam.googleapis.com",
"compute.googleapis.com", "compute.googleapis.com",
] ]
} }
module "producer_a_project" { module "producer-a" {
source = "./modules/producer" source = "./modules/producer"
producer_project_id = var.producer_a_project_id consumer_project_id = module.consumer-project.project_id
project_create = var.project_create prefix = var.prefix
producer_project_id = var.producer_a_project_id
project_create_config = var.project_create_config
} }
module "producer_b_project" { module "producer-b" {
source = "./modules/producer" source = "./modules/producer"
producer_project_id = var.producer_b_project_id consumer_project_id = module.consumer-project.project_id
project_create = var.project_create prefix = var.prefix
producer_project_id = var.producer_b_project_id
project_create_config = var.project_create_config
} }
resource "google_compute_region_network_endpoint_group" "psc_neg_a" { module "consumer-vpc" {
name = "psc-neg-a" source = "../../../modules/net-vpc"
region = var.region
project = module.consumer_project.project_id
network_endpoint_type = "PRIVATE_SERVICE_CONNECT"
psc_target_service = module.producer_a_project.psc_ilb_service_attachment.self_link
network = "default" name = "consumer"
subnetwork = "default" project_id = module.consumer-project.project_id
subnets = [
{
ip_cidr_range = "10.0.0.0/24"
name = "consumer"
region = var.region
},
]
} }
resource "google_compute_region_network_endpoint_group" "psc_neg_b" { module "glb" {
name = "psc-neg-b" source = "./../../../modules/net-lb-app-ext"
region = var.region name = "glb"
project = module.consumer_project.project_id project_id = module.consumer-project.project_id
network_endpoint_type = "PRIVATE_SERVICE_CONNECT" use_classic_version = false
psc_target_service = module.producer_b_project.psc_ilb_service_attachment.self_link backend_service_configs = {
default = {
network = "default" backends = [
subnetwork = "default" { backend = "neg-a" }
} ]
health_checks = []
resource "google_compute_global_forwarding_rule" "default" { protocol = "HTTPS"
project = module.consumer_project.project_id security_policy = google_compute_security_policy.cloud-armor-policy.name
name = "global-rule"
load_balancing_scheme = "EXTERNAL_MANAGED"
target = google_compute_target_http_proxy.default.id
port_range = "80"
}
resource "google_compute_target_http_proxy" "default" {
project = module.consumer_project.project_id
name = "target-proxy"
description = "a description"
url_map = google_compute_url_map.default.id
}
resource "google_compute_url_map" "default" {
project = module.consumer_project.project_id
name = "url-map-target-proxy"
description = "A simple URL Map, routing all traffic to the PSC NEG"
default_service = google_compute_backend_service.backend-a.id
host_rule {
hosts = ["*"]
path_matcher = "allpaths"
}
path_matcher {
name = "allpaths"
default_service = google_compute_backend_service.backend-a.id
path_rule {
paths = ["/anything/b/*"]
service = google_compute_backend_service.backend-b.id
} }
other = {
path_rule { backends = [
paths = ["/anything/a/*"] { backend = "neg-b" }
service = google_compute_backend_service.backend-a.id ]
health_checks = []
protocol = "HTTPS"
security_policy = google_compute_security_policy.cloud-armor-policy.name
}
}
# with a single serverless NEG the implied default health check is not needed
health_check_configs = {}
neg_configs = {
neg-a = {
psc = {
region = var.region
target_service = module.producer-a.exposed_service_psc_attachment.self_link
network = module.consumer-vpc.id
subnetwork = module.consumer-vpc.subnet_ids["${var.region}/consumer"]
}
}
neg-b = {
psc = {
region = var.region
target_service = module.producer-b.exposed_service_psc_attachment.self_link
network = module.consumer-vpc.id
subnetwork = module.consumer-vpc.subnet_ids["${var.region}/consumer"]
}
}
}
urlmap_config = {
default_service = "default"
host_rules = [{
hosts = ["*"]
path_matcher = "pathmap"
}]
path_matchers = {
pathmap = {
default_service = "default"
path_rules = [
{
paths = ["/b/*"]
service = "other"
route_action = {
url_rewrite = {
path_prefix = "/" # rewrite "/b/*" to "/*"
}
}
},
{
paths = ["/a/*"]
service = "default"
route_action = {
url_rewrite = {
path_prefix = "/" # rewrite "/b/*" to "/*"
}
}
},
]
}
} }
} }
} }
resource "google_compute_security_policy" "policy" {
resource "google_compute_security_policy" "cloud-armor-policy" {
provider = google-beta provider = google-beta
project = module.consumer_project.project_id project = module.consumer-project.project_id
name = "ddos-protection" name = "ddos-protection"
adaptive_protection_config { adaptive_protection_config {
layer_7_ddos_defense_config { layer_7_ddos_defense_config {
@ -110,29 +146,3 @@ resource "google_compute_security_policy" "policy" {
} }
} }
} }
resource "google_compute_backend_service" "backend-a" {
provider = google-beta
project = module.consumer_project.project_id
name = "backend-a"
load_balancing_scheme = "EXTERNAL_MANAGED"
protocol = "HTTPS"
backend {
group = google_compute_region_network_endpoint_group.psc_neg_a.id
balancing_mode = "UTILIZATION"
capacity_scaler = 1.0
}
}
resource "google_compute_backend_service" "backend-b" {
provider = google-beta
project = module.consumer_project.project_id
name = "backend-b"
load_balancing_scheme = "EXTERNAL_MANAGED"
protocol = "HTTPS"
backend {
group = google_compute_region_network_endpoint_group.psc_neg_b.id
balancing_mode = "UTILIZATION"
capacity_scaler = 1.0
}
}

View File

@ -1,5 +1,5 @@
/** /**
* Copyright 2023 Google LLC * Copyright 2024 Google LLC
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,10 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
module "producer_project" { module "producer-project" {
source = "../../../../../modules/project" source = "../../../../../modules/project"
name = var.producer_project_id name = var.producer_project_id
project_create = var.project_create project_create = var.project_create_config != null
billing_account = try(var.project_create_config.billing_account)
parent = try(var.project_create_config.parent)
prefix = var.prefix
services = [ services = [
"iam.googleapis.com", "iam.googleapis.com",
"run.googleapis.com", "run.googleapis.com",
@ -25,90 +29,66 @@ module "producer_project" {
] ]
} }
resource "google_service_account" "app" { module "app" {
project = module.producer_project.project_id source = "../../../../../modules/cloud-run-v2"
account_id = "example-app"
display_name = "Example App Service Account" name = "example-app"
project_id = module.producer-project.project_id
region = var.region
containers = {
hello = {
image = "kennethreitz/httpbin:latest"
ports = {
http = { container_port = 80 }
}
}
}
ingress = "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER"
service_account_create = true
} }
resource "google_cloud_run_service" "app" { module "producer-ilb" {
name = "example-app" source = "../../../../../modules/net-lb-app-int"
location = var.region name = "example-app"
project = module.producer_project.project_id project_id = module.producer-project.project_id
region = var.region
template { backend_service_configs = {
spec { default = {
containers { backends = [{
image = "kennethreitz/httpbin:latest" group = "my-neg"
ports { }]
container_port = 80 health_checks = []
}
}
global_access = true
health_check_configs = {}
neg_configs = {
my-neg = {
cloudrun = {
region = var.region
target_service = {
name = module.app.service_name
} }
} }
service_account_name = google_service_account.app.email
} }
} }
protocol = "HTTPS"
autogenerate_revision_name = true ssl_certificates = {
traffic { create_configs = {
percent = 100 default = {
latest_revision = true # certificate and key could also be read via file() from external files
} certificate = tls_self_signed_cert.example.cert_pem
metadata { private_key = tls_private_key.example.private_key_pem
annotations = { }
"run.googleapis.com/ingress" = "internal-and-cloud-load-balancing"
} }
} }
} vpc_config = {
network = module.producer-vpc.self_link
resource "google_compute_region_network_endpoint_group" "neg" { subnetwork = module.producer-vpc.subnets["${var.region}/ilb-subnetwork"].self_link
name = "example-app-neg"
network_endpoint_type = "SERVERLESS"
region = var.region
project = module.producer_project.project_id
cloud_run {
service = google_cloud_run_service.app.name
} }
} }
resource "google_compute_forwarding_rule" "psc_ilb_target_service" {
name = "producer-forwarding-rule"
region = var.region
project = module.producer_project.project_id
depends_on = [google_compute_subnetwork.proxy_subnet]
load_balancing_scheme = "INTERNAL_MANAGED"
port_range = "443"
allow_global_access = true
target = google_compute_region_target_https_proxy.default.id
network = google_compute_network.psc_ilb_network.name
subnetwork = google_compute_subnetwork.ilb_subnetwork.name
}
resource "google_compute_region_target_https_proxy" "default" {
name = "l7-ilb-target-http-proxy"
provider = google-beta
region = var.region
project = module.producer_project.project_id
url_map = google_compute_region_url_map.default.id
ssl_certificates = [google_compute_region_ssl_certificate.default.id]
}
resource "google_compute_region_ssl_certificate" "default" {
region = var.region
project = module.producer_project.project_id
name = "my-certificate"
private_key = tls_private_key.example.private_key_pem
certificate = tls_self_signed_cert.example.cert_pem
}
resource "google_compute_region_url_map" "default" {
name = "l7-ilb-regional-url-map"
provider = google-beta
region = var.region
project = module.producer_project.project_id
default_service = google_compute_region_backend_service.producer_service_backend.id
}
resource "tls_private_key" "example" { resource "tls_private_key" "example" {
algorithm = "RSA" algorithm = "RSA"
rsa_bits = 2048 rsa_bits = 2048
@ -130,114 +110,48 @@ resource "tls_self_signed_cert" "example" {
"server_auth", "server_auth",
] ]
} }
resource "google_compute_region_backend_service" "producer_service_backend" {
name = "producer-service"
region = var.region
project = module.producer_project.project_id
load_balancing_scheme = "INTERNAL_MANAGED"
protocol = "HTTPS"
backend { module "producer-vpc" {
group = google_compute_region_network_endpoint_group.neg.id source = "../../../../../modules/net-vpc"
balancing_mode = "UTILIZATION"
capacity_scaler = 1.0 project_id = module.producer-project.project_id
} name = "psc-ilb-network"
subnets = [
{
ip_cidr_range = "10.0.0.0/24"
name = "ilb-subnetwork"
region = var.region
},
]
subnets_proxy_only = [
{
ip_cidr_range = "10.0.1.0/24"
name = "l7-ilb-proxy-subnet"
region = var.region
active = true
},
]
subnets_psc = [
{
ip_cidr_range = "10.3.0.0/16"
name = "psc-private-subnetwork"
region = var.region
}
]
} }
resource "google_compute_network" "psc_ilb_network" { resource "google_compute_service_attachment" "exposed-psc-service" {
name = "psc-ilb-network" name = "producer-app"
auto_create_subnetworks = false
project = module.producer_project.project_id
}
resource "google_compute_subnetwork" "ilb_subnetwork" {
name = "ilb-subnetwork"
region = var.region
project = module.producer_project.project_id
network = google_compute_network.psc_ilb_network.id
ip_cidr_range = "10.0.0.0/24"
role = "ACTIVE"
}
# proxy-only subnet
resource "google_compute_subnetwork" "proxy_subnet" {
name = "l7-ilb-proxy-subnet"
provider = google-beta
ip_cidr_range = "10.0.1.0/24"
region = var.region
project = module.producer_project.project_id
purpose = "REGIONAL_MANAGED_PROXY"
role = "ACTIVE"
network = google_compute_network.psc_ilb_network.id
}
resource "google_compute_subnetwork" "psc_private_subnetwork" {
name = "psc-private-subnetwork"
region = var.region
project = module.producer_project.project_id
network = google_compute_network.psc_ilb_network.id
ip_cidr_range = "10.3.0.0/16"
purpose = "PRIVATE"
role = "ACTIVE"
}
resource "google_compute_subnetwork" "psc_ilb_nat" {
name = "psc-ilb-nat"
region = var.region
project = module.producer_project.project_id
network = google_compute_network.psc_ilb_network.id
purpose = "PRIVATE_SERVICE_CONNECT"
ip_cidr_range = "10.1.0.0/16"
}
resource "google_compute_subnetwork" "vms" {
name = "vms"
region = var.region
project = module.producer_project.project_id
network = google_compute_network.psc_ilb_network.id
ip_cidr_range = "10.4.0.0/16"
}
resource "google_compute_service_attachment" "psc_ilb_service_attachment" {
name = "my-psc-ilb"
region = var.region region = var.region
project = module.producer_project.project_id project = module.producer-project.project_id
description = "A service attachment configured with Terraform" description = "A service attachment configured with Terraform"
enable_proxy_protocol = false enable_proxy_protocol = false
connection_preference = "ACCEPT_AUTOMATIC" connection_preference = "ACCEPT_MANUAL"
nat_subnets = [google_compute_subnetwork.psc_ilb_nat.id] nat_subnets = [module.producer-vpc.subnets_psc["${var.region}/psc-private-subnetwork"].id]
target_service = google_compute_forwarding_rule.psc_ilb_target_service.id target_service = module.producer-ilb.id
consumer_accept_lists {
connection_limit = 10
project_id_or_num = var.consumer_project_id
}
} }
resource "google_service_account" "noop" {
project = module.producer_project.project_id
account_id = "noop-sa"
display_name = "Service Account for NOOP VM"
}
resource "google_compute_instance" "noop-vm" {
project = module.producer_project.project_id
name = "noop-ilb-vm"
machine_type = "e2-medium"
zone = var.zone
boot_disk {
initialize_params {
image = "debian-cloud/debian-11"
}
}
network_interface {
network = google_compute_network.psc_ilb_network.id
subnetwork = google_compute_subnetwork.vms.id
}
service_account {
email = google_service_account.noop.email
scopes = []
}
}

View File

@ -13,6 +13,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
output "psc_ilb_service_attachment" { output "exposed_service_psc_attachment" {
value = google_compute_service_attachment.psc_ilb_service_attachment value = google_compute_service_attachment.exposed-psc-service
} }

View File

@ -14,15 +14,32 @@
* limitations under the License. * limitations under the License.
*/ */
variable "consumer_project_id" {
description = "The producer project, in which the LB, PSC Service Attachment and Cloud Run service should be created."
type = string
}
variable "prefix" {
description = "Prefix used for resource names."
type = string
validation {
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
}
variable "producer_project_id" { variable "producer_project_id" {
description = "The producer project, in which the LB, PSC Service Attachment and Cloud Run service should be created." description = "The producer project, in which the LB, PSC Service Attachment and Cloud Run service should be created."
type = string type = string
} }
variable "project_create" { variable "project_create_config" {
description = "Create project instead of using an existing one." description = "Create project instead of using an existing one."
type = bool type = object({
default = false billing_account = string
parent = optional(string)
})
default = null
} }
variable "region" { variable "region" {
@ -30,9 +47,3 @@ variable "region" {
type = string type = string
default = "europe-west1" default = "europe-west1"
} }
variable "zone" {
description = "The GCP zone for the VM."
type = string
default = "europe-west1-b"
}

View File

@ -1,5 +1,5 @@
/** /**
* Copyright 2023 Google LLC * Copyright 2024 Google LLC
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,5 +16,5 @@
output "lb_ip" { output "lb_ip" {
description = "Load balancer IP address." description = "Load balancer IP address."
value = google_compute_global_forwarding_rule.default.ip_address value = module.glb.address
} }

View File

@ -1,5 +1,5 @@
/** /**
* Copyright 2023 Google LLC * Copyright 2024 Google LLC
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,10 +22,7 @@ variable "consumer_project_id" {
variable "prefix" { variable "prefix" {
description = "Prefix used for resource names." description = "Prefix used for resource names."
type = string type = string
validation { default = ""
condition = var.prefix != ""
error_message = "Prefix cannot be empty."
}
} }
variable "producer_a_project_id" { variable "producer_a_project_id" {
@ -38,20 +35,16 @@ variable "producer_b_project_id" {
type = string type = string
} }
variable "project_create" { variable "project_create_config" {
description = "Create project instead of using an existing one." description = "Create project instead of using an existing one."
type = bool type = object({
default = false billing_account = string
parent = optional(string)
})
default = null
} }
variable "region" { variable "region" {
description = "The GCP region in which the resources should be deployed." description = "The GCP region in which the resources should be deployed."
type = string type = string
default = "europe-west1"
}
variable "zone" {
description = "The GCP zone for the VM."
type = string
default = "europe-west1-b"
} }