Module 3 – Réseaux, Services et Ingress

Comprenez le modèle réseau Kubernetes, exposez vos applications via Services et Ingress, et sécurisez les flux avec NetworkPolicies.

Kubernetes abstrait le réseau afin que chaque Pod possède sa propre IP et que les services soient découvertes automatiquement. Ce module clarifie la circulation du trafic et comment l’exposer en interne comme en externe.

Objectifs

  • Visualiser le modèle réseau cluster (CNI, kube-proxy, CoreDNS).
  • Choisir le bon type de Service : ClusterIP, NodePort, LoadBalancer.
  • Mettre en place un Ingress Controller et rédiger des règles HTTP(S).
  • Sécuriser les échanges avec NetworkPolicy.

1. Modèle réseau Kubernetes

  • Chaque Pod obtient une IP unique routable dans le cluster (pas de NAT intra-cluster).
  • Le CNI (Calico, Cilium, Flannel…) s’occupe de l’attribution d’adresses et du routage.
  • kube-proxy (iptables ou IPVS) gère les règles pour exposer les Services.
  • CoreDNS fournit la résolution service.namespace.svc.cluster.local.

Vérifiez votre CNI :

kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl get pods -n kube-system -l k8s-app=calico-node

2. Services : ClusterIP, NodePort, LoadBalancer

Un Service sélectionne des Pods via des labels et expose un endpoint stable.

apiVersion: v1
kind: Service
metadata:
  name: webapp
  namespace: staging
spec:
  selector:
    app: webapp
  ports:
    - name: http
      port: 80
      targetPort: 8080
  type: ClusterIP
  • ClusterIP : visibilité uniquement intra-cluster.
  • NodePort : ouvre un port (30000-32767) sur chaque nœud pour accéder depuis l’extérieur.
  • LoadBalancer : provisionne un LB via le cloud provider (ou MetalLB en bare metal).

Pour convertir en NodePort :

kubectl patch svc webapp -p '{"spec": {"type": "NodePort", "ports": [{"port":80,"targetPort":8080,"nodePort":31080}]}}'

3. Ingress HTTP(S)

Un Ingress Controller (NGINX, Traefik, HAProxy, Istio Gateway) observe les ressources Ingress et configure la passerelle.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
kubectl get pods -n ingress-nginx

Déclarez ensuite une règle :

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: webapp
  namespace: staging
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - webapp.local
      secretName: webapp-tls
  rules:
    - host: webapp.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: webapp
                port:
                  number: 80

Sur votre poste :

echo "127.0.0.1 webapp.local" | sudo tee -a /etc/hosts
curl -H "Host: webapp.local" http://127.0.0.1:8080

4. DNS et découverte

CoreDNS résout automatiquement les services. Testez depuis un Pod utilitaire :

kubectl run dnsutils --image=ghcr.io/linuxserver/bind-tools -it --rm -- /bin/sh
# Dans le pod
nslookup webapp.staging.svc.cluster.local
curl webapp.staging.svc.cluster.local:80

5. NetworkPolicies

Sans NetworkPolicy, tout le trafic est autorisé. Restreignez les flux :

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
  namespace: staging
spec:
  podSelector:
    matchLabels:
      app: webapp
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              env: frontend
        - podSelector:
            matchLabels:
              role: gateway
      ports:
        - protocol: TCP
          port: 80

Pour filtrer le egress (sortie) : ajoutez policyTypes: ["Ingress", "Egress"] et définissez des egress rules.

6. Lab complet

  1. Déployez webapp (module 2) et exposez-le via un Service NodePort (port 31080).
  2. Installez ingress-nginx (commande ci-dessus) et créez un Ingress webapp.
  3. Ajoutez un certificat auto-signé :
    openssl req -new -x509 -nodes -out webapp.crt -keyout webapp.key -subj "/CN=webapp.local"
    kubectl create secret tls webapp-tls --cert=webapp.crt --key=webapp.key -n staging
    
  4. Appliquez la NetworkPolicy allow-frontend puis créez deux namespaces : frontend (label env=frontend) et backend. Vérifiez que seul frontend accède au Service.
  5. Inspectez les tables iptables : sudo iptables-save | grep KUBE-SVC (sur un nœud worker).

Solution détaillée

  1. Service NodePort
    kubectl get svc webapp -n staging doit afficher TYPE NodePort avec PORT(S) 80:31080/TCP.
    Test local : curl http://$(kind get clusters >/dev/null && kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}'):31080.
  2. Ingress
    kubectl get ingress -n staging doit montrer HOSTS webapp.local.
    curl -H "Host: webapp.local" http://127.0.0.1:8080 renvoie la page (ou Ingress Controller default backend si Service incorrect).
  3. TLS
    kubectl get secret webapp-tls -n staging → type kubernetes.io/tls.
    curl -k https://webapp.local:8443 (si vous exposez port 8443) doit répondre 200.
  4. DNS
    Dans le Pod dnsutils : nslookup webapp.staging.svc.cluster.local renvoie l’IP ClusterIP. curl webapp.staging.svc.cluster.local doit réussir.
  5. NetworkPolicy
    Après application de deny-all, tout trafic doit être bloqué. Déployez un Pod busybox dans un namespace sans label et testez : curl webapp.staging.svc.cluster.local → timeout.
    Ajoutez le namespace frontend avec label env=frontend et un Pod test : l’accès doit fonctionner.

Consignez les sorties kubectl describe ingress, kubectl get networkpolicy et un test curl réussi depuis le namespace autorisé.

Challenge

  • Mettre en place MetalLB ou kind loadbalancer pour tester le type LoadBalancer.
  • Déployer Traefik et comparer la configuration (kubectl get configmap -n kube-system traefik).
  • Créer une NetworkPolicy default deny sur le namespace staging et autoriser explicitement chaque flux.

Pièges récurrents

  • Oublier de créer le secret TLS référencé par un Ingress → code HTTP 502/404.
  • Mettre un Ingress sans contrôleur : la ressource est créée mais sans effet.
  • NetworkPolicy non appliquée car le CNI ne la supporte pas (ex. Flannel vanilla). Vérifiez la documentation de votre CNI.

Ressources

Checklist

  • ✅ Vous pouvez expliquer la différence entre ClusterIP, NodePort, LoadBalancer.
  • ✅ Vous avez configuré un Ingress et testé une résolution DNS intra-cluster.
  • ✅ Vous contrôlez le trafic avec une NetworkPolicy et savez valider son effet.