במאמר הזה נסביר איך לחשוף 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 ברשתות משניות (לא ברירת מחדל).
לפני שמתחילים
לפני שמתחילים, צריך לבצע את המשימות הבאות:
- כדי להכין את רשתות ה-VPC וליצור אשכול GKE עם רשת נוספת, פועלים לפי השלבים במאמר בנושא הגדרת תמיכה בריבוי רשתות עבור Pods.
- מוודאים שהאפשרות 'חלוקה לקבוצות משנה' מופעלת באשכול עבור מאזני עומסים פנימיים בשכבה 4. כדי להפעיל את התכונה הזו, משתמשים בדגל
--enable-l4-ilb-subsettingכשיוצרים או מעדכנים את האשכול. - מוודאים שבקלאסטר פועלת גרסה 1.36 של GKE או גרסה חדשה יותר.
Deploy multi-network Pods
כדי לצרף Pod לרשת נוספת, יוצרים Deployment עם ההערה networking.gke.io/interfaces. ההערה הזו מציינת את הרשתות והממשקים של ה-Pods.
שומרים את קובץ המניפסט הבא בשם
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-interfaceannotation setseth1מוגדרת כממשק ברירת המחדל של ה-Pods.מחילים את המניפסט על האשכול:
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 פנימי.
שומרים את קובץ המניפסט הבא בשם
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.
-
מחילים את המניפסט על האשכול:
kubectl apply -f internal-lb-service.yaml
פריסת שירות חיצוני של איזון עומסים
כדי לחשוף את web-app הפריסה ללקוחות חיצוניים, צריך ליצור שירות LoadBalancer חיצוני.
שומרים את קובץ המניפסט הבא בשם
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.
-
מחילים את המניפסט על האשכול:
kubectl apply -f external-lb-service.yaml
אימות השירותים
אחרי שפורסים את השירותים, צריך לוודא שמאזני העומסים נוצרו והוגדרו בצורה נכונה.
בודקים את הסטטוס של השירותים:
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.מציגים ברשימה את כללי ההעברה בפרויקט:
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מתארים את כלל ההעברה של מאזן העומסים הפנימי כדי לוודא שהוא מצורף לרשת הנכונה:
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
בדיקת מאזני העומסים
כדי לבדוק את מאזן העומסים החיצוני, שולחים בקשה לכתובת ה-IP החיצונית שלו:
curl EXTERNAL_LB_IP:80מחליפים את
EXTERNAL_LB_IPבכתובת ה-IP החיצונית של שירותweb-app-external-lb.כדי לבדוק את מאזן העומסים הפנימי, שולחים בקשה ממארח באותו 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.
למאזן העומסים אין קצוות עורפיים
אם מאזן העומסים הוקצה אבל אין לו קצה עורפי תקין, צריך לבצע את הפעולות הבאות:
- מוודאים שקיים מאגר צמתים עם ממשקי רשת ברשת שבה השירות משתמש.
- מוודאים שה-Pods שנבחרו על ידי השירות פועלים.
בודקים את נקודות הקצה של השירות:
kubectl describe endpointslice -l kubernetes.io/service-name=SERVICE_NAMEהבקר
multinet-endpointslice-controller.gke.ioיוצר את נקודות הקצה (endpoints) של כמה רשתות. כתובות ה-IP של ה-Pod שמפורטות ב-EndpointSlice שייכות לרשת שבה נעשה שימוש בשירות. אם ל-EndpointSlice אין נקודות קצה, צריך לוודא שתוויות הסלקטור של השירות תואמות ל-Pods שפועלים, ושהסלקטור של הרשת תואם לרשת של ה-Pods.