Just deployed a FortiGate-VM hub into Azure and AWS for a client's multi-cloud segmentation project. The performance overhead was higher than expected, but manageable after tuning.
The main value was consistency: identical security policy and routing config across clouds. Used BGP with the cloud providers for dynamic route injection.
Key Terraform modules handle:
- VNet/VPC and subnet creation with proper routing tables
- FortiGate-VM deployment (BYOL) with multiple NICs
- User-Assigned Identity / IAM Role for managed identity access
- Configuration via `fortios` provider for baseline policies
Biggest cost trap: the egress charges for inspected traffic between VPCs/VNets and on-prem. You pay cloud egress twice.
Example core module call for Azure:
```hcl
module "fortigate_hub_azure" {
source = "./modules/azure_fortigate"
region = "East US"
vnet_cidr = "10.10.0.0/16"
subnet_sizes = {
"external" = 28
"internal" = 28
"ha" = 28
}
fortios_version = "7.4.3"
}
```
Full config is in the repo. Main takeaway: test throughput with your actual traffic pattern before sizing. The specs on the datasheet assume optimal, large-packet flows. Our 2vCPU instance hit a bottleneck at ~700 Mbps with a mix of small packets.
Good on you for calling out the throughput gap between datasheet claims and real traffic. We saw the same thing on a GCP deployment last year, and it wasn't just packet size. The virtual NIC drivers and the hypervisor's network backend can throttle you unexpectedly, especially with small, frequent packets typical of east-west microservice chatter.
The double egress cost you mentioned is the silent killer in these hub-and-spoke designs. It's easy to miss until the first cloud bill hits. One way we've mitigated it is by shifting DNS-based service discovery to be hub-local, so more traffic stays within the same VPC/VNet for inspection instead of crossing back out. It's not a silver bullet, but it shaved off about 30% of our inter-zone traffic.
Are you handling HA? I found the `fortios` provider can be brittle during failover events if the config drift isn't managed tightly. We had to add a manual reconciliation step in our pipeline.
Migrate once, test twice.