diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index af3b657..0e873e1 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -14,6 +14,8 @@ This guide shows examples of errors you might see when deploying or using the li - [Azure](#azure) - [Azure: SkuNotAvailable / Capacity errors](#azure-skunotavailable--capacity-errors) - [Azure: Quota limit errors](#azure-quota-limit-errors) +- [Azure: Azure for Students errors](#azure-azure-for-students-errors) +- [Azure: Resource group already exists](#azure-resource-group-already-exists) - [GCP](#gcp) - [GCP: API not enabled / Billing errors](#gcp-api-not-enabled--billing-errors) - [GCP: Machine type not offered / Zone capacity errors](#gcp-machine-type-not-offered--zone-capacity-errors) @@ -263,17 +265,31 @@ terraform apply \ The Terraform commands in this Azure section assume you are running them from the `azure/` directory. -The default VM size is `Standard_B1s`, and the default region is `East US`. +The default VM size is `Standard_B1s`, and the default region is `East US`. The lab uses an x64 Ubuntu image, so the VM size must be x64. Arm64 sizes such as `Standard_B2pts_v2` won't work. ### Azure: SkuNotAvailable / Capacity errors -If Terraform fails with an error like: +`terraform plan` checks the VM size before creating anything. If the size can't be used, it stops with one of these messages: + +```text +VM size is not offered in . +``` + +```text +VM size is not available for your subscription in (NotAvailableForSubscription). +``` + +The second one is common on Azure for Students, where `Standard_B1s` is often restricted in `East US`. Switch region or VM size and retry. + +If the check passes but `terraform apply` still fails with an error like: ```text SkuNotAvailable: The requested VM size ... is currently not available in location "your location" ``` -This usually means the selected region does not currently have capacity for that SKU, or your subscription is restricted in that region. +the region is temporarily out of capacity for that size. Retry later, or switch region or VM size. + +To find a size that works, x64 sizes that are small enough for the lab include `Standard_B1s`, `Standard_B1ms`, `Standard_B2s`, and `Standard_B2ats_v2`. Check whether `Standard_B1s` is available in a region: @@ -330,6 +346,67 @@ terraform apply \ -var azure_vm_size="Standard_B1ms" ``` +### Azure: Azure for Students errors + +Azure for Students subscriptions have extra limits beyond VM size restrictions. + +**Allowed regions.** Many Student subscriptions only allow deployments to a small set of regions. Deploying elsewhere fails with an error like: + +```text +RequestDisallowedByAzure: Resource 'ctf-resources' was disallowed by Azure: This policy maintains a set of best available regions where your subscription can deploy resources. +``` + +List the regions your subscription allows: + +```sh +az policy assignment list \ + --subscription "YOUR_AZURE_SUBSCRIPTION_ID" \ + --disable-scope-strict-match \ + --query "[].parameters.listOfAllowedLocations.value" \ + -o json +``` + +If that prints an empty list, the restriction isn't visible to your account. Try another region, such as `eastus2`, `westus2`, or `centralus`. + +Retry with an allowed region: + +```sh +terraform apply \ + -var subscription_id="YOUR_AZURE_SUBSCRIPTION_ID" \ + -var az_region="eastus2" +``` + +**Credits used up.** When the Student credit runs out, the subscription is disabled and deployments fail with errors like `ReadOnlyDisabledSubscription`. Check the subscription state: + +```sh +az account show --subscription "YOUR_AZURE_SUBSCRIPTION_ID" --query state -o tsv +``` + +If it isn't `Enabled`, check your remaining credit in the Azure portal under **Subscriptions**, or upgrade to Pay-As-You-Go. + +### Azure: Resource group already exists + +If Terraform fails with: + +```text +A resource with the ID "/subscriptions/.../resourceGroups/ctf-resources" already exists +``` + +a lab from an earlier deploy is still there, but this Terraform directory has no record of it (for example, you deployed from another clone or deleted `terraform.tfstate`). Check what's in it first: + +```sh +az resource list \ + --subscription "YOUR_AZURE_SUBSCRIPTION_ID" \ + --resource-group ctf-resources \ + -o table +``` + +If it only contains old lab resources, delete it and retry. This permanently deletes everything in the group: + +```sh +az group delete --subscription "YOUR_AZURE_SUBSCRIPTION_ID" --name ctf-resources +``` + ## GCP The Terraform commands in this GCP section assume you are running them from the `gcp/` directory. Add `-var gcp_project="YOUR_GCP_PROJECT_ID"` to each `terraform apply`. diff --git a/azure/README.md b/azure/README.md index 4aed476..c894671 100644 --- a/azure/README.md +++ b/azure/README.md @@ -22,7 +22,7 @@ Deploy the lab here, then follow the [Playing the Lab guide](../GUIDE.md) to con 4. A GitHub fork of this repository > [!NOTE] -> If you have an Azure Student account, you may encounter errors. See [this workaround](https://github.com/g-now-zero/l2c-guides/blob/main/posts/ctf-azure-spot-instances-guide.md). +> Azure for Students subscriptions often restrict VM sizes and regions. If you're using one, see [Azure for Students errors](../TROUBLESHOOTING.md#azure-azure-for-students-errors). ## Deploy the Lab @@ -56,10 +56,11 @@ If deployment fails, see [TROUBLESHOOTING.md](../TROUBLESHOOTING.md#azure). ### VM size / capacity errors -If `terraform apply` fails with `SkuNotAvailable` or quota/capacity errors, switching region and/or VM size (`azure_vm_size`, default `Standard_B1s`) is usually the fastest fix. See: +`terraform plan` checks that the VM size (`azure_vm_size`, default `Standard_B1s`) is available for your subscription in your region. If it isn't, or `terraform apply` fails with `SkuNotAvailable` or quota errors, switching region and/or VM size is usually the fastest fix. See: - [Azure: SkuNotAvailable / Capacity errors](../TROUBLESHOOTING.md#azure-skunotavailable--capacity-errors) - [Azure: Quota limit errors](../TROUBLESHOOTING.md#azure-quota-limit-errors) +- [Azure: Azure for Students errors](../TROUBLESHOOTING.md#azure-azure-for-students-errors) ## Play the Lab diff --git a/azure/main.tf b/azure/main.tf index 481049a..66a984d 100644 --- a/azure/main.tf +++ b/azure/main.tf @@ -7,6 +7,10 @@ terraform { source = "hashicorp/azurerm" version = "~> 5.6" } + azapi = { + source = "Azure/azapi" + version = "~> 2.13" + } null = { source = "hashicorp/null" version = "~> 3.0" @@ -44,6 +48,12 @@ variable "setup_release_tag" { } locals { + # "East US" -> "eastus", the form the SKU API uses + az_location = lower(replace(var.az_region, " ", "")) + vm_size_sku = try(data.azapi_resource_list.vm_size.output.skus[0], null) + # Sizes that don't report an architecture are x64 + vm_size_architecture = coalesce(try(local.vm_size_sku.architecture, null), "x64") + setup_asset_name = "linux-ctfs-setup.tar.gz" setup_release_base = var.setup_release_tag == "latest" ? "https://github.com/learntocloud/linux-ctfs/releases/latest/download" : "https://github.com/learntocloud/linux-ctfs/releases/download/${var.setup_release_tag}" setup_release_url = "${local.setup_release_base}/${local.setup_asset_name}" @@ -107,7 +117,7 @@ locals { apt_get_update_with_retry() { local attempt for attempt in 1 2 3 4 5; do - if apt-get -o DPkg::Lock::Timeout=120 -o Acquire::Retries=3 update; then + if apt-get -o DPkg::Lock::Timeout=300 -o Acquire::Retries=3 update; then return 0 fi echo "apt-get update failed. Attempt $${attempt}/5." @@ -119,7 +129,7 @@ locals { wait_for_cloud_init apt_get_update_with_retry - apt-get -o DPkg::Lock::Timeout=120 -o Acquire::Retries=3 install -y ca-certificates curl tar gzip coreutils + apt-get -o DPkg::Lock::Timeout=300 -o Acquire::Retries=3 install -y ca-certificates curl tar gzip coreutils cd "$${WORK_DIR}" download_with_retry "$${SETUP_URL}" "$${ASSET_NAME}" @@ -151,6 +161,25 @@ provider "azurerm" { resource_provider_registrations = "core" } +# azapi is only used to look up VM size availability, which azurerm can't do. +provider "azapi" { + subscription_id = var.subscription_id + skip_provider_registration = true +} + +# Student and free subscriptions often can't use some VM sizes in some regions +# (SkuNotAvailable). Look the size up at plan time so that fails early. +data "azapi_resource_list" "vm_size" { + type = "Microsoft.Compute/skus@2021-07-01" + parent_id = "/subscriptions/${var.subscription_id}" + query_parameters = { + "$filter" = ["location eq '${local.az_location}'"] + } + response_export_values = { + skus = "value[?resourceType=='virtualMachines' && name=='${var.azure_vm_size}'].{restrictions: restrictions[?type=='Location'].reasonCode, architecture: capabilities[?name=='CpuArchitectureType'].value | [0]}" + } +} + # Create a resource group resource "azurerm_resource_group" "ctf_rg" { name = "ctf-resources" @@ -271,6 +300,21 @@ resource "azurerm_linux_virtual_machine" "ctf_vm" { } custom_data = var.use_local_setup ? base64encode(local.local_bootstrap_script) : null + + lifecycle { + precondition { + condition = local.vm_size_sku != null + error_message = "VM size ${var.azure_vm_size} is not offered in ${var.az_region}. Try a different azure_vm_size (e.g. Standard_B1s or Standard_B1ms) or az_region. See TROUBLESHOOTING.md." + } + precondition { + condition = try(length(local.vm_size_sku.restrictions), 0) == 0 + error_message = "VM size ${var.azure_vm_size} is not available for your subscription in ${var.az_region} (${join(", ", try(local.vm_size_sku.restrictions, []))}). This is common on Azure for Students. Try a different azure_vm_size or az_region. See TROUBLESHOOTING.md." + } + precondition { + condition = local.vm_size_architecture == "x64" + error_message = "VM size ${var.azure_vm_size} is ${local.vm_size_architecture}, but the lab uses an x64 Ubuntu image. Choose an x64 size such as Standard_B1s, Standard_B1ms, or Standard_B2ats_v2." + } + } } resource "azurerm_virtual_machine_extension" "release_setup" {