Aller au contenu principal

Concepts

L'offre Kubernetes proposée par NumSpot permet la mise à disposition de clusters Kubernetes clés en main. L'installation, la configuration et la maintenance du service sont assurées par NumSpot. L'utilisateur intéragit avec l'offre à travers la console ou les APIs NumSpot pour :

  • Créer des clusters
  • Consulter les informations des clusters (liste / détail / état)
  • Supprimer des clusters
  • Ajouter et supprimer des nœuds de travail (avec ou sans processeur graphique associé)
  • Mettre à jour la version de Kubernetes (plan de contrôle et nœuds de travail)
  • Mettre à jour le système hôte des machines des clusters
  • Obtenir les informations de connexion aux clusters (kubeconfig, clé d'accès SSH)

Le reste des opérations sur les éléments déployés dans les clusters (déploiement, configuration, sécurisation, maintenance, …) sont à la charge de l'utilisateur.

Qu'est-ce-que Kubernetes ?

Kubernetes est une plate-forme open-source extensible pour la gestion de charges de travail (workload) et de services conteneurisés. Elle se base sur une approche entièrement déclarative favorisant l'automatisation. Un vaste écosystème, souvent soutenu par la communauté, s'est formé autour d'elle afin d'augmenter ses fonctionnalités dans de nombreux domaines : sécurité, observabilité, réseau, stockage, intelligence artificielle et bien d'autres… Cet écosystème est en constante évolution et expansion.

Conteneurisation

Kubernetes orchestre les ressources machines, la mise en réseau et l’infrastructure de stockage sur les workloads des utilisateurs en se basant sur la technologie des conteneurs. Cette technologie, basée sur une virtualisation au niveau du système d'exploitation, consiste à déployer des conteneurs en isolation de l'hôte et des autres conteneurs : ils ont leurs propres systèmes de fichiers, ne peuvent voir que leurs propres processus et leur usage des ressources peut être contraint.

Étant donné que les conteneurs sont petits et rapides, une application peut être empaquetée dans chaque image de conteneur. Cette relation application-image tout-en-un permet de bénéficier de tous les bénéfices des conteneurs. Avec les conteneurs, des images immuables de conteneurs peuvent être créées au moment de la construction (build) des applications plutôt qu'au déploiement, vu que chaque application ne dépend pas du reste de la stack applicative et n'est pas liée à l'environnement de production. La génération d'images de conteneurs au moment du build permet d'obtenir un environnement constant qui peut être déployé tant en développement qu'en production. De la même manière, le monitoring et le management des conteneurs en est facilité. Cela est particulièrement vrai lorsque le cycle de vie des conteneurs est géré par l'infrastructure plutôt que caché par un gestionnaire de processus à l'intérieur du conteneur. Avec une application par conteneur, gérer ces conteneurs équivaut à gérer le déploiement des applications de manière unitaire.

L'utilisation des conteneurs au sein de Kubernetes offre de nombreux bénéfices :

  • Création et déploiement agile d'applications : augmente la simplicité et l'efficacité de la création d'images par rapport à l'utilisation d'images de VM
  • Développement, intégration et déploiement continus : fournit un processus pour construire et déployer fréquemment et de façon fiable avec la capacité de faire des rollbacks rapides et simples (grâce à l'immuabilité de l'image)
  • Séparation des besoins entre développeurs et opérations : création d'images applicatives au moment du build plutôt qu'au déploiement, tout en séparant l'application de l'infrastructure
  • Observabilité : informations venant non seulement du système d'exploitation sous-jacent mais aussi des signaux propres de l'application
  • Consistance entre les environnements de développement, tests et production : fonctionne de la même manière que ce soit sur un poste local que chez un fournisseur d'hébergement / dans le Cloud
  • Gestion centrée application : bascule le niveau d'abstraction d'une virtualisation hardware liée à l'OS à une logique de ressources orientée application
  • Micro-services faiblement couplés, distribués, élastiques : les applications sont séparées en petits morceaux indépendants et peuvent être déployées et gérées dynamiquement -- pas une stack monolithique dans une seule machine à tout faire
  • Isolation des ressources : performances de l'application prédictibles
  • Utilisation des ressources : haute efficacité et densité

Architecture

Composants du plan de contrôle

Les composants présentés ci-après fournissent le plan de contrôle du cluster. Ils prennent des décisions globales à propos du cluster, telles que la planification (scheduling). Ils détectent et répondent aux événements du cluster afin d'assurer que l'état déclaré pour les différents objets désirés correspond à l'état actuel des objets déployés (par exemple, démarrer un nouveau Pod lorsque le champ replicas d'un Deployment n'est pas satisfait). Ces composants sont typiquement exécutés de manière exclusive sur des machines dédiées, sur lesquelles on ne retrouvera pas de conteneurs utilisateur, appelées nœuds du plan de contrôle.

Serveur API

Le serveur API (kube-apiserver) est le composant principal de la plate-forme Kubernetes. Il expose l'API Kubernetes qui agit comme point d'accès au plan de contrôle du cluster en envoyant des demandes et ordres aux autres composants du plan de contrôle.

Base de données

La base de données (etcd) est de type clé-valeur. L'utilisation d'etcd permet une haute consistance et disponibilité des données qui sont utilisées par le plan de contrôle comme mémoire de sauvegarde de l'intégralité du cluster.

Ordonnanceur

L'ordonnanceur (kube-scheduler) surveille les Pods nouvellement créés qui ne sont pas assignés à un nœud et sélectionne le nœud adéquat sur lequel ils vont s'exécuter. Les facteurs pris en compte pour les décisions de planification (scheduling) comprennent les exigences individuelles et collectives en ressources, les contraintes matérielles/logicielles/politiques, les spécifications d'affinité et d'anti-affinité, la localité des données, les interférences entre charges de travail et les dates limites.

Gestionnaire de contrôleurs

Le gestionnaire de contrôleurs (kube-controller-manager) exécute les contrôleurs principaux du cluster.

Un contrôleur est un processus qui exécute une boucle de contrôle surveillant l'état partagé du cluster à travers le serveur API et effectuant des changements en essayant de déplacer l'état actuel vers l'état désiré.

Ce composant inclut différents contrôleurs ayant différentes responsabilités définies :

  • Contrôleur de nœud : responsable de détecter et apporter une réponse lorsqu'un nœud tombe en panne
  • Contrôleur de réplication : responsable de maintenir le bon nombre de Pods pour chaque objet ReplicationController dans le système
  • Contrôleur de point de terminaison : remplit les objets Endpoints permettant la jointure entre les Services et les Pods
  • Contrôleur de compte de service et de jeton : créent des comptes par défaut et des jetons d'accès à l'API pour les nouveaux espaces de noms

Composants des nœuds de travail

Les composants présentés ci-après s'exécutent sur chaque nœud, y compris les nœuds du plan de contrôle. Ils maintiennent les Pods en exécution et fournissent l'environnement d'exécution Kubernetes.

Agent kubelet

L'agent kubelet s'assure que les conteneurs fonctionnent dans les Pods. Il prend un ensemble de PodSpecs fournis par divers mécanismes et s'assure du fonctionnement et de la santé des conteneurs décrits dans ces PodSpecs.

Moteur de conteneur

Ce moteur fournit l'environnement d'exécution des conteneurs, il est responsable de leur exécution. Plusieurs environnements d'exécution sont compatibles avec Kubernetes. Les clusters Kubernetes fournis par NumSpot utilisent containerd.

Composants additionnels

Les composants présentés ci-après utilisent les ressources Kubernetes pour implémenter des fonctionnalités cluster. Comme ces derniers fournissent des fonctionnalités au niveau du cluster, leurs ressources appartiennent généralement à l'espace de nom kube-system.

Implémentation réseau

Ce composant est requis afin d'implémenter le modèle réseau de Kubernetes. Différentes implémentations de ce composant sont disponibles dans l'éco-système Kubernetes. Toutes ces implémentations doivent se conformer à la spécification Container Network Interface. Les clusters Kubernetes fournis par NumSpot utilisent cilium.

DNS

Ce composant est requis afin de servir les enregistrements DNS des services Kubernetes. Les conteneurs démarrés par Kubernetes incluent automatiquement ce serveur DNS dans leurs recherches DNS. Les clusters Kubernetes fournis par NumSpot utilisent coredns.

Métriques

Ce composant surveille les ressources des conteneurs, enregistre des métriques chronologiques génériques dans une base de données centrale et fournit une interface utilisateur pour parcourir ces données. Les clusters Kubernetes fournis par NumSpot utilisent metrics-server.

Objets Kubernetes

Workloads

Un workload est une application fonctionnant sur Kubernetes. Il peut être un composant unique ou un agrégat de composants fonctionnant dans un Pod unique ou une série de Pods. Dans Kubernetes, un Pod représente un ensemble de conteneurs en fonctionnement dans le cluster.

Les Pods Kubernetes ont un cycle de vie défini. Par exemple, quand un Pod est en fonction et qu'une panne critique survient sur le nœud où se situe ce Pod, tous les Pods du nœud seront en échec. Kubernetes traite ce niveau d'échec comme un état final. Un nouveau Pod devra être créé pour retrouver l'état initial, même si le nœud redevient sain.

Cependant, il est presque toujours inutile de gérer les Pods directement. D'autres objets sont mis à disposition afin de gérer un ou plusieurs Pods de manière centralisée et résiliente. Ces objets sont des boucles de contrôle auxquelles on indique une configuration et un nombre désiré de Pods. La boucle de contrôle va alors s'assurer en permanence que le nombre de Pods désirés est bien présent, avec la bonne configuration. Dès que l'état diffère, diverses actions seront entreprises afin de retrouver l'état désiré.

Kubernetes fournit plusieurs objets à cet effet :

  • Deployments et ReplicaSet : permettent de gérer des applications qui ne nécessitent pas d'état constant (stateless). Tous les Pods d'un Deployment sont interchangeables et peuvent être remplacés au besoin
  • StatefulSet : permet de lancer un ou plusieurs Pods en relation qui gardent plus ou moins la trace de leurs états. Les Pods d'un StatefulSet disposent d'un lien avec un volume persistant qui sera conservé si un redémarrage devait avoir lieu
  • DaemonSet : permet de définir des Pods qui effectuent des actions sur le nœud local. Pour chaque nouveau nœud, le plan de contrôle s'organise pour déployer les Pods des DaemonSets sur le nouveau nœud
  • Job et CronJob : tâches lancées jusqu'à leur accomplissement puis s'arrêtent. Les Jobs sont des tâches ponctuelles alors que les CronJobs sont des tâches récurrentes planifiées

Dans l’écosystème étendu de Kubernetes, des ressources supplémentaires proposées par des fournisseurs tiers offrent des fonctionnalités additionnelles. Ces ressources font appel aux CustomResourceDefinition.

Réseau

Dans un cluster Kubernetes, tous les Pods obtiennent une adresse IP (IPv4 et IPv6) unique au sein du cluster. Ceci signifie qu'il n'est pas nécessaire de créer explicitement des liens entre les Pods et qu'il n'est presque jamais nécessaire de faire correspondre les ports des conteneurs aux ports de leur hôte. Le modèle réseau qui en découle conserve alors une compatibilité avec les modèles précédemment utilisés par les machines virtuelles et hôtes physiques quant à l'allocation de port, la découverte des services, l'équilibrage de charge, la configuration des applications ainsi que les migrations.

Le modèle réseau de Kubernetes impose quelques règles qui doivent être respectées pour assurer le fonctionnement nominal du réseau au sein d'un cluster Kubernetes :

  • Tous les Pods peuvent communiquer avec les autres Pods sur n'importe quel nœud sans traduction d'adresse réseau (NAT)
  • Les agents d'un nœud (eg. daemon système, kubelet) peuvent communiquer avec tous les Pods de ce nœud

Ce modèle est principalement compatible avec le désir de Kubernetes de permettre le portage sans friction d'applications depuis des machines virtuelles vers des conteneurs. Dans le modèle réseau des machines virtuelles, les machines disposaient d'une adresse IP et pouvaient communiquer avec les autres machines virtuelles de l'environnement. Le modèle Kubernetes fournit les mêmes possibilités.

Les adresses IP existent au niveau des Pods tout comme les adresses MAC. Les conteneurs au sein d'un Pod partagent le même réseau. Cela signifie que tous les conteneurs d'un Pod peuvent communiquer avec les autres conteneurs du même Pod sur n'importe lequel de leur port en passant par la boucle locale (localhost). Cela signifie également que la gestion des ports doit être coordonnées entre les différents conteneurs d'un Pod, ce qui ne change pas du modèle réseau utilisé par les machines virtuelles. Les détails d'implémentation sont à la discrétion du moteur de conteneur utilisé.

Il est également possible de réserver un port sur le nœud lui-même afin de transférer le trafic vers un Pod, bien que cette opération n'est pas couramment utilisée. La manière dont cette fonctionnalité est implémentée est également à la discrétion du moteur de conteneur utilisé. Les Pod n'ont pas connaissance de l'existence ou absence d'un tel transfert de port.

Finalement, le modèle réseau de Kubernetes :

  • Permet d'utiliser la boucle locale pour communiquer entre les conteneurs au sein d'un Pod
  • Permet aux Pods de communiquer entre eux
  • Permet d'exposer publiquement les applications exécutées dans les Pods via les objets Service
    • Les objets Ingress fournissent une fonctionnalité additionnelle permettant d'exposer les applications HTTP, sites webs et APIs
    • Les API Gateway fournissent une famille d'API expressive, extensible et orientée sur les rôles afin de modeler des services réseau avancés
  • Permet d'exposer les applications exécutées dans les Pods via les objets Service uniquement au sein du cluster
Stockage

Pour les applications nécessitant un stockage persistant, Kubernetes fournit nativement différents mécanismes de stockage.

Les Volumes sont des répertoires accessibles depuis les conteneurs d'un Pod et qui sont liés non pas au cycle de vie des conteneurs mais au cycle de vie des Pods. Cela signifie que même si un conteneur est en échec, le volume reste accessible aux autres conteneurs du Pod. Plusieurs types de volumes sont disponibles (liste non exhaustive) :

  • emptyDir : volume éphémère lié au cycle de vie d'un Pod. Peut exister sur disque ou en mémoire
  • hostPath : volume qui monte un répertoire du nœud hébergeant le Pod. Utile pour accéder à des ressources du système hôte
  • nfs : volume qui monte un partage NFS
  • persistentVolumeClaim (PersistentVolumeClaim) : volume utilisant du stockage fournit par un PersistentVolume. Permet le provisionnement dynamique de stockage
  • configMap (ConfigMap) et secret (Secret) : volumes spéciaux permettant de rendre disponible le contenu des objets ConfigMap et Secret dans le système de fichier des conteneurs

Les PersistentVolumes sont des volumes existants indépendamment du cycle de vie des Pods. Un PersistentVolume est une unité de stockage qui a été provisionnée par un administrateur ou dynamiquement par une classe de stockage (StorageClass). Il abstrait l'implémentation du stockage sous-jacent, qui peut être du stockage cloud, du stockage réseau, du stockage local, …

Les PersistentVolumeClaims sont des demandes de stockage effectuées par un utilisateur. Un PersistentVolumeClaim spécifie la taille, le mode d'accès et la classe du stockage. Cet objet est similaire à la manière de réserver des ressources machines (CPU, mémoire), mais pour le stockage. Une fois le PersistentVolumeClaim créé, Kubernetes fait correspondre un PersistentVolume existant, tout en s'assurant que la taille du stockage demandée est disponible, et alloue le stockage.

Les StorageClass définissent le type de stockage et les politiques d'allocation dynamique pour les PersistentVolumes. Les détails de provisionnement du stockage sont abstraits (eg. SSH, HDD, stockage réseau, …) et permettent de spécifier les caractéristiques du stockage au travers de différentes classes. Les StorageClass font appel à des fournisseurs (eg. Ceph, NFS, AWS EBS, …) en spécifiant des paramètres spécifiques à ces fournisseurs (type de disque, réplication, chiffrement, …). Lorsque qu'un PersistentVolumeClaim est créé en spécifiant une StorageClass, Kubernetes provisionne dynamiquement du stockage en respectant les règles définies par celle-ci.

Kubernetes supporte le standard Container Storage Interface (CSI), qui permet aux fournisseurs de stockage de développer leurs propres implémentations pour s'intégrer de manière transparente. NumSpot fournit dans le cadre de ses offres OpenShift & Kubernetes un driver CSI pour les données de ses clients. Essentiel pour l'intégration et la gestion du stockage bloc, NumSpot facilite la flexibilité, l'automatisation et l'évolutivité nécessaires pour permettre à ses clients de gérer efficacement le stockage associé aux applications déployées dans leurs clusters.