Skip to content

Kubernetes — Documentation complète

Un conteneur, c'est simple. Cent conteneurs répartis sur plusieurs machines, qui doivent se parler, se relancer tout seuls quand ils tombent, monter en charge le vendredi soir et redescendre le lundi matin : là, il faut un chef d'orchestre. Kubernetes est ce chef d'orchestre — le standard de fait pour faire tourner des applications conteneurisées à l'échelle, sans supplier chaque nuit qu'aucune machine ne tombe.

Cette page rassemble l'essentiel en une documentation continue : des concepts de base jusqu'à l'administration avancée, chaque notion étant suivie d'une mise en pratique concrète. À parcourir de haut en bas pour apprendre, ou à picorer via le sommaire pour retrouver un exemple.


Présentation

Table des Matières

  1. Introduction à Kubernetes
  2. Concepts Clés
  3. Prérequis
  4. Installation
  5. Usage Basique

Introduction à Kubernetes

Pourquoi Kubernetes ?

Kubernetes est une plateforme open-source qui automatise : - Le déploiement d'applications conteneurisées - La mise à l'échelle (scaling) - La gestion des applications distribuées

Avantages principaux : - Haute disponibilité - Scalabilité automatique - Gestion simplifiée des applications complexes

Objectifs de cette documentation

  • Comprendre les concepts fondamentaux
  • Installer un cluster Kubernetes
  • Déployer et gérer des applications
  • Pratiquer avec des exercices concrets

Concepts Clés

Architecture du Cluster

  • Nœud Maître (Master) : Orchestre le cluster (API Server, Scheduler, Controller Manager)
  • Nœuds Travailleurs (Workers) : Exécutent les applications (kubelet, kube-proxy)

Composants Principaux

Composant Description
Pod Plus petite unité exécutable (1+ conteneurs)
Deployment Gère le cycle de vie des applications
Service Point d'accès réseau stable aux Pods
ConfigMap/Secret Gestion de configuration et données sensibles
Ingress Routeur HTTP pour accès externe
PersistentVolume Stockage persistant pour les données

Schéma Kubernetes


Prérequis

Configuration Matérielle

Rôle CPU RAM Stockage
Master 2 cœurs 2GB 20GB
Worker 1 cœur/Pod 1GB/Pod Variable

Configuration Logicielle

  • Runtime conteneur (Docker, containerd)
  • Kubernetes v1.25+
  • Swap désactivé (sudo swapoff -a)

Configuration Réseau

  • Ports ouverts : 6443 (API), 10250 (kubelet)
  • Connectivité entre tous les nœuds

Installation

Étapes d'Installation avec kubeadm

  1. Préparation du système :

    sudo apt update && sudo apt upgrade -y
    

  2. Installation des dépendances :

    sudo apt install -y apt-transport-https curl gnupg
    

  3. Ajout du dépôt Kubernetes :

    curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/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.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
    

  4. Installation des composants :

    sudo apt update
    sudo apt install -y kubelet kubeadm kubectl
    sudo apt-mark hold kubelet kubeadm kubectl
    

  5. Initialisation du cluster :

    sudo kubeadm init --pod-network-cidr=10.244.0.0/16
    

  6. Configuration du réseau :

    kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
    

  7. Ajout des workers :

    kubeadm join <MASTER_IP>:6443 --token <TOKEN> --discovery-token-ca-cert-hash sha256:<HASH>
    


Usage Basique

Commandes Essentielles

Commande Description
kubectl apply -f fichier.yaml Déploie une ressource
kubectl get pods Liste les Pods
kubectl describe pod <nom> Affiche les détails d'un Pod
kubectl logs <pod> Affiche les logs
kubectl exec -it <pod> -- bash Ouvre un shell dans un Pod

Exemple de Déploiement

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80

Bonnes Pratiques

  • Un conteneur par Pod en général
  • Utiliser des labels cohérents
  • Configurer des probes (liveness/readiness)
  • Gérer les secrets avec l'objet Secret

Mise en pratique — Pods et sondes

Créer un Pod avec une sonde de vie (livenessProbe)

Créer un Pod qui simule une application simple avec un fichier de "santé" (/tmp/healthy), surveillé par une sonde de vie (livenessProbe).
Cette sonde vérifiera si le fichier existe ; s’il est supprimé, Kubernetes redémarrera automatiquement le conteneur.

Contexte - Utiliser l’image busybox - Lancer le Pod dans un cluster Kubernetes déjà opérationnel (Minikube ou cluster distant) - Utiliser kubectl apply -f pod-liveness.yaml pour le déploiement

Ce que met en place le manifeste 1. Créer un fichier YAML nommé pod-liveness.yaml 2. Définir un Pod avec : - Un conteneur basé sur busybox - Une commande shell qui crée un fichier /tmp/healthy, le supprime après 30s, puis dort - Une livenessProbe qui vérifie ce fichier toutes les 5 secondes 3. Déployer le Pod avec kubectl apply -f pod-liveness.yaml 4. Observer le redémarrage automatique du Pod avec :

kubectl describe pod <nom>
kubectl get pod <nom> -w

Observer le comportement * Pour voir les événements et vérifier la sonde :

kubectl describe pod pod-liveness
  • Pour surveiller l’état du Pod en temps réel :
kubectl get pod pod-liveness -w

Manifeste :

apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness
  labels:
    app: pod-liveness
spec:
  restartPolicy: OnFailure
  containers:
  - name: app
    image: busybox
    args:
    - /bin/sh
    - -c
    - |
      touch /tmp/healthy
      sleep 30
      rm -rf /tmp/healthy
      sleep 600
    resources:
      requests:
        memory: "32Mi"
        cpu: "128m"
      limits:
        memory: "64Mi"
        cpu: "256m"
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

Init Container +

Volume partagé

Comprendre le fonctionnement des initContainers et le partage de volume entre initContainer et conteneur principal.

Contexte * Init container : prépare les données (copie de fichiers) dans un volume partagé emptyDir * Conteneur principal : utilise ces fichiers pour démarrer l’application

Ce que met en place le manifeste 1. Créer un Pod avec :

  • Un initContainer qui crée un fichier dans /mnt
  • Un volume emptyDir partagé avec le conteneur principal
  • Déployer et vérifie que le conteneur principal peut lire ce fichier

Observer le comportement * Pour voir les logs de l’init container :

kubectl logs <nom-pod> -c <nom-init-container>
  • Pour décrire le pod et vérifier les volumes montés :
kubectl describe pod <nom-pod>

Manifeste :

apiVersion: v1
kind: Pod
metadata:
  name: pod-init-demo
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  initContainers:
  - name: init-container
    image: busybox
    command:
    - /bin/sh
    - -c
    - echo "Hello from init container" > /mnt/message.txt
    volumeMounts:
    - name: shared-data
      mountPath: /mnt
  containers:
  - name: main-container
    image: busybox
    command:
    - /bin/sh
    - -c
    - cat /mnt/message.txt && sleep 3600
    volumeMounts:
    - name: shared-data
      mountPath: /mnt

Déploiements et Scaling

Table des Matières

  1. Déploiements (Deployments)
  2. Définition et Structure
  3. Cas d'Usage
  4. Scaling des Applications
  5. ReplicaSets
  6. Horizontal Pod Autoscaling (HPA)
  7. Stratégies de Déploiement
  8. Rolling Update
  9. Canary
  10. Blue-Green
  11. Commandes Utiles

Déploiements

Définition et Structure

Un Deployment Kubernetes permet de gérer des Pods et ReplicaSets en déclarant un état désiré. Kubernetes maintient automatiquement cet état.

Exemple de Deployment :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.23.3

Points clés : - Les labels (metadata, selector, template) doivent être cohérents - replicas définit le nombre de pods souhaités - template décrit les pods à créer

Cas d'Usage

  • Mise à l'échelle : Augmenter/diminuer le nombre de pods
  • Historique : Gestion des versions et rollback
  • Mises à jour : Déploiement sans interruption
  • Auto-réparation : Redémarrage automatique des pods défaillants

Scaling

ReplicaSets

Un ReplicaSet maintient un nombre stable de pods identiques.

Exemple :

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google_samples/gb-frontend:v3

Préférer les Deployments qui offrent plus de fonctionnalités

Horizontal Pod Autoscaling

L'HPA ajuste automatiquement le nombre de pods basé sur l'utilisation des ressources.

Exemple HPA :

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: frontend-scaler
spec:
  scaleTargetRef:
    kind: ReplicaSet
    name: frontend
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

Prérequis : - Serveur de métriques installé (Metrics Server) - Demandes de ressources définies dans les pods


Stratégies de Déploiement

Rolling Update (par défaut)

Mise à jour progressive pod par pod pour éviter les interruptions.

Commande :

kubectl set image deployment/nginx-deployment nginx=nginx:1.23.3

Canary

Déploie la nouvelle version sur un sous-ensemble de pods (ex: 20%) pour tester avant déploiement complet.

Blue-Green

  • Deux environnements complets (blue = actuel, green = nouveau)
  • Basculement instantané du trafic une fois la nouvelle version validée

Commandes Utiles

Commande Description
kubectl apply -f deployment.yml Créer/mettre à jour un déploiement
kubectl set image deployment/<name> <container>=<image> Mettre à jour l'image d'un conteneur
kubectl scale deployment/<name> --replicas=<n> Modifier le nombre de réplicas
kubectl rollout status deployment/<name> Suivre l'état du déploiement
kubectl rollout history deployment/<name> Voir l'historique des versions
kubectl rollout undo deployment/<name> --to-revision=<n> Revenir à une version antérieure
kubectl rollout restart deployment/<name> Redémarrer tous les pods

Bonnes Pratiques : - Toujours utiliser des Deployments plutôt que des ReplicaSets directement - Définir des probes (liveness/readiness) pour une meilleure gestion des pods - Utiliser des stratégies de déploiement adaptées à votre application


Mise en pratique — Déploiements et scaling

Créer un Deployment (replicas, labels, image)

Un Deployment avec :

  • 2 replicas
  • label app: nginx-deploy
  • image nginx:1.26.1
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deploy
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deploy
  template:
    metadata:
      labels:
        app: nginx-deploy
    spec:
      containers:
      - name: nginx
        image: nginx:1.26.1

Mettre à jour l’image nginx en version 1.27.0 :

Manifeste :

kubectl set image deployment/nginx-deploy nginx=nginx:1.27.0

Augmenter le nombre de replicas à 3 :

Manifeste :

kubectl scale deployment/nginx-deploy --replicas=3

Suivre le déploiement :

Manifeste :

kubectl rollout status deployment/nginx-deploy

Voir l’historique des déploiements et revenir à la première version (replicas 2) :

Manifeste :

kubectl rollout history deployment/nginx-deploy

kubectl rollout undo deployment/nginx-deploy --to-revision=1


Services et connectivité

Table des Matières

  1. Introduction aux Services
  2. Résolution DNS dans Kubernetes
  3. Types de Services
  4. ClusterIP
  5. NodePort
  6. LoadBalancer
  7. ExternalName
  8. Services Avancés
  9. Services sans Selector
  10. Ingress
  11. Outils de Débogage
  12. Architecture Globale

Introduction aux Services

Les Services dans Kubernetes fournissent une abstraction pour exposer une application exécutée sur un ensemble de Pods en tant que service réseau. Ils offrent :

  • Stabilité : Une IP et un nom DNS persistants même lorsque les Pods changent
  • Découverte de service : Mécanisme intégré pour localiser les services
  • Équilibrage de charge : Répartition du trafic entre les Pods sains

Résolution DNS dans Kubernetes

Kubernetes déploie automatiquement un service DNS (CoreDNS) qui permet la résolution des noms de services :

  • Même namespace : <service-name>
  • Autre namespace : <service-name>.<namespace-name>
  • FQDN complet : <service-name>.<namespace-name>.svc.cluster.local

Exemple pour un service db dans le namespace production : - Dans le même namespace : db - Depuis un autre namespace : db.production


Types de Services

ClusterIP

Type par défaut - accessible uniquement depuis l'intérieur du cluster.

apiVersion: v1
kind: Service
metadata:
  name: internal-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

NodePort

Expose le service sur un port statique de chaque nœud (plage 30000-32767 par défaut).

apiVersion: v1
kind: Service
metadata:
  name: nodeport-service
spec:
  type: NodePort
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 31000

LoadBalancer

Crée un équilibreur de charge externe (cloud providers).

apiVersion: v1
kind: Service
metadata:
  name: loadbalancer-service
spec:
  type: LoadBalancer
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080

ExternalName

Mappe un service à un nom DNS externe.

apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ExternalName
  externalName: my.database.example.com

Services Avancés

Services sans Selector

Pour pointer vers des endpoints externes au cluster :

Service :

apiVersion: v1
kind: Service
metadata:
  name: external-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

Endpoints :

apiVersion: v1
kind: Endpoints
metadata:
  name: external-service
subsets:
  - addresses:
      - ip: 192.0.2.42
    ports:
      - port: 9376

Ingress

Gère l'accès HTTP/HTTPS aux services :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

Outils de Débogage

Port Forwarding (accès direct à un Pod) :

kubectl port-forward pod/mon-pod 8080:8080

Vérification des Endpoints :

kubectl get endpoints <service-name>

Test DNS :

kubectl run -it --rm --image=busybox:1.28 dns-test -- nslookup <service-name>


Architecture Globale

      +---------------------+
      |     Cluster DNS     |
      +----------+----------+
                 |
      +----------v----------+
      |    Service IP      |
      +----------+----------+
                 |
+-----------+----------+--------------+
| ClusterIP | NodePort | LoadBalancer |
+-----------+----------+--------------+
                 |
      +----------v----------+
      |     Endpoints      |
      +----------+----------+
                 |
      +----------v----------+
      |       Pods         |
      +---------------------+

Mise en pratique — Services

Exposer un Pod avec un Service (ClusterIP)

Un Pod qui utilise l'image nginx:latest avec le port 80 en écoute.

Créer ensuite un service qui écouté sur le port 7354 à l'intérieur du cluster.

Lancez un pod curl pour valider le bon fonctionnement

kubectl run curlpod --image=curlimages/curl -i --tty --rm -- sh

Puis executez la commande suivante sur le pod.

curl <adresse-dns>:<port>

Manifeste :

apiVersion: v1
kind: Pod
metadata:
  name: pod-nginx
  labels:
    app: webapp
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: webapp
  ports:
  - protocol: TCP
    port: 7354       # Port sur lequel le Service écoute
    targetPort: 80   # Port sur le Pod cible
  type: ClusterIP

curl nginx-service:7354

VOIR SI L'INGRESS PEUT MARCHER

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: example-service
            port:
              number: 80

Gestion des Volumes et Stockage Persistant

Table des Matières

  1. Les Volumes
  2. emptyDir
  3. hostPath
  4. Persistent Volumes et Persistent Volume Claims
  5. Stateful vs Stateless Applications
  6. StatefulSets
  7. StorageClass

Les Volumes

Quoi ?

Les fichiers dans un conteneur sont éphémères par défaut, ce qui pose deux problèmes principaux : - Perte de données lors du redémarrage d'un conteneur. - Partage de fichiers nécessaire entre plusieurs conteneurs dans un Pod.

Les volumes Kubernetes résolvent ces problèmes. Deux types courants sont emptyDir et hostPath.


emptyDir

Un volume emptyDir est initialement vide et partagé entre les conteneurs d'un Pod.

Exemple

apiVersion: v1
kind: Pod
metadata:
  name: production
spec:
  containers:
  - name: container1
    image: image1
    volumeMounts:
    - name: storage
      mountPath: /vol/data
  - name: container2
    image: image2
    volumeMounts:
    - name: storage
      mountPath: /store/data
  volumes:
  - name: storage
    emptyDir: {}
- Description :
- Un volume emptyDir nommé storage est monté dans /vol/data pour container1 et /store/data pour container2.


hostPath

Un volume hostPath monte un fichier/dossier du système hôte dans un Pod.

Options
  • DirectoryOrCreate : Crée un dossier si inexistant (permissions : 0755).
  • FileOrCreate : Crée un fichier si inexistant (permissions : 0644).
  • Autres options : Directory, File, Socket, CharDevice, BlockDevice.
Exemple

apiVersion: v1
kind: Pod
metadata:
  name: test-webserver
spec:
  containers:
  - name: test-webserver
    image: nginx
    volumeMounts:
    - mountPath: /var/local/aaa
      name: mydir
    - mountPath: /var/local/aaa/1.txt
      name: myfile
  volumes:
  - name: mydir
    hostPath:
      path: /var/local/aaa
      type: DirectoryOrCreate
  - name: myfile
    hostPath:
      path: /var/local/aaa/1.txt
      type: FileOrCreate
- Description :
- Monte un dossier (/var/local/aaa) et un fichier (1.txt) depuis l'hôte.


Persistent Volumes et Persistent Volume Claims

Quoi ?

Les PersistentVolumes (PV) et PersistentVolumeClaims (PVC) permettent d'utiliser un stockage externe au cluster.

  • PV : Ressource de stockage physique/logique (ex : NFS, EBS).
  • PVC : Demande de stockage par un utilisateur (taille, mode d'accès).
Modes d'accès
  • ReadWriteOnce (RWO) : Montage en lecture/écriture par un seul nœud.
  • ReadOnlyMany (ROX) : Montage en lecture seule par plusieurs nœuds.
  • ReadWriteMany (RWX) : Montage en lecture/écriture par plusieurs nœuds.
Exemple

# PersistentVolume
kind: PersistentVolume
apiVersion: v1
metadata:
  name: access-log-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /var/log/syslog
    type: DirectoryOrCreate

# PersistentVolumeClaim
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: access-log-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 500Mi

# Pod utilisant le PVC
kind: Pod
apiVersion: v1
metadata:
  name: test
spec:
  volumes:
    - name: access-log-pvc-vol
      persistentVolumeClaim:
        claimName: access-log-pvc
  containers:
    - name: proxy
      image: nginx
      volumeMounts:
        - mountPath: "/nginx/"
          name: access-log-pvc-vol
- Description :
- Un PV de 1 Go est créé, puis un PVC de 500 Mo. Le Pod monte le PVC dans /nginx/.


Stateful vs stateless applications

Stateless

  • Pas de persistance : Chaque requête est indépendante.
  • Exemples : Services REST, proxies.

Stateful

  • Persistance des données : Bases de données, caches.
  • Géré via StatefulSets.
StatefulSets

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 3
  template:
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: storage
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: storage
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 1Gi
- Description :
- Créer 3 pods avec un PVC par pod (volumeClaimTemplates). - Résolution DNS : web-0.nginx, web-1.nginx, etc.


StorageClass

Quoi ?

Une StorageClass définit des classes de stockage pour un provisionnement dynamique.

Exemple (vSphere)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: vsphere-ssd
provisioner: kubernetes.io/vsphere-volume
parameters:
  diskformat: thin
  datastore: "MyDatastore1"
  type: ssd
Exemple (AWS EBS)

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: aws-ebs
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
  zone: eu-west-3
- Description :
- Définit une classe de stockage SSD sur AWS (gp2) dans la zone eu-west-3.


Résumé

  • Volumes : emptyDir (éphémère), hostPath (hôte).
  • PV/PVC : Stockage persistant externe.
  • StatefulSets : Pour applications avec état.
  • StorageClass : Provisionnement dynamique de stockage.

Mise en pratique — Stockage

Partager un volume entre conteneurs (emptyDir)

Un manifeste contenant deux pods avec une image busybox.

Ajoutez la commande command: ["sh", "-c", "while true; do echo container2; sleep 3600; done"]

Créez un volume vide nommé storage, sur le container1 il est monté dans /vol/data et sur le container2 il est monté dans /store/data

Manifeste :

apiVersion: v1
kind: Pod
metadata:
  name: pod-shared-volume
spec:
  containers:
  - name: container1
    image: busybox
    command: ["sh", "-c", "while true; do echo container1; sleep 3600; done"]
    volumeMounts:
    - name: storage
      mountPath: /vol/data
  - name: container2
    image: busybox
    command: ["sh", "-c", "while true; do echo container2; sleep 3600; done"]
    volumeMounts:
    - name: storage
      mountPath: /store/data
  volumes:
  - name: storage
    emptyDir: {}

Utiliser plusieurs volumes dans un Pod

Un pod qui utilise deux volumes :

  • un pour créer un fichier (nommé myfile)
  • un pour créer un dossier (nommé mydir).

Le dossier sera créer dans /var/local/folder et le fichier dans /var/local/folder/1.txt.

Vérifiez la présence du fichier et du dossier.

Manifeste :

apiVersion: v1
kind: Pod
metadata:
  name: pod-two-volumes
spec:
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "while true; do echo container2; sleep 3600; done"]
    volumeMounts:
    - mountPath: /var/local/folder
      name: mydir
    - mountPath: /var/local/folder/1.txt
      name: myfile
  volumes:
  - name: mydir
    hostPath:
      path: /var/local/folder
      type: DirectoryOrCreate
  - name: myfile
    hostPath:
      path: /var/local/folder/1.txt
      type: FileOrCreate
kubectl exec -it pod-two-volumes -c app -- sh

exercice bonus

Créez un PV de 1Go qui a pour path /mnt/data, il doit être monté en lecture et écriture par un seul noeud à la fois.

Créer un PVC qui utilise un 1Go du PV, il doit être monté en lecture et écriture par un seul noeud à la fois.

Créer un statefulset avec son service.

Le port exposé dans le service sera le port: 27017

Le conteneur doit utiliser l'image mongo:4.4, il aura 2 replicas. Le PVC sur le chemin /data/db et il doit utiliser tout le stockage défini au dessus.

Manifeste :

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mongo-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mongo-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: storage
          mountPath: /usr/share/nginx/html
      volumes:
      - name: storage
        persistentVolumeClaim:
          claimName: mongo-pvc

RBAC et Service Accounts

Table des Matières

  1. RBAC (Role-Based Access Control)
  2. Rôles et ClusterRoles
  3. RoleBindings et ClusterRoleBindings
  4. Service Accounts
  5. Création et Utilisation
  6. Comportement par Défaut

RBAC (Role-Based Access Control)

Quoi ?

Le RBAC (Contrôle d'Accès Basé sur les Rôles) permet de gérer finement les permissions des utilisateurs et des Service Accounts sur un cluster Kubernetes. Il permet par exemple d'autoriser la lecture des logs d'un Pod tout en interdisant sa modification.


Rôles et ClusterRoles

Role (Namespace-scopé)

Définit des permissions limitées à un namespace.

Commande :

kubectl create role pod-lecture --verb=get,list,watch --resource=pods,pods/logs

Manifeste YAML :

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-lecture
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "watch", "list"]

ClusterRole (Cluster-scopé)

Définit des permissions sur tout le cluster.

Commande :

kubectl create clusterrole pod-lecture --verb=watch,list,get --resource=pods,pods/log

Manifeste YAML :

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pod-lecture
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "watch", "list"]


RoleBindings et ClusterRoleBindings

RoleBinding

Lie un Role à un utilisateur/Service Account dans un namespace.

Commande :

kubectl create rolebinding pod-lecture --user=dev --role=pod-lecture

Manifeste YAML :

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: default
  name: pod-lecture
subjects:
- kind: User
  name: dev
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-lecture
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding

Lie un ClusterRole à un utilisateur/Service Account pour tout le cluster.

Commande :

kubectl create clusterrolebinding pod-lecture --user=dev --clusterrole=pod-lecture

Manifeste YAML :

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pod-lecture
subjects:
- kind: User
  name: dev
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-lecture
  apiGroup: rbac.authorization.k8s.io


Service Accounts

Quoi ?

Un Service Account est un compte utilisé par les conteneurs pour interagir avec l'API Kubernetes. Il est associé à des permissions via RBAC (RoleBinding/ClusterRoleBinding).


Création et Utilisation

Commande :

kubectl create serviceaccount mon-serviceaccount

Manifeste YAML :

apiVersion: v1
kind: ServiceAccount
metadata:
  name: mon-serviceaccount

Exemple de RoleBinding pour un Service Account :

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: default
  name: pod-lecture
subjects:
- kind: ServiceAccount
  name: mon-serviceaccount
  namespace: default
roleRef:
  kind: Role
  name: pod-lecture
  apiGroup: rbac.authorization.k8s.io


Comportement par Défaut

  • Par défaut, un Pod utilise le Service Account default.
  • Un token d'accès est automatiquement monté dans :
    /var/run/secrets/kubernetes.io/serviceaccount/token
    
  • Désactiver cette fonctionnalité :
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: build-robot
    automountServiceAccountToken: false  # Désactive le montage automatique
    
    Ou directement sur un Pod :
    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
    spec:
      serviceAccountName: build-robot
      automountServiceAccountToken: false  # Désactive pour ce Pod
    

Récapitulatif

Objet RBAC Portée Lien avec
Role Namespace Utilisateurs/Service Accounts (via RoleBinding)
ClusterRole Cluster Utilisateurs/Service Accounts (via ClusterRoleBinding)
ServiceAccount Pods Permissions via RBAC

Mise en pratique — RBAC

Créer un ServiceAccount et un Role (lecture des pods)

Un ServiceAccount associé à un Role qui lui permet de faire les 3 actions de lectures des pods, unqiuement de son namespace.

Mappez ce Service account sur un pod basique.

Manifeste :

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader-sa
---

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
subjects:
- kind: ServiceAccount
  name: pod-reader-sa
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io
---

apiVersion: v1
kind: Pod
metadata:
  name: pod-sa-demo
spec:
  serviceAccountName: pod-reader-sa
  containers:
  - name: app
    image: busybox
    command: ["sh", "-c", "sleep 3600"]


Helm et métriques

Table des Matières

  1. Helm - Gestionnaire de paquets Kubernetes
  2. Concepts Clés
  3. Architecture Helm
  4. Utilisation Basique
  5. Métriques dans Kubernetes
  6. Metrics Server
  7. Prometheus et ServiceMonitor

Helm - Gestionnaire de paquets Kubernetes

Concepts Clés

Helm est le gestionnaire de paquets standard pour Kubernetes qui simplifie : - Le déploiement d'applications - La gestion des versions - La configuration des applications

Terminologie Helm
Terme Description
Chart Package Helm contenant les ressources Kubernetes
Release Instance déployée d'un Chart
Repository Dépôt de Charts Helm
Values Paramètres de configuration personnalisables

Architecture Helm

Architecture Helm

Composants : - Client Helm : Interface en ligne de commande - Tiller (déprécié depuis Helm 3) : Composant serveur - Charts : Modèles YAML paramétrables - Releases : Versions déployées

Workflow : 1. Recherche de Charts (helm search) 2. Installation (helm install) 3. Mise à jour (helm upgrade) 4. Gestion des versions (helm rollback)

Utilisation Basique

Installation de Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Commandes Essentielles
Commande Description
helm repo add Ajouter un dépôt
helm search repo Rechercher des Charts
helm install Déployer une application
helm upgrade Mettre à jour une release
helm uninstall Supprimer une release
helm list Lister les releases
Exemple de Déploiement
# Ajout du dépôt stable
helm repo add stable https://charts.helm.sh/stable

# Installation de Nginx
helm install my-nginx stable/nginx-ingress

# Personnalisation avec values.yaml
helm install -f values.yaml my-app stable/mychart

Métriques dans Kubernetes

Metrics Server

Fonctionnalités : - Collecte des métriques CPU/RAM des nodes et pods - Nécessaire pour kubectl top et le HPA (Horizontal Pod Autoscaler)

Installation
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
Configuration pour Kubernetes 1.25+
# Ajouter dans le container args
- --kubelet-insecure-tls=true
Utilisation
# Voir l'utilisation des ressources
kubectl top nodes
kubectl top pods

Prometheus et ServiceMonitor

Stack de Monitoring : - Prometheus : Collecte et stocke les métriques - Grafana : Visualisation des données - ServiceMonitor : Définit les cibles de surveillance

Exemple de ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: myapp-monitor
spec:
  selector:
    matchLabels:
      app: myapp
  endpoints:
  - port: web
    interval: 30s
    path: /metrics

Fonctionnement : 1. Les applications exposent des métriques sur /metrics 2. ServiceMonitor définit quoi surveiller 3. Prometheus collecte périodiquement les données 4. Alertes et visualisation via Grafana

Déploiement avec Helm
# Ajout du dépôt Prometheus-Community
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

# Installation de Prometheus
helm install prometheus prometheus-community/prometheus

Bonnes Pratiques

Pour Helm : - Utiliser des valeurs par défaut bien documentées - Versionner les Charts avec sémantique (SemVer) - Tester les Charts avec helm template avant déploiement

Pour les Métriques : - Configurer des probes (liveness/readiness) - Surveiller les limites de ressources - Utiliser des dashboards Grafana pour la visualisation

Documentation Officielle Helm Documentation Prometheus Operator


Mise en pratique — Helm

Créer un chart Helm (serveur Nginx)

Un chart Helm simple pour déployer un serveur Nginx sur Kubernetes.

  • Un fichier Chart.yaml pour définir le chart.
  • Un fichier values.yaml pour définir les valeurs par défaut.
  • Un template de déploiement (deployment.yaml).
  • Un template de service (service.yaml).

Manifeste :

Créez un répertoire pour votre chart appelé my-nginx-chart. Dans ce répertoire, créez un sous-dossier templates.

Dans le répertoire my-nginx-chart, créez un fichier Chart.yaml.

apiVersion: v2
name: my-nginx-chart
description: A simple Helm chart for Nginx
version: 0.1.0

Dans le répertoire my-nginx-chart créez le fichier values.yaml.

replicaCount: 1

image:
  repository: nginx
  tag: "latest"

service:
  type: ClusterIP
  port: 80

Dans le sous-dossier templates créez les fichiers deployment.yaml et service.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        ports:
        - containerPort: 80
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: {{ .Values.service.type }}
  ports:
  - port: {{ .Values.service.port }}
    targetPort: 80
  selector:
    app: nginx

Créez ces deux fichiers de façon à ce qu'ils utilisent les values du fichier values.yaml.

Pour lancer la création du chart utilisez la commande suivante:

helm install my-nginx ./my-nginx-chart

Vérifiez que le déploiement et le service sont bien créés :

kubectl get pods
kubectl get svc

Supprimez la release une fois que vous avez terminé :

helm uninstall my-nginx


Administration Avancée

Table des Matières

  1. Gestion des Utilisateurs
  2. Installation de Cluster
  3. Architectures HA et Non-HA
  4. Procédure d'Installation
  5. Maintenance des Nœuds
  6. Mises à Jour de Cluster
  7. Gestion d'ETCD
  8. Récupération d'un Membre Corrompu
  9. Sauvegarde et Restauration

Gestion des Utilisateurs

Création d'un Utilisateur avec Certificat

  1. Génération du CSR :

    openssl req -new -newkey rsa:4096 -nodes -keyout user.key -out user.csr -subj "/CN=username/O=group"
    

  2. Création de la CSR Kubernetes :

    apiVersion: certificates.k8s.io/v1
    kind: CertificateSigningRequest
    metadata:
      name: user-access
    spec:
      request: $(cat user.csr | base64 | tr -d '\n')
      signerName: kubernetes.io/kube-apiserver-client
      expirationSeconds: 86400
      usages:
      - client auth
    

  3. Approbation et Récupération du Certificat :

    kubectl certificate approve user-access
    kubectl get csr user-access -o jsonpath='{.status.certificate}' | base64 -d > user.crt
    

  4. Configuration RBAC :

    kubectl create role dev --verb=create,list,update,delete --resource=pods
    kubectl create rolebinding dev-binding --role=dev --user=username
    

  5. Création du Kubeconfig :

    kubectl config set-credentials username --client-key=user.key --client-certificate=user.crt --embed-certs=true
    kubectl config set-context username --cluster=cluster-name --user=username
    


Installation de Cluster

Architectures HA et Non-HA

  • Non-HA : Single control plane
  • HA : Multiple control planes avec load balancer (VIP)

Procédure d'Installation

  1. Prérequis Communs :

    swapoff -a
    apt-get update && apt-get install -y containerd kubelet kubeadm kubectl
    

  2. Initialisation du Control Plane :

    kubeadm init --control-plane-endpoint "VIP:6443" --upload-certs
    

  3. Configuration du Réseau :

    kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
    

  4. Joindre les Workers :

    kubeadm join VIP:6443 --token <token> --discovery-token-ca-cert-hash <hash>
    


Maintenance des Nœuds

Drain d'un Nœud

kubectl drain <node> --ignore-daemonsets --delete-emptydir-data

Réintégration

kubectl uncordon <node>

Mises à Jour de Cluster

Processus de Mise à Jour

  1. Mise à Jour de kubeadm :

    apt-get update && apt-get install -y kubeadm=1.26.0-00
    

  2. Planification et Application :

    kubeadm upgrade plan
    kubeadm upgrade apply v1.26.0
    

  3. Mise à Jour des Composants :

    apt-get install -y kubelet=1.26.0-00 kubectl=1.26.0-00
    systemctl daemon-reload
    systemctl restart kubelet
    


Gestion d'ETCD

Récupération d'un membre corrompu

  1. Sauvegarde :

    ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 snapshot save snapshot.db
    

  2. Réinitialisation :

    mv /etc/kubernetes/manifests/etcd.yaml /tmp
    rm -rf /var/lib/etcd/member
    

  3. Réintégration :

    kubeadm join phase control-plane-join etcd
    

Sauvegarde et Restauration

  • Sauvegarde Régulière :

    etcdctl snapshot save /backup/etcd-snapshot-$(date +%F).db
    

  • Restauration :

    etcdctl snapshot restore /backup/etcd-snapshot.db --data-dir /var/lib/etcd-new
    chown -R etcd:etcd /var/lib/etcd-new
    


Bonnes Pratiques

  • Sécurité : Rotation régulière des certificats
  • Sauvegarde : Planification de sauvegardes ETCD quotidiennes
  • Monitoring : Surveillance des ressources et des nœuds
  • Documentation : Maintien d'un journal des changements

Documentation Officielle Kubernetes
Guide de Sauvegarde ETCD


Conclusion

1. Concepts fondamentaux

  • Pods : unité de déploiement de base, éphémère, peut contenir plusieurs conteneurs partageant réseau et volumes.
  • Deployments & ReplicaSets : permettent de garantir le nombre voulu de Pods, avec des mises à jour automatisées (rolling updates) et gestion du scaling.
  • Services : abstractions réseau exposant les Pods (ClusterIP, NodePort, LoadBalancer, ExternalName) avec résolution DNS interne.
  • Ingress : gestion du trafic HTTP(s) entrant vers les Services internes, via règles basées sur les hôtes/chemins.
  • Volumes et Persistance : emptyDir, hostPath, PV/PVC, StatefulSets et StorageClass pour gérer le stockage durable des données.

2. Sécurité et contrôle d'accès

  • ConfigMaps et Secrets : injection de configuration et de données sensibles dans les conteneurs (via variables ou volumes).
  • RBAC : définition de permissions granulaires via Role/ClusterRole et bindings, et utilisation des Service Accounts pour contrôler l’accès des pods à l’API.

3. Architecture du cluster

  • Nœuds Master (Control Plane) : kube-apiserver, etcd, kube-scheduler, kube-controller-manager, cloud-controller-manager.
  • Nœuds Worker : kubelet, runtime (Docker/containerd...), kube-proxy.
  • Communication via API, surveillance des états désirés, orchestration automatique.

4. Opérations avancées

  • Init Containers et probes (liveness, readiness, startup) pour assurer la préparation, la validation et la fiabilité des conteneurs.
  • Requests/Limits CPU et mémoire pour distribuer la charge et prévenir les interruptions.
  • Exercices pratiques (TP) : déploiement de pods, probes, configMaps, secrets, services, Ingress, scaling, mises à jour (deployments, canary, blue/green), port-forwarding.

5. Outils complémentaires

  • Helm : packaging, versioning et déploiement avec charts et valeurs.
  • Métriques : Metrics Server pour kubectl top et HPA ; Prometheus + ServiceMonitor pour monitoring avancé.
  • Administration avancée : gestion des utilisateurs et certificats, HA avec VIPs, maintenance des nœuds, mises à jour de version, sauvegarde/restauration d’ETCD.

Bonnes pratiques & points de vigilance

  • Toujours utiliser un approche déclarative YAML + versionnée, plutôt que des commandes imperatives isolées.
  • Définir de façon appropriée les requests et limits pour garantir stabilité et performances.
  • Utiliser des probes pour maintenir la résilience des applications.
  • Préférer les Deployments aux ReplicaSets pour bénéficier du rollbacks, des stratégies mises à jour, de la scalabilité.
  • Pour exposer un service externe, choisir le bon type : NodePort, LoadBalancer ou Ingress selon vos besoins.
  • Ne jamais stocker de données critiques dans des pods statiques : toujours les utiliser avec PV/PVC, StorageClass et StatefulSets si l’application est persistante.
  • Sécuriser l’accès avec RBAC, Service Accounts, et limiter l’accès aux tokens.
  • Sauvegarder régulièrement ETCD, planifier des mises à jour du cluster et les certificats.

Objectifs à garder en tête

  1. Modularité : chaque application doit être décomposée en composants conteneurisables (pods), orchestrés via deployments.
  2. Résilience : automatiser le redémarrage, l’exposition réseau et le scaling.
  3. Sécurité : configurer l’accès, la persistance, et la confidentialité via RBAC, Secrets et stockage durable.
  4. Observabilité & Opérations : utiliser Helm, monitoring, métriques pour gérer et faire évoluer votre infrastructure.
  5. Évolutivité : anticiper la montée en charge via HPA, architecture HA, et procédures de maintenance/déploiement robustes.

En résumé

Vous disposez désormais de :

  • Une base solide pour comprendre le fonctionnement de Kubernetes (pods, services, volumes, sécurité).
  • Des outils et bonnes pratiques pour déployer, faire évoluer et sécuriser vos clusters et applications.
  • Des exercices concrets pour renforcer la compréhension et vérifier l’appropriation des concepts.
  • Une vision complète vous permettant de passer facilement de la phase d’apprentissage à la production.