How do Kubernetes NetworkPolicies work, and what usually goes wrong with them?
Show the answer
Say this first
By default every pod can talk to every pod. Once any NetworkPolicy selects a pod for ingress or egress, that direction becomes deny by default for the pod and only what some policy allows gets through. Policies are additive allow lists with no deny rule. They only work if the CNI enforces them, and the classic mistakes are forgetting DNS on egress and mixing up the AND versus OR form of selectors.
Go deeper
Default deny plus an allow
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: shop
spec:
podSelector: {}
policyTypes: [Ingress]
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-from-web
namespace: shop
spec:
podSelector:
matchLabels:
app: api
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchLabels:
app: web
ports:
- protocol: TCP
port: 8080The AND vs OR trap
# One element: namespace AND pod must match
- from:
- namespaceSelector: {matchLabels: {team: web}}
podSelector: {matchLabels: {app: web}}
# Two elements: namespace OR pod matches
- from:
- namespaceSelector: {matchLabels: {team: web}}
- podSelector: {matchLabels: {app: web}}One dash changes the meaning and can open a namespace wide.
Enforcement
Calico, Cilium, the AWS VPC CNI with its network policy agent, and Azure's options enforce policies. Flannel alone does not, and the API server accepts the objects anyway, so nothing warns you.
They will ask next
You apply default-deny egress and everything breaks, even allowed calls. Why?
DNS. Pods can no longer reach CoreDNS on UDP and TCP 53 in
kube-system, so names never resolve. Add an egress rule allowing port 53 to the DNS pods.How do you write a deny rule?
Standard NetworkPolicy has none. You get deny by selecting the pod and not allowing the traffic. Calico and Cilium policies add explicit deny and cluster-wide scope.
Traps
- Assuming policies work on any cluster. The CNI must enforce them.
- Forgetting that a policy with only ingress rules leaves egress wide open for the same pods.