Оглавление
- Как выглядит model-loading storm и почему GPU здесь ни при чём
- Что именно кэширует FS-Cache и где проходят его границы
- Baseline-архитектура: общий NFS, локальный NVMe и неизменяемые ревизии
- Как включить cachefilesd и смонтировать NFS с опцией fsc
- Прогрев без шторма: одна ревизия, один узел, ограниченная параллельность
- Infrastructure gate: доказать, что кэш действительно участвует в чтении
- Application gate: загрузить модель, проверить readiness и отрицательный сценарий
- Production hardening: rollout, capacity и защита общего хранилища
- Наблюдаемость и troubleshooting: cache miss, сеть или loader
- Отказ и rollback: вернуться к обычному NFS без потери модели
- Итоговый runbook: от canary до устойчивого inference-кластера
Готовы перейти на современную серверную инфраструктуру?
В King Servers мы предлагаем серверы как на AMD EPYC, так и на Intel Xeon, с гибкими конфигурациями под любые задачи — от виртуализации и веб-хостинга до S3-хранилищ и кластеров хранения данных.
- S3-совместимое хранилище для резервных копий
- Панель управления, API, масштабируемость
- Поддержку 24/7 и помощь в выборе конфигурации
Результат регистрации
...
Создайте аккаунт
Быстрая регистрация для доступа к инфраструктуре
Как выглядит model-loading storm и почему GPU здесь ни при чём
Типичная авария начинается после обновления модели: оркестратор одновременно перезапускает несколько inference-реплик. Все они читают одни и те же файлы весов с общего NFS-экспорта. Сетевой порт storage занят крупными чтениями, latency метаданных растёт, readiness растягивается, а дорогие GPU ждут данные вместо обработки запросов.
Важно не перепутать это с нехваткой вычислительной мощности. Если процесс долго находится на этапе загрузки checkpoint, CPU не насыщен, GPU memory ещё пуста, а на NFS-клиентах растёт read traffic, узкое место находится до ускорителя. Чем дружнее стартуют узлы, тем сильнее они усиливают проблему: каждый холодный клиент снова тянет одинаковые байты.
Сначала зафиксируйте baseline: время от старта процесса до readiness, сетевое чтение NFS, I/O клиентов и момент появления модели в GPU memory. Повторите одну pinned revision на одном узле, затем на двух и на группе. Если одиночный старт приемлем, а параллельный резко деградирует, вы видите конкуренцию за общий путь данных.
Материал сознательно не повторяет DRAFT про GPUDirect Storage: GDS оптимизирует локальный путь NVMe→GPU, а здесь задача — перестать повторно перевозить одинаковые веса по сети. Для общего контекста полезно руководство о распределённом ML-кластере.
Полезно разложить старт на фазы ещё до изменения инфраструктуры. Отдельно измерьте получение manifest, обход каталога, открытие shards, фактическое чтение bytes, десериализацию tensors и перенос данных в VRAM. Один общий startup timer скрывает картину: FS-Cache влияет на чтение, но не обязан ускорять JSON parsing, построение графа или CUDA initialization. Если после тёплого чтения сеть разгрузилась, а readiness почти не изменилась, проблема просто переехала на следующий слой.
Реалистичный пример: три узла перезапускаются после смены deployment, первый начинает читать сразу, второй и третий подключаются через несколько секунд. Storage видит три одинаковых потока, а каждый loader конкурирует за bandwidth. Ограничение rollout до одного cold reader не увеличивает скорость диска, зато возвращает предсказуемость. Именно эту гипотезу надо проверить до установки cachefilesd, иначе любое улучшение легко приписать не тому изменению.

Что именно кэширует FS-Cache и где проходят его границы
FS-Cache — подсистема Linux для прозрачного локального кэширования данных сетевых файловых систем. Для NFS она работает вместе с CacheFiles: прочитанные страницы сохраняются на локальной файловой системе, а повторное чтение может обслуживаться с локального диска. Документация ядра Linux описывает CacheFiles как backend поверх уже смонтированной локальной файловой системы; очисткой и давлением по свободному месту управляет cachefilesd.
Ключевое слово — «повторное». Первый cold start всё равно читает веса из NFS. FS-Cache не заменяет capacity planning сети, не ускоряет все metadata operations и не превращает NFS в автономное хранилище. Зато второй запуск той же неизменной ревизии на том же узле получает шанс читать большую часть весов с локального NVMe.
Кэш локален для каждого GPU-узла. Прогрев node-a не прогревает node-b. CacheFiles также ограничен одним backend на клиенте, поэтому его каталог и политика места обслуживают все NFS-монты с fsc. Это удобно для изоляции, но требует управляемого rollout.
FS-Cache уместен, когда веса читаются многократно, версии публикуются как immutable-каталоги, а локальный NVMe дешевле постоянного дублирования всей библиотеки. Если узел запускает модель один раз и живёт месяцами, сначала измерьте пользу.
Отделяйте FS-Cache от обычного Linux page cache. Повторный запуск вскоре после первого может быть быстрым только потому, что данные остались в RAM. Это хороший результат для приложения, но слабое доказательство disk cache. Для корректного эксперимента наблюдайте local NVMe I/O и counters FS-Cache, а не пытайтесь бездумно очищать page cache на production-узле. Контролируемый canary и перезагрузка между сериями безопаснее глобального drop_caches.
Есть и operational trade-off: локальный disk cache не знает, какая модель важнее бизнесу. При давлении по месту culling может удалить давно не читавшиеся объекты, и следующий restart снова станет холодным. Поэтому capacity связывайте с рабочим набором и расписанием rollout. Если на одном узле чередуются десятки моделей, явный application cache или local mirror может дать более управляемую eviction policy.

Baseline-архитектура: общий NFS, локальный NVMe и неизменяемые ревизии
Минимальная схема состоит из авторитетного model repository на NFS и локального NVMe на каждом inference-узле. Экспорт монтируется read-only с fsc. CacheFiles хранит объекты на отдельном разделе. Приложение читает обычный путь /srv/models и не знает о кэше.
Для весов важнее всего неизменяемость. Не заменяйте model.safetensors на месте. Публикуйте новую ревизию в новом каталоге, проверяйте checksum, затем переключайте deployment на новый путь. Похожий принцип использует кэш Hugging Face Hub: blobs адресуются содержимым, snapshots ссылаются на конкретные ревизии.
NFSv4.2 полезен как современный baseline, но сам не включает local disk cache. Согласно RFC 7862, возможности minor version 2 расширяют NFSv4.1, причём многие optional. Фиксируйте vers=4.2 после проверки клиента и сервера; иначе разрешите negotiation и запишите фактическую версию через nfsstat -m.
Отдельный NVMe упрощает контроль места и исключает конкуренцию с root filesystem. Размер планируйте от рабочего набора активных ревизий на узле, а не от полного каталога моделей. Оставьте резерв для culling и деградации.

Как включить cachefilesd и смонтировать NFS с опцией fsc
Имена пакетов зависят от дистрибутива: обычно нужны NFS client utilities и cachefilesd. Сначала проверьте поддержку FS-Cache и CacheFiles в ядре, локальный cache directory и доступ daemon к /dev/cachefiles. Настраивайте один canary, а не всю группу.
sudo apt-get update
sudo apt-get install -y nfs-common cachefilesd
sudo systemctl enable --now cachefilesd
systemctl --no-pager --full status cachefilesd
sudo mkdir -p /srv/models
sudo mount -t nfs -o ro,hard,_netdev,vers=4.2,fsc storage.example:/models /srv/models
findmnt -no SOURCE,FSTYPE,OPTIONS /srv/models
nfsstat -m
Опция fsc включается на NFS mount и по умолчанию выключена; это указано в nfs(5). Там же обратите внимание на hard: для model weights лучше не превращать сетевой timeout в неожиданный I/O error внутри loader. Soft semantics допустима лишь после осознанной оценки поведения приложения.
Не копируйте rsize, wsize, nconnect и timeouts из чужого benchmark. Клиент и сервер согласуют возможности, а оптимум зависит от NIC, сети, nfs-utils и storage backend. Сначала оставьте defaults, затем меняйте один параметр на воспроизводимом cold/warm тесте.
Путь CacheFiles задаётся политикой cachefilesd. Синтаксис сверяйте с пакетом ОС: kernel docs описывают механизм, но layout и unit-файлы поставляет дистрибутив. Cache directory не должен находиться на самом NFS mount.
Безопасность mount остаётся отдельной задачей. Read-only защищает model repository от случайной записи клиента, но не аутентифицирует узел и не шифрует трафик. Если ваша модель угроз требует проверки identity или confidentiality, рассмотрите Kerberos security flavors и сетевую сегментацию, подтверждая поддержку на сервере и клиентах. Не смешивайте переход на новый security flavor с первым cache benchmark: сначала получите рабочий защищённый NFS baseline, затем добавляйте fsc.
Конфигурацию храните как код. Зафиксируйте package versions, kernel release, mount options, cachefilesd policy, filesystem и NVMe device. Это превращает canary в воспроизводимый unit, а не в ручную настройку. Перед масштабированием сравните вывод findmnt и systemd unit между узлами: дрейф одного флага способен объяснить ситуацию, когда половина группы получает cache hits, а другая продолжает читать NFS.

Прогрев без шторма: одна ревизия, один узел, ограниченная параллельность
После включения FS-Cache первый запуск остаётся холодным. Прогрев должен быть отдельным этапом rollout, а не побочным эффектом одновременного старта всех pod или services. Выберите canary, закрепите точный путь ревизии и последовательно прочитайте файлы весов. Только затем запускайте loader и переводите узел в ready.
Простейший warm-up читает ожидаемые форматы и завершает работу при ошибке. Он не проверяет корректность модели, зато подготавливает data pages. Для Hugging Face Hub заранее скачивайте точную revision в HF_HUB_CACHE; переменные HF_HOME и HF_HUB_CACHE описаны в официальном справочнике.
#!/usr/bin/env bash
set -euo pipefail
MODEL_DIR="/srv/models/acme-llm/revisions/7f3c2d1"
test -d "$MODEL_DIR"
find "$MODEL_DIR" -type f \( -name '*.safetensors' -o -name '*.json' \) -print0 |
while IFS= read -r -d '' file; do
dd if="$file" of=/dev/null bs=8M status=none
done
echo "warm-up complete: $MODEL_DIR"
Не запускайте скрипт одновременно на всех узлах. Ограничьте concurrency rolling update, отдельной очередью прогрева или init job с lease. В Kubernetes используйте небольшую волну и readiness gate; на выделенных серверах — последовательность в Ansible или systemd ordering.
После warm-up запустите приложение тем же filesystem path. vLLM предоставляет download_dir и load_format в актуальном LoadConfig, но для уже смонтированной immutable-ревизии проще передать local path. Специальные loaders добавляйте после доказанного baseline.

Infrastructure gate: доказать, что кэш действительно участвует в чтении
Работающий daemon ещё не доказывает cache hit. Infrastructure gate подтверждает всю цепочку: CacheFiles активен, NFS смонтирован с fsc, локальный NVMe принимает I/O, а повторный read создаёт меньше сетевого чтения. Сравнивайте одинаковую pinned revision на одном узле.
На разных ядрах counters различаются. Если доступен /proc/fs/fscache/stats, снимите его до и после чтения. Одновременно используйте nfsiostat, nfsstat -m, iostat -xz и network counters. Уменьшение NFS bytes при наличии local NVMe reads — более сильное доказательство, чем один ускорившийся wall time.
set -euo pipefail
systemctl is-active --quiet cachefilesd
findmnt -no OPTIONS /srv/models | tr ',' '\n' | grep -qx fsc
test -r /srv/models/acme-llm/revisions/7f3c2d1/config.json
nfsstat -m
if test -r /proc/fs/fscache/stats; then
sed -n '1,80p' /proc/fs/fscache/stats
fi
iostat -xz 1 3
nfsiostat 1 3 /srv/models
Добавьте отрицательную проверку. Прочитайте файл из новой непрогретой ревизии: он должен обратиться к NFS. Затем повторите чтение прогретой ревизии и наблюдайте local path. Так вы доказываете locality, а не случайное затишье в сети или Linux page cache.

Application gate: загрузить модель, проверить readiness и отрицательный сценарий
После инфраструктуры проверяйте приложение отдельно. Loader должен открыть конкретную ревизию, закончить загрузку, выделить GPU resources и пройти readiness. Не считайте HTTP 200 от процесса достаточным: endpoint может отвечать до полной готовности модели. Выполните короткий inference-запрос и проверьте model id.
Положительный тест — два последовательных рестарта canary с одинаковой ревизией. Первый фиксирует cold path, второй — warm. Не публикуйте универсальный процент ускорения: он зависит от размера модели, RAM page cache, NVMe, сети и loader.
Отрицательный тест проверяет границу. Укажите несуществующую ревизию и убедитесь, что deployment остаётся not ready, а не подхватывает старый snapshot. Затем выберите новую непрогретую ревизию: она должна пройти cold path и не притвориться cache hit.
Если inference, training и batch делят ускорители, согласуйте прогрев с общей политикой. Статья про GPU scheduling поможет не превратить storage rollout в конфликт за GPU slots.

Production hardening: rollout, capacity и защита общего хранилища
Baseline становится production-системой после правил rollout. Разрешайте прогрев ограниченному числу узлов, не начинайте следующую волну до прохождения обоих gates и сохраняйте serving capacity. В Kubernetes настройте rolling update и PodDisruptionBudget так, чтобы cold-start группа не совпадала со всеми unavailable replicas. На bare metal используйте draining.
Capacity планируйте по трём ресурсам. Первый — сеть и read throughput NFS на холодной волне. Второй — endurance и latency локального NVMe, потому что cache fill и culling создают I/O. Третий — свободное место: cachefilesd должен удалять старые объекты до заполнения filesystem.
Разделяйте ownership. Platform team отвечает за NFS export, immutable publishing и checksums. Node team — за cachefilesd, NVMe health и mount. Application team — за pin revision, readiness и rollback. Иначе фраза «медленно грузится модель» не указывает слой.
Сопоставляйте storage SLO с inference. В материале про AI Factory описаны latency, throughput и goodput; здесь к ним добавляется startup readiness. Кэш нужен, чтобы deployment предсказуемо возвращал serving capacity.
Рассчитайте верхнюю границу холодной волны без выдуманного коэффициента. Возьмите фактический объём файлов, который открывает loader, измеренный cold-read одного узла и доступный запас storage/network в рабочее время. Затем выберите concurrency, при котором serving traffic и фоновые операции остаются в SLO. Это не постоянная величина: окно обслуживания, backup и training jobs могут менять допустимую волну.
Для нескольких зон или стоек избегайте единого синхронного старта после сетевого инцидента. Добавьте jitter и локальные rollout budgets. После восстановления NFS десятки узлов могут одновременно обнаружить доступность и создать более сильный шторм, чем плановый deploy. Очередь прогрева с lease, приоритетом production-моделей и ограничением на storage domain делает recovery управляемым.
Наблюдаемость и troubleshooting: cache miss, сеть или loader
Набор сигналов нужен сразу. На NFS-сервере собирайте read bytes/operations, latency и queue depth. На клиентах — mount info, RPC/retrans, network throughput, local NVMe latency/utilization, место cache filesystem и состояние cachefilesd. В приложении разделите startup: resolve revision, open files, load weights, allocate GPU, readiness.
Начинайте с вопроса: какие байты читаются и откуда? Если сеть нагружена только на новой ревизии, это ожидаемый miss. Если на каждом рестарте старой — проверяйте fsc, daemon и стабильность file handles. Если сеть спокойна, NVMe занят, но loader медленный, bottleneck сместился в CPU deserialization, RAM pressure или копирование в GPU.
Не отключайте attribute caching и не ставьте actimeo=0 без измерений. Это увеличивает metadata traffic. Для весов безопаснее immutable paths: новая версия получает новый каталог, старая остаётся для rollback. Coherency решается моделью публикации, а не агрессивными mount options.
При заполнении cache filesystem остановите rollout, проверьте culling policy и рабочий набор. Не удаляйте внутреннюю структуру CacheFiles вручную при работающем daemon. Для аварийной очистки drain приложения, остановите cachefilesd, следуйте процедуре пакета ОС и повторите infrastructure gate.
События cachefilesd и kernel logs должны попадать в централизованный журнал с идентификатором узла. Алёрт нужен не на каждую miss: новая ревизия обязана промахнуться. Полезнее ловить daemon inactive, быстрое падение свободного места, повторяющиеся I/O errors, рост NFS retrans и ситуацию, когда старая pinned revision после нескольких запусков всё ещё генерирует полный remote read.
В postmortem сохраняйте revision, список реально открытых файлов, mount options и фазовые timings. Без revision сравнение cold и warm бессмысленно: deployment мог незаметно скачать другой snapshot. Без списка файлов можно прогреть safetensors, тогда как loader дополнительно читает tokenizer, quantization config или adapter. Наблюдаемость должна подтверждать фактический workload, а не ожидаемый layout каталога.
Отказ и rollback: вернуться к обычному NFS без потери модели
FS-Cache должен оставаться ускорителем. Если cachefilesd неисправен, сохраните serving replicas, остановите прогрев и drain узел. Затем остановите приложение, размонтируйте NFS и смонтируйте без fsc с теми же security и recovery options. После application gate узел может вернуться в пул на обычном NFS.
Не делайте remount на лету для изменения NFS-specific options: nfs(5) предупреждает, что многие нельзя корректно изменить remount-операцией. Полный unmount/mount после drain лучше отражает состояние. Если mount занят, найдите процессы через fuser или lsof.
Rollback модели независим от rollback кэша. Deployment возвращается на предыдущий immutable path, пока обе ревизии доступны на NFS. Локальный кэш старой версии может ускорить возврат, но это бонус. Проверяйте checksum и model identity так же строго, как при forward rollout.
Если нужен inference при полном отказе NFS, FS-Cache недостаточен: используйте local mirror, artifact distribution или object storage с application cache. Материал про LLMOps поможет встроить это в versioning и rollback.
Проведите game day до первого массового rollout. На canary остановите cachefilesd, подтвердите видимый failure mode, drain приложение, верните mount без fsc и выполните короткий inference test. Затем восстановите cache backend и повторите прогрев. Упражнение проверяет runbook, права, systemd ordering и то, что команда не зависит от памяти одного инженера. Оно также показывает реальное время восстановления, не превращая его в обещание для всех сред.
Итоговый runbook: от canary до устойчивого inference-кластера
Внедрение начинается с доказанного симптома. Снимите cold/warm baseline на pinned revision, отделите NFS bottleneck от CPU/GPU loading, затем включите fsc на canary. Прогрейте модель последовательно и пропустите узел через Infrastructure gate и Application gate.
Расширяйте rollout небольшими волнами. Каждый узел имеет свой локальный кэш и обязан пройти cold fill; чужой SUCCESS не заменяет его проверку. Ограничение concurrency защищает storage, immutable revisions делают поведение воспроизводимым.
Главный вывод: FS-Cache уменьшает повторную перевозку одинаковых весов, но не отменяет первый read, NFS availability и дисциплину версий. Наблюдайте сеть, local NVMe и application phases вместе. Тогда cache hit становится проверяемым механизмом.
Следующий шаг — выбрать GPU-узел, закрепить ревизию, дважды измерить загрузку без изменений и сохранить baseline. Если второй запуск повторяет полный network read, у вас ясная задача для canary. Если кэш работает, переходите к rollout и заранее репетируйте rollback без fsc.