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

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

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

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

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

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

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

אפשר להעניק ל-Config Sync הרשאה לנהל משאבים במרחב שמות באמצעות אובייקט RepoSync. אם אובייקט מסוג 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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

‫סנכרון תצורות לא שומר שדות מ-kubectl apply בצד הלקוח כשמאמצים אובייקטים

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

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

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

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

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