פריסת שירותים של מאזן עומסים בכמה רשתות

במאמר הזה נסביר איך לחשוף Pods בכמה רשתות ללקוחות פנימיים או חיצוניים באמצעות יצירה של מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי ומאזן עומסי רשת פנימי להעברת סיגנל ללא שינוי ב-GKE. Cloud de Confiance by S3NS במאמר הזה מתוארים ההגדרות הנדרשות, היכולות והמגבלות של שירותי LoadBalancer מרובי רשתות.

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

מידע נוסף על ריבוי רשתות ב-GKE זמין במאמר מידע על תמיכה בריבוי רשתות עבור Pods.

איך פועלים שירותי LoadBalancer בכמה רשתות

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

התווית networking.gke.io/network בבורר מסננת את נקודות הקצה לפי רשת. התווית הזו מבטיחה שמאזן העומסים ישלח תנועה רק לממשקי ה-Pod שמחוברים לרשת שצוינה.

מגבלות

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

  • אין תמיכה בשירותים שמשתמשים ב-externalTrafficPolicy: Cluster.
  • אין תמיכה בשירותים שמיועדים ל-Pods של hostNetwork.
  • אין תמיכה ב-IPv6 וברשתות עם פרוטוקול כפול.
  • אי אפשר לשנות את הרשת של שירות קיים.
  • יש תמיכה רק ברשתות Layer 3.
  • אין תמיכה במאזני עומסים שמבוססים על מאגרי יעד או על קצה עורפי של קבוצות מכונות.
  • אין תמיכה בשירותי ClusterIP ו-NodePort ברשתות משניות (לא ברירת מחדל).

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

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

  1. כדי להכין את רשתות ה-VPC וליצור אשכול GKE עם רשת נוספת, פועלים לפי השלבים במאמר בנושא הגדרת תמיכה בריבוי רשתות עבור Pods.
  2. מוודאים שהאפשרות 'חלוקה לקבוצות משנה' מופעלת באשכול עבור מאזני עומסים פנימיים בשכבה 4. כדי להפעיל את התכונה הזו, משתמשים בדגל --enable-l4-ilb-subsetting כשיוצרים או מעדכנים את האשכול.
  3. מוודאים שבקלאסטר פועלת גרסה 1.36 של GKE או גרסה חדשה יותר.

Deploy multi-network Pods

כדי לצרף Pod לרשת נוספת, יוצרים Deployment עם ההערה networking.gke.io/interfaces. ההערה הזו מציינת את הרשתות והממשקים של ה-Pods.

  1. שומרים את קובץ המניפסט הבא בשם web-app-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-app
      labels:
        app: web-app
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: web-app
      template:
        metadata:
          labels:
            app: web-app
          annotations:
            networking.gke.io/default-interface: 'eth1'
            networking.gke.io/interfaces: '[
              {"interfaceName":"eth0","network":"default"},
              {"interfaceName": "eth1","network": "dmz"}
            ]'
    spec:
      containers:
      - name: whereami
        image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
        ports:
        - containerPort: 8080
    

    המניפסט הזה יוצר פריסה בשם web-app עם שלושה פודים. ל-Pods יש שני ממשקים: eth0 שמחובר לרשת default ו-eth1 שמחובר לרשת dmz. ההערה networking.gke.io/default-interface annotation sets eth1 מוגדרת כממשק ברירת המחדל של ה-Pods.

  2. מחילים את המניפסט על האשכול:

    kubectl apply -f web-app-deployment.yaml
    

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

בדוגמה הבאה מוצג initContainer שמוסיף מסלול ברירת מחדל לממשק eth1:

initContainers:
      - name: init-routes-busybox
        image: busybox
        command: ['sh', '-c', 'ip route add default dev eth1 table 200 && ip rule add from 172.16.1.0/24 table 200']
        securityContext:
          capabilities:
            add: ["NET_ADMIN"]

בפקודה initContainer, מחליפים את 172.16.1.0/24 בטווח כתובות ה-IP המשני של רשת ה-Pod.

פריסת שירות LoadBalancer פנימי

כדי לחשוף את web-app הפריסה ברשת dmz, יוצרים שירות LoadBalancer פנימי.

  1. שומרים את קובץ המניפסט הבא בשם internal-lb-service.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: web-app-internal-lb
      namespace: default
      annotations:
        networking.gke.io/load-balancer-type: "Internal"
    spec:
      externalTrafficPolicy: Local
      ports:
      -   port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        networking.gke.io/network: dmz
        app: web-app
      type: LoadBalancer
    

    קובץ המניפסט הזה יוצר שירות עם המאפיינים הבאים:

    • networking.gke.io/load-balancer-type: "Internal": מציין מאזן עומסי רשת פנימי להעברת סיגנל ללא שינוי.
    • selector: בוחר רצפי מודעות עם התווית app: web-app שמחוברים לרשת dmz.
  2. מחילים את המניפסט על האשכול:

    kubectl apply -f internal-lb-service.yaml
    

פריסת שירות חיצוני של איזון עומסים

כדי לחשוף את web-app הפריסה ללקוחות חיצוניים, צריך ליצור שירות LoadBalancer חיצוני.

  1. שומרים את קובץ המניפסט הבא בשם external-lb-service.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: web-app-external-lb
      namespace: default
      annotations:
        cloud.google.com/l4-rbs: "enabled"
    spec:
      externalTrafficPolicy: Local
      ports:
      -   port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        networking.gke.io/network: dmz
        app: web-app
      type: LoadBalancer
    

    קובץ המניפסט הזה יוצר שירות עם המאפיינים הבאים:

    • cloud.google.com/l4-rbs: "enabled": מציין מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי שמבוסס על שירות קצה עורפי.
    • selector: בוחר את ה-Pods עם התווית app: web-app שמחוברים לרשת dmz.
  2. מחילים את המניפסט על האשכול:

    kubectl apply -f external-lb-service.yaml
    

אימות השירותים

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

  1. בודקים את הסטטוס של השירותים:

    kubectl get services
    

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

    NAME                  TYPE           CLUSTER-IP    EXTERNAL-IP     PORT(S)        AGE
    web-app-external-lb   LoadBalancer   10.8.47.77    35.239.57.231   80:31550/TCP   5m
    web-app-internal-lb   LoadBalancer   10.8.43.251   172.16.0.43     80:32628/TCP   6m
    kubernetes            ClusterIP      10.8.32.1     <none>          443/TCP        43h
    

    הכתובת EXTERNAL-IP של מאזן העומסים הפנימי שייכת לרשת dmz.

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

    gcloud compute forwarding-rules list
    

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

    NAME                                                   REGION        IP_ADDRESS     IP_PROTOCOL  TARGET
    af901673cc0f24907a6aa8c3ce4afc21                       us-central1   35.239.57.231  TCP          us-central1/backendServices/k8s2-xhvzqabw-default-web-app-external-lb-u4xbs4ot
    k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a us-central1   172.16.0.43    TCP          us-central1/backendServices/k8s2-xhvzqabw-default-web-app-internal-lb-vp1x1d6a
    
  3. מתארים את כלל ההעברה של מאזן העומסים הפנימי כדי לוודא שהוא מצורף לרשת הנכונה:

    gcloud compute forwarding-rules describe k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a --region=$REGION
    

    מחליפים את REGION באזור של האשכול.

    הפלט אמור להיראות כך: מוודאים שהשדות network ו-subnetwork תואמים לפרטים של רשת dmz.

    IPAddress: 172.16.0.43
    IPProtocol: TCP
    ...
    loadBalancingScheme: INTERNAL
    name: k8s2-tcp-xhvzqabw-default-web-app-internal-lb-vp1x1d6a
    network: https://www.googleapis.com/compute/v1/projects/projectId/global/networks/dmz-vpc
    ...
    subnetwork: https://www.googleapis.com/compute/v1/projects/projectId/regions/us-central1/subnetworks/dmz-subnet
    

בדיקת מאזני העומסים

  1. כדי לבדוק את מאזן העומסים החיצוני, שולחים בקשה לכתובת ה-IP החיצונית שלו:

    curl EXTERNAL_LB_IP:80
    

    מחליפים את EXTERNAL_LB_IP בכתובת ה-IP החיצונית של שירות web-app-external-lb.

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

    curl INTERNAL_LB_IP:80
    

    מחליפים את INTERNAL_LB_IP בכתובת ה-IP של שירות web-app-internal-lb.

פתרון בעיות

בקטע הזה מוסבר איך לפתור בעיות שקשורות למאזני עומסים מרובי-רשתות.

יצירת מאזן עומסים נכשלת

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

kubectl describe service SERVICE_NAME

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

הודעת שגיאה כמו network some-other-network does not exist מציינת שהרשת שצוינה בבורר השירות לא מוגדרת באשכול. מוודאים שהרשת קיימת:

kubectl get networks

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

kubectl get networks NETWORK_NAME -o yaml

מחליפים את NETWORK_NAME בשם הרשת.

בהגדרה תקינה, התנאים ParamsReady ו-Ready הם True. אם ParamsReady לא זהה ל-True, צריך לוודא שparametersRef במפרט Network תואם לשם, לסוג ולקבוצה של משאב GKENetworkParamSet קיים.

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

kubectl get gkenetworkparamsets GNP_NAME -o yaml

מחליפים את GNP_NAME בשם של GKENetworkParamSet.

למאזן העומסים אין קצוות עורפיים

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

  1. מוודאים שקיים מאגר צמתים עם ממשקי רשת ברשת שבה השירות משתמש.
  2. מוודאים שה-Pods שנבחרו על ידי השירות פועלים.
  3. בודקים את נקודות הקצה של השירות:

    kubectl describe endpointslice -l kubernetes.io/service-name=SERVICE_NAME
    

    הבקר multinet-endpointslice-controller.gke.io יוצר את נקודות הקצה (endpoints) של כמה רשתות. כתובות ה-IP של ה-Pod שמפורטות ב-EndpointSlice שייכות לרשת שבה נעשה שימוש בשירות. אם ל-EndpointSlice אין נקודות קצה, צריך לוודא שתוויות הסלקטור של השירות תואמות ל-Pods שפועלים, ושהסלקטור של הרשת תואם לרשת של ה-Pods.

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