Remove stale files

This commit is contained in:
Julio Castillo 2023-06-12 21:23:50 +02:00
parent ff231bd28c
commit bb47615493
2 changed files with 0 additions and 449 deletions

View File

@ -1,119 +0,0 @@
# Hub and Spoke via VPC Peering
This blueprint creates a simple **Hub and Spoke** setup, where the VPC network connects satellite locations (spokes) through a single intermediary location (hub) via [VPC Peering](https://cloud.google.com/vpc/docs/vpc-peering).
The blueprint shows some of the limitations that need to be taken into account when using VPC Peering, mostly due to the lack of transitivity between peerings:
- no mesh networking between the spokes
- complex support for managed services hosted in tenant VPCs connected via peering (Cloud SQL, GKE, etc.)
One possible solution to the managed service limitation above is presented here, using a static VPN to establish connectivity to the GKE masters in the tenant project ([courtesy of @drebes](https://github.com/drebes/tf-samples/blob/master/gke-master-from-hub/main.tf#L10)). Other solutions typically involve the use of proxies, as [described in this GKE article](https://cloud.google.com/kubernetes-engine/docs/archive/creating-kubernetes-engine-private-clusters-with-net-proxies).
One other topic that needs to be considered when using peering is the limit of 25 peerings in each peering group, which constrains the scalability of design like the one presented here.
The blueprint has been purposefully kept simple to show how to use and wire the VPC modules together, and so that it can be used as a basis for more complex scenarios. This is the high level diagram:
![High-level diagram](diagram.png "High-level diagram")
## Managed resources and services
This sample creates several distinct groups of resources:
- one VPC each for hub and each spoke
- one set of firewall rules for each VPC
- one Cloud NAT configuration for each spoke
- one test instance for each spoke
- one GKE cluster with a single nodepool in spoke 2
- one service account for the GCE instances
- one service account for the GKE nodes
- one static VPN gateway in hub and spoke 2 with a single tunnel each
## Testing GKE access from spoke 1
As mentioned above, a VPN tunnel is used as a workaround to avoid the peering transitivity issue that would prevent any VPC other than spoke 2 to connect to the GKE master. This diagram illustrates the solution
![Network-level diagram](diagram-network.png "Network-level diagram")
To test cluster access, first log on to the spoke 2 instance and confirm cluster and IAM roles are set up correctly:
```bash
gcloud container clusters get-credentials cluster-1 --zone europe-west1-b
kubectl get all
```
The blueprint configures the peering with the GKE master VPC to export routes for you, so that VPN routes are passed through the peering. You can disable by hand in the console or by editing the `peering_config` variable in the `gke-cluster` module, to test non-working configurations or switch to using the [GKE proxy](https://cloud.google.com/kubernetes-engine/docs/archive/creating-kubernetes-engine-private-clusters-with-net-proxies).
### Export routes via Terraform (recommended)
Change the GKE cluster module and add a new variable after `private_cluster_config`:
```tfvars
peering_config = {
export_routes = true
import_routes = false
}
```
If you added the variable after applying, simply apply Terraform again.
### Export routes via gcloud (alternative)
If you prefer to use `gcloud` to export routes on the peering, first identify the peering (it has a name like `gke-xxxxxxxxxxxxxxxxxxxx-xxxx-xxxx-peer`) in the Cloud Console from the *VPC network peering* page, or using `gcloud`, then configure it to export routes:
```
gcloud compute networks peerings list
# find the gke-xxxxxxxxxxxxxxxxxxxx-xxxx-xxxx-peer in the spoke-2 network
gcloud compute networks peerings update [peering name from above] \
--network spoke-2 --export-custom-routes
```
### Test routes
Then connect via SSH to the spoke 1 instance and run the same commands you ran on the spoke 2 instance above, you should be able to run `kubectl` commands against the cluster. To test the default situation with no supporting VPN, just comment out the two VPN modules in `main.tf` and run `terraform apply` to bring down the VPN gateways and tunnels. GKE should only become accessible from spoke 2.
## Operational considerations
A single pre-existing project is used in this blueprint to keep variables and complexity to a minimum, in a real world scenario each spoke would use a separate project (and Shared VPC).
A few APIs need to be enabled in the project, if `apply` fails due to a service not being enabled just click on the link in the error message to enable it for the project, then resume `apply`.
The VPN used to connect the GKE masters VPC does not account for HA, upgrading to use HA VPN is reasonably simple by using the relevant [module](../../../modules/net-vpn-ha).
<!-- BEGIN TFDOC -->
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [prefix](variables.tf#L34) | Prefix used for resource names. | <code>string</code> | ✓ | |
| [project_id](variables.tf#L69) | Project id used for all resources. | <code>string</code> | ✓ | |
| [ip_ranges](variables.tf#L15) | IP CIDR ranges. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; hub &#61; &#34;10.0.0.0&#47;24&#34;&#10; spoke-1 &#61; &#34;10.0.16.0&#47;24&#34;&#10; spoke-2 &#61; &#34;10.0.32.0&#47;24&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [ip_secondary_ranges](variables.tf#L25) | Secondary IP CIDR ranges. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; spoke-2-pods &#61; &#34;10.128.0.0&#47;18&#34;&#10; spoke-2-services &#61; &#34;172.16.0.0&#47;24&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [private_service_ranges](variables.tf#L43) | Private service IP CIDR ranges. | <code>map&#40;string&#41;</code> | | <code title="&#123;&#10; spoke-2-cluster-1 &#61; &#34;192.168.0.0&#47;28&#34;&#10;&#125;">&#123;&#8230;&#125;</code> |
| [project_create](variables.tf#L51) | Set to non null if project needs to be created. | <code title="object&#40;&#123;&#10; billing_account &#61; string&#10; oslogin &#61; bool&#10; parent &#61; string&#10;&#125;&#41;">object&#40;&#123;&#8230;&#125;&#41;</code> | | <code>null</code> |
| [region](variables.tf#L74) | VPC region. | <code>string</code> | | <code>&#34;europe-west1&#34;</code> |
## Outputs
| name | description | sensitive |
|---|---|:---:|
| [project](outputs.tf#L15) | Project id. | |
| [vms](outputs.tf#L20) | GCE VMs. | |
<!-- END TFDOC -->
## Test
```hcl
module "test" {
source = "./fabric/blueprints/networking/hub-and-spoke-peering"
prefix = "prefix"
project_create = {
billing_account = "123456-123456-123456"
oslogin = true
parent = "folders/123456789"
}
project_id = "project-1"
}
# tftest modules=22 resources=69
```

View File

@ -1,330 +0,0 @@
# 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
#
# 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.
locals {
vm-instances = [
module.vm-hub.instance,
module.vm-spoke-1.instance,
module.vm-spoke-2.instance
]
vm-startup-script = join("\n", [
"#! /bin/bash",
"apt-get update && apt-get install -y bash-completion dnsutils kubectl"
])
}
###############################################################################
# project #
###############################################################################
module "project" {
source = "../../../modules/project"
project_create = var.project_create != null
billing_account = try(var.project_create.billing_account, null)
oslogin = try(var.project_create.oslogin, false)
parent = try(var.project_create.parent, null)
name = var.project_id
services = [
"compute.googleapis.com",
"container.googleapis.com"
]
}
################################################################################
# Hub networking #
################################################################################
module "vpc-hub" {
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = "${var.prefix}-hub"
subnets = [
{
ip_cidr_range = var.ip_ranges.hub
name = "${var.prefix}-hub-1"
region = var.region
}
]
}
module "nat-hub" {
source = "../../../modules/net-cloudnat"
project_id = module.project.project_id
region = var.region
name = "${var.prefix}-hub"
router_name = "${var.prefix}-hub"
router_network = module.vpc-hub.self_link
}
module "vpc-hub-firewall" {
source = "../../../modules/net-vpc-firewall"
project_id = var.project_id
network = module.vpc-hub.name
default_rules_config = {
admin_ranges = values(var.ip_ranges)
}
}
################################################################################
# Spoke 1 networking #
################################################################################
module "vpc-spoke-1" {
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = "${var.prefix}-spoke-1"
subnets = [
{
ip_cidr_range = var.ip_ranges.spoke-1
name = "${var.prefix}-spoke-1-1"
region = var.region
}
]
}
module "vpc-spoke-1-firewall" {
source = "../../../modules/net-vpc-firewall"
project_id = module.project.project_id
network = module.vpc-spoke-1.name
default_rules_config = {
admin_ranges = values(var.ip_ranges)
}
}
module "nat-spoke-1" {
source = "../../../modules/net-cloudnat"
project_id = module.project.project_id
region = var.region
name = "${var.prefix}-spoke-1"
router_name = "${var.prefix}-spoke-1"
router_network = module.vpc-spoke-1.self_link
}
module "hub-to-spoke-1-peering" {
source = "../../../modules/net-vpc-peering"
local_network = module.vpc-hub.self_link
peer_network = module.vpc-spoke-1.self_link
export_local_custom_routes = true
export_peer_custom_routes = false
}
################################################################################
# Spoke 2 networking #
################################################################################
module "vpc-spoke-2" {
source = "../../../modules/net-vpc"
project_id = module.project.project_id
name = "${var.prefix}-spoke-2"
subnets = [
{
ip_cidr_range = var.ip_ranges.spoke-2
name = "${var.prefix}-spoke-2-1"
region = var.region
secondary_ip_ranges = {
pods = var.ip_secondary_ranges.spoke-2-pods
services = var.ip_secondary_ranges.spoke-2-services
}
}
]
}
module "vpc-spoke-2-firewall" {
source = "../../../modules/net-vpc-firewall"
project_id = module.project.project_id
network = module.vpc-spoke-2.name
default_rules_config = {
admin_ranges = values(var.ip_ranges)
}
}
module "nat-spoke-2" {
source = "../../../modules/net-cloudnat"
project_id = module.project.project_id
region = var.region
name = "${var.prefix}-spoke-2"
router_name = "${var.prefix}-spoke-2"
router_network = module.vpc-spoke-2.self_link
}
module "hub-to-spoke-2-peering" {
source = "../../../modules/net-vpc-peering"
local_network = module.vpc-hub.self_link
peer_network = module.vpc-spoke-2.self_link
export_local_custom_routes = true
export_peer_custom_routes = false
depends_on = [module.hub-to-spoke-1-peering]
}
################################################################################
# Test VMs #
################################################################################
module "vm-hub" {
source = "../../../modules/compute-vm"
project_id = module.project.project_id
zone = "${var.region}-b"
name = "${var.prefix}-hub"
network_interfaces = [{
network = module.vpc-hub.self_link
subnetwork = module.vpc-hub.subnet_self_links["${var.region}/${var.prefix}-hub-1"]
nat = false
addresses = null
}]
metadata = { startup-script = local.vm-startup-script }
service_account = module.service-account-gce.email
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
tags = ["ssh"]
}
module "vm-spoke-1" {
source = "../../../modules/compute-vm"
project_id = module.project.project_id
zone = "${var.region}-b"
name = "${var.prefix}-spoke-1"
network_interfaces = [{
network = module.vpc-spoke-1.self_link
subnetwork = module.vpc-spoke-1.subnet_self_links["${var.region}/${var.prefix}-spoke-1-1"]
nat = false
addresses = null
}]
metadata = { startup-script = local.vm-startup-script }
service_account = module.service-account-gce.email
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
tags = ["ssh"]
}
module "vm-spoke-2" {
source = "../../../modules/compute-vm"
project_id = module.project.project_id
zone = "${var.region}-b"
name = "${var.prefix}-spoke-2"
network_interfaces = [{
network = module.vpc-spoke-2.self_link
subnetwork = module.vpc-spoke-2.subnet_self_links["${var.region}/${var.prefix}-spoke-2-1"]
nat = false
addresses = null
}]
metadata = { startup-script = local.vm-startup-script }
service_account = module.service-account-gce.email
service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
tags = ["ssh"]
}
module "service-account-gce" {
source = "../../../modules/iam-service-account"
project_id = module.project.project_id
name = "${var.prefix}-gce-test"
iam_project_roles = {
(var.project_id) = [
"roles/container.developer",
"roles/logging.logWriter",
"roles/monitoring.metricWriter",
]
}
}
################################################################################
# GKE #
################################################################################
module "cluster-1" {
source = "../../../modules/gke-cluster-standard"
name = "${var.prefix}-cluster-1"
project_id = module.project.project_id
location = "${var.region}-b"
vpc_config = {
network = module.vpc-spoke-2.self_link
subnetwork = module.vpc-spoke-2.subnet_self_links["${var.region}/${var.prefix}-spoke-2-1"]
master_authorized_ranges = {
for name, range in var.ip_ranges : name => range
}
master_ipv4_cidr_block = var.private_service_ranges.spoke-2-cluster-1
}
max_pods_per_node = 32
labels = {
environment = "test"
}
private_cluster_config = {
enable_private_endpoint = true
master_global_access = true
peering_config = {
export_routes = true
import_routes = false
}
}
}
module "cluster-1-nodepool-1" {
source = "../../../modules/gke-nodepool"
name = "${var.prefix}-nodepool-1"
project_id = module.project.project_id
location = module.cluster-1.location
cluster_name = module.cluster-1.name
service_account = {
email = module.service-account-gke-node.email
}
}
# roles assigned via this module use non-authoritative IAM bindings at the
# project level, with no risk of conflicts with pre-existing roles
module "service-account-gke-node" {
source = "../../../modules/iam-service-account"
project_id = module.project.project_id
name = "${var.prefix}-gke-node"
iam_project_roles = {
(var.project_id) = [
"roles/logging.logWriter", "roles/monitoring.metricWriter",
]
}
}
################################################################################
# GKE peering VPN #
################################################################################
module "vpn-hub" {
source = "../../../modules/net-vpn-static"
project_id = module.project.project_id
region = var.region
network = module.vpc-hub.name
name = "${var.prefix}-hub"
remote_ranges = values(var.private_service_ranges)
tunnels = {
spoke-2 = {
peer_ip = module.vpn-spoke-2.address
shared_secret = ""
traffic_selectors = { local = ["0.0.0.0/0"], remote = null }
}
}
}
module "vpn-spoke-2" {
source = "../../../modules/net-vpn-static"
project_id = module.project.project_id
region = var.region
network = module.vpc-spoke-2.name
name = "${var.prefix}-spoke-2"
# use an aggregate of the remote ranges, so as to be less specific than the
# routes exchanged via peering
remote_ranges = ["10.0.0.0/8"]
tunnels = {
hub = {
peer_ip = module.vpn-hub.address
shared_secret = module.vpn-hub.random_secret
traffic_selectors = { local = ["0.0.0.0/0"], remote = null }
}
}
}