Automatiza tu TI desde Azure: menos costes, menos tareas manuales
Automatizar tu TI desde Azure puede aportarle múltiples ventajas a tu negocio. Sobre todo, en el sentido de ayudarte a reducir tanto los costes como el número de tareas manuales. Algo que, además, puede traducirse en un aumento de la productividad. A lo largo de este post vamos a explicarte cómo aprovechar esta opción.
¿Qué beneficios directos puedes obtener si optas por automatizar tu TI desde Azure? Desde un punto de vista pragmático, tal y como ya hemos comentado, podemos dividirlos en dos grandes apartados: infraestructura y tareas. En cuanto a la infraestructura, el escenario en el que más podemos aprovecharlas es el de las máquinas virtuales. Si nuestra empresa trabaja con ellas, ya sea a nivel de servidor o como escritorios remotos, por un lado, podemos optimizar la aplicación de las actualizaciones que sean necesarias. Y, por el otro, además, controlar el gasto monitorizando las necesidades concretas que tengamos en cada momento y, en función de ellas, apagar las que no resulten necesarias en un espacio de tiempo determinado o iniciarlas si es necesario contar con ellas.
A nivel de tareas, mientras, las automatizaciones pueden ayudarnos también a ahorrar tiempo. Y, con ello, contribuir también a aumentar significativamente la productividad. La clave, sobre todo, en este caso, es automatizar tareas manuales pesadas, en apariencia sencillas, pero que precisan la inversión de una gran cantidad de minutos, o tal vez incluso horas, para llevarlas a cabo de manera adecuada. Como, por poner un ejemplo rápido, gestionar las altas y las bajas.
Qué ventajas concretas te ofrece la opción de automatizar tu TI desde Azure
En el párrafo anterior ya hemos comentado algunas de las ventajas principales de automatizar tu TI desde Azure. No obstante, las automatizaciones también pueden resultarnos a su vez muy prácticas en otros ámbitos. Como, por ejemplo, para mejorar la calidad del servicio y obtener una mayor fiabilidad del resultado. En este caso, gracias al hecho de minimizar la introducción de posibles errores humanos a la hora de programar una tarea. Dicha tarea, además, estará del todo optimizada para lograr el resultado deseado. No obstante, hay que tener en cuenta que las automatizaciones requieren pruebas, supervisiones y mantenimientos a lo largo del tiempo según los cambios que se realicen en el entorno o la infraestructura de la empresa.
Por otro lado, las automatizaciones también nos permiten mejorar la estandarización. Es decir, permiten que todos los procesos se ejecuten de la misma manera, independientemente de quién los realice. Así, se fomenta un mejor gobierno a nivel de TI y evitamos la aparición de inconsistencias, errores o excesivas dilaciones al solucionar incidencias. Además, también pueden resultar muy prácticas para detectar posibles problemas de seguridad. Como, por ejemplo, identificar intrusiones indebidas, al revisar las conexiones y descubrir que un usuario en concreto no debería estar conectado en ese momento.
Finalmente, las automatizaciones también nos permiten optimizar la realización de auditorías. De forma fácil y sencilla podemos saber qué se ejecutó, cuándo se hizo, qué resultados se obtuvieron y qué errores, si los hubo, aparecieron. Con ello, en este caso, facilitamos el cumplimiento normativo. A grandes rasgos, podemos resumir todos estos beneficios a través de la siguiente tabla:
| Beneficio | Impacto |
|---|---|
| Reducción del tiempo operativo. | Ahorro a nivel de costes económicos. |
| Mayor control de la escalabilidad. | Crecimiento sostenible y adaptable a las necesidades de cada momento. |
| Minimización de errores. | Mayor calidad del servicio y fiabilidad de los resultados. |
| Impulso de la estandarización. | Mejor gobierno a nivel de TI dentro de la empresa. |
| Mejoras a nivel de seguridad. | Monitorizacion de posibles intrusiones y otras incidencias. |
| Optimización de auditorías. | Facilita la obtención de un mayor cumplimiento. |

Cómo puedes automatizar tu TI desde Azure: dos ejemplos prácticos
Ejemplo de encendido y apagado inteligente de VMs
Pensemos en una situación muy habitual: una empresa con múltiples servidores virtuales en Azure que su equipo solo utiliza en horario laboral. Por comodidad, o porque nadie se encarga de apagarlos, siguen encendidos por la noche, los fines de semana y los festivos, y cada una de esas horas se factura aunque no haya nadie trabajando. Para resolverlo hemos desarrollado un script en PowerShell que se ejecuta mediante las cuentas de Azure Automation, con una programación que decide cuándo debe actuar. El script no depende de una lista fija de máquinas: en cada ejecución detecta las VMs que hay en ese momento, así que se adapta si el entorno crece o cambia, sin tener que modificar el código. Además, incluye múltiples variables parametrizables, lo que nos permite ajustar su comportamiento a las necesidades de cada cliente sin tener que desarrollar una solución nueva. Veamos cómo funciona.

# ============================================================
# AVD AUTOSCALE
# Runbook pensado para ejecutarse cada x min en hora pico
# Objetivo: mantener x VMs encendidas SIN usuario por host pool
# y un MÍNIMO de x VMs encendidas por pool
# ============================================================
$ErrorActionPreference = ‘Stop’
# ============================================================
# CONEXIÓN Y CONTEXTO
# ============================================================
Connect-AzAccount -Identity | Out-Null
Set-AzContext -SubscriptionId $subscriptionId | Out-Null
# ============================================================
# CONFIGURACIÓN
# ============================================================
$BufferObjetivo = x # nº deseado de VMs encendidas sin usuario por pool
$MinEncendidasPorPool = x # nº MÍNIMO de VMs encendidas (con o sin usuario) por pool
$DryRun = $false # Activar en caso de querer hacer simulación
$hostPools = @(
@{ Label = «POOL1»; RG = «ResourceGroup1»; Name = «HostPool1» },
@{ Label = «POOL2»; RG = «ResourceGroup2»; Name = «HostPool2» }
)
# ============================================================
# CACHÉ DE VMs DE LA SUSCRIPCIÓN (para resolver RG/estado dinámicamente)
# ============================================================
Write-Output «Cacheando inventario de VMs de la suscripcion…»
$AllVMs = Get-AzVM -Status
function Resolve-VMInfo {
param([string]$VmShortName)
$VmShortName = ($VmShortName -split ‘\.’)[0]
# Match por nombre corto (case-insensitive)
$vm = $AllVMs | Where-Object { $_.Name -ieq $VmShortName } | Select-Object -First 1
if (-not $vm) { return $null }
# PowerState viene como «VM running», «VM deallocated», etc.
$powerState = ($vm.PowerState -replace ‘^VM\s+’,»).ToLower()
return [pscustomobject]@{
Name = $vm.Name
RG = $vm.ResourceGroupName
PowerState = $powerState
}
}
# ============================================================
# PROCESAMIENTO
# ============================================================
foreach ($pool in $hostPools) {
$sessionHosts = Get-AzWvdSessionHost `
-ResourceGroupName $pool.RG `
-HostPoolName $pool.Name
$MaquinasTotales = $sessionHosts.Count
$MaquinasEncendidas = ($sessionHosts | Where-Object { $_.Status -eq «Available» }).Count
$CandidatasApagar = New-Object System.Collections.Generic.List[object]
$EnDrain = New-Object System.Collections.Generic.List[string]
foreach ($sh in $sessionHosts | Where-Object { $_.Status -eq «Available» }) {
$shortName = ($sh.Name -split «/»)[-1]
$sesiones = Get-AzWvdUserSession `
-ResourceGroupName $pool.RG `
-HostPoolName $pool.Name `
-SessionHostName $shortName `
-ErrorAction SilentlyContinue
$numSesiones = @($sesiones).Count
if ($numSesiones -eq 0) {
if ($sh.AllowNewSession -eq $false) {
# Está libre pero en drain -> no se apaga, se avisa
$EnDrain.Add($shortName) | Out-Null
} else {
$CandidatasApagar.Add([pscustomobject]@{
ShortName = $shortName
}) | Out-Null
}
}
}
$MaquinasEncendidasSinUsuario = $CandidatasApagar.Count
# —————- SALIDA INFORMATIVA —————-
Write-Output «»
Write-Output «===== $($pool.Label) ($($pool.Name)) =====»
Write-Output «MaquinasTotales=$MaquinasTotales»
Write-Output «MaquinasEncendidas=$MaquinasEncendidas»
Write-Output «MaquinasEncendidasSinUsuario=$MaquinasEncendidasSinUsuario»
Write-Output «MaquinasEnDrainSinUsuario=$($EnDrain.Count) (excluidas de apagado)»
if ($EnDrain.Count -gt 0) {
Write-Output » Drain -> $($EnDrain -join ‘, ‘)»
}
Write-Output «Objetivo=$BufferObjetivo MinEncendidas=$MinEncendidasPorPool»
# —————- DECISIÓN —————-
# Nº de VMs a encender para cumplir A LA VEZ el buffer y el mínimo por pool
$faltanBuffer = $BufferObjetivo – $MaquinasEncendidasSinUsuario
$faltanMinimo = $MinEncendidasPorPool – $MaquinasEncendidas
$nEncender = [Math]::Max($faltanBuffer, $faltanMinimo)
if ($nEncender -gt 0) {
Write-Output «Accion=ENCENDER»
Write-Output «Maquinas a encender=$nEncender»
# Session hosts que NO estan Available (candidatos a encender)
$hostsNoAvailable = $sessionHosts | Where-Object { $_.Status -ne «Available» }
# Filtrar solo las que estan deallocated a nivel de VM
$candidatasEncender = @()
foreach ($sh in $hostsNoAvailable) {
$shortName = ($sh.Name -split «/»)[-1]
$vmInfo = Resolve-VMInfo -VmShortName $shortName
if ($vmInfo -and $vmInfo.PowerState -eq ‘deallocated’) {
$candidatasEncender += $vmInfo
}
}
if ($candidatasEncender.Count -eq 0) {
Write-Output » [WARN] No hay VMs ‘deallocated’ disponibles para encender en $($pool.Label).»
} else {
$seleccion = $candidatasEncender | Select-Object -First $nEncender
foreach ($vmInfo in $seleccion) {
if ($DryRun) {
Write-Output » [DRY-RUN] Start-AzVM -ResourceGroupName $($vmInfo.RG) -Name $($vmInfo.Name) -NoWait»
} else {
# -NoWait: lanza la orden y no espera al arranque -> todas casi en paralelo
Start-AzVM -ResourceGroupName $vmInfo.RG -Name $vmInfo.Name -NoWait | Out-Null
Write-Output » [OK] Orden de encendido enviada -> $($vmInfo.Name)»
}
}
if ($seleccion.Count -lt $nEncender) {
$faltan = $nEncender – $seleccion.Count
Write-Output » [WARN] Solo se han podido preparar $($seleccion.Count) de $nEncender. Faltan $faltan (no hay mas VMs deallocated).»
}
}
} elseif ($MaquinasEncendidasSinUsuario -gt $BufferObjetivo) {
$nApagar = $MaquinasEncendidasSinUsuario – $BufferObjetivo
# — TOPE: nunca bajar del minimo de VMs encendidas por pool —
$margenSobreMinimo = $MaquinasEncendidas – $MinEncendidasPorPool
if ($nApagar -gt $margenSobreMinimo) { $nApagar = $margenSobreMinimo }
if ($nApagar -le 0) {
Write-Output «Accion=NINGUNA (se respeta el minimo de $MinEncendidasPorPool encendidas por pool)»
} else {
Write-Output «Accion=APAGAR»
Write-Output «Maquinas a apagar=$nApagar»
$seleccion = $CandidatasApagar | Select-Object -First $nApagar
foreach ($cand in $seleccion) {
$vmInfo = Resolve-VMInfo -VmShortName $cand.ShortName
if (-not $vmInfo) {
Write-Output » [WARN] No se encontro VM ‘$($cand.ShortName)’ en la suscripcion. Skipping.»
continue
}
if ($DryRun) {
Write-Output » [DRY-RUN] Stop-AzVM -ResourceGroupName $($vmInfo.RG) -Name $($vmInfo.Name) -Force -NoWait»
} else {
# -NoWait: lanza la orden y no espera al deallocate -> todas casi en paralelo
Stop-AzVM -ResourceGroupName $vmInfo.RG -Name $vmInfo.Name -Force -NoWait | Out-Null
Write-Output » [OK] Orden de apagado enviada -> $($vmInfo.Name)»
}
}
}
} else {
Write-Output «Accion=NINGUNA (buffer en objetivo y minimo cumplido)»
}
}
Write-Output «»
Write-Output «===== FIN DE EJECUCION (DryRun=$DryRun) =====»
Los resultados obtenidos para confirmar el correcto funcionamiento, los podemos ver en Automation Account -> Runbook -> Job y dentro de aquí en Todos los Logs
Ejemplo de automatización alta de empleados
Pasemos ahora a los procesos. Cada vez que se incorpora una persona a la empresa, alguien de TI tiene que crear su usuario, asignarle la licencia, añadirlo a los grupos de su departamento y darle acceso a las carpetas y aplicaciones que necesita. Por eso hemos automatizado este proceso con un script en PowerShell que se ejecuta desde las cuentas de Azure Automation. A partir de unos pocos datos (nombre, departamento y puesto), el alta se completa sola, siempre de la misma forma y dejando constancia de cada acción. Veamos cómo funciona.
# ============================================================
# ALTA MASIVA DE USUARIOS DESDE CSV
# ============================================================
$ErrorActionPreference = ‘Stop’
# ============================================================
# CONFIGURACIÓN
# ============================================================
$CsvPath = «.\Usuarios.csv»
$DryRun = $true
Connect-MgGraph -Scopes «User.ReadWrite.All»
# ============================================================
# CARGAR CSV
# ============================================================
$Usuarios = Import-Csv $CsvPath
$Resultados = @()
# ============================================================
# VALIDACIONES
# ============================================================
$Duplicados = $Usuarios |
Group-Object UserPrincipalName |
Where-Object Count -gt 1 |
Select-Object -ExpandProperty Name
foreach ($Usuario in $Usuarios) {
$UPN = $Usuario.UserPrincipalName
if ([string\]::IsNullOrWhiteSpace($UPN)) {
$Resultados += [pscustomobject]@{
Usuario = «SIN_UPN»
Estado = «ERROR»
Detalle = «UPN vacío»
}
continue
}
if ($UPN -in $Duplicados) {
$Resultados += [pscustomobject]@{
Usuario = $UPN
Estado = «ERROR»
Detalle = «Duplicado en CSV»
}
continue
}
$Existe = Get-MgUser -Filter «userPrincipalName eq ‘$UPN'» -ErrorAction SilentlyContinue
if ($Existe) {
$Resultados += [pscustomobject]@{
Usuario = $UPN
Estado = «ERROR»
Detalle = «Ya existe»
}
continue
}
if ($DryRun) {
$Resultados += [pscustomobject]@{
Usuario = $UPN
Estado = «DRYRUN»
Detalle = «Usuario válido»
}
continue
}
try {
New-MgUser `
-DisplayName $Usuario.DisplayName `
-UserPrincipalName $UPN `
-MailNickname $Usuario.MailNickname `
-AccountEnabled `
-UsageLocation $Usuario.UsageLocation `
-PasswordProfile @{
Password = $Usuario.Password
ForceChangePasswordNextSignIn = $true
} | Out-Null
$Resultados += [pscustomobject]@{
Usuario = $UPN
Estado = «CREADO»
Detalle = «OK»
}
}
catch {
$Resultados += [pscustomobject]@{
Usuario = $UPN
Estado = «ERROR»
Detalle = $_.Exception.Message
}
}
}
# ============================================================
# RESUMEN FINAL
# ============================================================
Write-Output «»
Write-Output «===== RESUMEN =====»
$Resultados | Format-Table -AutoSize
Write-Output «»
Write-Output «Creados: $(@($Resultados | Where-Object Estado -eq ‘CREADO’).Count)»
Write-Output «Errores: $(@($Resultados | Where-Object Estado -eq ‘ERROR’).Count)»
Write-Output «DryRun : $(@($Resultados | Where-Object Estado -eq ‘DRYRUN’).Count)»
Aprende más asistiendo a nuestro webinar «Automatiza tu TI desde Azure: casos reales del día a día»
A lo largo de este post te hemos explicado cómo automatizar tu TI desde Azure puede ayudarte a reducir tanto los costes como las tareas que se realizan de manera manual en tu negocio. Y, también, te hemos presentado unos breves ejemplos prácticos relacionados con la implementación de automatizaciones. Si quieres aprender más acerca de esta tecnología y comprobar cómo podrias aprovecharla en tu empresa, solo tienes que apuntarte al webinar gratuito «Automatiza tu TI desde Azure: casos reales del día a día» que estamos preparando para el próximo jueves 22 de octubre.
¿Quieres aplicar esta tecnología o acceder a una revisión de tu infraestructura TI? Contacta con nosotros
En este post te hemos comentado cómo automatizar tu TI desde Azure puede ayudarte a reducir costes y ahorrar tiempo en tu negocio. Desde AWERTY podemos ayudarte a implementar esta tecnología en tu empresa. O, si lo prefieres, también puedes delegar su gestión en nuestras manos. Si no estás del todo seguro o tienes alguna duda o pregunta que desees plantearnos, ponte en contacto con nosotros. Estaremos encantados de darte todas las respuestas que necesites. Sin compromiso. Además, te ofrecemos la posibilidad de contar con una revisión gratuita de tres horas de la infraestructura y los procesos de TI de tu negocio. Una vez llevado a cabo, recibirás un informe en el que te detallaremos las posibles mejoras que se pueden introducir, priorizadas, así como una estimación del coste que supondría contar con la correspondiente optimización ya desplegada en la nube. Las plazas son muy limitadas.
Ante todo, queremos convertirnos en tu partner tecnológico de referencia. Nuestro objetivo es ayudarte y guiarte, para que puedas aprovechar todo lo que la IA y la transformación digital pueden hacer para multiplicar la productividad de tu negocio y modernizar su gestión. La satisfacción de nuestros más de 2.500 clientes y nuestros 30 años de experiencia en el sector de las Tecnologías de la Información son nuestras mejores cartas de presentación.
