The API Pods are Running and READY. The database Pods are Running and READY. The API logs show connection failures to the database, and nobody has changed either application.
By hand: deploy two services in one namespace, then apply a default-deny egress
NetworkPolicy that does not allow UDP 53 to kube-system.
Your CNI must enforce NetworkPolicy or this will not reproduce.
kind's default CNI (kindnet) accepts policies and silently ignores them, so
the calls will simply succeed and you will conclude the lab is broken. Use a
cluster with Calico or Cilium:
Terminal
minikube start --cni=calico# or kind with disableDefaultCNI: true, then apply Calico
Confirm enforcement is real before trusting any result:
Terminal
kubectl get pods -n kube-system -l k8s-app=calico-node
This is worth knowing beyond the lab: a NetworkPolicy that is accepted but not
enforced is a security control that exists only on paper, and nothing warns
you.
kubectl -n incident-03 get networkpolicykubectl -n incident-03 describe networkpolicy
Two properties cause most of these incidents:
A Pod selected by no policy is unrestricted. Security starts only when
something selects it — which is why a default-deny is usually the first
policy written, and why adding one breaks things that used to work.
Policies are additive with no deny rule. Traffic is allowed if any policy
allows it, so you cannot fix this by adding a deny — you widen an allow.
The classic mistake: a default-deny egress policy that permits traffic to the
database but forgets UDP 53 to CoreDNS. Every hostname lookup in the namespace
then times out, while the policy looks correct because the database rule is
right there.
Read this after you have fixed it, or after a genuine attempt. Being handed the answer costs you the only thing this tier teaches.
Root cause: a default-deny egress NetworkPolicy allows traffic to the database but not to CoreDNS. The API cannot resolve db, so it never opens a connection at all — the database rule is correct and never gets used.
The command that found it:nslookup db from inside the calling Pod timed out rather than returning NXDOMAIN. A timeout points at reachability of the resolver, not at a missing record.
The fix: add an egress rule permitting UDP 53 to the kube-system namespace.
Why everything looked healthy: the policy does exactly what it says, and both workloads are genuinely fine. Nothing reports an error, because from Kubernetes' point of view nothing is wrong.