Network Policies
Topic 23

Network Policies

SecuritySegmentation

By default, every Pod can talk to every other Pod — the flat network is wide open. A NetworkPolicy is a firewall rule for Pod traffic, expressed in terms of label selectors, that restricts which Pods may connect to which. It is how you segment a cluster and limit the blast radius of a compromise.

Two facts shape everything about policies: the default is allow-all, and a policy is only enforced if the CNI plugin supports it. Miss either and your security model is an illusion.

The Default Is Allow-All

With no policies, all Pod-to-Pod traffic is permitted. The moment a Pod is selected by any NetworkPolicy, it switches to default-deny for the direction that policy covers — only explicitly allowed traffic gets through. So policies are additive allow-lists layered onto a deny stance that you turn on by selecting a Pod. A common baseline is a default-deny policy for a namespace, then specific allows on top.

Default-deny ingress for a namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: shop
spec:
  podSelector: {}          # all Pods in the namespace
  policyTypes: ["Ingress"]   # no ingress allowed unless another policy permits it

Selectors and Rules

Policies pick the Pods they apply to with a podSelector, then list ingress and/or egress rules. Each rule allows traffic to or from sources chosen by podSelector (Pods by label), namespaceSelector (whole namespaces), or ipBlock (CIDR ranges), optionally narrowed to specific ports. The model is entirely label-driven, consistent with the rest of Kubernetes.

Allow only the api Pods to reach the database
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-allow-api
  namespace: shop
spec:
  podSelector:
    matchLabels:
      app: db
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api
      ports:
        - port: 5432

Enforcement Depends on the CNI

NetworkPolicy is an API, not an enforcer. The CNI plugin must implement it — Calico and Cilium do, plain Flannel does not. On a cluster whose plugin ignores policies, you can create all the NetworkPolicies you like and traffic flows unchanged, with no error. This is one of the most dangerous gaps in Kubernetes security: a policy that is silently not enforced gives a false sense of safety. Always confirm the plugin enforces policy.

Limits and Practical Use

NetworkPolicy operates at layers 3 and 4 — IPs and ports — not HTTP. It cannot match on paths, methods, or headers; that is the realm of a service mesh (Topic 24). A frequent self-inflicted outage is a default-deny egress policy that also blocks DNS, breaking name resolution for every Pod it covers; remember to allow egress to CoreDNS. Used carefully, policies are the backbone of cluster segmentation and a core control for the security chapter.

No policy vs default-deny baseline

No policy (default) — all Pod-to-Pod traffic allowed. Convenient, but any compromised Pod can reach everything.

Default-deny + allows — select all Pods to deny by default, then allow only required flows. The recommended posture.

Common Mistakes
  • Writing policies on a CNI that doesn't enforce them, so they are silently ignored.
  • Forgetting that default-allow means an unselected Pod is wide open — policies must select a Pod to restrict it.
  • A default-deny egress policy that blocks DNS, breaking resolution for every covered Pod.
  • Expecting NetworkPolicy to match HTTP paths or headers — it is L3/L4 only.
  • Relying on namespaces for isolation without any NetworkPolicy to back it.
Best Practices
  • Confirm the CNI plugin actually enforces NetworkPolicy before trusting any policy.
  • Adopt a default-deny baseline per namespace, then add specific allow rules.
  • Always allow egress to CoreDNS when using default-deny egress, or break DNS for the namespace.
  • Express allowed flows with label and namespace selectors, matching the rest of Kubernetes.
  • Reach for a service mesh when you need L7 (path/header) policy, not NetworkPolicy.
RelatedCNI plugins — the enforcer NetworkPolicy depends on (Topic 22)Service mesh — L7 policy beyond IP/port (Topic 24)Cloud security groups — the rough VM-world analog

Knowledge Check

What is the default Pod-to-Pod traffic behavior with no NetworkPolicies?

  • All traffic is allowed; a Pod becomes default-deny only once a policy selects it
  • All traffic is denied by default until you write a policy that explicitly allows each connection
  • Only traffic within the same namespace is allowed by default
  • Only traffic routed through a Service ClusterIP is allowed

You applied NetworkPolicies but traffic flows unchanged with no errors. Why?

  • The CNI plugin does not enforce NetworkPolicy — the API exists but nothing implements it
  • Policies only take effect after every node is drained and the control plane is restarted
  • NetworkPolicies only apply once the namespace has a LoadBalancer Service
  • The policies were created under the wrong apiVersion and silently skipped

A default-deny egress policy broke DNS in a namespace. What was missed?

  • An egress allow rule to CoreDNS — default-deny egress blocks name resolution too
  • An ingress rule permitting traffic from the API server
  • A LoadBalancer Service exposing CoreDNS externally
  • The policy should have used a wildcard ipBlock that allows egress to every destination CIDR

You got correct