Transformez votre Architecture applicative avec Kubernetes

Pour de nombreuses Entreprises, déployer une application en production peut être assimilé à un rituel plus qu’à de simples procédures.

 

La démocratisation de la conteneurisation avec Docker permet maintenant la standardisation des environnements et l’abstraction des spécificités de l’OS et du hardware, simplifiant grandement le déploiement.

 

Aujourd’hui la priorité est d’améliorer le déploiement et la gestion de ces conteneurs : c’est exactement ce que propose Kubernetes.

Architecture de Kubernetes : l’envers du décor

L’Architecture de Kubernetes est définie par deux types de nœuds :

  • Un nœud maître (appelé « Master ») chargé d’orchestrer le cluster (il ne contient pas d’autres services que Kubernetes)
  • Des nœuds esclaves (appelés « minions » ou « nodes »), correspondant à des hôtes Docker

Figure 1 : Architecture globale d’un cluster Kubernetes

 

Les outils en ligne de commande (proposés par le service « kubecfg ») se connectent à l’API endpoint lié au master, qui gère et orchestre tous les noeuds. Ces derniers correspondent à des hôtes Docker recevant des instructions provenant du master, et exécutant les conteneurs qu’ils hébergent.

La communication entre le master et les nodes (ainsi qu’à l’intérieur des nodes) est permise via un réseau privé interne au cluster, où chacune des ressources possède sa propre adresse IP afin d’être identifiée.

Ci-dessous les principaux éléments relatifs à l’utilisation de Kubernetes que nous étudierons dans cet article :

  • Kubelet : Service recevant des ordres du master qui gère leur exécution à travers les différents noeuds du cluster
  • Pod : Collection de conteneurs groupés, afin d’être déployés dans le même noeud (par exemple, une base de données et un serveur web conteneurisés)
  • Replication Controller : Objet définissant combien de pods ou de conteneurs doivent être en exécution. Ces conteneurs sont ordonnancés à travers de multiples noeuds
  • Service : Couche d’abstraction permettant la découverte de service/ports publiés par les conteneurs, ainsi que l’exposition de service. Un service mappe les ports d’un conteneur en exécution dans un pod à travers d’autres noeuds du cluster (via d’autres ports)

L’Architecture de Kubernetes est auto-réparatrice. En effet, lorsqu’on définit un pod, Kubernetes s’assure qu’il soit toujours opérationnel (i.e. en exécution). Si un conteneur venait à être détruit, il tentera automatiquement d’en redémarrer un autre.

De la même manière, si un Replication Controller est défini avec n répliques (le terme technique étant « replicas »), Kubernetes se chargera de veiller à ce que ces n répliques soient en fonctionnement, en redémarrant ou détruisant des conteneurs si nécessaire. Nous reviendrons sur ce qu’est un Replication Controller un peu plus tard dans cet article.

Au cœur de Kubernetes : Les Pods

Le pod est l’unité atomique de déploiement dans Kubernetes. Il regroupe un ou plusieurs conteneurs d’applications (généralement pas plus de 2), qui partagent une même adresse IP, le même espace partagé ainsi que les mêmes ports. Ils sont également exécutés sur le même nœud qui les héberge.

Les pods sont liés au nœud qui les déploie. Ils y demeurent jusqu’à leur expiration ou leur suppression. Dans le cas d’une défaillance du nœud, de nouveaux pods possédant les mêmes propriétés que les précédents seront déployés sur d’autres nœuds disponibles.

Figure 2 : Schéma représentatif des pods dans un nœud

 

Pour résumer, les pods s’exécutent toujours sur des nœuds. Un nœud (« node ») est une unité de travail dans Kubernetes pouvant être assimilée à une VM ou une machine physique. Chaque nœud exécute des pods et est géré par le nœud maître (« Master »). Il peut y avoir plusieurs pods dans un même nœud. L’ordonnancement des nœuds (le fait d’ordonner des tâches à exécuter aux nœuds selon certaines contraintes) est effectué de manière automatique par le master en fonction des ressources disponibles sur les nœuds.

Chaque nœud exécute au minimum :

  • Un conteneur d’exécution (Docker), qui permettra de récupérer l’ensemble des conteneurs à déployer depuis un registre
  • Kubelet, un agent qui servira de pont entre le master et l’ensemble des nodes du cluster. Il gère l’état des pods (et des conteneurs) exécutés sur une machine

Une Architecture Applicative fiable permise grâce à la réplication

Pourquoi répliquer nos applications ?

Avant de nous intéresser au fonctionnement de la réplication dans Kubernetes, rappelons brièvement pourquoi répliquer nos conteneurs.

3 bénéfices principaux peuvent être rendus :

  • Une meilleure fiabilité : en dupliquant n fois notre application, on peut anticiper les problèmes (et les pannes de service) si l’une d’entre elles venait à échouer
  • Du Load-Balancing : posséder plusieurs répliques d’une même application permet d’envoyer du trafic aux différentes instances, au lieu de surcharger une seule et même instance ou nœud. C’est une des fonctionnalités majeures proposée par Kubernetes
  • Le redimensionnement : Quand la charge devient trop importante pour le nombre de répliques existantes, Kubernetes permet d’effectuer la mise à échelle automatique sur l’application en ajoutant autant d’instances supplémentaires que nécessaire

Les types de réplication proposées par Kubernetes :

« Replication Controller »

Le Replication Controller correspond à la méthode originale de réplication dans Kubernetes. C’est une structure permettant de créer aisément plusieurs répliques d’un même pod, et qui s’assure que ce nombre de répliques en exécution soit toujours cohérent. Si l’on veut créer n répliques (n pouvant être variable), le Replication Controller redémarrera ou détruira des conteneurs afin qu’il y ait toujours n répliques opérationnelles du pod.

Si un pod venait à être détruit, le Replication Controller le remplace immédiatement. Il permet également d’effectuer la mise à échelle automatique sur les pods, la mise à jour ou encore des suppressions de pods.

« Replica Set » et « deployments »

Le Replica Set est la « nouvelle génération » de la réplication dans Kubernetes. Ils permettent les mêmes fonctionnalités de réplications que les Replication Controllers, en plus d’être dotés d’un nouveau type de « selector » (élément permettant de cibler le(s) pod(s) à répliquer). Il ne disposent cependant pas de fonctionnalités de mise à jour ou de suppression.

Ce sont les « deployments », qui définissent les Replica Set, et qui permettent l’ensemble des actions de mise à jour, de « roll back » (retour arrière lors de mauvaises manipulations) et de suppression.

Cette séparation entre les Replica Set et les deployments permet d’introduire une plus grande flexibilité au niveau de la gestion de la réplication. On préconisera donc cette démarche.

Exposition d’applications avec les services

Même si les pods ont leur propre adresse IP à travers le cluster, ces IP ne sont pas exposées à l’extérieur de Kubernetes. En tenant compte du fait que les pods peuvent être détruits ou remplacés par d’autres pods, il faut pouvoir permettre à l’ensemble des pods (et des applications) de se découvrir automatiquement entre eux.

Kubernetes répond à cette problématique en regroupant les pods dans des « services ». Un service Kubernetes est une couche d’abstraction qui définit une collection logique de pods et permet leur exposition à un trafic externe, du load-balancing et de la découverte de service entre eux.

Chaque service a sa propre adresse IP (unique pour le cluster) et expose un ou plusieurs ports afin de recevoir du trafic.

 

Figure 3 : schéma représentant les services dans un cluster Kubernetes

 

L’utilisation de labels selector (paires de clé/valeur liées à une ressource) permet d’identifier les pods et les services lors de leur utilisation. Les labels sont généralement employés pour :

  • Connaître l’environnement de production (prod, test, dev)
  • Savoir quelle est la version d’une application (beta, 1.3)
  • Différencier le type de service (back-end, front-end, BDD)

Figure 4 : schéma représentant les services dans un cluster Kubernetes

 

Comment s’assurer de la persistance de nos données avec Kubernetes ?

Les données et fichiers dans un conteneur sont éphémères, ce qui présente certains problèmes. En effet, lorsqu’une défaillance du conteneur se produit, Kubelet va tenter de le redémarrer mais les données contenues dans celui-ci seront perdues. De plus, lorsque plusieurs conteneurs s’exécutent ensemble dans un pod, il est souvent nécessaire de partager les fichiers (et données) entre eux.

« L’abstraction de volume » proposée par Kubernetes vient résoudre ces problèmes. Un volume est un simple dossier localisé sur disque ou dans un autre pod.

Si un volume est lié à un pod (il peut aussi être lié à des back-ends de stockage externes), il possède alors une durée de vie spécifique : la même que le pod qui le contient. Ainsi, un volume peut vivre plus longtemps que n’importe quel autre conteneur exécuté sur un pod, et les données sont préservées.

Quelques points d’attention lors de l’utilisation de Kubernetes

Malgré l’ensemble des louanges faites à travers le marché des orchestrateurs de conteneurs, il existe quelques limites à l’utilisation de l’outil. Le déploiement initial d’une application avec de la mise à échelle est un travail complexe et difficile à mettre en place. Des compétences spécifiques à l’outil sont requises.

De plus, concernant l’administration du réseau (notamment le SDN), Kubernetes impose 3 prérequis fondamentaux afin de fonctionner :

  • Tous les conteneurs peuvent communiquer avec les autres conteneurs sans NAT
  • Tous les nodes peuvent communiquer avec tous les conteneurs (et vice versa) sans NAT
  • L’IP visible d’un conteneur est la même aussi bien à l’intérieur de ce dernier que pour les autres conteneurs

Cela signifie qu’on ne peut pas simplement prendre deux machines exécutant Docker et s’attendre à ce que Kubernetes les gère. On doit s’assurer que les exigences soient respectées. Pour cela, on peut par exemple utiliser une surcouche réseau appelée Flannel (solution recommandée par Kubernetes).

Aussi, il n’existe pas vraiment de fonctionnalités liées à la sécurité dans le cluster. Pour permettre l’isolation d’application lors de leur exposition, il faut créer des règles d’acceptation de trafic appelées « Network policies ». Pour gérer les droits/accès des utilisateurs, il faut définir des « namespaces » et y assigner des utilisateurs manuellement.

Finalement, Kubernetes est une solution qui implémente de nombreuses fonctionnalités permettant d’améliorer la gestion d’une infrastructure applicative clusterisée. À l’heure de la grande tendance des technologies liées à la conteneurisation (comme Docker), tout l’enjeu réside dans l’orchestration à grande échelle des conteneurs. C’est dans cette perspective que vient se positionner Kubernetes en tant que solution prédominante sur le marché.

Aller plus loin

Pour en savoir plus sur Kubernetes et son utilisation :

  • Toute la documentation liée à Kubernetes :

https://kubernetes.io/docs/home/

  • La description et un exemple de prise en main de chacun des éléments cités précédemment :

http://kubernetesbyexample.com/

  • Tutoriel interactif de la solution (d’où proviennent l’ensemble des illustrations) :

https://kubernetesbootcamp.github.io/kubernetes-bootcamp/index.html

Auteur : Tahar Sayagh

Cloud Architect - DevOps Engineer