Tutorial: Creación de un conjunto de escalado de máquinas virtuales de Azure a partir de una imagen personalizada de Packer 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 la implementación de Terraform
- Usar variables y salidas para la implementación de Terraform
- Crear e implementar una infraestructura de red
- Crear una imagen de máquina virtual personalizada mediante Packer
- Crear e implementar un conjunto de escalado de máquinas virtuales mediante la imagen personalizada
- Crear e implementar un Jumpbox
1. Configurar su entorno
- Suscripción de Azure: Si no tiene una suscripción a Azure, cree una cuenta gratuita antes de empezar.
Configuración de Terraform: si aún no lo ha hecho, configure Terraform con una de las siguientes opciones:
2. Creación de una imagen de Packer
-
Puntos clave:
- Para confirmar que tiene acceso al ejecutable de Packer, ejecute el siguiente comando:
packer -v. - Dependiendo del entorno, es posible que tenga que establecer la ruta de acceso y volver a abrir la línea de comandos.
- Para confirmar que tiene acceso al ejecutable de Packer, ejecute el siguiente comando:
Cree un grupo de recursos con az group create para que contenga la imagen de Packer.
az group create -n myPackerImages -l eastusEjecute az ad sp create-for-rbac para que Packer pueda autenticarse en Azure con una entidad de servicio.
az ad sp create-for-rbac --role Contributor --query "{ client_id: appId, client_secret: password, tenant_id: tenant }"Puntos clave:
- Anote los valores de salida (
appId,client_secret,tenant_id).
- Anote los valores de salida (
Para ver la suscripción actual de Azure, ejecute az account show.
az account show --query "{ subscription_id: id }"Cree un archivo de plantilla Packer llamado
ubuntu.jsone inserte el siguiente código:{ "builders": [{ "type": "azure-arm", "client_id": "0bfc2293-4d69-49b5-83f7-bf0d60d20c45", "client_secret": "G3.6ytCh44Kcla~_JRPBDLkzsXLOa3edDL", "tenant_id": "c3fd441d-b8ad-487e-aa27-453079018fca", "subscription_id": "b162117f-53fa-4f42-8c77-6a65ca966c40", "managed_image_resource_group_name": "myPackerImages", "managed_image_name": "myPackerImage", "os_type": "Linux", "image_publisher": "Canonical", "image_offer": "UbuntuServer", "image_sku": "16.04-LTS", "azure_tags": { "dept": "Engineering", "task": "Image deployment" }, "location": "East US", "vm_size": "Standard_DS2_v2" }], "provisioners": [{ "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E sh '{{ .Path }}'", "inline": [ "apt-get update", "apt-get upgrade -y", "apt-get -y install nginx", "/usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync" ], "inline_shebang": "/bin/sh -x", "type": "shell" }] }Puntos clave:
- Establezca los campos
client_id,client_secretytenant_iden los valores respectivos de la entidad de servicio. - Establezca el campo
subscription_iden el identificador de la suscripción de Azure.
- Establezca los campos
Compile la imagen de Packer.
packer build ubuntu.json
3. Implementación del código de Terraform
Cree un directorio en el que probar el código de ejemplo de Terraform y conviértalo en el directorio actual.
Cree un archivo llamado
main.tfe 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 } data "azurerm_resource_group" "image" { name = var.packer_resource_group_name } data "azurerm_image" "image" { name = var.packer_image_name resource_group_name = data.azurerm_resource_group.image.name } 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 { id=data.azurerm_image.image.id } 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 } os_profile_linux_config { disable_password_authentication = true ssh_keys { path = "/home/azureuser/.ssh/authorized_keys" key_data = file("~/.ssh/id_rsa.pub") } } 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 = true ssh_keys { path = "/home/azureuser/.ssh/authorized_keys" key_data = file("~/.ssh/id_rsa.pub") } } tags = var.tags }Cree un archivo llamado
variables.tfque contenga las variables del proyecto e inserte el código siguiente:variable "packer_resource_group_name" { description = "Name of the resource group in which the Packer image will be created" default = "myPackerImages" } variable "packer_image_name" { description = "Name of the Packer image" default = "myPackerImage" } variable "resource_group_name" { description = "Name of the resource group in which the Packer image will be created" default = "myPackerImages" } 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" }Cree un archivo llamado
output.tfpara 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 }
4. 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.
5. 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 plancrea 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
-outopcional permite especificar un archivo de salida para el plan. El uso del parámetro-outgarantiza 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.
6. 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 applyanterior da por hecho que ejecutó anteriormenteterraform 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 aterraform apply. - Si no ha utilizado el parámetro
-out, simplemente llame aterraform applysin ningún parámetro.
7. Verificación de los resultados
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
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!).
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>.
8. Limpieza de recursos
Eliminación del conjunto de escalado de máquinas virtuales
Cuando ya no necesite los recursos creados a través de Terraform, realice los pasos siguientes:
Ejecute terraform plan y especifique la marca.
terraform plan -destroy -out main.destroy.tfplanPuntos clave:
- El comando
terraform plancrea 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
-outopcional permite especificar un archivo de salida para el plan. El uso del parámetro-outgarantiza 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.
- El comando
Ejecute terraform apply para aplicar el plan de ejecución.
terraform apply main.destroy.tfplan
Eliminación de la imagen de Packer y el grupo de recursos
Ejecute az group delete para eliminar el grupo de recursos que se ha usado para contener la imagen de Packer. También se elimina la imagen de Packer.
az group delete --name myPackerImages --yes
Solución de problemas de Terraform en Azure
Solución de problemas comunes al usar Terraform en Azure