자체 호스팅 환경은 Team 및 Enterprise 플랜에서 공개 베타 상태이며, Owner가 Cloud environments 관리자 페이지에서 Allow self-hosted environments를 켜서 활성화합니다. 이 페이지는 플래그 및 메트릭 참조이며, 설정은 빠른 시작을 참조하고 프로덕션 배포는 Deploy to production에서 플릿 레시피를 참조하세요.
/workspace 및 ~/.claude와 같은 기본값을 가정합니다. 설치된 버전에서 권한 있는 목록을 보려면 claude self-hosted-runner --help를 실행하세요.
메트릭 시리즈 및 일부 API 필드는 여전히 이 페이지에서 환경이라고 부르는 것을 pool이라고 사용합니다. 두 용어 모두 동일한 것을 나타냅니다. 환경 ID는 pool_id 필드이며, ccpool_... 형식입니다: 이 페이지에서 pool 식별자를 표시하는 곳마다 환경을 나타냅니다. CLI 플래그 및 환경 변수는 --environment-secret-file과 같이 environment로 표기합니다. 더 이상 사용되지 않는 pool 표기법은 여전히 작동하며, --environment-secret-file 행에서 설명합니다.
러너 CLI 플래그
대부분의 플래그에는 대응하는 환경 변수가 있습니다. 둘 다 설정되면 플래그가 우선합니다. 기간 플래그는 CLI에서 분 또는 초 단위 값을 받지만, 짝을 이루는 환경 변수는_MS 접미사가 나타내듯 항상 밀리초 단위이며, 기본값 열은 플래그의 단위를 표시합니다. --exit-if-unused-min 10은 SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS=600000과 같으며, SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS: "15"와 같은 Helm 값은 기본값인 15분이 아니라 15밀리초를 의미합니다.
대부분의 기간 플래그에는 최댓값이 있으며, 이는 각 타임아웃을 런타임의 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에는 상한이 없습니다. 상한을 초과했을 때의 동작은 사용 환경에 따라 다릅니다.
- 플래그: 오류와 함께 시작이 실패합니다.
- 환경 변수: 러너가 값을 거부하지 않고 타이머 상한으로 제한합니다.
세션 시작 타임아웃
/code-review와 같은 턴 도중 세션이 슬롯을 잃었다면 러너와 자식 바이너리를 v2.1.309 이상으로 업데이트하십시오. v2.1.299부터 v2.1.308까지는 user 또는 assistant 메시지 없이 시작 타임아웃이 지나면 러너가 턴 도중이라도 세션을 해제했습니다.
--startup-timeout-min <n>을 사용하면, 클론 이후 <n>분 이내에 자식 프로세스가 초기화되지 않을 때 러너가 세션 슬롯을 해제합니다. 자식 프로세스가 초기화되기 전에 시작된 턴 동안에는, 자식 프로세스의 활동 채널에 아무 줄도 없는 상태로 <n>분이 지날 때까지 세션이 슬롯을 유지합니다. 자식 프로세스가 초기화되면 러너는 해당 카운트를 초기화하며, 이후 해제는 --release-idle-session-min이 관리합니다. 자식 프로세스가 살아 있지만 멈춘 세션을 제한하려면 --kill-session-after-min을 설정하십시오.
자동 모드 규칙 목록
--server-auto-mode-lists를 사용하면 러너 외부에서 오는 자동 모드 분류기 규칙 중 어떤 것이 러너의 세션에 도달할지 결정할 수 있습니다. Anthropic의 컨트롤 플레인은 세션과 함께 규칙 목록을 보내고 러너에 이를 적용하도록 요청할 수 있습니다. 일부 항목은 조직의 관리자가 작성한 규칙일 수 있습니다. 목록은 environment, soft_deny, allow입니다.
environment: 항목은 분류기가 더 많이 허용하게 할 수도 있고 더 적게 허용하게 할 수도 있습니다.soft_deny: 항목은 사용자가 명시적으로 요청했거나allow예외가 적용되는 경우를 제외하고 작업을 차단합니다.allow:soft_deny항목에 대한 예외입니다.
no-allow: 기본값입니다.environment와soft_deny를 적용하고allow는 보류합니다.environment항목은 여전히 분류기가 더 많이 허용하게 할 수 있으므로, 기본값이 모든 완화를 배제하지는 않습니다.all: 세 가지 목록을 모두 적용합니다.none: 어떤 목록도 적용하지 않습니다. 이러한 목록으로 인한 모든 완화를 배제하려면none을 선택하십시오. 이 경우soft_deny제한도 함께 제외됩니다.
--log-level debug로 러너를 시작하십시오. 그러면 러너는 각 세션에 대해 the server asked this runner to apply가 포함된 줄 또는 the server did not ask this runner to apply the auto mode lists it sends가 포함된 줄을 로그에 기록합니다.
오케스트레이터 CLI 플래그
self-hosted-runner orchestrator 서브명령은 on-demand runners를 생성하며, --api-url, --environment-secret-file, --hooks-dir, --health-port 및 --log-level을 러너와 동일한 기본값으로 허용하며, 러너의 플래그에 하나가 있는 경우 동일한 환경 변수를 허용합니다. 단, --hooks-dir은 필수이며 spawn-runner 훅을 포함해야 합니다. 또한 자체 플래그를 사용합니다:
SCM 커넥터 플래그
SCM 커넥터를 사용할 수 없으므로 이 섹션의 플래그를 설정하지 않은 상태로 두세요.--scm-connector-host를 설정하면 연결이 열리지 않으며 오케스트레이터는 계속 재시도합니다. 러너는 여전히 세션 큐로 시작합니다.
커넥터는 오케스트레이터에서 Anthropic의 제어 평면으로의 상시 WebSocket 연결입니다. 저장소 선택기 및 분기 또는 ref 리졸버와 같은 호스팅된 사전 세션 흐름이 네트워크 내부에서만 라우팅 가능한 GitHub Enterprise Server 호스트에 도달할 수 있도록 설계되었습니다. GitHub Enterprise Server 페이지의 네트워크 요구 사항을 참조하여 이러한 흐름에 필요한 사항을 확인하세요.
각 연결 시도 시 오케스트레이터는 기존 환경 비밀을 전송하며, 30초 플러스 지터로 제한되는 지수 백오프를 사용하여 자동으로 재시도합니다.
환경 변수 전용 설정
이러한 러너 설정은 환경에서만 읽으며 대부분의 배포가 기본값으로 남겨두는 동작을 다룹니다:텔레메트리
세션 자식은 끄지 않으면 Anthropic에 운영 텔레메트리를 전송합니다. 코드 또는 저장소 내용은 전송되지 않습니다. 러너 프로세스에서 텔레메트리 변수를 설정하세요. 러너는 서버 제공 환경 변수를 적용한 후 다시 주장하므로 운영자의 설정이 항상 우선합니다. 한 가지 제어는 자체 호스팅 환경에만 해당됩니다:CLAUDE_CODE_BYOC_ENABLE_DATADOG=1은 Datadog 운영 메트릭을 옵트인하며, 이는 자체 호스팅 환경에서 기본적으로 꺼져 있습니다. 일반 Claude Code 텔레메트리 제어인 DISABLE_TELEMETRY, DO_NOT_TRACK, DISABLE_ERROR_REPORTING 및 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC은 environment variable reference에서 문서화된 대로 세션 자식에 적용됩니다. DISABLE_GROWTHBOOK은 관련이 있지만 다릅니다: DISABLE_GROWTHBOOK=1을 설정하면 기능 플래그 페칭이 비활성화되고, DISABLE_TELEMETRY도 설정되지 않으면 텔레메트리가 켜져 있습니다.
CLAUDE_CODE_ENABLE_TELEMETRY는 관련이 없습니다: Monitoring에서 설명한 대로 자신의 수집기로 OpenTelemetry 내보내기를 활성화하며, Anthropic의 분석을 제어하지 않습니다.
상태 엔드포인트
러너는 구성된 상태 포트에서GET /healthz를 제공합니다. 응답은 프로세스가 살아 있을 때마다 200 OK이며, 폴 루프가 어떤 상태에 있든 관계없이, 이 엔드포인트의 HTTP 프로브는 죽은 프로세스만 감지합니다. JSON 본문은 현재 상태를 설명합니다:
last_poll_age_ms를 생존 신호로 사용하세요. 무한정 증가하는 값은 폴 루프가 고착되었음을 나타냅니다. last_poll_at 및 last_poll_age_ms 모두 첫 번째 폴이 완료될 때까지 null입니다.
상태 포트에서 제공되는 오케스트레이터 자체의 /healthz는 항상 200을 반환합니다. 본문은 가장 최근 폴이 성공했는지 여부를 보고하는 connected 필드와 queue_counts의 상태별 스폰 큐 수를 전달합니다. connected가 false인 이유를 확인하려면 최상위 last_error 필드를 읽으세요. 이 필드는 폴이 성공할 때마다 null로 재설정됩니다. 상태 코드가 아닌 connected에 준비 및 경고를 게이트하세요.
SCM connector가 구성되면, 오케스트레이터의 /healthz 본문도 scm_connector_connected 및 connected, last_connected_at, last_error, reconnects 및 requests_forwarded를 포함하는 scm_connector 객체를 전달합니다. --scm-connector-host가 설정되지 않으면 두 필드 모두 null입니다.
Prometheus 메트릭
각 러너는/healthz와 같은 포트의 GET /metrics에서 Prometheus 메트릭을 제공합니다. 주요 시리즈는 다음과 같습니다.
오케스트레이터는 자체
/healthz와 같은 포트의 GET /metrics에서 자체 시리즈를 제공합니다.
오토스케일링에는 스케일링 방식에 맞는 시리즈를 선택하고, 스케일러에 전달하기 전에 게이트를 적용하십시오.
- 큐 깊이 기반 스케일링:
queue_pending_sessions가 아니라claude_code_self_hosted_orchestrator_pool_pending_sessions를 HPA 또는 KEDA 스케일러에 전달하십시오. - 용량 기반 스케일링: 러너의
active_sessions대capacity비율을 기준으로 스케일링하십시오. connected로 게이트 적용: 인스턴스별로claude_code_self_hosted_orchestrator_connected == 1로 쿼리를 필터링하여, 연결이 끊긴 레플리카의 오래된 값이 스케일러에 전달되지 않도록 하십시오.
ignoreNullValues: "true"에서 빈 결과를 0으로 읽고 스케일 인합니다. ScaledObject에 ignoreNullValues: "false"를 설정하고, 필요하면 fallback 레플리카 하한을 함께 설정하십시오.
다음 Prometheus Operator PodMonitor는 두 프로세스를 모두 다룹니다. Kubernetes 레시피에서 설정하는 app.kubernetes.io/part-of: claude-code-self-hosted-runner 레이블과 이름이 지정된 health 포트로 파드를 선택합니다. 배포에 맞게 네임스페이스를 조정하십시오.
샘플 알림 규칙
다음 샘플 알림 규칙은 출발점입니다. 플릿 규모에 맞게 임계값을 조정하십시오.손실된 러너와 대기 중인 세션에 대한 알림
고정 플릿에서는ClaudeRunnersBelowFloor를 로드하십시오. 온디맨드 러너를 사용하는 경우에는 대신 ClaudeOrchestratorSessionsWaiting과 ClaudeOrchestratorQueueWaitHigh를 로드하십시오.
고정 플릿에서 러너가 줄어들 때 알림
ClaudeRunnersBelowFloor는 등록되고 스크레이프되는 러너 수가 10분 동안 하한보다 적게 남아 있을 때 발생합니다.
- 하한:
expr의2를 레플리카 수의 약 절반(올림)으로 설정하십시오. 레플리카가 세 개라면2를 유지하며, 러너가 하나만 남거나 하나도 남지 않으면 알림이 발생합니다. - 네임스페이스: matcher와
labels의claude-runners를 바꾸고, 추가 네임스페이스마다 알림을 복사하십시오. 대상에namespace레이블이 없다면 matcher와 레이블을 제거하십시오. 그렇지 않으면 알림이 0을 읽고 발생합니다. ClaudeRunnerPollStale및ClaudeRunnerPollErrors: 샘플 알림 규칙에서 로드한 상태로 유지하십시오.ClaudeRunnersBelowFloor는 폴링할 수 없는 러너도 여전히 집계하기 때문입니다
세션이 온디맨드 러너를 기다릴 때 알림
ClaudeOrchestratorSessionsWaiting은 러너를 기다리는 세션 수가 10분 동안 0보다 큰 상태로 유지될 때 발생합니다. ClaudeOrchestratorQueueWaitHigh는 지난 10분 동안의 큐 대기 중 1%를 넘는 대기가 160초를 초과하고, 이 상태가 5분 동안 유지될 때 발생합니다.
- 임계값: 항상 대기 중인 세션이 있다면
ClaudeOrchestratorSessionsWaiting의> 0을 평소에 보이는 수보다 높게 올리십시오 ClaudeOrchestratorDisconnected: 샘플 알림 규칙에서 로드한 상태로 유지하십시오.ClaudeOrchestratorSessionsWaiting은 네임스페이스의 마지막 오케스트레이터 연결이 끊긴 후 약 2분이 지나면 발생을 멈추기 때문입니다
세션 자식 메트릭 전달
각 세션은 자체 OpenTelemetry 메트릭을 가진 별도의 자식 프로세스에서 실행됩니다.--capacity가 1보다 크면 러너는 이러한 자식 메트릭이 노출되는 방식을 재작성합니다. 러너 호스트에 OTEL_METRICS_EXPORTER=prometheus를 설정하고, 예를 들어 래퍼 스크립트나 세션이 상속하는 러너 자체 환경에서 세션 환경에 CLAUDE_CODE_ENABLE_TELEMETRY=1을 설정하면, 각 자식의 카운터 및 게이지 계측값이 러너 자체의 /metrics 엔드포인트에서 러너의 시리즈와 함께 다시 노출됩니다. 러너는 자식의 익스포터를 재작성하여 health 포트의 루프백 전용 수신기로 OTLP를 통해 푸시하도록 하고, 각 시리즈에 session_id 및 client_platform 레이블을 붙이며, 세션이 종료되면 해당 세션의 시리즈를 제거합니다. 히스토그램은 전달되지 않으며, 이름이 러너 자체의 접두사와 충돌하는 자식 메트릭은 삭제됩니다.
기본값인 --capacity 1에서는 재작성이 적용되지 않습니다. 세션의 자식은 평소처럼 포트 9464에 자체 Prometheus 엔드포인트를 바인딩합니다.
세션 메트릭을 러너 메트릭과 조인하기
유휴 세션에 든 비용을 확인하려면 러너의claude_code_self_hosted_runner_session_idle_seconds를 ccr_session_id 기준으로 Claude Code의 비용 메트릭과 조인하십시오. 러너의 메트릭에는 해당 레이블이 없으므로, 다음 쿼리처럼 label_replace로 레이블을 추가하십시오.
claude_code_cost_usage_total을 바꾸십시오. 이 쿼리는 모든 --capacity 값에서 작동합니다.
session_id: 포트 9464에서 Claude Code 메트릭의 이 레이블에는 Claude Code 자체의session.id가 들어 있으며, 이는 어떤 러너 시리즈와도 일치하지 않습니다. 이 레이블로 조인하면 아무것도 반환되지 않으므로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을 증가시키고, 종료 시점에 나머지 세 개 중 정확히 하나를 증가시킵니다. 따라서 sessions_started_total에서 나머지 세 개의 합을 빼면 현재 실행 중인 세션 자식의 수와 같습니다.
completed: 세션이 정상적으로 종료되었습니다. 여기에는 자식이 코드0으로 스스로 종료한 경우, 자식이 아직 연결되어 있는 동안 세션이 아카이브되거나 삭제된 경우, 그리고 러너가 슬롯을 정상적으로 반환한 경우가 포함됩니다. 슬롯 반환에는 유휴 타임아웃, 은퇴 시간 또는--kill-session-after-min한도에서 세션을 해제하는 경우, 시작 타임아웃, 자식이 종료되기 전에 폴링 루프가 감지한 서버 측 할당 해제가 해당합니다.sessions_completed_total을 증가시킵니다.failed: 자식이 0이 아닌 코드로 스스로 종료되었으며, 이는 크래시이거나 생성 후 설정 실패입니다.sessions_failed_total을 증가시킵니다.interrupted: 러너가 세션 성공도 러너 오류도 아닌 운영상의 이유로 자식을 종료했습니다. 예를 들어 드레인이나,--kill-session-after-min한도 이후의SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS유예 기간이 끝났을 때 여전히 러너에 남아 있던 세션을 종료하는 경우가 해당합니다.SIGTERM을 보내는 Kubernetes 롤링 재시작은 드레인의 한 예입니다.sessions_interrupted_total을 증가시킵니다.
--kill-session-after-min 한도에 도달한 모든 세션을 종료하고 이를 sessions_interrupted_total에 집계했습니다.
post-session 훅의 CLAUDE_RUNNER_EXIT_REASON은 정상적인 슬롯 반환을 다르게 분류합니다. 러너가 자식을 중지했기 때문에 훅은 해제, 시작 타임아웃, 서버 할당 해제, 폴링이 먼저 감지한 아카이브 또는 삭제를 interrupted로 보고합니다. 이 카운터들은 슬롯이 정상적으로 반환되었기 때문에 같은 이벤트를 completed로 기록합니다.
훅 수신 기록을 sessions_completed_total과 직접 대조하면 완료 수를 적게 집계하게 됩니다. 세션별 보장에는 훅을, 집계 비율에는 카운터를 사용하십시오.
기본값 --drain-grace-sec 0과 함께 --capacity 1을 사용하는 일회성 환경에서는 각 러너 프로세스가 하나의 세션이 끝난 직후 종료됩니다. sessions_completed_total, sessions_failed_total, sessions_interrupted_total은 세션 종료 시점, 즉 그 프로세스 종료 직전에만 증가하므로, 15~60초마다 수행되는 Prometheus 스크레이프가 러너의 시리즈가 사라지기 전에 증가분을 포착하는 경우는 드뭅니다. 이 세 개의 세션 종료 카운터가 이 섹션의 나머지 부분에서 말하는 종료 카운터입니다. sessions_started_total은 생성 시점에 증가하고 세션이 유지되는 동안 계속 보이므로 안정적으로 나타나지만, 일회성 환경에서는 누적 수라기보다는 “현재 실행 중인 세션”에 가까운 값을 나타냅니다.
종료 카운터 대신, 해당 목표에 맞게 다음 표의 시리즈를 사용하십시오.
orchestrator_* 행은 온디맨드 오케스트레이터를 실행하는 환경에만 존재합니다. --drain-grace-sec가 0보다 커서 러너가 세션보다 오래 유지되는 고정 플릿에서는 처리량에 sum(rate(claude_code_self_hosted_runner_sessions_started_total[5m]))를 사용하십시오. 일회성 플릿에서는 이 시리즈도 종료 카운터와 동일한 스크레이프 구간 문제가 있으므로, 대신 대기 중인 세션 수에 의존하십시오. 백로그는 Cloud environments 관리자 페이지에 있는 환경의 Activity 탭에서 확인하십시오. 러너는 큐 깊이 시리즈를 내보내지 않습니다.
세션별 결과 보고에는 대신 post-session 훅을 사용하십시오. 훅 자체의 계약에 따라, 이 훅은 VM 선점 같은 갑작스러운 러너 종료를 제외하고 자식 프로세스가 생성된 모든 세션 종료 시점에 실행됩니다.
다음 단계
- Self-hosted environments: 환경, 러너 및 세션 모델입니다. quickstart 및 Deploy to production은 설정 및 운영을 보유합니다.
- Customize sessions: 래퍼 스크립트, 라이프사이클 훅 및 온디맨드 러너
- Verify session identity: 세션 토큰, 해당 클레임 및 확인 방법