Ir al contenido
Copias de Seguridad en servicios PaaS de Azure

Copias de Seguridad en servicios PaaS de Azure

·2631 palabras·13 mins
Artículo Azure PaaS Backup
Jorge Perona Puro
Autor
Jorge Perona Puro
Siempre aprendiendo, como un becario
Tabla de contenido

Copias de Seguridad en servicios PaaS de Azure

Uno de los puntos más importantes y complejos de cubrir cuando desarrollamos un proyecto es afrontar la “resiliencia y continuidad del negocio”, es decir, como nos recuperamos en caso de ocurrir un desastre. Es aquí donde nace el “Plan de recuperación de desastres” o “BCDR”; BC de Business Continuity y DR de Disaster Recovery Plan. Dentro del “Disaster Recovery Plan” tenemos que afrontar las copias de seguridad de nuestra infraestructura.

En proyectos On Premise teníamos la posibilidad de realizar copias de seguridad (backups) de nuestros sistemas en Cintas, unidades externas; incluso los mas viejos del lugar recordaran las unidades ZIP; y con la llegada de los entornos virtualizados teníamos la opción de realizar snapshots de nuestras máquinas virtuales. En estos entornos On Premise la “Infraestructura física” había que replicarla, es decir, tener duplicados los sistemas e incluso nuestro Centro de Datos para realizar complejas “conmutaciones” en caso de desastre.

Con la llegada de los entornos Cloud públicos la disponibilidad y mantenimiento de los centros de datos y de la infraestructura física la delegamos entre otras cosas al proveedor y si bien es bastante improbable la indisponibilidad de estos Centros de Datos, no estamos totalmente a salvo. En este punto llegan conceptos como Región de Respaldo, Zonas de Disponibilidad o Grupos de Disponibilidad; por mencionar algunos de ellos.

Para sistemas críticos 24x7 es necesario desplegar nuestros sistemas replicados en dos regiones y es aquí donde entra la magia de los arquitectos, ya que no son infraestructuras triviales

Y como no hacer referencia a los Backups, en el caso de Azure, disponemos de varios servicios destinados a las copias de seguridad del dato o de nuestras máquinas virtuales. Mediante Backup Center podemos realizar copias de seguridad de Máquinas Virtuales, Discos, SQL Servers (en VM) y almacenamiento como puede ser Azure Blob o Azure Files de nuestras storage Account o incluso realizar una restauración de nuestras Máquinas Virtuales en una región secundaria mediante el uso de Azure Recovery Vault. Los servicios destinados a bases de datos cuentan con copias de seguridad automáticas pudiendo ser personalizadas en caso de necesitar guardar nuestros datos por un periodo de tiempo muy extenso (LTS).

Se puede dar el caso de una una caída de una región y si nuestros backups están en esa región, los backups no estarán disponibles. De aquí la importancia de Backup Multi-Region.

¿Y qué ocurre con servicios PaaS que por su naturaleza son muy cambiantes como pueden ser Azure Firewall o Azure Application Gateway; por poner algunos ejemplos; y para los que no existen servicios nativos de backup?

En mi opinión, la solución más eficiente es la utilización de filosofía DevOps e Infraestructura como código (IaC) ya que nos permite desplegar toda nuestra infraestructura de una forma rápida y eficiente en cualquier región de Azure de forma idéntica a como la teníamos desplegada de forma rápida y con poco esfuerzo.

La filosofía DevOps es un término muy bonito, pero ¿y si mi infraestructura lleva meses desplegada y operada de forma manual sin utilizar IaC?

Imagínate la cantidad de modificaciones que se realizan en un Azure Firewall al cabo de un año, imagínate además (en modo pesadilla) que al insertar una nueva regla se queda a medio desplegar y es necesario eliminarlo y redesplegarlo (… y para colmo si aplicamos las leyes de Murphy, fallara el día antes de irte de vacaciones o de la salida a bolsa de tu compañía).

Si lo hemos desplegado con IaC, recrearlo sería una tarea sencilla, de unos pocos minutos, pero si lo hemos hecho de forma manual, redesplegarlo es una tarea ardua, de días o semanas y esto en el más optimista de los casos y eso contando que tengamos registros de cambios actualizados.

Aquí entra en juego Azure Resource Manager

Azure Resource Manager es el servicio de implementación y administración de Azure que nos permite crear, actualizar y eliminar recursos en Azure. Todas las implementaciones se quedan guardadas en formato JSON, como si fuera una plantilla ARM.

Gracias a Azure Resource Manager podemos acceder a la configuración de todos nuestros elementos en formato JSON desde varias herramientas, dos herramientas nativas de Azure son Azure Powershell y Azure Resource Explorer

Azure Powershell son un conjunto de comandos (cmdlets) para administrar Azure desde Powershell:

targets

El comando Get-Azresource -ResourceId nos permite recuperar la información

Azure Resource Explorer es una herramienta web que contiene toda la información de nuestros recursos de Azure tal y como están desplegados y nos permite incluso modificarlos para solventar algún posible problema.

targets

Y llegados a este punto, ¿Por qué no exportar esta información y utilizarla para hacer redesplegar nuestra infraestructura? ¿Y si automatizamos estas exportaciones?

Exportación de servicios PaaS de Azure
#

Para realizar esta demo he creado un Azure Firewall con su correspondiente política. La demo tendrá tres pasos:

  • Exportación de la configuración del Firewall y de la política de firewall.
  • Eliminación de ambos
  • Recreación

Para la exportación de un recurso de Azure utilizaremos el comando Export-AzResourceGroup:

El siguiente script, recupera un recurso de Azure con el comando Get-AzResource y lo guarda en una variable que posteriormente utilizaremos con Export-AzResourceGroup que generara un fichero JSON con la configuración:

1PS> $exportFirewallPolicy = Get-AzResource -ResourceId /subscriptions/xxxxxxxx-aaaa-yyyy-zzzz-123456789123/resourceGroups/MyRG/providers/Microsoft.Network/firewallPolicies/central-firewall-policy-wus
2PS> Export-AzResourceGroup -ResourceGroupName $exportFirewallPolicy.ResourceGroupName -Resource $exportFirewallPolicy.ResourceId -Path c:\\temp\\firewall-policy.json -SkipAllParameterization

El JSON generado tendrá el siguiente formato:

targets

Importación de servicios PaaS de Azure
#

Para hacer el restore tenemos dos opciones:

  • Desde el Portal: Deploy a Custom Template
  • Azure Powershell

Para esta demo utilizare Deploy a Custom Template para hacer el restore de la política de firewall y Azure Powershell para restaurar el Firewall y así vemos los dos ejemplos.

Pero, antes de nada, y para nuestra prueba procederé a eliminar el Azure Firewall y el Azure Firewall Policy sobre los que hicimos backup en el paso anterior

targets

Una vez eliminados, podemos comenzar con el restore: En el portal de Azure buscaremos Deploy a Custom Template

targets

Seleccionamos la opción Build your own template in the editor

targets

Se nos abre un editor donde podemos cargar la templeate desde nuestro equipo o simplemente copiar y pegar desde otro editor y salvamos:

targets

Una vez salvemos solo nos quedara indicar la subscripción, Resource Group y la región donde queremos desplegarlo y pulsar sobre Review and Create para que comience el despliegue:

targets

Una vez desplegada la política, podemos desplegar el Firewall. Para ello abrimos desde una consola powershell conectada a nuestra subscripción ejecutamos el siguiente comando:

1New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile C:\\temp\\firewall-export.json

Donde el ResourceGroupName es una variable con el nombre del ResourceGroup de destino y TemplateFile es la ruta del fichero JSON exportado anteriormente.

targets

Bueno, ya sabemos como hacer un backup y un restore de nuestros elementos PaaS. El procedimiento de backup es el mismo para todos los elementos PaaS, solo debemos conocer su ID.

El restore es un procedimiento bastante sencillo, por lo general en caso de tener que recrear un elemento en la misma infraestructura solo hay que utilizar uno de los procedimientos anteriores, pero en caso de tener que recrearlo en una infraestructura distinta solo habría que adaptar los ID de elementos dependientes.

Vamos a suponer, por ejemplo, que lo queremos desplegar en una nueva VNET, tendríamos que buscar en el JSON el ID de la subnet anterior y cambiarla por la nueva VNET.

En el caso del firewall, las dependencias son tres: La IP pública, la Subnet donde se despliega y la política. Solo tendríamos que buscar estos ID y sustituirlos por los nuevos ID.

targets

Los IDs de los elementos de Azure responde al formato: /subscriptions/{subscription-guid}/resourceGroups/{resource-group-name}/{resource-provider-namespace}/{resource-type}/{resource-name}

Automatización de la exportación de los servicios PaaS de Azure
#

Bien, ahora que ya sabemos cómo hacer un backup y no menos importante como hacer un restore, vamos a por la segunda parte, ¿Cómo automatizar el proceso de Backup?

Para automatizar el proceso de backup necesitaremos estos cuatro elementos de Azure:

  • Storage Account v2 con un Container para guardar los JSON exportados
  • Automation Account encargado de la ejecución de los runbooks (scripts) para el proceso de exportación.
  • Managed Identity que actuara como identidad de la Automation Account para asignar los permisos RBAC necesarios.
  • Runbook de tipo Powershell con el siguiente Script:
  1<#
  2.SYNOPSIS
  3Script to Backup Azure PaaS Elements
  4
  5.SYNTAX
  6AzureBackupPaaS.ps1 [-BackupElementName <System.String>] [-StorageAccountName  <System.String>] [-BlobContainerName  <System.String>] [-StorageAccountKey  <System.String>] [-RetentionDays  <System.Int>]
  7
  8.DESCRIPTION
  9The Script export the configuration of the element to JSON
 10
 11.EXAMPLE
 12AzureBackupPaaS.ps1 -BackupElementName MyApplicationGateway -StorageAccountName MyStorageAccount -BlobContainerName backupBlobContainer -StorageAccountKey xxxxrfffee -RetentionDays 15
 13AzureBackupPaaS.ps1 -BackupElementName MyApplicationGateway -StorageAccountName MyStorageAccount -BlobContainerName backupBlobContainer -ManamentIdentityClientID xxxxrfffee -RetentionDays 15
 14#>
 15
 16#region parameters
 17Param(    
 18    [Parameter(Mandatory)]
 19        [string]$BackupElementName,
 20
 21    [Parameter(Mandatory)]
 22        [string]$StorageAccountName,
 23
 24    [Parameter(Mandatory)]
 25        [string]$BlobContainerName,
 26
 27    [Parameter()]
 28        [string]$ManamentIdentityClientID,    
 29
 30    # [Parameter()]
 31    #    [string]$StorageAccountKey,
 32
 33    [Parameter()]
 34        [int]$RetentionDays = 7
 35)
 36
 37$ErrorActionPreference = "Stop"
 38
 39function Login() {
 40    $connectionName = "AzureConnectionName"
 41    try
 42    {
 43        # Ensures you do not inherit an AzContext in your runbook
 44        Disable-AzContextAutosave -Scope Process
 45
 46            # Connect to Azure with user-assigned managed identity
 47        $AzureContext = (Connect-AzAccount -Identity -AccountId $ManamentIdentityClientID).context
 48
 49        # set and store context
 50        $AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
 51                           -DefaultProfile $AzureContext
 52
 53        Write-host $AzureContext
 54    }
 55    catch {
 56        if (!$AzureContext)
 57        {
 58            $ErrorMessage = "Connection $connectionName not found."
 59            throw $ErrorMessage
 60        } else{
 61            Write-Error -Message $_.Exception
 62            throw $_.Exception
 63        }
 64    }
 65}
 66
 67function Backup-To-Blob-Storage([string]$elementToBackupName, [string]$blobContainerName,$storageContext) {
 68    Write-Verbose "Starting $elementToBackupName export" -Verbose
 69    
 70    $BackupFilename = $elementToBackupName + (Get-Date).ToString("yyyyMMddHHmm") + ".json"
 71    $BackupFilePath = ($env:TEMP + "\" + $BackupFilename)
 72
 73    $ComponentToBackup = Get-AzResource -Name $elementToBackupName
 74    write-host "Element to Backup: "
 75    write-host $ComponentToBackup
 76
 77    Export-AzResourceGroup -ResourceGroupName $ComponentToBackup.ResourceGroupName `
 78                -Resource $ComponentToBackup.ResourceId `
 79              -SkipAllParameterization -Path $BackupFilePath
 80
 81    Write-Output "Creating request to copy $elementToBackupName  configuration"
 82    
 83    $outputFirewall = Set-AzStorageBlobContent -File $BackupFilePath `
 84                                               -Blob $BackupFilename `
 85                                               -Container $blobContainerName `
 86                                        -Context $storageContext `
 87                                        -Force -ErrorAction SilentlyContinue
 88
 89    Write-host $outputFirewall
 90}
 91
 92function Remove-Old-Backups([int]$retentionDays, [string]$blobContainerName, $storageContext) {
 93    Write-Output "Removing backups older than '$retentionDays' days from blob: '$blobContainerName'"
 94    
 95    $isOldDate = [DateTime]::UtcNow.AddDays(-$retentionDays)
 96    
 97    $blobs = Get-AzStorageBlob -Container $blobContainerName -Context $storageContext
 98    
 99    foreach ($blob in ($blobs | Where-Object { $_.LastModified.UtcDateTime -lt $isOldDate -and $_.BlobType -eq "BlockBlob" })) {
100
101        Write-Verbose ("Removing blob: " + $blob.Name) -Verbose
102        Remove-AzStorageBlob -Blob $blob.Name -Container $blobContainerName -Context $storageContext
103
104    }
105}
106
107Write-Verbose "Starting database backup" -Verbose
108
109#MAIN
110#Login to Azure
111Login
112
113#Connect with storage account as Backup Destination (Firs line is for key access, second one is for Managed Identity.)
114
115#$StorageContext = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageKey
116
117$StorageContext = New-AzStorageContext -StorageAccountName$StorageAccountName `
118                                       -UseConnectedAccount -Protocol Https
119
120#Importing needed modules
121Import-Module Az.Network
122Import-Module Az.Resources
123
124Backup-To-Blob-Storage `
125    -elementToBackupName $BackupElementName `
126    -blobContainerName $BlobContainerName `
127    -storageContext $storageContext
128
129#Remove old files backup
130Remove-Old-Backups `
131    -retentionDays $RetentionDays `
132    -storageContext $StorageContext `
133    -blobContainerName $BlobContainerName

El script se compone de cuatro partes:

  • Instrucciones y parametrización
  • Bloque de Funciones
    • Función Login: Para hacer login en Azure usando la Managed Identity
    • Función Backup-To-Blob-Storage encargado de hacer las copias de seguridad
    • Función Remove-Old-Backups encargado de eliminar copias antiguas (fuera del periodo de retención)
  • Bloque Main donde consumimos las funciones anteriores y consta de cuatro partes:
    • Llamada a Login
    • Conexión con la Storage Account usando la Identity Management
    • Llamada a la función de Backup Backup-To-Blob-Storage
    • Llamada a la función de Eliminación de copias antiguas Remove-Old-Backups

Configuración de la Automation Account y del Runbook
#

Para la configuración de nuestro Automation Account necesitaremos tener creada la Managed Identity y como no la automation account. La Storage Account, aunque no es necesaria en este punto, recomiendo crearla ya.

No vamos a entrar en este artículo en el proceso de creación de los elementos ya que lo haría muy extenso y desde el portal es bastante sencillo.

Para este ejemplo, he creado los siguientes elementos:

  • Storage Account v2: CentralHubOperations
  • Storage Account v2 Container: azurebackuppaas
  • Automation Account: CentralAutomation
  • Managed Identity: CentralAutomation-UserIdentity

Lo primero que tenemos que hacer es dotar a la Automation Account de identidad propia con nuestra Managed Identity (MI).

Una Managed Identity es un elemento de Azure que nos permite obtener Tokens desde Azure AD sin necesidad de gestionar credenciales. De esta forma podemos asignar permisos RBAC a otros elementos de Azure sin necesidad de gestionar complejos cambios de contraseña, caducidades de cuenta, etc.

Existe otro concepto interesante en la MI que es importante conocer antes de continuar y es el tipo de MI:

  • System-Assigned: Esta vinculado a un elemento de Azure directamente y a su ciclo de vida, por ejemplo, una VM o como es nuestro caso una Automation Account. Al eliminar el elemento, la identidad se destruye con él.
  • User-Assigned: Es una identidad creada por el administrador de Azure y su ciclo de vida es independiente al del elemento en el que se asocie.

En nuestro caso utilizaremos una User-Assigned identity ya que en el caso de tener que recrear la Automation Account se destruiría y sería necesario reasignar todos los permisos que veremos más adelante.

Para la asignación de nuestra Managed Identity, accederemos a nuestra Automation Account y en el Blade buscaremos Identity, seleccionaremos User Assigned y +Add

targets

Una vez creada y asignada la identidad, concedemos los siguientes permisos a la identidad que representa nuestra Managed Identity:

  • Sobre el recurso a hacer copia o su Resource Group permiso RBAC de Reader
  • Sobre la Storage Account permiso RBAC de Reader
  • Sobre el Container, dentro de la Storage Account, permiso RBAC de Storage Blob Data Contributor

Los permisos se asignan desde el Blade, opción Access Control IAM de cada elemento:

targets

targets

En la pantalla de asignación de Roles, buscaremos el rol de reader:

targets

En la pantalla Member seleccionaremos Managed Identity y seleccionaremos nuestra Managed Identity:

targets

Este proceso es de ejemplo y habrá que repetirlo en cada uno de los elementos y con los roles arriba indicados

Bien, llegados a este punto ya tenemos configurados todos los elementos de Azure implicados en la copia de seguridad, ahora vamos a ver como crear el runbook y como programar su ejecución:

Desde el portal de Azure, buscamos nuestra Automation Account y en el Blade RunBooks y New Runbook

targets

Asignamos nombre a nuestro Runbook y como Type Powershell 5.1. En el editor, pegamos el script anterior y lo publicamos pulsando sobre publish

targets

El último paso es consiste en programar los backups: Fecha, Hora, Repeticiones… etc… Para ello, desde el runbook recién publicado, el Blade lateral pulsaremos en y Add a Schedule donde nos saldrá un menú con dos opciones, en la primera podremos asociar nuestra tarea a un Schedule previamente creado o nos permitirá crear uno nuevo y en la segunda asociaremos la tarea programada con los parámetros necesarios.

targets

La primera opción es bastante sencilla, simplemente indicaremos Fecha de comienzo, Hora de ejecución (y su time zone) y si queremos que se ejecute una sola vez o sea recurrente. Para nuestro ejemplo podemos indicar que se ejecute diariamente a las 00:00 CET, sin fecha de fin:

targets

Por último, configuraremos los parámetros indicando:

  • BackupElementName: El elemento de Azure a hacer backup
  • StorageAccountName: El storage Account donde guardaremos los backups.
  • BlobContainerName: El container dentro de la Storage Account donde guardaremos el backup
  • ManagementIdentityClienID: El ClientID de nuestra Managed Identity.
  • RetentionDays: Perido de retención de los backups. Si no se indica nada se utilizara un valor de 7 días.
    targets

Con este último paso ya podemos dar por creado un sistema para hacer copias de seguridad de elementos PaaS en una Storage Account.

A partir de aquí ya queda en vuestras manos hacer un plan de copia de seguridad, como recomendación, utilizar los beneficios de réplica multirregión que ofrecen las Storage Account y muy importante documentar como hacer el restore de cada uno de los elementos a los que hagáis backup para poder detectar pequeñas adaptaciones que podáis necesitar.