Back to Checks
azure

Virtual Machine Scale Set is associated with a load balancer backend pool

vm_scaleset_associated_with_load_balancer
Service: vmSeverity: medium
OfficialBuilt-inVerified
Categories:resilience
Resource Type:microsoft.compute/virtualmachinescalesets

Azure VM scale sets are associated with at least one load balancer backend pool.

The evaluation looks for a backend pool link on each scale set's network configuration.

Risk

Without a load balancer, traffic targets instances directly, bypassing health-based distribution. This degrades availability (overloads, no failover) and reliability (dropped sessions, uneven scaling) and can amplify DoS impact by concentrating flows on fewer nodes, increasing outage risk.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler azure --checks vm_scaleset_associated_with_load_balancer

Recommendation

Associate VM scale sets with a Standard Load Balancer backend pool to enforce health-probed, even distribution and seamless failover.

Design for high availability: run multiple instances across zones, enable autoscale, and apply defense in depth with limited exposure and NSG controls. Prefer SKU Standard over legacy Basic.

Remediation

CLI

az vmss update --resource-group <RESOURCE_GROUP> --name <VMSS_NAME> --add virtualMachineProfile.networkProfile.networkInterfaceConfigurations[0].ipConfigurations[0].loadBalancerBackendAddressPools '{"id":"/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Network/loadBalancers/<LB_NAME>/backendAddressPools/<BACKEND_POOL_NAME>"}'

Terraform

# Attach VMSS to an existing Load Balancer backend pool
resource "azurerm_linux_virtual_machine_scale_set" "<example_resource_name>" {
  name                = "<example_resource_name>"
  resource_group_name = "<example_resource_name>"
  location            = "<example_location>"
  sku                 = "Standard_DS1_v2"
  instances           = 1

  admin_username                  = "azureuser"
  disable_password_authentication = true
  admin_ssh_key {
    username   = "azureuser"
    public_key = "<SSH_PUBLIC_KEY>"
  }

  source_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }

  network_interface {
    name    = "nic"
    primary = true
    ip_configuration {
      name                                   = "ipcfg"
      primary                                = true
      subnet_id                              = "<example_resource_id>"
      load_balancer_backend_address_pool_ids = ["<example_resource_id>"] # CRITICAL: associates VMSS with LB backend pool
    }
  }
}

NativeIaC

// Associate VMSS with a Load Balancer backend pool
resource vmss 'Microsoft.Compute/virtualMachineScaleSets@2023-09-01' = {
  name: '<example_resource_name>'
  location: resourceGroup().location
  properties: {
    virtualMachineProfile: {
      networkProfile: {
        networkInterfaceConfigurations: [
          {
            name: 'nic'
            properties: {
              ipConfigurations: [
                {
                  name: 'ipcfg'
                  properties: {
                    loadBalancerBackendAddressPools: [
                      { id: '<example_resource_id>' } // CRITICAL: attach VMSS NIC IP config to LB backend pool
                    ]
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Other

1In Azure Portal, go to Load balancers > select <LB_NAME>
2Under Settings, open Backend pools and select the target backend pool
3Click Add > IP configurations
4Choose Virtual machine scale set, select <VMSS_NAME> and its IP configuration
5Click Add, then Save to attach the scale set to the backend pool

Check Code

from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.vm.vm_client import vm_client


class vm_scaleset_associated_with_load_balancer(Check):
    """
    Ensure that Azure virtual machine scale sets are associated with a load balancer backend pool.

    This check evaluates whether each VM scale set is associated with at least one load balancer backend pool.
    - PASS: The scale set is associated with a load balancer backend pool.
    - FAIL: The scale set is not associated with any load balancer backend pool.
    """

    def execute(self):
        findings = []
        for subscription, scale_sets in vm_client.vm_scale_sets.items():
            subscription_name = vm_client.subscriptions.get(subscription, subscription)
            for scale_set in scale_sets.values():
                report = Check_Report_Azure(
                    metadata=self.metadata(), resource=scale_set
                )
                report.subscription = subscription
                report.resource_id = scale_set.resource_id
                report.resource_name = scale_set.resource_name
                report.location = scale_set.location
                if scale_set.load_balancer_backend_pools:
                    report.status = "PASS"
                    backend_pool_names = [
                        pool.split("/")[-1]
                        for pool in scale_set.load_balancer_backend_pools
                    ]
                    report.status_extended = f"Scale set '{scale_set.resource_name}' in subscription '{subscription_name} ({subscription})' is associated with load balancer backend pool(s): {', '.join(backend_pool_names)}."
                else:
                    report.status = "FAIL"
                    report.status_extended = f"Scale set '{scale_set.resource_name}' in subscription '{subscription_name} ({subscription})' is not associated with any load balancer backend pool."
                findings.append(report)
        return findings