Default Deny NetworkPolicy: Zero-Trust Examples
Implement default deny network policies in Kubernetes for zero-trust pod networking. Block all ingress and egress by default, then allow only required traffic
π‘ Quick Answer: Apply a default deny NetworkPolicy to block all ingress and egress traffic in a namespace, then create allow policies for specific required flows. Without any NetworkPolicy, all pods can communicate freely. A single empty-selector
{}policy with noingress/egressrules denies all traffic matching that direction.
The Problem
- By default, all pods can communicate with all other pods (flat network)
- A compromised pod can reach any service in the cluster
- Compliance requires network segmentation and least-privilege communication
- Need to prevent lateral movement after initial compromise
- Must allow only explicitly required traffic paths
The Solution
Default Deny All Ingress
# Block all incoming traffic to pods in this namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: production
spec:
podSelector: {} # Applies to ALL pods in namespace
policyTypes:
- Ingress
# No ingress rules = deny all incomingDefault Deny All Egress
# Block all outgoing traffic from pods in this namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-egress
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
# No egress rules = deny all outgoing (including DNS!)Default Deny Both (Full Isolation)
# Block all traffic in both directions
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- EgressAllow DNS (Required with Egress Deny)
# Must allow DNS or pods can't resolve service names
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53Allow Specific Service Communication
# Allow frontend β api-server on port 8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: api-server
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# Allow api-server β database on port 5432
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api-to-db
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api-server
ports:
- protocol: TCP
port: 5432Allow Ingress from External (Ingress Controller)
# Allow traffic from ingress-nginx namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-controller
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- protocol: TCP
port: 8080Complete Zero-Trust Example
# 1. Default deny all
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
---
# 2. Allow DNS for all pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: production
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- {protocol: UDP, port: 53}
- {protocol: TCP, port: 53}
---
# 3. Allow ingress β frontend
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-external-to-frontend
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- {protocol: TCP, port: 8080}
---
# 4. Allow frontend β api (ingress + egress)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-to-api
namespace: production
spec:
podSelector:
matchLabels:
app: frontend
policyTypes: [Egress]
egress:
- to:
- podSelector:
matchLabels:
app: api-server
ports:
- {protocol: TCP, port: 8080}Common Issues
Pods canβt resolve DNS after default-deny-egress
- Cause: DNS (port 53) is blocked by egress deny
- Fix: Add explicit allow-dns NetworkPolicy (shown above)
NetworkPolicy has no effect
- Cause: CNI doesnβt support NetworkPolicy (e.g., Flannel without policy engine)
- Fix: Use Calico, Cilium, or Antrea β they enforce NetworkPolicy rules
Pods in same namespace can still communicate after deny
- Cause: Another NetworkPolicy in the namespace allows the traffic
- Fix: NetworkPolicies are additive β any allow rule permits traffic. Check all policies
Health checks failing after deny
- Cause: Kubelet health probes come from node IP (not a pod)
- Fix: Allow ingress from node CIDR; or use
ipBlockwith node subnet
Best Practices
- Default deny first, then allow β zero-trust approach
- Always allow DNS with egress deny β pods need name resolution
- Use namespace labels for cross-namespace rules β cleaner than IP blocks
- Test with
kubectl exec+ curl β verify connectivity after applying policies - Label pods consistently β NetworkPolicy selectors depend on labels
- Document allowed flows β maintain a traffic matrix for the namespace
- Use CNI that supports NetworkPolicy β Calico, Cilium, Antrea (not basic Flannel)
Key Takeaways
- Without NetworkPolicy, all pods can talk to all pods (flat network)
podSelector: {}+ no rules = deny all (for that policyType)- NetworkPolicies are additive β if ANY policy allows traffic, itβs allowed
- Default deny egress blocks DNS β always add an allow-dns policy
- Required CNI support: Calico, Cilium, Antrea (basic Flannel doesnβt enforce)
- Combine namespace selectors + pod selectors for precise traffic control
- Zero-trust pattern: deny all β allow DNS β allow specific flows only

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
