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

במאמר הזה מוסבר איך לשפר את האבטחה והניהול של אשכול Kubernetes על ידי בידוד של עומסי עבודה של קונטיינרים במאגרי צמתים ייעודיים ב-Google Distributed Cloud‏ (GDC) עם פער אוויר. בידוד עומסי העבודה מאפשר לכם שליטה רבה יותר על הפודים ומקטין את הסיכון למתקפות של העלאת הרשאות באשכול Kubernetes. מידע נוסף על היתרונות והמגבלות של מאגרי צמתים ייעודיים זמין במאמר סקירה כללית על בידוד צמתים.

יש כמה תהליכי עבודה שקשורים לבידוד של עומסי העבודה של הקונטיינר, כולל:

  • הוספת כתם וסימון של מאגר צמתים: מוסיפים כתם ותווית למאגר צמתים כדי להרחיק ממנו את ה-Pods, אלא אם הם מסומנים באופן ספציפי להרצה במאגר הזה.

  • הוספת טולרנטיות וכלל שיוך לצומת: מחילים טולרנטיות וכללים על ה-Pods כדי לאלץ אותם לפעול רק במאגר הצמתים המיועד.

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

תהליכי העבודה האלה מיועדים לקהלים כמו אדמינים של IT בקבוצת האדמינים של הפלטפורמה, שאחראים על ניהול מאגרי הצמתים של אשכול Kubernetes, ומפתחי אפליקציות בקבוצת מפעילים של אפליקציות, שאחראים על ניהול עומסי עבודה של קונטיינרים. מידע נוסף זמין במאמר בנושא קהלים ב-GDC עם air gap.

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

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

שליחת בקשה לתפקידי IAM

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

תפקידים משותפים באשכול

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

  • User Cluster Admin (user-cluster-admin): יצירה, מחיקה, עריכה או צפייה במשאבים של אשכול משותף שמתארח בשרת של Management API. התפקיד הזה מספק גישה למאגרי הצמתים של האשכול המשותף.

  • מפתח אשכול משתמשים (user-cluster-developer): יצירה, מחיקה, עריכה או צפייה באשכול משותף. התפקיד הזה מספק גישה לממשקי API של מישור הנתונים שמתארחים באשכול המשותף.

התפקידים האלה לא קשורים למרחב שמות.

תפקידים רגילים באשכול

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

  • אדמין של אשכול (cluster-admin): יצירה, מחיקה, עריכה או צפייה בכל המשאבים באשכול רגיל. התפקיד הזה מספק גישה לממשקי API של מישור הנתונים שמתארחים באשכול הרגיל שמנהל את המשאבים של האשכול.

  • מפתח אשכול (cluster-developer): יצירה, מחיקה, עריכה או צפייה באשכול רגיל. התפקיד הזה מספק גישה לממשקי API של מישור הנתונים שמתארחים באשכול הרגיל שמנהל את האשכול.

  • אדמין רגיל של אשכול (standard-cluster-admin): יצירה, מחיקה, עריכה או צפייה במשאבים של אשכול רגיל שמארח בשרת של Management API. לתפקיד הזה מוקצית גישה למאגרי הצמתים של האשכול הרגיל.

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

הכנת הסביבה

כדי להריץ פקודות מול אשכול Kubernetes באמצעות ה-API, צריך לוודא שיש לכם את המשאבים הבאים:

  • נכנסים לחשבון ויוצרים את קובץ ה-kubeconfig של אשכול Kubernetes.

  • משתמשים בנתיב kubeconfig של אשכול Kubernetes כדי להחליף את הערך KUBERNETES_CLUSTER_KUBECONFIG בהוראות האלה.

  • נכנסים ויוצרים את קובץ ה-kubeconfig של שרת ה-API לניהול.

  • משתמשים בנתיב kubeconfig של שרת ה-API לניהול כדי להחליף את MANAGEMENT_API_SERVER בהוראות האלה.

  • בוחרים שם ספציפי ל-taint של הצומת ולתווית הצומת שרוצים להשתמש בהם עבור מאגרי הצמתים הייעודיים. לדוגמה, workloadType=untrusted.

הוספת דחייה (taint) ותווית למאגר צמתים חדש

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

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

  1. עורכים את הקטע nodePools של המשאב המותאם אישית Cluster ישירות כשיוצרים את מאגר הצמתים:

    nodePools:
      # Several lines of code are omitted here.
      - machineTypeName: n2-standard-2-gdc
        name: nodepool-1
        nodeCount: 3
        taints:
        - key: "TAINT_KEY"
          value: "TAINT_VALUE"
          effect: "TAINT_EFFECT"
        labels:
          LABEL_KEY: LABEL_VALUE
    

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

    • TAINT_KEY: החלק של מפתח הדחייה (taint) בצמד מפתח/ערך שמשויך לתזמון של TAINT_EFFECT. לדוגמה, workloadType.
    • TAINT_VALUE: החלק של ערך ההכתמה בצמד מפתח/ערך שמשויך לTAINT_EFFECT של תזמון. לדוגמה, untrusted.
    • TAINT_EFFECT: אחד מהערכים הבאים של אפקט:
      • NoSchedule: פודים שלא יכולים לסבול את ההכתמה הזו לא מתוזמנים בצומת, ופודים קיימים לא מוצאים מהצומת.
      • PreferNoSchedule: Kubernetes לא מתזמן הפעלה של קובצי Pod שלא יכולים להתמודד עם ההכתמה הזו בצומת.
      • NoExecute: ה-Pod מוצא מהצומת אם הוא כבר פועל בצומת, ולא מתוזמן בצומת אם הוא עדיין לא פועל בצומת.
    • LABEL_KEY: LABEL_VALUE: צמדי מפתח/ערך של תוויות הצומת, שתואמים לסלקטורים שציינתם במניפסטים של עומסי העבודה.
  2. מחילים את המשאב Cluster כדי ליצור את מאגר הצמתים החדש:

    kubectl apply -f cluster.yaml --kubeconfig MANAGEMENT_API_SERVER
    

    מחליפים את MANAGEMENT_API_SERVER בנתיב של קובץ ה-kubeconfig של שרת ה-API האזורי שבו מתארח אשכול Kubernetes.

הוספת תווית וסימון של מאגר צמתים קיים

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

אי אפשר להסיר כתם או תווית ממאגר צמתים אחרי שהם מוחלים.

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

  1. מציגים את רשימת הצמתים במאגר הצמתים הייעודי:

    kubectl get node --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG \
        -l baremetal.cluster.gke.io/node-pool=NODE_POOL_NAME
    

    מחליפים את המשתנים הבאים:

    • KUBERNETES_CLUSTER_KUBECONFIG: הנתיב של kubeconfig לאשכול Kubernetes.
    • NODE_POOL_NAME: השם של מאגר הצמתים הייעודי.

    שימו לב לכל מזהה צומת של כל הצמתים במאגר הצמתים מהפלט.

  2. לכל צומת במאגר הצמתים, מחילים את ההכתמות:

    kubectl taint nodes NODE_ID \
        TAINT_KEY=TAINT_VALUE:TAINT_EFFECT \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    מחליפים את המשתנים הבאים:

    • NODE_ID: המזהה של צומת העובד במאגר הצמתים הייעודי.
    • TAINT_KEY=TAINT_VALUE: זוג מפתח/ערך שמשויך לתזמון TAINT_EFFECT. לדוגמה: workloadType=untrusted.
    • TAINT_EFFECT: אחד מהערכים הבאים של אפקט:
      • NoSchedule: פודים שלא יכולים לסבול את ההכתמה הזו לא מתוזמנים בצומת, ופודים קיימים לא מוצאים מהצומת.
      • PreferNoSchedule: Kubernetes לא מתזמן הפעלה של קובצי Pod שלא יכולים להתמודד עם ההכתמה הזו בצומת.
      • NoExecute: ה-Pod מוצא מהצומת אם הוא כבר פועל בצומת, ולא מתוזמן בצומת אם הוא עדיין לא פועל בצומת.
    • KUBERNETES_CLUSTER_KUBECONFIG: הנתיב של kubeconfig לאשכול Kubernetes.
  3. לכל צומת במאגר הצמתים, צריך להחיל את התוויות שמתאימות לסלקטורים שתגדירו בעומסי העבודה של הקונטיינרים:

    kubectl label NODE_ID \
        LABEL_KEY:LABEL_VALUE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    מחליפים את המשתנים הבאים:

    • NODE_ID: המזהה של צומת העובד במאגר הצמתים הייעודי.
    • LABEL_KEY:LABEL_VALUE: צמדי מפתח/ערך של תוויות הצומת, שתואמים לסלקטורים שציינתם במניפסטים של עומסי העבודה.
    • KUBERNETES_CLUSTER_KUBECONFIG: הנתיב של kubeconfig לאשכול Kubernetes.

הוספת כלל סבילות וכלל שיוך צומת

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

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

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

  1. מוסיפים את הקטעים הבאים לקטע .spec.template.spec בקובץ המניפסט של עומס העבודה של הקונטיינר, כמו משאב מותאם אישית Deployment:

    tolerations:
    - key: TAINT_KEY
      operator: Equal
      value: TAINT_VALUE
      effect: TAINT_EFFECT
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: LABEL_KEY
              operator: In
              values:
              - "LABEL_VALUE"
    

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

    • TAINT_KEY: מפתח הכתם שהוחל על מאגר הצמתים הייעודי.
    • TAINT_VALUE: ערך ה-taint שהגדרתם למאגר הצמתים הייעודי.
    • TAINT_EFFECT: אחד מהערכים הבאים של אפקט:
      • NoSchedule: פודים שלא יכולים לסבול את ההכתמה הזו לא מתוזמנים בצומת, ופודים קיימים לא מוצאים מהצומת.
      • PreferNoSchedule: Kubernetes לא מתזמן הפעלה של קובצי Pod שלא יכולים להתמודד עם ההכתמה הזו בצומת.
      • NoExecute: ה-Pod מוצא מהצומת אם הוא כבר פועל בצומת, ולא מתוזמן בצומת אם הוא עדיין לא פועל בצומת.
    • LABEL_KEY: מפתח התווית של הצומת שהחלתם על מאגר הצמתים הייעודי.
    • LABEL_VALUE: ערך התווית של הצומת שהגדרתם למאגר הצמתים הייעודי.

    לדוגמה, במשאב Deployment הבא מתווספת טולרנטיות ל-taint‏ workloadType=untrusted:NoExecute וכלל שיוך צומת לתווית הצומת 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: workloadType
            operator: Equal
            value: untrusted
            effect: NoExecute
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: workloadType
                    operator: In
                    values:
                    - "untrusted"
          containers:
          - name: my-app
            image: harbor-1.org-1.zone1.google.gdc.test/harborproject/my-app
            ports:
            - containerPort: 80
          imagePullSecrets:
          - name: SECRET
    
  2. עדכון עומס העבודה של הקונטיינר:

    kubectl apply -f deployment.yaml -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    מחליפים את המשתנים הבאים:

    • NAMESPACE: מרחב השמות של עומס העבודה של הקונטיינר. במקרה של אשכולות משותפים, צריך להשתמש במרחב שמות של פרויקט. במקרים של אשכולות רגילים, אפשר להשתמש בכל מרחב שמות.
    • KUBERNETES_CLUSTER_KUBECONFIG: הנתיב של kubeconfig לאשכול Kubernetes.

‫GDC יוצר מחדש את הפודים שהושפעו. כלל ההתאמה של הצומת מכריח את הפודים להיכנס למאגר הצמתים הייעודי שיצרתם. הטולרנטיות מאפשרת להציב את ה-Pods האלה רק בצמתים.

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

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

  • כדי להציג את הפודים במרחב השמות הנתון:

    kubectl get pods -o=wide -n NAMESPACE \
        --kubeconfig KUBERNETES_CLUSTER_KUBECONFIG
    

    מחליפים את המשתנים הבאים:

    • NAMESPACE: מרחב השמות של עומס העבודה של הקונטיינר. במקרה של אשכולות משותפים, צריך להשתמש במרחב שמות של פרויקט. במקרים של אשכולות רגילים, אפשר להשתמש בכל מרחב שמות.
    • KUBERNETES_CLUSTER_KUBECONFIG: הנתיב של kubeconfig לאשכול Kubernetes.

    הפלט אמור להיראות כך:

    pod/kube-abc-12tyuj
    pod/kube-abc-39oplef
    pod/kube-abc-95rzkap
    

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

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