CKA — Kubernetes Administrator
Narrowing the Path With NetworkPolicy
Goal
You narrow down a NetworkPolicy from default deny through six forms, and in particular you tell the AND/OR structure of a from item apart by hand.
Why it matters
Let me be clear first. This lab environment has no CNI data plane to enforce policies. So you cannot verify whether traffic is actually blocked, and grading looks only at the object spec. This constraint actually resembles the exam. On the CKA too, what is mostly checked is whether the manifest is correct.
The mindset of a NetworkPolicy is different from a firewall. The moment even one policy selects a Pod, that Pod's traffic in the relevant direction (Ingress/Egress) switches to default deny, and only what the policies allow gets through. Policies only add up, and there is no such thing as a deny rule. That is why "one default-deny policy + as many allow policies as needed" is the standard pattern.
It is also a common incident to block DNS along with egress. If a Pod cannot resolve Service names, the symptom shows up as an application timeout rather than a network block, so diagnosis takes a long time.
Steps
- Create the namespaces
cka-netpol(labeltier=app) andcka-netpol-client(labeltier=client). Incka-netpol, create the Deploymentweb(2 replicas, imagenginx:1.27, Pod labelapp=web). - In
cka-netpol, create the NetworkPolicydefault-deny-ingress. The podSelector is an empty object, policyTypes is[Ingress], and there are no ingress rules. - Create the NetworkPolicy
allow-frontend. podSelectorapp=web; the ingress from has only one podSelector,app=frontend; port TCP 80. - Create the NetworkPolicy
allow-client-ns. podSelectorapp=web; the ingress from has only one namespaceSelector,tier=client(do not include a podSelector with it). - Create the NetworkPolicy
egress-dns-only. podSelectorapp=web, policyTypes[Egress], the egress to is the namespaceSelectorkubernetes.io/metadata.name=kube-system, with two ports, UDP 53 and TCP 53. - Create the NetworkPolicy
allow-cidr. podSelectorapp=web; the ingress from is an ipBlock with cidr10.0.0.0/16and10.0.5.0/24in except. - Create the NetworkPolicy
web-final. podSelectorapp=web, policyTypes[Ingress, Egress]. For ingress, put the namespaceSelectortier=clientand the podSelectorapp=frontendtogether inside a single from item, with port TCP 8080. For egress, the to is an ipBlock with cidr0.0.0.0/0and except169.254.169.254/32, with port TCP 443.
Reference
- Every namespace automatically gets the
kubernetes.io/metadata.namelabel. It is handy when selecting kube-system. - If you reread the stored form with
kubectl get netpol <이름> -n cka-netpol -o yaml(where the placeholder is the policy name), the AND/OR structure stands out. - Common mistake 1: splitting from into two items in step 7. Then it becomes OR, and every Pod in the client namespace gets through.
- Common mistake 2: writing
169.254.169.254/32as a separate to item instead of in except. except goes inside the ipBlock.
Prepare the target and the source
Create the namespaces cka-netpol (label tier=app) and cka-netpol-client (label tier=client). In cka-netpol, create the Deployment web (2 replicas, image nginx:1.27, Pod label app=web).
The namespace labels are the key that a namespaceSelector will pick later. Set the Pod labels exactly as well.
Default deny policy
In cka-netpol, create the NetworkPolicy default-deny-ingress. The podSelector is an empty object, policyTypes is [Ingress], and there are no ingress rules.
If you leave the podSelector as an empty object, every Pod in that namespace is a target. Writing no rules at all means deny everything.
Allow only Pods in the same namespace
Create the NetworkPolicy allow-frontend. podSelector app=web; the ingress from has only one podSelector, app=frontend; port TCP 80.
If you write only a podSelector in a from item, the scope is limited to the namespace that contains the policy. You must also specify the port.
Allow an entire other namespace
Create the NetworkPolicy allow-client-ns. podSelector app=web; the ingress from has only one namespaceSelector, tier=client (do not include a podSelector with it).
A namespaceSelector looks at the labels on the namespace. This time you must allow that whole namespace, so do not put a podSelector with it.
Block outgoing traffic except DNS
Create the NetworkPolicy egress-dns-only. podSelector app=web, policyTypes [Egress], the egress to is the namespaceSelector kubernetes.io/metadata.name=kube-system, with two ports, UDP 53 and TCP 53.
Every namespace automatically gets a label whose value is the same as its name. For DNS, UDP alone is sometimes not enough.
Allow by CIDR and exclude part of the range
Create the NetworkPolicy allow-cidr. podSelector app=web; the ingress from is an ipBlock with cidr 10.0.0.0/16 and 10.0.5.0/24 in except.
An ipBlock has a cidr and an except. The range in except must be contained within the cidr.
Putting it together: an AND condition and blocking the metadata range
Create the NetworkPolicy web-final. podSelector app=web, policyTypes [Ingress, Egress]. For ingress, put the namespaceSelector tier=client and the podSelector app=frontend together inside a single from item, with port TCP 8080. For egress, the to is an ipBlock with cidr 0.0.0.0/0 and except 169.254.169.254/32, with port TCP 443.
Splitting the from items in two gives OR, and using both selectors together inside one item gives AND. The position of a single dash changes the meaning.