Contents

Azure and Terraform - Load Balancer

Azure Terraform Templates

Here you will find the setup I created during the last few days studying some Azure resources.

The files listed bellow will create and launch a infrastructure in Azure. This is what is called “Infra as code”. Each file describes what resource I would like to create on Azure and how it should look like.

By the end of the execution you will have all it is needed to run

  1. 2 VMs
  2. 1 Load Balancer

To keep things organized resources are divided into files.

File Reason
variables.tf Definition of variables to be used by other files
terraform.tfvars Values to some of the variables to be used
providers.tf To tell terraform what provider we would like to use. In case of Azure we use azurerm
rg.tf Definitions and configuration values for our resource groups
storage_account.tf Definitions and configuration values to create a storage account to be used by other resources
vnet.tf Definition and configuration values to create a vnet to be used by network adapters (nic)
subnet.tf Definition and configuration values to create a subnet
nic.tf Definition and configuration values of network adapters to be used by VMs
aset.tf Definition and configuration values to create availability sets so we can have vms in different racks
vm.tf Definition and configuration values for a VM
public_ip.tf Definition and configuration valuer for an external IP used by the load balancer
lb.tf Definition and configuration to create a load balancer
lb_probe.tf Definition and configuration to configure probe values for the load balancer
lb_be_addr_pool.tf Definition and configuration to configure the pool of VMs which will be under the load balancer
lb_rules.tf Definition and configuration to configure route rules for the load balancer and the services it will forward the data to

If you are curious about each configuration and what else can you do/configure there is always a link to the resource on azurerm so you can read more about other parameters I’m not using


variables.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
variable "subscription_id" {
  type = string
  description = "Subscription ID"
}

variable "location" {
  type = string
  description = "Resource Group Location"
}

variable "vm_name" {
    description = "List of VM names"
    type = list(string)
    default = ["vm-01", "vm-02"]
}

variable "prefix" {
  description = "Resource Name Prefix"
  type = string
  default = "rainbow"
}

variable "environment" {
  description = "Environment name"
  type = string
}

terraform.tfvars

1
2
3
subscription_id = "....-....-....-....-......"
location = "Central US"
environment = "sandbox"

providers.tf

1
2
3
4
5
## <https://www.terraform.io/docs/providers/azurerm/index.html>
provider "azurerm" {
  subscription_id = var.subscription_id
  features {}
}

rg.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
## <https://www.terraform.io/docs/providers/azurerm/r/resource_group>
resource "azurerm_resource_group" "app" {
  name = "${var.prefix}-${var.environment}-app"
  location = var.location
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

## <https://www.terraform.io/docs/providers/azurerm/r/resource_group>
resource "azurerm_resource_group" "net" {
  name = "${var.prefix}-${var.environment}-vnet"
  location = var.location
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

## <https://www.terraform.io/docs/providers/azurerm/r/resource_group>
resource "azurerm_resource_group" "lb" {
  name     = "${var.prefix}-${var.environment}-lb"
  location = var.location
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

storage_account.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
## <https://www.terraform.io/docs/providers/azurerm/r/storage_account>
resource "azurerm_storage_account" "storage" {
  name = "${var.prefix}storageaccount"
  resource_group_name = azurerm_resource_group.app.name
  location = var.location
  account_tier = "Standard"
  account_replication_type = "LRS"
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

vnet.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## <https://www.terraform.io/docs/providers/azurerm/r/virtual_network>
resource "azurerm_virtual_network" "vnet" {
  name = "${var.prefix}-vms-vnet"
  location = var.location
  resource_group_name = azurerm_resource_group.net.name
  address_space = ["10.0.0.0/16"]
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

## <https://www.terraform.io/docs/providers/azurerm/r/virtual_network>
resource "azurerm_virtual_network" "vnet_aks" {
  name = "${var.prefix}-aks-vnet"
  location = var.location
  resource_group_name = azurerm_resource_group.net.name
  address_space = ["10.1.0.0/16"]
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

subnet.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
## <https://www.terraform.io/docs/providers/azurerm/r/subnet>
resource "azurerm_subnet" "subnet" {
  name = "${var.prefix}-vms-subnet"
  resource_group_name = azurerm_resource_group.net.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes = ["10.0.1.0/24"]
}

## <https://www.terraform.io/docs/providers/azurerm/r/subnet>
resource "azurerm_subnet" "subnet_aks" {
  name = "${var.prefix}-aks-subnet"
  resource_group_name = azurerm_resource_group.net.name
  virtual_network_name = azurerm_virtual_network.vnet_aks.name
  address_prefixes = ["10.1.0.0/22"]
}

nic.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
## <https://www.terraform.io/docs/providers/azurerm/r/network_interface.html>
resource "azurerm_network_interface" "nic" {
  for_each = toset(var.vm_name)
  name = "${var.prefix}-${each.value}-nic"
  location = var.location
  resource_group_name = azurerm_resource_group.app.name
  ip_configuration {
    name = "${var.prefix}-${each.value}-ipconfig"
    subnet_id = azurerm_subnet.subnet.id
    private_ip_address_allocation = "Dynamic"
  }
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
    belongs_to = each.value
  }
}

aset.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/availability_set>
resource "azurerm_availability_set" "avset" {
 name                         = "${var.prefix}-avset"
 location                     = var.location
 resource_group_name          = azurerm_resource_group.app.name
 platform_fault_domain_count  = 2
 platform_update_domain_count = 2
 managed                      = true
 tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

vm.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
## <https://www.terraform.io/docs/providers/azurerm/r/windows_virtual_machine>
resource "azurerm_virtual_machine" "vm" {
  for_each = toset(var.vm_name)
  name = "${var.prefix}-${each.value}"
  location = var.location
  resource_group_name = azurerm_resource_group.app.name
  network_interface_ids = [azurerm_network_interface.nic[each.key].id]
  availability_set_id   = azurerm_availability_set.avset.id
  vm_size = "Standard_B1LS"

  delete_os_disk_on_termination = true
  delete_data_disks_on_termination =  true

  storage_image_reference {
    publisher = "Canonical"
    offer = "UbuntuServer"
    sku = "18.04-LTS"
    version = "latest"
  }

  storage_os_disk {
    name = "${var.prefix}-${each.key}-os-disk"
    caching = "ReadWrite"
    create_option = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  storage_data_disk {
    name = "${var.prefix}-${each.key}-data-disk"
    caching = "None"
    create_option = "Empty"
    disk_size_gb = 512
    lun = 0
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name = "${var.prefix}-${each.key}"
    admin_username = "${each.key}-adm"
  }

  os_profile_linux_config {
    disable_password_authentication = true
    ssh_keys {
      path   = "/home/${each.key}-adm/.ssh/authorized_keys"
      key_data = file("~/.ssh/id_rsa.pub")
    }
  }
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
    belongs_to = each.value
  }
}

## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/dev_test_global_vm_shutdown_schedule>
resource "azurerm_dev_test_global_vm_shutdown_schedule" "vm_shutdown" {
  for_each = toset(var.vm_name)
  virtual_machine_id = azurerm_virtual_machine.vm[each.key].id
  location           = var.location
  enabled            = true

  daily_recurrence_time = "1500"
  timezone              = "Pacific Standard Time"

  notification_settings {
     enabled = false
  }
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
    belongs_to = each.value
  }
}

public_ip.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip>
resource "azurerm_public_ip" "public_ip_lb" {
  name                = "${var.prefix}-public-ip-loadbalancer"
  location            = var.location
  resource_group_name = azurerm_resource_group.lb.name
  allocation_method   = "Static"
  sku = "Standard"
  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

lb.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb>
resource "azurerm_lb" "lb" {
  name = "${var.prefix}-lb"
  location = var.location
  resource_group_name = azurerm_resource_group.lb.name
  sku = "standard"

  frontend_ip_configuration {
    name = "${var.prefix}-loadbalancer-front-end-ip"
    public_ip_address_id = azurerm_public_ip.public_ip_lb.id
  }

  tags = {
    owner = "unicorn"
    environment = var.environment
    budget_code = var.prefix
  }
}

lb_probe.tf

1
2
3
4
5
6
7
## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_probe>
resource "azurerm_lb_probe" "lb_probe" {
  resource_group_name = azurerm_resource_group.lb.name
  loadbalancer_id = azurerm_lb.lb.id
  name = "${var.prefix}-http-running-probe"
  port = 8080
}

lb_be_addr_pool.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_backend_address_pool>
resource "azurerm_lb_backend_address_pool" "lb_backend_pool" {
  resource_group_name = azurerm_resource_group.lb.name
  loadbalancer_id = azurerm_lb.lb.id
  name  = "rainbow-lb-back-end-address-pool"
}

## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_interface_backend_address_pool_association>
resource "azurerm_network_interface_backend_address_pool_association" "lb_association" {
  for_each = toset(var.vm_name)
  network_interface_id = azurerm_network_interface.nic[each.key].id
  ip_configuration_name   = "${var.prefix}-${each.value}-ipconfig"
  backend_address_pool_id = azurerm_lb_backend_address_pool.lb_backend_pool.id
}

lb_rules.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_rule>
resource "azurerm_lb_rule" "lb_rule_80" {
  resource_group_name            = azurerm_resource_group.lb.name
  loadbalancer_id                = azurerm_lb.lb.id
  name                           = "${var.prefix}-port-80"
  protocol                       = "Tcp"
  frontend_port                  = 80
  backend_port                   = 8080
  frontend_ip_configuration_name = azurerm_lb.lb.frontend_ip_configuration[0].name
  backend_address_pool_id = azurerm_lb_backend_address_pool.lb_backend_pool.id
  probe_id = azurerm_lb_probe.lb_probe.id
}

## <https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/lb_rule>
resource "azurerm_lb_rule" "lb_rule_443" {
  resource_group_name            = azurerm_resource_group.lb.name
  loadbalancer_id                = azurerm_lb.lb.id
  name                           = "${var.prefix}-port-443"
  protocol                       = "Tcp"
  frontend_port                  = 443
  backend_port                   = 8443
  frontend_ip_configuration_name = azurerm_lb.lb.frontend_ip_configuration[0].name
  backend_address_pool_id = azurerm_lb_backend_address_pool.lb_backend_pool.id
  probe_id = azurerm_lb_probe.lb_probe.id
}