Plugins de volume de stockage Kubernetes: Flexvolume vers CSI



À l'époque où Kubernetes était encore v1.0.0, les plugins de volume existaient. Ils étaient nécessaires pour se connecter aux systèmes Kubernetes afin de stocker des données de conteneurs persistantes (permanentes). Leur nombre était faible et parmi les premiers, il y avait des fournisseurs de stockage tels que GCE PD, Ceph, AWS EBS et autres.

Les plug-ins ont été livrés avec Kubernetes, pour lequel ils ont obtenu leur nom - dans l'arborescence. Cependant, beaucoup de l'ensemble existant de ces plug-ins n'était pas suffisant. Les artisans ont ajouté des plugins simples au cœur de Kubernetes à l'aide de correctifs, après quoi ils ont construit leur propre Kubernetes et l'ont mis sur leurs serveurs. Mais au fil du temps, les développeurs de Kubernetes ont réalisé que le poisson ne pouvait pas être résolu. Les gens ont besoin d'une canne à pêche . Et dans la version Kubernetes v1.2.0, il est apparu ...

Plugin Flexvolume: canne à pêche minimale


Les développeurs de Kubernetes ont créé le plugin FlexVolume, qui était une liaison logique de variables et de méthodes pour travailler avec des pilotes Flexvolume tiers.

Arrêtons-nous et examinons de plus près ce qu'est le pilote FlexVolume. Il s'agit d'un certain fichier exécutable ( fichier binaire, script Python, script Bash, etc.), qui, une fois exécuté, prend des arguments de ligne de commande et renvoie un message avec des champs précédemment connus au format JSON. Par convention, le premier argument de ligne de commande est toujours la méthode et le reste des arguments sont ses paramètres.


CIFS Partage le schéma de connexion dans OpenShift. Pilote Flexvolume - en plein centre

L'ensemble minimal de méthodes ressemble à ceci:

flexvolume_driver mount #      pod' #   : { "status": "Success"/"Failure"/"Not supported", "message": "       ", } flexvolume_driver unmount #      pod' #   : { "status": "Success"/"Failure"/"Not supported", "message": "       ", } flexvolume_driver init #     #   : { "status": "Success"/"Failure"/"Not supported", "message": "       ", // ,     attach/deatach "capabilities":{"attach": True/False} } 

L'utilisation des méthodes d' attach et de detach déterminera le scénario selon lequel le futur kubelet agira lorsque le pilote sera appelé. Il existe également des expandfs expandvolume et expandfs spéciales qui sont responsables du redimensionnement dynamique d'un volume.

Comme exemple des changements que la méthode expandvolume , et avec elle la possibilité d'effectuer un redimensionnement du volume en temps réel, vous pouvez consulter notre demande de pull dans l'opérateur Rook Ceph.

Voici un exemple d'implémentation du pilote Flexvolume pour travailler avec NFS:

 usage() { err "Invalid usage. Usage: " err "\t$0 init" err "\t$0 mount <mount dir> <json params>" err "\t$0 unmount <mount dir>" exit 1 } err() { echo -ne $* 1>&2 } log() { echo -ne $* >&1 } ismounted() { MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1` if [ "${MOUNT}" == "${MNTPATH}" ]; then echo "1" else echo "0" fi } domount() { MNTPATH=$1 NFS_SERVER=$(echo $2 | jq -r '.server') SHARE=$(echo $2 | jq -r '.share') if [ $(ismounted) -eq 1 ] ; then log '{"status": "Success"}' exit 0 fi mkdir -p ${MNTPATH} &> /dev/null mount -t nfs ${NFS_SERVER}:/${SHARE} ${MNTPATH} &> /dev/null if [ $? -ne 0 ]; then err "{ \"status\": \"Failure\", \"message\": \"Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}\"}" exit 1 fi log '{"status": "Success"}' exit 0 } unmount() { MNTPATH=$1 if [ $(ismounted) -eq 0 ] ; then log '{"status": "Success"}' exit 0 fi umount ${MNTPATH} &> /dev/null if [ $? -ne 0 ]; then err "{ \"status\": \"Failed\", \"message\": \"Failed to unmount volume at ${MNTPATH}\"}" exit 1 fi log '{"status": "Success"}' exit 0 } op=$1 if [ "$op" = "init" ]; then log '{"status": "Success", "capabilities": {"attach": false}}' exit 0 fi if [ $# -lt 2 ]; then usage fi shift case "$op" in mount) domount $* ;; unmount) unmount $* ;; *) log '{"status": "Not supported"}' exit 0 esac exit 1 

Ainsi, après avoir préparé le fichier exécutable réel, vous devez disposer le pilote dans le cluster Kubernetes . Le pilote doit être situé sur chaque nœud du cluster selon un chemin prédéfini. Par défaut, a été sélectionné:

/usr/libexec/kubernetes/kubelet-plugins/volume/exec/__~_/

... mais en utilisant différentes distributions Kubernetes (OpenShift, Rancher ...) le chemin peut être différent.

Problèmes de flexvolume: comment lancer une canne à pêche?


Placer le pilote Flexvolume sur les nœuds du cluster s'est avéré être une tâche non triviale. Après avoir effectué l'opération une fois manuellement, il est facile de rencontrer une situation où de nouveaux nœuds apparaissent dans le cluster: en raison de l'ajout d'un nouveau nœud, de la mise à l'échelle horizontale automatique ou, pire, du remplacement du nœud en raison d'un dysfonctionnement. Dans ce cas, il est impossible de travailler avec le stockage sur ces nœuds jusqu'à ce que vous leur ajoutiez manuellement le pilote Flexvolume de la même manière.

La solution à ce problème était l'une des primitives de Kubernetes - DaemonSet . Lorsqu'un nouveau nœud apparaît dans le cluster, il obtient automatiquement un pod de notre DaemonSet, auquel un volume local est attaché en cours de route pour trouver les pilotes Flexvolume. Une fois la création réussie, pod copie les fichiers nécessaires pour que le pilote fonctionne sur le disque.

Voici un exemple d'un tel DaemonSet pour disposer le plugin Flexvolume:

 apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: flex-set spec: template: metadata: name: flex-deploy labels: app: flex-deploy spec: containers: - image: <deployment_image> name: flex-deploy securityContext: privileged: true volumeMounts: - mountPath: /flexmnt name: flexvolume-mount volumes: - name: flexvolume-mount hostPath: path: <host_driver_directory> 

... et un exemple de script Bash pour disposer un pilote Flexvolume:

 #!/bin/sh set -o errexit set -o pipefail VENDOR=k8s.io DRIVER=nfs driver_dir=$VENDOR${VENDOR:+"~"}${DRIVER} if [ ! -d "/flexmnt/$driver_dir" ]; then mkdir "/flexmnt/$driver_dir" fi cp "/$DRIVER" "/flexmnt/$driver_dir/.$DRIVER" mv -f "/flexmnt/$driver_dir/.$DRIVER" "/flexmnt/$driver_dir/$DRIVER" while : ; do sleep 3600 done 

Il est important de ne pas oublier que l'opération de copie n'est pas atomique . Il est fort probable que kubelet commence à utiliser le pilote avant la fin du processus de préparation, ce qui entraînera une erreur dans le système. L'approche correcte serait de copier d'abord les fichiers du pilote sous un nom différent, puis d'utiliser l'opération de renommage atomique.


Schéma de travail avec Ceph dans l'instruction Rook: le pilote Flexvolume sur le diagramme est à l'intérieur de l'agent Rook

Le problème suivant lors de l'utilisation des pilotes Flexvolume est que pour la plupart des stockages , le logiciel nécessaire doit être installé sur le nœud du cluster (par exemple, le package ceph-common pour Ceph). Initialement, le plugin Flexvolume n'était pas conçu pour implémenter de tels systèmes complexes.

Une solution originale à ce problème peut être vue dans l'implémentation du pilote Flexvolume de l'opérateur Rook:

Le pilote lui-même est conçu comme un client RPC. La prise IPC pour la communication se trouve dans le même répertoire que le pilote lui-même. Nous nous souvenons que pour copier des fichiers de pilote, il serait bon d'utiliser DaemonSet, qui connecte un répertoire avec le pilote en tant que volume. Après avoir copié les fichiers de pilote de tour nécessaires, ce module ne meurt pas, mais se connecte au socket IPC via le volume attaché en tant que serveur RPC à part entière. Le package ceph-common est déjà installé à l'intérieur du conteneur de pod. Le socket IPC donne l'assurance que le kubelet communiquera avec le pod particulier situé sur le même nœud. Tout ingénieux est simple! ..

Au revoir, nos affectueux ... plugins dans l'arbre!


Les développeurs de Kubernetes ont découvert que le nombre de plugins de stockage à l'intérieur du noyau est de vingt. Et le changement dans chacun d'entre eux passe en quelque sorte par le cycle de sortie complet de Kubernetes.

Il s'avère que pour utiliser la nouvelle version du plugin pour le stockage, vous devez mettre à jour l'intégralité du cluster . En plus de cela, vous pouvez être surpris que la nouvelle version de Kubernetes devienne soudainement incompatible avec le noyau Linux utilisé ... Et donc, vous essuyez les larmes et serrez les dents et coordonnez avec les autorités et les utilisateurs le temps de mise à jour du noyau Linux et du cluster Kubernetes. Avec un temps d'arrêt possible dans la prestation de services.

La situation est plus que comique, non? Il est devenu clair pour toute la communauté que l'approche n'avait pas fonctionné. Avec une décision volontaire, les développeurs de Kubernetes annoncent que les nouveaux plugins de stockage ne seront plus acceptés dans le noyau. Pour tout le reste, comme nous le savons déjà, dans la mise en œuvre du plugin Flexvolume, un certain nombre de lacunes ont été révélées ...

Une fois pour toutes, le dernier plugin ajouté pour les volumes dans Kubernetes, CSI, a été appelé à résoudre le problème avec les entrepôts de données persistants. Sa version alpha, plus communément appelée plugins de volume CSI hors arbre, a été annoncée dans Kubernetes 1.9 .

Interface de stockage de conteneurs, ou spinning CSI 3000!


Tout d'abord, je voudrais noter que CSI n'est pas seulement un plugin de volume, mais un véritable standard pour créer des composants personnalisés pour travailler avec des entrepôts de données . Il a été supposé que les systèmes d'orchestration de conteneurs, tels que Kubernetes et Mesos, devraient «apprendre» à travailler avec des composants mis en œuvre conformément à cette norme. Et maintenant, Kubernetes a déjà appris.

Quel est le périphérique du plugin CSI dans Kubernetes? Le plugin CSI fonctionne avec des pilotes spéciaux (pilotes CSI ) écrits par des développeurs tiers. Le pilote CSI dans Kubernetes doit au moins être composé de deux composants (pods):

  • Contrôleur - gère le stockage persistant externe. Il est implémenté en tant que serveur gRPC pour lequel la primitive StatefulSet est utilisée.
  • Node - est responsable du montage des magasins persistants sur les nœuds de cluster. Il est également implémenté en tant que serveur gRPC, mais la primitive DaemonSet est utilisée pour cela.


Flux de travail du plugin CSI Kubernetes

Vous pouvez en apprendre davantage sur d'autres détails de CSI, par exemple, dans l'article « Comprendre le CSI », dont nous avons publié la traduction il y a un an.

Les avantages d'une telle implémentation


  • Pour les choses de base - par exemple, pour enregistrer un pilote pour un nœud - les développeurs de Kubernetes ont implémenté un ensemble de conteneurs. Vous n'avez plus besoin de créer vous-même une réponse JSON avec des fonctionnalités, comme cela a été fait pour le plugin Flexvolume.
  • Au lieu de «glisser» les nœuds des fichiers exécutables, nous plaçons maintenant les pods dans le cluster. C'est ce que nous attendions à l'origine de Kubernetes: tous les processus se produisent à l'intérieur de conteneurs déployés à l'aide de primitives Kubernetes.
  • Pour implémenter des pilotes complexes, vous n'avez plus besoin de développer un serveur RPC et un client RPC. Le client pour nous a été implémenté par les développeurs de Kubernetes.
  • Passer des arguments pour travailler avec le protocole gRPC est beaucoup plus pratique, flexible et plus fiable que de les passer par des arguments de ligne de commande. Pour comprendre comment ajouter la prise en charge des métriques d'utilisation du volume à CSI en ajoutant une méthode gRPC standardisée, consultez notre demande d'extraction pour le pilote vsphere-csi.
  • La communication se fait via des sockets IPC afin de ne pas se tromper que le pod kubelet envoie ou non une requête.

Cette liste vous rappelle-t-elle quelque chose? Les avantages de CSI sont la solution aux problèmes mêmes qui n'ont pas été pris en compte lors du développement du plugin Flexvolume.

Conclusions


CSI en tant que norme pour la mise en œuvre de plugins personnalisés pour interagir avec les entrepôts de données a été très chaleureusement accepté par la communauté. De plus, en raison de ses avantages et de sa polyvalence, les pilotes CSI sont créés même pour des référentiels tels que Ceph ou AWS EBS, des plugins pour travailler avec qui ont été ajoutés dans la toute première version de Kubernetes.

Début 2019, les plugins in-tree étaient obsolètes . Il est prévu de continuer à prendre en charge le plugin Flexvolume, mais il n'y aura pas de développement de nouvelles fonctionnalités pour celui-ci.

Nous avons nous-mêmes déjà de l'expérience avec ceph-csi, vsphere-csi et sommes prêts à ajouter à cette liste! Jusqu'à présent, CSI fait face aux tâches qui lui sont assignées avec un bang, et là, nous attendons et voyons.

N'oubliez pas que tout ce qui est nouveau est un vieux bien repensé!

PS


Lisez aussi dans notre blog:

Source: https://habr.com/ru/post/fr465417/


All Articles