From f62b9362a22be6e8996eb197fa8e6631d0501cf5 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sat, 15 Aug 2020 10:12:43 +0200 Subject: [PATCH] ILB for appliances example (#122) * rename infrastructure folder to networking * example WIP: VPCs * move ip forwarding to its own variable in compute-vm module * add per-instance metadata support to compute-vm module * ipip tunnels on linux savepoint * simple multinic gateways example * remove stale files * resolve conflicts * update diagram * rename folder * use a template for gw cloud config, rename some resources and files * Update README.md * Update README.md * add basic plan tests for all networking e2e examples * fix test for foundations/environments e2e example * fix shared vpc e2 example count error in gke node service account permissions * use module path for assets in onprem e2e example * use project id from module in ilb e2e example * add mising boilerplates in tests * run examples tests in ci * update module's README * rename ilb example * Update README.md * fix rp_filter configuration * README * Update README.md * Update README.md * Update README.md * update CHANGELOG * update CHANGELOG * Update README.md --- .ci/cloudbuild.test.yaml | 10 ++ CHANGELOG.md | 9 +- README.md | 9 +- modules/compute-vm/README.md | 4 +- modules/compute-vm/main.tf | 8 +- modules/compute-vm/variables.tf | 14 ++- modules/vpc-sc/README.md | 4 +- {infrastructure => networking}/README.md | 6 + .../hub-and-spoke-peering/README.md | 0 .../hub-and-spoke-peering/backend.tf.sample | 0 .../hub-and-spoke-peering/diagram-network.png | Bin .../hub-and-spoke-peering/diagram.png | Bin .../hub-and-spoke-peering/main.tf | 0 .../hub-and-spoke-peering/outputs.tf | 0 .../hub-and-spoke-peering/variables.tf | 0 .../hub-and-spoke-peering/versions.tf | 0 .../hub-and-spoke-vpn/README.md | 0 .../hub-and-spoke-vpn/backend.tf.sample | 0 .../hub-and-spoke-vpn/diagram.png | Bin .../hub-and-spoke-vpn/main.tf | 0 .../hub-and-spoke-vpn/outputs.tf | 0 .../hub-and-spoke-vpn/provider.tf | 0 .../hub-and-spoke-vpn/variables.tf | 0 networking/ilb-next-hop/README.md | 79 +++++++++++++ networking/ilb-next-hop/assets/gw.yaml | 72 ++++++++++++ networking/ilb-next-hop/backend.tf.sample | 20 ++++ networking/ilb-next-hop/diagram.png | Bin 0 -> 89752 bytes networking/ilb-next-hop/gateways.tf | 106 ++++++++++++++++++ networking/ilb-next-hop/main.tf | 64 +++++++++++ networking/ilb-next-hop/outputs.tf | 20 ++++ networking/ilb-next-hop/test_session.png | Bin 0 -> 32934 bytes networking/ilb-next-hop/variables.tf | 59 ++++++++++ networking/ilb-next-hop/versions.tf | 17 +++ networking/ilb-next-hop/vms.tf | 73 ++++++++++++ networking/ilb-next-hop/vpc-left.tf | 55 +++++++++ networking/ilb-next-hop/vpc-right.tf | 69 ++++++++++++ .../onprem-google-access-dns/README.md | 0 .../onprem-google-access-dns/assets/Corefile | 0 .../backend.tf.sample | 0 .../onprem-google-access-dns/diagram.png | Bin .../onprem-google-access-dns/main.tf | 2 +- .../onprem-google-access-dns/outputs.tf | 0 .../onprem-google-access-dns/variables.tf | 0 .../onprem-google-access-dns/versions.tf | 0 .../shared-vpc-gke/README.md | 35 ++---- .../shared-vpc-gke/backend.tf.sample | 0 .../shared-vpc-gke/diagram.gcpdraw | 0 .../shared-vpc-gke/diagram.png | Bin .../shared-vpc-gke/main.tf | 32 +++--- .../shared-vpc-gke/outputs.tf | 0 .../shared-vpc-gke/variables.tf | 0 .../shared-vpc-gke/versions.tf | 0 tests/conftest.py | 21 +++- .../foundations/environments/fixture/main.tf | 4 +- .../environments/fixture/variables.tf | 12 +- tests/modules/compute_vm/fixture/main.tf | 2 + tests/modules/compute_vm/fixture/variables.tf | 10 ++ .../modules/compute_vm/test_plan_metadata.py | 34 ++++++ tests/networking/__init__.py | 13 +++ .../hub_and_spoke_peering/__init__.py | 13 +++ .../hub_and_spoke_peering/fixture/main.tf | 20 ++++ .../fixture/variables.tf | 18 +++ .../hub_and_spoke_peering/test_plan.py | 27 +++++ .../networking/hub_and_spoke_vpn/__init__.py | 13 +++ .../hub_and_spoke_vpn/fixture/main.tf | 20 ++++ .../hub_and_spoke_vpn/fixture/variables.tf | 18 +++ .../networking/hub_and_spoke_vpn/test_plan.py | 27 +++++ tests/networking/ilb_next_hop/__init__.py | 13 +++ tests/networking/ilb_next_hop/fixture/main.tf | 21 ++++ .../ilb_next_hop/fixture/variables.tf | 23 ++++ tests/networking/ilb_next_hop/test_plan.py | 27 +++++ .../onprem_google_access_dns/__init__.py | 13 +++ .../onprem_google_access_dns/fixture/main.tf | 20 ++++ .../fixture/variables.tf | 18 +++ .../onprem_google_access_dns/test_plan.py | 27 +++++ tests/networking/shared_vpc_gke/__init__.py | 13 +++ .../networking/shared_vpc_gke/fixture/main.tf | 22 ++++ .../shared_vpc_gke/fixture/variables.tf | 28 +++++ tests/networking/shared_vpc_gke/test_plan.py | 30 +++++ tests/requirements.txt | 2 +- 80 files changed, 1201 insertions(+), 75 deletions(-) rename {infrastructure => networking}/README.md (86%) rename {infrastructure => networking}/hub-and-spoke-peering/README.md (100%) rename {infrastructure => networking}/hub-and-spoke-peering/backend.tf.sample (100%) rename {infrastructure => networking}/hub-and-spoke-peering/diagram-network.png (100%) rename {infrastructure => networking}/hub-and-spoke-peering/diagram.png (100%) rename {infrastructure => networking}/hub-and-spoke-peering/main.tf (100%) rename {infrastructure => networking}/hub-and-spoke-peering/outputs.tf (100%) rename {infrastructure => networking}/hub-and-spoke-peering/variables.tf (100%) rename {infrastructure => networking}/hub-and-spoke-peering/versions.tf (100%) rename {infrastructure => networking}/hub-and-spoke-vpn/README.md (100%) rename {infrastructure => networking}/hub-and-spoke-vpn/backend.tf.sample (100%) rename {infrastructure => networking}/hub-and-spoke-vpn/diagram.png (100%) rename {infrastructure => networking}/hub-and-spoke-vpn/main.tf (100%) rename {infrastructure => networking}/hub-and-spoke-vpn/outputs.tf (100%) rename {infrastructure => networking}/hub-and-spoke-vpn/provider.tf (100%) rename {infrastructure => networking}/hub-and-spoke-vpn/variables.tf (100%) create mode 100644 networking/ilb-next-hop/README.md create mode 100644 networking/ilb-next-hop/assets/gw.yaml create mode 100644 networking/ilb-next-hop/backend.tf.sample create mode 100644 networking/ilb-next-hop/diagram.png create mode 100644 networking/ilb-next-hop/gateways.tf create mode 100644 networking/ilb-next-hop/main.tf create mode 100644 networking/ilb-next-hop/outputs.tf create mode 100644 networking/ilb-next-hop/test_session.png create mode 100644 networking/ilb-next-hop/variables.tf create mode 100644 networking/ilb-next-hop/versions.tf create mode 100644 networking/ilb-next-hop/vms.tf create mode 100644 networking/ilb-next-hop/vpc-left.tf create mode 100644 networking/ilb-next-hop/vpc-right.tf rename {infrastructure => networking}/onprem-google-access-dns/README.md (100%) rename {infrastructure => networking}/onprem-google-access-dns/assets/Corefile (100%) rename {infrastructure => networking}/onprem-google-access-dns/backend.tf.sample (100%) rename {infrastructure => networking}/onprem-google-access-dns/diagram.png (100%) rename {infrastructure => networking}/onprem-google-access-dns/main.tf (99%) rename {infrastructure => networking}/onprem-google-access-dns/outputs.tf (100%) rename {infrastructure => networking}/onprem-google-access-dns/variables.tf (100%) rename {infrastructure => networking}/onprem-google-access-dns/versions.tf (100%) rename {infrastructure => networking}/shared-vpc-gke/README.md (78%) rename {infrastructure => networking}/shared-vpc-gke/backend.tf.sample (100%) rename {infrastructure => networking}/shared-vpc-gke/diagram.gcpdraw (100%) rename {infrastructure => networking}/shared-vpc-gke/diagram.png (100%) rename {infrastructure => networking}/shared-vpc-gke/main.tf (92%) rename {infrastructure => networking}/shared-vpc-gke/outputs.tf (100%) rename {infrastructure => networking}/shared-vpc-gke/variables.tf (100%) rename {infrastructure => networking}/shared-vpc-gke/versions.tf (100%) create mode 100644 tests/modules/compute_vm/test_plan_metadata.py create mode 100644 tests/networking/__init__.py create mode 100644 tests/networking/hub_and_spoke_peering/__init__.py create mode 100644 tests/networking/hub_and_spoke_peering/fixture/main.tf create mode 100644 tests/networking/hub_and_spoke_peering/fixture/variables.tf create mode 100644 tests/networking/hub_and_spoke_peering/test_plan.py create mode 100644 tests/networking/hub_and_spoke_vpn/__init__.py create mode 100644 tests/networking/hub_and_spoke_vpn/fixture/main.tf create mode 100644 tests/networking/hub_and_spoke_vpn/fixture/variables.tf create mode 100644 tests/networking/hub_and_spoke_vpn/test_plan.py create mode 100644 tests/networking/ilb_next_hop/__init__.py create mode 100644 tests/networking/ilb_next_hop/fixture/main.tf create mode 100644 tests/networking/ilb_next_hop/fixture/variables.tf create mode 100644 tests/networking/ilb_next_hop/test_plan.py create mode 100644 tests/networking/onprem_google_access_dns/__init__.py create mode 100644 tests/networking/onprem_google_access_dns/fixture/main.tf create mode 100644 tests/networking/onprem_google_access_dns/fixture/variables.tf create mode 100644 tests/networking/onprem_google_access_dns/test_plan.py create mode 100644 tests/networking/shared_vpc_gke/__init__.py create mode 100644 tests/networking/shared_vpc_gke/fixture/main.tf create mode 100644 tests/networking/shared_vpc_gke/fixture/variables.tf create mode 100644 tests/networking/shared_vpc_gke/test_plan.py diff --git a/.ci/cloudbuild.test.yaml b/.ci/cloudbuild.test.yaml index d248a3cb2..26f70ec0d 100644 --- a/.ci/cloudbuild.test.yaml +++ b/.ci/cloudbuild.test.yaml @@ -35,6 +35,16 @@ steps: env: - PATH=/usr/local/bin:/usr/bin:/bin:/builder/home/.local/bin - TF_CLI_CONFIG_FILE=/workspace/.ci/.terraformrc + - name: python:3-alpine + id: test-environments + entrypoint: pytest + args: + - -v + - tests/foundations + - tests/networking + env: + - PATH=/usr/local/bin:/usr/bin:/bin:/builder/home/.local/bin + - TF_CLI_CONFIG_FILE=/workspace/.ci/.terraformrc substitutions: _TERRAFORM_VERSION: 0.12.20 diff --git a/CHANGELOG.md b/CHANGELOG.md index 53bd94fab..168990b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [3.0.0] - 2020-08-15 + +- **incompatible change** the top-level `infrastructure` folder has been renamed to `networking` +- add end-to-end example for ILB as next hop +- add basic tests for `foundations` and `networking` end-to-end examples + ## [2.8.0] - 2020-08-01 - fine-grained Cloud DNS IAM via Service Directory example @@ -156,7 +162,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.8.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v3.0.0...HEAD +[3.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.8.0...v3.0.0 [2.8.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.7.1...v2.8.0 [2.7.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.7.0...v2.7.1 [2.7.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.6.0...v2.7.0 diff --git a/README.md b/README.md index 889ab07e9..b541bfcf2 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ This repository provides **end-to-end examples** and a **suite of Terraform modules** for Google Cloud, which support different use cases: -- starter kits used to bootstrap real-world cloud foundations and infrastructure -- reference examples used to deep dive on network patterns or product features +- starter kits used to bootstrap real-world cloud foundations, and reference examples used to deep dive on network patterns or product features - composable modules that support quick prototyping and testing - a comprehensive source of lean modules that lend themselves well to changes @@ -13,16 +12,16 @@ Both the examples and modules require some measure of Terraform skills to be use ## End-to-end examples -The examples in this repository are split in two main sections: **foundational examples** that bootstrap the organizational hierarchy and automation prerequisites, and **infrastructure scenarios** that implement core networking patterns or features. +The examples in this repository are split in several main sections: **foundational examples** that bootstrap the organizational hierarchy and automation prerequisites, **networking examples** that implement core patterns or features, **data solutions examples** that demonstrate how to integrate data services in complete scenarios, and **cloud operations examples** that leverage specific products to meet specific operational needs. Currently available examples: - **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments) -- **infrastructure** - [hub and spoke via peering](./infrastructure/hub-and-spoke-peering/), [hub and spoke via VPN](./infrastructure/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./infrastructure/onprem-google-access-dns/), [Shared VPC with GKE support](./infrastructure/shared-vpc-gke/) +- **networking** - [hub and spoke via peering](./networking/hub-and-spoke-peering/), [hub and spoke via VPN](./networking/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./networking/onprem-google-access-dns/), [Shared VPC with GKE support](./networking/shared-vpc-gke/), [ILB as next hop](./networking/ilb-next-hop) - **data solutions** - [GCE/GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/), [Cloud Storage to Bigquery with Cloud Dataflow](./data-solutions/gcs-to-bq-with-dataflow/) - **cloud operations** - [Resource tracking and remediation via Cloud Asset feeds](.//cloud-operations/asset-inventory-feed-remediation), [Granular Cloud DNS IAM via Service Directory](./cloud-operations/dns-fine-grained-iam) -For more information see the README files in the [foundations](./foundations/), [infrastructure](./infrastructure/), [data solutions](./data-solutions/) and [cloud operations](./cloud-operations/) folders. +For more information see the README files in the [foundations](./foundations/), [networking](./networking/), [data solutions](./data-solutions/) and [cloud operations](./cloud-operations/) folders. ## Modules diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md index 065e1fde1..128087c07 100644 --- a/modules/compute-vm/README.md +++ b/modules/compute-vm/README.md @@ -147,6 +147,7 @@ module "instance-group" { | *attached_disk_defaults* | Defaults for attached disks options. | object({...}) | | ... | | *attached_disks* | Additional disks, if options is null defaults will be used in its place. | list(object({...})) | | [] | | *boot_disk* | Boot disk properties. | object({...}) | | ... | +| *can_ip_forward* | Enable IP forwarding. | bool | | false | | *encryption* | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({...}) | | null | | *group* | Define this variable to create an instance group for instances. Disabled for template use. | object({...}) | | null | | *hostname* | Instance FQDN name. | string | | null | @@ -156,8 +157,9 @@ module "instance-group" { | *instance_type* | Instance type. | string | | f1-micro | | *labels* | Instance labels. | map(string) | | {} | | *metadata* | Instance metadata. | map(string) | | {} | +| *metadata_list* | List of instance metadata that will be cycled through. Ignored for template use. | list(map(string)) | | [] | | *min_cpu_platform* | Minimum CPU platform. | string | | null | -| *options* | Instance options. | object({...}) | | ... | +| *options* | Instance options. | object({...}) | | ... | | *scratch_disks* | Scratch disks configuration. | object({...}) | | ... | | *service_account* | Service account email. Unused if service account is auto-created. | string | | null | | *service_account_create* | Auto-create service account. | bool | | false | diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index 4f69eb283..834a1a602 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -94,11 +94,13 @@ resource "google_compute_instance" "default" { tags = var.tags machine_type = var.instance_type min_cpu_platform = var.min_cpu_platform - can_ip_forward = var.options.can_ip_forward + can_ip_forward = var.can_ip_forward allow_stopping_for_update = var.options.allow_stopping_for_update deletion_protection = var.options.deletion_protection - metadata = var.metadata labels = var.labels + metadata = merge( + var.metadata, try(element(var.metadata_list, each.value), {}) + ) dynamic attached_disk { for_each = { @@ -199,7 +201,7 @@ resource "google_compute_instance_template" "default" { tags = var.tags machine_type = var.instance_type min_cpu_platform = var.min_cpu_platform - can_ip_forward = var.options.can_ip_forward + can_ip_forward = var.can_ip_forward metadata = var.metadata labels = var.labels diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf index fc81797fe..61b3508d3 100644 --- a/modules/compute-vm/variables.tf +++ b/modules/compute-vm/variables.tf @@ -60,6 +60,12 @@ variable "boot_disk" { } } +variable "can_ip_forward" { + description = "Enable IP forwarding." + type = bool + default = false +} + variable "encryption" { description = "Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk." type = object({ @@ -120,6 +126,12 @@ variable "metadata" { default = {} } +variable "metadata_list" { + description = "List of instance metadata that will be cycled through. Ignored for template use." + type = list(map(string)) + default = [] +} + variable "min_cpu_platform" { description = "Minimum CPU platform." type = string @@ -148,13 +160,11 @@ variable "options" { description = "Instance options." type = object({ allow_stopping_for_update = bool - can_ip_forward = bool deletion_protection = bool preemptible = bool }) default = { allow_stopping_for_update = true - can_ip_forward = false deletion_protection = false preemptible = false } diff --git a/modules/vpc-sc/README.md b/modules/vpc-sc/README.md index 5840e58fc..18d35f039 100644 --- a/modules/vpc-sc/README.md +++ b/modules/vpc-sc/README.md @@ -97,9 +97,9 @@ module "vpc-sc" { | access_policy_title | Access Policy title to be created. | string | ✓ | | | org_id | Organization id in nnnnnn format. | number | ✓ | | | *access_level_perimeters* | Enforced mode -> Access Level -> Perimeters mapping. Enforced mode can be 'enforced' or 'dry_run' | map(map(list(string))) | | {} | -| *access_levels* | Access Levels. | map(object({...})) | | {} | +| *access_levels* | Access Levels. | map(object({...})) | | {} | | *perimeter_projects* | Perimeter -> Enforced Mode -> Projects Number mapping. Enforced mode can be 'enforced' or 'dry_run'. | map(map(list(number))) | | {} | -| *perimeters* | Set of Perimeters. | map(object({...})) | | {} | +| *perimeters* | Set of Perimeters. | map(object({...})) | | {} | ## Outputs diff --git a/infrastructure/README.md b/networking/README.md similarity index 86% rename from infrastructure/README.md rename to networking/README.md index 2bbc9ba63..56f403fe2 100644 --- a/infrastructure/README.md +++ b/networking/README.md @@ -28,6 +28,12 @@ The emulated on-premises environment can be used to test access to different ser
### Shared VPC with GKE and per-subnet support + This [example](./shared-vpc-gke/) shows how to configure a Shared VPC, including the specific IAM configurations needed for GKE, and to give different level of access to the VPC subnets to different identities. It is meant to be used as a starting point for most Shared VPC configurations, and to be integrated to the above examples where Shared VPC is needed in more complex network topologies. +
+ +### ILB as next hop + + This [example](./ilb-next-hop/) allows testing [ILB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview) using simple Linux gateway VMS between two VPCs, to emulate virtual appliances. An optional additional ILB can be enabled to test multiple load balancer configurations and hashing. diff --git a/infrastructure/hub-and-spoke-peering/README.md b/networking/hub-and-spoke-peering/README.md similarity index 100% rename from infrastructure/hub-and-spoke-peering/README.md rename to networking/hub-and-spoke-peering/README.md diff --git a/infrastructure/hub-and-spoke-peering/backend.tf.sample b/networking/hub-and-spoke-peering/backend.tf.sample similarity index 100% rename from infrastructure/hub-and-spoke-peering/backend.tf.sample rename to networking/hub-and-spoke-peering/backend.tf.sample diff --git a/infrastructure/hub-and-spoke-peering/diagram-network.png b/networking/hub-and-spoke-peering/diagram-network.png similarity index 100% rename from infrastructure/hub-and-spoke-peering/diagram-network.png rename to networking/hub-and-spoke-peering/diagram-network.png diff --git a/infrastructure/hub-and-spoke-peering/diagram.png b/networking/hub-and-spoke-peering/diagram.png similarity index 100% rename from infrastructure/hub-and-spoke-peering/diagram.png rename to networking/hub-and-spoke-peering/diagram.png diff --git a/infrastructure/hub-and-spoke-peering/main.tf b/networking/hub-and-spoke-peering/main.tf similarity index 100% rename from infrastructure/hub-and-spoke-peering/main.tf rename to networking/hub-and-spoke-peering/main.tf diff --git a/infrastructure/hub-and-spoke-peering/outputs.tf b/networking/hub-and-spoke-peering/outputs.tf similarity index 100% rename from infrastructure/hub-and-spoke-peering/outputs.tf rename to networking/hub-and-spoke-peering/outputs.tf diff --git a/infrastructure/hub-and-spoke-peering/variables.tf b/networking/hub-and-spoke-peering/variables.tf similarity index 100% rename from infrastructure/hub-and-spoke-peering/variables.tf rename to networking/hub-and-spoke-peering/variables.tf diff --git a/infrastructure/hub-and-spoke-peering/versions.tf b/networking/hub-and-spoke-peering/versions.tf similarity index 100% rename from infrastructure/hub-and-spoke-peering/versions.tf rename to networking/hub-and-spoke-peering/versions.tf diff --git a/infrastructure/hub-and-spoke-vpn/README.md b/networking/hub-and-spoke-vpn/README.md similarity index 100% rename from infrastructure/hub-and-spoke-vpn/README.md rename to networking/hub-and-spoke-vpn/README.md diff --git a/infrastructure/hub-and-spoke-vpn/backend.tf.sample b/networking/hub-and-spoke-vpn/backend.tf.sample similarity index 100% rename from infrastructure/hub-and-spoke-vpn/backend.tf.sample rename to networking/hub-and-spoke-vpn/backend.tf.sample diff --git a/infrastructure/hub-and-spoke-vpn/diagram.png b/networking/hub-and-spoke-vpn/diagram.png similarity index 100% rename from infrastructure/hub-and-spoke-vpn/diagram.png rename to networking/hub-and-spoke-vpn/diagram.png diff --git a/infrastructure/hub-and-spoke-vpn/main.tf b/networking/hub-and-spoke-vpn/main.tf similarity index 100% rename from infrastructure/hub-and-spoke-vpn/main.tf rename to networking/hub-and-spoke-vpn/main.tf diff --git a/infrastructure/hub-and-spoke-vpn/outputs.tf b/networking/hub-and-spoke-vpn/outputs.tf similarity index 100% rename from infrastructure/hub-and-spoke-vpn/outputs.tf rename to networking/hub-and-spoke-vpn/outputs.tf diff --git a/infrastructure/hub-and-spoke-vpn/provider.tf b/networking/hub-and-spoke-vpn/provider.tf similarity index 100% rename from infrastructure/hub-and-spoke-vpn/provider.tf rename to networking/hub-and-spoke-vpn/provider.tf diff --git a/infrastructure/hub-and-spoke-vpn/variables.tf b/networking/hub-and-spoke-vpn/variables.tf similarity index 100% rename from infrastructure/hub-and-spoke-vpn/variables.tf rename to networking/hub-and-spoke-vpn/variables.tf diff --git a/networking/ilb-next-hop/README.md b/networking/ilb-next-hop/README.md new file mode 100644 index 000000000..978138b1f --- /dev/null +++ b/networking/ilb-next-hop/README.md @@ -0,0 +1,79 @@ +# Internal Load Balancer as Next Hop + +This example bootstraps a minimal infrastructure for testing [ILB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview), using simple Linux gateway VMS between two VPCs to emulate virtual appliances. + +The following diagram shows the resources created by this example + +![High-level diagram](diagram.png "High-level diagram") + +Two ILBs are configured on the primary and secondary interfaces of gateway VMs with active health checks, but only the single one is used as next hop by default to simplify testing. The second (right-side) VPC has default routes that point to the gateway VMs, to also use the right-side ILB as next hop set the `ilb_right_enable` variable to `true`. + +## Testing + +Since ILBs as next hops only forward TCP and UDP traffic, simple tests use `curl` on clients to send HTTP requests. To make this practical, test VMs on both VPCs have `nginx` pre-installed and active on port 80. + +On the gateways, `iftop` is installed by default to quickly monitor traffic passing forwarded across VPCs. + +Session affinity on the ILB backend services can be changed using `gcloud compute backend-services update` on each of the ILBs, or by setting the `ilb_session_affinity` variable to update both ILBs. + +Simple `/root/start.sh` and `/root/stop.sh` scripts are pre-installed on both gateways to configure `iptables` so that health check requests are rejected and re-enabled, to quickly simulate removing instances from the ILB backends. + +Some scenarios to test: + +- short-lived connections with session affinity set to the default of `NONE`, then to `CLIENT_IP` +- long-lived connections, failing health checks on the active gateway while the connection is active + +### Useful commands (adjust names and addresses to match) + +Create a large file on a destination VM (eg `ilb-test-vm-right-1`) to test long-running connections. + +```bash +dd if=/dev/zero of=/var/www/html/test.txt bs=10M count=100 status=progress +``` + +Run curl from a source VM (eg `ilb-test-vm-left-1`) to send requests to a destination VM artifically slowing traffic. + +``` +curl -0 --output /dev/null --limit-rate 10k 10.0.1.3/test.txt +``` + +Monitor traffic from a source VM (eg `ilb-test-vm-left-1`) on the gateways. + +```bash +iftop -n -F 10.0.0.3/32 +``` + +Poll summary health status for a backend. + +```bash +watch '\ + gcloud compute backend-services get-health ilb-test-ilb-right \ + --region europe-west1 \ + --flatten status.healthStatus \ + --format "value(status.healthStatus.ipAddress, status.healthStatus.healthState)" \ +' +``` + +A sample testing session using `tmux`: + +Test session screenshot + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| project_id | Existing project id. | string | ✓ | | +| *ilb_right_enable* | Route right to left traffic through ILB. | bool | | false | +| *ilb_session_affinity* | Session affinity configuration for ILBs. | string | | CLIENT_IP | +| *ip_ranges* | IP CIDR ranges used for VPC subnets. | map(string) | | ... | +| *prefix* | Prefix used for resource names. | string | | ilb-test | +| *project_create* | Create project instead of using an existing one. | bool | | false | +| *region* | Region used for resources. | string | | europe-west1 | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| addresses | Internal addresses of created VMS. | | + diff --git a/networking/ilb-next-hop/assets/gw.yaml b/networking/ilb-next-hop/assets/gw.yaml new file mode 100644 index 000000000..c24012e97 --- /dev/null +++ b/networking/ilb-next-hop/assets/gw.yaml @@ -0,0 +1,72 @@ +#cloud-config + +# Copyright 2020 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. + +write_files: + - path: /etc/sysctl.conf + permissions: "0644" + owner: root + content: | + net.ipv4.ip_forward = 1 + net.ipv6.conf.all.forwarding = 1 + net.ipv4.conf.all.accept_redirects = 0 + net.ipv4.conf.all.send_redirects = 0 + # https://tldp.org/HOWTO/Adv-Routing-HOWTO/lartc.kernel.rpf.html + net.ipv4.conf.all.rp_filter = 2 + net.ipv4.conf.ens4.rp_filter = 2 + net.ipv4.conf.ens5.rp_filter = 2 + - path: /etc/netplan/99-nic2-routing.yaml + permissions: "0644" + owner: root + content: | + network: + ethernets: + ens5: + dhcp4: true + routes: + - to: 0.0.0.0/0 + via: ${gw_right} + table: 102 + routing-policy: + - from: ${ip_cidr_right} + to: 35.191.0.0/16 + table: 102 + - from: ${ip_cidr_right} + to: 130.211.0.0/22 + table: 102 + version: 2 + - path: /root/start.sh + permissions: "0755" + owner: root + content: | + #!/bin/bash + iptables -D INPUT -s 35.191.0.0/16 -j REJECT + iptables -D INPUT -s 130.211.0.0/22 -j REJECT + - path: /root/stop.sh + permissions: "0755" + owner: root + content: | + #!/bin/bash + iptables -I INPUT -s 35.191.0.0/16 -j REJECT + iptables -I INPUT -s 130.211.0.0/22 -j REJECT +package_update: true +package_upgrade: true +package_reboot_if_required: true +packages: + - iftop + - tcpdump +runcmd: + - sysctl -p + - netplan apply diff --git a/networking/ilb-next-hop/backend.tf.sample b/networking/ilb-next-hop/backend.tf.sample new file mode 100644 index 000000000..a540c7cd1 --- /dev/null +++ b/networking/ilb-next-hop/backend.tf.sample @@ -0,0 +1,20 @@ +# Copyright 2020 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 +# +# https://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. + + +terraform { + backend "gcs" { + bucket = "" + } +} diff --git a/networking/ilb-next-hop/diagram.png b/networking/ilb-next-hop/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..2d19799ccf85b11c409e7f6ffd326d2697510023 GIT binary patch literal 89752 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

cV+%-lfJxX5Lw*huI%s(x{fZUX~M&BW^kW*s@X5 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 literal 0 HcmV?d00001 diff --git a/networking/ilb-next-hop/gateways.tf b/networking/ilb-next-hop/gateways.tf new file mode 100644 index 000000000..7684e1309 --- /dev/null +++ b/networking/ilb-next-hop/gateways.tf @@ -0,0 +1,106 @@ +/** + * Copyright 2020 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. + */ + +module "gw" { + source = "../../modules/compute-vm" + project_id = module.project.project_id + region = var.region + name = "${local.prefix}gw" + instance_type = "f1-micro" + + boot_disk = { + image = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2004-lts", + type = "pd-ssd", + size = 10 + } + + network_interfaces = [ + { + network = module.vpc-left.self_link + subnetwork = values(module.vpc-left.subnet_self_links)[0], + nat = false, + addresses = null + }, + { + network = module.vpc-right.self_link + subnetwork = values(module.vpc-right.subnet_self_links)[0], + nat = false, + addresses = null + } + ] + tags = ["ssh"] + can_ip_forward = true + metadata = { + user-data = templatefile("${path.module}/assets/gw.yaml", { + gw_right = cidrhost(var.ip_ranges.right, 1) + ip_cidr_right = var.ip_ranges.right + }) + } + service_account = try( + module.service-accounts.emails["${local.prefix}gce-vm"], null + ) + service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"] + instance_count = 2 + group = { named_ports = null } +} + +module "ilb-left" { + source = "../../modules/net-ilb" + 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 + } + backends = [{ + failover = false + group = module.gw.group.self_link + balancing_mode = "CONNECTION" + }] + health_check_config = { + type = "tcp", check = { port = 22 }, config = {}, logging = true + } +} + +module "ilb-right" { + source = "../../modules/net-ilb" + 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 + } + backends = [{ + failover = false + group = module.gw.group.self_link + balancing_mode = "CONNECTION" + }] + health_check_config = { + type = "tcp", check = { port = 22 }, config = {}, logging = true + } +} diff --git a/networking/ilb-next-hop/main.tf b/networking/ilb-next-hop/main.tf new file mode 100644 index 000000000..b5ca75d21 --- /dev/null +++ b/networking/ilb-next-hop/main.tf @@ -0,0 +1,64 @@ +/** + * Copyright 2020 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. + */ + +locals { + addresses = { + for k, v in module.addresses.internal_addresses : + trimprefix(k, local.prefix) => v.address + } + prefix = var.prefix == null || var.prefix == "" ? "" : "${var.prefix}-" +} + +module "project" { + source = "../../modules/project" + name = var.project_id + project_create = var.project_create + services = [ + "compute.googleapis.com", + "dns.googleapis.com", + ] + service_config = { + disable_on_destroy = false + disable_dependent_services = false + } +} + +module "service-accounts" { + source = "../../modules/iam-service-accounts" + project_id = module.project.project_id + names = ["${local.prefix}gce-vm"] + iam_project_roles = { + (var.project_id) = [ + "roles/logging.logWriter", + "roles/monitoring.metricWriter", + ] + } +} + +module "addresses" { + source = "../../modules/net-address" + project_id = module.project.project_id + internal_addresses = { + "${local.prefix}ilb-left" = { + region = var.region, + subnetwork = values(module.vpc-left.subnet_self_links)[0] + }, + "${local.prefix}ilb-right" = { + region = var.region, + subnetwork = values(module.vpc-right.subnet_self_links)[0] + } + } +} diff --git a/networking/ilb-next-hop/outputs.tf b/networking/ilb-next-hop/outputs.tf new file mode 100644 index 000000000..9952e1c5a --- /dev/null +++ b/networking/ilb-next-hop/outputs.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2020 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 "addresses" { + description = "Internal addresses of created VMS." + value = null +} diff --git a/networking/ilb-next-hop/test_session.png b/networking/ilb-next-hop/test_session.png new file mode 100644 index 0000000000000000000000000000000000000000..42391b34a03491e30cc003bdf0ac5d491f661e63 GIT binary patch literal 32934 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 H|NMUdZ`NH^ literal 0 HcmV?d00001 diff --git a/networking/ilb-next-hop/variables.tf b/networking/ilb-next-hop/variables.tf new file mode 100644 index 000000000..d68067e4d --- /dev/null +++ b/networking/ilb-next-hop/variables.tf @@ -0,0 +1,59 @@ +/** + * Copyright 2020 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 "ilb_right_enable" { + description = "Route right to left traffic through ILB." + type = bool + default = false +} + +variable "ilb_session_affinity" { + description = "Session affinity configuration for ILBs." + type = string + default = "CLIENT_IP" +} + +variable "ip_ranges" { + description = "IP CIDR ranges used for VPC subnets." + type = map(string) + default = { + left = "10.0.0.0/24" + right = "10.0.1.0/24" + } +} + +variable "prefix" { + description = "Prefix used for resource names." + type = string + default = "ilb-test" +} + +variable "project_create" { + description = "Create project instead of using an existing one." + type = bool + default = false +} + +variable "project_id" { + description = "Existing project id." + type = string +} + +variable "region" { + description = "Region used for resources." + type = string + default = "europe-west1" +} diff --git a/networking/ilb-next-hop/versions.tf b/networking/ilb-next-hop/versions.tf new file mode 100644 index 000000000..92787679e --- /dev/null +++ b/networking/ilb-next-hop/versions.tf @@ -0,0 +1,17 @@ +# Copyright 2019 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 +# +# https://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. + +terraform { + required_version = ">= 0.12.6" +} diff --git a/networking/ilb-next-hop/vms.tf b/networking/ilb-next-hop/vms.tf new file mode 100644 index 000000000..6a8f22a0e --- /dev/null +++ b/networking/ilb-next-hop/vms.tf @@ -0,0 +1,73 @@ +/** + * Copyright 2020 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. + */ + +locals { + vm_startup_script = <=4.6.0 PyYAML>=5.3 -tftest>=1.5.0 +tftest>=1.5.1