Instance lifecycle¶
Every ChallengeInstance reports a status.phase driven by two controllers: the instance controller (pod health) and the lifecycle controller (TTL).
stateDiagram-v2
[*] --> Pending
Pending --> Creating : template Ready
Creating --> Running : pod passes readiness
Running --> Unhealthy : readiness fails ≥ threshold
Unhealthy --> Running : readiness recovers
Running --> Expiring : TTL − 60s
Expiring --> Running : extended in time
Expiring --> Expired : TTL reached
Expired --> [*] : instance deleted,\nworkload garbage-collected
Pending --> Failed
Creating --> Failed
Running --> Failed
Phases¶
| Phase | Meaning |
|---|---|
Pending |
Waiting for the referenced template to become Ready. |
Creating |
Workload created; waiting for the pod to be scheduled and pass its readiness check. |
Running |
Pod is up and ready. status.endpoint points at the service. |
Unhealthy |
Pod is running but has failed readiness at least unhealthyThreshold times (default 3). Recovers to Running on its own if readiness returns. |
Expiring |
Inside the 60-second grace window before TTL expiry. The backend gets an instance.expiring event — time to warn the player. |
Expired |
TTL reached. The instance is deleted; its Deployment, Service, and NetworkPolicy are garbage-collected. |
Failed |
Terminal error: template missing, invalid TTL, or the pod itself failed. |
Expired and Failed are terminal — the controllers stop reconciling an instance in those phases.
TTL and extension¶
The effective TTL is the template's spec.ttl, unless the instance sets spec.ttlOverride. status.startedAt is stamped once when the workload first comes up, and status.expiresAt is always startedAt + effective TTL.
Because expiresAt is recomputed on every reconcile, extending a live instance is just a spec update — which is exactly what the API's extend endpoint does:
curl -X PATCH localhost:8080/api/v1/instances/demo-web-team-alpha/extend \
-H "Authorization: Bearer $KIMO_API_KEY" \
-d '{"ttl": "2h"}'
The TTL is total-from-start, not from-now: extending to 2h means the instance lives two hours from startedAt. An instance already in Expiring recovers to Running if extended in time; an Expired instance is gone and cannot be resurrected — launch a new one.
Backend events¶
Each transition emits one event to the scoring backend:
| Phase entered | Event |
|---|---|
Creating |
instance.creating |
Running |
instance.running |
Unhealthy |
instance.unhealthy |
Expiring |
instance.expiring |
Expired |
instance.expired |
Failed |
instance.failed |
| deleted via API | instance.deleted |