iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
Formations
YAML / Bash · Intermédiaire

Kubernetes

De Docker Compose à Kubernetes : architecture complète, distributions (K8s, K3s, K0s, MicroK8s), objets fondamentaux, networking, Ingress, scaling automatique et déploiement en production.

KubernetesK3skubectlHelmDocker
01Pourquoi Kubernetes — le problème Docker seul ne résout pas02K8s, K3s, K0s, MicroK8s — quelle distribution choisir03Architecture interne — Control Plane et Worker Nodes04Installation — K3s en production et kubectl05Objets fondamentaux — Pod, Deployment, Service, Namespace06Configuration et stockage — ConfigMap, Secret, PVC07Networking et Ingress — exposer vos services08Scaling, RBAC, Helm et production
Chapitre 5·35 min

Objets fondamentaux — Pod, Deployment, Service, Namespace

Kubernetes fonctionne par déclaration d'objets dans des manifestes YAML. Vous décrivez l'état désiré, K8s le réalise et le maintient. Ce chapitre couvre les objets que vous utilisez dans 95% des déploiements.

Namespace — isolation logique

Les namespaces partitionnent le cluster en environnements isolés. Les ressources d'un namespace ne sont pas visibles des autres par défaut (côté réseau, avec NetworkPolicy).

namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: production
kubectl apply -f namespace.yaml
kubectl get namespaces
# NAME              STATUS   AGE
# default           Active   10m
# kube-system       Active   10m
# kube-public       Active   10m
# kube-node-lease   Active   10m
# production        Active   5s

Namespaces réservés :

  • default : où tout atterrit sans namespace explicite
  • kube-system : composants K8s (CoreDNS, kube-proxy, metrics-server)
  • kube-public : accessible sans authentification (données publiques du cluster)

Pod — l'unité de base

Un Pod est un ou plusieurs conteneurs qui partagent le réseau et le stockage. Dans 95% des cas : un Pod = un conteneur.

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mon-app
  namespace: production
  labels:
    app: mon-app
    version: "1.0"
spec:
  containers:
    - name: app
      image: nginx:1.25-alpine
      ports:
        - containerPort: 80
      resources:
        requests:
          memory: "64Mi"
          cpu: "100m"
        limits:
          memory: "128Mi"
          cpu: "200m"

Requests vs Limits :

  • requests : ce que le scheduler réserve sur le nœud pour décider du placement
  • limits : le maximum que le conteneur peut utiliser (OOMKilled si dépassement mémoire)

CPU en m = millicores. 100m = 0.1 vCPU. 1000m = 1 vCPU.

Ne déployez jamais un Pod directement en production. Les Pods sont éphémères et non auto-remplacés. Utilisez un Deployment.

Deployment — le workload standard

Un Deployment déclare le nombre de réplicas, l'image à utiliser, et la stratégie de mise à jour. Il crée et gère un ReplicaSet, qui lui-même gère les Pods.

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mon-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mon-app
  template:
    metadata:
      labels:
        app: mon-app
    spec:
      containers:
        - name: app
          image: mon-registry/mon-app:1.2.0
          ports:
            - containerPort: 3000
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "256Mi"
              cpu: "500m"
          env:
            - name: NODE_ENV
              value: production
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: database-url
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 15
          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1         # max pods en plus pendant l'update
      maxUnavailable: 0   # zéro downtime — tous les pods restent dispo

Probes — santé des conteneurs

livenessProbe : K8s tue et redémarre le conteneur si elle échoue. À utiliser pour détecter les deadlocks.

readinessProbe : K8s retire le pod du load balancer si elle échoue. Le conteneur tourne mais ne reçoit plus de trafic. À utiliser pour le warm-up au démarrage.

startupProbe : remplace liveness pendant le démarrage pour les apps lentes. Une fois réussie, liveness prend le relais.

startupProbe:
  httpGet:
    path: /health
    port: 3000
  failureThreshold: 30    # 30 * 10s = 5 min max pour démarrer
  periodSeconds: 10

Commandes sur les Deployments

# Déployer
kubectl apply -f deployment.yaml
 
# Status du rollout
kubectl rollout status deployment/mon-app -n production
 
# Historique des versions
kubectl rollout history deployment/mon-app -n production
 
# Mettre à jour l'image
kubectl set image deployment/mon-app app=mon-registry/mon-app:1.3.0 -n production
 
# Rollback à la version précédente
kubectl rollout undo deployment/mon-app -n production
 
# Rollback à une version spécifique
kubectl rollout undo deployment/mon-app --to-revision=2 -n production
 
# Scaler manuellement
kubectl scale deployment mon-app --replicas=5 -n production

Service — exposition réseau stable

Les Pods ont des IPs qui changent à chaque recréation. Un Service fournit une IP et un DNS stables, et distribue le trafic vers les Pods correspondants via un sélecteur de labels.

ClusterIP (type par défaut)

Accessible uniquement depuis l'intérieur du cluster. Pour la communication inter-services.

service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: mon-app
  namespace: production
spec:
  type: ClusterIP
  selector:
    app: mon-app       # cible tous les pods avec ce label
  ports:
    - port: 80         # port du Service
      targetPort: 3000 # port du conteneur
      protocol: TCP

DNS interne : mon-app.production.svc.cluster.local (ou juste mon-app depuis le même namespace).

NodePort

Expose le Service sur un port de chaque nœud (30000–32767). Accessible depuis l'extérieur via <node-ip>:<nodePort>.

spec:
  type: NodePort
  selector:
    app: mon-app
  ports:
    - port: 80
      targetPort: 3000
      nodePort: 30080   # optionnel, sinon assigné automatiquement

Usage : tests et développement. En production, préférer LoadBalancer ou Ingress.

LoadBalancer

Provisionne un load balancer externe (AWS ALB, GCP LB, etc.) qui route vers le Service.

spec:
  type: LoadBalancer
  selector:
    app: mon-app
  ports:
    - port: 80
      targetPort: 3000

Sur bare metal/K3s, ce type nécessite MetalLB ou Kube-VIP pour fonctionner.

Headless Service

Pas de ClusterIP — le DNS retourne directement les IPs des pods. Utilisé par StatefulSets.

spec:
  clusterIP: None
  selector:
    app: mon-db

ReplicaSet — sous le Deployment

Vous n'interagissez généralement pas directement avec les ReplicaSets — c'est le Deployment qui les gère. Mais comprendre leur rôle aide à diagnostiquer.

kubectl get replicasets -n production
# NAME                   DESIRED   CURRENT   READY
# mon-app-7d4b8f9c6      3         3         3     ← version actuelle
# mon-app-6c8b7f4d2      0         0         0     ← ancienne version (gardée pour rollback)

Chaque rolling update crée un nouveau ReplicaSet. L'ancien est conservé avec 0 réplica pour permettre le rollback.

StatefulSet — workloads avec état

Pour les bases de données et les services qui ont besoin d'une identité stable (PostgreSQL, Redis cluster, Elasticsearch).

statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
  namespace: production
spec:
  serviceName: postgres   # headless service
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16
          env:
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: postgres-secrets
                  key: password
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        resources:
          requests:
            storage: 20Gi

Différences StatefulSet vs Deployment :

  • Les pods ont des noms stables : postgres-0, postgres-1, postgres-2
  • Les pods démarrent et s'arrêtent dans l'ordre
  • Chaque pod a son propre PersistentVolumeClaim
  • Le DNS de chaque pod est stable : postgres-0.postgres.production.svc.cluster.local

Les objets fondamentaux sont maîtrisés. Le chapitre suivant couvre ConfigMaps, Secrets, PersistentVolumes et PersistentVolumeClaims — la gestion de la configuration et du stockage.

Précédent
Installation — K3s en production et kubectl
Suivant
Configuration et stockage — ConfigMap, Secret, PVC

Développeur fullstack passionné. J'apprends en construisant et je documente tout — front, back, outils. Le code s'apprend mieux en public.

Naviguer

IndexTous les articlesFormationsProfilOutilsBibliothech

Ailleurs

GitHub RSS

Newsletter

Les articles, libs et découvertes. Une fois par semaine, pas plus.

© 2026 William LoreeConçu & codé à la main