Home > Mobile >  Terraform provisioning azure windows vmss behind a public load balancer
Terraform provisioning azure windows vmss behind a public load balancer

Time:07-27

I'm trying to create a simple windows vmss with iis installed which displays the computer name. For some reason my script isn't running and the public IP address doesn't work. Could someone show me where I've gone wrong please?

Code:

terraform {
  required_version = ">= 0.13"
}

provider "azurerm" {
  features {}
}

variable "admin_username" {
  sensitive = true
  

}

variable "admin_password" {
  sensitive = true
  

}

resource "azurerm_resource_group" "rg1" {
  name     = "rg2"
  location = "uksouth"

}

resource "azurerm_virtual_network" "vn" {
  name                = "vn-vmss"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name

}

resource "azurerm_subnet" "subnet1" {
  name                 = "subnet-vmss"
  resource_group_name  = azurerm_resource_group.rg1.name
  virtual_network_name = azurerm_virtual_network.vn.name
  address_prefixes     = ["10.0.1.0/24"]

}

resource "azurerm_public_ip" "vmss-pip" {
  name                = "vmss-pip"
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name
  allocation_method   = "Static"
  sku = "Standard"
  domain_name_label = "vmss10101"


  tags = {
    "app" = "scale-set"
    "env" = "dev"
  }

}

resource "azurerm_network_interface" "nic" {
  name                = "vmss-nic"
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name

  ip_configuration {
    name                          = "public"
    subnet_id                     = azurerm_subnet.subnet1.id
    private_ip_address_allocation = "Dynamic"
    
    
  }

}

resource "azurerm_network_security_group" "nsg1" {
  name                = "nsg1"
  resource_group_name = azurerm_resource_group.rg1.name
  location            = azurerm_resource_group.rg1.location
  security_rule {
    name                       = "allow-rdp"
    description                = "allow-rdp"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "3389"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }
  security_rule {
    name                       = "allow-http"
    description                = "allow-http"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }

}
resource "azurerm_subnet_network_security_group_association" "nsg-assoc" {
  depends_on = [
    azurerm_network_security_group.nsg1
  ]
  subnet_id                 = azurerm_subnet.subnet1.id
  network_security_group_id = azurerm_network_security_group.nsg1.id

}

resource "azurerm_lb" "vmss_lb" {
    name = "vmss_lb"
    location = azurerm_resource_group.rg1.location
    resource_group_name = azurerm_resource_group.rg1.name
    sku = "Standard"
    
    
    frontend_ip_configuration {
      name = "PublicIP"
      public_ip_address_id = azurerm_public_ip.vmss-pip.id
      #zones = ["1","3"]
    }     
}

resource "azurerm_lb_backend_address_pool" "backend" {
    name = "backend"
    loadbalancer_id = azurerm_lb.vmss_lb.id
    
     
}

resource "azurerm_lb_probe" "http_probe" {
    name = "http_probe"
    protocol = "Tcp"
    port = 80
    loadbalancer_id = azurerm_lb.vmss_lb.id
  
}

resource "azurerm_lb_rule" "lb_rule" {
    name = "lb_rule"
    loadbalancer_id = azurerm_lb.vmss_lb.id
    protocol = "Tcp"
    frontend_port = 80
    backend_port = 80
    frontend_ip_configuration_name = "PublicIP"
  
}

resource "azurerm_windows_virtual_machine_scale_set" "vmss" {
   
  name                = "vmss"
  resource_group_name = azurerm_resource_group.rg1.name
  location            = azurerm_resource_group.rg1.location
  sku                 = "Standard_F2"
  instances           = 2
  admin_password      = var.admin_password
  admin_username      = var.admin_username
  

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2016-Datacenter"
    version   = "latest"
  }

  os_disk {
    storage_account_type = "Standard_LRS"
    caching              = "ReadWrite"
  }

  network_interface {
    name    = "example"
    primary = true

    ip_configuration {
      name      = "internal"
      primary   = true
      subnet_id = azurerm_subnet.subnet1.id
      load_balancer_backend_address_pool_ids = [azurerm_lb_backend_address_pool.backend.id]
      
    }
  }
}


resource "azurerm_virtual_machine_scale_set_extension" "iis_vmss_extension" {
    name = "iis_vmss_ext"
    virtual_machine_scale_set_id = azurerm_windows_virtual_machine_scale_set.vmss.id
    publisher            = "Microsoft.Compute"
    type                 = "CustomScriptExtension"
    type_handler_version = "1.9"
    protected_settings = <<SETTINGS
  {
    "commandToExecute": "powershell -command \"[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${base64encode(data.template_file.tf.rendered)}')) | Out-File -filepath iis.ps1\" && powershell -ExecutionPolicy Unrestricted -File iis.ps1"
  }
  SETTINGS
}


data "template_file" "tf" {
    template = "${file("iis.ps1")}"
} 
    

iis.ps1

Install-WindowsFeature -name Web-Server -IncludeManagementTools Add-Content -Path "C:\inetpub\wwwroot\Default.htm" -Value $($env:computername)

CodePudding user response:

We have tried the same in our local and it works fine after doing some modification in your code .

The PowerShell script which needs to be execute inside settings , this is case sensitive we need to use it properly. I have tried to execute PowerShell command directly without referring to iis.ps1 or any variable to it.

And after testing extension has been successfully installed with the image we provided in VMSS .

You can try with the below; main.tf

terraform {
  required_version = ">= 0.13"
}

provider "azurerm" {
  features {}
}


resource "azurerm_resource_group" "rg1" {
  name     = "rg2"
  location = "westus2"

}

resource "azurerm_virtual_network" "vn" {
  name                = "vn-vmss"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name

}

resource "azurerm_subnet" "subnet1" {
  name                 = "subnet-vmss"
  resource_group_name  = azurerm_resource_group.rg1.name
  virtual_network_name = azurerm_virtual_network.vn.name
  address_prefixes     = ["10.0.1.0/24"]

}

resource "azurerm_public_ip" "vmss-pip" {
  name                = "vmss-pip"
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name
  allocation_method   = "Static"
  sku = "Standard"
  domain_name_label = "vmss10101"


  tags = {
    "app" = "scale-set"
    "env" = "dev"
  }

}

resource "azurerm_network_interface" "nic" {
  name                = "vmss-nic"
  location            = azurerm_resource_group.rg1.location
  resource_group_name = azurerm_resource_group.rg1.name

  ip_configuration {
    name                          = "public"
    subnet_id                     = azurerm_subnet.subnet1.id
    private_ip_address_allocation = "Dynamic"
    
    
  }

}

resource "azurerm_network_security_group" "nsg1" {
  name                = "nsg1"
  resource_group_name = azurerm_resource_group.rg1.name
  location            = azurerm_resource_group.rg1.location
  security_rule {
    name                       = "allow-rdp"
    description                = "allow-rdp"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "3389"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }
  security_rule {
    name                       = "allow-http"
    description                = "allow-http"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }

}
resource "azurerm_subnet_network_security_group_association" "nsg-assoc" {
  depends_on = [
    azurerm_network_security_group.nsg1
  ]
  subnet_id                 = azurerm_subnet.subnet1.id
  network_security_group_id = azurerm_network_security_group.nsg1.id

}

resource "azurerm_lb" "vmss_lb" {
    name = "vmss_lb"
    location = azurerm_resource_group.rg1.location
    resource_group_name = azurerm_resource_group.rg1.name
    sku = "Standard"
    
    
    frontend_ip_configuration {
      name = "PublicIP"
      public_ip_address_id = azurerm_public_ip.vmss-pip.id
      #zones = ["1","3"]
    }     
}

resource "azurerm_lb_backend_address_pool" "backend" {
    name = "backend"
    loadbalancer_id = azurerm_lb.vmss_lb.id
    
     
}

resource "azurerm_lb_probe" "http_probe" {
    name = "http_probe"
    protocol = "Tcp"
    port = 80
    loadbalancer_id = azurerm_lb.vmss_lb.id
  
}

resource "azurerm_lb_rule" "lb_rule" {
    name = "lb_rule"
    loadbalancer_id = azurerm_lb.vmss_lb.id
    protocol = "Tcp"
    frontend_port = 80
    backend_port = 80
    frontend_ip_configuration_name = "PublicIP"
  
}

resource "azurerm_windows_virtual_machine_scale_set" "vmss" {
   
  name                = "vmss"
  resource_group_name = azurerm_resource_group.rg1.name
  location            = azurerm_resource_group.rg1.location
  sku                 = "Standard_F2"
  instances           = 2
  admin_password      = "Pxxxxx123!"
  admin_username      = "adminUsername"

  

  source_image_reference {
    publisher = "MicrosoftWindowsServer"
    offer     = "WindowsServer"
    sku       = "2016-Datacenter"
    version   = "latest"
  }

  os_disk {
    storage_account_type = "Standard_LRS"
    caching              = "ReadWrite"
  }

  network_interface {
    name    = "example"
    primary = true

    ip_configuration {
      name      = "internal"
      primary   = true
      subnet_id = azurerm_subnet.subnet1.id
      load_balancer_backend_address_pool_ids = [azurerm_lb_backend_address_pool.backend.id]
      
    }
  }
}


resource "azurerm_virtual_machine_scale_set_extension" "iis_vmss_extension" {
    name = "iis_vmss_ext"
    virtual_machine_scale_set_id = azurerm_windows_virtual_machine_scale_set.vmss.id
    publisher            = "Microsoft.Compute"
    type                 = "CustomScriptExtension"
    type_handler_version = "1.9"
  settings = <<SETTINGS
    {
        "commandToExecute": "powershell -ExecutionPolicy Unrestricted Install-WindowsFeature -Name Web-Server -IncludeAllSubFeature -IncludeManagementTools"
    }
SETTINGS
}

#data "template_file" "tf" {
#    template = "${file("iis.ps1")}"
#} 

OUTPUT SCREENSHOT FOR REFERNCE:- enter image description here enter image description here

enter image description here

enter image description here enter image description here

For more information please refer this Blog|Install IIS on Azure VM using Terraform by @Facundo Gauna .

CodePudding user response:

I copied the code the only change I made was the region. I can see the extension from your screenshot. When you accessed the public IP did you get the IIS page showing?

  • Related