Free lesson · CKA Prep Program · Module 4: Services and networking
Lock Traffic Down with NetworkPolicies
Without policies, every pod talks to every pod. NetworkPolicy adds the firewall; this lesson writes rules that allow exactly the needed flows and proves the rest are closed.
13 min reading
Objectives
- Explain the default-allow baseline and what a policy changes
- Write ingress plus egress rules with pod, namespace and IP selectors
- Isolate one namespace so only named clients reach named ports
- Prove a policy works with connection tests from allowed and denied pods
Why this matters
Flat networking is the default and the exam assumes you know it: any pod reaches any pod IP unless something says no. NetworkPolicy is that something, enforced by the CNI plugin. Policies are allow-lists, so the skill is enumerating legitimate flows completely, because the first forgotten flow is the first outage after lockdown.
Concepts
A policy selects pods it guards (podSelector, empty selects all in the namespace) and lists allowed ingress plus egress entries. Anything not allowed is denied once at least one policy selects the pod: no policy means open, one policy means default deny plus exceptions. Entries combine three peer kinds: podSelector (pods by label, same namespace unless paired), namespaceSelector (whole namespaces), and ipBlock (outside CIDRs, egress mostly). Ports narrow each entry to protocols plus numbers.
The classic rollout is deny-all first (empty ingress plus empty egress on all pods), then per-app allow rules, testing after each. Egress to kube-system DNS (UDP 53) is the forgotten rule that breaks name resolution cluster-wide: allow it explicitly or every lookup times out.
Worked example
Namespace demo locked down, API reachable only from frontend on port 8080, DNS kept working:
# 1. deny-all baseline
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: deny-all, namespace: demo }
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
# 2. the legitimate flows
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: api-allow, namespace: demo }
spec:
podSelector: { matchLabels: { app: api } }
policyTypes: [Ingress, Egress]
ingress:
- from: [{ podSelector: { matchLabels: { app: frontend } } }]
ports: [{ protocol: TCP, port: 8080 }]
egress:
- to: [{ namespaceSelector: {}, podSelector: { matchLabels: { k8s-app: kube-dns } } }]
ports: [{ protocol: UDP, port: 53 }]Prove it from both sides: kubectl exec into frontend curls the API fine, while a third debug pod times out. Timeout from the denied pod plus success from the allowed one is the whole test.
Exam notes
Policies need a enforcing CNI: on clusters without one they are silently ignored, so confirm enforcement exists before trusting a test. podSelector: {} guards every pod in the namespace, which surprises writers who meant one app. And egress DNS on TCP 53 matters for large responses: allow both UDP and TCP 53 to be safe.
Quick check
A 4-question self-check. Your answers stay on your device, are never stored or sent. Only a passing score (for example 3 of 4) is saved, and only to unlock lesson progress: at least 3 correct is required before a lesson counts as complete. It never counts toward any certification assessment.
Lesson feedback
No published feedback yet.
Log in and complete the lesson to leave feedback.
Exercise
Isolate a fictional payments namespace: only the checkout pods reach the ledger pods on 8443, nothing else enters, DNS keeps working. Show both policies and the two-sided connection test with expected results.
Pass criteria
Deny-all plus precise allow policy with podSelector, port 8443 and DNS egress; allowed-side success plus denied-side timeout both shown.