הגדרת רשת מרובת אשכולות ב-Cloud Service Mesh מנוהל
במדריך הזה מוסבר איך לצרף שני אשכולות ל-Cloud Service Mesh יחיד באמצעות Mesh CA או Certificate Authority Service, ואיך להפעיל איזון עומסים בין אשכולות. אפשר להרחיב את התהליך הזה בקלות כדי לכלול מספר כלשהו של אשכולות ברשת.
הגדרה של Cloud Service Mesh מרובה אשכולות יכולה לפתור כמה תרחישים חשובים בארגונים, כמו קנה מידה, מיקום ובידוד. מידע נוסף מופיע במאמר תרחישי שימוש בריבוי אשכולות.
דרישות מוקדמות
במדריך הזה אנחנו יוצאים מנקודת הנחה שיש לכם שני אשכולות GKE או יותר Google Cloud שעומדים בדרישות הבאות:
- Cloud Service Mesh מותקן באשכולות. צריך את
asmcli, את הכליistioctlודוגמאות ש-asmcliמוריד לספרייה שציינתם ב---output_dir. - לפני שמגדירים את Cloud Service Mesh, צריך לוודא שיש קישוריות בין כל הפודים באשכול. בנוסף, אם מצטרפים לאשכולות שלא נמצאים באותו פרויקט, הם צריכים להיות רשומים באותו פרויקט מארח של Fleet, והאשכולות צריכים להיות ביחד באותה רשת בתצורת VPC משותף. מומלץ גם להשתמש בפרויקט אחד לאירוח ה-VPC המשותף, ובשני פרויקטים של שירותים ליצירת אשכולות. מידע נוסף זמין במאמר בנושא הגדרת אשכולות עם VPC משותף.
- אם משתמשים ב-Certificate Authority Service, כל האשכולות צריכים להיות מקושרים לשרשרת של מאגרי רשות אישורים משניים לאותו מאגר רשות אישורים בסיסי. אחרת, כולם יצטרכו להשתמש באותו מאגר של רשויות אישורים.
הגדרת משתנים של פרויקט ושל אשכול
יוצרים את משתני הסביבה הבאים עבור מזהה הפרויקט, האזור או האזור של האשכול, שם האשכול וההקשר.
export PROJECT_1=PROJECT_ID_1 export LOCATION_1=CLUSTER_LOCATION_1 export CLUSTER_1=CLUSTER_NAME_1 export CTX_1="gke_${PROJECT_1}_${LOCATION_1}_${CLUSTER_1}" export PROJECT_2=PROJECT_ID_2 export LOCATION_2=CLUSTER_LOCATION_2 export CLUSTER_2=CLUSTER_NAME_2 export CTX_2="gke_${PROJECT_2}_${LOCATION_2}_${CLUSTER_2}"אם אלה אשכולות שנוצרו לאחרונה, חשוב לאחזר את פרטי הכניסה לכל אשכול באמצעות הפקודות הבאות
gcloud, אחרת לא יהיה אפשר להשתמש ב-contextשמשויך אליהם בשלבים הבאים של המדריך הזה.הפקודות משתנות בהתאם לסוג האשכול, אזורי או אזורי.
אזורי
gcloud container clusters get-credentials ${CLUSTER_1} --region ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --region ${LOCATION_2}אזורי
gcloud container clusters get-credentials ${CLUSTER_1} --zone ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --zone ${LOCATION_2}
יצירת כלל לחומת האש
במקרים מסוימים, צריך ליצור כלל בחומת האש כדי לאפשר תעבורת נתונים בין אשכולות. לדוגמה, צריך ליצור כלל לחומת האש אם:
- משתמשים ברשתות משנה שונות עבור האשכולות ברשת ה-mesh.
- ה-Pods פותחים יציאות אחרות מלבד 443 ו-15002.
מערכת GKE מוסיפה אוטומטית כללי חומת אש לכל צומת כדי לאפשר תעבורת נתונים באותה רשת משנה. אם הרשת שלכם מכילה כמה רשתות משנה, אתם צריכים להגדיר במפורש את כללי חומת האש כדי לאפשר תנועה בין רשתות משנה. צריך להוסיף כלל חומת אש חדש לכל רשת משנה כדי לאפשר את בלוקי CIDR של כתובות ה-IP של המקור ואת יציאות היעד של כל תעבורת הנתונים הנכנסת.
ההוראות הבאות מאפשרות תקשורת בין כל האשכולות בפרויקט או רק בין $CLUSTER_1 לבין $CLUSTER_2.
אוספים מידע על הרשת של האשכולות.
כל האשכולות בפרויקט
אם האשכולות נמצאים באותו פרויקט, אפשר להשתמש בפקודה הבאה כדי לאפשר תקשורת בין כל האשכולות בפרויקט. אם יש אשכולות בפרויקט שאתם לא רוצים לחשוף, אתם יכולים להשתמש בפקודה שבכרטיסייה Specific clusters (אשכולות ספציפיים).
function join_by { local IFS="$1"; shift; echo "$*"; } ALL_CLUSTER_CIDRS=$(gcloud container clusters list --project $PROJECT_1 --format='value(clusterIpv4Cidr)' | sort | uniq) ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}")) ALL_CLUSTER_NETTAGS=$(gcloud compute instances list --project $PROJECT_1 --format='value(tags.items.[0])' | sort | uniq) ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))אשכולות ספציפיים
הפקודה הבאה מאפשרת תקשורת בין
$CLUSTER_1לבין$CLUSTER_2, ולא חושפת אשכולות אחרים בפרויקט.function join_by { local IFS="$1"; shift; echo "$*"; } ALL_CLUSTER_CIDRS=$(for P in $PROJECT_1 $PROJECT_2; do gcloud --project $P container clusters list --filter="name:($CLUSTER_1,$CLUSTER_2)" --format='value(clusterIpv4Cidr)'; done | sort | uniq) ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}")) ALL_CLUSTER_NETTAGS=$(for P in $PROJECT_1 $PROJECT_2; do gcloud --project $P compute instances list --filter="name:($CLUSTER_1,$CLUSTER_2)" --format='value(tags.items.[0])' ; done | sort | uniq) ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))יוצרים את הכלל לחומת האש.
GKE
gcloud compute firewall-rules create istio-multicluster-pods \ --allow=tcp,udp,icmp,esp,ah,sctp \ --direction=INGRESS \ --priority=900 \ --source-ranges="${ALL_CLUSTER_CIDRS}" \ --target-tags="${ALL_CLUSTER_NETTAGS}" --quiet \ --network=YOUR_NETWORKטייס אוטומטי
TAGS="" for CLUSTER in ${CLUSTER_1} ${CLUSTER_2} do TAGS+=$(gcloud compute firewall-rules list --filter="Name:$CLUSTER*" --format="value(targetTags)" | uniq) && TAGS+="," done TAGS=${TAGS::-1} echo "Network tags for pod ranges are $TAGS" gcloud compute firewall-rules create asm-multicluster-pods \ --allow=tcp,udp,icmp,esp,ah,sctp \ --network=gke-cluster-vpc \ --direction=INGRESS \ --priority=900 --network=VPC_NAME \ --source-ranges="${ALL_CLUSTER_CIDRS}" \ --target-tags=$TAGS
הגדרת גילוי נקודות קצה
הפעלת גילוי נקודות קצה בין אשכולות ציבוריים או פרטיים באמצעות API הצהרתי
הפעלת Cloud Service Mesh מנוהל באמצעות Fleet API תאפשר גילוי נקודות קצה באשכול הזה. אם הקצאתם Cloud Service Mesh מנוהל באמצעות כלי אחר, תוכלו להפעיל ידנית איתור של נקודות קצה באשכולות ציבוריים או פרטיים בצי על ידי החלת ההגדרה "multicluster_mode":"connected" ב-configmap asm-options. בצבי קלאסטרים שבהם ההגדרה הזו מופעלת באותו צי, גילוי שירותים בין קלאסטרים מופעל אוטומטית בין כל הקלאסטרים.
זו הדרך היחידה להגדיר גילוי של נקודות קצה מרובות אשכולות אם יש לכם הטמעה של מישור בקרה מנוהל (TD), והדרך המומלצת להגדיר אותה אם יש לכם הטמעה מנוהלת (Istiod).
לפני שממשיכים, צריך ליצור כלל לחומת האש.
הפעלה
אם asm-options configmap כבר קיים באשכול, צריך להפעיל את גילוי נקודות הקצה באשכול:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"connected"}}'
אם asm-options configmap עדיין לא קיים באשכול, צריך ליצור אותו עם הנתונים המשויכים ולהפעיל את איתור נקודות הקצה באשכול:
kubectl --context ${CTX_1} create configmap asm-options -n istio-system --from-file <(echo '{"data":{"multicluster_mode":"connected"}}')
השבתה
כדי להשבית את גילוי נקודות הקצה באשכול:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"manual"}}'
אם מבטלים את הרישום של אשכול ב-Fleet בלי להשבית את איתור נקודות הקצה, יכול להיות שסודות יישארו באשכול. צריך לנקות באופן ידני את כל הסודות שנותרו.
מריצים את הפקודה הבאה כדי למצוא סודות שצריך להסיר:
kubectl get secrets -n istio-system -l istio.io/owned-by=mesh.googleapis.com,istio/multiCluster=trueמחיקת כל סוד:
kubectl delete secret SECRET_NAMEחוזרים על השלב הזה לכל סוד שנותר.
אימות הקישוריות בין כמה אשכולות
בקטע הזה מוסבר איך לפרוס את שירותי הדוגמה HelloWorld ו-Sleep בסביבה מרובת אשכולות כדי לוודא שאיזון העומסים בין האשכולות פועל.
הגדרת משתנה לספריית הדוגמאות
עוברים למיקום שבו
asmcliהורד, ומריצים את הפקודה הבאה כדי להגדיר אתASM_VERSIONexport ASM_VERSION="$(./asmcli --version)"מגדירים תיקייה פעילה לדוגמאות שבהן משתמשים כדי לוודא שאיזון העומסים בין אשכולות פועל. הדוגמאות ממוקמות בספריית משנה בספרייה
--output_dirשציינתם בפקודהasmcli install. בפקודה הבאה, משנים אתOUTPUT_DIRלספרייה שציינתם ב---output_dir.export SAMPLES_DIR=OUTPUT_DIR/istio-${ASM_VERSION%+*}
הפעלת הזרקה של sidecar
יוצרים את מרחב השמות לדוגמה בכל אשכול.
for CTX in ${CTX_1} ${CTX_2} do kubectl create --context=${CTX} namespace sample doneמפעילים את מרחב השמות להחדרה. השלבים תלויים בהטמעה של מישור הבקרה.
מנוהל (TD)
- מחילים את תווית ההזרקה שמוגדרת כברירת מחדל על מרחב השמות:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio.io/rev- istio-injection=enabled --overwrite doneמנוהל (Istiod)
מומלץ: מריצים את הפקודה הבאה כדי להחיל את תווית ברירת המחדל של הזרקה על מרחב השמות:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio.io/rev- istio-injection=enabled --overwrite doneאם אתם משתמשים קיימים במישור הבקרה המנוהל של Istiod: מומלץ להשתמש בהזרקה שמוגדרת כברירת מחדל, אבל יש תמיכה גם בהזרקה מבוססת-עדכון. פועלים לפי ההוראות הבאות:
מריצים את הפקודה הבאה כדי לאתר את ערוצי ההפצה הזמינים:
kubectl -n istio-system get controlplanerevisionהפלט אמור להיראות כך:
NAME AGE asm-managed-rapid 6d7hבפלט, הערך בעמודה
NAMEהוא תווית הגרסה שתואמת לערוץ ההפצה שזמין לגרסה של Cloud Service Mesh.החלת תווית הגרסה על מרחב השמות:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio-injection- istio.io/rev=REVISION_LABEL --overwrite done
התקנת השירות HelloWorld
יוצרים את השירות HelloWorld בשני האשכולות:
kubectl create --context=${CTX_1} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l service=helloworld -n samplekubectl create --context=${CTX_2} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l service=helloworld -n sample
פריסת HelloWorld v1 ו-v2 לכל אשכול
פריסת
HelloWorld v1אלCLUSTER_1ופריסתv2אלCLUSTER_2, מה שיעזור בהמשך לאמת את איזון העומסים בין האשכולות:kubectl create --context=${CTX_1} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l version=v1 -n samplekubectl create --context=${CTX_2} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l version=v2 -n sampleמריצים את הפקודות הבאות כדי לוודא ש-
HelloWorld v1ו-v2פועלים. מוודאים שהפלט דומה לזה שמוצג.:kubectl get pod --context=${CTX_1} -n sampleNAME READY STATUS RESTARTS AGE helloworld-v1-86f77cd7bd-cpxhv 2/2 Running 0 40s
kubectl get pod --context=${CTX_2} -n sampleNAME READY STATUS RESTARTS AGE helloworld-v2-758dd55874-6x4t8 2/2 Running 0 40s
פריסת שירות השינה
פורסים את שירות
Sleepבשני האשכולות. ה-Pod הזה יוצר תנועת רשת מלאכותית למטרות הדגמה:for CTX in ${CTX_1} ${CTX_2} do kubectl apply --context=${CTX} \ -f ${SAMPLES_DIR}/samples/sleep/sleep.yaml -n sample doneממתינים עד שהשירות
Sleepיופעל בכל אשכול. מוודאים שהפלט דומה לזה שמוצג:kubectl get pod --context=${CTX_1} -n sample -l app=sleepNAME READY STATUS RESTARTS AGE sleep-754684654f-n6bzf 2/2 Running 0 5s
kubectl get pod --context=${CTX_2} -n sample -l app=sleepNAME READY STATUS RESTARTS AGE sleep-754684654f-dzl9j 2/2 Running 0 5s
אימות איזון עומסים בין אשכולות
מתקשרים לשירות HelloWorld כמה פעמים ובודקים את הפלט כדי לוודא שמתקבלות תשובות מתחלפות מגרסה 1 ומגרסה 2:
מתקשרים לשירות
HelloWorld:kubectl exec --context="${CTX_1}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_1}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'הפלט אמור להיראות כך:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
מתקשרים שוב לשירות
HelloWorld:kubectl exec --context="${CTX_2}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_2}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'הפלט אמור להיראות כך:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
האימות של Cloud Service Mesh עם איזון עומסים ומרובה אשכולות הסתיים בהצלחה.
שמירה על תנועה בתוך האשכול
במקרים מסוימים, התנהגות ברירת המחדל של איזון העומסים בין אשכולות לא רצויה. כדי שתעבורת הנתונים תישאר 'מקומיות לאשכול' (כלומר, תעבורת נתונים שנשלחת מ-cluster-a תגיע רק ליעדים ב-cluster-a), צריך לסמן שמות מארחים או תווים כלליים כ-clusterLocal באמצעות MeshConfig.serviceSettings.
לדוגמה, אפשר לאכוף תנועה מקומית באשכול לשירות ספציפי, לכל השירותים במרחב שמות מסוים או באופן גלובלי לכל השירותים ברשת, באופן הבא:
לכל שירות
serviceSettings:
- settings:
clusterLocal: true
hosts:
- "mysvc.myns.svc.cluster.local"
לכל מרחב שמות
serviceSettings:
- settings:
clusterLocal: true
hosts:
- "*.myns.svc.cluster.local"
גלובלי
serviceSettings:
- settings:
clusterLocal: true
hosts:
- "*"
אפשר גם לשפר את הגישה לשירות על ידי הגדרת כלל גלובלי מקומי לאשכול והוספה של חריגים מפורשים, שיכולים להיות ספציפיים או כלליים. בדוגמה הבאה, כל השירותים באשכול יישארו מקומיים לאשכול, למעט שירותים במרחב השמות myns:
serviceSettings:
- settings:
clusterLocal: true
hosts:
- "*"
- settings:
clusterLocal: false
hosts:
- "*.myns.svc.cluster.local"
הפעלת שירות האשכול המקומי
בדיקה של מפת התצורה MeshConfig באשכול
kubectl get configmap -n istio-systemאמור להופיע מיפוי הגדרות עם אחד מהשמות
istio-asm-managed,istio-asm-managed-rapidאוistio-asm-managed-stable.אם עברתם מהטמעה של
ISTIODלהטמעה שלTRAFFIC_DIRECTOR, יכול להיות שיוצגו לכם יותר ממפת תצורה אחת. במקרה כזה, אפשר להריץ את הפקודה הבאה כדי לזהות את הערוץ:kubectl get controlplanerevision -n istio-systemהערוץ של הגרסה המתוקנת של מישור הבקרה הוא הערוץ שצריך לבחור.
עדכון מפת התצורה
cat <<EOF > config.yaml apiVersion: v1 kind: ConfigMap metadata: name: CONFIGMAP_NAME namespace: istio-system data: mesh: |- serviceSettings: - settings: clusterLocal: true hosts: - "*" EOFמחליפים את
CONFIGMAP_NAMEבשם של Config Map שמצאתם בשלב 1 ומעדכנים את Config Map.kubectl apply --context=${CTX_1} -f config.yamlמריצים את הפקודות הבאות כדי לוודא שהתכונה Local Cluster פועלת כצפוי. הפלט של קריאה ל-
HelloWorldעםCTX_1אמור להיראות כך:kubectl exec --context="${CTX_1}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_1}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'הפלט צריך להכיל את המחרוזת Only v1 is response:
Hello version: v1, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...אם מתקשרים אל
HelloWorldבאמצעותCTX_2:kubectl exec --context="${CTX_2}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_2}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'בפלט אמורות להופיע תשובות לסירוגין מגרסה 1 ומגרסה 2.
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
ניקוי שירות HelloWorld
אחרי שמסיימים לאמת את איזון העומסים, מסירים את שירות HelloWorld ואת שירות Sleep מהאשכול.
kubectl delete ns sample --context ${CTX_1}
kubectl delete ns sample --context ${CTX_2}