The model Kubernetes assumes
- Every Pod gets its own IP, cluster-wide.
- Pods can reach every other Pod's IP directly, on any node, without NAT.
- A node can reach every Pod on that node directly.
Kubernetes itself doesn't implement any of this — it just assumes it holds, and calls out to whatever CNI plugin is installed to make it true.
Common CNI plugins
- Calico — L3 routing with BGP or IP-in-IP encapsulation, and one of the most widely used implementations of
NetworkPolicy. - Cilium — built on eBPF rather than iptables, which enables very granular L3–L7 policy and strong observability (Hubble) with less overhead at scale.
- Flannel — simple overlay networking; minimal feature set, and notably does not implement NetworkPolicy on its own.
- Cloud-native CNIs (Amazon VPC CNI, Azure CNI) — assign Pods real IPs from the VPC/VNet address space directly, which simplifies some things (Pods are visible to other VPC resources) and constrains others (IP exhaustion becomes a real planning concern).
NetworkPolicy: default-allow until you say otherwise
Out of the box, any Pod can talk to any other Pod. A NetworkPolicy selects Pods by label and declares what's allowed; as soon as one policy selects a Pod, everything not explicitly allowed to it is denied.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-allow-from-app
spec:
podSelector:
matchLabels:
app: db
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels:
app: docktionary
ports:
- protocol: TCP
port: 5432This allows only Pods labeled app: docktionary to reach db on port 5432 — everything else, including other namespaces by default, is denied.
A default-deny baseline
A common starting point for a namespace: deny everything, then add policies that open exactly what's needed.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes: ["Ingress", "Egress"]Remember: the plugin has to support it
A NetworkPolicy manifest applies cleanly on any cluster, but it's silently a no-op if the CNI plugin doesn't enforce NetworkPolicy (Flannel without an add-on, for instance). Check what's actually running before trusting a policy is doing anything.
kubectl get pods -n kube-system -o wide # look for calico-node, cilium, etc.
kubectl get networkpolicy -A