forked from GoogleCloudPlatform/professional-services
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Terraform ILB example. (GoogleCloudPlatform#652)
- Loading branch information
Showing
5 changed files
with
359 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Internal HTTP Load Balancer Terraform Example | ||
This example shows how to deploy an internal HTTP load balancer using | ||
plain terraform (i.e. without using any external modules). This | ||
example will create all the required resources needed for a working | ||
internal load balancer except the GCP project. | ||
|
||
## Design | ||
In this example we use simple application (an nginx serving a simple | ||
HTML file) configured using a [startup | ||
script](https://cloud.google.com/compute/docs/instances/startup-scripts/linux). | ||
This application is deployed using a [Managed Instance | ||
Group](https://cloud.google.com/compute/docs/instance-groups) with a | ||
minimum of two instances. | ||
|
||
Besides the computing resources, the code also deploys a VPC, the | ||
required subnets, and all the components elements of a load balancer | ||
(forwarding rule, URL map, health check, etc). | ||
|
||
For testing purposes, an additional VM is also created. You can use | ||
this VM to confirm the load balancer is correctly configured. | ||
|
||
## Prerequisites | ||
1. You must have a recent version of Terraform installed (0.14+). | ||
1. A working GCP project with the GCE API enabled. | ||
|
||
## Deploy | ||
The terraform code defines multiple variables. Most of the variables | ||
provide default values that can be safely used but you must provide | ||
the project id where the resources will be created. Check the | ||
Variables section below for more details. | ||
|
||
In the following command, we define the `project_id` variable using | ||
terraform's `-var` option. Make sure to replace `$MYPROJECT` with your | ||
GCP project ID. | ||
|
||
```console | ||
$ terraform init | ||
$ terraform apply -var project_id=$MYPROJECT | ||
[Output omitted] | ||
Apply complete! Resources: 13 added, 0 changed, 0 destroyed. | ||
|
||
Outputs: | ||
|
||
ilb_ip = "10.0.1.5" | ||
``` | ||
|
||
After the apply completes, terraform will output the IP address of the load | ||
balancer. You can connect to the test instance and use curl to test | ||
the load balancer. You should see an output similar to this: | ||
```console | ||
user@local:~$ gcloud compute ssh --tunnel-through-iap vm-test | ||
Last login: xxxx | ||
user@vm-test:~$ curl 10.0.1.5 | ||
<pre> | ||
Name: vm-snv1.europe-west1-c.c.$MYPROJECT.internal | ||
IP: 10.0.1.4 | ||
Metadata: { | ||
"created-by": "projects/xxxx/regions/europe-west1/instanceGroupManagers/mig", | ||
"instance-template": "projects/xxxx/global/instanceTemplates/mig-template-20210518224515151200000001" | ||
} | ||
</pre> | ||
user@vm-test:~$ curl 10.0.1.5 | ||
<pre> | ||
Name: vm-tjg7.europe-west1-b.c.$MYPROJECT.internal | ||
IP: 10.0.1.3 | ||
Metadata: { | ||
"created-by": "projects/xxxx/regions/europe-west1/instanceGroupManagers/mig", | ||
"instance-template": "projects/xxxx/global/instanceTemplates/mig-template-20210518224515151200000001" | ||
} | ||
</pre> | ||
jccb@vm-test:~$ | ||
``` | ||
|
||
After you're finished, you can destroy all resources with `terraform destroy`. | ||
|
||
<!-- BEGIN TFDOC --> | ||
## Variables | ||
|
||
| name | description | type | required | default | | ||
|---|---|:---: |:---:|:---:| | ||
| project_id | Project where resources will be created | <code title="">string</code> | ✓ | | | ||
| *ranges* | CIDR ranges for proxy and backend instances | <code title="object({ proxy = string backend = string })">object({...})</code> | | <code title="{ proxy = "10.0.0.0/24" backend = "10.0.1.0/24" }">...</code> | | ||
| *region* | Default region for resources | <code title="">string</code> | | <code title="">europe-west1</code> | | ||
|
||
## Outputs | ||
|
||
| name | description | sensitive | | ||
|---|---|:---:| | ||
| ilb_ip | IP of the internal load balancer | | | ||
<!-- END TFDOC --> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
# Copyright 2021 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. | ||
|
||
# VPC | ||
resource "google_compute_network" "default" { | ||
provider = google-beta | ||
project = var.project_id | ||
name = "ilb-network" | ||
auto_create_subnetworks = false | ||
} | ||
|
||
# proxy only subnet | ||
resource "google_compute_subnetwork" "proxy" { | ||
provider = google-beta | ||
project = var.project_id | ||
name = "lb" | ||
ip_cidr_range = var.ranges.proxy | ||
region = var.region | ||
purpose = "INTERNAL_HTTPS_LOAD_BALANCER" | ||
role = "ACTIVE" | ||
network = google_compute_network.default.id | ||
} | ||
|
||
# backed subnet | ||
resource "google_compute_subnetwork" "default" { | ||
provider = google-beta | ||
project = var.project_id | ||
name = "backend" | ||
ip_cidr_range = var.ranges.backend | ||
region = var.region | ||
network = google_compute_network.default.id | ||
} | ||
|
||
# forwarding rule | ||
resource "google_compute_forwarding_rule" "default" { | ||
provider = google-beta | ||
project = var.project_id | ||
region = var.region | ||
depends_on = [google_compute_subnetwork.proxy] | ||
name = "forwarding-rule" | ||
ip_protocol = "TCP" | ||
load_balancing_scheme = "INTERNAL_MANAGED" | ||
port_range = "80" | ||
target = google_compute_region_target_http_proxy.default.id | ||
network = google_compute_network.default.id | ||
subnetwork = google_compute_subnetwork.default.id | ||
network_tier = "PREMIUM" | ||
} | ||
|
||
# http proxy | ||
resource "google_compute_region_target_http_proxy" "default" { | ||
provider = google-beta | ||
project = var.project_id | ||
region = var.region | ||
name = "proxy" | ||
url_map = google_compute_region_url_map.default.id | ||
} | ||
|
||
# url map | ||
resource "google_compute_region_url_map" "default" { | ||
provider = google-beta | ||
project = var.project_id | ||
region = var.region | ||
name = "map" | ||
default_service = google_compute_region_backend_service.default.id | ||
} | ||
|
||
# backend service | ||
resource "google_compute_region_backend_service" "default" { | ||
provider = google-beta | ||
project = var.project_id | ||
region = var.region | ||
protocol = "HTTP" | ||
name = "backend" | ||
load_balancing_scheme = "INTERNAL_MANAGED" | ||
timeout_sec = 10 | ||
health_checks = [google_compute_region_health_check.default.id] | ||
backend { | ||
group = google_compute_region_instance_group_manager.mig.instance_group | ||
balancing_mode = "UTILIZATION" | ||
capacity_scaler = 1.0 | ||
} | ||
} | ||
|
||
# instance template | ||
resource "google_compute_instance_template" "instance_template" { | ||
provider = google-beta | ||
project = var.project_id | ||
name_prefix = "mig-template-" | ||
machine_type = "e2-small" | ||
tags = ["http-server"] | ||
|
||
network_interface { | ||
network = google_compute_network.default.id | ||
subnetwork = google_compute_subnetwork.default.id | ||
access_config { | ||
# add external ip to fetch packages | ||
} | ||
} | ||
disk { | ||
source_image = "debian-cloud/debian-10" | ||
auto_delete = true | ||
boot = true | ||
} | ||
|
||
# install nginx and serve a simple web page | ||
metadata = { | ||
startup-script = <<-EOF1 | ||
#! /bin/bash | ||
set -euo pipefail | ||
export DEBIAN_FRONTEND=noninteractive | ||
apt-get update | ||
apt-get install -y nginx-light jq | ||
NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") | ||
IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") | ||
METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') | ||
cat <<EOF > /var/www/html/index.html | ||
<pre> | ||
Name: $NAME | ||
IP: $IP | ||
Metadata: $METADATA | ||
</pre> | ||
EOF | ||
EOF1 | ||
} | ||
lifecycle { | ||
create_before_destroy = true | ||
} | ||
} | ||
|
||
# health check | ||
resource "google_compute_region_health_check" "default" { | ||
provider = google-beta | ||
project = var.project_id | ||
region = var.region | ||
name = "hc" | ||
http_health_check { | ||
port_specification = "USE_SERVING_PORT" | ||
} | ||
} | ||
|
||
# MIG | ||
resource "google_compute_region_instance_group_manager" "mig" { | ||
provider = google-beta | ||
project = var.project_id | ||
region = var.region | ||
name = "mig" | ||
version { | ||
instance_template = google_compute_instance_template.instance_template.id | ||
name = "primary" | ||
} | ||
base_instance_name = "vm" | ||
target_size = 2 | ||
} | ||
|
||
# allow all access from IAP and health check ranges | ||
resource "google_compute_firewall" "fw-iap" { | ||
provider = google-beta | ||
project = var.project_id | ||
name = "allow-iap-hc" | ||
direction = "INGRESS" | ||
network = google_compute_network.default.id | ||
source_ranges = ["130.211.0.0/22", "35.191.0.0/16", "35.235.240.0/20"] | ||
allow { | ||
protocol = "tcp" | ||
} | ||
} | ||
|
||
# allow http from proxy subnet to backends | ||
resource "google_compute_firewall" "fw-ilb-to-backends" { | ||
provider = google-beta | ||
project = var.project_id | ||
name = "allow-ilb-to-backends" | ||
direction = "INGRESS" | ||
network = google_compute_network.default.id | ||
source_ranges = [var.ranges.proxy] | ||
target_tags = ["http-server"] | ||
allow { | ||
protocol = "tcp" | ||
ports = ["80", "443", "8080"] | ||
} | ||
} | ||
|
||
# test instance | ||
resource "google_compute_instance" "vm-test" { | ||
provider = google-beta | ||
project = var.project_id | ||
zone = "${var.region}-b" | ||
name = "vm-test" | ||
machine_type = "e2-small" | ||
network_interface { | ||
network = google_compute_network.default.id | ||
subnetwork = google_compute_subnetwork.default.id | ||
} | ||
boot_disk { | ||
initialize_params { | ||
image = "debian-cloud/debian-10" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Copyright 2021 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. | ||
|
||
output "ilb_ip" { | ||
description = "IP of the internal load balancer" | ||
value = google_compute_forwarding_rule.default.ip_address | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Copyright 2021 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_id" { | ||
description = "Project where resources will be created" | ||
type = string | ||
} | ||
|
||
variable "region" { | ||
description = "Default region for resources" | ||
type = string | ||
default = "europe-west1" | ||
} | ||
|
||
variable "ranges" { | ||
description = "CIDR ranges for proxy and backend instances" | ||
type = object({ | ||
proxy = string | ||
backend = string | ||
}) | ||
default = { | ||
proxy = "10.0.0.0/24" | ||
backend = "10.0.1.0/24" | ||
} | ||
} |