Network Policies: het stuk dat iedereen overslaat
Stel: je hebt een cluster met een frontend, een API en een database. Standaard kan de frontend rechtstreeks met de database praten. De API ook. Elke pod kan elke andere pod bereiken, in elke namespace. Dat is het standaardgedrag van Kubernetes, en de meeste clusters laten het zo staan.
Network Policies veranderen dat. Ze werken als een firewall binnen het cluster: je definieert wat verkeer is toegestaan, en al het andere wordt geblokkeerd.
Waarom de meeste clusters ze niet hebben
Network Policies zijn een Kubernetes-concept, maar de handhaving ervan ligt bij de CNI-plugin. De basis CNI die je bij veel managed clusters krijgt, ondersteunt Network Policies niet. Je hebt Calico, Cilium, Weave Net of een vergelijkbare plugin nodig.
Op AWS EKS kun je Calico of de VPC CNI met Network Policy-ondersteuning installeren. Op GKE en AKS kun je Network Policies aanzetten bij het aanmaken van het cluster. Als je dit vergeet, kun je later de CNI vervangen, maar dat is een operatie waar je niet op zit te wachten in productie.
Controleer eerst of je CNI Network Policies ondersteunt:
kubectl get nodes -o wide
# en kijk naar de CNI in de cluster-instellingen of de kube-system pods
De default-deny aanpak
De juiste manier om te beginnen is een default-deny policy voor egress en ingress in elke namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Een lege podSelector geldt voor alle pods in de namespace. Na het toepassen van deze policy komt er geen verkeer meer doorheen. Daarna bouw je allow-regels op voor wat daadwerkelijk nodig is.
Pod selectors, namespace selectors en IP blocks
Een Network Policy selecteert pods via labels. Stel je hebt een frontend die alleen naar de API mag praten:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Deze policy staat toe dat pods met het label app: frontend verkeer sturen naar pods met het label app: api op poort 8080. Verkeer van andere pods wordt geblokkeerd.
Voor verkeer tussen namespaces gebruik je namespaceSelector. Dit is nodig voor monitoring en logging die in een aparte namespace draaien:
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: monitoring
IP blocks gebruik je voor verkeer van buiten het cluster, zoals een extern systeem dat je database moet bereiken via een vaste IP-range.
Een realistisch voorbeeld
Stel je hebt drie namespaces: kube-system, monitoring en production. De applicatie in production bestaat uit een frontend, een API en een PostgreSQL-database.
De regels die je nodig hebt:
- Frontend ontvangt verkeer van de ingress controller (in
kube-system). - API ontvangt verkeer van de frontend.
- Database ontvangt verkeer van de API, op poort 5432.
- Prometheus in
monitoringmag metrics scrapen van alle pods inproduction, op poort 9090 of welke metrics-poort je gebruikt. - Alle pods mogen DNS-verkeer sturen naar
kube-system(poort 53, UDP en TCP). - Geen enkele andere verbinding is toegestaan.
DNS is een veelgemaakte fout: als je egress blokkeert zonder een uitzondering voor DNS, werken services niet meer omdat ze geen hostnamen kunnen resolven.
Cilium als alternatief
Cilium ondersteunt Network Policies, maar gaat verder met zijn eigen CiliumNetworkPolicy-resource. Daarmee kun je policies op basis van DNS-namen schrijven, L7-regels toevoegen en verkeer filteren op HTTP-methode of pad. Dat is nuttiger dan standaard Kubernetes Network Policies voor teams die fijnmazige controle willen.
Als je dit in de praktijk wilt leren en oefenen in een echte clusteromgeving, bekijk dan de Kubernetes-trainingen op ict-trainingen.com.
Network Policies zijn niet ingewikkeld. Ze vragen alleen dat je expliciet bent over wat je toestaat. Dat is de hele gedachte.