We were looking for a way to have our EC2 EBS volumes snapshotted on a daily basis.
We already use AWS and Ansible, so the solution comes quite straightforward:
Ansible + AWS = Daily Snapshots
Our procedure works with Ansible >= 2.1.
First step is about gathering every information required to build the snapshot from a given name:
1 2 3 4 5 |
- name: INFRASTRUCTURE ADD SNAPSHOT | Fetch id instance {{ name }} ec2_remote_facts: filters: "tag:Name": "{{ name }}" register: ec2_instances |
{{ name }} is the tag instance on which we want to operate.
As a second step we might want to verify if the snapshot already exists. If yes, then you can use “del_snapshot” to delete it (as showed later).
1 2 3 4 5 6 |
- name: INFRASTRUCTURE ADD SNAPSHOT | Get snapshot id ec2_snapshot_facts: filters: "tag:id_instance": "{{ ec2_instances.instances.0.id }}" register: id_snapshot when: del_snapshot == "true" |
Next step is about creating the snapshot:
1 2 3 4 5 6 7 8 9 |
- name: INFRASTRUCTURE ADD SNAPSHOT | Create snapshot on volume {{ add_volume_device_name }} ec2_snapshot: instance_id: "{{ ec2_instances.instances.0.id }}" device_name: "{{ add_volume_device_name }}" snapshot_tags: Name: "{{ name }}" id_instance: "{{ ec2_instances.instances.0.id }}" volume: "{{ add_volume_device_name }}" when: add_snapshot == "true" |
In detail:
- add_volume_device_name: device where making the snapshot on
- snapshot_tags: key value item that can be chosen at will, very important to tag items
Finally, we delete the old snapshot:
1 2 3 4 5 6 |
- name: INFRASTRUCTURE ADD SNAPSHOT | Delete snapshot {{ id_snapshot }} local_action: module: ec2_snapshot snapshot_id: "{{ id_snapshot.snapshots.0.snapshot_id }}" state: absent when: del_snapshot == "true" |
Now we proceed with the creation of the playbook:
1 2 3 4 5 6 7 8 |
- hosts: localhost connection: local vars_files: - vars/infrastructure_standalone_ec2_env.yml tasks: - include: roles/infrastructure/tasks/infrastructure_add_snapshot.yml when: add_snapshot == "true" or del_snapshot == "true" |
In detail:
- add_snapshot: this option creates the snapshot
- del_snapshot: this option deletes the snapshot
We have all the elements to create our snapshot. We proceed with a bash script:
1 2 3 4 |
#!/bin/bash ansible-playbook ansible/infrastructure_add_components_ec2.yml \ $TAGS_OPTION -e"name=standalone_name_server add_snapshot=true del_snapshot=false" |
In detail:
- why “infrastructure_add_components_ec2.yml”? because the playbook is used to add other components too (topics for another article!)
- name: is the tag instance on which we want to operate
- add_snapshot/del_snapshot: changes the flags true and false as you need
Now we schedule the execution of a cron for creating the snapshot.
1 |
04 00 * * * devops/infrastructure_add_components_ec2.sh |
Pay attention to data integrity. As written into the official documentation:
“You can take a snapshot of an attached volume that is in use. However, snapshots only capture data that has been written to your Amazon EBS volume at the time the snapshot command is issued. This might exclude any data that has been cached by any applications or the operating system. If you can pause any file writes to the volume long enough to take a snapshot, your snapshot should be complete. However, if you can’t pause all file writes to the volume, you should unmount the volume from within the instance, issue the snapshot command, and then remount the volume to ensure a consistent and complete snapshot. You can remount and use your volume while the snapshot status is pending.”
It was not the case, but you must check.
We have a simple daily snapshot system.
Enjoy!
Just curios to know whether above playbook performs snapshots of the multiple volumes(instances) at once. I see that you are using ‘ec2_instances.instances.0.id’ value which performes snapshot only for the first instance.
Our example does it for a single volume. you can edit the script as you need and take multi-volume snapshots.