Passa al contenuto principale

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​

  1. Crea il cluster e inoltra le porte:

    make kind-up # cluster `afe`, immagine afe:dev, CloudNativePG, Redis, serve e worker
    make kind-forward # API su 127.0.0.1:8765, ops su 9464 (serve) e 9465 (un worker); lascialo acceso

    make kind-up prende il token da AFE_API_TOKEN in .env. Senza quella variabile tiene il token generato la prima volta. Il token vive solo nel Secret del cluster.

    make kind-up sceglie anche l'harness dei modelli. L'ultima riga dice quale ha scelto. Può essere kind: workers on the dry harness (fake models) oppure kind: workers on the live harness (real models). Leggila prima di lanciare un flow. Un cluster live spende token veri.

  2. 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'approvazione
    afe resume T-0001 approve
    afe workers
    curl -s 127.0.0.1:9465/metrics | grep afe_tickets
  3. Per girare su modelli veri, metti OPENROUTER_API_KEY in .env (mai committato). Un make kind-up semplice va allora live: applica l'overlay deploy/kind-live e 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=0 forza 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 .env e rilanciare make kind-up: riscrive il Secret e riavvia serve e 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 git e deep fino a done. 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.

Vedi anche​