VK Cloud

S3-CSI в Managed Kubernetes: масштабирование приложений без потери общих файлов

24 июля 2026 г.
268267_007n7ek.jpg
Евгений Левашов
Автор статьи
_blog_head_100.png

Представьте, что интернет-магазин масштабирует сервис загрузки фотографий товаров с 2 до 10 подов. Покупатель загружает фото в под №3, а под №7 это фото не видит — у каждой реплики свой локальный диск. Та же картина на медиаплатформе: ролик попадает в один под, а транскодировщик крутится в другом. Или в системе документооборота, где PDF-файл должен быть доступен всем репликам одновременно.

S3-CSI решает именно эту проблему: аддон монтирует S3-бакет как обычный каталог, и все поды кластера видят одни и те же файлы. Конфигурация через persistent volume не требует сетевой файловой системы и инфраструктуры поверх кластера — достаточно бакета Object Storage и нескольких строк манифеста.

Расскажем, как это устроено изнутри, когда S3-CSI подходит, а когда нет, и как подключить аддон в VK Cloud Managed Kubernetes с примерами YAML-конфигурации.

Новиков2.jpg

Статья подготовлена вместе с экспертом

Сергей Новиков, менеджер продукта Managed Kubernetes

Почему масштабирование stateful-приложений сложнее

Kubernetes отлично масштабирует stateless-приложения: HTTP-сервис без внутреннего состояния можно размножить с replicas: 2 до replicas: 50 за секунды, и каждая реплика будет обрабатывать запросы независимо. Проблема начинается, когда приложение работает с файлами.

Как только несколько подов должны читать и писать одни и те же данные, хранение файлов в Kubernetes превращается в отдельную задачу. Загрузчики файлов, CMS, медиасервисы, системы документооборота — все они работают с пользовательским контентом и не укладываются в модель полностью stateless-приложений: им нужно общее файловое пространство, которое переживает рестарты и доступно сразу с нескольких нод.

Три сценария хранения файлов и их ограничения

EmptyDir и hostPath. EmptyDir создаётся вместе с подом и уничтожается вместе с ним: данные теряются при каждом рестарте. hostPath монтирует директорию хост-ноды в контейнер, что решает проблему эфемерности, но привязывает под к конкретной ноде — горизонтальное масштабирование невозможно, потому что планировщик не гарантирует попадание пода на ту же ноду.

PersistentVolume на блочном хранилище (режим RWO). Стандартный способ подключить постоянное хранилище. Блочные диски (аналоги AWS EBS, Google Persistent Disk) поддерживают только режим ReadWriteOnce: том монтируется к одной ноде одновременно. При горизонтальном масштабировании вторая реплика просто не получит доступ к тому же диску, если попала на другую ноду. Единственная точка записи — единственная точка отказа: если под с RWO-томом умирает, новая реплика должна дождаться отмонтирования диска, прежде чем получит к нему доступ.

ReadWriteMany через NFS или CephFS. Решение для по-настоящему разделяемого доступа: режим RWX позволяет монтировать том на нескольких нодах одновременно. Но цена такого решения — NFS-сервер или кластер Ceph нужно разворачивать и обслуживать отдельно. Ceph требует минимум 3 ноды (на каждой запускаются роли monitor, manager, OSD) и Rook-оператора для управления. Это отдельная операционная нагрузка, отдельный контур мониторинга, отдельная команда, которая понимает, почему упал OSD-демон. Плюс блочное и сетевое хранилище оплачивается по provisioned capacity: платите за зарезервированный объём, даже если диск заполнен наполовину.

Как работает S3-CSI: объектное хранилище как диск

CSI (Container Storage Interface) — стандартный интерфейс Kubernetes для подключения систем хранения данных. Драйвер состоит из двух компонентов: Controller Plugin (развёртывается как Deployment или StatefulSet) и Node Plugin (DaemonSet на каждой ноде кластера).

CSI-драйвер для объектного хранилища работает иначе, чем блочный: вместо протокола блочного хранилища (iSCSI, NVMe-oF) он монтирует S3-бакет в файловую систему через FUSE (Filesystem in Userspace). FUSE перехватывает системные вызовы файловой системы на уровне ядра и транслирует их в S3-операции (GET, PUT, LIST). Для приложения это выглядит как обычная директория — никакого S3-специфичного кода.

Существует несколько реализаций FUSE для S3: GeeseFS (рекомендованный вариант, баланс POSIX-совместимости и скорости), s3fs (широкая POSIX-поддержка, медленнее на параллельных операциях), goofys (максимальная скорость, минимум POSIX-совместимости). GeeseFS — клиент по умолчанию в драйвере csi-s3, у AWS-драйвера свой клиент Mountpoint

Архитектура S3-CSI в кластере

Поток работы: создание PersistentVolumeClaim запускает CSI Controller, который регистрирует PV и связывает его с бакетом Object Storage. При планировании пода Node Plugin на соответствующей ноде монтирует бакет через FUSE в указанный mountPath. С точки зрения контейнера по пути /data/uploads (или любому другому) находится обычная директория.

Принципиальное отличие от блочных дисков такое: S3-бакет может быть смонтирован одновременно на любом числе нод. Каждый под кластера, который ссылается на один PVC в режиме RWX, получает доступ к одному пространству файлов. При горизонтальном масштабировании через HPA или ручное kubectl scale новая реплика автоматически монтирует тот же бакет через Node Plugin на своей ноде и немедленно видит все файлы.

Отмонтировать диск и ждать, пока освободится предыдущий под, не нужно — как и ограничивать запись одной репликой. Все реплики работают с одним и тем же пространством объектов.

Изоляция данных от жизненного цикла контейнеров

S3-бакет существует независимо от любых объектов Kubernetes. CrashLoopBackOff пода, rolling update Deployment, node drain перед обслуживанием, полное пересоздание кластера — файлы остаются в бакете нетронутыми. Node Plugin размонтирует бакет при завершении пода, но содержимое бакета никуда не девается. EmptyDir уничтожает данные вместе с подом, hostPath привязывает их к конкретной ноде и теряет при миграции. При использовании dynamic provisioning с reclaimPolicy: Retain бакет не удаляется даже при удалении PVC.

Какие четыре задачи решает аддон S3-CSI в VK Cloud

1. Масштабирование без риска потери данных.

Масштабирование Kubernetes-приложений с файловыми данными обычно сводится к выбору между сложностью (NFS/Ceph) и ограничениями (RWO). S3-CSI убирает этот компромисс для сценариев с пользовательским контентом. При replicas: N в Deployment каждая из N реплик монтирует один и тот же бакет через свой Node Plugin. Файл, который загрузил пользователь через реплику №1, немедленно доступен репликам №2 и №3: физически он хранится в бакете, а не на локальном диске пода. HPA может добавить реплику за секунды, и она сразу включается в работу с полным доступом к данным.

2. Снижение затрат на хранение.

Блочный диск в Kubernetes работает по модели provisioned capacity: вы заказываете диск на 200 ГБ и платите за 200 ГБ, даже если сейчас занято 40 ГБ. При оверпровизионинге — а его рекомендуют, чтобы не упираться в лимит в пиковые моменты — разрыв между оплачиваемым и используемым объёмом бывает значительным. VK Object Storage работает по модели pay-per-use: оплата только за фактически занятый объём. При росте данных это обычно оказывается ощутимо дешевле provisioned SSD-дисков, особенно для архивных данных, старых версий файлов и резервных копий.

3. Защита от нехватки места.

Заполненный блочный диск — классическая операционная боль: поды останавливаются с ошибкой No space left on device, начинается цепочка ручных операций — ресайз PV в облаке, ресайз файловой системы внутри пода, перезапуск пода. S3-бакет не имеет физического потолка в привычном смысле: Object Storage масштабируется автоматически. Данные растут — бакет растёт вместе с ними, а операционные действия сводятся к настройке политик жизненного цикла объектов, а не к экстренному расширению диска в три часа ночи.

4. Постоянный доступ вне зависимости от состояния подов.

Rolling update Deployment с RWO-томом создаёт окно недоступности: пока старый под завершается и отмонтирует диск, новый под ждёт. При RWX через S3-CSI этой проблемы нет: все поды, старые и новые, работают с одним бакетом без очереди. То же при node drain: даже если нода уходит на обслуживание и все её поды переезжают на другие ноды, файлы в бакете никуда не деваются — Node Plugin на новой ноде монтирует тот же бакет, и под продолжает работу.

Подключение аддона и настройка PersistentVolume

Активация аддона

В VK Cloud Managed Kubernetes S3-CSI подключается как аддон: откройте панель управления, перейдите в раздел Managed Kubernetes, выберите кластер, затем раздел «Аддоны» и активируйте S3-CSI. Аддон доступен как при создании нового кластера, так и для уже работающего. После активации в кластере появится StorageClass для S3-CSI.

Статическое провизионирование: подключить существующий бакет

Подходит, когда бакет уже существует — например, данные уже там лежат или бакет создан заранее с нужными политиками. PersistentVolume создаётся вручную, с указанием имени бакета и данных доступа через Secret.

# Secret с данными доступа к Object Storage apiVersion: v1 kind: Secret metadata: name: s3-csi-secret namespace: production type: Opaque stringData: accessKey: "YOUR_ACCESS_KEY" secretKey: "YOUR_SECRET_KEY" --- # PersistentVolume, ссылающийся на существующий бакет apiVersion: v1 kind: PersistentVolume metadata: name: media-uploads-pv spec: capacity: storage: 1Ti # номинальное значение; реальный объём не ограничен accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: s3-csi csi: driver: s3.csi.aws.com volumeHandle: media-uploads-bucket volumeAttributes: bucketName: "media-uploads-bucket" endpoint: "https://hb.vkcs.cloud" nodeStageSecretRef: name: s3-csi-secret namespace: production --- # PVC, ссылающийся на PV apiVersion: v1 kind: PersistentVolumeClaim metadata: name: media-uploads-pvc namespace: production spec: accessModes: - ReadWriteMany resources: requests: storage: 1Ti storageClassName: s3-csi volumeName: media-uploads-pv

Статическое провизионирование стоит выбирать, когда бакет уже содержит данные, нужна точная настройка политик бакета (versioning, lifecycle) или идёт миграция с другого хранилища.

Динамическое провизионирование: бакет создаётся автоматически

Достаточно объявить PVC — CSI Controller сам создаст PV и бакет в Object Storage. Удобно для новых проектов и автоматизации через Helm.

apiVersion: v1 kind: PersistentVolumeClaim metadata: name: user-uploads-pvc namespace: production spec: accessModes: - ReadWriteMany resources: requests: storage: 500Gi # номинальное значение для PV storageClassName: s3-csi

По умолчанию reclaimPolicy: Delete — бакет удаляется вместе с PVC. Для продакшена рекомендуется Retain (прописывается в StorageClass или PV явно): с ним данные переживают даже случайное удаление PVC.

Монтирование в Pod и Deployment

apiVersion: apps/v1 kind: Deployment metadata: name: media-service namespace: production spec: replicas: 5 selector: matchLabels: app: media-service template: metadata: labels: app: media-service spec: containers: - name: media-service image: registry.example.com/media-service:latest volumeMounts: - name: uploads mountPath: /data/uploads # приложение работает с обычными файловыми путями volumes: - name: uploads persistentVolumeClaim: claimName: user-uploads-pvc

Все 5 реплик монтируют один бакет. Приложение в контейнере работает с директорией /data/uploads как с обычной файловой системой: читает, пишет новые файлы, создаёт поддиректории. Никакого S3 SDK в коде приложения не требуется.

Практические ограничения S3-CSI

  • Latency на случайном доступе. FUSE-прослойка добавляет задержку по сравнению с блочным хранилищем: для последовательного чтения и записи больших файлов (медиа, архивы, логи) она практически незаметна, для баз данных с интенсивным случайным read/write мелких блоков (4 КБ–64 КБ) — ощутима на каждой операции. SQLite, PostgreSQL, MySQL поверх S3-CSI — неподходящая конфигурация.
  • POSIX-несовместимость. S3-CSI не поддерживает надёжно блокировку файла (flock), атомарный rename (реализуется через copy + delete), partial overwrites и hard links. Обычные веб-приложения, которые читают и пишут файлы, работают корректно. Приложения с файловыми блокировками или с паттерном «запись во временный файл → rename в целевой» могут столкнуться с непредсказуемым поведением.
  • Конкурентная запись в один файл. При одновременной записи нескольких подов в один объект возникают race conditions: S3 не гарантирует консистентность при конкурентных PUT-запросах. Решение — каждый под пишет в свою поддиректорию или использует префикс (/data/uploads/{pod-name}/ или /data/uploads/{user-id}/).
  • Spark shuffle и аналогичные паттерны. Задачи, которым нужен rename как атомарная операция, и интенсивная конкурентная запись мелких файлов не подходят для S3-CSI.

S3-CSI — правильное решение для медиафайлов, пользовательских загрузок, документов, архивов, логов и любых сценариев с крупными файлами и преимущественно последовательным доступом. Неправильное — для баз данных, Spark shuffle, приложений с интенсивным file locking.

Сравнение способов хранения файлов

Параметр EmptyDir / hostPath PV (RWO, блочный SSD) PV (RWX, NFS/Ceph) S3-CSI (аддон)
Доступ с нескольких подов Нет Нет (один под/нода) Да Да
Данные при перезапуске пода Теряются / привязка к ноде Сохраняются Сохраняются Сохраняются
Данные при пересоздании кластера Теряются Сохраняются Сохраняются Сохраняются
Масштабирование на N нод Невозможно Нет (RWO) Да Да
Оплата хранения Provisioned capacity Provisioned + инфраструктура Ceph/NFS Pay-per-use
Ограничение объёма Объём ноды Зарезервированный размер диска Зарезервированный размер Практически нет
Операционная сложность Минимальная Низкая Высокая (Ceph — от 3 нод) Низкая (аддон)
Подходит для медиа/загрузок Нет Нет (при масштабировании) Да Да

S3-CSI закрывает пробел между блочными дисками (просто, но только RWO) и сетевыми файловыми системами (RWX, но с операционной нагрузкой). Для приложений с пользовательским контентом — медиа, загрузки, документы, архивы — компромисс понятный: горизонтальное масштабирование без NFS, данные переживают рестарты и пересоздание кластера, оплата за фактический объём, а не за зарезервированный.

POSIX-ограничения через FUSE — это граница применимости сценария, а не дефект реализации. Базы данных, Spark shuffle, приложения с file locking выбирают другие решения. Для пользовательских файлов в веб-приложениях подходит S3-CS.

Аддон в VK Cloud Managed Kubernetes снимает операционный барьер: не нужно разворачивать Ceph, настраивать NFS-сервер, управлять отдельным хранилищным кластером. Активация через панель управления, YAML-манифест с PVC — и поды получают разделяемое хранилище за минуты.

Частые вопросы про S3-CSI в Kubernetes

Что такое S3-CSI для Kubernetes?

Драйвер Kubernetes, который монтирует S3-бакет как обычный каталог внутри контейнера через FUSE. Приложение работает с обычными файловыми путями без S3-специфичного кода, а данные физически хранятся в объектном хранилище.

Как S3-CSI помогает при масштабировании?

При росте числа реплик каждая новая реплика монтирует тот же S3-бакет через Node Plugin на своей ноде и немедленно видит все файлы. Синхронизация между подами не требуется: файл, записанный в одну реплику, доступен остальным мгновенно.

Чем S3-хранилище дешевле блочного диска?

Блочный диск оплачивается по provisioned capacity — платите за зарезервированный объём вне зависимости от фактического использования. Object Storage работает по модели pay-per-use, оплачивая только фактически занятый объём. При неравномерном использовании или росте данных экономия бывает значительной.

Что происходит с файлами при перезапуске всех подов?

Файлы остаются в S3-бакете нетронутыми. Бакет существует независимо от подов, нод и кластера. После рестарта подов Node Plugin монтирует тот же бакет, и все данные снова доступны без каких-либо действий со стороны операционной команды.

Как активировать S3-CSI в VK Cloud Managed Kubernetes?

Панель управления VK Cloud → Managed Kubernetes → выбрать кластер → раздел «Аддоны» → активировать S3-CSI. Аддон доступен при создании нового кластера и для уже работающего. После активации появляется StorageClass, и можно создавать PVC с типом доступа ReadWriteMany.

Оставьте заявку, чтобы получить консультацию

Наши специалисты свяжутся с вами в ближайшее время и ответят на все вопросы.

section-subscribe_2x.png

            Узнавайте о выходе новых статей в блоге первыми!

            Будем держать в курсе новостей и облачных трендов

            section-subscribe_2x.png
              section-subscribe_2x.png
              Теги: kubernetes, автомасштабирование, объектное хранилище, архитектура, VK Cloud
              Ссылка скопирована
              Поделиться

              Почитать по теме

              _blog_head_158.png
              24 июля

              External Secrets Operator в Managed Kubernetes: безопасное управление секретами без ручной работы

              blog_head_39_69.png
              20 июля

              Kubernetes для разработчика: локально (Minikube, kind) и в облаке

              40+ готовых сервисов