From bf1abcfbfaa572cfca1f127df1c864df1dfc71c5 Mon Sep 17 00:00:00 2001 From: Jamil Date: Fri, 17 May 2024 09:39:21 -0700 Subject: [PATCH] feat(devops): Add example for spinning up performance testing VMs on Azure (#4647) Sets up boilerplate for Azure performance testing infra. They have some really interesting high performance VMs that would be fitting for our use cases, including [ones with RDMA-enabled Infiniband networking cards](https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/enable-infiniband) if we really want to go wild. --- terraform/environments/performance/.gitignore | 2 + terraform/environments/performance/README.md | 59 +++++++++ terraform/environments/performance/main.tf | 116 ++++++++++++++++++ .../environments/performance/variables.tf | 29 +++++ 4 files changed, 206 insertions(+) create mode 100644 terraform/environments/performance/.gitignore create mode 100644 terraform/environments/performance/README.md create mode 100644 terraform/environments/performance/main.tf create mode 100644 terraform/environments/performance/variables.tf diff --git a/terraform/environments/performance/.gitignore b/terraform/environments/performance/.gitignore new file mode 100644 index 000000000..b8131cb67 --- /dev/null +++ b/terraform/environments/performance/.gitignore @@ -0,0 +1,2 @@ +# This dir is simply an example; don't commit the lockfile +/.terraform.lock.hcl diff --git a/terraform/environments/performance/README.md b/terraform/environments/performance/README.md new file mode 100644 index 000000000..257f4d1cb --- /dev/null +++ b/terraform/environments/performance/README.md @@ -0,0 +1,59 @@ +# Performance Terraform environment + +This directory contains terraform examples for spinning up VMs on Azure to be +used for performance testing. + +This is primarily meant to be used internal by the Firezone Team at this time, +but anyone can use the scripts here by changing the variables in a local +`terraform.tfvars` as needed. + +## Get started + +1. [Install](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) + Terraform if you haven't already. +1. [Install](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) the + Azure CLI if you haven't already. +1. Clone this repository, and `cd` to this directory. +1. Run `terraform init` to initialize the directory. +1. Login to Azure using the Azure CLI with `az login`. +1. Find the subscription ID you want to use with `az account subscription list`. + If unsure, contact your Azure admin to avoid incurring billing charges under + the wrong billing subscription. +1. Generate a keypair to use for your own admin SSH access (**must** be RSA): + ```shell + ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa.azure + ``` +1. Obtain `terraform.tfvars` using one of the following methods: + + 1. Your team's shared credentials vault (e.g. 1password) + 1. Your Azure admin + 1. Or, generate it by following the instructions at + https://developer.hashicorp.com/terraform/tutorials/azure-get-started/azure-build + and populating a `terraform.tfvars` file in this directory: + + ```hcl + # Azure billing subscription ID + subscription_id = "SUBSCRIPTION-ID-FROM-PREVIOUS-STEP" + + # Obtain these variables by following the guide above + arm_client_id = "AZURE-SERVICE-PRINCIPAL-CLIENT-ID" + arm_client_secret = "AZURE-SERVICE-PRINCIPAL-CLIENT-SECRET" + arm_tenant_id = "AZURE-SERVICE-PRINCIPAL-TENANT-ID" + + # All VMs need a public RSA SSH key specified for the admin user. Insert yours below. + admin_ssh_public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7..." + + # Set your own naming prefix to avoid clobbering others' resources + naming_prefix = "CHANGEME" + ``` + +1. Run `terraform apply` to create the resources. +1. Done! You can now SSH into your VM like so: + ```shell + # Login using the name of resources used in Terraform config above + az ssh vm \ + --resource-group CHANGEME-rg-westus2 \ + --vm-name CHANGEME-vm-westus2 \ + --private-key-file ~/.ssh/id_rsa.azure \ + --local-user adminuser + ``` diff --git a/terraform/environments/performance/main.tf b/terraform/environments/performance/main.tf new file mode 100644 index 000000000..d6e6d2cf1 --- /dev/null +++ b/terraform/environments/performance/main.tf @@ -0,0 +1,116 @@ +locals { + # Find this with `az account subscription list` + arm_subscription_id = var.subscription_id + + # Generate these by following + # https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret?ajs_aid=fdab1b75-b67a-4e43-8a41-7cb014d5c881&product_intent=terraform#creating-a-service-principal-using-the-azure-cli + # + # and then saving to terraform.tfvars in this directory: + # + # arm_client_id = "..." + # arm_client_secret = "..." + # arm_tenant_id = "..." + arm_client_id = var.arm_client_id + arm_client_secret = var.arm_client_secret + arm_tenant_id = var.arm_tenant_id +} + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 3.0.2" + } + } + + required_version = ">= 1.1.0" +} + +provider "azurerm" { + features {} +} + +# US-west resource group +resource "azurerm_resource_group" "rg-westus2" { + name = "${var.naming_prefix}-rg-westus2" + location = "westus2" +} + +# US-west virtual network +resource "azurerm_virtual_network" "vnet-westus2" { + name = "${var.naming_prefix}-vnet-westus2" + resource_group_name = azurerm_resource_group.rg-westus2.name + location = azurerm_resource_group.rg-westus2.location + address_space = ["10.0.0.0/16"] +} + +# US-west subnet +resource "azurerm_subnet" "subnet-westus2" { + name = "${var.naming_prefix}-subnet-westus2" + resource_group_name = azurerm_resource_group.rg-westus2.name + virtual_network_name = azurerm_virtual_network.vnet-westus2.name + address_prefixes = ["10.0.0.0/24"] +} + +# NIC for US-west VM +resource "azurerm_network_interface" "nic-westus2" { + name = "${var.naming_prefix}-nic-westus2" + location = azurerm_resource_group.rg-westus2.location + resource_group_name = azurerm_resource_group.rg-westus2.name + + # Enable accelerated networking, can only be enabled on one NIC per VM + enable_accelerated_networking = true + + ip_configuration { + name = "${var.naming_prefix}-ipconfig-westus2" + subnet_id = azurerm_subnet.subnet-westus2.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.publicip-westus2.id + } +} + +# Public IP for US-west VM +resource "azurerm_public_ip" "publicip-westus2" { + name = "${var.naming_prefix}-publicip-westus2" + location = azurerm_resource_group.rg-westus2.location + resource_group_name = azurerm_resource_group.rg-westus2.name + allocation_method = "Dynamic" +} + +# US-west VM +resource "azurerm_linux_virtual_machine" "vm-westus2" { + name = "${var.naming_prefix}-vm-westus2" + resource_group_name = azurerm_resource_group.rg-westus2.name + location = azurerm_resource_group.rg-westus2.location + + # 16 vCPUs, 56 GB RAM, Premium SSD + size = "Standard_DS5_v2" + network_interface_ids = [ + azurerm_network_interface.nic-westus2.id + ] + + # Username of the admin user + admin_username = "adminuser" + + admin_ssh_key { + username = "adminuser" + public_key = var.admin_ssh_pubkey + } + + # Allow others access to the VM + identity { + type = "SystemAssigned" + } + + os_disk { + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts" + version = "latest" + } +} diff --git a/terraform/environments/performance/variables.tf b/terraform/environments/performance/variables.tf new file mode 100644 index 000000000..35e34607c --- /dev/null +++ b/terraform/environments/performance/variables.tf @@ -0,0 +1,29 @@ +variable "subscription_id" { + description = "The Azure billing subscription to use" + type = string +} + +variable "arm_client_id" { + description = "The Azure service principal client id" + type = string +} + +variable "arm_client_secret" { + description = "The Azure service principal client secret" + type = string +} + +variable "arm_tenant_id" { + description = "The Azure service principal tenant id" + type = string +} + +variable "admin_ssh_pubkey" { + description = "The SSH public key to use for the admin user" + type = string +} + +variable "naming_prefix" { + description = "The prefix to use for all resources" + type = string +}