Sauvegarder et restaurer votre Persistent Volume avec les Volume Snapshots sur OVHcloud Managed Kubernetes
Découvrez comment sauvegarder et restaurer votre Persistent Volume avec les Volume Snapshots sur OVHcloud Managed Kubernetes
Dans ce tutoriel, nous utilisons les Volume Snapshots Kubernetes pour sauvegarder et restaurer des volumes persistants sur un cluster OVHcloud Managed Kubernetes.
Les Volume Snapshots sont une fonctionnalité Kubernetes passée en disponibilité générale (GA) avec Kubernetes 1.20.
Ils permettent de créer un « instantané » (snapshot) d'un volume persistant. Un snapshot représente une copie d'un volume à un instant donné. Un snapshot peut être utilisé soit pour réhydrater un nouveau volume (pré-rempli avec les données du snapshot), soit pour restaurer un volume existant à un état antérieur (représenté par le snapshot).
Avant de commencer
Ce tutoriel suppose que vous disposez déjà d'un cluster OVHcloud Managed Kubernetes opérationnel, ainsi que de connaissances de base sur son fonctionnement. Pour en savoir plus sur ces sujets, veuillez consulter le guide de démarrage rapide OVHcloud Managed Kubernetes Service.
Ce tutoriel suppose également que vous êtes familiarisé avec les Persistent Volumes Kubernetes. Vous devez également savoir comment les PV sont gérés sur le service OVHcloud Managed Kubernetes. Veuillez consulter le guide Persistent Volumes sur OVHcloud Managed Kubernetes.
En pratique
Mise en place
Dans ce guide, nous allons utiliser un exemple simple : un petit serveur web Nginx avec un PersistentVolume.
Créez un fichier nommé nginx-example-with-pv.yml avec le contenu suivant :
---
apiVersion: v1
kind: Namespace
metadata:
name: nginx-example
labels:
app: nginx
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nginx-logs
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-logs
persistentVolumeClaim:
claimName: nginx-logs
containers:
- image: nginx:1.7.9
name: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/var/log/nginx"
name: nginx-logs
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: LoadBalancer
Puis appliquez-le au cluster :
kubectl apply -f nginx-example-with-pv.yml
Info
Si vous regardez attentivement la partie deployment de ce manifeste, vous remarquerez 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 en écriture sur le Persistent Volume à un instant donné.
Attendez d'obtenir une IP externe :
kubectl -n nginx-example get svc nginx-service -w
Lorsque vous disposez d'une IP externe de Load Balancer, enregistrez-la :
export LB_IP=$(kubectl -n nginx-example get svc nginx-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
Puis effectuez quelques appels vers l'URL pour générer des logs d'accès :
Nous devons maintenant nous connecter au pod pour lire le fichier de logs et vérifier que nos logs sont bien écrits.
Récupérez d'abord le nom du pod Nginx en cours d'exécution :
export POD_NAME=$(kubectl get po -n nginx-example -o name)
Puis connectez-vous à celui-ci et consultez vos logs d'accès :
kubectl -n nginx-example exec $POD_NAME -c nginx -- cat /var/log/nginx/access.log
Info
Les Volume Snapshots fonctionnent avec toutes les Storage Classes, y compris les volumes chiffrés LUKS (csi-cinder-high-speed-luks, csi-cinder-classic-luks, csi-cinder-high-speed-gen2-luks). Le chiffrement est maintenu de façon transparente pendant les opérations de snapshot et de restauration.
Vous devriez obtenir un résultat semblable à celui-ci :
$ kubectl apply -f nginx-example-with-pv.yml
namespace/nginx-example created
persistentvolumeclaim/nginx-logs created
deployment.apps/nginx-deployment created
service/nginx-service created
$ kubectl -n nginx-example get svc nginx-service -w
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service LoadBalancer 10.3.28.41 <pending> 80:32675/TCP 4s
nginx-service LoadBalancer 10.3.28.41 <pending> 80:32675/TCP 91s
nginx-service LoadBalancer 10.3.28.41 135.125.XX.XXX 80:32675/TCP 91s
nginx-service LoadBalancer 10.3.28.41 135.125.XX.XXX 80:32675/TCP 95s
$ export LB_IP=$(kubectl -n nginx-example get svc nginx-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ echo $LB_IP
135.125.XX.XXX
$ curl -I $LB_IP
HTTP/1.1 200 OK
Server: nginx/1.7.9
Date: Mon, 26 Sep 2022 06:56:32 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 23 Dec 2014 16:25:09 GMT
Connection: keep-alive
ETag: "54999765-264"
Accept-Ranges: bytes
$ curl -I $LB_IP
HTTP/1.1 200 OK
Server: nginx/1.7.9
Date: Mon, 26 Sep 2022 06:56:33 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 23 Dec 2014 16:25:09 GMT
Connection: keep-alive
ETag: "54999765-264"
Accept-Ranges: bytes
$ export POD_NAME=$(kubectl get po -n nginx-example -o name)
$ echo $POD_NAME
pod/nginx-deployment-5bfc8c9f6f-zplsl
$ kubectl -n nginx-example exec $POD_NAME -c nginx -- cat /var/log/nginx/access.log
10.2.0.0 - - [26/Sep/2022:06:56:32 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.64.1" "-"
141.94.164.46 - - [26/Sep/2022:06:56:33 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.64.1" "-"
Créer un snapshot
Créez un VolumeSnapshot dans un fichier nginx-example-snapshot.yml avec le contenu suivant :
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: nginx-snapshot
namespace: nginx-example
spec:
volumeSnapshotClassName: csi-cinder-snapclass-in-use-v1
source:
persistentVolumeClaimName: nginx-logs
Puis appliquez-le :
kubectl apply -f nginx-example-snapshot.yml
Vous devriez obtenir un résultat semblable à celui-ci :
$ kubectl apply -f nginx-example-snapshot.yml
volumesnapshot.snapshot.storage.k8s.io/nginx-snapshot created
$ kubectl -n nginx-example get VolumeSnapshot
NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE
nginx-snapshot true nginx-logs 1Gi csi-cinder-snapclass-in-use-v1 snapcontent-131c751e-5cdb-4575-b0c0-538273c67d36 5m20s 5m20s
Simuler un sinistre
Simulons un scénario de sinistre, en supprimant les fichiers de logs de la PVC :
kubectl -n nginx-example exec $POD_NAME -c nginx -- rm /var/log/nginx/access.log
kubectl -n nginx-example exec $POD_NAME -c nginx -- ls -al /var/log/nginx/
Vous devriez obtenir un résultat semblable à celui-ci :
$ kubectl -n nginx-example exec $POD_NAME -c nginx -- rm /var/log/nginx/access.log
kubectl -n nginx-example exec $POD_NAME -c nginx -- ls -al /var/log/nginx/
total 24
drwxr-xr-x 3 root root 4096 Sep 26 07:10 .
drwxr-xr-x 1 root root 4096 Jan 27 2015 ..
-rw-r--r-- 1 root root 0 Sep 26 06:54 error.log
drwx------ 2 root root 16384 Sep 26 06:54 lost+found
Restaurer le volume
Pour restaurer un snapshot donné, vous devez supprimer la PVC d'origine puis la recréer à partir du snapshot.
Réduisez le déploiement à 0 réplique et supprimez la PVC d'origine :
kubectl -n nginx-example scale deployment/nginx-deployment --replicas=0
kubectl -n nginx-example delete pvc nginx-logs
Créez ensuite un fichier nginx-example-restore.yml avec le contenu suivant :
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nginx-logs
namespace: nginx-example
labels:
app: nginx
spec:
dataSource:
name: nginx-snapshot
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Puis appliquez-le :
kubectl apply -f nginx-example-restore.yml
Vérifiez que la PVC est restaurée :
kubectl -n nginx-example get pvc
Le volume doit avoir un statut égal à Bound. Vous pouvez maintenant restaurer le déploiement à sa valeur de réplique de 1, et attendre que le pod repasse à l'état Running :
kubectl -n nginx-example scale deployment/nginx-deployment --replicas=1
kubectl -n nginx-example get pods -w
Vous pouvez maintenant vérifier que le fichier access.log est de nouveau présent et que son contenu est toujours là :
export POD_NAME=$(kubectl get po -n nginx-example -o name)
echo $POD_NAME
kubectl -n nginx-example exec $POD_NAME -c nginx -- ls -al /var/log/nginx/
kubectl -n nginx-example exec $POD_NAME -c nginx -- cat /var/log/nginx/access.log
Vous devriez obtenir un résultat semblable à celui-ci :
$ kubectl -n nginx-example scale deployment/nginx-deployment --replicas=0
kubectl -n nginx-example delete pvc nginx-logs
deployment.apps/nginx-deployment scaled
persistentvolumeclaim "nginx-logs" deleted
$ vi nginx-example-restore.yml
$ kubectl apply -f nginx-example-restore.yml
persistentvolumeclaim/nginx-logs created
$ kubectl -n nginx-example get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nginx-logs Bound ovh-managed-kubernetes-dmhe43-pvc-d5c65ae2-e9fd-48a9-8c29-d69cdd464f59 1Gi RWO csi-cinder-high-speed 7s
$ kubectl -n nginx-example scale deployment/nginx-deployment --replicas=1
kubectl -n nginx-example get pods -w
deployment.apps/nginx-deployment scaled
NAME READY STATUS RESTARTS AGE
nginx-deployment-5bfc8c9f6f-m627t 0/1 ContainerCreating 0 0s
nginx-deployment-5bfc8c9f6f-m627t 0/1 ContainerCreating 0 7s
nginx-deployment-5bfc8c9f6f-m627t 1/1 Running 0 10s
$ export POD_NAME=$(kubectl get po -n nginx-example -o name)
$ echo $POD_NAME
pod/nginx-deployment-5bfc8c9f6f-m627t
$ kubectl -n nginx-example exec $POD_NAME -c nginx -- ls -al /var/log/nginx/
total 28
drwxr-xr-x 3 root root 4096 Sep 26 06:54 .
drwxr-xr-x 1 root root 4096 Jan 27 2015 ..
-rw-r--r-- 1 root root 181 Sep 26 06:56 access.log
-rw-r--r-- 1 root root 0 Sep 26 06:54 error.log
drwx------ 2 root root 16384 Sep 26 06:54 lost+found
$ kubectl -n nginx-example exec $POD_NAME -c nginx -- cat /var/log/nginx/access.log
10.2.0.0 - - [26/Sep/2022:06:56:32 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.64.1" "-"
141.94.164.46 - - [26/Sep/2022:06:56:33 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.64.1" "-"
Suppression (nettoyage)
À la fin, vous pouvez procéder au nettoyage en supprimant l'ensemble des éléments. Supprimez le namespace nginx-example :
kubectl delete namespace nginx-example
Aller plus loin
-
Pour une formation ou une assistance technique sur la mise en œuvre de nos solutions, contactez votre commercial ou consultez la page Professional Services pour obtenir un devis et faire analyser votre projet par nos experts.
-
Échangez avec notre communauté d'utilisateurs.