## Introduction

Lorsque le trafic réseau est bloqué ou autorisé de manière inattendue dans Kubernetes, les Network Policies sont souvent les premières suspectes. Pourtant, leur dépannage peut être frustrant car elles sont silencieuses : aucun journal, aucun événement, aucun message d'erreur évident. Ce guide propose une approche pratique, basée sur des exemples, pour diagnostiquer et corriger les problèmes de Network Policies. Il s'adresse aux développeurs, ingénieurs DevOps et équipes plateforme.

Nous commencerons par comprendre les prérequis et l'environnement, puis nous aborderons les pratiques de configuration sûres, les techniques de vérification, les modes de défaillance et une liste de contrôle de dépannage reproductible. Tout au long du guide, vous trouverez des commandes `kubectl` concrètes, des exemples YAML et les sorties attendues pour vous aider à passer du problème à la résolution rapidement et en toute confiance.

À la fin de ce guide, vous serez capable de :

- Déterminer si une Network Policy est réellement la cause d'un problème de connectivité.
- Inspecter et valider les ressources Network Policy.
- Tester la connectivité de manière contrôlée.
- Mettre en œuvre des corrections avec un impact minimal.
- Vérifier que la correction fonctionne et documenter les étapes de récupération.

Nous supposons que vous disposez d'un cluster Kubernetes opérationnel et d'une familiarité de base avec `kubectl`.

## Inventaire de la version et de l'environnement

Avant de modifier toute configuration, établissez l'environnement exact. Cela évite les erreurs de diagnostic et garantit que toute correction est adaptée à la version de votre cluster et à votre plugin réseau.

**Étapes clés :**

1. **Vérifier la version de Kubernetes :**
   ```bash
   kubectl version --short
   ```
   Sortie attendue (exemple) :
   ```
   Client Version: v1.28.2
   Server Version: v1.28.2
   ```

2. **Identifier le plugin CNI et vérifier la prise en charge des Network Policies :** Les Network Policies sont appliquées par le fournisseur CNI (par exemple, Calico, Cilium, Weave, Antrea). Certains plugins ont des limitations. Vérifiez les pods du plugin :
   ```bash
   kubectl get pods -n kube-system | grep -E 'calico|cilium|weave|antrea'
   ```
   Exemple de sortie :
   ```
   calico-node-abcde                  1/1     Running   0          10d
   calico-kube-controllers-12345      1/1     Running   0          10d
   ```

3. **Confirmer la disponibilité de l'API NetworkPolicy :**
   ```bash
   kubectl api-resources | grep networkpolicies
   ```
   Exemple de sortie :
   ```
   networkpolicies                   netpol       networking.k8s.io/v1       true         NetworkPolicy
   ```

4. **Lister les Network Policies existantes dans l'espace de noms concerné :**
   ```bash
   kubectl get networkpolicies -n <namespace>
   ```
   Exemple (namespace `default`) :
   ```
   NAME            POD-SELECTOR          AGE
   deny-all        <none>                5d
   allow-web       app=web               2d
   ```

5. **Vérifier les libellés de l'espace de noms :** Les Network Policies reposent souvent sur des sélecteurs de namespace. Vérifiez les libellés :
   ```bash
   kubectl get namespace <namespace> --show-labels
   ```

6. **Inspecter les pods impliqués dans le problème de connectivité :**
   ```bash
   kubectl get pods -n <namespace> -o wide
   ```
   Notez les adresses IP des pods et leur placement sur les nœuds. Si les pods sont sur des nœuds différents, assurez-vous que le CNI fonctionne entre les nœuds.

Un piège courant est de supposer que la Network Policy est le problème alors qu'en réalité le CNI ne l'applique pas (par exemple, parce que le plugin n'est pas installé ou est mal configuré). Vérifiez toujours que les pods CNI sont sains et que la CRD de politique est présente.

## Chemin de configuration sûr

Apporter des modifications aux Network Policies peut avoir des effets immédiats sur le trafic en production. Suivez une approche sûre et incrémentale :

1. **Commencer par une évaluation en lecture seule :** Utilisez `kubectl describe` et `kubectl get -o yaml` pour comprendre les politiques actuelles.
   ```bash
   kubectl describe networkpolicy <policy-name> -n <namespace>
   ```
   Extrait de sortie :
   ```
   Spec:
     PodSelector:     app=web
     Ingress:
       From:
         PodSelector: app=api
       Ports:
         Port: 80
         Protocol: TCP
   ```

2. **Sauvegarder les politiques existantes avant les modifications :**
   ```bash
   kubectl get networkpolicy <policy-name> -n <namespace> -o yaml > policy-backup.yaml
   ```

3. **Apporter des modifications minimales :** Au lieu de réécrire toute la politique, ajustez uniquement le sélecteur ou la règle nécessaire. Par exemple, si vous devez autoriser le trafic à partir d'un nouveau namespace, ajoutez un `ipBlock` ou `namespaceSelector` sans perturber les règles existantes.

4. **Tester d'abord dans un namespace non productif :** Reproduisez la configuration dans un namespace de test et vérifiez le comportement avant de l'appliquer en production.

5. **Appliquer la modification et surveiller :** Utilisez `kubectl apply -f new-policy.yaml` puis testez immédiatement la connectivité.

**Exemple : Ajout d'une règle d'autorisation pour un namespace de supervision**

Politique d'origine (refuse tout trafic entrant vers `app=web`) :
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
```

Politique révisée pour autoriser le trafic entrant depuis le namespace `monitoring` sur le port 9090 :
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          purpose: monitoring
    ports:
    - port: 9090
      protocol: TCP
  policyTypes:
  - Ingress
```

Appliquer et vérifier :
```bash
kubectl apply -f revised-policy.yaml
kubectl get networkpolicy deny-all -n default -o yaml
```

**Piège :** Oublier que les Network Policies sont additives mais que leurs sélecteurs sont combinés par OU au sein d'une règle et par ET entre les règles. Une petite modification peut ouvrir ou fermer du trafic par inadvertance. Examinez toujours la politique complète après l'édition.

## Vérification et diagnostics

Pour confirmer si une Network Policy cause un problème, vous devez tester la connectivité d'un pod à un autre. Utilisez ces techniques :

1. **Créer un pod de test avec des outils réseau :**
   ```bash
   kubectl run test-pod --rm -it --image=nicolaka/netshoot -- /bin/bash
   ```
   Dans le pod, utilisez `curl`, `wget`, `nc` ou `telnet` pour tester les connexions.

2. **Tester la connectivité vers un service depuis l'intérieur du cluster :**
   ```bash
   kubectl exec -it <source-pod> -n <namespace> -- curl -v http://<service-name>.<namespace>.svc.cluster.local:80
   ```
   Sortie attendue si bloqué :
   ```
   *   Trying 10.96.0.10:80...
   * connect to 10.96.0.10 port 80 failed: Connection timed out
   ```
   Sortie attendue si autorisé :
   ```
   * Connected to 10.96.0.10 (10.96.0.10) port 80
   > GET / HTTP/1.1
   ...
   < HTTP/1.1 200 OK
   ```

3. **Vérifier si le trafic est bloqué en testant directement l'IP du pod :**
   Obtenez l'IP du pod cible :
   ```bash
   kubectl get pod <target-pod> -n <namespace> -o wide
   ```
   Puis à partir du pod source :
   ```bash
   curl http://<target-pod-ip>:80
   ```
   Si le service fonctionne mais que l'IP directe du pod échoue, la politique pourrait sélectionner les endpoints du service différemment.

4. **Inspecter les événements et journaux de la Network Policy :** Les Network Policies elles-mêmes ne produisent pas d'événements, mais le CNI peut journaliser les rejets. Pour Calico, vérifiez les journaux de `calico-node` :
   ```bash
   kubectl logs -n kube-system <calico-node-pod> | grep -i drop | tail -20
   ```
   Cela peut montrer les flux refusés avec les adresses IP source et destination.

5. **Utiliser `kubectl describe` pour voir si la politique s'applique aux bons pods :**
   La politique effective n'est pas dynamique ; elle dépend des sélecteurs. Vérifiez que le pod cible correspond au `podSelector` de la politique.
   ```bash
   kubectl get pods -n <namespace> --show-labels
   kubectl describe networkpolicy <policy-name> -n <namespace>
   ```

**Scénario réel :** Un développeur s'est plaint qu'un pod web ne pouvait pas atteindre un pod de base de données. Nous avons constaté que le pod de base de données avait le libellé `app=db`, mais que la Network Policy sélectionnait `app=database`. La politique ne s'appliquait pas et une autre politique de refus global bloquait le trafic. La correction du libellé a résolu le problème.

## Modes de défaillance et récupération

Détaillons les modes de défaillance courants et comment s'en remettre.

### 1. Politique non appliquée (le trafic circule toujours)

**Symptôme :** Vous avez appliqué une politique de refus global, mais le trafic continue de passer.

**Causes :**
- Le CNI ne prend pas en charge les Network Policies.
- La politique se trouve dans un namespace différent des pods ciblés.
- Le `podSelector` de la politique ne correspond à aucun pod.
- Il manque `policyTypes` dans la politique (par défaut, seul `Ingress` est appliqué).

**Diagnostic :**
```bash
kubectl get networkpolicy -A
kubectl describe networkpolicy <policy-name> -n <namespace>
kubectl get pods -n <namespace> --show-labels
```

**Récupération :** Corrigez le sélecteur ou le namespace. Assurez-vous que le `podSelector` de la politique correspond aux pods visés. Si vous utilisez un sélecteur de namespace, assurez-vous que le namespace possède les bons libellés.

### 2. Trafic bloqué de manière inattendue

**Symptôme :** Après l'application d'une politique, un trafic légitime échoue.

**Causes :**
- Règle d'entrée manquante pour une source requise.
- Règle d'entrée avec un champ `from` vide (ce qui signifie ne rien autoriser, et non tout autoriser).
- Inadéquation du port (par exemple, le service utilise 8080 mais la politique autorise 80).
- Utilisation d'`ipBlock` avec un mauvais CIDR.

**Diagnostic :** Testez la connectivité, examinez attentivement le YAML de la politique, comparez avec la définition du service.

**Récupération :** Modifiez la politique pour ajouter la règle nécessaire. En cas de doute, supprimez temporairement la politique pour rétablir le trafic, puis réappliquez-la progressivement.

**Exemple :**
Une politique destinée à autoriser uniquement le trafic à l'intérieur du namespace a accidentellement inclus un `podSelector: {}` (vide), qui sélectionne tous les pods du namespace, autorisant ainsi tout le trafic du namespace. C'est une erreur courante. Pour n'autoriser que des pods spécifiques, utilisez leurs libellés.

### 3. La politique s'applique mais la connectivité est partielle

**Symptôme :** Certains trafics fonctionnent, d'autres échouent.

**Causes :** Plusieurs politiques se combinent ; certaines règles sont en conflit. Des règles de sortie peuvent manquer si vous avez appliqué un refus de sortie sans autoriser le DNS (UDP 53) ou les adresses IP requises.

**Diagnostic :** Listez toutes les politiques du namespace et examinez leur effet combiné. Utilisez `kubectl get networkpolicy -n <namespace>` puis `describe` pour chacune. Des outils comme `kubectl-neat` ou des visualiseurs (par exemple, Octant, Lens) peuvent aider.

**Récupération :** Ajustez les politiques pour inclure les règles manquantes. Pour la sortie, n'oubliez pas d'autoriser le DNS et tout point de terminaison externe nécessaire.

### 4. Les journaux CNI montrent des rejets mais la politique semble correcte

**Symptôme :** Les journaux Calico/Cilium montrent des paquets refusés, mais la politique semble les autoriser.

**Causes :** L'ordre des politiques ? Non applicable, les Network Policies sont additives. Plus probablement : l'IP source ou destination dans le journal de rejet ne correspond pas aux pods que vous pensez en communication. Cela peut être une IP de service (ClusterIP) utilisée comme destination ; la Network Policy s'applique aux IP de pods, pas aux IP de service, mais le CNI peut rejeter si le pod backend n'est pas autorisé.

**Diagnostic :** Vérifiez les IP réelles des pods et le flux. Utilisez `kubectl get endpoints <service>` pour voir les IP des pods backend.

**Récupération :** Assurez-vous que la politique autorise le trafic vers les pods backend depuis les pods source.

## Liste de contrôle des opérations

Utilisez cette liste pour un dépannage systématique :

| Étape | Action | Commande / Vérification | Résultat attendu |
|-------|--------|--------------------------|------------------|
| 1 | Vérifier le cluster et le CNI | `kubectl get pods -n kube-system` | Tous les pods CNI en Running |
| 2 | Confirmer l'API NetworkPolicy | `kubectl api-resources \| grep networkpolicies` | Ressource listée |
| 3 | Identifier les pods affectés et leurs libellés | `kubectl get pods -n <ns> --show-labels` | Les libellés correspondent aux sélecteurs de politique |
| 4 | Lister toutes les politiques dans le namespace | `kubectl get networkpolicy -n <ns>` | Les politiques présentes comme prévu |
| 5 | Décrire la politique concernée | `kubectl describe networkpolicy <name> -n <ns>` | Les règles correspondent à l'accès prévu |
| 6 | Tester la connectivité depuis le pod source | `kubectl exec <src> -- curl -v <target-service>` | Réponse HTTP attendue ou délai d'attente |
| 7 | Tester la connectivité directement à l'IP du pod | `kubectl exec <src> -- curl <target-pod-ip>:port` | Identique au test du service, aide à isoler |
| 8 | Vérifier les journaux CNI pour les rejets | `kubectl logs -n kube-system <cni-pod> \| grep -i drop` | Pas de rejets inattendus ou rejets correspondant à la politique |
| 9 | Vérifier les libellés du namespace si vous utilisez namespaceSelector | `kubectl get namespace <ns> --show-labels` | Libellés requis présents |
| 10 | Appliquer la correction et re-tester | `kubectl apply -f fix.yaml` | Connectivité rétablie |

**Propriétaire et fréquence :** L'équipe plateforme ou réseau est généralement propriétaire des définitions de Network Policies. Les politiques doivent être revues trimestriellement et après tout changement significatif de l'architecture applicative. Un ingénieur désigné (par exemple, le responsable réseau ou l'ingénieur plateforme) doit posséder le dépôt des politiques et le processus de revue.

## Pièges courants

Voici les erreurs les plus fréquentes et comment les éviter :

1. **`podSelector: {}` vide :** Un sélecteur de pod vide sélectionne tous les pods du namespace. C'est rarement intentionnel, surtout dans une politique de refus global. Spécifiez toujours des libellés.

2. **Oublier `policyTypes` :** Si vous omettez `policyTypes`, seule l'entrée est appliquée. Pour contrôler la sortie, vous devez inclure explicitement `Egress`.

3. **Mal comprendre la sémantique des sélecteurs :** Au sein d'une même règle, les éléments `from` sont combinés par OU : si l'un correspond, la règle s'applique. Entre différentes règles, ils sont combinés par ET : le trafic doit satisfaire toutes les règles. Cela conduit souvent à une restriction excessive.

4. **Utiliser `ipBlock` de manière incorrecte :** `ipBlock` ne peut pas être utilisé avec `podSelector` ou `namespaceSelector` dans le même élément `from` ; ce sont des éléments de tableau séparés. De plus, le CIDR de `ipBlock` doit inclure exactement le CIDR du pod ou l'IP externe.

5. **Ne pas tenir compte de l'isolation des namespaces :** Une politique dans un namespace n'affecte pas les pods d'un autre namespace, sauf si les libellés de l'autre namespace sont utilisés. Assurez-vous que les règles de trafic inter-namespaces sont définies dans le namespace du pod cible.

6. **Ignorer le DNS dans les politiques de sortie :** Si vous créez une politique de refus de sortie sans autoriser l'UDP 53 vers votre serveur DNS, toute résolution externe échoue, provoquant des problèmes en cascade.

7. **Ne pas tester après les modifications :** Testez toujours à partir d'un pod source connu pour vérifier le comportement prévu. Utilisez des conteneurs de test éphémères pour éviter d'impacter la production.

8. **Supposer que les Network Policies sont appliquées par défaut :** Ce n'est pas le cas. Vous avez besoin d'un CNI qui les prend en charge et les politiques doivent être appliquées.

## Conclusion

Le dépannage des Network Policies Kubernetes est un processus systématique qui exige une observation attentive, des modifications incrémentales et une vérification approfondie. En construisant une solide compréhension de votre environnement, en utilisant des pratiques de configuration sûres et en employant les techniques de diagnostic décrites ici, vous pouvez résoudre rapidement les problèmes de connectivité causés par les politiques réseau.

Rappelez-vous toujours de :

- Vérifier que le CNI fonctionne et que les Network Policies sont prises en charge.
- Inspecter les libellés et sélecteurs réels avant de faire des suppositions.
- Tester la connectivité depuis l'intérieur du cluster avec des outils comme `netshoot`.
- Apporter des modifications minimales et sauvegarder les politiques avant de les éditer.
- Documenter chaque modification et son effet pour référence future.

Avec la pratique, ces étapes deviennent une seconde nature, transformant le dépannage des politiques réseau d'une tâche ardue en une procédure routinière. Pour approfondir, explorez la documentation Kubernetes sur les Network Policies et les spécificités de votre fournisseur CNI, car les implémentations varient.