Skip to content

server ls keeps a healed Machine 'suspect' for 10+ minutes after a partition alone #2506

Open

Description

@nick-potts

After a network partition alone (no power cut) heals, the other Machines keep showing the healed Machine as suspect in server ls for more than 10 minutes. Meanwhile the routing layer treats it as healthy. This is a status misreport. Related to #1423, which saw this after a power cut. There, a partition with no power cut converged in 39 s.

Where

Timeline (UTC)

  • 06:24:07: verify-cluster partition on machine-3, during a Deploy.
  • About 06:24:44: the partition was healed. Corrosion logs Rejoined the cluster, then Current node is considered ACTIVE at 06:24:49.
  • 06:29:23 and 06:35:01: server ls still shows machine-3 as suspect from machine-1 and machine-2.

server ls membership (06:29:23)

machine-1 view: [{"n":"machine-1","membership":"up"},{"n":"machine-2","membership":"up"},{"n":"machine-3","membership":"suspect"}]
machine-2 view: [{"n":"machine-1","membership":"up"},{"n":"machine-2","membership":"up"},{"n":"machine-3","membership":"suspect"}]
machine-3 view: [{"n":"machine-1","membership":"up"},{"n":"machine-2","membership":"up"},{"n":"machine-3","membership":"up"}]

At 06:35:01 it was the same: ["up","up","suspect"].

ReadRoutes at the same time

The Machine Down set was [], so routing treated machine-3 as healthy. The next Deploy brought machine-3's new copy In and routed it, and all three Machines served.

Expected

Once the heal is done and Corrosion has rejoined and synced, server ls stops showing suspect in about the time #1423's partition-only case took (around 40 s). If membership really stays Suspect in Corrosion, server ls should say why instead of showing a stale state.

Evidence, kept locally: server ls dumps, the Corrosion log of machine-1 and machine-3, and post-heal journals (/tmp/swarm-R3/owner/lanes2-a/head/suspect-after-heal.txt, corrosion-machine-*.txt, journal-machine-*-postheal.txt).

Activity

  1. added this to the after 0.3.0 milestone on Oct 21, 2026
  2. nick-potts commented on Oct 22, 2026

    @nick-potts
    ContributorAuthor

    Same symptom at v0.3.0-beta.7 with no partition at all: a Corrosion crash-restart on one Server is enough (soak corrosion-5, Boat run 11cefe48e2, 3 Servers, standalone).

    ssh machine-1 'kill -9 $(docker inspect -f "{{.State.Pid}}" ployz-corrosion)'   # 00:40:49, Docker restarts it in ~1 s
    ployz server ls --connect <machine-1>   # machine-2=suspect from 00:41:09 through 00:43:53 and counting
    ployz server ls --connect <machine-2>   # all up
    

    machine-2's overlay address answers ping from machine-1, the WireGuard handshake is recent, and Corrosion rows keep converging (identical table hashes on all three Servers), so only the SWIM view is stale. docker exec ployz-corrosion corrosion cluster membership-states on machine-1 shows the peer "state": "Suspect", "incarnation": 0, and the corrosion log never records a suspect or refute event.

    An earlier occurrence on the same run (machine-1's Corrosion crash at 00:14, then machine-2 powered off at 00:27) spread: both machine-1 and machine-2 reported healthy machine-3 as suspect for 8+ minutes, while machine-3 saw everyone up. It cleared only when machine-3 itself went down and back during a later partition.

    suspect isn't defined anywhere in docs/user/ (server ls MEMBERSHIP column). Evidence: soak evidence corrosion/c9-*, corrosion/c9b-suspect-repro.txt, corrosion/membership-watch.log.

  3. nick-potts commented on Oct 26, 2026

    @nick-potts
    ContributorAuthor

    Another trigger for the same slow heal, from soak-036 (main 6c849d95a3 + 0.3.6 bump, Boat, local Cloud with SERVERS=2 DAEMON=checkout):

    • verify-cluster update <run> --daemon machine-2=0.3.5 at 04:02 UTC (machine-2: 0.3.6 → 0.3.5, both daemons restart). update exits 1 with machine-1: expected 2 reachable Machines.
    • From 04:02 to about 04:13, ployz server ls shows machine-2 suspect. machine-1's journal logs asked peers Corrosion no longer hears whether this Machine was forgotten listed=[machine-2] every minute.
    • WireGuard handshakes on both sides were seconds old throughout, and a deploy that recreated a container on machine-2 at 04:07 worked.
    • By 04:14 machine-2 was up and the log line had stopped.

    So this is not a version-mix break (deploys worked the whole time), just the same ~10 minute suspect after a daemon restart. Not checked on v0.3.5 ↔ v0.3.5.

  4. nick-potts commented on Oct 28, 2026

    @nick-potts
    ContributorAuthor

    soak-038 (main b1e048a + local 0.3.8 bump, Boat, local Cloud, mixed 0.3.7/0.3.8): a related case, but here the Server stuck at 'suspect' isn't the one that was faulted.

    • A large-packet drop (--sport 51820 -m length --length 1001:65535 -j DROP) ran on machine-3 (0.3.8) from 03:58 to 04:12. Corrosion marked machine-3 Down at 04:11:46 and Up again at 04:12:40-50.
    • After that, machine-1 (0.3.7) and machine-3 kept reading machine-2 (0.3.7, never faulted) as suspect for 18+ minutes: server ls through Cloud and via --connect to each of them, at 04:18, 04:19 and 04:30. Through machine-2 itself all three were up.
    • Every minute both logged asked peers Corrosion no longer hears whether this Machine was forgotten listed=[MachineName("machine-2")].
    • Meanwhile WireGuard handshakes were fresh, Corrosion admin Cluster Members listed every peer with RTTs, and deploys across all 3 Servers still succeeded.
    • I stopped watching at 04:37, because the run went down for unrelated lab reasons. I didn't try it on 0.3.7, but the Corrosion image is the one 0.3.7 ships, so I don't think this sha caused it.

    Blocks the 0.3.8 cut: no. It didn't block a deploy, and it's not a regression as far as I can tell.

  5. nick-potts commented on Oct 31, 2026

    @nick-potts
    ContributorAuthor

    soak-0313 (freeze bc82b8f, Boat --cloud, 3 Servers on this sha's ployzd, same Corrosion image as v0.3.12): the same stuck suspect, after a Corrosion SIGKILL this time, and again it names a Server that wasn't faulted.

    • machine-1, machine-2 and machine-3 were all up in every view. At 19:09:31 docker kill -s KILL ployz-corrosion ran on machine-2. ployzd's keeper had it running again 0.7 s later. machine-1's Corrosion was not touched; it had last been killed at 19:05:18 and had recovered fully by 19:06:04.
    • From +10 s, machine-2 and machine-3 read machine-1 as suspect, and it stays that way: server ls through each Entry at +100 s, then at 19:15:30, 19:15:48 and 19:16:24. Through machine-1 itself all three are up.
    • Corrosion's own admin MembershipStates at 19:16:24 matches: machine-2 and machine-3 hold machine-1's actor Suspect at incarnation 0, and machine-1 holds both peers Alive. Ping over the overlay from machine-2 to machine-1 shows 0% loss. Nothing gets refuted, and nothing times out to Down. It cleared on its own between 19:16:24 and 19:18:04, so 7 to 8.5 min after the kill.
    • Routing and deploys are unaffected: a deploy of web (3 replicas) went through at rc 0 in 13 s, every replica took the change, and HTTPS from every Server stayed at 200 throughout.
    • For comparison, a graceful docker stop ployz-corrosion on machine-2 at 19:07:31 left one Entry's read empty during the 5.5 s stop, and every view was up by +8 s. Each case has one sample.

    Why it matters for 0.3.13: #3697 makes every Corrosion replacement end in SIGKILL, 1 s after SIGTERM, so a replacement now looks like the kill above, not the graceful stop. I didn't run it on v0.3.12 daemons. The kill happens at the Docker level, and v0.3.12 pins the same Corrosion image and config, so this should reproduce there too; this issue already shows it on 0.3.7 and 0.3.8. Blocks the 0.3.13 cut: no. It's a status misreport, with routing and deploys unaffected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    severity:mediumFeature degraded or workaround exists

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions