🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Kubernetes NetworkPolicy Blocking Traffic — Every Fix (2026)

Your pods suddenly can't talk to each other after applying a NetworkPolicy. DNS is failing, services are unreachable, or inter-namespace traffic is blocked. Here's every cause and the exact fix.

DevOpsBoysMay 24, 20264 min read
Share:Tweet

NetworkPolicy is one of the most misunderstood Kubernetes features. The moment you apply one, you may find that traffic that worked before is suddenly blocked — and the error messages give you nothing useful.

Here's every cause and fix.


How NetworkPolicy Works (Quick Recap)

By default, all pod-to-pod traffic is allowed in Kubernetes. A NetworkPolicy changes this by selecting pods and defining allowed ingress/egress rules.

Critical rule: The moment ANY NetworkPolicy selects a pod, ALL traffic not explicitly allowed is denied for that pod.

This is the #1 source of confusion.


Symptom: Connection Refused / Timeout After Applying NetworkPolicy

Cause 1: Policy Selects the Pod But Has No Rules

yaml
# This policy DENIES ALL traffic to pods with app=myapp
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: oops-deny-all
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
  - Ingress
  # No ingress rules = deny all ingress

Any NetworkPolicy with policyTypes: [Ingress] and no ingress: rules blocks all ingress traffic.

Fix — add explicit allow rules:

yaml
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

Cause 2: Wrong Pod Label Selector

bash
# Check what labels your pods actually have
kubectl get pods -n myapp --show-labels
 
# Check what the NetworkPolicy is selecting
kubectl describe networkpolicy my-policy -n myapp

If the podSelector labels don't match any pod labels, the policy has no effect. But if they accidentally match pods you didn't intend, those pods get restricted.

Debug:

bash
# Find all NetworkPolicies affecting a specific pod
kubectl get networkpolicy -n myapp -o yaml | grep -A5 "podSelector"
 
# Check if a specific pod is selected by any policy
kubectl get networkpolicy -n myapp -o json | \
  python3 -c "
import sys, json
data = json.load(sys.stdin)
for np in data['items']:
    sel = np['spec']['podSelector'].get('matchLabels', {})
    print(np['metadata']['name'], '->', sel)
"

Cause 3: Missing Namespace Selector for Cross-Namespace Traffic

This is the most common mistake. You want pods in namespace frontend to reach pods in namespace backend:

yaml
# WRONG — this only allows pods in the SAME namespace
ingress:
- from:
  - podSelector:
      matchLabels:
        app: frontend
 
# CORRECT — specify BOTH namespace and pod selector
ingress:
- from:
  - namespaceSelector:
      matchLabels:
        name: frontend
    podSelector:
      matchLabels:
        app: frontend

Note: When namespaceSelector and podSelector are in the same from item (same -), it's an AND condition. When they're separate items (separate -), it's an OR condition.

yaml
# AND condition (same - item) — pod must be in frontend namespace AND have app=frontend label
from:
- namespaceSelector:
    matchLabels:
      name: frontend
  podSelector:
    matchLabels:
      app: frontend
 
# OR condition (separate - items) — pod from frontend namespace OR any pod with app=frontend
from:
- namespaceSelector:
    matchLabels:
      name: frontend
- podSelector:
    matchLabels:
      app: frontend

Label your namespaces:

bash
kubectl label namespace frontend name=frontend
kubectl label namespace backend name=backend

Cause 4: DNS Broken (Port 53 Not Allowed)

After applying an egress NetworkPolicy, DNS resolution fails — pods can't resolve service names.

bash
# Test DNS from inside a pod
kubectl exec -it mypod -- nslookup kubernetes.default
# If this fails after applying egress policy, DNS is blocked

Fix — always allow DNS in egress policies:

yaml
spec:
  podSelector:
    matchLabels:
      app: myapp
  policyTypes:
  - Egress
  egress:
  - ports:                    # Allow DNS
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53
  - to:                       # Your other egress rules
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - protocol: TCP
      port: 8080

Cause 5: CNI Plugin Doesn't Support NetworkPolicy

Not all CNI plugins enforce NetworkPolicy. Flannel does NOT enforce NetworkPolicy by default.

CNI plugins that DO enforce NetworkPolicy:

  • ✅ Calico
  • ✅ Cilium
  • ✅ Weave Net
  • ✅ Antrea
  • ❌ Flannel (basic install — needs Calico alongside)
bash
# Check which CNI is installed
kubectl get pods -n kube-system | grep -E "calico|cilium|weave|flannel|antrea"
 
# On nodes, check CNI config
ls /etc/cni/net.d/

If you're on Flannel, NetworkPolicy objects are accepted by the API server but silently ignored. You need to install Calico or switch CNI.


Debugging NetworkPolicy

Tool 1: Check Effective Policies on a Pod

bash
# Cilium: show policies affecting a pod
kubectl exec -n kube-system cilium-xxxxx -- cilium endpoint list
kubectl exec -n kube-system cilium-xxxxx -- cilium policy get
 
# Calico: check policies on a node
calicoctl get networkpolicy -n myapp -o wide

Tool 2: Test Connectivity Directly

bash
# Run a debug pod and test connectivity
kubectl run debug --image=busybox --rm -it -- sh
 
# Inside debug pod:
wget -qO- http://my-service.my-namespace.svc.cluster.local:8080
nc -zv my-service.my-namespace 8080
nslookup my-service.my-namespace

Tool 3: Temporarily Remove Policy to Isolate

bash
# Delete policy to confirm it's the cause
kubectl delete networkpolicy my-policy -n myapp
 
# If traffic works after deletion → policy is the issue
# Reapply with correct rules

Common Patterns

Allow All Ingress (Open a specific pod)

yaml
spec:
  podSelector:
    matchLabels:
      app: myapp
  ingress:
  - {}  # Empty rule = allow all ingress

Default Deny All in Namespace

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}  # Selects all pods
  policyTypes:
  - Ingress
  - Egress

Allow Only from Same Namespace

yaml
ingress:
- from:
  - podSelector: {}  # Any pod in same namespace

Allow Prometheus Scraping

yaml
ingress:
- from:
  - namespaceSelector:
      matchLabels:
        name: monitoring
  ports:
  - port: 9090
    protocol: TCP

Related: Kubernetes Network Policies Complete Guide | Cilium eBPF Networking Guide | Kubernetes DNS Lookup Failing Fix

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments