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:
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.
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:
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
Una vez eliminados, podemos comenzar con el restore: En el portal de Azure buscaremos Deploy a Custom Template
Seleccionamos la opción Build your own template in the editor
Se nos abre un editor donde podemos cargar la templeate desde nuestro equipo o simplemente copiar y pegar desde otro editor y salvamos:
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:
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.
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.
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
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:
En la pantalla de asignación de Roles, buscaremos el rol de reader:
En la pantalla Member seleccionaremos Managed Identity y seleccionaremos nuestra Managed Identity:
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
Asignamos nombre a nuestro Runbook y como Type Powershell 5.1. En el editor, pegamos el script anterior y lo publicamos pulsando sobre publish
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.
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:
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.
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.