Shared storage в CI в 2026 — это почти всегда компромисс между простотой (NFS), «распределённостью» (GlusterFS) и системным подходом к отказоустойчивости и консистентности (CephFS). На бумаге все три дают POSIX-совместимый доступ, но на практике они по-разному ведут себя на типичных CI-нагрузках: миллионы маленьких файлов, много операций stat()/open()/rename(), параллельные сборки, частые удаления и перезаписи кэшей.
Ниже — практичное сравнение в формате «что сломается первым», «где будет больно по latency», «как лечится», и в каких сценариях лучше вообще не городить distributed filesystem ради кэша.
Контекст CI: почему кэш ломает нервы
CI cache часто выглядит безобидно (папка с зависимостями), но по профилю нагрузки это один из самых неприятных типов I/O.
- small files: множество файлов по 1–64 КБ, включая дерево
node_modules,vendor,.m2,pip-кэши; - metadata latency: львиная доля времени уходит на метаданные (поиск, права, владельцы, времена, каталогизация), а не на чтение данных;
- конкурентные записи: несколько job’ов могут читать/писать одни и те же пути, иногда с «умными» lock-файлами;
- атомарность: CI любит
rename()как «атомарный коммит» артефакта или кэша; - POSIX locks: часть инструментов полагается на advisory locks (например, через
flock), часть — на lock-файлы и семантикуO_EXCL.
Отсюда главный вывод: shared storage для CI — это не «прикрутить общий диск», а отдельный слой инфраструктуры, где важны и протокол, и консистентность, и поведение при сбоях.
Краткий TL;DR: что выбирать в 2026
Если сильно упростить выбор:
- NFS — лучший старт для shared storage, если вам нужна предсказуемость, минимальная сложность и вы готовы обеспечить надёжный сервер (и/или HA на уровне хранения).
- CephFS — когда нужны масштабирование, отказоустойчивость на уровне кластера и более «системное» поведение при сбоях, но вы готовы платить сложностью эксплуатации и требованиями к сети/дискам.
- GlusterFS — когда хочется относительно простого распределённого файлового слоя без полноценной экосистемы Ceph, но нужно очень трезво оценивать риски split brain и специфику healing.
В CI кэш — это расходник. Чем сложнее distributed filesystem, тем чаще вы будете выбирать между «чинить кластер сейчас» и «снести кэш и продолжить сборки».
Если вы только начинаете, полезно сперва зафиксировать терминологию и базовые ограничения NFS-подхода. Я подробно разбирал схожие компромиссы в отдельной заметке про выбор сетевого хранилища: NFS vs SSHFS для хранения файлов.

NFS в CI: простой и предсказуемый, но с одной «точкой правды»
NFS остаётся самым массовым вариантом shared storage по простой причине: он минимально меняет модель мышления. Есть сервер, есть экспорты, есть клиенты, есть понятные монтирования (mounts). Для CI это даёт два ключевых плюса: простая диагностика и понятная деградация.
POSIX locks и поведение приложений
Для CI важно, чтобы блокировки работали так, как ожидают инструменты. В NFS блокировки зависят от версии протокола и конфигурации, но в целом модель хорошо изучена и предсказуема: проблемы чаще выглядят как «клиент завис/отвалился/истёк lease», а не как тихая неконсистентность.
Производительность: small files и метаданные
У NFS типичная боль — metadata latency при большом числе операций с каталогами и атрибутами. При этом у вас есть сильный рычаг: вы можете масштабировать сервер (CPU/RAM/NVMe), тюнить параметры на клиенте и на сервере, и получить очень приличную производительность на small files — нередко лучше, чем «средний» распределённый FS на слабой сети.
Практический совет для CI: если кэш на NFS тормозит, сначала профилируйте, это чтение данных или метаданные. Часто узкое место — CPU сервера, недостаток RAM под page cache, медленный диск под журнал, перегруженный network stack или неудачные mount-опции на клиентах.
Отказоустойчивость
NFS сам по себе не делает магию HA. «Сервер умер» обычно означает «всё встало», особенно если клиенты смонтировали FS с поведением, которое блокирует системные вызовы при таймаутах. Поэтому NFS хорошо сочетается либо с отказоустойчивым блочным/объектным слоем ниже, либо со схемой active/passive на уровне сервера.
Когда NFS — лучший выбор
- 1–20 CI-раннеров, умеренный параллелизм.
- Нужен общий workspace/кэш без «зоопарка» компонентов.
- Есть возможность сделать быстрый NFS-сервер (NVMe, RAM) и нормальную сеть.
GlusterFS в CI: distributed filesystem «проще, чем Ceph», но не бесплатный
GlusterFS часто выбирают, когда хочется distributed filesystem без тяжёлой экосистемы. Он действительно может быть удобным, особенно если вы уже мыслите томами/репликацией и готовы жить с особенностями модели.
Про split brain: главный страх GlusterFS
Split brain — это ситуация, когда разные реплики одного и того же файла считают себя «истиной», и автоматическое слияние невозможно. Для CI это особенно опасно, потому что кэш и артефакты часто перезаписываются, а обновления идут параллельно. Итог — «странные» сборки, битые зависимости, флейки, которые исчезают при повторе.
Важно понимать: split brain — не «редкая катастрофа», а закономерность при сетевых проблемах, некорректных отказах узлов или при неудачно подобранной схеме репликации.
Healing: когда кластер «лечится», но вам всё равно больно
У GlusterFS есть healing, который синхронизирует реплики после восстановления связности. В CI healing неприятен тем, что он создаёт фоновую нагрузку и способен резко просадить latency именно тогда, когда раннеры уже под нагрузкой.
- Фоновая синхронизация может «съесть» IOPS и сеть.
- Время доступа к «горячим» каталогам становится непредсказуемым.
- В сложных кейсах требуется ручное вмешательство и понимание, какой файл «правильный».
Small files и метаданные
На small files GlusterFS часто упирается в метаданные и сетевые round-trip’ы. Если CI постоянно «ходит» по деревьям зависимостей, вы можете увидеть ситуацию, когда чтение «почти нулевое», а сборка медленная из-за stat() и обхода директорий.
Mounts и эксплуатационные нюансы
С точки зрения mounts GlusterFS обычно сложнее NFS: больше движущихся частей, больше состояний «кажется, смонтировано, но работает странно». В CI это проявляется как зависающие job’ы или внезапные ошибки I/O. Если вы идёте в GlusterFS, вам нужен чёткий runbook: что делаем при деградации, как быстро «обрубить» использование кэша, как диагностировать split brain, как включать/выключать healing.
Когда GlusterFS уместен
- Нужна репликация на уровне файлового слоя без отдельной системы хранения.
- Вы готовы принять риск split brain и умеете с ним жить (включая процедуру восстановления).
- Кэш можно потерять, а консистентность важнее абсолютной скорости.
CephFS в CI: мощно, масштабируемо, но требовательно
CephFS — это POSIX-совместимый shared storage поверх Ceph-кластера. В отличие от «файловой репликации», Ceph — это полноценная платформа хранения: OSD, MON, MGR и файловые MDS для метаданных. В 2026 это один из самых зрелых подходов к «кластерному диску», но и один из самых дорогих по операционной сложности.
Метаданные и MDS: где выигрываем и где упираемся
CephFS отдельно выделяет слой метаданных (MDS). Это даёт шанс лучше масштабировать metadata latency, особенно когда нагрузка реально упирается в операции с каталогами и атрибутами. Но обратная сторона — MDS становится критичным компонентом: его нужно мониторить, правильно настраивать и масштабировать.
Для CI это важный плюс: многие пайплайны не читают «много мегабайт», они делают «много маленьких действий». CephFS может быть очень хорош именно здесь, если кластер спроектирован правильно.
POSIX locks и консистентность
CephFS обычно выбирают, когда важны более строгие гарантии консистентности в распределённой среде. Но это не означает «никогда не будет проблем»: будут, просто другого класса — чаще в виде просадок при recovery/rebalance, проблем с медленными OSD или сетевой деградацией.
Performance: что реально влияет
В CephFS скорость кэша в CI часто определяется не «магическими настройками», а базой:
- сетевой задержкой и стабильностью;
- типом дисков под OSD (особенно под WAL/DB, если вынесены);
- количеством и состоянием PG/OSD (фоновые операции могут съедать latency);
- производительностью MDS (CPU/RAM) и его загруженностью.
Отказоустойчивость и «плата» за неё
Ceph умеет переживать отказы узлов и дисков, но почти всегда ценой: recovery создаёт нагрузку, а latency может «поплыть». В CI это чувствуется моментально: job’ы становятся медленнее, растёт время ожидания, кэш начинает «мешать» больше, чем помогать. Поэтому важно заранее иметь политику: при какой деградации мы отключаем shared storage для кэша и возвращаемся к локальному кэшу на раннерах.
Когда CephFS уместен
- Много раннеров, высокий параллелизм, нужно горизонтальное масштабирование.
- Нужна отказоустойчивость на уровне хранения, а не «один жирный NFS».
- Есть ресурсы на эксплуатацию Ceph: мониторинг, алерты, регулярные проверки, планирование роста.
Сравнение по ключевым болям CI: короткая матрица
Ниже — не «синтетический бенчмарк», а практическая матрица для типовых вопросов.
Small files и metadata latency
- NFS: часто лучший результат при хорошем сервере; узкое место — один сервер и его ресурсы.
- GlusterFS: может проседать на метаданных; поведение зависит от топологии, RTT и состояния тома.
- CephFS: потенциально лучше масштабируется по метаданным, но требует правильного MDS и здорового кластера.
POSIX locks
- NFS: как правило предсказуемо, но важно понимать версию/настройки и таймауты.
- GlusterFS: в спорных сценариях лучше избегать «общей записи» в один и тот же путь.
- CephFS: обычно более «кластерно» и консистентно, но цена — сложность и зависимость от состояния MDS/OSD.
Split brain, healing и recovery
- NFS: split brain как класс проблем обычно не про него; проблемы чаще «сервер недоступен».
- GlusterFS: split brain — ключевой риск; healing может мешать CI в самый неподходящий момент.
- CephFS: split brain в «глустеровском» смысле обычно не основной страх, но recovery/rebalance может съедать latency.

Практический подход: как проектировать shared storage для CI cache
1) Сначала решите, точно ли вам нужен shared storage
Парадокс CI: общий кэш удобен, но общий кэш же становится точкой массового отказа. Во многих командах лучше работает модель «локально быстро, по сети — только при необходимости».
- Локальный кэш на раннере.
- Разделение кэшей по ключам (ветка, lockfile, версия языка).
- Жёсткий TTL и готовность терять кэш без расследований.
2) Если shared storage нужен — изолируйте записи
Самый частый источник проблем с locks и консистентностью — несколько job’ов, которые пишут в один каталог. Самое эффективное «ускорение» — снизить конфликтность.
- Делайте кэш read-mostly и обновляйте его отдельной задачей.
- Пишите в уникальные пути по ключу сборки и «публикуйте» через атомарный
rename(). - Избегайте общей записи в один и тот же lock-файл на shared storage, если можно заменить на локальную синхронизацию.
3) План на деградацию важнее «идеальной» скорости
Для CI критично иметь «режим выживания»: что делаем, если shared storage деградировал. Хорошая практика — уметь быстро отключать сетевой кэш и продолжать сборки с локальными директориями.
- Фичефлаг в пайплайне: «не использовать сетевой кэш».
- Быстрая очистка кэша без попыток «сохранить любой ценой».
- Явное разделение: кэш можно потерять, релизные артефакты — обычно нет.
4) Мини-набор проверок, чтобы поймать проблемы раньше релиза
Сделайте пару простых smoke-проверок, которые выявляют проблемы с метаданными и атомарностью прямо в окружении раннеров (не на «голом» тестовом стенде).
mkdir -p /mnt/cache/ci-smoke
rm -rf /mnt/cache/ci-smoke/*
seq 1 5000 | xargs -I{} sh -c 'echo {} > /mnt/cache/ci-smoke/f-{}'
find /mnt/cache/ci-smoke -type f | wc -l
sh -c 'echo ok > /mnt/cache/ci-smoke/tmp && mv /mnt/cache/ci-smoke/tmp /mnt/cache/ci-smoke/commit'
flock -w 5 /mnt/cache/ci-smoke/lockfile -c 'echo locked'
Если такие проверки периодически «подвисают», дают I/O ошибки или сильно флуктуируют по времени на одном и том же объёме — shared storage, скорее всего, уже стал источником нестабильности CI.
Рекомендации выбора: что брать именно для CI
- Начать с NFS, если вы ещё не уверены в профиле нагрузки и хотите быстро получить рабочее решение с понятной диагностикой.
- Перейти на CephFS, если NFS упёрся в масштабирование и вам нужна кластерная отказоустойчивость, а команда готова обслуживать Ceph.
- Рассматривать GlusterFS, если вам нужен распределённый FS без полного Ceph, но вы готовы закладывать время на сценарии split brain и процедуры healing.
В 2026 лучший shared storage для CI — тот, который вы можете быстро объяснить, быстро починить и без сожаления отключить, когда он мешает релизу.
Мини-чеклист перед внедрением
- Опишите, что именно храните: кэш зависимостей, workspace, артефакты или всё вместе.
- Оцените долю small files и количество операций с метаданными.
- Проверьте требования инструментов к locks: где нужен
flock, гдеO_EXCL, где достаточно lock-файла. - Заранее решите, что делать при деградации: выключаем кэш, чистим, переключаемся.
- Определите допустимую неконсистентность: кэш можно потерять, релизные артефакты — обычно нет.
Финальные выводы
В споре GlusterFS vs CephFS vs NFS для CI нет «вечного победителя»: это выбор между простотой, распределённостью и эксплуатационной ценой отказоустойчивости. NFS остаётся самым практичным стартом для shared storage, CephFS выигрывает в крупных инсталляциях с требованиями к масштабированию и HA, а GlusterFS может быть компромиссом, который нужно брать осознанно — с пониманием split brain, healing и того, как они ударят по стабильности пайплайнов.
Если shared storage вы используете ещё и для веб-проектов (например, общие файлы или сессии), заранее проверьте поведение приложения на сетевой ФС: типичный пример — сборка мусора сессий и блокировки. По теме полезна отдельная статья: PHP-сессии на NFS и GC: где появляются подвисания.


