בידוד עומסי העבודה במאגרי צמתים ייעודיים

בדף הזה מוסבר איך להפחית את הסיכון למתקפות של הסלמת הרשאות (privilege escalation) באשכול שלכם. כדי לעשות את זה, צריך להגדיר ב-Google Kubernetes Engine ‏(GKE) שעומסי העבודה שלכם יתוזמנו במאגר נפרד וייעודי של צמתים, ולא בעומסי עבודה מנוהלים עם הרשאות ב-GKE. כדאי להשתמש בגישה הזו רק אם אי אפשר להשתמש ב-GKE Sandbox. GKE Sandbox היא הגישה המומלצת לבידוד צמתים. ‫GKE Sandbox מספק גם יתרונות נוספים לחיזוק עומסי העבודה.

הדף הזה מיועד למומחי אבטחה שנדרש להם בידוד של עומסי עבודה, אבל הם לא יכולים להשתמש ב-GKE Sandbox. כדי לקבל מידע נוסף על תפקידים נפוצים ועל משימות לדוגמה שאנחנו מתייחסים אליהן ב Google Cloud תוכן, אפשר לעיין במאמר תפקידים נפוצים של משתמשי GKE ומשימות.

הדף הזה רלוונטי לאשכולות רגילים ללא הקצאת צמתים אוטומטית (NAP). כדי להפריד בין עומסי עבודה באשכולות Autopilot ובאשכולות Standard עם הקצאה אוטומטית של צמתים, אפשר לעיין במאמר הגדרת הפרדה בין עומסי עבודה ב-GKE.

סקירה כללית

באשכולות GKE נעשה שימוש בעומסי עבודה מנוהלים של GKE עם הרשאות מיוחדות כדי להפעיל פונקציות ותכונות ספציפיות של האשכול, כמו איסוף מדדים. לעומסי העבודה האלה מוקצות הרשאות מיוחדות כדי שהם יפעלו בצורה תקינה באשכול.

יכול להיות שעומסי עבודה שאתם פורסים בצמתים שלכם ייפגעו על ידי גורם זדוני. הפעלת עומסי העבודה האלה לצד עומסי עבודה מנוהלים ב-GKE עם הרשאות מיוחדות, מאפשרת לתוקף שפורץ מקונטיינר שנפרץ להשתמש בפרטי הכניסה של עומס העבודה עם ההרשאות המיוחדות בצומת כדי להרחיב את ההרשאות שלו באשכול.

מניעת בריחה מקונטיינר

ההגנה העיקרית שלכם צריכה להיות האפליקציות. ל-GKE יש כמה תכונות שבהן אפשר להשתמש כדי להקשיח את האשכולות וה-Pods. ברוב המקרים, מומלץ מאוד להשתמש ב-GKE Sandbox כדי לבודד את עומסי העבודה. ‫GKE Sandbox מבוסס על פרויקט הקוד הפתוח gVisor, ומיישם את Linux kernel API במרחב המשתמש. כל Pod פועל על ליבת מערכת הפעלה ייעודית שיוצרת ארגז חול לאפליקציות כדי למנוע גישה לקריאות מערכת עם הרשאות מיוחדות בליבת המארח. עומסי עבודה שפועלים ב-GKE Sandbox מתוזמנים אוטומטית בצמתים נפרדים, ומבודדים מעומסי עבודה אחרים.

כדאי גם לפעול לפי ההמלצות במאמר הקשחת האבטחה באשכול.

הימנעות מהתקפות של הסלמת הרשאות (privilege escalation)

אם אתם לא יכולים להשתמש ב-GKE Sandbox, ואתם רוצים שכבת בידוד נוספת בנוסף לאמצעי אבטחה אחרים, אתם יכולים להשתמש בnode taints ובnode affinity כדי לתזמן את עומסי העבודה שלכם במאגר צמתים ייעודי. הכתמת צומת אומרת ל-GKE להימנע מתזמון עומסי עבודה ללא טולרנטיות תואמת (כמו עומסי עבודה שמנוהלים על ידי GKE) בצמתים האלה. ההגדרה node affinity בעומסי העבודה שלכם אומרת ל-GKE לתזמן את ה-Pods שלכם בצמתים הייעודיים.

המגבלות של בידוד הצמתים

  • תוקפים עדיין יכולים ליזום התקפות מניעת שירות (DoS) מהצומת שנפרץ.
  • צמתים שנפרצו עדיין יכולים לקרוא משאבים רבים, כולל כל ה-Pods ומרחבי השמות באשכול.
  • צמתים שנפרצו יכולים לגשת לערכי Secrets ולפרטי הכניסה שמשמשים כל Pod שפועל בצומת הזה.
  • שימוש במאגר צמתים נפרד כדי לבודד את עומסי העבודה יכול להשפיע על היעילות של העלויות, על התאמה אוטומטית לעומס ועל ניצול המשאבים.
  • צמתים שנפרצו עדיין יכולים לעקוף את מדיניות הרשת לתעבורת נתונים יוצאת (egress).
  • חלק מעומסי העבודה שמנוהלים על ידי GKE חייבים לפעול בכל צומת באשכול, והם מוגדרים כך שיפעלו למרות כל ההגבלות.
  • אם פורסים DaemonSets עם הרשאות גבוהות שיכולים לסבול כל taint, יכול להיות שה-Pods האלה יהיו דרך להסלמת הרשאות מצומת שנפרצה.

איך פועל בידוד הצמתים

כדי להטמיע בידוד של צמתים בעומסי העבודה, צריך לבצע את הפעולות הבאות:

  1. הוספת כתם ותווית למאגר צמתים בשביל עומסי העבודה.
  2. מעדכנים את עומסי העבודה עם כלל הסבילות והזיקה לצומת המתאים.

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

לפני שמתחילים

לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:

  • מפעילים את ממשק ה-API של Google Kubernetes Engine.
  • הפעלת Google Kubernetes Engine API
  • אם רוצים להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה gcloud components update כדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
  • בוחרים שם ספציפי ל-taint של הצומת ולתווית הצומת שרוצים להשתמש בהם עבור מאגרי הצמתים הייעודיים.

הוספת כתם ותווית למאגר צמתים בשביל עומסי העבודה

יוצרים מאגר צמתים חדש לעומסי העבודה ומחילים עליו taint של צומת ותווית צומת. כשמחילים דחייה (taint) או תווית ברמת מאגר הצמתים, כל הצמתים החדשים, כמו אלה שנוצרו על ידי התאמה אוטומטית לעומס (automatic scaling), מקבלים באופן אוטומטי את הדחייה (taint) והתוויות שצוינו.

אפשר גם להוסיף כתמי צומת ותוויות צומת למאגרי צמתים קיימים. אם משתמשים באפקט NoExecute, ‏ GKE מוציא את כל ה-Pods שפועלים בצמתים האלה ושאין להם סבילות ל-taint החדש.

כדי לבודד עומסי עבודה, צריך להשתמש תמיד בקידומת node-restriction.kubernetes.io/ עבור תוויות הצמתים ועבור הסלקטורים התואמים במניפסטים של ה-Pod. הקידומת הזו מונעת מפורץ להשתמש בהרשאה של הצומת כדי להגדיר או לשנות את התוויות שמשתמשות בקידומת הזו. מידע נוסף זמין במאמר בנושא בידוד/הגבלה של צמתים במאמרי העזרה של Kubernetes.

כדי להוסיף taint ותווית למאגר צמתים חדש, מריצים את הפקודה הבאה:

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --node-taints=TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
    --node-labels=node-restriction.kubernetes.io/LABEL_KEY=LABEL_VALUE

מחליפים את מה שכתוב בשדות הבאים:

  • POOL_NAME: השם של מאגר הצמתים החדש לעומסי העבודה.
  • CLUSTER_NAME: השם של אשכול GKE.
  • TAINT_KEY=TAINT_VALUE: זוג מפתח/ערך שמשויך לתזמון TAINT_EFFECT. לדוגמה: workloadType=untrusted.
  • TAINT_EFFECT: אחד מערכי האפקט הבאים: NoSchedule,‏ PreferNoSchedule או NoExecute. ‫NoExecute מספקת התחייבות טובה יותר לפינוי מאשר NoSchedule.
  • node-restriction.kubernetes.io/LABEL_KEY=LABEL_VALUE: צמדי מפתח/ערך של תוויות הצמתים, שתואמים לסלקטורים שציינתם במניפסטים של עומסי העבודה. הקידומת node-restriction.kubernetes.io/ מונעת שימוש בפרטי הכניסה של הצומת כדי להגדיר את צמדי המפתח/הערך האלה בצמתים.

הוספת כלל טולרנטיות וכלל שיוך צומת לעומסי העבודה

אחרי שמוסיפים דחייה למאגר הצמתים הייעודי, אי אפשר לתזמן בו עומסי עבודה אלא אם יש להם טולרנטיות שמתאימה לדחייה שהוספתם. מוסיפים את ה-טולרנטיות למפרט של עומסי העבודה כדי לאפשר ל-Pod-ים האלה להיקבע לשימוש במאגר הצמתים עם הדחייה (taint).

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

בדוגמה הבאה מוסיפים toleration ל-taint‏ workloadType=untrusted:NoExecute וכלל של node affinity לתווית הצומת workloadType=untrusted.

kind: Deployment
apiVersion: apps/v1
metadata:
  name: my-app
  namespace: default
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      tolerations:
      - key: TAINT_KEY
        operator: Equal
        value: TAINT_VALUE
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: node-restriction.kubernetes.io/LABEL_KEY
                operator: In
                values:
                - "LABEL_VALUE"
      containers:
      - name: sleep
        image: ubuntu
        command: ["/bin/sleep", "inf"]

מחליפים את מה שכתוב בשדות הבאים:

  • TAINT_KEY: מפתח הכתם שהוחל על מאגר הצמתים הייעודי.
  • TAINT_VALUE: ערך ה-taint שהוחל על מאגר הצמתים הייעודי.
  • LABEL_KEY: מפתח התווית של הצומת שהוספתם למאגר הצמתים הייעודי.
  • LABEL_VALUE: ערך התווית של הצומת שהחלתם על מאגר הצמתים הייעודי.

כשמעדכנים את ה-Deployment באמצעות kubectl apply, ‏ GKE יוצר מחדש את ה-Pods המושפעים. כלל ההתאמה של הצומת מאלץ את ה-Pods להיכנס למאגר הצמתים הייעודי שיצרתם. הסבילות מאפשרת להציב רק את ה-Pods האלה בצמתים.

איך מוודאים שההפרדה פועלת

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

kubectl get pods -o=wide

המלצות ושיטות מומלצות

אחרי שמגדירים בידוד של צמתים, מומלץ לבצע את הפעולות הבאות:

  • כדי להגביל מאגרי צמתים ספציפיים רק לעומסי עבודה שמנוהלים על ידי GKE, מוסיפים את ה-taint‏ components.gke.io/gke-managed-components. הוספת ההכתמה הזו מונעת מה-Pods שלכם להיות מתוזמנים בצמתים האלה, וכך משפרת את הבידוד.
  • כשיוצרים מאגרי צמתים חדשים, אפשר למנוע את ההרצה של רוב עומסי העבודה שמנוהלים על ידי GKE בצמתים האלה על ידי הוספת taint משלכם למאגרי הצמתים האלה.
  • בכל פעם שפורסים עומסי עבודה חדשים באשכול, למשל כשמתקינים כלי צד שלישי, צריך לבדוק את ההרשאות שנדרשות ל-Pods. ככל האפשר, מומלץ להימנע מפריסת עומסי עבודה שמשתמשים בהרשאות מורחבות לצמתים משותפים.

המאמרים הבאים