☸️ Kubernetes – Concepts, Installation & Déploiement
Guide complet IDEO‑Lab pour maîtriser l'orchestration de conteneurs, de Minikube au Cloud.
Vue d'ensemble K8s
Qu'est-ce que Kubernetes ? Problèmes résolus.
Orchestration Auto-healingArchitecture Cluster
Control Plane (Master) et Worker Nodes.
Control Plane Nodes etcdObjets Fondamentaux
Pods, Services, Deployments, Namespaces.
Pod Service DeploymentInstallation Locale
Minikube, kind, Docker Desktop.
Minikube kind DevCLI : kubectl
Installation, configuration, contextes.
kubectl kubeconfig contextClusters Cloud (GKE/EKS/AKS)
Principes des services managés.
GKE EKS AKSManifestes YAML & Pods
Déclaratif vs Impératif, anatomie d'un Pod.
YAML Pod applyDeployments
Gestion des replicas, rolling updates, rollbacks.
ReplicaSet Rolling UpdateStatefulSets & DaemonSets
Pods stables pour BDD (Stateful) et Pods par nœud (Daemon).
StatefulSet DaemonSetServices (Networking)
ClusterIP, NodePort, LoadBalancer.
ClusterIP NodePort LoadBalancerConfigMaps & Secrets
Injecter la configuration et les secrets.
ConfigMap Secret envVolumes & Persistance
PV, PVC, StorageClass.
PersistentVolume PVC StorageClassNamespaces
Isolation logique des ressources.
namespace isolation quotaIngress
Routage HTTP/HTTPS (L7) vers les Services.
Ingress Controller L7Sécurité : RBAC
Roles, ClusterRoles, Bindings, ServiceAccounts.
RBAC ServiceAccountHelm (Package Manager)
Gérer des "Charts" (paquets K8s).
Helm Charts ReleaseMonitoring & Logs
logs, top, Prometheus, Grafana.
kubectl Cheat‑sheet
Commandes fréquentes de gestion et debug.
cheat kubectlL'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ère | Docker Compose | Kubernetes |
|---|---|---|
| Usage | Développement local, tests | Production, Staging |
| Machines | Mono-nœud (1 PC) | Multi-nœuds (Cluster) |
| Gestion | Manuelle (up/down) | Automatisée (Orchestration) |
| Réseau | Simple (bridge) | Complexe, puissant (SDN) |
| HA | Non (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.
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.
| Composant | Rôle principal |
|---|---|
| API Server | Le "frontend" du cluster. C'est le seul composant auquel vous (kubectl) et les autres composants parlent. Il valide et traite les requêtes REST. |
| etcd | La "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...). |
| Scheduler | Observe 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 Manager | Exé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).
| Composant | Rôle principal |
|---|---|
| Kubelet | L'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-proxy | Le "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 Runtime | Le logiciel qui exécute les conteneurs (ex: Docker, containerd, CRI-O). Le Kubelet lui donne les ordres (ex: "Démarre ce conteneur"). |
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"
| Objet | Cas d'usage |
|---|---|
| StatefulSet | Similaire à 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. |
| DaemonSet | S'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). |
| Job | Cré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). |
| CronJob | Un "crontab" pour K8s. Lance un Job à une heure/fréquence définie (ex: "tous les jours à 2h du matin"). |
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
- Ouvrez Docker Desktop.
- Allez dans Settings (Préférences).
- Allez dans la section Kubernetes.
- Cochez "Enable Kubernetes".
- 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
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-desktopLes 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)
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 nodesEKS (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 nodesAKS (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 nodesDé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é)]
| Champ | Explication |
|---|---|
| apiVersion | Indique à K8s quelle version d'API utiliser. (ex: v1 pour les Pods/Services, apps/v1 pour les Deployments, batch/v1 pour les Jobs). |
| kind | Le type d'objet. (ex: Pod, Service, Deployment, ConfigMap, Ingress). |
| metadata | Données d'identification. Contient name (nom unique) et labels (étiquettes clés/valeurs pour les Selectors). |
| spec | Le 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.
- S'il n'existe pas : le crée (comme
- 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
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: 5Sché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
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éploieweb-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: 1GiK8s 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/logExemple : 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 écoutentFLUX 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.
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=INFOCré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 fichierLe 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écifique2. 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-dataStorageClass (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.
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").
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-namespaceCeci 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: 80Principe 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 :
- Créer un ServiceAccount (ex:
sa-prometheus). - Créer un Role ou ClusterRole avec les permissions (ex:
role-prometheusavec "get/list Services"). - Créer un RoleBinding qui lie
sa-prometheusàrole-prometheus. - 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
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 mysqlLogs (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-namespacekubectl Cheat-sheetRessources (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
