Cloud Service Mesh הוא כלי רב עוצמה לניהול ולמעקב אחרי אפליקציות מבוזרות. כדי להפיק את המרב מ-Cloud Service Mesh, כדאי להבין את ההפשטות הבסיסיות שלו, כולל קונטיינרים ו-Kubernetes. במדריך הזה מוסבר איך להכין אפליקציה ל-Cloud Service Mesh מקוד מקור ועד לקונטיינר שפועל ב-GKE, עד לשלב שלפני ההתקנה של Cloud Service Mesh.
אם אתם כבר מכירים את המושגים של Kubernetes ו-service mesh, אתם יכולים לדלג על המדריך הזה ולעבור ישירות אל מדריך ההתקנה של Cloud Service Mesh.
מטרות
- לגלות אפליקציית hello world פשוטה עם כמה שירותים.
- הפעלת האפליקציה מקוד המקור
- העברת האפליקציה לקונטיינר.
- יוצרים אשכול Kubernetes.
- פורסים את הקונטיינרים באשכול.
לפני שמתחילים
כדי להפעיל את Cloud Service Mesh API, מבצעים את השלבים הבאים:- נכנסים ל דף Kubernetes Engine במסוף Google Cloud .
- יוצרים או בוחרים פרויקט.
- מחכים עד שממשק ה-API והשירותים הקשורים מופעלים. הפעולה יכולה להימשך כמה דקות.
-
Verify that billing is enabled for your Google Cloud project.
במדריך הזה נעשה שימוש ב-Cloud Shell, שמקצה מכונה וירטואלית (VM) מסוג g1-small Compute Engine שמריצה מערכת הפעלה Linux מבוססת Debian.
הכנת Cloud Shell
היתרונות של שימוש ב-Cloud Shell:
- סביבות הפיתוח של Python 2 ו-Python 3 (כולל
virtualenv) מוגדרות. - כלי שורת הפקודה
gcloud,docker,gitו-kubectlשבהם נעשה שימוש במדריך הזה כבר מותקנים. יש לכם אפשרות לבחור מבין עורכי טקסט:
עורך קוד, שאליו ניגשים בלחיצה על בחלק העליון של חלון Cloud Shell.
Emacs, Vim או Nano, שאפשר לגשת אליהם משורת הפקודה ב-Cloud Shell.
In the Google Cloud console, activate Cloud Shell.
הורדת קוד לדוגמה
מורידים את קוד המקור של
helloserver:git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samplesעוברים לספרייה של הקוד לדוגמה:
cd anthos-service-mesh-samples/docs/helloserver
הכרת האפליקציה עם כמה שירותים
אפליקציית הדוגמה כתובה ב-Python, ויש לה שני רכיבים שמתקשרים באמצעות REST:
server: שרת פשוט עם נקודת קצה אחתGET, /, שמדפיסה את המחרוזת hello world במסוף.-
loadgen: סקריפט ששולח תנועה אלserver, עם מספר בקשות שניתן להגדרה לשנייה (RPS).
הפעלת האפליקציה מקוד המקור
כדי להכיר את האפליקציה לדוגמה, מריצים אותה ב-Cloud Shell.
מהספרייה
sample-apps/helloserver, מריצים את הפקודהserver:python3 server/server.pyבזמן ההפעלה, ב-
serverמוצגים הנתונים הבאים:INFO:root:Starting server...
פותחים חלון טרמינל נוסף כדי שאפשר יהיה לשלוח בקשות אל
server. לוחצים על כדי לפתוח סשן נוסף.שליחת בקשה אל
server:curl http://localhost:8080
serverמשיב:Hello World!
מהספרייה שבה הורדתם את הקוד לדוגמה, עוברים לספרייה שמכילה את
loadgen:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/loadgen
יוצרים את משתני הסביבה הבאים:
export SERVER_ADDR=http://localhost:8080 export REQUESTS_PER_SECOND=5התחלה
virtualenv:virtualenv --python python3 envמפעילים את הסביבה הווירטואלית:
source env/bin/activateמתקינים את הדרישות ל-
loadgen:pip3 install -r requirements.txtמריצים את הפקודה
loadgen:python3 loadgen.pyבהפעלה, הפקודה
loadgenמוציאה הודעה שדומה להודעה הבאה:Starting loadgen: 2019-05-20 10:44:12.448415 5 request(s) complete to http://localhost:8080
בחלון המסוף השני,
serverכותב הודעות למסוף בדומה להודעות הבאות:127.0.0.1 - - [21/Jun/2019 14:22:01] "GET / HTTP/1.1" 200 - INFO:root:GET request, Path: / Headers: Host: localhost:8080 User-Agent: python-requests/2.22.0 Accept-Encoding: gzip, deflate Accept: */*
מבחינת הרשת, כל האפליקציה פועלת עכשיו באותו מארח. לכן, אפשר להשתמש ב-
localhostכדי לשלוח בקשות אלserver.כדי לעצור את
loadgenואתserver, מזיניםCtrl-cבכל חלון של מסוף.בחלון הטרמינל
loadgen, משביתים את הסביבה הווירטואלית:deactivate
העברת האפליקציה למאגר
כדי להריץ את האפליקציה ב-GKE, צריך לארוז את האפליקציה לדוגמה – גם את server וגם את loadgen – בקונטיינרים. קונטיינר הוא דרך לארוז אפליקציה כך שהיא מבודדת מהסביבה הבסיסית.
כדי להוסיף את האפליקציה למאגר, צריך Dockerfile. Dockerfilebuildpack הוא קובץ טקסט שמגדיר את הפקודות שנדרשות כדי להרכיב את קוד המקור של האפליקציה ואת יחסי התלות שלה לתוך קובץ אימג' של Docker. אחרי שיוצרים את האימג', מעלים אותו למאגר קונטיינרים, כמו Docker Hub או Container Registry.
הדוגמה כוללת Dockerfile גם ל-server וגם ל-loadgen עם כל הפקודות שנדרשות כדי ליצור את קובצי האימג'. הנה Dockerfile של server:
- הפקודה
FROM python:3-slim as baseאומרת ל-Docker להשתמש בקובץ האימג' העדכני ביותר של Python 3 כקובץ האימג' הבסיסי. - הפקודה
COPY . .מעתיקה את קובצי המקור בספריית העבודה הנוכחית (במקרה הזה, רקserver.py) למערכת הקבצים של הקונטיינר. - הפקודה
ENTRYPOINTמגדירה את הפקודה שמשמשת להפעלת הקונטיינר. במקרה הזה, הפקודה כמעט זהה לזו שבה השתמשתם כדי להריץ אתserver.pyמקוד המקור. - הפקודה
EXPOSEמציינת שהשירותserverמאזין ליציאה8080. הפקודה הזו לא חושפת יציאות, אבל היא משמשת כתיעוד שצריך לפתוח את יציאה8080כשמריצים את הקונטיינר.
הכנה להעברת האפליקציה לקונטיינר
מגדירים את משתני הסביבה הבאים. מחליפים את
PROJECT_IDבמזהה שלGoogle Cloud הפרויקט.export PROJECT_ID="PROJECT_ID"
export GCR_REPO="asm-ready"
משתמשים בערך של
PROJECT_IDושלGCR_REPOכדי לתייג את קובץ האימג' של Docker כשיוצרים אותו ואז מעבירים אותו בדחיפה ל-Container Registry הפרטי.מגדירים את פרויקט ברירת המחדל Google Cloud ל-Google Cloud CLI.
gcloud config set project $PROJECT_ID
מגדירים את אזור ברירת המחדל ל-Google Cloud CLI.
gcloud config set compute/zone us-central1-bמוודאים ששירות Container Registry מופעל בפרויקטGoogle Cloud .
gcloud services enable containerregistry.googleapis.com
העברה לקונטיינרים של server
עוברים לספרייה שבה נמצאת הדוגמה
server:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
יוצרים את התמונה באמצעות
Dockerfileומשתני הסביבה שהגדרתם קודם:docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1 .הדגל
-tמייצג את תג Docker. זה השם של קובץ האימג' שבו משתמשים כשפורסים את הקונטיינר.מעבירים את התמונה בדחיפה ל-Container Registry:
docker push gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1
העברה לקונטיינרים של loadgen
עוברים לספרייה שבה נמצאת הדוגמה
loadgen:cd ../loadgenיוצרים את התמונה:
docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1 .מעבירים את התמונה בדחיפה ל-Container Registry:
docker push gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1
הכנת רשימה של התמונות
כדי לוודא שהתמונות נדחפו, אפשר לקבל רשימה של התמונות במאגר:
gcloud container images list --repository gcr.io/$PROJECT_ID/asm-ready
הפקודה מחזירה את שמות התמונות שדחפתם:
NAME gcr.io/PROJECT_ID/asm-ready/helloserver gcr.io/PROJECT_ID/asm-ready/loadgen
יצירת אשכול GKE
אפשר להריץ את הקונטיינרים האלה במכונה וירטואלית של Cloud Shell באמצעות הפקודה docker run. אבל בסביבת ייצור, צריך לתזמן את הפעולה של הקונטיינרים בצורה אחידה יותר. לדוגמה, אתם צריכים מערכת שתדאג שהקונטיינרים תמיד יפעלו, ושתאפשר לכם להגדיל את מספר המופעים של הקונטיינר ולהפעיל מופעים נוספים כדי להתמודד עם עלייה בתנועה.
אפשר להשתמש ב-GKE כדי להריץ אפליקציות בקונטיינרים. GKE היא פלטפורמה לניהול קונטיינרים שפועלת על ידי חיבור מכונות וירטואליות לאשכול. כל מכונה וירטואלית נקראת צומת. אשכולות GKE מבוססים על מערכת ניהול האשכולות בקוד פתוח Kubernetes. Kubernetes מספקת את המנגנונים שדרכם מתבצעת האינטראקציה עם האשכול.
כדי ליצור אשכול GKE:
יוצרים את האשכול:
gcloud container clusters create asm-ready \ --cluster-version latest \ --machine-type=n1-standard-4 \ --num-nodes 4
הפקודה
gcloudיוצרת אשכול בפרויקטGoogle Cloud ובאזור שהגדרתם קודם. כדי להפעיל את Cloud Service Mesh, מומלץ להשתמש לפחות ב-4 צמתים ובסוג המכונה n1-standard-4.השלמת הפקודה ליצירת האשכול נמשכת כמה דקות. כשהאשכול מוכן, הפקודה מציגה הודעה שדומה להודעה הבאה:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS asm-ready us-central1-b 1.13.5-gke.10 203.0.113.1 n1-standard-2 1.13.5-gke.10 4 RUNNING
מספקים פרטי כניסה לכלי שורת הפקודה
kubectlכדי שתוכלו להשתמש בו לניהול האשכול:gcloud container clusters get-credentials asm-readyעכשיו אפשר להשתמש ב-
kubectlכדי לתקשר עם Kubernetes. לדוגמה, אפשר להריץ את הפקודה הבאה כדי לקבל את הסטטוס של הצמתים:kubectl get nodesהפקודה מחזירה רשימה של הצמתים, בדומה לזו:
NAME STATUS ROLES AGE VERSION gke-asm-ready-default-pool-dbeb23dc-1vg0 Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-36z5 Ready <none> 100s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-fj7s Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-wbjw Ready <none> 99s v1.13.6-gke.13
הסבר על מושגי מפתח ב-Kubernetes
התרשים הבא מתאר את האפליקציה שפועלת ב-GKE:
לפני שמפעילים את הקונטיינרים ב-GKE, כדאי לעיין בכמה מושגים מרכזיים ב-Kubernetes. בסוף המדריך הזה מופיעים קישורים למידע נוסף על כל מושג.
צמתים ואשכולות: ב-GKE, צומת הוא מכונה וירטואלית. בפלטפורמות אחרות של Kubernetes, צומת יכול להיות מכונה פיזית או וירטואלית. קלאסטר הוא קבוצה של צמתים שאפשר להתייחס אליהם יחד כמכונה אחת, שבה פורסים אפליקציה מבוססת-קונטיינר.
Pods: ב-Kubernetes, קונטיינרים פועלים בתוך Pod. Pod הוא היחידה האטומית ב-Kubernetes. כל Pod מכיל מאגר אחד או יותר. פורסים את מאגרי התגים
serverו-loadgen, כל אחד ב-Pod משלו. כש-Pod מריץ כמה קונטיינרים (לדוגמה, שרת אפליקציות ושרת proxy), הקונטיינרים מנוהלים כישות אחת וחולקים את המשאבים של ה-Pod.פריסות: פריסה היא אובייקט Kubernetes שמייצג קבוצה של Pods זהים. פריסה מפעילה כמה עותקים של ה-Pods שמפוזרים בין הצמתים של אשכול. פריסה מחליפה באופן אוטומטי כל Pod שנכשל או מפסיק להגיב.
Kubernetes Service: הרצת קוד האפליקציה ב-GKE משנה את הרישות בין
loadgenלביןserver. כשמריצים את השירותים במכונה וירטואלית של Cloud Shell, אפשר לשלוח בקשות אלserverבאמצעות הכתובתlocalhost:8080. אחרי הפריסה ב-GKE, הפודים מתוזמנים להפעלה בצמתים הזמינים. כברירת מחדל, אי אפשר לקבוע באיזה צומת פועל ה-Pod, ולכן לPods אין כתובות IP יציבות.כדי לקבל כתובת IP עבור
server, צריך להגדיר הפשטה של הרשת מעל קבוצות ה-Pod, שנקראת Kubernetes Service. שירות Kubernetes מספק נקודת קצה יציבה ברשת עבור קבוצה של קובצי Pod. יש כמה סוגים של שירותים. serverמשתמש ב-LoadBalancer, שחושף כתובת IP חיצונית כדי שתוכלו להגיע אלserverמחוץ לאשכול.ל-Kubernetes יש גם מערכת DNS מובנית, שמקצה שמות DNS (לדוגמה,
helloserver.default.cluster.local) לשירותים. כך אפשר ל-Pods בתוך האשכול להגיע ל-Pods אחרים באשכול עם כתובת יציבה. אי אפשר להשתמש בשם ה-DNS הזה מחוץ לאשכול, למשל מ-Cloud Shell.
מניפסטים של Kubernetes
כשמריצים את האפליקציה מקוד המקור, משתמשים בפקודה אימפרטיבית: python3 server.py
ציווי הוא פועל שמוביל את המשפט: "תעשה את זה".
לעומת זאת, Kubernetes פועל לפי מודל הצהרתי. כלומר, במקום להגיד ל-Kubernetes בדיוק מה לעשות, אתם מספקים ל-Kubernetes מצב רצוי. לדוגמה, Kubernetes מפעיל ומפסיק את ה-Pods לפי הצורך, כך שמצב המערכת בפועל תואם למצב הרצוי.
מציינים את המצב הרצוי בקבוצה של מניפסטים או בקובצי YAML. קובץ YAML מכיל את המפרט של אובייקט Kubernetes אחד או יותר.
הדוגמה מכילה קובץ YAML עבור server ו-loadgen. כל קובץ YAML מציין את המצב הרצוי של אובייקט הפריסה והשירות של Kubernetes.
שרת
-
kindמציין את סוג האובייקט. -
metadata.nameמציין את השם של הפריסה. - השדה הראשון
specמכיל תיאור של המצב הרצוי. -
spec.replicasמציין את מספר ה-Pods הרצוי. - בקטע
spec.templateמוגדרת תבנית של Pod. השדהimageנכלל במפרט של ה-Pods, והוא השם של האימג' שצריך לשלוף מ-Container Registry.
השירות מוגדר כך:
-
LoadBalancer: לקוחות שולחים בקשות לכתובת ה-IP של מאזן עומסים ברשת, שיש לו כתובת IP יציבה שאפשר להגיע אליה מחוץ לאשכול. -
targetPort: חשוב לזכור שהפקודהEXPOSE 8080ב-Dockerfileלא חושפת אף יציאה. אתם חושפים את הפורט8080כדי שתוכלו להגיע למאגרserverמחוץ לאשכול. במקרה הזה,hellosvc.default.cluster.local:80(שם קצר:hellosvc) ממופה ליציאה8080של כתובת ה-IP של ה-Podhelloserver. port: מספר היציאה ששירותים אחרים באשכול משתמשים בו כששולחים בקשות.
מחולל עומסים
אובייקט הפריסה ב-loadgen.yaml דומה ל-server.yaml. הבדל בולט אחד הוא שאובייקט הפריסה מכיל קטע שנקרא env. בקטע הזה מוגדרים משתני הסביבה שנדרשים ל-loadgen, שהגדרתם קודם כשביצעתם את האפליקציה מהמקור.
מכיוון ש-loadgen לא מקבל בקשות נכנסות, השדה type מוגדר ל-ClusterIP. הסוג הזה מספק כתובת IP יציבה ששירותים באשכול יכולים להשתמש בה, אבל כתובת ה-IP לא חשופה ללקוחות חיצוניים.
פריסת הקונטיינרים ב-GKE
עוברים לספרייה שבה נמצאת הדוגמה
server:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
פותחים את
server.yamlבכלי לעריכת טקסט.מחליפים את השם בשדה
imageבשם של קובץ אימג' של Docker.image: gcr.io/PROJECT_ID/asm-ready/helloserver:v0.0.1
מחליפים את
PROJECT_IDבמזהה הפרויקט ב- Google Cloud .שמירה וסגירה
server.yaml.פורסים את קובץ ה-YAML ב-Kubernetes:
kubectl apply -f server.yamlאם הפקודה מצליחה, היא מחזירה את התגובה הבאה:
deployment.apps/helloserver created service/hellosvc created
עוברים לספרייה שבה נמצא
loadgen.cd ../loadgenפותחים את
loadgen.yamlבכלי לעריכת טקסט.מחליפים את השם בשדה
imageבשם של קובץ אימג' של Docker.image: gcr.io/PROJECT_ID/asm-ready/loadgen:v0.0.1
מחליפים את
PROJECT_IDבמזהה הפרויקט ב- Google Cloud .שומרים וסוגרים את הקובץ
loadgen.yamlוסוגרים את הכלי לעריכת טקסט.פורסים את קובץ ה-YAML ב-Kubernetes:
kubectl apply -f loadgen.yamlאם הפקודה מצליחה, היא מחזירה את התגובה הבאה:
deployment.apps/loadgenerator created service/loadgensvc created
בודקים את הסטטוס של ה-Pods:
kubectl get podsהתגובה של הפקודה תכלול סטטוס שדומה לזה:
NAME READY STATUS RESTARTS AGE helloserver-69b9576d96-mwtcj 1/1 Running 0 58s loadgenerator-774dbc46fb-gpbrz 1/1 Running 0 57s
מקבלים את יומני האפליקציה מ-Pod
loadgen. מחליפים אתPOD_IDבמזהה מהפלט הקודם.kubectl logs loadgenerator-POD_ID
קבלת כתובות ה-IP החיצוניות של
hellosvc:kubectl get serviceהתגובה של הפקודה אמורה להיראות כך:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hellosvc LoadBalancer 10.81.15.158 192.0.2.1 80:31127/TCP 33m kubernetes ClusterIP 10.81.0.1 <none> 443/TCP 93m loadgensvc ClusterIP 10.81.15.155 <none> 80/TCP 4m52s
שליחת בקשה אל
hellosvc. מחליפים אתEXTERNAL_IPבכתובת ה-IP החיצונית שלhellosvc.curl http://EXTERNAL_IP
מוכן ל-Cloud Service Mesh
עכשיו האפליקציה פרוסה ב-GKE. loadgen
יכול להשתמש ב-DNS של Kubernetes (hellosvc:80) כדי לשלוח בקשות אלserver, ואפשר לשלוח בקשות אל server עם כתובת IP חיצונית. למרות ש-Kubernetes מספקת לכם תכונות רבות, חסר מידע מסוים על השירותים:
- איך השירותים פועלים יחד? מה הקשר בין השירותים? איך התעבורה זורמת בין השירותים? אתם יודעים ש-
loadgenשולח בקשות אלserver, אבל נניח שאתם לא מכירים את האפליקציה. אי אפשר לענות על השאלות האלה על סמך רשימת ה-Pods הפועלים ב-GKE. - מדדים: כמה זמן לוקח ל-
serverלהגיב לבקשות נכנסות? כמה בקשות בשנייה (RPS) נכנסות אלserver? האם יש תשובות שגיאה? - פרטי אבטחה: האם התנועה בין
loadgenלביןserverהיא רגילהHTTPאו mTLS?
בעזרת Cloud Service Mesh אפשר לקבל תשובות לשאלות האלה. Cloud Service Mesh היא גרסה מנוהלת של פרויקט הקוד הפתוח Istio. Google CloudCloud Service Mesh פועל באמצעות הצבת פרוקסי מסוג Envoy מסוג sidecar בכל Pod. שרת ה-proxy של Envoy מיירט את כל התנועה הנכנסת והיוצאת לקונטיינרים של האפליקציה. המשמעות היא שגם server וגם loadgen מקבלים פרוקסי מסוג Envoy קובץ עזר חיצוני, וכל התנועה מ-loadgen אל server מתווכת על ידי פרוקסי Envoy. הקשרים בין שרתי ה-proxy של Envoy יוצרים את Service mesh. ארכיטקטורת ה-service mesh הזו מספקת שכבת בקרה מעל Kubernetes.
מכיוון ששרתי ה-proxy של Envoy פועלים בקונטיינרים משלהם, אתם יכולים להתקין את Cloud Service Mesh על אשכול GKE בלי לבצע שינויים משמעותיים בקוד האפליקציה. עם זאת, יש כמה דרכים עיקריות שבהן הכנתם את האפליקציה להטמעה של Cloud Service Mesh:
- שירותים לכל מאגרי התגים: גם לפריסות של
serverוגם לפריסות שלloadgenמצורף שירות Kubernetes. גם ל-loadgen, שלא מקבל בקשות נכנסות, יש שירות. - צריך לתת שם ליציאות בשירותים: למרות ש-GKE מאפשר להגדיר יציאות שירות ללא שם, ב-Cloud Service Mesh צריך לספק שם ליציאה שתואם לפרוטוקול של היציאה. בקובץ ה-YAML, היציאה של
serverנקראתhttpכיserverמשתמש בפרוטוקול התקשורתHTTP. אם השתמשתם ב-service, תצטרכו לתת ליציאה את השםgrpc.gRPC - פריסות מסומנות בתוויות: כך אפשר להשתמש בתכונות של Cloud Service Mesh לניהול תעבורה, כמו פיצול תעבורה בין גרסאות של אותו שירות.
התקנה של Cloud Service Mesh
נכנסים אל מדריך ההתקנה של Cloud Service Mesh ופועלים לפי ההוראות כדי להתקין את Cloud Service Mesh באשכול.
הסרת המשאבים
כדי לא לצבור חיובים לחשבון Google Cloud על המשאבים שבהם השתמשתם במדריך הזה, אתם יכולים למחוק את הפרויקט שמכיל את המשאבים או להשאיר את הפרויקט ולמחוק את המשאבים בנפרד.
כדי לנקות, מוחקים את אשכול GKE. מחיקת האשכול מוחקת את כל המשאבים שמרכיבים את אשכול הקונטיינר, כמו מופעי המחשוב, הדיסקים ומשאבי הרשת.
gcloud container clusters delete asm-ready
המאמרים הבאים
מידע נוסף על הטכנולוגיות שבהן נעשה שימוש במדריך הזה:
מידע נוסף על הכלים:
מידע נוסף על מושגים ב-Kubernetes: