→Distinguish a name-resolution failure from a connectivity failure
→Recognise an egress policy that forgot DNS
Cost — Free
— runs on kind or minikube.
Nothing to pay in the browser. Open the terminal runs this against a simulated cloud — the same API calls and the same commands, with no account and no bill. The figure above applies only if you build it in your own.
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.
Find out why they cannot talk.
Hands-on environment
Run this lab in a real terminal, free and in your browser. The environment is temporary and yours alone — break it as much as you like.
Opens in Killercoda, in a new tab — keep this page open for the steps.
Run it on your own machine
Run this lab on your own machine. One command starts the environment, with everything the lab needs already installed:
You will need:
docker
kubectl
kind
git clone https://github.com/EgyKode/EgyKode-lab.git
cd EgyKode-lab
./egykode start k8s
./egykode shell
You need Docker and Git installed. Everything else runs inside the environment. The first start downloads it and takes a few minutes; later starts are seconds.
Not sure what you already have? Run: npm run doctor — it checks and changes nothing.
Anything you tick here is your own record. EgyKode cannot see inside that terminal, so the success criteria stay self-assessed even when the environment checks your work for you.
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.
The rule it needs, and note that it names both protocols — DNS falls back to TCP
for responses too large for one datagram, so a UDP-only rule leaves a few lookups
hanging while most succeed:
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.