Repository navigation
NAS-144589 / 28.0.0-BETA.1 / truenas-appliance-runner: an HA mode, two appliances wired as an HA pair - #23
Conversation
| # there for a later step to show. | ||
| echo "APPLIANCE_DIR=$APPLIANCE_DIR" >> "$GITHUB_ENV" | ||
| script=appliance.sh | ||
| [ "$HA" = true ] && script=ha.sh |
There was a problem hiding this comment.
LOW — With ha: true, the ssh and disk inputs are silently ignored. ha.sh never reads APPLIANCE_SSH or APPLIANCE_DISK. A caller passing ssh: true gets an empty outputs.ssh and no TN_SSH, even though ssh is in fact enabled on both nodes, at TN_HA_NODE_A:22 / TN_HA_NODE_B:22. This only affects the new opt-in path, but the header comment above could say so: ssh is always on for a pair and reached at the node addresses, and disk doesn't apply. Another option is for ha.sh to die when it is given APPLIANCE_DISK.
| # | ||
| # APPLIANCE_DIR its state (default $RUNNER_TEMP/truenas-appliance) | ||
| # APPLIANCE_MEMORY_MB 6144 per node APPLIANCE_VCPUS 4 per node | ||
| # APPLIANCE_DATA_DISKS 4 shared disks APPLIANCE_DATA_DISK_GB 10 (sparse) |
There was a problem hiding this comment.
LOW — This header and SHARED="${APPLIANCE_DATA_DISKS:-4}" say a pair has 4 shared disks by default. Through the action, though, APPLIANCE_DATA_DISKS is always set from data-disk-count, whose default is '10'. So every caller of the action gets 10 shared LUNs per node, not 4. That is harmless, since the files are sparse, but the documented default only holds when ha.sh is run directly.
|
Three findings: three LOW. No human review needed. The HA path is opt-in (
|
|
This PR has been merged and conversations have been locked. |
Adds an HA mode to
truenas-appliance-runner. Withha: true, the action boots two TrueNAS appliances inside the runner, set up the way middleware expects an HA pair's hardware to be, and hands them over unconfigured. Licensing, the VIP, a pool and failover are left for the suite to set up, because that setup is what an HA suite tests.The new
ha.shsits next toappliance.shand reuseslib.shandtnctl.py. The single-appliance path is unchanged:hadefaults tofalse.What the pair is built from
{"disks": ["truenas_appliance:nightly", "truenas_appliance:nightly"]}.QEMU, with serials ending_c1and_c2. Middleware then reportsIXKVM, node A or B (utils/hardware/detect.py).enp1s0, the name middleware hard-codes for IXKVM. It has its own bridge.10.231.0.1. dnsmasq gives node A.11and node B.12, and.10is left free for the VIP. Docker's FORWARD DROP would block traffic between the nodes, so iptables rules accept it on both bridges.scsi-block, so SCSI-3 persistent reservations pass through. fenced needs them, andpool.createneeds fenced./etc/machine-id, and fenced builds its reservation keys from it. Node B gets a new machine-id and hostid over SSH and reboots, before anything is licensed.Two things that were not obvious
<db_root>/pr/aptpl_<serial>. If the write fails, LIO still applies the change but returns LOGICAL UNIT COMMUNICATION FAILURE, which looks like a transport bug. Debian's targetcli setsdb_rootto/etc/rtslib-fb-targetand doesn't createpr/in it, so the script creates it.PERSISTENT RESERVE OUTthrough SG_IO only for a process withCAP_SYS_RAWIO. qemu therefore runs under sudo, and its QMP socket and files are handed back to the runner user.Exports
TN_HOSTis node A, the only address a fresh pair answers on. AlsoTN_HA=true,TN_HA_NODE_A,TN_HA_NODE_B,TN_HA_VIP,TN_HA_NETMASKandTN_HA_GATEWAY.truenas-applianceon PATH: gainscall <a|b>,ssh <a|b>andconsole <a|b>.Testing
truenas/webui's
ha-e2ebranch boots a pair with this branch (ha: true, on atruenas-lab-xlargerunner: 12 vCPU, 24 GB). It then sets up HA over the API and runs one real failover: https://github.com/truenas/webui/actions/runs/38956716308shellcheck -x appliance.sh ha.sh lib.shis clean, and the CI step now includesha.sh.