Implementación de una Azure Application Gateway v2 mediante Terraform para dirigir el tráfico web

Nota:

Vea el archivo de registro que contiene los resultados de las pruebas de las versiones actuales y anteriores de Terraform.

Terraform habilita la definición, vista previa e implementación de la infraestructura en la nube. Con Terraform, se crean archivos de configuración mediante la sintaxis de HCL. La sintaxis de HCL permite especificar el proveedor de la nube, como Azure, y los elementos que componen la infraestructura de la nube. Después de crear los archivos de configuración, se crea un plan de ejecución que permite obtener una vista previa de los cambios de infraestructura antes de implementarlos. Una vez que compruebe los cambios, aplique el plan de ejecución para implementar la infraestructura.

En este artículo, usará Terraform para implementar un Azure Application Gateway v2 y dos servidores de prueba de Windows Server 2019 Datacenter para el grupo de back-end.

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 denominado providers.tf e inserte el siguiente código:

    terraform {
      required_version = ">=1.2"
      
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 3.0"
        }
        random = {
          source = "hashicorp/random"
          version = "~> 3.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
  3. Cree un archivo denominado main.tf e inserte el siguiente código:

    resource "random_string" "rg" {
      length  = 8
      upper   = false
      special = false
    }
    
    resource "azurerm_resource_group" "rg" {
      name     = "101-application-gateway-${random_string.rg.result}"
      location = "eastus"
    }
    
    resource "azurerm_virtual_network" "vnet" {
      name                = "myVNet"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      address_space       = ["10.21.0.0/16"]
    }
    
    resource "azurerm_subnet" "frontend" {
      name                 = "myAGSubnet"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.vnet.name
      address_prefixes     = ["10.21.0.0/24"]
    }
    
    resource "azurerm_subnet" "backend" {
      name                 = "myBackendSubnet"
      resource_group_name  = azurerm_resource_group.rg.name
      virtual_network_name = azurerm_virtual_network.vnet.name
      address_prefixes     = ["10.21.1.0/24"]
    }
    
    resource "azurerm_public_ip" "pip" {
      name                = "myAGPublicIPAddress"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      allocation_method   = "Static"
      sku                 = "Standard"
    }
    
    
    resource "azurerm_application_gateway" "main" {
      name                = "myAppGateway"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
    
      sku {
        name     = "Standard_v2"
        tier     = "Standard_v2"
        capacity = 2
      }
    
      gateway_ip_configuration {
        name      = "my-gateway-ip-configuration"
        subnet_id = azurerm_subnet.frontend.id
      }
    
      frontend_port {
        name = var.frontend_port_name
        port = 80
      }
    
      frontend_ip_configuration {
        name                 = var.frontend_ip_configuration_name
        public_ip_address_id = azurerm_public_ip.pip.id
      }
    
      backend_address_pool {
        name = var.backend_address_pool_name
      }
    
      backend_http_settings {
        name                  = var.http_setting_name
        cookie_based_affinity = "Disabled"
        port                  = 80
        protocol              = "Http"
        request_timeout       = 60
      }
    
      http_listener {
        name                           = var.listener_name
        frontend_ip_configuration_name = var.frontend_ip_configuration_name
        frontend_port_name             = var.frontend_port_name
        protocol                       = "Http"
      }
    
      request_routing_rule {
        name                       = var.request_routing_rule_name
        rule_type                  = "Basic"
        http_listener_name         = var.listener_name
        backend_address_pool_name  = var.backend_address_pool_name
        backend_http_settings_name = var.http_setting_name
        priority                   = 1
      }
    }
    
    resource "azurerm_network_interface" "nic" {
      count               = 2
      name                = "nic-${count.index+1}"
      location            = azurerm_resource_group.rg.location
      resource_group_name = azurerm_resource_group.rg.name
    
      ip_configuration {
        name                          = "nic-ipconfig-${count.index+1}"
        subnet_id                     = azurerm_subnet.backend.id
        private_ip_address_allocation = "Dynamic"
      }
    }
    
    resource "azurerm_network_interface_application_gateway_backend_address_pool_association" "nic-assoc" {
      count                   = 2
      network_interface_id    = azurerm_network_interface.nic[count.index].id
      ip_configuration_name   = "nic-ipconfig-${count.index+1}"
      backend_address_pool_id = one(azurerm_application_gateway.main.backend_address_pool).id
    }
    
    resource "random_password" "password" {
      length  = 16
      special = true
      lower   = true
      upper   = true
      numeric = true
    }
    
    resource "azurerm_windows_virtual_machine" "vm" {
      count               = 2
      name                = "myVM${count.index+1}"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
      size                = "Standard_DS1_v2"
      admin_username      = "azureadmin"
      admin_password      = random_password.password.result
    
      network_interface_ids = [
        azurerm_network_interface.nic[count.index].id,
      ]
    
      os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
    
    
      source_image_reference {
        publisher = "MicrosoftWindowsServer"
        offer     = "WindowsServer"
        sku       = "2019-Datacenter"
        version   = "latest"
      }
    }
    
    resource "azurerm_virtual_machine_extension" "vm-extensions" {
      count                = 2
      name                 = "vm${count.index+1}-ext"
      virtual_machine_id   = azurerm_windows_virtual_machine.vm[count.index].id
      publisher            = "Microsoft.Compute"
      type                 = "CustomScriptExtension"
      type_handler_version = "1.10"
    
      settings = <<SETTINGS
        {
            "commandToExecute": "powershell Add-WindowsFeature Web-Server; powershell Add-Content -Path \"C:\\inetpub\\wwwroot\\Default.htm\" -Value $($env:computername)"
        }
    SETTINGS
    
    }
    
  4. Cree un archivo denominado variables.tf e inserte el siguiente código:

    variable "backend_address_pool_name" {
        default = "myBackendPool"
    }
    
    variable "frontend_port_name" {
        default = "myFrontendPort"
    }
    
    variable "frontend_ip_configuration_name" {
        default = "myAGIPConfig"
    }
    
    variable "http_setting_name" {
        default = "myHTTPsetting"
    }
    
    variable "listener_name" {
        default = "myListener"
    }
    
    variable "request_routing_rule_name" {
        default = "myRoutingRule"
    }
    
  5. Cree un archivo denominado outputs.tf e inserte el siguiente código:

    output "gateway_frontend_ip" {
      value = "http://${azurerm_public_ip.pip.ip_address}"
    }
    

3. Inicialización de Terraform

Para inicializar la implementación de Terraform, ejecute terraform init. Este comando descarga el proveedor de Azure necesario para administrar los recursos de Azure.

terraform init -upgrade

Puntos clave:

  • El -upgrade parámetro actualiza los complementos de proveedor necesarios a la versión más reciente que cumple con las restricciones de versión de la configuración.

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, llame a terraform apply sin ningún parámetro.

6. Verificación de los resultados

  1. Para obtener el nombre del grupo de recursos, ejecute terraform state show.

    terraform state show azurerm_resource_group.rg
    
  2. Vaya a Azure Portal.

  3. En Servicios de Azure, seleccione Grupos de recursos.

  4. Seleccione el grupo de recursos creado en este artículo.

  5. Seleccione el recurso myAppGateway .

  6. En la página Información general , copie la dirección IP pública de front-end en el Portapapeles.

  7. Pegue la dirección IP pública en la barra de direcciones del explorador web. Actualice el explorador para ver el nombre de la máquina virtual. Una respuesta válida comprueba que la puerta de enlace de aplicaciones se ha creado correctamente y puede conectarse con el back-end.

7. Limpieza de recursos

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

  1. Ejecute el comando terraform plan y especifique la marca destroy.

    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