Kubernetes NetworkPolicy Blocks Pod Traffic — Connection Timeout
Fix connection timeouts between pods by auditing NetworkPolicies, allowing the intended ingress and egress, and verifying with DNS and port tests.
Symptoms
- One pod cannot reach another although both are Running and Ready
- Connections time out rather than getting refused
- Traffic works before a NetworkPolicy is applied
Possible causes
- A NetworkPolicy selects the pod and allows only specific ingress/egress
- Egress is default-deny and the pod cannot reach DNS or the target
- The policy selects pods by labels that changed
Diagnosis steps
List policies affecting the namespace
kubectl get networkpolicy -n <ns> -o yamlInterpretation
The selectors and allowed rules show which traffic is permitted and which is blocked.
Test DNS and a specific port from inside the pod
kubectl exec <pod> -- sh -c "nslookup db && nc -zv db 5432"Interpretation
DNS failure suggests egress to DNS is blocked; a port timeout suggests the target policy blocks it.
Root cause
Once a pod is selected by a NetworkPolicy, traffic not explicitly allowed is denied. With default-deny ingress and egress, connections time out because packets are dropped rather than refused, which looks different from a closed port.
Fix
Add policies that allow the specific ingress and egress the workload needs, explicitly permit DNS egress to kube-dns, and keep selectors aligned with stable pod labels.
Risk note
A broad allow-all policy defeats the purpose of segmentation; grant only the required ports and peers.
Verify the fix
Re-test connectivity from the pod and confirm DNS and the target port succeed; verify the intended and blocked peers behave as expected.
Symptoms
This debugging guide addresses “Kubernetes NetworkPolicy Blocks Pod Traffic — Connection Timeout”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.
Observed symptoms include:
- One pod cannot reach another although both are Running and Ready
- Connections time out rather than getting refused
- Traffic works before a NetworkPolicy is applied
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: List policies affecting the namespace
kubectl get networkpolicy -n <ns> -o yaml
The selectors and allowed rules show which traffic is permitted and which is blocked.
Step 2: Test DNS and a specific port from inside the pod
kubectl exec <pod> -- sh -c "nslookup db && nc -zv db 5432"
DNS failure suggests egress to DNS is blocked; a port timeout suggests the target policy blocks it.
Likely contributors, in order of frequency:
- A NetworkPolicy selects the pod and allows only specific ingress/egress
- Egress is default-deny and the pod cannot reach DNS or the target
- The policy selects pods by labels that changed
Root Cause
Once a pod is selected by a NetworkPolicy, traffic not explicitly allowed is denied. With default-deny ingress and egress, connections time out because packets are dropped rather than refused, which looks different from a closed port.
The Fix
Add policies that allow the specific ingress and egress the workload needs, explicitly permit DNS egress to kube-dns, and keep selectors aligned with stable pod labels.
Watch out: A broad allow-all policy defeats the purpose of segmentation; grant only the required ports and peers.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-app-to-db
spec:
podSelector:
matchLabels: { app: db } # target
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels: { app: web } # allowed source
ports:
- protocol: TCP
port: 5432
---
# do not forget DNS egress when using default-deny egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
spec:
podSelector: {}
policyTypes: ["Egress"]
egress:
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
Verify and Prevent
Re-test connectivity from the pod and confirm DNS and the target port succeed; verify the intended and blocked peers behave as expected.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.