Creación de un conjunto de escalado de máquinas virtuales de Azure mediante Terraform

Los conjuntos de escalado de máquinas virtuales de Azure permiten configurar máquinas virtuales idénticas. El número de instancias de máquina virtual se puede ajustar en función de la demanda o de una programación. Para más información, consulte Escalado automático de conjuntos de escalado de máquinas virtuales de Azure Portal.

En este artículo aprenderá a:

  • Configurar una implementación de Terraform
  • Usar variables y salidas para la implementación de Terraform
  • Crear e implementar la infraestructura de red
  • Crear e implementar un conjunto de escalado de máquinas virtuales y asociarlo a la red
  • Crear e implementar un Jumpbox para conectarse a las máquinas virtuales a través de SSH

1. Configurar su entorno

  • Suscripción de Azure: Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.

2. Implementación del código de Terraform

  1. Cree un directorio en el que probar el código de ejemplo de Terraform y conviértalo en el directorio actual.

  2. Cree un archivo llamado main.tf e inserte el siguiente código:

    terraform {
      required_version = ">=0.12"
      
      required_providers {
        azurerm = {
          source = "hashicorp/azurerm"
          version = "~>2.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
    resource "azurerm_resource_group" "vmss" {
     name     = var.resource_group_name
     location = var.location
     tags     = var.tags
    }
    
    resource "random_string" "fqdn" {
     length  = 6
     special = false
     upper   = false
     number  = false
    }
    
    resource "azurerm_virtual_network" "vmss" {
     name                = "vmss-vnet"
     address_space       = ["10.0.0.0/16"]
     location            = var.location
     resource_group_name = azurerm_resource_group.vmss.name
     tags                = var.tags
    }
    
    resource "azurerm_subnet" "vmss" {
     name                 = "vmss-subnet"
     resource_group_name  = azurerm_resource_group.vmss.name
     virtual_network_name = azurerm_virtual_network.vmss.name
     address_prefixes       = ["10.0.2.0/24"]
    }
    
    resource "azurerm_public_ip" "vmss" {
     name                         = "vmss-public-ip"
     location                     = var.location
     resource_group_name          = azurerm_resource_group.vmss.name
     allocation_method            = "Static"
     domain_name_label            = random_string.fqdn.result
     tags                         = var.tags
    }
    
    resource "azurerm_lb" "vmss" {
     name                = "vmss-lb"
     location            = var.location
     resource_group_name = azurerm_resource_group.vmss.name
    
     frontend_ip_configuration {
       name                 = "PublicIPAddress"
       public_ip_address_id = azurerm_public_ip.vmss.id
     }
    
     tags = var.tags
    }
    
    resource "azurerm_lb_backend_address_pool" "bpepool" {
     loadbalancer_id     = azurerm_lb.vmss.id
     name                = "BackEndAddressPool"
    }
    
    resource "azurerm_lb_probe" "vmss" {
     resource_group_name = azurerm_resource_group.vmss.name
     loadbalancer_id     = azurerm_lb.vmss.id
     name                = "ssh-running-probe"
     port                = var.application_port
    }
    
    resource "azurerm_lb_rule" "lbnatrule" {
       resource_group_name            = azurerm_resource_group.vmss.name
       loadbalancer_id                = azurerm_lb.vmss.id
       name                           = "http"
       protocol                       = "Tcp"
       frontend_port                  = var.application_port
       backend_port                   = var.application_port
       backend_address_pool_id        = azurerm_lb_backend_address_pool.bpepool.id
       frontend_ip_configuration_name = "PublicIPAddress"
       probe_id                       = azurerm_lb_probe.vmss.id
    }
    
    resource "azurerm_virtual_machine_scale_set" "vmss" {
     name                = "vmscaleset"
     location            = var.location
     resource_group_name = azurerm_resource_group.vmss.name
     upgrade_policy_mode = "Manual"
    
     sku {
       name     = "Standard_DS1_v2"
       tier     = "Standard"
       capacity = 2
     }
    
     storage_profile_image_reference {
       publisher = "Canonical"
       offer     = "UbuntuServer"
       sku       = "16.04-LTS"
       version   = "latest"
     }
    
     storage_profile_os_disk {
       name              = ""
       caching           = "ReadWrite"
       create_option     = "FromImage"
       managed_disk_type = "Standard_LRS"
     }
    
     storage_profile_data_disk {
       lun          = 0
       caching        = "ReadWrite"
       create_option  = "Empty"
       disk_size_gb   = 10
     }
    
     os_profile {
       computer_name_prefix = "vmlab"
       admin_username       = var.admin_user
       admin_password       = var.admin_password
       custom_data          = file("web.conf")
     }
    
     os_profile_linux_config {
       disable_password_authentication = false
     }
    
     network_profile {
       name    = "terraformnetworkprofile"
       primary = true
    
       ip_configuration {
         name                                   = "IPConfiguration"
         subnet_id                              = azurerm_subnet.vmss.id
         load_balancer_backend_address_pool_ids = [azurerm_lb_backend_address_pool.bpepool.id]
         primary = true
       }
     }
    
     tags = var.tags
    }
    
    resource "azurerm_public_ip" "jumpbox" {
     name                         = "jumpbox-public-ip"
     location                     = var.location
     resource_group_name          = azurerm_resource_group.vmss.name
     allocation_method            = "Static"
     domain_name_label            = "${random_string.fqdn.result}-ssh"
     tags                         = var.tags
    }
    
    resource "azurerm_network_interface" "jumpbox" {
     name                = "jumpbox-nic"
     location            = var.location
     resource_group_name = azurerm_resource_group.vmss.name
    
     ip_configuration {
       name                          = "IPConfiguration"
       subnet_id                     = azurerm_subnet.vmss.id
       private_ip_address_allocation = "dynamic"
       public_ip_address_id          = azurerm_public_ip.jumpbox.id
     }
    
     tags = var.tags
    }
    
    resource "azurerm_virtual_machine" "jumpbox" {
     name                  = "jumpbox"
     location              = var.location
     resource_group_name   = azurerm_resource_group.vmss.name
     network_interface_ids = [azurerm_network_interface.jumpbox.id]
     vm_size               = "Standard_DS1_v2"
    
     storage_image_reference {
       publisher = "Canonical"
       offer     = "UbuntuServer"
       sku       = "16.04-LTS"
       version   = "latest"
     }
    
     storage_os_disk {
       name              = "jumpbox-osdisk"
       caching           = "ReadWrite"
       create_option     = "FromImage"
       managed_disk_type = "Standard_LRS"
     }
    
     os_profile {
       computer_name  = "jumpbox"
       admin_username = var.admin_user
       admin_password = var.admin_password
     }
    
     os_profile_linux_config {
       disable_password_authentication = false
     }
    
     tags = var.tags
    }
    
  3. Cree un archivo llamado variables.tf que contenga las variables del proyecto e inserte el código siguiente:

    variable "resource_group_name" {
       description = "Name of the resource group in which the resources will be created"
       default     = "myResourceGroup"
    }
    
    variable "location" {
       default = "eastus"
       description = "Location where resources will be created"
    }
    
    variable "tags" {
       description = "Map of the tags to use for the resources that are deployed"
       type        = map(string)
       default = {
          environment = "codelab"
       }
    }
    
    variable "application_port" {
       description = "Port that you want to expose to the external load balancer"
       default     = 80
    }
    
    variable "admin_user" {
       description = "User name to use as the admin account on the VMs that will be part of the VM scale set"
       default     = "azureuser"
    }
    
    variable "admin_password" {
       description = "Default password for admin account"
    }
    
  4. Cree un archivo llamado output.tf para especificar qué valores muestra Terraform e inserte el código siguiente:

    output "vmss_public_ip_fqdn" {
       value = azurerm_public_ip.vmss.fqdn
    }
    
    output "jumpbox_public_ip_fqdn" {
       value = azurerm_public_ip.jumpbox.fqdn
    }
    
    output "jumpbox_public_ip" {
       value = azurerm_public_ip.jumpbox.ip_address
    }
    
  5. Cree un archivo llamado web.conf e inserte el siguiente código:

    #cloud-config
    packages:
     - nginx
    

3. Inicialización de Terraform

Para inicializar la implementación de Terraform, ejecute terraform init.

terraform init

Puntos clave:

  • Este comando descarga los módulos de Azure necesarios para crear un grupo de recursos de Azure.

4. Creación de un plan de ejecución de Terraform

Ejecute terraform plan para crear un plan de ejecución.

terraform plan -out main.tfplan

Puntos clave:

  • El comando terraform plan crea un plan de ejecución, pero no lo ejecuta. En su lugar, determina qué acciones son necesarias para crear la configuración especificada en los archivos de configuración. Este patrón le permite comprobar si el plan de ejecución coincide con sus expectativas antes de realizar cambios en los recursos reales.
  • El parámetro -out opcional permite especificar un archivo de salida para el plan. El uso del parámetro -out garantiza que el plan que ha revisado es exactamente lo que se aplica.
  • Para más información acerca de la seguridad y conservar los planes de ejecución, consulte la sección Advertencia de seguridad.

5. Aplicación de un plan de ejecución de Terraform

Ejecute terraform apply para aplicar el plan de ejecución a su infraestructura en la nube.

terraform apply main.tfplan

Puntos clave:

  • El comando terraform apply anterior da por hecho que ejecutó anteriormente terraform plan -out main.tfplan.
  • Si especificó un nombre de archivo diferente para el parámetro -out, use ese mismo nombre de archivo en la llamada a terraform apply.
  • Si no ha utilizado el parámetro -out, simplemente llame a terraform apply sin ningún parámetro.

6. Verificación de los resultados

  1. En la salida del comando terraform apply, verá los valores de lo siguiente:

    • Nombre de dominio completo de la máquina virtual
    • Nombre de dominio completo de Jumpbox
    • Dirección IP de Jumpbox
  2. Vaya a la dirección URL de la máquina virtual para confirmar una página predeterminada con el texto Welcome to nginx! (Le damos la bienvenida a nginx!).

  3. Use SSH para conectarse a la máquina virtual de Jumpbox con el nombre de usuario definido en el archivo de variables y la contraseña que especificó cuando ejecutó terraform apply. Por ejemplo: ssh azureuser@<ip_address>.

7. Limpieza de recursos

Cuando ya no necesite los recursos creados a través de Terraform, realice los pasos siguientes:

  1. Ejecute terraform plan y especifique la marca.

    terraform plan -destroy -out main.destroy.tfplan
    

    Puntos clave:

    • El comando terraform plan crea un plan de ejecución, pero no lo ejecuta. En su lugar, determina qué acciones son necesarias para crear la configuración especificada en los archivos de configuración. Este patrón le permite comprobar si el plan de ejecución coincide con sus expectativas antes de realizar cambios en los recursos reales.
    • El parámetro -out opcional permite especificar un archivo de salida para el plan. El uso del parámetro -out garantiza que el plan que ha revisado es exactamente lo que se aplica.
    • Para más información acerca de la seguridad y conservar los planes de ejecución, consulte la sección Advertencia de seguridad.
  2. Ejecute terraform apply para aplicar el plan de ejecución.

    terraform apply main.destroy.tfplan
    

Solución de problemas de Terraform en Azure

Solución de problemas comunes al usar Terraform en Azure

Pasos siguientes