What are Kubernetes network policies and how do you set default deny?
A Kubernetes network policy is a namespaced NetworkPolicy object that acts as a firewall for Pods: it selects Pods by label and lists the ingress and egress traffic they may send or receive. Without any policy, every Pod can reach every other Pod and any external address. A default deny is a policy with an empty podSelector and no allow rules, which isolates every Pod in the namespace until other policies open specific paths.
How network policies work
A Pod is non-isolated until a policy selects it. Once any policy selects a Pod for ingress or egress, only the traffic that some policy allows in that direction gets through. The Kubernetes documentation is explicit that policies “do not conflict; they are additive”: the result is the union of all rules that apply, and evaluation order does not matter.
Each policy has three parts:
podSelectorchooses the Pods the policy applies to. An empty selector{}selects every Pod in the namespace.policyTypessays whether the policy coversIngress,Egressor both. If you leave it out,Ingressis always set andEgressis set only when the policy has egress rules.ingressandegressrules list allowed peers (Pod labels, namespace labels or IP blocks) and ports.
A connection between two Pods needs both sides to agree: the source Pod’s egress policy and the destination Pod’s ingress policy must each allow it.
Enforcement depends on the CNI plugin
The API server stores NetworkPolicy objects, but the network plugin enforces them. In the words of the docs, “creating a NetworkPolicy resource without a controller that implements it will have no effect.” Flannel, for example, does not enforce network policies on its own and needs a separate policy controller. Cilium, Calico and Antrea enforce them. Check this before you rely on a policy, because an unenforced policy fails silently. The article on choosing a CNI plugin compares the common options.
How to set a default deny
Start every protected namespace with one policy that denies both directions:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: shop
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressThis blocks DNS too. Every name lookup now fails, which surfaces as timeouts that look unrelated to networking. Add an egress rule to the cluster DNS service right away:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: shop
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Then add one narrow policy per real traffic path, for example “Pods labelled app: api accept TCP 8080 from Pods labelled app: frontend”. The kubernetes.io/metadata.name label is set on every namespace automatically, so you can select namespaces by name without labelling them yourself. Check the labels of your DNS Pods, because k8s-app: kube-dns is a convention and not every distribution uses it.
What the core API cannot do
The upstream list of things NetworkPolicy does not support includes:
| Need | Core NetworkPolicy | Where it comes from instead |
|---|---|---|
Allow egress to a domain name such as api.stripe.com | No, IP blocks only | CNI extensions, such as Cilium toFQDNs rules |
| Rules on HTTP methods or paths (layer 7) | No | CNI extensions or a service mesh |
| Explicit deny rules | No, allow rules only | CNI policies with deny actions, ClusterNetworkPolicy |
| One policy for all namespaces | No, namespaced only | CNI cluster-wide policies, ClusterNetworkPolicy |
| Logging of allowed or dropped connections | No | CNI observability tooling |
| Encryption or TLS | No | Node-to-node encryption or a service mesh |
CNI plugins fill these gaps with their own resources. Cilium has CiliumNetworkPolicy and the cluster-scoped CiliumClusterwideNetworkPolicy, with layer 7 HTTP and DNS-based rules. Calico has its own NetworkPolicy and GlobalNetworkPolicy resources. These resources are not portable between plugins, so a switch of CNI means rewriting them.
Cluster-wide guardrails
Namespace owners can write their own NetworkPolicies, which makes them a poor tool for rules the platform team must guarantee, such as “no Pod reaches the cloud metadata endpoint”. SIG Network’s Network Policy API project addresses this with ClusterNetworkPolicy, a custom resource in the policy.networking.k8s.io/v1alpha2 API. It has two tiers: an Admin tier evaluated before namespace policies, which namespace owners cannot override, and a Baseline tier evaluated after them, which sets defaults they can override. Rules use Accept, Deny or Pass actions.
It succeeds the earlier AdminNetworkPolicy and BaselineAdminNetworkPolicy APIs, which the project lists as no longer actively developed. As of November 2026 the API version is alpha, and the project’s implementations page lists Calico, Kube-OVN and kube-network-policies. Until your CNI supports it, use the CNI’s own cluster-wide policy resource.
How to test that a policy blocks traffic
A policy that applies without errors is not proof that it works. Test each path from inside the cluster:
- Start a temporary Pod in the source namespace with the same labels as the real client, for example
kubectl run probe --rm -it --image=busybox --labels=app=frontend -n shop -- sh. - From that Pod, connect to an allowed destination and confirm it succeeds, then connect to a denied one and confirm it times out.
- Repeat with a Pod that has different labels, to confirm the selector is as narrow as you meant.
- If the CNI exposes policy verdicts, such as Cilium’s Hubble, check that dropped flows show the policy you expect.
Network policies are one layer. For untrusted code, combine them with a sandboxed runtime as described in how to isolate untrusted workloads, and for tenants that share a cluster, with the controls in Kubernetes multi-tenancy.
Network policies on Cloudfleet
Cloudfleet Kubernetes Engine (CFKE) uses Cilium to enforce NetworkPolicy, CiliumNetworkPolicy and CiliumClusterwideNetworkPolicy on every node, in every cloud and on self-managed nodes, with nothing to enable. The network policies guide shows the common patterns.