Refactor ILB module for Terraform 1.3 (#941)

* wip

* wip

* wip

* backport health check to compute-mig

* align blueprints and fast

* fix blueprints

* tfdoc
This commit is contained in:
Ludovico Magnocavallo 2022-11-02 18:05:20 +01:00 committed by GitHub
parent a214368800
commit 0563260678
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 619 additions and 503 deletions

View File

@ -13,25 +13,54 @@
# limitations under the License.
locals {
prefix = var.prefix != "" ? format("%s-", var.prefix) : ""
vpc_project = var.shared_vpc_project_id != null ? var.shared_vpc_project_id : module.project.project_id
network = module.vpc.self_link
subnetwork = var.project_create != null ? module.vpc.subnet_self_links[format("%s/%s", var.region, var.subnetwork)] : data.google_compute_subnetwork.subnetwork[0].self_link
node_base = format("%s%s", local.prefix, var.node_name)
node_prefix = length(local.node_base) > 12 ? substr(local.node_base, 0, 12) : local.node_base
node_netbios_names = [for idx in range(1, 3) : format("%s-%02d", local.node_prefix, idx)]
witness_name = format("%s%s", local.prefix, var.witness_name)
witness_netbios_name = length(local.witness_name) > 15 ? substr(local.witness_name, 0, 15) : local.witness_name
zones = var.project_create == null ? data.google_compute_zones.zones[0].names : formatlist("${var.region}-%s", ["a", "b", "c"])
node_zones = merge({ for idx, node_name in local.node_netbios_names : node_name => local.zones[idx] },
{ (local.witness_netbios_name) = local.zones[length(local.zones) - 1] })
cluster_full_name = format("%s%s", local.prefix, var.cluster_name)
cluster_netbios_name = length(local.cluster_full_name) > 15 ? substr(local.cluster_full_name, 0, 15) : local.cluster_full_name
ad_user_password_secret = format("%s%s-password", local.prefix, var.cluster_name)
ad_user_password_secret = "${local.cluster_full_name}-password"
cluster_full_name = "${local.prefix}${var.cluster_name}"
cluster_netbios_name = (
length(local.cluster_full_name) > 15
? substr(local.cluster_full_name, 0, 15)
: local.cluster_full_name
)
network = module.vpc.self_link
node_base = "${local.prefix}${var.node_name}"
node_prefix = (
length(local.node_base) > 12
? substr(local.node_base, 0, 12)
: local.node_base
)
node_netbios_names = [
for idx in range(1, 3) : format("%s-%02d", local.node_prefix, idx)
]
node_zones = merge(
{
for idx, node_name in local.node_netbios_names :
node_name => local.zones[idx]
},
{
(local.witness_netbios_name) = local.zones[length(local.zones) - 1]
}
)
prefix = var.prefix != "" ? "${var.prefix}-" : ""
subnetwork = (
var.project_create != null
? module.vpc.subnet_self_links["${var.region}/${var.subnetwork}"]
: data.google_compute_subnetwork.subnetwork[0].self_link
)
vpc_project = (
var.shared_vpc_project_id != null
? var.shared_vpc_project_id
: module.project.project_id
)
witness_name = "${local.prefix}${var.witness_name}"
witness_netbios_name = (
length(local.witness_name) > 15
? substr(local.witness_name, 0, 15)
: local.witness_name
)
zones = (
var.project_create == null
? data.google_compute_zones.zones[0].names
: formatlist("${var.region}-%s", ["a", "b", "c"])
)
}
module "project" {

View File

@ -15,26 +15,36 @@
# tfdoc:file:description Creates the VPC and manages the firewall rules and ILB.
locals {
listeners = { for aog in var.always_on_groups : format("%slb-%s", local.prefix, aog) => {
region = var.region
subnetwork = local.subnetwork
internal_addresses = merge(
local.listeners,
local.node_ips,
{
"${local.prefix}cluster" = {
region = var.region
subnetwork = local.subnetwork
}
(local.witness_netbios_name) = {
region = var.region
subnetwork = local.subnetwork
}
}
)
internal_address_ips = {
for k, v in module.ip-addresses.internal_addresses :
k => v.address
}
node_ips = { for node_name in local.node_netbios_names : node_name => {
region = var.region
subnetwork = local.subnetwork
}
}
internal_addresses = merge({
format("%scluster", local.prefix) = {
listeners = {
for aog in var.always_on_groups : "${local.prefix}lb-${aog}" => {
region = var.region
subnetwork = local.subnetwork
}
(local.witness_netbios_name) = {
}
node_ips = {
for node_name in local.node_netbios_names : node_name => {
region = var.region
subnetwork = local.subnetwork
}
}, local.listeners, local.node_ips)
}
}
data "google_compute_zones" "zones" {
@ -50,7 +60,6 @@ data "google_compute_subnetwork" "subnetwork" {
region = var.region
}
# Create VPC if required
module "vpc" {
source = "../../../modules/net-vpc"
@ -66,7 +75,6 @@ module "vpc" {
vpc_create = var.project_create != null ? true : false
}
# Firewall rules required for WSFC nodes
module "firewall" {
source = "../../../modules/net-vpc-firewall"
project_id = local.vpc_project
@ -76,7 +84,7 @@ module "firewall" {
https_source_ranges = []
ssh_source_ranges = []
custom_rules = {
format("%sallow-all-between-wsfc-nodes", local.prefix) = {
"${local.prefix}allow-all-between-wsfc-nodes" = {
description = "Allow all between WSFC nodes"
direction = "INGRESS"
action = "allow"
@ -91,7 +99,7 @@ module "firewall" {
]
extra_attributes = {}
}
format("%sallow-all-between-wsfc-witness", local.prefix) = {
"${local.prefix}allow-all-between-wsfc-witness" = {
description = "Allow all between WSFC witness nodes"
direction = "INGRESS"
action = "allow"
@ -106,7 +114,7 @@ module "firewall" {
]
extra_attributes = {}
}
format("%sallow-sql-to-wsfc-nodes", local.prefix) = {
"${local.prefix}allow-sql-to-wsfc-nodes" = {
description = "Allow SQL connections to WSFC nodes"
direction = "INGRESS"
action = "allow"
@ -119,7 +127,7 @@ module "firewall" {
]
extra_attributes = {}
}
format("%sallow-health-check-to-wsfc-nodes", local.prefix) = {
"${local.prefix}allow-health-check-to-wsfc-nodes" = {
description = "Allow health checks to WSFC nodes"
direction = "INGRESS"
action = "allow"
@ -135,39 +143,31 @@ module "firewall" {
}
}
# IP Address reservation for cluster and listener
module "ip-addresses" {
source = "../../../modules/net-address"
project_id = local.vpc_project
source = "../../../modules/net-address"
project_id = local.vpc_project
internal_addresses = local.internal_addresses
}
# L4 Internal Load Balancer for SQL Listener
module "listener-ilb" {
source = "../../../modules/net-ilb"
for_each = toset(var.always_on_groups)
project_id = var.project_id
region = var.region
name = format("%s-%s-ilb", var.prefix, each.value)
service_label = format("%s-%s-ilb", var.prefix, each.value)
address = module.ip-addresses.internal_addresses[format("%slb-%s", local.prefix, each.value)].address
network = local.network
subnetwork = local.subnetwork
source = "../../../modules/net-ilb"
for_each = toset(var.always_on_groups)
project_id = var.project_id
region = var.region
name = "${var.prefix}-${each.value}-ilb"
service_label = "${var.prefix}-${each.value}-ilb"
address = local.internal_address_ips["${local.prefix}lb-${each.value}"]
vpc_config = {
network = local.network
subnetwork = local.subnetwork
}
backends = [for k, node in module.nodes : {
failover = false
group = node.group.self_link
balancing_mode = "CONNECTION"
group = node.group.self_link
}]
health_check_config = {
type = "tcp",
check = { port = var.health_check_port },
config = var.health_check_config,
logging = true
enable_logging = true
tcp = {
port = var.health_check_port
}
}
}

View File

@ -199,20 +199,20 @@ module "squid-ilb" {
project_id = module.project-host.project_id
region = var.region
name = "squid-ilb"
service_label = "squid-ilb"
network = module.vpc.self_link
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
ports = [3128]
service_label = "squid-ilb"
vpc_config = {
network = module.vpc.self_link
subnetwork = module.vpc.subnet_self_links["${var.region}/proxy"]
}
backends = [{
failover = false
group = module.squid-mig.0.group_manager.instance_group
balancing_mode = "CONNECTION"
group = module.squid-mig.0.group_manager.instance_group
}]
health_check_config = {
type = "tcp"
check = { port = 3128 }
config = {}
logging = true
enable_logging = true
tcp = {
port = 3128
}
}
}

View File

@ -62,22 +62,22 @@ module "ilb-left" {
project_id = module.project.project_id
region = var.region
name = "${local.prefix}ilb-left"
network = module.vpc-left.self_link
subnetwork = values(module.vpc-left.subnet_self_links)[0]
address = local.addresses.ilb-left
ports = null
backend_config = {
session_affinity = var.ilb_session_affinity
timeout_sec = null
connection_draining_timeout_sec = null
vpc_config = {
network = module.vpc-left.self_link
subnetwork = values(module.vpc-left.subnet_self_links)[0]
}
address = local.addresses.ilb-left
backend_service_config = {
session_affinity = var.ilb_session_affinity
}
backends = [for z, mod in module.gw : {
failover = false
group = mod.group.self_link
balancing_mode = "CONNECTION"
group = mod.group.self_link
}]
health_check_config = {
type = "tcp", check = { port = 22 }, config = {}, logging = true
enable_logging = true
tcp = {
port = 22
}
}
}
@ -86,21 +86,21 @@ module "ilb-right" {
project_id = module.project.project_id
region = var.region
name = "${local.prefix}ilb-right"
network = module.vpc-right.self_link
subnetwork = values(module.vpc-right.subnet_self_links)[0]
address = local.addresses.ilb-right
ports = null
backend_config = {
session_affinity = var.ilb_session_affinity
timeout_sec = null
connection_draining_timeout_sec = null
vpc_config = {
network = module.vpc-right.self_link
subnetwork = values(module.vpc-right.subnet_self_links)[0]
}
address = local.addresses.ilb-right
backend_service_config = {
session_affinity = var.ilb_session_affinity
}
backends = [for z, mod in module.gw : {
failover = false
group = mod.group.self_link
balancing_mode = "CONNECTION"
group = mod.group.self_link
}]
health_check_config = {
type = "tcp", check = { port = 22 }, config = {}, logging = true
enable_logging = true
tcp = {
port = 22
}
}
}

View File

@ -120,16 +120,20 @@ module "ilb-nva-untrusted" {
name = "nva-untrusted-${each.value.0}"
service_label = var.prefix
global_access = true
network = module.landing-untrusted-vpc.self_link
subnetwork = module.landing-untrusted-vpc.subnet_self_links["${each.key}/landing-untrusted-default-${each.value.0}"]
backends = [for key, _ in local.nva_locality :
{
failover = false
group = module.nva-mig[key].group_manager.instance_group
balancing_mode = "CONNECTION"
} if local.nva_locality[key].region == each.key]
vpc_config = {
network = module.landing-untrusted-vpc.self_link
subnetwork = module.landing-untrusted-vpc.subnet_self_links["${each.key}/landing-untrusted-default-${each.value.0}"]
}
backends = [
for key, _ in local.nva_locality : {
group = module.nva-mig[key].group_manager.instance_group
} if local.nva_locality[key].region == each.key
]
health_check_config = {
type = "tcp", check = { port = 22 }, config = {}, logging = false
enable_logging = true
tcp = {
port = 22
}
}
}
@ -142,16 +146,20 @@ module "ilb-nva-trusted" {
name = "nva-trusted-${each.value.0}"
service_label = var.prefix
global_access = true
network = module.landing-trusted-vpc.self_link
subnetwork = module.landing-trusted-vpc.subnet_self_links["${each.key}/landing-trusted-default-${each.value.0}"]
backends = [for key, _ in local.nva_locality :
{
failover = false
group = module.nva-mig[key].group_manager.instance_group
balancing_mode = "CONNECTION"
} if local.nva_locality[key].region == each.key]
vpc_config = {
network = module.landing-trusted-vpc.self_link
subnetwork = module.landing-trusted-vpc.subnet_self_links["${each.key}/landing-trusted-default-${each.value.0}"]
}
backends = [
for key, _ in local.nva_locality : {
group = module.nva-mig[key].group_manager.instance_group
} if local.nva_locality[key].region == each.key
]
health_check_config = {
type = "tcp", check = { port = 22 }, config = {}, logging = false
enable_logging = true
tcp = {
port = 22
}
}
}

View File

@ -417,25 +417,25 @@ module "nginx-mig" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [instance_template](variables.tf#L150) | Instance template for the default version. | <code>string</code> | ✓ | |
| [location](variables.tf#L155) | Compute zone or region. | <code>string</code> | ✓ | |
| [name](variables.tf#L160) | Managed group name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L171) | Project id. | <code>string</code> | ✓ | |
| [instance_template](variables.tf#L174) | Instance template for the default version. | <code>string</code> | ✓ | |
| [location](variables.tf#L179) | Compute zone or region. | <code>string</code> | ✓ | |
| [name](variables.tf#L184) | Managed group name. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L195) | Project id. | <code>string</code> | ✓ | |
| [all_instances_config](variables.tf#L17) | Metadata and labels set to all instances in the group. | <code title="object&#40;&#123;&#10; labels &#61; optional&#40;map&#40;string&#41;&#41;&#10; metadata &#61; optional&#40;map&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [auto_healing_policies](variables.tf#L26) | Auto-healing policies for this group. | <code title="object&#40;&#123;&#10; health_check &#61; optional&#40;string&#41;&#10; initial_delay_sec &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [autoscaler_config](variables.tf#L35) | Optional autoscaler configuration. | <code title="object&#40;&#123;&#10; max_replicas &#61; number&#10; min_replicas &#61; number&#10; cooldown_period &#61; optional&#40;number&#41;&#10; mode &#61; optional&#40;string&#41; &#35; OFF, ONLY_UP, ON&#10; scaling_control &#61; optional&#40;object&#40;&#123;&#10; down &#61; optional&#40;object&#40;&#123;&#10; max_replicas_fixed &#61; optional&#40;number&#41;&#10; max_replicas_percent &#61; optional&#40;number&#41;&#10; time_window_sec &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; in &#61; optional&#40;object&#40;&#123;&#10; max_replicas_fixed &#61; optional&#40;number&#41;&#10; max_replicas_percent &#61; optional&#40;number&#41;&#10; time_window_sec &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10; scaling_signals &#61; optional&#40;object&#40;&#123;&#10; cpu_utilization &#61; optional&#40;object&#40;&#123;&#10; target &#61; number&#10; optimize_availability &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; load_balancing_utilization &#61; optional&#40;object&#40;&#123;&#10; target &#61; number&#10; &#125;&#41;&#41;&#10; metrics &#61; optional&#40;list&#40;object&#40;&#123;&#10; name &#61; string&#10; type &#61; string &#35; GAUGE, DELTA_PER_SECOND, DELTA_PER_MINUTE&#10; target_value &#61; number&#10; single_instance_assignment &#61; optional&#40;number&#41;&#10; time_series_filter &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#41;&#10; schedules &#61; optional&#40;list&#40;object&#40;&#123;&#10; duration_sec &#61; number&#10; name &#61; string&#10; min_required_replicas &#61; number&#10; cron_schedule &#61; string&#10; description &#61; optional&#40;bool&#41;&#10; timezone &#61; optional&#40;string&#41;&#10; disabled &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#41;&#10; &#125;&#41;, &#123;&#125;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [default_version_name](variables.tf#L83) | Name used for the default version. | <code>string</code> | | <code>&#34;default&#34;</code> |
| [description](variables.tf#L89) | Optional description used for all resources managed by this module. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [distribution_policy](variables.tf#L95) | DIstribution policy for regional MIG. | <code title="object&#40;&#123;&#10; target_shape &#61; optional&#40;string&#41;&#10; zones &#61; optional&#40;list&#40;string&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [health_check_config](variables.tf#L104) | 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 title="object&#40;&#123;&#10; check_interval_sec &#61; optional&#40;number&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; enable_logging &#61; optional&#40;bool, false&#41;&#10; healthy_threshold &#61; optional&#40;number&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10; unhealthy_threshold &#61; optional&#40;number&#41;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; service_name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; use_protocol &#61; optional&#40;string, &#34;http&#34;&#41; &#35; http http2 https&#10; &#125;&#41;&#41;&#10; tcp &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; use_ssl &#61; optional&#40;bool, false&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [named_ports](variables.tf#L165) | Named ports. | <code>map&#40;number&#41;</code> | | <code>null</code> |
| [stateful_config](variables.tf#L183) | Stateful configuration for individual instances. | <code title="map&#40;object&#40;&#123;&#10; minimal_action &#61; optional&#40;string&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; remove_state_on_destroy &#61; optional&#40;bool&#41;&#10; preserved_state &#61; optional&#40;object&#40;&#123;&#10; disks &#61; optional&#40;map&#40;object&#40;&#123;&#10; source &#61; string&#10; delete_on_instance_deletion &#61; optional&#40;bool&#41;&#10; read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#41;&#10; metadata &#61; optional&#40;map&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [stateful_disks](variables.tf#L176) | Stateful disk configuration applied at the MIG level to all instances, in device name => on permanent instance delete rule as boolean. | <code>map&#40;bool&#41;</code> | | <code>&#123;&#125;</code> |
| [target_pools](variables.tf#L202) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [target_size](variables.tf#L208) | Group target size, leave null when using an autoscaler. | <code>number</code> | | <code>null</code> |
| [update_policy](variables.tf#L214) | Update policy. Minimal action and type are required. | <code title="object&#40;&#123;&#10; minimal_action &#61; string&#10; type &#61; string&#10; max_surge &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; max_unavailable &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; min_ready_sec &#61; optional&#40;number&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; regional_redistribution_type &#61; optional&#40;string&#41;&#10; replacement_method &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [versions](variables.tf#L235) | Additional application versions, target_size is optional. | <code title="map&#40;object&#40;&#123;&#10; instance_template &#61; string&#10; target_size &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [wait_for_instances](variables.tf#L248) | Wait for all instances to be created/updated before returning. | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; status &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [health_check_config](variables.tf#L104) | 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 title="object&#40;&#123;&#10; check_interval_sec &#61; optional&#40;number&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; enable_logging &#61; optional&#40;bool, false&#41;&#10; healthy_threshold &#61; optional&#40;number&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10; unhealthy_threshold &#61; optional&#40;number&#41;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; service_name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http2 &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; https &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; tcp &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; ssl &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [named_ports](variables.tf#L189) | Named ports. | <code>map&#40;number&#41;</code> | | <code>null</code> |
| [stateful_config](variables.tf#L207) | Stateful configuration for individual instances. | <code title="map&#40;object&#40;&#123;&#10; minimal_action &#61; optional&#40;string&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; remove_state_on_destroy &#61; optional&#40;bool&#41;&#10; preserved_state &#61; optional&#40;object&#40;&#123;&#10; disks &#61; optional&#40;map&#40;object&#40;&#123;&#10; source &#61; string&#10; delete_on_instance_deletion &#61; optional&#40;bool&#41;&#10; read_only &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#41;&#10; metadata &#61; optional&#40;map&#40;string&#41;&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [stateful_disks](variables.tf#L200) | Stateful disk configuration applied at the MIG level to all instances, in device name => on permanent instance delete rule as boolean. | <code>map&#40;bool&#41;</code> | | <code>&#123;&#125;</code> |
| [target_pools](variables.tf#L226) | Optional list of URLs for target pools to which new instances in the group are added. | <code>list&#40;string&#41;</code> | | <code>&#91;&#93;</code> |
| [target_size](variables.tf#L232) | Group target size, leave null when using an autoscaler. | <code>number</code> | | <code>null</code> |
| [update_policy](variables.tf#L238) | Update policy. Minimal action and type are required. | <code title="object&#40;&#123;&#10; minimal_action &#61; string&#10; type &#61; string&#10; max_surge &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; max_unavailable &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; min_ready_sec &#61; optional&#40;number&#41;&#10; most_disruptive_action &#61; optional&#40;string&#41;&#10; regional_redistribution_type &#61; optional&#40;string&#41;&#10; replacement_method &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [versions](variables.tf#L259) | Additional application versions, target_size is optional. | <code title="map&#40;object&#40;&#123;&#10; instance_template &#61; string&#10; target_size &#61; optional&#40;object&#40;&#123;&#10; fixed &#61; optional&#40;number&#41;&#10; percent &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [wait_for_instances](variables.tf#L272) | Wait for all instances to be created/updated before returning. | <code title="object&#40;&#123;&#10; enabled &#61; bool&#10; status &#61; optional&#40;string&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
## Outputs

View File

@ -17,25 +17,16 @@
# tfdoc:file:description Health check resource.
locals {
hc = var.health_check_config
hc_grpc = try(local.hc.grpc, null) != null
hc_http = (
try(local.hc.http, null) != null &&
lower(try(local.hc.http.use_protocol, "")) == "http"
)
hc_http2 = (
try(local.hc.http, null) != null &&
lower(try(local.hc.http.use_protocol, "")) == "http2"
)
hc_https = (
try(local.hc.http, null) != null &&
lower(try(local.hc.http.use_protocol, "")) == "https"
)
hc_ssl = try(local.hc.tcp.use_ssl, null) == true
hc_tcp = try(local.hc.tcp, null) != null && !local.hc_ssl
hc = var.health_check_config
hc_grpc = try(local.hc.grpc, null) != null
hc_http = try(local.hc.http, null) != null
hc_http2 = try(local.hc.http2, null) != null
hc_https = try(local.hc.https, null) != null
hc_ssl = try(local.hc.ssl, null) != null
hc_tcp = try(local.hc.tcp, null) != null
}
resource "google_compute_health_check" "autohealing" {
resource "google_compute_health_check" "default" {
provider = google-beta
count = local.hc != null ? 1 : 0
project = var.project_id

View File

@ -17,7 +17,7 @@
locals {
health_check = (
try(var.auto_healing_policies.health_check, null) == null
? try(google_compute_health_check.autohealing.0.self_link, null)
? try(google_compute_health_check.default.0.self_link, null)
: try(var.auto_healing_policies.health_check, null)
)
instance_group_manager = (

View File

@ -37,6 +37,6 @@ output "health_check" {
value = (
var.health_check_config == null
? null
: google_compute_health_check.autohealing.0
: google_compute_health_check.default.0
)
}

View File

@ -124,7 +124,24 @@ variable "health_check_config" {
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
use_protocol = optional(string, "http") # http http2 https
}))
http2 = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
https = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
tcp = optional(object({
port = optional(number)
@ -133,7 +150,14 @@ variable "health_check_config" {
proxy_header = optional(string)
request = optional(string)
response = optional(string)
use_ssl = optional(bool, false)
}))
ssl = optional(object({
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request = optional(string)
response = optional(string)
}))
})
default = null

View File

@ -23,11 +23,13 @@ module "ilb" {
region = "europe-west1"
name = "ilb-test"
service_label = "ilb-test"
network = var.vpc.self_link
subnetwork = var.subnet.self_link
vpc_config = {
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}
group_configs = {
my-group = {
zone = "europe-west1-b", named_ports = null
zone = "europe-west1-b"
instances = [
"instance-1-self-link",
"instance-2-self-link"
@ -35,12 +37,12 @@ module "ilb" {
}
}
backends = [{
failover = false
group = module.ilb.groups.my-group.self_link
balancing_mode = "CONNECTION"
}]
health_check_config = {
type = "http", check = { port = 80 }, config = {}, logging = true
http = {
port = 80
}
}
}
# tftest modules=1 resources=4
@ -91,18 +93,21 @@ module "ilb" {
region = "europe-west1"
name = "ilb-test"
service_label = "ilb-test"
network = var.vpc.self_link
subnetwork = var.subnet.self_link
vpc_config = {
network = var.vpc.self_link
subnetwork = var.subnet.self_link
}
ports = [80]
backends = [
for z, mod in module.instance-group : {
failover = false
group = mod.group.self_link
balancing_mode = "CONNECTION"
balancing_mode = "UTILIZATION"
}
]
health_check_config = {
type = "http", check = { port = 80 }, config = {}, logging = true
http = {
port = 80
}
}
}
# tftest modules=3 resources=7
@ -113,37 +118,36 @@ module "ilb" {
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [backends](variables.tf#L33) | Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'. | <code title="list&#40;object&#40;&#123;&#10; failover &#61; bool&#10; group &#61; string&#10; balancing_mode &#61; string&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | ✓ | |
| [name](variables.tf#L98) | Name used for all resources. | <code>string</code> | ✓ | |
| [network](variables.tf#L103) | Network used for resources. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L114) | Project id where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L125) | GCP region. | <code>string</code> | ✓ | |
| [subnetwork](variables.tf#L136) | Subnetwork used for the forwarding rule. | <code>string</code> | ✓ | |
| [name](variables.tf#L184) | Name used for all resources. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L195) | Project id where resources will be created. | <code>string</code> | ✓ | |
| [region](variables.tf#L206) | GCP region. | <code>string</code> | ✓ | |
| [vpc_config](variables.tf#L217) | VPC-level configuration. | <code title="object&#40;&#123;&#10; network &#61; string&#10; subnetwork &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | ✓ | |
| [address](variables.tf#L17) | Optional IP address used for the forwarding rule. | <code>string</code> | | <code>null</code> |
| [backend_config](variables.tf#L23) | Optional backend configuration. | <code title="object&#40;&#123;&#10; session_affinity &#61; string&#10; timeout_sec &#61; number&#10; connection_draining_timeout_sec &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [failover_config](variables.tf#L42) | Optional failover configuration. | <code title="object&#40;&#123;&#10; disable_connection_drain &#61; bool&#10; drop_traffic_if_unhealthy &#61; bool&#10; ratio &#61; number&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [global_access](variables.tf#L52) | Global access, defaults to false if not set. | <code>bool</code> | | <code>null</code> |
| [group_configs](variables.tf#L58) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code title="map&#40;object&#40;&#123;&#10; instances &#61; list&#40;string&#41;&#10; named_ports &#61; map&#40;number&#41;&#10; zone &#61; string&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_check](variables.tf#L68) | Name of existing health check to use, disables auto-created health check. | <code>string</code> | | <code>null</code> |
| [health_check_config](variables.tf#L74) | Configuration of the auto-created helth check. | <code title="object&#40;&#123;&#10; type &#61; string &#35; http https tcp ssl http2&#10; check &#61; map&#40;any&#41; &#35; actual health check block attributes&#10; config &#61; map&#40;number&#41; &#35; interval, thresholds, timeout&#10; logging &#61; bool&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; type &#61; &#34;http&#34;&#10; check &#61; &#123;&#10; port_specification &#61; &#34;USE_SERVING_PORT&#34;&#10; &#125;&#10; config &#61; &#123;&#125;&#10; logging &#61; false&#10;&#125;">&#123;&#8230;&#125;</code> |
| [labels](variables.tf#L92) | Labels set on resources. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [ports](variables.tf#L108) | Comma-separated ports, leave null to use all ports. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [protocol](variables.tf#L119) | IP protocol used, defaults to TCP. | <code>string</code> | | <code>&#34;TCP&#34;</code> |
| [service_label](variables.tf#L130) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |
| [backend_service_config](variables.tf#L23) | Backend service level configuration. | <code title="object&#40;&#123;&#10; connection_draining_timeout_sec &#61; optional&#40;number&#41;&#10; connection_tracking &#61; optional&#40;object&#40;&#123;&#10; idle_timeout_sec &#61; optional&#40;number&#41;&#10; persist_conn_on_unhealthy &#61; optional&#40;string&#41;&#10; track_per_session &#61; optional&#40;bool&#41;&#10; &#125;&#41;&#41;&#10; enable_subsetting &#61; optional&#40;bool&#41;&#10; failover_config &#61; optional&#40;object&#40;&#123;&#10; disable_conn_drain &#61; optional&#40;bool&#41;&#10; drop_traffic_if_unhealthy &#61; optional&#40;bool&#41;&#10; ratio &#61; optional&#40;number&#41;&#10; &#125;&#41;&#41;&#10; log_sample_rate &#61; optional&#40;number&#41;&#10; session_affinity &#61; optional&#40;string&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>&#123;&#125;</code> |
| [backends](variables.tf#L56) | Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'. | <code title="list&#40;object&#40;&#123;&#10; group &#61; string&#10; balancing_mode &#61; optional&#40;string, &#34;CONNECTION&#34;&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; failover &#61; optional&#40;bool, false&#41;&#10;&#125;&#41;&#41;">list&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#91;&#93;</code> |
| [description](variables.tf#L75) | Optional description used for resources. | <code>string</code> | | <code>&#34;Terraform managed.&#34;</code> |
| [global_access](variables.tf#L81) | Global access, defaults to false if not set. | <code>bool</code> | | <code>null</code> |
| [group_configs](variables.tf#L87) | Optional unmanaged groups to create. Can be referenced in backends via outputs. | <code title="map&#40;object&#40;&#123;&#10; zone &#61; string&#10; instances &#61; optional&#40;list&#40;string&#41;, &#91;&#93;&#41;&#10; named_ports &#61; optional&#40;map&#40;number&#41;, &#123;&#125;&#41;&#10;&#125;&#41;&#41;">map&#40;object&#40;&#123;&#8230;&#125;&#41;&#41;</code> | | <code>&#123;&#125;</code> |
| [health_check](variables.tf#L98) | Name of existing health check to use, disables auto-created health check. | <code>string</code> | | <code>null</code> |
| [health_check_config](variables.tf#L104) | 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 title="object&#40;&#123;&#10; check_interval_sec &#61; optional&#40;number&#41;&#10; description &#61; optional&#40;string, &#34;Terraform managed.&#34;&#41;&#10; enable_logging &#61; optional&#40;bool, false&#41;&#10; healthy_threshold &#61; optional&#40;number&#41;&#10; timeout_sec &#61; optional&#40;number&#41;&#10; unhealthy_threshold &#61; optional&#40;number&#41;&#10; grpc &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; service_name &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; http2 &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; https &#61; optional&#40;object&#40;&#123;&#10; host &#61; optional&#40;string&#41;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request_path &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; tcp &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10; ssl &#61; optional&#40;object&#40;&#123;&#10; port &#61; optional&#40;number&#41;&#10; port_name &#61; optional&#40;string&#41;&#10; port_specification &#61; optional&#40;string&#41; &#35; USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT&#10; proxy_header &#61; optional&#40;string&#41;&#10; request &#61; optional&#40;string&#41;&#10; response &#61; optional&#40;string&#41;&#10; &#125;&#41;&#41;&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code title="&#123;&#10; tcp &#61; &#123;&#10; port_specification &#61; &#34;USE_SERVING_PORT&#34;&#10; &#125;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [labels](variables.tf#L178) | Labels set on resources. | <code>map&#40;string&#41;</code> | | <code>&#123;&#125;</code> |
| [ports](variables.tf#L189) | Comma-separated ports, leave null to use all ports. | <code>list&#40;string&#41;</code> | | <code>null</code> |
| [protocol](variables.tf#L200) | IP protocol used, defaults to TCP. | <code>string</code> | | <code>&#34;TCP&#34;</code> |
| [service_label](variables.tf#L211) | Optional prefix of the fully qualified forwarding rule name. | <code>string</code> | | <code>null</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [backend](outputs.tf#L17) | Backend resource. | |
| [backend_id](outputs.tf#L22) | Backend id. | |
| [backend_self_link](outputs.tf#L27) | Backend self link. | |
| [backend_service](outputs.tf#L17) | Backend resource. | |
| [backend_service_id](outputs.tf#L22) | Backend id. | |
| [backend_service_self_link](outputs.tf#L27) | Backend self link. | |
| [forwarding_rule](outputs.tf#L32) | Forwarding rule resource. | |
| [forwarding_rule_address](outputs.tf#L37) | Forwarding rule address. | |
| [forwarding_rule_id](outputs.tf#L42) | Forwarding rule id. | |
| [forwarding_rule_self_link](outputs.tf#L47) | Forwarding rule self link. | |
| [group_self_links](outputs.tf#L52) | Optional unmanaged instance group self links. | |
| [groups](outputs.tf#L59) | Optional unmanaged instance group resources. | |
| [group_self_links](outputs.tf#L57) | Optional unmanaged instance group self links. | |
| [groups](outputs.tf#L52) | Optional unmanaged instance group resources. | |
| [health_check](outputs.tf#L64) | Auto-created health-check resource. | |
| [health_check_self_id](outputs.tf#L69) | Auto-created health-check self id. | |
| [health_check_self_link](outputs.tf#L74) | Auto-created health-check self link. | |

33
modules/net-ilb/groups.tf Normal file
View File

@ -0,0 +1,33 @@
/**
* Copyright 2022 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 Optional instance group resources.
resource "google_compute_instance_group" "unmanaged" {
for_each = var.group_configs
project = var.project_id
zone = each.value.zone
name = each.key
description = "Terraform-managed."
instances = each.value.instances
dynamic "named_port" {
for_each = each.value.named_ports
content {
name = named_port.key
port = named_port.value
}
}
}

View File

@ -0,0 +1,119 @@
/**
* Copyright 2022 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 Health check resource.
locals {
hc = var.health_check_config
hc_grpc = try(local.hc.grpc, null) != null
hc_http = try(local.hc.http, null) != null
hc_http2 = try(local.hc.http2, null) != null
hc_https = try(local.hc.https, null) != null
hc_ssl = try(local.hc.ssl, null) != null
hc_tcp = try(local.hc.tcp, null) != null
}
resource "google_compute_health_check" "default" {
provider = google-beta
count = local.hc != null ? 1 : 0
project = var.project_id
name = var.name
description = local.hc.description
check_interval_sec = local.hc.check_interval_sec
healthy_threshold = local.hc.healthy_threshold
timeout_sec = local.hc.timeout_sec
unhealthy_threshold = local.hc.unhealthy_threshold
dynamic "grpc_health_check" {
for_each = local.hc_grpc ? [""] : []
content {
port = local.hc.grpc.port
port_name = local.hc.grpc.port_name
port_specification = local.hc.grpc.port_specification
grpc_service_name = local.hc.grpc.service_name
}
}
dynamic "http_health_check" {
for_each = local.hc_http ? [""] : []
content {
host = local.hc.http.host
port = local.hc.http.port
port_name = local.hc.http.port_name
port_specification = local.hc.http.port_specification
proxy_header = local.hc.http.proxy_header
request_path = local.hc.http.request_path
response = local.hc.http.response
}
}
dynamic "http2_health_check" {
for_each = local.hc_http2 ? [""] : []
content {
host = local.hc.http.host
port = local.hc.http.port
port_name = local.hc.http.port_name
port_specification = local.hc.http.port_specification
proxy_header = local.hc.http.proxy_header
request_path = local.hc.http.request_path
response = local.hc.http.response
}
}
dynamic "https_health_check" {
for_each = local.hc_https ? [""] : []
content {
host = local.hc.http.host
port = local.hc.http.port
port_name = local.hc.http.port_name
port_specification = local.hc.http.port_specification
proxy_header = local.hc.http.proxy_header
request_path = local.hc.http.request_path
response = local.hc.http.response
}
}
dynamic "ssl_health_check" {
for_each = local.hc_ssl ? [""] : []
content {
port = local.hc.tcp.port
port_name = local.hc.tcp.port_name
port_specification = local.hc.tcp.port_specification
proxy_header = local.hc.tcp.proxy_header
request = local.hc.tcp.request
response = local.hc.tcp.response
}
}
dynamic "tcp_health_check" {
for_each = local.hc_tcp ? [""] : []
content {
port = local.hc.tcp.port
port_name = local.hc.tcp.port_name
port_specification = local.hc.tcp.port_specification
proxy_header = local.hc.tcp.proxy_header
request = local.hc.tcp.request
response = local.hc.tcp.response
}
}
dynamic "log_config" {
for_each = try(local.hc.enable_logging, null) == true ? [""] : []
content {
enable = true
}
}
}

View File

@ -16,252 +16,100 @@
locals {
bs_conntrack = var.backend_service_config.connection_tracking
bs_failover = var.backend_service_config.failover_config
health_check = (
var.health_check != null
? var.health_check
: try(local.health_check_resource.self_link, null)
: google_compute_health_check.default.0.self_link
)
health_check_resource = try(
google_compute_health_check.http.0,
google_compute_health_check.https.0,
google_compute_health_check.tcp.0,
google_compute_health_check.ssl.0,
google_compute_health_check.http2.0,
{}
)
health_check_type = try(var.health_check_config.type, null)
}
resource "google_compute_forwarding_rule" "default" {
provider = google-beta
project = var.project_id
name = var.name
description = "Terraform managed."
provider = google-beta
project = var.project_id
region = var.region
name = var.name
description = var.description
ip_address = var.address
ip_protocol = var.protocol # TCP | UDP
backend_service = (
google_compute_region_backend_service.default.self_link
)
load_balancing_scheme = "INTERNAL"
region = var.region
network = var.network
subnetwork = var.subnetwork
ip_address = var.address
ip_protocol = var.protocol # TCP | UDP
ports = var.ports # "nnnnn" or "nnnnn,nnnnn,nnnnn" max 5
service_label = var.service_label
all_ports = var.ports == null ? true : null
network = var.vpc_config.network
ports = var.ports # "nnnnn" or "nnnnn,nnnnn,nnnnn" max 5
subnetwork = var.vpc_config.subnetwork
allow_global_access = var.global_access
backend_service = google_compute_region_backend_service.default.self_link
labels = var.labels
all_ports = var.ports == null ? true : null
service_label = var.service_label
# is_mirroring_collector = false
labels = var.labels
}
resource "google_compute_region_backend_service" "default" {
provider = google-beta
project = var.project_id
name = var.name
description = "Terraform managed."
load_balancing_scheme = "INTERNAL"
region = var.region
network = var.network
health_checks = [local.health_check]
protocol = var.protocol
session_affinity = try(var.backend_config.session_affinity, null)
timeout_sec = try(var.backend_config.timeout_sec, null)
connection_draining_timeout_sec = try(var.backend_config.connection_draining_timeout_sec, null)
provider = google-beta
project = var.project_id
region = var.region
name = var.name
description = var.description
load_balancing_scheme = "INTERNAL"
protocol = var.protocol
network = var.vpc_config.network
health_checks = [local.health_check]
connection_draining_timeout_sec = var.backend_service_config.connection_draining_timeout_sec
session_affinity = var.backend_service_config.session_affinity
timeout_sec = var.backend_service_config.timeout_sec
dynamic "backend" {
for_each = { for b in var.backends : b.group => b }
iterator = backend
content {
balancing_mode = backend.value.balancing_mode
description = "Terraform managed."
description = backend.value.description
failover = backend.value.failover
group = backend.key
}
}
dynamic "connection_tracking_policy" {
for_each = local.bs_conntrack == null ? [] : [""]
content {
connection_persistence_on_unhealthy_backends = (
local.bs_conntrack.persist_conn_on_unhealthy != null
? local.bs_conntrack.persist_conn_on_unhealthy
: null
)
idle_timeout_sec = local.bs_conntrack.idle_timeout_sec
tracking_mode = (
local.bs_conntrack.track_per_session != null
? local.bs_conntrack.track_per_session
: null
)
}
}
dynamic "failover_policy" {
for_each = var.failover_config == null ? [] : [var.failover_config]
iterator = config
for_each = local.bs_failover == null ? [] : [""]
content {
disable_connection_drain_on_failover = config.value.disable_connection_drain
drop_traffic_if_unhealthy = config.value.drop_traffic_if_unhealthy
failover_ratio = config.value.ratio
disable_connection_drain_on_failover = local.bs_failover.disable_conn_drain
drop_traffic_if_unhealthy = local.bs_failover.drop_traffic_if_unhealthy
failover_ratio = local.bs_failover.ratio
}
}
}
resource "google_compute_instance_group" "unmanaged" {
for_each = var.group_configs
project = var.project_id
zone = each.value.zone
name = each.key
description = "Terraform-managed."
instances = each.value.instances
dynamic "named_port" {
for_each = each.value.named_ports != null ? each.value.named_ports : {}
iterator = config
content {
name = config.key
port = config.value
}
}
}
resource "google_compute_health_check" "http" {
provider = google-beta
count = (
var.health_check == null && local.health_check_type == "http" ? 1 : 0
)
project = var.project_id
name = var.name
description = "Terraform managed."
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
http_health_check {
host = try(var.health_check_config.check.host, null)
port = try(var.health_check_config.check.port, null)
port_name = try(var.health_check_config.check.port_name, null)
port_specification = try(var.health_check_config.check.port_specification, null)
proxy_header = try(var.health_check_config.check.proxy_header, null)
request_path = try(var.health_check_config.check.request_path, null)
response = try(var.health_check_config.check.response, null)
}
dynamic "log_config" {
for_each = try(var.health_check_config.logging, false) ? [""] : []
for_each = var.backend_service_config.log_sample_rate == null ? [] : [""]
content {
enable = true
enable = true
sample_rate = var.backend_service_config.log_sample_rate
}
}
}
resource "google_compute_health_check" "https" {
provider = google-beta
count = (
var.health_check == null && local.health_check_type == "https" ? 1 : 0
)
project = var.project_id
name = var.name
description = "Terraform managed."
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
https_health_check {
host = try(var.health_check_config.check.host, null)
port = try(var.health_check_config.check.port, null)
port_name = try(var.health_check_config.check.port_name, null)
port_specification = try(var.health_check_config.check.port_specification, null)
proxy_header = try(var.health_check_config.check.proxy_header, null)
request_path = try(var.health_check_config.check.request_path, null)
response = try(var.health_check_config.check.response, null)
}
dynamic "log_config" {
for_each = try(var.health_check_config.logging, false) ? [""] : []
dynamic "subsetting" {
for_each = var.backend_service_config.enable_subsetting == true ? [""] : []
content {
enable = true
policy = "CONSISTENT_HASH_SUBSETTING"
}
}
}
resource "google_compute_health_check" "tcp" {
provider = google-beta
count = (
var.health_check == null && local.health_check_type == "tcp" ? 1 : 0
)
project = var.project_id
name = var.name
description = "Terraform managed."
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
tcp_health_check {
port = try(var.health_check_config.check.port, null)
port_name = try(var.health_check_config.check.port_name, null)
port_specification = try(var.health_check_config.check.port_specification, null)
proxy_header = try(var.health_check_config.check.proxy_header, null)
request = try(var.health_check_config.check.request, null)
response = try(var.health_check_config.check.response, null)
}
dynamic "log_config" {
for_each = try(var.health_check_config.logging, false) ? [""] : []
content {
enable = true
}
}
}
resource "google_compute_health_check" "ssl" {
provider = google-beta
count = (
var.health_check == null && local.health_check_type == "ssl" ? 1 : 0
)
project = var.project_id
name = var.name
description = "Terraform managed."
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
ssl_health_check {
port = try(var.health_check_config.check.port, null)
port_name = try(var.health_check_config.check.port_name, null)
port_specification = try(var.health_check_config.check.port_specification, null)
proxy_header = try(var.health_check_config.check.proxy_header, null)
request = try(var.health_check_config.check.request, null)
response = try(var.health_check_config.check.response, null)
}
dynamic "log_config" {
for_each = try(var.health_check_config.logging, false) ? [""] : []
content {
enable = true
}
}
}
resource "google_compute_health_check" "http2" {
provider = google-beta
count = (
var.health_check == null && local.health_check_type == "http2" ? 1 : 0
)
project = var.project_id
name = var.name
description = "Terraform managed."
check_interval_sec = try(var.health_check_config.config.check_interval_sec, null)
healthy_threshold = try(var.health_check_config.config.healthy_threshold, null)
timeout_sec = try(var.health_check_config.config.timeout_sec, null)
unhealthy_threshold = try(var.health_check_config.config.unhealthy_threshold, null)
http2_health_check {
host = try(var.health_check_config.check.host, null)
port = try(var.health_check_config.check.port, null)
port_name = try(var.health_check_config.check.port_name, null)
port_specification = try(var.health_check_config.check.port_specification, null)
proxy_header = try(var.health_check_config.check.proxy_header, null)
request_path = try(var.health_check_config.check.request_path, null)
response = try(var.health_check_config.check.response, null)
}
dynamic "log_config" {
for_each = try(var.health_check_config.logging, false) ? [""] : []
content {
enable = true
}
}
}

View File

@ -14,17 +14,17 @@
* limitations under the License.
*/
output "backend" {
output "backend_service" {
description = "Backend resource."
value = google_compute_region_backend_service.default
}
output "backend_id" {
output "backend_service_id" {
description = "Backend id."
value = google_compute_region_backend_service.default.id
}
output "backend_self_link" {
output "backend_service_self_link" {
description = "Backend self link."
value = google_compute_region_backend_service.default.self_link
}
@ -49,6 +49,11 @@ output "forwarding_rule_self_link" {
value = google_compute_forwarding_rule.default.self_link
}
output "groups" {
description = "Optional unmanaged instance group resources."
value = google_compute_instance_group.unmanaged
}
output "group_self_links" {
description = "Optional unmanaged instance group self links."
value = {
@ -56,22 +61,17 @@ output "group_self_links" {
}
}
output "groups" {
description = "Optional unmanaged instance group resources."
value = google_compute_instance_group.unmanaged
}
output "health_check" {
description = "Auto-created health-check resource."
value = local.health_check_resource
value = try(google_compute_health_check.default.0, null)
}
output "health_check_self_id" {
description = "Auto-created health-check self id."
value = try(local.health_check_resource.id, null)
value = try(google_compute_health_check.default.0.id, null)
}
output "health_check_self_link" {
description = "Auto-created health-check self link."
value = try(local.health_check_resource.self_link, null)
value = try(google_compute_health_check.default.0.self_link, null)
}

View File

@ -20,33 +20,62 @@ variable "address" {
default = null
}
variable "backend_config" {
description = "Optional backend configuration."
variable "backend_service_config" {
description = "Backend service level configuration."
type = object({
session_affinity = string
timeout_sec = number
connection_draining_timeout_sec = number
connection_draining_timeout_sec = optional(number)
connection_tracking = optional(object({
idle_timeout_sec = optional(number)
persist_conn_on_unhealthy = optional(string)
track_per_session = optional(bool)
}))
enable_subsetting = optional(bool)
failover_config = optional(object({
disable_conn_drain = optional(bool)
drop_traffic_if_unhealthy = optional(bool)
ratio = optional(number)
}))
log_sample_rate = optional(number)
session_affinity = optional(string)
timeout_sec = optional(number)
})
default = null
default = {}
nullable = false
validation {
condition = contains(
[
"NONE", "CLIENT_IP", "CLIENT_IP_NO_DESTINATION",
"CLIENT_IP_PORT_PROTO", "CLIENT_IP_PROTO"
],
coalesce(var.backend_service_config.session_affinity, "NONE")
)
error_message = "Invalid session affinity value."
}
}
variable "backends" {
description = "Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'."
type = list(object({
failover = bool
group = string
balancing_mode = string
balancing_mode = optional(string, "CONNECTION")
description = optional(string, "Terraform managed.")
failover = optional(bool, false)
}))
default = []
nullable = false
validation {
condition = alltrue([
for b in var.backends : contains(
["CONNECTION", "UTILIZATION"], coalesce(b.balancing_mode, "CONNECTION")
)])
error_message = "When specified balancing mode needs to be 'CONNECTION' or 'UTILIZATION'."
}
}
variable "failover_config" {
description = "Optional failover configuration."
type = object({
disable_connection_drain = bool
drop_traffic_if_unhealthy = bool
ratio = number
})
default = null
variable "description" {
description = "Optional description used for resources."
type = string
default = "Terraform managed."
}
variable "global_access" {
@ -58,11 +87,12 @@ variable "global_access" {
variable "group_configs" {
description = "Optional unmanaged groups to create. Can be referenced in backends via outputs."
type = map(object({
instances = list(string)
named_ports = map(number)
zone = string
instances = optional(list(string), [])
named_ports = optional(map(number), {})
}))
default = {}
default = {}
nullable = false
}
variable "health_check" {
@ -72,20 +102,76 @@ variable "health_check" {
}
variable "health_check_config" {
description = "Configuration of the auto-created helth check."
description = "Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage."
type = object({
type = string # http https tcp ssl http2
check = map(any) # actual health check block attributes
config = map(number) # interval, thresholds, timeout
logging = bool
check_interval_sec = optional(number)
description = optional(string, "Terraform managed.")
enable_logging = optional(bool, false)
healthy_threshold = optional(number)
timeout_sec = optional(number)
unhealthy_threshold = optional(number)
grpc = optional(object({
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
service_name = optional(string)
}))
http = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
http2 = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
https = optional(object({
host = optional(string)
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request_path = optional(string)
response = optional(string)
}))
tcp = optional(object({
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request = optional(string)
response = optional(string)
}))
ssl = optional(object({
port = optional(number)
port_name = optional(string)
port_specification = optional(string) # USE_FIXED_PORT USE_NAMED_PORT USE_SERVING_PORT
proxy_header = optional(string)
request = optional(string)
response = optional(string)
}))
})
default = {
type = "http"
check = {
tcp = {
port_specification = "USE_SERVING_PORT"
}
config = {}
logging = false
}
validation {
condition = (
(try(var.health_check_config.grpc, null) == null ? 0 : 1) +
(try(var.health_check_config.http, null) == null ? 0 : 1) +
(try(var.health_check_config.tcp, null) == null ? 0 : 1) <= 1
)
error_message = "Only one health check type can be configured at a time."
}
}
@ -100,11 +186,6 @@ variable "name" {
type = string
}
variable "network" {
description = "Network used for resources."
type = string
}
variable "ports" {
description = "Comma-separated ports, leave null to use all ports."
type = list(string)
@ -133,7 +214,11 @@ variable "service_label" {
default = null
}
variable "subnetwork" {
description = "Subnetwork used for the forwarding rule."
type = string
variable "vpc_config" {
description = "VPC-level configuration."
type = object({
network = string
subnetwork = string
})
nullable = false
}

View File

@ -15,21 +15,21 @@
*/
module "test" {
source = "../../../../modules/net-ilb"
project_id = "my-project"
region = "europe-west1"
network = "default"
subnetwork = "default"
name = "ilb-test"
labels = {}
address = var.address
backends = var.backends
backend_config = var.backend_config
failover_config = var.failover_config
global_access = var.global_access
health_check = var.health_check
health_check_config = var.health_check_config
ports = var.ports
protocol = var.protocol
service_label = var.service_label
source = "../../../../modules/net-ilb"
project_id = "my-project"
region = "europe-west1"
name = "ilb-test"
vpc_config = {
network = "default"
subnetwork = "default"
}
address = var.address
backend_service_config = var.backend_service_config
backends = var.backends
description = var.description
global_access = var.global_access
group_configs = var.group_configs
ports = var.ports
protocol = var.protocol
service_label = var.service_label
}

View File

@ -19,30 +19,20 @@ variable "address" {
default = null
}
variable "backend_service_config" {
description = "Backend service level configuration."
type = any
default = {}
}
variable "backends" {
type = list(object({
failover = bool
group = string
balancing_mode = string
}))
type = any
default = []
}
variable "backend_config" {
type = object({
session_affinity = string
timeout_sec = number
connection_draining_timeout_sec = number
})
default = null
}
variable "failover_config" {
type = object({
disable_connection_drain = bool
drop_traffic_if_unhealthy = bool
ratio = number
})
default = null
variable "description" {
type = string
default = "Terraform managed."
}
variable "global_access" {
@ -50,26 +40,9 @@ variable "global_access" {
default = null
}
variable "health_check" {
type = string
default = null
}
variable "health_check_config" {
type = object({
type = string # http https tcp ssl http2
check = map(any) # actual health check block attributes
config = map(number) # interval, thresholds, timeout
logging = bool
})
default = {
type = "http"
check = {
port_specification = "USE_SERVING_PORT"
}
config = {}
logging = false
}
variable "group_configs" {
type = any
default = {}
}
variable "ports" {

View File

@ -29,7 +29,7 @@ def test_defaults(plan_runner):
assert backend['backend'][0]['group'] == 'foo'
health_check = resources['google_compute_health_check']
for k, v in health_check.items():
if k == 'http_health_check':
if k == 'tcp_health_check':
assert len(v) == 1
assert v[0]['port_specification'] == 'USE_SERVING_PORT'
elif k.endswith('_health_check'):
@ -38,12 +38,14 @@ def test_defaults(plan_runner):
def test_forwarding_rule(plan_runner):
"Test forwarding rule variables."
_, resources = plan_runner(backends=_BACKENDS,
global_access='true',
_, resources = plan_runner(backends=_BACKENDS, global_access='true',
ports="[80]")
assert len(resources) == 3
values = [r['values'] for r in resources if r['type']
== 'google_compute_forwarding_rule'][0]
values = [
r['values']
for r in resources
if r['type'] == 'google_compute_forwarding_rule'
][0]
assert not values['all_ports']
assert values['ports'] == ['80']
assert values['allow_global_access']