Initial commit

This commit is contained in:
Francesco Zimbolo
2026-04-23 07:49:11 +00:00
commit 57ddf083f7
19 changed files with 802 additions and 0 deletions

21
docs/01-prerequisites.md Normal file
View File

@@ -0,0 +1,21 @@
# 01 - Prerequisites & Node Preparation
This documentation outlines the required state for bare-metal servers before executing the Ansible provisioning pipeline.
## Node State
* **OS:** Proxmox VE 8.x freshly installed.
* **Authentication:** Root password known. SSH key exchange is handled automatically by Ansible.
* **Network:** Static IPs assigned. If deploying Linstor, the management interface and Corosync/DRBD replication should ideally be physically separated. If utilizing a single NIC, QoS/traffic shaping must be handled at the switch level to prioritize Corosync UDP (5404/5405) over DRBD replication traffic.
* **Storage:** Target block devices intended for Linstor raw LVM provisioning must contain no existing partition tables, LVM metadata, or filesystems.
## Execution Environment
Local Ansible installation is not required. This repository enforces the use of an isolated VS Code DevContainer.
1. Open this repository in Visual Studio Code.
2. Ensure Docker/Podman and the "Dev Containers" extension are installed.
3. Select `Reopen in Container`.
4. Open a terminal within VS Code. All paths referenced in this documentation originate from the `ansible/` directory.
```bash
cd ansible/
```

34
docs/02-configuration.md Normal file
View File

@@ -0,0 +1,34 @@
# 02 - Configuring the Cluster
Cluster configurations are segmented per project/customer using Ansible inventories. Do not edit variables in the root directory.
## 1. Create the Environment
Copy the template directory for your specific project:
```bash
cp -r inventories/_template inventories/<customer_name>
mv inventories/<customer_name>/hosts.yml.example inventories/<customer_name>/hosts.yml
mv inventories/<customer_name>/group_vars/all.yml.example inventories/<customer_name>/group_vars/all.yml
```
## 2. Configure `hosts.yml`
Define the target PVE nodes. Ansible defaults to the `ansible_host` IP for Corosync and DRBD replication. If a dedicated backend network is available, define `priv_ip`. Ansible uses conditional fallback logic automatically.
```yaml
all:
children:
proxmox:
hosts:
pve-node-01:
ansible_host: 192.168.1.11
priv_ip: 10.0.0.11
```
## 3. Configure `group_vars/all.yml`
* **Deployment Toggles:** Set `deploy_linstor: true` for HCI setups, or `false` for traditional SAN integration.
* **Enterprise Licensing:** Supply a key in `pve_enterprise_key`. If empty (`""`), the playbook applies the `pve-no-subscription` repository.
* **HA Controller:** Define `ha_pool`, `ha_vip` (Virtual IP), and the CIDR prefix for the Linstor DB promoter.
* **Storage Pools:**
* If mapping a raw disk (`/dev/sda`), the playbook invokes `community.general.lvg` to create the VG/Thin Pool.
* If mapping an existing path (`pve/data`), LVM tasks are skipped, and the target is registered directly in Linstor.

21
docs/03-execution.md Normal file
View File

@@ -0,0 +1,21 @@
# 03 - Execution
Ensure you are operating within the `ansible/` directory inside the DevContainer.
## 1. Test Connectivity
Verify SSH access to the nodes before triggering the pipeline. Because SSH keys are not yet distributed, Ansible must prompt for the root password (`-k`).
```bash
ansible all -i inventories/<customer_name>/hosts.yml -m ping -u root -k
```
## 2. Execute the Playbook
Run the converged deployment playbook. You will be prompted for the SSH password once.
```bash
ansible-playbook -i inventories/<customer_name>/hosts.yml deploy.yml -u root -k
```
## Expected Behavior
* **Idempotency:** The playbook is declarative. If execution fails due to a transient network issue, re-running the exact command will bypass successful tasks and resume from the failure point.
* **Reboots:** If Phase 2 upgrades the running PVE kernel, the playbook forces a synchronized node reboot to ensure DRBD module compatibility against the active kernel headers. Ansible will pause and wait for the nodes to return online.

15
docs/04-architecture.md Normal file
View File

@@ -0,0 +1,15 @@
# 04 - Pipeline Architecture
The `deploy.yml` playbook orchestrates the initialization via sequential phases utilizing `include_role` blocks to guarantee procedural execution order.
## Phase 1: Repositories & Licensing
Evaluates the `pve_enterprise_key` variable. Modifies `/etc/apt/sources.list.d/`, drops the ceph/enterprise configurations as needed, and applies Linstor repository keys.
## Phase 2: System Updates & JS Patches
Forces a `dist-upgrade`. Implements a regex replacement targeting `proxmoxlib.js` to nullify the ExtJS subscription prompt. Installs required DRBD headers and modules. Issues a conditional reboot.
## Phase 3: Proxmox Clustering
Generates 4096-bit RSA keys, constructs a full-mesh authorized_keys trust, and nullifies StrictHostKeyChecking for the defined subnets. Bootstraps Corosync via `pvecm create` on Node 01, followed by asynchronous `pvecm add` operations on worker nodes.
## Phase 4: Linstor/DRBD Configuration (Conditional)
Wrapped in a feature flag (`deploy_linstor`). Executes standard DRBD module loading, configures global LVM filters, sets up High Availability components, and injects backend parameters into `/etc/pve/storage.cfg`.

View File

@@ -0,0 +1,18 @@
# 05 - Linstor & Storage Implementation
This document details the configuration enforcement executed by the Linstor roles.
## LVM Global Filter
To prevent PVE from detecting double LVM signatures (raw block vs DRBD layer), the playbook injects the following global filter into `/etc/lvm/lvm.conf`.
`global_filter =[ "r|^/dev/drbd|", "r|^/dev/mapper/[lL]instor|" ]`
## Storage Provisioning
The `community.general.lvg` task targets raw block devices strictly when the target string starts with `/dev/`. **The playbook does not invoke `wipefs`.** If residual partition tables exist on the target block device, the LVM module will purposefully fail to prevent data destruction.
## HA Controller Topology
Linstor Controller HA is handled via `drbd-reactor`.
1. A 200M DRBD resource (`linstor_db`) is spawned across all nodes.
2. The default `linstor-controller` systemd service is disabled.
3. A `var-lib-linstor.mount` unit is deployed.
4. The local `/var/lib/linstor` mount point is secured with the immutable flag (`chattr +i`). This guarantees that if the DRBD resource fails to mount, the local filesystem rejects writes, preventing database split-brains.
5. `drbd-reactor` manages the floating VIP and promoter plugin logic.

View File

@@ -0,0 +1,39 @@
# 06 - Troubleshooting
Common interventions for pipeline failures or hardware reuse.
## LVM Provisioning Failures (Dirty Disks)
If Ansible halts at the LVM Volume Group creation phase, the target block device likely retains partition data. Ensure you are targeting the correct device and wipe the signatures manually:
```bash
# Execute on the specific Proxmox node
wipefs -a /dev/sdX
```
Rerun the playbook after clearing the disk.
## Corosync Quorum Loss
If execution hangs on `pvecm status` or clustering commands, Corosync has lost quorum. In a 3-node cluster, 2 nodes must be online. To force a single active node to regain quorum and unblock operations (for recovery only):
```bash
pvecm expected 1
```
## Linstor HA VIP Unreachable
If the controller does not initialize, verify the promoter plugin state:
```bash
systemctl status drbd-reactor
journalctl -u drbd-reactor -n 50
```
Verify switch layer allows IP spoofing / MAC address floating for the defined `ha_vip`.
## Complete Cluster Reset
To obliterate Corosync configuration and reset the node to a standalone state:
```bash
systemctl stop pve-cluster
pmxcfs -l
rm /etc/pve/corosync.conf
rm -rf /etc/corosync/*
killall pmxcfs
systemctl start pve-cluster
```
*Note: If DRBD configurations are active, an OS reinstall is significantly faster and safer than manual DRBD block device teardown.*