פתרון בעיות בסנכרון הגדרות לאשכול

בדף הזה מוסבר איך לפתור בעיות בסנכרון של הגדרות לאשכול.

פתרון בעיות שקשורות ל-KNV 2009

שגיאות KNV2009 מציינות ש-Config Sync לא הצליח לסנכרן חלק מההגדרות עם האשכול. בקטעים הבאים מוסברות כמה מהסיבות הנפוצות ביותר לשגיאות ואיך לפתור אותן.

הפעולה אסורה במשאבים מסוימים

מכיוון שצריך להעניק לאובייקטים של RepoSync את ה-RBAC שלהם, יכול להיות שחסרות להם ההרשאות הדרושות להחלת משאבים.

כדי לוודא שההרשאות חסרות, אפשר לקבל את סטטוס המשאב RepoSync:

kubectl get reposync repo-sync -n NAMESPACE -o yaml

מחליפים את NAMESPACE במרחב השמות שבו יצרתם את מאגר מרחב השמות.

אפשר גם להשתמש בפקודה nomos status.

אם אתם רואים את ההודעות הבאות בסטטוס, המשמעות היא שלרכיב ה-reconciler ב-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 שמעניקה לחשבון השירות של הכלי לתיקון שגיאות הרשאה לניהול המשאב שנכשל במרחב השמות הזה. פרטים על הוספת 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. כך, Config Sync מפסיק לעדכן את הסטטוס של המשאבים המנוהלים באובייקט ResourceGroup. הפעולה הזו מקטינה את הגודל של אובייקט ResourceGroup. עם זאת, אי אפשר לראות את הסטטוס של משאבים מנוהלים מ-nomos status.

אם לא מוצגת שגיאה באובייקט RootSync או באובייקט RepoSync, סימן שהאובייקטים ממקור האמת סונכרנו עם האשכול. כדי לבדוק אם משאב ResourceGroup חורג ממגבלת הגודל של אובייקט etcd, בודקים את הסטטוס של משאב ResourceGroup ואת היומן של בקר ResourceGroup:

  1. בודקים את הסטטוס של 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 עדיין נמצא בתהליך התאמה.

  2. בודקים את היומנים של 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 Sync לא יכול להחיל את האובייקט התלוי כי עם ההערה config.kubernetes.io/depends-on,‏ Config Sync מחיל רק אובייקטים בסדר הרצוי. אפשר לשנות את ברירת המחדל של הזמן הקצוב לתפוגה של תהליך ההתאמה לזמן ארוך יותר על ידי הגדרת spec.override.reconcileTimeout.

יכול להיות גם שהתלות תסתנכרן אחרי שהניסיון הראשוני לסנכרון יסתיים. במקרה כזה, התלות אמורה להופיע כמתואמת בניסיון הבא לסנכרון, וכך לאפשר את החלת התלויות. במקרה כזה, יכול להיות שהשגיאה תדווח לזמן קצר ואז תוסר. הארכת זמן ההמתנה לסיום ההתאמה עשויה לעזור למנוע את הדיווח על השגיאה לסירוגין.

פרטי המלאי הם nil

אם אתם מקבלים את השגיאה הבאה כשכלי ההתאמה מנסה להחיל הגדרות על האשכול, סביר להניח שבמלאי שלכם אין משאבים או שבמניפסט יש הערה לא מנוהלת:

KNV2009: inventory info is nil\n\nFor more information, see https://g.co/cloud/acm-errors#knv2009

כדי לפתור את הבעיה, נסו את הפתרונות הבאים:

  1. כדי להימנע מהגדרת סנכרונים שבהם לכל המשאבים יש את ההערה configmanagement.gke.io/managed: disabled, צריך לוודא שלפחות משאב אחד מנוהל על ידי Config Sync.
  2. מוסיפים את ההערה configmanagement.gke.io/managed: disabled רק אחרי השלמת סנכרון ראשוני של המשאב בלי ההערה הזו.

תבניות מרובות של אובייקטים של מלאי שטחי פרסום

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

הבעיה מתרחשת כי Config Sync מנהל את הגדרת המלאי שלו. כדי לפתור את הבעיה, צריך למחוק את הגדרות המלאי במקור האמת.

אי אפשר לשנות שדות שלא ניתן לערוך

אי אפשר לשנות שדה שלא ניתן לשינוי בהגדרה על ידי שינוי הערך במקור האמת. ניסיון לבצע שינוי כזה גורם לשגיאה דומה לזו שמופיעה בהמשך:

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):

אם אתם צריכים לשנות שדה שלא ניתן לשינוי, אתם צריכים למחוק את האובייקט ממקור האמת, לחכות עד ש-Config Sync ימחק את האובייקט מהאשכול ואז ליצור מחדש את האובייקט במקור האמת עם העדכונים שלכם.

הדגימה של הסטטוס נכשלה

אפשר להשתמש באובייקט RepoSync כדי להעניק ל-Config Sync הרשאה לנהל משאבים במרחב שמות. אם אובייקט מסוג RepoSync משתמש באובייקט RoleBinding שמפנה אל ClusterRole או אל Role בהתאמה אישית, יכול להיות שתקבלו את הודעת השגיאה הבאה מהפריסה של Reconciler:

KNV2009: polling for status failed: unknown

כדי לפתור את הבעיה, צריך לוודא שלאובייקטים ClusterRole ו-Role יש לפחות את ההרשאות הבאות לכל משאב שמנוהל על ידי האובייקט RepoSync:

  • list
  • watch
  • get
  • patch
  • delete
  • create

הוראות להוספת ההרשאות האלה זמינות במאמר בנושא יצירת 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

‫Config Sync משתמש בKubernetes API discovery כדי לחפש אילו משאבים נתמכים על ידי האשכול. כך Config Sync יכול לאמת את סוגי המשאבים שצוינו במקור ולעקוב אחרי המשאבים האלה כדי לזהות שינויים באשכול.

לפני גרסה 1.28 של Kubernetes, בכל פעם שקצה עורפי של APIService היה לא תקין או החזיר תוצאה של רשימה ריקה, גילוי ה-API נכשל, מה שגרם לשגיאה ב-Config Sync וברכיבים אחרים של Kubernetes. הרבה שרתי קצה עורפיים נפוצים של APIService לא זמינים מאוד, ולכן זה יכול לקרות יחסית לעיתים קרובות, רק על ידי עדכון שרת הקצה העורפי או תזמון מחדש שלו בצומת אחר.

דוגמאות לקצה עורפי של APIService עם עותק יחיד כוללות את metrics-server ו-custom-metrics-stackdriver-adapter. חלק מהקצה העורפי של APIService תמיד מחזיר תוצאות של רשימה ריקה, כמו custom-metrics-stackdriver-adapter. סיבה נפוצה נוספת לכשל בגילוי ממשקי API היא שימוש ב-webhook לא תקין.

אחרי גרסה 1.28 של Kubernetes, כשהתכונה 'גילוי מצטבר' מופעלת, קצה עורפי לא תקין של APIService כבר לא גורם לשגיאות לא מטופלות. במקום זאת, קבוצת המשאבים שמטופלת על ידי APIService לא תכלול משאבים. כך הסנכרון יכול להימשך, כל עוד המשאב הבעייתי לא מצוין במקור.

תיקון עצמי מושהה

שעונים עם תיקון עצמי מנהלים משאבים, מזהים סטיות ממקור האמת ומבטלים את הסטיות האלה.

התיקון העצמי מושהה בזמן שמנסים לבצע סנכרון. המשמעות של ההתנהגות הזו היא שתיקון עצמי עלול להתעכב, במיוחד אם יש שגיאות סנכרון שמונעות מהכלי להשלים את הפעולה. כדי להפעיל מחדש את התיקון העצמי, צריך לתקן את כל השגיאות בסנכרון שדווחו.

מספר גבוה של בקשות ל-Kubernetes API

‫Config Sync משתמש באסטרטגיית ריבוי מופעים כדי להרחיב ולבודד דיירים ודומיינים של תקלות. לכן, לכל RootSync ו-RepoSync יש מופע משלו של כלי ההתאמה. בנוסף לסינכרון בכל פעם שמתבצעים שינויים במקור, כל מופע של כלי התיקון מסתנכרן גם באופן תקופתי כחלק מההתנהגות של התיקון העצמי, כדי לבטל שינויים שהוחמצו על ידי התיקון הפעיל של הסטיות. כשמוסיפים אובייקטים מסוג RootSync או RepoSync, מספר בקשות ה-API ששולחים תהליכי ה-reconciler לסנכרון משאבים עם Kubernetes גדל באופן לינארי. לכן, אם יש לכם הרבה אובייקטים מסוג RootSync ו-RepoSync, לפעמים זה עלול לגרום לעומס תנועה משמעותי ב-Kubernetes API.

כדי לבצע סנכרון, Config Sync משתמש ב-Server-Side Apply. הבקשה הזו מחליפה את התהליך הרגיל של בקשות GET ו-PATCH בבקשת PATCH אחת, וכך מצמצמת את המספר הכולל של קריאות ל-API, אבל מגדילה את מספר קריאות ה-PATCH. כך תוכלו לוודא שהשינויים שביצעתם נכונים, גם אם גרסת קבוצת המשאבים במקור לא תואמת לגרסת קבוצת המשאבים שמוגדרת כברירת מחדל באשכול. עם זאת, יכול להיות שתראו בקשות PATCH ביומן הביקורת, גם אם לא בוצע שינוי במקור או חריגה מהמצב הרצוי. זהו מצב רגיל, אבל הוא יכול להפתיע.

אם הסנכרון נכשל, המערכת מנסה שוב עד שהוא מצליח. עם זאת, אם נדרשת אינטראקציה אנושית, יכול להיות ש-Config Sync יחזיר שגיאה וינסה שוב במשך זמן מה, וכך יגדיל את מספר הבקשות שנשלחות ל-Kubernetes API. הניסיונות החוזרים מתבצעים בהשהיה אקספוננציאלית, אבל אם הרבה אובייקטים מסוג RootSync או RepoSync לא מצליחים להסתנכרן בו-זמנית, זה עלול לגרום לעומס תנועה משמעותי ב-Kubernetes API.

כדי לפתור את הבעיות האלה, אפשר לנסות את אחת מהאפשרויות הבאות:

  • כדאי לתקן שגיאות בהגדרות במהירות, כדי שלא יצטברו.
  • משלבים כמה אובייקטים מסוג RootSync או RepoSync כדי לצמצם את מספר כלי ההתאמה ששולחים בקשות ל-Kubernetes API.

הסרת ההתקנה של KubeVirt נחסמה על ידי finalizers

‫KubeVirt הוא חבילת Kubernetes שמשתמשת בכמה finalizers, ולכן נדרש סדר מחיקה מדויק כדי לאפשר ניקוי. אם אובייקטים של KubeVirt נמחקים בסדר לא נכון, יכול להיות שמחיקה של אובייקטים אחרים של KubeVirt תיעצר או שהם יפסיקו להגיב לזמן בלתי מוגבל.

אם ניסיתם להסיר את KubeVirt וההסרה נחסמה, צריך לפעול לפי ההוראות למחיקה ידנית של KubeVirt.

כדי לצמצם את הבעיה הזו בעתיד, צריך להצהיר על תלות בין אובייקטים של משאבים כדי לוודא שהם נמחקים בסדר הפוך של התלות.

חסימת מחיקת אובייקט על ידי finalizers

רכיבי finalizer ב-Kubernetes הם רשומות מטא-נתונים שמציינות ל-Kubernetes שאסור להסיר אובייקט עד שרכיב בקרה ספציפי יבצע ניקוי. אם התנאים לניקוי לא מתקיימים או אם ה-controller שמבצע את הניקוי של המשאב הזה לא תקין או נמחק, יכול להיות שהסנכרון או התיאום ייכשלו.

כדי לפתור את הבעיה, צריך לזהות איזה משאב עדיין נמצא בתהליך סיום ואיזה בקר צריך לבצע את הניקוי.

אם הבקר לא תקין, תיקון שורש הבעיה אמור לאפשר את השלמת הניקוי של המשאב, ובכך לבטל את החסימה של הסרת האובייקט.

אם הבקר תקין, הבקר אמור להחיל תנאי סטטוס על האובייקט שנמחק כדי להסביר למה הניקוי נתקע. אם לא, בודקים את היומנים של הבקר כדי לזהות את שורש הבעיה.

לעתים קרובות, אם אובייקט נתקע בתהליך המחיקה, זה סימן שהאובייקטים נמחקו בסדר הלא נכון. כדי למנוע בעיות כאלה בעתיד, מגדירים תלות בין אובייקטים של משאבים כדי לוודא שהם נמחקים בסדר הפוך של התלות.

השדות של ResourceGroup ממשיכים להשתנות

כשמנסים לסנכרן, המלאי מתעדכן וסטטוס המשאב משתנה ל'בהמתנה'. אם הסנכרון נכשל, המלאי מתעדכן וסטטוס המשאב משתנה ל-failed (נכשל). כשמנסים שוב לסנכרן אחרי שהסנכרון נכשל, התבנית הזו חוזרת על עצמה, וכך מתבצעים עדכונים תקופתיים למלאי. כתוצאה מכך, הערך של ResourceGroup [קבוצת משאבים] resourceVersion גדל עם כל עדכון, וסטטוס הסנכרון משתנה שוב ושוב. זהו מצב רגיל, אבל הוא יכול להפתיע.

יש כמה סיבות אפשריות לכשל בסנכרון. אחת הסיבות הנפוצות ביותר היא היעדר הרשאות מספיקות לניהול המשאבים שצוינו במקור. כדי לתקן את השגיאה הזו, צריך להוסיף את RoleBindings או ClusterRoleBinding המתאימים כדי להעניק למנגנון RepoSync או RootSync את הרשאת הגישור לניהול המשאבים שלא מצליחים להסתנכרן.

Config Sync לא מסיר או מחזיר שדות שלא צוינו במקור

‫Config Sync משתמש ב-Server-Side Apply כדי להחיל מניפסטים מהמקור על Kubernetes. הפעולה הזו נדרשת כדי לאפשר לבקרים אחרים לנהל את השדות metadata ו-spec. דוגמה אחת לכך היא Horizontal Pod Autoscaler (HPA), שמעדכן את מספר הרפליקות בפריסה. לכן, Config Sync מנהל רק את השדות שצוינו במניפסט המקור. התוצאה היא שאם מאמצים אובייקטים קיימים של משאבים, שדות שלא צוינו במקור לא משתנים, ולפעמים זה יכול לגרום לכך שההגדרה הממוזגת לא תהיה תקפה או נכונה.

כדי להימנע מהבעיה הזו כשמאמצים משאב, צריך להשתמש באותם שדות בדיוק במקור כשמאמצים אותו בפעם הראשונה, ואז לשנות את השדות במקור אחרי הסנכרון, כדי ש-Config Sync יסיר בצורה נכונה את השדות שהוא החיל קודם ויחליף אותם בשדות החדשים מהמקור. דרך נוספת להימנע מהבעיה הזו היא למחוק קודם את המשאב מהאשכול ולאפשר ל-Config Sync להחיל את הגרסה החדשה.

‫Config Sync לא שומר שדות מ-kubectl client-side apply כשמאמצים אובייקטים

מכיוון ש-Config Sync משתמש ב-Server-Side Apply, כשהוא מאמץ אובייקט שנוצר במקור באמצעות kubectl client-side apply, הוא מבטל את ההגדרה של כל השדות שהוגדרו באמצעות client-side apply אבל לא הוגדרו במקור.

אם רוצים לשמור את השדות האלה, צריך להשתמש באותם שדות בדיוק במקור כשמאמצים את האובייקט בפעם הראשונה, או ליצור את האובייקט באמצעות Server-Side Apply.

המאמרים הבאים

  • אם הבעיות נמשכות, כדאי לבדוק אם הבעיה שנתקלתם בה היא בעיה מוכרת.

אם לא מצאתם פתרון לבעיה שלכם במסמכי התיעוד, אפשר להיעזר במקורות המידע הבאים: