This project will deploy a set number of virtual machines (default is 3) behind a load balancer, and set up all the other resources that need to be deployed for those virtual machines such as network security groups so the VM's are only accessible through the internal network, Virtual Networks, Subnets, Virtual Nics and more.
- Create an Azure Account
- Install the Azure command line interface
- Install Packer
- Install Terraform
- Clone this repository
- Create environment variables
- Modify the packer file
- Modify terraform variable files if necessary
-
Log in to your Azure subscription and create a resource group for your image. The default in the terraform var.json is
udacity-image-rg
-
Modify the packer file (server.json) so the image builds in your perferred region, and modify it to include the resource group name you made in step 1.
-
Open on your terminal and add the following environment variables
- ARM_CLIENT_ID
- ARM_CLIENT_SECRET
- ARM_SUBSCRIPTION_ID
- ARM_TENANT_ID
These variables are used to connect to your subscription on Azure. Below are examples of adding enviroment variables to your terminal and os of choice.
Example: $env:ARM_CLIENT_ID = '0000000-0000-0000-0000-000000000000'
Example: export ARM_CLIENT_ID='0000000-0000-0000-0000-000000000000'
Example: ARM_CLIENT_ID='0000000-0000-0000-0000-000000000000'
Note: These variables are only there for the life time of the terminal if you would like to make thme permant you will have to look up the documentation for your operating system.
- Once all of the above steps are completed you can now run the command
packer build server.json
to build your server image. This may take a while so grab a cup of tea.
The terraform file creates these resources listed below
- resource group
- virtual network
- subnet
- network security group limiting access
- network interfaces
- a public ip
- load balancer
- availability set for the virtual machines
- Linux virtual machines (3 by default)
- 1 managed disk per instance
-
Run
terraform init
to prepare your directory for terraform -
Modify the
vars.tf
file if necessary, this contains the variables for the resource group name, prefix for most resources, number of vm's to create, and location. If number of VM's and Location are not specified they will default to3
instances andCanada East
respectively. You will need to change thepacker_resource_group
variable if you used a different resource group name for the packer image. -
Review the
main.tf
to confirm that is creating the correct resources for your needs. -
You can now run
terraform plan
to show the changes terraform will be making. Once comfortable you can nowterraform apply
to apply those changes and have terraform deploy those resources. -
If you no longer need the resources go ahead and run
terraform destory
this will remove all the resources in this script.
The following will be output by terraform if you have executed the terraform plan
and the same output will be made when using the terraform apply
.
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# azurerm_availability_set.main will be created
+ resource "azurerm_availability_set" "main" {
+ id = (known after apply)
+ location = "canadacentral"
+ managed = true
+ name = "udacity-pg-aset"
+ platform_fault_domain_count = 2
+ platform_update_domain_count = 5
+ resource_group_name = "udacity-project1-rg"
}
# azurerm_lb.main will be created
+ resource "azurerm_lb" "main" {
+ id = (known after apply)
+ location = "canadacentral"
+ name = "udacity-pg-lb"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ resource_group_name = "udacity-project1-rg"
+ sku = "Basic"
+ frontend_ip_configuration {
+ id = (known after apply)
+ inbound_nat_rules = (known after apply)
+ load_balancer_rules = (known after apply)
+ name = "PublicIPAddress"
+ outbound_rules = (known after apply)
+ private_ip_address = (known after apply)
+ private_ip_address_allocation = (known after apply)
+ private_ip_address_version = "IPv4"
+ public_ip_address_id = (known after apply)
+ public_ip_prefix_id = (known after apply)
+ subnet_id = (known after apply)
}
}
# azurerm_lb_backend_address_pool.main will be created
+ resource "azurerm_lb_backend_address_pool" "main" {
+ backend_ip_configurations = (known after apply)
+ id = (known after apply)
+ load_balancing_rules = (known after apply)
+ loadbalancer_id = (known after apply)
+ name = "udacity-pg-lb-backend-pool"
+ resource_group_name = "udacity-project1-rg"
}
# azurerm_lb_probe.main will be created
+ resource "azurerm_lb_probe" "main" {
+ id = (known after apply)
+ interval_in_seconds = 15
+ load_balancer_rules = (known after apply)
+ loadbalancer_id = (known after apply)
+ name = "http-server-probe"
+ number_of_probes = 2
+ port = 8080
+ protocol = (known after apply)
+ resource_group_name = "udacity-project1-rg"
}
# azurerm_lb_rule.main will be created
+ resource "azurerm_lb_rule" "main" {
+ backend_address_pool_id = (known after apply)
+ backend_port = 8080
+ disable_outbound_snat = false
+ enable_floating_ip = false
+ frontend_ip_configuration_id = (known after apply)
+ frontend_ip_configuration_name = "PublicIPAddress"
+ frontend_port = 80
+ id = (known after apply)
+ idle_timeout_in_minutes = (known after apply)
+ load_distribution = (known after apply)
+ loadbalancer_id = (known after apply)
+ name = "HTTP"
+ probe_id = (known after apply)
+ protocol = "Tcp"
+ resource_group_name = "udacity-project1-rg"
}
# azurerm_linux_virtual_machine.main[0] will be created
+ resource "azurerm_linux_virtual_machine" "main" {
+ admin_password = (sensitive value)
+ admin_username = "ud-admin"
+ allow_extension_operations = true
+ availability_set_id = (known after apply)
+ computer_name = (known after apply)
+ disable_password_authentication = false
+ extensions_time_budget = "PT1H30M"
+ id = (known after apply)
+ location = "canadacentral"
+ max_bid_price = -1
+ name = "udacity-pg-0-vm"
+ network_interface_ids = (known after apply)
+ priority = "Regular"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ provision_vm_agent = true
+ public_ip_address = (known after apply)
+ public_ip_addresses = (known after apply)
+ resource_group_name = "udacity-project1-rg"
+ size = "Standard_B1ls"
+ source_image_id = "/subscriptions/d5e2b852-260c-4bdf-befb-9803d0d29cde/resourceGroups/udacity-image-rg/providers/Microsoft.Compute/images/udacity-server-image"
+ tags = {
+ "environment" = "dev"
+ "project-name" = "Deploying a Web Server in Azure"
}
+ virtual_machine_id = (known after apply)
+ zone = (known after apply)
+ os_disk {
+ caching = "ReadWrite"
+ disk_size_gb = (known after apply)
+ name = (known after apply)
+ storage_account_type = "Standard_LRS"
+ write_accelerator_enabled = false
}
}
# azurerm_linux_virtual_machine.main[1] will be created
+ resource "azurerm_linux_virtual_machine" "main" {
+ admin_password = (sensitive value)
+ admin_username = "ud-admin"
+ allow_extension_operations = true
+ availability_set_id = (known after apply)
+ computer_name = (known after apply)
+ disable_password_authentication = false
+ extensions_time_budget = "PT1H30M"
+ id = (known after apply)
+ location = "canadacentral"
+ max_bid_price = -1
+ name = "udacity-pg-1-vm"
+ network_interface_ids = (known after apply)
+ priority = "Regular"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ provision_vm_agent = true
+ public_ip_address = (known after apply)
+ public_ip_addresses = (known after apply)
+ resource_group_name = "udacity-project1-rg"
+ size = "Standard_B1ls"
+ source_image_id = "/subscriptions/d5e2b852-260c-4bdf-befb-9803d0d29cde/resourceGroups/udacity-image-rg/providers/Microsoft.Compute/images/udacity-server-image"
+ tags = {
+ "environment" = "dev"
+ "project-name" = "Deploying a Web Server in Azure"
}
+ virtual_machine_id = (known after apply)
+ zone = (known after apply)
+ os_disk {
+ caching = "ReadWrite"
+ disk_size_gb = (known after apply)
+ name = (known after apply)
+ storage_account_type = "Standard_LRS"
+ write_accelerator_enabled = false
}
}
# azurerm_linux_virtual_machine.main[2] will be created
+ resource "azurerm_linux_virtual_machine" "main" {
+ admin_password = (sensitive value)
+ admin_username = "ud-admin"
+ allow_extension_operations = true
+ availability_set_id = (known after apply)
+ computer_name = (known after apply)
+ disable_password_authentication = false
+ extensions_time_budget = "PT1H30M"
+ id = (known after apply)
+ location = "canadacentral"
+ max_bid_price = -1
+ name = "udacity-pg-2-vm"
+ network_interface_ids = (known after apply)
+ priority = "Regular"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ provision_vm_agent = true
+ public_ip_address = (known after apply)
+ public_ip_addresses = (known after apply)
+ resource_group_name = "udacity-project1-rg"
+ size = "Standard_B1ls"
+ source_image_id = "/subscriptions/d5e2b852-260c-4bdf-befb-9803d0d29cde/resourceGroups/udacity-image-rg/providers/Microsoft.Compute/images/udacity-server-image"
+ tags = {
+ "environment" = "dev"
+ "project-name" = "Deploying a Web Server in Azure"
}
+ virtual_machine_id = (known after apply)
+ zone = (known after apply)
+ os_disk {
+ caching = "ReadWrite"
+ disk_size_gb = (known after apply)
+ name = (known after apply)
+ storage_account_type = "Standard_LRS"
+ write_accelerator_enabled = false
}
}
# azurerm_managed_disk.main[0] will be created
+ resource "azurerm_managed_disk" "main" {
+ create_option = "Empty"
+ disk_iops_read_write = (known after apply)
+ disk_mbps_read_write = (known after apply)
+ disk_size_gb = 1
+ id = (known after apply)
+ location = "canadacentral"
+ name = "data-disk-0"
+ resource_group_name = "udacity-project1-rg"
+ source_uri = (known after apply)
+ storage_account_type = "Standard_LRS"
}
# azurerm_managed_disk.main[1] will be created
+ resource "azurerm_managed_disk" "main" {
+ create_option = "Empty"
+ disk_iops_read_write = (known after apply)
+ disk_mbps_read_write = (known after apply)
+ disk_size_gb = 1
+ id = (known after apply)
+ location = "canadacentral"
+ name = "data-disk-1"
+ resource_group_name = "udacity-project1-rg"
+ source_uri = (known after apply)
+ storage_account_type = "Standard_LRS"
}
# azurerm_managed_disk.main[2] will be created
+ resource "azurerm_managed_disk" "main" {
+ create_option = "Empty"
+ disk_iops_read_write = (known after apply)
+ disk_mbps_read_write = (known after apply)
+ disk_size_gb = 1
+ id = (known after apply)
+ location = "canadacentral"
+ name = "data-disk-2"
+ resource_group_name = "udacity-project1-rg"
+ source_uri = (known after apply)
+ storage_account_type = "Standard_LRS"
}
# azurerm_network_interface.main[0] will be created
+ resource "azurerm_network_interface" "main" {
+ applied_dns_servers = (known after apply)
+ dns_servers = (known after apply)
+ enable_accelerated_networking = false
+ enable_ip_forwarding = false
+ id = (known after apply)
+ internal_dns_name_label = (known after apply)
+ internal_domain_name_suffix = (known after apply)
+ location = "canadacentral"
+ mac_address = (known after apply)
+ name = "udacity-pg-0-nic"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ resource_group_name = "udacity-project1-rg"
+ virtual_machine_id = (known after apply)
+ ip_configuration {
+ name = "internal"
+ primary = true
+ private_ip_address = (known after apply)
+ private_ip_address_allocation = "dynamic"
+ private_ip_address_version = "IPv4"
+ subnet_id = (known after apply)
}
}
# azurerm_network_interface.main[1] will be created
+ resource "azurerm_network_interface" "main" {
+ applied_dns_servers = (known after apply)
+ dns_servers = (known after apply)
+ enable_accelerated_networking = false
+ enable_ip_forwarding = false
+ id = (known after apply)
+ internal_dns_name_label = (known after apply)
+ internal_domain_name_suffix = (known after apply)
+ location = "canadacentral"
+ mac_address = (known after apply)
+ name = "udacity-pg-1-nic"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ resource_group_name = "udacity-project1-rg"
+ virtual_machine_id = (known after apply)
+ ip_configuration {
+ name = "internal"
+ primary = true
+ private_ip_address = (known after apply)
+ private_ip_address_allocation = "dynamic"
+ private_ip_address_version = "IPv4"
+ subnet_id = (known after apply)
}
}
# azurerm_network_interface.main[2] will be created
+ resource "azurerm_network_interface" "main" {
+ applied_dns_servers = (known after apply)
+ dns_servers = (known after apply)
+ enable_accelerated_networking = false
+ enable_ip_forwarding = false
+ id = (known after apply)
+ internal_dns_name_label = (known after apply)
+ internal_domain_name_suffix = (known after apply)
+ location = "canadacentral"
+ mac_address = (known after apply)
+ name = "udacity-pg-2-nic"
+ private_ip_address = (known after apply)
+ private_ip_addresses = (known after apply)
+ resource_group_name = "udacity-project1-rg"
+ virtual_machine_id = (known after apply)
+ ip_configuration {
+ name = "internal"
+ primary = true
+ private_ip_address = (known after apply)
+ private_ip_address_allocation = "dynamic"
+ private_ip_address_version = "IPv4"
+ subnet_id = (known after apply)
}
}
# azurerm_network_interface_backend_address_pool_association.main[0] will be created
+ resource "azurerm_network_interface_backend_address_pool_association" "main" {
+ backend_address_pool_id = (known after apply)
+ id = (known after apply)
+ ip_configuration_name = "internal"
+ network_interface_id = (known after apply)
}
# azurerm_network_interface_backend_address_pool_association.main[1] will be created
+ resource "azurerm_network_interface_backend_address_pool_association" "main" {
+ backend_address_pool_id = (known after apply)
+ id = (known after apply)
+ ip_configuration_name = "internal"
+ network_interface_id = (known after apply)
}
# azurerm_network_interface_backend_address_pool_association.main[2] will be created
+ resource "azurerm_network_interface_backend_address_pool_association" "main" {
+ backend_address_pool_id = (known after apply)
+ id = (known after apply)
+ ip_configuration_name = "internal"
+ network_interface_id = (known after apply)
}
# azurerm_network_security_group.main will be created
+ resource "azurerm_network_security_group" "main" {
+ id = (known after apply)
+ location = "canadacentral"
+ name = "udacity-pg-nsg"
+ resource_group_name = "udacity-project1-rg"
+ security_rule = [
+ {
+ access = "Allow"
+ description = ""
+ destination_address_prefix = "*"
+ destination_address_prefixes = []
+ destination_application_security_group_ids = []
+ destination_port_range = "8080"
+ destination_port_ranges = []
+ direction = "Inbound"
+ name = "HTTP"
+ priority = 100
+ protocol = "Tcp"
+ source_address_prefix = "*"
+ source_address_prefixes = []
+ source_application_security_group_ids = []
+ source_port_range = "*"
+ source_port_ranges = []
},
]
}
# azurerm_public_ip.main will be created
+ resource "azurerm_public_ip" "main" {
+ allocation_method = "Static"
+ fqdn = (known after apply)
+ id = (known after apply)
+ idle_timeout_in_minutes = 4
+ ip_address = (known after apply)
+ ip_version = "IPv4"
+ location = "canadacentral"
+ name = "lb-public-ip"
+ resource_group_name = "udacity-project1-rg"
+ sku = "Basic"
}
# azurerm_resource_group.main will be created
+ resource "azurerm_resource_group" "main" {
+ id = (known after apply)
+ location = "canadacentral"
+ name = "udacity-project1-rg"
}
# azurerm_subnet.main will be created
+ resource "azurerm_subnet" "main" {
+ address_prefix = (known after apply)
+ address_prefixes = [
+ "10.0.2.0/24",
]
+ enforce_private_link_endpoint_network_policies = false
+ enforce_private_link_service_network_policies = false
+ id = (known after apply)
+ name = "internal"
+ resource_group_name = "udacity-project1-rg"
+ virtual_network_name = "udacity-pg-network"
}
# azurerm_subnet_network_security_group_association.main will be created
+ resource "azurerm_subnet_network_security_group_association" "main" {
+ id = (known after apply)
+ network_security_group_id = (known after apply)
+ subnet_id = (known after apply)
}
# azurerm_virtual_machine_data_disk_attachment.main[0] will be created
+ resource "azurerm_virtual_machine_data_disk_attachment" "main" {
+ caching = "ReadWrite"
+ create_option = "Attach"
+ id = (known after apply)
+ lun = 0
+ managed_disk_id = (known after apply)
+ virtual_machine_id = (known after apply)
+ write_accelerator_enabled = false
}
# azurerm_virtual_machine_data_disk_attachment.main[1] will be created
+ resource "azurerm_virtual_machine_data_disk_attachment" "main" {
+ caching = "ReadWrite"
+ create_option = "Attach"
+ id = (known after apply)
+ lun = 10
+ managed_disk_id = (known after apply)
+ virtual_machine_id = (known after apply)
+ write_accelerator_enabled = false
}
# azurerm_virtual_machine_data_disk_attachment.main[2] will be created
+ resource "azurerm_virtual_machine_data_disk_attachment" "main" {
+ caching = "ReadWrite"
+ create_option = "Attach"
+ id = (known after apply)
+ lun = 20
+ managed_disk_id = (known after apply)
+ virtual_machine_id = (known after apply)
+ write_accelerator_enabled = false
}
# azurerm_virtual_network.main will be created
+ resource "azurerm_virtual_network" "main" {
+ address_space = [
+ "10.0.0.0/16",
]
+ guid = (known after apply)
+ id = (known after apply)
+ location = "canadacentral"
+ name = "udacity-pg-network"
+ resource_group_name = "udacity-project1-rg"
+ subnet = (known after apply)
+ vm_protection_enabled = false
}
Plan: 26 to add, 0 to change, 0 to destroy.