[k8s] Les différentes méthodes de Stockage de Données

<<< Chap 9 | Sommaire | Chap 11>>>

Chap. 10 Les différentes méthodes de Stockage de Données

I. Différences entre Conteneurs et Machines Virtuelles

Du point de vue d’un système hôte linux, voici ce que représente un conteneur.

  • Forme de virtualisation qui, contrairement à une virtualisation matérielle (virtualisation), se fait au niveau de l’OS/Application (conteneurisation)
  • Un conteneur n’est pas une machine virtuelle, mais juste un autre processus du système hôte
  • Un conteneur est une « implémentation avancée du mécanisme de « chroot »[1]

De ce fait, il n’y a pas de système d’exploitation installé dans un conteneur.

  • Seuls les programmes nécessaires pour faire tourner ses applications y sont présentes. Et ces applications sont dépendantes des resources de l’hôte (OS denpendencies).

  • Chaque conteneur possède son propre répertoire racine et ses propres processus, isolés du reste du système (jail) – cf. exercice vers la fin de ce chapitre

Il est possible d’installer un conteneur directement sur une machine physique, à condition que la machine hôte tourne avec un noyau linux, et quelque soit la distribution. Vous pouvez par exemple, monter un cluster kubernetes avec des Raspberry-Pi.

Cependant, l’utilisation de machines virtuelles peut être indispensable si:

  • La machine hôte ne tourne pas sous linux
    Puisque les programmes requis par les conteneurs risquent de ne pas être compatibles avec ceux de l’hôte.
  • Le système hôte utilise une version incompatible du noyau linux
    Certaines versions particulières de bibilothèques et binaires, nécessaire au bon fonctionnement du conteneur peuvent ne pas être présentes dans le noyau de l’hôte. Par exemple, avec une vieille distribution, vous ne pouvez pas faire tourner un conteneur installé avec des programmes plus récents.

II. Espace disque

Les méthodes pour présenter un espace disque aux conteneurs sont,

  • Bind-mounts
    Utilisé pour partager des fichiers entre le machine hôte et ses conteneurs via la méthode de « mount« . L’option de « bind » (lier) associé au « mount », permet de protéger les fichiers sources contre toutes modifications à partir de ces conteneurs.
  • tmpfs mounts
    Fichiers temporaires du conteneur, directement monté à partir de la mémoire physique du l’hôte.
  • Volumes
    Répertoires dédiés à chacun des conteneurs, et qui seront créés automatiquement s’ils n’existent pas.  Ces répertoires peuvent se trouver sur les machines hôtes respectifs au conteneurs, ou sur un serveur de stockage.

Image tirée du « Manage data in Docker »

Parmis toutes ces méthodes, l’utilisation des Volumes comme système de stockage de données, est celle préconisée par les équipes de docker et kubernetes. Cette méthode a  pour avantage d’être supportée par des systèmes d’exploitation autres que linux.

Bind-mountet tmpfs sont généralement utilisés pour des tâches spécifiques dans le conteneur.
Le premier est généralement utilisé pour la population du contenu des fichiers hosts de chaque conteneur, tandis que le second peut servir à stocker temporairements des données sensibles, qui seront détruites au redémarrage du conteneur. Les programmes df -h et findmnt peuvent vous fournir un liste de fichiers montés par ces conteneurs.

Pour information, kubelet s’occupe de gérer la création des fichiers /etc/{resolv.conf,hostname,hosts} sur chacun des conteneurs, pour éviter les problèmes de type écriture directe sur la machine hôte[1], dans les fichiers correspondants.

III. Stockage de données

3.1 Système de fichier

Depuis le début de cette série d’articles, je vous ai présenté des conteneurs utilisant un système de fichiers pour présenter les espaces de disque aux conteneurs (voir chap 4 concernant l’exemple ci-dessous).

apiVersion: v1
kind: Pod
metadata:
  name: pingtest01
spec:
  containers:
  - name: pod1
    image: docker.io/centos/tools:latest
    command:
    - /sbin/init

Le problème avec ce type de stockage est que, les modifications y apportées (ajout ou suppression de données) seraient perdues au redémarrage du conteneur. Et c’est là qu’entre en jeu le système de Volume pour y remédier.

3.2 Volumes

Dans le Chap 8, je vous ai présenté des Pods multi-conteneurs utilisant un Volume de type emptyDir, qui peut être partagé entre plusieurs conteneurs du même pod.

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-sidecar
  labels:
    app: pod-with-sidecar
spec:
  containers:
  # Log service
  - name: sidecar-container
    image: alpine:latest
    command: ["/bin/sh"]
    args: ["-c", "while true; do date >> /var/log/index.html; sleep 5;done"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log

  # Web server
  - name: app-container
    image: nginx:latest
    ports:
      - containerPort: 80
    volumeMounts:
    - name: shared-logs
      mountPath: /usr/share/nginx/html

# Shared volume
  volumes:
  - name: shared-logs
    emptyDir: {}

L’utilisation d’un système stockage partagé de type « Volumes » est précisé dans le fichier yaml avec justement l’ajout du mot clé volumes. Pour y accéder, chaque conteneur doit préciser le chemin d’accès avec volumeMounts.

Pour que le  même volume soit accessible à tous les conteneurs, ces derniers doivent utiliser comme nom du volume à monter, celui du volume partagé. Ensuite, ajouter le chemin où monter ce volume avec l’option mountPath dans le conteneur.

3.3 Les différents types de volumes

Voici une liste non exhaustive des différents types de volumes supportés par kubernetes. Connectez-vous sur la page officielle, pour avoir la liste complète à jour.

  • Local storage
    Un volume local représente un périphérique de stockage local monté tel un disque, une partition ou un dossier.
  • hostPath
    Un volume hostPath monte un fichier ou un dossier à l’intérieur d’un Pod, depuis le système de fichiers de l’hôte.
  • nfs
    Un volume nfs permet un partage NFS (Network File System) pour être monté dans un Pod.
  • persistentVolumeClaim
    Un volume persistentVolumeClaim est utilisé pour monter un PersistentVolume dans un Pod.
  • emptyDir
    Un volume emptyDir est le type de volume créé lorsqu’un Pod est assigné pour la première fois à un Node (nœud), et existe aussi longtemps que le Pod s’exécute sur ce nœud. Comme le nom l’indique, le volume est initialement vide.
  • configMap
    La ressource configMap fournit un moyen d’injecter des données de configuration dans les Pods.
  • secrets
    Un volume secret est utilisé pour fournir des informations sensibles, comme des mots de passe, aux Pods.
  • Cloud storage
    AWS, Microsoft Azure, Google Cloud, etc.
  • etc.

Une petite note concernant les fichiers et dossiers, sous linux/unix tout est fichiers.

3.4 Exercices

Sur la page de kubernetes, il vous est proposé un exercice pour vérifier la consistance de données ajoutées ou modifiées dans un volume type emptyDir.

Noter que le programme ps n’est disponible qu’après avoir installé procps dans ces conteneurs de cet exercice.

$ kubectl exec -it <nom-du-conteneur> -- apt update

$ kubectl exec -it <nom-du-conteneur> -- apt install procps

Ci-dessous le fichier yaml utilisé,

$ cat << EOF >> volumes.yaml
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    volumeMounts:
    - name: redis-storage
      mountPath: /data/redis
  volumes:
  - name: redis-storage
    emptyDir: {}
EOF

Au redémarrage du conteneur ( la valeur de RESTARTS pour le pod concerné doit avoir été incrémentée), vérifier que le fichier /data/redis/test-file existe toujours.

Afin de pouvoir faire une  comparaison avec un conteneur utilisant un système de fichier, je vous propose de refaire le même exercice, après avoir supprimé la partie « volumes » du fichier yaml. Vous pouvez aussi utiliser le fichier yaml ci-dessous.

$ cat << EOF >> file-system.yaml
apiVersion: v1
kind: Pod
metadata:
  name: redisfs
spec:
  containers:
  - name: redisfs
    image: redis
EOF

Pour pouvoir effectuer exactement les mêmes étapes que dans l’exercice précédant, créer un dossier /data/redis dans le conteneur redisfs.

Après avoir tué le processus Redis pour redémarrer le conteneur, le dossier ainsi que son contenu ne devrait plus exister.

3.5 Conclusion

Avec un système de fichiers, les modifications apportées au niveau des fichiers et données ne sont pas persistantes, et seront détruites au redémarrage du conteneur.

L’utilisation des Volumes permet d’éviter ce désagrément.

Ce qu’il faut savoir en ce qui concerne les volumes,

  • Les modifications apportées au sein de chaque conteneur persistent jusqu’au redémarrage ou à la destruction du Pod dans lequel ces conteneurs sont associés
  • Les Volumes peuvent être mis en commun entre plusieurs conteneurs du même pod

Ces deux limitations peuvent être outrepassées en passant par un serveur de stockage (local ou dans le Cloud) pour présenter les volumes, afin de garantir une sauvegarde de données indépendemment de l’état du Pod, de façon plus permanente.
Après il faut voir comment vous gérez votre cluster de stockage de donnée.

Sources

Manage data in Docker
Kubernetes: Documentation / Concepts / Stockage
docker container does not need an OS, but each container has one. Why?
What is the meaning of mounting /dev/sda1 to /etc/hosts in Docker container
Quelle est la différence entre un conteneur et une machine virtuelle?
Kubernetes Mount Propagation
Kubernetes – Volumes
Configurer un pod en utilisant un volume pour le stockage