כדי לוודא שהאשכולות תואמים למקור המידע המהימן המרכזי, חשוב לפתור את בעיות הסנכרון של ההגדרות ב-סנכרון תצורות. אם הסנכרון נכשל, הפריסות עלולות להיתקע וההגדרות של האשכולות עלולות לסטות מהמצב המוצהר שלהן. כדי לשחזר את ההתאמה האוטומטית, אתם יכולים לאבחן ולתקן שגיאות סנכרון נפוצות ב-KNV2009, כמו הרשאות חסרות של בקרת גישה מבוססת-תפקידים (RBAC), אובייקטים של ResourceGroup שחורגים ממגבלות הגודל של etcd וזמן אחזור של תגובות לפעולה מאתר אחר (webhook).
פתרון שגיאות KNV 2009
שגיאות מסוג KNV2009 מציינות שסנכרון ההגדרות נכשל בסנכרון של חלק מההגדרות לאשכול. בקטעים הבאים מפורטות כמה מהסיבות הנפוצות ביותר לבעיה ואיך לפתור אותן.
אסור לבצע פעולות במשאבים מסוימים
מכיוון שצריך להעניק לאובייקטים של RepoSync את ה-RBAC שלהם, יכול להיות שחסרות ההרשאות שנדרשות כדי להחיל משאבים.
כדי לוודא שההרשאות חסרות, אפשר לבדוק את סטטוס המשאב RepoSync:
kubectl get reposync repo-sync -n NAMESPACE -o yaml
מחליפים את NAMESPACE במרחב השמות שבו יצרתם את המאגר של מרחב השמות.
אפשר גם להשתמש בפקודה nomos status.
אם ההודעות הבאות מופיעות בסטטוס, סימן שלמנגנון ההתאמה ב-NAMESPACE אין את ההרשאה שנדרשת כדי להחיל את המשאב:
KNV2009: deployments.apps "nginx-deployment" is forbidden: User "system:serviceaccount:config-management-system:ns-reconciler-default" cannot get resource "deployments" in API group "apps" in the namespace "default"
כדי לפתור את הבעיה, צריך להצהיר על הגדרת RoleBinding שנותנת לחשבון השירות של ה-reconciler הרשאה לנהל את המשאב שנכשל במרחב השמות הזה. במאמר הגדרת סנכרון מכמה מאגרים מוסבר איך מוסיפים RoleBinding.
הבעיה הזו יכולה להשפיע גם על אובייקטים של RootSync אם השתמשתם ב-spec.override.roleRefs כדי לשנות את התפקידים שניתנו לאובייקט RootSync. אם לא הגדרתם את השדה הזה, אובייקטים מסוג RootSync מקבלים את התפקיד cluster-admin כברירת מחדל.
האובייקט ResourceGroup חורג ממגבלת הגודל של האובייקט etcd
אם מופיעה הודעת השגיאה הבאה כשמנסים להחיל הגדרות על האשכול, האובייקט ResourceGroup חורג ממגבלת הגודל של האובייקט etcd:
KNV2009: too many declared resources causing ResourceGroup.kpt.dev, config-management-system/root-sync failed to be applied: task failed (action: "Inventory", name: "inventory-add-0"): Request entity too large: limit is 3145728. To fix, split the resources into multiple repositories.
מומלץ לפצל את מאגר Git למספר מאגרים. אם אתם לא יכולים לפצל את מאגר Git כי האובייקט כבר גדול מדי והשינויים לא נשמרים, אתם יכולים להגדיר את RootSync או את RepoSync כך שישביתו זמנית את כתיבת סטטוס האובייקט ב-ResourceGroup. כדי לעשות את זה, מגדירים את השדה .spec.override.statusMode של האובייקט RootSync או RepoSync לערך disabled. כך, הכלי "סנכרון הגדרות" מפסיק לעדכן את הסטטוס של המשאבים המנוהלים באובייקט ResourceGroup. הפעולה הזו מקטינה את הגודל של האובייקט ResourceGroup. עם זאת, אי אפשר לראות את הסטטוס של משאבים מנוהלים מ-nomos status.
אם לא מופיעה שגיאה מהאובייקט RootSync או RepoSync, האובייקטים ממקור האמת סונכרנו עם האשכול. כדי לבדוק אם משאב ResourceGroup חורג ממגבלת הגודל של אובייקט etcd, בודקים את הסטטוס של משאב ResourceGroup ואת היומן של בקר ResourceGroup:
בודקים את הסטטוס של ResourceGroup:
כדי לבדוק את האובייקט
RootSync, מריצים את הפקודה הבאה:kubectl get resourcegroup root-sync -n config-management-systemכדי לבדוק את האובייקט
RepoSync, מריצים את הפקודה הבאה:kubectl get resourcegroup repo-sync -n NAMESPACEמחליפים את
NAMESPACEבמרחב השמות שבו יצרתם את המאגר.
הפלט אמור להיראות כך:
NAME RECONCILING STALLED AGE root-sync True False 35mאם הערך בעמודה
RECONCILINGהואTrue, סימן שהמשאב ResourceGroup עדיין בתהליך התאמה.בודקים את היומנים של ResourceGroup Controller:
kubectl logs deployment resource-group-controller-manager -c manager -n resource-group-systemאם בפלט מופיעה שגיאה שדומה לדוגמה הבאה, המשאב ResourceGroup גדול מדי וחורג ממגבלת הגודל של האובייקט
etcd:"error":"etcdserver: request is too large"
כדי למנוע מה-ResourceGroup להיות גדול מדי, צריך לצמצם את מספר המשאבים במאגר Git. אתם יכולים לפצל מאגר בסיס אחד לכמה מאגרי בסיס.
הזמן הקצוב לתפוגה של התאמת החלת התלות
אם אתם מסנכרנים אובייקטים עם יחסי תלות, יכול להיות שתקבלו הודעת שגיאה דומה לדוגמה הבאה כשהמנגנון לתיאום ינסה להחיל אובייקטים עם ההערה config.kubernetes.io/depends-on על האשכול:
KNV2009: skipped apply of Pod, bookstore/pod4: dependency apply reconcile timeout: bookstore_pod3__Pod For more information, see https://g.co/cloud/acm-errors#knv2009
השגיאה הזו מציינת שאובייקט התלות לא תואם לזמן הקצוב המוגדר כברירת מחדל של חמש דקות. סנכרון ההגדרות לא יכול להחיל את האובייקט התלוי כי עם ההערה config.kubernetes.io/depends-on, סנכרון ההגדרות מחיל אובייקטים רק בסדר שאתם רוצים. כדי לשנות את ברירת המחדל של הזמן הקצוב לתפוגה של ההתאמה לזמן ארוך יותר, מגדירים את spec.override.reconcileTimeout.
יכול להיות גם שהתלות תתואם אחרי שהניסיון הראשון לסנכרון יסתיים. במקרה כזה, התלות אמורה להיות מזוהה כמתואמת בניסיון הבא לסנכרון, וההחלה של כל התלויות תבוטל. במקרים כאלה, יכול להיות שהשגיאה תדווח לזמן קצר ואז תוסר. הארכת זמן הקצוב לתפוגה של ההתאמה עשויה לעזור למנוע את הדיווח על השגיאה לסירוגין.
אין פרטי מלאי
אם מופיעה השגיאה הבאה כש-reconciler מנסה להחיל הגדרות על האשכול, סביר להניח שאין משאבים במלאי או שבמניפסט יש הערה לא מנוהלת:
KNV2009: inventory info is nil\n\nFor more information, see https://g.co/cloud/acm-errors#knv2009
כדי לפתור את הבעיה, נסו את הפתרונות הבאים:
- כדי להימנע מהגדרת סנכרונים שבהם לכל המשאבים יש את האנוטציה
configmanagement.gke.io/managed: disabled, צריך לוודא שסנכרון תצורות מנהל לפחות משאב אחד. - מוסיפים את ההערה
configmanagement.gke.io/managed: disabledרק אחרי שמסיימים את הסנכרון הראשוני של המשאב בלי ההערה הזו.
תבניות מרובות של אובייקטים במלאי שטחי הפרסום
אם מופיעה השגיאה הבאה כשהמנגנון להתאמה מנסה להחיל הגדרות על האשכול, סביר להניח שיש לכם הגדרת מלאי שנוצרה על ידי kpt במקור המידע המהימן, למשל מאגר Git:
KNV2009: Package has multiple inventory object templates. The package should have one and only one inventory object template. For more information, see https://g.co/cloud/acm-errors#knv2009
הבעיה מתרחשת כי סנכרון תצורות מנהל את הגדרת המלאי שלו. כדי לפתור את הבעיה, צריך למחוק את הגדרת המלאי במקור המידע המהימן.
אי אפשר לשנות שדות שלא ניתנים לשינוי
אי אפשר לשנות שדה שלא ניתן לשינוי בקובץ תצורה על ידי שינוי הערך במקור המידע המהימן. אם תנסו לעשות את זה, תופיע הודעת שגיאה דומה לזו:
KNV2009: failed to apply RESOURCE: admission webhook "deny-immutable-field-updates.cnrm.cloud.google.com" denied the request: cannot make changes to immutable field(s):
אם אתם צריכים לשנות שדה שלא ניתן לשינוי, מחקו את האובייקט ממקור האמת, המתינו עד שסנכרון ההגדרות ימחק את האובייקט מהאשכול, ואז צרו מחדש את האובייקט במקור האמת עם העדכונים שלכם.
הדגימה של הסטטוס נכשלה
אתם יכולים לתת ל-סנכרון תצורות הרשאה לנהל משאבים במרחב שמות באמצעות אובייקט RepoSync. אם אובייקט RepoSync מהסוג הזה משתמש באובייקט RoleBinding שמפנה ל-ClusterRole או ל-Role בהתאמה אישית, יכול להיות שתופיע הודעת השגיאה הבאה מ-Reconciler Deployment:
KNV2009: polling for status failed: unknown
כדי לפתור את הבעיה, ודאו שלאובייקטים ClusterRole ו-Role יש לפחות את ההרשאות הבאות לכל משאב שמנוהל על ידי האובייקט RepoSync:
listwatchgetpatchdeletecreate
הוראות להוספת ההרשאות האלה מופיעות במאמר יצירת RoleBinding.
חיפוש ה-API נכשל
אם מופיעה הודעת שגיאה דומה לזו, יכול להיות שנתקלתם בשגיאה בגילוי ה-API:
KNV2002: API discovery failed: APIServer error: unable to retrieve the complete list of server APIs: external.metrics.k8s.io/v1beta1: received empty response for: external.metrics.k8s.io/v1beta1
סנכרון ההגדרות משתמש בגילוי של Kubernetes API כדי לחפש את המשאבים שנתמכים באשכול. כך סנכרון ההגדרות יכול לאמת את סוגי המשאבים שצוינו במקור, ולעקוב אחרי שינויים במשאבים האלה באשכול.
לפני גרסה 1.28 של Kubernetes, בכל פעם ש-backend של APIService לא היה תקין או החזיר תוצאה של רשימה ריקה, API Discovery נכשל, וגרם לשגיאה ב-סנכרון תצורות ובכמה רכיבים אחרים של Kubernetes. הרבה קצוות עורפיים נפוצים של APIService אינם עם זמינות גבוהה, ולכן זה יכול לקרות לעיתים קרובות יחסית, רק על ידי עדכון הקצה העורפי או תזמון מחדש שלו בצומת אחר.
דוגמאות לקצוות עורפיים של APIService עם רפליקה אחת כוללות את metrics-server ו-custom-metrics-stackdriver-adapter. חלק מה-backends של APIService תמיד מחזירים תוצאות של רשימה ריקה, כמו custom-metrics-stackdriver-adapter. סיבה נפוצה נוספת לכשל בזיהוי API היא תקינות לקויה של ה-webhooks.
אחרי גרסה 1.28 של Kubernetes, כשהתכונה Aggregated Discovery מופעלת, קצה עורפי לא תקין של APIService לא גורם יותר לשגיאות לא מטופלות. במקום זאת, קבוצת המשאבים שמטופלת על ידי אותו APIService מוצגת ללא משאבים. כך הסנכרון יכול להימשך, כל עוד המשאב הלא תקין לא צוין במקור.
תיקון עצמי מושהה
התיקון העצמי עוקב אחרי המשאבים המנוהלים, מזהה חריגה ממקור המידע המהימן ומתקן את החריגה.
התיקון העצמי מושהה בזמן ניסיון הסנכרון. המשמעות היא שייתכן עיכוב בתיקון העצמי, במיוחד אם יש שגיאות סנכרון שמונעות את השלמת ההתאמה. כדי להפעיל מחדש את התיקון העצמי, צריך לתקן את כל שגיאות הסנכרון שדווחו.
מספר גבוה של בקשות API של Kubernetes
בסנכרון תצורות נעשה שימוש באסטרטגיית כמה מופעים במקביל כדי לשנות את קנה המידה ולבודד דיירים ודומיינים של תקלות. לכן, לכל RootSync ו-RepoSync יש מכונת reconciler משלו. בנוסף לסנכרון בכל פעם שמתבצעים שינויים במקור, כל מופע של reconciler מסתנכרן גם באופן תקופתי כחלק מהתנהגות הריפוי העצמי שלו, כדי לבטל שינויים שהוחמצו על ידי תיקון הסטייה הפעיל. כשמוסיפים אובייקטים מסוג RootSync או RepoSync, יש עלייה לינארית במספר בקשות ה-API שנוצרות על ידי ה-reconcilers שמסנכרנים משאבים עם Kubernetes. לכן, אם יש לכם הרבה אובייקטים מסוג RootSync ו-RepoSync, לפעמים זה יכול לגרום לעומס תנועה משמעותי ב-Kubernetes API.
כדי לבצע סנכרון, Config Sync משתמש ב-Server-Side Apply. הפעולה הזו מחליפה את תהליך הבקשה הרגיל של GET ו-PATCH בבקשת PATCH אחת, וכך מפחיתה את המספר הכולל של הקריאות ל-API, אבל מגדילה את מספר הקריאות ל-PATCH. כך אפשר לוודא שהשינויים שבוצעו נכונים, גם אם גרסת קבוצת המשאבים במקור לא תואמת לגרסת ברירת המחדל של קבוצת המשאבים באשכול. עם זאת, יכול להיות שתראו בקשות PATCH ביומן הביקורת, גם אם לא היה שינוי במקור או חריגה מהמצב הרצוי. זה מצב רגיל, אבל הוא יכול להפתיע.
אם יש שגיאה בסנכרון, המערכת מנסה שוב עד שהסנכרון מצליח. אבל אם נדרשת אינטראקציה אנושית, יכול להיות שסנכרון ההגדרות יחזיר שגיאה וינסה שוב במשך זמן מה, מה שיגדיל את מספר הבקשות ל-Kubernetes API. הניסיונות החוזרים מתבצעים בהשהיה מעריכית, אבל אם הסנכרון של הרבה אובייקטים מסוג RootSync או RepoSync נכשל בו-זמנית, יכול להיות עומס תנועה משמעותי ב-Kubernetes API.
כדי לפתור את הבעיות האלה, נסו אחת מהאפשרויות הבאות:
- תקנו שגיאות בהגדרות במהירות, כדי שהן לא יצטברו.
- לשלב כמה אובייקטים של
RootSyncאוRepoSync, כדי לצמצם את מספר ה-reconcilers ששולחים בקשות ל-Kubernetes API.
הסרת ההתקנה של KubeVirt נחסמה על ידי פיינלייזרים
KubeVirt היא חבילת Kubernetes שמשתמשת בכמה פיינלייזרים, וצריך למחוק אותם בסדר מדויק כדי לבצע את הניקוי. אם אובייקטים של KubeVirt נמחקים בסדר הלא נכון, המחיקה של אובייקטים אחרים של KubeVirt עלולה להיתקע או להפסיק להגיב ללא הגבלת זמן.
אם ניסיתם להסיר את KubeVirt והוא נחסם, פעלו לפי ההוראות למחיקה ידנית של KubeVirt.
כדי למנוע את הבעיה הזו בעתיד, הצהירו על יחסי תלות בין אובייקטים של משאבים כדי לוודא שהם נמחקים בסדר הפוך ליחסי התלות.
מחיקת אובייקטים נחסמה על ידי פונקציות סופיות (finalizers)
מסיים (finalizer) של Kubernetes הוא רשומת מטא-נתונים שאומרת ל-Kubernetes לא לאפשר הסרה של אובייקט עד שבקר ספציפי יבצע ניקוי. זה יכול לגרום לכשל בסנכרון או בהתאמה, אם התנאים לניקוי לא מתקיימים או אם הבקר שמבצע את הניקוי של המשאב הזה לא תקין או נמחק.
כדי לפתור את הבעיה, צריך לזהות איזה משאב עדיין נמצא בתהליך סיום ואיזה בקר אמור לבצע את הניקוי.
אם הבקר לא תקין, תיקון שורש הבעיה אמור לאפשר את השלמת ניקוי המשאבים, ולבטל את החסימה של הסרת האובייקט.
אם הבקר תקין, הוא אמור להחיל תנאי סטטוס על האובייקט שנמחק כדי להסביר למה הניקוי נתקע. אם לא, בודקים ביומני הבקר אם יש אינדיקציות לשורש הבעיה.
בדרך כלל, אם אובייקט תקוע במצב מחיקה, זה סימן שהאובייקטים נמחקו בסדר הלא נכון. כדי למנוע בעיות כאלה בעתיד, הצהירו על יחסי תלות בין אובייקטים של משאבים, כדי לוודא שהם נמחקים בסדר הפוך ליחסי התלות.
השדות של ResourceGroup משתנים כל הזמן
כשמנסים לסנכרן, המלאי מתעדכן כדי לשנות את סטטוס המשאב ל"בהמתנה". אם הסנכרון נכשל, המלאי מתעדכן וסטטוס המשאב משתנה ל"נכשל". כשמנסים שוב לסנכרן אחרי שהסנכרון נכשל, התבנית הזו חוזרת על עצמה, וגורמת לעדכונים תקופתיים במלאי. זה גורם ל-ResourceGroup resourceVersion לגדול בכל עדכון, ולסטטוס הסנכרון להשתנות הלוך ושוב. זה מצב רגיל, אבל הוא יכול להפתיע.
יש כמה סיבות אפשריות לכשל בסנכרון. אחת הסיבות הנפוצות ביותר היא הרשאות לא מספיקות לניהול המשאבים שצוינו במקור. כדי לתקן את השגיאה, צריך להוסיף את ה-RoleBindings או ה-ClusterRoleBinding המתאימים כדי לתת למתאם RepoSync או RootSync הרשאה לנהל את המשאבים שהסנכרון שלהם נכשל.
סנכרון תצורות לא מסיר או מחזיר שדות שלא צוינו במקור
כדי להחיל מניפסטים מהמקור על Kubernetes, סנכרון ההגדרות משתמש ב-Server-Side Apply. הפעולה הזו נדרשת כדי לאפשר לבקרים אחרים לנהל את השדות metadata ו-spec. דוגמה אחת לכך היא Horizontal Pod Autoscaler (HPA), שמעדכן את מספר הרפליקות בפריסה. לכן, סנכרון ההגדרות מנהל רק את השדות שצוינו במניפסט המקור. כתוצאה מכך, כשמאמצים אובייקטים קיימים של משאבים, שדות שלא צוינו במקור לא משתנים, ולפעמים זה יכול לגרום לכך שההגדרה הממוזגת תהיה לא חוקית או שגויה.
כדי להימנע מהבעיה הזו כשמאמצים משאב, צריך להשתמש בדיוק באותם שדות במקור כשמאמצים אותו בפעם הראשונה, ואז לשנות את השדות במקור אחרי הסנכרון, כדי שסנכרון ההגדרות יסיר בצורה נכונה את השדות שהוחלו קודם ויחליף אותם בשדות החדשים מהמקור. דרך נוספת להימנע מהבעיה הזו היא למחוק קודם את המשאב מהאשכול, ולאפשר לסנכרון תצורות להחיל את הגרסה החדשה.
סנכרון ההגדרות לא שומר שדות מהחלה בצד הלקוח של kubectl כשמאמצים אובייקטים
מכיוון שסנכרון ההגדרות משתמש ב-Server-Side Apply, כשסנכרון ההגדרות מאמץ אובייקט שנוצר במקור באמצעות kubectl client-side apply, הוא מבטל את ההגדרה של כל השדות שהוגדרו באמצעות client-side apply אבל לא הוצהרו במקור.
אם אתם רוצים לשמור את השדות האלה, השתמשו באותם שדות בדיוק במקור כשאתם מאמצים את האובייקט בפעם הראשונה, או צרו את האובייקט באמצעות Server-Side Apply.
המאמרים הבאים
- אם אתם עדיין נתקלים בבעיות, כדאי לבדוק אם הבעיה היא בעיה ידועה.
אם לא מצאתם פתרון לבעיה במסמכי העזרה, תוכלו לקרוא את המאמר קבלת תמיכה כדי לקבל עזרה נוספת, כולל עצות בנושאים הבאים:
- לפתוח בקשת תמיכה באמצעות פנייה ל-Cloud Customer Care.
- לקבל תמיכה מהקהילה על ידי פרסום שאלות ב-Stack Overflow. אם אתם משתמשים ב-kpt או ב-Kustomize, השתמשו בתג
kptאוkustomizeכדי לחפש בעיות דומות. - דיווח על באגים או הגשת בקשות להוספת תכונות באמצעות Issue Tracker הציבורי ב-GitHub.