Copy-on-Write-Branching erstellt schnelle und kostengünstige isolierte Kopien von Produktionsdaten für CI/CD-Tests und agentenbasierte Anwendungsfälle.
von Yasamin Tari und Kartik Mathur
Snorkel AI entwickelt Datentools für KI-Teams, die von Experten für Datenannotation und Anbietern von Frontier-Modellen genutzt werden. In diesem konkreten Anwendungsfall liefert Snorkel Code über eine auf Kubernetes basierende CI-Pipeline aus. Jede offene Pull-Request sowie Ad-hoc-Commits erhalten ihren eigenen ephemeren Kubernetes-Namespace (einen "PR-Namespace"). Entwickler stellen ihren Branch dort bereit und führen vor dem Zusammenführen die gesamte Testsuite aus.
Diese Tests sind am nützlichsten, wenn sie mit echten Daten ausgeführt werden. Snorkels Produktionsdatenbank ist ein Amazon Aurora PostgreSQL-Cluster. Jeder PR-Namespace eine eigene Kopie dieser Datenbank bereitzustellen, war der schwierige Teil. Das Wiederherstellen einer Kopie dauerte etwa 20 Minuten pro Umgebung, was zu langsam ist, wenn Entwickler den ganzen Tag PRs öffnen und die Merge-Warteschlange für jeden Durchlauf eine frische Umgebung benötigt. Die Alternativen (gemeinsame Staging-Datenbanken, reduzierte Testdaten oder synthetische Daten) bringen genau die Probleme zurück, die ein produktionsebenes Testen lösen soll: sich gegenseitig beeinflussende Tests, veraltete Schemas und Bugs, die nur bei realen Datenstrukturen auftreten.
Snorkel würde Lakebase für CI/CD als Erfolg betrachten, wenn diese Kriterien erfüllt sind:
Lakebase ist die serverlose Postgres-Datenbank von Databricks. Speicher und Compute sind voneinander getrennt und unterstützen Branching: Sie können von jedem Zeitpunkt aus einen neuen, isolierten, beschreibbaren Branch einer Datenbank erstellen – genauso wie Sie einen Git-Branch erstellen.
Branches verwenden Copy-on-Write. Das Erstellen eines Branch ist eine Metadatenoperation, weshalb beim Erstellen keine Daten kopiert werden. Ein neuer Branch teilt sich Speicherseiten mit seinem Parent, und nur die Seiten, die der Branch ändert, werden als neuer Speicher geschrieben. Für CI bedeutet dies:

1. Eine frische Kopie der Produktion auf dem Main-Branch behalten. Lakebase ist Standard-Postgres, sodass es ohne benutzerdefinierte Tools als Ziel für AWS DMS fungiert. Snorkel leitet eine DMS-Task auf seine Produktions-Aurora-Datenbank und repliziert sie in den Main-Branch des Lakebase-Projekts: zuerst ein kompletter Load, gefolgt von einer kontinuierlichen Change Data Capture, die den Main-Branch innerhalb von etwa 2 Minuten nah an der Produktion hält. Der vollständige LOB-Modus übernimmt die 10 bis 20 MB großen JSONB-Werte. Das Team verwendet bereits DMS, sodass keine neue Replikationspipeline aufgebaut oder gewartet werden musste. Der Main-Branch ist die „goldene Kopie“, von der aus jeder PR-Branch startet.
2. Einen Branch erstellen, wenn ein PR geöffnet wird. Wenn ein Entwickler einen PR öffnet, ruft die CI-Pipeline die Lakebase-API auf, um einen Branch aus Main zu erstellen, legt eine Ablaufzeit dafür fest und übergibt die Verbindungsdetails des Branch an den PR-Namespace. Der Branch ist in unter einer Minute einsatzbereit.
3. Tests gegen echte Daten ausführen. Die Anwendung im PR-Namespace verbindet sich über Standard-Postgres mit ihrem Branch. Tests können Migrationen ausführen, Daten schreiben und Schemas ändern, ohne die Produktion, den Main-Branch oder andere PRs zu beeinträchtigen.
4. Den Branch löschen, wenn der PR geschlossen wird oder der Test erfolgreich ist, abgesichert durch eine TTL. Wenn der PR zusammengefügt oder geschlossen wird, löscht die Pipeline den Branch. Sollte dieser Bereinigungsschritt nicht ausgeführt werden, läuft der Branch automatisch ab, sobald seine TTL erreicht ist.
Zwei Sicherheitsanforderungen schlossen andere Optionen aus, weshalb sie einen eigenen Abschnitt verdienen.
Private Konnektivität. Produktionsdaten werden über private Netzwerke statt über das öffentliche Internet von Aurora zu Lakebase und von Lakebase zum CI-Cluster übertragen.
Identität. Snorkel hat zwei Arten von Datenbankbenutzern: Entwickler, die sich interaktiv verbinden, um eine PR-Umgebung zu debuggen, und CI-Pipelines, die ohne menschliches Zutun laufen. Okta SSO basiert auf interaktiven Browser-Logins, weshalb wir das Design nach Benutzertyp aufgeteilt haben:
Zwei Lakebase-Funktionen sorgen dafür, dass dieses Muster im großen Stil funktioniert: Copy-on-Write-Branching und Branch-Ablauf (TTL).

Copy-on-Write macht Branches sofort einsatzbereit. Ein neuer Branch kopiert keine Daten. Er verweist auf die bestehenden Speicherseiten seines Parents, und nur die Seiten, die der Branch modifiziert, werden als neuer Speicher geschrieben. Das Erstellen eines Branch aus einer ~1 TB großen Produktionskopie dauert in etwa so lange wie das Erstellen aus einer 1 GB großen Datenbank: Sekunden, statt der ~20 Minuten, die eine vollständige Wiederherstellung benötigte. Jeder PR-Namespace erhält sofort eine eigene, isolierte, beschreibbare Kopie der Produktion.
Copy-on-Write macht Branches kostengünstig. Jeder Branch teilt sich die meisten seiner Daten mit Main, sodass der Speicher mit den Änderungen wächst, die jeder Branch vornimmt, und nicht mit der Größe der Datenbank. Für Snorkel sind das etwa 5 bis 10 GB pro PR-Branch zusätzlich zur gemeinsamen Basis. Compute ist pro Branch vorhanden und skaliert bei Inaktivität auf Null, sodass nur die Branches Compute verbrauchen, die aktiv Tests ausführen.
Der Branch-Ablauf hält die Kosten langfristig niedrig. Copy-on-Write spart am meisten, wenn Branches nur von kurzer Dauer sind. Ein Branch behält die Version der Daten bei, die bei seiner Erstellung vorhanden war. Da DMS den Main-Branch kontinuierlich mit Produktionsänderungen aktualisiert, behält ein länger verbleibender Branch diese älteren Seiten bei, wodurch der verwendete Speicher mit der Zeit wächst. Das Festlegen einer TTL für jeden CI-Branch bedeutet, dass jeder Branch automatisch entfernt wird, sobald sein PR abgeschlossen ist. Dadurch bleibt der Speicher nahe an der Größe der Produktionsbasis plus den Änderungen aus aktiven PRs.
PR-Namespaces sind nicht die einzigen Workloads, die eine wegwerfbare Kopie der Produktion benötigen. KI-Agenten, die SQL schreiben, Migrationen ausführen oder Daten ändern, brauchen ebenfalls einen sicheren Ort, um Dinge auszuprobieren, und Copy-on-Write-Branching bietet ihnen genau das.
Ein Branch pro Agenten-Task. Jeder Agentenlauf erhält seinen eigenen Branch von Main. Der Agent kann echte Daten lesen, darauf schreiben und sogar das Schema ändern, ohne die Produktion oder die Arbeit anderer Agenten zu berühren. Das Erstellen eines Branch dauert Sekunden, unabhängig davon, wie groß die Datenbank ist, weshalb es praktikabel ist, für jede Task einen zu erstellen.
Viele Agenten parallel. Der Speicher wächst nur mit den Seiten, die jeder Branch ändert, und das Compute jedes Branch skaliert bei Inaktivität auf Null. Dutzende Agenten nebeneinander auszuführen kostet ungefähr so viel wie die Änderungen, die sie vornehmen, und nicht so viel wie Dutzende Kopien der Datenbank.
Änderungen überprüfen oder verwerfen. Teams können überprüfen, was ein Agent an seinem Branch geändert hat, bevor sie etwas in der Produktion anwenden. Wenn das Ergebnis nicht stimmt, löschen sie den Branch, und es muss nichts zurückgerollt werden.
TTLs räumen nach Agents auf. Agents können viele kurzlebige Branches erstellen. Ein Ablaufdatum für jeden Branch entfernt verwaiste Branches automatisch, genau wie TTLs CI-Branches bereinigen.
Bereichsbezogene Identität für Agents. Ähnlich wie CI-Pipelines können Agents als Dienstprinzipien mit kurzlebigen OAuth-Token ausgeführt werden, sodass jede von einem Agent ausgeführte Abfrage in den Prüfungsprotokollen nachvollzogen werden kann.
Möchten Sie jedem Pull Request eine eigene produktionsähnliche Datenbank geben? Erste Schritte mit Lakebase und lesen Sie die Branching-Dokumentation, um den Ablauf von Branches in Ihrer CI-Pipeline einzurichten.
(Dieser Blogbeitrag wurde mit KI-gestützten Tools übersetzt.) Originalbeitrag
Abonnieren Sie unseren Blog und erhalten Sie die neuesten Beiträge direkt in Ihren Posteingang.