Compare commits
No commits in common. "450d8fcb7abf75868957071114c85f0b4ba6025d" and "4069d8a77a73fdd67e32d7b82857cd6262355e46" have entirely different histories.
450d8fcb7a
...
4069d8a77a
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
all:
|
all:
|
||||||
vars:
|
vars:
|
||||||
skylab_state_dir: /var/lib/skylab
|
skylab_state_dir: /var/run/skylab
|
||||||
skylab_ansible_venv: "{{ skylab_state_dir }}/ansible-runtime"
|
skylab_ansible_venv: "{{ skylab_state_dir }}/ansible-runtime"
|
||||||
skylab_pip_version: 19.3.1
|
skylab_pip_version: 19.3.1
|
||||||
ansible_user: ansible
|
ansible_user: ansible
|
||||||
@ -34,13 +34,6 @@ en1:
|
|||||||
- server
|
- server
|
||||||
- docker-swarm
|
- docker-swarm
|
||||||
- datastore
|
- datastore
|
||||||
skylab_direct_peers:
|
|
||||||
- hostname: pegasus.local jupiter.svr.local
|
|
||||||
address: 192.168.42.10
|
|
||||||
- hostname: saturn.local remus.svr.local
|
|
||||||
address: 192.168.42.20
|
|
||||||
- hostname: orion.local
|
|
||||||
address: 192.168.42.30
|
|
||||||
|
|
||||||
hosts:
|
hosts:
|
||||||
pegasus: # jupiter
|
pegasus: # jupiter
|
||||||
@ -57,7 +50,6 @@ en1:
|
|||||||
bond: bond0
|
bond: bond0
|
||||||
bond0:
|
bond0:
|
||||||
type: bond
|
type: bond
|
||||||
firewall: internal
|
|
||||||
gateway: 10.42.101.1/24
|
gateway: 10.42.101.1/24
|
||||||
dns:
|
dns:
|
||||||
- 10.42.101.1
|
- 10.42.101.1
|
||||||
@ -67,7 +59,6 @@ en1:
|
|||||||
dhcp: false
|
dhcp: false
|
||||||
bond0.99:
|
bond0.99:
|
||||||
type: vlan
|
type: vlan
|
||||||
firewall: trusted
|
|
||||||
addresses:
|
addresses:
|
||||||
- 192.168.42.10/24
|
- 192.168.42.10/24
|
||||||
dhcp: false
|
dhcp: false
|
||||||
@ -86,7 +77,6 @@ en1:
|
|||||||
bond: bond0
|
bond: bond0
|
||||||
bond0:
|
bond0:
|
||||||
type: bond
|
type: bond
|
||||||
firewall: internal
|
|
||||||
dhcp: false
|
dhcp: false
|
||||||
gateway: 10.42.101.1/24
|
gateway: 10.42.101.1/24
|
||||||
addresses:
|
addresses:
|
||||||
@ -96,7 +86,6 @@ en1:
|
|||||||
- 10.42.101.1
|
- 10.42.101.1
|
||||||
bond0.99:
|
bond0.99:
|
||||||
type: vlan
|
type: vlan
|
||||||
firewall: trusted
|
|
||||||
dhcp: false
|
dhcp: false
|
||||||
addresses:
|
addresses:
|
||||||
- 192.168.42.20/24
|
- 192.168.42.20/24
|
||||||
@ -108,7 +97,6 @@ en1:
|
|||||||
skylab_cluster:
|
skylab_cluster:
|
||||||
address: 10.42.101.12/24
|
address: 10.42.101.12/24
|
||||||
interface: bond0
|
interface: bond0
|
||||||
skylab_datastore_device: sdb
|
|
||||||
skylab_networking:
|
skylab_networking:
|
||||||
eno1:
|
eno1:
|
||||||
bond: bond0
|
bond: bond0
|
||||||
@ -116,7 +104,6 @@ en1:
|
|||||||
bond: bond0
|
bond: bond0
|
||||||
bond0:
|
bond0:
|
||||||
type: bond
|
type: bond
|
||||||
firewall: internal
|
|
||||||
gateway: 10.42.101.1/24
|
gateway: 10.42.101.1/24
|
||||||
dns:
|
dns:
|
||||||
- 10.42.101.1
|
- 10.42.101.1
|
||||||
@ -126,7 +113,6 @@ en1:
|
|||||||
dhcp: false
|
dhcp: false
|
||||||
bond0.99:
|
bond0.99:
|
||||||
type: vlan
|
type: vlan
|
||||||
firewall: trusted
|
|
||||||
addresses:
|
addresses:
|
||||||
- 192.168.42.30/24
|
- 192.168.42.30/24
|
||||||
dhcp: false
|
dhcp: false
|
||||||
|
@ -21,5 +21,3 @@
|
|||||||
roles:
|
roles:
|
||||||
- role: server
|
- role: server
|
||||||
when: "'server' in skylab_roles | default([])"
|
when: "'server' in skylab_roles | default([])"
|
||||||
- role: datastore
|
|
||||||
when: "'datastore' in skylab_roles | default([])"
|
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
---
|
|
||||||
argument_specs:
|
|
||||||
main:
|
|
||||||
description: >-
|
|
||||||
This role makes several assumptions about the local storage configuration of the server:
|
|
||||||
|
|
||||||
1. There is one block device on the server that will be used for data storage
|
|
||||||
2. That block device will be joined to a glusterfs volume
|
|
||||||
3. The block device is encrypted with LUKS
|
|
||||||
|
|
||||||
This role mostly serves to perform housekeeping tasks and validation of expected configs.
|
|
||||||
Automating disk configuration seems like a really good way to lose all my data, so I decided
|
|
||||||
to leave that to the much more reliable manual configuration for the time being.
|
|
||||||
|
|
||||||
To that end, here is a quick cheatsheet of commands that might be useful in setting up
|
|
||||||
storage device(s) for this role (replace `DEVICE` with the block device for storage):
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Encrypt a block device, provide encryption key when prompted
|
|
||||||
cryptsetup luksFormat --type luks2 /dev/DEVICE
|
|
||||||
|
|
||||||
# Unlock encrypted block device and mount under a mapper
|
|
||||||
cryptsetup luksOpen /dev/DEVICE LABEL
|
|
||||||
|
|
||||||
# Lock an encrypted block device
|
|
||||||
cryptsetup luksClose LABEL
|
|
||||||
|
|
||||||
# Create and format a partition on the encrypted block device
|
|
||||||
mkfs.xfs /dev/mapper/LABEL -L LABEL
|
|
||||||
|
|
||||||
# Run from an existing server already in the gluster pool
|
|
||||||
# Add server to the gluster pool
|
|
||||||
gluster peer probe HOSTNAME
|
|
||||||
|
|
||||||
# To replace a brick from an already offline'd node, the old brick first needs to be force
|
|
||||||
# removed, replication reduced, and (if arbiter is enabled) any arbiter nodes removed
|
|
||||||
#
|
|
||||||
# Remove arbiter brick
|
|
||||||
gluster volume remove-brick VOLUME replica 2 HOSTNAME:/EXPORT force
|
|
||||||
# Remove dead data brick
|
|
||||||
gluster volume remove-brick VOLUME replica 1 HOSTNAME:/EXPORT force
|
|
||||||
# Remove dead node
|
|
||||||
gluster peer detach HOSTNAME
|
|
||||||
# Add new data brick
|
|
||||||
gluster volume add-brick VOLUME replica 2 HOSTNAME:/EXPORT start
|
|
||||||
#
|
|
||||||
# To re-add the arbiter you might need to clean up the `.glusterfs` directory and remove
|
|
||||||
# directory parametes from the old brick. These next commands need to be run on the host
|
|
||||||
# with the arbiter brick physically attached
|
|
||||||
#
|
|
||||||
rm -rf /EXPORT/.glusterfs
|
|
||||||
setfattr -x trusted.gfid /EXPORT
|
|
||||||
setfattr -x trusted.glusterfs.volume-id /EXPORT
|
|
||||||
# Re-add arbiter brick
|
|
||||||
gluster volume add-brick VOLUME replica 3 arbiter 1 HOSTNAME:/EXPORT
|
|
||||||
# Trigger a resync
|
|
||||||
gluster volume heal datastore
|
|
||||||
|
|
||||||
# General gluster debug info
|
|
||||||
gluster volume info VOLUME
|
|
||||||
gluster volume status VOLUME
|
|
||||||
```
|
|
||||||
options:
|
|
||||||
skylab_datastore_device:
|
|
||||||
description: The block device under `/dev/` that should be configured as datastore storage
|
|
||||||
type: str
|
|
||||||
required: true
|
|
@ -1,45 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Allow gluster through firewall
|
|
||||||
become: true
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
service: glusterfs
|
|
||||||
state: enabled
|
|
||||||
zone: trusted
|
|
||||||
immediate: true
|
|
||||||
permanent: true
|
|
||||||
|
|
||||||
- name: Create datastore directory
|
|
||||||
become: true
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: /mnt/brick/datastore
|
|
||||||
state: directory
|
|
||||||
|
|
||||||
- name: Fetch peer status
|
|
||||||
become: true
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: gluster peer status
|
|
||||||
changed_when: false
|
|
||||||
register: _gluster_peer_status_raw
|
|
||||||
|
|
||||||
- name: Check peer status
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that:
|
|
||||||
- not _gluster_peer_status_raw.stdout_lines[0].strip().endswith('0')
|
|
||||||
fail_msg: >-
|
|
||||||
ERROR: Datastore host '{{ inventory_hostname }}' is not joined to the gluster pool. Run the
|
|
||||||
command 'gluster peer probe {{ inventory_hostname }}.local' from another datastore host to
|
|
||||||
add it.
|
|
||||||
success_msg: >-
|
|
||||||
Datastore host {{ inventory_hostname }} is joined to the gluster pool
|
|
||||||
|
|
||||||
- name: Mount gluster volume
|
|
||||||
become: true
|
|
||||||
ansible.posix.mount:
|
|
||||||
path: /mnt/datastore
|
|
||||||
src: localhost:/datastore
|
|
||||||
state: mounted
|
|
||||||
fstype: glusterfs
|
|
||||||
# Note that this just needs to be any path *other* than the actual
|
|
||||||
# fstab. This is done just to prevent the devices from being
|
|
||||||
# automatically mounted at boot
|
|
||||||
fstab: "{{ skylab_state_dir }}/mounts"
|
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Install datastore packages
|
|
||||||
ansible.builtin.import_tasks: packages.yaml
|
|
||||||
|
|
||||||
- name: Configure mounting
|
|
||||||
ansible.builtin.import_tasks: mounts.yaml
|
|
||||||
|
|
||||||
- name: Configure glusterfs
|
|
||||||
ansible.builtin.import_tasks: gluster.yaml
|
|
@ -1,108 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Create mount points
|
|
||||||
become: true
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: directory
|
|
||||||
mode: 0755
|
|
||||||
owner: root
|
|
||||||
group: "{{ ansible_user }}"
|
|
||||||
loop:
|
|
||||||
- /mnt/datastore
|
|
||||||
- /mnt/brick
|
|
||||||
|
|
||||||
- name: Determine current mounts
|
|
||||||
vars:
|
|
||||||
_current_mounts: []
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_current_mounts: "{{ _current_mounts + [item.mount] }}"
|
|
||||||
loop: "{{ ansible_mounts }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.mount }}"
|
|
||||||
|
|
||||||
- name: Ensure mount points are empty when unmounted
|
|
||||||
when: item not in _current_mounts
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: "/usr/bin/ls {{ item }}"
|
|
||||||
changed_when: false
|
|
||||||
failed_when: _mountpoint_ls_raw.stdout
|
|
||||||
register: _mountpoint_ls_raw
|
|
||||||
loop:
|
|
||||||
- /mnt/datastore
|
|
||||||
- /mnt/brick
|
|
||||||
|
|
||||||
- name: Fetch block device information
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: lsblk /dev/{{ skylab_datastore_device }} --fs --json
|
|
||||||
changed_when: false
|
|
||||||
register: _lsblk_info_raw
|
|
||||||
|
|
||||||
- name: Process block device information
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_datastore_device_info: "{{ (_lsblk_info_raw.stdout | from_json).blockdevices[0] }}"
|
|
||||||
|
|
||||||
- name: Check state of the datastore device
|
|
||||||
ansible.builtin.assert:
|
|
||||||
that: _datastore_device_info.fstype == "crypto_LUKS"
|
|
||||||
fail_msg: >-
|
|
||||||
ERROR: Datastore block device {{ inventory_hostname }}:/dev/{{ skylab_datastore_device }}
|
|
||||||
must be LUKS encrypted
|
|
||||||
success_msg: >-
|
|
||||||
Datastore block device {{ inventory_hostname }}:/dev/{{ skylab_datastore_device }} is
|
|
||||||
LUKS encrypted
|
|
||||||
|
|
||||||
- name: Determine whether datastore block is decrypted
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_datastore_device_is_decrypted: "{{ _datastore_device_info.children is defined }}"
|
|
||||||
|
|
||||||
- name: Decrypt datastore block
|
|
||||||
when: not _datastore_device_is_decrypted
|
|
||||||
block:
|
|
||||||
- name: Prompt for decryption key
|
|
||||||
no_log: true
|
|
||||||
ansible.builtin.pause:
|
|
||||||
prompt: >-
|
|
||||||
Datastore device {{ inventory_hostname }}:/dev/{{ skylab_datastore_device }} is not
|
|
||||||
decrypted. Enter decryption passphrase to continue GlusterFS brick configuration
|
|
||||||
echo: false
|
|
||||||
register: _luks_decryption_key
|
|
||||||
|
|
||||||
- name: Open LUKS device
|
|
||||||
become: true
|
|
||||||
community.crypto.luks_device:
|
|
||||||
device: /dev/{{ skylab_datastore_device }}
|
|
||||||
state: opened
|
|
||||||
name: brick
|
|
||||||
passphrase: "{{ _luks_decryption_key.user_input }}"
|
|
||||||
|
|
||||||
- name: Fetch updated block device information
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: lsblk /dev/{{ skylab_datastore_device }} --fs --json
|
|
||||||
changed_when: false
|
|
||||||
register: _lsblk_info_raw
|
|
||||||
|
|
||||||
- name: Process updated block device information
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_datastore_device_info: "{{ (_lsblk_info_raw.stdout | from_json).blockdevices[0] }}"
|
|
||||||
|
|
||||||
- name: Create dummy fstab
|
|
||||||
ansible.builtin.file:
|
|
||||||
state: touch
|
|
||||||
path: "{{ skylab_state_dir }}/mounts"
|
|
||||||
owner: "{{ ansible_user }}"
|
|
||||||
group: "{{ ansible_user }}"
|
|
||||||
mode: 0644
|
|
||||||
access_time: preserve
|
|
||||||
modification_time: preserve
|
|
||||||
|
|
||||||
- name: Mount datastore block
|
|
||||||
become: true
|
|
||||||
ansible.posix.mount:
|
|
||||||
path: /mnt/brick
|
|
||||||
src: UUID={{ _datastore_device_info.children[0].uuid }}
|
|
||||||
state: mounted
|
|
||||||
fstype: "{{ _datastore_device_info.children[0].fstype }}"
|
|
||||||
# Note that this just needs to be any path *other* than the actual
|
|
||||||
# fstab. This is done just to prevent the devices from being
|
|
||||||
# automatically mounted at boot
|
|
||||||
fstab: "{{ skylab_state_dir }}/mounts"
|
|
@ -1,31 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Install gluster repository
|
|
||||||
become: true
|
|
||||||
ansible.builtin.dnf:
|
|
||||||
name: centos-release-gluster9
|
|
||||||
state: present
|
|
||||||
register: _datastore_repo_gluster
|
|
||||||
|
|
||||||
- name: Enable required repositories
|
|
||||||
become: true
|
|
||||||
ansible.builtin.lineinfile:
|
|
||||||
path: /etc/yum.repos.d/{{ item }}.repo
|
|
||||||
line: enabled=1
|
|
||||||
state: present
|
|
||||||
regexp: "#?enabled=(0|1)"
|
|
||||||
loop:
|
|
||||||
- Rocky-AppStream
|
|
||||||
- Rocky-PowerTools
|
|
||||||
register: _datastore_repo_powertools
|
|
||||||
|
|
||||||
- name: Install datastore packages
|
|
||||||
become: true
|
|
||||||
when: ansible_distribution == "Rocky"
|
|
||||||
ansible.builtin.dnf:
|
|
||||||
state: present
|
|
||||||
update_cache: "{{ _datastore_repo_powertools.changed or _datastore_repo_gluster.changed }}"
|
|
||||||
name:
|
|
||||||
- cryptsetup-luks
|
|
||||||
- glusterfs
|
|
||||||
- glusterfs-fuse
|
|
||||||
- glusterfs-server
|
|
@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Enable systemd-firewalld
|
|
||||||
become: true
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: firewalld
|
|
||||||
state: started
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
- name: Configure firewall interface zones
|
|
||||||
become: true
|
|
||||||
when: item.value.firewall is defined
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
interface: "{{ item.key }}"
|
|
||||||
zone: "{{ item.value.firewall }}"
|
|
||||||
state: enabled
|
|
||||||
permanent: true
|
|
||||||
immediate: true
|
|
||||||
loop: "{{ skylab_networking | dict2items }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.key }}"
|
|
||||||
|
|
||||||
- name: Configure firewall for docker interface
|
|
||||||
become: true
|
|
||||||
when: "'docker0' in ansible_interfaces"
|
|
||||||
ansible.posix.firewalld:
|
|
||||||
interface: docker0
|
|
||||||
zone: dmz
|
|
||||||
permanent: true
|
|
||||||
immediate: true
|
|
@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Retrieve current hostsfile contents
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: cat /etc/hosts
|
|
||||||
changed_when: false
|
|
||||||
register: _existing_hostsfile_raw
|
|
||||||
|
|
||||||
- name: Assemble hostsfile lines
|
|
||||||
vars:
|
|
||||||
_hostsfile_lines: []
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
_hostsfile_lines: "{{ _hostsfile_lines + [item.address + ' ' + item.hostname] }}"
|
|
||||||
loop: "{{ skylab_direct_peers }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.hostname }}"
|
|
||||||
|
|
||||||
- name: Configure directly connected peers
|
|
||||||
become: true
|
|
||||||
ansible.builtin.lineinfile:
|
|
||||||
path: /etc/hosts
|
|
||||||
line: "{{ item }}"
|
|
||||||
state: present
|
|
||||||
loop: "{{ _hostsfile_lines }}"
|
|
||||||
loop_control:
|
|
||||||
label: "{{ item.partition(' ')[0] }}"
|
|
||||||
|
|
||||||
- name: Remove unmanaged peer aliases
|
|
||||||
become: true
|
|
||||||
when: "'localhost' not in item and item not in _hostsfile_lines"
|
|
||||||
ansible.builtin.lineinfile:
|
|
||||||
path: /etc/hosts
|
|
||||||
line: "{{ item }}"
|
|
||||||
state: absent
|
|
||||||
loop: "{{ _existing_hostsfile_raw.stdout_lines }}"
|
|
@ -8,11 +8,3 @@
|
|||||||
- name: Configure network settings
|
- name: Configure network settings
|
||||||
when: skylab_networking is defined
|
when: skylab_networking is defined
|
||||||
ansible.builtin.include_tasks: networkd.yaml
|
ansible.builtin.include_tasks: networkd.yaml
|
||||||
|
|
||||||
- name: Configure firewall settings
|
|
||||||
when: skylab_networking is defined
|
|
||||||
ansible.builtin.include_tasks: firewalld.yaml
|
|
||||||
|
|
||||||
- name: Configure hostsfile
|
|
||||||
when: skylab_direct_peers is defined
|
|
||||||
ansible.builtin.include_tasks: hosts.yaml
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
/####### /## /## /## /## /## /####### /#####
|
/######## /## /## /## /## /## /####### /#####
|
||||||
/## /##___/## /##__/## /## /##___/## /##__/##
|
/## /##___/## /##__/## /## /##___/## /##__/##
|
||||||
/##____ /####### /###### /## /######## /######
|
/##____ /####### /###### /## /######## /######
|
||||||
######## /## |## /## /## /## /## /##__/##
|
\####### /## |## |## /## /## /## /##__/##
|
||||||
/## /## |## \### /## /## /## /######
|
/## /## |## \### /## /## /## /######
|
||||||
____/## /##_____
|
___/## /##_____
|
||||||
/###### ```````````````````` /######## ``````````````
|
/##### ``````````````````` /######## ``````````````
|
||||||
|
|
||||||
✨ {{ skylab_description }} @{{ skylab_location }}
|
✨ {{ skylab_description }} @{{ skylab_location }}
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
|
@ -9,12 +9,6 @@
|
|||||||
- python3-policycoreutils
|
- python3-policycoreutils
|
||||||
- python3-firewall
|
- python3-firewall
|
||||||
|
|
||||||
- name: Remove legacy state directory
|
|
||||||
become: true
|
|
||||||
ansible.builtin.file:
|
|
||||||
path: /var/run/skylab
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Create state directory
|
- name: Create state directory
|
||||||
become: true
|
become: true
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
Reference in New Issue
Block a user