Par Maxime Jumelle
CTO & Co-Founder
Publié le 8 juin 2023
Catégorie Cloud / DevOps
Kubernetes (d'abréviation K8s) est un outil extrêmement populaire dans le Cloud et qui est devenu, en quelques années, la référence en terme de déploiement d'applications dans le Cloud. Mais pourquoi (et surtout comment) Kubernetes est devenu la solution incontournable ?
Reprenons la définition officielle : « Kubernetes (K8s) est un système open-source permettant d'automatiser le déploiement, la mise à l'échelle et la gestion des applications conteneurisées ». En d'autres termes, avec Kubernetes, nous allons pouvoir déployer et mettre à l'échelle des applications ou des API développés dans n'importe quel langage, tant que ce dernier est conteneurisé (avec Docker par exemple).
Dans cet article, nous allons étudier le fonctionnement de Kubernetes. De prime abord, il peut y avoir des confusions lorsque l'on débute avec Kubernetes, notamment par le fait qu'il y a beaucoup de concepts à appréhender mais également une multitude de paramètres lorsqu'il faut déployer des applications. Mais heureusement, avec les Clouds publics, toute la difficulté technique est mise de côté pour se concentrer à l'essentiel : le développement.
Kubernetes est un projet qui a été à l'origine développé chez Google. Initialement, cela fait plus de 15 ans que Google utilise en interne son propre orchestrateur de conteneurs, qui à l'époque s'appelait Borg. Les besoins de Google en terme de gestion de conteneurs était clair : délivrer quotidiennement des centaines de milliers de conteneurs au sein de leur infrastructure globale. Borg, écrit en Go, était donc leur propre solution.
Au final des années, les besoins d'orchestration de conteneurs se sont ressenties au sein d'autres entreprises. Bien qu'il y avait Docker Swarm, l'orchestrateur de conteneurs développé par les créateurs de Docker, ce dernier ne remplissait pas globalement sa mission. Il fallut attendre 2014 pour que Google développe son propre orchestrateur en se basant sur sa forte expérience de gestion des conteneurs acquise avec Borg. Rendu open-source et légué à la CNCF, Kubernetes est aujourd'hui la référence incontournable et détrône les autres solutions telles que AWS ECS ou Docker Swarm.
À lire aussi : découvrez notre formation Cloud DevOps
Pour bien comprendre la très forte popularité de Kubernetes, il nous faut bien comprendre son fonctionnement et son écosystème.
Tout d'abord, l'écosystème est un point central lorsque l'on parle d'un projet open-source. Outre ses nombreuses mises à jours et améliorations, le système de configuration de Kubernetes est très flexible et permet à tout moment de mettre à jour des applications en continu sans perturber leur fonctionnement. Ensuite, Kubernetes est présent dans la plupart des fournisseurs Cloud, aussi bien chez Google que AWS, Azure ou encore Digital Ocean. Enfin, de nombreuses applications de références et des templates sont disponibles pour déployer très rapidement des solutions puissantes.
Avant toute chose, il faut bien évidemment présente le cluster Kubernetes dans son ensemble. Il s'agit de l'environnement constitué de serveurs physiques sur lesquels se base Kubernetes. Par l'intermédiaire de commandes systèmes, nous pouvons agir sur les différents objets du cluster par des opérations de lecture (get), de création (create), de mise à jour (patch) ou de suppression (delete). Ces 4 opérations, qui rappellent fortement les opérations CRUD, sont essentielles sous K8s (pour Kubernetes). Et c'est justement kubectl
qui va nous permettre d'interagir avec l'ensemble du cluster en communiquant avec l'API de K8s appelée API Objects.
Par exemple, kubectl get
signifie que l'on souhaite voir/lister des informations sur une ou plusieurs ressources, alors que kubectl patch
permettra de mettre à jour lesdites ressources.
Une des difficultés de K8s est qu'il y a beaucoup d'objets qui peuvent être difficiles à appréhender. Tout d'abord, commençons par les trois objets élémentaires.
Un Node (noeud) est un serveur physique/VM du cluster K8s qui exécute des conteneurs. Très souvent, ce n'est pas à nous de gérer les serveurs dans les Clouds publics. En revanche, nous devons plusieurs paramètres, dont la taille du cluster (nombres de noeuds), les ressources allouées à chaque noeud et les interfaces réseaux.
Un Pod est un objet central sous K8s. Il s'agit d'une isolation logique d'un ou de plusieurs conteneurs au sein d'un seul noeud. Un pod peut contenir un ou plusieurs conteneurs. Par exemple, supposons qu'une entreprise propose un environnement isolé contenant une application et une base de données pour chaque client, alors un pod serait attribué à chaque client et chaque pod contiendrait deux conteneurs : l'application et la base de données.
Ce sont notamment les pods qui vont être crées lorsqu'il y aura des montées en charge ou lorsque de nouvelles applications seront développées et déployées avec K8s.
Un Volume est un système de gestion de fichier qui peut être partagé entre les pods. C'est notamment utile lorsque des conteneurs, exécutés sur des pods différents (et potentiellement des noeuds différents), souhaitent partager des données sous forme de fichiers. Attention tout de même, la notion de volume sous K8s n'est pas persistante : le volume et les données seront détruits si le pod associé est supprimé. Pour cela, on utilise plutôt des PersistentVolume, bien qu'il ne soit tout de même pas conseillé d'y stocker des données de types relationnelles ou sensibles.
Les services fournissent une couche d'abstraction qui englobe un ensemble de pods et permet un trafic extérieure par des services d'équilibrage de charge et de découverte. Dans un cluster K8s, chaque service représente potentiellement une application accessible depuis l'extérieur, et exécutée dans plusieurs pods sur un ou plusieurs noeuds. Une adresse IP interne est attachée à ce service, permettant d'équilibrer le trafic parmi tous les pods du service.
Par exemple, nous avons ici deux services. Le premier service A contient un seul pod, lui-même exécuté sur un seul noeud. Ce service, qui possède une adresse IP interne 10.10.9.1
, permet de rediriger automatiquement le trafic vers le seul pod qu'il contient, d'adresse IP interne 10.10.10.1
.
Le second service B contient 3 pods exécutés sur 2 noeuds différents. La particularité ici est que chaque pod possède une adresse IP interne, mais le service, par l'intermédiaire de son adresse IP interne 10.10.9.2
, permet d'équilibrer le trafic parmi les 3 pods.
À lire aussi : découvrez notre formation Cloud DevOps
Ce qui est particulièrement intéressant, c'est d'être capable de centraliser les connexions dans l'équilibreur de charge, qui sera ainsi capable de répartir le trafic parmi tous les pods. Que l'on dispose de 2, 10 ou 100 pods, le trafic sera toujours redirigé grâce au service associé avec des techniques d'équilibrage de charge. De plus, nous pouvons créer autant de services que l'on souhaite, c'est-à-dire que des applications différentes peuvent être exécutées sur un seul et même cluster K8s.
kubectl
kubectl
est une interface en ligne de commande (CLI) utilisée pour interagir avec les clusters Kubernetes. Par exemple, il est possible d'afficher l'ensemble des noeuds d'un cluster avec la commande suivante.
kubectl get nodes
NAME STATUS ROLES AGE VERSION gke-cluster-test-pool-basique-adc59512-5044 Ready <none> 12m v1.16.15-gke.6000 gke-cluster-test-pool-basique-adc59512-v60w Ready <none> 12m v1.16.15-gke.6000 gke-cluster-test-pool-basique-adc59512-z6s1 Ready <none> 12m v1.16.15-gke.6000
La commande kubectl
suit une structure à plusieurs niveaux dans sa syntaxe, où chaque niveau correspond à une catégorie/action précise.
kubectl [niveau1] [niveau2] [niveau3] ... [niveauN]
create
, get
, apply
, delete
ou encore describe
.pod
, service
, deployment
, namespace
, configmap
, etc. Cette partie de la commande spécifie la ressource sur laquelle vous voulez agir.Au dessus du niveau 3 : à partir du niveau 3, cela correspond à un sous-ensemble spécifique de la ressource sur laquelle l'action va être effectuée. Par exemple, si l'on souhaite décrire un pod spécifique, il faut alors spécifier le nom du pod à ce niveau.
Lançons un premier pod avec une image Docker. La commande run
permet d'exécuter un conteneur Docker dans un pod.
kubectl run pod-test --image=blentai/docker_test:latest
pod/pod-test created
Après quelques secondes, nous pouvons voir que le pod est opérationnel avec kubectl get pods
.
NAME READY STATUS RESTARTS AGE pod-test 1/1 Running 0 11s
Testons si le pod fonctionne correctement en exécutant une commande directement à l'intérieur du pod. L'image Docker exécutée dans le pod est une API REST tout simple qui s'exécute sur le port 80.
kubectl exec pod-test -t -- wget -O - localhost
Connecting to localhost (127.0.0.1:80) - 100% |*******************************| 8 0:00:00 ETA Coucou !
La commande kubectl exec
permet d'obtenir un shell (terminal) dans un pod : cela permet par exemple de lancer des requêtes comme si le pod était une machine virtuelle et que nous y étions connecté en SSH. Vient ensuite le nom du pod auquel nous souhaitons exécuter la ou les commandes, puis l'argument -t
qui affichera le résultat de la commande en sortie standard (sur notre terminal). Ensuite, les double tirets --
permettent de séparer les arguments du kubectl exec
et les commandes Shell qui seront écrites par la suite.
L'instruction qui sera exécuté sur le pod pod-test
est wget -O - localhost
: cela signifie que nous allons envoyer une requête HTTP sur le port 80 du pod en affichant (avec -O -
) le contenu en sortie standard.
Jusqu'ici, nous avions crée un pod en spécifiant une image directement par ligne de commande. Mais lorsque l'on commence à avoir beaucoup de paramètres, il devient plus intéressant d'utiliser des fichiers de configuration qui détaillent tous les paramètres liés au pod. Ces fichiers sont édités en YAML et seront directement utilisé par K8s pour instancier de nouveaux pods.
apiVersion: v1 kind: Pod metadata: name: pod-test spec: containers: - name: pod-test image: blentai/docker_test:latest ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
Étudions les premiers champs.
apiVersion
est un champ obligatoire qui permet de spécifier quelle version API Objects nous utilisons.kind
est important puisqu'il permet de spécifier, dans chaque fichier de configuration YAML, de quelle type de ressource il s'agit.metadata
permet d'ajouter des métadonnées à la ressource, dont name
est l'attribut le plus important.spec
est un champ qui contient tous les attributs de la ressource kind
. Puisqu'il s'agit d'un pod, nous spécifions les informations de containers
, dont l'image Docker, le nom ou le port d'écoute.Il y a également deux autre spécifications très importantes : celles des ressources, avec notamment les champs requests
et limits
.
requests
mentionnent les ressources minimales qui seront attribuées au pod. Cela permet de s'assurer qu'il n'aura pas en dessous d'un certain niveau de mémoire ou de processeur.limits
mentionnent les ressources maximales qui peuvent être utilisées par le pod. Dans certains cas, il pourra évoluer entre les deux mais il sera limité par K8s pour ne pas consommer plus de ressources que celles définies en limites.On voit tout l'intérêt ici de correctement dimensionner le pool de noeuds, car il faut vérifier que le ratio mémoire/CPU des pods est cohérent avec celui des noeuds. Par exemple, si le ratio mémoire/CPU des noeuds est de 2 alors que celui des pods est de 3, alors un certaine partie des processeurs des noeuds ne seront pas utilisés car la limite en terme de mémoire sera atteinte, mais pas celle en terme de processeurs.
Maintenant que notre fichier de configuration est prêt, nous pouvons exécuter notre pod avec la commande apply
.
kubectl apply -f pod-test.yaml
pod/pod-test created
Regardons de plus près les configurations du pod pod-test
.
kubectl describe pod pod-test
Containers: pod-test: Container ID: docker://e98c547a34c03ceaa311a4d18317602bc5d1cfb6d9767651b8738a7aa61972e0 Image: blentai/docker_test:latest Image ID: docker-pullable://blentai/docker_test@sha256:49a59971411a725506c6269e5809b0904287ee514806d380c6425d3303d7b601 Port: 80/TCP Host Port: 0/TCP State: Running Started: Mon, 25 Jan 2021 22:24:35 +0100 Ready: True Restart Count: 0 Limits: cpu: 500m memory: 128Mi Requests: cpu: 250m memory: 64Mi Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-54clp (ro)
Nous voyons que les seuils limits
et requests
sont à présent fonctionnels.
Vous souhaitez vous former au Cloud / DevOps ?
Articles similaires
28 févr. 2024
Pour de nombreuses entreprises, innover chaque jour en proposant des applications à ses utilisateurs est un sujet primordial. Pour autant, cette course au déploiement continu de nouvelles applications nécessite des compétences bien particulières sur les architectures Cloud, l'automatisation de projets et la supervision. C'est à partir de ce moment qu'intervient le rôle de l'ingénieur DevOps dans les entreprises.
Maxime Jumelle
CTO & Co-Founder
Lire l'article
23 févr. 2024
Dans le monde du DevOps, les conteneurs sont rapidement devenus des incontournables, aussi important que les machines virtuelles. Des plateformes de conteneurisation comme Docker ont permis de simplifier et d'accélérer la création d'image et l'exécution de conteneurs sur différents systèmes, à portée de tous.
Maxime Jumelle
CTO & Co-Founder
Lire l'article
16 févr. 2024
Dans l'approche GitOps, il existe de nombreux outils permettant d'exécuter des pipelines CI/CD : certains se concentrent uniquement sur la partie intégration continue, d'autres avec le déploiement en plus. S'il y en a un qui est considéré comme l'un des plus matures et des plus robustes, c'est bien GitLab.
Maxime Jumelle
CTO & Co-Founder
Lire l'article
60 rue François 1er
75008 Paris
Blent est une plateforme 100% en ligne pour se former aux métiers Tech & Data.
Organisme de formation n°11755985075.
Data Engineering
IA Générative
MLOps
Cloud & DevOps
À propos
Gestion des cookies
© 2024 Blent.ai | Tous droits réservés