Volumes locaux

À partir du modèle suivant, créer un pod constitué de deux conteneurs. Basés sur busybox, ceux-ci vont nous permettre d'illustrer le fonctionnement des volumes partagés.

Nous allons commencer par un volume de type EmptyDir monté dans le /data/shared-storage sur chaque conteneur.

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
  labels:
    app: volume-test
spec:
  volumes:
    ... # volumes à partager
  containers:
    - name: busybox1
      image: busybox
      command: [ "/bin/sh", "-c", "--" ]
      args: ["trap : TERM INT; (while true; do sleep 1000; done) & wait"]
      volumeMounts:
        ... # montage du volume partagé dans le premier conteneur
    - name: busybox2
      image: busybox
      command: [ "/bin/sh", "-c", "--" ]
      args: ["trap : TERM INT; (while true; do sleep 2000; done) & wait"]
      volumeMounts:
        ... # montage du volume partagé dans le second conteneur
  • Appliquer le manifeste et vérifier la création.
  • La description du pod doit indiquer la présence du volume partagé
kubectl describe pod volume-test
Volumes:
  shared-storage:
    Type:    EmptyDir (a temporary directory that shares a pod's lifetime)
  • Nous pouvons exécuter un terminal à l'intérieur des deux conteneurs
kubectl exec -it volume-test -c busybox1 /bin/sh
kubectl exec -it volume-test -c busybox2 /bin/sh
  • Depuis le premier conteneur, créé un fichier à la racine
echo test1 > /test1.txt
  • Depuis le second conteneur, afficher les fichiers à la racine, rien de particulier ne doit apparaitre
  • Depuis le premier conteneur, créé un fichier dans /data/shared-storage/
echo test-shared1 > /data/shared-storage/shared1
  • Depuis le second conteneur, liste les fichiers dans le répertoire partagé
ls /data/shared-storage/
/data/shared-storage # ls
shared1
  • Nous allons tuer le second conteneur, ce qui va provoquer la création d'un nouveau conteneur pour prendre sa place
# Depuis l'intérieur de second conteneur
/ > kill 1
/ > command terminated with exit code 137
  • Après la recréation du conteneur, se connecter à l'intérieur.

Le fichier créé précédemment est-il toujours présent ?

Stockage distant

Nous allons manipuler les trois types de ressources qui permettent de monter des volumes distants dans un Pod :

  • les StorageClasses ;
  • les PersistentVolumes ;
  • les PersistentVolumeClaims ;

Les volumes distants se déclarent au niveau des Pods de la même manière que les volumes locaux. La différence étant qu'un volume distant est forcément attaché à une StorageClass.

Généralement, la StorageClass est fournie par l'administrateur de la plateforme et n'a pas besoin d'être créé par l'utilisateur. Nous allons cependant en créer une pour bien comprendre l'intéraction de tous les éléments.

Création et montage d'un PVC

Commençons par regarder notre StorageClass, celle-ci nous permettra de créer des PersistentVolumeClaim sans devoir spécifier les mêmes paramètres à chaque fois.

  • Vous disposez d'une StorageClass définie comme suit dans le cluster :
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: capacitive-fs
parameters:
  clusterID: 691e2997-9932-426f-be8e-ea633a02bb12
  csi.storage.k8s.io/controller-expand-secret-name: dtl-train-fs-secret
  csi.storage.k8s.io/controller-expand-secret-namespace: cephfs
  csi.storage.k8s.io/node-stage-secret-name: dtl-train-fs-secret
  csi.storage.k8s.io/node-stage-secret-namespace: cephfs
  csi.storage.k8s.io/provisioner-secret-name: dtl-train-fs-secret
  csi.storage.k8s.io/provisioner-secret-namespace: cephfs
  fsName: fast-distributed-fs
  mounter: kernel
  pool: dtl-train-cd-data
provisioner: cephfs.csi.ceph.com
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate

Grace à cette StorageClass, nous pouvons créer un PersistentVolumeClaim.

  • Créer le PVC selon le modèle suivant.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ceph-claim
  namespace: <votre namespace>
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 100Mi
  storageClassName: capacitive-fs
  • Après quelques secondes, la description du PVC doit indiqué que celui-ci est attaché à un volume persistant.
kubectl describe pvc ceph-claim
Name:          ceph-claim
...
Status:        Bound
Volume:        pvc-63318b64-bf5d-11e8-9a69-00505687a6c6
Annotations:   pv.kubernetes.io/bind-completed=yes
               pv.kubernetes.io/bound-by-controller=yes
               volume.beta.kubernetes.io/storage-provisioner=kubernetes.io/rbd
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      100Mi
Access Modes:  RWO
Events:
  Type    Reason                 Age   From                         Message
  ----    ------                 ----  ----                         -------
  Normal  ProvisioningSucceeded  15m   persistentvolume-controller  Successfully provisioned volume pvc-63318b64-bf5d-11e8-9a69-00505687a6c6 using kubernetes.io/rbd
  • Pour confirmer cela, nous pouvons afficher le volume persistant en question.
kubectl describe persistentvolume pvc-63318b64-bf5d-11e8-9a69-00505687a6c6
Name:            pvc-63318b64-bf5d-11e8-9a69-00505687a6c6                                     
...
Status:          Bound                                                                        
Claim:           apl/ceph-claim                                                               
Reclaim Policy:  Delete                                                                       
Access Modes:    RWO                                                                          
Capacity:        100Mi                                                                        
Source:                                                                                       
    Type:          RBD (a Rados Block Device mount on the host that shares a pod's lifetime)                                                     
    RBDImage:      kubernetes-dynamic-pvc-6333de5b-bf5d-11e8-8429-00505687593b                
    Keyring:       /etc/ceph/keyring                                                          
    SecretRef:     &{ceph-admin-secret }                                                      
    ReadOnly:      false                                                                      

Enfin, il ne nous reste plus qu'à créer un pod pour consommer ce volume persistant. Dans le cas d'un PV créé via un PersistentVolumeClaim comme c'est le cas ici, il suffit de monter le PVC comme un volume. Kubernetes gère alors pour nous le cycle de vie du provisionnement, les pods ne seront pas disponibles tant que le PVC ne disposera pas d'un PV attaché.

  • Créer un pod sur le modèle suivant.
apiVersion: v1
kind: Pod
metadata:
  name: volume-test
  labels:
    app: volume-test
spec:
  volumes:
    - name: claim-volume
      persistentVolumeClaim:
        claimName: <nom du pvc>
  containers:
    - name: busybox1
      image: busybox
      command: [ "/bin/sh", "-c", "--" ]
      args: ["trap : TERM INT; (while true; do sleep 1000; done) & wait"]
      volumeMounts:
        ... # monter le PVC déclaré comme volume plus haut
  • Après création, le volume partagé est utilisable depuis le Pod (nous pourrions vérifier de la même manière que pour les volumes emptyDir vus plus haut).

Suppression

La suppression des ressources persistantes est une opération délicate qui expose au risque de perte définitive de données. Nous allons observer les mécanismes offerts par Kubernetes pour protéger les volumes persistants de suppressions accidentelles.

PVC protection

La fonctionnalité "Storage Object in Use Protection" permet d'empêcher la suppression des volumes montés par des Pods.

  • Afficher la description du Pod créé précedemment
kubectl describe pod volume-test

Le résultat doit contenir le point de montage du conteneur ainsi qu'un évennement de montage du volume.

Containers:                                                                                                                                          
  busybox1:                                                                                                                                          
...                                                                                                                      
    Mounts:                                                                                                                                          
      /data/shared-volume from claim-volume (rw)                                                                                                     
...                                                                                                                                                    
Events:                                                                                                                                              
  Type    Reason                  Age   From                     Message                                                                             
  ----    ------                  ----  ----                     -------                                                                                                            
  Normal  SuccessfulAttachVolume  3s    attachdetach-controller  AttachVolume.Attach succeeded for volume "pvc-63318b64-bf5d-11e8-9a69-00505687a6c6" 
  • Afficher la description du PVC.
kubectl describe pvc <nom du pvc>

Le résultat doit contenir une ligne telle que ci-dessous.

Finalizers:    [kubernetes.io/pvc-protection]

Cette ligne indique que la protection des volumes déjà montés est activée.

  • Maintenant que nous avons vérifié la bonne activation de la protection, nous allons supprimer le PVC.
kubectl delete pvc <nom du pvc>
kubectl get pvc

Le PVC doit maintenant se trouver dans l'état Terminating

NAME         STATUS        VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ceph-claim   Terminating   pvc-63318b64-bf5d-11e8-9a69-00505687a6c6   100Mi      RWO            ceph           1h

Le PVC restera dans cet état tant qu'il sera monté dans un Pod. - Supprimons donc notre Pod

kubectl delete pod <nom du pod>

Immédiatement après la suppression du Pod, le PVC et le PV sont supprimés.

> kubectl get pvc
No resources found.

> kubectl get pv
No resources found.

Reclaim policy

L'attribut reclaim policy d'un PersistentVolume définit l'action à mener lors de la suppresion du PersistentVolumeClaim qui l'a provisionné dynamiquement.

La reclaim policy par défaut est Delete, ce qui signifie qu'à la suppression du PVC, le PV sera également supprimé.

Il est possible de modifier cette valeur pour Retain, afin de conserver le PV intact.

  • Recréer le PVC que nous venons de supprimer.
  • Attendre le provisionnement du PV correspondant.
  • Afficher la description du PV correspondant.
kubectl get pv <identifiant du pv créé>
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM            STORAGECLASS   REASON    AGE
pvc-96dd4fc0-bf6d-11e8-9a69-00505687a6c6   100Mi      RWO            Delete           Bound     ceph-claim       ceph                     25s

Comme prévu, la valeur de reclaim policy est Delete

  • Modifier la valeur de reclaim policy
kubectl edit pv <identifiant du pv>

Nous pouvons maintenant supprimer le PVC et constater que le PV n'est pas supprimé automatiquement.

kubectl delete pvc <nom du pvc>
kubectl get pv

Le statut du PV passe à Released

NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM            STORAGECLASS   REASON    AGE
pvc-96dd4fc0-bf6d-11e8-9a69-00505687a6c6   100Mi      RWO            Retain           Released   ceph-claim       ceph                     4m