Backup & Restore configuración ESXi

En este post, vamos a ver cómo realizar de manera automatizada Backup de la configuración de los ESXi de nuestra infraestructura. También vamos a ver como realizar el restore de la configuración mediante PowerCLI.

Seguramente muchos de vosotros, os hayáis encontrado con que la instalación del ESXi está sobre un USB, SD Card o incluso un disco sin protección. Y en caso de fallo del dispositivo, ¿que hacemos? ¿Volvemos a instalar y configurar de cero? Bueno, hay opciones como Autodeploy y Host Profile para configurar en semejanza a los demás.

Bien, yo me he encontrado en esta situación muchas veces, y es muy costoso en tiempo. Aún más con la posibilidad que dan los servidores Blades, para en caso de fallo en cualquiera de los Blades, poder mover el perfil a otro Blade vacío. En caso de tener disco local para arrancar, necesitaríamos instalar de cero, y como he dicho antes, apoyarnos en Host Profiles para configurar.

Ante este problema, decidí implementar un script para automatizar la realización de backups de la configuración de los ESXi.


##################################################################
## Realizar backup ESXi
## ------------------------------------------------------------###
## V. 1.0 Mario Gómez - CloudVM
## ------------------------------------------------------------###
## Syntaxis: backup_esxi.ps1 -VCENTER vCenterName
## ------------------------------------------------------------###
##################################################################

param(
[Parameter(Mandatory=$True)]
[string]$VCENTER
)

# Repositorio Backups ESXi
$filepath = "E:\CloudVM\BackupESXi"

# Declaración de Variables
$fecha = Get-Date -Format ddMMMMMMMMMMMMMyy
$user = "cloudvm@cloudvm.es"
$pass = "cloudvm@2020"

# Conectamos a vCenter Server

Connect-VIServer -Server $VCENTER -User $user -Password $pass -WarningAction Ignore | Out-Null

# Por cada Cluster, iremos recorriendo cada Host para realizar el backup de la configuración
$cluster_list = Get-Cluster

foreach ($cluster in $cluster_list)
{
       $cluster_name = $cluster.Name
       Write-Host "Realizando Backup de la configuración de los ESXi del Cluster [$cluster_name]" -ForegroundColor Yellow
       # Creamos una carpeta por cada Cluster sino existe ya
       if ((Get-ChildItem -Path $filepath).Name -ne $cluster_name){mkdir $filepath\$cluster_name | Out-Null}
       $list_esxi = $cluster | Get-VMHost
         foreach ($esxi in $list_esxi)
         {
            $esxi_name = $esxi.Name
            # Configurando Carpeta y Fichero
            # Creamos una carpeta por ESXi, sino existe.
            if ((Get-ChildItem -Path $filepath\$cluster_name).Name -notcontains "$esxi_name"){mkdir $filepath\$cluster_name\$esxi_name | Out-Null}
            # Luego crearemos una carpeta dentro con las fechas de los backups.
            $folder_esxi = $filepath + "\" + $cluster_name + "\" + $esxi_name + "\" + $esxi_name + "_" + $fecha
            mkdir $folder_esxi | Out-Null
            Write-Host "Realizando Backup del ESXi [$esxi_name]" -NoNewline
            # Realizamos el Backup
            Get-VMHostFirmware -VMHost $esxi_name -BackupConfiguration -DestinationPath $folder_esxi 
            Write-Host " [OK] Backup realizado para [$esxi_name] en Fecha : [$fecha]" -ForegroundColor Green
         }
}

Disconnect-VIServer -Server $VCENTER -Confirm:$false

El Script realiza la copia de la configuración de los ESXi en una ubicación que hayamos marcado, manteniendo una estructura de carpetas. Para ello por cada Cluster, creará una carpeta y dentro de cada Cluster, creara una carpeta por cada ESXi, y posteriormente dentro de cada ESXi, creará una carpeta para cada día que se ejecute.

Como podemos ver en la imagen, obtenemos por cada Backup un único fichero “tgz” con la config de cada ESXi.

2020-02-17 12_33_55-VM VMware Scripts

Ahora bien, ya tenemos nuestros backups y la pregunta que nos hacemos todos. ¿Funcionará el restore? ¿En qué estado nos dejará el ESXi? ¿Qué estado inicial espera el script antes del restore? Pues bien, yo he probado el script y funciona según lo esperado. Respeta vSAN, vDSwitch, NSX, etc. Es importante, que tras restaurar el ESXi tenga el mismo UUID y el mismo ID de Objeto en vCenter.

¿Qué estado inicial espera el script antes del restore?

  • Es importante que el ESXi, no sea desinventariado de vCenter, ya que como he dicho antes, debemos mantener el UUID e ID de Objeto de vCenter.
  • El ESXi debe ser reinstalado con la misma versión de vSphere ESXi y mismo Build.
  • El ESXi habrá sido reinstalado el SO, se habrá configurado simplemente la IP de Management.
  • El estado que espera es que simplemente esté conectado a vCenter (evidentemente, el certificado habrá cambiado cuando se ha reinstalado, por lo que tendremos que reconectar el ESXi). El propio script, sino esta en mantenimiento, lo pondrá.

¿En qué estado nos dejará el ESXi? Si tenemos Distributed Switch nos podemos encontrar alarmas, debido a un problema de sincronización. Si tenemos NSX, tendremos que redesplegar las VIBs de VXLAN. Si hemos instalado VIBs diferentes a las que alojaba la imagen instalada de ESXi, tendremos que instalar las VIBs. En cuando a vSAN, simplemente realizar un retest del Health Monitor de vSAN.

El script que he implementado es interactivo, irá preguntándonos información y confirmaciones según vayamos seleccionando el que queremos restaurar y  que backup queremos que se restaure.

El script es el siguiente:


#################################################################
## Realizar restore ESXi config
## -----------------------------------------------------------###
## V. 1.0 Mario Gómez - CloudVM
## -----------------------------------------------------------###
## Syntaxis: restore_backup_esxi.ps1 -VCENTER vCenterName
## -----------------------------------------------------------###
#################################################################
param(
[Parameter(Mandatory=$True)]
[string]$VCENTER
)

Connect -SERVER $VCENTER -TIPO VCENTER

# Inicializamos Tablas e indices

$cluster_table = @()
$esxi_table = @()
$backup_table = @()
$cluster_index = 0
$esxi_index = 0
$backup_index = 0

# Filepath Repositorio de Backups

$filepath = "E:\CloudVM\BackupESXi"

# Declaración de variables
$user = "cloudvm@cloudvm.es"
$pass = "cloudvm@2020"

# Recogemos el nombre del Cluster en el que está el ESXi que queremos restaurar

$cluster = (Get-Cluster).Name
$cluster | ForEach-Object {$hash = @{ Cluster = $_ ; Option = $esxi_index};$obj = New-Object PSObject -Property $hash; $cluster_table += $obj ; $cluster_index++}

# Imprimimos la lista de Cluster para el vCenter introducido y seleccionaremos el Cluster sobre el cuál se ubica el ESXi
$cluster_table | Out-Host
$cluster_index = Read-Host -Prompt "Elige el Cluster del ESXi a restaurar [OPCION]"

$filepath_cluster = $filepath + "\" + $cluster[$cluster_index]

# Mostramos los ESXi para seleccionar cual ESXi quieres restaurar.

$list_esxi_folder = (Get-ChildItem -Path $filepath_cluster).Name
$list_esxi_folder | ForEach-Object {$hash = @{ ESXi = $_ ; Option = $esxi_index};$obj = New-Object PSObject -Property $hash; $esxi_table += $obj ; $esxi_index++}

# Imprimimos la lista de ESXi para el vCenter introducido y seleccionar el ESXi sobre el cuál vamos a restaurar.
Write-Host "*** Lista ESXi de la Instancia de vCenter [$VCENTER] ***"
$esxi_table | Out-Host
$esxi_index = Read-Host -Prompt "Elige el ESXi a restaurar [OPCION]"

# Obtenemos el nombre del ESXi a restaurar
$esxi_to_restore = $list_esxi_folder[$esxi_index]

$filepath_esxi = $filepath_cluster + "\" + $esxi_to_restore

# Obtenemos un listado de los Backup que tiene el ESXi seleccionado

$list_backups = (Get-ChildItem -Path $filepath_esxi).Name
$list_backups | ForEach-Object {$hash = @{ Backup = $_ ; Option = $backup_index};$obj = New-Object PSObject -Property $hash; $backup_table += $obj ; $backup_index++}

# Imprimimos la lista de ESXi para el vCenter introducido y seleccionar el ESXi sobre el cuál vamos a restaurar.
Write-Host "*** Lista Backups realizados para el ESXi [$esxi_to_restore] ***"
$backup_table | Out-Host
$backup_index = Read-Host -Prompt "Elige el Backup a restaurar [OPCION]"

# Obtenemos el Backup del ESXi a restaurar
$backup_to_restore = $list_backups[$backup_index]
$filepath_backup_to_restore = $filepath_esxi + "\" + $backup_to_restore

$backup_file = (Get-ChildItem -Path $filepath_backup_to_restore).Name

# Construimos la ruta absoluta del Backup a restaurar

$filerestore = $filepath_backup_to_restore + "\" + $backup_file

######################################################################
#### COMIENZO RESTORE ########
######################################################################

Write-Host "*********************************************" -ForegroundColor White
Write-Host "CONSIDERACIONES PREVIAS A RESTAURAR EL BACKUP" -ForegroundColor Yellow
Write-Host "*********************************************" -ForegroundColor White

Write-Host " "
Write-Host "1. El ESXi debe de estar reinstalado sin haber realizado el Disconnect en vCenter [EL OBJETO HOST DEBE EXISTIR]" -ForegroundColor Green
Write-Host "2. El ESXi debe tener la misma versión de vSphere ESXi que el ESXi a restaurar [MISMA VERSION Y BUILD]" -ForegroundColor Green
Write-Host "3. El ESXi sobre el que se va a restaurar el Backup únicamente tiene que tener configurada la IP de Management" -ForegroundColor Green
Write-Host "4. El ESXi sobre el que se va a restaurar deberá estar conectado a vCenter [NECESARIO RECONECTAR, DEBIDO A ERROR DE CERTIFICADO]" -ForegroundColor Green
Write-Host " "

$confirmation = Read-Host -Prompt "¿Quieres continuar con el Restore? [S, N]"

if ($confirmation -ne "S")
{
    Write-Host "Salimos del Script de Restore"
    exit 1
}
# PROCEDEMOS A REALIZAR EL RESTORE
else
{
    Write-Host " "
    Write-Host "----------------------------------------------------" -ForegroundColor Magenta
    Write-Host "C O M I E N Z O S C R I P T R E S T O R E E S X i" -ForegroundColor Magenta
    Write-Host "----------------------------------------------------" -ForegroundColor Magenta
    Write-Host " "
    Connect-VIServer -Server $VCENTER -User $user -Password $pass -WarningAction Ignore | Out-Null

    $esxi = Get-VMHost -Name $esxi_to_restore
    # Comprobamos si el ESXi está en Mantenimiento
    if ($esxi.ConnectionState -ne "Maintenance")
    {
        Write-Host "Poniendo el ESXi [$esxi_to_restore] en Mantenimiento..." -NoNewline
        Set-VMHost -VMHost $esxi -State Maintenance -Confirm:$false | Out-Null
        Write-Host " [OK]" -ForegroundColor Green
    }
    Write-Host "ESXi [$esxi_to_restore] en Mantenimiento" -ForegroundColor Cyan
    Write-Host "Se va a restaurar la configuración para el ESXi [$esxi_to_restore] con el backup [$filerestore] " -ForegroundColor Yellow
    $confirmation_to_restore = Read-Host -Prompt "Estas seguro de que quieres restaurar [S/N]"
    if ($confirmation -eq "S")
    {
        $pass = Read-Host -Prompt "Introduce credencial de Root para el ESXi "
        Set-VMHostFirmware -VMHost $esxi_to_restore -Restore -SourcePath $filerestore -HostUser root -HostPassword $pass -Force
    }
    else
    {
         Write-Host "Abortado proceso de restore del ESXi [$esxi_to_restore]" -ForegroundColor Red
         exit 1
    }
}

Write-Host "ESXi [$esxi_to_restore] Restaurado" -ForegroundColor Green

Disconnect-VIServer -Server $VCENTER -Confirm:$false

Write-Host "S I G U I E N T E S P A S O S T R A S R E S T O R E" -ForegroundColor Yellow
Write-Host " "
Write-Host "1. EL ESXi SE REINICIA TRAS APLICAR EL RESTORE" -ForegroundColor Yellow
Write-Host "2. RECONECTAR ESXI EN vCENTER PARA RENOVAR EL CERTIFICADO TRAS RESTORE" -ForegroundColor Yellow
Write-Host "3. SI TIENES NSX, REALIZAR UN REDESPLIEGUE DE LAS VIBS DE VXLAN" -ForegroundColor Yellow
Write-Host "4. INSTALAR LAS VIBs ADICIONALES" -ForegroundColor Yellow
Write-Host "5. SI TIENES vSAN, REALIZAR UN RETEST EN EL MONITOR DE HEALTH DE vSAN" -ForegroundColor Yellow

Ya que estoy, os dejo un script para realizar un purgado de Backup, para mantener una retención X:


###################################################################
## Realizar purgado de los Backups de ESXi Retención en X días
## -------------------------------------------------------------###
## V. 1.0 Mario Gómez - CloudVM
## -------------------------------------------------------------###
## Syntaxis: PurgeBackups.ps1 
## -------------------------------------------------------------###
###################################################################


$root_backup = "E:\CloudVM\BackupESXi"
$clusters_folders = @()
$body = @()

# Determinar ubicación Script para ubicar el fichero de Log
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path

######## COMIENZO SCRIPT

$body += "################################################################################"
$body += "I N F O R M A C I Ó N B A C K U P S E L I M I N A D O S E S X i H C I"
$body += "################################################################################"
$body += " "
$body += " "

$clusters_folders = Get-ChildItem -Path $root_backup

$clusters_folders | ForEach-Object{
 $cluster_folder = $_.Name
 $body += "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
 $body += "Eliminados los siguientes ficheros para el Cluster [ " + $cluster_folder + " ]"
 $body += "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
 $body += " "
 $body += " "

 $root_backup_Cluster = $root_backup + "\" + $_.Name
 $list_esxi_folders = Get-ChildItem -Path $root_backup_Cluster
 $list_esxi_folders | ForEach-Object {
 $backup_esxi_folder = $root_backup_Cluster + "\" + $_.Name
 $esxi_folder = $_.Name
 Write-Host "Purgando Backups con retención posterior a X días en la carpeta [$esxi_folder]... "
 $body += "Backups con retención posterior a X días en la carpeta [ " + $esxi_folder + "] : "
 $body += " "
 # Modificar .AddDays(-X), donde X son los backup que se quieren retener. 
 $remove_items = Get-ChildItem -Path $backup_esxi_folder -Recurse | Where-Object CreationTime -LT (Get-Date).AddDays(-X)
 $body += "Eliminados las siguientes Carpetas/Ficheros : "
 $remove_items | ForEach-Object {$body += $_.Name}
 Get-ChildItem -Path $backup_esxi_folder -Recurse | Where-Object CreationTime -LT (Get-Date).AddDays(-X) | Remove-Item -Force -Recurse -Confirm:$false
 }
 $body += " "
 $body += " "
}

$fecha = Get-Date -Format ddMMMMMMMMMMyyyy
$attach_file_name = $ScriptDir + "\attach_files\Informe_purgado_backups_" + $fecha + ".txt"

$body | Out-File $attach_file_name

# Envíamos un correo con los backups purgados
Send-MailMessage -Attachments $attach_file_name -Body "Envio informe de Backups eliminados por Retencion mayor a X dias" -From smtp@cloudvm.es -to cloudvm@cloudvm.es -SmtpServer email.cloudvm.es -Subject "Informe Purgado de Backups ESXi"

Espero que os sea de utilidad y os haya gustado. Muchas gracias por compartir 😉

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *