Questions d'entretien Docker & Kubernetes
Les entretiens Docker et Kubernetes testent votre capacité à conteneuriser des applications et à les orchestrer à grande échelle. Ces questions sont couramment posées pour les rôles DevOps, SRE et ingénierie de plateforme. Elles couvrent à la fois les concepts fondamentaux comme les images et les conteneurs, et les compétences pratiques comme l'écriture de manifestes YAML et le débogage de clusters. Attendez-vous à un mélange d'explications conceptuelles, de tâches pratiques et de scénarios de dépannage.
Ce que couvrent les entretiens Docker & Kubernetes
Bases des conteneurs
Les questions couvrent l'architecture Docker, les images, les conteneurs, les volumes et les réseaux. On peut vous demander d'écrire des Dockerfiles et de comprendre les constructions multi-étapes.
Architecture Kubernetes
Concentrez-vous sur les composants du plan de contrôle, les nœuds, les pods, les déploiements, les services et l'ingress. Attendez-vous à des questions sur le scheduler, kubelet et le serveur API.
Réseau et stockage
Les sujets incluent le réseau de pods, les types de services, les politiques réseau, les volumes persistants et les classes de stockage. Vous devez comprendre comment les conteneurs communiquent à l'intérieur et entre les clusters.
CI/CD et surveillance
Questions sur l'intégration de Docker et Kubernetes avec les pipelines CI/CD, l'utilisation de Helm, la surveillance avec Prometheus et la journalisation avec Fluentd ou des outils similaires.
Exemples de questions d'entretien Docker & Kubernetes
- Quelle est la différence entre une image Docker et un conteneur ?Ce qu'une bonne réponse couvre
- Une image est un template immuable, un conteneur est une instance en cours d'exécution.
- L'image contient le code, les dépendances et la configuration, tandis que le conteneur ajoute une couche modifiable.
- Plusieurs conteneurs peuvent être créés à partir d'une même image.
- Les images sont stockées dans un registre, les conteneurs sont gérés par le runtime Docker.
Voir un exemple de réponse
Une image Docker est un artefact léger, autonome et exécutable qui inclut tout le nécessaire pour exécuter une application : code, runtime, bibliothèques et variables d'environnement. Elle est immuable et sert de modèle pour créer des conteneurs. Un conteneur est une instance en cours d'exécution de cette image, avec un système de fichiers en couche et un processus isolé. La principale différence réside dans le fait que l'image est statique et partagée, tandis que le conteneur est dynamique et peut être modifié (écriture dans la couche modifiable). Chaque conteneur possède son propre espace de noms, mais partage le noyau avec l'hôte. Les images permettent la reproductibilité des environnements, alors que les conteneurs fournissent l'isolation et la portabilité.
- Comment déboguer un Pod bloqué en CrashLoopBackOff ?Ce qu'une bonne réponse couvre
- Utiliser `kubectl logs <pod>` pour voir les logs de sortie standard et d'erreur.
- Vérifier les événements avec `kubectl describe pod <pod>` pour des détails sur l'échec.
- Exécuter `kubectl get events --sort-by='.lastTimestamp'` pour des événements récents.
- Si le problème est lié à l'image, tester l'image localement avec `docker run`.
- Augmenter temporairement les ressources ou modifier la commande d'entrée pour un shell interactif.
Voir un exemple de réponse
CrashLoopBackOff indique qu'un Pod démarre puis se crashe à plusieurs reprises. Pour déboguer, commencez par consulter les logs du conteneur avec `kubectl logs <pod>`. Si le conteneur a déjà redémarré, utilisez `kubectl logs --previous <pod>` pour voir les logs de la dernière tentative. Ensuite, examinez les événements du Pod avec `kubectl describe pod <pod>` pour identifier les erreurs comme une image introuvable, un port déjà occupé, ou un problème de configuration. Vérifiez également les liveness et readiness probes si elles sont configurées : une sonde mal configurée peut tuer le conteneur. Si le conteneur crash immédiatement, exécutez une commande shell temporaire (comme `sh`) en remplacement de la commande d'entrée pour inspecter l'environnement. Assurez-vous également que les variables d'environnement et les montages de volumes sont corrects. Une cause fréquente est un processus qui s'arrête immédiatement (par exemple, application qui échoue au démarrage). Enfin, si le problème persiste, testez l'image Docker localement pour reproduire l'erreur hors de Kubernetes.
- Écrivez un Dockerfile pour une application Node.js qui s'exécute sur le port 3000.Ce qu'une bonne réponse couvre
- Utiliser une image de base officielle Node.js (ex: node:14-alpine).
- Définir le répertoire de travail (WORKDIR).
- Copier package.json et installer les dépendances avant le code pour optimiser le cache.
- Copier le code source, exposer le port 3000, et définir la commande de démarrage.
- Utiliser un utilisateur non-root pour la sécurité.
Voir un exemple de réponse
Voici un Dockerfile complet pour une application Node.js. Il optimise la construction en copiant d'abord les fichiers de dépendances pour tirer parti du cache Docker. L'application écoute sur le port 3000. Le conteneur s'exécute en tant qu'utilisateur node (non-root) pour des raisons de sécurité. L'instruction EXPOSE est documentaire, le port est réellement lié au moment de l'exécution avec -p.
Solution de référencedockerfile # Étape 1 : image de base légère FROM node:14-alpine AS builder # Définir le répertoire de travail WORKDIR /app # Copier les fichiers de dépendances (pour le cache) COPY package*.json ./ # Installer les dépendances RUN npm ci --only=production # Copier le code source COPY . . # Exposer le port sur lequel l'application écoute EXPOSE 3000 # Utiliser un utilisateur non-root pour la sécurité USER node # Commande de démarrage CMD ["node", "server.js"] - Expliquez comment fonctionnent les Services Kubernetes et comment ils permettent l'équilibrage de charge.Ce qu'une bonne réponse couvre
- Un Service Kubernetes est une abstraction qui expose un ensemble de Pods comme un service réseau.
- Il utilise des sélecteurs d'étiquettes pour identifier les Pods cibles.
- Le Service reçoit une adresse IP stable (ClusterIP) et un nom DNS.
- L'équilibrage de charge est effectué au niveau du proxy kube-proxy via round-robin ou autres algorithmes.
- Les types de Service incluent ClusterIP, NodePort, LoadBalancer et ExternalName.
Voir un exemple de réponse
Un Service Kubernetes fournit une adresse IP et un nom DNS stables pour accéder à un ensemble de Pods, qui peuvent être créés ou détruits dynamiquement. Le Service sélectionne les Pods cibles via des sélecteurs d'étiquettes (labels). Lorsqu'un client envoie une requête à l'IP du Service, le proxy kube-proxy sur chaque nœud intercepte le trafic et le répartit uniformément entre les Pods correspondants, en utilisant par défaut un algorithme de round-robin. Cela permet un équilibrage de charge côté serveur. De plus, le Service gère la découverte de services via le DNS interne de Kubernetes. Il existe plusieurs types de Services : ClusterIP (interne au cluster), NodePort (expose sur un port de chaque nœud), LoadBalancer (intègre un équilibreur de charge externe) et ExternalName (renvoie un nom DNS externe). L'utilisation de Services permet de découpler les consommateurs des Pods individuels, offrant ainsi une haute disponibilité et une scalabilité transparente.
- Créez un Déploiement qui déploie une mise à jour sans interruption de service.Ce qu'une bonne réponse couvre
- Configurer un Deployment avec une stratégie de rolling update.
- Définir des readiness probes pour que le nouveau Pod soit prêt avant de continuer.
- Spécifier maxSurge et maxUnavailable pour contrôler le rollout.
- Créer un fichier YAML avec l'image de l'application et les sondes.
- Appliquer avec `kubectl apply` pour une mise à jour progressive.
Voir un exemple de réponse
Pour déployer une mise à jour sans interruption de service, on utilise un Deployment avec une stratégie de rolling update. Cette stratégie remplace progressivement les anciens Pods par les nouveaux, en maintenant un nombre minimum de Pods disponibles. Il est essentiel de configurer des readiness probes pour que le nouveau Pod ne reçoive du trafic que lorsqu'il est réellement prêt. Le paramètre `maxSurge` (nombre de Pods supplémentaires autorisés) et `maxUnavailable` (nombre de Pods indisponibles autorisés) contrôlent la vitesse et la disponibilité. Par exemple, un rolling update avec `maxSurge: 25%` et `maxUnavailable: 25%` garantit qu'il y a toujours au moins 75% des Pods en service. Le Deployment applique la mise à jour en créant d'abord de nouveaux Pods et en supprimant les anciens une fois que les nouveaux sont prêts. Si la mise à jour échoue (liveness probe), Kubernetes peut automatiquement annuler le rollout.
Solution de référenceyaml apiVersion: apps/v1 kind: Deployment metadata: name: mon-app spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: mon-app template: metadata: labels: app: mon-app spec: containers: - name: app image: mon-image:latest ports: - containerPort: 80 readinessProbe: httpGet: path: /healthz port: 80 initialDelaySeconds: 5 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: 80 initialDelaySeconds: 15 periodSeconds: 20 - Comment gérez-vous les secrets dans Kubernetes ?Ce qu'une bonne réponse couvre
- Utiliser des Secrets Kubernetes pour stocker des données sensibles comme mots de passe et clés API.
- Les Secrets sont encodés en base64 mais doivent être chiffrés au repos avec etcd encryption.
- Les injecter comme variables d'environnement ou montés comme volumes.
- Préférer des solutions externes comme HashiCorp Vault ou AWS Secrets Manager pour une sécurité renforcée.
- Éviter de stocker des secrets dans le code source ou les images.
Voir un exemple de réponse
Kubernetes propose les ressources de type Secret pour gérer les informations sensibles. Les Secrets sont stockés dans etcd, et par défaut uniquement encodés en base64 (pas chiffrés). Pour sécuriser les données au repos, il est recommandé d'activer le chiffrement des secrets dans etcd. Les Secrets peuvent être injectés dans les Pods de deux manières : en tant que variables d'environnement (via `envFrom` ou `valueFrom`) ou en tant que volumes montés (un fichier par clé). L'utilisation de volumes est préférable car elle permet de mettre à jour les secrets sans redémarrer les Pods (si le montage est supporté). Pour une sécurité accrue, on peut utiliser des solutions externes comme HashiCorp Vault, AWS Secrets Manager ou Azure Key Vault, souvent intégrées via des CSI drivers ou des sidecars. Il est crucial de ne jamais commiter les secrets dans le code source ou les images Docker. De plus, l'accès aux Secrets doit être limité via RBAC. En production, activez le chiffrement au repos et utilisez des politiques de rotation régulières.
- Décrivez le cycle de vie d'un Pod de la création à la suppression.Ce qu'une bonne réponse couvre
- 1. Phase Pending : le Pod est accepté mais les conteneurs ne sont pas encore créés.
- 2. Phase Running : au moins un conteneur en cours d'exécution.
- 3. Phase Succeeded : tous les conteneurs se terminent avec succès.
- 4. Phase Failed : les conteneurs se terminent avec une erreur.
- 5. Phase Unknown : l'état du Pod n'est pas accessible.
- Les événements et conditions (PodReady, Initialized, ContainersReady, PodScheduled) détaillent la progression.
Voir un exemple de réponse
Le cycle de vie d'un Pod commence par la soumission d'une spécification (YAML/JSON) au serveur API. Le Pod entre dans la phase Pending, où le scheduler lui attribue un nœud, puis le kubelet sur ce nœud télécharge les images et démarre les conteneurs. Une fois tous les conteneurs lancés, le Pod passe en phase Running. Si un conteneur principal se termine avec un code de sortie zéro (pour les jobs par exemple), le Pod passe en Succeeded. En cas d'échec (code non nul), il passe en Failed. Si le nœud perd la communication, le Pod peut être marqué Unknown. Pendant l'exécution, les conditions (PodReady, ContainersReady, etc.) sont mis à jour. Les sondes (liveness, readiness) affectent également la vie : une liveness probe échouée redémarre le conteneur. Lors de la suppression, le Pod reçoit un signal SIGTERM, puis après un délai de grâce, SIGKILL. Les hooks preStop permettent des actions de nettoyage avant l'arrêt. Le Pod est ensuite retiré de l'API et des endpoints des Services.
- Comment scaleriez-vous un déploiement en fonction de l'utilisation du CPU en utilisant HorizontalPodAutoscaler ?Ce qu'une bonne réponse couvre
- L'HorizontalPodAutoscaler (HPA) ajuste le nombre de réplicas en fonction des métriques.
- Pour le CPU, l'HPA utilise la métrique `cpu` provenant du Metrics Server.
- Il faut définir une cible d'utilisation CPU (ex: 50%) et des limites min/max.
- L'HPA applique la formule : desiredReplicas = ceil[currentReplicas * (currentMetricValue / targetMetricValue)].
- Les métriques doivent être collectées via Metrics Server ou un adaptateur personnalisé.
Voir un exemple de réponse
Pour scaler un déploiement en fonction de l'utilisation CPU, vous utilisez un HorizontalPodAutoscaler (HPA). L'HPA interroge périodiquement les métriques (via Metrics Server) et calcule le nombre de réplicas nécessaires pour maintenir l'utilisation CPU moyenne des Pods à un niveau cible. Par exemple, si la cible est 50% et l'utilisation actuelle est 100%, le nombre de réplicas sera doublé. La formule est : desiredReplicas = ceil[currentReplicas * (currentMetricValue / targetMetricValue)]. Il est important que les conteneurs aient des requests CPU définies pour que le Metrics Server puisse calculer le pourcentage d'utilisation. L'HPA supporte également des métriques personnalisées. Pour éviter des oscillations, un cooldown (stabilisation) est appliqué. Un exemple simple de HPA pour CPU est donné ci-dessous.
Solution de référenceyaml apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: mon-app-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: mon-app minReplicas: 2 maxReplicas: 10 targetCPUUtilizationPercentage: 50
Comment se préparer
- Entraînez-vous à écrire des Dockerfiles et des manifestes YAML Kubernetes à la main sans dépendre d'outils.
- Mettez en place un cluster local avec Minikube ou kind pour expérimenter avec de vrais déploiements et services.
- Comprenez parfaitement la ligne de commande kubectl, y compris les commandes de dépannage comme kubectl describe, kubectl logs et kubectl exec.
- Apprenez les concepts de base du réseau de conteneurs et comment Kubernetes implémente le réseau avec les plugins CNI.
- Étudiez les scénarios d'entretien courants comme les mises à jour progressives, les déploiements canary et les limites de ressources des pods.
Questions fréquemment posées
Dois-je connaître à la fois Docker et Kubernetes pour les entretiens ?
Oui, la plupart des entretiens couvrent les deux. Docker est souvent un prérequis, et les questions Kubernetes supposent une aisance avec les bases des conteneurs.
Quelle est la meilleure façon de se préparer aux questions pratiques ?
Mettez en place un cluster local (Minikube/kind) et entraînez-vous à déployer des applications, à écrire du YAML à partir de zéro et à déboguer des problèmes.
À quel point les compétences en écriture de manifestes YAML sont-elles importantes ?
Très important. De nombreux entretiens incluent l'écriture ou le débogage de fichiers YAML pour les déploiements, les services et les configmaps.
Dois-je me concentrer davantage sur Docker ou Kubernetes ?
Kubernetes a généralement plus de poids, mais les fondamentaux de Docker (images, Dockerfile, compose) sont également testés.
Y a-t-il des outils spécifiques que je devrais connaître ?
Connaissez kubectl, Helm et le débogage de base avec docker logs et exec. La familiarité avec Prometheus et Grafana est un plus.
Pratiquez les questions Docker & Kubernetes avec des retours instantanés de l'IA
Téléchargez votre CV, obtenez un entretien simulé personnalisé et voyez exactement ce qu'il faut améliorer — gratuit pour commencer.