For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/fr/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/fr/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/fr/guides/public-cloud/containers-orchestration/managed-kubernetes/backing-up-cluster-velero.md.

Sauvegarder un cluster Managed Kubernetes OVHcloud avec Velero

Voir en Markdown

Découvrez comment sauvegarder un cluster Managed Kubernetes OVHcloud avec Velero, y compris les volumes persistants

Objectif

Dans ce tutoriel, nous utilisons Velero pour sauvegarder et restaurer un cluster Managed Kubernetes OVHcloud.

Velero est un outil Open Source permettant de sauvegarder et restaurer en toute sécurité, d'effectuer une reprise après sinistre et de migrer les ressources d'un cluster Kubernetes.

Pour la sauvegarde de la configuration du cluster, nous utilisons le Swift Object Storage de notre Public Cloud avec l'API Swift S3 comme backend de stockage pour Velero. Velero utilise le protocole Amazon S3 pour stocker les sauvegardes du cluster sur un stockage objet compatible S31.

Pour la sauvegarde des volumes persistants, nous utilisons la prise en charge des snapshots CSI par Velero, qui permet à Velero de sauvegarder et de restaurer les volumes gérés par CSI via les API Kubernetes CSI Snapshot Beta.

Avant de commencer

Ce tutoriel suppose que vous disposez déjà d'un cluster Managed Kubernetes OVHcloud fonctionnel, ainsi que de connaissances de base sur son fonctionnement. Pour en savoir plus sur ces sujets, consultez la documentation Déployer une application Hello World.

En pratique

Créer le bucket Object Storage pour Velero

Velero a besoin d'un bucket compatible S3 comme backend de stockage pour stocker les données de votre cluster. Dans cette section, vous allez créer votre bucket S3 sur OVHcloud Object Storage.

Préparer votre environnement de travail

Avant de créer votre bucket Object Storage, vous devez :

Définir les variables d'environnement OpenStack

Vous devriez maintenant avoir accès à votre fichier RC OpenStack, avec un nom de fichier du type <user_name>-openrc.sh, ainsi qu'au nom d'utilisateur et au mot de passe de votre compte OpenStack.

Définissez les variables d'environnement en sourçant le fichier RC OpenStack :

source <user_name>-openrc.sh

Le shell vous demandera votre mot de passe OpenStack :

$ source <user_name>-openrc.sh
Please enter your OpenStack Password for project <project_name> as user <user_name>:

Créer les identifiants EC2

Les tokens Object Storage sont différents ; vous avez besoin de 2 paramètres (access et secret) pour générer un token Object Storage.

Ces identifiants seront stockés en toute sécurité dans Keystone. Pour les générer avec le client python-openstack :

openstack ec2 credentials create

Notez les paramètres access et secret :

$ openstack ec2 credentials create
+------------+----------------------------------------------------------------------------------------------------------------------------+
| Field      | Value
+------------+----------------------------------------------------------------------------------------------------------------------------+
| access     | 5a4d8b8d88104123a862c527ede5a3d3
| links      | {u'self': u'https://auth.cloud.ovh.net/v3/users/xxxx/credentials/OS-EC2/xxxx'}
| project_id | xxxx
| secret     | xxxx
| trust_id   | None
| user_id    | xxxx
+------------+----------------------------------------------------------------------------------------------------------------------------+

Configurer le client awscli

Installez le client awscli :

pip3 install awscli

Créez le fichier d'identifiants dans ~/.aws/credentials :

[default]
aws_access_key_id=`<AWS_ACCESS_KEY_ID>`
aws_secret_access_key=`<AWS_SECRET_ACCESS_KEY>`

<AWS_ACCESS_KEY_ID> et <AWS_SECRET_ACCESS_KEY> sont les identifiants Object Storage access et secret générés à l'étape précédente.

Complétez et enregistrez la configuration dans ~/.aws/config :

[plugins]
endpoint = awscli_plugin_endpoint

[default]
region = <s3_region>
endpoint_url = https://s3.<s3_region>.io.cloud.ovh.net/
Info

Remplacez s3_region par la région Public Cloud sans les chiffres (par exemple : gra, sbg, bhs)

Vous pouvez tester votre configuration en exécutant cette commande :

aws --profile default s3 ls
Info

Si votre fichier .aws/config ne contient qu'un seul profil, l'argument --profile default est facultatif.

Créer un bucket Object Storage pour Velero

Créez un nouveau bucket :

aws s3 mb s3://velero-s3
Info

Assurez-vous que le nom de votre bucket est suffisamment spécifique, sous peine d'obtenir une erreur BucketAlreadyExists, car les noms de bucket doivent être uniques parmi tous les utilisateurs S3.

Listez vos buckets :

aws s3 ls

Installer Velero

Nous vous recommandons fortement d'utiliser une release officielle de Velero. Les archives tar de chaque release contiennent le client en ligne de commande velero. Décompressez l'archive et ajoutez-la à votre PATH.

Installez Velero, y compris tous les prérequis, dans le cluster et démarrez le déploiement. Cela créera un namespace nommé velero, et y placera un déploiement nommé velero.

Exemple pour velero v1.16.2 :

velero install \
  --features=EnableCSI \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.12.2 \
  --bucket <your bucket name> \
  --secret-file ~/.aws/credentials \
  --backup-location-config region=`<s3_region>`,s3ForcePathStyle="true",s3Url=https://s3.`<s3_region>`.io.cloud.ovh.net,checksumAlgorithm="" \
  --snapshot-location-config region=`<s3_region>`,enableSharedConfig=true
Info

Remplacez s3_region par la région Public Cloud sans les chiffres (par exemple : gra, sbg, bhs).

Info

Depuis la version 1.14, le plugin-for-csi est intégré à Velero. Pour mettre à niveau une version plus ancienne, suivez les notes de mise à niveau : Upgrade-to-1.14. Consultez ces liens pour vérifier la compatibilité des plugins de Velero : velero-plugin-for-aws et velero-plugin-for-csi.

Pour permettre à Velero de réaliser des Volume Snapshots, nous devons déployer une nouvelle VolumeSnapshotClass. Créez un fichier velero-snapclass.yaml avec le contenu suivant :

apiVersion: snapshot.storage.k8s.io/v1
deletionPolicy: Delete
driver: cinder.csi.openstack.org
kind: VolumeSnapshotClass
metadata:
  name: csi-cinder-snapclass-in-use-v1-velero
  labels:
    velero.io/csi-volumesnapshot-class: "true"
parameters:
  force-create: "true"

Appliquez la nouvelle classe :

kubectl apply -f velero-snapclass.yaml

Dans notre exemple, le résultat ressemble à ceci :

$ kubectl apply -f velero-snapclass.yaml

volumesnapshotclass.snapshot.storage.k8s.io/csi-cinder-snapclass-in-use-v1-velero created

$ kubectl get volumesnapshotclass --show-labels
NAME                                    DRIVER                     DELETIONPOLICY   AGE   LABELS
csi-cinder-snapclass-in-use-v1          cinder.csi.openstack.org   Delete           50d   mks.ovh/version=1.31.6-2
csi-cinder-snapclass-in-use-v1-velero   cinder.csi.openstack.org   Delete           82m   velero.io/csi-volumesnapshot-class=true
csi-cinder-snapclass-v1                 cinder.csi.openstack.org   Delete           50d   mks.ovh/version=1.31.6-2

Vérifier que Velero fonctionne sans volumes persistants

Pour vérifier que Velero fonctionne correctement, testons avec un exemple de déploiement :

Copiez le code suivant dans un fichier nginx-example-without-pv.yml :

---
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-example
  labels:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: nginx-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx:1.27.3
          name: nginx
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: my-nginx
  namespace: nginx-example
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx
  type: ClusterIP

Déployez-le sur votre cluster :

kubectl create -f nginx-example-without-pv.yml

Vérifiez que les Pods ont bien été créés :

kubectl get pod -n nginx-example
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-7bfdb48f65-pz7v4   1/1     Running   0          65s
nginx-deployment-7bfdb48f65-x7mnf   1/1     Running   0          65s

Créez une sauvegarde du namespace :

Info

Depuis Velero 1.14, les CSI VolumeSnapshots sont utilisés par défaut pour les volumes persistants. Le flag --snapshot-move-data n'est plus nécessaire pour les volumes gérés par CSI et peut être omis sans risque. Il n'est requis que pour les volumes non-CSI sauvegardés avec Restic.

velero backup create nginx-backup --include-namespaces nginx-example --wait

Vérifiez que la sauvegarde est terminée :

velero get backups
NAME           STATUS      ERRORS   WARNINGS   CREATED                          EXPIRES   STORAGE LOCATION   SELECTOR
nginx-backup   Completed   0        0          2025-08-27 17:25:13 +0200 CEST   29d       default            <none>
Info

Attendez que le statut soit égal à Completed.

Simulez un sinistre :

kubectl delete namespace nginx-example
namespace "nginx-example" deleted

Restaurez le namespace supprimé :

velero restore create --from-backup nginx-backup
...

Vérifiez que la restauration s'est bien déroulée :

velero restore  get
NAME                          BACKUP         STATUS      STARTED                          COMPLETED                        ERRORS   WARNINGS   CREATED                          SELECTOR
nginx-backup-20250827173400   nginx-backup   Completed   2025-08-27 17:34:01 +0200 CEST   2025-08-27 17:34:03 +0200 CEST   0        1          2025-08-27 17:34:01 +0200 CEST   `<none>`

Vous pouvez constater que les ressources ont bien été recréées comme attendu :

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   2/2     2            2           8m6s

NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/my-nginx   ClusterIP   10.3.40.25   `<none>`        80/TCP    8m6s

NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-7bfdb48f65-pz7v4   1/1     Running   0          8m7s
pod/nginx-deployment-7bfdb48f65-x7mnf   1/1     Running   0          8m6s

Avant de continuer, nettoyez le namespace nginx-example :

kubectl delete namespace nginx-example

Vérifier que Velero fonctionne avec des volumes persistants

Info

Node Agents (Restic) : les node agents sont principalement utilisés pour les sauvegardes au niveau fichier ou pour les volumes persistants qui ne sont pas gérés par CSI.

Pour les volumes persistants gérés via CSI (comme avec le Managed Kubernetes OVHcloud), les CSI VolumeSnapshots constituent la méthode recommandée. Dans ce cas, il n'est pas nécessaire de déployer de Node Agents, car les sauvegardes et restaurations sont gérées nativement par le mécanisme de snapshot CSI.

Pour vérifier que Velero fonctionne correctement avec les Volume Snapshots des volumes persistants, testons avec un exemple de déploiement :

Copiez le code suivant dans un fichier nginx-example-with-pv.yml :

---
apiVersion: v1
kind: Namespace
metadata:
  name: nginx-example
  labels:
    app: nginx
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nginx-html
  namespace: nginx-example
  labels:
    app: nginx
spec:
  storageClassName: csi-cinder-high-speed
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: nginx-example
spec:
  strategy:
    type: Recreate
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      volumes:
        - name: nginx-html
          persistentVolumeClaim:
            claimName: nginx-html
      containers:
        - image: nginx:1.27.3
          name: nginx
          ports:
            - containerPort: 80
          volumeMounts:
            - mountPath: /usr/share/nginx/html
              name: nginx-html
              readOnly: false
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx
  name: nginx-service
  namespace: nginx-example
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    app: nginx
  type: ClusterIP
Info

Portez attention à la partie déploiement de ce manifeste : vous verrez que nous avons défini un .spec.strategy.type. Il spécifie la stratégie utilisée pour remplacer les anciens Pods par de nouveaux, et nous l'avons défini sur Recreate, afin que tous les Pods existants soient supprimés avant que de nouveaux ne soient créés.

Nous procédons ainsi car la Storage Class que nous utilisons, csi-cinder-high-speed, ne prend en charge que le mode ReadWriteOnce : nous ne pouvons donc avoir qu'un seul pod écrivant sur le volume persistant à un instant donné.

Déployez-le sur le cluster :

kubectl create -f nginx-example-with-pv.yml

Créez un fichier index.html :

kubectl -n nginx-example exec -it deploy/nginx-deployment -- sh -c 'echo hello world > /usr/share/nginx/html/index.html'
kubectl -n nginx-example exec -it deploy/nginx-deployment --  ls -lh /usr/share/nginx/html
total 20K
-rw-r--r-- 1 root root  12 Aug 27 15:53 index.html
drwx------ 2 root root 16K Aug 27 15:51 lost+found

Vérifiez que le serveur web répond comme attendu :

kubectl -n nginx-example port-forward svc/nginx-service 8080:80 > /dev/null&
curl 0.0.0.0:8080
hello world

Nous pouvons maintenant demander à velero de réaliser la sauvegarde du namespace :

Info

Rappel : --snapshot-move-data n'est pas nécessaire pour les volumes gérés par CSI. Il a été retiré de la commande ci-dessous.

velero backup create nginx-backup-with-pv --include-namespaces nginx-example --wait

Vérifiez que la sauvegarde s'est terminée avec succès :

velero backup get nginx-backup-with-pv
NAME                   STATUS                       ERRORS   WARNINGS   CREATED                          EXPIRES   STORAGE LOCATION   SELECTOR
nginx-backup-with-pv   Completed   0        0          2025-08-27 18:03:09 +0200 CEST   29d       default            `<none>`

Décrivez la sauvegarde pour confirmer que les volumesnapshots CSI ont bien été inclus dans la sauvegarde :

velero describe backup nginx-backup-with-pv --details --features=EnableCSI

Simulez un sinistre :

kubectl delete namespace nginx-example

Restaurez le namespace supprimé :

velero restore create --from-backup nginx-backup-with-pv --wait

Vérifiez que la restauration s'est bien déroulée :

kubectl get all -n nginx-example

Vérifiez que le serveur web répond comme attendu :

kubectl -n nginx-example port-forward svc/nginx-service 8080:80 > /dev/null&
curl 0.0.0.0:8080
hello world

Le contenu du fichier a bien été restauré !

Planifier des sauvegardes avec Velero

Avec Velero, vous pouvez planifier des sauvegardes régulières, une bonne solution pour la reprise après sinistre.

Dans ce guide, vous allez créer une ressource Velero schedule qui créera des sauvegardes régulières.

Copiez le code suivant dans un fichier schedule.yml :

apiVersion: velero.io/v1
kind: Schedule
metadata:
  name: daily-snapshot
  namespace: velero
spec:
  schedule: '15 */1 * * *' # Every hour at hh:15
  template:
    defaultVolumesToRestic: false
    includedNamespaces:
    - nginx-example
    ttl: 168h0m0s # Keep the backup 7 days
    storageLocation: default

Appliquez-le sur le cluster :

kubectl apply -f schedule.yml

Vérifiez que la planification a bien été créée :

velero schedule get

Attendez quelques minutes et vérifiez qu'une sauvegarde a été créée automatiquement :

velero backup get

Vous devriez obtenir un résultat comme celui-ci :

$ velero schedule get
NAME             STATUS    CREATED                          SCHEDULE     BACKUP TTL   LAST BACKUP   SELECTOR
daily-snapshot   Enabled   2024-06-17 12:32:01 +0200 CEST   15 0 * * *   168h0m0s     n/a           `<none>`

$ velero backup get
NAME                            STATUS      ERRORS   WARNINGS   CREATED                          EXPIRES   STORAGE LOCATION   SELECTOR
daily-snapshot-20240617111318   Completed   0        0          2024-06-17 13:15:18 +0200 CEST   6d        default            `<none>`
nginx-backup                    Completed   0        0          2024-06-17 12:11:23 +0200 CEST   29d       default            `<none>`
nginx-backup-with-pv            Completed   0        0          2024-06-17 12:25:34 +0200 CEST   29d       default            `<none>`

Suppression (nettoyage)

Nettoyez le namespace nginx-example :

kubectl delete namespace nginx-example

Nettoyez la planification velero :

velero schedule delete daily-snapshot

Nettoyez les sauvegardes velero existantes :

velero backup delete nginx-backup
velero backup delete nginx-backup-with-pv

Aller plus loin

Vous disposez maintenant d'un Velero fonctionnel sur votre cluster.
Consultez la documentation officielle de Velero pour apprendre à l'utiliser, notamment la planification des sauvegardes, l'utilisation des hooks pre- et post-backup, et d'autres sujets.

  • Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur ce lien pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l’équipe Professional Services.

Échangez avec notre communauté d'utilisateurs.

1 : S3 est une marque déposée appartenant à Amazon Technologies, Inc. Les services de OVHcloud ne sont pas sponsorisés, approuvés, ou affiliés de quelque manière que ce soit.

Cette page vous a-t-elle aidé ?