Il branching copy-on-write rende le copie isolate dei dati di produzione veloci ed economiche per i test CI/CD e i casi d'uso degli agenti.
Snorkel AI crea strumenti di data development per i team di IA, utilizzati da esperti di annotazione dei dati e fornitori di modelli di frontiera. In questo specifico caso d'uso, Snorkel rilascia codice tramite una pipeline CI basata su Kubernetes. Ogni pull request aperta, oltre ai commit ad-hoc, ottiene il proprio namespace Kubernetes effimero (un "namespace PR"). Gli sviluppatori distribuiscono lì il loro branch ed eseguono l'intera suite di test prima del merge.
Questi test sono più utili quando vengono eseguiti su dati reali. Il database di produzione di Snorkel è un cluster Amazon Aurora PostgreSQL. Fornire a ciascun namespace PR la propria copia di quel database era la parte difficile. Il ripristino di una copia richiedeva circa 20 minuti per ambiente, il che è troppo lento quando gli sviluppatori aprono PR tutto il giorno e la coda di merge necessita di un ambiente nuovo per ogni esecuzione. Le alternative (database di staging condivisi, fixture ridotte o dati sintetici) ripropongono i problemi che i test in stile produzione dovrebbero risolvere: test che interferiscono tra loro, schemi obsoleti e bug che compaiono solo con forme di dati reali.
Snorkel considererebbe Lakebase un successo per il CI/CD se soddisfacesse questi criteri:
Lakebase è il database Postgres serverless di Databricks. Lo storage e il compute sono separati e supporta il branching: puoi creare un branch di database nuovo, isolato e scrivibile da qualsiasi punto nel tempo, nello stesso modo in cui crei un branch Git.
I branch utilizzano la modalità copy-on-write. La creazione di un branch è un'operazione sui metadati, quindi nessun dato viene copiato al momento della creazione del branch. Un nuovo branch condivide le pagine di storage con il suo parent e solo le pagine modificate dal branch vengono scritte come nuovo storage. Per il CI, questo significa:

1. Mantieni una copia aggiornata della produzione sul branch principale. Lakebase è Postgres standard, quindi funziona come destinazione per AWS DMS senza strumenti personalizzati. Snorkel punta un task DMS al suo database Aurora di produzione e lo replica nel branch principale del progetto Lakebase: prima un carico completo, poi la cattura continua dei dati modificati (CDC) che mantiene il branch principale a circa 2 minuti dalla produzione. La modalità LOB completa trasferisce i valori JSONB da 10 a 20 MB. Il team utilizza già DMS, quindi non c'è stato bisogno di creare o mantenere una nuova pipeline di replica. Il branch principale è la "copia di riferimento" da cui inizia ogni branch PR.
2. Crea un branch quando si apre una PR. Quando uno sviluppatore apre una PR, la pipeline CI chiama l'API di Lakebase per creare un branch dal branch principale, imposta una scadenza e passa i dettagli di connessione del branch al namespace PR. Il branch è pronto in meno di un minuto.
3. Esegui i test sui dati reali. L'applicazione nel namespace PR si collega al proprio branch tramite Postgres standard. I test possono eseguire migrazioni, scrivere dati e modificare schemi senza influire sulla produzione, sul branch principale o su qualsiasi altra PR.
4. Elimina il branch quando la PR viene chiusa o il test viene superato, con TTL come rete di sicurezza. Quando la PR viene unita o chiusa, la pipeline elimina il branch. Se quel passaggio di pulizia non viene eseguito, il branch scade autonomamente al termine del suo TTL.
Due requisiti di sicurezza hanno escluso le altre opzioni, quindi meritano una sezione dedicata.
Connettività privata. I dati di produzione si spostano da Aurora a Lakebase e da Lakebase al cluster CI tramite rete privata anziché tramite internet pubblico.
Identità. Snorkel ha due tipi di utenti di database: sviluppatori che si connettono in modo interattivo per eseguire il debug di un ambiente PR e pipeline CI che vengono eseguite senza intervento umano. Okta SSO è basato sull'accesso interattivo tramite browser, quindi abbiamo suddiviso la progettazione per tipo di utente:
Due funzionalità di Lakebase fanno sì che questo pattern funzioni su scala: il branching copy-on-write e la scadenza dei branch (TTL).

Il copy-on-write rende i branch istantanei. Un nuovo branch non copia alcun dato. Punta alle pagine di storage esistenti del proprio parent e solo le pagine modificate dal branch vengono scritte come nuovo storage. Creare un branch da una copia di produzione di circa 1 TB richiede circa lo stesso tempo necessario per crearne uno da un database di 1 GB: pochi secondi, non i circa 20 minuti richiesti da un ripristino completo. Ciascun namespace PR ottiene immediatamente la propria copia di produzione isolata e scrivibile.
Il copy-on-write rende i branch economici. Ciascun branch condivide la maggior parte dei suoi dati con il branch principale, quindi lo storage cresce con le modifiche apportate da ciascun branch, non con le dimensioni del database. Per Snorkel, si tratta di circa 5-10 GB per branch PR oltre alla base condivisa. Il compute è per branch e si riduce a zero quando è inattivo, quindi solo i branch che eseguono attivamente test utilizzano il compute.
La scadenza dei branch mantiene bassi i costi nel tempo. Il copy-on-write offre il massimo risparmio quando i branch hanno una breve durata. Un branch mantiene la versione dei dati esistente al momento della sua creazione. Poiché DMS continua ad aggiornare il branch principale con le modifiche di produzione, un branch che rimane attivo continua a mantenere quelle pagine meno recenti, quindi lo storage utilizzato cresce nel tempo. L'impostazione di un TTL su ogni branch CI fa sì che ciascun branch venga rimosso automaticamente una volta completata la PR corrispondente. In questo modo lo storage rimane vicino alle dimensioni della base di produzione più le modifiche derivanti dalle PR attive.
I namespace PR non sono gli unici carichi di lavoro che richiedono una copia di produzione usa e getta. Anche gli agenti IA che scrivono SQL, eseguono migrazioni o modificano dati hanno bisogno di un luogo sicuro in cui provare le cose, e il branching copy-on-write ne offre uno.
Un branch per ogni task dell'agente. Ogni esecuzione dell'agente ottiene il proprio branch del branch principale. L'agente può leggere dati reali, scrivervi sopra e persino modificare lo schema senza toccare la produzione o il lavoro di qualsiasi altro agente. La creazione di un branch richiede pochi secondi indipendentemente dalle dimensioni del database, quindi è pratico crearne uno per ogni task.
Molti agenti in parallelo. Lo storage cresce solo con le pagine modificate da ciascun branch e il compute di ciascun branch si riduce a zero quando è inattivo. Eseguire decine di agenti fianco a fianco costa all'incirca quanto le modifiche che apportano, anziché richiedere decine di copie del database.
Esamina le modifiche o scartale. I team possono controllare ciò che un agente ha modificato sul suo branch prima di applicare qualsiasi cosa alla produzione. Se il risultato non è corretto, eliminano il branch e non c'è nulla da ripristinare.
I TTL ripuliscono il lavoro degli agent. Gli agent possono creare molti branch a breve termine. La scadenza su ogni branch elimina automaticamente quelli abbandonati, esattamente come i TTL ripuliscono i branch CI.
Identità con ambito per gli agent. Come le pipeline CI, gli agent possono essere eseguiti come service principal con token OAuth a breve termine, in modo che ogni query eseguita da un agent possa essere tracciata nei log di controllo.
Pronto a dare a ogni pull request un database simile a quello di produzione? Inizia con Lakebase e leggi la documentazione sul branching per configurare la scadenza dei branch nella tua pipeline CI.
(Questo post sul blog è stato tradotto utilizzando strumenti basati sull'intelligenza artificiale) Post originale
Iscriviti al nostro blog e ricevi gli ultimi articoli direttamente nella tua casella di posta.