Skip to content

Commit

Permalink
Merge pull request #160 from tanmaybangale/nb-psc-mig-l7xlb
Browse files Browse the repository at this point in the history
feat : add nb-psc-mig-l7xlb sample and tests
  • Loading branch information
danistrebel authored Oct 9, 2024
2 parents fe6612a + 64db907 commit d3787dd
Show file tree
Hide file tree
Showing 11 changed files with 563 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Sample modules are intended to demonstrate the most common network topologies fo
* [X Basic](samples/x-basic) for a basic Apigee X setup with the raw instance endpoints exposed as internal IP addresses.
* [X with external L7 LB](samples/x-l7xlb) for an Apigee X setup that is exposed via a global external L7 load balancer.
* [X with external L7 LB and northbound PSC](samples/x-nb-psc-xlb) for an Apigee X setup that uses a global external L7 load balancer and a Private Service Connect (PSC) Network Endpoint Group (NEG) to connect to an Apigee instance's service attachment.
* [X with external L7 LB, MIG and northbound PSC](samples/x-nb-psc-mig-l7xlb) for an Apigee X setup that uses a global external L7 load balancer-->Managed Instance Group-->Private Service Connect (PSC) Endpoint to connect to an Apigee instance's service attachment to leverage active health check with PSC.
* [X with southbound PSC](samples/x-sb-psc) for an Apigee X setup that uses Private Service Connect (PSC) to connect to a backend service in another VPC.
* [X with internal L4 LB and mTLS](samples/x-ilb-mtls) for a basic Apigee X setup plus exposure via regional L4 load balancer and envoy proxy to terminate mTLS.
* [X with external L4 LB and mTLS](samples/x-l4xlb-mtls) for a basic Apigee X setup plus exposure via global external L4 load balancer and envoy proxy to terminate mTLS.
Expand Down
Binary file added samples/.DS_Store
Binary file not shown.
Binary file added samples/x-nb-psc-mig-l7xlb/.DS_Store
Binary file not shown.
111 changes: 111 additions & 0 deletions samples/x-nb-psc-mig-l7xlb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Apigee X exposed in Multiple GCP Regions with PSC and MIG External HTTPS Load Balancer

End-to-end sample terraform code to provision Apigee X exposed by External Load Balancer with PSC and MIG.

If you plan to use LB-->PSC-NEG for Apigee northbound network routing, follow the instructions in this document to configure active health check.
At this time, PSC-NEG does not support active health check monitoring as mentioned [here](https://cloud.google.com/load-balancing/docs/negs#psc-neg).
To work around this limitation of PSC, you can modify the Apigee installation configuration to use a managed instance group (MIG), which does provide active health check capability. Refer the solution guide [here](https://cloud.google.com/apigee/docs/api-platform/system-administration/health-check-mig-workaround) and the network diagram below :

<p align="center">
<img src="./sample-architecture.png?raw=true" alt="Apigee X Shared VPC Multi Region Sample Architecture">
</p>



<!-- BEGIN_SAMPLES_DEFAULT_SETUP_INSTRUCTIONS -->
## Setup Instructions

Set the project ID where you want your Apigee Organization to be deployed to:

```sh
PROJECT_ID=my-project-id
```

```sh
cd samples/... # Sample from above
cp ./x-demo.tfvars ./my-config.tfvars
```

Decide on a [backend](https://www.terraform.io/language/settings/backends) and create the necessary config. To use a backend on Google Cloud Storage (GCS) use:

```sh
gsutil mb "gs://$PROJECT_ID-tf"

cat <<EOF >terraform.tf
terraform {
backend "gcs" {
bucket = "$PROJECT_ID-tf"
prefix = "terraform/state"
}
}
EOF
```

Validate your config:

```sh
terraform init
terraform plan --var-file=./my-config.tfvars -var "project_id=$PROJECT_ID"
```

and provision everything (takes roughly 25min):

```sh
terraform apply --var-file=./my-config.tfvars -var "project_id=$PROJECT_ID"
```
<!-- END_SAMPLES_DEFAULT_SETUP_INSTRUCTIONS -->

<!-- BEGIN_TF_DOCS -->
## Providers

| Name | Version |
|------|---------|
| <a name="provider_google"></a> [google](#provider\_google) | n/a |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_apigee-x-bridge-mig"></a> [apigee-x-bridge-mig](#module\_apigee-x-bridge-mig) | ../../modules/apigee-x-bridge-mig | n/a |
| <a name="module_apigee-x-core"></a> [apigee-x-core](#module\_apigee-x-core) | ../../modules/apigee-x-core | n/a |
| <a name="module_mig-l7xlb"></a> [mig-l7xlb](#module\_mig-l7xlb) | ../../modules/mig-l7xlb | n/a |
| <a name="module_project"></a> [project](#module\_project) | github.com/terraform-google-modules/cloud-foundation-fabric//modules/project | v28.0.0 |
| <a name="module_vpc"></a> [vpc](#module\_vpc) | github.com/terraform-google-modules/cloud-foundation-fabric//modules/net-vpc | v28.0.0 |

## Resources

| Name | Type |
|------|------|
| [google_compute_address.psc_endpoint_address](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) | resource |
| [google_compute_forwarding_rule.psc_ilb_consumer](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_forwarding_rule) | resource |
| [google_compute_global_address.external_address](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_global_address) | resource |
| [google_compute_managed_ssl_certificate.google_cert](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_managed_ssl_certificate) | resource |
| [google_compute_address.int_psc_ips](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/compute_address) | data source |
| [google_compute_global_address.my_lb_external_address](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/compute_global_address) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_apigee_envgroups"></a> [apigee\_envgroups](#input\_apigee\_envgroups) | Apigee Environment Groups. | <pre>map(object({<br> hostnames = list(string)<br> }))</pre> | `null` | no |
| <a name="input_apigee_environments"></a> [apigee\_environments](#input\_apigee\_environments) | Apigee Environments. | <pre>map(object({<br> display_name = optional(string)<br> description = optional(string)<br> node_config = optional(object({<br> min_node_count = optional(number)<br> max_node_count = optional(number)<br> }))<br> iam = optional(map(list(string)))<br> envgroups = list(string)<br> type = optional(string)<br> }))</pre> | `null` | no |
| <a name="input_apigee_instances"></a> [apigee\_instances](#input\_apigee\_instances) | Apigee Instances (only one instance for EVAL orgs). | <pre>map(object({<br> region = string<br> ip_range = string<br> environments = list(string)<br> }))</pre> | `null` | no |
| <a name="input_ax_region"></a> [ax\_region](#input\_ax\_region) | GCP region for storing Apigee analytics data. | `string` | n/a | yes |
| <a name="input_billing_account"></a> [billing\_account](#input\_billing\_account) | Billing account ID. | `string` | n/a | yes |
| <a name="input_billing_type"></a> [billing\_type](#input\_billing\_type) | Billing type of the Apigee organization. | `string` | `null` | no |
| <a name="input_exposure_subnets"></a> [exposure\_subnets](#input\_exposure\_subnets) | Subnets for exposing Apigee services | <pre>list(object({<br> name = string<br> ip_cidr_range = string<br> region = string<br> instance = string<br> secondary_ip_range = map(string)<br> }))</pre> | `[]` | no |
| <a name="input_lb_name"></a> [lb\_name](#input\_lb\_name) | Name of the load balancer. | `string` | n/a | yes |
| <a name="input_peering_range"></a> [peering\_range](#input\_peering\_range) | Peering CIDR range | `string` | n/a | yes |
| <a name="input_project_create"></a> [project\_create](#input\_project\_create) | Create project. When set to false, uses a data source to reference existing project. | `bool` | `false` | no |
| <a name="input_project_id"></a> [project\_id](#input\_project\_id) | Project ID. | `string` | n/a | yes |
| <a name="input_project_parent"></a> [project\_parent](#input\_project\_parent) | Parent folder or organization in 'folders/folder\_id' or 'organizations/org\_id' format. | `string` | n/a | yes |
| <a name="input_project_services"></a> [project\_services](#input\_project\_services) | List of services to enable in the project. | `list(string)` | <pre>[<br> "apigee.googleapis.com",<br> "cloudkms.googleapis.com",<br> "compute.googleapis.com",<br> "servicenetworking.googleapis.com"<br>]</pre> | no |
| <a name="input_psc_subnets"></a> [psc\_subnets](#input\_psc\_subnets) | Subnets for psc endpoints | <pre>list(object({<br> name = string<br> ip_cidr_range = string<br> region = string<br> instance = string<br> secondary_ip_range = map(string)<br> }))</pre> | `[]` | no |
| <a name="input_ssl_crt_domains"></a> [ssl\_crt\_domains](#input\_ssl\_crt\_domains) | Domains for the managed SSL certificate. | `list(string)` | n/a | yes |
| <a name="input_support_range1"></a> [support\_range1](#input\_support\_range1) | Support CIDR range of length /28 (required by Apigee for troubleshooting purposes). | `string` | n/a | yes |
| <a name="input_vpc_name"></a> [vpc\_name](#input\_vpc\_name) | Project ID. | `string` | n/a | yes |

## Outputs

No outputs.
<!-- END_TF_DOCS -->
141 changes: 141 additions & 0 deletions samples/x-nb-psc-mig-l7xlb/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* Copyright 2024 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 {
subnet_region_name = { for subnet in var.exposure_subnets :
subnet.region => "${subnet.region}/${subnet.name}"
}
psc_subnets = { for psc in var.psc_subnets :
psc.name => psc
}
region_psc_map = {for psc in var.psc_subnets :
psc.region => psc.name
}

}

module "project" {
source = "github.com/terraform-google-modules/cloud-foundation-fabric//modules/project?ref=v28.0.0"
name = var.project_id
parent = var.project_parent
billing_account = var.billing_account
project_create = var.project_create
services = var.project_services
}

module "vpc" {
source = "github.com/terraform-google-modules/cloud-foundation-fabric//modules/net-vpc?ref=v28.0.0"
project_id = module.project.project_id
name = var.vpc_name
subnets = [
for subnet in concat(var.exposure_subnets, var.psc_subnets) :
{
"name" = subnet.name
"region" = subnet.region
"secondary_ip_ranges" = subnet.secondary_ip_range
"ip_cidr_range" = subnet.ip_cidr_range
}
]
psa_config = {
ranges = {
apigee-range = var.peering_range
apigee-support-range1 = var.support_range1

#add_more_support_ranges_per_instance_region
}
}
}

module "apigee-x-core" {
source = "../../modules/apigee-x-core"
project_id = module.project.project_id
billing_type = var.billing_type
ax_region = var.ax_region
apigee_environments = var.apigee_environments
apigee_envgroups = var.apigee_envgroups
apigee_instances = var.apigee_instances
network = module.vpc.network.id
}


resource "google_compute_address" "psc_endpoint_address" {
for_each = local.psc_subnets
name = "psc-ip-${each.value.region}"
project = module.project.project_id
address_type = "INTERNAL"
subnetwork = module.vpc.subnet_self_links["${each.value.region}/${each.value.name}"]
region = each.value.region
}

resource "google_compute_forwarding_rule" "psc_ilb_consumer" {
for_each = local.psc_subnets
name = "psc-ea-${each.value.region}"
project = module.project.project_id
region = each.value.region
target = module.apigee-x-core.instance_service_attachments[each.value.region]
load_balancing_scheme = ""
network = module.vpc.network.id
ip_address = google_compute_address.psc_endpoint_address[each.value.name].id
depends_on = [
google_compute_address.psc_endpoint_address,
module.apigee-x-core
]
}

data "google_compute_address" "int_psc_ips" {
for_each = google_compute_address.psc_endpoint_address
name = each.value.name
region = each.value.region
project = module.project.project_id
}

module "apigee-x-bridge-mig" {
for_each = local.subnet_region_name
source = "../../modules/apigee-x-bridge-mig"
project_id = module.project.project_id
network = module.vpc.network.id
region = each.key
subnet = module.vpc.subnet_self_links[local.subnet_region_name[each.key]]
endpoint_ip = data.google_compute_address.int_psc_ips[local.region_psc_map[each.key]].address
}

resource "google_compute_global_address" "external_address" {
name = "lb-${var.lb_name}-ip"
project = module.project.project_id
address_type = "EXTERNAL"
}

data "google_compute_global_address" "my_lb_external_address" {
name = google_compute_global_address.external_address.name
project = module.project.project_id
}

resource "google_compute_managed_ssl_certificate" "google_cert" {
project = var.project_id
name = "ssl-cert"
managed {
domains = var.ssl_crt_domains
}
}

module "mig-l7xlb" {
source = "../../modules/mig-l7xlb"
project_id = module.project.project_id
name = var.lb_name
backend_migs = [for _, mig in module.apigee-x-bridge-mig : mig.instance_group]
ssl_certificate = [google_compute_managed_ssl_certificate.google_cert.id]
external_ip = data.google_compute_global_address.my_lb_external_address.address
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d3787dd

Please sign in to comment.