-
Notifications
You must be signed in to change notification settings - Fork 910
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Net LB App Internal Cross-Region recipe (#2214)
* reorder tfdoc methods * add support for recipes to tfdoc * fix repo url in tfdoc * update module README * validated untested recipe * validated untested refactored recipe * add optional proxy subnet creation, outputs, fixes * tested * tfdoc fix * fix README * exclude examples from test collector
- Loading branch information
Showing
12 changed files
with
923 additions
and
232 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
175 changes: 175 additions & 0 deletions
175
modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
# Cross-region internal Application Load Balancer with VM instance group backends | ||
|
||
This recipe shows an actual usage scenario for the [cross-region internal application load balancer](../README.md) by implementing the [example provided in the GCP documentation](https://cloud.google.com/load-balancing/docs/l7-internal/setting-up-l7-cross-reg-internal). | ||
|
||
<p align="center"> | ||
<img src="https://cloud.google.com/static/load-balancing/images/cross-reg-int-vm.svg" alt="Scenario diagram."> | ||
</p> | ||
|
||
<!-- BEGIN TOC --> | ||
- [Prerequisites](#prerequisites) | ||
- [Proxy-only global subnets](#proxy-only-global-subnets) | ||
- [Firewall rules](#firewall-rules) | ||
- [Variable configuration](#variable-configuration) | ||
- [VPC configuration options](#vpc-configuration-options) | ||
- [Instance configuration options](#instance-configuration-options) | ||
- [DNS configuration](#dns-configuration) | ||
- [Testing](#testing) | ||
- [Files](#files) | ||
- [Variables](#variables) | ||
- [Outputs](#outputs) | ||
<!-- END TOC --> | ||
|
||
## Prerequisites | ||
|
||
To run this recipe, you need | ||
|
||
- an existing GCP project with the `compute` API enabled | ||
- the `roles/compute.admin` role or equivalent (e.g. `roles/editor`) assigned on the project | ||
- an existing VPC in the same project | ||
- one regular subnet per region where you want to deploy the load balancer in the same VPC | ||
- an organization policy configuration that allows creation of internal application load balancer (the default configuration is fine) | ||
- access to the Docker Registry from the instances (e.g. via Cloud NAT) | ||
|
||
### Proxy-only global subnets | ||
|
||
The load balancer needs one proxy-only global subnet in each of its regions. If the subnets already exist the load balancer will consume them. If you need to create them, either do that manually or configure the module to do it for you as explained in the [Variable configuration](#variable-configuration) section below. | ||
|
||
### Firewall rules | ||
|
||
For the load balancer to work you need to allow ingress to the instances from the health check ranges, and from the load balancer proxy ranges. You can create firewall rules manually or configure the module to do it for you as explained in the [Variable configuration](#variable-configuration) section below. | ||
|
||
## Variable configuration | ||
|
||
With all the requirements in place, the only variables that are needed are those that configure the project and VPC details. Note that you need to use ids or self links in the VPC configuration not names (Shared VPC configurations are also supported). | ||
|
||
This is a simple minimal configuration: | ||
|
||
```tfvars | ||
project_id = "my-project" | ||
vpc_config = { | ||
network = "projects/my-project/global/networks/test" | ||
subnets = { | ||
europe-west1 = "projects/my-project/regions/europe-west1/subnetworks/default" | ||
europe-west8 = "projects/my-project/regions/europe-west8/subnetworks/default", | ||
} | ||
} | ||
# tftest modules=5 resources=15 | ||
``` | ||
|
||
### VPC configuration options | ||
|
||
The VPC configuration also allows creating instances in different subnets, and auto-creation of proxy subnets and firewall rules. This is a complete configuration with all options. | ||
|
||
```tfvars | ||
project_id = "my-project" | ||
vpc_config = { | ||
network = "projects/my-project/global/networks/test" | ||
subnets = { | ||
europe-west1 = "projects/my-project/regions/europe-west1/subnetworks/default" | ||
europe-west8 = "projects/my-project/regions/europe-west8/subnetworks/default", | ||
} | ||
# only specify this to use different subnets for instances | ||
subnets_instances = { | ||
europe-west1 = "projects/my-project/regions/europe-west1/subnetworks/vms" | ||
europe-west8 = "projects/my-project/regions/europe-west8/subnetworks/vms", | ||
} | ||
# create proxy subnets | ||
proxy_subnets_config = { | ||
europe-west1 = "172.16.193.0/24" | ||
europe-west8 = "172.16.192.0/24" | ||
} | ||
# create firewall rules | ||
firewall_config = { | ||
proxy_subnet_ranges = [ | ||
"172.16.193.0/24", | ||
"172.16.192.0/24" | ||
] | ||
enable_health_check = true | ||
enable_iap_ssh = true | ||
} | ||
} | ||
# tftest skip | ||
``` | ||
|
||
### Instance configuration options | ||
|
||
The instance type and the number of zones can be configured via the `instances_config` variable: | ||
|
||
```tfvars | ||
project_id = "my-project" | ||
vpc_config = { | ||
network = "projects/my-project/global/networks/test" | ||
subnets = { | ||
europe-west1 = "projects/my-project/regions/europe-west1/subnetworks/default" | ||
europe-west8 = "projects/my-project/regions/europe-west8/subnetworks/default", | ||
} | ||
instances_config = { | ||
# both attributes are optional | ||
machine_type = "e2-small" | ||
zones = ["b", "c"] | ||
} | ||
} | ||
# tftest modules=5 resources=15 | ||
``` | ||
|
||
### DNS configuration | ||
|
||
The DNS zone used for the load balancer record can be configured via the `dns_config` variable: | ||
|
||
```tfvars | ||
project_id = "my-project" | ||
vpc_config = { | ||
network = "projects/my-project/global/networks/test" | ||
subnets = { | ||
europe-west1 = "projects/my-project/regions/europe-west1/subnetworks/default" | ||
europe-west8 = "projects/my-project/regions/europe-west8/subnetworks/default", | ||
} | ||
dns_config = { | ||
# all attributes are optional | ||
client_networks = [ | ||
"projects/my-project/global/networks/test", | ||
"projects/my-other-project/global/networks/test" | ||
] | ||
domain = "foo.example." | ||
hostname = "lb-test" | ||
} | ||
} | ||
# tftest modules=5 resources=15 | ||
``` | ||
|
||
## Testing | ||
|
||
To test the load balancer behaviour, you can simply disable the service on the backend instances by connecting via SSH and issuing the `sudo systemctl stop nginx` command. | ||
|
||
If the backends are unhealthy and the necessary firewall rules are in place, check that the Docker containers have started successfully on the instances by connecting via SSH and issuing the `sudo systemctl status nginx` command. | ||
|
||
<!-- TFDOC OPTS files:1 --> | ||
<!-- BEGIN TFDOC --> | ||
## Files | ||
|
||
| name | description | modules | | ||
|---|---|---| | ||
| [instances.tf](./instances.tf) | Instance-related locals and resources. | <code>compute-vm</code> · <code>iam-service-account</code> | | ||
| [main.tf](./main.tf) | Load balancer and VPC resources. | <code>dns</code> · <code>net-lb-app-int-cross-region</code> · <code>net-vpc</code> · <code>net-vpc-firewall</code> | | ||
| [outputs.tf](./outputs.tf) | Module outputs. | | | ||
| [region_shortnames.tf](./region_shortnames.tf) | Region shortnames via locals. | | | ||
| [variables.tf](./variables.tf) | Module variables. | | | ||
|
||
## Variables | ||
|
||
| name | description | type | required | default | | ||
|---|---|:---:|:---:|:---:| | ||
| [project_id](variables.tf#L49) | Project used to create resources. | <code>string</code> | ✓ | | | ||
| [vpc_config](variables.tf#L55) | VPC configuration for load balancer and instances. Subnets are keyed by region. | <code title="object({ network = string subnets = map(string) subnets_instances = optional(map(string)) firewall_config = optional(object({ proxy_subnet_ranges = list(string) client_allowed_ranges = optional(list(string)) enable_health_check = optional(bool, true) enable_iap_ssh = optional(bool, false) })) proxy_subnets_config = optional(map(string)) })">object({…})</code> | ✓ | | | ||
| [dns_config](variables.tf#L17) | DNS configuration. | <code title="object({ client_networks = optional(list(string)) domain = optional(string, "gce.example.") hostname = optional(string) })">object({…})</code> | | <code>{}</code> | | ||
| [instances_config](variables.tf#L28) | Configuration for instances. | <code title="object({ machine_type = optional(string, "e2-micro") zones = optional(list(string), ["b"]) })">object({…})</code> | | <code>{}</code> | | ||
| [prefix](variables.tf#L42) | Prefix used for resource names. | <code>string</code> | | <code>"lb-xr-00"</code> | | ||
|
||
## Outputs | ||
|
||
| name | description | sensitive | | ||
|---|---|:---:| | ||
| [instances](outputs.tf#L17) | Instances details. | | | ||
| [lb](outputs.tf#L34) | Load balancer details. | | | ||
<!-- END TFDOC --> |
77 changes: 77 additions & 0 deletions
77
modules/net-lb-app-int-cross-region/recipe-cross-reg-int-app-lb-vm-dns/instances.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/** | ||
* Copyright 2024 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. | ||
*/ | ||
|
||
# tfdoc:file:description Instance-related locals and resources. | ||
|
||
locals { | ||
# use lb subnets for instances if instance subnets are not defined | ||
subnets_instances = coalesce( | ||
var.vpc_config.subnets_instances, var.vpc_config.subnets | ||
) | ||
# derive instance names/attributes from permutation of regions and zones | ||
instances = { | ||
for t in setproduct(local.regions, var.instances_config.zones) : | ||
"${var.prefix}-${local.region_shortnames[t.0]}-${t.1}" => { | ||
region = t.0 | ||
zone = "${t.0}-${t.1}" | ||
} | ||
} | ||
} | ||
|
||
module "instance-sa" { | ||
source = "../../iam-service-account" | ||
project_id = var.project_id | ||
name = "vm-default" | ||
prefix = var.prefix | ||
display_name = "Cross-region LB instances service account" | ||
iam_project_roles = { | ||
(var.project_id) = [ | ||
"roles/logging.logWriter", | ||
"roles/monitoring.metricWriter" | ||
] | ||
} | ||
} | ||
|
||
module "instances" { | ||
source = "../../compute-vm" | ||
for_each = local.instances | ||
project_id = var.project_id | ||
zone = each.value.zone | ||
name = each.key | ||
instance_type = var.instances_config.machine_type | ||
boot_disk = { | ||
initialize_params = { | ||
image = "projects/cos-cloud/global/images/family/cos-stable" | ||
} | ||
} | ||
network_interfaces = [{ | ||
network = var.vpc_config.network | ||
subnetwork = local.subnets_instances[each.value.region] | ||
}] | ||
tags = [var.prefix] | ||
metadata = { | ||
user-data = file("${path.module}/nginx-cloud-config.yaml") | ||
} | ||
service_account = { | ||
email = module.instance-sa.email | ||
} | ||
group = { | ||
named_ports = { | ||
http = 80 | ||
https = 443 | ||
} | ||
} | ||
} |
Oops, something went wrong.