# 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. - Published: 2026-02-12 - Updated: 2026-03-28 - Author: SharpSkill - Tags: kubernetes, k8s, container orchestration, devops, deployment - Reading time: 16 min --- 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. > **Prérequis** > > 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. ```bash # 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: Configured ``` Minikube 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. ```bash # 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-info ``` > **Alternatives à minikube** > > Kind (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. ```yaml # 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). ```bash # 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-pod ``` Les 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. ```yaml # 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: 5 ``` Le 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. ```bash # 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-deployment ``` La suppression d'un Pod déclenche automatiquement la création d'un nouveau Pod pour maintenir le nombre de réplicas souhaité. ## 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é. ```yaml # 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: TCP ``` Ce 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`. ```bash # 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 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-service ``` Pour exposer l'application à l'extérieur du cluster, le type NodePort ou LoadBalancer est nécessaire. ```yaml # 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: 30080 ``` Avec 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. ```yaml # 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. ```yaml # 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-config ``` Cette configuration injecte les variables d'environnement et monte le fichier nginx.conf dans le conteneur. ```bash # 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.conf ``` > **Mise à jour des ConfigMaps** > > La 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. ```yaml # 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: supersecretpassword ``` Les Secrets peuvent être injectés de la même manière que les ConfigMaps. ```yaml # 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 ``` ```bash # 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 # supersecretpassword ``` ## Namespaces : 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. ```yaml # namespace.yaml apiVersion: v1 kind: Namespace metadata: name: development labels: environment: development --- apiVersion: v1 kind: Namespace metadata: name: staging labels: environment: staging ``` Chaque ressource peut être créée dans un namespace spécifique. ```bash # 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=development ``` Les 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. ```yaml # 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: 30100 ``` Ce fichier unique déploie une application complète avec configuration externalisée, secrets, haute disponibilité et exposition réseau. ```bash # 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 myapp ``` ## Mise à jour et rollback Kubernetes facilite les mises à jour progressives (rolling updates) et les retours en arrière (rollbacks). ```bash # 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 # 2 # 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 myapp ``` La stratégie de mise à jour par défaut (RollingUpdate) remplace progressivement les anciens Pods par les nouveaux, garantissant une disponibilité continue. ## Commandes kubectl essentielles ```bash # 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 # Détails complets kubectl logs -f # Logs en streaming kubectl logs -c # Logs d'un conteneur spécifique kubectl exec -it -- /bin/sh # Shell interactif kubectl port-forward 8080:80 # Tunnel local vers le Pod # ======================================== # Édition et suppression # ======================================== kubectl edit deployment # Édition en direct (vi) kubectl delete -f manifest.yaml # Suppression via fichier kubectl delete pod --force # Suppression forcée ``` ## Conclusion 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 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. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/fr/blog/devops/kubernetes-deployer-premiere-application