מדריך קלוד קוד בעברית

תיעוד 143

הפניה לסביבות באירוח עצמי

הפניה מלאה ל-runner ול-orchestrator באירוח עצמי: דגלי CLI, משתני סביבה ומדדי Prometheus.

[!NOTE]

סביבות באירוח עצמי נמצאות בבטא ציבורית בתוכניות Team ו-Enterprise. Owner מפעיל אותן על ידי הפעלת Allow self-hosted environments בדף הניהול Cloud environments. הדף הזה הוא ההפניה לדגלים ולמדדים. ראו את ה-quickstart להתקנה ואת Deploy to production למתכוני הצי.

הדף הזה הוא ההפניה לשני התהליכים שאתם מריצים בסביבה באירוח עצמי: ה-runner, שמריץ cloud sessions של Claude Code על המארחים שלכם, וה-orchestrator האופציונלי ל-autoscaling, שמתחיל runners כש-sessions נכנסים לתור. לכל אחד טבלת דגלים משלו. שניהם רצים על מארחי Linux או macOS, שהברירות המחדל כמו /workspace ו-~/.claude מניחות. הריצו claude self-hosted-runner --help לרשימה הסמכותית בגרסה המותקנת אצלכם.

סדרות מדדים וכמה שדות API עדיין משתמשים ב-pool למה שהדפים האלה קוראים environment. שני המונחים מציינים את אותו הדבר. מזהה ה-environment הוא השדה pool_id, בצורה ccpool_...: בכל מקום שהדפים האלה מציגים מזהה pool, הוא מציין את ה-environment. דגלי CLI ומשתני סביבה כותבים אותו environment, למשל --environment-secret-file. איותי pool שיצאו משימוש עדיין עובדים, כפי שמתארת השורה של --environment-secret-file.

#דגלי CLI של ה-runner

לרוב הדגלים יש משתנה סביבה מתאים. כששניהם מוגדרים, הדגל גובר. דגלי משך מקבלים דקות או שניות ב-CLI, אבל משתנה הסביבה המזווג תמיד במילישניות, כפי שמציינת הסיומת _MS, ועמודת ברירת המחדל מציגה את יחידת הדגל: --exit-if-unused-min 10 שקול ל-SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS=600000, וערך Helm כמו SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS: "15" פירושו 15 מילישניות, ולא ברירת המחדל של 15 דקות.

דגלמשתנה סביבהברירת מחדלתיאור
--api-url <url>איןhttps://api.anthropic.comכתובת בסיס של ה-API. לעקוף רק לצורך בדיקות.
--base-dir <path>SELF_HOSTED_RUNNER_BASE_DIR/workspace. אין ב-Windowsספרייה ל-checkouts של מאגרים ולספריות עבודה לפי סשן. ה-runner זקוק לגישת כתיבה לנתיב הזה או להורה שלו. ה-runner יוצר את הספרייה בהפעלה ויוצא עם cannot create or write to base directory כשהוא לא יכול ליצור אותה או לכתוב אליה. לפני v2.1.225, ה-runner יצר את הספרייה כשהסשן הראשון התחיל, כך שנתיב בלתי שמיש הכשיל סשנים ולא את ההפעלה. ב-Windows, שאינו מארח runner נתמך, אין ברירת מחדל: ה-runner יוצא בהפעלה אלא אם מעבירים את הדגל או מגדירים את המשתנה. השתמשו באותו ערך בכל runner בסביבה. ראו שמירה על ספריית הבסיס והקיבולת זהות בכל ה-runners.
--capacity <n>אין1מספר הסשנים המקבילים המרבי שה-runner הזה מטפל בהם. כל הסשנים שייכים לאותו בעלים נעול. השתמשו באותו ערך בכל runner בסביבה. ראו שמירה על ספריית הבסיס והקיבולת זהות בכל ה-runners.
--client-label <label>SELF_HOSTED_RUNNER_CLIENT_LABELשם המארח של המארחהתווית שה-runner שולח כשהוא נרשם. ה-runner גם מדווח אותה כתווית client_label של claude_code_self_hosted_runner_info. דורש Claude Code v2.1.248 או מאוחר יותר.
--configure-gitSELF_HOSTED_RUNNER_CONFIGURE_GIT=1כבויבהפעלה, כותב זהות git גלובלית, מפעיל חתימת commit של Anthropic, מדליק משא ומתן על git push, ומתקין commit hooks שמוסיפים trailer של Co-authored-by:. משא ומתן על push דורש Claude Code v2.1.257 או מאוחר יותר. ראו הגדרת git.
--confine-repo-settings <mode>SELF_HOSTED_RUNNER_CONFINE_REPO_SETTINGSwarnקובע את מצב השומר שמסמן סשן כשהגדרות שהמאגר commit-הן מנסות להעניק גישת כתיבה או קריאה מחוץ ל-workspace של אותו סשן, להגדיר משתני סביבה, או לעקוף את עמדת ה-sandbox או ה-hooks של המפעיל, למשל sandbox.enabled: false או disableAllHooks. ברירת המחדל warn רושמת את ההפרה ועדיין מתחילה את הסשן, enforce מסרב לסשן, ו-off משבית את הסריקה. ראו הקשחת הפריסה.
--debug-token-dir <path>SELF_HOSTED_RUNNER_DEBUG_TOKEN_DIRלא מוגדרכותב טוקנים חיים לדיסק לבדיקה. לדיבוג בלבד. אל תשתמשו בפרודקשן.
--defer-shutdown-max-min <n>SELF_HOSTED_RUNNER_DEFER_SHUTDOWN_MAX_MS0ב-SIGTERM או SIGINT הראשון, ממשיך לשרת את הסשנים שכבר מחוברים במקום לנקז אותם, ואז משחרר את מה שעדיין מחובר N דקות אחר כך ויוצא. העלו את פסק הזמן לעצירה של המארח לפני שאתם מגדירים את זה. ראו דחיית הניקוז מעבר לאות הראשון. 0 משבית. דורש Claude Code v2.1.238 או מאוחר יותר.
--drain-grace-sec <n>SELF_HOSTED_RUNNER_DRAIN_GRACE_MS0עד שה-runner מקבל אות כיבוי או מגיע לזמן הפרישה שלו, שולט מתי ה-runner יוצא אחרי שהסשנים הפעילים שלו מסתיימים: 0 יוצא מיד בלי polling לעוד עבודה, וערך חיובי משאיר את ה-runner חי ומבצע polling מחדש לתור של הבעלים הנעול במשך אותו מספר שניות קודם, במחיר בידוד הקונטיינר לפי סשן שמתואר במקטע ההקשחה. אחרי אות ראשון שדחיתם עם --defer-shutdown-max-min, ה-runner יוצא ברגע שאין לו סשנים, בלי קשר למה שהגדרתם כאן.
--drain-marker-file <path>SELF_HOSTED_RUNNER_DRAIN_MARKER_FILEלא מוגדרקובץ סמן שהמארח כותב כדי להודיע על ניקוז מסודר לפני שליחת SIGTERM. כשהקובץ קיים כשהניקוז מתחיל, ה-runner מדווח על היציאה שלו ל-Anthropic כניקוז מארח ולא כאות כיבוי רגיל. הניקוז עצמו, כולל ההמתנה של --drain-wait-sec, רץ אותו דבר כמו בלי הדגל. ציינו נתיב במערכת קבצים מקומית שסשנים לא יכולים לכתוב אליה. דורש Claude Code v2.1.271 או מאוחר יותר.
--drain-wait-sec <n>SELF_HOSTED_RUNNER_DRAIN_WAIT_MS0ברגע שהניקוז מתחיל, וזה ב-SIGTERM אלא אם הגדרתם --defer-shutdown-max-min, מחכה עד N שניות שתור בתהליך ומשימות רקע של כל סשן יסתיימו לפני סיום תהליך הילד. במהלך ההמתנה הזו, ה-runner סופר משימת רקע שזה עתה הסתיימה כעדיין רצה עד שהתור ההמשך שקורא את התוצאה שלה מתחיל, לכל היותר בחלון SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS. העלו גם את פסק הזמן לעצירה.
--environment-secret-file <path>SELF_HOSTED_RUNNER_ENVIRONMENT_SECRETנדרשנתיב לקובץ שמכיל את סוד הסביבה, או, עבור runners שה-orchestrator יצר, JWT חד-פעמי של work-order. SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET נושא את ערך הסוד ישירות, לא נתיב קובץ. הדגל הישן --pool-secret-file והמשתנה SELF_HOSTED_RUNNER_POOL_SECRET עדיין עובדים ומדפיסים הודעת deprecation ל-stderr. בניית runner של תוכנית התצוגה המקדימה ישנות מ-2.1.216 מזהות רק את השמות הישנים האלה.
--exec-path <path>SELF_HOSTED_RUNNER_EXEC_PATHהבינארי של עצמובינארי או סקריפט wrapper להפעלה עבור כל סשן. ראו סקריפטי wrapper.
--exit-if-unused-min <n>SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS0יוצא אחרי N דקות של polling בלי שעבודה הוקצתה אי פעם, לצמצום של autoscaler. 0 משבית.
--git-host-rewrite <from>=<to>איןלא מוגדרמשכתב כתובות מקור https://<from>/... ל-https://<to>/... לפני clone, עבור DNS מסוג split-horizon. ניתן לחזור עליו. דגל בלבד.
--git-ssh-rewrite <host>איןלא מוגדרמשכתב כתובות מקור https://<host>/... ל-git@<host>:... לפני clone, עבור מארחי git של SSH בלבד. ניתן לחזור עליו. דגל בלבד.
--health-port <port>SELF_HOSTED_RUNNER_HEALTH_PORT8080פורט למאזין /healthz ו-/metrics. הגדירו 0 כדי להשבית.
--hold-idle-file <path>SELF_HOSTED_RUNNER_HOLD_IDLE_FILEלא מוגדרקובץ שהמארח ממשיך לשנות כדי להחזיק סשן סרק על ה-runner. ראו שמירת סשן סרק בזמן שהתהליכים שלו רצים. דורש Claude Code v2.1.311 או מאוחר יותר.
--hooks-dir <path>SELF_HOSTED_RUNNER_HOOKS_DIRלא מוגדרספרייה של סקריפטי lifecycle hook. ראו ווי מחזור חיים.
--host-config-snapshot <mode>SELF_HOSTED_RUNNER_HOST_CONFIG_SNAPSHOTdiskאיפה ה-runner שומר את צילום ההפעלה של ספריית תצורת המארח שממנה הוא מזריע כל סשן. disk מעתיק את הצילום לספרייה בבעלות ה-runner תחת --base-dir, ובכל התחלת סשן מאמת כל קובץ מול digest בזיכרון. אם קובץ בעותק שונה, הסשן נכשל וה-runner מסרב לסשנים עד שמפעילים אותו מחדש. memory מחזיק את כל הצילום על ה-heap, עם תקרה של 64 MiB. מעל התקרה, סשנים מתחילים בלי תצורת מארח ומציגים הודעה שאומרת זאת. כשה-runner לא יכול לכתוב את צילום הדיסק, הוא רושם את הכשל ומשתמש ב-memory עבור הריצה הזו. דורש Claude Code v2.1.271 או מאוחר יותר.
--kill-session-after-min <n>SELF_HOSTED_RUNNER_MAX_LIFETIME_MS0מגביל סשן ל-N דקות של שעון קיר, כגבול בטיחות לסשנים תקועים. ב-v2.1.260 או מאוחר יותר, ה-runner משחרר סשן שמגיע לגבול כדי שיוכל להתחדש בהודעה הבאה של המשתמש שלו, ומסיים אותו רק אם הוא עדיין על ה-runner כשחלון החסד SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS מסתיים. לפני v2.1.260, ה-runner סיים את הסשן בגבול. ראו יש סשנים שלא נספרים כסרק לפרטים ולאופן בחירת ערך. 0 משבית.
--lock-to-account <id>SELF_HOSTED_RUNNER_LOCK_TO_ACCOUNTלא מוגדרנועל מראש את ה-runner לחשבון מסוים בהפעלה במקום נעילה בסשן הראשון. מקבל כתובת אימייל או מזהה user_... בארגון של הסביבה. runner שננעל מראש לעולם לא קולט סשני ערוץ Claude Tag, שאין להם חשבון.
--log-file <path>SELF_HOSTED_RUNNER_LOG_FILEלא מוגדרמשקף לוגים של ה-runner לקובץ בנוסף ל-stdout ול-stderr, שנוצר עם הרשאות 0600. נדרש כדי ש-self-hosted-runner doctor יעקוב אחרי לוגים מקומית.
--log-level <level>איןinfoinfo או debug
--max-hold-min <n>SELF_HOSTED_RUNNER_MAX_HOLD_MS1440עם --hold-idle-file, משחרר סשן מוחזק בכל מקרה N דקות אחרי שהוא עבר לסרק. ערך ששווה ל---release-idle-session-min או נמוך ממנו לא מחזיק כלום. 0 מכבה את ההחזקה. דורש Claude Code v2.1.311 או מאוחר יותר.
--post-session-hook-timeout-sec <n>SELF_HOSTED_RUNNER_POST_SESSION_HOOK_TIMEOUT_MS60תקציב ל-hook של post-session בכל סיום סשן, כולל כיבוי ה-runner
--proxy-authorization-command <command>SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_COMMANDלא מוגדרפקודת shell שה-runner מריץ עבור כל חיבור ל-egress proxy שלכם, ומשתמש ב-stdout הגזום שלה כערך כותרת Proxy-Authorization. דורש HTTPS_PROXY או HTTP_PROXY, ואי אפשר לשלב עם --proxy-authorization-file. ראו אימות מול egress proxy. דורש Claude Code v2.1.238 או מאוחר יותר.
--proxy-authorization-file <path>SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_FILEלא מוגדרקובץ שה-runner קורא עבור כל חיבור ל-egress proxy שלכם, ומשתמש בתוכן הגזום שלו כערך כותרת Proxy-Authorization. השתמשו בדגל הזה לטוקן שתהליך אחר מסובב במקום. נושא את אותן דרישות כמו --proxy-authorization-command, ואי אפשר לשלב איתו. ראו אימות מול egress proxy. דורש Claude Code v2.1.238 או מאוחר יותר.
--push-outcome-on-releaseSELF_HOSTED_RUNNER_PUSH_OUTCOME_ON_RELEASEכבויבסיום סשן שיזם ה-runner, כמו ניקוז או שחרור סרק, ה-runner דוחף ענפי סשן ראשיים עם commits חדשים ל-origin לפני מחיקת ה-workspace. במיטב היכולת. מוסיף 30 שניות לתקציב הכיבוי. דורש git 2.29 או מאוחר יותר כדי לחדש מהם. הגבילו גישת push ל-refs של claude/*. ראו סשנים שחודשו מאבדים עבודה שלא נדחפה. מאגרים של hook מסוג checkout לא נדחפים. צלמו אותם מ-hook של post-session.
--release-idle-session-min <n>SELF_HOSTED_RUNNER_SESSION_IDLE_MS0משחרר חריץ סשן אחרי N דקות של חוסר פעילות ברגע שתור מסתיים או שהסשן ממתין לפעולת המשתמש. יש סשנים שלא נספרים כסרק, לכן שלבו עם --kill-session-after-min. משימת רקע שהסתיימה משאירה את הסשן עסוק לכל היותר בחלון SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS. כדי לעכב שחרור, הגדירו --hold-idle-file. 0 משבית.
--remove-session-state [bool]SELF_HOSTED_RUNNER_REMOVE_SESSION_STATEכבוימסיר את ספריות לפי-סשן של סשן תחת <base-dir>/_sessions/ כשהסשן מסתיים על ה-runner הזה, בכל תוצאה. שימוש חוזר ב-checkout שחומם מראש מתאר מה הן מחזיקות ומי יכול לקרוא אותן כשהן נשארות. ההסרה היא במיטב היכולת: ספריות לפי-סשן נשארות במקום כשה-runner נהרג או מגיע למועד הניקוז לפני שהניקוי רץ. כשהדגל מופעל, לוג הדיבוג של סשן שנכשל או שנקטע לא נשמר על הדיסק. דורש Claude Code v2.1.268 או מאוחר יותר.
--retire-at <epoch-seconds>SELF_HOSTED_RUNNER_RETIRE_ATלא מוגדרפורש את ה-runner בחותמת זמן Unix מוחלטת בשניות, עבור תשתית שהורגת את ה-runner בזמן ידוע. מחזור החיים של ה-runner מתאר את רצף השחרור ואת אופן קביעת גודל השוליים. ערכים לפני 2001 או אחרי שנת 5138 נדחים על ידי הדגל ומתעלמים מהם במשתנה הסביבה.
--server-auto-mode-lists <mode>SELF_HOSTED_RUNNER_SERVER_AUTO_MODE_LISTSno-allowאילו מרשימות כללי המסווג של מצב אוטומטי שמישור הבקרה שולח עם סשן רשאיות להגיע לאותו סשן: all, no-allow, או none. ראו רשימות כללים של מצב אוטומטי למה כל ערך חל. ערך לא תקין עוצר את ה-runner בהפעלה. דורש Claude Code v2.1.295 או מאוחר יותר.
--session-stop-grace-sec <n>SELF_HOSTED_RUNNER_SESSION_STOP_GRACE_MS5כמה זמן להמתין שתהליך Claude ייצא בצורה נקייה אחרי שסשן מסתיים, לפני הריגה בכוח. העלו את הערך אם ה-hooks של SessionEnd של הילד עצמו זקוקים ליותר זמן.
--startup-timeout-min <n>SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS15כמה זמן להמתין על תהליך ילד שלא אותחל לפני שחרור החריץ של הסשן. ראו פסק זמן להפעלת סשן לאיפה הספירה מתחילה ואילו סשנים הוא משאיר רצים. 0 משבית את פסק הזמן.
--trust-workspace [bool]SELF_HOSTED_RUNNER_TRUST_WORKSPACEמופעלמזריע אמון שנשמר לנתיבי המאגר של כל סשן כדי ש-permissions.allow ו-additionalDirectories שהמאגר commit-הן יכובדו. הגדירו false כדי להשמיט הענקות הרשאה שהמאגר commit-הן ולהגדיר כללי allow ב-settings.json של תצורת המארח. הגדרות sandbox.* שהמאגר commit-הן עדיין חלות בכל מקרה, ולכן שומר הגדרות המאגר סורק אותן בלי קשר לדגל הזה.
--use-anthropic-git-proxyCLAUDE_RUNNER_USE_GIT_PROXY=1כבוימשכפל מאגרים ב-github.com דרך פרוקסי git של Anthropic במקום אימות git שמנוהל על ידי הלקוח. דורש --capacity 1 ו-git 2.32 או מאוחר יותר. ה-runner מסרב להתחיל אחרת. מחליף את דגלי השכתוב.

לרוב דגלי המשך יש מקסימום, שנבחר כדי לשמור כל פסק זמן בתוך תקרת הטיימר של 32 סיביות של זמן הריצה, בערך 24.85 ימים. דגלי --*-min מוגבלים ל-10080 דקות, 7 ימים. --drain-grace-sec ל-604800 שניות, גם 7 ימים. ו---drain-wait-sec ל-86400 שניות, 24 שעות. --session-stop-grace-sec ו---post-session-hook-timeout-sec בלי תקרה. חריגה מתקרה מתנהגת אחרת לפי משטח:

  • דגל: ההפעלה נכשלת עם שגיאה.
  • משתנה סביבה: ה-runner מצמיד את הערך לתקרת הטיימר במקום לדחות אותו.

#פסק זמן להפעלת סשן

אם סשן איבד את המשבצת שלו במהלך תור כמו /code-review, עדכנו את ה-runner ואת הבינארי של הילד ל-v2.1.309 או לגרסה חדשה יותר. מ-v2.1.299 ועד v2.1.308, ה-runner שחרר סשן, גם באמצע תור, ברגע שפסק הזמן להפעלה חלף בלי הודעת user או assistant.

עם --startup-timeout-min <n>, ה-runner משחרר את המשבצת של סשן כשהילד שלו לא אותחל בתוך <n> דקות אחרי השכפול. במהלך תור שמתחיל לפני שהילד מאותחל, הסשן שומר את המשבצת שלו עד שחולפות <n> דקות בלי שורה בערוץ הפעילות של הילד. מרגע שהילד מאותחל, ה-runner מאפס את הספירה הזו ו---release-idle-session-min קובע את השחרור. כדי להגביל סשן שהילד שלו חי אבל תקוע, הגדירו --kill-session-after-min.

#רשימות כללים של מצב אוטומטי

--server-auto-mode-lists מאפשר לכם להחליט אילו כללי מסווג של מצב אוטומטי שמחוץ ל-runner מגיעים אל הסשנים על ה-runners שלכם. מישור הבקרה של Anthropic יכול לשלוח רשימות כללים עם סשן ולבקש מה-runner להחיל אותן. ייתכן שחלק מהרשומות הן כללים שמנהל בארגון שלכם כתב. הרשימות הן environment, soft_deny ו-allow:

  • environment: רשומה יכולה לגרום למסווג להתיר יותר וגם פחות.
  • soft_deny: רשומה חוסמת פעולה אלא אם המשתמש ביקש אותה במפורש או שחל חריג allow.
  • allow: החריגים לרשומות soft_deny.

הערך של הדגל קובע אילו רשימות ה-runner מחיל:

  • no-allow: ברירת המחדל. מחיל את environment ואת soft_deny ואינו מחיל את allow. רשומת environment עדיין יכולה לגרום למסווג להתיר יותר, ולכן ברירת המחדל אינה שוללת כל הקלה.
  • all: מחיל את שלוש הרשימות.
  • none: אינו מחיל אף אחת מהן. בחרו none כדי לשלול כל הקלה מהרשימות האלה. הבחירה הזו גם מסירה את המגבלות של soft_deny.

אין הגדרה של ה-runner שגורמת למישור הבקרה לבקש מה-runner להחיל את הרשימות. כשהוא אינו מבקש, הסשנים אינם מקבלים רשימה, בכל ערך שתגדירו. כדי לראות איזה משני המקרים קרה, הפעילו את ה-runner עם --log-level debug. עבור כל סשן ה-runner כותב אז שורה שמכילה the server asked this runner to apply, או שורה שמכילה the server did not ask this runner to apply the auto mode lists it sends.

#דגלי CLI של ה-orchestrator

פקודת המשנה self-hosted-runner orchestrator, שיוצרת runners לפי דרישה, מקבלת את --api-url, --environment-secret-file, --hooks-dir, --health-port ו---log-level עם אותן ברירות מחדל כמו ה-runner, ובמקום שלדגל של ה-runner יש משתנה סביבה, עם אותו משתנה סביבה, חוץ מכך ש---hooks-dir נדרש וחייב להכיל hook בשם spawn-runner. יש לה גם דגלים משלה:

דגלברירת מחדלתיאור
--hook-concurrency <n>4מקסימום hooks של spawn-runner שרצים במקביל. גם מגביל כמה בקשות spawn נתפסות בכל poll. ה-orchestrator בודק בקשות spawn חדשות רק אחרי שכל hook שהוא התחיל הסתיים, ולכן hook איטי אחד מעכב את ה-hooks הבאים של אותו orchestrator.
--hook-timeout <sec>60מסיים את עץ התהליכים של ה-hook אחרי מספר השניות הזה. פסק הזמן ועוד 5 שניות הארכה להריגה חייבים להישאר מתחת ל---expected-spawn-seconds. ה-orchestrator אוכף זאת בהפעלה.
--expected-spawn-seconds <sec>120זמן p99 צפוי מהרגע שבו ה-orchestrator מקבל בקשת spawn עד שה-runner נרשם, כולל כל המתנה לקיבולת בפלטפורמה שלכם. השרת אוכף טווח של 10 עד 3600. נשלח בכל poll כחכירה בצד השרת. אם אף runner לא נרשם לפני שהזמן חולף, הסשן מוצע מחדש עם מזהה הזמנה חדש. כל הרפליקות חייבות לחלוק את הערך הזה.
--min-idle <n>0שומר לפחות N משבצות סשן פנויות על ידי יצירה יזומה של runners בהמתנה. 0 משבית חימום מראש. שלבו עם --exit-if-unused-min של ה-runner כדי ש-runners בהמתנה עודפים יפנו את עצמם.
--shutdown-drain-sec <n>0בעת SIGTERM, מפסיק poll לבקשות spawn ונותן ל-hooks של spawn-runner שרצים ולכל poll שלא נענה עד מספר השניות הזה כדי לסיים, לפני עצירה של מה שנשאר. בערך 0, עוצר מיד. המקסימום הוא 3600, וה-orchestrator אוכף זאת בהפעלה. כדי לבחור ערך, ראו קביעת גודל ל---shutdown-drain-sec ולפסק הזמן לעצירה של ה-orchestrator. נדרש Claude Code v2.1.299 או חדש יותר.
--debug-dir <path>לא מוגדרכותב לדיסק את הזמנת העבודה של כל בקשת spawn ואת stderr של ה-hook. לניפוי שגיאות בלבד. אל תגדירו בייצור.

#דגלי מחבר SCM

מחבר ה-SCM אינו זמין, לכן השאירו את הדגלים בסעיף זה לא מוגדרים. אם תגדירו --scm-connector-host, החיבור אינו נפתח, וה-orchestrator ממשיך לנסות אותו. runners עדיין מתחילים כשסשנים נכנסים לתור.

המחבר הוא חיבור WebSocket קבוע מה-orchestrator אל מישור הבקרה של Anthropic. הוא נועד לאפשר לזרימות מתארחות שלפני הסשן, כמו בוחר המאגר והפותר של ענף או ref, להגיע למארח GitHub Enterprise Server שאפשר לנתב אליו רק מתוך הרשת שלכם. ראו דרישות רשת בדף GitHub Enterprise Server לגבי מה שהזרימות האלה צריכות.

דגלברירת מחדלתיאור
--scm-connector-host <host[:port]>לא מוגדרשם מארח של GitHub Enterprise Server שאליו מעבירים בקשות. הפורט ברירת המחדל שלו היא 443.
--scm-connector-id <n>נדרש עם --scm-connector-hostהמזהה המספרי של חיבור GitHub Enterprise Server של הארגון שלכם.
--scm-connector-provider <slug>gheמקטע נתיב שמזהה את הספק, שתואם את ^[a-z0-9-]{1,32}$.
--scm-connector-ca-file <path>לא מוגדרחבילת CA נוספת, בפורמט PEM, לחיבורי TLS אל מארח GitHub Enterprise Server.
--scm-connector-host-rewrite <from>=<to_host:to_port>לא מוגדרלבדיקות מקצה לקצה בלבד: מפנה את חיבור ה-TCP, ושומר את כותרת Host ואת ה-SNI של TLS כמו --scm-connector-host.

בכל ניסיון חיבור ה-orchestrator שולח את סוד הסביבה הקיים שלו, והוא מנסה שוב אוטומטית עם השהיה מעריכית, עם תקרה של 30 שניות בתוספת jitter.

#הגדרות דרך משתני סביבה בלבד

הגדרות runner אלה נקראות מהסביבה בלבד ומכסות התנהגות שרוב הפריסות משאירות בברירת המחדל:

משתנה סביבהברירת מחדלתיאור
SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS30000כמה זמן ה-runner מחשיב סשן כעסוק אחרי שמשימת רקע מסתיימת, בזמן שתור ההמשך שקורא את התוצאה עוד לא התחיל. השורות של --drain-wait-sec ושל --release-idle-session-min מתארות איפה ההחזקה חלה בניקוז ובשחרור של חוסר פעילות, ומחזור חיי runner מתאר איפה היא חלה בפרישה לפי --retire-at. 0 או ערך לא שמיש חוזרים לברירת המחדל, ולכן אי אפשר לכבות את ההחזקה. נדרש Claude Code v2.1.228 או חדש יותר.
SELF_HOSTED_RUNNER_HOST_CONFIG_DIR~/.claudeספרייה שנלכדת בתמונת ההפעלה של ה-runner ונזרעת אל CLAUDE_CONFIG_DIR של כל סשן. שינויים בדיסק חלים אחרי הפעלה מחדש של ה-runner. הגדרת המשתנה גם מעבירה את המקום שממנו ה-runner קורא את .claude.json עבור זריעת MCP, ולכן הגדרה שלו, כולל לברירת המחדל של המשתנה עצמו, מעבירה את החיפוש הזה. הצביעו על ספרייה ריקה כדי לבטל את הזריעה לגמרי.
SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS900000כמה זמן ה-runner ממתין, אחרי שסשן מגיע למגבלת --kill-session-after-min שלו, לסיום של תור שרץ או להשלמת השחרור, לפני שהוא מסיים את הסשן
SELF_HOSTED_RUNNER_POST_TURN_SETTLE_MS7000תקרה למשך הזמן שבו ה-runner סופר סשן כעסוק לצורך ניקוז --drain-wait-sec אחרי שתור מסתיים, בזמן שתהליך הסשן מדווח ל-Anthropic על סיום התור. 0 או ערך לא שמיש חוזרים לברירת המחדל, ולכן אי אפשר לכבות את ההחזקה. נדרש Claude Code v2.1.275 או חדש יותר.
SELF_HOSTED_RUNNER_SIGKILL_GRACE_MS30000כמה זמן ה-runner ממתין שמערכת ההפעלה תמסור SIGKILL לילד שתקוע ב-I/O שאי אפשר להפריע לו, לפני שהוא יוצא בעצמו. הרצפה היא --post-session-hook-timeout-sec ועוד 15 שניות, ועוד 30 שניות כש---push-outcome-on-release מוגדר, ולכן המינימום בפועל הוא 75 שניות בברירות המחדל.
CLAUDE_RUNNER_FETCH_DEPTH50עומק ה-fetch של Git עבור שכפולים חדשים. הגדירו מספר שלם חיובי, או full או 0, ל-fetch מלא. עבור שכפול שכבר נמצא במרחב העבודה, ראו שימוש חוזר ב-checkout שחומם מראש.
CLAUDE_RUNNER_FETCH_SERVER_PROGRESS_CAP_MS600000כמה זמן, במילישניות ולכל ניסיון, fetch של git רשאי לחכות לנתונים הראשונים שלו בזמן שמספרי ההתקדמות של שרת ה-git עצמו ממשיכים לעלות, כמו כשהשרת מכין את ה-pack למאגר גדול. 0 או off מכבים את ההמתנה. fetch כזה נחתך אז אחרי שתי דקות בלי נתונים. כל מספר שלם אחר מוגבל לטווח שבין 120000 ל-1800000, 2 עד 30 דקות. נדרש Claude Code v2.1.295 או חדש יותר.
CLAUDE_RUNNER_SKIP_GIT_VERIFYלא מוגדרכאשר הערך הוא 1, מדלגים על בדיקת קיום .git אחרי שרץ hook של checkout. הגדירו זאת כשה-hook שלכם מממש מקור שאינו git.
FORCE_AUTOUPDATE_PLUGINSלא מוגדרכאשר הערך הוא 1, מאפשרים לשוקי התוספים להתעדכן אוטומטית גם כשהבינארי מקובע
CLAUDE_CODE_DISABLE_ARTIFACTלא מוגדרכאשר הערך הוא 1, משביתים את כלי Artifact בסשנים בלי קשר להגדרת המנהל של הארגון, ומסירים את דרישת היציאה של *.frame.claudeusercontent.com

#טלמטריה

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

בקרה אחת ייחודית לסביבות באירוח עצמי: CLAUDE_CODE_BYOC_ENABLE_DATADOG=1 מפעיל הצטרפות למדדים תפעוליים של Datadog, שכבויים כברירת מחדל בסביבות באירוח עצמי. בקרי הטלמטריה הכלליים של Claude Code, DISABLE_TELEMETRY, DO_NOT_TRACK, DISABLE_ERROR_REPORTING ו-CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, חלים על ילדי הסשן כפי שמתועד בהפניה למשתני סביבה. DISABLE_GROWTHBOOK קשור אבל שונה: הגדרת DISABLE_GROWTHBOOK=1 משביתה שליפה של דגלי תכונות, והטלמטריה נשארת פעילה אלא אם מוגדר גם DISABLE_TELEMETRY.

CLAUDE_CODE_ENABLE_TELEMETRY אינו קשור: הוא מפעיל ייצוא OpenTelemetry אל האספן שלכם, כפי שמתואר בניטור, ואינו שולט באנליטיקה של Anthropic.

#נקודת קצה לתקינות

ה-runner מגיש GET /healthz בפורט התקינות שהוגדר. התגובה היא 200 OK בכל פעם שהתהליך חי, בכל מצב שבו נמצאת לולאת ה-poll, ולכן בדיקת HTTP על נקודת הקצה הזו מזהה רק תהליך מת. גוף ה-JSON מתאר את המצב הנוכחי:

{
  "status": "ok",
  "runner_id": "ccrunner_...",
  "active_sessions": 2,
  "last_poll_at": "2026-03-31T18:04:11.220Z",
  "last_poll_age_ms": 842
}

התריעו על last_poll_age_ms, ואל תשתמשו בו בבדיקת חיות. השאירו את הבדיקה הזו על קוד המצב של HTTP. הערך הוא הזמן שעבר מאז ה-poll המוצלח האחרון, ולכן הוא עולה גם כשה-runner לא יכול להגיע אל Anthropic. גם last_poll_at וגם last_poll_age_ms הם null עד שה-poll הראשון מצליח. כדי לתפוס polls שנכשלים כבר מההתחלה, התריעו גם על claude_code_self_hosted_runner_poll_errors_total, שרשום תחת מדדי Prometheus.

נקודת /healthz של ה-orchestrator עצמו, על פורט התקינות שלו, תמיד מחזירה 200. הגוף כולל שדה connected שמדווח אם ה-poll האחרון הצליח, ובנוסף ספירות של תור spawn לפי מצב ב-queue_counts. כדי לראות למה connected הוא false, קראו את השדה last_error ברמה העליונה. כל poll מוצלח מאפס אותו ל-null. התנו מוכנות והתראות לפי connected ולא לפי קוד המצב.

כשמחבר SCM מוגדר, גוף /healthz של ה-orchestrator כולל גם את scm_connector_connected ואובייקט scm_connector עם connected, last_connected_at, last_error, reconnects ו-requests_forwarded. שני השדות הם null כש---scm-connector-host אינו מוגדר.

#מדדי Prometheus

כל runner מגיש מדדי Prometheus ב-GET /metrics על אותה יציאה כמו /healthz. סדרות מרכזיות:

סדרההערות
claude_code_self_hosted_runner_info{runner_id,version,client_label}תמיד 1. שימושי למלאי הצי ולזיהוי סטיית גרסאות
claude_code_self_hosted_runner_capacityה---capacity שהוגדר
claude_code_self_hosted_runner_active_sessionsסשנים שרצים כרגע
claude_code_self_hosted_runner_locked_account{email}מופיעה ברגע שה-runner ננעל למשתמש והונפק אסימון סשן שנושא claim בשם act.email. הסדרה נעדרת ב-runner שננעל לסוכן Claude Tag, שאסימוני הסשן שלו אינם נושאים act.email. ערך התווית הוא כתובת הדוא"ל של החשבון. אם מאגר המדדים שלכם קריא לקהל רחב, השמיטו או בצעו hash לתווית בזמן ה-scrape, למשל עם metric_relabel_configs של Prometheus.
claude_code_self_hosted_runner_last_poll_age_secondsשניות מאז ה-poll המוצלח האחרון. התריעו אם מעל 60.
claude_code_self_hosted_runner_poll_errors_total{error_kind}כשלי PollWork מצטברים לפי סוג: transport, timeout, 5xx, 429, או 4xx. כל חמש הסדרות קיימות מתחילת התהליך. התריעו על rate(...[5m]) > 0.
claude_code_self_hosted_runner_sessions_started_total{client_platform}תהליכי בן של סשנים שהופעלו לאורך חיי ה-runner, סדרה אחת לכל מקור סשן כגון web_claude_ai, ios, android, desktop_app, או claude_code_cli, או unknown כשהשרת לא שלח מקור. סשני Slack נושאים claude_in_slack או claude-in-slack, לפי אינטגרציית Slack שיצרה אותם, ולכן התאימו את שניהם עם בורר regex כגון {client_platform=~"claude[-_]in[-_]slack"}. השתמשו ב-sum() לסך של הצי.
claude_code_self_hosted_runner_sessions_completed_total{client_platform}סשנים שהסתיימו בצורה נקייה, עם אותן תוויות. רחב יותר מיציאה נקייה רגילה: ראו סמנטיקה של מוני מחזור חיי סשן לגבי מה נספר.
claude_code_self_hosted_runner_sessions_failed_total{client_platform}סשנים שהסתיימו בכשל, עם אותן תוויות. אותה הסתייגות: ראו סמנטיקה של מוני מחזור חיי סשן.
claude_code_self_hosted_runner_sessions_interrupted_total{client_platform}סשנים שה-runner סיים מסיבה תפעולית ולא בגלל תוצאת הסשן, עם אותן תוויות. ראו סמנטיקה של מוני מחזור חיי סשן.
claude_code_self_hosted_runner_initializing_sessionsסשנים שנמצאים כרגע בשלב ה-init, מההקצאה ועד אירוע ה-init של תהליך הבן
claude_code_self_hosted_runner_session_init_duration_secondsהיסטוגרמה של משכי init של סשן
claude_code_self_hosted_runner_session_init_errors_totalסשנים שנכשלו לפני שהגיעו ל-init: כשל של checkout hook, הכנת git, בעיה באסימון, או קריסת תהליך בן לפני init
claude_code_self_hosted_runner_session_start_hook_errors_totalhooks של SessionStart שדיווחו על תוצאת שגיאה, אחד לכל הרצת hook שנכשלה
claude_code_self_hosted_runner_session_idle_seconds{session_id,client_platform}gauge לכל סשן של שניות מאז שהסשן עבר למצב idle. שימושי לסיום סשנים שנתקעו על בקשת הרשאה שלא נענתה.

ה-orchestrator מגיש סדרות משלו ב-GET /metrics על אותה יציאה כמו ה-/healthz שלו:

סדרההערות
claude_code_self_hosted_orchestrator_info{version,pool_id,orchestrator_uuid,hostname}תמיד 1
claude_code_self_hosted_orchestrator_connected1 כשה-poll האחרון הצליח. יורד ל-0 אחרי כל poll שנכשל, מכל סוג כשל
claude_code_self_hosted_orchestrator_last_poll_age_secondsשניות מאז ניסיון ה-poll האחרון, הצלחה או כשל, בניגוד למדד בעל אותו שם אצל ה-runner, שמודד את הזמן מאז ההצלחה האחרונה. שלבו עם connected כדי לתפוס polls שנכשלים. לולאת ה-poll של ה-orchestrator ממתינה לביצוע hook, ולכן התריעו מעל --hook-timeout בתוספת מרווח, בסביבות 90 שניות בברירות המחדל, במקום ערך קבוע של 60.
claude_code_self_hosted_orchestrator_poll_errors_total{error_kind}כשלי PollSpawnHints מצטברים לפי סוג: transport, timeout, 5xx, 429, או 4xx. כל חמש הסדרות קיימות מתחילת התהליך. התריעו על rate(...[5m]) > 0.
claude_code_self_hosted_orchestrator_queue_pending_sessionsבקשות spawn שאפשר לתבוע עכשיו
claude_code_self_hosted_orchestrator_queue_backing_off_sessionsבקשות spawn ב-backoff של ניסיון חוזר אחרי כשל hook שניתן לחזור עליו
claude_code_self_hosted_orchestrator_queue_circuit_broken_sessionsסשנים חסומים מ-spawn. כל אחד נשאר חסום עד שמשתמש שולח לו הודעה חדשה, או עד ש-Owner מנסה שוב מלשונית Activity של הסביבה. הספירה יכולה להישאר מעל אפס אחרי תיקון הסיבה. התריעו אם היא מעל אפס.
claude_code_self_hosted_orchestrator_pool_pending_sessionsסך הסשנים שממתינים ל-runner עבור הסביבה הזו. צבירה לכל הסביבה, זהה בכל מופע של orchestrator: השתמשו ב-MAX ולא ב-SUM בין המופעים.
claude_code_self_hosted_orchestrator_pool_active_sessionsסשנים שמוקצים כרגע ל-runner חי בסביבה הזו. צבירה לכל הסביבה, זהה בכל מופע של orchestrator: השתמשו ב-MAX ולא ב-SUM בין המופעים.
claude_code_self_hosted_orchestrator_spawn_hooks_total{result}תוצאות מצטברות של hook בשם spawn-runner: ok, retryable, non_retryable. סופר הפעלות hook של ה-orchestrator, לא תהליכי בן של סשן שה-runners מפעילים. אי אפשר להשוות ל-sessions_started_total, כי קיבולת גבוהה מאחת, מאגרי warm, ו-runners שמופעלים שוב לאותו סשן, כולם מרחיקים בין השניים.
claude_code_self_hosted_orchestrator_spawn_hook_duration_secondsהיסטוגרמה של משכי hook
claude_code_self_hosted_orchestrator_warm_hints_dispatched_totalבקשות spawn במצב standby שנשלחו מאז תחילת התהליך
claude_code_self_hosted_orchestrator_session_queue_wait_secondsהיסטוגרמה של מספר השניות שכל סשן המתין בתור לפני שה-orchestrator תבע אותו ל-spawn, נרשמת לפי חותמת הזמן של ההמתנה בתור שמישור הבקרה שולח עם בקשת ה-spawn של כל סשן. השתמשו להתראות על זמן תור ב-p50 וב-p99. הפעלות spawn של pre-warming אינן נדגמות.
claude_code_self_hosted_orchestrator_clock_skew_secondsהטיית שעון של מקומי פחות שרת. לצורכי אבחון, ומופיעה אחרי שנמדדה
claude_code_self_hosted_orchestrator_scm_connector_connected1 כש-WebSocket של מחבר SCM פתוח. 0 בזמן חיוג או בזמן backoff. נעדרת כש---scm-connector-host אינו מוגדר.
claude_code_self_hosted_orchestrator_scm_connector_requests_forwarded_totalבקשות HTTP מצטברות שתווכו אל מארח ה-SCM המוגדר מאז תחילת התהליך. נעדרת כש---scm-connector-host אינו מוגדר.

לצורך autoscaling, בחרו את הסדרה שתואמת את סגנון ה-scaling שלכם, וסננו אותה לפני שהיא מזינה את ה-scaler:

  • scaling לפי עומק תור: הזינו את claude_code_self_hosted_orchestrator_pool_pending_sessions ל-scaler של HPA או של KEDA, ולא את queue_pending_sessions.
  • scaling לפי קיבולת: בצעו scaling לפי היחס בין active_sessions של ה-runner לבין capacity.
  • סינון לפי connected: סננו את השאילתה עם claude_code_self_hosted_orchestrator_connected == 1 לכל מופע, כדי שערך מיושן של replica מנותק לא יזין את ה-scaler.

בזמן השבתה מלאה של poll, כשכל replica מנותק, השאילתה המסוננת לא מחזירה נתונים. HPA שומר על מספר ה-replicas הנוכחי כשהמדד חסר, אבל ה-Prometheus scaler של KEDA, בברירת המחדל ignoreNullValues: "true", קורא את התוצאה הריקה כאפס ומבצע scale in. הגדירו ignoreNullValues: "false" ב-ScaledObject, ואפשר גם עם רצפת replicas ב-fallback.

ה-PodMonitor הבא של Prometheus Operator מכסה את שני התהליכים. הוא בוחר pods לפי התווית app.kubernetes.io/part-of: claude-code-self-hosted-runner ולפי היציאה בשם health שמתכון Kubernetes מגדיר. התאימו את ה-namespaces לפריסה שלכם:

# Example Prometheus Operator PodMonitor for the Claude Code self-hosted
# runner + orchestrator. Adjust the namespace and label selectors to match
# your deployment. Both the runner and the orchestrator serve /metrics on
# their --health-port (default 8080).
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: claude-code-self-hosted-runner
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames:
      - claude-runners
  selector:
    matchExpressions:
      # Matches the runner Deployment from the Kubernetes recipe, plus any
      # on-demand runner Jobs and orchestrator pods you label the same way
      # and give a named 'health' containerPort.
      - key: app.kubernetes.io/part-of
        operator: In
        values: [claude-code-self-hosted-runner]
  podMetricsEndpoints:
    - port: health
      path: /metrics
      interval: 30s

#כללי התראה לדוגמה

כללי ההתראה לדוגמה האלה הם נקודת התחלה. כווננו את הספים לגודל הצי שלכם:

# Example Prometheus alert rules for the Claude Code self-hosted runner
# + orchestrator. Tune thresholds for your fleet size and SLOs.
groups:
  - name: claude-code-self-hosted-runner
    rules:
      - alert: ClaudeRunnerPollStale
        expr: claude_code_self_hosted_runner_last_poll_age_seconds > 60
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Runner {{ $labels.pod }} has not polled in >60s"
      - alert: ClaudeRunnerVersionDrift
        expr: count(count by (version) (claude_code_self_hosted_runner_info)) > 1
        for: 30m
        labels: {severity: info}
        annotations:
          summary: "Runners are running mixed versions"
      - alert: ClaudeRunnerInitErrorsHigh
        expr: sum by (namespace) (increase(claude_code_self_hosted_runner_session_init_errors_total[10m])) > 3
        for: 5m
        labels: {severity: warning}
        annotations:
          summary: "Sessions are failing before init (checkout hook / git / token / pre-init crash)"
      - alert: ClaudeRunnerPollErrors
        expr: sum by (pod) (rate(claude_code_self_hosted_runner_poll_errors_total[5m])) > 0
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Runner {{ $labels.pod }}: PollWork failing ({{ $value | humanize }}/s over 5m)"
      - alert: ClaudeRunnerSessionStartHookErrors
        expr: sum by (namespace) (increase(claude_code_self_hosted_runner_session_start_hook_errors_total[10m])) > 3
        for: 5m
        labels: {severity: warning}
        annotations:
          summary: "SessionStart hooks are failing"

  - name: claude-code-self-hosted-orchestrator
    rules:
      - alert: ClaudeOrchestratorDisconnected
        expr: claude_code_self_hosted_orchestrator_connected == 0
        for: 2m
        labels: {severity: critical}
        annotations:
          summary: "Orchestrator {{ $labels.pod }} cannot reach the Anthropic control plane"
      - alert: ClaudeOrchestratorPollStale
        expr: claude_code_self_hosted_orchestrator_last_poll_age_seconds > 90
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Orchestrator {{ $labels.pod }} has not polled in >90s (poll loop waits on hook execution)"
      - alert: ClaudeOrchestratorCircuitBroken
        expr: max by (namespace) (claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions and on (instance) max_over_time(claude_code_self_hosted_orchestrator_connected[2m]) == 1) > 0
        for: 1m
        labels: {severity: critical}
        annotations:
          summary: "Sessions blocked from spawning: {{ $value }}. Read each one's error in the Activity tab, fix the cause, then select Retry"
      - alert: ClaudeOrchestratorPollErrors
        expr: sum by (pod) (rate(claude_code_self_hosted_orchestrator_poll_errors_total[5m])) > 0
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Orchestrator {{ $labels.pod }}: PollSpawnHints failing ({{ $value | humanize }}/s over 5m)"
      - alert: ClaudeOrchestratorSpawnHookFailing
        expr: sum by (pod) (increase(claude_code_self_hosted_orchestrator_spawn_hooks_total{result!="ok"}[5m])) > 3
        for: 5m
        labels: {severity: warning}
        annotations:
          summary: "Orchestrator {{ $labels.pod }}: >3 spawn-runner hook failures in 5m"

#התראה על runners שאבדו ועל סשנים ממתינים

כדי לקבל התראה כש-runners אבדו, סשנים ממתינים, או שה-orchestrator לא פעיל, טענו את כללי ההתראה האלה של Prometheus לצד כללי ההתראה לדוגמה:

#התראה כשצי קבוע מאבד runners

ClaudeRunnersBelowFloor מופעל כשמספר ה-runners הרשומים שנגרדו נמוך מהרצפה במשך 10 דקות:

groups:
  # Fixed fleets only. With on-demand runners the count follows demand,
  # so ClaudeRunnersBelowFloor would fire whenever demand is low.
  - name: claude-code-self-hosted-fixed-fleet-capacity
    rules:
      - alert: ClaudeRunnersBelowFloor
        expr: (count(claude_code_self_hosted_runner_info{namespace="claude-runners"}) or vector(0)) < 2
        for: 10m
        labels: {severity: critical, namespace: claude-runners}
        annotations:
          summary: "Runners registered and scraped: {{ $value }}, below the floor. Check the runner workloads first, then the scrape targets if all are running."
  • רצפה: הגדירו את 2 ב-expr לכמחצית מספר ה-replicas, מעוגל כלפי מעלה. עם שלושה replicas השאירו 2, וההתראה מופעלת כשנותר runner אחד או אף אחד.
  • Namespace: החליפו את claude-runners ב-matcher וב-labels, והעתיקו את ההתראה לכל namespace נוסף. אם ליעדים שלכם אין תווית namespace, הסירו את ה-matcher ואת התווית, אחרת ההתראה קוראת 0 ומופעלת.
  • ClaudeRunnerPollStale ו-ClaudeRunnerPollErrors: השאירו אותם טעונים מתוך כללי ההתראה לדוגמה, כי ClaudeRunnersBelowFloor עדיין סופר runner שלא יכול לבצע poll

#התראה כשסשנים ממתינים ל-runners לפי דרישה

ClaudeOrchestratorSessionsWaiting מופעל כשמספר הסשנים שממתינים ל-runner נשאר מעל 0 במשך 10 דקות. ClaudeOrchestratorQueueWaitHigh מופעל כשיותר מ-1% מההמתנות בתור ב-10 הדקות האחרונות חרגו מ-160 שניות, וזה נמשך 5 דקות:

groups:
  # On-demand runners only. Needs no edit for the namespace.
  - name: claude-code-self-hosted-on-demand-capacity
    rules:
      - alert: ClaudeOrchestratorSessionsWaiting
        expr: |
          max by (namespace) (
            claude_code_self_hosted_orchestrator_pool_pending_sessions
            and on (instance)
            max_over_time(claude_code_self_hosted_orchestrator_connected[2m]) == 1
          ) > 0
        for: 10m
        labels: {severity: warning}
        annotations:
          summary: "Sessions waiting for a runner: {{ $value }}, above the threshold for 10 minutes. Check claude_code_self_hosted_orchestrator_spawn_hooks_total by result, then runner workloads that don't start."
      - alert: ClaudeOrchestratorQueueWaitHigh
        expr: |
          histogram_quantile(0.99, sum by (namespace, le) (
            rate(claude_code_self_hosted_orchestrator_session_queue_wait_seconds_bucket[10m])
          )) > 160
        for: 5m
        labels: {severity: warning}
        annotations:
          summary: "Over 1% of queue waits in the last 10 minutes exceeded 160 seconds. Check whether ClaudeOrchestratorDisconnected is firing, then claude_code_self_hosted_orchestrator_spawn_hooks_total by result and claude_code_self_hosted_orchestrator_spawn_hook_duration_seconds."
  • סף: אם סשן כלשהו תמיד ממתין, העלו את > 0 ב-ClaudeOrchestratorSessionsWaiting מעל המספר שאתם רואים בדרך כלל
  • ClaudeOrchestratorDisconnected: השאירו אותו טעון מתוך כללי ההתראה לדוגמה, כי ClaudeOrchestratorSessionsWaiting מפסיק להיות מופעל כ-2 דקות אחרי שה-orchestrator האחרון ב-namespace מתנתק

#התראה כשה-orchestrator לא פעיל

כדי לדעת שה-orchestrator עצמו לא פעיל, טענו את ClaudeOrchestratorAbsent. הוא מופעל כשאף orchestrator ב-namespace לא נגרד במשך 5 דקות:

groups:
  # On-demand runners only. Replace claude-runners with the orchestrator's namespace.
  - name: claude-code-self-hosted-on-demand-orchestrator
    rules:
      - alert: ClaudeOrchestratorAbsent
        expr: absent(claude_code_self_hosted_orchestrator_connected{namespace="claude-runners"})
        for: 5m
        labels: {severity: critical}
        annotations:
          summary: "No orchestrator has been scraped for 5 minutes. If it's down, no on-demand runner starts, and sessions wait. Check the orchestrator workload first, then its scrape target if it's running."
  • Namespace: החליפו את claude-runners ב-namespace של ה-orchestrator, והעתיקו את ההתראה לכל namespace נוסף שמריץ orchestrator. אם ליעדים שלכם אין תווית namespace, הסירו את ה-matcher, אחרת ההתראה מופעלת אחרי 5 דקות ונשארת פעילה.
  • שרתי Prometheus שלא גורדים את ה-orchestrator: השאירו את ההתראה מחוץ לקובצי הכללים שלהם, כי בשרת כזה היא מופעלת אחרי 5 דקות ונשארת פעילה
  • אל תסתמכו על ההתראות האחרות של ה-orchestrator: הן קוראות מדדים שה-orchestrator עצמו מגיש. ClaudeOrchestratorSessionsWaiting, ClaudeOrchestratorQueueWaitHigh וכללי ההתראה לדוגמה של ה-orchestrator מפסיקים כולם להיות מופעלים בתוך כ-10 דקות מרגע שה-orchestrator יורד.

#העברת מדדי תהליך בן של סשן

כל סשן רץ בתהליך בן משלו עם מדדי OpenTelemetry משלו. כש---capacity מעל אחד, ה-runner משכתב את אופן החשיפה של מדדי הבן האלה. הגדרת OTEL_METRICS_EXPORTER=prometheus על מארח ה-runner ו-CLAUDE_CODE_ENABLE_TELEMETRY=1 בסביבת הסשן, למשל מתוך סקריפט העטיפה או מסביבת ה-runner עצמו, שסשנים יורשים, חושפת מחדש את מכשירי ה-counter וה-gauge של כל בן בנקודת הקצה /metrics של ה-runner עצמו, לצד הסדרות של ה-runner. ה-runner משכתב את ה-exporter של הבן כך שידחוף ב-OTLP למקלט על loopback בלבד בפורט הבריאות, מתייג כל סדרה בתוויות session_id ו-client_platform, ומפנה את הסדרות של סשן כשהסשן מסתיים. היסטוגרמות לא עוברות, ומדד בן ששמו היה מתנגש עם הקידומת של ה-runner עצמו מושמט.

ברירת המחדל --capacity 1, השכתוב לא חל: תהליך הבן של הסשן קושר נקודת קצה Prometheus משלו בפורט 9464 כרגיל.

#צירוף מדדי סשן למדדי ה-runner

כדי לראות מה עלו סשנים במצב idle, צרפו את claude_code_self_hosted_runner_session_idle_seconds של ה-runner למדד העלות של Claude Code על ccr_session_id. למדד של ה-runner אין את התווית הזאת, אז תנו לו אחת עם label_replace, כמו בשאילתה הזאת:

sum by (ccr_session_id) (claude_code_cost_usage_total)
and on (ccr_session_id)
label_replace(
  claude_code_self_hosted_runner_session_idle_seconds > 600,
  "ccr_session_id", "cse_$1", "session_id", "session_(.*)"
)

השאילתה מחזירה תוצאה אחת לכל סשן ב-idle יותר מעשר דקות: העלות בדולר אמריקאי שתהליך Claude Code שלו ספר עד כה. כדי לצרף מדד Claude Code אחר, החליפו את claude_code_cost_usage_total בשאילתה. השאילתה עובדת בכל --capacity.

  • session_id: בפורט 9464, התווית הזאת על מדדי Claude Code מחזיקה את session.id של Claude Code עצמו, שלא תואם לאף סדרה של ה-runner. צירוף עליה לא מחזיר כלום, אז צרפו על ccr_session_id.
  • למדדי Claude Code אין ccr_session_id: בדקו ש-OTEL_METRICS_INCLUDE_SESSION_ID לא מוגדר ל-false

#סמנטיקה של מוני מחזור חיי סשן

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

  • completed: הסשן הסתיים בצורה נקייה. זה מכסה יציאה עצמית של הבן עם קוד 0, ארכוב או מחיקה של הסשן בזמן שהבן עדיין היה מחובר, והחזרה נקייה של המשבצת על ידי ה-runner: שחרור הסשן ב-timeout של idle, בזמן ה-retire, או במגבלת --kill-session-after-min, timeout של הפעלה, או deassign מצד השרת שלולאת ה-poll הבחינה בו לפני שהבן יצא. מגדיל את sessions_completed_total.
  • failed: הבן יצא בעצמו עם קוד שאינו אפס, קריסה או כשל הגדרה אחרי spawn. מגדיל את sessions_failed_total.
  • interrupted: ה-runner סיים את הבן מסיבה תפעולית שהיא לא הצלחת סשן ולא תקלה של ה-runner, למשל drain, או סיום סשן שעדיין היה על ה-runner כשחלון החסד SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS אחרי מגבלת --kill-session-after-min שלו הסתיים. הפעלה מחדש מתגלגלת ב-Kubernetes ששולחת SIGTERM היא דוגמה אחת ל-drain. מגדיל את sessions_interrupted_total.

לפני v2.1.260, ה-runner סיים כל סשן שהגיע למגבלת --kill-session-after-min שלו וספר אותו ב-sessions_interrupted_total.

CLAUDE_RUNNER_EXIT_REASON של ה-hook מסוג post-session מסווג מסירות נקיות אחרת. ה-hook מדווח על אלה כ-interrupted, כי ה-runner עצר את הבן: שחרור, timeout של הפעלה, deassign מהשרת, וארכוב או מחיקה שה-poll הבחין בהם קודם. המונים האלה רושמים את אותם אירועים כ-completed, כי המשבצת הוחזרה בצורה נקייה.

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

בסביבה חד פעמית, --capacity 1 עם ברירת המחדל --drain-grace-sec 0, כל תהליך runner יוצא רגעים אחרי שהסשן היחיד שלו מסתיים. sessions_completed_total, sessions_failed_total ו-sessions_interrupted_total גדלים רק בסוף הסשן, ממש לפני היציאה הזאת, כך ש-scrape של Prometheus כל 15 עד 60 שניות כמעט לא תופס את ההגדלה לפני שסדרות ה-runner נעלמות. שלושת מוני סוף הסשן האלה הם המונים הסופיים ששאר הסעיף הזה מתייחס אליהם. sessions_started_total גדל ב-spawn ונשאר גלוי למשך חיי הסשן, ולכן הוא מופיע באופן אמין, אבל בסביבה חד פעמית הוא קרוב יותר ל"סשנים שרצים כרגע" מאשר לספירה מצטברת.

השתמשו בסדרות בטבלה הזאת למטרה המתאימה במקום במונים הסופיים:

מטרהשימוש
תפוקהclaude_code_self_hosted_orchestrator_spawn_hooks_total{result="ok"}, מונה על ה-orchestrator ארוך החיים שגדל פעם אחת לכל hook מוצלח מסוג spawn-runner ונשאר משמעותי תחת rate(). הוא סופר הפעלות hook ולא סשנים, ולכן חימום מראש ו-spawn חוזר לאותו סשן מרחיקים אותו מספירות הסשנים.
ניצולתsum(claude_code_self_hosted_runner_active_sessions) מול sum(claude_code_self_hosted_runner_capacity), שני gauges תקפים בכל scrape בלי קשר למשך חיי ה-runner
צברclaude_code_self_hosted_orchestrator_pool_pending_sessions לעומק התור, ו-claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions, עם התראה אם מעל אפס
כשליםclaude_code_self_hosted_runner_sessions_failed_total, במאמץ סביר: קריסות אמיתיות אחרי spawn כן מגדילות אותו, ו-rate() משמעותי על runners שמאריכים ימים אחרי הסשנים שלהם עם --drain-grace-sec מעל 0. לסביבה חד פעמית יש אותה בעיית חלון scrape כמו למונים הסופיים האחרים, אז התייחסו לכל ערך שאינו אפס שכן רואים כדבר שכדאי לחקור. כשלים לפני spawn, כמו כשל hook של checkout, הכנת git, או בעיית token, מופיעים רק ב-session_init_errors_total.

שורות orchestrator_* קיימות רק בסביבות שמריצות את ה-orchestrator לפי דרישה. בצי קבוע שה-runners שלו מאריכים ימים אחרי הסשנים, עם --drain-grace-sec מעל 0, השתמשו ב-sum(rate(claude_code_self_hosted_runner_sessions_started_total[5m])) לתפוקה. בצי חד פעמי לסדרה הזאת יש אותה בעיית חלון scrape כמו למונים הסופיים, אז הסתמכו במקום זאת על ספירת הסשנים בתור. בדקו צבר בלשונית Activity של הסביבה, בדף הניהול Cloud environments: ה-runners לא מייצאים סדרת עומק תור.

לדיווח תוצאה לכל סשן, השתמשו ב-hook מסוג post-session: הוא מופעל בכל סוף סשן שבו נוצר תהליך בן, מלבד סיום פתאומי של ה-runner כמו preemption של VM, לפי החוזה של ה-hook עצמו.

#מה הלאה