בדף הזה מוסבר איך להגדיר ניתוב תעבורת נתונים לפודים.
כדי להבין איך פועל ניהול התנועה לשירותים, אפשר לעיין במאמר איך פועל ניהול התנועה לשירותים.
דרישות
- GKE בגרסה 1.30 ואילך.
מגבלות
- ל-
ServiceFunctionChainיכולה להיות פונקציית שירות אחת לכל היותר. - מומלץ להשתמש ב-100 צמתים לכל היותר, בנוסף ל-10 זוגות של
ServiceFunctionChainו-TrafficSelector. - התכונה "ניתוב תנועה לשירותים ב-GKE" זמינה רק בצמתים שפועלת בהם תמונת הצומת של מערכת הפעלה שמותאמת לקונטיינרים.
- התכונה "הפניית תנועה לשירות ב-GKE" תומכת רק בכתובות IP של תעבורת נתונים יוצאת (egress) ושל יעדים.
- התכונה 'הפניית תנועה לשירותים' לא מטפלת בקונפליקטים שמתעוררים כשמחילים על אותו נושא כמה TrafficSelector עם אורך קידומת זהה. כדי למנוע התנגשויות, כדאי לתכנן מראש את בוררי התנועה עם טווחי כתובות IP שלא חופפים וקריטריונים ברורים לבחירה.
הטמעה של ניהול תעבורה
באמצעות GKE Service Steering אתם יכולים להתאים אישית ולשלוט בתנועה ברשת בתוך אשכול. בקטע הזה מוסבר איך להטמיע את Service Steering באמצעות דוגמה של שער אינטרנט.
נניח שאתם רוצים ליצור שער אינטרנט שמאבטח את התנועה ממכשירי הלקוח של משתמשי הקצה לאינטרנט. מסיים VPN מושך תנועה אל השער המנוהל באמצעות מנהרה מאובטחת. תנועת משתמשי הקצה מופנית מחדש לחומת האש ואז לשרת ה-proxy. הפרוקסי מבצע תרגום של כתובת הרשת של המקור (SNAT) בתעבורת הנתונים, מסווה את כתובת המקור המקורית ושולח אותה לאינטרנט.
כדי להטמיע את GKE Service Steering:
- יוצרים VPC עם MTU של 8896.
- יוצרים אשכול GKE.
- יוצרים את ה-Pods של פונקציית השירות ואת השירות.
- יוצרים את
ServiceFunctionChain. - יוצרים את המשאב
TrafficSelectorעם הפניה אלServiceFunctionChain.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את המשימות הבאות:
- מפעילים את ממשק ה-API של Google Kubernetes Engine. הפעלת Google Kubernetes Engine API
- כדי להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז לאתחל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שבגרסאות קודמות של ה-CLI של gcloud אי אפשר להריץ את הפקודות שבמסמך הזה.
הכנת VPC
מכינים VPC. ב-Service Steering נעשה שימוש בהכמסה כדי להפנות את התנועה לפונקציות השירות המתאימות. הצפנה כוללת הוספה של כותרות נוספות לכל מנה, מה שמגדיל את גודל המנה. לא צריך לבצע הגדרה מיוחדת ב-VPC כדי להשתמש בהפניית תנועה לשירותים. כשמכינים את ה-VPC, מומלץ להביא בחשבון את התקורה של ה-encapsulation כשמחליטים על גודל ה-MTU. מידע נוסף זמין במאמר רשת VPC עם MTU מוגדר.
הפקודה הבאה מגדירה את גודל ה-MTU ב-VPC:
gcloud compute networks create VPC_NETWORK_NAME --mtu=8896
מחליפים את VPC_NETWORK_NAME בשם של רשת ה-VPC שמכילה את רשת המשנה.
יצירת אשכול GKE
כדי להפעיל את היכולות המתקדמות של ניהול כתובות IP וניתוב ברשת שנדרשות להטמעה של Service Steering ב-GKE, צריך ליצור אשכול GKE עם GKE Dataplane V2 באופן הבא:
gcloud container clusters create CLUSTER_NAME \
--network VPC_NAME \
--release-channel RELEASE_CHANNEL \
--cluster-version CLUSTER_VERSION \
--enable-dataplane-v2 \
--enable-ip-alias
מחליפים את מה שכתוב בשדות הבאים:
-
CLUSTER_NAME: שם האשכול. -
VPC_NAME: השם של ה-VPC שאליו רוצים לשייך את האשכול. -
RELEASE_CHANNEL: השם של ערוץ ההפצה. -
VERSION: גרסת GKE, שצריכה להיות 1.30 ואילך. אפשר גם להשתמש בדגל--release-channelכדי לבחור ערוץ הפצה. לערוץ ההפצה צריכה להיות גרסת ברירת מחדל של 1.30 ואילך.
יצירת ServiceFunction פודים
כדי ליצור את שרשרת השירותים, פורסים את ה-Pod של סיום ה-VPN ואת ה-Pods הנדרשים של פונקציות השירות בתוך האשכול. Pods מכילים את האפליקציות בקונטיינרים שמבצעות את הפונקציות של הרשת.
ה-Pod של סיום ה-VPN הוא בדרך כלל פונקציית השירות הראשונה בשרשרת, שמסיימת את התנועה שנכנסת לאשכול דרך ה-VPN. לאחר מכן, הוא מכוון את פונקציות השירות האחרות, כמו חומות אש ואיזון עומסים, לעיבוד נוסף לפני ההגעה ליעד הסופי.
בקובץ התצורה לדוגמה הבא מוגדרים שלושת הרכיבים הבאים, שחיוניים לניהול תנועת הרשת באשכול:
- VPN Pod: יוצר נקודת קצה (endpoint) של רשת וירטואלית פרטית (VPN) באשכול, שמאפשרת תקשורת מאובטחת ומוצפנת בין האשכול לבין רשתות חיצוניות.
- פריסת חומת אש: פריסה של כמה עותקים של Pod של חומת אש, שמספקים אבטחה ואיזון עומסים.
- Proxy DaemonSet: פורס Pod של שרת proxy בכל צומת באשכול, כדי לוודא שהתנועה ברשת תעובד באופן מקומי לפני שהיא תועבר לשירותים אחרים כמו חומת אש.
שומרים את קובץ המניפסט לדוגמה הבא בשם service_function.yaml:
apiVersion: v1
kind: Pod
metadata:
name: vpn
namespace: vpn
labels:
app: vpn
spec:
containers:
- name: vpn
image: openvpn
ports:
- containerPort: 51820
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: firewall
namespace: firewall
spec:
replicas: 3
selector:
matchLabels:
app: firewall
template:
metadata:
labels:
app: firewall
spec:
containers:
- name: firewall
image: firewall
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: proxy
namespace: proxy
spec:
selector:
matchLabels:
app: proxy
template:
metadata:
labels:
app: proxy
spec:
containers:
- name: proxy
image: proxy
החלת המניפסט:
kubectl apply -f service_function.yaml
יצירת ServiceFunctionChains
כדי להגדיר רצף של פונקציות רשת לתעבורת נתונים, יוצרים צינור שבו כל פונקציה, כמו חומת אש, שרת proxy ומאזן עומסים, מבצעת את המשימה הספציפית שלה לפני העברת תעבורת הנתונים לפונקציה הבאה.
שומרים את קובץ המניפסט לדוגמה הבא בשם ServiceFunctionChain.yaml:
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: firewall
spec:
sessionAffinity:
clientIPNoDestination:
timeoutSeconds: 3600
serviceFunctions:
- name: firewall
namespace: firewall
podSelector:
matchLabels:
app: firewall
---
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: proxy
spec:
sessionAffinity:
clientIPNoDestination: {}
serviceFunctions:
- name: proxy
namespace: proxy
podSelector:
matchLabels:
app: proxy
מחילים את המניפסט:
kubectl apply -f ServiceFunctionChain.yaml
פונקציות השירות מוגדרות בשורה בתוך ServiceFunctionChain באמצעות השדה serviceFunctions. פונקציית שירות היא בורר נקודות קצה (endpoint).
יצירת משאב TrafficSelector
כדי להגדיר איפה ואיזו תנועה נבחרת לניתוב תנועה לשירות, יוצרים את המשאב TrafficSelector שמפנה אל ServiceFunctionChains כדי להחיל אותו על התנועה שנבחרה.
שומרים את קובץ המניפסט לדוגמה הבא בשם TrafficSelector.yaml:
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
name: vpn-to-firewall
spec:
serviceFunctionChain: firewall
subject:
pods:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: vpn
podSelector:
matchLabels:
app: vpn
egress:
to:
ipBlock:
cidr: 0.0.0.0/0
ports:
- allPorts:
protocol: UDP
- allPorts:
protocol: TCP
---
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
name: firewall-to-proxy
spec:
serviceFunctionChain: proxy
subject:
pods:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: firewall
podSelector:
matchLabels:
app: firewall
egress:
to:
ipBlock:
cidr: 0.0.0.0/0
ports:
- allPorts:
protocol: UDP
- allPorts:
protocol: TCP
מחילים את המניפסט:
kubectl apply -f TrafficSelector.yaml
פתרון בעיות בהפניית שירותים
בקטע הזה מוסבר איך לפתור בעיות שקשורות ל-GKE Service Steering.
אין תנועה ברשת
כדי לנפות את הבעיה, אפשר לבצע את הפעולות הבאות:
שלב 1: מוודאים שההגדרה servicePathId מוגדרת ב-ServiceFunctionChain
מוודאים שהאפשרות servicePathId מוגדרת ב-ServiceFunctionChain. לכל אובייקט ServiceFunctionChain מוקצה מזהה servicePathId ייחודי, כמו שמוצג בדוגמה הבאה:
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: firewall
spec:
serviceFunctions:
- name: firewall
namespace: firewall
podSelector:
matchLabels:
app: firewal
status:
servicePathId: 1
שלב 2: מוודאים שנוצר שירות Kubernetes לכל פונקציית שירות
שירות ClusterIP נוצר באופן אוטומטי לכל פונקציית שירות. אפשר לראות את רשימת השירותים באמצעות kubectl:
kubectl get svc -A -l networking.gke.io/managed-by=service-steering-controller.gke.io
שלב 3: מוודאים שלכל פונקציית שירות נוצרת רשומה במפת ה-BPF בכל צומת כדי לאחסן את כתובת ה-IP של השירות
לכל פונקציית שירות, נוצרת רשומת מפת bpf בכל צומת כדי לאחסן את כתובת ה-IP של השירות.
אחזור השם של anetd Pod:
kubectl get pods -n kube-system -o wide -l k8s-app=cilium
רושמים את שם ה-Pod, בדומה ל-anetd.
מריצים את הפקודה הבאה:
kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcpath list
מחליפים את ANETD-POD-NAME בשם של ה-Pod של anetd.
הפלט אמור להיראות כך:
PATH SERVICE FUNCTION ADDRESS
(1, 1) 10.4.10.124
שלב 4: מוודאים שרשומות המפה של bpf נוצרו במפה sfcselect
בצומת, אם יש Pods שנבחרו על ידי TrafficSelector, רשומות של מפת bpf נוצרות במפה sfcselect. בדוגמה הבאה אפשר לראות שתעבורת TCP/UDP
מכל יציאה של נקודת הקצה (Pod) 3783 לכתובת ה-IP של היעד 10.0.2.12 מנותבת אל
ServiceFunctionChain.
מריצים את הפקודה הבאה:
kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcselect list
מחליפים את ANETD-POD-NAME בשם בפועל של ה-Pod של anetd באשכול.
הפלט אמור להיראות כך:
SELECTOR PATH
3783, egress, 0/TCP, 10.0.2.12/32 /32 (1, 1)
3783, egress, 0/UDP, 10.0.2.12/32 /32 (1, 1)
שלב 5: שימוש ב-tcpdump ביציאה 7081 כדי ללכוד ולנתח את תעבורת הרשת
התכונה 'ניתוב שירותים' מבצעת הצפנה של Geneve ביציאת UDP 7081. אפשר להשתמש ב-tcpdump בצמתים הרלוונטיים כדי לנתח את זרימת התנועה ולזהות את המקום שבו הבעיה מתרחשת.
המאמרים הבאים
- מידע על תמיכה בכמה רשתות לפודים
- מידע על ניתוב שירותים
- מידע נוסף על הגדרת תמיכה במספר רשתות עבור קבוצות Pod