Distribuire su kind
Obiettivo: far girare il motore su un cluster locale kind e portare un ticket fino in fondo.
Prerequisiti
- Docker.
- kind.
kubectl.
make kind-up fa il deploy dell'intero motore sul cluster: serve, due worker sull'harness dry,
Postgres tramite CloudNativePG e Redis. Fa anche il deploy dei pezzi sandbox di V7b: il namespace
afe-sandbox, l'RBAC del worker, netlock, e le immagini afe-sandbox:dev, afe-netlock:dev e
afe-egress-proxy:dev.
Passi
-
Crea il cluster e inoltra le porte:
make kind-up # cluster `afe`, immagine afe:dev, CloudNativePG, Redis, serve e workermake kind-forward # API su 127.0.0.1:8765, ops su 9464 (serve) e 9465 (un worker); lascialo accesomake kind-upprende il token daAFE_API_TOKENin.env. Senza quella variabile tiene il token generato la prima volta. Il token vive solo nel Secret del cluster.make kind-upsceglie anche l'harness dei modelli. L'ultima riga dice quale ha scelto. Può esserekind: workers on the dry harness (fake models)oppurekind: workers on the live harness (real models). Leggila prima di lanciare un flow. Un cluster live spende token veri. -
In un altro terminale esporta il token dal Secret e avvia un ticket:
export AFE_API_TOKEN=$(kubectl --context kind-afe -n afe get secret afe-secrets \-o jsonpath='{.data.AFE_API_TOKEN}' | base64 -d)afe run writer-reviewer -i request.yaml # si ferma all'approvazioneafe resume T-0001 approveafe workerscurl -s 127.0.0.1:9465/metrics | grep afe_tickets -
Per girare su modelli veri, metti
OPENROUTER_API_KEYin.env(mai committato). Unmake kind-upsemplice va allora live: applica l'overlaydeploy/kind-livee i worker girano senza--dry. Il Secret riceve la chiave. È il default sicuro ora, così una chiave vera non resta inutilizzata mentre i worker girano su modelli finti.make kind-up LIVE=0forza il dry anche con la chiave presente.make kind-up LIVE=1è live esplicito; senza la chiave si ferma con un messaggio.- Senza chiave e senza
LIVE, i worker restano finti.
Basta modificare
.enve rilanciaremake kind-up: riscrive il Secret e riavviaservee i worker.Anche il cluster in esecuzione riporta la sua modalità. Interroga l'annotazione del worker:
kubectl --context kind-afe -n afe get deploy worker \-o jsonpath='{.metadata.annotations.afe\.dev/model-mode}'# dry oppure live
Testare il cluster
make kind-test esegue i test sul cluster:
- i test di V6e portano un ticket attraverso due worker e controllano le metriche. Portano anche Redis a zero (i Pod diventano non pronti e non vengono riavviati), e mettono in coda un ticket senza worker.
- i test di V7b portano un flow
gitedeepfino adone. Cancellano il Pod del ticket dopo un checkpoint, e controllano che un worker ripristini il workspace su un Pod nuovo senza rieseguire un nodo completato. Controllano anche l'isolamento di rete: un Pod non raggiunge nulla di default, o solo un host in allowlist quando il progetto ne ha uno. Infine controllano che il Pod e la PVC del ticket siano spariti alla fine.
make kind-test si aspetta worker finti, e non fa parte di make ci. make kind-down cancella
il cluster.
Ogni job di GitHub Actions di questo repository gira sul runner self-hosted del board, perché i
runner ospitati di GitHub sono bloccati dalla fatturazione. runs-on: ubuntu-latest, e ogni altro
runner ospitato di GitHub, è vietato. La guardia in tests/ci/test_self_hosted_runner.py fa
fallire make ci su un job ospitato, legge ogni file di workflow .yml e .yaml, e rifiuta una
chiamata a un workflow riutilizzabile con uses: a livello di job. Una corsa notturna ripete
make kind-test sul runner e riporta ogni test rosso su una sola issue kind-regression
(.github/workflows/kind.yml). Non blocca mai make ci né un merge. Senza un runner self-hosted,
deploy/systemd/install.sh installa la stessa corsa come timer utente sulla macchina
dell'operatore.
Anche i workload di kind portano un limite di CPU e di memoria: serve, i worker, Redis e il
Postgres di CloudNativePG. Le suite notturne e2e/integration e la corsa kind condividono un
solo gruppo di concorrenza, così due corse pesanti non si sovrappongono mai sul runner.
Igiene del disco del runner
Un runner self-hosted conserva la cache di build di Docker, le immagini, i volumi e la cache di uv
tra un job e l'altro, quindi una corsa kind notturna farebbe crescere il disco di gigabyte ogni
volta. Il job kind lancia scripts/ci/runner_hygiene.sh guard 20 prima di make kind-up: libera
lo spazio che una corsa precedente ha lasciato e ferma il job con un messaggio chiaro quando / ha
meno di 20 GB liberi. Uno step runner cleanup lancia lo stesso script con clean in always(),
dopo make kind-down, così lo spazio viene liberato anche quando la corsa fallisce prima.
scripts/ci/runner_hygiene.sh ha due sottocomandi. clean limita la cache di build a 3 GB, poi
elimina le immagini pendenti, i container fermi, i volumi non usati e la cache di uv, stampando
df -h / e docker system df prima e dopo. guard <min-free-gb> esegue prima clean, poi
fallisce quando lo spazio libero su / è sotto la soglia. Lo script è pensato per il runner
dedicato: docker volume prune libera ogni volume non usato, il che va bene quando gli unici
container sull'host sono quelli usa-e-getta creati da una corsa kind.
Risoluzione dei problemi
LIVE=1 needs OPENROUTER_API_KEY in .env
make kind-up LIVE=1 è girato senza la chiave in .env. Aggiungi OPENROUTER_API_KEY=... a
.env e rilancia il comando.
Il flow finisce all'istante, come se il modello fosse finto
I worker sono sull'harness dry. make kind-up stampa la sua modalità come ultima riga. Anche
l'annotazione afe.dev/model-mode del worker legge dry. Metti una OPENROUTER_API_KEY vera in
.env e rilancia make kind-up. Se hai tenuto LIVE=0, toglilo.
make kind-forward non mostra nulla su 127.0.0.1:8765
L'inoltro delle porte gira in primo piano e deve restare aperto nel suo terminale. Controlla che
sia ancora in esecuzione, e che nessun altro processo occupi la porta 8765, 9464 o 9465.
afe run o afe resume non raggiungono l'API
AFE_API_TOKEN nella tua shell non corrisponde al Secret del cluster, oppure make kind-forward
non è in esecuzione. Riesporta il token con il comando del passo 2 e controlla che l'inoltro sia
attivo.