Introduction
Les espaces de noms organisent les ressources, mais ne bloquent pas automatiquement le trafic réseau. Les NetworkPolicies définissent quels Pods sélectionnés peuvent établir ou recevoir des connexions, à condition que le plugin réseau du cluster les applique. Le réseau Calico préparé pour ce laboratoire les prend bien en charge.
Vous allez d’abord vérifier que le trafic est ouvert, appliquer ensuite un refus par défaut, puis n’autoriser qu’un client identifié par un label provenant d’un espace de noms approuvé.
Le laboratoire suit une méthode sûre pour définir les règles réseau : établir une situation de référence fonctionnelle, bloquer le trafic, ajouter l’exception minimale attendue, puis tester à la fois un cas autorisé et un cas refusé. Tester uniquement le client autorisé ne permettrait pas de détecter une règle trop permissive.
Déployer le serveur et les clients
Dans cette étape, créez des espaces de noms distincts pour l’application et les clients, un serveur NGINX ainsi que deux clients exécutés en continu.
Les commandes utilisent volontairement des formes impératives familières afin que l’expérience réseau ne soit pas noyée dans un fichier YAML sans rapport direct. Un client reçoit le label role=approved, tandis que l’autre reçoit role=untrusted. L’espace de noms des clients reçoit le label access=approved. Les sélecteurs utilisés par les règles réseau s’appuieront ensuite sur ces deux niveaux de labels.
cd /home/labex/project/network-policy
kubectl create namespace practice-apps
kubectl create namespace practice-clients
kubectl label namespace practice-clients access=approved
Créez et exposez le serveur. kubectl expose crée un Service ClusterIP dont le sélecteur correspond au label de Pod app=protected-web généré pour le Deployment :
kubectl create deployment protected-web -n practice-apps --image=nginx:1.27-alpine --replicas=1
kubectl expose deployment protected-web -n practice-apps --port=80 --target-port=80
Créez deux Pods clients de diagnostic. Leurs boucles d’attente les maintiennent disponibles pour des tests répétés avec kubectl exec :
kubectl run crée directement chaque Pod autonome. --labels lui associe l’identité qui sera sélectionnée par la règle, --restart=Never empêche kubectl de créer un contrôleur de charge de travail, et -- sépare les options de kubectl de la commande sh -c exécutée dans le conteneur. Pour la commande d’attente, --all signifie que tous les Pods de practice-clients doivent devenir prêts.
kubectl run approved-client -n practice-clients --image=busybox:1.36 --image-pull-policy=IfNotPresent --labels=role=approved --restart=Never -- sh -c 'while true; do sleep 30; done'
kubectl run untrusted-client -n practice-clients --image=busybox:1.36 --image-pull-policy=IfNotPresent --labels=role=untrusted --restart=Never -- sh -c 'while true; do sleep 30; done'
kubectl wait --for=condition=Ready pod -n practice-clients --all --timeout=120s
kubectl rollout status deployment/protected-web -n practice-apps --timeout=60s
La simple séparation des espaces de noms permet toujours aux deux clients d’atteindre le Service.
Les commandes de vérification de l’état de préparation doivent produire des résultats confirmant que les deux Pods clients et le Deployment du serveur sont prêts :
pod/approved-client condition met
pod/untrusted-client condition met
deployment "protected-web" successfully rolled out
À ce stade, les labels décrivent les clients, mais ne les restreignent pas. Un label ne devient une règle de trafic qu’après avoir été utilisé par un sélecteur de NetworkPolicy.
Vérifier que le trafic est initialement ouvert
Dans cette étape, envoyez une requête au Service depuis les deux clients, à travers les espaces de noms. Le nom complet comprend le nom du Service et celui de son espace de noms.
Dans le même espace de noms, protected-web suffirait. Depuis practice-clients, protected-web.practice-apps indique au DNS du cluster à la fois le nom du Service et son espace de noms. Testez les deux clients avant d’appliquer la règle afin de pouvoir attribuer tout échec ultérieur à la règle, et non au DNS ou à la configuration du Service.
Comme dans le laboratoire consacré aux sondes de santé, wget -qO- écrit le corps de la réponse sans afficher la progression. --timeout=3 évite qu’une requête refusée ne reste bloquée indéfiniment, et le tube vers grep n’affiche que le texte NGINX reconnaissable.
cd /home/labex/project/network-policy
kubectl exec approved-client -n practice-clients -- wget -qO- --timeout=3 http://protected-web.practice-apps | grep 'Welcome to nginx'
kubectl exec untrusted-client -n practice-clients -- wget -qO- --timeout=3 http://protected-web.practice-apps | grep 'Welcome to nginx'
kubectl get networkpolicies -n practice-apps
En l’absence de NetworkPolicy sélectionnant les Pods, les connexions entrantes sont autorisées. Cela corrige l’idée répandue selon laquelle les espaces de noms constitueraient à eux seuls des frontières de sécurité réseau.
Les deux commandes doivent trouver Welcome to nginx, et kubectl get networkpolicies doit indiquer qu’aucune ressource n’est présente. Il s’agit de la situation de référence saine que vous allez volontairement modifier.
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
No resources found in practice-apps namespace.
La répétition du texte de la page prouve que les deux identités clientes peuvent atteindre le même Service avant le début de l’isolation.
Appliquer un refus par défaut des connexions entrantes
Dans cette étape, sélectionnez tous les Pods de practice-apps et n’autorisez aucune source entrante.
Une NetworkPolicy ne devient restrictive que pour les Pods sélectionnés par cette règle et pour la direction de trafic indiquée dans policyTypes. Ici, podSelector: {} sélectionne tous les Pods de practice-apps, et l’absence de toute règle d’autorisation ingress crée un refus par défaut des connexions entrantes.
cd /home/labex/project/network-policy
cat <<'EOF' > default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: default-deny-ingress, namespace: practice-apps}
spec:
podSelector: {}
policyTypes: [Ingress]
EOF
kubectl apply -f default-deny.yaml
kubectl exec approved-client -n practice-clients -- wget -qO- --timeout=3 http://protected-web.practice-apps || echo 'blocked as expected'
Un podSelector vide sélectionne tous les Pods de l’espace de noms concerné par la règle. Le délai d’attente attendu prouve que les connexions entrantes sont désormais refusées, et non que le Service a disparu.
|| echo ... gère le code de sortie non nul attendu de wget, afin que le terminal puisse continuer. Dans cette expérience contrôlée, l’échec constitue une preuve. Le Pod serveur reste prêt ; seule l’autorisation réseau a changé.
networkpolicy.networking.k8s.io/default-deny-ingress created
wget: download timed out
command terminated with exit code 1
blocked as expected
Le délai d’attente est attendu, car un paquet refusé ne reçoit aucune réponse de l’application. La dernière ligne confirme que le shell a volontairement transformé cet échec attendu en résultat lisible.
Autoriser un seul client approuvé
Dans cette étape, ajoutez une règle d’autorisation qui exige à la fois un espace de noms approuvé et un label de Pod approuvé.
Les NetworkPolicies sont additives. La règle de refus par défaut reste en place, tandis que cette seconde règle ajoute une seule source autorisée. Le Pod serveur sélectionné peut accepter des connexions TCP sur le port 80 uniquement lorsque l’espace de noms source et le Pod source correspondent tous deux aux critères.
cd /home/labex/project/network-policy
cat <<'EOF' > allow-approved.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: allow-approved-client, namespace: practice-apps}
spec:
podSelector: {matchLabels: {app: protected-web}}
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector: {matchLabels: {access: approved}}
podSelector: {matchLabels: {role: approved}}
ports:
- {protocol: TCP, port: 80}
EOF
kubectl apply -f allow-approved.yaml
kubectl exec approved-client -n practice-clients -- wget -qO- --timeout=3 http://protected-web.practice-apps | grep 'Welcome to nginx'
kubectl exec untrusted-client -n practice-clients -- wget -qO- --timeout=3 http://protected-web.practice-apps || echo 'untrusted client blocked'
Comme les deux sélecteurs se trouvent dans la même entrée from, ils doivent tous deux correspondre. Des entrées distinctes exprimeraient une relation logique OU.
La requête du client approuvé doit à nouveau réussir, tandis que celle du client non approuvé doit toujours expirer. Ce résultat en deux temps prouve que la règle est sélective et ne réautorise pas simplement toutes les connexions entrantes.
networkpolicy.networking.k8s.io/allow-approved-client created
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
wget: download timed out
command terminated with exit code 1
untrusted client blocked
Interprétez le résultat comme un ensemble : le contenu de la page pour approved-client, puis un délai d’attente pour untrusted-client. La réussite de la seule requête autorisée ne suffirait pas à prouver que la règle est assez restrictive.
Résumé
Vous avez démontré que les espaces de noms n’isolent pas le trafic par défaut, appliqué un refus par défaut des connexions entrantes, puis autorisé un seul client grâce à la combinaison de critères portant sur l’espace de noms, le Pod, le protocole et le port.


