במהלך ניהול של אשכולות רגילים ב-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.
- כדי ליצור את מאגר הצמתים בהצלחה, אם אפשר להקצות לפחות מספר מינימלי של צמתים מתוך המספר המבוקש, צריך להשתמש בהקצאת משאבים בשיטת הכי טוב שאפשר, שמתוארת בקטע הבא.
הקצאת משאבים בשיטת 'הכי טוב שאפשר'
במקרה של חומרה מסוימת, אפשר להשתמש בהקצאת משאבים בשיטת הכי טוב שאפשר, שבה 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, אזור הזמינות הזה תומך במעבדי 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 יוצר את מאגר הצמתים גם אם זמינים רק חמישה מעבדי 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כדי לקבל תמיכה נוספת מהקהילה. - פתיחת דיווחים על בעיות או בקשות להוספת תכונות באמצעות הכלי הציבורי למעקב אחר בעיות.