Marta Ríos hizo el ejercicio de anotar en qué se le iba la semana. El resultado incomoda: apagar y encender los entornos de desarrollo, borrar instantáneas de discos que ya nadie recuerda, revisar qué certificados están a punto de caducar, rotar credenciales, exportar un informe de recursos sin etiquetar y aplicar parches a las máquinas. Nada de eso es difícil, nada requiere criterio, y todo hay que hacerlo. Son horas de un perfil senior dedicadas a tareas que una máquina ejecutaría mejor, siempre igual y sin olvidarse.

Con la plataforma ya observable tras las tres lecciones anteriores, toca automatizar la operación. Azure Automation es el servicio que ejecuta scripts programados o disparados por eventos, con identidad propia, sin servidor que mantener y con registro de todo lo que hace. En esta lección construirás la cuenta de automatización de Contoso, escribirás el runbook que apaga los entornos de desarrollo por la noche, lo conectarás con las alertas de 07-01 y verás dónde termina Automation y empiezan Azure Update Manager y Machine Configuration.

Contenido

  1. Qué es Azure Automation y sus componentes
  2. Tipos de runbook y cuál elegir
  3. Crear aa-contoso-operaciones con identidad administrada
  4. El runbook estrella: apagar y encender por etiqueta
  5. Programaciones, pruebas, control de código fuente y publicación
  6. Disparar un runbook desde una alerta: runbook, Logic App o función
  7. Gestión de actualizaciones con Azure Update Manager
  8. Configuración de estado deseado y Machine Configuration
  9. Azure Resource Graph: inventario a escala
  10. Costes y buenas prácticas de runbooks
  11. Errores Comunes y Consejos
  12. Ejercicios
  13. Conclusión

  1. Qué es Azure Automation y sus componentes

Azure Automation es un servicio administrado que ejecuta scripts —llamados runbooks— en infraestructura de Microsoft, bajo una identidad propia y con un registro completo de cada ejecución. No hay que aprovisionar ni parchear nada. Sus piezas:

Componente Qué es Uso en Contoso
Cuenta de Automation El contenedor: identidad, activos, runbooks y trabajos aa-contoso-operaciones
Runbook El script y su lógica Detener-IniciarEntornosDev
Programación Cuándo se ejecuta, con su zona horaria Cada día laborable a las 20:00 y a las 7:30
Trabajo (job) Una ejecución concreta, con su salida y su estado Consultable y consultada por KQL
Variables Valores de configuración, con opción de cifrado Identificadores de suscripción, listas de exclusión
Credenciales Usuario y contraseña cifrados Acceso a sistemas antiguos de la oficina
Certificados y conexiones Material de autenticación reutilizable Integración con el sistema de facturación
Módulos Bibliotecas de PowerShell o Python disponibles Az.Accounts, Az.Compute, Az.Resources
Hybrid Runbook Worker Un agente que ejecuta el runbook fuera de Azure Servidores locales de la oficina de Barcelona

El Hybrid Runbook Worker merece una nota. Un runbook normal se ejecuta en la nube de Azure y solo alcanza lo que sea accesible desde internet o por red privada. Los servidores de facturación de mostradores que Contoso conserva en Barcelona no lo son. Instalando el agente en una de esas máquinas, el mismo runbook se ejecuta dentro de la red local, con acceso a recursos internos, pero programado y auditado desde Azure. Es la vía para automatizar lo local sin abrir nada hacia fuera, y encaja con la conectividad híbrida del módulo 2.

  1. Tipos de runbook y cuál elegir

Tipo Lenguaje Puntos de control Cuándo elegirlo
PowerShell PowerShell 7.x No La opción por defecto para tareas sobre Azure
PowerShell Workflow Sintaxis de flujo de trabajo Sí, con paralelismo Procesos muy largos e interrumpibles; en desuso
Python Python 3.x No Equipos con base Python, o bibliotecas de datos
Gráfico Editor visual, sin código No Demostraciones; difícil de versionar y revisar

La recomendación es directa: PowerShell salvo motivo de peso. Los módulos Az cubren todo Azure, la sintaxis es la misma que en Cloud Shell (módulo 1) y el resultado es un fichero de texto que se revisa en un pull request. Los runbooks gráficos parecen cómodos y no lo son: no se pueden diferenciar en Git, no se revisan bien y no se reutilizan.

  1. Crear aa-contoso-operaciones con identidad administrada

La cuenta necesita permisos para actuar sobre los recursos. La forma correcta —y la única aceptable en producción— es una identidad administrada asignada por el sistema, con los permisos mínimos y en el ámbito mínimo, aplicando el RBAC del módulo 4.

# 1. Cuenta de Automation con identidad administrada asignada por el sistema
az automation account create \
  --name aa-contoso-operaciones \
  --resource-group rg-contoso-seguridad-pro \
  --location westeurope --sku Free \
  --assign-identity \
  --tags entorno=produccion proyecto=contoso-reservas centro-coste=CC-1042 propietario=marta.rios

# 2. Identificador de la entidad de seguridad de esa identidad
PRINCIPAL=$(az automation account show \
  --name aa-contoso-operaciones --resource-group rg-contoso-seguridad-pro \
  --query identity.principalId -o tsv)

# 3. Permiso MÍNIMO y ACOTADO: solo iniciar/detener VMs, y solo en desarrollo
az role assignment create \
  --assignee "$PRINCIPAL" \
  --role "Colaborador de máquina virtual" \
  --scope "/subscriptions/<id-desarrollo>/resourceGroups/rg-contoso-reservas-dev"

# 4. Lectura global para poder inventariar, sin capacidad de modificar
az role assignment create --assignee "$PRINCIPAL" --role "Lector" \
  --scope "/subscriptions/<id-desarrollo>"

Tres decisiones que conviene razonar. El ámbito es rg-contoso-reservas-dev, no la suscripción: un fallo o un abuso del runbook no puede tocar producción, por construcción. El rol es el más específico que sirve, nunca Colaborador a nivel de suscripción, y menos aún Propietario —que además permitiría a la identidad concederse más permisos—. Y la identidad es administrada, sin secretos que rotar ni que puedan filtrarse; las cuentas de ejecución clásicas basadas en certificado están retiradas.

Después hay que importar los módulos necesarios (Az.Accounts, Az.Compute, Az.Resources) y fijar la versión del entorno de ejecución. Una actualización automática de módulos puede cambiar el comportamiento de un runbook que llevaba un año funcionando; en producción, la versión se fija y se actualiza deliberadamente.

  1. El runbook estrella: apagar y encender por etiqueta

Este es el runbook que más dinero ahorra y el que mejor ilustra las buenas prácticas. Los recursos de desarrollo etiquetados con horario=laborable no tienen por qué estar encendidos de noche ni en fin de semana: son unas 128 horas semanales de las 168 posibles, y eso es directamente factura.

<#
.SYNOPSIS
    Inicia o detiene los recursos de desarrollo etiquetados con horario=laborable.
.DESCRIPTION
    Idempotente: comprueba el estado antes de actuar y no falla si ya está como debe.
    Registra cada decisión para poder auditarla desde log-contoso-pro.
#>
param(
    [Parameter(Mandatory = $true)]
    [ValidateSet("Iniciar", "Detener")]
    [string]$Accion,

    [string]$GrupoRecursos = "rg-contoso-reservas-dev",
    [string]$EtiquetaClave = "horario",
    [string]$EtiquetaValor = "laborable",

    # Ejecución en seco: registra lo que haría, sin hacerlo. Imprescindible al estrenar.
    [bool]$Simulacion = $false
)

$ErrorActionPreference = "Stop"      # cualquier error no controlado detiene el runbook
$inicio = Get-Date
Write-Output "=== $Accion | grupo=$GrupoRecursos | simulacion=$Simulacion | $inicio ==="

try {
    # 1. Autenticación con la identidad administrada: sin secretos en el código
    Connect-AzAccount -Identity | Out-Null
    Write-Output "Autenticado con la identidad administrada de aa-contoso-operaciones."

    # 2. Localizar las máquinas por etiqueta. -Status trae el estado de energía real.
    $maquinas = Get-AzVM -ResourceGroupName $GrupoRecursos -Status |
        Where-Object { $_.Tags[$EtiquetaClave] -eq $EtiquetaValor }

    if (-not $maquinas) {
        Write-Warning "Ninguna máquina con $EtiquetaClave=$EtiquetaValor en $GrupoRecursos."
        return
    }
    Write-Output "Encontradas $($maquinas.Count) máquinas candidatas."

    $actuadas = 0; $omitidas = 0; $fallidas = 0

    foreach ($vm in $maquinas) {
        $estado = ($vm.Statuses | Where-Object Code -like "PowerState/*").Code

        # 3. Idempotencia: si ya está en el estado deseado, no se toca
        $yaCorrecto = ($Accion -eq "Iniciar"  -and $estado -eq "PowerState/running") -or
                      ($Accion -eq "Detener" -and $estado -eq "PowerState/deallocated")
        if ($yaCorrecto) {
            Write-Output "OMITIDA  $($vm.Name): ya está en $estado."
            $omitidas++; continue
        }

        if ($Simulacion) {
            Write-Output "SIMULADO $($vm.Name): se ejecutaría '$Accion' (estado actual $estado)."
            $actuadas++; continue
        }

        # 4. Cada máquina en su propio try: un fallo no debe abortar el resto
        try {
            if ($Accion -eq "Iniciar") {
                Start-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -NoWait | Out-Null
            } else {
                # -Force evita la confirmación interactiva; detener libera el coste de cómputo
                Stop-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Force -NoWait | Out-Null
            }
            Write-Output "HECHO    $($vm.Name): '$Accion' lanzada (estado previo $estado)."
            $actuadas++
        }
        catch {
            Write-Error "FALLO    $($vm.Name): $($_.Exception.Message)"
            $fallidas++
        }
    }

    $segundos = [int]((Get-Date) - $inicio).TotalSeconds
    Write-Output "=== Resumen: actuadas=$actuadas omitidas=$omitidas fallidas=$fallidas en ${segundos}s ==="

    # 5. Salida estructurada: se consulta con KQL y se puede alertar sobre ella
    if ($fallidas -gt 0) { throw "El runbook terminó con $fallidas máquinas fallidas." }
}
catch {
    Write-Error "Error general del runbook: $($_.Exception.Message)"
    throw            # relanzar marca el trabajo como Failed y permite alertar
}

Los cinco puntos numerados son las buenas prácticas que hacen la diferencia entre un script y un runbook de producción. Connect-AzAccount -Identity autentica sin un solo secreto. La selección por etiqueta en lugar de por lista de nombres significa que una máquina nueva se incorpora sola con solo etiquetarla —y refuerza la política de etiquetado del módulo 1—. La idempotencia permite ejecutarlo dos veces sin efectos raros, lo que importa mucho cuando lo dispara un reintento. El try por máquina evita que un fallo aislado deje las quince restantes encendidas. Y el throw final hace que el trabajo aparezca como fallido, condición sobre la que se puede alertar. El parámetro $Simulacion es la red de seguridad al estrenar: se ejecuta primero en seco y se revisa la salida.

Una advertencia de coste importante: detener una máquina desde el sistema operativo no deja de facturar. Solo el estado deallocated, que es el que produce Stop-AzVM, libera el cómputo. Es un error clásico que hace que la automatización no ahorre nada.

  1. Programaciones, pruebas, control de código fuente y publicación

El ciclo de vida de un runbook tiene un detalle que sorprende: existe en borrador y en publicado, y las programaciones ejecutan siempre la versión publicada. Editar sin publicar no cambia nada en producción, lo cual es una protección, no un fastidio.

El orden correcto de trabajo es: escribir, probar en el panel de prueba —que ejecuta el borrador de forma interactiva y muestra la salida en directo, ideal con $Simulacion = $true—, publicar, y solo entonces programar.

# Importar el runbook desde el repositorio contoso-infra
az automation runbook create --automation-account-name aa-contoso-operaciones \
  --resource-group rg-contoso-seguridad-pro --name Detener-IniciarEntornosDev \
  --type PowerShell --runbook-type PowerShell72

az automation runbook replace-content --automation-account-name aa-contoso-operaciones \
  --resource-group rg-contoso-seguridad-pro --name Detener-IniciarEntornosDev \
  --content @./runbooks/Detener-IniciarEntornosDev.ps1

az automation runbook publish --automation-account-name aa-contoso-operaciones \
  --resource-group rg-contoso-seguridad-pro --name Detener-IniciarEntornosDev

Las dos programaciones de Contoso son diarias, de lunes a viernes, en zona horaria W. Europe Standard Time: sch-apagado-dev a las 20:00 con el parámetro Accion=Detener, y sch-encendido-dev a las 07:30 con Accion=Iniciar. Los parámetros se asocian al vínculo entre programación y runbook, de modo que el mismo runbook sirve para las dos con una sola base de código. La zona horaria no es un detalle: una programación en UTC se desplaza una hora en verano y el equipo llega a las 8:00 con las máquinas apagadas.

El control de código fuente cierra el círculo con el módulo 5. La cuenta se conecta al repositorio contoso-infra de Azure Repos, carpeta /runbooks, y cada push a la rama principal sincroniza los runbooks. Las consecuencias son las que ya conoces: revisión por pull request, historial de quién cambió qué, y posibilidad de revertir. Con la sincronización activa, el portal deja de ser el sitio donde se edita; editar allí crea divergencias que la siguiente sincronización pisa.

  1. Disparar un runbook desde una alerta: runbook, Logic App o función

En 07-01 creaste ag-guardia-contoso y dejaste anunciado que un grupo de acciones puede ejecutar un runbook. Aquí se cierra el círculo: la alerta detecta, el runbook remedia.

flowchart LR
  A["Métrica: profundidad de<br/>cola-emision-tarjetas > 500"] --> B["Alerta de Azure Monitor"]
  B --> C["Grupo de acciones<br/>ag-equipo-contoso"]
  C --> D["Webhook del runbook<br/>Escalar-ProcesadoTarjetas"]
  C --> E["Correo al equipo"]
  D --> F["Aumenta instancias<br/>y registra la acción"]
  F --> G["Nueva ejecución<br/>visible en AzureDiagnostics"]

El disparador es un webhook: una URL con un token de un solo uso que se genera al crearlo y no se puede volver a consultar, por lo que hay que guardarla de inmediato en kv-contoso-pro. El grupo de acciones envía a esa URL el esquema común de alertas, y el runbook lo recibe en el parámetro $WebhookData, del que extrae qué recurso disparó la alerta:

param([object]$WebhookData)

if (-not $WebhookData) { throw "Este runbook debe invocarse desde un webhook de alerta." }

$alerta  = (ConvertFrom-Json $WebhookData.RequestBody).data.essentials
$recurso = $alerta.alertTargetIDs[0]
Write-Output "Alerta '$($alerta.alertRule)' con gravedad $($alerta.severity) sobre $recurso"

Connect-AzAccount -Identity | Out-Null
# ... lógica de remediación, idempotente y con registro ...

¿Runbook, Logic App o función? Las tres pueden reaccionar a una alerta, y la elección importa:

Runbook de Automation Logic App Azure Function
Fuerte en Operar infraestructura de Azure Integrar sistemas y notificar Lógica a medida y rendimiento
Lenguaje PowerShell / Python Diseñador visual, conectores El que elijas (06-03)
Latencia de arranque Segundos a algún minuto Segundos Milisegundos (o arranque en frío)
Ejecuciones largas Sí, horas Sí, con límites Limitado según el plan
Quién lo mantiene Operaciones Operaciones y negocio Desarrollo
Coste Minutos, con franja gratuita Por acción ejecutada Por ejecución y consumo
Caso en Contoso Apagar entornos, limpiar instantáneas Avisar en Teams y abrir incidencia (06-04) GenerarTarjetaEmbarque (06-03)

La regla que Contoso aplica: si la tarea manipula infraestructura de Azure y la escribiría un administrador, es un runbook. Si consiste en encadenar sistemas y notificar a personas, es una Logic App. Si es lógica de negocio con requisitos de latencia, es una función. Y nada impide combinarlas: la alerta de la cola dispara a la vez un runbook que escala y una Logic App que avisa en Teams.

  1. Gestión de actualizaciones con Azure Update Manager

La antigua solución de gestión de actualizaciones integrada en Automation ha sido sustituida por Azure Update Manager, un servicio independiente que ya no requiere cuenta de Automation ni área de trabajo, y que funciona igual para máquinas de Azure y para servidores habilitados para Arc.

Sus piezas son tres: evaluación del estado de parches de cada máquina, implementación puntual bajo demanda, y configuraciones de mantenimiento, que son ventanas recurrentes con su ámbito y su política de reinicio.

# Ventana de mantenimiento mensual para el entorno de desarrollo
az maintenance configuration create \
  --resource-group rg-contoso-seguridad-pro \
  --resource-name mc-contoso-dev-mensual \
  --location westeurope \
  --maintenance-scope InGuestPatch \
  --duration 03:00 \
  --recur-every "Month Second Saturday" \
  --start-date-time "2026-09-12 02:00" --time-zone "W. Europe Standard Time" \
  --reboot-setting IfRequired \
  --tags entorno=desarrollo proyecto=contoso-reservas centro-coste=CC-1042 propietario=marta.rios

Contoso mantiene dos configuraciones: mc-contoso-dev-mensual, que parchea vm-motor-disponibilidad-dev el segundo sábado de madrugada, y mc-contoso-pro-mensual, más conservadora, para el sistema operativo base de vmss-api-disponibilidad-pro. En un conjunto de escalado la estrategia preferible sigue siendo distinta: reemplazar instancias con una imagen nueva ya parcheada en lugar de parchear en caliente, que es lo coherente con el ganado frente a las mascotas del módulo 2. Y recuerda coordinar la ventana con una regla de procesamiento de alertas de 07-01 para no despertar a nadie con reinicios previstos.

  1. Configuración de estado deseado y Machine Configuration

Automation incluía State Configuration (DSC), que define en código el estado que una máquina debe tener —qué servicios corren, qué paquetes están instalados, qué claves de registro— y lo corrige cuando se desvía. Esa capacidad se ha trasladado a Azure Machine Configuration, una extensión de Azure Policy: en lugar de vivir en la cuenta de Automation, se asigna como una directiva más dentro de la iniciativa «Base de gobernanza de Contoso» del módulo 4, y su cumplimiento aparece junto al resto en el panel de gobernanza.

La diferencia conceptual con Automation es la que conviene retener: un runbook ejecuta una acción en un momento dado; Machine Configuration vigila y mantiene un estado de forma continua. Contoso lo usa para exigir que en todos los servidores estén el agente de Azure Monitor instalado y determinados servicios detenidos, sin escribir ni un runbook.

  1. Azure Resource Graph: inventario a escala

Antes de automatizar hay que saber sobre qué. Azure Resource Graph consulta con KQL los metadatos de todos los recursos de todas las suscripciones en segundos, algo que con az resource list recorriendo grupos tardaría minutos y agotaría los límites de la API. Es el complemento natural de Automation: el runbook actúa, Resource Graph decide sobre qué.

Resources
| where type =~ "microsoft.compute/virtualmachines"
| extend entorno   = tostring(tags["entorno"]),
         horario   = tostring(tags["horario"]),
         propietario = tostring(tags["propietario"]),
         centroCoste = tostring(tags["centro-coste"])
| where entorno == "desarrollo"
| extend Etiquetada = iif(isnotempty(horario), "sí", "NO")
| project name, resourceGroup, location, Etiquetada, propietario, centroCoste,
          tamano = tostring(properties.hardwareProfile.vmSize)
| order by Etiquetada asc, name asc

La consulta se lee igual que el KQL de 07-02, con dos diferencias: la tabla Resources contiene la configuración de los recursos, no sus registros, y no hay TimeGenerated porque describe el estado actual, no una serie temporal. Su valor aquí es concreto: la columna Etiquetada lista exactamente las máquinas de desarrollo que no llevan horario y que, por tanto, el runbook está ignorando y siguen encendidas de noche. Se ejecuta con az graph query -q "<consulta>" o desde un runbook con Search-AzGraph.

  1. Costes y buenas prácticas de runbooks

El modelo de precios es de los más benignos de Azure: se pagan los minutos de ejecución de los trabajos, con una franja mensual gratuita generosa —del orden de 500 minutos— que cubre de sobra un uso como el de Contoso, y los nodos gestionados por configuración de estado, si se usan. La cuenta de Automation en sí no cuesta nada. Puesto en perspectiva: el runbook de apagado consume unos pocos minutos al día y ahorra el 75 % del coste de cómputo de un entorno completo. Es probablemente la mejor relación de toda la plataforma, y volverás sobre ella en el módulo 8.

Las buenas prácticas que separan un runbook fiable de una bomba de relojería:

  • Idempotente: ejecutarlo dos veces produce el mismo resultado. Comprueba el estado antes de actuar.
  • Con parámetros, sin nada codificado a fuego: nombres, grupos y ámbitos como parámetros o variables de la cuenta.
  • Con modo de simulación: para estrenarlo sin riesgo y para depurar.
  • Con registro estructurado: Write-Output con un formato constante, para poder consultarlo con KQL.
  • Con tratamiento de errores por elemento: un fallo aislado no debe abortar el lote, pero sí reflejarse en el estado final.
  • Acotado por ámbito y por etiqueta: nunca a nivel de suscripción entera «por comodidad».
  • Versionado en Git, revisado por pull request y publicado desde el repositorio.

Y la vigilancia, que cierra con lo aprendido: los trabajos de Automation envían su estado y su salida a log-contoso-pro mediante una configuración de diagnóstico (categorías JobLogs y JobStreams), de modo que se puede alertar sobre JobStatus == "Failed" con una alerta de búsqueda de registros. Un runbook que falla en silencio es peor que no tener runbook, porque el equipo cree que la tarea se está haciendo.

Errores Comunes y Consejos

  • Editar y no publicar. La programación ejecuta la versión publicada; el borrador no cambia nada.
  • Detener la VM desde el sistema operativo. Sigue facturando: solo Stop-AzVM la libera (deallocated).
  • Permisos excesivos. Colaborador en la suscripción por comodidad convierte un fallo del runbook en un incidente de producción.
  • Programación en UTC. El cambio de hora desplaza el encendido y el equipo se encuentra las máquinas apagadas.
  • Runbooks sin vigilancia. Sin alerta sobre trabajos fallidos, la tarea deja de hacerse y nadie se entera.
  • Actualización automática de módulos en producción. Puede romper un runbook estable; fija las versiones.
  • Consejo: estrena todo runbook con $Simulacion = $true y revisa la salida antes de dejarlo actuar.
  • Consejo: selecciona por etiqueta, nunca por lista de nombres. Las listas envejecen; las etiquetas se mantienen solas si la política las exige.
  • Consejo: guarda el token del webhook en kv-contoso-pro en cuanto se genere. No hay forma de recuperarlo después.

Ejercicios

Ejercicio 1. Diseña un runbook que elimine las instantáneas de disco con más de 90 días en rg-contoso-reservas-dev, exceptuando las etiquetadas con conservar=si. Describe parámetros, salvaguardas, permisos, programación y vigilancia. No hace falta el código completo.

Ejercicio 2. El runbook de apagado lleva tres semanas ejecutándose «correctamente», pero la factura de desarrollo no ha bajado. Enumera cinco causas posibles y cómo comprobar cada una.

Ejercicio 3. Contoso Millas (centro-coste=CC-2077) necesita, cada noche, exportar los canjes del día a un fichero, dejarlo en stlagocontosopro y avisar al equipo financiero. Decide entre runbook, Logic App y función —o combinación— y justifica la arquitectura.

Soluciones

Solución 1: parámetros $GrupoRecursos, $DiasAntiguedad = 90, $EtiquetaExclusion = "conservar", $Simulacion = $true por defecto, porque es una operación destructiva y el valor seguro debe ser el predeterminado. Salvaguardas: filtrar por antigüedad con TimeCreated y excluir las etiquetadas; limitar el número de borrados por ejecución —por ejemplo 50— para que un error de filtro no arrase con todo; try por instantánea; y registro del nombre, la fecha y el tamaño de cada una antes de borrarla, de modo que quede constancia de lo eliminado. Permisos: un rol acotado a rg-contoso-reservas-dev con permiso de lectura y borrado de instantáneas, nunca Colaborador de suscripción. Programación: semanal, en fin de semana, fuera de la ventana de mantenimiento para no solapar. Vigilancia: alerta de búsqueda de registros sobre JobStatus == "Failed" y, además, sobre un número de borrados anormalmente alto, que es la señal de que el filtro se ha roto. Y la salvaguarda de fondo: comprobar que existen copias de seguridad vigentes antes de considerar prescindible una instantánea, algo que se trata en 07-05.

Solución 2: (a) Las máquinas se están deteniendo desde el sistema operativo o el estado es stopped y no deallocated, con lo que el cómputo se sigue facturando; se comprueba con Get-AzVM -Status o con Resource Graph mirando el estado de energía. (b) Faltan etiquetas: hay máquinas de desarrollo sin horario=laborable que el runbook ignora; se detecta con la consulta de Resource Graph del apartado 9. (c) El coste no es de cómputo: los discos administrados, las IP públicas y las direcciones reservadas se facturan aunque la máquina esté liberada, y pueden ser la mayor parte del gasto de un entorno pequeño. (d) Alguien enciende las máquinas y no las apaga, o hay un proceso que las inicia; se verifica con AzureActivity filtrando por la operación de inicio y viendo qué identidad la ejecuta. (e) El gasto está en otro sitio: App Service, bases de datos o el propio log-contoso-pro, que el runbook no toca; se confirma con el análisis de coste por recurso del módulo 8. Comprobación transversal: revisar los registros de trabajos en log-contoso-pro, porque «se ejecuta correctamente» puede significar que actúa sobre cero máquinas cada noche.

Solución 3: arquitectura combinada, con cada pieza en lo que hace mejor. Un runbook de PowerShell programado a las 23:30 ejecuta la consulta KQL de canjes sobre log-contoso-pro con Invoke-AzOperationalInsightsQuery, genera el fichero CSV y lo sube a stlagocontosopro autenticándose con la identidad administrada de aa-contoso-operaciones; es la opción correcta porque es una tarea de infraestructura, puede durar minutos y la escribiría un administrador. La notificación la resuelve una Logic App que reacciona a un evento de blob creado —Event Grid, módulo 6— y envía el aviso a Teams y por correo con el enlace: es integración con personas, no infraestructura, y el equipo financiero puede pedir cambios en el mensaje sin tocar código. No hace falta una función: no hay lógica de negocio compleja ni requisito de latencia. Permisos mínimos: Lector de Log Analytics sobre el área y Colaborador de datos de Storage Blob solo sobre el contenedor de destino. Vigilancia: alerta sobre trabajos fallidos y una segunda alerta si el fichero no aparece antes de las 00:30, porque un runbook que no se ejecuta no genera ningún error. Etiquetas: entorno, proyecto=contoso-millas, centro-coste=CC-2077 y propietario.

Conclusión

Ya sabes qué es Azure Automation y para qué sirve: ejecutar el trabajo repetitivo que consumía las semanas de Marta Ríos, sin servidores, con identidad propia y con registro de todo. Conoces sus componentes —cuenta, runbooks, programaciones, trabajos, variables, credenciales, certificados, conexiones y módulos— y el Hybrid Runbook Worker que lleva la misma automatización a los servidores locales de la oficina de Barcelona. Sabes elegir el tipo de runbook, con PowerShell como opción por defecto y los gráficos descartados por no ser versionables. Has creado aa-contoso-operaciones con identidad administrada y permisos mínimos acotados a rg-contoso-reservas-dev, aplicando el RBAC del módulo 4 en lugar de repartir Colaborador por comodidad.

El runbook estrella te ha dejado un patrón completo y reutilizable: autenticación sin secretos, selección por etiqueta en vez de por lista, idempotencia comprobando el estado antes de actuar, modo de simulación para estrenarlo sin riesgo, tratamiento de errores por máquina, registro estructurado y throw final para que el trabajo se marque como fallido y se pueda alertar sobre él —además del detalle que decide si la automatización ahorra o no: solo deallocated deja de facturar—. Sabes probarlo en el panel de prueba, publicarlo —porque la programación ejecuta la versión publicada, no el borrador—, programarlo con su zona horaria correcta y versionarlo en contoso-infra con control de código fuente, cerrando el círculo con el módulo 5.

Has cerrado también el círculo con 07-01: una alerta de Azure Monitor dispara un runbook por webhook, con su token guardado en kv-contoso-pro, y tienes la tabla de decisión para elegir entre runbook, Logic App y función según manipules infraestructura, integres sistemas o ejecutes lógica de negocio. Sitúas Azure Update Manager como sucesor de la gestión de actualizaciones, con sus configuraciones de mantenimiento mc-contoso-dev-mensual y mc-contoso-pro-mensual, y Machine Configuration como heredero de DSC dentro de Azure Policy, con la distinción clave: el runbook actúa una vez, la configuración mantiene un estado. Y llevas Azure Resource Graph como instrumento de inventario a escala para saber sobre qué automatizar, más los costes por minuto con su franja gratuita y las buenas prácticas que hacen un runbook fiable.

Queda la última pieza, y es la que decide si todo lo demás sirve de algo. Contoso tiene ahora una plataforma que ve lo que pasa y que se opera sola en buena medida, pero nada de eso responde a la pregunta del día malo: un borrado accidental, un cifrado por ransomware, una región completa que deja de responder. La lección 07-05, Copias de seguridad y recuperación ante desastres, cierra el módulo con los dos números que gobiernan esa conversación —RPO y RTO—, Azure Backup y sus almacenes, la protección frente al borrado malicioso, qué respalda cada servicio PaaS por sí solo y qué sigue siendo tuyo, Azure Site Recovery, la estrategia entre West Europe y North Europe, y el plan escrito que hay que probar, porque un plan no probado no existe.

Curso de Azure

Módulo 1: Introducción a Azure

Módulo 2: Servicios principales de Azure

Módulo 3: Bases de datos de Azure

Módulo 4: Seguridad en Azure

Módulo 5: Azure DevOps

Módulo 6: Servicios avanzados de Azure

Módulo 7: Monitoreo y gestión

Módulo 8: Gestión y optimización de costos

Módulo 9: Estudios de caso y mejores prácticas

© Copyright 2026. Todos los derechos reservados