NetworkPolicy Default Deny and DNS
Isolation techniques is a Domain 1 competency and NetworkPolicy is the one you will be asked about. This guide applies a default-deny to a namespace and then watches DNS stop working, because egress means all egress including port 53.
Cloud Native Security Guide 8 of 42 Intermediate
- Kubernetesapiserver v1.36.4, kubelet v1.36.3
- Runtimecontainerd 2.2.6
- CNICilium 1.18.1 - tunnel/VXLAN, with Hubble relay and UI
- Host OSUbuntu 26.04 LTS, kernel 7.0.0-29
- Built withkubeadm v1.36.3 - podSubnet 10.244.0.0/16, serviceSubnet 10.96.0.0/12
- TimeAbout 14 min
- Reviewed25 August 2026
Written against the versions above. Enforced by Cilium 1.18.1. The manifest is the generic `networking.k8s.io/v1` kind, which is what KCSA asks about and what works under any CNI that implements policy - the behaviour shown here is not Cilium-specific.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| CKA5001 | 192.168.0.41 | Ubuntu 26.04 LTS | Control Plane Node (tainted NoSchedule) | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE01 | 192.168.0.42 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE02 | 192.168.0.43 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
| CKA5001-NODE03 | 192.168.0.44 | Ubuntu 26.04 LTS | Worker Node | 2 Core | 4 GB | 50 GB |
Before you start
- guide 3 - which showed zero policies and a flat, open Pod network.
-
Before: a Pod that can resolve and reach things
Establish the baseline, so the change is attributable.
bash Example session kubectl -n kcsa-open exec plain -- nslookup kubernetes.default.svc.cluster.local 2>&1 | tail -2; echo "--- DNS works before the policy" --- DNS works before the policyExpected resultThe lookup returns without error - the trailing lines are blank, but the next step's failure is unambiguous by contrast.
Success conditionYou have a before state.
-
Seven lines that deny everything
An empty podSelector, and both policy types.
bash Example session printf 'apiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n name: default-deny-all\nspec:\n podSelector: {}\n policyTypes: ["Ingress","Egress"]\n' | kubectl -n kcsa-open apply -f - 2>&1 | tail -1networkpolicy.networking.k8s.io/default-deny-all createdkubectl -n kcsa-open get networkpolicy default-deny-all -o custom-columns='NAME:.metadata.name,TYPES:.spec.policyTypes'; echo "--- an EMPTY podSelector selects every Pod in the namespace"NAME TYPESdefault-deny-all [Ingress Egress]--- an EMPTY podSelector selects every Pod in the namespaceExpected result
networkpolicy.networking.k8s.io/default-deny-all created, thenTYPES [Ingress Egress].Success conditionYou can write the policy every namespace should probably start with.
-
After: DNS is gone, and so is everything else
The same lookup that worked two steps ago.
bash Example session kubectl -n kcsa-open exec plain -- nslookup kubernetes.default.svc.cluster.local 2>&1 | tail -3; echo "--- DNS is egress too, and default-deny took it with everything else";; connection timed out; no servers could be reached command terminated with exit code 1--- DNS is egress too, and default-deny took it with everything elsekubectl -n kcsa-open exec plain -- sh -c 'wget -q -O- --timeout=4 https://kubernetes.default.svc/version 2>&1 | head -1'; echo "--- and the apiserver is gone as well"wget: bad address 'kubernetes.default.svc'--- and the apiserver is gone as wellExpected result
;; connection timed out; no servers could be reached, thenwget: bad address 'kubernetes.default.svc'.Success conditionYou know the first thing a default-deny breaks.
Troubleshooting
Everything breaks the moment a default-deny is applied.
Why: DNS is egress and was denied with everything else.
Fix:Add an egress allow for UDP and TCP 53 to the CoreDNS Pods in
kube-system.podSelector: {}assumed to select nothing.Why: An empty selector selects ALL Pods in the namespace.
Fix:Use a label selector to narrow it.
{}is deliberately everything.A NetworkPolicy has no effect at all.
Why: The CNI does not implement policy.
Fix:Confirm the CNI first. Cilium and Calico do; some do not.
Traffic still flows after a deny policy.
Why: Another policy allows it - policies are additive and there is no deny.
Fix:List every policy selecting that Pod. Any allow wins.
Failures look like DNS bugs but DNS is healthy.
Why: Egress policy is blocking port 53, so names do not resolve.
Fix:
nslookupfrom inside the Pod.bad addressmeans resolution, not connectivity.Expected namespaces to isolate traffic.
Why: They do not. Namespaces are a naming and RBAC boundary, not a network one.
Fix:NetworkPolicy is the network boundary, and it is opt-in per namespace.