On this page
Kubernetes NetworkPolicy and network segmentation
The standard specification for explicitly defining which pods are allowed to communicate with each other, enforcing a zero-trust network model within a cluster.
What it is
By default, the Kubernetes networking model dictates that all Pods in a cluster can communicate freely with all other Pods, regardless of the Namespace they reside in. It is a flat, inherently open network.
A NetworkPolicy is a standard Kubernetes API resource that acts as an internal firewall for the cluster. It allows administrators to declaratively specify exactly which ingress (incoming) and egress (outgoing) traffic is permitted for a specific group of Pods. When a NetworkPolicy is applied to a Pod, that Pod instantly switches from “default allow” to “default deny,” meaning any traffic not explicitly whitelisted in the policy is dropped by the underlying network plugin (the CNI).
Why it matters
If an attacker breaches a vulnerable frontend container running in the web namespace, the default Kubernetes network allows that compromised container to instantly open a TCP connection to the mission-critical database container in the secure-data namespace. This lateral movement is how a minor vulnerability escalates into a catastrophic data breach.
NetworkPolicy enforces a zero-trust architecture. By explicitly defining that the database can only accept connections from the specific backend API pods, you physically quarantine the database. Even if the frontend is compromised, the network fabric itself drops the attacker’s packets before they reach the database.
How to implement
A NetworkPolicy uses standard Kubernetes labels and selectors to target Pods and define rules.
This example applies to any Pod labeled role: db. It denies all egress traffic, and it restricts ingress traffic strictly to Pods labeled role: api.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-db
namespace: production
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: api
ports:
- protocol: TCP
port: 5432
egress: [] # Empty array means "Deny all egress traffic"
The CNI Requirement
The Kubernetes API server accepts and stores NetworkPolicy resources, but it does not enforce them. Enforcement requires a Container Network Interface (CNI) plugin that supports network policies (e.g., Calico, Cilium, or Weave Net). If you apply a NetworkPolicy to a cluster running a basic CNI (like Flannel), the API server will return a success message, but the policy will be silently ignored, leaving your cluster entirely unprotected.
Common mistakes
Locking out CoreDNS
A classic failure mode is applying a strict “Deny All” egress policy to a Pod to lock it down, completely forgetting that the Pod relies on DNS to resolve service names. If a Pod cannot reach the cluster’s CoreDNS service (usually running on UDP port 53 in the kube-system namespace), it cannot resolve internal or external hostnames, breaking the application. Egress policies must almost always include a whitelist rule allowing UDP/53 traffic to the DNS infrastructure.
Namespace Boundaries
Administrators often assume that Kubernetes Namespaces inherently provide network isolation (e.g., assuming a pod in dev cannot talk to a pod in prod). This is dangerously false. Namespaces isolate names, not networks. To isolate namespaces, you must create a NetworkPolicy in each namespace that specifically uses a namespaceSelector to reject traffic from outside.
The Missing Default Deny
Because NetworkPolicy is additive, simply creating a policy that “Allows A to talk to B” does not automatically protect Pod C. The industry best practice is to always deploy a “Default Deny” policy to every namespace as a baseline.
# A baseline policy that drops all traffic by default
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {} # An empty selector matches ALL pods in the namespace
policyTypes:
- Ingress
- Egress
Once this baseline is applied, you must then write specific, additive policies to punch necessary holes through the firewall.
Verification
Verifying network policies requires active probing. The standard operational practice is to use a network diagnostic container (like netshoot) deployed into different namespaces with different labels.
- Exec into a
netshootpod that should not have access. - Attempt to
curlortelnetto the protected database. - Verify the connection hangs or times out (confirming the CNI dropped the packet).
- Exec into a pod that should have access, and verify the connection succeeds.