DevOpsFacile
AccueilParcours de formationCertificationsModulesCheat SheetÀ Propos
DevOpsFacile

Une plateforme d'apprentissage complète pour maîtriser les pratiques DevOps modernes, du débutant à l'expert.

contact@devopsfacile.fr

Formation

  • Parcours de formation
  • Modules

Informations

  • À Propos
  • Conditions d'utilisation
  • Confidentialité
  • Mentions légales

© 2026 DevOps Facile. Tous droits réservés.

Fait avec pour la communauté DevOps

ModulesCKA - Domaine 4 : Workloads et Scheduling (15%)

Module

Deployments, DaemonSets, StatefulSets, Jobs, ConfigMaps, Secrets, ressources, taints, affinités et autoscaling pour la certification CKA.

  • 3 heures
  • Avancé

Formation 100 % Linux

Tous les modules nécessitent un environnement Linux. Si vous êtes sur Windows, installez d'abord WSL (Windows Subsystem for Linux) avant de continuer.

CKA - Domaine 4 : Workloads et Scheduling (15%)

🎯 Objectifs

À la fin de ce module, tu seras capable de :

  • ✅ Gérer des Deployments : rolling update, rollback, scaling
  • ✅ Utiliser ConfigMaps et Secrets comme variables d'environnement et volumes
  • ✅ Configurer les ressources (requests/limits) et comprendre leur impact
  • ✅ Contrôler le scheduling avec Taints, Tolerations et Node Affinity
  • ✅ Créer des DaemonSets, StatefulSets, Jobs et CronJobs
  • ✅ Configurer le HPA et les Probes

📋 Prérequis

  • Modules Kubernetes Débutant et Avancé complétés
  • Module CKA : Architecture lu

🚀 Deployments

Rolling update et rollback

bash
# Déployer
kubectl create deployment nginx --image=nginx:1.27 --replicas=3

# Mettre à jour l'image
kubectl set image deployment/nginx nginx=nginx:1.28

# Suivre le rollout
kubectl rollout status deployment/nginx

# Historique
kubectl rollout history deployment/nginx
kubectl rollout history deployment/nginx --revision=2

# Rollback vers la révision précédente
kubectl rollout undo deployment/nginx

# Rollback vers une révision spécifique
kubectl rollout undo deployment/nginx --to-revision=1

# Mettre en pause un rollout
kubectl rollout pause deployment/nginx
kubectl rollout resume deployment/nginx

Stratégie de mise à jour

yaml
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1          # pods supplémentaires autorisés pendant la MAJ
      maxUnavailable: 0    # pods indisponibles autorisés pendant la MAJ
  template:
    spec:
      containers:
        - name: nginx
          image: nginx:1.28

💡 maxUnavailable: 0 garantit qu'aucun pod n'est supprimé avant qu'un nouveau soit prêt. Idéal en production.

Générer le YAML rapidement

bash
kubectl create deployment nginx \
  --image=nginx:1.27 \
  --replicas=3 \
  --dry-run=client -o yaml > deployment.yaml

kubectl apply -f deployment.yaml

⚙️ ConfigMaps

Créer un ConfigMap

bash
# Depuis des valeurs littérales
kubectl create configmap app-config \
  --from-literal=APP_ENV=production \
  --from-literal=APP_PORT=8080

# Depuis un fichier
kubectl create configmap nginx-conf \
  --from-file=nginx.conf

# YAML
kubectl create configmap app-config \
  --from-literal=APP_ENV=production \
  --dry-run=client -o yaml > configmap.yaml

Utiliser un ConfigMap

yaml
# En tant que variables d'environnement (toutes les clés)
spec:
  containers:
    - name: app
      envFrom:
        - configMapRef:
            name: app-config

# En tant que variable individuelle
spec:
  containers:
    - name: app
      env:
        - name: MY_ENV
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: APP_ENV

# En tant que volume (fichiers montés)
spec:
  volumes:
    - name: config-vol
      configMap:
        name: nginx-conf
  containers:
    - name: nginx
      volumeMounts:
        - name: config-vol
          mountPath: /etc/nginx/conf.d

🔒 Secrets

Créer un Secret

bash
# Générique (opaque)
kubectl create secret generic db-creds \
  --from-literal=DB_USER=admin \
  --from-literal=DB_PASS=s3cur3

# TLS
kubectl create secret tls tls-secret \
  --cert=tls.crt \
  --key=tls.key

# Docker registry
kubectl create secret docker-registry regcred \
  --docker-server=registry.example.com \
  --docker-username=user \
  --docker-password=password
yaml
# YAML : les valeurs doivent être en base64
# echo -n "admin" | base64  →  YWRtaW4=
apiVersion: v1
kind: Secret
metadata:
  name: db-creds
type: Opaque
data:
  DB_USER: YWRtaW4=
  DB_PASS: czNjdXIz

Utiliser un Secret

yaml
# En tant que variables d'environnement
spec:
  containers:
    - name: app
      envFrom:
        - secretRef:
            name: db-creds

# Variable individuelle
spec:
  containers:
    - name: app
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-creds
              key: DB_PASS

# En tant que volume
spec:
  volumes:
    - name: secret-vol
      secret:
        secretName: db-creds
  containers:
    - name: app
      volumeMounts:
        - name: secret-vol
          mountPath: /etc/secrets
          readOnly: true

⚠️ Les Secrets sont encodés en base64, pas chiffrés. N'oublie pas d'activer l'encryption at rest en production (EncryptionConfiguration).


📐 Resource Requests et Limits

Pourquoi c'est important

  • Les requests sont utilisées par le scheduler pour placer le Pod sur un node avec assez de ressources.
  • Les limits empêchent un Pod de consommer plus que sa part.
yaml
spec:
  containers:
    - name: app
      resources:
        requests:
          memory: "128Mi"    # le scheduler réserve 128 Mo
          cpu: "250m"        # réserve 0.25 CPU
        limits:
          memory: "256Mi"    # tué (OOMKilled) si dépassé
          cpu: "500m"        # ralenti (throttled) si dépassé

Comportements à retenir

ScénarioCPUMémoire
Dépasse la limitThrottled (ralenti)OOMKilled (tué)
Dépasse la requestAutorisé si node disponibleAutorisé si node disponible
Pas de request défini= valeur de la limit= valeur de la limit
bash
# Voir l'utilisation actuelle
kubectl top pods -n <namespace>
kubectl top nodes

LimitRange (pour forcer des defaults dans un namespace)

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: limits
  namespace: default
spec:
  limits:
    - type: Container
      default:
        cpu: "500m"
        memory: "128Mi"
      defaultRequest:
        cpu: "250m"
        memory: "64Mi"

ResourceQuota (pour limiter un namespace entier)

yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  name: namespace-quota
  namespace: default
spec:
  hard:
    pods: "10"
    requests.cpu: "4"
    requests.memory: "4Gi"
    limits.cpu: "8"
    limits.memory: "8Gi"

🎯 Scheduling : Taints et Tolerations

Concept

  • Une Taint sur un node repousse les Pods.
  • Une Toleration sur un Pod lui permet de tolérer une Taint.
bash
# Ajouter une taint
kubectl taint nodes worker1 env=production:NoSchedule
kubectl taint nodes worker1 env=production:NoExecute   # expulse aussi les pods existants
kubectl taint nodes worker1 env=production:PreferNoSchedule

# Supprimer une taint (ajouter un "-" à la fin)
kubectl taint nodes worker1 env=production:NoSchedule-

# Voir les taints d'un node
kubectl describe node worker1 | grep -A5 Taints
yaml
# Toleration correspondante dans le Pod
spec:
  tolerations:
    - key: "env"
      operator: "Equal"
      value: "production"
      effect: "NoSchedule"

# Tolérer toutes les taints (utile pour les DaemonSets)
  tolerations:
    - operator: "Exists"

💡 Les DaemonSets de kube-system ont souvent des tolerations pour toutes les taints, ce qui leur permet de tourner sur tous les nodes y compris ceux qui sont "réservés".


📍 Node Affinity

Plus expressif que nodeSelector, Node Affinity permet des conditions complexes.

bash
# Labelliser un node
kubectl label nodes worker1 disktype=ssd
kubectl label nodes worker2 disktype=hdd
yaml
spec:
  affinity:
    nodeAffinity:
      # REQUIRED : le Pod ne sera placé que sur un node correspondant
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: disktype
                operator: In         # In, NotIn, Exists, DoesNotExist, Gt, Lt
                values:
                  - ssd
      # PREFERRED : préférence, mais pas obligatoire
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 1
          preference:
            matchExpressions:
              - key: zone
                operator: In
                values:
                  - eu-west-1a

Pod Affinity / Anti-Affinity

yaml
spec:
  affinity:
    # Co-localiser ce Pod avec des Pods ayant app=cache
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchLabels:
              app: cache
          topologyKey: kubernetes.io/hostname

    # Ne pas placer ce Pod sur un node qui a déjà app=web
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          podAffinityTerm:
            labelSelector:
              matchLabels:
                app: web
            topologyKey: kubernetes.io/hostname

🌐 DaemonSets

Un DaemonSet garantit qu'un Pod tourne sur chaque node (ou un sous-ensemble). Utilisé pour les agents de monitoring, les log collectors, les plugins réseau CNI.

yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      name: fluentd
  template:
    metadata:
      labels:
        name: fluentd
    spec:
      tolerations:
        - operator: Exists   # tolère toutes les taints pour tourner partout
      containers:
        - name: fluentd
          image: fluent/fluentd:v1.16
bash
kubectl get daemonset
kubectl describe daemonset fluentd

🗄️ StatefulSets

Pour les applications qui ont besoin :

  • D'une identité stable (nom de pod prévisible : mysql-0, mysql-1...)
  • D'un stockage persistant propre à chaque pod
  • D'un ordre de démarrage garanti
yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: "mysql"    # headless service requis
  replicas: 3
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: "password"
          volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:             # PVC créé automatiquement pour chaque pod
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 1Gi

⏱️ Jobs et CronJobs

Job

Un Job exécute un Pod jusqu'à complétion (ne redémarre pas une fois terminé avec succès).

bash
kubectl create job test-job --image=busybox -- echo "Hello CKA"
yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: calcul
spec:
  completions: 5          # nombre de fois où le job doit réussir
  parallelism: 2          # pods qui tournent en parallèle
  backoffLimit: 4         # tentatives max avant échec
  template:
    spec:
      restartPolicy: OnFailure   # Never ou OnFailure (pas Always !)
      containers:
        - name: calcul
          image: busybox
          command: ["sh", "-c", "echo Calcul en cours; sleep 5"]

CronJob

bash
kubectl create cronjob backup \
  --image=busybox \
  --schedule="0 2 * * *" \
  -- sh -c "echo Backup de minuit"
yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup
spec:
  schedule: "0 2 * * *"       # syntaxe cron standard
  concurrencyPolicy: Forbid    # Allow, Forbid, Replace
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: backup
              image: busybox
              command: ["sh", "-c", "echo Backup"]

📈 Horizontal Pod Autoscaler (HPA)

bash
# Créer un HPA (nécessite metrics-server installé)
kubectl autoscale deployment nginx \
  --cpu-percent=50 \
  --min=2 \
  --max=10

kubectl get hpa
kubectl describe hpa nginx
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50

❤️ Probes (sondes de santé)

Les 3 types de probes

ProbeRôleAction si échec
livenessProbe"Est-il encore en vie ?"Redémarre le conteneur
readinessProbe"Est-il prêt à recevoir du trafic ?"Retire le pod du Service
startupProbe"A-t-il fini de démarrer ?"Désactive liveness/readiness pendant le démarrage
yaml
spec:
  containers:
    - name: app
      # Probe HTTP
      livenessProbe:
        httpGet:
          path: /healthz
          port: 8080
        initialDelaySeconds: 10    # attendre avant le 1er check
        periodSeconds: 10          # fréquence des checks
        failureThreshold: 3        # échecs consécutifs avant action

      # Probe TCP
      readinessProbe:
        tcpSocket:
          port: 5432
        initialDelaySeconds: 5
        periodSeconds: 10

      # Probe commande
      startupProbe:
        exec:
          command:
            - cat
            - /tmp/healthy
        initialDelaySeconds: 0
        periodSeconds: 5
        failureThreshold: 30       # 30 x 5s = 150s pour démarrer

📊 Récapitulatif des commandes clés

bash
# Deployments
kubectl rollout status deployment/<name>
kubectl rollout history deployment/<name>
kubectl rollout undo deployment/<name>
kubectl scale deployment/<name> --replicas=5

# ConfigMaps et Secrets
kubectl create configmap <name> --from-literal=key=val
kubectl create secret generic <name> --from-literal=key=val

# Scheduling
kubectl taint nodes <node> <key>=<value>:<effect>
kubectl label nodes <node> <key>=<value>
kubectl describe node <node> | grep -E "Taints|Labels"

# HPA
kubectl autoscale deployment <name> --cpu-percent=50 --min=2 --max=10
kubectl get hpa

# Top
kubectl top pods --sort-by=cpu
kubectl top nodes

🚀 Prochaines Étapes

  • Domaine suivant : CKA : Services et Réseau
  • Entraîne-toi : crée un StatefulSet avec PVCs, simule une montée en charge et observe le HPA
  • Référence : kubernetes.io/docs/concepts/workloads/
Retour aux modules

Sur cette page

  • 🎯 Objectifs
  • 📋 Prérequis
  • 🚀 Deployments
  • Rolling update et rollback
  • Stratégie de mise à jour
  • Générer le YAML rapidement
  • ⚙️ ConfigMaps
  • Créer un ConfigMap
  • Utiliser un ConfigMap
  • 🔒 Secrets
  • Créer un Secret
  • Utiliser un Secret
  • 📐 Resource Requests et Limits
  • Pourquoi c'est important
  • Comportements à retenir
  • LimitRange (pour forcer des defaults dans un namespace)
  • ResourceQuota (pour limiter un namespace entier)
  • 🎯 Scheduling : Taints et Tolerations
  • Concept
  • 📍 Node Affinity
  • Pod Affinity / Anti-Affinity
  • 🌐 DaemonSets
  • 🗄️ StatefulSets
  • ⏱️ Jobs et CronJobs
  • Job
  • CronJob
  • 📈 Horizontal Pod Autoscaler (HPA)
  • ❤️ Probes (sondes de santé)
  • Les 3 types de probes
  • 📊 Récapitulatif des commandes clés
  • 🚀 Prochaines Étapes