Como en cualquier otra plataforma, en un entorno de Kubernetes también es necesario tener un sistema de backups que nos permita hacer copias de seguridad de las cargas de trabajo que hemos desplegado en dicho entorno. Además, es posible que estemos haciendo uso de volúmenes persistentes que queramos respaldar con cierta periocidad. En este artículo te comparto cómo configurar Velero para un entorno con Azure Kubernetes Service.
Crear el clúster origen
Para este artículo he creado un clúster desde cero con una aplicación de ejemplo que me ayudará a ver el escenario completo.
# Variables
RESOURCE_GROUP="velero-demo"
LOCATION="westeurope"
AKS_NAME="velero-demo-aks"
# Create a resource group.
az group create --name $RESOURCE_GROUP --location $LOCATION
# Create an AKS cluster.
az aks create \
--resource-group $RESOURCE_GROUP \
--name $AKS_NAME \
--generate-ssh-keys
# Get the cluster credentials.
az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_NAME
Desplegar aplicación de ejemplo
Como aplicación de ejemplo voy a utilizar esta que tiene varios componentes: un frontal en Angular, una API en .NET Core y una base de datos SQL Server que utiliza un persistent volume. Esta la voy a desplegar usando dos configuraciones: una que tiene el persistent volume en formato Azure Disk y otra que lo tiene usando Azure Files con el protocolo NFS, para tener dos de los tres sabores 😉:
# Create a demo with azure disk
kubectl create ns tour-of-heroes-azure-disk
kubectl apply -n tour-of-heroes-azure-disk -f tour-of-heroes-demos/azure-disk --recursive
k get all -n tour-of-heroes-azure-disk
# Create a demo with azure file with nfs protocol
kubectl create ns tour-of-heroes-azure-files-nfs
kubectl apply -n tour-of-heroes-azure-files-nfs -f tour-of-heroes-demos/azure-files-nfs --recursive
k get all -n tour-of-heroes-azure-files-nfs
# Add some heroes via API (use client.http)
Para ambas lo que hago, una vez desplegadas, es utilizar un archivo que forma parte del repositorio, llamado client.http (que lo uso en conjunto con la extensión REST Client de Visual Studio Code) para lanzar varias llamadas a la API (para ello es necesario que cambies la IP por la que se haya asignado a los servicios asociados en esta en ambos despliegues) y así tener información de la que luego hacer backup y ver que ha funcionado correctamente.
Instalar Velero
Ahora que ya tienes un origen con cosas de las que hacer backup, lo siguiente que necesitas es hacer la copia de seguridad. Para ello, primeramente tienes que instalar Velero en tu local:
# Install Velero locally
brew install velero
Como te puedes imaginar, los backups deben almacenarse en algún sitio. En el caso de Azure este sitio es una cuenta de almacenamiento, por lo que podemos crear una, y un contenedor, de la siguiente forma:
# Create an storage account
STORAGE_NAME="k8svelerobackupg"
az storage account create \
--name $STORAGE_NAME \
--resource-group $RESOURCE_GROUP \
--sku Standard_GRS \
--encryption-services blob \
--https-only true \
--kind BlobStorage \
--access-tier Hot
# Create a container
BLOB_CONTAINER=backups
az storage container create \
-n $BLOB_CONTAINER \
--public-access off \
--account-name $STORAGE_NAME
Lo siguiente es generar un service principal (también puedes hacerlo con Azure AD Pod Identity) que le permita a Velero gestionar esta cuenta de almacenamiento que acabas de crear:
# Set permissions for velero
AZURE_SUBSCRIPTION_ID=`az account list --query '[?isDefault].id' -o tsv`
AZURE_TENANT_ID=`az account list --query '[?isDefault].tenantId' -o tsv`
AZURE_CLIENT_SECRET=$(az ad sp create-for-rbac --name "velero" --role "Contributor" --scopes /subscriptions/$AZURE_SUBSCRIPTION_ID --query 'password' -o tsv)
AZURE_CLIENT_ID=`az ad sp list --display-name "velero" --query '[0].appId' -o tsv`
#the resource group that contains your cluster's virtual machines/disks.
AKS_NODE_RESOURCE_GROUP=$(az aks show --resource-group $RESOURCE_GROUP --name $AKS_NAME --query nodeResourceGroup -o tsv)
Una vez que tienes todos los parámetros de este, hay que generar un archivo con el siguiente formato:
cat << EOF > ./credentials-velero
AZURE_SUBSCRIPTION_ID=${AZURE_SUBSCRIPTION_ID}
AZURE_TENANT_ID=${AZURE_TENANT_ID}
AZURE_CLIENT_ID=${AZURE_CLIENT_ID}
AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET}
AZURE_RESOURCE_GROUP=${AKS_NODE_RESOURCE_GROUP}
AZURE_CLOUD_NAME=AzurePublicCloud
EOF
Con todo esto, ya estamos listos para desplegar Velero en el clúster origen. La configuración en el caso de Azure sería como la siguiente:
# Install and start Velero
velero install \
--provider azure \
--plugins velero/velero-plugin-for-microsoft-azure:v1.4.1 \
--bucket $BLOB_CONTAINER \
--secret-file ./credentials-velero \
--backup-location-config resourceGroup=$RESOURCE_GROUP,storageAccount=$STORAGE_NAME,subscriptionId=$AZURE_SUBSCRIPTION_ID \
--snapshot-location-config resourceGroup=$RESOURCE_GROUP,subscriptionId=$AZURE_SUBSCRIPTION_ID \
--use-restic
# Velero is installed! ⛵ Use 'kubectl logs deployment/velero -n velero' to view the status.
kubectl logs deployment/velero -n velero
# Check that everthing is up and running
kubectl -n velero get pods
Como ves, en esta plataforma es necesario instalar el plugin velero/velero-plugin-for-microsoft-azure, que en el momento de escribir este artículo tiene su versión más reciente en la 1.4.1. También es importante el parámetro –use-restic ya que de lo contrario no podrás hacer el backup de los persistent volumes de manera correcta.
Hacer backup en el clúster origen
Lo último que nos queda por hacer con este clúster es generar los backups oportunos. En este caso voy a hacer dos: uno por cada namespace de mis ejemplos:
# To run a basic on-demand backup of your cluster with azure disk pv
velero backup create azure-disk-backup --default-volumes-to-restic --include-namespaces tour-of-heroes-azure-disk
velero backup describe azure-disk-backup --details
# To run a basic on-demand backup of your cluster with azure files (NFS protocol) pv
velero backup create azure-files-nfs-backup --default-volumes-to-restic --include-namespaces tour-of-heroes-azure-files-nfs
velero backup describe azure-files-nfs-backup --details
Como ves, a través de velero backup puedo crear copias de seguridad de un namespace completo, incluyendo los volúmenes en estos. Con velero backup describe puedo ver la evolución de los mismos. Para este ejemplo he utilizado backups a demanda, pero también es posible programarlos cada cierto tiempo.
Si quisieras ver todos los backups que has generado bajo esta configuración puedes utilizar este otro comando:
# Check all backups with velero
velero get backups
Crear un clúster de destino
Ahora que ya tenemos algo que restaurar vamos a crear un clúster de destino de la misma forma que el anterior:
# Create a new cluster
az group create --name $RESOURCE_GROUP-restore --location $LOCATION
# Create a new resource group
az aks create \
--resource-group $RESOURCE_GROUP-restore \
--name $AKS_NAME-restore \
--generate-ssh-keys
# Get the cluster credentials
az aks get-credentials --resource-group $RESOURCE_GROUP-restore --name $AKS_NAME-restore
Para que este pueda acceder a los backups generados anteriormente la instalación de Velero debe tener los mismos valores que en el origen:
# Deploy and configure velero here
velero install \
--provider azure \
--plugins velero/velero-plugin-for-microsoft-azure:v1.4.1 \
--bucket $BLOB_CONTAINER \
--secret-file ./credentials-velero \
--backup-location-config resourceGroup=$RESOURCE_GROUP,storageAccount=$STORAGE_NAME,subscriptionId=$AZURE_SUBSCRIPTION_ID \
--snapshot-location-config resourceGroup=$RESOURCE_GROUP,subscriptionId=$AZURE_SUBSCRIPTION_ID \
--use-restic
# Check the pods for velero
kubectl -n velero get pods
# Check the logs
kubectl logs deployment/velero -n velero
Puedes comprobar que estos son visibles desde aquí con el mismo comando con el que recuperaste todos los backups anteriormente:
# Check that you can see the backups
velero get backups
Ahora, la prueba de fuego, vemos que efectivamente no tenemos nada en los namespaces de los que hicimos backup:
# Nothing here
k get pods -n tour-of-heroes-azure-disk
k get pods -n tour-of-heroes-azure-files-nfs
Y procedemos a hacer la restauración:
# Restore backup
velero restore create --from-backup azure-disk-backup
velero restore create --from-backup azure-files-nfs-backup
En la salida de ambos comandos podremos lanzar un velero restore describe de cada uno de los procesos para ver cuál es el estado del mismo:
# See details
velero restore describe azure-disk-backup-XXXXXXXXXX --details
velero restore describe azure-files-nfs-backup-XXXXXXX --details
y, una vez finalicen, podremos comprobar que todos los recursos se han restaurado correctamente:
# Now tour-of-heroes is restored!
k get all -n tour-of-heroes-azure-disk
k get all -n tour-of-heroes-azure-files-nfs
Y que los registros en la base de datos introducidos a través de la API también están ahí.
El código completo, con las aplicaciones de ejemplo, los tienes en mi GitHub.
¡Saludos!