The arm existed to answer one question: how much of the meshed arm's
cost is the connection plugin and how much is the tunnel. Runs 37592061960
(docker), 37753506661 (SSH on the underlay) and 37621556682 (SSH over
WireGuard) answered it on web-app-gitea#0, debian/ext4:
pass 1 5964s / 8511s / 8832s
pass 2 5319s / 7472s / 7705s
Leaving ansible_connection: docker costs +4700s, the tunnel +554s - 89.5%
against 10.5%. The answer is recorded; the scaffolding does not need to ship.
Reverts d792519725, 1b28f87b37, 89b8a8c8d1, 0470491e1a, 529c5ace43,
dd3d10a9a2, c20dd0e5f5, 458d8956e1, 63ade1e03b, d281555945 and 4adfb6e3d2.
95cfc8b7b7 is already superseded by bbfd82f89, which sets the profiling limit
upstream.
keep_address left ansible_host alone, and the lab never sets it: the
docker connection uses inventory_hostname as the container name. Switching to
SSH without writing an address made ssh resolve 'web-app-gitea-swarm-mgr-01'
through DNS, and run 37617424998 died UNREACHABLE on all three nodes in 13
minutes.
switch_to_mesh now takes the addresses to dial. A member missing from the
mapping raises instead of falling back to its mesh address, because that
fallback would have produced the meshed arm under the other arm's name - a
wrong number rather than a failed run.
keep_address switches the connection, the user, the key and the ssh
args exactly as the mesh switch does, and leaves ansible_host where it was.
Against the other two transports that isolates the cost of leaving the local
connection from the cost of the tunnel.
Ansible appends -tt to any task it cannot pipeline when the task escalates,
and ansible.builtin.script is one of those, so the deploy over the mesh ran
those tasks on a pty. A pty ends every line with a carriage return, while
the container connection this transport replaces returned bare newlines. A
role that reads its own stdout therefore started failing for no reason other
than the deploy having moved onto the mesh: the Matomo bootstrap parsed a
perfectly good token as empty, because its regex anchors each line and a
trailing carriage return defeats that anchor.
The host the tool switches now asks for no tty, so the mesh returns the same
bytes the connection it replaced did, and no role has to learn about the
transport underneath it.
Taken from the connection plugin rather than guessed: the tty is added when
the task cannot pipeline and escalates, and the option carrying it is
exposed per host as ansible_ssh_use_tty.
The pass that runs over the mesh reaches every host by SSH where the
pass before it used the container connection, and it pays that difference
once per task. Measured in a container: an exec through a warm multiplexer
costs 7ms, a fresh connection 85ms, and 165ms once sudo asks for the
password every task demands. The pass runs thousands of tasks.
Two settings threw the multiplexer away. A persist window of 20s closes the
master whenever a host waits longer than that for its next task, which in a
linear play is most of them; and the named ControlPath points at a directory
nothing creates, so a master that cannot open its socket reconnects per task
without reporting it.
Neither is retuned for the repository. The tool that moves a host onto the
mesh now writes that host's own ssh_args, derived from the repository's
value so every other option is kept and only the window and the socket
differ. A host the mesh never touches keeps exactly what it had.
Confirmed against the built command: a switched host gets ControlPersist=600s
and a ControlPath under the directory Ansible creates, while a host beside it
keeps the repository's own.
The first pass of a deploy reaches the hosts however it can, because no tunnel
exists yet and that pass is what creates one. Every pass after it connects
over the mesh, which is what makes the mesh load-bearing rather than merely
present: a broken tunnel then fails the deploy at the connection, and no role
can quietly fall back to the underlay it was supposed to stop using.
A separate step rather than a fact set during the play, because a play cannot
change the transport it is already running over. A host holding no address on
the mesh is left alone -- rewriting it would strand a host that was
reachable.