paint-brush
객체 저장소 위에 파일 시스템을 배치하면 안되는 이유~에 의해@minio
6,908 판독값
6,908 판독값

객체 저장소 위에 파일 시스템을 배치하면 안되는 이유

~에 의해 MinIO7m2023/11/14
Read on Terminal Reader

너무 오래; 읽다

대규모 조직이 딥 러닝, AI 및 기타 데이터 집약적 사용 사례를 위해 방대한 양의 데이터를 저장하고 액세스해야 하는 경우 POSIX는 이러한 요구를 충족할 수 있는 능력이나 확장성이 없습니다.
featured image - 객체 저장소 위에 파일 시스템을 배치하면 안되는 이유
MinIO HackerNoon profile picture
0-item
1-item

스토리지를 구매할 때 일반적으로 미디어에 중점을 두지만 액세스 방법도 고려하는 것이 훨씬 더 중요할 수 있습니다. 인프라를 설계하고 조달할 때, 특히 클라우드 네이티브 개체 스토리지로 마이그레이션하기 위해 레거시 스토리지를 남겨둘 때 스토리지 프로토콜을 고려해야 합니다. 그러나 객체 스토리지는 통신을 위해 S3 API에 의존하는 반면, 레거시 워크로드는 Unix OS 간에 애플리케이션을 이식할 수 있도록 1980년대에 개발된 표준 세트를 제공하는 휴대용 운영 체제 인터페이스인 POSIX에 의존합니다. 대부분의 기업에서는 POSIX에서 실행되도록 개발된 애플리케이션을 수십 년 동안 사용해 왔을 가능성이 있습니다. 엔지니어들이 POSIX의 성능 저하를 이미 알고 있을 가능성도 있습니다.


즉, 특정 형식이나 특정 소스의 데이터만 수집할 수 있는 레거시 시스템이 있는 경우 옵션이 제한될 수 있으며 오래된 프로토콜을 구현하거나 코드를 다시 작성하는 것 외에는 선택의 여지가 없을 수 있습니다. 예를 들어, 네트워크를 통해 액세스되는 RESTful API가 아닌 파일 시스템이 있는 로컬 디스크에서만 수집할 수 있는 경우 애플리케이션에서 해당 데이터를 사용할 수 있으려면 먼저 해당 데이터를 디스크에서 사용할 수 있도록 설정해야 합니다. 그러나 객체 저장소를 파일 시스템으로 사용하는 것은 성능, 호환성, 데이터 무결성 및 보안과 관련하여 여러 가지 심각한 부정적인 영향을 미칩니다.


s3fs-fuse 라는 작은 유틸리티를 사용하여 실제 테스트를 통해 이를 보여드리겠습니다. 이 유틸리티를 사용하면 S3 버킷을 로컬 파일 시스템으로 마운트할 수 있습니다. S3(Simple Storage Service) 파일 시스템 - FUSE(사용자 공간의 파일 시스템)를 나타냅니다. FUSE(사용자 공간의 파일 시스템) 인터페이스를 활용하여 S3에 파일 시스템과 유사한 인터페이스를 제공하는 오픈 소스 프로젝트입니다.


s3fs-fuse 사용하여 S3 버킷을 마운트하면 마치 로컬 파일 시스템인 것처럼 버킷과 상호 작용할 수 있습니다. 이는 버킷의 파일에 대해 일반 파일 작업(예: 읽기, 쓰기, 이동 등)을 사용할 수 있음을 의미합니다. 이는 놀랍도록 편리한 것처럼 들리며 애플리케이션 개발을 단순화한다고 주장할 수 있습니다. 그러나 본질적으로 객체 스토리지와 파일 시스템에는 파일 시스템으로 마운트된 s3 버킷에 영향을 미치는 근본적인 차이점이 있습니다.


잠시 s3fs-fuse 유틸리티에서 한 걸음 물러나 객체 스토리지를 파일 시스템으로 취급하는 것이 최적이 아닌 실제 이유를 논의해 보겠습니다. 문제는 s3fs-fuse 보다 훨씬 크며 로컬 파일 시스템 API 호출을 S3 객체 API 호출로 변환하는 파일 클라이언트인 Amazon S3용 Rust 기반 Mountpoint 와 같은 다른 유틸리티를 포함합니다. 첫 번째 이유는 이러한 모든 유틸리티가 파일 시스템 작업을 위해 POSIX에 의존한다는 것입니다. POSIX는 비효율적이며 네트워크를 통해 매우 큰 파일을 작업하기 위한 것이 아닙니다.


POSIX 기반 시스템의 속도는 수요, 특히 동시 수요가 증가함에 따라 감소합니다. 대규모 조직이 딥 러닝, AI 및 기타 데이터 집약적 사용 사례를 위해 방대한 양의 데이터를 저장하고 액세스해야 하는 경우 POSIX는 이러한 요구를 충족할 수 있는 능력이나 확장성이 없습니다. All-Flash 어레이는 게임에서 POSIX를 유지했지만 확장성과 RESTful API(클라우드의 특징)는 크립토나이트와 같습니다.


이 때문에 객체 저장소 위에서 POSIX를 실행하는 것은 차선책입니다. 그 이유 중 일부를 살펴보겠습니다.


  1. 성능: POSIX FS 인터페이스는 본질적으로 IOPS 중심입니다. 수다스럽고 비용이 많이 들고 확장하기 어렵습니다. RESTful S3 API는 IOPS를 처리량 문제로 변환하여 이 문제를 해결합니다. 처리량을 확장하는 것이 더 쉽고 저렴합니다. 이것이 바로 객체 스토리지가 대규모로 고성능을 발휘하는 이유입니다. POSIX는 HTTP RESTful 인터페이스를 통해 수행하기에는 너무 복잡하기 때문에 S3를 통한 POSIX 계층화는 확장되지 않습니다.


  2. 의미: 객체 작업은 원자적이고 불변이므로 일관성 정확성을 보장할 방법이 없습니다. 즉, 충돌이 발생하면 커밋되지 않은 데이터가 손실되거나 공유 마운트의 경우 손상 문제가 발생할 수 있습니다.


  3. 데이터 무결성 : 파일에 대한 쓰기 또는 변형은 커밋될 때까지 네임스페이스에 표시되지 않습니다. 이는 공유 마운트에 대한 동시 액세스에 수정 사항이 표시되지 않음을 의미합니다. 공유 액세스에는 유용하지 않습니다.


  4. 액세스 제어: POSIX 권한 및 ACL은 원시적이며 S3 API의 ID 및 액세스 관리 정책 처리 방식과 호환되지 않습니다. 상위 S3 API에서는 POSIX 액세스 관리를 안전하게 구현하는 것이 불가능합니다.


또한 POSIX에는 객체 수준 암호화, 버전 관리, 불변성 등 개발자가 S3에서 좋아하는 대부분의 기능이 부족합니다. 이러한 기능은 POSIX 세계에 상응하는 것이 없으며 번역할 수 있는 것도 없습니다.

POSIX 문제점

이러한 예는 문제와 그 의미를 보여줍니다. 시작하려면 약 10GB이고 112개의 행이 있는 CSV 파일을 사용합니다.


참고: s3fs-fuse 이미 설치되어 있고 객체 스토리지의 버킷 중 하나를 파일 시스템에 마운트했다고 가정합니다. 그렇지 않은 경우 여기에 있는 지침을 따르십시오.


이 예에서는 버킷 이름이 test-bucket이고 파일 이름이 Taxi-data.csv이며 /home/user/ 디렉터리에 있고 s3fs-fuse bucket /home/user/test-bucket/에 마운트되어 있다고 가정합니다.

복사 작업

먼저 간단한 것을 시도해 보고 mc 명령을 사용하여 CSV 파일을 테스트 버킷에 복사하고 소요된 시간을 기록해 보겠습니다.

time mc cp /home/user/taxi-data.csv minio/test-bucket/taxi-data.csv


이 작업에는 많은 시간이 걸리지 않으며 파일이 버킷에 복사되어야 합니다. 이제 s3fs-fuse 사용하여 동일한 작업을 수행해 보겠습니다.

time cp /home/user/taxi-data.csv /home/user/test-bucket/taxi-data.csv


테스트 중 소요된 시간


 real 1m36.056s user 0m14.507s sys 0m31.891s


제 경우에는 파일을 버킷에 부분적으로만 복사할 수 있었고 다음 오류로 인해 작업이 실패했습니다.


 cp: error writing '/home/user/test-bucket/taxi-data.csv': Input/output error cp: failed to close '/home/user/test-bucket/taxi-data.csv': Input/output error


여러번 시도한 끝에 성공했습니다


 real 5m3.661s user 0m0.053s sys 2m35.234s


보시다시피 유틸리티가 수행해야 하는 API 호출의 양과 일반적인 작업 오버헤드로 인해 유틸리티가 불안정해지고 대부분의 작업이 완료되지도 않습니다.

팬더의 예

우리는 간단한 cp 예제를 보여줬는데, 설득력이 있을 수도 있고 아닐 수도 있습니다. 왜냐하면 현실을 직시하면 time cp 가 아주 초보적이라고 생각할 수도 있기 때문입니다.


따라서 더 많은 경험적 증거가 필요한 사람들을 위해 이를 테스트하기 위한 Python 코드 조각을 작성해 보겠습니다. s3fs-fusepython s3fs 패키지를 모두 사용하여 간단한 Pandas 예제를 수행하고 성능에 미치는 영향을 살펴보겠습니다.


 import timeit import os import fsspec import s3fs import pandas as pd # Write a dummy CSV file to test-bucket df = pd.DataFrame({"column1": ["new_value1"], "column2": ["new_value2"]}) df.to_csv("s3://test-bucket/data/test-data.csv", index=False) def process_s3(): # add fsspec for pandas to use `s3://` path style and access S3 buckets directly fsspec.config.conf = { "s3": { "key": os.getenv("AWS_ACCESS_KEY_ID", "minioadmin"), "secret": os.getenv("AWS_SECRET_ACCESS_KEY", "minioadmin"), "client_kwargs": { "endpoint_url": os.getenv("S3_ENDPOINT", "https://play.min.io") } } } s3 = s3fs.S3FileSystem() for i in range(100): # Read the existing data print(i) df = pd.read_csv('s3://test-bucket/data/test-data.csv') # Append a new row new_df = pd.concat([df, pd.DataFrame([{"column1": f"value{i}", "column2": f"value{i}"}])], ignore_index=True) # Write the data back to the file new_df.to_csv('s3://test-bucket/data/test-data.csv', index=False) execution_time = timeit.timeit(process_s3, number=1) print(f"Execution time: {execution_time:.2f} seconds")


테스트 중 소요된 시간

 Execution time: 8.54 seconds


이제 s3fs-fuse 에 대해 동일한 작업을 시도해 보겠습니다.


 import timeit import pandas as pd # Write a dummy CSV file to test-bucket df = pd.DataFrame({"column1": ["new_value1"], "column2": ["new_value2"]}) df.to_csv("s3://test-bucket/data/test-data.csv", index=False) def process_s3fs(): for i in range(100): # Read the existing data print(i) df = pd.read_csv('/home/user/test-bucket/data/test-data.csv') # Append a new row new_df = pd.concat([df, pd.DataFrame([{"column1": f"value{i}", "column2": f"value{i}"}])], ignore_index=True) # Write the data back to the file new_df.to_csv('/home/user/test-bucket/data/test-data.csv', index=False) execution_time = timeit.timeit(process_s3fs, number=1) print(f"Execution time: {execution_time:.2f} seconds")



테스트 중 소요된 시간

 Execution time: 9.59 seconds


이 예제에서는 S3 파일에 대한 지속적인 읽기 및 쓰기를 보여줍니다. 여러 클라이언트가 동시에 수행한다고 상상해보세요. 대기 시간이 극적으로 늘어납니다.

오버헤드를 제거하세요!

보시다시피 POSIX 변환을 사용하여 개체를 파일로 처리하는 것과 직접 API를 사용하여 개체 작업을 하는 것의 차이점은 밤낮입니다. 보안, 성능, 데이터 무결성 및 호환성에 있어서는 비교할 수 없습니다. MinIO에는 거의 모든 인기 프로그래밍 언어와 통합할 수 있는 SDK가 있으며 Kubernetes, 베어메탈 Linux, Docker 컨테이너 등 거의 모든 플랫폼에서 실행될 수 있습니다.


MinIO는 데이터 무결성을 보호하기 위해 액세스 및 삭제 코딩을 규제하는 PBAC와 결합된 저장 및 전송 중 암호화를 통해 객체를 보호합니다 . MinIO는 기본 하드웨어( MinIO 배포에 가장 적합한 하드웨어 선택 참조)를 활용하여 가능한 최고의 성능을 제공하기 때문에 MinIO를 실행하는 위치에 관계없이 가능한 최고의 성능을 얻을 수 있습니다. 우리는 기성 NVMe SSD 노드가 32개뿐인 MinIO를 GET에서 325GiB/s(349GB/s), PUT에서 165GiB/s(177GB/s)로 벤치마킹했습니다 .


MinIO와 애플리케이션 중간에 파일 시스템 유틸리티가 필요하지 않습니다! 레거시 앱이 얻을 수 있는 이점은 POSIX의 어려움으로 인해 상쇄됩니다.


애플리케이션에 POSIX 번역을 사용하는 방법에 대해 질문이 있는 경우 Slack 으로 문의해 주세요!


여기에도 게시되었습니다.