Introducción
Las APIs de VMWare para hacer copias de seguridad se apoyan en un mecanismo que registra los bloques de disco cambiados (Changed Block Tracking o CBT). Se han detectado en varias ocasiones problemas con este mecanismo en los que si no funciona bien puede hacer que nuestras copias de seguridad no sean válidas.
Aunque estos problemas se detectan y solucionan rápidamente, puede ser interesante tomar ciertas medidas para prevenir que uno de estos fallos nos afecte. Por ejemplo, uno de los casos detectados de fallo en el funcionamiento del CBT es el siguiente:
Este fallo puede ocurrir cuando se expande un disco virtual por encima de cierto límite. Esto puede afectar a que no se reporten correctamente los bloques de discos cambiados al sistema de copias de seguridad y nuestra copia de seguridad no sea consistente y nos falten datos.
Medidas de prevención
En este caso concreto, el fallo se puede producir cuando se amplia el volumen cumpliendo ciertas condiciones. Una opción para prevenir este problema es regenerar el CBT siempre que se amplíen un disco de nuestra máquina virtual. El procedimiento para regenerar el CBT es el siguiente:
- Desactivar el CBT
- Hacer un snapshot
- Borrar el snapshot
- Hacer una nueva copia de seguridad
Estas tareas se pueden hacer manualmente o programadas con un script similar al siguiente:
Obtener las máquinas con CBT habilitado:
$vms=get-vm | ?{$_.ExtensionData.Config.ChangeTrackingEnabled -eq $true}
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.ChangeTrackingEnabled = $false
foreach($vm in $vms){
$vm.ExtensionData.ReconfigVM($spec)
$snap=$vm | New-Snapshot -Name 'Disable CBT'
$snap | Remove-Snapshot -confirm:$false}
get-vm | ?{$_.ExtensionData.Config.ChangeTrackingEnabled -eq $true}
Hay que tener en cuenta que si se tiene la versión 7.7.2 de Netbackup puede ser de aplicación la siguiente nota técnica:
After upgrading to NetBackup 7.7.2, VMware CBT calls are not honored causing BLIB
Por otro lado, se podrían automatizar estas tareas con scripts más complejos como los que figuran a modo de ejemplo al final del artículo, que se podría programar antes de la copia de seguridad completa, y lo que hace es lo siguiente:
- Recorrer todas las máquinas de nuestro virtual center
- Suma el tamaño de sus discos. Si esta suma no es igual a la de la última ejecución, para esa máquina se aplica el procedimiento de regeneración del fichero de CBT
- Para las máquinas que no han cambiado de tamaño sus discos aplica el procedimiento a un máximo de X máquinas (en este ejemplo 5) para las cuales no se haya cambiado en Y días (60 en este caso). De esta forma, periódicamente se va regenerando el fichero de CBT para todas las máquinas de nuestra infraestructura y poco a poco para no suponer gran carga extra en nuestra infraestructura de copias de seguridad y almacenamiento.
Además de estos consejos, es imprescindible las pruebas de restauración periódicas para poder detectar cualquier posible problema de forma preventiva, así como aplicar las buenas prácticas sobre copias de seguridad en VMWare y creación de planificaciones con la opción de Force Rescan habilitado de forma periódica.
Referencias
Changed Block Tracking (CBT) on virtual machines (1020128)
Enabling or disabling Changed Block Tracking (CBT) on virtual machines (1031873)
Scripts de ejemplo
Mi más sincero agradecimiento a Juan Benjumea por crear y proporcionarme los siguientes scripts como muestra. Para que funcionen correctamente es necesario crear los siguientes campos personalizados en el virtual center:
- CBT_RESET: Almacena la fecha de la última vez que se ha regenerado el CBT
- VM_SIZE_DISK_GB: Contiene la suma de GB de todos los discos virtuales
Hay dos scripts, un primer script que rellena el tamaño de los discos (campo VM_SIZE_DISK_FB) y toma como parámetro el nombre del Virtual Center. Sólo hay que ejecutarlo la primera vez:
[void](Get-PSSnapin VMWare.VimAutomation.Core -ErrorVariable getVmwareSnapinErr 2> $null)
if ($getVmwareSnapinErr.Count -gt 0) { Add-PSSnapin VMware.VimAutomation.Core }
Write-Host $args[0]
Connect-VIServer -server $args[0]
# Inicializamos variables
$VMs = Get-VM *
$Data = @()
foreach ($VM in $VMs){
$VMDKs = $VM | get-HardDisk
$CapacityGBTOTAL = 0
$into = New-Object PSObject
foreach ($VMDK in $VMDKs) {
if ($VMDK -ne $null){
$CapacityGB = $VMDK.CapacityKB/1024/1024
$CapacityGB = [int]$CapacityGB
$CapacityGBTOTAL = ($CapacityGBTOTAL + $CapacityGB)
}
}
get-vm $VM | Set-Annotation -CustomAttribute VM_SIZE_DISK_GB -value $CapacityGBTOTAL
Add-Member -InputObject $into -MemberType NoteProperty -Name VMname $VM.Name
Add-Member -InputObject $into -MemberType NoteProperty -Name CapacityGB $CapacityGBTOTAL
$Data += $into
$Data | Sort-Object VMname,VMDK | Export-Csv -Path C:\temp\VM-VMDKs-SIZE.csv -NoTypeInformation
}
Disconnect-VIServer -Confirm:$False
Y un segundo script que se recorre todas las máquinas virtuales, regenera el CBT en las máquinas en las que se ha ampliado el disco y además 5 máquinas virtuales más en cada ejecución siempre que no haga 60 días que ya se ha cambiado (estos números habrá que cambiarlos en cada infraestructura dependiendo del número de máquinas virtuales). Hay que pasar como parámetro el nombre del Virtual Center:
[void](Get-PSSnapin VMWare.VimAutomation.Core -ErrorVariable getVmwareSnapinErr 2> $null)
if ($getVmwareSnapinErr.Count -gt 0) { Add-PSSnapin VMware.VimAutomation.Core }
Write-Host $args[0]
Connect-VIServer -server $args[0]
# Inicializamos variables
$VMs = Get-VM | ?{$_.ExtensionData.Config.ChangeTrackingEnabled -eq $true}
$Data = @()
$VMPROC = [int]$VMPROC
$VMPROC = 0
$spec = New-Object VMware.Vim.VirtualMachineConfigSpec
$spec.ChangeTrackingEnabled = $false
$date = Get-Date
$datetxt = Get-Date $date -Format dd/MM/yy
foreach ($VM in $VMs){
$reset = «NO»
$VMDKs = $VM | get-HardDisk
$CapacityGBTOTAL = 0
$into = New-Object PSObject
#Sumamos el valor de los discos de cada VM
foreach ($VMDK in $VMDKs) {
if ($VMDK -ne $null){
$CapacityGB = $VMDK.CapacityKB/1024/1024
$CapacityGB = [int]$CapacityGB
$CapacityGBTOTAL = ($CapacityGBTOTAL + $CapacityGB)
}
}
Add-Member -InputObject $into -MemberType NoteProperty -Name VMname $VM.Name
Add-Member -InputObject $into -MemberType NoteProperty -Name CapacityGB $CapacityGBTOTAL
#Compara el tamaño actual de los discos con el del valor ya existente en el campo VM_SIZE_DISK_GB y si es diferente ejecuta el disable CBT
$VM_SIZE_DISK_GB_OLD = (Get-VM $VM).CustomFields.Item{VM_SIZE_DISK_GB}
$fechatxt = (Get-VM $VM).CustomFields.Item{CBT_RESET}
$fechacsv = $fechatxt
if (($VM_SIZE_DISK_GB_OLD -ne $CapacityGBTOTAL)-or ($fechatxt -eq «»)) {
$vm.ExtensionData.ReconfigVM($spec)
$snap=$vm | New-Snapshot -Name ‘Disable CBT’
$snap | Remove-Snapshot -confirm:$false
get-vm $VM | Set-Annotation -CustomAttribute VM_SIZE_DISK_GB -value $CapacityGBTOTAL
get-vm $VM | Set-Annotation -CustomAttribute CBT_RESET -value $datetxt
$VMPROC = $VMPROC + 1
$reset = «YES»
$fechacsv = $datetxt
}
#Compara la fecha actual con el del valor del campo CBT_RESET
# y si la diferencia es mayor a 60 dias anteriores a la fecha actual ejecuta el disable CBT si no se ha realizado ya en 5 maquinas
if ($VMPROC -lt «5») {
if ($VM_SIZE_DISK_GB_OLD -eq $CapacityGBTOTAL) {
$fechatxt = (Get-VM $VM).CustomFields.Item{CBT_RESET}
$fecha = Get-Date $fechatxt
if ($fecha.adddays(60) -le $date) {
$vm.ExtensionData.ReconfigVM($spec)
$snap=$vm | New-Snapshot -Name ‘Disable CBT’
$snap | Remove-Snapshot -confirm:$false
get-vm $VM | Set-Annotation -CustomAttribute CBT_RESET -value $datetxt
$VMPROC = $VMPROC + 1
$reset = «YES»
$fechacsv = $datetxt
}
}
}
Add-Member -InputObject $into -MemberType NoteProperty -Name Reset $reset
Add-Member -InputObject $into -MemberType NoteProperty -Name Date $fechacsv
$Data += $into
$Data | Sort-Object VMname,VMDK,Reset,Date | Export-Csv -Path C:\temp\VM-VMDKs.csv -NoTypeInformation
}
Disconnect-VIServer -Confirm:$False