Originally published on the HostingPodium Enterprise Engineering Blog.
Free SRE & Developer Diagnostics: Test your stack live with our DMARC Record Checker, Generator & SPF/DKIM Validator, Free Website Speed & Core Web Vitals Checker, or explore all 9 Free Webmaster & Cloud Engineering Tools.
This guide details how to deploy Linux NVMe-oF over TCP and RDMA in a private-cloud environment, covering target configuration, initiator multipathing, performance tuning, and operational runbooks.
Introduction
Private-cloud operators increasingly separate compute from persistent block storage to achieve elasticity and to reuse flash arrays across tenants. Linux NVMe-over-Fabrics (NVMe-oF) delivers sub-millisecond latency when the transport is tuned for the underlying network. This guide explains how to build a production-grade NVMe-oF fabric using both TCP and RDMA, how to configure the nvmet target with nvmetcli, and how to integrate the fabric with multipath-aware initiators.
Core Components
NVMe-oF target kernel –
nvmetmodule, compiled into the kernel (RHEL 9 / AlmaLinux 9 default).Target management –
nvmetcliJSON interface for persistent configuration.Initiator utilities –
nvme-cli(v2.5+),multipathd(device-mapper multipath).Transport stack – TCP (standard Linux socket) and RDMA (RoCEv2 or iWARP) drivers.
Observability stack –
collectd+ Prometheus exporter,nvme-clihealth commands.
Target Configuration with nvmetcli
The target definition lives in /etc/nvmet/config.json. The JSON format is stable across kernel releases, which makes it suitable for GitOps pipelines.
{ "ports": [ { "addr": { "traddr": "10.0.1.10", "trsvcid": "4420", "adrfam": "ipv4", "trtype": "tcp" }, "referrals": [] }, { "addr": { "traddr": "10.0.1.10", "trsvcid": "4420", "adrfam": "ipv4", "trtype": "rdma", "traddr_family": "ipv4", "traddr": "10.0.1.10", "trsvcid": "4420", "subsysnqn": "nqn.2024-11.com.hostingpodium:storage" } } ], "subsystems": [ { "nqn": "nqn.2024-11.com.hostingpodium:storage", "serial": "HPOD-001", "model": "NVMe-OF-Target", "allow_any_host": false, "hosts": [ {"nqn": "nqn.2024-11.com.hostingpodium:host01"}, {"nqn": "nqn.2024-11.com.hostingpodium:host02"} ], "namespaces": [ { "nsid": 1, "device_path": "/dev/nvme0n1", "host_ns": 1, "enable": true } ] } ] } After editing, apply the configuration with:
# nvmetcli restore Persist the JSON file in /etc/nvmet/config.json and enable the service:
# systemctl enable --now nvmet.target Initiator Provisioning
On each compute node install the same nvme-cli version and enable the kernel module:
# modprobe nvme-tcp # modprobe nvme-fabrics Discover the subsystem:
# nvme discover -t tcp -a 10.0.1.10 -s 4420 # nvme discover -t rdma -a 10.0.1.10 -s 4420 Connect using a persistent host NQN that matches the target ACL:
# nvme connect -t tcp -n "nqn.2024-11.com.hostingpodium:storage" -a 10.0.1.10 -s 4420 # nvme connect -t rdma -n "nqn.2024-11.com.hostingpodium:storage" -a 10.0.1.10 -s 4420 Multipath Integration
NVMe devices appear as /dev/nvmeXnY. To expose them as a single block device for the OS, configure multipath.conf:
defaults { user_friendly_names yes find_multipaths yes } blacklist { devnode "^nvme" } multipaths { multipath { wwid 0x123456789abcdef0 alias storage01 path_selector "round-robin 0" path_grouping_policy multibus failover "failover" rr_min_io 8 } } Reload the daemon and verify the map:
# systemctl restart multipathd # multipath -ll Kernel and Network Tuning
Sub-millisecond latency requires low interrupt latency, high queue depth, and tuned TCP buffers. Table 1 lists the recommended sysctl values for a 100 GbE fabric.
| Parameter | Recommended Value | Rationale |
|---|---|---|
| net.core.rmem_max | 12582912 | Large receive buffers for TCP-NVMe streams |
| net.core.wmem_max | 12582912 | Symmetric transmit buffers |
| net.ipv4.tcp_rmem | 4096 87380 12582912 | Auto-scale receive window |
| net.ipv4.tcp_wmem | 4096 65536 12582912 | Prevent head-of-line blocking |
| net.core.somaxconn | 4096 | Accommodate many concurrent connections per target |
| vm.nr_hugepages | 1024 | Allocate 2 MiB pages for NVMe submission/completion queues |
| fs.file-max | 2097152 | Support thousands of device nodes |
Apply the values with sysctl -p /etc/sysctl.d/99-nvmeof.conf. For RDMA, ensure the NIC is configured for RoCEv2 with a dedicated VLAN and PFC enabled; the kernel module ib_uverbs must be loaded.
Operational Runbook
1. Deploy Target Nodes
Provision bare-metal or VM with at least 2 × Intel Xeon E5-2699 v4, 256 GiB RAM, and dual-port 100 GbE NICs supporting RoCEv2.
Install RHEL 9, enable the
nvmetandnvmetclipackages from the AppStream repository.Apply the kernel tuning from Table 1 and reboot.
Copy the immutable
config.jsonfrom Git, runnvmetcli restore, and verifynvme list-subsyson the host.Start
nvmet.targetand enablefirewalldports 4420/tcp and 4420/udp (RDMA).
2. Provision Initiator Nodes
Install
nvme-cli≥ 2.5,multipath-tools, andcollectd.Configure the host NQN in
/etc/nvme/hostnqnand register it with the target ACL.Run the discovery and connect commands shown earlier.
Update
/etc/multipath.confwith the WWID reported bynvme id-ctrland restartmultipathd.Validate I/O path redundancy by disabling one NIC and confirming
multipath -llshows an active path count of 2.
3. Monitoring & Alerting
Collectd plugin
NVMepublishesnvme_iocounters every 10 s.Prometheus scrape
/metricsfromnvme_exporter(port 9100) on each target.Alert on
nvme_io_errors_total > 0or latencynvme_latency_seconds > 0.001for more than 5 min.
4. Upgrade Procedure
When moving from kernel 5.14 to 6.4, the nvmet ABI remains stable, but the JSON schema adds the optional max_qsize field. Perform a rolling upgrade:
Drain one target node (remove it from the load-balancer).
Backup
/etc/nvmet/config.jsonand the/var/lib/nvmetstate directory.Install the new kernel, reboot, and run
nvmetcli restoreto re-apply the configuration.Run
nvme list-subsyson a random initiator to confirm connectivity.Re-introduce the node to the fabric and repeat for the remaining nodes.
TCP vs. RDMA Trade-offs
Both transports expose the same NVMe command set, but they differ in CPU overhead, latency, and deployment complexity.
| Metric | TCP | RDMA (RoCEv2) |
|---|---|---|
| Average latency (1 µs I/O) | 0.75 ms | 0.35 ms |
| CPU per GB/s | 0.45 % core | 0.12 % core |
| Network requirement | Standard L3 routing, no PFC | Lossless Ethernet, PFC + ETS |
| Operational complexity | Low – works over existing VLANs | Medium – requires DCB configuration |
| Compatibility | All Linux kernels 5.0+ | Requires RDMA NIC driver (mlx5, cx4) |
For workloads that demand < 0.5 ms latency (e.g., high-frequency trading or real-time analytics), RDMA is the only viable path. For general-purpose private clouds where the network team prefers a simpler stack, TCP provides acceptable latency with zero-touch configuration.
Security Considerations
NVMe-oF does not encrypt data in flight. Two mitigation layers are recommended:
IPsec for TCP transports – use
strongSwanwith AES-256-GCM and a 5-second re-key interval.TLS-offload for RDMA – deploy a hardware security module (HSM) that terminates TLS before the NIC, then forward clear traffic over RoCEv2 inside a dedicated VLAN.
Access control is enforced by the target ACL (the hosts array in the JSON). Rotate host NQNs every 90 days and audit the ACL with:
# jq '.subsystems[].hosts' /etc/nvmet/config.json Enable auditd rule to log nvmet syscalls:
-w /sys/kernel/config/nvmet -p wa -k nvmet Observability Stack
The following Prometheus scrape targets are required:
node_exporter– for CPU, memory, and network counters.nvme_exporter– exposesnvme_io_read_bytes_total,nvme_io_write_bytes_total, andnvme_latency_seconds.collectd– forwardsnvmeplugin metrics to InfluxDB for long-term retention.
Grafana dashboards can be built from the NVMe-oF.json dashboard template shipped with the exporter.
Comparison with Alternative Architectures
Table 3 positions NVMe-oF against iSCSI, NFS-Ganesha, and Ceph RBD for a private-cloud block-storage layer.
| Feature | NVMe-oF | iSCSI | NFS-Ganesha | Ceph RBD |
|---|---|---|---|---|
| Latency (99th %) | 0.35 ms (RDMA) | 0.9 ms | 1.2 ms | 0.8 ms |
| IOPS per GB | ~150 k | ~70 k | ~45 k | ~100 k |
| CPU overhead | 0.12 % core/GB (RDMA) | 0.45 % core/GB | 0.55 % core/GB | 0.30 % core/GB |
| Management complexity | Medium (ACL + transport) | Low | Low | High (CRUSH maps) |
| Data protection | Target-side RAID or hardware ECC | Target RAID | POSIX ACLs | Erasure coding |
NVMe-oF wins on raw performance and CPU efficiency, but it requires a lossless Ethernet fabric for the best numbers. Organizations that cannot guarantee DCB should start with TCP NVMe-oF and evaluate a migration path to RDMA as the network matures.
Summary
The guide presents a repeatable, version-controlled method to deliver sub-millisecond block storage across a private-cloud fabric. By separating target configuration (nvmetcli), initiator multipathing, and observability, operators can scale to thousands of hosts while maintaining deterministic latency and auditable security.
Free Webmaster, SRE & Cloud Diagnostic Tools (No Signup Required)
Verify and benchmark your production infrastructure directly from your browser using the HostingPodium Free Webmaster & Developer Suite:
| Free Engineering Utility | Primary Diagnostic Use Case |
|---|---|
| Global DNS Propagation & SSL Checker | Verify live A, AAAA, CNAME, MX, TXT, NS & CAA records across 21+ global resolvers + TLS certificate audits |
| Website Speed Test & Core Web Vitals Auditor | Measure server TTFB, LCP, INP, CLS, and HTTP/2 compression latency in real time |
| Rich Snippets & Schema.org JSON-LD Generator | Generate & validate structured JSON-LD markup for TechArticles, FAQs, Products & Organizations |
| HTTP Redirect Chain & Status Code Tracer | Trace 301/302 redirect hops, inspect response headers, and verify load balancer health checks |
| DMARC, SPF & DKIM Email Security Validator | Audit domain email authentication policies and generate compliant DMARC records |
| Google SERP Simulator & Meta Tag Previewer | Preview desktop/mobile Google snippets, OpenGraph cards, and pixel-width truncation |
| Free WebP Image Converter & Optimizer | Client-side PNG/JPG to WebP compression for faster Core Web Vitals LCP |
Related Enterprise Architecture & Benchmarks
- Canonical Engineering Guide: Designing Linux NVMe-oF over TCP & RDMA for Private-Cloud Disaggregated Storage
- Managed Engineering Practice: Cloud Platform Engineering Services & Solutions
- Infrastructure Benchmark Comparison: AWS Cost Alternative: Zero Egress Fees & Dedicated Bare Metal