Skip to content

Commit

Permalink
feat: Implement Envoy-based load balancing schemes (#269)
Browse files Browse the repository at this point in the history
* Implement Envoy-based load balancing schemes

Add configuration for load_balancing_scheme setting in forwarding
rules and backend service configuration.

Closes: #257

Signed-off-by: Jonathan Yu <[email protected]>

* remove explicit pinned version in example

* fix obj

Signed-off-by: Jonathan Yu <[email protected]>
Co-authored-by: Bharath KKB <[email protected]>
  • Loading branch information
jawnsy and bharathkkb authored Nov 3, 2022
1 parent 7f30d88 commit 125bf68
Show file tree
Hide file tree
Showing 22 changed files with 396 additions and 151 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ Current version is 3.0. Upgrade guides:
| https\_redirect | Set to `true` to enable https redirect on the lb. | `bool` | `false` | no |
| ipv6\_address | An existing IPv6 address to use (the actual IP address value) | `string` | `null` | no |
| labels | The labels to attach to resources created by this module | `map(string)` | `{}` | no |
| load\_balancing\_scheme | Load balancing scheme type (EXTERNAL for classic external load balancer, EXTERNAL\_MANAGED for Envoy-based load balancer, INTERNAL for classic internal load balancer, and INTERNAL\_SELF\_MANAGED for internal load balancer) | `string` | `"EXTERNAL"` | no |
| managed\_ssl\_certificate\_domains | Create Google-managed SSL certificates for specified domains. Requires `ssl` to be set to `true` and `use_ssl_certificates` set to `false`. | `list(string)` | `[]` | no |
| name | Name for the forwarding rule and prefix for supporting resources | `string` | n/a | yes |
| private\_key | Content of the private SSL key. Required if `ssl` is `true` and `ssl_certificates` is empty. | `string` | `null` | no |
Expand Down
86 changes: 46 additions & 40 deletions autogen/main.tf.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2020 Google LLC
* 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.
Expand Down Expand Up @@ -31,25 +31,27 @@ locals {

### IPv4 block ###
resource "google_compute_global_forwarding_rule" "http" {
provider = google-beta
project = var.project
count = local.create_http_forward ? 1 : 0
name = var.name
target = google_compute_target_http_proxy.default[0].self_link
ip_address = local.address
port_range = "80"
labels = var.labels
provider = google-beta
project = var.project
count = local.create_http_forward ? 1 : 0
name = var.name
target = google_compute_target_http_proxy.default[0].self_link
ip_address = local.address
port_range = "80"
labels = var.labels
load_balancing_scheme = var.load_balancing_scheme
}

resource "google_compute_global_forwarding_rule" "https" {
provider = google-beta
project = var.project
count = var.ssl ? 1 : 0
name = "${var.name}-https"
target = google_compute_target_https_proxy.default[0].self_link
ip_address = local.address
port_range = "443"
labels = var.labels
provider = google-beta
project = var.project
count = var.ssl ? 1 : 0
name = "${var.name}-https"
target = google_compute_target_https_proxy.default[0].self_link
ip_address = local.address
port_range = "443"
labels = var.labels
load_balancing_scheme = var.load_balancing_scheme
}

resource "google_compute_global_address" "default" {
Expand All @@ -64,25 +66,27 @@ resource "google_compute_global_address" "default" {

### IPv6 block ###
resource "google_compute_global_forwarding_rule" "http_ipv6" {
provider = google-beta
project = var.project
count = (var.enable_ipv6 && local.create_http_forward) ? 1 : 0
name = "${var.name}-ipv6-http"
target = google_compute_target_http_proxy.default[0].self_link
ip_address = local.ipv6_address
port_range = "80"
labels = var.labels
provider = google-beta
project = var.project
count = (var.enable_ipv6 && local.create_http_forward) ? 1 : 0
name = "${var.name}-ipv6-http"
target = google_compute_target_http_proxy.default[0].self_link
ip_address = local.ipv6_address
port_range = "80"
labels = var.labels
load_balancing_scheme = var.load_balancing_scheme
}

resource "google_compute_global_forwarding_rule" "https_ipv6" {
provider = google-beta
project = var.project
count = (var.enable_ipv6 && var.ssl) ? 1 : 0
name = "${var.name}-ipv6-https"
target = google_compute_target_https_proxy.default[0].self_link
ip_address = local.ipv6_address
port_range = "443"
labels = var.labels
provider = google-beta
project = var.project
count = (var.enable_ipv6 && var.ssl) ? 1 : 0
name = "${var.name}-ipv6-https"
target = google_compute_target_https_proxy.default[0].self_link
ip_address = local.ipv6_address
port_range = "443"
labels = var.labels
load_balancing_scheme = var.load_balancing_scheme
}

resource "google_compute_global_address" "default_ipv6" {
Expand Down Expand Up @@ -177,14 +181,16 @@ resource "google_compute_backend_service" "default" {
project = var.project
name = "${var.name}-backend-${each.key}"

load_balancing_scheme = var.load_balancing_scheme

{% if not serverless %}{# not necessary for serverless as default port_name=http, protocol=HTTP #}
port_name = each.value.port_name
protocol = each.value.protocol
port_name = each.value.port_name
protocol = each.value.protocol
{% endif %}

{% if not serverless %}
{# Limitation: Timeout sec is not supported for a backend service with Serverless network endpoint groups. #}
timeout_sec = lookup(each.value, "timeout_sec", null)
{# Limitation: Timeout sec is not supported for a backend service with Serverless network endpoint groups. #}
timeout_sec = lookup(each.value, "timeout_sec", null)
{% endif %}
description = lookup(each.value, "description", null)
connection_draining_timeout_sec = lookup(each.value, "connection_draining_timeout_sec", null)
Expand All @@ -193,9 +199,9 @@ resource "google_compute_backend_service" "default" {
custom_request_headers = lookup(each.value, "custom_request_headers", [])
custom_response_headers = lookup(each.value, "custom_response_headers", [])
{% if not serverless %}{# doesn't apply to serverless NEGs #}
health_checks = lookup(each.value, "health_check", null) == null ? null : [google_compute_health_check.default[each.key].self_link]
session_affinity = lookup(each.value, "session_affinity", null)
affinity_cookie_ttl_sec = lookup(each.value, "affinity_cookie_ttl_sec", null)
health_checks = lookup(each.value, "health_check", null) == null ? null : [google_compute_health_check.default[each.key].self_link]
session_affinity = lookup(each.value, "session_affinity", null)
affinity_cookie_ttl_sec = lookup(each.value, "affinity_cookie_ttl_sec", null)
{% endif %}

# To achieve a null backend security_policy, set each.value.security_policy to "" (empty string), otherwise, it fallsback to var.security_policy.
Expand Down
2 changes: 1 addition & 1 deletion autogen/outputs.tf.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2020 Google LLC
* 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.
Expand Down
8 changes: 7 additions & 1 deletion autogen/variables.tf.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2020 Google LLC
* 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.
Expand Down Expand Up @@ -243,3 +243,9 @@ variable "labels" {
type = map(string)
default = {}
}

variable "load_balancing_scheme" {
description = "Load balancing scheme type (EXTERNAL for classic external load balancer, EXTERNAL_MANAGED for Envoy-based load balancer, INTERNAL for classic internal load balancer, and INTERNAL_SELF_MANAGED for internal load balancer)"
type = string
default = "EXTERNAL"
}
2 changes: 1 addition & 1 deletion autogen/versions.tf.tmpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2021 Google LLC
* 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.
Expand Down
77 changes: 77 additions & 0 deletions examples/dynamic-backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# External HTTPS Load Balancer with dynamic backends

[![button](http://gstatic.com/cloudssh/images/open-btn.png)](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/GoogleCloudPlatform/terraform-google-lb-http&working_dir=examples/dynamic-backend&page=shell&tutorial=README.md)

This creates an external Envoy-based HTTPS Load Balancer using dynamic
backends suitable for integrating with a Google Kubernetes Engine cluster
running [gke-autoneg-controller](https://github.com/GoogleCloudPlatform/gke-autoneg-controller).
The load balancer will not route traffic to any backend service or bucket;
instead, it expects that an external user or service will register backends
(such as Network Endpoint Groups) accordingly to serve traffic. The example
will attempt to provision a Google-managed TLS certificate for the domain
"example.com" by default and use `/api/health` as a health check endpoint.

## Change to the example directory

```
[[ `basename $PWD` != https-gke ]] && cd examples/dynamic-backend
```

## Install Terraform

1. Install Terraform if it is not already installed (visit [terraform.io](https://terraform.io) for other distributions):

## Set up the environment

1. Set the project, replace `YOUR_PROJECT` with your project ID:

```
PROJECT=YOUR_PROJECT
```

```
gcloud config set project ${PROJECT}
```

2. Configure the environment for Terraform:

```
[[ $CLOUD_SHELL ]] || gcloud auth application-default login
export GOOGLE_PROJECT=$(gcloud config get-value project)
```

3. Create the dynamic backend load balancer.

```
(
cd dynamic-backend/
terraform init
terraform plan -out terraform.tfplan
terraform apply terraform.tfplan
)
```

4. Deploy the `gke-autoneg-controller` into a GKE cluster and configure it according to the instructions. This will create a Network Endpoint Group for a service and bind it to this load balancer.


## Cleanup

1. Delete the load balancing resources created by terraform:

```
terraform destroy
```

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

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| domains | Domain names to use in managed certificate | `list(string)` | <pre>[<br> "example.com"<br>]</pre> | no |
| project | n/a | `string` | n/a | yes |

## Outputs

No output.

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
92 changes: 92 additions & 0 deletions examples/dynamic-backend/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* 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.
*/

provider "google" {
project = var.project
}

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

resource "google_compute_managed_ssl_certificate" "frontend" {
name = "managedcert"

managed {
domains = var.domains
}
}

module "load_balancer" {
source = "../../modules/dynamic_backends"

name = "dynamic-backend-lb"
project = var.project
enable_ipv6 = true
create_ipv6_address = true
http_forward = false

load_balancing_scheme = "EXTERNAL_MANAGED"

ssl = true
use_ssl_certificates = true
ssl_certificates = [
google_compute_managed_ssl_certificate.frontend.self_link
]

backends = {
default = {
description = null
protocol = "HTTPS"
port = 443
port_name = "https"
timeout_sec = 30
connection_draining_timeout_sec = 0
enable_cdn = false
security_policy = null
session_affinity = null
affinity_cookie_ttl_sec = null
custom_request_headers = null
custom_response_headers = null
compression_mode = null

health_check = {
check_interval_sec = 15
timeout_sec = 15
healthy_threshold = 4
unhealthy_threshold = 4
request_path = "/api/health"
port = 443
host = null
logging = true
}

log_config = {
enable = true
sample_rate = 1.0
}

# leave blank, NEGs are dynamically added to the lb via autoneg
groups = []

iap_config = {
enable = false
oauth2_client_id = ""
oauth2_client_secret = ""
}
}
}
}
25 changes: 25 additions & 0 deletions examples/dynamic-backend/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* 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.
*/

variable "project" {
type = string
}

variable "domains" {
description = "Domain names to use in managed certificate"
type = list(string)
default = ["example.com"]
}
Loading

0 comments on commit 125bf68

Please sign in to comment.