Le stockage avec Kubernetes, entretien avec Yassine Tijani, contributeur Kubernetes
Entretien réalisé en avril 2019
Bonjour Yassine, peux-tu nous parler un peu de ton parcours, de ce qui t'a amené à devenir contributeur Kubernetes
C’est principalement l’envie d’avoir un ownership fort sur un produit que j’utilise et que j’avais repéré très tôt. J’avais en effet pressenti qu’il y aurait des enjeux de plateforming et de normalisation des infrastructures et j’ai alors fait l’état des lieux du marché en regardant les API et les abstractions fournies par les différents orchestrateurs.
Très vite, je me suis aperçu que Kubernetes était la réponse et j’ai donc commencé à contribuer à l’époque où j’étais chez Amadeus en 2017.
Qu’est-ce que tu fais dans la communauté Kubernetes ?
Je me concentre principalement sur le Scheduling (placement) et l’intégration des fournisseurs de Cloud au sein de Kubernetes. Je m’intéresse également au stockage, notamment la partie volume et la partie persistance.
Sur la partie placement je suis un des owners c’est-à-dire un des principaux responsables de ce qu’on appelle la Scheduling Policy.
Il faut savoir que Kubernetes contient des morceaux de code qui sont spécifiques à des Cloud Providers. A terme, l’objectif est de sortir ce code du projet.
Au FOSDEM 2019, toutes les conférences sur Kubernetes faisaient salle comble. Comment tu expliques cet engouement ?
Je pense que cet engouement vient principalement du fait que les grands acteurs du Cloud travaillent ensemble sur une seule et même solution, pour un “bien commun” à savoir la normalisation et la non-adhérence à un fournisseur de cloud.
Au cours d’un projet, différentes raisons (financières, techniques ou politiques) peuvent en effet pousser les parties prenantes à vouloir changer de cloud-provider.
Ensuite, les abstractions qui sont fournies par Kubernetes sont séduisantes. Les API qui sont proposées correspondent à l’utilisation quotidienne d’un OPs sur son infrastructure. Par exemple Kubernetes permet de modéliser ce qu’on appelle des déploiements et au final ça correspond bien à la réalité ou à une partie du métier d’un OPs.
Quelle est la feuille de route de Kubernetes en 2019 ?
La feuille de route de 2019 est tournée vers les extensions. Comme je l’ai dit tout à l’heure, on a commencé un travail de migration du code spécifique aux fournisseurs de cloud dans des repository différents. Cela permettra aux fournisseurs de cloud d’adopter un cycle de release bien spécifique et donc une vélocité adaptée à leurs équipes.
Un autre sujet sur lequel on va travailler, c’est le Container Storage Interface (CSI). Les plugins de volume vont aussi être migrés dans des repositories spécifiques.
On travaille aussi en même temps sur l’amélioration de la scalabilité de Kubernetes afin de pouvoir accueillir des infrastructures de plus en plus exigeantes.
En ce qui concerne le périmètre du projet, nous voulons éviter de reproduire les erreurs du passé et laisser le projet dériver vers une chasse aux fonctionnalités à l’infini, je pense notamment aux différents projets Open Source qui sont passés par ce chemin là et dont on apprend de jour en jour.
Quels sont les principaux défis que la communauté doit relever ?
Je vais commencer avec les défis techniques déjà, le premier c’est le stockage. Il faut savoir que près de la moitié des applications qui tournent sur des clusters Kubernetes managés sont stateful. Il est donc très important pour nous de couvrir tous les fossés fonctionnels afin d’assurer un fonctionnement optimal.
Le deuxième défi pour moi c’est la sécurité. Maintenant qu’on commence à avoir un nombre très important d’organisations qui adoptent Kubernetes, la sécurité deviendra un des axes critiques du projet. Je pense notamment à des audits de sécurité, la gestion des dépendances ainsi que le patch management.
Sur le plan organisationnel, il faut qu’on arrive à passer à l’échelle et à pouvoir embarquer de nouveaux contributeurs plus facilement, en incluant un spectre assez divers de personnes.
Kubernetes est déjà sur la bonne voie. C’est une des communautés les plus diverses en termes de points de vue et en termes de personnes. Cela représente une vraie force pour le projet.
Est-ce que tu peux expliquer le défi que représente le stockage? Quels sont les fossés fonctionnels que tu évoques ?
Oui. Avant d’aller plus loin, je vais faire une petite introduction au stockage dans Kubernetes.
Kubernetes fournit une abstraction afin de consommer des solutions de stockage. Cette abstraction se décline en plusieurs ressources : les Persistent Volume Claim (PVC) représentent la demande, les Persistent Volumes (PV) représentent quant à eux l’offre.
Un développeur demande donc des PVC et Kubernetes va approvisionner des PV s’intégrant avec différentes solutions de stockage.
Cette modélisation a des avantages mais aussi quelques inconvénients, notamment la disponibilité des disques lors d’un replacement (rescheduling) d’un conteneur : il faut pouvoir attacher et détacher le disque assez rapidement afin que l’application qui vient d’être replacée sur un autre nœud reste disponible. Cela suppose donc que la solution de stockage doit être très efficace en terme d’attachement et détachement de volume.
Le second défi est la gestion des pannes : lorsqu’un nœud subit une panne, les conteneurs qui montent un volume ne peuvent pas être replacés. La raison est simple : les nœuds masters sont incapables de savoir si les applicatifs sont en train d’écrire sur les disques.
En effet, si la panne concerne l’agent (la kubelet) tournant sur le nœud, les conteneurs eux tournent encore alors même que le nœud ne répond plus. Cela entraîne une vraie gêne pour le run, dans la mesure où à chaque panne de nœud les applicatifs avec un volume peuvent être en péril de disponibilité.
Donc si une application avec des volumes est placée sur un même domaine de panne (availabilty zone, hyperviseur, rack, etc.) l’application subira un down time très important, dans la mesure où les nœuds abritant l’application seront tous en panne et que Kubernetes ne détachera pas les volumes et ne replacera pas l’applicatif sur un autre nœud.
C’est un problème qu’on souhaite régler pour la version 1.15. (NDLR: la version 1.15 est sorti le 19 juin 2019).
Les cloud providers proposent des bases de données managées (AWS avec RDS, Google cloud SQL, Azure SQL DB). Ces solutions sont très pratiques : avec elles, pas besoin de se préoccuper du provisioning et du montage des disques, des backups, du monitoring, du compute ou de la RAM…
Est-ce que cela a du sens de faire tourner une base de données dans un cluster Kubernetes ?
C’est une question très légitime en effet, pour la majorité des cas d’usage faire tourner une base de données chez un fournisseur de cloud est suffisant.
Néanmoins pour des raisons de sécurité (cf. cloud act), de prix, de localisation près de la donnée ou simplement pour cause de régulation juridique, il peut être intéressant d’exécuter la base de données on premise ou à défaut le plus proche possible des applicatifs, c’est-à-dire co-localisée sur une même infrastructure.
Quels sont selon toi les points d’attention pour faire tourner une base de données dans Kubernetes ?
Pour faire tourner des bases de données ou plus généralement des applicatifs stateful il faut avoir une très bonne connaissance du métier de « DBA » (Database Administrator) ainsi qu’une très bonne connaissance système. Kubernetes permet peut-être de faciliter la gestion d’une base de données relationnelle mais il ne remplace certainement pas la connaissance métier sur les bases de données ou sur l’applicatif stateful qu’on veut faire tourner. On ne peut simplement pas faire le run de quelque chose qu’on ne comprend pas.
Pour la partie spécifique à Kubernetes, il faut avoir au préalable une connaissance assez fine des primitives stateful du style StatefulSet, PVC et PV. Ensuite il faut avoir une vision claire sur l’architecture du cluster Kubernetes, par exemple est-ce que les Pod Security Policy (PSP) sont activées et quelles sont les restrictions en termes de droit Unix pour les conteneurs stateful (par exemple, l’utilisateur avec lequel on doit tourner dans le conteneur groupe et le user auquel appartient le répertoire de données). Il faut aussi avoir en tête la gestion du capacity planning et se poser un certain nombre de questions :
- Où est-ce que j’en suis dans mes quotas,
- Quid de mon taux de remplissage de disque ?
- Est-ce que ma solution de stockage supporte le re-dimensionnement ?
- Comment je sauvegarde mes données ?
- Quels sont mes SLA sur le PRA (Plan de reprise d’activité).
Le sujet du multi montage de volume et aussi très important. Utiliser la mauvaise abstraction peut avoir des résultats désastreux qui peut mener deux replicas à écrire sur le même volume.
Tu as parlé tout à l’heure des backup. Est-ce que tu peux développer ?
La donnée a un rôle de plus en plus important dans le monde d’aujourd’hui. La question de la sauvegarde des disques est donc une des premières questions à se poser.
Il y a deux moyens pour le faire principalement : soit se reposer sur une feature alpha qui consiste à snapshot les volumes où à utiliser des outils qui se basent sur des Custom Resource Definition (CRD) afin d’offrir des mécanismes de sauvegarde plus natifs.
Un des désavantages de la première solution et que le snapshot n’est pas forcément consistant c’est-à-dire que si je suis en plein dans une transaction la sauvegarde sera corrompue. Ce mode est à privilégier donc lorsque la consistance de la donnée n’est pas une préoccupation. La seconde méthode offre une plus grande flexibilité car elle se base sur des mécanismes d’extension. Un des exemples est l’outil développé par Heptio qui s’appelle Velero. Ce dernier permet de spécifier ce qu’on appelle des hooks c’est-à-dire des commandes pre snapshot et post snapshot.
Il permet aussi de profiter de toute la puissance de l’abstraction fournie par Kubernetes par exemple on peut définir des politiques de sauvegarde qui vont être exécutées si une ressource est labellisée avec le bon label. Cela permet d’offrir du self-service aux utilisateurs.
Tu parlais tout à l’heure des solutions de stockage qui supportent le re-sizing. Qu’entends-tu par là ?
En ce moment on est dans une période de transition où les plugins de stockage commencent à être proposés au travers de l’interface CSI. Cette interface doit être respectée par n’importe quel plugin. Dans certains cas, les plugins ne sont pas encore assez matures pour supporter le redimensionnement ou alors le fournisseur de stockage ne supporte pas le redimensionnement. Il est donc très important de bien choisir son plugin si on n’utilise pas les plugins in tree à savoir ceux des fournisseurs Cloud. Une fois le plugin choisi il faut provisionner une Storage Class où il est indiqué que le redimensionnement est supporté.
Un des premiers bénéfices immédiats est que les équipes commencent à sous-dimensionner la taille des volumes et à redimensionner au besoin. Cela engendre un bénéfice économique réel lorsqu’on est un grand consommateur de stockage.
Quels sont les points d’attention d’un PRA dans un contexte Kubernetes ?
Quand on dit qu’on est en production il est nécessaire d’avoir un PRA en définissant un RTO (Recovery Time Objective) et un RPO (Recovery Point Objective) clairs.
Les types d’incidents qu’on peut observer sur une plate-forme comme Kubernetes peuvent être très complexes de par la nature distribuée du système. Il faut donc prendre ça en compte lors de la mise en place de ces indicateurs. Le PRA n’est pas un process ou du code que l’on met en place une fois et que l’on oublie, il faut être capable de le reproduire et de le maintenir il faut aussi s’assurer qu’il est toujours valable après les mises à jour de la plate-forme.
Le process de récupération peut être à plusieurs niveaux : perte de mon infra IAAS ? Perte de mes ETCD ? Perte du quorum sur ETCD ? Perte d’un datacenter, d’une zone ? Ce sont toutes ces questions qu’il faut se poser en amont et pour lesquelles il faut avoir des réponses précises et automatisées.
Quels sont les principaux défis du run sur un cluster Kubernetes ?
On constate qu’avec un modèle de run classique avec des niveaux de supports N1 N2 N3 N4, le coût d’OPEX (NDLR : coût d’exploitation) se trouve être beaucoup plus important lorsque une équipe qui fait le build s’occupe du run aussi. Pourquoi? La raison est simple : sur ce genre de système les niveaux N1 N2 et même N3 font « passe-plat ». L’un ne fait qu’escalader vers l’autre. Ceci est encore plus visible sur des problématiques de réseau ou de stockage par exemple sur le problème décrit plus haut lorsqu’un nœud est éteint et que les points de montage et l’attachement des disques n’est pas effectué. Il y a un certain nombre de commandes et une analyse à faire qui fait que seules les personnes ayant une certaine expertise sur la plate-forme peuvent effectuer. Il est donc faux de penser que Kubernetes seul peut transformer votre organisation. Il vous mettra en face de certains questionnements et faute d’y répondre, le projet fera face au risque de l’échec.
Tu as déjà vu du Kubernetes on premise ? Quid du stockage dans ce contexte ?
J’aime bien une phrase de David K. Rensin (Director of Customer Reliability Engineering chez Google Cloud Platform) :
Kubernetes sur du bare metal est le chemin le plus difficile qu’on peut choisir, mais il a comme avantage de garder tout sous votre contrôle.
En effet déployer un Kubernetes sur du bare metal ou on premise est assez dur. Les solutions de stockage ne sont en effet pas managées ! Heureusement que certaines solutions s’attaquent à cette problématique et visent à fournir des abstractions pour faciliter le management des solutions de stockage, notamment grâce à des opérateurs.
On voit de plus en plus d’acteurs (éditeurs ou communautés) proposer des opérateurs, notamment pour – on vient de le voir – le management du stockage. Quel est ton sentiment sur cette tendance ?
Les opérateurs sont un pattern qui a été mis en place par CoreOS afin d’encapsuler la logique métier dans du code et réagir à des changements d’état afin de manager de manière automatique des applications à état.
La communauté, les projets open source ainsi que des éditeurs de logiciels s’emparent de plus en plus du sujet car cela promet une abstraction et une automatisation au client, ce qui constitue donc un argument alléchant pour ce dernier.
Comme tout nouveau pattern, la maturité des implémentations diffère selon l’implication et la robustesse de l’équipe qui le maintient, il faut aussi noter qu’une solution mal conçue restera mal conçue – opérateur ou non. Il est donc très important de considérer l’architecture d’un produit ou d’un projet tout autant ou plus que la présence d’un opérateur afin d’automatiser les tâches de management.
On arrive à la dernière question. Quels conseils donnerais-tu à des personnes qui souhaitent s’investir dans la communauté Kubernetes ?
Je peux vous parler de mon expérience personnelle. Au début j’ai commencé à lire du code une fois par jour afin de m’habituer au style de code. Ensuite, j’ai commencé à essayer de lier la partie fonctionnelle c’est-à-dire quand j’utilisais Kubernetes à l’implémentation ce qui m’a permis de comprendre comment marchait le système. Après, j’ai commencé à contribuer sur des bug fixes afin de me faire connaître de la communauté. Ce n’est qu’après que j’ai commencé à proposer de nouvelles fonctionnalités et à ouvrir des issues pour compléter les fonctionnalités.
Pour résumer, les deux points essentiels qui je pense m’ont permis de devenir contributeur sont la lecture du code/revue de code ainsi que l’écriture de tests.