Aller au contenu principal
KubernetesDevOpsFormation

Pourquoi Kubernetes ? L'orchestration expliquée

74 min de lecture Apprendre Kubernetes — Chapitre 1

Découvre pourquoi Kubernetes est devenu le standard de l'orchestration : architecture, concepts fondamentaux et installation locale.

Ce chapitre est gratuit

Pas besoin de compte pour le lire. Decouvre le contenu et decide si le programme est fait pour toi.

Voir les autres chapitres

Un conteneur, c’est cool. Cent conteneurs, c’est le chaos.

Tu sais utiliser Docker. Tu sais créer des images, lancer des conteneurs, exposer des ports. Nickel. Mais maintenant, imagine la situation suivante :

Tu gères une application en production. Elle a :

  • 3 conteneurs pour l’API
  • 2 conteneurs pour le frontend
  • 1 conteneur pour la base de données
  • 1 conteneur pour le cache Redis
  • 1 conteneur pour le worker de tâches en arrière-plan

Ça fait 8 conteneurs. Gérable à la main ? Peut-être. Maintenant, multiplie par 10. Tu as 80 conteneurs répartis sur 15 serveurs.

Qui redémarre un conteneur quand il plante à 3h du matin ? Toi ? Non merci.

Qui ajoute des conteneurs quand le trafic explose un vendredi soir ? Un script bash fragile ? Bon courage.

Qui déploie la nouvelle version sans couper le service ? Tu vas vraiment arrêter tous les conteneurs, mettre à jour, et relancer en priant ?

C’est exactement là que l’orchestration entre en jeu. Et l’orchestrateur qui a gagné la bataille, c’est Kubernetes.

L’analogie du manager d’hôtel

Pour bien comprendre le rôle de Kubernetes, imagine un hôtel avec 100 chambres. Chaque chambre représente un conteneur. Tu as besoin d’un manager qui :

  • Attribue les chambres aux clients → place les conteneurs sur les bons serveurs
  • Vérifie que tout fonctionne → si une chambre a un problème, il en attribue une autre automatiquement
  • Gère l’affluence → plus de clients ? On ouvre des chambres supplémentaires
  • Organise les rénovations → mettre à jour une chambre sans mettre le client dehors
  • Gère les accès → qui peut aller où, avec quelle clé

Kubernetes, c’est ce manager. Tu lui dis “je veux 5 instances de mon API, toujours disponibles” et il se débrouille. Un serveur tombe ? Il relance les conteneurs ailleurs. Le trafic double ? Il en crée de nouveaux. Une nouvelle version arrive ? Il fait la transition en douceur.

🧠 À retenir : Kubernetes ne fait pas tourner tes conteneurs directement. Il déclare un état souhaité et s’assure en permanence que l’état réel y correspond. C’est le principe du contrôle déclaratif : tu dis “je veux 3 réplicas de mon API”, Kubernetes fait le nécessaire pour que ce soit toujours le cas.


Pourquoi Kubernetes s’est imposé ?

Avant K8s, il existait d’autres solutions d’orchestration : Docker Swarm, Apache Mesos, HashiCorp Nomad… Kubernetes a gagné, et de loin. Voici pourquoi :

Une base solide : 15 ans d’expérience Google

Kubernetes n’est pas sorti de nulle part. Google utilisait un système interne appelé Borg depuis le début des années 2000 pour orchestrer des millions de conteneurs dans ses datacenters. Quand Google a open-sourcé Kubernetes en 2014, c’était une version repensée de cette expertise.

🔥 Cas réel en entreprise : Chez Google, Borg gère des workloads massifs — Gmail, YouTube, Google Search. Chaque semaine, Google lance environ 4 milliards de conteneurs. Kubernetes est le fils spirituel de cette infrastructure. Quand tu utilises K8s, tu bénéficies de patterns éprouvés à une échelle que peu d’entreprises atteignent.

L’écosystème et la communauté

Kubernetes a un avantage écrasant : sa communauté. C’est le projet le plus actif de la CNCF (Cloud Native Computing Foundation) avec :

  • Plus de 88 000 étoiles sur GitHub
  • Des milliers de contributeurs (Google, Red Hat, Microsoft, Amazon, VMware…)
  • Un écosystème d’outils massif : Helm, Istio, ArgoCD, Prometheus, Grafana, Cert-Manager, Tekton…

Le standard de l’industrie

Tous les grands cloud providers proposent un Kubernetes managé :

Cloud ProviderService Kubernetes
AWSEKS (Elastic Kubernetes Service)
Google CloudGKE (Google Kubernetes Engine)
AzureAKS (Azure Kubernetes Service)
OVHcloudManaged Kubernetes
DigitalOceanDOKS
ScalewayKapsule

💡 Tip DevOps : En entreprise, tu travailleras rarement avec un cluster “bare metal”. La plupart des boîtes utilisent un Kubernetes managé (EKS, GKE, AKS). Le control plane est géré par le cloud provider — tu n’as qu’à te soucier de tes workloads. Mais comprendre l’architecture complète est indispensable pour debugger les problèmes en production.

Et les alternatives ?

Pour être honnête, les alternatives existent encore et ont leurs use cases :

  • Docker Swarm → Plus simple à configurer, mais écosystème limité. Docker Inc. a officiellement arrêté Swarm Mode dans Docker Desktop.
  • Nomad (HashiCorp) → Excellente alternative, plus simple que K8s, supporte les conteneurs ET les VMs. Adopté par certaines boîtes qui trouvent K8s trop complexe.
  • Amazon ECS → Spécifique AWS, pas d’orchestration multi-cloud.

Mais dans les offres d’emploi DevOps, c’est K8s qui domine massivement. Si tu dois choisir un orchestrateur à apprendre, c’est celui-là.

🧠 À retenir : Kubernetes n’est pas “le meilleur” dans l’absolu. C’est le standard. Et en informatique, le standard gagne souvent sur le meilleur (voir VHS vs Betamax, TCP/IP vs OSI). Le savoir-faire K8s est transférable partout : d’AWS à GCP, d’une startup à un grand groupe.


Prérequis

Avant d’aller plus loin, assure-toi d’avoir les bases suivantes :

  • Docker — Tu sais créer des images, lancer des conteneurs, écrire un Dockerfile et utiliser docker-compose
  • Linux — Tu es à l’aise dans un terminal (naviguer, éditer des fichiers, gérer des processus)
  • Réseau — Tu comprends les concepts d’IP, ports, DNS et load balancing
  • YAML — Tu sais lire et écrire du YAML (c’est le langage de configuration de Kubernetes)

⚠️ Attention : Si tu ne maîtrises pas Docker, arrête-toi ici. Kubernetes orchestre des conteneurs — il ne les remplace pas. Sans une bonne compréhension de Docker, tu vas te perdre dans l’abstraction. Reviens après avoir suivi une formation Docker complète.

Ce que tu vas apprendre dans ce chapitre

  • ☸️ Pourquoi l’orchestration de conteneurs est nécessaire
  • 🏗️ L’architecture de Kubernetes (control plane, worker nodes, composants)
  • 📦 Les concepts fondamentaux : Pods, Deployments, Services, Namespaces
  • 🛠️ Installer un cluster local avec Kind et utiliser kubectl
  • 🚀 Déployer ta première application sur Kubernetes
  • 🔍 Inspecter, debugger et gérer tes ressources K8s

Architecture de Kubernetes

Comprendre l’architecture de K8s, c’est la clé pour debugger efficacement en production. On va décortiquer chaque composant.

Un cluster Kubernetes se compose de deux grandes parties :

  • Le Control Plane (le cerveau) — il prend les décisions
  • Les Worker Nodes (les bras) — ils exécutent les conteneurs

Schéma d’architecture

graph TB
  subgraph CP["Control Plane"]
    API[API Server]
    ETCD[(etcd)]
    Sched[Scheduler]
    CM[Controller Manager]
    API --- ETCD
    API --- Sched
    API --- CM
  end
  subgraph W1["Worker Node 1"]
    Kubelet1[Kubelet]
    KProxy1[Kube-proxy]
    Pod1[Pod A]
    Pod2[Pod B]
    Kubelet1 --> Pod1
    Kubelet1 --> Pod2
  end
  subgraph W2["Worker Node 2"]
    Kubelet2[Kubelet]
    KProxy2[Kube-proxy]
    Pod3[Pod C]
    Pod4[Pod D]
    Kubelet2 --> Pod3
    Kubelet2 --> Pod4
  end
  API --> Kubelet1
  API --> Kubelet2
  style CP fill:#0a0e17,stroke:#dc2626,color:#f1f5f9
  style W1 fill:#0a0e17,stroke:#3b82f6,color:#f1f5f9
  style W2 fill:#0a0e17,stroke:#3b82f6,color:#f1f5f9
  style API fill:#7f1d1d,stroke:#dc2626,color:#f1f5f9
  style ETCD fill:#1a2332,stroke:#f59e0b,color:#f1f5f9

Le Control Plane : le cerveau du cluster

Le Control Plane est l’ensemble des composants qui gèrent l’état global du cluster. En production, ces composants tournent sur des nœuds dédiés appelés “masters” (généralement 3 pour la haute disponibilité).

API Server (kube-apiserver)

C’est le point d’entrée unique de tout le cluster. Absolument toute interaction avec Kubernetes passe par lui :

  • Quand tu tapes kubectl get pods, ta requête arrive à l’API Server
  • Quand le Scheduler doit placer un pod, il communique avec l’API Server
  • Quand un kubelet rapporte l’état d’un nœud, il envoie ça à l’API Server
  • Quand ArgoCD déploie une application, il parle à l’API Server

L’API Server expose une API REST et gère trois étapes pour chaque requête :

  1. Authentification — Qui es-tu ? (certificat, token, OIDC…)
  2. Autorisation — As-tu le droit ? (RBAC, ABAC…)
  3. Admission — La requête est-elle valide ? (Admission controllers, webhooks…)

🔥 Cas réel en entreprise : Dans un cluster de production multi-équipes, l’API Server est souvent le premier goulot d’étranglement. Si tu as des centaines de développeurs qui interrogent le cluster simultanément, ou des outils de monitoring trop agressifs, l’API Server peut saturer. C’est pour ça qu’on configure des rate limits et qu’on utilise des informers/caches côté client plutôt que de bombarder l’API directement.

etcd

etcd est une base de données clé-valeur distribuée qui stocke tout l’état du cluster :

  • La liste des pods, deployments, services
  • Les configurations (ConfigMaps)
  • Les secrets
  • Les RBAC (rôles, bindings)
  • L’état des nœuds

C’est la source de vérité unique du cluster. Si etcd est perdu et qu’il n’y a pas de backup, le cluster est perdu.

⚠️ Attention : En production, etcd est LE composant le plus critique. Il doit tourner en cluster de 3 ou 5 instances (toujours un nombre impair pour le consensus Raft). Les backups etcd doivent être automatisés et testés régulièrement. Un etcdctl snapshot save quotidien est le strict minimum.

💡 Tip DevOps : Sur les Kubernetes managés (EKS, GKE, AKS), tu n’as pas accès à etcd — c’est le cloud provider qui le gère et le backup. C’est un des gros avantages du managed : tu ne te réveilles pas à 3h du matin parce qu’etcd a rempli son disque.

Scheduler (kube-scheduler)

Quand un nouveau pod doit être créé et qu’il n’est pas encore assigné à un nœud, le Scheduler entre en action. Son rôle : décider sur quel nœud placer le pod.

Le Scheduler fonctionne en deux phases :

  1. Filtrage — Éliminer les nœuds qui ne conviennent pas (pas assez de CPU, mauvaise zone, taints incompatibles…)
  2. Scoring — Parmi les nœuds restants, attribuer un score pour choisir le meilleur

Les critères pris en compte sont nombreux :

  • Ressources disponibles — CPU et mémoire libres sur le nœud
  • Affinité/Anti-affinité — “Place ce pod près de tel autre” ou “éloigne-le de tel autre”
  • Taints et Tolerations — “Ce nœud est réservé aux workloads GPU” (taint), “ce pod accepte les nœuds GPU” (toleration)
  • Topologie — Zones de disponibilité, régions

🧠 À retenir : Le Scheduler ne déplace jamais un pod déjà en cours d’exécution. Il ne s’occupe que des pods non assignés. Si tu veux rééquilibrer les pods sur tes nœuds, tu dois utiliser un outil comme descheduler.

Controller Manager (kube-controller-manager)

Le Controller Manager regroupe un ensemble de boucles de contrôle (controllers) qui surveillent en permanence l’état du cluster et le corrigent si nécessaire. Chaque controller a une responsabilité précise :

ControllerRôle
ReplicaSet ControllerVérifie que le bon nombre de pods tourne. Un pod meurt ? Il en relance un.
Deployment ControllerGère les rolling updates et les rollbacks
Node ControllerSurveille la santé des nœuds (heartbeat toutes les 10s)
Job ControllerGère les tâches ponctuelles (batch jobs)
ServiceAccount ControllerCrée les comptes de service par défaut dans les namespaces
Endpoint ControllerMaintient la liste des IPs de pods derrière un Service

Le principe est toujours le même : boucle de réconciliation. Le controller compare l’état souhaité (ce que tu as déclaré dans ton YAML) avec l’état actuel (ce qui tourne réellement) et agit pour combler l’écart.

🧠 À retenir : Cette boucle de réconciliation est le cœur de Kubernetes. On l’appelle aussi le pattern du contrôleur ou reconciliation loop. C’est ce qui rend K8s self-healing : si quelque chose diverge de l’état souhaité, un controller le corrige automatiquement.


Les Worker Nodes : les bras du cluster

Les Worker Nodes sont les machines (physiques ou virtuelles) qui font tourner tes conteneurs. Chaque nœud embarque trois composants essentiels.

kubelet

Le kubelet est l’agent qui tourne sur chaque nœud. C’est lui qui fait le lien entre le Control Plane et les conteneurs.

Son fonctionnement :

  1. Il reçoit les spécifications de pods depuis l’API Server (via un watch)
  2. Il communique avec le container runtime pour créer/supprimer des conteneurs
  3. Il effectue des health checks (liveness probes, readiness probes) sur les conteneurs
  4. Il rapporte l’état du nœud et des pods au Control Plane

💡 Tip DevOps : Si un pod ne démarre pas sur un nœud, le premier réflexe est de vérifier les logs du kubelet : journalctl -u kubelet -f. C’est souvent lui qui te dira pourquoi (image introuvable, ressources insuffisantes, problème de permissions…).

kube-proxy

kube-proxy gère les règles réseau sur chaque nœud. Quand tu crées un Service Kubernetes, kube-proxy s’assure que le trafic réseau est correctement routé vers les bons pods.

Il fonctionne en trois modes possibles :

  • iptables (par défaut) — Crée des règles iptables pour le routage. Performant pour la plupart des cas.
  • IPVS — Plus performant pour les clusters avec beaucoup de Services (milliers). Utilise le module IPVS du kernel Linux.
  • userspace — Mode legacy, plus utilisé.

🔥 Cas réel en entreprise : Dans un cluster avec 5000+ Services, le mode iptables peut devenir lent (les règles iptables sont parcourues séquentiellement). C’est là qu’on passe en mode IPVS. Si tu gères un cluster de cette taille, tu le sais déjà. Sinon, iptables suffit largement.

Container Runtime

Le container runtime est le moteur qui fait réellement tourner les conteneurs. Kubernetes communique avec lui via l’interface standard CRI (Container Runtime Interface).

Les runtimes les plus courants :

  • containerd — Le plus répandu. C’est le runtime que Docker utilise en interne. Léger et fiable.
  • CRI-O — Créé spécifiquement pour Kubernetes par Red Hat. Utilisé par défaut dans OpenShift.

⚠️ Attention : Depuis Kubernetes 1.24, Docker n’est plus supporté comme runtime direct (suppression du “dockershim”). Mais pas de panique : tes images Docker restent 100% compatibles. Docker produit des images OCI standard que containerd sait lancer. C’est uniquement le “runtime Docker” qui n’est plus utilisé côté cluster.


Concepts fondamentaux

Maintenant que tu connais l’architecture, passons aux objets que tu vas manipuler au quotidien. On commence par les quatre piliers : Pods, Deployments, Services et Namespaces.

Pods : la brique de base

Le Pod est la plus petite unité déployable dans Kubernetes. Ce n’est pas un conteneur — c’est une enveloppe autour d’un ou plusieurs conteneurs qui partagent :

  • Le même réseau — Même adresse IP, mêmes ports (les conteneurs du pod se parlent via localhost)
  • Le même stockage — Volumes partagés entre conteneurs du pod
  • Le même cycle de vie — Ils démarrent et s’arrêtent ensemble

Dans 90% des cas, un pod contient un seul conteneur. Les pods multi-conteneurs servent pour des patterns bien spécifiques :

  • Sidecar — Un conteneur auxiliaire qui ajoute une fonctionnalité (ex: un proxy Envoy, un collecteur de logs)
  • Init Container — Un conteneur qui s’exécute avant le conteneur principal (ex: migrations de BDD, téléchargement de config)

Voici à quoi ressemble la déclaration d’un Pod simple. On déclare l’API version, le type d’objet, les métadonnées (nom et labels), puis la spec avec le ou les conteneurs :

apiVersion: v1
kind: Pod
metadata:
  name: mon-api
  labels:
    app: mon-api
    env: dev
spec:
  containers:
    - name: api
      image: nginx:1.27
      ports:
        - containerPort: 80
      resources:
        requests:
          memory: "64Mi"
          cpu: "100m"
        limits:
          memory: "128Mi"
          cpu: "250m"

Décortiquons ce YAML :

  • apiVersion: v1 — Les pods font partie de l’API core de Kubernetes
  • kind: Pod — Le type d’objet qu’on crée
  • metadata.name — Le nom unique du pod dans son namespace
  • metadata.labels — Des étiquettes clé-valeur pour organiser et sélectionner les pods
  • spec.containers — La liste des conteneurs dans le pod
  • resources.requests — Le minimum garanti de ressources (utilisé par le Scheduler pour placer le pod)
  • resources.limits — Le maximum autorisé (le pod est tué s’il dépasse la mémoire limit)

⚠️ Attention : Ne déploie jamais des pods directement en production. Un pod seul n’est pas résilient : s’il meurt, personne ne le recrée. Utilise toujours un Deployment (ou un StatefulSet, DaemonSet selon le cas) qui gère le cycle de vie des pods pour toi.

💡 Tip DevOps : Toujours définir les resources.requests et resources.limits sur tes conteneurs. Sans ça, le Scheduler ne peut pas prendre de bonnes décisions de placement, et un pod gourmand peut tuer le nœud entier en consommant toute la mémoire (OOM Kill). En entreprise, on utilise des LimitRange et ResourceQuota pour forcer ces bonnes pratiques au niveau du namespace.


Deployments : la gestion déclarative des pods

Un Deployment est l’objet que tu utiliseras 95% du temps pour déployer des applications. Il déclare l’état souhaité : quelle image, combien de réplicas, quelle stratégie de mise à jour.

Sous le capot, un Deployment crée un ReplicaSet, qui à son tour crée les Pods. La hiérarchie est :

Deployment → ReplicaSet → Pod(s)

Pourquoi cette hiérarchie ? Parce que lors d’une mise à jour, le Deployment crée un nouveau ReplicaSet avec la nouvelle version et scale down l’ancien progressivement. C’est comme ça que le rolling update fonctionne.

Voici un Deployment complet avec les bonnes pratiques :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mon-api
  labels:
    app: mon-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mon-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: mon-api
    spec:
      containers:
        - name: api
          image: nginx:1.27
          ports:
            - containerPort: 80
          resources:
            requests:
              memory: "64Mi"
              cpu: "100m"
            limits:
              memory: "128Mi"
              cpu: "250m"
          livenessProbe:
            httpGet:
              path: /healthz
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 15
          readinessProbe:
            httpGet:
              path: /ready
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10

Détaillons les éléments importants :

  • replicas: 3 — Kubernetes maintient toujours 3 pods actifs. Un pod meurt ? Un nouveau est recréé immédiatement.
  • selector.matchLabels — Le Deployment sait quels pods il gère grâce aux labels. Le selector doit matcher les labels du template.
  • strategy.type: RollingUpdate — Pendant une mise à jour, les anciens pods sont remplacés progressivement
  • maxUnavailable: 1 — Au maximum 1 pod indisponible pendant le update
  • maxSurge: 1 — Au maximum 1 pod en plus pendant le update (donc entre 2 et 4 pods pendant la transition)
  • livenessProbe — “Est-ce que le conteneur est vivant ?” Si la probe échoue, Kubernetes redémarre le conteneur
  • readinessProbe — “Est-ce que le conteneur est prêt à recevoir du trafic ?” Si la probe échoue, le pod est retiré du Service (plus de trafic)

🧠 À retenir : La différence entre liveness et readiness est cruciale. Liveness = le conteneur est-il vivant ? (sinon, on le tue et on le relance). Readiness = le conteneur est-il prêt ? (sinon, on arrête de lui envoyer du trafic mais on ne le tue pas). Confondre les deux est une erreur classique qui provoque des cascades de redémarrages.

🔥 Cas réel en entreprise : Imagine une API qui charge un gros modèle ML au démarrage (30 secondes). Si ta liveness probe a un initialDelaySeconds trop court, Kubernetes va tuer le conteneur avant qu’il ait fini de démarrer, le relancer, le tuer à nouveau… en boucle infinie. C’est le CrashLoopBackOff, un classique qu’on a tous vécu au moins une fois.


Services : l’accès réseau stable

Les pods sont éphémères — ils peuvent être recréés à tout moment avec une IP différente. Tu ne peux pas hardcoder l’IP d’un pod quelque part, elle changera au prochain redémarrage.

Un Service résout ce problème en fournissant :

  • Une adresse IP stable (ClusterIP) qui ne change pas
  • Un nom DNS pour la découverte de service (ex: mon-api-service.default.svc.cluster.local)
  • Du load balancing automatique entre les pods ciblés

Le Service sait quels pods cibler grâce au selector : il envoie le trafic à tous les pods dont les labels matchent.

Les types de Services

Kubernetes propose trois types de Services principaux, chacun avec un use case différent :

ClusterIP (par défaut) — Accessible uniquement à l’intérieur du cluster. C’est le type le plus utilisé pour la communication entre microservices.

apiVersion: v1
kind: Service
metadata:
  name: mon-api-service
spec:
  selector:
    app: mon-api
  ports:
    - port: 80
      targetPort: 80
  type: ClusterIP

Ce Service crée une IP virtuelle interne au cluster. Tout pod du cluster peut atteindre ton API via mon-api-service ou mon-api-service.default.svc.cluster.local.

NodePort — Expose le Service sur un port de chaque nœud du cluster (plage 30000-32767). Le trafic externe arrive sur <IP-du-noeud>:<NodePort> et est routé vers les pods.

apiVersion: v1
kind: Service
metadata:
  name: mon-api-nodeport
spec:
  selector:
    app: mon-api
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080
  type: NodePort

💡 Tip DevOps : Le NodePort est pratique pour le développement local ou les tests, mais en production, on l’utilise rarement directement. On préfère un LoadBalancer ou un Ingress Controller (NGINX, Traefik) qui gère le TLS, le routing par nom de domaine, etc.

LoadBalancer — Provisionne automatiquement un load balancer externe via le cloud provider (AWS ELB, GCP LB, Azure LB…). C’est la manière standard d’exposer un Service au monde extérieur en cloud.

apiVersion: v1
kind: Service
metadata:
  name: mon-api-lb
spec:
  selector:
    app: mon-api
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer

⚠️ Attention : Chaque Service de type LoadBalancer crée un load balancer dédié chez ton cloud provider. À 15-25€/mois chacun, ça chiffre vite si tu as 20 services. En pratique, on utilise un seul Ingress Controller (NGINX ou Traefik) derrière un LoadBalancer, et l’Ingress Controller route vers les différents services internes. On verra ça dans un chapitre ultérieur.

Comment le DNS fonctionne dans Kubernetes

Kubernetes inclut un serveur DNS interne (CoreDNS) qui attribue automatiquement un nom DNS à chaque Service. Le format est :

<nom-du-service>.<namespace>.svc.cluster.local

Exemples concrets :

  • mon-api-service.default.svc.cluster.local — Service “mon-api-service” dans le namespace “default”
  • postgres.database.svc.cluster.local — Service “postgres” dans le namespace “database”

Dans le même namespace, tu peux utiliser le nom court : mon-api-service.

🧠 À retenir : Grâce au DNS interne, tes microservices n’ont jamais besoin de connaître les IPs des pods. Ils se réfèrent aux Services par leur nom. C’est la base de la découverte de services dans Kubernetes.


Namespaces : l’isolation logique

Les Namespaces permettent de partitionner un cluster en espaces logiques isolés. C’est essentiel quand plusieurs équipes ou plusieurs environnements partagent le même cluster.

Par défaut, Kubernetes crée quatre namespaces :

NamespaceRôle
defaultLà où tes ressources atterrissent si tu ne spécifies pas de namespace
kube-systemLes composants système de K8s (CoreDNS, kube-proxy, controller-manager…)
kube-publicRessources lisibles par tous (rarement utilisé)
kube-node-leaseUtilisé pour les heartbeats des nœuds (mécanisme interne)

En pratique, tu crées tes propres namespaces. Deux stratégies courantes :

Par environnement :

kubectl create namespace dev
kubectl create namespace staging
kubectl create namespace production

Par équipe :

kubectl create namespace team-backend
kubectl create namespace team-frontend
kubectl create namespace team-data

🔥 Cas réel en entreprise : Dans un cluster mutualisé, les namespaces sont combinés avec des ResourceQuota (limiter les ressources par namespace) et des NetworkPolicy (isoler le réseau entre namespaces). Sans ça, l’équipe data peut lancer un job Spark qui consomme toute la mémoire du cluster et fait tomber l’API de production. Vécu, pas inventé.

💡 Tip DevOps : Ajoute toujours -n <namespace> à tes commandes kubectl, ou mieux, configure un contexte par défaut : kubectl config set-context --current --namespace=dev. Ça évite de travailler accidentellement dans le mauvais namespace. En production, un kubectl delete pod dans le mauvais namespace, ça fait mal.


Installation locale avec Kind

Pourquoi Kind plutôt que Minikube ?

Kind (Kubernetes IN Docker) crée des clusters Kubernetes en utilisant des conteneurs Docker comme nœuds. C’est devenu l’outil de référence pour le développement local, et voici pourquoi :

CritèreKindMinikube
TechnologieConteneurs DockerVM (ou conteneurs)
Démarrage~30 secondes~2-5 minutes
Multi-nœuds✅ Natif⚠️ Expérimental
RessourcesLégerPlus lourd (VM)
CI/CD✅ Parfait⚠️ Plus complexe
Utilisé parLe projet Kubernetes lui-mêmeDéveloppeurs individuels

💡 Tip DevOps : Kind est utilisé par le projet Kubernetes pour ses propres tests d’intégration. Si c’est assez bon pour tester Kubernetes lui-même, c’est assez bon pour ton dev local.

Installation de Kind et kubectl

Avant de créer un cluster, tu as besoin de deux outils : Kind pour créer le cluster et kubectl pour interagir avec.

Sur macOS avec Homebrew :

brew install kind kubectl

Sur Linux (amd64) :

# Kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

# kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

# Vérification
kind version
kubectl version --client

⚠️ Attention : Docker doit être installé et en cours d’exécution avant d’utiliser Kind. Kind crée des conteneurs Docker qui simulent des nœuds Kubernetes. Sans Docker, rien ne fonctionne.

Créer ton premier cluster

La commande la plus simple pour démarrer :

kind create cluster --name mon-cluster

Kind va :

  1. Télécharger l’image Docker du nœud Kubernetes
  2. Lancer un conteneur qui fait office de nœud (control plane + worker combinés)
  3. Configurer kubectl pour pointer vers ce cluster

Vérifie que tout fonctionne :

# Infos sur le cluster
kubectl cluster-info --context kind-mon-cluster

# Liste des nœuds
kubectl get nodes

# Tu devrais voir quelque chose comme :
# NAME                        STATUS   ROLES           AGE   VERSION
# mon-cluster-control-plane   Ready    control-plane   30s   v1.31.0

Cluster multi-nœuds : simuler la production

Un cluster avec un seul nœud, c’est bien pour commencer. Mais pour tester le scheduling, les affinités et la haute disponibilité, tu veux plusieurs nœuds.

Crée un fichier de configuration Kind :

# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker

Puis lance le cluster avec cette config :

kind create cluster --name lab --config kind-config.yaml

Vérifie :

kubectl get nodes
# NAME                STATUS   ROLES           AGE   VERSION
# lab-control-plane   Ready    control-plane   45s   v1.31.0
# lab-worker          Ready    <none>          30s   v1.31.0
# lab-worker2         Ready    <none>          30s   v1.31.0

Tu as maintenant un cluster avec 1 control plane et 2 workers, le tout dans des conteneurs Docker. Tu peux vérifier avec docker ps que Kind a lancé 3 conteneurs.

🧠 À retenir : Kind est parfait pour le dev local et les tests CI/CD. Mais ce n’est pas fait pour la production. Pour de la prod, utilise un Kubernetes managé (EKS, GKE, AKS) ou une installation bare-metal avec kubeadm.


Commandes kubectl essentielles

kubectl est ton interface principale avec Kubernetes. Voici les commandes que tu vas utiliser tous les jours :

Lire des informations

# Lister les pods (namespace par défaut)
kubectl get pods

# Lister les pods dans tous les namespaces
kubectl get pods -A

# Lister avec plus de détails (IP, nœud, statut)
kubectl get pods -o wide

# Détails complets d'un pod (événements, conditions, volumes...)
kubectl describe pod <nom-du-pod>

# Voir les logs d'un pod
kubectl logs <nom-du-pod>

# Suivre les logs en temps réel (comme tail -f)
kubectl logs -f <nom-du-pod>

# Logs d'un conteneur spécifique dans un pod multi-conteneurs
kubectl logs <nom-du-pod> -c <nom-du-conteneur>

Créer et modifier des ressources

# Appliquer un fichier YAML (crée ou met à jour)
kubectl apply -f mon-fichier.yaml

# Supprimer une ressource
kubectl delete -f mon-fichier.yaml
kubectl delete pod <nom-du-pod>

# Scaler un deployment
kubectl scale deployment mon-api --replicas=5

# Mettre à jour l'image d'un deployment
kubectl set image deployment/mon-api api=nginx:1.28

Debugger

# Ouvrir un shell dans un pod en cours d'exécution
kubectl exec -it <nom-du-pod> -- /bin/sh

# Voir les événements du cluster (très utile pour debug)
kubectl get events --sort-by='.lastTimestamp'

# Voir les ressources consommées par les pods
kubectl top pods

# Voir les ressources consommées par les nœuds
kubectl top nodes

# Voir toutes les ressources API disponibles
kubectl api-resources

💡 Tip DevOps : Configure l’autocomplétion de kubectl dans ton shell. Ça change la vie :

# Bash
echo 'source <(kubectl completion bash)' >> ~/.bashrc
# Zsh
echo 'source <(kubectl completion zsh)' >> ~/.zshrc

Et crée un alias : alias k=kubectl dans ton .bashrc ou .zshrc. En production, quand tu debugges un incident à 3h du matin, chaque frappe économisée compte.


Déploie ta première application

Passons à la pratique. Tu vas déployer une application nginx complète avec un Deployment et un Service.

Étape 1 — Le Deployment

Crée un fichier nginx-deployment.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo
  labels:
    app: nginx-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
          resources:
            requests:
              memory: "32Mi"
              cpu: "50m"
            limits:
              memory: "64Mi"
              cpu: "100m"

Applique-le :

kubectl apply -f nginx-deployment.yaml

Vérifie le déploiement :

# Le deployment
kubectl get deployment nginx-demo

# Les pods créés
kubectl get pods -l app=nginx-demo

# Le ReplicaSet créé automatiquement
kubectl get replicaset

Tu devrais voir 3 pods en status Running. Si un pod est en Pending ou CrashLoopBackOff, utilise kubectl describe pod <nom> pour comprendre pourquoi.

Étape 2 — Le Service

Maintenant, expose ton Deployment avec un Service. Crée nginx-service.yaml :

apiVersion: v1
kind: Service
metadata:
  name: nginx-demo-service
spec:
  selector:
    app: nginx-demo
  ports:
    - port: 80
      targetPort: 80
  type: NodePort

Applique-le :

kubectl apply -f nginx-service.yaml

Vérifie :

kubectl get service nginx-demo-service
# NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
# nginx-demo-service   NodePort   10.96.123.456   <none>        80:30XXX/TCP   5s

Le port 30XXX est le NodePort attribué automatiquement. Avec Kind, tu peux accéder à ton application via le port-forward :

kubectl port-forward service/nginx-demo-service 8080:80

Ouvre http://localhost:8080 dans ton navigateur — tu verras la page d’accueil nginx. 🎉

Étape 3 — Teste la résilience

Kubernetes promet le self-healing. Vérifions :

# Liste les pods
kubectl get pods -l app=nginx-demo

# Supprime un pod (simule un crash)
kubectl delete pod <nom-du-premier-pod>

# Regarde ce qui se passe
kubectl get pods -l app=nginx-demo -w

Tu vas voir : le pod supprimé disparaît, et un nouveau pod est immédiatement créé par le ReplicaSet pour maintenir les 3 réplicas. C’est le self-healing en action.

🧠 À retenir : Tu viens de voir le cœur de Kubernetes : tu déclares un état souhaité (3 réplicas), et Kubernetes se bat en permanence pour maintenir cet état. Que ce soit un crash, un nœud qui tombe, ou une suppression manuelle — le controller recrée ce qui manque.

Étape 4 — Teste le rolling update

Mets à jour l’image de ton deployment :

# Passe de nginx 1.27 à 1.28
kubectl set image deployment/nginx-demo nginx=nginx:1.28

# Observe le rolling update en temps réel
kubectl rollout status deployment/nginx-demo

# Vérifie l'historique des déploiements
kubectl rollout history deployment/nginx-demo

Pendant le rolling update, Kubernetes :

  1. Crée un nouveau ReplicaSet avec l’image 1.28
  2. Scale up le nouveau ReplicaSet (1 pod)
  3. Vérifie que le nouveau pod est Ready
  4. Scale down l’ancien ReplicaSet (1 pod)
  5. Répète jusqu’à ce que tous les pods soient sur la nouvelle version

Si quelque chose ne va pas, rollback instantané :

kubectl rollout undo deployment/nginx-demo

🔥 Cas réel en entreprise : Le rolling update est la stratégie de déploiement par défaut, mais il y en a d’autres. Le Blue/Green (deux environnements complets, switch instantané) et le Canary (envoyer un petit pourcentage de trafic vers la nouvelle version) sont courants en production. Des outils comme ArgoCD Rollouts ou Flagger permettent d’implémenter ces stratégies avancées sur Kubernetes.


Nettoyage

Quand tu as fini de jouer avec ton cluster, nettoie :

# Supprimer les ressources créées
kubectl delete -f nginx-deployment.yaml
kubectl delete -f nginx-service.yaml

# Ou supprimer le cluster entier
kind delete cluster --name mon-cluster
kind delete cluster --name lab

Résumé du chapitre

Voici ce que tu as appris dans ce premier chapitre :

ConceptCe qu’il faut retenir
KubernetesUn orchestrateur de conteneurs qui maintient un état déclaré
Control PlaneLe cerveau : API Server, etcd, Scheduler, Controller Manager
Worker NodeLes bras : kubelet, kube-proxy, container runtime
PodLa plus petite unité déployable (1 pod ≈ 1 conteneur)
DeploymentGère les pods : réplicas, rolling updates, rollbacks
ServiceAdresse réseau stable pour accéder aux pods (ClusterIP, NodePort, LoadBalancer)
NamespaceIsolation logique des ressources dans le cluster
KindOutil pour créer des clusters K8s locaux dans Docker
kubectlCLI pour interagir avec Kubernetes

🧠 À retenir : Kubernetes fonctionne sur un principe simple mais puissant : tu déclares ce que tu veux, Kubernetes s’assure que ça existe. Ce modèle déclaratif, combiné aux boucles de réconciliation des controllers, rend le système self-healing et résilient.


À toi de jouer

Exercice 1 — Crée ton cluster Kind

Installe Kind et crée un cluster multi-nœuds :

kind create cluster --name devops-lab --config kind-config.yaml

Vérifie avec kubectl cluster-info et kubectl get nodes. Explore les namespaces par défaut avec kubectl get ns. Combien de pods tournent dans kube-system ? À quoi sert chacun d’eux ?

Exercice 2 — Déploie et expose une application

  1. Crée un Deployment avec 5 réplicas d’une image httpd:2.4 (Apache)
  2. Ajoute des resources.requests et resources.limits
  3. Expose-le avec un Service de type NodePort
  4. Utilise kubectl port-forward pour y accéder dans ton navigateur
  5. Vérifie que les 5 pods sont répartis sur les différents nœuds avec kubectl get pods -o wide

Exercice 3 — Teste la résilience

  1. Supprime 2 pods manuellement et observe la recréation automatique
  2. Change l’image de ton deployment (ex: httpd:2.4httpd:2.5-alpine) et observe le rolling update
  3. Fais un rollback et vérifie que l’ancienne version est restaurée
  4. Essaie de scaler à 10 réplicas, puis redescends à 2

Exercice 4 — Explore l’architecture

  1. Liste les composants du control plane : kubectl get pods -n kube-system
  2. Identifie l’API Server, le Scheduler, etcd et le Controller Manager
  3. Exécute kubectl api-resources | head -30 pour voir les types de ressources disponibles
  4. Utilise kubectl get events -A --sort-by='.lastTimestamp' pour voir l’activité du cluster

🚀 Pratique en direct

Envie de tester immédiatement ? Lance le Playground DevOpsLab — un terminal Linux complet dans ton navigateur avec tous les outils pré-installés.

▶ Lancer le Playground


➡️ La suite : Dans le prochain chapitre, on plonge dans les Deployments avancés — stratégies de déploiement, health checks, resource management et bonnes pratiques de production. On continue ! 🚀

🖥️ Pratique sur ton propre serveur

Pour suivre Apprendre Kubernetes en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés