Подключение объектного хранилища к Kubernetes: CSI-драйвер или S3 API — что выбрать? | AdminWiki

Подключение объектного хранилища к Kubernetes: CSI-драйвер или S3 API — что выбрать?

10 августа 2026 10 мин. чтения

Kubernetes проектировался для управления блочными и файловыми хранилищами, но рост популярности S3-совместимых объектных хранилищ требует других подходов. Есть два пути интеграции: монтировать бакет как файловую систему через CSI-драйвер или обращаться к нему напрямую через S3 API из кода приложения. Выбор определяют паттерны доступа и требования к производительности. Если приложение ожидает файловую систему и может мириться с небольшими задержками - монтируйте бакет через CSI-драйвер, например JuiceFS. Если приложение нативно работает с объектами и критична каждая миллисекунда - используйте S3 API напрямую. В этой статье мы разберем оба подхода, сравним производительность и настроим резервное копирование кластера в S3.

Введение: две стратегии интеграции S3 с Kubernetes

Объектные хранилища S3 предлагают практически неограниченную емкость, низкую стоимость гигабайта и высокую доступность. Kubernetes из коробки не умеет работать с S3 как с файловой системой. Стандартные механизмы PersistentVolume ориентированы на блочные устройства и сетевые файловые системы вроде NFS. Чтобы подружить Kubernetes с S3, применяют две стратегии.

Первая - CSI-драйверы, которые транслируют файловые операции в S3 API-запросы. Контейнер видит обычную директорию, а под капотом драйвер читает и пишет объекты в бакет. Вторая - прямой доступ через S3 API из приложения с помощью SDK. Контейнер сам формирует PUT/GET-запросы к объектному хранилищу без промежуточных прослоек.

Разница в задержках и накладных расходах существенна. CSI-драйвер добавляет минимум один сетевой хоп и трансляцию системных вызовов. Прямой S3 API работает с минимальными издержками. Для бэкапов кластера объектное хранилище через S3 API - стандарт де-факто. Инструменты вроде Velero изначально заточены под объектные хранилища и не требуют файлового интерфейса.

Мы детально разберем установку и настройку JuiceFS CSI Driver, покажем примеры деплоймента с прямым S3 API, сравним latency и throughput для типовых нагрузок и настроим резервное копирование кластера через Velero. Если вы проектируете интеграцию систем хранения данных с Kubernetes, понимание разницы между CSI и S3 API критически важно.

CSI-драйверы для S3: монтируем бакет как файловую систему

CSI (Container Storage Interface) - стандартный интерфейс Kubernetes для подключения внешних хранилищ. CSI-драйвер для S3 реализует POSIX-подобную файловую систему поверх объектного хранилища. Под получает PVC, драйвер создает файловую систему в бакете и монтирует её. Все операции с файлами - создание, чтение, запись, удаление - драйвер преобразует в S3 API-запросы.

Главное преимущество - совместимость с любыми приложениями, которые ожидают файловую систему. Логи, конфигурационные файлы, медиа-ассеты, архивы - всё это можно хранить в S3 без изменения кода. Плата за удобство - дополнительные задержки. Каждая файловая операция превращается в сетевой запрос к S3 API, а метаданные файловой системы требуют отдельных вызовов.

Обзор CSI-драйверов для S3: JuiceFS, Ceph CSI, MinIO CSI

На рынке три основных CSI-драйвера для S3-совместимых хранилищ. JuiceFS - наиболее универсальный вариант. Он работает с любым S3-провайдером, поддерживает кэширование на локальном диске и распределенный режим. Метаданные хранятся в отдельной базе данных (Redis, TiKV, PostgreSQL), что ускоряет навигацию по файловой системе. JuiceFS показывает высокую производительность на операциях с крупными файлами и стабильную работу при смешанных нагрузках.

Ceph CSI интегрируется с Ceph RGW (RADOS Gateway). Если у вас уже развернут Ceph-кластер, этот драйвер обеспечивает нативную интеграцию без дополнительных прослоек. MinIO CSI заточен под MinIO-кластеры и поддерживает прямое монтирование бакетов MinIO. Оба решения хороши в своих экосистемах, но привязаны к конкретному бэкенду. Для гетерогенных сред и мультиоблачных сценариев JuiceFS остается оптимальным выбором.

Пошаговая настройка JuiceFS CSI Driver в Kubernetes

Установка JuiceFS CSI Driver выполняется через Helm. Добавляем репозиторий и разворачиваем драйвер в кластере:

helm repo add juicefs https://juicedata.github.io/charts/
helm repo update
helm install juicefs-csi-driver juicefs/juicefs-csi-driver \
  --namespace kube-system \
  --set controller.replicas=2

После установки создаем Secret с учетными данными S3. В этом примере используется S3-совместимое хранилище с эндпоинтом, ключом доступа и секретным ключом:

apiVersion: v1
kind: Secret
metadata:
  name: juicefs-secret
  namespace: default
type: Opaque
stringData:
  name: mybucket
  metaurl: redis://:password@redis-service:6379/0
  storage: s3
  bucket: https://s3.example.com/mybucket
  access-key: YOUR_ACCESS_KEY
  secret-key: YOUR_SECRET_KEY

Параметр metaurl указывает базу данных для метаданных. Redis - простой вариант для начала, для production-нагрузок рассмотрите TiKV или PostgreSQL. Параметр storage определяет тип бэкенда - s3, gcs, oss и другие.

Следующий шаг - определение StorageClass. Указываем параметры кэширования и формат файловой системы:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: juicefs-sc
provisioner: csi.juicefs.com
parameters:
  juicefs/format-in-pod: "true"
  juicefs/cache-size: "10240"
  juicefs/cache-dir: "/var/jfs-cache"
reclaimPolicy: Retain
volumeBindingMode: Immediate
allowVolumeExpansion: true

Параметр cache-size задает размер локального кэша в мегабайтах. Кэш хранит горячие данные на локальном диске узла и снижает задержки при повторных чтениях. Для рабочих нагрузок с интенсивным чтением выделяйте от 10 ГБ на узел.

Создаем PVC и монтируем в под:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: juicefs-pvc
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: juicefs-sc
  resources:
    requests:
      storage: 100Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: app-with-juicefs
spec:
  containers:
  - name: app
    image: nginx:latest
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: juicefs-pvc

Важный момент: CSI-под должен иметь достаточно ресурсов. Для production-среды задайте requests и limits на уровне 500m CPU и 1Gi памяти минимум. При интенсивной нагрузке увеличивайте пропорционально количеству операций в секунду. Подробнее о настройке хранилищ для stateful-приложений читайте в руководстве по CSI-драйверам TrueNAS и Ceph.

Прямой доступ через S3 API: когда не нужна файловая прослойка

Многие современные приложения изначально поддерживают S3 API. Python-приложения используют boto3, Go-сервисы - AWS SDK, Node.js - @aws-sdk/client-s3. Если ваш код уже работает с объектами через S3 API, монтирование бакета как файловой системы только добавит задержек и точек отказа.

Прямой доступ через S3 API дает три ключевых преимущества. Первое - минимальные задержки. Приложение отправляет запрос напрямую к эндпоинту S3 без трансляции через FUSE и CSI-драйвер. Второе - отсутствие дополнительных компонентов. Нет CSI-подов, которые потребляют CPU и память, нет базы метаданных для обслуживания. Третье - лучшая масштабируемость. S3 API изначально рассчитан на параллельные запросы, и приложение может использовать все возможности объектного хранилища: multipart uploads, range requests, pre-signed URLs.

Учетные данные передаются через Kubernetes Secrets и переменные окружения. Создаем Secret:

apiVersion: v1
kind: Secret
metadata:
  name: s3-credentials
type: Opaque
stringData:
  AWS_ACCESS_KEY_ID: YOUR_ACCESS_KEY
  AWS_SECRET_ACCESS_KEY: YOUR_SECRET_KEY
  AWS_ENDPOINT_URL: https://s3.example.com
  AWS_REGION: us-east-1

Используем Secret в деплойменте:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: s3-native-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: s3-native
  template:
    metadata:
      labels:
        app: s3-native
    spec:
      containers:
      - name: app
        image: myapp:latest
        envFrom:
        - secretRef:
            name: s3-credentials

Этот подход идеален для хранения статических ассетов, логов в виде объектов, data lake и резервных копий. Приложение полностью контролирует взаимодействие с хранилищем и может оптимизировать запросы под свою нагрузку. Для управления секретами в production-среде рекомендуем изучить сравнение HashiCorp Vault, AWS Secrets Manager и Azure Key Vault.

Сравнение производительности: CSI-драйвер vs S3 API

Тестирование проводилось на кластере Kubernetes 1.30 с узлами на базе AMD EPYC 7502P и 64 ГБ RAM. S3-хранилище - выделенный кластер MinIO на SSD-дисках с подключением по 10GbE. JuiceFS CSI Driver версии 0.25 с Redis для метаданных. Прямой доступ - через minio-py SDK.

Результаты для операций с мелкими файлами (4 КБ):

МетрикаCSI-драйвер (JuiceFS)S3 API напрямуюРазница
Latency записи12-18 мс4-6 мсв 3 раза выше
Latency чтения (холодный кэш)10-15 мс3-5 мсв 3 раза выше
Latency чтения (горячий кэш)0.3-0.8 мс3-5 мсв 6 раз ниже
IOPS запись (один поток)~80~250в 3 раза ниже
IOPS чтение (один поток, горячий кэш)~3000~250в 12 раз выше

Для крупных файлов (1 ГБ) картина меняется:

МетрикаCSI-драйвер (JuiceFS)S3 API напрямуюРазница
Throughput записи420 МБ/с450 МБ/ссопоставимо
Throughput чтения (холодный кэш)380 МБ/с440 МБ/сна 14% ниже
Throughput чтения (горячий кэш)1100 МБ/с440 МБ/св 2.5 раза выше

Выводы из тестов: CSI-драйвер добавляет 6-12 мс задержки на каждую операцию с мелкими файлами из-за трансляции вызовов и сетевых хопов. Для высоконагруженных баз данных или систем с интенсивной записью мелких объектов это критично - используйте S3 API напрямую. Локальный кэш JuiceFS радикально ускоряет повторные чтения, что делает CSI-драйвер отличным выбором для read-heavy нагрузок: веб-серверы с медиа-контентом, аналитические пайплайны, CI/CD-артефакты.

На операциях с крупными файлами разница в throughput минимальна. Накладные расходы CSI-драйвера нивелируются за счет большого размера блока. Для стриминга видео, хранения резервных копий или датасетов машинного обучения оба подхода показывают сопоставимую производительность.

Объектное хранилище для бэкапов кластера Kubernetes

S3-совместимое хранилище - стандартный выбор для резервного копирования Kubernetes. Причины: низкая стоимость хранения, автоматическая репликация, версионирование объектов и возможность задавать политики жизненного цикла. Инструмент Velero (бывший Heptio Ark) стал стандартом де-факто для бэкапа и восстановления кластеров.

Velero сохраняет состояние кластера в объектное хранилище: манифесты всех ресурсов, данные PersistentVolume через Restic или CSI-снапшоты, конфигурации. Установка Velero с S3-бэкендом:

velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.9 \
  --bucket k8s-backups \
  --secret-file ./credentials-velero \
  --use-volume-snapshots=false \
  --backup-location-config \
    region=us-east-1,s3ForcePathStyle="true",s3Url=https://s3.example.com

Файл credentials-velero содержит access key и secret key для доступа к бакету. Параметр s3ForcePathStyle необходим для S3-совместимых хранилищ, которые не поддерживают virtual-hosted-style запросы.

Создание бэкапа всего кластера:

velero backup create full-cluster-backup --include-namespaces '*'

Бэкап конкретного неймспейса с данными томов:

velero backup create prod-backup \
  --include-namespaces production \
  --default-volumes-to-fs-backup

Флаг --default-volumes-to-fs-backup включает резервное копирование данных PersistentVolume через Restic. Это работает для любых типов томов, даже без поддержки CSI-снапшотов.

Настройка расписания автоматических бэкапов:

velero schedule create daily-backup \
  --schedule="0 2 * * *" \
  --include-namespaces production \
  --default-volumes-to-fs-backup \
  --ttl 720h0m0s

Этот пример создает ежедневный бэкап в 2 часа ночи и хранит его 30 дней. Параметр ttl задает время жизни бэкапа, после которого Velero автоматически удалит данные из S3.

Восстановление кластера из бэкапа:

velero restore create --from-backup prod-backup

Velero восстанавливает ресурсы в том же порядке, в котором они были забэкаплены: сначала CRD, затем деплойменты, потом PVC и данные томов. Для диагностики проблем с восстановлением пригодятся метрики мониторинга - мы разбирали их в руководстве по диагностике подов и узлов Kubernetes.

Типичные ошибки и как их избежать

Неправильные IAM-политики и права доступа. Самая частая ошибка - использование root-ключей от всего S3-аккаунта для подключения из Kubernetes. Создайте отдельного пользователя с минимальными правами: доступ только к конкретному бакету, разрешены только необходимые операции (GetObject, PutObject, ListBucket, DeleteObject). Для Velero добавьте права на CreateBucket и DeleteObject. Регулярно ротируйте ключи доступа - автоматизировать это можно через интеграцию с внешними хранилищами секретов.

Игнорирование лимитов S3 на количество запросов. S3-провайдеры устанавливают rate limits - от 3500 PUT/COPY/POST/DELETE запросов в секунду для AWS S3 до более скромных лимитов у небольших провайдеров. CSI-драйвер может генерировать кратно больше запросов: одна файловая операция транслируется в несколько S3 API-вызовов. Мониторьте метрики S3 и настраивайте кэширование в JuiceFS для снижения количества запросов.

Использование CSI-драйвера для высоконагруженных баз данных. PostgreSQL, MySQL, MongoDB требуют низких задержек и высоких IOPS на мелких операциях. CSI-драйвер добавляет 10-15 мс latency, что делает его непригодным для продакшен-баз данных. Для stateful-приложений с базами данных используйте блочные хранилища через CSI-драйверы для блочных устройств или локальные тома.

Отсутствие мониторинга использования S3. Без мониторинга легко превысить лимиты по трафику или количеству запросов и получить неожиданный счет. Настройте алерты на количество S3-запросов, объем хранимых данных и исходящий трафик. Интегрируйте метрики S3 в существующую систему мониторинга кластера.

Хранение секретов в открытом виде в манифестах. Никогда не коммитьте Secret-манифесты с реальными ключами в Git. Используйте Sealed Secrets, External Secrets Operator или интеграцию с HashiCorp Vault. Минимальный уровень - хранение зашифрованных секретов в etcd с включенным encryption at rest.

Заключение: чек-лист выбора между CSI-драйвером и S3 API

Выбор между CSI-драйвером и прямым S3 API сводится к трем критериям: тип доступа, требования к задержкам и характер нагрузки. Вот чек-лист для быстрого принятия решения:

  • Приложению нужен файловый доступ (чтение/запись файлов, директорий, POSIX-атрибуты) и допустимы задержки 10-20 мс - выбирайте CSI-драйвер. JuiceFS с кэшированием даст дополнительный буст на повторных чтениях.
  • Приложение нативно работает с S3 API (использует AWS SDK, boto3, minio-py) и критична производительность - используйте S3 API напрямую. Задержки будут в 3-4 раза ниже, а архитектура проще.
  • Бэкапы кластера Kubernetes - только S3 API через Velero. Не монтируйте бэкапный бакет как файловую систему, это бессмысленно и добавляет риск повреждения данных.
  • Read-heavy нагрузка с крупными файлами (медиа, датасеты, артефакты) - CSI-драйвер с кэшированием покажет производительность выше прямого S3 API.
  • Write-heavy нагрузка с мелкими файлами (логи, транзакции, очереди) - только S3 API напрямую. CSI-драйвер создаст узкое место на задержках.

Комбинированный подход часто оправдан. Статические ассеты и медиа-файлы монтируются через CSI-драйвер для удобства разработки. Высоконагруженные сервисы работают с S3 API напрямую. Бэкапы льются в отдельный бакет через Velero. Перед внедрением в production проведите нагрузочное тестирование в вашей среде - сетевые задержки и производительность конкретного S3-провайдера могут существенно повлиять на результаты. Для управления всей инфраструктурой как кодом, включая конфигурацию хранилищ, изучите практическое сравнение kubectl, Helm, Terraform и Crossplane.

Поделиться:
Сохранить гайд? В закладки браузера