ЁЯЫВ рдзрдбрд╛ 12 тАФ Admission рдЖрдгрд┐ pod security: pod рдЪрд╛рд▓рдгреНрдпрд╛рдЖрдзреА рджрд░рд╡рд╛рдЬрд╛рд╡рд░рдЪреА рддрдкрд╛рд╕рдгреА
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 16 рдкреИрдХреА рдзрдбрд╛ 12 ┬╖ рдорд╛рдЧреАрд▓: lesson-11-k8s-secrets-network ┬╖ рдкреБрдвреАрд▓: lesson-13-dependencies
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ11, рдЖрдгрд┐ Kubernetes рдЪреЗ рд╢реЗрд╡рдЯрдЪреЗ рджрд╛рд░: admission. "рд╣рд╛ user pods рддрдпрд╛рд░ рдХрд░реВ рд╢рдХрддреЛ" рдЕрд╕реЗ RBAC рдореНрд╣рдЯрд▓реНрдпрд╛рдирдВрддрд░, admission controllers pod рдЪреНрдпрд╛ рдЖрдд рдкрд╛рд╣рддрд╛рдд рдЖрдгрд┐ рддреЛ рдЪрд╛рд▓реВ рд╢рдХрддреЛ рдХрд╛ рддреЗ рдард░рд╡рддрд╛рдд. рддреБрдореНрд╣реА рддреАрди Pod Security Standards (privileged, baseline, restricted), namespace labels рд╕рд╣ Pod Security Admission, рдЖрдгрд┐ standards рдордзреНрдпреЗ рди рдпреЗрдгрд╛рд▒реНрдпрд╛ рдирд┐рдпрдорд╛рдВрд╕рд╛рдареА policy engines (Kyverno, OPA Gatekeeper) рд╢рд┐рдХрддрд╛ тАФ рдЬрд╕реЗ pinned images рдЖрдгрд┐ resource limits.
- sec/cloud.py тАФ
admit(pod): "restricted" рдкрджреНрдзрддреАрдЪреА policy pod рдирд╛рдХрд╛рд░реЗрд▓ рддреА рдХрд╛рд░рдгреЗ - sec/demo.py тАФ
python3 sec/demo.py admission - sec/test_sec.py тАФ check
L12
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдХрддрд░рд┐рдирд╛рдХрдбреЗ рдПрдХ keycard (RBAC) рдЖрд╣реЗ рдЬреНрдпрд╛рдореБрд│реЗ рддреА рдкрд░рд┐рд╕рд░рд╛рдд рдПрдХрд╛ рдкрд╛рд╣реБрдгреНрдпрд╛рд▓рд╛ рдЖрдгреВ рд╢рдХрддреЗ. рдкрдг рджрд░рд╡рд╛рдЬрд╛рд╡рд░ рджреАрдкрд┐рдХрд╛рдЪреА team рддрд░реАрд╣реА рдкрд╛рд╣реБрдгреНрдпрд╛рд▓рд╛ рддрдкрд╛рд╕рддреЗ:
- ЁЯФС Master key рдирд╛рд╣реА. рдкрд╛рд╣реБрдгреЗ рдкреНрд░рддреНрдпреЗрдХ рджрд╛рд░ рдЙрдШрдбрдгрд╛рд░реА рдЪрд╛рд╡реА рдмрд╛рд│рдЧреВ рд╢рдХрдд рдирд╛рд╣реАрдд (privileged).
- ЁЯСд рдореБрдЦреНрдпрд╛рдзреНрдпрд╛рдкрдХ рдореНрд╣рдгреВрди рдирд╛рд╣реА. рдкрд╛рд╣реБрдгрд╛ рд╕рд╛рдзрд╛ рдкрд╛рд╣реБрдгрд╛ рдореНрд╣рдгреВрди рдпреЗрддреЛ, рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдо рдмрджрд▓реВ рд╢рдХрдгрд╛рд░реА рд╡реНрдпрдХреНрддреА рдореНрд╣рдгреВрди рдирд╛рд╣реА (root).
- ЁЯкЬ рд╢рд┐рдбреА рдирд╛рд╣реА. рдирдВрддрд░ рдЦреЛрд▓реНрдпрд╛рдВрдордзреНрдпреЗ рдЪрдврдгреНрдпрд╛рд╕рд╛рдареА рдкрд╛рд╣реБрдгрд╛ рд╢рд┐рдбреА рдЖрдгреВ рд╢рдХрдд рдирд╛рд╣реА (privilege escalation).
- ЁЯкЯ Boiler room рдЪреНрдпрд╛ рдЦрд┐рдбрдХреАрддреВрди рдирд╛рд╣реА. рдкрд╛рд╣реБрдгрд╛ рдЗрдорд╛рд░рддреАрдЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рдпрдВрддреНрд░рд╛рдВрдкрд░реНрдпрдВрдд рдЫрд┐рджреНрд░ рдкрд╛рдбреВ рд╢рдХрдд рдирд╛рд╣реА (hostPath тАФ node рдЪреА disk).
- ЁЯП╖я╕П рдкреВрд░реНрдг рдирд╛рд╡рд╛рдЪрд╛ рдмрд┐рд▓реНрд▓рд╛. "рдкрд╛рд╣реБрдгрд╛" рд╣реЗ рдирд╛рд╡ рдирд╛рд╣реА. "Results app, version 1.4.2" рд╣реЗ рдирд╛рд╡ рдЖрд╣реЗ тАФ рдЖрдгрд┐
рддреНрдпрд╛рд╡рд░рдЪрд╛ рдлреЛрдЯреЛ рдЬреБрд│рд╛рдпрд▓рд╛ рд╣рд╡рд╛ (pinned image tag рдЖрдгрд┐ digest,
:latestрдирд╛рд╣реА). - ЁЯН▒ рдЬреЗрд╡рдгрд╛рдЪреА рдорд░реНрдпрд╛рджрд╛. рдХреЛрдгрддрд╛рд╣реА рдкрд╛рд╣реБрдгрд╛ рдкреВрд░реНрдг рд╕реНрд╡рдпрдВрдкрд╛рдХрдШрд░ рд╕рдВрдкрд╡реВ рд╢рдХрдд рдирд╛рд╣реА (resource limits).
рдЖрдЬрдЪрд╛ рдкрд╣рд┐рд▓рд╛ рдкрд╛рд╣реБрдгрд╛ рд╕рд╣рд╛рд╣реА рдирд┐рдпрдо рдореЛрдбрддреЛ. рджрд░рд╡рд╛рдЬрд╛ рдирд╛рд╣реА рдореНрд╣рдгрддреЛ, рдЖрдгрд┐ рдпрд╛рджреА рджреЗрддреЛ. рдпрд╛рджреАрддрд▓реЗ рджреБрд░реБрд╕реНрдд рдХрд░рд╛, рдкрд░рдд рдпрд╛, рдЖрдгрд┐ рджрд░рд╡рд╛рдЬрд╛ рдЙрдШрдбрддреЛ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
k["ЁЯСй kubectl apply / CI"] --> a["ЁЯФР authentication"]
a --> r["тШ╕я╕П RBAC<br/>may create pods? (L10)"]
r --> m["тЬПя╕П mutating admission"]
m --> v{"ЁЯЫВ validating admission<br/>Pod Security Admission: restricted<br/>Kyverno / Gatekeeper / VAP"}
v -->|"тЭМ privileged ┬╖ root ┬╖ escalation<br/>hostPath ┬╖ :latest ┬╖ no limits"| no["403: rejected, with the reasons"]
v -->|"тЬЕ all rules pass"| etcd["ЁЯУТ stored тЖТ scheduled тЖТ runs"]
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/security/lesson-diagrams.html#l12
тЭУ рдХрд╛рдп
- Admission controller тАФ API server рдЪреНрдпрд╛ рдорд╛рд░реНрдЧрд╛рддрд▓рд╛ code рдЬреЛ authentication рдЖрдгрд┐ RBAC рдирдВрддрд░ рдЖрдгрд┐ object рд╕рд╛рдард╡рд▓рд╛ рдЬрд╛рдгреНрдпрд╛рдЖрдзреА рдЪрд╛рд▓рддреЛ. Mutating controllers object рдмрджрд▓реВ рд╢рдХрддрд╛рдд (рдПрдЦрд╛рджреА default рдЬреЛрдбрдгреЗ); validating controllers рдлрдХреНрдд рддреЛ рд╕реНрд╡реАрдХрд╛рд░реВ рдХрд┐рдВрд╡рд╛ рдирд╛рдХрд╛рд░реВ рд╢рдХрддрд╛рдд.
- Pod Security Standards тАФ Kubernetes project рдиреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ рддреАрди рдкрд╛рддрд│реНрдпрд╛:
- privileged тАФ рдХреЛрдгрддреНрдпрд╛рд╣реА рдорд░реНрдпрд╛рджрд╛ рдирд╛рд╣реАрдд (CNI рд╕рд╛рд░рдЦреНрдпрд╛ system pods рд╕рд╛рдареА);
- baseline тАФ рдУрд│рдЦреАрдЪреНрдпрд╛ рдореЛрдареНрдпрд╛ рдкрд│рд╡рд╛рдЯрд╛ рдерд╛рдВрдмрд╡рддреЗ: privileged containers, host namespaces,
hostPath, рдзреЛрдХрд╛рджрд╛рдпрдХ capabilities рдЬреЛрдбрдгреЗ; - restricted тАФ baseline рдЖрдгрд┐ hardening:
runAsNonRoot: true,allowPrivilegeEscalation: false, ALL capabilities drop рдХрд░рдгреЗ,RuntimeDefaultрдЪрд╛seccompProfile, рдЖрдгрд┐ рдлрдХреНрдд рд╕реБрд░рдХреНрд╖рд┐рдд volume types.
- Pod Security Admission (PSA) тАФ built-in controller рдЬреЛ рддреНрдпрд╛ рдкрд╛рддрд│реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ
namespace рд╡рд░ labels рдиреЗ рд▓рд╛рдЧреВ рдХрд░рддреЛ, рддреАрди modes рдордзреНрдпреЗ:
enforce(рдирд╛рдХрд╛рд░рдгреЗ),audit(audit log рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рдгреЗ) рдЖрдгрд┐warn(user рд▓рд╛ warning рджрд╛рдЦрд╡рдгреЗ).warnрдЖрдгрд┐auditрдиреЗ рд╕реБрд░реБрд╡рд╛рдд рдХрд░рд╛, рдордЧenforce. - PSA рдХрд╛рдп рддрдкрд╛рд╕рдд рдирд╛рд╣реА тАФ image tags, registries, resource limits, labels, signatures.
рддреНрдпрд╛рдВрдЪреНрдпрд╛рд╕рд╛рдареА policy engine рд▓рд╛рдЧрддреЛ:
- Kyverno тАФ Kubernetes YAML рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ policies;
- OPA Gatekeeper тАФ Rego рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ policies;
- ValidatingAdmissionPolicy тАФ Kubernetes рдордзреНрдпреЗрдЪ рдЕрд╕рд▓реЗрд▓реЗ (1.30 рдкрд╛рд╕реВрди stable), рдирд┐рдпрдо CEL рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ, рдЬрд╛рджрд╛ software рдирд╛рд╣реА.
- рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдо рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪрд╛:
- privileged тАФ container рд▓рд╛ host рдЪреА рдЬрд╡рд│рдЬрд╡рд│ рд╕рдЧрд│реА рддрд╛рдХрдж рдорд┐рд│рддреЗ; рддреНрдпрд╛рддреВрди рдирд┐рд╕рдЯрдгреЗ рд╕реЛрдкреЗ рдЕрд╕рддреЗ;
- root тАФ container escape bug node рд╡рд░ root рджреЗрддреЛ;
- allowPrivilegeEscalation тАФ process рд▓рд╛ рддреНрдпрд╛рдЪреНрдпрд╛ parent рдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд рд╣рдХреНрдХ рдорд┐рд│реВ рд╢рдХрддрд╛рдд (setuid);
- hostPath тАФ node рдЪреА disk;
/var/run/docker.sockрдХрд┐рдВрд╡рд╛/рдореНрд╣рдгрдЬреЗ рдкреВрд░реНрдг node; :latestрдХрд┐рдВрд╡рд╛ tag рдирд╛рд╣реА тАФ рдХрд╛рдп рдЪрд╛рд▓рддреЗ рддреЗ рдХрд│реВ рд╢рдХрдд рдирд╛рд╣реА, рдХрд┐рдВрд╡рд╛ "рддреНрдпрд╛рдЪ" рдЧреЛрд╖реНрдЯреАрдХрдбреЗ рдкрд░рдд rollback рдХрд░рддрд╛ рдпреЗрдд рдирд╛рд╣реА; digest (@sha256:тАж) рдиреЗрдордХреЗ bytes рд╕рд╛рдВрдЧрддреЛ;- limits рдирд╛рд╣реАрдд тАФ рдПрдХ pod node рдЪреА рдЙрдкрд╛рд╕рдорд╛рд░ рдХрд░реВ рд╢рдХрддреЛ (denial of service).
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг RBAC "рдХрддрд░рд┐рдирд╛ pods рддрдпрд╛рд░ рдХрд░реВ рд╢рдХрддреЗ рдХрд╛?" рдпрд╛рдЪреЗ рдЙрддреНрддрд░ рджреЗрддреЗ, "рддрд┐рдЪреНрдпрд╛ pod рдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ?" рдпрд╛рдЪреЗ рдирд╛рд╣реА. рдПрдЦрд╛рджреНрдпрд╛ namespace рдордзреНрдпреЗ pods рддрдпрд╛рд░ рдХрд░реВ рд╢рдХрдгрд╛рд░рд╛ рдХреЛрдгреАрд╣реА тАФ developer, CI pipeline, рдЪреЛрд░рд▓реЗрд▓рд╛ token тАФ рдирд╛рд╣реАрддрд░ node рдЪреА disk mount рдХреЗрд▓реЗрд▓рд╛ privileged pod рдЪрд╛рд▓рд╡реВрди node рддрд╛рдмреНрдпрд╛рдд рдШреЗрдК рд╢рдХрддреЛ, рдЖрдгрд┐ рддрд┐рдереВрди рддреНрдпрд╛рд╡рд░рдЪрд╛ рдкреНрд░рддреНрдпреЗрдХ pod. Admission рд╣реА рдЕрд╢реА рдПрдХрдореЗрд╡ рдЬрд╛рдЧрд╛ рдЖрд╣реЗ рдЬрд┐рдереВрди рдкреНрд░рддреНрдпреЗрдХ pod рдЬрд╛рддреЛ, рддреЛ рдХреЛрдгреАрд╣реА рдЖрдгрд┐ рдХрд╕рд╛рд╣реА рддрдпрд╛рд░ рдХреЗрд▓реЗрд▓рд╛ рдЕрд╕реЛ. рддрд┐рдерд▓рд╛ рдирд┐рдпрдо cluster рдЪреЗ рдЪреБрдХрд╛рдВрдкрд╛рд╕реВрди рдЖрдгрд┐ attackers рдкрд╛рд╕реВрди рд╕рд╛рд░рдЦреНрдпрд╛рдЪ рдкреНрд░рдХрд╛рд░реЗ рд╕рдВрд░рдХреНрд╖рдг рдХрд░рддреЛ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
sec/cloud.py рдордзрд▓реЗ admit(pod) pod["container"] рдЖрдгрд┐
pod.get("hostPath") рдкрд╛рд╣рддреЗ рдЖрдгрд┐ рдирд╛рдХрд╛рд░рдгреНрдпрд╛рдЪреА рдХрд╛рд░рдгреЗ рдЧреЛрд│рд╛ рдХрд░рддреЗ:
privileged: True;runAsNonRootTrueрд╡рд░ set рдХреЗрд▓реЗрд▓реЗ рдирд╛рд╣реА;allowPrivilegeEscalationFalseрд╡рд░ set рдХреЗрд▓реЗрд▓реЗ рдирд╛рд╣реА (рддреЗ рдирд╕реЗрд▓ рддрд░TrueрдЕрд╕рддреЗ, Kubernetes рд╕рд╛рд░рдЦреЗрдЪ);hostPathvolume;:latestрдиреЗ рд╕рдВрдкрдгрд╛рд░реА, рдХрд┐рдВрд╡рд╛ рдЕрдЬрд┐рдмрд╛рдд:рдирд╕рд▓реЗрд▓реА image;limitsрдирд╛рд╣реАрдд.
рддреЗ (True, []) рдХрд┐рдВрд╡рд╛ (False, [reasons]) рдкрд░рдд рдХрд░рддреЗ. рдкрд╣рд┐рд▓реНрдпрд╛ рдЪрд╛рд░ Pod Security
Standards рдЪреНрдпрд╛ рдХрд▓реНрдкрдирд╛ рдЖрд╣реЗрдд; рд╢реЗрд╡рдЯрдЪреЗ рджреЛрди policy engine рдирд┐рдпрдо рдЖрд╣реЗрдд тАФ model рддреНрдпрд╛рдВрдирд╛ рдПрдХрддреНрд░ рдареЗрд╡рддреЗ,
рдПрдХрдЪ рджрд╛рд░ рдореНрд╣рдгреВрди. sec/demo.py рдордзрд▓реЗ admission() рдПрдХ рд╡рд╛рдИрдЯ pod рдЖрдгрд┐ рдПрдХ рджреБрд░реБрд╕реНрдд
pod рд╡рд╛рдкрд░реВрди рдкрд╛рд╣рддреЗ. Snippet рд╡рд╛рдИрдЯ pod рдПрдХрд╛ рд╡реЗрд│реА рдПрдХ рдирд┐рдпрдо рдЕрд╕рд╛ рджреБрд░реБрд╕реНрдд рдХрд░рддреЛ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 sec/demo.py admission
python3 - <<'EOF'
import sys; sys.path.insert(0, "sec"); from cloud import admit
c = dict(image="school/results", privileged=True); pod = dict(container=c, hostPath="/var/run/docker.sock")
steps = (("first try", lambda: None),
("privileged off", lambda: c.update(privileged=False)),
("run as non-root", lambda: c.update(runAsNonRoot=True)),
("no escalation", lambda: c.update(allowPrivilegeEscalation=False)),
("no hostPath", lambda: pod.pop("hostPath")),
("tag :latest", lambda: c.update(image="school/results:latest")),
("pinned digest", lambda: c.update(image="school/results:1.4.2@sha256:9f1c")),
("limits", lambda: c.update(limits={"cpu": "500m", "memory": "256Mi"})))
for name, fix in steps:
fix(); ok, why = admit(pod)
print(f"{name:<16} тЖТ {'admitted' if ok else f'{len(why)} left: ' + '; '.join(why)}")
EOF
python3 sec/test_sec.py
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
admission рд╣реЗ рдЫрд╛рдкрддреЗ:
тХРтХРтХР admission тХРтХРтХР
тФАтФА first try тЖТ rejected: privileged container; may run as root (set runAsNonRoot: true); allowPrivilegeEscalation not false; mounts a hostPath volume; image has no pinned tag/digest; no resource limits
тФАтФА fixed тЖТ admitted
enforce with Pod Security Admission (restricted) or a policy engine (Kyverno / OPA Gatekeeper)
тЬЕ done тАФ every door checked
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
first try тЖТ 6 left: privileged container; may run as root (set runAsNonRoot: true); allowPrivilegeEscalation not false; mounts a hostPath volume; image has no pinned tag/digest; no resource limits
privileged off тЖТ 5 left: may run as root (set runAsNonRoot: true); allowPrivilegeEscalation not false; mounts a hostPath volume; image has no pinned tag/digest; no resource limits
run as non-root тЖТ 4 left: allowPrivilegeEscalation not false; mounts a hostPath volume; image has no pinned tag/digest; no resource limits
no escalation тЖТ 3 left: mounts a hostPath volume; image has no pinned tag/digest; no resource limits
no hostPath тЖТ 2 left: image has no pinned tag/digest; no resource limits
tag :latest тЖТ 2 left: image has no pinned tag/digest; no resource limits
pinned digest тЖТ 1 left: no resource limits
limits тЖТ admitted
Tests рдордзреНрдпреЗ тЬЕ L12 admission rejects a privileged, unpinned pod рдЖрд╣реЗ рдЖрдгрд┐ рд╢реЗрд╡рдЯ
16/16 passed рдиреЗ рд╣реЛрддреЛ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдкреНрд░рддреНрдпреЗрдХ рджреБрд░реБрд╕реНрддреА рдиреЗрдордХреЗ рдПрдХ рдХрд╛рд░рдг рдХрд╛рдвреВрди рдЯрд╛рдХрддреЗ, рдЖрдгрд┐ рд╕рд╣рд╛рд╣реА рдЧреЗрд▓реНрдпрд╛рд╡рд░рдЪ рджрд╛рд░ рдЙрдШрдбрддреЗ.
:latest tag рдЬреЛрдбрд▓реНрдпрд╛рдиреЗ рдорджрдд рдЭрд╛рд▓реА рдирд╛рд╣реА тАФ рддреЛ рд╣рд▓рдгрд╛рд░рд╛ tag рдЖрд╣реЗ, рдореНрд╣рдгреВрди рд╕рдВрдЦреНрдпрд╛ 2 рд╡рд░рдЪ рд░рд╛рд╣рд┐рд▓реА.
рдлрдХреНрдд digest рд╕рд╣ рдЦрд▒реНрдпрд╛ version рдиреЗ рддреЗ рджреБрд░реБрд╕реНрдд рдЭрд╛рд▓реЗ. Default рдиреЗ рдХрд╛рдп рдирд╡реНрд╣рддреЗ рд╣реЗ рд╕реБрджреНрдзрд╛ рд▓рдХреНрд╖рд╛рдд рдШреНрдпрд╛:
escalation рд╕рд╛рдареА рдзреЛрдХрд╛рджрд╛рдпрдХ рдард░рд╛рдпрд▓рд╛ pod рдиреЗ рдХрдзреАрдЪ "privileged: yes" рдореНрд╣рдЯрд▓реЗ рдирд╡реНрд╣рддреЗ тАФ allowPrivilegeEscalation
рддреБрдореНрд╣реА false рд▓рд┐рд╣реАрдкрд░реНрдпрдВрдд true рдореНрд╣рдгреВрди рдЧрдгрд▓реЗ рдЬрд╛рддреЗ. рд╕реБрд░рдХреНрд╖рд┐рдд settings рд▓рд┐рд╣рд╛рд╡реНрдпрд╛ рд▓рд╛рдЧрддрд╛рдд.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рдЖрдзреА
warnрд╡рд╛рдкрд░реВрди рди рдкрд╛рд╣рддрд╛, рдЪрд╛рд▓реВ pods рдиреЗ рднрд░рд▓реЗрд▓реНрдпрд╛ namespace рд╡рд░enforce: restrictedтАФ рдкреБрдврдЪрд╛ rollout fail рд╣реЛрддреЛ - рдПрдХрд╛ namespace рд▓рд╛ label рд▓рд╛рд╡рдгреЗ рдЖрдгрд┐ рдирд╡реЗ namespaces рд╡рд┐рд╕рд░рдгреЗ тАФ labels namespace template рдордзреНрдпреЗ
рдЬреЛрдбрд╛, рдХрд┐рдВрд╡рд╛
AdmissionConfigurationрдордзреНрдпреЗ cluster defaults рд▓рд╛рд╡рд╛ - рдПрдХрд╛ pod рд▓рд╛
hostPathрд▓рд╛рдЧрддреЛ рдореНрд╣рдгреВрди "рдЖрддреНрддрд╛рдкреБрд░рддреЗ" рдкреВрд░реНрдг namespace рд▓рд╛ рд╕реВрдЯ рджреЗрдгреЗ - PSA image tags рдХрд┐рдВрд╡рд╛ limits рддрдкрд╛рд╕рддреЗ рдЕрд╕реЗ рдорд╛рдирдгреЗ тАФ рддреЗ рддрдкрд╛рд╕рдд рдирд╛рд╣реА; рддреБрдореНрд╣рд╛рд▓рд╛ policy engine рд▓рд╛рдЧрддреЛ
- рд╡рд░реНрд╖рднрд░
Auditmode рдордзреНрдпреЗ рдЕрд╕рд▓реЗрд▓рд╛ policy engine: рддреЛ report рдХрд░рддреЛ, рдХреЛрдгреА рд╡рд╛рдЪрдд рдирд╛рд╣реА, рдХрд╛рд╣реАрдЪ block рд╣реЛрдд рдирд╛рд╣реА failurePolicy: IgnoreрдЕрд╕рд▓реЗрд▓рд╛ webhook policy engine тАФ рддреЛ рдмрдВрдж рдкрдбрд▓рд╛ рдХреА рд╕рдЧрд│реЗрдЪ admit рд╣реЛрддреЗ- рдЬреНрдпрд╛ image рдЪрд╛ user root рдЖрд╣реЗ рддрд┐рдЪреНрдпрд╛рд╕реЛрдмрдд
runAsNonRoot: trueтАФ pod start рд╣реЛрддрд╛рдирд╛рдЪ рдирд╛рдХрд╛рд░рд▓рд╛ рдЬрд╛рддреЛ; image numeric non-rootUSERрд╕рд╣ build рдХрд░рд╛
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ account рд╡рд░ тАФ school namespace рд╡рд░ Pod Security Admission. рдЖрдзреА рдХрд╛рдп
рддреБрдЯреЗрд▓ рддреЗ рдкрд╛рд╣рд╛, рдордЧ enforce рдХрд░рд╛:
kubectl label --dry-run=server --overwrite ns school pod-security.kubernetes.io/enforce=restricted
apiVersion: v1
kind: Namespace
metadata:
name: school
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
restricted (рдЖрдгрд┐ рдЦрд╛рд▓рдЪреЗ policy engine рдирд┐рдпрдо) рдкрд╛рд╕ рдХрд░рдгрд╛рд░рд╛ pod spec:
apiVersion: apps/v1
kind: Deployment
metadata: { name: results-api, namespace: school }
spec:
replicas: 3
selector: { matchLabels: { app: results-api } }
template:
metadata: { labels: { app: results-api } }
spec:
serviceAccountName: results-api
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 10001
seccompProfile: { type: RuntimeDefault }
containers:
- name: api
image: ghcr.io/baluraut/school-results:1.4.2@sha256:<the image digest from CI>
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities: { drop: ["ALL"] }
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { cpu: 500m, memory: 256Mi }
PSA рддрдкрд╛рд╕рдд рдирд╛рд╣реА рддреНрдпрд╛рд╕рд╛рдареА Kyverno тАФ :latest рдирд╛рд╣реА, рдЖрдгрд┐ CPU рд╡ memory limits
рдмрдВрдзрдирдХрд╛рд░рдХ (Kyverno 1.13+ рдкреНрд░рддреНрдпреЗрдХ рдирд┐рдпрдорд╛рд╡рд░ failureAction рдареЗрд╡рддреЛ; рдЬреБрдиреНрдпрд╛ releases рдордзреНрдпреЗ
spec.validationFailureAction рд╡рд╛рдкрд░рд▓реЗ рдЬрд╛рддреЗ):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata: { name: school-pod-rules }
spec:
background: true
rules:
- name: no-latest-tag
match: { any: [{ resources: { kinds: [Pod] } }] }
validate:
failureAction: Enforce
message: "Use a pinned version tag or a digest, not :latest."
pattern:
spec:
containers:
- image: "!*:latest"
- name: require-limits
match: { any: [{ resources: { kinds: [Pod] } }] }
validate:
failureAction: Enforce
message: "CPU and memory limits are required."
pattern:
spec:
containers:
- resources:
limits:
cpu: "?*"
memory: "?*"
рддреЛрдЪ limits рдирд┐рдпрдо, Kubernetes рдордзреНрдпреЗрдЪ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ ValidatingAdmissionPolicy (CEL) рдЖрдгрд┐ рддреНрдпрд╛рдЪреНрдпрд╛ binding рд╕рд╣:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata: { name: require-limits }
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
validations:
- expression: "object.spec.containers.all(c, has(c.resources) && has(c.resources.limits) && 'memory' in c.resources.limits && 'cpu' in c.resources.limits)"
message: "every container needs CPU and memory limits"
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata: { name: require-limits-school }
spec:
policyName: require-limits
validationActions: [Deny]
matchResources:
namespaceSelector: { matchLabels: { kubernetes.io/metadata.name: school } }
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдпрд╛рдЪ policies CI рдордзреНрдпреЗ рд╕реБрджреНрдзрд╛ рдЪрд╛рд▓рд╡рд╛ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде rendered manifests рд╡рд┐рд░реБрджреНрдз
kyverno apply), рдореНрд╣рдгрдЬреЗ developer рд▓рд╛ "rejected: no limits" pull request рдордзреНрдпреЗрдЪ рджрд┐рд╕реЗрд▓, rollout рджрд░рдореНрдпрд╛рди рд░рд╛рддреНрд░реА 2 рд╡рд╛рдЬрддрд╛ рдирд╛рд╣реА.
тПня╕П рдкреБрдвреЗ
Cluster рдЪреА рджрд╛рд░реЗ рдмрдВрдж рдЖрд╣реЗрдд: рдХреЛрдг рдХреГрддреА рдХрд░реВ рд╢рдХрддреЛ (RBAC), рдХреЛрдг connect рдХрд░реВ рд╢рдХрддреЛ (NetworkPolicy), рдХрд╛рдп рдЪрд╛рд▓реВ рд╢рдХрддреЗ (admission). рдкрдг pod рдЪреА image рдЗрддрд░рд╛рдВрдЪреНрдпрд╛ code рдиреЗ рднрд░рд▓реЗрд▓реА рдЖрд╣реЗ. рдкреБрдвреЗ: рд╡рд┐рддрд░рдг рдЦрд┐рдбрдХреА рдЙрдШрдбрддреЗ, dependencies рд╕рд╣.
git checkout lesson-13-dependencies