주요 컨텐츠로 이동
산업

CI/CD를 위한 Lakebase 브랜칭: 100개의 PR 데이터베이스에서 얻은 교훈

쓰기 시 복사 브랜칭을 통해 CI/CD 테스트 및 에이전트 유스케이스를 위해 프로덕션 데이터의 격리된 복사본을 빠르고 저렴하게 만들 수 있습니다.

작성자: Yasamin Tari , Kartik Mathur

  • Snorkel AI의 CI/CD 파이프라인은 열린 모든 풀 리퀘스트에 개별 Lakebase Postgres 브랜치를 제공합니다. 이 브랜치는 기존에 30분 이상 걸리던 프로덕션 데이터의 읽기/쓰기 복사본을 1분 이내에 생성하므로, 기존에는 PR별 복사 기능을 활성화할 수 없었습니다.
  • Lakebase 브랜치는 쓰기 시 복사(copy-on-write) 방식을 사용하므로, 약 2.5 TB의 프로덕션 데이터셋에서 100개의 동시 PR 데이터베이스가 실행되어도 각 브랜치에서 변경된 데이터의 스토리지마저 추가될 뿐입니다. PR이 완료되면 브랜치 만료(TTL) 기능이 각 브랜치를 자동으로 정리하므로 스토리지는 프로덕션 크기에 활성 PR의 변경사항이 더해진 수준으로 유지됩니다.
  • 프라이빗 연결과 Okta SSO 지원을 통해 관리되고 안전한 환경을 제공합니다.

문제점: 프로덕션 데이터를 사용한 테스트에 30분 이상 소요되어서는 안 됩니다.

Snorkel AI는 전문가 수준의 데이터 주석 작성자와 최첨단 모델 제공업체가 사용하는 AI 팀용 데이터 개발 도구를 만듭니다. 이 특정 사용 사례에서 Snorkel은 Kubernetes 기반의 CI 파이프라인을 통해 코드를 배포합니다. 모든 열린 풀 리퀘스트(PR)와 임시 커밋에는 독립적인 임시 Kubernetes 네임스페이스(이하 "PR 네임스페이스")가 할당됩니다. 개발자는 해당 브랜치에 코드를 배포하고 병합하기 전에 전체 테스트 스위트를 실행합니다.

이러한 테스트는 실제 데이터를 기반으로 실행될 때 가장 유용합니다. Snorkel의 프로덕션 데이터베이스는 Amazon Aurora PostgreSQL 클러스터입니다. 각 PR 네임스페이스에 해당 데이터베이스의 복사본을 제공하는 것이 어려운 부분이었습니다. 복사본을 복원하는 데 환경당 약 20분이 소요되었는데, 개발자들이 하루 종일 PR을 열고 병합 큐가 실행될 때마다 새로운 환경이 필요한 상황에서는 너무 느린 속도입니다. 대안(공유 스테이징 데이터베이스, 축소된 픽스처 또는 합성 데이터)을 사용하면 프로덕션 환경과 유사한 테스트를 통해 해결하고자 했던 문제들, 즉 테스트 간의 간섭, 오래된 스키마, 그리고 실제 데이터 형태에서만 나타나는 버그들이 다시 발생하게 됩니다.

성공 기준

Snorkel은 Lakebase가 다음 기준을 충족할 경우 CI/CD 관점에서 성공적이라고 판단합니다.

  • 빠른 프로비저닝: 새로운 PR 브랜치가 60초 이내에 준비됩니다(p95 기준).
  • 규모: 피크 시간대에 약 100개의 동시 PR 브랜치가 각각 독립적인 읽기 및 쓰기 작업을 수행합니다.
  • 호환성: 기존 애플리케이션 및 CI 스위트가 표준 Postgres를 통해 Lakebase에서 실행되며, Aurora와 유사한 성능을 제공하고 대용량 JSONB/LOB 컬럼을 지원합니다.
  • 최신 데이터: 지속적인 DMS 복제를 통해 메인 브랜치가 프로덕션 Aurora와 약 2분 이내의 차이를 유지합니다.
  • 보안: 프로덕션 데이터는 비공개 네트워킹에 유지되며 공용 인터넷을 거치지 않고, 개발자는 Okta SSO로 로그인하며, CI 파이프라인은 서비스 주체로 인증을 수행합니다.

데이터베이스 브랜칭이 CI/CD에 적합한 이유

Lakebase는 Databricks의 서버리스 Postgres 데이터베이스입니다. 스토리지와 컴퓨팅이 분리되어 있으며 브랜칭을 지원합니다. Git 브랜치를 생성하는 것과 같은 방식으로 특정 시점에서 데이터베이스의 새롭고 격리된 쓰기 가능한 브랜치를 생성할 수 있습니다.

브랜치는 쓰기 시 복사(copy-on-write) 방식으로 작동합니다. 브랜치 생성은 메타데이터 작업이므로 브랜치가 생성될 때 데이터가 복사되지 않습니다. 새 브랜치는 부모와 스토리지 페이지를 공유하며, 브랜치에서 변경된 페이지만 새로운 스토리지로 기록됩니다. CI 관점에서 이는 다음을 의미합니다.

  • 브랜치 생성은 몇 분이 아니라 몇 초 만에 완료됩니다. 데이터베이스 크기에 의존하지 않습니다.
  • 토리지는 데이터베이스 크기가 아니라 각 브랜치가 만드는 변경사항에 따라 증가합니다. Snorkel의 각 PR 브랜치는 약 1TB의 기본 데이터 위에 약 5~10GB의 변경사항을 기록합니다.
  • 컴퓨팅은 브랜치별로 제공되며 제로(0)로 자동 확장됩니다. 각 브랜치는 자체적인 자동 확장 컴퓨팅을 가지며, CI 실행 사이에는 제로로 축소됩니다. 100개의 프로비저닝된 브랜치가 있더라도 Snorkel은 피크 시간대에 초당 약 5회의 쿼리를 처리하며 동시에 트래픽을 처리하는 브랜치는 약 20~30개 정도일 것으로 예상합니다.

아키텍처

image1.png

1. 메인 브랜치에 프로덕션의 최신 복사본 유지. Lakebase는 표준 Postgres이므로 사용자 지정 도구 없이 AWS DMS의 타겟으로 작동합니다. Snorkel은 프로덕션 Aurora 데이터베이스에 DMS 작업을 지정하고 이를 Lakebase 프로젝트의 메인 브랜치에 복제합니다. 먼저 전체 로드를 수행한 다음 지속적인 변경 데이터 캡처(CDC)를 통해 메인 브랜치를 프로덕션과 약 2분 이내의 차이로 유지합니다. 전체 LOB 모드는 10~20MB의 JSONB 값을 그대로 유지합니다. 팀에서 이미 DMS를 실행하고 있었기 때문에 새로 구축하거나 유지 관리해야 할 복제 파이프라인이 없었습니다. 메인 브랜치는 모든 PR 브랜치가 시작되는 "골든 카피"입니다.

2. PR이 열릴 때 브랜치 생성. 개발자가 PR을 열면 CI 파이프라인이 Lakebase API를 호출하여 메인 브랜치에서 브랜치를 생성하고, 여기에 만료 시간을 설정한 후, 브랜치 연결 세부 정보를 PR 네임스페이스에 전달합니다. 브랜치는 1분 이내에 준비됩니다.

3. 실제 데이터를 사용하여 테스트 실행. PR 네임스페이스의 애플리케이션은 표준 Postgres를 통해 해당 브랜치에 연결됩니다. 테스트는 프로덕션, 메인 또는 다른 PR에 영향을 주지 않고 마이그레이션을 실행하고, 데이터를 쓰고, 스키마를 변경할 수 있습니다.

4. PR이 닫히거나 테스트가 통과할 때 TTL을 안전장치로 사용하여 브랜치 삭제. PR이 병합되거나 닫히면 파이프라인이 브랜치를 삭제합니다. 정리 단계가 실행되지 않더라도 TTL이 만료되면 브랜치가 자동으로 소멸됩니다.

보안: 인간과 파이프라인을 위한 비공개 네트워킹 및 신원 확인

두 가지 보안 요구사항으로 인해 다른 옵션이 배제되었으므로 별도의 섹션에서 다룹니다.

비공개 연결. 프로덕션 데이터는 공용 인터넷 대신 비공개 네트워킹을 통해 Aurora에서 Lakebase로, 그리고 Lakebase에서 CI 클러스터로 이동합니다.

신원 확인. Snorkel에는 두 가지 유형의 데이터베이스 사용자가 있습니다. PR 환경을 디버깅하기 위해 대화형으로 연결하는 개발자와 인간의 개입 없이 실행되는 CI 파이프라인입니다. Okta SSO는 대화형 브라우저 로그인을 중심으로 구축되어 있으므로 사용자 유형별로 설계를 분리했습니다.

  • 개발자: Okta는 Databricks 계정에 페더레이션되며, 사용자는 SCIM을 통해 프로비저닝됩니다. 개발자는 평소 사용하는 Okta 계정으로 로그인합니다.
  • CI 파이프라인: 각 PR 네임스페이스는 (팀별 또는 저장소별로 범위가 지정된) Databricks 서비스 주체로 실행되며, 이 역시 SCIM을 통해 프로비저닝됩니다. PR 파드는 서비스 주체의 자격 증명을 사용하여 Databricks SDK를 통해 수명이 짧은 Lakebase OAuth 토큰을 가져오고, 긴 테스트 실행 중에 이를 갱신합니다. CI에는 수명이 긴 데이터베이스 비밀번호가 존재하지 않습니다.
  • 감사: Postgres 감사 로그는 각 쿼리에 대한 서비스 주체 신원을 기록하므로 모든 쿼리를 이를 실행한 파이프라인까지 추적할 수 있습니다.

쓰기 시 복사와 브랜치 만료가 CI를 빠르고 저렴하게 유지하는 이유

두 가지 Lakebase 기능 덕분에 이 패턴이 대규모로 작동할 수 있습니다. 바로 쓰기 시 복사 브랜칭과 브랜치 만료(TTL)입니다.

image3.png

쓰기 시 복사로 브랜치를 즉시 생성. 새 브랜치는 데이터를 복사하지 않습니다. 부모의 기존 스토리지 페이지를 가리키고, 브랜치가 수정하는 페이지만 새 스토리지로 기록됩니다. ~1TB 규모의 프로덕션 복사본에서 브랜치를 생성하는 것은 1GB 데이터베이스에서 생성하는 것과 거의 비슷하게 수 초 만에 완료됩니다. 전체 복원에 ~20분이 걸렸던 것과 달리 몇 초면 충분합니다. 각 PR 네임스페이스는 프로덕션의 격리되고 쓰기 가능한 복사본을 즉시 얻게 됩니다.

쓰기 시 복사로 비용 절감. 모든 브랜치가 대부분의 데이터를 메인과 공유하므로 스토리지는 데이터베이스 크기가 아니라 각 브랜치가 만드는 변경사항에 따라 증가합니다. Snorkel의 경우 공유 기본 데이터 위에 PR 브랜치당 약 5~10GB가 추가됩니다. 컴퓨팅은 브랜치별로 제공되며 유휴 상태일 때는 제로로 확장되므로, 실제로 테스트를 활발하게 실행 중인 브랜치만 컴퓨팅을 사용합니다.

브랜치 만료로 장기적인 비용 절감 유지. 쓰기 시 복사는 브랜치의 수명이 짧을 때 가장 큰 절감 효과를 냅니다. 브랜치는 생성될 당시 존재하던 데이터 버전을 유지합니다. DMS가 프로덕션 변경사항으로 메인을 계속 업데이트함에 따라, 유지되는 브랜치는 계속해서 이전 페이지를 보유하게 되므로 사용하는 스토리지 크기가 시간이 지남에 따라 증가합니다. 모든 CI 브랜치에 TTL을 설정하면 PR이 완료되는 즉시 각 브랜치가 자동으로 제거됩니다. 이를 통해 스토리지를 프로덕션 베이스의 크기와 활성 PR의 변경사항을 합친 수준으로 유지할 수 있습니다.

AI 에이전트에도 동일한 패턴 적용

프로덕션의 일회성 복사본이 필요한 워크로드는 PR 네임스페이스만이 아닙니다. SQL을 작성하고, 마이그레이션을 실행하고, 데이터를 변경하는 AI 에이전트 역시 작업을 시도해 볼 안전한 장소가 필요하며, 쓰기 시 복사 브랜칭이 이를 제공합니다.

에이전트 작업당 하나의 브랜치. 각 에이전트 실행에는 메인의 자체 브랜치가 할당됩니다. 에이전트는 프로덕션이나 다른 에이전트의 작업에 영향을 주지 않고 실제 데이터를 읽고, 쓰고, 심지어 스키마를 변경할 수 있습니다. 데이터베이스 크기에 상관없이 브랜치 생성에 몇 초밖에 걸리지 않으므로 모든 작업에 대해 브랜치를 생성하는 것이 실용적입니다.

다수의 에이전트를 병렬로 실행. 스토리지는 각 브랜치가 변경하는 페이지만큼만 증가하며, 각 브랜치의 컴퓨팅은 유휴 상태일 때 제로로 확장됩니다. 수십 개의 에이전트를 나란히 실행하는 비용은 데이터베이스의 수십 개 복사본이 아니라 에이전트가 만드는 변경사항의 비용만큼만 발생합니다.

변경사항 검토 또는 폐기. 팀은 프로덕션에 적용하기 전에 에이전트가 브랜치에서 무엇을 변경했는지 확인할 수 있습니다. 결과가 올바르지 않으면 브랜치를 삭제하기만 하면 되므로 롤백할 필요가 없습니다.

TTL은 에이전트 작업이 끝난 후 깔끔하게 정리해 줍니다. 에이전트는 수명이 짧은 브랜치를 많이 만들 수 있습니다. 각 브랜치에 만료 기한을 설정하면 CI 브랜치를 정리하는 것과 마찬가지로 사용하지 않는 브랜치를 자동으로 삭제합니다.

에이전트를 위한 범위 지정 ID. CI 파이프라인처럼 에이전트는 수명이 짧은 OAuth 토큰을 사용하는 서비스 주체(service principal)로 실행될 수 있으므로, 에이전트가 실행하는 모든 쿼리는 감사 로그(audit log)에서 추적할 수 있습니다.

결과

  • 프로비저닝 시간: 기존 30분 이상 소요에서 Lakebase 사용 시 60초 미만으로 단축 [VERIFY p95 measured]
  • 규모: 약 2.5TB 규모의 프로덕션 데이터셋에서 동시 실행되는 약 100개의 PR 브랜치 지원하도록 설계
  • 호환성: Aurora 대비 성능 및 "주요 호환성 문제 없음"으로 Lakebase에서 CI 스위트 실행 가능
  • 도입: 여러 팀에 걸쳐 60~70명의 개발자에게 롤아웃
  • 개발자 평가: "이전에는 데이터를 직접 복사해야 했고, 복사 작업에 몇 시간이 걸렸으며 다양한 CI 플랫폼(GitHub Actions, CircleCI 등)에서 네트워크 및 기타 병목 현상에 자주 부딪혔습니다. 데이터가 VPC를 벗어날 때 보안 및 컴플라이언스 요구 사항을 충족하는 솔루션을 찾고 있었습니다."

CI/CD에서 Lakebase 브랜치를 사용하는 모범 사례

  1. 계속 동기화되는 main 브랜치에서 생성된, PR당 하나의 브랜치를 사용하세요.
  2. 항상 TTL을 설정하세요. 만료 기한을 선택 사항이 아닌 필수로 취급하세요. PR이나 테스트 실행이 보통 지속되는 시간에 맞추세요.
  3. 오래된 브랜치를 유지하는 대신 새 브랜치를 만드세요. PR에 더 최신 데이터가 필요한 경우 main 브랜치에서 새 브랜치를 만드세요. 몇 초면 됩니다.
  4. 컴퓨팅 리소스가 0으로 확장되도록 하세요. 프로비저닝된 대부분의 브랜치는 특정 시점에 유휴 상태입니다.
  5. 파이프라인에는 서비스 주체와 수명이 짧은 OAuth 토큰을 사용하고, 사용자에겐 SSO를 사용하세요.
  6. 브랜치별 스토리지를 모니터링하여 수명이 긴 브랜치를 일찍 찾아내세요.

모든 풀 리퀘스트에 프로덕션 환경과 유사한 자체 데이터베이스를 제공할 준비가 되셨나요? Lakebase 시작하기를 통해 브랜칭 문서를 읽고 CI 파이프라인에서 브랜치 만료를 설정해 보세요.

(이 글은 AI의 도움을 받아 번역되었습니다. 원문이 궁금하시다면 여기를 클릭해 주세요)

관련 태그:

기술

최신 게시물을 이메일로 받아보세요

블로그를 구독하고 최신 게시물을 이메일로 받아보세요.