4 décembre 2021

Kubernetes: pourquoi, pour qui, fiabilité, lock-in

Kubernetes est un sujet qui cristallise les passions. Comme on me l’a prouvé encore récemment, c’est un sujet sur lequel il est très difficile d’avoir une conversation sérieuse sans voir apparaître de la mauvaise foi et des approximations.

J’expliquerai dans cet article ma vision de cet outil, des problématiques qu’il résout, de pourquoi selon moi sa popularité explose.

Une définition rapide de Kubernetes

On peut trouver de nombreuses définitions de Kubernetes. En effet, les points de vues sur la technologie peuvent être différents entre une personne contribuant au projet, un ops chargé de son administration, un développeur l’utilisant pour déployer ses applications.

Voici quelques définitions qui me viennent en tête:

  • Une API et une base de données contenant l’état du monde, et des controllers exécutant des réconciliations.

  • Une plateforme extensible permettant d’abstraire de l’infrastructure.

  • Une abstraction pour déployer et gérer le cycle de vie d’applications.

Bref, Kubernetes peut être pris par différents bouts. Je ne rentrerai pas dans cet article sur comment Kubernetes fonctionne en détail, il existe déjà des tonnes de ressources sur le sujet (j’avais moi même écrit un article sur la configuration du control plane par exemple).

Pourquoi ?

Boucles de réconciliation

Le pattern utilisé par Kubernetes pour gérer le cycle de vie des ressources est je pense une très bonne idée. Avoir l’état du monde dans une base de données, une API devant pour gérer cet état, et des controllers dont le travail est de faire converger l’infrastructure vers l’état désiré est une technique très intéressante.

Le fait que Kubernetes ait popularisé cette pratique est une bonne chose.

Abstraire l’infrastructure

Kubernetes répond à plusieurs problématiques. Comme dit précédemment, c’est un outil permettant d’abstraire l’infrastructure sous-jacente. Il est également conçu pour que chaque composant soit interchangeable (ce qui se fait plus ou moins selon les composants, nous y reviendrons).

Cette abstraction de l’infrastructure via l’API de Kubernetes est intéressante. Elle permet de définir une certaine norme dans la façon dont les applications sont décrites: healthchecks, ressources allouées, configuration, secrets, ports réseaux, gestion des logs et des événements dans le cluster…​

Kubernetes gère également beaucoup de choses comme la tolérance aux pannes, mais j’en reparlerai un peu plus tard.

Portabilité

Cela a aussi un autre effet: que vous soyez sur un cluster Kubernetes on premise, sur une offre Kubernetes "as a service" dans le cloud, chez un ou différents fournisseurs, l’abstraction est (quasiment) la même.
En effet, les API de base du cluster sont toujours les mêmes. Une ressource de type Deployment aura par exemple le même format quel que soit le provider. Et cela est très intéressant. Je pense qu’aujourd’hui Kubernetes est la solution la plus intéressant pour éviter le "lock-in" chez un cloud provider par exemple, ou pour faire tourner des applications dans un mode "hybrid cloud".

Certaines ressources de Kubernetes ne sont pas 100 % portables. Par exemple, il existe un type de service appelé LoadBalancer permettant à Kubernetes (via un controller spécifique) de créer et configurer automatiquement des load balancers chez votre cloud provider et de les configurer automatiquement pour exposer vos services.

Bien que non portables, ces ressources sont quand même très intéressantes: une grande partie de leurs définitions est standardisée, seulement une petite partie est spécifique à un cloud en particulier. Voici par exemple une pull request que j’ai réalisé pour rajouter le support d’Exoscale pour l’ingress NGINX.
Seuls les annotations sont dans cette pull request spécifiques à Exoscale. Le reste est du Kubernetes standard (et le gros fichier YAML est autogénéré). Porter l’Ingress NGINX pour l’intégrer avec le load balancer d’Exoscale m’a donc demandé…​ l’ajout de 7 annotations.

C’est sur ce genre de ressources aux limites du cluster que Kubernetes peut manquer en portabilité. Mais comme montré, les changements sont en réalité assez faibles même ici dans la majorité des situations. Et au final rien ne vous oblige à les utiliser.

Je parle ici de ressources mais la portabilité au niveau du déploiement continu (ArgoCD, du monitoring (Prometheus par exemple), de la gestion des secrets (Vault) est aussi là. Toutes les briques citées fonctionneront aussi bien on premise que sur des offres cloud.

Il existe d’ailleurs une certification pour garantir que les offres Kubernetes fonctionnent correctement. les cloud providers doivent par exemple exécuter une batterie de tests à chaque nouvelle release mineure de Kubernetes pour pouvoir être certifiés.

Rendre les développeurs autonomes

Kubernetes permet de responsabiliser les développeurs et de leur fournir (avec un peu d’aide et d’outillage bien sûr) un moyen d’être autonome sur la gestion de leurs applications en production, entre autre:

  • Déployer de nouvelles applications, gérer leurs ressources et configurations

  • Gérer le déploiement de ces applications en production

  • Avoir une gestion des logs et du monitoring standard entre applications.

Bien que parfois Kubernetes soit un peu complexe sur certains sujets (j’y reviendrai), ceci est une réalité aujourd’hui. On revient ici sur le sujet de l’abstraction de l’infrastructure, où une certaine complexité va être (à raison) cachée aux développeurs, ces derniers pouvant se concentrer sur l’essentiel: déployer rapidement, souvent et de manière fiable (rollbacks, monitoring etc…​) leurs applications.

Pour qui ?

Qui peut être intéressé par Kubernetes ?

Je pense personnellement que bien que répondant à de nombreux besoins Kubernetes n’est pas pour tout le monde.

De nombreuses personnes ont des besoins très simples, par exemple une ou deux applications à faire tourner, Wordpress ou une base de données, quelques sites statiques. Il est beaucoup plus intéressant pour ces petits besoins de se tourner vers des PaaS et/ou des CDN qui feront très bien le travail.

Dans un autre extrême, peut être que certaines entreprises technologiques majeures ou ayant des besoin d’infrastructures particuliers atteindront les limites de Kubernetes, ou préféreront un outil répondant juste à leurs besoins. Ces entreprises avec ces besoins particuliers peuvent se permettre d’écrire des solutions en interne.

Le coeur de cible de Kubernetes est je pense les entreprises qui commencent à avoir 20, 30, 40…​ développeurs, un certain nombre de services et tout l’à côté à gérer. C’est comme vous le voyez volontairement assez vague, trancher à quel moment Kubernetes devient intéressant par rapport à une alternative est difficile et dépend de nombreuses choses.

Mais il arrive un moment où Kubernetes, et à fortiori les offres Kubernetes as a service deviennent intéressantes. Je mentionne encore une fois les offres as a service car bien qu’il soit possible de déployer du Kubernetes soit même (ce qui est très bien pour certains besoins), une offre as a service simplifiera beaucoup le travail pour un prix très raisonnable.

Je connais de nombreuses startups (pour être clair, déjà d’une certaine taille et avec un certain nombre de développeurs) qui bénéficient de Kubernetes au quotidien par exemple. Mon entreprise actuelle l’utilise depuis de nombreuses années (que ce soit pour déployer des applications ou pour construire des produits par dessus), et cela marche bien.

Bref, Kubernetes est là et son accessibilité (un appel API pour créer un cluster sur beaucoup de cloud providers) est un vrai atout.

Alternatives ?

Il existe des alternatives à Kubernetes. Personnellement, je n’ai jamais été fan des situations de monopole et il est vrai que Kubernetes a en quelque sorte "cannibalisé" l’écosystème DevOps.

J’ai déjà mentionné les PaaS précédemment pour les petits besoins. Pour le reste, une tendance forte actuelle est la migration vers d’autres solutions (notamment Kubernetes) quand une entreprise (et donc son SI) grossit, le PaaS se retrouvant vite limité au niveau des services proposés, de l’infrastructure (réseau par exemple), et causant des problèmes de lock-in.
A noter que garder une partie de l’infrastructure sur un PaaS ou CDN peut toujours être très intéressant, comme dit précédemment pour certains besoins cela reste pertinent. Rien n’empêche d’avoir quelques sites statiques, blogs, petites applications sur un PaaS et le reste sur Kubernetes.

On commence également à avoir de plus en plus de PaaS hybrides pouvant se déployer directement chez un cloud provider de votre choix. Cette approche est je trouve intéressante pour corriger les problèmes inhérents au PaaS, le futur nous dira si ça prend.

Côté orchestration, on a toujours Docker Swarm (mais son avenir est incertain), ou Nomad de Hashicorp. Ces solutions plus ou moins complètes mais malheureusement pour elles, l’accessibilité et la portabilité de Kubernetes sur le cloud font qu’elles ont du mal à décoller.

Il est également toujours possible de faire de l’infrastructure que je qualifierai de plus "classique": machines virtuelles, service discovery (Consul par exemple), outils d’infrastructure as code comme Ansible…​ Mais vous allez de toute façon devoir construire une abstraction pour les développeurs et ne pas les exposer directement au coeur de l’infrastructure mais en en leur permettant de travailler en autonomie.
A vous de voir si cela vaut le coup. La question à se poser dans ce cas est: est ce que l’alternative demandera moins de travail pour un résultat équivalent ?

Complexité

Stateful

Je n’ai pas parlé de services stateful comme des bases de données précédemment. Il fait sens selon moi d’utiliser des base de données as a service, ou d’installer des bases de données sur des machines virtuelles même si vous avez un ou des clusters Kubernetes de disponible.

Kubernetes permet de faire du stateful mais je pense personnellement que ça n’a pas forcément d’intérêts dans certains cas. Il vaut mieux selon moi, surtout si vous commencez avec Kubernetes:

  • Utiliser des base de données as a service de votre provider.

  • Déployer vos bases de données ou outils comme Kafka, RabbitMQ…​ sur des machines virtuelles classiques.

Il est possible de faire du stateful dans Kubernetes, qui comme il faut le rappeler est une boîte à outil: certaines primitives sont là. Cela demande un peu plus de travail et c’est pourquoi je pense qu’il vaut mieux dans certains cas ne pas essayer tout de suite de se lancer là dedans si des alternatives existent.
Par contre, pour monter des environnements de développement jetables, là ma réponse est différente. Kubernetes est très intéressant pour créer des bacs à sable. Si vous avez à déployer des dizaines, centaines instances de bases de données (ce qui, soyons franc, c’est un besoin plutôt rare) là Kubernetes peut sûrement avoir un intéret (mais je n’ai personnellement pas d’expérience sur le sujet).

CRD, operators

Kubernetes peut être étendu via par exemple des Custom Resources. Cela permet d’ajouter de nouveaux types de ressources à l’API Kubernetes et donc de pouvoir faire de nouvelles choses, en déployant de nouveaux controllers qui vont écouter ces ressources et faire des actions.

Je pense que l’ajout d’une CRD doit être quelque chose de réfléchi. L’API de base de Kubernetes est déjà vaste, et avec juste cette API de base et quelques outils de base (monitoring et déploiement continu par exemple) Kubernetes permet déjà beaucoup de choses. N’essayez pas d’aller trop loin trop vite, c’est le meilleur moyen de créer des problèmes.

Certains controllers mettent aussi, de manière assez surprenante, une pression énorme sur l’apiserver. Donc attention aussi à l’aspect performance (les frameworks modernes pour développer des CRD utilisent généralement un cache d’ailleurs).

Réseau

Le réseau dans Kubernetes n’est pas simple à appréhender, que ce soit au niveau des pods et des services mais aussi au niveau du control plane (j’y reviendrai). Là aussi, les offres as a service simplifient beaucoup les choses mais de bonnes notions en réseau sont utiles quand on travaille avec Kubernetes.

Coût d’entrée

Le coût d’entrée dans Kubernetes peut être important. Créer le cluster, comprendre les différents types de ressources, configurer le monitoring, gérer proprement ses manifests, les logs…​ sont autant de choses qu’il va falloir apprendre.
Toute la partie build et release des images de vos conteneurs est également importante. bref, Kubernetes tire beaucoup de choses (mais qui sont également nécessaires même sur d’autres solutions au final).

Kubernetes a aussi un coup organisationnel. C’est une nouvelle façon de travailler dans beaucoup d’entreprises, surtout celles faisant travailler leurs équipes "en silo".

Il y a un donc un investissement initial à faire, de la formation, et de nouvelles façons de travailler à mettre en place. Dans des équipes non matures sur les sujets évoqués précédemment, je pense que Kubernetes peut parfois causer plus de problèmes qu’autre chose. Se faire accompagner par un ou des experts peut être une alternative, mais une transition en douceur peut aussi être possible pour découvrir la technologie sur une partie limitée de l’infrastructure.

Opération

Maintenir un cluster Kubernetes on premise (donc sans utiliser une offre cloud) a un coût opérationnel. Gestion des composants du cluster, gestion des noeuds, des autorités de certification et du TLS dans le cluster demande des compétences solides.
Même les offres cloud demanderont de l’expertise pour la configuration du cluster, la mise en place d’outils, et pour pousser les bonnes pratiques à toutes les équipes.

Fiabilité

Est ce que Kubernetes est fiable ? Je dirai que oui.

Scalabilité

Kubernetes est souvent critiqué pour ses problèmes de scalabilité. C’est un non-problème selon moi. Voici les limites de Kubernetes selon sa documentation officielle à la date de publication de cet article:

No more than 110 pods per node
No more than 5000 nodes
No more than 150000 total pods
No more than 300000 total containers

Même en divisant ses nombres par 5, c’est énorme. Une majorité d’entreprises ne dépasseront pas les quelques dizaines de noeuds, ou centaines pour être gentil. Pour 99,99 % des besoins, Kubernetes est largement suffisant, surtout dans un monde ou plusieurs clusters sont généralement répartis sur plusieurs zones ou régions pour plus de robustesses.

Au quotidien

Je trouve Kubernetes stable. Pour l’utiliser depuis des années et avoir construit des produits complexes en l’utilisant comme base (avec parfois des use cases assez rares), je ne peux pas dire que Kubernetes ne marche pas ou n’est pas fiable.

Les clusters ont toujours bien réagit en cas de problèmes, et au final pas mal d’incidents peuvent passer inaperçu (perdre un noeud est un non événement, même si bien sûr il vaut mieux faire en sorte que ça n’arrive pas).

L’utilisation des services et du DNS interne du cluster simplifient la communication entre applications. Des outils comme ArgoCD sont géniaux, et l’objectif de rendre les développeurs maîtres de leurs applications en production est (globalement, j’y reviendrai) réussi.

Pour donner un exemple, des produits comme le load balancer as a service ou l’offre Kubernetes d’Exoscale utilisent beaucoup Kubernetes (pas de la façon dont vous pouvez le penser d’ailleurs pour le load balancer, c’est original) et au final…​ Je ne peux pas citer de tête un problème impactant l’utilisateur final sur un de ces produits à cause d’un problème dû à Kubernetes (et on parle de produits avec une astreinte 24/7).

Problèmes de Kubernetes

Kubernetes n’est pas parfait. J’ai déjà évoqué plusieurs problèmes précédemment, notamment dans la partie Complexité, et j’ai d’autres points qui me chiffonnent.

Control plane

Le control plane peut être difficile à configurer. De nombreux composants, de nombreux certificats et autorités de certification, avec une attention particulière à donner aux permissions de chaque composant. Ca se fait mais ça peut être pénible car la documentation n’est parfois pas claire, d’où mon article sur le sujet

Le réseau du control plane set aussi pénible. L’API server doit pouvoir joindre Kubelet (tournant sur les noeuds workers), Kubelet doit pouvoir joindre l’API server, et l’API server doit avoir accès au réseau interne du cluster pour l’aggregation layer.
Konnectivity a d’ailleurs été écrit pour répondre à ces problématiques, mais c’est encore une brique de plus à gérer. J’aurais aimé un système plus simple (même si on a aujourd’hui des outils comme k3s).

Une histoire d’abstraction

Kubernetes demande de nombreuses configuration pour sécuriser le cluster, les applications tournant dessus, et permettre à ces dernières de fonctionner correctement. Certaines choses complexes peuvent "leak" côté développeur, ce qu’il faut selon moi éviter. Par exemple:

  • les Network Policies (servant à ouvrir des flux réseaux dans le cluster, entre pods par exemple) sont je trouve très pénibles à écrire et source d’erreurs. Exposer cela aux développeurs à chaque fois qu’un nouveau service apparaît est pénible.

  • La gestion des secrets avec des outils comme Hashicorp Vault peut également être pénible: création d’init containers ou de sidecars pour récupérer les secrets par exemple.

  • Des choses comme les pod security policies (RIP bientôt) sont également complexes.

Je pense que si l’on veut rendre des développeurs vraiment autonomes sur ces sujets (et pas devoir demander de l’aide à chaque besoin de modification côté développeur) du travail est nécessaire côté ops pour simplifier au maximum ces configurations.
Par exemple, la majorité des besoins des développeurs sur les Network Policies sont "je veux que ce pod puisse parler à tel service/à tel pod". Ce besoin est simple mais écrire des Network Policies dans le format actuel est pénible.

Gérer les manifests

J’ai un avis mitigé sur Helm et Kustomize, les deux solutions les plus populaires pour gérer les manifests Kubernetes. Je suis sûr que d’autres solutions pour intéressantes émergeront.

TLS bootstrapping

Obligé d’écrire son propre controller pour valider les certificats serveurs de Kubelet. Cela peut se comprendre mais cela demande un peu de travail.

YAML blob

De nombreux outils dans l’écosystème Kubernetes demandent d’appliquer pour les déployer des milliers, voir dizaines de milliers de lignes de YAML.
Il y a sur certains outils une perte de maîtrise car on peut vite se retrouver dans un mode où l’on applique des YAML sans les comprendre, ce qui est toujours risqué.

N’oubliez pas non plus qu’appliquer un YAML est facile, mais ensuite il faudra également maintenir l’outil dans la durée.

Client Go/CRD

Il existe de nombreux frameworks pour interagir avec Kubernetes depuis Golang, comme par exemple Kubebuilder (qui utilise controller-runtime). Ces frameworks utilisent énormément la génération de code et sont peu flexibles. L’architecture de ces frameworks laisse également parfois à désirer (c’est d’ailleurs je trouve souvent le cas quand on regarde l’écosystème Kubernetes).
J’aimerai des efforts de simplification sur ces aspects. Golang n’aide pas non plus à produire des solutions élégantes.

Et je suis sûr que j’oublie des choses. Demander à de nouveaux utilisateurs de Kubernetes les points douloureux peut également être une bonne idée pour voir ce qui bloque. Bref, Kubernetes n’est pas parfait.

Discuter de Kubernetes

Je voulais évoquer dans ce dernier point les problèmes que l’on rencontre lorsqu’on discute de Kubernetes.

Certaines personnes rejettent complètement la technologie, ce qui en soit n’est pas du tout un problème. Il est au contraire intéressant de discuter de ce sujet, et comme dit dans cette article je ne recommande pas Kubernetes dans toutes les situations.
Je dirai même que la façon de travailler et l’organisation dans une entreprise sont plus importants que les technologies elles mêmes: pousser Kubernetes ne réglera pas tout vos problèmes par magie, surtout si ces derniers ne sont pas des problèmes techniques.

Il existe néanmoins une tendance chez certaines personnes à réagir très agressivement sur ce sujet. Kubernetes est le mal absolu, tout est à jeter, et si vous l’utilisez vous êtes soit un idiot soit vous avez des intentions cachées.
Ce discours est au final assez néfaste. Vous pouvez apporter toutes les preuves que vous voulez (retours d’expériences de production sur des années, REX divers…​), il n’y aura aucune écoute de l’autre côté et tout sera rejeté en bloc sans autre argument que "j’ai raison même si je ne sais pas pourquoi".
Débattre de cette manière est au final inutile.

On a aussi une partie des administrateurs systèmes qui rejettent la technologie. Parfois pour des raisons totalement valides (comme dit précédemment, il y en a), mais parfois avec des discours du type pas de conteneurs sur MA prod, MARRE DES DEVS, Pourquoi les gens veulent ça…​ ça ne vous rappelle rien ?

Le mythe du sysadmin grincheux n’est pas qu’un mythe. Au lieu de comprendre le besoin des développeurs, de se demander "mais pourquoi diable les conteneurs et Kubernetes sont si populaires", on a une réaction habituelle de rejet et d’enfermement dans son silo et de discours du type "je fais la même chose en 5 minutes en bash".
Cela montre selon moi une mauvaise compréhension du métier même d’administrateur système qui devrait au contraire être au service des développeurs et non là pour les dénigrer en permanence. API first, boucles de réconciliation, outillage, autonomie des développeurs sur la production, self service, monitoring efficace, autoscaling, rollbacks, fiabilité, chaos engineering, GitOps…​ C’est de ça dont je veux entendre parler. Et généralement, lorsque vous parlez de ces sujets à ces personnes, vous n’avez plus de réponses.

Vous ne souhaitez pas utiliser Kubernetes ? Cela peut tout à fait se comprendre. Apprendre de Kubernetes et étudier pourquoi sa popularité est ce qu’elle est aujourd’hui vous aidera à construire les solutions du futur si vous le souhaitez.

Tags: devops

Add a comment








If you have a bug/issue with the commenting system, please send me an email (my email is in the "About" section).

Top of page