במדריך הזה נסביר איך לחשוף כמה שירותי gRPC שנפרסו ב-Google Kubernetes Engine (GKE) בכתובת IP חיצונית אחת באמצעות מאזן עומסי רשת אזורי חיצוני להעברת סיגנל ללא שינוי וEnvoy Proxy. במדריך הזה מודגשות כמה מהתכונות המתקדמות ש-Envoy מספק ל-gRPC.
מבוא
gRPC היא מסגרת RPC מבוססת קוד פתוח, שאינה תלויה בשפה, שמבוססת על HTTP/2 ומשתמשת ב-מאגר אחסון לפרוטוקולים לייצוג יעיל של נתונים בשידור ולסריאליזציה מהירה. 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. המכונות האלה משתמשות במידע משכבת האפליקציה כדי להעביר בקשות דרך שרת proxy לשירותי gRPC שונים שפועלים באשכול. מופעי Envoy משתמשים ב-DNS של האשכול כדי לזהות ולאזן עומסים של בקשות gRPC נכנסות לקבוצות ה-Pod הפועלות והתקינות של כל שירות. כלומר, העומס של התנועה מאוזן בין ה-pods לפי בקשת RPC ולא לפי חיבור TCP מהלקוח.
ארכיטקטורה
במדריך הזה תפרסו שני שירותי gRPC, echo-grpc ו-reverse-grpc, באשכול Google Kubernetes Engine (GKE) ותחשפו אותם לאינטרנט בכתובת IP ציבורית. התרשים הבא מציג את הארכיטקטורה של חשיפת שני השירותים האלה דרך נקודת קצה אחת:
מאזן עומסי רשת אזורי חיצוני להעברת נתונים מקבל בקשות נכנסות מהאינטרנט (לדוגמה, מלקוחות בנייד או מצרכני שירות מחוץ לחברה). מאזן עומסי הרשת האזורי החיצוני להעברת סיגנל ללא שינוי מבצע את המשימות הבאות:
- מאזן את העומסים של החיבורים הנכנסים לצמתים במאגר. תעבורת הנתונים מועברת לשירות
envoyKubernetes, שחשוף לכל הצמתים באשכול. פרוקסי הרשת של Kubernetes מעביר את החיבורים האלה לקבוצות Pod שמריצות Envoy. - מבצע בדיקות תקינות של HTTP בצמתים באשכול.
Envoy מבצע את המשימות הבאות:
- מסיים חיבורי TLS.
- מגלה את ה-Pods שמריצים את שירותי gRPC על ידי שליחת שאילתה לשירות ה-DNS הפנימי של האשכול.
- התעבורה מנותבת ומאוזנת בין פודים של שירות gRPC.
- מבצע בדיקות תקינות של שירותי gRPC בהתאם לפרוטוקול בדיקת התקינות של gRPC.
- חושף נקודת קצה (endpoint) לבדיקת תקינות של מכונות Envoy על ידי מאזן עומסי רשת אזורי חיצוני להעברת סיגנל ללא שינוי.
שירותי ה-gRPC (echo-grpc ו-reverse-grpc) נחשפים כשירותים ללא ממשק משתמש (headless) של Kubernetes.
המשמעות היא שלא מוקצית כתובת clusterIP, ופרוקסי הרשת של Kubernetes לא מבצע איזון עומסים של תעבורת הנתונים לקבוצות ה-Pod. במקום זאת, נוצרת רשומת A של DNS שמכילה את כתובות ה-IP של ה-Pod בשירות ה-DNS של האשכול. Envoy
מאתר את כתובות ה-IP של ה-pod מתוך רשומת ה-DNS הזו ומבצע איזון עומסים
ביניהן בהתאם למדיניות שהוגדרה ב-Envoy.
בתרשים הבא מוצגים אובייקטים של Kubernetes שמוזכרים במדריך הזה:
עלויות
במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:
כדי ליצור הערכת עלויות בהתאם לשימוש החזוי, אתם יכולים להשתמש במחשבון התמחור.
כשמסיימים את המשימות שמתוארות במסמך הזה אפשר למחוק את המשאבים שיצרתם כדי להימנע מחיובים נוספים. מידע נוסף זמין בקטע הסרת המשאבים.
לפני שמתחילים
-
בדף לבחירת הפרויקט במסוף Google Cloud , בוחרים פרויקט ב- Google Cloud או יוצרים אותו.
התפקידים שנדרשים כדי לבחור או ליצור פרויקט
- Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
-
יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (
roles/resourcemanager.projectCreator), שכולל את ההרשאהresourcemanager.projects.create. איך מקצים תפקידים
-
במסוף Google Cloud , מפעילים את 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הרשומה של כלי העזר לאימות מאפשרת לכלי קובצי האימג' של הקונטיינר שפועלים ב-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מוודאים ששני Pods מוכנים לכל פריסה:
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, בהתאם לשמות של ה-pods של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) מספק כמה יתרונות בהשוואה למאזן עומסי רשת אזורי חיצוני להעברת סיגנל ללא שינוי, כמו יכולת מתקדמת לניהול תעבורת נתונים, אישורי TLS מנוהלים ושילוב עם מוצרים אחרים של Google Cloud Google Cloud, כמו Cloud CDN, Google Cloud Armor ו-IAP.
מומלץ להשתמש במאזן עומסים גלובלי חיצוני של אפליקציות או במאזן עומסים חיצוני אזורי של אפליקציות אם היכולות לניהול תעבורה שהם מציעים מתאימות לתרחישי השימוש שלכם, ואם אתם לא צריכים תמיכה באימות מבוסס-אישור לקוח, שנקרא גם אימות 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.
כדי להשתמש במאזן עומסים של אפליקציות (ALB) פנימי, קראו את מאמרי העזרה הגדרת Ingress למאזני עומסים של אפליקציות (ALB) פנימיים.
הסרת המשאבים
אחרי שמסיימים את המדריך, אפשר למחוק את המשאבים שנוצרו, כדי שהם יפסיקו להשתמש במכסה ולצבור חיובים. בסעיפים הבאים מוסבר איך למחוק או להשבית את המשאבים האלו.
מחיקת הפרויקט
- במסוף Google Cloud , נכנסים לדף Manage resources.
- ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
- כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.
מחיקת המשאבים
אם אתם רוצים לשמור את 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.