Caché de los runners (ARC)¶
Los runners de ARC (Actions Runner Controller) son pods efímeros: cada job arranca
vacío. Sin caché, cada job vuelve a bajar Python o Node, los paquetes pip/npm, los
charts de Helm, los providers de OpenTofu y las herramientas del pipeline de gitops.
Para evitarlo, los runners montan un volumen compartido en /cache que sobrevive
entre jobs, excepto el tool cache de setup-python/setup-node (ver abajo).
Cómo está armado¶
| Pieza | Dónde | Qué hace |
|---|---|---|
PVC arc-cache |
gitops/arc/cache/pvc.yaml |
20 Gi, ReadWriteMany (RWX: varios pods a la vez, en nodos distintos), StorageClass longhorn (se sirve por NFS) |
| Montaje y variables | gitops/arc/values-scaleset.yaml |
Monta el volumen en /cache y apunta las cachés de cada herramienta ahí; un initContainer deja las carpetas con el usuario del runner |
| Limpieza | gitops/arc/cache/prune-cronjob.yaml |
CronJob semanal (domingo 04:00) que borra archivos sin tocar hace más de 30 días de pip, npm, Helm y XDG, y muestra el uso |
Qué se guarda y dónde:
| Carpeta | Contenido | Variable |
|---|---|---|
/cache/pip, /cache/npm |
Paquetes descargados | PIP_CACHE_DIR, npm_config_cache |
/cache/helm, /cache/xdg |
Índices y charts de Helm, cachés genéricas | HELM_CACHE_HOME, XDG_CACHE_HOME |
/cache/tofu-plugins |
Providers de OpenTofu (por sistema y arquitectura) | TF_PLUGIN_CACHE_DIR |
/cache/dl |
Tarballs de helm, kustomize, kubeconform, gitleaks y argocd del pipeline de gitops |
RUNNER_CACHE |
El tool cache de setup-python y setup-node NO se comparte
setup-python borra y reinstala la carpeta de la versión que va a usar. Con el tool
cache en el volumen compartido, dos jobs en paralelo (por ejemplo render y
security de gitops) se pisaban la misma carpeta y fallaban con rm: cannot
remove … Stale file handle. Por eso RUNNER_TOOL_CACHE queda en el valor por
defecto (_work/_tool, local a cada runner) y Python/Node se descargan en cada job
(~20 s). Lo que sí se comparte es seguro en paralelo: pip, npm, Helm y los tarballs
de /cache/dl (se escriben a un archivo temporal y se renombran).
El clúster mezcla nodos amd64 y arm64 (deborah): por eso lo que depende de la
arquitectura va en carpetas separadas por ella (providers de OpenTofu y nombres de
tarball) y es seguro compartirlo.
Cómo se verifica lo que se reutiliza¶
Los binarios del pipeline de gitops no se confían a ciegas: en cada job se baja el
archivo de checksums que publica el proyecto (unos KB) y el tarball cacheado solo se
usa si su sha256 coincide; si no, se vuelve a descargar. El resto de cachés (tool
cache, pip, npm) no se puede verificar así.
Riesgo: caché compartida con un repo público
El scale set atiende también a repos públicos (por ejemplo homelab). Un PR de un
fork podría dejar en la caché un paquete alterado que después use un job de un
repo privado. Mitigación: en la org symintel, Settings → Actions → General →
Fork pull request workflows, exige aprobación para todos los colaboradores
externos. Si no necesitas que homelab sea público, hacerlo privado elimina el
riesgo.
Verificar que funciona¶
-
El volumen está enlazado y los runners lo montan:
-
Corre dos veces seguidas el mismo workflow. En el segundo,
pip installdiceUsing cached …y el paso de herramientas degitopsno descarga tarballs (tarda segundos). -
Mira cuánto ocupa (con un pod temporal, el runner ya no existe al terminar el job):
kubectl -n arc-runners run cache-du --rm -it --restart=Never --image=busybox:1.37 \ --overrides='{"spec":{"containers":[{"name":"cache-du","image":"busybox:1.37","command":["sh","-c","du -sh /cache/*; df -h /cache | tail -1"],"volumeMounts":[{"name":"c","mountPath":"/cache"}]}],"volumes":[{"name":"c","persistentVolumeClaim":{"claimName":"arc-cache"}}]}}'
Vaciar la caché¶
Es seguro: los jobs vuelven a descargar lo que falte. Con un pod temporal como el de
arriba pero con rm -rf /cache/*, o borrando el PVC (ArgoCD lo recrea):
Hazlo si sospechas de una caché alterada o corrupta.
Si falla¶
| Síntoma | Revisar |
|---|---|
Los runners no arrancan (Pending) |
kubectl -n arc-runners describe pvc arc-cache: Longhorn debe estar Healthy y los nodos tener nfs-common (rol k3s_prereqs) |
El job dice Permission denied en /cache |
El initContainer cache-perms no pudo hacer chown (NFS con squash de root): kubectl -n arc-runners logs <pod> -c cache-perms |
rm: cannot remove … Stale file handle en /cache/… |
Dos jobs escribiendo la misma carpeta del volumen: no compartas ahí cachés que se borran y reinstalan (como el tool cache); si hay datos corruptos, vacía esa carpeta |
Checksum incorrecto en el pipeline de gitops |
Una descarga corrupta o una caché alterada: vacía /cache/dl y reintenta |
| El volumen se llena | df -h /cache desde el pod temporal; sube el tamaño del PVC (Longhorn permite expandir) o vacía /cache/xdg o /cache/pip |