במדריך הזה נסביר איך לחשוף כמה שירותי gRPC שנפרסו ב-Google Kubernetes Engine (GKE) בכתובת IP חיצונית אחת באמצעות מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי ו-Envoy Proxy. במדריך הזה נסביר על חלק מהתכונות המתקדמות ש-Envoy מספק ל-gRPC.
מבוא
gRPC היא מסגרת RPC מבוססת קוד פתוח, שאינה תלויה בשפה ומבוססת על HTTP/2. היא משתמשת ב-protocol buffers לייצוג יעיל של נתונים בשידור ולסריאליזציה מהירה. gRPC, שנוצר בהשראת Stubby, מסגרת ה-RPC הפנימית של Google, מאפשר תקשורת עם השהיה נמוכה בין מיקרו-שירותים ובין לקוחות ניידים לבין ממשקי API.
פרוטוקול gRPC פועל על HTTP/2 ומציע כמה יתרונות על פני HTTP/1.1, כמו קידוד בינארי יעיל, ריבוב של בקשות ותגובות על פני חיבור יחיד ובקרה על זרימת נתונים אוטומטית. בנוסף, פרוטוקול gRPC מציע כמה אפשרויות לאיזון עומסים. ההדרכה הזו מתמקדת במצבים שבהם הלקוחות לא מהימנים, כמו לקוחות ניידים ולקוחות שפועלים מחוץ לגבולות המהימנות של ספק השירות. מבין אפשרויות איזון העומסים ש-gRPC מספק, במדריך הזה נעשה שימוש באיזון עומסים מבוסס-proxy.
במדריך הזה, אתם פורסים שירות Kubernetes של TYPE=LoadBalancer, שנחשף כמאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי בשכבת התעבורה (שכבה 4) ב-Google Cloud. השירות הזה מספק כתובת IP ציבורית אחת ומעביר חיבורי TCP ישירות לקצה העורפי שהוגדר. במדריך, הבק-אנד הוא פריסת Kubernetes של מופעי Envoy.
Envoy הוא פרוקסי קוד פתוח של שכבת האפליקציה (שכבה 7) שמציע תכונות מתקדמות רבות. במדריך הזה נשתמש בו כדי לסיים חיבורי TLS ולנתב תעבורת gRPC לשירות Kubernetes המתאים. בהשוואה לפתרונות אחרים בשכבת האפליקציה, כמו Kubernetes Ingress, שימוש ישיר ב-Envoy מספק אפשרויות רבות להתאמה אישית, כמו האפשרויות הבאות:
- זיהוי שירותים
- אלגוריתמים של איזון עומסים
- שינוי בקשות ותגובות – למשל, ל-JSON או ל-gRPC-Web
- אימות בקשות באמצעות אימות טוקנים של JWT
- בדיקות תקינות של gRPC
אם משלבים מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי עם Envoy, אפשר להגדיר נקודת קצה (כתובת IP חיצונית) שמעבירה תעבורת נתונים לקבוצה של מופעי Envoy שפועלים באשכול Google Kubernetes Engine. לאחר מכן, המופעים האלה משתמשים במידע בשכבת האפליקציה כדי להעביר בקשות באמצעות פרוקסי לשירותי gRPC שונים שפועלים באשכול. מופעי Envoy משתמשים ב-DNS של אשכול כדי לזהות ולאזן עומסים של בקשות gRPC נכנסות ל-pods תקינים שפועלים עבור כל שירות. כלומר, התנועה מאוזנת בין הפודים לפי בקשת RPC ולא לפי חיבור TCP מהלקוח.
ארכיטקטורה
במדריך הזה תפרסו שני שירותי gRPC, echo-grpc ו-reverse-grpc, באשכול Google Kubernetes Engine (GKE) ותחשפו אותם לאינטרנט בכתובת IP ציבורית. התרשים הבא מציג את הארכיטקטורה של חשיפת שני השירותים האלה דרך נקודת קצה אחת:
מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי מקבל בקשות נכנסות מהאינטרנט (לדוגמה, מלקוחות ניידים או מצרכני שירות מחוץ לחברה). מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי מבצע את המשימות הבאות:
- מאזן עומסים של חיבורים נכנסים לצמתים במאגר. תעבורת הנתונים מועברת אל
envoyKubernetes Service, שנחשף בכל הצמתים באשכול. פרוקסי הרשת של Kubernetes מעביר את החיבורים האלה לקבוצות Pod שמריצות Envoy. - מבצע בדיקות תקינות של HTTP בצמתים באשכול.
Envoy מבצע את המשימות הבאות:
- מסיים חיבורי TLS.
- מגלה את ה-Pods שמריצים את שירותי gRPC על ידי שליחת שאילתה לשירות ה-DNS הפנימי של האשכול.
- מנתב את תעבורת הנתונים ומאזן את העומס על פודים של שירות gRPC.
- מבצע בדיקות תקינות של שירותי gRPC בהתאם לפרוטוקול בדיקת התקינות של gRPC.
- חשיפת נקודת קצה לבדיקת התקינות של מופעי Envoy על ידי מאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי.
שירותי gRPC (echo-grpc ו-reverse-grpc) נחשפים כשירותים ללא כתובת IP ב-Kubernetes.
המשמעות היא שלא מוקצית כתובת clusterIP, ופרוקסי הרשת של Kubernetes לא מבצע איזון עומסים של תעבורת הנתונים לקבוצות ה-Pod. במקום זאת, נוצרת רשומת DNS A שמכילה את כתובות ה-IP של ה-Pod בשירות ה-DNS של האשכול. Envoy מגלה את כתובות ה-IP של ה-pod מתוך רשומת ה-DNS הזו ומבצע איזון עומסים ביניהן בהתאם למדיניות שהוגדרה ב-Envoy.
הדיאגרמה הבאה מציגה את אובייקטי Kubernetes שמוזכרים במדריך הזה:
עלויות
במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:
כדי להעריך את ההוצאות בהתאם לתחזית השימוש שלכם, אתם יכולים להיעזר במחשבון העלויות.
כשמסיימים את המשימות שמתוארות במסמך הזה אפשר למחוק את המשאבים שיצרתם כדי להימנע מחיובים נוספים. מידע נוסף זמין בקטע הסרת המשאבים.
לפני שמתחילים
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
הכנת הסביבה
ב-Cloud Shell, מגדירים את הפרויקט שבו רוצים להשתמש במדריך הזה: Google Cloud
gcloud config set project PROJECT_ID
מחליפים את
PROJECT_IDבמזהה הפרויקט ב-Google Cloud .מפעילים את ממשקי ה-API של Artifact Registry ו-GKE:
gcloud services enable artifactregistry.googleapis.com \ container.googleapis.com
יצירת אשכול GKE
ב-Cloud Shell, יוצרים אשכול GKE להרצת שירותי gRPC:
gcloud container clusters create envoy-grpc-tutorial \ --enable-ip-alias \ --release-channel rapid \ --scopes cloud-platform \ --workload-pool PROJECT_ID.svc.id.goog \ --location us-central1-fבמדריך הזה נעשה שימוש באזור
us-central1-f. אפשר להשתמש באזור או בתחום אחרים.כדי לוודא שההקשר
kubectlהוגדר, מציגים את הצמתים באשכול:kubectl get nodes --output nameהפלט אמור להיראות כך:
node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-1kpt node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-qn92 node/gke-envoy-grpc-tutorial-default-pool-c9a3c791-wf2h
יצירת מאגר Artifact Registry
ב-Cloud Shell, יוצרים מאגר חדש לאחסון תמונות של קונטיינרים:
gcloud artifacts repositories create envoy-grpc-tutorial-images \ --repository-format docker \ --location us-central1כדי למטב את זמן האחזור ואת רוחב הפס של הרשת כשצמתים שולפים תמונות של קונטיינרים, כדאי ליצור את המאגר באותו אזור שבו נמצא אשכול GKE.
נותנים את התפקיד Artifact Registry Reader במאגר לחשבון השירות של Google שמשמש את המכונות הווירטואליות של הצמתים באשכול GKE:
PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format 'value(projectNumber)') gcloud artifacts repositories add-iam-policy-binding envoy-grpc-tutorial-images \ --location us-central1 \ --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --role roles/artifactregistry.readerמוסיפים רשומה של כלי עזר לפרטי כניסה לשם המארח של המאגר לקובץ התצורה של Docker בספריית הבית של Cloud Shell:
gcloud auth configure-docker us-central1-docker.pkg.devהערך של credential helper מאפשר לכלי קובץ אימג' של קונטיינר שפועלים ב-Cloud Shell לבצע אימות למיקום של מאגר Artifact Registry כדי לשלוף ולדחוף תמונות.
פריסת שירותי gRPC
כדי לנתב תנועה לכמה שירותי gRPC מאחורי מאזן עומסים אחד, פורסים שני שירותי gRPC לדוגמה:
echo-grpcו-reverse-grpc. בשני השירותים יש שיטה אונרית שמקבלת מחרוזת בשדה הבקשהcontent. echo-grpcמגיב עם התוכן ללא שינוי, ואילוreverse-grpcמגיב עם מחרוזת התוכן הפוכה.ב-Cloud Shell, משכפלים את המאגר שמכיל את שירותי ה-gRPC ועוברים לספריית המאגר:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples cd kubernetes-engine-samples/networking/grpc-gke-nlb-tutorial/יוצרים אישור TLS בחתימה עצמית ומפתח פרטי:
openssl req -x509 -newkey rsa:4096 -nodes -sha256 -days 365 \ -keyout privkey.pem -out cert.pem -extensions san \ -config \ <(echo "[req]"; echo distinguished_name=req; echo "[san]"; echo subjectAltName=DNS:grpc.example.com ) \ -subj '/CN=grpc.example.com'יוצרים סוד של Kubernetes בשם
envoy-certsשמכיל את אישור ה-TLS בחתימה עצמית ואת המפתח הפרטי:kubectl create secret tls envoy-certs \ --key privkey.pem --cert cert.pem \ --dry-run=client --output yaml | kubectl apply --filename -Envoy משתמש באישור ה-TLS ובמפתח הפרטי הזה כשהוא מסיים חיבורי TLS.
יוצרים את קובצי האימג' של הקונטיינרים עבור האפליקציות לדוגמה
echo-grpcו-reverse-grpc, מעבירים את קובצי האימג' בדחיפה ל-Artifact Registry ופורסים את האפליקציות לאשכול GKE באמצעות Skaffold:skaffold run \ --default-repo=us-central1-docker.pkg.dev/PROJECT_ID/envoy-grpc-tutorial-images \ --module=echo-grpc,reverse-grpc \ --skip-testsSkaffold הוא כלי בקוד פתוח מבית Google שמבצע אוטומציה של תהליכי עבודה לפיתוח, לבנייה, להעברה ולפריסה של אפליקציות כקונטיינרים.
פורסים את Envoy באשכול GKE באמצעות Skaffold:
skaffold run \ --digest-source=none \ --module=envoy \ --skip-testsבודקים ששני פודים מוכנים לכל פריסה:
kubectl get deploymentsהפלט אמור להיראות כך: הערכים של
READYצריכים להיות2/2בכל הפריסות.NAME READY UP-TO-DATE AVAILABLE AGE echo-grpc 2/2 2 2 1m envoy 2/2 2 2 1m reverse-grpc 2/2 2 2 1m
מוודאים ש-
echo-grpc, envoyו-reverse-grpcקיימים כשירותי Kubernetes:kubectl get services --selector skaffold.dev/run-idהפלט אמור להיראות כך: גם
echo-grpcוגםreverse-grpcצריכים לכלול אתTYPE=ClusterIPו-CLUSTER-IP=None.NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE echo-grpc ClusterIP None <none> 8081/TCP 2m envoy LoadBalancer 10.40.2.203 203.0.113.1 443:31516/TCP 2m reverse-grpc ClusterIP None <none> 8082/TCP 2m
בדיקת שירותי gRPC
כדי לבדוק את השירותים, משתמשים בכלי שורת הפקודה
grpcurl.ב-Cloud Shell, מתקינים את
grpcurl:go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latestמקבלים את כתובת ה-IP החיצונית של שירות Kubernetes
envoyומאחסנים אותה במשתנה סביבה:EXTERNAL_IP=$(kubectl get service envoy \ --output=jsonpath='{.status.loadBalancer.ingress[0].ip}')שליחת בקשה לאפליקציה לדוגמה
echo-grpc:grpcurl -v -d '{"content": "echo"}' \ -proto echo-grpc/api/echo.proto \ -authority grpc.example.com -cacert cert.pem \ $EXTERNAL_IP:443 api.Echo/Echoהפלט אמור להיראות כך:
Resolved method descriptor: rpc Echo ( .api.EchoRequest ) returns ( .api.EchoResponse ); Request metadata to send: (empty) Response headers received: content-type: application/grpc date: Wed, 02 Jun 2021 07:18:22 GMT hostname: echo-grpc-75947768c9-jkdcw server: envoy x-envoy-upstream-service-time: 3 Response contents: { "content": "echo" } Response trailers received: (empty) Sent 1 request and received 1 responseבכותרת התגובה
hostnameמוצג השם של פודecho-grpcשטיפל בבקשה. אם חוזרים על הפקודה כמה פעמים, אמורים לראות שני ערכים שונים בכותרת התגובהhostname, שמתאימים לשמות של תרמילי ה-echo-grpc.כדי לוודא שההתנהגות זהה, משתמשים בשירות gRPC הפוך:
grpcurl -v -d '{"content": "reverse"}' \ -proto reverse-grpc/api/reverse.proto \ -authority grpc.example.com -cacert cert.pem \ $EXTERNAL_IP:443 api.Reverse/Reverseהפלט אמור להיראות כך:
Resolved method descriptor: rpc Reverse ( .api.ReverseRequest ) returns ( .api.ReverseResponse ); Request metadata to send: (empty) Response headers received: content-type: application/grpc date: Wed, 02 Jun 2021 07:20:15 GMT hostname: reverse-grpc-5c9b974f54-wlfwt server: envoy x-envoy-upstream-service-time: 1 Response contents: { "content": "esrever" } Response trailers received: (empty) Sent 1 request and received 1 response
הגדרות Envoy
כדי להבין טוב יותר את ההגדרה של Envoy, אפשר לעיין בקובץ ההגדרה
envoy/k8s/envoy.yamlבמאגר Git.בקטע
route_configמפורט איך בקשות נכנסות מנותבות לאפליקציות לדוגמהecho-grpcוreverse-grpc.אפליקציות לדוגמה מוגדרות כקלאסטרים של Envoy.
השדות
type: STRICT_DNSו-lb_policy: ROUND_ROBINבהגדרת האשכול מציינים ש-Envoy מבצע חיפושי DNS של שם המארח שצוין בשדהaddress, ומבצע איזון עומסים בין כתובות ה-IP בתגובה לחיפוש ה-DNS. התשובה מכילה כמה כתובות IP כי אובייקטים של שירות Kubernetes שמגדירים את האפליקציות לדוגמה מציינים שירותים ללא ראש.השדה
http2_protocol_optionsמציין ש-Envoy משתמש בפרוטוקול HTTP/2 באפליקציות לדוגמה.השדה
grpc_health_checkבקטעhealth_checksמציין ש-Envoy משתמש בפרוטוקול בדיקת התקינות של gRPC כדי לקבוע את התקינות של האפליקציות לדוגמה.פתרון בעיות
אם נתקלתם בבעיות במדריך הזה, מומלץ לעיין במסמכים הבאים:
אפשר גם לעיין בממשק הניהול של Envoy כדי לאבחן בעיות בהגדרות של Envoy.
כדי לפתוח את ממשק הניהול, מגדירים העברה ליציאה אחרת מ-Cloud Shell ליציאה
adminשל אחד מ-pods של Envoy:kubectl port-forward \ $(kubectl get pods -o name | grep envoy | head -n1) 8080:8090מחכים עד שהפלט הבא יופיע במסוף:
Forwarding from 127.0.0.1:8080 -> 8090
לוחצים על הלחצן Web preview (תצוגה מקדימה של אתר) ב-Cloud Shell ובוחרים באפשרות Preview on port 8080 (תצוגה מקדימה ביציאה 8080). ייפתח חלון חדש בדפדפן עם ממשק הניהול.
כשמסיימים, חוזרים ל-Cloud Shell ומקישים על
Control+Cכדי לסיים את העברת היציאות.
דרכים חלופיות לניתוב תנועת gRPC
אפשר לשנות את הפתרון הזה בכמה דרכים כדי להתאים אותו לסביבה שלכם.
מאזני עומסים חלופיים בשכבת האפליקציות
חלק מהפונקציות של שכבת האפליקציה ש-Envoy מספקת יכולות להיות מסופקות גם על ידי פתרונות אחרים לאיזון עומסים:
אתם יכולים להשתמש במאזן עומסים חיצוני גלובלי של אפליקציות או במאזן עומסים חיצוני אזורי של אפליקציות במקום במאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי וב-Envoy בניהול עצמי. שימוש במאזן עומסים חיצוני של אפליקציות (ALB) מספק כמה יתרונות בהשוואה למאזן עומסי רשת חיצוני מסוג passthrough, כמו יכולת מתקדמת לניהול תעבורה, אישורי TLS מנוהלים ושילוב עם מוצרים אחרים של Google Cloud Google Cloud, כמו Cloud CDN, Google Cloud Armor ו-IAP.
מומלץ להשתמש במאזן עומסים גלובלי חיצוני של אפליקציות (ALB) או במאזן עומסים חיצוני אזורי של אפליקציות (ALB) אם יכולות ניהול התנועה שהם מציעים מתאימות לתרחישי השימוש שלכם, ואם אתם לא צריכים תמיכה באימות מבוסס-אישורים של לקוחות, שנקרא גם אימות mutual TLS (mTLS). מידע נוסף זמין במאמרים הבאים:
אם אתם משתמשים ב-Cloud Service Mesh או ב-Istio, אתם יכולים להשתמש בתכונות שלהם כדי לנתב את תנועת הנתונים של gRPC ולבצע איזון עומסים. גם Cloud Service Mesh וגם Istio מספקים שער כניסה שנפרס כמאזן עומסי רשת חיצוני עם העברת נתונים ישירה, עם קצה עורפי של Envoy, בדומה לארכיטקטורה שמוצגת במדריך הזה. ההבדל העיקרי הוא ש-Envoy מוגדר באמצעות אובייקטים של ניתוב תנועה של Istio.
כדי שיהיה אפשר לנתב את שירותי הדוגמה במדריך הזה ב-Cloud Service Mesh או ב-Istio service mesh, צריך להסיר את השורה
clusterIP: Noneממניפסטים של שירותי Kubernetes (echo-service.yamlו-reverse-service.yaml). המשמעות היא שצריך להשתמש בפונקציונליות של גילוי שירותים ואיזון עומסים ב-Cloud Service Mesh או ב-Istio במקום בפונקציונליות דומה ב-Envoy.אם אתם כבר משתמשים ב-Cloud Service Mesh או ב-Istio, מומלץ להשתמש בשער הכניסה כדי לנתב לשירותי ה-gRPC.
אפשר להשתמש ב-NGINX במקום ב-Envoy, כפריסה או באמצעות NGINX Ingress Controller for Kubernetes. השתמשנו ב-Envoy במדריך הזה כי הוא מספק פונקציונליות מתקדמת יותר של gRPC, כמו תמיכה בפרוטוקול בדיקת תקינות של gRPC.
קישוריות פנימית לרשת VPC
אם רוצים לחשוף את השירותים מחוץ לאשכול GKE אבל רק בתוך רשת ה-VPC, אפשר להשתמש במאזן עומסי רשת פנימי להעברת סיגנל ללא שינוי או במאזן עומסים פנימי של אפליקציות (ALB).
כדי להשתמש במאזן עומסי רשת פנימי להעברת סיגנל ללא שינוי במקום במאזן עומסי רשת חיצוני להעברת סיגנל ללא שינוי, מוסיפים את ההערה
cloud.google.com/load-balancer-type: "Internal"למניפסטenvoy-service.yaml.כדי להשתמש במאזן עומסים פנימי של אפליקציות, אפשר לעיין במסמכים בנושא הגדרת Ingress למאזני עומסים פנימיים של אפליקציות.
הסרת המשאבים
אחרי שמסיימים את המדריך, אפשר למחוק את המשאבים שנוצרו, כדי שהם יפסיקו להשתמש במכסה ולצבור חיובים. בסעיפים הבאים מוסבר איך למחוק או להשבית את המשאבים האלו.
מחיקת הפרויקט
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
מחיקת המשאבים
אם אתם רוצים לשמור את הפרויקט שבו השתמשתם במדריך הזה, אתם צריכים למחוק את המשאבים הבודדים: Google Cloud
ב-Cloud Shell, מוחקים את השיבוט המקומי של מאגר ה-Git:
cd ; rm -rf kubernetes-engine-samples/networking/grpc-gke-nlb-tutorial/מחיקת אשכול GKE:
gcloud container clusters delete envoy-grpc-tutorial \ --location us-central1-f --async --quietמחיקת המאגר ב-Artifact Registry:
gcloud artifacts repositories delete envoy-grpc-tutorial-images \ --location us-central1 --async --quiet
המאמרים הבאים
- מידע על רשתות GKE
- דוגמאות לאופן החשיפה של שירותי gRPC ללקוחות בתוך אשכול Kubernetes
אפשר לעיין באפשרויות של איזון עומסים ב-gRPC.
כדאי להעמיק את הקריאה ולהכיר דוגמאות לארכיטקטורות, תרשימים ושיטות מומלצות בנושאי Google Cloud. כל אלה זמינים במרכז הארכיטקטורה של Cloud.