אבטחת פודים ב-Kubernetes: הטמעת Pod Security Standards

כל פוד עם הרשאות יתר הוא נקודת כניסה פוטנציאלית לאשכול וסיכון לכל השירותים. אנו מטמיעים Pod Security Standards באופן מלא: מבצעים ביקורת, בוחרים מצב, מעבירים עומסי עבודה ללא השבתה ומוסרים לצוות מדיניויות ונהלים מוכנים. אנו מסירים מהמהנדסים בדיקה ידנית של הרשאות והופכים את אבטחת הפודים לתהליך מנוהל.

היכולות שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

Pod Security Standards: למה פודים מקבלים הרשאות מיותרות

תמונה אופיינית באשכול בן יותר משנה: במניפסטים מופיע privileged: true או hostNetwork: true, הקונטיינר רץ כ-root, ו-hostPath mount תיקיית node. אף אחד לא כתב את זה בזדון — את המניפסט העתיקו מדוגמה של מישהו אחר כדי ש«פשוט יעבוד», והוסיפו capability של kernel מיותרת בעצת פורום. אחר כך הקובץ חי ב-repository ומופרס בכל release, עד שמישהו מבחין בו.

למה זה לא נתפס: כברירת מחדל שום דבר לא מגביל. שרת ה-API של Kubernetes מקבל כל securityContext, אם ב-cluster לא הוגדרו admission controllers, וההרשאה ליצור pods ב-namespace ניתנת כמעט לכל service account.

Pod Security Standards קיימים כמערכת של profiles, אבל עד שלא מפעילים אותם על namespace מסוים, הם נשארים תיאור של רצוי, ולא בדיקה בזמן deployment.

המחיר של הרשאות יתר של קונטיינרים הוא מוחשי. pod privileged רואה התקנים של node ועוקף את בידוד ה-kernel — פגיעה בקונטיינר אחד הופכת לפגיעה בכל ה-node. הרצה כ-root יחד עם mount של תיקיית node או socket של runtime פותחת דרך ל-pods שכנים, ו-hostNetwork — ל-metadata רשת של הענן. חולשות בדרגת חומרה בינונית הופכות לקריטיות.

הצד השני: profiles נוקשים שוברים workloads לגיטימיים — אוספי metrics, סוכני רשת, דרייברים של storage. לכן השאלה היא לא «לאסור הכול», אלא «איך לתת בדיוק את ההרשאות הנדרשות ולא לשבור את ה-release». נסביר איך זה נסגר.

מה נותן מערך אבטחת pods מנוהל ב-cluster

לפני הטמעת policies, שיעור ה-workloads עם privileged נמדד באחוזים בודדים — וכמעט תמיד אלו חריגים שנשכחו. אחרי הפעלת Pod Security Standards במצב enforcement, קונטיינרים כאלה לא עוברים יצירה, ושיעור ה-pods עם privileged יורד לאפס בלי מעבר ידני על כל מניפסט.

  • שיעור ה-pods עם privileged — אפס כברירת מחדל; חריג מוגדר במפורש ועם scope, ולא על כל ה-cluster.
  • הגבלת הרשאות: הרצה ממשתמש לא privileged, root filesystem לקריאה בלבד, איסור הסלמת הרשאות.
  • הקטנת משטח התקיפה: מה-manifests נעלמים host paths, רשת ה-node ו-capabilities מיותרות של kernel — הנתיב הנפוץ ביותר ליציאה מגבולות ה-pod נסגר.
  • זמן בדיקה של תרחיש deployment חדש — דקות: ה-policy מסרבת בעת application של המניפסט, ולא אחרי יממה בגלל תקרית בפרודקשן.
  • Audit של מניפסטים נותן יומן הפרות ואזהרות: רואים אילו צוותים ושירותים עדיין לא הותאמו ל-profile.
  • סוג כשל שנעלם: בריחה מ-container, קריאת secrets מנקודת mount משותפת, הרשאות משתמעות על ה-node.

את המדידות האלה כדאי לקחת לא פעם אחת: ה-policy קשור ל-namespace, מניפסטים נבדקים לפני rollout, וחריגים חיים עם תאריך סקירה. אז ה-profile נשאר כלי עבודה, ולא מסמך שעוקפים אותו.

השוואת מצבי Pod Security: baseline ו-restricted

ב-Pod Security Standards יש שלוש רמות של policies, והבחירה ביניהן היא בחירה של סוג workload, ולא עיקרון «מחמיר יותר זה טוב יותר». הרמה privileged לא מטילה הגבלות: ה-pod מקבל גישה למשאבי host, לכן משאירים אותה רק ל-pods מערכתיים — דרייברים של רשת, סוכני monitoring של node.

baseline סוגרת את המסוכן בעליל: host network namespaces ותהליכים, הרצה כ-root, capability מיותרות. restricted מוסיפה דרישות ל-profile seccomp, root filesystem לקריאה בלבד, הרצה ממשתמש לא privileged, ואיפוס מפורש של כל ה-capabilities.

רמה מה מותר מתי מתאימה מגבלות ל-workload
privileged הכול, כולל host namespaces והתקנים pods מערכתיים: דרייברים של רשת, אוספי metrics של node אין הגנה — הרמה לא מגבילה את ה-pod
baseline קונטיינרים רגילים בלי גישה ל-host שירותים מורשתיים שאי אפשר לשכתב מהר נופלים pods עם mount של host paths, פורטים privileged, תהליכי root
restricted images תואמים ל-profile נוקשה שירותים חדשים וכל מה שבאמת ניתן לשפר צריך non-root, איפוס capability, seccomp ו-volume נפרד לכתיבה

להפעיל רמות מיד במצב enforcement זה מסוכן: מצב warning מחזיר רשימת הפרות בתשובת שרת ה-API וכותב אותן ל-audit log, בלי לחסום הרצה. הצוות רואה את פרופיל ה-workload האמיתי, מתקן מניפסטים, ורק אחר כך מעביר את ה-namespace למצב enforcement — קודם בשירותים חדשים, אחר כך בשאר.

איך אנחנו מטמיעים policies: audit, תכנית, בדיקה, מסירה

הטמעת Pod Security Standards היא לא תווית אחת על namespace. ה-policies חושפות את מה שהצטבר במניפסטים במשך שנים: קונטיינרים privileged, hostPath, hostNetwork, הרצה כ-root, capabilities מיותרות. לכן הולכים מ-inventory למצב רך ורק אחר כך לחסימה, עם דרך חזרה בכל שלב.

  1. Audit של ה-cluster ו-inventory של מניפסטים. אוספים workloads לפי namespaces, כולל CronJob, DaemonSet ואופרטורים, ומתעדים עבור כל אחד משתמש, הרשאות ו-mounts. התוצאה — טבלה «workload → כללים מופרים», ולא זרם כללי של אזהרות.
  2. תכנית מעבר. מפזרים workloads לפי שלושה profiles — מוגבל, בסיסי, privileged — ומחליטים אילו namespaces יקבלו מצב חוסם מיד, ואילו יעברו דרך מצב רך.
  3. הפעלה במצב רך. מציבים תגיות audit ואזהרות: ה-controller לא חוסם דבר, אבל כל הפרה נכנסת ל-events ול-log. כמה ימים של מצב כזה מראים את היקף התיקונים האמיתי בלי סיכון למערך ה-production.
  4. בדיקת קונפיגורציות. משכתבים מניפסטים ל-profile הנדרש: מסירים capabilities מיותרות, מוציאים hostPath לטובת volumes, מגדירים runAsNonRoot ו-seccomp. התיקונים עוברים review והרצה בסביבת בדיקות.
  5. מעבר workload. מפעילים חסימה לפי namespaces — מהפחות קריטיים לפרודקשן, עם מעקב אחרי דחיות וחזרה מהירה של התגית.
  6. מסירת נהלים. מוסרים policies כקוד ב-repository, כללים לשירותים חדשים, checklist ל-review של מניפסטים וסדר חריגים.

ארטיפקטים של הטמעה: policies גישה, roles ונהלים

צוות הלקוח מקבל לא סט פקודות חד-פעמיות, אלא ערכה עובדת שלפיה אפשר להיות בתורנות ולשנות policies בלעדינו. להלן מה בדיוק נשאר ב-repository ובמאגר הידע הפנימי אחרי הטמעת Pod Security Standards.

  • קונפיגורציות של cluster: מניפסטים של namespaces עם תגיות pod-security.kubernetes.io/enforce, audit ו-warn, רמות baseline או restricted שנבחרו, רשימת חריגים נפרדת ל-namespaces מערכתיים.
  • מטריצת roles: טבלה «namespace — רמת policy — מי רשאי להוציא workload מתחתיה», עם קישור ל-roles גישה והפרדה בין הזכות לשנות policy לבין הרשאות release.
  • תרשימי פריסת workload: אילו workloads חיים ב-profile נוקשה, ואיפה צריך privileged — עם ציון סיבה ובעלים, ולא עם הערה «נטפל בזה אחר כך».
  • נהלי אבטחה: סדר הוצאת policy — קודם מצבי audit ואזהרה על תעבורה חיה, אחר כך הפעלת מצב enforcement לפי קריטריון שסוכם מראש למספר ההפרות ב-log.
  • הוראות לתורנות: מה לעשות כשה-pod לא נוצר בגלל policy — איך לקרוא הודעת admission controller, איפה לחפש חריג, איך להחזיר שינוי בלי להסיר את כל המצב.
  • תיעוד למפתחים: מניפסט לדוגמה עם שדות חובה — הרצה לא כ-superuser, profile seccomp, root filesystem לקריאה בלבד, capabilities מאופסות.

כל סעיף נבדק בסביבת הלקוח וקשור ל-namespace מסוים, לכן מהנדס חדש נכנס לעבודה לפי מסמך, ולא לפי הזיכרון של קולגה.

מקרה בוחן: איך הסרנו pods privileged בלי downtime של שירותים

נקודת פתיחה

Cluster עם כמה עשרות צוותים: 46 namespaces, מתוכם 11 עם pods privileged — סוכן רשת, איסוף logs, דרייברים של nodes. Audit של Kubernetes הראה ש-88% מהקונטיינרים רצו בלי profile seccomp, ולשש מתוך עשרה workloads היה allowPrivilegeEscalation: true.

לא הייתה policy משותפת: כל namespace חי לפי כללים משלו, וכל שירות יכול היה לקבל mount של תיקיית node.

סדר המעבר

התחלנו ממצבי warn ו-audit בכל ה-namespaces — תוך שבוע אספנו דוח הפרות ופיצלנו אותן לשלוש קבוצות: תיקון מניפסטים, החלפת images, חריגים מערכתיים.

אחר כך הפעלנו enforce בגלים: קודם שירותי stateless, לאחר מכן מערכי stateful עם volumes קבועים, ובאחרונים — סוכנים על כל node, שאי אפשר לעצור בלי לאבד את ה-node עצמו. workloads מערכתיים הועברו ל-namespaces נפרדים עם רמת baseline ורשימת הרשאות צרה לפי שמות.

לא היה downtime: העדכון נעשה דרך החלפה הדרגתית של replicas עם בדיקת readiness, ולא דרך restart של כל המערך.

תוצאה

תוצאה מעשית אחרי שני release cycles: pods privileged ב-namespaces עובדים — אפס, שיעור הקונטיינרים בלי seccomp ירד מ-88% ל-4%. דחיות בשלב admission בזמן rollout — אפס אחרי השבועיים הראשונים, כשהצוותים התרגלו לדרישות החדשות.

הרצה כ-root ו-mount של תיקיות node סגורים, ושירות חדש מקבל כברירת מחדל profile restricted ולא דורש אישורים נפרדים מהאבטחה.

מה לעשות אם ב-cluster כבר פרוסים pods privileged?

policy אבטחת pods תוכננה ל-cluster נקי, שבו מניפסטים נכתבים מלכתחילה ל-profile נוקשה. ב-cluster עם workload מורשתי — אופרטורים ישנים, סוכני vendor, אוספי metrics — הפעלה ישירה של profile נוקשה מפילה שירותים עובדים.

לכן הצעד הראשון הוא לא איסור, אלא מצבי בדיקה בלי חסימה: ה-controller מעביר הכול, אבל מתעד אילו pods ולפי אילו כללים חורגים מה-policy.

תוך כמה ימים הרצה כזו נותנת רשימה מדויקת של מפרים והבעלים שלהם — בלי תקלה אחת. אחר כך ה-policy מופעלת לא בכל מקום בבת אחת, אלא לפי namespaces: תגית עם ה-profile הנדרש מוצבת על אלו שהמניפסטים שלהם כבר מוכנים. חריגות מוגדרות כ-exceptions בתוך ה-policy עצמה, ולא ככיבוי של ה-profile כולו.

Exception מתאר כללים קונקרטיים — mount של תיקיות host, הסלמת הרשאות, capabilities נוספות של kernel — ונקשר ל-namespace אחד. כל רשומה מקבלת סיבה, בעלים ותאריך סקירה. במקביל מתקנים מניפסטים: הרצה ממשתמש לא privileged, root filesystem לקריאה בלבד, איפוס capabilities מיותרות.

workload שאי אפשר לתקן — image של vendor שדורש privileged או גישה להתקנים — מוציאים ל-namespace נפרד עם profile מרוכך ומחזיקים שם עד החלפת הרכיב. זו אזור נסיגה גלוי ומנוהל, ולא חור ב-policy על כל ה-cluster.

תוקף החיים של הנסיגה — הדבר העיקרי. Exception בלי תאריך סקירה הופך לקבוע, ובעוד חצי שנה policy נוקשה קיימת רק על הנייר. אנחנו מנהלים registry של חריגים ובכל cycle מראים כמה יש, אילו פגו ומה מונע לסגור את השאר. אז profile נוקשה נשאר כלל ברירת מחדל, והנסיגות — ממוקדות ובולטות.

ספקות טכניים של צוותי הנדסה: סיכונים ותאימות

לפני ההפעלה כמעט כל צוות שואל את אותה קבוצת שאלות: האם הפרודקשן ייפול, מה לעשות עם רכיבים מערכתיים והאם יש דרך חזרה. להלן התשובות שאנחנו נותנים בהתחלה, וסדר הפעולות שמסיר את הסיכונים העיקריים של ההטמעה.

מה יקרה ל-pods שכבר רצים?

ה-policy בודקת pods ביצירה ולא בודקת מחדש את אלו שרצים — ברגע ההפעלה שום דבר לא נכבה. הסיכון הוא דחוי: בעדכון או restart מדורג ה-node ייצור מחדש את ה-pod, והוא לא יעבור בדיקה. לכן קודם מפעילים audit ומנתחים events.

מה לעשות עם רכיבים מערכתיים של ה-cluster?

תוספי רשת ו-storage, איסוף logs, monitoring ו-ingress controllers דורשים privileged או גישה ל-node. עבור ה-namespaces שלהם מגדירים exceptions מפורשים ורמה נפרדת במקום כיבוי ה-policy לגמרי — שאר ה-cluster נשאר תחת profile נוקשה.

מה הכי часто לא עובר בדיקה באפליקציות?

קונטיינרים privileged, mount של תיקיות node, הרצה כ-root, כתיבה ל-root filesystem, capabilities מיותרות של kernel. חלק נסגר בתיקון security context במניפסט, וחלק — בבנייה מחדש של image למשתמש לא privileged.

האם אפשר להחזיר שינויים?

כן: הרמה נקבעת בתגית על namespace, והסרת התגית מחזירה את ההתנהגות הקודמת תוך שניות, בלי לבנות מחדש את ה-cluster. הסתייגות — חזרה לא משחזרת pods שנדחו ב-enforcement, לכן מעבירים namespaces אחד אחד, עם מעקב בכל שלב.

נדון במשימה: נתאים מצב ותכנית מעבר

כדי להתאים מצב Pod Security Standards ולהרכיב תכנית הטמעה, מספיק snapshot ראשוני של ה-cluster: מספר namespaces, תגיות שכבר הוצבו, נוכחות workloads privileged. זה מספיק כדי לתת הערכת עבודה לפי שלבים, ולא לחשב בעיוורון.

מה צריך מכם:

  • רשימת namespaces עם בעלים וסדר rollout;
  • snapshot של מניפסטים נוכחיים או גישה לקונפיגורציה לקריאה בלבד;
  • רשימת workloads שצריכים privileged, host ports או volumes — עם נימוק;
  • חלון זמן שבו אפשר להפעיל audit ולראות אזהרות בלי להשפיע על פרודקשן;
  • איש קשר של מהנדס תורן בזמן המעבר ומידע על סביבת הבדיקות.

מה אנחנו נותנים בתמורה:

  • תכנית הטמעה: איזו רמת policies שמים על איזה namespace ואיפה מתירים exceptions;
  • תוכנית מעבר — קודם audit, אחר כך אזהרות, אחר כך enforcement, עם נקודת חזרה בכל שלב;
  • הערכת עבודה לפי שלבים עם סימון מה הולך במקביל ומה דורש חלון;
  • exceptions כ-roles נפרדים עם הגבלת scope ותוקף חיים;
  • נוהל לניתוח התראות ותזכורת לצוותי הפיתוח.

תארו את המשימה בצורה חופשית — נדון בה ונחזור עם הערכה ותכנית מעבר שמותאמת לחלונות התחזוקה שלכם.