Notre expérience dans le développement d'un pilote CSI dans Kubernetes pour Yandex.Cloud

Notre expérience dans le développement d'un pilote CSI dans Kubernetes pour Yandex.Cloud

Nous sommes heureux d'annoncer que Flant étend sa contribution aux outils Open Source pour Kubernetes en publiant version alpha du pilote CSI (Interface de stockage de conteneurs) pour Yandex.Cloud.

Mais avant de passer aux détails de mise en œuvre, répondons à la question de savoir pourquoi cela est nécessaire alors que Yandex dispose déjà d'un service. Service géré pour Kubernetes.

introduction

Pourquoi est-ce

Au sein de notre entreprise, dès le début de l'utilisation de Kubernetes en production (c'est-à-dire depuis plusieurs années maintenant), nous développons notre propre outil (deckhouse), que nous prévoyons d'ailleurs de rendre prochainement disponible sous forme de projet Open Source. . Avec son aide, nous configurons et configurons de manière uniforme tous nos clusters, et il y en a actuellement plus de 100, sur une grande variété de configurations matérielles et dans tous les services cloud disponibles.

Les clusters qui utilisent Deckhouse disposent de tous les composants nécessaires au fonctionnement : équilibreurs, surveillance avec des graphiques, des métriques et des alertes pratiques, authentification des utilisateurs via des fournisseurs externes pour accéder à tous les tableaux de bord, etc. Il ne sert à rien d'installer un tel cluster « gonflé » dans une solution gérée, car cela est souvent soit impossible, soit entraînera la nécessité de désactiver la moitié des composants.

NB: C'est notre expérience, et elle est assez spécifique. Nous ne suggérons en aucun cas à chacun de déployer lui-même des clusters Kubernetes au lieu d’utiliser des solutions toutes faites. À propos, nous n'avons aucune réelle expérience dans l'exploitation de Kubernetes depuis Yandex et nous ne donnerons aucune évaluation de ce service dans cet article.

Qu'est-ce que c'est et pour qui ?

Nous avons donc déjà parlé de l'approche moderne du stockage dans Kubernetes : comment fonctionne le CSI ? и comment la communauté est née à cette approche.

Actuellement, de nombreux grands fournisseurs de services cloud ont développé des pilotes pour utiliser leurs disques cloud comme volumes persistants dans Kubernetes. Si le fournisseur ne dispose pas d'un tel pilote, mais que toutes les fonctions nécessaires sont fournies via l'API, alors rien ne vous empêche d'implémenter le pilote vous-même. C'est ce qui s'est passé avec Yandex.Cloud.

Nous avons pris comme base de développement Pilote CSI pour le cloud DigitalOcean et quelques idées de pilotes pour GCP, puisque l'interaction avec l'API de ces cloud (Google et Yandex) présente un certain nombre de similitudes. En particulier, l'API et GCP, et y Yandex renvoyer un objet Operation pour suivre l'état des opérations de longue durée (par exemple, la création d'un nouveau disque). Pour interagir avec l'API Yandex.Cloud, utilisez SDK Yandex.Cloud Go.

Le résultat du travail effectué publié sur GitHub et peut être utile pour ceux qui, pour une raison quelconque, utilisent leur propre installation Kubernetes sur des machines virtuelles Yandex.Cloud (mais pas un cluster géré prêt à l'emploi) et souhaitent utiliser (commander) des disques via CSI.

exécution

Caractéristiques principales

Actuellement, le pilote prend en charge les fonctions suivantes :

  • Ordonner les disques dans toutes les zones du cluster selon la topologie des nœuds du cluster ;
  • Retrait des disques précédemment commandés ;
  • Redimensionnement hors ligne pour les disques (Yandex.Cloud ne prend pas en charge augmentant le nombre de disques montés sur la machine virtuelle). Pour plus d'informations sur la façon dont le pilote a dû être modifié pour rendre le redimensionnement aussi simple que possible, voir ci-dessous.

À l'avenir, nous prévoyons d'implémenter la prise en charge de la création et de la suppression d'instantanés de disque.

La principale difficulté et comment la surmonter

L'absence de possibilité d'augmenter les disques en temps réel dans l'API Yandex.Cloud est une limitation qui complique l'opération de redimensionnement pour PV (Persistent Volume) : dans ce cas, il faut que le pod d'application qui utilise le disque soit arrêté, et cela peut entraîner des temps d'arrêt des applications.

selon Spécifications CSI, si le contrôleur CSI signale qu'il ne peut redimensionner les disques que « hors ligne » (VolumeExpansion.OFFLINE), alors le processus d'augmentation du disque devrait se dérouler comme ceci :

Si le plugin n'a que VolumeExpansion.OFFLINE la capacité d'extension et le volume sont actuellement publiés ou disponibles sur un nœud, puis ControllerExpandVolume DOIT être appelé SEULEMENT après :

  • Le plugin a un contrôleur PUBLISH_UNPUBLISH_VOLUME capacité et ControllerUnpublishVolume a été invoqué avec succès.

OU SINON

  • Le plugin n'a PAS de contrôleur PUBLISH_UNPUBLISH_VOLUME capacité, le plugin a un nœud STAGE_UNSTAGE_VOLUME capacité, et NodeUnstageVolume a été complété avec succès.

OU SINON

  • Le plugin n'a PAS de contrôleur PUBLISH_UNPUBLISH_VOLUME capacité, ni nœud STAGE_UNSTAGE_VOLUME capacité, et NodeUnpublishVolume a réussi.

Cela signifie essentiellement que vous devez détacher le disque de la machine virtuelle avant de l'étendre.

Cependant, malheureusement mise en oeuvre La spécification CSI via side-cars ne répond pas à ces exigences :

  • Dans un conteneur side-car csi-attacher, qui devrait être responsable de la présence de l'écart requis entre les montages, cette fonctionnalité n'est tout simplement pas implémentée dans le redimensionnement hors ligne. Une discussion à ce sujet a été lancée ici.
  • Qu’est-ce qu’un conteneur side-car exactement dans ce contexte ? Le plugin CSI lui-même n'interagit pas avec l'API Kubernetes, mais répond uniquement aux appels gRPC qui lui sont envoyés par les conteneurs side-car. Dernier sont en cours de développement par la communauté Kubernetes.

Dans notre cas (plugin CSI), l'opération d'augmentation du disque ressemble à ceci :

  1. Nous recevons un appel gRPC ControllerExpandVolume;
  2. Nous essayons d'augmenter le disque dans l'API, mais nous recevons une erreur sur l'impossibilité d'effectuer l'opération car le disque est monté ;
  3. Nous stockons l'identifiant du disque dans une carte, qui contient les disques pour lesquels l'opération d'augmentation doit être effectuée. Ci-dessous, par souci de concision, nous appellerons cette carte comme volumeResizeRequired;
  4. Supprimez manuellement le pod qui utilise le disque. Kubernetes le redémarrera. Pour que le disque n'ait pas le temps de monter (ControllerPublishVolume) avant de terminer l'opération d'augmentation lors de la tentative de montage, nous vérifions que le disque donné est toujours dans volumeResizeRequired et renvoie une erreur ;
  5. Le pilote CSI tente de réexécuter l'opération de redimensionnement. Si l'opération a réussi, retirez le disque de volumeResizeRequired;
  6. Parce que L'ID de disque est manquant dans volumeResizeRequired, ControllerPublishVolume réussit, le disque est monté, le pod démarre.

Tout semble assez simple, mais comme toujours, il y a des pièges. Agrandit les disques redimensionneur externe, qui en cas d'erreur lors de l'opération utilise une file d'attente avec une augmentation exponentielle du délai d'attente jusqu'à 1000 secondes :

func DefaultControllerRateLimiter() RateLimiter {
  return NewMaxOfRateLimiter(
  NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
  // 10 qps, 100 bucket size.  This is only for retry speed and its only the overall factor (not per item)
  &BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
  )
}

Cela peut périodiquement entraîner une prolongation de l'opération d'extension du disque pendant plus de 15 minutes et, par conséquent, l'indisponibilité du pod correspondant.

La seule option qui nous a permis de réduire facilement et sans douleur les temps d'arrêt potentiels était l'utilisation de notre version de redimensionneur externe avec un délai d'attente maximum. en 5 secondes:

workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)

Nous n'avons pas jugé nécessaire d'engager de toute urgence une discussion et de corriger le redimensionneur externe, car le redimensionnement hors ligne des disques est un retour en arrière qui disparaîtra bientôt de tous les fournisseurs de cloud.

Comment commencer à utiliser ?

Le pilote est pris en charge sur Kubernetes version 1.15 et ultérieure. Pour que le chauffeur puisse travailler, les conditions suivantes doivent être remplies :

  • Drapeau --allow-privileged mettre à la valeur true pour le serveur API et kubelet ;
  • Inclus --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true pour le serveur API et kubelet ;
  • Propagation du montage (propagation du mont) doit être activé sur le cluster. Lors de l'utilisation de Docker, le démon doit être configuré pour autoriser les montages partagés.

Toutes les étapes nécessaires à l'installation elle-même décrit dans README. L'installation implique la création d'objets dans Kubernetes à partir de manifestes.

Pour que le chauffeur travaille, vous aurez besoin des éléments suivants :

  • Spécifiez l'identifiant du répertoire dans le manifeste (folder-id) Yandex.Cloud (voir la documentation);
  • Pour interagir avec l'API Yandex.Cloud, le pilote CSI utilise un compte de service. Dans le manifeste, le secret doit être transmis clés autorisées du compte de service. Dans le document décrit, comment créer un compte de service et obtenir des clés.

En tout - essayer, et nous serons heureux de recevoir des commentaires et nouveaux problèmessi vous rencontrez des problèmes !

Un soutien supplémentaire

De ce fait, notons que nous avons implémenté ce pilote CSI non pas par grande envie de s'amuser à écrire des applications en Go, mais en raison d'un besoin urgent au sein de l'entreprise. Il ne nous semble pas pratique de maintenir notre propre implémentation, donc si Yandex manifeste son intérêt et décide de continuer à prendre en charge le pilote, nous serons heureux de leur transférer le référentiel.

De plus, Yandex a probablement sa propre implémentation du pilote CSI dans son cluster Kubernetes géré, qui peut être publié en Open Source. Nous considérons également cette option de développement comme favorable : la communauté pourra utiliser un pilote éprouvé d'un prestataire de services, et non d'une société tierce.

PS

A lire aussi sur notre blog :

Source: habr.com

Ajouter un commentaire