במדריך הזה נסביר איך להעביר אפליקציה שנוצרה לצמתים באמצעות מעבד x86 (Intel או AMD) באשכול Google Kubernetes Engine (GKE) לאפליקציה מרובת-ארכיטקטורות (multi-arch) שפועלת בצמתי x86 או Arm. קהל היעד של המדריך הזה הוא מנהלי פלטפורמות, מפעילים של אפליקציות ומפתחי אפליקציות שרוצים להריץ את עומסי העבודה הקיימים שלהם שתואמים ל-x86 ב-Arm.
באמצעות אשכולות GKE, אתם יכולים להריץ עומסי עבודה בצמתים של Arm באמצעות סדרות המכונות C4A, N4A או Tau T2A. במדריך הזה נעשה שימוש בצמתים מסוג C4A, שבדומה לצמתים מסוג N4A ו-T2A, יכולים לפעול באשכול GKE שלכם בדיוק כמו כל צומת אחר באמצעות מעבדי x86 (Intel או AMD). צמתים מסוג C4A מספקים ביצועים גבוהים באופן עקבי לעומסי העבודה שלכם על בסיס Arm.
מידע נוסף זמין במאמר בנושא עומסי עבודה של Arm ב-GKE.
ההנחה היא שאתם מכירים את Kubernetes ואת Docker. במדריך הזה נעשה שימוש ב-Google Kubernetes Engine וב-Artifact Registry.
מטרות
במדריך הזה תבצעו את המשימות הבאות:
- אחסון תמונות של קונטיינרים באמצעות Docker ב-Artifact Registry.
- פריסת עומס עבודה (workload) שתואם ל-x86 באשכול GKE.
- בונים מחדש עומס עבודה שתואם ל-x86 כדי להריץ אותו ב-Arm.
- הוספת מאגר צמתים של Arm לאשכול קיים.
- פריסת עומס עבודה שתואם ל-Arm להרצה בצומת Arm.
- יצירת תמונה מרובת ארכיטקטורות להרצת עומס עבודה בכמה ארכיטקטורות.
- הפעלת עומסי עבודה בכמה ארכיטקטורות באשכול GKE אחד.
עלויות
במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:
כדי להעריך את ההוצאות בהתאם לתחזית השימוש שלכם, אתם יכולים להיעזר במחשבון העלויות.
כשמסיימים את המשימות שמתוארות במסמך הזה אפשר למחוק את המשאבים שיצרתם כדי להימנע מחיובים נוספים. מידע נוסף זמין בקטע הסרת המשאבים.
לפני שמתחילים
כדי להפעיל את Kubernetes Engine API, מבצעים את השלבים הבאים:- נכנסים לחשבון Google Cloud . אם אתם משתמשים חדשים ב- Google Cloud, צרו חשבון כדי שתוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
-
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.
Enable the Artifact Registry and Google Kubernetes Engine APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.-
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.
Enable the Artifact Registry and Google Kubernetes Engine APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.
כדי להימנע מחיובים נוספים אחרי שסיימתם את המדריך, תוכלו למחוק את המשאבים שיצרתם. פרטים נוספים מופיעים במאמר בנושא הסרת המשאבים.
הפעלת Cloud Shell
במדריך הזה תשתמשו ב-Cloud Shell, שהיא סביבת מעטפת לניהול משאבים שמתארחים ב-Google Cloud.
ב-Cloud Shell מותקנים מראש Google Cloud CLI וכלי שורת הפקודה kubectl. ה-CLI של gcloud הוא ממשק שורת הפקודה העיקרי ל- Google Cloud, ו-kubectl הוא ממשק שורת הפקודה העיקרי להרצת פקודות מול אשכולות Kubernetes.
מפעילים את Cloud Shell:
נכנסים למסוף Google Cloud .
לוחצים על Activate Cloud Shell
בפינה הימנית העליונה של המסוף.
סשן של Cloud Shell יופיע בתוך המסוף.
משתמשים בשורת הפקודה הזו כדי להריץ פקודות gcloud ו-kubectl.
הכנת הסביבה
בקטע הזה מוסבר איך להכין את הסביבה כדי לפעול לפי ההוראות במדריך.
הגדרת ברירת המחדל של ה-CLI של gcloud
מגדירים משתני סביבה למזהה הפרויקט, למיקום של Compute Engine עבור האשכול ולשם האשכול החדש.
export PROJECT_ID=PROJECT_ID
export CONTROL_PLANE_LOCATION=us-central1-a
export CLUSTER_NAME=my-cluster
מחליפים את PROJECT_ID במזהה הפרויקט שבחרתם למדריך הזה בקטע לפני שמתחילים.
במדריך הזה, תיצרו משאבים ב-us-central1-a. כדי לראות רשימה מלאה של המקומות שבהם סדרת המכונות C4A זמינה, אפשר לעיין במאמר בנושא אזורים ותחומים זמינים.
שכפול מאגר Git
משכפלים את המאגר:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samplesמעבירים את ספריית העבודה הנוכחית למאגר ששוכפל בשלב הקודם:
cd kubernetes-engine-samples/workloads/migrate-x86-app-to-multi-arch/המאגר הזה מכיל את הקבצים שדרושים לכם כדי להשלים את ההדרכה הזו. בהדרכה הזו נעשה שימוש בפריסות של Kubernetes. פריסה היא אובייקט Kubernetes API שמאפשר להפעיל כמה רפליקות של Pods שמפוזרות בין הצמתים באשכול.
יצירת אשכול GKE ופריסת אפליקציית x86
בחלק הראשון של המדריך הזה, יוצרים אשכול עם צמתי x86 ופורסים אפליקציית x86. אפליקציית הדוגמה היא שירות שמגיב לבקשות HTTP. היא בנויה בשפת התכנות Golang.
ההגדרה הזו מייצגת את מה שעשוי להיות בסביבת אשכול טיפוסית, באמצעות אפליקציות שתואמות ל-x86 וצמתים של x86.
יצירת אשכול GKE
קודם כל, יוצרים GKE באמצעות צמתים עם מעבדי x86. בעזרת ההגדרה הזו, יוצרים סביבת אשכול טיפוסית להפעלת אפליקציות x86.
יוצרים את האשכול:
gcloud container clusters create $CLUSTER_NAME \
--release-channel=rapid \
--location=$CONTROL_PLANE_LOCATION \
--machine-type=e2-standard-2 \
--num-nodes=1 \
--async
השבתנו את ההתאמה האוטומטית לעומס של האשכול הזה כדי להדגים פונקציונליות ספציפית בשלבים מאוחרים יותר.
יצירת האשכול עשויה להימשך כמה דקות. הדגל --async מאפשר להפעיל את הפעולה הזו ברקע בזמן שאתם מבצעים את השלבים הבאים.
אפשר ליצור אשכולות עם צמתי Arm בלבד, אבל במדריך הזה קודם ניצור אשכול עם צמתי x86 בלבד כדי ללמוד על התהליך של התאמת אפליקציות x86 בלבד ל-Arm.
יצירת מאגר Docker ב-Artifact Registry
יוצרים מאגר ב-Artifact Registry לאחסון קובצי אימג' של Docker:
gcloud artifacts repositories create docker-repo \ --repository-format=docker \ --location=us-central1 \ --description="Docker repository"מגדירים את כלי שורת הפקודה של Docker לאימות למאגר הזה ב-Artifact Registry:
gcloud auth configure-docker us-central1-docker.pkg.dev
יצירת תמונת x86 והעברה שלה בדחיפה ל-Artifact Registry
מבצעים build של גרסה של האפליקציה שתואמת ל-x86:
docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1 .מעבירים את האימג' ל-Artifact Registry:
docker push us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1
פריסת אפליקציית x86
מריצים את הסקריפט הבא כדי לוודא שהאשכול מוכן:
echo echo -ne "Waiting for GKE cluster to finish provisioning" gke_status="" while [ -z $gke_status ]; do sleep 2 echo -ne '.' gke_status=$(gcloud container clusters list --format="value(STATUS)" --filter="NAME=$CLUSTER_NAME AND STATUS=RUNNING") done echo echo "GKE Cluster '$CLUSTER_NAME' is $gke_status" echoכשהאשכול מוכן, הפלט אמור להיראות כך:
GKE Cluster 'my-cluster' is RUNNINGמאחזרים את פרטי הכניסה של האשכול כדי ש-
kubectlיוכל להתחבר ל-Kubernetes API של האשכול:gcloud container clusters get-credentials $CLUSTER_NAME --location $CONTROL_PLANE_LOCATION --project $PROJECT_IDמעדכנים את התמונה באמצעות kustomize ומפעילים את אפליקציית x86:
$(cd k8s/overlays/x86 && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1) kubectl apply -k k8s/overlays/x86פריסת שירות כדי לחשוף את האפליקציה לאינטרנט:
kubectl apply -f k8s/hello-service.yamlבודקים שהקצאת כתובת ה-IP החיצונית לשירות,
hello-service, הסתיימה:echo echo -ne "Waiting for External IP to be provisioned" external_ip="" while [ -z $external_ip ]; do sleep 2 echo -ne '.' external_ip=$(kubectl get svc hello-service --template="{{range .status.loadBalancer.ingress}}{{.ip}}{{end}}") done echo echo "External IP: $external_ip" echoאחרי הקצאת כתובת ה-IP החיצונית, הפלט אמור להיראות כך:
External IP: 203.0.113.0שולחים בקשת HTTP כדי לבדוק שהפריסה פועלת כמצופה:
curl -w '\n' http://$external_ipהפלט אמור להיראות כך:
Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64הפלט מראה שהפריסה הזו שתואמת ל-x86 פועלת בצומת במאגר הצמתים שמוגדר כברירת מחדל בארכיטקטורה
amd64. לצמתים במאגר הצמתים שמוגדר כברירת מחדל באשכול יש מעבדי x86 (Intel או AMD).
הוספת צמתי Arm לאשכול
בחלק הבא של המדריך הזה, תוסיפו צמתים של Arm לאשכול הקיים. הצמתים האלה הם המקום שבו הגרסה של האפליקציה שתואמת ל-Arm נפרסת כשהיא נבנית מחדש כדי לפעול ב-Arm.
נקודת ביקורת
עד עכשיו השגת את המטרות הבאות:
- ליצור אשכול GKE באמצעות צמתים מסוג x86.
- לאחסן קובץ אימג' של קונטיינר שתואם ל-x86 באמצעות Docker ב-Artifact Registry.
- לפרוס עומס עבודה שתואם ל-x86 באשכול GKE.
הגדרתם סביבת אשכול עם צמתים מסוג x86 ועומס עבודה שתואם ל-x86. ההגדרה הזו דומה לסביבות האשכולות הקיימות שלכם אם אתם לא משתמשים כרגע בצמתי Arm ובעומסי עבודה שתואמים ל-Arm.
הוספת מאגר צמתים של Arm לאשכול
כדי להוסיף מאגר צמתים של Arm לאשכול קיים:
gcloud container node-pools create arm-pool \
--cluster $CLUSTER_NAME \
--location $CONTROL_PLANE_LOCATION \
--machine-type=c4a-standard-2 \
--num-nodes=1
סוג המכונה c4a-standard-2 הוא מכונת Arm VM מסדרת המכונות C4A.
תהליך יצירת מאגר צמתים עם צמתי Arm זהה לתהליך יצירת מאגר צמתים עם צמתי x86. אחרי שיוצרים את מאגר הצמתים הזה, פועלים באותו אשכול גם צמתי x86 וגם צמתי Arm.
מידע נוסף על הוספת מאגרי צמתים של Arm לאשכולות קיימים זמין במאמר הוספת מאגר צמתים של Arm לאשכול GKE.
הגדלת הקיבולת של האפליקציה הקיימת שפועלת בצמתים מבוססי x86
צמתים מסוגי ארכיטקטורה שונים יכולים לפעול יחד בצורה חלקה באשכול אחד. כברירת מחדל, GKE לא מקצה עומסי עבודה קיימים שפועלים בצמתי x86 לצמתי Arm באשכול, כי דחייה (taint) ממוקמת באופן אוטומטי בצמתי Arm. עם זאת, אם רוצים ש-GKE יקצה עומסי עבודה שתואמים ל-x86 ושאין להם טולרנטיות מתאימה לצמתי Arm, אפשר להגדיר את מאגרי הצמתים כך ש-GKE לא יוסיף את הדחייה. מידע נוסף זמין במאמר בנושא הגדרת דחיית ברירת המחדל של ארכיטקטורת Arm.
כדי לראות את ההשפעה של ההכתמה שמוגדרת כברירת מחדל, מגדילים את קנה המידה של האפליקציה הקיימת:
מעדכנים את עומס העבודה ומגדילים את קנה המידה שלו ל-6 רפליקות:
$(cd k8s/overlays/x86_increase_replicas && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/x86-hello:v0.0.1) kubectl apply -k k8s/overlays/x86_increase_replicas/מחכים 30 שניות ואז מריצים את הפקודה הבאה כדי לבדוק את סטטוס הפריסה:
kubectl get pods -l="app=hello" --field-selector="status.phase=Pending"הפלט אמור להיראות כך:
NAME READY STATUS RESTARTS AGE x86-hello-deployment-6b7b456dd5-6tkxd 0/1 Pending 0 40s x86-hello-deployment-6b7b456dd5-k95b7 0/1 Pending 0 40s x86-hello-deployment-6b7b456dd5-kc876 0/1 Pending 0 40sבפלט הזה מוצגים פודים עם סטטוס Pending (בהמתנה) כי לא נשאר מקום בצמתים מבוססי-x86. מאחר שהמידרוג האוטומטי של האשכול מושבת, והצמתים של Arm מוכתמים כברירת מחדל, עומסי העבודה לא ייפרסו באף אחד מהצמתים הזמינים של Arm. ההגדרה הזו מונעת מ-GKE לתזמן עומסי עבודה של x86 בצמתי Arm. כדי לבצע פריסה לצומתי Arm, צריך לציין שהפריסה תואמת לצומתי Arm. אפשר גם להגדיר את GKE להסרת ה-taint שמוגדר כברירת מחדל.
בודקים את ה-Pods שנמצאים במצב Running:
kubectl get pods -l="app=hello" --field-selector="status.phase=Running" -o wideהפלט אמור להיראות כך:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES x86-hello-deployment-6b7b456dd5-cjclz 1/1 Running 0 62s 10.100.0.17 gke-my-cluster-default-pool-32019863-b41t <none> <none> x86-hello-deployment-6b7b456dd5-mwfkd 1/1 Running 0 34m 10.100.0.11 gke-my-cluster-default-pool-32019863-b41t <none> <none> x86-hello-deployment-6b7b456dd5-n56rg 1/1 Running 0 62s 10.100.0.16 gke-my-cluster-default-pool-32019863-b41t <none> <none>בפלט הזה, העמודה
NODEמציינת שכל ה-Pods מהפריסה פועלים רק במאגר ברירת המחדל, כלומר ה-Pods שתואמים ל-x86 מתוזמנים רק לצמתים של x86. ה-Pod המקורי שכבר תזמן לפני יצירת מאגר הצמתים של Arm עדיין פועל באותו צומת.מריצים את הפקודה הבאה כדי לגשת לשירות ולראות את הפלט:
for i in $(seq 1 6); do curl -w '\n' http://$external_ip; doneהפלט אמור להיראות כך:
Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-cjclz, CPU PLATFORM:linux/amd64מהפלט הזה אפשר לראות שכל ה-Pods שמשרתים בקשות פועלים בצמתי x86. חלק מה-Pods לא יכולים להגיב כי הם עדיין במצב Pending, כי אין מקום בצמתי x86 הקיימים והם לא יתוזמנו לצמתי Arm.
צריך לבנות מחדש את האפליקציה כדי להפעיל אותה ב-Arm
בקטע הקודם, הוספתם מאגר צמתים של Arm לאשכול הקיים. עם זאת, כשביצעתם הגדלה של אפליקציית x86 הקיימת, לא בוצע תזמון של אף אחד מעומסי העבודה לצמתי Arm. בקטע הזה, תבנו מחדש את האפליקציה כך שהיא תהיה תואמת ל-Arm, כדי שהיא תוכל לפעול בצמתי Arm באשכול.
בדוגמה הזו, צריך לבצע את השלבים האלה באמצעות docker build.
הגישה הזו כוללת שני שלבים:
- שלב ראשון: בניית הקוד ל-Arm.
- שלב שני: מעתיקים את קובץ ההפעלה למאגר קטן.
אחרי שמבצעים את השלבים האלה, מקבלים תמונה שתואמת ל-Arm בנוסף לתמונה שתואמת ל-x86.
השלב השני של העתקת קובץ ההפעלה לקונטיינר אחר מתבסס על אחת השיטות המומלצות ליצירת קונטיינר, והיא ליצור את קובץ האימג' הקטן ביותר שאפשר.
במדריך הזה נעשה שימוש באפליקציה לדוגמה שנבנתה באמצעות שפת התכנות Golang. באמצעות Golang, אפשר לבצע קומפילציה צולבת של אפליקציה למערכות הפעלה שונות ולפלטפורמות CPU שונות על ידי ציון משתני סביבה, GOOS ו-GOARCH, בהתאמה.
מריצים את הפקודה
cat Dockerfile_armכדי לראות את קובץ ה-Dockerfile שנכתב עבור Arm:# # Build: 1st stage # FROM golang:1.18-alpine as builder WORKDIR /app COPY go.mod . COPY hello.go . RUN GOARCH=arm64 go build -o /hello && \ apk add --update --no-cache file && \ file /helloקטע הקוד שמוצג כאן מציג רק את השלב הראשון. שני השלבים נכללים בקובץ.
בקובץ הזה, ההגדרה
GOARCH=arm64מורה לקומפיילר של Go לבצע build של האפליקציה עבור סט פקודות Arm. אין צורך להגדיר אתGOOSכי תמונת הבסיס בשלב הראשון היא תמונת Linux Alpine.יוצרים את הקוד עבור Arm ומעבירים אותו בדחיפה ל-Artifact Registry:
docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1 -f Dockerfile_arm . docker push us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1
פריסת גרסת Arm של האפליקציה
עכשיו, אחרי שהאפליקציה בנויה להרצה בצמתי Arm, אפשר לפרוס אותה בצמתי Arm באשכול.
בודקים את
add_arm_support.yamlעל ידי הרצת הפקודהcat k8s/overlays/arm/add_arm_support.yaml:הפלט אמור להיראות כך:
nodeSelector: kubernetes.io/arch: arm64התג
nodeSelectorמציין שעומס העבודה צריך לפעול רק בצמתי Arm. כשמשתמשים ב-nodeSelector, GKE מוסיף טולרנטיות שתואמת ל-דחייה (taint) שמוגדר כברירת מחדל בצמתי Arm, וכך מאפשר ל-GKE להקצות את עומס העבודה בצמתים האלה. מידע נוסף על הגדרת השדה הזה זמין במאמר הכנת עומס עבודה של Arm לפריסה.פורסים עותק אחד של גרסת האפליקציה שתואמת ל-Arm:
$(cd k8s/overlays/arm && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/arm-hello:v0.0.1) kubectl apply -k k8s/overlays/armממתינים 5 שניות, ואז בודקים אם הפריסה של Arm עונה לבקשות
curl:for i in $(seq 1 6); do curl -w '\n' http://$external_ip; doneהפלט אמור להיראות כך:
Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-mwfkd, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:arm-hello-deployment-69b4b6bdcc-n5l28, CPU PLATFORM:linux/arm64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:x86-hello-deployment-6b7b456dd5-n56rg, CPU PLATFORM:linux/amd64הפלט הזה צריך לכלול תגובות גם מהאפליקציות שתואמות ל-x86 וגם מהאפליקציות שתואמות ל-Arm, בתגובה לבקשה
curl.
איך יוצרים תמונה מרובת ארכיטקטורות כדי להריץ עומס עבודה בארכיטקטורות שונות
אפשר להשתמש באסטרטגיה שמתוארת בקטע הקודם ולפרוס עומסי עבודה נפרדים עבור x86 ו-Arm, אבל זה ידרוש מכם לתחזק ולשמור על שני תהליכי build ושני קובצי אימג' של קונטיינרים.
הכי טוב לבנות ולהריץ את האפליקציה בצורה חלקה גם בפלטפורמות x86 וגם בפלטפורמות Arm. אנחנו ממליצים על הגישה הזו. כדי להריץ את האפליקציה עם מניפסט אחד בכמה פלטפורמות ארכיטקטורה, צריך להשתמש בתמונות מרובות ארכיטקטורות (multi-arch). מידע נוסף על תמונות מרובות ארכיטקטורות זמין במאמר יצירת תמונות מרובות ארכיטקטורות לעומסי עבודה של Arm.
כדי להשתמש בתמונות מרובות ארכיטקטורות, צריך לוודא שהאפליקציה עומדת בדרישות המוקדמות הבאות:
- לאפליקציה שלך אין תלות בפלטפורמת ארכיטקטורה ספציפית.
- כל התלויות חייבות להיות מיועדות למבנים מרובים או לפלטפורמות היעד לפחות.
אפליקציית הדוגמה שבה נעשה שימוש במדריך הזה עומדת בשני התנאים המוקדמים האלה. עם זאת, מומלץ לבדוק את האפליקציות שלכם כשיוצרים את התמונות שלהן עם תמיכה בכמה ארכיטקטורות, לפני שפורסים אותן בסביבת ייצור.
יצירה ודחיפה של תמונות מרובות ארכיטקטורות
אתם יכולים ליצור קובצי אימג' מרובי-ארכיטקטורה באמצעות Docker Buildx אם עומדים בדרישות המוקדמות הבאות:
- תמונת הבסיס תומכת במספר ארכיטקטורות. כדי לבדוק את זה, מריצים את הפקודה
docker manifest inspectבתמונת הבסיס ובודקים את רשימת פלטפורמות הארכיטקטורה. בסוף הקטע הזה יש דוגמה לאופן הבדיקה של תמונה. - האפליקציה לא דורשת שלבי בנייה מיוחדים לכל פלטפורמת ארכיטקטורה. אם נדרשו שלבים מיוחדים, יכול להיות ש-Buildx לא יספיק. תצטרכו ליצור Dockerfile נפרד לכל פלטפורמה וליצור את המניפסט באופן ידני באמצעות
docker manifest create.
קובץ האימג' הבסיסי של האפליקציה לדוגמה הוא Alpine, שתומך בכמה ארכיטקטורות. אין גם שלבים ספציפיים לפלטפורמת ארכיטקטורה, כך שאפשר ליצור את התמונה מרובת הארכיטקטורות באמצעות Buildx.
בודקים את קובץ Docker על ידי הפעלת הפקודה
cat Dockerfile:# This is a multi-stage Dockerfile. # 1st stage builds the app in the target platform # 2nd stage create a lean image coping the binary from the 1st stage # # Build: 1st stage # FROM golang:1.18-alpine as builder ARG BUILDPLATFORM ARG TARGETPLATFORM RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" WORKDIR /app COPY go.mod . COPY hello.go . RUN go build -o /hello && \ apk add --update --no-cache file && \ file /hello # # Release: 2nd stage # FROM alpine WORKDIR / COPY --from=builder /hello /hello CMD [ "/hello" ]קובץ ה-Dockerfile הזה מגדיר שני שלבים: שלב הבנייה ושלב השחרור. אתם משתמשים באותו Dockerfile ששימש לבניית אפליקציית x86.
מריצים את הפקודה הבאה כדי ליצור ולהשתמש ב-
docker buildxחדש:docker buildx create --name multiarch --use --bootstrapאחרי שיצרתם את כלי הבנייה החדש הזה, אתם יכולים לבנות ולדחוף תמונה שתואמת גם ל-
linux/amd64וגם ל-linux/arm64באמצעות הדגל--platform. לכל פלטפורמה שמסופקת עם הדגל, Buildx יוצר תמונה בפלטפורמת היעד. כש-Buildx יוצר את קובץ האימג'linux/arm64, הוא מוריד קובצי אימג' בסיסייםarm64. בשלב הראשון, המערכת בונה את הקובץ הבינארי בתמונהarm64 golang:1.18-alpineעבורarm64. בשלב השני, מתבצעת הורדה של תמונתarm64Alpine Linux והקובץ הבינארי מועתק לשכבה של התמונה הזו.בנייה והעלאה של התמונה:
docker buildx build -t us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1 -f Dockerfile --platform linux/amd64,linux/arm64 --push .הפלט אמור להיראות כך:
=> [linux/arm64 builder x/x] .. => [linux/amd64 builder x/x] ..בפלט הזה אפשר לראות שנוצרו שתי תמונות, אחת עבור
linux/arm64ואחת עבורlinux/amd64.בודקים את קובץ המניפסט של תמונת המולטי-ארכיטקטורה החדשה:
docker manifest inspect us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1הפלט אמור להיראות כך:
{ "schemaVersion": 2, "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json", "manifests": [ { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 739, "digest": "sha256:dfcf8febd94d61809bca8313850a5af9113ad7d4741edec1362099c9b7d423fc", "platform": { "architecture": "amd64", "os": "linux" } }, { "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "size": 739, "digest": "sha256:90b637d85a93c3dc03fc7a97d1fd640013c3f98c7c362d1156560bbd01f6a419", "platform": { "architecture": "arm64", "os": "linux" } } ]בפלט הזה, הקטע
manifestsכולל שני קובצי מניפסט, אחד עם ארכיטקטורת הפלטפורמהamd64והשני עם ארכיטקטורת הפלטפורמהarm64.כשפורסים את קובץ האימג' של הקונטיינר הזה באשכול, GKE מוריד באופן אוטומטי רק את קובץ האימג' שתואם לארכיטקטורה של הצומת.
פריסת הגרסה מרובת הארכיטקטורות של האפליקציה
לפני שמפעילים את תמונת המולטי-ארכיטקטורה, צריך למחוק את עומסי העבודה המקוריים:
kubectl delete deploy x86-hello-deployment arm-hello-deploymentבודקים את
add_multiarch_support.yamlkustomize overlay על ידי הרצת הפקודהcat k8s/overlays/multiarch/add_multiarch_support.yaml:הפלט כולל את קבוצת הטולרנטיות הבאה:
tolerations: - key: kubernetes.io/arch operator: Equal value: arm64 effect: NoScheduleהטולרנטיות הזו מאפשרת להריץ את עומס העבודה בצמתי Arm באשכול, כי הטולרנטיות תואמת לדחייה שמוגדרת כברירת מחדל בכל צמתי Arm. עכשיו עומס העבודה הזה יכול לפעול בכל צומת באשכול, ולכן נדרשת רק הסבילות. אם מגדירים רק את ה-toleration, GKE יכול לתזמן את עומס העבודה גם לצמתי x86 וגם לצמתי Arm. אם רוצים לציין איפה GKE יכול לתזמן עומסי עבודה, אפשר להשתמש בבוררי צמתים ובכללי שיוך צמתים. מידע נוסף על הגדרת השדות האלה זמין במאמר הכנת עומס עבודה של Arm לפריסה.
פורסים את קובץ האימג' של הקונטיינר עם כמה ארכיטקטורות עם 6 רפליקות:
$(cd k8s/overlays/multiarch && kustomize edit set image hello=us-central1-docker.pkg.dev/$PROJECT_ID/docker-repo/multiarch-hello:v0.0.1) kubectl apply -k k8s/overlays/multiarchממתינים 10 שניות ואז מוודאים שכל העותקים של האפליקציה פועלים:
kubectl get pods -l="app=hello" -o wideהפלט אמור להיראות כך:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES multiarch-hello-deployment-65bfd784d-5xrrr 1/1 Running 0 95s 10.100.1.5 gke-my-cluster-arm-pool-e172cff7-shwc <none> <none> multiarch-hello-deployment-65bfd784d-7h94b 1/1 Running 0 95s 10.100.1.4 gke-my-cluster-arm-pool-e172cff7-shwc <none> <none> multiarch-hello-deployment-65bfd784d-7qbkz 1/1 Running 0 95s 10.100.1.7 gke-my-cluster-arm-pool-e172cff7-shwc <none> <none> multiarch-hello-deployment-65bfd784d-7wqb6 1/1 Running 0 95s 10.100.1.6 gke-my-cluster-arm-pool-e172cff7-shwc <none> <none> multiarch-hello-deployment-65bfd784d-h2g2k 1/1 Running 0 95s 10.100.0.19 gke-my-cluster-default-pool-32019863-b41t <none> <none> multiarch-hello-deployment-65bfd784d-lc9dc 1/1 Running 0 95s 10.100.0.18 gke-my-cluster-default-pool-32019863-b41t <none> <none>הפלט הזה כולל עמודה
NODEשמציינת שה-Pods פועלים בשני הצמתים במאגר הצמתים של Arm ובצמתים אחרים במאגר הצמתים שמוגדר כברירת מחדל (x86).מריצים את הפקודה הבאה כדי לגשת לשירות ולראות את הפלט:
for i in $(seq 1 6); do curl -w '\n' http://$external_ip; doneהפלט אמור להיראות כך:
Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7qbkz, CPU PLATFORM:linux/arm64 Hello from NODE:gke-my-cluster-default-pool-32019863-b41t, POD:multiarch-hello-deployment-65bfd784d-lc9dc, CPU PLATFORM:linux/amd64 Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-5xrrr, CPU PLATFORM:linux/arm64 Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7wqb6, CPU PLATFORM:linux/arm64 Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7h94b, CPU PLATFORM:linux/arm64 Hello from NODE:gke-my-cluster-arm-pool-e172cff7-shwc, POD:multiarch-hello-deployment-65bfd784d-7wqb6, CPU PLATFORM:linux/arm64אפשר לראות שקבוצות ה-Pod שפועלות בפלטפורמות ארכיטקטורה עונות על הבקשות.
יצרתם ופרסתם תמונה מרובת ארכיטקטורות כדי להריץ עומס עבודה בצורה חלקה בכמה ארכיטקטורות.
הסרת המשאבים
כדי להימנע מחיובים בחשבון Google Cloud בגלל השימוש במשאבים שנעשה במסגרת המדריך הזה, אפשר למחוק את הפרויקט שמכיל את המשאבים, או להשאיר את הפרויקט ולמחוק את המשאבים בנפרד.
אחרי שמסיימים את המדריך, אפשר למחוק את המשאבים שיצרתם כדי לצמצם את השימוש במכסה ולהפסיק את החיובים. הסעיפים הבאים נסביר איך למחוק או להשבית את המשאבים האלו.
מחיקת הפרויקט
הדרך הקלה ביותר לבטל את החיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך הזה.
כדי למחוק את הפרויקט:
- במסוף Google Cloud , נכנסים לדף Manage resources.
- ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
- כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.
מחיקת השירות, האשכול והמאגר
אם לא רוצים למחוק את הפרויקט כולו, צריך למחוק את האשכול ואת המאגר שיצרתם בשביל המדריך הזה:
מריצים את הפקודה
kubectl deleteכדי למחוק את השירות של האפליקציה:kubectl delete service hello-serviceהפקודה הזו מוחקת את מאזן העומסים של Compute Engine שיצרתם כשחשפתם את הפריסה.
כדי למחוק את האשכול, מריצים את הפקודה
gcloud container clusters delete:gcloud container clusters delete $CLUSTER_NAME --location $CONTROL_PLANE_LOCATIONמחיקת המאגר:
gcloud artifacts repositories delete docker-repo —location=us-central1 --async
המאמרים הבאים
- עומסי עבודה של Arm ב-GKE
- יצירת אשכולות ומאגרי צמתים עם צמתי Arm
- פיתוח קובצי אימג' מרובי-ארכיטקטורה לעומסי עבודה של Arm
- הכנת עומס עבודה של Arm לפריסה
- הכנת עומסי עבודה של Autopilot בארכיטקטורת Arm
- שיטות מומלצות להרצה של אפליקציות Kubernetes שעברו אופטימיזציה של העלויות ב-GKE
- כדאי להעמיק את הקריאה ולהכיר דוגמאות לארכיטקטורות, תרשימים ושיטות מומלצות בנושאי Google Cloud. כל אלה זמינים במרכז הארכיטקטורה של Cloud.