POSIX가 객체 스토어에 적합하지 않은가요? 데이터를 바탕으로 한 답변

이 게시물의 저자는 MinIO 기사에 제시된 관점에 의문을 제기하며, POSIX가 객체 저장소에 적합한 선택이 아니라고 제안합니다. 그는 MinIO s3fs-fuse와 JuiceFS를 포함한 종합적인 테스트를 실시했습니다. 결과는 MinIO와 JuiceFS가 우수한 성능을 제공하는 반면 s3fs-fuse는 뒤쳐졌다는 것을 나타냅니다. 작은 파일 덮어쓰기 시나리오에서 JuiceFS FUSE-POSIX는 다른 솔루션들을 능가합니다.

최근 MinIO 블로그에 게시된 “객체 저장소 위에 파일 시스템을 올리는 것은 나쁜 생각이다. 이유는 다음과 같다.”라는 제목의 기사를 접했습니다. 저자는 s3fs-fuse를 예로 들어 POSIX 방식으로 MinIO 데이터에 접근할 때 발생하는 성능 문제를 설명하며, 직접 MinIO에 접근하는 것에 비해 성능이 상당히 뒤쳐졌다고 강조했습니다. 저자는 이러한 성능 문제를 POSIX의 본질적인 결함으로 귀착했습니다. 그러나 우리의 경험은 이러한 결론과는 다소 다릅니다.

POSIX는 유용하고 널리 채택된 표준입니다. POSIX를 따르는 소프트웨어 개발은 다양한 운영 체제 간의 호환성과 이식성을 보장합니다. 다양한 산업의 대부분의 응용 프로그램이 POSIX 표준을 준수합니다. 클라우드 컴퓨팅, 빅데이터, AI 기술의 발전과 저장되는 데이터 양의 증가에 따라 객체 스토어와 같은 탄력적인 스토리지 솔루션에 대한 수요가 증가하고 있습니다. MinIO와 같은 객체 스토어는 다양한 언어로 SDK를 제공하지만, 많은 전통적인 응용 프로그램은 객체 스토리지 API를 사용하도록 코드를 적응시키기 어렵습니다. 이로 인해 다양한 스토리지 제품이 객체 스토어 위에 POSIX 인터페이스를 구현하여 이러한 비탄력적인 수요를 충족시키고 있습니다.

산업 내의 많은 제품들, 예를 들어 Ceph, JuiceFS, Weka 등이 객체 스토어에 POSIX 인터페이스를 성공적으로 구현했습니다. 이러한 솔루션은 많은 사용자 기반과 수많은 성공 사례를 가지고 있으며, 성능 측면에서도 우수한 성과를 보입니다.

POSIX의 복잡성이 만만찮다는 것은 사실이지만, 관련된 문제들은 극복할 수 있는 수준입니다. 이러한 주장을 확인하고자 하는 존중과 열망을 가지고, 저는 테스트 환경을 구축하고, MinIO 기사에서와 동일한 샘플 데이터 및 테스트 방법을 사용하여 검증을 진행했습니다.

비교 대상 제품 및 테스트 목표

종합적인 평가를 위해 JuiceFS를 비교에 추가했습니다.

JuiceFS는 오픈 소스, 클라우드 네이티브 분산 파일 시스템입니다. 객체 스토리지를 데이터 저장소 계층으로 사용하고 별도의 데이터베이스에서 메타데이터를 저장합니다. POSIX API, S3 API, CSI Driver, HDFS API, WebDAV를 포함한 다양한 접근 방식을 제공하며, 독특한 데이터 청크링, 캐싱, 동시 읽기/쓰기 메커니즘을 포함합니다. JuiceFS는 기본적으로 s3fs-fuse와 같은 도구들과는 다른 파일 시스템으로, 객체 스토리지를 POSIX 프로토콜로 변환하는 것만을 수행합니다.

JuiceFS를 비교에 도입하여 객체 스토리지 위에 POSIX와 같은 프로토콜을 구현하는 것의 장단점을 객관적으로 평가하고자 했습니다.

I conducted the following two tests on MinIO, JuiceFS, and s3fs-fuse:

  • 10GB 파일 작성
  • Pandas로 작은 파일 덮어쓰기

세 가지 솔루션 모두 별도의 서버에 배포된 MinIO 인스턴스를 기본 저장소로 사용했습니다. 테스트 샘플로는 MinIO 기사에서 언급한 것과 동일한 CSV 파일을 사용한 10GB 파일을 사용했습니다.

이 기사의 모든 환경, 소프트웨어, 스크립트, 샘플 데이터는 환경을 재현하고 테스트 결과를 재현할 수 있는 완전한 코드와 지침을 제공합니다.

서버 및 테스트 환경 설정

동일한 구성의 클라우드 서버 두 대:

  • 시스템: Ubuntu 22.04 x64
  • CPU: 8개의 코어
  • RAM: 16GB
  • SSD: 500GB
  • 네트워크: VPC

각 서버에 대한 정보:

Server IP Purpose
Server A 172.16.254.18 Deploying the MinIO instance
Server B 172.16.254.19 As the test environment

서버 A 준비

1. 다음 명령어를 사용하여 Docker로 Server A에 MinIO를 배포했습니다:

# 전용 디렉토리 생성 및 이동.
mkdir minio && cd minio

# 구성 파일 생성.
mkdir config
touch config/minio

2. config/minio 파일에 다음 정보를 기록했습니다:

MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=abc123abc
MINIO_VOLUMES="/mnt/data"

3. MinIO 컨테이너를 생성했습니다:

sudo docker run -d --name minio \
  -p 9000:9000 \
  -p 9090:9090 \
  -v /mnt/minio-data:/mnt/data \
  -v ./config/minio:/etc/config.env \
  -e "MINIO_CONFIG_ENV_FILE=/etc/config.env" \
  --restart unless-stopped \
  minio/minio server --console-address ":9090"

4. MinIO의 Web 콘솔에서 세 개의 버킷을 미리 생성했습니다:

Bucket name Purpose
test-minio For testing MinIO
test-juicefs For testing JuiceFS
test-s3fs For testing s3fs-fuse

Server B 준비

1. 10GB 테스트 샘플 파일을 다운로드했습니다.

curl -LO https://data.cityofnewyork.us/api/views/t29m-gskq/rows.csv?accessType=DOWNLOAD

2. mc 클라이언트를 설치했습니다.

mc는 MinIO 프로젝트에서 개발한 명령줄 파일 관리자로, Linux 명령줄에서 로컬 및 S3 호환 객체 스토리지에 대한 읽기 및 쓰기 작업을 수행할 수 있습니다. mc cp 명령은 데이터 복사 중에 실시간 진행률 및 속도 업데이트를 제공하여 다양한 테스트를 관찰하는 데 도움이 됩니다.

참고: 테스트 공정성을 유지하기 위해 세 가지 접근 방식 모두 mc를 사용하여 파일 쓰기 테스트를 진행했습니다.

# mc 다운로드.
wget https://dl.min.io/client/mc/release/linux-amd64/mc

# mc 버전 확인.
mc -v
mc version RELEASE.2023-09-20T15-22-31Z (commit-id=38b8665e9e8649f98e6162bdb5163172e6ecc187)
Runtime: go1.21.1 linux/amd64

# mc 설치.
sudo install mc /usr/bin

# MinIO에 별칭 설정.
mc alias set my http://172.16.254.18:9000 admin abc123abc

3. s3fs-fuse를 다운로드했습니다.

sudo apt install s3fs

# 버전 확인.
s3fs --version
Amazon Simple Storage Service File System V1.93 (commit:unknown) with OpenSSL

# 객체 스토리지 액세스 키 설정.
echo admin:abc123abc >  ~/.passwd-s3fs

# 키 파일 권한 수정.
chmod 600  ~/.passwd-s3fs

# 마운팅 디렉토리 생성.
mkdir mnt-s3fs

# 객체 스토리지 마운트.
s3fs test-s3fs:/ /root/mnt-s3fs -o url=http://172.16.254.18:9000 -o use_path_request_style

4. JuiceFS를 설치했습니다.

I used the official script to install the latest JuiceFS Community Edition.

# 일괄 설치 스크립트
curl -sSL https://d.juicefs.com/install | sh -

# 버전 확인.
juicefs version
juicefs version 1.1.0+2023-09-04.08c4ae6

5. 파일 시스템을 생성했습니다. JuiceFS는 사용하기 전에 생성해야 하는 파일 시스템입니다. 객체 스토리지 외에도 메타데이터 엔진으로 데이터베이스가 필요합니다. 다양한 데이터베이스를 지원합니다. 여기서는 일반적으로 사용되는 Redis를 메타데이터 엔진으로 사용했습니다.

참고: Redis를 Server A에 설치했으며, 비밀번호 없이 172.16.254.18:6379를 통해 접근 가능합니다. 설치 과정은 여기서 생략하며, 자세한 내용은 Redis 문서를 참조하시기 바랍니다.

# 파일 시스템 생성.
juicefs format --storage minio \
--bucket http://172.16.254.18:9000/test-juicefs \
--access-key admin \
--secret-key abc123abc \
--trash-days 0 \
redis://172.16.254.18/1 \
myjfs

6. POSIX와 S3 API 방식을 더 일반적으로 사용하여 JuiceFS에 접근하고 성능을 테스트했습니다.

# 마운트 디렉토리 생성.
mkdir ~/mnt-juicefs

# POSIX 모드로 파일 시스템 마운트.
juicefs mount redis://172.16.254.18/1 /root/mnt-juicefs

# S3 API 방식으로 파일 시스템에 접근.
export MINIO_ROOT_USER=admin
export MINIO_ROOT_PASSWORD=abc123abc
juicefs gateway redis://172.16.254.18/1 0.0.0.0:9000

# JuiceFS S3 API에 별칭 설정하기.
mc alias set juicefs http://172.16.254.18:9000 admin abc123abc

참고: JuiceFS Gateway는 Server A 또는 인터넷에 접근 가능한 다른 서버에 배포할 수 있으며, 네트워크 기반 S3 API를 노출합니다.

테스트 및 결과

다음은 테스트 결과의 간단한 요약입니다:

Test MinIO S3FS-FUSE JuiceFS
(FUSE)
JuiceFS
(S3 gateway)
Writing a 10 GB file 0m27.651s 3m6.380s 0m28.107s 0m28.091s
Overwriting small files with Pandas 0.83s 0.78s 0.46s 0.96s

테스트 1: 10GB 파일 쓰기

이 테스트는 대용량 파일 쓰기 성능을 평가하기 위해 설계되었습니다. 소요 시간이 짧을수록 성능이 우수합니다. 쓰기 작업 기간을 측정하기 위해 time 명령어를 사용하여 세 가지 지표를 제공했습니다.

  • real: 명령의 시작부터 종료까지의 실제 시간으로, I/O 작업 완료 대기, 프로세스 전환 대기, 자원 대기 등 모든 대기 시간을 포함합니다.
  • user: 사용자 모드에서 실행된 시간으로, 사용자 코드 실행에 사용된 CPU 시간을 나타냅니다. 일반적으로 명령의 계산 부하를 나타냅니다.
  • sys: 커널 모드에서 실행된 시간으로, 커널 코드 실행에 사용된 CPU 시간을 나타냅니다. 일반적으로 파일 I/O, 프로세스 관리와 같은 시스템 호출과 관련된 부하를 나타냅니다.

MinIO

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  my/test-minio/

MinIO에 직접 10GB 파일을 쓰는 결과:

real    0m27.651s
user    0m10.767s
sys 0m5.439s

s3fs-fuse

I ran the following command to perform a copy test:

time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-s3fs/

s3fs-fuse에 직접 10GB 파일을 쓰는 결과:

real 3m6.380s
user 0m0.012s
sys 0m5.459s

참고: s3fs-fuse의 경우 쓰기 시간이 3분 6초였지만, MinIO의 기사에서 설명한 쓰기 실패는 발생하지 않았습니다.

JuiceFS

I tested the performance of JuiceFS for large file writes using both the POSIX and S3 API methods:

# POSIX 쓰기 테스트
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv /root/mnt-juicefs/

# S3 API 쓰기 테스트
time mc cp ./2018_Yellow_Taxi_Trip_Data.csv  juicefs/myjfs/

JuiceFS POSIX로 10GB 파일을 쓰는 결과:

real    0m28.107s
user    0m0.292s
sys 0m6.930s

JuiceFS S3 API로 10GB 파일을 쓰는 결과:

real    0m28.091s
user    0m13.643s
sys 0m4.142s

대용량 파일 쓰기 결과 요약

다음 그림은 테스트 결과를 보여줍니다:

Large file write results (lower is better)

테스트 결과, MinIO와 JuiceFS 모두 비슷한 성능을 보였으며, 약 30초 내에 작업을 완료했습니다. 반면, s3fs-fuse는 10GB 파일을 쓰는 데 3분 이상이 걸렸으며, 앞의 두 가지 방법보다 약 6배 느린 속도로 나타났습니다.

큰 파일을 작성할 때, mc는 파일을 청크로 나누어 S3 인터페이스에 청크 단위로 업로드하기 위해 Multipart API를 활용합니다. 반면에, s3fs-fuse는 POSIX에 단일 스레드로만 작성할 수 있습니다. JuiceFS는 또한 순차적인 쓰기 중에 큰 파일을 자동으로 청크로 분할하고 이를 MinIO에 동시에 쓰기 때문에, 직접적인 MinIO 쓰기와 동등한 성능을 보장합니다. 반면 S3FS는 먼저 단일 스레드로 캐시 디스크에 쓰고, 이후 파일을 청크 단위로 MinIO에 업로드하여 쓰기 시간이 더 길어집니다.

10GB 파일을 작성하는 데 30초가 소요되어 평균 속도는 333MB/s였습니다. 이는 클라우드 서버 SSD의 대역폭에 의한 제한이었습니다. 이러한 테스트 결과는 MinIO와 JuiceFS가 로컬 SSD 대역폭을 최대로 활용할 수 있으며, 서버 클라우드 디스크와 네트워크 대역폭의 개선으로 성능이 향상될 것임을 시사합니다.

테스트 2: Pandas로 작은 파일 덮어쓰기

이 테스트는 객체 저장소 시스템의 작은 파일 덮어쓰기 시나리오에서의 성능을 평가했습니다. 각 소프트웨어의 테스트 스크립트는 약간씩 다릅니다. 모든 스크립트 코드는 여기에서 확인할 수 있습니다.

MinIO

I got the test script and ran the test:

# 테스트 스크립트 획득.
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-minio.py

# 테스트 실행.
python3 pandas-minio.py

결과는 다음과 같았습니다:

Execution time: 0.83 seconds

s3fs-fuse

I got the test script and ran the test:

# 테스트 스크립트 획득.
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-s3fs.py

# 테스트 실행.
python3 pandas-s3fs.py

테스트 결과는 다음과 같았습니다:

Execution time: 0.78 seconds

JuiceFS POSIX

I got the test script and ran the test:

# 테스트 스크립트 획득.
curl -LO gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-posix.py

# 테스트 실행.
python3 pandas-juicefs-posix.py

테스트 결과는 다음과 같습니다:

Execution time: 0.43 seconds

JuiceFS S3 API

I got the test script and ran the test:

# 테스트 스크립트 획득.
curl -LO https://gist.githubusercontent.com/yuhr123/7acb7e6bb42fb0ff12f3ba64d2cdd7da/raw/30c748e20b56dec642a58f9cccd7ea6e213dab3c/pandas-juicefs-s3api.py

# 테스트 실행.
python3 pandas-juicefs-s3api.py

테스트 결과는 다음과 같습니다:

Execution time: 0.86 seconds

Pandas 작은 파일 덮어쓰기 요약

다음 그림은 테스트 결과를 보여줍니다:

Pandas overwrite results (lower is better)

이번 테스트에서 JuiceFS FUSE-POSIX는 가장 빠른 속도를 자랑했으며, 다른 솔루션들의 거의 두 배의 속도를 보였습니다. MinIO, s3fs-fuse, 그리고 JuiceFS S3 Gateway는 유사한 성능을 보였습니다. 작은 파일 덮어쓰기의 관점에서 POSIX 인터페이스가 더 효율적이며, 객체 저장소 인터페이스보다 더 우수한 성능을 제공했습니다.

문제 및 분석

문제 1: S3FS가 왜 그렇게 느렸나?

분석: 테스트 데이터에 따르면, 동일한 10GB 파일을 쓸 때 S3FS는 3분이 소요되었고, MinIO와 JuiceFS는 모두 약 30초 만에 작업을 완료했습니다. 이러한 큰 성능 차이는 주로 다른 기술적 구현 방식 때문입니다. s3fs-fuse가 파일을 쓸 때, 먼저 로컬 임시 파일에 파일을 쓰고 이를 객체 저장소에 청크 단위로 업로드합니다. 로컬 디스크 공간이 부족할 경우 동기식으로 업로드합니다. 이는 로컬 디스크와 S3 저장소 간 데이터를 복사해야 하므로, 큰 파일이나 많은 양의 파일은 성능 저하를 초래합니다.

또한, S3FS는 기본 객체 스토리지의 메타데이터 관리 기능에 의존합니다. 많은 양의 파일을 처리할 때, 메타데이터를 검색하기 위해 객체 스토리지와의 빈번한 상호 작용은 성능에 상당한 영향을 미칩니다. 간단히 말해, S3FS에 기록되는 파일의 크기와 총 수량이 커질수록 성능 오버헤드도 더 커집니다.

문제 2: 왜 JuiceFS가 더 빠른가?

분석: 테스트에서 JuiceFS와 S3FS 모두 FUSE를 사용하여 읽기와 쓰기를 수행했습니다. JuiceFS는 MinIO처럼 디스크 대역폭을 충분히 활용했지만, S3FS와 같은 성능 문제를 겪지 않았습니다.

답은 각각의 기술 아키텍처에 있습니다. 파일 쓰기 시 FUSE 계층을 통해 데이터가 처리되지만, JuiceFS는 고도의 동시성, 캐싱 및 데이터 청크 기법을 사용하여 FUSE 계층과 기본 객체 스토리지 간의 통신 오버헤드를 줄입니다. 이로써 JuiceFS는 동시에 더 많은 파일 읽기 및 쓰기 요청을 처리할 수 있어, 대기 시간과 전송 지연을 감소시킵니다.

또한, JuiceFS는 메타데이터를 관리하기 위한 전용 데이터베이스(이 경우 Redis)를 사용합니다. 특히 많은 양의 파일을 다룰 때, 독립적인 메타데이터 엔진은 부담을 효과적으로 완화하여 파일 위치 속도를 높입니다.

결론

위의 테스트들은 객체 저장소를 기반으로 하고 POSIX 인터페이스를 구현한 경우에도 성능 저하가 발생하지 않는다는 것을 보여줍니다. 큰 파일이나 작은 파일을 쓰는 경우에도 JuiceFS는 POSIX 접근으로 인한 기본 객체 저장소 성능 저하 없이 직접 MinIO 쓰기와 비슷한 성능을 보입니다. 또한 Pandas 테이블 덮어쓰기 측면에서 JuiceFS FUSE-POSIX 성능은 일관되며 MinIO를 거의 두 배 이상 능가합니다.

테스트 결과는 S3 API와 POSIX 인터페이스 간의 변환 시 성능 저하가 발생할 수 있는 일부 소프트웨어(예: s3fs-fuse)를 나타냅니다. 일시적인 S3 접근을 위한 편리한 도구로는 유용하지만, 안정적이고 고성능의 장기 사용을 위해서는 더 적합한 솔루션을 선택하기 위한 신중한 연구와 검증이 필요합니다.

단순한 비정형 파일 보관을 위해서는 MinIO나 클라우드 객체 저장소를 직접 사용하는 것이 좋습니다. 하지만 AI 모델 훈련, 빅데이터 분석, Kubernetes 데이터 지속성 등 대규모 데이터 저장 및 처리가 포함된 시나리오의 경우, JuiceFS의 독립적인 메타데이터 관리, 동시 읽기 쓰기 기능 및 캐싱 메커니즘은 우수한 성능을 제공합니다. 이는 고성능 파일 시스템 솔루션으로 고려할 가치가 있습니다.

Source:
https://dzone.com/articles/is-posix-really-unsuitable-for-object-stores-a-dat