Article principal · Ce tutoriel fait partie de la série Kubernetes domestique sur Proxmox VE. Tutoriel précédent : kube-prometheus-stack. Dernière étape du parcours.
Une fois le cluster productif, la dernière question à régler est la sauvegarde. Sans plan de reprise testé, une suppression accidentelle, un upgrade raté, un incident de stockage Ceph peuvent anéantir des semaines de configuration et de données. Velero est l outil de référence pour sauvegarder un cluster Kubernetes : il capture les objets de l API server (Deployments, Services, ConfigMaps, Secrets, CRD) et les volumes persistants associés, vers un stockage objet S3-compatible. La version 1.18 sortie au printemps 2026 ajoute le support des cache volumes pour les data movers et le filtrage glob sur les namespaces. Ce tutoriel installe Velero 1.18, configure le bucket S3 fourni par Rook-Ceph, lance les premières sauvegardes programmées, et teste une restauration complète d un namespace.
Étape 1 — Préparer le bucket S3 et les credentials
Velero a besoin d un bucket pour y stocker les objets sérialisés et les snapshots de volumes. Le bucket S3 ObjectStore de Rook-Ceph (créé dans le tutoriel Rook) convient parfaitement. On crée un user dédié à Velero pour cloisonner les permissions.
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- \
radosgw-admin user create --uid=velero --display-name="Velero Backup User"
# Noter access_key et secret_key de la sortie
# Créer le bucket via la CLI s3cmd ou via une CRD ObjectBucketClaim
cat > velero-bucket-claim.yaml <<EOF
apiVersion: objectbucket.io/v1alpha1
kind: ObjectBucketClaim
metadata:
name: velero-backups
namespace: velero
spec:
generateBucketName: velero-
storageClassName: rook-ceph-bucket
EOF
kubectl create namespace velero
kubectl apply -f velero-bucket-claim.yaml
# Récupérer le nom de bucket généré
kubectl -n velero get cm velero-backups -o jsonpath='{.data.BUCKET_NAME}'
Le bucket est créé dans Ceph et géré par Rook. L approche par ObjectBucketClaim est plus propre que la création manuelle parce qu elle versionne la déclaration et la lie au cycle de vie du namespace velero.
Étape 2 — Installer Velero avec la CLI officielle
Velero s installe via sa CLI dédiée plutôt qu en pur Helm parce que la CLI configure correctement les BackupStorageLocation et VolumeSnapshotLocation, ce qui est plus tatillon en YAML pur.
# Installer la CLI velero 1.18
VELERO_VERSION=v1.18.0
curl -L https://github.com/vmware-tanzu/velero/releases/download/\$\{VELERO_VERSION\}/velero-\$\{VELERO_VERSION\}-linux-amd64.tar.gz -o velero.tar.gz
tar -xvzf velero.tar.gz
sudo install velero-\$\{VELERO_VERSION\}-linux-amd64/velero /usr/local/bin/
# Préparer le fichier de credentials S3
cat > credentials-velero <<EOF
[default]
aws_access_key_id=ACCESSKEYHERE
aws_secret_access_key=SECRETKEYHERE
EOF
# Récupérer l endpoint interne du bucket Ceph
S3_HOST=$(kubectl -n rook-ceph get svc rook-ceph-rgw-my-store \
-o jsonpath='{.spec.clusterIP}')
# Installer Velero avec le plugin AWS et le data mover Kopia (par défaut depuis 1.12)
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.14.0 \
--bucket velero-xxxxxxxx \
--secret-file ./credentials-velero \
--use-volume-snapshots=false \
--backup-location-config region=default,s3ForcePathStyle=true,s3Url=http://\$\{S3_HOST\} \
--uploader-type kopia \
--features=EnableCSI \
--default-volumes-to-fs-backup
L installation crée le namespace velero, déploie le pod Velero principal et le DaemonSet node-agent. La présence du flag --default-volumes-to-fs-backup et de Kopia comme uploader configure le file system backup, qui copie les fichiers depuis chaque pod vers le bucket. C est la méthode universelle qui fonctionne avec n importe quelle StorageClass, y compris Rook-Ceph RBD et CephFS.
Étape 3 — Vérifier que Velero est opérationnel
Avant la première sauvegarde, vérifier que tous les composants sont sains. La CLI Velero fournit des commandes dédiées au diagnostic.
velero version
# Doit afficher Client v1.18.0 et Server v1.18.0
velero backup-location get
# default doit être en état Available
velero get plugin
# Doit lister velero-plugin-for-aws et le data mover
L état Available sur la BackupStorageLocation confirme que Velero peut lire et écrire dans le bucket. Si l état est Unavailable, vérifier en priorité la résolution du DNS interne, l accessibilité du Service Ceph RGW depuis le namespace velero, et la validité des credentials S3.
Étape 4 — Lancer la première sauvegarde manuelle
Avant d automatiser, on teste manuellement la sauvegarde d un namespace. C est l occasion de mesurer la durée et la taille produite.
velero backup create test-demo-1 \
--include-namespaces demo \
--wait
velero backup describe test-demo-1 --details
# Status doit progresser : InProgress → Completed
# Items backed up indique le nombre d objets capturés
Voir la sauvegarde passer en Completed avec un nombre d items cohérent (Pods, PersistentVolumes, Services, Secrets…) et un volume de données reflétant la taille réelle du PVC confirme que Velero capture bien tout. Pour vérifier que les données du volume sont effectivement copiées, inspecter le bucket avec un client S3.
Étape 5 — Programmer les sauvegardes nocturnes
Une sauvegarde manuelle n a aucune valeur opérationnelle si elle n est pas automatisée. Velero gère les schedules nativement, avec une syntaxe cron.
velero schedule create nightly-full \
--schedule="0 2 * * *" \
--ttl 720h \
--include-namespaces "*" \
--exclude-namespaces "kube-system,velero,monitoring"
velero schedule create nightly-monitoring \
--schedule="0 3 * * *" \
--ttl 168h \
--include-namespaces "monitoring"
velero schedule get
# Doit lister les deux schedules avec next backup time
La séparation du namespace monitoring (qui peut peser plusieurs Gio à cause de Prometheus) avec une rétention plus courte évite que les snapshots du stack d observabilité ne saturent le bucket. Le TTL de 720 heures (30 jours) sur les sauvegardes générales correspond à un compromis raisonnable pour un homelab.
Étape 6 — Tester une restauration complète
Une sauvegarde non testée n est pas une sauvegarde. Le test consiste à supprimer un namespace existant et à le restaurer depuis Velero, puis à vérifier que les pods redémarrent et que les données sont bien là.
# Supprimer le namespace demo
kubectl delete namespace demo
sleep 30
kubectl get namespace demo
# Doit retourner NotFound
# Restaurer depuis la sauvegarde
velero restore create demo-restore-1 \
--from-backup test-demo-1 \
--wait
velero restore describe demo-restore-1
# Status doit être Completed
# Vérifier que les pods reviennent
kubectl get pods -n demo
# Vérifier les données du volume
kubectl exec test-pod -n demo -- cat /data/hello.txt
# Doit afficher : persistent-data
Le fichier hello.txt qui réapparaît avec son contenu prouve que le file system backup a effectivement copié les données et que la restauration les a réinjectées dans un nouveau volume Rook-Ceph. C est l unique critère qui valide la chaîne de bout en bout.
Étape 7 — Sauvegarder vers un stockage externe au cluster
Sauvegarder dans le même cluster qui est sauvegardé n a qu une valeur partielle : si tout le cluster brûle (incendie, vol, panne disque catastrophique), la sauvegarde brûle avec lui. La pratique sérieuse consiste à répliquer le bucket vers un stockage externe : un VPS Hetzner avec MinIO, un compte Backblaze B2, un Wasabi, ou un disque externe via rclone synchronisé chaque nuit.
# Exemple de réplication via rclone (à exécuter depuis un VPS externe)
rclone sync \
s3-homelab:velero-xxxxxxxx \
s3-backblaze:backup-homelab/velero \
--transfers 4 \
--checkers 8 \
--log-file /var/log/rclone-velero.log
Cette commande recopie l intégralité du bucket de sauvegarde vers un compte B2 distant. La règle universelle 3-2-1 (3 copies, 2 supports, 1 hors-site) devient applicable : la donnée vit sur les disques Ceph, dans le bucket Velero, et hors-site sur B2. Tester régulièrement la restauration depuis le bucket distant en montant temporairement le second BackupStorageLocation.
Étape 8 — Surveiller la santé via Prometheus et Grafana
Velero expose des métriques Prometheus quand le flag --features=EnableCSI est passé à l installation. Le ServiceMonitor associé doit être créé pour que kube-prometheus-stack les scrape.
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: velero
namespace: velero
labels:
release: kube-prometheus-stack
spec:
selector:
matchLabels:
app.kubernetes.io/name: velero
endpoints:
- port: monitoring
interval: 30s
Une fois le ServiceMonitor appliqué, les métriques velero_backup_success_total, velero_backup_failure_total, velero_backup_duration_seconds deviennent requêtables. Le dashboard Grafana Velero (importable depuis grafana.com via l ID 11055) affiche tout ce qu il faut savoir : timeline des sauvegardes, taux de succès, durée par namespace, taille cumulée du bucket.
Étape 9 — Préparer la procédure de Disaster Recovery
La sauvegarde n a de sens que si l on sait restaurer un cluster complet, pas juste un namespace. La procédure de DR consiste, sur un nouveau cluster Kubernetes vierge : installer Velero pointé vers le même bucket, lister les sauvegardes disponibles, et lancer une restauration globale. Documenter cette procédure est aussi important que de la sauvegarder.
# Sur le cluster cible (vierge), après installation de Velero pointé sur le même bucket
velero backup get
# Liste toutes les sauvegardes disponibles dans le bucket
velero restore create dr-2026-05-06 \
--from-backup nightly-full-20260505020000 \
--include-namespaces "demo,gitea,vaultwarden,nextcloud" \
--wait
# Vérifier la santé après restauration
kubectl get pods -A
kubectl get pvc -A
Quelques minutes après le démarrage de la restauration, les pods reviennent en Running et les volumes sont remontés. C est exactement le scénario qu on espère ne jamais avoir à exécuter, mais qu il faut tester au moins une fois pour pouvoir y compter.
Erreurs fréquentes et résolutions
| Symptôme | Cause | Résolution |
|---|---|---|
| BackupStorageLocation passe en Unavailable | Endpoint S3 injoignable ou credentials invalides | Vérifier kubectl logs -n velero deploy/velero et tester la connexion s3 depuis un pod |
| Sauvegarde Completed mais volume vide à la restauration | Annotation backup.velero.io/backup-volumes manquante sur le pod |
Vérifier que --default-volumes-to-fs-backup est bien actif |
| Restauration échoue avec « namespace already exists » | Le namespace cible existe déjà avec des conflits | Supprimer le namespace cible avant restauration ou utiliser --namespace-mappings |
| Schedule ne se déclenche pas | Cron syntax invalide ou cluster sans NTP synchronisé | Vérifier velero schedule describe et l heure du nœud |
| Le bucket grossit indéfiniment | TTL non appliqué sur les vieux backups | Vérifier velero backup get --selector velero.io/schedule-name=... et la cohérence des TTL |
Pour la suite
L environnement est désormais complet : hyperviseur, VM, Kubernetes HA, CNI eBPF, stockage répliqué, GitOps, observabilité, sauvegardes. Toute charge déployée à partir de maintenant bénéficie de la chaîne complète. C est le point d arrivée du parcours initial et le point de départ pour tout ce qu on voudra héberger ensuite : Gitea, Vaultwarden, Nextcloud, services internes, API personnelles. Pour la vue d ensemble et les pistes d évolution (sécurité durcie, cluster multi-nœuds Proxmox, stockage à grande échelle), retourner au guide principal Kubernetes domestique sur Proxmox VE.
Ressources et documentation officielle
- Documentation Velero : velero.io/docs
- Notes de version Velero 1.18 : github.com/vmware-tanzu/velero/releases
- File system backup avec Kopia : velero.io/file-system-backup
- Plugin AWS Velero : github.com/vmware-tanzu/velero-plugin-for-aws
- Disaster Recovery patterns : velero.io/disaster-case
- Documentation rclone (réplication externe) : rclone.org/docs
Étape 10 — Comprendre la différence entre file system backup et CSI snapshots
Velero offre deux mécanismes de sauvegarde de volumes : le file system backup avec Kopia (utilisé ici) qui copie les fichiers depuis l intérieur du pod, et les CSI snapshots qui s appuient sur la fonctionnalité de snapshot du driver CSI sous-jacent. Les deux ont des compromis distincts qu il faut comprendre pour les utiliser à bon escient.
Le file system backup fonctionne avec n importe quel volume, indépendamment du driver. Il est portable : on peut restaurer une sauvegarde Rook-Ceph sur un cluster utilisant local-path-provisioner. Il copie effectivement les fichiers donc consomme du débit réseau et du temps. Pour un volume de 10 Gio, compter une à dix minutes selon la latence du bucket.
Les CSI snapshots sont quasi-instantanés (le snapshot Ceph se fait en O(1) au niveau bloc) mais sont liés au driver source. Restaurer un snapshot Rook-Ceph sur un autre cluster nécessite que le bucket soit accessible et que Rook soit présent. La portabilité est plus restreinte mais la fenêtre de sauvegarde est nulle, ce qui est précieux pour les bases de données très volumineuses.
Pour un homelab, le file system backup avec Kopia est le bon défaut parce qu il est simple, portable et fiable. Pour des volumes Ceph très gros (100 Gio+), basculer cette charge spécifique sur CSI snapshots accélère la sauvegarde sans changer le reste de la configuration. Velero supporte les deux modes simultanément, l annotation backup.velero.io/backup-volumes-excludes permet d exclure du file system backup les volumes traités par CSI.
Étape 11 — Versionner Velero dans Argo CD
Comme tous les composants déployés au cours de ce parcours, Velero doit lui-même vivre dans Git pour permettre une reconstruction reproductible. La pratique consiste à committer le manifest généré par velero install --dry-run -o yaml dans le dépôt GitOps, puis à le pousser via une Application Argo CD.
velero install \
--dry-run -o yaml \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.14.0 \
--bucket velero-xxxxxxxx \
--secret-file ./credentials-velero \
--use-volume-snapshots=false \
--backup-location-config region=default,s3ForcePathStyle=true,s3Url=http://rgw.rook-ceph.svc \
--uploader-type kopia \
--features=EnableCSI \
--default-volumes-to-fs-backup \
> clusters/homelab/infra/velero/install.yaml
git add clusters/homelab/infra/velero
git commit -m "Manage Velero via Argo CD"
git push
Une fois cette Application synchronisée, mettre à niveau Velero revient à régénérer le manifest avec la nouvelle version de la CLI et committer. Argo CD applique l upgrade. La Secret cloud-credentials reste hors-Git et est créée séparément (ou via sealed-secrets).
Étape 12 — Établir une routine de vérification mensuelle
Le rituel qui paie consiste à dédier une heure par mois à vérifier que la chaîne de sauvegarde fonctionne réellement. La routine type comporte cinq étapes : afficher la liste des sauvegardes récentes (velero backup get), vérifier qu aucune n est en Failed, mesurer la taille cumulée du bucket, lancer une restauration de test sur un namespace jetable, et confirmer que les pods restaurés démarrent. Quinze minutes effectives par mois pour la sérénité d avoir une sauvegarde qui fonctionne.
Cette discipline simple distingue les environnements qui survivent réellement aux incidents de ceux qui croient seulement y survivre. Le premier mardi de chaque mois est une date naturelle pour cette routine, suffisamment fréquente pour détecter les dérives, suffisamment espacée pour ne pas devenir une corvée.