본문 바로가기
WIKI 기술 지식 베이스

메타데이터 검색

원문 보기 위키 갱신

lakeFS Metadata Search는 객체 메타데이터로 대규모 데이터 레이크를 쉽게 검색할 수 있게 해 주면서, 검색에 버저닝의 힘을 더해 줘요. 덕분에 재현 가능한 쿼리가 가능해지는데, 이는 데이터가 끊임없이 진화하고 메타데이터가 합리적 의사 결정의 열쇠가 되는 협업·ML 중심 환경에서 필수적인 능력이에요.

출처: 문서

본문

lakeFS Team과 lakeFS Enterprise에서 사용할 수 있어요. 무료 평가판을 시작하거나 문의하세요.

참고

lakeFS Metadata search는 현재 lakeFS Enterprise 고객 대상 프라이빗 프리뷰예요. 시작하려면 문의하세요!

개요

Metadata Search에서는 다음 두 가지로 객체 메타데이터를 쿼리할 수 있어요:

  • 시스템 메타데이터: 객체 경로, 크기, 마지막 수정 시각, 커미터처럼 자동으로 수집되는 속성.

  • 사용자 정의 메타데이터: 수집, 처리, 큐레이션 중에 보통 추가되는 lakeFS 객체 메타데이터로 저장되는 커스텀 라벨, 어노테이션, 태그.

간단하고 확장 가능한 검색을 위해 lakeFS는 객체 메타데이터를 버저닝된 Iceberg 테이블로 노출해요. DuckDB, PyIceberg, Spark, Trino 같은 클라이언트와 완전히 호환돼요. 어느 lakeFS 버전에서든 빠르고 표현력 있는 쿼리가 가능하죠. 자세한 내용은 How It Works를 보세요. lakeFS Enterprise에서는 자체 클라이언트를 구성하지 않고도 lakeFS 웹 UI에서 같은 SQL을 실행할 수 있어요.

이점

  • 확장 가능: 수백만, 수십억 개 객체의 메타데이터를 검색해요.

  • 쿼리 재현성: 특정 커밋이나 태그에 대해 메타데이터 쿼리를 실행해 일관된 결과를 얻어요.

  • 인프라 부담 없음: lakeFS가 메타데이터 수집과 인덱싱을 네이티브로 관리해요. 별도의 메타데이터 추적 시스템을 만들고, 배포하고, 유지할 필요가 없어요.

사용 사례

  • 데이터 탐색: 유연한 필터(어노테이션, 객체 크기, 타임스탬프 등)로 관련 데이터를 빠르게 찾아요.

  • 데이터 거버넌스: 메타데이터 태그를 감사하고, 민감 데이터(PII 등)를 탐지하고, 소유권·분류 라벨이 제대로 붙어 있는지 확인해 내부 정책과 외부 규정 요구 사항을 충족시켜요.

  • 운영 문제 해결: 워크플로 ID나 게시 시각 같은 메타데이터로 데이터를 필터·조사해 계보(lineage)를 추적하고, 파이프라인 문제를 디버깅하고, 데이터가 어떻게 만들어졌거나 수정됐는지 파악해요. 물론 특정 lakeFS 버전 안에서요.

동작 방식

lakeFS Metadata Search는 lakeFS Iceberg 지원 위에 만들어져 있고, 카탈로그 수준 시스템 테이블을 사용해 버저닝된 객체 메타데이터를 관리하고 쿼리용으로 노출해요.

Metadata Search는 선택한 저장소와 브랜치에서 메타데이터 인덱싱을 켜는 방식으로 동작해요(Configuration 참고). 설정이 끝나면 lakeFS가 자동으로:

  • 선택된 각 데이터 저장소마다 메타데이터 저장소를 만들어요. 이름 규칙은 <repo>-metadata이고 repo는 데이터 저장소의 id예요.

  • 데이터 저장소의 설정된 각 브랜치마다 메타데이터 저장소에 대응되는 브랜치를 만들어요. 예컨대 데이터 저장소 my-repo의 dev 브랜치는 my-repo-metadata에 대응하는 dev 브랜치를 가져요.

  • 메타데이터 저장소의 각 대응 브랜치에서 버저닝된 Iceberg 객체 메타데이터 테이블을 유지해요.

  • 백그라운드 처리 파이프라인으로 메타데이터를 지속적으로 동기화해, 객체 메타데이터 테이블이 대응되는 데이터 저장소 브랜치의 변화와 최종적 일관성(eventual consistency)을 유지하게 해요.

  • lakeFS Iceberg REST 카탈로그를 래핑해, 데이터 저장소 참조(브랜치, 커밋, 태그)에 대해 발행된 테이블 쿼리를 번역하고 메타데이터 저장소의 대응 테이블로 해석해요. 이 간접 계층 덕분에 메타데이터 쿼리를 전부 데이터 저장소 네임스페이스로 표현할 수 있고, 하부 메타데이터 스토리지로의 매핑은 lakeFS가 알아서 처리해요.

메타데이터 쿼리하기

메타데이터 쿼리는 항상 데이터 저장소 네임스페이스를 통해 수행돼요. lakeFS가 내부적으로 관리하는 메타데이터 저장소가 아니에요. 다음 방법으로 메타데이터를 쿼리할 수 있어요:

  • 브랜치 이름: <repo>.<branch>.system.object_metadata — 주어진 브랜치의 최신 메타데이터 상태를 검색해요.

  • 커밋 ID: <repo>.<commit_id>.system.object_metadata — 특정 커밋 시점의 메타데이터 스냅샷을 가져와요.

  • 태그 이름: <repo>.<tag_name>.system.object_metadata — 태그가 붙은 커밋의 메타데이터 스냅샷을 가져와요.

팁

커밋 ID나 태그를 사용하면 쿼리가 재현 가능해져요. 불변의 시점에서 항상 정확한 메타데이터 상태에 접근할 수 있죠.

쿼리는 lakeFS Iceberg REST 카탈로그를 통해 실행돼요. Trino, DuckDB, Spark, PyIceberg 같은 표준 엔진과 완전히 호환돼요. 자신의 엔진을 카탈로그에 연결하거나, lakeFS 웹 UI에서 검색할 수 있어요. 웹 UI에서는 lakeFS 서버가 쿼리를 실행하죠.

정보

lakeFS의 풀 Iceberg 지원 라이선스가 없어도 Metadata Search를 사용할 수 있어요. 이 기능은 객체 메타데이터 쿼리를 위해 lakeFS 관리 Iceberg REST 카탈로그에 의존하지만, 추가 Iceberg 테이블을 관리하는 다른 카탈로그와 나란히 동작할 수 있어요.

객체 메타데이터 테이블 스키마

lakeFS 객체 메타데이터 테이블의 각 행은 대응 브랜치에서 주어진 객체의 최신 메타데이터 버전을 나타내요. 객체당 최대 한 행만 있어서 쿼리 성능이 일관되고 예측 가능하게 유지돼요.

컬럼 이름 필수 데이터 타입 설명
repository yes string 객체가 저장된 저장소의 이름이에요.
path yes string 저장소 안에서 객체를 식별하는 고유 경로예요.
commit_id yes string 객체가 추가되거나 수정된 최신 커밋 ID예요.
size_bytes yes Long 객체의 바이트 단위 크기예요.
last_modified yes Timestamp 객체가 마지막으로 수정된 시각이에요.
etag yes string 객체의 ETag(콘텐츠 해시)예요. 객체 콘텐츠의 변화만 반영하고 메타데이터 변화는 반영하지 않아요.
user_metadata no Map 사용자 정의 메타데이터(어노테이션, 태그 등). 없으면 빈 맵이 저장돼요.
committer no string 객체의 최신 변경을 커밋한 사용자예요.
content_type no string 객체의 MIME 타입(예: application/json, image/png)이에요.
creation_date no Timestamp commit_id에 기록된 커밋의 생성 시각이에요.

일관성

lakeFS 객체 메타데이터 테이블은 최종적 일관성(eventual consistency)을 가져요. 즉 새로 커밋된 객체가 검색 가능해지기까지 몇 분이 걸릴 수 있어요. 메타데이터는 원자적으로(atomic) 검색 가능해져요 — 커밋의 객체 메타데이터가 전부 제공되거나 전혀 제공되지 않아요. 커밋은 순차적으로 처리돼요: 자식 커밋은 부모 커밋이 완전히 수집된 후에 처리돼요.

팁

브랜치의 최신 상태가 메타데이터 검색 쿼리에 사용 가능한지 확인하려면 다음 쿼리가 결과를 반환하는지 보세요:

USE "<repo>.<branch>.system";
SELECT * FROM object_metadata
WHERE commit_id = <head_commit> -- Replace with the head commit ID of the branch you are looking at
LIMIT 1;

시작하기

설정

lakeFS Metadata Search는 lakeFS 서버와 통합되는 별도 서비스로 동작해요.

lakeFS Enterprise를 직접 호스팅(self-hosting)하는 경우:

  • 문의해서 기능을 활성화하세요.

  • 아래 설정을 Helm values 파일에 추가하세요.

  • 갱신된 설정으로 Helm 차트를 설치하거나 업그레이드하세요.

참고

lakefs Helm 차트 버전 1.10.0부터 Metadata Search 서비스는 레거시 독립형 treeverse/mds 이미지 대신 treeverse/lakefs-enterprise 이미지로(lakefs mds run으로 호출) 동작해요. 차트의 mds.config 블록은 아래에 문서화된 스키마를 사용해요.

이전 버전에서 차트 >= 1.10.0으로 업그레이드하는 경우: 설정 스키마가 바뀌었어요. 기존 설치는 업그레이드 전에 mds.config를 새 키로 이전해야 해요 (예: lakefs.endpoint → metadata_search.lakefs_mds_endpoint, lakefs.secret_access_key → metadata_search.secret_key, 그리고 metadata_settings.* 키들은 metadata_search 아래로 이동).

lakeFS Cloud를 사용하는 경우:

문의해서 기능을 활성화하세요. 아래 샘플 설정에 포함된 정보를 요청드릴 거예요.

Metadata Search 서비스에 필요한 것:

  • lakeFS 서버 연결 설정: 서비스가 lakeFS 인스턴스와 통신할 수 있게 해요.

  • 메타데이터별 설정: 메타데이터를 어떻게 수집하고 어느 저장소·브랜치를 검색 가능하게 할지 제어해요.

설정 레퍼런스

모든 설정은 최상위 metadata_search 키 아래에 있어요.

  • lakefs_mds_endpoint (string : "") - lakeFS 서버 엔드포인트. 필수.

  • access_key_id (string : "") - lakeFS 액세스 키.

  • secret_key (string : "") - lakeFS 시크릿 키.

  • listen_address (string : "0.0.0.0:8080") - 서비스의 운영 엔드포인트(/_health, /metrics, /_pprof/)를 서빙하는 HTTP listen 주소.

  • period (duration : 60s) - 메타데이터 수집 패스 사이의 간격.

  • concurrency (int : 25) - 병렬로 처리되는 브랜치 수.

  • max_commits (int : 1000) - 검색 가능한 브랜치당 처리할 최대 커밋 수.

  • since (string : "") - 메타데이터 추출을 위해 커밋을 처리할 가장 이른 시점을 정하는 RFC 3339 타임스탬프 (예: 2025-01-01T00:00:00Z). 생략하면 브랜치가 생성된 시점부터 메타데이터가 수집돼요.

  • repositories (map[string]repo : {}) - 저장소별 설정으로의 매핑. 이 맵이 비어 있지 않으면 메타데이터 검색이 활성화돼요. 완전한 브랜치 이름이나 유연성을 위한 브랜치 접두사를 지정할 수 있어요. 접두사는 뒤에 별표를 붙여 표현해요, 예: dev-*.

  • repositories.<name>.branches ([]string : []) - 객체 메타데이터를 검색 가능하게 할 브랜치 이름(또는 접두사).

  • repositories.<name>.storage_namespace (string : "") - 생성되는 <repo>-metadata 저장소의 선택적 스토리지 네임스페이스 오버라이드. 생략하면 lakeFS가 데이터 저장소의 네임스페이스를 바탕으로 하나를 고름.

참고

Metadata search는 기본적으로 꺼져 있어요. 포함할 저장소와 브랜치를 명시적으로 설정해야 해요.

팁

브랜드 접두사(예: feature-*)를 쓰면 새 브랜치가 추가될 때마다 수동 업데이트할 필요가 줄어들어요.

검증 (chart 1.10.0+)

lakefs Helm 차트 버전 1.10.0 이상에서는 lakefs_mds_endpoint가 비어 있지 않고 period, concurrency, max_commits가 모두 양수(period > 0, concurrency >= 1, max_commits >= 1)가 아니면 Metadata Search 서비스가 시작을 거부해요. 이전 버전과 달리 브랜치별 제한을 끄려고 max_commits: 0을 쓰는 건 더 이상 받아들여지지 않아요.

샘플 설정

예시

metadata_search:
  lakefs_mds_endpoint: "https://example.lakefs.io"
  access_key_id: "AKIAIOSFOLEXAMPLE"
  secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
  period: 60s
  concurrency: 25
  max_commits: 1000
  since: "2025-01-01T00:00:00Z"
  repositories:
    example-repo-1:
      branches:
        - main
        - dev
    example-repo-2:
      branches:
        - main
        - feature-*

lakeFS 웹 UI에서 검색하기

Iceberg 클라이언트를 연결하는 건 파이프라인과 노트북에는 맞는 선택이지만, 브랜치에 대해 빠른 답만 원할 때가 많아요. 어떤 객체에 라벨이 붙어 있는지, 어떤 커밋이 얼마나 많은 데이터를 추가했는지 같은 것들이요. 이런 질문을 위해 lakeFS Enterprise는 lakeFS 웹 UI의 Metadata Search 탭에서 object_metadata 테이블 위의 SQL을 실행하게 해 줘요. 클라이언트, 카탈로그 설정, 관리할 자격 증명이 필요 없죠.

lakeFS Cloud에서는 문의해서 라이선스에 Metadata Search를 추가하면 lakeFS가 쿼리 서비스를 대신 운영해요. lakeFS Enterprise를 직접 운영한다면 Self-Managed Installations용 Metadata Search Web UI 문서를 참고해 활성화하세요.

Metadata Search 탭 사용하기

lakeFS 웹 UI에서 저장소를 열고 Metadata Search 탭을 선택하세요. 이 탭은 세 부분으로 이루어져 있어요:

  • 왼쪽 위의 ref 선택기 — Metadata Search가 이 저장소에 대해 동기화한 ref 목록을 보여 줘요. 기본 쿼리를 아직 편집하지 않았다면 다른 ref를 고르면 쿼리의 참조가 다시 작성돼요.

  • SQL 편집기 — 선택한 ref의 객체 메타데이터를 미리 보는 쿼리가 미리 채워져 있어요.

  • Execute 버튼 (또는 Ctrl+Enter / Cmd+Enter)과 그 뒤의 결과 그리드 — 쿼리가 반환한 총 행 수와 함께 결과의 처음 1,000행을 보여 줘요. 타임스탬프는 UTC로 표시되고 user_metadata 맵은 JSON으로 렌더링돼요.

기본 쿼리는 다음과 같아요:

-- Metadata for my-repo @ main.
SELECT path, user_metadata, content_type, last_modified, size_bytes, committer, commit_id, etag, creation_date
FROM "my-repo.main.system".object_metadata
LIMIT 20;

테이블은 "<repo>.<ref>.system".object_metadata 형태로 주소 지정해요. <ref>는 Metadata Search가 동기화한 브랜치, 태그, 커밋 ID이고, 네임스페이스에 점이 들어 있으므로 큰따옴표로 감싸야 해요. 쿼리 서비스는 DuckDB를 실행하므로 필터를 DuckDB SQL로 작성하고, 아래 예시 쿼리와 동일하게 user_metadata['key'] 맵 문법으로 사용자 정의 메타데이터에 접근하세요. ref 선택기는 현재 동기화된 브랜치만 나열하므로, 태그나 커밋을 쿼리하려면 테이블 이름에 직접 입력하고, 불변 ref가 쿼리를 재현 가능하게 만든다는 점을 기억하세요.

저장소와 ref에 걸쳐 쿼리하기

하나의 쿼리가 여러 object_metadata 테이블을 참조할 수 있어요. 같은 저장소의 여러 ref일 수도 있고, 다른 저장소일 수도 있죠. 이렇게 버전을 비교하거나 레이크 전체를 한 번에 검색해요. ref는 컬럼으로 저장되지 않으므로, 결합할 때는 각 테이블에 라벨을 붙이세요:

SELECT repository, ref, path, size_bytes, user_metadata
FROM (
  SELECT *, 'main' AS ref FROM "my-repo.main.system".object_metadata
  UNION ALL
  SELECT *, 'v1.2.0' AS ref FROM "my-repo.v1.2.0.system".object_metadata
)
WHERE user_metadata['animal'] = 'cat'
LIMIT 100;

집합 연산도 같은 방식으로 동작해요. 이 쿼리는 main에는 존재하지만 v1.2.0 릴리스에는 포함되지 않은 객체를 나열해요:

SELECT path
FROM "my-repo.main.system".object_metadata
EXCEPT
SELECT path
FROM "my-repo.v1.2.0.system".object_metadata;

쿼리는 이름 댄 모든 테이블을 스캔한다는 점을 기억하세요. 큰 테이블을 여러 개 결합하면 크기의 합만큼 비용이 들고 아래 제한에 걸릴 수 있어요.

권한

쿼리를 실행하려면 쿼리가 참조하는 모든 저장소에 대해 fs:ReadRepository 액션이 필요해요. 리소스 arn:lakefs:fs:::repository/<repo>에 대해 검사돼요. 하나라도 이 권한이 없는 저장소가 있으면 쿼리 전체가 거부돼요. fs:ReadRepository는 표준 읽기 정책의 일부이므로, 웹 UI에서 저장소를 탐색할 수 있는 사람이라면 누구나 그 저장소의 메타데이터도 검색할 수 있어요. 그리고 자신의 엔진을 카탈로그에 연결할 때와 달리 <repo>-metadata 저장소에 대한 접근은 필요하지 않아요.

이 권한은 저장소의 모든 ref에 있는 모든 객체의 메타데이터를 다루는 점에 유의하세요. 브랜치 수준·객체 수준 정책으로는 메타데이터 쿼리가 볼 수 있는 범위가 좁아지지 않아요. 모든 쿼리는 참조한 저장소와 함께 lakeFS 감사 로그에 기록돼요.

쿼리 규칙과 제한

쿼리 서비스는 행 상한을 강제하려고 SQL을 SELECT * FROM (<your SQL>) AS q LIMIT <cap>으로 감싸요. 그래서 쿼리는 단일 SELECT 형태의 문장이어야 하고, 파스 오류가 나면 여러분의 텍스트가 아니라 래퍼가 인용돼요. 다음 형태가 동작해요:

  • WITH 절, ORDER BY, 자체 LIMIT 또는 OFFSET을 포함한 단일 SELECT.

  • VALUES, DuckDB의 FROM-우선 문법, 그리고 검사용 문장 SHOW TABLES, DESCRIBE, SUMMARIZE.

  • 그 자체로 끝나는 후행 ;, 또는 그 앞에 ; 없이 붙는 후행 주석.

다음은 실패해요:

  • 문장이 두 개 이상인 경우, 예: SELECT 1; SELECT 2.

  • ; 뒤에 주석이 오는 경우, 예: SELECT 1; -- done.

  • EXPLAIN, PRAGMA, SET, CREATE TABLE, COPY, 그리고 SELECT가 아닌 다른 모든 문장.

  • 쿼리가 이름 댄 object_metadata 테이블 외의 다른 어떤 테이블.

각 쿼리는 릴리스마다 조정되는 제한 아래에서 실행돼요:

  • 행 상한: 더 큰 결과는 잘려서 저장되고 API 응답에 truncated: true로 표시돼요.

  • 바이트 상한: 크기 상한을 넘는 결과는 쿼리를 실패시켜요. 컬럼을 줄이거나 LIMIT을 추가하세요.

  • 시간 예산: 너무 오래 실행되는 쿼리는 실패하고, iceberg_query.request_timeout 안에서도 끝나야 해요. 이 값은 직접 호스팅하는 설치에서 설정할 수 있어요.

  • 컬럼 타입: 모든 컬럼은 Parquet 호환이어야 해요. INTERVAL은 캐스팅하거나 date_diff를 사용하세요.

  • 표시되는 행: 웹 UI는 총 행 수와 함께 결과의 처음 1,000행을 렌더링해요.

  • 동시성: 쿼리 서비스는 설치 전체에서 한 번에 하나의 쿼리만 실행해요. 다른 쿼리가 실행 중이면 Metadata Search 탭에 "Another metadata query is running. Try again shortly."가 표시되고 쿼리를 자동으로 재시도하지 않아요.

웹 UI 검색 제한

  • S3 전용: Azure, GCS, 멀티 스토리지 백엔드 설치에서도 Iceberg REST 카탈로그를 통한 쿼리는 가능해요.

  • 선택적 쿼리: 테이블이 파티셔닝·정렬되어 있지 않아서 매우 큰 테이블이나 다중 테이블 유니언은 타임아웃될 수 있어요.

  • 최종적 일관성: 새 커밋은 동기화된 후에야 검색 가능해져요.

  • 실험적 API: mds/query 엔드포인트는 이후 릴리스에서 바뀔 수 있어요.

메타데이터로 검색하는 방법

팁

인터랙티브 검색에는 이제 lakeFS 웹 UI의 Metadata Search 탭이 더 간단한 선택예요. 클라이언트 설정, 카탈로그 구성, 자격 증명이 필요 없거든요. 아래 설명대로 자신의 엔진을 연결하는 건, 파이프라인이나 노트북에서 쿼리할 때, 웹 UI 제한을 넘는 결과가 필요할 때, 또는 쿼리 서비스가 아직 지원하지 않는 스토리지 백엔드에서 실행할 때 쓰면 돼요.

lakeFS에서 객체 메타데이터로 검색하려면 lakeFS가 자동으로 만들고 관리하는 Iceberg object_metadata 테이블을 쿼리해요. 이 테이블은 항상 데이터 저장소 네임스페이스 아래에서 이용할 수 있어요:

<repo>.<ref>.system.object_metadata

DuckDB, Trino, Spark, PyIceberg 등 Iceberg 호환 엔진은 어느 것이든 사용할 수 있어요.

DuckDB를 쓴다면 object_metadata 테이블을 참조하는 방법의 세부 사항은 Iceberg REST Catalog 가이드를 참고하세요.

요구 사항

Iceberg 클라이언트는 lakeFS Iceberg REST 카탈로그의 인증 요구 사항을 충족해야 해요. 메타데이터 검색 쿼리를 수행하려면 사용자가 적절한 메타데이터 저장소에 접근할 수 있어야 해요(How it Works 참고).

S3 게이트웨이와 메타데이터 키 대소문자

객체를 S3 게이트웨이로 업로드하면 사용자 정의 메타데이터 키에 X-Amz-Meta- 접두사가 붙고, 키 자체는 S3 명세에 맞춰 소문자로 저장돼요. 예를 들어 메타데이터 키 MyKey로 객체를 S3 게이트웨이로 업로드하면 user_metadata 맵에는 X-Amz-Meta-mykey가 저장되므로 user_metadata['X-Amz-Meta-mykey']로 쿼리하세요. lakeFS API로 설정한 메타데이터는 접두사 없이 저장돼요 — 같은 업로드가 user_metadata['mykey']로 쿼리되죠.

인증

lakeFS는 메타데이터 검색 쿼리에 필요한 최소 권한을 부여하는 읽기 전용 정책과 함께 mds-service-user라는 전용 서비스 사용자를 자동으로 만들어요. 이 사용자를 사용하려면:

  • lakeFS API / lakectl / 웹 UI에서 mds-service-user의 자격 증명을 생성하세요.

  • Iceberg 카탈로그를 초기화할 때 생성된 액세스 키와 시크릿 키를 사용하세요(아래 Search Steps 참고).

이 서비스 사용자를 쓰면 메타데이터 검색 클라이언트가 Iceberg 메타데이터 테이블에 최소 권한으로 접근하게 돼요.

참고

데이터 저장소와 그에 대응하는 메타데이터 저장소 둘 다에 읽기 접근 권한이 있는 다른 lakeFS 사용자를 쓸 수도 있어요.

검색 단계

  • lakeFS Iceberg 카탈로그를 초기화하고 인증해요. 다음 예시는 PyIceberg를 사용해요:
from pyiceberg.catalog.rest import RestCatalog

catalog = RestCatalog(name = "my_catalog", **{
    'prefix': 'lakefs',
    'uri': f'{lakefs_endpoint}/mds/iceberg/api',
    'oauth2-server-uri': f'{lakefs_endpoint}/mds/iceberg/api/v1/oauth/tokens',
    'credential': f'{lakefs_client_key}:{lakefs_client_secret}',
})
  • 쿼리하고 싶은 참조를 나타내는 객체 메타데이터 테이블을 로드해요.

  • SQL로 시스템 또는 사용자 정의 메타데이터를 검색해요.

PyIceberg와 DuckDB를 사용하는 예시예요:

요구 사항

이 예시에는 duckdb 설치가 필요해요.

from pyiceberg.catalog import load_catalog

# Initialize the catalog
catalog = RestCatalog(name = "my_catalog", **{
    'prefix': 'lakefs',
    'uri': 'https://lakefs.example.com/mds/iceberg/api',
    'oauth2-server-uri': 'https://lakefs.example.com/mds/iceberg/api/iceberg/api/v1/oauth/tokens',
    'credential': f'AKIAlakefs12345EXAMPLE:abc/lakefs/1234567bPxRfiCYEXAMPLEKEY',
})

# `repo` is the repository name we would like to search
con = catalog.load_table('repo.main.system.object_metadata').scan().to_duckdb('object_metadata')

query = f"""
SELECT path
FROM object_metadata
WHERE user_metadata['animal'] = 'cat'
  AND last_modified > (now() - INTERVAL '20 days')
"""

df = con.execute(query).df()

이 쿼리는 최근에 추가된 모든 고양이 이미지를 찾아요. 사용자 정의 메타데이터와 시스템 메타데이터 필드를 결합해 강력하고 버전 인식적인 검색을 하는 방법을 보여 주죠.

참고

이 카탈로그 초기화는 클래식 lakeFS Iceberg 카탈로그와 다르다는 점에 유의하세요. 엔드포인트에 mds 경로 세그먼트가 추가로 있어서, 요청이 Metadata Search 카탈로그로 라우팅돼요.

재현 가능한 쿼리 작성하기

협업 환경이나 반복적 개발 과정에서는 메타데이터 쿼리가 일관되고 재현 가능한 결과를 반환하게 하는 게 중요해요. 이를 위해서는 브랜치 이름 대신 커밋 ID나 태그 이름 같은 불변 참조로 객체 메타데이터 테이블을 쿼리해야 해요.

왜 브랜치 이름을 쓰면 안 될까요?

브랜치 이름으로 메타데이터 테이블을 쿼리하면(예: repo.main.system.object_metadata), 메타데이터가 이미 수집됐다는 가정 하에(최종적 일관성 제약 안에서) 쿼리 시점의 브랜치 HEAD 커밋 상태를 기준으로 결과를 반환해요. 하지만 브랜치 HEAD는 가변적이고 커밋마다 앞으로 나아가기 때문에, 그런 쿼리의 결과는 시간이 지나면서 바뀔 수 있어요.

안정성을 위해 커밋 ID나 태그 이름을 사용하세요

안정성과 재현성을 위해 쿼리에 lakeFS 커밋 ID나 태그 이름을 사용하세요. 데이터 저장소에서 만들어진 각 커밋이나 태그는 메타데이터를 포함한 저장소 상태의 특정하고 고정된 스냅샷을 참조해요. 그래서 같은 쿼리는 이후 브랜치 변화와 무관하게 항상 같은 결과를 반환하죠.

커밋 ID 사용하기

  • 데이터 저장소에서 관련 커밋 ID를 찾아요 (예: my-repo 저장소 dev 브랜치의 dc3117ec3a727104226c896bf7ab9350ee5da06ae052406262840e9a4a8c9ffb).

  • 다음 패턴으로 객체 메타데이터 테이블을 쿼리해요:

<repo>.<commit_id>.system.object_metadata

예시:

my-repo.dc3117e.system.object_metadata
my-repo.dc3117ec3a727104226c896bf7ab9350ee5da06ae052406262840e9a4a8c9ffb.system.object_metadata

두 테이블 경로 모두 커밋 dc3117ec3a727104226c896bf7ab9350ee5da06ae052406262840e9a4a8c9ffb의 메타데이터를 반환해요.

팁

가독성을 위해 짧은 커밋 SHA(예: dc3117e)를 선호하세요.

태그 이름 사용하기

  • 데이터 저장소에서 관련 태그를 찾아요 (예: my-repo 저장소 main 브랜치의 v0.2.1).

  • 다음 패턴으로 객체 메타데이터 테이블을 쿼리해요:

<repo>.<tag_name>.system.object_metadata

예시:

my-repo.v0.2.1.system.object_metadata

팁

엔드 투 엔드 재현성을 위해서는 쿼리에 커밋 ID나 태그 이름을 직접 넣고, 그 쿼리들을 Git으로 버저닝하세요.

예시 쿼리

이 섹션은 lakeFS Metadata Search를 사용해 표준 SQL로 다양한 유형의 질문에 답하는 방법을 보여 줘요.

단순함과 가독성을 위해 예시는 Trino SQL로 작성했어요. 다른 엔진(예: DuckDB, Spark, PyIceberg)을 사용한다면 문법을 조정해야 할 수 있어요.

아래 예시는 단순함을 위해 브랜치 이름을 참조로 사용해요. 하지만 재현 가능한 결과를 위해서는 커밋 ID나 태그 이름을 쓰는 게 권해요. 브랜치 참조를 바꿔 어떤 예시든 재현 가능한 쿼리로 만들 수 있어요.

객체 어노테이션과 라벨링

객체 라벨로 필터하기

다음 예시는 앉아 있지 않은(dog 라벨) 강아지 이미지를 반환해요:

USE "repo.main.system";

SELECT * FROM object_metadata
WHERE path LIKE `%.jpg`
  AND user_metadata['animal'] = 'dog'
  AND user_metadata['position'] != 'sitting';
AI 기반 어노테이터의 메타데이터 보기

AI 기반 도구가 어노테이션한 모든 객체는 출처를 나타내는 객체 메타데이터 키-값 쌍 source: autolabel을 포함한다고 가정해요. 다음 예시는 그런 AI 어노테이션 객체를 모두 반환해요:

USE "repo.main.system";

SELECT *
FROM object_metadata
WHERE user_metadata['source'] = 'autolabel';

파일 속성과 스토리지

확장자와 크기로 필터하기

2MB보다 큰 모든 .png 파일을 찾아요.

USE "repo.main.system";

SELECT *
FROM object_metadata
WHERE path LIKE '%.png'
  AND size_bytes > 2000000;
추가 시각으로 객체 필터하기

이 예시는 지난 7일 동안 추가된 모든 객체를 찾아요.

USE "repo.main.system";

SELECT *
FROM object_metadata
WHERE last_modified >= current_timestamp - interval '7' day;

감사와 거버넌스

민감 데이터 태깅 오류 탐지

customers/ 아래의 모든 객체는 사용자 메타데이터 PII=true를 가져야 한다고 가정해요. 이 예시는 PII=false이거나 PII 키가 없는 객체를 반환해요.

USE "repo.main.system";

SELECT *
FROM object_metadata
WHERE path LIKE 'customers/%'
  AND (
    user_metadata['PII'] = 'false'
        OR user_metadata['PII'] IS NULL
    );

Self-Managed 설치용 Metadata Search 웹 UI

lakeFS 웹 UI의 Metadata Search 탭은 Metadata Search 쿼리 서비스에서 쿼리를 실행해요. lakeFS 서버가 매 쿼리마다 호출하는 별도 pod이에요. 쿼리 서비스는 Metadata Search 설정이 동기화하는 테이블을 읽기 때문에 그 설정은 추가 변경이 필요 없어요. self-managed lakeFS Enterprise 설치에서 이 탭을 활성화하려면:

  • 문의해서 기능을 활성화하세요.

  • Object Store Prerequisites에서 설명한 대로 오브젝트 스토어를 준비하세요.

  • lakefs Helm 차트 버전 1.12.42 이상으로, 차트 README에서 설명하는 방식대로 쿼리 서비스를 배포하세요.

  • lakeFS 서버 설정에 Iceberg Query Service 설정을 추가하세요.

Metadata Search 쿼리 서비스의 동작 방식

웹 UI에서 검색하면 배포에 구성 요소 하나가 추가돼요. Metadata Search 쿼리 서비스라는 별도 pod이 DuckDB 엔진을 내장해 쿼리를 실행하고 메타데이터 테이블을 오브젝트 스토리지에서 직접 읽어요. lakeFS 서버는 그 앞에 남아 인증, RBAC, 감사 로깅을 포함한 나머지 모든 것을 처리하고, 쿼리가 읽을 수 있는 테이블만큼의 단기 자격 증명을 pod에 넘겨요. 그래서 pod 자체는 데이터에 대한 접근 권한을 갖지 않아요. 결과는 여러분이 고른 오브젝트 스토어 위치에 Parquet 파일로 기록되고, 웹 UI가 그곳에서 읽어요.

flowchart LR
  UI["lakeFS Web UI"] -->|SQL| SRV["lakeFS server<br/>auth, RBAC, credentials"]
  SRV -->|authorized query| POD["Query Service pod<br/>DuckDB"]
  POD -->|read| OM[("object_metadata tables")]
  POD -->|write| RES[("results location")]
  RES -->|read result| UI

Metadata Search 쿼리 서비스: lakeFS 서버가 각 쿼리를 승인해 쿼리 서비스 pod으로 전달하고, pod은 메타데이터 테이블을 읽어 웹 UI가 표시할 결과를 기록해요.

오브젝트 스토어 사전 준비물

  • 자격 증명 벤딩(credentials vending): Credentials Vending에서 설명한 대로 blockstore.s3.credentials_vending.role_arn을 설정하고, 벤딩 역할이 <repo>-metadata 저장소의 스토리지 네임스페이스를 읽을 수 있게 하세요. 벤딩은 S3 전용이므로 쿼리 서비스도 S3 전용이에요.

  • 결과 위치: 모든 저장소 스토리지 네임스페이스 밖의 S3 접두사, 예: s3://my-bucket/lakefs-mds-results. lakeFS 서버의 신원이 읽고 쓸 수 있어야 해요. 각 결과는 그 아래 _lakefs/mds_query/results/<query_id>.parquet에 저장돼요.

  • 라이프사이클 규칙: <results location>/_lakefs/mds_query/results/ 아래의 객체를 만료시키세요. 결과 파일을 지우는 건 이것밖에 없거든요.

경고

라이프사이클 규칙은 결과 위치 아래의 정확히 _lakefs/mds_query/results/ 접두사에만 범위를 두세요. 더 넓은 접두사의 규칙은 무관한 객체까지 만료시켜요.

Iceberg Query Service 설정 레퍼런스

모든 설정은 lakeFS 서버 설정의 최상위 iceberg_query 키 아래에 있어요. Helm 차트로 쿼리 서비스를 배포하면 차트가 enabled, endpoint, token, results_location을 대신 설정해 줘요.

  • enabled (bool : false) - 쿼리 엔드포인트와 Metadata Search 탭을 활성화해요.

  • endpoint (string : "") - 쿼리 서비스의 base URL, 예: http://<query-service-host>:8080. 필수.

  • token (string : "") - lakeFS 서버가 매 호출마다 쿼리 서비스에 제시하는 공유 시크릿. 필수.

  • results_location (string : "") - 위 사전 준비물의 결과 위치. 필수.

  • results_storage_id (string : "") - 멀티 스토리지 백엔드 설치에서 결과 위치를 담는 blockstore. 생략하면 단일 또는 기본 blockstore가 사용돼요.

  • request_timeout (duration : 30s) - 서버가 쿼리 완료를 기다리는 시간. lakeFS 앞의 로드밸런서의 idle 타임아웃보다 짧게 유지하세요.

참고

쿼리 서비스는 기본적으로 꺼져 있어요. enabled를 설정하면 lakeFS 서버는 endpoint, token, results_location이 모두 설정되지 않으면 시작을 거부해요.

Iceberg Query Service 샘플 설정

예시

blockstore:
  type: s3
  s3:
    credentials_vending:
      role_arn: arn:aws:iam::123456789012:role/lakefs-mds-vending
iceberg_query:
  enabled: true
  endpoint: http://<query-service-host>:8080
  token: "<shared secret>"
  results_location: s3://my-bucket/lakefs-mds-results

Self-Managed 제한

  • 단일 pod: 이중화가 없어서 재시작 중에 실행 중이던 쿼리는 실패하고 다시 실행해야 해요.

  • 결과 보존: 결과 위치에서 결과 파일을 지우는 건 라이프사이클 규칙뿐이에요.

더 알아보기 (Learn more)

공식 문서: lakeFS Metadata Search 가이드