Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

☸️ Kubernetes – Concepts, Installation & Déploiement

Guide complet IDEO‑Lab pour maîtriser l'orchestration de conteneurs, de Minikube au Cloud.

1.1

Vue d'ensemble K8s

Qu'est-ce que Kubernetes ? Problèmes résolus.

Orchestration Auto-healing
1.2

Architecture Cluster

Control Plane (Master) et Worker Nodes.

Control Plane Nodes etcd
1.3

Objets Fondamentaux

Pods, Services, Deployments, Namespaces.

Pod Service Deployment
2.1

Installation Locale

Minikube, kind, Docker Desktop.

Minikube kind Dev
2.2

CLI : kubectl

Installation, configuration, contextes.

kubectl kubeconfig context
2.3

Clusters Cloud (GKE/EKS/AKS)

Principes des services managés.

GKE EKS AKS
3.1

Manifestes YAML & Pods

Déclaratif vs Impératif, anatomie d'un Pod.

YAML Pod apply
3.2

Deployments

Gestion des replicas, rolling updates, rollbacks.

ReplicaSet Rolling Update
3.3

StatefulSets & DaemonSets

Pods stables pour BDD (Stateful) et Pods par nœud (Daemon).

StatefulSet DaemonSet
4.1

Services (Networking)

ClusterIP, NodePort, LoadBalancer.

ClusterIP NodePort LoadBalancer
4.2

ConfigMaps & Secrets

Injecter la configuration et les secrets.

ConfigMap Secret env
4.3

Volumes & Persistance

PV, PVC, StorageClass.

PersistentVolume PVC StorageClass
5.1

Namespaces

Isolation logique des ressources.

namespace isolation quota
5.2

Ingress

Routage HTTP/HTTPS (L7) vers les Services.

Ingress Controller L7
5.3

Sécurité : RBAC

Roles, ClusterRoles, Bindings, ServiceAccounts.

RBAC ServiceAccount
6.1

Helm (Package Manager)

Gérer des "Charts" (paquets K8s).

Helm Charts Release
6.2

Monitoring & Logs

logs, top, Prometheus, Grafana.

logs Prometheus Metrics
7.1

kubectl Cheat‑sheet

Commandes fréquentes de gestion et debug.

cheat kubectl
1.1 Vue d'ensemble Kubernetes
L'Orchestrateur de Conteneurs

Kubernetes (souvent abrégé "K8s") est un système open-source (créé par Google) pour **automatiser le déploiement, la mise à l'échelle et la gestion** des applications conteneurisées.

Il gère un "cluster" de machines (VMs ou bare-metal) et y place des conteneurs (Docker, containerd) de manière intelligente pour garantir la haute disponibilité et l'utilisation optimale des ressources.

Concepts Fondamentaux
  • Déclaratif : Vous décrivez l'**état désiré** (ex: "Je veux 3 instances de mon app") dans un fichier YAML, et K8s se charge de faire converger la réalité vers cet état.
  • Auto-réparation (Auto-healing) : Si un conteneur ou un nœud tombe, K8s le détecte et redémarre/remplace automatiquement les conteneurs affectés.
  • Mise à l'échelle (Scaling) : Augmentez ou diminuez le nombre de conteneurs (replicas) d'une simple commande (kubectl scale) ou automatiquement (HPA).
  • Service Discovery : K8s fournit un DNS interne pour que les services puissent se trouver facilement (ex: "app-web" peut appeler "db" par son nom).
K8s vs. Docker Compose

C'est une confusion fréquente. Ils ne sont pas concurrents directs.

CritèreDocker ComposeKubernetes
UsageDéveloppement local, testsProduction, Staging
MachinesMono-nœud (1 PC)Multi-nœuds (Cluster)
GestionManuelle (up/down)Automatisée (Orchestration)
RéseauSimple (bridge)Complexe, puissant (SDN)
HANon (si le PC tombe, tout tombe)Oui (auto-healing, multi-nœuds)

Analogie : Docker est le "conteneur" (la boîte). Docker Compose est le "manuel d'instructions" pour assembler quelques boîtes sur une étagère. Kubernetes est "l'entrepôt robotisé" qui gère des milliers de boîtes sur des centaines d'étagères, 24/7.

Problèmes résolus par K8s
SCÉNARIO 1: Serveur en panne
Sans K8s: Votre app est down à 3h du matin. Vous recevez une alerte.
Avec K8s: Le nœud est marqué "NotReady". K8s redéploie automatiquement les conteneurs sur les nœuds sains. L'app continue de fonctionner sans interruption de service.

SCÉNARIO 2: Pic de trafic (Black Friday)
Sans K8s: Votre serveur sature (100% CPU). Vous devez provisionner un nouveau serveur, le configurer, déployer l'app, configurer le load balancer. (Temps: 2h)
Avec K8s: `kubectl scale deployment/mon-app --replicas=10`. (Temps: 15 secondes). Ou K8s le fait pour vous (Horizontal Pod Autoscaler).

SCÉNARIO 3: Mise à jour (V2)
Sans K8s: Downtime planifié. Vous arrêtez V1, déployez V2. Si V2 bug, vous re-déployez V1 (rollback manuel).
Avec K8s: "Rolling Update". K8s déploie V2 progressivement (1 pod, puis 2, etc.) tout en arrêtant V1. Si V2 échoue (health checks), K8s stoppe le déploiement et fait un rollback automatique vers V1. Zéro downtime.
1.2 Architecture du Cluster
Schéma d'un cluster K8s

Un cluster est composé de deux types de machines : le **Control Plane** (le cerveau) et les **Worker Nodes** (les muscles).

[Image d'une architecture Kubernetes]
+------------------------------------------------------+
| CONTROL PLANE (Master Node)                          |
|                                                      |
| +-----------+   +-------------+   +----------------+ |
| | API Server| ⇔ | Scheduler   | ⇔ | Controller Mgr | |
| +-----------+   +-------------+   +----------------+ |
|      |                                               |
|      |               +-----------+                   |
|      +-------------> |   etcd    | (Base de données) |
|                      +-----------+                   |
+------------------------------------------------------+
       |
       | (kubectl parle à l'API Server)
       |
       | (L'API Server parle au Kubelet)
       ▼
+---------------------+     +---------------------+
| WORKER NODE 1       |     | WORKER NODE 2       |
|                     |     |                     |
| +---------+         |     | +---------+         |
| | Kubelet | ⇔ Kube-Proxy  |     | Kubelet | ⇔ Kube-Proxy  |
| +---------+         |     | +---------+         |
| | [POD 1] | [POD 2] |     | | [POD 3] |         |
| +---------+---------+     | +---------+         |
+---------------------+     +---------------------+
Le Control Plane (Le Cerveau)

Le Control Plane prend les décisions globales du cluster (ex: planifier les pods) et maintient l'état désiré. Il n'exécute pas les conteneurs applicatifs.

ComposantRôle principal
API ServerLe "frontend" du cluster. C'est le seul composant auquel vous (kubectl) et les autres composants parlent. Il valide et traite les requêtes REST.
etcdLa "base de données" (clé-valeur) du cluster. C'est la seule source de vérité. Stocke l'état désiré ET l'état actuel de tous les objets (Pods, Services...).
SchedulerObserve l'API Server pour de nouveaux Pods "non planifiés". Choisit le meilleur Worker Node pour exécuter un Pod (selon CPU, RAM, contraintes...).
Controller ManagerExécute les "boucles de contrôle". Ex: le *Replication Controller* vérifie que le nombre de Pods actuel = le nombre désiré. Le *Node Controller* vérifie si un nœud est tombé.

En production, le Control Plane est "HA" (Haute Dispo) avec 3 ou 5 masters pour la redondance d'etcd.

Les Worker Nodes (Les Muscles)

Les Workers sont les machines (VMs ou physiques) qui exécutent les charges de travail (vos conteneurs applicatifs).

ComposantRôle principal
KubeletL'agent K8s qui tourne sur *chaque* nœud. Il parle à l'API Server et s'assure que les conteneurs décrits dans les "PodSpecs" sont en cours d'exécution et en bonne santé sur son nœud.
Kube-proxyLe "proxy" réseau qui tourne sur *chaque* nœud. Il gère les règles réseau (via iptables ou ipvs) pour permettre la communication réseau vers vos Pods depuis l'intérieur ou l'extérieur du cluster (la magie des Services K8s).
Container RuntimeLe logiciel qui exécute les conteneurs (ex: Docker, containerd, CRI-O). Le Kubelet lui donne les ordres (ex: "Démarre ce conteneur").
1.3 Objets Fondamentaux
1. Pod : La plus petite unité

Vous ne lancez jamais un conteneur seul. Vous lancez un Pod. Un Pod est une "enveloppe" autour d'un ou plusieurs conteneurs.

+---------------------------+
| POD (IP: 10.1.1.2)        |
|                           |
|  +-------------------+    |
|  | Conteneur A (App) |    | (Partage localhost,
|  | Port: 8080        |    |  volumes, IPC)
|  +-------------------+    |
|                           |
|  +-------------------+    |
|  | Conteneur B (Sidecar) |  |
|  | ex: un logger     |    |
|  +-------------------+    |
+---------------------------+
  • Un Pod est l'unité de déploiement et de scaling.
  • Tous les conteneurs d'un Pod partagent la même **adresse IP** et le même **namespace réseau** (ils peuvent communiquer via localhost).
  • Ils peuvent partager des **Volumes** (stockage).
  • 99% du temps, un Pod contient 1 seul conteneur.
  • Les Pods sont **éphémères** (jetables). S'ils meurent, ils sont remplacés (avec une nouvelle IP).
2. Deployment : Le gestionnaire

Vous ne créez (presque) jamais de Pods manuellement. Vous créez un **Deployment**.

Un Deployment est un objet qui décrit un **état désiré** (ex: "Je veux 3 Pods de mon app-nginx"). Il gère un ReplicaSet qui, lui, gère la création/destruction des Pods.

Avantages
  • Rolling Updates : Déployer une nouvelle version sans downtime.
  • Rollbacks : Revenir à une version précédente si la nouvelle bug.
  • Scaling : kubectl scale deployment --replicas=5.
               [kubectl scale --replicas=3]
                            ▼
+-------------------------------------------------------+
| Deployment (mon-app)                                  |
|  "Je veux 3 replicas de l'image nginx:1.21"           |
|                                                       |
|  +-------------------------------------------------+  |
|  | ReplicaSet (mon-app-7f... - Géré par Deployment)  |
|  |  "Je m'assure qu'il y a 3 Pods"                   |
|  |                                                 |
|  |  +-------+   +-------+   +-------+              |
|  |  | Pod 1 |   | Pod 2 |   | Pod 3 |              |
|  |  +-------+   +-------+   +-------+              |
|  +-------------------------------------------------+  |
+-------------------------------------------------------+
3. Service : L'adresse stable

Problème : Les Pods sont éphémères. Si un Pod meurt, le Deployment le remplace par un nouveau... avec une nouvelle IP. Comment les autres Pods peuvent-ils le trouver ?

Le **Service** est une abstraction réseau qui fournit une **adresse IP stable** et un **nom DNS** pour un groupe de Pods.

               [Requête vers 'http://mon-service']
                            ▼
+-------------------------------------------------------+
| Service (mon-service) (IP: 10.96.0.10 - STABLE)       |
|  (Selector: app=mon-app)                              |
|                                                       |
|  (Redirige le trafic vers les Pods sains)             |
|        /                 |                 \          |
|       ▼                  ▼                  ▼         |
|  +-------+          +-------+          +-------+      |
|  | Pod 1 |          | Pod 2 |          | Pod 3 |      |
|  | (IP: 10.1.1.2)   | (IP: 10.1.1.3)   | (IP: 10.1.2.2) |
|  +-------+          +-------+          +-------+      |
+-------------------------------------------------------+

Le Service utilise un **Selector** (des labels) pour savoir à quels Pods envoyer le trafic.

Autres objets de "Workload"
ObjetCas d'usage
StatefulSetSimilaire à un Deployment, mais pour des applications "stateful" (ex: BDD). Fournit des garanties d'identité réseau stable (ex: db-0, db-1) et de stockage persistant unique.
DaemonSetS'assure qu'une instance d'un Pod tourne sur **chaque nœud** (ou un sous-ensemble de nœuds) du cluster. Parfait pour les agents de logging (Fluentd), de monitoring (Prometheus Node Exporter) ou de réseau (Calico).
JobCrée un ou plusieurs Pods et s'assure qu'ils se terminent avec succès (status 0). Utilisé pour des tâches batch (ex: migration de BDD, rapport de fin de mois).
CronJobUn "crontab" pour K8s. Lance un Job à une heure/fréquence définie (ex: "tous les jours à 2h du matin").
2.1 Installation Locale (Dev)
Minikube (Le standard historique)

Minikube crée un cluster K8s **mono-nœud** dans une VM (VirtualBox, Hyper-V, KVM) ou un conteneur. Idéal pour tester K8s et kubectl.

Installation (exemple Linux)
# 1. Installer Minikube
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube /usr/local/bin/

# 2. Démarrer le cluster (avec le driver Docker)
minikube start --driver=docker

# 3. Vérifier le statut
minikube status
kubectl get nodes
Commandes utiles
# Démarrer / Arrêter
minikube start
minikube stop

# Ouvrir le Dashboard K8s
minikube dashboard

# Exposer un service de type NodePort
minikube service [nom-du-service]

# Supprimer le cluster
minikube delete
kind (Kubernetes in Docker)

kind est un outil plus récent qui exécute un cluster K8s (y compris multi-nœuds) **à l'intérieur de conteneurs Docker**. C'est très léger et rapide. Très populaire pour la CI/CD.

Installation (exemple Linux)
# 1. Installer 'kind'
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

# 2. Créer un cluster
kind create cluster --name dev-cluster

# 3. Charger le kubeconfig
kind get kubeconfig --name dev-cluster > ~/.kube/config-kind
export KUBECONFIG=~/.kube/config-kind

# 4. Vérifier
kubectl get nodes
Cluster Multi-nœuds

Créez un fichier kind-config.yml :

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
kind create cluster --config kind-config.yml
Docker Desktop (Le plus simple)

Si vous avez Docker Desktop (Windows ou Mac), il inclut un cluster K8s mono-nœud.

Activation
  1. Ouvrez Docker Desktop.
  2. Allez dans Settings (Préférences).
  3. Allez dans la section Kubernetes.
  4. Cochez "Enable Kubernetes".
  5. Cliquez sur "Apply & Restart".

Docker Desktop s'occupe de tout (installation, kubectl, configuration du contexte).

Changer de contexte

kubectl doit savoir à quel cluster parler (Docker, Minikube, GKE...).

# Lister les contextes
kubectl config get-contexts

# Changer pour le contexte Docker
kubectl config use-context docker-desktop
2.2 CLI : kubectl (Le couteau suisse)
Installation de kubectl

kubectl est l'outil CLI unique pour interagir avec l'API Server de Kubernetes.

Linux (Debian/Ubuntu)
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubectl
Windows (via Chocolatey)
choco install kubernetes-cli
macOS (via Homebrew)
brew install kubectl
Vérification
kubectl version --client
Fichier ~/.kube/config

kubectl trouve les informations de connexion (API Server, certificats, tokens) dans un fichier YAML appelé config, situé dans $HOME/.kube/.

Ce fichier gère plusieurs **Contextes** (ex: dev, prod, local).

# Lister tous les contextes
kubectl config get-contexts

CURRENT   NAME              CLUSTER         AUTHINFO        NAMESPACE
* docker-desktop    docker-desktop  docker-desktop
          gke_my-project_... gke_my-project_... gke_my-project_...
          minikube          minikube        minikube        default

# Voir le contexte actuel
kubectl config current-context

# Changer de contexte (pour parler au cluster GKE)
kubectl config use-context gke_my-project_...

# Changer de contexte (pour revenir au local)
kubectl config use-context docker-desktop

Les outils (Minikube, kind, gcloud, az) mettent à jour ce fichier automatiquement pour vous.

Autocomplétion (Bash & Zsh)

Ceci est **essentiel** pour être productif. Cela vous permet d'appuyer sur [TAB] pour compléter les commandes, les types d'objets et les noms de vos Pods/Services.

Activation (Bash)
# Installer bash-completion
sudo apt-get install bash-completion

# Ajouter à votre .bashrc
echo 'source <(kubectl completion bash)' >>~/.bashrc
source ~/.bashrc
Activation (Zsh)
# Ajouter à votre .zshrc
echo 'source <(kubectl completion zsh)' >>~/.zshrc
source ~/.zshrc
Exemples d'utilisation
kubectl g [TAB]
# Affiche: get
kubectl get po [TAB]
# Affiche: pods
kubectl get pods mon-app-web-12345 [TAB]
# (Aucune complétion, car c'est le nom complet)
kubectl logs mon-app-web- [TAB]
# Affiche: mon-app-web-12345 (complète le nom du pod)
2.3 Clusters Cloud Managés (GKE, EKS, AKS)
Pourquoi un service managé ?

Installer et maintenir un cluster K8s en production soi-même ("K8s The Hard Way") est **extrêmement complexe**. Il faut gérer :

  • La haute disponibilité (HA) du Control Plane (etcd).
  • La génération et la rotation des certificats TLS.
  • Les mises à jour (patchs de sécurité K8s).
  • L'intégration au réseau du Cloud (VPC).
  • Le provisionnement des LoadBalancers.

Un service managé (GKE, EKS, AKS) gère **gratuitement** (ou presque) le Control Plane pour vous. Vous ne payez que pour les Worker Nodes (les VMs).

VOTRE RESPONSABILITÉ (Cluster managé)
+------------------------------------------------------+
| WORKER NODE 1 (VM) | WORKER NODE 2 (VM) | ... (VMs)  |
| (Vous payez)       | (Vous payez)       |            |
+------------------------------------------------------+

RESPONSABILITÉ DU CLOUD PROVIDER
+------------------------------------------------------+
| CONTROL PLANE (HA, Sécurisé, Mis à jour)             |
| (Gratuit ou faible coût)                             |
+------------------------------------------------------+
GKE (Google Kubernetes Engine)

Considéré comme le plus mature et le plus simple (K8s vient de Google).

Prérequis
# Installer Google Cloud CLI
gcloud components install gke-gcloud-auth-plugin
Création d'un cluster (Autopilot)

Autopilot est un mode GKE "serverless" où vous ne gérez *même pas* les nœuds. Vous payez au Pod.

gcloud container clusters create-auto mon-cluster-autopilot \
    --region=europe-west1

# Récupérer les credentials (met à jour le kubeconfig)
gcloud container clusters get-credentials mon-cluster-autopilot \
    --region=europe-west1

# Vérifier
kubectl get nodes
EKS (Amazon Elastic Kubernetes Service)

Intégration profonde avec l'écosystème AWS (IAM, VPC, ELB).

Prérequis
# Installer AWS CLI
# Installer eksctl (l'outil simple pour EKS)
brew install eksctl
Création d'un cluster (via eksctl)
# Crée un cluster (CloudFormation) et 2 nœuds m5.large
eksctl create cluster \
    --name mon-cluster-eks \
    --region=eu-west-3 \
    --nodegroup-name=nodes-standards \
    --node-type=t3.medium \
    --nodes=2

# (Prend 10-15 minutes)
# eksctl met à jour le kubeconfig automatiquement

# Vérifier
kubectl get nodes
AKS (Azure Kubernetes Service)

L'offre K8s managée de Microsoft Azure.

Prérequis
# Installer Azure CLI
az login
Création d'un cluster
# 1. Créer un groupe de ressources
az group create --name ResGroup-AKS --location westeurope

# 2. Créer le cluster
az aks create \
    --resource-group ResGroup-AKS \
    --name mon-cluster-aks \
    --node-count 2 \
    --enable-managed-identity \
    --generate-ssh-keys

# 3. Récupérer les credentials
az aks get-credentials --resource-group ResGroup-AKS --name mon-cluster-aks

# 4. Vérifier
kubectl get nodes
3.1 Manifestes YAML & Pods
Déclaratif (La voie K8s) vs Impératif

Il y a deux façons de "dire" à K8s quoi faire :

1. Impératif (Ordres directs)

Vous donnez des ordres. Facile pour débuter, mais difficile à reproduire et à maintenir.

# Crée un deployment
kubectl create deployment nginx --image=nginx

# Change l'image (mise à jour)
kubectl set image deployment/nginx nginx=nginx:1.23

# Change les replicas
kubectl scale deployment/nginx --replicas=3
2. Déclaratif (Fichiers YAML)

Vous écrivez l'état final désiré dans un fichier YAML et vous dites à K8s : "Fais en sorte que la réalité ressemble à ce fichier." C'est la **méthode standard** pour la production (stockée dans Git).

# Fichier: nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.23
# Appliquer l'état désiré
kubectl apply -f nginx-deployment.yml

Si vous modifiez replicas: 5 dans le YAML et refaites apply, K8s calcule la différence et crée 2 Pods.

Anatomie d'un manifeste K8s

Tous les fichiers YAML K8s ont 4 champs principaux :

apiVersion: [Version de l'API à utiliser]
kind: [Type d'objet à créer]
metadata: [Infos sur l'objet (nom, labels...)]
spec: [La "spécification" de l'objet (son état désiré)]
ChampExplication
apiVersionIndique à K8s quelle version d'API utiliser. (ex: v1 pour les Pods/Services, apps/v1 pour les Deployments, batch/v1 pour les Jobs).
kindLe type d'objet. (ex: Pod, Service, Deployment, ConfigMap, Ingress).
metadataDonnées d'identification. Contient name (nom unique) et labels (étiquettes clés/valeurs pour les Selectors).
specLe plus important. C'est là que vous décrivez l'état désiré. La structure de spec change *totalement* en fonction du kind. (ex: pour un Pod, spec contient containers. Pour un Service, spec contient ports et selector).
Exemple : Pod Nginx (pod.yml)

Ceci est la définition la plus simple d'un Pod. (Rappel : en pratique, on utilise un Deployment).

# apiVersion 'v1' pour les objets "core"
apiVersion: v1

# kind 'Pod'
kind: Pod

metadata:
  name: mon-pod-nginx
  labels:
    app: serveur-web # Label pour les Services
    env: dev

spec:
  # 'spec' d'un Pod contient une liste de conteneurs
  containers:
  
  # Premier (et unique) conteneur
  - name: nginx-container
    image: nginx:1.22
    ports:
      - containerPort: 80 # Port exposé par le conteneur
    
    # Limites de ressources (bonne pratique)
    resources:
      requests: # Quantité garantie
        memory: "64Mi"
        cpu: "250m" # 0.25 vCPU
      limits: # Plafond maximum
        memory: "128Mi"
        cpu: "500m"
kubectl apply vs kubectl create

Cette distinction est cruciale pour les débutants.

kubectl create -f mon-fichier.yml
  • Impératif.
  • Tente de créer la ressource.
  • Si la ressource (ex: name: mon-pod) existe déjà, cela échoue avec une erreur "AlreadyExists".
  • À n'utiliser que si vous êtes certain que l'objet n'existe pas.
kubectl apply -f mon-fichier.yml (La bonne méthode)
  • Déclaratif.
  • Regarde l'API Server si l'objet existe.
    • S'il n'existe pas : le crée (comme create).
    • S'il existe déjà : K8s calcule la différence (un "diff") entre le YAML et l'état actuel, et n'applique que les changements.
  • C'est la commande idempotente à utiliser 99% du temps, notamment en CI/CD.
Supprimer
# Supprime l'objet créé par le fichier
kubectl delete -f mon-fichier.yml
3.2 Deployments (Mises à jour & Scaling)
Exemple : deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mon-app-deployment
spec:
  # 1. État désiré : 3 replicas
  replicas: 3
  
  # 2. Selector : quels Pods ce Deployment gère-t-il ?
  selector:
    matchLabels:
      app: mon-app # Doit correspondre aux labels du template
      
  # 3. Stratégie de mise à jour
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1       # (max 1 Pod de *plus* que 'replicas')
      maxUnavailable: 0 # (min 0 Pods *en moins* que 'replicas')

  # 4. Template de Pod : à quoi doit ressembler chaque Pod ?
  template:
    metadata:
      labels:
        app: mon-app # Le label que le 'selector' utilise
    spec:
      containers:
      - name: app-container
        image: mon-image:v1.0
        ports:
        - containerPort: 8080
        
        # Health Checks (ESSENTIEL pour le rolling update)
        livenessProbe: # K8s tue le Pod si ça échoue
          httpGet:
            path: /healthz
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
          
        readinessProbe: # K8s arrête d'envoyer du trafic (Service)
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
Schéma d'un Rolling Update (maxSurge=1, maxUnavailable=0)

Vous appliquez un YAML avec image: mon-image:v2.0.

ÉTAT INITIAL (replicas=3)
Service -> [ V1 ] [ V1 ] [ V1 ]

ÉTAPE 1 (maxSurge=1)
K8s ajoute 1 Pod V2. Total = 4 Pods (3+1)
Service -> [ V1 ] [ V1 ] [ V1 ] [ V2 (starting) ]

ÉTAPE 2 (readinessProbe V2 OK)
K8s ajoute V2 au Service.
Service -> [ V1 ] [ V1 ] [ V1 ] [ V2 (Ready) ]

ÉTAPE 3 (maxUnavailable=0)
K8s supprime 1 Pod V1. Total = 3 Pods.
Service -> [ V1 ] [ V1 ] [ V2 ]

ÉTAPE 4
K8s ajoute 1 Pod V2. Total = 4 Pods.
Service -> [ V1 ] [ V1 ] [ V2 ] [ V2 (starting) ]

ÉTAPE 5 (readinessProbe V2 OK)
K8s supprime 1 Pod V1. Total = 3 Pods.
Service -> [ V1 ] [ V2 ] [ V2 ]

... (processus répété)

ÉTAT FINAL
Service -> [ V2 ] [ V2 ] [ V2 ]

Si le readinessProbe du Pod V2 échoue, K8s arrête le déploiement et (selon config) peut déclencher un rollback.

Gérer les Deployments
# Appliquer un changement (ex: changer l'image dans le YAML)
kubectl apply -f deployment.yml

# Voir le statut du déploiement
kubectl rollout status deployment/mon-app-deployment

# Mettre à l'échelle (scaling)
kubectl scale deployment/mon-app-deployment --replicas=5

# Mettre à l'échelle automatiquement (HPA)
# (Nécessite le Metrics Server)
kubectl autoscale deployment/mon-app-deployment --cpu-percent=80 --min=3 --max=10

# Voir l'historique des versions
kubectl rollout history deployment/mon-app-deployment

# Revenir à la version précédente (Rollback)
kubectl rollout undo deployment/mon-app-deployment

# Revenir à une version spécifique (ex: 3)
kubectl rollout undo deployment/mon-app-deployment --to-revision=3
3.3 StatefulSets & DaemonSets
StatefulSet (Pour les BDD, files d'attente...)

Les Deployments gèrent des Pods "anonymes" et interchangeables. C'est parfait pour des frontends web, mais pas pour des bases de données en cluster (ex: ZooKeeper, Kafka, MySQL en réplication).

Un StatefulSet offre des garanties uniques :

  • Identité Réseau Stable : Les Pods sont nommés web-0, web-1, web-2. S'ils redémarrent, ils gardent ce nom et ce nom DNS.
  • Stockage Persistant Stable : Chaque Pod (web-0) est lié à son propre PersistentVolumeClaim (data-web-0).
  • Déploiement Ordonné : K8s déploie web-0, attend qu'il soit "Ready", PUIS déploie web-1, etc. (Inverse pour la suppression).
# Extrait YAML d'un StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  replicas: 3
  serviceName: "nginx" # Service "Headless" requis
  selector:
    matchLabels:
      app: nginx
  
  template:
    # ... (template de Pod) ...
    
  # Définit le template pour le stockage
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

K8s va créer 3 Pods (web-0, web-1, web-2) et 3 Volumes (data-web-0, data-web-1, data-web-2).

DaemonSet (Un Pod par Nœud)

Un DaemonSet garantit qu'une copie d'un Pod s'exécute sur **tous** (ou un sous-ensemble) les nœuds du cluster. Si vous ajoutez un nœud, le DaemonSet y ajoute automatiquement le Pod.

Cas d'usage typiques
  • Agents de Logging : (ex: Fluentd, Logstash) pour collecter les logs de *chaque* nœud.
  • Agents de Monitoring : (ex: Prometheus Node Exporter, Datadog Agent) pour collecter les métriques de *chaque* nœud.
  • Réseau/Stockage : (ex: Calico, Ceph) pour gérer le CNI ou le stockage distribué sur *chaque* nœud.
# Extrait YAML d'un DaemonSet (pour un agent de log)
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-agent
spec:
  selector:
    matchLabels:
      name: fluentd-agent
  template:
    metadata:
      labels:
        name: fluentd-agent
    spec:
      containers:
      - name: fluentd
        image: fluent/fluentd-k8s:v1
        
        # Monte les logs du NŒUD HÔTE dans le conteneur
        volumeMounts:
        - name: varlog
          mountPath: /var/log
          
      volumes:
      - name: varlog
        hostPath: # Accède au filesystem de l'hôte
          path: /var/log
4.1 Services (Exposition réseau)
Exemple : service.yml

Ce Service va cibler les Pods du Deployment de l'exemple 3.2.

apiVersion: v1
kind: Service
metadata:
  name: mon-service-app
spec:
  # 1. Type de service
  # (ClusterIP, NodePort, LoadBalancer, ExternalName)
  type: ClusterIP 
  
  # 2. Selector : trouve les Pods avec ce label
  selector:
    app: mon-app # Doit correspondre au label des Pods (cf Deployment)

  # 3. Ports
  ports:
  - protocol: TCP
    port: 80 # Port sur lequel le Service écoute
    targetPort: 8080 # Port sur lequel les Pods écoutent
FLUX DE LA REQUÊTE
[Autre Pod] -> http://mon-service-app:80 -> [Service] -> [Pod Cible]:8080

K8s crée automatiquement une entrée DNS interne : mon-service-app.default.svc.cluster.local (accessible en short-name mon-service-app depuis le même Namespace).

1. ClusterIP (Défaut)

Expose le Service sur une adresse IP **interne** au cluster. C'est le type par défaut.

Usage : Communication interne (ex: un frontend web qui parle à un backend API, ou une API qui parle à une BDD). Le service n'est **pas accessible** depuis l'extérieur du cluster.

type: ClusterIP
[Internet] -X-> [Service ClusterIP]
                   |
[Pod Frontend] ->--+--> [Pods Backend]
2. NodePort (Externe simple)

Expose le Service sur un port statique (ex: 30000-32767) sur **l'IP de chaque Worker Node**.

Usage : Développement, démo, ou cas où vous gérez votre propre Load Balancer externe. Un service NodePort crée *aussi* un ClusterIP.

type: NodePort
# nodePort: 30080 (optionnel, K8s en choisit un sinon)
[Internet] -> http://[IP_DU_NODE]:30080 -> [Service NodePort] -> [Pods Backend]

Inconvénient : Vous devez connaître l'IP d'au moins un nœud, et le port est dans une plage élevée.

3. LoadBalancer (Externe Cloud)

Le type le plus courant pour exposer une application sur Internet. Expose le Service en utilisant le **Load Balancer du fournisseur Cloud** (GCP, AWS, Azure).

Usage : Production. Un service LoadBalancer crée *aussi* un NodePort et un ClusterIP.

type: LoadBalancer
[Internet] -> http://[IP_PUBLIQUE_DU_LB] -> [Service LB] -> [Pods Backend]
               (Provisionnée par AWS/GCP/Azure)

K8s parle à l'API du Cloud, provisionne un LB, et configure les règles pour router le trafic vers les NodePorts des nœuds.

4.2 ConfigMaps & Secrets
ConfigMap (Configuration non-sensible)

Un ConfigMap est un objet K8s qui stocke des données de configuration (clés-valeurs) en **texte clair**. Il permet de découpler la configuration de l'image Docker.

Exemple YAML (configmap.yml)
apiVersion: v1
kind: ConfigMap
metadata:
  name: mon-app-config
data:
  # Clés-valeurs simples
  APP_COLOR: "blue"
  API_URL: "https://api.monsite.com/v1"
  
  # Contenu de type "fichier" (ex: config.properties)
  config.properties: |
    feature.flag.x=true
    log.level=INFO
Création impérative
# Depuis un fichier
kubectl create configmap config-file --from-file=mon-fichier.conf

# Depuis des clés
kubectl create configmap app-vars --from-literal=APP_USER=admin
Secret (Configuration sensible)

Similaire à un ConfigMap, mais conçu pour les données sensibles (mots de passe, clés d'API, certificats TLS). Les données sont stockées en **Base64** dans etcd.

Attention : Base64 n'est *pas* du chiffrement, c'est de l'encodage. C'est juste pour éviter que le secret soit lisible à l'œil nu. La vraie sécurité vient de RBAC (qui peut *lire* le Secret) et du chiffrement etcd au repos.

Exemple YAML (secret.yml)
apiVersion: v1
kind: Secret
metadata:
  name: mon-app-secret
type: Opaque # Type par défaut (données arbitraires)
data:
  # Les valeurs DOIVENT être en Base64
  # echo -n 'mon-super-pass' | base64
  DB_PASSWORD: "bW9uLXN1cGVyLXBhc3M="
  # echo -n 'admin' | base64
  DB_USER: "YWRtaW4="
Création impérative
kubectl create secret generic db-secret \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASSWORD=mon-super-pass
Utilisation dans un Pod

Il y a deux façons principales d'exposer un ConfigMap ou un Secret à un Pod :

apiVersion: v1
kind: Pod
metadata:
  name: pod-avec-config
spec:
  containers:
  - name: mon-app
    image: mon-image
    
    # 1. En tant que Variables d'Environnement
    env:
      - name: MON_APP_URL # Nom de la variable
        valueFrom:
          configMapKeyRef:
            name: mon-app-config # Nom du ConfigMap
            key: API_URL        # Clé dans le ConfigMap
            
      - name: DATABASE_PASS
        valueFrom:
          secretKeyRef:
            name: mon-app-secret # Nom du Secret
            key: DB_PASSWORD    # Clé dans le Secret

    # 2. En tant que Fichier (monté en volume)
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config # Le fichier 'config.properties' sera ici
      
  volumes:
  - name: config-volume
    configMap:
      name: mon-app-config # Monte TOUT le ConfigMap
      items:
      - key: config.properties # Monte juste cette clé
        path: config.properties # sous ce nom de fichier
4.3 Volumes & Persistance (PV, PVC)
Le problème : Les Pods sont éphémères

Le système de fichiers (filesystem) d'un conteneur est **éphémère**. Si un conteneur crash et redémarre (ou si le Pod est recréé), toutes les données écrites sont **perdues**.

Volumes K8s

K8s fournit une abstraction de "Volume" qui est liée au cycle de vie du **Pod** (et non du conteneur). Si le conteneur crash, le volume persiste.

Types de volumes courants :

  • emptyDir : Un répertoire vide créé quand le Pod démarre. Vides à chaque (re)démarrage du Pod. Utile pour du cache temporaire entre conteneurs d'un même Pod.
  • configMap / secret : Monte un ConfigMap ou un Secret en tant que fichiers (lecture seule).
  • hostPath : Monte un répertoire du **nœud hôte** (dangereux, à éviter sauf cas précis comme les DaemonSets).
  • persistentVolumeClaim : La bonne méthode pour le stockage persistant (BDD, uploads...).
PersistentVolume (PV) & PersistentVolumeClaim (PVC)

K8s abstrait le stockage (EBS, GCE Disk, NFS...) via deux objets :

  • PersistentVolume (PV) : Une "part" de stockage dans le cluster. C'est l'**Offre** de stockage, généralement créée par l'Admin. (ex: "J'ai un disque NFS de 100Go").
  • PersistentVolumeClaim (PVC) : Une **Demande** de stockage faite par un utilisateur/Pod. (ex: "Mon Pod a besoin de 10Go de stockage rapide").

K8s fait le "matching" (binding) entre un PVC et un PV compatible.

ADMINISTRATEUR
+----------------------------+
| PersistentVolume (PV)      |
| "Offre: 100Gi, NFS, 'slow'" |
+----------------------------+
+----------------------------+
| PersistentVolume (PV)      |
| "Offre: 50Gi, SSD, 'fast'"  |
+----------------------------+
       |
       | K8s "bind" (lie)
       |
UTILISATEUR (Développeur)
+----------------------------+
| PersistentVolumeClaim (PVC)|
| "Demande: 10Gi, 'fast'"    |
+----------------------------+
       |
       | (Utilisé par le Pod)
       ▼
+----------------------------+
| Pod (ex: BDD PostgreSQL)   |
+----------------------------+

Le développeur n'a pas besoin de savoir ce qu'est "EBS" ou "GCE Disk". Il demande juste "10Gi fast", et K8s s'occupe de lui fournir le bon PV.

Exemple : PVC et Pod
1. pvc.yml (La Demande)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mon-pvc-data
spec:
  accessModes:
    - ReadWriteOnce # Montable en R/W par 1 seul nœud
    # ReadWriteMany (NFS)
    # ReadOnlyMany
  resources:
    requests:
      storage: 5Gi # Je demande 5 Giga
  # storageClassName: "fast" # (Optionnel) demande un type spécifique
2. pod-db.yml (Le Consommateur)
apiVersion: v1
kind: Pod
metadata:
  name: postgres-db
spec:
  containers:
  - name: postgres
    image: postgres:15
    ports:
    - containerPort: 5432
    volumeMounts:
    - name: data-storage
      # Monte le volume dans le répertoire de données de Postgres
      mountPath: /var/lib/postgresql/data
      
  volumes:
  - name: data-storage
    # Ce volume utilise le PVC
    persistentVolumeClaim:
      claimName: mon-pvc-data
StorageClass (Provisionnement Dynamique)

Créer des PV manuellement est fastidieux. Les **StorageClasses** permettent le **provisionnement dynamique**.

L'admin définit une "StorageClass" (ex: "ssd-fast" qui pointe vers GCE PD-SSD, ou "hdd-slow" qui pointe vers GCE PD-Standard).

# Exemple de StorageClass (Cloud)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/gce-pd # Provisionneur GKE
parameters:
  type: pd-ssd # Type de disque Google

Quand un utilisateur crée un PVC demandant la StorageClass "fast-ssd", K8s appelle l'API Google, **crée un disque SSD GCE** (le PV) à la volée, et le lie au PVC. Tout est automatique.

5.1 Namespaces (Isolation logique)
Isolation virtuelle

Un Namespace (NS) est un "cluster virtuel" à l'intérieur de votre cluster K8s. Il permet de partitionner les ressources.

Important : Les Namespaces n'isolent **pas** le réseau par défaut. Un Pod du NS "dev" peut appeler un Pod du NS "prod" (sauf si une NetworkPolicy est en place).

Namespaces par défaut
  • default : Là où vos objets vont si vous ne spécifiez rien.
  • kube-system : Réservé aux composants du Control Plane (API Server, CoreDNS, etcd...). Ne pas toucher !
  • kube-public : Données publiques, lisibles par tous.
  • kube-node-lease : Gère les "heartbeats" des nœuds.
Cas d'usage

La meilleure pratique est de ne **jamais** utiliser le NS default. Créez des Namespaces par environnement, par équipe ou par application.

CLUSTER K8s
+------------------------------------------+
| Namespace: dev                           |
|  [Deploy: app-v2] [Svc: app] [DB: postgres]|
+------------------------------------------+
| Namespace: staging                       |
|  [Deploy: app-v1.5] [Svc: app] [DB: clone] |
+------------------------------------------+
| Namespace: prod                          |
|  [Deploy: app-v1] [Svc: app] [DB: prod-db] |
+------------------------------------------+
| Namespace: monitoring                    |
|  [Prometheus] [Grafana]                  |
+------------------------------------------+

Les noms des objets (Deployments, Services) doivent être uniques *au sein d'un Namespace*.

Utilisation de kubectl
# Créer un Namespace
kubectl create namespace dev
# ou via YAML
# apiVersion: v1
# kind: Namespace
# metadata:
#   name: dev

# Lister tous les Namespaces
kubectl get namespaces
# (ou 'kubectl get ns')

# Lister les Pods dans un Namespace spécifique
kubectl get pods --namespace=dev
# Raccourci:
kubectl get pods -n dev

# Définir le NS par défaut pour le contexte actuel
kubectl config set-context --current --namespace=dev
# (Maintenant, 'kubectl get pods' cible 'dev' par défaut)

# Supprimer un NS (supprime TOUT ce qu'il contient)
kubectl delete namespace dev
Quotas

Les Namespaces sont la base pour appliquer des ResourceQuotas (ex: "L'équipe 'dev' ne peut pas utiliser plus de 20 CPU et 100Gi de RAM").

5.2 Ingress (Routage L7)
Problème : Trop de LoadBalancers

Un Service de type LoadBalancer (cf 4.1) provisionne un Load Balancer Cloud (L4) **par service**. Si vous avez 20 services, vous payez pour 20 LoadBalancers (très cher).

Solution : Ingress (L7)

Un Ingress est un "proxy inverse intelligent" (L7) qui tourne dans le cluster. Il permet de router le trafic HTTP/HTTPS vers plusieurs services en se basant sur le **nom d'hôte** (Host) ou le **chemin** (Path).

Vous n'exposez qu'un seul LoadBalancer (celui de l'Ingress) qui sert de point d'entrée unique.

[Internet]
    |
    ▼
[Service type: LoadBalancer] (1 seul LB payant)
    |
    ▼
[POD: Ingress Controller (ex: Nginx)]
    |
    |-- (Host: 'api.monsite.com')  --> [Service: api]      --> [Pods API]
    |
    |-- (Host: 'blog.monsite.com') --> [Service: blog]     --> [Pods Blog]
    |
    |-- (Host: 'monsite.com'
    |    Path: '/admin')            --> [Service: admin]    --> [Pods Admin]
L'Ingress Controller (Le moteur)

Créer un objet kind: Ingress (le YAML) ne fait **RIEN** tout seul.

Un objet Ingress est une "règle de routage". Vous avez besoin d'un **Ingress Controller** (un vrai logiciel qui tourne dans un Pod) pour lire ces règles et appliquer la configuration.

Le Controller n'est (souvent) pas installé par défaut.

Contrôleurs populaires
  • Ingress-Nginx : Le plus populaire, maintenu par K8s (utilise Nginx).
  • Traefik : Très populaire, moderne, gère le SSL (Let's Encrypt) automatiquement.
  • Contrôleurs Cloud : GKE/AWS/Azure ont leurs propres Ingress Controllers qui provisionnent des LB L7 (ex: Google Cloud Load Balancer).
Installation (exemple Nginx Ingress via Helm)
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

helm install nginx-ingress ingress-nginx/ingress-nginx \
    --namespace ingress-nginx \
    --create-namespace

Ceci va créer un Deployment (le contrôleur) et un Service de type LoadBalancer pour l'exposer.

Exemple : ingress.yml

Ce YAML définit les règles de routage (après avoir installé un Ingress Controller).

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mon-ingress
  annotations:
    # Annotation spécifique au contrôleur (ici Nginx)
    nginx.ingress.kubernetes.io/rewrite-target: /
    # Annotation pour le SSL (si cert-manager est installé)
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  # Classe d'Ingress (dit quel contrôleur utiliser)
  ingressClassName: nginx
  
  # Gestion du TLS (HTTPS)
  tls:
  - hosts:
    - api.monsite.com
    - blog.monsite.com
    secretName: monsite-tls-secret # Secret (kind: Secret) contenant le cert/key
    
  rules:
  # Règle 1: Routage basé sur l'hôte
  - host: "api.monsite.com"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service # Service (ClusterIP)
            port:
              number: 80
              
  # Règle 2: Autre hôte
  - host: "blog.monsite.com"
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: blog-wordpress-service
            port:
              number: 80
5.3 Sécurité : RBAC (Role-Based Access Control)
Principe de RBAC

RBAC (Role-Based Access Control) est le mécanisme de sécurité de K8s. Il repose sur 4 objets :

QUI ? (Sujet)
  -> User (Humain, géré en externe)
  -> Group (Groupe d'humains)
  -> ServiceAccount (Processus dans un Pod)
  
    LIE (Binding)
    +----------------------+
    | RoleBinding          | (Pour un Namespace)
    | ClusterRoleBinding   | (Pour tout le cluster)
    +----------------------+
    
COMMENT ? (Permissions)
  -> Role         (Liste de verbes/ressources DANS un Namespace)
  -> ClusterRole  (Liste de verbes/ressources PARTOUT)
  • Role : (Quoi) "Peut *get*, *list*, *watch* les *Pods*". (Où) **Dans** un Namespace (ex: "dev").
  • RoleBinding : (Lien) "Lie le *User 'bob'* au *Role 'pod-reader'*". (Où) **Dans** le Namespace "dev".
  • ClusterRole : (Quoi) "Peut *get*, *list* les *Nodes*". (Où) **Partout** (cluster-wide).
  • ClusterRoleBinding : (Lien) "Lie le *Group 'admins'* au *ClusterRole 'cluster-admin'*". (Où) **Partout**.
ServiceAccount (Identité pour les Pods)

Par défaut, un Pod s'exécute avec le ServiceAccount (SA) "default" du Namespace, qui n'a (presque) aucun droit.

Si un Pod a besoin de parler à l'API K8s (ex: un Pod Prometheus qui doit découvrir les Services), vous devez :

  1. Créer un ServiceAccount (ex: sa-prometheus).
  2. Créer un Role ou ClusterRole avec les permissions (ex: role-prometheus avec "get/list Services").
  3. Créer un RoleBinding qui lie sa-prometheus à role-prometheus.
  4. Attacher le ServiceAccount au Pod (spec.serviceAccountName: sa-prometheus).
Exemple : Role (Namespace "dev")

Autorise la lecture des Pods dans le NS "dev".

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: dev
rules:
- apiGroups: [""] # "" = Core API group
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]
Exemple : RoleBinding (Namespace "dev")

Donne le Role "pod-reader" à l'utilisateur "jane.doe".

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: jane-can-read-pods
  namespace: dev
subjects:
- kind: User
  name: "jane.doe" # Nom de l'utilisateur
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role # Lie à un Role (pas ClusterRole)
  name: pod-reader # Nom du Role ci-dessus
  apiGroup: rbac.authorization.k8s.io
6.1 Helm (Le gestionnaire de paquets)
Problème : Gérer des YAMLs complexes

Une application simple (ex: WordPress) nécessite plusieurs objets K8s (Deployment, Service, Secret, PVC...). Une application complexe (ex: Prometheus) peut nécessiter 50+ fichiers YAML.

Solution : Helm

Helm est le "apt" ou "brew" de Kubernetes. Il gère des **Charts**.

  • Chart : Un "paquet" Helm. C'est un dossier contenant des templates de YAML et un fichier values.yml (pour la configuration).
  • Values.yml : Le fichier de configuration que vous modifiez (ex: image.tag, replicaCount, ingress.enabled).
  • Release : Une instance d'un Chart déployé sur votre cluster. (Vous pouvez installer le Chart "mysql" 5 fois = 5 Releases).
  • Repository : Un "dépôt" d'index de Charts (ex: bitnami, jetstack).
Commandes Helm de base
# Ajouter un dépôt de Charts
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# Chercher un Chart
helm search repo bitnami/mysql

# Installer un Chart (crée une "Release")
helm install my-release-mysql bitnami/mysql \
    --namespace mysql \
    --create-namespace \
    --set auth.rootPassword="mon-pass"

# Mettre à jour (ex: changer le mot de passe)
helm upgrade my-release-mysql bitnami/mysql \
    --set auth.rootPassword="nouveau-pass"

# Lister les "Releases" installées
helm list -n mysql

# Désinstaller une "Release" (supprime tous les objets K8s)
helm uninstall my-release-mysql -n mysql
6.2 Monitoring & Logs
Logs (stdout/stderr)

La bonne pratique dans K8s est de logger sur la **sortie standard** (stdout) et non dans des fichiers. Le Container Runtime capture ce flux.

# Voir les logs d'un Pod (depuis le début)
kubectl logs [NOM-DU-POD]

# Suivre les logs en direct (style tail -f)
kubectl logs -f [NOM-DU-POD]

# Si le Pod a plusieurs conteneurs, spécifiez lequel
kubectl logs -f [NOM-DU-POD] -c [NOM-CONTENEUR]

# Voir les logs du Pod *précédent* (s'il a crashé)
kubectl logs --previous [NOM-DU-POD]

kubectl logs est utile pour le debug instantané, mais pas pour l'historique (les logs sont perdus si le nœud meurt). Pour la production, on utilise des "log shippers" (Fluentd, Promtail) pour agréger les logs (via un DaemonSet).

Métriques (CPU/RAM)

K8s intègre un **Metrics Server** (doit souvent être installé) qui collecte les métriques de base (CPU/RAM) des nœuds et des Pods.

Installation (Minikube)
minikube addons enable metrics-server
Commandes
# Voir l'utilisation CPU/RAM des Nœuds
kubectl top nodes
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
minikube   350m         17%    1783Mi          45%

# Voir l'utilisation CPU/RAM des Pods
kubectl top pods -n kube-system
NAME                               CPU(cores)   MEMORY(bytes)
coredns-5dd...                     4m           10Mi
etcd-minikube                      18m          47Mi
kube-apiserver-minikube            60m          256Mi
kube-controller-manager-minikube   15m          42Mi

Ces métriques sont utilisées par le Horizontal Pod Autoscaler (HPA) pour le scaling automatique.

Stack Monitoring (Prometheus & Grafana)

Pour un monitoring avancé (métriques applicatives, dashboards, alertes), la stack standard est Prometheus + Grafana.

  • Prometheus : La base de données Time-Series (TSDB). Elle "scrape" (collecte) les métriques exposées par vos applications (sur un endpoint /metrics).
  • Grafana : L'outil de visualisation (dashboards) qui se connecte à Prometheus.
  • Alertmanager : Gère les alertes (Slack, PagerDuty...) définies dans Prometheus.
[Grafana (Dashboards)] <--> [Prometheus (BDD Métriques)] <-- [Alertmanager]
                                |
                                | (Scrape /metrics)
                                ▼
+-------------------------------------------------------------+
| Cluster K8s                                                 |
|  [Pod App 1 (/metrics)] [Pod App 2 (/metrics)] [Nodes...]   |
+-------------------------------------------------------------+
Installation (via Helm)
# La stack "kube-prometheus-stack" installe tout (Prometheus, Grafana, Alertmanager)
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install prometheus prometheus-community/kube-prometheus-stack \
    --namespace monitoring --create-namespace
7.1 kubectl Cheat-sheet
Ressources (raccourcis)

po (pods), svc (services), deploy (deployments), ns (namespaces), cm (configmaps), pv, pvc, sa, netpol (networkpolicies)

# Lister les pods du namespace actuel
kubectl get pods

# Lister les pods avec plus d'infos (IP, Nœud)
kubectl get pods -o wide

# Lister les pods dans TOUS les namespaces
kubectl get pods --all-namespaces
# Raccourci:
kubectl get pods -A

# Lister les services
kubectl get svc

# Lister les deployments
kubectl get deploy

# Lister les nœuds
kubectl get nodes

# Lister les objets par label
kubectl get pods -l app=mon-app

# Voir le YAML d'un objet existant
kubectl get deployment/mon-app -o yaml
Débogage
# Décrire un Pod (voir évènements, erreurs, volumes...)
# C'EST LA COMMANDE N°1 POUR LE DEBUG
kubectl describe pod [NOM-DU-POD]

# Décrire un Nœud (voir ressources, statut, Pods dessus)
kubectl describe node [NOM-DU-NODE]

# Voir les logs d'un Pod
kubectl logs [NOM-DU-POD]

# Suivre les logs d'un Pod
kubectl logs -f [NOM-DU-POD]

# Voir les logs du conteneur précédent (s'il a crashé)
kubectl logs --previous [NOM-DU-POD]

# Voir l'utilisation CPU/RAM (si Metrics Server installé)
kubectl top pods
kubectl top nodes
Gestion (Déclaratif)
# Appliquer un manifeste (créer ou mettre à jour)
kubectl apply -f mon-fichier.yml

# Appliquer tous les manifestes d'un dossier
kubectl apply -f ./mon-dossier/

# Supprimer les objets d'un manifeste
kubectl delete -f mon-fichier.yml

# Supprimer par nom
kubectl delete pod [NOM-POD]
kubectl delete service [NOM-SERVICE]

# Supprimer un pod sans attendre (force)
kubectl delete pod [NOM-POD] --grace-period=0 --force
Gestion (Impératif)
# Changer le nombre de replicas
kubectl scale deployment/mon-app --replicas=5

# Mettre à jour l'image d'un deployment
kubectl set image deployment/mon-app [NOM-CONTENEUR]=[NOUVELLE-IMAGE:TAG]

# Voir l'historique et faire un rollback
kubectl rollout status deployment/mon-app
kubectl rollout history deployment/mon-app
kubectl rollout undo deployment/mon-app
Interaction
# Ouvrir un shell dans un conteneur (comme docker exec)
kubectl exec -it [NOM-DU-POD] -- /bin/bash
# (Utiliser /bin/sh si bash n'existe pas)

# Exécuter une commande simple
kubectl exec [NOM-DU-POD] -- ls /app

# Copier des fichiers (local -> pod)
kubectl cp ./mon-fichier.txt [NOM-DU-POD]:/tmp/fichier.txt

# Copier des fichiers (pod -> local)
kubectl cp [NOM-DU-POD]:/app/logs.txt ./logs-app.txt

# Port-forward (local) -> Pod (debug)
# Accédez à http://localhost:8080 sur votre PC
kubectl port-forward pod/[NOM-DU-POD] 8080:80

# Port-forward (local) -> Service (debug)
kubectl port-forward service/[NOM-SERVICE] 8080:80