Here's a fact that surprises people new to Kubernetes and should genuinely alarm them a little: by default, every pod in your cluster can talk to every other pod, unrestricted, regardless of namespace, regardless of what the two pods actually do. Your carefully separated services, your isolated namespaces, all of that organizational structure means nothing to the network unless you explicitly tell Kubernetes to enforce it. Network policies are how you actually do that, and most clusters are running without them.
The default is flat, and flat means one compromised pod can reach everything. Without network policies, the entire pod network is one big open space, any pod can initiate a connection to any other pod on any port, cluster-wide. This means that if an attacker compromises a single pod, maybe through a vulnerable dependency, a misconfigured service, whatever the entry point, they can potentially reach every other pod in your cluster from that one foothold, regardless of namespace boundaries that look like isolation on paper but do nothing to actually restrict network traffic. Namespaces organize your resources. They do not, by themselves, segment your network.
A network policy is basically a firewall rule scoped to pods. At its core, a network policy specifies which pods can talk to which other pods, on which ports, and in which direction, ingress traffic coming in, egress traffic going out. You define it declaratively, the same way you define everything else in Kubernetes, and the cluster's networking layer enforces it. The concept maps directly onto ordinary network segmentation, just expressed in pod selectors and labels instead of IP ranges.
Default deny is the posture you actually want, the same principle as everywhere else in security. The strongest, most defensible starting point is denying all traffic by default and then explicitly allowing only the specific connections your applications actually need. This is least privilege applied to your pod network, exactly the same principle that governs good access control everywhere, just expressed here as network rules instead of permissions. Most clusters do the opposite by default, implicitly allow-all, until someone deliberately locks it down, and most clusters never get that deliberate step taken.
A crucial gotcha: applying one policy can silently change the default for a whole namespace. Here's the part that trips people up constantly. The moment you apply any network policy that selects a given pod, that pod's traffic becomes default-deny for whatever traffic type the policy governs, ingress or egress, unless explicitly allowed by that or another policy. So adding one narrow, well-intentioned policy can unexpectedly block traffic you didn't think to explicitly allow, because you've just flipped that pod from implicit allow-all to default-deny, and everything not covered by a rule now silently fails. This is the number one source of "I added a network policy and now things are randomly broken" incidents, and understanding this behavior upfront saves you a lot of confused debugging later.
Start with the traffic that actually needs isolating, don't try to lock down everything on day one. A sane rollout: identify your genuinely sensitive workloads first, databases, anything handling credentials or regulated data, internal services that should never be reachable from outside their intended callers, and apply restrictive network policies there first. Trying to policy your entire cluster comprehensively on day one, before you understand the actual traffic patterns, is how you end up either with policies so loose they don't protect anything, or so tight they break things constantly and get disabled out of frustration. Start narrow, on what actually matters most, and expand deliberately.
Test in a non-production environment first, because the failure mode is "things silently stop working," not a helpful error message. Network policies fail silently in a specific, annoying way, a blocked connection typically just times out or gets refused, without a clear message pointing you back to "a network policy did this." Testing changes in a non-production environment before applying them to production avoids discovering this the hard way, with real traffic failing and an on-call engineer trying to figure out why a perfectly normal-looking deployment suddenly can't reach its database.
Not every Kubernetes networking layer enforces this identically, so verify yours actually does what you think. Network policy enforcement depends on your cluster's networking implementation, your CNI plugin, and not every implementation supports the full network policy specification, or supports it identically. Verifying that your specific setup actually enforces the policies the way you expect, rather than assuming compliance with the spec guarantees identical real-world behavior everywhere, is a step worth taking explicitly rather than assuming.
The summary. Your cluster's pods can all talk to each other by default, which means one compromised pod is potentially a foothold to everything, unless you're actively enforcing network policies to prevent it. Adopt default-deny as your posture, understand that applying any policy to a pod flips its default behavior for that traffic direction, start with your most sensitive workloads rather than trying to cover everything immediately, test in non-production first because failures are silent, and confirm your specific networking implementation actually enforces what you think it does. The flat, wide-open default isn't a bug, it's just an invitation most clusters never explicitly decline.
Top comments (0)