3.9 KiB
04 - Architecture & Phase Breakdown
deploy.yml runs as a single play across all nodes, executing phases sequentially. Phases that only apply to cluster or Linstor deployments are gated by runtime conditions evaluated per-node.
Conditions & Flags
| Condition | Meaning |
|---|---|
_skip_cluster |
True when inventory has only 1 node, or standalone_mode: true. Skips phases 3 and 4 entirely |
deploy_linstor |
Must be true for Linstor roles to run. Independent of node count |
priv_nic_1/2 + priv_ip defined |
Required for Phase 0 (p2p bridge) to run |
Phase 0 — P2P Private Network (Optional)
Role: p2p_network
Condition: not _skip_cluster and priv_nic_1, priv_nic_2, priv_ip all defined
Validates that both NICs exist on the node, then writes a bridge stanza into /etc/network/interfaces and applies it with ifreload -a. The bridge is named p2p and receives the node's priv_ip address. This phase is also available as a standalone playbook (network.yml) for reconfiguring the network independently of a full deployment.
Phase 1 — Repositories & Licensing
Configures APT sources in DEB822 format (.sources files, not legacy .list). Behavior is per-node based on whether pve_enterprise_key is set:
- With key: Enterprise repository is added, no-subscription repository is removed, key is registered via
pvesubscription set. - Without key: No-subscription repository is added, enterprise repository is removed.
Legacy .list files for pve-enterprise, pve-no-subscription, and ceph are always deleted to prevent APT cache duplication. The LINBIT repository is added here if deploy_linstor is true.
Optionally disables IPv6 system-wide via sysctl (disable_ipv6: true) — useful when IPv6 is unrouted and causes TLS connection delays.
Phase 2 — Updates & Nag Removal
Runs apt dist-upgrade asynchronously (up to 1 hour, polled every 30 seconds) to prevent SSH timeout during long upgrades. Applies a regex patch to proxmoxlib.js to suppress the subscription nag dialog. Installs DRBD kernel modules and Linstor packages if deploy_linstor is true.
After upgrades, checks for /var/run/reboot-required and reboots nodes that need it. An explicit sync barrier waits for all nodes to come back online before proceeding — this prevents any_errors_fatal from aborting the run if nodes reboot at different times.
Phase 3 — Proxmox Clustering
Condition: not _skip_cluster
Generates 4096-bit RSA keys on all nodes, distributes public keys to build full-mesh root SSH trust, and disables StrictHostKeyChecking for the management and Corosync subnets.
Cluster formation is guarded by pvecm status — if the cluster already exists, formation tasks are skipped:
- Node 1:
pvecm create <name> --link0 <corosync_ip> - Worker nodes:
pvecm add <master_ip> --link0 <corosync_ip>— throttled to one node at a time to prevent race conditions in the Corosync join sequence.
Phase 4 — Linstor Configuration
Condition: deploy_linstor and not _skip_cluster
Executed via four roles in order:
| Role | Responsibility |
|---|---|
linstor_cluster |
Populates /etc/hosts with cluster node entries (private + public), registers all nodes in Linstor, configures fallback interfaces, waits for satellites to come Online |
linstor_storage |
Configures LVM global filter, optionally wipes disks, creates VGs and thin pools, registers storage pools and resource groups in Linstor |
linstor_ha |
Spawns the linstor_db DRBD resource, migrates the controller database onto it, deploys the drbd-reactor promoter config with floating VIP |
proxmox_storage |
Removes local-lvm if pve/data is managed by Linstor, registers each resource group as a Proxmox storage backend via pvesm add drbd |
Previous: Running the Playbooks | Index | Next: Linstor & Storage Deep Dive