DEV Community

Cover image for Crear VM-Apache2 con Terraform en Azure [ES]
kevingo710
kevingo710

Posted on

Crear VM-Apache2 con Terraform en Azure [ES]

Luego de conocer ciertos principios de DevOps y lo que es Infraestructura como Código se procederá a la creación de recursos en un proveedor Cloud en este caso Azure usando Terraform.

Por que Terraform?

Es agnóstico a la plataforma, funciona con proveedores de nubes publicas muy usados en la actualidad, automatización del proceso de la creación de infraestructura

Terraform trabaja en torno a estos archivos *.tf *.tfvars y *.tfstate

Archivo * .tf:

Contienen realmente los recursos que se crearán en el proveedor de la nube . Estos contienen todas las configuraciones que debe tener el recurso creado.

Archivo * .tfvars:

Este archivo contiene las variables que se pueden reemplazar en archivos * .tf

Archivo * .tfstate:

Esta es la fuente de verdad para terraform. Este archivo contiene los ID y las propiedades de los recursos que creó Terraform para que pueda administrar o destruir esos recursos en el futuro.

Ejemplo introductorio crear un recurso:

Recursos:
-Cuenta de Azure

1. Instalar Terraform

Esta herramienta esta disponible para Windows, Mac, Linux

2. Instalar el CLI de Azure

Para instalar la línea de comandos de Azure si está en Windows recomiendo usar el MSI(Microsoft Installer) de la documentación oficial

Autenticarse en CLI de Azure

Usar el comando

az login

Iniciar sesión con las credenciales que tenga una suscripción activa en la Cloud

Crear un directorio

Le puede dar cualquier nombre a este directorio en este caso "learn-terraform-azure" dentro de el crear el archivo main.tf en este archivo estará el código escrito en HCL(Hashi Corp Language)

# Configure the Azure provider
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.26"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "myTFResourceGroup"
  location = "westus2"
}

Enter fullscreen mode Exit fullscreen mode

Aquí hay dos declaraciones importantes esta provider donde se declara el proveedor de la nube a usar y resource donde se indica el tipo de recurso a elegir de todos los que se encuentra disponibles en Azure en este caso un grupo de recursos con una región de despliegue

Inicializar terraform

Dentro del proyecto ejecutar el comando terraform init el cual leera la configuracion inicial del archivo escrito para preparar el entorno de terraform para su posterior despliegue

image.png

Generar el plan de ejecución

Ejecutar el comando terraform plan con lo cual se obtendrá un plan detallado de todo lo que se creara con respecto al código

Aplicar la configuracion

Una vez revisado el plan y saber que recursos se crearan se ejecuta terraform apply luego aceptar la ejecucion con yes y se tendran creado los recursos

Inspeccionar el estado
Ver el grupo de recursos que se han creado mediante terraform
terraform show

Ver en la consola de la nube de Azure

image.png

Destruir el recurso

Usando el comando terraform destroy destruimos lo creado en el proveedor de la nube luego de aceptar la ejecucion con escribiendo yes

image.png

image.png

Cambios en la infraestructura

Se puede agregar distintos cambios al codigo sin afectar el plan previamente creado una vez realizado esto se ejecutará terraform plan -out=newplan para obtener el plan de salida de los nuevos y luego terraform apply newplan

Segunda parte

*En el siguiente ejemplo se creará una máquina virtual en Azure que tendrá instalado un servidor web de apache, todo esto desde código sin acceder al servidor *

Crear un archivo variables.tf en que se declara el uso de variables en la creación de los recursos

variable "location" {}

variable "admin_username" {
  type        = string
  description = "Administrator user name for virtual machine"
}

variable "admin_password" {
  type        = string
  description = "Password must meet Azure complexity requirements"
}

variable "prefix" {
  type    = string
  default = "my"
}

variable "tags" {
  type = map

  default = {
    Environment = "Terraform GS"
    Dept        = "Engineering"
  }
}

variable "sku" {
  default = {
    westus2 = "16.04-LTS"
    eastus  = "18.04-LTS"
  }
}


Enter fullscreen mode Exit fullscreen mode

Crear el archivo terraform.tfvars en donde se establecen los valores de las varibles

location       = "xxxxx"
prefix         = "xx"
admin_username = "xxxxx"
admin_password = "xxxxxxxx"
Enter fullscreen mode Exit fullscreen mode

Crear un archivo azure-user-data.sh que tendrá los script iniciales que se ejecutaran en la maquina virtual creada en Azure

#! /bin/bash
sudo apt-get update
sudo apt-get install -y apache2
sudo systemctl start apache2
sudo systemctl enable apache2
echo "<h1>Demp Apache2 from Azure Virtual Machine</h1>" | sudo tee /var/www/html/index.html

Enter fullscreen mode Exit fullscreen mode

Las siguientes configuraciones se realizaran en el archivo main.tf

Agregar una regla de red que habilite el puerto 80

    security_rule {
    name                       = "allow-http"
    description                = "allow-http"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }
Enter fullscreen mode Exit fullscreen mode

Dentro del recurso de red

resource "azurerm_network_security_group" "nsg" {
  name                = "myTFNSG"
  location            = "westus2"
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "SSH"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

    security_rule {
    name                       = "allow-http"
    description                = "allow-http"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }
}
Enter fullscreen mode Exit fullscreen mode

Declarar la data para leer el archivo de configuracion inicial tambien llamado cloud-init

data "template_file" "linux-vm-cloud-init" {
  template = file("azure-user-data.sh")
}
Enter fullscreen mode Exit fullscreen mode

Cargar la data en sistema operativo de la maquina virtual, decodificando el archivo anteriormente declarado

  os_profile {
    computer_name  = "myTFVM-kg"
    admin_username = var.admin_username
    admin_password = var.admin_password
    custom_data = base64encode(data.template_file.linux-vm-cloud-init.rendered)
  }
Enter fullscreen mode Exit fullscreen mode

Configuración completa del archivo main.tf

Tener en cuenta usar vm_size = "Standard_B1s" para asegurarnos usar la capa gratis de Azure

Declarar una salida por consola de la ip de la vm creada

output "public_ip_address" {
  value = data.azurerm_public_ip.ip.ip_address
}
Enter fullscreen mode Exit fullscreen mode

main.tf

# Configure the Azure provider
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.26"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "myTFResourceGroup"
  location = "westus2"

  tags = {
      Environment = "Terraform Getting Started"
      Team = "DevOps"
  }
}

# Create a virtual network
resource "azurerm_virtual_network" "vnet" {
    name                = "myTFVnet"
    address_space       = ["10.0.0.0/16"]
    location            = "westus2"
    resource_group_name = azurerm_resource_group.rg.name
}

# Create subnet
resource "azurerm_subnet" "subnet" {
  name                 = "myTFSubnet"
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = ["10.0.1.0/24"]
}

# Create public IP
resource "azurerm_public_ip" "publicip" {
  name                = "myTFPublicIP"
  location            = "westus2"
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method   = "Static"
}

# Create Network Security Group and rule
resource "azurerm_network_security_group" "nsg" {
  name                = "myTFNSG"
  location            = "westus2"
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name                       = "SSH"
    priority                   = 1001
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "22"
    source_address_prefix      = "*"
    destination_address_prefix = "*"
  }

    security_rule {
    name                       = "allow-http"
    description                = "allow-http"
    priority                   = 110
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "80"
    source_address_prefix      = "Internet"
    destination_address_prefix = "*"
  }
}

# Create network interface
resource "azurerm_network_interface" "nic" {
  name                      = "myNIC"
  location                  = "westus2"
  resource_group_name       = azurerm_resource_group.rg.name

  ip_configuration {
    name                          = "myNICConfg"
    subnet_id                     = azurerm_subnet.subnet.id
    private_ip_address_allocation = "dynamic"
    public_ip_address_id          = azurerm_public_ip.publicip.id
  }
}

data "template_file" "linux-vm-cloud-init" {
  template = file("azure-user-data.sh")
}

# Create a Linux virtual machine
resource "azurerm_virtual_machine" "vm" {
  name                  = "myTFVM"
  location              = "westus2"
  resource_group_name   = azurerm_resource_group.rg.name
  network_interface_ids = [azurerm_network_interface.nic.id]
  vm_size               = "Standard_B1s"


  storage_os_disk {
    name              = "myOsDisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Premium_LRS"
  }

  storage_image_reference {
    publisher = "Canonical"
    offer     = "UbuntuServer"
    sku       = lookup(var.sku, var.location)
    version   = "latest"
  }

  os_profile {
    computer_name  = "myTFVM-kg"
    admin_username = var.admin_username
    admin_password = var.admin_password
    custom_data = base64encode(data.template_file.linux-vm-cloud-init.rendered)
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }
}

data "azurerm_public_ip" "ip" {
  name                = azurerm_public_ip.publicip.name
  resource_group_name = azurerm_virtual_machine.vm.resource_group_name
  depends_on          = [azurerm_virtual_machine.vm]
}

output "public_ip_address" {
  value = data.azurerm_public_ip.ip.ip_address
}


Enter fullscreen mode Exit fullscreen mode

*Estrucutra de archivos *

image.png

Ejecutar
terraform plan

terraform apply - yes

image.png

image.png

Se ha creado un servidor web-apache2 desde el código en minutos 👏🏼👏🏼

terraform destroy

Se destruye el recurso

En minutos se crea y destruye un servidor web en la nube con un gasto de minimo de apenas centavos

Almacenar el estado remoto en Terraform Cloud

Los backends remotos de Terraform permiten que Terraform utilice un espacio de almacenamiento compartido para los datos de estado. El backend remoto de Terraform Cloud también permite a los equipos versionar, auditar y colaborar fácilmente en cambios de infraestructura.

Registrarse en Terraform Cloud

Configurar el backend remoto

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.26"
    }
  }

+ backend "remote" {
+   organization = "<ORG_NAME>"
+   workspaces {
+     name = "Example-Workspace"
+   }
+ }
}

provider "azurerm" {
  features {}
}
Enter fullscreen mode Exit fullscreen mode

Iniciar sesion en local terraform login

Ver la cuenta de azure iniciadoaz account list

Ver informacion necesaria de la cuenta de azureaz account set --subscription="SUBSCRIPTION_ID"

Copiar las ID en la cloud de terraform

az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/SUBSCRIPTION_ID"
Enter fullscreen mode Exit fullscreen mode

image.png

Aplicar las configuraciones terraform apply

image.png

Destruir los recursos creados terraform destroy

Terraform Cloud ofrece un entorno de ejecución compartido predecible y confiable con herramientas para ayudarlo a trabajar juntos en configuraciones y módulos de Terraform.

Aunque Terraform Cloud puede actuar como un backend remoto estándar para admitir las ejecuciones de Terraform en máquinas locales, funciona incluso mejor como un entorno de ejecución remota.

Discussion (0)