Set up digital ocean block storage with Ansible
Ansible is a great tool for automating environment setup and deploy. This article shows how to programmatically set up digital ocean block storage with Ansible. I started by reading this article on how to use the digital ocean manually and built an Ansible runbook inspired by it. The complete runbook is available as a gist, we will build it piece by piece in this post.
Digital Ocean block storage
Digital ocean lets you create volumes and attach them to droplets. For those of you more familiar with Amazon Web Services, digital oceans volumes are to droplets what EBS volumes are to EC2 instances.
When you create a volume in digital ocean and attach it to a droplet it shows up in the /dev/disk-by-id
folder.
It is not formatted into partitions and does not have a file system.
Goals
The goal of our runbook is to automate the setup of a new volume attached to a droplet so that it can be used by applications. I use this runbook in my chatbot before installing a Redis datastore that uses the volume. The runbook should also be a noop with droplets that are already set up
Finding the name of the volume
Let's start by defining the first step to get the volume name. We look at what's in /dev/disk/by-id
and discard entries that contain part
(they refer to partitions of disks instead of the whole volume).
We store the name of the volume for the future steps:
- name: Get the volume name
shell: ls /dev/disk/by-id/ | grep -v part
register: volume_name_raw
- set_fact:
volume_name: "{{ volume_name_raw.stdout }}"
Now we want to be able to run this recipe multiple times, so let's find a way to know if the disk is already set up.
We can do that by checking /etc/fstab
which describes the disk to mount on boot:
- name: Check if the volume is already setup
command: grep '{{ volume_name }}' /etc/fstab -q
register: volume_present
ignore_errors: True
Formatting the volume
All the following steps setup the volume as ext4
and should not run if the volume is already setup:
- name: Label the volume
command: parted /dev/disk/by-id/{{ volume_name }} mklabel gpt
when: volume_present|failed
- name: Create an ext4 partition
command: parted -a opt /dev/disk/by-id/{{ volume_name }} mkpart primary ext4 0% 100%
when: volume_present|failed
- name: Build the ext4 metadata
command: mkfs.ext4 /dev/disk/by-id/{{ volume_name }}-part1
when: volume_present|failed
- name: Create the mount point
command: mkdir -p /mnt/data
when: volume_present|failed
Mounting the volume and persisting the mount
Finally, the volume is ready, we want to ensure that it is mounted and configured in fstab. This will be a noop for a volume that is already mounted and there:
- name: Mount volume read-write
mount:
path: /mnt/data
src: /dev/disk/by-id/{{ volume_name }}-part1
fstype: ext4
opts: defaults,discard
state: mounted
As I wrote previously, you can then use the volume for various applications. I use them to persist a Redis database for my bot. It is really handy to have an ansible cookbook to automate their set up. The complete runbook with all the steps is available as a gist.
Don't forget to also check out the articles discussing how I build my chatbot using Digital Ocean: Syncing org mode reminders to my bot and Managing my todos, notes, and reminders.