הגדרת שער NAT לתעבורת נתונים יוצאת

במאמר הזה מוסבר איך להגדיר שער NAT לתעבורת נתונים יוצאת (egress) ב-Google Distributed Cloud. השער הזה מספק כתובות IP של SNAT קבועות ודטרמיניסטיות לתעבורת הנתונים היוצאת מהאשכולות שלכם. כשמריצים עומסי עבודה שיש להם תנועת משתמשים יוצאת (מחוץ לאשכולות), הלקוחות רוצים לזהות את התנועה הזו באמצעות כמה כתובות IP דטרמיניסטיות. כך הלקוחות יכולים להגדיר אמצעי אבטחה מבוססי-IP, כמו מדיניות של רשימת היתרים.

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

שער NAT ליציאה מופעל באמצעות שני משאבים בהתאמה אישית. עבור מרחב שמות נתון, המשאב המותאם אישית NetworkGatewayGroup מציין כתובות IP צפות שאפשר להגדיר בממשק הרשת של צומת שנבחר לפעול כשער. המשאב המותאם אישית EgressNatPolicy מאפשר להגדיר מדיניות ניתוב של תעבורת נתונים יוצאת (egress) כדי לשלוט בתעבורה בשער היציאה.

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

שער NAT לתעבורת נתונים יוצאת הוא פתרון מתקדם לרישות שמבוסס על Dataplane V2.

איך שער NAT ליציאה פועל

הלוגיקה לבחירת תעבורת יציאה מבוססת על בורר של מרחב שמות, בורר של Pod וקבוצה של טווחי כתובות IP של יעד בפורמט בלוקים של CIDR. כדי להמחיש איך שער NAT ליציאה פועל, נתייחס לזרימת מנות מ-Pod לצרכן חיצוני ולתגובה המתאימה. נניח שלרשת המשנה של הצומת יש כתובות IP בבלוק ה-CIDR‏ 192.168.1.0/24.

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

תרשים של שער NAT לתעבורת נתונים יוצאת (egress) ב-Google Distributed Cloud

זרימת המנות דרך שער ה-NAT של היציאה יכולה להיראות כך:

  1. תעבורת נתונים יוצאת נוצרת מ-Pod עם כתובת ה-IP‏ 10.10.10.1 בצומת עם כתובת ה-IP‏ 192.168.1.1.

    כתובת היעד של התעבורה היא נקודת קצה מחוץ לאשכול.

  2. אם התעבורה תואמת לכלל יציאה, תוכנית ה-eBPF מפנה את התעבורה היוצאת לצומת השער, במקום להסוות אותה ישירות עם כתובת ה-IP של הצומת.

  3. צומת השער מקבל את תעבורת הנתונים היוצאת.

  4. צומת השער מסווה את כתובת ה-IP של המקור של תעבורת הנתונים המקורית, 10.10.10.1, באמצעות כתובת ה-IP של תעבורת הנתונים היוצאת מהמקור, 192.168.1.100, שצוינה במשאב המותאם אישית EgressNATPolicy.

  5. תנועת החזרה מגיעה בחזרה לצומת של שער הכניסה עם היעד 192.168.1.100.

  6. צומת השער מתאים את מעקב החיבורים של תנועת החזרה למעקב החיבורים של תנועת היציאה המקורית, וכותב מחדש את כתובת ה-IP של היעד כ-10.10.10.1.

  7. התנועה של 10.10.10.1 מטופלת כתנועה בתוך האשכול, מנותבת לצומת המקורי ומועברת בחזרה ל-Pod המקורי.

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

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

כשיוצרים אשכול חדש בגרסה 1.36.100-gke.144, צריך לכלול את פרטי קבוצת שער הרשת (הערה ומפרט) בקובץ ההגדרות של האשכול.

יצירת משאב מותאם אישית NetworkGatewayGroup

כדי להפעיל את Network Gateway Group (קבוצת שערים לרשת), צריך להגדיר את השדה spec.clusterNetwork.advancedNetworking לערך true בקובץ התצורה של האשכול כשיוצרים אשכול, כמו שמוצג בדוגמה הבאה:

apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: cluster1
  namespace: cluster-cluster1
spec:
  clusterNetwork:
    ...
    advancedNetworking: true
    ...

כשיוצרים את המשאב המותאם אישית NetworkGatewayGroup, מגדירים את מרחב השמות שלו למרחב השמות של האשכול ומציינים רשימה של כתובות IP צפות, כמו בדוגמה הבאה:

kind: NetworkGatewayGroup
apiVersion: networking.gke.io/v1
metadata:
  namespace: cluster-cluster1
  name: default
spec:
  floatingIPs:
  - 192.168.1.100
  - 192.168.1.101
  - 192.168.1.102

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

  • תת-רשת של הצומת: כתובת ה-IP הצפה צריכה להיות זהה לתת-הרשת של הצומת.
  • תפקיד הצומת (מישור הבקרה, worker): לצמתי worker יש עדיפות על פני צמתי מישור הבקרה בהקצאת כתובות IP צפות.
  • אם לצומת יש כתובת IP צפה: המפעיל נותן עדיפות להקצאות לצמתים שלא הוקצתה להם כבר כתובת IP צפה.

מיפוי הכתובת לצומת נמצא בקטע status כשמקבלים את האובייקט NetworkGatewayGroup. שימו לב שאובייקט NetworkGatewayGroup נמצא במרחב השמות kube-system. אם צומת שער מושבת, מפעיל הרשת המתקדם מקצה את כתובות ה-IP הצפות לצומת הזמין הבא.

אימות ההגדרה של שער הגישה

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

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

kubectl -n kube-system get networkgatewaygroups.networking.gke.io default -o yaml

התגובה עבור אשכול עם שני צמתים, worker1 ו-worker2, עשויה להיראות כך:

kind: NetworkGatewayGroup
apiVersion: networking.gke.io/v1
metadata:
  namespace: kube-system
  name: default
spec:
  floatingIPs:
  - 192.168.1.100
  - 192.168.1.101
  - 192.168.1.102
status:
  nodes:
    worker1: Up
    worker2: Up // Or Down
  floatingIPs:
    192.168.1.100: worker1
    192.168.1.101: worker2
    192.168.1.102: worker1

הגדרת כללים לבחירת תנועה

משאב EgressNATPolicy בהתאמה אישית מציין כללים לבחירת תנועה ומקצה כתובת IP דטרמיניסטית לתנועה יוצאת (egress) שיוצאת מהאשכול. כשמציינים את המשאב המותאם אישית, צריך לציין גם את egress (עם כלל אחד לפחות), את destinationCIDRs ואת egressSourceIP.

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

הגדרת כללי ניתוב לתעבורת נתונים יוצאת (egress)

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

  • צריך לציין כלל אחד או יותר לבחירת תעבורת נתונים יוצאת (egress) בקטע egress.

    • כל כלל מורכב מpodSelector וnamespaceSelector.
    • הבחירה מבוססת על תווית של מרחב שמות, namespaceSelector.matchLabels.user, ועל תווית של Pod,‏ podSelector.matchLabels.role.
    • אם Pod תואם לאחד מהכללים (התאמה מתבצעת באמצעות יחס OR), הוא נבחר לתעבורת נתונים יוצאת.
  • מציינים את כתובות היעד המותרות בקטע destinationCIDRs.

    • ‫destinationCIDRs מקבל רשימה של בלוקים של CIDR.
    • אם לתעבורת נתונים יוצאת מ-Pod יש כתובת IP ליעד שנמצאת בטווח של אחד מבלוקי ה-CIDR שצוינו, היא נבחרת לתעבורת נתונים יוצאת (egress).

בדוגמה הבאה, תעבורת נתונים יוצאת (egress) מ-Pod מותרת כשמתקיימים הקריטריונים הבאים:

  • ה-Pod מסומן בתווית role: frontend.
  • ה-Pod נמצא במרחב שמות עם התווית user: alice או user: paul.
  • ה-Pod מתקשר עם כתובות IP בבלוק ה-CIDR‏ 8.8.8.0/24.
kind: EgressNATPolicy
apiVersion: networking.gke.io/v1
metadata:
  name: egress
spec:
  sources:
  - namespaceSelector:
      matchLabels:
        user: alice
    podSelector:
      matchLabels:
        role: frontend
  - namespaceSelector:
      matchLabels:
        user: paul
    podSelector:
      matchLabels:
        role: frontend
  action: SNAT
  destinations:
    - cidr: 8.8.8.0/24
  gatewayRef:
    name: default
    namespace: kube-system

מידע נוסף על השימוש בתוויות זמין במאמר תוויות וסלקטורים במסמכי Kubernetes.

קבלת כתובת IP של מקור לתעבורת נתונים יוצאת

המשאב המותאם אישית (מדיניות) EgressNATPolicy משתמש בערכים gatewayRef.name ו-gatewayRef.namespace כדי למצוא אובייקט NetworkGatewayGroup (שער). המדיניות משתמשת באחת מכתובות ה-IP הצפות של השער ככתובת ה-IP של המקור לתעבורת נתונים יוצאת. אם יש כמה כתובות IP צפות בשער התואם, המדיניות משתמשת בכתובת ה-IP הראשונה בfloatingIPsרשימה ומתעלמת מכל כתובת IP אחרת. בשער לדוגמה, הכתובת הראשונה ברשימה floatingIPs היא 192.168.1.100. אם יש שדות או ערכים לא תקינים בקטע gatewayRef, לא תהיה אפשרות להחיל את אובייקט המדיניות.

כמה כללי מדיניות לתעבורת נתונים יוצאת וכמה אובייקטים של שערים

כמו שמתואר בקטע הקודם, כל אובייקט egressNATPolicy (מדיניות) משתמש בכתובת ה-IP הראשונה ברשימה floatingIPs מאובייקט השער שתואמת ל-gatewayRef.name ול-gatewayRef.namespace. אפשר ליצור כמה כללים, ואם אתם מתכוונים להשתמש בכתובות IP שונות, אתם צריכים ליצור כמה אובייקטים של NetworkGatewayGroup ולהפנות אליהם בהתאם.

כל משאב NetworkGatewayGroup צריך להכיל כתובות IP וירטואליות ייחודיות. כדי להגדיר כמה אובייקטים של EgressNATPolicy כך שישתמשו באותה כתובת IP, צריך להשתמש באותם gatewayRef.name ו-gatewayRef.namespace בשניהם.

כדי להגדיר כמה מדיניות תעבורת נתונים יוצאת (egress) וכמה אובייקטים של שערים:

  1. יוצרים אובייקטים של שערים במרחב השמות kube-system כדי לנהל כל כתובת IP צפה. בדרך כלל, לכל מדיניות תעבורת נתונים יוצאת (egress) צריך להיות אובייקט שער תואם כדי להבטיח שהקצאת כתובת ה-IP תהיה נכונה.

    לאחר מכן מאמתים כל אובייקט של שער באמצעות kubectl כדי לקבל את סטטוס ההקצאה של כתובות ה-IP הצפות:

    kind: NetworkGatewayGroup
    apiVersion: networking.gke.io/v1
    metadata:
      namespace: kube-system
      name: gateway1
    spec:
      floatingIPs:
      - 192.168.1.100
    status:
      ...
      floatingIPs:
        192.168.1.100: worker1
    ---
    kind: NetworkGatewayGroup
    apiVersion: networking.gke.io/v1
    metadata:
      namespace: kube-system
      name: gateway2
    spec:
      floatingIPs:
      - 192.168.1.101
    status:
      ...
      floatingIPs:
        192.168.1.101: worker2
    ---
    kind: NetworkGatewayGroup
    apiVersion: networking.gke.io/v1
    metadata:
      namespace: kube-system
      name: gateway3
    spec:
      floatingIPs:
      - 192.168.1.102
    status:
      ...
      floatingIPs:
        192.168.1.102: worker1
    
  2. יוצרים כמה כללי מדיניות שמפנים לאובייקטים של השער, כמו gateway1 שנוצר בשלב הקודם:

    kind: EgressNATPolicy
    apiVersion: networking.gke.io/v1
    metadata:
      name: egress1
    spec:
      ...
      gatewayRef:
        name: gateway1
        namespace: kube-system
    ---
    kind: EgressNATPolicy
    apiVersion: networking.gke.io/v1
    metadata:
      name: egress2
    spec:
      ...
      gatewayRef:
        name: gateway2
        namespace: kube-system
    ---
    kind: EgressNATPolicy
    apiVersion: networking.gke.io/v1
    metadata:
      name: egress3
    spec:
      ...
      gatewayRef:
        name: gateway3
        namespace: kube-system
    

(אופציונלי) ציון צמתים להצבת כתובות IP צפות

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

kind: NetworkGatewayGroup
apiVersion: networking.gke.io/v1
metadata:
  namespace: cluster-cluster1
  name: default
spec:
  floatingIPs:
  - 192.168.1.100
  - 192.168.1.101
  - 192.168.1.102
  nodeSelector:
    node-type: "egressNat"

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

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

בגרסה 1.34 ומעלה של אשכולות, אפשר להגדיר את שער ה-NAT לתעבורת נתונים יוצאת (egress) עם יתירות כשל מהירה. כשיש לכם כמה כתובות IP צפות ואתם מגדירים יתירות כשל מהירה, תקבלו תעבורת נתונים יוצאת (egress) בזמינות גבוהה. התכונה הזו מספקת חלוקת עומס טובה יותר לתעבורת נתונים יוצאת (egress) ומעבר מהיר יותר ליתירות כשל כדי לצמצם את זמן ההשבתה. במקום להסתמך על צומת שער יחיד בכל פעם (פעיל-המתנה), האשכול מחלק את התנועה היוצאת בין כמה צמתי שער וכל כתובות ה-IP הצפות שהוגדרו בNetworkGatewayGroup משאב.

היתרונות העיקריים של מודל פעיל-פעיל הם:

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

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

ההבדלים העיקריים

הגדרת שער NAT לתעבורת נתונים יוצאת (egress) למעבר מהיר לגיבוי משנה את אופן הפעולה של שער NAT לתעבורת נתונים יוצאת (egress):

יכולת פעיל-המתנה (ברירת מחדל) פעיל-פעיל (מעבר מהיר לגיבוי)
שימוש בכתובות IP צפות ‫EgressNATPolicy משתמש רק בכתובת ה-IP הצפה הראשונה ב-NetworkGatewayGroup. כל כתובות ה-IP הצפות שמופיעות ב-NetworkGatewayGroup מחלקות באופן פעיל את תעבורת הנתונים היוצאת.
יתירות כשל אם צומת השער נכשל, אותה כתובת IP צפה עוברת לצומת אחר, מה שיכול לגרום להפרעה בתנועה. אם צומת שער נכשל, התעבורה מופנית לכתובת IP אחרת תקינה בצומת אחר. חיבורים חדשים מנותבים באופן מיידי דרך שערים תקינים, בעוד שחיבורים קיימים עם שמירת מצב בצומת שנכשל מסתיימים.
תעבורת נתונים כל התנועה של מדיניות מסוימת עוברת דרך צומת שער יחיד. התנועה מתחלקת בין כמה צמתי שער בהתבסס על גיבוב עקבי של נקודת הקצה של המקור, כמו Pod.

הגדרת מעבר מהיר לגיבוי (failover)

הגדרת התכונה כוללת שני שלבים עיקריים:

  1. מציינים כמה כתובות IP צפות.

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

    הנה הגדרה לדוגמה:

    apiVersion: networking.gke.io/v1
    kind: NetworkGatewayGroup
    metadata:
      name: egress-gateways
      namespace: cluster-admin
    spec:
      nodeSelector:
        # Selects nodes that are designated as egress gateways
        node-role.kubernetes.io/egress: ""
      floatingIPs:
      - "192.168.1.100"
      - "192.168.1.101"
      - "192.168.1.102"
    
  2. כדי להפעיל מעבר מהיר לגיבוי, מוסיפים את ההערה networking.gke.io/egressnat-ha: "enable" למשאב המותאם אישית EgressNATPolicy:

    kind: EgressNATPolicy
    apiVersion: networking.gke.io/v1
    metadata:
      name: egress
      annotations:
        networking.gke.io/egressnat-ha: "enable"
    spec:
      ...
    

כללים לבחירת תעבורת נתונים יוצאת ומדיניות רשת

שער NAT ליציאה תואם לממשקי API של מדיניות רשת ב-Kubernetes. כללי מדיניות של רשת נבדקים קודם ומקבלים עדיפות על פני כללי בחירת התנועה של שער NAT ליציאה. לדוגמה, אם תעבורת היציאה מפעילה מדיניות רשת ב-Kubernetes שגורמת להשמטת החבילה, כללי שער היציאה לא יבדקו את החבילה. רק אם מדיניות רשת ב-Kubernetes מאפשרת לחבילה לצאת, כללי הבחירה של תעבורת הנתונים היוצאת (egress) מוערכים כדי להחליט איך לטפל בתעבורת נתונים, באמצעות שער NAT ליציאה או באמצעות הסוואה ישירה עם כתובת ה-IP של הצומת שבו פועל ה-Pod.

מגבלות

המגבלות הנוכחיות של שער NAT ליציאה כוללות:

  • שער NAT ליציאה מופעל רק במצב IPv4.

  • כתובות IP של תעבורת יציאה צריכות להיות באותו דומיין Layer 2 עם כתובות IP של צמתים.

  • אם אתם מגדירים איזון עומסים רגיל של BGP לצד Egress NAT ומשתמשים ב-GKE On-Prem API כדי לנהל את האשכולות (עם Terraform, ה Google Cloud מסוף או gcloud CLI), לא תהיה תמיכה בבוררי עמיתים של BGP. חוסר התמיכה הזה עלול לגרום להפעלת סשנים של BGP באופן אקראי באמצעות כתובות IP מקומיות שגויות לצורך יצירת קשר עם עמיתים, מה שמוביל לכשל ב-BGP peering. פתרון עקיף אפשר למצוא במאמר הגדרת מאזני עומסים בחבילה עם BGP: מגבלת BGP Selector.