본문으로 건너뛰기

5.4 Xata OSS와 Kubernetes

Neon이 PostgreSQL을 패치해 저장 엔진을 바꿨다면, Xata는 PostgreSQL을 변경하지 않고 블록 스토리지 계층에서 copy-on-write를 구현했습니다. 2026년에 Xata 플랫폼의 핵심이 Apache 2.0으로 공개되었습니다. 이에 따라 Kubernetes 클러스터가 있는 조직은 vanilla PostgreSQL로 branching과 scale-to-zero를 자체 운영할 수 있게 되었습니다. 이 장에서는 공개 범위와 구조, quickstart를 정리합니다. Kubernetes 클러스터가 필요하므로 이 노트에서는 실측하지 않았습니다.

요약

  • CoW는 파일시스템(ZFS)이나 저장 엔진(Neon)이 아니라 네트워크 블록 장치 계층에서 일어납니다. 새 branch는 부모의 블록 인덱스 메타데이터를 가리키며, 쓰기가 발생한 블록만 복제됩니다.
  • PostgreSQL 소스를 패치하지 않으므로 upstream 동작과 확장 ABI가 유지됩니다. 다만 선택할 수 있는 이미지와 preload library, 업그레이드 범위는 플랫폼이 정합니다(문서 기준). 따라서 모든 확장과 버전을 사용할 수 있다는 뜻은 아닙니다.
  • 기반은 CloudNativePG(PostgreSQL operator)와 OpenEBS(Mayastor 복제 엔진)입니다.
  • 공식 입장은 "단일 PostgreSQL 인스턴스에는 과하다"입니다. 여러 팀이 branch를 많이 만드는 환경을 위한 플랫폼입니다.

공개된 것과 공개되지 않은 것

구성 요소공개 여부
SQL gateway (라우팅, IP 필터)Apache 2.0
branch operator (Kubernetes 리소스 관리)Apache 2.0
clusters, projects control plane 서비스Apache 2.0
인증 서비스 (Keycloak 기반)Apache 2.0
xata CLIApache 2.0
scale-to-zero CNPG pluginApache 2.0
pgroll, pgstreamApache 2.0 (별도 저장소, 이전부터 공개)
Xatastor 스토리지 엔진비공개
다중 조직, 다중 리전 배포 코드비공개

공개 범위의 경계가 Neon과 정확히 반대입니다. Neon은 저장 엔진이 공개이고 control plane은 비공개입니다. 반면 Xata는 control plane과 branch operator가 공개이고 자사 스토리지 엔진 Xatastor는 비공개입니다. 오픈소스 버전은 Xatastor 대신 OpenEBS Mayastor 위에서 동작합니다. 공식 블로그는 OSS 버전에 "적대적 멀티테넌시 관련 보안 기능"이 없으므로 공개 PaaS 용도에는 맞지 않는다고 밝힙니다.

구조

branch를 만들면 operator가 부모 볼륨의 CoW clone을 만들고, 그 위에서 CloudNativePG cluster를 하나 더 실행합니다. 각 branch는 완전한 PostgreSQL 프로세스이므로 DBLab처럼 branch마다 메모리를 소비합니다. 다만 scale-to-zero plugin이 유휴 branch의 compute를 중지해 비용을 줄입니다. 블록 볼륨은 NVMe-oF로 네트워크에 연결됩니다. 공식 블로그는 "수십만 IOPS"를 언급합니다.

quickstart

로컬 Kubernetes(kind)와 Tilt로 전체 스택을 실행하는 절차가 저장소 README에 있습니다. README에 명시된 선행 조건은 Docker, kind, Tilt 세 가지입니다. tilt up은 현재 디렉터리의 Tiltfile을 읽습니다. 따라서 저장소를 먼저 받은 뒤 그 안에서 실행합니다.

git clone https://github.com/xataio/xata.git
cd xata

kind create cluster --wait 10m
tilt up # 첫 실행은 이미지 전체를 내려받으므로 오래 걸립니다

curl -fsSL https://xata.io/install.sh | bash
xata auth login --profile local \
--issuer http://localhost:8080/realms/xata \
--api-url http://localhost:5001 --client-secret devsecret
xata auth switch local
xata project create --name my-project
xata branch create

tilt up은 control plane, Keycloak, CNPG operator, OpenEBS를 kind 클러스터에 배포합니다. README는 첫 실행이 이미지 다운로드 때문에 오래 걸리지만, 다음 실행부터는 빨라진다고 안내합니다. 브라우저 로그인 화면이 나타나면 로컬 개발용 계정 dev@xata.tech와 README에 적힌 비밀번호를 사용합니다.

로컬 kind에서는 복제 없는 로컬 스토리지를 사용하고, 운영에서는 Mayastor 복제 볼륨을 사용합니다. macOS에서 kind 자체는 동작합니다. 하지만 Mayastor는 아래 "운영에 넣기 전에 확인할 것"의 Linux 커널 요구사항을 충족해야 하므로 CoW 성능은 Linux 노드에서 따로 검증합니다.

Neon, DBLab과 다른 점

Xata OSS 도입에는 PostgreSQL을 Kubernetes에서 CloudNativePG로 운영하겠다는 결정이 포함됩니다. 이미 그렇게 운영 중인 팀이라면 branch operator를 추가하는 정도의 변화입니다. 그러나 VM 위에서 systemd로 PostgreSQL을 실행하는 팀에는 플랫폼 교체에 해당합니다. 반면 DBLab은 기존 운영 방식을 바꾸지 않고 함께 도입할 수 있습니다.

Neon과 비교했을 때 가장 큰 차이는 vanilla PostgreSQL이라는 점입니다. Neon의 Postgres 패치가 부담스럽거나 특정 확장이 필요하다면 Xata 방식이 적합합니다. 대신 Neon의 page-version 단위 history(임의 LSN에서 branch)는 없습니다. 볼륨 snapshot 시점에서만 분기합니다.

pgroll과 pgstream

Xata가 먼저 공개한 두 도구는 branching 없이도 유용합니다. pgroll은 schema 변경을 "확장 → 이중 쓰기 → 축소" 단계로 나눕니다. 두 schema 버전을 동시에 서비스하는 zero-downtime 마이그레이션 도구입니다. pgstream은 DDL까지 포함한 logical replication 스트림을 다른 PostgreSQL이나 검색 엔진으로 보내는 CDC 도구입니다. Xata가 제시하는 흐름은 branch에서 마이그레이션을 검증한 뒤 운영에 pgroll로 적용하는 것입니다. 이어서 pgstream으로 마스킹된 데이터를 개발 branch에 채웁니다.

Xata 클라우드와 OSS의 차이

항목Xata 클라우드Xata OSS
스토리지 엔진Xatastor (비공개)OpenEBS Mayastor 또는 로컬 스토리지
멀티리전, 멀티조직지원코드 비공개
적대적 멀티테넌시 보안포함미포함 (공식 블로그 명시)
branch 생성 시간공식 블로그 기준 1~2초 (초기 20초 이상에서 개선)스토리지 클래스에 따라 다름
운영 주체Xata도입 조직

공식 블로그 "A thousand Postgres branches for $1"이 강조하는 경제성은 CoW 스토리지와 scale-to-zero의 조합에서 나옵니다. OSS에서도 같은 조합을 사용하지만, 그 비용은 Kubernetes 노드와 스토리지 운영 비용으로 바뀝니다. branch 1,000개가 저렴하다는 주장은 유휴 branch의 compute가 중지되어 있다는 전제에 기반합니다. 따라서 scale-to-zero plugin 없이 운영하면 branch 수만큼 PostgreSQL 프로세스가 메모리를 점유합니다.

운영에 넣기 전에 확인할 것

Mayastor(OpenEBS Replicated PV)의 전제 조건은 공식 문서에 수치로 정리되어 있습니다.

항목요구값
Linux 커널5.13 이상, 5.15 권장
커널 모듈nvme-tcp, ext4 (선택적으로 xfs)
hugepageIO-engine 노드마다 2 MiB 페이지 1,024장, 즉 2 GiB
IO-engine 전용 자원노드마다 CPU 2코어, RAM 1 GiB
CPUSSE4.2를 지원하는 x86-64
worker 노드최소 3대, N-way 미러링이면 복제 수 이상
전송NVMe-oF TCP

hugepage는 페이지 한 장이 아니라 총 2 GiB라는 점을 놓치기 쉽습니다. io_uring은 필수 조건 목록에 없습니다. AIO 계열 backend도 사용하므로 io_uring은 선택 가능한 구성으로 보는 편이 맞습니다.

PVC snapshot과 clone을 CSI 드라이버가 지원하는지도 확인해야 합니다. branch operator가 부모 볼륨에서 CoW clone을 만드는 경로는 CSI VolumeSnapshot과 clone 기능을 기반으로 하기 때문입니다.

CloudNativePG에서는 branch마다 cluster 리소스가 생깁니다. 따라서 operator의 리소스 한도와 namespace 정책을 미리 정합니다. 팀마다 namespace를 나누는 구조라면 gateway의 라우팅 규칙과 Keycloak realm 설계도 함께 필요합니다. 인증 서비스가 Keycloak 기반이므로 사내 SSO(OIDC)와 연동하기 쉽습니다.

주의할 점

  • kind에서 동작하는 것과 Mayastor 복제 볼륨에서 동작하는 것은 서로 다른 검증입니다. 로컬 스토리지에서는 CoW clone이 아닌 전체 복사로 동작하는 스토리지 클래스도 있습니다. 이 경우 branch 생성 시간이 데이터 크기에 비례할 수 있습니다.
  • 부모 branch를 삭제할 때 자식 볼륨의 블록 소유권 처리는 스토리지 계층의 규칙을 따릅니다. 삭제 전에 자식 branch 목록을 확인하는 절차를 운영 문서에 추가합니다.
  • OSS 버전은 자사 PaaS를 만들기 위한 것이 아니라고 Xata가 밝혔습니다. 외부 고객에게 branch를 제공하는 용도라면 BYOC 상용 옵션이 전제입니다.

심화 체크

  • branch operator가 만드는 Kubernetes 리소스(CNPG Cluster, PVC, Service)를 나열하고, 어느 것이 CoW 대상이고 어느 것이 새로 생성되는지 구분했는가?
  • scale-to-zero plugin이 compute를 중지한 branch에 첫 접속이 들어올 때 gateway가 어떻게 처리하는지 확인했는가?
  • pgstream으로 마스킹 데이터를 채우는 경로와 CoW branch에서 원본 데이터를 그대로 받는 경로 중 어느 것이 조직의 데이터 정책에 맞는지 결정했는가?

연습 문제

  1. Neon, DBLab, Xata 세 방식에서 "branch 하나가 소비하는 메모리"가 어디서 결정되는지 각각 적습니다.
  2. 이미 CloudNativePG로 운영 중인 클러스터에 Xata branch operator를 추가할 때 스토리지 클래스에서 확인할 조건을 나열합니다.
  3. kind 환경에서 xata branch create가 어떤 Kubernetes 리소스를 만드는지 kubectl get으로 추적하는 계획을 세웁니다.

참고