Cerraste el módulo 1 con los cimientos puestos: la cuenta, la jerarquía de facturación, los grupos de recursos rg-contoso-reservas-dev y rg-contoso-reservas-pro, el esquema de etiquetado obligatorio y un script de Azure CLI que despliega todo eso de forma idempotente. Ahora empieza la construcción real de la plataforma, y lo hacemos por la pieza menos glamurosa y más inevitable: una máquina virtual.
Contoso Airlines tiene un problema muy común en cualquier migración. Su motor de disponibilidad heredado —el proceso que calcula qué plazas quedan libres en cada vuelo y a qué precio— es una aplicación Java monolítica escrita hace once años, con dependencias del sistema operativo, rutas absolutas y un servicio que arranca con un script propio. Nadie en el equipo se atreve a reescribirlo antes de la temporada alta. Diego Salas lo resume en una frase: «funciona, no lo entiende nadie del todo, y si lo tocamos ahora no vendemos billetes en julio».
Esa aplicación no puede ir a un servicio de plataforma todavía. Necesita un servidor con acceso al sistema operativo. En Azure, eso es una máquina virtual. En esta lección aprenderás cuándo una VM es la respuesta correcta y cuándo es una pereza cara, qué recursos arrastra consigo, cómo elegir tamaño y disco sin arruinarte, cómo crearla y configurarla desde Azure CLI, y —sobre todo— cómo apagarla de forma que deje de facturar de verdad, que es un matiz que sorprende a casi todo el mundo la primera vez.
Aviso de coste: esta lección crea recursos que se facturan por hora. Un tamaño
Standard_B1scon disco Standard SSD cuesta muy poco al día, pero no cuesta cero. Al final de la lección tienes la limpieza completa; ejecútala si no vas a seguir usando la VM.
Contenido
- VM frente a PaaS: cuándo tiene sentido cada uno
- Anatomía de una máquina virtual en Azure
- Familias y tamaños de VM: cómo leer la nomenclatura
- Discos: tipos, rendimiento y coste
- Imágenes: marketplace, imágenes propias y galerías
- Crear la VM del motor de disponibilidad con Azure CLI
- Conectarse por SSH e instalar el servicio
- Configuración inicial automática: cloud-init y extensiones
- Estados de una VM y qué se factura en cada uno
- Instantáneas e imágenes: copias y clones
- Limpieza al terminar
- Errores Comunes y Consejos
- Ejercicios
- Conclusión
- VM frente a PaaS: cuándo tiene sentido cada uno
En la lección 01-02 viste el modelo de responsabilidad compartida: con IaaS gestionas el sistema operativo hacia arriba; con PaaS, solo tu aplicación y sus datos. La pregunta práctica no es cuál es «mejor», sino qué te obliga a quedarte abajo.
| Situación | Elección razonable | Por qué |
|---|---|---|
| Software heredado con dependencias del SO, servicios propios, rutas fijas | Máquina virtual | Necesitas control total del sistema operativo |
| Licencia de terceros que exige instalación en servidor | Máquina virtual | El fabricante no soporta otro modelo |
| Aplicación web moderna (Java, .NET, Node, Python) empaquetable | App Service (02-03) | Menos superficie que administrar y parchear |
| Proceso por eventos, ejecución corta e intermitente | Azure Functions (06-03) | Pagas por ejecución, no por servidor encendido |
| Aplicación ya contenerizada | Container Apps / AKS (06-01, 06-02) | Portabilidad y densidad |
| Necesitas GPU, kernel personalizado o software de red a bajo nivel | Máquina virtual | Solo IaaS te da ese nivel |
El coste real de una VM no es la factura mensual: es el trabajo recurrente que trae consigo. Parches del sistema operativo, copias de seguridad, endurecimiento de la configuración, supervisión del agente, rotación de claves. Con App Service, buena parte de eso desaparece de tu lista.
Por eso la decisión de Contoso queda registrada así, y conviene que la interiorices porque marca todo el módulo:
- El motor de disponibilidad heredado va a VM, como paso intermedio y explícitamente temporal.
- Contoso Reservas (web pública) y la nueva API de Disponibilidad van a App Service (lección 02-03).
- La VM se moderniza más adelante, cuando el equipo pueda reescribir el motor; en el módulo 6 verás a dónde acaba yendo.
Esto es exactamente lo que el Cloud Adoption Framework llama rehost («lift and shift»): mueves primero, optimizas después. Es una estrategia legítima siempre que el «después» tenga fecha. Si no la tiene, la VM se queda diez años.
- Anatomía de una máquina virtual en Azure
Cuando en el portal pulsas «Crear máquina virtual», Azure no crea un recurso: crea varios, cada uno con su propio ciclo de vida y su propia línea en la factura. Entender esto evita la sorpresa clásica de borrar la VM y seguir pagando.
graph TD
RG["Grupo de recursos<br/>rg-contoso-reservas-dev"] --> VM["Máquina virtual<br/>vm-motor-disponibilidad-dev"]
VM --> OSD["Disco de SO gestionado<br/>(persistente)"]
VM --> TMP["Disco temporal /mnt<br/>(volátil, no se factura aparte)"]
VM --> DAT["Discos de datos<br/>(opcionales, persistentes)"]
VM --> NIC["Interfaz de red (NIC)"]
NIC --> SUBNET["Subred de una red virtual"]
NIC --> PIP["IP pública<br/>(opcional)"]
NIC --> NSG["Grupo de seguridad de red<br/>(filtra el tráfico)"]
Los recursos que arrastra una VM:
- Disco de sistema operativo: disco gestionado, persistente. Sobrevive a la VM si no marcas su borrado.
- Disco temporal: espacio local del host físico, montado normalmente en
/mnt(Linux) oD:(Windows). Su contenido se pierde si la VM se desasigna o se mueve de host. Sirve para archivos de intercambio y ficheros de trabajo desechables. Nunca para datos. - Discos de datos: opcionales, persistentes, se conectan y desconectan en caliente.
- NIC: la tarjeta de red virtual. Vive dentro de una subred de una red virtual.
- IP pública: opcional. Si es estática, se factura aunque la VM esté apagada.
- NSG: el cortafuegos de nivel de red. Puede asociarse a la NIC o a la subred (lección 02-05).
La regla mental útil: la VM es el cómputo; todo lo demás sobrevive a la VM. Por eso el módulo 1 terminaba con esa consulta de discos huérfanos e IP públicas sin asociar.
- Familias y tamaños de VM: cómo leer la nomenclatura
Azure ofrece cientos de tamaños agrupados en familias, cada una optimizada para un perfil de carga.
| Familia | Perfil | Cuándo usarla | Ejemplo típico en Contoso |
|---|---|---|---|
| B (ráfagas) | Acumula créditos de CPU cuando está ociosa y los gasta en picos | Entornos de desarrollo, servidores poco cargados con picos cortos | La VM de pruebas del motor de disponibilidad |
| D (uso general) | Equilibrio CPU/memoria (≈4 GB por vCPU) | Servidores de aplicación, web, cargas normales | El motor de disponibilidad en producción |
| E (memoria) | ≈8 GB por vCPU | Bases de datos, cachés, análisis en memoria | Un servidor de informes heredado |
| F (cómputo) | ≈2 GB por vCPU, CPU más rápida | Cálculo intensivo, procesamiento por lotes | Cálculo nocturno de tarifas |
| L (almacenamiento) | Discos NVMe locales muy rápidos | Bases NoSQL, almacenes de datos grandes | No aplica hoy |
| N (GPU) | Aceleración gráfica o de IA | Entrenamiento de modelos, render | No aplica hoy |
| M (memoria masiva) | Cientos de GB o TB de RAM | SAP HANA, bases enormes | No aplica hoy |
Leer un nombre de tamaño
Un nombre como Standard_D4ds_v5 se descompone así:
Standard_D 4 d s _v5
│ │ │ │ │
│ │ │ │ └── versión de la generación (v5, v6…)
│ │ │ └───── s = admite almacenamiento premium (Premium SSD)
│ │ └─────── d = incluye disco temporal local
│ └───────── número de vCPU (4)
└─────────── familia (D = uso general)Otros sufijos que aparecen a menudo:
| Sufijo | Significado |
|---|---|
a |
Procesador AMD |
p |
Procesador Arm (Ampere); más barato, pero requiere binarios Arm |
s |
Compatible con almacenamiento premium |
d |
Con disco temporal local |
i |
Instancia aislada (host físico dedicado) |
m |
Variante con más memoria dentro de la familia |
Ejemplos concretos para orientarte:
Standard_B1s: 1 vCPU, 1 GB de RAM. Ideal para probar y para laboratorios como el de esta lección.Standard_B2ms: 2 vCPU, 8 GB. Un entorno de desarrollo decente.Standard_D4ds_v5: 4 vCPU, 16 GB. Un servidor de aplicación de producción modesto.Standard_E8ds_v5: 8 vCPU, 64 GB. Una base de datos en VM.
Para ver qué hay disponible en tu región y con qué precio orientativo, la CLI te ayuda:
# Tamaños disponibles en West Europe, filtrando la serie B y mostrando
# solo lo que importa para decidir: nombre, vCPU y memoria.
az vm list-sizes \
--location westeurope \
--query "[?starts_with(name, 'Standard_B')].{Tamaño:name, vCPU:numberOfCores, MemoriaMB:memoryInMb}" \
--output tableaz vm list-sizes devuelve el catálogo de la región; el --query con JMESPath que aprendiste en 01-06 filtra por prefijo y renombra las columnas. Ojo: no todos los tamaños están disponibles en todas las regiones ni en todas las suscripciones (hay cuotas, como viste en 01-05).
Consejo de dimensionamiento: empieza pequeño. Cambiar el tamaño de una VM en Azure es una operación de minutos (az vm resize), no un proyecto. Sobredimensionar «por si acaso» es el error de coste número uno de las migraciones, y Azure Advisor te lo recordará en el módulo 8.
- Discos: tipos, rendimiento y coste
Los discos de Azure son discos gestionados: tú creas un recurso de disco y Azure se ocupa de las cuentas de almacenamiento, la replicación y la disponibilidad por debajo. Antes existían los discos no gestionados en cuentas propias; hoy no hay razón para usarlos.
| Tipo | Tecnología | Rendimiento | Casos de uso | Coste relativo |
|---|---|---|---|---|
| Standard HDD | Disco magnético | Bajo, latencia variable (ms) | Copias, archivos, cargas de acceso esporádico | € |
| Standard SSD | SSD | Moderado y más consistente | Desarrollo, pruebas, servidores web ligeros | €€ |
| Premium SSD | SSD, IOPS garantizadas | Alto, latencia de un dígito en ms | Producción, bases de datos, aplicaciones sensibles | €€€ |
| Premium SSD v2 | SSD, IOPS y rendimiento configurables aparte del tamaño | Alto y ajustable con precisión | Producción con necesidades finas | €€€ |
| Ultra Disk | SSD de latencia submilisegundo | Muy alto, IOPS y MB/s ajustables en caliente | SAP HANA, bases OLTP extremas | €€€€ |
Detalles que conviene tener claros desde el principio:
- El rendimiento depende del tamaño en Standard y Premium SSD clásicos: un disco P10 (128 GB) da menos IOPS que un P30 (1 TB). Si necesitas más IOPS, a veces la solución es un disco más grande, no uno más caro.
- Solo los tamaños de VM con
sen el nombre admiten Premium SSD. - El SLA de instancia única del 99,9 % exige discos Premium SSD (o superiores) en todos los discos de la VM. Con discos Standard no hay SLA de instancia única; para eso hacen falta zonas o conjuntos de disponibilidad, y de eso trata la lección 02-02.
- El disco temporal no se factura por separado, pero es volátil: se pierde al desasignar la VM o si Azure la mueve de host físico. Trátalo como una carpeta
/tmpgrande. - Los discos se facturan por capacidad aprovisionada, no por espacio usado: un disco de 1 TB con 10 GB escritos cuesta como 1 TB. Y sigue costando aunque la VM esté apagada.
Decisión de Contoso Airlines para el motor de disponibilidad:
- Desarrollo:
Standard_B1s+ disco de SO Standard SSD de 30 GB. Suficiente para validar el despliegue. - Producción (cuando llegue el momento):
Standard_D4ds_v5+ Premium SSD, para tener SLA y latencia predecible.
- Imágenes: marketplace, imágenes propias y galerías
Una imagen es la plantilla del disco de sistema operativo desde la que arranca la VM.
- Imágenes del marketplace: publicadas por Microsoft o por terceros. Incluyen desde sistemas operativos limpios (Ubuntu, Debian, RHEL, Windows Server) hasta appliances con software preinstalado. Algunas llevan coste de licencia adicional por hora además del cómputo: fíjate siempre en el precio antes de desplegar.
- Imágenes propias (personalizadas): creadas a partir de una VM que ya has configurado. Sirven para el patrón golden image: instalas y endureces una vez, despliegas cien veces iguales.
- Azure Compute Gallery: el servicio para organizar imágenes propias con versiones, replicarlas a varias regiones y compartirlas entre suscripciones. Es lo que usarás cuando las imágenes dejen de ser una y pasen a ser un catálogo.
Buscar imágenes desde la CLI:
# Alias cómodos que Azure mantiene (UbuntuLTS, Debian11, Win2022Datacenter...).
az vm image list --output table
# Búsqueda real en el marketplace: todas las imágenes de Ubuntu Server 22.04
# publicadas por Canonical y disponibles en West Europe.
az vm image list \
--publisher Canonical \
--location westeurope \
--all \
--query "[?contains(sku, '22_04')].{Publicador:publisher, Oferta:offer, SKU:sku, Version:version}" \
--output tableEl identificador completo de una imagen tiene el formato Publicador:Oferta:SKU:Versión, por ejemplo Canonical:ubuntu-24_04-lts:server:latest. Usar latest es cómodo para pruebas; en producción fija una versión concreta para que dos despliegues del mismo script produzcan lo mismo.
- Crear la VM del motor de disponibilidad con Azure CLI
Vamos al grano. Creamos la VM de desarrollo del motor de disponibilidad, con autenticación solo por clave SSH (nunca contraseña), tamaño económico y las etiquetas obligatorias de Contoso.
Paso 1: generar el par de claves SSH
# Genera un par de claves ed25519 (más corto y moderno que RSA).
# -C añade un comentario que ayuda a identificar la clave luego.
ssh-keygen -t ed25519 -f ~/.ssh/contoso_motor -C "[email protected]"Esto crea dos ficheros: ~/.ssh/contoso_motor (clave privada, no sale nunca de tu equipo) y ~/.ssh/contoso_motor.pub (clave pública, la que subimos a Azure). Si el comando pide una frase de paso, ponla: protege la clave si te roban el portátil.
Paso 2: crear la máquina virtual
#!/usr/bin/env bash
set -euo pipefail
# ---- Parámetros (misma nomenclatura que el módulo 1) ----
GRUPO="rg-contoso-reservas-dev"
REGION="westeurope"
VM="vm-motor-disponibilidad-dev"
IMAGEN="Canonical:ubuntu-24_04-lts:server:latest"
TAMANO="Standard_B1s"
# ---- Creación de la VM ----
az vm create \
--resource-group "${GRUPO}" \
--name "${VM}" \
--image "${IMAGEN}" \
--size "${TAMANO}" \
--admin-username azureuser \
--ssh-key-values ~/.ssh/contoso_motor.pub \
--public-ip-sku Standard \
--public-ip-address-allocation static \
--os-disk-name "disco-so-${VM}" \
--os-disk-size-gb 30 \
--storage-sku StandardSSD_LRS \
--nsg-rule SSH \
--tags entorno=desarrollo \
proyecto=contoso-reservas \
centro-coste=CC-1042 \
[email protected] \
criticidad=baja \
--output tableQué hace cada opción, una por una:
| Opción | Efecto |
|---|---|
--image |
Imagen de partida, en formato Publicador:Oferta:SKU:Versión |
--size |
Tamaño de VM (familia B, 1 vCPU, 1 GB) |
--admin-username |
Usuario administrador que se crea en el sistema |
--ssh-key-values |
Clave pública que se instala en ~/.ssh/authorized_keys. Al indicarla, Azure deshabilita el acceso por contraseña |
--public-ip-sku Standard |
SKU Standard: cerrada por defecto, compatible con zonas. La SKU Basic está retirada |
--public-ip-address-allocation static |
La IP no cambia al reiniciar. Recuerda: se factura aunque la VM esté apagada |
--os-disk-name |
Nombre explícito del disco, para no acabar con nombres aleatorios |
--storage-sku StandardSSD_LRS |
Tipo de disco del sistema operativo |
--nsg-rule SSH |
Crea un NSG con una regla de entrada para el puerto 22 |
--tags |
Las etiquetas obligatorias del esquema de Contoso, en minúsculas y sin acentos |
Si no indicas red virtual, az vm create crea una con un nombre derivado (vm-motor-disponibilidad-devVNET) y una subred por defecto. Para el laboratorio vale; en producción no. En la lección 02-05 diseñaremos vnet-contoso-pro con sus subredes y conectaremos ahí las VM con --vnet-name y --subnet.
Advertencia de seguridad:
--nsg-rule SSHabre el puerto 22 a todo internet (0.0.0.0/0). Es aceptable durante diez minutos en un laboratorio; no lo es en producción. En 02-05 verás cómo restringirlo por IP de origen y, mejor aún, cómo usar Azure Bastion para no exponer SSH en absoluto.
La salida incluye la IP pública asignada. También puedes recuperarla en cualquier momento:
IP=$(az vm show \
--resource-group rg-contoso-reservas-dev \
--name vm-motor-disponibilidad-dev \
--show-details \
--query publicIps \
--output tsv)
echo "IP pública: ${IP}"--show-details (o -d) es el que hace que az vm show incluya datos de red; sin él, la consulta devuelve vacío. Es una de esas rarezas de la CLI que conviene memorizar.
- Conectarse por SSH e instalar el servicio
Ya dentro de la VM, simulamos el despliegue del motor de disponibilidad. El motor real es Java, así que instalamos el entorno de ejecución y un servicio HTTP mínimo que responda como lo haría el motor:
# --- Dentro de la VM ---
sudo apt-get update
sudo apt-get install -y openjdk-21-jre-headless nginx
# Página de salud que imita la respuesta del motor heredado.
echo '{"servicio":"motor-disponibilidad","estado":"ok","version":"legado-3.4"}' \
| sudo tee /var/www/html/salud.json
sudo systemctl enable --now nginx
curl -s http://localhost/salud.jsonDesde tu equipo, comprueba que responde por internet. Antes hay que abrir el puerto 80 en el NSG, porque solo abrimos el 22:
# Regla de entrada para HTTP en el NSG que creó az vm create.
az network nsg rule create \
--resource-group rg-contoso-reservas-dev \
--nsg-name "vm-motor-disponibilidad-devNSG" \
--name permitir-http \
--priority 320 \
--protocol Tcp \
--destination-port-ranges 80 \
--access Allow \
--direction Inbound \
--output none
curl -s "http://${IP}/salud.json"La prioridad (320) determina el orden de evaluación: número más bajo, se evalúa antes. En 02-05 verás las reglas por defecto y las etiquetas de servicio con detalle.
- Configuración inicial automática: cloud-init y extensiones
Instalar a mano funciona una vez. Para hacerlo cien veces iguales hay dos mecanismos.
cloud-init (Linux)
cloud-init es el estándar de la industria para configurar una máquina Linux en su primer arranque. Se pasa un fichero YAML y Azure lo inyecta.
#cloud-config
package_update: true
packages:
- openjdk-21-jre-headless
- nginx
write_files:
- path: /var/www/html/salud.json
content: '{"servicio":"motor-disponibilidad","estado":"ok","version":"legado-3.4"}'
permissions: '0644'
runcmd:
- systemctl enable --now nginxGuárdalo como init-motor.yaml y úsalo al crear la VM:
az vm create \
--resource-group rg-contoso-reservas-dev \
--name vm-motor-disponibilidad-dev \
--image Canonical:ubuntu-24_04-lts:server:latest \
--size Standard_B1s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/contoso_motor.pub \
--custom-data init-motor.yaml \
--output noneBloque a bloque: package_update refresca el índice de paquetes; packages instala; write_files crea ficheros con permisos concretos; runcmd ejecuta órdenes al final. La primera línea #cloud-config es obligatoria y debe ser exactamente esa: sin ella, cloud-init ignora el fichero. Puedes verificar el resultado dentro de la VM con cloud-init status --wait y revisar /var/log/cloud-init-output.log cuando algo no salga.
Extensiones de VM
Las extensiones son agentes pequeños que Azure instala y ejecuta dentro de la VM después del arranque, a través del agente de Azure. A diferencia de cloud-init, se pueden aplicar a una VM ya existente y se gestionan desde el plano de control.
| Extensión | Para qué sirve |
|---|---|
customScript |
Ejecuta un script arbitrario (el comodín) |
AzureMonitorLinuxAgent |
Envía métricas y registros a Log Analytics (módulo 7) |
AADSSHLoginForLinux |
Inicio de sesión SSH con identidad de Microsoft Entra ID (módulo 4) |
NetworkWatcherAgentLinux |
Diagnósticos de red (lección 02-05) |
# Ejecutar un script de configuración en una VM ya creada.
az vm extension set \
--resource-group rg-contoso-reservas-dev \
--vm-name vm-motor-disponibilidad-dev \
--name customScript \
--publisher Microsoft.Azure.Extensions \
--version 2.1 \
--settings '{"commandToExecute":"echo motor-disponibilidad-desplegado > /var/www/html/estado.txt"}' \
--output noneCriterio práctico: cloud-init para la configuración base inmutable del primer arranque; extensiones para agentes de plataforma y para actuar sobre máquinas ya desplegadas. Si acabas escribiendo scripts largos en cualquiera de los dos, la respuesta real es una imagen propia o un contenedor.
- Estados de una VM y qué se factura en cada uno
Este apartado es el que más dinero ahorra de toda la lección.
| Estado | Comando | ¿Se factura el cómputo? | ¿Se factura el disco? | Notas |
|---|---|---|---|---|
| En ejecución | az vm start |
Sí | Sí | Estado normal |
| Detenida (parada desde dentro del SO) | sudo shutdown -h now |
Sí | Sí | El hardware sigue reservado |
| Detenida (desasignada) | az vm deallocate |
No | Sí | Libera el host; se pierde el disco temporal |
| Eliminada | az vm delete |
No | Depende | Los discos y la IP pueden sobrevivir |
Léelo otra vez: apagar la VM desde dentro del sistema operativo NO deja de facturar el cómputo. Azure mantiene los recursos del host reservados para ti. Solo la desasignación libera el hardware y detiene el cargo por cómputo.
# Detener y desasignar: esto sí para el reloj del cómputo.
az vm deallocate \
--resource-group rg-contoso-reservas-dev \
--name vm-motor-disponibilidad-dev
# Comprobar el estado real de la VM.
az vm get-instance-view \
--resource-group rg-contoso-reservas-dev \
--name vm-motor-disponibilidad-dev \
--query "instanceView.statuses[?starts_with(code,'PowerState')].displayStatus" \
--output tsvConsecuencias de desasignar que debes conocer:
- Se pierde el contenido del disco temporal (
/mnt). - Si la IP pública es dinámica, se libera y al arrancar recibirás otra. Con estática la conservas, pero la pagas mientras exista.
- La IP privada dinámica también puede cambiar al reasignar.
Contoso aplica esto de forma sistemática: las VM de rg-contoso-reservas-dev se desasignan cada noche y los fines de semana. En el módulo 7 automatizarás ese apagado con Azure Automation, y en el módulo 8 verás cuánto representa en la factura (típicamente, más de la mitad del gasto de los entornos que no son producción).
- Instantáneas e imágenes: copias y clones
Dos mecanismos que se confunden a menudo:
| Mecanismo | Qué es | Uso típico |
|---|---|---|
| Instantánea (snapshot) | Copia puntual de un disco concreto | Punto de retorno antes de un cambio arriesgado |
| Imagen | Plantilla de una VM completa (SO + discos de datos), normalmente generalizada | Crear muchas VM idénticas |
# 1. Instantánea del disco de sistema operativo antes de actualizar el motor.
DISCO_ID=$(az vm show \
--resource-group rg-contoso-reservas-dev \
--name vm-motor-disponibilidad-dev \
--query "storageProfile.osDisk.managedDisk.id" \
--output tsv)
az snapshot create \
--resource-group rg-contoso-reservas-dev \
--name "snap-motor-$(date +%Y%m%d)" \
--source "${DISCO_ID}" \
--tags entorno=desarrollo proyecto=contoso-reservas centro-coste=CC-1042 \
--output tablePrimero obtenemos el ID de recurso del disco (esa cadena /subscriptions/.../disks/... que viste en 01-05) y después creamos la instantánea a partir de él. Una instantánea ocupa y se factura; bórrala cuando ya no la necesites.
Para una imagen generalizada de Linux, el proceso completo es: sudo waagent -deprovision+user dentro de la VM, luego az vm deallocate, az vm generalize y az image create. Una VM generalizada ya no se puede volver a usar: solo sirve como origen de imagen. No lo hagas con la máquina que necesitas mañana.
Para copias de seguridad de verdad (con política, retención y recuperación granular) no se usan instantáneas manuales, sino Azure Backup, que verás en la lección 07-05.
- Limpieza al terminar
# Opción A: borrar solo la VM y sus recursos asociados (--yes evita la confirmación).
az vm delete \
--resource-group rg-contoso-reservas-dev \
--name vm-motor-disponibilidad-dev \
--yes
# Comprobación imprescindible: ¿quedaron discos o IP huérfanos?
az disk list --resource-group rg-contoso-reservas-dev --output table
az network public-ip list --resource-group rg-contoso-reservas-dev --output table
az network nic list --resource-group rg-contoso-reservas-dev --output table
# Opción B (laboratorio): borrar el grupo entero. Irreversible.
# az group delete --name rg-contoso-reservas-dev --yes --no-waitaz vm delete no borra por defecto el disco de SO, la NIC ni la IP pública. Al crear la VM puedes pedir que se borren con ella:
az vm create ... \
--os-disk-delete-option Delete \
--nic-delete-option Delete \
--data-disk-delete-option DeleteRecuerda que el grupo rg-contoso-reservas-pro tiene el bloqueo no-borrar-produccion (CanNotDelete) que pusiste en 01-05: cualquier intento de borrado ahí fallará hasta que lo retires. Es exactamente lo que queremos.
Errores Comunes y Consejos
- Creer que apagar la VM deja de facturar. Solo
az vm deallocatedetiene el cargo por cómputo. Apagar desde el sistema operativo no. - Borrar la VM y dejar discos e IP huérfanos. Se facturan por existir. Revisa siempre después de borrar, o usa las opciones
--*-delete-option Delete. - Guardar datos en el disco temporal.
/mntse vacía al desasignar o al migrar de host. Ahí solo va lo desechable. - Sobredimensionar la VM «por si acaso». Redimensionar es un
az vm resizede dos minutos con un reinicio. Empieza pequeño. - Abrir SSH o RDP a todo internet. El puerto 22 abierto recibe intentos de acceso automatizados en minutos. Restringe por IP de origen o usa Azure Bastion (02-05).
- Usar contraseñas en lugar de claves SSH. Con
--ssh-key-valuesAzure deshabilita el acceso por contraseña. No hay ninguna razón para lo contrario. - Usar
latesten la versión de imagen en producción. Dos despliegues idénticos pueden dar máquinas distintas. Fija la versión. - Olvidar
--show-detailsenaz vm show. Sin él no verás las IP y creerás que la VM no tiene red. - Consejo de nomenclatura: nombra explícitamente disco, NIC e IP (
disco-so-…,nic-…,ip-…). Los nombres automáticos con sufijos aleatorios convierten la limpieza en arqueología. - Consejo de licencias: si migras Windows Server o SQL Server con Software Assurance, mira Azure Hybrid Benefit (lección 08-03) antes de desplegar; el ahorro puede superar el 40 %.
Ejercicios
Ejercicio 1: elegir tamaño y disco con criterio
Para cada caso de Contoso Airlines, propón familia, tamaño aproximado y tipo de disco de SO, y justifica la elección:
- VM de pruebas donde Diego Salas valida cada versión del motor de disponibilidad; se usa dos horas al día.
- Motor de disponibilidad en producción durante la temporada alta: 4 vCPU y 16 GB estimados, latencia importante, requiere SLA de instancia única.
- Proceso nocturno que recalcula tarifas: dos horas de CPU al 100 %, poca memoria, sin persistencia relevante.
- Servidor de informes heredado que carga en memoria un cubo de 48 GB.
Ejercicio 2: desplegar el motor con cloud-init y verificar el ahorro
- Escribe un
init-motor.yamlque instalenginx, cree/var/www/html/salud.jsoncon{"servicio":"motor-disponibilidad","estado":"ok"}y arranque el servicio. - Crea
vm-motor-disponibilidad-devenrg-contoso-reservas-devconStandard_B1s, disco Standard SSD de 30 GB, clave SSH y las cuatro etiquetas obligatorias. - Abre el puerto 80 en el NSG y comprueba la respuesta desde tu equipo.
- Desasigna la VM y demuestra con un comando que su estado es deallocated.
Ejercicio 3: auditoría de gasto oculto
Escribe los comandos de Azure CLI que respondan a estas preguntas en la suscripción de desarrollo:
- ¿Qué VM hay y en qué estado de energía está cada una?
- ¿Hay discos sin conectar a ninguna VM y cuántos GB suman?
- ¿Hay IP públicas sin asociar?
- ¿Qué VM no tienen la etiqueta
propietario?
Soluciones
Solución 1:
| Caso | Propuesta | Justificación |
|---|---|---|
| 1. Pruebas dos horas al día | Standard_B2s + Standard SSD |
La serie B acumula créditos mientras está ociosa; con desasignación nocturna el coste es mínimo. No necesita SLA |
| 2. Producción del motor | Standard_D4ds_v5 + Premium SSD |
Uso general equilibrado 4 vCPU/16 GB; el SLA de instancia única del 99,9 % exige discos Premium en todos los discos |
| 3. Recálculo nocturno | Standard_F4s_v2 + Standard SSD |
Familia de cómputo: más CPU por euro y poca memoria necesaria. Desasignar al terminar |
| 4. Informes con cubo de 48 GB | Standard_E8ds_v5 (8 vCPU / 64 GB) + Premium SSD |
Familia de memoria: ≈8 GB por vCPU, con margen sobre los 48 GB del cubo |
Solución 2:
#cloud-config
package_update: true
packages:
- nginx
write_files:
- path: /var/www/html/salud.json
content: '{"servicio":"motor-disponibilidad","estado":"ok"}'
permissions: '0644'
runcmd:
- systemctl enable --now nginx#!/usr/bin/env bash
set -euo pipefail
GRUPO="rg-contoso-reservas-dev"
VM="vm-motor-disponibilidad-dev"
# 2. Creación de la VM con cloud-init y etiquetas obligatorias.
az vm create \
--resource-group "${GRUPO}" \
--name "${VM}" \
--image Canonical:ubuntu-24_04-lts:server:latest \
--size Standard_B1s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/contoso_motor.pub \
--custom-data init-motor.yaml \
--os-disk-name "disco-so-${VM}" \
--os-disk-size-gb 30 \
--storage-sku StandardSSD_LRS \
--nsg-rule SSH \
--tags entorno=desarrollo proyecto=contoso-reservas \
centro-coste=CC-1042 [email protected] \
--output none
# 3. Abrir HTTP y probar.
az network nsg rule create \
--resource-group "${GRUPO}" \
--nsg-name "${VM}NSG" \
--name permitir-http --priority 320 \
--protocol Tcp --destination-port-ranges 80 \
--access Allow --direction Inbound --output none
IP=$(az vm show -g "${GRUPO}" -n "${VM}" --show-details --query publicIps -o tsv)
curl -s "http://${IP}/salud.json"
# 4. Desasignar y comprobar el estado.
az vm deallocate --resource-group "${GRUPO}" --name "${VM}"
az vm get-instance-view -g "${GRUPO}" -n "${VM}" \
--query "instanceView.statuses[?starts_with(code,'PowerState')].code" -o tsv
# Salida esperada: PowerState/deallocatedSolución 3:
# 1. VM y su estado de energía (--show-details incluye powerState).
az vm list --show-details \
--query "[].{VM:name, Grupo:resourceGroup, Estado:powerState, Tamaño:hardwareProfile.vmSize}" \
--output table
# 2. Discos sin conectar y su tamaño.
az disk list \
--query "[?diskState=='Unattached'].{Disco:name, GB:diskSizeGb, Grupo:resourceGroup}" \
--output table
# 3. IP públicas sin asociar a ninguna configuración de red.
az network public-ip list \
--query "[?ipConfiguration==null].{IP:name, Direccion:ipAddress, Grupo:resourceGroup}" \
--output table
# 4. VM sin etiqueta propietario.
az vm list \
--query "[?tags.propietario == \`null\`].{VM:name, Grupo:resourceGroup}" \
--output tableLos puntos 2 y 3 son la fuente más habitual de gasto invisible: se facturan por existir, no por usarse.
Conclusión
Ya sabes desplegar cómputo IaaS en Azure con criterio. Has visto cuándo una VM es la respuesta correcta —el motor de disponibilidad heredado de Contoso, que no puede reescribirse todavía— y cuándo es simplemente el camino cómodo y caro. Conoces la anatomía completa de una VM y los recursos que arrastra: disco de SO, disco temporal volátil, discos de datos, NIC, IP pública y NSG, cada uno con su ciclo de vida propio. Sabes leer la nomenclatura de tamaños (Standard_D4ds_v5) y elegir familia según el perfil de carga, y comparar tipos de disco entendiendo que el SLA de instancia única exige Premium SSD. Has creado una VM Linux con claves SSH, la has configurado con cloud-init y extensiones, y —lo más rentable de la lección— has interiorizado la diferencia entre detenida y detenida (desasignada), junto con la limpieza que evita discos e IP huérfanos.
Pero esta VM tiene un problema de fondo que ningún tamaño arregla: es una sola máquina. Si el host falla, si hay mantenimiento de plataforma o si en abril se abre la venta de la temporada de verano y llegan diez veces más peticiones de las habituales, no hay red de seguridad. Una instancia única no tiene SLA salvo con discos Premium, y aun así sigue siendo un único punto de fallo.
En la siguiente lección, Escalado y alta disponibilidad del cómputo, resolvemos exactamente eso: escalado vertical frente a horizontal y por qué la nube apuesta por el segundo, conjuntos de escalado de máquinas virtuales con reglas automáticas por métrica y programadas para el pico de venta de Contoso, zonas y conjuntos de disponibilidad con sus dominios de error y actualización, y las cuatro opciones de balanceo de carga de Azure comparadas. Al terminar tendrás la API de Disponibilidad sirviendo detrás de un balanceador con dos instancias en zonas distintas.
Curso de Azure
Módulo 1: Introducción a Azure
- ¿Qué es Azure?
- Modelos de servicio, regiones y zonas de disponibilidad
- Crear y configurar tu cuenta de Azure
- Recorrido por el portal de Azure
- Azure Resource Manager: suscripciones, grupos de recursos y etiquetas
- Azure CLI, PowerShell y Cloud Shell
Módulo 2: Servicios principales de Azure
- Máquinas virtuales de Azure
- Escalado y alta disponibilidad del cómputo
- Azure App Service
- Azure Storage: blobs, archivos, colas y tablas
- Redes en Azure: redes virtuales, subredes y NSG
- Conectividad híbrida y entrega global
Módulo 3: Bases de datos de Azure
- Elegir el servicio de datos adecuado
- Azure SQL Database
- Azure Cosmos DB
- Azure Database for MySQL
- Azure Database for PostgreSQL
- Analítica de datos: Data Lake, Data Factory y Synapse
Módulo 4: Seguridad en Azure
- Microsoft Entra ID y gestión de identidades
- RBAC e identidades administradas
- Azure Key Vault
- Protección DDoS y firewall de aplicaciones web
- Microsoft Defender for Cloud
- Gobernanza y cumplimiento con Azure Policy
Módulo 5: Azure DevOps
- Introducción a Azure DevOps
- Azure Repos
- Azure Pipelines: integración continua
- Despliegue continuo con entornos y aprobaciones
- Azure Artifacts
- Infraestructura como código con Bicep
Módulo 6: Servicios avanzados de Azure
- Contenedores en Azure: Container Registry y Container Apps
- Azure Kubernetes Service (AKS)
- Azure Functions
- Azure Logic Apps
- Mensajería y eventos: Service Bus, Event Grid y Event Hubs
- Servicios de IA de Azure
Módulo 7: Monitoreo y gestión
- Azure Monitor: métricas, alertas y paneles
- Log Analytics y consultas KQL
- Application Insights
- Azure Automation y runbooks
- Copias de seguridad y recuperación ante desastres
Módulo 8: Gestión y optimización de costos
- Calculadora de precios y estimación de costes
- Azure Cost Management: análisis, presupuestos y alertas
- Reservas, planes de ahorro y Azure Hybrid Benefit
- Azure Advisor
- Estrategias de optimización y cultura FinOps
