<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sergey Platonov</title>
    <description>The latest articles on DEV Community by Sergey Platonov (@pltnvs).</description>
    <link>https://dev.to/pltnvs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1730592%2Fa940c3cd-3341-4a82-9c79-7d9d29871176.jpg</url>
      <title>DEV Community: Sergey Platonov</title>
      <link>https://dev.to/pltnvs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pltnvs"/>
    <language>en</language>
    <item>
      <title>The Definitive Guide to mdraid, mdadm, and Linux Software RAID</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Tue, 29 Jul 2025 07:25:40 +0000</pubDate>
      <link>https://dev.to/pltnvs/the-definitive-guide-to-mdraid-mdadm-and-linux-software-raid-57aa</link>
      <guid>https://dev.to/pltnvs/the-definitive-guide-to-mdraid-mdadm-and-linux-software-raid-57aa</guid>
      <description>&lt;h2&gt;
  
  
  What Is mdraid? Core Concepts
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;mdraid&lt;/strong&gt; (often shortened to &lt;em&gt;MD RAID&lt;/em&gt; or simply &lt;em&gt;md&lt;/em&gt;) is the Linux kernel’s built‑in software RAID framework. It aggregates multiple block devices (drives, partitions, loopbacks, NVMe namespaces, etc.) into a single logical block device (/dev/mdX) that can deliver improved performance, redundancy, capacity aggregation or some combination depending on the selected RAID level.&lt;/p&gt;

&lt;p&gt;At its heart, mdraid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lives primarily in the Linux kernel as the md (Multiple Device) driver.&lt;/li&gt;
&lt;li&gt;Uses on‑disk superblock metadata to describe array membership and layout.&lt;/li&gt;
&lt;li&gt;Exposes assembled arrays as standard block devices that can be partitioned, formatted, LVM’ed, encrypted, or used directly by applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: &lt;strong&gt;mdraid is the engine; mdadm is the toolkit and dashboard.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How mdraid Fits in the Linux Storage Stack
&lt;/h2&gt;

&lt;p&gt;A simplified vertical stack (bottom → top):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Physical / Virtual Drives]
  SATA / SAS / NVMe / iSCSI LUNs / VMDKs / Cloud Block Vols
        ↓
[mdraid Kernel Layer]  ← assembled via mdadm
  RAID0 | RAID1 | RAID4/5/6 | RAID10 | RAID1E | linear | multipath | etc.
        ↓
[Optional Layers]
  LUKS dm-crypt  |  LVM PV/VG/LV (incl. LVM-thin)  |  Filesystems (ext4, XFS, btrfs, ZFS-on-Linux as zvol consumer, etc.)
        ↓
[Applications / Containers / VMs]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because md devices appear as regular block devices, you can build rich storage stacks: encrypt then RAID, RAID then encrypt, layer LVM for flexible volume management, or present md devices to virtualization hosts.&lt;/p&gt;

&lt;h2&gt;
  
  
  mdadm vs mdraid: Terminology Clarified
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;th&gt;Where You See It&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;md&lt;/td&gt;
&lt;td&gt;Kernel driver&lt;/td&gt;
&lt;td&gt;Implements software RAID logic.&lt;/td&gt;
&lt;td&gt;/proc/mdstat, /sys/block/md*, kernel logs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mdraid&lt;/td&gt;
&lt;td&gt;Informal name&lt;/td&gt;
&lt;td&gt;Linux md software RAID subsystem.&lt;/td&gt;
&lt;td&gt;Docs &amp;amp; articles: “Linux mdraid,” etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mdadm&lt;/td&gt;
&lt;td&gt;User-space tool&lt;/td&gt;
&lt;td&gt;Create, assemble, grow, monitor, fail, remove arrays; generate config.&lt;/td&gt;
&lt;td&gt;CLI: &lt;code&gt;mdadm --create /dev/md0 …&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/etc/mdadm.conf&lt;/td&gt;
&lt;td&gt;Config file&lt;/td&gt;
&lt;td&gt;Records ARRAY definitions &amp;amp; metadata defaults; persists arrays across boots.&lt;/td&gt;
&lt;td&gt;At boot/assembly time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember: You manage arrays with &lt;strong&gt;mdadm&lt;/strong&gt;; the arrays themselves are provided by the &lt;strong&gt;mdraid&lt;/strong&gt; kernel layer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Supported RAID Levels &amp;amp; Modes
&lt;/h2&gt;

&lt;p&gt;mdraid supports a broad set of personalities (RAID implementations). Availability may vary slightly by kernel version, but common ones include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;linear – Concatenate devices end‑to‑end; no redundancy.&lt;/li&gt;
&lt;li&gt;RAID 0 (striping) – Performance &amp;amp; aggregate capacity; zero redundancy.&lt;/li&gt;
&lt;li&gt;RAID 1 (mirroring) – Redundancy via copies; read parallelism.&lt;/li&gt;
&lt;li&gt;RAID 4 – Dedicated parity disk; rarely used.&lt;/li&gt;
&lt;li&gt;RAID 5 – Distributed parity across members; 1‑disk fault tolerance.&lt;/li&gt;
&lt;li&gt;RAID 6 – Dual distributed parity; 2‑disk fault tolerance.&lt;/li&gt;
&lt;li&gt;RAID 10 – Striped mirrors (mdraid implements as an n‑way layout over mirrored sets; flexible). Good mix of speed + redundancy.&lt;/li&gt;
&lt;li&gt;RAID 1E / RAID 10 variants – Extended / asymmetric mirror‑stripe layouts for odd numbers of drives.&lt;/li&gt;
&lt;li&gt;Multipath – md can be used (less common today) to provide failover across multiple I/O paths.&lt;/li&gt;
&lt;li&gt;Faulty – Testing personality that injects failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Architecture Elements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Superblock Metadata&lt;/strong&gt; – Small headers stored on member devices that describe array UUID, RAID level, layout, chunk size, role of each device, and state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;md Personalities&lt;/strong&gt; – RAID level implementations registered with the kernel’s md subsystem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bitmaps&lt;/strong&gt; – Optional on‑disk or in‑memory bitmaps track which stripes are dirty, dramatically shortening resync/recovery after unclean shutdowns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reshape Engine&lt;/strong&gt; – Allows changing array geometry (add/remove devices, change RAID level in some cases) online in many scenarios. Performance impact can be significant; plan maintenance windows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mdmon (External Metadata Monitor)&lt;/strong&gt; – Required for some external metadata formats (e.g., IMSM/Intel Matrix) to keep metadata in sync.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sysfs Controls&lt;/strong&gt; – Tunables under &lt;code&gt;/sys/block/mdX/md/&lt;/code&gt; expose runtime parameters (stripe cache, sync speed limits, write‑mostly flags, etc.).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Homelab NAS or DIY storage server using commodity disks.&lt;/li&gt;
&lt;li&gt;Bootable mirrors (RAID1) for root filesystem resiliency.&lt;/li&gt;
&lt;li&gt;RAID10 for database or virtualization workloads needing strong random I/O + redundancy.&lt;/li&gt;
&lt;li&gt;RAID5/6 for bulk capacity with parity protection (backup targets, media libraries—though see risk discussion below on rebuild windows and URE rates).&lt;/li&gt;
&lt;li&gt;Aggregating NVMe drives when hardware RAID isn’t desired or available.&lt;/li&gt;
&lt;li&gt;Cloud or virtual environments where virtual disks need software‑defined redundancy across failure domains.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Planning an mdraid Deployment
&lt;/h2&gt;

&lt;p&gt;Before typing &lt;code&gt;mdadm --create&lt;/code&gt;, answer these:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workload Profile&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Random vs sequential; read‑heavy vs write‑heavy; mixed DB + VM vs cold archive.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redundancy vs Capacity&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
How many failures must you tolerate? RAID1/10 vs RAID5/6 trade‑offs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Media Type&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
HDD, SSD, NVMe, or mixed? Parity RAID on SSD behaves differently (write amplification, TRIM behavior, queue depth scaling).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Growth Expectations&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Will you add drives later? Consider RAID10 or start with larger drive count in RAID6; know reshape implications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Boot Requirements&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
If booting from md, choose metadata format (0.90 or 1.0) that places superblock where firmware/bootloader expects.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitoring &amp;amp; Alerting Plan&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Email alerts, systemd timers, &lt;code&gt;mdadm --monitor&lt;/code&gt;, integration with Prometheus/node_exporter, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backup Strategy&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
RAID ≠ backup. Always maintain off‑array copies of critical data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step‑by‑Step: Creating and Managing Arrays with mdadm
&lt;/h2&gt;

&lt;p&gt;Below are high‑signal, copy‑paste‑friendly examples. Adjust device names and sizes to your environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install mdadm
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Debian/Ubuntu:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install -y mdadm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;RHEL/CentOS/Rocky/Alma:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dnf install -y mdadm   # or yum on older releases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create a RAID1 Mirror (Bootable Friendly Metadata)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mdadm --create /dev/md0 \
  --level=1 \
  --raid-devices=2 \
  --metadata=1.0 \
  /dev/sda1 /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;--metadata=1.0 stores the superblock at the end of the device, leaving initial sectors clean for bootloaders.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Create a RAID5 Array&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mdadm --create /dev/md/data \
  --level=5 \
  --raid-devices=4 \
  --chunk=256K \
  /dev/sd[b-e]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Assemble Existing Arrays (e.g., after reboot)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mdadm --assemble --scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check Status&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/mdstat
sudo mdadm --detail /dev/md0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Mark a Device as Failed &amp;amp; Remove It&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mdadm /dev/md0 --fail /dev/sdb1
sudo mdadm /dev/md0 --remove /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add Replacement Drive&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mdadm /dev/md0 --add /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generate /etc/mdadm.conf&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mdadm --detail --scan | sudo tee -a /etc/mdadm.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt;&lt;br&gt;
After creating or modifying arrays, regenerate your initramfs if the system boots from md devices so the early boot environment knows how to assemble arrays.&lt;/p&gt;
&lt;h2&gt;
  
  
  Chunk Size, Stripe Geometry &amp;amp; Alignment
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Chunk&lt;/strong&gt; (sometimes called “stripe unit”) – The amount of contiguous data written to each member before moving to the next.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Stripe&lt;/strong&gt; – One full pass across all data disks in the array (excludes parity disks in descriptive math but included in physical layout).&lt;/p&gt;
&lt;h3&gt;
  
  
  Why it matters:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Too small a chunk → frequent parity calculations, more IOPS overhead on large sequential writes.&lt;/li&gt;
&lt;li&gt;Too large a chunk → small random writes waste bandwidth; read‑modify‑write penalties.&lt;/li&gt;
&lt;li&gt;Align chunk to filesystem block and workload I/O sizes to reduce partial‑stripe writes.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Rules of Thumb
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;64K–256K&lt;/strong&gt; chunks common for parity RAID on HDDs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Larger (256K–1M+)&lt;/strong&gt; chunks often beneficial for large sequential workflows (backups, media, VM images) and on fast SSD/NVMe backends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benchmark your workload&lt;/strong&gt;: &lt;code&gt;fio&lt;/code&gt; with realistic I/O depth &amp;amp; patterns beats rules of thumb every time.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Alignment Checklist
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Use whole‑disk members when possible (avoid legacy partition offset issues).&lt;/li&gt;
&lt;li&gt;If partitioning, start at &lt;strong&gt;1MiB boundary&lt;/strong&gt; (modern default in &lt;code&gt;parted&lt;/code&gt; &amp;amp; &lt;code&gt;gdisk&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Filesystem &lt;code&gt;mkfs&lt;/code&gt; tools often have &lt;code&gt;-E stride=stripe_unit&lt;/code&gt; or &lt;code&gt;-d su=&lt;/code&gt; options—set them!&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Performance Tuning Tips
&lt;/h2&gt;

&lt;p&gt;Performance depends on workload, media, CPU, and kernel version. Start with measurement, then tune.&lt;/p&gt;


&lt;h3&gt;
  
  
  1. Set Appropriate Chunk Size at Creation
&lt;/h3&gt;

&lt;p&gt;Changing later usually means rebuild. Match to workload I/O size mix.&lt;/p&gt;


&lt;h3&gt;
  
  
  2. Increase Stripe Cache (RAID5/6)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;stripe_cache_size&lt;/code&gt; sysfs tunable can significantly improve parity RAID write throughput by caching partial stripes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;4096 | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /sys/block/md0/md/stripe_cache_size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Tune Sync/Resync/Reshape Speeds
&lt;/h3&gt;

&lt;p&gt;Limit or accelerate background operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 50000 | sudo tee /proc/sys/dev/raid/speed_limit_min  # KB/s
echo 500000 | sudo tee /proc/sys/dev/raid/speed_limit_max # KB/s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Raise during maintenance windows; lower during production peaks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Enable or Place Write‑Mostly Devices
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mdadm --write-mostly /dev/md0 /dev/sdd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Use Bitmaps to Shorten Resync Windows
&lt;/h3&gt;

&lt;p&gt;Create with &lt;code&gt;--bitmap=internal&lt;/code&gt; (or &lt;code&gt;--bitmap=external&lt;/code&gt; to separate device). Faster recovery after power loss.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. TRIM / Discard on SSD Arrays
&lt;/h3&gt;

&lt;p&gt;Ensure filesystem supports discard; consider periodic fstrim rather than continuous discard for performance stability.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. NUMA &amp;amp; IRQ Affinity
&lt;/h3&gt;

&lt;p&gt;High‑throughput NVMe + mdraid builds benefit from CPU affinity tuning—pin IRQs, balance queues.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Benchmark Regularly
&lt;/h3&gt;

&lt;p&gt;Use fio, dd (for rough sequential), iostat, perf, and application‑level metrics (DB TPS, VM boot time) to validate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring, Alerts &amp;amp; Maintenance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Key Health Indicators:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Degraded arrays, failed drives, mismatched events, bitmap resync in progress, high mismatch counts after check runs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Enable mdadm Monitor Service
&lt;/h3&gt;

&lt;p&gt;Create a simple systemd unit or use distro packages:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo mdadm --monitor --daemonise --scan --syslog --program=/usr/sbin/mdadm-email.sh&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Where your script sends email, Slack, PagerDuty, etc.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Check &lt;code&gt;/proc/mdstat&lt;/code&gt; Regularly
&lt;/h3&gt;

&lt;p&gt;Automate:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;watch -n 2 cat /proc/mdstat&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Scheduled Consistency Checks
&lt;/h3&gt;

&lt;p&gt;Many distros schedule a monthly check:&lt;br&gt;&lt;br&gt;
&lt;code&gt;echo check &amp;gt; /sys/block/mdX/md/sync_action&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To repair mismatches (if any are found):&lt;br&gt;&lt;br&gt;
&lt;code&gt;echo repair &amp;gt; /sys/block/mdX/md/sync_action&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  SMART + Predictive Failure
&lt;/h3&gt;

&lt;p&gt;RAID hides but does not prevent media failure. Use &lt;code&gt;smartctl&lt;/code&gt;, &lt;code&gt;nvme-cli&lt;/code&gt;, and vendor tools.&lt;br&gt;&lt;br&gt;
Integrate SMART alerts with md state for proactive failure prediction and diagnostics.&lt;/p&gt;
&lt;h2&gt;
  
  
  Recovery, Rebuilds &amp;amp; Reshape Operations
&lt;/h2&gt;

&lt;p&gt;When a member fails:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identify&lt;/strong&gt;: Use &lt;code&gt;mdadm --detail&lt;/code&gt; and check system logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail the Device&lt;/strong&gt;: &lt;code&gt;mdadm /dev/mdX --fail /dev/sdY&lt;/code&gt; (if not auto‑failed).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove&lt;/strong&gt;: &lt;code&gt;mdadm /dev/mdX --remove /dev/sdY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Replace Hardware / Repartition Replacement Drive.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add&lt;/strong&gt;: &lt;code&gt;mdadm /dev/mdX --add /dev/sdZ&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Rebuild&lt;/strong&gt;: &lt;code&gt;watch /proc/mdstat&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Rebuild Performance Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Large modern disks = long rebuild windows; risk of 2nd failure rises.&lt;/li&gt;
&lt;li&gt;Use bitmaps to reduce resync scope after unclean shutdowns.&lt;/li&gt;
&lt;li&gt;Raise &lt;code&gt;speed_limit_min&lt;/code&gt; during maintenance to shorten exposure.&lt;/li&gt;
&lt;li&gt;On SSD/NVMe parity RAID, controller queue and CPU bottlenecks matter.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Reshaping (e.g., RAID5 → RAID6, add disks)
&lt;/h3&gt;

&lt;p&gt;Reshape is I/O heavy and lengthy. Always back up.&lt;br&gt;&lt;br&gt;
Expect degraded performance; schedule during off‑peak hours.&lt;/p&gt;
&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encryption&lt;/strong&gt;: Layer &lt;code&gt;LUKS&lt;/code&gt;/&lt;code&gt;dm-crypt&lt;/code&gt; above mdraid (common) or below (each member encrypted) depending on your threat model.
Above is simpler; below preserves per‑disk confidentiality when disks are moved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Erase Before Reuse&lt;/strong&gt;: Superblocks persist. Wipe old metadata using
&lt;code&gt;mdadm --zero-superblock /dev/sdX&lt;/code&gt; before reassigning drives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Control&lt;/strong&gt;: md devices are block devices. Secure them with proper permissions and enable audit logging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firmware Trust&lt;/strong&gt;: When mixing vendor drives, ensure no malicious firmware modification.
Supply chain trust is critical in sensitive environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Alternatives to mdraid
&lt;/h2&gt;

&lt;p&gt;Linux admins have choices. Here’s how &lt;strong&gt;mdraid&lt;/strong&gt; stacks up against popular alternatives.&lt;/p&gt;
&lt;h3&gt;
  
  
  xiRAID: High‑Performance Software RAID
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;xiRAID&lt;/strong&gt; (from Xinnor) is a modern, high‑performance software RAID engine engineered for today’s multi‑core CPUs and fast SSD/NVMe media.&lt;br&gt;&lt;br&gt;
Across multiple publicly reported benchmarks and partner tests, xiRAID has consistently shown higher performance than traditional mdraid—often substantially so under heavy write, mixed database, virtualization, or degraded/rebuild conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reported Advantages&lt;/strong&gt; (varies by version, platform, and workload):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher IOPS and throughput vs mdraid on NVMe and SSD arrays.&lt;/li&gt;
&lt;li&gt;Dramatically faster degraded‑mode performance (a common mdraid pain point).&lt;/li&gt;
&lt;li&gt;Faster rebuild times, reducing risk windows.&lt;/li&gt;
&lt;li&gt;Lower CPU overhead in some configurations; better multi‑core scaling.&lt;/li&gt;
&lt;li&gt;Optimizations for large‑capacity SSD/QLC media and write amplification reduction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Consider xiRAID When:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run database, virtualization, analytics, or AI workloads on dense flash/NVMe.&lt;/li&gt;
&lt;li&gt;Rebuild speed and minimal performance drop during failure are business‑critical.&lt;/li&gt;
&lt;li&gt;You need to squeeze maximum performance from software RAID without dedicated hardware controllers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Operational Notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Commercial licensing (free tiers often limited by drive count—check current program).&lt;/li&gt;
&lt;li&gt;Kernel module / driver stack is separate from mdraid; evaluate distro compatibility.&lt;/li&gt;
&lt;li&gt;Migration from mdraid typically requires data evacuation + recreate.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Hardware RAID Controllers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Battery‑backed cache (BBU) accelerates writes.&lt;/li&gt;
&lt;li&gt;Controller offloads parity computation.&lt;/li&gt;
&lt;li&gt;Integrated management and vendor support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proprietary metadata; controller lock‑in.&lt;/li&gt;
&lt;li&gt;Rebuilds tied to card health.&lt;/li&gt;
&lt;li&gt;Limited transparency compared to &lt;code&gt;mdadm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Potential single point of failure without identical spare controller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where It Fits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Legacy datacenters.&lt;/li&gt;
&lt;li&gt;Environments requiring OS‑agnostic boot processes.&lt;/li&gt;
&lt;li&gt;Workflows with existing tooling and operational dependency on vendor RAID cards.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  LVM RAID (device‑mapper RAID)
&lt;/h3&gt;

&lt;p&gt;Logical Volume Manager (LVM2) can create RAID volumes using the &lt;code&gt;device‑mapper‑raid&lt;/code&gt; target. Under the hood it leverages similar code paths to &lt;code&gt;md&lt;/code&gt; but integrates tightly with LVM volume groups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use When:&lt;/strong&gt; You want LVM flexibility (snapshots, thin provisioning) and RAID protection in one stack layer. Modern distros make this increasingly attractive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caveat:&lt;/strong&gt; Tooling and recovery flows differ from raw &lt;code&gt;mdadm&lt;/code&gt;; mixing both can confuse newcomers.&lt;/p&gt;
&lt;h3&gt;
  
  
  Btrfs Native RAID Profiles
&lt;/h3&gt;

&lt;p&gt;Btrfs can do data/metadata replication (RAID1/10) and parity (RAID5/6—still flagged as having historical reliability caveats; check current kernel status). Provides end‑to‑end checksums, transparent compression, snapshots, send/receive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Great For:&lt;/strong&gt; Self‑healing replicated storage where checksums matter more than raw parity write speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch Out:&lt;/strong&gt; Historically unstable RAID5/6; always confirm current kernel guidance before production use.&lt;/p&gt;
&lt;h3&gt;
  
  
  ZFS RAID‑Z &amp;amp; Mirrors
&lt;/h3&gt;

&lt;p&gt;ZFS provides integrated RAID (mirrors, RAID‑Z1/2/3), checksums, compression, snapshots, send/receive replication, and robust scrubbing. Excellent data integrity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengths:&lt;/strong&gt; Bit‑rot detection, self‑healing, scalable pools, advanced caching (ARC/L2ARC, ZIL/SLOG).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trade‑Offs:&lt;/strong&gt; RAM hungry; license separation (CDDL) from Linux kernel means out‑of‑tree module; tuning required for small RAM systems.&lt;/p&gt;

&lt;p&gt;Absolutely! Here's the &lt;strong&gt;formatted markdown version&lt;/strong&gt; of the full &lt;strong&gt;FAQ, Glossary, and Final Thoughts&lt;/strong&gt; section. You can &lt;strong&gt;copy and paste this directly into your Dev.to post&lt;/strong&gt;:&lt;/p&gt;
&lt;h3&gt;
  
  
  FAQ: mdraid, mdadm &amp;amp; Linux RAID Troubleshooting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Q: Is mdraid stable for production?&lt;/strong&gt;&lt;br&gt;
Yes—mdraid has powered Linux servers for decades. It’s widely trusted in enterprise, hosting, and cloud images. Stability depends more on hardware quality, monitoring, and admin discipline than on the md layer itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I expand a RAID5 array by adding a drive?&lt;/strong&gt;&lt;br&gt;
Yes, &lt;code&gt;mdadm&lt;/code&gt; supports growing RAID5/6 arrays. The reshape can take a long time and is I/O heavy; always back up first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Should I use RAID5 with large (&amp;gt;14TB) disks?&lt;/strong&gt;&lt;br&gt;
Consider RAID6 or RAID10 instead. Rebuild times and URE risk make single‑parity arrays risky at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What metadata version should I pick for a boot array?&lt;/strong&gt;&lt;br&gt;
Use &lt;code&gt;1.0&lt;/code&gt; (or &lt;code&gt;0.90&lt;/code&gt; on very old systems) so bootloaders that expect clean starting sectors can function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I know if my array is healthy?&lt;/strong&gt;&lt;br&gt;
Check &lt;code&gt;/proc/mdstat&lt;/code&gt;, &lt;code&gt;mdadm --detail&lt;/code&gt;, and configure &lt;code&gt;mdadm --monitor&lt;/code&gt; email alerts. Also monitor SMART.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I mix SSD and HDD in one md array?&lt;/strong&gt;&lt;br&gt;
Technically yes, but performance drops to the slowest members. Better: separate tiers, or mark slower disks write‑mostly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I safely remove old RAID metadata from a reused disk?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mdadm --zero-superblock /dev/sdX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Q: What’s faster: mdraid or xiRAID?&lt;/strong&gt;&lt;br&gt;
In multiple published benchmarks on flash/NVMe workloads, xiRAID has outperformed mdraid—sometimes by large margins—especially under degraded or rebuild conditions. Always benchmark with your own hardware and workload mix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Glossary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Array&lt;/strong&gt; – A logical grouping of drives presented as one block device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bitmap&lt;/strong&gt; – A map of dirty stripes that speeds resync after unclean shutdowns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chunk (Stripe Unit)&lt;/strong&gt; – Data segment written to one disk before moving to the next in a stripe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Degraded&lt;/strong&gt; – Array running with one or more failed/missing members but still serving I/O.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hot Spare&lt;/strong&gt; – Idle member device that automatically rebuilds into an array upon failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mdadm&lt;/strong&gt; – User‑space tool for managing mdraid arrays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata / Superblock&lt;/strong&gt; – On‑disk record of array identity and layout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parity&lt;/strong&gt; – Calculated redundancy data enabling reconstruction of lost blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resync / Rebuild&lt;/strong&gt; – Process of restoring redundancy after failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reshape&lt;/strong&gt; – Changing array geometry (size, level, layout) in place.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;mdraid&lt;/strong&gt; remains a foundation technology for Linux storage: robust, flexible, battle‑tested, and free. For many workloads—especially HDD‑based capacity pools—it’s the obvious default. But the storage landscape has changed. With NVMe density, flash wear patterns, extreme rebuild windows, and ever‑higher performance expectations, specialized engines can deliver meaningful gains in throughput, latency consistency, degraded‑mode resilience, and rebuild speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The smart move:&lt;/strong&gt;&lt;br&gt;
Deploy mdraid where it fits, benchmark xiRAID (or other alternatives) where performance matters, and always design around &lt;strong&gt;data protection, observability, and recoverability&lt;/strong&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Performance Guide Pt. 3: Setting Up and Testing RAID</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Wed, 02 Apr 2025 06:05:54 +0000</pubDate>
      <link>https://dev.to/pltnvs/performance-guide-pt-3-setting-up-and-testing-raid-38df</link>
      <guid>https://dev.to/pltnvs/performance-guide-pt-3-setting-up-and-testing-raid-38df</guid>
      <description>&lt;p&gt;This is the third and the final part of the Performance Guide. The first two parts were about performance characteristics, the ways to measure it and optimal hardware and software configurations. Now, in this concluding section, we'll be focusing entirely on RAID. We'll cover topics like choosing the right RAID geometry, configuring NUMA nodes, and conducting RAID testing. Let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  xiRAID 4.0.x
&lt;/h2&gt;

&lt;h3&gt;
  
  
  RAID geometry selection
&lt;/h3&gt;

&lt;p&gt;One of the key factors in achieving optimal performance is selecting the correct RAID geometry.&lt;/p&gt;

&lt;p&gt;The following parameters should be considered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The expected workload.&lt;/li&gt;
&lt;li&gt;The characteristics of the drives.&lt;/li&gt;
&lt;li&gt;The expected functionality of RAID in cases of failure and recovery.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Recommendations on selecting RAID geometry
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If you deal with a large number of random workload threads, we recommend choosing RAID 5/50 configuration (RAID 50 must have a minimum of 8 drives).&lt;/li&gt;
&lt;li&gt;For random workloads, it is recommended to use a strip size of 16K.&lt;/li&gt;
&lt;li&gt;For sequential workloads, it is recommended to use a strip size larger than 16K (such as 32K, 64K, or 128K). However, the strip size should be selected in a way that ensures the RAID stripe size is 1MB or less. If the stripe size exceeds 1MB, merge functions will not work (the merge function is explained below in this document).&lt;/li&gt;
&lt;li&gt;If you deal with a large number of drives and a relatively low number of writes, you can consider using RAID 6 configuration.&lt;/li&gt;
&lt;li&gt;Different models of drives can exhibit the best write performance when using different block sizes. For certain drives, the maximum performance can be achieved with a 128K block, while for others it may be 64K or 32K. This can only be verified by experiment. The optimal size of the data block for achieving the best performance in a RAID should be used as the RAID strip size for sequential write workload.&lt;/li&gt;
&lt;li&gt;For sequential write workload, it is important to find a balance between the write block size and the characteristics of the drives, as well as their number. If the write operation primarily involves the same and sufficiently large block, it is crucial to ensure that this block size matches the width of the RAID stripe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An ideal scenario with sequential workload would involve receiving 1MB requests for writing, while the drives show their maximum performance when handling a 128K block. To achieve maximum performance for the drives, a RAID 5 configuration with 9 drives (8+1) can be created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4aa0qs05f9gqbs9xi7xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4aa0qs05f9gqbs9xi7xe.png" alt="img1" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Writing with a 1MB block to a RAID 7+1 with a stripe size of 64K. The width of the stripe is 448K, which is not a multiple of the write block size. It is important to pay attention to the presence of read operations from the drives due to Read-Modify-Write operations and their volume.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbfpb6d4ai832vlx182u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbfpb6d4ai832vlx182u.png" alt="img2" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Writing with a 1MB block to a RAID 8+1. The strip size here is 64K, and the width of the stripe is 64K x 8 = 512K, which is a multiple of the write block size. This means that there are no Read-Modify-Write operations, as all data on the RAID is written in full stripes (see the Merge write section below). Therefore, there are no read operations from the drives and the final write performance is significantly better.&lt;/p&gt;

&lt;h3&gt;
  
  
  ccNUMA
&lt;/h3&gt;

&lt;p&gt;The location of arrays on the necessary NUMA nodes is crucial as NUMA can have a significant impact on system performance. xiRAID aims to process IO requests on the same cores that initiated them. However, problems can arise if the drives are on a different NUMA node.&lt;/p&gt;

&lt;p&gt;Therefore,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;try creating arrays of drives on a single NUMA node;&lt;/li&gt;
&lt;li&gt;try running the workload on that same NUMA node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To determine the NUMA node to which the device is connected, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /sys/class/nvme/nvmeXnY/device/numa_node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To determine the connection of all devices, including NVMe, you can use the lstopo command (mentioned above).&lt;/p&gt;

&lt;p&gt;If you want to run fio or other applications on a specific NUMA node, you can use the taskset command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;taskset -c `cat /sys/devices/system/node/node1/cpulist` fio&amp;lt;fio_config_file.cfg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following fio settings can be used for multiple arrays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;--numa_cpu_nodes=0: This option specifies the NUMA node(s) to be used for CPU affinity. In this case, NUMA node 0 is specified. You can adjust this value to the desired NUMA node(s) or a comma-separated list of multiple NUMA nodes.&lt;/li&gt;
&lt;li&gt;--numa_mem_policy=local: This option sets the memory allocation policy to "local," which means that memory allocation for the FIO process will prefer the local NUMA node(s) specified by numa_cpu_nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdz0demov3zg8f1oz9ac5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdz0demov3zg8f1oz9ac5.png" alt="img 3" width="800" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All drives, except nvme9c9n1, are connected to a single NUMA node, and a load-generating application is running on the same NUMA node. You can see that the I/O commands coming to the nvme9c9n1 drive, which is connected to another NUMA node, take longer to execute. This results in reduced performance for the entire array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Merge write
&lt;/h3&gt;

&lt;p&gt;Data writing to RAID arrays with parity (such as RAID 5, RAID 6, RAID 7.3, RAID 50, etc.) is performed one stripe at a time. This process can be carried out in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it is necessary to write or overwrite an entire stripe as a whole, checksums are calculated based on the data that will be written in the stripe. After that, both the checksums and the data are written to the drives. This is considered the best and fastest way to write to parity RAID.&lt;/li&gt;
&lt;li&gt;In many cases, it is necessary to write or overwrite only a part of the stripe. In such situations, the Read-Modify-Write (RMW) approach is used. The old data that is supposed to be overwritten and its corresponding checksum fragments (R) are read from the drives. Afterward, new values for the checksum fragments (M) are calculated using the received old data, old checksums, and new data. Finally, the new data and recalculated checksums are written to the drives (W). This approach is significantly slower than the first one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a RAID receives random workload, the Read-Modify-Write method must be used. However, if it is known that a RAID receives sequential write workload, you can attempt to avoid executing each write command separately. Instead, you can wait for the next write commands to come to the same stripe. If you manage to receive all the commands that allow overwriting the entire stripe (which is highly possible with sequential workload), you can combine these commands (Merge) and rewrite the stripe the first way. This way you can avoid performing RMW for each of the commands and significantly increase performance (up to several times). To achieve this, use the Merge Wait function in xiRAID.&lt;/p&gt;

&lt;p&gt;It is important to keep in mind that using merge write can have a negative impact on random operations and often leads to increased delays.&lt;/p&gt;

&lt;p&gt;In addition, it is not always possible to merge commands into a full stripe with sequential write. The xiRAID engine ensures that confirmation of write command execution is sent to the applications that initiated them only after the data has been successfully written to the drives. In order for the merge to work, it is necessary for the program to be able to send multiple commands consecutively without waiting for confirmation of data writing from the first command. Moreover, the data from these commands should be sufficient to form a complete stripe.&lt;/p&gt;

&lt;p&gt;For a synthetic workload, this condition can be defined as follows:&lt;/p&gt;

&lt;p&gt;Queue depth*io size must exceed the width of the stripe&lt;/p&gt;

&lt;p&gt;Merge is activated with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xicli raid modify -n &amp;lt;raid_name&amp;gt; -mwe 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Furthermore, for a workload, it is necessary to monitor the iostat indicators. The statistics output by the "iostat -xmt 1" command appear to be convenient for this purpose.&lt;/p&gt;

&lt;p&gt;The presence of read operations on drives with a write-only RAID load indicates the execution of read-modify-write operations.&lt;/p&gt;

&lt;p&gt;The next steps will involve increasing the mm and mw parameters until the read operations either disappear completely or their value becomes small.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rdcli raid modify -n raidname -mm 2000 -mw 2000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The merge function only works on a RAID with a stripe size of 1MB or less.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5t7o2sg8rdth92myf0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5t7o2sg8rdth92myf0v.png" alt="img4" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Writing with a 1MB block to a RAID 7+1 with a stripe size of 64K. The width of the stripe is 448K, which is not a multiple of the write block size. The configuration is similar to the one shown in picture 1, with the only difference being that Merge Write is enabled on the RAID. This allows for writing to be performed in full stripes, which results in significantly higher writing performance.&lt;/p&gt;

&lt;p&gt;Writing with a 1MB block to a RAID 7+1 with merge enabled&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbphnytou8onkqqmkkeby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbphnytou8onkqqmkkeby.png" alt="img5" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This picture shows the RAID configuration, while the previous picture displays the corresponding workload. Note that the merge_write_enabled parameter is set to 1.&lt;/p&gt;

&lt;h3&gt;
  
  
  Merge read settings
&lt;/h3&gt;

&lt;p&gt;Performing a merge for read operations may not seem obvious, but it can significantly enhance the efficiency of RAID in degraded mode. This mode refers to the situation when one or more drives fail in the RAID system, but it has not went offline. In this situation, using merge for read operations allows you to reduce the number of commands needed to calculate and restore data from a failed drive (or drives). This, in turn, significantly improves performance.&lt;/p&gt;

&lt;p&gt;The requirements for efficient operation of merge for read operations are similar:&lt;/p&gt;

&lt;p&gt;the queue depth * IO size must exceed the width of the stripe.&lt;/p&gt;

&lt;p&gt;Merge for sequential read operations in failure mode is configured as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enabling xicli raid modify -n raidname -mre 1.&lt;/li&gt;
&lt;li&gt;In degraded mode, it is important to monitor the need for increasing timeouts when using iostat. If the total number of reads from the drives exceeds the number of reads from the array, it is necessary to increase the delays of mw and mm. For example:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rdcli raid modify -n raidname -mm 2000 -mw 2000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In the current versions of xiRAID (4.0.0 and 4.0.1), there is a common threshold value of merge_wait (mw) and merge_max (mm) for Merge Write and Merge Read, which can make it difficult to use them simultaneously. This issue will be addressed and fixed in future versions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Sched setting
&lt;/h3&gt;

&lt;p&gt;xiRAID attempts to process each I/O on the same core where it was initiated by the application or drive. However, this approach results in limited parallelization of processing when dealing with multithreaded loads.&lt;/p&gt;

&lt;p&gt;If you notice that the number of threads in your workload is low and the htop command indicates a high workload on certain cores while others remain idle, it is advisable to enable the sched mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xicli raid modify -n raidname -se 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mode distributes processing tasks across all available cores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclba00iocch0qyw71lxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclba00iocch0qyw71lxd.png" alt="img6" width="800" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf4790hk6o8ijpv5gu50.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf4790hk6o8ijpv5gu50.png" alt="img7" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These pictures show the performance of xiRAID RAID when the sched mode is turned off and the loading of RAID engine processor cores. You can see that only 4 cores are being loaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F304vng5390sect97u7js.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F304vng5390sect97u7js.png" alt="img8" width="800" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rkta6a9f5c82v19dr86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rkta6a9f5c82v19dr86.png" alt="img9" width="800" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These two pictures show the performance of this xiRAID RAID under the same load, with the sched enabled. The performance has significantly improved, while also ensuring a more balanced distribution of the load on the processor cores.&lt;/p&gt;

&lt;p&gt;Init and rebuild priorities&lt;br&gt;
You can manage the service request queue depth, which enables you to allocate system resources between user IO and in-system processes.&lt;/p&gt;

&lt;p&gt;The general scenario is as follows: if you are unsatisfied with performance parameters or experiencing delays when testing performance during array recovery or initialization (although we do not recommend the latter), you have the option to reduce the priority of these operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  RAID testing
&lt;/h3&gt;

&lt;p&gt;RAID testing is generally similar to drive testing, although there are some differences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Workflow
&lt;/h3&gt;

&lt;p&gt;This section outlines the main objectives discussed in the previous sections.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define RAID performance testing tools and objectives. Use applications such as fio or vdbench for system testing. Do not use dd utilities and desktop applications like Crystal Disk.&lt;/li&gt;
&lt;li&gt;Test the drives and backend as described above in the "Drive Performance" section.&lt;/li&gt;
&lt;li&gt;Choose the array geometry that is best suited to your tasks, as described in the "xiRAID 4.0.x" section.&lt;/li&gt;
&lt;li&gt;Determine the expected RAID performance levels based on the tests conducted on the included drives (as described in the "Drive Performance" section above).&lt;/li&gt;
&lt;li&gt;Create the RAID and wait for the initialization process to complete.&lt;/li&gt;
&lt;li&gt;Run the pre-conditioning on the array. Then, run tests on the array and adjust the parameters if necessary.&lt;/li&gt;
&lt;li&gt;Make sure to perform array tests, including during simulated failure (degraded mode) and ongoing reconstruction (reconstruction mode).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you are testing in accordance with this document, steps 2-4 should already be completed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-conditioning and typical settings
&lt;/h3&gt;

&lt;p&gt;In order to obtain repeatable performance results, it is necessary to prepare the drives beforehand. As mentioned above, when preparing individual drives, we recommend following the guidelines provided in the “Drives Performance” section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;before testing sequential workload: overwrite all drives sequentially with a 128K block;&lt;/li&gt;
&lt;li&gt;before testing random workload: overwrite all drives randomly with a 4KB block.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During RAID testing, it is possible to overwrite drives with a 128K or 4K block, but this can only be done before the RAID is assembled. Once the RAID is assembled, writing directly to the drives is not possible, as it would result in the loss of RAID metadata and the RAID itself. At the same time, after the RAID is created, all disks will be partially overwritten by a block equal to the size of the strip during initialization.&lt;/p&gt;

&lt;p&gt;This makes it difficult to apply this approach in practice. Thus, we suggest performing pre-conditioning as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;before testing sequential workload, the entire RAID should be overwritten (preferably 1.5 - 2 times) sequentially with a block equal to the size of the RAID strip. Then each drive will be overwritten sequentially, with a block equal to the size of the strip (chunk). This method ensures that the RAID performance reaches a steady state corresponding to the selected chunk size during its creation.&lt;/li&gt;
&lt;li&gt;before testing random workload, it is recommended to initiate a random write workload to a RAID with a 4K block size and a number of threads equal to the number of processor threads in the system. The duration of the writing process should be set to 30-40 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance troubleshooting
&lt;/h3&gt;

&lt;p&gt;If you are not getting satisfactory results, we recommend using the following tools to analyze the problem:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;iostat&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pay attention to the statistics of the drives included in the RAID. If you see a high load on one or more drives, indicated by a growth in command queues, we recommend doing the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check the distribution of drives among NUMA nodes.&lt;/li&gt;
&lt;li&gt;Ensure the correctness of the offset setting for multithreaded tests.&lt;/li&gt;
&lt;li&gt;If a drive is consistently slower than others for an extended period of time, with a significantly larger queue of commands, it should be replaced.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;htop&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you notice a high consumption of CPU resources, you should check the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For AMD processors, it is necessary for the number of cores (die) on each chiplet to match the number of cores given in specifications (in the BIOS settings).&lt;/li&gt;
&lt;li&gt;Ensure that all processor memory channels are utilized by memory modules. Install the memory modules according to the motherboard's manual and ensure that they operate at the same frequency.&lt;/li&gt;
&lt;li&gt;Run the "dmesg" command and check its output for memory errors, as well as any other hardware errors.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thank you for reading! If you have any questions or thoughts, please leave them in the comments below. I’d love to hear your feedback!&lt;/p&gt;

&lt;p&gt;Original article can be found &lt;a href="https://xinnor.io/blog/performance-guide-pt-3-setting-up-and-testing-raid/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>performance</category>
      <category>data</category>
      <category>raid</category>
    </item>
    <item>
      <title>Performance Guide Pt. 2: Hardware and Software Configuration</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Mon, 31 Mar 2025 08:16:56 +0000</pubDate>
      <link>https://dev.to/pltnvs/performance-guide-pt-2-hardware-and-software-configuration-48ad</link>
      <guid>https://dev.to/pltnvs/performance-guide-pt-2-hardware-and-software-configuration-48ad</guid>
      <description>&lt;p&gt;&lt;strong&gt;This is the second part of our Performance Guide blog post series. In the previous part, we've covered the fundamentals of system performance, its basic units and methods for measurement. In this part, we’ll be discussing the optimal hardware configuration and Linux settings and walk you through the process of basic calculation of the expected performance.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hardware
&lt;/h2&gt;

&lt;p&gt;To identify performance problems, it is necessary to configure the hardware and software before starting the tests. Based on our experience, low performance is often caused by incorrect settings and configurations.&lt;/p&gt;

&lt;p&gt;The overall storage capacity of storage devices will always be limited by the capacity of the computer bus that attaches them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drive connection methods and topology
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PCIe&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most modern NVMe storage devices connected through U.2 or U.3 connectors, utilize up to four PCI Express lanes.&lt;/p&gt;

&lt;p&gt;To achieve optimal performance, it is important to ensure that the correct number of PCIe lanes are used to connect the drives and that there is no overcommit.&lt;/p&gt;

&lt;p&gt;Ensure that the version of the PCIe protocol matches the one used by the drives. You can test the connection using the "lspci -vv" command. Pay attention to the "LnkCap" and "LnkSta" sections. The first indicates the connectivity, while the second indicates the actual connection status.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Non-Volatile memory controller: KIOXIA Corporation NVMe SSD Controller Cx6 (rev 01) (prog-if 02 [NVM Express])
Subsystem: KIOXIA Corporation Generic NVMe CM6
Physical Slot: 2
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast &amp;gt;TAbort- &amp;lt;TAbort- &amp;lt;MAbort- &amp;gt;SERR- &amp;lt;PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 140
NUMA node: 0
IOMMU group: 41
Region 0: Memory at da510000 (64-bit, non-prefetchable) [size=32K]
Expansion ROM at da500000 [disabled] [size=64K]
Capabilities: [40] Power Management version 3
        Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
        Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [70] Express (v2) Endpoint, MSI 00
        DevCap: MaxPayload 512 bytes, PhantFunc 0, Latency L0s unlimited, L1 unlimited
                ExtTag+ AttnBtn- AttnInd- PwrInd- RBE+ FLReset+ SlotPowerLimit 75.000W
        DevCtl: CorrErr+ NonFatalErr+ FatalErr+ UnsupReq+
                RlxdOrd+ ExtTag+ PhantFunc- AuxPwr- NoSnoop+ FLReset-
                MaxPayload 256 bytes, MaxReadReq 512 bytes
        DevSta: CorrErr+ NonFatalErr- FatalErr- UnsupReq+ AuxPwr- TransPend-
        LnkCap: Port #1, Speed 16GT/s, Width x4, ASPM not supported
                ClockPM- Surprise- LLActRep- BwNot- ASPMOptComp+
        LnkCtl: ASPM Disabled; RCB 64 bytes, Disabled- CommClk+
                ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
        LnkSta: Speed 16GT/s (ok), Width x4 (ok)
                TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the protocol version or the number of lanes differ from the expected ones, you should check the BIOS settings, as well as the capabilities of the motherboard. The performance of PCIe connections is influenced by both the PCIe version and number of lanes, as indicated in the table provided below.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;PCIe Generation&lt;/th&gt;
&lt;th&gt;Single Lane Transmission Speed&lt;/th&gt;
&lt;th&gt;x1&lt;/th&gt;
&lt;th&gt;x2&lt;/th&gt;
&lt;th&gt;x4&lt;/th&gt;
&lt;th&gt;x8&lt;/th&gt;
&lt;th&gt;x16&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;td&gt;8 GT/s&lt;/td&gt;
&lt;td&gt;0.985 GB/s&lt;/td&gt;
&lt;td&gt;1.969 GB/s&lt;/td&gt;
&lt;td&gt;3.938 GB/s&lt;/td&gt;
&lt;td&gt;7.877 GB/s&lt;/td&gt;
&lt;td&gt;15.754 GB/s (126 Gbit/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4.0&lt;/td&gt;
&lt;td&gt;16 GT/s&lt;/td&gt;
&lt;td&gt;1.969 GB/s&lt;/td&gt;
&lt;td&gt;3.938 GB/s&lt;/td&gt;
&lt;td&gt;7.877 GB/s&lt;/td&gt;
&lt;td&gt;15.754 GB/s&lt;/td&gt;
&lt;td&gt;31.508 GB/s (252 Gbit/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;td&gt;32 GT/s&lt;/td&gt;
&lt;td&gt;3.938 GB/s&lt;/td&gt;
&lt;td&gt;7.877 GB/s&lt;/td&gt;
&lt;td&gt;15.754 GB/s&lt;/td&gt;
&lt;td&gt;31.508 GB/s&lt;/td&gt;
&lt;td&gt;64.008 GB/s (512 Gbit/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6.0&lt;/td&gt;
&lt;td&gt;64 GT/s&lt;/td&gt;
&lt;td&gt;7.563 GB/s&lt;/td&gt;
&lt;td&gt;15.125 GB/s&lt;/td&gt;
&lt;td&gt;30.250 GB/s&lt;/td&gt;
&lt;td&gt;60.500 GB/s&lt;/td&gt;
&lt;td&gt;121.000 GB/s (968 Gbit/s)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Backplane&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To identify bottlenecks, it is worth checking the physical connection and studying the specifications for BackPlane and NVMe expander cards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retimers and SAS-HBA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;NVMe drives can be connected to PCIe retimers, OCuLink ports on the motherboard, or tri-mode SAS HBA adapters via a BackPlane. However, if SAS drives are being used, they must be connected to the SAS HBA. If you are using a SAS HBA, ensure that the controllers are correctly installed and update the SAS HBA controller to the latest firmware version. Note that the performance of your storage system will not exceed the performance of the PCIe interfaces used to connect the drives, whether they are connected directly or indirectly.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SAS Generation&lt;/th&gt;
&lt;th&gt;Number of Ports&lt;/th&gt;
&lt;th&gt;Max Performance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SAS-3&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1200 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4800 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SAS-4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2400 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;9600 MB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ensure that the wide ports and links are correctly configured using the management utilities provided by SAS HBA.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drives
&lt;/h2&gt;

&lt;p&gt;For tasks that do not involve small block sizes, we highly recommend reformatting NVMe namespaces in 4k.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory
&lt;/h2&gt;

&lt;p&gt;When calculating checksums and during recovery, arrays with parity use RAM for temporary data storage. Therefore, it is critically important to correctly install and configure memory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://xinnor.io/what-is-xiraid/" rel="noopener noreferrer"&gt;xiRAID&lt;/a&gt; does not require a significant amount of memory. However, it is necessary to use error-correcting code memory, symmetric multiprocessing, and preferably memory with the highest supported frequency on the platform.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Failing to comply with step 2 may lead to a performance loss of about 30%-40%.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  CPU
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cores and comands requirements.
xiRAID requires a processor with support for the AVX instruction set, which is available on all modern Intel and AMD x86-64 processors. So, if you want to use xiRAID, your processor needs to have this extension.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To achieve high performance for random workload, it is necessary to have 1-2 cores for every expected 1 million IOps. For sequential workload, make sure you have at least 4 cores for every 20 GBps.&lt;/p&gt;

&lt;h2&gt;
  
  
  BIOS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;С-States must be turned off.&lt;/li&gt;
&lt;li&gt;PowerManagement. The CPU operation mode needs to be switched to performance (balanced is used by default).&lt;/li&gt;
&lt;li&gt;CPU Topology (AMD only). The number of cores (die) on each chipset must match the number of cores specified. Incorrect configuration can result in a significant loss of performance.&lt;/li&gt;
&lt;li&gt;HT/SMT. We recommend switching on HT/SMT to achieve better performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Linux
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preliminary checks and settings
&lt;/h3&gt;

&lt;p&gt;The main tool for managing NVMe in Linux is the nvme management utility.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;to see all the NVMe drives connected to the system, run the "nvme list" command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nvme list
Node                  Generic               SN                   Model                                    Namespace Usage                      Format           FW Rev  
--------------------- --------------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme7n1          /dev/ng7n1            BTLJ85110C314P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10131
/dev/nvme6n1          /dev/ng6n1            BTLJ85110CDH4P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10131
/dev/nvme5n1          /dev/ng5n1            BTLJ85110C1K4P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10131
/dev/nvme4n1          /dev/ng4n1            BTLJ85110BU94P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10170
/dev/nvme3n1          /dev/ng3n1            BTLJ85110CG74P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10131
/dev/nvme2n1          /dev/ng2n1            BTLJ85110C4N4P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10170
/dev/nvme1n1          /dev/ng1n1            BTLJ85110C8G4P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10170
/dev/nvme0n1          /dev/ng0n1            BTLJ85110BV34P0DGN   INTEL SSDPE2KX040T8                      1           4.00  TB /   4.00  TB      4 KiB +  0 B   VDV10131
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;to view information about all NVMe subsystems and verify the drive connections, run the nvme list-subsys command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nvme list-subsys
nvme-subsys7 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110C314P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme7 pcie 0000:e6:00.0 live
nvme-subsys6 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110CDH4P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme6 pcie 0000:e5:00.0 live
nvme-subsys5 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110C1K4P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme5 pcie 0000:e4:00.0 live
nvme-subsys4 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110BU94P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme4 pcie 0000:e3:00.0 live
nvme-subsys3 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110CG74P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme3 pcie 0000:9b:00.0 live
nvme-subsys2 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110C4N4P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme2 pcie 0000:9a:00.0 live
nvme-subsys1 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110C8G4P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme1 pcie 0000:99:00.0 live
nvme-subsys0 - NQN=nqn.2014.08.org.nvmexpress:80868086BTLJ85110BV34P0DGN  INTEL SSDPE2KX040T8
\
 +- nvme0 pcie 0000:98:00.0 live
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;we recommend checking the sector size and firmware version:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvme id-ctrl /dev/nvmeX -H | grep "LBA Format"
nvme id-ctrl /dev/nvmeX -H | grep "Firmware"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All drives intended for use in one RAID must have the same model, firmware version (preferably the latest one), and sector size.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;run the following command to view the status of SMART drives:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvme smart-log /dev/nvmeX --output-format=json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using EBOF, check the native NVMe multipath parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvme list-subsys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and configure Round Robin if necessary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvme connect -t rdma -a &amp;lt;target_address&amp;gt; -s &amp;lt;subnet&amp;gt; -n &amp;lt;namespace_id&amp;gt; -p rr
echo "rr" &amp;gt; /sys/class/nvme/nvmeX/subsysY/ana_group/default_load_balance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Kernel parameters
&lt;/h2&gt;

&lt;p&gt;To improve performance, you should configure the kernel boot parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;intel_idle.max_cstate=0: Sets the maximum C-state for Intel processors to 0. C-states are power-saving states for the CPU, and setting it to 0 ensures that the processor does not enter any idle power-saving state.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Applying the kernel parameters presented below will lead to a security risk. While they improve performance, they also reduce system security and Xinnor never uses them for production implementations or public performance tests. Please use these parameters with care and at your own responsibility.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;noibrs: Disables the Indirect Branch Restricted Speculation (IBRS) mitigation. IBRS is a feature that protects against certain Spectre vulnerabilities by preventing speculative execution of indirect branches.&lt;/li&gt;
&lt;li&gt;noibpb: Disables the Indirect Branch Predictor Barrier (IBPB) mitigation. IBPB is another Spectre mitigation that helps prevent speculative execution of indirect branches.&lt;/li&gt;
&lt;li&gt;nopti: Disables the Page Table Isolation (PTI) mitigation. PTI is a security feature that isolates kernel and user page tables to mitigate certain variants of the Meltdown vulnerability.&lt;/li&gt;
&lt;li&gt;nospectre_v2: Disables the Spectre Variant 2 mitigation. Spectre Variant 2, also known as Branch Target Injection, is a vulnerability that can allow unauthorized access to sensitive information.&lt;/li&gt;
&lt;li&gt;nospectre_v1: Disables the Spectre Variant 1 mitigation. Spectre Variant 1, also known as Bounds Check Bypass, is another vulnerability that can lead to unauthorized access to data.&lt;/li&gt;
&lt;li&gt;l1tf=off: Turns off the L1 Terminal Fault (L1TF) mitigation. L1TF is a vulnerability that allows unauthorized access to data in the L1 cache.&lt;/li&gt;
&lt;li&gt;nospec_store_bypass_disable: Disables the Speculative Store Bypass (SSB) mitigation. SSB is a vulnerability that can allow unauthorized access to sensitive data stored in the cache.&lt;/li&gt;
&lt;li&gt;no_stf_barrier: Disables the Single Thread Indirect Branch Predictors (STIBP) mitigation. STIBP is a feature that prevents speculation across different threads, mitigating certain Spectre vulnerabilities.&lt;/li&gt;
&lt;li&gt;mds=off: Disables the Microarchitectural Data Sampling (MDS) mitigation. MDS is a vulnerability that can lead to data leakage across various microarchitectural buffers.&lt;/li&gt;
&lt;li&gt;tsx=on: Enables Intel Transactional Synchronization Extensions (TSX). TSX is an Intel feature that provides support for transactional memory, allowing for efficient and concurrent execution of certain code segments.&lt;/li&gt;
&lt;li&gt;tsx_async_abort=off: Disables asynchronous aborts in Intel TSX. Asynchronous aborts are a mechanism that can terminate transactions and undo their effects in certain cases.&lt;/li&gt;
&lt;li&gt;mitigations=off: Turns off all generic mitigations for security vulnerabilities. This parameter disables all known hardware and software mitigations for various vulnerabilities, prioritizing performance over security.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's important to note that disabling or modifying these security mitigations can potentially expose your system to security vulnerabilities. These parameters are typically used for debugging or performance testing purposes and are not recommended for regular usage, especially in production environments.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sed -i 's/^GRUB_CMDLINE_LINUX="\(.*\)"$/GRUB_CMDLINE_LINUX="noibrs noibpb nopti nospectre_v2 nospectre_v1 l1tf=off nospec_store_bypass_disable no_stf_barrier mds=off tsx=on tsx_async_abort=off mitigations=off intel_idle.max_cstate=0 \1"/' /etc/default/grub
update-grub or grub2-mkconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We recommend setting the polling mode for NVMe devices in Intel-based systems (excluding AMD).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "options nvme poll_queues=4" &amp;gt;&amp;gt; /etc/modprobe.d/nvme.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dracut -f or update-initramfs -u -k all&lt;/p&gt;

&lt;h2&gt;
  
  
  Schedulers
&lt;/h2&gt;

&lt;p&gt;Make sure schedulers are set to ‘none’ or ‘noop’:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /sys/block/nvme*/queue/scheduler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If they are not, you can run the following Bash script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for nvme_device in /sys/block/nvme*; do
    echo noop &amp;gt; $nvme_device/queue/scheduler
done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This setting is not permanent, so you can add this loop to the rc.local or a similar file. However, please ensure that it functions correctly. Please note that permissions for the rc.local file may need to be modified to allow it to execute after a system reboot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similarly, the script increases the I/O scheduler queue depth to 512 for NVMe devices by writing "512" to the /sys/block//queue/nr_requests file. Increasing the queue depth can allow for better utilization of the device and potentially improve performance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for nvme_device in /sys/block/nvme*; do
    echo 512 &amp;gt; $nvme_device/queue/nr_requests
done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This setting is also not permanent, so you can add this loop to the rc.local or a similar file. However, please ensure that it functions correctly. Please note that permissions for the rc.local file may need to be modified to allow it to execute after a system reboot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When using Flash drives connected via HBA, please refer to the HBA instructions for recommendations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other settings
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Settings 1-5 are not permanent. So you can add this loop to the rc.local or a similar file. However, please ensure that it functions correctly. Please note that permissions for the rc.local file may need to be modified to allow it to execute after a system reboot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Disabling Transparent Huge Pages (THP): The script sets the THP to "never" by writing "never" to the /sys/kernel/mm/transparent_hugepage/enabled file. This helps reduce latency.&lt;br&gt;
echo never &amp;gt; /sys/kernel/mm/transparent_hugepage/enabled&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disabling Kernel Transparent Huge Pages (KPTI): The script sets KPTI to "never" by writing "never" to /sys/kernel/mm/transparent_hugepage/defrag file. This is another step to improve performance.&lt;br&gt;
echo never &amp;gt; /sys/kernel/mm/transparent_hugepage/defrag&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disabling Kernel Same-Page Merging (KSM): The script disables KSM by writing "0" to the /sys/kernel/mm/ksm/run file. Disabling KSM reduces CPU usage by avoiding redundant memory sharing among processes.&lt;br&gt;
echo 0 &amp;gt; /sys/kernel/mm/ksm/run&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Pattern-dependent) Setting read-ahead value for NVMe devices: The script uses the blockdev command to set the read-ahead value to 65536 (the maximum size) for NVMe devices. This setting controls the amount of data the system reads ahead of time from the storage device, which can help improve performance in some scenarios (mostly on sequential read).&lt;br&gt;
blockdev --setra 65536 /dev/nvme0n1&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Installing necessary packages: The script checks for the availability of package managers (dnf or apt) and installs the cpufrequtils and tuned packages if they are available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting CPU frequency governor: The script uses the cpupower frequency-set command to set the CPU frequency governor to "performance," which keeps the CPU running at the highest frequency. This can improve performance at the cost of increased power consumption and potential higher temperatures.&lt;br&gt;
cpupower frequency-set -g performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Displaying current CPU frequency governor: The script displays the current CPU frequency governor by reading the value from the /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor file.&lt;br&gt;
echo "Current CPU frequency governor: $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor)"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stopping irqbalance service: The script stops the irqbalance service, which distributes interrupts across CPU cores to balance the load. Stopping irqbalance can be useful when trying to maximize performance in certain scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;systemctl stop irqbalance&lt;br&gt;
systemctl status irqbalance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting system profile to throughput-performance: The script uses the tuned-adm command to set the system profile to "throughput-performance" provided by the tuned package. This profile is designed to optimize the system for high throughput and performance.&lt;br&gt;
tuned-adm profile throughput-performance&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Drive Performance
&lt;/h2&gt;

&lt;p&gt;After evaluating the system characteristics and determining the test objectives (as discussed in the previous blog post), it is necessary to proceed with the basic calculation of the expected performance. This calculation should be based on the hardware specifications and the conducted tests.&lt;/p&gt;

&lt;p&gt;This should be done as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the manufacturer's specifications for the drives.&lt;/li&gt;
&lt;li&gt;Run tests on 1-3 separate drives.&lt;/li&gt;
&lt;li&gt;If the results obtained differ significantly from the characteristics stated in the specification, refer to the troubleshooting guide.&lt;/li&gt;
&lt;li&gt;Calculate the total expected performance of all drives intended for use in RAID.&lt;/li&gt;
&lt;li&gt;Run tests simultaneously on all drives intended for use in the RAID.&lt;/li&gt;
&lt;li&gt;If the results obtained differ significantly from the expected ones, refer to the troubleshooting guide.&lt;/li&gt;
&lt;li&gt;Calculate the expected performance of the array based on these results.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The calculations should be based on the manufacturers' specifications, which often include the performance of random read/write 4k blocks, as well as of mixed workloads (70% read, 30% write). They also provide information on the sequential read/write 128k block performance.&lt;/p&gt;

&lt;p&gt;The total queue depth or the ratio of the queue depth to the number of threads is often specified.&lt;/p&gt;

&lt;p&gt;To assess performance levels, you can use the fio utility. Here are some examples of fio configuration files:&lt;/p&gt;

&lt;p&gt;Prepare the drive for the tests: overwrite the drive with a 128k block twice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=128k
ioengine=libaio
rw=write
iodepth=32
numjobs=1
blockalign=128k
[drive]
filename=/dev/nvme1n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test the workflows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=128k
ioengine=libaio
rw=read / write
iodepth=8
numjobs=2
norandommap
time_based=1
runtime=600
group_reporting
offset_increment=50%
gtod_reduce=1
[drive]
filename=/dev/nvme1n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prepare the drive for tests: overwrite the drive with a 4k block using random pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=4k
ioengine=libaio
rw=randwrite
iodepth=128
numjobs=2
random_generator=tausworthe64
[drive]
filename=/dev/nvme1n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test random workload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=4k
ioengine=libaio
rw=randrw
rwmixread=0 / 50 / 70 / 100
iodepth=128
numjobs=2
norandommap
time_based=1
runtime=600
random_generator=tausworthe64
group_reporting
gtod_reduce=1
[drive]
filename=/dev/nvme1n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After receiving the results for one drive, you should run tests on all drives simultaneously to calculate the total performance.&lt;/p&gt;

&lt;p&gt;Prepare all drives for testing: overwrite each with the 128k block twice. Examples of fio configuration files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=128k
ioengine=libaio
rw=write
iodepth=32
numjobs=1
blockalign=128k
[drive1]
filename=/dev/nvme1n1
[drive2]
filename=/dev/nvme2n1
[drive3]
filename=/dev/nvme3n1
. . .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test the workflows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=128k
ioengine=libaio
rw=read / write
iodepth=8
numjobs=2
norandommap
time_based=1
runtime=600
group_reporting
offset_increment=50%
gtod_reduce=1
[drive1]
filename=/dev/nvme1n1
[drive2]
filename=/dev/nvme2n1
[drive3]
filename=/dev/nvme3n1
. . .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prepare all drives for testing: overwrite each with a 4k block using random pattern.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=4k
ioengine=libaio
rw=randwrite
iodepth=128
numjobs=2
random_generator=tausworthe64
[drive1]
filename=/dev/nvme1n1
[drive2]
filename=/dev/nvme2n1
[drive3]
filename=/dev/nvme3n1
. . .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test random workload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
bs=4k
ioengine=libaio
rw=randrw
rwmixread=0 / 50 / 70 / 100
iodepth=128
numjobs=2
norandommap
time_based=1
runtime=600
random_generator=tausworthe64
group_reporting
gtod_reduce=1
[drive1]
filename=/dev/nvme1n1
[drive2]
filename=/dev/nvme2n1
[drive3]
filename=/dev/nvme3n1
. . .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ideally, the test results for all drives should be equal to the results for one drive multiplied by the number of drives (in terms of GBps for sequential tests and IOPS for random tests). However, due to platform limitations, these results are not always achieved across all patterns. These limitations should be taken into account further on.&lt;/p&gt;

&lt;p&gt;To ensure accurate results, it is recommended to repeat sequential tests using a block size that corresponds to the future array strip size (unless it is already equal to the specified block size used in the sequential tests). This is important because drives may show varying performance based on the block size being used.&lt;/p&gt;

&lt;p&gt;Additionally, the load level, determined by the number of threads and the queue depth, should correspond to both the manufacturer's specifications and the expected load on the RAID.&lt;/p&gt;

&lt;p&gt;To calculate the expected RAID performance, use the Table below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c1g3zxl5v99x1o9ig19.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4c1g3zxl5v99x1o9ig19.PNG" alt="t22" width="663" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r0b4byd2i57lgq2v29f.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r0b4byd2i57lgq2v29f.PNG" alt="t2" width="651" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;T&lt;/strong&gt; is the number of threads required for the test as given in the specification for the drive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q&lt;/strong&gt; is the queue depth required for the test as given in the specification for the drive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;N&lt;/strong&gt; is the number of drives used in the tests and in RAID creation.&lt;/p&gt;

&lt;p&gt;These calculations are theoretical and allow us to estimate the maximum theoretical performance of the array.&lt;/p&gt;

&lt;p&gt;In reality, the performance of the system can be influenced by both external factors (such as the operation of internal components of storage devices and temperature conditions), as well as internal factors (like the need to perform calculations and temporarily store data in memory). Therefore, we consider it normal for approximately 90-95% of the calculated performance to be achieved on the array.&lt;/p&gt;

&lt;p&gt;Thank you for reading! If you have any questions or thoughts, please leave them in the comments below. I’d love to hear your feedback!&lt;/p&gt;

&lt;p&gt;Original article can be found &lt;a href="https://xinnor.io/blog/performance-guide-pt-2-hardware-and-software-configuration/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>performance</category>
      <category>discuss</category>
      <category>software</category>
      <category>raid</category>
    </item>
    <item>
      <title>Virtualized NFSoRDMA-based Disaggregated Storage Solution for AI Workloads</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Wed, 26 Mar 2025 04:54:47 +0000</pubDate>
      <link>https://dev.to/pltnvs/virtualized-nfsordma-based-disaggregated-storage-solution-for-ai-workloads-3gpc</link>
      <guid>https://dev.to/pltnvs/virtualized-nfsordma-based-disaggregated-storage-solution-for-ai-workloads-3gpc</guid>
      <description>&lt;p&gt;In the fields of HPC and AI, the demand for efficient and scalable storage solutions is ever-increasing. Traditional storage systems often struggle to meet the high throughput and low latency requirements of modern AI workloads. Disaggregated storage, particularly when combined with NFSoRDMA, presents a promising solution to these challenges. This blog post will explore the objectives, performance requirements, and solutions for implementing disaggregated storage tailored for AI workloads.&lt;/p&gt;

&lt;p&gt;NFSoRDMA combines the widely adopted NFS protocol with the high-performance RDMA technology. By using standard protocols and avoiding proprietary software, we can sidestep limitations in OS compatibility and version conflicts. NFSoRDMA allows to achieve the required performance levels with minimal deployment costs, without the need for specific compatibility lists for parallel file system clients or strict version compatibility for all components. We maximize the utilization of a 400Gbit interface, demonstrating that high performance can be achieved efficiently. This integration ensures low latency and high throughput, making it ideal for our demanding storage needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Objectives
&lt;/h2&gt;

&lt;p&gt;AI workloads often demand more than just a block device. They require sophisticated file storage systems capable of handling high performance and scalability needs. Our primary objectives in developing disaggregated storage solutions include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Achieving High Throughput&lt;/strong&gt;: The goal is to reach dozens of GBps from a few clients using one or two storage nodes, whether real or virtual.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maximizing IOPS&lt;/strong&gt;: It's crucial to obtain as many small IOPS as possible to support the high-speed data processing needs of AI tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity in Configuration&lt;/strong&gt;: Keeping both hardware and software configurations as straightforward as possible is essential for ease of deployment and maintenance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Flexibility&lt;/strong&gt;: The solution must be deployable on-premise or in the cloud, offering on-demand scalability and flexibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI tasks often necessitate parallel access to data from multiple clients at speeds of tens to hundreds of gigabytes per second. Our software solutions aim to minimize complexity while ensuring high performance and scalability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtl1vs2h05260n9tvcxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtl1vs2h05260n9tvcxp.png" alt="img1" width="800" height="722"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Required disaggregated storage solution&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Performance Requirements
&lt;/h2&gt;

&lt;p&gt;For efficient cluster operations, it is essential to have fast data loading and quick checkpoint writing. These requirements are critical for maintaining high performance in AI and HPC environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyp4bncloyhqvlao0alr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyp4bncloyhqvlao0alr.jpg" alt="IMG2" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;More details here: &lt;a href="https://www.depts.ttu.edu/hpcc/events/LUG24/slides/Day2/LUG_2024_Talk_15-AI_Workload_Optimization_with_Lustre.pdf" rel="noopener noreferrer"&gt;IO for Large Language Models and Secured AI Workflows&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The provided graph above illustrates GPU utilization and Lustre read/write rates during an iterative processing cycle, common in HPC workloads. Initially, there's a brief period where the GPU utilization ramps up, known as the startup phase. This is followed by sequences of compute iterations, where GPU utilization remains high, indicating active processing. Periodically, there are drops in GPU utilization, corresponding to checkpointing phases where data is saved. During these phases, the GPUs are mostly idle, waiting for the checkpoint to complete.&lt;/p&gt;

&lt;p&gt;The Lustre read/write rates reflect this workflow with distinct phases. At the beginning, there's a significant spike in read activity during the initialization phase as the system loads initial data, which occurs only once. During compute iterations, read activity is minimal, reflecting the workload's focus on computation rather than data movement. Every few compute iterations, checkpointing occurs, causing spikes in write activity. During these phases, data is written to storage, and GPU computation is paused.&lt;/p&gt;

&lt;p&gt;Although this example is based on data from an NVIDIA presentation focused on Lustre, the underlying principles are also applicable to NFS systems. The current pattern reveals opportunities for efficiency improvements. For example, implementing parallel or asynchronous checkpointing could significantly reduce the idle time of GPUs during checkpointing phases. Our solution aims to address these inefficiencies, providing a more streamlined and effective process for handling high-throughput storage demands in HPC and AI workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  High-Level Solution Description
&lt;/h2&gt;

&lt;p&gt;Our solution integrates a high-performance storage engine with well-known filesystem services, focusing on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Software-defined RAID&lt;/strong&gt;: Deployable across various environments such as bare-metal, virtual machines, and DPUs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tuned Filesystem (FS) and Optimized Server Configuration&lt;/strong&gt;: Ensures optimal performance and efficiency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RDMA-based Interfaces for Data Access&lt;/strong&gt;: Provides the high-speed data access required for AI workloads.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main idea is to deploy different elements of the file storage system on-demand across the necessary hosts. Disaggregated storage resources are combined into virtual RAID using xiRAID Opus RAID engine, which requires minimal CPU cores. Volumes are then created and exported to virtual machines via VHOST controllers or NVMe-oF, offering flexible and scalable storage solutions.&lt;/p&gt;

&lt;p&gt;We will explore the virtualization of NFSoRDMA and xiRAID Opus, observing the limitations in the Linux kernel space and explaining how our solution can be virtualized.&lt;/p&gt;

&lt;p&gt;To validate our solution, we will utilize FIO (Flexible I/O Tester) to conduct two types of tests: sequential reads/writes to demonstrate data load and checkpoints performance, and random reads to demonstrate small data reads performance. FIO allows us to utilize various engines and regulate the load, ensuring simplicity and repeatability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Virtualized NFSoRDMA + xiRAID Opus Solution
&lt;/h2&gt;

&lt;p&gt;New virtual storage systems comprise two critical components: a high-performance engine running in user space and virtual machines that act as NAS gateways, instantiated on demand. This architecture allows efficient allocation of storage resources, balancing high performance with the scalability and flexibility required in virtualized environments.&lt;/p&gt;

&lt;p&gt;We deployed on-demand storage controllers and built virtual storage volumes for tenants from disaggregated storage resources. Deploying on-demand storage controllers and constructing virtual storage volumes from disaggregated storage resources offers each tenant its own dedicated virtual storage. This approach leverages two key components: xiRAID Opus, a high-performance block volume, and an NFS gateway. xiRAID Opus provides RAID-protected block devices tailored for virtualized environments, ensuring robust performance and reliability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzqv8xo94eeckxkqh9qiv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzqv8xo94eeckxkqh9qiv.png" alt="iMG3" width="800" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Virtualized solution architecture with on-demand storage controllers&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, performance remains a significant challenge in virtual environments, worsened by hardware and software limitations such as below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PCI slot taxation by accelerators&lt;/strong&gt;: This issue is particularly critical in cloud environments than in bare metal installations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Linux kernel updates and live patching&lt;/strong&gt;: Frequent in virtualized settings, these updates can destabilize proprietary software reliant on specific kernel versions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vhost protocol implementation&lt;/strong&gt;: Limited to 250K IOPS per volume in the kernel, this constraint consumes significant resources, hindering overall efficiency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To overcome these challenges, our solution operates the block device engine efficiently, using just 2-4 CPU cores while providing access to high-performance virtual block devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of Our Virtualized Solution
&lt;/h2&gt;

&lt;p&gt;Our virtualized storage solution includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Software RAID controller in User Space&lt;/li&gt;
&lt;li&gt;Volume manager with QoS Support&lt;/li&gt;
&lt;li&gt;Multi-threaded VHOST in User Space&lt;/li&gt;
&lt;li&gt;SR_IOV to pass NIC functions into VM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cxvr37gqrmyb8fzw90u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9cxvr37gqrmyb8fzw90u.png" alt="IMG4" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Our virtualized solution architecture&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By aggregating namespaces into virtual arrays and creating volumes with specific size and performance characteristics, we pass these devices into virtual machines. These VMs function as virtual NVMe over RDMA servers, connected to high-performance network cards, either on the same or remote hosts, and client VMs can connect directly or through a host using virtio-fs.&lt;/p&gt;

&lt;p&gt;The data path in our solution, while complex, is optimized by reducing levels and enhancing the efficiency of each. This optimization maintains compatibility with existing solutions, while reinventing or improving key components (highlighted in color) to achieve greater efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7ruy9zr3lx3rjum9gba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7ruy9zr3lx3rjum9gba.png" alt="img5" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Data flow design&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Testing Configuration
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Only two CPU cores for RAID and vhost controller&lt;/li&gt;
&lt;li&gt;24 CPU cores for NFS SERVER VM&lt;/li&gt;
&lt;li&gt;RAID 50 (8+1) x2&lt;/li&gt;
&lt;li&gt;KIOXIA CM6-R drives&lt;/li&gt;
&lt;li&gt;AMD EPYC 7702P&lt;/li&gt;
&lt;li&gt;Filesystem is aligned with RAID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We created one volume, passed it into a single VM, and applied load from two virtual clients on a remote host to evaluate performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjdw0fmhyy779c4lm5i8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcjdw0fmhyy779c4lm5i8.png" alt="img6" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Test architecture&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Testing Results
&lt;/h2&gt;

&lt;p&gt;In performance comparisons for sequential operations, mdraid shows significant performance losses, up to 50%, whereas xiRAID Opus maximizes interface read performance, achieving approximately 60% of the interface's potential for writes with one or two clients. This highlights xiRAID Opus's superior performance in virtualized environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltbp3mk6euuwqnaz2wh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltbp3mk6euuwqnaz2wh0.png" alt="graph 1" width="800" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudcvk55w9o0us3a7mwcx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fudcvk55w9o0us3a7mwcx.png" alt="graph2" width="800" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In random read operations, when using 2 clients, xiRAID Opus shows superior scalability and a significant increase in performance, reaching up to 850k-950k IOPS. In contrast, mdraid-based solutions failed to scale effectively, demonstrating kernel limitations that cap small block read performance at 200-250k IOPS per VM. Our user-space solution nearly approaches 1 million IOPS after connecting 3 clients, further highlighting the scalability and efficiency of xiRAID Opus over mdraid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ir8jjed4nyf9u9puc7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ir8jjed4nyf9u9puc7w.png" alt="graph3" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When comparing CPU load, mdraid combined with kernel vhost and a virtual machine utilizes nearly 100% of about a quarter of the CPU cores. Conversely, xiRAID Opus uses only two fully loaded cores, with around 12% of the remaining cores operating at approximately 25% load.&lt;/p&gt;

&lt;p&gt;MDRAID + NFS virtual machine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lxkis4gogw1n3yhxwnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lxkis4gogw1n3yhxwnz.png" alt="img7" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;¼ of all CPU cores are fully loaded&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;xiRAID Opus + NFS virtual machine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cx5hzcdnij786abn44a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cx5hzcdnij786abn44a.png" alt="img8" width="800" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Only 2 CPU cores are fully loaded&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Wrap-Up and Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The following conclusions highlight the significant efficiencies observed in our virtualization of NFSoRDMA and xiRAID Opus:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single virtual NFS server can saturate a 2x200 Gbit interface, performing comparably to a large server.&lt;/li&gt;
&lt;li&gt;xiRAID Opus storage engine requires only 2 CPU cores, whereas mdraid consumes much more CPU.&lt;/li&gt;
&lt;li&gt;mdraid is limited both in sequential and random operations.&lt;/li&gt;
&lt;li&gt;By virtualizing our solutions, we achieve around 60% efficiency for write operations and 100% efficiency for read operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NFS over RDMA combined with xiRAID enables the creation of fast storage nodes, providing 50 GBps performance and saturating a 400 Gbit network. This is ideal to provide fast storage to NVIDIA DGX systems at universities and large research institutions. The main ingredients for such solution are the storage engine, NFS server, and client tuning.&lt;/p&gt;

&lt;p&gt;Achieving high performance in virtual environment proves to be possible. While Linux kernel presents performance limitations, the user space-based RAID engine is the solution. It reduces resource consumption while maintaining performance, comparable to bare-metal installations. Our extensive testing and implementation of disaggregated storage based on NFSoRDMA highlight significant advancements in performance and efficiency for AI workloads.&lt;/p&gt;

&lt;p&gt;Thank you for reading! If you have any questions or thoughts, please leave them in the comments below. I’d love to hear your feedback!&lt;/p&gt;

&lt;p&gt;Original article can be found &lt;a href="https://xinnor.io/blog/virtualized-nfsordma-based-disaggregated-storage-solution-for-ai-workloads/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Appendix
&lt;/h2&gt;

&lt;h3&gt;
  
  
  NFS Settings
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Server Side&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/nfs.conf
nfs.conf
threads=32
[nfsd]
# debug=0
threads=32
rdma=y
rdma-port=20049

/etc/exports
/data *(rw,no_root_squash,sync,insecure)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Client Side&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/etc/modprobe.d/nfsclient.conf options nfs max_session_slots=180 Mount options nfsvers=3,rdma,port=20049,sync,nconnect=16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MDRAID tuning
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 24 &amp;gt; /sys/block/mdX/md/group_thread_cnt
mdadm –-grow /dev/mdX bitmap=none #gives 13GBps write but not recommended in real env
mdadm –-grow /dev/mdX --bitmap=internal --bitmap-chunk=524288. #gives 7,5 GBps write
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ZFS settings
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;zpool create -o ashift=12 test -O recordsize=1M -O compression=off -O dedup=off -O atime=off -O xattr=sa -O logbias=throughput raidz

zfs_vdev_sync_{read/write}_max_active=64
zfs_vdev_async_write_max_active=64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fio config
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
bs=1M
iodepth=32
direct=1
ioengine=libaio
rw=read/write
size=100G
[dir]
directory=/test

[global]
bs=4k
iodepth=128
direct=1
ioengine=libaio
rw=randread
size=100G
norandommap
[dir]
directory=/test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>data</category>
      <category>discuss</category>
      <category>virtualmachine</category>
    </item>
    <item>
      <title>Performance Guide Pt. 1: Performance Characteristics and How It Can Be Measured</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Mon, 24 Mar 2025 06:40:08 +0000</pubDate>
      <link>https://dev.to/pltnvs/performance-guide-pt-1-performance-characteristics-and-how-it-can-be-measured-4mi3</link>
      <guid>https://dev.to/pltnvs/performance-guide-pt-1-performance-characteristics-and-how-it-can-be-measured-4mi3</guid>
      <description>&lt;p&gt;We're excited to introduce a new blog post series focused on testing and enhancing storage performance. Throughout this series, we'll walk you through the entire process, from defining objectives and preparing the necessary hardware and software to optimizing performance using a &lt;a href="https://xinnor.io/what-is-xiraid/" rel="noopener noreferrer"&gt;software RAID&lt;/a&gt; engine. In our first blog post, we'll delve into the fundamentals of system performance, including its core components and methods for measurement.&lt;/p&gt;

&lt;p&gt;The performance of a data storage system is usually evaluated based on its inherent set of interrelated characteristics, such as data transfer bandwidth, input/output performance, etc. This approach allows for a detailed comparison among existing solutions and between the solutions and specifications provided by suppliers. It is also useful for predicting the performance of an application. The output characteristics of a system may, however, vary as the load changes. For instance, they can be influenced by factors such as the number of queues, the depth of the request queue, the size of the read and write blocks, the alignment of the blocks, the locality of requests, and the ability to compress and deduplicate data.&lt;/p&gt;

&lt;p&gt;This chapter covers data storage units, basic workload patterns, and provides instructions on how to measure and test performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Storage Units
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GBps or GiBps&lt;/strong&gt;. Data storage system transfer bandwidth measured in GB (binary or decimal). This parameter measures how much data can be processed during read and write operations per unit of time. It is typically used to evaluate the data storage system performance when dealing with large block sizes, ranging from 64kB to 8MB. This parameter is directly proportional to the following one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IOps&lt;/strong&gt;. Input/output operations per second (IOPS) is a parameter that indicates the number of requests a data storage system can process. It is typically used to evaluate the performance of a data storage system when dealing with small block sizes, ranging from 512B to 64kB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;avg lat&lt;/strong&gt;. Average latency is the waiting period for a request to be processed, measured in nanoseconds (ns), microseconds (us), and milliseconds (ms). This parameter is inversely proportional to the previous one. Sometimes, in advanced analytics, average latency is divided into submission and completion latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;99.x lat&lt;/strong&gt;. Indicates the response time for 99.x requests, where x is 5,9,95,99, etc. This parameter should be considered if the application is sensitive to latency or when using data storage system in a complex application cluster with multiple nodes involved in the processing of requests. For more complex tests, the latency distribution can also be taken into account.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CPU load&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage Utilization&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application parameters&lt;/strong&gt;: number of supported threads, transactions, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, when measuring and evaluating these parameters, it is important to consider the workload on the storage device, as it can affect its performance. The performance differs due to devices’ features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terms and Characteristics Describing the Workload Patterns
&lt;/h2&gt;

&lt;h3&gt;
  
  
  I/O
&lt;/h3&gt;

&lt;p&gt;An I/O is a single read/write request. That I/O is issued to a storage medium (like a hard drive or solid state drive).&lt;/p&gt;

&lt;h3&gt;
  
  
  I/O Request Size (block size)
&lt;/h3&gt;

&lt;p&gt;The I/O request has a size, which can vary from small (like 1 Kilobyte) to large (several megabytes). Different application workloads will issue I/O operations with varying request sizes. The size of the I/O request can impact latency and IOPS figures (two metrics we will discuss shortly).&lt;/p&gt;

&lt;h3&gt;
  
  
  Access patterns
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Sequential access
&lt;/h3&gt;

&lt;p&gt;Sequential access is a type of access where the next input/output (I/O) operation starts from the same location (address or LBA) where the previous I/O operation ended. In other words, I/O operations form a sequence of reads or writes which come sequentially, one after another.&lt;/p&gt;

&lt;p&gt;In real-life scenarios, sequential access I/O typically uses relatively large I/O sizes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Random access
&lt;/h3&gt;

&lt;p&gt;I/O requests are issued in a seemingly random pattern to the storage media. The data could be stored all over various regions of the storage media. An example of such an access pattern is a heavy utilized database server or a virtualization host running a lot of virtual machines (all operating simultaneously).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In real life pure sequential and pure random patterns rarely can be found. But usually real applications generate workload which could be close to some “pure“ patterns within a timeframe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Queue depth
&lt;/h3&gt;

&lt;p&gt;The queue depth is a number (usually between 1 and ~128) that shows how many I/O requests are queued (in-flight) on average. Having a queue is beneficial as the requests in the queue can be submitted to the storage subsystem in an optimized manner and often in parallel. A queue improves performance at the cost of latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Measure and Test Performance
&lt;/h2&gt;

&lt;p&gt;Prior to conducting any performance tests, two essential steps should be taken in order to analyze the final results correctly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Defining test objectives&lt;/li&gt;
&lt;li&gt;Setting expectations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Generally, the approach to testing should be as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Defining the objectives, forming expectations and designing a test strategy.&lt;/li&gt;
&lt;li&gt;Setting up test environment suitable for the task.&lt;/li&gt;
&lt;li&gt;Studying specifications for the hardware and evaluating the results accordingly.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Steps two and three are interlinked and usually executed at the same time. Some elements of the equipment used in testing are predetermined, while others must be chosen to ensure an optimal outcome.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Software setup.&lt;/li&gt;
&lt;li&gt;Testing individual components and removing bottlenecks.&lt;/li&gt;
&lt;li&gt;Carrying out tests.&lt;/li&gt;
&lt;li&gt;Assessing the results.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Steps 4-7 and sometimes 2 can be repeated until the desired result is achieved.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Depending on the desired outcomes, we can determine the type of testing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;System testing&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The primary objective of this testing is to comprehend the system behavior under various loading types and in different scenarios. This type of testing is most common and synthetic benchmarks like fio, vdbench, and iometer are generally used for it. During testing, parameters such as the number of threads and queue depth, read-write ratio, block size, and so on are altered. This data often provides an accurate prediction of what to expect during other testing scenarios.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Testing application performance&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is used to understand how a real application will work with storage. It acts as a tool to imitate the activity of real applications as well as launches.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Acceptance testing&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is used to determine if a new storage or modified settings of an existing one meet the project requirements. A fixed set of tests is used.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Comparative testing&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Allows to see how storages' performance differs when tested in the most similar conditions. A fixed set of tests is used.&lt;/p&gt;

&lt;p&gt;The main focus of this blog post series is system testing.&lt;/p&gt;

&lt;p&gt;Example of a test objective and expected results:&lt;/p&gt;

&lt;p&gt;Understanding the xiRAID RAID engine's capabilities for both random and sequential workloads when using a server equipped with 16 PCI-E v5 drives.&lt;/p&gt;

&lt;p&gt;Boost maximum performance levels 2 times higher than those obtained on previous generation drives.&lt;/p&gt;

&lt;p&gt;'&amp;gt;40 million IOps per read (4k block)&lt;/p&gt;

&lt;p&gt;'&amp;gt;2 million IOps per record (4k block)&lt;/p&gt;

&lt;p&gt;'&amp;gt;200Gbps per read (1Mb block)&lt;/p&gt;

&lt;p&gt;'&amp;gt;100Gbps per write (1Mb block)&lt;/p&gt;

&lt;p&gt;While running system and application performance tests, it's essential to also test the system in case of drive failure, reconstruction or if restriping and resizing. This is due to a significant decrease in array performance that might happen during these operations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Restriping refers to the process of adding an additional drive to a RAID in order to increase its volume or change its level. It involves changing the configuration of the RAID.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Tool for Testing the Drive Performance
&lt;/h2&gt;

&lt;p&gt;At present, the most preferred tool for creating a workload on drives for the Linux OS is the fio - Flexible I/O tester program. It allows custom-defining workload patterns. The standard command to run the fio program is as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# fio fio.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where "fix.cfg" is a configuration file that describes the necessary FIO startup parameters, defines the tested devices, and outlines the load patterns.&lt;/p&gt;

&lt;p&gt;Generally, this file contains one section, [global], which specifies parameters that are common to all tasks [jobs] and at least one section of the job. Most of the options can be specified both in the [global] section and in the [jobs] section.&lt;/p&gt;

&lt;p&gt;Let us consider an example of a fio configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
direct=1
ioengine=libaio
rw=randrw
rwmixread=50
iodepth=128
numjobs=2
offset_increment=2%
norandommap
time_based=1
runtime=600
random_generator=tausworthe64
group_reporting
gtod_reduce=1

[drive]
filename=/dev/nvme1n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Major fio parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;[global]&lt;/strong&gt;: [global] section start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;direct=1&lt;/strong&gt;: Enables direct I/O, bypassing the operating system's cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;bs=4k&lt;/strong&gt;: Specifies the block size for I/O operations. In this example it’s set to 4 kilobytes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ioengine=libaio&lt;/strong&gt;: Sets the I/O engine to libaio, which provides asynchronous I/O support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;rw=randrw&lt;/strong&gt;: Specifies the I/O access pattern. In this example it is set to random read/write. It allows to set the portion of the reads in the next parameter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;rwmixread=50&lt;/strong&gt;: Sets the percentage of reads in the random read/write mix. It takes different values (0, 50, 70, or 100) for separate test runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iodepth&lt;/strong&gt;=128: Determines the depth of I/O submission queue per job. It sets the maximum number of I/O requests in flight at any given time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;numjobs=2&lt;/strong&gt;: Specifies the number of parallel jobs/threads to be used during the test. Each job defined below will be launched in “numjobs“ number of threads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;offset_increment=2%&lt;/strong&gt;: Specifies offset between jobs start LBAs. The real start LBA for each thread will be offset_increment * thread_number. In this example - the offset is 2% of the target device size. It’s important to use this option at sequential patterns, since multiple threads working with the same stripes at the same time reduces the performance because of RAID engine stripe work logic and also such pattern does not reflect real tasks. For random patterns this option can be omitted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;norandommap&lt;/strong&gt;: Disables random file access mapping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;time_based=1&lt;/strong&gt;: Uses a time-based duration for the test instead of specifying the number of I/O operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;runtime=600&lt;/strong&gt;: Sets the duration of the test to 600 seconds (10 minutes).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;random_generator=tausworthe64&lt;/strong&gt;: Defines the random number generator algorithm used by FIO.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;group_reporting&lt;/strong&gt;: Enables reporting at the job group level instead of individual job level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;gtod_reduce=1&lt;/strong&gt;: Activates gettimeofday reduction, which reduces the overhead of timing-related operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;[drive]&lt;/strong&gt;: Previous section finished, job with name “drive“ starts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;filename=/dev/nvme1n1&lt;/strong&gt;: Specifies the target device or file to perform I/O operations on. In this case, it's set to the block device /dev/nvme1n1, likely an NVMe SSD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information on configuring fio can be found in the man-page of this program.&lt;/p&gt;

&lt;p&gt;Thank you for reading! If you have any questions or thoughts, please leave them in the comments below. I’d love to hear your feedback!&lt;/p&gt;

&lt;p&gt;Original article can be found &lt;a href="https://xinnor.io/blog/performance-guide-pt-1-performance-characteristics-and-how-it-can-be-measured/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>performance</category>
      <category>testing</category>
      <category>data</category>
      <category>discuss</category>
    </item>
    <item>
      <title>High-Performance, Highly Available Lustre Solution with xiRAID 4.1 on Dual-Node Shared NVMe</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Fri, 21 Mar 2025 05:28:31 +0000</pubDate>
      <link>https://dev.to/pltnvs/high-performance-highly-available-lustre-solution-with-xiraid-41-on-dual-node-shared-nvme-n6h</link>
      <guid>https://dev.to/pltnvs/high-performance-highly-available-lustre-solution-with-xiraid-41-on-dual-node-shared-nvme-n6h</guid>
      <description>&lt;p&gt;This comprehensive guide demonstrates how to create a robust, high-performance Lustre file system using xiRAID Classic 4.1 and Pacemaker on an SBB platform. We'll walk through the entire process, from system layout and hardware configuration to software installation, cluster setup, and performance tuning. By leveraging dual-ported NVMe drives and advanced clustering techniques, we'll achieve a highly available storage solution capable of delivering impressive read and write speeds. Whether you're building a new Lustre installation or looking to expand an existing one, this article provides a detailed roadmap for creating a cutting-edge, fault-tolerant parallel file system suitable for demanding high-performance computing environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  System layout
&lt;/h2&gt;

&lt;p&gt;xiRAID Classic 4.1 supports integration of RAIDs into Pacemaker-based HA-clusters. This ability allows users who require clusterization of their services to benefit from xiRAID Classic's great performance and reliability.&lt;/p&gt;

&lt;p&gt;This article describes using an NVMe SBB system (a single box with two x86-64 servers and a set of shared NVMe drives) as a basic Lustre parallel filesystem HA-cluster with data placed on clustered RAIDs based on xiRAID Classic 4.1.&lt;/p&gt;

&lt;p&gt;This article will familiarize you with how to deploy xiRAID Classic for a real-life task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lustre server SBB Platform
&lt;/h2&gt;

&lt;p&gt;We will use Viking VDS2249R as the SBB platform. The configuration details are presented in the table below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74guc2omfkzq3qqxd3m1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74guc2omfkzq3qqxd3m1.jpg" alt="Image1" width="666" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Viking VDS2249R&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Node 0&lt;/th&gt;
&lt;th&gt;Node 1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hostname&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;node26&lt;/td&gt;
&lt;td&gt;node27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CPU&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AMD EPYC 7713P 64-Core&lt;/td&gt;
&lt;td&gt;AMD EPYC 7713P 64-Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;256GB&lt;/td&gt;
&lt;td&gt;256GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OS drives&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2 x Samsung SSD 970 EVO Plus 250GB mirrored&lt;/td&gt;
&lt;td&gt;2 x Samsung SSD 970 EVO Plus 250GB mirrored&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rocky Linux 8.9&lt;/td&gt;
&lt;td&gt;Rocky Linux 8.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IPMI address&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;192.168.64.106&lt;/td&gt;
&lt;td&gt;192.168.67.23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IPMI login&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;admin&lt;/td&gt;
&lt;td&gt;admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IPMI password&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;admin&lt;/td&gt;
&lt;td&gt;admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Management NIC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;enp194s0f0: 192.168.65.26/24&lt;/td&gt;
&lt;td&gt;enp194s0f0: 192.168.65.27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cluster Heartbeat NIC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;enp194s0f1: 10.10.10.1&lt;/td&gt;
&lt;td&gt;enp194s0f1: 10.10.10.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infiniband LNET HDR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ib0: 100.100.100.26&lt;/td&gt;
&lt;td&gt;ib0: 100.100.100.27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;ib3: 100.100.100.126&lt;/td&gt;
&lt;td&gt;ib3: 100.100.100.127&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NVMes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24 x Kioxia CM6-R 3.84Tb KCM61RUL3T8&lt;/td&gt;
&lt;td&gt;24 x Kioxia CM6-R 3.84Tb KCM61RUL3T8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  System configuration and tuning
&lt;/h2&gt;

&lt;p&gt;Before software installation and configuration, we need to prepare the platform to provide optimal performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance tuning
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tuned-adm profile accelerator-performance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Network configuration
&lt;/h2&gt;

&lt;p&gt;Check that all IP addresses are resolvable from both hosts. In our case, we will use resolving via the hosts file, so we have the following content in /etc/hosts on both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.65.26 node26
192.168.65.27 node27
10.10.10.1 node26-ic
10.10.10.2 node27-ic
192.168.64.50 node26-ipmi
192.168.64.76 node27-ipmi
100.100.100.26 node26-ib
100.100.100.27 node27-ib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Policy-based routing setup
&lt;/h2&gt;

&lt;p&gt;We use a multirail configuration on the servers: two IB interfaces on each server are configured to work in the same IPv4 networks. To make the Linux IP stack work properly in this configuration, we need to set up policy-based routing on both servers for these interfaces.&lt;/p&gt;

&lt;p&gt;node26 setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# nmcli connection modify ib0 ipv4.route-metric 100
node26# nmcli connection modify ib3 ipv4.route-metric 101
node26# nmcli connection modify ib0 ipv4.routes "100.100.100.0/24 src=100.100.100.26 table=100"
node26# nmcli connection modify ib0 ipv4.routing-rules "priority 101 from 100.100.100.26 table 100"
node26# nmcli connection modify ib3 ipv4.routes "100.100.100.0/24 src=100.100.100.126 table=200"
node26# nmcli connection modify ib3 ipv4.routing-rules "priority 102 from 100.100.100.126 table 200"
node26# nmcli connection up ib0
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6)
node26# nmcli connection up ib3
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/7)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;node27 setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# nmcli connection modify ib0 ipv4.route-metric 100
node27# nmcli connection modify ib3 ipv4.route-metric 101
node27# nmcli connection modify ib0 ipv4.routes "100.100.100.0/24 src=100.100.100.27 table=100"
node27# nmcli connection modify ib0 ipv4.routing-rules "priority 101 from 100.100.100.27 table 100"
node27# nmcli connection modify ib3 ipv4.routes "100.100.100.0/24 src=100.100.100.127 table=200"
node27# nmcli connection modify ib3 ipv4.routing-rules "priority 102 from 100.100.100.127 table 200"
node27# nmcli connection up ib0
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6)
node26# nmcli connection up ib3
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/7)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  NVMe drives setup
&lt;/h2&gt;

&lt;p&gt;In the SBB system, we have 24 Kioxia CM6-R 3.84TB KCM61RUL3T84 drives. They are PCIe 4.0, dual-ported, read-intensive drives with 1DWPD endurance. A single drive's performance can theoretically reach up to 6.9GB/s for sequential read and 4.2GB/s for sequential write (according to the vendor specification).&lt;/p&gt;

&lt;p&gt;In our setup, we plan to create a simple Lustre installation with sufficient performance. However, since each NVMe in the SBB system is connected to each server with only 2 PCIe lanes, the NVMe drives' performance will be limited. To overcome this limitation, we will create 2 namespaces on each NVMe drive, which will be used for the Lustre OST RAIDs, and create separate RAIDs from the first NVMe namespaces and the second NVMe namespaces. By configuring our cluster software to use the RAIDs made from the first namespaces (and their Lustre servers) on Lustre node #0 and the RAIDs created from the second namespaces on node #1, we will be able to utilize all four PCIe lanes for each NVMe used to store OST data, as Lustre itself will distribute the workload among all OSTs.&lt;/p&gt;

&lt;p&gt;Since we are deploying a simple Lustre installation, we will use a simple filesystem scheme with just one metadata server. As we will have only one metadata server, we will need only one RAID for the metadata. Because of this, we will not create two namespaces on the drives used for the MDT RAID.&lt;/p&gt;

&lt;p&gt;Here is how the NVMe drive configuration looks initially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nvme list
Node                  SN                   Model                                    Namespace Usage                      Format           FW Rev
--------------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1          21G0A046T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme1n1          21G0A04BT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme10n1         21G0A04ET2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme11n1         21G0A045T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme12n1         S59BNM0R702322Z      Samsung SSD 970 EVO Plus 250GB           1           8.67  GB / 250.06  GB    512   B +  0 B   2B2QEXM7
/dev/nvme13n1         21G0A04KT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme14n1         21G0A047T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme15n1         21G0A04CT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme16n1         11U0A00KT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme17n1         21G0A04JT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme18n1         21G0A048T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme19n1         S59BNM0R702439A      Samsung SSD 970 EVO Plus 250GB           1         208.90  kB / 250.06  GB    512   B +  0 B   2B2QEXM7
/dev/nvme2n1          21G0A041T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme20n1         21G0A03TT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme21n1         21G0A04FT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme22n1         21G0A03ZT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme23n1         21G0A04DT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme24n1         21G0A03VT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme25n1         21G0A044T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme3n1          21G0A04GT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme4n1          21G0A042T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme5n1          21G0A04HT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme6n1          21G0A049T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme7n1          21G0A043T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme8n1          21G0A04AT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme9n1          21G0A03XT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Samsung drives are used for the operating system installation.&lt;/p&gt;

&lt;p&gt;Let's reserve /dev/nvme0 and /dev/nvme1 drives for the metadata RAID1. Currently, xiRAID does not support spare pools in a cluster configuration, but having a spare drive is really useful for quick manual drive replacement. So, let's also reserve /dev/nvme3 to be a spare for the RAID1 drive and split all other KCM61RUL3T84 drives into 2 namespaces.&lt;/p&gt;

&lt;p&gt;Let’s take /dev/nvme4 as an example. All other drives will be splited in absolutely the same way.&lt;/p&gt;

&lt;p&gt;Check the maximum possible size of the drive to be sure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nvme id-ctrl /dev/nvme4 | grep -i tnvmcap
tnvmcap : 3840755982336
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the maximal number of the namespaces supported by the drive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nvme id-ctrl /dev/nvme4 | grep ^nn
nn : 64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the controller used for the drive connection at both servers (they will differ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# nvme id-ctrl /dev/nvme4 | grep ^cntlid
cntlid : 0x1

node26# nvme id-ctrl /dev/nvme4 | grep ^cntlid
cntlid : 0x2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to calculate the size of the namespaces we are going to create. The real size of the drive in 4K blocks is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3840755982336/4096=937684566
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, each namespace size in 4K blocks will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;937684566/2=468842283
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In fact, it is not possible to create 2 namespaces of exactly this size because of the NVMe internal architecture. So, we will create namespaces of 468700000 blocks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are building a system for write-intensive tasks, we recommend using write-intensive drives with 3DWPD endurance. If that is not possible and you have to use read-optimized drives, consider leaving some space (10-25%) of the NVMe volume unallocated by namespaces. In many cases, this helps turn the NVMe behavior in terms of write performance degradation closer to that of write-intensive drives.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a first step, remove the existing namespace on one of the nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# nvme delete-ns /dev/nvme4 -n 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, create namespaces on the same node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# nvme create-ns /dev/nvme4 --nsze=468700000 --ncap=468700000 -b=4096 --dps=0 -m 1
create-ns: Success, created nsid:1
node26# nvme create-ns /dev/nvme4 --nsze=468700000 --ncap=468700000 -b=4096 --dps=0 -m 1
create-ns: Success, created nsid:2
node26# nvme attach-ns /dev/nvme4 --namespace-id=1 -controllers=0x2
attach-ns: Success, nsid:1
node26# nvme attach-ns /dev/nvme4 --namespace-id=2 -controllers=0x2
attach-ns: Success, nsid:2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Attach the namespaces on the second node with the proper controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# nvme attach-ns /dev/nvme4 --namespace-id=1 -controllers=0x1
attach-ns: Success, nsid:1
node27# nvme attach-ns /dev/nvme4 --namespace-id=2 -controllers=0x1
attach-ns: Success, nsid:2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like this on both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nvme list |grep nvme4
/dev/nvme4n1          21G0A042T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme4n2          21G0A042T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All other drives were split in the same way. Here is the resulting configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nvme list
Node                  SN                   Model                                    Namespace Usage                      Format           FW Rev
--------------------- -------------------- ---------------------------------------- --------- -------------------------- ---------------- --------
/dev/nvme0n1          21G0A046T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme1n1          21G0A04BT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme10n1         21G0A04ET2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme10n2         21G0A04ET2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme11n1         21G0A045T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme11n2         21G0A045T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme12n1         S59BNM0R702322Z      Samsung SSD 970 EVO Plus 250GB           1           8.67  GB / 250.06  GB    512   B +  0 B   2B2QEXM7
/dev/nvme13n1         21G0A04KT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme13n2         21G0A04KT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme14n1         21G0A047T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme14n2         21G0A047T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme15n1         21G0A04CT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme15n2         21G0A04CT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme16n1         11U0A00KT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme16n2         11U0A00KT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme17n1         21G0A04JT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme17n2         21G0A04JT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme18n1         21G0A048T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme18n2         21G0A048T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme19n1         S59BNM0R702439A      Samsung SSD 970 EVO Plus 250GB           1         208.90  kB / 250.06  GB    512   B +  0 B   2B2QEXM7
/dev/nvme2n1          21G0A041T2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme20n1         21G0A03TT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme20n2         21G0A03TT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme21n1         21G0A04FT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme21n2         21G0A04FT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme22n1         21G0A03ZT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme22n2         21G0A03ZT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme23n1         21G0A04DT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme23n2         21G0A04DT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme24n1         21G0A03VT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme24n2         21G0A03VT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme25n1         21G0A044T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme25n2         21G0A044T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme3n1          21G0A04GT2G8         KCM61RUL3T84                             1           0.00   B /   3.84  TB      4 KiB +  0 B   0106
/dev/nvme4n1          21G0A042T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme4n2          21G0A042T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme5n1          21G0A04HT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme5n2          21G0A04HT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme6n1          21G0A049T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme6n2          21G0A049T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme7n1          21G0A043T2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme7n2          21G0A043T2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme8n1          21G0A04AT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme8n2          21G0A04AT2G8         KCM61RUL3T84                             2           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme9n1          21G0A03XT2G8         KCM61RUL3T84                             1           0.00   B /   1.92  TB      4 KiB +  0 B   0106
/dev/nvme9n2          21G0A03XT2G8         KCM61RUL3T84  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Software components installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Lustre installation
&lt;/h3&gt;

&lt;p&gt;Create Lustre repo file /etc/yum.repos.d/lustre-repo.repo :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lustre-server]
name=lustre-server
baseurl=https://downloads.whamcloud.com/public/lustre/latest-release/el8.9/server
# exclude=*debuginfo*
gpgcheck=0

[lustre-client]
name=lustre-client
baseurl=https://downloads.whamcloud.com/public/lustre/latest-release/el8.9/client
# exclude=*debuginfo*
gpgcheck=0

[e2fsprogs-wc]
name=e2fsprogs-wc
baseurl=https://downloads.whamcloud.com/public/e2fsprogs/latest/el8
# exclude=*debuginfo*
gpgcheck=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installing e2fs tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yum --nogpgcheck --disablerepo=* --enablerepo=e2fsprogs-wc install e2fsprogs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installing Lustre kernel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yum --nogpgcheck --disablerepo=baseos,extras,updates --enablerepo=lustre-server install kernel kernel-devel kernel-headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reboot to the new kernel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the kernel version after reboot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# uname -a
Linux node26 4.18.0-513.9.1.el8_lustre.x86_64 #1 SMP Sat Dec 23 05:23:32 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installing lustre server components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yum --nogpgcheck --enablerepo=lustre-server,ha install kmod-lustre kmod-lustre-osd-ldiskfs lustre-osd-ldiskfs-mount lustre lustre-resource-agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check Lustre module load:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[root@node26 ~]# modprobe -v lustre
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/net/libcfs.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/net/lnet.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/obdclass.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/ptlrpc.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/fld.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/fid.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/osc.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/lov.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/mdc.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/lmv.ko
insmod /lib/modules/4.18.0-513.9.1.el8_lustre.x86_64/extra/lustre/fs/lustre.ko
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unload modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# lustre_rmmod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installing xiRAID Classic 4.1
&lt;/h2&gt;

&lt;p&gt;Installing xiRAID Classic 4.1 at both nodes from the repositories following the Xinnor xiRAID 4.1.0 Installation Guide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum install -y epel-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum install https://pkg.xinnor.io/repository/Repository/xiraid/el/8/kver-4.18/xiraid-repo-1.1.0-446.kver.4.18.noarch.rpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum install xiraid-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pacemaker installation&lt;br&gt;
Running the following steps at both nodes:&lt;/p&gt;

&lt;p&gt;Enable cluster repo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum config-manager --set-enabled ha appstream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installing cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum install pcs pacemaker psmisc policycoreutils-python3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Csync2 installation
&lt;/h2&gt;

&lt;p&gt;Since we are installing the system on Rocky Linux 8, there is no need to compile Csync2 from sources ourselves. Just install the Csync2 package from the Xinnor repository on both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum install csync2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  NTP server installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum install chrony
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  HA cluster setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Time synchronisation setup
&lt;/h3&gt;

&lt;p&gt;Modify /etc/chrony.conf file if needed to setup working with proper NTP servers. At this setup we will work with the default settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# systemctl enable --now chronyd.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify, that time sync works properly by running chronyc tracking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pacemaker cluster creation
&lt;/h2&gt;

&lt;p&gt;In this chapter, the cluster configuration is described. In our cluster, we use a dedicated network to create a cluster interconnect. This network is physically created as a single direct connection (by dedicated Ethernet cable without any switch) between enp194s0f1 interfaces on the servers. The cluster interconnect is a very important component of any HA-cluster, and its reliability should be high. A Pacemaker-based cluster can be configured with two cluster interconnect networks for improved reliability through redundancy. While in our configuration we will use a single network configuration, please consider using a dual network interconnect for your projects if needed.&lt;/p&gt;

&lt;p&gt;Set the firewall to allow pacemaker software to work (on both nodes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# firewall-cmd --add-service=high-availability
# firewall-cmd --permanent --add-service=high-availability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set the same password for the hacluster user at both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# passwd hacluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the cluster software at both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# systemctl start pcsd.service
# systemctl enable pcsd.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Authenticate the cluster nodes from one node by their interconnect interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs host auth node26-ic node27-ic -u hacluster
Password:
node26-ic: Authorized
node27-ic: Authorized
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create and start the cluster (start at one node):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs cluster setup lustrebox0 node26-ic node27-ic
No addresses specified for host 'node26-ic', using 'node26-ic'
No addresses specified for host 'node27-ic', using 'node27-ic'
Destroying cluster on hosts: 'node26-ic', 'node27-ic'...
node26-ic: Successfully destroyed cluster
node27-ic: Successfully destroyed cluster
Requesting remove 'pcsd settings' from 'node26-ic', 'node27-ic'
node26-ic: successful removal of the file 'pcsd settings'
node27-ic: successful removal of the file 'pcsd settings'
Sending 'corosync authkey', 'pacemaker authkey' to 'node26-ic', 'node27-ic'
node26-ic: successful distribution of the file 'corosync authkey'
node26-ic: successful distribution of the file 'pacemaker authkey'
node27-ic: successful distribution of the file 'corosync authkey'
node27-ic: successful distribution of the file 'pacemaker authkey'
Sending 'corosync.conf' to 'node26-ic', 'node27-ic'
node26-ic: successful distribution of the file 'corosync.conf'
node27-ic: successful distribution of the file 'corosync.conf'
Cluster has been successfully set up.

node26# pcs cluster start --all
node26-ic: Starting Cluster...
node27-ic: Starting Cluster...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the current cluster status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs status
Cluster name: lustrebox0

WARNINGS:
No stonith devices and stonith-enabled is not false

Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node27-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Fri Jul 12 20:55:53 2024 on node26-ic
  * Last change:  Fri Jul 12 20:55:12 2024 by hacluster via hacluster on node27-ic
  * 2 nodes configured
  * 0 resource instances configured

Node List:
  * Online: [ node26-ic node27-ic ]

Full List of Resources:
  * No resources

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fencing setup
&lt;/h2&gt;

&lt;p&gt;It's very important to have properly configured and working fencing (STONITH) in any HA cluster that works with shared storage devices. In our case, the shared devices are all the NVMe namespaces we created earlier. The fencing (STONITH) design should be developed and implemented by the cluster administrator in consideration of the system's abilities and architecture. In this system, we will use fencing via IPMI. Anyway, when designing and deploying your own cluster, please choose the fencing configuration on your own, considering all the possibilities, limitations, and risks.&lt;/p&gt;

&lt;p&gt;First of all, let's check the list of installed fencing agents in our system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs stonith list
fence_watchdog - Dummy watchdog fence agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we don’t have the IPMI fencing agent installed at our cluster nodes. To install it, run the following command (at both nodes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# yum install fence-agents-ipmilan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may check the IPMI fencing agent options description by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pcs stonith describe fence_ipmilan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding the fencing resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs stonith create node27.stonith fence_ipmilan ip="192.168.67.23" auth=password password="admin" username="admin" method="onoff" lanplus=true pcmk_host_list="node27-ic" pcmk_host_check=static-list op monitor interval=10s
node26# pcs stonith create node26.stonith fence_ipmilan ip="192.168.64.106" auth=password password="admin" username="admin" method="onoff" lanplus=true pcmk_host_list="node26-ic" pcmk_host_check=static-list op monitor interval=10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Preventing the STONITH resources from start on the node it should kill:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs constraint location node27.stonith avoids node27-ic=INFINITY
node26# pcs constraint location node26.stonith avoids node26-ic=INFINITY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Csync2 configuration
&lt;/h2&gt;

&lt;p&gt;Configure firewall to allow Csync2 to work (run at both nodes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# firewall-cmd --add-port=30865/tcp
# firewall-cmd --permanent --add-port=30865/tcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the Csync2 configuration file /usr/local/etc/csync2.cfg with the following content at node26 only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nossl * *;
group csxiha {
host node26;
host node27;
key /usr/local/etc/csync2.key_ha;
include /etc/xiraid/raids; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate the key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# csync2 -k /usr/local/etc/csync2.key_ha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the config and the key file to the second node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# scp /usr/local/etc/csync2.cfg /usr/local/etc/csync2.key_ha node27:/usr/local/etc/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Csync2 synchronisation by schedule one time per minute run crontab -e at both nodes and add the following record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * * /usr/local/sbin/csync2 -x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also for asynchronous synchronisation run the following command to create a synchronisation script (repeat the script creation procedure at both nodes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# vi /etc/xiraid/config_update_handler.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fill the created script with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/bash
/usr/local/sbin/csync2 -xv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file.&lt;/p&gt;

&lt;p&gt;After that run the following command to set correct permissions for the script file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# chmod +x /etc/xiraid/config_update_handler.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  xiRAID Configuration for cluster setup
&lt;/h2&gt;

&lt;p&gt;Disable RAID autostart to prevent RAIDs from being activated by xiRAID itself during a node boot. In a cluster configuration, RAIDs have to be activated by Pacemaker via cluster resources. Run the following command on both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# xicli settings cluster modify --raid_autostart 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make xiRAID Classic 4.1 resource agent visible for Pacemaker (run command this sequence at both nodes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# mkdir -p /usr/lib/ocf/resource.d/xraid
# ln -s /etc/xraid/agents/raid /usr/lib/ocf/resource.d/xraid/raid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  xiRAID RAIDs creation
&lt;/h2&gt;

&lt;p&gt;To be able to create RAIDs, we need to install licenses for xiRAID Classic 4.1 on both hosts first. The licenses should be received from Xinnor. To generate the licenses, Xinnor requires the output of the xicli license show command (from both nodes).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# xicli license show
Kernel version: 4.18.0-513.9.1.el8_lustre.x86_64

hwkey: B8828A09E09E8F48
license_key: null
version: 0
crypto_version: 0
created: 0-0-0
expired: 0-0-0
disks: 4
levels: 0
type: nvme
disks_in_use: 2
status: trial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The license files received from Xinnor needs to be installed by xicli license update -p  command (once again, at both nodes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# xicli license show
Kernel version: 4.18.0-513.9.1.el8_lustre.x86_64

hwkey: B8828A09E09E8F48
license_key: 0F5A4B87A0FC6DB7544EA446B1B4AF5F34A08169C44E5FD119CE6D2352E202677768ECC78F56B583DABE11698BBC800EC96E556AA63E576DAB838010247678E7E3B95C7C4E3F592672D06C597045EAAD8A42CDE38C363C533E98411078967C38224C9274B862D45D4E6DED70B7E34602C80B60CBA7FDE93316438AFDCD7CBD23
version: 1
crypto_version: 1
created: 2024-7-16
expired: 2024-9-30
disks: 600
levels: 70
type: nvme
disks_in_use: 2
status: valid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we plan to deploy a small Lustre installation, combining MGT and MDT on the same target device is absolutely OK. But for medium or large Lustre installations, it's better to use a separate target (and RAID) for MGT.&lt;/p&gt;

&lt;p&gt;Here is the list of the RAIDs we need to create.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;RAID Name&lt;/th&gt;
&lt;th&gt;RAID Level&lt;/th&gt;
&lt;th&gt;Number of devices&lt;/th&gt;
&lt;th&gt;Strip size&lt;/th&gt;
&lt;th&gt;Drive list&lt;/th&gt;
&lt;th&gt;Lustre target&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;r_mdt0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;/dev/nvme0n1 /dev/nvme1n1&lt;/td&gt;
&lt;td&gt;MGT + MDT index=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost0&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;/dev/nvme4n1 /dev/nvme5n1 /dev/nvme6n1 /dev/nvme7n1 /dev/nvme8n1 /dev/nvme9n1 /dev/nvme10n1 /dev/nvme11n1 /dev/nvme13n1 /dev/nvme14n1&lt;/td&gt;
&lt;td&gt;OST index=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost1&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;/dev/nvme4n2 /dev/nvme5n2 /dev/nvme6n2 /dev/nvme7n2 /dev/nvme8n2 /dev/nvme9n2 /dev/nvme10n2 /dev/nvme11n2 /dev/nvme13n2 /dev/nvme14n2&lt;/td&gt;
&lt;td&gt;OST index=1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost2&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;/dev/nvme15n1 /dev/nvme16n1 /dev/nvme17n1 /dev/nvme18n1 /dev/nvme20n1 /dev/nvme21n1 /dev/nvme22n1 /dev/nvme23n1 /dev/nvme24n1 /dev/nvme25n1&lt;/td&gt;
&lt;td&gt;OST index=2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost3&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;/dev/nvme15n2 /dev/nvme16n2 /dev/nvme17n2 /dev/nvme18n2 /dev/nvme20n2 /dev/nvme21n2 /dev/nvme22n2 /dev/nvme23n2 /dev/nvme24n2 /dev/nvme25n2&lt;/td&gt;
&lt;td&gt;OST index=3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Creating all the RAIDs at the first node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# xicli raid create -n r_mdt0 -l 1 -d /dev/nvme0n1 /dev/nvme1n1
node26# xicli raid create -n r_ost0 -l 6 -ss 128 -d /dev/nvme4n1 /dev/nvme5n1 /dev/nvme6n1 /dev/nvme7n1 /dev/nvme8n1 /dev/nvme9n1 /dev/nvme10n1 /dev/nvme11n1 /dev/nvme13n1 /dev/nvme14n1
node26# xicli raid create -n r_ost1 -l 6 -ss 128 -d /dev/nvme4n2 /dev/nvme5n2 /dev/nvme6n2 /dev/nvme7n2 /dev/nvme8n2 /dev/nvme9n2 /dev/nvme10n2 /dev/nvme11n2 /dev/nvme13n2 /dev/nvme14n2
node26# xicli raid create -n r_ost2 -l 6 -ss 128 -d /dev/nvme15n1 /dev/nvme16n1 /dev/nvme17n1 /dev/nvme18n1 /dev/nvme20n1 /dev/nvme21n1 /dev/nvme22n1 /dev/nvme23n1 /dev/nvme24n1 /dev/nvme25n1
node26# xicli raid create -n r_ost3 -l 6 -ss 128 -d /dev/nvme15n2 /dev/nvme16n2 /dev/nvme17n2 /dev/nvme18n2 /dev/nvme20n2 /dev/nvme21n2 /dev/nvme22n2 /dev/nvme23n2 /dev/nvme24n2 /dev/nvme25n2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this stage, there is no need to wait for the RAIDs initialization to finish - it can be safely left to run in the background.&lt;/p&gt;

&lt;p&gt;Checking the RAID statuses at the first node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ode26# xicli raid show
╔RAIDs═══╦══════════════════╦═════════════╦════════════════════════╦═══════════════════╗
║ name   ║ static           ║ state       ║ devices                ║ info              ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_mdt0 ║ size: 3576 GiB   ║ online      ║ 0 /dev/nvme0n1 online  ║                   ║
║        ║ level: 1         ║ initialized ║ 1 /dev/nvme1n1 online  ║                   ║
║        ║ strip_size: 16   ║             ║                        ║                   ║
║        ║ block_size: 4096 ║             ║                        ║                   ║
║        ║ sparepool: -     ║             ║                        ║                   ║
║        ║ active: True     ║             ║                        ║                   ║
║        ║ config: True     ║             ║                        ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost0 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n1 online  ║ init_progress: 11 ║
║        ║ level: 6         ║ initing     ║ 1 /dev/nvme5n1 online  ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n1 online  ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n1 online  ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n1 online  ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n1 online  ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n1 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme11n1 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme13n1 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme14n1 online ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost1 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n2 online  ║ init_progress: 7  ║
║        ║ level: 6         ║ initing     ║ 1 /dev/nvme5n2 online  ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n2 online  ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n2 online  ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n2 online  ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n2 online  ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n2 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme11n2 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme13n2 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme14n2 online ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost2 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n1 online ║ init_progress: 5  ║
║        ║ level: 6         ║ initing     ║ 1 /dev/nvme16n1 online ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n1 online ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n1 online ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n1 online ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n1 online ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n1 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme23n1 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme24n1 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme25n1 online ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost3 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n2 online ║ init_progress: 2  ║
║        ║ level: 6         ║ initing     ║ 1 /dev/nvme16n2 online ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n2 online ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n2 online ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n2 online ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n2 online ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n2 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme23n2 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme24n2 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme25n2 online ║                   ║
╚════════╩══════════════════╩═════════════╩════════════════════════╩═══════════════════╝
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking that the RAID configs were successfully replicated to the second node (please note that on the second node, the RAID status is None, which is expected in this case):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# xicli raid show
╔RAIDs═══╦══════════════════╦═══════╦═════════╦══════╗
║ name   ║ static           ║ state ║ devices ║ info ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_mdt0 ║ size: 3576 GiB   ║ None  ║         ║      ║
║        ║ level: 1         ║       ║         ║      ║
║        ║ strip_size: 16   ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost0 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost1 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost2 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost3 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╚════════╩══════════════════╩═══════╩═════════╩══════╝
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After RAID creation, there's no need to wait for RAID initialization to finish. The RAIDs are available for use immediately after creation, albeit with slightly reduced performance.&lt;/p&gt;

&lt;p&gt;For optimal performance, it's better to dedicate specific disjoint CPU core sets to each RAID. Currently, all RAIDs are active on node26, so the sets will joint, but when they are spread between node26 and node27, they will not joint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# xicli raid modify -n r_mdt0 -ca 0-7 -se 1
node26# xicli raid modify -n r_ost0 -ca 8-67 -se 1
node26# xicli raid modify -n r_ost1 -ca 8-67 -se 1 # will be running at node27
node26# xicli raid modify -n r_ost2 -ca 68-127 -se 1
node26# xicli raid modify -n r_ost3 -ca 68-127 -se 1 # will be running at node27
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lustre setup
&lt;/h2&gt;

&lt;h2&gt;
  
  
  LNET configuration
&lt;/h2&gt;

&lt;p&gt;To make lustre working, we need to configure Lustre network stack (LNET).&lt;/p&gt;

&lt;p&gt;Run at both nodes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# systemctl start lnet
# systemctl enable lnet
# lnetctl net add --net o2ib0 --if ib0
# lnetctl net add --net o2ib0 --if ib3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# lnetctl net show -v
net:
    - net type: lo
      local NI(s):
        - nid: 0@lo
          status: up
          statistics:
              send_count: 289478
              recv_count: 289474
              drop_count: 4
          tunables:
              peer_timeout: 0
              peer_credits: 0
              peer_buffer_credits: 0
              credits: 0
          lnd tunables:
          dev cpt: 0
          CPT: "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]"
    - net type: o2ib
      local NI(s):
        - nid: 100.100.100.26@o2ib
          status: down
          interfaces:
              0: ib0
          statistics:
              send_count: 213607
              recv_count: 213604
              drop_count: 7
          tunables:
              peer_timeout: 180
              peer_credits: 8
              peer_buffer_credits: 0
              credits: 256
          lnd tunables:
              peercredits_hiw: 4
              map_on_demand: 1
              concurrent_sends: 8
              fmr_pool_size: 512
              fmr_flush_trigger: 384
              fmr_cache: 1
              ntx: 512
              conns_per_peer: 1
          dev cpt: -1
          CPT: "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]"
        - nid: 100.100.100.126@o2ib
          status: up
          interfaces:
              0: ib3
          statistics:
              send_count: 4
              recv_count: 4
              drop_count: 0
          tunables:
              peer_timeout: 180
              peer_credits: 8
              peer_buffer_credits: 0
              credits: 256
          lnd tunables:
              peercredits_hiw: 4
              map_on_demand: 1
              concurrent_sends: 8
              fmr_pool_size: 512
              fmr_flush_trigger: 384
              fmr_cache: 1
              ntx: 512
              conns_per_peer: 1
          dev cpt: -1
          CPT: "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please pay attention to the LNET at the hosts - NIDs. We will use 100.100.100.26@o2ib for node26 and 100.100.100.27@o2ib for node27 as primary NIDs.&lt;/p&gt;

&lt;p&gt;Save the LNET configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# lnetctl export -b &amp;gt; /etc/lnet.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  LDISKFS filesystems creation
&lt;/h2&gt;

&lt;p&gt;At this step, we format the RAIDs into LDISKFS filesystem format. During formatting, we specify the target type (--mgs/--mdt/--ost), unique number of the specific target type (--index), Lustre filesystem name (--fsname), NIDs where each target filesystem could be mounted and where the corresponding servers will get started automatically (--servicenode), and NIDs where MGS could be found (--mgsnode).&lt;/p&gt;

&lt;p&gt;Since our RAIDs will work within a cluster, we specify NIDs of both server nodes as the NIDs where the target filesystem could be mounted and where the corresponding servers will get started automatically for each target filesystem. For the same reason, we specify two NIDs where other servers should look for the MGS service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# mkfs.lustre --mgs --mdt --fsname=lustre0 --index=0 --servicenode=100.100.100.26@o2ib --servicenode=100.100.100.27@o2ib --mgsnode=100.100.100.26@o2ib --mgsnode=100.100.100.27@o2ib /dev/xi_r_mdt0
node26# mkfs.lustre --ost --fsname=lustre0 --index=0 --servicenode=100.100.100.26@o2ib --servicenode=100.100.100.27@o2ib --mgsnode=100.100.100.26@o2ib --mgsnode=100.100.100.27@o2ib /dev/xi_r_ost0
node26# mkfs.lustre --ost --fsname=lustre0 --index=1 --servicenode=100.100.100.26@o2ib --servicenode=100.100.100.27@o2ib --mgsnode=100.100.100.26@o2ib --mgsnode=100.100.100.27@o2ib /dev/xi_r_ost1
node26# mkfs.lustre --ost --fsname=lustre0 --index=2 --servicenode=100.100.100.26@o2ib --servicenode=100.100.100.27@o2ib --mgsnode=100.100.100.26@o2ib --mgsnode=100.100.100.27@o2ib /dev/xi_r_ost2
node26# mkfs.lustre --ost --fsname=lustre0 --index=3 --servicenode=100.100.100.26@o2ib --servicenode=100.100.100.27@o2ib --mgsnode=100.100.100.26@o2ib --mgsnode=100.100.100.27@o2ib /dev/xi_r_ost3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More details could be found in the Lustre documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cluster resources creation
&lt;/h2&gt;

&lt;p&gt;Please check the table below. The configuration to configure is described in the table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;RAID name&lt;/th&gt;
&lt;th&gt;HA cluster RAID resource name&lt;/th&gt;
&lt;th&gt;Lustre target&lt;/th&gt;
&lt;th&gt;Mountpoint&lt;/th&gt;
&lt;th&gt;HA cluster filesystem resource name&lt;/th&gt;
&lt;th&gt;Preferred cluster node&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;r_mdt0&lt;/td&gt;
&lt;td&gt;rr_mdt0&lt;/td&gt;
&lt;td&gt;MGT + MDT index=0&lt;/td&gt;
&lt;td&gt;/lustre_t/mdt0&lt;/td&gt;
&lt;td&gt;fsr_mdt0&lt;/td&gt;
&lt;td&gt;node26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost0&lt;/td&gt;
&lt;td&gt;rr_ost0&lt;/td&gt;
&lt;td&gt;OST index=0&lt;/td&gt;
&lt;td&gt;/lustre_t/ost0&lt;/td&gt;
&lt;td&gt;fsr_ost0&lt;/td&gt;
&lt;td&gt;node26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost1&lt;/td&gt;
&lt;td&gt;rr_ost1&lt;/td&gt;
&lt;td&gt;OST index=1&lt;/td&gt;
&lt;td&gt;/lustre_t/ost1&lt;/td&gt;
&lt;td&gt;fsr_ost1&lt;/td&gt;
&lt;td&gt;node27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost2&lt;/td&gt;
&lt;td&gt;rr_ost2&lt;/td&gt;
&lt;td&gt;OST index=2&lt;/td&gt;
&lt;td&gt;/lustre_t/ost2&lt;/td&gt;
&lt;td&gt;fsr_ost2&lt;/td&gt;
&lt;td&gt;node26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;r_ost3&lt;/td&gt;
&lt;td&gt;rr_ost3&lt;/td&gt;
&lt;td&gt;OST index=3&lt;/td&gt;
&lt;td&gt;/lustre_t/ost3&lt;/td&gt;
&lt;td&gt;fsr_ost3&lt;/td&gt;
&lt;td&gt;node27&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To create Pacemaker resources for xiRAID Classic RAIDs, we will use the xiRAID resource agent, which was installed with xiRAID Classic and made available to Pacemaker in one of the previous steps.&lt;/p&gt;

&lt;p&gt;To cluster Lustre services, there are two options, as currently two resource agents are capable of managing Lustre OSDs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ocf💓Filesystem: Distributed by ClusterLabs in the resource-agents package, the Filesystem RA is a very mature and stable application and has been part of the Pacemaker project for many years. Filesystem provides generic support for mounting and unmounting storage devices, which indirectly includes Lustre.&lt;/li&gt;
&lt;li&gt;ocf:lustre:Lustre: Developed specifically for Lustre OSDs, this RA is distributed by the Lustre project and is available in Lustre releases from version 2.10.0 onwards. As a result of its narrower scope, it is less complex than ocf💓Filesystem and better suited for managing Lustre storage resources.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For simplicity, we will use ocf💓Filesystem in our case. However, ocf:lustre:Lustre can also be easily used in conjunction with xiRAID Classic in a Pacemaker cluster configuration. For more details on Lustre clustering, please check this page of Lustre documentation.&lt;/p&gt;

&lt;p&gt;First of all, create mountpoints for all the RAIDs formatted in LDISKFS at both nodes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# mkdir -p /lustre_t/ost3
# mkdir -p /lustre_t/ost2
# mkdir -p /lustre_t/ost1
# mkdir -p /lustre_t/ost0
# mkdir -p /lustre_t/mdt0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unload all the RAIDs at the node where they are active:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# xicli raid show
╔RAIDs═══╦══════════════════╦═════════════╦════════════════════════╦══════╗
║ name   ║ static           ║ state       ║ devices                ║ info ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_mdt0 ║ size: 3576 GiB   ║ online      ║ 0 /dev/nvme0n1 online  ║      ║
║        ║ level: 1         ║ initialized ║ 1 /dev/nvme1n1 online  ║      ║
║        ║ strip_size: 16   ║             ║                        ║      ║
║        ║ block_size: 4096 ║             ║                        ║      ║
║        ║ sparepool: -     ║             ║                        ║      ║
║        ║ active: True     ║             ║                        ║      ║
║        ║ config: True     ║             ║                        ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost0 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n1 online  ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme5n1 online  ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n1 online  ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n1 online  ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n1 online  ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n1 online  ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n1 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme11n1 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme13n1 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme14n1 online ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost1 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n2 online  ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme5n2 online  ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n2 online  ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n2 online  ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n2 online  ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n2 online  ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n2 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme11n2 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme13n2 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme14n2 online ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost2 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n1 online ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme16n1 online ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n1 online ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n1 online ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n1 online ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n1 online ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n1 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme23n1 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme24n1 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme25n1 online ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost3 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n2 online ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme16n2 online ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n2 online ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n2 online ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n2 online ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n2 online ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n2 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme23n2 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme24n2 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme25n2 online ║      ║
╚════════╩══════════════════╩═════════════╩════════════════════════╩══════╝

node26# xicli raid unload -n r_mdt0
node26# xicli raid unload -n r_ost0
node26# xicli raid unload -n r_ost1
node26# xicli raid unload -n r_ost2
node26# xicli raid unload -n r_ost3

node26# xicli raid show
╔RAIDs═══╦══════════════════╦═══════╦═════════╦══════╗
║ name   ║ static           ║ state ║ devices ║ info ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_mdt0 ║ size: 3576 GiB   ║ None  ║         ║      ║
║        ║ level: 1         ║       ║         ║      ║
║        ║ strip_size: 16   ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost0 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost1 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost2 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╠════════╬══════════════════╬═══════╬═════════╬══════╣
║ r_ost3 ║ size: 14302 GiB  ║ None  ║         ║      ║
║        ║ level: 6         ║       ║         ║      ║
║        ║ strip_size: 128  ║       ║         ║      ║
║        ║ block_size: 4096 ║       ║         ║      ║
║        ║ sparepool: -     ║       ║         ║      ║
║        ║ active: False    ║       ║         ║      ║
║        ║ config: True     ║       ║         ║      ║
╚════════╩══════════════════╩═══════╩═════════╩══════╝
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a copy of the cluster information base to make changes to at the first node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs cluster cib fs_cfg
node26# ls -l fs_cfg
-rw-r--r--. 1 root root 8614 Jul 20 02:04 fs_cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Getting the RAIDs UUIDs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# grep uuid /etc/xiraid/raids/*.conf
/etc/xiraid/raids/r_mdt0.conf:    "uuid": "75E2CAA5-3E5B-4ED0-89E9-4BF3850FD542",
/etc/xiraid/raids/r_ost0.conf:    "uuid": "AB341442-20AC-43B1-8FE6-F9ED99D1D6C0",
/etc/xiraid/raids/r_ost1.conf:    "uuid": "1441D09C-0073-4555-A398-71984E847F9E",
/etc/xiraid/raids/r_ost2.conf:    "uuid": "0E225812-6877-4344-A552-B6A408EC7351",
/etc/xiraid/raids/r_ost3.conf:    "uuid": "F749B8A7-3CC4-45A9-A61E-E75EDBB3A53E",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating resource rr_mdt0 for the r_mdt0 RAID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg resource create rr_mdt0 ocf:xraid:raid name=r_mdt0 uuid=75E2CAA5-3E5B-4ED0-89E9-4BF3850FD542 op monitor interval=5s meta migration-threshold=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting a constraint to make the first node preferable for r_mdt0 resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg constraint location rr_mdt0 prefers node26-ic=50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating a resource for the r_mdt0 RAID mountpoint at /lustre_t/mdt0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg resource create fsr_mdt0 Filesystem device="/dev/xi_r_mdt0" directory="/lustre_t/mdt0" fstype="lustre"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure the cluster to start rr_mdt0 and fsr_mdt0 at the same node ONLY:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg constraint colocation add rr_mdt0 with fsr_mdt0 INFINITY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure the cluster to start fsr_mdt0 only after rr_mdt0:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg constraint order rr_mdt0 then fsr_mdt0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure other resources in the same way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg resource create rr_ost0 ocf:xraid:raid name=r_ost0 uuid=AB341442-20AC-43B1-8FE6-F9ED99D1D6C0 op monitor interval=5s meta migration-threshold=1
node26# pcs -f fs_cfg constraint location rr_ost0 prefers node26-ic=50
node26# pcs -f fs_cfg resource create fsr_ost0 Filesystem device="/dev/xi_r_ost0" directory="/lustre_t/ost0" fstype="lustre"
node26# pcs -f fs_cfg constraint colocation add rr_ost0 with fsr_ost0 INFINITY
node26# pcs -f fs_cfg constraint order rr_ost0 then fsr_ost0

node26# pcs -f fs_cfg resource create rr_ost1 ocf:xraid:raid name=r_ost1 uuid=1441D09C-0073-4555-A398-71984E847F9E op monitor interval=5s meta migration-threshold=1
node26# pcs -f fs_cfg constraint location rr_ost1 prefers node27-ic=50
node26# pcs -f fs_cfg resource create fsr_ost1 Filesystem device="/dev/xi_r_ost1" directory="/lustre_t/ost1" fstype="lustre"
node26# pcs -f fs_cfg constraint colocation add rr_ost1 with fsr_ost1 INFINITY
node26# pcs -f fs_cfg constraint order rr_ost1 then fsr_ost1

node26# pcs -f fs_cfg resource create rr_ost2 ocf:xraid:raid name=r_ost2 uuid=0E225812-6877-4344-A552-B6A408EC7351 op monitor interval=5s meta migration-threshold=1
node26# pcs -f fs_cfg constraint location rr_ost2 prefers node26-ic=50
node26# pcs -f fs_cfg resource create fsr_ost2 Filesystem device="/dev/xi_r_ost2" directory="/lustre_t/ost2" fstype="lustre"
node26# pcs -f fs_cfg constraint colocation add rr_ost2 with fsr_ost2 INFINITY
node26# pcs -f fs_cfg constraint order rr_ost2 then fsr_ost2

node26# pcs -f fs_cfg resource create rr_ost3 ocf:xraid:raid name=r_ost3 uuid=F749B8A7-3CC4-45A9-A61E-E75EDBB3A53E op monitor interval=5s meta migration-threshold=1
node26# pcs -f fs_cfg constraint location rr_ost3 prefers node27-ic=50
node26# pcs -f fs_cfg resource create fsr_ost3 Filesystem device="/dev/xi_r_ost3" directory="/lustre_t/ost3" fstype="lustre"
node26# pcs -f fs_cfg constraint colocation add rr_ost3 with fsr_ost3 INFINITY
node26# pcs -f fs_cfg constraint order rr_ost3 then fsr_ost3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In xiRAID Classic 4.1, it is required to guarantee that only one RAID can be starting at a time. To do so, we define the following constraints. This limitation is planned for removal in xiRAID Classic 4.2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg constraint order start rr_mdt0 then start rr_ost0 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_mdt0 then start rr_ost1 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_mdt0 then start rr_ost2 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_mdt0 then start rr_ost3 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_ost0 then start rr_ost1 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_ost0 then start rr_ost2 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_ost0 then start rr_ost3 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_ost1 then start rr_ost2 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_ost1 then start rr_ost3 kind=Serialize
node26# pcs -f fs_cfg constraint order start rr_ost2 then start rr_ost3 kind=Serialize
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To ensure Lustre servers start in the proper order, we need to configure the cluster to start MDS before all the OSS's. Since the Linux kernel starts MDSes and OSS's automatically when mounting the LDISKFS filesystem, we just need to set the proper start order for the fsr_* resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs -f fs_cfg constraint order fsr_mdt0 then fsr_ost0
node26# pcs -f fs_cfg constraint order fsr_mdt0 then fsr_ost1
node26# pcs -f fs_cfg constraint order fsr_mdt0 then fsr_ost2
node26# pcs -f fs_cfg constraint order fsr_mdt0 then fsr_ost3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applying the batch cluster information base changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs cluster cib-push fs_cfg --config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking the resulting cluster configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs status
Cluster name: lustrebox0
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node26-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Tue Jul 23 02:14:54 2024 on node26-ic
  * Last change:  Tue Jul 23 02:14:50 2024 by root via root on node26-ic
  * 2 nodes configured
  * 12 resource instances configured

Node List:
  * Online: [ node26-ic node27-ic ]

Full List of Resources:
  * node27.stonith      (stonith:fence_ipmilan):         Started node26-ic
  * node26.stonith      (stonith:fence_ipmilan):         Started node27-ic
  * rr_mdt0             (ocf::xraid:raid):               Started node26-ic
  * fsr_mdt0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost0             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost1             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost1            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost2             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost2            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost3             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost3            (ocf::heartbeat:Filesystem):     Started node27-ic

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Double-check on both nodes that the RAIDs are active and the filesystems are mounted properly. Please note that we have all the OST RAIDs based on /dev/nvme*n1 active on the first node (node26) and all the OST RAIDs based on /dev/nvme*n2 on the second one (node27), which will help us utilize the full NVMe throughput as planned.&lt;/p&gt;

&lt;p&gt;node26:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# xicli raid show
╔RAIDs═══╦══════════════════╦═════════════╦════════════════════════╦══════╗
║ name   ║ static           ║ state       ║ devices                ║ info ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_mdt0 ║ size: 3576 GiB   ║ online      ║ 0 /dev/nvme0n1 online  ║      ║
║        ║ level: 1         ║ initialized ║ 1 /dev/nvme1n1 online  ║      ║
║        ║ strip_size: 16   ║             ║                        ║      ║
║        ║ block_size: 4096 ║             ║                        ║      ║
║        ║ sparepool: -     ║             ║                        ║      ║
║        ║ active: True     ║             ║                        ║      ║
║        ║ config: True     ║             ║                        ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost0 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n1 online  ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme5n1 online  ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n1 online  ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n1 online  ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n1 online  ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n1 online  ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n1 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme11n1 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme13n1 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme14n1 online ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost1 ║ size: 14302 GiB  ║ None        ║                        ║      ║
║        ║ level: 6         ║             ║                        ║      ║
║        ║ strip_size: 128  ║             ║                        ║      ║
║        ║ block_size: 4096 ║             ║                        ║      ║
║        ║ sparepool: -     ║             ║                        ║      ║
║        ║ active: False    ║             ║                        ║      ║
║        ║ config: True     ║             ║                        ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost2 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n1 online ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme16n1 online ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n1 online ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n1 online ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n1 online ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n1 online ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n1 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme23n1 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme24n1 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme25n1 online ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost3 ║ size: 14302 GiB  ║ None        ║                        ║      ║
║        ║ level: 6         ║             ║                        ║      ║
║        ║ strip_size: 128  ║             ║                        ║      ║
║        ║ block_size: 4096 ║             ║                        ║      ║
║        ║ sparepool: -     ║             ║                        ║      ║
║        ║ active: False    ║             ║                        ║      ║
║        ║ config: True     ║             ║                        ║      ║
╚════════╩══════════════════╩═════════════╩════════════════════════╩══════╝

node26# df -h|grep xi
/dev/xi_r_mdt0       2.1T  5.7M  2.0T   1% /lustre_t/mdt0
/dev/xi_r_ost0        14T  1.3M   14T   1% /lustre_t/ost0
/dev/xi_r_ost2        14T  1.3M   14T   1% /lustre_t/ost2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;node27:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# xicli raid show
╔RAIDs═══╦══════════════════╦═════════════╦════════════════════════╦══════╗
║ name   ║ static           ║ state       ║ devices                ║ info ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_mdt0 ║ size: 3576 GiB   ║ None        ║                        ║      ║
║        ║ level: 1         ║             ║                        ║      ║
║        ║ strip_size: 16   ║             ║                        ║      ║
║        ║ block_size: 4096 ║             ║                        ║      ║
║        ║ sparepool: -     ║             ║                        ║      ║
║        ║ active: False    ║             ║                        ║      ║
║        ║ config: True     ║             ║                        ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost0 ║ size: 14302 GiB  ║ None        ║                        ║      ║
║        ║ level: 6         ║             ║                        ║      ║
║        ║ strip_size: 128  ║             ║                        ║      ║
║        ║ block_size: 4096 ║             ║                        ║      ║
║        ║ sparepool: -     ║             ║                        ║      ║
║        ║ active: False    ║             ║                        ║      ║
║        ║ config: True     ║             ║                        ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost1 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n2 online  ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme5n2 online  ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n2 online  ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n2 online  ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n2 online  ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n2 online  ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n2 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme11n2 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme13n2 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme14n2 online ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost2 ║ size: 14302 GiB  ║ None        ║                        ║      ║
║        ║ level: 6         ║             ║                        ║      ║
║        ║ strip_size: 128  ║             ║                        ║      ║
║        ║ block_size: 4096 ║             ║                        ║      ║
║        ║ sparepool: -     ║             ║                        ║      ║
║        ║ active: False    ║             ║                        ║      ║
║        ║ config: True     ║             ║                        ║      ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬══════╣
║ r_ost3 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n2 online ║      ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme16n2 online ║      ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n2 online ║      ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n2 online ║      ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n2 online ║      ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n2 online ║      ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n2 online ║      ║
║        ║                  ║             ║ 7 /dev/nvme23n2 online ║      ║
║        ║                  ║             ║ 8 /dev/nvme24n2 online ║      ║
║        ║                  ║             ║ 9 /dev/nvme25n2 online ║      ║
╚════════╩══════════════════╩═════════════╩════════════════════════╩══════╝

node27# df -h|grep xi
/dev/xi_r_ost1        14T  1.3M   14T   1% /lustre_t/ost1
/dev/xi_r_ost3        14T  1.3M   14T   1% /lustre_t/ost3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Lustre performance tuning
&lt;/h2&gt;

&lt;p&gt;Here we set some parameters for the performance optimisation. All the commands have to be run at the host, where MDS server is running.&lt;/p&gt;

&lt;p&gt;Server-side parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lustre performance tuning
Here we set some parameters for the performance optimisation. All the commands have to be run at the host, where MDS server is running.

Server-side parameters:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These parameters are optimised for the best performance. They are not universal and can be not optimal for some cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testbed description
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Lustre client systems:
&lt;/h3&gt;

&lt;p&gt;The Lustre client systems are 4 servers in identical configurations connected to the same Infiniband switch Mellanox QuantumTM HDR Edge Switch QM8700. The SBB system nodes (the cluster nodes) are also connected to the same switch. Lustre client parameters are modified to get the best performance. These parameter changes are accepted by the Lustre community for modern tests showing high performance. More details are provided in the table below:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hostname&lt;/th&gt;
&lt;th&gt;lclient00&lt;/th&gt;
&lt;th&gt;lclient01&lt;/th&gt;
&lt;th&gt;lclient02&lt;/th&gt;
&lt;th&gt;lclient03&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CPU&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AMD EPYC 7502 32-Core&lt;/td&gt;
&lt;td&gt;AMD EPYC 7502 32-Core&lt;/td&gt;
&lt;td&gt;AMD EPYC 7502 32-Core&lt;/td&gt;
&lt;td&gt;AMD EPYC 7502 32-Core&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;256GB&lt;/td&gt;
&lt;td&gt;256GB&lt;/td&gt;
&lt;td&gt;256GB&lt;/td&gt;
&lt;td&gt;256GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OS drives&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;INTEL SSDPEKKW256G8&lt;/td&gt;
&lt;td&gt;INTEL SSDPEKKW256G8&lt;/td&gt;
&lt;td&gt;INTEL SSDPEKKW256G8&lt;/td&gt;
&lt;td&gt;INTEL SSDPEKKW256G8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rocky Linux 8.7&lt;/td&gt;
&lt;td&gt;Rocky Linux 8.7&lt;/td&gt;
&lt;td&gt;Rocky Linux 8.7&lt;/td&gt;
&lt;td&gt;Rocky Linux 8.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Management NIC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;192.168.65.50&lt;/td&gt;
&lt;td&gt;192.168.65.52&lt;/td&gt;
&lt;td&gt;192.168.65.54&lt;/td&gt;
&lt;td&gt;192.168.65.56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Infiniband LNET HDR&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;100.100.100.50&lt;/td&gt;
&lt;td&gt;100.100.100.52&lt;/td&gt;
&lt;td&gt;100.100.100.54&lt;/td&gt;
&lt;td&gt;100.100.100.56&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Lustre clients are combined into a simple OpenMPI cluster, and the standard parallel filesystem test - IOR - is used to run the tests. The test files are created in the /stripe filesystem subfolder, which was created on the Lustre filesystem with the following striping parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01# mount -t lustre 100.100.100.26@o2ib:100.100.100.27@o2ib:/lustre0 /mnt.l
lclient01# mkdir /mnt.l/stripe4M
lclient01# lfs setstripe -c -1 -S 4M /mnt.l/stripe4M/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Test results
&lt;/h2&gt;

&lt;p&gt;We used the standard parallel filesystem IOR test to measure the performance of the installation. For example, we ran 4 tests. Each test is started with 128 threads spread among 4 clients. The tests differ by transfer size (1M and 128M) and the use of directIO.&lt;/p&gt;

&lt;p&gt;Normal state cluster performance&lt;br&gt;
Tests with directIO enabled&lt;/p&gt;

&lt;p&gt;The following list shows the test command and results for directIO enabled test with transfer size of 1MB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01# /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 1M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile --posix.odirect

. . . 

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     19005      19005      0.006691    8388608    1024.00    0.008597   55.17      3.92       55.17      0
read      82075      82077      0.001545    8388608    1024.00    0.002592   12.78      0.213460   12.78      0
Max Write: 19005.04 MiB/sec (19928.23 MB/sec)
Max Read:  82075.33 MiB/sec (86062.22 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       19005.04   19005.04   19005.04       0.00   19005.04   19005.04   19005.04       0.00   55.17357         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
read        82075.33   82075.33   82075.33       0.00   82075.33   82075.33   82075.33       0.00   12.77578         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following list shows the test command and results for directIO enabled test with transfer size of 128MB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01# /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 128M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile --posix.odirect

. . .

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     52892      413.23     0.306686    8388608    131072     0.096920   19.82      0.521081   19.82      0
read      70588      551.50     0.229853    8388608    131072     0.002983   14.85      0.723477   14.85      0
Max Write: 52892.27 MiB/sec (55461.56 MB/sec)
Max Read:  70588.32 MiB/sec (74017.22 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       52892.27   52892.27   52892.27       0.00     413.22     413.22     413.22       0.00   19.82475         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
read        70588.32   70588.32   70588.32       0.00     551.47     551.47     551.47       0.00   14.85481         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tests with directIO disabled&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The following list shows the test command and results for buffered IO (directIO disabled) test with transfer size of 1MB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01#  /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 1M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile

. . .

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     48202      48204      0.002587    8388608    1024.00    0.008528   21.75      1.75       21.75      0
read      40960      40960      0.002901    8388608    1024.00    0.002573   25.60      2.39       25.60      0
Max Write: 48202.43 MiB/sec (50543.91 MB/sec)
Max Read:  40959.57 MiB/sec (42949.22 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       48202.43   48202.43   48202.43       0.00   48202.43   48202.43   48202.43       0.00   21.75359         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
read        40959.57   40959.57   40959.57       0.00   40959.57   40959.57   40959.57       0.00   25.60027         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following list shows the test command and results for buffered IO (directIO disabled) test with transfer size of 128MB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01#  /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 128M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile

. . .

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     46315      361.84     0.349582    8388608    131072     0.009255   22.64      2.70       22.64      0
read      39435      308.09     0.368192    8388608    131072     0.002689   26.59      7.65       26.59      0
Max Write: 46314.67 MiB/sec (48564.45 MB/sec)
Max Read:  39434.54 MiB/sec (41350.12 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       46314.67   46314.67   46314.67       0.00     361.83     361.83     361.83       0.00   22.64026         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
read        39434.54   39434.54   39434.54       0.00     308.08     308.08     308.08       0.00   26.59029         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Failover behavior
&lt;/h2&gt;

&lt;p&gt;To check the cluster behavior in case of a node failure, we will crash a node to simulate such a failure. Before the failure simulation, let's check the normal cluster state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# pcs status
Cluster name: lustrebox0
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node27-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Tue Aug 13 19:13:23 2024 on node26-ic
  * Last change:  Tue Aug 13 19:13:18 2024 by hacluster via hacluster on node27-ic
  * 2 nodes configured
  * 12 resource instances configured

Node List:
  * Online: [ node26-ic node27-ic ]

Full List of Resources:
  * rr_mdt0             (ocf::xraid:raid):               Started node26-ic
  * fsr_mdt0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost0             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost1             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost1            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost2             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost2            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost3             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost3            (ocf::heartbeat:Filesystem):     Started node27-ic
  * node27.stonith      (stonith:fence_ipmilan):         Started node26-ic
  * node26.stonith      (stonith:fence_ipmilan):         Started node27-ic

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s execute the node node26 crash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# echo c &amp;gt; /proc/sysrq-trigger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here node27 identifies, that node26 does not responding and preparing to fence it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# pcs status
Cluster name: lustrebox0
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node27-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Fri Aug 30 00:55:04 2024 on node27-ic
  * Last change:  Thu Aug 29 01:26:09 2024 by root via root on node26-ic
  * 2 nodes configured
  * 12 resource instances configured

Node List:
  * Node node26-ic: UNCLEAN (offline)
  * Online: [ node27-ic ]

Full List of Resources:
  * rr_mdt0             (ocf::xraid:raid):               Started node26-ic (UNCLEAN)
  * fsr_mdt0            (ocf::heartbeat:Filesystem):     Started node26-ic (UNCLEAN)
  * rr_ost0             (ocf::xraid:raid):               Started node26-ic (UNCLEAN)
  * fsr_ost0            (ocf::heartbeat:Filesystem):     Started node26-ic (UNCLEAN)
  * rr_ost1             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost1            (ocf::heartbeat:Filesystem):     Stopped
  * rr_ost2             (ocf::xraid:raid):               Started node26-ic (UNCLEAN)
  * fsr_ost2            (ocf::heartbeat:Filesystem):     Started node26-ic (UNCLEAN)
  * rr_ost3             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost3            (ocf::heartbeat:Filesystem):     Stopping node27-ic
  * node27.stonith      (stonith:fence_ipmilan):         Started node26-ic (UNCLEAN)
  * node26.stonith      (stonith:fence_ipmilan):         Started node27-ic

Pending Fencing Actions:
  * reboot of node26-ic pending: client=pacemaker-controld.286449, origin=node27-ic

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, all the cluster resources are online at node27 after successful node26 fencing.&lt;/p&gt;

&lt;p&gt;During the experiment, the cluster required about 1 minute 50 seconds to identify node26's absence, fence it, and start all the services in the required sequence on the survived node27.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# pcs status
Cluster name: lustrebox0
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node27-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Fri Aug 30 00:56:30 2024 on node27-ic
  * Last change:  Thu Aug 29 01:26:09 2024 by root via root on node26-ic
  * 2 nodes configured
  * 12 resource instances configured

Node List:
  * Online: [ node27-ic ]
  * OFFLINE: [ node26-ic ]

Full List of Resources:
  * rr_mdt0             (ocf::xraid:raid):               Started node27-ic
  * fsr_mdt0            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost0             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost0            (ocf::heartbeat:Filesystem):     Starting node27-ic
  * rr_ost1             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost1            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost2             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost2            (ocf::heartbeat:Filesystem):     Starting node27-ic
  * rr_ost3             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost3            (ocf::heartbeat:Filesystem):     Started node27-ic
  * node27.stonith      (stonith:fence_ipmilan):         Stopped
  * node26.stonith      (stonith:fence_ipmilan):         Started node27-ic

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since node26 was not shut down properly, the RAIDs migrated to node27 are under initialization to prevent from write hole. It’s the expected behaviour:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# xicli raid show
╔RAIDs═══╦══════════════════╦═════════════╦════════════════════════╦═══════════════════╗
║ name   ║ static           ║ state       ║ devices                ║ info              ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_mdt0 ║ size: 3576 GiB   ║ online      ║ 0 /dev/nvme0n1 online  ║                   ║
║        ║ level: 1         ║ initialized ║ 1 /dev/nvme1n1 online  ║                   ║
║        ║ strip_size: 16   ║             ║                        ║                   ║
║        ║ block_size: 4096 ║             ║                        ║                   ║
║        ║ sparepool: -     ║             ║                        ║                   ║
║        ║ active: True     ║             ║                        ║                   ║
║        ║ config: True     ║             ║                        ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost0 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n1 online  ║ init_progress: 31 ║
║        ║ level: 6         ║ initing     ║ 1 /dev/nvme5n1 online  ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n1 online  ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n1 online  ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n1 online  ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n1 online  ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n1 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme11n1 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme13n1 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme14n1 online ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost1 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme4n2 online  ║                   ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme5n2 online  ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme6n2 online  ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme7n2 online  ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme8n2 online  ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme9n2 online  ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme10n2 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme11n2 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme13n2 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme14n2 online ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost2 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n1 online ║ init_progress: 29 ║
║        ║ level: 6         ║ initing     ║ 1 /dev/nvme16n1 online ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n1 online ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n1 online ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n1 online ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n1 online ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n1 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme23n1 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme24n1 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme25n1 online ║                   ║
╠════════╬══════════════════╬═════════════╬════════════════════════╬═══════════════════╣
║ r_ost3 ║ size: 14302 GiB  ║ online      ║ 0 /dev/nvme15n2 online ║                   ║
║        ║ level: 6         ║ initialized ║ 1 /dev/nvme16n2 online ║                   ║
║        ║ strip_size: 128  ║             ║ 2 /dev/nvme17n2 online ║                   ║
║        ║ block_size: 4096 ║             ║ 3 /dev/nvme18n2 online ║                   ║
║        ║ sparepool: -     ║             ║ 4 /dev/nvme20n2 online ║                   ║
║        ║ active: True     ║             ║ 5 /dev/nvme21n2 online ║                   ║
║        ║ config: True     ║             ║ 6 /dev/nvme22n2 online ║                   ║
║        ║                  ║             ║ 7 /dev/nvme23n2 online ║                   ║
║        ║                  ║             ║ 8 /dev/nvme24n2 online ║                   ║
║        ║                  ║             ║ 9 /dev/nvme25n2 online ║                   ║
╚════════╩══════════════════╩═════════════╩════════════════════════╩═══════════════════╝
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Failover state cluster performance
&lt;/h2&gt;

&lt;p&gt;Now all the Lustre filesystem servers are running on the survived node. In this configuration, we expect the performance to be halved because now all communication will go through only one server. Other bottlenecks in this situation are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decreased NVMe performance: since we have one server running, all the workload goes to the NVMes via only 2 PCIe lanes;&lt;/li&gt;
&lt;li&gt;Lack of CPU;&lt;/li&gt;
&lt;li&gt;Lack of RAM.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tests with directIO enabled
&lt;/h2&gt;

&lt;p&gt;The following list shows the test command and results for directIO enabled test with a transfer size of 1MB on the system with just one node working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01# /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 1M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile --posix.odirect

. . .

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     17185      17185      0.007389    8388608    1024.00    0.012074   61.02      2.86       61.02      0
read      45619      45620      0.002803    8388608    1024.00    0.003000   22.99      0.590771   22.99      0
Max Write: 17185.06 MiB/sec (18019.84 MB/sec)
Max Read:  45619.10 MiB/sec (47835.10 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       17185.06   17185.06   17185.06       0.00   17185.06   17185.06   17185.06       0.00   61.01671         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
read        45619.10   45619.10   45619.10       0.00   45619.10   45619.10   45619.10       0.00   22.98546         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following list shows the test command and results for directIO enabled test with a transfer size of 128MB on the system with just one node working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01# /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 128M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile --posix.odirect

. . .

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     30129      235.39     0.524655    8388608    131072     0.798392   34.80      1.64       34.80      0
read      35731      279.15     0.455215    8388608    131072     0.002234   29.35      2.37       29.35      0
Max Write: 30129.26 MiB/sec (31592.82 MB/sec)
Max Read:  35730.91 MiB/sec (37466.57 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       30129.26   30129.26   30129.26       0.00     235.38     235.38     235.38       0.00   34.80258         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
read        35730.91   35730.91   35730.91       0.00     279.15     279.15     279.15       0.00   29.34647         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tests with directIO disabled
&lt;/h2&gt;

&lt;p&gt;The following list shows the test command and results for buffered IO (directIO disabled) test with a transfer size of 1MB on the system with just one node working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01#  /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 1M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile

. . .

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     30967      31042      0.004072    8388608    1024.00    0.008509   33.78      7.55       33.86      0
read      38440      38441      0.003291    8388608    1024.00    0.282087   27.28      8.22       27.28      0
Max Write: 30966.96 MiB/sec (32471.21 MB/sec)
Max Read:  38440.06 MiB/sec (40307.32 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       30966.96   30966.96   30966.96       0.00   30966.96   30966.96   30966.96       0.00   33.86112         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
read        38440.06   38440.06   38440.06       0.00   38440.06   38440.06   38440.06       0.00   27.27821         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592  1048576 1048576.0 POSIX      0
Finished            : Thu Sep 12 03:18:41 2024
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following list shows the test command and results for buffered IO (directIO disabled) test with a transfer size of 1MB on the system with just one node working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lclient01#  /usr/lib64/openmpi/bin/mpirun --allow-run-as-root --hostfile ./hfile -np 128 --map-by node /usr/bin/ior -F -t 128M -b 8G  -k -r -w -o /mnt.l/stripe4M/testfile

. . .

access    bw(MiB/s)  IOPS       Latency(s)  block(KiB) xfer(KiB)  open(s)    wr/rd(s)   close(s)   total(s)   iter
------    ---------  ----       ----------  ---------- ---------  --------   --------   --------   --------   ----
write     30728      240.72     0.515679    8388608    131072     0.010178   34.03      8.70       34.12      0
read      35974      281.05     0.386365    8388608    131072     0.067996   29.15      10.73      29.15      0
Max Write: 30727.85 MiB/sec (32220.49 MB/sec)
Max Read:  35974.24 MiB/sec (37721.72 MB/sec)

Summary of all tests:
Operation   Max(MiB)   Min(MiB)  Mean(MiB)     StdDev   Max(OPs)   Min(OPs)  Mean(OPs)     StdDev    Mean(s) Stonewall(s) Stonewall(MiB) Test# #Tasks tPN reps fPP reord reordoff reordrand seed segcnt   blksiz    xsize aggs(MiB)   API RefNum
write       30727.85   30727.85   30727.85       0.00     240.06     240.06     240.06       0.00   34.12461         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
read        35974.24   35974.24   35974.24       0.00     281.05     281.05     281.05       0.00   29.14797         NA            NA     0    128  32    1   1     0        1         0    0      1 8589934592 134217728 1048576.0 POSIX      0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Failback
&lt;/h2&gt;

&lt;p&gt;Meanwhile node26 booted after the crash. At our configuration the cluster software does not start automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs status
Error: error running crm_mon, is pacemaker running?
crm_mon: Connection to cluster failed: Connection refused
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It could be useful in real life: before returning a node to a cluster, the administrator should identify, localize, and fix the problem to prevent it from recurring.&lt;/p&gt;

&lt;p&gt;The cluster software works properly at node27:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node27# pcs status
Cluster name: lustrebox0
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node27-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Sat Aug 31 01:13:57 2024 on node27-ic
  * Last change:  Thu Aug 29 01:26:09 2024 by root via root on node26-ic
  * 2 nodes configured
  * 12 resource instances configured

Node List:
  * Online: [ node27-ic ]
  * OFFLINE: [ node26-ic ]

Full List of Resources:
  * rr_mdt0             (ocf::xraid:raid):               Started node27-ic
  * fsr_mdt0            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost0             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost0            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost1             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost1            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost2             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost2            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost3             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost3            (ocf::heartbeat:Filesystem):     Started node27-ic
  * node27.stonith      (stonith:fence_ipmilan):         Stopped
  * node26.stonith      (stonith:fence_ipmilan):         Started node27-ic

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since we know the reason of the node26 crash, we start the cluster software there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs cluster start
Starting Cluster...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some time the cluster software starts and the resources, which should work at node26, become properly moved from node27 to node26. The failback process took about 30 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node26# pcs status
Cluster name: lustrebox0
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node27-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Sat Aug 31 01:15:03 2024 on node26-ic
  * Last change:  Thu Aug 29 01:26:09 2024 by root via root on node26-ic
  * 2 nodes configured
  * 12 resource instances configured

Node List:
  * Online: [ node26-ic node27-ic ]

Full List of Resources:
  * rr_mdt0             (ocf::xraid:raid):               Started node26-ic
  * fsr_mdt0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost0             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost1             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost1            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost2             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost2            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost3             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost3            (ocf::heartbeat:Filesystem):     Started node27-ic
  * node27.stonith      (stonith:fence_ipmilan):         Started node26-ic
  * node26.stonith      (stonith:fence_ipmilan):         Started node27-ic

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
node27# pcs status
Cluster name: lustrebox0
Cluster Summary:
  * Stack: corosync (Pacemaker is running)
  * Current DC: node27-ic (version 2.1.7-5.el8_10-0f7f88312) - partition with quorum
  * Last updated: Sat Aug 31 01:15:40 2024 on node27-ic
  * Last change:  Thu Aug 29 01:26:09 2024 by root via root on node26-ic
  * 2 nodes configured
  * 12 resource instances configured

Node List:
  * Online: [ node26-ic node27-ic ]

Full List of Resources:
  * rr_mdt0             (ocf::xraid:raid):               Started node26-ic
  * fsr_mdt0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost0             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost0            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost1             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost1            (ocf::heartbeat:Filesystem):     Started node27-ic
  * rr_ost2             (ocf::xraid:raid):               Started node26-ic
  * fsr_ost2            (ocf::heartbeat:Filesystem):     Started node26-ic
  * rr_ost3             (ocf::xraid:raid):               Started node27-ic
  * fsr_ost3            (ocf::heartbeat:Filesystem):     Started node27-ic
  * node27.stonith      (stonith:fence_ipmilan):         Started node26-ic
  * node26.stonith      (stonith:fence_ipmilan):         Started node27-ic

Daemon Status:
  corosync: active/disabled
  pacemaker: active/disabled
  pcsd: active/enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The article shows the possibility of creating a small, highly available, and high-performance Lustre installation based on an SBB system with dual-ported NVMe drives and xiRAID Classic 4.1 RAID engine. It also demonstrates the ease of xiRAID Classic integration with Pacemaker clusters and compatibility of xiRAID Classic with the classical approach to Lustre clustering.&lt;/p&gt;

&lt;p&gt;The configuration is straightforward and requires the following program components to be installed and properly configured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;xiRAID Classic 4.1 and Csync2&lt;/li&gt;
&lt;li&gt;Lustre software&lt;/li&gt;
&lt;li&gt;Pacemaker software&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The resulting system, based on the Viking VDS2249R SBB system, equipped with two single-CPU servers and 24 PCIe 4.0 NVMe drives, showed performance up to &lt;strong&gt;55GB/s&lt;/strong&gt; on writing and up to &lt;strong&gt;86GB/s&lt;/strong&gt; on reading from Lustre clients, using the standard parallel filesystem test program IOR.&lt;/p&gt;

&lt;p&gt;This article, with minimal changes, can also be used to set up additional systems to expand existing Lustre installations.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>performance</category>
      <category>installguide</category>
      <category>lustre</category>
    </item>
    <item>
      <title>Asynchronous I/O: A Practical Guide for Optimizing HPC Workflows with xiRAID in Lustre Environments</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Wed, 19 Mar 2025 14:15:20 +0000</pubDate>
      <link>https://dev.to/pltnvs/asynchronous-io-a-practical-guide-for-optimizing-hpc-workflows-with-xiraid-in-lustre-environments-3921</link>
      <guid>https://dev.to/pltnvs/asynchronous-io-a-practical-guide-for-optimizing-hpc-workflows-with-xiraid-in-lustre-environments-3921</guid>
      <description>&lt;p&gt;In today's AI world, powerful storage is key for many GPUs working together on large datasets. These workflows involve an initial data load at high speeds, followed by data loading during training and periodic checkpoints, all at tens of gigabytes per second. Storage must handle many GPUs accessing massive datasets (hundreds of terabytes to petabytes) while delivering high throughput (tens of gigabytes per second or more) and efficient performance for small operations. This versatility is critical to prevent delays in computational clusters. Our goal is to minimize downtime and maximize efficiency.&lt;/p&gt;

&lt;p&gt;Research groups often use limited infrastructures or cloud services. The growth of AI cloud services demands a data storage system that is fast, high-capacity, and integrates seamlessly into cloud infrastructure. Ideal solutions should be software-defined, deployable on any hardware, and easy to integrate.&lt;/p&gt;

&lt;p&gt;At Xinnor, we provide high-performance storage solutions for diverse clients. Recently, we've observed a growing demand for storage tailored to HPC and AI, especially for shared file systems in smaller setups (with 1-2 DGXs or HGXs) and among cloud providers. These setups require several key features.&lt;/p&gt;

&lt;p&gt;For small standalone installations, solutions need to be created consisting of only one or two storage controllers. These solutions should be capable of delivering performance levels corresponding to a 400-gigabit network and have the potential to scale up to 800 gigabits in the future.&lt;/p&gt;

&lt;p&gt;For cloud environments we need to create a solution that primarily delivers performance of approximately 20 gigabytes per second per client’s virtual machine. Additionally, it must ensure consistent read and write access simultaneously from multiple virtual machines, and support essential requirements such as multi-tenancy and Quality of Service (QoS).&lt;/p&gt;

&lt;p&gt;Our developments enable us to achieve the necessary performance levels while consuming minimal resources. &lt;a href="https://xinnor.io/news/324-at-supercomputer-2023-in-denver-xinnor-will-demonstrate-xiraid-breaking-the-world-record-performance-for-pcie-gen5-drives/" rel="noopener noreferrer"&gt;Recent tests with KIOXIA&lt;/a&gt; showcased xiRAID's capabilities in both RAID5 and RAID6 configurations using 24 PCIe Gen5 drives. The results were impressive, achieving near-theoretical performance with minimal CPU load.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ypyoqrp1w9rtsbu2yda.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ypyoqrp1w9rtsbu2yda.PNG" alt="IMG1" width="800" height="453"&gt;&lt;/a&gt;&lt;br&gt;
However, to meet all the requirements for our solution, we certainly need a parallel or clustered file system. For this, we have chosen Lustre.&lt;/p&gt;

&lt;p&gt;This blog highlights how xiRAID, combined with our Lustre tuning expertise, delivers outstanding results in Lustre environments:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Why We Rely on Lustre&lt;/li&gt;
&lt;li&gt;Our Objectives&lt;/li&gt;
&lt;li&gt;Tested Architectures&lt;/li&gt;
&lt;li&gt;Test Stand Configuration&lt;/li&gt;
&lt;li&gt;Block Device Performance&lt;/li&gt;
&lt;li&gt;IOR Single Test Results&lt;/li&gt;
&lt;li&gt;Testing Synchronous and Asynchronous I/O Operations&lt;/li&gt;
&lt;li&gt;Lustre vs. NFSoRDMA Testing&lt;/li&gt;
&lt;li&gt;Testing Lustre in the Cloud Environment&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;li&gt;Appendix&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Why We Rely on Lustre
&lt;/h2&gt;

&lt;p&gt;But first, why Lustre? At Xinnor, we rely on Lustre for our high-performance storage solutions because it offers several key advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Shared storage for parallel workflows. Lustre enables the creation of shared storage, allowing multiple nodes to access the same file system concurrently. This is crucial for modern AI and HPC workloads, where numerous processing units need efficient, simultaneous access to data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability for growing demands. Lustre's architecture supports linear scalability. We can seamlessly add new storage nodes to the cluster without performance degradation. This ensures our storage solutions can grow alongside our clients' increasing workloads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shared-disk architecture. Lustre's shared-disk architecture perfectly aligns with our approach of providing high-performance block storage solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flexibility for Diverse Deployments. As a software solution, Lustre is deployable on any hardware and within virtualized infrastructures. This flexibility allows us to meet various performance targets across different environments.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond these core benefits, Lustre boasts a proven track record in handling HPC tasks with high streaming performance. However, our goal extends beyond optimizing for large block I/O. We also aim to extract maximum performance from small block I/O operations, critical for many AI applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  Our Objectives
&lt;/h2&gt;

&lt;p&gt;At Xinnor, we have several installations with a combined capacity exceeding 100 petabytes. Each Lustre project is unique, and to ensure the highest performance levels, we fine-tune each solution through a multi-stage process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hardware and software configuration: we configure drives, storage services, and OS settings. This includes software installation, testing, and RAID configuration adjustments.&lt;/li&gt;
&lt;li&gt;Lustre OSS and MDS testing: we test Lustre using I/O utilities like OBDFilter-survey and MDtest.&lt;/li&gt;
&lt;li&gt;Client-perspective testing: we employ standard HPC industry I/O tools (IOR) and FIO for testing from the client's perspective. Using FIO with asynchronous engines helps us achieve optimal efficiency at each storage stack level.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our performance objectives include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Achieving tens of GBps throughput from a few Lustre clients using a couple of Object Storage Servers (OSS).&lt;/li&gt;
&lt;li&gt;Attaining several million IOPS in the same configuration.&lt;/li&gt;
&lt;li&gt;Maintaining a simple hardware and software configuration for easy deployment.&lt;/li&gt;
&lt;li&gt;Developing an easily reproducible test approach for consistency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benchmarking with IOR presents challenges. Buffered I/O can be CPU-intensive, while Direct I/O may create uneven storage loads. Performance scaling with additional I/O threads can be limited on HDDs and read-intensive SSDs. Increasing I/O size isn't always effective either. Therefore, one of our objectives is to demonstrate how Asynchronous I/O (AIO) helps us achieve optimal performance.&lt;/p&gt;

&lt;p&gt;We conducted a comprehensive analysis to identify the most effective configurations for HPC workflows. This included comparisons of Lustre 2.15.4 over ldiskfs, Lustre 2.15.4 over ZFS and NFSoRDMA (v3 and v4.2).&lt;/p&gt;

&lt;p&gt;These comparisons will be further explored to showcase the best performing configurations. We will demonstrate the performance benefits of asynchronous engines compared to classic Buffered I/O and Direct I/O approaches. Additionally, we will benchmark ldiskfs vs. ZFS to determine the better backend file system for different scenarios. Finally, we will compare our solutions against NFS, a competitor for smaller research groups and cloud-deployed systems.&lt;/p&gt;

&lt;p&gt;Through these comparisons and configurations, we aim to showcase the superior performance and versatility of our Lustre-based storage solutions in various HPC and AI environments.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tested Architectures
&lt;/h2&gt;

&lt;p&gt;Our testing involved two primary architectures: a "Cluster-in-the-box" solution and a virtualized solution, both designed to assess the performance of Lustre in various scenarios.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3f7one2rebtkvqkyg8ou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3f7one2rebtkvqkyg8ou.png" alt="img2" width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Cluster-in-the-box architecture&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first architecture we are testing is the "Cluster-in-the-box" solution. This high-performance system is designed for small installations, offering a fully integrated and fault-tolerant setup within a single enclosure. Despite its compact form factor, it supports multiple clients, allowing them to read and write data consistently. Furthermore, leveraging Lustre's capabilities, it can easily scale if the need arises. This solution is ideal for small research groups, combining the convenience of a plug-and-play setup with the high performance typically associated with larger Lustre deployments. Unlike traditional Lustre clusters, which require separate OST/OSS/MDS/MGS components that need to be interconnected, our "Cluster in the Box" offers a streamlined, all-in-one package that significantly simplifies deployment and management.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxshjl89uq9q49cshyh30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxshjl89uq9q49cshyh30.png" alt="Img3" width="800" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Virtualized solution architecture&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The second architecture is a virtualized solution, suitable for deployment in cloud environments, whether private or public. This approach caters to the growing demand for flexible, cloud-based storage solutions. Unlike most clients who use traditional bare-metal distributed systems, our virtualized architecture stands out by providing a robust and scalable solution within a virtual environment. This setup not only supports the performance needs of HPC and AI workloads but also ensures seamless integration into existing cloud infrastructures, offering a modern alternative to conventional bare-metal installations.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test Stand Configuration
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Hardware configuration:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;CPU: 64-Core Processor per node (AMD 7702P)&lt;/li&gt;
&lt;li&gt;Memory: 256 GB RAM per Node&lt;/li&gt;
&lt;li&gt;Networking: 1 x MT28908 Family [ConnectX-6] per node&lt;/li&gt;
&lt;li&gt;Drives: 24x KIOXIA CM6-R 3.84TB: 1.6TB namespace per node&lt;/li&gt;
&lt;li&gt;The clients are based on the same hardware and Rocky Linux 9&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Software configuration:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Rocky Linux 8 with Lustre 2.15.4.&lt;/li&gt;
&lt;li&gt;RAID: 4 х RAID 6: 10 drives(8d+2p), ss=64k for OSS&lt;/li&gt;
&lt;li&gt;2x RAID1 for MGS and MDS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Block Device Performance
&lt;/h2&gt;

&lt;p&gt;To start, we created a storage array consisting of four RAID6 volumes for data, with two arrays on each node, and two RAID1 volumes for the MGS/MDS. Our initial focus was to test the block device performance of these RAID6 arrays to establish a baseline for the potential performance of the file system within this compact unit. The results were impressive, with single drive performance reaching millions of IOPS for 4K random reads and writes, and up to 93.4 GBps for sequential reads with multiple jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FIO configuration 1&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
bs=4k
rw=randread/randwrite
norandommap
bs=4k
direct=1
group_reporting
random_generator=lfsr
norandommap
time_based=1
runtime=60
iodepth=128
ioengine=libaio
[file1]
filename=/dev/xi_data1
[file2]
filename=/dev/xi_data1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmut4fhgejm9a9qgxajc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdmut4fhgejm9a9qgxajc.PNG" alt="IMG4" width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FIO configuration 2&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
bs=1024k
rw=read/write
direct=1
group_reporting
time_based=1
runtime=60
iodepth=32
ioengine=libaio
numjobs=1
offset_increment=3%
[file1]
filename=/dev/xi_data1
[file2]
filename=/dev/xi_data1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevvtyava1skitojrjvf1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fevvtyava1skitojrjvf1.PNG" alt="IMG5" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When running multiple jobs, which is naturally our target workload, we observe that for random reads, we approach 12.5 million IOPS, and for random writes, we reach 2 million IOPS. Under streaming workloads, we can achieve up to 93 gigabytes per second for reads and 67 gigabytes per second for writes.&lt;/p&gt;

&lt;h2&gt;
  
  
  IOR Single Client Test Results
&lt;/h2&gt;

&lt;p&gt;Next, we deployed the file system with default parameters and conducted the following round of tests. We conducted an IOR test with a single client to assess potential performance. For this test, the client was connected via a 200 Gbit port. The theoretical maximum throughput for streaming read/write operations is approximately 22-24 GBps, and for random operations, around 4.2M IOPS, which represents the maximum capacity of the 200 Gbit connection.&lt;/p&gt;

&lt;p&gt;Our IOR tests provided valuable insights into the performance differences between Direct I/O (DIO) and Buffered I/O in various scenarios. Here's a detailed breakdown of the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Direct I/O (DIO) Performance
&lt;/h2&gt;

&lt;p&gt;Large Sequential I/O Operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;64M Write Operations: 13053 MiB.&lt;/li&gt;
&lt;li&gt;64M Read Operations: 12288 MiB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small Random I/O Operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4k Write Operations: 6542 IOPS.&lt;/li&gt;
&lt;li&gt;4k Read Operations: 6742 IOPS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These results indicate that DIO provides stable and consistent performance for both large sequential and small random I/O operations. This stability is essential for applications requiring predictable I/O behavior, making DIO a reliable choice for demanding environments.&lt;/p&gt;

&lt;p&gt;However, it is worth noting that the performance for small blocks is extremely low.&lt;/p&gt;

&lt;p&gt;The load on the CPU is noticeable but not critical.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2kdak0b9hrr2leizzz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2kdak0b9hrr2leizzz8.png" alt="IMG5" width="800" height="37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Buffered I/O Performance
&lt;/h2&gt;

&lt;p&gt;Large Sequential I/O Operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;64M Write Operations: 3874 MiB.&lt;/li&gt;
&lt;li&gt;64M Read Operations: 12757 MiB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small Random I/O Operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4k Write Operations: 7359 IOPS.&lt;/li&gt;
&lt;li&gt;4k Read Operations: 556629 IOPS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vsi3moqzplqewjjshi4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vsi3moqzplqewjjshi4.png" alt="img6" width="800" height="47"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One notable observation was the variability in buffered I/O write results, ranging from 2,000 to 28,000 IOPS. Additionally, CPU load fluctuated significantly during these operations, spanning from 6% to 100%. This variability and high CPU load highlights the challenges of using buffered I/O in environments requiring consistent performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions from Single Client Tests
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;With the existing approach we can meet the required performance for large sequential I/Os, achieving a single-threaded performance peak of approximately 13 GBps (almost half of potential 24 GBps).&lt;/li&gt;
&lt;li&gt;DIO proves to be more stable compared to buffered I/O in these scenarios, making it a preferred choice for large sequential workloads.&lt;/li&gt;
&lt;li&gt;The performance for small random I/Os remains far from the potential performance of the block device.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing Synchronous (SYNC) and Asynchronous I/O (AIO) operations
&lt;/h2&gt;

&lt;p&gt;We often use the FIO utility because it offers extensive capabilities for regulating load and selecting different io engines for data access. This allows us to evaluate the system’s behavior under various types of workloads.&lt;/p&gt;

&lt;p&gt;We conducted tests with various parameters to understand their impact on performance:&lt;/p&gt;

&lt;p&gt;4k random reads and writes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tested with a fixed numjobs=1 and variable iodepth.&lt;/li&gt;
&lt;li&gt;Also tested with numjobs=32 and variable iodepth.&lt;/li&gt;
&lt;li&gt;Tested with a fixed iodepth=1 and variable numjobs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1M sequential reads and writes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conducted with fixed numjobs=1 and variable iodepth.&lt;/li&gt;
&lt;li&gt;Also explored numjobs=32 and variable iodepth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I/O engines used: libaio, io_uring, and sync. We also used variable Lustre client settings and Lustre OSS settings.&lt;/p&gt;

&lt;p&gt;Configurations description for testing Fio in distributed environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OPT_OSS – optimized OSS/OST settings, with no changing Clients settings&lt;/li&gt;
&lt;li&gt;OPT_CL1 – optimized Client with max rpc in flight = 1 (lctl set_param &lt;em&gt;osc.&lt;em&gt;.max_pages_per_rpc=4096 osc.&lt;/em&gt;.checksums=0 osc.*.max_rpcs_in_flight=1)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;OPT_CL128 – optimized Client with max rpc in flight = 128 (lctl set_param osc.&lt;em&gt;.max_pages_per_rpc=4096 osc.&lt;/em&gt;.checksums=0 &lt;em&gt;osc.*.max_rpcs_in_flight=128)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;ASYNC – ioengine=libaio/io_uring&lt;/li&gt;
&lt;li&gt;SYNC – ioengine=sync&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Important! In this section, we do not differentiate between io_uring and libaio because we did not observe any difference between them in our tests. Therefore, we labeled both engines as “async” on the graphs. Also, we do not address sequential workloads here; we will address them later when we compare with NFS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Testing Results
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;4k Random Reads, numjobs=1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4ji8ovg6mihcz68sysu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4ji8ovg6mihcz68sysu.png" alt="graph1" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When running a single job, increasing the number of requests at once (IO depth) significantly improved performance for the async engine. However, the sync engine, which always uses a queue depth of 1, only matched the async engine's performance when running 16 jobs at once. When using the sync engine, we can theoretically employ multiple threads as an alternative to the asynchronous engine with a high queue depth, but this is effective only up to 16 queues. Beyond 16 queues, performance does not continue to increase. Unfortunately, the sync engine couldn't handle more jobs effectively, and its latency increased significantly.&lt;/p&gt;

&lt;p&gt;Performance varies depending on the type of workload and the settings of both the client and server parts of the Lustre file system. This is clearly illustrated in the graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4k Random Writes, numjobs=1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ddyse3b3e5g6jet9r35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ddyse3b3e5g6jet9r35.png" alt="graph2" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similar results were seen with random writes. The Lustre client performed best when a configuration setting "max rpc flight" was set to a moderate value (between 8 and 24). Again, the sync engine achieved similar performance to the async engine with 16 jobs, but it didn't scale well with more jobs.&lt;/p&gt;

&lt;p&gt;At the same time, the impact of different settings on random write performance is more straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4k Random Reads, numjobs=32&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj1gwfeab5bxu1vd2kxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj1gwfeab5bxu1vd2kxf.png" alt="graph3" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most impressive results came from tests with 32 jobs per client. In this scenario, the async engine achieved nearly 4M IOPS, demonstrating Lustre's excellent scalability for high workloads.&lt;/p&gt;

&lt;p&gt;On the graph, we can see that the performance of Lustre under async IO workloads scales quite well with increasing load, gradually approaching half of the network interface’s capacity in terms of throughput. And, of course, the performance is significantly higher than what we observed when using DIO and Buffered IO in the IOR utility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4k Random Writes, numjobs=32&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhc7njecj8b2ijsmwq797.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhc7njecj8b2ijsmwq797.png" alt="graph4" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Random writes also showed near-linear improvement with increasing queue depth, reaching close to 1M IOPS. More detailed results including latency graphs can be observed in our presentation for LUG24 conference &lt;a href="https://www.depts.ttu.edu/hpcc/events/LUG24/slides/Day2/LUG_2024_Talk_11-Asynchronous_IO_A_Practical_Guide_for_Optimizing_HPC_Workflows.pdf" rel="noopener noreferrer"&gt;“Asynchronous I/O: A Practical Guide for Optimizing HPC Workflows”&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Insights from Testing SYNC and AIO
&lt;/h2&gt;

&lt;p&gt;Our tests provided several key insights into the performance of synchronous (SYNC) and asynchronous I/O (AIO) operations, particularly for large and small block I/Os.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The performance difference between synchronous (SYNC) and asynchronous I/O (AIO) is minimal for large I/O operations. This observation is consistent, though not explicitly shown in the charts.&lt;/li&gt;
&lt;li&gt;For small block I/Os, the difference reaches several times. SYNC operations scale effectively up to 16 jobs, indicating good performance within this range.&lt;/li&gt;
&lt;li&gt;We achieved 49% of the maximum potential performance for random writes. This performance level is primarily constrained by the drives' capabilities.&lt;/li&gt;
&lt;li&gt;For random reads, we reached 46% of the maximum possible performance, limited by the dual 200Gbit Host Channel Adapters (HCAs).&lt;/li&gt;
&lt;li&gt;Achieving around 50% of the storage system’s capabilities on a parallel file system is quite a good result, as storage needs to perform a significant amount of additional work compared to just a block device. Additionally, we have greatly exceeded our expectations, as we had repeatedly heard that Lustre does not suit this type of workload, but we have proved that wrong. Furthermore, we see that there is still great potential for future growth, and we believe that over time we will be able to approach the efficiency of 70-80%.&lt;/li&gt;
&lt;li&gt;The parameter max_rpc_in_flight has a significant impact on performance. Optimal results were observed with values ranging from 8 to 24.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lustre vs NFSoRDMA Testing
&lt;/h2&gt;

&lt;p&gt;When building small-scale systems, there are various approaches to consider. For instance, with Lustre, you can create a fully open-source solution using the ZFS file system as the backend. ZFS offers integrated RAID management and a volume manager, and it integrates well with Lustre. This makes it a robust option for those who prefer open-source solutions.&lt;/p&gt;

&lt;p&gt;Alternatively, you can build a system based on NFS instead of Lustre. NFS has its own advantages, such as having a built-in client in the Linux kernel, which means you are not dependent on specific versions compatible with the Lustre client. This plug-and-play nature is a significant benefit. However, the primary downside is the lack of an open-source NFS implementation that matches the comprehensive functionality of Lustre. While there is an open-source NFS server, it is mainly designed for testing and does not offer the same level of scalability as Lustre. Nonetheless, for small systems, particularly those with one or two controllers, NFS can still be a viable option worth testing.&lt;/p&gt;

&lt;p&gt;Here we'll present our test results for ZFS with NFS. We tested with optimal configurations, the best settings are described in the appendix. Now, let's delve into the performance graphs and detailed findings.&lt;/p&gt;

&lt;p&gt;We compared NFSoRDMA and Lustre 2.15.4 over ldiskfs and ZFS using the same testing approach. We mounted NFS with Sync and Async options as well as changed the NFS server and client settings. Our key findings include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No difference between sync and async mount options for reads.&lt;/li&gt;
&lt;li&gt;No difference between NFS3 and NFS4.1 in most cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The graphs below show the outcome of our testing:&lt;/p&gt;

&lt;h2&gt;
  
  
  Lustre vs NFS3 vs NFS 4.2, 4k READ Ios, numjobs=1
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq99k4uuuhciqq89si4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgq99k4uuuhciqq89si4v.png" alt="graph5" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The benchmark results showed an interesting trend in performance between NFS and Lustre. For single-threaded workloads (number of jobs = 1), NFS exhibited better performance, but this advantage plateaued quickly at around 250K IOPS (regardless of NFS version). In contrast, Lustre's performance scaled linearly as the number of jobs increased.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lustre vs NFS3 vs NFS 4.2, 4k READ IOs, numjobs=32
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiumbpoi17yl1qlln74f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiumbpoi17yl1qlln74f3.png" alt="graph6" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After increasing the number of jobs, Lustre performance scales linearly and NFS plateaus at 250K IOPS. And Lustre over ZFS shows the bottleneck at 100K IOPS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lustre vs NFS3 vs NFS 4.2, 4k WRITE IOs, numjobs=1
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94ubnct6mk694qh2rsz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94ubnct6mk694qh2rsz5.png" alt="graph7" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similar trends emerge in 4K random write tests. While NFS with the async mount option boasts the highest initial speeds, it again encounters a ceiling at 250K IOPS. Lustre maintains its linear scaling, but at a lower overall performance level. As expected, ZFS significantly lags behind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lustre vs NFS3 vs NFS 4.2, 4k WRITE IOs, numjobs=32
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq6426kbdl02ohj83nc6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzq6426kbdl02ohj83nc6.png" alt="graph8" width="800" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the number of jobs increases, NFS remains capped, while Lustre continues to scale linearly. Lustre over ZFS performance also does not scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lustre vs NFS, 1M sequential reads
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feg0rbnbtchkyqy26v03b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feg0rbnbtchkyqy26v03b.png" alt="graph9" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6c9596qw7apo1w37m1py.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6c9596qw7apo1w37m1py.png" alt="graph10" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tests involving sequential workloads, including reads at both single and 32 jobs, show minimal performance differences between NFS and Lustre over ldiskfs.&lt;/p&gt;

&lt;p&gt;Note that the upper performance limit is around 45 GB/s, which is related to the performance of the network connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lustre vs NFS, 1M sequential writes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwg6oycz2dd57lj2oguo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwg6oycz2dd57lj2oguo.png" alt="graph11" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkx47o8hzv73gf7eb3976.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkx47o8hzv73gf7eb3976.png" alt="graph12" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The situation for sequential writes is similar, but for a single job only Lustre over ldiskfs demonstrates scalability.&lt;/p&gt;

&lt;p&gt;Note that the upper performance limit is around 45 GB/s, which is related to the performance of the network connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions for Lustre vs NFSoRDMA Testing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Lustre easily reaches the maximum network connection performance with a total throughput of 400 Gbps when using a small number of clients, which is exactly what we need.&lt;/li&gt;
&lt;li&gt;ZFS does not allow us to achieve the required performance numbers on small block IOs.&lt;/li&gt;
&lt;li&gt;NFS over RDMA performs better for NJ=1 and iodepth=1 but does not scale well on small random IOs.&lt;/li&gt;
&lt;li&gt;Lustre performs significantly better as the workload increases.&lt;/li&gt;
&lt;li&gt;Overall, NFS over RDMA can be considered a decent solution for sequential workloads, but it slightly lags behind Lustre in terms of write performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing Lustre in the Cloud Environment
&lt;/h2&gt;

&lt;p&gt;In this study, we investigated the virtualization of Lustre, specifically focusing on its OSS layer. We compared two data paths: a user-space implementation (using xiRAID Opus on SPDK) and a kernel-space implementation (Virtio-blk implementations within the Linux kernel). Both configurations utilized Lustre OPS_OSS and asynchronous I/O, with Opus leveraging Lustre OPS_OSS with asynchronous I/O and virtio-blk using aio=io_uring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoberkoj01onwpotrwpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhoberkoj01onwpotrwpw.png" alt="img58" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this image, you can see two deployment options. On the left is the option using Opus, and on the right is the option using xiRAID. As you can see, Opus will use only one core, while the virtual machines operating as Lustre OSS servers will use three virtual cores each. Meanwhile, xiRAID Classic will use eight cores.&lt;/p&gt;

&lt;p&gt;For each deployment option, we had two OSS virtual machines and two RAID Protected Volumes.&lt;/p&gt;

&lt;p&gt;Interestingly, both approaches delivered similar results for sequential reads and writes, reaching around 45 GB/s (the network capacity limit). The results were as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frad0pjqrnrcb3st2hrcs.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frad0pjqrnrcb3st2hrcs.PNG" alt="img75" width="732" height="181"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, with an Opus-based solution, we can achieve the same level of performance as with a xiRAID Classic-based solution while using 8 times fewer CPU resources. Overall, to saturate the performance of a 200 Gbps interface with Opus, only a single CPU core is needed.&lt;/p&gt;

&lt;p&gt;However, a significant difference emerged for random operations. The user-space approach exhibited scaling, while the kernel-space approach did not. This can be attributed to the limitation of virtio-blk implementation.&lt;/p&gt;

&lt;p&gt;The user-space approach offers promising results for achieving scalability in random operations. We observed performance of 4M IOPS for random reads and 1M IOPS for random writes.&lt;/p&gt;

&lt;p&gt;Additionally, we have completely replicated the performance results of the Bare Metal solution. However, we consumed significantly fewer computational resources and memory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3v87hzblxg58ov3s5kps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3v87hzblxg58ov3s5kps.png" alt="graph13" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43fq3og90txfovs4d3nj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43fq3og90txfovs4d3nj.png" alt="graph14" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions for Lustre in Cloud Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kernel-based virtio-blk achieves good performance on large IOs.&lt;/li&gt;
&lt;li&gt;Kernel block devices exposed to VM do not provide good performance on small block IOs.&lt;/li&gt;
&lt;li&gt;The solution is to run block device and vhost controller in user space: xiRAID Opus solves the problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Lustre stands out as a powerful option for data storage, even against established solutions like SAN and NFS. Lustre easily achieves performance matching the capabilities of network interfaces, 400 Gbps and above, using only two clients.&lt;/p&gt;

&lt;p&gt;Its asynchronous I/O function significantly boosts performance. For random workloads, it is essential to use asynchronous I/O. Additionally, it is crucial to use the correct backend for Lustre, as ZFS does not handle the load well at all. However, for the best results, further development of io_uring features is needed.&lt;/p&gt;

&lt;p&gt;Overall, the performance for synchronous small block IOs, after proper configuration, turned out to be quite good and even exceeded all our expectations. It approached half the capacity of a super high-performance block device, and we still see room for potential improvements in the future.&lt;/p&gt;

&lt;p&gt;When operating in a virtualized environment, using only a few CPUs, we can achieve performance levels comparable to a bare-metal solution while ensuring super-high flexibility in deploying resources on-demand where we need them – on any hypervisor, within GPU environments, or on external storage arrays.&lt;/p&gt;

&lt;p&gt;However, the high efficiency of the solution in terms of CPU resource consumption, as well as the ability to ensure high-performance access for small random IO, is possible only if specialized storage solutions operating in the Linux user space, such as xiRAID Opus, are used.&lt;/p&gt;

&lt;p&gt;Thank you for reading! If you have any questions or thoughts, please leave them in the comments below. I’d love to hear your feedback!&lt;/p&gt;

&lt;p&gt;Original article can be found &lt;a href="https://xinnor.io/blog/asynchronous-i-o-a-practical-guide-for-optimizing-hpc-workflows-with-xiraid-in-lustre-environments/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>raid</category>
      <category>lustre</category>
      <category>hpc</category>
      <category>storage</category>
    </item>
    <item>
      <title>High-Performance Block Volumes in Virtual Cloud Environments: Parallel File Systems Comparison</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Mon, 17 Mar 2025 19:32:46 +0000</pubDate>
      <link>https://dev.to/pltnvs/high-performance-block-volumes-in-virtual-cloud-environments-parallel-file-systems-comparison-11kn</link>
      <guid>https://dev.to/pltnvs/high-performance-block-volumes-in-virtual-cloud-environments-parallel-file-systems-comparison-11kn</guid>
      <description>&lt;p&gt;In virtualized cloud environments, supporting the intensive data demands of AI workloads requires a robust and scalable storage solution. Parallel file systems, such as Lustre and pNFS, provide the distributed data handling needed for these environments, allowing data to scale seamlessly across multiple nodes with minimal performance degradation. By integrating xiRAID Opus with these parallel file systems, Xinnor delivers enhanced storage performance, ensuring both random and sequential workloads achieve low-latency, high-throughput access. This blog explores how Lustre and pNFS, optimized with xiRAID Opus, create a flexible and high-performing storage architecture for AI-focused cloud environments.&lt;/p&gt;

&lt;p&gt;To address the scalability challenges posed by AI workloads in virtualized cloud environments, integrating parallel file systems like Lustre and pNFS becomes essential. These systems enable distributed data handling, ensuring that workloads can scale across numerous compute and storage nodes without a significant performance hit. By leveraging the underlying block device performance delivered by xiRAID Opus, parallel file systems further optimize both random and sequential workloads, ensuring low-latency, high-throughput access to shared storage resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Xinnor Lustre Solution for Cloud Environments
&lt;/h2&gt;

&lt;p&gt;Lustre is a well-known parallel file system used primarily in HPC environments, but it can also be leveraged for AI workloads, thanks to its scalability and high throughput. Lustre provides high availability over shared storage, making it ideal for cloud environments where reliability and performance are paramount.&lt;/p&gt;

&lt;p&gt;At Xinnor, we have extensive experience with Lustre, having successfully deployed it in numerous production environments. Our expertise extends into virtualized environments, where we enable the deployment of Lustre to provide high-performance storage solutions.&lt;/p&gt;

&lt;p&gt;In these setups, both the OSS and MDS components of Lustre are tuned by us for optimal performance. The architecture is built around disaggregated storage resources, which we transform into high-performance volumes using xiRAID Opus. These volumes are then passed through to virtual machines (VMs), forming the foundation for a highly scalable and efficient storage solution suited for AI workloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80vcsvq6r1n96ktrwyfg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80vcsvq6r1n96ktrwyfg.png" alt="Image1" width="800" height="700"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To validate our solution, we implemented a virtualized Lustre environment and conducted performance tests to demonstrate its scalability and efficiency for AI workloads in cloud environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fst79kf5wmubwtubqr2t3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fst79kf5wmubwtubqr2t3.png" alt="Image2" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Environment Details:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CPU: 64-Core Processor per node (AMD 7702P)&lt;/li&gt;
&lt;li&gt;Memory: 256 GB RAM per node&lt;/li&gt;
&lt;li&gt;Networking: 1 x MT28908 Family [ConnectX-6] per node&lt;/li&gt;
&lt;li&gt;Drives: 24x KIOXIA CM6-R 3.84TB (Gen 4)&lt;/li&gt;
&lt;li&gt;Aggregated drive performance per node:

&lt;ul&gt;
&lt;li&gt;9M IOPS (4k random read)&lt;/li&gt;
&lt;li&gt;3M IOPS (4k random write)&lt;/li&gt;
&lt;li&gt;70 GBps (128k sequential write/read)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Overview:
&lt;/h2&gt;

&lt;p&gt;Host Configuration:&lt;br&gt;
We deployed three virtual machines (VMs) across two hosts—two OSS and one Lustre MDS. Each VM was configured with dedicated RAID setups:&lt;br&gt;
OSS VMs use RAID 6 (16+2).&lt;br&gt;
The MDS VM uses RAID 1+1.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Host Configuration&lt;/strong&gt;:&lt;br&gt;
We deployed three virtual machines (VMs) across two hosts—two OSS and one Lustre MDS. Each VM was configured with dedicated RAID setups:&lt;br&gt;
a. OSS VMs use RAID 6 (16+2).&lt;br&gt;
b. The MDS VM uses RAID 1+1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Allocation&lt;/strong&gt;:&lt;br&gt;
Each storage controller within the VMs is assigned a single CPU core. In total, only three CPU cores are utilized for managing the block storage system, maximizing efficiency without compromising performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VM Configuration&lt;/strong&gt;:&lt;br&gt;
Each OSS and MDS VM is assigned three virtual cores for processing. The Lustre Client VMs are deployed on an external host, with each client VM provisioned with 32 cores, ensuring sufficient computational power for handling intensive workloads.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lustre Solution Performance
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9avmkfbcet3blnes60r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9avmkfbcet3blnes60r.png" alt="Image3.1" width="663" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9s2ooe5dwofmd1x15ent.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9s2ooe5dwofmd1x15ent.png" alt="Image3.2" width="732" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When testing &lt;strong&gt;sequential workloads&lt;/strong&gt; (1M block size, 32 jobs), we achieved the following performance metrics with xiRAID Opus: 44 GB/s at read and 43 GB/s at write operations.&lt;/p&gt;

&lt;p&gt;In addition to sequential workloads, we also tested random workloads, where xiRAID Opus demonstrated significantly better scaling at higher I/O depths compared to Lustre without it. This test used MDRAID (RAID 0) and Opus (RAID 6), showcasing the significant boost in both read and write performance when xiRAID Opus is incorporated into the solution. As seen in the graph above, Lustre with xiRAID Opus achieves remarkable performance growth, especially as the I/O depth increases. This scaling can be attributed to the efficiency of the multithreaded vhost-user-blk architecture, which distributes I/O tasks more effectively, leading to substantial improvements in throughput.&lt;/p&gt;

&lt;p&gt;However, one of the primary limitations in maximizing streaming throughput lies in the network interface capacity, which often acts as a bottleneck. Despite this constraint, xiRAID Opus ensures high performance by maximizing network utilization, effectively mitigating the impact of network limitations.&lt;/p&gt;

&lt;p&gt;Moreover, while Lustre has traditionally been considered unsuitable for small block I/O operations, recent advancements have significantly enhanced its capabilities. With improved asynchronous I/O support and the integration of high-performance interfaces, low-latency devices can now be passed directly into the MDS. This innovation, in combination with xiRAID Opus, delivers strong small block I/O performance, addressing a critical pain point for AI and cloud workloads that demand efficient data handling at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reducing the Complexity of Lustre Administration with VirtioFS
&lt;/h2&gt;

&lt;p&gt;When managing file systems in virtualized environments, one of the key challenges is reducing administrative complexity while maintaining performance. To address this, we implemented &lt;strong&gt;VirtioFS&lt;/strong&gt;, a solution for sharing file systems directly between hosts and VMs. VirtioFS eliminates the need for installing client software within the VMs by sharing a mounted file system from the host. This simplification makes it an ideal solution for cloud service providers, reducing administrative burden without sacrificing performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frky0jvjs3ldqwidgjdrh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frky0jvjs3ldqwidgjdrh.png" alt="Image4" width="792" height="817"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Xinnor-tuned VirtioFS: Performance Results
&lt;/h2&gt;

&lt;p&gt;To fully optimize file system performance in virtualized environments, we’ve applied tuning to VirtioFS. This tuning allows VirtioFS to deliver performance on par with native Lustre clients, even in heavily virtualized environments. The performance improvements are especially significant in high-throughput workloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9c6zuafuxym6ss10ujlb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9c6zuafuxym6ss10ujlb.png" alt="Image5" width="764" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sequential operations results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xr8luftpl4eaf05qtnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xr8luftpl4eaf05qtnl.png" alt="Image61" width="750" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fehv8k3hlpdf5oc2d7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6fehv8k3hlpdf5oc2d7y.png" alt="Image6.2" width="688" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These results show that with the right optimizations, VirtioFS can match the performance of native Lustre clients in sequential workloads while still providing the simplicity of a virtualized file system environment. However, in random operations VirtioFS is not able to demonstrate the same level of scalability as the native Lustre client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Xinnor Lustre Solution Outcomes
&lt;/h2&gt;

&lt;p&gt;The Xinnor Lustre solution demonstrates powerful performance capabilities, even with a virtualized setup. By pairing xiRAID Opus with virtualized Lustre OSS and MDS components, our solution is capable of handling both sequential and random I/O operations with minimal overhead. Key outcomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;:&lt;br&gt;
a. With only two virtualized OSS, Lustre delivers impressive sequential and random I/O performance.&lt;br&gt;
b. Critical to this performance is the high-performance block device provided by xiRAID Opus, which is passed directly to the OSS and MDS virtual machines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Skill Requirements&lt;/strong&gt;:&lt;br&gt;
a. While Lustre configuration requires advanced expertise to set up the system and client VMs, VirtioFS offers a simplified alternative for workloads with primarily sequential patterns, reducing complexity without sacrificing throughput.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solution for Cloud Environments&lt;/strong&gt;:&lt;br&gt;
a. Xinnor can deliver this high-performance Lustre solution for cloud-based environments, tailored to AI workloads as well as HPC.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While Lustre has a legacy in HPC environments, it’s also highly effective for AI-centric workloads. However, Lustre can be complex to administer, particularly in cloud environments, where configurations like LNET and client setups add layers of complexity. Additionally, Lustre supports a limited number of operating systems, making expert configuration essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Vision for the Future: pNFS Block Layout
&lt;/h2&gt;

&lt;p&gt;pNFS (Parallel NFS) Block Layout is a part of the pNFS extension in NFSv4.1, designed to enable parallel access to storage devices, improving scalability and performance.&lt;/p&gt;

&lt;p&gt;The block layout specifically focuses on enabling clients to access storage blocks directly, bypassing the NFS server for data transfers. This layout is ideal for environments where block storage devices (like SANs) are used, providing high-performance parallel access to large datasets.&lt;/p&gt;

&lt;p&gt;This approach allows VMs to directly interact with xiRAID Opus block volumes, while a pNFS MDS server manages scalability. This flexible design minimizes the complexity of shared storage setups in cloud environments, ensuring both scalability and high performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rz20wwngvbsimcb02mm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rz20wwngvbsimcb02mm.png" alt="Image7" width="800" height="789"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key Features of pNFS Block Layout:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Direct Data Access&lt;/strong&gt;: Clients can bypass the NFS server and read/write directly to storage volumes using block-level protocols (e.g., iSCSI, Fibre Channel), reducing bottlenecks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate Data and Metadata Paths&lt;/strong&gt;: The NFS server manages metadata, but the data itself flows directly between clients and storage, streamlining performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Access&lt;/strong&gt;: pNFS allows multiple clients to read/write to different sections of a file simultaneously, improving throughput for large datasets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: By offloading data transfers to the storage devices themselves, pNFS supports high-scale operations, making it a perfect fit for cloud environments handling AI workloads or massive data sets.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  pNFS Architecture in Cloud Environments
&lt;/h2&gt;

&lt;p&gt;The beauty of pNFS is its simplicity, offering high-performance shared storage while requiring minimal system resources. It doesn’t need third-party client software or the direct passing of a high-performance network to VMs, making it incredibly versatile.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shared Storage Support: pNFS can efficiently manage high-performance storage with low CPU overhead.&lt;/li&gt;
&lt;li&gt;No Third-Party Software: Data volumes can be shared across compute nodes without needing additional software, simplifying the overall architecture.
What makes this architecture especially appealing is that it leverages the same hardware we used in our Lustre testing earlier, showing just how adaptable and powerful pNFS can be.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fun9ut6wkq3ebuxvuc1md.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fun9ut6wkq3ebuxvuc1md.png" alt="Image66" width="800" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  pNFS Performance Results
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pphxl7frxq1dsf6s3oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pphxl7frxq1dsf6s3oh.png" alt="Image86" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sequential operations (1M, 32 jobs):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sequential Read:

&lt;ul&gt;
&lt;li&gt;Without xiRAID Opus: 34.8 GB/s&lt;/li&gt;
&lt;li&gt;With xiRAID Opus: 47 GB/s&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Sequential Write:

&lt;ul&gt;
&lt;li&gt;Without xiRAID Opus: 32.7 GB/s&lt;/li&gt;
&lt;li&gt;With xiRAID Opus: 46 GB/s&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By integrating xiRAID Opus, we further optimized the performance of pNFS block layouts. When we compare pNFS with and without xiRAID Opus, the results clearly demonstrate its value in high-performance environments. This test used MDRAID (RAID 0) and Opus (RAID 6), showcasing the significant boost in both read and write performance when xiRAID Opus is incorporated into the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  pNFS vs Lustre: Accelerated by Xinnor Solutions
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flna4o6a1sxwjnbhrdsvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flna4o6a1sxwjnbhrdsvz.png" alt="Image090" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When comparing the pNFS block layout to Lustre, our solutions provide significant acceleration in both setups. Both Lustre and pNFS, when paired with xiRAID Opus, are capable of delivering strong, near-equal performance in high-throughput environments:&lt;/p&gt;

&lt;p&gt;Sequential Performance Comparison (1M, 32 jobs):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sequential Read:

&lt;ul&gt;
&lt;li&gt;Lustre: 44 GB/s&lt;/li&gt;
&lt;li&gt;pNFS: 47 GB/s&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Sequential Write:

&lt;ul&gt;
&lt;li&gt;Lustre: 43 GB/s&lt;/li&gt;
&lt;li&gt;pNFS: 46 GB/s&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These results demonstrate that both Lustre and pNFS, when optimized by xiRAID Opus, are powerful solutions, capable of delivering outstanding performance in high-performance cloud environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  pNFS in Cloud Environments: Conclusions
&lt;/h2&gt;

&lt;p&gt;We believe pNFS represents the future of scalable, high-performance storage in cloud environments. With proper configuration, pNFS block layout can achieve tens or even hundreds of gigabytes per second in throughput, with minimal resource consumption.&lt;/p&gt;

&lt;p&gt;Key Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Supports large-scale environments, offering massive throughput potential with low system overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Performance&lt;/strong&gt;: Delivers exceptional performance for both sequential and random small block operations, with minimal latency due to direct interaction with storage devices.&lt;/li&gt;
&lt;li&gt;No &lt;strong&gt;Third-Party Client Software&lt;/strong&gt;: Simplifies setup and management by removing the need for additional software on client machines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Challenges:&lt;/p&gt;

&lt;p&gt;While pNFS is highly promising, the current Open Source MDS is not production-ready, making it suitable for POCs but not yet for full production environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Xinnor offers two robust solutions tailored for AI workloads in cloud environments: xiRAID Opus and the Xinnor Lustre Solution. These high-performance tools are engineered to handle the demanding nature of AI applications. Our comparison of Lustre and pNFS, accelerated by xiRAID Opus, demonstrates that both parallel file systems provide exceptional scalability and performance for AI workloads in virtualized cloud settings. Lustre offers high throughput and reliability, making it suitable for complex cloud environments. On the other hand, pNFS presents a simpler, versatile alternative that minimizes setup complexity without sacrificing performance. While each solution has unique strengths, xiRAID Opus consistently enhances both, supporting fast, efficient data access across multiple cloud-based nodes. Together, these parallel file systems and xiRAID Opus form a powerful foundation for AI workloads.&lt;/p&gt;

&lt;p&gt;You can read the original blogpost &lt;a href="https://xinnor.io/blog/high-performance-block-volumes-in-virtual-cloud-environments-parallel-file-systems-comparison/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>highperformance</category>
      <category>performance</category>
      <category>ai</category>
      <category>virtualmachine</category>
    </item>
    <item>
      <title>How to Build High-Performance NFS Storage with xiRAID Backend and RDMA Access</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Mon, 17 Mar 2025 15:54:54 +0000</pubDate>
      <link>https://dev.to/pltnvs/how-to-build-high-performance-nfs-storage-with-xiraid-backend-and-rdma-access-1ok4</link>
      <guid>https://dev.to/pltnvs/how-to-build-high-performance-nfs-storage-with-xiraid-backend-and-rdma-access-1ok4</guid>
      <description>&lt;p&gt;This paper outlines the process of configuring a high-performance Network File System (NFS) storage solution using the xiRAID RAID engine, Remote Direct Memory Access (RDMA), and the XFS file system. Modern data-intensive workloads (such as those in AI &amp;amp; machine learning, high-performance computing, scientific research, media &amp;amp; entertainment (e.g., 4K/8K video rendering, real-time asset streaming), virtualized environments requiring rapid storage access, etc.) demand storage subsystems capable of delivering extreme throughput with minimal latency.&lt;/p&gt;

&lt;p&gt;By leveraging xiRAID’s optimized RAID engine alongside RDMA’s low-latency data transfers and XFS’s scalability, this approach achieves unprecedented sequential access performance, critical for large-scale datasets, while offering actionable insights for improving random read/write efficiency.&lt;/p&gt;

&lt;p&gt;The document focuses on maximizing throughput and reducing latency, particularly for sequential access patterns common in scenarios like AI/ML model training, large-scale HPC simulations, real-time media rendering pipelines, virtualized infrastructure requiring consistent I/O performance, etc. Though it does not cover full production configurations (e.g., security settings), the procedures outlined enable organizations to deploy a high-performance NFS storage foundation that balances simplicity, scalability, and raw speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  InfiniBand Network Setup
&lt;/h3&gt;

&lt;p&gt;For RDMA access, both the NFS server and clients must have the NVIDIA MLNX_OFED driver support (--with-nfsrdma) installed. Download the appropriate driver for your operating system from &lt;a href="https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/" rel="noopener noreferrer"&gt;NVIDIA’s website&lt;/a&gt; and install it using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./mlnxofedinstall --with-nfsrdma
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure that similar configurations are applied on the NFS clients. Configure the InfiniBand adapters and verify the network settings. The following utilities can be used to check the performance of the Infiniband network:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ib_send_bw for bandwidth testing.&lt;/li&gt;
&lt;li&gt;ib_send_lat for latency testing.&lt;/li&gt;
&lt;li&gt;ib_read_bw and ib_read_lat for RDMA read bandwidth/latency.&lt;/li&gt;
&lt;li&gt;ib_write_bw and ib_write_lat for RDMA write bandwidth/latency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disk Subsystem Performance Check
&lt;/h3&gt;

&lt;p&gt;Before setting up RAID, configuring a file system and NFS server, determine the desired RAID level for data and file system journals.&lt;/p&gt;

&lt;p&gt;Test raw drive performance to ensure no bottlenecks exist at the server or disk subsystem level. Refer to Xinnor's performance guide for detailed recommendations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://xinnor.io/blog/performance-guide-pt-1-performance-characteristics-and-how-it-can-be-measured/" rel="noopener noreferrer"&gt;https://xinnor.io/blog/performance-guide-pt-1-performance-characteristics-and-how-it-can-be-measured/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://xinnor.io/blog/performance-guide-pt-2-hardware-and-software-configuration/" rel="noopener noreferrer"&gt;https://xinnor.io/blog/performance-guide-pt-2-hardware-and-software-configuration/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After ensuring that the drives performance meets the requirements, start setting up RAID and configuring the file system.&lt;/p&gt;

&lt;h3&gt;
  
  
  xRAID Setup
&lt;/h3&gt;

&lt;p&gt;This document uses RAID 6 with 10 drives and a strip size of 128k for data, and RAID 0 with a strip size of 16k for file system logs. (In production environment it is better to use RAID 1 or 10).&lt;/p&gt;

&lt;p&gt;Install the latest xiRAID version using &lt;a href="https://xinnor.io/resources/xiraid-classic/" rel="noopener noreferrer"&gt;the documentation&lt;/a&gt; and create the RAID arrays as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xicli raid create -n media6 -l 6 -d /dev/nvme16n2 /dev/nvme9n2 /dev/nvme20n2 /dev/nvme18n2 /dev/nvme8n2 /dev/nvme12n2 /dev/nvme13n2 /dev/nvme19n2 /dev/nvme23n2 /dev/nvme24n2 -ss 128
xicli raid create -n media0 -l 0 -d /dev/nvme7n1 /dev/nvme6n1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the RAID status after the initialization process is complete using xicli raid show&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30bef90367okcgtxnfz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30bef90367okcgtxnfz4.png" alt="Image1" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating the RAID array, verify that the performance at the RAID layer meets expectations before proceeding to file system creation. For RAID performance checks and additional tuning, refer to the materials in Xinnor's performance guide.&lt;/p&gt;

&lt;p&gt;Based on our testing experience, the sequential write speed to the RAID should be approximately 90-95% of the write speed to raw data drives.&lt;/p&gt;

&lt;h3&gt;
  
  
  XFS Setup and Mount
&lt;/h3&gt;

&lt;p&gt;Create the XFS file system with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkfs.xfs -d su=128k,sw=8 -l logdev=/dev/xi_media0,size=1G /dev/xi_media6 -f -ssize=4k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the geometry of your RAID, the file system creation options may vary. Pay special attention to parameters such as su=128k and sw=8, as these are important for aligning the file system geometry with the RAID configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4azjq1ebsgt5svyvgzl9.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4azjq1ebsgt5svyvgzl9.PNG" alt="Image2" width="800" height="686"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mount the file system using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mount -t xfs /dev/xi_media6 /mnt/data -o logdev=/dev/xi_media0,noatime,nodiratime,logbsize=256k,largeio,inode64,swalloc,allocsize=131072k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoy74huh5kj6nso74228.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feoy74huh5kj6nso74228.PNG" alt="Image3" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similar to the RAID setup, you should also test the performance of the file system by writing several large files to a directory. The performance should be approximately 70-80% of the RAID performance for writes and 90-100% for reads.&lt;/p&gt;

&lt;p&gt;For permanent mounting of the file system, follow the recommendations in the &lt;a href="https://xinnor.io/docs/xiRAID-4.2.0/E/en/AG/2/file_system_mounting_aspects.html" rel="noopener noreferrer"&gt;xiRAID documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  NFS Server Setup
&lt;/h3&gt;

&lt;p&gt;With the disk subsystem, RAID, and file system properly configured, the next step is to install and configure the NFS server. The installation is straightforward, but several optimizations are necessary to achieve better performance.&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Install&lt;/strong&gt; nfs-utils &lt;strong&gt;packages&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yum install nfs-utils
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.&lt;strong&gt;Firewall setup&lt;/strong&gt;. Below is an example of a simple firewall configuration for a test environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=mountd
firewall-cmd --permanent --add-service=rpc-bind
firewall-cmd --reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3.&lt;strong&gt;NFS share directory creation&lt;/strong&gt;. The following commands create a directory for an NFS file share. These settings are suitable for testing purposes only, as they do not include access restrictions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p /mnt/data
chown nfsnobody:nfsnobody /mnt/data
chmod 777 /mnt/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4.&lt;strong&gt;NFS export configuration&lt;/strong&gt;. For the /mnt/data directory, typically found in /etc/exports. If the file does not exist, create it manually and add the following line in the /etc/exports file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/mnt/data *(rw,sync,insecure,no_root_squash,no_subtree_check,no_wdelay)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi49gctl6vo70ognftt9t.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi49gctl6vo70ognftt9t.PNG" alt="Image4" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5.&lt;strong&gt;NFS Server configuration tuning&lt;/strong&gt;. Edit the NFS server configuration file /etc/nfs.conf to adjust the number of threads for handling requests and enable RDMA connections. The configuration should resemble the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[exportd]
# debug="all|auth|call|general|parse"
# manage-gids=n
# state-directory-path=/var/lib/nfs
threads=64

[nfsd]
# debug=0
threads=64
# host=
# port=0
# grace-time=90
# lease-time=90
# udp=n
# tcp=y
vers3=y
vers4=y
vers4.0=y
vers4.1=y
vers4.2=y
rdma=y
rdma-port=20049
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbamc53qlixh0icwwolx9.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbamc53qlixh0icwwolx9.PNG" alt="Image5" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6.&lt;strong&gt;Enable, restart and check NFS Server&lt;/strong&gt;&lt;br&gt;
After applying all settings, enable and restart the NFS server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl enable nfs-server
systemctl restart nfs-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the status of the NFS server to ensure there are no errors, particularly those related to the RDMA module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl status nfs-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NFS Client Setup
&lt;/h3&gt;

&lt;p&gt;You can now proceed to configure the NFS client.&lt;/p&gt;

&lt;p&gt;7.&lt;strong&gt;Install nfs-utils packages&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yum install nfs-utils
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;8.&lt;strong&gt;NFS client kernel module options&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Add the following line to /etc/modprobe.d/nfsclient.conf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;options nfs max_session_slots=180
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Increasing the max_session_slots value allows more simultaneous in-flight requests, improving performance for workloads with many small or parallel I/O operations.&lt;/p&gt;

&lt;p&gt;9.&lt;strong&gt;Reboot the system&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;10.&lt;strong&gt;Mount NFS Share&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a directory for the NFS file share (in this example, /mnt/nfs) and mount it using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mount -o rdma,port=20049,nconnect=16,vers=4.2 10.239.239.100:/mnt/data /mnt/nfs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvp9oajwp436br7z4xosw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvp9oajwp436br7z4xosw.PNG" alt="Image6" width="800" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After completing the setup, you can run performance tests from the NFS client. If everything is configured correctly, the performance should meet expectations. Use fio with the following configuration for testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[global]
rw=read
#rw=write
bs=1024K
iodepth=32
direct=1
ioengine=libaio
runtime=4000
size=32G
numjobs=4
group_reporting
exitall

[job3]
directory=/mnt/nfs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the configuration, you can expect NFS performance to be 50-70% of the XFS file system's performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;By following the outlined steps, users can set up a high-performance NFS storage system leveraging xiRAID and RDMA. The configuration ensures optimal performance for sequential data access patterns and provides flexibility for tuning based on specific workload requirements. For production environments, additional configurations such as security settings should be applied as needed.&lt;/p&gt;

&lt;p&gt;Read more &lt;a href="https://xinnor.io/blog/how-to-build-high-performance-nfs-storage-with-xiraid-backend-and-rdma-access/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>performance</category>
      <category>rdma</category>
      <category>nfs</category>
      <category>storage</category>
    </item>
    <item>
      <title>High-Performance Storage Solution for PostgreSQL in Virtual Environments with XIRAID Engine and Kioxia PCIe5 Drives</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Wed, 12 Mar 2025 14:30:18 +0000</pubDate>
      <link>https://dev.to/pltnvs/high-performance-storage-solution-for-postgresql-in-virtual-environments-with-xiraid-engine-and-4lkb</link>
      <guid>https://dev.to/pltnvs/high-performance-storage-solution-for-postgresql-in-virtual-environments-with-xiraid-engine-and-4lkb</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Objectives&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;PostgreSQL is a highly popular open-source database due to its rich feature set, robust performance, and flexible data handling. It is used everywhere from small websites to large-scale enterprise applications, attracting users with its object-relational capabilities, advanced indexing, and strong security. However, to truly unleash its potential, PostgreSQL demands fast storage. Its transactional nature and ability to handle large datasets require low latency and high throughput. This is why pairing PostgreSQL with fast storage solutions is crucial for optimizing performance, minimizing downtime, and ensuring seamless data access for demanding workloads.&lt;/p&gt;

&lt;p&gt;For flexibility, scalability and cost optimization, it is preferrable to run PostgreSQL on Virtual Machines, especially in development and testing environments. But sometimes, Virtualization introduces an abstraction layer that can lead to performance overhead compared to running directly on bare metal. On the other hand, using just bare metal leads to non-optimal usage of the CPU and storage resources, because one application typically doesn’t fully utilize the bare metal server performance.&lt;/p&gt;

&lt;p&gt;In this document, we’ll look at the optimal way to provide high performance to PostgreSQL in a virtualized environment.&lt;/p&gt;

&lt;p&gt;With this goal, we are comparing the performance of vHOST Kernel Target with Mdadm against SPDK vhost-blk target protected by Xinnor’s xiRAID Opus.&lt;/p&gt;

&lt;p&gt;Mdadm, which stands for "Multiple Devices Administration", is a software tool used in Linux systems to manage software RAID (Redundant Array of Independent Disks) configurations. Unlike hardware RAID controllers, mdadm relies on the computer's CPU and software to achieve data redundancy and performance improvements across multiple physical disks.&lt;/p&gt;

&lt;p&gt;XiRAID Opus (Optimized Performance in User Space) is a high-performance software RAID engine based on the SPDK libraries, designed specifically for NVMe storage devices.&lt;/p&gt;

&lt;p&gt;We are focusing the benchmark on software RAID, as hardware RAID has only 16 PCIe lanes, meaning that by the design the performance is limited to the one of maximum 4 NVMe drives per controller, which is not sufficient for PostgreSQL applications.&lt;/p&gt;

&lt;p&gt;As testing tool, we employed the pgbench utility and conducted tests on all three built-in scripts: tpcb-like, simple-update, and select-only. The script details are provided in Appendix 2.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Test Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Hardware Configuration:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Motherboard&lt;/em&gt;&lt;/strong&gt;: Supermicro H13DSH&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU&lt;/strong&gt;: Dual AMD EPYC 9534 64-Core Processors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt;: 773,672 MB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drives&lt;/strong&gt;: 10xKIOXIA KCMYXVUG3T20&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Software Configuration:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OS&lt;/strong&gt;: Ubuntu 22.04.3 LTS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kernel&lt;/strong&gt;: Version 5.15.0-91-generic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;xiRAID Opus&lt;/strong&gt;: Version xnr-1077&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QEMU Emulator&lt;/strong&gt;: Version 6.2.0&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  RAID Configuration:
&lt;/h4&gt;

&lt;p&gt;Two RAID groups (4+1 configuration) were created utilizing drives on 2 independent NUMA nodes. The stripe size was set to 64K. A full RAID initialization was conducted prior to benchmarking.&lt;/p&gt;

&lt;p&gt;Each RAID group was divided into 7 segments, with each segment being allocated to a virtual machine via a dedicated vhost controller.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary of Resources Allocated:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RAID Groups&lt;/strong&gt;: 2&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volumes&lt;/strong&gt;: 14&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;vhost Controllers&lt;/strong&gt;: 14&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VMs&lt;/strong&gt;: 14, with each using segmented RAID volumes as storage devices.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3989lhq55uqc0zdbncvf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3989lhq55uqc0zdbncvf.png" alt="Distibution of Virtual machines" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Distribution of virtual machines, vhost controllers, RAID groups and NVMe drives&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;During the creation of mdraid, volumes, and vhost targets, assignment to specific CPU cores was not conducted because not supported. Nevertheless, virtual machines continued to operate on specific cores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3k16igfxed69lvp0556i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3k16igfxed69lvp0556i.png" alt="XiRAID" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;xiRAID. Placement of the array and VMs on cores&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With xiRAID it is possible to assign the RAID engine to specific cores. In this example we are using 8 cores for any NUMA node. Such placement allows to separate infrastructure and database workload, and to isolate VM loads from each other.&lt;/p&gt;

&lt;p&gt;This feature is not available on MDRAID, so the application must share the core resources with the RAID engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn83mjv4bs5032ew70kkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn83mjv4bs5032ew70kkd.png" alt="mdraid" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;mdraid. Placement of the array and VMs on cores&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Virtual Machine Configuration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CPU Allocation&lt;/strong&gt;: 8&lt;br&gt;
-cpu host -smp 8&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;QEMU Memory Configuration&lt;/strong&gt;:&lt;br&gt;
&lt;strong&gt;Memory Allocation&lt;/strong&gt;: Each VM is provisioned with 32 GB of RAM via Hugepages. Memory is pre-allocated and bound to the same NUMA node as the allocated vCPUs to ensure efficient CPU-memory interaction.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-m 32G -object memory-backend-file,id=mem,size=32G,mem-path=/dev/hugepages,
share=on,prealloc=yes,host-nodes=0,policy=bind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Operating System&lt;/strong&gt;: VMs run Debian GNU/Linux 12 (Bookworm)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL Version&lt;/strong&gt;: 15&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL Configuration&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install postgresql-15 // installing PostgreSQL 15
cd /etc/postgresql/15/main/
sed -i 's|/var/lib/postgresql/15/main|/test/postgresql/15/main|g' postgresql.conf //
configuring the folder for the data
sed -i -e "s/^#\?\s*listen_addresses\s*[=]\s*[^\t#]*/listen_addresses = '127.0.0.1'/" postgresql.conf
sed -i -e "/^max_connections/s/[= ][^\t#]*/ = '300'/" postgresql.conf // increasing the number of connections up to 300

apt-get install xfsprogs
mkdir /test
mkfs.xfs /dev/vda -f
mount /dev/vda /test -o discard,noatime,largeio,inode64,swalloc,allocsize=64M -t xfs
cp -rp /var/lib/postgresql /test/
service postgresql restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configuring the folder for the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo -u postgres createdb test
sudo -u postgres pgbench -i -s 50000 test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created and initialized the database for testing purposes. It is important to choose the scaling correctly, so that all data does not fit into the RAM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;We conducted tests while varying the number of clients and reported in this document only those where we achieved the maximum stable results. To adjust the number of clients, we selected the following values for the parameter -c (number of clients simulated, equal to the number of concurrent database sessions): 10, 20, 50, 100, 200, 500, 1000. For all script types, we reached a plateau at 100 clients.&lt;/p&gt;

&lt;p&gt;As best practice, we fixed the parameter -j (number of worker threads within pgbench*) equal to the number of VM cores.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using more than one thread can be helpful on multi-CPU machines. Clients are distributed as evenly as possible among available threads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tests appear as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo -u postgres pgbench -j 8 -c 100 -b select-only -T 200 test
sudo -u postgres pgbench -j 8 -c 100 -b simple-update -T 200 test
sudo -u postgres pgbench -j 8 -c 100 -T 200 test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We conducted the test three times and recorded the average results across all virtual machines. Additionally, we performed select-only tests in degraded mode, as this script generates the maximum load on reading, enabling an assessment of the maximum impact on the database performance.&lt;/p&gt;

&lt;p&gt;During the test, we monitored the array performance using the iostat utility. The total server performance comprises the sum of the performance of all machines (14 for xiRAID Opus and 16 for mdraid).&lt;/p&gt;

&lt;h4&gt;
  
  
  Select-only Test Results
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faggzxu0qd0m4i8585d0e.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faggzxu0qd0m4i8585d0e.PNG" alt="Select-only" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Select-only Test Results, Degraded Mode
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feb9yyhucap2drstpfnp3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feb9yyhucap2drstpfnp3.PNG" alt="Degraded mode" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Simple-update Test Results
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi63oj2l8flbz7khou3qm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi63oj2l8flbz7khou3qm.PNG" alt="Simple-update" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  TPC-B-like Test Results
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne8nhewhlzgzchpv55nt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne8nhewhlzgzchpv55nt.PNG" alt="TPC" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In select-only, with all the drives in the RAID operating properly, xiRAID Opus provides 30-40% better transaction per second than mdraid. Mdraid is nearing its maximum capabilities, and further scaling (by increasing the number of cores for virtual machines) would become challenging. This is not the case for xiRAID. The main reason for such a difference is the fact that xiRAID Opus enables the vhost target to run on a separate CCD.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When comparing different protection schemes, we cannot stop at measuring performance in normal operation. Indeed, RAID protection is needed to prevent data loss in case of one or more drives failure. In this situation (degraded mode), maintaining high performance is critical to avoid downtime to the database users.&lt;/p&gt;

&lt;p&gt;When comparing performance in degraded mode, mdraid experiences a significant drop in performance, leading to over 20X times slower performance than xiRAID. In other terms, with MDRAID, users will be waiting for their data and this situation can lead to business losses (think about an online travel agency or a trading company).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;When it comes to writing data to the database, each write of small blocks generates RAID calculations. In this situation, mdraid's performance is six times worse than xiRAID Opus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The TPC-B Like script is more complex than the simple update and consumes more CPU resources, which again slows down mdraid on write operations. In this case, xiRAID outpaces mdraid by five times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In conclusion, xiRAID provides great and stable performance to multiple VMs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means that applications will be able to get access to their data without any delay, even in case of drive failures or extensive write operations.&lt;/p&gt;

&lt;p&gt;Furthermore, the scalability of xiRAID on VMs allows the system admin to consolidate the number of servers needed for large/multiple Database deployments. This benefit oversimplifies the storage infrastructure while providing great cost saving.&lt;/p&gt;

&lt;p&gt;Thank you for reading! If you have any questions or thoughts about this high-performance storage solution for PostgreSQL, please leave them in the comments below. I'd love to hear your feedback and discuss how this setup could benefit your projects!&lt;/p&gt;

&lt;h3&gt;
  
  
  Appendix 1. mdraid Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;md0 : active raid5 nvme40n2[5] nvme45n2[3] nvme36n2[2] nvme46n2[1] nvme35n2[0]
12501939456 blocks super 1.2 level 5, 64k chunk, algorithm 2 [5/5] [UUUUU]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bitmaps disabled
cat /sys/block/md0/md/group_thread_cnt
16
Vhost target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figtwu1wjtbsfp272hpl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figtwu1wjtbsfp272hpl1.png" alt="Example code launching" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Example Code for Launching VMs
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;taskset -a -c $CPU qemu-system-x86_64 -enable-kvm -smp 8 -cpu host -m 32G -drive file=$DISK_FILE,format=qcow2 --nographic \
-device vhost-scsi-pci,wwpn=naa.5001405dc22c8c4e,bus=pci.0,addr=0x5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Original article can be found &lt;a href="https://xinnor.io/blog/high-performance-storage-solution-for-postgresql-database-in-virtual-environment-boosted-by-xiraid-engine-and-kioxia-pcie5-drives/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>postgressql</category>
      <category>database</category>
      <category>datastorage</category>
    </item>
    <item>
      <title>Understanding RAID Levels: A Comprehensive Guide to RAID 0, 1, 5, 6, 10, and Beyond</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Wed, 12 Mar 2025 14:27:43 +0000</pubDate>
      <link>https://dev.to/pltnvs/understanding-raid-levels-a-comprehensive-guide-to-raid-0-1-5-6-10-and-beyond-35f6</link>
      <guid>https://dev.to/pltnvs/understanding-raid-levels-a-comprehensive-guide-to-raid-0-1-5-6-10-and-beyond-35f6</guid>
      <description>&lt;p&gt;In today’s fast-paced digital landscape, data storage is crucial for safeguarding critical information. &lt;a href="https://xinnor.io/what-is-xiraid/" rel="noopener noreferrer"&gt;RAID &lt;/a&gt;technology has revolutionized data storage, offering improved performance, increased data redundancy, and optimized capacity. However, with various RAID levels available, selecting the ideal configuration can be challenging.&lt;/p&gt;

&lt;p&gt;In this comprehensive article, we demystify RAID technology, guiding you through the intricacies of RAID 0, RAID 1, RAID 5, RAID 6, RAID 10, and more. By exploring their characteristics, benefits, and drawbacks, we empower you to make informed decisions that align with your specific storage demands. Whether you’re a tech enthusiast, system administrator, or business owner, this guide equips you with the expertise to fortify your data infrastructure effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  RAID 0
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeyztuggwgqasmatz2v4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faeyztuggwgqasmatz2v4.PNG" alt="RAID 0 diagram" width="581" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RAID 0 encompasses a configuration wherein all drives are merged into a single logical one. This level delivers exceptional performance at a reduced cost. However, it lacks data protection mechanisms, rendering it highly susceptible to data loss in the event of a drive failure. Consequently, the adoption of RAID 0 is not recommended for mission critical data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Offers high-speed performance and availability while maintaining a cost-effective approach.&lt;/li&gt;
&lt;li&gt;Utilizes the entire capacity of each individual drive.&lt;/li&gt;
&lt;li&gt;Configuration is straightforward and user-friendly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RAID 0 lacks any form of data protection.&lt;/li&gt;
&lt;li&gt;In the event of a single drive failure, all data becomes irreversibly lost, with no possibility of recovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Areas of application
&lt;/h3&gt;

&lt;p&gt;This RAID level is advisable for implementation in non-mission-critical scenarios. RAID 0 is suitable for purposes where the primary concern is maximizing performance and data read/write speeds. It is commonly used in scenarios where data redundancy (fault tolerance) is not a critical requirement, and the main focus is on improving the system’s overall data processing capabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35jbdk958n9i461ptj5d.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F35jbdk958n9i461ptj5d.PNG" alt="Raid 1" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RAID 1
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwn8jzvv359veev5uzrh.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwn8jzvv359veev5uzrh.PNG" alt="Raid1" width="415" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RAID 1, also known as “mirroring,” is a method in which all data is duplicated on two separate drives, with one set of data appearing as a logical drive. RAID 1 is primarily focused on providing data protection rather than improving performance or increasing storage capacity. Because data is replicated over 2 drives, the usable capacity is 50% of the total available drives in the RAID array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;High levels of redundancy — each drive is an exact copy of another.&lt;/li&gt;
&lt;li&gt;If one drive fails, the system continues to function normally with no data loss.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Usable capacity is limited to 50% due to the need to store complete duplicates of data.&lt;/li&gt;
&lt;li&gt;RAID 1 performance does not significantly exceed that of a single drive.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Areas of application
&lt;/h3&gt;

&lt;p&gt;This RAID level finds frequent utilization in scenarios where storage capacity and cost are not a concern, yet the imperative requirement lies in the ability to fully recover data in the event of a drive failure. It’s commonly used for booth drives, small business applications, and personal data storage, ensuring continuous access to information even if one drive fails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuiyrx7opebqahagcr0n7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuiyrx7opebqahagcr0n7.PNG" alt="raID5" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RAID 5
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvj382vulo64vkl6nync.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvj382vulo64vkl6nync.PNG" alt="rAID5." width="735" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RAID 5, widely regarded as the most prevalent and versatile RAID level, employs a technique known as data block striping across the entirety of drives within the array (comprising 3 to N drives). It further distributes parity information evenly across all drives. In the event of a single drive failure, the system utilizes the parity information from the functioning drives to recover lost data blocks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Strikes a favorable balance between cost and performance considerations.&lt;/li&gt;
&lt;li&gt;Capability to recover data in the event of a single drive failure.&lt;/li&gt;
&lt;li&gt;Enhanced data read performance.&lt;/li&gt;
&lt;li&gt;Scalability: RAID 5 facilitates effortless expansion of storage capacity by incorporating additional drives without system interruption.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages:
&lt;/h3&gt;

&lt;p&gt;Parity storage leads to a reduction in individual drive capacity.&lt;br&gt;
data loss in case 2 drives fail in the array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Areas of application
&lt;/h3&gt;

&lt;p&gt;This RAID level enjoys widespread adoption across diverse environments, including file servers, general-purpose storage servers, backup servers, and streaming data applications, among others. It offers superior performance while maintaining an optimal price-performance ratio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82wfvtkk0ho1vurjcoon.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82wfvtkk0ho1vurjcoon.PNG" alt="raid66" width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RAID 6
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs92gcbp84v40xdgw12wo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs92gcbp84v40xdgw12wo.PNG" alt="Raid6" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RAID 6, also known as “double-parity interleaving,” is a data storage and recovery technique that distributes data across multiple drives while utilizing double-parity for enhanced fault tolerance. While RAID 6 performs similarly to RAID 5 in terms of performance and capacity, it offers an advantage by distributing the second parity scheme across different drives, allowing it to withstand the simultaneous failure of two drives within the array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RAID 6 provides a reasonable price-quality ratio with good overall performance.&lt;/li&gt;
&lt;li&gt;The array can endure the simultaneous failure of two drives or the failure of one drive, followed by the subsequent failure of a second drive during data recovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RAID 6 incurs higher costs compared to RAID 5, as it sacrifices the capacity of two drives for parity data.&lt;/li&gt;
&lt;li&gt;In most scenarios, RAID 6 performs slightly slower than RAID 5.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Areas of application
&lt;/h3&gt;

&lt;p&gt;RAID 6 is highly recommended for applications such as file servers, shared storage servers, and backup servers. It strikes a favorable balance between cost and performance, offering reliable and versatile operation. The key advantage of RAID 6 lies in its ability to tolerate the failure of two drives simultaneously or the failure of one drive followed by a second drive during the data recovery process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklwzpf9io5kvuy61qlv4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklwzpf9io5kvuy61qlv4.PNG" alt="RAID" width="800" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RAID 7.3
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7g9lxbo3wixcezaobpm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7g9lxbo3wixcezaobpm.PNG" alt="Raid73" width="731" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To increase the reliability of the data warehouse, XINNOR engineers have developed and introduced to the market a new triple-parity RAID level, known as RAID 7.3. This level was designed with a unique erasure coding technology, which allows to perform checksum calculations at high speed. Thus, RAID 7.3 achieves performance comparable to RAID 6.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;p&gt;RAID 7.3, with triple parity, is ideal for use with high-capacity drives, where the recovery process can take long time. This is especially true in conditions of intense workload, where a long rebuilding process increases the risk of subsequent drive failure and potentially threatens data security.&lt;/p&gt;

&lt;p&gt;The use of RAID 7.3 in combination with hard drives or hybrid solutions significantly reduces storage costs by reducing the number of drives used, meeting customer requirements for reliability and performance.&lt;/p&gt;

&lt;p&gt;In addition, RAID 7.3 provides extensive capabilities for managing the infrastructure of your data centers. It offers a convenient and reliable technology for organizing a storage array.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj46hegidbum7quo6a5m8.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj46hegidbum7quo6a5m8.PNG" alt="raid 10" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RAID 10
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzru31md95czk1iwj5615.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzru31md95czk1iwj5615.PNG" alt="RAID10" width="686" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RAID 10, also known as “striping and mirroring”, combines the benefits of RAID 1 and RAID 0 by creating multiple mirrored sets that are interleaved. RAID 10 provides high performance, good data protection, and does not require parity calculations.&lt;/p&gt;

&lt;p&gt;RAID 10 requires at least four drives, and the usable capacity is 50% of the total drive capacity. However, it is worth noting that RAID 10 can use more than four drives, which must be a multiple of two. For example, a RAID 10 array of eight drives provides high performance on both spinning and SSD drives because data reads and writes are split into smaller chunks on each drive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;High speed and reliability through a combination of striping and mirroring.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Expensive configuration because it requires the use of more drives to achieve usable capacity.&lt;/li&gt;
&lt;li&gt;Not recommended for large capacities due to cost constraints.&lt;/li&gt;
&lt;li&gt;Slightly slower than RAID 5 in some streaming scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Areas of application
&lt;/h3&gt;

&lt;p&gt;This RAID level is well-suited for databases, as it offers elevated read and write performance, and for virtualization, providing servers with both high performance and reliability. It is particularly relevant in domains such as video editing and multimedia applications, where RAID 10 can efficiently manage substantial data volumes. Additionally, it is recommended for mission-critical applications due to its robust data protection and recovery capabilities in the event of drive failure. Moreover, in the context of high-traffic file servers, RAID 10 adeptly handles heavy network traffic while delivering remarkable file system responsiveness.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlwwtui4vvmxa6l8zygt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlwwtui4vvmxa6l8zygt.PNG" alt="raid10" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  RAID 50 &amp;amp; 60
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jg3qyzbphuxrb9gvga8.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jg3qyzbphuxrb9gvga8.PNG" alt="raid50" width="482" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9y6l6b2e1v5knv31i6uc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9y6l6b2e1v5knv31i6uc.PNG" alt="raid60" width="574" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also RAID 5+0 (RAID 50) and RAID 6+0 (RAID 60), which are hybrid RAID configurations that combine the features of multiple RAID levels for improved performance and fault tolerance. RAID 5+0 uses multiple RAID 5 arrays interleaved with RAID 0, providing faster data access and the ability to tolerate a single drive failure per RAID 5 array. RAID 6+0 combines multiple RAID 6 arrays interleaved with RAID 0, providing even better fault tolerance by tolerating two-drives failures per RAID 6 array. These configurations are suitable for situations requiring both high performance and enhanced data protection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf6unfde0yi68n0tqzk2.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frf6unfde0yi68n0tqzk2.PNG" alt="Raid MN" width="800" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  RAID N+M
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flv3pivr6lrbg3601zq7t.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flv3pivr6lrbg3601zq7t.PNG" alt="mn raid" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RAID level N+M is a data block allocation system using M parity distribution. This level allows the end user to independently determine the number of drives that will be used to store checksums. RAID N+M is supported by xiRAID. This is an innovative technology, thanks to which it is possible to restore information in the event of a failure of up to 32 drives (depends on how many drives are used to store checksums).&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Choose the RAID Level
&lt;/h2&gt;

&lt;p&gt;Choosing the right RAID level depends on your specific storage needs, performance requirements, data redundancy preferences, and budget constraints. Here are the key factors to consider when making this decision:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Requirements&lt;/strong&gt;: Different RAID levels offer varying levels of performance. RAID 0, for example, provides excellent performance by striping data across multiple drives, but it lacks data redundancy. On the other hand, RAID 5 and RAID 6 offer both performance and redundancy but are not as fast as RAID 0. Consider the speed at which you need to access and transfer data, as well as the workload demands of your system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Redundancy and Fault Tolerance&lt;/strong&gt;: If data protection is a top priority, RAID levels with redundancy are essential. RAID 1 mirrors data across drives, providing a high level of fault tolerance, while RAID 5 and RAID 6 use distributed parity to protect against drive failures. RAID 10 combines mirroring and striping, offering both speed and redundancy. Assess the criticality of your data and how much protection you need against potential drive failures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Drive Utilization&lt;/strong&gt;: Different RAID levels use drives in various ways, impacting overall storage capacity. RAID 0 utilizes all drives for data storage, providing maximum capacity but no redundancy. In contrast, RAID 1 uses half the capacity for mirroring, reducing usable storage but ensuring complete redundancy. Evaluate how important drive utilization is for your setup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Number of Drives Available&lt;/strong&gt;: Some RAID levels require a minimum number of drives to function effectively. RAID 5, for instance, needs a minimum of three drives, while RAID 6 typically requires at least four drives. If you have limited drive slots or a specific number of available drives, this will influence your RAID level choice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost Considerations&lt;/strong&gt;: RAID configurations come with varying costs based on the number of drives needed and the drive types used (HDDs or SSDs). RAID 0 and RAID 5 might be more cost-effective due to their lower drive requirements, while RAID 1 and RAID 10 could be more expensive due to the need for mirroring. Balance your budget constraints with the level of performance and redundancy required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity and Manageability&lt;/strong&gt;: Some RAID levels, like RAID 0 and RAID 1, are relatively simple to set up and manage, making them suitable for less experienced users. In contrast, RAID 5 and RAID 6 configurations involve distributed parity, which adds complexity but provides more redundancy. Consider the level of expertise and effort required for configuring and maintaining your chosen RAID level.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specific Use Cases&lt;/strong&gt;: Certain RAID levels excel in particular scenarios. For instance, RAID 0 is ideal for temporary data storage or high-performance applications where redundancy is not a concern. RAID 5 and RAID 6 are well-suited for data-centric environments that require both performance and fault tolerance. Identify your specific use case to align it with the RAID level that best suits your requirements.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By carefully evaluating these factors and understanding the strengths and weaknesses of each RAID level, you can confidently select the right RAID configuration that aligns with your storage needs and ensures the optimal balance between performance, data protection, and cost-effectiveness.&lt;/p&gt;

&lt;p&gt;Several software solutions are available to optimize RAID configurations and achieve peak performance. A notable example is xiRAID, a &lt;a href="https://xinnor.io/what-is-xiraid/" rel="noopener noreferrer"&gt;software RAID&lt;/a&gt; engine, a universal tool compatible with all RAID levels. We can help you choose the best solution for your business needs.&lt;/p&gt;

&lt;p&gt;Thank you for reading! If you have any questions or thoughts about this RAID Levels, please leave them in the comments below. I’d love to hear your feedback and discuss how this setup could benefit your projects!&lt;/p&gt;

&lt;p&gt;Original article can be found &lt;a href="https://xinnor.io/blog/a-guide-to-raid-pt-2-raid-levels-explained/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>raid</category>
      <category>storage</category>
      <category>raidlevels</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Sergey Platonov</dc:creator>
      <pubDate>Mon, 10 Mar 2025 16:39:12 +0000</pubDate>
      <link>https://dev.to/pltnvs/-1n1i</link>
      <guid>https://dev.to/pltnvs/-1n1i</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/pltnvs" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1730592%2Fa940c3cd-3341-4a82-9c79-7d9d29871176.jpg" alt="pltnvs"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/pltnvs/how-to-build-high-performance-nfs-storage-with-xiraid-backend-and-rdma-access-5cio" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to Build High-Performance NFS Storage with xiRAID Backend and RDMA Access&lt;/h2&gt;
      &lt;h3&gt;Sergey Platonov ・ Feb 18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#performance&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#rdma&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#nfs&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#storage&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>performance</category>
      <category>rdma</category>
      <category>nfs</category>
      <category>storage</category>
    </item>
  </channel>
</rss>
