← Index
Cours · Fondamentaux

k8s · bases

Kubernetes en 12 concepts, chacun accompagné d'un schéma. L'idée centrale : tu déclares l'état désiré, le cluster fait le reste.

NIVEAU · Débutant+
DURÉE · ~20 min
PRÉ-REQUIS · Docker / conteneurs

Qu'est-ce que Kubernetes ? 01

Un orchestrateur déclaratif de conteneurs

Tu écris ce que tu veux (3 replicas de mon API, exposées en HTTPS) ; Kubernetes fait tourner, redémarre, scale, réseau, route — en continu.

  • Déclaratif : tu décris l'état désiré dans du YAML, pas la suite d'actions à exécuter.
  • Self-healing : un pod qui crash est recréé, un node qui tombe voit ses pods replanifiés ailleurs.
  • Scalable : tu passes de 1 à 100 replicas avec kubectl scale (ou l'autoscaler).
  • Portable : même API sur AWS, GCP, Azure, bare-metal, dev local (kind, minikube).
  • API centrée : tout est une ressource stockée dans etcd, manipulée via l'API Server.
DESIRED STATE ce que tu déclares replicas: 3 image: api:v2 port: 8080 KUBERNETES compare & agit diff → action create · update · delete ACTUAL STATE ce qui tourne 3 pods running sur les nodes observe (boucle continue)
Fig. 01 · Le modèle déclaratif

Architecture 02

Control plane + nodes

Le control plane est le cerveau (décide). Les nodes sont les bras (exécutent). Un cluster = 1+ control plane + N nodes.

CONTROL PLANE — le cerveau kube-apiserver point d'entrée unique · REST / gRPC etcd état du cluster (kv) scheduler pod → node controller-mgr boucles de réconc. cloud-controller LB, volumes cloud L'API Server est le seul à parler à etcd. Tous les autres composants passent par lui. API WORKER NODES — les bras (N machines) node-1 kubelet kube-proxy container runtime (containerd) pod nginx pod api pod db kubelet exécute les pods que l'API Server lui assigne. kube-proxy gère les règles iptables/ipvs. node-2 kubelet kube-proxy container runtime pod pod pod
Fig. 02 · Architecture — Control plane (cyan) · Nodes (rose) · Pods (vert)
API SERVER
Porte d'entrée
ETCD
Source de vérité
SCHEDULER
Place les pods
CONTROLLER-MGR
Réconcilie
KUBELET
Agent par node
KUBE-PROXY
Routage L4

Boucle de réconciliation 03

Le pattern fondamental

Un controller est une boucle : lire desired, lire actual, agir pour combler l'écart. Tout Kubernetes est ça.

  • Chaque type d'objet (Deployment, Service, Node…) a son controller.
  • La boucle tourne en continu — c'est pour ça qu'on parle de self-healing.
  • Tu peux écrire ton propre controller (operator pattern) pour gérer des CRDs.
observe actual state diff desired ≠ actual ? act create / update / delete desired depuis etcd
Fig. 03 · Reconciliation loop

Pod 04

L'unité atomique

Un pod = 1+ conteneurs qui partagent le même réseau (localhost, IP) et les mêmes volumes. On déploie rarement des pods directement.

  • Éphémère : une IP, un hostname, ça meurt et c'est remplacé — ne te lie pas à une IP de pod.
  • Co-localisation : les conteneurs d'un pod sont toujours sur le même node.
  • Multi-container surtout pour des sidecars (log, proxy, init).
POD 10.244.1.23 · node-1 app node:20 :3000 log-sidecar fluentbit tails /var/log network ns localhost partagé volumes emptyDir / pvc
Fig. 04 · Pod = conteneurs + net + volumes partagés
apiVersion: v1
kind: Pod
metadata:
  name: web
spec:
  containers:
    - name: nginx
      image: nginx:1.27
      ports: [{ containerPort: 80 }]

Deployment & ReplicaSet 05

Gérer N replicas

Un Deployment pilote un ReplicaSet qui maintient N pods identiques. C'est ce qu'on utilise pour 95 % des apps stateless.

  • Rolling update : le Deployment crée un nouveau RS, scale up le neuf, scale down l'ancien.
  • Rollback : kubectl rollout undo — le RS précédent est encore là.
  • Scale : replicas: N suffit — le RS s'en charge.
Deployment web · replicas: 3 ReplicaSet web-6f9b pod web-6f9b-a1 pod web-6f9b-b2 pod web-6f9b-c3 owns owns
Fig. 05 · Deployment → ReplicaSet → Pods
apiVersion: apps/v1
kind: Deployment
metadata: { name: web }
spec:
  replicas: 3
  selector:
    matchLabels: { app: web }
  template:                    # ← pod template
    metadata: { labels: { app: web } }
    spec:
      containers:
        - name: web
          image: nginx:1.27

Service 06

Un endpoint stable pour des pods volatils

Les pods vont et viennent, leurs IPs changent. Un Service donne une IP/DNS fixe qui load-balance vers les pods matchés par son selector.

  • ClusterIP (défaut) : accessible uniquement depuis le cluster.
  • NodePort : expose sur un port de chaque node (30000–32767).
  • LoadBalancer : demande un LB au cloud provider (AWS ELB, GCP LB…).
  • Headless (clusterIP: None) : pour du DNS direct pod par pod (StatefulSet).
  • DNS interne : svc.namespace.svc.cluster.local — le nom du service résout automatiquement.
client curl http://web Service · ClusterIP web · 10.96.12.4 :80 selector: app=web Endpoints IPs des pods match pod app=web 10.244.1.23 :80 pod app=web 10.244.2.17 :80 pod app=web 10.244.3.42 :80 selector match → endpoints auto-maintenus
Fig. 06 · Service (selector) → Endpoints → Pods

Ingress 07

HTTP routing · hostname & path

Le Service expose en L4 (IP:port). L'Ingress route en L7 selon l'hôte et le chemin — un seul LB cloud suffit pour N apps. Il te faut un Ingress Controller (nginx, Traefik, HAProxy…).

Internet HTTPS / 443 Ingress Controller nginx / traefik / … api.ex.com/* → svc api ex.com/static/* → svc web Service api ClusterIP :8080 Service web ClusterIP :80 api-pod-1 api-pod-2 api-pod-3 web-pod-1 web-pod-2
Fig. 07 · Ingress → Services → Pods (L7 routing par host/path)

ConfigMap & Secret 08

Séparer la config du code

ConfigMap pour les valeurs non-sensibles, Secret pour les creds (base64, chiffrés au repos si configuré). Injection en env ou en volume.

  • Même image, configs différentes par environnement.
  • Monter en volume = hot-reload possible ; en env = fixé au démarrage.
  • Secrets ne sont pas chiffrés par défaut — activer encryption-config sur l'API Server.
envFrom:
  - configMapRef: { name: app-config }
  - secretRef:    { name: db-creds }

volumeMounts:
  - name: tls
    mountPath: /etc/tls
    readOnly: true
volumes:
  - name: tls
    secret: { secretName: tls-cert }

Volume · PV · PVC 09

Persistance hors du pod

Un emptyDir disparaît avec le pod. Pour survivre, un pod réclame un PVC qui se bind à un PV provisionné par une StorageClass.

Pod db mount: /data PVC data-db 10Gi · RWO PV pvc-92ab · 10Gi bound StorageClass ebs-gp3 (auto) claim bind provisionne
Fig. 09 · Pod → PVC → PV ← StorageClass
  • RWO : 1 node à la fois · ROX : lecture multi-nodes · RWX : r/w multi-nodes.
  • En dynamique : la StorageClass crée le PV automatiquement quand le PVC est posé.

Namespace 10

Isolation logique

Un cluster, plusieurs namespaces pour partitionner — par équipe, par env, par app. Les noms de ressources sont uniques par namespace.

cluster · prod-eu ns: web pod nginx svc web ns: api pod api svc api ns: db pod pg pvc data
Fig. 10 · Un cluster, trois namespaces
  • Support le RBAC, les quotas, les NetworkPolicies, les LimitRanges.
  • N'isole pas réseau par défaut — il faut des NetworkPolicies.
  • Ressources cluster-scoped (Node, PV, StorageClass) ne sont pas dans un ns.

Labels & Selectors 11

Le tissu conjonctif

Les labels sont des tags key=value posés sur des objets. Les selectors piochent des objets par match de labels. Presque tout lien dans k8s passe par là.

  • Deployment sélectionne ses pods · Service sélectionne ses endpoints · NetworkPolicy sélectionne ses cibles.
  • Bonne pratique : app=, env=, version=, tier=.
  • Les annotations sont différentes : métadonnées non-sélectionnables (pour outils, docs).
# Filtrer
kubectl get po -l 'app=web,env=prod'
kubectl get po -l 'env in (prod,stg)'
kubectl get po -l '!canary'

# Le selector d'un Service
selector:
  app: web
  tier: frontend

Probes & Ressources 12

Santé + quotas

Trois probes pour la santé, deux champs pour les ressources. C'est ce qui sépare un pod qui crash silencieusement d'un pod que k8s sait gérer.

  • livenessProbe : le pod est-il vivant ? (échec → redémarrage)
  • readinessProbe : prêt à recevoir du trafic ? (échec → retiré du Service)
  • startupProbe : démarrage lent — désactive les autres tant qu'elle n'est pas OK.
  • requests : réservation (utilisée par le scheduler).
  • limits : plafond (dépassement CPU → throttle · mémoire → OOMKill).
resources:
  requests: { cpu: 100m, memory: 128Mi }
  limits:   { cpu: 500m, memory: 512Mi }

livenessProbe:
  httpGet:   { path: /healthz, port: 8080 }
  periodSeconds: 10

readinessProbe:
  httpGet:   { path: /ready, port: 8080 }
  initialDelaySeconds: 5

Autres workloads 13

Au-delà du Deployment

STATEFULSET
Pods avec identité stable
DAEMONSET
1 pod par node
JOB
Run-to-completion
CRONJOB
Job planifié (cron)
  • StatefulSet — bases de données, Kafka, etc. Chaque pod a un nom ordonné (db-0, db-1…) et un PVC par pod.
  • DaemonSet — agents par node : Fluent Bit, node-exporter, CNI, CSI driver.
  • Job — tâche one-shot (migrations, batchs). completions et parallelism configurables.
  • CronJob — génère un Job à une expression cron (0 2 * * *).