При покупке хранилища основное внимание обычно уделяется носителям, но, возможно, еще важнее учитывать и методы доступа. Вам необходимо будет учитывать протоколы хранения при проектировании и приобретении инфраструктуры, особенно если вы оставляете устаревшее хранилище для перехода к облачному объектному хранилищу. Однако объектное хранилище использует для связи API S3, в то время как устаревшие рабочие нагрузки полагаются на POSIX, интерфейс переносимой операционной системы, который предоставляет набор стандартов, разработанных в 1980-х годах, позволяющих переносить приложения между ОС Unix. Скорее всего, на большинстве предприятий уже несколько десятилетий эксплуатируются приложения, разработанные для работы на POSIX. Вероятно также, что инженеры уже знают о низкой производительности POSIX.
При этом, если у вас есть устаревшие системы, которые могут принимать данные только в определенном формате или из определенного источника, ваши возможности могут быть ограничены, и у вас может не быть другого выбора, кроме как реализовать устаревший протокол или переписать свой код. Например, если вы можете получать данные только с локального диска с файловой системой, а не с помощью API-интерфейсов RESTful, доступных по сети, то вы должны сначала сделать эти данные доступными на диске, прежде чем ваше приложение сможет их использовать. Однако использование хранилища объектов в качестве файловой системы имеет ряд серьезных негативных последствий, когда речь идет о производительности, совместимости, целостности данных и безопасности.
Давайте продемонстрируем это на примере реальных испытаний с помощью небольшой утилиты под названием s3fs-fuse . Эта утилита позволяет смонтировать корзину S3 как локальную файловую систему. Это означает файловую систему S3 (Simple Storage Service) — FUSE (файловая система в пространстве пользователя). Это проект с открытым исходным кодом, который использует интерфейс FUSE (файловая система в пользовательском пространстве) для представления S3 интерфейса, подобного файловой системе.
После того как корзина S3 смонтирована с помощью s3fs-fuse
, вы можете взаимодействовать с ней, как если бы это была локальная файловая система. Это означает, что вы можете использовать обычные файловые операции (например, чтение, запись, перемещение и т. д.) с файлами в вашей корзине. Это звучит удивительно удобно, и мы можем утверждать, что это упрощает разработку приложений. Но по своей сути объектное хранилище и файловые системы имеют фундаментальные различия, которые повлияют на корзину s3, смонтированную как файловую систему.
Давайте на минутку отойдем от утилиты s3fs-fuse
и обсудим реальные причины, по которым рассмотрение объектного хранилища как файловой системы далеко не оптимально. Проблема намного серьезнее, чем s3fs-fuse
, и включает в себя другие утилиты, такие как точка монтирования на основе Rust для Amazon S3 , файловый клиент, который преобразует вызовы API локальной файловой системы в вызовы API объекта S3. Первая причина заключается в том, что все эти утилиты используют POSIX для операций с файловой системой. POSIX неэффективен и никогда не предназначался для работы с очень большими файлами по сети.
Скорость систем на базе POSIX снижается по мере увеличения спроса, особенно одновременного спроса на них. Когда крупным организациям необходимо хранить океаны данных и получать к ним доступ для глубокого обучения, искусственного интеллекта и других сценариев использования с интенсивным использованием данных, POSIX не имеет возможности или масштабируемости для удовлетворения этих требований. Хотя массивы All-Flash сохранили POSIX в игре, масштабируемость и API-интерфейсы RESTful (отличительные черты облака) подобны криптониту.
По этой причине запуск POSIX поверх хранилища объектов неоптимален. Давайте рассмотрим некоторые причины:
Производительность: интерфейс POSIX FS по своей сути ориентирован на IOPS. Они болтливы, дороги и их трудно масштабировать. RESTful S3 API решает эту проблему, превращая количество операций ввода-вывода в секунду в проблему пропускной способности. Пропускную способность легче и дешевле масштабировать. Вот почему объектное хранилище отличается высокой производительностью в больших масштабах. Наложение POSIX поверх S3 не будет масштабироваться, поскольку POSIX слишком «болтлив», чтобы его можно было выполнять через интерфейс HTTP RESTful.
Семантика. Поскольку объектные операции являются атомарными и неизменяемыми, невозможно гарантировать корректность согласованности. Это означает, что вы можете потерять незафиксированные данные в случае сбоя или столкнуться с проблемами повреждения в случае общего монтирования.
Целостность данных : записи или любые изменения в файле не будут отображаться в пространстве имен до тех пор, пока он не будет зафиксирован. Это означает, что одновременный доступ к общим узлам не заметит изменений. Это бесполезно для общего доступа.
Контроль доступа. Разрешения POSIX и списки ACL примитивны и несовместимы со способом обработки политик идентификации и управления доступом API S3. Невозможно безопасно реализовать управление доступом POSIX на верхних API-интерфейсах S3.
В POSIX также отсутствует большая часть функций, которые так нравятся разработчикам в S3, такие как шифрование на уровне объекта, управление версиями, неизменяемость — они просто не имеют эквивалента в мире POSIX, и ничто не может их преобразовать.
Эти примеры иллюстрируют проблему и ее последствия. Для начала мы будем использовать этот CSV-файл размером примерно 10 ГБ и содержащий 112 строк.
Примечание. Мы предполагаем, что s3fs-fuse
уже установлен и вы смонтировали один из бакетов из объектного хранилища в свою файловую систему. Если нет, следуйте инструкциям здесь .
В этих примерах мы предполагаем, что имя корзины — test-bucket, а имя файла — такси-data.csv находится в каталоге /home/user/, а s3fs-fuse bucket
смонтирована в /home/user/test-bucket/.
Сначала мы попробуем что-то простое: попробуем скопировать CSV-файл в нашу тестовую корзину с помощью команд mc и записать затраченное время.
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, чтобы проверить это. Мы сделаем простой пример Pandas как с s3fs-fuse
так и с пакетом python s3fs
и посмотрим, как это повлияет на производительность.
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 на уровне 325 ГиБ/с (349 ГБ/с) на GET и 165 ГиБ/с (177 ГБ/с) на PUT всего с 32 узлами готовых твердотельных накопителей NVMe.
Просто нет необходимости в утилите файловой системы между MinIO и вашим приложением! Любые преимущества, которые могут получить устаревшие приложения, будут сведены на нет недостатками POSIX.
Если у вас есть какие-либо вопросы по использованию перевода POSIX для вашего приложения, обязательно свяжитесь с нами в Slack !
Также опубликовано здесь .