## Introduction Lorsqu'un Service Kubernetes ne route plus correctement le trafic, la cause profonde se cache souvent dans ses objets EndpointSlice. Ces petites ressources API répertorient les adresses IP et les ports des pods prêts afin que kube-proxy et les contrôleurs d'ingrès puissent transmettre les requêtes. Si un EndpointSlice est supprimé accidentellement, corrompu par un mauvais manifeste ou perdu lors d'une migration de cluster, le Service devient un trou noir : aucune erreur n'apparaît sur le Service lui-même, mais chaque requête se bloque ou échoue. Ce guide présente des procédures pratiques de sauvegarde, de restauration et de validation des objets EndpointSlice. Il couvre la détection de version, l'inventaire de l'environnement, les modifications de configuration sûres, les diagnostics, les modes de défaillance et une liste de contrôle opérationnelle. Chaque section comprend des commandes concrètes, les résultats attendus et les décisions de reprise. L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets, vérifier le résultat et documenter la procédure de reprise si l'état attendu n'est pas atteint. Cet article s'adresse aux développeurs, aux consultants DevOps et aux équipes techniques de startups qui exécutent Kubernetes en production ou en préproduction. Il suppose une familiarité de base avec kubectl et les concepts de mise en réseau essentiels, mais aucune expérience préalable des EndpointSlices n'est requise. ## Inventaire de la version et de l'environnement Avant de toucher aux EndpointSlices, confirmez ce qui s'exécute dans le cluster. Les EndpointSlices sont devenus stables dans Kubernetes 1.21, et les clusters plus anciens peuvent encore s'appuyer sur des objets Endpoints. La procédure de sauvegarde et de restauration diffère selon l'objet présent. Commencez par un inventaire en lecture seule. Exécutez les commandes suivantes pour capturer l'état actuel : ```bash kubectl version --short kubectl get nodes -o wide kubectl get services --all-namespaces kubectl get endpointslices --all-namespaces ``` Le résultat attendu de `kubectl get endpointslices --all-namespaces` sur un cluster sain ressemble à ceci : ```text NAMESPACE NAME ADDRESSTYPE PORTS ENDPOINTS AGE default nginx-service-abcde IPv4 80 3 2d kube-system kube-dns-xyz12 IPv4 53 2 30d ``` Si aucun EndpointSlice n'apparaît alors que des Services existent, le cluster utilise peut-être des Endpoints hérités. Vérifiez avec `kubectl get endpoints --all-namespaces`. Dans Kubernetes 1.21 et versions ultérieures, les Endpoints et les EndpointSlices coexistent, mais kube-proxy utilise les EndpointSlices par défaut. Notez la version exacte de Kubernetes, car le comportement de restauration change entre les versions. Par exemple, dans Kubernetes 1.22, le champ `addressType` d'EndpointSlice était défini par défaut sur `IPv4`, tandis que dans la version 1.25, le champ prend en charge `IPv4`, `IPv6` et `FQDN`. Sauvegarder sur la version 1.22 et restaurer sur la 1.25 peut nécessiter d'ajuster le manifeste. Capturez également les libellés et les références de propriétaire actuels des EndpointSlices. La référence de propriétaire lie un EndpointSlice à son Service. Sans une référence de propriétaire correcte, l'EndpointSlice risque de ne pas être collecté par le ramasse-miettes ou d'être ignoré par les contrôleurs. Utilisez : ```bash kubectl get endpointslices -n default -o yaml ``` Inspectez la sortie pour `ownerReferences` et `labels.kubernetes.io/service-name`. S'ils sont absents, l'EndpointSlice est orphelin et doit être traité comme un candidat à la sauvegarde manuelle. Conditions préalables à une sauvegarde sûre : - Accès en lecture à tous les espaces de noms où des Services sont déployés. - Version de kubectl correspondant à la version mineure du cluster (dans un écart d'une version mineure). - Un répertoire accessible en écriture pour les fichiers de sauvegarde, tel que `/var/backups/k8s-endpointslices`. - Aucune modification active des Services ou des Pods pendant la sauvegarde (ou utilisez une fenêtre de maintenance). Une petite étape de vérification avant toute modification : exécutez `kubectl get endpointslices -n default -o jsonpath='{.items[*].metadata.name}'` et comparez la sortie avec les noms des Services. Chaque Service doit avoir au moins un EndpointSlice associé. Si un Service n'a aucun EndpointSlice, le trafic vers celui-ci échouera ; c'est le premier signal de défaillance. ## Chemin de configuration sûr La sauvegarde des EndpointSlices est une opération de lecture, mais leur restauration est une opération d'écriture. Le chemin le plus sûr consiste à restaurer d'abord dans un espace de noms temporaire, à vérifier que les objets sont créés correctement, puis à les déplacer vers l'espace de noms cible uniquement après confirmation. ### Procédure de sauvegarde Utilisez `kubectl get` avec `-o yaml` pour exporter tous les EndpointSlices d'un espace de noms. Par exemple : ```bash mkdir -p /var/backups/k8s-endpointslices/default kubectl get endpointslices -n default -o yaml > /var/backups/k8s-endpointslices/default/all-endpointslices.yaml ``` Ce fichier contient l'état en direct complet, y compris `metadata.resourceVersion` et `metadata.uid`. Ces champs sont spécifiques au cluster et doivent être supprimés avant une restauration dans un autre cluster. Une sauvegarde plus sûre supprime les champs dynamiques : ```bash kubectl get endpointslices -n default -o yaml | grep -v 'resourceVersion\|uid\|creationTimestamp\|generation' > /var/backups/k8s-endpointslices/default/all-endpointslices-clean.yaml ``` Cependant, ce simple `grep` peut supprimer des lignes à l'intérieur de la spécification des conteneurs si des noms de champs correspondent. Une méthode plus fiable utilise `kubectl get --export`, mais ce drapeau est obsolète. L'approche recommandée est d'utiliser un outil comme `kubectl neat` (du projet `itaysk/kubectl-neat`) ou d'écrire un petit script jq : ```bash kubectl get endpointslices -n default -o json | jq 'del(.items[].metadata.resourceVersion, .items[].metadata.uid, .items[].metadata.creationTimestamp, .items[].metadata.generation)' > /var/backups/k8s-endpointslices/default/all-endpointslices-clean.json ``` Stockez la sauvegarde dans un système de contrôle de version ou un magasin d'objets chiffré. Pour la reprise après sinistre, conservez des sauvegardes à la fois des objets EndpointSlice et des objets Service associés, car les EndpointSlices sont généralement détenus par les Services et sont recréés par le contrôleur EndpointSlice. ### Procédure de restauration (essai à blanc d'abord) Avant d'appliquer une sauvegarde, testez la restauration dans un espace de noms de test. Créez un espace de noms `restore-test` et appliquez la sauvegarde nettoyée avec `--dry-run=server` : ```bash kubectl create namespace restore-test kubectl apply -f /var/backups/k8s-endpointslices/default/all-endpointslices-clean.yaml -n restore-test --dry-run=server ``` Sortie attendue pour une restauration valide : ```text endpointslice.discovery.k8s.io/nginx-service-abcde created (server dry run) ``` Si la sortie affiche des erreurs concernant des champs manquants ou des adresses invalides, corrigez le fichier de sauvegarde avant de continuer. Appliquez ensuite réellement dans l'espace de noms de test : ```bash kubectl apply -f /var/backups/k8s-endpointslices/default/all-endpointslices-clean.yaml -n restore-test ``` Vérifiez que les points de terminaison sont renseignés : ```bash kubectl get endpointslices -n restore-test -o wide ``` La colonne `ENDPOINTS` doit afficher le même nombre d'adresses IP de pods prêts que l'original. Si l'original avait 3 points de terminaison, la tranche restaurée doit également en afficher 3. Après vérification, supprimez l'espace de noms de test : ```bash kubectl delete namespace restore-test ``` Enfin, restaurez dans l'espace de noms cible uniquement si le Service n'a pas déjà d'EndpointSlice. Si le Service existe et que son EndpointSlice est manquant, l'application de la sauvegarde le recréera ; le contrôleur EndpointSlice peut également le recréer automatiquement en quelques minutes. Vérifiez avec : ```bash kubectl get endpointslices -n default -l kubernetes.io/service-name=nginx-service ``` Si la sauvegarde a réussi, la sortie doit afficher la tranche avec les bons libellés et points de terminaison. Si le contrôleur la recrée en premier, la sauvegarde appliquée peut entrer en conflit. Observez toujours l'état actuel avant d'appliquer une restauration. ### Stratégie de retour en arrière Si une restauration cause des problèmes (par exemple, des adresses IP de points de terminaison erronées parce que les pods ont changé), supprimez l'EndpointSlice restauré et laissez le contrôleur le recréer à partir de l'état actuel des pods : ```bash kubectl delete endpointslice -n default nginx-service-abcde ``` En quelques secondes, le contrôleur EndpointSlice créera une nouvelle tranche basée sur l'état de préparation actuel des pods. C'est le retour en arrière le plus rapide pour une tranche corrompue, mais il repose sur le bon fonctionnement du contrôleur. Si le contrôleur est défaillant, restaurez plutôt à partir d'une sauvegarde reconnue comme bonne. ## Vérification et diagnostics La vérification de la santé d'un EndpointSlice va au-delà de la simple existence de l'objet. La tranche doit avoir des points de terminaison prêts, des ports corrects et des libellés correspondants. Utilisez les vérifications de diagnostic suivantes. ### Vérifier la connectivité de l'EndpointSlice Le test de bout en bout le plus simple consiste à faire un curl sur un Service qui utilise la tranche. Pour un Service de type ClusterIP : ```bash kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- curl -v http://nginx-service.default.svc.cluster.local ``` La sortie attendue inclut `HTTP/1.1 200 OK` si les points de terminaison sont sains. Si la connexion se bloque ou renvoie `502 Bad Gateway`, l'EndpointSlice peut être vide ou contenir des adresses IP obsolètes. Inspectez directement le contenu de la tranche : ```bash kubectl get endpointslices -n default nginx-service-abcde -o yaml ``` Recherchez le tableau `endpoints`. Chaque point de terminaison doit avoir un champ `addresses` avec une adresse IP de pod et un champ `conditions.ready` défini sur `true`. Si `ready` est `false` ou manquant, le pod n'est pas prêt et le trafic ne sera pas routé. Exemple d'entrée de point de terminaison sain : ```yaml endpoints: - addresses: - 10.244.1.5 conditions: ready: true serving: true terminating: false targetRef: kind: Pod name: nginx-deployment-6d4cf56db6-abcde namespace: default ``` Si `ready` est `false`, vérifiez l'état du pod avec `kubectl get pods -n default -o wide`. Le pod peut être en `CrashLoopBackOff` ou `Pending`. Résolvez le problème avec `kubectl describe pod ` et `kubectl logs --previous`. ### Valider les mappages de ports Les EndpointSlices stockent les numéros de port et les protocoles. Confirmez qu'ils correspondent à la définition du Service. Comparez : ```bash kubectl get service nginx-service -n default -o yaml kubectl get endpointslice nginx-service-abcde -n default -o yaml ``` Les `ports` du Service doivent correspondre exactement aux `ports` de l'EndpointSlice. Par exemple, un Service avec `port: 80, targetPort: 8080` devrait avoir un EndpointSlice avec `ports: [{name: http, port: 8080, protocol: TCP}]`. Si le targetPort est absent ou incorrect, le trafic sera envoyé vers le mauvais port de conteneur. ### Diagnostiquer les problèmes du contrôleur Si les EndpointSlices ne sont pas créés ou mis à jour, vérifiez les journaux du contrôleur EndpointSlice dans kube-controller-manager. Sur un cluster géré (EKS, GKE, AKS), vous ne pouvez pas accéder directement aux journaux du contrôleur, mais vous pouvez vérifier les événements : ```bash kubectl get events -n default --sort-by='.lastTimestamp' ``` Recherchez les événements `FailedCreateEndpointSlice` ou `FailedUpdateEndpointSlice`. S'ils sont présents, le contrôleur peut manquer de permissions ou le serveur d'API peut rejeter la tranche en raison de champs invalides. Sur un cluster autogéré, consultez les journaux du contrôleur : ```bash kubectl logs -n kube-system kube-controller-manager- | grep endpointslice ``` Des erreurs telles que `endpointslice controller: error syncing service` indiquent une boucle de contrôleur défaillante. Redémarrer le pod kube-controller-manager peut résoudre le problème. ## Modes de défaillance et reprise Comprendre les modes de défaillance courants aide à planifier la reprise. Voici les scénarios les plus fréquents et les étapes de reprise concrètes. ### Suppression accidentelle d'un EndpointSlice Un opérateur exécute par erreur `kubectl delete endpointslice -n default nginx-service-abcde`. Le Service existe toujours, mais le trafic échoue car aucun point de terminaison n'est disponible. Reprise : - Restaurez immédiatement à partir de la sauvegarde : `kubectl apply -f /var/backups/k8s-endpointslices/default/nginx-service-abcde.yaml` - Si aucune sauvegarde n'existe, supprimez et recréez le Service pour forcer le contrôleur à générer une nouvelle tranche : `kubectl delete service nginx-service -n default && kubectl apply -f nginx-service.yaml` - Ou attendez : dans la plupart des clusters, le contrôleur EndpointSlice recrée une tranche supprimée en 1 à 2 minutes, tant que le Service existe encore et que les pods sont prêts. ### Adresses IP obsolètes après le redémarrage d'un pod Un pod redémarre et obtient une nouvelle adresse IP, mais l'EndpointSlice affiche toujours l'ancienne adresse IP. Cela peut se produire si le contrôleur EndpointSlice est en retard ou si une mise à jour manuelle a défini une mauvaise adresse. Le trafic peut être envoyé vers un pod mort et expirer. Reprise : - Forcez le contrôleur à se resynchroniser en supprimant l'EndpointSlice : `kubectl delete endpointslice -n default nginx-service-abcde` - Le contrôleur créera une nouvelle tranche avec les adresses IP actuelles des pods. - Si le contrôleur est défaillant, modifiez manuellement la tranche avec `kubectl edit endpointslice -n default nginx-service-abcde` et mettez à jour le champ `addresses`. ### EndpointSlice non créé pour un nouveau Service Un nouveau Service est déployé, mais `kubectl get endpointslices` n'affiche rien. Cela signifie généralement que le sélecteur du Service ne correspond à aucun pod. Reprise : - Vérifiez le sélecteur du Service : `kubectl get service new-service -n default -o yaml | grep selector -A3` - Vérifiez les pods avec des libellés correspondants : `kubectl get pods -n default -l app=new-app` - Si aucun pod ne correspond, mettez à jour le sélecteur du Service ou les libellés des pods. - Après correction, attendez quelques secondes et vérifiez à nouveau. Le contrôleur devrait créer la tranche automatiquement. ### EndpointSlice invalide après une modification manuelle Une modification manuelle corrompt la tranche, par exemple en définissant `port: 9999` alors que le conteneur écoute sur 8080. Le trafic échoue avec une connexion refusée. Reprise : - Restaurez à partir de la sauvegarde : `kubectl apply -f /var/backups/k8s-endpointslices/default/nginx-service-abcde.yaml` - Ou supprimez la tranche et laissez le contrôleur la recréer. ### Reprise après sinistre après la perte du cluster Si l'ensemble du cluster est perdu et doit être reconstruit à partir des sauvegardes, les EndpointSlices seuls ne suffisent pas. La sauvegarde doit inclure les objets Service, les Deployments et d'autres ressources. Étapes de reprise : 1. Reconstruisez le cluster et configurez la mise en réseau. 2. Appliquez tous les manifestes Deployment et StatefulSet. 3. Appliquez les manifestes Service. 4. Attendez que les pods deviennent prêts. 5. Le contrôleur EndpointSlice créera les tranches automatiquement. Ne restaurez pas les anciens EndpointSlices, car leurs adresses IP de pods sont obsolètes par rapport à l'ancien cluster. 6. Ne restaurez les EndpointSlices manuellement que si le contrôleur est désactivé ou si le cluster utilise un proxy de service personnalisé qui n'utilise pas les EndpointSlices. ## Liste de contrôle opérationnelle Utilisez cette liste de contrôle avant et après toute opération de sauvegarde ou de restauration d'EndpointSlice. Remplacez les valeurs d'exemple par les vôtres. | # | Étape | Commande / Action | Résultat attendu | Responsable | |---|-------|-------------------|------------------|-------------| | 1 | Enregistrer la version de Kubernetes | `kubectl version --short` | Version 1.24.0 ou supérieure | Priya Shah, responsable ingénierie | | 2 | Lister tous les EndpointSlices | `kubectl get endpointslices --all-namespaces` | Liste non vide pour chaque Service | Priya Shah | | 3 | Sauvegarder toutes les tranches | `kubectl get endpointslices -n default -o yaml > backup.yaml` | Fichier créé, aucune erreur | Priya Shah | | 4 | Supprimer les champs dynamiques | Utiliser `kubectl neat` ou jq | Fichier sans resourceVersion, uid | Priya Shah | | 5 | Tester la restauration dans un espace de noms de test | `kubectl apply -f backup.yaml -n restore-test --dry-run=server` | Aucune erreur | Priya Shah | | 6 | Appliquer la restauration | `kubectl apply -f backup.yaml -n default` | EndpointSlice créé | Priya Shah | | 7 | Vérifier les points de terminaison | `kubectl get endpointslices -n default -o wide` | ENDPOINTS correspond à l'original | Priya Shah | | 8 | Tester la connectivité | `curl http://nginx-service.default.svc.cluster.local` | HTTP 200 | Priya Shah | | 9 | Valider la sauvegarde dans git | `git add backup.yaml && git commit` | Sauvegarde versionnée | Priya Shah | | 10 | Documenter les étapes de reprise | Mettre à jour le runbook | Le runbook inclut un plan de retour en arrière | Priya Shah | Conservez cette liste de contrôle dans le runbook de votre équipe. Chaque opérateur doit savoir où les sauvegardes sont stockées, comment restaurer et comment vérifier sans causer de perturbations supplémentaires. ## Conclusion La sauvegarde et la restauration des EndpointSlices Kubernetes ne sont pas des procédures complexes, mais elles exigent de la discipline. Les objets sont petits et souvent gérés automatiquement, ce qui pousse de nombreuses équipes à les ignorer jusqu'à ce qu'une panne de Service révèle la lacune. En suivant les étapes de ce guide, vous pouvez créer des sauvegardes fiables, tester les restaurations en toute sécurité, diagnostiquer les défaillances courantes et récupérer rapidement. Commencez par une vérification à faible risque : choisissez un Service dans un espace de noms de développement, sauvegardez son EndpointSlice, supprimez-le et restaurez-le à partir de la sauvegarde. Chronométrez la durée du processus et documentez les erreurs éventuelles. Étendez ensuite la procédure aux espaces de noms de production avec des contrôles de changement appropriés. N'oubliez pas que les EndpointSlices ne sont qu'une partie de la chaîne de routage des Services. Des dépendances telles que kube-proxy, CoreDNS et le contrôleur EndpointSlice interagissent toutes. Lors du dépannage, considérez l'ensemble de la pile, mais gardez vos procédures de sauvegarde et de restauration ciblées et versionnées. Un flux de travail technique fiable rend les défaillances visibles, protège les valeurs sensibles, limite les modifications à la ressource prévue et définit la vérification de la reprise avant qu'un incident ne force la décision. Avec ce guide, vous disposez des commandes et des listes de contrôle pour mettre en œuvre ce flux de travail pour les EndpointSlices dès aujourd'hui.