Concepts clés
Architecture d'un cluster Kubernetes
Théorie

Un cluster Kubernetes est composé d'un Control Plane (cerveau du cluster) et de Nodes (machines qui exécutent les workloads). Tout communique via l'API Server.

ComposantRôle
kube-apiserverPoint d'entrée unique du cluster. Expose l'API REST Kubernetes. Toutes les interactions (kubectl, dashboards) passent par lui.
etcdBase de données clé-valeur distribuée. Stocke l'état complet du cluster (source de vérité).
kube-schedulerSélectionne le Node sur lequel chaque Pod sera exécuté en fonction des ressources disponibles et des contraintes.
kube-controller-managerBoucle de contrôle qui s'assure que l'état réel du cluster correspond à l'état désiré (ex: relancer un Pod crashé).
kubeletAgent qui tourne sur chaque Node. Il reçoit les instructions du Control Plane et gère les Pods localement.
kube-proxyGère les règles réseau sur chaque Node pour router le trafic vers les bons Pods.
Container RuntimeMoteur de conteneurs utilisé par kubelet (Docker, containerd, CRI-O).
Les objets Kubernetes essentiels
Ressources

Kubernetes gère des objets déclarés en YAML. Chaque objet a un apiVersion, un kind, des metadata et un spec.

ObjetDescription
PodUnité de base : un ou plusieurs conteneurs partageant réseau et stockage. Éphémère par nature.
DeploymentGère le cycle de vie d'un ensemble de Pods identiques (réplicas, rolling update, rollback).
ReplicaSetGarantit qu'un nombre précis de Pods tourne en permanence. Géré automatiquement par un Deployment.
ServiceExpose un ensemble de Pods via une IP stable et un DNS interne. Assure la découverte de services.
IngressRègles HTTP/HTTPS pour router le trafic externe vers les bons Services (reverse proxy L7).
ConfigMapStocke des données de configuration non sensibles (clé-valeur ou fichiers).
SecretStocke des données sensibles (mots de passe, tokens) encodées en base64.
PersistentVolumeRessource de stockage provisionné dans le cluster (indépendant des Pods).
PersistentVolumeClaimDemande de stockage faite par un Pod. Lié à un PersistentVolume.
NamespacePartition virtuelle du cluster pour isoler des ressources (par équipe, env, app).
StatefulSetComme un Deployment mais pour les apps avec état (BDD) : identité stable, stockage persistant par Pod.
DaemonSetGarantit qu'un Pod tourne sur chaque Node (ex: agent de logs, monitoring).
Job / CronJobExécution de tâches ponctuelles ou planifiées (migration BDD, rapports).
HorizontalPodAutoscalerAjuste automatiquement le nombre de réplicas en fonction de la charge CPU/mémoire.
Installation
kubectl — le client CLI
Essentiel

kubectl est l'outil en ligne de commande pour interagir avec un cluster Kubernetes. À installer sur toutes les machines depuis lesquelles on gère le cluster.

WINDOWS
# Via winget (Windows Package Manager)
winget install Kubernetes.kubectl

# Via chocolatey
choco install kubernetes-cli

# Via scoop
scoop install kubectl

# Vérifier l'installation
kubectl version --client
MACOS
# Via Homebrew
brew install kubectl

# Vérifier
kubectl version --client
LINUX
# Télécharger le binaire (remplacer amd64 par arm64 si besoin)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

# Rendre exécutable et déplacer
chmod +x kubectl
sudo mv kubectl /usr/local/bin/

# Via apt (Debian/Ubuntu)
sudo apt-get update && sudo apt-get install -y kubectl

# Vérifier
kubectl version --client
Minikube — cluster local (dev)
LocalDev

Minikube crée un cluster Kubernetes mono-nœud sur votre machine. Idéal pour apprendre et tester en local. Nécessite Docker, VirtualBox ou Hyper-V.

WINDOWS
# Via winget
winget install Kubernetes.minikube

# Via chocolatey
choco install minikube

# Démarrer avec le driver Docker (recommandé)
minikube start --driver=docker

# Démarrer avec Hyper-V (nécessite droits admin)
minikube start --driver=hyperv
MACOS
brew install minikube
minikube start --driver=docker
LINUX
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
minikube start --driver=docker
BASH
# Gestion du cluster minikube
minikube start                     # Démarrer le cluster
minikube stop                      # Arrêter le cluster
minikube delete                    # Supprimer le cluster
minikube status                    # État du cluster
minikube dashboard                 # Ouvrir le dashboard web
minikube ip                        # Afficher l'IP du cluster

# Utiliser le registre Docker interne de minikube
eval $(minikube docker-env)        # Linux/macOS — pointer Docker vers minikube
minikube docker-env | Invoke-Expression  # Windows PowerShell

# Addons
minikube addons list               # Lister les addons disponibles
minikube addons enable ingress     # Activer l'Ingress Controller
minikube addons enable metrics-server  # Activer les métriques
Kind — Kubernetes dans Docker
LocalCI

Kind (Kubernetes IN Docker) fait tourner les nœuds Kubernetes dans des conteneurs Docker. Parfait pour les pipelines CI et les tests multi-nœuds.

BASH
# Installation via Go
go install sigs.k8s.io/kind@latest

# macOS
brew install kind

# Windows (chocolatey)
choco install kind

# Créer un cluster
kind create cluster
kind create cluster --name mon-cluster

# Créer un cluster multi-nœuds avec config
kind create cluster --config kind-config.yaml

# Lister / supprimer
kind get clusters
kind delete cluster --name mon-cluster
YAML
# kind-config.yaml — cluster 1 control-plane + 2 workers
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
Docker Desktop — K8s intégré (Windows & macOS)
WindowsmacOS

Docker Desktop inclut un cluster Kubernetes intégré activable en un clic. La solution la plus simple sur Windows et macOS.

ÉtapeAction
1. Ouvrir Docker DesktopParamètres → Kubernetes → cocher "Enable Kubernetes" → Apply & Restart
2. Vérifierkubectl cluster-info — doit afficher docker-desktop
3. Changer de contextekubectl config use-context docker-desktop
Contextes kubectl (kubeconfig)
Config

Le fichier ~/.kube/config stocke les informations de connexion à tous vos clusters. Un contexte associe un cluster, un utilisateur et un namespace.

BASH
# Lister les contextes disponibles
kubectl config get-contexts

# Afficher le contexte actif
kubectl config current-context

# Changer de contexte
kubectl config use-context minikube
kubectl config use-context docker-desktop
kubectl config use-context mon-cluster-prod

# Fusionner deux kubeconfig
KUBECONFIG=~/.kube/config:~/nouveau-cluster.yaml kubectl config view --flatten > ~/.kube/config

# Définir un namespace par défaut pour le contexte actif
kubectl config set-context --current --namespace=mon-namespace
kubectl — commandes essentielles
Obtenir des informations sur les ressources
Essentiel
BASH
# Informations générales
kubectl cluster-info                       # Infos sur le cluster
kubectl get nodes                          # Lister les nœuds
kubectl get nodes -o wide                  # Avec IP et version

# Lister les ressources
kubectl get pods                           # Pods du namespace actif
kubectl get pods -A                        # Pods de TOUS les namespaces
kubectl get pods -n kube-system            # Pods d'un namespace spécifique
kubectl get pods -o wide                   # Avec IP et nœud
kubectl get pods --watch                   # Mise à jour en temps réel
kubectl get deployments                    # Deployments
kubectl get services                       # Services (svc)
kubectl get ingress                        # Ingress
kubectl get configmaps                     # ConfigMaps (cm)
kubectl get secrets                        # Secrets
kubectl get pvc                            # PersistentVolumeClaims
kubectl get all                            # Toutes les ressources principales
kubectl get all -n mon-namespace           # Dans un namespace

# Détails d'une ressource (équivalent docker inspect)
kubectl describe pod mon-pod
kubectl describe deployment mon-deploy
kubectl describe service mon-service
kubectl describe node mon-node

# Affichage en YAML ou JSON
kubectl get pod mon-pod -o yaml
kubectl get deployment mon-deploy -o json

# Appliquer / supprimer des manifests YAML
kubectl apply -f manifest.yaml             # Créer ou mettre à jour
kubectl apply -f ./k8s/                    # Tous les fichiers d'un dossier
kubectl apply -f https://example.com/app.yaml
kubectl delete -f manifest.yaml            # Supprimer les ressources du manifest

# Supprimer des ressources
kubectl delete pod mon-pod
kubectl delete deployment mon-deploy
kubectl delete service mon-service
kubectl delete pod mon-pod --grace-period=0 --force  # Forcer la suppression
Logs, exec & port-forward
Essentiel
BASH
# Logs d'un Pod
kubectl logs mon-pod                       # Logs du container principal
kubectl logs mon-pod -f                    # Suivre en temps réel
kubectl logs mon-pod --previous            # Logs du container précédent (après crash)
kubectl logs mon-pod -c mon-container      # Container spécifique (Pod multi-container)
kubectl logs -l app=mon-app -f             # Logs de tous les Pods avec un label

# Exécuter une commande dans un Pod
kubectl exec mon-pod -- ls /app
kubectl exec -it mon-pod -- bash           # Shell interactif
kubectl exec -it mon-pod -c api -- sh      # Dans un container spécifique

# Port-forward (accès local à un Pod/Service)
kubectl port-forward pod/mon-pod 8080:80
kubectl port-forward svc/mon-service 8080:80
kubectl port-forward deployment/mon-deploy 8080:3000

# Copier des fichiers
kubectl cp mon-pod:/app/log.txt ./log.txt  # Pod → local
kubectl cp ./config.json mon-pod:/app/     # Local → Pod

# Métriques (nécessite metrics-server)
kubectl top nodes
kubectl top pods
kubectl top pods -n mon-namespace
Commandes impératives rapides
Pratique

En plus de l'approche déclarative (fichiers YAML), kubectl propose des commandes impératives pour créer des ressources rapidement ou générer des templates.

BASH
# Créer des ressources rapidement
kubectl run mon-pod --image=nginx:alpine
kubectl create deployment mon-deploy --image=nginx:alpine --replicas=3
kubectl create service clusterip mon-svc --tcp=80:80
kubectl create namespace mon-namespace
kubectl create configmap ma-config --from-literal=ENV=production
kubectl create secret generic mon-secret --from-literal=PASSWORD=s3cr3t

# Générer un YAML sans appliquer (--dry-run=client -o yaml)
kubectl create deployment mon-app --image=nginx --dry-run=client -o yaml > deployment.yaml
kubectl run mon-pod --image=nginx --dry-run=client -o yaml > pod.yaml
kubectl create service clusterip mon-svc --tcp=80:80 --dry-run=client -o yaml

# Mettre à l'échelle
kubectl scale deployment mon-deploy --replicas=5

# Mettre à jour l'image d'un Deployment (rolling update)
kubectl set image deployment/mon-deploy app=mon-image:v2

# Rollback
kubectl rollout status deployment/mon-deploy
kubectl rollout history deployment/mon-deploy
kubectl rollout undo deployment/mon-deploy
kubectl rollout undo deployment/mon-deploy --to-revision=2

# Éditer une ressource directement
kubectl edit deployment mon-deploy

# Labeler / annoter une ressource
kubectl label pod mon-pod env=production
kubectl annotate pod mon-pod description="Mon application"
Pods
Manifest d'un Pod
YAML

Un Pod est l'unité d'exécution de base. En pratique, on ne crée pas de Pods directement — on utilise des Deployments. Utile pour les tests et la compréhension.

YAML
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mon-pod
  namespace: default
  labels:
    app: mon-app
    env: production
spec:
  containers:
    - name: api
      image: nginx:alpine
      ports:
        - containerPort: 80
      env:
        - name: ENV
          value: "production"
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mon-secret
              key: password
      resources:
        requests:           # Minimum garanti
          cpu: "100m"       # 100 millicores = 0.1 CPU
          memory: "128Mi"
        limits:             # Maximum autorisé
          cpu: "500m"
          memory: "256Mi"
      livenessProbe:        # Redémarrer si le container est bloqué
        httpGet:
          path: /health
          port: 80
        initialDelaySeconds: 10
        periodSeconds: 5
      readinessProbe:       # Accepter du trafic seulement si prêt
        httpGet:
          path: /ready
          port: 80
        initialDelaySeconds: 5
        periodSeconds: 3
  restartPolicy: Always     # Always | OnFailure | Never
  initContainers:           # Conteneurs qui s'exécutent avant les containers principaux
    - name: init-db
      image: busybox
      command: ["sh", "-c", "until nc -z db 5432; do sleep 2; done"]
Deployments
Manifest d'un Deployment
Essentiel

Un Deployment gère un ensemble de Pods identiques (réplicas). Il assure les mises à jour progressives (rolling update), les rollbacks et la haute disponibilité.

YAML
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mon-app
  namespace: default
  labels:
    app: mon-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: mon-app               # Doit correspondre aux labels du Pod template
  strategy:
    type: RollingUpdate          # Mise à jour progressive (défaut)
    rollingUpdate:
      maxUnavailable: 1          # Max Pods indisponibles pendant la MàJ
      maxSurge: 1                # Max Pods supplémentaires pendant la MàJ
  template:                      # Template des Pods gérés par ce Deployment
    metadata:
      labels:
        app: mon-app
        version: "1.0"
    spec:
      containers:
        - name: api
          image: mon-image:1.0
          ports:
            - containerPort: 3000
          env:
            - name: NODE_ENV
              value: production
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 15
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5
BASH
# Déployer
kubectl apply -f deployment.yaml

# Suivre le déploiement en temps réel
kubectl rollout status deployment/mon-app

# Mettre à jour l'image (rolling update automatique)
kubectl set image deployment/mon-app api=mon-image:2.0

# Rollback en cas de problème
kubectl rollout undo deployment/mon-app
kubectl rollout history deployment/mon-app        # Voir l'historique
kubectl rollout undo deployment/mon-app --to-revision=1

# Mise à l'échelle manuelle
kubectl scale deployment mon-app --replicas=5

# Autoscaling (HPA)
kubectl autoscale deployment mon-app --cpu-percent=70 --min=2 --max=10
HorizontalPodAutoscaler (HPA)
Scaling

L'HPA ajuste automatiquement le nombre de réplicas en fonction de métriques (CPU, mémoire). Nécessite metrics-server installé dans le cluster.

YAML
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: mon-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: mon-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
Services
Types de Services
Essentiel

Un Service expose un ensemble de Pods via une IP stable et un nom DNS interne, indépendamment de leur cycle de vie. Le selector relie le Service aux Pods cibles.

TypeAccessibilitéUsage
ClusterIPInterne au cluster uniquementCommunication entre services (défaut)
NodePortVia l'IP du Node + un port (30000-32767)Dev/test, accès externe simple
LoadBalancerIP externe via un load balancer cloudProduction sur AWS/GCP/Azure
ExternalNameAlias DNS vers un service externeIntégrer une BDD externe au cluster
YAML
# ClusterIP — interne (défaut)
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  type: ClusterIP
  selector:
    app: mon-app           # Sélectionne les Pods avec ce label
  ports:
    - port: 80             # Port du Service (dans le cluster)
      targetPort: 3000     # Port du container

---
# NodePort — accès externe via IP:NodePort
apiVersion: v1
kind: Service
metadata:
  name: api-nodeport
spec:
  type: NodePort
  selector:
    app: mon-app
  ports:
    - port: 80
      targetPort: 3000
      nodePort: 30080      # Port sur chaque Node (optionnel, auto si omis)

---
# LoadBalancer — IP externe (cloud)
apiVersion: v1
kind: Service
metadata:
  name: api-lb
spec:
  type: LoadBalancer
  selector:
    app: mon-app
  ports:
    - port: 80
      targetPort: 3000
BASH
# Accéder à un NodePort avec minikube
minikube service api-nodeport --url

# Exposer un Deployment rapidement (impératif)
kubectl expose deployment mon-app --type=NodePort --port=80 --target-port=3000
ConfigMaps & Secrets
ConfigMap — configuration non sensible
Config

Un ConfigMap stocke des données de configuration découplées de l'image. Injecté dans les Pods via variables d'environnement ou fichiers montés.

YAML
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  NODE_ENV: "production"
  API_URL: "https://api.example.com"
  config.json: |
    {
      "debug": false,
      "logLevel": "warn"
    }
YAML
# Utiliser un ConfigMap dans un Pod
spec:
  containers:
    - name: api
      image: mon-image
      # Injecter toutes les clés comme variables d'environnement
      envFrom:
        - configMapRef:
            name: app-config
      # Ou injecter une clé spécifique
      env:
        - name: NODE_ENV
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: NODE_ENV
      # Ou monter comme fichier
      volumeMounts:
        - name: config-vol
          mountPath: /app/config
  volumes:
    - name: config-vol
      configMap:
        name: app-config
BASH
# Créer un ConfigMap en ligne de commande
kubectl create configmap app-config \
  --from-literal=NODE_ENV=production \
  --from-literal=API_URL=https://api.example.com \
  --from-file=config.json
Secret — données sensibles
Sécurité

Les Secrets stockent des données encodées en base64. Pour une vraie sécurité en production, les coupler avec des solutions comme Vault, Sealed Secrets ou les secrets managers cloud.

BASH
# Encoder en base64 (Linux/macOS)
echo -n "monMotDePasse" | base64     # bW9uTW90RGVQYXNzZQ==

# Créer un secret en ligne de commande (recommandé — pas de base64 manuel)
kubectl create secret generic db-secret \
  --from-literal=DB_PASSWORD=monMotDePasse \
  --from-literal=DB_USER=admin

# Secret TLS (certificat)
kubectl create secret tls mon-tls \
  --cert=tls.crt \
  --key=tls.key
YAML
# secret.yaml (valeurs en base64)
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  DB_PASSWORD: bW9uTW90RGVQYXNzZQ==   # echo -n "monMotDePasse" | base64
  DB_USER: YWRtaW4=                    # echo -n "admin" | base64

---
# Utilisation dans un Pod
spec:
  containers:
    - name: api
      envFrom:
        - secretRef:
            name: db-secret
      env:
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: DB_PASSWORD
Volumes & PersistentVolumeClaims
PersistentVolume & PersistentVolumeClaim
StockagePersistance

Un PersistentVolume (PV) est une ressource de stockage du cluster. Un PersistentVolumeClaim (PVC) est une demande de stockage par un Pod. Le cluster lie automatiquement un PVC à un PV compatible.

YAML
# PersistentVolume (provisionné par l'admin)
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mon-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce      # RWO: un seul Node | RWX: plusieurs Nodes
  persistentVolumeReclaimPolicy: Retain  # Retain | Delete | Recycle
  hostPath:              # Stockage local (dev uniquement)
    path: /data/mon-app

---
# PersistentVolumeClaim (demande par le Pod)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mon-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: standard   # Classe de stockage (cloud ou local)

---
# Utiliser le PVC dans un Deployment
spec:
  template:
    spec:
      containers:
        - name: db
          image: postgres:15
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: mon-pvc
BASH
kubectl get pv                  # Lister les PersistentVolumes
kubectl get pvc                 # Lister les PersistentVolumeClaims
kubectl describe pvc mon-pvc    # Vérifier le binding
kubectl get storageclass        # Classes de stockage disponibles
Namespaces
Gérer les namespaces
OrganisationIsolation

Les namespaces permettent d'isoler des ressources dans un même cluster (par équipe, environnement ou application). Les ressources de namespaces différents ne se voient pas par défaut.

BASH
# Namespaces par défaut
# default      — namespace principal
# kube-system  — composants Kubernetes internes
# kube-public  — données accessibles publiquement
# kube-node-lease — heartbeats des nodes

# Créer un namespace
kubectl create namespace production
kubectl create namespace staging

# Travailler dans un namespace
kubectl get pods -n production
kubectl apply -f deployment.yaml -n production

# Définir le namespace par défaut de la session
kubectl config set-context --current --namespace=production

# Revenir au namespace par défaut
kubectl config set-context --current --namespace=default

# Supprimer un namespace (ATTENTION : supprime tout ce qu'il contient)
kubectl delete namespace staging
YAML
# Déclarer le namespace dans le manifest
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mon-app
  namespace: production    # <-- spécifier le namespace
spec:
  # ...
Ingress
Ingress Controller & règles HTTP
HTTPRoutingTLS

L'Ingress est un reverse proxy L7 qui route le trafic HTTP/HTTPS entrant vers les bons Services selon des règles (host, path). Nécessite un Ingress Controller (nginx, traefik…).

BASH
# Installer nginx-ingress-controller via Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx

# Avec minikube (addon intégré)
minikube addons enable ingress
YAML
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mon-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:                                   # HTTPS avec un Secret TLS
    - hosts:
        - monapp.example.com
      secretName: mon-tls
  rules:
    - host: monapp.example.com           # Routage par host
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service        # Service cible
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80
    - host: admin.example.com            # Sous-domaine différent
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: admin-service
                port:
                  number: 80
Kubernetes avec Docker
Workflow complet : Docker → Kubernetes
EssentielDocker

Le flux typique : construire une image Docker, la pousser vers un registry, puis la déployer dans Kubernetes via un manifest YAML.

BASH
# 1. Construire l'image Docker
docker build -t monuser/mon-app:1.0 .

# 2. Pousser vers Docker Hub (ou autre registry)
docker login
docker push monuser/mon-app:1.0

# 3. Déployer dans Kubernetes
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

# ---- Développement local avec minikube ----

# Pointer Docker sur le daemon interne de minikube (évite de pousser sur un registry)
eval $(minikube docker-env)          # Linux/macOS
minikube docker-env | Invoke-Expression  # Windows PowerShell

# Construire l'image directement dans minikube
docker build -t mon-app:local .

# Déployer avec imagePullPolicy: Never (utilise l'image locale)
kubectl run mon-pod --image=mon-app:local --image-pull-policy=Never
Stack complète : API + Base de données
Exemple complet

Exemple d'une application avec une API Node.js et une base PostgreSQL déployées dans Kubernetes.

YAML
# k8s/secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  POSTGRES_PASSWORD: bW9uTW90RGVQYXNzZQ==

---
# k8s/postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:15-alpine
          ports:
            - containerPort: 5432
          env:
            - name: POSTGRES_DB
              value: mydb
            - name: POSTGRES_USER
              value: admin
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: POSTGRES_PASSWORD
          volumeMounts:
            - name: pg-data
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: pg-data
          persistentVolumeClaim:
            claimName: pg-pvc

---
# k8s/postgres-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: postgres          # DNS interne : postgres.default.svc.cluster.local
spec:
  selector:
    app: postgres
  ports:
    - port: 5432
      targetPort: 5432

---
# k8s/api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      initContainers:
        - name: wait-for-db
          image: busybox
          command: ["sh", "-c", "until nc -z postgres 5432; do sleep 2; done"]
      containers:
        - name: api
          image: monuser/mon-api:1.0
          ports:
            - containerPort: 3000
          env:
            - name: DATABASE_URL
              value: "postgresql://admin:$(POSTGRES_PASSWORD)@postgres:5432/mydb"
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: POSTGRES_PASSWORD

---
# k8s/api-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  type: NodePort
  selector:
    app: api
  ports:
    - port: 80
      targetPort: 3000
      nodePort: 30000
BASH
# Déployer toute la stack
kubectl apply -f k8s/

# Vérifier
kubectl get pods
kubectl get services

# Accéder à l'API avec minikube
minikube service api-service --url
Registry privé — imagePullSecrets
RegistryAuth

Pour utiliser des images d'un registry privé (Docker Hub privé, GitHub Container Registry, AWS ECR…), il faut créer un Secret de type docker-registry.

BASH
# Créer le secret d'authentification registry
kubectl create secret docker-registry regcred \
  --docker-server=ghcr.io \
  --docker-username=monuser \
  --docker-password=MON_TOKEN \
  --docker-email=moi@example.com
YAML
# Utiliser le secret dans un Pod
spec:
  imagePullSecrets:
    - name: regcred          # Référencer le secret créé
  containers:
    - name: api
      image: ghcr.io/monuser/mon-app:1.0
Helm — gestionnaire de paquets K8s
Installation & concepts
InstallConcepts

Helm est le gestionnaire de paquets de Kubernetes. Un chart est un paquet d'templates YAML paramétrables. Un release est une instance de chart déployée dans le cluster.

BASH
# Installation de Helm
# Windows (chocolatey)
choco install kubernetes-helm

# Windows (winget)
winget install Helm.Helm

# macOS
brew install helm

# Linux (script officiel)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Vérifier
helm version
Commandes Helm essentielles
Essentiel
BASH
# ===== REPOSITORIES =====
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update                              # Mettre à jour les repos
helm repo list                                # Lister les repos
helm search repo postgresql                   # Chercher un chart

# ===== INSTALLER / METTRE À JOUR =====
helm install mon-postgres bitnami/postgresql           # Installer
helm install mon-postgres bitnami/postgresql \
  --set auth.postgresPassword=s3cr3t \
  --set primary.persistence.size=10Gi \
  --namespace production --create-namespace

helm upgrade mon-postgres bitnami/postgresql \         # Mettre à jour
  --set image.tag=15.4.0

helm upgrade --install mon-postgres bitnami/postgresql # Installer ou MàJ

# Avec un fichier de valeurs
helm install mon-postgres bitnami/postgresql -f values.yaml
helm upgrade mon-postgres bitnami/postgresql -f values.yaml

# ===== GÉRER LES RELEASES =====
helm list                                     # Releases dans le namespace actif
helm list -A                                  # Toutes les releases
helm status mon-postgres                      # État d'une release
helm history mon-postgres                     # Historique des révisions
helm rollback mon-postgres 1                  # Rollback à la révision 1
helm uninstall mon-postgres                   # Désinstaller

# ===== INSPECTER UN CHART =====
helm show values bitnami/postgresql           # Valeurs par défaut
helm show chart bitnami/postgresql            # Infos du chart
helm template mon-app ./mon-chart             # Prévisualiser le YAML généré
helm lint ./mon-chart                         # Valider un chart

# ===== CRÉER SON PROPRE CHART =====
helm create mon-chart                         # Scaffold d'un chart
helm package mon-chart                        # Empaqueter (.tgz)
helm install mon-app ./mon-chart -f custom-values.yaml
Structure d'un chart Helm
Structure
BASH
mon-chart/
├── Chart.yaml           # Métadonnées du chart (nom, version, description)
├── values.yaml          # Valeurs par défaut (surchargeables à l'install)
├── templates/           # Templates YAML avec syntaxe Go templating
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── _helpers.tpl     # Fonctions/partials réutilisables
│   └── NOTES.txt        # Message affiché après l'installation
└── charts/              # Dépendances (sous-charts)
YAML
# values.yaml
replicaCount: 2
image:
  repository: monuser/mon-app
  tag: "1.0"
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
  port: 80
ingress:
  enabled: false
resources:
  limits:
    cpu: 500m
    memory: 256Mi

---
# templates/deployment.yaml — utilise les valeurs
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "mon-chart.fullname" . }}
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
Bonnes pratiques
Règles essentielles en production
PratiqueDescription
Toujours définir les ressourcesSpécifier requests et limits CPU/mémoire sur chaque container. Sans ça, un Pod peut épuiser les ressources du Node.
Liveness & Readiness probesConfigurer les deux probes sur chaque container. La liveness redémarre les containers bloqués, la readiness évite d'envoyer du trafic vers des Pods non prêts.
Ne jamais utiliser :latestToujours tagger les images avec une version précise en production. :latest empêche de savoir quelle version est déployée et bloque le cache.
Utiliser des namespacesIsoler les environnements (dev, staging, production) et les équipes dans des namespaces séparés.
Approche déclarativeToujours travailler avec des fichiers YAML versionnés dans Git. Éviter les commandes impératives en production.
Secrets externalisésNe jamais commiter des Secrets en clair dans Git. Utiliser Sealed Secrets, Vault, AWS Secrets Manager ou SOPS.
Utilisateur non-rootConfigurer securityContext.runAsNonRoot: true et readOnlyRootFilesystem: true dans les containers.
PodDisruptionBudgetDéfinir un PDB pour garantir un minimum de Pods disponibles lors des mises à jour ou maintenances de Nodes.
Multi-réplicasToujours avoir au moins 2 réplicas en production pour assurer la haute disponibilité.
MonitoringInstaller Prometheus + Grafana pour surveiller l'état du cluster et des workloads.
Cheat sheet — commandes kubectl indispensables
Référence
CommandeDescription
kubectl get all -n nsToutes les ressources d'un namespace
kubectl apply -f ./k8s/Appliquer tous les manifests d'un dossier
kubectl describe pod nomDiagnostiquer un Pod (events, état)
kubectl logs -f pod/nomSuivre les logs en temps réel
kubectl exec -it pod/nom -- bashShell dans un container
kubectl port-forward svc/nom 8080:80Accès local à un Service
kubectl scale deploy/nom --replicas=5Changer le nombre de réplicas
kubectl rollout undo deploy/nomRollback du dernier déploiement
kubectl top podsConsommation CPU/mémoire des Pods
kubectl get events --sort-by=.lastTimestampÉvénements du cluster triés par date
kubectl config use-context nomChanger de cluster
kubectl explain deployment.specDocumentation inline d'une ressource

Aucun résultat pour votre recherche.