How to Write a Kubernetes NetworkPolicy for Default-Deny Ingress
By default, every pod in a Kubernetes namespace can reach every other pod. A NetworkPolicy with an empty podSelector and no ingress rules flips that: nothing gets in unless you say so. Here's how to write the canonical default-deny ingress policy.
Why the default is wide open
Kubernetes networking follows an allow-all model out of the box. Any pod in any namespace can dial any other pod by IP - no firewall, no admission check. That's convenient for development but a problem in production: a compromised pod in one namespace can probe every service reachable on the cluster network.
A NetworkPolicy is the Kubernetes-native way to restrict that. The CNI
plugin (Calico, Cilium, Flannel with Calico, etc.) enforces it at the
network level - not at the app level.
The default-deny ingress pattern
The canonical manifest looks like this:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: app-default-deny-ingress
spec:
podSelector: {}
policyTypes:
- Ingress
Three things make this work together:
podSelector: {}- an empty selector selects every pod in the namespace, so the policy applies cluster-wide within that namespace.policyTypes: [Ingress]- declares that this policy governs inbound traffic to matching pods.- No
ingress:rules - when policyTypes names Ingress but the ingress rules list is absent (or empty), Kubernetes drops all inbound traffic. The absence of a rule is the deny.
Apply it and verify with kubectl:
kubectl apply -f networkpolicy.yaml
kubectl get networkpolicy -n <namespace>
kubectl describe networkpolicy app-default-deny-ingress
Adding explicit allow rules on top
Default-deny is the base. You build up from it with targeted allow rules.
For example, to let a frontend pod reach a backend pod on port 8080:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
This policy applies only to pods labeled app: backend and allows
inbound TCP 8080 from pods labeled app: frontend. Every other source
is still denied by the default-deny policy applied earlier.
Egress default-deny
To block outbound traffic too, add Egress to policyTypes with no
egress rules:
policyTypes:
- Ingress
- Egress
Be careful - this also blocks DNS (UDP 53). A full zero-trust setup adds
an explicit egress rule allowing traffic to kube-dns in the
kube-system namespace before locking egress down.
What to check if NetworkPolicy has no effect
A NetworkPolicy object is inert unless the CNI plugin supports it.
kubectl apply succeeds even with a CNI that ignores NetworkPolicy.
Run kubectl get pods -n kube-system and look for Calico, Cilium, or
Weave - plain Flannel without a policy controller does nothing.
Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.
Try it in a workspace →What you'll practice
- Writing the default-deny ingress NetworkPolicy manifest with the correct podSelector and policyTypes
- Inspecting applied policies with kubectl describe networkpolicy
- Layering targeted allow rules on top of a default-deny baseline
FAQ
What does podSelector: {} mean in a NetworkPolicy?
An empty podSelector matches every pod in the namespace, so the policy applies to all pods - not just ones with a specific label. Combined with policyTypes: [Ingress] and no ingress rules, it creates a namespace-wide default-deny.
How do I block all pod-to-pod traffic in a Kubernetes namespace?
Apply a NetworkPolicy with podSelector: {}, policyTypes: [Ingress], and no ingress rules. This matches every pod and drops all inbound connections. Then add targeted allow rules for the paths that need to communicate.
Why does my NetworkPolicy have no effect?
NetworkPolicy enforcement depends on the CNI plugin. If your cluster uses plain Flannel or another CNI that does not implement NetworkPolicy, the objects are accepted by the API server but silently ignored. Switch to Calico, Cilium, or a policy-aware CNI.
What is the role of a NetworkPolicy in Kubernetes?
A NetworkPolicy is a pod-level firewall that controls which pods can talk to which. By default all pods can reach each other; a NetworkPolicy restricts ingress and egress to only the traffic you explicitly allow.
Keep learning
Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.
Open the workspace →