Ansible – Create striped logical volume with 4 disk in LVM, format and mount

In cloud environments virtual hard disk have limits. No only for disk sizes but also for IO performance. Usually IO performance is dependent on disk size which means, if you need more IOPs you have to use a bigger disk. Bigger disks are more expensive than smaller ones. Unfortunately the relationship between IOPs and disk size is not linear. So a double sized virtual hard disk has not necessarily 2-times the IOPs.

In Azure for example there are also managed virtual hard disks and unmanaged virtual hard disk. One important difference is that the price per month for managed virtual hard disks his calculated by the provisioned size. The price per month for unmanaged hard disks is calculated by their actually used capacity.

So, if you need reasonably IO performance for a VM but don’t want to pay a hell of money for large virtual hards, then it would make sense to combine a bunch of smaller hard disk in your VM and configure your VM to distribute reads/writes equally across the smaller disk.

In a Linux based VM you can use for example LVM (Logical Volume Manager) to create a striped logical volume to distribute IO reads/writes evenly across the disks.

The following Ansible playbook creates a striped logical volume with 4 disk.

---
- hosts: linux_datadisk_lvm_stripe4
  become: true
 
  tasks:

    - name: set fact device list
      set_fact:
        lvm_pv_list: "{{ lvm_pv_list + [item] }}"
      with_items: 
        - /dev/sdb
        - /dev/sdc
        - /dev/sdd
        - /dev/sde

    - name: debug output logical volume size
      debug:
        msg: '{{ ((ansible_devices[(lvm_pv_list[0] | basename)].sectors|int) * (ansible_devices[(lvm_pv_list[0] | basename)].sectorsize|int) / 1073741824 * 0.99 * 4)|int }}g'

    - name: Create a volume group on top of group
      lvg:
        vg: vg-data
        pvs: '{{ lvm_pv_list }}'
      when: lvm_pv_list | length == 4

    - name: Create a logical volume
      lvol:
        vg: vg-data
        lv: lv-data
        opts: "-i 4"
        size: '{{ ((ansible_devices[(lvm_pv_list[0] | basename)].sectors|int) * (ansible_devices[(lvm_pv_list[0] | basename)].sectorsize|int) / 1073741824 * 0.99 * 4)|int }}g'
      when: lvm_pv_list | length == 4

    - name: Create a ext4 filesystem on /dev/vg-data/lv-data
      filesystem:
        fstype: ext4
        dev: /dev/vg-data/lv-data
      when: lvm_pv_list | length == 4

    - name: Mount LV Volume (/dev/mapper/vg--data-lv--data)
      mount:
        path: /srv
        src: /dev/mapper/vg--data-lv--data
        fstype: ext4
        opts: discard,noatime
        state: mounted
      when: lvm_pv_list | length == 4