Renseignez votre domaine et vos adresses : les commandes et les fichiers de la page s'adaptent. Les valeurs restent dans votre navigateur et ne nous sont jamais transmises.
01Deux filets, deux usages
| Couche | Outil | Fréquence | Rétention | Sert à |
|---|---|---|---|---|
| Objets Kubernetes | Velero | Chaque nuit | 30 jours | Restaurer une application ou un namespace |
| Volumes Ceph | Velero, snapshot CSI puis copie Kopia | Avec les objets | 30 jours | Récupérer les données d'une application |
| etcd | talos-backup, chiffré age | Toutes les 6 heures | 14 jours | Reconstruire un cluster perdu |
| VM et configuration | OpenTofu et Git | À chaque changement | Historique Git | Recréer l'infrastructure |
Velero répond à « j'ai supprimé mon application » ; etcd répond à « le cluster n'existe plus ». Les deux partent vers un stockage S3 situé hors du cluster Proxmox : une sauvegarde rangée dans le Ceph qu'elle protège ne protège pas grand-chose. Notre page stratégie de sauvegarde revient sur ce principe.
02Un S3 hors du cluster
Le stockage est un serveur de sauvegarde séparé, avec un pool ZFS. Nous y avons installé Garage, un serveur S3 léger écrit en Rust : un binaire, un service systemd, un dataset ZFS compressé avec un quota. Caddy le publie en HTTPS et filtre les adresses : seules l'IP de sortie des clusters et le bastion passent.
s3.k8s.exemple.fr, etcd-demo.s3.k8s.exemple.fr, etcd-mgmt.s3.k8s.exemple.fr { @autorise remote_ip 203.0.113.35 198.51.100.10 handle @autorise { reverse_proxy 127.0.0.1:3900 } respond 403 }
garage bucket create velero-demo garage bucket create etcd-demo garage key create k8s-demo garage bucket allow --read --write velero-demo --key k8s-demo garage bucket allow --read --write etcd-demo --key k8s-demo
Chaque cluster a sa clé, qui n'ouvre que ses deux buckets : un cluster compromis ne peut pas effacer les sauvegardes de l'autre. Une règle de cycle de vie supprime les snapshots etcd de plus de 14 jours.
garage key create affiche la clé secrète. Nous l'avons appris de la façon habituelle : une clé apparue en clair dans un terminal, donc dans un historique, est une clé à renouveler. Le playbook capture désormais la sortie et l'écrit directement dans SOPS.
La version de talos-backup utilisée ignore l'option qui force l'adressage des buckets par chemin et appelle etcd-demo.s3.k8s.exemple.fr. Garage sait servir ce mode (option root_domain), Caddy reçoit les noms des buckets concernés, et un enregistrement DNS générique couvre le tout.
03Velero : objets et volumes
Velero sauvegarde chaque nuit les objets Kubernetes. Pour les volumes, il demande un instantané CSI à ceph-csi, puis son data mover copie le contenu de l'instantané vers S3 avec Kopia : la sauvegarde ne dépend plus du Ceph d'origine.
configuration:
features: EnableCSI
defaultSnapshotMoveData: true
backupStorageLocation:
- name: default
provider: aws
bucket: velero-demo
default: true
config:
region: garage
s3ForcePathStyle: "true"
s3Url: https://s3.k8s.exemple.fr
checksumAlgorithm: ""
snapshotsEnabled: false # pas de VolumeSnapshotLocation : on passe par CSI
deployNodeAgent: true # copie le contenu des snapshots vers S3 (Kopia)
schedules:
quotidienne:
schedule: "CRON_TZ=Europe/Paris 30 0 * * *"
template:
ttl: 720h
snapshotMoveData: true
La ligne checksumAlgorithm: "" n'est pas une coquetterie : les versions récentes
du SDK AWS ajoutent par défaut une somme de contrôle que les S3 compatibles n'acceptent pas
tous. La clé S3 arrive dans un secret créé depuis SOPS, jamais dans les valeurs Helm.
04talos-backup : etcd chiffré
etcd est la mémoire du cluster : objets, secrets, état de tout. Le perdre, c'est l'amnésie totale. talos-backup demande un instantané à l'API Talos, le chiffre avec une clé publique age et l'envoie dans S3. La clé privée correspondante est dans SOPS, et nulle part ailleurs sur la plateforme.
# Un compte qui ne peut faire qu'une chose : sauvegarder etcd apiVersion: talos.dev/v1alpha1 kind: ServiceAccount metadata: name: talos-backup-secrets namespace: system-upgrade spec: roles: [os:etcd:backup] --- apiVersion: batch/v1 kind: CronJob metadata: name: talos-backup namespace: system-upgrade spec: schedule: "15 */6 * * *" timeZone: Europe/Paris concurrencyPolicy: Forbid jobTemplate: spec: backoffLimit: 2 template: spec: restartPolicy: Never # garde le pod en échec, et ses journaux containers: - name: talos-backup image: ghcr.io/siderolabs/talos-backup:v0.1.0-beta.3 envFrom: # clés S3, bucket, nom du cluster, clé publique age - secretRef: { name: talos-backup-s3 } env: - { name: CUSTOM_S3_ENDPOINT, value: "https://s3.k8s.exemple.fr" }
Le rôle os:etcd:backup doit être autorisé côté Talos, dans le document
KubeTalosAPIAccessConfig vu au chapitre 02, pour le namespace concerné.
La version de talos-backup disponible à la rédaction ignore plusieurs options documentées : l'adressage par chemin, la compression, et l'un des deux noms de variable de la clé age. Nous fournissons la clé sous les deux noms, servons les buckets en sous-domaine, et acceptons des snapshots non compressés (quelques dizaines de Mo). Autre leçon : avec restartPolicy: OnFailure, un job en échec supprime ses pods, et l'on enquête sans journaux.
05Restaurer avec Velero
Le test que nous faisons, et que nous vous conseillons de refaire régulièrement : restaurer un namespace dans un autre namespace, pour ne rien écraser.
velero backup get velero restore create test-restauration \ --from-backup velero-quotidienne-20261028003000 \ --include-namespaces boutique \ --namespace-mappings boutique:boutique-restore \ --wait velero restore describe test-restauration kubectl -n boutique-restore get pods,pvc
Les volumes sont recréés dans Ceph puis remplis depuis S3. Pour remplacer la production, on
supprime le namespace d'origine et l'on restaure sans --namespace-mappings.
Une copie de volume prise à chaud est cohérente « comme après une coupure de courant ». Une base de données s'en remet en général, mais « en général » n'est pas une politique de sauvegarde : pour une vraie base, ajoutez des hooks Velero qui figent les écritures, ou la sauvegarde native de la base vers S3.
06Reconstruire depuis etcd
Le scénario du pire : le cluster a disparu, VM comprises. La procédure tient en quatre étapes, et nous la tenons pour écrite tant qu'elle n'a pas été chronométrée lors d'un exercice de reprise.
- Récupérer et déchiffrer le dernier snapshot.
- Recréer les VM avec OpenTofu, sans laisser Talos amorcer un etcd vide.
- Amorcer le premier control plane depuis le snapshot ; les autres le rejoignent.
- Relancer le bootstrap du cluster pour réaligner le socle, puis restaurer les volumes avec Velero si besoin.
SECRETS=secrets/secrets.sops.yaml
OBJ=$(rclone lsf -R --files-only s3:etcd-demo | tail -1)
rclone cat "s3:etcd-demo/$OBJ" \
| age -d -i <(sops -d --extract '["etcd_backup"]["age_private"]' $SECRETS) \
> db.snapshot
talosctl -n 10.20.1.11 bootstrap --recover-from=./db.snapshot
# le snapshot contient en clair tous les secrets du cluster
shred -u db.snapshot
La moitié du travail a déjà été vérifiée : nous déchiffrons régulièrement un snapshot et comptons les clés qu'il contient. Une archive qui ne se déchiffre pas, mieux vaut l'apprendre un mardi après-midi qu'un dimanche à 3 heures.
07Liste de contrôle
| Point | Vérification | Fait |
|---|---|---|
| S3 | Hors du cluster Proxmox, filtré par adresse, une clé par cluster | ☐ |
| Secrets | Clés S3 et clé privée age dans SOPS, copie de la clé age hors du bastion | ☐ |
| Velero | velero backup get : sauvegardes récentes, état Completed | ☐ |
| Volumes | Data mover actif, VolumeSnapshotClass ceph-rbd présente | ☐ |
| etcd | Jobs talos-backup Complete, objets récents dans le bucket | ☐ |
| Test | Une restauration Velero dans un namespace de test, chaque trimestre | ☐ |
| Test | Un snapshot etcd déchiffré, chaque mois | ☐ |
| Reprise | Exercice complet de reconstruction depuis etcd, chronométré | ☐ |
| Alertes | Un échec de sauvegarde réveille quelqu'un (page observabilité, à venir) | ☐ |
Ce chapitre clôt la mise en place. Il reste deux briques, que nous traiterons dans une page à part : l'observabilité, pour qu'un échec de nuit ne passe plus inaperçu, et la sécurité des accès, avec authentification unique et double facteur. La plateforme est déjà prête à accueillir des développeurs : leur guide les attend.
Une plateforme Kubernetes, sans y laisser vos nuits
Nous concevons, montons et exploitons des plateformes Kubernetes sur Proxmox VE pour des équipes qui veulent se consacrer à leur code : mises à jour nocturnes, sauvegardes testées, déploiement en GitOps. Reprise d'un cluster existant, plateforme clé en main ou astreinte : nous intervenons au forfait comme au long cours.