I've implemented the setup above and it works fine with one major limitation: The hosts that are mounting R/O have no way of knowing that the shared volume has changed. After performing updates from the host that has write access, I need to manually sync the filesystem and then force the reading clients to flush their inode buffers using a command like echo -n 2 | sudo -n /bin/dd of=/proc/sys/vm/drop_caches
. Note, that if file content might change, you need to write 3 instead of 2, to also flush files.
Another issue I sometimes encounter, is that R/O clients might fail to mount the shared storage with 'permission denied'. To resolve this I need to unmount the volume from the R/W node, mount on any R/O nodes that experience the issue and then mount again on the R/W node.
Below is an Ansible role that accomplishes this:
---
- name: Determine the canonical path of the shared-data directory
set_fact:
shared_dir_real_path: "{{ shared_dir_path | realpath }}"
- debug:
msg: "Manually forcing flushing and re-read of directories on volume at {{ shared_dir_path }} (real path: {{ shared_dir_real_path }})."
verbosity: 1
- name: Determine shared-dir mount point
command: "/usr/bin/env stat -c '%m' {{ shared_dir_real_path }}"
register: shared_dir_mount_point
changed_when: False
- name: Determine the mount point's filesystem type and mount options
set_fact:
"shared_dir_mount_{{ item }}": "{{ ansible_mounts | selectattr('mount', 'equalto', shared_dir_mount_point.stdout) | map(attribute = item) | join(',') }}"
with_items:
- fstype
- options
- name: Verify the shared-dir is mounted GFS2
assert:
that: "'{{ shared_dir_mount_fstype }}' == 'gfs2'"
- name: Determine the access to the shared-data directory
set_fact:
shared_dir_access_flags: "{{ ['ro', 'rw'] | intersect( shared_dir_mount_options.split(',') )}}"
- name: Verify Access mode sanity
assert:
that: shared_dir_access_flags | length == 1
- name: Sync the shared filesystem
command: "sudo -n /bin/sync -f {{ shared_dir_real_path }}"
args:
warn: false # Silence warning about the use of sude instead of 'become', which is here deliberate
when: "'rw' in shared_dir_access_flags"
- name: Force re-load of directory inodes
shell: "echo -n 2 | sudo -n /bin/dd of=/proc/sys/vm/drop_caches"
when: "'ro' in shared_dir_access_flags"