Kubernetes : Déployer votre première application
Guide pratique pour déployer une application sur Kubernetes. De l'installation de minikube aux Deployments, Services et ConfigMaps, avec des exemples concrets.

Kubernetes (K8s) est devenu le standard de facto pour l'orchestration de conteneurs. Conçu par Google et maintenant géré par la CNCF, Kubernetes automatise le déploiement, la mise à l'échelle et la gestion des applications conteneurisées. Ce guide accompagne la mise en place d'un cluster local et le déploiement d'une première application.
Une connaissance de base de Docker est recommandée avant d'aborder Kubernetes. Les conteneurs sont les briques fondamentales que Kubernetes orchestre. La lecture préalable du guide Docker facilite la compréhension des concepts présentés ici.
Comprendre l'architecture Kubernetes
Kubernetes repose sur une architecture maître-worker. Le Control Plane (plan de contrôle) prend les décisions globales sur le cluster, tandis que les Nodes (nœuds) exécutent les charges de travail.
# Architecture Kubernetes simplifiée
┌─────────────────────────────────────────────────────────────┐
│ CONTROL PLANE │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ API Server │ │ Scheduler │ │ Controller Manager │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ etcd ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ NODE 1 │ │ NODE 2 │ │ NODE 3 │
│ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │
│ │ kubelet │ │ │ │ kubelet │ │ │ │ kubelet │ │
│ ├───────────┤ │ │ ├───────────┤ │ │ ├───────────┤ │
│ │ kube-proxy│ │ │ │ kube-proxy│ │ │ │ kube-proxy│ │
│ ├───────────┤ │ │ ├───────────┤ │ │ ├───────────┤ │
│ │ Pods │ │ │ │ Pods │ │ │ │ Pods │ │
│ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘ └─────────────────┘L'API Server est le point d'entrée pour toutes les commandes. etcd stocke l'état du cluster. Le Scheduler assigne les Pods aux Nodes. Les Controllers maintiennent l'état désiré du système.
Installation de l'environnement local
Pour expérimenter Kubernetes localement, plusieurs options existent : minikube, kind, k3d ou Docker Desktop. Minikube reste la solution la plus répandue pour l'apprentissage.
# terminal
# Installation de kubectl (client Kubernetes)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
# Vérification de l'installation
kubectl version --client
# Client Version: v1.31.0
# Installation de minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# Démarrage du cluster local
minikube start --driver=docker --cpus=2 --memory=4096
# Vérification du statut
minikube status
# minikube: Running
# cluster: Running
# kubectl: ConfiguredMinikube crée un cluster Kubernetes single-node dans une machine virtuelle ou un conteneur Docker. Les ressources allouées (CPU, mémoire) peuvent être ajustées selon les besoins.
# terminal
# Accès au dashboard Kubernetes (interface web)
minikube dashboard
# Vérification des nodes du cluster
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# minikube Ready control-plane 5m v1.31.0
# Informations détaillées sur le cluster
kubectl cluster-infoKind (Kubernetes in Docker) démarre plus rapidement et convient mieux aux tests CI/CD. K3d utilise k3s, une distribution légère de Kubernetes. Docker Desktop intègre Kubernetes directement mais consomme plus de ressources.
Les Pods : unité de base
Un Pod est la plus petite unité déployable dans Kubernetes. Un Pod encapsule un ou plusieurs conteneurs qui partagent le même réseau et le même stockage.
# pod-simple.yaml
apiVersion: v1
kind: Pod
metadata:
# Nom unique du Pod dans le namespace
name: nginx-pod
# Labels pour l'organisation et la sélection
labels:
app: nginx
environment: development
spec:
containers:
# Définition du conteneur principal
- name: nginx
# Image Docker à utiliser
image: nginx:1.25-alpine
# Ports exposés par le conteneur
ports:
- containerPort: 80
# Ressources allouées au conteneur
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"Ce manifest YAML déclare un Pod contenant un seul conteneur nginx. Les labels permettent d'identifier et de sélectionner les Pods. Les resources définissent les garanties minimales (requests) et les limites maximales (limits).
# terminal
# Création du Pod
kubectl apply -f pod-simple.yaml
# pod/nginx-pod created
# Liste des Pods
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# nginx-pod 1/1 Running 0 30s
# Détails complets du Pod
kubectl describe pod nginx-pod
# Logs du conteneur
kubectl logs nginx-pod
# Exécution d'une commande dans le Pod
kubectl exec -it nginx-pod -- /bin/sh
# Suppression du Pod
kubectl delete pod nginx-podLes Pods sont éphémères par nature. En cas de crash ou de suppression, Kubernetes ne les recrée pas automatiquement. Les Deployments résolvent cette limitation.
Deployments : gestion déclarative
Un Deployment définit l'état désiré pour un ensemble de Pods identiques. Kubernetes maintient automatiquement cet état en créant, mettant à jour ou supprimant des Pods selon les besoins.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
# Nom du Deployment
name: webapp-deployment
labels:
app: webapp
spec:
# Nombre de réplicas souhaité
replicas: 3
# Sélecteur pour identifier les Pods gérés
selector:
matchLabels:
app: webapp
# Template pour la création des Pods
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
# Probe de vivacité : redémarre le conteneur si échec
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
# Probe de disponibilité : retire le Pod du Service si échec
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5Le Deployment crée un ReplicaSet qui maintient 3 Pods identiques. Les probes vérifient la santé des conteneurs et permettent à Kubernetes de réagir automatiquement aux problèmes.
# terminal
# Création du Deployment
kubectl apply -f deployment.yaml
# deployment.apps/webapp-deployment created
# Vérification du Deployment
kubectl get deployments
# NAME READY UP-TO-DATE AVAILABLE AGE
# webapp-deployment 3/3 3 3 1m
# Liste des Pods créés par le Deployment
kubectl get pods -l app=webapp
# NAME READY STATUS RESTARTS AGE
# webapp-deployment-7d9f8b6c4-abc12 1/1 Running 0 1m
# webapp-deployment-7d9f8b6c4-def34 1/1 Running 0 1m
# webapp-deployment-7d9f8b6c4-ghi56 1/1 Running 0 1m
# Mise à l'échelle manuelle
kubectl scale deployment webapp-deployment --replicas=5
# Historique des déploiements
kubectl rollout history deployment webapp-deploymentLa suppression d'un Pod déclenche automatiquement la création d'un nouveau Pod pour maintenir le nombre de réplicas souhaité.
Prêt à réussir tes entretiens DevOps ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Services : exposition réseau
Les Pods ont des adresses IP éphémères. Les Services fournissent une adresse stable pour accéder à un ensemble de Pods, avec load balancing intégré.
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp-service
spec:
# Type de Service : ClusterIP (interne), NodePort, LoadBalancer
type: ClusterIP
# Sélecteur pour identifier les Pods cibles
selector:
app: webapp
ports:
# Port exposé par le Service
- port: 80
# Port du conteneur cible
targetPort: 80
# Protocole (TCP par défaut)
protocol: TCPCe Service de type ClusterIP est accessible uniquement depuis l'intérieur du cluster. Les requêtes vers webapp-service:80 sont distribuées entre les Pods avec le label app: webapp.
# terminal
# Création du Service
kubectl apply -f service.yaml
# service/webapp-service created
# Liste des Services
kubectl get services
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# webapp-service ClusterIP 10.96.123.456 <none> 80/TCP 30s
# Test depuis un Pod temporaire
kubectl run curl-test --rm -it --image=curlimages/curl -- curl webapp-service
# Description détaillée du Service
kubectl describe service webapp-servicePour exposer l'application à l'extérieur du cluster, le type NodePort ou LoadBalancer est nécessaire.
# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: webapp-nodeport
spec:
type: NodePort
selector:
app: webapp
ports:
- port: 80
targetPort: 80
# Port sur chaque Node (30000-32767)
nodePort: 30080Avec minikube, la commande minikube service webapp-nodeport ouvre automatiquement le navigateur vers l'URL correcte.
ConfigMaps : configuration externalisée
Les ConfigMaps séparent la configuration du code. Les valeurs peuvent être injectées comme variables d'environnement ou fichiers montés.
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: webapp-config
data:
# Valeurs simples clé-valeur
APP_ENV: "production"
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"
# Configuration multilignes (fichier complet)
nginx.conf: |
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
}Les ConfigMaps stockent des données non sensibles. Pour les secrets (mots de passe, tokens), les Secrets Kubernetes sont plus appropriés.
# deployment-with-config.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-configured
spec:
replicas: 2
selector:
matchLabels:
app: webapp-configured
template:
metadata:
labels:
app: webapp-configured
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
# Injection des variables d'environnement
envFrom:
- configMapRef:
name: webapp-config
# Ou variables individuelles
env:
- name: SPECIFIC_VAR
valueFrom:
configMapKeyRef:
name: webapp-config
key: LOG_LEVEL
# Montage du fichier de configuration
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: webapp-configCette configuration injecte les variables d'environnement et monte le fichier nginx.conf dans le conteneur.
# terminal
# Application des ressources
kubectl apply -f configmap.yaml
kubectl apply -f deployment-with-config.yaml
# Vérification des variables d'environnement
kubectl exec deployment/webapp-configured -- printenv | grep APP_ENV
# APP_ENV=production
# Vérification du fichier monté
kubectl exec deployment/webapp-configured -- cat /etc/nginx/conf.d/default.confLa modification d'un ConfigMap ne redémarre pas automatiquement les Pods. Pour appliquer les changements, un redémarrage manuel est nécessaire : kubectl rollout restart deployment webapp-configured. Certains outils comme Reloader automatisent ce processus.
Secrets : données sensibles
Les Secrets stockent des informations sensibles comme les mots de passe, tokens ou clés SSH. Bien que encodés en base64, ils ne sont pas chiffrés par défaut au repos.
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: webapp-secrets
type: Opaque
# Les valeurs doivent être encodées en base64
data:
# echo -n 'admin' | base64
username: YWRtaW4=
# echo -n 'supersecretpassword' | base64
password: c3VwZXJzZWNyZXRwYXNzd29yZA==
---
# Alternative : stringData accepte les valeurs en clair
apiVersion: v1
kind: Secret
metadata:
name: webapp-secrets-plain
type: Opaque
stringData:
username: admin
password: supersecretpasswordLes Secrets peuvent être injectés de la même manière que les ConfigMaps.
# deployment-with-secrets.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp-secure
spec:
replicas: 1
selector:
matchLabels:
app: webapp-secure
template:
metadata:
labels:
app: webapp-secure
spec:
containers:
- name: webapp
image: nginx:1.25-alpine
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: webapp-secrets
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: webapp-secrets
key: password# terminal
# Création du Secret
kubectl apply -f secret.yaml
# Liste des Secrets (les valeurs ne sont pas affichées)
kubectl get secrets
# NAME TYPE DATA AGE
# webapp-secrets Opaque 2 10s
# Décodage d'une valeur
kubectl get secret webapp-secrets -o jsonpath='{.data.password}' | base64 -d
# supersecretpasswordNamespaces : isolation logique
Les Namespaces partitionnent un cluster en environnements virtuels isolés. Cette séparation permet de gérer plusieurs équipes ou environnements sur un même cluster.
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
environment: development
---
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
environment: stagingChaque ressource peut être créée dans un namespace spécifique.
# terminal
# Création des namespaces
kubectl apply -f namespace.yaml
# Liste des namespaces
kubectl get namespaces
# NAME STATUS AGE
# default Active 1d
# development Active 10s
# staging Active 10s
# Création d'une ressource dans un namespace spécifique
kubectl apply -f deployment.yaml -n development
# Liste des Pods dans un namespace
kubectl get pods -n development
# Changement du namespace par défaut
kubectl config set-context --current --namespace=developmentLes ressources dans des namespaces différents sont isolées par défaut. La communication cross-namespace est possible via le DNS interne : service-name.namespace.svc.cluster.local.
Application complète : assemblage des ressources
Voici une application complète combinant tous les concepts présentés.
# complete-app.yaml
---
# Namespace dédié
apiVersion: v1
kind: Namespace
metadata:
name: myapp
---
# ConfigMap pour la configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
namespace: myapp
data:
APP_NAME: "MyApp"
LOG_LEVEL: "info"
---
# Secret pour les données sensibles
apiVersion: v1
kind: Secret
metadata:
name: myapp-secrets
namespace: myapp
type: Opaque
stringData:
api-key: "sk-1234567890abcdef"
---
# Deployment avec 3 réplicas
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx:1.25-alpine
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: myapp-config
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: myapp-secrets
key: api-key
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
---
# Service pour l'exposition interne
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: myapp
spec:
type: ClusterIP
selector:
app: myapp
ports:
- port: 80
targetPort: 80
---
# Service NodePort pour l'accès externe (développement)
apiVersion: v1
kind: Service
metadata:
name: myapp-nodeport
namespace: myapp
spec:
type: NodePort
selector:
app: myapp
ports:
- port: 80
targetPort: 80
nodePort: 30100Ce fichier unique déploie une application complète avec configuration externalisée, secrets, haute disponibilité et exposition réseau.
# terminal
# Déploiement de l'application complète
kubectl apply -f complete-app.yaml
# Vérification de toutes les ressources
kubectl get all -n myapp
# NAME READY STATUS RESTARTS AGE
# pod/myapp-7d9f8b6c4-abc12 1/1 Running 0 30s
# pod/myapp-7d9f8b6c4-def34 1/1 Running 0 30s
# pod/myapp-7d9f8b6c4-ghi56 1/1 Running 0 30s
#
# NAME TYPE CLUSTER-IP PORT(S) AGE
# service/myapp-service ClusterIP 10.96.123.456 80/TCP 30s
# service/myapp-nodeport NodePort 10.96.123.789 80:30100/TCP 30s
#
# NAME READY UP-TO-DATE AVAILABLE AGE
# deployment.apps/myapp 3/3 3 3 30s
# Accès à l'application avec minikube
minikube service myapp-nodeport -n myappMise à jour et rollback
Kubernetes facilite les mises à jour progressives (rolling updates) et les retours en arrière (rollbacks).
# terminal
# Mise à jour de l'image du Deployment
kubectl set image deployment/myapp myapp=nginx:1.26-alpine -n myapp
# Suivi du déploiement en temps réel
kubectl rollout status deployment/myapp -n myapp
# Waiting for deployment "myapp" rollout to finish: 1 out of 3 new replicas updated
# Waiting for deployment "myapp" rollout to finish: 2 out of 3 new replicas updated
# deployment "myapp" successfully rolled out
# Historique des révisions
kubectl rollout history deployment/myapp -n myapp
# REVISION CHANGE-CAUSE
# 1 <none>
# 2 <none>
# Rollback vers la révision précédente
kubectl rollout undo deployment/myapp -n myapp
# Rollback vers une révision spécifique
kubectl rollout undo deployment/myapp --to-revision=1 -n myappLa stratégie de mise à jour par défaut (RollingUpdate) remplace progressivement les anciens Pods par les nouveaux, garantissant une disponibilité continue.
Commandes kubectl essentielles
# terminal
# ========================================
# Informations générales
# ========================================
kubectl cluster-info # Infos sur le cluster
kubectl get nodes -o wide # Nodes avec détails
kubectl api-resources # Liste des types de ressources
# ========================================
# Gestion des ressources
# ========================================
kubectl get all # Toutes les ressources du namespace
kubectl get pods -A # Pods de tous les namespaces
kubectl get pods -o wide # Pods avec IP et Node
kubectl get pods -w # Mode watch (temps réel)
# ========================================
# Inspection et debug
# ========================================
kubectl describe pod <name> # Détails complets
kubectl logs <pod> -f # Logs en streaming
kubectl logs <pod> -c <container> # Logs d'un conteneur spécifique
kubectl exec -it <pod> -- /bin/sh # Shell interactif
kubectl port-forward <pod> 8080:80 # Tunnel local vers le Pod
# ========================================
# Édition et suppression
# ========================================
kubectl edit deployment <name> # Édition en direct (vi)
kubectl delete -f manifest.yaml # Suppression via fichier
kubectl delete pod <name> --force # Suppression forcéeConclusion
Kubernetes transforme la gestion des applications conteneurisées en fournissant un cadre déclaratif, résilient et extensible. Les concepts fondamentaux présentés ici constituent la base pour des déploiements production-ready.
Checklist pour un premier déploiement Kubernetes
- ✅ Cluster local fonctionnel (minikube, kind ou k3d)
- ✅ kubectl installé et configuré
- ✅ Deployment avec replicas et probes de santé
- ✅ Service pour l'exposition réseau
- ✅ ConfigMap pour la configuration externalisée
- ✅ Secret pour les données sensibles
- ✅ Namespace pour l'isolation
- ✅ Limites de ressources définies (requests/limits)
- ✅ Stratégie de mise à jour et rollback maîtrisée
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
La maîtrise de Kubernetes ouvre la porte à des architectures cloud-native évolutives. Les prochaines étapes incluent l'exploration des Ingress Controllers pour le routage HTTP, des PersistentVolumes pour le stockage, et de Helm pour la gestion des packages. Kubernetes devient un atout majeur lors des entretiens DevOps et SRE.
Tags
Partager
Articles similaires

Questions d'entretien DevOps essentielles : Guide complet 2026
Préparez vos entretiens DevOps avec les questions incontournables sur CI/CD, Kubernetes, Docker, Terraform et les pratiques SRE. Réponses détaillées incluses.

Docker : Du développement à la production
Guide complet Docker pour conteneuriser vos applications. Dockerfile, Docker Compose, multi-stage builds et déploiement production expliqués avec exemples pratiques.

Entretien Kubernetes : Pods, Services et Deployments en pratique
Questions d'entretien Kubernetes sur les Pods, Services et Deployments avec exemples YAML, fonctionnement réseau et stratégies de scaling pour 2026.