Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,21 @@ steps:
- verify internal-lb-http
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestInternalLbCloudRun --stage teardown --verbose']
- id: apply internal-lb-http gce-mig
waitFor:
- create
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestInternalLbGCEMIG --stage apply --verbose']
- id: verify internal-lb-http gce-mig
waitFor:
- apply internal-lb-http gce-mig
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'sleep 360 && cft test run TestInternalLbGCEMIG --stage verify --verbose']
- id: teardown internal-lb-http gce-mig
waitFor:
- verify internal-lb-http gce-mig
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run TestInternalLbGCEMIG --stage teardown --verbose']
tags:
- 'ci'
- 'integration'
Expand Down
8 changes: 7 additions & 1 deletion examples/internal-lb-cloud-run/readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# HTTP Internal Regional Load Balancer Example
# HTTP Internal Cross-Regional Load Balancer Example

This example creates a simple application with below components.

Expand All @@ -17,4 +17,10 @@ The forwarding rules and its dependecies are created as part of `frontend` modul
|------|-------------|------|---------|:--------:|
| project\_id | n/a | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| external\_cloudrun\_uris | The uris of the publicaly accesible cloud-run services |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
255 changes: 255 additions & 0 deletions examples/internal-lb-gce-mig/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

provider "google" {
project = var.project_id
}

provider "google-beta" {
project = var.project_id
}

module "internal-lb-network" {
source = "terraform-google-modules/network/google//modules/vpc"
version = "~> 10.0.0"
project_id = var.project_id
network_name = "int-lb-mig-network"
auto_create_subnetworks = false
}

module "internal-lb-subnet" {
source = "terraform-google-modules/network/google//modules/subnets"
version = "~> 10.0.0"

subnets = [
{
subnet_name = "int-lb-mig-subnet-a"
subnet_ip = "10.1.2.0/24"
subnet_region = "us-east1"
},
{
subnet_name = "int-lb-mig-proxy-only-subnet-a"
subnet_ip = "10.129.0.0/23"
subnet_region = "us-east1"
purpose = "GLOBAL_MANAGED_PROXY"
role = "ACTIVE"
},
{
subnet_name = "int-lb-mig-subnet-b"
subnet_ip = "10.1.3.0/24"
subnet_region = "us-central1"
},
{
subnet_name = "int-lb-mig-proxy-only-subnet-b",
subnet_ip = "10.130.0.0/23"
subnet_region = "us-central1"
purpose = "GLOBAL_MANAGED_PROXY"
role = "ACTIVE"
}
]

network_name = module.internal-lb-network.network_name
project_id = var.project_id
depends_on = [module.internal-lb-network]
}

module "instance-template-region-a" {
source = "terraform-google-modules/vm/google//modules/instance_template"
version = "~> 13.0"

project_id = var.project_id
region = "us-east1"
source_image_project = "debian-cloud"
source_image = "debian-12"
network = module.internal-lb-network.network_name
subnetwork = module.internal-lb-subnet.subnets["us-east1/int-lb-mig-subnet-a"].name
access_config = [{ network_tier : "PREMIUM" }]
name_prefix = "instance-template-region-a"
startup_script = <<EOF
#! /bin/bash
sudo apt-get update
sudo apt-get install apache2 -y
sudo a2ensite default-ssl
sudo a2enmod ssl
vm_hostname="$(curl -H "Metadata-Flavor:Google" \
http://169.254.169.254/computeMetadata/v1/instance/name)"
sudo echo "Page served from: $vm_hostname" | \
tee /var/www/html/index.html
sudo systemctl restart apache2
EOF
tags = [
"load-balanced-backend"
]
}

module "instance-template-region-b" {
source = "terraform-google-modules/vm/google//modules/instance_template"
version = "~> 13.0"

project_id = var.project_id
region = "us-central1"
source_image_project = "debian-cloud"
source_image = "debian-12"
network = module.internal-lb-network.network_name
subnetwork = module.internal-lb-subnet.subnets["us-central1/int-lb-mig-subnet-b"].name
access_config = [{ network_tier : "PREMIUM" }]
name_prefix = "instance-template-region-b"
startup_script = <<EOF
#! /bin/bash
sudo apt-get update
sudo apt-get install apache2 -y
sudo a2ensite default-ssl
sudo a2enmod ssl
vm_hostname="$(curl -H "Metadata-Flavor:Google" \
http://169.254.169.254/computeMetadata/v1/instance/name)"
sudo echo "Page served from: $vm_hostname" | \
tee /var/www/html/index.html
sudo systemctl restart apache2
EOF
tags = [
"load-balanced-backend"
]
}

module "mig-region-a" {
source = "terraform-google-modules/vm/google//modules/mig"
version = "~> 13.0"
instance_template = module.instance-template-region-a.self_link
project_id = var.project_id
region = "us-east1"
hostname = "mig-group-region-a"
target_size = 2
named_ports = [{
name = "http",
port = 80
}]
depends_on = [module.instance-template-region-a]
}

module "mig-region-b" {
source = "terraform-google-modules/vm/google//modules/mig"
version = "~> 13.0"
instance_template = module.instance-template-region-b.self_link
project_id = var.project_id
region = "us-central1"
hostname = "mig-group-region-b"
target_size = 2
named_ports = [{
name = "http",
port = 80
}]
depends_on = [module.instance-template-region-b]
}

module "internal-lb-http-backend" {
source = "terraform-google-modules/lb-http/google//modules/backend"
version = "~> 0.4.0"

project_id = var.project_id
name = "int-lb-mig-http-backend"
enable_cdn = false
load_balancing_scheme = "INTERNAL_MANAGED"
groups = [
{
group : module.mig-region-a.instance_group,
},
{
group : module.mig-region-b.instance_group,
}
]
health_check = {
protocol : "HTTP",
port_specification = "USE_SERVING_PORT"
proxy_header = "NONE"
request_path = "/"
}
firewall_networks = [module.internal-lb-network.network_name]
firewall_source_ranges = [
"10.129.0.0/23",
"10.130.0.0/23"
]
target_tags = [
"load-balanced-backend"
]
}

module "internal-lb-http-frontend" {
source = "terraform-google-modules/lb-http/google//modules/frontend"
version = "~> 12.0"

project_id = var.project_id
name = "int-lb-mig-http-frontend"
url_map_input = module.internal-lb-http-backend.backend_service_info
network = module.internal-lb-network.network_name
load_balancing_scheme = "INTERNAL_MANAGED"
internal_forwarding_rules_config = [
{
"region" : "us-east1",
"subnetwork" : module.internal-lb-subnet.subnets["us-east1/int-lb-mig-subnet-a"].id
},
{
"region" : "us-central1",
"subnetwork" : module.internal-lb-subnet.subnets["us-central1/int-lb-mig-subnet-b"].id
}
]
}

resource "google_vpc_access_connector" "internal_lb_vpc_connector" {
provider = google-beta
project = var.project_id
name = "fe-vpc-cx-gce"
region = "us-east1"
ip_cidr_range = "10.8.0.0/28"
network = module.internal-lb-network.network_name
max_throughput = 500
min_throughput = 300
}

module "frontend-service-a" {
source = "GoogleCloudPlatform/cloud-run/google//modules/v2"
version = "~> 0.16.3"
project_id = var.project_id
location = "us-east1"
service_name = "fs-gce-a"
containers = [{ "env_vars" : { "TARGET_IP" : module.internal-lb-http-frontend.ip_address_internal_managed_http[0] }, "ports" = { "container_port" = 80, "name" = "http1" }, "container_name" = "", "container_image" = "gcr.io/design-center-container-repo/redirect-traffic:latest-2002" }]
members = ["allUsers"]
vpc_access = {
connector = google_vpc_access_connector.internal_lb_vpc_connector.id
egress = "ALL_TRAFFIC"
}
ingress = "INGRESS_TRAFFIC_ALL"
cloud_run_deletion_protection = false
enable_prometheus_sidecar = false
depends_on = [google_vpc_access_connector.internal_lb_vpc_connector]
}

module "frontend-service-b" {
source = "GoogleCloudPlatform/cloud-run/google//modules/v2"
version = "~> 0.16.3"
project_id = var.project_id
location = "us-east1"
service_name = "fs-gce-b"
containers = [{ "env_vars" : { "TARGET_IP" : module.internal-lb-http-frontend.ip_address_internal_managed_http[1] }, "ports" = { "container_port" = 80, "name" = "http1" }, "container_name" = "", "container_image" = "gcr.io/design-center-container-repo/redirect-traffic:latest-2002" }]
members = ["allUsers"]
vpc_access = {
connector = google_vpc_access_connector.internal_lb_vpc_connector.id
egress = "ALL_TRAFFIC"
}
ingress = "INGRESS_TRAFFIC_ALL"
cloud_run_deletion_protection = false
enable_prometheus_sidecar = false
}

20 changes: 20 additions & 0 deletions examples/internal-lb-gce-mig/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

output "external_cloudrun_uris" {
description = "List of URIs for the frontend Cloud Run services"
value = [module.frontend-service-a.service_uri, module.frontend-service-b.service_uri]
}
20 changes: 20 additions & 0 deletions examples/internal-lb-gce-mig/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# HTTP Cross-Regional Load Balancer Example - GCE MIG

This example creates a cross regional HTTP forwarding rule to forward traffic to GCE managed instance group. The `google_compute_region_backend_service` and its dependencies are created as part of `backend` module.
The forwarding rules and its dependecies are created as part of `frontend` modules.
The forwarding rule is INTERNAL_MANAGED and can not be accessed on open internet. This example also creates two publicly accessible cloud-run services to access the internal load balancer using the internal ip address of the forwarding rule.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| project\_id | n/a | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| external\_cloudrun\_uris | The uris of the publicaly accesible cloud-run services |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
19 changes: 19 additions & 0 deletions examples/internal-lb-gce-mig/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Copyright 2025 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

variable "project_id" {
type = string
}
2 changes: 2 additions & 0 deletions metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ spec:
location: examples/https-redirect
- name: internal-lb-cloud-run
location: examples/internal-lb-cloud-run
- name: internal-lb-gce-mig
location: examples/internal-lb-gce-mig
- name: lb-http-separate-frontend-and-backend
location: examples/lb-http-separate-frontend-and-backend
- name: mig-nat-http-lb
Expand Down
1 change: 1 addition & 0 deletions modules/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ This module creates `google_compute_backend_service` resource and its dependenci
| enable\_cdn | Enable Cloud CDN for this BackendService. | `bool` | `false` | no |
| firewall\_networks | Names of the networks to create firewall rules in | `list(string)` | <pre>[<br> "default"<br>]</pre> | no |
| firewall\_projects | Names of the projects to create firewall rules in | `list(string)` | <pre>[<br> "default"<br>]</pre> | no |
| firewall\_source\_ranges | Source ranges for the global Application Load Balancer's proxies. This list should contain the `ip_cidr_range` of each GLOBAL\_MANAGED\_PROXY subnet. | `list(string)` | <pre>[<br> "10.127.0.0/23"<br>]</pre> | no |
| groups | The list of backend instance group which serves the traffic. | <pre>list(object({<br> group = string<br> description = optional(string)<br><br> balancing_mode = optional(string)<br> capacity_scaler = optional(number)<br> max_connections = optional(number)<br> max_connections_per_instance = optional(number)<br> max_connections_per_endpoint = optional(number)<br> max_rate = optional(number)<br> max_rate_per_instance = optional(number)<br> max_rate_per_endpoint = optional(number)<br> max_utilization = optional(number)<br> }))</pre> | `[]` | no |
| health\_check | Input for creating HttpHealthCheck or HttpsHealthCheck resource for health checking this BackendService. A health check must be specified unless the backend service uses an internet or serverless NEG as a backend. | <pre>object({<br> host = optional(string, null)<br> request_path = optional(string, null)<br> request = optional(string, null)<br> response = optional(string, null)<br> port = optional(number, null)<br> port_name = optional(string, null)<br> proxy_header = optional(string, null)<br> port_specification = optional(string, null)<br> protocol = optional(string, null)<br> check_interval_sec = optional(number, 5)<br> timeout_sec = optional(number, 5)<br> healthy_threshold = optional(number, 2)<br> unhealthy_threshold = optional(number, 2)<br> logging = optional(bool, false)<br> })</pre> | `null` | no |
| host\_path\_mappings | The list of host/path for which traffic could be sent to the backend service | <pre>list(object({<br> host = string<br> path = string<br> }))</pre> | <pre>[<br> {<br> "host": "*",<br> "path": "/*"<br> }<br>]</pre> | no |
Expand Down
Loading