Velero + S3 Glacier : ma stratégie backup


Après des mois à construire mon homelab, une question me taraudait : et si tout plante ?

Mon Dell R430 tourne bien, Talos est stable, mes apps sont déployées… mais je n’avais aucun backup. Rien. Nada. Un crash disque, une mauvaise manip kubectl delete, et des mois de travail partent en fumée.

Il était temps de mettre en place une vraie stratégie de backup, comme on fait dans le monde pro.

La règle 3-2-1

Avant de foncer tête baissée, petit rappel des bonnes pratiques :

  • 3 copies de vos données
  • 2 supports différents (local + cloud)
  • 1 copie offsite (hors de chez vous)

Pour un homelab Kubernetes, ça se traduit par :

  • Les données live dans le cluster (copie 1)
  • Un backup local sur un autre disque/NAS (copie 2) - optionnel pour moi
  • Un backup cloud offsite (copie 3) - c’est ça qu’on va mettre en place

Velero : le standard pour backup K8s

Velero (anciennement Heptio Ark) est l’outil de référence pour sauvegarder des clusters Kubernetes. Il backup :

  • Toutes les ressources K8s (Deployments, Services, ConfigMaps, Secrets…)
  • Les PersistentVolumes (via snapshots ou File System Backup)
  • Les Custom Resources

Le tout vers un stockage objet (S3, GCS, Azure Blob…).

Mon choix : AWS S3 + Glacier

J’avais déjà un compte AWS, donc S3 était le choix évident. Mais stocker des backups en S3 Standard, ça coûte cher sur la durée (~$0.023/GB/mois).

La solution : S3 Lifecycle Policies pour archiver automatiquement vers Glacier :

Âge du backupStorage ClassCoût/GB/mois
0-30 joursS3 Standard~$0.023
30-120 joursGlacier Instant Retrieval~$0.004
120+ joursGlacier Deep Archive~$0.00099

Glacier Instant Retrieval = récupération en millisecondes, parfait pour les backups récents. Glacier Deep Archive = récupération en 12h, mais le moins cher du marché.

Installation de Velero

Prérequis AWS

  1. Créer un bucket S3 dans une région proche (eu-west-1 pour moi)

  2. Créer un user IAM velero avec cette policy :

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeVolumes",
                "ec2:DescribeSnapshots",
                "ec2:CreateTags",
                "ec2:CreateVolume",
                "ec2:CreateSnapshot",
                "ec2:DeleteSnapshot"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObject",
                "s3:AbortMultipartUpload",
                "s3:ListMultipartUploadParts"
            ],
            "Resource": "arn:aws:s3:::VOTRE-BUCKET/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::VOTRE-BUCKET"
        }
    ]
}
  1. Générer des Access Keys pour ce user

Installation CLI

brew install velero

Fichier credentials

Créer un fichier velero-credentials (à ne PAS commit dans git !) :

[default]
aws_access_key_id=VOTRE_ACCESS_KEY
aws_secret_access_key=VOTRE_SECRET_KEY

Déploiement dans le cluster

velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.11.1 \
  --bucket VOTRE-BUCKET \
  --backup-location-config region=eu-west-1 \
  --secret-file ./velero-credentials \
  --use-node-agent \
  --default-volumes-to-fs-backup

Les flags importants :

  • --use-node-agent : active le node-agent (DaemonSet) pour backup les PVCs via File System Backup
  • --default-volumes-to-fs-backup : backup tous les volumes par défaut

Vérification

velero backup-location get

Doit afficher Available. Si c’est Unavailable, vérifier :

  • Les credentials AWS
  • Le nom du bucket
  • La région
  • La policy IAM

Configuration des schedules

Backup quotidien complet

velero schedule create daily-full \
  --schedule="0 2 * * *" \
  --ttl 720h \
  --include-cluster-resources=true
  • Tous les jours à 2h du matin
  • Rétention 30 jours (720h)
  • Inclut les ressources cluster-wide

Backup des apps critiques

velero schedule create critical-apps \
  --schedule="0 */6 * * *" \
  --ttl 168h \
  --include-namespaces=production,monitoring
  • Toutes les 6 heures
  • Rétention 7 jours
  • Seulement les namespaces critiques

Vérifier les schedules

velero schedule get

Configuration S3 Lifecycle

Dans la console AWS S3 → Bucket → Management → Lifecycle rules :

  1. Create lifecycle rule
  2. Rule name : velero-backup-lifecycle
  3. Scope : Apply to all objects
  4. Transitions :
    • Jour 30 → Glacier Instant Retrieval
    • Jour 120 → Glacier Deep Archive
  5. Expiration : Jour 365 (optionnel)

Commandes utiles

Backup manuel

# Backup complet
velero backup create manual-backup-$(date +%Y%m%d)

# Backup d'un namespace
velero backup create ns-backup --include-namespaces=mon-namespace

Lister les backups

velero backup get

Voir les détails d’un backup

velero backup describe mon-backup --details

Voir les logs

velero backup logs mon-backup

Restauration

# Restaurer tout
velero restore create --from-backup daily-full-20260130

# Restaurer un namespace spécifique
velero restore create --from-backup daily-full-20260130 \
  --include-namespaces=mon-namespace

# Restaurer vers un nouveau namespace
velero restore create --from-backup daily-full-20260130 \
  --include-namespaces=old-namespace \
  --namespace-mappings old-namespace:new-namespace

Le récap

ComposantConfiguration
StorageS3 tom-homelab-backups (eu-west-1)
Backup quotidien2h00, rétention 30 jours
Backup critique/6h, rétention 7 jours
Glacier IRAprès 30 jours
Deep ArchiveAprès 120 jours
ExpirationAprès 365 jours

Ce que j’aurais voulu savoir avant

  1. Le fichier credentials doit avoir le header [default] - sinon Velero ne parse pas les credentials

  2. Vérifier la policy IAM - l’erreur AccessDenied: not authorized to perform s3:ListBucket signifie souvent que le bucket name dans la policy ne match pas

  3. File System Backup est lent - pour les gros PVCs, ça peut prendre du temps. Les logs montrent la progression

  4. Glacier a un minimum de 90 jours d’écart - entre Glacier IR et Deep Archive, AWS impose un écart de 90 jours minimum

  5. Les backups “PartiallyFailed” ne sont pas forcément cassés - souvent c’est juste des pods completed (Jobs) dont les volumes ne peuvent pas être backupés


Voilà, mon homelab est maintenant protégé. Si mon Dell R430 décide de rendre l’âme demain, je peux reconstruire tout le cluster à partir des backups S3. Ça fait quand même dormir plus tranquille.

La prochaine étape ? Peut-être un backup local sur mon NAS Synology en plus, pour avoir la copie 2 de la règle 3-2-1. Mais ça, c’est pour un autre article.