How to Backup AKS with Velero: A Step-by-Step Guide

Backing Up AKS with Velero

Prerequisites

  • AKS cluster running
  • Azure CLI installed
  • kubectl configured
  • Helm installed

Step 1: Create Azure Storage Account & Blob Container

# Set variables
RESOURCE_GROUP="myResourceGroup"
LOCATION="eastus"
STORAGE_ACCOUNT="velerobackupstorage"
BLOB_CONTAINER="velero-backups"
AKS_CLUSTER="myAKSCluster"
# Create resource group (if not exists)
az group create --name $RESOURCE_GROUP --location $LOCATION
# Create storage account
az storage account create \
--name $STORAGE_ACCOUNT \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--sku Standard_LRS \
--encryption-services blob
# Create blob container
az storage container create \
--name $BLOB_CONTAINER \
--account-name $STORAGE_ACCOUNT

Step 2: Create Service Principal for Velero

# Create service principal
AZURE_SUBSCRIPTION_ID=$(az account show --query id -o tsv)
AZURE_TENANT_ID=$(az account show --query tenantId -o tsv)
# Create SP and assign contributor role
AZURE_CLIENT_SECRET=$(az ad sp create-for-rbac \
--name velero-sp \
--role Contributor \
--scopes /subscriptions/$AZURE_SUBSCRIPTION_ID \
--query password \
-o tsv)
AZURE_CLIENT_ID=$(az ad sp list \
--display-name velero-sp \
--query '[0].appId' \
-o tsv)
echo "Client ID: $AZURE_CLIENT_ID"
echo "Client Secret: $AZURE_CLIENT_SECRET"

Step 3: Create Velero Credentials File

# Create credentials file
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=${RESOURCE_GROUP}
AZURE_CLOUD_NAME=AzurePublicCloud
EOF

Step 4: Install Velero on AKS

# Add Velero Helm repo
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
helm repo update
# Get storage account access key
STORAGE_ACCOUNT_KEY=$(az storage account keys list \
--account-name $STORAGE_ACCOUNT \
--resource-group $RESOURCE_GROUP \
--query '[0].value' \
-o tsv)
# Install Velero with Azure plugin
velero install \
--provider azure \
--plugins velero/velero-plugin-for-microsoft-azure:v1.8.0 \
--bucket $BLOB_CONTAINER \
--secret-file ./credentials-velero \
--backup-location-config \
resourceGroup=$RESOURCE_GROUP,\
storageAccount=$STORAGE_ACCOUNT,\
storageAccountKeyEnvVar=AZURE_STORAGE_ACCOUNT_ACCESS_KEY \
--snapshot-location-config \
resourceGroup=$RESOURCE_GROUP,\
apiTimeout=5m \
--use-volume-snapshots=true \
--wait

Step 5: Verify Velero Installation

# Check Velero pods are running
kubectl get pods -n velero
# Check backup storage location is available
velero backup-location get
# Expected output:
# NAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED
# default azure velero-backups Available ...

Step 6: Create Backups

Manual Backup (Full Cluster)

# Backup entire cluster
velero backup create full-cluster-backup \
--include-cluster-resources=true \
--wait
# Check backup status
velero backup describe full-cluster-backup
velero backup logs full-cluster-backup

Backup Specific Namespace

# Backup a single namespace
velero backup create my-app-backup \
--include-namespaces my-app-namespace \
--wait
# Backup multiple namespaces
velero backup create multi-ns-backup \
--include-namespaces namespace1,namespace2 \
--wait

Backup with Labels

# Backup resources matching a label
velero backup create label-backup \
--selector app=my-application \
--wait

Exclude Specific Resources

# Exclude secrets and specific namespaces
velero backup create selective-backup \
--exclude-namespaces kube-system,velero \
--exclude-resources secrets \
--wait

Step 7: Schedule Automated Backups

# Daily backup at 2am UTC (keep 30 days)
velero schedule create daily-backup \
--schedule="0 2 * * *" \
--ttl 720h \
--include-cluster-resources=true
# Weekly backup every Sunday at midnight (keep 90 days)
velero schedule create weekly-backup \
--schedule="0 0 * * 0" \
--ttl 2160h
# Namespace-specific daily backup
velero schedule create daily-app-backup \
--schedule="0 2 * * *" \
--include-namespaces production \
--ttl 168h
# List all schedules
velero schedule get

Step 8: Restore from Backup

Full Restore

# List available backups
velero backup get
# Restore full cluster backup
velero restore create \
--from-backup full-cluster-backup \
--wait
# Check restore status
velero restore get
velero restore describe <restore-name>

Restore Specific Namespace

# Restore a specific namespace
velero restore create \
--from-backup my-app-backup \
--include-namespaces my-app-namespace \
--wait

Restore to Different Namespace

# Restore namespace-A into namespace-B
velero restore create \
--from-backup my-app-backup \
--namespace-mappings old-namespace:new-namespace \
--wait

Restore Specific Resources Only

# Restore only deployments and services
velero restore create \
--from-backup full-cluster-backup \
--include-resources deployments,services \
--wait

Step 9: Backup Hooks (Pre/Post Actions)

Useful for database consistency before backup:

# deployment-with-backup-hooks.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
annotations:
pre.hook.backup.velero.io/command: '["/bin/bash", "-c", "mysqldump -u root -p$MYSQL_ROOT_PASSWORD mydb > /backup/dump.sql"]'
pre.hook.backup.velero.io/timeout: "60s"
post.hook.backup.velero.io/command: '["/bin/bash", "-c", "rm -f /backup/dump.sql"]'
kubectl apply -f deployment-with-backup-hooks.yaml

Step 10: Monitor & Troubleshoot

# View backup details
velero backup describe my-backup --details
# View backup logs
velero backup logs my-backup
# View restore logs
velero restore logs my-restore
# Check Velero server logs
kubectl logs deployment/velero -n velero
# List all backups with status
velero backup get
# Delete old backup manually
velero backup delete old-backup-name

Summary Cheat Sheet

TaskCommand
Full backupvelero backup create <name> --include-cluster-resources=true
Namespace backupvelero backup create <name> --include-namespaces <ns>
Schedule dailyvelero schedule create <name> --schedule="0 2 * * *"
List backupsvelero backup get
Restore backupvelero restore create --from-backup <name>
Check statusvelero backup describe <name>
View logsvelero backup logs <name>

Best Practices

  • Test restores regularly – don’t wait for disaster to find out your backup is broken
  • Use TTL to automatically expire old backups and save storage costs
  • Backup before upgrades – always take a snapshot before AKS version upgrades
  • Store credentials securely – use Azure Key Vault instead of plain credentials files
  • Use hooks for databases to ensure data consistency
  • Cross-region storage – store backups in a different Azure region for disaster recovery
  • Combine with GitOps – use Velero for stateful data + Git for manifests

Leave a comment