Ir al contenido principal
Industria

Bifurcación de Lakebase para CI/CD: lecciones de 100 bases de datos de PR

La ramificación basada en copia en escritura permite crear copias aisladas de los datos de producción de forma rápida y económica para pruebas de CI/CD y casos de uso de agentes.

por Yasamin Tari y Kartik Mathur

  • La canalización de CI/CD de Snorkel AI asigna a cada solicitud de extracción abierta su propia rama de Lakebase Postgres, una copia completa de lectura y escritura de los datos de producción lista en menos de un minuto en lugar de más de 30 minutos, debido a lo cual nunca pudieron habilitar la copia por solicitud de extracción.
  • Las ramas de Lakebase utilizan copia en escritura (copy-on-write), por lo que 100 bases de datos de solicitudes de extracción simultáneas en un conjunto de datos de producción de ~2.5 TB solo añaden almacenamiento para los datos que modifica cada rama. La caducidad de las ramas (TTL) elimina cada rama automáticamente cuando finaliza su solicitud de extracción, por lo que el almacenamiento se mantiene cercano al tamaño de producción más los cambios de las solicitudes de extracción activas.
  • La conectividad privada y la compatibilidad con Okta SSO ofrecen un entorno seguro y regulado.

El problema: las pruebas con datos de producción no deberían tomar más de 30 minutos

Snorkel AI crea herramientas de desarrollo de datos para equipos de IA, utilizadas por anotadores de datos expertos y proveedores de modelos de vanguardia. En este caso de uso específico, Snorkel implementa código a través de un pipeline de CI integrado en Kubernetes. Cada pull request abierto, además de los commits ad-hoc, obtiene su propio espacio de nombres efímero de Kubernetes (un "espacio de nombres de PR"). Los desarrolladores despliegan su rama allí y ejecutan el conjunto completo de pruebas antes de fusionarla.

Estas pruebas son más útiles cuando se ejecutan con datos reales. La base de datos de producción de Snorkel es un clúster de Amazon Aurora PostgreSQL. Otorgarle a cada espacio de nombres de PR su propia copia de esa base de datos era la parte difícil. Restaurar una copia tomaba unos 20 minutos por entorno, lo cual es demasiado lento cuando los desarrolladores abren PRs todo el día y la cola de fusión necesita un entorno nuevo para cada ejecución. Las alternativas (bases de datos de staging compartidas, fixtures recortados o datos sintéticos) devuelven los problemas que las pruebas similares a producción se supone que deben resolver: pruebas que interfieren entre sí, esquemas obsoletos y errores que solo aparecen con formas de datos reales.

Criterios de éxito

Snorkel consideraría que Lakebase es un éxito para CI/CD si cumplía con estos criterios:

  • Aprovisionamiento rápido: Una nueva rama de PR está lista en menos de 60 segundos (p95).
  • Escala: Alrededor de 100 ramas de PR concurrentes en el pico, cada una con lecturas y escrituras independientes.
  • Compatibilidad: La aplicación existente y el conjunto de CI se ejecutan en Lakebase sobre Postgres estándar, con un rendimiento comparable al de Aurora y soporte para columnas grandes JSONB/LOB.
  • Datos recientes: La rama principal se mantiene a unos 2 minutos de la producción de Aurora mediante la replicación continua de DMS.
  • Seguridad: Los datos de producción se mantienen en redes privadas y nunca cruzan la internet pública, los desarrolladores inician sesión con Okta SSO, y los pipelines de CI se autentican como entidades de servicio.

Por qué el ramificación de bases de datos se adapta a CI/CD

Lakebase es la base de datos Postgres serverless de Databricks. Su almacenamiento y computación están separados, y admite bifurcaciones: puedes crear una rama nueva, aislada y escribible de una base de datos desde cualquier punto en el tiempo, de la misma manera que creas una rama de Git.

Las ramas son de copia en escritura (copy-on-write). Crear una rama es una operación de metadatos, por lo que no se copia ningún dato cuando se crea la rama. Una rama nueva comparte páginas de almacenamiento con su rama principal, y solo las páginas que la rama cambia se escriben como almacenamiento nuevo. Para CI, esto significa:

  • Crear una rama toma segundos, no minutos. No depende del tamaño de la base de datos.
  • El almacenamiento crece con los cambios que realiza cada rama, no con el tamaño de la base de datos. Cada una de las ramas de PR de Snorkel escribe entre 5 y 10 GB de cambios además de una base de ~1 TB.
  • La computación es por rama y se escala a cero. Cada rama tiene su propia computación de autoescalado, que se reduce a cero entre ejecuciones de CI. Incluso con 100 ramas aprovisionadas, Snorkel espera que solo entre 20 y 30 atiendan tráfico al mismo tiempo, a unas 5 consultas por segundo cada una en el pico.

La arquitectura

image1.png

1. Mantén una copia fresca de producción en la rama principal. Lakebase es Postgres estándar, por lo que funciona como destino para AWS DMS sin herramientas personalizadas. Snorkel apunta una tarea de DMS a su base de datos Aurora de producción y la replica en la rama principal del proyecto Lakebase: primero una carga completa, luego la captura continua de datos de cambios (CDC) que mantiene la principal a unos 2 minutos de la producción. El modo LOB completo transfiere los valores JSONB de 10 a 20 MB. El equipo ya ejecuta DMS, por lo que no hubo que construir ni mantener ningún pipeline de replicación nuevo. La rama principal es la "copia dorada" de la que parte cada rama de PR.

2. Crea una rama cuando se abre un PR. Cuando un desarrollador abre un PR, el pipeline de CI llama a la API de Lakebase para crear una rama a partir de principal, le establece un tiempo de expiración y pasa los detalles de conexión de la rama al espacio de nombres del PR. La rama está lista en menos de un minuto.

3. Ejecuta pruebas con datos reales. La aplicación en el espacio de nombres del PR se conecta a su rama a través de Postgres estándar. Las pruebas pueden ejecutar migraciones, escribir datos y cambiar esquemas sin afectar la producción, la principal ni ningún otro PR.

4. Elimina la rama cuando se cierra el PR o se pasan las pruebas, con TTL como red de seguridad. Cuando el PR se fusiona o se cierra, el pipeline elimina la rama. Si ese paso de limpieza no se ejecuta, la rama expira por sí sola cuando se agota su TTL.

Seguridad: redes privadas e identidad para humanos y pipelines

Dos requisitos de seguridad descartaron otras opciones, por lo que merecen su propia sección.

Conectividad privada. Los datos de producción se mueven de Aurora a Lakebase, y de Lakebase al clúster de CI, a través de redes privadas en lugar de la internet pública.

Identidad. Snorkel tiene dos tipos de usuarios de base de datos: desarrolladores que se conectan interactivamente para depurar un entorno de PR, y pipelines de CI que se ejecutan sin intervención humana. Okta SSO está diseñado en torno al inicio de sesión interactivo en el navegador, por lo que dividimos el diseño por tipo de usuario:

  • Desarrolladores: Okta está federado con la cuenta de Databricks, y los usuarios se aprovisionan a través de SCIM. Los desarrolladores inician sesión con su identidad habitual de Okta.
  • Pipelines de CI: Cada espacio de nombres de PR se ejecuta como una entidad de servicio de Databricks (con ámbito por equipo o por repositorio), también aprovisionada a través de SCIM. El pod de PR utiliza las credenciales de la entidad de servicio para obtener tokens OAuth de Lakebase de corta duración a través del SDK de Databricks, y los actualiza durante las ejecuciones de pruebas largas. No hay contraseñas de bases de datos de larga duración en CI.
  • Auditoría: Los registros de auditoría de Postgres registran la identidad de la entidad de servicio para cada consulta, por lo que cada consulta se puede rastrear hasta el pipeline que la ejecutó.

Por qué la copia en escritura y la expiración de ramas mantienen a CI rápido y económico

Dos características de Lakebase hacen que este patrón funcione a escala: la ramificación por copia en escritura y la expiración de ramas (TTL).

image3.png

La copia en escritura hace que las ramas sean instantáneas. Una rama nueva no copia ningún dato. Apunta a las páginas de almacenamiento existentes de su rama principal, y solo las páginas que la rama modifica se escriben como almacenamiento nuevo. Crear una rama a partir de una copia de producción de ~1 TB toma casi el mismo tiempo que crear una a partir de una base de datos de 1 GB: segundos, no los ~20 minutos que tomaba una restauración completa. Cada espacio de nombres de PR obtiene su propia copia de producción aislada y escribible de inmediato.

La copia en escritura hace que las ramas sean económicas. Cada rama comparte la mayor parte de sus datos con la principal, por lo que el almacenamiento crece con los cambios que realiza cada rama, y no con el tamaño de la base de datos. Para Snorkel, eso es de unos 5 a 10 GB por rama de PR además de la base compartida. La computación es por rama y se escala a cero cuando está inactiva, por lo que solo las ramas que ejecutan pruebas activamente utilizan computación.

La expiración de ramas la mantiene económica a lo largo del tiempo. La copia en escritura ahorra más cuando las ramas son de corta duración. Una rama conserva la versión de los datos que existía cuando se creó. A medida que DMS sigue actualizando la principal con los cambios de producción, una rama que permanece activa sigue reteniendo esas páginas más antiguas, por lo que el almacenamiento que utiliza crece con el tiempo. Configurar un TTL en cada rama de CI significa que cada rama se elimina automáticamente una vez que su PR termina. Esto mantiene el almacenamiento cerca del tamaño de la base de producción más los cambios de los PR activos.

El mismo patrón funciona para los agentes de IA

Los espacios de nombres de PR no son las únicas cargas de trabajo que necesitan una copia desechable de producción. Los agentes de IA que escriben SQL, ejecutan migraciones o cambian datos también necesitan un lugar seguro para probar cosas, y la ramificación por copia en escritura les proporciona uno.

Una rama por tarea de agente. Cada ejecución de agente obtiene su propia rama de la principal. El agente puede leer datos reales, escribir en ellos e incluso cambiar el esquema sin tocar la producción ni el trabajo de ningún otro agente. Crear una rama toma segundos sin importar cuán grande sea la base de datos, por lo que es práctico crear una para cada tarea.

Muchos agentes en paralelo. El almacenamiento solo crece con las páginas que cambia cada rama, y la computación de cada rama se escala a cero cuando está inactiva. Ejecutar decenas de agentes codo a codo cuesta más o menos lo mismo que los cambios que realizan, en lugar de decenas de copias de la base de datos.

Revisa los cambios o descártalos. Los equipos pueden verificar lo que un agente cambió en su rama antes de aplicar cualquier cosa a producción. Si el resultado no es el correcto, eliminan la rama y no hay nada que revertir.

Los TTLs limpian después de los agentes. Los agentes pueden crear muchas ramas de corta duración. Una fecha de caducidad en cada rama elimina las abandonadas automáticamente, del mismo modo en que los TTLs limpian las ramas de CI.

Identidad delimitada para agentes. Al igual que las canalizaciones de CI, los agentes pueden ejecutarse como entidades de servicio con tokens de OAuth de corta duración, por lo que cada consulta que ejecuta un agente se puede rastrear en los registros de auditoría.

Resultados

  • Tiempo de aprovisionamiento: más de 30 minutos antes, menos de 60 segundos con Lakebase [VERIFY p95 measured]
  • Escala: Diseñado para unos 100 PR branches concurrentes en un conjunto de datos de producción de ~2.5 TB
  • Compatibilidad: El conjunto de CI se ejecuta en Lakebase sin "problemas importantes de compatibilidad" / rendimiento en comparación con Aurora
  • Adopción: Implementación para 60 o 70 desarrolladores en todos los equipos
  • Cita de desarrollador: "Anteriormente teníamos que copiar datos físicamente y esos trabajos de copia tomaban horas y con frecuencia se encontraban con cuellos de botella de red y de otro tipo con varias plataformas de CI (github actions, circle ci, etc.). Estábamos buscando una solución que cumpla con nuestros requisitos de seguridad y cumplimiento si los datos salen de nuestra VPC"

Mejores prácticas para la creación de ramas de Lakebase en CI/CD

  1. Una rama por PR, creada a partir de una rama principal sincronizada continuamente.
  2. Establece siempre un TTL. Trata la caducidad como obligatoria, no opcional. Ajústala a la duración habitual de un PR o ejecución de prueba.
  3. Crea una nueva rama en lugar de conservar una antigua. Si un PR necesita datos más actualizados, crea una nueva rama a partir de la principal. Solo toma unos segundos.
  4. Permite que el cómputo se reduzca a cero. La mayoría de las ramas aprovisionadas están inactivas en un momento dado.
  5. Utiliza entidades de servicio y tokens de OAuth de corta duración para las canalizaciones, y SSO para las personas.
  6. Monitorea el almacenamiento por rama para detectar tempranamente las ramas de larga duración.

¿Estás listo para darle a cada pull request su propia base de datos similar a la de producción? Comienza con Lakebase y lee la documentación sobre ramificación para configurar la caducidad de las ramas en tu canalización de CI.

(Esta entrada del blog ha sido traducida utilizando herramientas basadas en inteligencia artificial) Publicación original

Etiquetas relacionadas:

Tecnología

Recibe las últimas publicaciones en tu bandeja de entrada

Suscríbete a nuestro blog y recibe las últimas publicaciones directamente en tu bandeja de entrada.