כשמנהלים אשכולות Standard ב-Google Kubernetes Engine (GKE), בעיות במאגרי הצמתים עלולות לשבש פעולות קריטיות. הבעיות האלה יכולות למנוע מכם להרחיב אופקית את עומסי העבודה כדי לעמוד בביקוש, או לבצע שדרוגים חיוניים בתשתית, מה שעלול להשפיע על האמינות של האפליקציה.
בדף הזה מוסבר איך לפתור את הבעיות הנפוצות האלה במאגרי צמתים. כאן תוכלו למצוא הנחיות איך לוודא אם אין לכם מספיק משאבים, איך להשתמש בתכונות כמו הקצאה לפי מאמץ מרבי כדי ליצור צמתים, ואיך להעביר את עומסי העבודה שלכם בצורה בטוחה בלי לגרום לשיבושים.
המידע הזה חשוב לאדמינים ולמפעילים של הפלטפורמה שאחראים לניהול התשתית של האשכול. הוא יכול גם לעזור למפתחי אפליקציות שצריכים להבין איך המגבלות של מאגרי הצמתים יכולות להשפיע על פריסת האפליקציות שלהם. למידע נוסף על התפקידים הנפוצים ודוגמאות למשימות שאנחנו מתייחסים אליהן בתוכן של Google Cloud , קראו את המאמר תפקידי משתמשים ומשימות נפוצים ב-GKE.
בעיות ביצירת מאגר צמתים
בקטע הזה מפורטות בעיות שעשויות לקרות כשאתם יוצרים מאגרי צמתים חדשים באשכולות רגילים, והצעות לתיקון הבעיות.
הבעיה: לא הצלחנו ליצור מאגר צמתים בגלל מחסור במשאבים
הבעיה הבאה מתרחשת כשיוצרים מאגר צמתים עם חומרה ספציפית באזור ב- Google Cloud שאין בו מספיק חומרה זמינה כדי לעמוד בדרישות.
כדי לוודא שיצירת מאגר הצמתים נכשלה כי לא היו מספיק משאבים באזור, בודקים אם יש הודעות שגיאה רלוונטיות ביומנים.
נכנסים לדף Logs Explorer במסוף Google Cloud :
בשדה Query, מציינים את השאילתה הבאה:
log_id(cloudaudit.googleapis.com/activity) resource.labels.cluster_name="CLUSTER_NAME" protoPayload.status.message:("ZONE_RESOURCE_POOL_EXHAUSTED" OR "does not have enough resources available to fulfill the request" OR "resource pool exhausted" OR "does not exist in zone")מחליפים את
CLUSTER_NAMEבשם של אשכול GKE.לוחצים על Run query.
יכול להיות שתופיע אחת מהודעות השגיאה הבאות:
resource pool exhaustedThe zone does not have enough resources available to fulfill the request. Try a different zone, or try again later.ZONE_RESOURCE_POOL_EXHAUSTEDZONE_RESOURCE_POOL_EXHAUSTED_WITH_DETAILSMachine type with name 'MACHINE_NAME' does not exist in zone 'ZONE_NAME'
כדי לפתור את הבעיה, נסו את הפתרונות הבאים:
- חשוב לוודא שבאזור או בתחום שבחרתם יש את החומרה הספציפית שאתם צריכים. Google Cloud בטבלת הזמינות של Compute Engine אפשר לבדוק אם אזורים ספציפיים תומכים בחומרה ספציפית. לבחור לצמתים אזור או תחום אחרים ב-Google Cloud , שבהם אולי יש זמינות טובה יותר של החומרה שאתם צריכים.
- יוצרים את מאגר הצמתים עם סוגי מכונות קטנים יותר. מגדילים את מספר הצמתים במאגר הצמתים כדי שקיבולת המחשוב הכוללת תישאר זהה.
- כדי לשריין את המשאבים מראש, אתם יכולים להשתמש בשמירת קיבולת ב-Compute Engine.
- מגדירים ComputeClass בהתאמה אישית עם רשימה מתועדפת של סדרות מכונות חלופיות, ומפעילים העברה פעילה (
optimizeRulePriority: true). ההגדרה הזו מאפשרת ל-GKE להקצות באופן אוטומטי חומרה חלופית כשסדרת המכונות המועדפת לא זמינה באזור, ולהעביר את עומסי העבודה בחזרה כשהקיבולת המועדפת מתאוששת. - כדי ליצור בהצלחה את מאגר הצמתים, השתמשו בהקצאה לפי יכולת, שמתוארת בקטע הבא, אם היא יכולה להקצות לפחות מספר מינימלי מסוים של צמתים מתוך המספר המבוקש.
הקצאה לפי מאמץ מרבי
בחומרה מסוימת, אתם יכולים להשתמש בהקצאה במידת האפשר, שמורה ל-GKE ליצור את מאגר הצמתים אם הוא יכול להקצות לפחות מספר מינימלי מסוים של צמתים. GKE ממשיך לנסות להקצות את שאר הצמתים כדי למלא את הבקשה המקורית לאורך זמן. כדי להורות ל-GKE להשתמש בהקצאה לפי מאמץ מרבי, משתמשים בפקודה הבאה:
gcloud container node-pools create NODE_POOL_NAME \
--cluster=CLUSTER_NAME \
--location=CONTROL_PLANE_LOCATION \
--node-locations=ZONE1,ZONE2,... \
--machine-type=MACHINE_TYPE
--best-effort-provision \
--min-provision-nodes=MINIMUM_NODES
מחליפים את מה שכתוב בשדות הבאים:
-
NODE_POOL_NAME: השם של מאגר הצמתים החדש. -
CONTROL_PLANE_LOCATION: המיקום ב-Compute Engine של מישור הבקרה של האשכול. באשכולות אזוריים צריך לציין אזור, ובאשכולות של תחומים צריך לציין תחום. ZONE1,ZONE2,...: אזורי Compute Engine של הצמתים. האזורים האלה חייבים לתמוך בחומרה שנבחרה.MACHINE_TYPE: סוג המכונה של Compute Engine לצמתים. לדוגמה,a2-highgpu-1g.-
MINIMUM_NODES: המספר המינימלי של צמתים ש-GKE צריך להקצות כדי ליצור את מאגר הצמתים. אם לא מציינים ערך, ברירת המחדל היא1.
לדוגמה, נניח שאתם צריכים 10 צמתים עם מעבדי NVIDIA A100 40GB GPU מצורפים ב-us-central1-c. לפי מיקומי GPU, האזור הזה תומך במעבדי GPU מסוג A100. כדי למנוע כשל ביצירת מאגר הצמתים אם אין 10 מכונות GPU זמינות, אתם משתמשים בהקצאה לפי מאמץ מרבי.
gcloud container node-pools create a100-nodes \
--cluster=ml-cluster \
--location=us-central1 \
--node-locations=us-central1-c \
--num-nodes=10 \
--machine-type=a2-highgpu-1g \
--accelerator=type=nvidia-tesla-a100,count=1 \
--best-effort-provision \
--min-provision-nodes=5
GKE יוצר את מאגר הצמתים גם אם רק חמישה GPUs זמינים ב-us-central1-c. עם הזמן, GKE מנסה להקצות עוד צמתים עד שיש 10 צמתים במאגר הצמתים.
שגיאה: המכונה לא מכילה את המטא-נתונים "instance-template"
אם מאגר צמתים נכשל בשדרוג, בהתאמה לעומס או בתיקון אוטומטי של צמתים, יכול להיות שתראו את השגיאה הבאה בסטטוס שלו:
Instance INSTANCE_NAME does not contain 'instance-template' metadata
השגיאה הזו מציינת שהמטא-נתונים של מכונות וירטואליות שהוקצו על ידי GKE נפגמו. זה קורה בדרך כלל כשסקריפטים או אוטומציה שנוצרו בהתאמה אישית מנסים להוסיף מטא-נתונים חדשים של מכונה (כמו block-project-ssh-keys), ובמקום רק להוסיף או לעדכן ערכים, הם גם מוחקים מטא-נתונים קיימים.
במאמר הגדרת מטא-נתונים בהתאמה אישית תוכלו לקרוא על מטא-נתונים של מכונות וירטואליות.
אם נמחקו ערכים קריטיים של מטא-נתונים (בין היתר: instance-template, kube-labels, kubelet-config, kubeconfig, cluster-name, configure-sh, cluster-uid), הצומת או כל מאגר הצמתים עלולים להפוך ללא יציבים, כי הערכים האלה חיוניים לפעולות של GKE.
אם המטא-נתונים של המכונה נפגמו, מומלץ לשחזר אותם על ידי יצירה מחדש של מאגר הצמתים שמכיל את המכונות הווירטואליות הפגומות. תצטרכו להוסיף מאגר צמתים לאשכול ולהגדיל את מספר הצמתים במאגר הצמתים החדש, תוך כדי גידור והסרה של צמתים במאגר אחר. איך מעבירים עומסי עבודה בין מאגרי צמתים
כדי לראות מי ערך את המטא-נתונים של המכונה ומתי, אתם יכולים לעיין במידע של רישום ביומן הביקורת של Compute Engine או למצוא יומנים באמצעות Logs Explorer, עם שאילתת חיפוש שדומה לזו:
resource.type="gce_instance_group_manager"
protoPayload.methodName="v1.compute.instanceGroupManagers.setInstanceTemplate"
ביומנים אפשר למצוא את כתובת ה-IP של מקור הבקשה ואת סוכן המשתמש. לדוגמה:
requestMetadata: {
callerIp: "REDACTED"
callerSuppliedUserAgent: "google-api-go-client/0.5 GoogleContainerEngine/v1"
}
העברת עומסי עבודה בין מאגרי צמתים
כדי להעביר עומסי עבודה ממאגר צמתים אחד למאגר צמתים אחר, צריך לפעול לפי ההוראות הבאות. אם אתם רוצים לשנות את מאפייני המכונה של הצמתים במאגר הצמתים, קראו את המאמר שינוי קנה מידה אנכי באמצעות שינוי מאפייני המכונה של הצומת.
איך מעבירים Pods למאגר צמתים חדש
כדי להעביר Pods למאגר צמתים חדש, צריך לבצע את הפעולות הבאות:
הגדרת הצמתים במאגר הצמתים הקיים כ-Cordon: הפעולה הזו מסמנת את הצמתים במאגר הצמתים הקיים כ-Unschedulable. אחרי שמסמנים את הצמתים כ-unschedulable, המערכת של Kubernetes מפסיקה לתזמן Pods חדשים לצמתים האלה.
ניקוז הצמתים במאגר הצמתים הקיים: הפעולה הזו מפנה בצורה חלקה את עומסי העבודה שפועלים בצמתים של מאגר הצמתים הקיים.
השלבים האלה, שמבוצעים בנפרד לכל צומת, גורמים לפודים שפועלים במאגר הצמתים הקיים להסתיים בצורה תקינה. Kubernetes מתזמן אותם מחדש בצמתים זמינים אחרים.
כדי לוודא ש-Kubernetes יסיים את האפליקציות בצורה תקינה, הקונטיינרים צריכים לטפל באות SIGTERM. הגישה הזו מאפשרת לסגור חיבורים פעילים ללקוחות ולבצע commit או rollback של טרנזקציות במסד הנתונים בצורה נקייה. בשדה spec.terminationGracePeriodSeconds במניפסט של ה-Pod, אתם יכולים לציין כמה זמן Kubernetes צריך להמתין לפני עצירת הקונטיינרים ב-Pod. ברירת המחדל היא 30 שניות.
מידע נוסף על סיום Pod זמין במסמכי התיעוד של Kubernetes.
אפשר לבודד ולרוקן צמתים באמצעות הפקודות kubectl cordon ו-kubectl drain.
יצירת מאגר צמתים והעברת עומסי עבודה
כדי להעביר את עומסי העבודה למאגר צמתים חדש, יוצרים את מאגר הצמתים החדש, ואז מבודדים ומרוקנים את הצמתים במאגר הצמתים הקיים:
מוסיפים מאגר צמתים לאשכול.
מריצים את הפקודה הבאה כדי לוודא שמאגר הצמתים החדש נוצר:
gcloud container node-pools list --cluster CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATIONמחליפים את מה שכתוב בשדות הבאים:
-
CLUSTER_NAME: שם האשכול. -
CONTROL_PLANE_LOCATION: המיקום ב-Compute Engine של מישור הבקרה של האשכול. באשכולות אזוריים צריך לציין אזור, ובאשכולות של תחומים צריך לציין תחום.
-
כדי להשבית את ההתאמה האוטומטית לעומס (automatic scaling) במאגר הצמתים הקיים, אם היא מופעלת, מריצים את הפקודה הבאה:
gcloud container clusters update CLUSTER_NAME --location=CONTROL_PLANE_LOCATION \ --no-enable-autoscaling \ --node-pool=EXISTING_NODE_POOL_NAMEמריצים את הפקודה הבאה כדי לראות באיזה צומת הפודים פועלים (ראו את העמודה
NODE):kubectl get pods -o=wideמציגים רשימה של הצמתים במאגר הצמתים הקיים, ומחליפים את
EXISTING_NODE_POOL_NAMEבשם:kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAMEמריצים את הפקודה
kubectl cordon NODE(מחליפים אתNODEבשמות מהפקודה הקודמת). פקודת המעטפת הבאה עוברת על כל צומת במאגר הצמתים הקיים ומסמנת אותם כ-Unschedulable:for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do kubectl cordon "$node"; doneאם רוצים, מעדכנים את עומסי העבודה שפועלים במאגר הצמתים הקיים כדי להוסיף nodeSelector לתווית
cloud.google.com/gke-nodepool:NEW_NODE_POOL_NAME, כאשרNEW_NODE_POOL_NAMEהוא השם של מאגר הצמתים החדש. כך אפשר לוודא ש-GKE ימקם את עומסי העבודה האלה בצמתים במאגר הצמתים החדש.מרוקנים כל צומת על ידי פינוי כל ה-Pods עם תקופת סיום הדרגתית של 10 שניות:
for node in $(kubectl get nodes -l cloud.google.com/gke-nodepool=EXISTING_NODE_POOL_NAME -o=name); do kubectl drain --force --ignore-daemonsets --delete-emptydir-data --grace-period=GRACEFUL_TERMINATION_SECONDS "$node"; doneמחליפים את
GRACEFUL_TERMINATION_PERIOD_SECONDSבמשך הזמן הנדרש לסיום תקין.כדי לוודא שהצמתים במאגר הצמתים הקיים נמצאים בסטטוס
SchedulingDisabledברשימת הצמתים, מריצים את הפקודה הבאה:kubectl get nodesבנוסף, הפודים אמורים לפעול עכשיו בצמתים במאגר הצמתים החדש:
kubectl get pods -o=wideאם לא צריך את מאגר הצמתים הקיים, מוחקים אותו:
gcloud container node-pools delete default-pool --cluster CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION
המאמרים הבאים
אם לא מצאתם פתרון לבעיה במסמכי העזרה, תוכלו לקבל עזרה נוספת בקבלת תמיכה, כולל עצות בנושאים הבאים:
- לפתוח בקשת תמיכה באמצעות פנייה ל-Cloud Customer Care.
- לקבל תמיכה מהקהילה על ידי פרסום שאלות ב-StackOverflow ושימוש בתג
google-kubernetes-engineכדי לחפש בעיות דומות. אתם יכולים גם להצטרף לערוץ Slack של#kubernetes-engineכדי לקבל תמיכה מהקהילה. - דיווח על בעיות או שליחת בקשות להוספת תכונות באמצעות הכלי הציבורי Issue Tracker.