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



Nous sommes heureux d'annoncer que Flant reconstitue sa contribution aux outils Open Source pour Kubernetes en publiant une version alpha du pilote CSI (Container Storage Interface) pour Yandex.Cloud.

Mais avant de passer aux détails de l'implémentation, nous répondrons à la question de savoir pourquoi cela est nécessaire lorsque Yandex dispose déjà du service Managed Service pour Kubernetes .

introduction


Pourquoi est-ce?


Au sein de notre entreprise, dès le début de l'exploitation de Kubernetes en production (c'est-à-dire depuis plusieurs années), notre propre outil (deckhouse) se développe, que nous prévoyons d'ailleurs de mettre à disposition sous forme de projet Open Source dans un avenir proche. Avec son aide, nous configurons et configurons uniformément tous nos clusters, et pour le moment, il y en a plus de 100 sur les configurations matérielles les plus diverses et dans tous les services cloud disponibles.

Les clusters utilisant deckhouse disposent de tous les composants nécessaires au travail: équilibreurs, surveillance avec des graphiques, des mesures et des alertes pratiques, authentification des utilisateurs via des fournisseurs externes pour accéder à tous les tableaux de bord, etc. Cela n'a pas de sens de mettre un tel cluster «gonflé» dans une solution gérée, car cela est souvent impossible ou entraînera la nécessité de désactiver la moitié des composants.

NB : C'est notre expérience, et c'est assez spécifique. En aucun cas, nous ne prétendons que tout le monde devrait s'engager indépendamment dans le déploiement du cluster Kubernetes au lieu d'utiliser des solutions prêtes à l'emploi. Soit dit en passant, nous n'avons aucune expérience réelle dans l'utilisation de Kubernetes de Yandex et nous ne donnerons aucune évaluation de ce service dans cet article.

C'est quoi et pour qui?


Nous avons donc déjà parlé de l'approche moderne du stockage dans Kubernetes: comment fonctionne CSI et comment la communauté est venue à cette approche.

Actuellement, de nombreux grands fournisseurs de services cloud ont développé des pilotes pour utiliser leurs disques cloud en tant que volume persistant dans Kubernetes. Si le fournisseur n'a pas un tel pilote, mais en même temps toutes les fonctions nécessaires sont fournies via l'API, alors rien n'empêche le pilote de mettre en œuvre ses propres ressources. Et c'est arrivé avec Yandex.Cloud.

Comme base de développement, nous avons pris le pilote CSI pour le cloud DigitalOcean et quelques idées du pilote pour GCP , car l'interaction avec l'API de ces clouds (Google et Yandex) présente un certain nombre de similitudes. En particulier, l'API etGCP et Yandex renvoient un objet Operationpour suivre l'état des opérations longues (par exemple, créer un nouveau disque). Pour interagir avec l'API Yandex.Cloud , le SDK Yandex.Cloud Go est utilisé .

Le résultat du travail effectué est publié sur GitHub et peut être utile à ceux qui, pour une raison quelconque, utilisent leur propre installation de 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.

la mise en oeuvre


Principales caractéristiques


Actuellement, le pilote prend en charge les fonctions suivantes:

  • Ordonner les disques dans toutes les zones du cluster en fonction de 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 l' augmentation des disques montés sur une machine virtuelle). Pour savoir comment modifier le pilote afin de redimensionner le plus indolore possible, voir ci-dessous.

À l'avenir, il est prévu de mettre en œuvre la prise en charge de la création et de la suppression de disques d'instantanés.

La principale difficulté et son dépassement


Le manque de capacité à étendre les disques en temps réel dans l'API Yandex.Cloud est une limitation qui complique l'opération de redimensionnement pour PV (Volume persistant): dans ce cas, il est nécessaire que le pod de l'application qui utilise le disque soit arrêté, ce qui peut provoquer un simple applications.

Selon la spécification CSI , si le contrôleur CSI signale qu'il ne peut redimensionner les disques que «hors ligne» ( VolumeExpansion.OFFLINE), le processus d'augmentation du disque devrait se dérouler comme suit:

Si le plugin n'a qu'une VolumeExpansion.OFFLINEcapacité d'expansion et que le volume est actuellement publié ou disponible sur un nœud, alors ControllerExpandVolumeDOIT être appelé UNIQUEMENT après:

  • Le plugin a une PUBLISH_UNPUBLISH_VOLUMEcapacité de contrôleur et ControllerUnpublishVolumea été appelé avec succès.

OU SINON

  • Le plugin n'a PAS de PUBLISH_UNPUBLISH_VOLUMEcapacité de contrôleur , le plugin a la STAGE_UNSTAGE_VOLUMEcapacité de nœud et NodeUnstageVolumes'est terminé avec succès.

OU SINON

  • Le plugin n'a PAS de PUBLISH_UNPUBLISH_VOLUMEcapacité de contrôleur , ni de STAGE_UNSTAGE_VOLUMEcapacité de nœud , et NodeUnpublishVolumes'est terminé avec succès.

En substance, cela signifie la nécessité de déconnecter le disque de la machine virtuelle avant de l'augmenter.

Cependant, malheureusement, la mise en œuvre de la spécification CSI via side-car ne répond pas à ces exigences:

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

Dans notre cas (plugin CSI), l'opération pour augmenter le disque est la suivante:

  1. Nous recevons un appel gRPC ControllerExpandVolume;
  2. Nous essayons d'augmenter le disque dans l'API, mais nous obtenons une erreur concernant l'impossibilité d'effectuer l'opération, car le disque est monté;
  3. Nous enregistrons l'identifiant du disque dans une carte contenant les disques pour lesquels vous devez effectuer une opération d'augmentation. Par souci de concision, nous appellerons cette carte volumeResizeRequired:
  4. Supprimez manuellement le module qui utilise le disque. Kubernetes le redémarrera. Afin que le disque n'ait pas le temps de monter ( ControllerPublishVolume) avant la fin de l'opération d'augmentation lors de la tentative de montage, nous vérifions que ce disque est toujours en place volumeResizeRequiredet renvoyons une erreur;
  5. Le pilote CSI tente de réexécuter l'opération de redimensionnement. Si l'opération a réussi, supprimez le disque de volumeResizeRequired;
  6. Parce que l'identifiant du disque manque volumeResizeRequired, il ControllerPublishVolumeréussit, le disque est monté, le pod démarre.

Tout semble assez simple, mais comme toujours, il y a des pièges. Le redimensionneur externe est impliqué dans l' expansion du disque qui, en cas d'erreur pendant l'opération, utilise une file d' attente avec une augmentation exponentielle du délai d'expiration 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 conduire périodiquement au fait que l'opération d'augmentation du disque est étirée pendant plus de 15 minutes et, par conséquent, à l'inaccessibilité du pod correspondant.

La seule option qui nous a permis de réduire le temps d'immobilisation potentiel assez facilement et sans douleur était d'utiliser notre version de redimensionnement externe avec un délai maximum de 5 secondes :

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

Nous n'avons pas jugé nécessaire de lancer d'urgence une discussion et de corriger le redimensionneur externe, car les disques de redimensionnement hors ligne sont un atavisme qui disparaîtra bientôt de tous les fournisseurs de cloud.

Comment commencer à utiliser?


Le pilote est pris en charge dans Kubernetes version 1.15 et supérieure. Pour que le conducteur fonctionne, les conditions suivantes doivent être remplies:

  • L'indicateur est --allow-privilegeddéfini sur la valeur truedu serveur API et du kubelet;
  • Inclus --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=truepour le serveur API et le kubelet;
  • Le montage de propagation ( propagation du montage ) doit être inclus dans le cluster. Lors de l'utilisation de Docker, le démon doit être configuré pour que les montages partagés soient autorisés.

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

Pour que le pilote fonctionne, vous aurez besoin des éléments suivants:

  • Indiquez l'identifiant du répertoire du catalogue Yandex.Cloud ( folder-id) dans le manifeste ( voir la documentation );
  • Pour interagir avec l'API Yandex.Cloud dans le pilote CSI, un compte de service est utilisé. Dans le manifeste secret, vous devez transmettre les clés autorisées au compte de service. La documentation décrit comment créer un compte de service et obtenir les clés.

En général, essayez -le et nous serons heureux de recevoir des commentaires et de nouveaux problèmes si vous rencontrez des problèmes!

Un soutien supplémentaire


En conséquence, nous tenons à noter que nous avons implémenté ce pilote CSI non pas par un grand désir d'avoir du plaisir à écrire des applications sur Go, mais en raison du besoin urgent au sein de l'entreprise. Il ne semble pas conseillé de prendre en charge notre propre implémentation.Par conséquent, si Yandex montre de l'intérêt et décide de continuer à prendre en charge le pilote, nous transférerons volontiers le référentiel à leur disposition.

De plus, probablement, Yandex dans le cluster géré Kubernetes a sa propre implémentation du pilote CSI, qui peut être publié en Open Source. Cette option de développement nous semble également favorable - la communauté pourra utiliser le pilote éprouvé du prestataire de services et non d'une société tierce.

PS


Lisez aussi dans notre blog:

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


All Articles