feat(docs): Example Gateway terraform module for GCP (#4011)

Adds a working example of the simplest way to deploy Gateways to GCP
that is also mostly cloud platform agnostic.

I avoided using COS and Docker for this because:

- Systemd is already installed and supports IPv6 already
- Can be more easily adapted to other platforms where Docker may not be
available or trickier to setup (E.g. CentOS 7)
- COS is Google-specific

---------

Signed-off-by: Jamil <jamilbk@users.noreply.github.com>
Co-authored-by: Andrew Dryga <andrew@dryga.com>
This commit is contained in:
Jamil
2024-03-12 10:57:18 -07:00
committed by GitHub
parent 270563bb93
commit 81ef6ce7a1
8 changed files with 308 additions and 12 deletions

View File

@@ -102,10 +102,13 @@ product documentation, organized as follows:
- [swift/](../swift/apple): macOS / iOS clients.
- [kotlin/](../kotlin/android): Android / ChromeOS clients.
- [website/](../website): Marketing website and product documentation.
- [terraform/](../terraform): Terraform files for our cloud infrastructure:
- [terraform/](../terraform): Terraform files for various example deployments.
- [terraform/examples/gcp/nat_gateway](../terraform/examples/gcp/nat_gateway):
Example Terraform configurations for deploying a cluster of Firezone
gateways behind a NAT gateway on GCP with single egress IP.
- [terraform/modules/gateway-google-cloud-compute](../terraform/modules/gateway-google-cloud-compute):
Example Terraform module for deploying a Gateway to a Google Compute
Regional Instance Group.
Production-ready Terraform module for deploying regional Firezone gateways
to Google Cloud Compute.
## Quickstart

View File

@@ -1,7 +1,8 @@
# Ignore Terraform state and temporary files
.terraform
*.tfstate.backup
terraform.tfstate.d
**/.terraform
**/*.tfstate.backup
**/terraform.tfstate.d
**/terraform.tfvars
out.plan
# Don't ever commit these files to git

View File

@@ -0,0 +1,16 @@
# Terraform Examples
This directory contains examples of how to use Terraform to deploy Firezone
Gateways to your infrastructure.
## Examples
Each example below is self-contained and includes a `README.md` with
instructions on how to deploy the example.
### Google Cloud Platform (GCP)
- [NAT Gateway](./gcp/nat_gateway): This example shows how to deploy one or more
Firezone Gateways in a single GCP VPC that is configured with a Cloud NAT for
egress. Read this if you're looking to deploy Firezone Gateways behind a
single, shared static IP address on GCP.

View File

@@ -0,0 +1,102 @@
# GCP NAT Gateway Example
In this example, we will deploy one or more Firezone Gateways in a single VPC on
Google Cloud Platform (GCP) that are configured to egress traffic through a
single Cloud NAT that is assigned a single static IP address.
## Common use cases
Use this guide to give your Firezone Clients a static public IP address for
egress traffic to particular Resource(s). Here are some common use cases for
this example:
- Use IP whitelisting to access a third-party or partner application such as a
client's DB or third-party API.
- Use IP whitelisting with your identity provider to lock down access to a
public application.
- Enabling a team of remote contractors access to a regionally-locked
application or service.
## High availability
All Firezone Gateways deployed in this example will automatically failover and
load balance for each other. No other configuration is necessary. To perform
upgrades with minimal downtime, see
[minimal downtime upgrades](#minimal-downtime-upgrades).
## Prerequisites
1. [Terraform](https://www.terraform.io/downloads.html)
1. [Google Cloud Platform (GCP) account](https://cloud.google.com/)
1. [Google Cloud SDK](https://cloud.google.com/sdk/docs/install)
1. [Enable the Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=compute.googleapis.com)
1. A [Firezone Site](https://www.firezone.dev/kb/deploy/sites) dedicated to use
for this example. This Site should contain **only** the Firezone Gateway(s)
deployed in this example and any associated Resources.
1. A Firezone Gateway token. See
[Multiple Gateways](https://www.firezone.dev/kb/deploy/gateways#deploy-multiple-gateways)
for instructions on how to obtain a Firezone Gateway token that can be used
across multiple instances.
## Sizing
Simply update the number of replicas to deploy more or fewer Firezone Gateways.
There's no limit to the number of Firezone Gateways you can deploy in a single
VPC.
We've tested with `f1-micro` instances which still work quite well for most
applications. However, you may want to consider a larger instance type if you
have a high volume of traffic or lots of concurrent connections.
## Deployment
1. Configure the necessary Terraform
[variables](https://developer.hashicorp.com/terraform/language/values/variables).
Here's an example `terraform.tfvars` you can use as a starting point:
```hcl
project_id = "my-gcp-project"
region = "us-west1"
zone = "us-west1-a"
token = "<YOUR GATEWAY TOKEN>"
replicas = 3
machine_type = "f1-micro"
log_level = "info"
```
1. Run `terraform init` to initialize the working directory and download the
required providers.
1. Run `terraform apply` to deploy the Firezone Gateway(s) into your GCP
project.
You can see the static IP address assigned to the Cloud NAT in the Terraform
output. This is the IP address that your Firezone Gateway(s) will use to egress
traffic.
You can verify all Firezone Gateways are using this IP by viewing the Site in
the Firezone admin portal, where you should now see the Firezone Gateway(s)
listed as `Online`.
<center>
![Online Gateways](./online-gateways.png)
</center>
## Upgrading
To upgrade the Firezone Gateway(s) to the latest version, simply update the
`token` and issue a `terraform apply` which will trigger a redeployment of the
Firezone Gateway(s).
This will incur about a minute or two of downtime as Terraform destroys the
existing Firezone Gateway(s) and deploys new ones in their place.
## Future improvements
- Minimal downtime upgrades using a regional instance manager.
- Expose the ability to select an existing subnetwork instead of auto-creating a
new one.
- Expose the ability to select an existing
[regional external IP address](https://cloud.google.com/nat/docs/ports-and-addresses)
instead of auto-creating a new one.

View File

@@ -0,0 +1,112 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "5.19.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
zone = var.zone
}
resource "google_project_service" "compute-api" {
project = var.project_id
service = "compute.googleapis.com"
}
resource "google_service_account" "firezone" {
account_id = "firezone-gateway"
display_name = "Firezone Gateway Service Account"
}
resource "google_compute_network" "firezone" {
name = "firezone-gateway"
auto_create_subnetworks = true
depends_on = [google_project_service.compute-api]
}
resource "google_compute_router" "firezone" {
name = "firezone-gateway-router"
network = google_compute_network.firezone.id
}
resource "google_compute_router_nat" "firezone" {
name = "firezone-gateway-nat"
router = google_compute_router.firezone.name
nat_ip_allocate_option = "AUTO_ONLY"
source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES"
}
resource "google_compute_instance_template" "gateway" {
name = "gateway-template"
description = "Instance template for the Firezone Gateway"
instance_description = "Firezone Gateway"
machine_type = var.machine_type
tags = ["firezone-gateway"]
can_ip_forward = true
scheduling {
automatic_restart = true
on_host_maintenance = "MIGRATE"
}
disk {
source_image = "debian-cloud/debian-12"
auto_delete = true
boot = true
}
network_interface {
network = google_compute_network.firezone.id
}
service_account {
email = google_service_account.firezone.email
scopes = ["cloud-platform"]
}
}
// Allow SSH access to the gateways. This is optional but helpful for debugging
// and administration of the gateways. Since they're not publicly accessible,
// you need to tunnel through IAP:
//
// gcloud compute ssh --tunnel-through-iap --project <PROJECT_ID> --zone <ZONE> gateway-0
resource "google_compute_firewall" "ssh-rule" {
name = "allow-ssh"
network = google_compute_network.firezone.name
allow {
protocol = "tcp"
ports = ["22"]
}
target_tags = ["gateway"]
source_ranges = ["0.0.0.0/0"]
}
resource "google_compute_instance_from_template" "gateway" {
name = "gateway-${count.index}"
count = var.replicas
source_instance_template = google_compute_instance_template.gateway.self_link_unique
# Script is defined here to set instance-specific metadata
metadata_startup_script = <<-SCRIPT
#!/usr/bin/env bash
set -euo pipefail
# Install dependencies
sudo apt-get update
sudo apt-get install -y iptables curl
# Set necessary environment variables and run installer
FIREZONE_ID="gateway-${google_compute_instance_template.gateway.id}-${count.index}" \
FIREZONE_TOKEN="${var.token}" \
bash <(curl -fsSL https://raw.githubusercontent.com/firezone/firezone/main/scripts/gateway-systemd-install.sh)
SCRIPT
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@@ -0,0 +1,54 @@
################################################################################
## Google Cloud Project
################################################################################
variable "project_id" {
type = string
description = "Google Cloud Project ID"
}
################################################################################
## Compute
################################################################################
variable "region" {
type = string
description = "Region to deploy the Gateway(s) in."
}
variable "zone" {
type = string
description = "Availability to deploy the Gateway(s) in."
}
variable "replicas" {
type = number
description = "Number of Gateway replicas to deploy in the availability zone."
default = 3
}
variable "machine_type" {
type = string
default = "n1-standard-1"
}
################################################################################
## Observability
################################################################################
variable "log_level" {
type = string
nullable = false
default = "info"
description = "Sets RUST_LOG environment variable to configure the Gateway's log level. Default: 'info'."
}
################################################################################
## Firezone
################################################################################
variable "token" {
type = string
description = "Gateway token to use for authentication."
}

View File

@@ -68,13 +68,21 @@ A single Client connection to a single Gateway can typically reach speeds of **1
Gbps** or more. This scales linearly with each Client connection up to the
number of CPU cores available to the Gateway.
Use the table below as a rough guide for sizing your Gateway deployments:
In our tests, we've found that even a single `f1.micro` instance on Google Cloud
Platform, equipped with a single shared vCPU core, can effortlessly handle up to
1 Gbps of tunneled traffic. This performance is attributed to the efficiency of
the WireGuard® protocol and the Rust programming language.
| Gateway size | Users served | CPU cores | Memory | Network link |
| ------------ | ------------ | --------- | ------ | ------------ |
| Small | 100 | 2 | 2 GB | 1 Gbps |
| Medium | 1,000 | 8 | 8 GB | 10 Gbps |
| Large | 10,000 | 32 | 32 GB | 40 Gbps |
Use the table below as a rough guide for sizing your Gateway deployments. These
are general recommendations and may not be accurate for your specific use case.
If you're unsure, start with a smaller Gateway and scale up as needed.
| Gateway size | Users served | CPU cores | Memory | Network link |
| ------------ | -------------- | --------- | ------ | ------------ |
| Micro | 10 - 100 | 1 | 512 MB | 1 Gbps |
| Small | 100 - 250 | 2 | 1 GB | 1 Gbps |
| Medium | 250 - 1,000 | 4 | 4 GB | 10 Gbps |
| Large | 1,000 - 10,000 | 16 | 16 GB | 25 Gbps |
To go beyond the table above, you can deploy additional Gateways and use
Firezone's [automatic load balancing](#load-balancing) to distribute Client