Корпоративный SSD на 7,68 ТБ стоит как небольшой сервер, и отдавать его целиком одной задаче расточительно. В NVMe для таких случаев придумали неймспейсы: физический носитель нарезается на логические устройства, каждое получает собственный номер NSID и подключается к контроллерам без перезагрузки. У технологии есть и вторая, менее известная сторона. Один и тот же неймспейс можно показать сразу нескольким хостам, превратив одиночный диск в общее хранилище для группы серверов. Ниже разобраны команды nvme-cli, которые отвечают за каждый шаг, и ловушки, о которых легко споткнуться.
Одна оговорка про версии. В nvme-cli 3.0 команды переоформили в иерархию, свежая 3.2, вышедшая в конце октября 2026 года, продолжает эту линию, а старые имена работают с предупреждением, поэтому примеры даются в обоих написаниях.
Из чего состоит NVMe подсистема и где в ней живут неймспейсы
Подсистема NVM это весь SSD или программный экспортёр. Внутри неё живут контроллеры, а у контроллеров неймспейсы, независимые адресные пространства логических блоков LBA. Каждому неймспейсу назначается номер NSID, а размеры описывают три поля: nsze показывает полный размер, ncap выделенную ёмкость, nuse реально занятый объём. В Linux контроллер выглядит как символьное устройство /dev/nvme0, а неймспейс как блочное /dev/nvme0n1.
Стандарт двигал эту механику по частям. Multi-path I/O с возможностью разделять неймспейсы между контроллерами появился ещё в спецификации 1.1 от 11 октября 2012 года, полноценное управление неймспейсами на лету стандартизировали в редакции 1.2.1 в июне 2016 года, а в версии 1.3 мая 2017 года добавили дескрипторы идентификации с UUID и NGUID. Актуальная редакция 2.4 от 4 августа 2026 года продолжает эту машинерию.
Неймспейс это сам том, контроллер это дверь к нему, а подсистема дом. Несколько дверей открываются в одну комнату, если при создании тома выставлен флаг совместного использования. За него отвечает поле NMIC в структуре Identify Namespace, где нулевой бит разрешает разделять неймспейс между контроллерами подсистемы.
Проверить, сколько дверей вообще есть, можно парой команд:
nvme id-ctrl /dev/nvme0 | grep -w nn
cat /sys/class/nvme/nvme0/cntlid
Поле nn задаёт максимум одновременно активных неймспейсов подсистемы: если вернулось 16, то семнадцатый том создать не выйдет, сколько места ни оставалось. Атрибут cntlid из ядра 4.6 покажет идентификатор контроллера, он понадобится для подключения. Рядом в /sys/class/nvme/nvme0/ лежат model, serial и firmware_rev, transport возвращает pcie, tcp, rdma или fc, а state отвечает за состояние: live, resetting или dead.
Ограничение железа тоже стоит помнить. Команды управления неймспейсами опциональны: если прошивка их не поддерживает, create-ns вернёт ошибку Invalid Command Opcode, зато корпоративные модели и программная цель nvmet в ядре Linux умеют их из коробки.
Создание и удаление неймспейсов командами create-ns и delete-ns
Создание делается одной командой к символьному устройству контроллера:
nvme create-ns /dev/nvme0 --nsze 11995709440 --ncap 1199570940 --flbas 0 --dps 0 --nmic 1
Числа здесь не случайны: nsze это размер в логических блоках, и 11995709440 блоков по 512 байт дают 6,14 ТБ, а опция --nsze-si принимает тот же объём в записи 6.14T. ncap в десять раз меньше nsze, что включает тонкое выделение: ёмкость расходуется по мере записи, а не сразу. flbas выбирает формат блока из списка, который вернул nvme id-ns, dps описывает сквозную защиту данных, а nmic 1 как раз и помечает неймспейс как разделяемый.
В ответ контроллер присваивает свободный номер, например NSID 5, и дальше все операции ведутся по нему.
В nvme-cli 3.0 те же действия выглядят компактнее:
nvme ns create /dev/nvme0 --nsze-si 6.14T --ncap-si 6T --block-size 4096 --nmic 1
Опция --block-size сама подбирает подходящий формат блока. Скрипты под ветку 2.x продолжат работать на алиасах create-ns, attach-ns, detach-ns, delete-ns, id-ns и ns-descs, но у новых имён будущее надёжнее.
Удаление выглядит зеркально, и номер в нём обязателен:
nvme delete-ns /dev/nvme0 --namespace-id=5
Номер 0xffffffff, он же all или -1, означает "все неймспейсы сразу", и такая команда стирает разметку подсистемы целиком. Контроллер откажется удалять том, пока тот подключён хотя бы к одному контроллеру, поэтому порядок одинаковый: сначала detach, потом delete.
Подключение и отключение неймспейсов через attach-ns и detach-ns без перезагрузки
Новый неймспейс сначала никто не видит: он существует, но не подключён ни к одному контроллеру. Подключение выполняет команда attach, причём устройством должен быть именно контроллер:
nvme attach-ns /dev/nvme0 --namespace-id=5 --controllers=0
nvme ns attach /dev/nvme1 -n 0x2 -c 0x21,0x22
Вторая строка показывает виртуализированную подсистему: неймспейс 0x2 подключается сразу к контроллерам 0x21 и 0x22. Идентификаторы берутся из /sys/class/nvme/nvmeX/cntlid или из вывода nvme list-subsys, а без списка -c подключение идёт к контроллеру устройства, с которым работали.
Обратное действие отвязывает том от конкретных контроллеров:
nvme detach-ns /dev/nvme0 --namespace-id=5 --controllers=0
После отсоединения блочное устройство /dev/nvme0n5 исчезает из системы, а после подключения появляется. Обычно ядро замечает изменение само, но его можно поторопить:
nvme ns-rescan /dev/nvme0
echo 1 > /sys/class/nvme/nvme0/rescan_controller
Атрибут rescan_controller появился в ядре 4.7 и работает только на запись: любое значение запускает повторный опрос неймспейсов, и всё происходит вживую на смонтированной системе.
Совместный доступ нескольких хостов к одному неймспейсу по сети
Настоящее разделение начинается, когда подсистему экспортируют по сети через NVMe over Fabrics: каждый хост получает собственный контроллер, и расшаренный неймспейс виден всем. В Linux роль сервера хранения берёт подсистема nvmet, настроенная через configfs: каталог подсистемы с именем вроде nqn.2018-09.com.example:pool0, внутри namespaces/1 с устройством на backend. Атрибут attr_allow_any_host в значении 1 допускает любого клиента, а каталог allowed_hosts ограничивает подключения конкретными NQN.
Клиентская сторона лаконична:
nvme discover -t tcp -a 10.0.0.10 -s 4420
nvme connect -t tcp -a 10.0.0.10 -s 4420 -n nqn.2018-09.com.example:pool0
Порт 4420 стал стандартом де-факто для NVMe-oF, поэтому в команде его можно и не указывать. Подключение создаёт на хосте контроллер, скажем nvme2, и расшаренный том появляется как /dev/nvme2n1. Полная последовательность настройки одного общего тома выглядит так:
- на сервере хранения создать неймспейс через nvme create-ns с параметром --nmic 1 и зафиксировать возвращённый NSID;
- подключить его командой nvme attach-ns к контроллерам из списка --controllers;
- в configfs nvmet создать подсистему с NQN, добавить неймспейс с device_path и выставить attr_allow_any_host либо перечислить хосты в allowed_hosts;
- объявить транспортный порт с типом tcp, сетевым адресом и номером 4420;
- на каждом клиенте выполнить nvme discover, затем nvme connect с адресом, портом и NQN подсистемы;
- для согласованного доступа к записи настроить NVMe-резервирования или кластерную файловую систему.
С версии 3.2 в комплект nvme-cli входит фоновый процесс nvme-discoverd: он держит связь с discovery-контроллером и сам подтягивает изменения с цели, заменяя старые юниты автоподключения.
Остался главный вопрос этой части. Что будет, если два хоста начнут писать в один неймспейс одновременно? Обычные файловые системы о соседях не знают, и метаданные превращаются в кашу. Ответ унесён в финальный раздел, а пока о проверке.
Проверка состояния неймспейсов командами id-ns, ns-descs и list-subsys
Диагностика начинается с запроса Identify Namespace:
nvme id-ns /dev/nvme0n1
nvme id ns /dev/nvme0 -n 1
В выводе важны nsze, ncap и nuse, а поле nmic покажет, помечен ли том как разделяемый. Опция --force показывает даже неподключённый неймспейс, но работает только на контроллерах 1.2 и новее, а значение 0xffffffff вместо номера возвращает типовые возможности по всем томам.
Дескрипторы идентификации выдаёт nvme ns-descs:
nvme ns-descs /dev/nvme0n1
В ответ прилетают UUID, NGUID и EUI64, стабильные идентификаторы, которые не меняются при пересоздании тома: по ним кластерные инструменты узнают диск даже после смены NSID. Те же значения лежат в sysfs: /sys/block/nvme0n1/uuid, рядом nsid и wwid.
Картину всех дисков показывает nvme list, а связи складывает nvme list-subsys:
nvme-subsys0 - NQN=nvmf-test
+- nvme0 rdma traddr=1.1.1.3,trsvcid=4420,host_traddr=1.1.1.1
+- nvme1 rdma traddr=1.1.1.3,trsvcid=4420,host_traddr=1.1.1.2
Два контроллера с разными исходными адресами означают два хоста на одной цели, а для скриптов есть режим -o json. Состояние контроллера читается из /sys/class/nvme/nvme0/state: live, resetting или dead, transport и subsysnqn говорят о способе связи, hostnqn появился в ядре 5.7. В многопутевых конфигурациях путь описывает /sys/block/nvme0c0n1/ana_state со значениями optimized, non-optimized, inaccessible и persistent-loss, а политика выбора пути живёт в /sys/class/nvme-subsystem/nvme-subsys0/iopolicy со значениями numa, round-robin и queue-depth.
Форматирование и безопасное стирание командой nvme format
Новый неймспейс перед использованием форматируют, и NVMe делает это аппаратно:
nvme format /dev/nvme0n1 --lbaf=0
nvme format /dev/nvme0 --namespace-id=1 --ses=1
lbaf выбирает формат логического блока, а --block-size 4096 переведёт том на четырёхкилобайтный сектор, что часто поднимает производительность. Ключевой параметр ses управляет глубиной стирания: 1 стирает пользовательские данные, 2 выполняет криптографическое стирание, уничтожая ключ шифрования, и заканчивается за секунды даже на больших объёмах, поэтому его выбирают при передаче тома другой команде.
После успешной команды nvme-cli сам перечитывает таблицу разделов через BLKRRPART, поэтому размер блока обновляется сразу. Опция --reset дополнительно сбрасывает контроллер и требует символьного устройства.
Здесь прячутся две ловушки с нумерацией. Первая: суффикс 0 в /dev/nvme0 не гарантирует, что /dev/nvme0n1 принадлежит контроллеру nvme0, и форматирование не того устройства стирает данные безвозвратно, поэтому перед командой смотрят model и serial в /sys/class/nvme/nvme0/. Вторая: у части контроллеров бит FNA запрещает форматировать неймспейсы по одному, и запрос к символьному устройству стирает сразу все тома подсистемы.
Резервирования и типичные ошибки при работе с общими неймспейсами
Ответ на вопрос об одновременной записи дают NVMe-резервирования, механизм координации на уровне контроллера. Каждый участник регистрируется через nvme resv-register, том захватывается nvme resv-acquire, состояние показывает nvme resv-report, освобождение выполняет nvme resv-release. Тип Write Exclusive с числом 1 означает, что писать может владелец, остальные только читают; Exclusive Access с числом 2 оставляет весь доступ владельцу. В цели nvmet поддержку резервирований включает флаг resv_enable, появившийся в ядре 6.13.
Альтернатива это кластерная файловая система вроде OCFS2 или GFS2, которая сама согласовывает записи через блокировки: резервирования дешевле, кластерная ФС даёт настоящий одновременный доступ. На цели есть и настройка ANA: идентификатор ana_grpid у неймспейса принимает значения от 1 до 128 и сообщает клиентам, какой путь сейчас оптимальный.
Осталось собрать грабли. Invalid Command Opcode означает не поломку, а отсутствие функции в прошивке. Лимит nn не даст создать том сверх разрешённого числа. Номер 0xffffffff в delete-ns стирает всё, что подключено, и дважды перечитать команду перед Enter не зазорно. Наконец, расшаренный том без резервирований или кластерной ФС рушит данные так же надёжно, как и неразделённый, поэтому шестой пункт списка пропускают только любители сюрпризов.
Занятно, что механизм, придуманный в 2012 году для крупных хранилищ, теперь доступен на любом дистрибутиве. И спецификация продолжает двигаться: в редакции 2.1 описана живая миграция, а свежая 2.4 научилась переносить PCIe-подсистемы между хостами. Похоже, перестановка общего тома между серверами станет такой же рутиной, какой сегодня выглядит обычное подключение неймспейса.