Files
proxmox-post-install/docs/04-architecture.md
Francesco Zimbolo 8477f5b592 Docs rewrite
2026-04-24 12:58:14 +00:00

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