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
68 changes: 54 additions & 14 deletions modules/net-lb-int/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This module allows managing a GCE Internal Load Balancer and integrates the forw
- [Multiple forwarding rules](#multiple-forwarding-rules)
- [Dual stack (IPv4 and IPv6)](#dual-stack-ipv4-and-ipv6)
- [PSC service attachments](#psc-service-attachments)
- [Zonal affinity traffic policy](#zonal-affinity-traffic-policy)
- [Regional health check](#regional-health-check)
- [End to end example](#end-to-end-example)
- [Context](#context)
Expand Down Expand Up @@ -282,6 +283,45 @@ module "ilb" {
# tftest modules=1 resources=7
```

### Zonal affinity traffic policy

The `backend_service_config.network_pass_through_lb_traffic_policy` block allows tuning the backend service behavior for network passthrough load balancers, including zonal affinity spillover settings.

```hcl
module "ilb" {
source = "./fabric/modules/net-lb-int"
project_id = var.project_id
region = "europe-west1"
name = "ilb-test"
service_label = "ilb-test"
vpc_config = {
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}
backend_service_config = {
network_pass_through_lb_traffic_policy = {
zonal_affinity = {
spillover = "ZONAL_AFFINITY_SPILL_CROSS_ZONE"
spillover_ratio = 0.5
}
}
}
group_configs = {
my-group = {
zone = "europe-west1-b"
instances = [
"instance-1-self-link",
"instance-2-self-link"
]
}
}
backends = [{
group = module.ilb.groups.my-group.self_link
}]
}
# tftest modules=1 resources=4
```

### Regional health check

The `is_regional` flag in the `health_check_config` block allows creating a regional health check instead of a global one.
Expand Down Expand Up @@ -459,21 +499,21 @@ One other issue is a `Provider produced inconsistent final plan` error which is

| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [name](variables.tf#L208) | Name used for all resources. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L213) | Project id where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L218) | GCP region. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L244) | VPC-level configuration. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [name](variables.tf#L235) | Name used for all resources. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L240) | Project id where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L245) | GCP region. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L271) | VPC-level configuration. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [backend_service_config](variables.tf#L17) | Backend service level configuration. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [backends](variables.tf#L58) | Load balancer backends. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [context](variables.tf#L69) | Context-specific interpolations. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [description](variables.tf#L82) | Optional description used for resources. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [forwarding_rules_config](variables.tf#L88) | The optional forwarding rules configuration. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#8230;&#125;</code> |
| [group_configs](variables.tf#L104) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_check](variables.tf#L117) | Name of existing health check to use, disables auto-created health check. Also set `health_check_config = null` when cross-referencing an health check from another load balancer module to avoid a Terraform error. | <code>string</code> | | <code>null</code> |
| [health_check_config](variables.tf#L123) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#8230;&#125;</code> |
| [labels](variables.tf#L202) | Labels set on resources. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [service_attachments](variables.tf#L223) | PSC service attachments, keyed by forwarding rule. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [service_label](variables.tf#L238) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |
| [backends](variables.tf#L85) | Load balancer backends. | <code>list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [context](variables.tf#L96) | Context-specific interpolations. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [description](variables.tf#L109) | Optional description used for resources. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [forwarding_rules_config](variables.tf#L115) | The optional forwarding rules configuration. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#8230;&#125;</code> |
| [group_configs](variables.tf#L131) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_check](variables.tf#L144) | Name of existing health check to use, disables auto-created health check. Also set `health_check_config = null` when cross-referencing an health check from another load balancer module to avoid a Terraform error. | <code>string</code> | | <code>null</code> |
| [health_check_config](variables.tf#L150) | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | <code>object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#8230;&#125;</code> |
| [labels](variables.tf#L229) | Labels set on resources. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [service_attachments](variables.tf#L250) | PSC service attachments, keyed by forwarding rule. | <code>map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>null</code> |
| [service_label](variables.tf#L265) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |

## Outputs

Expand Down
13 changes: 13 additions & 0 deletions modules/net-lb-int/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ locals {
)
bs_conntrack = var.backend_service_config.connection_tracking
bs_failover = var.backend_service_config.failover_config
bs_nptlb = var.backend_service_config.network_pass_through_lb_traffic_policy
forwarding_rule_names = {
for k, v in var.forwarding_rules_config :
k => k == "" ? var.name : "${var.name}-${k}"
Expand Down Expand Up @@ -150,6 +151,18 @@ resource "google_compute_region_backend_service" "default" {
}
}

dynamic "network_pass_through_lb_traffic_policy" {
for_each = local.bs_nptlb != null ? [""] : []
content {
dynamic "zonal_affinity" {
for_each = local.bs_nptlb.zonal_affinity != null ? [""] : []
content {
spillover = local.bs_nptlb.zonal_affinity.spillover
spillover_ratio = local.bs_nptlb.zonal_affinity.spillover_ratio
}
}
}
}
}

resource "google_compute_service_attachment" "default" {
Expand Down
27 changes: 27 additions & 0 deletions modules/net-lb-int/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ variable "backend_service_config" {
optional_mode = optional(string)
optional_fields = optional(list(string))
}))
network_pass_through_lb_traffic_policy = optional(object({
zonal_affinity = object({
spillover = optional(string, "ZONAL_AFFINITY_DISABLED")
spillover_ratio = optional(number)
})
}))
name = optional(string)
description = optional(string, "Terraform managed.")
protocol = optional(string, "UNSPECIFIED")
Expand All @@ -53,6 +59,27 @@ variable "backend_service_config" {
)
error_message = "Invalid session affinity value."
}
validation {
condition = (
try(var.backend_service_config.network_pass_through_lb_traffic_policy, null) == null
|| contains(
["ZONAL_AFFINITY_DISABLED", "ZONAL_AFFINITY_SPILL_CROSS_ZONE", "ZONAL_AFFINITY_STAY_WITHIN_ZONE"],
coalesce(var.backend_service_config.network_pass_through_lb_traffic_policy.zonal_affinity.spillover, "ZONAL_AFFINITY_DISABLED")
)
)
error_message = "network_pass_through_lb_traffic_policy.zonal_affinity.spillover must be one of ZONAL_AFFINITY_DISABLED, ZONAL_AFFINITY_SPILL_CROSS_ZONE, or ZONAL_AFFINITY_STAY_WITHIN_ZONE."
}
validation {
condition = (
try(var.backend_service_config.network_pass_through_lb_traffic_policy, null) == null
|| try(var.backend_service_config.network_pass_through_lb_traffic_policy.zonal_affinity.spillover_ratio, null) == null
|| (
var.backend_service_config.network_pass_through_lb_traffic_policy.zonal_affinity.spillover_ratio >= 0 &&
var.backend_service_config.network_pass_through_lb_traffic_policy.zonal_affinity.spillover_ratio <= 1
)
)
error_message = "network_pass_through_lb_traffic_policy.zonal_affinity.spillover_ratio must be a number between 0 and 1."
}
}

variable "backends" {
Expand Down
1 change: 1 addition & 0 deletions tests/modules/net_lb_int/tftest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ tests:
health-checks-https:
health-checks-ssl:
health-checks-tcp:
zonal-affinity:
32 changes: 32 additions & 0 deletions tests/modules/net_lb_int/zonal-affinity.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright 2026 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.

project_id = "my-project"
region = "europe-west1"
name = "ilb-test"
vpc_config = {
network = "default"
subnetwork = "default"
}
backends = [{
group = "foo"
}]
backend_service_config = {
network_pass_through_lb_traffic_policy = {
zonal_affinity = {
spillover = "ZONAL_AFFINITY_SPILL_CROSS_ZONE"
spillover_ratio = 0.5
}
}
}
23 changes: 23 additions & 0 deletions tests/modules/net_lb_int/zonal-affinity.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2026 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.

values:
google_compute_region_backend_service.default:
network_pass_through_lb_traffic_policy:
- zonal_affinity:
- spillover: ZONAL_AFFINITY_SPILL_CROSS_ZONE
spillover_ratio: 0.5

counts:
google_compute_region_backend_service: 1
Loading