Devops

Managing Volumes in Ansible: Practical Patterns for Storage Automation

April 7, 2026
Published
#Ansible#Automation#DevOps#Infrastructure as Code#Linux#Storage

Volumes are one of those things you don’t think about—until something breaks. A missing mount, a misconfigured filesystem, or a non-persistent volume can take down an otherwise perfectly automated system.

Ansible doesn’t have a single “volume” abstraction like container platforms do. Instead, it gives you building blocks: disk formatting, filesystem creation, mounting, and persistence. Once you understand how these pieces fit together, you can fully automate storage across your infrastructure.

What “Volumes” Mean in Ansible

In Ansible, managing volumes usually involves three steps:

  • Preparing the device (partitioning or identifying the disk)
  • Creating a filesystem
  • Mounting the volume and ensuring persistence

These steps map to specific modules:

  • ansible.builtin.filesystem → create filesystems
  • ansible.builtin.mount → mount and persist volumes
  • ansible.builtin.parted → optional disk partitioning

A Simple Volume Setup Example

Let’s start with a common scenario: attaching a new disk (/dev/xvdf) and mounting it at /data.

Step 1: Create a Filesystem

Before mounting, the disk needs a filesystem:

YAML
1- name: Create ext4 filesystem on disk
2  ansible.builtin.filesystem:
3    fstype: ext4
4    dev: /dev/xvdf
5

This is idempotent—Ansible won’t recreate the filesystem if it already exists.

Step 2: Mount the Volume

YAML
1- name: Mount the volume
2  ansible.builtin.mount:
3    path: /data
4    src: /dev/xvdf
5    fstype: ext4
6    state: mounted
7

This does two things:

  • Mounts the volume immediately
  • Adds it to /etc/fstab for persistence

Here’s Where Things Get Interesting

The mount module is more powerful than it looks. Its state parameter controls behavior:

  • mounted → mount and persist
  • unmounted → unmount but keep fstab entry
  • absent → remove from fstab
  • present → add to fstab but don’t mount

This gives you fine-grained control over system state—especially useful in rolling deployments or migrations.

Making Mounts Persistent (and Safe)

A common mistake developers make is assuming a mounted volume will survive a reboot. Without an /etc/fstab entry, it won’t.

Using Ansible ensures persistence automatically when state: mounted is used. But you can also explicitly define mount options:

YAML
1- name: Mount volume with options
2  ansible.builtin.mount:
3    path: /data
4    src: /dev/xvdf
5    fstype: ext4
6    opts: noatime,nodiratime
7    state: mounted
8

These options can improve performance by reducing disk writes.

Working with Multiple Volumes

In real systems, you rarely manage just one disk. You might have logs, backups, and application data on separate volumes.

Instead of repeating tasks, define volumes as data:

YAML
1volumes:
2  - device: /dev/xvdf
3    mount_point: /data
4  - device: /dev/xvdg
5    mount_point: /logs
6

Then loop through them:

YAML
1- name: Create filesystems
2  ansible.builtin.filesystem:
3    fstype: ext4
4    dev: "{{ item.device }}"
5  loop: "{{ volumes }}"
6
7- name: Mount volumes
8  ansible.builtin.mount:
9    path: "{{ item.mount_point }}"
10    src: "{{ item.device }}"
11    fstype: ext4
12    state: mounted
13  loop: "{{ volumes }}"
14

This pattern keeps your playbooks clean and scalable.

Handling Partitioned Disks

If your disk isn’t pre-partitioned, you can automate that too:

YAML
1- name: Create partition
2  ansible.builtin.parted:
3    device: /dev/xvdf
4    number: 1
5    state: present
6    part_type: primary
7    fs_type: ext4
8

Then reference the partition:

TEXT
1dev: /dev/xvdf1

This is especially useful in cloud environments where raw disks are attached.

Volume Management in Containers (Bonus Context)

If you’re using Ansible with Docker, volumes show up differently. Instead of mounting block devices, you define Docker volumes:

YAML
1- name: Create Docker volume
2  community.docker.docker_volume:
3    name: app_data
4

And attach it to containers:

YAML
1- name: Run container with volume
2  community.docker.docker_container:
3    name: my_app
4    image: my_image
5    volumes:
6      - app_data:/var/lib/app
7

Different abstraction—but same goal: persistent storage.

Gotchas You’ll Eventually Hit

  • Device naming changes: Cloud providers may rename devices after reboot. Consider using UUIDs.
  • Filesystem mismatch: Mounting with the wrong fstype will fail silently in some cases.
  • Permissions: Mounting works, but apps fail due to ownership issues.

Using UUID instead of device paths is more reliable:

YAML
1- name: Mount using UUID
2  ansible.builtin.mount:
3    path: /data
4    src: UUID=1234-5678
5    fstype: ext4
6    state: mounted
7

Performance and Reliability Tips

Volume management isn’t just about making things work—it’s about making them stable and efficient.

  • Use noatime to reduce disk writes
  • Separate high-IO workloads onto dedicated volumes
  • Validate mounts after provisioning in CI/CD pipelines
  • Avoid hardcoding device names in dynamic environments

Putting It All Together

A minimal but production-ready playbook might look like this:

YAML
1- hosts: all
2  become: yes
3  vars:
4    volumes:
5      - device: /dev/xvdf
6        mount_point: /data
7
8  tasks:
9    - name: Ensure filesystem exists
10      ansible.builtin.filesystem:
11        fstype: ext4
12        dev: "{{ item.device }}"
13      loop: "{{ volumes }}"
14
15    - name: Ensure mount point exists
16      ansible.builtin.file:
17        path: "{{ item.mount_point }}"
18        state: directory
19      loop: "{{ volumes }}"
20
21    - name: Mount volumes
22      ansible.builtin.mount:
23        path: "{{ item.mount_point }}"
24        src: "{{ item.device }}"
25        fstype: ext4
26        state: mounted
27      loop: "{{ volumes }}"
28

Clean, repeatable, and fully automated.

Final Thought

Ansible doesn’t try to hide how storage works—it exposes it. That might feel verbose at first, but it gives you precise control over how volumes are created, mounted, and maintained.

Once you internalize these patterns, managing volumes becomes just another predictable part of your infrastructure code.

Comments

Leave a comment on this article with your name, email, and message.

Loading comments...

Similar Articles

More posts from the same category you may want to read next.

Share: