Scaling
ImpVMRunnerPool supports three scaling modes driven by spec.scaling.mode.
Modes
| Mode | Behavior |
|---|---|
webhook | Scale from GitHub webhook demand signals |
polling | Scale by polling GitHub API for queued jobs |
hybrid | Use both signals, take the higher demand |
hybrid is recommended for most deployments when both demand sources are configured. For an organisation-scoped pool, polling does not currently provide organisation-wide queue depth; use webhook demand or pre-warm with minIdle.
Configuration
spec:
scaling:
mode: hybrid
minIdle: 2 # always-ready runners
maxConcurrent: 10 # hard cap on simultaneous VMs
scaleUpStep: 2 # max new VMs per reconcile cycle
cooldownSeconds: 60 # wait after scale-down before scaling up againScheduling Math
- Start at
minIdlepre-registered runners. - In
hybridmode, raise by the higher of queue depth (polling) and webhook demand. - Cap by
maxConcurrent. - Add at most
scaleUpStepVMs per reconcile. - After scale-down, wait
cooldownSecondsbefore scaling up again.
Monitor
kubectl get impvmrunnerpool ci-pool -n default -o yaml
kubectl get impvm -n default -l imp.dev/pool=ci-poolRequired Secrets
For GitHub Actions, use a GitHub App secret with tokenSource: github_app. The Secret contains github-app-private-key, github-app-id, and github-app-installation-id. The operator signs a short-lived App JWT and mints installation tokens when needed.
A static token value is still accepted for compatibility, but the source marks it as deprecated for GitHub Actions pools.
Capacity Visibility
GitHub shows runner capacity only after VMs register. minIdle controls how many are pre-registered and ready for immediate job pickup.
maxConcurrent is a hard upper bound on runner VMs, not a guarantee that GitHub will assign that many jobs. Job assignment still depends on the runner group and labels selected by the workflow.
