הגדרת איזון עומסים בחבילה באמצעות MetalLB

בדף הזה מוסבר איך להגדיר איזון עומסים בחבילה באמצעות MetalLB ב-Google Distributed Cloud. מאזני עומסים של MetalLB פועלים במאגר ייעודי של צמתי worker או באותם צמתים שבהם פועל מישור הבקרה.

במאמר סקירה כללית על מאזני עומסים יש דוגמאות לטופולוגיות של איזון עומסים שזמינות ב-Google Distributed Cloud.

דרישות

  • כל הצמתים של מאזן העומסים צריכים להיות באותה רשת משנה בשכבה 2.
  • כל כתובות ה-VIP צריכות להיות ברשת המשנה של צמתי איזון העומסים, ואפשר להעביר אותן דרך השער של רשת המשנה.
  • השער של רשת המשנה של מאזן העומסים צריך להאזין להודעות ARP ללא תמורה ולהעביר חבילות ARP לצמתי מאזן העומסים.

שדות להגדרת התצורה

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

loadBalancer.mode

כדי להפעיל איזון עומסים בחבילה, הערך הזה צריך להיות bundled.

loadBalancer.ports.controlPlaneLBPort

הערך הזה מציין את יציאת היעד שתשמש לתנועה שנשלחת למישור הבקרה של Kubernetes (שרתי Kubernetes API).

loadBalancer.vips.controlPlaneVIP

הערך הזה מציין את כתובת ה-IP של היעד שבה יש להשתמש לתנועה שנשלחת למישור הבקרה של Kubernetes (שרתי ה-API של Kubernetes). כתובת ה-IP הזו צריכה להיות באותה תת-רשת של שכבה 2 כמו הצמתים באשכול. לא לכלול את הכתובת הזו בקטע address pools של קובץ התצורה.

loadBalancer.vips.ingressVIP

הערך הזה מציין את כתובת ה-IP שתשמש שירותים מאחורי מאזן העומסים (LB) לתעבורת נתונים נכנסת (ingress). אסור להשתמש בשדה הזה בקובצי ההגדרות של אשכול אדמין. הכתובת הזו צריכה להופיע בקטע address pools בהגדרות.

loadBalancer.addressPools

החלק הזה של ההגדרה מכיל מאגר כתובות אחד או יותר. כל מאגר כתובות מציין רשימה של טווחי כתובות IP. כשיוצרים שירות מסוג LoadBalancer, כתובות ה-IP החיצוניות של השירות נבחרות מתוך הטווחים האלה.

מאגרי הכתובות מצוינים בפורמט הבא:

- name: POOL_NAME
  avoidBuggyIPs: BOOLEAN
  manualAssign: BOOLEAN
  addresses:
  - IP_RANGE
  - IP_RANGE2
  • name: שם מאגר כתובות, pool-name, לשימושכם בארגון. אי אפשר לשנות את השדה הזה.
  • avoidBuggyIPs: (אופציונלי) true או false. אם true, המאגר לא כולל כתובות IP שמסתיימות ב-.0 וב-.255. חלק מציוד הרשת מפסיק את התנועה לכתובות המיוחדות האלה. אפשר להשמיט את השדה הזה. ערך ברירת המחדל שלו הוא false. אפשר לשנות את השדה הזה.
  • manualAssign: (אופציונלי) true או false. אם הערך הוא true, כתובות במאגר הזה לא מוקצות באופן אוטומטי לשירותי Kubernetes. אם true, כתובת IP במאגר הזה משמשת רק אם היא מצוינת במפורש על ידי שירות. אפשר להשמיט את השדה הזה. ערך ברירת המחדל שלו הוא false. אפשר לשנות את השדה הזה.
  • addresses רשימה של טווח כתובות IP אחד או יותר שלא חופפים. אפשר לציין את ip-range בסימון CIDR (למשל 198.51.100.0/24) או בסימון טווח (למשל 198.51.100.0-198.51.100.10, בלי רווחים משני צידי המקף). אי אפשר לשנות את השדה הזה.

טווח כתובות ה-IP בaddresses לא יכול להיות חופף, והוא חייב להיות באותה רשת משנה כמו הצמתים שמריצים מאזני עומסים.

loadBalancer.nodePoolSpec

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

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

node-role.kubernetes.io/load-balancer:NoSchedule

ב-Google Distributed Cloud נוספים טולרנסים לכתם הזה לפודים שנדרשים לאיזון עומסים.

בדוגמה הבאה מוצג מאגר צמתים של איזון עומסים עם שני צמתים. לצומת הראשון יש כתובת IP רגילה nodePoolSpec.nodes.address (‎1.2.3.4) וכתובת IP של Kubernetes‏ nodePoolSpec.nodes.k8sIP (10.0.0.32). כשמציינים את כתובת k8sIP האופציונלית של צומת, היא מוקדשת לטיפול בתנועת נתונים של הצומת, כמו בקשות ותגובות ל-Kubernetes API, ל-kubelet ולעומסי עבודה. במקרה כזה, כתובת ה-IP הרגילה nodePoolSpec.nodes.address משמשת לחיבורי SSH לצומת לפעולות באשכול הניהול. אם לא מציינים כתובת k8sIP, כתובת ה-IP הרגילה של הצומת מטפלת בכל התנועה של הצומת.

nodePoolSpec:
  nodes:
  - address: 1.2.3.4
    k8sIP: 10.0.0.32
  - address: 10.0.0.33

כברירת מחדל, כל הצמתים במאגר הצמתים של מאזן העומסים צריכים להיות באותה רשת משנה של שכבה 2 כמו כתובות ה-VIP של איזון העומסים שמוגדרות בקטע loadBalancer.addressPools של קובץ התצורה. עם זאת, אם מציינים כתובת IP של Kubernetes‏ k8sIP לצומת, רק הכתובת הזו צריכה להיות באותה רשת משנה של שכבה 2 כמו כתובות ה-IP הווירטואליות האחרות של מאזן העומסים.

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

איזון עומסים במישור הבקרה

מאזן העומסים של מישור הבקרה משרת את כתובת ה-IP הווירטואלית (VIP) של מישור הבקרה. ‫Google Distributed Cloud מריץ את Keepalived ו-HAProxy כ-pods סטטיים של Kubernetes בצמתים של איזון העומסים, כדי להודיע על כתובת ה-VIP של מישור הבקרה. ‫Keepalived משתמש בפרוטוקול היתירות של נתב וירטואלי (VRRP) בצמתי מאזן העומסים כדי להשיג זמינות גבוהה.

איזון עומסים במישור הנתונים

מאזן העומסים של מישור הנתונים מיועד לכל שירותי Kubernetes מסוג LoadBalancer. ‫Google Distributed Cloud משתמש ב-MetalLB שפועל במצב Layer 2 לאיזון עומסים במישור הנתונים. אפשר להגדיר איזון עומסים במישור הנתונים רק דרך Google Distributed Cloud. אל תשנו את MetalLB ConfigMap ישירות. אתם יכולים להשתמש בכל התכונות של MetalLB, כולל שיתוף כתובות IP בין שירותים. מידע על התכונות זמין במסמכי MetalLB.

‫MetalLB מריץ Pod של רמקול בכל צומת באמצעות daemonset, ומשתמש ב-memberlist לזמינות גבוהה. יש צומת ייעודי של מאזן עומסים של MetalLB לכל שירות Kubernetes, ולא אחד לכל האשכול. כך, אם יש כמה שירותים, התעבורה מתחלקת בין הצמתים של מאזן העומסים.

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

הפרדה של מאזן עומסים

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

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

הגדרות ברירת המחדל של איזון העומסים

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

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

apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: hybrid-ha-lb
  namespace: cluster-hybrid-ha-lb
spec:
  type: hybrid
  profile: default
  anthosBareMetalVersion: 1.34
  gkeConnect:
    projectID: project-fleet
  controlPlane:
    loadBalancer:
      mode: bundled
    nodePoolSpec:
      nodes:
      - address: 10.200.0.2
      - address: 10.200.0.3
      - address: 10.200.0.4
  clusterNetwork:
    pods:
      cidrBlocks:
      - 192.168.0.0/16
    services:
      cidrBlocks:
      - 10.96.0.0/20
  ...
  loadBalancer:
    mode: bundled
    ...
    nodePoolSpec:
      nodes:
      - address: 10.200.0.5
      - address: 10.200.0.6
      - address: 10.200.0.7
  clusterOperations:
  ...

הפרדה של מאזני עומסים כשיוצרים אשכול

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

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

מאזני עומסים נפרדים למישור הבקרה ולמישור הנתונים

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

  1. בקובץ התצורה של האשכול, מציינים מאגר צמתים של איזון עומסים עם loadBalancer.nodePoolSpec, כמו שמתואר בקטע loadBalancer.nodePoolSpec במסמך הזה.

  2. מוסיפים את controlPlane.loadBalancer.mode לקובץ התצורה של האשכול ומגדירים את הערך mode ל-bundled.

  3. ממשיכים להגדיר את האשכול ומריצים את הפקודה bmctl create cluster כדי ליצור את האשכול.

העברת איזון עומסים של מישור הנתונים ממישור הבקרה

אם יש לכם אשכול קיים בגרסה 1.32 ומעלה, שבה לא מוגדרים controlPlane.loadBalancer.mode וגם לא loadBalancer.nodePoolSpec, מאזן העומסים של מישור הבקרה ומאזן העומסים של מישור הנתונים פועלים שניהם במאגר הצמתים של מישור הבקרה. אתם יכולים לעדכן את האשכול כדי להעביר את מאזן העומסים של מישור הנתונים למאגר צמתים של מאזן עומסים.

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

מאזן עומסים של מישור הנתונים הועבר למאגר הצמתים של מאזן העומסים

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

  1. בקובץ התצורה של האשכול, מציינים מאגר צמתים של איזון עומסים עם loadBalancer.nodePoolSpec, כמו שמתואר בקטע loadBalancer.nodePoolSpec במסמך הזה.

  2. מוסיפים את controlPlane.loadBalancer.mode לקובץ התצורה של האשכול ומגדירים את הערך mode ל-bundled.

  3. מריצים את הפקודה הבאה כדי לעדכן את האשכול:

    bmctl update cluster -c CLUSTER_NAME --kubeconfig=ADMIN_KUBECONFIG
    

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

    • CLUSTER_NAME: שם האשכול שרוצים לעדכן.

    • ADMIN_KUBECONFIG: הנתיב לקובץ kubeconfig של אשכול האדמין.

שמירה על כתובת ה-IP של המקור של הלקוח

שירות LoadBalancer שנוצר באמצעות פתרון מאוחד לאיזון עומסים בשכבה 2 משתמש בהגדרת ברירת המחדל LoadBalancer למדיניות תעבורת נתונים חיצונית.Cluster ההגדרה הזו, spec.externalTrafficPolicy: Cluster, מעבירה תנועה חיצונית לנקודות קצה ברמת האשכול, אבל היא גם מסתירה את כתובת ה-IP של מקור הלקוח.

‫Google Distributed Cloud תומך בשתי שיטות לשמירת כתובת ה-IP של מקור הלקוח:

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

  • מגדירים את מדיניות התעבורה החיצונית ל-local עבור השירות LoadBalancer ומגדירים בהתאם את השירותים וה-Ingress שקשורים אליו. בקטעים הבאים מוסבר איך להגדיר את האשכול כך שישתמש בשיטה הזו.

LoadBalancer Services

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

apiVersion: v1
kind: Pod
...
spec:
  nodeSelector:
      baremetal.cluster.gke.io/lbnode: "true"
...

NodePort Services

‫Kubernetes מבצע תרגום כתובות רשת של מקור (SNAT) עבור NodePort Services. כדי לשמור את כתובות ה-IP של מקור הלקוח, מגדירים את service.spec.externalTrafficPolicy ל-Local. מערכת Kubernetes לא תבצע יותר SNAT, אבל אתם צריכים לוודא שיש פודים שפועלים בדיוק בכתובת ה-IP של הצומת שבחרתם.

תעבורת נתונים נכנסת (Ingress)

אם האפליקציות שלכם הן שירותי HTTP, תוכלו להשיג חשיפה של כתובות ה-IP של הלקוחות על ידי הגדרת רכיבי כניסה:

  1. פותחים את istio-ingress השירות לעריכה:

    kubectl edit service -n gke-system istio-ingress
    
  2. מוסיפים את externalTrafficPolicy: Local אל spec, שומרים ויוצאים מהעורך.

    apiVersion: v1
    kind: Service
    ...
    spec:
    ...
      externalTrafficPolicy: Local
    
  3. פותחים את istio-ingress הפריסה לעריכה:

    kubectl edit deployment -n gke-system istio-ingress
    
  4. מוסיפים את nodeSelector לפריסה, שומרים ויוצאים מהעורך.

    apiVersion: apps/v1
    kind: Deployment
    ...
    spec:
      ...
      template:
        ...
        spec:
          ...
          nodeSelector:
              baremetal.cluster.gke.io/lbnode: "true"
    ...
    

עכשיו, כל השירותים שמוגדרים מאחורי Ingress רואים כותרת X-Forwarded-For עם כתובת ה-IP של הלקוח, כמו בדוגמה הבאה:

X-Forwarded-For: 21.0.104.4