ЁЯПл The SchoolтА║тШ╕я╕П KubernetesтА║ЁЯЪлЁЯУЭ рдзрдбрд╛ 19 тАФ NetworkPolicies: рдЪрд┐рдареНрдареНрдпрд╛ рдкрд╛рдард╡рдгреНрдпрд╛рдЪреЗ рдирд┐рдпрдо
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯЪлЁЯУЭ рдзрдбрд╛ 19 тАФ NetworkPolicies: рдЪрд┐рдареНрдареНрдпрд╛ рдкрд╛рдард╡рдгреНрдпрд╛рдЪреЗ рдирд┐рдпрдо

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: рдзрдбрд╛ 19 / 26 ┬╖ рдорд╛рдЧреАрд▓: lesson-18-jobs-cronjobs ┬╖ рдкреБрдвреАрд▓: lesson-20-taints-affinity


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдЖрдзреАрдЪреЗ рд╕рдЧрд│реЗ, рдЖрдгрд┐ cluster рдЪреНрдпрд╛ рдЖрдд рдХреЛрдг рдХреЛрдгрд╛рд╢реА рдмреЛрд▓реВ рд╢рдХрддреЗ рдпрд╛рд╡рд░ рдХреБрд▓реВрдк. рдЦрд░реА file:

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рдЖрд╢реНрдЪрд░реНрдп: рдирд╡реНрдпрд╛ cluster рдордзреНрдпреЗ рдкреНрд░рддреНрдпреЗрдХ pod рдкреНрд░рддреНрдпреЗрдХ pod рд╢реА рдХреБрдЬрдмреБрдЬреВ рд╢рдХрддреЛ ЁЯШ│ тАФ рдХреЛрдгрддреЗрд╣реА рдореВрд▓ рдХреЛрдгрддреНрдпрд╛рд╣реА рд╡рд░реНрдЧрд╛рддрд▓реНрдпрд╛ рдХреЛрдгрддреНрдпрд╛рд╣реА рдореБрд▓рд╛рд▓рд╛ рдЪрд┐рдареНрдареА рджреЗрдК рд╢рдХрддреЗ, рдереЗрдЯ рдЧреБрдгрдкрддреНрд░рд┐рдХреЗрдЪреНрдпрд╛ рд╡рд╣реАрдкрд░реНрдпрдВрддрд╕реБрджреНрдзрд╛. рдПрдХ compromised pod = рд╕рдВрдкреВрд░реНрдг рд╢рд╛рд│реЗрдЪреА рдореЛрдлрдд рд╕рдлрд░. (Security groups рдмрд╛рд╣реЗрд░реВрди рдмрд╛рдХрд╛рдВрдЪреЗ рд░рдХреНрд╖рдг рдХрд░рддрд╛рдд; рдЖрддрд▓реНрдпрд╛ рдЪрд┐рдареНрдареНрдпрд╛рдВрд╡рд░ рдХреЛрдгреАрдЪ рд▓рдХреНрд╖ рдареЗрд╡рдд рдирд╡реНрд╣рддреЗ.)

NetworkPolicies рдореНрд╣рдгрдЬреЗ рдЪрд┐рдареНрдареНрдпрд╛ рдкрд╛рдард╡рдгреНрдпрд╛рдЪреЗ рдирд┐рдпрдо:

  1. рдкрд╣рд┐рд▓рд╛ рд▓рд╛рд╡рд▓реЗрд▓рд╛ рдирд┐рдпрдо: "рдпрд╛ рд╡рд░реНрдЧрд╛рдд рдЕрдЬрд┐рдмрд╛рдд рдЪрд┐рдареНрдареНрдпрд╛ рдирд╛рд╣реАрдд" (default-deny тАФ рд░рд┐рдХрд╛рдорд╛ selector рдЕрд╕рд▓реЗрд▓реА policy, рдЬреА рдкреНрд░рддреНрдпреЗрдХ pod рдирд┐рд╡рдбрддреЗ). рдЬреНрдпрд╛ рдХреНрд╖рдгреА рдХреЛрдгрддреАрд╣реА policy рдПрдЦрд╛рджрд╛ pod рдирд┐рд╡рдбрддреЗ, рддреНрдпрд╛ рдХреНрд╖рдгреА рддреЛ pod рд╕реНрдкрд╖реНрдЯрдкрдгреЗ рдкрд░рд╡рд╛рдирдЧреА рди рджрд┐рд▓реЗрд▓реЗ рдХрд╛рд╣реАрд╣реА рд╕реНрд╡реАрдХрд╛рд░рдгреЗ рдерд╛рдВрдмрд╡рддреЛ.
  2. рдордЧ, рд╡рд░реНрдЧрд╛рд▓рд╛ рд▓рд╛рдЧрддрд╛рдд рддреЗрд╡рдвреНрдпрд╛рдЪ рдЪрд┐рдареНрдареНрдпрд╛рдВрдирд╛ рдкрд░рд╡рд╛рдирдЧреА рджреНрдпрд╛: "analytics school-api рд▓рд╛ рдЪрд┐рдареНрдареА рджреЗрдК рд╢рдХрддреЗ, рдлрдХреНрдд seat 3000" рдЖрдгрд┐ "рдлрд╛рдЯрдХ (ingress/ALB) рджреЛрдиреНрд╣реА apps рдирд╛ рдЪрд┐рдареНрдареА рджреЗрдК рд╢рдХрддреЗ". рд╕рдВрдкрд▓реЗ. рдЖрддрд╛ compromised pod рдкреЛрд╣реЛрдЪреВ рд╢рдХрддреЛтАж рдиреЗрдордХреЗ рдХрд╛рд╣реАрдЪ рдЬрд╛рд╕реНрддреАрдЪреЗ рдирд╛рд╣реА.

рдПрдХ рдкреНрд░рд╛рдорд╛рдгрд┐рдХ рдЕрдЯ: рдирд┐рдпрдо рддреЗрд╡реНрд╣рд╛рдЪ рдЪрд╛рд▓рддрд╛рдд рдЬреЗрд╡реНрд╣рд╛ рд╢рд╛рд│реЗрдиреЗ рддреЗ рд╡рд╛рдЪрдгрд╛рд░реА рд╢рд┐рдХреНрд╖рд┐рдХрд╛ рдиреЗрдорд▓реЗрд▓реА рдЕрд╕рддреЗ тАФ CNI рдиреЗ NetworkPolicy support рдХреЗрд▓реАрдЪ рдкрд╛рд╣рд┐рдЬреЗ. Minikube: --cni=calico рдиреЗ рд╕реБрд░реВ рдХрд░рд╛ (рдХрд┐рдВрд╡рд╛ enable рдХрд░рд╛). EKS: VPC CNI рдордзреНрдпреЗ network-policy switch рдЖрд╣реЗ (рдХрд┐рдВрд╡рд╛ Calico install рдХрд░рд╛). рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА рдХрд░рдгрд╛рд░рд╛ рдирд╛рд╣реА = рдирд┐рдпрдо рд╢рд╛рдВрддрдкрдгреЗ рджреБрд░реНрд▓рдХреНрд╖рд┐рдд тАФ рдиреЗрд╣рдореА test рдХрд░рд╛!

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
    subgraph before["ЁЯШ│ default: everyone whispers"]
        a1["ЁЯкС any pod"] ---|"any note"| b1["ЁЯкС any pod"]
    end
    subgraph after["ЁЯЪлЁЯУЭ with policies"]
        deny["1 default-deny:<br/>no notes at all"]
        allow1["2 allow: analytics тЖТ api :3000"]
        allow2["3 allow: gate тЖТ apps :3000/:8000"]
        blocked["тЭМ anything else: dropped"]
    end
    before -->|"apply k8s/network-policies.yaml"| after

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

Defense in depth: security groups (AWS L10) рдЗрдорд╛рд░рддреАрдЪреЗ рд░рдХреНрд╖рдг рдХрд░рддрд╛рдд, RBAC (L17) API рдЪреЗ рд░рдХреНрд╖рдг рдХрд░рддреЗ, NetworkPolicies pod-to-pod рдЪреЗ рд░рдХреНрд╖рдг рдХрд░рддрд╛рдд. рд╣рд╛ "attacker рд▓рд╛ рдПрдХ pod рдорд┐рд│рд╛рд▓рд╛" рдЖрдгрд┐ "attacker рд▓рд╛ рдПрдХ pod рдорд┐рд│рд╛рд▓рд╛ рдЖрдгрд┐ рдордЧ database" рдпрд╛рдВрддрд▓рд╛ рдлрд░рдХ рдЖрд╣реЗ. Auditors рд╣реЗ рдирд╛рд╡рд╛рдирд┐рд╢реА рдорд╛рдЧрддрд╛рдд.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛ (policy рд▓рд╛рдЧреВ рдХрд░рдгрд╛рд▒реНрдпрд╛ CNI рд╕рд╣ cluster)

# before: anyone can reach the api тАФ even a random debug pod:
kubectl -n school run spy --rm -it --image=curlimages/curl --restart=Never \
  -- curl -s -m 3 http://school-api && echo "ЁЯШ│ wide open"

# post the rules:
kubectl apply -f k8s/network-policies.yaml

# the spy is now blocked...
kubectl -n school run spy --rm -it --image=curlimages/curl --restart=Never \
  -- curl -s -m 3 http://school-api || echo "ЁЯЪл note intercepted!"

# ...but the real conversation still works (analytics wears the right label):
kubectl -n school exec deploy/school-analytics -- \
  python -c "import urllib.request;print(urllib.request.urlopen('http://school-api',timeout=3).status)"
# тЖТ 200 ЁЯОЙ  (if this ALSO fails: your CNI isn't enforcing тАФ see the catch above)

ЁЯФз рдпрд╛ рдзрдбреНрдпрд╛рд╕рд╛рдареА kubectl

kubectl get networkpolicy ┬╖ kubectl exec spy -- curl тАж

ЁЯФЧ рдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд: ЁЯкк AWS L10 (security groups) ┬╖ L21 (NACLs)

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд▓реЗ рдкрд╛рд╣рд┐рдЬреЗ

default-deny рдирдВрддрд░ spy pod рдЪрд╛ DB рдХрдбрдЪрд╛ curl time out рд╣реЛрддреЛ; analytics тЖТ api call рдЕрдЬреВрдирд╣реА рдЪрд╛рд▓рддреЛ.

ЁЯз╣ рд╕рд╛рдлрд╕рдлрд╛рдИ

kubectl delete networkpolicy тАж тАФ рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛ рдареЗрд╡рд╛, рддреНрдпрд╛рдЪ рддрд░ рдореБрджреНрджрд╛ рдЖрд╣реЗрдд

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

тПня╕П рдкреБрдвреЗ

рдХреЛрдгрддреЗ pods рдХреЛрдгрддреНрдпрд╛ рдмрд╛рдХрд╛рдВрд╡рд░ рдмрд╕реВ рд╢рдХрддрд╛рдд тАФ рд░рд╛рдЦреАрд╡ рдЬрд╛рдЧрд╛, allergy рдЯреЗрдмрд▓, рдЖрдгрд┐ рд╢рд┐рдХреНрд╖рд┐рдХреЗрдЪреА рдЦреБрд░реНрдЪреА: taints, tolerations рдЖрдгрд┐ affinity.

git checkout lesson-20-taints-affinity

ЁЯЪлЁЯУЭ Lesson 19 тАФ NetworkPolicies: passing-notes rules

ЁЯУН You are here: Lesson 19 of 26 ┬╖ Previous: lesson-18-jobs-cronjobs ┬╖ Next: lesson-20-taints-affinity


ЁЯУж What's in this branch

Everything before, plus locking down who may talk to whom inside the cluster. Real file:

ЁЯзТ Explain like I'm 5

Surprise: in a fresh cluster, every pod can whisper to every pod ЁЯШ│ тАФ any kid can pass a note to any other kid, in any classroom, including straight to the grade book. One compromised pod = free tour of the whole school. (Security groups guard the desks from outside; nobody's been watching the notes inside.)

NetworkPolicies are the passing-notes rules:

  1. First rule posted: "no notes at all in this classroom" (default-deny тАФ an empty-selector policy that selects every pod). The moment ANY policy selects a pod, that pod stops accepting anything not explicitly allowed.
  2. Then, allow exactly the notes the class needs: "analytics may pass notes to school-api, seat 3000 only" and "the gate (ingress/ALB) may pass notes to both apps". Done. A compromised pod can now reachтАж precisely nothing extra.

One honest catch: rules only work if the school hired a teacher who reads them тАФ the CNI must support NetworkPolicy. Minikube: start with --cni=calico (or enable it). EKS: VPC CNI has a network-policy switch (or install Calico). No enforcer = rules silently ignored тАФ always test!

ЁЯЧ║я╕П Diagram

flowchart LR
    subgraph before["ЁЯШ│ default: everyone whispers"]
        a1["ЁЯкС any pod"] ---|"any note"| b1["ЁЯкС any pod"]
    end
    subgraph after["ЁЯЪлЁЯУЭ with policies"]
        deny["1 default-deny:<br/>no notes at all"]
        allow1["2 allow: analytics тЖТ api :3000"]
        allow2["3 allow: gate тЖТ apps :3000/:8000"]
        blocked["тЭМ anything else: dropped"]
    end
    before -->|"apply k8s/network-policies.yaml"| after

тЭУ What

ЁЯдФ Why

Defense in depth: security groups (AWS L10) guard the building, RBAC (L17) guards the API, NetworkPolicies guard pod-to-pod. It's the difference between "attacker got one pod" and "attacker got one pod and then the database". Auditors ask for this by name.

ЁЯзк Try it (cluster with a policy-enforcing CNI)

# before: anyone can reach the api тАФ even a random debug pod:
kubectl -n school run spy --rm -it --image=curlimages/curl --restart=Never \
  -- curl -s -m 3 http://school-api && echo "ЁЯШ│ wide open"

# post the rules:
kubectl apply -f k8s/network-policies.yaml

# the spy is now blocked...
kubectl -n school run spy --rm -it --image=curlimages/curl --restart=Never \
  -- curl -s -m 3 http://school-api || echo "ЁЯЪл note intercepted!"

# ...but the real conversation still works (analytics wears the right label):
kubectl -n school exec deploy/school-analytics -- \
  python -c "import urllib.request;print(urllib.request.urlopen('http://school-api',timeout=3).status)"
# тЖТ 200 ЁЯОЙ  (if this ALSO fails: your CNI isn't enforcing тАФ see the catch above)

ЁЯФз kubectl for this lesson

kubectl get networkpolicy ┬╖ kubectl exec spy -- curl тАж

ЁЯФЧ Builds on: ЁЯкк AWS L10 (security groups) ┬╖ L21 (NACLs)

тЬЕ Verify тАФ what you should see

the spy pod's curl to the DB times out after the default-deny; the analytics тЖТ api call still works.

ЁЯз╣ Clean up

kubectl delete networkpolicy тАж тАФ or keep them, they're the point

тЪая╕П Common mistakes

тПня╕П Next

Which pods may sit at which desks тАФ reserved seats, allergy tables, and the teacher's chair: taints, tolerations & affinity.

git checkout lesson-20-taints-affinity
тЖР Previousjobs cronjobsNext тЖТtaints affinity

This page is the lesson's README from the lesson-19-network-policies branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.