S'assurer que l'état du cluster correspond en permanence à un état désiré.
S'appuyer sur le `kube-controller-manager`. Il exécute des boucles de contrôle qui surveillent les ressources (par exemple, ReplicaSets, Deployments) et réconcilient les différences.
Pourquoi: C'est le mécanisme déclaratif et auto-réparateur essentiel. Si un Pod géré par un ReplicaSet meurt, le contrôleur le remplace automatiquement.
Attribuer automatiquement les Pods nouvellement créés au nœud de travail le plus approprié.
S'appuyer sur le `kube-scheduler`. Il filtre les nœuds en fonction des exigences des Pods (par exemple, les requêtes de ressources) et les note pour choisir le meilleur ajustement.
Pourquoi: Le scheduler prend des décisions de placement basées sur la politique, l'affinité et la disponibilité, en masquant la sélection des nœuds à l'utilisateur.
S'assurer que les conteneurs spécifiés dans les Pods sont en cours d'exécution et sains sur un nœud de travail donné.
L'agent `kubelet` s'exécute sur chaque nœud, communique avec le serveur API et gère le cycle de vie des conteneurs (démarrage, arrêt, vérifications de santé) via un runtime de conteneurs.
Pourquoi: Kubelet est le lien entre le plan de contrôle et le nœud de travail ; il exécute les spécifications des Pods.
Persister de manière fiable l'état et la configuration entiers du cluster Kubernetes.
Utiliser `etcd`, un magasin clé-valeur cohérent et hautement disponible. Il sert de source unique de vérité pour le cluster.
Pourquoi: Tous les objets du cluster (Pods, Services, etc.) sont stockés dans etcd. Seul le serveur API communique directement avec lui.
Implémenter des règles réseau sur chaque nœud pour permettre la communication via les Services Kubernetes.
Le composant `kube-proxy` sur chaque nœud maintient les règles réseau (par exemple, iptables, IPVS) qui acheminent le trafic d'une IP de Service vers les Pods backend corrects.
Pourquoi: Kube-proxy est le détail d'implémentation derrière l'abstraction Service, gérant l'équilibrage de charge et le routage.
Partitionner logiquement un seul cluster Kubernetes pour plusieurs équipes, projets ou environnements.
Créer des ressources `Namespace`. Les Namespaces fournissent une portée pour les noms et un moyen d'attacher l'autorisation et les politiques (par exemple, ResourceQuotas).
Pourquoi: Les Namespaces permettent la mutualisation et l'organisation des ressources sans la surcharge de plusieurs clusters.
Fournir un point de terminaison réseau stable (IP et DNS) pour un ensemble de Pods éphémères.
Définir une ressource `Service` qui cible un ensemble de Pods à l'aide d'un sélecteur d'étiquettes.
Pourquoi: Les Pods sont éphémères et leurs IPs changent. Un Service fournit une abstraction durable qui équilibre la charge du trafic vers les Pods corrects.
Exposer une application s'exécutant dans des Pods à différentes portées réseau.
Choisir un `type` de Service : `ClusterIP` (interne uniquement, par défaut), `NodePort` (expose sur chaque nœud IP:port), ou `LoadBalancer` (provisionne un équilibreur de charge cloud).
Pourquoi: Le type de Service détermine l'accessibilité de l'application, de purement interne à entièrement externe.
Permettre la découverte réseau directe de Pods individuels, en contournant le proxy du Service.
Créer un `Service` avec `clusterIP: None`. Cela crée des enregistrements DNS A pour chaque Pod, permettant aux clients de se connecter directement aux Pods.
Pourquoi: Essentiel pour les applications avec état comme les bases de données (souvent avec des StatefulSets) où une communication pair-à-pair ou une identité de Pod stable est requise.
Organiser et sélectionner un sous-ensemble d'objets Kubernetes.
Attacher des `labels` clé-valeur aux objets (par exemple, `app: my-api`). Utiliser des `label selectors` dans d'autres objets (par exemple, Services, Deployments) pour les cibler.
Pourquoi: Les Labels sont le mécanisme de regroupement central dans Kubernetes, permettant un couplage lâche entre les ressources.
Désolidariser la configuration de l'application de l'image du conteneur.
Stocker les données de configuration non sensibles dans un `ConfigMap`. Le monter comme un volume ou injecter des clés comme variables d'environnement dans les Pods.
Pourquoi: Cela permet de gérer la configuration indépendamment du code de l'application, suivant les principes de la 12-Factor App.
Stocker des données sensibles comme des mots de passe, des jetons ou des clés API pour l'utilisation de l'application.
Utiliser un objet `Secret`. Monter comme un volume ou injecter comme une variable d'environnement.
Pourquoi: Les Secrets sont spécifiquement destinés aux données sensibles et sont traités plus sûrement que les ConfigMaps (par exemple, non affichés par défaut dans `kubectl describe`, peuvent être chiffrés au repos).
Fournir aux applications avec état un stockage qui survit aux redémarrages de Pods.
Un Pod crée une `PersistentVolumeClaim` (PVC) pour demander du stockage. Un administrateur provisionne un `PersistentVolume` (PV) qui satisfait la demande.
Pourquoi: Cela découple la consommation de stockage (PVC) du provisionnement de stockage (PV), permettant des définitions de charge de travail portables.
Gérer l'allocation de CPU et de mémoire pour les conteneurs.
Définir `resources.requests` pour les ressources garanties (utilisées pour la planification) et `resources.limits` pour l'utilisation maximale autorisée (appliquée à l'exécution).
Pourquoi: Les requêtes garantissent que les Pods disposent de suffisamment de ressources pour fonctionner ; les limites empêchent les Pods de consommer trop de ressources et d'impacter d'autres charges de travail.
Définir des contraintes de ressources agrégées sur un namespace.
Créer un objet `ResourceQuota` pour limiter la quantité totale de CPU, de mémoire ou le nombre d'objets (Pods, Services) pouvant être créés dans un namespace.
Pourquoi: Les ResourceQuotas sont essentiels pour les environnements mutualisés afin d'assurer un partage équitable des ressources et de prévenir la surconsommation.
Gérer les ressources Kubernetes à l'aide de fichiers de configuration versionnés.
Utiliser `kubectl apply -f <filename.yaml>`. Cette commande crée ou met à jour des ressources en fonction du contenu du fichier.
Pourquoi: `apply` est déclaratif, ce qui le rend idéal pour GitOps et CI/CD. Il suit les changements et effectue une fusion à trois voies, ce qui est plus sûr que les commandes impératives `create` ou `replace`.
Diagnostiquer pourquoi un Pod ne fonctionne pas correctement (par exemple, bloqué en Pending, ContainerCreating, ou CrashLoopBackOff).
Utiliser `kubectl describe pod <nom-du-pod>`. Vérifier la section `Events` en bas pour des messages détaillés du scheduler, kubelet ou des contrôleurs.
Pourquoi: `describe` fournit un journal d'événements chronologique qui est l'outil principal pour déboguer les problèmes de cycle de vie des ressources.
Fournir des fonctionnalités réseau pour les conteneurs, permettant la communication de Pod à Pod à travers le cluster.
Utiliser un plugin Container Network Interface (CNI) (par exemple, Calico, Flannel, Cilium). Le kubelet sur chaque nœud utilise le plugin CNI pour configurer le réseau pour chaque Pod.
Pourquoi: CNI fournit une interface standard, permettant à Kubernetes d'être intégré avec diverses solutions réseau sans modifier les composants centraux.
Contrôler l'accès aux ressources de l'API Kubernetes pour les utilisateurs et les applications.
Utiliser le contrôle d'accès basé sur les rôles (RBAC). Définir un `Role` (avec portée de namespace) ou un `ClusterRole` (avec portée de cluster) avec des permissions, et le lier à un sujet (Utilisateur, Groupe, ServiceAccount) à l'aide d'un `RoleBinding` ou d'un `ClusterRoleBinding`.
Pourquoi: RBAC est la norme pour sécuriser Kubernetes, permettant le principe du moindre privilège pour toutes les interactions API.
Gérer une application sans état, permettant des mises à jour et des rollbacks faciles.
Utiliser une charge de travail `Deployment`. Il gère les ReplicaSets pour assurer qu'un nombre désiré de répliques de Pods est en cours d'exécution et fournit des stratégies de mise à jour déclaratives.
Pourquoi: Les Deployments sont la norme pour les applications sans état, masquant les détails de la mise à l'échelle et des mises à jour progressives.
Déployer une application avec état (par exemple, une base de données) qui nécessite une identité réseau et un stockage stables.
Utiliser une charge de travail `StatefulSet`. Il fournit à chaque Pod un nom d'hôte stable et unique et un stockage persistant qui le suit lors des redémarrages.
Pourquoi: Contrairement aux Deployments, les StatefulSets gèrent les Pods avec identité, assurant un déploiement et une mise à l'échelle ordonnés, ce qui est critique pour les systèmes avec état.
Déployer un agent (par exemple, collecteur de logs, agent de monitoring) sur chaque nœud du cluster.
Utiliser une charge de travail `DaemonSet`. Il garantit qu'une copie d'un Pod s'exécute sur chaque nœud (ou un sous-ensemble de nœuds).
Pourquoi: Les DaemonSets automatisent la distribution des services au niveau des nœuds, s'adaptant automatiquement aux nouveaux nœuds à mesure qu'ils rejoignent le cluster.
Exécuter une tâche finie, unique, qui doit s'exécuter jusqu'à son achèvement.
Utiliser une ressource `Job`. Elle crée un ou plusieurs Pods et s'assure qu'ils se terminent avec succès.
Pourquoi: Les Jobs sont destinés au traitement par lots, contrairement aux Deployments qui sont pour les services continus. Les Pods ne sont pas remplacés après une exécution réussie.
Exécuter une tâche selon un calendrier récurrent (par exemple, sauvegardes nocturnes, rapports).
Utiliser une ressource `CronJob`. Elle crée des Jobs basés sur une chaîne de planification cron.
Pourquoi: Les CronJobs offrent un moyen natif de Kubernetes pour gérer les tâches récurrentes basées sur le temps.
Redémarrer automatiquement un conteneur qui est devenu insensible (par exemple, blocage).
Configurer une `livenessProbe` dans la spécification du conteneur. Si la sonde échoue, le kubelet redémarre le conteneur.
Pourquoi: Les sondes de liveness fournissent un puissant mécanisme d'auto-réparation pour les applications qui peuvent rester bloquées dans un état défaillant sans planter.
Empêcher le trafic d'être envoyé à un conteneur qui n'est pas encore prêt à servir les requêtes.
Configurer une `readinessProbe` dans la spécification du conteneur. Le Pod n'est ajouté aux points de terminaison du Service qu'après que la sonde a réussi.
Pourquoi: Les sondes de readiness sont essentielles pour les mises à jour progressives sans interruption de service, garantissant que les nouveaux Pods sont entièrement initialisés avant de recevoir le trafic de production.
Exécuter des tâches de configuration ou attendre que les dépendances soient prêtes avant de démarrer le conteneur principal de l'application.
Définir un ou plusieurs `initContainers` dans la spécification du Pod. Ils s'exécutent séquentiellement jusqu'à leur achèvement avant le démarrage des conteneurs d'application.
Pourquoi: Les conteneurs Init offrent une séparation nette pour la logique de configuration, garantissant que les prérequis sont satisfaits sans encombrer le conteneur principal de l'application.
S'assurer que les Pods sont planifiés sur des nœuds avec des caractéristiques spécifiques (par exemple, des nœuds avec des GPU, des SSD).
Utiliser `nodeAffinity` dans la spécification du Pod pour définir des règles basées sur les labels des nœuds. Peut être une contrainte "requise" (dure) ou "préférée" (douce).
Pourquoi: L'affinité de nœud est plus expressive que `nodeSelector` et est la manière moderne de contrôler le placement des Pods en fonction des propriétés des nœuds.
Contrôler la co-localisation des Pods les uns par rapport aux autres pour la performance ou la haute disponibilité.
Utiliser `podAffinity` pour planifier les Pods ensemble (par exemple, sur le même nœud) ou `podAntiAffinity` pour les disperser (par exemple, sur différents nœuds ou zones).
Pourquoi: L'anti-affinité est cruciale pour garantir que les répliques d'un service ne se trouvent pas sur le même domaine de défaillance, augmentant ainsi la disponibilité.
Empêcher les Pods à usage général d'être planifiés sur des nœuds dédiés ou à usage spécial.
Appliquer un `Taint` à un nœud. Les Pods doivent avoir une `Toleration` correspondante dans leur spécification pour être planifiés sur ce nœud.
Pourquoi: Les Taints et les Tolérations garantissent que les nœuds sont réservés aux charges de travail qui sont explicitement autorisées à y s'exécuter.
Assurer une haute disponibilité en distribuant les Pods uniformément sur les domaines de défaillance comme les zones ou les nœuds.
Définir des `topologySpreadConstraints` dans la spécification du Pod pour contrôler la répartition des Pods en fonction des labels et des clés de topologie (par exemple, `topology.kubernetes.io/zone`).
Pourquoi: Cela offre un contrôle plus granulaire sur la haute disponibilité que l'anti-affinité de Pod, empêchant toutes les répliques d'être concentrées en un seul endroit.
Mettre à l'échelle automatiquement le nombre de répliques d'applications en fonction de la charge observée.
Créer une ressource `HorizontalPodAutoscaler` (HPA) qui cible un Deployment et spécifie une métrique (par exemple, l'utilisation du CPU) et une valeur cible.
Pourquoi: Le HPA permet une mise à l'échelle élastique, garantissant les performances sous charge tout en réduisant les coûts pendant les périodes creuses, sans intervention manuelle.
Ajouter ou supprimer automatiquement des nœuds de travail du cluster pour correspondre à la demande de ressources.
Déployer le `Cluster Autoscaler`. Il surveille les Pods qui ne peuvent pas être planifiés (en raison de la rareté des ressources) et ajoute des nœuds, ou supprime les nœuds sous-utilisés.
Pourquoi: Le Cluster Autoscaler gère l'élasticité au niveau de l'infrastructure, en collaboration avec les fournisseurs de cloud pour ajuster la taille du cluster en fonction des besoins de la charge de travail.
Garantir qu'un nombre minimum de répliques d'applications reste disponible pendant les interruptions volontaires (par exemple, les mises à niveau de nœuds).
Créer un `PodDisruptionBudget` (PDB) spécifiant `minAvailable` ou `maxUnavailable` pour un ensemble de Pods.
Pourquoi: Les PDBs empêchent des actions comme `kubectl drain` de mettre hors service trop de répliques à la fois, protégeant la disponibilité de l'application.
Effectuer une mise à jour sans interruption de service pour une application sans état.
Utiliser un `Deployment` avec la stratégie par défaut `RollingUpdate`. Configurer `maxSurge` et `maxUnavailable` pour contrôler le processus de mise à jour.
Pourquoi: Les mises à jour progressives remplacent progressivement les anciens Pods par de nouveaux, garantissant que le service reste disponible tout au long de la mise à jour.
Livraison d'Applications Cloud Native
Gérer les déploiements d'infrastructure et d'applications de manière déclarative avec le contrôle de version et un journal d'audit.
Implémenter GitOps. Utiliser un dépôt Git comme source unique de vérité. Utiliser un outil comme Argo CD ou Flux pour synchroniser automatiquement l'état du cluster avec Git.
Pourquoi: GitOps fournit un historique clair et auditable de tous les changements et permet des rollbacks faciles en annulant les commits Git. Il opérationnalise l'Infrastructure as Code.
Packager, configurer et déployer des applications Kubernetes complexes de manière réutilisable et versionnée.
Utiliser `Helm`, le gestionnaire de paquets pour Kubernetes. Packager les applications sous forme de `Charts` avec des manifestes templatisés et des fichiers `values.yaml` configurables.
Pourquoi: Helm simplifie la gestion des applications complexes avec de nombreux composants, gérant les dépendances, le versionnement et la gestion du cycle de vie.
Personnaliser les manifestes Kubernetes pour différents environnements sans utiliser de templates.
Utiliser `Kustomize`. Définir un fichier `kustomization.yaml` qui spécifie une configuration de base et applique des patchs ou des overlays pour chaque environnement.
Pourquoi: Kustomize offre un moyen déclaratif et sans template de gérer les variantes de configuration, ce qui peut être plus simple et moins sujet aux erreurs que le templating basé sur du texte.
Tester une nouvelle version d'application avec un petit sous-ensemble de trafic de production avant un déploiement complet.
Déployer la nouvelle version à côté de l'ancienne. Utiliser un service mesh ou un contrôleur Ingress pour acheminer un petit pourcentage du trafic (par exemple, 5%) vers la nouvelle version "canary".
Pourquoi: Les releases Canary réduisent le risque d'introduire une mauvaise version en limitant le rayon d'impact et en permettant des tests en production.
Déployer une nouvelle version d'application avec zéro temps d'arrêt et une capacité de rollback instantanée.
Déployer la nouvelle version "verte" à côté de la version "bleue" existante. Une fois la version verte vérifiée, basculer 100% du trafic du bleu au vert au niveau du Service/routeur.
Pourquoi: Les déploiements bleu-vert éliminent les temps d'arrêt. Le rollback est aussi simple que de rebasculer le trafic vers l'environnement bleu.
Architecture Cloud Native
Concevoir une application complexe comme une collection de services petits, indépendants et faiblement couplés.
Structurer l'application en microservices, chacun organisé autour d'une capacité métier. Chaque service doit posséder ses propres données et communiquer via des APIs bien définies.
Pourquoi: Cette architecture permet le développement, le déploiement et la mise à l'échelle indépendants des services, améliorant l'agilité et la résilience.
Construire une application portable, scalable et cloud-native en suivant les meilleures pratiques établies.
Adhérer à la méthodologie Twelve-Factor App. Un principe clé est de stocker toute la configuration qui varie entre les environnements dans des variables d'environnement.
Pourquoi: Cela sépare strictement la configuration du code, permettant à la même image de conteneur d'être promue entre les environnements sans modifications.
Gérer la communication complexe service-à-service, en fournissant la gestion du trafic, la sécurité et l'observabilité.
Implémenter un service mesh (par exemple, Istio, Linkerd). Il injecte un proxy sidecar dans chaque Pod pour intercepter et gérer tout le trafic réseau.
Pourquoi: Un service mesh abstrait les préoccupations réseau (mTLS, tentatives, coupe-circuits) du code d'application, les appliquant au niveau de la plateforme.
Étendre ou améliorer la fonctionnalité d'un conteneur d'application sans modifier son code.
Déployer un conteneur "sidecar" dans le même Pod que l'application principale. Il partage le même réseau et le même stockage.
Pourquoi: Les sidecars sont utilisés pour les préoccupations transversales comme la journalisation, le monitoring ou le proxy (comme dans un service mesh), favorisant la séparation des préoccupations.
Obtenir une compréhension approfondie du comportement d'un système distribué pour faciliter le dépannage.
Mettre en œuvre les trois piliers de l'observabilité : les `Metrics` (données numériques agrégées), les `Logs` (événements discrets) et les `Traces` (flux de requêtes de bout en bout).
Pourquoi: Ensemble, ces types de données offrent une vue complète de la santé et des performances du système, ce qui est essentiel pour les architectures de microservices complexes.