Adjust this based on your drives
vars/drives.yml
mountpoint: "/data"
volume_name: md1
raid_level: '0'
drives:
- '/dev/nvme0n1'
- '/dev/nvme1n1'
- '/dev/nvme2n1'
- '/dev/nvme3n1'
- '/dev/nvme6n1'
- '/dev/nvme7n1'
- '/dev/nvme8n1'
- '/dev/nvme9n1'
- '/dev/nvme10n1'
- '/dev/nvme11n1'
- '/dev/nvme12n1'
- '/dev/nvme13n1'
---
- name: This play sets up VM volumes and
hosts: all
become: true
vars_files:
- vars/drives.yml
tasks:
- name: Create mount point
ansible.builtin.file:
path: '{{mountpoint}}'
state: directory
mode: '0755'
- name: Configure raid
include_role:
name: mrlesmithjr.mdadm
vars:
mdadm_arrays:
- name: '{{volume_name}}'
devices: '{{drives}}'
# filesystem: 'ext4'
filesystem_opts: ''
level: '{{raid_level}}'
mountpoint: '{{mountpoint}}'
state: 'present'
opts: 'noatime'
- name: Create filesystem on RAID array
ansible.builtin.command:
cmd: mkfs.ext4 /dev/{{volume_name}}
- name: Mount {{volume_name}} to /data
ansible.builtin.mount:
path: '{{mountpoint}}'
src: '/dev/{{volume_name}}'
fstype: ext4
state: mounted
opts: defaults
benchmark.yml
---
- name: Install fio and run benchmarks
hosts: all
become: true
tasks:
- name: Update apt cache
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
- name: Install fio
ansible.builtin.apt:
name: fio
state: present
- name: Clear existing fio results files from /tmp
ansible.builtin.file:
path: "/tmp/fio_results_*"
state: absent
- name: Run 4K Random Read/Write Test on /data with different parameters
ansible.builtin.command:
cmd: >
fio --name=rand{{ item.operation }}
--directory=/data
--ioengine=libaio
--iodepth={{ item.iodepth }}
--rw=rand{{ item.operation }}
--bs=4k
--direct=1
--size=4G
--numjobs={{ item.numjobs }}
--runtime=60
--group_reporting
loop:
- { operation: 'read', iodepth: 16, numjobs: 32 }
- { operation: 'read', iodepth: 16, numjobs: 64 }
- { operation: 'read', iodepth: 16, numjobs: 128 }
- { operation: 'read', iodepth: 64, numjobs: 32 }
- { operation: 'read', iodepth: 64, numjobs: 64 }
- { operation: 'read', iodepth: 64, numjobs: 128 }
- { operation: 'read', iodepth: 256, numjobs: 32 }
- { operation: 'read', iodepth: 256, numjobs: 64 }
- { operation: 'read', iodepth: 256, numjobs: 128 }
- { operation: 'write', iodepth: 16, numjobs: 32 }
- { operation: 'write', iodepth: 16, numjobs: 64 }
- { operation: 'write', iodepth: 16, numjobs: 128 }
- { operation: 'write', iodepth: 64, numjobs: 32 }
- { operation: 'write', iodepth: 64, numjobs: 64 }
- { operation: 'write', iodepth: 64, numjobs: 128 }
- { operation: 'write', iodepth: 256, numjobs: 32 }
- { operation: 'write', iodepth: 256, numjobs: 64 }
- { operation: 'write', iodepth: 256, numjobs: 128 }
register: fio_test_result
loop_control:
label: "{{ item.operation }}_iodepth_{{ item.iodepth }}_numjobs_{{ item.numjobs }}"
- name: Save Test Results
ansible.builtin.copy:
content: "{{ item.stdout }}"
dest: "/tmp/fio_results_4k_rand_{{ item.item.operation }}_{{ item.item.iodepth }}_{{ item.item.numjobs }}.txt"
loop: "{{ fio_test_result.results }}"
loop_control:
label: "{{ item.item.operation }}_iodepth_{{ item.item.iodepth }}_numjobs_{{ item.item.numjobs }}"
- name: Create Python script for processing results
ansible.builtin.copy:
dest: "/tmp/process_fio_results.py"
content: |
import re
import csv
import os
output_dir = "/tmp"
pattern = r"iops\s+:\s+min=\d+,\s+max=\d+,\s+avg=(\d+.\d+),"
csv_file_path = '/tmp/fio_results.csv'
# Prepare CSV file
with open(csv_file_path, 'w', newline='') as csvfile:
csvwriter = csv.writer(csvfile)
csvwriter.writerow(['Filename', 'Operation', 'Iodepth', 'Numjobs', 'Avg IOPS'])
for filename in os.listdir(output_dir):
if filename.startswith("fio_results_4k_rand") and filename.endswith(".txt"):
operation, iodepth, numjobs = filename.replace('fio_results_4k_rand_', '').replace('.txt', '').split('_')
filepath = os.path.join(output_dir, filename)
with open(filepath, 'r') as file:
content = file.read()
match = re.search(pattern, content, re.MULTILINE)
if match:
avg_iops = float(match.group(1))
csvwriter.writerow([filename, operation, iodepth, numjobs, avg_iops])
print(f"Results written to {csv_file_path}")
mode: '0755'
- name: Run Python script to process results
ansible.builtin.command:
cmd: python3 /tmp/process_fio_results.py
- name: Fetch results JSON file to localhost
ansible.builtin.fetch:
src: "/tmp/fio_results.csv"
dest: "./fio_results.csv"
flat: yes
cleanup.yml
---
- name: Dismantle and delete RAID array md1
hosts: all
become: true
vars_files:
- vars/drives.yml
tasks:
- name: Unmount the RAID array if it's mounted
ansible.builtin.mount:
path: "{{mountpoint}}"
src: "/dev/{{volume_name}}"
fstype: ext4
state: unmounted
ignore_errors: yes
- name: Stop the RAID array md1
ansible.builtin.command:
cmd: mdadm --stop /dev/{{volume_name}}
ignore_errors: yes
- name: Wipe NVMe drives
ansible.builtin.shell:
cmd: "wipefs -a {{ item }}"
ignore_errors: yes
loop: "{{drives}}"
- name: Zero superblock on RAID devices
ansible.builtin.shell:
cmd: mdadm --zero-superblock {{ item }}
ignore_errors: yes
loop: "{{drives}}"
- name: Remove or comment RAID array from fstab
ansible.builtin.lineinfile:
path: /etc/fstab
regexp: '^/dev/{{volume_name}}'
state: absent