Skip to content

Commit cfd456f

Browse files
authored
feat: added example for cross regional internal lb with gce mig as backend (#500)
1 parent e70f5d4 commit cfd456f

File tree

17 files changed

+436
-6
lines changed

17 files changed

+436
-6
lines changed

build/int.cloudbuild.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,21 @@ steps:
143143
- verify internal-lb-http
144144
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
145145
args: ['/bin/bash', '-c', 'cft test run TestInternalLbCloudRun --stage teardown --verbose']
146+
- id: apply internal-lb-http gce-mig
147+
waitFor:
148+
- create
149+
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
150+
args: ['/bin/bash', '-c', 'cft test run TestInternalLbGCEMIG --stage apply --verbose']
151+
- id: verify internal-lb-http gce-mig
152+
waitFor:
153+
- apply internal-lb-http gce-mig
154+
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
155+
args: ['/bin/bash', '-c', 'sleep 360 && cft test run TestInternalLbGCEMIG --stage verify --verbose']
156+
- id: teardown internal-lb-http gce-mig
157+
waitFor:
158+
- verify internal-lb-http gce-mig
159+
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
160+
args: ['/bin/bash', '-c', 'cft test run TestInternalLbGCEMIG --stage teardown --verbose']
146161
tags:
147162
- 'ci'
148163
- 'integration'

examples/internal-lb-cloud-run/readme.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# HTTP Internal Regional Load Balancer Example
1+
# HTTP Internal Cross-Regional Load Balancer Example
22

33
This example creates a simple application with below components.
44

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

20+
## Outputs
21+
22+
| Name | Description |
23+
|------|-------------|
24+
| external\_cloudrun\_uris | The uris of the publicaly accesible cloud-run services |
25+
2026
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
provider "google" {
18+
project = var.project_id
19+
}
20+
21+
provider "google-beta" {
22+
project = var.project_id
23+
}
24+
25+
module "internal-lb-network" {
26+
source = "terraform-google-modules/network/google//modules/vpc"
27+
version = "~> 10.0.0"
28+
project_id = var.project_id
29+
network_name = "int-lb-mig-network"
30+
auto_create_subnetworks = false
31+
}
32+
33+
module "internal-lb-subnet" {
34+
source = "terraform-google-modules/network/google//modules/subnets"
35+
version = "~> 10.0.0"
36+
37+
subnets = [
38+
{
39+
subnet_name = "int-lb-mig-subnet-a"
40+
subnet_ip = "10.1.2.0/24"
41+
subnet_region = "us-east1"
42+
},
43+
{
44+
subnet_name = "int-lb-mig-proxy-only-subnet-a"
45+
subnet_ip = "10.129.0.0/23"
46+
subnet_region = "us-east1"
47+
purpose = "GLOBAL_MANAGED_PROXY"
48+
role = "ACTIVE"
49+
},
50+
{
51+
subnet_name = "int-lb-mig-subnet-b"
52+
subnet_ip = "10.1.3.0/24"
53+
subnet_region = "us-central1"
54+
},
55+
{
56+
subnet_name = "int-lb-mig-proxy-only-subnet-b",
57+
subnet_ip = "10.130.0.0/23"
58+
subnet_region = "us-central1"
59+
purpose = "GLOBAL_MANAGED_PROXY"
60+
role = "ACTIVE"
61+
}
62+
]
63+
64+
network_name = module.internal-lb-network.network_name
65+
project_id = var.project_id
66+
depends_on = [module.internal-lb-network]
67+
}
68+
69+
module "instance-template-region-a" {
70+
source = "terraform-google-modules/vm/google//modules/instance_template"
71+
version = "~> 13.0"
72+
73+
project_id = var.project_id
74+
region = "us-east1"
75+
source_image_project = "debian-cloud"
76+
source_image = "debian-12"
77+
network = module.internal-lb-network.network_name
78+
subnetwork = module.internal-lb-subnet.subnets["us-east1/int-lb-mig-subnet-a"].name
79+
access_config = [{ network_tier : "PREMIUM" }]
80+
name_prefix = "instance-template-region-a"
81+
startup_script = <<EOF
82+
#! /bin/bash
83+
sudo apt-get update
84+
sudo apt-get install apache2 -y
85+
sudo a2ensite default-ssl
86+
sudo a2enmod ssl
87+
vm_hostname="$(curl -H "Metadata-Flavor:Google" \
88+
http://169.254.169.254/computeMetadata/v1/instance/name)"
89+
sudo echo "Page served from: $vm_hostname" | \
90+
tee /var/www/html/index.html
91+
sudo systemctl restart apache2
92+
EOF
93+
tags = [
94+
"load-balanced-backend"
95+
]
96+
}
97+
98+
module "instance-template-region-b" {
99+
source = "terraform-google-modules/vm/google//modules/instance_template"
100+
version = "~> 13.0"
101+
102+
project_id = var.project_id
103+
region = "us-central1"
104+
source_image_project = "debian-cloud"
105+
source_image = "debian-12"
106+
network = module.internal-lb-network.network_name
107+
subnetwork = module.internal-lb-subnet.subnets["us-central1/int-lb-mig-subnet-b"].name
108+
access_config = [{ network_tier : "PREMIUM" }]
109+
name_prefix = "instance-template-region-b"
110+
startup_script = <<EOF
111+
#! /bin/bash
112+
sudo apt-get update
113+
sudo apt-get install apache2 -y
114+
sudo a2ensite default-ssl
115+
sudo a2enmod ssl
116+
vm_hostname="$(curl -H "Metadata-Flavor:Google" \
117+
http://169.254.169.254/computeMetadata/v1/instance/name)"
118+
sudo echo "Page served from: $vm_hostname" | \
119+
tee /var/www/html/index.html
120+
sudo systemctl restart apache2
121+
EOF
122+
tags = [
123+
"load-balanced-backend"
124+
]
125+
}
126+
127+
module "mig-region-a" {
128+
source = "terraform-google-modules/vm/google//modules/mig"
129+
version = "~> 13.0"
130+
instance_template = module.instance-template-region-a.self_link
131+
project_id = var.project_id
132+
region = "us-east1"
133+
hostname = "mig-group-region-a"
134+
target_size = 2
135+
named_ports = [{
136+
name = "http",
137+
port = 80
138+
}]
139+
depends_on = [module.instance-template-region-a]
140+
}
141+
142+
module "mig-region-b" {
143+
source = "terraform-google-modules/vm/google//modules/mig"
144+
version = "~> 13.0"
145+
instance_template = module.instance-template-region-b.self_link
146+
project_id = var.project_id
147+
region = "us-central1"
148+
hostname = "mig-group-region-b"
149+
target_size = 2
150+
named_ports = [{
151+
name = "http",
152+
port = 80
153+
}]
154+
depends_on = [module.instance-template-region-b]
155+
}
156+
157+
module "internal-lb-http-backend" {
158+
source = "terraform-google-modules/lb-http/google//modules/backend"
159+
version = "~> 0.4.0"
160+
161+
project_id = var.project_id
162+
name = "int-lb-mig-http-backend"
163+
enable_cdn = false
164+
load_balancing_scheme = "INTERNAL_MANAGED"
165+
groups = [
166+
{
167+
group : module.mig-region-a.instance_group,
168+
},
169+
{
170+
group : module.mig-region-b.instance_group,
171+
}
172+
]
173+
health_check = {
174+
protocol : "HTTP",
175+
port_specification = "USE_SERVING_PORT"
176+
proxy_header = "NONE"
177+
request_path = "/"
178+
}
179+
firewall_networks = [module.internal-lb-network.network_name]
180+
firewall_source_ranges = [
181+
"10.129.0.0/23",
182+
"10.130.0.0/23"
183+
]
184+
target_tags = [
185+
"load-balanced-backend"
186+
]
187+
}
188+
189+
module "internal-lb-http-frontend" {
190+
source = "terraform-google-modules/lb-http/google//modules/frontend"
191+
version = "~> 12.0"
192+
193+
project_id = var.project_id
194+
name = "int-lb-mig-http-frontend"
195+
url_map_input = module.internal-lb-http-backend.backend_service_info
196+
network = module.internal-lb-network.network_name
197+
load_balancing_scheme = "INTERNAL_MANAGED"
198+
internal_forwarding_rules_config = [
199+
{
200+
"region" : "us-east1",
201+
"subnetwork" : module.internal-lb-subnet.subnets["us-east1/int-lb-mig-subnet-a"].id
202+
},
203+
{
204+
"region" : "us-central1",
205+
"subnetwork" : module.internal-lb-subnet.subnets["us-central1/int-lb-mig-subnet-b"].id
206+
}
207+
]
208+
}
209+
210+
resource "google_vpc_access_connector" "internal_lb_vpc_connector" {
211+
provider = google-beta
212+
project = var.project_id
213+
name = "fe-vpc-cx-gce"
214+
region = "us-east1"
215+
ip_cidr_range = "10.8.0.0/28"
216+
network = module.internal-lb-network.network_name
217+
max_throughput = 500
218+
min_throughput = 300
219+
}
220+
221+
module "frontend-service-a" {
222+
source = "GoogleCloudPlatform/cloud-run/google//modules/v2"
223+
version = "~> 0.16.3"
224+
project_id = var.project_id
225+
location = "us-east1"
226+
service_name = "fs-gce-a"
227+
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" }]
228+
members = ["allUsers"]
229+
vpc_access = {
230+
connector = google_vpc_access_connector.internal_lb_vpc_connector.id
231+
egress = "ALL_TRAFFIC"
232+
}
233+
ingress = "INGRESS_TRAFFIC_ALL"
234+
cloud_run_deletion_protection = false
235+
enable_prometheus_sidecar = false
236+
depends_on = [google_vpc_access_connector.internal_lb_vpc_connector]
237+
}
238+
239+
module "frontend-service-b" {
240+
source = "GoogleCloudPlatform/cloud-run/google//modules/v2"
241+
version = "~> 0.16.3"
242+
project_id = var.project_id
243+
location = "us-east1"
244+
service_name = "fs-gce-b"
245+
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" }]
246+
members = ["allUsers"]
247+
vpc_access = {
248+
connector = google_vpc_access_connector.internal_lb_vpc_connector.id
249+
egress = "ALL_TRAFFIC"
250+
}
251+
ingress = "INGRESS_TRAFFIC_ALL"
252+
cloud_run_deletion_protection = false
253+
enable_prometheus_sidecar = false
254+
}
255+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
output "external_cloudrun_uris" {
18+
description = "List of URIs for the frontend Cloud Run services"
19+
value = [module.frontend-service-a.service_uri, module.frontend-service-b.service_uri]
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# HTTP Cross-Regional Load Balancer Example - GCE MIG
2+
3+
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.
4+
The forwarding rules and its dependecies are created as part of `frontend` modules.
5+
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.
6+
7+
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
8+
## Inputs
9+
10+
| Name | Description | Type | Default | Required |
11+
|------|-------------|------|---------|:--------:|
12+
| project\_id | n/a | `string` | n/a | yes |
13+
14+
## Outputs
15+
16+
| Name | Description |
17+
|------|-------------|
18+
| external\_cloudrun\_uris | The uris of the publicaly accesible cloud-run services |
19+
20+
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
variable "project_id" {
18+
type = string
19+
}

metadata.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ spec:
6060
location: examples/https-redirect
6161
- name: internal-lb-cloud-run
6262
location: examples/internal-lb-cloud-run
63+
- name: internal-lb-gce-mig
64+
location: examples/internal-lb-gce-mig
6365
- name: lb-http-separate-frontend-and-backend
6466
location: examples/lb-http-separate-frontend-and-backend
6567
- name: mig-nat-http-lb

modules/backend/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This module creates `google_compute_backend_service` resource and its dependenci
1717
| enable\_cdn | Enable Cloud CDN for this BackendService. | `bool` | `false` | no |
1818
| firewall\_networks | Names of the networks to create firewall rules in | `list(string)` | <pre>[<br> "default"<br>]</pre> | no |
1919
| firewall\_projects | Names of the projects to create firewall rules in | `list(string)` | <pre>[<br> "default"<br>]</pre> | no |
20+
| 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 |
2021
| 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 |
2122
| 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 |
2223
| 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 |

0 commit comments

Comments
 (0)