Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”. This article also participated in the “Digitalstar Project” to win a creative gift package and creative incentive money.

In the previous three practical deployment exercises, we learned about application deployment, resource group, and virtual network creation deployment. In this article we deploy a relatively complex infrastructure, cloud computing instance, in combination with the modules that are important to Terraform.

First, build reuse module

Terraform module is an important means to write high-quality Terraform code and improve the reuse of code. It can be said that a mature production environment should be assembled by several credible mature modules.

The basic documents of Terraform module shall be provided as follows:

  • Main.tf, for resource definition, interdependence
  • Variable. tf, used to declare variables, so that the calling module side can use its own values
  • Elsiders.tf, to carry on the content that the caller cares about after the resource is created, such as the resource Id, etc

So we first create a folder, azure_machine_module, to hold our module, with the directory structure shown below.

README.mdDocumentation is used to describe the module for your convenience.

1.1 the resource group

Resource groups are containers for holding Azure solution-related resources. A resource group can contain all the resources of a solution, or it can contain only the resources you want to manage as a group.

#main.tf
# resource group
resource "azurerm_resource_group" "myterraformgroup" {
    name     = "myResourceGroup"
    location = var.location
    tags = {
        environment = "Terraform Demo"}}Copy the code

1.2 Network

It is well known that for Azure home products, when creating compute instances (virtual machines), you need to create a virtual network for them or use the current virtual network. As a best practice, each group of virtual machines will be assigned to a separate subnet of the virtual network, as shown in the figure below.

So what we have to say aboutNetwork communicationIn this part, we need to provide network interface, virtual network interface, subnet.

#main.tf
# random string
resource "random_string" "nic_prefix" {
  length  = 4
  special = false
}

# Virtual network interface
resource "azurerm_virtual_network" "myterraformnetwork" {
    name                = "myVnet"
    address_space       = ["10.0.0.0/16"]
    location            = var.location
    resource_group_name = azurerm_resource_group.myterraformgroup.name
    tags = {
        environment = "Terraform Demo"}}# subnet
resource "azurerm_subnet" "myterraformsubnet" {
    name                 = "mySubnet"
    resource_group_name  = azurerm_resource_group.myterraformgroup.name
    virtual_network_name = azurerm_virtual_network.myterraformnetwork.name
    address_prefixes       = ["10.0.1.0/24"]}# Network interface
resource "azurerm_network_interface" "vm_nic" {
  name                = "${var.vm_name}-nic1"
  location            = var.location
  resource_group_name = azurerm_resource_group.myterraformgroup.name
  ip_configuration {
    name                          = "${var.vm_name}_nic_${random_string.nic_prefix.result}"
    subnet_id                     = azurerm_subnet.myterraformsubnet.id
    private_ip_address_allocation = "Static"
    private_ip_address            = var.static_ip_address
  }
  tags = var.tags
}
Copy the code

Due to the time, part of the dynamic variables are not taken out, and the optimization will be carried out when there is time.

1.3 the virtual machine

To deploy virtual machines, we need to use resource groups, networks, and instance security groups to ensure access security.

#main.tf
# security group
resource "azurerm_network_interface_security_group_association" "vm_nic_sg" {
  network_interface_id      = azurerm_network_interface.vm_nic.id
  network_security_group_id = var.network_security_group_id
  count                     = var.network_security_group_id = = "" ? Zero: 1
}

# example
resource "azurerm_virtual_machine" "windows_vm" {
  name                = var.vm_name
  vm_size             = var.vm_size
  location            = var.location
  resource_group_name = azurerm_resource_group.myterraformgroup.name

  tags = merge(var.tags, { activityName = "${var.activity_tag} " })

  network_interface_ids = [
    "${azurerm_network_interface.vm_nic.id}",]storage_image_reference {
    publisher = var.publisher
    offer     = var.offer
    sku       = var.sku
    version   = "latest"
  }

  identity {
    type = "SystemAssigned"
  }

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

  os_profile {
    admin_password = var.admin_password
    admin_username = "azureuser"
    computer_name  = var.vm_name
  }

  os_profile_windows_config {
    provision_vm_agent = true
  }

  delete_os_disk_on_termination    = var.vm_os_disk_delete_flag
  delete_data_disks_on_termination = var.vm_data_disk_delete_flag
}
Copy the code

1.4 other

You also need to define input and output variables.

The # exmission.tf file outputs anything we want to pass back to the root user for reuse
output "vm_id" {
  value = "${azurerm_virtual_machine.windows_vm.id}"
}

output "vm_name" {
  value = "${azurerm_virtual_machine.windows_vm.name}"
}

output "vm_location" {
  value = "${azurerm_virtual_machine.windows_vm.location}"
}

output "vm_resource_group_name" {
  value = "${azurerm_virtual_machine.windows_vm.resource_group_name}"
}
Copy the code
The # variables.tf file defines all variables that the module expects to define from the root module call
# variable "resource_group_name" {
#}

variable "location"{}variable "sloc"{}variable "vm_size" {
  default = "Standard_B1s"
}

# variable "vm_subnet_id" {
#}

variable "vm_name"{}variable "vm_os_disk_delete_flag" {
  default = true
}

variable "vm_data_disk_delete_flag" {
  default = true
}

variable "network_security_group_id" {
  default = ""
}

variable "static_ip_address"{}variable "publisher"{}variable "offer"{}variable "sku"{}variable "tags" {
  type        = map
  description = "All mandatory tags to use on all assets"

  default = {
    activityName       = "AzureVMWindowsDemo"
    automation         = "Terraform"
    costCenter1        = "A00000"
    dataClassification = "Demo"
    managedBy          = "[email protected]"
    solutionOwner      = "[email protected]"}}variable "activity_tag"{}variable "admin_password"{}Copy the code

That’s it, module definition is complete!

Second, use modules to build business

The entire project structure directory is shown in the figure below.

Main.tf file, using submodules, providing detailed parameters, authentication information

module windows_desktop_vm_using_local_module {
  source              = "./azure_machine_module"
 # resource_group_name = azurerm_resource_group.myterraformgroup.name
  location            = "eastus"
  sloc                = "uks"
# vm_subnet_id = module.azurerm_network_interface.vnet_subnets[0]
  vm_name             = "testCompute"
  vm_size             = var.desktop_vm_size
  publisher           = var.desktop_vm_image_publisher
  offer               = var.desktop_vm_image_offer
  sku                 = var.desktop_vm_image_sku
  static_ip_address   = "10.0.1.15"
  activity_tag        = "Windows Desktop"
  admin_password      = ! "" @#qwe123"
}

provider "azurerm" {
   features {}
   subscription_id   = "<yours>"
   tenant_id         = "<yours>"
   client_id         = "<yours>"
   client_secret     = "<yours>"
}
Copy the code

Variable. tf, define variables

# read in from the terraform.auto.tfvars file
variable "global_settings"{}variable "desktop_vm_image_publisher"{}variable "desktop_vm_image_offer"{}variable "desktop_vm_image_sku"{}variable "desktop_vm_image_version"{}variable "desktop_vm_size"{}Copy the code

Terraform.auto. Tfvars, the actual parameter

global_settings = {

  #Set of tags 
  tags = {
    applicationName = "Windows VM Demo"
    businessUnit    = "Technical Solutions"
    costCenter      = "MPN Sponsorship"
    DR              = "NON-DR-ENABLED"
    deploymentType  = "Terraform"
    environment     = "Dev"
    owner           = "Jack Roper"
    version         = "0.1"}}# Desktop VM variables
desktop_vm_image_publisher  = "MicrosoftWindowsDesktop" 
desktop_vm_image_offer      = "Windows-10" 
desktop_vm_image_sku        = "20h1-pro" 
desktop_vm_image_version    = "latest"
desktop_vm_size             = "Standard_B1s"
Copy the code

3. Perform deployment

Terraform init Initializes the environment

terraform planPreviewing deployment Plans

terraform applyPerform the deployment

It took about six minutes to create the execution deployment process, which was a long wait.

Check the Azure Portal Control panel to ensure that the resource was successfully created.