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

사이징 가이드

원문 보기 위키 갱신

시스템 요구 사항

출처: 문서

본문

운영체제와 ISA

lakeFS는 MacOS와 Linux에서 실행할 수 있어요. Windows 바이너리도 있지만 철저히 테스트되지 않았으므로 - Windows에서의 프로덕션 배포는 권장하지 않아요. x86_64와 arm64 아키텍처가 MacOS와 Linux 모두에서 지원돼요.

메모리와 CPU 요구 사항

lakeFS 서버에는 최소 512MB의 RAM과 1개의 CPU 코어가 필요해요. 높은 처리량을 위해서는 추가 CPU가 요청을 여러 코어로 분산하는 데 도움이 돼요. 대형 diff나 커밋 연산 같은 "비싼" 연산은 여러 코어를 활용할 수 있어요.

네트워크

S3 Gateway 같은 데이터 API를 사용한다면, 계획된 동시 네트워크 업/다운로드 연산을 지원할 만큼 충분한 네트워크 대역폭이 필요해요. 대부분의 클라우드 제공자에서 더 강력한 머신(즉, 더 비싸고 보통 CPU 코어가 더 많은)은 네트워크 대역폭도 더 커요.

메타데이터 API만 사용한다면(예: Hadoop/Spark 클라이언트만 사용) 네트워크 대역폭은 요청당 약 1Kb 수준으로 최소화돼요.

디스크

lakeFS는 빠른 로컬 디스크의 혜택을 크게 받아요. lakeFS 인스턴스는 기반 스토리지에 강한 내구성 보장을 요구하지 않아요. 디스크는 장기 저장소가 아니라 lakeFS 메타데이터의 로컬 캐싱 레이어로만 쓰이거든요. lakeFS는 임시 디스크(ephemeral disks)와 함께 동작하도록 설계되었어요 - 이런 디스크는 보통 NVMe 기반이고 머신의 라이프사이클에 묶여 있어요. 임시 디스크를 사용하면 lakeFS가 매우 높은 처리량/비용 비율을 제공할 수 있어요. 퍼블릭 클라우드에서 얻을 수 있는 최선일 테니 이를 권장해요.

최소 512 MiB의 로컬 캐시가 제공되어야 해요. 대형 설치(100개 이상의 동시 활성 브랜치, 커밋당 1억 개 이상의 객체)라면 최소 10 GiB를 할당하기를 권장해요 - 상대적으로 느린 스토리지(객체 스토리지) 위의 캐싱 레이어이므로, 크기 산정 방법은 아래 중요 메트릭을 참고하세요: 활발히 참조되는 커밋의 모든 커밋 메타데이터를 담을 만큼 충분히 커야 해요.

lakeFS KV 스토어

lakeFS는 브랜치 레퍼런스, 인증·권한 정보를 관리하고 브랜치에 걸친 현재 커밋되지 않은 데이터를 추적하기 위해 키-값 데이터베이스를 사용해요.

모범 사례, 요구 사항, 벤치마크는 해당 드라이버 탭을 참고하세요.

스토리지

메타데이터 스토어에 저장되는 데이터셋은 대부분의 메타데이터가 객체 스토리지로 밀려 내려가기 때문에 상대적으로 작아요. 필요한 스토리지는 대개 특정 시점에 모든 브랜치에 걸쳐 커밋되지 않은 쓰기의 양에 비례해요: 100,000건의 커밋되지 않은 쓰기당 약 150 MiB 수준이에요.

프로덕션 배포는 10 GiB로 시작하기를 권장해요. 아마 그 이상이면 충분할 거예요.

PostgreSQLDynamoDB

RAM

데이터 크기가 작으므로 그 데이터 대부분을 RAM에 담을 만큼 충분한 메모리를 제공하는 것이 권장돼요. 클라우드 제공자는 이 파라미터 튜닝을 대신해 줘요 - 선택한 인스턴스의 가용 RAM에 대해 고정 비율로 설정돼요 (AWS RDS는 25%, Google Cloud SQL은 30%). 여러분의 데이터베이스에 대한 구성·프로비저닝 정보는 선택한 클라우드 제공자와 확인하는 것이 좋아요. 셀프 매니지드 데이터베이스 인스턴스라면 이 모범 사례를 따르세요

이상적으로는 PostgreSQL 인스턴스의 shared_buffers를 현재 활성 데이터셋을 담을 만큼 충분히 크게 구성하세요. shared_buffers로 지정한 크기의 약 4배에 해당하는 RAM을 수용할 수 있는 데이터베이스 인스턴스를 고르세요. 예를 들어 어떤 설치가 임의 시점에 약 500,000건의 커밋되지 않은 쓰기를 갖는다면 약 750 MiB의 shared_buffers가 필요하고, 그러려면 약 3 GiB의 RAM이 필요해요.

CPU

PostgreSQL CPU 코어는 동시 요청 확장에 도움이 돼요. 초당 5,000 요청마다 1개의 CPU 코어가 이상적이에요.

lakeFS는 여러분을 위해 DynamoDB 테이블을 생성하며, 기본적으로 온디맨드 용량 설정이에요. 애플리케이션이 수행할 읽기·쓰기 처리량을 지정할 필요가 없어요. DynamoDB가 워크로드가 늘고 줄는 대로 즉시 수용하거든요.

테이블 설정을 프로비저닝된 용량으로 커스터마이즈해 읽기/쓰기 용량을 미리 할당해 비용을 관리·최적화할 수도 있어요 (벤치마크 참고)

참고 사항

  • DynamoDB 온디맨드 용량은 테이블이 남용되면 원치 않는 비용을 만들 수 있어요. 비용 상한을 두고 싶다면 테이블을 프로비저닝된 용량으로 바꾸세요.

  • lakeFS는 DynamoDB 테이블의 라이프사이클을 관리하지 않아요. 최소한의 노력으로 시스템을 평가할 수 있도록 테이블 생성만 포함했어요. 테이블 생성 이후의 변경은 수동이나 서드파티 도구로 처리해야 해요.

RAM

AWS가 관리해요.

CPU

AWS가 관리해요.

스케일링 팩터

lakeFS의 스케일링은, 대부분의 데이터 시스템처럼 두 축 위에서 움직여요: 요청 처리량(주어진 시간당 양)과 레이턴시(단일 요청 완료 시간)예요.

레이턴시와 처리량 고려 사항 이해하기

대부분의 lakeFS 연산은 매우 낮은 레이턴시를 목표로 설계되었어요. 잘 튜닝된 로컬 디스크 캐시(위 Storage 참고)를 가정하면, 대부분의 크리티컬 패스 연산 (객체 쓰기, 객체 요청, 객체 삭제)은 p90 기준 25ms 미만으로 완료되도록 설계되었어요. 객체 나열은 당연히 더 많은 데이터에 접근해야 하지만, 항상 기반 객체 스토리지가 제공하는 수준과 동등해야 하고 대부분의 경우 실제로 더 빨라요. 최악의 경우 1,000개의 공통 프리픽스를 반환하는 디렉터리 나열에서는 p90 기준 75ms의 레이턴시를 예상하세요.

브랜치 관리(생성, 나열, 삭제)는 모두 상수 시간 연산으로, 일반적으로 p90 기준 30ms 미만이 걸려요.

커밋과 머지는 더 오래 걸릴 수 있어요. 도입된 변경량에 비례하기 때문이에요. 이것이 lakeFS를 대형 데이터 레이크에 최적으로 만들어요 - 커밋당 도입되는 변경량은 대개 비교적 안정적으로 유지되는 반면 전체 데이터셋은 시간이 지나며 커지는 것이 보통이거든요. 즉 lakeFS는 예측 가능한 성능을 제공해요: 100개의 변경을 커밋하는 데 걸리는 시간은 결과 커밋에 객체가 500개든 5억 개든 거의 동일해요.

자세한 내용은 Data Model 문서를 참고하세요.

처리량 스케일링은 lakeFS에 사용 가능한 CPU 코어 수에 크게 좌우돼요. 많은 경우 코어가 많은 머신으로 스케일 업하는 것보다 작은 클라우드 인스턴스(또는 컨테이너) 플릿에 걸쳐 lakeFS를 스케일하는 편이 쉬워요. 실제로 lakeFS는 양쪽 모두에서 잘 동작해요. 대부분의 크리티컬 패스 연산은 머신 간 확장에 매우 잘 맞아요.

벤치마크

PostgresSQLDynamoDB

아래 모든 벤치마크는 AWS us-east-1의 2 x c5ad.4xlarge 인스턴스로 측정되었어요. Google Cloud에서는 로컬 SSD가 붙은 c2-standard-16 머신 유형으로 비슷한 결과를 얻을 수 있어요. Azure에서는 Standard_F16s_v2 가상 머신을 사용할 수 있어요.

사용된 PostgreSQL 인스턴스는 db.m6g.2xlarge (8 vCPU, 32GB RAM)였어요. Google Cloud나 Azure의 동등한 머신도 비슷한 결과를 낼 거예요.

테스트에 사용된 예제 리포지토리는 대형 lakeFS 설치의 메타데이터를 담고 있으며, 각 커밋은 약 1억 8천만 개의 객체(약 7.5 페타바이트의 데이터)를 포함해요.

모든 테스트는 lakectl abuse 명령으로 재현 가능하므로, 이를 사용해 여러분의 구성을 적절히 사이징하고 튜닝하세요. 모든 테스트에는 그것을 생성한 해당 lakectl abuse 명령이 함께 제공돼요.

랜덤 읽기

이 테스트는 주어진 커밋에 대해 lakeFS로 랜덤 읽기 요청을 생성해요. 경로는 사전 구성된(그리고 실제 존재하는) 경로 집합을 담은 파일에서 무작위로 요청돼요.

실행된 명령:

lakectl abuse random-read \
    --from-file randomly_selected_paths.txt \
    --amount 500000 \
    --parallelism 128 \
    lakefs://example-repo/<commit hash>

참고 lakeFS 버전 <= v0.33.1은 리포지토리와 커밋 해시 사이 구분자로 '/' 대신 '@'를 사용해요.

결과 히스토그램(원본):

Histogram (ms):
1   0
2   0
5   37945
7   179727
10  296964
15  399682
25  477502
50  499625
75  499998
100 499998
250 500000
350 500000
500 500000
750 500000
1000    500000
5000    500000
min 3
max 222
total   500000

즉 모든 요청의 50%가 10ms 미만, 99.9%가 50ms 미만이었어요

처리량:

실험 중 평균 처리량은 10851.69 requests/second였어요

랜덤 쓰기

이 테스트는 주어진 lakeFS 브랜치로 랜덤 쓰기 요청을 생성해요. 모든 경로는 사전 생성되며 서로를 덮어쓰지 않아요 (덮어쓰기는 데이터 레이크 구성에서 비교적 드물거든요).

실행된 명령:

lakectl abuse random-write \
    --amount 500000 \
    --parallelism 64 \
    lakefs://example-repo/main

참고 lakeFS 버전 <= v0.33.1은 리포지토리와 브랜치 사이 구분자로 '/' 대신 '@'를 사용해요.

결과 히스토그램(원본):

Histogram (ms):
1   0
2   0
5   30715
7   219647
10  455807
15  498144
25  499535
50  499742
75  499784
100 499802
250 500000
350 500000
500 500000
750 500000
1000    500000
5000    500000
min 3
max 233
total   500000

즉 모든 요청의 50%가 10ms 미만, 99.9%가 25ms 미만이었어요.

처리량:

실험 중 평균 처리량은 7595.46 requests/second였어요.

브랜치 생성

이 테스트는 주어진 레퍼런스에서 브랜치를 생성해요.

실행된 명령:

lakectl abuse create-branches \
    --amount 500000 \
    --branch-prefix "benchmark-" \
    --parallelism 256 \
    lakefs://example-repo/<commit hash>

참고 lakeFS 버전 <= v0.33.1은 리포지토리와 커밋 해시 사이 구분자로 '/' 대신 '@'를 사용해요.

결과 히스토그램(원본):

Histogram (ms):
1   0
2   1
5   5901
7   39835
10  135863
15  270201
25  399895
50  484932
75  497180
100 499303
250 499996
350 500000
500 500000
750 500000
1000    500000
5000    500000
min 2
max 304
total   500000

즉 모든 요청의 50%가 15ms 미만, 99.9%가 100ms 미만이었어요.

처리량:

실험 중 평균 처리량은 7069.03 requests/second였어요.

아래 모든 벤치마크는 AWS us-east-1의 m5.xlarge 인스턴스로 측정되었어요.

사용된 DynamoDB 테이블은 500/1000 읽기/쓰기 용량으로 프로비저닝되었어요.

테스트에 사용된 예제 리포지토리는 대형 lakeFS 설치의 메타데이터를 담고 있으며, 각 커밋은 약 1억 개의 객체(약 3.5 페타바이트의 데이터)를 포함해요.

모든 테스트는 lakectl abuse 명령으로 재현 가능하므로, 이를 사용해 여러분의 구성을 적절히 사이징하고 튜닝하세요. 모든 테스트에는 그것을 생성한 해당 lakectl abuse 명령이 함께 제공돼요.

랜덤 읽기

이 테스트는 주어진 커밋에 대해 lakeFS로 랜덤 읽기 요청을 생성해요. 경로는 사전 구성된(그리고 실제 존재하는) 경로 집합을 담은 파일에서 무작위로 요청돼요.

실행된 명령:

lakectl abuse random-read \
    --from-file randomly_selected_paths.txt \
    --amount 500000 \
    --parallelism 128 \
    lakefs://example-repo/<commit hash>

결과 히스토그램(원본): 프로비저닝된 읽기 용량 단위 = 1000 프로비저닝된 쓰기 용량 단위 = 1000

Histogram (ms):
1   0
2   0
5   0
7   0
10  0
15  0
25  122
50  47364
75  344489
100 460404
250 497912
350 498016
500 498045
750 498111
1000 498176
5000 499478
min 18
max 52272
total 500000

결과 히스토그램(원본): 프로비저닝된 읽기 용량 단위 = 500 프로비저닝된 쓰기 용량 단위 = 500

Histogram (ms):
1   0
2   0
5   0
7   0
10  0
15  1
25  2672
50  239661
75  420171
100 470146
250 486603
350 486715
500 486789
750 487443
1000    488113
5000    493201
min 14
max 648085
total   499998

랜덤 쓰기

이 테스트는 주어진 lakeFS 브랜치로 랜덤 쓰기 요청을 생성해요. 모든 경로는 사전 생성되며 서로를 덮어쓰지 않아요 (덮어쓰기는 데이터 레이크 구성에서 비교적 드물거든요).

실행된 명령:

lakectl abuse random-write \
    --amount 500000 \
    --parallelism 64 \
    lakefs://example-repo/main

결과 히스토그램(원본): 프로비저닝된 읽기 용량 단위 = 1000 프로비저닝된 쓰기 용량 단위 = 1000

Histogram (ms):
1   0
2   0
5   0
7   0
10  0
15  0
25  24
50  239852
75  458504
100 485225
250 493687
350 493872
500 493960
750 496239
1000    499194
5000    500000
min 23
max 4437
total   500000

결과 히스토그램(원본): 프로비저닝된 읽기 용량 단위 = 500 프로비저닝된 쓰기 용량 단위 = 500

Histogram (ms):
1   0
2   0
5   0
7   0
10  0
15  0
25  174
50  266460
75  462641
100 484486
250 490633
350 490856
500 490984
750 492973
1000 495605
5000 498920
min 21
max 50157
total 500000

브랜치 생성

이 테스트는 주어진 레퍼런스에서 브랜치를 생성해요.

실행된 명령:

lakectl abuse create-branches \
    --amount 500000 \
    --branch-prefix "benchmark-" \
    --parallelism 256 \
    lakefs://example-repo/<commit hash>

결과 히스토그램(원본): 프로비저닝된 읽기 용량 단위 = 1000 프로비저닝된 쓰기 용량 단위 = 1000

Histogram (ms):
1   0
2   0
5   0
7   0
10  0
15  0
25  0
50  628
75  26153
100 58099
250 216160
350 307078
500 406165
750 422898
1000    431332
5000    475848
min 41
max 430725
total   490054

결과 히스토그램(원본): 프로비저닝된 읽기 용량 단위 = 500 프로비저닝된 쓰기 용량 단위 = 500

Histogram (ms):
1   0
2   0
5   0
7   0
10  0
15  0
25  0
50  3132
75  155570
100 292745
250 384224
350 397258
500 431141
750 441360
1000 445597
5000 469538
min 39
max 760626
total 497520

중요 메트릭

lakeFS는 Prometheus 프로토콜로 메트릭을 노출해요. 모든 lakeFS 인스턴스는 이를 추출하는 데 쓸 수 있는 /metrics 엔드포인트를 노출해요.

lakeFS 사이징 시 추적할 만한 주요 메트릭은 다음과 같아요:

api_requests_total - 시간에 따른 API 요청 처리량을 추적해요.

api_request_duration_seconds - 연산 유형별 레이턴시 히스토그램이에요.

gateway_request_duration_seconds - S3 Gateway 연산별 레이턴시 히스토그램이에요.

PostgreSQLDynamoDB

dynamo_request_duration_seconds - DynamoDB 요청에 소요된 시간이에요.

dynamo_consumed_capacity_total - 연산이 소비한 용량 단위예요.

dynamo_failures_total - KV 스토어 작업 중 발생한 총 오류 수예요.

레퍼런스 아키텍처

아래는 lakeFS 배포를 위한 몇 가지 예제 아키텍처예요.

레퍼런스 아키텍처: 데이터 과학/연구 환경

사용 사례: 머신러닝이나 알고리즘 개발 관리. lakeFS 브랜치를 사용해 실험의 격리와 재현성을 모두 달성해요. lakeFS가 관리하는 데이터는 구조화된 표 형식 데이터와 학습에 사용되는 비구조화 센서·이미지 데이터 모두예요. 20~50명의 연구자 팀과 2천만 객체에 걸친 500 TiB 데이터셋 크기를 가정해요.

환경: lakeFS는 AWS EKS로 관리되는 Kubernetes에 배포되고 AWS RDS Aurora의 PostgreSQL과 함께 구성돼요

사이징: 대부분의 작업이 사람에 의해 이루어지므로(자동화 파이프라인 대비) 대부분의 실험은 규모가 작아요. 수십에서 수천 개의 객체를 읽고 쓰죠. 병렬로 활성화되는 브랜치 수는 비교적 적어 사용자당 1~2개 수준이고, 각 브랜치는 임의 시점에 소량의 커밋되지 않은 변경을 나타내요. 브랜치당 5,000건의 커밋되지 않은 쓰기 = 약 50만 건으로 가정해요.

예상 처리량을 지원하기 위해서는 초당 요청이 수십~수백 수준이므로 중간 규모의 lakeFS 인스턴스 한 대면 충분히 넘쳐요. 고가용성을 위해 CPU 코어 1개와 RAM 1 GiB를 가진 파드 2개를 배포해요.

PostgreSQL 인스턴스는 매우 작은 데이터셋을 담을 것으로 예상돼요 (50만 건 기준 예상 데이터셋 크기는 150MiB (for 100k records) * 5 = 750MiB). 이를 담을 충분한 RAM을 확보하려면 3 GiB의 RAM이 필요하므로, 매우 중간 규모의 Aurora 인스턴스 db.t3.large (2 vCPU, 8GB RAM)로도 충분해요. GCP나 Azure의 동등한 데이터베이스 인스턴스도 비슷한 결과를 줄 거예요.

레퍼런스 아키텍처: 자동화된 프로덕션 파이프라인

사용 사례: Apache Spark와 Airflow로 여러 동시 데이터 파이프라인 관리. Airflow DAG는 격리와 CI/CD를 위해 브랜치를 만드는 것으로 시작해요. lakeFS가 관리하는 데이터는 구조화된 표 형식 데이터예요. 전체 데이터셋 크기는 5억 객체에 걸친 10 PiB예요. 예상 처리량은 100개의 동시 브랜치에 걸쳐 초당 1만 읽기 + 2천 쓰기예요.

환경: lakeFS는 AWS EKS로 관리되는 Kubernetes에 배포되고 AWS RDS의 PostgreSQL과 함께 구성돼요

사이징: 데이터 파이프라인은 본질적으로 버스트성이에요: 많은 객체를 동시에 읽고, 계산이나 집계를 하고, 다시 많은 객체를 동시에 쓰죠. 동시에 활성화되는 브랜치 수는 많을 것으로 예상돼요. 하루에 수많은 Airflow DAG가 실행되며 각각 임의 시점에 중간 정도의 커밋되지 않은 변경을 나타내요. 브랜치당 1,000건의 커밋되지 않은 쓰기 * 2,500 브랜치 = 약 250만 건으로 가정해요.

예상 처리량을 지원하려면 위 벤치마크 수치를 보면 코어당 대략 625 요청이므로, 피크 트래픽을 커버하려면 24코어가 필요해요. 4 CPU 코어 파드 6개를 배포할 수 있어요.

PostgreSQL 인스턴스로 넘어가면 - 50만 건 기준 예상 데이터셋 크기는 150MiB (for 100k records) * 25 = 3750 MiB예요. 이를 담을 충분한 RAM을 확보하려면 최소 15 GiB의 RAM이 필요하므로 db.r5.xlarge (4 vCPU, 32GB RAM) Aurora 인스턴스를 선택해요. GCP나 Azure의 동등한 데이터베이스 인스턴스도 비슷한 결과를 줄 거예요.

더 알아보기 (Learn more)

공식 문서의 사이징 가이드는 https://docs.lakefs.io/admin/sizing-guide 에서 확인할 수 있어요.