Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Troubleshoot ARC (Actions Runner Controller) runners on Rackspace Spot Kubernetes. Diagnose stuck jobs, scaling issues, and cluster access. Activates on "runner", "ARC", "stuck job", "queued", "GitHub Actions", or "CI stuck".
allowed-tools
Read, Grep, Glob, Bash
ARC Runner Troubleshooting Guide
Overview
project-beta uses self-hosted GitHub Actions runners deployed via ARC (Actions Runner Controller) on Rackspace Spot Kubernetes. This guide covers common issues and troubleshooting procedures.
If the ArgoCD helm release name doesn't match runnerScaleSetName:
ArgoCD tracks resources under the old release name
New AutoscalingRunnerSet created with different name
Old ARS may not be pruned, resulting in stale runners
Stale runners have broken registration → empty labels
Fix:
# argocd/apps-live/arc-runners.yamlhelm:releaseName:arc-beta-runners# MUST match runnerScaleSetName!# examples/runners-values.yamlgha-runner-scale-set:runnerScaleSetName:"arc-beta-runners"# MUST match releaseName!
Diagnosis tip: Check runner pod names:
arc-runners-*-runner-* → OLD ARS still active (problem!)
arc-beta-runners-*-runner-* → NEW ARS deployed (correct!)
Symptoms:
Runners show empty labels [] in GitHub
Runners show os: "unknown" in GitHub API
ALL jobs stuck in "queued" state indefinitely
Runners appear online but never pick up jobs
Diagnosis:
# Check runner labels via GitHub API
gh api /orgs/Matchpoint-AI/actions/runners --jq '.runners[] | {name, status, labels: [.labels[].name], os}'# Bad output (empty labels):
{
"name": "arc-runners-w74pg-runner-2xppt",
"status": "online",
"labels": [],
"os": "unknown"
}
# Good output (proper labels):
{
"name": "arc-beta-runners-xxxxx-runner-yyyyy",
"status": "online",
"labels": ["arc-beta-runners", "self-hosted", "Linux", "X64"],
"os": "Linux"
}
"You cannot use additional labels to target runners created by ARC. You can only use the installation name of the runner scale set that you specified during the installation or by defining the value of the runnerScaleSetName field in your values.yaml file."
How ARC Labels Work:
ARC uses ONLY the runnerScaleSetName as the GitHub label
Cannot add custom labels via ACTIONS_RUNNER_LABELS environment variable
ARC automatically adds self-hosted, OS, and architecture labels
Cannot have multiple custom labels on a single scale set
Fix:
# examples/runners-values.yaml or frontend-runners-values.yamlgha-runner-scale-set:runnerScaleSetName:"arc-beta-runners"# This becomes the GitHub labeltemplate:spec:containers:-name:runnerenv:# DO NOT SET ACTIONS_RUNNER_LABELS - it's ignored by ARC!# Only runnerScaleSetName matters-name:RUNNER_NAME_PREFIXvalue:"arc-beta"
githubConfigSecret:arc-org-github-secret# String reference to pre-created secret
The Conflict:
Helm --set gha-runner-scale-set.githubConfigSecret.github_token= expects githubConfigSecret to be a map
Values file defines githubConfigSecret as a string (secret name reference)
Result: interface conversion: interface {} is string, not map[string]interface {}
Symptoms:
ArgoCD Application shows ComparisonError in conditions
Manifest generation fails repeatedly
Runners may appear to work but sync is broken
Application status shows Unknown sync status
Diagnosis:
# Check ArgoCD Application status
kubectl get application arc-runners -n argocd -o jsonpath='{.status.conditions[*]}'# Look for error like:# "failed parsing --set data: unable to parse key: interface conversion: interface {} is string, not map[string]interface {}"# Check ApplicationSet for conflicting parameters
kubectl get applicationset github-runners -n argocd -o jsonpath='{.spec.template.spec.source.helm}'
Fix:
Remove parameters section from argocd/applicationset.yaml
Use pre-created secrets referenced in values file
# argocd/applicationset.yaml - DO NOT include parametershelm:releaseName:'{{name}}'valueFiles:-'../../{{valuesFile}}'# NO parameters section - values file handles secrets# examples/runners-values.yamlgithubConfigSecret:arc-org-github-secret# Pre-created in cluster
Apply Fix to Cluster:
# kubectl apply may not remove fields - use replace
kubectl replace -f argocd/applicationset.yaml --force
# Verify parameters removed
kubectl get applicationset github-runners -n argocd -o jsonpath='{.spec.template.spec.source.helm}'
Secret Setup:
# Create the secret manually in the cluster
kubectl create secret generic arc-org-github-secret \
--namespace=arc-runners \
--from-literal=github_token='ghp_...'
References:
PR #94 in matchpoint-github-runners-helm (the fix)
Issue #89 in matchpoint-github-runners-helm
3. Jobs Stuck in Queued State (2-5+ minutes)
Root Cause:minRunners: 0 causes cold-start delays
Symptoms:
Jobs stuck in "queued" status for 2-5+ minutes
First job of the day takes significantly longer
Parallel PRs cause cascading delays
Diagnosis:
# Check current Helm valuescat /home/pselamy/repositories/matchpoint-github-runners-helm/examples/beta-runners-values.yaml | grep minRunners
# Check if issue is minRunners: 0# If minRunners: 0 → cold start on every job
Fix:
# examples/beta-runners-values.yamlminRunners:2# Changed from 0 - keep 2 runners pre-warmedmaxRunners:20
error: You must be logged in to the server (the server has asked for the client to provide credentials)
error: unknown command "oidc-login" for "kubectl"
dial tcp: lookup hcp-xxx.spot.rackspace.com: no such host
# Install ngpc CLI from Rackspace
pip install ngpc-cli
# Login and refresh credentials
ngpc login
ngpc kubeconfig get <cloudspace-name>
5. DNS Resolution Failures
Problem: Cluster hostname not resolving
dial tcp: lookup hcp-xxx.spot.rackspace.com: no such host
Causes:
Cluster was deleted/migrated (most common)
Using stale kubeconfig file that points to old cluster
DNS propagation delay
Wrong cluster endpoint
Solution:
Use terraform to get kubeconfig for the CURRENT active cluster:
# Get fresh kubeconfig from terraform (see Option A above)export TF_HTTP_PASSWORD="<github-token>"cd /home/pselamy/repositories/matchpoint-github-runners-helm/terraform
terraform init
terraform output -raw kubeconfig_raw > /tmp/runners-kubeconfig.yaml
Note: The kubeconfig-matchpoint-runners-prod.yaml file in the repo root may be stale if the cluster was recreated. Always use terraform output to get the current kubeconfig.
Diagnosis:
# Check terraform state for current cloudspacecd /home/pselamy/repositories/matchpoint-github-runners-helm/terraform
export TF_HTTP_PASSWORD="<github-token>"
terraform init
terraform state list | grep cloudspace
# View cloudspace details
terraform state show module.cloudspace.spot_cloudspace.main
6. Missing Tools (wget, curl, Docker CLI)
Problem: CI workflows fail with "command not found" for common tools
ghcr.io/actions/actions-runner:latest - Generic (missing many tools)
ghcr.io/matchpoint-ai/arc-runner:latest - Custom (has all tools)
Symptoms:
/bin/bash: wget: command not found
/bin/bash: docker: command not found
Root Cause: Configuration may be using the generic image instead of custom.
Diagnosis:
# Check which image is configured
grep -r "ghcr.io" examples/*.yaml values/*.yaml | grep -v "#"# Check which image is actually running
kubectl get pods -n arc-runners -o jsonpath='{.items[0].spec.containers[0].image}'
Custom Image Includes:
Tool
Version
wget, curl, jq
latest
Node.js
20 LTS
Python
3.12 + pip + poetry
Docker CLI
24.x
Terraform
1.9.x
PostgreSQL client
16
Build tools
make, gcc, etc.
Fix:
# examples/runners-values.yamlcontainers:-name:runnerimage:ghcr.io/matchpoint-ai/arc-runner:latest# NOT actions-runner!
Note: The custom image is built from images/arc-runner/Dockerfile in this repo. The build workflow runs on pushes to images/arc-runner/**.
Reference: Issue #135, PR #138
7. Docker-in-Docker (DinD) Issues
Problem: Docker commands fail even though DinD sidecar is configured
Symptoms:
Cannot connect to the Docker daemon at tcp://localhost:2375
Diagnosis:
# Check pod has 2 containers (runner + dind)
kubectl get pods -n arc-runners -o jsonpath='{.items[*].spec.containers[*].name}'# Should show: runner dind# Check DinD logs
kubectl logs -n arc-runners <pod-name> -c dind --tail=50
# Should show: "API listen on [::]:2375"# Verify DOCKER_HOST env var
kubectl get pods -n arc-runners -o jsonpath='{.items[0].spec.containers[0].env}' | jq '.[] | select(.name=="DOCKER_HOST")'# Should show: tcp://localhost:2375
Common Issues:
DinD not running: Check if privileged mode is allowed in cluster
Wrong DOCKER_HOST: Should be tcp://localhost:2375
Missing sidecar: Check pod template in values file
Verify DinD is healthy:
kubectl exec -n arc-runners <pod-name> -c runner -- docker version
kubectl exec -n arc-runners <pod-name> -c runner -- docker info
8. Configuration Mismatch
Problem: Documentation says one thing, deployed config is different
Key Insight: The examples/*.yaml files are what actually gets deployed. The values/repositories.yaml is documentation/reference only.
Audit Configuration:
# Check what's ACTUALLY deployedcat examples/beta-runners-values.yaml | grep -E "(minRunners|maxRunners)"# vs what documentation sayscat values/repositories.yaml | grep -E "(minRunners|maxRunners)"
Monitoring Commands
Check Workflow Status
# List queued workflows
gh run list --repo Matchpoint-AI/project-beta-api --status queued
# List in-progress workflows
gh run list --repo Matchpoint-AI/project-beta-api --status in_progress
# View specific run
gh run view <RUN_ID> --repo Matchpoint-AI/project-beta-api
Check Runner Status (when cluster accessible)
# Set kubeconfigexport KUBECONFIG=/path/to/kubeconfig.yaml
# Check runner scale set
kubectl get autoscalingrunnerset -n arc-beta-runners-new
# Check runner pods
kubectl get pods -n arc-beta-runners-new -l app.kubernetes.io/component=runner
# Check ARC controller logs
kubectl logs -n arc-systems deployment/arc-gha-rs-controller --tail=50
# Check for scaling events
kubectl get events -n arc-beta-runners-new --sort-by='.lastTimestamp' | tail -20
Check GitHub Registration
# List registered runners
gh api /orgs/Matchpoint-AI/actions/runners --jq '.runners[] | {name, status, busy}'# Check runner groups
gh api /orgs/Matchpoint-AI/actions/runner-groups --jq '.runner_groups[].name'