En esta guía, exploraremos cómo utilizar Terraform para crear un disco Premium ZRS y cómo adjuntarlo a varias máquinas virtuales ubicadas en diferentes zonas geográficas. Para llevar a cabo este proceso, es esencial tener en cuenta el tipo de disco, ya que está sujeto a límites de «max_shares» según la siguiente información:
– Discos Premium SSD P15 y P20: Límite de 2 «max_shares».
– Discos P30, P40, P50: Límite de 5 «max_shares».
– Discos P60, P70, P80: Límite de 10 «max_shares».
– Para discos Ultra, el valor mínimo de «max_shares» es 1 y el máximo es 5.
Introducción
Azure Ultra Disk es una solución de almacenamiento de alto rendimiento diseñada para cargas de trabajo exigentes que requieren bajos tiempos de respuesta y altas tasas de transferencia de datos. Terraform, una herramienta de infraestructura como código (IaC), nos permite definir y gestionar nuestra infraestructura de manera declarativa, lo que lo convierte en una opción ideal para automatizar la creación y configuración de recursos en la nube.
En esta guía, exploraremos cómo utilizar Terraform para crear discos UltraDisk y adjuntarlos a múltiples máquinas virtuales en Azure. Cubriremos detalladamente cada parte del código necesario y proporcionaremos explicaciones claras para facilitar su comprensión.
Información relevante:
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/managed_disk
- https://learn.microsoft.com/es-es/azure/virtual-machines/disks-redundancy
- https://www.nealshah.dev/posts/2020/05/terraform-for-azure-deploying-multiple-vms-with-multiple-managed-disks/
Estructura del Repositorio
Asegúrate de que la estructura de tu repositorio siga esta organización:
├── env
│ ├── code
│ │ └── storage
│ │ └── managed_ultra_disk
│ │ ├── backend.tf
│ │ ├── disk.tf
│ │ ├── provider.tf
│ │ └── variables.tf
│ └── pro
│ └── storage
│ └── managed_ultra_disk
│ ├── backend.tfvars
│ └── vars.tfvars
└── modulo
└── virtual_machine
├── data.tf
├── main.tf
├── provider.tf
├── terraform.tfstate
├── terraform.tfstate.backup
└── variables.tf
Configuración del Código
Parte 1: Configuración del Almacenamiento
Comenzamos definiendo los recursos de almacenamiento en Azure mediante Terraform.
Archivo: backend.tf
terraform {
backend "azurerm" {
}
}
Información detallada del codigo:
- Terraform Block (
terraform { }
):- Este bloque define la configuración global de Terraform para un proyecto. Aquí es donde se pueden especificar opciones generales y configuraciones que afectan a todo el proyecto.
- Backend Block (
backend "azurerm" { }
):- Este bloque configura el «backend» de Terraform. El backend es responsable de guardar el estado de la infraestructura administrada por Terraform.
- En este caso, se está utilizando el backend de AzureRM (
azurerm
). Esto significa que el estado de la infraestructura se almacenará en Azure, específicamente en un contenedor de almacenamiento de Azure Blob. - La configuración adicional, como la información de la suscripción de Azure y las credenciales necesarias, generalmente se proporciona en este bloque. Sin embargo, en tu fragmento de código, no se proporcionan opciones adicionales, lo que implica que se asumen los valores predeterminados o se proporcionarán en otro lugar (por ejemplo, a través de variables de entorno o archivos de configuración separados).
Archivo: disk.tf
resource "azurerm_managed_disk" "storage_ultra_disk_01" {
name = var.vm_ultra_disk_name_01
location = var.vm_ultra_disk_location_01
resource_group_name = var.vm_ultra_disk_rg_01
storage_account_type = var.vm_ultra_disk_type_01
create_option = var.vm_ultra_disk_option_01
disk_size_gb = var.vm_ultra_disk_size_01
max_shares = var.vm_ultra_disk_shares
tags = var.tags
}
Información detallada del codigo:
- Resource Block (
resource "azurerm_managed_disk" "storage_ultra_disk_01" { }
):- Este bloque define un nuevo recurso de Terraform del tipo
azurerm_managed_disk
. Este recurso representa un disco administrado en Azure.
- Este bloque define un nuevo recurso de Terraform del tipo
- Atributos del Recurso:
name
: Especifica el nombre del disco. El valor se toma de la variablevm_ultra_disk_name_01
.location
: Especifica la ubicación geográfica donde se creará el disco. El valor se toma de la variablevm_ultra_disk_location_01
.resource_group_name
: Especifica el nombre del grupo de recursos al que pertenecerá el disco. El valor se toma de la variablevm_ultra_disk_rg_01
.storage_account_type
: Especifica el tipo de cuenta de almacenamiento que se utilizará para almacenar el disco. El valor se toma de la variablevm_ultra_disk_type_01
.create_option
: Especifica cómo se creará el disco. El valor se toma de la variablevm_ultra_disk_option_01
.disk_size_gb
: Especifica el tamaño del disco en gigabytes. El valor se toma de la variablevm_ultra_disk_size_01
.max_shares
: Especifica el número máximo de acciones que se pueden establecer para compartir el disco. El valor se toma de la variablevm_ultra_disk_shares
.tags
: Especifica los tags o etiquetas que se aplicarán al recurso. El valor se toma de la variabletags
.
- Variables:
- Las variables (por ejemplo,
var.vm_ultra_disk_name_01
,var.vm_ultra_disk_location_01
, etc.) se utilizan para proporcionar valores dinámicos a los atributos del recurso. Estas variables deben estar definidas en otro lugar del archivo de configuración de Terraform, en un archivo separado o en línea de comandos, para que el código sea más flexible y reutilizable.
- Las variables (por ejemplo,
Archivo: provider.tf
provider "azurerm" {
subscription_id = var.subscription_id
tenant_id = var.tenant_id
features {}
}
provider "azurerm" {
subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
tenant_id = var.tenant_id
alias = "mngt"
features {}
}
En este archivo, definimos los proveedores de Azure que utilizaremos en nuestro código Terraform.
Archivo: variables.tf
variable "tags" {
type = map(string)
default = {}
description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`"
}
###################################################################################
######################### Variables Data Ultra Disk ##############################
###################################################################################
variable "subscription_id" {
type = string
description = "ID Subscription"
}
variable "tenant_id" {
type = string
description = "Tenant ID"
}
variable "vm_ultra_disk_name_01" {
type = string
description = "Nombre"
}
variable "vm_ultra_disk_location_01" {
type = string
description = "Location del disco"
}
variable "vm_ultra_disk_rg_01" {
type = string
description = "RG del disco"
}
variable "vm_ultra_disk_size_01" {
type = string
description = "Tamaño del disco"
}
variable "vm_ultra_disk_type_01" {
type = string
description = "The method to use when creating the managed disk. Changing this forces a new resource to be created. Possible values include: Import, Empty, Copy, FromImage, Restore"
}
variable "vm_ultra_disk_option_01" {
type = string
description = "The method to use when creating the managed disk. Changing this forces a new resource to be created. Possible values include: Import, Empty, Copy, FromImage, Restore"
}
variable "vm_ultra_disk_shares" {
type = string
description = "Nombre"
}
Aquí definimos todas las variables necesarias para configurar los recursos, como etiquetas, ID de suscripción, etc.
Parte 2: Configuración del Módulo de Máquina Virtual
Luego, adjuntamos los discos a las máquinas virtuales existentes.
Archivo: backend.tfvars
resource_group_name = "RG-REDORBITA-TF-01"
storage_account_name = "ST-REDORBITA"
container_name = "TF"
key = "LZ/CORP/env/pro/storage/managed_ultra_disk/terraform.tfstate"
subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
tenant_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
- Este bloque de configuración de Terraform define el backend que se utilizará para almacenar el estado del proyecto. En este caso, se está utilizando el backend
azurerm
, que se refiere a Azure Blob Storage. - Los atributos especificados son:
resource_group_name
: El nombre del grupo de recursos de Azure donde se encuentra almacenada la cuenta de almacenamiento.storage_account_name
: El nombre de la cuenta de almacenamiento de Azure Blob.container_name
: El nombre del contenedor dentro de la cuenta de almacenamiento donde se almacenará el estado de Terraform.key
: La clave o ruta dentro del contenedor donde se almacenará el archivo de estado de Terraform.subscription_id
: El ID de la suscripción de Azure donde se encuentra la cuenta de almacenamiento.tenant_id
: El ID del inquilino (tenant) de Azure asociado a la cuenta de almacenamiento.
Archivo: vars.tfvars
Este fragmento de código contiene dos secciones principales: una sección para definir etiquetas y otra sección para definir variables relacionadas con la instancia de una máquina virtual y su disco administrado.
tags = {
BrokerCloud = "Azure"
CreationDate = "2024"
Environment = "PRO"
LandingZone = "YES"
OU = "CORP"
Tier = "Gold"
NSSRID = "XXXXXXXXX"
Owner = "XXXXX@red-orbita.com"
}
- Este bloque define un conjunto de etiquetas que se aplicarán a los recursos creados por Terraform. Las etiquetas proporcionan metadatos adicionales para identificar y organizar los recursos.
- Cada etiqueta está definida como un par clave-valor, donde la clave representa el nombre de la etiqueta y el valor representa el contenido de la etiqueta.
###############################################################################
######################### Variables Instancia01 #################################
###############################################################################
subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
tenant_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
vm_ultra_disk_name_01 = "srvredorbita-ultra-disk-01"
vm_ultra_disk_location_01 = "West Europe"
vm_ultra_disk_rg_01 = "RG-REDORBITA"
vm_ultra_disk_size_01 = "4"
vm_ultra_disk_type_01 = "Premium_ZRS"
vm_ultra_disk_option_01 = "Empty"
vm_ultra_disk_shares = "3"
- Estas variables están relacionadas con la creación de una instancia de máquina virtual y su disco administrado asociado.
- Las variables
subscription_id
ytenant_id
especifican los IDs de suscripción e inquilino (tenant) de Azure, respectivamente, necesarios para la autenticación de Terraform con Azure. - Las otras variables definen diferentes aspectos de un disco administrado para la instancia de la máquina virtual, como el nombre, ubicación, grupo de recursos, tamaño, tipo, opción de creación y número máximo de acciones permitidas.
Modulo - Virtual_Machine
data.tf
data "azurerm_managed_disk" "existing_disks" {
name = "srvredorbita-ultra-disk-01"
resource_group_name = var.vm_ultra_disk_rg_01
}
data "azurerm_virtual_machine" "existing_vms" {
count = length(keys(var.virtual_machine_names))
name = keys(var.virtual_machine_names)[count.index]
resource_group_name = var.vm_ultra_disk_rg_01
}
Recuperación de un Disco Administrado Existente:
Este bloque de datos define un recurso de tipo azurerm_managed_disk, que se utiliza para recuperar información sobre un disco administrado existente en Azure.
La propiedad name especifica el nombre del disco administrado que se desea recuperar.
La propiedad resource_group_name se establece utilizando la variable var.vm_ultra_disk_rg_01, que contiene el nombre del grupo de recursos de Azure donde se encuentra el disco administrado.
Recuperación de Máquinas Virtuales Existentes:
Este bloque de datos define un recurso de tipo azurerm_virtual_machine, que se utiliza para recuperar información sobre máquinas virtuales existentes en Azure.
La propiedad count se utiliza para iterar sobre las claves del mapa var.virtual_machine_names, que contiene los nombres de las máquinas virtuales que se desean recuperar. La longitud del mapa determina la cantidad de iteraciones.
La propiedad name se establece utilizando la función keys(var.virtual_machine_names)[count.index], que recupera el nombre de la máquina virtual en cada iteración.
La propiedad resource_group_name se establece utilizando la variable var.vm_ultra_disk_rg_01, que contiene el nombre del grupo de recursos de Azure donde se encuentran las máquinas virtuales.
Archivo: main.tf
Este fragmento de código define un recurso en Terraform que adjunta discos administrados a máquinas virtuales existentes en Azure
resource "azurerm_virtual_machine_data_disk_attachment" "attach_disk_to_vm" {
count = length(data.azurerm_virtual_machine.existing_vms)
managed_disk_id = data.azurerm_managed_disk.existing_disks.id
virtual_machine_id = data.azurerm_virtual_machine.existing_vms[count.index].id
lun = count.index
caching = "ReadWrite"
}
- Este bloque define un recurso de tipo
azurerm_virtual_machine_data_disk_attachment
, que se utiliza para adjuntar discos administrados a máquinas virtuales existentes en Azure. - La propiedad
count
especifica el número de iteraciones que se realizarán. En este caso, el número de iteraciones se determina por la longitud del conjunto de datosdata.azurerm_virtual_machine.existing_vms
, lo que significa que Terraform creará un recurso por cada máquina virtual existente. - La propiedad
managed_disk_id
especifica el ID del disco administrado que se adjuntará a la máquina virtual. El ID se obtiene del conjunto de datosdata.azurerm_managed_disk.existing_disks
, que contiene la información sobre los discos administrados existentes. - La propiedad
virtual_machine_id
especifica el ID de la máquina virtual a la que se adjuntará el disco administrado. El ID se obtiene del conjunto de datosdata.azurerm_virtual_machine.existing_vms
, que contiene la información sobre las máquinas virtuales existentes. - La propiedad
lun
(Logical Unit Number) especifica el número de unidad lógica que se asignará al disco adjunto. En este caso, se utilizacount.index
para asignar un número de unidad lógica único a cada disco adjunto, basado en el índice de la iteración. - La propiedad
caching
especifica la configuración de almacenamiento en caché para el disco adjunto. En este caso, se establece en «ReadWrite», lo que significa que se permite tanto la lectura como la escritura en la caché del disco.
Archivo: provider.tf
provider "azurerm" {
subscription_id = var.subscription_id
tenant_id = var.tenant_id
features {}
}
provider "azurerm" {
subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
tenant_id = var.tenant_id
alias = "mngt"
features {}
}
- Este bloque de proveedor configura la conexión a Azure utilizando valores dinámicos para
subscription_id
ytenant_id
, que se espera que sean proporcionados mediante variables (var.subscription_id
yvar.tenant_id
) definidas en otro lugar de la configuración de Terraform. Esto proporciona flexibilidad para que Terraform use la suscripción y el inquilino específicos proporcionados dinámicamente. - El bloque
features {}
está presente, pero no contiene ninguna configuración adicional en este momento. Este bloque se puede utilizar para configurar características adicionales del proveedor en futuras implementaciones. - Este segundo bloque de proveedor también se conecta a Azure, pero en lugar de utilizar una variable para
subscription_id
, se proporciona directamente un ID de suscripción estático. Esto significa que este proveedor específico siempre utilizará la misma suscripción, independientemente de las variables externas. Se recomienda usar esta configuración con precaución, ya que puede limitar la flexibilidad de la configuración. - Se especifica un alias para este proveedor utilizando
alias = "mngt"
. El alias se utiliza para distinguir este proveedor de otros proveedores en el caso de que haya múltiples proveedores configurados. Esto puede ser útil cuando se necesita interactuar con múltiples suscripciones o inquilinos de Azure en la misma configuración de Terraform. - Al igual que en el primer bloque, el bloque
features {}
está presente sin ninguna configuración adicional.
Archivo: variables.tf
contiene definiciones de variables utilizadas en la configuración de Terraform. Aquí está la explicación detallada:
variable "virtual_machine_names" {
type = map(object({
hostname = string
}))
default = {
srvredorbita01 ={
hostname = "srvredorbita01"
},
srvredorbita02 = {
hostname = "srvredorbita02"
}
srvredorbita03 = {
hostname = "srvredorbita03"
}
srvredorbita04 = {
hostname = "srvredorbita04"
}
srvredorbita05 = {
hostname = "srvredorbita05"
}
srvredorbita06 = {
hostname = "srvredorbita06"
}
srvredorbita07 = {
hostname = "srvredorbita07"
}
srvredorbita08 = {
hostname = "srvredorbita08"
}
srvredorbita09 = {
hostname = "srvredorbita09"
}
srvredorbita10 = {
hostname = "srvredorbita10"
}
}
}
variable "vm_ultra_disk_rg_01" {
type = string
description = "RG del disco"
default = "RG-REDORBITA"
}
variable "disks_per_instance" {
type = string
description = ""
default = ""
}
- Variable «virtual_machine_names»:
- Esta variable es un mapa de objetos que define los nombres de las máquinas virtuales y sus respectivos nombres de host. El mapa contiene múltiples entradas, cada una con una clave que representa el nombre de la máquina virtual y un objeto que contiene la propiedad «hostname» que representa el nombre de host de la máquina virtual.
- El tipo de la variable es
map(object({ hostname = string }))
, lo que significa que se espera un mapa donde cada valor es un objeto con una propiedad «hostname» que es una cadena. - El valor predeterminado proporciona un conjunto de nombres de máquinas virtuales junto con sus nombres de host asociados.
- Variable «vm_ultra_disk_rg_01»:
- Esta variable especifica el nombre del grupo de recursos donde se encuentra el disco administrado. El tipo de la variable es una cadena (
string
), lo que significa que se espera un valor de cadena. - La descripción proporciona información sobre el propósito de la variable.
- El valor predeterminado establece el nombre del grupo de recursos en «RG-REDORBITA».
- Esta variable especifica el nombre del grupo de recursos donde se encuentra el disco administrado. El tipo de la variable es una cadena (
- Variable «disks_per_instance»:
- Esta variable define la cantidad de discos por instancia. El tipo de la variable es una cadena (
string
). - La descripción está vacía en este caso, lo que significa que no se proporciona información adicional sobre la variable.
- El valor predeterminado también está vacío en este caso, lo que significa que se espera que el usuario proporcione un valor específico según sus necesidades.
- Esta variable define la cantidad de discos por instancia. El tipo de la variable es una cadena (
:wq!