8(800) 222 32 56
Панель управления
vLLM

LMCache MP для vLLM: node-local KV-кеш без сюрпризов в production

LMCache MP для vLLM: node-local KV-кеш без сюрпризов в production
Подберите идеальное решение для ваших задач:
в России, США и Нидерландах обеспечат максимальную скорость. Воспользуйтесь всеми преимуществами надежного оборудования. Базовая помощь и техническое обслуживание входят в пакет услуг.
TTFT растёт именно на повторяемых длинных промптах, хотя GPU загружен не полностью, а перезапуск vLLM каждый раз обнуляет прогрев. В такой ситуации внешний KV-кеш может снять повторный prefill, но легко превратиться в ещё один источник memory pressure и скрытых зависимостей. Разберём LMCache MP как node-local сервис: где он полезен, как разделить infrastructure и application gates, какие метрики смотреть и как откатиться без простоя. Все unstable и evolving части помечаем прямо в runbook.

Готовы перейти на современную серверную инфраструктуру?

В King Servers мы предлагаем серверы как на AMD EPYC, так и на Intel Xeon, с гибкими конфигурациями под любые задачи — от виртуализации и веб-хостинга до S3-хранилищ и кластеров хранения данных.

  • S3-совместимое хранилище для резервных копий
  • Панель управления, API, масштабируемость
  • Поддержку 24/7 и помощь в выборе конфигурации

Создайте аккаунт

Быстрая регистрация для доступа к инфраструктуре

Где заканчивается prefix caching и начинается LMCache

У vLLM уже есть GPU prefix caching, и это важно проговорить до установки ещё одного сервиса. Встроенный кеш сохраняет блоки KV на ускорителе и хорошо работает, пока нужный префикс остаётся в ограниченном бюджете HBM конкретного engine. Проблема начинается, когда длинные системные промпты, RAG-контекст и несколько tenants вытесняют друг друга, а перезапуск worker обнуляет локальное состояние.

LMCache добавляет внешний уровень для KV-объектов. В рекомендуемом multiprocess-режиме отдельный процесс принимает и отдаёт кеш нескольким engine instances на одном узле. Это не «ускоритель для любого запроса»: выигрыш появляется только при повторяемых префиксах, а чтение из RAM всё равно медленнее попадания в GPU cache. Поэтому сначала ответьте на вопрос: повторяется ли у вас большой начальный контекст достаточно часто, чтобы его повторное вычисление было дороже переноса?

Типичный кейс — корпоративный помощник, где инструкция и набор документов одинаковы для сотен диалогов, а пользовательская часть короткая. В таком профиле холодный запрос строит KV, последующие могут взять совпавший непрерывный префикс. Для случайных одноразовых prompts кеш будет только занимать память. Общую картину throughput, TTFT и goodput полезно сверить с материалом про AI Factory: оптимизировать надо пользовательский SLO, а не красивый hit rate.

Путь KV-кеша от GPU через RAM к локальному хранилищу LMCache

Почему MP-режим стоит отделить от vLLM

Официальный quickstart LMCache на дату запуска называет MP mode рекомендуемым: кеш работает как standalone service, открывает management и observability endpoints и может обслуживать несколько vLLM engines. In-process режим в документации уже помечен deprecated. Это сильный архитектурный сигнал, но не обещание полной стабильности интерфейсов.

Разделение процессов даёт понятную границу отказа. vLLM можно перезапустить после обновления модели или CUDA-библиотек, не смешивая жизненный цикл engine с жизненным циклом node-local кеша. С другой стороны, появляется ZMQ endpoint, HTTP endpoint, shared memory и отдельный бюджет RAM. Если сервис LMCache жив, а connector в vLLM настроен на другой port, модель продолжит отвечать без полезного кеша или не пройдёт application gate — это уже наблюдаемая инфраструктурная ошибка, а не загадочная деградация GPU.

Схема для одного dedicated server проста: LMCache слушает ZMQ на 5555 для connector и HTTP на 8080 для health/metrics, а один или несколько vLLM workers подключаются через LMCacheMPConnector. Не выставляйте эти ports в публичную сеть. Оставьте их на loopback либо в закрытом management VLAN и фильтруйте доступ. Для нескольких GPU workers проверьте, что они действительно используют один cache service, а не случайно запускают по копии с разными namespaces.

Повторное использование префикса запроса из KV-кеша

Статус функций: что считать production-ready, а что проверять в стенде

У LMCache быстро меняются connector snapshots, container images и режимы transfer. В MP quickstart для контейнерного сценария прямо рекомендованы nightly images и сказано, что MP interfaces actively evolving. Значит, тег latest-nightly годится для лаборатории, но не для незаметного обновления production. Зафиксируйте проверенный image digest, версии vLLM, LMCache, драйвера и CUDA в одном release manifest.

Не переносите команды из старого in-process примера в новый MP deployment по памяти. Например, локальный disk backend всё ещё описан на странице старого режима с LMCACHE_USE_EXPERIMENTAL; это отдельная ветка риска. Для первого rollout разумнее оставить L1 в RAM, доказать reuse и только затем оценивать L2. NVMe полезен, когда working set больше RAM и префиксы реально возвращаются до eviction; общий фон про накопители есть в статье про NVMe и распределённое хранение.

Проверяли ли вы совместимость после каждого изменения только по тому, что процесс стартует? Этого мало. Нужен положительный тест повторного запроса и отрицательный тест несовпадающего префикса. Первый должен дать LMCache hit, второй — честный miss без ошибки ответа. Так вы докажете не только доступность connector, но и границу его действия.

Node-local архитектура LMCache MP и нескольких vLLM workers

Resource budget: HBM, RAM, shared memory и CPU

Кеш нельзя настраивать остаточным принципом. Сначала зафиксируйте HBM для weights, activations и внутреннего KV vLLM; затем выделите отдельный потолок RAM для LMCache L1; после этого оставьте запас ОС, page cache, network buffers и sidecars. Если LMCache забирает память, которой нет, kernel OOM killer может выбрать вовсе не cache service, а vLLM worker или exporter.

В MP quickstart демонстрационный --l1-size-gb задаётся явно. Не копируйте число из примера: начните с небольшого лимита, соберите hit rate, eviction и retrieval latency, затем увеличивайте только при подтверждённом reuse. Хороший бюджет отвечает на три вопроса: сколько гигабайт разрешено кешу; при каком memory pressure rollout останавливается; какой процесс первым ограничивает systemd или cgroup.

Отдельно проверьте /dev/shm. Для контейнерного CUDA IPC документация требует общий IPC namespace; слишком маленький tmpfs проявится не как «мало RAM», а как ошибка регистрации или transfer. Infrastructure gate должен проверить mount, права и ёмкость. Application gate — что повторный запрос действительно получает совпавший префикс. И обязательно отрицательная граница: другой tenant или другая cache salt не должны читать чужое состояние.

  • HBM: не уменьшайте запас vLLM ради кеша без замера tail latency.
  • RAM: лимит LMCache плюс резерв ОС и pinned memory.
  • Shared memory: отдельная проверка размера и namespace.
  • CPU: следите, не упираются ли transfer workers в один NUMA node.
Бюджет GPU, RAM и NVMe для многоуровневого KV-кеша

Runbook для одного выделенного GPU-сервера

Начинайте с loopback и одного vLLM engine. Так проще отделить connector от сети и Kubernetes. Установку выполняйте в отдельном virtual environment и фиксируйте lock-файл. Команда ниже повторяет структуру официального quickstart, но использует production chunk size по умолчанию 256, а не демонстрационные 16.

bashstart-lmcache.sh
uv venv --python 3.12
source .venv/bin/activate
uv pip install lmcache vllm

lmcache server \
  --host localhost \
  --port 5555 \
  --http-host 127.0.0.1 \
  --http-port 8080 \
  --l1-size-gb 20 \
  --eviction-policy LRU

До запуска модели проверьте HTTP health endpoint. Только после этого стартуйте vLLM и явно передайте адрес connector. Не добавляйте незнакомые flags из issue или nightly PR без сверки с вашей версией. Базовая форма вызова подтверждена текущей официальной документацией:

bashstart-vllm.sh
vllm serve Qwen/Qwen3-8B \
  --port 8000 \
  --kv-transfer-config \
  '{"kv_connector":"LMCacheMPConnector","kv_role":"kv_both","kv_connector_extra_config":{"lmcache.mp.host":"localhost","lmcache.mp.port":5555}}'

Если используете container runtime, не повторяйте механически --network host и --ipc host из quickstart: это удобно для smoke test, но расширяет область доверия. Сначала опишите, какие sockets и shared-memory объекты действительно нужны. Для production контейнеров рассмотрите isolated IPC только после проверки ограничений вашей связки: документация MP configuration предупреждает, что настройки server и workers должны совпадать, а часть интеграций ещё несовместима.

LMCache DaemonSet рядом с vLLM pods на GPU-узле Kubernetes

Application gate: доказать hit, miss и неизменность ответа

Готовый process и HTTP 200 — только infrastructure gate. Application gate должен пройти через OpenAI-compatible endpoint vLLM. Отправьте один длинный повторяемый префикс дважды, затем измените начало запроса. На втором одинаковом вызове ожидается retrieve в LMCache; на изменённом — miss либо меньшая длина совпавшего непрерывного prefix. Не сравнивайте только текст ответа: sampling может дать разные формулировки даже при корректном кеше.

bashsmoke-test.sh
curl -sS http://127.0.0.1:8080/healthcheck

curl -sS http://127.0.0.1:8000/v1/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"Qwen/Qwen3-8B","prompt":"\nQuestion A","max_tokens":32}'

curl -sS http://127.0.0.1:8000/v1/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"Qwen/Qwen3-8B","prompt":"\nQuestion B","max_tokens":32}'

Запишите timestamps, prompt token count, TTFT на клиенте и LMCache counters. Один быстрый ответ ничего не доказывает: возможно, префикс остался во внутреннем GPU cache vLLM. LMCache MP metrics намеренно не включают L0 GPU prefix cache, поэтому сопоставляйте источники. Для надёжного теста прогрейте, создайте контролируемое давление на GPU cache или перезапустите только vLLM engine, сохранив cache service.

Отрицательная проверка безопасности не менее важна. Используйте другой cache salt или изолированный tenant и убедитесь, что hit не пересекает границу. Если ваша версия не поддерживает требуемую изоляцию, не размещайте недоверенные workloads в одном cache namespace. Больше общих практик по защите моделей и данных — в материале о безопасности GPU-серверов.

Наблюдаемость LMCache: cache hit, latency и memory pressure

Kubernetes: DaemonSet рядом с vLLM, а не общий кеш на весь кластер

Официальный deployment guide описывает node-local pattern: один LMCache server в DaemonSet на GPU-узел и несколько vLLM pods в Deployment. Это разумная граница по latency и отказам. Pod должен подключаться к cache service на том же node, а scheduler — не переселять engine на другую машину, сохраняя старый адрес.

В текущем примере LMCache DaemonSet использует host networking, общий /dev/shm и не запрашивает GPU resource, чтобы ускорители оставались у vLLM pods. У этой простоты есть цена: шире network и IPC trust boundary. Закройте ports NetworkPolicy, используйте nodeSelector для GPU nodes и не допускайте DaemonSet на CPU-only узлы — документация предупреждает, что там возможны CUDA initialization errors.

bashdeploy-and-check.sh
kubectl create namespace multi-process
kubectl apply -f examples/multi_process/lmcache-daemonset.yaml
kubectl apply -f examples/multi_process/vllm-deployment.yaml

kubectl get pods -n multi-process -o wide
kubectl get daemonset -n multi-process
kubectl logs -n multi-process -l app=lmcache-server --tail=100

Не считайте sample manifests готовой security baseline. Зафиксируйте image digest, ресурсы, probes, Pod Security settings и rollout strategy. Во время canary проверьте: vLLM pod и LMCache pod находятся на одном node; readiness зависит от application gate, а не только от процесса; eviction cache pod не роняет inference; перезапуск vLLM не стирает node-local L1. Если кластер ещё только строится, начните с базового руководства по развёртыванию Kubernetes, а GPU-specific слой добавляйте отдельно.

Восстановление vLLM и LMCache с изоляцией неисправного узла

NUMA и топология: когда быстрый кеш становится удалённой памятью

На многосокетном dedicated server слово «локальный» ещё не означает близкий к GPU. GPU может быть подключён к PCIe root complex первого CPU, а LMCache process и его pinned buffers окажутся на NUMA node второго. Тогда каждый transfer пересекает inter-socket fabric, конкурирует с сетью и storage и добавляет вариативность. Проверять надо не только общий объём RAM, но и физическую близость CPU, GPU, NIC и memory.

Снимите топологию командами nvidia-smi topo -m, lscpu -e и numactl --hardware. Зафиксируйте CPU affinity vLLM workers и cache service в canary, но не прибивайте процессы к случайным cores. Сначала измерьте retrieve latency без binding, затем с согласованным NUMA placement. Если улучшение есть только на одном GPU, вероятно, проблема в topology, а не в размере cache.

Характерный случай: на четырёх GPU два ускорителя стабильно получают hit быстро, а у двух p99 заметно выше при одинаковом prompt. Увеличение --l1-size-gb здесь не помогает и даже усиливает pressure. Полезнее распределить workers по sockets, обеспечить локальную память и проверить IRQ affinity сетевой карты. Отрицательная проверка тоже нужна: неверное binding не должно приводить к падению, только к измеримой деградации, иначе rollback слишком хрупок.

Для контейнеров убедитесь, что CPU manager и topology manager Kubernetes не расходятся с ручными affinity settings. Не обещайте zero-copy как универсальное свойство: конкретный путь зависит от transfer mode, shared memory и версии connector. В отчёте canary храните topology map рядом с version manifest, иначе следующий аппаратный refresh сделает старые выводы непереносимыми.

Tenant isolation: кеш не должен стать каналом между клиентами

KV cache содержит производное от prompt состояние. Это не исходный текст в привычном формате, но относиться к нему как к безобидным временным байтам нельзя. Общий cache service расширяет область, где живут следы пользовательского контекста, а значит требует той же дисциплины, что embeddings, логи запросов и временные файлы.

Начните с модели доверия. Если все запросы принадлежат одному приложению и одной политике доступа, node-local shared cache проще. Если на GPU обслуживаются независимые клиенты, нужны отдельные cache salts, namespaces или физически раздельные services, подтверждённые вашей версией LMCache. Не полагайтесь на префикс «он всё равно не угадает»: side-channel через hit/miss и latency тоже может раскрывать факт наличия похожего контекста.

Application gate для изоляции строится как парный тест. Tenant A сохраняет известный длинный prefix; tenant B отправляет тот же prefix через свою identity. Ожидаемый результат — miss в чужом namespace и отсутствие retrieve bytes из cache A. Затем A повторяет запрос и получает hit. Этот отрицательный тест должен запускаться после update connector, смены cache policy и изменения routing.

Управляющие endpoints /status и /clear-cache держите в management plane. Они не должны быть доступны от inference clients или публичного ingress. Логи очищайте от prompt fragments и tokens, а права на cache directory и shared memory проверяйте отдельно. При инциденте безопасный порядок действий такой: остановить новые записи, изолировать node, очистить cache, проверить audit trail, затем вернуть узел через application gate. Не расширяйте доступ ради диагностики на живом multi-tenant трафике.

Метрики, которые показывают пользу, а не просто активность

Наблюдаемость должна ответить: сколько токенов реально найдено, сколько времени заняло retrieve и не вытесняет ли кеш полезный working set. В MP metrics reference есть token-level lookup counters, L1 usage, eviction loop, transfer latency и failure counters. Hit rate считайте как отношение hit tokens к requested tokens, а не как долю запросов: один короткий hit и один огромный miss не равноценны.

Смотрите на распределения. Средний TTFT может улучшиться, пока p99 ухудшается из-за медленного retrieve или очереди transfer workers. Сопоставляйте клиентский TTFT, vLLM queue time, GPU utilization, LMCache retrieve latency и memory pressure на node. Если hit rate высокий, но TTFT не меняется, проверьте размер совпавшего prefix, L0 GPU cache и стоимость копирования.

Практический dashboard можно строить четырьмя рядами: traffic и prompt tokens; lookup requested/hit; latency store/retrieve; capacity и eviction. Alert нужен не на сам miss, а на смену профиля: падение hit ratio при том же workload, рост retrieval latency, L1 allocation failures, непрерывные evictions или dropped events. Перед каждым release сохраните baseline за одинаковое окно и повторите application gate. Так «кеш включён» превращается в проверяемое утверждение.

Failure modes: как не лечить кеш расширением привилегий

Самая опасная реакция на ошибку CUDA IPC — добавить privileged, hostIPC и hostNetwork одновременно. Иногда после этого всё стартует, но причина теряется, а blast radius растёт. Разделяйте сбой по слоям. Infrastructure gate проверяет endpoint, shared memory, device visibility и version lock. Application gate проверяет store, retrieve, miss и isolation.

Если connector не регистрирует KV tensors, сверьте версии и transfer mode, затем размер и mount /dev/shm. Если health зелёный, но hits нулевые, проверьте непрерывность prefix, chunk alignment, cache salt и то, что запрос попал на тот же node-local service. Если hits есть, а latency хуже, ограничьте L1, уменьшите contention и временно отключите кеш для canary группы — не меняйте сразу пять параметров.

При OOM сначала остановите рост cache budget и подтвердите, кто потребляет память. Уменьшение vLLM GPU memory utilization не исправит host RAM pressure. При подозрении на stale cache очистка через management endpoint допустима как восстановление, но это потеря производительности, а не данных модели. Она должна быть редкой, журналируемой и недоступной внешнему клиенту.

  • Connector crash: vLLM rollback на конфигурацию без LMCache.
  • Cache service crash: рестарт только node-local сервиса, затем smoke test.
  • Version mismatch: возврат к закреплённой паре images.
  • Isolation doubt: отключение общего namespace до доказательства границы.

Canary rollout и критерии остановки

Вводите LMCache не как обязательную зависимость сразу для всего трафика, а как canary. Сначала один dedicated GPU server или один Kubernetes node, затем небольшой процент повторяемой нагрузки. Сравнивайте с контрольной группой без внешнего KV cache при одинаковой модели, sampling settings и traffic mix. Не публикуйте выводы по синтетическому prompt, если production prompts короче или почти не повторяются.

До старта определите stop conditions: рост error rate, ухудшение p95/p99 TTFT, host memory pressure, частые allocation failures, потеря tenant isolation или невозможность быстро отключить connector. Успех — это не максимальный hit rate, а улучшение целевого SLO без роста риска и стоимости узла. Иногда честный результат пилота — оставить только встроенный prefix cache vLLM.

Rollout checklist должен включать version manifest, resource limits, network policy, health и application probes, dashboard, rollback command и владельца on-call. После каждого изменения версии повторяйте три проверки: одинаковый prefix даёт hit; изменённый prefix даёт miss; другой tenant не видит чужой cache. Эта тройка ловит больше реальных ошибок, чем длинный список процессов со статусом running.

Итог: кешировать только доказанную повторяемость

LMCache MP полезен не потому, что добавляет ещё один слой к AI stack, а потому, что выносит повторно используемый KV cache за пределы конкретного vLLM engine и делает его node-local ресурсом с отдельным жизненным циклом. На выделенном GPU-сервере это помогает переживать restart engine и делить кеш между workers; в Kubernetes естественная форма — один DaemonSet instance на GPU node.

Начните с RAM L1, loopback, одного engine и измеримого application gate. Зафиксируйте версии, не переносите nightly в production без canary и не включайте disk или distributed backends, пока hit profile не доказан. Затем добавьте resource budget, observability, tenant boundary и rollback. Это скучнее обещания «ускорить LLM в разы», зато именно так инфраструктура остаётся управляемой.

Следующий практический шаг: возьмите один повторяемый production prompt, прогоните контроль без LMCache и canary с MP mode, а затем сравните TTFT, hit tokens, retrieval latency и memory pressure. Если тест показывает устойчивую пользу, переносите pattern на второй узел. Если нет — сохраните результаты и не платите RAM за кеш, который workload не использует. Для подбора выделенного GPU-сервера и сетевой схемы можно обратиться к команде KingServers с уже готовым профилем нагрузки.

Memory pressure в LLM-инференсе: cgroup v2, PSI и systemd-oomd
AI

Memory pressure в LLM-инференсе: cgroup v2, PSI и systemd-oomd

Практический runbook для защиты LLM-инференса от дефицита host RAM: PSI, cgroup v2, systemd-oomd, лимиты vLLM, алерты и аварийное восстановление.

NVIDIA CDI для rootless GPU-контейнеров: безопасный запуск LLM inference
AI

NVIDIA CDI для rootless GPU-контейнеров: безопасный запуск LLM inference

Практический runbook: NVIDIA Container Toolkit CDI, rootless Podman и Docker, выбор GPU/MIG, запуск vLLM, hardening, обновления и rollback.