במהלך ניהול של אשכולות רגילים ב-Google Kubernetes Engine (GKE), בעיות במאגרי הצמתים עלולות לשבש פעולות קריטיות. הבעיות האלה יכולות למנוע מכם להרחיב את נפח העבודה כדי לעמוד בביקוש או לבצע שדרוגים חיוניים בתשתית, מה שעלול להשפיע על המהימנות של האפליקציה.
בדף הזה מוסבר איך לפתור בעיות נפוצות במאגרי צמתים. תוכלו לקבל הנחיות לגבי בדיקה אם אין לכם מספיק משאבים, שימוש בתכונות כמו הקצאת משאבים בשיטת הכי טוב שאפשר ליצירת צמתים והעברה בטוחה של עומסי העבודה בלי לגרום להפרעה.
המידע הזה חשוב לאדמינים ולמפעילים של הפלטפורמה שאחראים על ניהול התשתית של האשכול. הוא יכול להיות שימושי גם למפתחי אפליקציות שצריכים להבין איך מגבלות של מאגר צמתים יכולות להשפיע על פריסות האפליקציות שלהם. מידע נוסף על התפקידים הנפוצים ומשימות לדוגמה שאליהם אנחנו מתייחסים בתוכן זמין במאמר תפקידי משתמשים נפוצים ומשימות ב-GKE. Google Cloud
בעיות ביצירת מאגר צמתים
בקטע הזה מפורטות בעיות שיכולות לקרות כשיוצרים מאגרי צמתים חדשים באשכולות רגילים, ומוצעות הצעות לפתרון שלהן.
בעיה: יצירת מאגר הצמתים נכשלת בגלל מחסור במשאבים
הבעיה הבאה מתרחשת כשיוצרים מאגר צמתים עם חומרה ספציפית באזור 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.
- כדי ליצור את מאגר הצמתים בהצלחה, אם אפשר להקצות לפחות מספר מינימלי של צמתים מתוך המספר המבוקש, צריך להשתמש בהקצאת משאבים בשיטת המאמץ המרבי, שמתוארת בקטע הבא.
הקצאת משאבים בשיטת הכי טוב שאפשר
במקרה של חומרה מסוימת, אפשר להשתמש בהקצאת משאבים בשיטת הכי טוב שאפשר, שבה 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 צמתים עם יחידות GPU של NVIDIA A100 בנפח 40GB שמצורפות ל-us-central1-c. לפי מיקומי ה-GPU, האזור הזה תומך במעבדי A100 GPU. כדי למנוע כשל ביצירת מאגר צמתים אם אין 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 יוצר את מאגר הצמתים גם אם זמינים רק חמישה מעבדי GPU ב-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"
}
העברת עומסי עבודה בין מאגרי צמתים
כדי להעביר עומסי עבודה ממאגר צמתים אחד למאגר צמתים אחר, פועלים לפי ההוראות הבאות. אם רוצים לשנות את מאפייני המכונה של הצמתים במאגר הצמתים, אפשר לעיין במאמר בנושא שינוי מאפייני המכונה של הצמתים כדי להגדיל את הקיבולת.
איך מעבירים קבוצות Pod למאגר צמתים חדש
כדי להעביר Pods למאגר צמתים חדש, צריך לבצע את הפעולות הבאות:
מבודדים את הצמתים במאגר הצמתים הקיים: הפעולה הזו מסמנת את הצמתים במאגר הצמתים הקיים כלא ניתנים לתזמון. מערכת Kubernetes מפסיקה לתזמן Pods חדשים לצמתים האלה אחרי שמסמנים אותם כלא ניתנים לתזמון.
מרוקנים את הצמתים במאגר הצמתים הקיים: הפעולה הזו מפנה את עומסי העבודה שפועלים בצמתים של מאגר הצמתים הקיים בצורה מסודרת.
השלבים האלה, שצריך לבצע לכל צומת בנפרד, גורמים לסיום תקין של ה-Pods שפועלים במאגר הצמתים הקיים. מערכת Kubernetes מתזמנת אותם מחדש בצמתים זמינים אחרים.
כדי לוודא ש-Kubernetes מסיים את האפליקציות בצורה תקינה, הקונטיינרים צריכים לטפל באות SIGTERM. אפשר להשתמש בגישה הזו כדי לסגור חיבורים פעילים ללקוחות ולבצע או לבטל טרנזקציות במסד הנתונים בצורה נקייה. במניפסט של ה-Pod, אפשר להשתמש בשדה spec.terminationGracePeriodSeconds כדי לציין כמה זמן 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. מציינים אזור לאשכולות אזוריים או אזור זמין לאשכולות אזוריים.
-
כדי להשבית את ההתאמה האוטומטית לעומס במאגר הצמתים הקיים, אם הוא מופעל, מריצים את הפקודה הבאה:
gcloud container clusters update CLUSTER_NAME --location=CONTROL_PLANE_LOCATION \ --no-enable-autoscaling \ --node-pool=EXISTING_NODE_POOL_NAMEמריצים את הפקודה הבאה כדי לראות באיזה צומת פועלים ה-Pods (ראו את העמודה
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בשמות מהפקודה הקודמת). פקודת ה-Shell הבאה מבצעת איטרציה על כל צומת במאגר הצמתים הקיים ומסמנת אותם כצמתים שלא ניתן לתזמן בהם משימות: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בנוסף, אמור להיות אפשר לראות שה-Pods פועלים עכשיו בצמתים במאגר הצמתים החדש:
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כדי לקבל תמיכה נוספת מהקהילה. - פתיחת באגים או בקשות להוספת תכונות באמצעות הכלי הציבורי למעקב אחר בעיות.