← Retourner à la liste des articles
Image blog
Auteur

Par Maxime Jumelle

CTO & Co-Founder

Publié le 8 juin 2023

Catégorie Cloud / DevOps

Tutoriel Kubernetes : premiers pas

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 ?

Logo Kubernetes

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.

Concepts de Kubernetes

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 info : L'orchestration de conteneurs vise précisément à faciliter l'administration de conteneurs par des outils d'automatisation, de mise à l'échelle et de haute disponibilité.

Pour bien comprendre la très forte popularité de Kubernetes, il nous faut bien comprendre son fonctionnement et son écosystème.

L'écosystème Kubernetes

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.

Cluster Kubernetes

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.

Objets K8s

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.

Nodes Kubernetes

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.

Pods Kubernetes

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.

Services

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.

Services Kubernetes

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.

Ligne de commande 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]
  • Niveau 1 : le premier niveau représente l'action générale que l'on souhaite effectuer, comme create, get, apply, delete ou encore describe.
  • Niveau 2 : le deuxième niveau représente le type de ressource Kubernetes sur lequel on souhaite appliquer l'action du niveau précédent. Par exemple, on peut spécifier 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.

Configuration YAML

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.
  • Le champ kind est important puisqu'il permet de spécifier, dans chaque fichier de configuration YAML, de quelle type de ressource il s'agit.
  • Le champ 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.

  • Les spécifications 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.
  • À l'inverse, les spécifications 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

Blog

28 févr. 2024

Cloud / DevOps

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

Maxime Jumelle

CTO & Co-Founder

Lire l'article

Blog

23 févr. 2024

Cloud / DevOps

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

Maxime Jumelle

CTO & Co-Founder

Lire l'article

Blog

16 févr. 2024

Cloud / DevOps

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

Maxime Jumelle

CTO & Co-Founder

Lire l'article