The "Open by Default" Problem
By default, Kubernetes networking is completely permissive. Any Pod in any namespace can send traffic to any other Pod in any namespace. This is convenient for getting started, but it is a serious security risk in production.
Consider a realistic scenario: your cluster runs a public-facing web application, an internal API, and a PostgreSQL database. Without Network Policies, if an attacker compromises the web application Pod, they can directly connect to the database on port 5432 — no additional barriers. Defense in depth requires that you explicitly define which Pods are allowed to communicate.
How Network Policies Work
A NetworkPolicy is a Kubernetes resource that acts as a firewall rule for Pods. It uses label selectors to target Pods and defines rules for allowed Ingress (incoming) and Egress (outgoing) traffic.
Critical implementation detail: Network Policies require a CNI plugin that supports them. Flannel does not support Network Policies. Calico and Cilium do. If you apply a NetworkPolicy with an unsupported CNI, it will be silently ignored — a dangerous false sense of security.
The Additive Model
Network Policies are additive and whitelisting-based:
- A Pod with no NetworkPolicy selecting it: all traffic allowed.
- A Pod selected by one or more NetworkPolicies: only traffic explicitly allowed by those policies is permitted. Everything else is dropped.
This means you can build up rules incrementally. Start with a default-deny policy, then add specific allow rules.
A Concrete Allow Rule
After applying a default-deny policy to the finance namespace, you would add an explicit allow rule targeting payments-api Pods, permitting ingress specifically from Pods labeled app: frontend on the application's port — everything else stays blocked.
Egress Policies
Egress policies control outbound traffic from Pods. A common pattern is to allow Pods to reach CoreDNS (so DNS still works) and specific external endpoints, while blocking everything else — an egress rule permitting DNS traffic to the kube-system namespace on port 53, plus a separate rule permitting traffic to the database Pods on their port, with nothing else allowed out. Forgetting to allow DNS in an egress policy is one of the most common mistakes — Pods suddenly cannot resolve any hostnames and appear completely broken.