As part of the LVM series, we have seen how to export and import logical volumes between different machines in the previous article. In this article, we will see how to use ansible to automate the Logical Volume Manager (LVM) setup in Linux.
Ansible is a simple and easy-to-use automation tool that offers different modules to work with disk management in Linux. When you have more machines to install and configure the operating system with the same configuration then ansible is of great use. A particular use case I can think of is when you are building a cluster where all the servers have the same storage space and need the same LVM partition scheme.
Creating a logical volume manually involves 4 steps.
- STEP 1: Initialize the drive as the physical volume.
- STEP 2: Create a volume group for the physical volume.
- STEP 3: Create the logical volume from the volume group.
- STEP 4: Format the logical volume and mount the file system.
To learn how to perform the above 4 steps manually, take a look at our introduction to LVM article.
Table of Contents
As the first step, you need to gather disk-related information for the target host. This is a useful task when you want to decide the space allocation dynamically.
Either you can do it manually or use the ansible facts mechanism which collects the disk-related facts. The below playbook will retrieve the disk-related information of the target host.
--- - name: LVM Setup hosts: localhost connection: local gather_facts: true tasks: - name: Collect stats for hardware ansible.builtin.setup: gather_subset: - hardware - name: Print the stat output for devices ansible.builtin.debug: var: hostvars[inventory_hostname].ansible_devices
The above playbook will first collect the hardware details using the setup module. In the second task, the output of ansible_devices
alone will be printed.
You can further apply all sorts of filters as per your requirement to get specific data and compute dynamic values for new partition creations. For example, the below task will print all the devices that start with sd*
and their size.
- name: Print the disk size only for sd disks ansible.builtin.debug: msg: "{{ ansible_devices[item].size }}" loop: "{{ ansible_devices.keys() | map('regex_search', 'sd.*') | select('string') | list }}"
Since I have only one disk it prints the sda disk size.
TASK [Print the disk size only for sd disks] ********************************************** ok: [localhost] => (item=sda) => { "msg": "931.51 GB" }
Ansible Playbook for Creating LVM
I will be using the following playbook for demonstration. You can replicate the same code by changing the disk name and partition size per your requirement. I will walk you through each task in the playbook with its output in the subsequent sections.
--- - name: LVM Testing hosts: localhost become: true gather_facts: False tasks: - name: Partition /dev/sdd disk community.general.parted: device: /dev/sdd number: 1 flags: [ lvm ] state: present part_end: 5GiB - name: Task for PV and VG community.general.lvg: vg: ostechnixlab pvs: /dev/sdd1 - name: Logical volume with 1GB size community.general.lvol: vg: ostechnixlab lv: labpart1 size: 1G - name: Format the volume with ext4 fs community.general.filesystem: fstype: ext4 dev: /dev/ostechnixlab/labpart1 - name: Target directory under /opt/ ansible.builtin.file: path: /opt/lvm_test/ state: directory mode: '0755' - name: mount the lv on /data1 ansible.posix.mount: path: /opt/lvm_test/ src: /dev/ostechnixlab/labpart1 fstype: ext4 state: mounted
Create Volume using Parted Module
As the first step, you must create a volume from the raw disk with lvm as the type. You can either use the entire disk or further partition the disk and just use only that particular partition for LVM.
Ansible uses parted module for creating partitions. This is similar to parted command in Linux which is used to configure device partitions.
Heads Up: parted
in a community module that ships with the community.general
namespace. If you do not have community modules installed, install them using the below command.
$ ansible-galaxy collection install community.general
I have a disk /dev/sdd
with 15GB in size.
$ lsblk /dev/sdd NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdd 8:48 0 15G 0 disk
I will create a partition that is /dev/sdd1
of size 5GB. The following task uses the parted
module to partition /dev/sdd1
of 5GB with lvm as type.
- device: Provide the block device name like
/dev/sda
,/dev/sdb
etc. - number: The number of partitions that will be created. Here it is set as 1.
- flags: It sets the type for your partition. In this case, it is LVM.
- state: Setting the state to "
present
" will create the partition. - part_end: Size for the partition.
- name: Partition /dev/sdd disk community.builtin.parted: device: /dev/sdd number: 1 flags: [lvm] state: present part_end: 5GiB
Following is the output for the above task.
Run the lsblk
command to check the partition.
$ lsblk /dev/sdd NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdd 8:48 0 15G 0 disk └─sdd1 8:49 0 5G 0 part
Create Physical Volume and Volume Group
The next step is to initialize /dev/sdd1
as physical volume and add it to a volume group. Use the lvg module which is also maintained under community.general namespace.
The following task will initialize /dev/sdd1
as physical volume and add it to the volume group named ostechnixlab.
- name: Task for PV and VG lvg: vg: ostechnixlab pvs: /dev/sdd1
Following is the output for the above task.
You can also initialize multiple physical volumes and add them to the volume group.
- name: Task for PV and VG lvg: vg: ostechnixlab pvs: /dev/sdd1, /dev/sdd2, /dev/sdd3
You can also define the extent size. By default, it is set to 4MB.
- name: Task for PV and VG lvg: vg: ostechnixlab pvs: /dev/sdd1, /dev/sdd2, /dev/sdd3 pesize: 8
You can check the volume group status by running the following command.
$ sudo vgs ostechnixlab VG #PV #LV #SN Attr VSize VFree ostechnixlab 1 0 0 wz--n- <5.00g <5.00g
Create Logical Volume
The next step is to create the logical volume using the community-maintained lvol module.
In the below task, I am creating a logical volume called lbapart1
from the volume group ostechnixlab
. The total size of the volume group is 5GB and the logical volume is set to 1GB in size.
- name: Logical volume with 1GB size community.general.lvol: vg: ostechnixlab lv: labpart1 size: 1G
Below is the output for the above task.
Run the lvs
command to check the volume created.
$ sudo lvs LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert labpart1 ostechnixlab -wi-a----- 1.00g
Mount the Logical Volume
In this step, you will mount the logical volume to start consuming it. At first, you must format the volume with any supported file system type and mount the volume.
I will divide the above steps into 3 tasks.
- The first task will format the volume with the
ext4
file system. For this filesystem module should be used which is part of the "community.general
" namespace. - The second task will use the file module to create a directory with the volume that will be mounted. For this, the file module should be used which is part of the "
ansible.builtin
" namespace. - The third task will mount the formatted volume in the file system we created in the second task. For this, the mount module should be used which is part of the "
ansible.posix
" namespace.
- name: Format the volume with ext4 fs community.general.filesystem: fstype: ext4 dev: /dev/ostechnixlab/labpart1 - name: Target directory under /opt/ ansible.builtin.file: path: /opt/lvm_test/ state: directory mode: '0755' - name: mount the lv on /data1 ansible.posix.mount: path: /opt/lvm_test/ src: /dev/ostechnixlab/labpart1 fstype: ext4 state: mounted
Following is the output for the above tasks.
You can use the mount
and/or df
command to verify the file system type and mount status.
$ mount | grep -i labpart1 /dev/mapper/ostechnixlab-labpart1 on /opt/lvm_test type ext4 (rw,relatime)
$ df -h /opt/lvm_test/ Filesystem Size Used Avail Use% Mounted on /dev/mapper/ostechnixlab-labpart1 974M 24K 907M 1% /opt/lvm_test
Conclusion
In this article, we have seen what are the different ansible modules that we can use to create partitions, logical volume and mount the file system. You can create a dedicated role for LVM and reuse it across different environments dynamically just by passing arguments.